110394SMichael.Corcoran@Sun.COM /*
210394SMichael.Corcoran@Sun.COM * CDDL HEADER START
310394SMichael.Corcoran@Sun.COM *
410394SMichael.Corcoran@Sun.COM * The contents of this file are subject to the terms of the
510394SMichael.Corcoran@Sun.COM * Common Development and Distribution License (the "License").
610394SMichael.Corcoran@Sun.COM * You may not use this file except in compliance with the License.
710394SMichael.Corcoran@Sun.COM *
810394SMichael.Corcoran@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910394SMichael.Corcoran@Sun.COM * or http://www.opensolaris.org/os/licensing.
1010394SMichael.Corcoran@Sun.COM * See the License for the specific language governing permissions
1110394SMichael.Corcoran@Sun.COM * and limitations under the License.
1210394SMichael.Corcoran@Sun.COM *
1310394SMichael.Corcoran@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
1410394SMichael.Corcoran@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510394SMichael.Corcoran@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
1610394SMichael.Corcoran@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
1710394SMichael.Corcoran@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
1810394SMichael.Corcoran@Sun.COM *
1910394SMichael.Corcoran@Sun.COM * CDDL HEADER END
2010394SMichael.Corcoran@Sun.COM */
2110394SMichael.Corcoran@Sun.COM /*
22*12004Sjiang.liu@intel.com * Copyright (c) 2009-2010, Intel Corporation.
2310394SMichael.Corcoran@Sun.COM * All rights reserved.
2410394SMichael.Corcoran@Sun.COM */
2510394SMichael.Corcoran@Sun.COM
2610394SMichael.Corcoran@Sun.COM #include <sys/types.h>
2710394SMichael.Corcoran@Sun.COM #include <sys/atomic.h>
2810394SMichael.Corcoran@Sun.COM #include <sys/sunddi.h>
2910394SMichael.Corcoran@Sun.COM #include <sys/sunndi.h>
3010394SMichael.Corcoran@Sun.COM #include <sys/acpi/acpi.h>
3110394SMichael.Corcoran@Sun.COM #include <sys/acpica.h>
3210394SMichael.Corcoran@Sun.COM #include <sys/acpidev.h>
3310394SMichael.Corcoran@Sun.COM #include <sys/acpidev_impl.h>
3410394SMichael.Corcoran@Sun.COM
3510394SMichael.Corcoran@Sun.COM static ACPI_STATUS acpidev_scope_probe(acpidev_walk_info_t *infop);
3610394SMichael.Corcoran@Sun.COM static acpidev_filter_result_t acpidev_scope_filter(acpidev_walk_info_t *infop,
3710394SMichael.Corcoran@Sun.COM char *devname, int maxlen);
3810394SMichael.Corcoran@Sun.COM static ACPI_STATUS acpidev_scope_init(acpidev_walk_info_t *infop);
3910394SMichael.Corcoran@Sun.COM
4010394SMichael.Corcoran@Sun.COM /*
4110394SMichael.Corcoran@Sun.COM * Default class driver for ACPI scope objects.
4210394SMichael.Corcoran@Sun.COM * This class driver is used to handle predefined ACPI SCOPE objects
4310394SMichael.Corcoran@Sun.COM * under the ACPI root object, such as _PR_, _SB_ and _TZ_ etc.
4410394SMichael.Corcoran@Sun.COM * The default policy for ACPI SCOPE objects is SKIP.
4510394SMichael.Corcoran@Sun.COM */
4610394SMichael.Corcoran@Sun.COM acpidev_class_t acpidev_class_scope = {
4710394SMichael.Corcoran@Sun.COM 0, /* adc_refcnt */
4810394SMichael.Corcoran@Sun.COM ACPIDEV_CLASS_REV1, /* adc_version */
4910394SMichael.Corcoran@Sun.COM ACPIDEV_CLASS_ID_SCOPE, /* adc_class_id */
5010394SMichael.Corcoran@Sun.COM "ACPI Scope", /* adc_class_name */
5110394SMichael.Corcoran@Sun.COM ACPIDEV_TYPE_SCOPE, /* adc_dev_type */
5210394SMichael.Corcoran@Sun.COM NULL, /* adc_private */
5310394SMichael.Corcoran@Sun.COM NULL, /* adc_pre_probe */
5410394SMichael.Corcoran@Sun.COM NULL, /* adc_post_probe */
5510394SMichael.Corcoran@Sun.COM acpidev_scope_probe, /* adc_probe */
5610394SMichael.Corcoran@Sun.COM acpidev_scope_filter, /* adc_filter */
5710394SMichael.Corcoran@Sun.COM acpidev_scope_init, /* adc_init */
5810394SMichael.Corcoran@Sun.COM NULL, /* adc_fini */
5910394SMichael.Corcoran@Sun.COM };
6010394SMichael.Corcoran@Sun.COM
6110394SMichael.Corcoran@Sun.COM acpidev_class_list_t *acpidev_class_list_scope = NULL;
6210394SMichael.Corcoran@Sun.COM
6310394SMichael.Corcoran@Sun.COM /*
6410394SMichael.Corcoran@Sun.COM * All SCOPE objects share a global pseudo unit address space across the system.
6510394SMichael.Corcoran@Sun.COM */
6610394SMichael.Corcoran@Sun.COM static uint32_t acpidev_scope_unitaddr = 0;
6710394SMichael.Corcoran@Sun.COM
6810394SMichael.Corcoran@Sun.COM /* Filter rule table for ACPI SCOPE objects. */
6910394SMichael.Corcoran@Sun.COM static acpidev_filter_rule_t acpidev_scope_filters[] = {
7010394SMichael.Corcoran@Sun.COM { /* For safety, _SB_ is hardcoded as DEVICE by acpica */
7110394SMichael.Corcoran@Sun.COM NULL,
7210394SMichael.Corcoran@Sun.COM 0,
7310394SMichael.Corcoran@Sun.COM ACPIDEV_FILTER_DEFAULT,
7410394SMichael.Corcoran@Sun.COM &acpidev_class_list_device,
7510394SMichael.Corcoran@Sun.COM 1,
7610394SMichael.Corcoran@Sun.COM 1,
7710394SMichael.Corcoran@Sun.COM ACPIDEV_OBJECT_NAME_SB,
7810394SMichael.Corcoran@Sun.COM ACPIDEV_NODE_NAME_MODULE_SBD,
7910394SMichael.Corcoran@Sun.COM },
8010394SMichael.Corcoran@Sun.COM { /* Handle _PR_ object. */
8110394SMichael.Corcoran@Sun.COM NULL,
8210394SMichael.Corcoran@Sun.COM 0,
8310394SMichael.Corcoran@Sun.COM ACPIDEV_FILTER_SCAN,
8410394SMichael.Corcoran@Sun.COM &acpidev_class_list_scope,
8510394SMichael.Corcoran@Sun.COM 1,
8610394SMichael.Corcoran@Sun.COM 1,
8710394SMichael.Corcoran@Sun.COM ACPIDEV_OBJECT_NAME_PR,
8810394SMichael.Corcoran@Sun.COM ACPIDEV_NODE_NAME_PROCESSOR,
8910394SMichael.Corcoran@Sun.COM },
9010394SMichael.Corcoran@Sun.COM { /* Ignore all other scope objects. */
9110394SMichael.Corcoran@Sun.COM NULL,
9210394SMichael.Corcoran@Sun.COM 0,
9310394SMichael.Corcoran@Sun.COM ACPIDEV_FILTER_SKIP,
9410394SMichael.Corcoran@Sun.COM NULL,
9510394SMichael.Corcoran@Sun.COM 1,
9610394SMichael.Corcoran@Sun.COM INT_MAX,
9710394SMichael.Corcoran@Sun.COM NULL,
9810394SMichael.Corcoran@Sun.COM NULL,
9910394SMichael.Corcoran@Sun.COM }
10010394SMichael.Corcoran@Sun.COM };
10110394SMichael.Corcoran@Sun.COM
10210394SMichael.Corcoran@Sun.COM static ACPI_STATUS
acpidev_scope_probe(acpidev_walk_info_t * infop)10310394SMichael.Corcoran@Sun.COM acpidev_scope_probe(acpidev_walk_info_t *infop)
10410394SMichael.Corcoran@Sun.COM {
105*12004Sjiang.liu@intel.com ACPI_STATUS rc = AE_OK;
10610394SMichael.Corcoran@Sun.COM int flags;
10710394SMichael.Corcoran@Sun.COM
10810394SMichael.Corcoran@Sun.COM ASSERT(infop != NULL);
10910394SMichael.Corcoran@Sun.COM ASSERT(infop->awi_hdl != NULL);
11010394SMichael.Corcoran@Sun.COM ASSERT(infop->awi_info != NULL);
11110394SMichael.Corcoran@Sun.COM if (infop->awi_info->Type != ACPI_TYPE_LOCAL_SCOPE) {
11210394SMichael.Corcoran@Sun.COM return (AE_OK);
11310394SMichael.Corcoran@Sun.COM }
11410394SMichael.Corcoran@Sun.COM
115*12004Sjiang.liu@intel.com flags = ACPIDEV_PROCESS_FLAG_SCAN;
116*12004Sjiang.liu@intel.com switch (infop->awi_op_type) {
117*12004Sjiang.liu@intel.com case ACPIDEV_OP_BOOT_PROBE:
118*12004Sjiang.liu@intel.com flags |= ACPIDEV_PROCESS_FLAG_CREATE;
119*12004Sjiang.liu@intel.com break;
120*12004Sjiang.liu@intel.com
121*12004Sjiang.liu@intel.com case ACPIDEV_OP_BOOT_REPROBE:
122*12004Sjiang.liu@intel.com break;
123*12004Sjiang.liu@intel.com
124*12004Sjiang.liu@intel.com case ACPIDEV_OP_HOTPLUG_PROBE:
125*12004Sjiang.liu@intel.com flags |= ACPIDEV_PROCESS_FLAG_SYNCSTATUS |
126*12004Sjiang.liu@intel.com ACPIDEV_PROCESS_FLAG_HOLDBRANCH;
127*12004Sjiang.liu@intel.com break;
128*12004Sjiang.liu@intel.com
129*12004Sjiang.liu@intel.com default:
130*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_WARN, "!acpidev: unknown operation type %u "
13110394SMichael.Corcoran@Sun.COM "in acpidev_scope_probe().", infop->awi_op_type);
13210394SMichael.Corcoran@Sun.COM rc = AE_BAD_PARAMETER;
133*12004Sjiang.liu@intel.com break;
134*12004Sjiang.liu@intel.com }
135*12004Sjiang.liu@intel.com
136*12004Sjiang.liu@intel.com if (rc == AE_OK) {
137*12004Sjiang.liu@intel.com rc = acpidev_process_object(infop, flags);
13810394SMichael.Corcoran@Sun.COM }
13910394SMichael.Corcoran@Sun.COM if (ACPI_FAILURE(rc) && rc != AE_NOT_EXIST && rc != AE_ALREADY_EXISTS) {
14010394SMichael.Corcoran@Sun.COM cmn_err(CE_WARN,
14110394SMichael.Corcoran@Sun.COM "!acpidev: failed to process scope object %s.",
14210394SMichael.Corcoran@Sun.COM infop->awi_name);
14310394SMichael.Corcoran@Sun.COM } else {
14410394SMichael.Corcoran@Sun.COM rc = AE_OK;
14510394SMichael.Corcoran@Sun.COM }
14610394SMichael.Corcoran@Sun.COM
14710394SMichael.Corcoran@Sun.COM return (rc);
14810394SMichael.Corcoran@Sun.COM }
14910394SMichael.Corcoran@Sun.COM
15010394SMichael.Corcoran@Sun.COM static acpidev_filter_result_t
acpidev_scope_filter(acpidev_walk_info_t * infop,char * devname,int maxlen)15110394SMichael.Corcoran@Sun.COM acpidev_scope_filter(acpidev_walk_info_t *infop, char *devname, int maxlen)
15210394SMichael.Corcoran@Sun.COM {
15310394SMichael.Corcoran@Sun.COM acpidev_filter_result_t res;
15410394SMichael.Corcoran@Sun.COM
15510394SMichael.Corcoran@Sun.COM ASSERT(infop != NULL);
15610394SMichael.Corcoran@Sun.COM if (infop->awi_op_type == ACPIDEV_OP_BOOT_PROBE ||
15710394SMichael.Corcoran@Sun.COM infop->awi_op_type == ACPIDEV_OP_BOOT_REPROBE ||
15810394SMichael.Corcoran@Sun.COM infop->awi_op_type == ACPIDEV_OP_HOTPLUG_PROBE) {
15910394SMichael.Corcoran@Sun.COM res = acpidev_filter_device(infop, infop->awi_hdl,
16010394SMichael.Corcoran@Sun.COM ACPIDEV_ARRAY_PARAM(acpidev_scope_filters),
16110394SMichael.Corcoran@Sun.COM devname, maxlen);
16210394SMichael.Corcoran@Sun.COM } else {
163*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_WARN, "!acpidev: unknown operation type %u "
16410394SMichael.Corcoran@Sun.COM "in acpidev_scope_filter().", infop->awi_op_type);
16510394SMichael.Corcoran@Sun.COM res = ACPIDEV_FILTER_FAILED;
16610394SMichael.Corcoran@Sun.COM }
16710394SMichael.Corcoran@Sun.COM
16810394SMichael.Corcoran@Sun.COM return (res);
16910394SMichael.Corcoran@Sun.COM }
17010394SMichael.Corcoran@Sun.COM
17110394SMichael.Corcoran@Sun.COM static ACPI_STATUS
acpidev_scope_init(acpidev_walk_info_t * infop)17210394SMichael.Corcoran@Sun.COM acpidev_scope_init(acpidev_walk_info_t *infop)
17310394SMichael.Corcoran@Sun.COM {
17410394SMichael.Corcoran@Sun.COM char unitaddr[32];
17510394SMichael.Corcoran@Sun.COM char *compatible[] = {
17610394SMichael.Corcoran@Sun.COM ACPIDEV_HID_SCOPE,
17710394SMichael.Corcoran@Sun.COM ACPIDEV_TYPE_SCOPE,
17810394SMichael.Corcoran@Sun.COM ACPIDEV_HID_VIRTNEX,
17910394SMichael.Corcoran@Sun.COM ACPIDEV_TYPE_VIRTNEX,
18010394SMichael.Corcoran@Sun.COM };
18110394SMichael.Corcoran@Sun.COM
18210394SMichael.Corcoran@Sun.COM ASSERT(infop != NULL);
18310394SMichael.Corcoran@Sun.COM ASSERT(infop->awi_hdl != NULL);
18410394SMichael.Corcoran@Sun.COM ASSERT(infop->awi_dip != NULL);
18510394SMichael.Corcoran@Sun.COM if (ACPI_FAILURE(acpidev_set_compatible(infop,
18610394SMichael.Corcoran@Sun.COM ACPIDEV_ARRAY_PARAM(compatible)))) {
18710394SMichael.Corcoran@Sun.COM return (AE_ERROR);
18810394SMichael.Corcoran@Sun.COM }
18910394SMichael.Corcoran@Sun.COM (void) snprintf(unitaddr, sizeof (unitaddr), "%u",
19010394SMichael.Corcoran@Sun.COM atomic_inc_32_nv(&acpidev_scope_unitaddr) - 1);
19110394SMichael.Corcoran@Sun.COM if (ACPI_FAILURE(acpidev_set_unitaddr(infop, NULL, 0, unitaddr))) {
19210394SMichael.Corcoran@Sun.COM return (AE_ERROR);
19310394SMichael.Corcoran@Sun.COM }
19410394SMichael.Corcoran@Sun.COM
19510394SMichael.Corcoran@Sun.COM return (AE_OK);
19610394SMichael.Corcoran@Sun.COM }
197