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