b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran/*
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * CDDL HEADER START
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran *
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * The contents of this file are subject to the terms of the
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * Common Development and Distribution License (the "License").
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * You may not use this file except in compliance with the License.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran *
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * or http://www.opensolaris.org/os/licensing.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * See the License for the specific language governing permissions
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * and limitations under the License.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran *
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * When distributing Covered Code, include this CDDL HEADER in each
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * If applicable, add the following below this CDDL HEADER, with the
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * fields enclosed by brackets "[]" replaced with your own identifying
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * information: Portions Copyright [yyyy] [name of copyright owner]
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran *
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * CDDL HEADER END
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran/*
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * Use is subject to license terms.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran/*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Copyright (c) 2009-2010, Intel Corporation.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * All rights reserved.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran#include <sys/types.h>
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran#include <sys/cmn_err.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/note.h>
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran#include <sys/sysmacros.h>
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran#include <sys/sunddi.h>
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran#include <sys/sunndi.h>
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran#include <sys/acpi/acpi.h>
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran#include <sys/acpica.h>
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran#include <sys/acpidev.h>
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran#include <sys/acpidev_impl.h>
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran#include <util/sscanf.h>
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran/* Data structures used to extract the numeric unit address from string _UID. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranstatic acpidev_pseudo_uid_head_t acpidev_uid_heads[ACPIDEV_CLASS_ID_MAX];
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranstatic char *acpidev_uid_formats[] = {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "%u",
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran};
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranstatic char *acpidev_unknown_object_name = "<unknown>";
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranint
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_query_device_status(ACPI_HANDLE hdl)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran int status;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(hdl != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (hdl == NULL) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: hdl is NULL in acpidev_query_device_status().");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (0);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ACPI_FAILURE(acpica_eval_int(hdl, METHOD_NAME__STA, &status))) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /*
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * Set the default value according to ACPI3.0b sec 6.3.7:
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * If a device object (including the processor object) does
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * not have an _STA object, then OSPM assumes that all of the
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * above bits are set (in other words, the device is present,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * enabled, shown in the UI, and functioning).
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran status = 0xF;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (status);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranboolean_t
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_check_device_present(int status)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /*
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * According to ACPI3.0 Spec, if either the ACPI_STA_DEVICE_PRESENT bit
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * or the ACPI_STA_DEVICE_FUNCTIONING bit is set, the device exists.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (status & (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_FUNCTIONING)) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (B_TRUE);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (B_FALSE);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranboolean_t
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_check_device_enabled(int stat)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /*
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * According to ACPI3.0 Spec, if either the ACPI_STA_DEVICE_PRESENT bit
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * or the ACPI_STA_DEVICE_FUNCTIONING bit is set, the device exists.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * Return true if device exists and has been enabled.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if ((stat & (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_FUNCTIONING)) &&
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (stat & ACPI_STA_DEVICE_ENABLED)) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (B_TRUE);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (B_FALSE);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranboolean_t
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_match_device_id(ACPI_DEVICE_INFO *infop, char **ids, int count)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran int i, j;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(infop != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(ids != NULL || count == 0);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Special case to match all devices if count is 0. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (count == 0) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (B_TRUE);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran } else if (infop == NULL || ids == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: invalid parameters in "
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "acpidev_match_device_id().");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (B_FALSE);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Match _HID first. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (infop->Valid & ACPI_VALID_HID) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran for (i = 0; i < count; i++) {
571909175b4f9a1ef15ec4afead6d6d463dbe760Dana Myers if (strncmp(ids[i], infop->HardwareId.String,
571909175b4f9a1ef15ec4afead6d6d463dbe760Dana Myers infop->HardwareId.Length) == 0) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (B_TRUE);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Match _CID next. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (infop->Valid & ACPI_VALID_CID) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran for (i = 0; i < count; i++) {
571909175b4f9a1ef15ec4afead6d6d463dbe760Dana Myers for (j = 0; j < infop->CompatibleIdList.Count; j++) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (strncmp(ids[i],
571909175b4f9a1ef15ec4afead6d6d463dbe760Dana Myers infop->CompatibleIdList.Ids[j].String,
571909175b4f9a1ef15ec4afead6d6d463dbe760Dana Myers infop->CompatibleIdList.Ids[j].Length)
571909175b4f9a1ef15ec4afead6d6d463dbe760Dana Myers == 0) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (B_TRUE);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (B_FALSE);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranstruct acpidev_get_device_arg {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran boolean_t skip_non_exist;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran int id_count;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran char **device_ids;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran void *user_arg;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPI_WALK_CALLBACK user_func;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran};
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranstatic ACPI_STATUS
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_get_device_callback(ACPI_HANDLE hdl, UINT32 level, void *arg,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran void **retval)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPI_STATUS rc;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPI_DEVICE_INFO *infop;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran struct acpidev_get_device_arg *argp;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran argp = (struct acpidev_get_device_arg *)arg;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(argp != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(hdl != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Query object information. */
571909175b4f9a1ef15ec4afead6d6d463dbe760Dana Myers rc = AcpiGetObjectInfo(hdl, &infop);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ACPI_FAILURE(rc)) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran cmn_err(CE_WARN, "!acpidev: failed to get ACPI object info "
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "in acpidev_get_device_callback().");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_CTRL_DEPTH);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /*
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * Skip scanning of children if the device is neither PRESENT nor
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * FUNCTIONING.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * Please refer to ACPI Spec3.0b Sec 6.3.1 and 6.5.1.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (argp->skip_non_exist && (infop->Valid & ACPI_VALID_STA) &&
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran !acpidev_check_device_present(infop->CurrentStatus)) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rc = AE_CTRL_DEPTH;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Call user callback if matched. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran } else if (acpidev_match_device_id(infop, argp->device_ids,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran argp->id_count)) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rc = argp->user_func(hdl, level, argp->user_arg, retval);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran } else {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rc = AE_OK;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Free ACPI object info buffer. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran AcpiOsFree(infop);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (rc);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael CorcoranACPI_STATUS
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_get_device_by_id(ACPI_HANDLE hdl, char **ids, int count,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran int maxdepth, boolean_t skip_non_exist,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPI_WALK_CALLBACK userfunc, void *userarg, void **retval)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPI_STATUS rc;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran struct acpidev_get_device_arg arg;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(userfunc != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (hdl == NULL || userfunc == NULL || (ids == NULL && count != 0)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: invalid parameters "
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "in acpidev_get_device_by_id().");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_BAD_PARAMETER);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Enumerate all descendant objects. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran arg.skip_non_exist = skip_non_exist;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran arg.device_ids = ids;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran arg.id_count = count;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran arg.user_arg = userarg;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran arg.user_func = userfunc;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rc = AcpiWalkNamespace(ACPI_TYPE_DEVICE, hdl, maxdepth,
571909175b4f9a1ef15ec4afead6d6d463dbe760Dana Myers &acpidev_get_device_callback, NULL, &arg, retval);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (rc);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael CorcoranACPI_STATUS
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_walk_apic(ACPI_BUFFER *bufp, ACPI_HANDLE hdl, char *method,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_apic_walker_t func, void *context)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPI_STATUS rc;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ssize_t len;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPI_BUFFER buf;
3b17bf656ccff642e3bb47eab92a32f02dff5e97Michael Corcoran ACPI_OBJECT *obj;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPI_SUBTABLE_HEADER *ap;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPI_TABLE_MADT *mp = NULL;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(func != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (func == NULL) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: invalid parameters for acpidev_walk_apic().");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_BAD_PARAMETER);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran buf.Pointer = NULL;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran buf.Length = ACPI_ALLOCATE_BUFFER;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* A walk buffer was passed in if bufp isn't NULL. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (bufp != NULL) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ap = (ACPI_SUBTABLE_HEADER *)(bufp->Pointer);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran len = bufp->Length;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran } else if (method != NULL) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /*
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * Otherwise, if we have an evaluate method, we get the walk
3b17bf656ccff642e3bb47eab92a32f02dff5e97Michael Corcoran * buffer from a successful invocation of
3b17bf656ccff642e3bb47eab92a32f02dff5e97Michael Corcoran * AcpiEvaluateObjectTyped().
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(hdl != NULL);
3b17bf656ccff642e3bb47eab92a32f02dff5e97Michael Corcoran rc = AcpiEvaluateObjectTyped(hdl, method, NULL, &buf,
3b17bf656ccff642e3bb47eab92a32f02dff5e97Michael Corcoran ACPI_TYPE_BUFFER);
3b17bf656ccff642e3bb47eab92a32f02dff5e97Michael Corcoran if (ACPI_SUCCESS(rc)) {
3b17bf656ccff642e3bb47eab92a32f02dff5e97Michael Corcoran ASSERT(buf.Length >= sizeof (*obj));
3b17bf656ccff642e3bb47eab92a32f02dff5e97Michael Corcoran obj = buf.Pointer;
3b17bf656ccff642e3bb47eab92a32f02dff5e97Michael Corcoran ap = (ACPI_SUBTABLE_HEADER *)obj->Buffer.Pointer;
3b17bf656ccff642e3bb47eab92a32f02dff5e97Michael Corcoran len = obj->Buffer.Length;
3b17bf656ccff642e3bb47eab92a32f02dff5e97Michael Corcoran } else {
3b17bf656ccff642e3bb47eab92a32f02dff5e97Michael Corcoran if (rc != AE_NOT_FOUND)
3b17bf656ccff642e3bb47eab92a32f02dff5e97Michael Corcoran cmn_err(CE_WARN, "!acpidev: failed to evaluate "
3b17bf656ccff642e3bb47eab92a32f02dff5e97Michael Corcoran "%s in acpidev_walk_apic().", method);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (rc);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran } else {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* As a last resort, walk the MADT table. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rc = AcpiGetTable(ACPI_SIG_MADT, 1, (ACPI_TABLE_HEADER **)&mp);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ACPI_FAILURE(rc)) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran cmn_err(CE_WARN, "!acpidev: failed to get MADT table "
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "in acpidev_walk_apic().");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (rc);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ap = (ACPI_SUBTABLE_HEADER *)(mp + 1);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran len = mp->Header.Length - sizeof (*mp);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(len >= 0);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran for (rc = AE_OK; len > 0 && ACPI_SUCCESS(rc); len -= ap->Length,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ap = (ACPI_SUBTABLE_HEADER *)(((char *)ap) + ap->Length)) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(len >= sizeof (ACPI_SUBTABLE_HEADER));
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (len <= sizeof (ACPI_SUBTABLE_HEADER) ||
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ap->Length <= sizeof (ACPI_SUBTABLE_HEADER) ||
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran len < ap->Length) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran cmn_err(CE_WARN,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "!acpidev: invalid APIC entry in MADT/_MAT.");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran break;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rc = (*func)(ap, context);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (buf.Pointer != NULL) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran AcpiOsFree(buf.Pointer);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (rc);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranchar *
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_get_object_name(ACPI_HANDLE hdl)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPI_BUFFER buf;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran char *objname = acpidev_unknown_object_name;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran buf.Length = ACPI_ALLOCATE_BUFFER;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran buf.Pointer = NULL;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ACPI_SUCCESS(AcpiGetName(hdl, ACPI_FULL_PATHNAME, &buf))) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(buf.Pointer != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran objname = (char *)buf.Pointer;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (objname);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranvoid
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_free_object_name(char *objname)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (objname != acpidev_unknown_object_name && objname != NULL) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran AcpiOsFree(objname);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_walk_info_t *
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_alloc_walk_info(acpidev_op_type_t op_type, int lvl, ACPI_HANDLE hdl,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_class_list_t **listpp, acpidev_walk_info_t *pinfop)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_walk_info_t *infop = NULL;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_data_handle_t datap = NULL;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(0 <= lvl && lvl < ACPIDEV_MAX_ENUM_LEVELS);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop = kmem_zalloc(sizeof (*infop), KM_SLEEP);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_op_type = op_type;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_level = lvl;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_parent = pinfop;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_class_list = listpp;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_hdl = hdl;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_name = acpidev_get_object_name(hdl);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Cache ACPI device information. */
571909175b4f9a1ef15ec4afead6d6d463dbe760Dana Myers if (ACPI_FAILURE(AcpiGetObjectInfo(hdl, &infop->awi_info))) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran cmn_err(CE_WARN, "!acpidev: failed to get object info for %s "
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "in acpidev_alloc_walk_info().", infop->awi_name);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_free_object_name(infop->awi_name);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran kmem_free(infop, sizeof (*infop));
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /*
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * Get or create an ACPI object data handle, which will be used to
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * maintain object status information.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if ((datap = acpidev_data_get_handle(hdl)) != NULL) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(datap->aod_hdl == hdl);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(datap->aod_level == lvl);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran } else if ((datap = acpidev_data_create_handle(hdl)) != NULL) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran datap->aod_level = lvl;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran datap->aod_hdl = hdl;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to create object "
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "handle for %s in acpidev_alloc_walk_info().",
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_name);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran AcpiOsFree(infop->awi_info);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_free_object_name(infop->awi_name);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran kmem_free(infop, sizeof (*infop));
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_data = datap;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Sync DEVICE_CREATED flag. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (datap->aod_iflag & ACPIDEV_ODF_DEVINFO_CREATED) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(datap->aod_dip != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(datap->aod_class != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_dip = datap->aod_dip;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_flags |= ACPIDEV_WI_DEVICE_CREATED;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (infop);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranvoid
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_free_walk_info(acpidev_walk_info_t *infop)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /*
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * The ACPI object data handle will only be released when the
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * corresponding object is going to be destroyed.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (infop != NULL) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (infop->awi_info != NULL) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran AcpiOsFree(infop->awi_info);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (infop->awi_name != NULL) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_free_object_name(infop->awi_name);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran kmem_free(infop, sizeof (*infop));
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcorandev_info_t *
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_walk_info_get_pdip(acpidev_walk_info_t *infop)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran while (infop != NULL) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (infop->awi_dip != NULL) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (infop->awi_dip);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop = infop->awi_parent;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran/*
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * Called to release resources when the corresponding object is going
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * to be destroyed.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranstatic void
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_free_object_handler(ACPI_HANDLE hdl, void *data)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu _NOTE(ARGUNUSED(hdl));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_data_handle_t objhdl = data;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (objhdl->aod_class != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu atomic_dec_32(&objhdl->aod_class->adc_refcnt);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objhdl->aod_class = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran kmem_free(objhdl, sizeof (acpidev_data_handle_t));
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_data_handle_t
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_data_get_handle(ACPI_HANDLE hdl)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran void *ptr;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_data_handle_t objhdl = NULL;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_SUCCESS(AcpiGetData(hdl, acpidev_free_object_handler, &ptr))) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran objhdl = (acpidev_data_handle_t)ptr;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (objhdl);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_data_handle_t
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_data_create_handle(ACPI_HANDLE hdl)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_data_handle_t objhdl;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran objhdl = kmem_zalloc(sizeof (*objhdl), KM_SLEEP);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objhdl->aod_bdtype = ACPIDEV_INVALID_BOARD;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objhdl->aod_bdnum = UINT32_MAX;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objhdl->aod_portid = UINT32_MAX;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objhdl->aod_class_id = ACPIDEV_CLASS_ID_INVALID;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(AcpiAttachData(hdl, acpidev_free_object_handler,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (void *)objhdl))) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran cmn_err(CE_WARN,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "!acpidev: failed to attach handle data to object.");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran kmem_free(objhdl, sizeof (*objhdl));
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (objhdl);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranvoid
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_data_destroy_handle(ACPI_HANDLE hdl)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran void *ptr;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_data_handle_t objhdl = NULL;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_SUCCESS(AcpiGetData(hdl, acpidev_free_object_handler, &ptr)) &&
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_SUCCESS(AcpiDetachData(hdl, acpidev_free_object_handler))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objhdl = ptr;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (objhdl->aod_class != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu atomic_dec_32(&objhdl->aod_class->adc_refcnt);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu objhdl->aod_class = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran kmem_free(ptr, sizeof (acpidev_data_handle_t));
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael CorcoranACPI_HANDLE
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_data_get_object(acpidev_data_handle_t hdl)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(hdl != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return ((hdl != NULL) ? hdl->aod_hdl : NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcorandev_info_t *
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_data_get_devinfo(acpidev_data_handle_t hdl)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(hdl != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (hdl == NULL ||
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (hdl->aod_iflag & ACPIDEV_ODF_DEVINFO_CREATED) == 0) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran } else {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(hdl->aod_dip != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (hdl->aod_dip);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranint
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_data_get_status(acpidev_data_handle_t hdl)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(hdl != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (hdl == NULL ||
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (hdl->aod_iflag & ACPIDEV_ODF_STATUS_VALID) == 0) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (0);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran } else {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (hdl->aod_status);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranvoid
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_data_set_flag(acpidev_data_handle_t hdl, uint32_t flag)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(hdl != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu atomic_or_32(&hdl->aod_eflag, flag);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranvoid
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_data_clear_flag(acpidev_data_handle_t hdl, uint32_t flag)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(hdl != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu atomic_and_32(&hdl->aod_eflag, ~flag);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranuint32_t
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_data_get_flag(acpidev_data_handle_t hdl, uint32_t flag)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(hdl != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (hdl->aod_eflag & flag);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuboolean_t
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_data_dr_capable(acpidev_data_handle_t hdl)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(hdl != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (hdl->aod_iflag & ACPIDEV_ODF_HOTPLUG_CAPABLE);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuboolean_t
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_data_dr_ready(acpidev_data_handle_t hdl)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(hdl != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (hdl->aod_iflag & ACPIDEV_ODF_HOTPLUG_READY);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuboolean_t
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_data_dr_failed(acpidev_data_handle_t hdl)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(hdl != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (hdl->aod_iflag & ACPIDEV_ODF_HOTPLUG_FAILED);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranstatic char *
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_generate_pseudo_unitaddr(char *uid, acpidev_class_id_t cid,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran char *buf, size_t len)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_pseudo_uid_t *up, **pp;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(len >= 64);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(cid >= 0 && cid < ACPIDEV_CLASS_ID_MAX);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (cid < 0 || cid >= ACPIDEV_CLASS_ID_MAX) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran mutex_enter(&acpidev_uid_heads[cid].apuh_lock);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran for (pp = &acpidev_uid_heads[cid].apuh_first; *pp != NULL;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran pp = &(*pp)->apu_next) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (strcmp(uid, (*pp)->apu_uid) == 0 &&
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (*pp)->apu_cid == cid) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran break;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* uid doesn't exist, create one and insert it into the list. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (*pp == NULL) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran up = kmem_zalloc(sizeof (*up), KM_SLEEP);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran up->apu_uid = ddi_strdup(uid, KM_SLEEP);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran up->apu_cid = cid;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran up->apu_nid = acpidev_uid_heads[cid].apuh_id++;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran *pp = up;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(*pp != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran mutex_exit(&acpidev_uid_heads[cid].apuh_lock);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /*
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * Generate a special format unit address with three fields to
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * guarantee uniqueness. Normal unit addresses for ACPI devices have
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * either one or two fields.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (snprintf(buf, len, "%u,%u,0", (*pp)->apu_nid, cid) > len) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (buf);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranstatic char *
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_gen_unitaddr(char *uid, char *fmt, char *buf, size_t len)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran size_t i, cnt;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran uint_t id1, id2;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(len >= 64);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (fmt == NULL || strlen(fmt) == 0) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /*
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * Count '%' in format string to protect sscanf().
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * Only support '%u' and '%x', and maximum 2 conversions.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran for (cnt = 0, i = 0; fmt[i] != 0 && cnt <= 2; i++) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (fmt[i] != '%') {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran continue;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran } else if (fmt[i + 1] == 'u' || fmt[i + 1] == 'x') {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Skip next character. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran i++;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran cnt++;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran } else {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Invalid conversion, stop walking. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran cnt = SIZE_MAX;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (cnt != 1 && cnt != 2) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: invalid uid format string '%s'.", fmt);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Scan uid and generate unitaddr. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (sscanf(uid, fmt, &id1, &id2) != cnt) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /*
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * Reverse the order of the two IDs to match the requirements of the
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * hotplug driver.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (cnt == 2 && snprintf(buf, len, "%u,%u", id2, id1) >= len) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: generated unitaddr is too long.");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran } else if (cnt == 1 && snprintf(buf, len, "%u", id1) >= len) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: generated unitaddr is too long.");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (buf);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranchar *
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_generate_unitaddr(char *uid, char **fmts, size_t nfmt,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran char *buf, size_t len)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran size_t i;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran uint_t count = 0;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ulong_t val;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran char **formats = NULL;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran char *rbuf = NULL;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran char *endp = NULL;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(len >= 64);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Use _UID as unit address if it's a decimal integer. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ddi_strtoul(uid, &endp, 10, &val) == 0 &&
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (endp == NULL || *endp == 0)) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (snprintf(buf, len, "%s", uid) >= len) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran } else {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (buf);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* First handle uid format strings from device property. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, ddi_root_node(),
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran DDI_PROP_DONTPASS,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_PROP_NAME_UID_FORMAT, &formats, &count) == DDI_SUCCESS) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Walk through format strings and try to generate unitaddr. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran for (i = 0; i < count && rbuf == NULL; i++) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rbuf = acpidev_gen_unitaddr(uid, formats[i], buf, len);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ddi_prop_free(formats);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Then handle embedded uid format strings. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (fmts != NULL) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran for (i = 0; i < nfmt && rbuf == NULL; i++) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rbuf = acpidev_gen_unitaddr(uid, fmts[i], buf, len);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (rbuf);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran/*
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * The Solaris device "unit-address" property is composed of a comma-delimited
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * list of hexadecimal values. According to the ACPI spec, the ACPI _UID method
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * could return an integer or a string. If it returns an integer, it is used
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * as the unit-address as is. If _UID returns a string, we try to extract some
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * meaningful integers to compose the unit-address property. If we fail to
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * extract any integers, a pseudo-sequential number will be generated for the
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * unit-address.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael CorcoranACPI_STATUS
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_set_unitaddr(acpidev_walk_info_t *infop, char **fmts, size_t nfmt,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran char *unitaddr)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran char unit[64];
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(infop != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(infop->awi_dip != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(infop->awi_info != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (infop == NULL || infop->awi_dip == NULL ||
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_info == NULL) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: invalid parameters in acpidev_set_unitaddr().");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_BAD_PARAMETER);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (infop->awi_info->Valid & ACPI_VALID_UID) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ndi_prop_update_string(DDI_DEV_T_NONE, infop->awi_dip,
571909175b4f9a1ef15ec4afead6d6d463dbe760Dana Myers ACPIDEV_PROP_NAME_ACPI_UID,
571909175b4f9a1ef15ec4afead6d6d463dbe760Dana Myers infop->awi_info->UniqueId.String) != NDI_SUCCESS) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran cmn_err(CE_WARN,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "!acpidev: failed to set UID property for %s.",
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_name);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_ERROR);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (unitaddr == NULL && (infop->awi_info->Valid & ACPI_VALID_UID)) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Try to generate unit address from _UID. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (fmts == NULL) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran fmts = acpidev_uid_formats;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran nfmt = sizeof (acpidev_uid_formats) / sizeof (char *);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran unitaddr = acpidev_generate_unitaddr(
571909175b4f9a1ef15ec4afead6d6d463dbe760Dana Myers infop->awi_info->UniqueId.String, fmts, nfmt,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran unit, sizeof (unit));
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Generate pseudo sequential unit address. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (unitaddr == NULL) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran unitaddr = acpidev_generate_pseudo_unitaddr(
571909175b4f9a1ef15ec4afead6d6d463dbe760Dana Myers infop->awi_info->UniqueId.String,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_class_curr->adc_class_id,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran unit, sizeof (unit));
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (unitaddr == NULL) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran cmn_err(CE_WARN, "!acpidev: failed to generate unit "
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "address from %s.",
571909175b4f9a1ef15ec4afead6d6d463dbe760Dana Myers infop->awi_info->UniqueId.String);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_ERROR);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (unitaddr == NULL) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /*
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * Some ACPI objects may have no _UID method available, so we
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * can't generate the "unit-address" property for them.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * On the other hand, it's legal to support such a device
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * without a unit address, so return success here.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_OK);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ndi_prop_update_string(DDI_DEV_T_NONE, infop->awi_dip,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_PROP_NAME_UNIT_ADDR, unitaddr) != NDI_SUCCESS) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran cmn_err(CE_WARN, "!acpidev: failed to set unitaddr for %s.",
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_name);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_ERROR);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_OK);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael CorcoranACPI_STATUS
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_set_compatible(acpidev_walk_info_t *infop, char **compat, int acount)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran int count, i, j;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran char **compatible = NULL;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPI_DEVICE_INFO *di;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /*
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * Generate compatible list for device based on:
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * * Device HID if available
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * * Device CIDs if available
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * * property array passed in
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(infop != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(infop->awi_dip != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(infop->awi_info != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(compat != NULL || acount == 0);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (infop == NULL || infop->awi_dip == NULL ||
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_info == NULL || (compat == NULL && acount != 0)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: invalid parameters "
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "in acpidev_set_compatible().");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_BAD_PARAMETER);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Compute string count. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran count = acount;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran di = infop->awi_info;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (di->Valid & ACPI_VALID_HID) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran count++;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (di->Valid & ACPI_VALID_CID) {
571909175b4f9a1ef15ec4afead6d6d463dbe760Dana Myers count += di->CompatibleIdList.Count;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran compatible = kmem_zalloc(sizeof (char *) * count, KM_SLEEP);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Generate string array. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran i = 0;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (di->Valid & ACPI_VALID_HID) {
571909175b4f9a1ef15ec4afead6d6d463dbe760Dana Myers compatible[i++] = di->HardwareId.String;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (di->Valid & ACPI_VALID_CID) {
571909175b4f9a1ef15ec4afead6d6d463dbe760Dana Myers for (j = 0; j < di->CompatibleIdList.Count; j++) {
571909175b4f9a1ef15ec4afead6d6d463dbe760Dana Myers compatible[i++] = di->CompatibleIdList.Ids[j].String;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran for (j = 0; j < acount; j++) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran compatible[i++] = compat[j];
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(i == count);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Set "compatible" property. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ndi_prop_update_string_array(DDI_DEV_T_NONE, infop->awi_dip,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran OBP_COMPATIBLE, compatible, count) != NDI_SUCCESS) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran cmn_err(CE_WARN, "!acpidev: failed to set compatible "
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "property for %s in acpidev_set_compatible().",
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_name);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran kmem_free(compatible, count * sizeof (char *));
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_ERROR);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran kmem_free(compatible, count * sizeof (char *));
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_OK);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu/* Evaluate _OST method under object, which is used to support hotplug event. */
a31148363f598def767ac48c5d82e1572e44b935Gerry LiuACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_eval_ost(ACPI_HANDLE hdl, uint32_t code, uint32_t status,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu char *bufp, size_t len)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_STATUS rc;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_OBJECT args[3];
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_OBJECT_LIST arglist;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu args[0].Type = ACPI_TYPE_INTEGER;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu args[0].Integer.Value = code;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu args[1].Type = ACPI_TYPE_INTEGER;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu args[1].Integer.Value = status;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu args[2].Type = ACPI_TYPE_BUFFER;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu args[2].Buffer.Pointer = (UINT8 *)bufp;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu args[2].Buffer.Length = (UINT32)len;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (bufp == NULL || len == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu arglist.Count = 2;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu arglist.Count = 3;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu arglist.Pointer = args;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = AcpiEvaluateObject(hdl, ACPIDEV_METHOD_NAME_OST, &arglist, NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (rc != AE_OK && rc != AE_NOT_FOUND) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to evaluate _OST method, code 0x%x.", rc);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (rc);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry LiuACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_eval_ej0(ACPI_HANDLE hdl)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_STATUS rc;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_OBJECT args[1];
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPI_OBJECT_LIST arglist;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Quotation from ACPI spec 4.0 section 6.3.3.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Arg0 An Integer containing a device ejection control
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * 0 Cancel a mark for ejection request (EJ0 will never be called
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * with this value)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * 1 Hot eject or mark for ejection
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu args[0].Type = ACPI_TYPE_INTEGER;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu args[0].Integer.Value = 1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu arglist.Count = 1;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu arglist.Pointer = args;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = AcpiEvaluateObject(hdl, ACPIDEV_METHOD_NAME_EJ0, &arglist, NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (rc != AE_OK) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to evaluate _EJ0 method, code 0x%x.", rc);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (rc);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry LiuACPI_STATUS
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuacpidev_eval_pxm(ACPI_HANDLE hdl, uint32_t *idp)
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu int pxmid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ASSERT(idp != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Try to evaluate ACPI _PXM method to get proximity doamin id.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Quotation from ACPI4.0:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * If the Local APIC ID / Local SAPIC ID / Local x2APIC ID of a
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * dynamically added processor is not present in the System Resource
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Affinity Table (SRAT), a _PXM object must exist for the processor's
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * device or one of its ancestors in the ACPI Namespace.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu while (hdl != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_SUCCESS(acpica_eval_int(hdl,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_METHOD_NAME_PXM, &pxmid))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *idp = (uint32_t)pxmid;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_OK);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(AcpiGetParent(hdl, &hdl))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu break;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_NOT_FOUND);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu}