]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/acpi/executer/excreate.c
NOMMU: Support XIP on initramfs
[linux-2.6-omap-h63xx.git] / drivers / acpi / executer / excreate.c
1 /******************************************************************************
2  *
3  * Module Name: excreate - Named object creation
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2008, Intel Corp.
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 #include <acpi/acpi.h>
45 #include <acpi/acinterp.h>
46 #include <acpi/amlcode.h>
47 #include <acpi/acnamesp.h>
48
49 #define _COMPONENT          ACPI_EXECUTER
50 ACPI_MODULE_NAME("excreate")
51 #ifndef ACPI_NO_METHOD_EXECUTION
52 /*******************************************************************************
53  *
54  * FUNCTION:    acpi_ex_create_alias
55  *
56  * PARAMETERS:  walk_state           - Current state, contains operands
57  *
58  * RETURN:      Status
59  *
60  * DESCRIPTION: Create a new named alias
61  *
62  ******************************************************************************/
63 acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state)
64 {
65         struct acpi_namespace_node *target_node;
66         struct acpi_namespace_node *alias_node;
67         acpi_status status = AE_OK;
68
69         ACPI_FUNCTION_TRACE(ex_create_alias);
70
71         /* Get the source/alias operands (both namespace nodes) */
72
73         alias_node = (struct acpi_namespace_node *)walk_state->operands[0];
74         target_node = (struct acpi_namespace_node *)walk_state->operands[1];
75
76         if ((target_node->type == ACPI_TYPE_LOCAL_ALIAS) ||
77             (target_node->type == ACPI_TYPE_LOCAL_METHOD_ALIAS)) {
78                 /*
79                  * Dereference an existing alias so that we don't create a chain
80                  * of aliases.  With this code, we guarantee that an alias is
81                  * always exactly one level of indirection away from the
82                  * actual aliased name.
83                  */
84                 target_node =
85                     ACPI_CAST_PTR(struct acpi_namespace_node,
86                                   target_node->object);
87         }
88
89         /*
90          * For objects that can never change (i.e., the NS node will
91          * permanently point to the same object), we can simply attach
92          * the object to the new NS node.  For other objects (such as
93          * Integers, buffers, etc.), we have to point the Alias node
94          * to the original Node.
95          */
96         switch (target_node->type) {
97
98                 /* For these types, the sub-object can change dynamically via a Store */
99
100         case ACPI_TYPE_INTEGER:
101         case ACPI_TYPE_STRING:
102         case ACPI_TYPE_BUFFER:
103         case ACPI_TYPE_PACKAGE:
104         case ACPI_TYPE_BUFFER_FIELD:
105
106                 /*
107                  * These types open a new scope, so we need the NS node in order to access
108                  * any children.
109                  */
110         case ACPI_TYPE_DEVICE:
111         case ACPI_TYPE_POWER:
112         case ACPI_TYPE_PROCESSOR:
113         case ACPI_TYPE_THERMAL:
114         case ACPI_TYPE_LOCAL_SCOPE:
115
116                 /*
117                  * The new alias has the type ALIAS and points to the original
118                  * NS node, not the object itself.
119                  */
120                 alias_node->type = ACPI_TYPE_LOCAL_ALIAS;
121                 alias_node->object =
122                     ACPI_CAST_PTR(union acpi_operand_object, target_node);
123                 break;
124
125         case ACPI_TYPE_METHOD:
126
127                 /*
128                  * Control method aliases need to be differentiated
129                  */
130                 alias_node->type = ACPI_TYPE_LOCAL_METHOD_ALIAS;
131                 alias_node->object =
132                     ACPI_CAST_PTR(union acpi_operand_object, target_node);
133                 break;
134
135         default:
136
137                 /* Attach the original source object to the new Alias Node */
138
139                 /*
140                  * The new alias assumes the type of the target, and it points
141                  * to the same object.  The reference count of the object has an
142                  * additional reference to prevent deletion out from under either the
143                  * target node or the alias Node
144                  */
145                 status = acpi_ns_attach_object(alias_node,
146                                                acpi_ns_get_attached_object
147                                                (target_node),
148                                                target_node->type);
149                 break;
150         }
151
152         /* Since both operands are Nodes, we don't need to delete them */
153
154         return_ACPI_STATUS(status);
155 }
156
157 /*******************************************************************************
158  *
159  * FUNCTION:    acpi_ex_create_event
160  *
161  * PARAMETERS:  walk_state          - Current state
162  *
163  * RETURN:      Status
164  *
165  * DESCRIPTION: Create a new event object
166  *
167  ******************************************************************************/
168
169 acpi_status acpi_ex_create_event(struct acpi_walk_state *walk_state)
170 {
171         acpi_status status;
172         union acpi_operand_object *obj_desc;
173
174         ACPI_FUNCTION_TRACE(ex_create_event);
175
176         obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_EVENT);
177         if (!obj_desc) {
178                 status = AE_NO_MEMORY;
179                 goto cleanup;
180         }
181
182         /*
183          * Create the actual OS semaphore, with zero initial units -- meaning
184          * that the event is created in an unsignalled state
185          */
186         status = acpi_os_create_semaphore(ACPI_NO_UNIT_LIMIT, 0,
187                                           &obj_desc->event.os_semaphore);
188         if (ACPI_FAILURE(status)) {
189                 goto cleanup;
190         }
191
192         /* Attach object to the Node */
193
194         status =
195             acpi_ns_attach_object((struct acpi_namespace_node *)walk_state->
196                                   operands[0], obj_desc, ACPI_TYPE_EVENT);
197
198       cleanup:
199         /*
200          * Remove local reference to the object (on error, will cause deletion
201          * of both object and semaphore if present.)
202          */
203         acpi_ut_remove_reference(obj_desc);
204         return_ACPI_STATUS(status);
205 }
206
207 /*******************************************************************************
208  *
209  * FUNCTION:    acpi_ex_create_mutex
210  *
211  * PARAMETERS:  walk_state          - Current state
212  *
213  * RETURN:      Status
214  *
215  * DESCRIPTION: Create a new mutex object
216  *
217  *              Mutex (Name[0], sync_level[1])
218  *
219  ******************************************************************************/
220
221 acpi_status acpi_ex_create_mutex(struct acpi_walk_state *walk_state)
222 {
223         acpi_status status = AE_OK;
224         union acpi_operand_object *obj_desc;
225
226         ACPI_FUNCTION_TRACE_PTR(ex_create_mutex, ACPI_WALK_OPERANDS);
227
228         /* Create the new mutex object */
229
230         obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_MUTEX);
231         if (!obj_desc) {
232                 status = AE_NO_MEMORY;
233                 goto cleanup;
234         }
235
236         /* Create the actual OS Mutex */
237
238         status = acpi_os_create_mutex(&obj_desc->mutex.os_mutex);
239         if (ACPI_FAILURE(status)) {
240                 goto cleanup;
241         }
242
243         /* Init object and attach to NS node */
244
245         obj_desc->mutex.sync_level =
246             (u8) walk_state->operands[1]->integer.value;
247         obj_desc->mutex.node =
248             (struct acpi_namespace_node *)walk_state->operands[0];
249
250         status =
251             acpi_ns_attach_object(obj_desc->mutex.node, obj_desc,
252                                   ACPI_TYPE_MUTEX);
253
254       cleanup:
255         /*
256          * Remove local reference to the object (on error, will cause deletion
257          * of both object and semaphore if present.)
258          */
259         acpi_ut_remove_reference(obj_desc);
260         return_ACPI_STATUS(status);
261 }
262
263 /*******************************************************************************
264  *
265  * FUNCTION:    acpi_ex_create_region
266  *
267  * PARAMETERS:  aml_start           - Pointer to the region declaration AML
268  *              aml_length          - Max length of the declaration AML
269  *              region_space        - space_iD for the region
270  *              walk_state          - Current state
271  *
272  * RETURN:      Status
273  *
274  * DESCRIPTION: Create a new operation region object
275  *
276  ******************************************************************************/
277
278 acpi_status
279 acpi_ex_create_region(u8 * aml_start,
280                       u32 aml_length,
281                       u8 region_space, struct acpi_walk_state *walk_state)
282 {
283         acpi_status status;
284         union acpi_operand_object *obj_desc;
285         struct acpi_namespace_node *node;
286         union acpi_operand_object *region_obj2;
287
288         ACPI_FUNCTION_TRACE(ex_create_region);
289
290         /* Get the Namespace Node */
291
292         node = walk_state->op->common.node;
293
294         /*
295          * If the region object is already attached to this node,
296          * just return
297          */
298         if (acpi_ns_get_attached_object(node)) {
299                 return_ACPI_STATUS(AE_OK);
300         }
301
302         /*
303          * Space ID must be one of the predefined IDs, or in the user-defined
304          * range
305          */
306         if ((region_space >= ACPI_NUM_PREDEFINED_REGIONS) &&
307             (region_space < ACPI_USER_REGION_BEGIN)) {
308                 ACPI_ERROR((AE_INFO, "Invalid AddressSpace type %X",
309                             region_space));
310                 return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID);
311         }
312
313         ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Region Type - %s (%X)\n",
314                           acpi_ut_get_region_name(region_space), region_space));
315
316         /* Create the region descriptor */
317
318         obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_REGION);
319         if (!obj_desc) {
320                 status = AE_NO_MEMORY;
321                 goto cleanup;
322         }
323
324         /*
325          * Remember location in AML stream of address & length
326          * operands since they need to be evaluated at run time.
327          */
328         region_obj2 = obj_desc->common.next_object;
329         region_obj2->extra.aml_start = aml_start;
330         region_obj2->extra.aml_length = aml_length;
331
332         /* Init the region from the operands */
333
334         obj_desc->region.space_id = region_space;
335         obj_desc->region.address = 0;
336         obj_desc->region.length = 0;
337         obj_desc->region.node = node;
338
339         /* Install the new region object in the parent Node */
340
341         status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_REGION);
342
343       cleanup:
344
345         /* Remove local reference to the object */
346
347         acpi_ut_remove_reference(obj_desc);
348         return_ACPI_STATUS(status);
349 }
350
351 /*******************************************************************************
352  *
353  * FUNCTION:    acpi_ex_create_processor
354  *
355  * PARAMETERS:  walk_state          - Current state
356  *
357  * RETURN:      Status
358  *
359  * DESCRIPTION: Create a new processor object and populate the fields
360  *
361  *              Processor (Name[0], cpu_iD[1], pblock_addr[2], pblock_length[3])
362  *
363  ******************************************************************************/
364
365 acpi_status acpi_ex_create_processor(struct acpi_walk_state *walk_state)
366 {
367         union acpi_operand_object **operand = &walk_state->operands[0];
368         union acpi_operand_object *obj_desc;
369         acpi_status status;
370
371         ACPI_FUNCTION_TRACE_PTR(ex_create_processor, walk_state);
372
373         /* Create the processor object */
374
375         obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_PROCESSOR);
376         if (!obj_desc) {
377                 return_ACPI_STATUS(AE_NO_MEMORY);
378         }
379
380         /* Initialize the processor object from the operands */
381
382         obj_desc->processor.proc_id = (u8) operand[1]->integer.value;
383         obj_desc->processor.length = (u8) operand[3]->integer.value;
384         obj_desc->processor.address =
385             (acpi_io_address) operand[2]->integer.value;
386
387         /* Install the processor object in the parent Node */
388
389         status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0],
390                                        obj_desc, ACPI_TYPE_PROCESSOR);
391
392         /* Remove local reference to the object */
393
394         acpi_ut_remove_reference(obj_desc);
395         return_ACPI_STATUS(status);
396 }
397
398 /*******************************************************************************
399  *
400  * FUNCTION:    acpi_ex_create_power_resource
401  *
402  * PARAMETERS:  walk_state          - Current state
403  *
404  * RETURN:      Status
405  *
406  * DESCRIPTION: Create a new power_resource object and populate the fields
407  *
408  *              power_resource (Name[0], system_level[1], resource_order[2])
409  *
410  ******************************************************************************/
411
412 acpi_status acpi_ex_create_power_resource(struct acpi_walk_state *walk_state)
413 {
414         union acpi_operand_object **operand = &walk_state->operands[0];
415         acpi_status status;
416         union acpi_operand_object *obj_desc;
417
418         ACPI_FUNCTION_TRACE_PTR(ex_create_power_resource, walk_state);
419
420         /* Create the power resource object */
421
422         obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_POWER);
423         if (!obj_desc) {
424                 return_ACPI_STATUS(AE_NO_MEMORY);
425         }
426
427         /* Initialize the power object from the operands */
428
429         obj_desc->power_resource.system_level = (u8) operand[1]->integer.value;
430         obj_desc->power_resource.resource_order =
431             (u16) operand[2]->integer.value;
432
433         /* Install the  power resource object in the parent Node */
434
435         status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0],
436                                        obj_desc, ACPI_TYPE_POWER);
437
438         /* Remove local reference to the object */
439
440         acpi_ut_remove_reference(obj_desc);
441         return_ACPI_STATUS(status);
442 }
443 #endif
444
445 /*******************************************************************************
446  *
447  * FUNCTION:    acpi_ex_create_method
448  *
449  * PARAMETERS:  aml_start       - First byte of the method's AML
450  *              aml_length      - AML byte count for this method
451  *              walk_state      - Current state
452  *
453  * RETURN:      Status
454  *
455  * DESCRIPTION: Create a new method object
456  *
457  ******************************************************************************/
458
459 acpi_status
460 acpi_ex_create_method(u8 * aml_start,
461                       u32 aml_length, struct acpi_walk_state *walk_state)
462 {
463         union acpi_operand_object **operand = &walk_state->operands[0];
464         union acpi_operand_object *obj_desc;
465         acpi_status status;
466         u8 method_flags;
467
468         ACPI_FUNCTION_TRACE_PTR(ex_create_method, walk_state);
469
470         /* Create a new method object */
471
472         obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_METHOD);
473         if (!obj_desc) {
474                 status = AE_NO_MEMORY;
475                 goto exit;
476         }
477
478         /* Save the method's AML pointer and length  */
479
480         obj_desc->method.aml_start = aml_start;
481         obj_desc->method.aml_length = aml_length;
482
483         /*
484          * Disassemble the method flags. Split off the Arg Count
485          * for efficiency
486          */
487         method_flags = (u8) operand[1]->integer.value;
488
489         obj_desc->method.method_flags =
490             (u8) (method_flags & ~AML_METHOD_ARG_COUNT);
491         obj_desc->method.param_count =
492             (u8) (method_flags & AML_METHOD_ARG_COUNT);
493
494         /*
495          * Get the sync_level. If method is serialized, a mutex will be
496          * created for this method when it is parsed.
497          */
498         if (method_flags & AML_METHOD_SERIALIZED) {
499                 /*
500                  * ACPI 1.0: sync_level = 0
501                  * ACPI 2.0: sync_level = sync_level in method declaration
502                  */
503                 obj_desc->method.sync_level = (u8)
504                     ((method_flags & AML_METHOD_SYNCH_LEVEL) >> 4);
505         }
506
507         /* Attach the new object to the method Node */
508
509         status = acpi_ns_attach_object((struct acpi_namespace_node *)operand[0],
510                                        obj_desc, ACPI_TYPE_METHOD);
511
512         /* Remove local reference to the object */
513
514         acpi_ut_remove_reference(obj_desc);
515
516       exit:
517         /* Remove a reference to the operand */
518
519         acpi_ut_remove_reference(operand[1]);
520         return_ACPI_STATUS(status);
521 }