vserver 1.9.5.x5
[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                 /* Complete the Index reference object */
446
447                 return_desc->reference.opcode    = AML_INDEX_OP;
448                 return_desc->reference.offset    = index;
449
450                 /* Store the reference to the Target */
451
452                 status = acpi_ex_store (return_desc, operand[2], walk_state);
453
454                 /* Return the reference */
455
456                 walk_state->result_obj = return_desc;
457                 goto cleanup;
458
459
460         default:
461
462                 ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_1T_1R: Unknown opcode %X\n",
463                                 walk_state->opcode));
464                 status = AE_AML_BAD_OPCODE;
465                 break;
466         }
467
468
469 store_result_to_target:
470
471         if (ACPI_SUCCESS (status)) {
472                 /*
473                  * Store the result of the operation (which is now in return_desc) into
474                  * the Target descriptor.
475                  */
476                 status = acpi_ex_store (return_desc, operand[2], walk_state);
477                 if (ACPI_FAILURE (status)) {
478                         goto cleanup;
479                 }
480
481                 if (!walk_state->result_obj) {
482                         walk_state->result_obj = return_desc;
483                 }
484         }
485
486
487 cleanup:
488
489         /* Delete return object on error */
490
491         if (ACPI_FAILURE (status)) {
492                 acpi_ut_remove_reference (return_desc);
493         }
494
495         return_ACPI_STATUS (status);
496 }
497
498
499 /*******************************************************************************
500  *
501  * FUNCTION:    acpi_ex_opcode_2A_0T_1R
502  *
503  * PARAMETERS:  walk_state          - Current walk state
504  *
505  * RETURN:      Status
506  *
507  * DESCRIPTION: Execute opcode with 2 arguments, no target, and a return value
508  *
509  ******************************************************************************/
510
511 acpi_status
512 acpi_ex_opcode_2A_0T_1R (
513         struct acpi_walk_state          *walk_state)
514 {
515         union acpi_operand_object       **operand = &walk_state->operands[0];
516         union acpi_operand_object       *return_desc = NULL;
517         acpi_status                     status = AE_OK;
518         u8                              logical_result = FALSE;
519
520
521         ACPI_FUNCTION_TRACE_STR ("ex_opcode_2A_0T_1R",
522                 acpi_ps_get_opcode_name (walk_state->opcode));
523
524
525         /* Create the internal return object */
526
527         return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
528         if (!return_desc) {
529                 status = AE_NO_MEMORY;
530                 goto cleanup;
531         }
532
533         /*
534          * Execute the Opcode
535          */
536         if (walk_state->op_info->flags & AML_LOGICAL_NUMERIC) /* logical_op (Operand0, Operand1) */ {
537                 status = acpi_ex_do_logical_numeric_op (walk_state->opcode,
538                                   operand[0]->integer.value, operand[1]->integer.value,
539                                   &logical_result);
540                 goto store_logical_result;
541         }
542         else if (walk_state->op_info->flags & AML_LOGICAL)  /* logical_op (Operand0, Operand1) */ {
543                 status = acpi_ex_do_logical_op (walk_state->opcode, operand[0],
544                                  operand[1], &logical_result);
545                 goto store_logical_result;
546         }
547
548
549         switch (walk_state->opcode) {
550         case AML_ACQUIRE_OP:            /* Acquire (mutex_object, Timeout) */
551
552                 status = acpi_ex_acquire_mutex (operand[1], operand[0], walk_state);
553                 if (status == AE_TIME) {
554                         logical_result = TRUE;      /* TRUE = Acquire timed out */
555                         status = AE_OK;
556                 }
557                 break;
558
559
560         case AML_WAIT_OP:               /* Wait (event_object, Timeout) */
561
562                 status = acpi_ex_system_wait_event (operand[1], operand[0]);
563                 if (status == AE_TIME) {
564                         logical_result = TRUE;      /* TRUE, Wait timed out */
565                         status = AE_OK;
566                 }
567                 break;
568
569
570         default:
571
572                 ACPI_REPORT_ERROR (("acpi_ex_opcode_2A_0T_1R: Unknown opcode %X\n",
573                         walk_state->opcode));
574                 status = AE_AML_BAD_OPCODE;
575                 goto cleanup;
576         }
577
578
579 store_logical_result:
580         /*
581          * Set return value to according to logical_result. logical TRUE (all ones)
582          * Default is FALSE (zero)
583          */
584         if (logical_result) {
585                 return_desc->integer.value = ACPI_INTEGER_MAX;
586         }
587
588         walk_state->result_obj = return_desc;
589
590
591 cleanup:
592
593         /* Delete return object on error */
594
595         if (ACPI_FAILURE (status)) {
596                 acpi_ut_remove_reference (return_desc);
597         }
598
599         return_ACPI_STATUS (status);
600 }
601
602