status_t get_irq_routing_table(acpi_handle busDeviceHandle, acpi_data *retBuffer) { ACPI_STATUS status; status = AcpiGetIrqRoutingTable(busDeviceHandle, (ACPI_BUFFER*)retBuffer); if (status == AE_BUFFER_OVERFLOW) dprintf("evaluate_method: the passed buffer is too small!\n"); return status == AE_OK ? B_OK : B_ERROR; }
void enumerateSystemBusses() { auto sb = getChild(ACPI_ROOT_OBJECT, "_SB_"); for(auto child : getChildren(sb)) { auto id = getHardwareId(child); if(id != "PNP0A03" && id != "PNP0A08") continue; frigg::infoLogger() << "thor: Found PCI host bridge" << frigg::endLog; pci::RoutingInfo routing{*kernelAlloc}; acpi::ScopedBuffer buffer; ACPICA_CHECK(AcpiGetIrqRoutingTable(child, buffer.get())); size_t offset = 0; while(true) { auto route = (ACPI_PCI_ROUTING_TABLE *)((char *)buffer.data() + offset); if(!route->Length) break; auto slot = route->Address >> 16; auto function = route->Address & 0xFFFF; assert(function == 0xFFFF); auto index = static_cast<pci::IrqIndex>(route->Pin + 1); if(!*route->Source) { frigg::infoLogger() << " Route for slot " << slot << ", " << nameOf(index) << ": " << "GSI " << route->SourceIndex << frigg::endLog; configureIrq(route->SourceIndex, {TriggerMode::level, Polarity::low}); auto pin = getGlobalSystemIrq(route->SourceIndex); routing.push({slot, index, pin}); }else{ frigg::infoLogger() << " Route for slot " << slot << ", " << nameOf(index) << ": " << (const char *)route->Source << "[" << route->SourceIndex << "]" << frigg::endLog; assert(!route->SourceIndex); auto pin = configureRoute(const_cast<const char *>(route->Source)); routing.push({slot, index, pin}); } offset += route->Length; } pci::pciDiscover(routing); } }
int acpi_pcib_attach(device_t dev, ACPI_BUFFER *prt, int busno) { ACPI_STATUS status; int error; ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); /* * Don't attach if we're not really there. * * XXX: This isn't entirely correct since we may be a PCI bus * on a hot-plug docking station, etc. */ if (!acpi_DeviceIsPresent(dev)) return_VALUE(ENXIO); /* * Get the PCI interrupt routing table for this bus. If we can't * get it, this is not an error but may reduce functionality. There * are several valid bridges in the field that do not have a _PRT, so * only warn about missing tables if bootverbose is set. */ prt->Length = ACPI_ALLOCATE_BUFFER; status = AcpiGetIrqRoutingTable(acpi_get_handle(dev), prt); if (ACPI_FAILURE(status) && (bootverbose || status != AE_NOT_FOUND)) device_printf(dev, "could not get PCI interrupt routing table for %s - %s\n", acpi_name(acpi_get_handle(dev)), AcpiFormatException(status)); /* * Attach the PCI bus proper. */ if (device_add_child(dev, "pci", busno) == NULL) { device_printf(device_get_parent(dev), "couldn't attach pci bus\n"); return_VALUE(ENXIO); } /* * Now go scan the bus. */ prt_walk_table(prt, prt_attach_devices, dev); error = bus_generic_attach(dev); return_VALUE(error); }
static int acpi_get_gsiv(dev_info_t *dip, ACPI_HANDLE pciobj, int devno, int ipin, int *pci_irqp, iflag_t *intr_flagp, acpi_psm_lnk_t *acpipsmlnkp) { ACPI_BUFFER rb; ACPI_PCI_ROUTING_TABLE *prtp; int status; int dev_adr; /* * Get the IRQ routing table */ rb.Pointer = NULL; rb.Length = ACPI_ALLOCATE_BUFFER; if (AcpiGetIrqRoutingTable(pciobj, &rb) != AE_OK) { return (ACPI_PSM_FAILURE); } status = ACPI_PSM_FAILURE; dev_adr = (devno << 16 | 0xffff); for (prtp = rb.Pointer; prtp->Length != 0; prtp = NEXT_PRT_ITEM(prtp)) { /* look until a matching dev/pin is found */ if (dev_adr != prtp->Address || ipin != prtp->Pin) continue; /* NULL Source name means index is GSIV */ if (*prtp->Source == 0) { intr_flagp->intr_el = INTR_EL_LEVEL; intr_flagp->intr_po = INTR_PO_ACTIVE_LOW; ASSERT(pci_irqp != NULL); *pci_irqp = prtp->SourceIndex; status = ACPI_PSM_SUCCESS; } else status = acpi_eval_lnk(dip, prtp->Source, pci_irqp, intr_flagp, acpipsmlnkp); break; } AcpiOsFree(rb.Pointer); return (status); }
int acpi_pcib_attach(device_t dev, ACPI_BUFFER *prt, int busno) { device_t child; ACPI_STATUS status; ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); if (!acpi_DeviceIsPresent(dev)) { /* Caller should already have checked it */ panic("%s device is not present", __func__); } ACPI_SERIAL_INIT(pcib); /* * Get the PCI interrupt routing table for this bus. If we can't * get it, this is not an error but may reduce functionality. There * are several valid bridges in the field that do not have a _PRT, so * only warn about missing tables if bootverbose is set. */ prt->Length = ACPI_ALLOCATE_BUFFER; status = AcpiGetIrqRoutingTable(acpi_get_handle(dev), prt); if (ACPI_FAILURE(status) && (bootverbose || status != AE_NOT_FOUND)) device_printf(dev, "could not get PCI interrupt routing table for %s - %s\n", acpi_name(acpi_get_handle(dev)), AcpiFormatException(status)); /* * Attach the PCI bus proper. */ if ((child = device_add_child(dev, "pci", busno)) == NULL) { device_printf(device_get_parent(dev), "couldn't attach pci bus\n"); return_VALUE(ENXIO); } /* * Now go scan the bus. */ prt_walk_table(prt, prt_attach_devices, dev); return_VALUE (bus_generic_attach(dev)); }
static ACPI_STATUS AcpiDbDeviceResources ( ACPI_HANDLE ObjHandle, UINT32 NestingLevel, void *Context, void **ReturnValue) { ACPI_NAMESPACE_NODE *Node; ACPI_NAMESPACE_NODE *PrtNode = NULL; ACPI_NAMESPACE_NODE *CrsNode = NULL; ACPI_NAMESPACE_NODE *PrsNode = NULL; ACPI_NAMESPACE_NODE *AeiNode = NULL; char *ParentPath; ACPI_BUFFER ReturnObj; ACPI_STATUS Status; Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle); ParentPath = AcpiNsGetExternalPathname (Node); if (!ParentPath) { return (AE_NO_MEMORY); } /* Get handles to the resource methods for this device */ (void) AcpiGetHandle (Node, METHOD_NAME__PRT, ACPI_CAST_PTR (ACPI_HANDLE, &PrtNode)); (void) AcpiGetHandle (Node, METHOD_NAME__CRS, ACPI_CAST_PTR (ACPI_HANDLE, &CrsNode)); (void) AcpiGetHandle (Node, METHOD_NAME__PRS, ACPI_CAST_PTR (ACPI_HANDLE, &PrsNode)); (void) AcpiGetHandle (Node, METHOD_NAME__AEI, ACPI_CAST_PTR (ACPI_HANDLE, &AeiNode)); if (!PrtNode && !CrsNode && !PrsNode && !AeiNode) { goto Cleanup; /* Nothing to do */ } AcpiOsPrintf ("\nDevice: %s\n", ParentPath); /* Prepare for a return object of arbitrary size */ ReturnObj.Pointer = AcpiGbl_DbBuffer; ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE; /* _PRT */ if (PrtNode) { AcpiOsPrintf ("Evaluating _PRT\n"); Status = AcpiEvaluateObject (PrtNode, NULL, NULL, &ReturnObj); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("Could not evaluate _PRT: %s\n", AcpiFormatException (Status)); goto GetCrs; } ReturnObj.Pointer = AcpiGbl_DbBuffer; ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE; Status = AcpiGetIrqRoutingTable (Node, &ReturnObj); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("GetIrqRoutingTable failed: %s\n", AcpiFormatException (Status)); goto GetCrs; } AcpiRsDumpIrqList (ACPI_CAST_PTR (UINT8, AcpiGbl_DbBuffer)); } /* _CRS */ GetCrs: if (CrsNode) { AcpiOsPrintf ("Evaluating _CRS\n"); ReturnObj.Pointer = AcpiGbl_DbBuffer; ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE; Status = AcpiEvaluateObject (CrsNode, NULL, NULL, &ReturnObj); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("Could not evaluate _CRS: %s\n", AcpiFormatException (Status)); goto GetPrs; } /* This code is here to exercise the AcpiWalkResources interface */ Status = AcpiWalkResources (Node, METHOD_NAME__CRS, AcpiDbResourceCallback, NULL); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("AcpiWalkResources failed: %s\n", AcpiFormatException (Status)); goto GetPrs; } /* Get the _CRS resource list */ ReturnObj.Pointer = AcpiGbl_DbBuffer; ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE; Status = AcpiGetCurrentResources (Node, &ReturnObj); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("AcpiGetCurrentResources failed: %s\n", AcpiFormatException (Status)); goto GetPrs; } /* Dump the _CRS resource list */ AcpiRsDumpResourceList (ACPI_CAST_PTR (ACPI_RESOURCE, ReturnObj.Pointer)); /* * Perform comparison of original AML to newly created AML. This tests both * the AML->Resource conversion and the Resource->Aml conversion. */ Status = AcpiDmTestResourceConversion (Node, METHOD_NAME__CRS); /* Execute _SRS with the resource list */ Status = AcpiSetCurrentResources (Node, &ReturnObj); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("AcpiSetCurrentResources failed: %s\n", AcpiFormatException (Status)); goto GetPrs; } } /* _PRS */ GetPrs: if (PrsNode) { AcpiOsPrintf ("Evaluating _PRS\n"); ReturnObj.Pointer = AcpiGbl_DbBuffer; ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE; Status = AcpiEvaluateObject (PrsNode, NULL, NULL, &ReturnObj); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("Could not evaluate _PRS: %s\n", AcpiFormatException (Status)); goto GetAei; } ReturnObj.Pointer = AcpiGbl_DbBuffer; ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE; Status = AcpiGetPossibleResources (Node, &ReturnObj); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("AcpiGetPossibleResources failed: %s\n", AcpiFormatException (Status)); goto GetAei; } AcpiRsDumpResourceList (ACPI_CAST_PTR (ACPI_RESOURCE, AcpiGbl_DbBuffer)); } /* _AEI */ GetAei: if (AeiNode) { AcpiOsPrintf ("Evaluating _AEI\n"); ReturnObj.Pointer = AcpiGbl_DbBuffer; ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE; Status = AcpiEvaluateObject (AeiNode, NULL, NULL, &ReturnObj); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("Could not evaluate _AEI: %s\n", AcpiFormatException (Status)); goto Cleanup; } ReturnObj.Pointer = AcpiGbl_DbBuffer; ReturnObj.Length = ACPI_DEBUG_BUFFER_SIZE; Status = AcpiGetEventResources (Node, &ReturnObj); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("AcpiGetEventResources failed: %s\n", AcpiFormatException (Status)); goto Cleanup; } AcpiRsDumpResourceList (ACPI_CAST_PTR (ACPI_RESOURCE, AcpiGbl_DbBuffer)); } Cleanup: ACPI_FREE (ParentPath); return (AE_OK); }
ACPI_STATUS DisplayOneDevice (ACPI_HANDLE ObjHandle, UINT32 Level, void *Context, void **RetVal) { ACPI_STATUS Status; ACPI_DEVICE_INFO *Info; ACPI_BUFFER Path; ACPI_BUFFER Result; ACPI_OBJECT Obj; char Buffer[256]; uint8 prt_buf[1024]; ACPI_BUFFER Prt = { .Length = sizeof (prt_buf), .Pointer = prt_buf }; ACPI_PCI_ROUTING_TABLE *prtd; uint32 addr=0; uint32 fun = 0; bool pcibus=FALSE; u8 busnum; Path.Length = sizeof (Buffer); Path.Pointer = Buffer; Status = AcpiGetName (ObjHandle, ACPI_FULL_PATHNAME, &Path); if (ACPI_SUCCESS (Status)) { DLOG_COM1 ("%s: \n", Path.Pointer); } Status = AcpiGetObjectInfo (ObjHandle, &Info); if (ACPI_SUCCESS (Status)) { DLOG_COM1 (" "); if (Info->Flags & ACPI_PCI_ROOT_BRIDGE) { DLOG_COM1 (" PCI_ROOT"); busnum = 0; pcibus = TRUE; } if (Info->Valid & ACPI_VALID_STA) DLOG_COM1 (" STA %.8X", Info->CurrentStatus); if (Info->Valid & ACPI_VALID_ADR) { DLOG_COM1 (" ADR %.8X", Info->Address); addr = Info->Address >> 16; fun = Info->Address & 0x7; } if (Info->Valid & ACPI_VALID_HID) DLOG_COM1 (" HID %s", Info->HardwareId.String); if (Info->Valid & ACPI_VALID_UID) DLOG_COM1 (" UID %s", Info->UniqueId.String); if (Info->Valid & ACPI_VALID_CID) DLOG_COM1 (" CID"); ACPI_FREE (Info); } Result.Length = sizeof (Obj); Result.Pointer = &Obj; Status = AcpiEvaluateObjectTyped (ObjHandle, "_DDN", NULL, &Result, ACPI_TYPE_STRING); if (ACPI_SUCCESS (Status)) { DLOG_COM1 (" DDN=%s", Obj.String.Pointer); } Result.Length = sizeof (Obj); Result.Pointer = &Obj; Status = AcpiEvaluateObjectTyped (ObjHandle, "_STR", NULL, &Result, ACPI_TYPE_STRING); if (ACPI_SUCCESS (Status)) { DLOG_COM1 (" STR=%s", Obj.String.Pointer); } Result.Length = sizeof (Obj); Result.Pointer = &Obj; Status = AcpiEvaluateObjectTyped (ObjHandle, "_MLS", NULL, &Result, ACPI_TYPE_STRING); if (ACPI_SUCCESS (Status)) { DLOG_COM1 (" MLS=%s", Obj.String.Pointer); } Status = AcpiEvaluateObjectTyped (ObjHandle, "_BBN", NULL, &Result, ACPI_TYPE_INTEGER); if (ACPI_SUCCESS (Status)) { DLOG_COM1 (" BBN=%d", Obj.Integer.Value); } else if (Status != AE_NOT_FOUND) DLOG_COM1 (" bbnERR=%d", Status); Status = AcpiEvaluateObjectTyped (ObjHandle, "_PXM", NULL, &Result, ACPI_TYPE_INTEGER); if (ACPI_SUCCESS (Status)) { DLOG_COM1 (" PXM=%d", Obj.Integer.Value); } else if (Status != AE_NOT_FOUND) DLOG_COM1 (" pxmERR=%d", Status); DLOG_COM1 ("\n"); for (;;) { Status = AcpiGetIrqRoutingTable (ObjHandle, &Prt); if (ACPI_FAILURE (Status)) { if (Status == AE_BUFFER_OVERFLOW) { DLOG_COM1 ("AcpiGetIrqRoutingTable failed: BUFFER OVERFLOW\n"); } break; } else break; } if (ACPI_SUCCESS (Status)) { int i; /* Check if ObjHandle refers to a non-root PCI bus */ if (READ (0, addr, fun, 0, dword) != 0xFFFFFFFF) { u8 hdrtype = READ (0, addr, fun, 0x0E, byte); if ((hdrtype & 0x7F) == 1) { /* PCI-to-PCI bridge headerType == 1 */ busnum = READ (0, addr, fun, 0x19, byte); //busnum = READ (0, addr, fun, 0x1A, byte); DLOG_COM1 (" bus=0x%.02X\n", busnum); pcibus = TRUE; } } for (i=0;i<sizeof(prt_buf);) { pci_irq_t irq; prtd = (ACPI_PCI_ROUTING_TABLE *)(&prt_buf[i]); if (prtd->Length == 0) break; if (pcibus) { irq.pin = prtd->Pin + 1; /* ACPI numbers pins from 0 */ irq.gsi = 0; } if (prtd->Source[0]) { DLOG_COM1 (" PRT entry: len=%d pin=%d addr=%p srcidx=0x%x src=%s\n", prtd->Length, prtd->Pin, (uint32)prtd->Address, prtd->SourceIndex, &prtd->Source[0]); GetLnkInfo (&prtd->Source[0], &irq); } else { DLOG_COM1 (" PRT entry: len=%d pin=%d addr=%p fixed IRQ=0x%x\n", prtd->Length, prtd->Pin, (uint32)prtd->Address, prtd->SourceIndex); irq.gsi = prtd->SourceIndex; irq.polarity = POLARITY_DEFAULT; irq.trigger = TRIGGER_DEFAULT; } if (pcibus && irq.gsi != 0) pci_irq_register (&irq); i+=prtd->Length; } } #if 0 ACPI_STATUS DisplayResource (ACPI_RESOURCE *Resource, void *Context); DLOG_COM1 (" _PRS:\n"); AcpiWalkResources (ObjHandle, "_PRS", DisplayResource, NULL); DLOG_COM1 (" _CRS:\n"); AcpiWalkResources (ObjHandle, "_CRS", DisplayResource, NULL); #endif return AE_OK; }