olsneracpi.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  1. /*
  2. Copyright (c) 2014 Simon Brenner
  3. Permission is hereby granted, free of charge, to any person obtaining a copy
  4. of this software and associated documentation files (the "Software"), to deal
  5. in the Software without restriction, including without limitation the rights
  6. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. copies of the Software, and to permit persons to whom the Software is
  8. furnished to do so, subject to the following conditions:
  9. The above copyright notice and this permission notice shall be included in
  10. all copies or substantial portions of the Software.
  11. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  12. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  13. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  14. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  15. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  16. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  17. THE SOFTWARE.
  18. */
  19. #include "acpi.h"
  20. #include "accommon.h"
  21. #include "acapps.h"
  22. #include "actables.h"
  23. #include "acutils.h"
  24. #include <errno.h>
  25. #define _COMPONENT ACPI_UTILITIES
  26. ACPI_MODULE_NAME ("harvey")
  27. /******************************************************************************
  28. *
  29. * Example ACPICA handler and handler installation
  30. *
  31. *****************************************************************************/
  32. #if 0
  33. static void NotifyHandler (
  34. ACPI_HANDLE Device,
  35. UINT32 Value,
  36. void *Context)
  37. {
  38. ACPI_INFO ((AE_INFO, "Received a notify 0x%x (device %p, context %p)", Value, Device, Context));
  39. }
  40. static ACPI_STATUS InstallHandlers (void)
  41. {
  42. ACPI_STATUS Status;
  43. /* Install global notify handler */
  44. Status = AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY,
  45. NotifyHandler, NULL);
  46. if (ACPI_FAILURE (Status))
  47. {
  48. ACPI_EXCEPTION ((AE_INFO, Status, "While installing Notify handler"));
  49. return (Status);
  50. }
  51. return (AE_OK);
  52. }
  53. /******************************************************************************
  54. *
  55. * Example ACPICA initialization code. This shows a full initialization with
  56. * no early ACPI table access.
  57. *
  58. *****************************************************************************/
  59. static ACPI_STATUS InitializeFullAcpi (void)
  60. {
  61. ACPI_STATUS Status;
  62. /* Initialize the ACPICA subsystem */
  63. Status = AcpiInitializeSubsystem ();
  64. if (ACPI_FAILURE (Status))
  65. {
  66. ACPI_EXCEPTION ((AE_INFO, Status, "While initializing ACPICA"));
  67. return (Status);
  68. }
  69. /* Initialize the ACPICA Table Manager and get all ACPI tables */
  70. Status = AcpiInitializeTables (NULL, 0, FALSE);
  71. if (ACPI_FAILURE (Status))
  72. {
  73. ACPI_EXCEPTION ((AE_INFO, Status, "While initializing Table Manager"));
  74. return (Status);
  75. }
  76. /* Create the ACPI namespace from ACPI tables */
  77. Status = AcpiLoadTables ();
  78. if (ACPI_FAILURE (Status))
  79. {
  80. ACPI_EXCEPTION ((AE_INFO, Status, "While loading ACPI tables"));
  81. return (Status);
  82. }
  83. /* Install local handlers */
  84. Status = InstallHandlers ();
  85. if (ACPI_FAILURE (Status))
  86. {
  87. ACPI_EXCEPTION ((AE_INFO, Status, "While installing handlers"));
  88. return (Status);
  89. }
  90. /* Initialize the ACPI hardware */
  91. Status = AcpiEnableSubsystem (ACPI_FULL_INITIALIZATION);
  92. if (ACPI_FAILURE (Status))
  93. {
  94. ACPI_EXCEPTION ((AE_INFO, Status, "While enabling ACPICA"));
  95. return (Status);
  96. }
  97. /* Complete the ACPI namespace object initialization */
  98. Status = AcpiInitializeObjects (ACPI_FULL_INITIALIZATION);
  99. if (ACPI_FAILURE (Status))
  100. {
  101. ACPI_EXCEPTION ((AE_INFO, Status, "While initializing ACPICA objects"));
  102. return (Status);
  103. }
  104. return (AE_OK);
  105. }
  106. static ACPI_STATUS ExecuteOSI(int pic_mode)
  107. {
  108. ACPI_STATUS Status;
  109. ACPI_OBJECT_LIST ArgList;
  110. ACPI_OBJECT Arg[1];
  111. ACPI_BUFFER ReturnValue;
  112. /* Setup input argument */
  113. ArgList.Count = 1;
  114. ArgList.Pointer = Arg;
  115. Arg[0].Type = ACPI_TYPE_INTEGER;
  116. Arg[0].Integer.Value = pic_mode;
  117. ACPI_INFO ((AE_INFO, "Executing _PIC(%ld)", Arg[0].Integer.Value));
  118. /* Ask ACPICA to allocate space for the return object */
  119. ReturnValue.Length = ACPI_ALLOCATE_BUFFER;
  120. Status = AcpiEvaluateObject (NULL, "\\_PIC", &ArgList, &ReturnValue);
  121. ////ACPI_FREE_BUFFER(ReturnValue);
  122. if (Status == AE_NOT_FOUND)
  123. {
  124. printf("\\_PIC was not found. Assuming that's ok.\n");
  125. return AE_OK;
  126. }
  127. if (ACPI_FAILURE (Status))
  128. {
  129. ACPI_EXCEPTION ((AE_INFO, Status, "While executing _PIC"));
  130. return Status;
  131. }
  132. printf("_PIC returned.\n");
  133. return Status;
  134. }
  135. #endif
  136. #define CHECK_STATUS(fmt, ...) do { if (ACPI_FAILURE(status)) { \
  137. printf("ACPI failed (%d): " fmt "\n", status, ## __VA_ARGS__); \
  138. goto failed; \
  139. } } while(0)
  140. #pragma pack(1)
  141. typedef union acpi_apic_struct
  142. {
  143. struct {
  144. UINT8 Type;
  145. UINT8 Length;
  146. };
  147. ACPI_MADT_LOCAL_APIC LocalApic;
  148. ACPI_MADT_IO_APIC IOApic;
  149. ACPI_MADT_INTERRUPT_OVERRIDE InterruptOverride;
  150. ACPI_MADT_LOCAL_APIC_NMI LocalApicNMI;
  151. } ACPI_APIC_STRUCT;
  152. #pragma pack()
  153. ACPI_STATUS FindIOAPICs(int *pic_mode) {
  154. ACPI_TABLE_MADT* table = NULL;
  155. ACPI_STATUS status = AcpiGetTable("APIC", 0, (ACPI_TABLE_HEADER**)&table);
  156. CHECK_STATUS("AcpiGetTable");
  157. char* endOfTable = (char*)table + table->Header.Length;
  158. char* p = (char*)(table + 1);
  159. int n = 0;
  160. while (p < endOfTable) {
  161. ACPI_APIC_STRUCT* apic = (ACPI_APIC_STRUCT*)p;
  162. p += apic->Length;
  163. n++;
  164. switch (apic->Type)
  165. {
  166. case ACPI_MADT_TYPE_IO_APIC:
  167. printf("Found I/O APIC. ID %#x Addr %#x GSI base %#x.\n",
  168. (int)apic->IOApic.Id,
  169. apic->IOApic.Address,
  170. apic->IOApic.GlobalIrqBase);
  171. //AddIOAPIC(&apic->IOApic);
  172. *pic_mode = 1;
  173. break;
  174. }
  175. }
  176. if (*pic_mode)
  177. {
  178. printf("I/O APICs found, setting APIC mode\n");
  179. }
  180. else
  181. {
  182. printf("I/O APICs NOT found, setting PIC mode\n");
  183. //AddPIC();
  184. }
  185. failed:
  186. return AE_OK;
  187. }
  188. static ACPI_STATUS PrintAPICTable(void) {
  189. static const char *polarities[] = {
  190. "Bus-Conformant",
  191. "Active-High",
  192. "Reserved",
  193. "Active-Low"
  194. };
  195. static const char *triggerings[] = {
  196. "Bus-Conformant",
  197. "Edge-Triggered",
  198. "Reserved",
  199. "Level-Triggered"
  200. };
  201. ACPI_TABLE_MADT* table = NULL;
  202. ACPI_STATUS status = AcpiGetTable("APIC", 0, (ACPI_TABLE_HEADER**)&table);
  203. CHECK_STATUS("AcpiGetTable");
  204. printf("Found APIC table: %p\n", table);
  205. printf("Address of Local APIC: %#x\n", table->Address);
  206. printf("Flags: %#x\n", table->Flags);
  207. char* endOfTable = (char*)table + table->Header.Length;
  208. char* p = (char*)(table + 1);
  209. int n = 0;
  210. while (p < endOfTable) {
  211. ACPI_APIC_STRUCT* apic = (ACPI_APIC_STRUCT*)p;
  212. p += apic->Length;
  213. n++;
  214. switch (apic->Type)
  215. {
  216. case ACPI_MADT_TYPE_LOCAL_APIC:
  217. printf("%d: Local APIC. Processor ID %#x APIC ID %#x En=%d (%#x)\n", n,
  218. (int)apic->LocalApic.ProcessorId,
  219. (int)apic->LocalApic.Id,
  220. apic->LocalApic.LapicFlags & 1,
  221. apic->LocalApic.LapicFlags);
  222. break;
  223. case ACPI_MADT_TYPE_IO_APIC:
  224. printf("%d: I/O APIC. ID %#x Addr %#x GSI base %#x\n", n,
  225. (int)apic->IOApic.Id,
  226. apic->IOApic.Address,
  227. apic->IOApic.GlobalIrqBase);
  228. break;
  229. case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
  230. {
  231. UINT32 flags = apic->InterruptOverride.IntiFlags;
  232. printf("%d: Interrupt Override. Source %#x GSI %#x Pol=%s Trigger=%s\n", n,
  233. apic->InterruptOverride.SourceIrq,
  234. apic->InterruptOverride.GlobalIrq,
  235. polarities[flags & 3], triggerings[(flags >> 2) & 3]);
  236. break;
  237. }
  238. case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
  239. {
  240. UINT32 flags = apic->InterruptOverride.IntiFlags;
  241. printf("%d: Local APIC NMI. Processor ID %#x Pol=%s Trigger=%s LINT# %#x\n", n,
  242. apic->LocalApicNMI.ProcessorId,
  243. polarities[flags & 3], triggerings[(flags >> 2) & 3],
  244. apic->LocalApicNMI.Lint);
  245. break;
  246. }
  247. default:
  248. printf("%d: Unknown APIC type %d\n", n, apic->Type);
  249. break;
  250. }
  251. }
  252. failed:
  253. return status;
  254. }
  255. ACPI_STATUS PrintAcpiDevice(ACPI_HANDLE Device)
  256. {
  257. ACPI_DEVICE_INFO* info = NULL;
  258. ACPI_STATUS status = AcpiGetObjectInfo(Device, &info);
  259. if (ACPI_SUCCESS(status)) {
  260. printf("Device %p type %#x\n", Device, info->Type);
  261. }
  262. //ACPI_FREE(info);
  263. return_ACPI_STATUS(status);
  264. }
  265. static ACPI_STATUS PrintDeviceCallback(ACPI_HANDLE Device, UINT32 Depth, void *Context, void** ReturnValue)
  266. {
  267. return PrintAcpiDevice(Device);
  268. }
  269. // PNP0C0F = PCI Interrupt Link Device
  270. // PNP0A03 = PCI Root Bridge
  271. ACPI_STATUS PrintDevices(void) {
  272. ACPI_STATUS status = AE_OK;
  273. printf("Searching for PNP0A03\n");
  274. status = AcpiGetDevices("PNP0A03", PrintDeviceCallback, NULL, NULL);
  275. CHECK_STATUS("AcpiGetDevices PNP0A03");
  276. printf("Searching for PNP0C0F\n");
  277. status = AcpiGetDevices("PNP0C0F", PrintDeviceCallback, NULL, NULL);
  278. CHECK_STATUS("AcpiGetDevices PNP0C0F");
  279. failed:
  280. return_ACPI_STATUS(status);
  281. }
  282. typedef struct IRQRouteData
  283. {
  284. ACPI_PCI_ID pci;
  285. unsigned pin;
  286. int8_t gsi;
  287. // triggering: 1 = edge triggered, 0 = level
  288. int8_t triggering;
  289. // polarity: 1 = active-low, 0 = active-high
  290. int8_t polarity;
  291. BOOLEAN found;
  292. } IRQRouteData;
  293. static void ResetBuffer(ACPI_BUFFER* buffer) {
  294. ////ACPI_FREE_BUFFER((*buffer));
  295. buffer->Pointer = 0;
  296. buffer->Length = ACPI_ALLOCATE_BUFFER;
  297. }
  298. static ACPI_STATUS RouteIRQLinkDevice(ACPI_HANDLE Device, ACPI_PCI_ROUTING_TABLE* found, IRQRouteData* data) {
  299. ACPI_STATUS status = AE_OK;
  300. ACPI_HANDLE LinkDevice = NULL;
  301. ACPI_BUFFER buffer = {0, NULL};
  302. printf("Routing IRQ Link device %s\n", found->Source);
  303. status = AcpiGetHandle(Device, found->Source, &LinkDevice);
  304. CHECK_STATUS("AcpiGetHandle %s", found->Source);
  305. ResetBuffer(&buffer);
  306. status = AcpiGetCurrentResources(LinkDevice, &buffer);
  307. CHECK_STATUS("AcpiGetCurrentResources");
  308. printf("Got %lu bytes of current resources\n", buffer.Length);
  309. ACPI_RESOURCE* resource = (ACPI_RESOURCE*)buffer.Pointer;
  310. switch (resource->Type) {
  311. case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
  312. // The interrupt count must be 1 when returned from _CRS, supposedly.
  313. // I think the "possible resource setting" may list several.
  314. printf("Extended IRQ: %d interrupts, first one %#x. %s triggered, Active-%s.\n",
  315. resource->Data.ExtendedIrq.InterruptCount,
  316. resource->Data.ExtendedIrq.Interrupts[0],
  317. resource->Data.ExtendedIrq.Triggering ? "Edge" : "Level",
  318. resource->Data.ExtendedIrq.Polarity ? "Low" : "High");
  319. data->gsi = resource->Data.ExtendedIrq.Interrupts[0];
  320. data->triggering = resource->Data.ExtendedIrq.Triggering;
  321. data->polarity = resource->Data.ExtendedIrq.Polarity;
  322. break;
  323. case ACPI_RESOURCE_TYPE_IRQ:
  324. printf("IRQ: %d interrupts, first one %#x.\n",
  325. resource->Data.Irq.InterruptCount,
  326. resource->Data.Irq.Interrupts[0]);
  327. data->gsi = resource->Data.Irq.Interrupts[0];
  328. // PIC interrupts can't be set up for specific polarity and triggering,
  329. // I think.
  330. break;
  331. default:
  332. printf("RouteIRQLinkDevice: unknown resource type %d\n", resource->Type);
  333. status = AE_BAD_DATA;
  334. goto failed;
  335. }
  336. status = AcpiSetCurrentResources(LinkDevice, &buffer);
  337. CHECK_STATUS("AcpiSetCurrentResources");
  338. failed:
  339. //ACPI_FREE_BUFFER(buffer);
  340. return_ACPI_STATUS(status);
  341. }
  342. static ACPI_STATUS RouteIRQCallback(ACPI_HANDLE Device, UINT32 Depth, void *Context, void** ReturnValue)
  343. {
  344. IRQRouteData* data = (IRQRouteData*)Context;
  345. ACPI_STATUS status = AE_OK;
  346. ACPI_RESOURCE* resource = NULL;
  347. ACPI_BUFFER buffer = {0, NULL};
  348. buffer.Length = ACPI_ALLOCATE_BUFFER;
  349. ACPI_PCI_ROUTING_TABLE* found = NULL;
  350. ACPI_DEVICE_INFO* info = NULL;
  351. status = AcpiGetObjectInfo(Device, &info);
  352. CHECK_STATUS("AcpiGetObjectInfo");
  353. if (!(info->Flags & ACPI_PCI_ROOT_BRIDGE)) {
  354. printf("RouteIRQCallback: not a root bridge.\n");
  355. goto failed;
  356. }
  357. printf("RouteIRQ: Root bridge with address %#x:\n", info->Address);
  358. int rootBus = -1;
  359. // Get _CRS, parse, check if the bus number range includes the one in
  360. // data->pci.Bus - then we've found the right *root* PCI bridge.
  361. // Though this might actually be a lot more complicated if we allow for
  362. // multiple root pci bridges.
  363. status = AcpiGetCurrentResources(Device, &buffer);
  364. CHECK_STATUS("AcpiGetCurrentResources");
  365. printf("Got %lu bytes of current resources\n", buffer.Length);
  366. status = AcpiBufferToResource(buffer.Pointer, buffer.Length, &resource);
  367. resource = (ACPI_RESOURCE*)buffer.Pointer;
  368. printf("Got resources %p (status %#x)\n", resource, status);
  369. //CHECK_STATUS();
  370. while (resource->Type != ACPI_RESOURCE_TYPE_END_TAG) {
  371. printf("Got resource type %d\n", resource->Type);
  372. ACPI_RESOURCE_ADDRESS64 addr64;
  373. ACPI_STATUS status = AcpiResourceToAddress64(resource, &addr64);
  374. printf("Processed and got type\n", addr64.ResourceType);
  375. if (status == AE_OK && addr64.ResourceType == ACPI_BUS_NUMBER_RANGE)
  376. {
  377. printf("RouteIRQ: Root bridge bus range %#x..%#x\n",
  378. addr64.Address.Minimum,
  379. addr64.Address.Maximum);
  380. if (data->pci.Bus < addr64.Address.Minimum ||
  381. data->pci.Bus > addr64.Address.Maximum)
  382. {
  383. // This is not the root bridge we're looking for...
  384. goto failed;
  385. }
  386. rootBus = addr64.Address.Minimum;
  387. break;
  388. }
  389. resource = ACPI_NEXT_RESOURCE(resource);
  390. }
  391. // dunno!
  392. if (rootBus == -1)
  393. {
  394. printf("Couldn't figure out the bus number for root bridge %#x\n",
  395. info->Address);
  396. goto failed;
  397. }
  398. // This requires us to walk the chain of pci-pci bridges between the
  399. // root bridge and the device. Unimplemented.
  400. if (rootBus != data->pci.Bus)
  401. {
  402. printf("Unimplemented! Device on bus %#x, but root is %#x\n",
  403. data->pci.Bus, rootBus);
  404. goto failed;
  405. }
  406. ResetBuffer(&buffer);
  407. status = AcpiGetIrqRoutingTable(Device, &buffer);
  408. CHECK_STATUS("AcpiGetIrqRoutingTable");
  409. printf("Got %u bytes of IRQ routing table\n", buffer.Length);
  410. ACPI_PCI_ROUTING_TABLE* route = buffer.Pointer;
  411. ACPI_PCI_ROUTING_TABLE* const end = buffer.Pointer + buffer.Length;
  412. printf("Routing table: %p..%p\n", route, end);
  413. UINT64 pciAddr = data->pci.Device;
  414. while (route < end && route->Length) {
  415. if ((route->Address >> 16) == pciAddr && route->Pin == data->pin) {
  416. found = route;
  417. break;
  418. }
  419. route = (ACPI_PCI_ROUTING_TABLE*)((char*)route + route->Length);
  420. }
  421. if (!found) {
  422. goto failed;
  423. }
  424. printf("RouteIRQ: %02x:%02x.%d pin %d -> %s:%d\n",
  425. data->pci.Bus, data->pci.Device, data->pci.Function,
  426. found->Pin,
  427. found->Source[0] ? found->Source : NULL,
  428. found->SourceIndex);
  429. if (found->Source[0]) {
  430. status = RouteIRQLinkDevice(Device, found, data);
  431. printf("status %#x irq %#x\n", status, data->gsi);
  432. CHECK_STATUS("RouteIRQLinkDevice");
  433. } else {
  434. data->gsi = found->SourceIndex;
  435. }
  436. data->found = TRUE;
  437. status = AE_CTRL_TERMINATE;
  438. failed:
  439. //ACPI_FREE_BUFFER(buffer);
  440. ACPI_FREE(info);
  441. return_ACPI_STATUS(status);
  442. }
  443. ACPI_STATUS RouteIRQ(ACPI_PCI_ID* device, int pin, int* irq) {
  444. IRQRouteData data = { *device, pin, 0, 0, 0, FALSE };
  445. ACPI_STATUS status = AE_OK;
  446. status = AcpiGetDevices("PNP0A03", RouteIRQCallback, &data, NULL);
  447. if (status == AE_OK)
  448. {
  449. if (data.found)
  450. {
  451. *irq = data.gsi
  452. | (data.triggering ? 0x100 : 0)
  453. | (data.polarity ? 0x200 : 0);
  454. }
  455. else
  456. {
  457. status = AE_NOT_FOUND;
  458. }
  459. }
  460. return_ACPI_STATUS(status);
  461. }
  462. #if 0
  463. // reserve some virtual memory space (never touched) to keep track pci device
  464. // handles.
  465. static const char pci_device_handles[65536] PLACEHOLDER_SECTION;
  466. static void MsgFindPci(uintptr_t rcpt, uintptr_t arg)
  467. {
  468. ACPI_PCI_ID temp = { 0, 0, 0, 0 };
  469. u16 vendor = arg >> 16;
  470. u16 device = arg;
  471. uintptr_t addr = -1;
  472. printf("acpica: find pci %#x:%#x.\n", vendor, device);
  473. ACPI_STATUS status = FindPCIDevByVendor(vendor, device, &temp);
  474. if (ACPI_SUCCESS(status)) {
  475. addr = temp.Bus << 16 | temp.Device << 3 | temp.Function;
  476. }
  477. send1(MSG_ACPI_FIND_PCI, rcpt, addr);
  478. }
  479. static void MsgClaimPci(uintptr_t rcpt, uintptr_t addr, uintptr_t pins)
  480. {
  481. addr &= 0xffff;
  482. ACPI_PCI_ID id = { 0, (addr >> 8) & 0xff, (addr >> 3) & 31, addr & 7 };
  483. printf("acpica: claim pci %02x:%02x.%x\n", id.Bus, id.Device, id.Function);
  484. // Set up whatever stuff to track PCI device drivers in general
  485. int irqs[4] = {0};
  486. for (int pin = 0; pin < 4; pin++) {
  487. if (!(pins & (1 << pin))) continue;
  488. ACPI_STATUS status = RouteIRQ(&id, 0, &irqs[pin]);
  489. CHECK_STATUS("RouteIRQ");
  490. printf("acpica: %02x:%02x.%x pin %d routed to IRQ %#x\n",
  491. id.Bus, id.Device, id.Function,
  492. pin, irqs[pin]);
  493. }
  494. if (pins & ACPI_PCI_CLAIM_MASTER) {
  495. u64 value;
  496. AcpiOsReadPciConfiguration(&id, PCI_COMMAND, &value, 16);
  497. if (!(value & PCI_COMMAND_MASTER)) {
  498. value |= PCI_COMMAND_MASTER;
  499. AcpiOsWritePciConfiguration(&id, PCI_COMMAND, value, 16);
  500. }
  501. }
  502. pins = (u64)irqs[3] << 48 | (u64)irqs[2] << 32 | irqs[1] << 16 | irqs[0];
  503. send2(MSG_ACPI_CLAIM_PCI, rcpt, addr, pins);
  504. hmod(rcpt, (uintptr_t)pci_device_handles + addr, 0);
  505. return;
  506. failed:
  507. send2(MSG_ACPI_CLAIM_PCI, rcpt, 0, 0);
  508. }
  509. static size_t debugger_buffer_pos = 0;
  510. static void debugger_pre_cmd(void) {
  511. debugger_buffer_pos = 0;
  512. AcpiGbl_MethodExecuting = FALSE;
  513. AcpiGbl_StepToNextCall = FALSE;
  514. AcpiDbSetOutputDestination(ACPI_DB_CONSOLE_OUTPUT);
  515. }
  516. void GlobalEventHandler(UINT32 EventType, ACPI_HANDLE Device,
  517. UINT32 EventNumber, void *Context) {
  518. if (EventType == ACPI_EVENT_TYPE_FIXED &&
  519. EventNumber == ACPI_EVENT_POWER_BUTTON) {
  520. printf("POWER BUTTON! Shutting down.\n");
  521. AcpiEnterSleepStatePrep(ACPI_STATE_S5);
  522. AcpiEnterSleepState(ACPI_STATE_S5);
  523. }
  524. }
  525. #endif
  526. #if 0
  527. void start() {
  528. ACPI_STATUS status = AE_OK;
  529. printf("ACPICA: start\n");
  530. // NB! Must be at least as large as physical memory - the ACPI tables could
  531. // be anywhere. (Could be handled by AcpiOsMapMemory though.)
  532. map(0, MAP_PHYS | PROT_READ | PROT_WRITE | PROT_NO_CACHE,
  533. (void*)ACPI_PHYS_BASE, 0, USER_MAP_MAX - ACPI_PHYS_BASE);
  534. char* p = ((char*)ACPI_PHYS_BASE) + 0x100000;
  535. printf("Testing physical memory access: %p (0x100000): %x\n", p, *(u32*)p);
  536. __default_section_init();
  537. init_heap();
  538. ACPI_DEBUG_INITIALIZE (); /* For debug version only */
  539. status = InitializeFullAcpi ();
  540. CHECK_STATUS("InitializeFullAcpi");
  541. /* Enable debug output, example debug print */
  542. AcpiDbgLayer = ACPI_EXAMPLE; //ACPI_ALL_COMPONENTS;
  543. AcpiDbgLevel = ACPI_LV_ALL_EXCEPTIONS | ACPI_LV_INTERRUPTS;
  544. int pic_mode = 0; // Default is PIC mode if something fails
  545. status = FindIOAPICs(&pic_mode);
  546. CHECK_STATUS("Find IOAPIC");
  547. status = ExecuteOSI(pic_mode);
  548. CHECK_STATUS("ExecuteOSI");
  549. // Tables we get in Bochs:
  550. // * DSDT: All the AML code
  551. // * FACS
  552. // * FACP
  553. // * APIC (= MADT)
  554. // * SSDT: Secondary System Description Table
  555. // Contains more AML code loaded automatically by ACPICA
  556. // More tables on qemu:
  557. // * Another SSDT (Loaded by ACPICA)
  558. // * HPET table
  559. // PrintFACSTable();
  560. // PrintFACPTable();
  561. PrintAPICTable();
  562. CHECK_STATUS("PrintAPICTable");
  563. // TODO Do something like PrintDevices to disable all pci interrupt link
  564. // devices (call _DIS). Then we'll enable them as we go along.
  565. PrintDevices();
  566. EnumeratePCI();
  567. AcpiWriteBitRegister(ACPI_BITREG_SCI_ENABLE, 1);
  568. //AcpiWriteBitRegister(ACPI_BITREG_POWER_BUTTON_ENABLE, 1);
  569. AcpiInstallGlobalEventHandler(GlobalEventHandler, NULL);
  570. AcpiEnableEvent(ACPI_EVENT_POWER_BUTTON, 0);
  571. printf("Waiting for SCI interrupts...\n");
  572. for (;;) {
  573. uintptr_t rcpt = 0x100;
  574. uintptr_t arg = 0;
  575. uintptr_t arg2 = 0;
  576. uintptr_t msg = recv2(&rcpt, &arg, &arg2);
  577. //printf("acpica: Received %#lx from %#lx: %#lx %#lx\n", msg, rcpt, arg, arg2);
  578. if (msg == MSG_PULSE) {
  579. if (AcpiOsCheckInterrupt(rcpt, arg)) {
  580. continue;
  581. } else {
  582. printf("acpica: Unhandled pulse: %#x from %#lx\n", arg, rcpt);
  583. }
  584. }
  585. switch (msg & 0xff)
  586. {
  587. case MSG_ACPI_FIND_PCI:
  588. MsgFindPci(rcpt, arg);
  589. break;
  590. case MSG_ACPI_CLAIM_PCI:
  591. MsgClaimPci(rcpt, arg, arg2);
  592. break;
  593. // This feels a bit wrong, but as long as we use PIO access to PCI
  594. // configuration space, we need to serialize all accesses.
  595. case MSG_ACPI_READ_PCI:
  596. arg = PciReadWord((arg & 0x7ffffffc) | 0x80000000);
  597. send1(MSG_ACPI_READ_PCI, rcpt, arg);
  598. break;
  599. case MSG_ACPI_DEBUGGER_INIT:
  600. debugger_pre_cmd();
  601. send0(MSG_ACPI_DEBUGGER_INIT, rcpt);
  602. break;
  603. case MSG_ACPI_DEBUGGER_BUFFER:
  604. assert(debugger_buffer_pos < ACPI_DB_LINE_BUFFER_SIZE);
  605. AcpiGbl_DbLineBuf[debugger_buffer_pos++] = arg;
  606. send0(MSG_ACPI_DEBUGGER_BUFFER, rcpt);
  607. break;
  608. case MSG_ACPI_DEBUGGER_CMD:
  609. assert(debugger_buffer_pos < ACPI_DB_LINE_BUFFER_SIZE);
  610. AcpiGbl_DbLineBuf[debugger_buffer_pos++] = 0;
  611. AcpiDbCommandDispatch(AcpiGbl_DbLineBuf, NULL, NULL);
  612. debugger_pre_cmd();
  613. send0(MSG_ACPI_DEBUGGER_CMD, rcpt);
  614. break;
  615. case MSG_ACPI_DEBUGGER_CLR_BUFFER:
  616. debugger_pre_cmd();
  617. send0(MSG_ACPI_DEBUGGER_CLR_BUFFER, rcpt);
  618. break;
  619. case MSG_REG_IRQ:
  620. RegIRQ(rcpt, arg);
  621. continue;
  622. case MSG_IRQ_ACK:
  623. AckIRQ(rcpt);
  624. continue;
  625. }
  626. // TODO Handle other stuff.
  627. if (rcpt == 0x100)
  628. {
  629. hmod(rcpt, 0, 0);
  630. }
  631. }
  632. status = AcpiTerminate();
  633. CHECK_STATUS("AcpiTerminate");
  634. printf("Acpi terminated... Halting.\n");
  635. failed:
  636. printf("ACPI failed :( (status %x)\n", status);
  637. abort();
  638. }
  639. #endif