Subversion Repositories Kolibri OS

Rev

Rev 1498 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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