patch-2.4.0-test3 linux/drivers/acpi/dispatcher/dsobject.c

Next file: linux/drivers/acpi/dispatcher/dsopcode.c
Previous file: linux/drivers/acpi/dispatcher/dsmthdat.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test2/linux/drivers/acpi/dispatcher/dsobject.c linux/drivers/acpi/dispatcher/dsobject.c
@@ -0,0 +1,598 @@
+
+/******************************************************************************
+ *
+ * Module Name: dsobject - Dispatcher object management routines
+ *
+ *****************************************************************************/
+
+/*
+ *  Copyright (C) 2000 R. Byron Moore
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "acpi.h"
+#include "parser.h"
+#include "amlcode.h"
+#include "dispatch.h"
+#include "interp.h"
+#include "namesp.h"
+
+#define _COMPONENT          DISPATCHER
+	 MODULE_NAME         ("dsobject");
+
+
+/*******************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_init_one_object
+ *
+ * PARAMETERS:  Obj_handle      - NTE of the object
+ *              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) Op Regions
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_init_one_object (
+	ACPI_HANDLE             obj_handle,
+	u32                     level,
+	void                    *context,
+	void                    **return_value)
+{
+	OBJECT_TYPE_INTERNAL    type;
+	ACPI_STATUS             status;
+	ACPI_OBJECT_INTERNAL    *obj_desc;
+	INIT_WALK_INFO          *info = (INIT_WALK_INFO *) context;
+
+
+	/*
+	 * We are only interested in objects owned by the table that
+	 * was just loaded
+	 */
+
+	if (((ACPI_NAMED_OBJECT*) obj_handle)->owner_id !=
+			info->table_desc->table_id)
+	{
+		return AE_OK;
+	}
+
+
+	/* 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:
+
+		acpi_ds_initialize_region (obj_handle);
+
+		info->op_region_count++;
+		break;
+
+
+	case ACPI_TYPE_METHOD:
+
+		info->method_count++;
+
+
+		/*
+		 * Always parse methods to detect errors, we may delete
+		 * the parse tree below
+		 */
+
+		status = acpi_ds_parse_method (obj_handle);
+
+		/* TBD: [Errors] what do we do with an error? */
+
+		if (ACPI_FAILURE (status)) {
+			break;
+		}
+
+		/*
+		 * Keep the parse tree only if we are parsing all methods
+		 * at init time (versus just-in-time)
+		 */
+
+		if (acpi_gbl_when_to_parse_methods != METHOD_PARSE_AT_INIT) {
+
+			acpi_ns_delete_namespace_subtree (obj_handle);
+
+			obj_desc = ((ACPI_NAMED_OBJECT*)obj_handle)->object;
+			acpi_ps_delete_parse_tree (obj_desc->method.parser_op);
+			obj_desc->method.parser_op = NULL;
+		}
+
+		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:  None
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Walk the entire namespace and perform any necessary initialization
+ *              on the objects found therein
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+acpi_ds_initialize_objects (
+	ACPI_TABLE_DESC         *table_desc,
+	ACPI_NAMED_OBJECT       *start_entry)
+{
+	ACPI_STATUS             status;
+	INIT_WALK_INFO          info;
+
+
+	info.method_count = 0;
+	info.op_region_count = 0;
+	info.table_desc = table_desc;
+
+
+	/* Walk entire namespace from the supplied root */
+
+	status = acpi_walk_namespace (ACPI_TYPE_ANY, start_entry,
+			  ACPI_INT32_MAX, acpi_ds_init_one_object,
+			  &info, NULL);
+
+	return (AE_OK);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_init_object_from_op
+ *
+ * PARAMETERS:  Op              - Parser op used to init the internal object
+ *              Opcode          - AML opcode associated with the object
+ *              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 (
+	ACPI_WALK_STATE         *walk_state,
+	ACPI_GENERIC_OP         *op,
+	u16                     opcode,
+	ACPI_OBJECT_INTERNAL    *obj_desc)
+{
+	ACPI_STATUS             status;
+	ACPI_GENERIC_OP         *arg;
+	ACPI_BYTELIST_OP        *byte_list;
+	ACPI_OBJECT_INTERNAL    *arg_desc;
+	ACPI_OP_INFO            *op_info;
+
+
+	op_info = acpi_ps_get_opcode_info (opcode);
+	if (!op_info) {
+		/* Unknown opcode */
+
+		return AE_TYPE;
+	}
+
+
+	/* Get and prepare the first argument */
+
+	switch (obj_desc->common.type)
+	{
+	case ACPI_TYPE_BUFFER:
+
+		/* First arg is a number */
+
+		acpi_ds_create_operand (walk_state, op->value.arg);
+		arg_desc = walk_state->operands [walk_state->num_operands - 1];
+		acpi_ds_obj_stack_pop (1, walk_state);
+
+		/* Resolve the object (could be an arg or local) */
+
+		status = acpi_aml_resolve_to_value (&arg_desc);
+		if (ACPI_FAILURE (status)) {
+			acpi_cm_remove_reference (arg_desc);
+			return status;
+		}
+
+		/* We are expecting a number */
+
+		if (arg_desc->common.type != ACPI_TYPE_NUMBER) {
+			acpi_cm_remove_reference (arg_desc);
+			return AE_TYPE;
+		}
+
+		/* Get the value, delete the internal object */
+
+		obj_desc->buffer.length = arg_desc->number.value;
+		acpi_cm_remove_reference (arg_desc);
+
+		/* Allocate the buffer */
+
+		obj_desc->buffer.pointer =
+				  acpi_cm_callocate (obj_desc->buffer.length);
+
+		if (!obj_desc->buffer.pointer) {
+			return AE_NO_MEMORY;
+		}
+
+		/*
+		 * Second arg is the buffer data (optional)
+		 * Byte_list can be either individual bytes or a
+		 * string initializer!
+		 */
+
+		/* skip first arg */
+		arg = op->value.arg;
+		byte_list = (ACPI_BYTELIST_OP *) arg->next;
+		if (byte_list) {
+			if (byte_list->opcode != AML_BYTELIST_OP) {
+				return AE_TYPE;
+			}
+
+			MEMCPY (obj_desc->buffer.pointer, byte_list->data,
+					obj_desc->buffer.length);
+		}
+
+		break;
+
+
+	case ACPI_TYPE_NUMBER:
+		obj_desc->number.value = op->value.integer;
+		break;
+
+
+	case ACPI_TYPE_STRING:
+		obj_desc->string.pointer = op->value.string;
+		obj_desc->string.length = STRLEN (op->value.string);
+		break;
+
+
+	case ACPI_TYPE_METHOD:
+		break;
+
+
+	case INTERNAL_TYPE_REFERENCE:
+
+		switch (op_info->flags & OP_INFO_TYPE)
+		{
+		case OPTYPE_LOCAL_VARIABLE:
+
+			/* Split the opcode into a base opcode + offset */
+
+			obj_desc->reference.op_code = AML_LOCAL_OP;
+			obj_desc->reference.offset = opcode - AML_LOCAL_OP;
+			break;
+
+		case OPTYPE_METHOD_ARGUMENT:
+
+			/* Split the opcode into a base opcode + offset */
+
+			obj_desc->reference.op_code = AML_ARG_OP;
+			obj_desc->reference.offset = opcode - AML_ARG_OP;
+			break;
+
+		default: /* Constants, Literals, etc.. */
+
+			if (op->opcode == AML_NAMEPATH_OP) {
+				/* Nte was saved in Op */
+
+				obj_desc->reference.nte = op->acpi_named_object;
+			}
+
+			obj_desc->reference.op_code = opcode;
+			break;
+		}
+
+		break;
+
+
+	default:
+
+		break;
+	}
+
+	return AE_OK;
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_build_internal_simple_obj
+ *
+ * PARAMETERS:  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_simple_obj (
+	ACPI_WALK_STATE         *walk_state,
+	ACPI_GENERIC_OP         *op,
+	ACPI_OBJECT_INTERNAL    **obj_desc_ptr)
+{
+	ACPI_OBJECT_INTERNAL    *obj_desc;
+	OBJECT_TYPE_INTERNAL    type;
+	ACPI_STATUS             status;
+
+
+	if (op->opcode == AML_NAMEPATH_OP) {
+		/*
+		 * This is an object reference.  If The name was
+		 * previously looked up in the NS, it is stored in this op.
+		 * Otherwise, go ahead and look it up now
+		 */
+
+		if (!op->acpi_named_object) {
+			status = acpi_ns_lookup (walk_state->scope_info,
+					  op->value.string, ACPI_TYPE_ANY,
+					  IMODE_EXECUTE,
+					  NS_SEARCH_PARENT | NS_DONT_OPEN_SCOPE,
+					  NULL,
+					  (ACPI_NAMED_OBJECT**)&(op->acpi_named_object));
+
+			if (ACPI_FAILURE (status)) {
+				return (status);
+			}
+		}
+
+		/*
+		 * The reference will be a Reference
+		 * TBD: [Restructure] unless we really need a separate
+		 *  type of INTERNAL_TYPE_REFERENCE change
+		 *  Acpi_ds_map_opcode_to_data_type to handle this case
+		 */
+		type = INTERNAL_TYPE_REFERENCE;
+	}
+	else {
+		type = acpi_ds_map_opcode_to_data_type (op->opcode, NULL);
+	}
+
+
+	/* Create and init the internal ACPI object */
+
+	obj_desc = acpi_cm_create_internal_object (type);
+	if (!obj_desc) {
+		return (AE_NO_MEMORY);
+	}
+
+	status = acpi_ds_init_object_from_op (walk_state, op,
+			 op->opcode, obj_desc);
+
+	if (ACPI_FAILURE (status)) {
+		acpi_cm_remove_reference (obj_desc);
+		return (status);
+	}
+
+	*obj_desc_ptr = obj_desc;
+
+	return (AE_OK);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_build_internal_package_obj
+ *
+ * PARAMETERS:  Op              - Parser object to be translated
+ *              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 (
+	ACPI_WALK_STATE         *walk_state,
+	ACPI_GENERIC_OP         *op,
+	ACPI_OBJECT_INTERNAL    **obj_desc_ptr)
+{
+	ACPI_GENERIC_OP         *arg;
+	ACPI_OBJECT_INTERNAL    *obj_desc;
+	ACPI_STATUS             status = AE_OK;
+
+
+	obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_PACKAGE);
+	if (!obj_desc) {
+		return (AE_NO_MEMORY);
+	}
+
+	/* The first argument must be the package length */
+
+	arg = op->value.arg;
+	obj_desc->package.count = arg->value.integer;
+
+	/*
+	 * Allocate the array of pointers (ptrs to the
+	 * individual objects) Add an extra pointer slot so
+	 * that the list is always null terminated.
+	 */
+
+	obj_desc->package.elements =
+			 acpi_cm_callocate ((obj_desc->package.count + 1) *
+			 sizeof (void *));
+
+	if (!obj_desc->package.elements) {
+		/* Package vector allocation failure   */
+
+		REPORT_ERROR ("Ds_build_internal_package_obj: Package vector allocation failure");
+
+		acpi_cm_free (obj_desc);
+		return (AE_NO_MEMORY);
+	}
+
+	obj_desc->package.next_element = obj_desc->package.elements;
+
+	/*
+	 * Now init the elements of the package
+	 */
+
+	arg = arg->next;
+	while (arg) {
+		if (arg->opcode == AML_PACKAGE_OP) {
+			status = acpi_ds_build_internal_package_obj (walk_state, arg,
+					  obj_desc->package.next_element);
+		}
+
+		else {
+			status = acpi_ds_build_internal_simple_obj (walk_state, arg,
+					  obj_desc->package.next_element);
+		}
+
+		obj_desc->package.next_element++;
+		arg = arg->next;
+	}
+
+	*obj_desc_ptr = obj_desc;
+	return (status);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_build_internal_object
+ *
+ * PARAMETERS:  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
+ *
+ ****************************************************************************/
+
+ACPI_STATUS
+acpi_ds_build_internal_object (
+	ACPI_WALK_STATE         *walk_state,
+	ACPI_GENERIC_OP         *op,
+	ACPI_OBJECT_INTERNAL    **obj_desc_ptr)
+{
+	ACPI_STATUS             status;
+
+
+	if (op->opcode == AML_PACKAGE_OP) {
+		status = acpi_ds_build_internal_package_obj (walk_state, op,
+				  obj_desc_ptr);
+	}
+
+	else {
+		status = acpi_ds_build_internal_simple_obj (walk_state, op,
+				  obj_desc_ptr);
+	}
+
+	return (status);
+}
+
+
+/*****************************************************************************
+ *
+ * FUNCTION:    Acpi_ds_create_named_object
+ *
+ * PARAMETERS:  Op              - Parser object to be translated
+ *              Obj_desc_ptr    - Where the ACPI internal object is returned
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION:
+ *
+ ****************************************************************************/
+
+ACPI_STATUS
+acpi_ds_create_named_object (
+	ACPI_WALK_STATE         *walk_state,
+	ACPI_NAMED_OBJECT       *entry,
+	ACPI_GENERIC_OP         *op)
+{
+	ACPI_STATUS             status;
+	ACPI_OBJECT_INTERNAL    *obj_desc;
+
+
+	if (!op->value.arg) {
+		/* No arguments, there is nothing to do */
+
+		return (AE_OK);
+	}
+
+
+	/* Build an internal object for the argument(s) */
+
+	status = acpi_ds_build_internal_object (walk_state,
+			 op->value.arg, &obj_desc);
+	if (ACPI_FAILURE (status)) {
+		goto cleanup;
+	}
+
+
+	/* Re-type the object according to it's argument */
+
+	entry->type = obj_desc->common.type;
+
+	/* Init obj */
+
+	status = acpi_ns_attach_object ((ACPI_HANDLE) entry, obj_desc,
+			   (u8) entry->type);
+	if (ACPI_FAILURE (status)) {
+		goto cleanup;
+	}
+
+	return (status);
+
+
+cleanup:
+
+	acpi_cm_remove_reference (obj_desc);
+
+	return (status);
+}
+
+

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)