/// <summary> /// Called as callback when a root device is found /// </summary> /// <param name="Object">The object</param> /// <param name="NestingLevel">Nesting level</param> /// <param name="Context">User context</param> /// <param name="ReturnValue">Return value if early returned</param> /// <returns>Status</returns> private static int onRootDevice(void *Object, uint NestingLevel, void *Context, void **ReturnValue) { // Get routing table AcpiObjects.Buffer buffer; buffer.Length = Acpica.ACPI_ALLOCATE_BUFFER; int status = Acpica.AcpiGetIrqRoutingTable(Object, &buffer); if (status != Acpica.AE_OK) { Panic.DoPanic("[PCI] Couldn't get ACPI IRQ Routing Table"); } // The last entry will have Length 0 Acpica.PCIRoutingTable *table = (Acpica.PCIRoutingTable *)buffer.Pointer; while (table->Length > 0) { // No reference source if (table->Source[0] == 0) { uint slot = (uint)(table->Address >> 16); addIRQ(slot, table->Pin, table->SourceIndex, 0, 0); } // Source is not null, that means we need to lookup the reference resource else { void *handle = null; status = Acpica.AcpiGetHandle(Object, Util.CharPtrToString(table->Source), &handle); if (status != Acpica.AE_OK) { Panic.DoPanic("[PCI] Couldn't load references handle"); } status = Acpica.AcpiWalkResources(handle, Acpica.METHOD_NAME__CRS, onIRQResource, table); if (status != Acpica.AE_OK) { Panic.DoPanic("[PCI] Couldn't process resources for IRQ"); } } // Next entry table = (Acpica.PCIRoutingTable *)((byte *)table + table->Length); } // The object returned should be freed by us Acpica.AcpiOsFree(buffer.Pointer); return(Acpica.AE_OK); }
/// <summary> /// Handles IRQ resources /// </summary> /// <param name="Resource">The resource</param> /// <param name="Context">User context</param> /// <returns>Status</returns> private static int onIRQResource(AcpiObjects.Resource *Resource, void *Context) { Acpica.PCIRoutingTable *table = (Acpica.PCIRoutingTable *)Context; uint slot = (uint)(table->Address >> 16); if (Resource->Type == AcpiObjects.ResourceType.IRQ) { AcpiObjects.ResourceIRQ *irq = (AcpiObjects.ResourceIRQ *)((byte *)Resource + sizeof(AcpiObjects.Resource)); byte *interrupts = (byte *)irq + sizeof(AcpiObjects.ResourceIRQ); addIRQ(slot, table->Pin, interrupts[table->SourceIndex], irq->Polarity, irq->Trigger); } else if (Resource->Type == AcpiObjects.ResourceType.EXTENDED_IRQ) { AcpiObjects.ResourceExtendedIRQ *irq = (AcpiObjects.ResourceExtendedIRQ *)((byte *)Resource + sizeof(AcpiObjects.Resource)); uint *interrupts = (uint *)((byte *)irq + sizeof(AcpiObjects.ResourceExtendedIRQ)); addIRQ(slot, table->Pin, interrupts[table->SourceIndex], irq->Polarity, irq->Trigger); } return(Acpica.AE_OK); }