Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  1 /******************************************************************************
  2  *
  3  * Module Name: tbinstal - ACPI table installation and removal
  4  *
  5  *****************************************************************************/
  6 
  7 /*
  8  * Copyright (C) 2000 - 2007, 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 #include <acpi/acpi.h>
 45 #include <acpi/acnamesp.h>
 46 #include <acpi/actables.h>
 47 
 48 #define _COMPONENT          ACPI_TABLES
 49 ACPI_MODULE_NAME("tbinstal")
 50 
 51 /******************************************************************************
 52  *
 53  * FUNCTION:    acpi_tb_verify_table
 54  *
 55  * PARAMETERS:  table_desc          - table
 56  *
 57  * RETURN:      Status
 58  *
 59  * DESCRIPTION: this function is called to verify and map table
 60  *
 61  *****************************************************************************/
 62 acpi_status acpi_tb_verify_table(struct acpi_table_desc *table_desc)
 63 {
 64         acpi_status status = AE_OK;
 65 
 66         ACPI_FUNCTION_TRACE(tb_verify_table);
 67 
 68         /* Map the table if necessary */
 69 
 70         if (!table_desc->pointer) {
 71                 if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) ==
 72                     ACPI_TABLE_ORIGIN_MAPPED) {
 73                         table_desc->pointer =
 74                             acpi_os_map_memory(table_desc->address,
 75                                                table_desc->length);
 76                 }
 77                 if (!table_desc->pointer) {
 78                         return_ACPI_STATUS(AE_NO_MEMORY);
 79                 }
 80         }
 81 
 82         /* FACS is the odd table, has no standard ACPI header and no checksum */
 83 
 84         if (!ACPI_COMPARE_NAME(&table_desc->signature, ACPI_SIG_FACS)) {
 85 
 86                 /* Always calculate checksum, ignore bad checksum if requested */
 87 
 88                 status =
 89                     acpi_tb_verify_checksum(table_desc->pointer,
 90                                             table_desc->length);
 91         }
 92 
 93         return_ACPI_STATUS(status);
 94 }
 95 
 96 /*******************************************************************************
 97  *
 98  * FUNCTION:    acpi_tb_add_table
 99  *
100  * PARAMETERS:  table_desc          - Table descriptor
101  *              table_index         - Where the table index is returned
102  *
103  * RETURN:      Status
104  *
105  * DESCRIPTION: This function is called to add the ACPI table
106  *
107  ******************************************************************************/
108 
109 acpi_status
110 acpi_tb_add_table(struct acpi_table_desc *table_desc,
111                   acpi_native_uint * table_index)
112 {
113         acpi_native_uint i;
114         acpi_native_uint length;
115         acpi_status status = AE_OK;
116 
117         ACPI_FUNCTION_TRACE(tb_add_table);
118 
119         if (!table_desc->pointer) {
120                 status = acpi_tb_verify_table(table_desc);
121                 if (ACPI_FAILURE(status) || !table_desc->pointer) {
122                         return_ACPI_STATUS(status);
123                 }
124         }
125 
126         /* The table must be either an SSDT or a PSDT or an OEMx */
127 
128         if ((!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_PSDT))
129             &&
130             (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT))
131             && (strncmp(table_desc->pointer->signature, "OEM", 3))) {
132                 ACPI_ERROR((AE_INFO,
133                             "Table has invalid signature [%4.4s], must be SSDT, PSDT or OEMx",
134                             table_desc->pointer->signature));
135                 return_ACPI_STATUS(AE_BAD_SIGNATURE);
136         }
137 
138         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
139 
140         /* Check if table is already registered */
141 
142         for (i = 0; i < acpi_gbl_root_table_list.count; ++i) {
143                 if (!acpi_gbl_root_table_list.tables[i].pointer) {
144                         status =
145                             acpi_tb_verify_table(&acpi_gbl_root_table_list.
146                                                  tables[i]);
147                         if (ACPI_FAILURE(status)
148                             || !acpi_gbl_root_table_list.tables[i].pointer) {
149                                 continue;
150                         }
151                 }
152 
153                 length = ACPI_MIN(table_desc->length,
154                                   acpi_gbl_root_table_list.tables[i].length);
155                 if (ACPI_MEMCMP(table_desc->pointer,
156                                 acpi_gbl_root_table_list.tables[i].pointer,
157                                 length)) {
158                         continue;
159                 }
160 
161                 /* Table is already registered */
162 
163                 acpi_tb_delete_table(table_desc);
164                 *table_index = i;
165                 goto release;
166         }
167 
168         /*
169          * Add the table to the global table list
170          */
171         status = acpi_tb_store_table(table_desc->address, table_desc->pointer,
172                                      table_desc->length, table_desc->flags,
173                                      table_index);
174         if (ACPI_FAILURE(status)) {
175                 goto release;
176         }
177 
178         acpi_tb_print_table_header(table_desc->address, table_desc->pointer);
179 
180       release:
181         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
182         return_ACPI_STATUS(status);
183 }
184 
185 /*******************************************************************************
186  *
187  * FUNCTION:    acpi_tb_resize_root_table_list
188  *
189  * PARAMETERS:  None
190  *
191  * RETURN:      Status
192  *
193  * DESCRIPTION: Expand the size of global table array
194  *
195  ******************************************************************************/
196 
197 acpi_status acpi_tb_resize_root_table_list(void)
198 {
199         struct acpi_table_desc *tables;
200 
201         ACPI_FUNCTION_TRACE(tb_resize_root_table_list);
202 
203         /* allow_resize flag is a parameter to acpi_initialize_tables */
204 
205         if (!(acpi_gbl_root_table_list.flags & ACPI_ROOT_ALLOW_RESIZE)) {
206                 ACPI_ERROR((AE_INFO,
207                             "Resize of Root Table Array is not allowed"));
208                 return_ACPI_STATUS(AE_SUPPORT);
209         }
210 
211         /* Increase the Table Array size */
212 
213         tables = ACPI_ALLOCATE_ZEROED((acpi_gbl_root_table_list.size +
214                                        ACPI_ROOT_TABLE_SIZE_INCREMENT)
215                                       * sizeof(struct acpi_table_desc));
216         if (!tables) {
217                 ACPI_ERROR((AE_INFO,
218                             "Could not allocate new root table array"));
219                 return_ACPI_STATUS(AE_NO_MEMORY);
220         }
221 
222         /* Copy and free the previous table array */
223 
224         if (acpi_gbl_root_table_list.tables) {
225                 ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables,
226                             acpi_gbl_root_table_list.size *
227                             sizeof(struct acpi_table_desc));
228 
229                 if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
230                         ACPI_FREE(acpi_gbl_root_table_list.tables);
231                 }
232         }
233 
234         acpi_gbl_root_table_list.tables = tables;
235         acpi_gbl_root_table_list.size += ACPI_ROOT_TABLE_SIZE_INCREMENT;
236         acpi_gbl_root_table_list.flags |= (u8) ACPI_ROOT_ORIGIN_ALLOCATED;
237 
238         return_ACPI_STATUS(AE_OK);
239 }
240 
241 /*******************************************************************************
242  *
243  * FUNCTION:    acpi_tb_store_table
244  *
245  * PARAMETERS:  Address             - Table address
246  *              Table               - Table header
247  *              Length              - Table length
248  *              Flags               - flags
249  *
250  * RETURN:      Status and table index.
251  *
252  * DESCRIPTION: Add an ACPI table to the global table list
253  *
254  ******************************************************************************/
255 
256 acpi_status
257 acpi_tb_store_table(acpi_physical_address address,
258                     struct acpi_table_header *table,
259                     u32 length, u8 flags, acpi_native_uint * table_index)
260 {
261         acpi_status status = AE_OK;
262 
263         /* Ensure that there is room for the table in the Root Table List */
264 
265         if (acpi_gbl_root_table_list.count >= acpi_gbl_root_table_list.size) {
266                 status = acpi_tb_resize_root_table_list();
267                 if (ACPI_FAILURE(status)) {
268                         return (status);
269                 }
270         }
271 
272         /* Initialize added table */
273 
274         acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].
275             address = address;
276         acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].
277             pointer = table;
278         acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].length =
279             length;
280         acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].
281             owner_id = 0;
282         acpi_gbl_root_table_list.tables[acpi_gbl_root_table_list.count].flags =
283             flags;
284 
285         ACPI_MOVE_32_TO_32(&
286                            (acpi_gbl_root_table_list.
287                             tables[acpi_gbl_root_table_list.count].signature),
288                            table->signature);
289 
290         *table_index = acpi_gbl_root_table_list.count;
291         acpi_gbl_root_table_list.count++;
292         return (status);
293 }
294 
295 /*******************************************************************************
296  *
297  * FUNCTION:    acpi_tb_delete_table
298  *
299  * PARAMETERS:  table_index         - Table index
300  *
301  * RETURN:      None
302  *
303  * DESCRIPTION: Delete one internal ACPI table
304  *
305  ******************************************************************************/
306 
307 void acpi_tb_delete_table(struct acpi_table_desc *table_desc)
308 {
309         /* Table must be mapped or allocated */
310         if (!table_desc->pointer) {
311                 return;
312         }
313         switch (table_desc->flags & ACPI_TABLE_ORIGIN_MASK) {
314         case ACPI_TABLE_ORIGIN_MAPPED:
315                 acpi_os_unmap_memory(table_desc->pointer, table_desc->length);
316                 break;
317         case ACPI_TABLE_ORIGIN_ALLOCATED:
318                 ACPI_FREE(table_desc->pointer);
319                 break;
320         default:;
321         }
322 
323         table_desc->pointer = NULL;
324 }
325 
326 /*******************************************************************************
327  *
328  * FUNCTION:    acpi_tb_terminate
329  *
330  * PARAMETERS:  None
331  *
332  * RETURN:      None
333  *
334  * DESCRIPTION: Delete all internal ACPI tables
335  *
336  ******************************************************************************/
337 
338 void acpi_tb_terminate(void)
339 {
340         acpi_native_uint i;
341 
342         ACPI_FUNCTION_TRACE(tb_terminate);
343 
344         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
345 
346         /* Delete the individual tables */
347 
348         for (i = 0; i < acpi_gbl_root_table_list.count; ++i) {
349                 acpi_tb_delete_table(&acpi_gbl_root_table_list.tables[i]);
350         }
351 
352         /*
353          * Delete the root table array if allocated locally. Array cannot be
354          * mapped, so we don't need to check for that flag.
355          */
356         if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
357                 ACPI_FREE(acpi_gbl_root_table_list.tables);
358         }
359 
360         acpi_gbl_root_table_list.tables = NULL;
361         acpi_gbl_root_table_list.flags = 0;
362         acpi_gbl_root_table_list.count = 0;
363 
364         ACPI_DEBUG_PRINT((ACPI_DB_INFO, "ACPI Tables freed\n"));
365         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
366 }
367 
368 /*******************************************************************************
369  *
370  * FUNCTION:    acpi_tb_delete_namespace_by_owner
371  *
372  * PARAMETERS:  table_index         - Table index
373  *
374  * RETURN:      None
375  *
376  * DESCRIPTION: Delete all namespace objects created when this table was loaded.
377  *
378  ******************************************************************************/
379 
380 void acpi_tb_delete_namespace_by_owner(acpi_native_uint table_index)
381 {
382         acpi_owner_id owner_id;
383 
384         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
385         if (table_index < acpi_gbl_root_table_list.count) {
386                 owner_id =
387                     acpi_gbl_root_table_list.tables[table_index].owner_id;
388         } else {
389                 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
390                 return;
391         }
392 
393         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
394         acpi_ns_delete_namespace_by_owner(owner_id);
395 }
396 
397 /*******************************************************************************
398  *
399  * FUNCTION:    acpi_tb_allocate_owner_id
400  *
401  * PARAMETERS:  table_index         - Table index
402  *
403  * RETURN:      Status
404  *
405  * DESCRIPTION: Allocates owner_id in table_desc
406  *
407  ******************************************************************************/
408 
409 acpi_status acpi_tb_allocate_owner_id(acpi_native_uint table_index)
410 {
411         acpi_status status = AE_BAD_PARAMETER;
412 
413         ACPI_FUNCTION_TRACE(tb_allocate_owner_id);
414 
415         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
416         if (table_index < acpi_gbl_root_table_list.count) {
417                 status = acpi_ut_allocate_owner_id
418                     (&(acpi_gbl_root_table_list.tables[table_index].owner_id));
419         }
420 
421         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
422         return_ACPI_STATUS(status);
423 }
424 
425 /*******************************************************************************
426  *
427  * FUNCTION:    acpi_tb_release_owner_id
428  *
429  * PARAMETERS:  table_index         - Table index
430  *
431  * RETURN:      Status
432  *
433  * DESCRIPTION: Releases owner_id in table_desc
434  *
435  ******************************************************************************/
436 
437 acpi_status acpi_tb_release_owner_id(acpi_native_uint table_index)
438 {
439         acpi_status status = AE_BAD_PARAMETER;
440 
441         ACPI_FUNCTION_TRACE(tb_release_owner_id);
442 
443         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
444         if (table_index < acpi_gbl_root_table_list.count) {
445                 acpi_ut_release_owner_id(&
446                                          (acpi_gbl_root_table_list.
447                                           tables[table_index].owner_id));
448                 status = AE_OK;
449         }
450 
451         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
452         return_ACPI_STATUS(status);
453 }
454 
455 /*******************************************************************************
456  *
457  * FUNCTION:    acpi_tb_get_owner_id
458  *
459  * PARAMETERS:  table_index         - Table index
460  *              owner_id            - Where the table owner_id is returned
461  *
462  * RETURN:      Status
463  *
464  * DESCRIPTION: returns owner_id for the ACPI table
465  *
466  ******************************************************************************/
467 
468 acpi_status
469 acpi_tb_get_owner_id(acpi_native_uint table_index, acpi_owner_id * owner_id)
470 {
471         acpi_status status = AE_BAD_PARAMETER;
472 
473         ACPI_FUNCTION_TRACE(tb_get_owner_id);
474 
475         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
476         if (table_index < acpi_gbl_root_table_list.count) {
477                 *owner_id =
478                     acpi_gbl_root_table_list.tables[table_index].owner_id;
479                 status = AE_OK;
480         }
481 
482         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
483         return_ACPI_STATUS(status);
484 }
485 
486 /*******************************************************************************
487  *
488  * FUNCTION:    acpi_tb_is_table_loaded
489  *
490  * PARAMETERS:  table_index         - Table index
491  *
492  * RETURN:      Table Loaded Flag
493  *
494  ******************************************************************************/
495 
496 u8 acpi_tb_is_table_loaded(acpi_native_uint table_index)
497 {
498         u8 is_loaded = FALSE;
499 
500         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
501         if (table_index < acpi_gbl_root_table_list.count) {
502                 is_loaded = (u8)
503                     (acpi_gbl_root_table_list.tables[table_index].
504                      flags & ACPI_TABLE_IS_LOADED);
505         }
506 
507         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
508         return (is_loaded);
509 }
510 
511 /*******************************************************************************
512  *
513  * FUNCTION:    acpi_tb_set_table_loaded_flag
514  *
515  * PARAMETERS:  table_index         - Table index
516  *              is_loaded           - TRUE if table is loaded, FALSE otherwise
517  *
518  * RETURN:      None
519  *
520  * DESCRIPTION: Sets the table loaded flag to either TRUE or FALSE.
521  *
522  ******************************************************************************/
523 
524 void acpi_tb_set_table_loaded_flag(acpi_native_uint table_index, u8 is_loaded)
525 {
526 
527         (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
528         if (table_index < acpi_gbl_root_table_list.count) {
529                 if (is_loaded) {
530                         acpi_gbl_root_table_list.tables[table_index].flags |=
531                             ACPI_TABLE_IS_LOADED;
532                 } else {
533                         acpi_gbl_root_table_list.tables[table_index].flags &=
534                             ~ACPI_TABLE_IS_LOADED;
535                 }
536         }
537 
538         (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
539 }
540 
  This page was automatically generated by the LXR engine.