1 /*******************************************************************************
3 * Module Name: cmutils - common utility procedures
6 ******************************************************************************/
9 * Copyright (C) 2000, 2001 R. Byron Moore
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
36 #define _COMPONENT ACPI_UTILITIES
37 MODULE_NAME ("cmutils")
40 /*******************************************************************************
42 * FUNCTION: Acpi_cm_valid_acpi_name
44 * PARAMETERS: Character - The character to be examined
46 * RETURN: 1 if Character may appear in a name, else 0
48 * DESCRIPTION: Check for a valid ACPI name. Each character must be one of:
53 ******************************************************************************/
56 acpi_cm_valid_acpi_name (
59 NATIVE_CHAR *name_ptr = (NATIVE_CHAR *) &name;
63 for (i = 0; i < ACPI_NAME_SIZE; i++) {
64 if (!((name_ptr[i] == '_') ||
65 (name_ptr[i] >= 'A' && name_ptr[i] <= 'Z') ||
66 (name_ptr[i] >= '0' && name_ptr[i] <= '9'))) {
76 /*******************************************************************************
78 * FUNCTION: Acpi_cm_valid_acpi_character
80 * PARAMETERS: Character - The character to be examined
82 * RETURN: 1 if Character may appear in a name, else 0
84 * DESCRIPTION: Check for a printable character
86 ******************************************************************************/
89 acpi_cm_valid_acpi_character (
90 NATIVE_CHAR character)
93 return ((u8) ((character == '_') ||
94 (character >= 'A' && character <= 'Z') ||
95 (character >= '0' && character <= '9')));
99 /*******************************************************************************
101 * FUNCTION: Acpi_cm_mutex_initialize
107 * DESCRIPTION: Create the system mutex objects.
109 ******************************************************************************/
112 acpi_cm_mutex_initialize (
120 * Create each of the predefined mutex objects
122 for (i = 0; i < NUM_MTX; i++) {
123 status = acpi_cm_create_mutex (i);
124 if (ACPI_FAILURE (status)) {
133 /*******************************************************************************
135 * FUNCTION: Acpi_cm_mutex_terminate
141 * DESCRIPTION: Delete all of the system mutex objects.
143 ******************************************************************************/
146 acpi_cm_mutex_terminate (
153 * Delete each predefined mutex object
155 for (i = 0; i < NUM_MTX; i++) {
156 acpi_cm_delete_mutex (i);
163 /*******************************************************************************
165 * FUNCTION: Acpi_cm_create_mutex
167 * PARAMETERS: Mutex_iD - ID of the mutex to be created
171 * DESCRIPTION: Create a mutex object.
173 ******************************************************************************/
176 acpi_cm_create_mutex (
177 ACPI_MUTEX_HANDLE mutex_id)
179 ACPI_STATUS status = AE_OK;
182 if (mutex_id > MAX_MTX) {
183 return (AE_BAD_PARAMETER);
187 if (!acpi_gbl_acpi_mutex_info[mutex_id].mutex) {
188 status = acpi_os_create_semaphore (1, 1,
189 &acpi_gbl_acpi_mutex_info[mutex_id].mutex);
190 acpi_gbl_acpi_mutex_info[mutex_id].locked = FALSE;
191 acpi_gbl_acpi_mutex_info[mutex_id].use_count = 0;
198 /*******************************************************************************
200 * FUNCTION: Acpi_cm_delete_mutex
202 * PARAMETERS: Mutex_iD - ID of the mutex to be deleted
206 * DESCRIPTION: Delete a mutex object.
208 ******************************************************************************/
211 acpi_cm_delete_mutex (
212 ACPI_MUTEX_HANDLE mutex_id)
217 if (mutex_id > MAX_MTX) {
218 return (AE_BAD_PARAMETER);
222 status = acpi_os_delete_semaphore (acpi_gbl_acpi_mutex_info[mutex_id].mutex);
224 acpi_gbl_acpi_mutex_info[mutex_id].mutex = NULL;
225 acpi_gbl_acpi_mutex_info[mutex_id].locked = FALSE;
231 /*******************************************************************************
233 * FUNCTION: Acpi_cm_acquire_mutex
235 * PARAMETERS: Mutex_iD - ID of the mutex to be acquired
239 * DESCRIPTION: Acquire a mutex object.
241 ******************************************************************************/
244 acpi_cm_acquire_mutex (
245 ACPI_MUTEX_HANDLE mutex_id)
252 if (mutex_id > MAX_MTX) {
253 return (AE_BAD_PARAMETER);
257 this_thread_id = acpi_os_get_thread_id ();
260 * Deadlock prevention. Check if this thread owns any mutexes of value
261 * greater than or equal to this one. If so, the thread has violated
262 * the mutex ordering rule. This indicates a coding error somewhere in
263 * the ACPI subsystem code.
265 for (i = mutex_id; i < MAX_MTX; i++) {
266 if (acpi_gbl_acpi_mutex_info[i].owner_id == this_thread_id) {
268 return (AE_ALREADY_ACQUIRED);
271 return (AE_ACQUIRE_DEADLOCK);
276 status = acpi_os_wait_semaphore (acpi_gbl_acpi_mutex_info[mutex_id].mutex,
279 if (ACPI_SUCCESS (status)) {
280 acpi_gbl_acpi_mutex_info[mutex_id].locked = TRUE;
281 acpi_gbl_acpi_mutex_info[mutex_id].use_count++;
282 acpi_gbl_acpi_mutex_info[mutex_id].owner_id = this_thread_id;
289 /*******************************************************************************
291 * FUNCTION: Acpi_cm_release_mutex
293 * PARAMETERS: Mutex_iD - ID of the mutex to be released
297 * DESCRIPTION: Release a mutex object.
299 ******************************************************************************/
302 acpi_cm_release_mutex (
303 ACPI_MUTEX_HANDLE mutex_id)
310 if (mutex_id > MAX_MTX) {
311 return (AE_BAD_PARAMETER);
316 * Mutex must be acquired in order to release it!
318 if (!acpi_gbl_acpi_mutex_info[mutex_id].locked) {
319 return (AE_NOT_ACQUIRED);
324 * Deadlock prevention. Check if this thread owns any mutexes of value
325 * greater than this one. If so, the thread has violated
326 * the mutex ordering rule. This indicates a coding error somewhere in
327 * the ACPI subsystem code.
329 this_thread_id = acpi_os_get_thread_id ();
330 for (i = mutex_id; i < MAX_MTX; i++) {
331 if (acpi_gbl_acpi_mutex_info[i].owner_id == this_thread_id) {
336 return (AE_RELEASE_DEADLOCK);
340 acpi_gbl_acpi_mutex_info[mutex_id].locked = FALSE; /* Mark before unlocking */
341 acpi_gbl_acpi_mutex_info[mutex_id].owner_id = 0;
343 status = acpi_os_signal_semaphore (acpi_gbl_acpi_mutex_info[mutex_id].mutex, 1);
350 /*******************************************************************************
352 * FUNCTION: Acpi_cm_create_update_state_and_push
354 * PARAMETERS: *Object - Object to be added to the new state
355 * Action - Increment/Decrement
356 * State_list - List the state will be added to
360 * DESCRIPTION: Create a new state and push it
362 ******************************************************************************/
365 acpi_cm_create_update_state_and_push (
366 ACPI_OPERAND_OBJECT *object,
368 ACPI_GENERIC_STATE **state_list)
370 ACPI_GENERIC_STATE *state;
373 /* Ignore null objects; these are expected */
379 state = acpi_cm_create_update_state (object, action);
381 return (AE_NO_MEMORY);
385 acpi_cm_push_generic_state (state_list, state);
390 /*******************************************************************************
392 * FUNCTION: Acpi_cm_create_pkg_state_and_push
394 * PARAMETERS: *Object - Object to be added to the new state
395 * Action - Increment/Decrement
396 * State_list - List the state will be added to
400 * DESCRIPTION: Create a new state and push it
402 ******************************************************************************/
405 acpi_cm_create_pkg_state_and_push (
406 void *internal_object,
407 void *external_object,
409 ACPI_GENERIC_STATE **state_list)
411 ACPI_GENERIC_STATE *state;
414 state = acpi_cm_create_pkg_state (internal_object, external_object, index);
416 return (AE_NO_MEMORY);
420 acpi_cm_push_generic_state (state_list, state);
425 /*******************************************************************************
427 * FUNCTION: Acpi_cm_push_generic_state
429 * PARAMETERS: List_head - Head of the state stack
430 * State - State object to push
434 * DESCRIPTION: Push a state object onto a state stack
436 ******************************************************************************/
439 acpi_cm_push_generic_state (
440 ACPI_GENERIC_STATE **list_head,
441 ACPI_GENERIC_STATE *state)
443 /* Push the state object onto the front of the list (stack) */
445 state->common.next = *list_head;
452 /*******************************************************************************
454 * FUNCTION: Acpi_cm_pop_generic_state
456 * PARAMETERS: List_head - Head of the state stack
460 * DESCRIPTION: Pop a state object from a state stack
462 ******************************************************************************/
465 acpi_cm_pop_generic_state (
466 ACPI_GENERIC_STATE **list_head)
468 ACPI_GENERIC_STATE *state;
471 /* Remove the state object at the head of the list (stack) */
475 /* Update the list head */
477 *list_head = state->common.next;
484 /*******************************************************************************
486 * FUNCTION: Acpi_cm_create_generic_state
492 * DESCRIPTION: Create a generic state object. Attempt to obtain one from
493 * the global state cache; If none available, create a new one.
495 ******************************************************************************/
498 acpi_cm_create_generic_state (void)
500 ACPI_GENERIC_STATE *state;
503 acpi_cm_acquire_mutex (ACPI_MTX_CACHES);
505 acpi_gbl_state_cache_requests++;
507 /* Check the cache first */
509 if (acpi_gbl_generic_state_cache) {
510 /* There is an object available, use it */
512 state = acpi_gbl_generic_state_cache;
513 acpi_gbl_generic_state_cache = state->common.next;
514 state->common.next = NULL;
516 acpi_gbl_state_cache_hits++;
517 acpi_gbl_generic_state_cache_depth--;
519 acpi_cm_release_mutex (ACPI_MTX_CACHES);
524 /* The cache is empty, create a new object */
526 acpi_cm_release_mutex (ACPI_MTX_CACHES);
528 state = acpi_cm_callocate (sizeof (ACPI_GENERIC_STATE));
534 /* Always zero out the object before init */
536 MEMSET (state, 0, sizeof (ACPI_GENERIC_STATE));
538 state->common.data_type = ACPI_DESC_TYPE_STATE;
545 /*******************************************************************************
547 * FUNCTION: Acpi_cm_create_update_state
549 * PARAMETERS: Object - Initial Object to be installed in the
551 * Action - Update action to be performed
555 * DESCRIPTION: Create an "Update State" - a flavor of the generic state used
556 * to update reference counts and delete complex objects such
559 ******************************************************************************/
562 acpi_cm_create_update_state (
563 ACPI_OPERAND_OBJECT *object,
566 ACPI_GENERIC_STATE *state;
569 /* Create the generic state object */
571 state = acpi_cm_create_generic_state ();
576 /* Init fields specific to the update struct */
578 state->update.object = object;
579 state->update.value = action;
585 /*******************************************************************************
587 * FUNCTION: Acpi_cm_create_pkg_state
589 * PARAMETERS: Object - Initial Object to be installed in the
591 * Action - Update action to be performed
595 * DESCRIPTION: Create an "Update State" - a flavor of the generic state used
596 * to update reference counts and delete complex objects such
599 ******************************************************************************/
602 acpi_cm_create_pkg_state (
603 void *internal_object,
604 void *external_object,
607 ACPI_GENERIC_STATE *state;
610 /* Create the generic state object */
612 state = acpi_cm_create_generic_state ();
617 /* Init fields specific to the update struct */
619 state->pkg.source_object = (ACPI_OPERAND_OBJECT *) internal_object;
620 state->pkg.dest_object = external_object;
621 state->pkg.index = index;
622 state->pkg.num_packages = 1;
628 /*******************************************************************************
630 * FUNCTION: Acpi_cm_create_control_state
636 * DESCRIPTION: Create a "Control State" - a flavor of the generic state used
637 * to support nested IF/WHILE constructs in the AML.
639 ******************************************************************************/
642 acpi_cm_create_control_state (
645 ACPI_GENERIC_STATE *state;
648 /* Create the generic state object */
650 state = acpi_cm_create_generic_state ();
656 /* Init fields specific to the control struct */
658 state->common.state = CONTROL_CONDITIONAL_EXECUTING;
664 /*******************************************************************************
666 * FUNCTION: Acpi_cm_delete_generic_state
668 * PARAMETERS: State - The state object to be deleted
672 * DESCRIPTION: Put a state object back into the global state cache. The object
673 * is not actually freed at this time.
675 ******************************************************************************/
678 acpi_cm_delete_generic_state (
679 ACPI_GENERIC_STATE *state)
682 /* If cache is full, just free this state object */
684 if (acpi_gbl_generic_state_cache_depth >= MAX_STATE_CACHE_DEPTH) {
685 acpi_cm_free (state);
688 /* Otherwise put this object back into the cache */
691 acpi_cm_acquire_mutex (ACPI_MTX_CACHES);
693 /* Clear the state */
695 MEMSET (state, 0, sizeof (ACPI_GENERIC_STATE));
696 state->common.data_type = ACPI_DESC_TYPE_STATE;
698 /* Put the object at the head of the global cache list */
700 state->common.next = acpi_gbl_generic_state_cache;
701 acpi_gbl_generic_state_cache = state;
702 acpi_gbl_generic_state_cache_depth++;
705 acpi_cm_release_mutex (ACPI_MTX_CACHES);
711 /*******************************************************************************
713 * FUNCTION: Acpi_cm_delete_generic_state_cache
719 * DESCRIPTION: Purge the global state object cache. Used during subsystem
722 ******************************************************************************/
725 acpi_cm_delete_generic_state_cache (
728 ACPI_GENERIC_STATE *next;
731 /* Traverse the global cache list */
733 while (acpi_gbl_generic_state_cache) {
734 /* Delete one cached state object */
736 next = acpi_gbl_generic_state_cache->common.next;
737 acpi_cm_free (acpi_gbl_generic_state_cache);
738 acpi_gbl_generic_state_cache = next;
739 acpi_gbl_generic_state_cache_depth--;
746 /*******************************************************************************
748 * FUNCTION: Acpi_cm_resolve_package_references
750 * PARAMETERS: Obj_desc - The Package object on which to resolve refs
754 * DESCRIPTION: Walk through a package and turn internal references into values
756 ******************************************************************************/
759 acpi_cm_resolve_package_references (
760 ACPI_OPERAND_OBJECT *obj_desc)
763 ACPI_OPERAND_OBJECT *sub_object;
766 if (obj_desc->common.type != ACPI_TYPE_PACKAGE) {
767 /* The object must be a package */
769 REPORT_ERROR (("Must resolve Package Refs on a Package\n"));
774 * TBD: what about nested packages? */
776 for (count = 0; count < obj_desc->package.count; count++) {
777 sub_object = obj_desc->package.elements[count];
779 if (sub_object->common.type == INTERNAL_TYPE_REFERENCE) {
780 if (sub_object->reference.opcode == AML_ZERO_OP) {
781 sub_object->common.type = ACPI_TYPE_INTEGER;
782 sub_object->integer.value = 0;
785 else if (sub_object->reference.opcode == AML_ONE_OP) {
786 sub_object->common.type = ACPI_TYPE_INTEGER;
787 sub_object->integer.value = 1;
790 else if (sub_object->reference.opcode == AML_ONES_OP) {
791 sub_object->common.type = ACPI_TYPE_INTEGER;
792 sub_object->integer.value = ACPI_INTEGER_MAX;
801 /*******************************************************************************
803 * FUNCTION: Acpi_cm_walk_package_tree
805 * PARAMETERS: Obj_desc - The Package object on which to resolve refs
809 * DESCRIPTION: Walk through a package
811 ******************************************************************************/
814 acpi_cm_walk_package_tree (
815 ACPI_OPERAND_OBJECT *source_object,
817 ACPI_PKG_CALLBACK walk_callback,
820 ACPI_STATUS status = AE_OK;
821 ACPI_GENERIC_STATE *state_list = NULL;
822 ACPI_GENERIC_STATE *state;
824 ACPI_OPERAND_OBJECT *this_source_obj;
827 state = acpi_cm_create_pkg_state (source_object, target_object, 0);
829 return (AE_NO_MEMORY);
833 this_index = state->pkg.index;
834 this_source_obj = (ACPI_OPERAND_OBJECT *)
835 state->pkg.source_object->package.elements[this_index];
839 * 1) An uninitialized package element. It is completely
840 * legal to declare a package and leave it uninitialized
841 * 2) Not an internal object - can be a namespace node instead
842 * 3) Any type other than a package. Packages are handled in else
845 if ((!this_source_obj) ||
846 (!VALID_DESCRIPTOR_TYPE (
847 this_source_obj, ACPI_DESC_TYPE_INTERNAL)) ||
848 (!IS_THIS_OBJECT_TYPE (
849 this_source_obj, ACPI_TYPE_PACKAGE))) {
851 status = walk_callback (ACPI_COPY_TYPE_SIMPLE, this_source_obj,
853 if (ACPI_FAILURE (status)) {
854 /* TBD: must delete package created up to this point */
860 while (state->pkg.index >= state->pkg.source_object->package.count) {
862 * We've handled all of the objects at this level, This means
863 * that we have just completed a package. That package may
864 * have contained one or more packages itself.
866 * Delete this state and pop the previous state (package).
868 acpi_cm_delete_generic_state (state);
869 state = acpi_cm_pop_generic_state (&state_list);
872 /* Finished when there are no more states */
876 * We have handled all of the objects in the top level
877 * package just add the length of the package objects
884 * Go back up a level and move the index past the just
885 * completed package object.
892 /* This is a sub-object of type package */
894 status = walk_callback (ACPI_COPY_TYPE_PACKAGE, this_source_obj,
896 if (ACPI_FAILURE (status)) {
897 /* TBD: must delete package created up to this point */
904 * The callback above returned a new target package object.
908 * Push the current state and create a new one
910 acpi_cm_push_generic_state (&state_list, state);
911 state = acpi_cm_create_pkg_state (this_source_obj,
912 state->pkg.this_target_obj, 0);
914 /* TBD: must delete package created up to this point */
916 return (AE_NO_MEMORY);
921 /* We should never get here */
923 return (AE_AML_INTERNAL);
928 /*******************************************************************************
930 * FUNCTION: _Report_error
932 * PARAMETERS: Module_name - Caller's module name (for error output)
933 * Line_number - Caller's line number (for error output)
934 * Component_id - Caller's component ID (for error output)
935 * Message - Error message to use on failure
939 * DESCRIPTION: Print error message
941 ******************************************************************************/
945 NATIVE_CHAR *module_name,
951 acpi_os_printf ("%8s-%04d: *** Error: ", module_name, line_number);
955 /*******************************************************************************
957 * FUNCTION: _Report_warning
959 * PARAMETERS: Module_name - Caller's module name (for error output)
960 * Line_number - Caller's line number (for error output)
961 * Component_id - Caller's component ID (for error output)
962 * Message - Error message to use on failure
966 * DESCRIPTION: Print warning message
968 ******************************************************************************/
972 NATIVE_CHAR *module_name,
977 acpi_os_printf ("%8s-%04d: *** Warning: ", module_name, line_number);
981 /*******************************************************************************
983 * FUNCTION: _Report_info
985 * PARAMETERS: Module_name - Caller's module name (for error output)
986 * Line_number - Caller's line number (for error output)
987 * Component_id - Caller's component ID (for error output)
988 * Message - Error message to use on failure
992 * DESCRIPTION: Print information message
994 ******************************************************************************/
998 NATIVE_CHAR *module_name,
1003 acpi_os_printf ("%8s-%04d: *** Info: ", module_name, line_number);