initial commit with v2.6.9
[linux-2.6.9-moxart.git] / drivers / acpi / dispatcher / dsutils.c
blob24462789ad00604ac2242a76623299b1aa22d04d
1 /*******************************************************************************
3 * Module Name: dsutils - Dispatcher utilities
5 ******************************************************************************/
7 /*
8 * Copyright (C) 2000 - 2004, R. Byron Moore
9 * All rights reserved.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
45 #include <acpi/acpi.h>
46 #include <acpi/acparser.h>
47 #include <acpi/amlcode.h>
48 #include <acpi/acdispat.h>
49 #include <acpi/acinterp.h>
50 #include <acpi/acnamesp.h>
51 #include <acpi/acdebug.h>
53 #define _COMPONENT ACPI_DISPATCHER
54 ACPI_MODULE_NAME ("dsutils")
57 #ifndef ACPI_NO_METHOD_EXECUTION
59 /*******************************************************************************
61 * FUNCTION: acpi_ds_is_result_used
63 * PARAMETERS: Op - Current Op
64 * walk_state - Current State
66 * RETURN: TRUE if result is used, FALSE otherwise
68 * DESCRIPTION: Check if a result object will be used by the parent
70 ******************************************************************************/
73 acpi_ds_is_result_used (
74 union acpi_parse_object *op,
75 struct acpi_walk_state *walk_state)
77 const struct acpi_opcode_info *parent_info;
80 ACPI_FUNCTION_TRACE_PTR ("ds_is_result_used", op);
83 /* Must have both an Op and a Result Object */
85 if (!op) {
86 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null Op\n"));
87 return_VALUE (TRUE);
91 * If there is no parent, we are executing at the method level.
92 * An executing method typically has no parent, since each method
93 * is parsed separately.
95 if (!op->common.parent) {
97 * If this is the last statement in the method, we know it is not a
98 * Return() operator (would not come here.) The following code is the
99 * optional support for a so-called "implicit return". Some AML code
100 * assumes that the last value of the method is "implicitly" returned
101 * to the caller. Just save the last result as the return value.
102 * NOTE: this is optional because the ASL language does not actually
103 * support this behavior.
105 if ((acpi_gbl_enable_interpreter_slack) &&
106 (walk_state->parser_state.aml >= walk_state->parser_state.aml_end)) {
107 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
108 "Result of [%s] will be implicitly returned\n",
109 acpi_ps_get_opcode_name (op->common.aml_opcode)));
111 /* Use the top of the result stack as the implicit return value */
113 walk_state->return_desc = walk_state->results->results.obj_desc[0];
114 return_VALUE (TRUE);
117 /* No parent, the return value cannot possibly be used */
119 return_VALUE (FALSE);
122 /* Get info on the parent. The root_op is AML_SCOPE */
124 parent_info = acpi_ps_get_opcode_info (op->common.parent->common.aml_opcode);
125 if (parent_info->class == AML_CLASS_UNKNOWN) {
126 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown parent opcode. Op=%p\n", op));
127 return_VALUE (FALSE);
131 * Decide what to do with the result based on the parent. If
132 * the parent opcode will not use the result, delete the object.
133 * Otherwise leave it as is, it will be deleted when it is used
134 * as an operand later.
136 switch (parent_info->class) {
137 case AML_CLASS_CONTROL:
139 switch (op->common.parent->common.aml_opcode) {
140 case AML_RETURN_OP:
142 /* Never delete the return value associated with a return opcode */
144 goto result_used;
146 case AML_IF_OP:
147 case AML_WHILE_OP:
150 * If we are executing the predicate AND this is the predicate op,
151 * we will use the return value
153 if ((walk_state->control_state->common.state == ACPI_CONTROL_PREDICATE_EXECUTING) &&
154 (walk_state->control_state->control.predicate_op == op)) {
155 goto result_used;
157 break;
159 default:
160 /* Ignore other control opcodes */
161 break;
164 /* The general control opcode returns no result */
166 goto result_not_used;
169 case AML_CLASS_CREATE:
172 * These opcodes allow term_arg(s) as operands and therefore
173 * the operands can be method calls. The result is used.
175 goto result_used;
178 case AML_CLASS_NAMED_OBJECT:
180 if ((op->common.parent->common.aml_opcode == AML_REGION_OP) ||
181 (op->common.parent->common.aml_opcode == AML_DATA_REGION_OP) ||
182 (op->common.parent->common.aml_opcode == AML_PACKAGE_OP) ||
183 (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP) ||
184 (op->common.parent->common.aml_opcode == AML_BUFFER_OP) ||
185 (op->common.parent->common.aml_opcode == AML_INT_EVAL_SUBTREE_OP)) {
187 * These opcodes allow term_arg(s) as operands and therefore
188 * the operands can be method calls. The result is used.
190 goto result_used;
193 goto result_not_used;
196 default:
199 * In all other cases. the parent will actually use the return
200 * object, so keep it.
202 goto result_used;
206 result_used:
207 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Result of [%s] used by Parent [%s] Op=%p\n",
208 acpi_ps_get_opcode_name (op->common.aml_opcode),
209 acpi_ps_get_opcode_name (op->common.parent->common.aml_opcode), op));
211 return_VALUE (TRUE);
214 result_not_used:
215 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Result of [%s] not used by Parent [%s] Op=%p\n",
216 acpi_ps_get_opcode_name (op->common.aml_opcode),
217 acpi_ps_get_opcode_name (op->common.parent->common.aml_opcode), op));
219 return_VALUE (FALSE);
223 /*******************************************************************************
225 * FUNCTION: acpi_ds_delete_result_if_not_used
227 * PARAMETERS: Op - Current parse Op
228 * result_obj - Result of the operation
229 * walk_state - Current state
231 * RETURN: Status
233 * DESCRIPTION: Used after interpretation of an opcode. If there is an internal
234 * result descriptor, check if the parent opcode will actually use
235 * this result. If not, delete the result now so that it will
236 * not become orphaned.
238 ******************************************************************************/
240 void
241 acpi_ds_delete_result_if_not_used (
242 union acpi_parse_object *op,
243 union acpi_operand_object *result_obj,
244 struct acpi_walk_state *walk_state)
246 union acpi_operand_object *obj_desc;
247 acpi_status status;
250 ACPI_FUNCTION_TRACE_PTR ("ds_delete_result_if_not_used", result_obj);
253 if (!op) {
254 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null Op\n"));
255 return_VOID;
258 if (!result_obj) {
259 return_VOID;
262 if (!acpi_ds_is_result_used (op, walk_state)) {
264 * Must pop the result stack (obj_desc should be equal to result_obj)
266 status = acpi_ds_result_pop (&obj_desc, walk_state);
267 if (ACPI_SUCCESS (status)) {
268 acpi_ut_remove_reference (result_obj);
272 return_VOID;
276 /*******************************************************************************
278 * FUNCTION: acpi_ds_resolve_operands
280 * PARAMETERS: walk_state - Current walk state with operands on stack
282 * RETURN: Status
284 * DESCRIPTION: Resolve all operands to their values. Used to prepare
285 * arguments to a control method invocation (a call from one
286 * method to another.)
288 ******************************************************************************/
290 acpi_status
291 acpi_ds_resolve_operands (
292 struct acpi_walk_state *walk_state)
294 u32 i;
295 acpi_status status = AE_OK;
298 ACPI_FUNCTION_TRACE_PTR ("ds_resolve_operands", walk_state);
302 * Attempt to resolve each of the valid operands
303 * Method arguments are passed by reference, not by value. This means
304 * that the actual objects are passed, not copies of the objects.
306 for (i = 0; i < walk_state->num_operands; i++) {
307 status = acpi_ex_resolve_to_value (&walk_state->operands[i], walk_state);
308 if (ACPI_FAILURE (status)) {
309 break;
313 return_ACPI_STATUS (status);
317 /*******************************************************************************
319 * FUNCTION: acpi_ds_clear_operands
321 * PARAMETERS: walk_state - Current walk state with operands on stack
323 * RETURN: None
325 * DESCRIPTION: Clear all operands on the current walk state operand stack.
327 ******************************************************************************/
329 void
330 acpi_ds_clear_operands (
331 struct acpi_walk_state *walk_state)
333 u32 i;
336 ACPI_FUNCTION_TRACE_PTR ("acpi_ds_clear_operands", walk_state);
340 * Remove a reference on each operand on the stack
342 for (i = 0; i < walk_state->num_operands; i++) {
344 * Remove a reference to all operands, including both
345 * "Arguments" and "Targets".
347 acpi_ut_remove_reference (walk_state->operands[i]);
348 walk_state->operands[i] = NULL;
351 walk_state->num_operands = 0;
352 return_VOID;
354 #endif
357 /*******************************************************************************
359 * FUNCTION: acpi_ds_create_operand
361 * PARAMETERS: walk_state - Current walk state
362 * Arg - Parse object for the argument
363 * arg_index - Which argument (zero based)
365 * RETURN: Status
367 * DESCRIPTION: Translate a parse tree object that is an argument to an AML
368 * opcode to the equivalent interpreter object. This may include
369 * looking up a name or entering a new name into the internal
370 * namespace.
372 ******************************************************************************/
374 acpi_status
375 acpi_ds_create_operand (
376 struct acpi_walk_state *walk_state,
377 union acpi_parse_object *arg,
378 u32 arg_index)
380 acpi_status status = AE_OK;
381 char *name_string;
382 u32 name_length;
383 union acpi_operand_object *obj_desc;
384 union acpi_parse_object *parent_op;
385 u16 opcode;
386 acpi_interpreter_mode interpreter_mode;
387 const struct acpi_opcode_info *op_info;
390 ACPI_FUNCTION_TRACE_PTR ("ds_create_operand", arg);
393 /* A valid name must be looked up in the namespace */
395 if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) &&
396 (arg->common.value.string)) {
397 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", arg));
399 /* Get the entire name string from the AML stream */
401 status = acpi_ex_get_name_string (ACPI_TYPE_ANY, arg->common.value.buffer,
402 &name_string, &name_length);
404 if (ACPI_FAILURE (status)) {
405 return_ACPI_STATUS (status);
409 * All prefixes have been handled, and the name is
410 * in name_string
415 * Special handling for buffer_field declarations. This is a deferred
416 * opcode that unfortunately defines the field name as the last
417 * parameter instead of the first. We get here when we are performing
418 * the deferred execution, so the actual name of the field is already
419 * in the namespace. We don't want to attempt to look it up again
420 * because we may be executing in a different scope than where the
421 * actual opcode exists.
423 if ((walk_state->deferred_node) &&
424 (walk_state->deferred_node->type == ACPI_TYPE_BUFFER_FIELD) &&
425 (arg_index != 0)) {
426 obj_desc = ACPI_CAST_PTR (union acpi_operand_object, walk_state->deferred_node);
427 status = AE_OK;
429 else /* All other opcodes */ {
431 * Differentiate between a namespace "create" operation
432 * versus a "lookup" operation (IMODE_LOAD_PASS2 vs.
433 * IMODE_EXECUTE) in order to support the creation of
434 * namespace objects during the execution of control methods.
436 parent_op = arg->common.parent;
437 op_info = acpi_ps_get_opcode_info (parent_op->common.aml_opcode);
438 if ((op_info->flags & AML_NSNODE) &&
439 (parent_op->common.aml_opcode != AML_INT_METHODCALL_OP) &&
440 (parent_op->common.aml_opcode != AML_REGION_OP) &&
441 (parent_op->common.aml_opcode != AML_INT_NAMEPATH_OP)) {
442 /* Enter name into namespace if not found */
444 interpreter_mode = ACPI_IMODE_LOAD_PASS2;
446 else {
447 /* Return a failure if name not found */
449 interpreter_mode = ACPI_IMODE_EXECUTE;
452 status = acpi_ns_lookup (walk_state->scope_info, name_string,
453 ACPI_TYPE_ANY, interpreter_mode,
454 ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
455 walk_state,
456 ACPI_CAST_INDIRECT_PTR (struct acpi_namespace_node, &obj_desc));
458 * The only case where we pass through (ignore) a NOT_FOUND
459 * error is for the cond_ref_of opcode.
461 if (status == AE_NOT_FOUND) {
462 if (parent_op->common.aml_opcode == AML_COND_REF_OF_OP) {
464 * For the Conditional Reference op, it's OK if
465 * the name is not found; We just need a way to
466 * indicate this to the interpreter, set the
467 * object to the root
469 obj_desc = ACPI_CAST_PTR (union acpi_operand_object, acpi_gbl_root_node);
470 status = AE_OK;
472 else {
474 * We just plain didn't find it -- which is a
475 * very serious error at this point
477 status = AE_AML_NAME_NOT_FOUND;
481 if (ACPI_FAILURE (status)) {
482 ACPI_REPORT_NSERROR (name_string, status);
486 /* Free the namestring created above */
488 ACPI_MEM_FREE (name_string);
490 /* Check status from the lookup */
492 if (ACPI_FAILURE (status)) {
493 return_ACPI_STATUS (status);
496 /* Put the resulting object onto the current object stack */
498 status = acpi_ds_obj_stack_push (obj_desc, walk_state);
499 if (ACPI_FAILURE (status)) {
500 return_ACPI_STATUS (status);
502 ACPI_DEBUGGER_EXEC (acpi_db_display_argument_object (obj_desc, walk_state));
504 else {
505 /* Check for null name case */
507 if (arg->common.aml_opcode == AML_INT_NAMEPATH_OP) {
509 * If the name is null, this means that this is an
510 * optional result parameter that was not specified
511 * in the original ASL. Create a Zero Constant for a
512 * placeholder. (Store to a constant is a Noop.)
514 opcode = AML_ZERO_OP; /* Has no arguments! */
516 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Null namepath: Arg=%p\n", arg));
518 else {
519 opcode = arg->common.aml_opcode;
522 /* Get the object type of the argument */
524 op_info = acpi_ps_get_opcode_info (opcode);
525 if (op_info->object_type == ACPI_TYPE_INVALID) {
526 return_ACPI_STATUS (AE_NOT_IMPLEMENTED);
529 if (op_info->flags & AML_HAS_RETVAL) {
530 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
531 "Argument previously created, already stacked \n"));
533 ACPI_DEBUGGER_EXEC (acpi_db_display_argument_object (
534 walk_state->operands [walk_state->num_operands - 1], walk_state));
537 * Use value that was already previously returned
538 * by the evaluation of this argument
540 status = acpi_ds_result_pop_from_bottom (&obj_desc, walk_state);
541 if (ACPI_FAILURE (status)) {
543 * Only error is underflow, and this indicates
544 * a missing or null operand!
546 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Missing or null operand, %s\n",
547 acpi_format_exception (status)));
548 return_ACPI_STATUS (status);
551 else {
552 /* Create an ACPI_INTERNAL_OBJECT for the argument */
554 obj_desc = acpi_ut_create_internal_object (op_info->object_type);
555 if (!obj_desc) {
556 return_ACPI_STATUS (AE_NO_MEMORY);
559 /* Initialize the new object */
561 status = acpi_ds_init_object_from_op (walk_state, arg,
562 opcode, &obj_desc);
563 if (ACPI_FAILURE (status)) {
564 acpi_ut_delete_object_desc (obj_desc);
565 return_ACPI_STATUS (status);
569 /* Put the operand object on the object stack */
571 status = acpi_ds_obj_stack_push (obj_desc, walk_state);
572 if (ACPI_FAILURE (status)) {
573 return_ACPI_STATUS (status);
576 ACPI_DEBUGGER_EXEC (acpi_db_display_argument_object (obj_desc, walk_state));
579 return_ACPI_STATUS (AE_OK);
583 /*******************************************************************************
585 * FUNCTION: acpi_ds_create_operands
587 * PARAMETERS: first_arg - First argument of a parser argument tree
589 * RETURN: Status
591 * DESCRIPTION: Convert an operator's arguments from a parse tree format to
592 * namespace objects and place those argument object on the object
593 * stack in preparation for evaluation by the interpreter.
595 ******************************************************************************/
597 acpi_status
598 acpi_ds_create_operands (
599 struct acpi_walk_state *walk_state,
600 union acpi_parse_object *first_arg)
602 acpi_status status = AE_OK;
603 union acpi_parse_object *arg;
604 u32 arg_count = 0;
607 ACPI_FUNCTION_TRACE_PTR ("ds_create_operands", first_arg);
610 /* For all arguments in the list... */
612 arg = first_arg;
613 while (arg) {
614 status = acpi_ds_create_operand (walk_state, arg, arg_count);
615 if (ACPI_FAILURE (status)) {
616 goto cleanup;
619 ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Arg #%d (%p) done, Arg1=%p\n",
620 arg_count, arg, first_arg));
622 /* Move on to next argument, if any */
624 arg = arg->common.next;
625 arg_count++;
628 return_ACPI_STATUS (status);
631 cleanup:
633 * We must undo everything done above; meaning that we must
634 * pop everything off of the operand stack and delete those
635 * objects
637 (void) acpi_ds_obj_stack_pop_and_delete (arg_count, walk_state);
639 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "While creating Arg %d - %s\n",
640 (arg_count + 1), acpi_format_exception (status)));
641 return_ACPI_STATUS (status);