1 /*******************************************************************************
3 * Module Name: dsmthdat - control method arguments and local variables
6 ******************************************************************************/
9 * Copyright (C) 2000, 2001 R. Byron Moore
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
35 #define _COMPONENT ACPI_DISPATCHER
36 MODULE_NAME ("dsmthdat")
39 /*******************************************************************************
41 * FUNCTION: Acpi_ds_method_data_init
43 * PARAMETERS: Walk_state - Current walk state object
47 * DESCRIPTION: Initialize the data structures that hold the method's arguments
48 * and locals. The data struct is an array of NTEs for each.
49 * This allows Ref_of and De_ref_of to work properly for these
52 ******************************************************************************/
55 acpi_ds_method_data_init (
56 ACPI_WALK_STATE *walk_state)
62 * Walk_state fields are initialized to zero by the
63 * Acpi_cm_callocate().
65 * An Node is assigned to each argument and local so
66 * that Ref_of() can return a pointer to the Node.
69 /* Init the method arguments */
71 for (i = 0; i < MTH_NUM_ARGS; i++) {
72 MOVE_UNALIGNED32_TO_32 (&walk_state->arguments[i].name,
74 walk_state->arguments[i].name |= (i << 24);
75 walk_state->arguments[i].data_type = ACPI_DESC_TYPE_NAMED;
76 walk_state->arguments[i].type = ACPI_TYPE_ANY;
77 walk_state->arguments[i].flags = ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_ARG;
80 /* Init the method locals */
82 for (i = 0; i < MTH_NUM_LOCALS; i++) {
83 MOVE_UNALIGNED32_TO_32 (&walk_state->local_variables[i].name,
86 walk_state->local_variables[i].name |= (i << 24);
87 walk_state->local_variables[i].data_type = ACPI_DESC_TYPE_NAMED;
88 walk_state->local_variables[i].type = ACPI_TYPE_ANY;
89 walk_state->local_variables[i].flags = ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_LOCAL;
96 /*******************************************************************************
98 * FUNCTION: Acpi_ds_method_data_delete_all
100 * PARAMETERS: Walk_state - Current walk state object
104 * DESCRIPTION: Delete method locals and arguments. Arguments are only
105 * deleted if this method was called from another method.
107 ******************************************************************************/
110 acpi_ds_method_data_delete_all (
111 ACPI_WALK_STATE *walk_state)
114 ACPI_OPERAND_OBJECT *object;
117 /* Delete the locals */
119 for (index = 0; index < MTH_NUM_LOCALS; index++) {
120 object = walk_state->local_variables[index].object;
124 walk_state->local_variables[index].object = NULL;
126 /* Was given a ref when stored */
128 acpi_cm_remove_reference (object);
133 /* Delete the arguments */
135 for (index = 0; index < MTH_NUM_ARGS; index++) {
136 object = walk_state->arguments[index].object;
140 walk_state->arguments[index].object = NULL;
142 /* Was given a ref when stored */
144 acpi_cm_remove_reference (object);
152 /*******************************************************************************
154 * FUNCTION: Acpi_ds_method_data_init_args
156 * PARAMETERS: *Params - Pointer to a parameter list for the method
157 * Max_param_count - The arg count for this method
158 * Walk_state - Current walk state object
162 * DESCRIPTION: Initialize arguments for a method
164 ******************************************************************************/
167 acpi_ds_method_data_init_args (
168 ACPI_OPERAND_OBJECT **params,
170 ACPI_WALK_STATE *walk_state)
181 /* Copy passed parameters into the new method stack frame */
183 for (pindex = mindex = 0;
184 (mindex < MTH_NUM_ARGS) && (pindex < max_param_count);
186 if (params[pindex]) {
189 * Set the current method argument to the
190 * Params[Pindex++] argument object descriptor
192 status = acpi_ds_store_object_to_local (AML_ARG_OP, mindex,
193 params[pindex], walk_state);
194 if (ACPI_FAILURE (status)) {
210 /*******************************************************************************
212 * FUNCTION: Acpi_ds_method_data_get_entry
214 * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
215 * Index - Which local_var or argument to get
216 * Entry - Pointer to where a pointer to the stack
218 * Walk_state - Current walk state object
222 * DESCRIPTION: Get the address of the object entry given by Opcode:Index
224 ******************************************************************************/
227 acpi_ds_method_data_get_entry (
230 ACPI_WALK_STATE *walk_state,
231 ACPI_OPERAND_OBJECT ***entry)
236 * Get the requested object.
237 * The stack "Opcode" is either a Local_variable or an Argument
244 if (index > MTH_MAX_LOCAL) {
245 return (AE_BAD_PARAMETER);
248 *entry = (ACPI_OPERAND_OBJECT **)
249 &walk_state->local_variables[index].object;
255 if (index > MTH_MAX_ARG) {
256 return (AE_BAD_PARAMETER);
259 *entry = (ACPI_OPERAND_OBJECT **)
260 &walk_state->arguments[index].object;
265 return (AE_BAD_PARAMETER);
273 /*******************************************************************************
275 * FUNCTION: Acpi_ds_method_data_set_entry
277 * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
278 * Index - Which local_var or argument to get
279 * Object - Object to be inserted into the stack entry
280 * Walk_state - Current walk state object
284 * DESCRIPTION: Insert an object onto the method stack at entry Opcode:Index.
286 ******************************************************************************/
289 acpi_ds_method_data_set_entry (
292 ACPI_OPERAND_OBJECT *object,
293 ACPI_WALK_STATE *walk_state)
296 ACPI_OPERAND_OBJECT **entry;
299 /* Get a pointer to the stack entry to set */
301 status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry);
302 if (ACPI_FAILURE (status)) {
306 /* Increment ref count so object can't be deleted while installed */
308 acpi_cm_add_reference (object);
310 /* Install the object into the stack entry */
318 /*******************************************************************************
320 * FUNCTION: Acpi_ds_method_data_get_type
322 * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
323 * Index - Which local_var or argument whose type
325 * Walk_state - Current walk state object
327 * RETURN: Data type of selected Arg or Local
328 * Used only in Exec_monadic2()/Type_op.
330 ******************************************************************************/
333 acpi_ds_method_data_get_type (
336 ACPI_WALK_STATE *walk_state)
339 ACPI_OPERAND_OBJECT **entry;
340 ACPI_OPERAND_OBJECT *object;
343 /* Get a pointer to the requested stack entry */
345 status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry);
346 if (ACPI_FAILURE (status)) {
347 return ((ACPI_TYPE_NOT_FOUND));
350 /* Get the object from the method stack */
354 /* Get the object type */
357 /* Any == 0 => "uninitialized" -- see spec 15.2.3.5.2.28 */
358 return (ACPI_TYPE_ANY);
361 return (object->common.type);
365 /*******************************************************************************
367 * FUNCTION: Acpi_ds_method_data_get_node
369 * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
370 * Index - Which local_var or argument whose type
372 * Walk_state - Current walk state object
374 * RETURN: Get the Node associated with a local or arg.
376 ******************************************************************************/
378 ACPI_NAMESPACE_NODE *
379 acpi_ds_method_data_get_node (
382 ACPI_WALK_STATE *walk_state)
384 ACPI_NAMESPACE_NODE *node = NULL;
391 if (index > MTH_MAX_LOCAL) {
395 node = &walk_state->local_variables[index];
401 if (index > MTH_MAX_ARG) {
405 node = &walk_state->arguments[index];
418 /*******************************************************************************
420 * FUNCTION: Acpi_ds_method_data_get_value
422 * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
423 * Index - Which local_var or argument to get
424 * Walk_state - Current walk state object
425 * *Dest_desc - Ptr to Descriptor into which selected Arg
426 * or Local value should be copied
430 * DESCRIPTION: Retrieve value of selected Arg or Local from the method frame
431 * at the current top of the method stack.
432 * Used only in Acpi_aml_resolve_to_value().
434 ******************************************************************************/
437 acpi_ds_method_data_get_value (
440 ACPI_WALK_STATE *walk_state,
441 ACPI_OPERAND_OBJECT **dest_desc)
444 ACPI_OPERAND_OBJECT **entry;
445 ACPI_OPERAND_OBJECT *object;
448 /* Validate the object descriptor */
451 return (AE_BAD_PARAMETER);
455 /* Get a pointer to the requested method stack entry */
457 status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry);
458 if (ACPI_FAILURE (status)) {
462 /* Get the object from the method stack */
467 /* Examine the returned object, it must be valid. */
471 * Index points to uninitialized object stack value.
472 * This means that either 1) The expected argument was
473 * not passed to the method, or 2) A local variable
474 * was referenced by the method (via the ASL)
475 * before it was initialized. Either case is an error.
481 return (AE_AML_UNINITIALIZED_ARG);
486 return (AE_AML_UNINITIALIZED_LOCAL);
493 * Index points to initialized and valid object stack value.
494 * Return an additional reference to the object
498 acpi_cm_add_reference (object);
504 /*******************************************************************************
506 * FUNCTION: Acpi_ds_method_data_delete_value
508 * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
509 * Index - Which local_var or argument to delete
510 * Walk_state - Current walk state object
514 * DESCRIPTION: Delete the entry at Opcode:Index on the method stack. Inserts
515 * a null into the stack slot after the object is deleted.
517 ******************************************************************************/
520 acpi_ds_method_data_delete_value (
523 ACPI_WALK_STATE *walk_state)
526 ACPI_OPERAND_OBJECT **entry;
527 ACPI_OPERAND_OBJECT *object;
530 /* Get a pointer to the requested entry */
532 status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry);
533 if (ACPI_FAILURE (status)) {
537 /* Get the current entry in this slot k */
542 * Undefine the Arg or Local by setting its descriptor
543 * pointer to NULL. Locals/Args can contain both
544 * ACPI_OPERAND_OBJECTS and ACPI_NAMESPACE_NODEs
550 (VALID_DESCRIPTOR_TYPE (object, ACPI_DESC_TYPE_INTERNAL))) {
552 * There is a valid object in this slot
553 * Decrement the reference count by one to balance the
554 * increment when the object was stored in the slot.
556 acpi_cm_remove_reference (object);
564 /*******************************************************************************
566 * FUNCTION: Acpi_ds_store_object_to_local
568 * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
569 * Index - Which local_var or argument to set
570 * Src_desc - Value to be stored
571 * Walk_state - Current walk state
575 * DESCRIPTION: Store a value in an Arg or Local. The Src_desc is installed
576 * as the new value for the Arg or Local and the reference count
577 * for Src_desc is incremented.
579 ******************************************************************************/
582 acpi_ds_store_object_to_local (
585 ACPI_OPERAND_OBJECT *src_desc,
586 ACPI_WALK_STATE *walk_state)
589 ACPI_OPERAND_OBJECT **entry;
592 /* Parameter validation */
595 return (AE_BAD_PARAMETER);
599 /* Get a pointer to the requested method stack entry */
601 status = acpi_ds_method_data_get_entry (opcode, index, walk_state, &entry);
602 if (ACPI_FAILURE (status)) {
606 if (*entry == src_desc) {
612 * If there is an object already in this slot, we either
613 * have to delete it, or if this is an argument and there
614 * is an object reference stored there, we have to do
620 * Check for an indirect store if an argument
621 * contains an object reference (stored as an Node).
622 * We don't allow this automatic dereferencing for
623 * locals, since a store to a local should overwrite
624 * anything there, including an object reference.
626 * If both Arg0 and Local0 contain Ref_of (Local4):
628 * Store (1, Arg0) - Causes indirect store to local4
629 * Store (1, Local0) - Stores 1 in local0, overwriting
630 * the reference to local4
631 * Store (1, De_refof (Local0)) - Causes indirect store to local4
636 if ((opcode == AML_ARG_OP) &&
637 (VALID_DESCRIPTOR_TYPE (*entry, ACPI_DESC_TYPE_NAMED))) {
638 /* Detach an existing object from the Node */
640 acpi_ns_detach_object ((ACPI_NAMESPACE_NODE *) *entry);
643 * Store this object into the Node
644 * (do the indirect store)
646 status = acpi_ns_attach_object ((ACPI_NAMESPACE_NODE *) *entry, src_desc,
647 src_desc->common.type);
652 #ifdef ACPI_ENABLE_IMPLICIT_CONVERSION
654 * Perform "Implicit conversion" of the new object to the type of the
657 status = acpi_aml_convert_to_target_type ((*entry)->common.type, &src_desc, walk_state);
658 if (ACPI_FAILURE (status)) {
664 * Delete the existing object
665 * before storing the new one
667 acpi_ds_method_data_delete_value (opcode, index, walk_state);
672 * Install the Obj_stack descriptor (*Src_desc) into
673 * the descriptor for the Arg or Local.
674 * Install the new object in the stack entry
675 * (increments the object reference count by one)
677 status = acpi_ds_method_data_set_entry (opcode, index, src_desc, walk_state);
678 if (ACPI_FAILURE (status)) {