ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / acpi / executer / exoparg2.c
1 /******************************************************************************
2  *
3  * Module Name: exoparg2 - AML execution - opcodes with 2 arguments
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2004, R. Byron Moore
9  * All rights reserved.
10  *
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.
25  *
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.
29  *
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.
42  */
43
44
45 #include <acpi/acpi.h>
46 #include <acpi/acparser.h>
47 #include <acpi/acinterp.h>
48 #include <acpi/acevents.h>
49 #include <acpi/amlcode.h>
50
51
52 #define _COMPONENT          ACPI_EXECUTER
53          ACPI_MODULE_NAME    ("exoparg2")
54
55
56 /*!
57  * Naming convention for AML interpreter execution routines.
58  *
59  * The routines that begin execution of AML opcodes are named with a common
60  * convention based upon the number of arguments, the number of target operands,
61  * and whether or not a value is returned:
62  *
63  *      AcpiExOpcode_xA_yT_zR
64  *
65  * Where:
66  *
67  * xA - ARGUMENTS:    The number of arguments (input operands) that are
68  *                    required for this opcode type (1 through 6 args).
69  * yT - TARGETS:      The number of targets (output operands) that are required
70  *                    for this opcode type (0, 1, or 2 targets).
71  * zR - RETURN VALUE: Indicates whether this opcode type returns a value
72  *                    as the function return (0 or 1).
73  *
74  * The AcpiExOpcode* functions are called via the Dispatcher component with
75  * fully resolved operands.
76 !*/
77
78
79 /*******************************************************************************
80  *
81  * FUNCTION:    acpi_ex_opcode_2A_0T_0R
82  *
83  * PARAMETERS:  walk_state          - Current walk state
84  *
85  * RETURN:      Status
86  *
87  * DESCRIPTION: Execute opcode with two arguments, no target, and no return
88  *              value.
89  *
90  * ALLOCATION:  Deletes both operands
91  *
92  ******************************************************************************/
93
94 acpi_status
95 acpi_ex_opcode_2A_0T_0R (
96         struct acpi_walk_state          *walk_state)
97 {
98         union acpi_operand_object       **operand = &walk_state->operands[0];
99         struct acpi_namespace_node      *node;
100         acpi_status                     status = AE_OK;
101
102
103         ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_0T_0R",
104                         acpi_ps_get_opcode_name (walk_state->opcode));
105
106
107         /* Examine the opcode */
108
109         switch (walk_state->opcode) {
110         case AML_NOTIFY_OP:         /* Notify (notify_object, notify_value) */
111
112                 /* The first operand is a namespace node */
113
114                 node = (struct acpi_namespace_node *) operand[0];
115
116                 /* Notifies allowed on this object? */
117
118                 if (!acpi_ev_is_notify_object (node)) {
119                         ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unexpected notify object type [%s]\n",
120                                         acpi_ut_get_type_name (node->type)));
121
122                         status = AE_AML_OPERAND_TYPE;
123                         break;
124                 }
125
126                 /*
127                  * Dispatch the notify to the appropriate handler
128                  * NOTE: the request is queued for execution after this method
129                  * completes.  The notify handlers are NOT invoked synchronously
130                  * from this thread -- because handlers may in turn run other
131                  * control methods.
132                  */
133                 status = acpi_ev_queue_notify_request (node,
134                                   (u32) operand[1]->integer.value);
135                 break;
136
137
138         default:
139
140                 ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_0T_0R: Unknown opcode %X\n",
141                                 walk_state->opcode));
142                 status = AE_AML_BAD_OPCODE;
143         }
144
145         return_ACPI_STATUS (status);
146 }
147
148
149 /*******************************************************************************
150  *
151  * FUNCTION:    acpi_ex_opcode_2A_2T_1R
152  *
153  * PARAMETERS:  walk_state          - Current walk state
154  *
155  * RETURN:      Status
156  *
157  * DESCRIPTION: Execute a dyadic operator (2 operands) with 2 output targets
158  *              and one implicit return value.
159  *
160  ******************************************************************************/
161
162 acpi_status
163 acpi_ex_opcode_2A_2T_1R (
164         struct acpi_walk_state          *walk_state)
165 {
166         union acpi_operand_object       **operand = &walk_state->operands[0];
167         union acpi_operand_object       *return_desc1 = NULL;
168         union acpi_operand_object       *return_desc2 = NULL;
169         acpi_status                     status;
170
171
172         ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_2T_1R", acpi_ps_get_opcode_name (walk_state->opcode));
173
174
175         /*
176          * Execute the opcode
177          */
178         switch (walk_state->opcode) {
179         case AML_DIVIDE_OP:             /* Divide (Dividend, Divisor, remainder_result quotient_result) */
180
181                 return_desc1 = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
182                 if (!return_desc1) {
183                         status = AE_NO_MEMORY;
184                         goto cleanup;
185                 }
186
187                 return_desc2 = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
188                 if (!return_desc2) {
189                         status = AE_NO_MEMORY;
190                         goto cleanup;
191                 }
192
193                 /* Quotient to return_desc1, remainder to return_desc2 */
194
195                 status = acpi_ut_divide (&operand[0]->integer.value, &operand[1]->integer.value,
196                                    &return_desc1->integer.value, &return_desc2->integer.value);
197                 if (ACPI_FAILURE (status)) {
198                         goto cleanup;
199                 }
200                 break;
201
202
203         default:
204
205                 ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_2T_1R: Unknown opcode %X\n",
206                                 walk_state->opcode));
207                 status = AE_AML_BAD_OPCODE;
208                 goto cleanup;
209         }
210
211
212         /* Store the results to the target reference operands */
213
214         status = acpi_ex_store (return_desc2, operand[2], walk_state);
215         if (ACPI_FAILURE (status)) {
216                 goto cleanup;
217         }
218
219         status = acpi_ex_store (return_desc1, operand[3], walk_state);
220         if (ACPI_FAILURE (status)) {
221                 goto cleanup;
222         }
223
224         /* Return the remainder */
225
226         walk_state->result_obj = return_desc1;
227
228
229 cleanup:
230         /*
231          * Since the remainder is not returned indirectly, remove a reference to
232          * it. Only the quotient is returned indirectly.
233          */
234         acpi_ut_remove_reference (return_desc2);
235
236         if (ACPI_FAILURE (status)) {
237                 /* Delete the return object */
238
239                 acpi_ut_remove_reference (return_desc1);
240         }
241
242         return_ACPI_STATUS (status);
243 }
244
245
246 /*******************************************************************************
247  *
248  * FUNCTION:    acpi_ex_opcode_2A_1T_1R
249  *
250  * PARAMETERS:  walk_state          - Current walk state
251  *
252  * RETURN:      Status
253  *
254  * DESCRIPTION: Execute opcode with two arguments, one target, and a return
255  *              value.
256  *
257  ******************************************************************************/
258
259 acpi_status
260 acpi_ex_opcode_2A_1T_1R (
261         struct acpi_walk_state          *walk_state)
262 {
263         union acpi_operand_object       **operand = &walk_state->operands[0];
264         union acpi_operand_object       *return_desc = NULL;
265         union acpi_operand_object       *temp_desc = NULL;
266         u32                             index;
267         acpi_status                     status = AE_OK;
268         acpi_size                       length;
269
270
271         ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_1T_1R", acpi_ps_get_opcode_name (walk_state->opcode));
272
273
274         /*
275          * Execute the opcode
276          */
277         if (walk_state->op_info->flags & AML_MATH) {
278                 /* All simple math opcodes (add, etc.) */
279
280                 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
281                 if (!return_desc) {
282                         status = AE_NO_MEMORY;
283                         goto cleanup;
284                 }
285
286                 return_desc->integer.value = acpi_ex_do_math_op (walk_state->opcode,
287                                   operand[0]->integer.value,
288                                   operand[1]->integer.value);
289                 goto store_result_to_target;
290         }
291
292
293         switch (walk_state->opcode) {
294         case AML_MOD_OP:                /* Mod (Dividend, Divisor, remainder_result (ACPI 2.0) */
295
296                 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
297                 if (!return_desc) {
298                         status = AE_NO_MEMORY;
299                         goto cleanup;
300                 }
301
302                 /* return_desc will contain the remainder */
303
304                 status = acpi_ut_divide (&operand[0]->integer.value, &operand[1]->integer.value,
305                                   NULL, &return_desc->integer.value);
306                 break;
307
308
309         case AML_CONCAT_OP:             /* Concatenate (Data1, Data2, Result) */
310
311                 /*
312                  * Convert the second operand if necessary.  The first operand
313                  * determines the type of the second operand, (See the Data Types
314                  * section of the ACPI specification.)  Both object types are
315                  * guaranteed to be either Integer/String/Buffer by the operand
316                  * resolution mechanism above.
317                  */
318                 switch (ACPI_GET_OBJECT_TYPE (operand[0])) {
319                 case ACPI_TYPE_INTEGER:
320                         status = acpi_ex_convert_to_integer (operand[1], &temp_desc, walk_state);
321                         break;
322
323                 case ACPI_TYPE_STRING:
324                         status = acpi_ex_convert_to_string (operand[1], &temp_desc, 16, ACPI_UINT32_MAX, walk_state);
325                         break;
326
327                 case ACPI_TYPE_BUFFER:
328                         status = acpi_ex_convert_to_buffer (operand[1], &temp_desc, walk_state);
329                         break;
330
331                 default:
332                         ACPI_REPORT_ERROR (("Concat - invalid obj type: %X\n",
333                                         ACPI_GET_OBJECT_TYPE (operand[0])));
334                         status = AE_AML_INTERNAL;
335                 }
336
337                 if (ACPI_FAILURE (status)) {
338                         goto cleanup;
339                 }
340
341                 /*
342                  * Both operands are now known to be the same object type
343                  * (Both are Integer, String, or Buffer), and we can now perform the
344                  * concatenation.
345                  */
346                 status = acpi_ex_do_concatenate (operand[0], temp_desc, &return_desc, walk_state);
347                 if (temp_desc != operand[1]) {
348                         acpi_ut_remove_reference (temp_desc);
349                 }
350                 break;
351
352
353         case AML_TO_STRING_OP:          /* to_string (Buffer, Length, Result) (ACPI 2.0) */
354
355                 /*
356                  * Input object is guaranteed to be a buffer at this point (it may have
357                  * been converted.)  Copy the raw buffer data to a new object of type String.
358                  */
359
360                 /* Get the length of the new string */
361
362                 length = 0;
363                 if (operand[1]->integer.value == 0) {
364                         /* Handle optional length value */
365
366                         operand[1]->integer.value = ACPI_INTEGER_MAX;
367                 }
368
369                 while ((length < operand[0]->buffer.length) &&
370                            (length < operand[1]->integer.value) &&
371                            (operand[0]->buffer.pointer[length])) {
372                         length++;
373                 }
374
375                 if (length > ACPI_MAX_STRING_CONVERSION) {
376                         status = AE_AML_STRING_LIMIT;
377                         goto cleanup;
378                 }
379
380                 /* Create the internal return object */
381
382                 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_STRING);
383                 if (!return_desc) {
384                         status = AE_NO_MEMORY;
385                         goto cleanup;
386                 }
387
388                 /* Allocate a new string buffer (Length + 1 for null terminator) */
389
390                 return_desc->string.pointer = ACPI_MEM_CALLOCATE (length + 1);
391                 if (!return_desc->string.pointer) {
392                         status = AE_NO_MEMORY;
393                         goto cleanup;
394                 }
395
396                 /* Copy the raw buffer data with no transform */
397
398                 ACPI_MEMCPY (return_desc->string.pointer, operand[0]->buffer.pointer, length);
399
400                 /* Set the string length */
401
402                 return_desc->string.length = (u32) length;
403                 break;
404
405
406         case AML_CONCAT_RES_OP:         /* concatenate_res_template (Buffer, Buffer, Result) (ACPI 2.0) */
407
408                 status = acpi_ex_concat_template (operand[0], operand[1], &return_desc, walk_state);
409                 break;
410
411
412         case AML_INDEX_OP:              /* Index (Source Index Result) */
413
414                 /* Create the internal return object */
415
416                 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_REFERENCE);
417                 if (!return_desc) {
418                         status = AE_NO_MEMORY;
419                         goto cleanup;
420                 }
421
422                 index = (u32) operand[1]->integer.value;
423
424                 /*
425                  * At this point, the Source operand is either a Package or a Buffer
426                  */
427                 if (ACPI_GET_OBJECT_TYPE (operand[0]) == ACPI_TYPE_PACKAGE) {
428                         /* Object to be indexed is a Package */
429
430                         if (index >= operand[0]->package.count) {
431                                 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Index value (%X) beyond package end (%X)\n",
432                                         index, operand[0]->package.count));
433                                 status = AE_AML_PACKAGE_LIMIT;
434                                 goto cleanup;
435                         }
436
437                         return_desc->reference.target_type = ACPI_TYPE_PACKAGE;
438                         return_desc->reference.object    = operand[0];
439                         return_desc->reference.where     = &operand[0]->package.elements [index];
440                 }
441                 else {
442                         /* Object to be indexed is a Buffer */
443
444                         if (index >= operand[0]->buffer.length) {
445                                 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Index value (%X) beyond end of buffer (%X)\n",
446                                         index, operand[0]->buffer.length));
447                                 status = AE_AML_BUFFER_LIMIT;
448                                 goto cleanup;
449                         }
450
451                         return_desc->reference.target_type = ACPI_TYPE_BUFFER_FIELD;
452                         return_desc->reference.object    = operand[0];
453                 }
454
455                 /* Complete the Index reference object */
456
457                 return_desc->reference.opcode    = AML_INDEX_OP;
458                 return_desc->reference.offset    = index;
459
460                 /* Store the reference to the Target */
461
462                 status = acpi_ex_store (return_desc, operand[2], walk_state);
463
464                 /* Return the reference */
465
466                 walk_state->result_obj = return_desc;
467                 goto cleanup;
468
469
470         default:
471
472                 ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_1T_1R: Unknown opcode %X\n",
473                                 walk_state->opcode));
474                 status = AE_AML_BAD_OPCODE;
475                 break;
476         }
477
478
479 store_result_to_target:
480
481         if (ACPI_SUCCESS (status)) {
482                 /*
483                  * Store the result of the operation (which is now in return_desc) into
484                  * the Target descriptor.
485                  */
486                 status = acpi_ex_store (return_desc, operand[2], walk_state);
487                 if (ACPI_FAILURE (status)) {
488                         goto cleanup;
489                 }
490
491                 if (!walk_state->result_obj) {
492                         walk_state->result_obj = return_desc;
493                 }
494         }
495
496
497 cleanup:
498
499         /* Delete return object on error */
500
501         if (ACPI_FAILURE (status)) {
502                 acpi_ut_remove_reference (return_desc);
503         }
504
505         return_ACPI_STATUS (status);
506 }
507
508
509 /*******************************************************************************
510  *
511  * FUNCTION:    acpi_ex_opcode_2A_0T_1R
512  *
513  * PARAMETERS:  walk_state          - Current walk state
514  *
515  * RETURN:      Status
516  *
517  * DESCRIPTION: Execute opcode with 2 arguments, no target, and a return value
518  *
519  ******************************************************************************/
520
521 acpi_status
522 acpi_ex_opcode_2A_0T_1R (
523         struct acpi_walk_state          *walk_state)
524 {
525         union acpi_operand_object       **operand = &walk_state->operands[0];
526         union acpi_operand_object       *return_desc = NULL;
527         acpi_status                     status = AE_OK;
528         u8                              logical_result = FALSE;
529
530
531         ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_0T_1R", acpi_ps_get_opcode_name (walk_state->opcode));
532
533
534         /* Create the internal return object */
535
536         return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
537         if (!return_desc) {
538                 status = AE_NO_MEMORY;
539                 goto cleanup;
540         }
541
542         /*
543          * Execute the Opcode
544          */
545         if (walk_state->op_info->flags & AML_LOGICAL) /* logical_op (Operand0, Operand1) */ {
546                 logical_result = acpi_ex_do_logical_op (walk_state->opcode,
547                                  operand[0]->integer.value,
548                                  operand[1]->integer.value);
549                 goto store_logical_result;
550         }
551
552
553         switch (walk_state->opcode) {
554         case AML_ACQUIRE_OP:            /* Acquire (mutex_object, Timeout) */
555
556                 status = acpi_ex_acquire_mutex (operand[1], operand[0], walk_state);
557                 if (status == AE_TIME) {
558                         logical_result = TRUE;      /* TRUE = Acquire timed out */
559                         status = AE_OK;
560                 }
561                 break;
562
563
564         case AML_WAIT_OP:               /* Wait (event_object, Timeout) */
565
566                 status = acpi_ex_system_wait_event (operand[1], operand[0]);
567                 if (status == AE_TIME) {
568                         logical_result = TRUE;      /* TRUE, Wait timed out */
569                         status = AE_OK;
570                 }
571                 break;
572
573
574         default:
575
576                 ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_0T_1R: Unknown opcode %X\n",
577                         walk_state->opcode));
578                 status = AE_AML_BAD_OPCODE;
579                 goto cleanup;
580         }
581
582
583 store_logical_result:
584         /*
585          * Set return value to according to logical_result. logical TRUE (all ones)
586          * Default is FALSE (zero)
587          */
588         if (logical_result) {
589                 return_desc->integer.value = ACPI_INTEGER_MAX;
590         }
591
592         walk_state->result_obj = return_desc;
593
594
595 cleanup:
596
597         /* Delete return object on error */
598
599         if (ACPI_FAILURE (status)) {
600                 acpi_ut_remove_reference (return_desc);
601         }
602
603         return_ACPI_STATUS (status);
604 }
605
606