Subversion Repositories Kolibri OS

Rev

Go to most recent revision | 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 - 2010, 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:    AcpiEvUpdateGpeEnableMasks
  138.  *
  139.  * PARAMETERS:  GpeEventInfo            - GPE to update
  140.  *
  141.  * RETURN:      Status
  142.  *
  143.  * DESCRIPTION: Updates GPE register enable masks based upon whether there are
  144.  *              references (either wake or run) to this GPE
  145.  *
  146.  ******************************************************************************/
  147.  
  148. ACPI_STATUS
  149. AcpiEvUpdateGpeEnableMasks (
  150.     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
  151. {
  152.     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
  153.     UINT8                   RegisterBit;
  154.  
  155.  
  156.     ACPI_FUNCTION_TRACE (EvUpdateGpeEnableMasks);
  157.  
  158.  
  159.     GpeRegisterInfo = GpeEventInfo->RegisterInfo;
  160.     if (!GpeRegisterInfo)
  161.     {
  162.         return_ACPI_STATUS (AE_NOT_EXIST);
  163.     }
  164.  
  165.     RegisterBit = (UINT8)
  166.         (1 << (GpeEventInfo->GpeNumber - GpeRegisterInfo->BaseGpeNumber));
  167.  
  168.     /* Clear the wake/run bits up front */
  169.  
  170.     ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, RegisterBit);
  171.     ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
  172.  
  173.     /* Set the mask bits only if there are references to this GPE */
  174.  
  175.     if (GpeEventInfo->RuntimeCount)
  176.     {
  177.         ACPI_SET_BIT (GpeRegisterInfo->EnableForRun, RegisterBit);
  178.     }
  179.  
  180.     if (GpeEventInfo->WakeupCount)
  181.     {
  182.         ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, RegisterBit);
  183.     }
  184.  
  185.     return_ACPI_STATUS (AE_OK);
  186. }
  187.  
  188.  
  189. /*******************************************************************************
  190.  *
  191.  * FUNCTION:    AcpiEvEnableGpe
  192.  *
  193.  * PARAMETERS:  GpeEventInfo            - GPE to enable
  194.  *
  195.  * RETURN:      Status
  196.  *
  197.  * DESCRIPTION: Hardware-enable a GPE. Always enables the GPE, regardless
  198.  *              of type or number of references.
  199.  *
  200.  * Note: The GPE lock should be already acquired when this function is called.
  201.  *
  202.  ******************************************************************************/
  203.  
  204. ACPI_STATUS
  205. AcpiEvEnableGpe (
  206.     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
  207. {
  208.     ACPI_STATUS             Status;
  209.  
  210.  
  211.     ACPI_FUNCTION_TRACE (EvEnableGpe);
  212.  
  213.  
  214.     /*
  215.      * We will only allow a GPE to be enabled if it has either an
  216.      * associated method (_Lxx/_Exx) or a handler. Otherwise, the
  217.      * GPE will be immediately disabled by AcpiEvGpeDispatch the
  218.      * first time it fires.
  219.      */
  220.     if (!(GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK))
  221.     {
  222.         return_ACPI_STATUS (AE_NO_HANDLER);
  223.     }
  224.  
  225.     /* Ensure the HW enable masks are current */
  226.  
  227.     Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo);
  228.     if (ACPI_FAILURE (Status))
  229.     {
  230.         return_ACPI_STATUS (Status);
  231.     }
  232.  
  233.     /* Clear the GPE (of stale events) */
  234.  
  235.     Status = AcpiHwClearGpe (GpeEventInfo);
  236.     if (ACPI_FAILURE (Status))
  237.     {
  238.         return_ACPI_STATUS (Status);
  239.     }
  240.  
  241.     /* Enable the requested GPE */
  242.  
  243.     Status = AcpiHwWriteGpeEnableReg (GpeEventInfo);
  244.     return_ACPI_STATUS (Status);
  245. }
  246.  
  247.  
  248. /*******************************************************************************
  249.  *
  250.  * FUNCTION:    AcpiEvDisableGpe
  251.  *
  252.  * PARAMETERS:  GpeEventInfo            - GPE to disable
  253.  *
  254.  * RETURN:      Status
  255.  *
  256.  * DESCRIPTION: Hardware-disable a GPE. Always disables the requested GPE,
  257.  *              regardless of the type or number of references.
  258.  *
  259.  * Note: The GPE lock should be already acquired when this function is called.
  260.  *
  261.  ******************************************************************************/
  262.  
  263. ACPI_STATUS
  264. AcpiEvDisableGpe (
  265.     ACPI_GPE_EVENT_INFO     *GpeEventInfo)
  266. {
  267.     ACPI_STATUS             Status;
  268.  
  269.  
  270.     ACPI_FUNCTION_TRACE (EvDisableGpe);
  271.  
  272.  
  273.     /*
  274.      * Note: Always disable the GPE, even if we think that that it is already
  275.      * disabled. It is possible that the AML or some other code has enabled
  276.      * the GPE behind our back.
  277.      */
  278.  
  279.     /* Ensure the HW enable masks are current */
  280.  
  281.     Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo);
  282.     if (ACPI_FAILURE (Status))
  283.     {
  284.         return_ACPI_STATUS (Status);
  285.     }
  286.  
  287.     /*
  288.      * Always H/W disable this GPE, even if we don't know the GPE type.
  289.      * Simply clear the enable bit for this particular GPE, but do not
  290.      * write out the current GPE enable mask since this may inadvertently
  291.      * enable GPEs too early. An example is a rogue GPE that has arrived
  292.      * during ACPICA initialization - possibly because AML or other code
  293.      * has enabled the GPE.
  294.      */
  295.     Status = AcpiHwLowDisableGpe (GpeEventInfo);
  296.     return_ACPI_STATUS (Status);
  297. }
  298.  
  299.  
  300. /*******************************************************************************
  301.  *
  302.  * FUNCTION:    AcpiEvLowGetGpeInfo
  303.  *
  304.  * PARAMETERS:  GpeNumber           - Raw GPE number
  305.  *              GpeBlock            - A GPE info block
  306.  *
  307.  * RETURN:      A GPE EventInfo struct. NULL if not a valid GPE (The GpeNumber
  308.  *              is not within the specified GPE block)
  309.  *
  310.  * DESCRIPTION: Returns the EventInfo struct associated with this GPE. This is
  311.  *              the low-level implementation of EvGetGpeEventInfo.
  312.  *
  313.  ******************************************************************************/
  314.  
  315. ACPI_GPE_EVENT_INFO *
  316. AcpiEvLowGetGpeInfo (
  317.     UINT32                  GpeNumber,
  318.     ACPI_GPE_BLOCK_INFO     *GpeBlock)
  319. {
  320.     UINT32                  GpeIndex;
  321.  
  322.  
  323.     /*
  324.      * Validate that the GpeNumber is within the specified GpeBlock.
  325.      * (Two steps)
  326.      */
  327.     if (!GpeBlock ||
  328.         (GpeNumber < GpeBlock->BlockBaseNumber))
  329.     {
  330.         return (NULL);
  331.     }
  332.  
  333.     GpeIndex = GpeNumber - GpeBlock->BlockBaseNumber;
  334.     if (GpeIndex >= GpeBlock->GpeCount)
  335.     {
  336.         return (NULL);
  337.     }
  338.  
  339.     return (&GpeBlock->EventInfo[GpeIndex]);
  340. }
  341.  
  342.  
  343. /*******************************************************************************
  344.  *
  345.  * FUNCTION:    AcpiEvGetGpeEventInfo
  346.  *
  347.  * PARAMETERS:  GpeDevice           - Device node. NULL for GPE0/GPE1
  348.  *              GpeNumber           - Raw GPE number
  349.  *
  350.  * RETURN:      A GPE EventInfo struct. NULL if not a valid GPE
  351.  *
  352.  * DESCRIPTION: Returns the EventInfo struct associated with this GPE.
  353.  *              Validates the GpeBlock and the GpeNumber
  354.  *
  355.  *              Should be called only when the GPE lists are semaphore locked
  356.  *              and not subject to change.
  357.  *
  358.  ******************************************************************************/
  359.  
  360. ACPI_GPE_EVENT_INFO *
  361. AcpiEvGetGpeEventInfo (
  362.     ACPI_HANDLE             GpeDevice,
  363.     UINT32                  GpeNumber)
  364. {
  365.     ACPI_OPERAND_OBJECT     *ObjDesc;
  366.     ACPI_GPE_EVENT_INFO     *GpeInfo;
  367.     UINT32                  i;
  368.  
  369.  
  370.     ACPI_FUNCTION_ENTRY ();
  371.  
  372.  
  373.     /* A NULL GpeDevice means use the FADT-defined GPE block(s) */
  374.  
  375.     if (!GpeDevice)
  376.     {
  377.         /* Examine GPE Block 0 and 1 (These blocks are permanent) */
  378.  
  379.         for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++)
  380.         {
  381.             GpeInfo = AcpiEvLowGetGpeInfo (GpeNumber,
  382.                         AcpiGbl_GpeFadtBlocks[i]);
  383.             if (GpeInfo)
  384.             {
  385.                 return (GpeInfo);
  386.             }
  387.         }
  388.  
  389.         /* The GpeNumber was not in the range of either FADT GPE block */
  390.  
  391.         return (NULL);
  392.     }
  393.  
  394.     /* A Non-NULL GpeDevice means this is a GPE Block Device */
  395.  
  396.     ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) GpeDevice);
  397.     if (!ObjDesc ||
  398.         !ObjDesc->Device.GpeBlock)
  399.     {
  400.         return (NULL);
  401.     }
  402.  
  403.     return (AcpiEvLowGetGpeInfo (GpeNumber, ObjDesc->Device.GpeBlock));
  404. }
  405.  
  406.  
  407. /*******************************************************************************
  408.  *
  409.  * FUNCTION:    AcpiEvGpeDetect
  410.  *
  411.  * PARAMETERS:  GpeXruptList        - Interrupt block for this interrupt.
  412.  *                                    Can have multiple GPE blocks attached.
  413.  *
  414.  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
  415.  *
  416.  * DESCRIPTION: Detect if any GP events have occurred. This function is
  417.  *              executed at interrupt level.
  418.  *
  419.  ******************************************************************************/
  420.  
  421. UINT32
  422. AcpiEvGpeDetect (
  423.     ACPI_GPE_XRUPT_INFO     *GpeXruptList)
  424. {
  425.     ACPI_STATUS             Status;
  426.     ACPI_GPE_BLOCK_INFO     *GpeBlock;
  427.     ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo;
  428.     UINT32                  IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
  429.     UINT8                   EnabledStatusByte;
  430.     UINT32                  StatusReg;
  431.     UINT32                  EnableReg;
  432.     ACPI_CPU_FLAGS          Flags;
  433.     UINT32                  i;
  434.     UINT32                  j;
  435.  
  436.  
  437.     ACPI_FUNCTION_NAME (EvGpeDetect);
  438.  
  439.     /* Check for the case where there are no GPEs */
  440.  
  441.     if (!GpeXruptList)
  442.     {
  443.         return (IntStatus);
  444.     }
  445.  
  446.     /*
  447.      * We need to obtain the GPE lock for both the data structs and registers
  448.      * Note: Not necessary to obtain the hardware lock, since the GPE
  449.      * registers are owned by the GpeLock.
  450.      */
  451.     Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
  452.  
  453.     /* Examine all GPE blocks attached to this interrupt level */
  454.  
  455.     GpeBlock = GpeXruptList->GpeBlockListHead;
  456.     while (GpeBlock)
  457.     {
  458.         /*
  459.          * Read all of the 8-bit GPE status and enable registers in this GPE
  460.          * block, saving all of them. Find all currently active GP events.
  461.          */
  462.         for (i = 0; i < GpeBlock->RegisterCount; i++)
  463.         {
  464.             /* Get the next status/enable pair */
  465.  
  466.             GpeRegisterInfo = &GpeBlock->RegisterInfo[i];
  467.  
  468.             /* Read the Status Register */
  469.  
  470.             Status = AcpiHwRead (&StatusReg, &GpeRegisterInfo->StatusAddress);
  471.             if (ACPI_FAILURE (Status))
  472.             {
  473.                 goto UnlockAndExit;
  474.             }
  475.  
  476.             /* Read the Enable Register */
  477.  
  478.             Status = AcpiHwRead (&EnableReg, &GpeRegisterInfo->EnableAddress);
  479.             if (ACPI_FAILURE (Status))
  480.             {
  481.                 goto UnlockAndExit;
  482.             }
  483.  
  484.             ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
  485.                 "Read GPE Register at GPE%X: Status=%02X, Enable=%02X\n",
  486.                 GpeRegisterInfo->BaseGpeNumber, StatusReg, EnableReg));
  487.  
  488.             /* Check if there is anything active at all in this register */
  489.  
  490.             EnabledStatusByte = (UINT8) (StatusReg & EnableReg);
  491.             if (!EnabledStatusByte)
  492.             {
  493.                 /* No active GPEs in this register, move on */
  494.  
  495.                 continue;
  496.             }
  497.  
  498.             /* Now look at the individual GPEs in this byte register */
  499.  
  500.             for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
  501.             {
  502.                 /* Examine one GPE bit */
  503.  
  504.                 if (EnabledStatusByte & (1 << j))
  505.                 {
  506.                     /*
  507.                      * Found an active GPE. Dispatch the event to a handler
  508.                      * or method.
  509.                      */
  510.                     IntStatus |= AcpiEvGpeDispatch (
  511.                         &GpeBlock->EventInfo[((ACPI_SIZE) i *
  512.                             ACPI_GPE_REGISTER_WIDTH) + j],
  513.                         j + GpeRegisterInfo->BaseGpeNumber);
  514.                 }
  515.             }
  516.         }
  517.  
  518.         GpeBlock = GpeBlock->Next;
  519.     }
  520.  
  521. UnlockAndExit:
  522.  
  523.     AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
  524.     return (IntStatus);
  525. }
  526.  
  527.  
  528. /*******************************************************************************
  529.  *
  530.  * FUNCTION:    AcpiEvAsynchExecuteGpeMethod
  531.  *
  532.  * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
  533.  *
  534.  * RETURN:      None
  535.  *
  536.  * DESCRIPTION: Perform the actual execution of a GPE control method. This
  537.  *              function is called from an invocation of AcpiOsExecute and
  538.  *              therefore does NOT execute at interrupt level - so that
  539.  *              the control method itself is not executed in the context of
  540.  *              an interrupt handler.
  541.  *
  542.  ******************************************************************************/
  543.  
  544. static void ACPI_SYSTEM_XFACE
  545. AcpiEvAsynchExecuteGpeMethod (
  546.     void                    *Context)
  547. {
  548.     ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
  549.     ACPI_STATUS             Status;
  550.     ACPI_GPE_EVENT_INFO     *LocalGpeEventInfo;
  551.     ACPI_EVALUATE_INFO      *Info;
  552.  
  553.  
  554.     ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod);
  555.  
  556.  
  557.     /* Allocate a local GPE block */
  558.  
  559.     LocalGpeEventInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_EVENT_INFO));
  560.     if (!LocalGpeEventInfo)
  561.     {
  562.         ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY,
  563.             "while handling a GPE"));
  564.         return_VOID;
  565.     }
  566.  
  567.     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
  568.     if (ACPI_FAILURE (Status))
  569.     {
  570.         return_VOID;
  571.     }
  572.  
  573.     /* Must revalidate the GpeNumber/GpeBlock */
  574.  
  575.     if (!AcpiEvValidGpeEvent (GpeEventInfo))
  576.     {
  577.         Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
  578.         return_VOID;
  579.     }
  580.  
  581.     /* Update the GPE register masks for return to enabled state */
  582.  
  583.     (void) AcpiEvUpdateGpeEnableMasks (GpeEventInfo);
  584.  
  585.     /*
  586.      * Take a snapshot of the GPE info for this level - we copy the info to
  587.      * prevent a race condition with RemoveHandler/RemoveBlock.
  588.      */
  589.     ACPI_MEMCPY (LocalGpeEventInfo, GpeEventInfo,
  590.         sizeof (ACPI_GPE_EVENT_INFO));
  591.  
  592.     Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
  593.     if (ACPI_FAILURE (Status))
  594.     {
  595.         return_VOID;
  596.     }
  597.  
  598.     /*
  599.      * Must check for control method type dispatch one more time to avoid a
  600.      * race with EvGpeInstallHandler
  601.      */
  602.     if ((LocalGpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
  603.             ACPI_GPE_DISPATCH_METHOD)
  604.     {
  605.         /* Allocate the evaluation information block */
  606.  
  607.         Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
  608.         if (!Info)
  609.         {
  610.             Status = AE_NO_MEMORY;
  611.         }
  612.         else
  613.         {
  614.             /*
  615.              * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx
  616.              * control method that corresponds to this GPE
  617.              */
  618.             Info->PrefixNode = LocalGpeEventInfo->Dispatch.MethodNode;
  619.             Info->Flags = ACPI_IGNORE_RETURN_VALUE;
  620.  
  621.             Status = AcpiNsEvaluate (Info);
  622.             ACPI_FREE (Info);
  623.         }
  624.  
  625.         if (ACPI_FAILURE (Status))
  626.         {
  627.             ACPI_EXCEPTION ((AE_INFO, Status,
  628.                 "while evaluating GPE method [%4.4s]",
  629.                 AcpiUtGetNodeName (LocalGpeEventInfo->Dispatch.MethodNode)));
  630.         }
  631.     }
  632.  
  633.     /* Defer enabling of GPE until all notify handlers are done */
  634.  
  635.     Status = AcpiOsExecute (OSL_NOTIFY_HANDLER,
  636.                 AcpiEvAsynchEnableGpe, LocalGpeEventInfo);
  637.     if (ACPI_FAILURE (Status))
  638.     {
  639.         ACPI_FREE (LocalGpeEventInfo);
  640.     }
  641.     return_VOID;
  642. }
  643.  
  644.  
  645. /*******************************************************************************
  646.  *
  647.  * FUNCTION:    AcpiEvAsynchEnableGpe
  648.  *
  649.  * PARAMETERS:  Context (GpeEventInfo) - Info for this GPE
  650.  *
  651.  * RETURN:      None
  652.  *
  653.  * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to
  654.  *              complete (i.e., finish execution of Notify)
  655.  *
  656.  ******************************************************************************/
  657.  
  658. static void ACPI_SYSTEM_XFACE
  659. AcpiEvAsynchEnableGpe (
  660.     void                    *Context)
  661. {
  662.     ACPI_GPE_EVENT_INFO     *GpeEventInfo = Context;
  663.     ACPI_STATUS             Status;
  664.  
  665.  
  666.     if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
  667.             ACPI_GPE_LEVEL_TRIGGERED)
  668.     {
  669.         /*
  670.          * GPE is level-triggered, we clear the GPE status bit after handling
  671.          * the event.
  672.          */
  673.         Status = AcpiHwClearGpe (GpeEventInfo);
  674.         if (ACPI_FAILURE (Status))
  675.         {
  676.             goto Exit;
  677.         }
  678.     }
  679.  
  680.     /* Enable this GPE */
  681.  
  682.     (void) AcpiHwWriteGpeEnableReg (GpeEventInfo);
  683.  
  684. Exit:
  685.     ACPI_FREE (GpeEventInfo);
  686.     return;
  687. }
  688.  
  689.  
  690. /*******************************************************************************
  691.  *
  692.  * FUNCTION:    AcpiEvGpeDispatch
  693.  *
  694.  * PARAMETERS:  GpeEventInfo    - Info for this GPE
  695.  *              GpeNumber       - Number relative to the parent GPE block
  696.  *
  697.  * RETURN:      INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
  698.  *
  699.  * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC)
  700.  *              or method (e.g. _Lxx/_Exx) handler.
  701.  *
  702.  *              This function executes at interrupt level.
  703.  *
  704.  ******************************************************************************/
  705.  
  706. UINT32
  707. AcpiEvGpeDispatch (
  708.     ACPI_GPE_EVENT_INFO     *GpeEventInfo,
  709.     UINT32                  GpeNumber)
  710. {
  711.     ACPI_STATUS             Status;
  712.  
  713.  
  714.     ACPI_FUNCTION_TRACE (EvGpeDispatch);
  715.  
  716.  
  717.     AcpiGpeCount++;
  718.  
  719.     /*
  720.      * If edge-triggered, clear the GPE status bit now. Note that
  721.      * level-triggered events are cleared after the GPE is serviced.
  722.      */
  723.     if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
  724.             ACPI_GPE_EDGE_TRIGGERED)
  725.     {
  726.         Status = AcpiHwClearGpe (GpeEventInfo);
  727.         if (ACPI_FAILURE (Status))
  728.         {
  729.             ACPI_EXCEPTION ((AE_INFO, Status,
  730.                 "Unable to clear GPE[0x%2X]", GpeNumber));
  731.             return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
  732.         }
  733.     }
  734.  
  735.     /*
  736.      * Dispatch the GPE to either an installed handler, or the control method
  737.      * associated with this GPE (_Lxx or _Exx). If a handler exists, we invoke
  738.      * it and do not attempt to run the method. If there is neither a handler
  739.      * nor a method, we disable this GPE to prevent further such pointless
  740.      * events from firing.
  741.      */
  742.     switch (GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK)
  743.     {
  744.     case ACPI_GPE_DISPATCH_HANDLER:
  745.  
  746.         /*
  747.          * Invoke the installed handler (at interrupt level)
  748.          * Ignore return status for now.
  749.          * TBD: leave GPE disabled on error?
  750.          */
  751.         (void) GpeEventInfo->Dispatch.Handler->Address (
  752.                         GpeEventInfo->Dispatch.Handler->Context);
  753.  
  754.         /* It is now safe to clear level-triggered events. */
  755.  
  756.         if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
  757.                 ACPI_GPE_LEVEL_TRIGGERED)
  758.         {
  759.             Status = AcpiHwClearGpe (GpeEventInfo);
  760.             if (ACPI_FAILURE (Status))
  761.             {
  762.                 ACPI_EXCEPTION ((AE_INFO, Status,
  763.                     "Unable to clear GPE[0x%2X]", GpeNumber));
  764.                 return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
  765.             }
  766.         }
  767.         break;
  768.  
  769.     case ACPI_GPE_DISPATCH_METHOD:
  770.  
  771.         /*
  772.          * Disable the GPE, so it doesn't keep firing before the method has a
  773.          * chance to run (it runs asynchronously with interrupts enabled).
  774.          */
  775.         Status = AcpiEvDisableGpe (GpeEventInfo);
  776.         if (ACPI_FAILURE (Status))
  777.         {
  778.             ACPI_EXCEPTION ((AE_INFO, Status,
  779.                 "Unable to disable GPE[0x%2X]", GpeNumber));
  780.             return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
  781.         }
  782.  
  783.         /*
  784.          * Execute the method associated with the GPE
  785.          * NOTE: Level-triggered GPEs are cleared after the method completes.
  786.          */
  787.         Status = AcpiOsExecute (OSL_GPE_HANDLER,
  788.                     AcpiEvAsynchExecuteGpeMethod, GpeEventInfo);
  789.         if (ACPI_FAILURE (Status))
  790.         {
  791.             ACPI_EXCEPTION ((AE_INFO, Status,
  792.                 "Unable to queue handler for GPE[0x%2X] - event disabled",
  793.                 GpeNumber));
  794.         }
  795.         break;
  796.  
  797.     default:
  798.  
  799.         /*
  800.          * No handler or method to run!
  801.          * 03/2010: This case should no longer be possible. We will not allow
  802.          * a GPE to be enabled if it has no handler or method.
  803.          */
  804.         ACPI_ERROR ((AE_INFO,
  805.             "No handler or method for GPE[0x%2X], disabling event",
  806.             GpeNumber));
  807.  
  808.         /*
  809.          * Disable the GPE. The GPE will remain disabled a handler
  810.          * is installed or ACPICA is restarted.
  811.          */
  812.         Status = AcpiEvDisableGpe (GpeEventInfo);
  813.         if (ACPI_FAILURE (Status))
  814.         {
  815.             ACPI_EXCEPTION ((AE_INFO, Status,
  816.                 "Unable to disable GPE[0x%2X]", GpeNumber));
  817.             return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
  818.         }
  819.         break;
  820.     }
  821.  
  822.     return_UINT32 (ACPI_INTERRUPT_HANDLED);
  823. }
  824.  
  825.