1 /******************************************************************************
3 * Module Name: amdyadic - ACPI AML (p-code) execution for dyadic operators
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
31 #define _COMPONENT ACPI_EXECUTER
32 MODULE_NAME ("amdyadic")
35 /*******************************************************************************
37 * FUNCTION: Acpi_aml_do_concatenate
39 * PARAMETERS: *Obj_desc - Object to be converted. Must be an
40 * Integer, Buffer, or String
44 * DESCRIPTION: Concatenate two objects OF THE SAME TYPE.
46 ******************************************************************************/
49 acpi_aml_do_concatenate (
50 ACPI_OPERAND_OBJECT
*obj_desc
,
51 ACPI_OPERAND_OBJECT
*obj_desc2
,
52 ACPI_OPERAND_OBJECT
**actual_ret_desc
,
53 ACPI_WALK_STATE
*walk_state
)
57 ACPI_INTEGER this_integer
;
58 ACPI_OPERAND_OBJECT
*ret_desc
;
60 u32 integer_size
= sizeof (ACPI_INTEGER
);
64 * There are three cases to handle:
65 * 1) Two Integers concatenated to produce a buffer
66 * 2) Two Strings concatenated to produce a string
67 * 3) Two Buffers concatenated to produce a buffer
69 switch (obj_desc
->common
.type
) {
70 case ACPI_TYPE_INTEGER
:
72 /* Handle both ACPI 1.0 and ACPI 2.0 Integer widths */
74 if (walk_state
->method_node
->flags
& ANOBJ_DATA_WIDTH_32
) {
76 * We are running a method that exists in a 32-bit ACPI table.
77 * Truncate the value to 32 bits by zeroing out the upper
80 integer_size
= sizeof (u32
);
83 /* Result of two integers is a buffer */
85 ret_desc
= acpi_cm_create_internal_object (ACPI_TYPE_BUFFER
);
87 return (AE_NO_MEMORY
);
90 /* Need enough space for two integers */
92 ret_desc
->buffer
.length
= integer_size
* 2;
93 new_buf
= acpi_cm_callocate (ret_desc
->buffer
.length
);
96 (("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n"));
97 status
= AE_NO_MEMORY
;
101 ret_desc
->buffer
.pointer
= (u8
*) new_buf
;
103 /* Convert the first integer */
105 this_integer
= obj_desc
->integer
.value
;
106 for (i
= 0; i
< integer_size
; i
++) {
107 new_buf
[i
] = (u8
) this_integer
;
111 /* Convert the second integer */
113 this_integer
= obj_desc2
->integer
.value
;
114 for (; i
< (integer_size
* 2); i
++) {
115 new_buf
[i
] = (u8
) this_integer
;
122 case ACPI_TYPE_STRING
:
124 ret_desc
= acpi_cm_create_internal_object (ACPI_TYPE_STRING
);
126 return (AE_NO_MEMORY
);
129 /* Operand1 is string */
131 new_buf
= acpi_cm_allocate (obj_desc
->string
.length
+
132 obj_desc2
->string
.length
+ 1);
135 (("Aml_exec_dyadic2_r/Concat_op: String allocation failure\n"));
136 status
= AE_NO_MEMORY
;
140 STRCPY (new_buf
, obj_desc
->string
.pointer
);
141 STRCPY (new_buf
+ obj_desc
->string
.length
,
142 obj_desc2
->string
.pointer
);
144 /* Point the return object to the new string */
146 ret_desc
->string
.pointer
= new_buf
;
147 ret_desc
->string
.length
= obj_desc
->string
.length
+=
148 obj_desc2
->string
.length
;
152 case ACPI_TYPE_BUFFER
:
154 /* Operand1 is a buffer */
156 ret_desc
= acpi_cm_create_internal_object (ACPI_TYPE_BUFFER
);
158 return (AE_NO_MEMORY
);
161 new_buf
= acpi_cm_allocate (obj_desc
->buffer
.length
+
162 obj_desc2
->buffer
.length
);
165 (("Aml_exec_dyadic2_r/Concat_op: Buffer allocation failure\n"));
166 status
= AE_NO_MEMORY
;
170 MEMCPY (new_buf
, obj_desc
->buffer
.pointer
,
171 obj_desc
->buffer
.length
);
172 MEMCPY (new_buf
+ obj_desc
->buffer
.length
, obj_desc2
->buffer
.pointer
,
173 obj_desc2
->buffer
.length
);
176 * Point the return object to the new buffer
179 ret_desc
->buffer
.pointer
= (u8
*) new_buf
;
180 ret_desc
->buffer
.length
= obj_desc
->buffer
.length
+
181 obj_desc2
->buffer
.length
;
185 status
= AE_AML_INTERNAL
;
190 *actual_ret_desc
= ret_desc
;
196 acpi_cm_remove_reference (ret_desc
);
201 /*******************************************************************************
203 * FUNCTION: Acpi_aml_exec_dyadic1
205 * PARAMETERS: Opcode - The opcode to be executed
209 * DESCRIPTION: Execute Type 1 dyadic operator with numeric operands:
212 * ALLOCATION: Deletes both operands
214 ******************************************************************************/
217 acpi_aml_exec_dyadic1 (
219 ACPI_WALK_STATE
*walk_state
)
221 ACPI_OPERAND_OBJECT
*obj_desc
= NULL
;
222 ACPI_OPERAND_OBJECT
*val_desc
= NULL
;
223 ACPI_NAMESPACE_NODE
*node
;
224 ACPI_STATUS status
= AE_OK
;
227 /* Resolve all operands */
229 status
= acpi_aml_resolve_operands (opcode
, WALK_OPERANDS
, walk_state
);
230 /* Get the operands */
232 status
|= acpi_ds_obj_stack_pop_object (&val_desc
, walk_state
);
233 status
|= acpi_ds_obj_stack_pop_object (&obj_desc
, walk_state
);
234 if (ACPI_FAILURE (status
)) {
235 /* Invalid parameters on object stack */
241 /* Examine the opcode */
245 /* Def_notify := Notify_op Notify_object Notify_value */
249 /* The Obj_desc is actually an Node */
251 node
= (ACPI_NAMESPACE_NODE
*) obj_desc
;
254 /* Object must be a device or thermal zone */
256 if (node
&& val_desc
) {
257 switch (node
->type
) {
258 case ACPI_TYPE_DEVICE
:
259 case ACPI_TYPE_THERMAL
:
262 * Dispatch the notify to the appropriate handler
263 * NOTE: the request is queued for execution after this method
264 * completes. The notify handlers are NOT invoked synchronously
265 * from this thread -- because handlers may in turn run other
269 status
= acpi_ev_queue_notify_request (node
,
270 (u32
) val_desc
->integer
.value
);
274 status
= AE_AML_OPERAND_TYPE
;
282 REPORT_ERROR (("Acpi_aml_exec_dyadic1: Unknown dyadic opcode %X\n",
284 status
= AE_AML_BAD_OPCODE
;
290 /* Always delete both operands */
292 acpi_cm_remove_reference (val_desc
);
293 acpi_cm_remove_reference (obj_desc
);
300 /*******************************************************************************
302 * FUNCTION: Acpi_aml_exec_dyadic2_r
304 * PARAMETERS: Opcode - The opcode to be executed
308 * DESCRIPTION: Execute Type 2 dyadic operator with numeric operands and
309 * one or two result operands.
311 * ALLOCATION: Deletes one operand descriptor -- other remains on stack
313 ******************************************************************************/
316 acpi_aml_exec_dyadic2_r (
318 ACPI_WALK_STATE
*walk_state
,
319 ACPI_OPERAND_OBJECT
**return_desc
)
321 ACPI_OPERAND_OBJECT
*obj_desc
= NULL
;
322 ACPI_OPERAND_OBJECT
*obj_desc2
= NULL
;
323 ACPI_OPERAND_OBJECT
*res_desc
= NULL
;
324 ACPI_OPERAND_OBJECT
*res_desc2
= NULL
;
325 ACPI_OPERAND_OBJECT
*ret_desc
= NULL
;
326 ACPI_OPERAND_OBJECT
*ret_desc2
= NULL
;
327 ACPI_STATUS status
= AE_OK
;
328 u32 num_operands
= 3;
331 /* Resolve all operands */
333 status
= acpi_aml_resolve_operands (opcode
, WALK_OPERANDS
, walk_state
);
334 /* Get all operands */
336 if (AML_DIVIDE_OP
== opcode
) {
338 status
|= acpi_ds_obj_stack_pop_object (&res_desc2
, walk_state
);
341 status
|= acpi_ds_obj_stack_pop_object (&res_desc
, walk_state
);
342 status
|= acpi_ds_obj_stack_pop_object (&obj_desc2
, walk_state
);
343 status
|= acpi_ds_obj_stack_pop_object (&obj_desc
, walk_state
);
344 if (ACPI_FAILURE (status
)) {
349 /* Create an internal return object if necessary */
354 case AML_BIT_NAND_OP
:
359 case AML_MULTIPLY_OP
:
360 case AML_SHIFT_LEFT_OP
:
361 case AML_SHIFT_RIGHT_OP
:
362 case AML_SUBTRACT_OP
:
364 ret_desc
= acpi_cm_create_internal_object (ACPI_TYPE_INTEGER
);
366 status
= AE_NO_MEMORY
;
380 /* Def_add := Add_op Operand1 Operand2 Result */
384 ret_desc
->integer
.value
= obj_desc
->integer
.value
+
385 obj_desc2
->integer
.value
;
389 /* Def_and := And_op Operand1 Operand2 Result */
393 ret_desc
->integer
.value
= obj_desc
->integer
.value
&
394 obj_desc2
->integer
.value
;
398 /* Def_nAnd := NAnd_op Operand1 Operand2 Result */
400 case AML_BIT_NAND_OP
:
402 ret_desc
->integer
.value
= ~(obj_desc
->integer
.value
&
403 obj_desc2
->integer
.value
);
407 /* Def_or := Or_op Operand1 Operand2 Result */
411 ret_desc
->integer
.value
= obj_desc
->integer
.value
|
412 obj_desc2
->integer
.value
;
416 /* Def_nOr := NOr_op Operand1 Operand2 Result */
420 ret_desc
->integer
.value
= ~(obj_desc
->integer
.value
|
421 obj_desc2
->integer
.value
);
425 /* Def_xOr := XOr_op Operand1 Operand2 Result */
429 ret_desc
->integer
.value
= obj_desc
->integer
.value
^
430 obj_desc2
->integer
.value
;
434 /* Def_divide := Divide_op Dividend Divisor Remainder Quotient */
438 if (!obj_desc2
->integer
.value
) {
440 (("Aml_exec_dyadic2_r/Divide_op: Divide by zero\n"));
442 status
= AE_AML_DIVIDE_BY_ZERO
;
446 ret_desc2
= acpi_cm_create_internal_object (ACPI_TYPE_INTEGER
);
448 status
= AE_NO_MEMORY
;
452 /* Remainder (modulo) */
454 ret_desc
->integer
.value
= ACPI_MODULO (obj_desc
->integer
.value
,
455 obj_desc2
->integer
.value
);
457 /* Result (what we used to call the quotient) */
459 ret_desc2
->integer
.value
= ACPI_DIVIDE (obj_desc
->integer
.value
,
460 obj_desc2
->integer
.value
);
464 /* Def_multiply := Multiply_op Operand1 Operand2 Result */
466 case AML_MULTIPLY_OP
:
468 ret_desc
->integer
.value
= obj_desc
->integer
.value
*
469 obj_desc2
->integer
.value
;
473 /* Def_shift_left := Shift_left_op Operand Shift_count Result */
475 case AML_SHIFT_LEFT_OP
:
477 ret_desc
->integer
.value
= obj_desc
->integer
.value
<<
478 obj_desc2
->integer
.value
;
482 /* Def_shift_right := Shift_right_op Operand Shift_count Result */
484 case AML_SHIFT_RIGHT_OP
:
486 ret_desc
->integer
.value
= obj_desc
->integer
.value
>>
487 obj_desc2
->integer
.value
;
491 /* Def_subtract := Subtract_op Operand1 Operand2 Result */
493 case AML_SUBTRACT_OP
:
495 ret_desc
->integer
.value
= obj_desc
->integer
.value
-
496 obj_desc2
->integer
.value
;
500 /* Def_concat := Concat_op Data1 Data2 Result */
506 * Convert the second operand if necessary. The first operand
507 * determines the type of the second operand, (See the Data Types
508 * section of the ACPI specification.) Both object types are
509 * guaranteed to be either Integer/String/Buffer by the operand
510 * resolution mechanism above.
513 switch (obj_desc
->common
.type
) {
514 case ACPI_TYPE_INTEGER
:
515 status
= acpi_aml_convert_to_integer (&obj_desc2
, walk_state
);
518 case ACPI_TYPE_STRING
:
519 status
= acpi_aml_convert_to_string (&obj_desc2
, walk_state
);
522 case ACPI_TYPE_BUFFER
:
523 status
= acpi_aml_convert_to_buffer (&obj_desc2
, walk_state
);
527 status
= AE_AML_INTERNAL
;
530 if (ACPI_FAILURE (status
)) {
536 * Both operands are now known to be the same object type
537 * (Both are Integer, String, or Buffer), and we can now perform the
540 status
= acpi_aml_do_concatenate (obj_desc
, obj_desc2
, &ret_desc
, walk_state
);
541 if (ACPI_FAILURE (status
)) {
549 REPORT_ERROR (("Acpi_aml_exec_dyadic2_r: Unknown dyadic opcode %X\n",
551 status
= AE_AML_BAD_OPCODE
;
557 * Store the result of the operation (which is now in Obj_desc) into
558 * the result descriptor, or the location pointed to by the result
559 * descriptor (Res_desc).
562 status
= acpi_aml_exec_store (ret_desc
, res_desc
, walk_state
);
563 if (ACPI_FAILURE (status
)) {
567 if (AML_DIVIDE_OP
== opcode
) {
568 status
= acpi_aml_exec_store (ret_desc2
, res_desc2
, walk_state
);
571 * Since the remainder is not returned, remove a reference to
572 * the object we created earlier
575 acpi_cm_remove_reference (ret_desc2
);
581 /* Always delete the operands */
583 acpi_cm_remove_reference (obj_desc
);
584 acpi_cm_remove_reference (obj_desc2
);
587 /* Delete return object on error */
589 if (ACPI_FAILURE (status
)) {
590 /* On failure, delete the result ops */
592 acpi_cm_remove_reference (res_desc
);
593 acpi_cm_remove_reference (res_desc2
);
596 /* And delete the internal return object */
598 acpi_cm_remove_reference (ret_desc
);
603 /* Set the return object and exit */
605 *return_desc
= ret_desc
;
610 /*******************************************************************************
612 * FUNCTION: Acpi_aml_exec_dyadic2_s
614 * PARAMETERS: Opcode - The opcode to be executed
618 * DESCRIPTION: Execute Type 2 dyadic synchronization operator
620 * ALLOCATION: Deletes one operand descriptor -- other remains on stack
622 ******************************************************************************/
625 acpi_aml_exec_dyadic2_s (
627 ACPI_WALK_STATE
*walk_state
,
628 ACPI_OPERAND_OBJECT
**return_desc
)
630 ACPI_OPERAND_OBJECT
*obj_desc
;
631 ACPI_OPERAND_OBJECT
*time_desc
;
632 ACPI_OPERAND_OBJECT
*ret_desc
= NULL
;
636 /* Resolve all operands */
638 status
= acpi_aml_resolve_operands (opcode
, WALK_OPERANDS
, walk_state
);
639 /* Get all operands */
641 status
|= acpi_ds_obj_stack_pop_object (&time_desc
, walk_state
);
642 status
|= acpi_ds_obj_stack_pop_object (&obj_desc
, walk_state
);
643 if (ACPI_FAILURE (status
)) {
644 /* Invalid parameters on object stack */
650 /* Create the internal return object */
652 ret_desc
= acpi_cm_create_internal_object (ACPI_TYPE_INTEGER
);
654 status
= AE_NO_MEMORY
;
658 /* Default return value is FALSE, operation did not time out */
660 ret_desc
->integer
.value
= 0;
663 /* Examine the opcode */
667 /* Def_acquire := Acquire_op Mutex_object Timeout */
671 status
= acpi_aml_acquire_mutex (time_desc
, obj_desc
, walk_state
);
675 /* Def_wait := Wait_op Acpi_event_object Timeout */
679 status
= acpi_aml_system_wait_event (time_desc
, obj_desc
);
685 REPORT_ERROR (("Acpi_aml_exec_dyadic2_s: Unknown dyadic synchronization opcode %X\n", opcode
));
686 status
= AE_AML_BAD_OPCODE
;
692 * Return a boolean indicating if operation timed out
693 * (TRUE) or not (FALSE)
696 if (status
== AE_TIME
) {
697 ret_desc
->integer
.value
= ACPI_INTEGER_MAX
; /* TRUE, op timed out */
706 acpi_cm_remove_reference (time_desc
);
707 acpi_cm_remove_reference (obj_desc
);
709 /* Delete return object on error */
711 if (ACPI_FAILURE (status
) &&
713 acpi_cm_remove_reference (ret_desc
);
718 /* Set the return object and exit */
720 *return_desc
= ret_desc
;
725 /*******************************************************************************
727 * FUNCTION: Acpi_aml_exec_dyadic2
729 * PARAMETERS: Opcode - The opcode to be executed
733 * DESCRIPTION: Execute Type 2 dyadic operator with numeric operands and
736 * ALLOCATION: Deletes one operand descriptor -- other remains on stack
737 * containing result value
739 ******************************************************************************/
742 acpi_aml_exec_dyadic2 (
744 ACPI_WALK_STATE
*walk_state
,
745 ACPI_OPERAND_OBJECT
**return_desc
)
747 ACPI_OPERAND_OBJECT
*obj_desc
;
748 ACPI_OPERAND_OBJECT
*obj_desc2
;
749 ACPI_OPERAND_OBJECT
*ret_desc
= NULL
;
754 /* Resolve all operands */
756 status
= acpi_aml_resolve_operands (opcode
, WALK_OPERANDS
, walk_state
);
757 /* Get all operands */
759 status
|= acpi_ds_obj_stack_pop_object (&obj_desc2
, walk_state
);
760 status
|= acpi_ds_obj_stack_pop_object (&obj_desc
, walk_state
);
761 if (ACPI_FAILURE (status
)) {
762 /* Invalid parameters on object stack */
768 /* Create the internal return object */
770 ret_desc
= acpi_cm_create_internal_object (ACPI_TYPE_INTEGER
);
772 status
= AE_NO_MEMORY
;
783 /* Def_lAnd := LAnd_op Operand1 Operand2 */
787 lboolean
= (u8
) (obj_desc
->integer
.value
&&
788 obj_desc2
->integer
.value
);
792 /* Def_lEqual := LEqual_op Operand1 Operand2 */
796 lboolean
= (u8
) (obj_desc
->integer
.value
==
797 obj_desc2
->integer
.value
);
801 /* Def_lGreater := LGreater_op Operand1 Operand2 */
803 case AML_LGREATER_OP
:
805 lboolean
= (u8
) (obj_desc
->integer
.value
>
806 obj_desc2
->integer
.value
);
810 /* Def_lLess := LLess_op Operand1 Operand2 */
814 lboolean
= (u8
) (obj_desc
->integer
.value
<
815 obj_desc2
->integer
.value
);
819 /* Def_lOr := LOr_op Operand1 Operand2 */
823 lboolean
= (u8
) (obj_desc
->integer
.value
||
824 obj_desc2
->integer
.value
);
830 REPORT_ERROR (("Acpi_aml_exec_dyadic2: Unknown dyadic opcode %X\n", opcode
));
831 status
= AE_AML_BAD_OPCODE
;
837 /* Set return value to logical TRUE (all ones) or FALSE (zero) */
840 ret_desc
->integer
.value
= ACPI_INTEGER_MAX
;
843 ret_desc
->integer
.value
= 0;
849 /* Always delete operands */
851 acpi_cm_remove_reference (obj_desc
);
852 acpi_cm_remove_reference (obj_desc2
);
855 /* Delete return object on error */
857 if (ACPI_FAILURE (status
) &&
859 acpi_cm_remove_reference (ret_desc
);
864 /* Set the return object and exit */
866 *return_desc
= ret_desc
;