patch-2.4.14 linux/drivers/acpi/executer/exmisc.c
Next file: linux/drivers/acpi/executer/exmonad.c
Previous file: linux/drivers/acpi/executer/exfldio.c
Back to the patch index
Back to the overall index
- Lines: 708
- Date:
Wed Oct 24 14:06:22 2001
- Orig file:
v2.4.13/linux/drivers/acpi/executer/exmisc.c
- Orig date:
Sun Sep 23 11:40:56 2001
diff -u --recursive --new-file v2.4.13/linux/drivers/acpi/executer/exmisc.c linux/drivers/acpi/executer/exmisc.c
@@ -2,7 +2,7 @@
/******************************************************************************
*
* Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes
- * $Revision: 83 $
+ * $Revision: 92 $
*
*****************************************************************************/
@@ -38,424 +38,403 @@
/*******************************************************************************
*
- * FUNCTION: Acpi_ex_triadic
+ * FUNCTION: Acpi_ex_get_object_reference
*
- * PARAMETERS: Opcode - The opcode to be executed
- * Walk_state - Current walk state
- * Return_desc - Where to store the return object
+ * PARAMETERS: Obj_desc - Create a reference to this object
+ * Return_desc - Where to store the reference
*
* RETURN: Status
*
- * DESCRIPTION: Execute Triadic operator (3 operands)
- *
- * ALLOCATION: Deletes one operand descriptor -- other remains on stack
+ * DESCRIPTION: Obtain and return a "reference" to the target object
+ * Common code for the Ref_of_op and the Cond_ref_of_op.
*
******************************************************************************/
acpi_status
-acpi_ex_triadic (
- u16 opcode,
- acpi_walk_state *walk_state,
- acpi_operand_object **return_desc)
+acpi_ex_get_object_reference (
+ acpi_operand_object *obj_desc,
+ acpi_operand_object **return_desc,
+ acpi_walk_state *walk_state)
{
- acpi_operand_object **operand = &walk_state->operands[0];
- acpi_operand_object *ret_desc = NULL;
- acpi_operand_object *tmp_desc;
- ACPI_SIGNAL_FATAL_INFO *fatal;
acpi_status status = AE_OK;
- FUNCTION_TRACE ("Ex_triadic");
-
-
-#define obj_desc1 operand[0]
-#define obj_desc2 operand[1]
-#define res_desc operand[2]
-
-
- switch (opcode) {
-
- case AML_FATAL_OP:
-
- /* Def_fatal := Fatal_op Fatal_type Fatal_code Fatal_arg */
+ FUNCTION_TRACE_PTR ("Ex_get_object_reference", obj_desc);
- ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
- "Fatal_op: Type %x Code %x Arg %x <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n",
- (u32) obj_desc1->integer.value, (u32) obj_desc2->integer.value,
- (u32) res_desc->integer.value));
-
- fatal = ACPI_MEM_ALLOCATE (sizeof (ACPI_SIGNAL_FATAL_INFO));
- if (fatal) {
- fatal->type = (u32) obj_desc1->integer.value;
- fatal->code = (u32) obj_desc2->integer.value;
- fatal->argument = (u32) res_desc->integer.value;
+ if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_INTERNAL)) {
+ if (obj_desc->common.type != INTERNAL_TYPE_REFERENCE) {
+ *return_desc = NULL;
+ status = AE_TYPE;
+ goto cleanup;
}
/*
- * Signal the OS
+ * Not a Name -- an indirect name pointer would have
+ * been converted to a direct name pointer in Acpi_ex_resolve_operands
*/
- acpi_os_signal (ACPI_SIGNAL_FATAL, fatal);
-
- /* Might return while OS is shutting down */
-
- ACPI_MEM_FREE (fatal);
- break;
-
+ switch (obj_desc->reference.opcode) {
+ case AML_LOCAL_OP:
+ case AML_ARG_OP:
- case AML_MID_OP:
-
- /* Def_mid := Mid_op Source Index Length Result */
-
- /* Create the internal return object (string or buffer) */
-
- break;
-
-
- case AML_INDEX_OP:
-
- /* Def_index := Index_op Source Index Destination */
+ *return_desc = (void *) acpi_ds_method_data_get_node (obj_desc->reference.opcode,
+ obj_desc->reference.offset, walk_state);
+ break;
- /* Create the internal return object */
+ default:
- ret_desc = acpi_ut_create_internal_object (INTERNAL_TYPE_REFERENCE);
- if (!ret_desc) {
- status = AE_NO_MEMORY;
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "(Internal) Unknown Ref subtype %02x\n",
+ obj_desc->reference.opcode));
+ *return_desc = NULL;
+ status = AE_AML_INTERNAL;
goto cleanup;
}
- /*
- * At this point, the Obj_desc1 operand is either a Package or a Buffer
- */
- if (obj_desc1->common.type == ACPI_TYPE_PACKAGE) {
- /* Object to be indexed is a Package */
+ }
- if (obj_desc2->integer.value >= obj_desc1->package.count) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Index value beyond package end\n"));
- status = AE_AML_PACKAGE_LIMIT;
- goto cleanup;
- }
-
- if ((res_desc->common.type == INTERNAL_TYPE_REFERENCE) &&
- (res_desc->reference.opcode == AML_ZERO_OP)) {
- /*
- * There is no actual result descriptor (the Zero_op Result
- * descriptor is a placeholder), so just delete the placeholder and
- * return a reference to the package element
- */
- acpi_ut_remove_reference (res_desc);
- }
-
- else {
- /*
- * Each element of the package is an internal object. Get the one
- * we are after.
- */
- tmp_desc = obj_desc1->package.elements[obj_desc2->integer.value];
- ret_desc->reference.opcode = AML_INDEX_OP;
- ret_desc->reference.target_type = tmp_desc->common.type;
- ret_desc->reference.object = tmp_desc;
-
- status = acpi_ex_store (ret_desc, res_desc, walk_state);
- ret_desc->reference.object = NULL;
- }
+ else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) {
+ /* Must be a named object; Just return the Node */
- /*
- * The local return object must always be a reference to the package element,
- * not the element itself.
- */
- ret_desc->reference.opcode = AML_INDEX_OP;
- ret_desc->reference.target_type = ACPI_TYPE_PACKAGE;
- ret_desc->reference.where = &obj_desc1->package.elements[obj_desc2->integer.value];
- }
-
- else {
- /* Object to be indexed is a Buffer */
-
- if (obj_desc2->integer.value >= obj_desc1->buffer.length) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Index value beyond end of buffer\n"));
- status = AE_AML_BUFFER_LIMIT;
- goto cleanup;
- }
-
- ret_desc->reference.opcode = AML_INDEX_OP;
- ret_desc->reference.target_type = ACPI_TYPE_BUFFER_FIELD;
- ret_desc->reference.object = obj_desc1;
- ret_desc->reference.offset = (u32) obj_desc2->integer.value;
+ *return_desc = obj_desc;
+ }
- status = acpi_ex_store (ret_desc, res_desc, walk_state);
- }
- break;
+ else {
+ *return_desc = NULL;
+ status = AE_TYPE;
}
cleanup:
- /* Always delete operands */
-
- acpi_ut_remove_reference (obj_desc1);
- acpi_ut_remove_reference (obj_desc2);
-
- /* Delete return object on error */
-
- if (ACPI_FAILURE (status)) {
- acpi_ut_remove_reference (res_desc);
-
- if (ret_desc) {
- acpi_ut_remove_reference (ret_desc);
- ret_desc = NULL;
- }
- }
-
- /* Set the return object and exit */
-
- *return_desc = ret_desc;
+ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p Ref=%p\n", obj_desc, *return_desc));
return_ACPI_STATUS (status);
}
/*******************************************************************************
*
- * FUNCTION: Acpi_ex_hexadic
+ * FUNCTION: Acpi_ex_do_concatenate
*
- * PARAMETERS: Opcode - The opcode to be executed
+ * PARAMETERS: *Obj_desc - Object to be converted. Must be an
+ * Integer, Buffer, or String
* Walk_state - Current walk state
- * Return_desc - Where to store the return object
*
* RETURN: Status
*
- * DESCRIPTION: Execute Match operator
+ * DESCRIPTION: Concatenate two objects OF THE SAME TYPE.
*
******************************************************************************/
acpi_status
-acpi_ex_hexadic (
- u16 opcode,
- acpi_walk_state *walk_state,
- acpi_operand_object **return_desc)
+acpi_ex_do_concatenate (
+ acpi_operand_object *obj_desc,
+ acpi_operand_object *obj_desc2,
+ acpi_operand_object **actual_return_desc,
+ acpi_walk_state *walk_state)
{
- acpi_operand_object **operand = &walk_state->operands[0];
- acpi_operand_object *ret_desc = NULL;
- acpi_status status = AE_OK;
- u32 index;
- u32 match_value = (u32) -1;
+ acpi_status status;
+ u32 i;
+ acpi_integer this_integer;
+ acpi_operand_object *return_desc;
+ NATIVE_CHAR *new_buf;
+ u32 integer_size = sizeof (acpi_integer);
- FUNCTION_TRACE ("Ex_hexadic");
+ FUNCTION_ENTRY ();
-#define pkg_desc operand[0]
-#define op1_desc operand[1]
-#define V1_desc operand[2]
-#define op2_desc operand[3]
-#define V2_desc operand[4]
-#define start_desc operand[5]
+ /*
+ * There are three cases to handle:
+ * 1) Two Integers concatenated to produce a buffer
+ * 2) Two Strings concatenated to produce a string
+ * 3) Two Buffers concatenated to produce a buffer
+ */
+ switch (obj_desc->common.type) {
+ case ACPI_TYPE_INTEGER:
- switch (opcode) {
+ /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */
- case AML_MATCH_OP:
+ if (walk_state->method_node->flags & ANOBJ_DATA_WIDTH_32) {
+ /*
+ * We are running a method that exists in a 32-bit ACPI table.
+ * Truncate the value to 32 bits by zeroing out the upper
+ * 32-bit field
+ */
+ integer_size = sizeof (u32);
+ }
- /* Validate match comparison sub-opcodes */
+ /* Result of two integers is a buffer */
- if ((op1_desc->integer.value > MAX_MATCH_OPERATOR) ||
- (op2_desc->integer.value > MAX_MATCH_OPERATOR)) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "operation encoding out of range\n"));
- status = AE_AML_OPERAND_VALUE;
- goto cleanup;
+ return_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER);
+ if (!return_desc) {
+ return (AE_NO_MEMORY);
}
- index = (u32) start_desc->integer.value;
- if (index >= (u32) pkg_desc->package.count) {
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Start position value out of range\n"));
- status = AE_AML_PACKAGE_LIMIT;
+ /* Need enough space for two integers */
+
+ return_desc->buffer.length = integer_size * 2;
+ new_buf = ACPI_MEM_CALLOCATE (return_desc->buffer.length);
+ if (!new_buf) {
+ REPORT_ERROR
+ (("Ex_do_concatenate: Buffer allocation failure\n"));
+ status = AE_NO_MEMORY;
goto cleanup;
}
- ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
- if (!ret_desc) {
+ return_desc->buffer.pointer = (u8 *) new_buf;
+
+ /* Convert the first integer */
+
+ this_integer = obj_desc->integer.value;
+ for (i = 0; i < integer_size; i++) {
+ new_buf[i] = (u8) this_integer;
+ this_integer >>= 8;
+ }
+
+ /* Convert the second integer */
+
+ this_integer = obj_desc2->integer.value;
+ for (; i < (integer_size * 2); i++) {
+ new_buf[i] = (u8) this_integer;
+ this_integer >>= 8;
+ }
+
+ break;
+
+
+ case ACPI_TYPE_STRING:
+
+ return_desc = acpi_ut_create_internal_object (ACPI_TYPE_STRING);
+ if (!return_desc) {
+ return (AE_NO_MEMORY);
+ }
+
+ /* Operand0 is string */
+
+ new_buf = ACPI_MEM_ALLOCATE (obj_desc->string.length +
+ obj_desc2->string.length + 1);
+ if (!new_buf) {
+ REPORT_ERROR
+ (("Ex_do_concatenate: String allocation failure\n"));
status = AE_NO_MEMORY;
goto cleanup;
+ }
+
+ STRCPY (new_buf, obj_desc->string.pointer);
+ STRCPY (new_buf + obj_desc->string.length,
+ obj_desc2->string.pointer);
+
+ /* Point the return object to the new string */
+
+ return_desc->string.pointer = new_buf;
+ return_desc->string.length = obj_desc->string.length +=
+ obj_desc2->string.length;
+ break;
+
+
+ case ACPI_TYPE_BUFFER:
+
+ /* Operand0 is a buffer */
+
+ return_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER);
+ if (!return_desc) {
+ return (AE_NO_MEMORY);
+ }
+ new_buf = ACPI_MEM_ALLOCATE (obj_desc->buffer.length +
+ obj_desc2->buffer.length);
+ if (!new_buf) {
+ REPORT_ERROR
+ (("Ex_do_concatenate: Buffer allocation failure\n"));
+ status = AE_NO_MEMORY;
+ goto cleanup;
}
+ MEMCPY (new_buf, obj_desc->buffer.pointer,
+ obj_desc->buffer.length);
+ MEMCPY (new_buf + obj_desc->buffer.length, obj_desc2->buffer.pointer,
+ obj_desc2->buffer.length);
+
/*
- * Examine each element until a match is found. Within the loop,
- * "continue" signifies that the current element does not match
- * and the next should be examined.
- * Upon finding a match, the loop will terminate via "break" at
- * the bottom. If it terminates "normally", Match_value will be -1
- * (its initial value) indicating that no match was found. When
- * returned as a Number, this will produce the Ones value as specified.
+ * Point the return object to the new buffer
*/
- for ( ; index < pkg_desc->package.count; ++index) {
- /*
- * Treat any NULL or non-numeric elements as non-matching.
- * TBD [Unhandled] - if an element is a Name,
- * should we examine its value?
- */
- if (!pkg_desc->package.elements[index] ||
- ACPI_TYPE_INTEGER != pkg_desc->package.elements[index]->common.type) {
- continue;
- }
- /*
- * Within these switch statements:
- * "break" (exit from the switch) signifies a match;
- * "continue" (proceed to next iteration of enclosing
- * "for" loop) signifies a non-match.
- */
- switch (op1_desc->integer.value) {
+ return_desc->buffer.pointer = (u8 *) new_buf;
+ return_desc->buffer.length = obj_desc->buffer.length +
+ obj_desc2->buffer.length;
+ break;
- case MATCH_MTR: /* always true */
- break;
+ default:
+ status = AE_AML_INTERNAL;
+ return_desc = NULL;
+ }
- case MATCH_MEQ: /* true if equal */
+ *actual_return_desc = return_desc;
+ return (AE_OK);
- if (pkg_desc->package.elements[index]->integer.value
- != V1_desc->integer.value) {
- continue;
- }
- break;
+cleanup:
- case MATCH_MLE: /* true if less than or equal */
+ acpi_ut_remove_reference (return_desc);
+ return (status);
+}
- if (pkg_desc->package.elements[index]->integer.value
- > V1_desc->integer.value) {
- continue;
- }
- break;
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_ex_do_math_op
+ *
+ * PARAMETERS: Opcode - AML opcode
+ * Operand0 - Integer operand #0
+ * Operand0 - Integer operand #1
+ *
+ * RETURN: Integer result of the operation
+ *
+ * DESCRIPTION: Execute a math AML opcode. The purpose of having all of the
+ * math functions here is to prevent a lot of pointer dereferencing
+ * to obtain the operands.
+ *
+ ******************************************************************************/
- case MATCH_MLT: /* true if less than */
+acpi_integer
+acpi_ex_do_math_op (
+ u16 opcode,
+ acpi_integer operand0,
+ acpi_integer operand1)
+{
- if (pkg_desc->package.elements[index]->integer.value
- >= V1_desc->integer.value) {
- continue;
- }
- break;
+ switch (opcode) {
+ case AML_ADD_OP: /* Add (Operand0, Operand1, Result) */
- case MATCH_MGE: /* true if greater than or equal */
+ return (operand0 + operand1);
- if (pkg_desc->package.elements[index]->integer.value
- < V1_desc->integer.value) {
- continue;
- }
- break;
+ case AML_BIT_AND_OP: /* And (Operand0, Operand1, Result) */
- case MATCH_MGT: /* true if greater than */
+ return (operand0 & operand1);
- if (pkg_desc->package.elements[index]->integer.value
- <= V1_desc->integer.value) {
- continue;
- }
- break;
+ case AML_BIT_NAND_OP: /* NAnd (Operand0, Operand1, Result) */
- default: /* undefined */
+ return (~(operand0 & operand1));
- continue;
- }
+ case AML_BIT_OR_OP: /* Or (Operand0, Operand1, Result) */
- switch(op2_desc->integer.value) {
+ return (operand0 | operand1);
- case MATCH_MTR:
- break;
+ case AML_BIT_NOR_OP: /* NOr (Operand0, Operand1, Result) */
+ return (~(operand0 | operand1));
- case MATCH_MEQ:
- if (pkg_desc->package.elements[index]->integer.value
- != V2_desc->integer.value) {
- continue;
- }
- break;
+ case AML_BIT_XOR_OP: /* XOr (Operand0, Operand1, Result) */
+ return (operand0 ^ operand1);
- case MATCH_MLE:
- if (pkg_desc->package.elements[index]->integer.value
- > V2_desc->integer.value) {
- continue;
- }
- break;
+ case AML_MULTIPLY_OP: /* Multiply (Operand0, Operand1, Result) */
+ return (operand0 * operand1);
- case MATCH_MLT:
- if (pkg_desc->package.elements[index]->integer.value
- >= V2_desc->integer.value) {
- continue;
- }
- break;
+ case AML_SHIFT_LEFT_OP: /* Shift_left (Operand, Shift_count, Result) */
+ return (operand0 << operand1);
- case MATCH_MGE:
- if (pkg_desc->package.elements[index]->integer.value
- < V2_desc->integer.value) {
- continue;
- }
- break;
+ case AML_SHIFT_RIGHT_OP: /* Shift_right (Operand, Shift_count, Result) */
+ return (operand0 >> operand1);
- case MATCH_MGT:
- if (pkg_desc->package.elements[index]->integer.value
- <= V2_desc->integer.value) {
- continue;
- }
- break;
+ case AML_SUBTRACT_OP: /* Subtract (Operand0, Operand1, Result) */
+ return (operand0 - operand1);
- default:
+ default:
- continue;
- }
+ return (0);
+ }
+}
- /* Match found: exit from loop */
- match_value = index;
- break;
+/*******************************************************************************
+ *
+ * FUNCTION: Acpi_ex_do_logical_op
+ *
+ * PARAMETERS: Opcode - AML opcode
+ * Operand0 - Integer operand #0
+ * Operand0 - Integer operand #1
+ *
+ * RETURN: TRUE/FALSE result of the operation
+ *
+ * DESCRIPTION: Execute a logical AML opcode. The purpose of having all of the
+ * functions here is to prevent a lot of pointer dereferencing
+ * to obtain the operands and to simplify the generation of the
+ * logical value.
+ *
+ * Note: cleanest machine code seems to be produced by the code
+ * below, rather than using statements of the form:
+ * Result = (Operand0 == Operand1);
+ *
+ ******************************************************************************/
+
+u8
+acpi_ex_do_logical_op (
+ u16 opcode,
+ acpi_integer operand0,
+ acpi_integer operand1)
+{
+
+
+ switch (opcode) {
+
+ case AML_LAND_OP: /* LAnd (Operand0, Operand1) */
+
+ if (operand0 && operand1) {
+ return (TRUE);
}
+ break;
- /* Match_value is the return value */
- ret_desc->integer.value = match_value;
+ case AML_LEQUAL_OP: /* LEqual (Operand0, Operand1) */
+
+ if (operand0 == operand1) {
+ return (TRUE);
+ }
break;
- }
+ case AML_LGREATER_OP: /* LGreater (Operand0, Operand1) */
-cleanup:
+ if (operand0 > operand1) {
+ return (TRUE);
+ }
+ break;
- /* Free the operands */
- acpi_ut_remove_reference (start_desc);
- acpi_ut_remove_reference (V2_desc);
- acpi_ut_remove_reference (op2_desc);
- acpi_ut_remove_reference (V1_desc);
- acpi_ut_remove_reference (op1_desc);
- acpi_ut_remove_reference (pkg_desc);
-
-
- /* Delete return object on error */
-
- if (ACPI_FAILURE (status) &&
- (ret_desc)) {
- acpi_ut_remove_reference (ret_desc);
- ret_desc = NULL;
- }
+ case AML_LLESS_OP: /* LLess (Operand0, Operand1) */
+ if (operand0 < operand1) {
+ return (TRUE);
+ }
+ break;
- /* Set the return object and exit */
- *return_desc = ret_desc;
- return_ACPI_STATUS (status);
+ case AML_LOR_OP: /* LOr (Operand0, Operand1) */
+
+ if (operand0 || operand1) {
+ return (TRUE);
+ }
+ break;
+ }
+
+ return (FALSE);
}
+
+
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)