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