예제 #1
0
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;
}
예제 #2
0
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;
}
예제 #3
0
/*
 * 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);
}
예제 #4
0
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;
	}
}
예제 #5
0
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);
}
예제 #6
0
/*
 * 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);
}