Home | History | Annotate | Line # | Download | only in events
evxface.c revision 1.4
      1 /******************************************************************************
      2  *
      3  * Module Name: evxface - External interfaces for ACPI events
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2011, 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 
     45 #define __EVXFACE_C__
     46 
     47 #include "acpi.h"
     48 #include "accommon.h"
     49 #include "acnamesp.h"
     50 #include "acevents.h"
     51 #include "acinterp.h"
     52 
     53 #define _COMPONENT          ACPI_EVENTS
     54         ACPI_MODULE_NAME    ("evxface")
     55 
     56 
     57 /*******************************************************************************
     58  *
     59  * FUNCTION:    AcpiInstallExceptionHandler
     60  *
     61  * PARAMETERS:  Handler         - Pointer to the handler function for the
     62  *                                event
     63  *
     64  * RETURN:      Status
     65  *
     66  * DESCRIPTION: Saves the pointer to the handler function
     67  *
     68  ******************************************************************************/
     69 
     70 ACPI_STATUS
     71 AcpiInstallExceptionHandler (
     72     ACPI_EXCEPTION_HANDLER  Handler)
     73 {
     74     ACPI_STATUS             Status;
     75 
     76 
     77     ACPI_FUNCTION_TRACE (AcpiInstallExceptionHandler);
     78 
     79 
     80     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
     81     if (ACPI_FAILURE (Status))
     82     {
     83         return_ACPI_STATUS (Status);
     84     }
     85 
     86     /* Don't allow two handlers. */
     87 
     88     if (AcpiGbl_ExceptionHandler)
     89     {
     90         Status = AE_ALREADY_EXISTS;
     91         goto Cleanup;
     92     }
     93 
     94     /* Install the handler */
     95 
     96     AcpiGbl_ExceptionHandler = Handler;
     97 
     98 Cleanup:
     99     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
    100     return_ACPI_STATUS (Status);
    101 }
    102 
    103 ACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler)
    104 
    105 
    106 /*******************************************************************************
    107  *
    108  * FUNCTION:    AcpiInstallGlobalEventHandler
    109  *
    110  * PARAMETERS:  Handler         - Pointer to the global event handler function
    111  *              Context         - Value passed to the handler on each event
    112  *
    113  * RETURN:      Status
    114  *
    115  * DESCRIPTION: Saves the pointer to the handler function. The global handler
    116  *              is invoked upon each incoming GPE and Fixed Event. It is
    117  *              invoked at interrupt level at the time of the event dispatch.
    118  *              Can be used to update event counters, etc.
    119  *
    120  ******************************************************************************/
    121 
    122 ACPI_STATUS
    123 AcpiInstallGlobalEventHandler (
    124     ACPI_GBL_EVENT_HANDLER  Handler,
    125     void                    *Context)
    126 {
    127     ACPI_STATUS             Status;
    128 
    129 
    130     ACPI_FUNCTION_TRACE (AcpiInstallGlobalEventHandler);
    131 
    132 
    133     /* Parameter validation */
    134 
    135     if (!Handler)
    136     {
    137         return_ACPI_STATUS (AE_BAD_PARAMETER);
    138     }
    139 
    140     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
    141     if (ACPI_FAILURE (Status))
    142     {
    143         return_ACPI_STATUS (Status);
    144     }
    145 
    146     /* Don't allow two handlers. */
    147 
    148     if (AcpiGbl_GlobalEventHandler)
    149     {
    150         Status = AE_ALREADY_EXISTS;
    151         goto Cleanup;
    152     }
    153 
    154     AcpiGbl_GlobalEventHandler = Handler;
    155     AcpiGbl_GlobalEventHandlerContext = Context;
    156 
    157 
    158 Cleanup:
    159     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
    160     return_ACPI_STATUS (Status);
    161 }
    162 
    163 ACPI_EXPORT_SYMBOL (AcpiInstallGlobalEventHandler)
    164 
    165 
    166 /*******************************************************************************
    167  *
    168  * FUNCTION:    AcpiInstallFixedEventHandler
    169  *
    170  * PARAMETERS:  Event           - Event type to enable.
    171  *              Handler         - Pointer to the handler function for the
    172  *                                event
    173  *              Context         - Value passed to the handler on each GPE
    174  *
    175  * RETURN:      Status
    176  *
    177  * DESCRIPTION: Saves the pointer to the handler function and then enables the
    178  *              event.
    179  *
    180  ******************************************************************************/
    181 
    182 ACPI_STATUS
    183 AcpiInstallFixedEventHandler (
    184     UINT32                  Event,
    185     ACPI_EVENT_HANDLER      Handler,
    186     void                    *Context)
    187 {
    188     ACPI_STATUS             Status;
    189 
    190 
    191     ACPI_FUNCTION_TRACE (AcpiInstallFixedEventHandler);
    192 
    193 
    194     /* Parameter validation */
    195 
    196     if (Event > ACPI_EVENT_MAX)
    197     {
    198         return_ACPI_STATUS (AE_BAD_PARAMETER);
    199     }
    200 
    201     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
    202     if (ACPI_FAILURE (Status))
    203     {
    204         return_ACPI_STATUS (Status);
    205     }
    206 
    207     /* Don't allow two handlers. */
    208 
    209     if (NULL != AcpiGbl_FixedEventHandlers[Event].Handler)
    210     {
    211         Status = AE_ALREADY_EXISTS;
    212         goto Cleanup;
    213     }
    214 
    215     /* Install the handler before enabling the event */
    216 
    217     AcpiGbl_FixedEventHandlers[Event].Handler = Handler;
    218     AcpiGbl_FixedEventHandlers[Event].Context = Context;
    219 
    220     Status = AcpiEnableEvent (Event, 0);
    221     if (ACPI_FAILURE (Status))
    222     {
    223         ACPI_WARNING ((AE_INFO, "Could not enable fixed event 0x%X", Event));
    224 
    225         /* Remove the handler */
    226 
    227         AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
    228         AcpiGbl_FixedEventHandlers[Event].Context = NULL;
    229     }
    230     else
    231     {
    232         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
    233             "Enabled fixed event %X, Handler=%p\n", Event, Handler));
    234     }
    235 
    236 
    237 Cleanup:
    238     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
    239     return_ACPI_STATUS (Status);
    240 }
    241 
    242 ACPI_EXPORT_SYMBOL (AcpiInstallFixedEventHandler)
    243 
    244 
    245 /*******************************************************************************
    246  *
    247  * FUNCTION:    AcpiRemoveFixedEventHandler
    248  *
    249  * PARAMETERS:  Event           - Event type to disable.
    250  *              Handler         - Address of the handler
    251  *
    252  * RETURN:      Status
    253  *
    254  * DESCRIPTION: Disables the event and unregisters the event handler.
    255  *
    256  ******************************************************************************/
    257 
    258 ACPI_STATUS
    259 AcpiRemoveFixedEventHandler (
    260     UINT32                  Event,
    261     ACPI_EVENT_HANDLER      Handler)
    262 {
    263     ACPI_STATUS             Status = AE_OK;
    264 
    265 
    266     ACPI_FUNCTION_TRACE (AcpiRemoveFixedEventHandler);
    267 
    268 
    269     /* Parameter validation */
    270 
    271     if (Event > ACPI_EVENT_MAX)
    272     {
    273         return_ACPI_STATUS (AE_BAD_PARAMETER);
    274     }
    275 
    276     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
    277     if (ACPI_FAILURE (Status))
    278     {
    279         return_ACPI_STATUS (Status);
    280     }
    281 
    282     /* Disable the event before removing the handler */
    283 
    284     Status = AcpiDisableEvent (Event, 0);
    285 
    286     /* Always Remove the handler */
    287 
    288     AcpiGbl_FixedEventHandlers[Event].Handler = NULL;
    289     AcpiGbl_FixedEventHandlers[Event].Context = NULL;
    290 
    291     if (ACPI_FAILURE (Status))
    292     {
    293         ACPI_WARNING ((AE_INFO,
    294             "Could not write to fixed event enable register 0x%X", Event));
    295     }
    296     else
    297     {
    298         ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Disabled fixed event %X\n", Event));
    299     }
    300 
    301     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
    302     return_ACPI_STATUS (Status);
    303 }
    304 
    305 ACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler)
    306 
    307 
    308 /*******************************************************************************
    309  *
    310  * FUNCTION:    AcpiInstallNotifyHandler
    311  *
    312  * PARAMETERS:  Device          - The device for which notifies will be handled
    313  *              HandlerType     - The type of handler:
    314  *                                  ACPI_SYSTEM_NOTIFY: SystemHandler (00-7f)
    315  *                                  ACPI_DEVICE_NOTIFY: DriverHandler (80-ff)
    316  *                                  ACPI_ALL_NOTIFY:  both system and device
    317  *              Handler         - Address of the handler
    318  *              Context         - Value passed to the handler on each GPE
    319  *
    320  * RETURN:      Status
    321  *
    322  * DESCRIPTION: Install a handler for notifies on an ACPI device
    323  *
    324  ******************************************************************************/
    325 
    326 ACPI_STATUS
    327 AcpiInstallNotifyHandler (
    328     ACPI_HANDLE             Device,
    329     UINT32                  HandlerType,
    330     ACPI_NOTIFY_HANDLER     Handler,
    331     void                    *Context)
    332 {
    333     ACPI_OPERAND_OBJECT     *ObjDesc;
    334     ACPI_OPERAND_OBJECT     *NotifyObj;
    335     ACPI_NAMESPACE_NODE     *Node;
    336     ACPI_STATUS             Status;
    337 
    338 
    339     ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler);
    340 
    341 
    342     /* Parameter validation */
    343 
    344     if ((!Device)  ||
    345         (!Handler) ||
    346         (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
    347     {
    348         return_ACPI_STATUS (AE_BAD_PARAMETER);
    349     }
    350 
    351     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    352     if (ACPI_FAILURE (Status))
    353     {
    354         return_ACPI_STATUS (Status);
    355     }
    356 
    357     /* Convert and validate the device handle */
    358 
    359     Node = AcpiNsValidateHandle (Device);
    360     if (!Node)
    361     {
    362         Status = AE_BAD_PARAMETER;
    363         goto UnlockAndExit;
    364     }
    365 
    366     /*
    367      * Root Object:
    368      * Registering a notify handler on the root object indicates that the
    369      * caller wishes to receive notifications for all objects. Note that
    370      * only one <external> global handler can be regsitered (per notify type).
    371      */
    372     if (Device == ACPI_ROOT_OBJECT)
    373     {
    374         /* Make sure the handler is not already installed */
    375 
    376         if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
    377                 AcpiGbl_SystemNotify.Handler)       ||
    378             ((HandlerType & ACPI_DEVICE_NOTIFY) &&
    379                 AcpiGbl_DeviceNotify.Handler))
    380         {
    381             Status = AE_ALREADY_EXISTS;
    382             goto UnlockAndExit;
    383         }
    384 
    385         if (HandlerType & ACPI_SYSTEM_NOTIFY)
    386         {
    387             AcpiGbl_SystemNotify.Node    = Node;
    388             AcpiGbl_SystemNotify.Handler = Handler;
    389             AcpiGbl_SystemNotify.Context = Context;
    390         }
    391 
    392         if (HandlerType & ACPI_DEVICE_NOTIFY)
    393         {
    394             AcpiGbl_DeviceNotify.Node    = Node;
    395             AcpiGbl_DeviceNotify.Handler = Handler;
    396             AcpiGbl_DeviceNotify.Context = Context;
    397         }
    398 
    399         /* Global notify handler installed */
    400     }
    401 
    402     /*
    403      * All Other Objects:
    404      * Caller will only receive notifications specific to the target object.
    405      * Note that only certain object types can receive notifications.
    406      */
    407     else
    408     {
    409         /* Notifies allowed on this object? */
    410 
    411         if (!AcpiEvIsNotifyObject (Node))
    412         {
    413             Status = AE_TYPE;
    414             goto UnlockAndExit;
    415         }
    416 
    417         /* Check for an existing internal object */
    418 
    419         ObjDesc = AcpiNsGetAttachedObject (Node);
    420         if (ObjDesc)
    421         {
    422             /* Object exists - make sure there's no handler */
    423 
    424             if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
    425                     ObjDesc->CommonNotify.SystemNotify)   ||
    426                 ((HandlerType & ACPI_DEVICE_NOTIFY) &&
    427                     ObjDesc->CommonNotify.DeviceNotify))
    428             {
    429                 Status = AE_ALREADY_EXISTS;
    430                 goto UnlockAndExit;
    431             }
    432         }
    433         else
    434         {
    435             /* Create a new object */
    436 
    437             ObjDesc = AcpiUtCreateInternalObject (Node->Type);
    438             if (!ObjDesc)
    439             {
    440                 Status = AE_NO_MEMORY;
    441                 goto UnlockAndExit;
    442             }
    443 
    444             /* Attach new object to the Node */
    445 
    446             Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type);
    447 
    448             /* Remove local reference to the object */
    449 
    450             AcpiUtRemoveReference (ObjDesc);
    451             if (ACPI_FAILURE (Status))
    452             {
    453                 goto UnlockAndExit;
    454             }
    455         }
    456 
    457         /* Install the handler */
    458 
    459         NotifyObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY);
    460         if (!NotifyObj)
    461         {
    462             Status = AE_NO_MEMORY;
    463             goto UnlockAndExit;
    464         }
    465 
    466         NotifyObj->Notify.Node    = Node;
    467         NotifyObj->Notify.Handler = Handler;
    468         NotifyObj->Notify.Context = Context;
    469 
    470         if (HandlerType & ACPI_SYSTEM_NOTIFY)
    471         {
    472             ObjDesc->CommonNotify.SystemNotify = NotifyObj;
    473         }
    474 
    475         if (HandlerType & ACPI_DEVICE_NOTIFY)
    476         {
    477             ObjDesc->CommonNotify.DeviceNotify = NotifyObj;
    478         }
    479 
    480         if (HandlerType == ACPI_ALL_NOTIFY)
    481         {
    482             /* Extra ref if installed in both */
    483 
    484             AcpiUtAddReference (NotifyObj);
    485         }
    486     }
    487 
    488 
    489 UnlockAndExit:
    490     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    491     return_ACPI_STATUS (Status);
    492 }
    493 
    494 ACPI_EXPORT_SYMBOL (AcpiInstallNotifyHandler)
    495 
    496 
    497 /*******************************************************************************
    498  *
    499  * FUNCTION:    AcpiRemoveNotifyHandler
    500  *
    501  * PARAMETERS:  Device          - The device for which notifies will be handled
    502  *              HandlerType     - The type of handler:
    503  *                                  ACPI_SYSTEM_NOTIFY: SystemHandler (00-7f)
    504  *                                  ACPI_DEVICE_NOTIFY: DriverHandler (80-ff)
    505  *                                  ACPI_ALL_NOTIFY:  both system and device
    506  *              Handler         - Address of the handler
    507  *
    508  * RETURN:      Status
    509  *
    510  * DESCRIPTION: Remove a handler for notifies on an ACPI device
    511  *
    512  ******************************************************************************/
    513 
    514 ACPI_STATUS
    515 AcpiRemoveNotifyHandler (
    516     ACPI_HANDLE             Device,
    517     UINT32                  HandlerType,
    518     ACPI_NOTIFY_HANDLER     Handler)
    519 {
    520     ACPI_OPERAND_OBJECT     *NotifyObj;
    521     ACPI_OPERAND_OBJECT     *ObjDesc;
    522     ACPI_NAMESPACE_NODE     *Node;
    523     ACPI_STATUS             Status;
    524 
    525 
    526     ACPI_FUNCTION_TRACE (AcpiRemoveNotifyHandler);
    527 
    528 
    529     /* Parameter validation */
    530 
    531     if ((!Device)  ||
    532         (!Handler) ||
    533         (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE))
    534     {
    535         return_ACPI_STATUS (AE_BAD_PARAMETER);
    536     }
    537 
    538     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    539     if (ACPI_FAILURE (Status))
    540     {
    541         return_ACPI_STATUS (Status);
    542     }
    543 
    544     /* Convert and validate the device handle */
    545 
    546     Node = AcpiNsValidateHandle (Device);
    547     if (!Node)
    548     {
    549         Status = AE_BAD_PARAMETER;
    550         goto UnlockAndExit;
    551     }
    552 
    553     /* Root Object */
    554 
    555     if (Device == ACPI_ROOT_OBJECT)
    556     {
    557         ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
    558             "Removing notify handler for namespace root object\n"));
    559 
    560         if (((HandlerType & ACPI_SYSTEM_NOTIFY) &&
    561               !AcpiGbl_SystemNotify.Handler)        ||
    562             ((HandlerType & ACPI_DEVICE_NOTIFY) &&
    563               !AcpiGbl_DeviceNotify.Handler))
    564         {
    565             Status = AE_NOT_EXIST;
    566             goto UnlockAndExit;
    567         }
    568 
    569         if (HandlerType & ACPI_SYSTEM_NOTIFY)
    570         {
    571             AcpiGbl_SystemNotify.Node    = NULL;
    572             AcpiGbl_SystemNotify.Handler = NULL;
    573             AcpiGbl_SystemNotify.Context = NULL;
    574         }
    575 
    576         if (HandlerType & ACPI_DEVICE_NOTIFY)
    577         {
    578             AcpiGbl_DeviceNotify.Node    = NULL;
    579             AcpiGbl_DeviceNotify.Handler = NULL;
    580             AcpiGbl_DeviceNotify.Context = NULL;
    581         }
    582     }
    583 
    584     /* All Other Objects */
    585 
    586     else
    587     {
    588         /* Notifies allowed on this object? */
    589 
    590         if (!AcpiEvIsNotifyObject (Node))
    591         {
    592             Status = AE_TYPE;
    593             goto UnlockAndExit;
    594         }
    595 
    596         /* Check for an existing internal object */
    597 
    598         ObjDesc = AcpiNsGetAttachedObject (Node);
    599         if (!ObjDesc)
    600         {
    601             Status = AE_NOT_EXIST;
    602             goto UnlockAndExit;
    603         }
    604 
    605         /* Object exists - make sure there's an existing handler */
    606 
    607         if (HandlerType & ACPI_SYSTEM_NOTIFY)
    608         {
    609             NotifyObj = ObjDesc->CommonNotify.SystemNotify;
    610             if (!NotifyObj)
    611             {
    612                 Status = AE_NOT_EXIST;
    613                 goto UnlockAndExit;
    614             }
    615 
    616             if (NotifyObj->Notify.Handler != Handler)
    617             {
    618                 Status = AE_BAD_PARAMETER;
    619                 goto UnlockAndExit;
    620             }
    621 
    622             /* Remove the handler */
    623 
    624             ObjDesc->CommonNotify.SystemNotify = NULL;
    625             AcpiUtRemoveReference (NotifyObj);
    626         }
    627 
    628         if (HandlerType & ACPI_DEVICE_NOTIFY)
    629         {
    630             NotifyObj = ObjDesc->CommonNotify.DeviceNotify;
    631             if (!NotifyObj)
    632             {
    633                 Status = AE_NOT_EXIST;
    634                 goto UnlockAndExit;
    635             }
    636 
    637             if (NotifyObj->Notify.Handler != Handler)
    638             {
    639                 Status = AE_BAD_PARAMETER;
    640                 goto UnlockAndExit;
    641             }
    642 
    643             /* Remove the handler */
    644 
    645             ObjDesc->CommonNotify.DeviceNotify = NULL;
    646             AcpiUtRemoveReference (NotifyObj);
    647         }
    648     }
    649 
    650 
    651 UnlockAndExit:
    652     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    653     return_ACPI_STATUS (Status);
    654 }
    655 
    656 ACPI_EXPORT_SYMBOL (AcpiRemoveNotifyHandler)
    657 
    658 
    659 /*******************************************************************************
    660  *
    661  * FUNCTION:    AcpiInstallGpeHandler
    662  *
    663  * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
    664  *                                defined GPEs)
    665  *              GpeNumber       - The GPE number within the GPE block
    666  *              Type            - Whether this GPE should be treated as an
    667  *                                edge- or level-triggered interrupt.
    668  *              Address         - Address of the handler
    669  *              Context         - Value passed to the handler on each GPE
    670  *
    671  * RETURN:      Status
    672  *
    673  * DESCRIPTION: Install a handler for a General Purpose Event.
    674  *
    675  ******************************************************************************/
    676 
    677 ACPI_STATUS
    678 AcpiInstallGpeHandler (
    679     ACPI_HANDLE             GpeDevice,
    680     UINT32                  GpeNumber,
    681     UINT32                  Type,
    682     ACPI_GPE_HANDLER        Address,
    683     void                    *Context)
    684 {
    685     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
    686     ACPI_GPE_HANDLER_INFO   *Handler;
    687     ACPI_STATUS             Status;
    688     ACPI_CPU_FLAGS          Flags;
    689 
    690 
    691     ACPI_FUNCTION_TRACE (AcpiInstallGpeHandler);
    692 
    693 
    694     /* Parameter validation */
    695 
    696     if ((!Address) || (Type & ~ACPI_GPE_XRUPT_TYPE_MASK))
    697     {
    698         return_ACPI_STATUS (AE_BAD_PARAMETER);
    699     }
    700 
    701     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
    702     if (ACPI_FAILURE (Status))
    703     {
    704         return_ACPI_STATUS (Status);
    705     }
    706 
    707     /* Allocate and init handler object (before lock) */
    708 
    709     Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_HANDLER_INFO));
    710     if (!Handler)
    711     {
    712         Status = AE_NO_MEMORY;
    713         goto UnlockAndExit;
    714     }
    715 
    716     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
    717 
    718     /* Ensure that we have a valid GPE number */
    719 
    720     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
    721     if (!GpeEventInfo)
    722     {
    723         Status = AE_BAD_PARAMETER;
    724         goto FreeAndExit;
    725     }
    726 
    727     /* Make sure that there isn't a handler there already */
    728 
    729     if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
    730             ACPI_GPE_DISPATCH_HANDLER)
    731     {
    732         Status = AE_ALREADY_EXISTS;
    733         goto FreeAndExit;
    734     }
    735 
    736     Handler->Address = Address;
    737     Handler->Context = Context;
    738     Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode;
    739     Handler->OriginalFlags = (UINT8) (GpeEventInfo->Flags &
    740         (ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK));
    741 
    742     /*
    743      * If the GPE is associated with a method, it may have been enabled
    744      * automatically during initialization, in which case it has to be
    745      * disabled now to avoid spurious execution of the handler.
    746      */
    747     if (((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) ||
    748          (Handler->OriginalFlags & ACPI_GPE_DISPATCH_NOTIFY)) &&
    749         GpeEventInfo->RuntimeCount)
    750     {
    751         Handler->OriginallyEnabled = TRUE;
    752         (void) AcpiEvRemoveGpeReference (GpeEventInfo);
    753 
    754         /* Sanity check of original type against new type */
    755 
    756         if (Type != (UINT32) (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK))
    757         {
    758             ACPI_WARNING ((AE_INFO, "GPE type mismatch (level/edge)"));
    759         }
    760     }
    761 
    762     /* Install the handler */
    763 
    764     GpeEventInfo->Dispatch.Handler = Handler;
    765 
    766     /* Setup up dispatch flags to indicate handler (vs. method/notify) */
    767 
    768     GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
    769     GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_HANDLER);
    770 
    771     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
    772 
    773 
    774 UnlockAndExit:
    775     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
    776     return_ACPI_STATUS (Status);
    777 
    778 FreeAndExit:
    779     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
    780     ACPI_FREE (Handler);
    781     goto UnlockAndExit;
    782 }
    783 
    784 ACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler)
    785 
    786 
    787 /*******************************************************************************
    788  *
    789  * FUNCTION:    AcpiRemoveGpeHandler
    790  *
    791  * PARAMETERS:  GpeDevice       - Namespace node for the GPE (NULL for FADT
    792  *                                defined GPEs)
    793  *              GpeNumber       - The event to remove a handler
    794  *              Address         - Address of the handler
    795  *
    796  * RETURN:      Status
    797  *
    798  * DESCRIPTION: Remove a handler for a General Purpose AcpiEvent.
    799  *
    800  ******************************************************************************/
    801 
    802 ACPI_STATUS
    803 AcpiRemoveGpeHandler (
    804     ACPI_HANDLE             GpeDevice,
    805     UINT32                  GpeNumber,
    806     ACPI_GPE_HANDLER        Address)
    807 {
    808     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
    809     ACPI_GPE_HANDLER_INFO   *Handler;
    810     ACPI_STATUS             Status;
    811     ACPI_CPU_FLAGS          Flags;
    812 
    813 
    814     ACPI_FUNCTION_TRACE (AcpiRemoveGpeHandler);
    815 
    816 
    817     /* Parameter validation */
    818 
    819     if (!Address)
    820     {
    821         return_ACPI_STATUS (AE_BAD_PARAMETER);
    822     }
    823 
    824     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
    825     if (ACPI_FAILURE (Status))
    826     {
    827         return_ACPI_STATUS (Status);
    828     }
    829 
    830     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
    831 
    832     /* Ensure that we have a valid GPE number */
    833 
    834     GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
    835     if (!GpeEventInfo)
    836     {
    837         Status = AE_BAD_PARAMETER;
    838         goto UnlockAndExit;
    839     }
    840 
    841     /* Make sure that a handler is indeed installed */
    842 
    843     if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) !=
    844             ACPI_GPE_DISPATCH_HANDLER)
    845     {
    846         Status = AE_NOT_EXIST;
    847         goto UnlockAndExit;
    848     }
    849 
    850     /* Make sure that the installed handler is the same */
    851 
    852     if (GpeEventInfo->Dispatch.Handler->Address != Address)
    853     {
    854         Status = AE_BAD_PARAMETER;
    855         goto UnlockAndExit;
    856     }
    857 
    858     /* Remove the handler */
    859 
    860     Handler = GpeEventInfo->Dispatch.Handler;
    861 
    862     /* Restore Method node (if any), set dispatch flags */
    863 
    864     GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode;
    865     GpeEventInfo->Flags &=
    866         ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
    867     GpeEventInfo->Flags |= Handler->OriginalFlags;
    868 
    869     /*
    870      * If the GPE was previously associated with a method and it was
    871      * enabled, it should be enabled at this point to restore the
    872      * post-initialization configuration.
    873      */
    874     if ((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) &&
    875         Handler->OriginallyEnabled)
    876     {
    877         (void) AcpiEvAddGpeReference (GpeEventInfo);
    878     }
    879 
    880     /* Now we can free the handler object */
    881 
    882     ACPI_FREE (Handler);
    883 
    884 
    885 UnlockAndExit:
    886     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
    887     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
    888     return_ACPI_STATUS (Status);
    889 }
    890 
    891 ACPI_EXPORT_SYMBOL (AcpiRemoveGpeHandler)
    892 
    893 
    894 /*******************************************************************************
    895  *
    896  * FUNCTION:    AcpiAcquireGlobalLock
    897  *
    898  * PARAMETERS:  Timeout         - How long the caller is willing to wait
    899  *              Handle          - Where the handle to the lock is returned
    900  *                                (if acquired)
    901  *
    902  * RETURN:      Status
    903  *
    904  * DESCRIPTION: Acquire the ACPI Global Lock
    905  *
    906  * Note: Allows callers with the same thread ID to acquire the global lock
    907  * multiple times. In other words, externally, the behavior of the global lock
    908  * is identical to an AML mutex. On the first acquire, a new handle is
    909  * returned. On any subsequent calls to acquire by the same thread, the same
    910  * handle is returned.
    911  *
    912  ******************************************************************************/
    913 
    914 ACPI_STATUS
    915 AcpiAcquireGlobalLock (
    916     UINT16                  Timeout,
    917     UINT32                  *Handle)
    918 {
    919     ACPI_STATUS             Status;
    920 
    921 
    922     if (!Handle)
    923     {
    924         return (AE_BAD_PARAMETER);
    925     }
    926 
    927     /* Must lock interpreter to prevent race conditions */
    928 
    929     AcpiExEnterInterpreter ();
    930 
    931     Status = AcpiExAcquireMutexObject (Timeout,
    932                 AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ());
    933 
    934     if (ACPI_SUCCESS (Status))
    935     {
    936         /* Return the global lock handle (updated in AcpiEvAcquireGlobalLock) */
    937 
    938         *Handle = AcpiGbl_GlobalLockHandle;
    939     }
    940 
    941     AcpiExExitInterpreter ();
    942     return (Status);
    943 }
    944 
    945 ACPI_EXPORT_SYMBOL (AcpiAcquireGlobalLock)
    946 
    947 
    948 /*******************************************************************************
    949  *
    950  * FUNCTION:    AcpiReleaseGlobalLock
    951  *
    952  * PARAMETERS:  Handle      - Returned from AcpiAcquireGlobalLock
    953  *
    954  * RETURN:      Status
    955  *
    956  * DESCRIPTION: Release the ACPI Global Lock. The handle must be valid.
    957  *
    958  ******************************************************************************/
    959 
    960 ACPI_STATUS
    961 AcpiReleaseGlobalLock (
    962     UINT32                  Handle)
    963 {
    964     ACPI_STATUS             Status;
    965 
    966 
    967     if (!Handle || (Handle != AcpiGbl_GlobalLockHandle))
    968     {
    969         return (AE_NOT_ACQUIRED);
    970     }
    971 
    972     Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex);
    973     return (Status);
    974 }
    975 
    976 ACPI_EXPORT_SYMBOL (AcpiReleaseGlobalLock)
    977 
    978