status_t get_next_entry(uint32 objectType, const char *base, char *result, size_t length, void **counter) { ACPI_HANDLE parent, child, newChild; ACPI_BUFFER buffer; ACPI_STATUS status; TRACE("get_next_entry %ld, %s\n", objectType, base); if (base == NULL || !strcmp(base, "\\")) { parent = ACPI_ROOT_OBJECT; } else { status = AcpiGetHandle(NULL, (ACPI_STRING)base, &parent); if (status != AE_OK) return B_ENTRY_NOT_FOUND; } child = *counter; status = AcpiGetNextObject(objectType, parent, child, &newChild); if (status != AE_OK) return B_ENTRY_NOT_FOUND; *counter = newChild; buffer.Length = length; buffer.Pointer = result; status = AcpiGetName(newChild, ACPI_FULL_PATHNAME, &buffer); if (status != AE_OK) return B_NO_MEMORY; /* Corresponds to AE_BUFFER_OVERFLOW */ return B_OK; }
status_t get_next_object(uint32 objectType, acpi_handle parent, acpi_handle* currentChild) { acpi_handle child = *currentChild; return AcpiGetNextObject(objectType, parent, child, currentChild) == AE_OK ? B_OK : B_ERROR; }
/* * Intialize hot plug control for ACPI mode. */ static int pciehpc_acpi_hpc_init(pcie_hp_ctrl_t *ctrl_p) { ACPI_HANDLE pcibus_obj; int status = AE_ERROR; ACPI_HANDLE slot_dev_obj; ACPI_HANDLE hdl; pciehpc_acpi_t *acpi_p; uint16_t bus_methods = 0; uint16_t slot_methods = 0; /* get the ACPI object for the bus node */ status = acpica_get_handle(ctrl_p->hc_dip, &pcibus_obj); if (status != AE_OK) return (DDI_FAILURE); /* get the ACPI object handle for the child node */ status = AcpiGetNextObject(ACPI_TYPE_DEVICE, pcibus_obj, NULL, &slot_dev_obj); if (status != AE_OK) return (DDI_FAILURE); /* * gather the info about the ACPI methods present on the bus node * and the child nodes. */ if (AcpiGetHandle(pcibus_obj, "_OSC", &hdl) == AE_OK) bus_methods |= PCIEHPC_ACPI_OSC_PRESENT; if (AcpiGetHandle(pcibus_obj, "_OSHP", &hdl) == AE_OK) bus_methods |= PCIEHPC_ACPI_OSHP_PRESENT; if (AcpiGetHandle(pcibus_obj, "_HPX", &hdl) == AE_OK) bus_methods |= PCIEHPC_ACPI_HPX_PRESENT; if (AcpiGetHandle(pcibus_obj, "_HPP", &hdl) == AE_OK) bus_methods |= PCIEHPC_ACPI_HPP_PRESENT; if (AcpiGetHandle(pcibus_obj, "_DSM", &hdl) == AE_OK) bus_methods |= PCIEHPC_ACPI_DSM_PRESENT; if (AcpiGetHandle(slot_dev_obj, "_SUN", &hdl) == AE_OK) slot_methods |= PCIEHPC_ACPI_SUN_PRESENT; if (AcpiGetHandle(slot_dev_obj, "_PS0", &hdl) == AE_OK) slot_methods |= PCIEHPC_ACPI_PS0_PRESENT; if (AcpiGetHandle(slot_dev_obj, "_EJ0", &hdl) == AE_OK) slot_methods |= PCIEHPC_ACPI_EJ0_PRESENT; if (AcpiGetHandle(slot_dev_obj, "_STA", &hdl) == AE_OK) slot_methods |= PCIEHPC_ACPI_STA_PRESENT; /* save ACPI object handles, etc. */ acpi_p = kmem_zalloc(sizeof (pciehpc_acpi_t), KM_SLEEP); acpi_p->bus_obj = pcibus_obj; acpi_p->slot_dev_obj = slot_dev_obj; acpi_p->bus_methods = bus_methods; acpi_p->slot_methods = slot_methods; ctrl_p->hc_misc_data = acpi_p; return (DDI_SUCCESS); }
bool hasChild(ACPI_HANDLE parent, const char *path) { ACPI_HANDLE child = nullptr; while(true) { ACPI_STATUS status = AcpiGetNextObject(ACPI_TYPE_ANY, parent, child, &child); if(status == AE_NOT_FOUND) return false; ACPICA_CHECK(status); acpi::ScopedBuffer buffer; ACPICA_CHECK(AcpiGetName(child, ACPI_SINGLE_NAME, buffer.get())); if(!strcmp(static_cast<char *>(buffer.data()), path)) return true; } }
static ACPI_STATUS AcpiNsDeleteSubtree ( ACPI_HANDLE StartHandle) { ACPI_STATUS Status; ACPI_HANDLE ChildHandle; ACPI_HANDLE ParentHandle; ACPI_HANDLE NextChildHandle; ACPI_HANDLE Dummy; UINT32 Level; ACPI_FUNCTION_TRACE (NsDeleteSubtree); ParentHandle = StartHandle; ChildHandle = NULL; Level = 1; /* * Traverse the tree of objects until we bubble back up * to where we started. */ while (Level > 0) { /* Attempt to get the next object in this scope */ Status = AcpiGetNextObject (ACPI_TYPE_ANY, ParentHandle, ChildHandle, &NextChildHandle); ChildHandle = NextChildHandle; /* Did we get a new object? */ if (ACPI_SUCCESS (Status)) { /* Check if this object has any children */ if (ACPI_SUCCESS (AcpiGetNextObject (ACPI_TYPE_ANY, ChildHandle, NULL, &Dummy))) { /* * There is at least one child of this object, * visit the object */ Level++; ParentHandle = ChildHandle; ChildHandle = NULL; } } else { /* * No more children in this object, go back up to * the object's parent */ Level--; /* Delete all children now */ AcpiNsDeleteChildren (ChildHandle); ChildHandle = ParentHandle; Status = AcpiGetParent (ParentHandle, &ParentHandle); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } } /* Now delete the starting object, and we are done */ AcpiNsDeleteNode (ChildHandle); return_ACPI_STATUS (AE_OK); }
/* * Install/uninstall ACPI system event handler for child objects of hdl. * Return DDI_SUCCESS on success, and DDI_FAILURE on failure. */ static int acpinex_event_walk(boolean_t init, acpinex_softstate_t *sp, ACPI_HANDLE hdl) { int rc; int retval = DDI_SUCCESS; dev_info_t *dip; ACPI_HANDLE child = NULL; ACPI_OBJECT_TYPE type; ACPI_DEVICE_INFO *infop; acpidev_data_handle_t dhdl; /* Walk all child objects. */ ASSERT(hdl != NULL); while (ACPI_SUCCESS(AcpiGetNextObject(ACPI_TYPE_ANY, hdl, child, &child))) { /* Skip unwanted object types. */ if (ACPI_FAILURE(AcpiGetType(child, &type)) || type > ACPI_TYPE_NS_NODE_MAX || BT_TEST(acpinex_object_type_mask, type) == 0) { continue; } /* Get data associated with the object. Skip it if fails. */ dhdl = acpidev_data_get_handle(child); if (dhdl == NULL) { ACPINEX_DEBUG(CE_NOTE, "!acpinex: failed to get data " "associated with %p, skip.", child); continue; } /* Query ACPI object info for the object. */ if (ACPI_FAILURE(AcpiGetObjectInfo(child, &infop))) { cmn_err(CE_WARN, "!acpidnex: failed to get object info for %p.", child); continue; } if (init) { rc = acpinex_event_install_handler(child, sp, infop, dhdl); if (rc != DDI_SUCCESS) { ACPINEX_DEBUG(CE_WARN, "!acpinex: failed to " "install handler for child %p of %s.", child, sp->ans_path); retval = DDI_FAILURE; /* * Try to handle descendants if both of the * following two conditions are true: * 1) Device corresponding to the current object is * enabled. If the device is absent/disabled, * no notification should be generated from * descendant objects of it. * 2) No Solaris device node has been created for the * current object yet. If the device node has been * created for the current object, notification * events from child objects should be handled by * the corresponding driver. */ } else if (acpidev_check_device_enabled( acpidev_data_get_status(dhdl)) && ACPI_FAILURE(acpica_get_devinfo(child, &dip))) { rc = acpinex_event_walk(B_TRUE, sp, child); if (rc != DDI_SUCCESS) { ACPINEX_DEBUG(CE_WARN, "!acpinex: failed to install " "handler for descendants of %s.", sp->ans_path); retval = DDI_FAILURE; } } } else { rc = DDI_SUCCESS; /* Uninstall handler for descendants if needed. */ if (ACPI_FAILURE(acpica_get_devinfo(child, &dip))) { rc = acpinex_event_walk(B_FALSE, sp, child); } if (rc == DDI_SUCCESS) { rc = acpinex_event_uninstall_handler(child, infop, dhdl); } /* Undo will be done by caller in case of failure. */ if (rc != DDI_SUCCESS) { ACPINEX_DEBUG(CE_WARN, "!acpinex: failed to " "uninstall handler for descendants of %s.", sp->ans_path); AcpiOsFree(infop); retval = DDI_FAILURE; break; } } /* Release cached resources. */ AcpiOsFree(infop); } return (retval); }