:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / drivers / bus / acpi / executer / ammonad.c
1
2 /******************************************************************************
3  *
4  * Module Name: ammonad - ACPI AML (p-code) execution for monadic operators
5  *              $Revision$
6  *
7  *****************************************************************************/
8
9 /*
10  *  Copyright (C) 2000, 2001 R. Byron Moore
11  *
12  *  This program is free software; you can redistribute it and/or modify
13  *  it under the terms of the GNU General Public License as published by
14  *  the Free Software Foundation; either version 2 of the License, or
15  *  (at your option) any later version.
16  *
17  *  This program is distributed in the hope that it will be useful,
18  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  *  GNU General Public License for more details.
21  *
22  *  You should have received a copy of the GNU General Public License
23  *  along with this program; if not, write to the Free Software
24  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25  */
26
27
28 #include "acpi.h"
29 #include "acparser.h"
30 #include "acdispat.h"
31 #include "acinterp.h"
32 #include "amlcode.h"
33 #include "acnamesp.h"
34
35
36 #define _COMPONENT          ACPI_EXECUTER
37          MODULE_NAME         ("ammonad")
38
39
40 /*******************************************************************************
41  *
42  * FUNCTION:    Acpi_aml_get_object_reference
43  *
44  * PARAMETERS:  Obj_desc        - Create a reference to this object
45  *              Ret_desc        - Where to store the reference
46  *
47  * RETURN:      Status
48  *
49  * DESCRIPTION: Obtain and return a "reference" to the target object
50  *              Common code for the Ref_of_op and the Cond_ref_of_op.
51  *
52  ******************************************************************************/
53
54 static ACPI_STATUS
55 acpi_aml_get_object_reference (
56         ACPI_OPERAND_OBJECT     *obj_desc,
57         ACPI_OPERAND_OBJECT     **ret_desc,
58         ACPI_WALK_STATE         *walk_state)
59 {
60         ACPI_STATUS             status = AE_OK;
61
62
63         if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_INTERNAL)) {
64                 if (obj_desc->common.type != INTERNAL_TYPE_REFERENCE) {
65                         *ret_desc = NULL;
66                         status = AE_TYPE;
67                         goto cleanup;
68                 }
69
70                 /*
71                  * Not a Name -- an indirect name pointer would have
72                  * been converted to a direct name pointer in Acpi_aml_resolve_operands
73                  */
74                 switch (obj_desc->reference.opcode) {
75                 case AML_LOCAL_OP:
76                 case AML_ARG_OP:
77
78                         *ret_desc = (void *) acpi_ds_method_data_get_node (obj_desc->reference.opcode,
79                                           obj_desc->reference.offset, walk_state);
80                         break;
81
82                 default:
83
84                         *ret_desc = NULL;
85                         status = AE_AML_INTERNAL;
86                         goto cleanup;
87                 }
88
89         }
90
91         else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) {
92                 /* Must be a named object;  Just return the Node */
93
94                 *ret_desc = obj_desc;
95         }
96
97         else {
98                 *ret_desc = NULL;
99                 status = AE_TYPE;
100         }
101
102
103 cleanup:
104
105         return (status);
106 }
107
108
109 /*******************************************************************************
110  *
111  * FUNCTION:    Acpi_aml_exec_monadic1
112  *
113  * PARAMETERS:  Opcode              - The opcode to be executed
114  *
115  * RETURN:      Status
116  *
117  * DESCRIPTION: Execute Type 1 monadic operator with numeric operand on
118  *              object stack
119  *
120  ******************************************************************************/
121
122 ACPI_STATUS
123 acpi_aml_exec_monadic1 (
124         u16                     opcode,
125         ACPI_WALK_STATE         *walk_state)
126 {
127         ACPI_OPERAND_OBJECT     *obj_desc;
128         ACPI_STATUS             status;
129
130
131         /* Resolve all operands */
132
133         status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS, walk_state);
134         /* Get all operands */
135
136         status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state);
137         if (ACPI_FAILURE (status)) {
138                 goto cleanup;
139         }
140
141
142         /* Examine the opcode */
143
144         switch (opcode) {
145
146         /*  Def_release :=  Release_op  Mutex_object */
147
148         case AML_RELEASE_OP:
149
150                 status = acpi_aml_release_mutex (obj_desc, walk_state);
151                 break;
152
153
154         /*  Def_reset   :=  Reset_op    Acpi_event_object */
155
156         case AML_RESET_OP:
157
158                 status = acpi_aml_system_reset_event (obj_desc);
159                 break;
160
161
162         /*  Def_signal  :=  Signal_op   Acpi_event_object */
163
164         case AML_SIGNAL_OP:
165
166                 status = acpi_aml_system_signal_event (obj_desc);
167                 break;
168
169
170         /*  Def_sleep   :=  Sleep_op    Msec_time   */
171
172         case AML_SLEEP_OP:
173
174                 acpi_aml_system_do_suspend ((u32) obj_desc->integer.value);
175                 break;
176
177
178         /*  Def_stall   :=  Stall_op    Usec_time   */
179
180         case AML_STALL_OP:
181
182                 acpi_aml_system_do_stall ((u32) obj_desc->integer.value);
183                 break;
184
185
186         /*  Unknown opcode  */
187
188         default:
189
190                 REPORT_ERROR (("Acpi_aml_exec_monadic1: Unknown monadic opcode %X\n",
191                         opcode));
192                 status = AE_AML_BAD_OPCODE;
193                 break;
194
195         } /* switch */
196
197
198 cleanup:
199
200         /* Always delete the operand */
201
202         acpi_cm_remove_reference (obj_desc);
203
204         return (AE_OK);
205 }
206
207
208 /*******************************************************************************
209  *
210  * FUNCTION:    Acpi_aml_exec_monadic2_r
211  *
212  * PARAMETERS:  Opcode              - The opcode to be executed
213  *
214  * RETURN:      Status
215  *
216  * DESCRIPTION: Execute Type 2 monadic operator with numeric operand and
217  *              result operand on operand stack
218  *
219  ******************************************************************************/
220
221 ACPI_STATUS
222 acpi_aml_exec_monadic2_r (
223         u16                     opcode,
224         ACPI_WALK_STATE         *walk_state,
225         ACPI_OPERAND_OBJECT     **return_desc)
226 {
227         ACPI_OPERAND_OBJECT     *obj_desc;
228         ACPI_OPERAND_OBJECT     *res_desc;
229         ACPI_OPERAND_OBJECT     *ret_desc = NULL;
230         ACPI_OPERAND_OBJECT     *ret_desc2 = NULL;
231         u32                     res_val;
232         ACPI_STATUS             status;
233         u32                     i;
234         u32                     j;
235         ACPI_INTEGER            digit;
236
237
238         /* Resolve all operands */
239
240         status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS, walk_state);
241         /* Get all operands */
242
243         status |= acpi_ds_obj_stack_pop_object (&res_desc, walk_state);
244         status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state);
245         if (ACPI_FAILURE (status)) {
246                 goto cleanup;
247         }
248
249
250         /* Create a return object of type NUMBER for most opcodes */
251
252         switch (opcode) {
253         case AML_BIT_NOT_OP:
254         case AML_FIND_SET_LEFT_BIT_OP:
255         case AML_FIND_SET_RIGHT_BIT_OP:
256         case AML_FROM_BCD_OP:
257         case AML_TO_BCD_OP:
258         case AML_COND_REF_OF_OP:
259
260                 ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
261                 if (!ret_desc) {
262                         status = AE_NO_MEMORY;
263                         goto cleanup;
264                 }
265
266                 break;
267         }
268
269
270         switch (opcode) {
271         /*  Def_not :=  Not_op  Operand Result  */
272
273         case AML_BIT_NOT_OP:
274
275                 ret_desc->integer.value = ~obj_desc->integer.value;
276                 break;
277
278
279         /*  Def_find_set_left_bit := Find_set_left_bit_op Operand Result */
280
281         case AML_FIND_SET_LEFT_BIT_OP:
282
283                 ret_desc->integer.value = obj_desc->integer.value;
284
285                 /*
286                  * Acpi specification describes Integer type as a little
287                  * endian unsigned value, so this boundry condition is valid.
288                  */
289                 for (res_val = 0; ret_desc->integer.value && res_val < ACPI_INTEGER_BIT_SIZE; ++res_val) {
290                         ret_desc->integer.value >>= 1;
291                 }
292
293                 ret_desc->integer.value = res_val;
294                 break;
295
296
297         /*  Def_find_set_right_bit := Find_set_right_bit_op Operand Result */
298
299         case AML_FIND_SET_RIGHT_BIT_OP:
300
301                 ret_desc->integer.value = obj_desc->integer.value;
302
303                 /*
304                  * Acpi specification describes Integer type as a little
305                  * endian unsigned value, so this boundry condition is valid.
306                  */
307                 for (res_val = 0; ret_desc->integer.value && res_val < ACPI_INTEGER_BIT_SIZE; ++res_val) {
308                         ret_desc->integer.value <<= 1;
309                 }
310
311                 /* Since returns must be 1-based, subtract from 33 (65) */
312
313                 ret_desc->integer.value = res_val == 0 ? 0 : (ACPI_INTEGER_BIT_SIZE + 1) - res_val;
314                 break;
315
316
317         /*  Def_from_bDC := From_bCDOp  BCDValue    Result  */
318
319         case AML_FROM_BCD_OP:
320
321                 /*
322                  * The 64-bit ACPI integer can hold 16 4-bit BCD integers
323                  */
324                 ret_desc->integer.value = 0;
325                 for (i = 0; i < ACPI_MAX_BCD_DIGITS; i++) {
326                         /* Get one BCD digit */
327
328                         digit = (ACPI_INTEGER) ((obj_desc->integer.value >> (i * 4)) & 0xF);
329
330                         /* Check the range of the digit */
331
332                         if (digit > 9) {
333                                 status = AE_AML_NUMERIC_OVERFLOW;
334                                 goto cleanup;
335                         }
336
337                         if (digit > 0) {
338                                 /* Sum into the result with the appropriate power of 10 */
339
340                                 for (j = 0; j < i; j++) {
341                                         digit *= 10;
342                                 }
343
344                                 ret_desc->integer.value += digit;
345                         }
346                 }
347                 break;
348
349
350         /*  Def_to_bDC  :=  To_bCDOp Operand Result */
351
352         case AML_TO_BCD_OP:
353
354
355                 if (obj_desc->integer.value > ACPI_MAX_BCD_VALUE) {
356                         status = AE_AML_NUMERIC_OVERFLOW;
357                         goto cleanup;
358                 }
359
360                 ret_desc->integer.value = 0;
361                 for (i = 0; i < ACPI_MAX_BCD_DIGITS; i++) {
362                         /* Divide by nth factor of 10 */
363
364                         digit = obj_desc->integer.value;
365                         for (j = 0; j < i; j++) {
366                                 digit /= 10;
367                         }
368
369                         /* Create the BCD digit */
370
371                         if (digit > 0) {
372                                 ret_desc->integer.value += (ACPI_MODULO (digit, 10) << (i * 4));
373                         }
374                 }
375                 break;
376
377
378         /*  Def_cond_ref_of     :=  Cond_ref_of_op  Source_object   Result  */
379
380         case AML_COND_REF_OF_OP:
381
382                 /*
383                  * This op is a little strange because the internal return value is
384                  * different than the return value stored in the result descriptor
385                  * (There are really two return values)
386                  */
387
388                 if ((ACPI_NAMESPACE_NODE *) obj_desc == acpi_gbl_root_node) {
389                         /*
390                          * This means that the object does not exist in the namespace,
391                          * return FALSE
392                          */
393
394                         ret_desc->integer.value = 0;
395
396                         /*
397                          * Must delete the result descriptor since there is no reference
398                          * being returned
399                          */
400
401                         acpi_cm_remove_reference (res_desc);
402                         goto cleanup;
403                 }
404
405                 /* Get the object reference and store it */
406
407                 status = acpi_aml_get_object_reference (obj_desc, &ret_desc2, walk_state);
408                 if (ACPI_FAILURE (status)) {
409                         goto cleanup;
410                 }
411
412                 status = acpi_aml_exec_store (ret_desc2, res_desc, walk_state);
413
414                 /* The object exists in the namespace, return TRUE */
415
416                 ret_desc->integer.value = ACPI_INTEGER_MAX;
417                 goto cleanup;
418                 break;
419
420
421         case AML_STORE_OP:
422
423                 /*
424                  * A store operand is typically a number, string, buffer or lvalue
425                  * TBD: [Unhandled] What about a store to a package?
426                  */
427
428                 /*
429                  * Do the store, and be careful about deleting the source object,
430                  * since the object itself may have been stored.
431                  */
432
433                 status = acpi_aml_exec_store (obj_desc, res_desc, walk_state);
434                 if (ACPI_FAILURE (status)) {
435                         /* On failure, just delete the Obj_desc */
436
437                         acpi_cm_remove_reference (obj_desc);
438                 }
439
440                 else {
441                         /*
442                          * Normally, we would remove a reference on the Obj_desc parameter;
443                          * But since it is being used as the internal return object
444                          * (meaning we would normally increment it), the two cancel out,
445                          * and we simply don't do anything.
446                          */
447                         *return_desc = obj_desc;
448                 }
449
450                 obj_desc = NULL;
451                 return (status);
452
453                 break;
454
455
456         case AML_DEBUG_OP:
457
458                 /* Reference, returning an Reference */
459
460                 return (AE_OK);
461                 break;
462
463
464         /*
465          * These are obsolete opcodes
466          */
467
468         /*  Def_shift_left_bit  :=  Shift_left_bit_op   Source          Bit_num */
469         /*  Def_shift_right_bit :=  Shift_right_bit_op  Source          Bit_num */
470
471         case AML_SHIFT_LEFT_BIT_OP:
472         case AML_SHIFT_RIGHT_BIT_OP:
473
474                 status = AE_SUPPORT;
475                 goto cleanup;
476                 break;
477
478
479         default:
480
481                 REPORT_ERROR (("Acpi_aml_exec_monadic2_r: Unknown monadic opcode %X\n",
482                         opcode));
483                 status = AE_AML_BAD_OPCODE;
484                 goto cleanup;
485         }
486
487
488         status = acpi_aml_exec_store (ret_desc, res_desc, walk_state);
489
490
491 cleanup:
492         /* Always delete the operand object */
493
494         acpi_cm_remove_reference (obj_desc);
495
496         /* Delete return object(s) on error */
497
498         if (ACPI_FAILURE (status)) {
499                 acpi_cm_remove_reference (res_desc); /* Result descriptor */
500                 if (ret_desc) {
501                         acpi_cm_remove_reference (ret_desc);
502                         ret_desc = NULL;
503                 }
504         }
505
506         /* Set the return object and exit */
507
508         *return_desc = ret_desc;
509         return (status);
510 }
511
512
513 /*******************************************************************************
514  *
515  * FUNCTION:    Acpi_aml_exec_monadic2
516  *
517  * PARAMETERS:  Opcode              - The opcode to be executed
518  *
519  * RETURN:      Status
520  *
521  * DESCRIPTION: Execute Type 2 monadic operator with numeric operand:
522  *              Deref_of_op, Ref_of_op, Size_of_op, Type_op, Increment_op,
523  *              Decrement_op, LNot_op,
524  *
525  ******************************************************************************/
526
527 ACPI_STATUS
528 acpi_aml_exec_monadic2 (
529         u16                     opcode,
530         ACPI_WALK_STATE         *walk_state,
531         ACPI_OPERAND_OBJECT     **return_desc)
532 {
533         ACPI_OPERAND_OBJECT     *obj_desc;
534         ACPI_OPERAND_OBJECT     *tmp_desc;
535         ACPI_OPERAND_OBJECT     *ret_desc = NULL;
536         ACPI_STATUS             resolve_status;
537         ACPI_STATUS             status;
538         u32                     type;
539         ACPI_INTEGER            value;
540
541
542         /* Attempt to resolve the operands */
543
544         resolve_status = acpi_aml_resolve_operands (opcode, WALK_OPERANDS, walk_state);
545         /* Always get all operands */
546
547         status = acpi_ds_obj_stack_pop_object (&obj_desc, walk_state);
548
549
550         /* Now we can check the status codes */
551
552         if (ACPI_FAILURE (resolve_status)) {
553                 goto cleanup;
554         }
555
556         if (ACPI_FAILURE (status)) {
557                 goto cleanup;
558         }
559
560
561         /* Get the operand and decode the opcode */
562
563
564         switch (opcode) {
565
566         /*  Def_lNot := LNot_op Operand */
567
568         case AML_LNOT_OP:
569
570                 ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
571                 if (!ret_desc) {
572                         status = AE_NO_MEMORY;
573                         goto cleanup;
574                 }
575
576                 ret_desc->integer.value = !obj_desc->integer.value;
577                 break;
578
579
580         /*  Def_decrement   :=  Decrement_op Target */
581         /*  Def_increment   :=  Increment_op Target */
582
583         case AML_DECREMENT_OP:
584         case AML_INCREMENT_OP:
585
586                 /*
587                  * Since we are expecting an Reference on the top of the stack, it
588                  * can be either an Node or an internal object.
589                  *
590                  * TBD: [Future] This may be the prototype code for all cases where
591                  * an Reference is expected!! 10/99
592                  */
593
594                 if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) {
595                         ret_desc = obj_desc;
596                 }
597
598                 else {
599                         /*
600                          * Duplicate the Reference in a new object so that we can resolve it
601                          * without destroying the original Reference object
602                          */
603
604                         ret_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_REFERENCE);
605                         if (!ret_desc) {
606                                 status = AE_NO_MEMORY;
607                                 goto cleanup;
608                         }
609
610                         ret_desc->reference.opcode = obj_desc->reference.opcode;
611                         ret_desc->reference.offset = obj_desc->reference.offset;
612                         ret_desc->reference.object = obj_desc->reference.object;
613                 }
614
615
616                 /*
617                  * Convert the Ret_desc Reference to a Number
618                  * (This deletes the original Ret_desc)
619                  */
620
621                 status = acpi_aml_resolve_operands (AML_LNOT_OP, &ret_desc, walk_state);
622                 if (ACPI_FAILURE (status)) {
623                         goto cleanup;
624                 }
625
626                 /* Do the actual increment or decrement */
627
628                 if (AML_INCREMENT_OP == opcode) {
629                         ret_desc->integer.value++;
630                 }
631                 else {
632                         ret_desc->integer.value--;
633                 }
634
635                 /* Store the result back in the original descriptor */
636
637                 status = acpi_aml_exec_store (ret_desc, obj_desc, walk_state);
638
639                 /* Objdesc was just deleted (because it is an Reference) */
640
641                 obj_desc = NULL;
642
643                 break;
644
645
646         /*  Def_object_type :=  Object_type_op  Source_object   */
647
648         case AML_TYPE_OP:
649
650                 if (INTERNAL_TYPE_REFERENCE == obj_desc->common.type) {
651                         /*
652                          * Not a Name -- an indirect name pointer would have
653                          * been converted to a direct name pointer in Resolve_operands
654                          */
655                         switch (obj_desc->reference.opcode) {
656                         case AML_ZERO_OP:
657                         case AML_ONE_OP:
658                         case AML_ONES_OP:
659
660                                 /* Constants are of type Number */
661
662                                 type = ACPI_TYPE_INTEGER;
663                                 break;
664
665
666                         case AML_DEBUG_OP:
667
668                                 /* Per 1.0b spec, Debug object is of type Debug_object */
669
670                                 type = ACPI_TYPE_DEBUG_OBJECT;
671                                 break;
672
673
674                         case AML_INDEX_OP:
675
676                                 /* Get the type of this reference (index into another object) */
677
678                                 type = obj_desc->reference.target_type;
679                                 if (type == ACPI_TYPE_PACKAGE) {
680                                         /*
681                                          * The main object is a package, we want to get the type
682                                          * of the individual package element that is referenced by
683                                          * the index.
684                                          */
685                                         type = (*(obj_desc->reference.where))->common.type;
686                                 }
687
688                                 break;
689
690
691                         case AML_LOCAL_OP:
692                         case AML_ARG_OP:
693
694                                 type = acpi_ds_method_data_get_type (obj_desc->reference.opcode,
695                                                   obj_desc->reference.offset, walk_state);
696                                 break;
697
698
699                         default:
700
701                                 REPORT_ERROR (("Acpi_aml_exec_monadic2/Type_op: Internal error - Unknown Reference subtype %X\n",
702                                         obj_desc->reference.opcode));
703                                 status = AE_AML_INTERNAL;
704                                 goto cleanup;
705                         }
706                 }
707
708                 else {
709                         /*
710                          * It's not a Reference, so it must be a direct name pointer.
711                          */
712                         type = acpi_ns_get_type ((ACPI_HANDLE) obj_desc);
713                 }
714
715                 /* Allocate a descriptor to hold the type. */
716
717                 ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
718                 if (!ret_desc) {
719                         status = AE_NO_MEMORY;
720                         goto cleanup;
721                 }
722
723                 ret_desc->integer.value = type;
724                 break;
725
726
727         /*  Def_size_of :=  Size_of_op  Source_object   */
728
729         case AML_SIZE_OF_OP:
730
731                 if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) {
732                         obj_desc = acpi_ns_get_attached_object (obj_desc);
733                 }
734
735                 if (!obj_desc) {
736                         value = 0;
737                 }
738
739                 else {
740                         switch (obj_desc->common.type) {
741
742                         case ACPI_TYPE_BUFFER:
743
744                                 value = obj_desc->buffer.length;
745                                 break;
746
747
748                         case ACPI_TYPE_STRING:
749
750                                 value = obj_desc->string.length;
751                                 break;
752
753
754                         case ACPI_TYPE_PACKAGE:
755
756                                 value = obj_desc->package.count;
757                                 break;
758
759                         case INTERNAL_TYPE_REFERENCE:
760
761                                 value = 4;
762                                 break;
763
764                         default:
765
766                                 status = AE_AML_OPERAND_TYPE;
767                                 goto cleanup;
768                         }
769                 }
770
771                 /*
772                  * Now that we have the size of the object, create a result
773                  * object to hold the value
774                  */
775
776                 ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
777                 if (!ret_desc) {
778                         status = AE_NO_MEMORY;
779                         goto cleanup;
780                 }
781
782                 ret_desc->integer.value = value;
783                 break;
784
785
786         /*  Def_ref_of  :=  Ref_of_op   Source_object   */
787
788         case AML_REF_OF_OP:
789
790                 status = acpi_aml_get_object_reference (obj_desc, &ret_desc, walk_state);
791                 if (ACPI_FAILURE (status)) {
792                         goto cleanup;
793                 }
794                 break;
795
796
797         /*  Def_deref_of := Deref_of_op Obj_reference   */
798
799         case AML_DEREF_OF_OP:
800
801
802                 /* Check for a method local or argument */
803
804                 if (!VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) {
805                         /*
806                          * Must resolve/dereference the local/arg reference first
807                          */
808                         switch (obj_desc->reference.opcode) {
809                         /* Set Obj_desc to the value of the local/arg */
810
811                         case AML_LOCAL_OP:
812                         case AML_ARG_OP:
813
814                                 acpi_ds_method_data_get_value (obj_desc->reference.opcode,
815                                                 obj_desc->reference.offset, walk_state, &tmp_desc);
816
817                                 /*
818                                  * Delete our reference to the input object and
819                                  * point to the object just retrieved
820                                  */
821                                 acpi_cm_remove_reference (obj_desc);
822                                 obj_desc = tmp_desc;
823                                 break;
824
825                         default:
826
827                                 /* Index op - handled below */
828                                 break;
829                         }
830                 }
831
832
833                 /* Obj_desc may have changed from the code above */
834
835                 if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) {
836                         /* Get the actual object from the Node (This is the dereference) */
837
838                         ret_desc = ((ACPI_NAMESPACE_NODE *) obj_desc)->object;
839
840                         /* Returning a pointer to the object, add another reference! */
841
842                         acpi_cm_add_reference (ret_desc);
843                 }
844
845                 else {
846                         /*
847                          * This must be a reference object produced by the Index
848                          * ASL operation -- check internal opcode
849                          */
850
851                         if ((obj_desc->reference.opcode != AML_INDEX_OP) &&
852                                 (obj_desc->reference.opcode != AML_REF_OF_OP)) {
853                                 status = AE_TYPE;
854                                 goto cleanup;
855                         }
856
857
858                         switch (obj_desc->reference.opcode) {
859                         case AML_INDEX_OP:
860
861                                 /*
862                                  * Supported target types for the Index operator are
863                                  * 1) A Buffer
864                                  * 2) A Package
865                                  */
866
867                                 if (obj_desc->reference.target_type == ACPI_TYPE_BUFFER_FIELD) {
868                                         /*
869                                          * The target is a buffer, we must create a new object that
870                                          * contains one element of the buffer, the element pointed
871                                          * to by the index.
872                                          *
873                                          * NOTE: index into a buffer is NOT a pointer to a
874                                          * sub-buffer of the main buffer, it is only a pointer to a
875                                          * single element (byte) of the buffer!
876                                          */
877                                         ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
878                                         if (!ret_desc) {
879                                                 status = AE_NO_MEMORY;
880                                                 goto cleanup;
881                                         }
882
883                                         tmp_desc = obj_desc->reference.object;
884                                         ret_desc->integer.value =
885                                                 tmp_desc->buffer.pointer[obj_desc->reference.offset];
886
887                                         /* TBD: [Investigate] (see below) Don't add an additional
888                                          * ref!
889                                          */
890                                 }
891
892                                 else if (obj_desc->reference.target_type == ACPI_TYPE_PACKAGE) {
893                                         /*
894                                          * The target is a package, we want to return the referenced
895                                          * element of the package.  We must add another reference to
896                                          * this object, however.
897                                          */
898
899                                         ret_desc = *(obj_desc->reference.where);
900                                         if (!ret_desc) {
901                                                 /*
902                                                  * We can't return a NULL dereferenced value.  This is
903                                                  * an uninitialized package element and is thus a
904                                                  * severe error.
905                                                  */
906
907                                                 status = AE_AML_UNINITIALIZED_ELEMENT;
908                                                 goto cleanup;
909                                         }
910
911                                         acpi_cm_add_reference (ret_desc);
912                                 }
913
914                                 else {
915                                         status = AE_AML_OPERAND_TYPE;
916                                         goto cleanup;
917                                 }
918
919                                 break;
920
921
922                         case AML_REF_OF_OP:
923
924                                 ret_desc = obj_desc->reference.object;
925
926                                 /* Add another reference to the object! */
927
928                                 acpi_cm_add_reference (ret_desc);
929                                 break;
930                         }
931                 }
932
933                 break;
934
935
936         default:
937
938                 REPORT_ERROR (("Acpi_aml_exec_monadic2: Unknown monadic opcode %X\n",
939                         opcode));
940                 status = AE_AML_BAD_OPCODE;
941                 goto cleanup;
942         }
943
944
945 cleanup:
946
947         if (obj_desc) {
948                 acpi_cm_remove_reference (obj_desc);
949         }
950
951         /* Delete return object on error */
952
953         if (ACPI_FAILURE (status) &&
954                 (ret_desc)) {
955                 acpi_cm_remove_reference (ret_desc);
956                 ret_desc = NULL;
957         }
958
959         *return_desc = ret_desc;
960         return (status);
961 }
962