/* * 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); }