vserver 2.0 rc7
[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 - 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                 /* 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         /*
207          * Execute the opcode
208          */
209         switch (walk_state->opcode) {
210         case AML_DIVIDE_OP:             /* Divide (Dividend, Divisor, remainder_result quotient_result) */
211
212                 return_desc1 = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
213                 if (!return_desc1) {
214                         status = AE_NO_MEMORY;
215                         goto cleanup;
216                 }
217
218                 return_desc2 = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
219                 if (!return_desc2) {
220                         status = AE_NO_MEMORY;
221                         goto cleanup;
222                 }
223
224                 /* Quotient to return_desc1, remainder to return_desc2 */
225
226                 status = acpi_ut_divide (operand[0]->integer.value,
227                                    operand[1]->integer.value,
228                                    &return_desc1->integer.value,
229                                    &return_desc2->integer.value);
230                 if (ACPI_FAILURE (status)) {
231                         goto cleanup;
232                 }
233                 break;
234
235
236         default:
237
238                 ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_2T_1R: Unknown opcode %X\n",
239                                 walk_state->opcode));
240                 status = AE_AML_BAD_OPCODE;
241                 goto cleanup;
242         }
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         u32                             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         /*
308          * Execute the opcode
309          */
310         if (walk_state->op_info->flags & AML_MATH) {
311                 /* All simple math opcodes (add, etc.) */
312
313                 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
314                 if (!return_desc) {
315                         status = AE_NO_MEMORY;
316                         goto cleanup;
317                 }
318
319                 return_desc->integer.value = acpi_ex_do_math_op (walk_state->opcode,
320                                   operand[0]->integer.value,
321                                   operand[1]->integer.value);
322                 goto store_result_to_target;
323         }
324
325
326         switch (walk_state->opcode) {
327         case AML_MOD_OP:                /* Mod (Dividend, Divisor, remainder_result (ACPI 2.0) */
328
329                 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
330                 if (!return_desc) {
331                         status = AE_NO_MEMORY;
332                         goto cleanup;
333                 }
334
335                 /* return_desc will contain the remainder */
336
337                 status = acpi_ut_divide (operand[0]->integer.value,
338                                    operand[1]->integer.value,
339                                    NULL,
340                                    &return_desc->integer.value);
341                 break;
342
343
344         case AML_CONCAT_OP:             /* Concatenate (Data1, Data2, Result) */
345
346                 status = acpi_ex_do_concatenate (operand[0], operand[1],
347                                  &return_desc, walk_state);
348                 break;
349
350
351         case AML_TO_STRING_OP:          /* to_string (Buffer, Length, Result) (ACPI 2.0) */
352
353                 /*
354                  * Input object is guaranteed to be a buffer at this point (it may have
355                  * been converted.)  Copy the raw buffer data to a new object of type String.
356                  */
357
358                 /*
359                  * Get the length of the new string. It is the smallest of:
360                  * 1) Length of the input buffer
361                  * 2) Max length as specified in the to_string operator
362                  * 3) Length of input buffer up to a zero byte (null terminator)
363                  *
364                  * NOTE: A length of zero is ok, and will create a zero-length, null
365                  *       terminated string.
366                  */
367                 length = 0;
368                 while ((length < operand[0]->buffer.length) &&
369                            (length < operand[1]->integer.value) &&
370                            (operand[0]->buffer.pointer[length])) {
371                         length++;
372                         if (length > ACPI_MAX_STRING_CONVERSION) {
373                                 status = AE_AML_STRING_LIMIT;
374                                 goto cleanup;
375                         }
376                 }
377
378                 /* Allocate a new string object */
379
380                 return_desc = acpi_ut_create_string_object (length);
381                 if (!return_desc) {
382                         status = AE_NO_MEMORY;
383                         goto cleanup;
384                 }
385
386                 /* Copy the raw buffer data with no transform. NULL terminated already. */
387
388                 ACPI_MEMCPY (return_desc->string.pointer,
389                         operand[0]->buffer.pointer, length);
390                 break;
391
392
393         case AML_CONCAT_RES_OP:         /* concatenate_res_template (Buffer, Buffer, Result) (ACPI 2.0) */
394
395                 status = acpi_ex_concat_template (operand[0], operand[1],
396                                  &return_desc, walk_state);
397                 break;
398
399
400         case AML_INDEX_OP:              /* Index (Source Index Result) */
401
402                 /* Create the internal return object */
403
404                 return_desc = acpi_ut_create_internal_object (ACPI_TYPE_LOCAL_REFERENCE);
405                 if (!return_desc) {
406                         status = AE_NO_MEMORY;
407                         goto cleanup;
408                 }
409
410                 index = (u32) operand[1]->integer.value;
411
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) beyond package end (%X)\n",
421                                         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 [index];
429                 }
430                 else {
431                         /* Object to be indexed is a Buffer/String */
432
433                         if (index >= operand[0]->buffer.length) {
434                                 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
435                                         "Index value (%X) beyond end of buffer (%X)\n",
436                                         index, operand[0]->buffer.length));
437                                 status = AE_AML_BUFFER_LIMIT;
438                                 goto cleanup;
439                         }
440
441                         return_desc->reference.target_type = ACPI_TYPE_BUFFER_FIELD;
442                         return_desc->reference.object    = operand[0];
443                 }
444
445                 /*
446                  * Add a reference to the target package/buffer/string for the life
447                  * of the index.
448                  */
449                 acpi_ut_add_reference (operand[0]);
450
451                 /* Complete the Index reference object */
452
453                 return_desc->reference.opcode    = AML_INDEX_OP;
454                 return_desc->reference.offset    = index;
455
456                 /* Store the reference to the Target */
457
458                 status = acpi_ex_store (return_desc, operand[2], walk_state);
459
460                 /* Return the reference */
461
462                 walk_state->result_obj = return_desc;
463                 goto cleanup;
464
465
466         default:
467
468                 ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_1T_1R: Unknown opcode %X\n",
469                                 walk_state->opcode));
470                 status = AE_AML_BAD_OPCODE;
471                 break;
472         }
473
474
475 store_result_to_target:
476
477         if (ACPI_SUCCESS (status)) {
478                 /*
479                  * Store the result of the operation (which is now in return_desc) into
480                  * the Target descriptor.
481                  */
482                 status = acpi_ex_store (return_desc, operand[2], walk_state);
483                 if (ACPI_FAILURE (status)) {
484                         goto cleanup;
485                 }
486
487                 if (!walk_state->result_obj) {
488                         walk_state->result_obj = return_desc;
489                 }
490         }
491
492
493 cleanup:
494
495         /* Delete return object on error */
496
497         if (ACPI_FAILURE (status)) {
498                 acpi_ut_remove_reference (return_desc);
499         }
500
501         return_ACPI_STATUS (status);
502 }
503
504
505 /*******************************************************************************
506  *
507  * FUNCTION:    acpi_ex_opcode_2A_0T_1R
508  *
509  * PARAMETERS:  walk_state          - Current walk state
510  *
511  * RETURN:      Status
512  *
513  * DESCRIPTION: Execute opcode with 2 arguments, no target, and a return value
514  *
515  ******************************************************************************/
516
517 acpi_status
518 acpi_ex_opcode_2A_0T_1R (
519         struct acpi_walk_state          *walk_state)
520 {
521         union acpi_operand_object       **operand = &walk_state->operands[0];
522         union acpi_operand_object       *return_desc = NULL;
523         acpi_status                     status = AE_OK;
524         u8                              logical_result = FALSE;
525
526
527         ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_0T_1R",
528                 acpi_ps_get_opcode_name (walk_state->opcode));
529
530
531         /* Create the internal return object */
532
533         return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
534         if (!return_desc) {
535                 status = AE_NO_MEMORY;
536                 goto cleanup;
537         }
538
539         /*
540          * Execute the Opcode
541          */
542         if (walk_state->op_info->flags & AML_LOGICAL_NUMERIC) /* logical_op (Operand0, Operand1) */ {
543                 status = acpi_ex_do_logical_numeric_op (walk_state->opcode,
544                                   operand[0]->integer.value, operand[1]->integer.value,
545                                   &logical_result);
546                 goto store_logical_result;
547         }
548         else if (walk_state->op_info->flags & AML_LOGICAL)  /* logical_op (Operand0, Operand1) */ {
549                 status = acpi_ex_do_logical_op (walk_state->opcode, operand[0],
550                                  operand[1], &logical_result);
551                 goto store_logical_result;
552         }
553
554
555         switch (walk_state->opcode) {
556         case AML_ACQUIRE_OP:            /* Acquire (mutex_object, Timeout) */
557
558                 status = acpi_ex_acquire_mutex (operand[1], operand[0], walk_state);
559                 if (status == AE_TIME) {
560                         logical_result = TRUE;      /* TRUE = Acquire timed out */
561                         status = AE_OK;
562                 }
563                 break;
564
565
566         case AML_WAIT_OP:               /* Wait (event_object, Timeout) */
567
568                 status = acpi_ex_system_wait_event (operand[1], operand[0]);
569                 if (status == AE_TIME) {
570                         logical_result = TRUE;      /* TRUE, Wait timed out */
571                         status = AE_OK;
572                 }
573                 break;
574
575
576         default:
577
578                 ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_0T_1R: Unknown opcode %X\n",
579                         walk_state->opcode));
580                 status = AE_AML_BAD_OPCODE;
581                 goto cleanup;
582         }
583
584
585 store_logical_result:
586         /*
587          * Set return value to according to logical_result. logical TRUE (all ones)
588          * Default is FALSE (zero)
589          */
590         if (logical_result) {
591                 return_desc->integer.value = ACPI_INTEGER_MAX;
592         }
593
594         walk_state->result_obj = return_desc;
595
596
597 cleanup:
598
599         /* Delete return object on error */
600
601         if (ACPI_FAILURE (status)) {
602                 acpi_ut_remove_reference (return_desc);
603         }
604
605         return_ACPI_STATUS (status);
606 }
607
608