[ACPI] increase MAX_IO_APICS to 64 on i386
[deliverable/linux.git] / drivers / acpi / dispatcher / dsobject.c
CommitLineData
1da177e4
LT
1/******************************************************************************
2 *
3 * Module Name: dsobject - Dispatcher object management routines
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2005, R. Byron Moore
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44
45#include <acpi/acpi.h>
46#include <acpi/acparser.h>
47#include <acpi/amlcode.h>
48#include <acpi/acdispat.h>
49#include <acpi/acnamesp.h>
50#include <acpi/acinterp.h>
51
52#define _COMPONENT ACPI_DISPATCHER
53 ACPI_MODULE_NAME ("dsobject")
54
44f6c012
RM
55static acpi_status
56acpi_ds_build_internal_object (
57 struct acpi_walk_state *walk_state,
58 union acpi_parse_object *op,
59 union acpi_operand_object **obj_desc_ptr);
60
1da177e4
LT
61
62#ifndef ACPI_NO_METHOD_EXECUTION
44f6c012 63/*******************************************************************************
1da177e4
LT
64 *
65 * FUNCTION: acpi_ds_build_internal_object
66 *
67 * PARAMETERS: walk_state - Current walk state
68 * Op - Parser object to be translated
69 * obj_desc_ptr - Where the ACPI internal object is returned
70 *
71 * RETURN: Status
72 *
73 * DESCRIPTION: Translate a parser Op object to the equivalent namespace object
74 * Simple objects are any objects other than a package object!
75 *
44f6c012 76 ******************************************************************************/
1da177e4 77
44f6c012 78static acpi_status
1da177e4
LT
79acpi_ds_build_internal_object (
80 struct acpi_walk_state *walk_state,
81 union acpi_parse_object *op,
82 union acpi_operand_object **obj_desc_ptr)
83{
84 union acpi_operand_object *obj_desc;
85 acpi_status status;
86
87
88 ACPI_FUNCTION_TRACE ("ds_build_internal_object");
89
90
91 *obj_desc_ptr = NULL;
92 if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
93 /*
94 * This is an named object reference. If this name was
95 * previously looked up in the namespace, it was stored in this op.
96 * Otherwise, go ahead and look it up now
97 */
98 if (!op->common.node) {
44f6c012
RM
99 status = acpi_ns_lookup (walk_state->scope_info,
100 op->common.value.string,
1da177e4 101 ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
44f6c012
RM
102 ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
103 NULL,
1da177e4
LT
104 (struct acpi_namespace_node **) &(op->common.node));
105
106 if (ACPI_FAILURE (status)) {
107 ACPI_REPORT_NSERROR (op->common.value.string, status);
108 return_ACPI_STATUS (status);
109 }
110 }
111 }
112
113 /* Create and init the internal ACPI object */
114
44f6c012
RM
115 obj_desc = acpi_ut_create_internal_object (
116 (acpi_ps_get_opcode_info (op->common.aml_opcode))->object_type);
1da177e4
LT
117 if (!obj_desc) {
118 return_ACPI_STATUS (AE_NO_MEMORY);
119 }
120
44f6c012
RM
121 status = acpi_ds_init_object_from_op (walk_state, op, op->common.aml_opcode,
122 &obj_desc);
1da177e4
LT
123 if (ACPI_FAILURE (status)) {
124 acpi_ut_remove_reference (obj_desc);
125 return_ACPI_STATUS (status);
126 }
127
128 *obj_desc_ptr = obj_desc;
129 return_ACPI_STATUS (AE_OK);
130}
131
132
44f6c012 133/*******************************************************************************
1da177e4
LT
134 *
135 * FUNCTION: acpi_ds_build_internal_buffer_obj
136 *
137 * PARAMETERS: walk_state - Current walk state
138 * Op - Parser object to be translated
139 * buffer_length - Length of the buffer
140 * obj_desc_ptr - Where the ACPI internal object is returned
141 *
142 * RETURN: Status
143 *
144 * DESCRIPTION: Translate a parser Op package object to the equivalent
145 * namespace object
146 *
44f6c012 147 ******************************************************************************/
1da177e4
LT
148
149acpi_status
150acpi_ds_build_internal_buffer_obj (
151 struct acpi_walk_state *walk_state,
152 union acpi_parse_object *op,
153 u32 buffer_length,
154 union acpi_operand_object **obj_desc_ptr)
155{
156 union acpi_parse_object *arg;
157 union acpi_operand_object *obj_desc;
158 union acpi_parse_object *byte_list;
159 u32 byte_list_length = 0;
160
161
162 ACPI_FUNCTION_TRACE ("ds_build_internal_buffer_obj");
163
164
165 obj_desc = *obj_desc_ptr;
166 if (obj_desc) {
167 /*
168 * We are evaluating a Named buffer object "Name (xxxx, Buffer)".
169 * The buffer object already exists (from the NS node)
170 */
171 }
172 else {
173 /* Create a new buffer object */
174
175 obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_BUFFER);
176 *obj_desc_ptr = obj_desc;
177 if (!obj_desc) {
178 return_ACPI_STATUS (AE_NO_MEMORY);
179 }
180 }
181
182 /*
183 * Second arg is the buffer data (optional) byte_list can be either
184 * individual bytes or a string initializer. In either case, a
185 * byte_list appears in the AML.
186 */
187 arg = op->common.value.arg; /* skip first arg */
188
189 byte_list = arg->named.next;
190 if (byte_list) {
191 if (byte_list->common.aml_opcode != AML_INT_BYTELIST_OP) {
192 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
193 "Expecting bytelist, got AML opcode %X in op %p\n",
194 byte_list->common.aml_opcode, byte_list));
195
196 acpi_ut_remove_reference (obj_desc);
197 return (AE_TYPE);
198 }
199
200 byte_list_length = (u32) byte_list->common.value.integer;
201 }
202
203 /*
204 * The buffer length (number of bytes) will be the larger of:
205 * 1) The specified buffer length and
206 * 2) The length of the initializer byte list
207 */
208 obj_desc->buffer.length = buffer_length;
209 if (byte_list_length > buffer_length) {
210 obj_desc->buffer.length = byte_list_length;
211 }
212
213 /* Allocate the buffer */
214
215 if (obj_desc->buffer.length == 0) {
216 obj_desc->buffer.pointer = NULL;
217 ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
218 "Buffer defined with zero length in AML, creating\n"));
219 }
220 else {
221 obj_desc->buffer.pointer = ACPI_MEM_CALLOCATE (
222 obj_desc->buffer.length);
223 if (!obj_desc->buffer.pointer) {
224 acpi_ut_delete_object_desc (obj_desc);
225 return_ACPI_STATUS (AE_NO_MEMORY);
226 }
227
228 /* Initialize buffer from the byte_list (if present) */
229
230 if (byte_list) {
231 ACPI_MEMCPY (obj_desc->buffer.pointer, byte_list->named.data,
232 byte_list_length);
233 }
234 }
235
236 obj_desc->buffer.flags |= AOPOBJ_DATA_VALID;
237 op->common.node = (struct acpi_namespace_node *) obj_desc;
238 return_ACPI_STATUS (AE_OK);
239}
240
241
44f6c012 242/*******************************************************************************
1da177e4
LT
243 *
244 * FUNCTION: acpi_ds_build_internal_package_obj
245 *
246 * PARAMETERS: walk_state - Current walk state
247 * Op - Parser object to be translated
248 * package_length - Number of elements in the package
249 * obj_desc_ptr - Where the ACPI internal object is returned
250 *
251 * RETURN: Status
252 *
253 * DESCRIPTION: Translate a parser Op package object to the equivalent
254 * namespace object
255 *
44f6c012 256 ******************************************************************************/
1da177e4
LT
257
258acpi_status
259acpi_ds_build_internal_package_obj (
260 struct acpi_walk_state *walk_state,
261 union acpi_parse_object *op,
262 u32 package_length,
263 union acpi_operand_object **obj_desc_ptr)
264{
265 union acpi_parse_object *arg;
266 union acpi_parse_object *parent;
267 union acpi_operand_object *obj_desc = NULL;
268 u32 package_list_length;
269 acpi_status status = AE_OK;
270 u32 i;
271
272
273 ACPI_FUNCTION_TRACE ("ds_build_internal_package_obj");
274
275
276 /* Find the parent of a possibly nested package */
277
278 parent = op->common.parent;
279 while ((parent->common.aml_opcode == AML_PACKAGE_OP) ||
280 (parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) {
281 parent = parent->common.parent;
282 }
283
284 obj_desc = *obj_desc_ptr;
285 if (obj_desc) {
286 /*
287 * We are evaluating a Named package object "Name (xxxx, Package)".
288 * Get the existing package object from the NS node
289 */
290 }
291 else {
292 obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_PACKAGE);
293 *obj_desc_ptr = obj_desc;
294 if (!obj_desc) {
295 return_ACPI_STATUS (AE_NO_MEMORY);
296 }
297
298 obj_desc->package.node = parent->common.node;
299 }
300
301 obj_desc->package.count = package_length;
302
303 /* Count the number of items in the package list */
304
305 package_list_length = 0;
306 arg = op->common.value.arg;
307 arg = arg->common.next;
308 while (arg) {
309 package_list_length++;
310 arg = arg->common.next;
311 }
312
313 /*
314 * The package length (number of elements) will be the greater
315 * of the specified length and the length of the initializer list
316 */
317 if (package_list_length > package_length) {
318 obj_desc->package.count = package_list_length;
319 }
320
321 /*
322 * Allocate the pointer array (array of pointers to the
323 * individual objects). Add an extra pointer slot so
324 * that the list is always null terminated.
325 */
326 obj_desc->package.elements = ACPI_MEM_CALLOCATE (
327 ((acpi_size) obj_desc->package.count + 1) * sizeof (void *));
328
329 if (!obj_desc->package.elements) {
330 acpi_ut_delete_object_desc (obj_desc);
331 return_ACPI_STATUS (AE_NO_MEMORY);
332 }
333
334 /*
335 * Now init the elements of the package
336 */
337 i = 0;
338 arg = op->common.value.arg;
339 arg = arg->common.next;
340 while (arg) {
341 if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) {
342 /* Object (package or buffer) is already built */
343
44f6c012
RM
344 obj_desc->package.elements[i] =
345 ACPI_CAST_PTR (union acpi_operand_object, arg->common.node);
1da177e4
LT
346 }
347 else {
348 status = acpi_ds_build_internal_object (walk_state, arg,
44f6c012 349 &obj_desc->package.elements[i]);
1da177e4
LT
350 }
351
352 i++;
353 arg = arg->common.next;
354 }
355
356 obj_desc->package.flags |= AOPOBJ_DATA_VALID;
357 op->common.node = (struct acpi_namespace_node *) obj_desc;
358 return_ACPI_STATUS (status);
359}
360
361
44f6c012 362/*******************************************************************************
1da177e4
LT
363 *
364 * FUNCTION: acpi_ds_create_node
365 *
366 * PARAMETERS: walk_state - Current walk state
367 * Node - NS Node to be initialized
368 * Op - Parser object to be translated
369 *
370 * RETURN: Status
371 *
372 * DESCRIPTION: Create the object to be associated with a namespace node
373 *
44f6c012 374 ******************************************************************************/
1da177e4
LT
375
376acpi_status
377acpi_ds_create_node (
378 struct acpi_walk_state *walk_state,
379 struct acpi_namespace_node *node,
380 union acpi_parse_object *op)
381{
382 acpi_status status;
383 union acpi_operand_object *obj_desc;
384
385
386 ACPI_FUNCTION_TRACE_PTR ("ds_create_node", op);
387
388
389 /*
390 * Because of the execution pass through the non-control-method
391 * parts of the table, we can arrive here twice. Only init
392 * the named object node the first time through
393 */
394 if (acpi_ns_get_attached_object (node)) {
395 return_ACPI_STATUS (AE_OK);
396 }
397
398 if (!op->common.value.arg) {
399 /* No arguments, there is nothing to do */
400
401 return_ACPI_STATUS (AE_OK);
402 }
403
404 /* Build an internal object for the argument(s) */
405
44f6c012
RM
406 status = acpi_ds_build_internal_object (walk_state, op->common.value.arg,
407 &obj_desc);
1da177e4
LT
408 if (ACPI_FAILURE (status)) {
409 return_ACPI_STATUS (status);
410 }
411
412 /* Re-type the object according to its argument */
413
414 node->type = ACPI_GET_OBJECT_TYPE (obj_desc);
415
416 /* Attach obj to node */
417
418 status = acpi_ns_attach_object (node, obj_desc, node->type);
419
420 /* Remove local reference to the object */
421
422 acpi_ut_remove_reference (obj_desc);
423 return_ACPI_STATUS (status);
424}
425
426#endif /* ACPI_NO_METHOD_EXECUTION */
427
428
44f6c012 429/*******************************************************************************
1da177e4
LT
430 *
431 * FUNCTION: acpi_ds_init_object_from_op
432 *
433 * PARAMETERS: walk_state - Current walk state
434 * Op - Parser op used to init the internal object
435 * Opcode - AML opcode associated with the object
436 * ret_obj_desc - Namespace object to be initialized
437 *
438 * RETURN: Status
439 *
440 * DESCRIPTION: Initialize a namespace object from a parser Op and its
441 * associated arguments. The namespace object is a more compact
442 * representation of the Op and its arguments.
443 *
44f6c012 444 ******************************************************************************/
1da177e4
LT
445
446acpi_status
447acpi_ds_init_object_from_op (
448 struct acpi_walk_state *walk_state,
449 union acpi_parse_object *op,
450 u16 opcode,
451 union acpi_operand_object **ret_obj_desc)
452{
453 const struct acpi_opcode_info *op_info;
454 union acpi_operand_object *obj_desc;
455 acpi_status status = AE_OK;
456
457
458 ACPI_FUNCTION_TRACE ("ds_init_object_from_op");
459
460
461 obj_desc = *ret_obj_desc;
462 op_info = acpi_ps_get_opcode_info (opcode);
463 if (op_info->class == AML_CLASS_UNKNOWN) {
464 /* Unknown opcode */
465
466 return_ACPI_STATUS (AE_TYPE);
467 }
468
469 /* Perform per-object initialization */
470
471 switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
472 case ACPI_TYPE_BUFFER:
473
474 /*
475 * Defer evaluation of Buffer term_arg operand
476 */
44f6c012
RM
477 obj_desc->buffer.node = (struct acpi_namespace_node *)
478 walk_state->operands[0];
1da177e4
LT
479 obj_desc->buffer.aml_start = op->named.data;
480 obj_desc->buffer.aml_length = op->named.length;
481 break;
482
483
484 case ACPI_TYPE_PACKAGE:
485
486 /*
487 * Defer evaluation of Package term_arg operand
488 */
44f6c012
RM
489 obj_desc->package.node = (struct acpi_namespace_node *)
490 walk_state->operands[0];
1da177e4
LT
491 obj_desc->package.aml_start = op->named.data;
492 obj_desc->package.aml_length = op->named.length;
493 break;
494
495
496 case ACPI_TYPE_INTEGER:
497
498 switch (op_info->type) {
499 case AML_TYPE_CONSTANT:
500 /*
501 * Resolve AML Constants here - AND ONLY HERE!
502 * All constants are integers.
44f6c012
RM
503 * We mark the integer with a flag that indicates that it started
504 * life as a constant -- so that stores to constants will perform
505 * as expected (noop). zero_op is used as a placeholder for optional
506 * target operands.
1da177e4
LT
507 */
508 obj_desc->common.flags = AOPOBJ_AML_CONSTANT;
509
510 switch (opcode) {
511 case AML_ZERO_OP:
512
513 obj_desc->integer.value = 0;
514 break;
515
516 case AML_ONE_OP:
517
518 obj_desc->integer.value = 1;
519 break;
520
521 case AML_ONES_OP:
522
523 obj_desc->integer.value = ACPI_INTEGER_MAX;
524
525 /* Truncate value if we are executing from a 32-bit ACPI table */
526
527#ifndef ACPI_NO_METHOD_EXECUTION
528 acpi_ex_truncate_for32bit_table (obj_desc);
529#endif
530 break;
531
532 case AML_REVISION_OP:
533
534 obj_desc->integer.value = ACPI_CA_VERSION;
535 break;
536
537 default:
538
44f6c012
RM
539 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
540 "Unknown constant opcode %X\n", opcode));
1da177e4
LT
541 status = AE_AML_OPERAND_TYPE;
542 break;
543 }
544 break;
545
546
547 case AML_TYPE_LITERAL:
548
549 obj_desc->integer.value = op->common.value.integer;
550 break;
551
552
553 default:
44f6c012
RM
554 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unknown Integer type %X\n",
555 op_info->type));
1da177e4
LT
556 status = AE_AML_OPERAND_TYPE;
557 break;
558 }
559 break;
560
561
562 case ACPI_TYPE_STRING:
563
564 obj_desc->string.pointer = op->common.value.string;
565 obj_desc->string.length = (u32) ACPI_STRLEN (op->common.value.string);
566
567 /*
568 * The string is contained in the ACPI table, don't ever try
569 * to delete it
570 */
571 obj_desc->common.flags |= AOPOBJ_STATIC_POINTER;
572 break;
573
574
575 case ACPI_TYPE_METHOD:
576 break;
577
578
579 case ACPI_TYPE_LOCAL_REFERENCE:
580
581 switch (op_info->type) {
582 case AML_TYPE_LOCAL_VARIABLE:
583
584 /* Split the opcode into a base opcode + offset */
585
586 obj_desc->reference.opcode = AML_LOCAL_OP;
587 obj_desc->reference.offset = opcode - AML_LOCAL_OP;
588
589#ifndef ACPI_NO_METHOD_EXECUTION
44f6c012
RM
590 status = acpi_ds_method_data_get_node (AML_LOCAL_OP,
591 obj_desc->reference.offset,
592 walk_state,
593 (struct acpi_namespace_node **) &obj_desc->reference.object);
1da177e4
LT
594#endif
595 break;
596
597
598 case AML_TYPE_METHOD_ARGUMENT:
599
600 /* Split the opcode into a base opcode + offset */
601
602 obj_desc->reference.opcode = AML_ARG_OP;
603 obj_desc->reference.offset = opcode - AML_ARG_OP;
604
605#ifndef ACPI_NO_METHOD_EXECUTION
44f6c012
RM
606 status = acpi_ds_method_data_get_node (AML_ARG_OP,
607 obj_desc->reference.offset,
608 walk_state,
609 (struct acpi_namespace_node **) &obj_desc->reference.object);
1da177e4
LT
610#endif
611 break;
612
613 default: /* Other literals, etc.. */
614
615 if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
616 /* Node was saved in Op */
617
618 obj_desc->reference.node = op->common.node;
619 }
620
621 obj_desc->reference.opcode = opcode;
622 break;
623 }
624 break;
625
626
627 default:
628
629 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Unimplemented data type: %X\n",
630 ACPI_GET_OBJECT_TYPE (obj_desc)));
631
632 status = AE_AML_OPERAND_TYPE;
633 break;
634 }
635
636 return_ACPI_STATUS (status);
637}
638
639
This page took 0.084173 seconds and 5 git commands to generate.