utmisc.c revision 80062
1/*******************************************************************************
2 *
3 * Module Name: utmisc - common utility procedures
4 *              $Revision: 44 $
5 *
6 ******************************************************************************/
7
8/******************************************************************************
9 *
10 * 1. Copyright Notice
11 *
12 * Some or all of this work - Copyright (c) 1999, 2000, 2001, Intel Corp.
13 * All rights reserved.
14 *
15 * 2. License
16 *
17 * 2.1. This is your license from Intel Corp. under its intellectual property
18 * rights.  You may have additional license terms from the party that provided
19 * you this software, covering your right to use that party's intellectual
20 * property rights.
21 *
22 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23 * copy of the source code appearing in this file ("Covered Code") an
24 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25 * base code distributed originally by Intel ("Original Intel Code") to copy,
26 * make derivatives, distribute, use and display any portion of the Covered
27 * Code in any form, with the right to sublicense such rights; and
28 *
29 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30 * license (with the right to sublicense), under only those claims of Intel
31 * patents that are infringed by the Original Intel Code, to make, use, sell,
32 * offer to sell, and import the Covered Code and derivative works thereof
33 * solely to the minimum extent necessary to exercise the above copyright
34 * license, and in no event shall the patent license extend to any additions
35 * to or modifications of the Original Intel Code.  No other license or right
36 * is granted directly or by implication, estoppel or otherwise;
37 *
38 * The above copyright and patent license is granted only if the following
39 * conditions are met:
40 *
41 * 3. Conditions
42 *
43 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44 * Redistribution of source code of any substantial portion of the Covered
45 * Code or modification with rights to further distribute source must include
46 * the above Copyright Notice, the above License, this list of Conditions,
47 * and the following Disclaimer and Export Compliance provision.  In addition,
48 * Licensee must cause all Covered Code to which Licensee contributes to
49 * contain a file documenting the changes Licensee made to create that Covered
50 * Code and the date of any change.  Licensee must include in that file the
51 * documentation of any changes made by any predecessor Licensee.  Licensee
52 * must include a prominent statement that the modification is derived,
53 * directly or indirectly, from Original Intel Code.
54 *
55 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56 * Redistribution of source code of any substantial portion of the Covered
57 * Code or modification without rights to further distribute source must
58 * include the following Disclaimer and Export Compliance provision in the
59 * documentation and/or other materials provided with distribution.  In
60 * addition, Licensee may not authorize further sublicense of source of any
61 * portion of the Covered Code, and must include terms to the effect that the
62 * license from Licensee to its licensee is limited to the intellectual
63 * property embodied in the software Licensee provides to its licensee, and
64 * not to intellectual property embodied in modifications its licensee may
65 * make.
66 *
67 * 3.3. Redistribution of Executable. Redistribution in executable form of any
68 * substantial portion of the Covered Code or modification must reproduce the
69 * above Copyright Notice, and the following Disclaimer and Export Compliance
70 * provision in the documentation and/or other materials provided with the
71 * distribution.
72 *
73 * 3.4. Intel retains all right, title, and interest in and to the Original
74 * Intel Code.
75 *
76 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77 * Intel shall be used in advertising or otherwise to promote the sale, use or
78 * other dealings in products derived from or relating to the Covered Code
79 * without prior written authorization from Intel.
80 *
81 * 4. Disclaimer and Export Compliance
82 *
83 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84 * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86 * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87 * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89 * PARTICULAR PURPOSE.
90 *
91 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98 * LIMITED REMEDY.
99 *
100 * 4.3. Licensee shall not export, either directly or indirectly, any of this
101 * software or system incorporating such software without first obtaining any
102 * required license or other approval from the U. S. Department of Commerce or
103 * any other agency or department of the United States Government.  In the
104 * event Licensee exports any such software from the United States or
105 * re-exports any such software from a foreign destination, Licensee shall
106 * ensure that the distribution and export/re-export of the software is in
107 * compliance with all laws, regulations, orders, or other restrictions of the
108 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109 * any of its subsidiaries will export/re-export any technical data, process,
110 * software, or service, directly or indirectly, to any country for which the
111 * United States government or any agency thereof requires an export license,
112 * other governmental approval, or letter of assurance, without first obtaining
113 * such license, approval or letter.
114 *
115 *****************************************************************************/
116
117
118#define __UTMISC_C__
119
120#include "acpi.h"
121#include "acevents.h"
122#include "achware.h"
123#include "acnamesp.h"
124#include "acinterp.h"
125#include "amlcode.h"
126#include "acdebug.h"
127
128
129#define _COMPONENT          ACPI_UTILITIES
130        MODULE_NAME         ("utmisc")
131
132
133/*******************************************************************************
134 *
135 * FUNCTION:    AcpiUtValidAcpiName
136 *
137 * PARAMETERS:  Character           - The character to be examined
138 *
139 * RETURN:      1 if Character may appear in a name, else 0
140 *
141 * DESCRIPTION: Check for a valid ACPI name.  Each character must be one of:
142 *              1) Upper case alpha
143 *              2) numeric
144 *              3) underscore
145 *
146 ******************************************************************************/
147
148BOOLEAN
149AcpiUtValidAcpiName (
150    UINT32                  Name)
151{
152    NATIVE_CHAR             *NamePtr = (NATIVE_CHAR *) &Name;
153    UINT32                  i;
154
155
156    for (i = 0; i < ACPI_NAME_SIZE; i++)
157    {
158        if (!((NamePtr[i] == '_') ||
159              (NamePtr[i] >= 'A' && NamePtr[i] <= 'Z') ||
160              (NamePtr[i] >= '0' && NamePtr[i] <= '9')))
161        {
162            return (FALSE);
163        }
164    }
165
166
167    return (TRUE);
168}
169
170
171/*******************************************************************************
172 *
173 * FUNCTION:    AcpiUtValidAcpiCharacter
174 *
175 * PARAMETERS:  Character           - The character to be examined
176 *
177 * RETURN:      1 if Character may appear in a name, else 0
178 *
179 * DESCRIPTION: Check for a printable character
180 *
181 ******************************************************************************/
182
183BOOLEAN
184AcpiUtValidAcpiCharacter (
185    NATIVE_CHAR             Character)
186{
187
188    return ((BOOLEAN)   ((Character == '_') ||
189                        (Character >= 'A' && Character <= 'Z') ||
190                        (Character >= '0' && Character <= '9')));
191}
192
193/*******************************************************************************
194 *
195 * FUNCTION:    AcpiUtStrupr
196 *
197 * PARAMETERS:  SrcString       - The source string to convert to
198 *
199 * RETURN:      SrcString
200 *
201 * DESCRIPTION: Convert string to uppercase
202 *
203 ******************************************************************************/
204
205NATIVE_CHAR *
206AcpiUtStrupr (
207    NATIVE_CHAR             *SrcString)
208{
209    NATIVE_CHAR             *String;
210
211
212    /* Walk entire string, uppercasing the letters */
213
214    for (String = SrcString; *String; )
215    {
216        *String = (char) TOUPPER (*String);
217        String++;
218    }
219
220
221    return (SrcString);
222}
223
224/*******************************************************************************
225 *
226 * FUNCTION:    AcpiUtMutexInitialize
227 *
228 * PARAMETERS:  None.
229 *
230 * RETURN:      Status
231 *
232 * DESCRIPTION: Create the system mutex objects.
233 *
234 ******************************************************************************/
235
236ACPI_STATUS
237AcpiUtMutexInitialize (
238    void)
239{
240    UINT32                  i;
241    ACPI_STATUS             Status;
242
243
244    FUNCTION_TRACE ("UtMutexInitialize");
245
246
247    /*
248     * Create each of the predefined mutex objects
249     */
250    for (i = 0; i < NUM_MTX; i++)
251    {
252        Status = AcpiUtCreateMutex (i);
253        if (ACPI_FAILURE (Status))
254        {
255            return_ACPI_STATUS (Status);
256        }
257    }
258
259    return_ACPI_STATUS (AE_OK);
260}
261
262
263/*******************************************************************************
264 *
265 * FUNCTION:    AcpiUtMutexTerminate
266 *
267 * PARAMETERS:  None.
268 *
269 * RETURN:      None.
270 *
271 * DESCRIPTION: Delete all of the system mutex objects.
272 *
273 ******************************************************************************/
274
275void
276AcpiUtMutexTerminate (
277    void)
278{
279    UINT32                  i;
280
281
282    FUNCTION_TRACE ("UtMutexTerminate");
283
284
285    /*
286     * Delete each predefined mutex object
287     */
288    for (i = 0; i < NUM_MTX; i++)
289    {
290        AcpiUtDeleteMutex (i);
291    }
292
293    return_VOID;
294}
295
296
297/*******************************************************************************
298 *
299 * FUNCTION:    AcpiUtCreateMutex
300 *
301 * PARAMETERS:  MutexID         - ID of the mutex to be created
302 *
303 * RETURN:      Status
304 *
305 * DESCRIPTION: Create a mutex object.
306 *
307 ******************************************************************************/
308
309ACPI_STATUS
310AcpiUtCreateMutex (
311    ACPI_MUTEX_HANDLE       MutexId)
312{
313    ACPI_STATUS             Status = AE_OK;
314
315
316    FUNCTION_TRACE_U32 ("UtCreateMutex", MutexId);
317
318
319    if (MutexId > MAX_MTX)
320    {
321        return_ACPI_STATUS (AE_BAD_PARAMETER);
322    }
323
324
325    if (!AcpiGbl_AcpiMutexInfo[MutexId].Mutex)
326    {
327        Status = AcpiOsCreateSemaphore (1, 1,
328                        &AcpiGbl_AcpiMutexInfo[MutexId].Mutex);
329        AcpiGbl_AcpiMutexInfo[MutexId].OwnerId = ACPI_MUTEX_NOT_ACQUIRED;
330        AcpiGbl_AcpiMutexInfo[MutexId].UseCount = 0;
331    }
332
333    return_ACPI_STATUS (Status);
334}
335
336
337/*******************************************************************************
338 *
339 * FUNCTION:    AcpiUtDeleteMutex
340 *
341 * PARAMETERS:  MutexID         - ID of the mutex to be deleted
342 *
343 * RETURN:      Status
344 *
345 * DESCRIPTION: Delete a mutex object.
346 *
347 ******************************************************************************/
348
349ACPI_STATUS
350AcpiUtDeleteMutex (
351    ACPI_MUTEX_HANDLE       MutexId)
352{
353    ACPI_STATUS             Status;
354
355
356    FUNCTION_TRACE_U32 ("UtDeleteMutex", MutexId);
357
358
359    if (MutexId > MAX_MTX)
360    {
361        return_ACPI_STATUS (AE_BAD_PARAMETER);
362    }
363
364
365    Status = AcpiOsDeleteSemaphore (AcpiGbl_AcpiMutexInfo[MutexId].Mutex);
366
367    AcpiGbl_AcpiMutexInfo[MutexId].Mutex = NULL;
368    AcpiGbl_AcpiMutexInfo[MutexId].OwnerId = ACPI_MUTEX_NOT_ACQUIRED;
369
370    return_ACPI_STATUS (Status);
371}
372
373
374/*******************************************************************************
375 *
376 * FUNCTION:    AcpiUtAcquireMutex
377 *
378 * PARAMETERS:  MutexID         - ID of the mutex to be acquired
379 *
380 * RETURN:      Status
381 *
382 * DESCRIPTION: Acquire a mutex object.
383 *
384 ******************************************************************************/
385
386ACPI_STATUS
387AcpiUtAcquireMutex (
388    ACPI_MUTEX_HANDLE       MutexId)
389{
390    ACPI_STATUS             Status;
391    UINT32                  i;
392    UINT32                  ThisThreadId;
393
394
395    PROC_NAME ("UtAcquireMutex");
396
397
398    if (MutexId > MAX_MTX)
399    {
400        return (AE_BAD_PARAMETER);
401    }
402
403
404    ThisThreadId = AcpiOsGetThreadId ();
405
406    /*
407     * Deadlock prevention.  Check if this thread owns any mutexes of value
408     * greater than or equal to this one.  If so, the thread has violated
409     * the mutex ordering rule.  This indicates a coding error somewhere in
410     * the ACPI subsystem code.
411     */
412    for (i = MutexId; i < MAX_MTX; i++)
413    {
414        if (AcpiGbl_AcpiMutexInfo[i].OwnerId == ThisThreadId)
415        {
416            if (i == MutexId)
417            {
418                DEBUG_PRINTP (ACPI_ERROR,
419                        ("Mutex [%s] already acquired by this thread [%X]\n",
420                        AcpiUtGetMutexName (MutexId), ThisThreadId));
421
422                return (AE_ALREADY_ACQUIRED);
423            }
424
425            DEBUG_PRINTP (ACPI_ERROR,
426                    ("Invalid acquire order: Thread %X owns [%s], wants [%s]\n",
427                    ThisThreadId, AcpiUtGetMutexName (i),
428                    AcpiUtGetMutexName (MutexId)));
429
430            return (AE_ACQUIRE_DEADLOCK);
431        }
432    }
433
434
435    DEBUG_PRINTP (TRACE_MUTEX,
436                ("Thread %X attempting to acquire Mutex [%s]\n",
437                ThisThreadId, AcpiUtGetMutexName (MutexId)));
438
439    Status = AcpiOsWaitSemaphore (AcpiGbl_AcpiMutexInfo[MutexId].Mutex,
440                                    1, WAIT_FOREVER);
441
442    if (ACPI_SUCCESS (Status))
443    {
444        DEBUG_PRINTP (TRACE_MUTEX, ("Thread %X acquired Mutex [%s]\n",
445                    ThisThreadId, AcpiUtGetMutexName (MutexId)));
446
447        AcpiGbl_AcpiMutexInfo[MutexId].UseCount++;
448        AcpiGbl_AcpiMutexInfo[MutexId].OwnerId = ThisThreadId;
449    }
450
451    else
452    {
453        DEBUG_PRINTP (ACPI_ERROR, ("Thread %X could not acquire Mutex [%s] %s\n",
454                    ThisThreadId, AcpiUtGetMutexName (MutexId),
455                    AcpiFormatException (Status)));
456    }
457
458    return (Status);
459}
460
461
462/*******************************************************************************
463 *
464 * FUNCTION:    AcpiUtReleaseMutex
465 *
466 * PARAMETERS:  MutexID         - ID of the mutex to be released
467 *
468 * RETURN:      Status
469 *
470 * DESCRIPTION: Release a mutex object.
471 *
472 ******************************************************************************/
473
474ACPI_STATUS
475AcpiUtReleaseMutex (
476    ACPI_MUTEX_HANDLE       MutexId)
477{
478    ACPI_STATUS             Status;
479    UINT32                  i;
480    UINT32                  ThisThreadId;
481
482
483    PROC_NAME ("UtReleaseMutex");
484
485
486    ThisThreadId = AcpiOsGetThreadId ();
487    DEBUG_PRINTP (TRACE_MUTEX,
488        ("Thread %X releasing Mutex [%s]\n", ThisThreadId,
489        AcpiUtGetMutexName (MutexId)));
490
491    if (MutexId > MAX_MTX)
492    {
493        return (AE_BAD_PARAMETER);
494    }
495
496
497    /*
498     * Mutex must be acquired in order to release it!
499     */
500    if (AcpiGbl_AcpiMutexInfo[MutexId].OwnerId == ACPI_MUTEX_NOT_ACQUIRED)
501    {
502        DEBUG_PRINTP (ACPI_ERROR,
503                ("Mutex [%s] is not acquired, cannot release\n",
504                AcpiUtGetMutexName (MutexId)));
505
506        return (AE_NOT_ACQUIRED);
507    }
508
509
510    /*
511     * Deadlock prevention.  Check if this thread owns any mutexes of value
512     * greater than this one.  If so, the thread has violated the mutex
513     * ordering rule.  This indicates a coding error somewhere in
514     * the ACPI subsystem code.
515     */
516    for (i = MutexId; i < MAX_MTX; i++)
517    {
518        if (AcpiGbl_AcpiMutexInfo[i].OwnerId == ThisThreadId)
519        {
520            if (i == MutexId)
521            {
522                continue;
523            }
524
525            DEBUG_PRINTP (ACPI_ERROR,
526                    ("Invalid release order: owns [%s], releasing [%s]\n",
527                    AcpiUtGetMutexName (i), AcpiUtGetMutexName (MutexId)));
528
529            return (AE_RELEASE_DEADLOCK);
530        }
531    }
532
533
534    /* Mark unlocked FIRST */
535
536    AcpiGbl_AcpiMutexInfo[MutexId].OwnerId = ACPI_MUTEX_NOT_ACQUIRED;
537
538    Status = AcpiOsSignalSemaphore (AcpiGbl_AcpiMutexInfo[MutexId].Mutex, 1);
539
540    if (ACPI_FAILURE (Status))
541    {
542        DEBUG_PRINTP (ACPI_ERROR, ("Thread %X could not release Mutex [%s] %s\n",
543                    ThisThreadId, AcpiUtGetMutexName (MutexId),
544                    AcpiFormatException (Status)));
545    }
546    else
547    {
548        DEBUG_PRINTP (TRACE_MUTEX, ("Thread %X released Mutex [%s]\n",
549                    ThisThreadId, AcpiUtGetMutexName (MutexId)));
550    }
551
552    return (Status);
553}
554
555
556/*******************************************************************************
557 *
558 * FUNCTION:    AcpiUtCreateUpdateStateAndPush
559 *
560 * PARAMETERS:  *Object         - Object to be added to the new state
561 *              Action          - Increment/Decrement
562 *              StateList       - List the state will be added to
563 *
564 * RETURN:      None
565 *
566 * DESCRIPTION: Create a new state and push it
567 *
568 ******************************************************************************/
569
570ACPI_STATUS
571AcpiUtCreateUpdateStateAndPush (
572    ACPI_OPERAND_OBJECT     *Object,
573    UINT16                  Action,
574    ACPI_GENERIC_STATE      **StateList)
575{
576    ACPI_GENERIC_STATE       *State;
577
578
579    /* Ignore null objects; these are expected */
580
581    if (!Object)
582    {
583        return (AE_OK);
584    }
585
586    State = AcpiUtCreateUpdateState (Object, Action);
587    if (!State)
588    {
589        return (AE_NO_MEMORY);
590    }
591
592
593    AcpiUtPushGenericState (StateList, State);
594    return (AE_OK);
595}
596
597
598/*******************************************************************************
599 *
600 * FUNCTION:    AcpiUtCreatePkgStateAndPush
601 *
602 * PARAMETERS:  *Object         - Object to be added to the new state
603 *              Action          - Increment/Decrement
604 *              StateList       - List the state will be added to
605 *
606 * RETURN:      None
607 *
608 * DESCRIPTION: Create a new state and push it
609 *
610 ******************************************************************************/
611
612ACPI_STATUS
613AcpiUtCreatePkgStateAndPush (
614    void                    *InternalObject,
615    void                    *ExternalObject,
616    UINT16                  Index,
617    ACPI_GENERIC_STATE      **StateList)
618{
619    ACPI_GENERIC_STATE       *State;
620
621
622    State = AcpiUtCreatePkgState (InternalObject, ExternalObject, Index);
623    if (!State)
624    {
625        return (AE_NO_MEMORY);
626    }
627
628
629    AcpiUtPushGenericState (StateList, State);
630    return (AE_OK);
631}
632
633
634/*******************************************************************************
635 *
636 * FUNCTION:    AcpiUtPushGenericState
637 *
638 * PARAMETERS:  ListHead            - Head of the state stack
639 *              State               - State object to push
640 *
641 * RETURN:      Status
642 *
643 * DESCRIPTION: Push a state object onto a state stack
644 *
645 ******************************************************************************/
646
647void
648AcpiUtPushGenericState (
649    ACPI_GENERIC_STATE      **ListHead,
650    ACPI_GENERIC_STATE      *State)
651{
652    FUNCTION_TRACE ("UtPushGenericState");
653
654    /* Push the state object onto the front of the list (stack) */
655
656    State->Common.Next = *ListHead;
657    *ListHead = State;
658
659    return_VOID;
660}
661
662
663/*******************************************************************************
664 *
665 * FUNCTION:    AcpiUtPopGenericState
666 *
667 * PARAMETERS:  ListHead            - Head of the state stack
668 *
669 * RETURN:      Status
670 *
671 * DESCRIPTION: Pop a state object from a state stack
672 *
673 ******************************************************************************/
674
675ACPI_GENERIC_STATE *
676AcpiUtPopGenericState (
677    ACPI_GENERIC_STATE      **ListHead)
678{
679    ACPI_GENERIC_STATE      *State;
680
681
682    FUNCTION_TRACE ("DsPopGenericState");
683
684
685    /* Remove the state object at the head of the list (stack) */
686
687    State = *ListHead;
688    if (State)
689    {
690        /* Update the list head */
691
692        *ListHead = State->Common.Next;
693    }
694
695    return_PTR (State);
696}
697
698
699/*******************************************************************************
700 *
701 * FUNCTION:    AcpiUtCreateGenericState
702 *
703 * PARAMETERS:  None
704 *
705 * RETURN:      Status
706 *
707 * DESCRIPTION: Create a generic state object.  Attempt to obtain one from
708 *              the global state cache;  If none available, create a new one.
709 *
710 ******************************************************************************/
711
712ACPI_GENERIC_STATE *
713AcpiUtCreateGenericState (void)
714{
715    ACPI_GENERIC_STATE      *State;
716
717
718    AcpiUtAcquireMutex (ACPI_MTX_CACHES);
719
720    AcpiGbl_StateCacheRequests++;
721
722    /* Check the cache first */
723
724    if (AcpiGbl_GenericStateCache)
725    {
726        /* There is an object available, use it */
727
728        State = AcpiGbl_GenericStateCache;
729        AcpiGbl_GenericStateCache = State->Common.Next;
730        State->Common.Next = NULL;
731
732        AcpiGbl_StateCacheHits++;
733        AcpiGbl_GenericStateCacheDepth--;
734
735        AcpiUtReleaseMutex (ACPI_MTX_CACHES);
736
737        DEBUG_PRINT (TRACE_EXEC, ("CreateGenState: State %p from cache\n", State));
738    }
739
740    else
741    {
742        /* The cache is empty, create a new object */
743
744        AcpiUtReleaseMutex (ACPI_MTX_CACHES);
745
746        State = ACPI_MEM_CALLOCATE (sizeof (ACPI_GENERIC_STATE));
747    }
748
749    /* Initialize */
750
751    if (State)
752    {
753        /* Always zero out the object before init */
754
755        MEMSET (State, 0, sizeof (ACPI_GENERIC_STATE));
756
757        State->Common.DataType = ACPI_DESC_TYPE_STATE;
758    }
759
760    return (State);
761}
762
763
764/*******************************************************************************
765 *
766 * FUNCTION:    AcpiUtCreateUpdateState
767 *
768 * PARAMETERS:  Object              - Initial Object to be installed in the
769 *                                    state
770 *              Action              - Update action to be performed
771 *
772 * RETURN:      Status
773 *
774 * DESCRIPTION: Create an "Update State" - a flavor of the generic state used
775 *              to update reference counts and delete complex objects such
776 *              as packages.
777 *
778 ******************************************************************************/
779
780ACPI_GENERIC_STATE *
781AcpiUtCreateUpdateState (
782    ACPI_OPERAND_OBJECT     *Object,
783    UINT16                  Action)
784{
785    ACPI_GENERIC_STATE      *State;
786
787
788    FUNCTION_TRACE_PTR ("UtCreateUpdateState", Object);
789
790
791    /* Create the generic state object */
792
793    State = AcpiUtCreateGenericState ();
794    if (!State)
795    {
796        return (NULL);
797    }
798
799    /* Init fields specific to the update struct */
800
801    State->Update.Object = Object;
802    State->Update.Value  = Action;
803
804    return_PTR (State);
805}
806
807
808/*******************************************************************************
809 *
810 * FUNCTION:    AcpiUtCreatePkgState
811 *
812 * PARAMETERS:  Object              - Initial Object to be installed in the
813 *                                    state
814 *              Action              - Update action to be performed
815 *
816 * RETURN:      Status
817 *
818 * DESCRIPTION: Create an "Update State" - a flavor of the generic state used
819 *              to update reference counts and delete complex objects such
820 *              as packages.
821 *
822 ******************************************************************************/
823
824ACPI_GENERIC_STATE *
825AcpiUtCreatePkgState (
826    void                    *InternalObject,
827    void                    *ExternalObject,
828    UINT16                  Index)
829{
830    ACPI_GENERIC_STATE      *State;
831
832
833    FUNCTION_TRACE_PTR ("UtCreatePkgState", InternalObject);
834
835
836    /* Create the generic state object */
837
838    State = AcpiUtCreateGenericState ();
839    if (!State)
840    {
841        return (NULL);
842    }
843
844    /* Init fields specific to the update struct */
845
846    State->Pkg.SourceObject = (ACPI_OPERAND_OBJECT *) InternalObject;
847    State->Pkg.DestObject   = ExternalObject;
848    State->Pkg.Index        = Index;
849    State->Pkg.NumPackages  = 1;
850
851    return_PTR (State);
852}
853
854
855/*******************************************************************************
856 *
857 * FUNCTION:    AcpiUtCreateControlState
858 *
859 * PARAMETERS:  None
860 *
861 * RETURN:      Status
862 *
863 * DESCRIPTION: Create a "Control State" - a flavor of the generic state used
864 *              to support nested IF/WHILE constructs in the AML.
865 *
866 ******************************************************************************/
867
868ACPI_GENERIC_STATE *
869AcpiUtCreateControlState (
870    void)
871{
872    ACPI_GENERIC_STATE      *State;
873
874
875    FUNCTION_TRACE ("UtCreateControlState");
876
877    /* Create the generic state object */
878
879    State = AcpiUtCreateGenericState ();
880    if (!State)
881    {
882        return (NULL);
883    }
884
885
886    /* Init fields specific to the control struct */
887
888    State->Common.State = CONTROL_CONDITIONAL_EXECUTING;
889
890    return_PTR (State);
891}
892
893
894/*******************************************************************************
895 *
896 * FUNCTION:    AcpiUtDeleteGenericState
897 *
898 * PARAMETERS:  State               - The state object to be deleted
899 *
900 * RETURN:      Status
901 *
902 * DESCRIPTION: Put a state object back into the global state cache.  The object
903 *              is not actually freed at this time.
904 *
905 ******************************************************************************/
906
907void
908AcpiUtDeleteGenericState (
909    ACPI_GENERIC_STATE      *State)
910{
911    FUNCTION_TRACE ("UtDeleteGenericState");
912
913
914    /* If cache is full, just free this state object */
915
916    if (AcpiGbl_GenericStateCacheDepth >= MAX_STATE_CACHE_DEPTH)
917    {
918        ACPI_MEM_FREE (State);
919    }
920
921    /* Otherwise put this object back into the cache */
922
923    else
924    {
925        AcpiUtAcquireMutex (ACPI_MTX_CACHES);
926
927        /* Clear the state */
928
929        MEMSET (State, 0, sizeof (ACPI_GENERIC_STATE));
930        State->Common.DataType = ACPI_DESC_TYPE_STATE;
931
932        /* Put the object at the head of the global cache list */
933
934        State->Common.Next = AcpiGbl_GenericStateCache;
935        AcpiGbl_GenericStateCache = State;
936        AcpiGbl_GenericStateCacheDepth++;
937
938
939        AcpiUtReleaseMutex (ACPI_MTX_CACHES);
940    }
941    return_VOID;
942}
943
944
945/*******************************************************************************
946 *
947 * FUNCTION:    AcpiUtDeleteGenericStateCache
948 *
949 * PARAMETERS:  None
950 *
951 * RETURN:      Status
952 *
953 * DESCRIPTION: Purge the global state object cache.  Used during subsystem
954 *              termination.
955 *
956 ******************************************************************************/
957
958void
959AcpiUtDeleteGenericStateCache (
960    void)
961{
962    ACPI_GENERIC_STATE      *Next;
963
964
965    FUNCTION_TRACE ("UtDeleteGenericStateCache");
966
967
968    /* Traverse the global cache list */
969
970    while (AcpiGbl_GenericStateCache)
971    {
972        /* Delete one cached state object */
973
974        Next = AcpiGbl_GenericStateCache->Common.Next;
975        ACPI_MEM_FREE (AcpiGbl_GenericStateCache);
976
977        AcpiGbl_GenericStateCache = Next;
978        AcpiGbl_GenericStateCacheDepth--;
979    }
980
981    return_VOID;
982}
983
984
985/*******************************************************************************
986 *
987 * FUNCTION:    AcpiUtResolvePackageReferences
988 *
989 * PARAMETERS:  ObjDesc         - The Package object on which to resolve refs
990 *
991 * RETURN:      Status
992 *
993 * DESCRIPTION: Walk through a package and turn internal references into values
994 *
995 ******************************************************************************/
996
997ACPI_STATUS
998AcpiUtResolvePackageReferences (
999    ACPI_OPERAND_OBJECT     *ObjDesc)
1000{
1001    UINT32                  Count;
1002    ACPI_OPERAND_OBJECT     *SubObject;
1003
1004
1005    FUNCTION_TRACE ("AcpiUtResolvePackageReferences");
1006
1007
1008    if (ObjDesc->Common.Type != ACPI_TYPE_PACKAGE)
1009    {
1010        /* The object must be a package */
1011
1012        REPORT_ERROR (("Must resolve Package Refs on a Package\n"));
1013        return_ACPI_STATUS(AE_ERROR);
1014    }
1015
1016    /*
1017     * TBD: what about nested packages? */
1018
1019    for (Count = 0; Count < ObjDesc->Package.Count; Count++)
1020    {
1021        SubObject = ObjDesc->Package.Elements[Count];
1022
1023        if (SubObject->Common.Type == INTERNAL_TYPE_REFERENCE)
1024        {
1025            if (SubObject->Reference.Opcode == AML_ZERO_OP)
1026            {
1027                SubObject->Common.Type  = ACPI_TYPE_INTEGER;
1028                SubObject->Integer.Value = 0;
1029            }
1030
1031            else if (SubObject->Reference.Opcode == AML_ONE_OP)
1032            {
1033                SubObject->Common.Type  = ACPI_TYPE_INTEGER;
1034                SubObject->Integer.Value = 1;
1035            }
1036
1037            else if (SubObject->Reference.Opcode == AML_ONES_OP)
1038            {
1039                SubObject->Common.Type  = ACPI_TYPE_INTEGER;
1040                SubObject->Integer.Value = ACPI_INTEGER_MAX;
1041            }
1042        }
1043    }
1044
1045    return_ACPI_STATUS(AE_OK);
1046}
1047
1048#ifdef ACPI_DEBUG
1049
1050/*******************************************************************************
1051 *
1052 * FUNCTION:    AcpiUtDisplayInitPathname
1053 *
1054 * PARAMETERS:  ObjHandle           - Handle whose pathname will be displayed
1055 *              Path                - Additional path string to be appended
1056 *
1057 * RETURN:      ACPI_STATUS
1058 *
1059 * DESCRIPTION: Display full pathnbame of an object, DEBUG ONLY
1060 *
1061 ******************************************************************************/
1062
1063void
1064AcpiUtDisplayInitPathname (
1065    ACPI_HANDLE             ObjHandle,
1066    char                    *Path)
1067{
1068    ACPI_STATUS             Status;
1069    UINT32                  Length = 128;
1070    char                    Buffer[128];
1071
1072
1073    Status = AcpiNsHandleToPathname (ObjHandle, &Length, Buffer);
1074    if (ACPI_SUCCESS (Status))
1075    {
1076        if (Path)
1077        {
1078            DEBUG_PRINT (TRACE_INIT, ("%s.%s\n", Buffer, Path))
1079        }
1080        else
1081        {
1082            DEBUG_PRINT (TRACE_INIT, ("%s\n", Buffer))
1083        }
1084    }
1085}
1086#endif
1087
1088/*******************************************************************************
1089 *
1090 * FUNCTION:    AcpiUtWalkPackageTree
1091 *
1092 * PARAMETERS:  ObjDesc         - The Package object on which to resolve refs
1093 *
1094 * RETURN:      Status
1095 *
1096 * DESCRIPTION: Walk through a package
1097 *
1098 ******************************************************************************/
1099
1100ACPI_STATUS
1101AcpiUtWalkPackageTree (
1102    ACPI_OPERAND_OBJECT     *SourceObject,
1103    void                    *TargetObject,
1104    ACPI_PKG_CALLBACK       WalkCallback,
1105    void                    *Context)
1106{
1107    ACPI_STATUS             Status = AE_OK;
1108    ACPI_GENERIC_STATE      *StateList = NULL;
1109    ACPI_GENERIC_STATE      *State;
1110    UINT32                  ThisIndex;
1111    ACPI_OPERAND_OBJECT     *ThisSourceObj;
1112
1113
1114    FUNCTION_TRACE ("AcpiUtWalkPackageTree");
1115
1116
1117    State = AcpiUtCreatePkgState (SourceObject, TargetObject, 0);
1118    if (!State)
1119    {
1120        return_ACPI_STATUS (AE_NO_MEMORY);
1121    }
1122
1123    while (State)
1124    {
1125        ThisIndex     = State->Pkg.Index;
1126        ThisSourceObj = (ACPI_OPERAND_OBJECT *)
1127                        State->Pkg.SourceObject->Package.Elements[ThisIndex];
1128
1129        /*
1130         * Check for
1131         * 1) An uninitialized package element.  It is completely
1132         *      legal to declare a package and leave it uninitialized
1133         * 2) Not an internal object - can be a namespace node instead
1134         * 3) Any type other than a package.  Packages are handled in else
1135         *      case below.
1136         */
1137        if ((!ThisSourceObj) ||
1138            (!VALID_DESCRIPTOR_TYPE (
1139                    ThisSourceObj, ACPI_DESC_TYPE_INTERNAL)) ||
1140            (!IS_THIS_OBJECT_TYPE (
1141                    ThisSourceObj, ACPI_TYPE_PACKAGE)))
1142        {
1143
1144            Status = WalkCallback (ACPI_COPY_TYPE_SIMPLE, ThisSourceObj,
1145                                    State, Context);
1146            if (ACPI_FAILURE (Status))
1147            {
1148                /* TBD: must delete package created up to this point */
1149
1150                return_ACPI_STATUS (Status);
1151            }
1152
1153            State->Pkg.Index++;
1154            while (State->Pkg.Index >= State->Pkg.SourceObject->Package.Count)
1155            {
1156                /*
1157                 * We've handled all of the objects at this level,  This means
1158                 * that we have just completed a package.  That package may
1159                 * have contained one or more packages itself.
1160                 *
1161                 * Delete this state and pop the previous state (package).
1162                 */
1163                AcpiUtDeleteGenericState (State);
1164                State = AcpiUtPopGenericState (&StateList);
1165
1166
1167                /* Finished when there are no more states */
1168
1169                if (!State)
1170                {
1171                    /*
1172                     * We have handled all of the objects in the top level
1173                     * package just add the length of the package objects
1174                     * and exit
1175                     */
1176                    return_ACPI_STATUS (AE_OK);
1177                }
1178
1179                /*
1180                 * Go back up a level and move the index past the just
1181                 * completed package object.
1182                 */
1183                State->Pkg.Index++;
1184            }
1185        }
1186
1187        else
1188        {
1189            /* This is a sub-object of type package */
1190
1191            Status = WalkCallback (ACPI_COPY_TYPE_PACKAGE, ThisSourceObj,
1192                                        State, Context);
1193            if (ACPI_FAILURE (Status))
1194            {
1195                /* TBD: must delete package created up to this point */
1196
1197                return_ACPI_STATUS (Status);
1198            }
1199
1200
1201            /*
1202             * The callback above returned a new target package object.
1203             */
1204
1205            /*
1206             * Push the current state and create a new one
1207             */
1208            AcpiUtPushGenericState (&StateList, State);
1209            State = AcpiUtCreatePkgState (ThisSourceObj,
1210                                            State->Pkg.ThisTargetObj, 0);
1211            if (!State)
1212            {
1213                /* TBD: must delete package created up to this point */
1214
1215                return_ACPI_STATUS (AE_NO_MEMORY);
1216            }
1217        }
1218    }
1219
1220    /* We should never get here */
1221
1222    return (AE_AML_INTERNAL);
1223
1224}
1225
1226
1227/*******************************************************************************
1228 *
1229 * FUNCTION:    _ReportError
1230 *
1231 * PARAMETERS:  ModuleName          - Caller's module name (for error output)
1232 *              LineNumber          - Caller's line number (for error output)
1233 *              ComponentId         - Caller's component ID (for error output)
1234 *              Message             - Error message to use on failure
1235 *
1236 * RETURN:      None
1237 *
1238 * DESCRIPTION: Print error message
1239 *
1240 ******************************************************************************/
1241
1242void
1243_ReportError (
1244    NATIVE_CHAR             *ModuleName,
1245    UINT32                  LineNumber,
1246    UINT32                  ComponentId)
1247{
1248
1249
1250    AcpiOsPrintf ("%8s-%04d: *** Error: ", ModuleName, LineNumber);
1251}
1252
1253
1254/*******************************************************************************
1255 *
1256 * FUNCTION:    _ReportWarning
1257 *
1258 * PARAMETERS:  ModuleName          - Caller's module name (for error output)
1259 *              LineNumber          - Caller's line number (for error output)
1260 *              ComponentId         - Caller's component ID (for error output)
1261 *              Message             - Error message to use on failure
1262 *
1263 * RETURN:      None
1264 *
1265 * DESCRIPTION: Print warning message
1266 *
1267 ******************************************************************************/
1268
1269void
1270_ReportWarning (
1271    NATIVE_CHAR             *ModuleName,
1272    UINT32                  LineNumber,
1273    UINT32                  ComponentId)
1274{
1275
1276    AcpiOsPrintf ("%8s-%04d: *** Warning: ", ModuleName, LineNumber);
1277}
1278
1279
1280/*******************************************************************************
1281 *
1282 * FUNCTION:    _ReportInfo
1283 *
1284 * PARAMETERS:  ModuleName          - Caller's module name (for error output)
1285 *              LineNumber          - Caller's line number (for error output)
1286 *              ComponentId         - Caller's component ID (for error output)
1287 *              Message             - Error message to use on failure
1288 *
1289 * RETURN:      None
1290 *
1291 * DESCRIPTION: Print information message
1292 *
1293 ******************************************************************************/
1294
1295void
1296_ReportInfo (
1297    NATIVE_CHAR             *ModuleName,
1298    UINT32                  LineNumber,
1299    UINT32                  ComponentId)
1300{
1301
1302    AcpiOsPrintf ("%8s-%04d: *** Info: ", ModuleName, LineNumber);
1303}
1304
1305
1306