utmisc.c revision 77424
1/*******************************************************************************
2 *
3 * Module Name: utmisc - common utility procedures
4 *              $Revision: 42 $
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                    AcpiUtFormatException (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                    AcpiUtFormatException (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 = AcpiUtCallocate (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        AcpiUtFree (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        AcpiUtFree (AcpiGbl_GenericStateCache);
976        AcpiGbl_GenericStateCache = Next;
977        AcpiGbl_GenericStateCacheDepth--;
978    }
979
980    return_VOID;
981}
982
983
984/*******************************************************************************
985 *
986 * FUNCTION:    AcpiUtResolvePackageReferences
987 *
988 * PARAMETERS:  ObjDesc         - The Package object on which to resolve refs
989 *
990 * RETURN:      Status
991 *
992 * DESCRIPTION: Walk through a package and turn internal references into values
993 *
994 ******************************************************************************/
995
996ACPI_STATUS
997AcpiUtResolvePackageReferences (
998    ACPI_OPERAND_OBJECT     *ObjDesc)
999{
1000    UINT32                  Count;
1001    ACPI_OPERAND_OBJECT     *SubObject;
1002
1003
1004    FUNCTION_TRACE ("AcpiUtResolvePackageReferences");
1005
1006
1007    if (ObjDesc->Common.Type != ACPI_TYPE_PACKAGE)
1008    {
1009        /* The object must be a package */
1010
1011        REPORT_ERROR (("Must resolve Package Refs on a Package\n"));
1012        return_ACPI_STATUS(AE_ERROR);
1013    }
1014
1015    /*
1016     * TBD: what about nested packages? */
1017
1018    for (Count = 0; Count < ObjDesc->Package.Count; Count++)
1019    {
1020        SubObject = ObjDesc->Package.Elements[Count];
1021
1022        if (SubObject->Common.Type == INTERNAL_TYPE_REFERENCE)
1023        {
1024            if (SubObject->Reference.Opcode == AML_ZERO_OP)
1025            {
1026                SubObject->Common.Type  = ACPI_TYPE_INTEGER;
1027                SubObject->Integer.Value = 0;
1028            }
1029
1030            else if (SubObject->Reference.Opcode == AML_ONE_OP)
1031            {
1032                SubObject->Common.Type  = ACPI_TYPE_INTEGER;
1033                SubObject->Integer.Value = 1;
1034            }
1035
1036            else if (SubObject->Reference.Opcode == AML_ONES_OP)
1037            {
1038                SubObject->Common.Type  = ACPI_TYPE_INTEGER;
1039                SubObject->Integer.Value = ACPI_INTEGER_MAX;
1040            }
1041        }
1042    }
1043
1044    return_ACPI_STATUS(AE_OK);
1045}
1046
1047#ifdef ACPI_DEBUG
1048
1049/*******************************************************************************
1050 *
1051 * FUNCTION:    AcpiUtDisplayInitPathname
1052 *
1053 * PARAMETERS:  ObjHandle           - Handle whose pathname will be displayed
1054 *              Path                - Additional path string to be appended
1055 *
1056 * RETURN:      ACPI_STATUS
1057 *
1058 * DESCRIPTION: Display full pathnbame of an object, DEBUG ONLY
1059 *
1060 ******************************************************************************/
1061
1062void
1063AcpiUtDisplayInitPathname (
1064    ACPI_HANDLE             ObjHandle,
1065    char                    *Path)
1066{
1067    ACPI_STATUS             Status;
1068    UINT32                  Length = 128;
1069    char                    Buffer[128];
1070
1071
1072    Status = AcpiNsHandleToPathname (ObjHandle, &Length, Buffer);
1073    if (ACPI_SUCCESS (Status))
1074    {
1075        if (Path)
1076        {
1077            DEBUG_PRINT (TRACE_INIT, ("%s.%s\n", Buffer, Path))
1078        }
1079        else
1080        {
1081            DEBUG_PRINT (TRACE_INIT, ("%s\n", Buffer))
1082        }
1083    }
1084}
1085#endif
1086
1087/*******************************************************************************
1088 *
1089 * FUNCTION:    AcpiUtWalkPackageTree
1090 *
1091 * PARAMETERS:  ObjDesc         - The Package object on which to resolve refs
1092 *
1093 * RETURN:      Status
1094 *
1095 * DESCRIPTION: Walk through a package
1096 *
1097 ******************************************************************************/
1098
1099ACPI_STATUS
1100AcpiUtWalkPackageTree (
1101    ACPI_OPERAND_OBJECT     *SourceObject,
1102    void                    *TargetObject,
1103    ACPI_PKG_CALLBACK       WalkCallback,
1104    void                    *Context)
1105{
1106    ACPI_STATUS             Status = AE_OK;
1107    ACPI_GENERIC_STATE      *StateList = NULL;
1108    ACPI_GENERIC_STATE      *State;
1109    UINT32                  ThisIndex;
1110    ACPI_OPERAND_OBJECT     *ThisSourceObj;
1111
1112
1113    FUNCTION_TRACE ("AcpiUtWalkPackageTree");
1114
1115
1116    State = AcpiUtCreatePkgState (SourceObject, TargetObject, 0);
1117    if (!State)
1118    {
1119        return_ACPI_STATUS (AE_NO_MEMORY);
1120    }
1121
1122    while (State)
1123    {
1124        ThisIndex     = State->Pkg.Index;
1125        ThisSourceObj = (ACPI_OPERAND_OBJECT *)
1126                        State->Pkg.SourceObject->Package.Elements[ThisIndex];
1127
1128        /*
1129         * Check for
1130         * 1) An uninitialized package element.  It is completely
1131         *      legal to declare a package and leave it uninitialized
1132         * 2) Not an internal object - can be a namespace node instead
1133         * 3) Any type other than a package.  Packages are handled in else
1134         *      case below.
1135         */
1136        if ((!ThisSourceObj) ||
1137            (!VALID_DESCRIPTOR_TYPE (
1138                    ThisSourceObj, ACPI_DESC_TYPE_INTERNAL)) ||
1139            (!IS_THIS_OBJECT_TYPE (
1140                    ThisSourceObj, ACPI_TYPE_PACKAGE)))
1141        {
1142
1143            Status = WalkCallback (ACPI_COPY_TYPE_SIMPLE, ThisSourceObj,
1144                                    State, Context);
1145            if (ACPI_FAILURE (Status))
1146            {
1147                /* TBD: must delete package created up to this point */
1148
1149                return_ACPI_STATUS (Status);
1150            }
1151
1152            State->Pkg.Index++;
1153            while (State->Pkg.Index >= State->Pkg.SourceObject->Package.Count)
1154            {
1155                /*
1156                 * We've handled all of the objects at this level,  This means
1157                 * that we have just completed a package.  That package may
1158                 * have contained one or more packages itself.
1159                 *
1160                 * Delete this state and pop the previous state (package).
1161                 */
1162                AcpiUtDeleteGenericState (State);
1163                State = AcpiUtPopGenericState (&StateList);
1164
1165
1166                /* Finished when there are no more states */
1167
1168                if (!State)
1169                {
1170                    /*
1171                     * We have handled all of the objects in the top level
1172                     * package just add the length of the package objects
1173                     * and exit
1174                     */
1175                    return_ACPI_STATUS (AE_OK);
1176                }
1177
1178                /*
1179                 * Go back up a level and move the index past the just
1180                 * completed package object.
1181                 */
1182                State->Pkg.Index++;
1183            }
1184        }
1185
1186        else
1187        {
1188            /* This is a sub-object of type package */
1189
1190            Status = WalkCallback (ACPI_COPY_TYPE_PACKAGE, ThisSourceObj,
1191                                        State, Context);
1192            if (ACPI_FAILURE (Status))
1193            {
1194                /* TBD: must delete package created up to this point */
1195
1196                return_ACPI_STATUS (Status);
1197            }
1198
1199
1200            /*
1201             * The callback above returned a new target package object.
1202             */
1203
1204            /*
1205             * Push the current state and create a new one
1206             */
1207            AcpiUtPushGenericState (&StateList, State);
1208            State = AcpiUtCreatePkgState (ThisSourceObj,
1209                                            State->Pkg.ThisTargetObj, 0);
1210            if (!State)
1211            {
1212                /* TBD: must delete package created up to this point */
1213
1214                return_ACPI_STATUS (AE_NO_MEMORY);
1215            }
1216        }
1217    }
1218
1219    /* We should never get here */
1220
1221    return (AE_AML_INTERNAL);
1222
1223}
1224
1225
1226/*******************************************************************************
1227 *
1228 * FUNCTION:    _ReportError
1229 *
1230 * PARAMETERS:  ModuleName          - Caller's module name (for error output)
1231 *              LineNumber          - Caller's line number (for error output)
1232 *              ComponentId         - Caller's component ID (for error output)
1233 *              Message             - Error message to use on failure
1234 *
1235 * RETURN:      None
1236 *
1237 * DESCRIPTION: Print error message
1238 *
1239 ******************************************************************************/
1240
1241void
1242_ReportError (
1243    NATIVE_CHAR             *ModuleName,
1244    UINT32                  LineNumber,
1245    UINT32                  ComponentId)
1246{
1247
1248
1249    AcpiOsPrintf ("%8s-%04d: *** Error: ", ModuleName, LineNumber);
1250}
1251
1252
1253/*******************************************************************************
1254 *
1255 * FUNCTION:    _ReportWarning
1256 *
1257 * PARAMETERS:  ModuleName          - Caller's module name (for error output)
1258 *              LineNumber          - Caller's line number (for error output)
1259 *              ComponentId         - Caller's component ID (for error output)
1260 *              Message             - Error message to use on failure
1261 *
1262 * RETURN:      None
1263 *
1264 * DESCRIPTION: Print warning message
1265 *
1266 ******************************************************************************/
1267
1268void
1269_ReportWarning (
1270    NATIVE_CHAR             *ModuleName,
1271    UINT32                  LineNumber,
1272    UINT32                  ComponentId)
1273{
1274
1275    AcpiOsPrintf ("%8s-%04d: *** Warning: ", ModuleName, LineNumber);
1276}
1277
1278
1279/*******************************************************************************
1280 *
1281 * FUNCTION:    _ReportInfo
1282 *
1283 * PARAMETERS:  ModuleName          - Caller's module name (for error output)
1284 *              LineNumber          - Caller's line number (for error output)
1285 *              ComponentId         - Caller's component ID (for error output)
1286 *              Message             - Error message to use on failure
1287 *
1288 * RETURN:      None
1289 *
1290 * DESCRIPTION: Print information message
1291 *
1292 ******************************************************************************/
1293
1294void
1295_ReportInfo (
1296    NATIVE_CHAR             *ModuleName,
1297    UINT32                  LineNumber,
1298    UINT32                  ComponentId)
1299{
1300
1301    AcpiOsPrintf ("%8s-%04d: *** Info: ", ModuleName, LineNumber);
1302}
1303
1304
1305