import of ftp.dlink.com/GPL/DSMG-600_reB/ppclinux.tar.gz
[linux-2.4.21-pre4.git] / drivers / acpi / dispatcher / dsobject.c
1 /******************************************************************************
2  *
3  * Module Name: dsobject - Dispatcher object management routines
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
34 #define _COMPONENT          ACPI_DISPATCHER
35          MODULE_NAME         ("dsobject")
36
37
38 /*******************************************************************************
39  *
40  * FUNCTION:    Acpi_ds_init_one_object
41  *
42  * PARAMETERS:  Obj_handle      - Node
43  *              Level           - Current nesting level
44  *              Context         - Points to a init info struct
45  *              Return_value    - Not used
46  *
47  * RETURN:      Status
48  *
49  * DESCRIPTION: Callback from Acpi_walk_namespace. Invoked for every object
50  *              within the  namespace.
51  *
52  *              Currently, the only objects that require initialization are:
53  *              1) Methods
54  *              2) Op Regions
55  *
56  ******************************************************************************/
57
58 acpi_status
59 acpi_ds_init_one_object (
60         acpi_handle             obj_handle,
61         u32                     level,
62         void                    *context,
63         void                    **return_value)
64 {
65         acpi_object_type8       type;
66         acpi_status             status;
67         acpi_init_walk_info     *info = (acpi_init_walk_info *) context;
68         u8                      table_revision;
69
70
71         PROC_NAME ("Ds_init_one_object");
72
73
74         info->object_count++;
75         table_revision = info->table_desc->pointer->revision;
76
77         /*
78          * We are only interested in objects owned by the table that
79          * was just loaded
80          */
81         if (((acpi_namespace_node *) obj_handle)->owner_id !=
82                         info->table_desc->table_id) {
83                 return (AE_OK);
84         }
85
86
87         /* And even then, we are only interested in a few object types */
88
89         type = acpi_ns_get_type (obj_handle);
90
91         switch (type) {
92
93         case ACPI_TYPE_REGION:
94
95                 acpi_ds_initialize_region (obj_handle);
96
97                 info->op_region_count++;
98                 break;
99
100
101         case ACPI_TYPE_METHOD:
102
103                 info->method_count++;
104
105                 if (!(acpi_dbg_level & ACPI_LV_INIT)) {
106                         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, "."));
107                 }
108
109                 /*
110                  * Set the execution data width (32 or 64) based upon the
111                  * revision number of the parent ACPI table.
112                  */
113                 if (table_revision == 1) {
114                         ((acpi_namespace_node *)obj_handle)->flags |= ANOBJ_DATA_WIDTH_32;
115                 }
116
117                 /*
118                  * Always parse methods to detect errors, we may delete
119                  * the parse tree below
120                  */
121                 status = acpi_ds_parse_method (obj_handle);
122                 if (ACPI_FAILURE (status)) {
123                         ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Method %p [%4.4s] - parse failure, %s\n",
124                                 obj_handle, (char*)&((acpi_namespace_node *)obj_handle)->name,
125                                 acpi_format_exception (status)));
126
127                         /* This parse failed, but we will continue parsing more methods */
128
129                         break;
130                 }
131
132                 /*
133                  * Delete the parse tree.  We simple re-parse the method
134                  * for every execution since there isn't much overhead
135                  */
136                 acpi_ns_delete_namespace_subtree (obj_handle);
137                 break;
138
139         default:
140                 break;
141         }
142
143         /*
144          * We ignore errors from above, and always return OK, since
145          * we don't want to abort the walk on a single error.
146          */
147         return (AE_OK);
148 }
149
150
151 /*******************************************************************************
152  *
153  * FUNCTION:    Acpi_ds_initialize_objects
154  *
155  * PARAMETERS:  None
156  *
157  * RETURN:      Status
158  *
159  * DESCRIPTION: Walk the entire namespace and perform any necessary
160  *              initialization on the objects found therein
161  *
162  ******************************************************************************/
163
164 acpi_status
165 acpi_ds_initialize_objects (
166         acpi_table_desc         *table_desc,
167         acpi_namespace_node     *start_node)
168 {
169         acpi_status             status;
170         acpi_init_walk_info     info;
171
172
173         FUNCTION_TRACE ("Ds_initialize_objects");
174
175
176         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
177                 "**** Starting initialization of namespace objects ****\n"));
178         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK, "Parsing Methods:"));
179
180
181         info.method_count   = 0;
182         info.op_region_count = 0;
183         info.object_count   = 0;
184         info.table_desc     = table_desc;
185
186
187         /* Walk entire namespace from the supplied root */
188
189         status = acpi_walk_namespace (ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX,
190                           acpi_ds_init_one_object, &info, NULL);
191         if (ACPI_FAILURE (status)) {
192                 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Walk_namespace failed! %x\n", status));
193         }
194
195         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OK,
196                 "\n%d Control Methods found and parsed (%d nodes total)\n",
197                 info.method_count, info.object_count));
198         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
199                 "%d Control Methods found\n", info.method_count));
200         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
201                 "%d Op Regions found\n", info.op_region_count));
202
203         return_ACPI_STATUS (AE_OK);
204 }
205
206
207 /*****************************************************************************
208  *
209  * FUNCTION:    Acpi_ds_init_object_from_op
210  *
211  * PARAMETERS:  Op              - Parser op used to init the internal object
212  *              Opcode          - AML opcode associated with the object
213  *              Obj_desc        - Namespace object to be initialized
214  *
215  * RETURN:      Status
216  *
217  * DESCRIPTION: Initialize a namespace object from a parser Op and its
218  *              associated arguments.  The namespace object is a more compact
219  *              representation of the Op and its arguments.
220  *
221  ****************************************************************************/
222
223 acpi_status
224 acpi_ds_init_object_from_op (
225         acpi_walk_state         *walk_state,
226         acpi_parse_object       *op,
227         u16                     opcode,
228         acpi_operand_object     **ret_obj_desc)
229 {
230         acpi_status             status;
231         acpi_parse_object       *arg;
232         acpi_parse2_object      *byte_list;
233         acpi_operand_object     *arg_desc;
234         const acpi_opcode_info  *op_info;
235         acpi_operand_object     *obj_desc;
236
237
238         PROC_NAME ("Ds_init_object_from_op");
239
240
241         obj_desc = *ret_obj_desc;
242         op_info = acpi_ps_get_opcode_info (opcode);
243         if (op_info->class == AML_CLASS_UNKNOWN) {
244                 /* Unknown opcode */
245
246                 return (AE_TYPE);
247         }
248
249
250         /* Get and prepare the first argument */
251
252         switch (obj_desc->common.type) {
253         case ACPI_TYPE_BUFFER:
254
255                 /* First arg is a number */
256
257                 acpi_ds_create_operand (walk_state, op->value.arg, 0);
258                 arg_desc = walk_state->operands [walk_state->num_operands - 1];
259                 acpi_ds_obj_stack_pop (1, walk_state);
260
261                 /* Resolve the object (could be an arg or local) */
262
263                 status = acpi_ex_resolve_to_value (&arg_desc, walk_state);
264                 if (ACPI_FAILURE (status)) {
265                         acpi_ut_remove_reference (arg_desc);
266                         return (status);
267                 }
268
269                 /* We are expecting a number */
270
271                 if (arg_desc->common.type != ACPI_TYPE_INTEGER) {
272                         ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
273                                 "Expecting number, got obj: %p type %X\n",
274                                 arg_desc, arg_desc->common.type));
275                         acpi_ut_remove_reference (arg_desc);
276                         return (AE_TYPE);
277                 }
278
279                 /* Get the value, delete the internal object */
280
281                 obj_desc->buffer.length = (u32) arg_desc->integer.value;
282                 acpi_ut_remove_reference (arg_desc);
283
284                 /* Allocate the buffer */
285
286                 if (obj_desc->buffer.length == 0) {
287                         obj_desc->buffer.pointer = NULL;
288                         REPORT_WARNING (("Buffer created with zero length in AML\n"));
289                         break;
290                 }
291
292                 else {
293                         obj_desc->buffer.pointer = ACPI_MEM_CALLOCATE (
294                                            obj_desc->buffer.length);
295
296                         if (!obj_desc->buffer.pointer) {
297                                 return (AE_NO_MEMORY);
298                         }
299                 }
300
301                 /*
302                  * Second arg is the buffer data (optional) Byte_list can be either
303                  * individual bytes or a string initializer.
304                  */
305                 arg = op->value.arg;         /* skip first arg */
306
307                 byte_list = (acpi_parse2_object *) arg->next;
308                 if (byte_list) {
309                         if (byte_list->opcode != AML_INT_BYTELIST_OP) {
310                                 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Expecting bytelist, got: %p\n",
311                                         byte_list));
312                                 return (AE_TYPE);
313                         }
314
315                         MEMCPY (obj_desc->buffer.pointer, byte_list->data,
316                                         obj_desc->buffer.length);
317                 }
318
319                 break;
320
321
322         case ACPI_TYPE_PACKAGE:
323
324                 /*
325                  * When called, an internal package object has already been built and
326                  * is pointed to by Obj_desc. Acpi_ds_build_internal_object builds another
327                  * internal package object, so remove reference to the original so
328                  * that it is deleted.  Error checking is done within the remove
329                  * reference function.
330                  */
331                 acpi_ut_remove_reference (obj_desc);
332                 status = acpi_ds_build_internal_object (walk_state, op, ret_obj_desc);
333                 break;
334
335         case ACPI_TYPE_INTEGER:
336                 obj_desc->integer.value = op->value.integer;
337                 break;
338
339
340         case ACPI_TYPE_STRING:
341                 obj_desc->string.pointer = op->value.string;
342                 obj_desc->string.length = STRLEN (op->value.string);
343
344                 /*
345                  * The string is contained in the ACPI table, don't ever try
346                  * to delete it
347                  */
348                 obj_desc->common.flags |= AOPOBJ_STATIC_POINTER;
349                 break;
350
351
352         case ACPI_TYPE_METHOD:
353                 break;
354
355
356         case INTERNAL_TYPE_REFERENCE:
357
358                 switch (op_info->type) {
359                 case AML_TYPE_LOCAL_VARIABLE:
360
361                         /* Split the opcode into a base opcode + offset */
362
363                         obj_desc->reference.opcode = AML_LOCAL_OP;
364                         obj_desc->reference.offset = opcode - AML_LOCAL_OP;
365                         break;
366
367
368                 case AML_TYPE_METHOD_ARGUMENT:
369
370                         /* Split the opcode into a base opcode + offset */
371
372                         obj_desc->reference.opcode = AML_ARG_OP;
373                         obj_desc->reference.offset = opcode - AML_ARG_OP;
374                         break;
375
376
377                 default: /* Constants, Literals, etc.. */
378
379                         if (op->opcode == AML_INT_NAMEPATH_OP) {
380                                 /* Node was saved in Op */
381
382                                 obj_desc->reference.node = op->node;
383                         }
384
385                         obj_desc->reference.opcode = opcode;
386                         break;
387                 }
388
389                 break;
390
391
392         default:
393
394                 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unimplemented data type: %x\n",
395                         obj_desc->common.type));
396
397                 break;
398         }
399
400         return (AE_OK);
401 }
402
403
404 /*****************************************************************************
405  *
406  * FUNCTION:    Acpi_ds_build_internal_simple_obj
407  *
408  * PARAMETERS:  Op              - Parser object to be translated
409  *              Obj_desc_ptr    - Where the ACPI internal object is returned
410  *
411  * RETURN:      Status
412  *
413  * DESCRIPTION: Translate a parser Op object to the equivalent namespace object
414  *              Simple objects are any objects other than a package object!
415  *
416  ****************************************************************************/
417
418 static acpi_status
419 acpi_ds_build_internal_simple_obj (
420         acpi_walk_state         *walk_state,
421         acpi_parse_object       *op,
422         acpi_operand_object     **obj_desc_ptr)
423 {
424         acpi_operand_object     *obj_desc;
425         acpi_object_type8       type;
426         acpi_status             status;
427         u32                     length;
428         char                    *name;
429
430
431         FUNCTION_TRACE ("Ds_build_internal_simple_obj");
432
433
434         if (op->opcode == AML_INT_NAMEPATH_OP) {
435                 /*
436                  * This is an object reference.  If The name was
437                  * previously looked up in the NS, it is stored in this op.
438                  * Otherwise, go ahead and look it up now
439                  */
440                 if (!op->node) {
441                         status = acpi_ns_lookup (walk_state->scope_info,
442                                           op->value.string, ACPI_TYPE_ANY,
443                                           IMODE_EXECUTE,
444                                           NS_SEARCH_PARENT | NS_DONT_OPEN_SCOPE,
445                                           NULL,
446                                           (acpi_namespace_node **)&(op->node));
447
448                         if (ACPI_FAILURE (status)) {
449                                 if (status == AE_NOT_FOUND) {
450                                         name = NULL;
451                                         acpi_ns_externalize_name (ACPI_UINT32_MAX, op->value.string, &length, &name);
452
453                                         if (name) {
454                                                 REPORT_WARNING (("Reference %s at AML %X not found\n",
455                                                                  name, op->aml_offset));
456                                                 ACPI_MEM_FREE (name);
457                                         }
458
459                                         else {
460                                                 REPORT_WARNING (("Reference %s at AML %X not found\n",
461                                                                    op->value.string, op->aml_offset));
462                                         }
463
464                                         *obj_desc_ptr = NULL;
465                                 }
466
467                                 else {
468                                         return_ACPI_STATUS (status);
469                                 }
470                         }
471                 }
472
473                 /*
474                  * The reference will be a Reference
475                  * TBD: [Restructure] unless we really need a separate
476                  *  type of INTERNAL_TYPE_REFERENCE change
477                  *  Acpi_ds_map_opcode_to_data_type to handle this case
478                  */
479                 type = INTERNAL_TYPE_REFERENCE;
480         }
481         else {
482                 type = acpi_ds_map_opcode_to_data_type (op->opcode, NULL);
483         }
484
485
486         /* Create and init the internal ACPI object */
487
488         obj_desc = acpi_ut_create_internal_object (type);
489         if (!obj_desc) {
490                 return_ACPI_STATUS (AE_NO_MEMORY);
491         }
492
493         status = acpi_ds_init_object_from_op (walk_state, op, op->opcode, &obj_desc);
494         if (ACPI_FAILURE (status)) {
495                 acpi_ut_remove_reference (obj_desc);
496                 return_ACPI_STATUS (status);
497         }
498
499         *obj_desc_ptr = obj_desc;
500
501         return_ACPI_STATUS (AE_OK);
502 }
503
504
505 /*****************************************************************************
506  *
507  * FUNCTION:    Acpi_ds_build_internal_package_obj
508  *
509  * PARAMETERS:  Op              - Parser object to be translated
510  *              Obj_desc_ptr    - Where the ACPI internal object is returned
511  *
512  * RETURN:      Status
513  *
514  * DESCRIPTION: Translate a parser Op package object to the equivalent
515  *              namespace object
516  *
517  ****************************************************************************/
518
519 acpi_status
520 acpi_ds_build_internal_package_obj (
521         acpi_walk_state         *walk_state,
522         acpi_parse_object       *op,
523         acpi_operand_object     **obj_desc_ptr)
524 {
525         acpi_parse_object       *arg;
526         acpi_operand_object     *obj_desc;
527         acpi_status             status = AE_OK;
528
529
530         FUNCTION_TRACE ("Ds_build_internal_package_obj");
531
532
533         obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_PACKAGE);
534         *obj_desc_ptr = obj_desc;
535         if (!obj_desc) {
536                 return_ACPI_STATUS (AE_NO_MEMORY);
537         }
538
539         if (op->opcode == AML_VAR_PACKAGE_OP) {
540                 /*
541                  * Variable length package parameters are evaluated JIT
542                  */
543                 return_ACPI_STATUS (AE_OK);
544         }
545
546         /* The first argument must be the package length */
547
548         arg = op->value.arg;
549         obj_desc->package.count = arg->value.integer32;
550
551         /*
552          * Allocate the array of pointers (ptrs to the
553          * individual objects) Add an extra pointer slot so
554          * that the list is always null terminated.
555          */
556         obj_desc->package.elements = ACPI_MEM_CALLOCATE (
557                          (obj_desc->package.count + 1) * sizeof (void *));
558
559         if (!obj_desc->package.elements) {
560                 acpi_ut_delete_object_desc (obj_desc);
561                 return_ACPI_STATUS (AE_NO_MEMORY);
562         }
563
564         obj_desc->package.next_element = obj_desc->package.elements;
565
566         /*
567          * Now init the elements of the package
568          */
569         arg = arg->next;
570         while (arg) {
571                 if (arg->opcode == AML_PACKAGE_OP) {
572                         status = acpi_ds_build_internal_package_obj (walk_state, arg,
573                                           obj_desc->package.next_element);
574                 }
575
576                 else {
577                         status = acpi_ds_build_internal_simple_obj (walk_state, arg,
578                                           obj_desc->package.next_element);
579                 }
580
581                 obj_desc->package.next_element++;
582                 arg = arg->next;
583         }
584
585         obj_desc->package.flags |= AOPOBJ_DATA_VALID;
586         return_ACPI_STATUS (status);
587 }
588
589
590 /*****************************************************************************
591  *
592  * FUNCTION:    Acpi_ds_build_internal_object
593  *
594  * PARAMETERS:  Op              - Parser object to be translated
595  *              Obj_desc_ptr    - Where the ACPI internal object is returned
596  *
597  * RETURN:      Status
598  *
599  * DESCRIPTION: Translate a parser Op object to the equivalent namespace
600  *              object
601  *
602  ****************************************************************************/
603
604 acpi_status
605 acpi_ds_build_internal_object (
606         acpi_walk_state         *walk_state,
607         acpi_parse_object       *op,
608         acpi_operand_object     **obj_desc_ptr)
609 {
610         acpi_status             status;
611
612
613         switch (op->opcode) {
614         case AML_PACKAGE_OP:
615         case AML_VAR_PACKAGE_OP:
616
617                 status = acpi_ds_build_internal_package_obj (walk_state, op, obj_desc_ptr);
618                 break;
619
620
621         default:
622
623                 status = acpi_ds_build_internal_simple_obj (walk_state, op, obj_desc_ptr);
624                 break;
625         }
626
627         return (status);
628 }
629
630
631 /*****************************************************************************
632  *
633  * FUNCTION:    Acpi_ds_create_node
634  *
635  * PARAMETERS:  Op              - Parser object to be translated
636  *              Obj_desc_ptr    - Where the ACPI internal object is returned
637  *
638  * RETURN:      Status
639  *
640  * DESCRIPTION:
641  *
642  ****************************************************************************/
643
644 acpi_status
645 acpi_ds_create_node (
646         acpi_walk_state         *walk_state,
647         acpi_namespace_node     *node,
648         acpi_parse_object       *op)
649 {
650         acpi_status             status;
651         acpi_operand_object     *obj_desc;
652
653
654         FUNCTION_TRACE_PTR ("Ds_create_node", op);
655
656
657         /*
658          * Because of the execution pass through the non-control-method
659          * parts of the table, we can arrive here twice.  Only init
660          * the named object node the first time through
661          */
662         if (node->object) {
663                 return_ACPI_STATUS (AE_OK);
664         }
665
666         if (!op->value.arg) {
667                 /* No arguments, there is nothing to do */
668
669                 return_ACPI_STATUS (AE_OK);
670         }
671
672         /* Build an internal object for the argument(s) */
673
674         status = acpi_ds_build_internal_object (walk_state, op->value.arg, &obj_desc);
675         if (ACPI_FAILURE (status)) {
676                 return_ACPI_STATUS (status);
677         }
678
679         /* Re-type the object according to it's argument */
680
681         node->type = obj_desc->common.type;
682
683         /* Init obj */
684
685         status = acpi_ns_attach_object (node, obj_desc, (u8) node->type);
686
687         /* Remove local reference to the object */
688
689         acpi_ut_remove_reference (obj_desc);
690         return_ACPI_STATUS (status);
691 }
692
693