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/*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Copyright (c) 2009-2010, Intel Corporation.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * All rights reserved.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran/*
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * Platform specific device enumerator for ACPI specific devices.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * "x86 system devices" refers to the suite of hardware components which are
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * common to the x86 platform and play important roles in the system
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * architecture but can't be enumerated/discovered through industry-standard
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * bus specifications. Examples of these x86 system devices include:
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * * Logical processor/CPU
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * * Memory device
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * * Non-PCI discoverable IOMMU or DMA Remapping Engine
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * * Non-PCI discoverable IOxAPIC
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * * Non-PCI discoverable HPET (High Precision Event Timer)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * * ACPI defined devices, including power button, sleep button, battery etc.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran *
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * X86 system devices may be discovered through BIOS/Firmware interfaces, such
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * as SMBIOS tables, MPS tables and ACPI tables since their discovery isn't
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * covered by any industry-standard bus specifications.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran *
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * In order to aid Solaris in flexibly managing x86 system devices,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * x86 system devices are placed into a specific firmware device
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * subtree whose device path is '/devices/fw'.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran *
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * This driver populates the firmware device subtree with ACPI-discoverable
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * system devices if possible. To achieve that, the ACPI object
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * namespace is abstracted as ACPI virtual buses which host system devices.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * Another nexus driver for the ACPI virtual bus will manage all devices
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * connected to it.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran *
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * For more detailed information, please refer to PSARC/2009/104.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran#include <sys/types.h>
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran#include <sys/bitmap.h>
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran#include <sys/cmn_err.h>
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran#include <sys/ddi_subrdefs.h>
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran#include <sys/errno.h>
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran#include <sys/modctl.h>
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran#include <sys/mutex.h>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/note.h>
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran#include <sys/obpdefs.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>
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu#include <sys/acpidev_dr.h>
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran#include <sys/acpidev_impl.h>
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran/* Patchable through /etc/system */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranint acpidev_options = 0;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranint acpidev_debug = 0;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
a31148363f598def767ac48c5d82e1572e44b935Gerry Liukrwlock_t acpidev_class_lock;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_class_list_t *acpidev_class_list_root = NULL;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuulong_t acpidev_object_type_mask[BT_BITOUL(ACPI_TYPE_NS_NODE_MAX + 1)];
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran/* ACPI device autoconfig global status */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcorantypedef enum acpidev_status {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_STATUS_FAILED = -2, /* ACPI device autoconfig failed */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_STATUS_DISABLED = -1, /* ACPI device autoconfig disabled */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_STATUS_UNKNOWN = 0, /* initial status */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_STATUS_INITIALIZED, /* ACPI device autoconfig initialized */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_STATUS_FIRST_PASS, /* first probing finished */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_STATUS_READY /* second probing finished */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran} acpidev_status_t;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranstatic acpidev_status_t acpidev_status = ACPIDEV_STATUS_UNKNOWN;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranstatic kmutex_t acpidev_drv_lock;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranstatic dev_info_t *acpidev_root_dip = NULL;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran/* Boot time ACPI device enumerator. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranstatic void acpidev_boot_probe(int type);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran/* DDI module auto configuration interface */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranextern struct mod_ops mod_miscops;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranstatic struct modlmisc modlmisc = {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran &mod_miscops,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "ACPI device enumerator"
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran};
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranstatic struct modlinkage modlinkage = {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran MODREV_1,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (void *)&modlmisc,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran NULL
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran};
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranint
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran_init(void)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran int err;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if ((err = mod_install(&modlinkage)) == 0) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran bzero(acpidev_object_type_mask,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran sizeof (acpidev_object_type_mask));
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran mutex_init(&acpidev_drv_lock, NULL, MUTEX_DRIVER, NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rw_init(&acpidev_class_lock, NULL, RW_DEFAULT, NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_dr_init();
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran impl_bus_add_probe(acpidev_boot_probe);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran } else {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran cmn_err(CE_WARN, "!acpidev: failed to install driver.");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (err);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranint
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran_fini(void)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* No support for module unload. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (EBUSY);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranint
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran_info(struct modinfo *modinfop)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (mod_info(&modlinkage, modinfop));
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran/* Check blacklists and load platform specific driver modules. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranstatic ACPI_STATUS
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_load_plat_modules(void)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_OK);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran/* Unload platform specific driver modules. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranstatic void
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_unload_plat_modules(void)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran/* Unregister all device class drivers from the device driver lists. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranstatic void
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_class_list_fini(void)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_unload_plat_modules();
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((acpidev_options & ACPIDEV_OUSER_NO_PCI) == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (void) acpidev_unregister_class(&acpidev_class_list_scope,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu &acpidev_class_pci);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (void) acpidev_unregister_class(&acpidev_class_list_device,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu &acpidev_class_pci);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if ((acpidev_options & ACPIDEV_OUSER_NO_MEM) == 0) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (void) acpidev_unregister_class(&acpidev_class_list_device,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran &acpidev_class_memory);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (acpidev_options & ACPIDEV_OUSER_NO_CPU) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (void) acpidev_unregister_class(&acpidev_class_list_device,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran &acpidev_class_cpu);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (void) acpidev_unregister_class(&acpidev_class_list_scope,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran &acpidev_class_cpu);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (void) acpidev_unregister_class(&acpidev_class_list_root,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran &acpidev_class_cpu);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if ((acpidev_options & ACPIDEV_OUSER_NO_CONTAINER) == 0) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (void) acpidev_unregister_class(&acpidev_class_list_device,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran &acpidev_class_container);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (void) acpidev_unregister_class(&acpidev_class_list_device,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran &acpidev_class_device);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (void) acpidev_unregister_class(&acpidev_class_list_root,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran &acpidev_class_device);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (void) acpidev_unregister_class(&acpidev_class_list_root,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran &acpidev_class_scope);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran/* Register all device class drivers onto the driver lists. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranstatic ACPI_STATUS
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_class_list_init(uint64_t *fp)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPI_STATUS rc = AE_OK;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Set bit in mask for supported object types. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran BT_SET(acpidev_object_type_mask, ACPI_TYPE_LOCAL_SCOPE);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran BT_SET(acpidev_object_type_mask, ACPI_TYPE_DEVICE);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /*
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * Register the ACPI scope class driver onto the class driver lists.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * Currently only ACPI scope objects under ACPI root node, such as _PR,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * _SB, _TZ etc, need to be handled, so only register the scope class
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * driver onto the root list.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ACPI_FAILURE(acpidev_register_class(&acpidev_class_list_root,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran &acpidev_class_scope, B_FALSE))) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran goto error_out;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /*
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * Register the ACPI device class driver onto the class driver lists.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * The ACPI device class driver should be registered at the tail to
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * handle all device objects which haven't been handled by other
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * HID/CID specific device class drivers.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ACPI_FAILURE(acpidev_register_class(&acpidev_class_list_root,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran &acpidev_class_device, B_TRUE))) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran goto error_root_device;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ACPI_FAILURE(acpidev_register_class(&acpidev_class_list_device,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran &acpidev_class_device, B_TRUE))) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran goto error_device_device;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Check and register support for ACPI container device. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if ((acpidev_options & ACPIDEV_OUSER_NO_CONTAINER) == 0) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ACPI_FAILURE(acpidev_register_class(
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran &acpidev_class_list_device, &acpidev_class_container,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran B_FALSE))) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran goto error_device_container;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran *fp |= ACPI_DEVCFG_CONTAINER;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Check and register support for ACPI CPU device. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if ((acpidev_options & ACPIDEV_OUSER_NO_CPU) == 0) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Handle ACPI CPU Device */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ACPI_FAILURE(acpidev_register_class(
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran &acpidev_class_list_device, &acpidev_class_cpu, B_FALSE))) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran goto error_device_cpu;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Handle ACPI Processor under _PR */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ACPI_FAILURE(acpidev_register_class(
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran &acpidev_class_list_scope, &acpidev_class_cpu, B_FALSE))) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran goto error_scope_cpu;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* House-keeping for CPU scan */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ACPI_FAILURE(acpidev_register_class(
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran &acpidev_class_list_root, &acpidev_class_cpu, B_FALSE))) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran goto error_root_cpu;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran BT_SET(acpidev_object_type_mask, ACPI_TYPE_PROCESSOR);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran *fp |= ACPI_DEVCFG_CPU;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Check support of ACPI memory devices. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if ((acpidev_options & ACPIDEV_OUSER_NO_MEM) == 0) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /*
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * Register the ACPI memory class driver onto the
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * acpidev_class_list_device list because ACPI module
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * class driver uses that list.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ACPI_FAILURE(acpidev_register_class(
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran &acpidev_class_list_device, &acpidev_class_memory,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran B_FALSE))) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran goto error_device_memory;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran *fp |= ACPI_DEVCFG_MEMORY;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Check support of PCI/PCIex Host Bridge devices. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((acpidev_options & ACPIDEV_OUSER_NO_PCI) == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Register pci/pciex class drivers onto
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * the acpidev_class_list_device class list because ACPI
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * module class driver uses that list.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(acpidev_register_class(
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu &acpidev_class_list_device, &acpidev_class_pci,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu B_FALSE))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu goto error_device_pci;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Register pci/pciex class drivers onto the
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * acpidev_class_list_scope class list.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(acpidev_register_class(
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu &acpidev_class_list_scope, &acpidev_class_pci,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu B_FALSE))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu goto error_scope_pci;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu *fp |= ACPI_DEVCFG_PCI;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Check blacklist and load platform specific modules. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rc = acpidev_load_plat_modules();
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ACPI_FAILURE(rc)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to check blacklist "
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "or load pratform modules.");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran goto error_plat;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_OK);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranerror_plat:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((acpidev_options & ACPIDEV_OUSER_NO_PCI) == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (void) acpidev_unregister_class(&acpidev_class_list_scope,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu &acpidev_class_pci);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuerror_scope_pci:
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if ((acpidev_options & ACPIDEV_OUSER_NO_PCI) == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (void) acpidev_unregister_class(&acpidev_class_list_device,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu &acpidev_class_pci);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liuerror_device_pci:
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if ((acpidev_options & ACPIDEV_OUSER_NO_MEM) == 0) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (void) acpidev_unregister_class(&acpidev_class_list_device,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran &acpidev_class_memory);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranerror_device_memory:
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (acpidev_options & ACPIDEV_OUSER_NO_CPU) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (void) acpidev_unregister_class(&acpidev_class_list_root,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran &acpidev_class_cpu);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranerror_root_cpu:
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (acpidev_options & ACPIDEV_OUSER_NO_CPU) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (void) acpidev_unregister_class(&acpidev_class_list_scope,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran &acpidev_class_cpu);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranerror_scope_cpu:
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (acpidev_options & ACPIDEV_OUSER_NO_CPU) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (void) acpidev_unregister_class(&acpidev_class_list_device,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran &acpidev_class_cpu);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranerror_device_cpu:
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if ((acpidev_options & ACPIDEV_OUSER_NO_CONTAINER) == 0) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (void) acpidev_unregister_class(&acpidev_class_list_device,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran &acpidev_class_container);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranerror_device_container:
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (void) acpidev_unregister_class(&acpidev_class_list_device,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran &acpidev_class_device);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranerror_device_device:
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (void) acpidev_unregister_class(&acpidev_class_list_root,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran &acpidev_class_device);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranerror_root_device:
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (void) acpidev_unregister_class(&acpidev_class_list_root,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran &acpidev_class_scope);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranerror_out:
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to register built-in class drivers.");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran *fp = 0;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_ERROR);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran/*
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * Called in single threaded context during boot, no protection for
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * reentrance.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranstatic ACPI_STATUS
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_create_root_node(void)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran int circ, rv = AE_OK;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran dev_info_t *dip = NULL;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_data_handle_t objhdl;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran char *compatibles[] = {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_HID_ROOTNEX,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_TYPE_ROOTNEX,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_HID_VIRTNEX,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_TYPE_VIRTNEX,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran };
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ndi_devi_enter(ddi_root_node(), &circ);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(acpidev_root_dip == NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Query whether device node already exists. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran dip = ddi_find_devinfo(ACPIDEV_NODE_NAME_ROOT, -1, 0);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (dip != NULL && ddi_get_parent(dip) == ddi_root_node()) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ndi_devi_exit(ddi_root_node(), circ);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran cmn_err(CE_WARN, "!acpidev: node /devices/%s already exists, "
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "disable driver.", ACPIDEV_NODE_NAME_ROOT);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_ALREADY_EXISTS);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Create the device node if it doesn't exist. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rv = ndi_devi_alloc(ddi_root_node(), ACPIDEV_NODE_NAME_ROOT,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (pnode_t)DEVI_SID_NODEID, &dip);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (rv != NDI_SUCCESS) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ndi_devi_exit(ddi_root_node(), circ);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to create device node "
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "for ACPI root with errcode %d.", rv);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_ERROR);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Build cross reference between dip and ACPI object. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ACPI_FAILURE(acpica_tag_devinfo(dip, ACPI_ROOT_OBJECT))) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (void) ddi_remove_child(dip, 0);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ndi_devi_exit(ddi_root_node(), circ);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to tag object %s.",
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_OBJECT_NAME_SB);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_ERROR);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Set device properties. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rv = ndi_prop_update_string_array(DDI_DEV_T_NONE, dip,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran OBP_COMPATIBLE, ACPIDEV_ARRAY_PARAM(compatibles));
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (rv == NDI_SUCCESS) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rv = ndi_prop_update_string(DDI_DEV_T_NONE, dip,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran OBP_DEVICETYPE, ACPIDEV_TYPE_ROOTNEX);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (rv != DDI_SUCCESS) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to set device property for /devices/%s.",
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_NODE_NAME_ROOT);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran goto error_out;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Manually create an object handle for the root node */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran objhdl = acpidev_data_create_handle(ACPI_ROOT_OBJECT);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (objhdl == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to create object "
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "handle for the root node.");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran goto error_out;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran objhdl->aod_level = 0;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran objhdl->aod_hdl = ACPI_ROOT_OBJECT;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran objhdl->aod_dip = dip;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran objhdl->aod_class = &acpidev_class_scope;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran objhdl->aod_status = acpidev_query_device_status(ACPI_ROOT_OBJECT);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran objhdl->aod_iflag = ACPIDEV_ODF_STATUS_VALID |
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_ODF_DEVINFO_CREATED | ACPIDEV_ODF_DEVINFO_TAGGED;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Bind device driver. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (void) ndi_devi_bind_driver(dip, 0);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_root_dip = dip;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ndi_devi_exit(ddi_root_node(), circ);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_OK);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranerror_out:
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (void) acpica_untag_devinfo(dip, ACPI_ROOT_OBJECT);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (void) ddi_remove_child(dip, 0);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ndi_devi_exit(ddi_root_node(), circ);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_ERROR);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranstatic void
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_initialize(void)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran int rc;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran char *str = NULL;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran uint64_t features = 0;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Check whether it has already been initialized. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (acpidev_status == ACPIDEV_STATUS_DISABLED) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran cmn_err(CE_CONT, "?acpidev: ACPI device autoconfig "
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "disabled by user.\n");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran } else if (acpidev_status != ACPIDEV_STATUS_UNKNOWN) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_DEBUG(CE_NOTE,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: initialization called more than once.");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Check whether ACPI device autoconfig has been disabled by user. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rc = ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(),
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran DDI_PROP_DONTPASS, "acpidev-autoconfig", &str);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (rc == DDI_SUCCESS) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (strcasecmp(str, "off") == 0 || strcasecmp(str, "no") == 0) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran cmn_err(CE_CONT, "?acpidev: ACPI device autoconfig "
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "disabled by user.\n");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ddi_prop_free(str);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_status = ACPIDEV_STATUS_DISABLED;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ddi_prop_free(str);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Initialize acpica subsystem. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ACPI_FAILURE(acpica_init())) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran cmn_err(CE_WARN,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "!acpidev: failed to initialize acpica subsystem.");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_status = ACPIDEV_STATUS_FAILED;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Check ACPICA subsystem status. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (!acpica_get_core_feature(ACPI_FEATURE_FULL_INIT)) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran cmn_err(CE_WARN, "!acpidev: ACPICA hasn't been fully "
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "initialized, ACPI device autoconfig will be disabled.");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_status = ACPIDEV_STATUS_DISABLED;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Converts acpidev-options from type string to int, if any */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(),
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran DDI_PROP_DONTPASS, "acpidev-options", &str) == DDI_PROP_SUCCESS) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran long data;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rc = ddi_strtol(str, NULL, 0, &data);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (rc == 0) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (void) e_ddi_prop_remove(DDI_DEV_T_NONE,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ddi_root_node(), "acpidev-options");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (void) e_ddi_prop_update_int(DDI_DEV_T_NONE,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ddi_root_node(), "acpidev-options", data);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ddi_prop_free(str);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Get acpidev_options user options. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_options = ddi_prop_get_int(DDI_DEV_T_ANY, ddi_root_node(),
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran DDI_PROP_DONTPASS, "acpidev-options", acpidev_options);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Check whether ACPI based DR has been disabled by user. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = ddi_prop_lookup_string(DDI_DEV_T_ANY, ddi_root_node(),
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu DDI_PROP_DONTPASS, "acpidev-dr", &str);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (rc == DDI_SUCCESS) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (strcasecmp(str, "off") == 0 || strcasecmp(str, "no") == 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmn_err(CE_CONT, "?acpidev: ACPI based DR has been "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "disabled by user.\n");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_dr_enable = 0;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ddi_prop_free(str);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Register all device class drivers. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ACPI_FAILURE(acpidev_class_list_init(&features))) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran cmn_err(CE_WARN,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "!acpidev: failed to initalize class driver lists.");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_status = ACPIDEV_STATUS_FAILED;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Create root node for ACPI/firmware device subtree. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ACPI_FAILURE(acpidev_create_root_node())) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran cmn_err(CE_WARN, "!acpidev: failed to create root node "
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "for acpi device tree.");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_class_list_fini();
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_status = ACPIDEV_STATUS_FAILED;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Notify acpica to enable ACPI device auto configuration. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpica_set_core_feature(ACPI_FEATURE_DEVCFG);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpica_set_devcfg_feature(features);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_DEBUG(CE_NOTE, "!acpidev: ACPI device autoconfig initialized.");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_status = ACPIDEV_STATUS_INITIALIZED;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran/*
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * Probe devices in ACPI namespace which can't be enumerated by other methods
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * at boot time.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranstatic ACPI_STATUS
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_boot_probe_device(acpidev_op_type_t op_type)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPI_STATUS rc = AE_OK;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_walk_info_t *infop;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(acpidev_root_dip != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(op_type == ACPIDEV_OP_BOOT_PROBE ||
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran op_type == ACPIDEV_OP_BOOT_REPROBE);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop = acpidev_alloc_walk_info(op_type, 0, ACPI_ROOT_OBJECT,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran &acpidev_class_list_root, NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (infop == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to allocate walk info "
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "object in acpi_boot_probe_device().");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_ERROR);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Enumerate ACPI devices. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rc = acpidev_probe_child(infop);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ACPI_FAILURE(rc)) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran cmn_err(CE_WARN, "!acpidev: failed to probe child object "
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "under ACPI root node.");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_free_walk_info(infop);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (rc);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran/*
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * Platform specific device prober for ACPI virtual bus.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * It will be called in single-threaded environment to enumerate devices in
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * ACPI namespace at boot time.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranstatic void
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_boot_probe(int type)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPI_STATUS rc;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Initialize subsystem on first pass. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran mutex_enter(&acpidev_drv_lock);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (type == 0) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_initialize();
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (acpidev_status != ACPIDEV_STATUS_INITIALIZED &&
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_status != ACPIDEV_STATUS_DISABLED) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran cmn_err(CE_WARN, "!acpidev: driver disabled due to "
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "initalization failure.");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Probe ACPI devices */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (type == 0 && acpidev_status == ACPIDEV_STATUS_INITIALIZED) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rc = acpidev_boot_probe_device(ACPIDEV_OP_BOOT_PROBE);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ACPI_SUCCESS(rc)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Support of DR operations will be disabled
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * if failed to initialize DR subsystem.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu rc = acpidev_dr_initialize(acpidev_root_dip);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (ACPI_FAILURE(rc) && rc != AE_SUPPORT) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu cmn_err(CE_CONT, "?acpidev: failed to "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "initialize DR subsystem.");
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_status = ACPIDEV_STATUS_FIRST_PASS;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to probe ACPI "
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "devices during boot.");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_status = ACPIDEV_STATUS_FAILED;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran } else if (type != 0 && acpidev_status == ACPIDEV_STATUS_FIRST_PASS) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rc = acpidev_boot_probe_device(ACPIDEV_OP_BOOT_REPROBE);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ACPI_SUCCESS(rc)) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_status = ACPIDEV_STATUS_READY;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to reprobe "
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "ACPI devices during boot.");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_status = ACPIDEV_STATUS_FAILED;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran } else if (acpidev_status != ACPIDEV_STATUS_FAILED &&
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_status != ACPIDEV_STATUS_DISABLED &&
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_status != ACPIDEV_STATUS_READY) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran cmn_err(CE_WARN,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "!acpidev: invalid ACPI device autoconfig global status.");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran mutex_exit(&acpidev_drv_lock);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael CorcoranACPI_STATUS
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_probe_child(acpidev_walk_info_t *infop)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran int circ;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran dev_info_t *pdip;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPI_STATUS res, rc = AE_OK;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPI_HANDLE child;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPI_OBJECT_TYPE type;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_class_list_t *it;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_walk_info_t *cinfop;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_data_handle_t datap;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Validate parameter first. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(infop != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (infop == NULL) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: infop is NULL in acpidev_probe_child().");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_BAD_PARAMETER);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(infop->awi_level < ACPIDEV_MAX_ENUM_LEVELS - 1);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (infop->awi_level >= ACPIDEV_MAX_ENUM_LEVELS - 1) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: recursive level is too deep "
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "in acpidev_probe_child().");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_BAD_PARAMETER);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(infop->awi_class_list != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(infop->awi_hdl != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(infop->awi_info != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(infop->awi_name != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(infop->awi_data != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (infop->awi_class_list == NULL || infop->awi_hdl == NULL ||
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_info == NULL || infop->awi_name == NULL ||
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_data == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: infop has NULL fields in "
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "acpidev_probe_child().");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_BAD_PARAMETER);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran pdip = acpidev_walk_info_get_pdip(infop);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (pdip == NULL) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: pdip is NULL in acpidev_probe_child().");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_BAD_PARAMETER);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ndi_devi_enter(pdip, &circ);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rw_enter(&acpidev_class_lock, RW_READER);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Call pre-probe callback functions. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran for (it = *(infop->awi_class_list); it != NULL; it = it->acl_next) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (it->acl_class->adc_pre_probe == NULL) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran continue;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_class_curr = it->acl_class;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ACPI_FAILURE(it->acl_class->adc_pre_probe(infop))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to pre-probe "
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "device of type %s under %s.",
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran it->acl_class->adc_class_name, infop->awi_name);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Walk child objects. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran child = NULL;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran while (ACPI_SUCCESS(AcpiGetNextObject(ACPI_TYPE_ANY,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_hdl, child, &child))) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Skip object if we're not interested in it. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ACPI_FAILURE(AcpiGetType(child, &type)) ||
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran type > ACPI_TYPE_NS_NODE_MAX ||
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran BT_TEST(acpidev_object_type_mask, type) == 0) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran continue;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* It's another hotplug-capable board, skip it. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (infop->awi_op_type == ACPIDEV_OP_HOTPLUG_PROBE &&
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu acpidev_dr_device_is_board(child)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu continue;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Allocate the walk info structure. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran cinfop = acpidev_alloc_walk_info(infop->awi_op_type,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_level + 1, child, NULL, infop);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (cinfop == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to allocate "
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "walk info child object of %s.",
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_name);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Mark error and continue to handle next child. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rc = AE_ERROR;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran continue;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /*
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * Remember the class list used to handle this object.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * It should be the same list for different passes of scans.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(cinfop->awi_data != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran datap = cinfop->awi_data;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (cinfop->awi_op_type == ACPIDEV_OP_BOOT_PROBE) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran datap->aod_class_list = infop->awi_class_list;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Call registered process callbacks. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran for (it = *(infop->awi_class_list); it != NULL;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran it = it->acl_next) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (it->acl_class->adc_probe == NULL) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran continue;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran cinfop->awi_class_curr = it->acl_class;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran res = it->acl_class->adc_probe(cinfop);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ACPI_FAILURE(res)) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rc = res;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to "
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "process object of type %s under %s.",
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran it->acl_class->adc_class_name,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_name);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Free resources. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_free_walk_info(cinfop);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Call post-probe callback functions. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran for (it = *(infop->awi_class_list); it != NULL; it = it->acl_next) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (it->acl_class->adc_post_probe == NULL) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran continue;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_class_curr = it->acl_class;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ACPI_FAILURE(it->acl_class->adc_post_probe(infop))) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to post-probe "
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "device of type %s under %s.",
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran it->acl_class->adc_class_name, infop->awi_name);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rw_exit(&acpidev_class_lock);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ndi_devi_exit(pdip, circ);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (rc);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael CorcoranACPI_STATUS
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_process_object(acpidev_walk_info_t *infop, int flags)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPI_STATUS rc = AE_OK;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran char *devname;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran dev_info_t *dip, *pdip;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPI_HANDLE hdl;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPI_DEVICE_INFO *adip;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_class_t *clsp;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_data_handle_t datap;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_filter_result_t res;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Validate parameters first. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(infop != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (infop == NULL) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: infop is NULL in acpidev_process_object().");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_BAD_PARAMETER);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(infop->awi_hdl != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(infop->awi_info != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(infop->awi_data != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(infop->awi_class_curr != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(infop->awi_class_curr->adc_filter != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran hdl = infop->awi_hdl;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran adip = infop->awi_info;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran datap = infop->awi_data;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran clsp = infop->awi_class_curr;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (hdl == NULL || datap == NULL || adip == NULL || clsp == NULL ||
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran clsp->adc_filter == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: infop has NULL pointer in "
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "acpidev_process_object().");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_BAD_PARAMETER);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran pdip = acpidev_walk_info_get_pdip(infop);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (pdip == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: failed to get pdip for %s "
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "in acpidev_process_object().", infop->awi_name);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_BAD_PARAMETER);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /*
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * Check whether the object has already been handled.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * Tag and child dip pointer are used to indicate the object has been
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * handled by the ACPI auto configure driver. It has the
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * following usages:
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * 1) Prevent creating dip for objects which already have a dip
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * when reloading the ACPI auto configure driver.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * 2) Prevent creating multiple dips for ACPI objects with ACPI
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * aliases. Currently ACPICA framework has no way to tell whether
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * an object is an alias or not for some types of object. So tag
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * is used to indicate that the object has been handled.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * 3) Prevent multiple class drivers from creating multiple devices for
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * the same ACPI object.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if ((flags & ACPIDEV_PROCESS_FLAG_CREATE) &&
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (flags & ACPIDEV_PROCESS_FLAG_CHECK) &&
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran !(infop->awi_flags & ACPIDEV_WI_DISABLE_CREATE) &&
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (infop->awi_flags & ACPIDEV_WI_DEVICE_CREATED)) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(infop->awi_dip != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_DEBUG(CE_NOTE,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: device has already been created for object %s.",
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_name);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_ALREADY_EXISTS);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /*
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * Determine action according to following rules based on device
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * status returned by _STA method. Please refer to ACPI3.0b section
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * 6.3.1 and 6.5.1.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * present functioning enabled Action
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * 0 0 x Do nothing
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * 1 x 0 Do nothing
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * 1 x 1 Create node and scan child
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * x 1 0 Do nothing
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * x 1 1 Create node and scan child
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if ((datap->aod_iflag & ACPIDEV_ODF_STATUS_VALID) == 0 ||
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (flags & ACPIDEV_PROCESS_FLAG_SYNCSTATUS)) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (adip->Valid & ACPI_VALID_STA) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran datap->aod_status = adip->CurrentStatus;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran } else {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran datap->aod_status = acpidev_query_device_status(hdl);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran datap->aod_iflag |= ACPIDEV_ODF_STATUS_VALID;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (!acpidev_check_device_enabled(datap->aod_status)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_NOTE, "!acpidev: object %s doesn't exist.",
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_name);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Need to scan for hotplug-capable boards even if object
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * doesn't exist or has been disabled during the first pass.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * So just disable creating device node and keep on scanning.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (infop->awi_op_type == ACPIDEV_OP_BOOT_PROBE) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu flags &= ~ACPIDEV_PROCESS_FLAG_CREATE;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu } else {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu return (AE_NOT_EXIST);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(infop->awi_data != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(infop->awi_parent != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(infop->awi_parent->awi_data != NULL);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (flags & ACPIDEV_PROCESS_FLAG_CREATE) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mutex_enter(&(DEVI(pdip)->devi_lock));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /*
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * Put the device into offline state if its parent is in
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu * offline state.
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (DEVI_IS_DEVICE_OFFLINE(pdip)) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu flags |= ACPIDEV_PROCESS_FLAG_OFFLINE;
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu mutex_exit(&(DEVI(pdip)->devi_lock));
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Evaluate filtering rules and generate device name. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran devname = kmem_zalloc(ACPIDEV_MAX_NAMELEN + 1, KM_SLEEP);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (void) memcpy(devname, (char *)&adip->Name, sizeof (adip->Name));
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (flags & ACPIDEV_PROCESS_FLAG_CREATE) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran res = clsp->adc_filter(infop, devname, ACPIDEV_MAX_NAMELEN);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran } else {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran res = clsp->adc_filter(infop, NULL, 0);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Create device if requested. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if ((flags & ACPIDEV_PROCESS_FLAG_CREATE) &&
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran !(infop->awi_flags & ACPIDEV_WI_DISABLE_CREATE) &&
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran !(infop->awi_flags & ACPIDEV_WI_DEVICE_CREATED) &&
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (res == ACPIDEV_FILTER_DEFAULT || res == ACPIDEV_FILTER_CREATE)) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran int ret;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /*
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * Allocate dip and set default properties.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran * Properties can be overriden in class specific init routines.
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(infop->awi_dip == NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ndi_devi_alloc_sleep(pdip, devname, (pnode_t)DEVI_SID_NODEID,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran &dip);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_dip = dip;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ret = ndi_prop_update_string(DDI_DEV_T_NONE, dip,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran OBP_DEVICETYPE, clsp->adc_dev_type);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ret != NDI_SUCCESS) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to set device property for %s.",
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_name);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (void) ddi_remove_child(dip, 0);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_dip = NULL;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran kmem_free(devname, ACPIDEV_MAX_NAMELEN + 1);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_ERROR);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Build cross reference between dip and ACPI object. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if ((flags & ACPIDEV_PROCESS_FLAG_NOTAG) == 0 &&
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPI_FAILURE(acpica_tag_devinfo(dip, hdl))) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran cmn_err(CE_WARN,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "!acpidev: failed to tag object %s.",
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_name);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (void) ddi_remove_child(dip, 0);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_dip = NULL;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran kmem_free(devname, ACPIDEV_MAX_NAMELEN + 1);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_ERROR);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Call class specific initialization callback. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (clsp->adc_init != NULL &&
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPI_FAILURE(clsp->adc_init(infop))) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to initialize device %s.",
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_name);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if ((flags & ACPIDEV_PROCESS_FLAG_NOTAG) == 0) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (void) acpica_untag_devinfo(dip, hdl);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (void) ddi_remove_child(dip, 0);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_dip = NULL;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran kmem_free(devname, ACPIDEV_MAX_NAMELEN + 1);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_ERROR);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Set device into offline state if requested. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (flags & ACPIDEV_PROCESS_FLAG_OFFLINE) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran mutex_enter(&(DEVI(dip)->devi_lock));
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran DEVI_SET_DEVICE_OFFLINE(dip);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran mutex_exit(&(DEVI(dip)->devi_lock));
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Mark status */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_flags |= ACPIDEV_WI_DEVICE_CREATED;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran datap->aod_iflag |= ACPIDEV_ODF_DEVINFO_CREATED;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran datap->aod_dip = dip;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran datap->aod_class = clsp;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Hold reference count on class driver. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran atomic_inc_32(&clsp->adc_refcnt);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if ((flags & ACPIDEV_PROCESS_FLAG_NOTAG) == 0) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran datap->aod_iflag |= ACPIDEV_ODF_DEVINFO_TAGGED;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Bind device driver. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if ((flags & ACPIDEV_PROCESS_FLAG_NOBIND) != 0) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran mutex_enter(&(DEVI(dip)->devi_lock));
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran DEVI(dip)->devi_flags |= DEVI_NO_BIND;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran mutex_exit(&(DEVI(dip)->devi_lock));
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran } else {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (void) ndi_devi_bind_driver(dip, 0);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu /* Hold reference on branch when hot-adding devices. */
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu if (flags & ACPIDEV_PROCESS_FLAG_HOLDBRANCH) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu e_ddi_branch_hold(dip);
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Free resources */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran kmem_free(devname, ACPIDEV_MAX_NAMELEN + 1);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rc = AE_OK;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Recursively scan child objects if requested. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran switch (res) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran case ACPIDEV_FILTER_DEFAULT:
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* FALLTHROUGH */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran case ACPIDEV_FILTER_SCAN:
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Check if we need to scan child. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if ((flags & ACPIDEV_PROCESS_FLAG_SCAN) &&
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran !(infop->awi_flags & ACPIDEV_WI_DISABLE_SCAN) &&
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran !(infop->awi_flags & ACPIDEV_WI_CHILD_SCANNED)) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* probe child object. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rc = acpidev_probe_child(infop);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ACPI_FAILURE(rc)) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to probe subtree of %s.",
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_name);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rc = AE_ERROR;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Mark object as scanned. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_flags |= ACPIDEV_WI_CHILD_SCANNED;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran break;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran case ACPIDEV_FILTER_CREATE:
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* FALLTHROUGH */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran case ACPIDEV_FILTER_CONTINUE:
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* FALLTHROUGH */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran case ACPIDEV_FILTER_SKIP:
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran break;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran case ACPIDEV_FILTER_FAILED:
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: failed to probe device for %s.",
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_name);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rc = AE_ERROR;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran break;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran default:
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran cmn_err(CE_WARN,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "!acpidev: unknown filter result code %d.", res);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rc = AE_ERROR;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran break;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (rc);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_filter_result_t
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_filter_default(acpidev_walk_info_t *infop, ACPI_HANDLE hdl,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_filter_rule_t *afrp, char *devname, int len)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu _NOTE(ARGUNUSED(hdl));
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(afrp != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(devname == NULL || len >= ACPIDEV_MAX_NAMELEN);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (infop->awi_level < afrp->adf_minlvl ||
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_level > afrp->adf_maxlvl) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (ACPIDEV_FILTER_CONTINUE);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran } else if (afrp->adf_pattern != NULL &&
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran strncmp(afrp->adf_pattern,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (char *)&infop->awi_info->Name,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran sizeof (infop->awi_info->Name))) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (ACPIDEV_FILTER_CONTINUE);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (afrp->adf_replace != NULL && devname != NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu (void) strlcpy(devname, afrp->adf_replace, len);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (afrp->adf_retcode);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_filter_result_t
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_filter_device(acpidev_walk_info_t *infop, ACPI_HANDLE hdl,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_filter_rule_t *afrp, int entries, char *devname, int len)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_filter_result_t res;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Evaluate filtering rules. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran for (; entries > 0; entries--, afrp++) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (afrp->adf_filter_func != NULL) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran res = afrp->adf_filter_func(infop, hdl, afrp,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran devname, len);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran } else {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran res = acpidev_filter_default(infop, hdl, afrp,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran devname, len);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (res == ACPIDEV_FILTER_DEFAULT ||
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran res == ACPIDEV_FILTER_SCAN) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran infop->awi_class_list = afrp->adf_class_list;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran break;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (res);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcorandev_info_t *
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_root_node(void)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (acpidev_root_dip);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael CorcoranACPI_STATUS
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_register_class(acpidev_class_list_t **listpp, acpidev_class_t *clsp,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran boolean_t tail)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPI_STATUS rc;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_class_list_t *item;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_class_list_t *temp;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(clsp != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(listpp != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (listpp == NULL || clsp == NULL) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPIDEV_DEBUG(CE_WARN,
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu "!acpidev: invalid parameter in acpidev_register_class().");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_BAD_PARAMETER);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran } else if (clsp->adc_version != ACPIDEV_CLASS_REV) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran cmn_err(CE_WARN,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "!acpidev: class driver %s version mismatch.",
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran clsp->adc_class_name);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_BAD_DATA);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rc = AE_OK;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran item = kmem_zalloc(sizeof (*item), KM_SLEEP);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran item->acl_class = clsp;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rw_enter(&acpidev_class_lock, RW_WRITER);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran /* Check for duplicated item. */
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran for (temp = *listpp; temp != NULL; temp = temp->acl_next) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (temp->acl_class == clsp) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran cmn_err(CE_WARN,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "!acpidev: register duplicate class driver %s.",
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran clsp->adc_class_name);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rc = AE_ALREADY_EXISTS;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran break;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ACPI_SUCCESS(rc)) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (tail) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran while (*listpp) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran listpp = &(*listpp)->acl_next;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran item->acl_next = *listpp;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran *listpp = item;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rw_exit(&acpidev_class_lock);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (ACPI_FAILURE(rc)) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran kmem_free(item, sizeof (*item));
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (rc);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael CorcoranACPI_STATUS
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoranacpidev_unregister_class(acpidev_class_list_t **listpp,
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_class_t *clsp)
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran{
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ACPI_STATUS rc = AE_NOT_FOUND;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran acpidev_class_list_t *temp;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(clsp != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran ASSERT(listpp != NULL);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (listpp == NULL || clsp == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: invalid parameter "
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "in acpidev_unregister_class().");
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (AE_BAD_PARAMETER);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rw_enter(&acpidev_class_lock, RW_WRITER);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran for (temp = NULL; *listpp; listpp = &(*listpp)->acl_next) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if ((*listpp)->acl_class == clsp) {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran temp = *listpp;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran *listpp = (*listpp)->acl_next;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran break;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran if (temp == NULL) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: class %p(%s) doesn't exist "
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "in acpidev_unregister_class().",
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (void *)clsp, clsp->adc_class_name);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rc = AE_NOT_FOUND;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran } else if (temp->acl_class->adc_refcnt != 0) {
a31148363f598def767ac48c5d82e1572e44b935Gerry Liu ACPIDEV_DEBUG(CE_WARN, "!acpidev: class %p(%s) is still in use "
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran "in acpidev_unregister_class()..",
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran (void *)clsp, clsp->adc_class_name);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rc = AE_ERROR;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran } else {
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran kmem_free(temp, sizeof (*temp));
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rc = AE_OK;
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran }
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran rw_exit(&acpidev_class_lock);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran return (rc);
b72d5b75fd6f5bb08d29f65652d60058fc3a2608Michael Corcoran}