merge ROS Shell without integrated explorer part into trunk
[reactos.git] / reactos / drivers / bus / acpi / dispatcher / dswload.c
1 /******************************************************************************
2 *
3 * Module Name: dswload - Dispatcher namespace load callbacks
4 * $Revision: 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_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