evgpe.c revision 193249
10SN/A/****************************************************************************** 20SN/A * 30SN/A * Module Name: evgpe - General Purpose Event handling and dispatch 40SN/A * $Revision: 1.68 $ 50SN/A * 62362SN/A *****************************************************************************/ 70SN/A 82362SN/A/****************************************************************************** 90SN/A * 100SN/A * 1. Copyright Notice 110SN/A * 120SN/A * Some or all of this work - Copyright (c) 1999 - 2007, Intel Corp. 130SN/A * All rights reserved. 140SN/A * 150SN/A * 2. License 160SN/A * 170SN/A * 2.1. This is your license from Intel Corp. under its intellectual property 180SN/A * rights. You may have additional license terms from the party that provided 190SN/A * you this software, covering your right to use that party's intellectual 202362SN/A * property rights. 212362SN/A * 222362SN/A * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 230SN/A * copy of the source code appearing in this file ("Covered Code") an 240SN/A * irrevocable, perpetual, worldwide license under Intel's copyrights in the 250SN/A * base code distributed originally by Intel ("Original Intel Code") to copy, 260SN/A * make derivatives, distribute, use and display any portion of the Covered 270SN/A * Code in any form, with the right to sublicense such rights; and 280SN/A * 290SN/A * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 300SN/A * license (with the right to sublicense), under only those claims of Intel 310SN/A * patents that are infringed by the Original Intel Code, to make, use, sell, 320SN/A * offer to sell, and import the Covered Code and derivative works thereof 333984SN/A * solely to the minimum extent necessary to exercise the above copyright 340SN/A * license, and in no event shall the patent license extend to any additions 350SN/A * to or modifications of the Original Intel Code. No other license or right 360SN/A * is granted directly or by implication, estoppel or otherwise; 3712876Sdl * 3815088Sdl * The above copyright and patent license is granted only if the following 3915088Sdl * conditions are met: 404980SN/A * 410SN/A * 3. Conditions 420SN/A * 430SN/A * 3.1. Redistribution of Source with Rights to Further Distribute Source. 440SN/A * Redistribution of source code of any substantial portion of the Covered 450SN/A * Code or modification with rights to further distribute source must include 460SN/A * the above Copyright Notice, the above License, this list of Conditions, 474980SN/A * and the following Disclaimer and Export Compliance provision. In addition, 484980SN/A * Licensee must cause all Covered Code to which Licensee contributes to 490SN/A * contain a file documenting the changes Licensee made to create that Covered 504980SN/A * Code and the date of any change. Licensee must include in that file the 514980SN/A * documentation of any changes made by any predecessor Licensee. Licensee 520SN/A * must include a prominent statement that the modification is derived, 534980SN/A * directly or indirectly, from Original Intel Code. 544980SN/A * 554980SN/A * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 564980SN/A * Redistribution of source code of any substantial portion of the Covered 570SN/A * Code or modification without rights to further distribute source must 580SN/A * include the following Disclaimer and Export Compliance provision in the 594980SN/A * documentation and/or other materials provided with distribution. In 600SN/A * addition, Licensee may not authorize further sublicense of source of any 610SN/A * portion of the Covered Code, and must include terms to the effect that the 620SN/A * license from Licensee to its licensee is limited to the intellectual 630SN/A * property embodied in the software Licensee provides to its licensee, and 644980SN/A * not to intellectual property embodied in modifications its licensee may 650SN/A * make. 660SN/A * 674980SN/A * 3.3. Redistribution of Executable. Redistribution in executable form of any 684980SN/A * substantial portion of the Covered Code or modification must reproduce the 694980SN/A * above Copyright Notice, and the following Disclaimer and Export Compliance 704980SN/A * provision in the documentation and/or other materials provided with the 714980SN/A * distribution. 724980SN/A * 734980SN/A * 3.4. Intel retains all right, title, and interest in and to the Original 744980SN/A * Intel Code. 750SN/A * 760SN/A * 3.5. Neither the name Intel nor any other trademark owned or controlled by 774980SN/A * Intel shall be used in advertising or otherwise to promote the sale, use or 784980SN/A * other dealings in products derived from or relating to the Covered Code 794980SN/A * without prior written authorization from Intel. 804980SN/A * 814980SN/A * 4. Disclaimer and Export Compliance 824980SN/A * 834980SN/A * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 844980SN/A * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 854980SN/A * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 864980SN/A * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 874980SN/A * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 884980SN/A * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 894980SN/A * PARTICULAR PURPOSE. 904980SN/A * 914980SN/A * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 924980SN/A * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 934980SN/A * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 944980SN/A * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 954980SN/A * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 964980SN/A * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 974980SN/A * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 984980SN/A * LIMITED REMEDY. 994980SN/A * 1004980SN/A * 4.3. Licensee shall not export, either directly or indirectly, any of this 1014980SN/A * software or system incorporating such software without first obtaining any 1024980SN/A * required license or other approval from the U. S. Department of Commerce or 1034980SN/A * any other agency or department of the United States Government. In the 1044980SN/A * event Licensee exports any such software from the United States or 1054980SN/A * re-exports any such software from a foreign destination, Licensee shall 1064980SN/A * ensure that the distribution and export/re-export of the software is in 1074980SN/A * compliance with all laws, regulations, orders, or other restrictions of the 1084980SN/A * U.S. Export Administration Regulations. Licensee agrees that neither it nor 1094980SN/A * any of its subsidiaries will export/re-export any technical data, process, 1104980SN/A * software, or service, directly or indirectly, to any country for which the 1114980SN/A * United States government or any agency thereof requires an export license, 1124980SN/A * other governmental approval, or letter of assurance, without first obtaining 1134980SN/A * such license, approval or letter. 1144980SN/A * 1154980SN/A *****************************************************************************/ 1164980SN/A 1174980SN/A#include <contrib/dev/acpica/acpi.h> 1184980SN/A#include <contrib/dev/acpica/acevents.h> 1194980SN/A#include <contrib/dev/acpica/acnamesp.h> 1204980SN/A 1214980SN/A#define _COMPONENT ACPI_EVENTS 1224980SN/A ACPI_MODULE_NAME ("evgpe") 1234980SN/A 1244980SN/A/* Local prototypes */ 1254980SN/A 1264980SN/Astatic void 1274980SN/AAcpiEvAsynchEnableGpe ( 1280SN/A void *Context); 1290SN/A 1304980SN/Astatic void ACPI_SYSTEM_XFACE 1310SN/AAcpiEvAsynchExecuteGpeMethod ( 1320SN/A void *Context); 1330SN/A 1340SN/A 1354980SN/A/******************************************************************************* 1364980SN/A * 1370SN/A * FUNCTION: AcpiEvSetGpeType 1380SN/A * 1390SN/A * PARAMETERS: GpeEventInfo - GPE to set 1404980SN/A * Type - New type 1414980SN/A * 1420SN/A * RETURN: Status 1430SN/A * 1440SN/A * DESCRIPTION: Sets the new type for the GPE (wake, run, or wake/run) 1450SN/A * 1460SN/A ******************************************************************************/ 1470SN/A 1483203SN/AACPI_STATUS 1494980SN/AAcpiEvSetGpeType ( 1500SN/A ACPI_GPE_EVENT_INFO *GpeEventInfo, 1510SN/A UINT8 Type) 1524980SN/A{ 1534980SN/A ACPI_STATUS Status; 1540SN/A 1550SN/A 1560SN/A ACPI_FUNCTION_TRACE (EvSetGpeType); 1574980SN/A 1580SN/A 1590SN/A /* Validate type and update register enable masks */ 1600SN/A 1614980SN/A switch (Type) 1620SN/A { 1630SN/A case ACPI_GPE_TYPE_WAKE: 1640SN/A case ACPI_GPE_TYPE_RUNTIME: 16515088Sdl case ACPI_GPE_TYPE_WAKE_RUN: 16615088Sdl break; 1674980SN/A 1687646SN/A default: 1697646SN/A return_ACPI_STATUS (AE_BAD_PARAMETER); 1707646SN/A } 1717646SN/A 1727646SN/A /* Disable the GPE if currently enabled */ 1737646SN/A 1747646SN/A Status = AcpiEvDisableGpe (GpeEventInfo); 17515088Sdl 1767646SN/A /* Type was validated above */ 1777646SN/A 1787646SN/A GpeEventInfo->Flags &= ~ACPI_GPE_TYPE_MASK; /* Clear type bits */ 1797646SN/A GpeEventInfo->Flags |= Type; /* Insert type */ 1804980SN/A return_ACPI_STATUS (Status); 1814980SN/A} 1820SN/A 1830SN/A 1840SN/A/******************************************************************************* 1850SN/A * 1860SN/A * FUNCTION: AcpiEvUpdateGpeEnableMasks 1870SN/A * 1884980SN/A * PARAMETERS: GpeEventInfo - GPE to update 1894980SN/A * Type - What to do: ACPI_GPE_DISABLE or 1904980SN/A * ACPI_GPE_ENABLE 1914980SN/A * 1920SN/A * RETURN: Status 1930SN/A * 1940SN/A * DESCRIPTION: Updates GPE register enable masks based on the GPE type 1950SN/A * 1960SN/A ******************************************************************************/ 1970SN/A 1980SN/AACPI_STATUS 1994980SN/AAcpiEvUpdateGpeEnableMasks ( 2004980SN/A ACPI_GPE_EVENT_INFO *GpeEventInfo, 2014980SN/A UINT8 Type) 2024980SN/A{ 2034980SN/A ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 2044980SN/A UINT8 RegisterBit; 2054980SN/A 2060SN/A 2070SN/A ACPI_FUNCTION_TRACE (EvUpdateGpeEnableMasks); 2080SN/A 2090SN/A 2104980SN/A GpeRegisterInfo = GpeEventInfo->RegisterInfo; 2110SN/A if (!GpeRegisterInfo) 2120SN/A { 2130SN/A return_ACPI_STATUS (AE_NOT_EXIST); 2140SN/A } 2150SN/A RegisterBit = (UINT8) 2160SN/A (1 << (GpeEventInfo->GpeNumber - GpeRegisterInfo->BaseGpeNumber)); 2170SN/A 2180SN/A /* 1) Disable case. Simply clear all enable bits */ 2190SN/A 2204980SN/A if (Type == ACPI_GPE_DISABLE) 2210SN/A { 2224980SN/A ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, RegisterBit); 2234980SN/A ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit); 2240SN/A return_ACPI_STATUS (AE_OK); 2254980SN/A } 2260SN/A 2270SN/A /* 2) Enable case. Set/Clear the appropriate enable bits */ 2280SN/A 22915088Sdl switch (GpeEventInfo->Flags & ACPI_GPE_TYPE_MASK) 2304980SN/A { 23115088Sdl case ACPI_GPE_TYPE_WAKE: 2324980SN/A ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, RegisterBit); 2334980SN/A ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit); 2340SN/A break; 2350SN/A 2360SN/A case ACPI_GPE_TYPE_RUNTIME: 2374980SN/A ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, RegisterBit); 2384980SN/A ACPI_SET_BIT (GpeRegisterInfo->EnableForRun, RegisterBit); 2390SN/A break; 2404980SN/A 2414980SN/A case ACPI_GPE_TYPE_WAKE_RUN: 2420SN/A ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, RegisterBit); 2434980SN/A ACPI_SET_BIT (GpeRegisterInfo->EnableForRun, RegisterBit); 2440SN/A break; 2450SN/A 2460SN/A default: 24715088Sdl return_ACPI_STATUS (AE_BAD_PARAMETER); 2484980SN/A } 24915088Sdl 2504980SN/A return_ACPI_STATUS (AE_OK); 2514980SN/A} 2520SN/A 2530SN/A 2540SN/A/******************************************************************************* 2554980SN/A * 25615088Sdl * FUNCTION: AcpiEvEnableGpe 2574980SN/A * 2584980SN/A * PARAMETERS: GpeEventInfo - GPE to enable 2594980SN/A * WriteToHardware - Enable now, or just mark data structs 2604980SN/A * (WAKE GPEs should be deferred) 2614980SN/A * 2624980SN/A * RETURN: Status 2634980SN/A * 2644980SN/A * DESCRIPTION: Enable a GPE based on the GPE type 2654980SN/A * 2664980SN/A ******************************************************************************/ 2674980SN/A 2684980SN/AACPI_STATUS 2694980SN/AAcpiEvEnableGpe ( 2704980SN/A ACPI_GPE_EVENT_INFO *GpeEventInfo, 2714980SN/A BOOLEAN WriteToHardware) 2724980SN/A{ 2734980SN/A ACPI_STATUS Status; 2744980SN/A 2754980SN/A 2764980SN/A ACPI_FUNCTION_TRACE (EvEnableGpe); 2774980SN/A 2784980SN/A 2794980SN/A /* Make sure HW enable masks are updated */ 2804980SN/A 2814980SN/A Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo, ACPI_GPE_ENABLE); 2824980SN/A if (ACPI_FAILURE (Status)) 2834980SN/A { 2840SN/A return_ACPI_STATUS (Status); 2850SN/A } 2860SN/A 2870SN/A /* Mark wake-enabled or HW enable, or both */ 2884980SN/A 2890SN/A switch (GpeEventInfo->Flags & ACPI_GPE_TYPE_MASK) 2900SN/A { 2910SN/A case ACPI_GPE_TYPE_WAKE: 2924980SN/A 2937646SN/A ACPI_SET_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED); 2940SN/A break; 2950SN/A 2964980SN/A case ACPI_GPE_TYPE_WAKE_RUN: 29715088Sdl 2984980SN/A ACPI_SET_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED); 2994980SN/A 3004980SN/A /*lint -fallthrough */ 3014980SN/A 3024980SN/A case ACPI_GPE_TYPE_RUNTIME: 3034980SN/A 3044980SN/A ACPI_SET_BIT (GpeEventInfo->Flags, ACPI_GPE_RUN_ENABLED); 3054980SN/A 3064980SN/A if (WriteToHardware) 3074980SN/A { 3084980SN/A /* Clear the GPE (of stale events), then enable it */ 3094980SN/A 3104980SN/A Status = AcpiHwClearGpe (GpeEventInfo); 3114980SN/A if (ACPI_FAILURE (Status)) 3124980SN/A { 3134980SN/A return_ACPI_STATUS (Status); 3144980SN/A } 3154980SN/A 3164980SN/A /* Enable the requested runtime GPE */ 3174980SN/A 3184980SN/A Status = AcpiHwWriteGpeEnableReg (GpeEventInfo); 3194980SN/A } 3204980SN/A break; 3214980SN/A 3224980SN/A default: 3234980SN/A return_ACPI_STATUS (AE_BAD_PARAMETER); 3244980SN/A } 3254980SN/A 3264980SN/A return_ACPI_STATUS (AE_OK); 3274980SN/A} 3284980SN/A 3294980SN/A 3304980SN/A/******************************************************************************* 3314980SN/A * 3324980SN/A * FUNCTION: AcpiEvDisableGpe 3334980SN/A * 3344980SN/A * PARAMETERS: GpeEventInfo - GPE to disable 3354980SN/A * 3364980SN/A * RETURN: Status 3374980SN/A * 3384980SN/A * DESCRIPTION: Disable a GPE based on the GPE type 3394980SN/A * 3404980SN/A ******************************************************************************/ 3414980SN/A 3424980SN/AACPI_STATUS 3434980SN/AAcpiEvDisableGpe ( 3444980SN/A ACPI_GPE_EVENT_INFO *GpeEventInfo) 3454980SN/A{ 3464980SN/A ACPI_STATUS Status; 3474980SN/A 3484980SN/A 3494980SN/A ACPI_FUNCTION_TRACE (EvDisableGpe); 3504980SN/A 3514980SN/A 3524980SN/A if (!(GpeEventInfo->Flags & ACPI_GPE_ENABLE_MASK)) 3534980SN/A { 3544980SN/A return_ACPI_STATUS (AE_OK); 3550SN/A } 3560SN/A 3570SN/A /* Make sure HW enable masks are updated */ 3584980SN/A 3594980SN/A Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo, ACPI_GPE_DISABLE); 3600SN/A if (ACPI_FAILURE (Status)) 3614980SN/A { 3624980SN/A return_ACPI_STATUS (Status); 3634980SN/A } 36415541Spsandoz 3654980SN/A /* Mark wake-disabled or HW disable, or both */ 3664980SN/A 3674980SN/A switch (GpeEventInfo->Flags & ACPI_GPE_TYPE_MASK) 3684980SN/A { 3694980SN/A case ACPI_GPE_TYPE_WAKE: 3704980SN/A ACPI_CLEAR_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED); 3714980SN/A break; 3724980SN/A 3734980SN/A case ACPI_GPE_TYPE_WAKE_RUN: 3744980SN/A ACPI_CLEAR_BIT (GpeEventInfo->Flags, ACPI_GPE_WAKE_ENABLED); 3754980SN/A 3760SN/A /*lint -fallthrough */ 3774980SN/A 3780SN/A case ACPI_GPE_TYPE_RUNTIME: 3790SN/A 3800SN/A /* Disable the requested runtime GPE */ 3814980SN/A 3824980SN/A ACPI_CLEAR_BIT (GpeEventInfo->Flags, ACPI_GPE_RUN_ENABLED); 3834980SN/A Status = AcpiHwWriteGpeEnableReg (GpeEventInfo); 3844980SN/A break; 3854980SN/A 3864980SN/A default: 3874980SN/A return_ACPI_STATUS (AE_BAD_PARAMETER); 3884980SN/A } 3894980SN/A 3904980SN/A return_ACPI_STATUS (AE_OK); 39110786Schegar} 3924980SN/A 3934980SN/A 3944980SN/A/******************************************************************************* 39510786Schegar * 39610786Schegar * FUNCTION: AcpiEvGetGpeEventInfo 39712876Sdl * 39810786Schegar * PARAMETERS: GpeDevice - Device node. NULL for GPE0/GPE1 39910786Schegar * GpeNumber - Raw GPE number 40010786Schegar * 40110786Schegar * RETURN: A GPE EventInfo struct. NULL if not a valid GPE 40210786Schegar * 4034980SN/A * DESCRIPTION: Returns the EventInfo struct associated with this GPE. 4044980SN/A * Validates the GpeBlock and the GpeNumber 4054980SN/A * 4064980SN/A * Should be called only when the GPE lists are semaphore locked 4074980SN/A * and not subject to change. 4084980SN/A * 4094980SN/A ******************************************************************************/ 4104980SN/A 4110SN/AACPI_GPE_EVENT_INFO * 41212876SdlAcpiEvGetGpeEventInfo ( 41312876Sdl ACPI_HANDLE GpeDevice, 41412876Sdl UINT32 GpeNumber) 4154980SN/A{ 41612876Sdl ACPI_OPERAND_OBJECT *ObjDesc; 41712876Sdl ACPI_GPE_BLOCK_INFO *GpeBlock; 41812876Sdl ACPI_NATIVE_UINT i; 41912876Sdl 42010786Schegar 42110786Schegar ACPI_FUNCTION_ENTRY (); 42210786Schegar 4234980SN/A 42410786Schegar /* A NULL GpeBlock means use the FADT-defined GPE block(s) */ 4254980SN/A 42615541Spsandoz if (!GpeDevice) 4274980SN/A { 42810786Schegar /* Examine GPE Block 0 and 1 (These blocks are permanent) */ 42910786Schegar 43010786Schegar for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++) 43110786Schegar { 43210786Schegar GpeBlock = AcpiGbl_GpeFadtBlocks[i]; 43310786Schegar if (GpeBlock) 43410786Schegar { 43510786Schegar if ((GpeNumber >= GpeBlock->BlockBaseNumber) && 43610786Schegar (GpeNumber < GpeBlock->BlockBaseNumber + 43710786Schegar (GpeBlock->RegisterCount * 8))) 43810786Schegar { 43910786Schegar return (&GpeBlock->EventInfo[GpeNumber - 44010786Schegar GpeBlock->BlockBaseNumber]); 4410SN/A } 44212876Sdl } 44312876Sdl } 44412876Sdl 4450SN/A /* The GpeNumber was not in the range of either FADT GPE block */ 4464980SN/A 4474980SN/A return (NULL); 4480SN/A } 4494980SN/A 4500SN/A /* A Non-NULL GpeDevice means this is a GPE Block Device */ 4514980SN/A 4524980SN/A ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) GpeDevice); 4534980SN/A if (!ObjDesc || 4544980SN/A !ObjDesc->Device.GpeBlock) 4554980SN/A { 4564980SN/A return (NULL); 4574980SN/A } 4584980SN/A 4594980SN/A GpeBlock = ObjDesc->Device.GpeBlock; 4604980SN/A 4614980SN/A if ((GpeNumber >= GpeBlock->BlockBaseNumber) && 4624980SN/A (GpeNumber < GpeBlock->BlockBaseNumber + (GpeBlock->RegisterCount * 8))) 4634980SN/A { 4644980SN/A return (&GpeBlock->EventInfo[GpeNumber - GpeBlock->BlockBaseNumber]); 4654980SN/A } 4664980SN/A 4674980SN/A return (NULL); 4684980SN/A} 4694980SN/A 4704980SN/A 4714980SN/A/******************************************************************************* 4724980SN/A * 4734980SN/A * FUNCTION: AcpiEvGpeDetect 4744980SN/A * 47515088Sdl * PARAMETERS: GpeXruptList - Interrupt block for this interrupt. 4764980SN/A * Can have multiple GPE blocks attached. 4774980SN/A * 4784980SN/A * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED 4790SN/A * 4800SN/A * DESCRIPTION: Detect if any GP events have occurred. This function is 4810SN/A * executed at interrupt level. 4824980SN/A * 48315088Sdl ******************************************************************************/ 48415088Sdl 48515088SdlUINT32 48615088SdlAcpiEvGpeDetect ( 4874980SN/A ACPI_GPE_XRUPT_INFO *GpeXruptList) 4884980SN/A{ 48915088Sdl ACPI_STATUS Status; 49015088Sdl ACPI_GPE_BLOCK_INFO *GpeBlock; 49115088Sdl ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 49215088Sdl UINT32 IntStatus = ACPI_INTERRUPT_NOT_HANDLED; 49312876Sdl UINT8 EnabledStatusByte; 4944980SN/A UINT32 StatusReg; 4954980SN/A UINT32 EnableReg; 49612876Sdl ACPI_CPU_FLAGS Flags; 49712876Sdl ACPI_NATIVE_UINT i; 49812876Sdl ACPI_NATIVE_UINT j; 49912876Sdl 5004980SN/A 5014980SN/A ACPI_FUNCTION_NAME (EvGpeDetect); 5020SN/A 503 /* Check for the case where there are no GPEs */ 504 505 if (!GpeXruptList) 506 { 507 return (IntStatus); 508 } 509 510 /* 511 * We need to obtain the GPE lock for both the data structs and registers 512 * Note: Not necessary to obtain the hardware lock, since the GPE registers 513 * are owned by the GpeLock. 514 */ 515 Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 516 517 /* Examine all GPE blocks attached to this interrupt level */ 518 519 GpeBlock = GpeXruptList->GpeBlockListHead; 520 while (GpeBlock) 521 { 522 /* 523 * Read all of the 8-bit GPE status and enable registers 524 * in this GPE block, saving all of them. 525 * Find all currently active GP events. 526 */ 527 for (i = 0; i < GpeBlock->RegisterCount; i++) 528 { 529 /* Get the next status/enable pair */ 530 531 GpeRegisterInfo = &GpeBlock->RegisterInfo[i]; 532 533 /* Read the Status Register */ 534 535 Status = AcpiHwLowLevelRead (ACPI_GPE_REGISTER_WIDTH, &StatusReg, 536 &GpeRegisterInfo->StatusAddress); 537 if (ACPI_FAILURE (Status)) 538 { 539 goto UnlockAndExit; 540 } 541 542 /* Read the Enable Register */ 543 544 Status = AcpiHwLowLevelRead (ACPI_GPE_REGISTER_WIDTH, &EnableReg, 545 &GpeRegisterInfo->EnableAddress); 546 if (ACPI_FAILURE (Status)) 547 { 548 goto UnlockAndExit; 549 } 550 551 ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, 552 "Read GPE Register at GPE%X: Status=%02X, Enable=%02X\n", 553 GpeRegisterInfo->BaseGpeNumber, StatusReg, EnableReg)); 554 555 /* Check if there is anything active at all in this register */ 556 557 EnabledStatusByte = (UINT8) (StatusReg & EnableReg); 558 if (!EnabledStatusByte) 559 { 560 /* No active GPEs in this register, move on */ 561 562 continue; 563 } 564 565 /* Now look at the individual GPEs in this byte register */ 566 567 for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) 568 { 569 /* Examine one GPE bit */ 570 571 if (EnabledStatusByte & (1 << j)) 572 { 573 /* 574 * Found an active GPE. Dispatch the event to a handler 575 * or method. 576 */ 577 IntStatus |= AcpiEvGpeDispatch ( 578 &GpeBlock->EventInfo[(i * ACPI_GPE_REGISTER_WIDTH) + j], 579 (UINT32) j + GpeRegisterInfo->BaseGpeNumber); 580 } 581 } 582 } 583 584 GpeBlock = GpeBlock->Next; 585 } 586 587UnlockAndExit: 588 589 AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 590 return (IntStatus); 591} 592 593 594/******************************************************************************* 595 * 596 * FUNCTION: AcpiEvAsynchExecuteGpeMethod 597 * 598 * PARAMETERS: Context (GpeEventInfo) - Info for this GPE 599 * 600 * RETURN: None 601 * 602 * DESCRIPTION: Perform the actual execution of a GPE control method. This 603 * function is called from an invocation of AcpiOsExecute and 604 * therefore does NOT execute at interrupt level - so that 605 * the control method itself is not executed in the context of 606 * an interrupt handler. 607 * 608 ******************************************************************************/ 609 610static void ACPI_SYSTEM_XFACE 611AcpiEvAsynchExecuteGpeMethod ( 612 void *Context) 613{ 614 ACPI_GPE_EVENT_INFO *GpeEventInfo = (void *) Context; 615 ACPI_STATUS Status; 616 ACPI_GPE_EVENT_INFO LocalGpeEventInfo; 617 ACPI_EVALUATE_INFO *Info; 618 619 620 ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod); 621 622 623 Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 624 if (ACPI_FAILURE (Status)) 625 { 626 return_VOID; 627 } 628 629 /* Must revalidate the GpeNumber/GpeBlock */ 630 631 if (!AcpiEvValidGpeEvent (GpeEventInfo)) 632 { 633 Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 634 return_VOID; 635 } 636 637 /* Set the GPE flags for return to enabled state */ 638 639 (void) AcpiEvEnableGpe (GpeEventInfo, FALSE); 640 641 /* 642 * Take a snapshot of the GPE info for this level - we copy the 643 * info to prevent a race condition with RemoveHandler/RemoveBlock. 644 */ 645 ACPI_MEMCPY (&LocalGpeEventInfo, GpeEventInfo, 646 sizeof (ACPI_GPE_EVENT_INFO)); 647 648 Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 649 if (ACPI_FAILURE (Status)) 650 { 651 return_VOID; 652 } 653 654 /* 655 * Must check for control method type dispatch one more 656 * time to avoid race with EvGpeInstallHandler 657 */ 658 if ((LocalGpeEventInfo.Flags & ACPI_GPE_DISPATCH_MASK) == 659 ACPI_GPE_DISPATCH_METHOD) 660 { 661 /* Allocate the evaluation information block */ 662 663 Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); 664 if (!Info) 665 { 666 Status = AE_NO_MEMORY; 667 } 668 else 669 { 670 /* 671 * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx 672 * control method that corresponds to this GPE 673 */ 674 Info->PrefixNode = LocalGpeEventInfo.Dispatch.MethodNode; 675 Info->Parameters = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT *, GpeEventInfo); 676 Info->ParameterType = ACPI_PARAM_GPE; 677 Info->Flags = ACPI_IGNORE_RETURN_VALUE; 678 679 Status = AcpiNsEvaluate (Info); 680 ACPI_FREE (Info); 681 } 682 683 if (ACPI_FAILURE (Status)) 684 { 685 ACPI_EXCEPTION ((AE_INFO, Status, 686 "while evaluating GPE method [%4.4s]", 687 AcpiUtGetNodeName (LocalGpeEventInfo.Dispatch.MethodNode))); 688 } 689 } 690 691 /* Defer enabling of GPE until all notify handlers are done */ 692 AcpiOsExecute(OSL_NOTIFY_HANDLER, AcpiEvAsynchEnableGpe, GpeEventInfo); 693 return_VOID; 694} 695 696static void 697AcpiEvAsynchEnableGpe ( 698 void *Context) 699{ 700 ACPI_GPE_EVENT_INFO *GpeEventInfo = (void *) Context; 701 ACPI_STATUS Status; 702 703 if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) == 704 ACPI_GPE_LEVEL_TRIGGERED) 705 { 706 /* 707 * GPE is level-triggered, we clear the GPE status bit after 708 * handling the event. 709 */ 710 Status = AcpiHwClearGpe (GpeEventInfo); 711 if (ACPI_FAILURE (Status)) 712 { 713 return_VOID; 714 } 715 } 716 717 /* Enable this GPE */ 718 719 (void) AcpiHwWriteGpeEnableReg (GpeEventInfo); 720 return_VOID; 721} 722 723 724/******************************************************************************* 725 * 726 * FUNCTION: AcpiEvGpeDispatch 727 * 728 * PARAMETERS: GpeEventInfo - Info for this GPE 729 * GpeNumber - Number relative to the parent GPE block 730 * 731 * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED 732 * 733 * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC) 734 * or method (e.g. _Lxx/_Exx) handler. 735 * 736 * This function executes at interrupt level. 737 * 738 ******************************************************************************/ 739 740UINT32 741AcpiEvGpeDispatch ( 742 ACPI_GPE_EVENT_INFO *GpeEventInfo, 743 UINT32 GpeNumber) 744{ 745 ACPI_STATUS Status; 746 747 748 ACPI_FUNCTION_TRACE (EvGpeDispatch); 749 750 751 AcpiGpeCount++; 752 753 /* 754 * If edge-triggered, clear the GPE status bit now. Note that 755 * level-triggered events are cleared after the GPE is serviced. 756 */ 757 if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) == 758 ACPI_GPE_EDGE_TRIGGERED) 759 { 760 Status = AcpiHwClearGpe (GpeEventInfo); 761 if (ACPI_FAILURE (Status)) 762 { 763 ACPI_EXCEPTION ((AE_INFO, Status, 764 "Unable to clear GPE[%2X]", GpeNumber)); 765 return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); 766 } 767 } 768 769 if (!AcpiGbl_SystemAwakeAndRunning) 770 { 771 /* 772 * We just woke up because of a wake GPE. Disable any further GPEs 773 * until we are fully up and running (Only wake GPEs should be enabled 774 * at this time, but we just brute-force disable them all.) 775 * 1) We must disable this particular wake GPE so it won't fire again 776 * 2) We want to disable all wake GPEs, since we are now awake 777 */ 778 (void) AcpiHwDisableAllGpes (); 779 } 780 781 /* 782 * Dispatch the GPE to either an installed handler, or the control method 783 * associated with this GPE (_Lxx or _Exx). If a handler exists, we invoke 784 * it and do not attempt to run the method. If there is neither a handler 785 * nor a method, we disable this GPE to prevent further such pointless 786 * events from firing. 787 */ 788 switch (GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) 789 { 790 case ACPI_GPE_DISPATCH_HANDLER: 791 792 /* 793 * Invoke the installed handler (at interrupt level) 794 * Ignore return status for now. TBD: leave GPE disabled on error? 795 */ 796 (void) GpeEventInfo->Dispatch.Handler->Address ( 797 GpeEventInfo->Dispatch.Handler->Context); 798 799 /* It is now safe to clear level-triggered events. */ 800 801 if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) == 802 ACPI_GPE_LEVEL_TRIGGERED) 803 { 804 Status = AcpiHwClearGpe (GpeEventInfo); 805 if (ACPI_FAILURE (Status)) 806 { 807 ACPI_EXCEPTION ((AE_INFO, Status, 808 "Unable to clear GPE[%2X]", GpeNumber)); 809 return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); 810 } 811 } 812 break; 813 814 case ACPI_GPE_DISPATCH_METHOD: 815 816 /* 817 * Disable the GPE, so it doesn't keep firing before the method has a 818 * chance to run (it runs asynchronously with interrupts enabled). 819 */ 820 Status = AcpiEvDisableGpe (GpeEventInfo); 821 if (ACPI_FAILURE (Status)) 822 { 823 ACPI_EXCEPTION ((AE_INFO, Status, 824 "Unable to disable GPE[%2X]", GpeNumber)); 825 return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); 826 } 827 828 /* 829 * Execute the method associated with the GPE 830 * NOTE: Level-triggered GPEs are cleared after the method completes. 831 */ 832 Status = AcpiOsExecute (OSL_GPE_HANDLER, 833 AcpiEvAsynchExecuteGpeMethod, GpeEventInfo); 834 if (ACPI_FAILURE (Status)) 835 { 836 ACPI_EXCEPTION ((AE_INFO, Status, 837 "Unable to queue handler for GPE[%2X] - event disabled", 838 GpeNumber)); 839 } 840 break; 841 842 default: 843 844 /* No handler or method to run! */ 845 846 ACPI_ERROR ((AE_INFO, 847 "No handler or method for GPE[%2X], disabling event", 848 GpeNumber)); 849 850 /* 851 * Disable the GPE. The GPE will remain disabled until the ACPI 852 * Core Subsystem is restarted, or a handler is installed. 853 */ 854 Status = AcpiEvDisableGpe (GpeEventInfo); 855 if (ACPI_FAILURE (Status)) 856 { 857 ACPI_EXCEPTION ((AE_INFO, Status, 858 "Unable to disable GPE[%2X]", GpeNumber)); 859 return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); 860 } 861 break; 862 } 863 864 return_UINT32 (ACPI_INTERRUPT_HANDLED); 865} 866 867