Home | History | Annotate | Line # | Download | only in events
evmisc.c revision 1.1
      1 /******************************************************************************
      2  *
      3  * Module Name: evmisc - Miscellaneous event manager support functions
      4  *
      5  *****************************************************************************/
      6 
      7 /******************************************************************************
      8  *
      9  * 1. Copyright Notice
     10  *
     11  * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp.
     12  * All rights reserved.
     13  *
     14  * 2. License
     15  *
     16  * 2.1. This is your license from Intel Corp. under its intellectual property
     17  * rights.  You may have additional license terms from the party that provided
     18  * you this software, covering your right to use that party's intellectual
     19  * property rights.
     20  *
     21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
     22  * copy of the source code appearing in this file ("Covered Code") an
     23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
     24  * base code distributed originally by Intel ("Original Intel Code") to copy,
     25  * make derivatives, distribute, use and display any portion of the Covered
     26  * Code in any form, with the right to sublicense such rights; and
     27  *
     28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
     29  * license (with the right to sublicense), under only those claims of Intel
     30  * patents that are infringed by the Original Intel Code, to make, use, sell,
     31  * offer to sell, and import the Covered Code and derivative works thereof
     32  * solely to the minimum extent necessary to exercise the above copyright
     33  * license, and in no event shall the patent license extend to any additions
     34  * to or modifications of the Original Intel Code.  No other license or right
     35  * is granted directly or by implication, estoppel or otherwise;
     36  *
     37  * The above copyright and patent license is granted only if the following
     38  * conditions are met:
     39  *
     40  * 3. Conditions
     41  *
     42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
     43  * Redistribution of source code of any substantial portion of the Covered
     44  * Code or modification with rights to further distribute source must include
     45  * the above Copyright Notice, the above License, this list of Conditions,
     46  * and the following Disclaimer and Export Compliance provision.  In addition,
     47  * Licensee must cause all Covered Code to which Licensee contributes to
     48  * contain a file documenting the changes Licensee made to create that Covered
     49  * Code and the date of any change.  Licensee must include in that file the
     50  * documentation of any changes made by any predecessor Licensee.  Licensee
     51  * must include a prominent statement that the modification is derived,
     52  * directly or indirectly, from Original Intel Code.
     53  *
     54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
     55  * Redistribution of source code of any substantial portion of the Covered
     56  * Code or modification without rights to further distribute source must
     57  * include the following Disclaimer and Export Compliance provision in the
     58  * documentation and/or other materials provided with distribution.  In
     59  * addition, Licensee may not authorize further sublicense of source of any
     60  * portion of the Covered Code, and must include terms to the effect that the
     61  * license from Licensee to its licensee is limited to the intellectual
     62  * property embodied in the software Licensee provides to its licensee, and
     63  * not to intellectual property embodied in modifications its licensee may
     64  * make.
     65  *
     66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
     67  * substantial portion of the Covered Code or modification must reproduce the
     68  * above Copyright Notice, and the following Disclaimer and Export Compliance
     69  * provision in the documentation and/or other materials provided with the
     70  * distribution.
     71  *
     72  * 3.4. Intel retains all right, title, and interest in and to the Original
     73  * Intel Code.
     74  *
     75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
     76  * Intel shall be used in advertising or otherwise to promote the sale, use or
     77  * other dealings in products derived from or relating to the Covered Code
     78  * without prior written authorization from Intel.
     79  *
     80  * 4. Disclaimer and Export Compliance
     81  *
     82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
     83  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
     84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
     85  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
     86  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
     87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
     88  * PARTICULAR PURPOSE.
     89  *
     90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
     91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
     92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
     93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
     94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
     95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
     96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
     97  * LIMITED REMEDY.
     98  *
     99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
    100  * software or system incorporating such software without first obtaining any
    101  * required license or other approval from the U. S. Department of Commerce or
    102  * any other agency or department of the United States Government.  In the
    103  * event Licensee exports any such software from the United States or
    104  * re-exports any such software from a foreign destination, Licensee shall
    105  * ensure that the distribution and export/re-export of the software is in
    106  * compliance with all laws, regulations, orders, or other restrictions of the
    107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
    108  * any of its subsidiaries will export/re-export any technical data, process,
    109  * software, or service, directly or indirectly, to any country for which the
    110  * United States government or any agency thereof requires an export license,
    111  * other governmental approval, or letter of assurance, without first obtaining
    112  * such license, approval or letter.
    113  *
    114  *****************************************************************************/
    115 
    116 #include "acpi.h"
    117 #include "accommon.h"
    118 #include "acevents.h"
    119 #include "acnamesp.h"
    120 #include "acinterp.h"
    121 
    122 #define _COMPONENT          ACPI_EVENTS
    123         ACPI_MODULE_NAME    ("evmisc")
    124 
    125 
    126 /* Local prototypes */
    127 
    128 static void ACPI_SYSTEM_XFACE
    129 AcpiEvNotifyDispatch (
    130     void                    *Context);
    131 
    132 static UINT32
    133 AcpiEvGlobalLockHandler (
    134     void                    *Context);
    135 
    136 static ACPI_STATUS
    137 AcpiEvRemoveGlobalLockHandler (
    138     void);
    139 
    140 
    141 /*******************************************************************************
    142  *
    143  * FUNCTION:    AcpiEvIsNotifyObject
    144  *
    145  * PARAMETERS:  Node            - Node to check
    146  *
    147  * RETURN:      TRUE if notifies allowed on this object
    148  *
    149  * DESCRIPTION: Check type of node for a object that supports notifies.
    150  *
    151  *              TBD: This could be replaced by a flag bit in the node.
    152  *
    153  ******************************************************************************/
    154 
    155 BOOLEAN
    156 AcpiEvIsNotifyObject (
    157     ACPI_NAMESPACE_NODE     *Node)
    158 {
    159     switch (Node->Type)
    160     {
    161     case ACPI_TYPE_DEVICE:
    162     case ACPI_TYPE_PROCESSOR:
    163     case ACPI_TYPE_THERMAL:
    164         /*
    165          * These are the ONLY objects that can receive ACPI notifications
    166          */
    167         return (TRUE);
    168 
    169     default:
    170         return (FALSE);
    171     }
    172 }
    173 
    174 
    175 /*******************************************************************************
    176  *
    177  * FUNCTION:    AcpiEvQueueNotifyRequest
    178  *
    179  * PARAMETERS:  Node            - NS node for the notified object
    180  *              NotifyValue     - Value from the Notify() request
    181  *
    182  * RETURN:      Status
    183  *
    184  * DESCRIPTION: Dispatch a device notification event to a previously
    185  *              installed handler.
    186  *
    187  ******************************************************************************/
    188 
    189 ACPI_STATUS
    190 AcpiEvQueueNotifyRequest (
    191     ACPI_NAMESPACE_NODE     *Node,
    192     UINT32                  NotifyValue)
    193 {
    194     ACPI_OPERAND_OBJECT     *ObjDesc;
    195     ACPI_OPERAND_OBJECT     *HandlerObj = NULL;
    196     ACPI_GENERIC_STATE      *NotifyInfo;
    197     ACPI_STATUS             Status = AE_OK;
    198 
    199 
    200     ACPI_FUNCTION_NAME (EvQueueNotifyRequest);
    201 
    202 
    203     /*
    204      * For value 3 (Ejection Request), some device method may need to be run.
    205      * For value 2 (Device Wake) if _PRW exists, the _PS0 method may need
    206      *   to be run.
    207      * For value 0x80 (Status Change) on the power button or sleep button,
    208      *   initiate soft-off or sleep operation?
    209      */
    210     ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
    211         "Dispatching Notify on [%4.4s] Node %p Value 0x%2.2X (%s)\n",
    212         AcpiUtGetNodeName (Node), Node, NotifyValue,
    213         AcpiUtGetNotifyName (NotifyValue)));
    214 
    215     /* Get the notify object attached to the NS Node */
    216 
    217     ObjDesc = AcpiNsGetAttachedObject (Node);
    218     if (ObjDesc)
    219     {
    220         /* We have the notify object, Get the right handler */
    221 
    222         switch (Node->Type)
    223         {
    224         /* Notify allowed only on these types */
    225 
    226         case ACPI_TYPE_DEVICE:
    227         case ACPI_TYPE_THERMAL:
    228         case ACPI_TYPE_PROCESSOR:
    229 
    230             if (NotifyValue <= ACPI_MAX_SYS_NOTIFY)
    231             {
    232                 HandlerObj = ObjDesc->CommonNotify.SystemNotify;
    233             }
    234             else
    235             {
    236                 HandlerObj = ObjDesc->CommonNotify.DeviceNotify;
    237             }
    238             break;
    239 
    240         default:
    241 
    242             /* All other types are not supported */
    243 
    244             return (AE_TYPE);
    245         }
    246     }
    247 
    248     /*
    249      * If there is any handler to run, schedule the dispatcher.
    250      * Check for:
    251      * 1) Global system notify handler
    252      * 2) Global device notify handler
    253      * 3) Per-device notify handler
    254      */
    255     if ((AcpiGbl_SystemNotify.Handler &&
    256             (NotifyValue <= ACPI_MAX_SYS_NOTIFY)) ||
    257         (AcpiGbl_DeviceNotify.Handler &&
    258             (NotifyValue > ACPI_MAX_SYS_NOTIFY))  ||
    259         HandlerObj)
    260     {
    261         NotifyInfo = AcpiUtCreateGenericState ();
    262         if (!NotifyInfo)
    263         {
    264             return (AE_NO_MEMORY);
    265         }
    266 
    267         if (!HandlerObj)
    268         {
    269             ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
    270                 "Executing system notify handler for Notify (%4.4s, %X) "
    271                 "node %p\n",
    272                 AcpiUtGetNodeName (Node), NotifyValue, Node));
    273         }
    274 
    275         NotifyInfo->Common.DescriptorType = ACPI_DESC_TYPE_STATE_NOTIFY;
    276         NotifyInfo->Notify.Node = Node;
    277         NotifyInfo->Notify.Value = (UINT16) NotifyValue;
    278         NotifyInfo->Notify.HandlerObj = HandlerObj;
    279 
    280         Status = AcpiOsExecute (
    281                     OSL_NOTIFY_HANDLER, AcpiEvNotifyDispatch, NotifyInfo);
    282         if (ACPI_FAILURE (Status))
    283         {
    284             AcpiUtDeleteGenericState (NotifyInfo);
    285         }
    286     }
    287     else
    288     {
    289         /* There is no notify handler (per-device or system) for this device */
    290 
    291         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
    292             "No notify handler for Notify (%4.4s, %X) node %p\n",
    293             AcpiUtGetNodeName (Node), NotifyValue, Node));
    294     }
    295 
    296     return (Status);
    297 }
    298 
    299 
    300 /*******************************************************************************
    301  *
    302  * FUNCTION:    AcpiEvNotifyDispatch
    303  *
    304  * PARAMETERS:  Context         - To be passed to the notify handler
    305  *
    306  * RETURN:      None.
    307  *
    308  * DESCRIPTION: Dispatch a device notification event to a previously
    309  *              installed handler.
    310  *
    311  ******************************************************************************/
    312 
    313 static void ACPI_SYSTEM_XFACE
    314 AcpiEvNotifyDispatch (
    315     void                    *Context)
    316 {
    317     ACPI_GENERIC_STATE      *NotifyInfo = (ACPI_GENERIC_STATE *) Context;
    318     ACPI_NOTIFY_HANDLER     GlobalHandler = NULL;
    319     void                    *GlobalContext = NULL;
    320     ACPI_OPERAND_OBJECT     *HandlerObj;
    321 
    322 
    323     ACPI_FUNCTION_ENTRY ();
    324 
    325 
    326     /*
    327      * We will invoke a global notify handler if installed. This is done
    328      * _before_ we invoke the per-device handler attached to the device.
    329      */
    330     if (NotifyInfo->Notify.Value <= ACPI_MAX_SYS_NOTIFY)
    331     {
    332         /* Global system notification handler */
    333 
    334         if (AcpiGbl_SystemNotify.Handler)
    335         {
    336             GlobalHandler = AcpiGbl_SystemNotify.Handler;
    337             GlobalContext = AcpiGbl_SystemNotify.Context;
    338         }
    339     }
    340     else
    341     {
    342         /* Global driver notification handler */
    343 
    344         if (AcpiGbl_DeviceNotify.Handler)
    345         {
    346             GlobalHandler = AcpiGbl_DeviceNotify.Handler;
    347             GlobalContext = AcpiGbl_DeviceNotify.Context;
    348         }
    349     }
    350 
    351     /* Invoke the system handler first, if present */
    352 
    353     if (GlobalHandler)
    354     {
    355         GlobalHandler (NotifyInfo->Notify.Node, NotifyInfo->Notify.Value,
    356             GlobalContext);
    357     }
    358 
    359     /* Now invoke the per-device handler, if present */
    360 
    361     HandlerObj = NotifyInfo->Notify.HandlerObj;
    362     if (HandlerObj)
    363     {
    364         HandlerObj->Notify.Handler (NotifyInfo->Notify.Node,
    365             NotifyInfo->Notify.Value,
    366             HandlerObj->Notify.Context);
    367     }
    368 
    369     /* All done with the info object */
    370 
    371     AcpiUtDeleteGenericState (NotifyInfo);
    372 }
    373 
    374 
    375 /*******************************************************************************
    376  *
    377  * FUNCTION:    AcpiEvGlobalLockHandler
    378  *
    379  * PARAMETERS:  Context         - From thread interface, not used
    380  *
    381  * RETURN:      ACPI_INTERRUPT_HANDLED
    382  *
    383  * DESCRIPTION: Invoked directly from the SCI handler when a global lock
    384  *              release interrupt occurs. Attempt to acquire the global lock,
    385  *              if successful, signal the thread waiting for the lock.
    386  *
    387  * NOTE: Assumes that the semaphore can be signaled from interrupt level. If
    388  * this is not possible for some reason, a separate thread will have to be
    389  * scheduled to do this.
    390  *
    391  ******************************************************************************/
    392 
    393 static UINT32
    394 AcpiEvGlobalLockHandler (
    395     void                    *Context)
    396 {
    397     BOOLEAN                 Acquired = FALSE;
    398     ACPI_STATUS             Status;
    399 
    400 
    401     /*
    402      * Attempt to get the lock.
    403      *
    404      * If we don't get it now, it will be marked pending and we will
    405      * take another interrupt when it becomes free.
    406      */
    407     ACPI_ACQUIRE_GLOBAL_LOCK (AcpiGbl_FACS, Acquired);
    408     if (Acquired)
    409     {
    410         /* Got the lock, now wake the thread waiting for it */
    411 
    412         AcpiGbl_GlobalLockAcquired = TRUE;
    413 
    414         /* Send a unit to the semaphore */
    415 
    416         Status = AcpiOsSignalSemaphore (AcpiGbl_GlobalLockSemaphore, 1);
    417         if (ACPI_FAILURE (Status))
    418         {
    419             ACPI_ERROR ((AE_INFO, "Could not signal Global Lock semaphore"));
    420         }
    421     }
    422 
    423     return (ACPI_INTERRUPT_HANDLED);
    424 }
    425 
    426 
    427 /*******************************************************************************
    428  *
    429  * FUNCTION:    AcpiEvInitGlobalLockHandler
    430  *
    431  * PARAMETERS:  None
    432  *
    433  * RETURN:      Status
    434  *
    435  * DESCRIPTION: Install a handler for the global lock release event
    436  *
    437  ******************************************************************************/
    438 
    439 ACPI_STATUS
    440 AcpiEvInitGlobalLockHandler (
    441     void)
    442 {
    443     ACPI_STATUS             Status;
    444 
    445 
    446     ACPI_FUNCTION_TRACE (EvInitGlobalLockHandler);
    447 
    448 
    449     /* Attempt installation of the global lock handler */
    450 
    451     Status = AcpiInstallFixedEventHandler (ACPI_EVENT_GLOBAL,
    452                 AcpiEvGlobalLockHandler, NULL);
    453 
    454     /*
    455      * If the global lock does not exist on this platform, the attempt to
    456      * enable GBL_STATUS will fail (the GBL_ENABLE bit will not stick).
    457      * Map to AE_OK, but mark global lock as not present. Any attempt to
    458      * actually use the global lock will be flagged with an error.
    459      */
    460     if (Status == AE_NO_HARDWARE_RESPONSE)
    461     {
    462         ACPI_ERROR ((AE_INFO,
    463             "No response from Global Lock hardware, disabling lock"));
    464 
    465         AcpiGbl_GlobalLockPresent = FALSE;
    466         return_ACPI_STATUS (AE_OK);
    467     }
    468 
    469     AcpiGbl_GlobalLockPresent = TRUE;
    470     return_ACPI_STATUS (Status);
    471 }
    472 
    473 
    474 /*******************************************************************************
    475  *
    476  * FUNCTION:    AcpiEvRemoveGlobalLockHandler
    477  *
    478  * PARAMETERS:  None
    479  *
    480  * RETURN:      Status
    481  *
    482  * DESCRIPTION: Remove the handler for the Global Lock
    483  *
    484  ******************************************************************************/
    485 
    486 static ACPI_STATUS
    487 AcpiEvRemoveGlobalLockHandler (
    488     void)
    489 {
    490     ACPI_STATUS             Status;
    491 
    492 
    493     ACPI_FUNCTION_TRACE (EvRemoveGlobalLockHandler);
    494 
    495     AcpiGbl_GlobalLockPresent = FALSE;
    496     Status = AcpiRemoveFixedEventHandler (ACPI_EVENT_GLOBAL,
    497                 AcpiEvGlobalLockHandler);
    498 
    499     return_ACPI_STATUS (Status);
    500 }
    501 
    502 
    503 /******************************************************************************
    504  *
    505  * FUNCTION:    AcpiEvAcquireGlobalLock
    506  *
    507  * PARAMETERS:  Timeout         - Max time to wait for the lock, in millisec.
    508  *
    509  * RETURN:      Status
    510  *
    511  * DESCRIPTION: Attempt to gain ownership of the Global Lock.
    512  *
    513  * MUTEX:       Interpreter must be locked
    514  *
    515  * Note: The original implementation allowed multiple threads to "acquire" the
    516  * Global Lock, and the OS would hold the lock until the last thread had
    517  * released it. However, this could potentially starve the BIOS out of the
    518  * lock, especially in the case where there is a tight handshake between the
    519  * Embedded Controller driver and the BIOS. Therefore, this implementation
    520  * allows only one thread to acquire the HW Global Lock at a time, and makes
    521  * the global lock appear as a standard mutex on the OS side.
    522  *
    523  *****************************************************************************/
    524 
    525 ACPI_STATUS
    526 AcpiEvAcquireGlobalLock (
    527     UINT16                  Timeout)
    528 {
    529     ACPI_STATUS             Status = AE_OK;
    530     BOOLEAN                 Acquired = FALSE;
    531 
    532 
    533     ACPI_FUNCTION_TRACE (EvAcquireGlobalLock);
    534 
    535 
    536     /*
    537      * Only one thread can acquire the GL at a time, the GlobalLockMutex
    538      * enforces this. This interface releases the interpreter if we must wait.
    539      */
    540     Status = AcpiExSystemWaitMutex (AcpiGbl_GlobalLockMutex->Mutex.OsMutex,
    541                 Timeout);
    542     if (ACPI_FAILURE (Status))
    543     {
    544         return_ACPI_STATUS (Status);
    545     }
    546 
    547     /*
    548      * Update the global lock handle and check for wraparound. The handle is
    549      * only used for the external global lock interfaces, but it is updated
    550      * here to properly handle the case where a single thread may acquire the
    551      * lock via both the AML and the AcpiAcquireGlobalLock interfaces. The
    552      * handle is therefore updated on the first acquire from a given thread
    553      * regardless of where the acquisition request originated.
    554      */
    555     AcpiGbl_GlobalLockHandle++;
    556     if (AcpiGbl_GlobalLockHandle == 0)
    557     {
    558         AcpiGbl_GlobalLockHandle = 1;
    559     }
    560 
    561     /*
    562      * Make sure that a global lock actually exists. If not, just treat the
    563      * lock as a standard mutex.
    564      */
    565     if (!AcpiGbl_GlobalLockPresent)
    566     {
    567         AcpiGbl_GlobalLockAcquired = TRUE;
    568         return_ACPI_STATUS (AE_OK);
    569     }
    570 
    571     /* Attempt to acquire the actual hardware lock */
    572 
    573     ACPI_ACQUIRE_GLOBAL_LOCK (AcpiGbl_FACS, Acquired);
    574     if (Acquired)
    575     {
    576        /* We got the lock */
    577 
    578         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Acquired hardware Global Lock\n"));
    579 
    580         AcpiGbl_GlobalLockAcquired = TRUE;
    581         return_ACPI_STATUS (AE_OK);
    582     }
    583 
    584     /*
    585      * Did not get the lock. The pending bit was set above, and we must now
    586      * wait until we get the global lock released interrupt.
    587      */
    588     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Waiting for hardware Global Lock\n"));
    589 
    590     /*
    591      * Wait for handshake with the global lock interrupt handler.
    592      * This interface releases the interpreter if we must wait.
    593      */
    594     Status = AcpiExSystemWaitSemaphore (AcpiGbl_GlobalLockSemaphore,
    595                 ACPI_WAIT_FOREVER);
    596 
    597     return_ACPI_STATUS (Status);
    598 }
    599 
    600 
    601 /*******************************************************************************
    602  *
    603  * FUNCTION:    AcpiEvReleaseGlobalLock
    604  *
    605  * PARAMETERS:  None
    606  *
    607  * RETURN:      Status
    608  *
    609  * DESCRIPTION: Releases ownership of the Global Lock.
    610  *
    611  ******************************************************************************/
    612 
    613 ACPI_STATUS
    614 AcpiEvReleaseGlobalLock (
    615     void)
    616 {
    617     BOOLEAN                 Pending = FALSE;
    618     ACPI_STATUS             Status = AE_OK;
    619 
    620 
    621     ACPI_FUNCTION_TRACE (EvReleaseGlobalLock);
    622 
    623 
    624     /* Lock must be already acquired */
    625 
    626     if (!AcpiGbl_GlobalLockAcquired)
    627     {
    628         ACPI_WARNING ((AE_INFO,
    629             "Cannot release the ACPI Global Lock, it has not been acquired"));
    630         return_ACPI_STATUS (AE_NOT_ACQUIRED);
    631     }
    632 
    633     if (AcpiGbl_GlobalLockPresent)
    634     {
    635         /* Allow any thread to release the lock */
    636 
    637         ACPI_RELEASE_GLOBAL_LOCK (AcpiGbl_FACS, Pending);
    638 
    639         /*
    640          * If the pending bit was set, we must write GBL_RLS to the control
    641          * register
    642          */
    643         if (Pending)
    644         {
    645             Status = AcpiWriteBitRegister (
    646                         ACPI_BITREG_GLOBAL_LOCK_RELEASE, ACPI_ENABLE_EVENT);
    647         }
    648 
    649         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Released hardware Global Lock\n"));
    650     }
    651 
    652     AcpiGbl_GlobalLockAcquired = FALSE;
    653 
    654     /* Release the local GL mutex */
    655 
    656     AcpiOsReleaseMutex (AcpiGbl_GlobalLockMutex->Mutex.OsMutex);
    657     return_ACPI_STATUS (Status);
    658 }
    659 
    660 
    661 /******************************************************************************
    662  *
    663  * FUNCTION:    AcpiEvTerminate
    664  *
    665  * PARAMETERS:  none
    666  *
    667  * RETURN:      none
    668  *
    669  * DESCRIPTION: Disable events and free memory allocated for table storage.
    670  *
    671  ******************************************************************************/
    672 
    673 void
    674 AcpiEvTerminate (
    675     void)
    676 {
    677     UINT32                  i;
    678     ACPI_STATUS             Status;
    679 
    680 
    681     ACPI_FUNCTION_TRACE (EvTerminate);
    682 
    683 
    684     if (AcpiGbl_EventsInitialized)
    685     {
    686         /*
    687          * Disable all event-related functionality. In all cases, on error,
    688          * print a message but obviously we don't abort.
    689          */
    690 
    691         /* Disable all fixed events */
    692 
    693         for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++)
    694         {
    695             Status = AcpiDisableEvent (i, 0);
    696             if (ACPI_FAILURE (Status))
    697             {
    698                 ACPI_ERROR ((AE_INFO,
    699                     "Could not disable fixed event %u", (UINT32) i));
    700             }
    701         }
    702 
    703         /* Disable all GPEs in all GPE blocks */
    704 
    705         Status = AcpiEvWalkGpeList (AcpiHwDisableGpeBlock, NULL);
    706 
    707         /* Remove SCI handler */
    708 
    709         Status = AcpiEvRemoveSciHandler ();
    710         if (ACPI_FAILURE(Status))
    711         {
    712             ACPI_ERROR ((AE_INFO,
    713                 "Could not remove SCI handler"));
    714         }
    715 
    716         Status = AcpiEvRemoveGlobalLockHandler ();
    717         if (ACPI_FAILURE(Status))
    718         {
    719             ACPI_ERROR ((AE_INFO,
    720                 "Could not remove Global Lock handler"));
    721         }
    722     }
    723 
    724     /* Deallocate all handler objects installed within GPE info structs */
    725 
    726     Status = AcpiEvWalkGpeList (AcpiEvDeleteGpeHandlers, NULL);
    727 
    728     /* Return to original mode if necessary */
    729 
    730     if (AcpiGbl_OriginalMode == ACPI_SYS_MODE_LEGACY)
    731     {
    732         Status = AcpiDisable ();
    733         if (ACPI_FAILURE (Status))
    734         {
    735             ACPI_WARNING ((AE_INFO, "AcpiDisable failed"));
    736         }
    737     }
    738     return_VOID;
    739 }
    740 
    741