Merge /spare/repo/linux-2.6/
[linux-2.6] / 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 - 2005, 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         u32                             value;
101         acpi_status                     status = AE_OK;
102
103
104         ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_0T_0R",
105                         acpi_ps_get_opcode_name (walk_state->opcode));
106
107
108         /* Examine the opcode */
109
110         switch (walk_state->opcode) {
111         case AML_NOTIFY_OP:         /* Notify (notify_object, notify_value) */
112
113                 /* The first operand is a namespace node */
114
115                 node = (struct acpi_namespace_node *) operand[0];
116
117                 /* Second value is the notify value */
118
119                 value = (u32) operand[1]->integer.value;
120
121                 /* Are notifies allowed on this object? */
122
123                 if (!acpi_ev_is_notify_object (node)) {
124                         ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
125                                         "Unexpected notify object type [%s]\n",
126                                         acpi_ut_get_type_name (node->type)));
127
128                         status = AE_AML_OPERAND_TYPE;
129                         break;
130                 }
131
132 #ifdef ACPI_GPE_NOTIFY_CHECK
133                 /*
134                  * GPE method wake/notify check.  Here, we want to ensure that we
135                  * don't receive any "device_wake" Notifies from a GPE _Lxx or _Exx
136                  * GPE method during system runtime.  If we do, the GPE is marked
137                  * as "wake-only" and disabled.
138                  *
139                  * 1) Is the Notify() value == device_wake?
140                  * 2) Is this a GPE deferred method?  (An _Lxx or _Exx method)
141                  * 3) Did the original GPE happen at system runtime?
142                  *    (versus during wake)
143                  *
144                  * If all three cases are true, this is a wake-only GPE that should
145                  * be disabled at runtime.
146                  */
147                 if (value == 2)     /* device_wake */ {
148                         status = acpi_ev_check_for_wake_only_gpe (walk_state->gpe_event_info);
149                         if (ACPI_FAILURE (status)) {
150                                 /* AE_WAKE_ONLY_GPE only error, means ignore this notify */
151
152                                 return_ACPI_STATUS (AE_OK)
153                         }
154                 }
155 #endif
156
157                 /*
158                  * Dispatch the notify to the appropriate handler
159                  * NOTE: the request is queued for execution after this method
160                  * completes.  The notify handlers are NOT invoked synchronously
161                  * from this thread -- because handlers may in turn run other
162                  * control methods.
163                  */
164                 status = acpi_ev_queue_notify_request (node, value);
165                 break;
166
167
168         default:
169
170                 ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_0T_0R: Unknown opcode %X\n",
171                                 walk_state->opcode));
172                 status = AE_AML_BAD_OPCODE;
173         }
174
175         return_ACPI_STATUS (status);
176 }
177
178
179 /*******************************************************************************
180  *
181  * FUNCTION:    acpi_ex_opcode_2A_2T_1R
182  *
183  * PARAMETERS:  walk_state          - Current walk state
184  *
185  * RETURN:      Status
186  *
187  * DESCRIPTION: Execute a dyadic operator (2 operands) with 2 output targets
188  *              and one implicit return value.
189  *
190  ******************************************************************************/
191
192 acpi_status
193 acpi_ex_opcode_2A_2T_1R (
194         struct acpi_walk_state          *walk_state)
195 {
196         union acpi_operand_object       **operand = &walk_state->operands[0];
197         union acpi_operand_object       *return_desc1 = NULL;
198         union acpi_operand_object       *return_desc2 = NULL;
199         acpi_status                     status;
200
201
202         ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_2T_1R",
203                 acpi_ps_get_opcode_name (walk_state->opcode));
204
205
206         /* Execute the opcode */
207
208         switch (walk_state->opcode) {
209         case AML_DIVIDE_OP:
210
211                 /* Divide (Dividend, Divisor, remainder_result quotient_result) */
212
213                 return_desc1 = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
214                 if (!return_desc1) {
215                         status = AE_NO_MEMORY;
216                         goto cleanup;
217                 }
218
219                 return_desc2 = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
220                 if (!return_desc2) {
221                         status = AE_NO_MEMORY;
222                         goto cleanup;
223                 }
224
225                 /* Quotient to return_desc1, remainder to return_desc2 */
226
227                 status = acpi_ut_divide (operand[0]->integer.value,
228                                    operand[1]->integer.value,
229                                    &return_desc1->integer.value,
230                                    &return_desc2->integer.value);
231                 if (ACPI_FAILURE (status)) {
232                         goto cleanup;
233                 }
234                 break;
235
236
237         default:
238
239                 ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_2T_1R: Unknown opcode %X\n",
240                                 walk_state->opcode));
241                 status = AE_AML_BAD_OPCODE;
242                 goto cleanup;
243         }
244
245         /* Store the results to the target reference operands */
246
247         status = acpi_ex_store (return_desc2, operand[2], walk_state);
248         if (ACPI_FAILURE (status)) {
249                 goto cleanup;
250         }
251
252         status = acpi_ex_store (return_desc1, operand[3], walk_state);
253         if (ACPI_FAILURE (status)) {
254                 goto cleanup;
255         }
256
257         /* Return the remainder */
258
259         walk_state->result_obj = return_desc1;
260
261
262 cleanup:
263         /*
264          * Since the remainder is not returned indirectly, remove a reference to
265          * it. Only the quotient is returned indirectly.
266          */
267         acpi_ut_remove_reference (return_desc2);
268
269         if (ACPI_FAILURE (status)) {
270                 /* Delete the return object */
271
272                 acpi_ut_remove_reference (return_desc1);
273         }
274
275         return_ACPI_STATUS (status);
276 }
277
278
279 /*******************************************************************************
280  *
281  * FUNCTION:    acpi_ex_opcode_2A_1T_1R
282  *
283  * PARAMETERS:  walk_state          - Current walk state
284  *
285  * RETURN:      Status
286  *
287  * DESCRIPTION: Execute opcode with two arguments, one target, and a return
288  *              value.
289  *
290  ******************************************************************************/
291
292 acpi_status
293 acpi_ex_opcode_2A_1T_1R (
294         struct acpi_walk_state          *walk_state)
295 {
296         union acpi_operand_object       **operand = &walk_state->operands[0];
297         union acpi_operand_object       *return_desc = NULL;
298         acpi_integer                    index;
299         acpi_status                     status = AE_OK;
300         acpi_size                       length;
301
302
303         ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_1T_1R",
304                 acpi_ps_get_opcode_name (walk_state->opcode));
305
306
307         /* Execute the opcode */
308
309         if (walk_state->op_info->flags & AML_MATH) {
310                 /* All simple math opcodes (add, etc.) */
311
312                 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
313                 if (!return_desc) {
314                         status = AE_NO_MEMORY;
315                         goto cleanup;
316                 }
317
318                 return_desc->integer.value = acpi_ex_do_math_op (walk_state->opcode,
319                                   operand[0]->integer.value,
320                                   operand[1]->integer.value);
321                 goto store_result_to_target;
322         }
323
324         switch (walk_state->opcode) {
325         case AML_MOD_OP: /* Mod (Dividend, Divisor, remainder_result (ACPI 2.0) */
326
327                 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
328                 if (!return_desc) {
329                         status = AE_NO_MEMORY;
330                         goto cleanup;
331                 }
332
333                 /* return_desc will contain the remainder */
334
335                 status = acpi_ut_divide (operand[0]->integer.value,
336                                    operand[1]->integer.value,
337                                    NULL,
338                                    &return_desc->integer.value);
339                 break;
340
341
342         case AML_CONCAT_OP: /* Concatenate (Data1, Data2, Result) */
343
344                 status = acpi_ex_do_concatenate (operand[0], operand[1],
345                                  &return_desc, walk_state);
346                 break;
347
348
349         case AML_TO_STRING_OP: /* to_string (Buffer, Length, Result) (ACPI 2.0) */
350
351                 /*
352                  * Input object is guaranteed to be a buffer at this point (it may have
353                  * been converted.)  Copy the raw buffer data to a new object of
354                  * type String.
355                  */
356
357                 /*
358                  * Get the length of the new string. It is the smallest of:
359                  * 1) Length of the input buffer
360                  * 2) Max length as specified in the to_string operator
361                  * 3) Length of input buffer up to a zero byte (null terminator)
362                  *
363                  * NOTE: A length of zero is ok, and will create a zero-length, null
364                  *       terminated string.
365                  */
366                 length = 0;
367                 while ((length < operand[0]->buffer.length) &&
368                            (length < operand[1]->integer.value) &&
369                            (operand[0]->buffer.pointer[length])) {
370                         length++;
371                         if (length > ACPI_MAX_STRING_CONVERSION) {
372                                 status = AE_AML_STRING_LIMIT;
373                                 goto cleanup;
374                         }
375                 }
376
377                 /* Allocate a new string object */
378
379                 return_desc = acpi_ut_create_string_object (length);
380                 if (!return_desc) {
381                         status = AE_NO_MEMORY;
382                         goto cleanup;
383                 }
384
385                 /* Copy the raw buffer data with no transform. NULL terminated already*/
386
387                 ACPI_MEMCPY (return_desc->string.pointer,
388                         operand[0]->buffer.pointer, length);
389                 break;
390
391
392         case AML_CONCAT_RES_OP:
393
394                 /* concatenate_res_template (Buffer, Buffer, Result) (ACPI 2.0) */
395
396                 status = acpi_ex_concat_template (operand[0], operand[1],
397                                  &return_desc, walk_state);
398                 break;
399
400
401         case AML_INDEX_OP:              /* Index (Source Index Result) */
402
403                 /* Create the internal return object */
404
405                 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_REFERENCE);
406                 if (!return_desc) {
407                         status = AE_NO_MEMORY;
408                         goto cleanup;
409                 }
410
411                 index = operand[1]->integer.value;
412
413                 /* At this point, the Source operand is a Package, Buffer, or String */
414
415                 if (ACPI_GET_OBJECT_TYPE (operand[0]) == ACPI_TYPE_PACKAGE) {
416                         /* Object to be indexed is a Package */
417
418                         if (index >= operand[0]->package.count) {
419                                 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
420                                         "Index value (%X%8.8X) beyond package end (%X)\n",
421                                         ACPI_FORMAT_UINT64 (index), operand[0]->package.count));
422                                 status = AE_AML_PACKAGE_LIMIT;
423                                 goto cleanup;
424                         }
425
426                         return_desc->reference.target_type = ACPI_TYPE_PACKAGE;
427                         return_desc->reference.object    = operand[0];
428                         return_desc->reference.where     = &operand[0]->package.elements [
429                                           index];
430                 }
431                 else {
432                         /* Object to be indexed is a Buffer/String */
433
434                         if (index >= operand[0]->buffer.length) {
435                                 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
436                                         "Index value (%X%8.8X) beyond end of buffer (%X)\n",
437                                         ACPI_FORMAT_UINT64 (index), operand[0]->buffer.length));
438                                 status = AE_AML_BUFFER_LIMIT;
439                                 goto cleanup;
440                         }
441
442                         return_desc->reference.target_type = ACPI_TYPE_BUFFER_FIELD;
443                         return_desc->reference.object    = operand[0];
444                 }
445
446                 /*
447                  * Add a reference to the target package/buffer/string for the life
448                  * of the index.
449                  */
450                 acpi_ut_add_reference (operand[0]);
451
452                 /* Complete the Index reference object */
453
454                 return_desc->reference.opcode    = AML_INDEX_OP;
455                 return_desc->reference.offset    = (u32) index;
456
457                 /* Store the reference to the Target */
458
459                 status = acpi_ex_store (return_desc, operand[2], walk_state);
460
461                 /* Return the reference */
462
463                 walk_state->result_obj = return_desc;
464                 goto cleanup;
465
466
467         default:
468
469                 ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_1T_1R: Unknown opcode %X\n",
470                                 walk_state->opcode));
471                 status = AE_AML_BAD_OPCODE;
472                 break;
473         }
474
475
476 store_result_to_target:
477
478         if (ACPI_SUCCESS (status)) {
479                 /*
480                  * Store the result of the operation (which is now in return_desc) into
481                  * the Target descriptor.
482                  */
483                 status = acpi_ex_store (return_desc, operand[2], walk_state);
484                 if (ACPI_FAILURE (status)) {
485                         goto cleanup;
486                 }
487
488                 if (!walk_state->result_obj) {
489                         walk_state->result_obj = return_desc;
490                 }
491         }
492
493
494 cleanup:
495
496         /* Delete return object on error */
497
498         if (ACPI_FAILURE (status)) {
499                 acpi_ut_remove_reference (return_desc);
500         }
501
502         return_ACPI_STATUS (status);
503 }
504
505
506 /*******************************************************************************
507  *
508  * FUNCTION:    acpi_ex_opcode_2A_0T_1R
509  *
510  * PARAMETERS:  walk_state          - Current walk state
511  *
512  * RETURN:      Status
513  *
514  * DESCRIPTION: Execute opcode with 2 arguments, no target, and a return value
515  *
516  ******************************************************************************/
517
518 acpi_status
519 acpi_ex_opcode_2A_0T_1R (
520         struct acpi_walk_state          *walk_state)
521 {
522         union acpi_operand_object       **operand = &walk_state->operands[0];
523         union acpi_operand_object       *return_desc = NULL;
524         acpi_status                     status = AE_OK;
525         u8                              logical_result = FALSE;
526
527
528         ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_0T_1R",
529                 acpi_ps_get_opcode_name (walk_state->opcode));
530
531
532         /* Create the internal return object */
533
534         return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
535         if (!return_desc) {
536                 status = AE_NO_MEMORY;
537                 goto cleanup;
538         }
539
540         /* Execute the Opcode */
541
542         if (walk_state->op_info->flags & AML_LOGICAL_NUMERIC) {
543                 /* logical_op (Operand0, Operand1) */
544
545                 status = acpi_ex_do_logical_numeric_op (walk_state->opcode,
546                                   operand[0]->integer.value, operand[1]->integer.value,
547                                   &logical_result);
548                 goto store_logical_result;
549         }
550         else if (walk_state->op_info->flags & AML_LOGICAL) {
551                 /* logical_op (Operand0, Operand1) */
552
553                 status = acpi_ex_do_logical_op (walk_state->opcode, operand[0],
554                                  operand[1], &logical_result);
555                 goto store_logical_result;
556         }
557
558         switch (walk_state->opcode) {
559         case AML_ACQUIRE_OP:            /* Acquire (mutex_object, Timeout) */
560
561                 status = acpi_ex_acquire_mutex (operand[1], operand[0], walk_state);
562                 if (status == AE_TIME) {
563                         logical_result = TRUE;      /* TRUE = Acquire timed out */
564                         status = AE_OK;
565                 }
566                 break;
567
568
569         case AML_WAIT_OP:               /* Wait (event_object, Timeout) */
570
571                 status = acpi_ex_system_wait_event (operand[1], operand[0]);
572                 if (status == AE_TIME) {
573                         logical_result = TRUE;      /* TRUE, Wait timed out */
574                         status = AE_OK;
575                 }
576                 break;
577
578
579         default:
580
581                 ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_0T_1R: Unknown opcode %X\n",
582                         walk_state->opcode));
583                 status = AE_AML_BAD_OPCODE;
584                 goto cleanup;
585         }
586
587
588 store_logical_result:
589         /*
590          * Set return value to according to logical_result. logical TRUE (all ones)
591          * Default is FALSE (zero)
592          */
593         if (logical_result) {
594                 return_desc->integer.value = ACPI_INTEGER_MAX;
595         }
596
597         walk_state->result_obj = return_desc;
598
599
600 cleanup:
601
602         /* Delete return object on error */
603
604         if (ACPI_FAILURE (status)) {
605                 acpi_ut_remove_reference (return_desc);
606         }
607
608         return_ACPI_STATUS (status);
609 }
610
611