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
29 #define _COMPONENT ACPI_DISPATCHER
30 MODULE_NAME ("dsmthdat")
33 /*******************************************************************************
35 * FUNCTION: Acpi_ds_method_data_init
37 * PARAMETERS: Walk_state - Current walk state object
41 * DESCRIPTION: Initialize the data structures that hold the method's arguments
42 * and locals. The data struct is an array of NTEs for each.
43 * This allows Ref_of and De_ref_of to work properly for these
46 ******************************************************************************/
49 acpi_ds_method_data_init (
50 ACPI_WALK_STATE
*walk_state
)
56 * Walk_state fields are initialized to zero by the
57 * Acpi_cm_callocate().
59 * An Node is assigned to each argument and local so
60 * that Ref_of() can return a pointer to the Node.
63 /* Init the method arguments */
65 for (i
= 0; i
< MTH_NUM_ARGS
; i
++) {
66 MOVE_UNALIGNED32_TO_32 (&walk_state
->arguments
[i
].name
,
68 walk_state
->arguments
[i
].name
|= (i
<< 24);
69 walk_state
->arguments
[i
].data_type
= ACPI_DESC_TYPE_NAMED
;
70 walk_state
->arguments
[i
].type
= ACPI_TYPE_ANY
;
71 walk_state
->arguments
[i
].flags
= ANOBJ_END_OF_PEER_LIST
| ANOBJ_METHOD_ARG
;
74 /* Init the method locals */
76 for (i
= 0; i
< MTH_NUM_LOCALS
; i
++) {
77 MOVE_UNALIGNED32_TO_32 (&walk_state
->local_variables
[i
].name
,
80 walk_state
->local_variables
[i
].name
|= (i
<< 24);
81 walk_state
->local_variables
[i
].data_type
= ACPI_DESC_TYPE_NAMED
;
82 walk_state
->local_variables
[i
].type
= ACPI_TYPE_ANY
;
83 walk_state
->local_variables
[i
].flags
= ANOBJ_END_OF_PEER_LIST
| ANOBJ_METHOD_LOCAL
;
90 /*******************************************************************************
92 * FUNCTION: Acpi_ds_method_data_delete_all
94 * PARAMETERS: Walk_state - Current walk state object
98 * DESCRIPTION: Delete method locals and arguments. Arguments are only
99 * deleted if this method was called from another method.
101 ******************************************************************************/
104 acpi_ds_method_data_delete_all (
105 ACPI_WALK_STATE
*walk_state
)
108 ACPI_OPERAND_OBJECT
*object
;
111 /* Delete the locals */
113 for (index
= 0; index
< MTH_NUM_LOCALS
; index
++) {
114 object
= walk_state
->local_variables
[index
].object
;
118 walk_state
->local_variables
[index
].object
= NULL
;
120 /* Was given a ref when stored */
122 acpi_cm_remove_reference (object
);
127 /* Delete the arguments */
129 for (index
= 0; index
< MTH_NUM_ARGS
; index
++) {
130 object
= walk_state
->arguments
[index
].object
;
134 walk_state
->arguments
[index
].object
= NULL
;
136 /* Was given a ref when stored */
138 acpi_cm_remove_reference (object
);
146 /*******************************************************************************
148 * FUNCTION: Acpi_ds_method_data_init_args
150 * PARAMETERS: *Params - Pointer to a parameter list for the method
151 * Max_param_count - The arg count for this method
152 * Walk_state - Current walk state object
156 * DESCRIPTION: Initialize arguments for a method
158 ******************************************************************************/
161 acpi_ds_method_data_init_args (
162 ACPI_OPERAND_OBJECT
**params
,
164 ACPI_WALK_STATE
*walk_state
)
175 /* Copy passed parameters into the new method stack frame */
177 for (pindex
= mindex
= 0;
178 (mindex
< MTH_NUM_ARGS
) && (pindex
< max_param_count
);
180 if (params
[pindex
]) {
183 * Set the current method argument to the
184 * Params[Pindex++] argument object descriptor
186 status
= acpi_ds_store_object_to_local (AML_ARG_OP
, mindex
,
187 params
[pindex
], walk_state
);
188 if (ACPI_FAILURE (status
)) {
204 /*******************************************************************************
206 * FUNCTION: Acpi_ds_method_data_get_entry
208 * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
209 * Index - Which local_var or argument to get
210 * Entry - Pointer to where a pointer to the stack
212 * Walk_state - Current walk state object
216 * DESCRIPTION: Get the address of the object entry given by Opcode:Index
218 ******************************************************************************/
221 acpi_ds_method_data_get_entry (
224 ACPI_WALK_STATE
*walk_state
,
225 ACPI_OPERAND_OBJECT
***entry
)
230 * Get the requested object.
231 * The stack "Opcode" is either a Local_variable or an Argument
238 if (index
> MTH_MAX_LOCAL
) {
239 return (AE_BAD_PARAMETER
);
242 *entry
= (ACPI_OPERAND_OBJECT
**)
243 &walk_state
->local_variables
[index
].object
;
249 if (index
> MTH_MAX_ARG
) {
250 return (AE_BAD_PARAMETER
);
253 *entry
= (ACPI_OPERAND_OBJECT
**)
254 &walk_state
->arguments
[index
].object
;
259 return (AE_BAD_PARAMETER
);
267 /*******************************************************************************
269 * FUNCTION: Acpi_ds_method_data_set_entry
271 * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
272 * Index - Which local_var or argument to get
273 * Object - Object to be inserted into the stack entry
274 * Walk_state - Current walk state object
278 * DESCRIPTION: Insert an object onto the method stack at entry Opcode:Index.
280 ******************************************************************************/
283 acpi_ds_method_data_set_entry (
286 ACPI_OPERAND_OBJECT
*object
,
287 ACPI_WALK_STATE
*walk_state
)
290 ACPI_OPERAND_OBJECT
**entry
;
293 /* Get a pointer to the stack entry to set */
295 status
= acpi_ds_method_data_get_entry (opcode
, index
, walk_state
, &entry
);
296 if (ACPI_FAILURE (status
)) {
300 /* Increment ref count so object can't be deleted while installed */
302 acpi_cm_add_reference (object
);
304 /* Install the object into the stack entry */
312 /*******************************************************************************
314 * FUNCTION: Acpi_ds_method_data_get_type
316 * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
317 * Index - Which local_var or argument whose type
319 * Walk_state - Current walk state object
321 * RETURN: Data type of selected Arg or Local
322 * Used only in Exec_monadic2()/Type_op.
324 ******************************************************************************/
327 acpi_ds_method_data_get_type (
330 ACPI_WALK_STATE
*walk_state
)
333 ACPI_OPERAND_OBJECT
**entry
;
334 ACPI_OPERAND_OBJECT
*object
;
337 /* Get a pointer to the requested stack entry */
339 status
= acpi_ds_method_data_get_entry (opcode
, index
, walk_state
, &entry
);
340 if (ACPI_FAILURE (status
)) {
341 return ((ACPI_TYPE_NOT_FOUND
));
344 /* Get the object from the method stack */
348 /* Get the object type */
351 /* Any == 0 => "uninitialized" -- see spec 15.2.3.5.2.28 */
352 return (ACPI_TYPE_ANY
);
355 return (object
->common
.type
);
359 /*******************************************************************************
361 * FUNCTION: Acpi_ds_method_data_get_node
363 * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
364 * Index - Which local_var or argument whose type
366 * Walk_state - Current walk state object
368 * RETURN: Get the Node associated with a local or arg.
370 ******************************************************************************/
372 ACPI_NAMESPACE_NODE
*
373 acpi_ds_method_data_get_node (
376 ACPI_WALK_STATE
*walk_state
)
378 ACPI_NAMESPACE_NODE
*node
= NULL
;
385 if (index
> MTH_MAX_LOCAL
) {
389 node
= &walk_state
->local_variables
[index
];
395 if (index
> MTH_MAX_ARG
) {
399 node
= &walk_state
->arguments
[index
];
412 /*******************************************************************************
414 * FUNCTION: Acpi_ds_method_data_get_value
416 * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
417 * Index - Which local_var or argument to get
418 * Walk_state - Current walk state object
419 * *Dest_desc - Ptr to Descriptor into which selected Arg
420 * or Local value should be copied
424 * DESCRIPTION: Retrieve value of selected Arg or Local from the method frame
425 * at the current top of the method stack.
426 * Used only in Acpi_aml_resolve_to_value().
428 ******************************************************************************/
431 acpi_ds_method_data_get_value (
434 ACPI_WALK_STATE
*walk_state
,
435 ACPI_OPERAND_OBJECT
**dest_desc
)
438 ACPI_OPERAND_OBJECT
**entry
;
439 ACPI_OPERAND_OBJECT
*object
;
442 /* Validate the object descriptor */
445 return (AE_BAD_PARAMETER
);
449 /* Get a pointer to the requested method stack entry */
451 status
= acpi_ds_method_data_get_entry (opcode
, index
, walk_state
, &entry
);
452 if (ACPI_FAILURE (status
)) {
456 /* Get the object from the method stack */
461 /* Examine the returned object, it must be valid. */
465 * Index points to uninitialized object stack value.
466 * This means that either 1) The expected argument was
467 * not passed to the method, or 2) A local variable
468 * was referenced by the method (via the ASL)
469 * before it was initialized. Either case is an error.
475 return (AE_AML_UNINITIALIZED_ARG
);
480 return (AE_AML_UNINITIALIZED_LOCAL
);
487 * Index points to initialized and valid object stack value.
488 * Return an additional reference to the object
492 acpi_cm_add_reference (object
);
498 /*******************************************************************************
500 * FUNCTION: Acpi_ds_method_data_delete_value
502 * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
503 * Index - Which local_var or argument to delete
504 * Walk_state - Current walk state object
508 * DESCRIPTION: Delete the entry at Opcode:Index on the method stack. Inserts
509 * a null into the stack slot after the object is deleted.
511 ******************************************************************************/
514 acpi_ds_method_data_delete_value (
517 ACPI_WALK_STATE
*walk_state
)
520 ACPI_OPERAND_OBJECT
**entry
;
521 ACPI_OPERAND_OBJECT
*object
;
524 /* Get a pointer to the requested entry */
526 status
= acpi_ds_method_data_get_entry (opcode
, index
, walk_state
, &entry
);
527 if (ACPI_FAILURE (status
)) {
531 /* Get the current entry in this slot k */
536 * Undefine the Arg or Local by setting its descriptor
537 * pointer to NULL. Locals/Args can contain both
538 * ACPI_OPERAND_OBJECTS and ACPI_NAMESPACE_NODEs
544 (VALID_DESCRIPTOR_TYPE (object
, ACPI_DESC_TYPE_INTERNAL
))) {
546 * There is a valid object in this slot
547 * Decrement the reference count by one to balance the
548 * increment when the object was stored in the slot.
550 acpi_cm_remove_reference (object
);
558 /*******************************************************************************
560 * FUNCTION: Acpi_ds_store_object_to_local
562 * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP
563 * Index - Which local_var or argument to set
564 * Src_desc - Value to be stored
565 * Walk_state - Current walk state
569 * DESCRIPTION: Store a value in an Arg or Local. The Src_desc is installed
570 * as the new value for the Arg or Local and the reference count
571 * for Src_desc is incremented.
573 ******************************************************************************/
576 acpi_ds_store_object_to_local (
579 ACPI_OPERAND_OBJECT
*src_desc
,
580 ACPI_WALK_STATE
*walk_state
)
583 ACPI_OPERAND_OBJECT
**entry
;
586 /* Parameter validation */
589 return (AE_BAD_PARAMETER
);
593 /* Get a pointer to the requested method stack entry */
595 status
= acpi_ds_method_data_get_entry (opcode
, index
, walk_state
, &entry
);
596 if (ACPI_FAILURE (status
)) {
600 if (*entry
== src_desc
) {
606 * If there is an object already in this slot, we either
607 * have to delete it, or if this is an argument and there
608 * is an object reference stored there, we have to do
614 * Check for an indirect store if an argument
615 * contains an object reference (stored as an Node).
616 * We don't allow this automatic dereferencing for
617 * locals, since a store to a local should overwrite
618 * anything there, including an object reference.
620 * If both Arg0 and Local0 contain Ref_of (Local4):
622 * Store (1, Arg0) - Causes indirect store to local4
623 * Store (1, Local0) - Stores 1 in local0, overwriting
624 * the reference to local4
625 * Store (1, De_refof (Local0)) - Causes indirect store to local4
630 if ((opcode
== AML_ARG_OP
) &&
631 (VALID_DESCRIPTOR_TYPE (*entry
, ACPI_DESC_TYPE_NAMED
))) {
632 /* Detach an existing object from the Node */
634 acpi_ns_detach_object ((ACPI_NAMESPACE_NODE
*) *entry
);
637 * Store this object into the Node
638 * (do the indirect store)
640 status
= acpi_ns_attach_object ((ACPI_NAMESPACE_NODE
*) *entry
, src_desc
,
641 src_desc
->common
.type
);
646 #ifdef ACPI_ENABLE_IMPLICIT_CONVERSION
648 * Perform "Implicit conversion" of the new object to the type of the
651 status
= acpi_aml_convert_to_target_type ((*entry
)->common
.type
, &src_desc
, walk_state
);
652 if (ACPI_FAILURE (status
)) {
658 * Delete the existing object
659 * before storing the new one
661 acpi_ds_method_data_delete_value (opcode
, index
, walk_state
);
666 * Install the Obj_stack descriptor (*Src_desc) into
667 * the descriptor for the Arg or Local.
668 * Install the new object in the stack entry
669 * (increments the object reference count by one)
671 status
= acpi_ds_method_data_set_entry (opcode
, index
, src_desc
, walk_state
);
672 if (ACPI_FAILURE (status
)) {