:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / drivers / bus / acpi / dispatcher / dsutils.c
1 /*******************************************************************************
2  *
3  * Module Name: dsutils - Dispatcher utilities
4  *              $Revision$
5  *
6  ******************************************************************************/
7
8 /*
9  *  Copyright (C) 2000, 2001 R. Byron Moore
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, write to the Free Software
23  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  */
25
26
27 #include "acpi.h"
28 #include "acparser.h"
29 #include "amlcode.h"
30 #include "acdispat.h"
31 #include "acinterp.h"
32 #include "acnamesp.h"
33 #include "acdebug.h"
34
35 #define _COMPONENT          ACPI_DISPATCHER
36          MODULE_NAME         ("dsutils")
37
38
39 /*******************************************************************************
40  *
41  * FUNCTION:    Acpi_ds_is_result_used
42  *
43  * PARAMETERS:  Op
44  *              Result_obj
45  *              Walk_state
46  *
47  * RETURN:      Status
48  *
49  * DESCRIPTION: Check if a result object will be used by the parent
50  *
51  ******************************************************************************/
52
53 u8
54 acpi_ds_is_result_used (
55         ACPI_PARSE_OBJECT       *op,
56         ACPI_WALK_STATE         *walk_state)
57 {
58         ACPI_OPCODE_INFO        *parent_info;
59
60
61         /* Must have both an Op and a Result Object */
62
63         if (!op) {
64                 return (TRUE);
65         }
66
67
68         /*
69          * If there is no parent, the result can't possibly be used!
70          * (An executing method typically has no parent, since each
71          * method is parsed separately)  However, a method that is
72          * invoked from another method has a parent.
73          */
74         if (!op->parent) {
75                 return (FALSE);
76         }
77
78
79         /*
80          * Get info on the parent.  The root Op is AML_SCOPE
81          */
82
83         parent_info = acpi_ps_get_opcode_info (op->parent->opcode);
84         if (ACPI_GET_OP_TYPE (parent_info) != ACPI_OP_TYPE_OPCODE) {
85                 return (FALSE);
86         }
87
88
89         /*
90          * Decide what to do with the result based on the parent.  If
91          * the parent opcode will not use the result, delete the object.
92          * Otherwise leave it as is, it will be deleted when it is used
93          * as an operand later.
94          */
95
96         switch (ACPI_GET_OP_CLASS (parent_info)) {
97         /*
98          * In these cases, the parent will never use the return object
99          */
100         case OPTYPE_CONTROL:        /* IF, ELSE, WHILE only */
101
102                 switch (op->parent->opcode) {
103                 case AML_RETURN_OP:
104
105                         /* Never delete the return value associated with a return opcode */
106
107                         return (TRUE);
108                         break;
109
110                 case AML_IF_OP:
111                 case AML_WHILE_OP:
112
113                         /*
114                          * If we are executing the predicate AND this is the predicate op,
115                          * we will use the return value!
116                          */
117
118                         if ((walk_state->control_state->common.state == CONTROL_PREDICATE_EXECUTING) &&
119                                 (walk_state->control_state->control.predicate_op == op)) {
120                                 return (TRUE);
121                         }
122
123                         break;
124                 }
125
126
127                 /* Fall through to not used case below */
128
129
130         case OPTYPE_NAMED_OBJECT:   /* Scope, method, etc. */
131
132                 /*
133                  * These opcodes allow Term_arg(s) as operands and therefore
134                  * method calls.  The result is used.
135                  */
136                 if ((op->parent->opcode == AML_REGION_OP)       ||
137                         (op->parent->opcode == AML_CREATE_FIELD_OP) ||
138                         (op->parent->opcode == AML_BIT_FIELD_OP)    ||
139                         (op->parent->opcode == AML_BYTE_FIELD_OP)   ||
140                         (op->parent->opcode == AML_WORD_FIELD_OP)   ||
141                         (op->parent->opcode == AML_DWORD_FIELD_OP)  ||
142                         (op->parent->opcode == AML_QWORD_FIELD_OP)) {
143                         return (TRUE);
144                 }
145
146                 return (FALSE);
147                 break;
148
149         /*
150          * In all other cases. the parent will actually use the return
151          * object, so keep it.
152          */
153         default:
154                 break;
155         }
156
157         return (TRUE);
158 }
159
160
161 /*******************************************************************************
162  *
163  * FUNCTION:    Acpi_ds_delete_result_if_not_used
164  *
165  * PARAMETERS:  Op
166  *              Result_obj
167  *              Walk_state
168  *
169  * RETURN:      Status
170  *
171  * DESCRIPTION: Used after interpretation of an opcode.  If there is an internal
172  *              result descriptor, check if the parent opcode will actually use
173  *              this result.  If not, delete the result now so that it will
174  *              not become orphaned.
175  *
176  ******************************************************************************/
177
178 void
179 acpi_ds_delete_result_if_not_used (
180         ACPI_PARSE_OBJECT       *op,
181         ACPI_OPERAND_OBJECT     *result_obj,
182         ACPI_WALK_STATE         *walk_state)
183 {
184         ACPI_OPERAND_OBJECT     *obj_desc;
185         ACPI_STATUS             status;
186
187
188         if (!op) {
189                 return;
190         }
191
192         if (!result_obj) {
193                 return;
194         }
195
196
197         if (!acpi_ds_is_result_used (op, walk_state)) {
198                 /*
199                  * Must pop the result stack (Obj_desc should be equal
200                  *  to Result_obj)
201                  */
202
203                 status = acpi_ds_result_pop (&obj_desc, walk_state);
204                 if (ACPI_SUCCESS (status)) {
205                         acpi_cm_remove_reference (result_obj);
206                 }
207         }
208
209         return;
210 }
211
212
213 /*******************************************************************************
214  *
215  * FUNCTION:    Acpi_ds_create_operand
216  *
217  * PARAMETERS:  Walk_state
218  *              Arg
219  *
220  * RETURN:      Status
221  *
222  * DESCRIPTION: Translate a parse tree object that is an argument to an AML
223  *              opcode to the equivalent interpreter object.  This may include
224  *              looking up a name or entering a new name into the internal
225  *              namespace.
226  *
227  ******************************************************************************/
228
229 ACPI_STATUS
230 acpi_ds_create_operand (
231         ACPI_WALK_STATE         *walk_state,
232         ACPI_PARSE_OBJECT       *arg,
233         u32                     arg_index)
234 {
235         ACPI_STATUS             status = AE_OK;
236         NATIVE_CHAR             *name_string;
237         u32                     name_length;
238         OBJECT_TYPE_INTERNAL    data_type;
239         ACPI_OPERAND_OBJECT     *obj_desc;
240         ACPI_PARSE_OBJECT       *parent_op;
241         u16                     opcode;
242         u32                     flags;
243         OPERATING_MODE          interpreter_mode;
244
245
246         /* A valid name must be looked up in the namespace */
247
248         if ((arg->opcode == AML_NAMEPATH_OP) &&
249                 (arg->value.string)) {
250                 /* Get the entire name string from the AML stream */
251
252                 status = acpi_aml_get_name_string (ACPI_TYPE_ANY,
253                                    arg->value.buffer,
254                                    &name_string,
255                                    &name_length);
256
257                 if (ACPI_FAILURE (status)) {
258                         return (status);
259                 }
260
261                 /*
262                  * All prefixes have been handled, and the name is
263                  * in Name_string
264                  */
265
266                 /*
267                  * Differentiate between a namespace "create" operation
268                  * versus a "lookup" operation (IMODE_LOAD_PASS2 vs.
269                  * IMODE_EXECUTE) in order to support the creation of
270                  * namespace objects during the execution of control methods.
271                  */
272
273                 parent_op = arg->parent;
274                 if ((acpi_ps_is_node_op (parent_op->opcode)) &&
275                         (parent_op->opcode != AML_METHODCALL_OP) &&
276                         (parent_op->opcode != AML_REGION_OP) &&
277                         (parent_op->opcode != AML_NAMEPATH_OP)) {
278                         /* Enter name into namespace if not found */
279
280                         interpreter_mode = IMODE_LOAD_PASS2;
281                 }
282
283                 else {
284                         /* Return a failure if name not found */
285
286                         interpreter_mode = IMODE_EXECUTE;
287                 }
288
289                 status = acpi_ns_lookup (walk_state->scope_info, name_string,
290                                  ACPI_TYPE_ANY, interpreter_mode,
291                                  NS_SEARCH_PARENT | NS_DONT_OPEN_SCOPE,
292                                  walk_state,
293                                  (ACPI_NAMESPACE_NODE **) &obj_desc);
294
295                 /* Free the namestring created above */
296
297                 acpi_cm_free (name_string);
298
299                 /*
300                  * The only case where we pass through (ignore) a NOT_FOUND
301                  * error is for the Cond_ref_of opcode.
302                  */
303
304                 if (status == AE_NOT_FOUND) {
305                         if (parent_op->opcode == AML_COND_REF_OF_OP) {
306                                 /*
307                                  * For the Conditional Reference op, it's OK if
308                                  * the name is not found;  We just need a way to
309                                  * indicate this to the interpreter, set the
310                                  * object to the root
311                                  */
312                                 obj_desc = (ACPI_OPERAND_OBJECT *) acpi_gbl_root_node;
313                                 status = AE_OK;
314                         }
315
316                         else {
317                                 /*
318                                  * We just plain didn't find it -- which is a
319                                  * very serious error at this point
320                                  */
321                                 status = AE_AML_NAME_NOT_FOUND;
322                         }
323                 }
324
325                 /* Check status from the lookup */
326
327                 if (ACPI_FAILURE (status)) {
328                         return (status);
329                 }
330
331                 /* Put the resulting object onto the current object stack */
332
333                 status = acpi_ds_obj_stack_push (obj_desc, walk_state);
334                 if (ACPI_FAILURE (status)) {
335                         return (status);
336                 }
337                 DEBUGGER_EXEC (acpi_db_display_argument_object (obj_desc, walk_state));
338         }
339
340
341         else {
342                 /* Check for null name case */
343
344                 if (arg->opcode == AML_NAMEPATH_OP) {
345                         /*
346                          * If the name is null, this means that this is an
347                          * optional result parameter that was not specified
348                          * in the original ASL.  Create an Reference for a
349                          * placeholder
350                          */
351                         opcode = AML_ZERO_OP;       /* Has no arguments! */
352
353                         /*
354                          * TBD: [Investigate] anything else needed for the
355                          * zero op lvalue?
356                          */
357                 }
358
359                 else {
360                         opcode = arg->opcode;
361                 }
362
363
364                 /* Get the data type of the argument */
365
366                 data_type = acpi_ds_map_opcode_to_data_type (opcode, &flags);
367                 if (data_type == INTERNAL_TYPE_INVALID) {
368                         return (AE_NOT_IMPLEMENTED);
369                 }
370
371                 if (flags & OP_HAS_RETURN_VALUE) {
372                         DEBUGGER_EXEC (acpi_db_display_argument_object (walk_state->operands [walk_state->num_operands - 1], walk_state));
373
374                         /*
375                          * Use value that was already previously returned
376                          * by the evaluation of this argument
377                          */
378
379                         status = acpi_ds_result_pop_from_bottom (&obj_desc, walk_state);
380                         if (ACPI_FAILURE (status)) {
381                                 /*
382                                  * Only error is underflow, and this indicates
383                                  * a missing or null operand!
384                                  */
385                                 return (status);
386                         }
387
388                 }
389
390                 else {
391                         /* Create an ACPI_INTERNAL_OBJECT for the argument */
392
393                         obj_desc = acpi_cm_create_internal_object (data_type);
394                         if (!obj_desc) {
395                                 return (AE_NO_MEMORY);
396                         }
397
398                         /* Initialize the new object */
399
400                         status = acpi_ds_init_object_from_op (walk_state, arg,
401                                          opcode, &obj_desc);
402                         if (ACPI_FAILURE (status)) {
403                                 acpi_cm_delete_object_desc (obj_desc);
404                                 return (status);
405                         }
406            }
407
408                 /* Put the operand object on the object stack */
409
410                 status = acpi_ds_obj_stack_push (obj_desc, walk_state);
411                 if (ACPI_FAILURE (status)) {
412                         return (status);
413                 }
414
415                 DEBUGGER_EXEC (acpi_db_display_argument_object (obj_desc, walk_state));
416         }
417
418         return (AE_OK);
419 }
420
421
422 /*******************************************************************************
423  *
424  * FUNCTION:    Acpi_ds_create_operands
425  *
426  * PARAMETERS:  First_arg           - First argument of a parser argument tree
427  *
428  * RETURN:      Status
429  *
430  * DESCRIPTION: Convert an operator's arguments from a parse tree format to
431  *              namespace objects and place those argument object on the object
432  *              stack in preparation for evaluation by the interpreter.
433  *
434  ******************************************************************************/
435
436 ACPI_STATUS
437 acpi_ds_create_operands (
438         ACPI_WALK_STATE         *walk_state,
439         ACPI_PARSE_OBJECT       *first_arg)
440 {
441         ACPI_STATUS             status = AE_OK;
442         ACPI_PARSE_OBJECT       *arg;
443         u32                     arg_count = 0;
444
445
446         /* For all arguments in the list... */
447
448         arg = first_arg;
449         while (arg) {
450                 status = acpi_ds_create_operand (walk_state, arg, arg_count);
451                 if (ACPI_FAILURE (status)) {
452                         goto cleanup;
453                 }
454
455                 /* Move on to next argument, if any */
456
457                 arg = arg->next;
458                 arg_count++;
459         }
460
461         return (status);
462
463
464 cleanup:
465         /*
466          * We must undo everything done above; meaning that we must
467          * pop everything off of the operand stack and delete those
468          * objects
469          */
470
471         acpi_ds_obj_stack_pop_and_delete (arg_count, walk_state);
472
473         return (status);
474 }
475
476
477 /*******************************************************************************
478  *
479  * FUNCTION:    Acpi_ds_resolve_operands
480  *
481  * PARAMETERS:  Walk_state          - Current walk state with operands on stack
482  *
483  * RETURN:      Status
484  *
485  * DESCRIPTION: Resolve all operands to their values.  Used to prepare
486  *              arguments to a control method invocation (a call from one
487  *              method to another.)
488  *
489  ******************************************************************************/
490
491 ACPI_STATUS
492 acpi_ds_resolve_operands (
493         ACPI_WALK_STATE         *walk_state)
494 {
495         u32                     i;
496         ACPI_STATUS             status = AE_OK;
497
498
499         /*
500          * Attempt to resolve each of the valid operands
501          * Method arguments are passed by value, not by reference
502          */
503
504         /*
505          * TBD: [Investigate] Note from previous parser:
506          *   Ref_of problem with Acpi_aml_resolve_to_value() conversion.
507          */
508
509         for (i = 0; i < walk_state->num_operands; i++) {
510                 status = acpi_aml_resolve_to_value (&walk_state->operands[i], walk_state);
511                 if (ACPI_FAILURE (status)) {
512                         break;
513                 }
514         }
515
516         return (status);
517 }
518
519
520 /*******************************************************************************
521  *
522  * FUNCTION:    Acpi_ds_map_opcode_to_data_type
523  *
524  * PARAMETERS:  Opcode          - AML opcode to map
525  *              Out_flags       - Additional info about the opcode
526  *
527  * RETURN:      The ACPI type associated with the opcode
528  *
529  * DESCRIPTION: Convert a raw AML opcode to the associated ACPI data type,
530  *              if any.  If the opcode returns a value as part of the
531  *              intepreter execution, a flag is returned in Out_flags.
532  *
533  ******************************************************************************/
534
535 OBJECT_TYPE_INTERNAL
536 acpi_ds_map_opcode_to_data_type (
537         u16                     opcode,
538         u32                     *out_flags)
539 {
540         OBJECT_TYPE_INTERNAL    data_type = INTERNAL_TYPE_INVALID;
541         ACPI_OPCODE_INFO        *op_info;
542         u32                     flags = 0;
543
544
545         op_info = acpi_ps_get_opcode_info (opcode);
546         if (ACPI_GET_OP_TYPE (op_info) != ACPI_OP_TYPE_OPCODE) {
547                 /* Unknown opcode */
548
549                 return (data_type);
550         }
551
552         switch (ACPI_GET_OP_CLASS (op_info)) {
553
554         case OPTYPE_LITERAL:
555
556                 switch (opcode) {
557                 case AML_BYTE_OP:
558                 case AML_WORD_OP:
559                 case AML_DWORD_OP:
560
561                         data_type = ACPI_TYPE_INTEGER;
562                         break;
563
564
565                 case AML_STRING_OP:
566
567                         data_type = ACPI_TYPE_STRING;
568                         break;
569
570                 case AML_NAMEPATH_OP:
571                         data_type = INTERNAL_TYPE_REFERENCE;
572                         break;
573
574                 default:
575                         break;
576                 }
577                 break;
578
579
580         case OPTYPE_DATA_TERM:
581
582                 switch (opcode) {
583                 case AML_BUFFER_OP:
584
585                         data_type = ACPI_TYPE_BUFFER;
586                         break;
587
588                 case AML_PACKAGE_OP:
589
590                         data_type = ACPI_TYPE_PACKAGE;
591                         break;
592
593                 default:
594                         break;
595                 }
596                 break;
597
598
599         case OPTYPE_CONSTANT:
600         case OPTYPE_METHOD_ARGUMENT:
601         case OPTYPE_LOCAL_VARIABLE:
602
603                 data_type = INTERNAL_TYPE_REFERENCE;
604                 break;
605
606
607         case OPTYPE_MONADIC2:
608         case OPTYPE_MONADIC2_r:
609         case OPTYPE_DYADIC2:
610         case OPTYPE_DYADIC2_r:
611         case OPTYPE_DYADIC2_s:
612         case OPTYPE_INDEX:
613         case OPTYPE_MATCH:
614         case OPTYPE_RETURN:
615
616                 flags = OP_HAS_RETURN_VALUE;
617                 data_type = ACPI_TYPE_ANY;
618                 break;
619
620         case OPTYPE_METHOD_CALL:
621
622                 flags = OP_HAS_RETURN_VALUE;
623                 data_type = ACPI_TYPE_METHOD;
624                 break;
625
626
627         case OPTYPE_NAMED_OBJECT:
628
629                 data_type = acpi_ds_map_named_opcode_to_data_type (opcode);
630                 break;
631
632
633         case OPTYPE_DYADIC1:
634         case OPTYPE_CONTROL:
635
636                 /* No mapping needed at this time */
637
638                 break;
639
640
641         default:
642
643                 break;
644         }
645
646         /* Return flags to caller if requested */
647
648         if (out_flags) {
649                 *out_flags = flags;
650         }
651
652         return (data_type);
653 }
654
655
656 /*******************************************************************************
657  *
658  * FUNCTION:    Acpi_ds_map_named_opcode_to_data_type
659  *
660  * PARAMETERS:  Opcode              - The Named AML opcode to map
661  *
662  * RETURN:      The ACPI type associated with the named opcode
663  *
664  * DESCRIPTION: Convert a raw Named AML opcode to the associated data type.
665  *              Named opcodes are a subsystem of the AML opcodes.
666  *
667  ******************************************************************************/
668
669 OBJECT_TYPE_INTERNAL
670 acpi_ds_map_named_opcode_to_data_type (
671         u16                     opcode)
672 {
673         OBJECT_TYPE_INTERNAL    data_type;
674
675
676         /* Decode Opcode */
677
678         switch (opcode) {
679         case AML_SCOPE_OP:
680                 data_type = INTERNAL_TYPE_SCOPE;
681                 break;
682
683         case AML_DEVICE_OP:
684                 data_type = ACPI_TYPE_DEVICE;
685                 break;
686
687         case AML_THERMAL_ZONE_OP:
688                 data_type = ACPI_TYPE_THERMAL;
689                 break;
690
691         case AML_METHOD_OP:
692                 data_type = ACPI_TYPE_METHOD;
693                 break;
694
695         case AML_POWER_RES_OP:
696                 data_type = ACPI_TYPE_POWER;
697                 break;
698
699         case AML_PROCESSOR_OP:
700                 data_type = ACPI_TYPE_PROCESSOR;
701                 break;
702
703         case AML_DEF_FIELD_OP:                          /* Def_field_op */
704                 data_type = INTERNAL_TYPE_DEF_FIELD_DEFN;
705                 break;
706
707         case AML_INDEX_FIELD_OP:                        /* Index_field_op */
708                 data_type = INTERNAL_TYPE_INDEX_FIELD_DEFN;
709                 break;
710
711         case AML_BANK_FIELD_OP:                         /* Bank_field_op */
712                 data_type = INTERNAL_TYPE_BANK_FIELD_DEFN;
713                 break;
714
715         case AML_NAMEDFIELD_OP:                         /* NO CASE IN ORIGINAL  */
716                 data_type = ACPI_TYPE_ANY;
717                 break;
718
719         case AML_NAME_OP:                               /* Name_op - special code in original */
720         case AML_NAMEPATH_OP:
721                 data_type = ACPI_TYPE_ANY;
722                 break;
723
724         case AML_ALIAS_OP:
725                 data_type = INTERNAL_TYPE_ALIAS;
726                 break;
727
728         case AML_MUTEX_OP:
729                 data_type = ACPI_TYPE_MUTEX;
730                 break;
731
732         case AML_EVENT_OP:
733                 data_type = ACPI_TYPE_EVENT;
734                 break;
735
736         case AML_REGION_OP:
737                 data_type = ACPI_TYPE_REGION;
738                 break;
739
740
741         default:
742                 data_type = ACPI_TYPE_ANY;
743                 break;
744
745         }
746
747         return (data_type);
748 }
749
750