Merge /spare/repo/linux-2.6/
[pandora-kernel.git] / drivers / acpi / tables / tbxface.c
1 /******************************************************************************
2  *
3  * Module Name: tbxface - Public interfaces to the ACPI subsystem
4  *                         ACPI table oriented interfaces
5  *
6  *****************************************************************************/
7
8 /*
9  * Copyright (C) 2000 - 2005, R. Byron Moore
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions, and the following disclaimer,
17  *    without modification.
18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19  *    substantially similar to the "NO WARRANTY" disclaimer below
20  *    ("Disclaimer") and any redistribution must be conditioned upon
21  *    including a substantially similar Disclaimer requirement for further
22  *    binary redistribution.
23  * 3. Neither the names of the above-listed copyright holders nor the names
24  *    of any contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * Alternatively, this software may be distributed under the terms of the
28  * GNU General Public License ("GPL") version 2 as published by the Free
29  * Software Foundation.
30  *
31  * NO WARRANTY
32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42  * POSSIBILITY OF SUCH DAMAGES.
43  */
44
45 #include <linux/module.h>
46
47 #include <acpi/acpi.h>
48 #include <acpi/acnamesp.h>
49 #include <acpi/actables.h>
50
51 #define _COMPONENT          ACPI_TABLES
52 ACPI_MODULE_NAME("tbxface")
53
54 /*******************************************************************************
55  *
56  * FUNCTION:    acpi_load_tables
57  *
58  * PARAMETERS:  None
59  *
60  * RETURN:      Status
61  *
62  * DESCRIPTION: This function is called to load the ACPI tables from the
63  *              provided RSDT
64  *
65  ******************************************************************************/
66 acpi_status acpi_load_tables(void)
67 {
68         struct acpi_pointer rsdp_address;
69         acpi_status status;
70
71         ACPI_FUNCTION_TRACE("acpi_load_tables");
72
73         /* Get the RSDP */
74
75         status = acpi_os_get_root_pointer(ACPI_LOGICAL_ADDRESSING,
76                                           &rsdp_address);
77         if (ACPI_FAILURE(status)) {
78                 ACPI_REPORT_ERROR(("acpi_load_tables: Could not get RSDP, %s\n",
79                                    acpi_format_exception(status)));
80                 goto error_exit;
81         }
82
83         /* Map and validate the RSDP */
84
85         acpi_gbl_table_flags = rsdp_address.pointer_type;
86
87         status = acpi_tb_verify_rsdp(&rsdp_address);
88         if (ACPI_FAILURE(status)) {
89                 ACPI_REPORT_ERROR(("acpi_load_tables: RSDP Failed validation: %s\n", acpi_format_exception(status)));
90                 goto error_exit;
91         }
92
93         /* Get the RSDT via the RSDP */
94
95         status = acpi_tb_get_table_rsdt();
96         if (ACPI_FAILURE(status)) {
97                 ACPI_REPORT_ERROR(("acpi_load_tables: Could not load RSDT: %s\n", acpi_format_exception(status)));
98                 goto error_exit;
99         }
100
101         /* Now get the tables needed by this subsystem (FADT, DSDT, etc.) */
102
103         status = acpi_tb_get_required_tables();
104         if (ACPI_FAILURE(status)) {
105                 ACPI_REPORT_ERROR(("acpi_load_tables: Error getting required tables (DSDT/FADT/FACS): %s\n", acpi_format_exception(status)));
106                 goto error_exit;
107         }
108
109         ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI Tables successfully acquired\n"));
110
111         /* Load the namespace from the tables */
112
113         status = acpi_ns_load_namespace();
114         if (ACPI_FAILURE(status)) {
115                 ACPI_REPORT_ERROR(("acpi_load_tables: Could not load namespace: %s\n", acpi_format_exception(status)));
116                 goto error_exit;
117         }
118
119         return_ACPI_STATUS(AE_OK);
120
121       error_exit:
122         ACPI_REPORT_ERROR(("acpi_load_tables: Could not load tables: %s\n",
123                            acpi_format_exception(status)));
124
125         return_ACPI_STATUS(status);
126 }
127
128 #ifdef ACPI_FUTURE_USAGE
129 /*******************************************************************************
130  *
131  * FUNCTION:    acpi_load_table
132  *
133  * PARAMETERS:  table_ptr       - pointer to a buffer containing the entire
134  *                                table to be loaded
135  *
136  * RETURN:      Status
137  *
138  * DESCRIPTION: This function is called to load a table from the caller's
139  *              buffer.  The buffer must contain an entire ACPI Table including
140  *              a valid header.  The header fields will be verified, and if it
141  *              is determined that the table is invalid, the call will fail.
142  *
143  ******************************************************************************/
144
145 acpi_status acpi_load_table(struct acpi_table_header *table_ptr)
146 {
147         acpi_status status;
148         struct acpi_table_desc table_info;
149         struct acpi_pointer address;
150
151         ACPI_FUNCTION_TRACE("acpi_load_table");
152
153         if (!table_ptr) {
154                 return_ACPI_STATUS(AE_BAD_PARAMETER);
155         }
156
157         /* Copy the table to a local buffer */
158
159         address.pointer_type = ACPI_LOGICAL_POINTER | ACPI_LOGICAL_ADDRESSING;
160         address.pointer.logical = table_ptr;
161
162         status = acpi_tb_get_table_body(&address, table_ptr, &table_info);
163         if (ACPI_FAILURE(status)) {
164                 return_ACPI_STATUS(status);
165         }
166
167         /* Check signature for a valid table type */
168
169         status = acpi_tb_recognize_table(&table_info, ACPI_TABLE_ALL);
170         if (ACPI_FAILURE(status)) {
171                 return_ACPI_STATUS(status);
172         }
173
174         /* Install the new table into the local data structures */
175
176         status = acpi_tb_install_table(&table_info);
177         if (ACPI_FAILURE(status)) {
178                 if (status == AE_ALREADY_EXISTS) {
179                         /* Table already exists, no error */
180
181                         status = AE_OK;
182                 }
183
184                 /* Free table allocated by acpi_tb_get_table_body */
185
186                 acpi_tb_delete_single_table(&table_info);
187                 return_ACPI_STATUS(status);
188         }
189
190         /* Convert the table to common format if necessary */
191
192         switch (table_info.type) {
193         case ACPI_TABLE_FADT:
194
195                 status = acpi_tb_convert_table_fadt();
196                 break;
197
198         case ACPI_TABLE_FACS:
199
200                 status = acpi_tb_build_common_facs(&table_info);
201                 break;
202
203         default:
204                 /* Load table into namespace if it contains executable AML */
205
206                 status =
207                     acpi_ns_load_table(table_info.installed_desc,
208                                        acpi_gbl_root_node);
209                 break;
210         }
211
212         if (ACPI_FAILURE(status)) {
213                 /* Uninstall table and free the buffer */
214
215                 (void)acpi_tb_uninstall_table(table_info.installed_desc);
216         }
217
218         return_ACPI_STATUS(status);
219 }
220
221 /*******************************************************************************
222  *
223  * FUNCTION:    acpi_unload_table
224  *
225  * PARAMETERS:  table_type    - Type of table to be unloaded
226  *
227  * RETURN:      Status
228  *
229  * DESCRIPTION: This routine is used to force the unload of a table
230  *
231  ******************************************************************************/
232
233 acpi_status acpi_unload_table(acpi_table_type table_type)
234 {
235         struct acpi_table_desc *table_desc;
236
237         ACPI_FUNCTION_TRACE("acpi_unload_table");
238
239         /* Parameter validation */
240
241         if (table_type > ACPI_TABLE_MAX) {
242                 return_ACPI_STATUS(AE_BAD_PARAMETER);
243         }
244
245         /* Find all tables of the requested type */
246
247         table_desc = acpi_gbl_table_lists[table_type].next;
248         while (table_desc) {
249                 /*
250                  * Delete all namespace entries owned by this table.  Note that these
251                  * entries can appear anywhere in the namespace by virtue of the AML
252                  * "Scope" operator.  Thus, we need to track ownership by an ID, not
253                  * simply a position within the hierarchy
254                  */
255                 acpi_ns_delete_namespace_by_owner(table_desc->owner_id);
256                 acpi_ut_release_owner_id(&table_desc->owner_id);
257                 table_desc = table_desc->next;
258         }
259
260         /* Delete (or unmap) all tables of this type */
261
262         acpi_tb_delete_tables_by_type(table_type);
263         return_ACPI_STATUS(AE_OK);
264 }
265
266 /*******************************************************************************
267  *
268  * FUNCTION:    acpi_get_table_header
269  *
270  * PARAMETERS:  table_type      - one of the defined table types
271  *              Instance        - the non zero instance of the table, allows
272  *                                support for multiple tables of the same type
273  *                                see acpi_gbl_acpi_table_flag
274  *              out_table_header - pointer to the struct acpi_table_header if successful
275  *
276  * DESCRIPTION: This function is called to get an ACPI table header.  The caller
277  *              supplies an pointer to a data area sufficient to contain an ACPI
278  *              struct acpi_table_header structure.
279  *
280  *              The header contains a length field that can be used to determine
281  *              the size of the buffer needed to contain the entire table.  This
282  *              function is not valid for the RSD PTR table since it does not
283  *              have a standard header and is fixed length.
284  *
285  ******************************************************************************/
286
287 acpi_status
288 acpi_get_table_header(acpi_table_type table_type,
289                       u32 instance, struct acpi_table_header *out_table_header)
290 {
291         struct acpi_table_header *tbl_ptr;
292         acpi_status status;
293
294         ACPI_FUNCTION_TRACE("acpi_get_table_header");
295
296         if ((instance == 0) ||
297             (table_type == ACPI_TABLE_RSDP) || (!out_table_header)) {
298                 return_ACPI_STATUS(AE_BAD_PARAMETER);
299         }
300
301         /* Check the table type and instance */
302
303         if ((table_type > ACPI_TABLE_MAX) ||
304             (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags) &&
305              instance > 1)) {
306                 return_ACPI_STATUS(AE_BAD_PARAMETER);
307         }
308
309         /* Get a pointer to the entire table */
310
311         status = acpi_tb_get_table_ptr(table_type, instance, &tbl_ptr);
312         if (ACPI_FAILURE(status)) {
313                 return_ACPI_STATUS(status);
314         }
315
316         /* The function will return a NULL pointer if the table is not loaded */
317
318         if (tbl_ptr == NULL) {
319                 return_ACPI_STATUS(AE_NOT_EXIST);
320         }
321
322         /* Copy the header to the caller's buffer */
323
324         ACPI_MEMCPY((void *)out_table_header, (void *)tbl_ptr,
325                     sizeof(struct acpi_table_header));
326
327         return_ACPI_STATUS(status);
328 }
329
330 #endif                          /*  ACPI_FUTURE_USAGE  */
331
332 /*******************************************************************************
333  *
334  * FUNCTION:    acpi_get_table
335  *
336  * PARAMETERS:  table_type      - one of the defined table types
337  *              Instance        - the non zero instance of the table, allows
338  *                                support for multiple tables of the same type
339  *                                see acpi_gbl_acpi_table_flag
340  *              ret_buffer      - pointer to a structure containing a buffer to
341  *                                receive the table
342  *
343  * RETURN:      Status
344  *
345  * DESCRIPTION: This function is called to get an ACPI table.  The caller
346  *              supplies an out_buffer large enough to contain the entire ACPI
347  *              table.  The caller should call the acpi_get_table_header function
348  *              first to determine the buffer size needed.  Upon completion
349  *              the out_buffer->Length field will indicate the number of bytes
350  *              copied into the out_buffer->buf_ptr buffer. This table will be
351  *              a complete table including the header.
352  *
353  ******************************************************************************/
354
355 acpi_status
356 acpi_get_table(acpi_table_type table_type,
357                u32 instance, struct acpi_buffer *ret_buffer)
358 {
359         struct acpi_table_header *tbl_ptr;
360         acpi_status status;
361         acpi_size table_length;
362
363         ACPI_FUNCTION_TRACE("acpi_get_table");
364
365         /* Parameter validation */
366
367         if (instance == 0) {
368                 return_ACPI_STATUS(AE_BAD_PARAMETER);
369         }
370
371         status = acpi_ut_validate_buffer(ret_buffer);
372         if (ACPI_FAILURE(status)) {
373                 return_ACPI_STATUS(status);
374         }
375
376         /* Check the table type and instance */
377
378         if ((table_type > ACPI_TABLE_MAX) ||
379             (ACPI_IS_SINGLE_TABLE(acpi_gbl_table_data[table_type].flags) &&
380              instance > 1)) {
381                 return_ACPI_STATUS(AE_BAD_PARAMETER);
382         }
383
384         /* Get a pointer to the entire table */
385
386         status = acpi_tb_get_table_ptr(table_type, instance, &tbl_ptr);
387         if (ACPI_FAILURE(status)) {
388                 return_ACPI_STATUS(status);
389         }
390
391         /*
392          * acpi_tb_get_table_ptr will return a NULL pointer if the
393          * table is not loaded.
394          */
395         if (tbl_ptr == NULL) {
396                 return_ACPI_STATUS(AE_NOT_EXIST);
397         }
398
399         /* Get the table length */
400
401         if (table_type == ACPI_TABLE_RSDP) {
402                 /* RSD PTR is the only "table" without a header */
403
404                 table_length = sizeof(struct rsdp_descriptor);
405         } else {
406                 table_length = (acpi_size) tbl_ptr->length;
407         }
408
409         /* Validate/Allocate/Clear caller buffer */
410
411         status = acpi_ut_initialize_buffer(ret_buffer, table_length);
412         if (ACPI_FAILURE(status)) {
413                 return_ACPI_STATUS(status);
414         }
415
416         /* Copy the table to the buffer */
417
418         ACPI_MEMCPY((void *)ret_buffer->pointer, (void *)tbl_ptr, table_length);
419         return_ACPI_STATUS(AE_OK);
420 }
421
422 EXPORT_SYMBOL(acpi_get_table);