:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / drivers / bus / acpi / dispatcher / dswload.c
1 /******************************************************************************
2  *
3  * Module Name: dswload - Dispatcher namespace load callbacks
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 "acevents.h"
34
35
36 #define _COMPONENT          ACPI_DISPATCHER
37          MODULE_NAME         ("dswload")
38
39
40 /*******************************************************************************
41  *
42  * FUNCTION:    Acpi_ds_load1_begin_op
43  *
44  * PARAMETERS:  Walk_state      - Current state of the parse tree walk
45  *              Op              - Op that has been just been reached in the
46  *                                walk;  Arguments have not been evaluated yet.
47  *
48  * RETURN:      Status
49  *
50  * DESCRIPTION: Descending callback used during the loading of ACPI tables.
51  *
52  ******************************************************************************/
53
54 ACPI_STATUS
55 acpi_ds_load1_begin_op (
56         u16                     opcode,
57         ACPI_PARSE_OBJECT       *op,
58         ACPI_WALK_STATE         *walk_state,
59         ACPI_PARSE_OBJECT       **out_op)
60 {
61         ACPI_NAMESPACE_NODE     *node;
62         ACPI_STATUS             status;
63         OBJECT_TYPE_INTERNAL    data_type;
64         NATIVE_CHAR             *path;
65
66
67         /* We are only interested in opcodes that have an associated name */
68
69         if (!acpi_ps_is_named_op (opcode)) {
70                 *out_op = op;
71                 return (AE_OK);
72         }
73
74
75         /* Check if this object has already been installed in the namespace */
76
77         if (op && op->node) {
78                 *out_op = op;
79                 return (AE_OK);
80         }
81
82         path = acpi_ps_get_next_namestring (walk_state->parser_state);
83
84         /* Map the raw opcode into an internal object type */
85
86         data_type = acpi_ds_map_named_opcode_to_data_type (opcode);
87
88
89
90         /*
91          * Enter the named type into the internal namespace.  We enter the name
92          * as we go downward in the parse tree.  Any necessary subobjects that involve
93          * arguments to the opcode must be created as we go back up the parse tree later.
94          */
95         status = acpi_ns_lookup (walk_state->scope_info, path,
96                          data_type, IMODE_LOAD_PASS1,
97                          NS_NO_UPSEARCH, walk_state, &(node));
98
99         if (ACPI_FAILURE (status)) {
100                 return (status);
101         }
102
103         if (!op) {
104                 /* Create a new op */
105
106                 op = acpi_ps_alloc_op (opcode);
107                 if (!op) {
108                         return (AE_NO_MEMORY);
109                 }
110         }
111
112         /* Initialize */
113
114         ((ACPI_PARSE2_OBJECT *)op)->name = node->name;
115
116         /*
117          * Put the Node in the "op" object that the parser uses, so we
118          * can get it again quickly when this scope is closed
119          */
120         op->node = node;
121
122
123         acpi_ps_append_arg (acpi_ps_get_parent_scope (walk_state->parser_state), op);
124
125         *out_op = op;
126
127         return (status);
128 }
129
130
131 /*******************************************************************************
132  *
133  * FUNCTION:    Acpi_ds_load1_end_op
134  *
135  * PARAMETERS:  Walk_state      - Current state of the parse tree walk
136  *              Op              - Op that has been just been completed in the
137  *                                walk;  Arguments have now been evaluated.
138  *
139  * RETURN:      Status
140  *
141  * DESCRIPTION: Ascending callback used during the loading of the namespace,
142  *              both control methods and everything else.
143  *
144  ******************************************************************************/
145
146 ACPI_STATUS
147 acpi_ds_load1_end_op (
148         ACPI_WALK_STATE         *walk_state,
149         ACPI_PARSE_OBJECT       *op)
150 {
151         OBJECT_TYPE_INTERNAL    data_type;
152
153
154         /* We are only interested in opcodes that have an associated name */
155
156         if (!acpi_ps_is_named_op (op->opcode)) {
157                 return (AE_OK);
158         }
159
160
161         /* Get the type to determine if we should pop the scope */
162
163         data_type = acpi_ds_map_named_opcode_to_data_type (op->opcode);
164
165         if (op->opcode == AML_NAME_OP) {
166                 /* For Name opcode, check the argument */
167
168                 if (op->value.arg) {
169                         data_type = acpi_ds_map_opcode_to_data_type (
170                                           (op->value.arg)->opcode, NULL);
171                         ((ACPI_NAMESPACE_NODE *)op->node)->type =
172                                           (u8) data_type;
173                 }
174         }
175
176
177         /* Pop the scope stack */
178
179         if (acpi_ns_opens_scope (data_type)) {
180
181                 acpi_ds_scope_stack_pop (walk_state);
182         }
183
184         return (AE_OK);
185
186 }
187
188
189 /*******************************************************************************
190  *
191  * FUNCTION:    Acpi_ds_load2_begin_op
192  *
193  * PARAMETERS:  Walk_state      - Current state of the parse tree walk
194  *              Op              - Op that has been just been reached in the
195  *                                walk;  Arguments have not been evaluated yet.
196  *
197  * RETURN:      Status
198  *
199  * DESCRIPTION: Descending callback used during the loading of ACPI tables.
200  *
201  ******************************************************************************/
202
203 ACPI_STATUS
204 acpi_ds_load2_begin_op (
205         u16                     opcode,
206         ACPI_PARSE_OBJECT       *op,
207         ACPI_WALK_STATE         *walk_state,
208         ACPI_PARSE_OBJECT       **out_op)
209 {
210         ACPI_NAMESPACE_NODE     *node;
211         ACPI_STATUS             status;
212         OBJECT_TYPE_INTERNAL    data_type;
213         NATIVE_CHAR             *buffer_ptr;
214         void                    *original = NULL;
215
216
217         /* We only care about Namespace opcodes here */
218
219         if (!acpi_ps_is_namespace_op (opcode) &&
220                 opcode != AML_NAMEPATH_OP) {
221                 return (AE_OK);
222         }
223
224
225         /* Temp! same code as in psparse */
226
227         if (!acpi_ps_is_named_op (opcode)) {
228                 return (AE_OK);
229         }
230
231         if (op) {
232                 /*
233                  * Get the name we are going to enter or lookup in the namespace
234                  */
235                 if (opcode == AML_NAMEPATH_OP) {
236                         /* For Namepath op, get the path string */
237
238                         buffer_ptr = op->value.string;
239                         if (!buffer_ptr) {
240                                 /* No name, just exit */
241
242                                 return (AE_OK);
243                         }
244                 }
245
246                 else {
247                         /* Get name from the op */
248
249                         buffer_ptr = (NATIVE_CHAR *) &((ACPI_PARSE2_OBJECT *)op)->name;
250                 }
251         }
252
253         else {
254                 buffer_ptr = acpi_ps_get_next_namestring (walk_state->parser_state);
255         }
256
257
258         /* Map the raw opcode into an internal object type */
259
260         data_type = acpi_ds_map_named_opcode_to_data_type (opcode);
261
262
263         if (opcode == AML_DEF_FIELD_OP      ||
264                 opcode == AML_BANK_FIELD_OP     ||
265                 opcode == AML_INDEX_FIELD_OP) {
266                 node = NULL;
267                 status = AE_OK;
268         }
269
270         else if (opcode == AML_NAMEPATH_OP) {
271                 /*
272                  * The Name_path is an object reference to an existing object. Don't enter the
273                  * name into the namespace, but look it up for use later
274                  */
275                 status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr,
276                                  data_type, IMODE_EXECUTE,
277                                  NS_SEARCH_PARENT, walk_state,
278                                  &(node));
279         }
280
281         else {
282                 if (op && op->node) {
283                         original = op->node;
284                         node = op->node;
285
286                         if (acpi_ns_opens_scope (data_type)) {
287                                 status = acpi_ds_scope_stack_push (node,
288                                                    data_type,
289                                                    walk_state);
290                                 if (ACPI_FAILURE (status)) {
291                                         return (status);
292                                 }
293
294                         }
295                         return (AE_OK);
296                 }
297
298                 /*
299                  * Enter the named type into the internal namespace.  We enter the name
300                  * as we go downward in the parse tree.  Any necessary subobjects that involve
301                  * arguments to the opcode must be created as we go back up the parse tree later.
302                  */
303                 status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr,
304                                  data_type, IMODE_EXECUTE,
305                                  NS_NO_UPSEARCH, walk_state,
306                                  &(node));
307         }
308
309         if (ACPI_SUCCESS (status)) {
310                 if (!op) {
311                         /* Create a new op */
312
313                         op = acpi_ps_alloc_op (opcode);
314                         if (!op) {
315                                 return (AE_NO_MEMORY);
316                         }
317
318                         /* Initialize */
319
320                         ((ACPI_PARSE2_OBJECT *)op)->name = node->name;
321                         *out_op = op;
322                 }
323
324
325                 /*
326                  * Put the Node in the "op" object that the parser uses, so we
327                  * can get it again quickly when this scope is closed
328                  */
329                 op->node = node;
330
331         }
332
333
334         return (status);
335 }
336
337
338 /*******************************************************************************
339  *
340  * FUNCTION:    Acpi_ds_load2_end_op
341  *
342  * PARAMETERS:  Walk_state      - Current state of the parse tree walk
343  *              Op              - Op that has been just been completed in the
344  *                                walk;  Arguments have now been evaluated.
345  *
346  * RETURN:      Status
347  *
348  * DESCRIPTION: Ascending callback used during the loading of the namespace,
349  *              both control methods and everything else.
350  *
351  ******************************************************************************/
352
353 ACPI_STATUS
354 acpi_ds_load2_end_op (
355         ACPI_WALK_STATE         *walk_state,
356         ACPI_PARSE_OBJECT       *op)
357 {
358         ACPI_STATUS             status = AE_OK;
359         OBJECT_TYPE_INTERNAL    data_type;
360         ACPI_NAMESPACE_NODE     *node;
361         ACPI_PARSE_OBJECT       *arg;
362         ACPI_NAMESPACE_NODE     *new_node;
363
364
365         if (!acpi_ps_is_namespace_object_op (op->opcode)) {
366                 return (AE_OK);
367         }
368
369         if (op->opcode == AML_SCOPE_OP) {
370                 if (((ACPI_PARSE2_OBJECT *)op)->name == -1) {
371                         return (AE_OK);
372                 }
373         }
374
375
376         data_type = acpi_ds_map_named_opcode_to_data_type (op->opcode);
377
378         /*
379          * Get the Node/name from the earlier lookup
380          * (It was saved in the *op structure)
381          */
382         node = op->node;
383
384         /*
385          * Put the Node on the object stack (Contains the ACPI Name of
386          * this object)
387          */
388
389         walk_state->operands[0] = (void *) node;
390         walk_state->num_operands = 1;
391
392         /* Pop the scope stack */
393
394         if (acpi_ns_opens_scope (data_type)) {
395
396                 acpi_ds_scope_stack_pop (walk_state);
397         }
398
399
400         /*
401          * Named operations are as follows:
402          *
403          * AML_SCOPE
404          * AML_DEVICE
405          * AML_THERMALZONE
406          * AML_METHOD
407          * AML_POWERRES
408          * AML_PROCESSOR
409          * AML_FIELD
410          * AML_INDEXFIELD
411          * AML_BANKFIELD
412          * AML_NAMEDFIELD
413          * AML_NAME
414          * AML_ALIAS
415          * AML_MUTEX
416          * AML_EVENT
417          * AML_OPREGION
418          * AML_CREATEFIELD
419          * AML_CREATEBITFIELD
420          * AML_CREATEBYTEFIELD
421          * AML_CREATEWORDFIELD
422          * AML_CREATEDWORDFIELD
423          * AML_METHODCALL
424          */
425
426
427         /* Decode the opcode */
428
429         arg = op->value.arg;
430
431         switch (op->opcode) {
432
433         case AML_CREATE_FIELD_OP:
434         case AML_BIT_FIELD_OP:
435         case AML_BYTE_FIELD_OP:
436         case AML_WORD_FIELD_OP:
437         case AML_DWORD_FIELD_OP:
438
439                 /*
440                  * Create the field object, but the field buffer and index must
441                  * be evaluated later during the execution phase
442                  */
443
444                 /* Get the Name_string argument */
445
446                 if (op->opcode == AML_CREATE_FIELD_OP) {
447                         arg = acpi_ps_get_arg (op, 3);
448                 }
449                 else {
450                         /* Create Bit/Byte/Word/Dword field */
451
452                         arg = acpi_ps_get_arg (op, 2);
453                 }
454
455                 /*
456                  * Enter the Name_string into the namespace
457                  */
458
459                 status = acpi_ns_lookup (walk_state->scope_info,
460                                  arg->value.string,
461                                  INTERNAL_TYPE_DEF_ANY,
462                                  IMODE_LOAD_PASS1,
463                                  NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE,
464                                  walk_state, &(new_node));
465
466                 if (ACPI_SUCCESS (status)) {
467                         /* We could put the returned object (Node) on the object stack for later, but
468                          * for now, we will put it in the "op" object that the parser uses, so we
469                          * can get it again at the end of this scope
470                          */
471                         op->node = new_node;
472
473                         /*
474                          * If there is no object attached to the node, this node was just created and
475                          * we need to create the field object.  Otherwise, this was a lookup of an
476                          * existing node and we don't want to create the field object again.
477                          */
478                         if (!new_node->object) {
479                                 /*
480                                  * The Field definition is not fully parsed at this time.
481                                  * (We must save the address of the AML for the buffer and index operands)
482                                  */
483                                 status = acpi_aml_exec_create_field (((ACPI_PARSE2_OBJECT *) op)->data,
484                                                    ((ACPI_PARSE2_OBJECT *) op)->length,
485                                                    new_node, walk_state);
486                         }
487                 }
488
489
490                 break;
491
492
493         case AML_METHODCALL_OP:
494
495                 /*
496                  * Lookup the method name and save the Node
497                  */
498
499                 status = acpi_ns_lookup (walk_state->scope_info, arg->value.string,
500                                  ACPI_TYPE_ANY, IMODE_LOAD_PASS2,
501                                  NS_SEARCH_PARENT | NS_DONT_OPEN_SCOPE,
502                                  walk_state, &(new_node));
503
504                 if (ACPI_SUCCESS (status)) {
505
506 /* has name already been resolved by here ??*/
507
508                         /* TBD: [Restructure] Make sure that what we found is indeed a method! */
509                         /* We didn't search for a method on purpose, to see if the name would resolve! */
510
511                         /* We could put the returned object (Node) on the object stack for later, but
512                          * for now, we will put it in the "op" object that the parser uses, so we
513                          * can get it again at the end of this scope
514                          */
515                         op->node = new_node;
516                 }
517
518
519                  break;
520
521
522         case AML_PROCESSOR_OP:
523
524                 /* Nothing to do other than enter object into namespace */
525
526                 status = acpi_aml_exec_create_processor (op, (ACPI_HANDLE) node);
527                 if (ACPI_FAILURE (status)) {
528                         goto cleanup;
529                 }
530
531                 break;
532
533
534         case AML_POWER_RES_OP:
535
536                 /* Nothing to do other than enter object into namespace */
537
538                 status = acpi_aml_exec_create_power_resource (op, (ACPI_HANDLE) node);
539                 if (ACPI_FAILURE (status)) {
540                         goto cleanup;
541                 }
542
543                 break;
544
545
546         case AML_THERMAL_ZONE_OP:
547
548                 /* Nothing to do other than enter object into namespace */
549
550                 break;
551
552
553         case AML_DEF_FIELD_OP:
554
555                 arg = op->value.arg;
556
557                 status = acpi_ds_create_field (op, arg->node, walk_state);
558                 break;
559
560
561         case AML_INDEX_FIELD_OP:
562
563                 arg = op->value.arg;
564
565                 status = acpi_ds_create_index_field (op, (ACPI_HANDLE) arg->node,
566                                    walk_state);
567                 break;
568
569
570         case AML_BANK_FIELD_OP:
571
572                 arg = op->value.arg;
573                 status = acpi_ds_create_bank_field (op, arg->node, walk_state);
574                 break;
575
576
577         /*
578          * Method_op Pkg_length Names_string Method_flags Term_list
579          */
580         case AML_METHOD_OP:
581
582                 if (!node->object) {
583                         status = acpi_aml_exec_create_method (((ACPI_PARSE2_OBJECT *) op)->data,
584                                            ((ACPI_PARSE2_OBJECT *) op)->length,
585                                            arg->value.integer, (ACPI_HANDLE) node);
586                 }
587
588                 break;
589
590
591         case AML_MUTEX_OP:
592
593                 status = acpi_ds_create_operands (walk_state, arg);
594                 if (ACPI_FAILURE (status)) {
595                         goto cleanup;
596                 }
597
598                 status = acpi_aml_exec_create_mutex (walk_state);
599                 break;
600
601
602         case AML_EVENT_OP:
603
604                 status = acpi_ds_create_operands (walk_state, arg);
605                 if (ACPI_FAILURE (status)) {
606                         goto cleanup;
607                 }
608
609                 status = acpi_aml_exec_create_event (walk_state);
610                 break;
611
612
613         case AML_REGION_OP:
614
615                 if (node->object) {
616                         break;
617                 }
618
619
620                 /*
621                  * The Op_region is not fully parsed at this time. Only valid argument is the Space_id.
622                  * (We must save the address of the AML of the address and length operands)
623                  */
624
625                 status = acpi_aml_exec_create_region (((ACPI_PARSE2_OBJECT *) op)->data,
626                                    ((ACPI_PARSE2_OBJECT *) op)->length,
627                                    (ACPI_ADDRESS_SPACE_TYPE) arg->value.integer,
628                                    walk_state);
629
630                 break;
631
632
633         /* Namespace Modifier Opcodes */
634
635         case AML_ALIAS_OP:
636
637                 status = acpi_ds_create_operands (walk_state, arg);
638                 if (ACPI_FAILURE (status)) {
639                         goto cleanup;
640                 }
641
642                 status = acpi_aml_exec_create_alias (walk_state);
643                 break;
644
645
646         case AML_NAME_OP:
647
648                 /*
649                  * Because of the execution pass through the non-control-method
650                  * parts of the table, we can arrive here twice.  Only init
651                  * the named object node the first time through
652                  */
653
654                 if (!node->object) {
655                         status = acpi_ds_create_node (walk_state, node, op);
656                 }
657
658                 break;
659
660
661         case AML_NAMEPATH_OP:
662
663                 break;
664
665
666         default:
667                 break;
668         }
669
670
671 cleanup:
672
673         /* Remove the Node pushed at the very beginning */
674
675         acpi_ds_obj_stack_pop (1, walk_state);
676         return (status);
677 }
678
679