Linux-2.6.12-rc2
[cascardo/linux.git] / drivers / acpi / namespace / nsload.c
1 /******************************************************************************
2  *
3  * Module Name: nsload - namespace loading/expanding/contracting procedures
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/acnamesp.h>
47 #include <acpi/acdispat.h>
48
49
50 #define _COMPONENT          ACPI_NAMESPACE
51          ACPI_MODULE_NAME    ("nsload")
52
53
54 #ifndef ACPI_NO_METHOD_EXECUTION
55
56 /*******************************************************************************
57  *
58  * FUNCTION:    acpi_ns_load_table
59  *
60  * PARAMETERS:  table_desc      - Descriptor for table to be loaded
61  *              Node            - Owning NS node
62  *
63  * RETURN:      Status
64  *
65  * DESCRIPTION: Load one ACPI table into the namespace
66  *
67  ******************************************************************************/
68
69 acpi_status
70 acpi_ns_load_table (
71         struct acpi_table_desc          *table_desc,
72         struct acpi_namespace_node      *node)
73 {
74         acpi_status                     status;
75
76
77         ACPI_FUNCTION_TRACE ("ns_load_table");
78
79
80         /* Check if table contains valid AML (must be DSDT, PSDT, SSDT, etc.) */
81
82         if (!(acpi_gbl_table_data[table_desc->type].flags & ACPI_TABLE_EXECUTABLE)) {
83                 /* Just ignore this table */
84
85                 return_ACPI_STATUS (AE_OK);
86         }
87
88         /* Check validity of the AML start and length */
89
90         if (!table_desc->aml_start) {
91                 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Null AML pointer\n"));
92                 return_ACPI_STATUS (AE_BAD_PARAMETER);
93         }
94
95         ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "AML block at %p\n",
96                 table_desc->aml_start));
97
98         /* Ignore table if there is no AML contained within */
99
100         if (!table_desc->aml_length) {
101                 ACPI_REPORT_WARNING (("Zero-length AML block in table [%4.4s]\n",
102                         table_desc->pointer->signature));
103                 return_ACPI_STATUS (AE_OK);
104         }
105
106         /*
107          * Parse the table and load the namespace with all named
108          * objects found within.  Control methods are NOT parsed
109          * at this time.  In fact, the control methods cannot be
110          * parsed until the entire namespace is loaded, because
111          * if a control method makes a forward reference (call)
112          * to another control method, we can't continue parsing
113          * because we don't know how many arguments to parse next!
114          */
115         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
116                 "**** Loading table into namespace ****\n"));
117
118         status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
119         if (ACPI_FAILURE (status)) {
120                 return_ACPI_STATUS (status);
121         }
122
123         status = acpi_ns_parse_table (table_desc, node->child);
124         (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
125
126         if (ACPI_FAILURE (status)) {
127                 return_ACPI_STATUS (status);
128         }
129
130         /*
131          * Now we can parse the control methods.  We always parse
132          * them here for a sanity check, and if configured for
133          * just-in-time parsing, we delete the control method
134          * parse trees.
135          */
136         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
137                 "**** Begin Table Method Parsing and Object Initialization ****\n"));
138
139         status = acpi_ds_initialize_objects (table_desc, node);
140
141         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
142                 "**** Completed Table Method Parsing and Object Initialization ****\n"));
143
144         return_ACPI_STATUS (status);
145 }
146
147
148 /*******************************************************************************
149  *
150  * FUNCTION:    acpi_ns_load_table_by_type
151  *
152  * PARAMETERS:  table_type          - Id of the table type to load
153  *
154  * RETURN:      Status
155  *
156  * DESCRIPTION: Load an ACPI table or tables into the namespace.  All tables
157  *              of the given type are loaded.  The mechanism allows this
158  *              routine to be called repeatedly.
159  *
160  ******************************************************************************/
161
162 acpi_status
163 acpi_ns_load_table_by_type (
164         acpi_table_type                 table_type)
165 {
166         u32                             i;
167         acpi_status                     status;
168         struct acpi_table_desc          *table_desc;
169
170
171         ACPI_FUNCTION_TRACE ("ns_load_table_by_type");
172
173
174         status = acpi_ut_acquire_mutex (ACPI_MTX_TABLES);
175         if (ACPI_FAILURE (status)) {
176                 return_ACPI_STATUS (status);
177         }
178
179         /*
180          * Table types supported are:
181          * DSDT (one), SSDT/PSDT (multiple)
182          */
183         switch (table_type) {
184         case ACPI_TABLE_DSDT:
185
186                 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading DSDT\n"));
187
188                 table_desc = acpi_gbl_table_lists[ACPI_TABLE_DSDT].next;
189
190                 /* If table already loaded into namespace, just return */
191
192                 if (table_desc->loaded_into_namespace) {
193                         goto unlock_and_exit;
194                 }
195
196                 /* Now load the single DSDT */
197
198                 status = acpi_ns_load_table (table_desc, acpi_gbl_root_node);
199                 if (ACPI_SUCCESS (status)) {
200                         table_desc->loaded_into_namespace = TRUE;
201                 }
202                 break;
203
204
205         case ACPI_TABLE_SSDT:
206
207                 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading %d SSDTs\n",
208                         acpi_gbl_table_lists[ACPI_TABLE_SSDT].count));
209
210                 /*
211                  * Traverse list of SSDT tables
212                  */
213                 table_desc = acpi_gbl_table_lists[ACPI_TABLE_SSDT].next;
214                 for (i = 0; i < acpi_gbl_table_lists[ACPI_TABLE_SSDT].count; i++) {
215                         /*
216                          * Only attempt to load table if it is not
217                          * already loaded!
218                          */
219                         if (!table_desc->loaded_into_namespace) {
220                                 status = acpi_ns_load_table (table_desc, acpi_gbl_root_node);
221                                 if (ACPI_FAILURE (status)) {
222                                         break;
223                                 }
224
225                                 table_desc->loaded_into_namespace = TRUE;
226                         }
227
228                         table_desc = table_desc->next;
229                 }
230                 break;
231
232
233         case ACPI_TABLE_PSDT:
234
235                 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Loading %d PSDTs\n",
236                         acpi_gbl_table_lists[ACPI_TABLE_PSDT].count));
237
238                 /*
239                  * Traverse list of PSDT tables
240                  */
241                 table_desc = acpi_gbl_table_lists[ACPI_TABLE_PSDT].next;
242
243                 for (i = 0; i < acpi_gbl_table_lists[ACPI_TABLE_PSDT].count; i++) {
244                         /* Only attempt to load table if it is not already loaded! */
245
246                         if (!table_desc->loaded_into_namespace) {
247                                 status = acpi_ns_load_table (table_desc, acpi_gbl_root_node);
248                                 if (ACPI_FAILURE (status)) {
249                                         break;
250                                 }
251
252                                 table_desc->loaded_into_namespace = TRUE;
253                         }
254
255                         table_desc = table_desc->next;
256                 }
257                 break;
258
259
260         default:
261                 status = AE_SUPPORT;
262                 break;
263         }
264
265
266 unlock_and_exit:
267         (void) acpi_ut_release_mutex (ACPI_MTX_TABLES);
268         return_ACPI_STATUS (status);
269 }
270
271
272 /*******************************************************************************
273  *
274  * FUNCTION:    acpi_load_namespace
275  *
276  * PARAMETERS:  None
277  *
278  * RETURN:      Status
279  *
280  * DESCRIPTION: Load the name space from what ever is pointed to by DSDT.
281  *              (DSDT points to either the BIOS or a buffer.)
282  *
283  ******************************************************************************/
284
285 acpi_status
286 acpi_ns_load_namespace (
287         void)
288 {
289         acpi_status                     status;
290
291
292         ACPI_FUNCTION_TRACE ("acpi_load_name_space");
293
294
295         /* There must be at least a DSDT installed */
296
297         if (acpi_gbl_DSDT == NULL) {
298                 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "DSDT is not in memory\n"));
299                 return_ACPI_STATUS (AE_NO_ACPI_TABLES);
300         }
301
302         /*
303          * Load the namespace.  The DSDT is required,
304          * but the SSDT and PSDT tables are optional.
305          */
306         status = acpi_ns_load_table_by_type (ACPI_TABLE_DSDT);
307         if (ACPI_FAILURE (status)) {
308                 return_ACPI_STATUS (status);
309         }
310
311         /* Ignore exceptions from these */
312
313         (void) acpi_ns_load_table_by_type (ACPI_TABLE_SSDT);
314         (void) acpi_ns_load_table_by_type (ACPI_TABLE_PSDT);
315
316         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
317                 "ACPI Namespace successfully loaded at root %p\n",
318                 acpi_gbl_root_node));
319
320         return_ACPI_STATUS (status);
321 }
322
323
324 #ifdef ACPI_FUTURE_USAGE
325
326 /*******************************************************************************
327  *
328  * FUNCTION:    acpi_ns_delete_subtree
329  *
330  * PARAMETERS:  start_handle        - Handle in namespace where search begins
331  *
332  * RETURNS      Status
333  *
334  * DESCRIPTION: Walks the namespace starting at the given handle and deletes
335  *              all objects, entries, and scopes in the entire subtree.
336  *
337  *              Namespace/Interpreter should be locked or the subsystem should
338  *              be in shutdown before this routine is called.
339  *
340  ******************************************************************************/
341
342 acpi_status
343 acpi_ns_delete_subtree (
344         acpi_handle                     start_handle)
345 {
346         acpi_status                     status;
347         acpi_handle                     child_handle;
348         acpi_handle                     parent_handle;
349         acpi_handle                     next_child_handle;
350         acpi_handle                     dummy;
351         u32                             level;
352
353
354         ACPI_FUNCTION_TRACE ("ns_delete_subtree");
355
356
357         parent_handle = start_handle;
358         child_handle = NULL;
359         level        = 1;
360
361         /*
362          * Traverse the tree of objects until we bubble back up
363          * to where we started.
364          */
365         while (level > 0) {
366                 /* Attempt to get the next object in this scope */
367
368                 status = acpi_get_next_object (ACPI_TYPE_ANY, parent_handle,
369                                   child_handle, &next_child_handle);
370
371                 child_handle = next_child_handle;
372
373                 /* Did we get a new object? */
374
375                 if (ACPI_SUCCESS (status)) {
376                         /* Check if this object has any children */
377
378                         if (ACPI_SUCCESS (acpi_get_next_object (ACPI_TYPE_ANY, child_handle,
379                                          NULL, &dummy))) {
380                                 /*
381                                  * There is at least one child of this object,
382                                  * visit the object
383                                  */
384                                 level++;
385                                 parent_handle = child_handle;
386                                 child_handle = NULL;
387                         }
388                 }
389                 else {
390                         /*
391                          * No more children in this object, go back up to
392                          * the object's parent
393                          */
394                         level--;
395
396                         /* Delete all children now */
397
398                         acpi_ns_delete_children (child_handle);
399
400                         child_handle = parent_handle;
401                         status = acpi_get_parent (parent_handle, &parent_handle);
402                         if (ACPI_FAILURE (status)) {
403                                 return_ACPI_STATUS (status);
404                         }
405                 }
406         }
407
408         /* Now delete the starting object, and we are done */
409
410         acpi_ns_delete_node (child_handle);
411
412         return_ACPI_STATUS (AE_OK);
413 }
414
415
416 /*******************************************************************************
417  *
418  *  FUNCTION:       acpi_ns_unload_name_space
419  *
420  *  PARAMETERS:     Handle          - Root of namespace subtree to be deleted
421  *
422  *  RETURN:         Status
423  *
424  *  DESCRIPTION:    Shrinks the namespace, typically in response to an undocking
425  *                  event.  Deletes an entire subtree starting from (and
426  *                  including) the given handle.
427  *
428  ******************************************************************************/
429
430 acpi_status
431 acpi_ns_unload_namespace (
432         acpi_handle                     handle)
433 {
434         acpi_status                     status;
435
436
437         ACPI_FUNCTION_TRACE ("ns_unload_name_space");
438
439
440         /* Parameter validation */
441
442         if (!acpi_gbl_root_node) {
443                 return_ACPI_STATUS (AE_NO_NAMESPACE);
444         }
445
446         if (!handle) {
447                 return_ACPI_STATUS (AE_BAD_PARAMETER);
448         }
449
450         /* This function does the real work */
451
452         status = acpi_ns_delete_subtree (handle);
453
454         return_ACPI_STATUS (status);
455 }
456
457 #endif  /*  ACPI_FUTURE_USAGE  */
458
459 #endif
460