summaryrefslogtreecommitdiffstats
path: root/drivers/acpi/dispatcher
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 15:20:36 -0700
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /drivers/acpi/dispatcher
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'drivers/acpi/dispatcher')
-rw-r--r--drivers/acpi/dispatcher/Makefile9
-rw-r--r--drivers/acpi/dispatcher/dsfield.c601
-rw-r--r--drivers/acpi/dispatcher/dsinit.c235
-rw-r--r--drivers/acpi/dispatcher/dsmethod.c597
-rw-r--r--drivers/acpi/dispatcher/dsmthdat.c715
-rw-r--r--drivers/acpi/dispatcher/dsobject.c618
-rw-r--r--drivers/acpi/dispatcher/dsopcode.c1151
-rw-r--r--drivers/acpi/dispatcher/dsutils.c744
-rw-r--r--drivers/acpi/dispatcher/dswexec.c751
-rw-r--r--drivers/acpi/dispatcher/dswload.c976
-rw-r--r--drivers/acpi/dispatcher/dswscope.c229
-rw-r--r--drivers/acpi/dispatcher/dswstate.c1100
12 files changed, 7726 insertions, 0 deletions
diff --git a/drivers/acpi/dispatcher/Makefile b/drivers/acpi/dispatcher/Makefile
new file mode 100644
index 00000000000..eb7e602a83c
--- /dev/null
+++ b/drivers/acpi/dispatcher/Makefile
@@ -0,0 +1,9 @@
+#
+# Makefile for all Linux ACPI interpreter subdirectories
+#
+
+obj-y := dsfield.o dsmthdat.o dsopcode.o dswexec.o dswscope.o \
+ dsmethod.o dsobject.o dsutils.o dswload.o dswstate.o \
+ dsinit.o
+
+EXTRA_CFLAGS += $(ACPI_CFLAGS)
diff --git a/drivers/acpi/dispatcher/dsfield.c b/drivers/acpi/dispatcher/dsfield.c
new file mode 100644
index 00000000000..2779211be75
--- /dev/null
+++ b/drivers/acpi/dispatcher/dsfield.c
@@ -0,0 +1,601 @@
+/******************************************************************************
+ *
+ * Module Name: dsfield - Dispatcher field routines
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2005, R. Byron Moore
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+
+#include <acpi/acpi.h>
+#include <acpi/amlcode.h>
+#include <acpi/acdispat.h>
+#include <acpi/acinterp.h>
+#include <acpi/acnamesp.h>
+#include <acpi/acparser.h>
+
+
+#define _COMPONENT ACPI_DISPATCHER
+ ACPI_MODULE_NAME ("dsfield")
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_create_buffer_field
+ *
+ * PARAMETERS: Opcode - The opcode to be executed
+ * Operands - List of operands for the opcode
+ * walk_state - Current state
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Execute the create_field operators:
+ * create_bit_field_op,
+ * create_byte_field_op,
+ * create_word_field_op,
+ * create_dword_field_op,
+ * create_qword_field_op,
+ * create_field_op (all of which define fields in buffers)
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_create_buffer_field (
+ union acpi_parse_object *op,
+ struct acpi_walk_state *walk_state)
+{
+ union acpi_parse_object *arg;
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object *second_desc = NULL;
+ u32 flags;
+
+
+ ACPI_FUNCTION_TRACE ("ds_create_buffer_field");
+
+
+ /* Get the name_string argument */
+
+ if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {
+ arg = acpi_ps_get_arg (op, 3);
+ }
+ else {
+ /* Create Bit/Byte/Word/Dword field */
+
+ arg = acpi_ps_get_arg (op, 2);
+ }
+
+ if (!arg) {
+ return_ACPI_STATUS (AE_AML_NO_OPERAND);
+ }
+
+ if (walk_state->deferred_node) {
+ node = walk_state->deferred_node;
+ status = AE_OK;
+ }
+ else {
+ /*
+ * During the load phase, we want to enter the name of the field into
+ * the namespace. During the execute phase (when we evaluate the size
+ * operand), we want to lookup the name
+ */
+ if (walk_state->parse_flags & ACPI_PARSE_EXECUTE) {
+ flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE;
+ }
+ else {
+ flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND;
+ }
+
+ /*
+ * Enter the name_string into the namespace
+ */
+ status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string,
+ ACPI_TYPE_ANY, ACPI_IMODE_LOAD_PASS1,
+ flags, walk_state, &(node));
+ if (ACPI_FAILURE (status)) {
+ ACPI_REPORT_NSERROR (arg->common.value.string, status);
+ return_ACPI_STATUS (status);
+ }
+ }
+
+ /* We could put the returned object (Node) on the object stack for later, but
+ * for now, we will put it in the "op" object that the parser uses, so we
+ * can get it again at the end of this scope
+ */
+ op->common.node = node;
+
+ /*
+ * If there is no object attached to the node, this node was just created and
+ * we need to create the field object. Otherwise, this was a lookup of an
+ * existing node and we don't want to create the field object again.
+ */
+ obj_desc = acpi_ns_get_attached_object (node);
+ if (obj_desc) {
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ /*
+ * The Field definition is not fully parsed at this time.
+ * (We must save the address of the AML for the buffer and index operands)
+ */
+
+ /* Create the buffer field object */
+
+ obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER_FIELD);
+ if (!obj_desc) {
+ status = AE_NO_MEMORY;
+ goto cleanup;
+ }
+
+ /*
+ * Remember location in AML stream of the field unit
+ * opcode and operands -- since the buffer and index
+ * operands must be evaluated.
+ */
+ second_desc = obj_desc->common.next_object;
+ second_desc->extra.aml_start = op->named.data;
+ second_desc->extra.aml_length = op->named.length;
+ obj_desc->buffer_field.node = node;
+
+ /* Attach constructed field descriptors to parent node */
+
+ status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_BUFFER_FIELD);
+ if (ACPI_FAILURE (status)) {
+ goto cleanup;
+ }
+
+
+cleanup:
+
+ /* Remove local reference to the object */
+
+ acpi_ut_remove_reference (obj_desc);
+ return_ACPI_STATUS (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_get_field_names
+ *
+ * PARAMETERS: Info - create_field info structure
+ * ` walk_state - Current method state
+ * Arg - First parser arg for the field name list
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Process all named fields in a field declaration. Names are
+ * entered into the namespace.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_get_field_names (
+ struct acpi_create_field_info *info,
+ struct acpi_walk_state *walk_state,
+ union acpi_parse_object *arg)
+{
+ acpi_status status;
+ acpi_integer position;
+
+
+ ACPI_FUNCTION_TRACE_PTR ("ds_get_field_names", info);
+
+
+ /* First field starts at bit zero */
+
+ info->field_bit_position = 0;
+
+ /* Process all elements in the field list (of parse nodes) */
+
+ while (arg) {
+ /*
+ * Three types of field elements are handled:
+ * 1) Offset - specifies a bit offset
+ * 2) access_as - changes the access mode
+ * 3) Name - Enters a new named field into the namespace
+ */
+ switch (arg->common.aml_opcode) {
+ case AML_INT_RESERVEDFIELD_OP:
+
+ position = (acpi_integer) info->field_bit_position
+ + (acpi_integer) arg->common.value.size;
+
+ if (position > ACPI_UINT32_MAX) {
+ ACPI_REPORT_ERROR (("Bit offset within field too large (> 0xFFFFFFFF)\n"));
+ return_ACPI_STATUS (AE_SUPPORT);
+ }
+
+ info->field_bit_position = (u32) position;
+ break;
+
+
+ case AML_INT_ACCESSFIELD_OP:
+
+ /*
+ * Get a new access_type and access_attribute -- to be used for all
+ * field units that follow, until field end or another access_as keyword.
+ *
+ * In field_flags, preserve the flag bits other than the ACCESS_TYPE bits
+ */
+ info->field_flags = (u8) ((info->field_flags & ~(AML_FIELD_ACCESS_TYPE_MASK)) |
+ ((u8) ((u32) arg->common.value.integer >> 8)));
+
+ info->attribute = (u8) (arg->common.value.integer);
+ break;
+
+
+ case AML_INT_NAMEDFIELD_OP:
+
+ /* Lookup the name */
+
+ status = acpi_ns_lookup (walk_state->scope_info,
+ (char *) &arg->named.name,
+ info->field_type, ACPI_IMODE_EXECUTE, ACPI_NS_DONT_OPEN_SCOPE,
+ walk_state, &info->field_node);
+ if (ACPI_FAILURE (status)) {
+ ACPI_REPORT_NSERROR ((char *) &arg->named.name, status);
+ if (status != AE_ALREADY_EXISTS) {
+ return_ACPI_STATUS (status);
+ }
+
+ /* Already exists, ignore error */
+ }
+ else {
+ arg->common.node = info->field_node;
+ info->field_bit_length = arg->common.value.size;
+
+ /* Create and initialize an object for the new Field Node */
+
+ status = acpi_ex_prep_field_value (info);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+ }
+
+ /* Keep track of bit position for the next field */
+
+ position = (acpi_integer) info->field_bit_position
+ + (acpi_integer) arg->common.value.size;
+
+ if (position > ACPI_UINT32_MAX) {
+ ACPI_REPORT_ERROR (("Field [%4.4s] bit offset too large (> 0xFFFFFFFF)\n",
+ (char *) &info->field_node->name));
+ return_ACPI_STATUS (AE_SUPPORT);
+ }
+
+ info->field_bit_position += info->field_bit_length;
+ break;
+
+
+ default:
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid opcode in field list: %X\n",
+ arg->common.aml_opcode));
+ return_ACPI_STATUS (AE_AML_BAD_OPCODE);
+ }
+
+ arg = arg->common.next;
+ }
+
+ return_ACPI_STATUS (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_create_field
+ *
+ * PARAMETERS: Op - Op containing the Field definition and args
+ * region_node - Object for the containing Operation Region
+ * ` walk_state - Current method state
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Create a new field in the specified operation region
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_create_field (
+ union acpi_parse_object *op,
+ struct acpi_namespace_node *region_node,
+ struct acpi_walk_state *walk_state)
+{
+ acpi_status status;
+ union acpi_parse_object *arg;
+ struct acpi_create_field_info info;
+
+
+ ACPI_FUNCTION_TRACE_PTR ("ds_create_field", op);
+
+
+ /* First arg is the name of the parent op_region (must already exist) */
+
+ arg = op->common.value.arg;
+ if (!region_node) {
+ status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.name,
+ ACPI_TYPE_REGION, ACPI_IMODE_EXECUTE,
+ ACPI_NS_SEARCH_PARENT, walk_state, &region_node);
+ if (ACPI_FAILURE (status)) {
+ ACPI_REPORT_NSERROR (arg->common.value.name, status);
+ return_ACPI_STATUS (status);
+ }
+ }
+
+ /* Second arg is the field flags */
+
+ arg = arg->common.next;
+ info.field_flags = (u8) arg->common.value.integer;
+ info.attribute = 0;
+
+ /* Each remaining arg is a Named Field */
+
+ info.field_type = ACPI_TYPE_LOCAL_REGION_FIELD;
+ info.region_node = region_node;
+
+ status = acpi_ds_get_field_names (&info, walk_state, arg->common.next);
+
+ return_ACPI_STATUS (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_init_field_objects
+ *
+ * PARAMETERS: Op - Op containing the Field definition and args
+ * ` walk_state - Current method state
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: For each "Field Unit" name in the argument list that is
+ * part of the field declaration, enter the name into the
+ * namespace.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_init_field_objects (
+ union acpi_parse_object *op,
+ struct acpi_walk_state *walk_state)
+{
+ acpi_status status;
+ union acpi_parse_object *arg = NULL;
+ struct acpi_namespace_node *node;
+ u8 type = 0;
+
+
+ ACPI_FUNCTION_TRACE_PTR ("ds_init_field_objects", op);
+
+
+ switch (walk_state->opcode) {
+ case AML_FIELD_OP:
+ arg = acpi_ps_get_arg (op, 2);
+ type = ACPI_TYPE_LOCAL_REGION_FIELD;
+ break;
+
+ case AML_BANK_FIELD_OP:
+ arg = acpi_ps_get_arg (op, 4);
+ type = ACPI_TYPE_LOCAL_BANK_FIELD;
+ break;
+
+ case AML_INDEX_FIELD_OP:
+ arg = acpi_ps_get_arg (op, 3);
+ type = ACPI_TYPE_LOCAL_INDEX_FIELD;
+ break;
+
+ default:
+ return_ACPI_STATUS (AE_BAD_PARAMETER);
+ }
+
+ /*
+ * Walk the list of entries in the field_list
+ */
+ while (arg) {
+ /* Ignore OFFSET and ACCESSAS terms here */
+
+ if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {
+ status = acpi_ns_lookup (walk_state->scope_info,
+ (char *) &arg->named.name,
+ type, ACPI_IMODE_LOAD_PASS1,
+ ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND,
+ walk_state, &node);
+ if (ACPI_FAILURE (status)) {
+ ACPI_REPORT_NSERROR ((char *) &arg->named.name, status);
+ if (status != AE_ALREADY_EXISTS) {
+ return_ACPI_STATUS (status);
+ }
+
+ /* Name already exists, just ignore this error */
+
+ status = AE_OK;
+ }
+
+ arg->common.node = node;
+ }
+
+ /* Move to next field in the list */
+
+ arg = arg->common.next;
+ }
+
+ return_ACPI_STATUS (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_create_bank_field
+ *
+ * PARAMETERS: Op - Op containing the Field definition and args
+ * region_node - Object for the containing Operation Region
+ * ` walk_state - Current method state
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Create a new bank field in the specified operation region
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_create_bank_field (
+ union acpi_parse_object *op,
+ struct acpi_namespace_node *region_node,
+ struct acpi_walk_state *walk_state)
+{
+ acpi_status status;
+ union acpi_parse_object *arg;
+ struct acpi_create_field_info info;
+
+
+ ACPI_FUNCTION_TRACE_PTR ("ds_create_bank_field", op);
+
+
+ /* First arg is the name of the parent op_region (must already exist) */
+
+ arg = op->common.value.arg;
+ if (!region_node) {
+ status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.name,
+ ACPI_TYPE_REGION, ACPI_IMODE_EXECUTE,
+ ACPI_NS_SEARCH_PARENT, walk_state, &region_node);
+ if (ACPI_FAILURE (status)) {
+ ACPI_REPORT_NSERROR (arg->common.value.name, status);
+ return_ACPI_STATUS (status);
+ }
+ }
+
+ /* Second arg is the Bank Register (Field) (must already exist) */
+
+ arg = arg->common.next;
+ status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string,
+ ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
+ ACPI_NS_SEARCH_PARENT, walk_state, &info.register_node);
+ if (ACPI_FAILURE (status)) {
+ ACPI_REPORT_NSERROR (arg->common.value.string, status);
+ return_ACPI_STATUS (status);
+ }
+
+ /* Third arg is the bank_value */
+
+ arg = arg->common.next;
+ info.bank_value = (u32) arg->common.value.integer;
+
+ /* Fourth arg is the field flags */
+
+ arg = arg->common.next;
+ info.field_flags = (u8) arg->common.value.integer;
+
+ /* Each remaining arg is a Named Field */
+
+ info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD;
+ info.region_node = region_node;
+
+ status = acpi_ds_get_field_names (&info, walk_state, arg->common.next);
+
+ return_ACPI_STATUS (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_create_index_field
+ *
+ * PARAMETERS: Op - Op containing the Field definition and args
+ * region_node - Object for the containing Operation Region
+ * ` walk_state - Current method state
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Create a new index field in the specified operation region
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_create_index_field (
+ union acpi_parse_object *op,
+ struct acpi_namespace_node *region_node,
+ struct acpi_walk_state *walk_state)
+{
+ acpi_status status;
+ union acpi_parse_object *arg;
+ struct acpi_create_field_info info;
+
+
+ ACPI_FUNCTION_TRACE_PTR ("ds_create_index_field", op);
+
+
+ /* First arg is the name of the Index register (must already exist) */
+
+ arg = op->common.value.arg;
+ status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string,
+ ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
+ ACPI_NS_SEARCH_PARENT, walk_state, &info.register_node);
+ if (ACPI_FAILURE (status)) {
+ ACPI_REPORT_NSERROR (arg->common.value.string, status);
+ return_ACPI_STATUS (status);
+ }
+
+ /* Second arg is the data register (must already exist) */
+
+ arg = arg->common.next;
+ status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string,
+ ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
+ ACPI_NS_SEARCH_PARENT, walk_state, &info.data_register_node);
+ if (ACPI_FAILURE (status)) {
+ ACPI_REPORT_NSERROR (arg->common.value.string, status);
+ return_ACPI_STATUS (status);
+ }
+
+ /* Next arg is the field flags */
+
+ arg = arg->common.next;
+ info.field_flags = (u8) arg->common.value.integer;
+
+ /* Each remaining arg is a Named Field */
+
+ info.field_type = ACPI_TYPE_LOCAL_INDEX_FIELD;
+ info.region_node = region_node;
+
+ status = acpi_ds_get_field_names (&info, walk_state, arg->common.next);
+
+ return_ACPI_STATUS (status);
+}
+
+
diff --git a/drivers/acpi/dispatcher/dsinit.c b/drivers/acpi/dispatcher/dsinit.c
new file mode 100644
index 00000000000..b4d264dbbf6
--- /dev/null
+++ b/drivers/acpi/dispatcher/dsinit.c
@@ -0,0 +1,235 @@
+/******************************************************************************
+ *
+ * Module Name: dsinit - Object initialization namespace walk
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2005, R. Byron Moore
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+
+#include <acpi/acpi.h>
+#include <acpi/acdispat.h>
+#include <acpi/acnamesp.h>
+
+#define _COMPONENT ACPI_DISPATCHER
+ ACPI_MODULE_NAME ("dsinit")
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_init_one_object
+ *
+ * PARAMETERS: obj_handle - Node
+ * Level - Current nesting level
+ * Context - Points to a init info struct
+ * return_value - Not used
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Callback from acpi_walk_namespace. Invoked for every object
+ * within the namespace.
+ *
+ * Currently, the only objects that require initialization are:
+ * 1) Methods
+ * 2) Operation Regions
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_init_one_object (
+ acpi_handle obj_handle,
+ u32 level,
+ void *context,
+ void **return_value)
+{
+ acpi_object_type type;
+ acpi_status status;
+ struct acpi_init_walk_info *info = (struct acpi_init_walk_info *) context;
+
+
+ ACPI_FUNCTION_NAME ("ds_init_one_object");
+
+
+ /*
+ * We are only interested in objects owned by the table that
+ * was just loaded
+ */
+ if (((struct acpi_namespace_node *) obj_handle)->owner_id !=
+ info->table_desc->table_id) {
+ return (AE_OK);
+ }
+
+ info->object_count++;
+
+ /* And even then, we are only interested in a few object types */
+
+ type = acpi_ns_get_type (obj_handle);
+
+ switch (type) {
+ case ACPI_TYPE_REGION:
+
+ status = acpi_ds_initialize_region (obj_handle);
+ if (ACPI_FAILURE (status)) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region %p [%4.4s] - Init failure, %s\n",
+ obj_handle, acpi_ut_get_node_name (obj_handle),
+ acpi_format_exception (status)));
+ }
+
+ info->op_region_count++;
+ break;
+
+
+ case ACPI_TYPE_METHOD:
+
+ info->method_count++;
+
+ /* Print a dot for each method unless we are going to print the entire pathname */
+
+ if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) {
+ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "."));
+ }
+
+ /*
+ * Set the execution data width (32 or 64) based upon the
+ * revision number of the parent ACPI table.
+ * TBD: This is really for possible future support of integer width
+ * on a per-table basis. Currently, we just use a global for the width.
+ */
+ if (info->table_desc->pointer->revision == 1) {
+ ((struct acpi_namespace_node *) obj_handle)->flags |= ANOBJ_DATA_WIDTH_32;
+ }
+
+ /*
+ * Always parse methods to detect errors, we will delete
+ * the parse tree below
+ */
+ status = acpi_ds_parse_method (obj_handle);
+ if (ACPI_FAILURE (status)) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Method %p [%4.4s] - parse failure, %s\n",
+ obj_handle, acpi_ut_get_node_name (obj_handle),
+ acpi_format_exception (status)));
+
+ /* This parse failed, but we will continue parsing more methods */
+
+ break;
+ }
+
+ /*
+ * Delete the parse tree. We simply re-parse the method
+ * for every execution since there isn't much overhead
+ */
+ acpi_ns_delete_namespace_subtree (obj_handle);
+ acpi_ns_delete_namespace_by_owner (((struct acpi_namespace_node *) obj_handle)->object->method.owning_id);
+ break;
+
+
+ case ACPI_TYPE_DEVICE:
+
+ info->device_count++;
+ break;
+
+
+ default:
+ break;
+ }
+
+ /*
+ * We ignore errors from above, and always return OK, since
+ * we don't want to abort the walk on a single error.
+ */
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_initialize_objects
+ *
+ * PARAMETERS: table_desc - Descriptor for parent ACPI table
+ * start_node - Root of subtree to be initialized.
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Walk the namespace starting at "start_node" and perform any
+ * necessary initialization on the objects found therein
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_initialize_objects (
+ struct acpi_table_desc *table_desc,
+ struct acpi_namespace_node *start_node)
+{
+ acpi_status status;
+ struct acpi_init_walk_info info;
+
+
+ ACPI_FUNCTION_TRACE ("ds_initialize_objects");
+
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+ "**** Starting initialization of namespace objects ****\n"));
+ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "Parsing all Control Methods:"));
+
+ info.method_count = 0;
+ info.op_region_count = 0;
+ info.object_count = 0;
+ info.device_count = 0;
+ info.table_desc = table_desc;
+
+ /* Walk entire namespace from the supplied root */
+
+ status = acpi_walk_namespace (ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX,
+ acpi_ds_init_one_object, &info, NULL);
+ if (ACPI_FAILURE (status)) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "walk_namespace failed, %s\n",
+ acpi_format_exception (status)));
+ }
+
+ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
+ "\nTable [%4.4s](id %4.4X) - %hd Objects with %hd Devices %hd Methods %hd Regions\n",
+ table_desc->pointer->signature, table_desc->table_id, info.object_count,
+ info.device_count, info.method_count, info.op_region_count));
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+ "%hd Methods, %hd Regions\n", info.method_count, info.op_region_count));
+
+ return_ACPI_STATUS (AE_OK);
+}
+
+
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c
new file mode 100644
index 00000000000..9f0456cb9bb
--- /dev/null
+++ b/drivers/acpi/dispatcher/dsmethod.c
@@ -0,0 +1,597 @@
+/******************************************************************************
+ *
+ * Module Name: dsmethod - Parser/Interpreter interface - control method parsing
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2005, R. Byron Moore
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+
+#include <acpi/acpi.h>
+#include <acpi/acparser.h>
+#include <acpi/amlcode.h>
+#include <acpi/acdispat.h>
+#include <acpi/acinterp.h>
+#include <acpi/acnamesp.h>
+
+
+#define _COMPONENT ACPI_DISPATCHER
+ ACPI_MODULE_NAME ("dsmethod")
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_parse_method
+ *
+ * PARAMETERS: obj_handle - Method node
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Call the parser and parse the AML that is associated with the
+ * method.
+ *
+ * MUTEX: Assumes parser is locked
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_parse_method (
+ acpi_handle obj_handle)
+{
+ acpi_status status;
+ union acpi_operand_object *obj_desc;
+ union acpi_parse_object *op;
+ struct acpi_namespace_node *node;
+ acpi_owner_id owner_id;
+ struct acpi_walk_state *walk_state;
+
+
+ ACPI_FUNCTION_TRACE_PTR ("ds_parse_method", obj_handle);
+
+
+ /* Parameter Validation */
+
+ if (!obj_handle) {
+ return_ACPI_STATUS (AE_NULL_ENTRY);
+ }
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "**** Parsing [%4.4s] **** named_obj=%p\n",
+ acpi_ut_get_node_name (obj_handle), obj_handle));
+
+ /* Extract the method object from the method Node */
+
+ node = (struct acpi_namespace_node *) obj_handle;
+ obj_desc = acpi_ns_get_attached_object (node);
+ if (!obj_desc) {
+ return_ACPI_STATUS (AE_NULL_OBJECT);
+ }
+
+ /* Create a mutex for the method if there is a concurrency limit */
+
+ if ((obj_desc->method.concurrency != ACPI_INFINITE_CONCURRENCY) &&
+ (!obj_desc->method.semaphore)) {
+ status = acpi_os_create_semaphore (obj_desc->method.concurrency,
+ obj_desc->method.concurrency,
+ &obj_desc->method.semaphore);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+ }
+
+ /*
+ * Allocate a new parser op to be the root of the parsed
+ * method tree
+ */
+ op = acpi_ps_alloc_op (AML_METHOD_OP);
+ if (!op) {
+ return_ACPI_STATUS (AE_NO_MEMORY);
+ }
+
+ /* Init new op with the method name and pointer back to the Node */
+
+ acpi_ps_set_name (op, node->name.integer);
+ op->common.node = node;
+
+ /*
+ * Get a new owner_id for objects created by this method. Namespace
+ * objects (such as Operation Regions) can be created during the
+ * first pass parse.
+ */
+ owner_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_METHOD);
+ obj_desc->method.owning_id = owner_id;
+
+ /* Create and initialize a new walk state */
+
+ walk_state = acpi_ds_create_walk_state (owner_id, NULL, NULL, NULL);
+ if (!walk_state) {
+ return_ACPI_STATUS (AE_NO_MEMORY);
+ }
+
+ status = acpi_ds_init_aml_walk (walk_state, op, node,
+ obj_desc->method.aml_start,
+ obj_desc->method.aml_length, NULL, 1);
+ if (ACPI_FAILURE (status)) {
+ acpi_ds_delete_walk_state (walk_state);
+ return_ACPI_STATUS (status);
+ }
+
+ /*
+ * Parse the method, first pass
+ *
+ * The first pass load is where newly declared named objects are
+ * added into the namespace. Actual evaluation of
+ * the named objects (what would be called a "second
+ * pass") happens during the actual execution of the
+ * method so that operands to the named objects can
+ * take on dynamic run-time values.
+ */
+ status = acpi_ps_parse_aml (walk_state);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
+ "**** [%4.4s] Parsed **** named_obj=%p Op=%p\n",
+ acpi_ut_get_node_name (obj_handle), obj_handle, op));
+
+ acpi_ps_delete_parse_tree (op);
+ return_ACPI_STATUS (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_begin_method_execution
+ *
+ * PARAMETERS: method_node - Node of the method
+ * obj_desc - The method object
+ * calling_method_node - Caller of this method (if non-null)
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Prepare a method for execution. Parses the method if necessary,
+ * increments the thread count, and waits at the method semaphore
+ * for clearance to execute.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_begin_method_execution (
+ struct acpi_namespace_node *method_node,
+ union acpi_operand_object *obj_desc,
+ struct acpi_namespace_node *calling_method_node)
+{
+ acpi_status status = AE_OK;
+
+
+ ACPI_FUNCTION_TRACE_PTR ("ds_begin_method_execution", method_node);
+
+
+ if (!method_node) {
+ return_ACPI_STATUS (AE_NULL_ENTRY);
+ }
+
+ /*
+ * If there is a concurrency limit on this method, we need to
+ * obtain a unit from the method semaphore.
+ */
+ if (obj_desc->method.semaphore) {
+ /*
+ * Allow recursive method calls, up to the reentrancy/concurrency
+ * limit imposed by the SERIALIZED rule and the sync_level method
+ * parameter.
+ *
+ * The point of this code is to avoid permanently blocking a
+ * thread that is making recursive method calls.
+ */
+ if (method_node == calling_method_node) {
+ if (obj_desc->method.thread_count >= obj_desc->method.concurrency) {
+ return_ACPI_STATUS (AE_AML_METHOD_LIMIT);
+ }
+ }
+
+ /*
+ * Get a unit from the method semaphore. This releases the
+ * interpreter if we block
+ */
+ status = acpi_ex_system_wait_semaphore (obj_desc->method.semaphore,
+ ACPI_WAIT_FOREVER);
+ }
+
+ /*
+ * Increment the method parse tree thread count since it has been
+ * reentered one more time (even if it is the same thread)
+ */
+ obj_desc->method.thread_count++;
+ return_ACPI_STATUS (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_call_control_method
+ *
+ * PARAMETERS: Thread - Info for this thread
+ * this_walk_state - Current walk state
+ * Op - Current Op to be walked
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Transfer execution to a called control method
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_call_control_method (
+ struct acpi_thread_state *thread,
+ struct acpi_walk_state *this_walk_state,
+ union acpi_parse_object *op)
+{
+ acpi_status status;
+ struct acpi_namespace_node *method_node;
+ struct acpi_walk_state *next_walk_state;
+ union acpi_operand_object *obj_desc;
+ struct acpi_parameter_info info;
+ u32 i;
+
+
+ ACPI_FUNCTION_TRACE_PTR ("ds_call_control_method", this_walk_state);
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Execute method %p, currentstate=%p\n",
+ this_walk_state->prev_op, this_walk_state));
+
+ /*
+ * Get the namespace entry for the control method we are about to call
+ */
+ method_node = this_walk_state->method_call_node;
+ if (!method_node) {
+ return_ACPI_STATUS (AE_NULL_ENTRY);
+ }
+
+ obj_desc = acpi_ns_get_attached_object (method_node);
+ if (!obj_desc) {
+ return_ACPI_STATUS (AE_NULL_OBJECT);
+ }
+
+ obj_desc->method.owning_id = acpi_ut_allocate_owner_id (ACPI_OWNER_TYPE_METHOD);
+
+ /* Init for new method, wait on concurrency semaphore */
+
+ status = acpi_ds_begin_method_execution (method_node, obj_desc,
+ this_walk_state->method_node);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ if (!(obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY)) {
+ /* 1) Parse: Create a new walk state for the preempting walk */
+
+ next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id,
+ op, obj_desc, NULL);
+ if (!next_walk_state) {
+ return_ACPI_STATUS (AE_NO_MEMORY);
+ }
+
+ /* Create and init a Root Node */
+
+ op = acpi_ps_create_scope_op ();
+ if (!op) {
+ status = AE_NO_MEMORY;
+ goto cleanup;
+ }
+
+ status = acpi_ds_init_aml_walk (next_walk_state, op, method_node,
+ obj_desc->method.aml_start, obj_desc->method.aml_length,
+ NULL, 1);
+ if (ACPI_FAILURE (status)) {
+ acpi_ds_delete_walk_state (next_walk_state);
+ goto cleanup;
+ }
+
+ /* Begin AML parse */
+
+ status = acpi_ps_parse_aml (next_walk_state);
+ acpi_ps_delete_parse_tree (op);
+ }
+
+ /* 2) Execute: Create a new state for the preempting walk */
+
+ next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id,
+ NULL, obj_desc, thread);
+ if (!next_walk_state) {
+ status = AE_NO_MEMORY;
+ goto cleanup;
+ }
+ /*
+ * The resolved arguments were put on the previous walk state's operand
+ * stack. Operands on the previous walk state stack always
+ * start at index 0.
+ * Null terminate the list of arguments
+ */
+ this_walk_state->operands [this_walk_state->num_operands] = NULL;
+
+ info.parameters = &this_walk_state->operands[0];
+ info.parameter_type = ACPI_PARAM_ARGS;
+
+ status = acpi_ds_init_aml_walk (next_walk_state, NULL, method_node,
+ obj_desc->method.aml_start, obj_desc->method.aml_length,
+ &info, 3);
+ if (ACPI_FAILURE (status)) {
+ goto cleanup;
+ }
+
+ /*
+ * Delete the operands on the previous walkstate operand stack
+ * (they were copied to new objects)
+ */
+ for (i = 0; i < obj_desc->method.param_count; i++) {
+ acpi_ut_remove_reference (this_walk_state->operands [i]);
+ this_walk_state->operands [i] = NULL;
+ }
+
+ /* Clear the operand stack */
+
+ this_walk_state->num_operands = 0;
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+ "Starting nested execution, newstate=%p\n", next_walk_state));
+
+ if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) {
+ status = obj_desc->method.implementation (next_walk_state);
+ return_ACPI_STATUS (status);
+ }
+
+ return_ACPI_STATUS (AE_OK);
+
+
+ /* On error, we must delete the new walk state */
+
+cleanup:
+ if (next_walk_state && (next_walk_state->method_desc)) {
+ /* Decrement the thread count on the method parse tree */
+
+ next_walk_state->method_desc->method.thread_count--;
+ }
+ (void) acpi_ds_terminate_control_method (next_walk_state);
+ acpi_ds_delete_walk_state (next_walk_state);
+ return_ACPI_STATUS (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_restart_control_method
+ *
+ * PARAMETERS: walk_state - State for preempted method (caller)
+ * return_desc - Return value from the called method
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Restart a method that was preempted by another (nested) method
+ * invocation. Handle the return value (if any) from the callee.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_restart_control_method (
+ struct acpi_walk_state *walk_state,
+ union acpi_operand_object *return_desc)
+{
+ acpi_status status;
+
+
+ ACPI_FUNCTION_TRACE_PTR ("ds_restart_control_method", walk_state);
+
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+ "****Restart [%4.4s] Op %p return_value_from_callee %p\n",
+ (char *) &walk_state->method_node->name, walk_state->method_call_op,
+ return_desc));
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+ " return_from_this_method_used?=%X res_stack %p Walk %p\n",
+ walk_state->return_used,
+ walk_state->results, walk_state));
+
+ /* Did the called method return a value? */
+
+ if (return_desc) {
+ /* Are we actually going to use the return value? */
+
+ if (walk_state->return_used) {
+ /* Save the return value from the previous method */
+
+ status = acpi_ds_result_push (return_desc, walk_state);
+ if (ACPI_FAILURE (status)) {
+ acpi_ut_remove_reference (return_desc);
+ return_ACPI_STATUS (status);
+ }
+
+ /*
+ * Save as THIS method's return value in case it is returned
+ * immediately to yet another method
+ */
+ walk_state->return_desc = return_desc;
+ }
+
+ /*
+ * The following code is the
+ * optional support for a so-called "implicit return". Some AML code
+ * assumes that the last value of the method is "implicitly" returned
+ * to the caller. Just save the last result as the return value.
+ * NOTE: this is optional because the ASL language does not actually
+ * support this behavior.
+ */
+ else if (!acpi_ds_do_implicit_return (return_desc, walk_state, FALSE)) {
+ /*
+ * Delete the return value if it will not be used by the
+ * calling method
+ */
+ acpi_ut_remove_reference (return_desc);
+ }
+ }
+
+ return_ACPI_STATUS (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_terminate_control_method
+ *
+ * PARAMETERS: walk_state - State of the method
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Terminate a control method. Delete everything that the method
+ * created, delete all locals and arguments, and delete the parse
+ * tree if requested.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_terminate_control_method (
+ struct acpi_walk_state *walk_state)
+{
+ union acpi_operand_object *obj_desc;
+ struct acpi_namespace_node *method_node;
+ acpi_status status;
+
+
+ ACPI_FUNCTION_TRACE_PTR ("ds_terminate_control_method", walk_state);
+
+
+ if (!walk_state) {
+ return (AE_BAD_PARAMETER);
+ }
+
+ /* The current method object was saved in the walk state */
+
+ obj_desc = walk_state->method_desc;
+ if (!obj_desc) {
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ /* Delete all arguments and locals */
+
+ acpi_ds_method_data_delete_all (walk_state);
+
+ /*
+ * Lock the parser while we terminate this method.
+ * If this is the last thread executing the method,
+ * we have additional cleanup to perform
+ */
+ status = acpi_ut_acquire_mutex (ACPI_MTX_PARSER);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ /* Signal completion of the execution of this method if necessary */
+
+ if (walk_state->method_desc->method.semaphore) {
+ status = acpi_os_signal_semaphore (
+ walk_state->method_desc->method.semaphore, 1);
+ if (ACPI_FAILURE (status)) {
+ ACPI_REPORT_ERROR (("Could not signal method semaphore\n"));
+ status = AE_OK;
+
+ /* Ignore error and continue cleanup */
+ }
+ }
+
+ if (walk_state->method_desc->method.thread_count) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+ "*** Not deleting method namespace, there are still %d threads\n",
+ walk_state->method_desc->method.thread_count));
+ }
+
+ if (!walk_state->method_desc->method.thread_count) {
+ /*
+ * Support to dynamically change a method from not_serialized to
+ * Serialized if it appears that the method is written foolishly and
+ * does not support multiple thread execution. The best example of this
+ * is if such a method creates namespace objects and blocks. A second
+ * thread will fail with an AE_ALREADY_EXISTS exception
+ *
+ * This code is here because we must wait until the last thread exits
+ * before creating the synchronization semaphore.
+ */
+ if ((walk_state->method_desc->method.concurrency == 1) &&
+ (!walk_state->method_desc->method.semaphore)) {
+ status = acpi_os_create_semaphore (1,
+ 1,
+ &walk_state->method_desc->method.semaphore);
+ }
+
+ /*
+ * There are no more threads executing this method. Perform
+ * additional cleanup.
+ *
+ * The method Node is stored in the walk state
+ */
+ method_node = walk_state->method_node;
+
+ /*
+ * Delete any namespace entries created immediately underneath
+ * the method
+ */
+ status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ if (method_node->child) {
+ acpi_ns_delete_namespace_subtree (method_node);
+ }
+
+ /*
+ * Delete any namespace entries created anywhere else within
+ * the namespace
+ */
+ acpi_ns_delete_namespace_by_owner (walk_state->method_desc->method.owning_id);
+ status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+ }
+
+ status = acpi_ut_release_mutex (ACPI_MTX_PARSER);
+ return_ACPI_STATUS (status);
+}
+
+
diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c
new file mode 100644
index 00000000000..f31d095f983
--- /dev/null
+++ b/drivers/acpi/dispatcher/dsmthdat.c
@@ -0,0 +1,715 @@
+/*******************************************************************************
+ *
+ * Module Name: dsmthdat - control method arguments and local variables
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2005, R. Byron Moore
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+
+#include <acpi/acpi.h>
+#include <acpi/acdispat.h>
+#include <acpi/amlcode.h>
+#include <acpi/acnamesp.h>
+#include <acpi/acinterp.h>
+
+
+#define _COMPONENT ACPI_DISPATCHER
+ ACPI_MODULE_NAME ("dsmthdat")
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_method_data_init
+ *
+ * PARAMETERS: walk_state - Current walk state object
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Initialize the data structures that hold the method's arguments
+ * and locals. The data struct is an array of NTEs for each.
+ * This allows ref_of and de_ref_of to work properly for these
+ * special data types.
+ *
+ * NOTES: walk_state fields are initialized to zero by the
+ * ACPI_MEM_CALLOCATE().
+ *
+ * A pseudo-Namespace Node is assigned to each argument and local
+ * so that ref_of() can return a pointer to the Node.
+ *
+ ******************************************************************************/
+
+void
+acpi_ds_method_data_init (
+ struct acpi_walk_state *walk_state)
+{
+ u32 i;
+
+
+ ACPI_FUNCTION_TRACE ("ds_method_data_init");
+
+
+ /* Init the method arguments */
+
+ for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) {
+ ACPI_MOVE_32_TO_32 (&walk_state->arguments[i].name,
+ NAMEOF_ARG_NTE);
+ walk_state->arguments[i].name.integer |= (i << 24);
+ walk_state->arguments[i].descriptor = ACPI_DESC_TYPE_NAMED;
+ walk_state->arguments[i].type = ACPI_TYPE_ANY;
+ walk_state->arguments[i].flags = ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_ARG;
+ }
+
+ /* Init the method locals */
+
+ for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++) {
+ ACPI_MOVE_32_TO_32 (&walk_state->local_variables[i].name,
+ NAMEOF_LOCAL_NTE);
+
+ walk_state->local_variables[i].name.integer |= (i << 24);
+ walk_state->local_variables[i].descriptor = ACPI_DESC_TYPE_NAMED;
+ walk_state->local_variables[i].type = ACPI_TYPE_ANY;
+ walk_state->local_variables[i].flags = ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_LOCAL;
+ }
+
+ return_VOID;
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_method_data_delete_all
+ *
+ * PARAMETERS: walk_state - Current walk state object
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Delete method locals and arguments. Arguments are only
+ * deleted if this method was called from another method.
+ *
+ ******************************************************************************/
+
+void
+acpi_ds_method_data_delete_all (
+ struct acpi_walk_state *walk_state)
+{
+ u32 index;
+
+
+ ACPI_FUNCTION_TRACE ("ds_method_data_delete_all");
+
+
+ /* Detach the locals */
+
+ for (index = 0; index < ACPI_METHOD_NUM_LOCALS; index++) {
+ if (walk_state->local_variables[index].object) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Deleting Local%d=%p\n",
+ index, walk_state->local_variables[index].object));
+
+ /* Detach object (if present) and remove a reference */
+
+ acpi_ns_detach_object (&walk_state->local_variables[index]);
+ }
+ }
+
+ /* Detach the arguments */
+
+ for (index = 0; index < ACPI_METHOD_NUM_ARGS; index++) {
+ if (walk_state->arguments[index].object) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Deleting Arg%d=%p\n",
+ index, walk_state->arguments[index].object));
+
+ /* Detach object (if present) and remove a reference */
+
+ acpi_ns_detach_object (&walk_state->arguments[index]);
+ }
+ }
+
+ return_VOID;
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_method_data_init_args
+ *
+ * PARAMETERS: *Params - Pointer to a parameter list for the method
+ * max_param_count - The arg count for this method
+ * walk_state - Current walk state object
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Initialize arguments for a method. The parameter list is a list
+ * of ACPI operand objects, either null terminated or whose length
+ * is defined by max_param_count.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_method_data_init_args (
+ union acpi_operand_object **params,
+ u32 max_param_count,
+ struct acpi_walk_state *walk_state)
+{
+ acpi_status status;
+ u32 index = 0;
+
+
+ ACPI_FUNCTION_TRACE_PTR ("ds_method_data_init_args", params);
+
+
+ if (!params) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "No param list passed to method\n"));
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ /* Copy passed parameters into the new method stack frame */
+
+ while ((index < ACPI_METHOD_NUM_ARGS) && (index < max_param_count) && params[index]) {
+ /*
+ * A valid parameter.
+ * Store the argument in the method/walk descriptor.
+ * Do not copy the arg in order to implement call by reference
+ */
+ status = acpi_ds_method_data_set_value (AML_ARG_OP, index, params[index], walk_state);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ index++;
+ }
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%d args passed to method\n", index));
+ return_ACPI_STATUS (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_method_data_get_node
+ *
+ * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
+ * Index - which local_var or argument whose type
+ * to get
+ * walk_state - Current walk state object
+ *
+ * RETURN: Get the Node associated with a local or arg.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_method_data_get_node (
+ u16 opcode,
+ u32 index,
+ struct acpi_walk_state *walk_state,
+ struct acpi_namespace_node **node)
+{
+ ACPI_FUNCTION_TRACE ("ds_method_data_get_node");
+
+
+ /*
+ * Method Locals and Arguments are supported
+ */
+ switch (opcode) {
+ case AML_LOCAL_OP:
+
+ if (index > ACPI_METHOD_MAX_LOCAL) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Local index %d is invalid (max %d)\n",
+ index, ACPI_METHOD_MAX_LOCAL));
+ return_ACPI_STATUS (AE_AML_INVALID_INDEX);
+ }
+
+ /* Return a pointer to the pseudo-node */
+
+ *node = &walk_state->local_variables[index];
+ break;
+
+ case AML_ARG_OP:
+
+ if (index > ACPI_METHOD_MAX_ARG) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Arg index %d is invalid (max %d)\n",
+ index, ACPI_METHOD_MAX_ARG));
+ return_ACPI_STATUS (AE_AML_INVALID_INDEX);
+ }
+
+ /* Return a pointer to the pseudo-node */
+
+ *node = &walk_state->arguments[index];
+ break;
+
+ default:
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Opcode %d is invalid\n", opcode));
+ return_ACPI_STATUS (AE_AML_BAD_OPCODE);
+ }
+
+ return_ACPI_STATUS (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_method_data_set_value
+ *
+ * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
+ * Index - which local_var or argument to get
+ * Object - Object to be inserted into the stack entry
+ * walk_state - Current walk state object
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Insert an object onto the method stack at entry Opcode:Index.
+ * Note: There is no "implicit conversion" for locals.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_method_data_set_value (
+ u16 opcode,
+ u32 index,
+ union acpi_operand_object *object,
+ struct acpi_walk_state *walk_state)
+{
+ acpi_status status;
+ struct acpi_namespace_node *node;
+
+
+ ACPI_FUNCTION_TRACE ("ds_method_data_set_value");
+
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
+ "new_obj %p Opcode %X, Refs=%d [%s]\n", object,
+ opcode, object->common.reference_count,
+ acpi_ut_get_type_name (object->common.type)));
+
+ /* Get the namespace node for the arg/local */
+
+ status = acpi_ds_method_data_get_node (opcode, index, walk_state, &node);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ /*
+ * Increment ref count so object can't be deleted while installed.
+ * NOTE: We do not copy the object in order to preserve the call by
+ * reference semantics of ACPI Control Method invocation.
+ * (See ACPI specification 2.0_c)
+ */
+ acpi_ut_add_reference (object);
+
+ /* Install the object */
+
+ node->object = object;
+ return_ACPI_STATUS (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_method_data_get_type
+ *
+ * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
+ * Index - which local_var or argument whose type
+ * to get
+ * walk_state - Current walk state object
+ *
+ * RETURN: Data type of current value of the selected Arg or Local
+ *
+ ******************************************************************************/
+#ifdef ACPI_FUTURE_USAGE
+acpi_object_type
+acpi_ds_method_data_get_type (
+ u16 opcode,
+ u32 index,
+ struct acpi_walk_state *walk_state)
+{
+ acpi_status status;
+ struct acpi_namespace_node *node;
+ union acpi_operand_object *object;
+
+
+ ACPI_FUNCTION_TRACE ("ds_method_data_get_type");
+
+
+ /* Get the namespace node for the arg/local */
+
+ status = acpi_ds_method_data_get_node (opcode, index, walk_state, &node);
+ if (ACPI_FAILURE (status)) {
+ return_VALUE ((ACPI_TYPE_NOT_FOUND));
+ }
+
+ /* Get the object */
+
+ object = acpi_ns_get_attached_object (node);
+ if (!object) {
+ /* Uninitialized local/arg, return TYPE_ANY */
+
+ return_VALUE (ACPI_TYPE_ANY);
+ }
+
+ /* Get the object type */
+
+ return_VALUE (ACPI_GET_OBJECT_TYPE (object));
+}
+#endif /* ACPI_FUTURE_USAGE */
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_method_data_get_value
+ *
+ * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
+ * Index - which local_var or argument to get
+ * walk_state - Current walk state object
+ * *dest_desc - Ptr to Descriptor into which selected Arg
+ * or Local value should be copied
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Retrieve value of selected Arg or Local from the method frame
+ * at the current top of the method stack.
+ * Used only in acpi_ex_resolve_to_value().
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_method_data_get_value (
+ u16 opcode,
+ u32 index,
+ struct acpi_walk_state *walk_state,
+ union acpi_operand_object **dest_desc)
+{
+ acpi_status status;
+ struct acpi_namespace_node *node;
+ union acpi_operand_object *object;
+
+
+ ACPI_FUNCTION_TRACE ("ds_method_data_get_value");
+
+
+ /* Validate the object descriptor */
+
+ if (!dest_desc) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null object descriptor pointer\n"));
+ return_ACPI_STATUS (AE_BAD_PARAMETER);
+ }
+
+ /* Get the namespace node for the arg/local */
+
+ status = acpi_ds_method_data_get_node (opcode, index, walk_state, &node);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ /* Get the object from the node */
+
+ object = node->object;
+
+ /* Examine the returned object, it must be valid. */
+
+ if (!object) {
+ /*
+ * Index points to uninitialized object.
+ * This means that either 1) The expected argument was
+ * not passed to the method, or 2) A local variable
+ * was referenced by the method (via the ASL)
+ * before it was initialized. Either case is an error.
+ */
+
+ /* If slack enabled, init the local_x/arg_x to an Integer of value zero */
+
+ if (acpi_gbl_enable_interpreter_slack) {
+ object = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
+ if (!object) {
+ return_ACPI_STATUS (AE_NO_MEMORY);
+ }
+
+ object->integer.value = 0;
+ node->object = object;
+ }
+
+ /* Otherwise, return the error */
+
+ else switch (opcode) {
+ case AML_ARG_OP:
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Uninitialized Arg[%d] at node %p\n",
+ index, node));
+
+ return_ACPI_STATUS (AE_AML_UNINITIALIZED_ARG);
+
+ case AML_LOCAL_OP:
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Uninitialized Local[%d] at node %p\n",
+ index, node));
+
+ return_ACPI_STATUS (AE_AML_UNINITIALIZED_LOCAL);
+
+ default:
+ ACPI_REPORT_ERROR (("Not Arg/Local opcode: %X\n", opcode));
+ return_ACPI_STATUS (AE_AML_INTERNAL);
+ }
+ }
+
+ /*
+ * The Index points to an initialized and valid object.
+ * Return an additional reference to the object
+ */
+ *dest_desc = object;
+ acpi_ut_add_reference (object);
+
+ return_ACPI_STATUS (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_method_data_delete_value
+ *
+ * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
+ * Index - which local_var or argument to delete
+ * walk_state - Current walk state object
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Delete the entry at Opcode:Index on the method stack. Inserts
+ * a null into the stack slot after the object is deleted.
+ *
+ ******************************************************************************/
+
+void
+acpi_ds_method_data_delete_value (
+ u16 opcode,
+ u32 index,
+ struct acpi_walk_state *walk_state)
+{
+ acpi_status status;
+ struct acpi_namespace_node *node;
+ union acpi_operand_object *object;
+
+
+ ACPI_FUNCTION_TRACE ("ds_method_data_delete_value");
+
+
+ /* Get the namespace node for the arg/local */
+
+ status = acpi_ds_method_data_get_node (opcode, index, walk_state, &node);
+ if (ACPI_FAILURE (status)) {
+ return_VOID;
+ }
+
+ /* Get the associated object */
+
+ object = acpi_ns_get_attached_object (node);
+
+ /*
+ * Undefine the Arg or Local by setting its descriptor
+ * pointer to NULL. Locals/Args can contain both
+ * ACPI_OPERAND_OBJECTS and ACPI_NAMESPACE_NODEs
+ */
+ node->object = NULL;
+
+ if ((object) &&
+ (ACPI_GET_DESCRIPTOR_TYPE (object) == ACPI_DESC_TYPE_OPERAND)) {
+ /*
+ * There is a valid object.
+ * Decrement the reference count by one to balance the
+ * increment when the object was stored.
+ */
+ acpi_ut_remove_reference (object);
+ }
+
+ return_VOID;
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_store_object_to_local
+ *
+ * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
+ * Index - which local_var or argument to set
+ * obj_desc - Value to be stored
+ * walk_state - Current walk state
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Store a value in an Arg or Local. The obj_desc is installed
+ * as the new value for the Arg or Local and the reference count
+ * for obj_desc is incremented.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_store_object_to_local (
+ u16 opcode,
+ u32 index,
+ union acpi_operand_object *obj_desc,
+ struct acpi_walk_state *walk_state)
+{
+ acpi_status status;
+ struct acpi_namespace_node *node;
+ union acpi_operand_object *current_obj_desc;
+ union acpi_operand_object *new_obj_desc;
+
+
+ ACPI_FUNCTION_TRACE ("ds_store_object_to_local");
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Opcode=%X Index=%d Obj=%p\n",
+ opcode, index, obj_desc));
+
+ /* Parameter validation */
+
+ if (!obj_desc) {
+ return_ACPI_STATUS (AE_BAD_PARAMETER);
+ }
+
+ /* Get the namespace node for the arg/local */
+
+ status = acpi_ds_method_data_get_node (opcode, index, walk_state, &node);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ current_obj_desc = acpi_ns_get_attached_object (node);
+ if (current_obj_desc == obj_desc) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p already installed!\n",
+ obj_desc));
+ return_ACPI_STATUS (status);
+ }
+
+ /*
+ * If the reference count on the object is more than one, we must
+ * take a copy of the object before we store. A reference count
+ * of exactly 1 means that the object was just created during the
+ * evaluation of an expression, and we can safely use it since it
+ * is not used anywhere else.
+ */
+ new_obj_desc = obj_desc;
+ if (obj_desc->common.reference_count > 1) {
+ status = acpi_ut_copy_iobject_to_iobject (obj_desc, &new_obj_desc, walk_state);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+ }
+
+ /*
+ * If there is an object already in this slot, we either
+ * have to delete it, or if this is an argument and there
+ * is an object reference stored there, we have to do
+ * an indirect store!
+ */
+ if (current_obj_desc) {
+ /*
+ * Check for an indirect store if an argument
+ * contains an object reference (stored as an Node).
+ * We don't allow this automatic dereferencing for
+ * locals, since a store to a local should overwrite
+ * anything there, including an object reference.
+ *
+ * If both Arg0 and Local0 contain ref_of (Local4):
+ *
+ * Store (1, Arg0) - Causes indirect store to local4
+ * Store (1, Local0) - Stores 1 in local0, overwriting
+ * the reference to local4
+ * Store (1, de_refof (Local0)) - Causes indirect store to local4
+ *
+ * Weird, but true.
+ */
+ if (opcode == AML_ARG_OP) {
+ /*
+ * Make sure that the object is the correct type. This may be overkill, but
+ * it is here because references were NS nodes in the past. Now they are
+ * operand objects of type Reference.
+ */
+ if (ACPI_GET_DESCRIPTOR_TYPE (current_obj_desc) != ACPI_DESC_TYPE_OPERAND) {
+ ACPI_REPORT_ERROR (("Invalid descriptor type while storing to method arg: [%s]\n",
+ acpi_ut_get_descriptor_name (current_obj_desc)));
+ return_ACPI_STATUS (AE_AML_INTERNAL);
+ }
+
+ /*
+ * If we have a valid reference object that came from ref_of(), do the
+ * indirect store
+ */
+ if ((current_obj_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE) &&
+ (current_obj_desc->reference.opcode == AML_REF_OF_OP)) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
+ "Arg (%p) is an obj_ref(Node), storing in node %p\n",
+ new_obj_desc, current_obj_desc));
+
+ /*
+ * Store this object to the Node (perform the indirect store)
+ * NOTE: No implicit conversion is performed, as per the ACPI
+ * specification rules on storing to Locals/Args.
+ */
+ status = acpi_ex_store_object_to_node (new_obj_desc,
+ current_obj_desc->reference.object, walk_state,
+ ACPI_NO_IMPLICIT_CONVERSION);
+
+ /* Remove local reference if we copied the object above */
+
+ if (new_obj_desc != obj_desc) {
+ acpi_ut_remove_reference (new_obj_desc);
+ }
+ return_ACPI_STATUS (status);
+ }
+ }
+
+ /*
+ * Delete the existing object
+ * before storing the new one
+ */
+ acpi_ds_method_data_delete_value (opcode, index, walk_state);
+ }
+
+ /*
+ * Install the Obj descriptor (*new_obj_desc) into
+ * the descriptor for the Arg or Local.
+ * (increments the object reference count by one)
+ */
+ status = acpi_ds_method_data_set_value (opcode, index, new_obj_desc, walk_state);
+
+ /* Remove local reference if we copied the object above */
+
+ if (new_obj_desc != obj_desc) {
+ acpi_ut_remove_reference (new_obj_desc);
+ }
+
+ return_ACPI_STATUS (status);
+}
+
+
diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c
new file mode 100644
index 00000000000..eb8af4785bc
--- /dev/null
+++ b/drivers/acpi/dispatcher/dsobject.c
@@ -0,0 +1,618 @@
+/******************************************************************************
+ *
+ * Module Name: dsobject - Dispatcher object management routines
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2005, R. Byron Moore
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+
+#include <acpi/acpi.h>
+#include <acpi/acparser.h>
+#include <acpi/amlcode.h>
+#include <acpi/acdispat.h>
+#include <acpi/acnamesp.h>
+#include <acpi/acinterp.h>
+
+#define _COMPONENT ACPI_DISPATCHER
+ ACPI_MODULE_NAME ("dsobject")
+
+
+#ifndef ACPI_NO_METHOD_EXECUTION
+/*****************************************************************************
+ *
+ * FUNCTION: acpi_ds_build_internal_object
+ *
+ * PARAMETERS: walk_state - Current walk state
+ * Op - Parser object to be translated
+ * obj_desc_ptr - Where the ACPI internal object is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Translate a parser Op object to the equivalent namespace object
+ * Simple objects are any objects other than a package object!
+ *
+ ****************************************************************************/
+
+acpi_status
+acpi_ds_build_internal_object (
+ struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op,
+ union acpi_operand_object **obj_desc_ptr)
+{
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
+
+
+ ACPI_FUNCTION_TRACE ("ds_build_internal_object");
+
+
+ *obj_desc_ptr = NULL;
+ if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
+ /*
+ * This is an named object reference. If this name was
+ * previously looked up in the namespace, it was stored in this op.
+ * Otherwise, go ahead and look it up now
+ */
+ if (!op->common.node) {
+ status = acpi_ns_lookup (walk_state->scope_info, op->common.value.string,
+ ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
+ ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL,
+ (struct acpi_namespace_node **) &(op->common.node));
+
+ if (ACPI_FAILURE (status)) {
+ ACPI_REPORT_NSERROR (op->common.value.string, status);
+ return_ACPI_STATUS (status);
+ }
+ }
+ }
+
+ /* Create and init the internal ACPI object */
+
+ obj_desc = acpi_ut_create_internal_object ((acpi_ps_get_opcode_info (op->common.aml_opcode))->object_type);
+ if (!obj_desc) {
+ return_ACPI_STATUS (AE_NO_MEMORY);
+ }
+
+ status = acpi_ds_init_object_from_op (walk_state, op, op->common.aml_opcode, &obj_desc);
+ if (ACPI_FAILURE (status)) {
+ acpi_ut_remove_reference (obj_desc);
+ return_ACPI_STATUS (status);
+ }
+
+ *obj_desc_ptr = obj_desc;
+ return_ACPI_STATUS (AE_OK);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION: acpi_ds_build_internal_buffer_obj
+ *
+ * PARAMETERS: walk_state - Current walk state
+ * Op - Parser object to be translated
+ * buffer_length - Length of the buffer
+ * obj_desc_ptr - Where the ACPI internal object is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Translate a parser Op package object to the equivalent
+ * namespace object
+ *
+ ****************************************************************************/
+
+acpi_status
+acpi_ds_build_internal_buffer_obj (
+ struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op,
+ u32 buffer_length,
+ union acpi_operand_object **obj_desc_ptr)
+{
+ union acpi_parse_object *arg;
+ union acpi_operand_object *obj_desc;
+ union acpi_parse_object *byte_list;
+ u32 byte_list_length = 0;
+
+
+ ACPI_FUNCTION_TRACE ("ds_build_internal_buffer_obj");
+
+
+ obj_desc = *obj_desc_ptr;
+ if (obj_desc) {
+ /*
+ * We are evaluating a Named buffer object "Name (xxxx, Buffer)".
+ * The buffer object already exists (from the NS node)
+ */
+ }
+ else {
+ /* Create a new buffer object */
+
+ obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER);
+ *obj_desc_ptr = obj_desc;
+ if (!obj_desc) {
+ return_ACPI_STATUS (AE_NO_MEMORY);
+ }
+ }
+
+ /*
+ * Second arg is the buffer data (optional) byte_list can be either
+ * individual bytes or a string initializer. In either case, a
+ * byte_list appears in the AML.
+ */
+ arg = op->common.value.arg; /* skip first arg */
+
+ byte_list = arg->named.next;
+ if (byte_list) {
+ if (byte_list->common.aml_opcode != AML_INT_BYTELIST_OP) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+ "Expecting bytelist, got AML opcode %X in op %p\n",
+ byte_list->common.aml_opcode, byte_list));
+
+ acpi_ut_remove_reference (obj_desc);
+ return (AE_TYPE);
+ }
+
+ byte_list_length = (u32) byte_list->common.value.integer;
+ }
+
+ /*
+ * The buffer length (number of bytes) will be the larger of:
+ * 1) The specified buffer length and
+ * 2) The length of the initializer byte list
+ */
+ obj_desc->buffer.length = buffer_length;
+ if (byte_list_length > buffer_length) {
+ obj_desc->buffer.length = byte_list_length;
+ }
+
+ /* Allocate the buffer */
+
+ if (obj_desc->buffer.length == 0) {
+ obj_desc->buffer.pointer = NULL;
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
+ "Buffer defined with zero length in AML, creating\n"));
+ }
+ else {
+ obj_desc->buffer.pointer = ACPI_MEM_CALLOCATE (
+ obj_desc->buffer.length);
+ if (!obj_desc->buffer.pointer) {
+ acpi_ut_delete_object_desc (obj_desc);
+ return_ACPI_STATUS (AE_NO_MEMORY);
+ }
+
+ /* Initialize buffer from the byte_list (if present) */
+
+ if (byte_list) {
+ ACPI_MEMCPY (obj_desc->buffer.pointer, byte_list->named.data,
+ byte_list_length);
+ }
+ }
+
+ obj_desc->buffer.flags |= AOPOBJ_DATA_VALID;
+ op->common.node = (struct acpi_namespace_node *) obj_desc;
+ return_ACPI_STATUS (AE_OK);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION: acpi_ds_build_internal_package_obj
+ *
+ * PARAMETERS: walk_state - Current walk state
+ * Op - Parser object to be translated
+ * package_length - Number of elements in the package
+ * obj_desc_ptr - Where the ACPI internal object is returned
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Translate a parser Op package object to the equivalent
+ * namespace object
+ *
+ ****************************************************************************/
+
+acpi_status
+acpi_ds_build_internal_package_obj (
+ struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op,
+ u32 package_length,
+ union acpi_operand_object **obj_desc_ptr)
+{
+ union acpi_parse_object *arg;
+ union acpi_parse_object *parent;
+ union acpi_operand_object *obj_desc = NULL;
+ u32 package_list_length;
+ acpi_status status = AE_OK;
+ u32 i;
+
+
+ ACPI_FUNCTION_TRACE ("ds_build_internal_package_obj");
+
+
+ /* Find the parent of a possibly nested package */
+
+ parent = op->common.parent;
+ while ((parent->common.aml_opcode == AML_PACKAGE_OP) ||
+ (parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) {
+ parent = parent->common.parent;
+ }
+
+ obj_desc = *obj_desc_ptr;
+ if (obj_desc) {
+ /*
+ * We are evaluating a Named package object "Name (xxxx, Package)".
+ * Get the existing package object from the NS node
+ */
+ }
+ else {
+ obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_PACKAGE);
+ *obj_desc_ptr = obj_desc;
+ if (!obj_desc) {
+ return_ACPI_STATUS (AE_NO_MEMORY);
+ }
+
+ obj_desc->package.node = parent->common.node;
+ }
+
+ obj_desc->package.count = package_length;
+
+ /* Count the number of items in the package list */
+
+ package_list_length = 0;
+ arg = op->common.value.arg;
+ arg = arg->common.next;
+ while (arg) {
+ package_list_length++;
+ arg = arg->common.next;
+ }
+
+ /*
+ * The package length (number of elements) will be the greater
+ * of the specified length and the length of the initializer list
+ */
+ if (package_list_length > package_length) {
+ obj_desc->package.count = package_list_length;
+ }
+
+ /*
+ * Allocate the pointer array (array of pointers to the
+ * individual objects). Add an extra pointer slot so
+ * that the list is always null terminated.
+ */
+ obj_desc->package.elements = ACPI_MEM_CALLOCATE (
+ ((acpi_size) obj_desc->package.count + 1) * sizeof (void *));
+
+ if (!obj_desc->package.elements) {
+ acpi_ut_delete_object_desc (obj_desc);
+ return_ACPI_STATUS (AE_NO_MEMORY);
+ }
+
+ /*
+ * Now init the elements of the package
+ */
+ i = 0;
+ arg = op->common.value.arg;
+ arg = arg->common.next;
+ while (arg) {
+ if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) {
+ /* Object (package or buffer) is already built */
+
+ obj_desc->package.elements[i] = ACPI_CAST_PTR (union acpi_operand_object, arg->common.node);
+ }
+ else {
+ status = acpi_ds_build_internal_object (walk_state, arg,
+ &obj_desc->package.elements[i]);
+ }
+
+ i++;
+ arg = arg->common.next;
+ }
+
+ obj_desc->package.flags |= AOPOBJ_DATA_VALID;
+ op->common.node = (struct acpi_namespace_node *) obj_desc;
+ return_ACPI_STATUS (status);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION: acpi_ds_create_node
+ *
+ * PARAMETERS: walk_state - Current walk state
+ * Node - NS Node to be initialized
+ * Op - Parser object to be translated
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Create the object to be associated with a namespace node
+ *
+ ****************************************************************************/
+
+acpi_status
+acpi_ds_create_node (
+ struct acpi_walk_state *walk_state,
+ struct acpi_namespace_node *node,
+ union acpi_parse_object *op)
+{
+ acpi_status status;
+ union acpi_operand_object *obj_desc;
+
+
+ ACPI_FUNCTION_TRACE_PTR ("ds_create_node", op);
+
+
+ /*
+ * Because of the execution pass through the non-control-method
+ * parts of the table, we can arrive here twice. Only init
+ * the named object node the first time through
+ */
+ if (acpi_ns_get_attached_object (node)) {
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ if (!op->common.value.arg) {
+ /* No arguments, there is nothing to do */
+
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ /* Build an internal object for the argument(s) */
+
+ status = acpi_ds_build_internal_object (walk_state, op->common.value.arg, &obj_desc);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ /* Re-type the object according to its argument */
+
+ node->type = ACPI_GET_OBJECT_TYPE (obj_desc);
+
+ /* Attach obj to node */
+
+ status = acpi_ns_attach_object (node, obj_desc, node->type);
+
+ /* Remove local reference to the object */
+
+ acpi_ut_remove_reference (obj_desc);
+ return_ACPI_STATUS (status);
+}
+
+#endif /* ACPI_NO_METHOD_EXECUTION */
+
+
+/*****************************************************************************
+ *
+ * FUNCTION: acpi_ds_init_object_from_op
+ *
+ * PARAMETERS: walk_state - Current walk state
+ * Op - Parser op used to init the internal object
+ * Opcode - AML opcode associated with the object
+ * ret_obj_desc - Namespace object to be initialized
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Initialize a namespace object from a parser Op and its
+ * associated arguments. The namespace object is a more compact
+ * representation of the Op and its arguments.
+ *
+ ****************************************************************************/
+
+acpi_status
+acpi_ds_init_object_from_op (
+ struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op,
+ u16 opcode,
+ union acpi_operand_object **ret_obj_desc)
+{
+ const struct acpi_opcode_info *op_info;
+ union acpi_operand_object *obj_desc;
+ acpi_status status = AE_OK;
+
+
+ ACPI_FUNCTION_TRACE ("ds_init_object_from_op");
+
+
+ obj_desc = *ret_obj_desc;
+ op_info = acpi_ps_get_opcode_info (opcode);
+ if (op_info->class == AML_CLASS_UNKNOWN) {
+ /* Unknown opcode */
+
+ return_ACPI_STATUS (AE_TYPE);
+ }
+
+ /* Perform per-object initialization */
+
+ switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
+ case ACPI_TYPE_BUFFER:
+
+ /*
+ * Defer evaluation of Buffer term_arg operand
+ */
+ obj_desc->buffer.node = (struct acpi_namespace_node *) walk_state->operands[0];
+ obj_desc->buffer.aml_start = op->named.data;
+ obj_desc->buffer.aml_length = op->named.length;
+ break;
+
+
+ case ACPI_TYPE_PACKAGE:
+
+ /*
+ * Defer evaluation of Package term_arg operand
+ */
+ obj_desc->package.node = (struct acpi_namespace_node *) walk_state->operands[0];
+ obj_desc->package.aml_start = op->named.data;
+ obj_desc->package.aml_length = op->named.length;
+ break;
+
+
+ case ACPI_TYPE_INTEGER:
+
+ switch (op_info->type) {
+ case AML_TYPE_CONSTANT:
+ /*
+ * Resolve AML Constants here - AND ONLY HERE!
+ * All constants are integers.
+ * We mark the integer with a flag that indicates that it started life
+ * as a constant -- so that stores to constants will perform as expected (noop).
+ * (zero_op is used as a placeholder for optional target operands.)
+ */
+ obj_desc->common.flags = AOPOBJ_AML_CONSTANT;
+
+ switch (opcode) {
+ case AML_ZERO_OP:
+
+ obj_desc->integer.value = 0;
+ break;
+
+ case AML_ONE_OP:
+
+ obj_desc->integer.value = 1;
+ break;
+
+ case AML_ONES_OP:
+
+ obj_desc->integer.value = ACPI_INTEGER_MAX;
+
+ /* Truncate value if we are executing from a 32-bit ACPI table */
+
+#ifndef ACPI_NO_METHOD_EXECUTION
+ acpi_ex_truncate_for32bit_table (obj_desc);
+#endif
+ break;
+
+ case AML_REVISION_OP:
+
+ obj_desc->integer.value = ACPI_CA_VERSION;
+ break;
+
+ default:
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown constant opcode %X\n", opcode));
+ status = AE_AML_OPERAND_TYPE;
+ break;
+ }
+ break;
+
+
+ case AML_TYPE_LITERAL:
+
+ obj_desc->integer.value = op->common.value.integer;
+ break;
+
+
+ default:
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Integer type %X\n", op_info->type));
+ status = AE_AML_OPERAND_TYPE;
+ break;
+ }
+ break;
+
+
+ case ACPI_TYPE_STRING:
+
+ obj_desc->string.pointer = op->common.value.string;
+ obj_desc->string.length = (u32) ACPI_STRLEN (op->common.value.string);
+
+ /*
+ * The string is contained in the ACPI table, don't ever try
+ * to delete it
+ */
+ obj_desc->common.flags |= AOPOBJ_STATIC_POINTER;
+ break;
+
+
+ case ACPI_TYPE_METHOD:
+ break;
+
+
+ case ACPI_TYPE_LOCAL_REFERENCE:
+
+ switch (op_info->type) {
+ case AML_TYPE_LOCAL_VARIABLE:
+
+ /* Split the opcode into a base opcode + offset */
+
+ obj_desc->reference.opcode = AML_LOCAL_OP;
+ obj_desc->reference.offset = opcode - AML_LOCAL_OP;
+
+#ifndef ACPI_NO_METHOD_EXECUTION
+ status = acpi_ds_method_data_get_node (AML_LOCAL_OP, obj_desc->reference.offset,
+ walk_state, (struct acpi_namespace_node **) &obj_desc->reference.object);
+#endif
+ break;
+
+
+ case AML_TYPE_METHOD_ARGUMENT:
+
+ /* Split the opcode into a base opcode + offset */
+
+ obj_desc->reference.opcode = AML_ARG_OP;
+ obj_desc->reference.offset = opcode - AML_ARG_OP;
+
+#ifndef ACPI_NO_METHOD_EXECUTION
+ status = acpi_ds_method_data_get_node (AML_ARG_OP, obj_desc->reference.offset,
+ walk_state, (struct acpi_namespace_node **) &obj_desc->reference.object);
+#endif
+ break;
+
+ default: /* Other literals, etc.. */
+
+ if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
+ /* Node was saved in Op */
+
+ obj_desc->reference.node = op->common.node;
+ }
+
+ obj_desc->reference.opcode = opcode;
+ break;
+ }
+ break;
+
+
+ default:
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unimplemented data type: %X\n",
+ ACPI_GET_OBJECT_TYPE (obj_desc)));
+
+ status = AE_AML_OPERAND_TYPE;
+ break;
+ }
+
+ return_ACPI_STATUS (status);
+}
+
+
diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c
new file mode 100644
index 00000000000..5c987a0e7b7
--- /dev/null
+++ b/drivers/acpi/dispatcher/dsopcode.c
@@ -0,0 +1,1151 @@
+/******************************************************************************
+ *
+ * Module Name: dsopcode - Dispatcher Op Region support and handling of
+ * "control" opcodes
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2005, R. Byron Moore
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+
+#include <acpi/acpi.h>
+#include <acpi/acparser.h>
+#include <acpi/amlcode.h>
+#include <acpi/acdispat.h>
+#include <acpi/acinterp.h>
+#include <acpi/acnamesp.h>
+#include <acpi/acevents.h>
+
+#define _COMPONENT ACPI_DISPATCHER
+ ACPI_MODULE_NAME ("dsopcode")
+
+
+/*****************************************************************************
+ *
+ * FUNCTION: acpi_ds_execute_arguments
+ *
+ * PARAMETERS: Node - Parent NS node
+ * aml_length - Length of executable AML
+ * aml_start - Pointer to the AML
+ *
+ * RETURN: Status.
+ *
+ * DESCRIPTION: Late (deferred) execution of region or field arguments
+ *
+ ****************************************************************************/
+
+acpi_status
+acpi_ds_execute_arguments (
+ struct acpi_namespace_node *node,
+ struct acpi_namespace_node *scope_node,
+ u32 aml_length,
+ u8 *aml_start)
+{
+ acpi_status status;
+ union acpi_parse_object *op;
+ struct acpi_walk_state *walk_state;
+
+
+ ACPI_FUNCTION_TRACE ("ds_execute_arguments");
+
+
+ /*
+ * Allocate a new parser op to be the root of the parsed tree
+ */
+ op = acpi_ps_alloc_op (AML_INT_EVAL_SUBTREE_OP);
+ if (!op) {
+ return_ACPI_STATUS (AE_NO_MEMORY);
+ }
+
+ /* Save the Node for use in acpi_ps_parse_aml */
+
+ op->common.node = scope_node;
+
+ /* Create and initialize a new parser state */
+
+ walk_state = acpi_ds_create_walk_state (0, NULL, NULL, NULL);
+ if (!walk_state) {
+ return_ACPI_STATUS (AE_NO_MEMORY);
+ }
+
+ status = acpi_ds_init_aml_walk (walk_state, op, NULL, aml_start,
+ aml_length, NULL, 1);
+ if (ACPI_FAILURE (status)) {
+ acpi_ds_delete_walk_state (walk_state);
+ return_ACPI_STATUS (status);
+ }
+
+ /* Mark this parse as a deferred opcode */
+
+ walk_state->parse_flags = ACPI_PARSE_DEFERRED_OP;
+ walk_state->deferred_node = node;
+
+ /* Pass1: Parse the entire declaration */
+
+ status = acpi_ps_parse_aml (walk_state);
+ if (ACPI_FAILURE (status)) {
+ acpi_ps_delete_parse_tree (op);
+ return_ACPI_STATUS (status);
+ }
+
+ /* Get and init the Op created above */
+
+ op->common.node = node;
+ acpi_ps_delete_parse_tree (op);
+
+ /* Evaluate the deferred arguments */
+
+ op = acpi_ps_alloc_op (AML_INT_EVAL_SUBTREE_OP);
+ if (!op) {
+ return_ACPI_STATUS (AE_NO_MEMORY);
+ }
+
+ op->common.node = scope_node;
+
+ /* Create and initialize a new parser state */
+
+ walk_state = acpi_ds_create_walk_state (0, NULL, NULL, NULL);
+ if (!walk_state) {
+ return_ACPI_STATUS (AE_NO_MEMORY);
+ }
+
+ /* Execute the opcode and arguments */
+
+ status = acpi_ds_init_aml_walk (walk_state, op, NULL, aml_start,
+ aml_length, NULL, 3);
+ if (ACPI_FAILURE (status)) {
+ acpi_ds_delete_walk_state (walk_state);
+ return_ACPI_STATUS (status);
+ }
+
+ /* Mark this execution as a deferred opcode */
+
+ walk_state->deferred_node = node;
+ status = acpi_ps_parse_aml (walk_state);
+ acpi_ps_delete_parse_tree (op);
+ return_ACPI_STATUS (status);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION: acpi_ds_get_buffer_field_arguments
+ *
+ * PARAMETERS: obj_desc - A valid buffer_field object
+ *
+ * RETURN: Status.
+ *
+ * DESCRIPTION: Get buffer_field Buffer and Index. This implements the late
+ * evaluation of these field attributes.
+ *
+ ****************************************************************************/
+
+acpi_status
+acpi_ds_get_buffer_field_arguments (
+ union acpi_operand_object *obj_desc)
+{
+ union acpi_operand_object *extra_desc;
+ struct acpi_namespace_node *node;
+ acpi_status status;
+
+
+ ACPI_FUNCTION_TRACE_PTR ("ds_get_buffer_field_arguments", obj_desc);
+
+
+ if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ /* Get the AML pointer (method object) and buffer_field node */
+
+ extra_desc = acpi_ns_get_secondary_object (obj_desc);
+ node = obj_desc->buffer_field.node;
+
+ ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname (ACPI_TYPE_BUFFER_FIELD, node, NULL));
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] buffer_field Arg Init\n",
+ acpi_ut_get_node_name (node)));
+
+ /* Execute the AML code for the term_arg arguments */
+
+ status = acpi_ds_execute_arguments (node, acpi_ns_get_parent_node (node),
+ extra_desc->extra.aml_length, extra_desc->extra.aml_start);
+ return_ACPI_STATUS (status);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION: acpi_ds_get_buffer_arguments
+ *
+ * PARAMETERS: obj_desc - A valid Buffer object
+ *
+ * RETURN: Status.
+ *
+ * DESCRIPTION: Get Buffer length and initializer byte list. This implements
+ * the late evaluation of these attributes.
+ *
+ ****************************************************************************/
+
+acpi_status
+acpi_ds_get_buffer_arguments (
+ union acpi_operand_object *obj_desc)
+{
+ struct acpi_namespace_node *node;
+ acpi_status status;
+
+
+ ACPI_FUNCTION_TRACE_PTR ("ds_get_buffer_arguments", obj_desc);
+
+
+ if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ /* Get the Buffer node */
+
+ node = obj_desc->buffer.node;
+ if (!node) {
+ ACPI_REPORT_ERROR ((
+ "No pointer back to NS node in buffer obj %p\n", obj_desc));
+ return_ACPI_STATUS (AE_AML_INTERNAL);
+ }
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Buffer Arg Init\n"));
+
+ /* Execute the AML code for the term_arg arguments */
+
+ status = acpi_ds_execute_arguments (node, node,
+ obj_desc->buffer.aml_length, obj_desc->buffer.aml_start);
+ return_ACPI_STATUS (status);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION: acpi_ds_get_package_arguments
+ *
+ * PARAMETERS: obj_desc - A valid Package object
+ *
+ * RETURN: Status.
+ *
+ * DESCRIPTION: Get Package length and initializer byte list. This implements
+ * the late evaluation of these attributes.
+ *
+ ****************************************************************************/
+
+acpi_status
+acpi_ds_get_package_arguments (
+ union acpi_operand_object *obj_desc)
+{
+ struct acpi_namespace_node *node;
+ acpi_status status;
+
+
+ ACPI_FUNCTION_TRACE_PTR ("ds_get_package_arguments", obj_desc);
+
+
+ if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ /* Get the Package node */
+
+ node = obj_desc->package.node;
+ if (!node) {
+ ACPI_REPORT_ERROR ((
+ "No pointer back to NS node in package %p\n", obj_desc));
+ return_ACPI_STATUS (AE_AML_INTERNAL);
+ }
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Package Arg Init\n"));
+
+ /* Execute the AML code for the term_arg arguments */
+
+ status = acpi_ds_execute_arguments (node, node,
+ obj_desc->package.aml_length, obj_desc->package.aml_start);
+ return_ACPI_STATUS (status);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION: acpi_ds_get_region_arguments
+ *
+ * PARAMETERS: obj_desc - A valid region object
+ *
+ * RETURN: Status.
+ *
+ * DESCRIPTION: Get region address and length. This implements the late
+ * evaluation of these region attributes.
+ *
+ ****************************************************************************/
+
+acpi_status
+acpi_ds_get_region_arguments (
+ union acpi_operand_object *obj_desc)
+{
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ union acpi_operand_object *extra_desc;
+
+
+ ACPI_FUNCTION_TRACE_PTR ("ds_get_region_arguments", obj_desc);
+
+
+ if (obj_desc->region.flags & AOPOBJ_DATA_VALID) {
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ extra_desc = acpi_ns_get_secondary_object (obj_desc);
+ if (!extra_desc) {
+ return_ACPI_STATUS (AE_NOT_EXIST);
+ }
+
+ /* Get the Region node */
+
+ node = obj_desc->region.node;
+
+ ACPI_DEBUG_EXEC (acpi_ut_display_init_pathname (ACPI_TYPE_REGION, node, NULL));
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "[%4.4s] op_region Arg Init at AML %p\n",
+ acpi_ut_get_node_name (node), extra_desc->extra.aml_start));
+
+ /* Execute the argument AML */
+
+ status = acpi_ds_execute_arguments (node, acpi_ns_get_parent_node (node),
+ extra_desc->extra.aml_length, extra_desc->extra.aml_start);
+ return_ACPI_STATUS (status);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION: acpi_ds_initialize_region
+ *
+ * PARAMETERS: Op - A valid region Op object
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Front end to ev_initialize_region
+ *
+ ****************************************************************************/
+
+acpi_status
+acpi_ds_initialize_region (
+ acpi_handle obj_handle)
+{
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
+
+
+ obj_desc = acpi_ns_get_attached_object (obj_handle);
+
+ /* Namespace is NOT locked */
+
+ status = acpi_ev_initialize_region (obj_desc, FALSE);
+ return (status);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION: acpi_ds_init_buffer_field
+ *
+ * PARAMETERS: aml_opcode - create_xxx_field
+ * obj_desc - buffer_field object
+ * buffer_desc - Host Buffer
+ * offset_desc - Offset into buffer
+ * Length - Length of field (CREATE_FIELD_OP only)
+ * Result - Where to store the result
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Perform actual initialization of a buffer field
+ *
+ ****************************************************************************/
+
+acpi_status
+acpi_ds_init_buffer_field (
+ u16 aml_opcode,
+ union acpi_operand_object *obj_desc,
+ union acpi_operand_object *buffer_desc,
+ union acpi_operand_object *offset_desc,
+ union acpi_operand_object *length_desc,
+ union acpi_operand_object *result_desc)
+{
+ u32 offset;
+ u32 bit_offset;
+ u32 bit_count;
+ u8 field_flags;
+ acpi_status status;
+
+
+ ACPI_FUNCTION_TRACE_PTR ("ds_init_buffer_field", obj_desc);
+
+
+ /* Host object must be a Buffer */
+
+ if (ACPI_GET_OBJECT_TYPE (buffer_desc) != ACPI_TYPE_BUFFER) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+ "Target of Create Field is not a Buffer object - %s\n",
+ acpi_ut_get_object_type_name (buffer_desc)));
+
+ status = AE_AML_OPERAND_TYPE;
+ goto cleanup;
+ }
+
+ /*
+ * The last parameter to all of these opcodes (result_desc) started
+ * out as a name_string, and should therefore now be a NS node
+ * after resolution in acpi_ex_resolve_operands().
+ */
+ if (ACPI_GET_DESCRIPTOR_TYPE (result_desc) != ACPI_DESC_TYPE_NAMED) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "(%s) destination not a NS Node [%s]\n",
+ acpi_ps_get_opcode_name (aml_opcode), acpi_ut_get_descriptor_name (result_desc)));
+
+ status = AE_AML_OPERAND_TYPE;
+ goto cleanup;
+ }
+
+ offset = (u32) offset_desc->integer.value;
+
+ /*
+ * Setup the Bit offsets and counts, according to the opcode
+ */
+ switch (aml_opcode) {
+ case AML_CREATE_FIELD_OP:
+
+ /* Offset is in bits, count is in bits */
+
+ bit_offset = offset;
+ bit_count = (u32) length_desc->integer.value;
+ field_flags = AML_FIELD_ACCESS_BYTE;
+ break;
+
+ case AML_CREATE_BIT_FIELD_OP:
+
+ /* Offset is in bits, Field is one bit */
+
+ bit_offset = offset;
+ bit_count = 1;
+ field_flags = AML_FIELD_ACCESS_BYTE;
+ break;
+
+ case AML_CREATE_BYTE_FIELD_OP:
+
+ /* Offset is in bytes, field is one byte */
+
+ bit_offset = 8 * offset;
+ bit_count = 8;
+ field_flags = AML_FIELD_ACCESS_BYTE;
+ break;
+
+ case AML_CREATE_WORD_FIELD_OP:
+
+ /* Offset is in bytes, field is one word */
+
+ bit_offset = 8 * offset;
+ bit_count = 16;
+ field_flags = AML_FIELD_ACCESS_WORD;
+ break;
+
+ case AML_CREATE_DWORD_FIELD_OP:
+
+ /* Offset is in bytes, field is one dword */
+
+ bit_offset = 8 * offset;
+ bit_count = 32;
+ field_flags = AML_FIELD_ACCESS_DWORD;
+ break;
+
+ case AML_CREATE_QWORD_FIELD_OP:
+
+ /* Offset is in bytes, field is one qword */
+
+ bit_offset = 8 * offset;
+ bit_count = 64;
+ field_flags = AML_FIELD_ACCESS_QWORD;
+ break;
+
+ default:
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+ "Unknown field creation opcode %02x\n",
+ aml_opcode));
+ status = AE_AML_BAD_OPCODE;
+ goto cleanup;
+ }
+
+ /* Entire field must fit within the current length of the buffer */
+
+ if ((bit_offset + bit_count) >
+ (8 * (u32) buffer_desc->buffer.length)) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+ "Field [%4.4s] size %d exceeds Buffer [%4.4s] size %d (bits)\n",
+ acpi_ut_get_node_name (result_desc),
+ bit_offset + bit_count,
+ acpi_ut_get_node_name (buffer_desc->buffer.node),
+ 8 * (u32) buffer_desc->buffer.length));
+ status = AE_AML_BUFFER_LIMIT;
+ goto cleanup;
+ }
+
+ /*
+ * Initialize areas of the field object that are common to all fields
+ * For field_flags, use LOCK_RULE = 0 (NO_LOCK), UPDATE_RULE = 0 (UPDATE_PRESERVE)
+ */
+ status = acpi_ex_prep_common_field_object (obj_desc, field_flags, 0,
+ bit_offset, bit_count);
+ if (ACPI_FAILURE (status)) {
+ goto cleanup;
+ }
+
+ obj_desc->buffer_field.buffer_obj = buffer_desc;
+
+ /* Reference count for buffer_desc inherits obj_desc count */
+
+ buffer_desc->common.reference_count = (u16) (buffer_desc->common.reference_count +
+ obj_desc->common.reference_count);
+
+
+cleanup:
+
+ /* Always delete the operands */
+
+ acpi_ut_remove_reference (offset_desc);
+ acpi_ut_remove_reference (buffer_desc);
+
+ if (aml_opcode == AML_CREATE_FIELD_OP) {
+ acpi_ut_remove_reference (length_desc);
+ }
+
+ /* On failure, delete the result descriptor */
+
+ if (ACPI_FAILURE (status)) {
+ acpi_ut_remove_reference (result_desc); /* Result descriptor */
+ }
+ else {
+ /* Now the address and length are valid for this buffer_field */
+
+ obj_desc->buffer_field.flags |= AOPOBJ_DATA_VALID;
+ }
+
+ return_ACPI_STATUS (status);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION: acpi_ds_eval_buffer_field_operands
+ *
+ * PARAMETERS: walk_state - Current walk
+ * Op - A valid buffer_field Op object
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Get buffer_field Buffer and Index
+ * Called from acpi_ds_exec_end_op during buffer_field parse tree walk
+ *
+ ****************************************************************************/
+
+acpi_status
+acpi_ds_eval_buffer_field_operands (
+ struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op)
+{
+ acpi_status status;
+ union acpi_operand_object *obj_desc;
+ struct acpi_namespace_node *node;
+ union acpi_parse_object *next_op;
+
+
+ ACPI_FUNCTION_TRACE_PTR ("ds_eval_buffer_field_operands", op);
+
+
+ /*
+ * This is where we evaluate the address and length fields of the
+ * create_xxx_field declaration
+ */
+ node = op->common.node;
+
+ /* next_op points to the op that holds the Buffer */
+
+ next_op = op->common.value.arg;
+
+ /* Evaluate/create the address and length operands */
+
+ status = acpi_ds_create_operands (walk_state, next_op);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ obj_desc = acpi_ns_get_attached_object (node);
+ if (!obj_desc) {
+ return_ACPI_STATUS (AE_NOT_EXIST);
+ }
+
+ /* Resolve the operands */
+
+ status = acpi_ex_resolve_operands (op->common.aml_opcode,
+ ACPI_WALK_OPERANDS, walk_state);
+
+ ACPI_DUMP_OPERANDS (ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
+ acpi_ps_get_opcode_name (op->common.aml_opcode),
+ walk_state->num_operands, "after acpi_ex_resolve_operands");
+
+ if (ACPI_FAILURE (status)) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "(%s) bad operand(s) (%X)\n",
+ acpi_ps_get_opcode_name (op->common.aml_opcode), status));
+
+ return_ACPI_STATUS (status);
+ }
+
+ /* Initialize the Buffer Field */
+
+ if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {
+ /* NOTE: Slightly different operands for this opcode */
+
+ status = acpi_ds_init_buffer_field (op->common.aml_opcode, obj_desc,
+ walk_state->operands[0], walk_state->operands[1],
+ walk_state->operands[2], walk_state->operands[3]);
+ }
+ else {
+ /* All other, create_xxx_field opcodes */
+
+ status = acpi_ds_init_buffer_field (op->common.aml_opcode, obj_desc,
+ walk_state->operands[0], walk_state->operands[1],
+ NULL, walk_state->operands[2]);
+ }
+
+ return_ACPI_STATUS (status);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION: acpi_ds_eval_region_operands
+ *
+ * PARAMETERS: walk_state - Current walk
+ * Op - A valid region Op object
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Get region address and length
+ * Called from acpi_ds_exec_end_op during op_region parse tree walk
+ *
+ ****************************************************************************/
+
+acpi_status
+acpi_ds_eval_region_operands (
+ struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op)
+{
+ acpi_status status;
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object *operand_desc;
+ struct acpi_namespace_node *node;
+ union acpi_parse_object *next_op;
+
+
+ ACPI_FUNCTION_TRACE_PTR ("ds_eval_region_operands", op);
+
+
+ /*
+ * This is where we evaluate the address and length fields of the op_region declaration
+ */
+ node = op->common.node;
+
+ /* next_op points to the op that holds the space_iD */
+
+ next_op = op->common.value.arg;
+
+ /* next_op points to address op */
+
+ next_op = next_op->common.next;
+
+ /* Evaluate/create the address and length operands */
+
+ status = acpi_ds_create_operands (walk_state, next_op);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ /* Resolve the length and address operands to numbers */
+
+ status = acpi_ex_resolve_operands (op->common.aml_opcode, ACPI_WALK_OPERANDS, walk_state);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ ACPI_DUMP_OPERANDS (ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
+ acpi_ps_get_opcode_name (op->common.aml_opcode),
+ 1, "after acpi_ex_resolve_operands");
+
+ obj_desc = acpi_ns_get_attached_object (node);
+ if (!obj_desc) {
+ return_ACPI_STATUS (AE_NOT_EXIST);
+ }
+
+ /*
+ * Get the length operand and save it
+ * (at Top of stack)
+ */
+ operand_desc = walk_state->operands[walk_state->num_operands - 1];
+
+ obj_desc->region.length = (u32) operand_desc->integer.value;
+ acpi_ut_remove_reference (operand_desc);
+
+ /*
+ * Get the address and save it
+ * (at top of stack - 1)
+ */
+ operand_desc = walk_state->operands[walk_state->num_operands - 2];
+
+ obj_desc->region.address = (acpi_physical_address) operand_desc->integer.value;
+ acpi_ut_remove_reference (operand_desc);
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "rgn_obj %p Addr %8.8X%8.8X Len %X\n",
+ obj_desc,
+ ACPI_FORMAT_UINT64 (obj_desc->region.address),
+ obj_desc->region.length));
+
+ /* Now the address and length are valid for this opregion */
+
+ obj_desc->region.flags |= AOPOBJ_DATA_VALID;
+
+ return_ACPI_STATUS (status);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION: acpi_ds_eval_data_object_operands
+ *
+ * PARAMETERS: walk_state - Current walk
+ * Op - A valid data_object Op object
+ * obj_desc - data_object
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Get the operands and complete the following data object types:
+ * Buffer, Package.
+ *
+ ****************************************************************************/
+
+acpi_status
+acpi_ds_eval_data_object_operands (
+ struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op,
+ union acpi_operand_object *obj_desc)
+{
+ acpi_status status;
+ union acpi_operand_object *arg_desc;
+ u32 length;
+
+
+ ACPI_FUNCTION_TRACE ("ds_eval_data_object_operands");
+
+
+ /* The first operand (for all of these data objects) is the length */
+
+ status = acpi_ds_create_operand (walk_state, op->common.value.arg, 1);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ status = acpi_ex_resolve_operands (walk_state->opcode,
+ &(walk_state->operands [walk_state->num_operands -1]),
+ walk_state);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ /* Extract length operand */
+
+ arg_desc = walk_state->operands [walk_state->num_operands - 1];
+ length = (u32) arg_desc->integer.value;
+
+ /* Cleanup for length operand */
+
+ status = acpi_ds_obj_stack_pop (1, walk_state);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ acpi_ut_remove_reference (arg_desc);
+
+ /*
+ * Create the actual data object
+ */
+ switch (op->common.aml_opcode) {
+ case AML_BUFFER_OP:
+
+ status = acpi_ds_build_internal_buffer_obj (walk_state, op, length, &obj_desc);
+ break;
+
+ case AML_PACKAGE_OP:
+ case AML_VAR_PACKAGE_OP:
+
+ status = acpi_ds_build_internal_package_obj (walk_state, op, length, &obj_desc);
+ break;
+
+ default:
+ return_ACPI_STATUS (AE_AML_BAD_OPCODE);
+ }
+
+ if (ACPI_SUCCESS (status)) {
+ /*
+ * Return the object in the walk_state, unless the parent is a package --
+ * in this case, the return object will be stored in the parse tree
+ * for the package.
+ */
+ if ((!op->common.parent) ||
+ ((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) &&
+ (op->common.parent->common.aml_opcode != AML_VAR_PACKAGE_OP) &&
+ (op->common.parent->common.aml_opcode != AML_NAME_OP))) {
+ walk_state->result_obj = obj_desc;
+ }
+ }
+
+ return_ACPI_STATUS (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_exec_begin_control_op
+ *
+ * PARAMETERS: walk_list - The list that owns the walk stack
+ * Op - The control Op
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Handles all control ops encountered during control method
+ * execution.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_exec_begin_control_op (
+ struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op)
+{
+ acpi_status status = AE_OK;
+ union acpi_generic_state *control_state;
+
+
+ ACPI_FUNCTION_NAME ("ds_exec_begin_control_op");
+
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n", op,
+ op->common.aml_opcode, walk_state));
+
+ switch (op->common.aml_opcode) {
+ case AML_IF_OP:
+ case AML_WHILE_OP:
+
+ /*
+ * IF/WHILE: Create a new control state to manage these
+ * constructs. We need to manage these as a stack, in order
+ * to handle nesting.
+ */
+ control_state = acpi_ut_create_control_state ();
+ if (!control_state) {
+ status = AE_NO_MEMORY;
+ break;
+ }
+ /*
+ * Save a pointer to the predicate for multiple executions
+ * of a loop
+ */
+ control_state->control.aml_predicate_start = walk_state->parser_state.aml - 1;
+ control_state->control.package_end = walk_state->parser_state.pkg_end;
+ control_state->control.opcode = op->common.aml_opcode;
+
+
+ /* Push the control state on this walk's control stack */
+
+ acpi_ut_push_generic_state (&walk_state->control_state, control_state);
+ break;
+
+ case AML_ELSE_OP:
+
+ /* Predicate is in the state object */
+ /* If predicate is true, the IF was executed, ignore ELSE part */
+
+ if (walk_state->last_predicate) {
+ status = AE_CTRL_TRUE;
+ }
+
+ break;
+
+ case AML_RETURN_OP:
+
+ break;
+
+ default:
+ break;
+ }
+
+ return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_exec_end_control_op
+ *
+ * PARAMETERS: walk_list - The list that owns the walk stack
+ * Op - The control Op
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Handles all control ops encountered during control method
+ * execution.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_exec_end_control_op (
+ struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op)
+{
+ acpi_status status = AE_OK;
+ union acpi_generic_state *control_state;
+
+
+ ACPI_FUNCTION_NAME ("ds_exec_end_control_op");
+
+
+ switch (op->common.aml_opcode) {
+ case AML_IF_OP:
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", op));
+
+ /*
+ * Save the result of the predicate in case there is an
+ * ELSE to come
+ */
+ walk_state->last_predicate =
+ (u8) walk_state->control_state->common.value;
+
+ /*
+ * Pop the control state that was created at the start
+ * of the IF and free it
+ */
+ control_state = acpi_ut_pop_generic_state (&walk_state->control_state);
+ acpi_ut_delete_generic_state (control_state);
+ break;
+
+
+ case AML_ELSE_OP:
+
+ break;
+
+
+ case AML_WHILE_OP:
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op));
+
+ if (walk_state->control_state->common.value) {
+ /* Predicate was true, go back and evaluate it again! */
+
+ status = AE_CTRL_PENDING;
+ }
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[WHILE_OP] termination! Op=%p\n", op));
+
+ /* Pop this control state and free it */
+
+ control_state = acpi_ut_pop_generic_state (&walk_state->control_state);
+
+ walk_state->aml_last_while = control_state->control.aml_predicate_start;
+ acpi_ut_delete_generic_state (control_state);
+ break;
+
+
+ case AML_RETURN_OP:
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+ "[RETURN_OP] Op=%p Arg=%p\n",op, op->common.value.arg));
+
+ /*
+ * One optional operand -- the return value
+ * It can be either an immediate operand or a result that
+ * has been bubbled up the tree
+ */
+ if (op->common.value.arg) {
+ /* Since we have a real Return(), delete any implicit return */
+
+ acpi_ds_clear_implicit_return (walk_state);
+
+ /* Return statement has an immediate operand */
+
+ status = acpi_ds_create_operands (walk_state, op->common.value.arg);
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+ /*
+ * If value being returned is a Reference (such as
+ * an arg or local), resolve it now because it may
+ * cease to exist at the end of the method.
+ */
+ status = acpi_ex_resolve_to_value (&walk_state->operands [0], walk_state);
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+
+ /*
+ * Get the return value and save as the last result
+ * value. This is the only place where walk_state->return_desc
+ * is set to anything other than zero!
+ */
+ walk_state->return_desc = walk_state->operands[0];
+ }
+ else if ((walk_state->results) &&
+ (walk_state->results->results.num_results > 0)) {
+ /* Since we have a real Return(), delete any implicit return */
+
+ acpi_ds_clear_implicit_return (walk_state);
+
+ /*
+ * The return value has come from a previous calculation.
+ *
+ * If value being returned is a Reference (such as
+ * an arg or local), resolve it now because it may
+ * cease to exist at the end of the method.
+ *
+ * Allow references created by the Index operator to return unchanged.
+ */
+ if ((ACPI_GET_DESCRIPTOR_TYPE (walk_state->results->results.obj_desc[0]) == ACPI_DESC_TYPE_OPERAND) &&
+ (ACPI_GET_OBJECT_TYPE (walk_state->results->results.obj_desc [0]) == ACPI_TYPE_LOCAL_REFERENCE) &&
+ ((walk_state->results->results.obj_desc [0])->reference.opcode != AML_INDEX_OP)) {
+ status = acpi_ex_resolve_to_value (&walk_state->results->results.obj_desc [0], walk_state);
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+ }
+
+ walk_state->return_desc = walk_state->results->results.obj_desc [0];
+ }
+ else {
+ /* No return operand */
+
+ if (walk_state->num_operands) {
+ acpi_ut_remove_reference (walk_state->operands [0]);
+ }
+
+ walk_state->operands [0] = NULL;
+ walk_state->num_operands = 0;
+ walk_state->return_desc = NULL;
+ }
+
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+ "Completed RETURN_OP State=%p, ret_val=%p\n",
+ walk_state, walk_state->return_desc));
+
+ /* End the control method execution right now */
+
+ status = AE_CTRL_TERMINATE;
+ break;
+
+
+ case AML_NOOP_OP:
+
+ /* Just do nothing! */
+ break;
+
+
+ case AML_BREAK_POINT_OP:
+
+ /* Call up to the OS service layer to handle this */
+
+ status = acpi_os_signal (ACPI_SIGNAL_BREAKPOINT, "Executed AML Breakpoint opcode");
+
+ /* If and when it returns, all done. */
+
+ break;
+
+
+ case AML_BREAK_OP:
+ case AML_CONTINUE_OP: /* ACPI 2.0 */
+
+
+ /* Pop and delete control states until we find a while */
+
+ while (walk_state->control_state &&
+ (walk_state->control_state->control.opcode != AML_WHILE_OP)) {
+ control_state = acpi_ut_pop_generic_state (&walk_state->control_state);
+ acpi_ut_delete_generic_state (control_state);
+ }
+
+ /* No while found? */
+
+ if (!walk_state->control_state) {
+ return (AE_AML_NO_WHILE);
+ }
+
+ /* Was: walk_state->aml_last_while = walk_state->control_state->Control.aml_predicate_start; */
+
+ walk_state->aml_last_while = walk_state->control_state->control.package_end;
+
+ /* Return status depending on opcode */
+
+ if (op->common.aml_opcode == AML_BREAK_OP) {
+ status = AE_CTRL_BREAK;
+ }
+ else {
+ status = AE_CTRL_CONTINUE;
+ }
+ break;
+
+
+ default:
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown control opcode=%X Op=%p\n",
+ op->common.aml_opcode, op));
+
+ status = AE_AML_BAD_OPCODE;
+ break;
+ }
+
+ return (status);
+}
+
diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c
new file mode 100644
index 00000000000..462c5d83e74
--- /dev/null
+++ b/drivers/acpi/dispatcher/dsutils.c
@@ -0,0 +1,744 @@
+/*******************************************************************************
+ *
+ * Module Name: dsutils - Dispatcher utilities
+ *
+ ******************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2005, R. Byron Moore
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+
+#include <acpi/acpi.h>
+#include <acpi/acparser.h>
+#include <acpi/amlcode.h>
+#include <acpi/acdispat.h>
+#include <acpi/acinterp.h>
+#include <acpi/acnamesp.h>
+#include <acpi/acdebug.h>
+
+#define _COMPONENT ACPI_DISPATCHER
+ ACPI_MODULE_NAME ("dsutils")
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_clear_implicit_return
+ *
+ * PARAMETERS: walk_state - Current State
+ *
+ * RETURN: None.
+ *
+ * DESCRIPTION: Clear and remove a reference on an implicit return value. Used
+ * to delete "stale" return values (if enabled, the return value
+ * from every operator is saved at least momentarily, in case the
+ * parent method exits.)
+ *
+ ******************************************************************************/
+
+void
+acpi_ds_clear_implicit_return (
+ struct acpi_walk_state *walk_state)
+{
+ ACPI_FUNCTION_NAME ("ds_clear_implicit_return");
+
+
+ /*
+ * Slack must be enabled for this feature
+ */
+ if (!acpi_gbl_enable_interpreter_slack) {
+ return;
+ }
+
+ if (walk_state->implicit_return_obj) {
+ /*
+ * Delete any "stale" implicit return. However, in
+ * complex statements, the implicit return value can be
+ * bubbled up several levels.
+ */
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+ "Removing reference on stale implicit return obj %p\n",
+ walk_state->implicit_return_obj));
+
+ acpi_ut_remove_reference (walk_state->implicit_return_obj);
+ walk_state->implicit_return_obj = NULL;
+ }
+}
+
+
+#ifndef ACPI_NO_METHOD_EXECUTION
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_do_implicit_return
+ *
+ * PARAMETERS: return_desc - The return value
+ * walk_state - Current State
+ * add_reference - True if a reference should be added to the
+ * return object
+ *
+ * RETURN: TRUE if implicit return enabled, FALSE otherwise
+ *
+ * DESCRIPTION: Implements the optional "implicit return". We save the result
+ * of every ASL operator and control method invocation in case the
+ * parent method exit. Before storing a new return value, we
+ * delete the previous return value.
+ *
+ ******************************************************************************/
+
+u8
+acpi_ds_do_implicit_return (
+ union acpi_operand_object *return_desc,
+ struct acpi_walk_state *walk_state,
+ u8 add_reference)
+{
+ ACPI_FUNCTION_NAME ("ds_do_implicit_return");
+
+
+ /*
+ * Slack must be enabled for this feature, and we must
+ * have a valid return object
+ */
+ if ((!acpi_gbl_enable_interpreter_slack) ||
+ (!return_desc)) {
+ return (FALSE);
+ }
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+ "Result %p will be implicitly returned; Prev=%p\n",
+ return_desc,
+ walk_state->implicit_return_obj));
+
+ /*
+ * Delete any "stale" implicit return value first. However, in
+ * complex statements, the implicit return value can be
+ * bubbled up several levels, so we don't clear the value if it
+ * is the same as the return_desc.
+ */
+ if (walk_state->implicit_return_obj) {
+ if (walk_state->implicit_return_obj == return_desc) {
+ return (TRUE);
+ }
+ acpi_ds_clear_implicit_return (walk_state);
+ }
+
+ /* Save the implicit return value, add a reference if requested */
+
+ walk_state->implicit_return_obj = return_desc;
+ if (add_reference) {
+ acpi_ut_add_reference (return_desc);
+ }
+
+ return (TRUE);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_is_result_used
+ *
+ * PARAMETERS: Op - Current Op
+ * walk_state - Current State
+ *
+ * RETURN: TRUE if result is used, FALSE otherwise
+ *
+ * DESCRIPTION: Check if a result object will be used by the parent
+ *
+ ******************************************************************************/
+
+u8
+acpi_ds_is_result_used (
+ union acpi_parse_object *op,
+ struct acpi_walk_state *walk_state)
+{
+ const struct acpi_opcode_info *parent_info;
+
+ ACPI_FUNCTION_TRACE_PTR ("ds_is_result_used", op);
+
+
+ /* Must have both an Op and a Result Object */
+
+ if (!op) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null Op\n"));
+ return_VALUE (TRUE);
+ }
+
+ /*
+ * We know that this operator is not a
+ * Return() operator (would not come here.) The following code is the
+ * optional support for a so-called "implicit return". Some AML code
+ * assumes that the last value of the method is "implicitly" returned
+ * to the caller. Just save the last result as the return value.
+ * NOTE: this is optional because the ASL language does not actually
+ * support this behavior.
+ */
+ acpi_ds_do_implicit_return (walk_state->result_obj, walk_state, TRUE);
+
+ /*
+ * Now determine if the parent will use the result
+ *
+ * If there is no parent, or the parent is a scope_op, we are executing
+ * at the method level. An executing method typically has no parent,
+ * since each method is parsed separately. A method invoked externally
+ * via execute_control_method has a scope_op as the parent.
+ */
+ if ((!op->common.parent) ||
+ (op->common.parent->common.aml_opcode == AML_SCOPE_OP)) {
+ /* No parent, the return value cannot possibly be used */
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "At Method level, result of [%s] not used\n",
+ acpi_ps_get_opcode_name (op->common.aml_opcode)));
+ return_VALUE (FALSE);
+ }
+
+ /* Get info on the parent. The root_op is AML_SCOPE */
+
+ parent_info = acpi_ps_get_opcode_info (op->common.parent->common.aml_opcode);
+ if (parent_info->class == AML_CLASS_UNKNOWN) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown parent opcode. Op=%p\n", op));
+ return_VALUE (FALSE);
+ }
+
+ /*
+ * Decide what to do with the result based on the parent. If
+ * the parent opcode will not use the result, delete the object.
+ * Otherwise leave it as is, it will be deleted when it is used
+ * as an operand later.
+ */
+ switch (parent_info->class) {
+ case AML_CLASS_CONTROL:
+
+ switch (op->common.parent->common.aml_opcode) {
+ case AML_RETURN_OP:
+
+ /* Never delete the return value associated with a return opcode */
+
+ goto result_used;
+
+ case AML_IF_OP:
+ case AML_WHILE_OP:
+
+ /*
+ * If we are executing the predicate AND this is the predicate op,
+ * we will use the return value
+ */
+ if ((walk_state->control_state->common.state == ACPI_CONTROL_PREDICATE_EXECUTING) &&
+ (walk_state->control_state->control.predicate_op == op)) {
+ goto result_used;
+ }
+ break;
+
+ default:
+ /* Ignore other control opcodes */
+ break;
+ }
+
+ /* The general control opcode returns no result */
+
+ goto result_not_used;
+
+
+ case AML_CLASS_CREATE:
+
+ /*
+ * These opcodes allow term_arg(s) as operands and therefore
+ * the operands can be method calls. The result is used.
+ */
+ goto result_used;
+
+
+ case AML_CLASS_NAMED_OBJECT:
+
+ if ((op->common.parent->common.aml_opcode == AML_REGION_OP) ||
+ (op->common.parent->common.aml_opcode == AML_DATA_REGION_OP) ||
+ (op->common.parent->common.aml_opcode == AML_PACKAGE_OP) ||
+ (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP) ||
+ (op->common.parent->common.aml_opcode == AML_BUFFER_OP) ||
+ (op->common.parent->common.aml_opcode == AML_INT_EVAL_SUBTREE_OP)) {
+ /*
+ * These opcodes allow term_arg(s) as operands and therefore
+ * the operands can be method calls. The result is used.
+ */
+ goto result_used;
+ }
+
+ goto result_not_used;
+
+
+ default:
+
+ /*
+ * In all other cases. the parent will actually use the return
+ * object, so keep it.
+ */
+ goto result_used;
+ }
+
+
+result_used:
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Result of [%s] used by Parent [%s] Op=%p\n",
+ acpi_ps_get_opcode_name (op->common.aml_opcode),
+ acpi_ps_get_opcode_name (op->common.parent->common.aml_opcode), op));
+
+ return_VALUE (TRUE);
+
+
+result_not_used:
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Result of [%s] not used by Parent [%s] Op=%p\n",
+ acpi_ps_get_opcode_name (op->common.aml_opcode),
+ acpi_ps_get_opcode_name (op->common.parent->common.aml_opcode), op));
+
+ return_VALUE (FALSE);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_delete_result_if_not_used
+ *
+ * PARAMETERS: Op - Current parse Op
+ * result_obj - Result of the operation
+ * walk_state - Current state
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Used after interpretation of an opcode. If there is an internal
+ * result descriptor, check if the parent opcode will actually use
+ * this result. If not, delete the result now so that it will
+ * not become orphaned.
+ *
+ ******************************************************************************/
+
+void
+acpi_ds_delete_result_if_not_used (
+ union acpi_parse_object *op,
+ union acpi_operand_object *result_obj,
+ struct acpi_walk_state *walk_state)
+{
+ union acpi_operand_object *obj_desc;
+ acpi_status status;
+
+
+ ACPI_FUNCTION_TRACE_PTR ("ds_delete_result_if_not_used", result_obj);
+
+
+ if (!op) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null Op\n"));
+ return_VOID;
+ }
+
+ if (!result_obj) {
+ return_VOID;
+ }
+
+ if (!acpi_ds_is_result_used (op, walk_state)) {
+ /* Must pop the result stack (obj_desc should be equal to result_obj) */
+
+ status = acpi_ds_result_pop (&obj_desc, walk_state);
+ if (ACPI_SUCCESS (status)) {
+ acpi_ut_remove_reference (result_obj);
+ }
+ }
+
+ return_VOID;
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_resolve_operands
+ *
+ * PARAMETERS: walk_state - Current walk state with operands on stack
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Resolve all operands to their values. Used to prepare
+ * arguments to a control method invocation (a call from one
+ * method to another.)
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_resolve_operands (
+ struct acpi_walk_state *walk_state)
+{
+ u32 i;
+ acpi_status status = AE_OK;
+
+
+ ACPI_FUNCTION_TRACE_PTR ("ds_resolve_operands", walk_state);
+
+
+ /*
+ * Attempt to resolve each of the valid operands
+ * Method arguments are passed by reference, not by value. This means
+ * that the actual objects are passed, not copies of the objects.
+ */
+ for (i = 0; i < walk_state->num_operands; i++) {
+ status = acpi_ex_resolve_to_value (&walk_state->operands[i], walk_state);
+ if (ACPI_FAILURE (status)) {
+ break;
+ }
+ }
+
+ return_ACPI_STATUS (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_clear_operands
+ *
+ * PARAMETERS: walk_state - Current walk state with operands on stack
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Clear all operands on the current walk state operand stack.
+ *
+ ******************************************************************************/
+
+void
+acpi_ds_clear_operands (
+ struct acpi_walk_state *walk_state)
+{
+ u32 i;
+
+
+ ACPI_FUNCTION_TRACE_PTR ("ds_clear_operands", walk_state);
+
+
+ /* Remove a reference on each operand on the stack */
+
+ for (i = 0; i < walk_state->num_operands; i++) {
+ /*
+ * Remove a reference to all operands, including both
+ * "Arguments" and "Targets".
+ */
+ acpi_ut_remove_reference (walk_state->operands[i]);
+ walk_state->operands[i] = NULL;
+ }
+
+ walk_state->num_operands = 0;
+ return_VOID;
+}
+#endif
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_create_operand
+ *
+ * PARAMETERS: walk_state - Current walk state
+ * Arg - Parse object for the argument
+ * arg_index - Which argument (zero based)
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Translate a parse tree object that is an argument to an AML
+ * opcode to the equivalent interpreter object. This may include
+ * looking up a name or entering a new name into the internal
+ * namespace.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_create_operand (
+ struct acpi_walk_state *walk_state,
+ union acpi_parse_object *arg,
+ u32 arg_index)
+{
+ acpi_status status = AE_OK;
+ char *name_string;
+ u32 name_length;
+ union acpi_operand_object *obj_desc;
+ union acpi_parse_object *parent_op;
+ u16 opcode;
+ acpi_interpreter_mode interpreter_mode;
+ const struct acpi_opcode_info *op_info;
+
+
+ ACPI_FUNCTION_TRACE_PTR ("ds_create_operand", arg);
+
+
+ /* A valid name must be looked up in the namespace */
+
+ if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) &&
+ (arg->common.value.string)) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", arg));
+
+ /* Get the entire name string from the AML stream */
+
+ status = acpi_ex_get_name_string (ACPI_TYPE_ANY, arg->common.value.buffer,
+ &name_string, &name_length);
+
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ /* All prefixes have been handled, and the name is in name_string */
+
+ /*
+ * Special handling for buffer_field declarations. This is a deferred
+ * opcode that unfortunately defines the field name as the last
+ * parameter instead of the first. We get here when we are performing
+ * the deferred execution, so the actual name of the field is already
+ * in the namespace. We don't want to attempt to look it up again
+ * because we may be executing in a different scope than where the
+ * actual opcode exists.
+ */
+ if ((walk_state->deferred_node) &&
+ (walk_state->deferred_node->type == ACPI_TYPE_BUFFER_FIELD) &&
+ (arg_index != 0)) {
+ obj_desc = ACPI_CAST_PTR (union acpi_operand_object, walk_state->deferred_node);
+ status = AE_OK;
+ }
+ else /* All other opcodes */ {
+ /*
+ * Differentiate between a namespace "create" operation
+ * versus a "lookup" operation (IMODE_LOAD_PASS2 vs.
+ * IMODE_EXECUTE) in order to support the creation of
+ * namespace objects during the execution of control methods.
+ */
+ parent_op = arg->common.parent;
+ op_info = acpi_ps_get_opcode_info (parent_op->common.aml_opcode);
+ if ((op_info->flags & AML_NSNODE) &&
+ (parent_op->common.aml_opcode != AML_INT_METHODCALL_OP) &&
+ (parent_op->common.aml_opcode != AML_REGION_OP) &&
+ (parent_op->common.aml_opcode != AML_INT_NAMEPATH_OP)) {
+ /* Enter name into namespace if not found */
+
+ interpreter_mode = ACPI_IMODE_LOAD_PASS2;
+ }
+ else {
+ /* Return a failure if name not found */
+
+ interpreter_mode = ACPI_IMODE_EXECUTE;
+ }
+
+ status = acpi_ns_lookup (walk_state->scope_info, name_string,
+ ACPI_TYPE_ANY, interpreter_mode,
+ ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
+ walk_state,
+ ACPI_CAST_INDIRECT_PTR (struct acpi_namespace_node, &obj_desc));
+ /*
+ * The only case where we pass through (ignore) a NOT_FOUND
+ * error is for the cond_ref_of opcode.
+ */
+ if (status == AE_NOT_FOUND) {
+ if (parent_op->common.aml_opcode == AML_COND_REF_OF_OP) {
+ /*
+ * For the Conditional Reference op, it's OK if
+ * the name is not found; We just need a way to
+ * indicate this to the interpreter, set the
+ * object to the root
+ */
+ obj_desc = ACPI_CAST_PTR (union acpi_operand_object, acpi_gbl_root_node);
+ status = AE_OK;
+ }
+ else {
+ /*
+ * We just plain didn't find it -- which is a
+ * very serious error at this point
+ */
+ status = AE_AML_NAME_NOT_FOUND;
+ }
+ }
+
+ if (ACPI_FAILURE (status)) {
+ ACPI_REPORT_NSERROR (name_string, status);
+ }
+ }
+
+ /* Free the namestring created above */
+
+ ACPI_MEM_FREE (name_string);
+
+ /* Check status from the lookup */
+
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ /* Put the resulting object onto the current object stack */
+
+ status = acpi_ds_obj_stack_push (obj_desc, walk_state);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+ ACPI_DEBUGGER_EXEC (acpi_db_display_argument_object (obj_desc, walk_state));
+ }
+ else {
+ /* Check for null name case */
+
+ if (arg->common.aml_opcode == AML_INT_NAMEPATH_OP) {
+ /*
+ * If the name is null, this means that this is an
+ * optional result parameter that was not specified
+ * in the original ASL. Create a Zero Constant for a
+ * placeholder. (Store to a constant is a Noop.)
+ */
+ opcode = AML_ZERO_OP; /* Has no arguments! */
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Null namepath: Arg=%p\n", arg));
+ }
+ else {
+ opcode = arg->common.aml_opcode;
+ }
+
+ /* Get the object type of the argument */
+
+ op_info = acpi_ps_get_opcode_info (opcode);
+ if (op_info->object_type == ACPI_TYPE_INVALID) {
+ return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
+ }
+
+ if (op_info->flags & AML_HAS_RETVAL) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+ "Argument previously created, already stacked \n"));
+
+ ACPI_DEBUGGER_EXEC (acpi_db_display_argument_object (
+ walk_state->operands [walk_state->num_operands - 1], walk_state));
+
+ /*
+ * Use value that was already previously returned
+ * by the evaluation of this argument
+ */
+ status = acpi_ds_result_pop_from_bottom (&obj_desc, walk_state);
+ if (ACPI_FAILURE (status)) {
+ /*
+ * Only error is underflow, and this indicates
+ * a missing or null operand!
+ */
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Missing or null operand, %s\n",
+ acpi_format_exception (status)));
+ return_ACPI_STATUS (status);
+ }
+ }
+ else {
+ /* Create an ACPI_INTERNAL_OBJECT for the argument */
+
+ obj_desc = acpi_ut_create_internal_object (op_info->object_type);
+ if (!obj_desc) {
+ return_ACPI_STATUS (AE_NO_MEMORY);
+ }
+
+ /* Initialize the new object */
+
+ status = acpi_ds_init_object_from_op (walk_state, arg,
+ opcode, &obj_desc);
+ if (ACPI_FAILURE (status)) {
+ acpi_ut_delete_object_desc (obj_desc);
+ return_ACPI_STATUS (status);
+ }
+ }
+
+ /* Put the operand object on the object stack */
+
+ status = acpi_ds_obj_stack_push (obj_desc, walk_state);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ ACPI_DEBUGGER_EXEC (acpi_db_display_argument_object (obj_desc, walk_state));
+ }
+
+ return_ACPI_STATUS (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_create_operands
+ *
+ * PARAMETERS: walk_state - Current state
+ * first_arg - First argument of a parser argument tree
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Convert an operator's arguments from a parse tree format to
+ * namespace objects and place those argument object on the object
+ * stack in preparation for evaluation by the interpreter.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_create_operands (
+ struct acpi_walk_state *walk_state,
+ union acpi_parse_object *first_arg)
+{
+ acpi_status status = AE_OK;
+ union acpi_parse_object *arg;
+ u32 arg_count = 0;
+
+
+ ACPI_FUNCTION_TRACE_PTR ("ds_create_operands", first_arg);
+
+
+ /* For all arguments in the list... */
+
+ arg = first_arg;
+ while (arg) {
+ status = acpi_ds_create_operand (walk_state, arg, arg_count);
+ if (ACPI_FAILURE (status)) {
+ goto cleanup;
+ }
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Arg #%d (%p) done, Arg1=%p\n",
+ arg_count, arg, first_arg));
+
+ /* Move on to next argument, if any */
+
+ arg = arg->common.next;
+ arg_count++;
+ }
+
+ return_ACPI_STATUS (status);
+
+
+cleanup:
+ /*
+ * We must undo everything done above; meaning that we must
+ * pop everything off of the operand stack and delete those
+ * objects
+ */
+ (void) acpi_ds_obj_stack_pop_and_delete (arg_count, walk_state);
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "While creating Arg %d - %s\n",
+ (arg_count + 1), acpi_format_exception (status)));
+ return_ACPI_STATUS (status);
+}
+
+
diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c
new file mode 100644
index 00000000000..2071a0d2bbb
--- /dev/null
+++ b/drivers/acpi/dispatcher/dswexec.c
@@ -0,0 +1,751 @@
+/******************************************************************************
+ *
+ * Module Name: dswexec - Dispatcher method execution callbacks;
+ * dispatch to interpreter.
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2005, R. Byron Moore
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+
+#include <acpi/acpi.h>
+#include <acpi/acparser.h>
+#include <acpi/amlcode.h>
+#include <acpi/acdispat.h>
+#include <acpi/acinterp.h>
+#include <acpi/acnamesp.h>
+#include <acpi/acdebug.h>
+#include <acpi/acdisasm.h>
+
+
+#define _COMPONENT ACPI_DISPATCHER
+ ACPI_MODULE_NAME ("dswexec")
+
+/*
+ * Dispatch table for opcode classes
+ */
+static ACPI_EXECUTE_OP acpi_gbl_op_type_dispatch [] = {
+ acpi_ex_opcode_0A_0T_1R,
+ acpi_ex_opcode_1A_0T_0R,
+ acpi_ex_opcode_1A_0T_1R,
+ acpi_ex_opcode_1A_1T_0R,
+ acpi_ex_opcode_1A_1T_1R,
+ acpi_ex_opcode_2A_0T_0R,
+ acpi_ex_opcode_2A_0T_1R,
+ acpi_ex_opcode_2A_1T_1R,
+ acpi_ex_opcode_2A_2T_1R,
+ acpi_ex_opcode_3A_0T_0R,
+ acpi_ex_opcode_3A_1T_1R,
+ acpi_ex_opcode_6A_0T_1R};
+
+/*****************************************************************************
+ *
+ * FUNCTION: acpi_ds_get_predicate_value
+ *
+ * PARAMETERS: walk_state - Current state of the parse tree walk
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Get the result of a predicate evaluation
+ *
+ ****************************************************************************/
+
+acpi_status
+acpi_ds_get_predicate_value (
+ struct acpi_walk_state *walk_state,
+ union acpi_operand_object *result_obj) {
+ acpi_status status = AE_OK;
+ union acpi_operand_object *obj_desc;
+ union acpi_operand_object *local_obj_desc = NULL;
+
+
+ ACPI_FUNCTION_TRACE_PTR ("ds_get_predicate_value", walk_state);
+
+
+ walk_state->control_state->common.state = 0;
+
+ if (result_obj) {
+ status = acpi_ds_result_pop (&obj_desc, walk_state);
+ if (ACPI_FAILURE (status)) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+ "Could not get result from predicate evaluation, %s\n",
+ acpi_format_exception (status)));
+
+ return_ACPI_STATUS (status);
+ }
+ }
+ else {
+ status = acpi_ds_create_operand (walk_state, walk_state->op, 0);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ status = acpi_ex_resolve_to_value (&walk_state->operands [0], walk_state);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ obj_desc = walk_state->operands [0];
+ }
+
+ if (!obj_desc) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No predicate obj_desc=%p State=%p\n",
+ obj_desc, walk_state));
+
+ return_ACPI_STATUS (AE_AML_NO_OPERAND);
+ }
+
+ /*
+ * Result of predicate evaluation must be an Integer
+ * object. Implicitly convert the argument if necessary.
+ */
+ status = acpi_ex_convert_to_integer (obj_desc, &local_obj_desc, 16);
+ if (ACPI_FAILURE (status)) {
+ goto cleanup;
+ }
+
+ if (ACPI_GET_OBJECT_TYPE (local_obj_desc) != ACPI_TYPE_INTEGER) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+ "Bad predicate (not an integer) obj_desc=%p State=%p Type=%X\n",
+ obj_desc, walk_state, ACPI_GET_OBJECT_TYPE (obj_desc)));
+
+ status = AE_AML_OPERAND_TYPE;
+ goto cleanup;
+ }
+
+ /* Truncate the predicate to 32-bits if necessary */
+
+ acpi_ex_truncate_for32bit_table (local_obj_desc);
+
+ /*
+ * Save the result of the predicate evaluation on
+ * the control stack
+ */
+ if (local_obj_desc->integer.value) {
+ walk_state->control_state->common.value = TRUE;
+ }
+ else {
+ /*
+ * Predicate is FALSE, we will just toss the
+ * rest of the package
+ */
+ walk_state->control_state->common.value = FALSE;
+ status = AE_CTRL_FALSE;
+ }
+
+
+cleanup:
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Completed a predicate eval=%X Op=%p\n",
+ walk_state->control_state->common.value, walk_state->op));
+
+ /* Break to debugger to display result */
+
+ ACPI_DEBUGGER_EXEC (acpi_db_display_result_object (local_obj_desc, walk_state));
+
+ /*
+ * Delete the predicate result object (we know that
+ * we don't need it anymore)
+ */
+ if (local_obj_desc != obj_desc) {
+ acpi_ut_remove_reference (local_obj_desc);
+ }
+ acpi_ut_remove_reference (obj_desc);
+
+ walk_state->control_state->common.state = ACPI_CONTROL_NORMAL;
+ return_ACPI_STATUS (status);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION: acpi_ds_exec_begin_op
+ *
+ * PARAMETERS: walk_state - Current state of the parse tree walk
+ * out_op - Return op if a new one is created
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Descending callback used during the execution of control
+ * methods. This is where most operators and operands are
+ * dispatched to the interpreter.
+ *
+ ****************************************************************************/
+
+acpi_status
+acpi_ds_exec_begin_op (
+ struct acpi_walk_state *walk_state,
+ union acpi_parse_object **out_op)
+{
+ union acpi_parse_object *op;
+ acpi_status status = AE_OK;
+ u32 opcode_class;
+
+
+ ACPI_FUNCTION_TRACE_PTR ("ds_exec_begin_op", walk_state);
+
+
+ op = walk_state->op;
+ if (!op) {
+ status = acpi_ds_load2_begin_op (walk_state, out_op);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ op = *out_op;
+ walk_state->op = op;
+ walk_state->opcode = op->common.aml_opcode;
+ walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode);
+
+ if (acpi_ns_opens_scope (walk_state->op_info->object_type)) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s) Popping scope for Op %p\n",
+ acpi_ut_get_type_name (walk_state->op_info->object_type), op));
+
+ status = acpi_ds_scope_stack_pop (walk_state);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+ }
+ }
+
+ if (op == walk_state->origin) {
+ if (out_op) {
+ *out_op = op;
+ }
+
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ /*
+ * If the previous opcode was a conditional, this opcode
+ * must be the beginning of the associated predicate.
+ * Save this knowledge in the current scope descriptor
+ */
+ if ((walk_state->control_state) &&
+ (walk_state->control_state->common.state ==
+ ACPI_CONTROL_CONDITIONAL_EXECUTING)) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Exec predicate Op=%p State=%p\n",
+ op, walk_state));
+
+ walk_state->control_state->common.state = ACPI_CONTROL_PREDICATE_EXECUTING;
+
+ /* Save start of predicate */
+
+ walk_state->control_state->control.predicate_op = op;
+ }
+
+
+ opcode_class = walk_state->op_info->class;
+
+ /* We want to send namepaths to the load code */
+
+ if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
+ opcode_class = AML_CLASS_NAMED_OBJECT;
+ }
+
+ /*
+ * Handle the opcode based upon the opcode type
+ */
+ switch (opcode_class) {
+ case AML_CLASS_CONTROL:
+
+ status = acpi_ds_result_stack_push (walk_state);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ status = acpi_ds_exec_begin_control_op (walk_state, op);
+ break;
+
+
+ case AML_CLASS_NAMED_OBJECT:
+
+ if (walk_state->walk_type == ACPI_WALK_METHOD) {
+ /*
+ * Found a named object declaration during method
+ * execution; we must enter this object into the
+ * namespace. The created object is temporary and
+ * will be deleted upon completion of the execution
+ * of this method.
+ */
+ status = acpi_ds_load2_begin_op (walk_state, NULL);
+ }
+
+ if (op->common.aml_opcode == AML_REGION_OP) {
+ status = acpi_ds_result_stack_push (walk_state);
+ }
+ break;
+
+
+ case AML_CLASS_EXECUTE:
+ case AML_CLASS_CREATE:
+
+ /*
+ * Most operators with arguments.
+ * Start a new result/operand state
+ */
+ status = acpi_ds_result_stack_push (walk_state);
+ break;
+
+
+ default:
+ break;
+ }
+
+ /* Nothing to do here during method execution */
+
+ return_ACPI_STATUS (status);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION: acpi_ds_exec_end_op
+ *
+ * PARAMETERS: walk_state - Current state of the parse tree walk
+ * Op - Op that has been just been completed in the
+ * walk; Arguments have now been evaluated.
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Ascending callback used during the execution of control
+ * methods. The only thing we really need to do here is to
+ * notice the beginning of IF, ELSE, and WHILE blocks.
+ *
+ ****************************************************************************/
+
+acpi_status
+acpi_ds_exec_end_op (
+ struct acpi_walk_state *walk_state)
+{
+ union acpi_parse_object *op;
+ acpi_status status = AE_OK;
+ u32 op_type;
+ u32 op_class;
+ union acpi_parse_object *next_op;
+ union acpi_parse_object *first_arg;
+
+
+ ACPI_FUNCTION_TRACE_PTR ("ds_exec_end_op", walk_state);
+
+
+ op = walk_state->op;
+ op_type = walk_state->op_info->type;
+ op_class = walk_state->op_info->class;
+
+ if (op_class == AML_CLASS_UNKNOWN) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown opcode %X\n", op->common.aml_opcode));
+ return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
+ }
+
+ first_arg = op->common.value.arg;
+
+ /* Init the walk state */
+
+ walk_state->num_operands = 0;
+ walk_state->return_desc = NULL;
+ walk_state->result_obj = NULL;
+
+ /* Call debugger for single step support (DEBUG build only) */
+
+ ACPI_DEBUGGER_EXEC (status = acpi_db_single_step (walk_state, op, op_class));
+ ACPI_DEBUGGER_EXEC (if (ACPI_FAILURE (status)) {return_ACPI_STATUS (status);});
+
+ /* Decode the Opcode Class */
+
+ switch (op_class) {
+ case AML_CLASS_ARGUMENT: /* constants, literals, etc. -- do nothing */
+ break;
+
+
+ case AML_CLASS_EXECUTE: /* most operators with arguments */
+
+ /* Build resolved operand stack */
+
+ status = acpi_ds_create_operands (walk_state, first_arg);
+ if (ACPI_FAILURE (status)) {
+ goto cleanup;
+ }
+
+ /* Done with this result state (Now that operand stack is built) */
+
+ status = acpi_ds_result_stack_pop (walk_state);
+ if (ACPI_FAILURE (status)) {
+ goto cleanup;
+ }
+
+ /*
+ * All opcodes require operand resolution, with the only exceptions
+ * being the object_type and size_of operators.
+ */
+ if (!(walk_state->op_info->flags & AML_NO_OPERAND_RESOLVE)) {
+ /* Resolve all operands */
+
+ status = acpi_ex_resolve_operands (walk_state->opcode,
+ &(walk_state->operands [walk_state->num_operands -1]),
+ walk_state);
+ if (ACPI_SUCCESS (status)) {
+ ACPI_DUMP_OPERANDS (ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
+ acpi_ps_get_opcode_name (walk_state->opcode),
+ walk_state->num_operands, "after ex_resolve_operands");
+ }
+ }
+
+ if (ACPI_SUCCESS (status)) {
+ /*
+ * Dispatch the request to the appropriate interpreter handler
+ * routine. There is one routine per opcode "type" based upon the
+ * number of opcode arguments and return type.
+ */
+ status = acpi_gbl_op_type_dispatch[op_type] (walk_state);
+ }
+ else {
+ /*
+ * Treat constructs of the form "Store(local_x,local_x)" as noops when the
+ * Local is uninitialized.
+ */
+ if ((status == AE_AML_UNINITIALIZED_LOCAL) &&
+ (walk_state->opcode == AML_STORE_OP) &&
+ (walk_state->operands[0]->common.type == ACPI_TYPE_LOCAL_REFERENCE) &&
+ (walk_state->operands[1]->common.type == ACPI_TYPE_LOCAL_REFERENCE) &&
+ (walk_state->operands[0]->reference.opcode ==
+ walk_state->operands[1]->reference.opcode) &&
+ (walk_state->operands[0]->reference.offset ==
+ walk_state->operands[1]->reference.offset)) {
+ status = AE_OK;
+ }
+ else {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+ "[%s]: Could not resolve operands, %s\n",
+ acpi_ps_get_opcode_name (walk_state->opcode),
+ acpi_format_exception (status)));
+ }
+ }
+
+ /* Always delete the argument objects and clear the operand stack */
+
+ acpi_ds_clear_operands (walk_state);
+
+ /*
+ * If a result object was returned from above, push it on the
+ * current result stack
+ */
+ if (ACPI_SUCCESS (status) &&
+ walk_state->result_obj) {
+ status = acpi_ds_result_push (walk_state->result_obj, walk_state);
+ }
+
+ break;
+
+
+ default:
+
+ switch (op_type) {
+ case AML_TYPE_CONTROL: /* Type 1 opcode, IF/ELSE/WHILE/NOOP */
+
+ /* 1 Operand, 0 external_result, 0 internal_result */
+
+ status = acpi_ds_exec_end_control_op (walk_state, op);
+
+ /* Make sure to properly pop the result stack */
+
+ if (ACPI_SUCCESS (status)) {
+ status = acpi_ds_result_stack_pop (walk_state);
+ }
+ else if (status == AE_CTRL_PENDING) {
+ status = acpi_ds_result_stack_pop (walk_state);
+ if (ACPI_SUCCESS (status)) {
+ status = AE_CTRL_PENDING;
+ }
+ }
+ break;
+
+
+ case AML_TYPE_METHOD_CALL:
+
+ /*
+ * If the method is referenced from within a package
+ * declaration, it is not a invocation of the method, just
+ * a reference to it.
+ */
+ if ((op->asl.parent) &&
+ ((op->asl.parent->asl.aml_opcode == AML_PACKAGE_OP) ||
+ (op->asl.parent->asl.aml_opcode == AML_VAR_PACKAGE_OP))) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Method Reference in a Package, Op=%p\n", op));
+ op->common.node = (struct acpi_namespace_node *) op->asl.value.arg->asl.node->object;
+ acpi_ut_add_reference (op->asl.value.arg->asl.node->object);
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Method invocation, Op=%p\n", op));
+
+ /*
+ * (AML_METHODCALL) Op->Asl.Value.Arg->Asl.Node contains
+ * the method Node pointer
+ */
+ /* next_op points to the op that holds the method name */
+
+ next_op = first_arg;
+
+ /* next_op points to first argument op */
+
+ next_op = next_op->common.next;
+
+ /*
+ * Get the method's arguments and put them on the operand stack
+ */
+ status = acpi_ds_create_operands (walk_state, next_op);
+ if (ACPI_FAILURE (status)) {
+ break;
+ }
+
+ /*
+ * Since the operands will be passed to another control method,
+ * we must resolve all local references here (Local variables,
+ * arguments to *this* method, etc.)
+ */
+ status = acpi_ds_resolve_operands (walk_state);
+ if (ACPI_FAILURE (status)) {
+ /* On error, clear all resolved operands */
+
+ acpi_ds_clear_operands (walk_state);
+ break;
+ }
+
+ /*
+ * Tell the walk loop to preempt this running method and
+ * execute the new method
+ */
+ status = AE_CTRL_TRANSFER;
+
+ /*
+ * Return now; we don't want to disturb anything,
+ * especially the operand count!
+ */
+ return_ACPI_STATUS (status);
+
+
+ case AML_TYPE_CREATE_FIELD:
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
+ "Executing create_field Buffer/Index Op=%p\n", op));
+
+ status = acpi_ds_load2_end_op (walk_state);
+ if (ACPI_FAILURE (status)) {
+ break;
+ }
+
+ status = acpi_ds_eval_buffer_field_operands (walk_state, op);
+ break;
+
+
+ case AML_TYPE_CREATE_OBJECT:
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
+ "Executing create_object (Buffer/Package) Op=%p\n", op));
+
+ switch (op->common.parent->common.aml_opcode) {
+ case AML_NAME_OP:
+
+ /*
+ * Put the Node on the object stack (Contains the ACPI Name of
+ * this object)
+ */
+ walk_state->operands[0] = (void *) op->common.parent->common.node;
+ walk_state->num_operands = 1;
+
+ status = acpi_ds_create_node (walk_state, op->common.parent->common.node, op->common.parent);
+ if (ACPI_FAILURE (status)) {
+ break;
+ }
+
+ /* Fall through */
+ /*lint -fallthrough */
+
+ case AML_INT_EVAL_SUBTREE_OP:
+
+ status = acpi_ds_eval_data_object_operands (walk_state, op,
+ acpi_ns_get_attached_object (op->common.parent->common.node));
+ break;
+
+ default:
+
+ status = acpi_ds_eval_data_object_operands (walk_state, op, NULL);
+ break;
+ }
+
+ /* Done with this result state (Now that operand stack is built) */
+
+ status = acpi_ds_result_stack_pop (walk_state);
+ if (ACPI_FAILURE (status)) {
+ goto cleanup;
+ }
+
+ /*
+ * If a result object was returned from above, push it on the
+ * current result stack
+ */
+ if (ACPI_SUCCESS (status) &&
+ walk_state->result_obj) {
+ status = acpi_ds_result_push (walk_state->result_obj, walk_state);
+ }
+ break;
+
+
+ case AML_TYPE_NAMED_FIELD:
+ case AML_TYPE_NAMED_COMPLEX:
+ case AML_TYPE_NAMED_SIMPLE:
+ case AML_TYPE_NAMED_NO_OBJ:
+
+ status = acpi_ds_load2_end_op (walk_state);
+ if (ACPI_FAILURE (status)) {
+ break;
+ }
+
+ if (op->common.aml_opcode == AML_REGION_OP) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
+ "Executing op_region Address/Length Op=%p\n", op));
+
+ status = acpi_ds_eval_region_operands (walk_state, op);
+ if (ACPI_FAILURE (status)) {
+ break;
+ }
+
+ status = acpi_ds_result_stack_pop (walk_state);
+ }
+
+ break;
+
+
+ case AML_TYPE_UNDEFINED:
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Undefined opcode type Op=%p\n", op));
+ return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
+
+
+ case AML_TYPE_BOGUS:
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+ "Internal opcode=%X type Op=%p\n",
+ walk_state->opcode, op));
+ break;
+
+
+ default:
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+ "Unimplemented opcode, class=%X type=%X Opcode=%X Op=%p\n",
+ op_class, op_type, op->common.aml_opcode, op));
+
+ status = AE_NOT_IMPLEMENTED;
+ break;
+ }
+ }
+
+ /*
+ * ACPI 2.0 support for 64-bit integers: Truncate numeric
+ * result value if we are executing from a 32-bit ACPI table
+ */
+ acpi_ex_truncate_for32bit_table (walk_state->result_obj);
+
+ /*
+ * Check if we just completed the evaluation of a
+ * conditional predicate
+ */
+
+ if ((ACPI_SUCCESS (status)) &&
+ (walk_state->control_state) &&
+ (walk_state->control_state->common.state ==
+ ACPI_CONTROL_PREDICATE_EXECUTING) &&
+ (walk_state->control_state->control.predicate_op == op)) {
+ status = acpi_ds_get_predicate_value (walk_state, walk_state->result_obj);
+ walk_state->result_obj = NULL;
+ }
+
+
+cleanup:
+
+ /* Invoke exception handler on error */
+
+ if (ACPI_FAILURE (status) &&
+ acpi_gbl_exception_handler &&
+ !(status & AE_CODE_CONTROL)) {
+ acpi_ex_exit_interpreter ();
+ status = acpi_gbl_exception_handler (status,
+ walk_state->method_node->name.integer, walk_state->opcode,
+ walk_state->aml_offset, NULL);
+ acpi_ex_enter_interpreter ();
+ }
+
+ if (walk_state->result_obj) {
+ /* Break to debugger to display result */
+
+ ACPI_DEBUGGER_EXEC (acpi_db_display_result_object (walk_state->result_obj, walk_state));
+
+ /*
+ * Delete the result op if and only if:
+ * Parent will not use the result -- such as any
+ * non-nested type2 op in a method (parent will be method)
+ */
+ acpi_ds_delete_result_if_not_used (op, walk_state->result_obj, walk_state);
+ }
+
+#ifdef _UNDER_DEVELOPMENT
+
+ if (walk_state->parser_state.aml == walk_state->parser_state.aml_end) {
+ acpi_db_method_end (walk_state);
+ }
+#endif
+
+ /* Always clear the object stack */
+
+ walk_state->num_operands = 0;
+
+#ifdef ACPI_DISASSEMBLER
+
+ /* On error, display method locals/args */
+
+ if (ACPI_FAILURE (status)) {
+ acpi_dm_dump_method_info (status, walk_state, op);
+ }
+#endif
+
+ return_ACPI_STATUS (status);
+}
+
+
diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c
new file mode 100644
index 00000000000..06d75867958
--- /dev/null
+++ b/drivers/acpi/dispatcher/dswload.c
@@ -0,0 +1,976 @@
+/******************************************************************************
+ *
+ * Module Name: dswload - Dispatcher namespace load callbacks
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2005, R. Byron Moore
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+
+#include <acpi/acpi.h>
+#include <acpi/acparser.h>
+#include <acpi/amlcode.h>
+#include <acpi/acdispat.h>
+#include <acpi/acinterp.h>
+#include <acpi/acnamesp.h>
+#include <acpi/acevents.h>
+
+#ifdef _ACPI_ASL_COMPILER
+#include <acpi/acdisasm.h>
+#endif
+
+#define _COMPONENT ACPI_DISPATCHER
+ ACPI_MODULE_NAME ("dswload")
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_init_callbacks
+ *
+ * PARAMETERS: walk_state - Current state of the parse tree walk
+ * pass_number - 1, 2, or 3
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Init walk state callbacks
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_init_callbacks (
+ struct acpi_walk_state *walk_state,
+ u32 pass_number)
+{
+
+ switch (pass_number) {
+ case 1:
+ walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE;
+ walk_state->descending_callback = acpi_ds_load1_begin_op;
+ walk_state->ascending_callback = acpi_ds_load1_end_op;
+ break;
+
+ case 2:
+ walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE;
+ walk_state->descending_callback = acpi_ds_load2_begin_op;
+ walk_state->ascending_callback = acpi_ds_load2_end_op;
+ break;
+
+ case 3:
+#ifndef ACPI_NO_METHOD_EXECUTION
+ walk_state->parse_flags |= ACPI_PARSE_EXECUTE | ACPI_PARSE_DELETE_TREE;
+ walk_state->descending_callback = acpi_ds_exec_begin_op;
+ walk_state->ascending_callback = acpi_ds_exec_end_op;
+#endif
+ break;
+
+ default:
+ return (AE_BAD_PARAMETER);
+ }
+
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_load1_begin_op
+ *
+ * PARAMETERS: walk_state - Current state of the parse tree walk
+ * Op - Op that has been just been reached in the
+ * walk; Arguments have not been evaluated yet.
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Descending callback used during the loading of ACPI tables.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_load1_begin_op (
+ struct acpi_walk_state *walk_state,
+ union acpi_parse_object **out_op)
+{
+ union acpi_parse_object *op;
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ acpi_object_type object_type;
+ char *path;
+ u32 flags;
+
+
+ ACPI_FUNCTION_NAME ("ds_load1_begin_op");
+
+
+ op = walk_state->op;
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state));
+
+ /* We are only interested in opcodes that have an associated name */
+
+ if (op) {
+ if (!(walk_state->op_info->flags & AML_NAMED)) {
+#if 0
+ if ((walk_state->op_info->class == AML_CLASS_EXECUTE) ||
+ (walk_state->op_info->class == AML_CLASS_CONTROL)) {
+ acpi_os_printf ("\n\n***EXECUTABLE OPCODE %s***\n\n", walk_state->op_info->name);
+ *out_op = op;
+ return (AE_CTRL_SKIP);
+ }
+#endif
+ *out_op = op;
+ return (AE_OK);
+ }
+
+ /* Check if this object has already been installed in the namespace */
+
+ if (op->common.node) {
+ *out_op = op;
+ return (AE_OK);
+ }
+ }
+
+ path = acpi_ps_get_next_namestring (&walk_state->parser_state);
+
+ /* Map the raw opcode into an internal object type */
+
+ object_type = walk_state->op_info->object_type;
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+ "State=%p Op=%p [%s]\n", walk_state, op, acpi_ut_get_type_name (object_type)));
+
+ switch (walk_state->opcode) {
+ case AML_SCOPE_OP:
+
+ /*
+ * The target name of the Scope() operator must exist at this point so
+ * that we can actually open the scope to enter new names underneath it.
+ * Allow search-to-root for single namesegs.
+ */
+ status = acpi_ns_lookup (walk_state->scope_info, path, object_type,
+ ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, &(node));
+#ifdef _ACPI_ASL_COMPILER
+ if (status == AE_NOT_FOUND) {
+ /*
+ * Table disassembly:
+ * Target of Scope() not found. Generate an External for it, and
+ * insert the name into the namespace.
+ */
+ acpi_dm_add_to_external_list (path);
+ status = acpi_ns_lookup (walk_state->scope_info, path, object_type,
+ ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT, walk_state, &(node));
+ }
+#endif
+ if (ACPI_FAILURE (status)) {
+ ACPI_REPORT_NSERROR (path, status);
+ return (status);
+ }
+
+ /*
+ * Check to make sure that the target is
+ * one of the opcodes that actually opens a scope
+ */
+ switch (node->type) {
+ case ACPI_TYPE_LOCAL_SCOPE: /* Scope */
+ case ACPI_TYPE_DEVICE:
+ case ACPI_TYPE_POWER:
+ case ACPI_TYPE_PROCESSOR:
+ case ACPI_TYPE_THERMAL:
+
+ /* These are acceptable types */
+ break;
+
+ case ACPI_TYPE_INTEGER:
+ case ACPI_TYPE_STRING:
+ case ACPI_TYPE_BUFFER:
+
+ /*
+ * These types we will allow, but we will change the type. This
+ * enables some existing code of the form:
+ *
+ * Name (DEB, 0)
+ * Scope (DEB) { ... }
+ *
+ * Note: silently change the type here. On the second pass, we will report a warning
+ */
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)\n",
+ path, acpi_ut_get_type_name (node->type)));
+
+ node->type = ACPI_TYPE_ANY;
+ walk_state->scope_info->common.value = ACPI_TYPE_ANY;
+ break;
+
+ default:
+
+ /* All other types are an error */
+
+ ACPI_REPORT_ERROR (("Invalid type (%s) for target of Scope operator [%4.4s] (Cannot override)\n",
+ acpi_ut_get_type_name (node->type), path));
+
+ return (AE_AML_OPERAND_TYPE);
+ }
+ break;
+
+
+ default:
+
+ /*
+ * For all other named opcodes, we will enter the name into the namespace.
+ *
+ * Setup the search flags.
+ * Since we are entering a name into the namespace, we do not want to
+ * enable the search-to-root upsearch.
+ *
+ * There are only two conditions where it is acceptable that the name
+ * already exists:
+ * 1) the Scope() operator can reopen a scoping object that was
+ * previously defined (Scope, Method, Device, etc.)
+ * 2) Whenever we are parsing a deferred opcode (op_region, Buffer,
+ * buffer_field, or Package), the name of the object is already
+ * in the namespace.
+ */
+ if (walk_state->deferred_node) {
+ /* This name is already in the namespace, get the node */
+
+ node = walk_state->deferred_node;
+ status = AE_OK;
+ break;
+ }
+
+ flags = ACPI_NS_NO_UPSEARCH;
+ if ((walk_state->opcode != AML_SCOPE_OP) &&
+ (!(walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP))) {
+ flags |= ACPI_NS_ERROR_IF_FOUND;
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[%s] Cannot already exist\n",
+ acpi_ut_get_type_name (object_type)));
+ }
+ else {
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[%s] Both Find or Create allowed\n",
+ acpi_ut_get_type_name (object_type)));
+ }
+
+ /*
+ * Enter the named type into the internal namespace. We enter the name
+ * as we go downward in the parse tree. Any necessary subobjects that involve
+ * arguments to the opcode must be created as we go back up the parse tree later.
+ */
+ status = acpi_ns_lookup (walk_state->scope_info, path, object_type,
+ ACPI_IMODE_LOAD_PASS1, flags, walk_state, &(node));
+ if (ACPI_FAILURE (status)) {
+ ACPI_REPORT_NSERROR (path, status);
+ return (status);
+ }
+ break;
+ }
+
+
+ /* Common exit */
+
+ if (!op) {
+ /* Create a new op */
+
+ op = acpi_ps_alloc_op (walk_state->opcode);
+ if (!op) {
+ return (AE_NO_MEMORY);
+ }
+ }
+
+ /* Initialize */
+
+ op->named.name = node->name.integer;
+
+#if (defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY))
+ op->named.path = (u8 *) path;
+#endif
+
+
+ /*
+ * Put the Node in the "op" object that the parser uses, so we
+ * can get it again quickly when this scope is closed
+ */
+ op->common.node = node;
+ acpi_ps_append_arg (acpi_ps_get_parent_scope (&walk_state->parser_state), op);
+
+ *out_op = op;
+ return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_load1_end_op
+ *
+ * PARAMETERS: walk_state - Current state of the parse tree walk
+ * Op - Op that has been just been completed in the
+ * walk; Arguments have now been evaluated.
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Ascending callback used during the loading of the namespace,
+ * both control methods and everything else.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_load1_end_op (
+ struct acpi_walk_state *walk_state)
+{
+ union acpi_parse_object *op;
+ acpi_object_type object_type;
+ acpi_status status = AE_OK;
+
+
+ ACPI_FUNCTION_NAME ("ds_load1_end_op");
+
+
+ op = walk_state->op;
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state));
+
+ /* We are only interested in opcodes that have an associated name */
+
+ if (!(walk_state->op_info->flags & (AML_NAMED | AML_FIELD))) {
+ return (AE_OK);
+ }
+
+ /* Get the object type to determine if we should pop the scope */
+
+ object_type = walk_state->op_info->object_type;
+
+#ifndef ACPI_NO_METHOD_EXECUTION
+ if (walk_state->op_info->flags & AML_FIELD) {
+ if (walk_state->opcode == AML_FIELD_OP ||
+ walk_state->opcode == AML_BANK_FIELD_OP ||
+ walk_state->opcode == AML_INDEX_FIELD_OP) {
+ status = acpi_ds_init_field_objects (op, walk_state);
+ }
+ return (status);
+ }
+
+
+ if (op->common.aml_opcode == AML_REGION_OP) {
+ status = acpi_ex_create_region (op->named.data, op->named.length,
+ (acpi_adr_space_type) ((op->common.value.arg)->common.value.integer), walk_state);
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+ }
+#endif
+
+ if (op->common.aml_opcode == AML_NAME_OP) {
+ /* For Name opcode, get the object type from the argument */
+
+ if (op->common.value.arg) {
+ object_type = (acpi_ps_get_opcode_info ((op->common.value.arg)->common.aml_opcode))->object_type;
+ op->common.node->type = (u8) object_type;
+ }
+ }
+
+ if (op->common.aml_opcode == AML_METHOD_OP) {
+ /*
+ * method_op pkg_length name_string method_flags term_list
+ *
+ * Note: We must create the method node/object pair as soon as we
+ * see the method declaration. This allows later pass1 parsing
+ * of invocations of the method (need to know the number of
+ * arguments.)
+ */
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+ "LOADING-Method: State=%p Op=%p named_obj=%p\n",
+ walk_state, op, op->named.node));
+
+ if (!acpi_ns_get_attached_object (op->named.node)) {
+ walk_state->operands[0] = (void *) op->named.node;
+ walk_state->num_operands = 1;
+
+ status = acpi_ds_create_operands (walk_state, op->common.value.arg);
+ if (ACPI_SUCCESS (status)) {
+ status = acpi_ex_create_method (op->named.data,
+ op->named.length, walk_state);
+ }
+ walk_state->operands[0] = NULL;
+ walk_state->num_operands = 0;
+
+ if (ACPI_FAILURE (status)) {
+ return (status);
+ }
+ }
+ }
+
+ /* Pop the scope stack */
+
+ if (acpi_ns_opens_scope (object_type)) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s): Popping scope for Op %p\n",
+ acpi_ut_get_type_name (object_type), op));
+
+ status = acpi_ds_scope_stack_pop (walk_state);
+ }
+
+ return (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_load2_begin_op
+ *
+ * PARAMETERS: walk_state - Current state of the parse tree walk
+ * Op - Op that has been just been reached in the
+ * walk; Arguments have not been evaluated yet.
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Descending callback used during the loading of ACPI tables.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_load2_begin_op (
+ struct acpi_walk_state *walk_state,
+ union acpi_parse_object **out_op)
+{
+ union acpi_parse_object *op;
+ struct acpi_namespace_node *node;
+ acpi_status status;
+ acpi_object_type object_type;
+ char *buffer_ptr;
+
+
+ ACPI_FUNCTION_TRACE ("ds_load2_begin_op");
+
+
+ op = walk_state->op;
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state));
+
+ if (op) {
+ /* We only care about Namespace opcodes here */
+
+ if ((!(walk_state->op_info->flags & AML_NSOPCODE) && (walk_state->opcode != AML_INT_NAMEPATH_OP)) ||
+ (!(walk_state->op_info->flags & AML_NAMED))) {
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ /*
+ * Get the name we are going to enter or lookup in the namespace
+ */
+ if (walk_state->opcode == AML_INT_NAMEPATH_OP) {
+ /* For Namepath op, get the path string */
+
+ buffer_ptr = op->common.value.string;
+ if (!buffer_ptr) {
+ /* No name, just exit */
+
+ return_ACPI_STATUS (AE_OK);
+ }
+ }
+ else {
+ /* Get name from the op */
+
+ buffer_ptr = (char *) &op->named.name;
+ }
+ }
+ else {
+ /* Get the namestring from the raw AML */
+
+ buffer_ptr = acpi_ps_get_next_namestring (&walk_state->parser_state);
+ }
+
+ /* Map the opcode into an internal object type */
+
+ object_type = walk_state->op_info->object_type;
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+ "State=%p Op=%p Type=%X\n", walk_state, op, object_type));
+
+
+ switch (walk_state->opcode) {
+ case AML_FIELD_OP:
+ case AML_BANK_FIELD_OP:
+ case AML_INDEX_FIELD_OP:
+
+ node = NULL;
+ status = AE_OK;
+ break;
+
+ case AML_INT_NAMEPATH_OP:
+
+ /*
+ * The name_path is an object reference to an existing object. Don't enter the
+ * name into the namespace, but look it up for use later
+ */
+ status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, object_type,
+ ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, &(node));
+ break;
+
+ case AML_SCOPE_OP:
+
+ /*
+ * The Path is an object reference to an existing object. Don't enter the
+ * name into the namespace, but look it up for use later
+ */
+ status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, object_type,
+ ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, walk_state, &(node));
+ if (ACPI_FAILURE (status)) {
+#ifdef _ACPI_ASL_COMPILER
+ if (status == AE_NOT_FOUND) {
+ status = AE_OK;
+ }
+ else {
+ ACPI_REPORT_NSERROR (buffer_ptr, status);
+ }
+#else
+ ACPI_REPORT_NSERROR (buffer_ptr, status);
+#endif
+ return_ACPI_STATUS (status);
+ }
+ /*
+ * We must check to make sure that the target is
+ * one of the opcodes that actually opens a scope
+ */
+ switch (node->type) {
+ case ACPI_TYPE_LOCAL_SCOPE: /* Scope */
+ case ACPI_TYPE_DEVICE:
+ case ACPI_TYPE_POWER:
+ case ACPI_TYPE_PROCESSOR:
+ case ACPI_TYPE_THERMAL:
+
+ /* These are acceptable types */
+ break;
+
+ case ACPI_TYPE_INTEGER:
+ case ACPI_TYPE_STRING:
+ case ACPI_TYPE_BUFFER:
+
+ /*
+ * These types we will allow, but we will change the type. This
+ * enables some existing code of the form:
+ *
+ * Name (DEB, 0)
+ * Scope (DEB) { ... }
+ */
+
+ ACPI_REPORT_WARNING (("Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)\n",
+ buffer_ptr, acpi_ut_get_type_name (node->type)));
+
+ node->type = ACPI_TYPE_ANY;
+ walk_state->scope_info->common.value = ACPI_TYPE_ANY;
+ break;
+
+ default:
+
+ /* All other types are an error */
+
+ ACPI_REPORT_ERROR (("Invalid type (%s) for target of Scope operator [%4.4s]\n",
+ acpi_ut_get_type_name (node->type), buffer_ptr));
+
+ return (AE_AML_OPERAND_TYPE);
+ }
+ break;
+
+ default:
+
+ /* All other opcodes */
+
+ if (op && op->common.node) {
+ /* This op/node was previously entered into the namespace */
+
+ node = op->common.node;
+
+ if (acpi_ns_opens_scope (object_type)) {
+ status = acpi_ds_scope_stack_push (node, object_type, walk_state);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ }
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ /*
+ * Enter the named type into the internal namespace. We enter the name
+ * as we go downward in the parse tree. Any necessary subobjects that involve
+ * arguments to the opcode must be created as we go back up the parse tree later.
+ *
+ * Note: Name may already exist if we are executing a deferred opcode.
+ */
+ if (walk_state->deferred_node) {
+ /* This name is already in the namespace, get the node */
+
+ node = walk_state->deferred_node;
+ status = AE_OK;
+ break;
+ }
+
+ status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr, object_type,
+ ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, walk_state, &(node));
+ break;
+ }
+
+ if (ACPI_FAILURE (status)) {
+ ACPI_REPORT_NSERROR (buffer_ptr, status);
+ return_ACPI_STATUS (status);
+ }
+
+
+ if (!op) {
+ /* Create a new op */
+
+ op = acpi_ps_alloc_op (walk_state->opcode);
+ if (!op) {
+ return_ACPI_STATUS (AE_NO_MEMORY);
+ }
+
+ /* Initialize the new op */
+
+ if (node) {
+ op->named.name = node->name.integer;
+ }
+ if (out_op) {
+ *out_op = op;
+ }
+ }
+
+ /*
+ * Put the Node in the "op" object that the parser uses, so we
+ * can get it again quickly when this scope is closed
+ */
+ op->common.node = node;
+
+ return_ACPI_STATUS (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_load2_end_op
+ *
+ * PARAMETERS: walk_state - Current state of the parse tree walk
+ * Op - Op that has been just been completed in the
+ * walk; Arguments have now been evaluated.
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Ascending callback used during the loading of the namespace,
+ * both control methods and everything else.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_load2_end_op (
+ struct acpi_walk_state *walk_state)
+{
+ union acpi_parse_object *op;
+ acpi_status status = AE_OK;
+ acpi_object_type object_type;
+ struct acpi_namespace_node *node;
+ union acpi_parse_object *arg;
+ struct acpi_namespace_node *new_node;
+#ifndef ACPI_NO_METHOD_EXECUTION
+ u32 i;
+#endif
+
+
+ ACPI_FUNCTION_TRACE ("ds_load2_end_op");
+
+ op = walk_state->op;
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n",
+ walk_state->op_info->name, op, walk_state));
+
+ /* Only interested in opcodes that have namespace objects */
+
+ if (!(walk_state->op_info->flags & AML_NSOBJECT)) {
+ return_ACPI_STATUS (AE_OK);
+ }
+
+ if (op->common.aml_opcode == AML_SCOPE_OP) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+ "Ending scope Op=%p State=%p\n", op, walk_state));
+ }
+
+
+ object_type = walk_state->op_info->object_type;
+
+ /*
+ * Get the Node/name from the earlier lookup
+ * (It was saved in the *op structure)
+ */
+ node = op->common.node;
+
+ /*
+ * Put the Node on the object stack (Contains the ACPI Name of
+ * this object)
+ */
+ walk_state->operands[0] = (void *) node;
+ walk_state->num_operands = 1;
+
+ /* Pop the scope stack */
+
+ if (acpi_ns_opens_scope (object_type) && (op->common.aml_opcode != AML_INT_METHODCALL_OP)) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "(%s) Popping scope for Op %p\n",
+ acpi_ut_get_type_name (object_type), op));
+
+ status = acpi_ds_scope_stack_pop (walk_state);
+ if (ACPI_FAILURE (status)) {
+ goto cleanup;
+ }
+ }
+
+ /*
+ * Named operations are as follows:
+ *
+ * AML_ALIAS
+ * AML_BANKFIELD
+ * AML_CREATEBITFIELD
+ * AML_CREATEBYTEFIELD
+ * AML_CREATEDWORDFIELD
+ * AML_CREATEFIELD
+ * AML_CREATEQWORDFIELD
+ * AML_CREATEWORDFIELD
+ * AML_DATA_REGION
+ * AML_DEVICE
+ * AML_EVENT
+ * AML_FIELD
+ * AML_INDEXFIELD
+ * AML_METHOD
+ * AML_METHODCALL
+ * AML_MUTEX
+ * AML_NAME
+ * AML_NAMEDFIELD
+ * AML_OPREGION
+ * AML_POWERRES
+ * AML_PROCESSOR
+ * AML_SCOPE
+ * AML_THERMALZONE
+ */
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+ "Create-Load [%s] State=%p Op=%p named_obj=%p\n",
+ acpi_ps_get_opcode_name (op->common.aml_opcode), walk_state, op, node));
+
+ /* Decode the opcode */
+
+ arg = op->common.value.arg;
+
+ switch (walk_state->op_info->type) {
+#ifndef ACPI_NO_METHOD_EXECUTION
+
+ case AML_TYPE_CREATE_FIELD:
+
+ /*
+ * Create the field object, but the field buffer and index must
+ * be evaluated later during the execution phase
+ */
+ status = acpi_ds_create_buffer_field (op, walk_state);
+ break;
+
+
+ case AML_TYPE_NAMED_FIELD:
+
+ switch (op->common.aml_opcode) {
+ case AML_INDEX_FIELD_OP:
+
+ status = acpi_ds_create_index_field (op, (acpi_handle) arg->common.node,
+ walk_state);
+ break;
+
+ case AML_BANK_FIELD_OP:
+
+ status = acpi_ds_create_bank_field (op, arg->common.node, walk_state);
+ break;
+
+ case AML_FIELD_OP:
+
+ status = acpi_ds_create_field (op, arg->common.node, walk_state);
+ break;
+
+ default:
+ /* All NAMED_FIELD opcodes must be handled above */
+ break;
+ }
+ break;
+
+
+ case AML_TYPE_NAMED_SIMPLE:
+
+ status = acpi_ds_create_operands (walk_state, arg);
+ if (ACPI_FAILURE (status)) {
+ goto cleanup;
+ }
+
+ switch (op->common.aml_opcode) {
+ case AML_PROCESSOR_OP:
+
+ status = acpi_ex_create_processor (walk_state);
+ break;
+
+ case AML_POWER_RES_OP:
+
+ status = acpi_ex_create_power_resource (walk_state);
+ break;
+
+ case AML_MUTEX_OP:
+
+ status = acpi_ex_create_mutex (walk_state);
+ break;
+
+ case AML_EVENT_OP:
+
+ status = acpi_ex_create_event (walk_state);
+ break;
+
+ case AML_DATA_REGION_OP:
+
+ status = acpi_ex_create_table_region (walk_state);
+ break;
+
+ case AML_ALIAS_OP:
+
+ status = acpi_ex_create_alias (walk_state);
+ break;
+
+ default:
+ /* Unknown opcode */
+
+ status = AE_OK;
+ goto cleanup;
+ }
+
+ /* Delete operands */
+
+ for (i = 1; i < walk_state->num_operands; i++) {
+ acpi_ut_remove_reference (walk_state->operands[i]);
+ walk_state->operands[i] = NULL;
+ }
+
+ break;
+#endif /* ACPI_NO_METHOD_EXECUTION */
+
+ case AML_TYPE_NAMED_COMPLEX:
+
+ switch (op->common.aml_opcode) {
+#ifndef ACPI_NO_METHOD_EXECUTION
+ case AML_REGION_OP:
+ /*
+ * The op_region is not fully parsed at this time. Only valid argument is the space_id.
+ * (We must save the address of the AML of the address and length operands)
+ */
+ /*
+ * If we have a valid region, initialize it
+ * Namespace is NOT locked at this point.
+ */
+ status = acpi_ev_initialize_region (acpi_ns_get_attached_object (node), FALSE);
+ if (ACPI_FAILURE (status)) {
+ /*
+ * If AE_NOT_EXIST is returned, it is not fatal
+ * because many regions get created before a handler
+ * is installed for said region.
+ */
+ if (AE_NOT_EXIST == status) {
+ status = AE_OK;
+ }
+ }
+ break;
+
+
+ case AML_NAME_OP:
+
+ status = acpi_ds_create_node (walk_state, node, op);
+ break;
+#endif /* ACPI_NO_METHOD_EXECUTION */
+
+
+ default:
+ /* All NAMED_COMPLEX opcodes must be handled above */
+ /* Note: Method objects were already created in Pass 1 */
+ break;
+ }
+ break;
+
+
+ case AML_CLASS_INTERNAL:
+
+ /* case AML_INT_NAMEPATH_OP: */
+ break;
+
+
+ case AML_CLASS_METHOD_CALL:
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
+ "RESOLVING-method_call: State=%p Op=%p named_obj=%p\n",
+ walk_state, op, node));
+
+ /*
+ * Lookup the method name and save the Node
+ */
+ status = acpi_ns_lookup (walk_state->scope_info, arg->common.value.string,
+ ACPI_TYPE_ANY, ACPI_IMODE_LOAD_PASS2,
+ ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
+ walk_state, &(new_node));
+ if (ACPI_SUCCESS (status)) {
+ /*
+ * Make sure that what we found is indeed a method
+ * We didn't search for a method on purpose, to see if the name would resolve
+ */
+ if (new_node->type != ACPI_TYPE_METHOD) {
+ status = AE_AML_OPERAND_TYPE;
+ }
+
+ /* We could put the returned object (Node) on the object stack for later, but
+ * for now, we will put it in the "op" object that the parser uses, so we
+ * can get it again at the end of this scope
+ */
+ op->common.node = new_node;
+ }
+ else {
+ ACPI_REPORT_NSERROR (arg->common.value.string, status);
+ }
+ break;
+
+
+ default:
+ break;
+ }
+
+cleanup:
+
+ /* Remove the Node pushed at the very beginning */
+
+ walk_state->operands[0] = NULL;
+ walk_state->num_operands = 0;
+ return_ACPI_STATUS (status);
+}
+
+
diff --git a/drivers/acpi/dispatcher/dswscope.c b/drivers/acpi/dispatcher/dswscope.c
new file mode 100644
index 00000000000..65f456151e2
--- /dev/null
+++ b/drivers/acpi/dispatcher/dswscope.c
@@ -0,0 +1,229 @@
+/******************************************************************************
+ *
+ * Module Name: dswscope - Scope stack manipulation
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2005, R. Byron Moore
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+
+#include <acpi/acpi.h>
+#include <acpi/acdispat.h>
+
+
+#define _COMPONENT ACPI_DISPATCHER
+ ACPI_MODULE_NAME ("dswscope")
+
+
+#define STACK_POP(head) head
+
+
+/****************************************************************************
+ *
+ * FUNCTION: acpi_ds_scope_stack_clear
+ *
+ * PARAMETERS: None
+ *
+ * DESCRIPTION: Pop (and free) everything on the scope stack except the
+ * root scope object (which remains at the stack top.)
+ *
+ ***************************************************************************/
+
+void
+acpi_ds_scope_stack_clear (
+ struct acpi_walk_state *walk_state)
+{
+ union acpi_generic_state *scope_info;
+
+ ACPI_FUNCTION_NAME ("ds_scope_stack_clear");
+
+
+ while (walk_state->scope_info) {
+ /* Pop a scope off the stack */
+
+ scope_info = walk_state->scope_info;
+ walk_state->scope_info = scope_info->scope.next;
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
+ "Popped object type (%s)\n", acpi_ut_get_type_name (scope_info->common.value)));
+ acpi_ut_delete_generic_state (scope_info);
+ }
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: acpi_ds_scope_stack_push
+ *
+ * PARAMETERS: *Node, - Name to be made current
+ * Type, - Type of frame being pushed
+ *
+ * DESCRIPTION: Push the current scope on the scope stack, and make the
+ * passed Node current.
+ *
+ ***************************************************************************/
+
+acpi_status
+acpi_ds_scope_stack_push (
+ struct acpi_namespace_node *node,
+ acpi_object_type type,
+ struct acpi_walk_state *walk_state)
+{
+ union acpi_generic_state *scope_info;
+ union acpi_generic_state *old_scope_info;
+
+
+ ACPI_FUNCTION_TRACE ("ds_scope_stack_push");
+
+
+ if (!node) {
+ /* Invalid scope */
+
+ ACPI_REPORT_ERROR (("ds_scope_stack_push: null scope passed\n"));
+ return_ACPI_STATUS (AE_BAD_PARAMETER);
+ }
+
+ /* Make sure object type is valid */
+
+ if (!acpi_ut_valid_object_type (type)) {
+ ACPI_REPORT_WARNING (("ds_scope_stack_push: Invalid object type: 0x%X\n", type));
+ }
+
+ /* Allocate a new scope object */
+
+ scope_info = acpi_ut_create_generic_state ();
+ if (!scope_info) {
+ return_ACPI_STATUS (AE_NO_MEMORY);
+ }
+
+ /* Init new scope object */
+
+ scope_info->common.data_type = ACPI_DESC_TYPE_STATE_WSCOPE;
+ scope_info->scope.node = node;
+ scope_info->common.value = (u16) type;
+
+ walk_state->scope_depth++;
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
+ "[%.2d] Pushed scope ", (u32) walk_state->scope_depth));
+
+ old_scope_info = walk_state->scope_info;
+ if (old_scope_info) {
+ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC,
+ "[%4.4s] (%s)",
+ acpi_ut_get_node_name (old_scope_info->scope.node),
+ acpi_ut_get_type_name (old_scope_info->common.value)));
+ }
+ else {
+ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC,
+ "[\\___] (%s)", "ROOT"));
+ }
+
+ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC,
+ ", New scope -> [%4.4s] (%s)\n",
+ acpi_ut_get_node_name (scope_info->scope.node),
+ acpi_ut_get_type_name (scope_info->common.value)));
+
+ /* Push new scope object onto stack */
+
+ acpi_ut_push_generic_state (&walk_state->scope_info, scope_info);
+ return_ACPI_STATUS (AE_OK);
+}
+
+
+/****************************************************************************
+ *
+ * FUNCTION: acpi_ds_scope_stack_pop
+ *
+ * PARAMETERS: Type - The type of frame to be found
+ *
+ * DESCRIPTION: Pop the scope stack until a frame of the requested type
+ * is found.
+ *
+ * RETURN: Count of frames popped. If no frame of the requested type
+ * was found, the count is returned as a negative number and
+ * the scope stack is emptied (which sets the current scope
+ * to the root). If the scope stack was empty at entry, the
+ * function is a no-op and returns 0.
+ *
+ ***************************************************************************/
+
+acpi_status
+acpi_ds_scope_stack_pop (
+ struct acpi_walk_state *walk_state)
+{
+ union acpi_generic_state *scope_info;
+ union acpi_generic_state *new_scope_info;
+
+
+ ACPI_FUNCTION_TRACE ("ds_scope_stack_pop");
+
+
+ /*
+ * Pop scope info object off the stack.
+ */
+ scope_info = acpi_ut_pop_generic_state (&walk_state->scope_info);
+ if (!scope_info) {
+ return_ACPI_STATUS (AE_STACK_UNDERFLOW);
+ }
+
+ walk_state->scope_depth--;
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
+ "[%.2d] Popped scope [%4.4s] (%s), New scope -> ",
+ (u32) walk_state->scope_depth,
+ acpi_ut_get_node_name (scope_info->scope.node),
+ acpi_ut_get_type_name (scope_info->common.value)));
+
+ new_scope_info = walk_state->scope_info;
+ if (new_scope_info) {
+ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC,
+ "[%4.4s] (%s)\n",
+ acpi_ut_get_node_name (new_scope_info->scope.node),
+ acpi_ut_get_type_name (new_scope_info->common.value)));
+ }
+ else {
+ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC,
+ "[\\___] (ROOT)\n"));
+ }
+
+ acpi_ut_delete_generic_state (scope_info);
+ return_ACPI_STATUS (AE_OK);
+}
+
+
diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c
new file mode 100644
index 00000000000..e555b3fbd5e
--- /dev/null
+++ b/drivers/acpi/dispatcher/dswstate.c
@@ -0,0 +1,1100 @@
+/******************************************************************************
+ *
+ * Module Name: dswstate - Dispatcher parse tree walk management routines
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2005, R. Byron Moore
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+
+#include <acpi/acpi.h>
+#include <acpi/acparser.h>
+#include <acpi/acdispat.h>
+#include <acpi/acnamesp.h>
+
+#define _COMPONENT ACPI_DISPATCHER
+ ACPI_MODULE_NAME ("dswstate")
+
+
+#ifdef ACPI_FUTURE_USAGE
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_result_insert
+ *
+ * PARAMETERS: Object - Object to push
+ * Index - Where to insert the object
+ * walk_state - Current Walk state
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Insert an object onto this walk's result stack
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_result_insert (
+ void *object,
+ u32 index,
+ struct acpi_walk_state *walk_state)
+{
+ union acpi_generic_state *state;
+
+
+ ACPI_FUNCTION_NAME ("ds_result_insert");
+
+
+ state = walk_state->results;
+ if (!state) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No result object pushed! State=%p\n",
+ walk_state));
+ return (AE_NOT_EXIST);
+ }
+
+ if (index >= ACPI_OBJ_NUM_OPERANDS) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+ "Index out of range: %X Obj=%p State=%p Num=%X\n",
+ index, object, walk_state, state->results.num_results));
+ return (AE_BAD_PARAMETER);
+ }
+
+ if (!object) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+ "Null Object! Index=%X Obj=%p State=%p Num=%X\n",
+ index, object, walk_state, state->results.num_results));
+ return (AE_BAD_PARAMETER);
+ }
+
+ state->results.obj_desc [index] = object;
+ state->results.num_results++;
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
+ "Obj=%p [%s] State=%p Num=%X Cur=%X\n",
+ object, object ? acpi_ut_get_object_type_name ((union acpi_operand_object *) object) : "NULL",
+ walk_state, state->results.num_results, walk_state->current_result));
+
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_result_remove
+ *
+ * PARAMETERS: Object - Where to return the popped object
+ * Index - Where to extract the object
+ * walk_state - Current Walk state
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Pop an object off the bottom of this walk's result stack. In
+ * other words, this is a FIFO.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_result_remove (
+ union acpi_operand_object **object,
+ u32 index,
+ struct acpi_walk_state *walk_state)
+{
+ union acpi_generic_state *state;
+
+
+ ACPI_FUNCTION_NAME ("ds_result_remove");
+
+
+ state = walk_state->results;
+ if (!state) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No result object pushed! State=%p\n",
+ walk_state));
+ return (AE_NOT_EXIST);
+ }
+
+ if (index >= ACPI_OBJ_MAX_OPERAND) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+ "Index out of range: %X State=%p Num=%X\n",
+ index, walk_state, state->results.num_results));
+ }
+
+ /* Check for a valid result object */
+
+ if (!state->results.obj_desc [index]) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+ "Null operand! State=%p #Ops=%X, Index=%X\n",
+ walk_state, state->results.num_results, index));
+ return (AE_AML_NO_RETURN_VALUE);
+ }
+
+ /* Remove the object */
+
+ state->results.num_results--;
+
+ *object = state->results.obj_desc [index];
+ state->results.obj_desc [index] = NULL;
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
+ "Obj=%p [%s] Index=%X State=%p Num=%X\n",
+ *object, (*object) ? acpi_ut_get_object_type_name (*object) : "NULL",
+ index, walk_state, state->results.num_results));
+
+ return (AE_OK);
+}
+
+#endif /* ACPI_FUTURE_USAGE */
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_result_pop
+ *
+ * PARAMETERS: Object - Where to return the popped object
+ * walk_state - Current Walk state
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Pop an object off the bottom of this walk's result stack. In
+ * other words, this is a FIFO.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_result_pop (
+ union acpi_operand_object **object,
+ struct acpi_walk_state *walk_state)
+{
+ acpi_native_uint index;
+ union acpi_generic_state *state;
+
+
+ ACPI_FUNCTION_NAME ("ds_result_pop");
+
+
+ state = walk_state->results;
+ if (!state) {
+ return (AE_OK);
+ }
+
+ if (!state->results.num_results) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Result stack is empty! State=%p\n",
+ walk_state));
+ return (AE_AML_NO_RETURN_VALUE);
+ }
+
+ /* Remove top element */
+
+ state->results.num_results--;
+
+ for (index = ACPI_OBJ_NUM_OPERANDS; index; index--) {
+ /* Check for a valid result object */
+
+ if (state->results.obj_desc [index -1]) {
+ *object = state->results.obj_desc [index -1];
+ state->results.obj_desc [index -1] = NULL;
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s] Index=%X State=%p Num=%X\n",
+ *object, (*object) ? acpi_ut_get_object_type_name (*object) : "NULL",
+ (u32) index -1, walk_state, state->results.num_results));
+
+ return (AE_OK);
+ }
+ }
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No result objects! State=%p\n", walk_state));
+ return (AE_AML_NO_RETURN_VALUE);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_result_pop_from_bottom
+ *
+ * PARAMETERS: Object - Where to return the popped object
+ * walk_state - Current Walk state
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Pop an object off the bottom of this walk's result stack. In
+ * other words, this is a FIFO.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_result_pop_from_bottom (
+ union acpi_operand_object **object,
+ struct acpi_walk_state *walk_state)
+{
+ acpi_native_uint index;
+ union acpi_generic_state *state;
+
+
+ ACPI_FUNCTION_NAME ("ds_result_pop_from_bottom");
+
+
+ state = walk_state->results;
+ if (!state) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+ "Warning: No result object pushed! State=%p\n", walk_state));
+ return (AE_NOT_EXIST);
+ }
+
+ if (!state->results.num_results) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "No result objects! State=%p\n", walk_state));
+ return (AE_AML_NO_RETURN_VALUE);
+ }
+
+ /* Remove Bottom element */
+
+ *object = state->results.obj_desc [0];
+
+ /* Push entire stack down one element */
+
+ for (index = 0; index < state->results.num_results; index++) {
+ state->results.obj_desc [index] = state->results.obj_desc [index + 1];
+ }
+
+ state->results.num_results--;
+
+ /* Check for a valid result object */
+
+ if (!*object) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null operand! State=%p #Ops=%X, Index=%X\n",
+ walk_state, state->results.num_results, (u32) index));
+ return (AE_AML_NO_RETURN_VALUE);
+ }
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s], Results=%p State=%p\n",
+ *object, (*object) ? acpi_ut_get_object_type_name (*object) : "NULL",
+ state, walk_state));
+
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_result_push
+ *
+ * PARAMETERS: Object - Where to return the popped object
+ * walk_state - Current Walk state
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Push an object onto the current result stack
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_result_push (
+ union acpi_operand_object *object,
+ struct acpi_walk_state *walk_state)
+{
+ union acpi_generic_state *state;
+
+
+ ACPI_FUNCTION_NAME ("ds_result_push");
+
+
+ state = walk_state->results;
+ if (!state) {
+ ACPI_REPORT_ERROR (("No result stack frame during push\n"));
+ return (AE_AML_INTERNAL);
+ }
+
+ if (state->results.num_results == ACPI_OBJ_NUM_OPERANDS) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+ "Result stack overflow: Obj=%p State=%p Num=%X\n",
+ object, walk_state, state->results.num_results));
+ return (AE_STACK_OVERFLOW);
+ }
+
+ if (!object) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null Object! Obj=%p State=%p Num=%X\n",
+ object, walk_state, state->results.num_results));
+ return (AE_BAD_PARAMETER);
+ }
+
+ state->results.obj_desc [state->results.num_results] = object;
+ state->results.num_results++;
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s] State=%p Num=%X Cur=%X\n",
+ object, object ? acpi_ut_get_object_type_name ((union acpi_operand_object *) object) : "NULL",
+ walk_state, state->results.num_results, walk_state->current_result));
+
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_result_stack_push
+ *
+ * PARAMETERS: walk_state - Current Walk state
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Push an object onto the walk_state result stack.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_result_stack_push (
+ struct acpi_walk_state *walk_state)
+{
+ union acpi_generic_state *state;
+
+ ACPI_FUNCTION_NAME ("ds_result_stack_push");
+
+
+ state = acpi_ut_create_generic_state ();
+ if (!state) {
+ return (AE_NO_MEMORY);
+ }
+
+ state->common.data_type = ACPI_DESC_TYPE_STATE_RESULT;
+ acpi_ut_push_generic_state (&walk_state->results, state);
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Results=%p State=%p\n",
+ state, walk_state));
+
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_result_stack_pop
+ *
+ * PARAMETERS: walk_state - Current Walk state
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Pop an object off of the walk_state result stack.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_result_stack_pop (
+ struct acpi_walk_state *walk_state)
+{
+ union acpi_generic_state *state;
+
+ ACPI_FUNCTION_NAME ("ds_result_stack_pop");
+
+
+ /* Check for stack underflow */
+
+ if (walk_state->results == NULL) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Underflow - State=%p\n",
+ walk_state));
+ return (AE_AML_NO_OPERAND);
+ }
+
+ state = acpi_ut_pop_generic_state (&walk_state->results);
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
+ "Result=%p remaining_results=%X State=%p\n",
+ state, state->results.num_results, walk_state));
+
+ acpi_ut_delete_generic_state (state);
+
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_obj_stack_delete_all
+ *
+ * PARAMETERS: walk_state - Current Walk state
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Clear the object stack by deleting all objects that are on it.
+ * Should be used with great care, if at all!
+ *
+ ******************************************************************************/
+#ifdef ACPI_FUTURE_USAGE
+acpi_status
+acpi_ds_obj_stack_delete_all (
+ struct acpi_walk_state *walk_state)
+{
+ u32 i;
+
+
+ ACPI_FUNCTION_TRACE_PTR ("ds_obj_stack_delete_all", walk_state);
+
+
+ /* The stack size is configurable, but fixed */
+
+ for (i = 0; i < ACPI_OBJ_NUM_OPERANDS; i++) {
+ if (walk_state->operands[i]) {
+ acpi_ut_remove_reference (walk_state->operands[i]);
+ walk_state->operands[i] = NULL;
+ }
+ }
+
+ return_ACPI_STATUS (AE_OK);
+}
+#endif /* ACPI_FUTURE_USAGE */
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_obj_stack_push
+ *
+ * PARAMETERS: Object - Object to push
+ * walk_state - Current Walk state
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Push an object onto this walk's object/operand stack
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_obj_stack_push (
+ void *object,
+ struct acpi_walk_state *walk_state)
+{
+ ACPI_FUNCTION_NAME ("ds_obj_stack_push");
+
+
+ /* Check for stack overflow */
+
+ if (walk_state->num_operands >= ACPI_OBJ_NUM_OPERANDS) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+ "overflow! Obj=%p State=%p #Ops=%X\n",
+ object, walk_state, walk_state->num_operands));
+ return (AE_STACK_OVERFLOW);
+ }
+
+ /* Put the object onto the stack */
+
+ walk_state->operands [walk_state->num_operands] = object;
+ walk_state->num_operands++;
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n",
+ object, acpi_ut_get_object_type_name ((union acpi_operand_object *) object),
+ walk_state, walk_state->num_operands));
+
+ return (AE_OK);
+}
+
+
+#if 0
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_obj_stack_pop_object
+ *
+ * PARAMETERS: pop_count - Number of objects/entries to pop
+ * walk_state - Current Walk state
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT
+ * deleted by this routine.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_obj_stack_pop_object (
+ union acpi_operand_object **object,
+ struct acpi_walk_state *walk_state)
+{
+ ACPI_FUNCTION_NAME ("ds_obj_stack_pop_object");
+
+
+ /* Check for stack underflow */
+
+ if (walk_state->num_operands == 0) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+ "Missing operand/stack empty! State=%p #Ops=%X\n",
+ walk_state, walk_state->num_operands));
+ *object = NULL;
+ return (AE_AML_NO_OPERAND);
+ }
+
+ /* Pop the stack */
+
+ walk_state->num_operands--;
+
+ /* Check for a valid operand */
+
+ if (!walk_state->operands [walk_state->num_operands]) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+ "Null operand! State=%p #Ops=%X\n",
+ walk_state, walk_state->num_operands));
+ *object = NULL;
+ return (AE_AML_NO_OPERAND);
+ }
+
+ /* Get operand and set stack entry to null */
+
+ *object = walk_state->operands [walk_state->num_operands];
+ walk_state->operands [walk_state->num_operands] = NULL;
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n",
+ *object, acpi_ut_get_object_type_name (*object),
+ walk_state, walk_state->num_operands));
+
+ return (AE_OK);
+}
+#endif
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_obj_stack_pop
+ *
+ * PARAMETERS: pop_count - Number of objects/entries to pop
+ * walk_state - Current Walk state
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT
+ * deleted by this routine.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_obj_stack_pop (
+ u32 pop_count,
+ struct acpi_walk_state *walk_state)
+{
+ u32 i;
+
+ ACPI_FUNCTION_NAME ("ds_obj_stack_pop");
+
+
+ for (i = 0; i < pop_count; i++) {
+ /* Check for stack underflow */
+
+ if (walk_state->num_operands == 0) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+ "Underflow! Count=%X State=%p #Ops=%X\n",
+ pop_count, walk_state, walk_state->num_operands));
+ return (AE_STACK_UNDERFLOW);
+ }
+
+ /* Just set the stack entry to null */
+
+ walk_state->num_operands--;
+ walk_state->operands [walk_state->num_operands] = NULL;
+ }
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n",
+ pop_count, walk_state, walk_state->num_operands));
+
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_obj_stack_pop_and_delete
+ *
+ * PARAMETERS: pop_count - Number of objects/entries to pop
+ * walk_state - Current Walk state
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Pop this walk's object stack and delete each object that is
+ * popped off.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_obj_stack_pop_and_delete (
+ u32 pop_count,
+ struct acpi_walk_state *walk_state)
+{
+ u32 i;
+ union acpi_operand_object *obj_desc;
+
+
+ ACPI_FUNCTION_NAME ("ds_obj_stack_pop_and_delete");
+
+
+ for (i = 0; i < pop_count; i++) {
+ /* Check for stack underflow */
+
+ if (walk_state->num_operands == 0) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+ "Underflow! Count=%X State=%p #Ops=%X\n",
+ pop_count, walk_state, walk_state->num_operands));
+ return (AE_STACK_UNDERFLOW);
+ }
+
+ /* Pop the stack and delete an object if present in this stack entry */
+
+ walk_state->num_operands--;
+ obj_desc = walk_state->operands [walk_state->num_operands];
+ if (obj_desc) {
+ acpi_ut_remove_reference (walk_state->operands [walk_state->num_operands]);
+ walk_state->operands [walk_state->num_operands] = NULL;
+ }
+ }
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n",
+ pop_count, walk_state, walk_state->num_operands));
+
+ return (AE_OK);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_obj_stack_get_value
+ *
+ * PARAMETERS: Index - Stack index whose value is desired. Based
+ * on the top of the stack (index=0 == top)
+ * walk_state - Current Walk state
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Retrieve an object from this walk's object stack. Index must
+ * be within the range of the current stack pointer.
+ *
+ ******************************************************************************/
+#ifdef ACPI_FUTURE_USAGE
+void *
+acpi_ds_obj_stack_get_value (
+ u32 index,
+ struct acpi_walk_state *walk_state)
+{
+
+ ACPI_FUNCTION_TRACE_PTR ("ds_obj_stack_get_value", walk_state);
+
+
+ /* Can't do it if the stack is empty */
+
+ if (walk_state->num_operands == 0) {
+ return_PTR (NULL);
+ }
+
+ /* or if the index is past the top of the stack */
+
+ if (index > (walk_state->num_operands - (u32) 1)) {
+ return_PTR (NULL);
+ }
+
+ return_PTR (walk_state->operands[(acpi_native_uint)(walk_state->num_operands - 1) -
+ index]);
+}
+#endif /* ACPI_FUTURE_USAGE */
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_get_current_walk_state
+ *
+ * PARAMETERS: Thread - Get current active state for this Thread
+ *
+ * RETURN: Pointer to the current walk state
+ *
+ * DESCRIPTION: Get the walk state that is at the head of the list (the "current"
+ * walk state.)
+ *
+ ******************************************************************************/
+
+struct acpi_walk_state *
+acpi_ds_get_current_walk_state (
+ struct acpi_thread_state *thread)
+
+{
+ ACPI_FUNCTION_NAME ("ds_get_current_walk_state");
+
+
+ if (!thread) {
+ return (NULL);
+ }
+
+ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Current walk_state %p\n",
+ thread->walk_state_list));
+
+ return (thread->walk_state_list);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_push_walk_state
+ *
+ * PARAMETERS: walk_state - State to push
+ * walk_list - The list that owns the walk stack
+ *
+ * RETURN: None
+ *
+ * DESCRIPTION: Place the walk_state at the head of the state list.
+ *
+ ******************************************************************************/
+
+void
+acpi_ds_push_walk_state (
+ struct acpi_walk_state *walk_state,
+ struct acpi_thread_state *thread)
+{
+ ACPI_FUNCTION_TRACE ("ds_push_walk_state");
+
+
+ walk_state->next = thread->walk_state_list;
+ thread->walk_state_list = walk_state;
+
+ return_VOID;
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_pop_walk_state
+ *
+ * PARAMETERS: walk_list - The list that owns the walk stack
+ *
+ * RETURN: A walk_state object popped from the stack
+ *
+ * DESCRIPTION: Remove and return the walkstate object that is at the head of
+ * the walk stack for the given walk list. NULL indicates that
+ * the list is empty.
+ *
+ ******************************************************************************/
+
+struct acpi_walk_state *
+acpi_ds_pop_walk_state (
+ struct acpi_thread_state *thread)
+{
+ struct acpi_walk_state *walk_state;
+
+
+ ACPI_FUNCTION_TRACE ("ds_pop_walk_state");
+
+
+ walk_state = thread->walk_state_list;
+
+ if (walk_state) {
+ /* Next walk state becomes the current walk state */
+
+ thread->walk_state_list = walk_state->next;
+
+ /*
+ * Don't clear the NEXT field, this serves as an indicator
+ * that there is a parent WALK STATE
+ * NO: walk_state->Next = NULL;
+ */
+ }
+
+ return_PTR (walk_state);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_create_walk_state
+ *
+ * PARAMETERS: Origin - Starting point for this walk
+ * Thread - Current thread state
+ *
+ * RETURN: Pointer to the new walk state.
+ *
+ * DESCRIPTION: Allocate and initialize a new walk state. The current walk
+ * state is set to this new state.
+ *
+ ******************************************************************************/
+
+struct acpi_walk_state *
+acpi_ds_create_walk_state (
+ acpi_owner_id owner_id,
+ union acpi_parse_object *origin,
+ union acpi_operand_object *mth_desc,
+ struct acpi_thread_state *thread)
+{
+ struct acpi_walk_state *walk_state;
+ acpi_status status;
+
+
+ ACPI_FUNCTION_TRACE ("ds_create_walk_state");
+
+
+ walk_state = acpi_ut_acquire_from_cache (ACPI_MEM_LIST_WALK);
+ if (!walk_state) {
+ return_PTR (NULL);
+ }
+
+ walk_state->data_type = ACPI_DESC_TYPE_WALK;
+ walk_state->owner_id = owner_id;
+ walk_state->origin = origin;
+ walk_state->method_desc = mth_desc;
+ walk_state->thread = thread;
+
+ walk_state->parser_state.start_op = origin;
+
+ /* Init the method args/local */
+
+#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY))
+ acpi_ds_method_data_init (walk_state);
+#endif
+
+ /* Create an initial result stack entry */
+
+ status = acpi_ds_result_stack_push (walk_state);
+ if (ACPI_FAILURE (status)) {
+ acpi_ut_release_to_cache (ACPI_MEM_LIST_WALK, walk_state);
+ return_PTR (NULL);
+ }
+
+ /* Put the new state at the head of the walk list */
+
+ if (thread) {
+ acpi_ds_push_walk_state (walk_state, thread);
+ }
+
+ return_PTR (walk_state);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_init_aml_walk
+ *
+ * PARAMETERS: walk_state - New state to be initialized
+ * Op - Current parse op
+ * method_node - Control method NS node, if any
+ * aml_start - Start of AML
+ * aml_length - Length of AML
+ * Params - Method args, if any
+ * return_obj_desc - Where to store a return object, if any
+ * pass_number - 1, 2, or 3
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Initialize a walk state for a pass 1 or 2 parse tree walk
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_init_aml_walk (
+ struct acpi_walk_state *walk_state,
+ union acpi_parse_object *op,
+ struct acpi_namespace_node *method_node,
+ u8 *aml_start,
+ u32 aml_length,
+ struct acpi_parameter_info *info,
+ u32 pass_number)
+{
+ acpi_status status;
+ struct acpi_parse_state *parser_state = &walk_state->parser_state;
+ union acpi_parse_object *extra_op;
+
+
+ ACPI_FUNCTION_TRACE ("ds_init_aml_walk");
+
+
+ walk_state->parser_state.aml =
+ walk_state->parser_state.aml_start = aml_start;
+ walk_state->parser_state.aml_end =
+ walk_state->parser_state.pkg_end = aml_start + aml_length;
+
+ /* The next_op of the next_walk will be the beginning of the method */
+
+ walk_state->next_op = NULL;
+
+ if (info) {
+ if (info->parameter_type == ACPI_PARAM_GPE) {
+ walk_state->gpe_event_info = ACPI_CAST_PTR (struct acpi_gpe_event_info,
+ info->parameters);
+ }
+ else {
+ walk_state->params = info->parameters;
+ walk_state->caller_return_desc = &info->return_object;
+ }
+ }
+
+ status = acpi_ps_init_scope (&walk_state->parser_state, op);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ if (method_node) {
+ walk_state->parser_state.start_node = method_node;
+ walk_state->walk_type = ACPI_WALK_METHOD;
+ walk_state->method_node = method_node;
+ walk_state->method_desc = acpi_ns_get_attached_object (method_node);
+
+ /* Push start scope on scope stack and make it current */
+
+ status = acpi_ds_scope_stack_push (method_node, ACPI_TYPE_METHOD, walk_state);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+
+ /* Init the method arguments */
+
+ status = acpi_ds_method_data_init_args (walk_state->params, ACPI_METHOD_NUM_ARGS, walk_state);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+ }
+ else {
+ /*
+ * Setup the current scope.
+ * Find a Named Op that has a namespace node associated with it.
+ * search upwards from this Op. Current scope is the first
+ * Op with a namespace node.
+ */
+ extra_op = parser_state->start_op;
+ while (extra_op && !extra_op->common.node) {
+ extra_op = extra_op->common.parent;
+ }
+
+ if (!extra_op) {
+ parser_state->start_node = NULL;
+ }
+ else {
+ parser_state->start_node = extra_op->common.node;
+ }
+
+ if (parser_state->start_node) {
+ /* Push start scope on scope stack and make it current */
+
+ status = acpi_ds_scope_stack_push (parser_state->start_node,
+ parser_state->start_node->type, walk_state);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+ }
+ }
+
+ status = acpi_ds_init_callbacks (walk_state, pass_number);
+ return_ACPI_STATUS (status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: acpi_ds_delete_walk_state
+ *
+ * PARAMETERS: walk_state - State to delete
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Delete a walk state including all internal data structures
+ *
+ ******************************************************************************/
+
+void
+acpi_ds_delete_walk_state (
+ struct acpi_walk_state *walk_state)
+{
+ union acpi_generic_state *state;
+
+
+ ACPI_FUNCTION_TRACE_PTR ("ds_delete_walk_state", walk_state);
+
+
+ if (!walk_state) {
+ return;
+ }
+
+ if (walk_state->data_type != ACPI_DESC_TYPE_WALK) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p is not a valid walk state\n", walk_state));
+ return;
+ }
+
+ if (walk_state->parser_state.scope) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "%p walk still has a scope list\n", walk_state));
+ }
+
+ /* Always must free any linked control states */
+
+ while (walk_state->control_state) {
+ state = walk_state->control_state;
+ walk_state->control_state = state->common.next;
+
+ acpi_ut_delete_generic_state (state);
+ }
+
+ /* Always must free any linked parse states */
+
+ while (walk_state->scope_info) {
+ state = walk_state->scope_info;
+ walk_state->scope_info = state->common.next;
+
+ acpi_ut_delete_generic_state (state);
+ }
+
+ /* Always must free any stacked result states */
+
+ while (walk_state->results) {
+ state = walk_state->results;
+ walk_state->results = state->common.next;
+
+ acpi_ut_delete_generic_state (state);
+ }
+
+ acpi_ut_release_to_cache (ACPI_MEM_LIST_WALK, walk_state);
+ return_VOID;
+}
+
+
+#ifdef ACPI_ENABLE_OBJECT_CACHE
+/******************************************************************************
+ *
+ * FUNCTION: acpi_ds_delete_walk_state_cache
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Purge the global state object cache. Used during subsystem
+ * termination.
+ *
+ ******************************************************************************/
+
+void
+acpi_ds_delete_walk_state_cache (
+ void)
+{
+ ACPI_FUNCTION_TRACE ("ds_delete_walk_state_cache");
+
+
+ acpi_ut_delete_generic_cache (ACPI_MEM_LIST_WALK);
+ return_VOID;
+}
+#endif
+
+