Home | History | Annotate | Line # | Download | only in events
      1       1.1    jruoho /******************************************************************************
      2       1.1    jruoho  *
      3       1.1    jruoho  * Module Name: evgpe - General Purpose Event handling and dispatch
      4       1.1    jruoho  *
      5       1.1    jruoho  *****************************************************************************/
      6       1.1    jruoho 
      7  1.1.1.18  christos /******************************************************************************
      8  1.1.1.18  christos  *
      9  1.1.1.18  christos  * 1. Copyright Notice
     10  1.1.1.18  christos  *
     11  1.1.1.19  christos  * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
     12       1.1    jruoho  * All rights reserved.
     13       1.1    jruoho  *
     14  1.1.1.18  christos  * 2. License
     15  1.1.1.18  christos  *
     16  1.1.1.18  christos  * 2.1. This is your license from Intel Corp. under its intellectual property
     17  1.1.1.18  christos  * rights. You may have additional license terms from the party that provided
     18  1.1.1.18  christos  * you this software, covering your right to use that party's intellectual
     19  1.1.1.18  christos  * property rights.
     20  1.1.1.18  christos  *
     21  1.1.1.18  christos  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
     22  1.1.1.18  christos  * copy of the source code appearing in this file ("Covered Code") an
     23  1.1.1.18  christos  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
     24  1.1.1.18  christos  * base code distributed originally by Intel ("Original Intel Code") to copy,
     25  1.1.1.18  christos  * make derivatives, distribute, use and display any portion of the Covered
     26  1.1.1.18  christos  * Code in any form, with the right to sublicense such rights; and
     27  1.1.1.18  christos  *
     28  1.1.1.18  christos  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
     29  1.1.1.18  christos  * license (with the right to sublicense), under only those claims of Intel
     30  1.1.1.18  christos  * patents that are infringed by the Original Intel Code, to make, use, sell,
     31  1.1.1.18  christos  * offer to sell, and import the Covered Code and derivative works thereof
     32  1.1.1.18  christos  * solely to the minimum extent necessary to exercise the above copyright
     33  1.1.1.18  christos  * license, and in no event shall the patent license extend to any additions
     34  1.1.1.18  christos  * to or modifications of the Original Intel Code. No other license or right
     35  1.1.1.18  christos  * is granted directly or by implication, estoppel or otherwise;
     36  1.1.1.18  christos  *
     37  1.1.1.18  christos  * The above copyright and patent license is granted only if the following
     38  1.1.1.18  christos  * conditions are met:
     39  1.1.1.18  christos  *
     40  1.1.1.18  christos  * 3. Conditions
     41  1.1.1.18  christos  *
     42  1.1.1.18  christos  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
     43  1.1.1.18  christos  * Redistribution of source code of any substantial portion of the Covered
     44  1.1.1.18  christos  * Code or modification with rights to further distribute source must include
     45  1.1.1.18  christos  * the above Copyright Notice, the above License, this list of Conditions,
     46  1.1.1.18  christos  * and the following Disclaimer and Export Compliance provision. In addition,
     47  1.1.1.18  christos  * Licensee must cause all Covered Code to which Licensee contributes to
     48  1.1.1.18  christos  * contain a file documenting the changes Licensee made to create that Covered
     49  1.1.1.18  christos  * Code and the date of any change. Licensee must include in that file the
     50  1.1.1.18  christos  * documentation of any changes made by any predecessor Licensee. Licensee
     51  1.1.1.18  christos  * must include a prominent statement that the modification is derived,
     52  1.1.1.18  christos  * directly or indirectly, from Original Intel Code.
     53  1.1.1.18  christos  *
     54  1.1.1.18  christos  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
     55  1.1.1.18  christos  * Redistribution of source code of any substantial portion of the Covered
     56  1.1.1.18  christos  * Code or modification without rights to further distribute source must
     57  1.1.1.18  christos  * include the following Disclaimer and Export Compliance provision in the
     58  1.1.1.18  christos  * documentation and/or other materials provided with distribution. In
     59  1.1.1.18  christos  * addition, Licensee may not authorize further sublicense of source of any
     60  1.1.1.18  christos  * portion of the Covered Code, and must include terms to the effect that the
     61  1.1.1.18  christos  * license from Licensee to its licensee is limited to the intellectual
     62  1.1.1.18  christos  * property embodied in the software Licensee provides to its licensee, and
     63  1.1.1.18  christos  * not to intellectual property embodied in modifications its licensee may
     64  1.1.1.18  christos  * make.
     65  1.1.1.18  christos  *
     66  1.1.1.18  christos  * 3.3. Redistribution of Executable. Redistribution in executable form of any
     67  1.1.1.18  christos  * substantial portion of the Covered Code or modification must reproduce the
     68  1.1.1.18  christos  * above Copyright Notice, and the following Disclaimer and Export Compliance
     69  1.1.1.18  christos  * provision in the documentation and/or other materials provided with the
     70  1.1.1.18  christos  * distribution.
     71  1.1.1.18  christos  *
     72  1.1.1.18  christos  * 3.4. Intel retains all right, title, and interest in and to the Original
     73  1.1.1.18  christos  * Intel Code.
     74  1.1.1.18  christos  *
     75  1.1.1.18  christos  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
     76  1.1.1.18  christos  * Intel shall be used in advertising or otherwise to promote the sale, use or
     77  1.1.1.18  christos  * other dealings in products derived from or relating to the Covered Code
     78  1.1.1.18  christos  * without prior written authorization from Intel.
     79  1.1.1.18  christos  *
     80  1.1.1.18  christos  * 4. Disclaimer and Export Compliance
     81  1.1.1.18  christos  *
     82  1.1.1.18  christos  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
     83  1.1.1.18  christos  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
     84  1.1.1.18  christos  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
     85  1.1.1.18  christos  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
     86  1.1.1.18  christos  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
     87  1.1.1.18  christos  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
     88  1.1.1.18  christos  * PARTICULAR PURPOSE.
     89  1.1.1.18  christos  *
     90  1.1.1.18  christos  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
     91  1.1.1.18  christos  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
     92  1.1.1.18  christos  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
     93  1.1.1.18  christos  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
     94  1.1.1.18  christos  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
     95  1.1.1.18  christos  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
     96  1.1.1.18  christos  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
     97  1.1.1.18  christos  * LIMITED REMEDY.
     98  1.1.1.18  christos  *
     99  1.1.1.18  christos  * 4.3. Licensee shall not export, either directly or indirectly, any of this
    100  1.1.1.18  christos  * software or system incorporating such software without first obtaining any
    101  1.1.1.18  christos  * required license or other approval from the U. S. Department of Commerce or
    102  1.1.1.18  christos  * any other agency or department of the United States Government. In the
    103  1.1.1.18  christos  * event Licensee exports any such software from the United States or
    104  1.1.1.18  christos  * re-exports any such software from a foreign destination, Licensee shall
    105  1.1.1.18  christos  * ensure that the distribution and export/re-export of the software is in
    106  1.1.1.18  christos  * compliance with all laws, regulations, orders, or other restrictions of the
    107  1.1.1.18  christos  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
    108  1.1.1.18  christos  * any of its subsidiaries will export/re-export any technical data, process,
    109  1.1.1.18  christos  * software, or service, directly or indirectly, to any country for which the
    110  1.1.1.18  christos  * United States government or any agency thereof requires an export license,
    111  1.1.1.18  christos  * other governmental approval, or letter of assurance, without first obtaining
    112  1.1.1.18  christos  * such license, approval or letter.
    113  1.1.1.18  christos  *
    114  1.1.1.18  christos  *****************************************************************************
    115  1.1.1.18  christos  *
    116  1.1.1.18  christos  * Alternatively, you may choose to be licensed under the terms of the
    117  1.1.1.18  christos  * following license:
    118  1.1.1.18  christos  *
    119   1.1.1.2    jruoho  * Redistribution and use in source and binary forms, with or without
    120   1.1.1.2    jruoho  * modification, are permitted provided that the following conditions
    121   1.1.1.2    jruoho  * are met:
    122   1.1.1.2    jruoho  * 1. Redistributions of source code must retain the above copyright
    123   1.1.1.2    jruoho  *    notice, this list of conditions, and the following disclaimer,
    124   1.1.1.2    jruoho  *    without modification.
    125   1.1.1.2    jruoho  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
    126   1.1.1.2    jruoho  *    substantially similar to the "NO WARRANTY" disclaimer below
    127   1.1.1.2    jruoho  *    ("Disclaimer") and any redistribution must be conditioned upon
    128   1.1.1.2    jruoho  *    including a substantially similar Disclaimer requirement for further
    129   1.1.1.2    jruoho  *    binary redistribution.
    130   1.1.1.2    jruoho  * 3. Neither the names of the above-listed copyright holders nor the names
    131   1.1.1.2    jruoho  *    of any contributors may be used to endorse or promote products derived
    132   1.1.1.2    jruoho  *    from this software without specific prior written permission.
    133   1.1.1.2    jruoho  *
    134   1.1.1.2    jruoho  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    135   1.1.1.2    jruoho  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    136  1.1.1.15  christos  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    137   1.1.1.2    jruoho  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    138  1.1.1.18  christos  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    139  1.1.1.18  christos  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    140  1.1.1.18  christos  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    141  1.1.1.18  christos  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    142  1.1.1.18  christos  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    143  1.1.1.18  christos  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    144  1.1.1.18  christos  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    145  1.1.1.18  christos  *
    146  1.1.1.18  christos  * Alternatively, you may choose to be licensed under the terms of the
    147  1.1.1.18  christos  * GNU General Public License ("GPL") version 2 as published by the Free
    148  1.1.1.18  christos  * Software Foundation.
    149  1.1.1.18  christos  *
    150  1.1.1.18  christos  *****************************************************************************/
    151       1.1    jruoho 
    152       1.1    jruoho #include "acpi.h"
    153       1.1    jruoho #include "accommon.h"
    154       1.1    jruoho #include "acevents.h"
    155       1.1    jruoho #include "acnamesp.h"
    156       1.1    jruoho 
    157       1.1    jruoho #define _COMPONENT          ACPI_EVENTS
    158       1.1    jruoho         ACPI_MODULE_NAME    ("evgpe")
    159       1.1    jruoho 
    160   1.1.1.3  christos #if (!ACPI_REDUCED_HARDWARE) /* Entire module */
    161   1.1.1.3  christos 
    162       1.1    jruoho /* Local prototypes */
    163       1.1    jruoho 
    164       1.1    jruoho static void ACPI_SYSTEM_XFACE
    165       1.1    jruoho AcpiEvAsynchExecuteGpeMethod (
    166       1.1    jruoho     void                    *Context);
    167       1.1    jruoho 
    168       1.1    jruoho static void ACPI_SYSTEM_XFACE
    169       1.1    jruoho AcpiEvAsynchEnableGpe (
    170       1.1    jruoho     void                    *Context);
    171       1.1    jruoho 
    172       1.1    jruoho 
    173       1.1    jruoho /*******************************************************************************
    174       1.1    jruoho  *
    175   1.1.1.2    jruoho  * FUNCTION:    AcpiEvUpdateGpeEnableMask
    176       1.1    jruoho  *
    177       1.1    jruoho  * PARAMETERS:  GpeEventInfo            - GPE to update
    178       1.1    jruoho  *
    179       1.1    jruoho  * RETURN:      Status
    180       1.1    jruoho  *
    181   1.1.1.2    jruoho  * DESCRIPTION: Updates GPE register enable mask based upon whether there are
    182   1.1.1.2    jruoho  *              runtime references to this GPE
    183       1.1    jruoho  *
    184       1.1    jruoho  ******************************************************************************/
    185       1.1    jruoho 
    186       1.1    jruoho ACPI_STATUS
    187   1.1.1.2    jruoho AcpiEvUpdateGpeEnableMask (
    188       1.1    jruoho     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
    189       1.1    jruoho {
    190       1.1    jruoho     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
    191   1.1.1.2    jruoho     UINT32                  RegisterBit;
    192       1.1    jruoho 
    193       1.1    jruoho 
    194   1.1.1.2    jruoho     ACPI_FUNCTION_TRACE (EvUpdateGpeEnableMask);
    195       1.1    jruoho 
    196       1.1    jruoho 
    197       1.1    jruoho     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
    198       1.1    jruoho     if (!GpeRegisterInfo)
    199       1.1    jruoho     {
    200       1.1    jruoho         return_ACPI_STATUS (AE_NOT_EXIST);
    201       1.1    jruoho     }
    202       1.1    jruoho 
    203   1.1.1.3  christos     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
    204       1.1    jruoho 
    205   1.1.1.2    jruoho     /* Clear the run bit up front */
    206       1.1    jruoho 
    207       1.1    jruoho     ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
    208       1.1    jruoho 
    209   1.1.1.2    jruoho     /* Set the mask bit only if there are references to this GPE */
    210       1.1    jruoho 
    211       1.1    jruoho     if (GpeEventInfo->RuntimeCount)
    212       1.1    jruoho     {
    213   1.1.1.2    jruoho         ACPI_SET_BIT (GpeRegisterInfo->EnableForRun, (UINT8) RegisterBit);
    214       1.1    jruoho     }
    215       1.1    jruoho 
    216   1.1.1.7  christos     GpeRegisterInfo->EnableMask = GpeRegisterInfo->EnableForRun;
    217       1.1    jruoho     return_ACPI_STATUS (AE_OK);
    218       1.1    jruoho }
    219       1.1    jruoho 
    220       1.1    jruoho 
    221       1.1    jruoho /*******************************************************************************
    222       1.1    jruoho  *
    223       1.1    jruoho  * FUNCTION:    AcpiEvEnableGpe
    224       1.1    jruoho  *
    225       1.1    jruoho  * PARAMETERS:  GpeEventInfo            - GPE to enable
    226       1.1    jruoho  *
    227       1.1    jruoho  * RETURN:      Status
    228       1.1    jruoho  *
    229  1.1.1.11  christos  * DESCRIPTION: Enable a GPE.
    230       1.1    jruoho  *
    231       1.1    jruoho  ******************************************************************************/
    232       1.1    jruoho 
    233       1.1    jruoho ACPI_STATUS
    234       1.1    jruoho AcpiEvEnableGpe (
    235       1.1    jruoho     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
    236       1.1    jruoho {
    237       1.1    jruoho     ACPI_STATUS             Status;
    238       1.1    jruoho 
    239       1.1    jruoho 
    240       1.1    jruoho     ACPI_FUNCTION_TRACE (EvEnableGpe);
    241       1.1    jruoho 
    242       1.1    jruoho 
    243       1.1    jruoho     /* Enable the requested GPE */
    244       1.1    jruoho 
    245   1.1.1.6  christos     Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE);
    246       1.1    jruoho     return_ACPI_STATUS (Status);
    247       1.1    jruoho }
    248       1.1    jruoho 
    249       1.1    jruoho 
    250       1.1    jruoho /*******************************************************************************
    251       1.1    jruoho  *
    252   1.1.1.8  christos  * FUNCTION:    AcpiEvMaskGpe
    253   1.1.1.8  christos  *
    254   1.1.1.8  christos  * PARAMETERS:  GpeEventInfo            - GPE to be blocked/unblocked
    255   1.1.1.8  christos  *              IsMasked                - Whether the GPE is masked or not
    256   1.1.1.8  christos  *
    257   1.1.1.8  christos  * RETURN:      Status
    258   1.1.1.8  christos  *
    259   1.1.1.8  christos  * DESCRIPTION: Unconditionally mask/unmask a GPE during runtime.
    260   1.1.1.8  christos  *
    261   1.1.1.8  christos  ******************************************************************************/
    262   1.1.1.8  christos 
    263   1.1.1.8  christos ACPI_STATUS
    264   1.1.1.8  christos AcpiEvMaskGpe (
    265   1.1.1.8  christos     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
    266   1.1.1.8  christos     BOOLEAN                 IsMasked)
    267   1.1.1.8  christos {
    268   1.1.1.8  christos     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
    269   1.1.1.8  christos     UINT32                  RegisterBit;
    270   1.1.1.8  christos 
    271   1.1.1.8  christos 
    272   1.1.1.8  christos     ACPI_FUNCTION_TRACE (EvMaskGpe);
    273   1.1.1.8  christos 
    274   1.1.1.8  christos 
    275   1.1.1.8  christos     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
    276   1.1.1.8  christos     if (!GpeRegisterInfo)
    277   1.1.1.8  christos     {
    278   1.1.1.8  christos         return_ACPI_STATUS (AE_NOT_EXIST);
    279   1.1.1.8  christos     }
    280   1.1.1.8  christos 
    281   1.1.1.8  christos     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
    282   1.1.1.8  christos 
    283   1.1.1.8  christos     /* Perform the action */
    284   1.1.1.8  christos 
    285   1.1.1.8  christos     if (IsMasked)
    286   1.1.1.8  christos     {
    287   1.1.1.8  christos         if (RegisterBit & GpeRegisterInfo->MaskForRun)
    288   1.1.1.8  christos         {
    289   1.1.1.8  christos             return_ACPI_STATUS (AE_BAD_PARAMETER);
    290   1.1.1.8  christos         }
    291   1.1.1.8  christos 
    292   1.1.1.8  christos         (void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
    293   1.1.1.8  christos         ACPI_SET_BIT (GpeRegisterInfo->MaskForRun, (UINT8) RegisterBit);
    294   1.1.1.8  christos     }
    295   1.1.1.8  christos     else
    296   1.1.1.8  christos     {
    297   1.1.1.8  christos         if (!(RegisterBit & GpeRegisterInfo->MaskForRun))
    298   1.1.1.8  christos         {
    299   1.1.1.8  christos             return_ACPI_STATUS (AE_BAD_PARAMETER);
    300   1.1.1.8  christos         }
    301   1.1.1.8  christos 
    302   1.1.1.8  christos         ACPI_CLEAR_BIT (GpeRegisterInfo->MaskForRun, (UINT8) RegisterBit);
    303   1.1.1.8  christos         if (GpeEventInfo->RuntimeCount &&
    304   1.1.1.8  christos             !GpeEventInfo->DisableForDispatch)
    305   1.1.1.8  christos         {
    306   1.1.1.8  christos             (void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE);
    307   1.1.1.8  christos         }
    308   1.1.1.8  christos     }
    309   1.1.1.8  christos 
    310   1.1.1.8  christos     return_ACPI_STATUS (AE_OK);
    311   1.1.1.8  christos }
    312   1.1.1.8  christos 
    313   1.1.1.8  christos 
    314   1.1.1.8  christos /*******************************************************************************
    315   1.1.1.8  christos  *
    316   1.1.1.2    jruoho  * FUNCTION:    AcpiEvAddGpeReference
    317       1.1    jruoho  *
    318   1.1.1.2    jruoho  * PARAMETERS:  GpeEventInfo            - Add a reference to this GPE
    319  1.1.1.13  christos  *              ClearOnEnable           - Clear GPE status before enabling it
    320       1.1    jruoho  *
    321       1.1    jruoho  * RETURN:      Status
    322       1.1    jruoho  *
    323   1.1.1.2    jruoho  * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
    324   1.1.1.2    jruoho  *              hardware-enabled.
    325       1.1    jruoho  *
    326       1.1    jruoho  ******************************************************************************/
    327       1.1    jruoho 
    328       1.1    jruoho ACPI_STATUS
    329   1.1.1.2    jruoho AcpiEvAddGpeReference (
    330  1.1.1.13  christos     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
    331  1.1.1.13  christos     BOOLEAN                 ClearOnEnable)
    332       1.1    jruoho {
    333   1.1.1.2    jruoho     ACPI_STATUS             Status = AE_OK;
    334       1.1    jruoho 
    335       1.1    jruoho 
    336   1.1.1.2    jruoho     ACPI_FUNCTION_TRACE (EvAddGpeReference);
    337       1.1    jruoho 
    338       1.1    jruoho 
    339   1.1.1.2    jruoho     if (GpeEventInfo->RuntimeCount == ACPI_UINT8_MAX)
    340   1.1.1.2    jruoho     {
    341   1.1.1.2    jruoho         return_ACPI_STATUS (AE_LIMIT);
    342   1.1.1.2    jruoho     }
    343       1.1    jruoho 
    344   1.1.1.2    jruoho     GpeEventInfo->RuntimeCount++;
    345   1.1.1.2    jruoho     if (GpeEventInfo->RuntimeCount == 1)
    346   1.1.1.2    jruoho     {
    347   1.1.1.2    jruoho         /* Enable on first reference */
    348       1.1    jruoho 
    349  1.1.1.13  christos         if (ClearOnEnable)
    350  1.1.1.13  christos         {
    351  1.1.1.13  christos             (void) AcpiHwClearGpe (GpeEventInfo);
    352  1.1.1.13  christos         }
    353  1.1.1.13  christos 
    354   1.1.1.2    jruoho         Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo);
    355   1.1.1.2    jruoho         if (ACPI_SUCCESS (Status))
    356   1.1.1.2    jruoho         {
    357   1.1.1.2    jruoho             Status = AcpiEvEnableGpe (GpeEventInfo);
    358   1.1.1.2    jruoho         }
    359   1.1.1.2    jruoho 
    360   1.1.1.2    jruoho         if (ACPI_FAILURE (Status))
    361   1.1.1.2    jruoho         {
    362   1.1.1.2    jruoho             GpeEventInfo->RuntimeCount--;
    363   1.1.1.2    jruoho         }
    364   1.1.1.2    jruoho     }
    365   1.1.1.2    jruoho 
    366   1.1.1.2    jruoho     return_ACPI_STATUS (Status);
    367   1.1.1.2    jruoho }
    368   1.1.1.2    jruoho 
    369   1.1.1.2    jruoho 
    370   1.1.1.2    jruoho /*******************************************************************************
    371   1.1.1.2    jruoho  *
    372   1.1.1.2    jruoho  * FUNCTION:    AcpiEvRemoveGpeReference
    373   1.1.1.2    jruoho  *
    374   1.1.1.2    jruoho  * PARAMETERS:  GpeEventInfo            - Remove a reference to this GPE
    375   1.1.1.2    jruoho  *
    376   1.1.1.2    jruoho  * RETURN:      Status
    377   1.1.1.2    jruoho  *
    378   1.1.1.2    jruoho  * DESCRIPTION: Remove a reference to a GPE. When the last reference is
    379   1.1.1.2    jruoho  *              removed, the GPE is hardware-disabled.
    380   1.1.1.2    jruoho  *
    381   1.1.1.2    jruoho  ******************************************************************************/
    382   1.1.1.2    jruoho 
    383   1.1.1.2    jruoho ACPI_STATUS
    384   1.1.1.2    jruoho AcpiEvRemoveGpeReference (
    385   1.1.1.2    jruoho     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
    386   1.1.1.2    jruoho {
    387   1.1.1.2    jruoho     ACPI_STATUS             Status = AE_OK;
    388   1.1.1.2    jruoho 
    389   1.1.1.2    jruoho 
    390   1.1.1.2    jruoho     ACPI_FUNCTION_TRACE (EvRemoveGpeReference);
    391   1.1.1.2    jruoho 
    392   1.1.1.2    jruoho 
    393   1.1.1.2    jruoho     if (!GpeEventInfo->RuntimeCount)
    394       1.1    jruoho     {
    395   1.1.1.2    jruoho         return_ACPI_STATUS (AE_LIMIT);
    396   1.1.1.2    jruoho     }
    397   1.1.1.2    jruoho 
    398   1.1.1.2    jruoho     GpeEventInfo->RuntimeCount--;
    399   1.1.1.2    jruoho     if (!GpeEventInfo->RuntimeCount)
    400   1.1.1.2    jruoho     {
    401   1.1.1.2    jruoho         /* Disable on last reference */
    402   1.1.1.2    jruoho 
    403   1.1.1.2    jruoho         Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo);
    404   1.1.1.2    jruoho         if (ACPI_SUCCESS (Status))
    405   1.1.1.2    jruoho         {
    406   1.1.1.6  christos             Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
    407   1.1.1.2    jruoho         }
    408   1.1.1.2    jruoho 
    409   1.1.1.2    jruoho         if (ACPI_FAILURE (Status))
    410   1.1.1.2    jruoho         {
    411   1.1.1.2    jruoho             GpeEventInfo->RuntimeCount++;
    412   1.1.1.2    jruoho         }
    413       1.1    jruoho     }
    414       1.1    jruoho 
    415       1.1    jruoho     return_ACPI_STATUS (Status);
    416       1.1    jruoho }
    417       1.1    jruoho 
    418       1.1    jruoho 
    419       1.1    jruoho /*******************************************************************************
    420       1.1    jruoho  *
    421       1.1    jruoho  * FUNCTION:    AcpiEvLowGetGpeInfo
    422       1.1    jruoho  *
    423       1.1    jruoho  * PARAMETERS:  GpeNumber           - Raw GPE number
    424       1.1    jruoho  *              GpeBlock            - A GPE info block
    425       1.1    jruoho  *
    426       1.1    jruoho  * RETURN:      A GPE EventInfo struct. NULL if not a valid GPE (The GpeNumber
    427       1.1    jruoho  *              is not within the specified GPE block)
    428       1.1    jruoho  *
    429       1.1    jruoho  * DESCRIPTION: Returns the EventInfo struct associated with this GPE. This is
    430       1.1    jruoho  *              the low-level implementation of EvGetGpeEventInfo.
    431       1.1    jruoho  *
    432       1.1    jruoho  ******************************************************************************/
    433       1.1    jruoho 
    434       1.1    jruoho ACPI_GPE_EVENT_INFO *
    435       1.1    jruoho AcpiEvLowGetGpeInfo (
    436       1.1    jruoho     UINT32                  GpeNumber,
    437       1.1    jruoho     ACPI_GPE_BLOCK_INFO     *GpeBlock)
    438       1.1    jruoho {
    439       1.1    jruoho     UINT32                  GpeIndex;
    440       1.1    jruoho 
    441       1.1    jruoho 
    442       1.1    jruoho     /*
    443       1.1    jruoho      * Validate that the GpeNumber is within the specified GpeBlock.
    444       1.1    jruoho      * (Two steps)
    445       1.1    jruoho      */
    446       1.1    jruoho     if (!GpeBlock ||
    447       1.1    jruoho         (GpeNumber < GpeBlock->BlockBaseNumber))
    448       1.1    jruoho     {
    449       1.1    jruoho         return (NULL);
    450       1.1    jruoho     }
    451       1.1    jruoho 
    452       1.1    jruoho     GpeIndex = GpeNumber - GpeBlock->BlockBaseNumber;
    453       1.1    jruoho     if (GpeIndex >= GpeBlock->GpeCount)
    454       1.1    jruoho     {
    455       1.1    jruoho         return (NULL);
    456       1.1    jruoho     }
    457       1.1    jruoho 
    458       1.1    jruoho     return (&GpeBlock->EventInfo[GpeIndex]);
    459       1.1    jruoho }
    460       1.1    jruoho 
    461       1.1    jruoho 
    462       1.1    jruoho /*******************************************************************************
    463       1.1    jruoho  *
    464       1.1    jruoho  * FUNCTION:    AcpiEvGetGpeEventInfo
    465       1.1    jruoho  *
    466       1.1    jruoho  * PARAMETERS:  GpeDevice           - Device node. NULL for GPE0/GPE1
    467       1.1    jruoho  *              GpeNumber           - Raw GPE number
    468       1.1    jruoho  *
    469       1.1    jruoho  * RETURN:      A GPE EventInfo struct. NULL if not a valid GPE
    470       1.1    jruoho  *
    471       1.1    jruoho  * DESCRIPTION: Returns the EventInfo struct associated with this GPE.
    472       1.1    jruoho  *              Validates the GpeBlock and the GpeNumber
    473       1.1    jruoho  *
    474       1.1    jruoho  *              Should be called only when the GPE lists are semaphore locked
    475       1.1    jruoho  *              and not subject to change.
    476       1.1    jruoho  *
    477       1.1    jruoho  ******************************************************************************/
    478       1.1    jruoho 
    479       1.1    jruoho ACPI_GPE_EVENT_INFO *
    480       1.1    jruoho AcpiEvGetGpeEventInfo (
    481       1.1    jruoho     ACPI_HANDLE             GpeDevice,
    482       1.1    jruoho     UINT32                  GpeNumber)
    483       1.1    jruoho {
    484       1.1    jruoho     ACPI_OPERAND_OBJECT     *ObjDesc;
    485       1.1    jruoho     ACPI_GPE_EVENT_INFO     *GpeInfo;
    486       1.1    jruoho     UINT32                  i;
    487       1.1    jruoho 
    488       1.1    jruoho 
    489       1.1    jruoho     ACPI_FUNCTION_ENTRY ();
    490       1.1    jruoho 
    491       1.1    jruoho 
    492       1.1    jruoho     /* A NULL GpeDevice means use the FADT-defined GPE block(s) */
    493       1.1    jruoho 
    494       1.1    jruoho     if (!GpeDevice)
    495       1.1    jruoho     {
    496       1.1    jruoho         /* Examine GPE Block 0 and 1 (These blocks are permanent) */
    497       1.1    jruoho 
    498       1.1    jruoho         for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++)
    499       1.1    jruoho         {
    500       1.1    jruoho             GpeInfo = AcpiEvLowGetGpeInfo (GpeNumber,
    501   1.1.1.7  christos                 AcpiGbl_GpeFadtBlocks[i]);
    502       1.1    jruoho             if (GpeInfo)
    503       1.1    jruoho             {
    504       1.1    jruoho                 return (GpeInfo);
    505       1.1    jruoho             }
    506       1.1    jruoho         }
    507       1.1    jruoho 
    508       1.1    jruoho         /* The GpeNumber was not in the range of either FADT GPE block */
    509       1.1    jruoho 
    510       1.1    jruoho         return (NULL);
    511       1.1    jruoho     }
    512       1.1    jruoho 
    513       1.1    jruoho     /* A Non-NULL GpeDevice means this is a GPE Block Device */
    514       1.1    jruoho 
    515       1.1    jruoho     ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) GpeDevice);
    516       1.1    jruoho     if (!ObjDesc ||
    517       1.1    jruoho         !ObjDesc->Device.GpeBlock)
    518       1.1    jruoho     {
    519       1.1    jruoho         return (NULL);
    520       1.1    jruoho     }
    521       1.1    jruoho 
    522       1.1    jruoho     return (AcpiEvLowGetGpeInfo (GpeNumber, ObjDesc->Device.GpeBlock));
    523       1.1    jruoho }
    524       1.1    jruoho 
    525       1.1    jruoho 
    526       1.1    jruoho /*******************************************************************************
    527       1.1    jruoho  *
    528       1.1    jruoho  * FUNCTION:    AcpiEvGpeDetect
    529       1.1    jruoho  *
    530       1.1    jruoho  * PARAMETERS:  GpeXruptList        - Interrupt block for this interrupt.
    531       1.1    jruoho  *                                    Can have multiple GPE blocks attached.
    532       1.1    jruoho  *
    533       1.1    jruoho  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
    534       1.1    jruoho  *
    535       1.1    jruoho  * DESCRIPTION: Detect if any GP events have occurred. This function is
    536       1.1    jruoho  *              executed at interrupt level.
    537       1.1    jruoho  *
    538       1.1    jruoho  ******************************************************************************/
    539       1.1    jruoho 
    540       1.1    jruoho UINT32
    541       1.1    jruoho AcpiEvGpeDetect (
    542       1.1    jruoho     ACPI_GPE_XRUPT_INFO     *GpeXruptList)
    543       1.1    jruoho {
    544       1.1    jruoho     ACPI_GPE_BLOCK_INFO     *GpeBlock;
    545   1.1.1.5  christos     ACPI_NAMESPACE_NODE     *GpeDevice;
    546       1.1    jruoho     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
    547   1.1.1.5  christos     ACPI_GPE_EVENT_INFO     *GpeEventInfo;
    548   1.1.1.5  christos     UINT32                  GpeNumber;
    549       1.1    jruoho     UINT32                  IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
    550       1.1    jruoho     ACPI_CPU_FLAGS          Flags;
    551       1.1    jruoho     UINT32                  i;
    552       1.1    jruoho     UINT32                  j;
    553       1.1    jruoho 
    554       1.1    jruoho 
    555       1.1    jruoho     ACPI_FUNCTION_NAME (EvGpeDetect);
    556       1.1    jruoho 
    557       1.1    jruoho     /* Check for the case where there are no GPEs */
    558       1.1    jruoho 
    559       1.1    jruoho     if (!GpeXruptList)
    560       1.1    jruoho     {
    561       1.1    jruoho         return (IntStatus);
    562       1.1    jruoho     }
    563       1.1    jruoho 
    564       1.1    jruoho     /*
    565       1.1    jruoho      * We need to obtain the GPE lock for both the data structs and registers
    566       1.1    jruoho      * Note: Not necessary to obtain the hardware lock, since the GPE
    567       1.1    jruoho      * registers are owned by the GpeLock.
    568       1.1    jruoho      */
    569       1.1    jruoho     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
    570       1.1    jruoho 
    571       1.1    jruoho     /* Examine all GPE blocks attached to this interrupt level */
    572       1.1    jruoho 
    573       1.1    jruoho     GpeBlock = GpeXruptList->GpeBlockListHead;
    574       1.1    jruoho     while (GpeBlock)
    575       1.1    jruoho     {
    576   1.1.1.5  christos         GpeDevice = GpeBlock->Node;
    577   1.1.1.5  christos 
    578       1.1    jruoho         /*
    579       1.1    jruoho          * Read all of the 8-bit GPE status and enable registers in this GPE
    580       1.1    jruoho          * block, saving all of them. Find all currently active GP events.
    581       1.1    jruoho          */
    582       1.1    jruoho         for (i = 0; i < GpeBlock->RegisterCount; i++)
    583       1.1    jruoho         {
    584       1.1    jruoho             /* Get the next status/enable pair */
    585       1.1    jruoho 
    586       1.1    jruoho             GpeRegisterInfo = &GpeBlock->RegisterInfo[i];
    587       1.1    jruoho 
    588   1.1.1.2    jruoho             /*
    589   1.1.1.2    jruoho              * Optimization: If there are no GPEs enabled within this
    590   1.1.1.2    jruoho              * register, we can safely ignore the entire register.
    591   1.1.1.2    jruoho              */
    592   1.1.1.2    jruoho             if (!(GpeRegisterInfo->EnableForRun |
    593   1.1.1.2    jruoho                   GpeRegisterInfo->EnableForWake))
    594   1.1.1.2    jruoho             {
    595   1.1.1.3  christos                 ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
    596   1.1.1.4  christos                     "Ignore disabled registers for GPE %02X-%02X: "
    597   1.1.1.3  christos                     "RunEnable=%02X, WakeEnable=%02X\n",
    598   1.1.1.3  christos                     GpeRegisterInfo->BaseGpeNumber,
    599   1.1.1.3  christos                     GpeRegisterInfo->BaseGpeNumber + (ACPI_GPE_REGISTER_WIDTH - 1),
    600   1.1.1.3  christos                     GpeRegisterInfo->EnableForRun,
    601   1.1.1.3  christos                     GpeRegisterInfo->EnableForWake));
    602   1.1.1.2    jruoho                 continue;
    603   1.1.1.2    jruoho             }
    604   1.1.1.2    jruoho 
    605       1.1    jruoho             /* Now look at the individual GPEs in this byte register */
    606       1.1    jruoho 
    607       1.1    jruoho             for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
    608       1.1    jruoho             {
    609  1.1.1.11  christos                 /* Detect and dispatch one GPE bit */
    610       1.1    jruoho 
    611   1.1.1.5  christos                 GpeEventInfo = &GpeBlock->EventInfo[((ACPI_SIZE) i *
    612   1.1.1.5  christos                     ACPI_GPE_REGISTER_WIDTH) + j];
    613   1.1.1.5  christos                 GpeNumber = j + GpeRegisterInfo->BaseGpeNumber;
    614  1.1.1.11  christos                 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
    615  1.1.1.11  christos                 IntStatus |= AcpiEvDetectGpe (
    616  1.1.1.11  christos                     GpeDevice, GpeEventInfo, GpeNumber);
    617  1.1.1.11  christos                 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
    618       1.1    jruoho             }
    619       1.1    jruoho         }
    620       1.1    jruoho 
    621       1.1    jruoho         GpeBlock = GpeBlock->Next;
    622       1.1    jruoho     }
    623       1.1    jruoho 
    624       1.1    jruoho     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
    625       1.1    jruoho     return (IntStatus);
    626       1.1    jruoho }
    627       1.1    jruoho 
    628       1.1    jruoho 
    629       1.1    jruoho /*******************************************************************************
    630       1.1    jruoho  *
    631       1.1    jruoho  * FUNCTION:    AcpiEvAsynchExecuteGpeMethod
    632       1.1    jruoho  *
    633       1.1    jruoho  * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
    634       1.1    jruoho  *
    635       1.1    jruoho  * RETURN:      None
    636       1.1    jruoho  *
    637       1.1    jruoho  * DESCRIPTION: Perform the actual execution of a GPE control method. This
    638       1.1    jruoho  *              function is called from an invocation of AcpiOsExecute and
    639       1.1    jruoho  *              therefore does NOT execute at interrupt level - so that
    640       1.1    jruoho  *              the control method itself is not executed in the context of
    641       1.1    jruoho  *              an interrupt handler.
    642       1.1    jruoho  *
    643       1.1    jruoho  ******************************************************************************/
    644       1.1    jruoho 
    645       1.1    jruoho static void ACPI_SYSTEM_XFACE
    646       1.1    jruoho AcpiEvAsynchExecuteGpeMethod (
    647       1.1    jruoho     void                    *Context)
    648       1.1    jruoho {
    649       1.1    jruoho     ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
    650   1.1.1.5  christos     ACPI_STATUS             Status = AE_OK;
    651       1.1    jruoho     ACPI_EVALUATE_INFO      *Info;
    652   1.1.1.3  christos     ACPI_GPE_NOTIFY_INFO    *Notify;
    653       1.1    jruoho 
    654       1.1    jruoho 
    655       1.1    jruoho     ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod);
    656       1.1    jruoho 
    657       1.1    jruoho 
    658   1.1.1.2    jruoho     /* Do the correct dispatch - normal method or implicit notify */
    659   1.1.1.2    jruoho 
    660   1.1.1.5  christos     switch (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags))
    661       1.1    jruoho     {
    662   1.1.1.2    jruoho     case ACPI_GPE_DISPATCH_NOTIFY:
    663   1.1.1.2    jruoho         /*
    664   1.1.1.2    jruoho          * Implicit notify.
    665   1.1.1.2    jruoho          * Dispatch a DEVICE_WAKE notify to the appropriate handler.
    666   1.1.1.2    jruoho          * NOTE: the request is queued for execution after this method
    667   1.1.1.2    jruoho          * completes. The notify handlers are NOT invoked synchronously
    668   1.1.1.2    jruoho          * from this thread -- because handlers may in turn run other
    669   1.1.1.2    jruoho          * control methods.
    670   1.1.1.3  christos          *
    671   1.1.1.3  christos          * June 2012: Expand implicit notify mechanism to support
    672   1.1.1.3  christos          * notifies on multiple device objects.
    673   1.1.1.2    jruoho          */
    674   1.1.1.5  christos         Notify = GpeEventInfo->Dispatch.NotifyList;
    675   1.1.1.3  christos         while (ACPI_SUCCESS (Status) && Notify)
    676   1.1.1.3  christos         {
    677   1.1.1.7  christos             Status = AcpiEvQueueNotifyRequest (
    678   1.1.1.7  christos                 Notify->DeviceNode, ACPI_NOTIFY_DEVICE_WAKE);
    679   1.1.1.3  christos 
    680   1.1.1.3  christos             Notify = Notify->Next;
    681   1.1.1.3  christos         }
    682   1.1.1.2    jruoho         break;
    683   1.1.1.2    jruoho 
    684   1.1.1.2    jruoho     case ACPI_GPE_DISPATCH_METHOD:
    685   1.1.1.2    jruoho 
    686       1.1    jruoho         /* Allocate the evaluation information block */
    687       1.1    jruoho 
    688       1.1    jruoho         Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
    689       1.1    jruoho         if (!Info)
    690       1.1    jruoho         {
    691       1.1    jruoho             Status = AE_NO_MEMORY;
    692       1.1    jruoho         }
    693       1.1    jruoho         else
    694       1.1    jruoho         {
    695       1.1    jruoho             /*
    696   1.1.1.2    jruoho              * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the
    697   1.1.1.2    jruoho              * _Lxx/_Exx control method that corresponds to this GPE
    698       1.1    jruoho              */
    699   1.1.1.5  christos             Info->PrefixNode = GpeEventInfo->Dispatch.MethodNode;
    700       1.1    jruoho             Info->Flags = ACPI_IGNORE_RETURN_VALUE;
    701       1.1    jruoho 
    702       1.1    jruoho             Status = AcpiNsEvaluate (Info);
    703       1.1    jruoho             ACPI_FREE (Info);
    704       1.1    jruoho         }
    705       1.1    jruoho 
    706       1.1    jruoho         if (ACPI_FAILURE (Status))
    707       1.1    jruoho         {
    708       1.1    jruoho             ACPI_EXCEPTION ((AE_INFO, Status,
    709       1.1    jruoho                 "while evaluating GPE method [%4.4s]",
    710   1.1.1.5  christos                 AcpiUtGetNodeName (GpeEventInfo->Dispatch.MethodNode)));
    711       1.1    jruoho         }
    712   1.1.1.2    jruoho         break;
    713   1.1.1.2    jruoho 
    714   1.1.1.2    jruoho     default:
    715   1.1.1.3  christos 
    716   1.1.1.5  christos         goto ErrorExit; /* Should never happen */
    717       1.1    jruoho     }
    718       1.1    jruoho 
    719       1.1    jruoho     /* Defer enabling of GPE until all notify handlers are done */
    720       1.1    jruoho 
    721       1.1    jruoho     Status = AcpiOsExecute (OSL_NOTIFY_HANDLER,
    722   1.1.1.7  christos         AcpiEvAsynchEnableGpe, GpeEventInfo);
    723   1.1.1.5  christos     if (ACPI_SUCCESS (Status))
    724       1.1    jruoho     {
    725   1.1.1.5  christos         return_VOID;
    726       1.1    jruoho     }
    727   1.1.1.5  christos 
    728   1.1.1.5  christos ErrorExit:
    729   1.1.1.5  christos     AcpiEvAsynchEnableGpe (GpeEventInfo);
    730       1.1    jruoho     return_VOID;
    731       1.1    jruoho }
    732       1.1    jruoho 
    733       1.1    jruoho 
    734       1.1    jruoho /*******************************************************************************
    735       1.1    jruoho  *
    736       1.1    jruoho  * FUNCTION:    AcpiEvAsynchEnableGpe
    737       1.1    jruoho  *
    738       1.1    jruoho  * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
    739   1.1.1.2    jruoho  *              Callback from AcpiOsExecute
    740       1.1    jruoho  *
    741       1.1    jruoho  * RETURN:      None
    742       1.1    jruoho  *
    743       1.1    jruoho  * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to
    744       1.1    jruoho  *              complete (i.e., finish execution of Notify)
    745       1.1    jruoho  *
    746       1.1    jruoho  ******************************************************************************/
    747       1.1    jruoho 
    748       1.1    jruoho static void ACPI_SYSTEM_XFACE
    749       1.1    jruoho AcpiEvAsynchEnableGpe (
    750       1.1    jruoho     void                    *Context)
    751       1.1    jruoho {
    752       1.1    jruoho     ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
    753   1.1.1.5  christos     ACPI_CPU_FLAGS          Flags;
    754   1.1.1.2    jruoho 
    755   1.1.1.2    jruoho 
    756   1.1.1.5  christos     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
    757   1.1.1.2    jruoho     (void) AcpiEvFinishGpe (GpeEventInfo);
    758   1.1.1.5  christos     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
    759   1.1.1.2    jruoho 
    760   1.1.1.2    jruoho     return;
    761   1.1.1.2    jruoho }
    762   1.1.1.2    jruoho 
    763   1.1.1.2    jruoho 
    764   1.1.1.2    jruoho /*******************************************************************************
    765   1.1.1.2    jruoho  *
    766   1.1.1.2    jruoho  * FUNCTION:    AcpiEvFinishGpe
    767   1.1.1.2    jruoho  *
    768   1.1.1.2    jruoho  * PARAMETERS:  GpeEventInfo        - Info for this GPE
    769   1.1.1.2    jruoho  *
    770   1.1.1.2    jruoho  * RETURN:      Status
    771   1.1.1.2    jruoho  *
    772   1.1.1.2    jruoho  * DESCRIPTION: Clear/Enable a GPE. Common code that is used after execution
    773   1.1.1.2    jruoho  *              of a GPE method or a synchronous or asynchronous GPE handler.
    774   1.1.1.2    jruoho  *
    775   1.1.1.2    jruoho  ******************************************************************************/
    776   1.1.1.2    jruoho 
    777   1.1.1.2    jruoho ACPI_STATUS
    778   1.1.1.2    jruoho AcpiEvFinishGpe (
    779   1.1.1.2    jruoho     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
    780   1.1.1.2    jruoho {
    781       1.1    jruoho     ACPI_STATUS             Status;
    782       1.1    jruoho 
    783       1.1    jruoho 
    784       1.1    jruoho     if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
    785       1.1    jruoho             ACPI_GPE_LEVEL_TRIGGERED)
    786       1.1    jruoho     {
    787       1.1    jruoho         /*
    788   1.1.1.2    jruoho          * GPE is level-triggered, we clear the GPE status bit after
    789   1.1.1.2    jruoho          * handling the event.
    790       1.1    jruoho          */
    791       1.1    jruoho         Status = AcpiHwClearGpe (GpeEventInfo);
    792       1.1    jruoho         if (ACPI_FAILURE (Status))
    793       1.1    jruoho         {
    794   1.1.1.2    jruoho             return (Status);
    795       1.1    jruoho         }
    796       1.1    jruoho     }
    797       1.1    jruoho 
    798   1.1.1.2    jruoho     /*
    799   1.1.1.2    jruoho      * Enable this GPE, conditionally. This means that the GPE will
    800   1.1.1.5  christos      * only be physically enabled if the EnableMask bit is set
    801   1.1.1.2    jruoho      * in the EventInfo.
    802   1.1.1.2    jruoho      */
    803   1.1.1.2    jruoho     (void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_CONDITIONAL_ENABLE);
    804   1.1.1.8  christos     GpeEventInfo->DisableForDispatch = FALSE;
    805   1.1.1.2    jruoho     return (AE_OK);
    806       1.1    jruoho }
    807       1.1    jruoho 
    808       1.1    jruoho 
    809       1.1    jruoho /*******************************************************************************
    810       1.1    jruoho  *
    811  1.1.1.11  christos  * FUNCTION:    AcpiEvDetectGpe
    812  1.1.1.11  christos  *
    813  1.1.1.11  christos  * PARAMETERS:  GpeDevice           - Device node. NULL for GPE0/GPE1
    814  1.1.1.11  christos  *              GpeEventInfo        - Info for this GPE
    815  1.1.1.11  christos  *              GpeNumber           - Number relative to the parent GPE block
    816  1.1.1.11  christos  *
    817  1.1.1.11  christos  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
    818  1.1.1.11  christos  *
    819  1.1.1.11  christos  * DESCRIPTION: Detect and dispatch a General Purpose Event to either a function
    820  1.1.1.11  christos  *              (e.g. EC) or method (e.g. _Lxx/_Exx) handler.
    821  1.1.1.11  christos  * NOTE:        GPE is W1C, so it is possible to handle a single GPE from both
    822  1.1.1.11  christos  *              task and irq context in parallel as long as the process to
    823  1.1.1.11  christos  *              detect and mask the GPE is atomic.
    824  1.1.1.11  christos  *              However the atomicity of ACPI_GPE_DISPATCH_RAW_HANDLER is
    825  1.1.1.11  christos  *              dependent on the raw handler itself.
    826  1.1.1.11  christos  *
    827  1.1.1.11  christos  ******************************************************************************/
    828  1.1.1.11  christos 
    829  1.1.1.11  christos UINT32
    830  1.1.1.11  christos AcpiEvDetectGpe (
    831  1.1.1.11  christos     ACPI_NAMESPACE_NODE     *GpeDevice,
    832  1.1.1.11  christos     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
    833  1.1.1.11  christos     UINT32                  GpeNumber)
    834  1.1.1.11  christos {
    835  1.1.1.11  christos     UINT32                  IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
    836  1.1.1.11  christos     UINT8                   EnabledStatusByte;
    837  1.1.1.11  christos     UINT64                  StatusReg;
    838  1.1.1.11  christos     UINT64                  EnableReg;
    839  1.1.1.11  christos     UINT32                  RegisterBit;
    840  1.1.1.11  christos     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
    841  1.1.1.11  christos     ACPI_GPE_HANDLER_INFO   *GpeHandlerInfo;
    842  1.1.1.11  christos     ACPI_CPU_FLAGS          Flags;
    843  1.1.1.11  christos     ACPI_STATUS             Status;
    844  1.1.1.11  christos 
    845  1.1.1.11  christos 
    846  1.1.1.11  christos     ACPI_FUNCTION_TRACE (EvGpeDetect);
    847  1.1.1.11  christos 
    848  1.1.1.11  christos 
    849  1.1.1.11  christos     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
    850  1.1.1.11  christos 
    851  1.1.1.13  christos     if (!GpeEventInfo)
    852  1.1.1.13  christos     {
    853  1.1.1.13  christos         GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
    854  1.1.1.13  christos         if (!GpeEventInfo)
    855  1.1.1.13  christos         {
    856  1.1.1.13  christos             goto ErrorExit;
    857  1.1.1.13  christos         }
    858  1.1.1.13  christos     }
    859  1.1.1.13  christos 
    860  1.1.1.11  christos     /* Get the info block for the entire GPE register */
    861  1.1.1.11  christos 
    862  1.1.1.11  christos     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
    863  1.1.1.11  christos 
    864  1.1.1.11  christos     /* Get the register bitmask for this GPE */
    865  1.1.1.11  christos 
    866  1.1.1.11  christos     RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);
    867  1.1.1.11  christos 
    868  1.1.1.11  christos     /* GPE currently enabled (enable bit == 1)? */
    869  1.1.1.11  christos 
    870  1.1.1.11  christos     Status = AcpiHwRead (&EnableReg, &GpeRegisterInfo->EnableAddress);
    871  1.1.1.11  christos     if (ACPI_FAILURE (Status))
    872  1.1.1.11  christos     {
    873  1.1.1.11  christos         goto ErrorExit;
    874  1.1.1.11  christos     }
    875  1.1.1.11  christos 
    876  1.1.1.11  christos     /* GPE currently active (status bit == 1)? */
    877  1.1.1.11  christos 
    878  1.1.1.11  christos     Status = AcpiHwRead (&StatusReg, &GpeRegisterInfo->StatusAddress);
    879  1.1.1.11  christos     if (ACPI_FAILURE (Status))
    880  1.1.1.11  christos     {
    881  1.1.1.11  christos         goto ErrorExit;
    882  1.1.1.11  christos     }
    883  1.1.1.11  christos 
    884  1.1.1.11  christos     /* Check if there is anything active at all in this GPE */
    885  1.1.1.11  christos 
    886  1.1.1.11  christos     ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
    887  1.1.1.11  christos         "Read registers for GPE %02X: Status=%02X, Enable=%02X, "
    888  1.1.1.11  christos         "RunEnable=%02X, WakeEnable=%02X\n",
    889  1.1.1.11  christos         GpeNumber,
    890  1.1.1.11  christos         (UINT32) (StatusReg & RegisterBit),
    891  1.1.1.11  christos         (UINT32) (EnableReg & RegisterBit),
    892  1.1.1.11  christos         GpeRegisterInfo->EnableForRun,
    893  1.1.1.11  christos         GpeRegisterInfo->EnableForWake));
    894  1.1.1.11  christos 
    895  1.1.1.11  christos     EnabledStatusByte = (UINT8) (StatusReg & EnableReg);
    896  1.1.1.11  christos     if (!(EnabledStatusByte & RegisterBit))
    897  1.1.1.11  christos     {
    898  1.1.1.11  christos         goto ErrorExit;
    899  1.1.1.11  christos     }
    900  1.1.1.11  christos 
    901  1.1.1.11  christos     /* Invoke global event handler if present */
    902  1.1.1.11  christos 
    903  1.1.1.11  christos     AcpiGpeCount++;
    904  1.1.1.11  christos     if (AcpiGbl_GlobalEventHandler)
    905  1.1.1.11  christos     {
    906  1.1.1.11  christos         AcpiGbl_GlobalEventHandler (ACPI_EVENT_TYPE_GPE,
    907  1.1.1.11  christos             GpeDevice, GpeNumber,
    908  1.1.1.11  christos             AcpiGbl_GlobalEventHandlerContext);
    909  1.1.1.11  christos     }
    910  1.1.1.11  christos 
    911  1.1.1.11  christos     /* Found an active GPE */
    912  1.1.1.11  christos 
    913  1.1.1.11  christos     if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==
    914  1.1.1.11  christos         ACPI_GPE_DISPATCH_RAW_HANDLER)
    915  1.1.1.11  christos     {
    916  1.1.1.11  christos         /* Dispatch the event to a raw handler */
    917  1.1.1.11  christos 
    918  1.1.1.11  christos         GpeHandlerInfo = GpeEventInfo->Dispatch.Handler;
    919  1.1.1.11  christos 
    920  1.1.1.11  christos         /*
    921  1.1.1.11  christos          * There is no protection around the namespace node
    922  1.1.1.11  christos          * and the GPE handler to ensure a safe destruction
    923  1.1.1.11  christos          * because:
    924  1.1.1.11  christos          * 1. The namespace node is expected to always
    925  1.1.1.11  christos          *    exist after loading a table.
    926  1.1.1.11  christos          * 2. The GPE handler is expected to be flushed by
    927  1.1.1.11  christos          *    AcpiOsWaitEventsComplete() before the
    928  1.1.1.11  christos          *    destruction.
    929  1.1.1.11  christos          */
    930  1.1.1.11  christos         AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
    931  1.1.1.11  christos         IntStatus |= GpeHandlerInfo->Address (
    932  1.1.1.11  christos             GpeDevice, GpeNumber, GpeHandlerInfo->Context);
    933  1.1.1.11  christos         Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
    934  1.1.1.11  christos     }
    935  1.1.1.11  christos     else
    936  1.1.1.11  christos     {
    937  1.1.1.11  christos         /* Dispatch the event to a standard handler or method. */
    938  1.1.1.11  christos 
    939  1.1.1.11  christos         IntStatus |= AcpiEvGpeDispatch (GpeDevice,
    940  1.1.1.11  christos             GpeEventInfo, GpeNumber);
    941  1.1.1.11  christos     }
    942  1.1.1.11  christos 
    943  1.1.1.11  christos ErrorExit:
    944  1.1.1.11  christos     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
    945  1.1.1.11  christos     return (IntStatus);
    946  1.1.1.11  christos }
    947  1.1.1.11  christos 
    948  1.1.1.11  christos 
    949  1.1.1.11  christos /*******************************************************************************
    950  1.1.1.11  christos  *
    951       1.1    jruoho  * FUNCTION:    AcpiEvGpeDispatch
    952       1.1    jruoho  *
    953   1.1.1.2    jruoho  * PARAMETERS:  GpeDevice           - Device node. NULL for GPE0/GPE1
    954   1.1.1.2    jruoho  *              GpeEventInfo        - Info for this GPE
    955   1.1.1.2    jruoho  *              GpeNumber           - Number relative to the parent GPE block
    956       1.1    jruoho  *
    957       1.1    jruoho  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
    958       1.1    jruoho  *
    959       1.1    jruoho  * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC)
    960       1.1    jruoho  *              or method (e.g. _Lxx/_Exx) handler.
    961       1.1    jruoho  *
    962       1.1    jruoho  ******************************************************************************/
    963       1.1    jruoho 
    964       1.1    jruoho UINT32
    965       1.1    jruoho AcpiEvGpeDispatch (
    966   1.1.1.2    jruoho     ACPI_NAMESPACE_NODE     *GpeDevice,
    967       1.1    jruoho     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
    968       1.1    jruoho     UINT32                  GpeNumber)
    969       1.1    jruoho {
    970       1.1    jruoho     ACPI_STATUS             Status;
    971   1.1.1.2    jruoho     UINT32                  ReturnValue;
    972       1.1    jruoho 
    973       1.1    jruoho 
    974       1.1    jruoho     ACPI_FUNCTION_TRACE (EvGpeDispatch);
    975       1.1    jruoho 
    976       1.1    jruoho 
    977       1.1    jruoho     /*
    978   1.1.1.2    jruoho      * Always disable the GPE so that it does not keep firing before
    979   1.1.1.2    jruoho      * any asynchronous activity completes (either from the execution
    980   1.1.1.2    jruoho      * of a GPE method or an asynchronous GPE handler.)
    981   1.1.1.2    jruoho      *
    982   1.1.1.2    jruoho      * If there is no handler or method to run, just disable the
    983   1.1.1.2    jruoho      * GPE and leave it disabled permanently to prevent further such
    984   1.1.1.2    jruoho      * pointless events from firing.
    985   1.1.1.2    jruoho      */
    986   1.1.1.2    jruoho     Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
    987   1.1.1.2    jruoho     if (ACPI_FAILURE (Status))
    988   1.1.1.2    jruoho     {
    989   1.1.1.2    jruoho         ACPI_EXCEPTION ((AE_INFO, Status,
    990   1.1.1.4  christos             "Unable to disable GPE %02X", GpeNumber));
    991   1.1.1.2    jruoho         return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
    992   1.1.1.2    jruoho     }
    993   1.1.1.2    jruoho 
    994   1.1.1.2    jruoho     /*
    995   1.1.1.4  christos      * If edge-triggered, clear the GPE status bit now. Note that
    996   1.1.1.4  christos      * level-triggered events are cleared after the GPE is serviced.
    997   1.1.1.4  christos      */
    998   1.1.1.4  christos     if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
    999   1.1.1.4  christos             ACPI_GPE_EDGE_TRIGGERED)
   1000   1.1.1.4  christos     {
   1001   1.1.1.4  christos         Status = AcpiHwClearGpe (GpeEventInfo);
   1002   1.1.1.4  christos         if (ACPI_FAILURE (Status))
   1003   1.1.1.4  christos         {
   1004   1.1.1.4  christos             ACPI_EXCEPTION ((AE_INFO, Status,
   1005   1.1.1.4  christos                 "Unable to clear GPE %02X", GpeNumber));
   1006   1.1.1.7  christos             (void) AcpiHwLowSetGpe (
   1007   1.1.1.7  christos                 GpeEventInfo, ACPI_GPE_CONDITIONAL_ENABLE);
   1008   1.1.1.4  christos             return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
   1009   1.1.1.4  christos         }
   1010   1.1.1.4  christos     }
   1011   1.1.1.4  christos 
   1012   1.1.1.8  christos     GpeEventInfo->DisableForDispatch = TRUE;
   1013   1.1.1.8  christos 
   1014   1.1.1.4  christos     /*
   1015   1.1.1.2    jruoho      * Dispatch the GPE to either an installed handler or the control
   1016   1.1.1.2    jruoho      * method associated with this GPE (_Lxx or _Exx). If a handler
   1017   1.1.1.2    jruoho      * exists, we invoke it and do not attempt to run the method.
   1018   1.1.1.2    jruoho      * If there is neither a handler nor a method, leave the GPE
   1019   1.1.1.2    jruoho      * disabled.
   1020       1.1    jruoho      */
   1021   1.1.1.5  christos     switch (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags))
   1022       1.1    jruoho     {
   1023       1.1    jruoho     case ACPI_GPE_DISPATCH_HANDLER:
   1024       1.1    jruoho 
   1025   1.1.1.2    jruoho         /* Invoke the installed handler (at interrupt level) */
   1026   1.1.1.2    jruoho 
   1027   1.1.1.2    jruoho         ReturnValue = GpeEventInfo->Dispatch.Handler->Address (
   1028   1.1.1.2    jruoho             GpeDevice, GpeNumber,
   1029   1.1.1.2    jruoho             GpeEventInfo->Dispatch.Handler->Context);
   1030       1.1    jruoho 
   1031  1.1.1.12  christos         /* If requested, clear (if level-triggered) and re-enable the GPE */
   1032       1.1    jruoho 
   1033   1.1.1.2    jruoho         if (ReturnValue & ACPI_REENABLE_GPE)
   1034       1.1    jruoho         {
   1035   1.1.1.2    jruoho             (void) AcpiEvFinishGpe (GpeEventInfo);
   1036       1.1    jruoho         }
   1037       1.1    jruoho         break;
   1038       1.1    jruoho 
   1039       1.1    jruoho     case ACPI_GPE_DISPATCH_METHOD:
   1040   1.1.1.2    jruoho     case ACPI_GPE_DISPATCH_NOTIFY:
   1041       1.1    jruoho         /*
   1042       1.1    jruoho          * Execute the method associated with the GPE
   1043       1.1    jruoho          * NOTE: Level-triggered GPEs are cleared after the method completes.
   1044       1.1    jruoho          */
   1045       1.1    jruoho         Status = AcpiOsExecute (OSL_GPE_HANDLER,
   1046   1.1.1.7  christos             AcpiEvAsynchExecuteGpeMethod, GpeEventInfo);
   1047       1.1    jruoho         if (ACPI_FAILURE (Status))
   1048       1.1    jruoho         {
   1049       1.1    jruoho             ACPI_EXCEPTION ((AE_INFO, Status,
   1050   1.1.1.4  christos                 "Unable to queue handler for GPE %02X - event disabled",
   1051       1.1    jruoho                 GpeNumber));
   1052       1.1    jruoho         }
   1053       1.1    jruoho         break;
   1054       1.1    jruoho 
   1055       1.1    jruoho     default:
   1056       1.1    jruoho         /*
   1057       1.1    jruoho          * No handler or method to run!
   1058       1.1    jruoho          * 03/2010: This case should no longer be possible. We will not allow
   1059       1.1    jruoho          * a GPE to be enabled if it has no handler or method.
   1060       1.1    jruoho          */
   1061       1.1    jruoho         ACPI_ERROR ((AE_INFO,
   1062   1.1.1.4  christos             "No handler or method for GPE %02X, disabling event",
   1063       1.1    jruoho             GpeNumber));
   1064       1.1    jruoho         break;
   1065       1.1    jruoho     }
   1066       1.1    jruoho 
   1067       1.1    jruoho     return_UINT32 (ACPI_INTERRUPT_HANDLED);
   1068       1.1    jruoho }
   1069       1.1    jruoho 
   1070   1.1.1.3  christos #endif /* !ACPI_REDUCED_HARDWARE */
   1071