ACPI_STATUS AcpiGetVendorResource ( ACPI_HANDLE DeviceHandle, char *Name, ACPI_VENDOR_UUID *Uuid, ACPI_BUFFER *RetBuffer) { ACPI_VENDOR_WALK_INFO Info; ACPI_STATUS Status; /* Other parameters are validated by AcpiWalkResources */ if (!Uuid || !RetBuffer) { return (AE_BAD_PARAMETER); } Info.Uuid = Uuid; Info.Buffer = RetBuffer; Info.Status = AE_NOT_EXIST; /* Walk the _CRS or _PRS resource list for this device */ Status = AcpiWalkResources (DeviceHandle, Name, AcpiRsMatchVendorResource, &Info); if (ACPI_FAILURE (Status)) { return (Status); } return (Info.Status); }
status_t walk_resources(acpi_handle busDeviceHandle, char* method, acpi_walk_resources_callback callback, void* context) { return AcpiWalkResources(busDeviceHandle, method, (ACPI_WALK_RESOURCE_CALLBACK)callback, context); }
void walkResources(ACPI_HANDLE object, const char *method, F functor) { auto fptr = [] (ACPI_RESOURCE *r, void *c) -> ACPI_STATUS { (*static_cast<F *>(c))(r); return AE_OK; }; ACPICA_CHECK(AcpiWalkResources(object, const_cast<char *>(method), fptr, &functor)); }
void GetLnkInfo (char *lnkname, pci_irq_t *irq) { ACPI_HANDLE Handle; ACPI_STATUS Status; Status = AcpiGetHandle (NULL, lnkname, &Handle); if (ACPI_SUCCESS (Status)) { AcpiWalkResources (Handle, "_CRS", GetLnkIrq, (void *) irq); } }
static ACPI_STATUS pci_child_data_callback(ACPI_HANDLE object, uint32_t nesting_level, void* context, void** out_value) { pci_child_auxdata_ctx_t* ctx = (pci_child_auxdata_ctx_t*)context; if ((ctx->i + 1) > ctx->max) { return AE_CTRL_TERMINATE; } auxdata_i2c_device_t* data = ctx->data + ctx->i; data->protocol_id = ZX_PROTOCOL_I2C; ACPI_DEVICE_INFO* info = NULL; ACPI_STATUS acpi_status = AcpiGetObjectInfo(object, &info); if (acpi_status == AE_OK) { // These length fields count the trailing NUL. // Publish HID if ((info->Valid & ACPI_VALID_HID) && info->HardwareId.Length <= HID_LENGTH + 1) { const char* hid = info->HardwareId.String; data->props[data->propcount].id = BIND_ACPI_HID_0_3; data->props[data->propcount++].value = htobe32(*((uint32_t*)(hid))); data->props[data->propcount].id = BIND_ACPI_HID_4_7; data->props[data->propcount++].value = htobe32(*((uint32_t*)(hid + 4))); } // Check for I2C HID devices via CID if ((info->Valid & ACPI_VALID_CID) && info->CompatibleIdList.Count > 0) { ACPI_PNP_DEVICE_ID* cid = &info->CompatibleIdList.Ids[0]; if (cid->Length <= CID_LENGTH + 1) { if (!strncmp(cid->String, I2C_HID_CID_STRING, CID_LENGTH)) { data->props[data->propcount].id = BIND_I2C_CLASS; data->props[data->propcount++].value = I2C_CLASS_HID; } data->props[data->propcount].id = BIND_ACPI_CID_0_3; data->props[data->propcount++].value = htobe32(*((uint32_t*)(cid->String))); data->props[data->propcount].id = BIND_ACPI_CID_4_7; data->props[data->propcount++].value = htobe32(*((uint32_t*)(cid->String + 4))); } } ACPI_FREE(info); } ZX_ASSERT(data->propcount <= AUXDATA_MAX_DEVPROPS); // call _CRS to get i2c info acpi_status = AcpiWalkResources(object, (char*)"_CRS", pci_child_data_resources_callback, ctx); if ((acpi_status == AE_OK) || (acpi_status == AE_CTRL_TERMINATE)) { ctx->i++; } return AE_OK; }
ACPI_STATUS acpi_lookup_irq_resource(device_t dev, int rid, struct resource *res, ACPI_RESOURCE *acpi_res) { struct lookup_irq_request req; ACPI_STATUS status; req.acpi_res = acpi_res; req.res = res; req.counter = 0; req.rid = rid; req.found = 0; status = AcpiWalkResources(acpi_get_handle(dev), "_CRS", acpi_lookup_irq_handler, &req); if (ACPI_SUCCESS(status) && req.found == 0) status = AE_NOT_FOUND; return (status); }
/* * Fetch a device's resources and associate them with the device. * * Note that it might be nice to also locate ACPI-specific resource items, such * as GPE bits. * * We really need to split the resource-fetching code out from the * resource-parsing code, since we may want to use the parsing * code for _PRS someday. */ ACPI_STATUS acpi_parse_resources(device_t dev, ACPI_HANDLE handle, struct acpi_parse_resource_set *set, void *arg) { struct acpi_resource_context arc; ACPI_STATUS status; ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__); set->set_init(dev, arg, &arc.context); arc.set = set; arc.dev = dev; status = AcpiWalkResources(handle, "_CRS", acpi_parse_resource, &arc); if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { printf("can't fetch resources for %s - %s\n", acpi_name(handle), AcpiFormatException(status)); return_ACPI_STATUS (status); } set->set_done(dev, arc.context); return_ACPI_STATUS (AE_OK); }
static int acpi_pci_link_attach(device_t dev) { struct acpi_pci_link_softc *sc; struct link_count_request creq; struct link_res_request rreq; ACPI_STATUS status; int i; sc = device_get_softc(dev); sc->pl_dev = dev; ACPI_SERIAL_BEGIN(pci_link); /* * Count the number of current resources so we know how big of * a link array to allocate. On some systems, _CRS is broken, * so for those systems try to derive the count from _PRS instead. */ creq.in_dpf = DPF_OUTSIDE; creq.count = 0; status = AcpiWalkResources(acpi_get_handle(dev), "_CRS", acpi_count_irq_resources, &creq); sc->pl_crs_bad = ACPI_FAILURE(status); if (sc->pl_crs_bad) { creq.in_dpf = DPF_OUTSIDE; creq.count = 0; status = AcpiWalkResources(acpi_get_handle(dev), "_PRS", acpi_count_irq_resources, &creq); if (ACPI_FAILURE(status)) { device_printf(dev, "Unable to parse _CRS or _PRS: %s\n", AcpiFormatException(status)); ACPI_SERIAL_END(pci_link); return (ENXIO); } } sc->pl_num_links = creq.count; if (creq.count == 0) { ACPI_SERIAL_END(pci_link); return (0); } sc->pl_links = malloc(sizeof(struct link) * sc->pl_num_links, M_PCI_LINK, M_WAITOK | M_ZERO); /* Initialize the child links. */ for (i = 0; i < sc->pl_num_links; i++) { sc->pl_links[i].l_irq = PCI_INVALID_IRQ; sc->pl_links[i].l_bios_irq = PCI_INVALID_IRQ; sc->pl_links[i].l_sc = sc; sc->pl_links[i].l_isa_irq = FALSE; sc->pl_links[i].l_res_index = -1; } /* Try to read the current settings from _CRS if it is valid. */ if (!sc->pl_crs_bad) { rreq.in_dpf = DPF_OUTSIDE; rreq.link_index = 0; rreq.res_index = 0; rreq.sc = sc; status = AcpiWalkResources(acpi_get_handle(dev), "_CRS", link_add_crs, &rreq); if (ACPI_FAILURE(status)) { device_printf(dev, "Unable to parse _CRS: %s\n", AcpiFormatException(status)); goto fail; } } /* * Try to read the possible settings from _PRS. Note that if the * _CRS is toast, we depend on having a working _PRS. However, if * _CRS works, then it is ok for _PRS to be missing. */ rreq.in_dpf = DPF_OUTSIDE; rreq.link_index = 0; rreq.res_index = 0; rreq.sc = sc; status = AcpiWalkResources(acpi_get_handle(dev), "_PRS", link_add_prs, &rreq); if (ACPI_FAILURE(status) && (status != AE_NOT_FOUND || sc->pl_crs_bad)) { device_printf(dev, "Unable to parse _PRS: %s\n", AcpiFormatException(status)); goto fail; } if (bootverbose) acpi_pci_link_dump(sc, 1, "Initial Probe"); /* Verify initial IRQs if we have _PRS. */ if (status != AE_NOT_FOUND) for (i = 0; i < sc->pl_num_links; i++) if (!link_valid_irq(&sc->pl_links[i], sc->pl_links[i].l_irq)) sc->pl_links[i].l_irq = PCI_INVALID_IRQ; if (bootverbose) acpi_pci_link_dump(sc, 0, "Validation"); /* Save initial IRQs. */ for (i = 0; i < sc->pl_num_links; i++) sc->pl_links[i].l_initial_irq = sc->pl_links[i].l_irq; /* * Try to disable this link. If successful, set the current IRQ to * zero and flags to indicate this link is not routed. If we can't * run _DIS (i.e., the method doesn't exist), assume the initial * IRQ was routed by the BIOS. */ if (ACPI_SUCCESS(AcpiEvaluateObject(acpi_get_handle(dev), "_DIS", NULL, NULL))) for (i = 0; i < sc->pl_num_links; i++) sc->pl_links[i].l_irq = PCI_INVALID_IRQ; else for (i = 0; i < sc->pl_num_links; i++) if (PCI_INTERRUPT_VALID(sc->pl_links[i].l_irq)) sc->pl_links[i].l_routed = TRUE; if (bootverbose) acpi_pci_link_dump(sc, 0, "After Disable"); ACPI_SERIAL_END(pci_link); return (0); fail: ACPI_SERIAL_END(pci_link); for (i = 0; i < sc->pl_num_links; i++) if (sc->pl_links[i].l_irqs != NULL) free(sc->pl_links[i].l_irqs, M_PCI_LINK); free(sc->pl_links, M_PCI_LINK); return (ENXIO); }
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; }