patch-2.4.0-prerelease linux/drivers/acpi/parser/psparse.c
Next file: linux/drivers/acpi/parser/psscope.c
Previous file: linux/drivers/acpi/parser/psopcode.c
Back to the patch index
Back to the overall index
- Lines: 631
- Date:
Fri Dec 29 14:07:21 2000
- Orig file:
v2.4.0-test12/linux/drivers/acpi/parser/psparse.c
- Orig date:
Sun Oct 8 10:50:15 2000
diff -u --recursive --new-file v2.4.0-test12/linux/drivers/acpi/parser/psparse.c linux/drivers/acpi/parser/psparse.c
@@ -1,7 +1,7 @@
/******************************************************************************
*
* Module Name: psparse - Parser top level AML parse routines
- * $Revision: 51 $
+ * $Revision: 71 $
*
*****************************************************************************/
@@ -30,7 +30,7 @@
* generated parser to tightly constrain stack and dynamic memory
* usage. At the same time, parsing is kept flexible and the code
* fairly compact by parsing based on a list of AML opcode
- * templates in Acpi_gbl_Aml_op_info[]
+ * templates in Aml_op_info[]
*/
#include "acpi.h"
@@ -50,95 +50,6 @@
/*******************************************************************************
*
- * FUNCTION: Acpi_ps_delete_completed_op
- *
- * PARAMETERS: State - Walk state
- * Op - Completed op
- *
- * RETURN: AE_OK
- *
- * DESCRIPTION: Callback function for Acpi_ps_get_next_walk_op(). Used during
- * Acpi_ps_delete_parse tree to delete Op objects when all sub-objects
- * have been visited (and deleted.)
- *
- ******************************************************************************/
-
-ACPI_STATUS
-acpi_ps_delete_completed_op (
- ACPI_WALK_STATE *state,
- ACPI_PARSE_OBJECT *op)
-{
-
- acpi_ps_free_op (op);
- return (AE_OK);
-}
-
-
-#ifndef PARSER_ONLY
-/*******************************************************************************
- *
- * FUNCTION: Acpi_ps_delete_parse_tree
- *
- * PARAMETERS: Subtree_root - Root of tree (or subtree) to delete
- *
- * RETURN: None
- *
- * DESCRIPTION: Delete a portion of or an entire parse tree.
- *
- ******************************************************************************/
-
-void
-acpi_ps_delete_parse_tree (
- ACPI_PARSE_OBJECT *subtree_root)
-{
- ACPI_WALK_STATE *walk_state;
- ACPI_WALK_LIST walk_list;
-
-
- if (!subtree_root) {
- return;
- }
-
- /* Create and initialize a new walk list */
-
- walk_list.walk_state = NULL;
- walk_state = acpi_ds_create_walk_state (TABLE_ID_DSDT, NULL, NULL, &walk_list);
- if (!walk_state) {
- return;
- }
-
- walk_state->parser_state = NULL;
- walk_state->parse_flags = 0;
- walk_state->descending_callback = NULL;
- walk_state->ascending_callback = NULL;
-
-
- walk_state->origin = subtree_root;
- walk_state->next_op = subtree_root;
-
-
- /* Head downward in the tree */
-
- walk_state->next_op_info = NEXT_OP_DOWNWARD;
-
- /* Visit all nodes in the subtree */
-
- while (walk_state->next_op) {
- acpi_ps_get_next_walk_op (walk_state, walk_state->next_op,
- acpi_ps_delete_completed_op);
- }
-
- /* We are done with this walk */
-
- acpi_ds_delete_walk_state (walk_state);
-
- return;
-}
-#endif
-
-
-/*******************************************************************************
- *
* FUNCTION: Acpi_ps_peek_opcode
*
* PARAMETERS: None
@@ -149,7 +60,7 @@
*
******************************************************************************/
-u32
+static u32
acpi_ps_get_opcode_size (
u32 opcode)
{
@@ -323,7 +234,7 @@
*
******************************************************************************/
-u8
+static u8
acpi_ps_complete_this_op (
ACPI_WALK_STATE *walk_state,
ACPI_PARSE_OBJECT *op)
@@ -344,11 +255,11 @@
/* Delete this op and the subtree below it if asked to */
if (((walk_state->parse_flags & ACPI_PARSE_TREE_MASK) == ACPI_PARSE_DELETE_TREE) &&
- (opcode_class != OPTYPE_CONSTANT) &&
- (opcode_class != OPTYPE_LITERAL) &&
+ (opcode_class != OPTYPE_CONSTANT) &&
+ (opcode_class != OPTYPE_LITERAL) &&
(opcode_class != OPTYPE_LOCAL_VARIABLE) &&
(opcode_class != OPTYPE_METHOD_ARGUMENT) &&
- (opcode_class != OPTYPE_DATA_TERM) &&
+ (opcode_class != OPTYPE_DATA_TERM) &&
(op->opcode != AML_NAMEPATH_OP))
{
/* Make sure that we only delete this subtree */
@@ -356,7 +267,7 @@
if (op->parent) {
/*
* Check if we need to replace the operator and its subtree
- * with a return value op
+ * with a return value op (placeholder op)
*/
parent_info = acpi_ps_get_opcode_info (op->parent->opcode);
@@ -364,7 +275,29 @@
switch (ACPI_GET_OP_CLASS (parent_info))
{
case OPTYPE_CONTROL: /* IF, ELSE, WHILE only */
+ break;
+
case OPTYPE_NAMED_OBJECT: /* Scope, method, etc. */
+
+ /*
+ * These opcodes contain Term_arg operands. The current
+ * op must be replace by a placeholder return op
+ */
+
+ if ((op->parent->opcode == AML_REGION_OP) ||
+ (op->parent->opcode == AML_CREATE_FIELD_OP) ||
+ (op->parent->opcode == AML_BIT_FIELD_OP) ||
+ (op->parent->opcode == AML_BYTE_FIELD_OP) ||
+ (op->parent->opcode == AML_WORD_FIELD_OP) ||
+ (op->parent->opcode == AML_DWORD_FIELD_OP) ||
+ (op->parent->opcode == AML_QWORD_FIELD_OP))
+ {
+ replacement_op = acpi_ps_alloc_op (AML_RETURN_VALUE_OP);
+ if (!replacement_op) {
+ return (FALSE);
+ }
+ }
+
break;
default:
@@ -381,13 +314,13 @@
/* This op is the first in the list */
if (replacement_op) {
- replacement_op->parent = op->parent;
+ replacement_op->parent = op->parent;
replacement_op->value.arg = NULL;
- op->parent->value.arg = replacement_op;
- replacement_op->next = op->next;
+ op->parent->value.arg = replacement_op;
+ replacement_op->next = op->next;
}
else {
- op->parent->value.arg = op->next;
+ op->parent->value.arg = op->next;
}
}
@@ -443,8 +376,7 @@
*
******************************************************************************/
-
-ACPI_STATUS
+static ACPI_STATUS
acpi_ps_next_parse_state (
ACPI_WALK_STATE *walk_state,
ACPI_PARSE_OBJECT *op,
@@ -452,6 +384,8 @@
{
ACPI_PARSE_STATE *parser_state = walk_state->parser_state;
ACPI_STATUS status = AE_CTRL_PENDING;
+ u8 *start;
+ u32 package_length;
switch (callback_status)
@@ -490,10 +424,12 @@
* Predicate of an IF was true, and we are at the matching ELSE.
* Just close out this package
*
- * Parser_state->Aml is modified by the package length procedure
+ * Note: Parser_state->Aml is modified by the package length procedure
+ * TBD: [Investigate] perhaps it shouldn't, too much trouble
*/
- parser_state->aml = (parser_state->aml +
- acpi_ps_get_next_package_length (parser_state)) -1;
+ start = parser_state->aml;
+ package_length = acpi_ps_get_next_package_length (parser_state);
+ parser_state->aml = start + package_length;
break;
@@ -528,7 +464,7 @@
/* Will return value (if any) be used by the caller? */
- walk_state->return_used = acpi_ds_is_result_used (op);
+ walk_state->return_used = acpi_ds_is_result_used (op, walk_state);
break;
@@ -573,24 +509,59 @@
u16 opcode;
ACPI_PARSE_OBJECT pre_op;
ACPI_PARSE_STATE *parser_state;
+ u8 *aml_op_start;
parser_state = walk_state->parser_state;
- if (walk_state->prev_op) {
- op = walk_state->prev_op;
- arg_types = walk_state->prev_arg_types;
+#ifndef PARSER_ONLY
+ if (walk_state->walk_type & WALK_METHOD_RESTART) {
+ /* We are restarting a preempted control method */
+
+ if (acpi_ps_has_completed_scope (parser_state)) {
+ /*
+ * We must check if a predicate to an IF or WHILE statement
+ * was just completed
+ */
+ if ((parser_state->scope->parse_scope.op) &&
+ ((parser_state->scope->parse_scope.op->opcode == AML_IF_OP) ||
+ (parser_state->scope->parse_scope.op->opcode == AML_WHILE_OP)) &&
+ (walk_state->control_state) &&
+ (walk_state->control_state->common.state ==
+ CONTROL_PREDICATE_EXECUTING))
+ {
+
+ /*
+ * A predicate was just completed, get the value of the
+ * predicate and branch based on that value
+ */
+
+ status = acpi_ds_get_predicate_value (walk_state, NULL, TRUE);
+ status = acpi_ps_next_parse_state (walk_state, op, status);
+ }
+
+ acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count);
+ }
+
+ else if (walk_state->prev_op) {
+ /* We were in the middle of an op */
+
+ op = walk_state->prev_op;
+ arg_types = walk_state->prev_arg_types;
+ }
}
+#endif
/*
* Iterative parsing loop, while there is more aml to process:
*/
- while (parser_state->aml < parser_state->aml_end) {
+ while ((parser_state->aml < parser_state->aml_end) || (op)) {
if (!op) {
/* Get the next opcode from the AML stream */
+ aml_op_start = parser_state->aml;
aml_offset = parser_state->aml - parser_state->aml_start;
- opcode = acpi_ps_peek_opcode (parser_state);
+ opcode = acpi_ps_peek_opcode (parser_state);
/*
* First cut to determine what we have found:
@@ -625,7 +596,9 @@
/* The opcode is unrecognized. Just skip unknown opcodes */
- parser_state->aml += acpi_ps_get_opcode_size (opcode);
+ /* Assume one-byte bad opcode */
+
+ parser_state->aml++;
continue;
}
@@ -677,25 +650,26 @@
deferred_op = acpi_ps_to_extended_op (op);
if (deferred_op) {
/*
- * Skip parsing of control method or opregion body,
+ * Defer final parsing of an Operation_region body,
* because we don't have enough info in the first pass
- * to parse them correctly.
+ * to parse it correctly (i.e., there may be method
+ * calls within the Term_arg elements of the body.
*
- * Backup to beginning of Op_region declaration (2 for
- * Opcode, 4 for name)
+ * However, we must continue parsing because
+ * the opregion is not a standalone package --
+ * we don't know where the end is at this point.
*
- * Body_length is unknown until we parse the body
+ * (Length is unknown until parse of the body complete)
*/
- deferred_op->data = parser_state->aml - 6;
+ deferred_op->data = aml_op_start;
deferred_op->length = 0;
}
}
}
- else {
-
+ else {
/* Not a named opcode, just allocate Op and append to parent */
op = acpi_ps_alloc_op (opcode);
@@ -703,6 +677,23 @@
return (AE_NO_MEMORY);
}
+
+ if ((op->opcode == AML_CREATE_FIELD_OP) ||
+ (op->opcode == AML_BIT_FIELD_OP) ||
+ (op->opcode == AML_BYTE_FIELD_OP) ||
+ (op->opcode == AML_WORD_FIELD_OP) ||
+ (op->opcode == AML_DWORD_FIELD_OP))
+ {
+ /*
+ * Backup to beginning of Create_xXXfield declaration
+ * Body_length is unknown until we parse the body
+ */
+ deferred_op = (ACPI_PARSE2_OBJECT *) op;
+
+ deferred_op->data = aml_op_start;
+ deferred_op->length = 0;
+ }
+
acpi_ps_append_arg (acpi_ps_get_parent_scope (parser_state), op);
if ((walk_state->descending_callback != NULL)) {
@@ -728,7 +719,11 @@
}
+ /* Start Arg_count at zero because we don't know if there are any args yet */
+
arg_count = 0;
+
+
if (arg_types) /* Are there any arguments that must be processed? */ {
/* get arguments */
@@ -761,12 +756,11 @@
arg = acpi_ps_get_next_arg (parser_state,
GET_CURRENT_ARG_TYPE (arg_types),
&arg_count);
-
if (arg) {
arg->aml_offset = aml_offset;
+ acpi_ps_append_arg (op, arg);
}
- acpi_ps_append_arg (op, arg);
INCREMENT_ARG_LIST (arg_types);
}
@@ -800,6 +794,10 @@
}
}
+
+ /*
+ * Zero Arg_count means that all arguments for this op have been processed
+ */
if (!arg_count) {
/* completed Op, prepare for next */
@@ -821,11 +819,27 @@
*/
deferred_op->length = parser_state->aml -
- deferred_op->data;
+ deferred_op->data;
}
}
}
+ if ((op->opcode == AML_CREATE_FIELD_OP) ||
+ (op->opcode == AML_BIT_FIELD_OP) ||
+ (op->opcode == AML_BYTE_FIELD_OP) ||
+ (op->opcode == AML_WORD_FIELD_OP) ||
+ (op->opcode == AML_DWORD_FIELD_OP) ||
+ (op->opcode == AML_QWORD_FIELD_OP))
+ {
+ /*
+ * Backup to beginning of Create_xXXfield declaration (1 for
+ * Opcode)
+ *
+ * Body_length is unknown until we parse the body
+ */
+ deferred_op = (ACPI_PARSE2_OBJECT *) op;
+ deferred_op->length = parser_state->aml - deferred_op->data;
+ }
/* This op complete, notify the dispatcher */
@@ -841,6 +855,9 @@
close_this_op:
+ /*
+ * Finished one argument of the containing scope
+ */
parser_state->scope->parse_scope.arg_count--;
/* Close this Op (may result in parse subtree deletion) */
@@ -850,18 +867,58 @@
}
- if (status == AE_CTRL_END) {
- acpi_ps_pop_scope (parser_state, &op, &arg_types);
+ switch (status)
+ {
+ case AE_OK:
+ break;
+
+
+ case AE_CTRL_TRANSFER:
+
+ /*
+ * We are about to transfer to a called method.
+ */
+ walk_state->prev_op = op;
+ walk_state->prev_arg_types = arg_types;
+ return (status);
+ break;
+
+
+ case AE_CTRL_END:
+
+ acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count);
+
status = walk_state->ascending_callback (walk_state, op);
status = acpi_ps_next_parse_state (walk_state, op, status);
+
acpi_ps_complete_this_op (walk_state, op);
op = NULL;
status = AE_OK;
- }
+ break;
+
+
+ case AE_CTRL_TERMINATE:
+
+ status = AE_OK;
+
+ /* Clean up */
+ do
+ {
+ if (op) {
+ acpi_ps_complete_this_op (walk_state, op);
+ }
+
+ acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count);
+ } while (op);
+
+ return (status);
+ break;
+
+
+ default: /* All other non-AE_OK status */
- else if (ACPI_FAILURE (status)) {
if (op == NULL) {
- acpi_ps_pop_scope (parser_state, &op, &arg_types);
+ acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count);
}
walk_state->prev_op = op;
walk_state->prev_arg_types = arg_types;
@@ -870,27 +927,15 @@
* TEMP:
*/
- if (status == AE_CTRL_TERMINATE) {
- status = AE_OK;
-
- /* Clean up */
- do
- {
- if (op) {
- acpi_ps_complete_this_op (walk_state, op);
- }
-
- acpi_ps_pop_scope (parser_state, &op, &arg_types);
- } while (op);
- }
return (status);
+ break;
}
/* This scope complete? */
if (acpi_ps_has_completed_scope (parser_state)) {
- acpi_ps_pop_scope (parser_state, &op, &arg_types);
+ acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count);
}
else {
@@ -899,6 +944,9 @@
}
+
+ /* Arg_count is non-zero */
+
else {
/* complex argument, push Op and prepare for argument */
@@ -937,7 +985,7 @@
acpi_ps_complete_this_op (walk_state, op);
}
- acpi_ps_pop_scope (parser_state, &op, &arg_types);
+ acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count);
} while (op);
@@ -953,7 +1001,7 @@
acpi_ps_complete_this_op (walk_state, op);
}
- acpi_ps_pop_scope (parser_state, &op, &arg_types);
+ acpi_ps_pop_scope (parser_state, &op, &arg_types, &arg_count);
} while (op);
@@ -996,7 +1044,6 @@
ACPI_WALK_LIST *prev_walk_list = acpi_gbl_current_walk_list;
ACPI_OPERAND_OBJECT *return_desc;
ACPI_OPERAND_OBJECT *mth_desc = NULL;
- ACPI_NAMESPACE_NODE *start_node;
/* Create and initialize a new parser state */
@@ -1034,19 +1081,16 @@
if (method_node) {
- start_node = method_node;
parser_state->start_node = method_node;
walk_state->walk_type = WALK_METHOD;
- if (start_node) {
- /* Push start scope on scope stack and make it current */
-
- status = acpi_ds_scope_stack_push (start_node, ACPI_TYPE_METHOD, walk_state);
- if (ACPI_FAILURE (status)) {
- return (status);
- }
+ /* 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 (status);
}
+
/* Init arguments if this is a control method */
/* TBD: [Restructure] add walkstate as a param */
@@ -1057,6 +1101,8 @@
/* Setup the current scope */
node = parser_state->start_op->node;
+ parser_state->start_node = node;
+
if (node) {
/* Push start scope on scope stack and make it current */
@@ -1145,6 +1191,7 @@
*/
acpi_ds_restart_control_method (walk_state, return_desc);
+ walk_state->walk_type |= WALK_METHOD_RESTART;
}
/*
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)