--- /dev/null Fri Jun 26 08:09:30 2009 +++ new/usr/src/uts/i86pc/io/acpi/acpidev/acpidev_device.c Fri Jun 26 08:09:29 2009 @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2009, Intel Corporation. + * All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static ACPI_STATUS acpidev_device_probe(acpidev_walk_info_t *infop); +static acpidev_filter_result_t acpidev_device_filter(acpidev_walk_info_t *infop, + char *devname, int maxlen); +static ACPI_STATUS acpidev_device_init(acpidev_walk_info_t *infop); + +/* + * Default class driver for ACPI DEVICE object. + * The default policy for DEVICE object is scanning child objects without + * creating device node. But some special DEVICE objects will have device + * node created for them. + */ +acpidev_class_t acpidev_class_device = { + 0, /* adc_refcnt */ + ACPIDEV_CLASS_REV1, /* adc_version */ + ACPIDEV_CLASS_ID_DEVICE, /* adc_class_id */ + "ACPI Device", /* adc_class_name */ + ACPIDEV_TYPE_DEVICE, /* adc_dev_type */ + NULL, /* adc_private */ + NULL, /* adc_pre_probe */ + NULL, /* adc_post_probe */ + acpidev_device_probe, /* adc_probe */ + acpidev_device_filter, /* adc_filter */ + acpidev_device_init, /* adc_init */ + NULL, /* adc_fini */ +}; + +/* + * List head of class drivers which will be called in order when handling + * children of ACPI DEVICE object. + */ +acpidev_class_list_t *acpidev_class_list_device = NULL; + +/* Filter rule table for boot. */ +static acpidev_filter_rule_t acpidev_device_filters[] = { + { /* _SB_ object type is hardcoded to DEVICE by acpica */ + NULL, + 0, + ACPIDEV_FILTER_SCAN, + &acpidev_class_list_device, + 1, + 1, + ACPIDEV_OBJECT_NAME_SB, + NULL, + }, + { /* Ignore other device objects under ACPI root object */ + NULL, + 0, + ACPIDEV_FILTER_SKIP, + NULL, + 1, + 1, + NULL, + NULL, + }, + { /* Scan other device objects not directly under ACPI root */ + NULL, + 0, + ACPIDEV_FILTER_SCAN, + &acpidev_class_list_device, + 2, + INT_MAX, + NULL, + NULL, + } +}; + +static ACPI_STATUS +acpidev_device_probe(acpidev_walk_info_t *infop) +{ + ACPI_STATUS rc; + int flags; + + ASSERT(infop != NULL); + ASSERT(infop->awi_hdl != NULL); + ASSERT(infop->awi_info != NULL); + + if (infop->awi_info->Type != ACPI_TYPE_DEVICE) { + return (AE_OK); + } + + if (infop->awi_op_type == ACPIDEV_OP_BOOT_PROBE) { + flags = ACPIDEV_PROCESS_FLAG_SCAN | ACPIDEV_PROCESS_FLAG_CREATE; + rc = acpidev_process_object(infop, flags); + } else if (infop->awi_op_type == ACPIDEV_OP_BOOT_REPROBE) { + flags = ACPIDEV_PROCESS_FLAG_SCAN; + rc = acpidev_process_object(infop, flags); + } else if (infop->awi_op_type == ACPIDEV_OP_HOTPLUG_PROBE) { + flags = ACPIDEV_PROCESS_FLAG_SCAN | ACPIDEV_PROCESS_FLAG_CREATE; + rc = acpidev_process_object(infop, flags); + } else { + ACPIDEV_DEBUG(CE_WARN, + "acpidev: unknown operation type %u in device_probe().", + infop->awi_op_type); + rc = AE_BAD_PARAMETER; + } + if (ACPI_FAILURE(rc) && rc != AE_NOT_EXIST && rc != AE_ALREADY_EXISTS) { + cmn_err(CE_CONT, + "?acpidev: failed to process device object %s.\n", + infop->awi_name); + } else { + rc = AE_OK; + } + + return (rc); +} + +static acpidev_filter_result_t +acpidev_device_filter(acpidev_walk_info_t *infop, char *devname, int maxlen) +{ + acpidev_filter_result_t res; + + ASSERT(infop != NULL); + if (infop->awi_op_type == ACPIDEV_OP_BOOT_PROBE || + infop->awi_op_type == ACPIDEV_OP_BOOT_REPROBE || + infop->awi_op_type == ACPIDEV_OP_HOTPLUG_PROBE) { + res = acpidev_filter_device(infop, infop->awi_hdl, + ACPIDEV_ARRAY_PARAM(acpidev_device_filters), + devname, maxlen); + } else { + ACPIDEV_DEBUG(CE_WARN, + "acpidev: unknown operation type %u in device_filter().", + infop->awi_op_type); + res = ACPIDEV_FILTER_FAILED; + } + + return (res); +} + +/*ARGSUSED*/ +static ACPI_STATUS +acpidev_device_init(acpidev_walk_info_t *infop) +{ + char *compatibles[] = { + ACPIDEV_TYPE_DEVICE, + ACPIDEV_HID_VIRTNEX, + ACPIDEV_TYPE_VIRTNEX, + }; + + if (ACPI_FAILURE(acpidev_set_compatibles(infop, + ACPIDEV_ARRAY_PARAM(compatibles)))) { + return (AE_ERROR); + } + if (ACPI_FAILURE(acpidev_set_unitaddr(infop, NULL, 0, NULL))) { + return (AE_ERROR); + } + + return (AE_OK); +}