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_rsc.h>
34*12004Sjiang.liu@intel.com #include <sys/acpidev_dr.h>
3510394SMichael.Corcoran@Sun.COM #include <sys/acpidev_impl.h>
3610394SMichael.Corcoran@Sun.COM
3710394SMichael.Corcoran@Sun.COM static ACPI_STATUS acpidev_memory_probe(acpidev_walk_info_t *infop);
3810394SMichael.Corcoran@Sun.COM static acpidev_filter_result_t acpidev_memory_filter(
3910394SMichael.Corcoran@Sun.COM acpidev_walk_info_t *infop, char *devname, int maxlen);
4010394SMichael.Corcoran@Sun.COM static ACPI_STATUS acpidev_memory_init(acpidev_walk_info_t *infop);
4110394SMichael.Corcoran@Sun.COM
4210394SMichael.Corcoran@Sun.COM /*
4310394SMichael.Corcoran@Sun.COM * Default class driver for ACPI memory objects.
4410394SMichael.Corcoran@Sun.COM */
4510394SMichael.Corcoran@Sun.COM acpidev_class_t acpidev_class_memory = {
4610394SMichael.Corcoran@Sun.COM 0, /* adc_refcnt */
4710394SMichael.Corcoran@Sun.COM ACPIDEV_CLASS_REV1, /* adc_version */
4810394SMichael.Corcoran@Sun.COM ACPIDEV_CLASS_ID_MEMORY, /* adc_class_id */
4910394SMichael.Corcoran@Sun.COM "ACPI memory", /* adc_class_name */
5010394SMichael.Corcoran@Sun.COM ACPIDEV_TYPE_MEMORY, /* adc_dev_type */
5110394SMichael.Corcoran@Sun.COM NULL, /* adc_private */
5210394SMichael.Corcoran@Sun.COM NULL, /* adc_pre_probe */
5310394SMichael.Corcoran@Sun.COM NULL, /* adc_post_probe */
5410394SMichael.Corcoran@Sun.COM acpidev_memory_probe, /* adc_probe */
5510394SMichael.Corcoran@Sun.COM acpidev_memory_filter, /* adc_filter */
5610394SMichael.Corcoran@Sun.COM acpidev_memory_init, /* adc_init */
5710394SMichael.Corcoran@Sun.COM NULL, /* adc_fini */
5810394SMichael.Corcoran@Sun.COM };
5910394SMichael.Corcoran@Sun.COM
6010394SMichael.Corcoran@Sun.COM /*
6110394SMichael.Corcoran@Sun.COM * List of class drivers which will be called in order when handling
6210394SMichael.Corcoran@Sun.COM * children of ACPI memory objects.
6310394SMichael.Corcoran@Sun.COM */
6410394SMichael.Corcoran@Sun.COM acpidev_class_list_t *acpidev_class_list_memory = NULL;
6510394SMichael.Corcoran@Sun.COM
6610394SMichael.Corcoran@Sun.COM static char *acpidev_memory_device_ids[] = {
6710394SMichael.Corcoran@Sun.COM ACPIDEV_HID_MEMORY,
6810394SMichael.Corcoran@Sun.COM };
6910394SMichael.Corcoran@Sun.COM
7010394SMichael.Corcoran@Sun.COM static char *acpidev_memory_uid_formats[] = {
7110394SMichael.Corcoran@Sun.COM "MEM%x-%x",
7210394SMichael.Corcoran@Sun.COM };
7310394SMichael.Corcoran@Sun.COM
7410394SMichael.Corcoran@Sun.COM /* Filter rule table for memory objects. */
7510394SMichael.Corcoran@Sun.COM static acpidev_filter_rule_t acpidev_memory_filters[] = {
7610394SMichael.Corcoran@Sun.COM { /* Ignore all memory objects under the ACPI root object */
7710394SMichael.Corcoran@Sun.COM NULL,
7810394SMichael.Corcoran@Sun.COM 0,
7910394SMichael.Corcoran@Sun.COM ACPIDEV_FILTER_SKIP,
8010394SMichael.Corcoran@Sun.COM NULL,
8110394SMichael.Corcoran@Sun.COM 1,
8210394SMichael.Corcoran@Sun.COM 1,
8310394SMichael.Corcoran@Sun.COM NULL,
8410394SMichael.Corcoran@Sun.COM NULL,
8510394SMichael.Corcoran@Sun.COM },
8610394SMichael.Corcoran@Sun.COM { /* Create node and scan child for all other memory objects */
8710394SMichael.Corcoran@Sun.COM NULL,
8810394SMichael.Corcoran@Sun.COM 0,
8910394SMichael.Corcoran@Sun.COM ACPIDEV_FILTER_DEFAULT,
9010394SMichael.Corcoran@Sun.COM &acpidev_class_list_device,
9110394SMichael.Corcoran@Sun.COM 2,
9210394SMichael.Corcoran@Sun.COM INT_MAX,
9310394SMichael.Corcoran@Sun.COM NULL,
9410394SMichael.Corcoran@Sun.COM ACPIDEV_NODE_NAME_MEMORY,
9510394SMichael.Corcoran@Sun.COM }
9610394SMichael.Corcoran@Sun.COM };
9710394SMichael.Corcoran@Sun.COM
9810394SMichael.Corcoran@Sun.COM static ACPI_STATUS
acpidev_memory_probe(acpidev_walk_info_t * infop)9910394SMichael.Corcoran@Sun.COM acpidev_memory_probe(acpidev_walk_info_t *infop)
10010394SMichael.Corcoran@Sun.COM {
101*12004Sjiang.liu@intel.com ACPI_STATUS rc = AE_OK;
10210394SMichael.Corcoran@Sun.COM int flags;
10310394SMichael.Corcoran@Sun.COM
10410394SMichael.Corcoran@Sun.COM ASSERT(infop != NULL);
10510394SMichael.Corcoran@Sun.COM ASSERT(infop->awi_hdl != NULL);
10610394SMichael.Corcoran@Sun.COM ASSERT(infop->awi_info != NULL);
10710394SMichael.Corcoran@Sun.COM if (infop->awi_info->Type != ACPI_TYPE_DEVICE ||
10810394SMichael.Corcoran@Sun.COM acpidev_match_device_id(infop->awi_info,
10910394SMichael.Corcoran@Sun.COM ACPIDEV_ARRAY_PARAM(acpidev_memory_device_ids)) == 0) {
11010394SMichael.Corcoran@Sun.COM return (AE_OK);
11110394SMichael.Corcoran@Sun.COM }
11210394SMichael.Corcoran@Sun.COM
113*12004Sjiang.liu@intel.com flags = ACPIDEV_PROCESS_FLAG_SCAN;
114*12004Sjiang.liu@intel.com switch (infop->awi_op_type) {
115*12004Sjiang.liu@intel.com case ACPIDEV_OP_BOOT_PROBE:
116*12004Sjiang.liu@intel.com if (acpica_get_devcfg_feature(ACPI_DEVCFG_MEMORY)) {
117*12004Sjiang.liu@intel.com flags |= ACPIDEV_PROCESS_FLAG_CREATE;
118*12004Sjiang.liu@intel.com acpidev_dr_check(infop);
119*12004Sjiang.liu@intel.com }
120*12004Sjiang.liu@intel.com break;
121*12004Sjiang.liu@intel.com
122*12004Sjiang.liu@intel.com case ACPIDEV_OP_BOOT_REPROBE:
123*12004Sjiang.liu@intel.com break;
124*12004Sjiang.liu@intel.com
125*12004Sjiang.liu@intel.com case ACPIDEV_OP_HOTPLUG_PROBE:
126*12004Sjiang.liu@intel.com if (acpica_get_devcfg_feature(ACPI_DEVCFG_MEMORY)) {
127*12004Sjiang.liu@intel.com flags |= ACPIDEV_PROCESS_FLAG_CREATE |
128*12004Sjiang.liu@intel.com ACPIDEV_PROCESS_FLAG_SYNCSTATUS |
129*12004Sjiang.liu@intel.com ACPIDEV_PROCESS_FLAG_HOLDBRANCH;
130*12004Sjiang.liu@intel.com }
131*12004Sjiang.liu@intel.com break;
132*12004Sjiang.liu@intel.com
133*12004Sjiang.liu@intel.com default:
134*12004Sjiang.liu@intel.com ACPIDEV_DEBUG(CE_WARN, "!acpidev: unknown operation type %u "
13510394SMichael.Corcoran@Sun.COM "in acpidev_memory_probe.", infop->awi_op_type);
13610394SMichael.Corcoran@Sun.COM rc = AE_BAD_PARAMETER;
137*12004Sjiang.liu@intel.com break;
138*12004Sjiang.liu@intel.com }
139*12004Sjiang.liu@intel.com
140*12004Sjiang.liu@intel.com if (rc == AE_OK) {
141*12004Sjiang.liu@intel.com rc = acpidev_process_object(infop, flags);
14210394SMichael.Corcoran@Sun.COM }
14310394SMichael.Corcoran@Sun.COM if (ACPI_FAILURE(rc) && rc != AE_NOT_EXIST && rc != AE_ALREADY_EXISTS) {
14410394SMichael.Corcoran@Sun.COM cmn_err(CE_WARN,
14510394SMichael.Corcoran@Sun.COM "!acpidev: failed to process memory object %s.",
14610394SMichael.Corcoran@Sun.COM infop->awi_name);
14710394SMichael.Corcoran@Sun.COM } else {
14810394SMichael.Corcoran@Sun.COM rc = AE_OK;
14910394SMichael.Corcoran@Sun.COM }
15010394SMichael.Corcoran@Sun.COM
15110394SMichael.Corcoran@Sun.COM return (rc);
15210394SMichael.Corcoran@Sun.COM }
15310394SMichael.Corcoran@Sun.COM
15410394SMichael.Corcoran@Sun.COM static acpidev_filter_result_t
acpidev_memory_filter(acpidev_walk_info_t * infop,char * devname,int maxlen)15510394SMichael.Corcoran@Sun.COM acpidev_memory_filter(acpidev_walk_info_t *infop, char *devname, int maxlen)
15610394SMichael.Corcoran@Sun.COM {
15710394SMichael.Corcoran@Sun.COM acpidev_filter_result_t res;
15810394SMichael.Corcoran@Sun.COM
15910394SMichael.Corcoran@Sun.COM ASSERT(infop != NULL);
16010394SMichael.Corcoran@Sun.COM if (infop->awi_op_type == ACPIDEV_OP_BOOT_PROBE ||
16110394SMichael.Corcoran@Sun.COM infop->awi_op_type == ACPIDEV_OP_BOOT_REPROBE ||
16210394SMichael.Corcoran@Sun.COM infop->awi_op_type == ACPIDEV_OP_HOTPLUG_PROBE) {
16310394SMichael.Corcoran@Sun.COM res = acpidev_filter_device(infop, infop->awi_hdl,
16410394SMichael.Corcoran@Sun.COM ACPIDEV_ARRAY_PARAM(acpidev_memory_filters),
16510394SMichael.Corcoran@Sun.COM devname, maxlen);
16610394SMichael.Corcoran@Sun.COM } else {
16710394SMichael.Corcoran@Sun.COM res = ACPIDEV_FILTER_FAILED;
16810394SMichael.Corcoran@Sun.COM }
16910394SMichael.Corcoran@Sun.COM
17010394SMichael.Corcoran@Sun.COM return (res);
17110394SMichael.Corcoran@Sun.COM }
17210394SMichael.Corcoran@Sun.COM
17310394SMichael.Corcoran@Sun.COM static ACPI_STATUS
acpidev_memory_init(acpidev_walk_info_t * infop)17410394SMichael.Corcoran@Sun.COM acpidev_memory_init(acpidev_walk_info_t *infop)
17510394SMichael.Corcoran@Sun.COM {
17610394SMichael.Corcoran@Sun.COM char *compatible[] = {
17710394SMichael.Corcoran@Sun.COM ACPIDEV_TYPE_MEMORY,
17810394SMichael.Corcoran@Sun.COM "mem"
17910394SMichael.Corcoran@Sun.COM };
18010394SMichael.Corcoran@Sun.COM
18110394SMichael.Corcoran@Sun.COM ASSERT(infop != NULL);
18210394SMichael.Corcoran@Sun.COM ASSERT(infop->awi_hdl != NULL);
18310394SMichael.Corcoran@Sun.COM ASSERT(infop->awi_dip != NULL);
18410394SMichael.Corcoran@Sun.COM if (ACPI_FAILURE(acpidev_resource_process(infop, B_TRUE))) {
18510394SMichael.Corcoran@Sun.COM cmn_err(CE_WARN, "!acpidev: failed to process resources of "
18610394SMichael.Corcoran@Sun.COM "memory device %s.", infop->awi_name);
18710394SMichael.Corcoran@Sun.COM return (AE_ERROR);
18810394SMichael.Corcoran@Sun.COM }
18910394SMichael.Corcoran@Sun.COM
19010394SMichael.Corcoran@Sun.COM if (ACPI_FAILURE(acpidev_set_compatible(infop,
19110394SMichael.Corcoran@Sun.COM ACPIDEV_ARRAY_PARAM(compatible)))) {
19210394SMichael.Corcoran@Sun.COM return (AE_ERROR);
19310394SMichael.Corcoran@Sun.COM }
19410394SMichael.Corcoran@Sun.COM
19510394SMichael.Corcoran@Sun.COM if (ACPI_FAILURE(acpidev_set_unitaddr(infop,
19610394SMichael.Corcoran@Sun.COM ACPIDEV_ARRAY_PARAM(acpidev_memory_uid_formats), NULL))) {
19710394SMichael.Corcoran@Sun.COM return (AE_ERROR);
19810394SMichael.Corcoran@Sun.COM }
19910394SMichael.Corcoran@Sun.COM
20010394SMichael.Corcoran@Sun.COM return (AE_OK);
20110394SMichael.Corcoran@Sun.COM }
202