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