- Kai Germaschewski: ISDN update (including Makefiles)
[davej-history.git] / drivers / acpi / dispatcher / dsobject.c
blob042cc4a8093cdf11f089e0c51029402ee7e86de5
1 /******************************************************************************
3 * Module Name: dsobject - Dispatcher object management routines
4 * $Revision: 53 $
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"
34 #define _COMPONENT DISPATCHER
35 MODULE_NAME ("dsobject")
38 /*******************************************************************************
40 * FUNCTION: Acpi_ds_init_one_object
42 * PARAMETERS: Obj_handle - Node
43 * Level - Current nesting level
44 * Context - Points to a init info struct
45 * Return_value - Not used
47 * RETURN: Status
49 * DESCRIPTION: Callback from Acpi_walk_namespace. Invoked for every object
50 * within the namespace.
52 * Currently, the only objects that require initialization are:
53 * 1) Methods
54 * 2) Op Regions
56 ******************************************************************************/
58 ACPI_STATUS
59 acpi_ds_init_one_object (
60 ACPI_HANDLE obj_handle,
61 u32 level,
62 void *context,
63 void **return_value)
65 OBJECT_TYPE_INTERNAL type;
66 ACPI_STATUS status;
67 ACPI_INIT_WALK_INFO *info = (ACPI_INIT_WALK_INFO *) context;
68 u8 table_revision;
71 info->object_count++;
72 table_revision = info->table_desc->pointer->revision;
75 * We are only interested in objects owned by the table that
76 * was just loaded
79 if (((ACPI_NAMESPACE_NODE *) obj_handle)->owner_id !=
80 info->table_desc->table_id)
82 return (AE_OK);
86 /* And even then, we are only interested in a few object types */
88 type = acpi_ns_get_type (obj_handle);
90 switch (type)
93 case ACPI_TYPE_REGION:
95 acpi_ds_initialize_region (obj_handle);
97 info->op_region_count++;
98 break;
101 case ACPI_TYPE_METHOD:
103 info->method_count++;
106 * Set the execution data width (32 or 64) based upon the
107 * revision number of the parent ACPI table.
110 if (table_revision == 1) {
111 ((ACPI_NAMESPACE_NODE *)obj_handle)->flags |= ANOBJ_DATA_WIDTH_32;
115 * Always parse methods to detect errors, we may delete
116 * the parse tree below
119 status = acpi_ds_parse_method (obj_handle);
121 /* TBD: [Errors] what do we do with an error? */
123 if (ACPI_FAILURE (status)) {
124 break;
128 * Delete the parse tree. We simple re-parse the method
129 * for every execution since there isn't much overhead
131 acpi_ns_delete_namespace_subtree (obj_handle);
132 break;
134 default:
135 break;
139 * We ignore errors from above, and always return OK, since
140 * we don't want to abort the walk on a single error.
142 return (AE_OK);
146 /*******************************************************************************
148 * FUNCTION: Acpi_ds_initialize_objects
150 * PARAMETERS: None
152 * RETURN: Status
154 * DESCRIPTION: Walk the entire namespace and perform any necessary
155 * initialization on the objects found therein
157 ******************************************************************************/
159 ACPI_STATUS
160 acpi_ds_initialize_objects (
161 ACPI_TABLE_DESC *table_desc,
162 ACPI_NAMESPACE_NODE *start_node)
164 ACPI_STATUS status;
165 ACPI_INIT_WALK_INFO info;
168 info.method_count = 0;
169 info.op_region_count = 0;
170 info.object_count = 0;
171 info.table_desc = table_desc;
174 /* Walk entire namespace from the supplied root */
176 status = acpi_walk_namespace (ACPI_TYPE_ANY, start_node,
177 ACPI_UINT32_MAX, acpi_ds_init_one_object,
178 &info, NULL);
180 return (AE_OK);
184 /*****************************************************************************
186 * FUNCTION: Acpi_ds_init_object_from_op
188 * PARAMETERS: Op - Parser op used to init the internal object
189 * Opcode - AML opcode associated with the object
190 * Obj_desc - Namespace object to be initialized
192 * RETURN: Status
194 * DESCRIPTION: Initialize a namespace object from a parser Op and its
195 * associated arguments. The namespace object is a more compact
196 * representation of the Op and its arguments.
198 ****************************************************************************/
200 ACPI_STATUS
201 acpi_ds_init_object_from_op (
202 ACPI_WALK_STATE *walk_state,
203 ACPI_PARSE_OBJECT *op,
204 u16 opcode,
205 ACPI_OPERAND_OBJECT **obj_desc)
207 ACPI_STATUS status;
208 ACPI_PARSE_OBJECT *arg;
209 ACPI_PARSE2_OBJECT *byte_list;
210 ACPI_OPERAND_OBJECT *arg_desc;
211 ACPI_OPCODE_INFO *op_info;
214 op_info = acpi_ps_get_opcode_info (opcode);
215 if (ACPI_GET_OP_TYPE (op_info) != ACPI_OP_TYPE_OPCODE) {
216 /* Unknown opcode */
218 return (AE_TYPE);
222 /* Get and prepare the first argument */
224 switch ((*obj_desc)->common.type)
226 case ACPI_TYPE_BUFFER:
228 /* First arg is a number */
230 acpi_ds_create_operand (walk_state, op->value.arg, 0);
231 arg_desc = walk_state->operands [walk_state->num_operands - 1];
232 acpi_ds_obj_stack_pop (1, walk_state);
234 /* Resolve the object (could be an arg or local) */
236 status = acpi_aml_resolve_to_value (&arg_desc, walk_state);
237 if (ACPI_FAILURE (status)) {
238 acpi_cm_remove_reference (arg_desc);
239 return (status);
242 /* We are expecting a number */
244 if (arg_desc->common.type != ACPI_TYPE_NUMBER) {
245 acpi_cm_remove_reference (arg_desc);
246 return (AE_TYPE);
249 /* Get the value, delete the internal object */
251 (*obj_desc)->buffer.length = (u32) arg_desc->number.value;
252 acpi_cm_remove_reference (arg_desc);
254 /* Allocate the buffer */
256 if ((*obj_desc)->buffer.length == 0) {
257 (*obj_desc)->buffer.pointer = NULL;
258 REPORT_WARNING (("Buffer created with zero length in AML\n"));
259 break;
262 else {
263 (*obj_desc)->buffer.pointer =
264 acpi_cm_callocate ((*obj_desc)->buffer.length);
266 if (!(*obj_desc)->buffer.pointer) {
267 return (AE_NO_MEMORY);
272 * Second arg is the buffer data (optional)
273 * Byte_list can be either individual bytes or a
274 * string initializer!
277 /* skip first arg */
278 arg = op->value.arg;
279 byte_list = (ACPI_PARSE2_OBJECT *) arg->next;
280 if (byte_list) {
281 if (byte_list->opcode != AML_BYTELIST_OP) {
282 return (AE_TYPE);
285 MEMCPY ((*obj_desc)->buffer.pointer, byte_list->data,
286 (*obj_desc)->buffer.length);
289 break;
292 case ACPI_TYPE_PACKAGE:
295 * When called, an internal package object has already
296 * been built and is pointed to by *Obj_desc.
297 * Acpi_ds_build_internal_object build another internal
298 * package object, so remove reference to the original
299 * so that it is deleted. Error checking is done
300 * within the remove reference function.
302 acpi_cm_remove_reference(*obj_desc);
304 status = acpi_ds_build_internal_object (walk_state, op, obj_desc);
305 break;
307 case ACPI_TYPE_NUMBER:
308 (*obj_desc)->number.value = op->value.integer;
309 break;
312 case ACPI_TYPE_STRING:
313 (*obj_desc)->string.pointer = op->value.string;
314 (*obj_desc)->string.length = STRLEN (op->value.string);
315 break;
318 case ACPI_TYPE_METHOD:
319 break;
322 case INTERNAL_TYPE_REFERENCE:
324 switch (ACPI_GET_OP_CLASS (op_info))
326 case OPTYPE_LOCAL_VARIABLE:
328 /* Split the opcode into a base opcode + offset */
330 (*obj_desc)->reference.op_code = AML_LOCAL_OP;
331 (*obj_desc)->reference.offset = opcode - AML_LOCAL_OP;
332 break;
334 case OPTYPE_METHOD_ARGUMENT:
336 /* Split the opcode into a base opcode + offset */
338 (*obj_desc)->reference.op_code = AML_ARG_OP;
339 (*obj_desc)->reference.offset = opcode - AML_ARG_OP;
340 break;
342 default: /* Constants, Literals, etc.. */
344 if (op->opcode == AML_NAMEPATH_OP) {
345 /* Node was saved in Op */
347 (*obj_desc)->reference.node = op->node;
350 (*obj_desc)->reference.op_code = opcode;
351 break;
354 break;
357 default:
359 break;
362 return (AE_OK);
366 /*****************************************************************************
368 * FUNCTION: Acpi_ds_build_internal_simple_obj
370 * PARAMETERS: Op - Parser object to be translated
371 * Obj_desc_ptr - Where the ACPI internal object is returned
373 * RETURN: Status
375 * DESCRIPTION: Translate a parser Op object to the equivalent namespace object
376 * Simple objects are any objects other than a package object!
378 ****************************************************************************/
380 static ACPI_STATUS
381 acpi_ds_build_internal_simple_obj (
382 ACPI_WALK_STATE *walk_state,
383 ACPI_PARSE_OBJECT *op,
384 ACPI_OPERAND_OBJECT **obj_desc_ptr)
386 ACPI_OPERAND_OBJECT *obj_desc;
387 OBJECT_TYPE_INTERNAL type;
388 ACPI_STATUS status;
389 u32 length;
390 char *name;
393 if (op->opcode == AML_NAMEPATH_OP) {
395 * This is an object reference. If The name was
396 * previously looked up in the NS, it is stored in this op.
397 * Otherwise, go ahead and look it up now
400 if (!op->node) {
401 status = acpi_ns_lookup (walk_state->scope_info,
402 op->value.string, ACPI_TYPE_ANY,
403 IMODE_EXECUTE,
404 NS_SEARCH_PARENT | NS_DONT_OPEN_SCOPE,
405 NULL,
406 (ACPI_NAMESPACE_NODE **)&(op->node));
408 if (ACPI_FAILURE (status)) {
409 if (status == AE_NOT_FOUND) {
410 name = NULL;
411 acpi_ns_externalize_name (ACPI_UINT32_MAX, op->value.string, &length, &name);
413 if (name) {
414 REPORT_WARNING (("Reference %s AML %X not found\n",
415 name, op->aml_offset));
416 acpi_cm_free (name);
418 else {
419 REPORT_WARNING (("Reference %s AML %X not found\n",
420 op->value.string, op->aml_offset));
422 *obj_desc_ptr = NULL;
425 return (status);
430 * The reference will be a Reference
431 * TBD: [Restructure] unless we really need a separate
432 * type of INTERNAL_TYPE_REFERENCE change
433 * Acpi_ds_map_opcode_to_data_type to handle this case
435 type = INTERNAL_TYPE_REFERENCE;
437 else {
438 type = acpi_ds_map_opcode_to_data_type (op->opcode, NULL);
442 /* Create and init the internal ACPI object */
444 obj_desc = acpi_cm_create_internal_object (type);
445 if (!obj_desc) {
446 return (AE_NO_MEMORY);
449 status = acpi_ds_init_object_from_op (walk_state, op,
450 op->opcode, &obj_desc);
452 if (ACPI_FAILURE (status)) {
453 acpi_cm_remove_reference (obj_desc);
454 return (status);
457 *obj_desc_ptr = obj_desc;
459 return (AE_OK);
463 /*****************************************************************************
465 * FUNCTION: Acpi_ds_build_internal_package_obj
467 * PARAMETERS: Op - Parser object to be translated
468 * Obj_desc_ptr - Where the ACPI internal object is returned
470 * RETURN: Status
472 * DESCRIPTION: Translate a parser Op package object to the equivalent
473 * namespace object
475 ****************************************************************************/
477 ACPI_STATUS
478 acpi_ds_build_internal_package_obj (
479 ACPI_WALK_STATE *walk_state,
480 ACPI_PARSE_OBJECT *op,
481 ACPI_OPERAND_OBJECT **obj_desc_ptr)
483 ACPI_PARSE_OBJECT *arg;
484 ACPI_OPERAND_OBJECT *obj_desc;
485 ACPI_STATUS status = AE_OK;
488 obj_desc = acpi_cm_create_internal_object (ACPI_TYPE_PACKAGE);
489 if (!obj_desc) {
490 return (AE_NO_MEMORY);
493 /* The first argument must be the package length */
495 arg = op->value.arg;
496 obj_desc->package.count = arg->value.integer;
499 * Allocate the array of pointers (ptrs to the
500 * individual objects) Add an extra pointer slot so
501 * that the list is always null terminated.
504 obj_desc->package.elements =
505 acpi_cm_callocate ((obj_desc->package.count + 1) *
506 sizeof (void *));
508 if (!obj_desc->package.elements) {
509 /* Package vector allocation failure */
511 REPORT_ERROR (("Ds_build_internal_package_obj: Package vector allocation failure\n"));
513 acpi_cm_delete_object_desc (obj_desc);
514 return (AE_NO_MEMORY);
517 obj_desc->package.next_element = obj_desc->package.elements;
520 * Now init the elements of the package
523 arg = arg->next;
524 while (arg) {
525 if (arg->opcode == AML_PACKAGE_OP) {
526 status = acpi_ds_build_internal_package_obj (walk_state, arg,
527 obj_desc->package.next_element);
530 else {
531 status = acpi_ds_build_internal_simple_obj (walk_state, arg,
532 obj_desc->package.next_element);
535 obj_desc->package.next_element++;
536 arg = arg->next;
539 *obj_desc_ptr = obj_desc;
540 return (status);
544 /*****************************************************************************
546 * FUNCTION: Acpi_ds_build_internal_object
548 * PARAMETERS: Op - Parser object to be translated
549 * Obj_desc_ptr - Where the ACPI internal object is returned
551 * RETURN: Status
553 * DESCRIPTION: Translate a parser Op object to the equivalent namespace
554 * object
556 ****************************************************************************/
558 ACPI_STATUS
559 acpi_ds_build_internal_object (
560 ACPI_WALK_STATE *walk_state,
561 ACPI_PARSE_OBJECT *op,
562 ACPI_OPERAND_OBJECT **obj_desc_ptr)
564 ACPI_STATUS status;
567 if (op->opcode == AML_PACKAGE_OP) {
568 status = acpi_ds_build_internal_package_obj (walk_state, op,
569 obj_desc_ptr);
572 else {
573 status = acpi_ds_build_internal_simple_obj (walk_state, op,
574 obj_desc_ptr);
577 return (status);
581 /*****************************************************************************
583 * FUNCTION: Acpi_ds_create_node
585 * PARAMETERS: Op - Parser object to be translated
586 * Obj_desc_ptr - Where the ACPI internal object is returned
588 * RETURN: Status
590 * DESCRIPTION:
592 ****************************************************************************/
594 ACPI_STATUS
595 acpi_ds_create_node (
596 ACPI_WALK_STATE *walk_state,
597 ACPI_NAMESPACE_NODE *node,
598 ACPI_PARSE_OBJECT *op)
600 ACPI_STATUS status;
601 ACPI_OPERAND_OBJECT *obj_desc;
604 if (!op->value.arg) {
605 /* No arguments, there is nothing to do */
607 return (AE_OK);
611 /* Build an internal object for the argument(s) */
613 status = acpi_ds_build_internal_object (walk_state,
614 op->value.arg, &obj_desc);
615 if (ACPI_FAILURE (status)) {
616 return (status);
620 /* Re-type the object according to it's argument */
622 node->type = obj_desc->common.type;
624 /* Init obj */
626 status = acpi_ns_attach_object ((ACPI_HANDLE) node, obj_desc,
627 (u8) node->type);
628 if (ACPI_FAILURE (status)) {
629 goto cleanup;
632 return (status);
635 cleanup:
637 acpi_cm_remove_reference (obj_desc);
639 return (status);