Home | History | Annotate | Line # | Download | only in events
evxface.c revision 1.8
      1 /******************************************************************************
      2  *
      3  * Module Name: evxface - External interfaces for ACPI events
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2016, Intel Corp.
      9  * All rights reserved.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions, and the following disclaimer,
     16  *    without modification.
     17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
     18  *    substantially similar to the "NO WARRANTY" disclaimer below
     19  *    ("Disclaimer") and any redistribution must be conditioned upon
     20  *    including a substantially similar Disclaimer requirement for further
     21  *    binary redistribution.
     22  * 3. Neither the names of the above-listed copyright holders nor the names
     23  *    of any contributors may be used to endorse or promote products derived
     24  *    from this software without specific prior written permission.
     25  *
     26  * Alternatively, this software may be distributed under the terms of the
     27  * GNU General Public License ("GPL") version 2 as published by the Free
     28  * Software Foundation.
     29  *
     30  * NO WARRANTY
     31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
     34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
     40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     41  * POSSIBILITY OF SUCH DAMAGES.
     42  */
     43 
     44 #define EXPORT_ACPI_INTERFACES
     45 
     46 #include "acpi.h"
     47 #include "accommon.h"
     48 #include "acnamesp.h"
     49 #include "acevents.h"
     50 #include "acinterp.h"
     51 
     52 #define _COMPONENT          ACPI_EVENTS
     53         ACPI_MODULE_NAME    ("evxface")
     54 
     55 #if (!ACPI_REDUCED_HARDWARE)
     56 
     57 /* Local prototypes */
     58 
     59 static ACPI_STATUS
     60 AcpiEvInstallGpeHandler (
     61     ACPI_HANDLE             GpeDevice,
     62     UINT32                  GpeNumber,
     63     UINT32                  Type,
     64     BOOLEAN                 IsRawHandler,
     65     ACPI_GPE_HANDLER        Address,
     66     void                    *Context);
     67 
     68 #endif
     69 
     70 
     71 /*******************************************************************************
     72  *
     73  * FUNCTION:    AcpiInstallNotifyHandler
     74  *
     75  * PARAMETERS:  Device          - The device for which notifies will be handled
     76  *              HandlerType     - The type of handler:
     77  *                                  ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
     78  *                                  ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
     79  *                                  ACPI_ALL_NOTIFY:    Both System and Device
     80  *              Handler         - Address of the handler
     81  *              Context         - Value passed to the handler on each GPE
     82  *
     83  * RETURN:      Status
     84  *
     85  * DESCRIPTION: Install a handler for notifications on an ACPI Device,
     86  *              ThermalZone, or Processor object.
     87  *
     88  * NOTES:       The Root namespace object may have only one handler for each
     89  *              type of notify (System/Device). Device/Thermal/Processor objects
     90  *              may have one device notify handler, and multiple system notify
     91  *              handlers.
     92  *
     93  ******************************************************************************/
     94 
     95 ACPI_STATUS
     96 AcpiInstallNotifyHandler (
     97     ACPI_HANDLE             Device,
     98     UINT32                  HandlerType,
     99     ACPI_NOTIFY_HANDLER     Handler,
    100     void                    *Context)
    101 {
    102     ACPI_NAMESPACE_NODE     *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device);
    103     ACPI_OPERAND_OBJECT     *ObjDesc;
    104     ACPI_OPERAND_OBJECT     *HandlerObj;
    105     ACPI_STATUS             Status;
    106     UINT32                  i;
    107 
    108 
    109     ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler);
    110 
    111 
    112     /* Parameter validation */
    113 
    114     if ((!Device) || (!Handler) || (!HandlerType) ||
    115         (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
    116     {
    117         return_ACPI_STATUS (AE_BAD_PARAMETER);
    118     }
    119 
    120     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    121     if (ACPI_FAILURE (Status))
    122     {
    123         return_ACPI_STATUS (Status);
    124     }
    125 
    126     /*
    127      * Root Object:
    128      * Registering a notify handler on the root object indicates that the
    129      * caller wishes to receive notifications for all objects. Note that
    130      * only one global handler can be registered per notify type.
    131      * Ensure that a handler is not already installed.
    132      */
    133     if (Device == ACPI_ROOT_OBJECT)
    134     {
    135         for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
    136         {
    137             if (HandlerType & (i+1))
    138             {
    139                 if (AcpiGbl_GlobalNotify[i].Handler)
    140                 {
    141                     Status = AE_ALREADY_EXISTS;
    142                     goto UnlockAndExit;
    143                 }
    144 
    145                 AcpiGbl_GlobalNotify[i].Handler = Handler;
    146                 AcpiGbl_GlobalNotify[i].Context = Context;
    147             }
    148         }
    149 
    150         goto UnlockAndExit; /* Global notify handler installed, all done */
    151     }
    152 
    153     /*
    154      * All Other Objects:
    155      * Caller will only receive notifications specific to the target
    156      * object. Note that only certain object types are allowed to
    157      * receive notifications.
    158      */
    159 
    160     /* Are Notifies allowed on this object? */
    161 
    162     if (!AcpiEvIsNotifyObject (Node))
    163     {
    164         Status = AE_TYPE;
    165         goto UnlockAndExit;
    166     }
    167 
    168     /* Check for an existing internal object, might not exist */
    169 
    170     ObjDesc = AcpiNsGetAttachedObject (Node);
    171     if (!ObjDesc)
    172     {
    173         /* Create a new object */
    174 
    175         ObjDesc = AcpiUtCreateInternalObject (Node->Type);
    176         if (!ObjDesc)
    177         {
    178             Status = AE_NO_MEMORY;
    179             goto UnlockAndExit;
    180         }
    181 
    182         /* Attach new object to the Node, remove local reference */
    183 
    184         Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type);
    185         AcpiUtRemoveReference (ObjDesc);
    186         if (ACPI_FAILURE (Status))
    187         {
    188             goto UnlockAndExit;
    189         }
    190     }
    191 
    192     /* Ensure that the handler is not already installed in the lists */
    193 
    194     for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
    195     {
    196         if (HandlerType & (i+1))
    197         {
    198             HandlerObj = ObjDesc->CommonNotify.NotifyList[i];
    199             while (HandlerObj)
    200             {
    201                 if (HandlerObj->Notify.Handler == Handler)
    202                 {
    203                     Status = AE_ALREADY_EXISTS;
    204                     goto UnlockAndExit;
    205                 }
    206 
    207                 HandlerObj = HandlerObj->Notify.Next[i];
    208             }
    209         }
    210     }
    211 
    212     /* Create and populate a new notify handler object */
    213 
    214     HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY);
    215     if (!HandlerObj)
    216     {
    217         Status = AE_NO_MEMORY;
    218         goto UnlockAndExit;
    219     }
    220 
    221     HandlerObj->Notify.Node = Node;
    222     HandlerObj->Notify.HandlerType = HandlerType;
    223     HandlerObj->Notify.Handler = Handler;
    224     HandlerObj->Notify.Context = Context;
    225 
    226     /* Install the handler at the list head(s) */
    227 
    228     for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
    229     {
    230         if (HandlerType & (i+1))
    231         {
    232             HandlerObj->Notify.Next[i] =
    233                 ObjDesc->CommonNotify.NotifyList[i];
    234 
    235             ObjDesc->CommonNotify.NotifyList[i] = HandlerObj;
    236         }
    237     }
    238 
    239     /* Add an extra reference if handler was installed in both lists */
    240 
    241     if (HandlerType == ACPI_ALL_NOTIFY)
    242     {
    243         AcpiUtAddReference (HandlerObj);
    244     }
    245 
    246 
    247 UnlockAndExit:
    248     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    249     return_ACPI_STATUS (Status);
    250 }
    251 
    252 ACPI_EXPORT_SYMBOL (AcpiInstallNotifyHandler)
    253 
    254 
    255 /*******************************************************************************
    256  *
    257  * FUNCTION:    AcpiRemoveNotifyHandler
    258  *
    259  * PARAMETERS:  Device          - The device for which the handler is installed
    260  *              HandlerType     - The type of handler:
    261  *                                  ACPI_SYSTEM_NOTIFY: System Handler (00-7F)
    262  *                                  ACPI_DEVICE_NOTIFY: Device Handler (80-FF)
    263  *                                  ACPI_ALL_NOTIFY:    Both System and Device
    264  *              Handler         - Address of the handler
    265  *
    266  * RETURN:      Status
    267  *
    268  * DESCRIPTION: Remove a handler for notifies on an ACPI device
    269  *
    270  ******************************************************************************/
    271 
    272 ACPI_STATUS
    273 AcpiRemoveNotifyHandler (
    274     ACPI_HANDLE             Device,
    275     UINT32                  HandlerType,
    276     ACPI_NOTIFY_HANDLER     Handler)
    277 {
    278     ACPI_NAMESPACE_NODE     *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device);
    279     ACPI_OPERAND_OBJECT     *ObjDesc;
    280     ACPI_OPERAND_OBJECT     *HandlerObj;
    281     ACPI_OPERAND_OBJECT     *PreviousHandlerObj;
    282     ACPI_STATUS             Status = AE_OK;
    283     UINT32                  i;
    284 
    285 
    286     ACPI_FUNCTION_TRACE (AcpiRemoveNotifyHandler);
    287 
    288 
    289     /* Parameter validation */
    290 
    291     if ((!Device) || (!Handler) || (!HandlerType) ||
    292         (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
    293     {
    294         return_ACPI_STATUS (AE_BAD_PARAMETER);
    295     }
    296 
    297     /* Root Object. Global handlers are removed here */
    298 
    299     if (Device == ACPI_ROOT_OBJECT)
    300     {
    301         for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
    302         {
    303             if (HandlerType & (i+1))
    304             {
    305                 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    306                 if (ACPI_FAILURE (Status))
    307                 {
    308                     return_ACPI_STATUS (Status);
    309                 }
    310 
    311                 if (!AcpiGbl_GlobalNotify[i].Handler ||
    312                     (AcpiGbl_GlobalNotify[i].Handler != Handler))
    313                 {
    314                     Status = AE_NOT_EXIST;
    315                     goto UnlockAndExit;
    316                 }
    317 
    318                 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
    319                     "Removing global notify handler\n"));
    320 
    321                 AcpiGbl_GlobalNotify[i].Handler = NULL;
    322                 AcpiGbl_GlobalNotify[i].Context = NULL;
    323 
    324                 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    325 
    326                 /* Make sure all deferred notify tasks are completed */
    327 
    328                 AcpiOsWaitEventsComplete ();
    329             }
    330         }
    331 
    332         return_ACPI_STATUS (AE_OK);
    333     }
    334 
    335     /* All other objects: Are Notifies allowed on this object? */
    336 
    337     if (!AcpiEvIsNotifyObject (Node))
    338     {
    339         return_ACPI_STATUS (AE_TYPE);
    340     }
    341 
    342     /* Must have an existing internal object */
    343 
    344     ObjDesc = AcpiNsGetAttachedObject (Node);
    345     if (!ObjDesc)
    346     {
    347         return_ACPI_STATUS (AE_NOT_EXIST);
    348     }
    349 
    350     /* Internal object exists. Find the handler and remove it */
    351 
    352     for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
    353     {
    354         if (HandlerType & (i+1))
    355         {
    356             Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    357             if (ACPI_FAILURE (Status))
    358             {
    359                 return_ACPI_STATUS (Status);
    360             }
    361 
    362             HandlerObj = ObjDesc->CommonNotify.NotifyList[i];
    363             PreviousHandlerObj = NULL;
    364 
    365             /* Attempt to find the handler in the handler list */
    366 
    367             while (HandlerObj &&
    368                   (HandlerObj->Notify.Handler != Handler))
    369             {
    370                 PreviousHandlerObj = HandlerObj;
    371                 HandlerObj = HandlerObj->Notify.Next[i];
    372             }
    373 
    374             if (!HandlerObj)
    375             {
    376                 Status = AE_NOT_EXIST;
    377                 goto UnlockAndExit;
    378             }
    379 
    380             /* Remove the handler object from the list */
    381 
    382             if (PreviousHandlerObj) /* Handler is not at the list head */
    383             {
    384                 PreviousHandlerObj->Notify.Next[i] =
    385                     HandlerObj->Notify.Next[i];
    386             }
    387             else /* Handler is at the list head */
    388             {
    389                 ObjDesc->CommonNotify.NotifyList[i] =
    390                     HandlerObj->Notify.Next[i];
    391             }
    392 
    393             (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    394 
    395             /* Make sure all deferred notify tasks are completed */
    396 
    397             AcpiOsWaitEventsComplete ();
    398             AcpiUtRemoveReference (HandlerObj);
    399         }
    400     }
    401 
    402     return_ACPI_STATUS (Status);
    403 
    404 
    405 UnlockAndExit:
    406     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    407     return_ACPI_STATUS (Status);
    408 }
    409 
    410 ACPI_EXPORT_SYMBOL (AcpiRemoveNotifyHandler)
    411 
    412 
    413 /*******************************************************************************
    414  *
    415  * FUNCTION:    AcpiInstallExceptionHandler
    416  *
    417  * PARAMETERS:  Handler         - Pointer to the handler function for the
    418  *                                event
    419  *
    420  * RETURN:      Status
    421  *
    422  * DESCRIPTION: Saves the pointer to the handler function
    423  *
    424  ******************************************************************************/
    425 
    426 ACPI_STATUS
    427 AcpiInstallExceptionHandler (
    428     ACPI_EXCEPTION_HANDLER  Handler)
    429 {
    430     ACPI_STATUS             Status;
    431 
    432 
    433     ACPI_FUNCTION_TRACE (AcpiInstallExceptionHandler);
    434 
    435 
    436     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
    437     if (ACPI_FAILURE (Status))
    438     {
    439         return_ACPI_STATUS (Status);
    440     }
    441 
    442     /* Don't allow two handlers. */
    443 
    444     if (AcpiGbl_ExceptionHandler)
    445     {
    446         Status = AE_ALREADY_EXISTS;
    447         goto Cleanup;
    448     }
    449 
    450     /* Install the handler */
    451 
    452     AcpiGbl_ExceptionHandler = Handler;
    453 
    454 Cleanup:
    455     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
    456     return_ACPI_STATUS (Status);
    457 }
    458 
    459 ACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler)
    460 
    461 
    462 #if (!ACPI_REDUCED_HARDWARE)
    463 /*******************************************************************************
    464  *
    465  * FUNCTION:    AcpiInstallSciHandler
    466  *
    467  * PARAMETERS:  Address             - Address of the handler
    468  *              Context             - Value passed to the handler on each SCI
    469  *
    470  * RETURN:      Status
    471  *
    472  * DESCRIPTION: Install a handler for a System Control Interrupt.
    473  *
    474  ******************************************************************************/
    475 
    476 ACPI_STATUS
    477 AcpiInstallSciHandler (
    478     ACPI_SCI_HANDLER        Address,
    479     void                    *Context)
    480 {
    481     ACPI_SCI_HANDLER_INFO   *NewSciHandler;
    482     ACPI_SCI_HANDLER_INFO   *SciHandler;
    483     ACPI_CPU_FLAGS          Flags;
    484     ACPI_STATUS             Status;
    485 
    486 
    487     ACPI_FUNCTION_TRACE (AcpiInstallSciHandler);
    488 
    489 
    490     if (!Address)
    491     {
    492         return_ACPI_STATUS (AE_BAD_PARAMETER);
    493     }
    494 
    495     /* Allocate and init a handler object */
    496 
    497     NewSciHandler = ACPI_ALLOCATE (sizeof (ACPI_SCI_HANDLER_INFO));
    498     if (!NewSciHandler)
    499     {
    500         return_ACPI_STATUS (AE_NO_MEMORY);
    501     }
    502 
    503     NewSciHandler->Address = Address;
    504     NewSciHandler->Context = Context;
    505 
    506     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
    507     if (ACPI_FAILURE (Status))
    508     {
    509         goto Exit;
    510     }
    511 
    512     /* Lock list during installation */
    513 
    514     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
    515     SciHandler = AcpiGbl_SciHandlerList;
    516 
    517     /* Ensure handler does not already exist */
    518 
    519     while (SciHandler)
    520     {
    521         if (Address == SciHandler->Address)
    522         {
    523             Status = AE_ALREADY_EXISTS;
    524             goto UnlockAndExit;
    525         }
    526 
    527         SciHandler = SciHandler->Next;
    528     }
    529 
    530     /* Install the new handler into the global list (at head) */
    531 
    532     NewSciHandler->Next = AcpiGbl_SciHandlerList;
    533     AcpiGbl_SciHandlerList = NewSciHandler;
    534 
    535 
    536 UnlockAndExit:
    537 
    538     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
    539     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
    540 
    541 Exit:
    542     if (ACPI_FAILURE (Status))
    543     {
    544         ACPI_FREE (NewSciHandler);
    545     }
    546     return_ACPI_STATUS (Status);
    547 }
    548 
    549 ACPI_EXPORT_SYMBOL (AcpiInstallSciHandler)
    550 
    551 
    552 /*******************************************************************************
    553  *
    554  * FUNCTION:    AcpiRemoveSciHandler
    555  *
    556  * PARAMETERS:  Address             - Address of the handler
    557  *
    558  * RETURN:      Status
    559  *
    560  * DESCRIPTION: Remove a handler for a System Control Interrupt.
    561  *
    562  ******************************************************************************/
    563 
    564 ACPI_STATUS
    565 AcpiRemoveSciHandler (
    566     ACPI_SCI_HANDLER        Address)
    567 {
    568     ACPI_SCI_HANDLER_INFO   *PrevSciHandler;
    569     ACPI_SCI_HANDLER_INFO   *NextSciHandler;
    570     ACPI_CPU_FLAGS          Flags;
    571     ACPI_STATUS             Status;
    572 
    573 
    574     ACPI_FUNCTION_TRACE (AcpiRemoveSciHandler);
    575 
    576 
    577     if (!Address)
    578     {
    579         return_ACPI_STATUS (AE_BAD_PARAMETER);
    580     }
    581 
    582     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
    583     if (ACPI_FAILURE (Status))
    584     {
    585         return_ACPI_STATUS (Status);
    586     }
    587 
    588     /* Remove the SCI handler with lock */
    589 
    590     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
    591 
    592     PrevSciHandler = NULL;
    593     NextSciHandler = AcpiGbl_SciHandlerList;
    594     while (NextSciHandler)
    595     {
    596         if (NextSciHandler->Address == Address)
    597         {
    598             /* Unlink and free the SCI handler info block */
    599 
    600             if (PrevSciHandler)
    601             {
    602                 PrevSciHandler->Next = NextSciHandler->Next;
    603             }
    604             else
    605             {
    606                 AcpiGbl_SciHandlerList = NextSciHandler->Next;
    607             }
    608 
    609             AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
    610             ACPI_FREE (NextSciHandler);
    611             goto UnlockAndExit;
    612         }
    613 
    614         PrevSciHandler = NextSciHandler;
    615         NextSciHandler = NextSciHandler->Next;
    616     }
    617 
    618     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
    619     Status = AE_NOT_EXIST;
    620 
    621 
    622 UnlockAndExit:
    623     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
    624     return_ACPI_STATUS (Status);
    625 }
    626 
    627 ACPI_EXPORT_SYMBOL (AcpiRemoveSciHandler)
    628 
    629 
    630 /*******************************************************************************
    631  *
    632  * FUNCTION:    AcpiInstallGlobalEventHandler
    633  *
    634  * PARAMETERS:  Handler         - Pointer to the global event handler function
    635  *              Context         - Value passed to the handler on each event
    636  *
    637  * RETURN:      Status
    638  *
    639  * DESCRIPTION: Saves the pointer to the handler function. The global handler
    640  *              is invoked upon each incoming GPE and Fixed Event. It is
    641  *              invoked at interrupt level at the time of the event dispatch.
    642  *              Can be used to update event counters, etc.
    643  *
    644  ******************************************************************************/
    645 
    646 ACPI_STATUS
    647 AcpiInstallGlobalEventHandler (
    648     ACPI_GBL_EVENT_HANDLER  Handler,
    649     void                    *Context)
    650 {
    651     ACPI_STATUS             Status;
    652 
    653 
    654     ACPI_FUNCTION_TRACE (AcpiInstallGlobalEventHandler);
    655 
    656 
    657     /* Parameter validation */
    658 
    659     if (!Handler)
    660     {
    661         return_ACPI_STATUS (AE_BAD_PARAMETER);
    662     }
    663 
    664     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
    665     if (ACPI_FAILURE (Status))
    666     {
    667         return_ACPI_STATUS (Status);
    668     }
    669 
    670     /* Don't allow two handlers. */
    671 
    672     if (AcpiGbl_GlobalEventHandler)
    673     {
    674         Status = AE_ALREADY_EXISTS;
    675         goto Cleanup;
    676     }
    677 
    678     AcpiGbl_GlobalEventHandler = Handler;
    679     AcpiGbl_GlobalEventHandlerContext = Context;
    680 
    681 
    682 Cleanup:
    683     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
    684     return_ACPI_STATUS (Status);
    685 }
    686 
    687 ACPI_EXPORT_SYMBOL (AcpiInstallGlobalEventHandler)
    688 
    689 
    690 /*******************************************************************************
    691  *
    692  * FUNCTION:    AcpiInstallFixedEventHandler
    693  *
    694  * PARAMETERS:  Event           - Event type to enable.
    695  *              Handler         - Pointer to the handler function for the
    696  *                                event
    697  *              Context         - Value passed to the handler on each GPE
    698  *
    699  * RETURN:      Status
    700  *
    701  * DESCRIPTION: Saves the pointer to the handler function and then enables the
    702  *              event.
    703  *
    704  ******************************************************************************/
    705 
    706 ACPI_STATUS
    707 AcpiInstallFixedEventHandler (
    708     UINT32                  Event,
    709     ACPI_EVENT_HANDLER      Handler,
    710     void                    *Context)
    711 {
    712     ACPI_STATUS             Status;
    713 
    714 
    715     ACPI_FUNCTION_TRACE (AcpiInstallFixedEventHandler);
    716 
    717 
    718     /* Parameter validation */
    719 
    720     if (Event > ACPI_EVENT_MAX)
    721     {
    722         return_ACPI_STATUS (AE_BAD_PARAMETER);
    723     }
    724 
    725     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
    726     if (ACPI_FAILURE (Status))
    727     {
    728         return_ACPI_STATUS (Status);
    729     }
    730 
    731     /* Do not allow multiple handlers */
    732 
    733     if (AcpiGbl_FixedEventHandlers[Event].Handler)
    734     {
    735         Status = AE_ALREADY_EXISTS;
    736         goto Cleanup;
    737     }
    738 
    739     /* Install the handler before enabling the event */
    740 
    741     AcpiGbl_FixedEventHandlers[Event].Handler = Handler;
    742     AcpiGbl_FixedEventHandlers[Event].Context = Context;
    743 
    744     Status = AcpiEnableEvent (Event, 0);
    745     if (ACPI_FAILURE (Status))
    746     {
    747         ACPI_WARNING ((AE_INFO,
    748             "Could not enable fixed event - %s (%u)",
    749             AcpiUtGetEventName (Event), Event));
    750 
    751         /* Remove the handler */
    752 
    753         AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
    754         AcpiGbl_FixedEventHandlers[Event].Context = NULL;
    755     }
    756     else
    757     {
    758         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
    759             "Enabled fixed event %s (%X), Handler=%p\n",
    760             AcpiUtGetEventName (Event), Event, Handler));
    761     }
    762 
    763 
    764 Cleanup:
    765     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
    766     return_ACPI_STATUS (Status);
    767 }
    768 
    769 ACPI_EXPORT_SYMBOL (AcpiInstallFixedEventHandler)
    770 
    771 
    772 /*******************************************************************************
    773  *
    774  * FUNCTION:    AcpiRemoveFixedEventHandler
    775  *
    776  * PARAMETERS:  Event           - Event type to disable.
    777  *              Handler         - Address of the handler
    778  *
    779  * RETURN:      Status
    780  *
    781  * DESCRIPTION: Disables the event and unregisters the event handler.
    782  *
    783  ******************************************************************************/
    784 
    785 ACPI_STATUS
    786 AcpiRemoveFixedEventHandler (
    787     UINT32                  Event,
    788     ACPI_EVENT_HANDLER      Handler)
    789 {
    790     ACPI_STATUS             Status = AE_OK;
    791 
    792 
    793     ACPI_FUNCTION_TRACE (AcpiRemoveFixedEventHandler);
    794 
    795 
    796     /* Parameter validation */
    797 
    798     if (Event > ACPI_EVENT_MAX)
    799     {
    800         return_ACPI_STATUS (AE_BAD_PARAMETER);
    801     }
    802 
    803     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
    804     if (ACPI_FAILURE (Status))
    805     {
    806         return_ACPI_STATUS (Status);
    807     }
    808 
    809     /* Disable the event before removing the handler */
    810 
    811     Status = AcpiDisableEvent (Event, 0);
    812 
    813     /* Always Remove the handler */
    814 
    815     AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
    816     AcpiGbl_FixedEventHandlers[Event].Context = NULL;
    817 
    818     if (ACPI_FAILURE (Status))
    819     {
    820         ACPI_WARNING ((AE_INFO,
    821             "Could not disable fixed event - %s (%u)",
    822             AcpiUtGetEventName (Event), Event));
    823     }
    824     else
    825     {
    826         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
    827             "Disabled fixed event - %s (%X)\n",
    828             AcpiUtGetEventName (Event), Event));
    829     }
    830 
    831     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
    832     return_ACPI_STATUS (Status);
    833 }
    834 
    835 ACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler)
    836 
    837 
    838 /*******************************************************************************
    839  *
    840  * FUNCTION:    AcpiEvInstallGpeHandler
    841  *
    842  * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
    843  *                                defined GPEs)
    844  *              GpeNumber       - The GPE number within the GPE block
    845  *              Type            - Whether this GPE should be treated as an
    846  *                                edge- or level-triggered interrupt.
    847  *              IsRawHandler    - Whether this GPE should be handled using
    848  *                                the special GPE handler mode.
    849  *              Address         - Address of the handler
    850  *              Context         - Value passed to the handler on each GPE
    851  *
    852  * RETURN:      Status
    853  *
    854  * DESCRIPTION: Internal function to install a handler for a General Purpose
    855  *              Event.
    856  *
    857  ******************************************************************************/
    858 
    859 static ACPI_STATUS
    860 AcpiEvInstallGpeHandler (
    861     ACPI_HANDLE             GpeDevice,
    862     UINT32                  GpeNumber,
    863     UINT32                  Type,
    864     BOOLEAN                 IsRawHandler,
    865     ACPI_GPE_HANDLER        Address,
    866     void                    *Context)
    867 {
    868     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
    869     ACPI_GPE_HANDLER_INFO   *Handler;
    870     ACPI_STATUS             Status;
    871     ACPI_CPU_FLAGS          Flags;
    872 
    873 
    874     ACPI_FUNCTION_TRACE (EvInstallGpeHandler);
    875 
    876 
    877     /* Parameter validation */
    878 
    879     if ((!Address) || (Type & ~ACPI_GPE_XRUPT_TYPE_MASK))
    880     {
    881         return_ACPI_STATUS (AE_BAD_PARAMETER);
    882     }
    883 
    884     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
    885     if (ACPI_FAILURE (Status))
    886     {
    887         return_ACPI_STATUS (Status);
    888     }
    889 
    890     /* Allocate and init handler object (before lock) */
    891 
    892     Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_HANDLER_INFO));
    893     if (!Handler)
    894     {
    895         Status = AE_NO_MEMORY;
    896         goto UnlockAndExit;
    897     }
    898 
    899     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
    900 
    901     /* Ensure that we have a valid GPE number */
    902 
    903     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
    904     if (!GpeEventInfo)
    905     {
    906         Status = AE_BAD_PARAMETER;
    907         goto FreeAndExit;
    908     }
    909 
    910     /* Make sure that there isn't a handler there already */
    911 
    912     if ((ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
    913             ACPI_GPE_DISPATCH_HANDLER) ||
    914         (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
    915             ACPI_GPE_DISPATCH_RAW_HANDLER))
    916     {
    917         Status = AE_ALREADY_EXISTS;
    918         goto FreeAndExit;
    919     }
    920 
    921     Handler->Address = Address;
    922     Handler->Context = Context;
    923     Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode;
    924     Handler->OriginalFlags = (UINT8) (GpeEventInfo->Flags &
    925         (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK));
    926 
    927     /*
    928      * If the GPE is associated with a method, it may have been enabled
    929      * automatically during initialization, in which case it has to be
    930      * disabled now to avoid spurious execution of the handler.
    931      */
    932     if (((ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) ==
    933             ACPI_GPE_DISPATCH_METHOD) ||
    934          (ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) ==
    935             ACPI_GPE_DISPATCH_NOTIFY)) &&
    936         GpeEventInfo->RuntimeCount)
    937     {
    938         Handler->OriginallyEnabled = TRUE;
    939         (void) AcpiEvRemoveGpeReference (GpeEventInfo);
    940 
    941         /* Sanity check of original type against new type */
    942 
    943         if (Type != (UINT32) (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK))
    944         {
    945             ACPI_WARNING ((AE_INFO, "GPE type mismatch (level/edge)"));
    946         }
    947     }
    948 
    949     /* Install the handler */
    950 
    951     GpeEventInfo->Dispatch.Handler = Handler;
    952 
    953     /* Setup up dispatch flags to indicate handler (vs. method/notify) */
    954 
    955     GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
    956     GpeEventInfo->Flags |= (UINT8) (Type | (IsRawHandler ?
    957         ACPI_GPE_DISPATCH_RAW_HANDLER : ACPI_GPE_DISPATCH_HANDLER));
    958 
    959     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
    960 
    961 
    962 UnlockAndExit:
    963     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
    964     return_ACPI_STATUS (Status);
    965 
    966 FreeAndExit:
    967     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
    968     ACPI_FREE (Handler);
    969     goto UnlockAndExit;
    970 }
    971 
    972 
    973 /*******************************************************************************
    974  *
    975  * FUNCTION:    AcpiInstallGpeHandler
    976  *
    977  * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
    978  *                                defined GPEs)
    979  *              GpeNumber       - The GPE number within the GPE block
    980  *              Type            - Whether this GPE should be treated as an
    981  *                                edge- or level-triggered interrupt.
    982  *              Address         - Address of the handler
    983  *              Context         - Value passed to the handler on each GPE
    984  *
    985  * RETURN:      Status
    986  *
    987  * DESCRIPTION: Install a handler for a General Purpose Event.
    988  *
    989  ******************************************************************************/
    990 
    991 ACPI_STATUS
    992 AcpiInstallGpeHandler (
    993     ACPI_HANDLE             GpeDevice,
    994     UINT32                  GpeNumber,
    995     UINT32                  Type,
    996     ACPI_GPE_HANDLER        Address,
    997     void                    *Context)
    998 {
    999     ACPI_STATUS             Status;
   1000 
   1001 
   1002     ACPI_FUNCTION_TRACE (AcpiInstallGpeHandler);
   1003 
   1004 
   1005     Status = AcpiEvInstallGpeHandler (GpeDevice, GpeNumber, Type,
   1006         FALSE, Address, Context);
   1007 
   1008     return_ACPI_STATUS (Status);
   1009 }
   1010 
   1011 ACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler)
   1012 
   1013 
   1014 /*******************************************************************************
   1015  *
   1016  * FUNCTION:    AcpiInstallGpeRawHandler
   1017  *
   1018  * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
   1019  *                                defined GPEs)
   1020  *              GpeNumber       - The GPE number within the GPE block
   1021  *              Type            - Whether this GPE should be treated as an
   1022  *                                edge- or level-triggered interrupt.
   1023  *              Address         - Address of the handler
   1024  *              Context         - Value passed to the handler on each GPE
   1025  *
   1026  * RETURN:      Status
   1027  *
   1028  * DESCRIPTION: Install a handler for a General Purpose Event.
   1029  *
   1030  ******************************************************************************/
   1031 
   1032 ACPI_STATUS
   1033 AcpiInstallGpeRawHandler (
   1034     ACPI_HANDLE             GpeDevice,
   1035     UINT32                  GpeNumber,
   1036     UINT32                  Type,
   1037     ACPI_GPE_HANDLER        Address,
   1038     void                    *Context)
   1039 {
   1040     ACPI_STATUS             Status;
   1041 
   1042 
   1043     ACPI_FUNCTION_TRACE (AcpiInstallGpeRawHandler);
   1044 
   1045 
   1046     Status = AcpiEvInstallGpeHandler (GpeDevice, GpeNumber, Type,
   1047         TRUE, Address, Context);
   1048 
   1049     return_ACPI_STATUS (Status);
   1050 }
   1051 
   1052 ACPI_EXPORT_SYMBOL (AcpiInstallGpeRawHandler)
   1053 
   1054 
   1055 /*******************************************************************************
   1056  *
   1057  * FUNCTION:    AcpiRemoveGpeHandler
   1058  *
   1059  * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
   1060  *                                defined GPEs)
   1061  *              GpeNumber       - The event to remove a handler
   1062  *              Address         - Address of the handler
   1063  *
   1064  * RETURN:      Status
   1065  *
   1066  * DESCRIPTION: Remove a handler for a General Purpose AcpiEvent.
   1067  *
   1068  ******************************************************************************/
   1069 
   1070 ACPI_STATUS
   1071 AcpiRemoveGpeHandler (
   1072     ACPI_HANDLE             GpeDevice,
   1073     UINT32                  GpeNumber,
   1074     ACPI_GPE_HANDLER        Address)
   1075 {
   1076     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
   1077     ACPI_GPE_HANDLER_INFO   *Handler;
   1078     ACPI_STATUS             Status;
   1079     ACPI_CPU_FLAGS          Flags;
   1080 
   1081 
   1082     ACPI_FUNCTION_TRACE (AcpiRemoveGpeHandler);
   1083 
   1084 
   1085     /* Parameter validation */
   1086 
   1087     if (!Address)
   1088     {
   1089         return_ACPI_STATUS (AE_BAD_PARAMETER);
   1090     }
   1091 
   1092     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
   1093     if (ACPI_FAILURE (Status))
   1094     {
   1095         return_ACPI_STATUS (Status);
   1096     }
   1097 
   1098     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
   1099 
   1100     /* Ensure that we have a valid GPE number */
   1101 
   1102     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
   1103     if (!GpeEventInfo)
   1104     {
   1105         Status = AE_BAD_PARAMETER;
   1106         goto UnlockAndExit;
   1107     }
   1108 
   1109     /* Make sure that a handler is indeed installed */
   1110 
   1111     if ((ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) !=
   1112             ACPI_GPE_DISPATCH_HANDLER) &&
   1113         (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) !=
   1114             ACPI_GPE_DISPATCH_RAW_HANDLER))
   1115     {
   1116         Status = AE_NOT_EXIST;
   1117         goto UnlockAndExit;
   1118     }
   1119 
   1120     /* Make sure that the installed handler is the same */
   1121 
   1122     if (GpeEventInfo->Dispatch.Handler->Address != Address)
   1123     {
   1124         Status = AE_BAD_PARAMETER;
   1125         goto UnlockAndExit;
   1126     }
   1127 
   1128     /* Remove the handler */
   1129 
   1130     Handler = GpeEventInfo->Dispatch.Handler;
   1131     GpeEventInfo->Dispatch.Handler = NULL;
   1132 
   1133     /* Restore Method node (if any), set dispatch flags */
   1134 
   1135     GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode;
   1136     GpeEventInfo->Flags &=
   1137         ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
   1138     GpeEventInfo->Flags |= Handler->OriginalFlags;
   1139 
   1140     /*
   1141      * If the GPE was previously associated with a method and it was
   1142      * enabled, it should be enabled at this point to restore the
   1143      * post-initialization configuration.
   1144      */
   1145     if (((ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) ==
   1146             ACPI_GPE_DISPATCH_METHOD) ||
   1147          (ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) ==
   1148             ACPI_GPE_DISPATCH_NOTIFY)) &&
   1149         Handler->OriginallyEnabled)
   1150     {
   1151         (void) AcpiEvAddGpeReference (GpeEventInfo);
   1152     }
   1153 
   1154     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
   1155     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
   1156 
   1157     /* Make sure all deferred GPE tasks are completed */
   1158 
   1159     AcpiOsWaitEventsComplete ();
   1160 
   1161     /* Now we can free the handler object */
   1162 
   1163     ACPI_FREE (Handler);
   1164     return_ACPI_STATUS (Status);
   1165 
   1166 UnlockAndExit:
   1167     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
   1168     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
   1169     return_ACPI_STATUS (Status);
   1170 }
   1171 
   1172 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeHandler)
   1173 
   1174 
   1175 /*******************************************************************************
   1176  *
   1177  * FUNCTION:    AcpiAcquireGlobalLock
   1178  *
   1179  * PARAMETERS:  Timeout         - How long the caller is willing to wait
   1180  *              Handle          - Where the handle to the lock is returned
   1181  *                                (if acquired)
   1182  *
   1183  * RETURN:      Status
   1184  *
   1185  * DESCRIPTION: Acquire the ACPI Global Lock
   1186  *
   1187  * Note: Allows callers with the same thread ID to acquire the global lock
   1188  * multiple times. In other words, externally, the behavior of the global lock
   1189  * is identical to an AML mutex. On the first acquire, a new handle is
   1190  * returned. On any subsequent calls to acquire by the same thread, the same
   1191  * handle is returned.
   1192  *
   1193  ******************************************************************************/
   1194 
   1195 ACPI_STATUS
   1196 AcpiAcquireGlobalLock (
   1197     UINT16                  Timeout,
   1198     UINT32                  *Handle)
   1199 {
   1200     ACPI_STATUS             Status;
   1201 
   1202 
   1203     if (!Handle)
   1204     {
   1205         return (AE_BAD_PARAMETER);
   1206     }
   1207 
   1208     /* Must lock interpreter to prevent race conditions */
   1209 
   1210     AcpiExEnterInterpreter ();
   1211 
   1212     Status = AcpiExAcquireMutexObject (Timeout,
   1213         AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ());
   1214 
   1215     if (ACPI_SUCCESS (Status))
   1216     {
   1217         /* Return the global lock handle (updated in AcpiEvAcquireGlobalLock) */
   1218 
   1219         *Handle = AcpiGbl_GlobalLockHandle;
   1220     }
   1221 
   1222     AcpiExExitInterpreter ();
   1223     return (Status);
   1224 }
   1225 
   1226 ACPI_EXPORT_SYMBOL (AcpiAcquireGlobalLock)
   1227 
   1228 
   1229 /*******************************************************************************
   1230  *
   1231  * FUNCTION:    AcpiReleaseGlobalLock
   1232  *
   1233  * PARAMETERS:  Handle      - Returned from AcpiAcquireGlobalLock
   1234  *
   1235  * RETURN:      Status
   1236  *
   1237  * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
   1238  *
   1239  ******************************************************************************/
   1240 
   1241 ACPI_STATUS
   1242 AcpiReleaseGlobalLock (
   1243     UINT32                  Handle)
   1244 {
   1245     ACPI_STATUS             Status;
   1246 
   1247 
   1248     if (!Handle || (Handle != AcpiGbl_GlobalLockHandle))
   1249     {
   1250         return (AE_NOT_ACQUIRED);
   1251     }
   1252 
   1253     Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex);
   1254     return (Status);
   1255 }
   1256 
   1257 ACPI_EXPORT_SYMBOL (AcpiReleaseGlobalLock)
   1258 
   1259 #endif /* !ACPI_REDUCED_HARDWARE */
   1260