--- /dev/null Fri Jun 26 08:09:31 2009 +++ new/usr/src/uts/i86pc/io/acpi/acpidev/acpidev_memory.c Fri Jun 26 08:09:31 2009 @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2009, Intel Corporation. + * All rights reserved. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static ACPI_STATUS acpidev_memory_probe(acpidev_walk_info_t *infop); +static acpidev_filter_result_t acpidev_memory_filter( + acpidev_walk_info_t *infop, char *devname, int maxlen); +static ACPI_STATUS acpidev_memory_init(acpidev_walk_info_t *infop); + +/* + * Default class driver for ACPI memory objects. + */ +acpidev_class_t acpidev_class_memory = { + 0, /* adc_refcnt */ + ACPIDEV_CLASS_REV1, /* adc_version */ + ACPIDEV_CLASS_ID_MEMORY, /* adc_class_id */ + "ACPI memory", /* adc_class_name */ + ACPIDEV_TYPE_MEMORY, /* adc_dev_type */ + NULL, /* adc_private */ + NULL, /* adc_pre_probe */ + NULL, /* adc_post_probe */ + acpidev_memory_probe, /* adc_probe */ + acpidev_memory_filter, /* adc_filter */ + acpidev_memory_init, /* adc_init */ + NULL, /* adc_fini */ +}; + +/* + * List head of class drivers which will be called in order when handling + * children of ACPI memory object. + */ +acpidev_class_list_t *acpidev_class_list_memory = NULL; + +static char *acpidev_memory_device_ids[] = { + ACPIDEV_HID_MEMORY, +}; + +static char *acpidev_memory_uid_formats[] = { + "MEM%x-%x", +}; + +/* Filter rule table for memory objects. */ +static acpidev_filter_rule_t acpidev_memory_filters[] = { + { /* Ignore all memory objects under ACPI root object */ + NULL, + 0, + ACPIDEV_FILTER_SKIP, + NULL, + 1, + 1, + NULL, + NULL, + }, + { /* Create node and scan child for all other memory objects */ + NULL, + 0, + ACPIDEV_FILTER_DEFAULT, + &acpidev_class_list_device, + 2, + INT_MAX, + NULL, + ACPIDEV_NODE_NAME_MEMORY, + } +}; + +static ACPI_STATUS +acpidev_memory_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 || + acpidev_match_device_id(infop->awi_info, + ACPIDEV_ARRAY_PARAM(acpidev_memory_device_ids)) == 0) { + 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 memory_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 memory object %s.\n", + infop->awi_name); + } else { + rc = AE_OK; + } + + return (rc); +} + +static acpidev_filter_result_t +acpidev_memory_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_memory_filters), + devname, maxlen); + } else { + res = ACPIDEV_FILTER_FAILED; + } + + return (res); +} + +/*ARGSUSED*/ +static ACPI_STATUS +acpidev_memory_init(acpidev_walk_info_t *infop) +{ + char *compatibles[] = { + ACPIDEV_TYPE_MEMORY, + "mem" + }; + + ASSERT(infop != NULL); + ASSERT(infop->awi_hdl != NULL); + ASSERT(infop->awi_dip != NULL); + if (ACPI_FAILURE(acpidev_resource_process(infop, B_TRUE))) { + cmn_err(CE_WARN, + "acpidev: failed to process resources of memory device %s.", + infop->awi_name); + return (AE_ERROR); + } + + if (ACPI_FAILURE(acpidev_set_compatibles(infop, + ACPIDEV_ARRAY_PARAM(compatibles)))) { + return (AE_ERROR); + } + + if (ACPI_FAILURE(acpidev_set_unitaddr(infop, + ACPIDEV_ARRAY_PARAM(acpidev_memory_uid_formats), NULL))) { + return (AE_ERROR); + } + + return (AE_OK); +}