- Kai Germaschewski: ISDN update (including Makefiles)
[davej-history.git] / drivers / acpi / dispatcher / dswload.c
blobb3f1dc06230e5824a64bd3ada530109b105bc86a
1 /******************************************************************************
3 * Module Name: dswload - Dispatcher namespace load callbacks
4 * $Revision: 24 $
6 *****************************************************************************/
8 /*
9 * Copyright (C) 2000 R. Byron Moore
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.
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.
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
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"
36 #define _COMPONENT DISPATCHER
37 MODULE_NAME ("dswload")
40 /*****************************************************************************
42 * FUNCTION: Acpi_ds_load1_begin_op
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.
48 * RETURN: Status
50 * DESCRIPTION: Descending callback used during the loading of ACPI tables.
52 ****************************************************************************/
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)
61 ACPI_NAMESPACE_NODE *node;
62 ACPI_STATUS status;
63 OBJECT_TYPE_INTERNAL data_type;
64 NATIVE_CHAR *path;
67 /* We are only interested in opcodes that have an associated name */
69 if (!acpi_ps_is_named_op (opcode)) {
70 *out_op = op;
71 return (AE_OK);
75 /* Check if this object has already been installed in the namespace */
77 if (op && op->node) {
78 *out_op = op;
79 return (AE_OK);
82 path = acpi_ps_get_next_namestring (walk_state->parser_state);
84 /* Map the raw opcode into an internal object type */
86 data_type = acpi_ds_map_named_opcode_to_data_type (opcode);
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.
95 status = acpi_ns_lookup (walk_state->scope_info, path,
96 data_type, IMODE_LOAD_PASS1,
97 NS_NO_UPSEARCH, walk_state, &(node));
99 if (ACPI_FAILURE (status)) {
100 return (status);
103 if (!op) {
104 /* Create a new op */
106 op = acpi_ps_alloc_op (opcode);
107 if (!op) {
108 return (AE_NO_MEMORY);
112 /* Initialize */
114 ((ACPI_PARSE2_OBJECT *)op)->name = node->name;
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
120 op->node = node;
123 acpi_ps_append_arg (acpi_ps_get_parent_scope (walk_state->parser_state), op);
125 *out_op = op;
127 return (status);
131 /*****************************************************************************
133 * FUNCTION: Acpi_ds_load1_end_op
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.
139 * RETURN: Status
141 * DESCRIPTION: Ascending callback used during the loading of the namespace,
142 * both control methods and everything else.
144 ****************************************************************************/
146 ACPI_STATUS
147 acpi_ds_load1_end_op (
148 ACPI_WALK_STATE *walk_state,
149 ACPI_PARSE_OBJECT *op)
151 OBJECT_TYPE_INTERNAL data_type;
154 /* We are only interested in opcodes that have an associated name */
156 if (!acpi_ps_is_named_op (op->opcode)) {
157 return (AE_OK);
161 /* Get the type to determine if we should pop the scope */
163 data_type = acpi_ds_map_named_opcode_to_data_type (op->opcode);
165 if (op->opcode == AML_NAME_OP) {
166 /* For Name opcode, check the argument */
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;
177 /* Pop the scope stack */
179 if (acpi_ns_opens_scope (data_type)) {
181 acpi_ds_scope_stack_pop (walk_state);
184 return (AE_OK);
189 /*****************************************************************************
191 * FUNCTION: Acpi_ds_load2_begin_op
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.
197 * RETURN: Status
199 * DESCRIPTION: Descending callback used during the loading of ACPI tables.
201 ****************************************************************************/
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)
210 ACPI_NAMESPACE_NODE *node;
211 ACPI_STATUS status;
212 OBJECT_TYPE_INTERNAL data_type;
213 NATIVE_CHAR *buffer_ptr;
214 void *original = NULL;
217 /* We only care about Namespace opcodes here */
219 if (!acpi_ps_is_namespace_op (opcode) &&
220 opcode != AML_NAMEPATH_OP)
222 return (AE_OK);
226 /* Temp! same code as in psparse */
228 if (!acpi_ps_is_named_op (opcode)) {
229 return (AE_OK);
232 if (op) {
234 * Get the name we are going to enter or lookup in the namespace
236 if (opcode == AML_NAMEPATH_OP) {
237 /* For Namepath op, get the path string */
239 buffer_ptr = op->value.string;
240 if (!buffer_ptr) {
241 /* No name, just exit */
243 return (AE_OK);
247 else {
248 /* Get name from the op */
250 buffer_ptr = (NATIVE_CHAR *) &((ACPI_PARSE2_OBJECT *)op)->name;
254 else {
255 buffer_ptr = acpi_ps_get_next_namestring (walk_state->parser_state);
259 /* Map the raw opcode into an internal object type */
261 data_type = acpi_ds_map_named_opcode_to_data_type (opcode);
264 if (opcode == AML_DEF_FIELD_OP ||
265 opcode == AML_BANK_FIELD_OP ||
266 opcode == AML_INDEX_FIELD_OP)
268 node = NULL;
269 status = AE_OK;
272 else if (opcode == AML_NAMEPATH_OP) {
274 * The Name_path is an object reference to an existing object. Don't enter the
275 * name into the namespace, but look it up for use later
277 status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr,
278 data_type, IMODE_EXECUTE,
279 NS_SEARCH_PARENT, walk_state,
280 &(node));
283 else {
284 if (op && op->node) {
285 original = op->node;
286 node = op->node;
288 if (acpi_ns_opens_scope (data_type)) {
289 status = acpi_ds_scope_stack_push (node,
290 data_type,
291 walk_state);
292 if (ACPI_FAILURE (status)) {
293 return (status);
297 return (AE_OK);
301 * Enter the named type into the internal namespace. We enter the name
302 * as we go downward in the parse tree. Any necessary subobjects that involve
303 * arguments to the opcode must be created as we go back up the parse tree later.
305 status = acpi_ns_lookup (walk_state->scope_info, buffer_ptr,
306 data_type, IMODE_EXECUTE,
307 NS_NO_UPSEARCH, walk_state,
308 &(node));
311 if (ACPI_SUCCESS (status)) {
312 if (!op) {
313 /* Create a new op */
315 op = acpi_ps_alloc_op (opcode);
316 if (!op) {
317 return (AE_NO_MEMORY);
320 /* Initialize */
322 ((ACPI_PARSE2_OBJECT *)op)->name = node->name;
323 *out_op = op;
328 * Put the Node in the "op" object that the parser uses, so we
329 * can get it again quickly when this scope is closed
331 op->node = node;
336 return (status);
340 /*****************************************************************************
342 * FUNCTION: Acpi_ds_load2_end_op
344 * PARAMETERS: Walk_state - Current state of the parse tree walk
345 * Op - Op that has been just been completed in the
346 * walk; Arguments have now been evaluated.
348 * RETURN: Status
350 * DESCRIPTION: Ascending callback used during the loading of the namespace,
351 * both control methods and everything else.
353 ****************************************************************************/
355 ACPI_STATUS
356 acpi_ds_load2_end_op (
357 ACPI_WALK_STATE *walk_state,
358 ACPI_PARSE_OBJECT *op)
360 ACPI_STATUS status = AE_OK;
361 OBJECT_TYPE_INTERNAL data_type;
362 ACPI_NAMESPACE_NODE *node;
363 ACPI_PARSE_OBJECT *arg;
364 ACPI_NAMESPACE_NODE *new_node;
367 if (!acpi_ps_is_namespace_object_op (op->opcode)) {
368 return (AE_OK);
371 if (op->opcode == AML_SCOPE_OP) {
372 if (((ACPI_PARSE2_OBJECT *)op)->name == -1) {
373 return (AE_OK);
378 data_type = acpi_ds_map_named_opcode_to_data_type (op->opcode);
381 * Get the Node/name from the earlier lookup
382 * (It was saved in the *op structure)
384 node = op->node;
387 * Put the Node on the object stack (Contains the ACPI Name of
388 * this object)
391 walk_state->operands[0] = (void *) node;
392 walk_state->num_operands = 1;
394 /* Pop the scope stack */
396 if (acpi_ns_opens_scope (data_type)) {
398 acpi_ds_scope_stack_pop (walk_state);
403 * Named operations are as follows:
405 * AML_SCOPE
406 * AML_DEVICE
407 * AML_THERMALZONE
408 * AML_METHOD
409 * AML_POWERRES
410 * AML_PROCESSOR
411 * AML_FIELD
412 * AML_INDEXFIELD
413 * AML_BANKFIELD
414 * AML_NAMEDFIELD
415 * AML_NAME
416 * AML_ALIAS
417 * AML_MUTEX
418 * AML_EVENT
419 * AML_OPREGION
420 * AML_CREATEFIELD
421 * AML_CREATEBITFIELD
422 * AML_CREATEBYTEFIELD
423 * AML_CREATEWORDFIELD
424 * AML_CREATEDWORDFIELD
425 * AML_METHODCALL
429 /* Decode the opcode */
431 arg = op->value.arg;
433 switch (op->opcode)
436 case AML_CREATE_FIELD_OP:
437 case AML_BIT_FIELD_OP:
438 case AML_BYTE_FIELD_OP:
439 case AML_WORD_FIELD_OP:
440 case AML_DWORD_FIELD_OP:
443 * Create the field object, but the field buffer and index must
444 * be evaluated later during the execution phase
447 /* Get the Name_string argument */
449 if (op->opcode == AML_CREATE_FIELD_OP) {
450 arg = acpi_ps_get_arg (op, 3);
452 else {
453 /* Create Bit/Byte/Word/Dword field */
455 arg = acpi_ps_get_arg (op, 2);
459 * Enter the Name_string into the namespace
462 status = acpi_ns_lookup (walk_state->scope_info,
463 arg->value.string,
464 INTERNAL_TYPE_DEF_ANY,
465 IMODE_LOAD_PASS1,
466 NS_NO_UPSEARCH | NS_DONT_OPEN_SCOPE,
467 walk_state, &(new_node));
469 if (ACPI_SUCCESS (status)) {
470 /* We could put the returned object (Node) on the object stack for later, but
471 * for now, we will put it in the "op" object that the parser uses, so we
472 * can get it again at the end of this scope
474 op->node = new_node;
477 * If there is no object attached to the node, this node was just created and
478 * we need to create the field object. Otherwise, this was a lookup of an
479 * existing node and we don't want to create the field object again.
481 if (!new_node->object) {
483 * The Field definition is not fully parsed at this time.
484 * (We must save the address of the AML for the buffer and index operands)
486 status = acpi_aml_exec_create_field (((ACPI_PARSE2_OBJECT *) op)->data,
487 ((ACPI_PARSE2_OBJECT *) op)->length,
488 new_node, walk_state);
493 break;
496 case AML_METHODCALL_OP:
499 * Lookup the method name and save the Node
502 status = acpi_ns_lookup (walk_state->scope_info, arg->value.string,
503 ACPI_TYPE_ANY, IMODE_LOAD_PASS2,
504 NS_SEARCH_PARENT | NS_DONT_OPEN_SCOPE,
505 walk_state, &(new_node));
507 if (ACPI_SUCCESS (status)) {
509 /* has name already been resolved by here ??*/
511 /* TBD: [Restructure] Make sure that what we found is indeed a method! */
512 /* We didn't search for a method on purpose, to see if the name would resolve! */
514 /* We could put the returned object (Node) on the object stack for later, but
515 * for now, we will put it in the "op" object that the parser uses, so we
516 * can get it again at the end of this scope
518 op->node = new_node;
522 break;
525 case AML_PROCESSOR_OP:
527 /* Nothing to do other than enter object into namespace */
529 status = acpi_aml_exec_create_processor (op, (ACPI_HANDLE) node);
530 if (ACPI_FAILURE (status)) {
531 goto cleanup;
534 break;
537 case AML_POWER_RES_OP:
539 /* Nothing to do other than enter object into namespace */
541 status = acpi_aml_exec_create_power_resource (op, (ACPI_HANDLE) node);
542 if (ACPI_FAILURE (status)) {
543 goto cleanup;
546 break;
549 case AML_THERMAL_ZONE_OP:
551 /* Nothing to do other than enter object into namespace */
553 break;
556 case AML_DEF_FIELD_OP:
558 arg = op->value.arg;
560 status = acpi_ds_create_field (op,
561 arg->node,
562 walk_state);
563 break;
566 case AML_INDEX_FIELD_OP:
568 arg = op->value.arg;
570 status = acpi_ds_create_index_field (op,
571 (ACPI_HANDLE) arg->node,
572 walk_state);
573 break;
576 case AML_BANK_FIELD_OP:
578 arg = op->value.arg;
579 status = acpi_ds_create_bank_field (op,
580 arg->node,
581 walk_state);
582 break;
586 * Method_op Pkg_length Names_string Method_flags Term_list
588 case AML_METHOD_OP:
590 if (!node->object) {
591 status = acpi_aml_exec_create_method (((ACPI_PARSE2_OBJECT *) op)->data,
592 ((ACPI_PARSE2_OBJECT *) op)->length,
593 arg->value.integer, (ACPI_HANDLE) node);
596 break;
599 case AML_MUTEX_OP:
601 status = acpi_ds_create_operands (walk_state, arg);
602 if (ACPI_FAILURE (status)) {
603 goto cleanup;
606 status = acpi_aml_exec_create_mutex (walk_state);
607 break;
610 case AML_EVENT_OP:
612 status = acpi_ds_create_operands (walk_state, arg);
613 if (ACPI_FAILURE (status)) {
614 goto cleanup;
617 status = acpi_aml_exec_create_event (walk_state);
618 break;
621 case AML_REGION_OP:
623 if (node->object) {
624 break;
629 * The Op_region is not fully parsed at this time. Only valid argument is the Space_id.
630 * (We must save the address of the AML of the address and length operands)
633 status = acpi_aml_exec_create_region (((ACPI_PARSE2_OBJECT *) op)->data,
634 ((ACPI_PARSE2_OBJECT *) op)->length,
635 (ACPI_ADDRESS_SPACE_TYPE) arg->value.integer,
636 walk_state);
638 break;
641 /* Namespace Modifier Opcodes */
643 case AML_ALIAS_OP:
645 status = acpi_ds_create_operands (walk_state, arg);
646 if (ACPI_FAILURE (status)) {
647 goto cleanup;
650 status = acpi_aml_exec_create_alias (walk_state);
651 break;
654 case AML_NAME_OP:
657 * Because of the execution pass through the non-control-method
658 * parts of the table, we can arrive here twice. Only init
659 * the named object node the first time through
662 if (!node->object) {
663 status = acpi_ds_create_node (walk_state, node, op);
666 break;
669 case AML_NAMEPATH_OP:
671 break;
674 default:
675 break;
679 cleanup:
681 /* Remove the Node pushed at the very beginning */
683 acpi_ds_obj_stack_pop (1, walk_state);
684 return (status);