patch-2.4.14 linux/drivers/acpi/dispatcher/dsfield.c

Next file: linux/drivers/acpi/dispatcher/dsmethod.c
Previous file: linux/drivers/acpi/debugger/dbxface.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.13/linux/drivers/acpi/dispatcher/dsfield.c linux/drivers/acpi/dispatcher/dsfield.c
@@ -1,7 +1,7 @@
 /******************************************************************************
  *
  * Module Name: dsfield - Dispatcher field routines
- *              $Revision: 44 $
+ *              $Revision: 46 $
  *
  *****************************************************************************/
 
@@ -29,78 +29,178 @@
 #include "acdispat.h"
 #include "acinterp.h"
 #include "acnamesp.h"
+#include "acparser.h"
 
 
 #define _COMPONENT          ACPI_DISPATCHER
 	 MODULE_NAME         ("dsfield")
 
 
-/*
- * Field flags: Bits 00 - 03 : Access_type (Any_acc, Byte_acc, etc.)
- *                   04      : Lock_rule (1 == Lock)
- *                   05 - 06 : Update_rule
- */
-
-#define FIELD_ACCESS_TYPE_MASK      0x0F
-#define FIELD_LOCK_RULE_MASK        0x10
-#define FIELD_UPDATE_RULE_MASK      0x60
-
-
 /*******************************************************************************
  *
- * FUNCTION:    Acpi_ds_create_field
+ * FUNCTION:    Acpi_ds_create_buffer_field
  *
- * PARAMETERS:  Op              - Op containing the Field definition and args
- *              Region_node     - Object for the containing Operation Region
- *  `           Walk_state      - Current method state
+ * PARAMETERS:  Opcode              - The opcode to be executed
+ *              Operands            - List of operands for the opcode
+ *              Walk_state          - Current state
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Create a new field in the specified operation region
+ * 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_field (
+acpi_ds_create_buffer_field (
 	acpi_parse_object       *op,
-	acpi_namespace_node     *region_node,
 	acpi_walk_state         *walk_state)
 {
-	acpi_status             status = AE_AML_ERROR;
 	acpi_parse_object       *arg;
 	acpi_namespace_node     *node;
-	u8                      field_flags;
-	u32                     field_bit_position = 0;
+	acpi_status             status;
+	acpi_operand_object     *obj_desc;
 
 
-	FUNCTION_TRACE_PTR ("Ds_create_field", op);
+	FUNCTION_TRACE ("Ds_create_buffer_field");
 
 
-	/* First arg is the name of the parent Op_region */
+	/* Get the Name_string argument */
 
-	arg = op->value.arg;
-	if (!region_node) {
-		status = acpi_ns_lookup (walk_state->scope_info, arg->value.name,
-				  ACPI_TYPE_REGION, IMODE_EXECUTE,
-				  NS_SEARCH_PARENT, walk_state, &region_node);
-		if (ACPI_FAILURE (status)) {
-			return_ACPI_STATUS (status);
-		}
+	if (op->opcode == AML_CREATE_FIELD_OP) {
+		arg = acpi_ps_get_arg (op, 3);
 	}
+	else {
+		/* Create Bit/Byte/Word/Dword field */
 
-	/* Second arg is the field flags */
+		arg = acpi_ps_get_arg (op, 2);
+	}
 
-	arg = arg->next;
-	field_flags = (u8) arg->value.integer;
+	if (!arg) {
+		return_ACPI_STATUS (AE_AML_NO_OPERAND);
+	}
 
-	/* Each remaining arg is a Named Field */
+	/*
+	 * Enter the Name_string into the namespace
+	 */
+	status = acpi_ns_lookup (walk_state->scope_info, arg->value.string,
+			 INTERNAL_TYPE_DEF_ANY, IMODE_LOAD_PASS1,
+			 NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE,
+			 walk_state, &(node));
+	if (ACPI_FAILURE (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->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.
+	 */
+	if (node->object) {
+		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;
+	}
+
+	/*
+	 * Allocate a method object for this field unit
+	 */
+	obj_desc->buffer_field.extra = acpi_ut_create_internal_object (
+			   INTERNAL_TYPE_EXTRA);
+	if (!obj_desc->buffer_field.extra) {
+		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.
+	 */
+	obj_desc->buffer_field.extra->extra.aml_start = ((acpi_parse2_object *) op)->data;
+	obj_desc->buffer_field.extra->extra.aml_length = ((acpi_parse2_object *) op)->length;
+	obj_desc->buffer_field.node = node;
+
+	/* Attach constructed field descriptor to parent node */
+
+	status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_BUFFER_FIELD);
+
+
+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 (
+	ACPI_CREATE_FIELD_INFO  *info,
+	acpi_walk_state         *walk_state,
+	acpi_parse_object       *arg)
+{
+	acpi_status             status;
+
+
+	FUNCTION_TRACE_U32 ("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) */
 
-	arg = arg->next;
 	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->opcode) {
 		case AML_INT_RESERVEDFIELD_OP:
 
-			field_bit_position += arg->value.size;
+			info->field_bit_position += arg->value.size;
 			break;
 
 
@@ -110,48 +210,57 @@
 			 * Get a new Access_type and Access_attribute for all
 			 * entries (until end or another Access_as keyword)
 			 */
-			field_flags = (u8) ((field_flags & FIELD_ACCESS_TYPE_MASK) ||
-					   ((u8) (arg->value.integer >> 8)));
+			info->field_flags = (u8) ((info->field_flags & FIELD_ACCESS_TYPE_MASK) ||
+					  ((u8) (arg->value.integer >> 8)));
 			break;
 
 
 		case AML_INT_NAMEDFIELD_OP:
 
+			/* Enter a new field name into the namespace */
+
 			status = acpi_ns_lookup (walk_state->scope_info,
 					  (NATIVE_CHAR *) &((acpi_parse2_object *)arg)->name,
-					  INTERNAL_TYPE_REGION_FIELD, IMODE_LOAD_PASS1,
+					  info->field_type, IMODE_LOAD_PASS1,
 					  NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE,
-					  NULL, &node);
+					  NULL, &info->field_node);
 			if (ACPI_FAILURE (status)) {
 				return_ACPI_STATUS (status);
 			}
 
-			/*
-			 * Initialize an object for the new Node that is on
-			 * the object stack
-			 */
-			status = acpi_ex_prep_region_field_value (node, region_node, field_flags,
-					  field_bit_position, arg->value.size);
+			/* Create and initialize an object for the new Field Node */
+
+			info->field_bit_length = arg->value.size;
+
+			status = acpi_ex_prep_field_value (info);
 			if (ACPI_FAILURE (status)) {
 				return_ACPI_STATUS (status);
 			}
 
-			/* Keep track of bit position for *next* field */
+			/* Keep track of bit position for the next field */
+
+			info->field_bit_position += info->field_bit_length;
+			break;
+
+
+		default:
 
-			field_bit_position += arg->value.size;
+			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid opcode in field list: %X\n",
+				arg->opcode));
+			return_ACPI_STATUS (AE_AML_ERROR);
 			break;
 		}
 
 		arg = arg->next;
 	}
 
-	return_ACPI_STATUS (status);
+	return_ACPI_STATUS (AE_OK);
 }
 
 
 /*******************************************************************************
  *
- * FUNCTION:    Acpi_ds_create_bank_field
+ * FUNCTION:    Acpi_ds_create_field
  *
  * PARAMETERS:  Op              - Op containing the Field definition and args
  *              Region_node     - Object for the containing Operation Region
@@ -159,29 +268,25 @@
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Create a new bank field in the specified operation region
+ * DESCRIPTION: Create a new field in the specified operation region
  *
  ******************************************************************************/
 
 acpi_status
-acpi_ds_create_bank_field (
+acpi_ds_create_field (
 	acpi_parse_object       *op,
 	acpi_namespace_node     *region_node,
 	acpi_walk_state         *walk_state)
 {
 	acpi_status             status = AE_AML_ERROR;
 	acpi_parse_object       *arg;
-	acpi_namespace_node     *register_node;
-	acpi_namespace_node     *node;
-	u32                     bank_value;
-	u8                      field_flags;
-	u32                     field_bit_position = 0;
+	ACPI_CREATE_FIELD_INFO  info;
 
 
-	FUNCTION_TRACE_PTR ("Ds_create_bank_field", op);
+	FUNCTION_TRACE_PTR ("Ds_create_field", op);
 
 
-	/* First arg is the name of the parent Op_region */
+	/* First arg is the name of the parent Op_region (must already exist) */
 
 	arg = op->value.arg;
 	if (!region_node) {
@@ -193,82 +298,88 @@
 		}
 	}
 
-	/* Second arg is the Bank Register */
+	/* Second arg is the field flags */
 
 	arg = arg->next;
+	info.field_flags = arg->value.integer8;
 
-	status = acpi_ns_lookup (walk_state->scope_info, arg->value.string,
-			  INTERNAL_TYPE_BANK_FIELD_DEFN, IMODE_LOAD_PASS1,
-			  NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE,
-			  NULL, &register_node);
-	if (ACPI_FAILURE (status)) {
-		return_ACPI_STATUS (status);
-	}
+	/* Each remaining arg is a Named Field */
 
-	/* Third arg is the Bank_value */
+	info.field_type = INTERNAL_TYPE_REGION_FIELD;
+	info.region_node = region_node;
 
-	arg = arg->next;
-	bank_value = arg->value.integer32;
+	status = acpi_ds_get_field_names (&info, walk_state, arg->next);
 
+	return_ACPI_STATUS (status);
+}
 
-	/* Next arg is the field flags */
 
-	arg = arg->next;
-	field_flags = arg->value.integer8;
+/*******************************************************************************
+ *
+ * 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
+ *
+ ******************************************************************************/
 
-	/* Each remaining arg is a Named Field */
+acpi_status
+acpi_ds_create_bank_field (
+	acpi_parse_object       *op,
+	acpi_namespace_node     *region_node,
+	acpi_walk_state         *walk_state)
+{
+	acpi_status             status = AE_AML_ERROR;
+	acpi_parse_object       *arg;
+	ACPI_CREATE_FIELD_INFO  info;
 
-	arg = arg->next;
-	while (arg) {
-		switch (arg->opcode) {
-		case AML_INT_RESERVEDFIELD_OP:
 
-			field_bit_position += arg->value.size;
-			break;
+	FUNCTION_TRACE_PTR ("Ds_create_bank_field", op);
 
 
-		case AML_INT_ACCESSFIELD_OP:
+	/* First arg is the name of the parent Op_region (must already exist) */
 
-			/*
-			 * Get a new Access_type and Access_attribute for
-			 * all entries (until end or another Access_as keyword)
-			 */
-			field_flags = (u8) ((field_flags & FIELD_ACCESS_TYPE_MASK) ||
-					 ((u8) (arg->value.integer >> 8)));
-			break;
+	arg = op->value.arg;
+	if (!region_node) {
+		status = acpi_ns_lookup (walk_state->scope_info, arg->value.name,
+				  ACPI_TYPE_REGION, IMODE_EXECUTE,
+				  NS_SEARCH_PARENT, walk_state, &region_node);
+		if (ACPI_FAILURE (status)) {
+			return_ACPI_STATUS (status);
+		}
+	}
 
+	/* Second arg is the Bank Register (must already exist) */
 
-		case AML_INT_NAMEDFIELD_OP:
+	arg = arg->next;
+	status = acpi_ns_lookup (walk_state->scope_info, arg->value.string,
+			  INTERNAL_TYPE_BANK_FIELD_DEFN, IMODE_EXECUTE,
+			  NS_SEARCH_PARENT, walk_state, &info.register_node);
+	if (ACPI_FAILURE (status)) {
+		return_ACPI_STATUS (status);
+	}
 
-			status = acpi_ns_lookup (walk_state->scope_info,
-					  (NATIVE_CHAR *) &((acpi_parse2_object *)arg)->name,
-					  INTERNAL_TYPE_REGION_FIELD, IMODE_LOAD_PASS1,
-					  NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE,
-					  NULL, &node);
-			if (ACPI_FAILURE (status)) {
-				return_ACPI_STATUS (status);
-			}
+	/* Third arg is the Bank_value */
 
-			/*
-			 * Initialize an object for the new Node that is on
-			 * the object stack
-			 */
-			status = acpi_ex_prep_bank_field_value (node, region_node, register_node,
-					  bank_value, field_flags, field_bit_position,
-					  arg->value.size);
-			if (ACPI_FAILURE (status)) {
-				return_ACPI_STATUS (status);
-			}
+	arg = arg->next;
+	info.bank_value = arg->value.integer32;
 
-			/* Keep track of bit position for the *next* field */
+	/* Fourth arg is the field flags */
 
-			field_bit_position += arg->value.size;
-			break;
+	arg = arg->next;
+	info.field_flags = arg->value.integer8;
 
-		}
+	/* Each remaining arg is a Named Field */
 
-		arg = arg->next;
-	}
+	info.field_type = INTERNAL_TYPE_BANK_FIELD;
+	info.region_node = region_node;
+
+	status = acpi_ds_get_field_names (&info, walk_state, arg->next);
 
 	return_ACPI_STATUS (status);
 }
@@ -296,107 +407,44 @@
 {
 	acpi_status             status;
 	acpi_parse_object       *arg;
-	acpi_namespace_node     *node;
-	acpi_namespace_node     *index_register_node;
-	acpi_namespace_node     *data_register_node;
-	u8                      field_flags;
-	u32                     field_bit_position = 0;
+	ACPI_CREATE_FIELD_INFO  info;
 
 
 	FUNCTION_TRACE_PTR ("Ds_create_index_field", op);
 
 
-	arg = op->value.arg;
-
-	/* First arg is the name of the Index register */
+	/* First arg is the name of the Index register (must already exist) */
 
+	arg = op->value.arg;
 	status = acpi_ns_lookup (walk_state->scope_info, arg->value.string,
-			  ACPI_TYPE_ANY, IMODE_LOAD_PASS1,
-			  NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE,
-			  NULL, &index_register_node);
+			  ACPI_TYPE_ANY, IMODE_EXECUTE,
+			  NS_SEARCH_PARENT, walk_state, &info.register_node);
 	if (ACPI_FAILURE (status)) {
 		return_ACPI_STATUS (status);
 	}
 
-	/* Second arg is the data register */
+	/* Second arg is the data register (must already exist) */
 
 	arg = arg->next;
-
 	status = acpi_ns_lookup (walk_state->scope_info, arg->value.string,
-			  INTERNAL_TYPE_INDEX_FIELD_DEFN, IMODE_LOAD_PASS1,
-			  NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE,
-			  NULL, &data_register_node);
+			  INTERNAL_TYPE_INDEX_FIELD_DEFN, IMODE_EXECUTE,
+			  NS_SEARCH_PARENT, walk_state, &info.data_register_node);
 	if (ACPI_FAILURE (status)) {
 		return_ACPI_STATUS (status);
 	}
 
-
 	/* Next arg is the field flags */
 
 	arg = arg->next;
-	field_flags = (u8) arg->value.integer;
+	info.field_flags = arg->value.integer8;
 
 
 	/* Each remaining arg is a Named Field */
 
-	arg = arg->next;
-	while (arg) {
-		switch (arg->opcode) {
-		case AML_INT_RESERVEDFIELD_OP:
-
-			field_bit_position += arg->value.size;
-			break;
-
-
-		case AML_INT_ACCESSFIELD_OP:
-
-			/*
-			 * Get a new Access_type and Access_attribute for all
-			 * entries (until end or another Access_as keyword)
-			 */
-			field_flags = (u8) ((field_flags & FIELD_ACCESS_TYPE_MASK) ||
-					 ((u8) (arg->value.integer >> 8)));
-			break;
-
+	info.field_type = INTERNAL_TYPE_INDEX_FIELD;
+	info.region_node = region_node;
 
-		case AML_INT_NAMEDFIELD_OP:
-
-			status = acpi_ns_lookup (walk_state->scope_info,
-					  (NATIVE_CHAR *) &((acpi_parse2_object *)arg)->name,
-					  INTERNAL_TYPE_INDEX_FIELD, IMODE_LOAD_PASS1,
-					  NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE,
-					  NULL, &node);
-			if (ACPI_FAILURE (status)) {
-				return_ACPI_STATUS (status);
-			}
-
-			/*
-			 * Initialize an object for the new Node that is on
-			 * the object stack
-			 */
-			status = acpi_ex_prep_index_field_value (node, index_register_node,
-					  data_register_node, field_flags,
-					  field_bit_position, arg->value.size);
-			if (ACPI_FAILURE (status)) {
-				return_ACPI_STATUS (status);
-			}
-
-			/* Keep track of bit position for the *next* field */
-
-			field_bit_position += arg->value.size;
-			break;
-
-
-		default:
-
-			ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid opcode in field list: %X\n",
-				arg->opcode));
-			status = AE_AML_ERROR;
-			break;
-		}
-
-		arg = arg->next;
-	}
+	status = acpi_ds_get_field_names (&info, walk_state, arg->next);
 
 	return_ACPI_STATUS (status);
 }

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