PageRenderTime 69ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/base/Kernel/Singularity.Hal.Acpi/AcpiTables.cs

#
C# | 785 lines | 694 code | 62 blank | 29 comment | 46 complexity | ddfce769e966a48c0782490665cd040d MD5 | raw file
  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Microsoft Research Singularity
  4. //
  5. // Copyright (c) Microsoft Corporation. All rights reserved.
  6. //
  7. // File: AcpiTables.cs
  8. //
  9. // Note:
  10. // Based on ACPI 3.0 Spec.
  11. // Define to dump all ACPI tables in uuencoded binary form to the debugger
  12. // at boot time.
  13. //#define DUMP_ACPI_TABLES_UUENCODED
  14. // Define to dump a trace of all raw read/writes performed by the ACPI
  15. // interpreter to the debugger. This can be processed by a tool
  16. // %SINGULARITY_ROOT%\Windows\ACPI\TestFiles\parse_read_write_trace.pl
  17. // to produce a read/write trace for use by the test harness.
  18. //#define DUMP_RAW_READ_WRITES
  19. // Define to dump all names in the initial ACPI namespace tree.
  20. //#define DUMP_ACPI_NAMESPACE
  21. namespace Microsoft.Singularity.Hal.Acpi
  22. {
  23. using System;
  24. using System.Collections;
  25. using System.Text;
  26. using Microsoft.Singularity.Io;
  27. using Microsoft.Singularity.Hal;
  28. internal sealed class VerboseOut
  29. {
  30. [System.Diagnostics.Conditional("VERBOSE")]
  31. internal static void WriteLine(string format, __arglist)
  32. {
  33. DebugStub.WriteLine(format, new ArgIterator(__arglist));
  34. }
  35. [System.Diagnostics.Conditional("VERBOSE")]
  36. internal static void WriteLine(string message)
  37. {
  38. DebugStub.WriteLine(message);
  39. }
  40. [System.Diagnostics.Conditional("VERBOSE")]
  41. internal static void WriteLine()
  42. {
  43. DebugStub.WriteLine();
  44. }
  45. [System.Diagnostics.Conditional("VERBOSE")]
  46. internal static void Write(string format, __arglist)
  47. {
  48. DebugStub.Write(format, new ArgIterator(__arglist));
  49. }
  50. [System.Diagnostics.Conditional("VERBOSE")]
  51. internal static void Write(string message)
  52. {
  53. DebugStub.Write(message);
  54. }
  55. [System.Diagnostics.Conditional("VERBOSE")]
  56. internal static void Print(string format, __arglist)
  57. {
  58. DebugStub.Print(format, new ArgIterator(__arglist));
  59. }
  60. [System.Diagnostics.Conditional("VERBOSE")]
  61. internal static void Print(string message)
  62. {
  63. DebugStub.Print(message);
  64. }
  65. }
  66. [ CLSCompliant(false) ]
  67. public class AcpiTables
  68. {
  69. private static Fadt fadt;
  70. private static Madt madt;
  71. private static Dsdt dsdt;
  72. private static Ssdt ssdt;
  73. private static Srat srat;
  74. private static SystemTableHeader rsdtHeader;
  75. private static Rsdt rsdt;
  76. private static PMTimer pmTimer;
  77. private static AcpiNamespace acpiNamespace;
  78. private static ReservedObjects reservedObjects;
  79. private static UIntPtr GetRsdpBase()
  80. {
  81. unsafe
  82. {
  83. return Platform.ThePlatform.AcpiRoot32;
  84. }
  85. }
  86. public static Fadt GetFadt()
  87. {
  88. return fadt;
  89. }
  90. public static Madt GetMadt()
  91. {
  92. return madt;
  93. }
  94. public static Srat GetSrat()
  95. {
  96. return srat;
  97. }
  98. public static PMTimer GetPMTimer()
  99. {
  100. return pmTimer;
  101. }
  102. public static AcpiNamespace AcpiNamespace
  103. {
  104. get
  105. {
  106. return acpiNamespace;
  107. }
  108. }
  109. private class StringSet
  110. {
  111. private SortedList map = new SortedList();
  112. public void Add(string s)
  113. {
  114. map.Add(s, null);
  115. }
  116. public bool Contains(string s)
  117. {
  118. return map.ContainsKey(s);
  119. }
  120. }
  121. public static void Parse()
  122. {
  123. UIntPtr rsdpBase = GetRsdpBase();
  124. if (rsdpBase == UIntPtr.Zero) {
  125. VerboseOut.Print("ACPI RSDP not found\n");
  126. }
  127. #if DUMP_ACPI_TABLES_UUENCODED
  128. UuencodeDumpRegion("RSDP.dmp",
  129. IoMemory.MapPhysicalMemory(
  130. rsdpBase, 36u,
  131. true, false));
  132. #endif
  133. Rsdp rsdp = Rsdp.Parse(rsdpBase, 36u);
  134. VerboseOut.Print("ACPI RSDP OemId is {0:x8}\n",
  135. __arglist(rsdp.OemId));
  136. VerboseOut.Print("ACPI RSDP revision is {0:x8}\n",
  137. __arglist(rsdp.Revision));
  138. if (rsdp.Revision == 2) {
  139. rsdtHeader = SystemTableHeader.Create(rsdp.XsdtAddress);
  140. #if DUMP_ACPI_TABLES_UUENCODED
  141. UuencodeDumpRegion("XSDT.dmp",
  142. IoMemory.MapPhysicalMemory(
  143. rsdtHeader.Address, rsdtHeader.FullTableLength,
  144. true, false));
  145. #endif
  146. rsdt = Xsdt.Create(rsdtHeader);
  147. }
  148. else {
  149. rsdtHeader = SystemTableHeader.Create(rsdp.RsdtAddress);
  150. #if DUMP_ACPI_TABLES_UUENCODED
  151. UuencodeDumpRegion("RSDT.dmp",
  152. IoMemory.MapPhysicalMemory(
  153. rsdtHeader.Address, rsdtHeader.FullTableLength,
  154. true, false));
  155. #endif
  156. rsdt = Rsdt.Create(rsdtHeader);
  157. }
  158. VerboseOut.Print("ACPI RSDT/XSDT OemTableId is {0}\n",
  159. __arglist(rsdtHeader.OemTableId));
  160. VerboseOut.Print("ACPI RSDT/XSDT Revision is {0:x8}\n",
  161. __arglist(rsdtHeader.Revision));
  162. VerboseOut.Print("ACPI RSDT/XSDT CreatorId is {0:x8}\n",
  163. __arglist(rsdtHeader.CreatorId));
  164. VerboseOut.Print("ACPI RSDT/XSDT CreatorRevision is {0:x8}\n",
  165. __arglist(rsdtHeader.CreatorRevision));
  166. VerboseOut.Print("RSDT contains:\n");
  167. for (int i = 0; i < rsdt.EntryCount; i++) {
  168. SystemTableHeader header = rsdt.GetTableHeader(i);
  169. VerboseOut.Print(" {0:x8}\n", __arglist(header.Signature));
  170. if (header.Signature == Fadt.Signature) {
  171. fadt = Fadt.Create(header);
  172. }
  173. else if (header.Signature == Madt.Signature) {
  174. madt = Madt.Create(header);
  175. }
  176. else if (header.Signature == Ssdt.Signature) {
  177. ssdt = Ssdt.Create(header);
  178. }
  179. // Srat, Slit
  180. else if (header.Signature == Srat.Signature) {
  181. srat = Srat.Create(header);
  182. srat.ParseSratStructure();
  183. // srat.DumpSratOffsets();
  184. // srat.DumpSratImportantFields();
  185. // srat.DumpSratStructure();
  186. }
  187. }
  188. SystemTableHeader dsdtHeader = null;
  189. if (fadt != null) {
  190. pmTimer = PMTimer.Create(fadt);
  191. VerboseOut.Print("PMTimer Value={0} Width={1}\n",
  192. __arglist(pmTimer.Value, pmTimer.Width));
  193. uint t0 = pmTimer.Value;
  194. uint t1 = pmTimer.Value;
  195. uint t2 = pmTimer.Value;
  196. uint delta = (t2 >= t1) ? t2 - t1 : ((t1 | 0xff000000) - t2);
  197. VerboseOut.Print("Read cost {0} ticks\n", __arglist(delta));
  198. if (fadt.DSDT != 0) {
  199. dsdtHeader = SystemTableHeader.Create(fadt.DSDT);
  200. dsdt = Dsdt.Create(dsdtHeader);
  201. }
  202. }
  203. VerboseOut.Print("Parsing and loading AML\n");
  204. #if DUMP_ACPI_TABLES_UUENCODED
  205. if (dsdtHeader != null) {
  206. UuencodeDumpRegion("ACPI.DSDT.dmp",
  207. IoMemory.MapPhysicalMemory(
  208. dsdtHeader.Address, dsdtHeader.FullTableLength,
  209. true, false));
  210. }
  211. for (int i = 0; i < rsdt.EntryCount; i++) {
  212. SystemTableHeader header = rsdt.GetTableHeader(i);
  213. UuencodeDumpRegion("ACPI." + header.Signature + "." + header.OemTableId + ".dmp",
  214. IoMemory.MapPhysicalMemory(
  215. header.Address, header.FullTableLength,
  216. true, false));
  217. }
  218. #endif // DUMP_ACPI_TABLES_UUENCODED
  219. }
  220. public static AcpiDevice[] LoadDevices()
  221. {
  222. OperationRegionAccessor operationRegionAccessor = new OperationRegionAccessor();
  223. acpiNamespace = new AcpiNamespace();
  224. reservedObjects = new ReservedObjects(acpiNamespace);
  225. reservedObjects.CreateReservedObjects();
  226. if (dsdt != null) {
  227. if (ParseAndLoadRegion(dsdt.Region, operationRegionAccessor) == AmlParser.ParseSuccess.Failure) {
  228. throw new Exception("AML parser failure while parsing DSDT");
  229. }
  230. }
  231. // From the spec: "SSDTs are a continuation of the DSDT. Multiple SSDTs
  232. // can be used as part of a platform description. After the DSDT is loaded
  233. // into the ACPI Namespace, each secondary description table listed in the
  234. // RSDT/XSDT with a unique OEM Table ID is loaded." - section 2.1, General
  235. // ACPI Terminology
  236. StringSet visitedOemTableIds = new StringSet();
  237. for (int i = 0; i < rsdt.EntryCount; i++) {
  238. SystemTableHeader header = rsdt.GetTableHeader(i);
  239. VerboseOut.Print(" {0:x8}\n", __arglist(header.Signature));
  240. string oemTableId = header.OemTableId;
  241. if (!visitedOemTableIds.Contains(oemTableId) && header.Signature == Ssdt.Signature) {
  242. visitedOemTableIds.Add(oemTableId);
  243. ssdt = Ssdt.Create(header);
  244. if (ParseAndLoadRegion(ssdt.Region, operationRegionAccessor) == AmlParser.ParseSuccess.Failure) {
  245. throw new Exception("AML parser failure while parsing SSDT " + oemTableId);
  246. }
  247. }
  248. }
  249. #if DUMP_ACPI_NAMESPACE
  250. DebugStub.WriteLine("Dumping ACPI namespace tree...");
  251. acpiNamespace.DumpTree();
  252. #endif
  253. return GetDeviceInfo(operationRegionAccessor);
  254. }
  255. #if DUMP_ACPI_TABLES_UUENCODED
  256. private static void UuencodeDumpRegion(string filename, IoMemory region)
  257. {
  258. DebugStub.Print("\nbegin 777 {0}\n", __arglist(filename));
  259. StringBuilder line = new StringBuilder();
  260. int inputBytesOnLine = 0;
  261. for (int i = 0; i < region.Length; i += 3) {
  262. byte b1 = (byte)0, b2 = (byte)0, b3 = (byte)0;
  263. b1 = region.Read8(i);
  264. inputBytesOnLine++;
  265. if (i + 1 < region.Length) {
  266. b2 = region.Read8(i + 1);
  267. inputBytesOnLine++;
  268. }
  269. if (i + 2 < region.Length) {
  270. b3 = region.Read8(i + 2);
  271. inputBytesOnLine++;
  272. }
  273. line.Append((char)(32 + (b1 >> 2)));
  274. line.Append((char)(32 + (((b1 << 4) | (b2 >> 4)) & 0x3F)));
  275. line.Append((char)(32 + (((b2 << 2) | (b3 >> 6)) & 0x3F)));
  276. line.Append((char)(32 + (b3 & 0x3F)));
  277. if (line.Length >= 60 || i + 3 >= region.Length) {
  278. DebugStub.Print("{0}{1}\n", __arglist((char)(inputBytesOnLine + 32), line.ToString()));
  279. line.Remove(0, line.Length);
  280. inputBytesOnLine = 0;
  281. }
  282. }
  283. DebugStub.Print("end\n\n");
  284. }
  285. #endif // #if DUMP_ACPI_TABLES_UUENCODED
  286. private static AmlParser.ParseSuccess ParseAndLoadRegion(IoMemory region, AcpiObject.IOperationRegionAccessor operationRegionAccessor)
  287. {
  288. AmlParser.AMLCode result;
  289. int offset = 0;
  290. AmlParser parser = new AmlParser(new IoMemoryAmlStreamAdapter(region), null, null);
  291. AmlParser.ParseSuccess parseSuccess =
  292. parser.ParseAMLCode(out result, ref offset, region.Length);
  293. if (parseSuccess == AmlParser.ParseSuccess.Success) {
  294. AmlLoader loader = new AmlLoader(acpiNamespace, operationRegionAccessor);
  295. loader.Load(result);
  296. }
  297. return parseSuccess;
  298. }
  299. private static AcpiDevice[] GetDeviceInfo(AcpiObject.IOperationRegionAccessor operationRegionAccessor)
  300. {
  301. ArrayList deviceInfo = new ArrayList();
  302. AmlInterpreter interpreter = new AmlInterpreter(acpiNamespace, operationRegionAccessor);
  303. foreach (AcpiNamespace.Node crsNode in acpiNamespace.GetAllNodes()) {
  304. if (crsNode.Name != "_CRS") {
  305. continue;
  306. }
  307. VerboseOut.Write("Loading resource descriptors for ACPI device ");
  308. foreach (string segment in crsNode.Path.RemoveSegment().NameSegments) {
  309. VerboseOut.Write(segment + "\\");
  310. }
  311. VerboseOut.WriteLine();
  312. AcpiNamespace.Node hidNode =
  313. acpiNamespace.LookupNode(crsNode.Path.RemoveSegmentAbsolute().AddSegmentAbsolute("_HID"));
  314. if (hidNode == null) {
  315. throw new Exception("Found device with _CRS property but no matching _HID property");
  316. }
  317. AcpiObject.AcpiObject hidObject = hidNode.Value;
  318. if (hidObject is AcpiObject.BytecodeMethod) {
  319. AmlInterpreterThread thread =
  320. interpreter.InvokeMethodOnNewThread(null, hidNode.Path, new AcpiObject.AcpiObject[] { });
  321. interpreter.Run();
  322. hidObject = thread.ExitValue;
  323. }
  324. string deviceId = HidObjectToDeviceId(hidObject);
  325. AcpiObject.AcpiObject crsObject = crsNode.Value;
  326. if (crsObject is AcpiObject.BytecodeMethod) {
  327. AmlInterpreterThread thread =
  328. interpreter.InvokeMethodOnNewThread(null, crsNode.Path, new AcpiObject.AcpiObject[] { });
  329. interpreter.Run();
  330. crsObject = thread.ExitValue;
  331. }
  332. if (crsObject is AcpiObject.Buffer) {
  333. byte[] crsBuffer = crsObject.GetAsBuffer().Contents;
  334. ResourceDescriptor[] resourceDescriptors = ResourceDescriptorParser.Parse(crsBuffer);
  335. VerboseOut.WriteLine("Loaded resource descriptor for device " + deviceId);
  336. deviceInfo.Add(new AcpiDevice(deviceId, resourceDescriptors));
  337. }
  338. else {
  339. VerboseOut.WriteLine("No resource descriptor for device " + deviceId);
  340. }
  341. }
  342. return (AcpiDevice[])deviceInfo.ToArray(typeof(AcpiDevice));
  343. }
  344. private static string HidObjectToDeviceId(AcpiObject.AcpiObject obj)
  345. {
  346. AcpiObject.AcpiObjectType type =
  347. (AcpiObject.AcpiObjectType)((AcpiObject.Integer)(obj.ObjectType())).Value;
  348. string hid;
  349. if (type == AcpiObject.AcpiObjectType.Integer)
  350. {
  351. // Swap byte order so that all fields are contiguous
  352. ulong eisaId = ByteOrder.Swap((uint)(((AcpiObject.Integer)obj).Value));
  353. hid = String.Format("{0}{1}{2}{3:X}{4:X}{5:X}{6:X}",
  354. (char)(((eisaId >> 26) & 0x1F) + '@'),
  355. (char)(((eisaId >> 21) & 0x1F) + '@'),
  356. (char)(((eisaId >> 16) & 0x1F) + '@'),
  357. (eisaId >> 12) & 0xF,
  358. (eisaId >> 8) & 0xF,
  359. (eisaId >> 4) & 0xF,
  360. (eisaId >> 0) & 0xF);
  361. }
  362. else if (type == AcpiObject.AcpiObjectType.String) {
  363. hid = ((AcpiObject.String)obj).Value;
  364. }
  365. else {
  366. throw new ArgumentException("_HID object was not an integer or string as expected");
  367. }
  368. if (hid.StartsWith("PNP")) {
  369. return "/pnp/" + hid;
  370. }
  371. else {
  372. return "/acpi/" + hid;
  373. }
  374. }
  375. public class IoMemoryAmlStreamAdapter : IAmlStream
  376. {
  377. private IoMemory region;
  378. public IoMemoryAmlStreamAdapter(IoMemory region)
  379. {
  380. this.region = region;
  381. }
  382. public byte ReadByteData(ref int offset)
  383. {
  384. if (offset + 1 > region.Length) {
  385. throw new EndOfAmlStreamException();
  386. }
  387. byte result = region.Read8(offset);
  388. offset++;
  389. return result;
  390. }
  391. public bool TryReadByteData(ref int offset, out byte result)
  392. {
  393. if (offset + 1 > region.Length) {
  394. result = 0;
  395. return false;
  396. }
  397. result = region.Read8(offset);
  398. offset++;
  399. return true;
  400. }
  401. public char ReadChar(ref int offset)
  402. {
  403. if (offset + 1 > region.Length) {
  404. throw new EndOfAmlStreamException();
  405. }
  406. char result = (char)region.Read8(offset);
  407. offset++;
  408. return result;
  409. }
  410. public byte[] ReadByteDataArray(ref int offset, int length)
  411. {
  412. if (offset + length > region.Length) {
  413. throw new EndOfAmlStreamException();
  414. }
  415. byte[] result = new byte[length];
  416. if (length != 0) {
  417. region.Read8(offset, result, 0, length);
  418. }
  419. offset += length;
  420. return result;
  421. }
  422. public bool TryReadByteDataArray(ref int offset, int length, out byte[] result)
  423. {
  424. if (offset + length > region.Length) {
  425. result = null;
  426. return false;
  427. }
  428. result = new byte[length];
  429. if (length != 0) {
  430. region.Read8(offset, result, 0, length);
  431. }
  432. offset += length;
  433. return true;
  434. }
  435. public ushort ReadWordData(ref int offset)
  436. {
  437. if (offset + 2 > region.Length) {
  438. throw new EndOfAmlStreamException();
  439. }
  440. ushort result = ByteOrder.LittleEndianToHost(region.Read16(offset));
  441. offset += 2;
  442. return result;
  443. }
  444. public uint ReadDWordData(ref int offset)
  445. {
  446. if (offset + 4 > region.Length) {
  447. throw new EndOfAmlStreamException();
  448. }
  449. uint result = ByteOrder.LittleEndianToHost(region.Read32(offset));
  450. offset += 4;
  451. return result;
  452. }
  453. public ulong ReadQWordData(ref int offset)
  454. {
  455. if (offset + 8 > region.Length) {
  456. throw new EndOfAmlStreamException();
  457. }
  458. ulong result = ByteOrder.LittleEndianToHost(region.Read64(offset));
  459. offset += 8;
  460. return result;
  461. }
  462. }
  463. public class OperationRegionAccessor : AcpiObject.IOperationRegionAccessor
  464. {
  465. private const ushort PciAddressPort = 0xcf8;
  466. private const uint PciConfigEnableMask = 1u << 31;
  467. private IoPort pciConfigAddressPort;
  468. private IoPort pciConfigDataPort;
  469. public OperationRegionAccessor()
  470. {
  471. IoPortRange pciConfigPorts = new IoPortRange(PciAddressPort, 8, Access.ReadWrite);
  472. pciConfigAddressPort = pciConfigPorts.PortAtOffset(0, 4, Access.Write);
  473. pciConfigDataPort = pciConfigPorts.PortAtOffset(4, 4, Access.ReadWrite);
  474. }
  475. public byte Read8(AcpiObject.RegionSpace regionSpace, ulong offset)
  476. {
  477. byte result;
  478. switch (regionSpace) {
  479. case AcpiObject.RegionSpace.SystemMemory:
  480. // TODO: This is a first stab - ideally the AcpiObject.OperationRegion
  481. // ought to be holding onto an IoMemoryRange and passing it in repeatedly.
  482. IoMemory region = IoMemory.MapPhysicalMemory(offset, 1, true/*readable*/, false/*writable*/);
  483. result = region.Read8(0);
  484. break;
  485. case AcpiObject.RegionSpace.SystemIO:
  486. IoPort port = new IoPort((ushort)offset, 1, Access.Read);
  487. result = port.Read8();
  488. break;
  489. case AcpiObject.RegionSpace.PCI_Config:
  490. pciConfigAddressPort.Write32(PciConfigEnableMask | (uint)offset);
  491. result = pciConfigDataPort.Read8();
  492. break;
  493. default:
  494. throw new Exception("Unimplemented operation region type" + regionSpace);
  495. }
  496. #if DUMP_RAW_READ_WRITES
  497. DebugStub.WriteLine("ACPI read: space: " + regionSpace + ", offset: " + offset + ", bytes: " + 1 + ", result: " + result.ToString("X"));
  498. #endif
  499. return result;
  500. }
  501. public void Write8(AcpiObject.RegionSpace regionSpace, ulong offset, byte value)
  502. {
  503. #if DUMP_RAW_READ_WRITES
  504. DebugStub.WriteLine("ACPI write: space: " + regionSpace + ", offset: " + offset + ", bytes: " + 1 + ", value: " + value.ToString("X"));
  505. #endif
  506. switch (regionSpace) {
  507. case AcpiObject.RegionSpace.SystemMemory:
  508. IoMemory region = IoMemory.MapPhysicalMemory(offset, 1, true/*readable*/, true/*writable*/);
  509. region.Write8(0, value);
  510. break;
  511. case AcpiObject.RegionSpace.SystemIO:
  512. IoPort port = new IoPort((ushort)offset, 1, Access.ReadWrite);
  513. port.Write8(value);
  514. break;
  515. case AcpiObject.RegionSpace.PCI_Config:
  516. pciConfigAddressPort.Write32(PciConfigEnableMask | (uint)offset);
  517. pciConfigDataPort.Write8(value);
  518. break;
  519. default:
  520. throw new Exception("Unimplemented operation region type" + regionSpace);
  521. }
  522. }
  523. public ushort Read16(AcpiObject.RegionSpace regionSpace, ulong offset)
  524. {
  525. ushort result;
  526. switch (regionSpace) {
  527. case AcpiObject.RegionSpace.SystemMemory:
  528. // TODO: This is a first stab - ideally the AcpiObject.OperationRegion
  529. // ought to be holding onto an IoMemoryRange and passing it in.
  530. IoMemory region = IoMemory.MapPhysicalMemory(offset, 2, true/*readable*/, false/*writable*/);
  531. result = region.Read16(0);
  532. break;
  533. case AcpiObject.RegionSpace.SystemIO:
  534. IoPort port = new IoPort((ushort)offset, 2, Access.Read);
  535. result = port.Read16();
  536. break;
  537. case AcpiObject.RegionSpace.PCI_Config:
  538. pciConfigAddressPort.Write32(PciConfigEnableMask | (uint)offset);
  539. result = pciConfigDataPort.Read16();
  540. break;
  541. default:
  542. throw new Exception("Unimplemented operation region type" + regionSpace);
  543. }
  544. #if DUMP_RAW_READ_WRITES
  545. DebugStub.WriteLine("ACPI read: space: " + regionSpace + ", offset: " + offset + ", bytes: " + 2 + ", result: " + result.ToString("X"));
  546. #endif
  547. return result;
  548. }
  549. public void Write16(AcpiObject.RegionSpace regionSpace, ulong offset, ushort value)
  550. {
  551. #if DUMP_RAW_READ_WRITES
  552. DebugStub.WriteLine("ACPI write: space: " + regionSpace + ", offset: " + offset + ", bytes: " + 2 + ", value: " + value.ToString("X"));
  553. #endif
  554. switch (regionSpace) {
  555. case AcpiObject.RegionSpace.SystemMemory:
  556. IoMemory region = IoMemory.MapPhysicalMemory(offset, 2, true/*readable*/, true/*writable*/);
  557. region.Write16(0, value);
  558. break;
  559. case AcpiObject.RegionSpace.SystemIO:
  560. IoPort port = new IoPort((ushort)offset, 2, Access.ReadWrite);
  561. port.Write16(value);
  562. break;
  563. case AcpiObject.RegionSpace.PCI_Config:
  564. pciConfigAddressPort.Write32(PciConfigEnableMask | (uint)offset);
  565. pciConfigDataPort.Write16(value);
  566. break;
  567. default:
  568. throw new Exception("Unimplemented operation region type" + regionSpace);
  569. }
  570. }
  571. public uint Read32(AcpiObject.RegionSpace regionSpace, ulong offset)
  572. {
  573. uint result;
  574. switch (regionSpace) {
  575. case AcpiObject.RegionSpace.SystemMemory:
  576. IoMemory region = IoMemory.MapPhysicalMemory(offset, 4, true/*readable*/, false/*writable*/);
  577. result = region.Read32(0);
  578. break;
  579. case AcpiObject.RegionSpace.SystemIO:
  580. IoPort port = new IoPort((ushort)offset, 4, Access.Read);
  581. result = port.Read32();
  582. break;
  583. case AcpiObject.RegionSpace.PCI_Config:
  584. pciConfigAddressPort.Write32(PciConfigEnableMask | (uint)offset);
  585. result = pciConfigDataPort.Read32();
  586. break;
  587. default:
  588. throw new Exception("Unimplemented operation region type" + regionSpace);
  589. }
  590. #if DUMP_RAW_READ_WRITES
  591. DebugStub.WriteLine("ACPI read: space: " + regionSpace + ", offset: " + offset + ", bytes: " + 4 + ", result: " + result.ToString("X"));
  592. #endif
  593. return result;
  594. }
  595. public void Write32(AcpiObject.RegionSpace regionSpace, ulong offset, uint value)
  596. {
  597. #if DUMP_RAW_READ_WRITES
  598. DebugStub.WriteLine("ACPI write: space: " + regionSpace + ", offset: " + offset + ", bytes: " + 4 + ", value: " + value.ToString("X"));
  599. #endif
  600. switch (regionSpace) {
  601. case AcpiObject.RegionSpace.SystemMemory:
  602. IoMemory region = IoMemory.MapPhysicalMemory(offset, 4, true/*readable*/, true/*writable*/);
  603. region.Write32(0, value);
  604. break;
  605. case AcpiObject.RegionSpace.SystemIO:
  606. IoPort port = new IoPort((ushort)offset, 4, Access.ReadWrite);
  607. port.Write32(value);
  608. break;
  609. case AcpiObject.RegionSpace.PCI_Config:
  610. pciConfigAddressPort.Write32(PciConfigEnableMask | (uint)offset);
  611. pciConfigDataPort.Write32(value);
  612. break;
  613. default:
  614. throw new Exception("Unimplemented operation region type" + regionSpace);
  615. }
  616. }
  617. public byte[] ReadBytes(AcpiObject.RegionSpace regionSpace, ulong offset, ulong length)
  618. {
  619. byte[] result = new byte[length];
  620. switch (regionSpace) {
  621. case AcpiObject.RegionSpace.SystemMemory:
  622. IoMemory region = IoMemory.MapPhysicalMemory(offset, length, true/*readable*/, false/*writable*/);
  623. for (ulong i = 0; i < length; i++) {
  624. result[i] = region.Read8((int)i);
  625. }
  626. break;
  627. default:
  628. throw new Exception("ReadBytes() only supported for SystemMemory regions");
  629. }
  630. #if DUMP_RAW_READ_WRITES
  631. DebugStub.Write("ACPI read: space: " + regionSpace + ", offset: " + offset + ", bytes: " + length + ", result: {");
  632. for (int i = 0; i < result.Length; i++) {
  633. DebugStub.Write(result[i].ToString("X"));
  634. if (i < result.Length - 1) {
  635. DebugStub.Write(",");
  636. }
  637. }
  638. DebugStub.WriteLine("}");
  639. #endif
  640. return result;
  641. }
  642. }
  643. }
  644. public class AcpiDevice
  645. {
  646. string deviceId;
  647. ResourceDescriptor[] resourceDescriptors;
  648. public AcpiDevice(string deviceId, ResourceDescriptor[] resourceDescriptors)
  649. {
  650. this.deviceId = deviceId;
  651. this.resourceDescriptors = resourceDescriptors;
  652. }
  653. public string DeviceId
  654. {
  655. get
  656. {
  657. return deviceId;
  658. }
  659. }
  660. public ResourceDescriptor[] ResourceDescriptors {
  661. get
  662. {
  663. return resourceDescriptors;
  664. }
  665. }
  666. }
  667. }