evgpe.c revision 206117
1114239Snjl/****************************************************************************** 2114239Snjl * 3114239Snjl * Module Name: evgpe - General Purpose Event handling and dispatch 4114239Snjl * 5114239Snjl *****************************************************************************/ 6114239Snjl 7114239Snjl/****************************************************************************** 8114239Snjl * 9114239Snjl * 1. Copyright Notice 10114239Snjl * 11202771Sjkim * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. 12114239Snjl * All rights reserved. 13114239Snjl * 14114239Snjl * 2. License 15114239Snjl * 16114239Snjl * 2.1. This is your license from Intel Corp. under its intellectual property 17114239Snjl * rights. You may have additional license terms from the party that provided 18114239Snjl * you this software, covering your right to use that party's intellectual 19114239Snjl * property rights. 20114239Snjl * 21114239Snjl * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 22114239Snjl * copy of the source code appearing in this file ("Covered Code") an 23114239Snjl * irrevocable, perpetual, worldwide license under Intel's copyrights in the 24114239Snjl * base code distributed originally by Intel ("Original Intel Code") to copy, 25114239Snjl * make derivatives, distribute, use and display any portion of the Covered 26114239Snjl * Code in any form, with the right to sublicense such rights; and 27114239Snjl * 28114239Snjl * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 29114239Snjl * license (with the right to sublicense), under only those claims of Intel 30114239Snjl * patents that are infringed by the Original Intel Code, to make, use, sell, 31114239Snjl * offer to sell, and import the Covered Code and derivative works thereof 32114239Snjl * solely to the minimum extent necessary to exercise the above copyright 33114239Snjl * license, and in no event shall the patent license extend to any additions 34114239Snjl * to or modifications of the Original Intel Code. No other license or right 35114239Snjl * is granted directly or by implication, estoppel or otherwise; 36114239Snjl * 37114239Snjl * The above copyright and patent license is granted only if the following 38114239Snjl * conditions are met: 39114239Snjl * 40114239Snjl * 3. Conditions 41114239Snjl * 42114239Snjl * 3.1. Redistribution of Source with Rights to Further Distribute Source. 43114239Snjl * Redistribution of source code of any substantial portion of the Covered 44114239Snjl * Code or modification with rights to further distribute source must include 45114239Snjl * the above Copyright Notice, the above License, this list of Conditions, 46114239Snjl * and the following Disclaimer and Export Compliance provision. In addition, 47114239Snjl * Licensee must cause all Covered Code to which Licensee contributes to 48114239Snjl * contain a file documenting the changes Licensee made to create that Covered 49114239Snjl * Code and the date of any change. Licensee must include in that file the 50114239Snjl * documentation of any changes made by any predecessor Licensee. Licensee 51114239Snjl * must include a prominent statement that the modification is derived, 52114239Snjl * directly or indirectly, from Original Intel Code. 53114239Snjl * 54114239Snjl * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 55114239Snjl * Redistribution of source code of any substantial portion of the Covered 56114239Snjl * Code or modification without rights to further distribute source must 57114239Snjl * include the following Disclaimer and Export Compliance provision in the 58114239Snjl * documentation and/or other materials provided with distribution. In 59114239Snjl * addition, Licensee may not authorize further sublicense of source of any 60114239Snjl * portion of the Covered Code, and must include terms to the effect that the 61114239Snjl * license from Licensee to its licensee is limited to the intellectual 62114239Snjl * property embodied in the software Licensee provides to its licensee, and 63114239Snjl * not to intellectual property embodied in modifications its licensee may 64114239Snjl * make. 65114239Snjl * 66114239Snjl * 3.3. Redistribution of Executable. Redistribution in executable form of any 67114239Snjl * substantial portion of the Covered Code or modification must reproduce the 68114239Snjl * above Copyright Notice, and the following Disclaimer and Export Compliance 69114239Snjl * provision in the documentation and/or other materials provided with the 70114239Snjl * distribution. 71114239Snjl * 72114239Snjl * 3.4. Intel retains all right, title, and interest in and to the Original 73114239Snjl * Intel Code. 74114239Snjl * 75114239Snjl * 3.5. Neither the name Intel nor any other trademark owned or controlled by 76114239Snjl * Intel shall be used in advertising or otherwise to promote the sale, use or 77114239Snjl * other dealings in products derived from or relating to the Covered Code 78114239Snjl * without prior written authorization from Intel. 79114239Snjl * 80114239Snjl * 4. Disclaimer and Export Compliance 81114239Snjl * 82114239Snjl * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 83114239Snjl * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 84114239Snjl * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 85114239Snjl * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 86114239Snjl * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 87114239Snjl * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 88114239Snjl * PARTICULAR PURPOSE. 89114239Snjl * 90114239Snjl * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 91114239Snjl * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 92114239Snjl * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 93114239Snjl * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 94114239Snjl * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 95114239Snjl * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 96114239Snjl * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 97114239Snjl * LIMITED REMEDY. 98114239Snjl * 99114239Snjl * 4.3. Licensee shall not export, either directly or indirectly, any of this 100114239Snjl * software or system incorporating such software without first obtaining any 101114239Snjl * required license or other approval from the U. S. Department of Commerce or 102114239Snjl * any other agency or department of the United States Government. In the 103114239Snjl * event Licensee exports any such software from the United States or 104114239Snjl * re-exports any such software from a foreign destination, Licensee shall 105114239Snjl * ensure that the distribution and export/re-export of the software is in 106114239Snjl * compliance with all laws, regulations, orders, or other restrictions of the 107114239Snjl * U.S. Export Administration Regulations. Licensee agrees that neither it nor 108114239Snjl * any of its subsidiaries will export/re-export any technical data, process, 109114239Snjl * software, or service, directly or indirectly, to any country for which the 110114239Snjl * United States government or any agency thereof requires an export license, 111114239Snjl * other governmental approval, or letter of assurance, without first obtaining 112114239Snjl * such license, approval or letter. 113114239Snjl * 114114239Snjl *****************************************************************************/ 115114239Snjl 116193341Sjkim#include <contrib/dev/acpica/include/acpi.h> 117193341Sjkim#include <contrib/dev/acpica/include/accommon.h> 118193341Sjkim#include <contrib/dev/acpica/include/acevents.h> 119193341Sjkim#include <contrib/dev/acpica/include/acnamesp.h> 120114239Snjl 121114239Snjl#define _COMPONENT ACPI_EVENTS 122114239Snjl ACPI_MODULE_NAME ("evgpe") 123114239Snjl 124151937Sjkim/* Local prototypes */ 125114239Snjl 126193267Sjkimstatic void ACPI_SYSTEM_XFACE 127193267SjkimAcpiEvAsynchExecuteGpeMethod ( 128175256Snjl void *Context); 129175256Snjl 130151937Sjkimstatic void ACPI_SYSTEM_XFACE 131193267SjkimAcpiEvAsynchEnableGpe ( 132151937Sjkim void *Context); 133151937Sjkim 134151937Sjkim 135114239Snjl/******************************************************************************* 136114239Snjl * 137129684Snjl * FUNCTION: AcpiEvUpdateGpeEnableMasks 138129684Snjl * 139129684Snjl * PARAMETERS: GpeEventInfo - GPE to update 140129684Snjl * 141129684Snjl * RETURN: Status 142129684Snjl * 143206117Sjkim * DESCRIPTION: Updates GPE register enable masks based upon whether there are 144206117Sjkim * references (either wake or run) to this GPE 145129684Snjl * 146129684Snjl ******************************************************************************/ 147129684Snjl 148129684SnjlACPI_STATUS 149129684SnjlAcpiEvUpdateGpeEnableMasks ( 150206117Sjkim ACPI_GPE_EVENT_INFO *GpeEventInfo) 151129684Snjl{ 152129684Snjl ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 153129684Snjl UINT8 RegisterBit; 154129684Snjl 155129684Snjl 156167802Sjkim ACPI_FUNCTION_TRACE (EvUpdateGpeEnableMasks); 157129684Snjl 158129684Snjl 159129684Snjl GpeRegisterInfo = GpeEventInfo->RegisterInfo; 160129684Snjl if (!GpeRegisterInfo) 161129684Snjl { 162129684Snjl return_ACPI_STATUS (AE_NOT_EXIST); 163129684Snjl } 164193267Sjkim 165167802Sjkim RegisterBit = (UINT8) 166167802Sjkim (1 << (GpeEventInfo->GpeNumber - GpeRegisterInfo->BaseGpeNumber)); 167129684Snjl 168206117Sjkim /* Clear the wake/run bits up front */ 169129684Snjl 170206117Sjkim ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, RegisterBit); 171206117Sjkim ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit); 172206117Sjkim 173206117Sjkim /* Set the mask bits only if there are references to this GPE */ 174206117Sjkim 175206117Sjkim if (GpeEventInfo->RuntimeCount) 176129684Snjl { 177206117Sjkim ACPI_SET_BIT (GpeRegisterInfo->EnableForRun, RegisterBit); 178129684Snjl } 179129684Snjl 180206117Sjkim if (GpeEventInfo->WakeupCount) 181129684Snjl { 182206117Sjkim ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, RegisterBit); 183129684Snjl } 184129684Snjl 185129684Snjl return_ACPI_STATUS (AE_OK); 186129684Snjl} 187129684Snjl 188129684Snjl 189129684Snjl/******************************************************************************* 190129684Snjl * 191129684Snjl * FUNCTION: AcpiEvEnableGpe 192129684Snjl * 193129684Snjl * PARAMETERS: GpeEventInfo - GPE to enable 194129684Snjl * 195129684Snjl * RETURN: Status 196129684Snjl * 197206117Sjkim * DESCRIPTION: Hardware-enable a GPE. Always enables the GPE, regardless 198206117Sjkim * of type or number of references. 199129684Snjl * 200206117Sjkim * Note: The GPE lock should be already acquired when this function is called. 201206117Sjkim * 202129684Snjl ******************************************************************************/ 203129684Snjl 204129684SnjlACPI_STATUS 205129684SnjlAcpiEvEnableGpe ( 206206117Sjkim ACPI_GPE_EVENT_INFO *GpeEventInfo) 207129684Snjl{ 208129684Snjl ACPI_STATUS Status; 209129684Snjl 210129684Snjl 211167802Sjkim ACPI_FUNCTION_TRACE (EvEnableGpe); 212129684Snjl 213129684Snjl 214206117Sjkim /* 215206117Sjkim * We will only allow a GPE to be enabled if it has either an 216206117Sjkim * associated method (_Lxx/_Exx) or a handler. Otherwise, the 217206117Sjkim * GPE will be immediately disabled by AcpiEvGpeDispatch the 218206117Sjkim * first time it fires. 219206117Sjkim */ 220206117Sjkim if (!(GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK)) 221206117Sjkim { 222206117Sjkim return_ACPI_STATUS (AE_NO_HANDLER); 223206117Sjkim } 224129684Snjl 225206117Sjkim /* Ensure the HW enable masks are current */ 226206117Sjkim 227206117Sjkim Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo); 228129684Snjl if (ACPI_FAILURE (Status)) 229129684Snjl { 230129684Snjl return_ACPI_STATUS (Status); 231129684Snjl } 232129684Snjl 233206117Sjkim /* Clear the GPE (of stale events) */ 234129684Snjl 235206117Sjkim Status = AcpiHwClearGpe (GpeEventInfo); 236206117Sjkim if (ACPI_FAILURE (Status)) 237129684Snjl { 238206117Sjkim return_ACPI_STATUS (Status); 239206117Sjkim } 240131440Smarks 241206117Sjkim /* Enable the requested GPE */ 242129684Snjl 243206117Sjkim Status = AcpiHwWriteGpeEnableReg (GpeEventInfo); 244206117Sjkim return_ACPI_STATUS (Status); 245129684Snjl} 246129684Snjl 247129684Snjl 248129684Snjl/******************************************************************************* 249129684Snjl * 250129684Snjl * FUNCTION: AcpiEvDisableGpe 251129684Snjl * 252129684Snjl * PARAMETERS: GpeEventInfo - GPE to disable 253129684Snjl * 254129684Snjl * RETURN: Status 255129684Snjl * 256206117Sjkim * DESCRIPTION: Hardware-disable a GPE. Always disables the requested GPE, 257206117Sjkim * regardless of the type or number of references. 258129684Snjl * 259206117Sjkim * Note: The GPE lock should be already acquired when this function is called. 260206117Sjkim * 261129684Snjl ******************************************************************************/ 262129684Snjl 263129684SnjlACPI_STATUS 264129684SnjlAcpiEvDisableGpe ( 265129684Snjl ACPI_GPE_EVENT_INFO *GpeEventInfo) 266129684Snjl{ 267129684Snjl ACPI_STATUS Status; 268129684Snjl 269129684Snjl 270167802Sjkim ACPI_FUNCTION_TRACE (EvDisableGpe); 271129684Snjl 272129684Snjl 273193267Sjkim /* 274193267Sjkim * Note: Always disable the GPE, even if we think that that it is already 275193267Sjkim * disabled. It is possible that the AML or some other code has enabled 276193267Sjkim * the GPE behind our back. 277193267Sjkim */ 278129684Snjl 279206117Sjkim /* Ensure the HW enable masks are current */ 280129684Snjl 281206117Sjkim Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo); 282129684Snjl if (ACPI_FAILURE (Status)) 283129684Snjl { 284129684Snjl return_ACPI_STATUS (Status); 285129684Snjl } 286129684Snjl 287193267Sjkim /* 288193267Sjkim * Always H/W disable this GPE, even if we don't know the GPE type. 289193267Sjkim * Simply clear the enable bit for this particular GPE, but do not 290193267Sjkim * write out the current GPE enable mask since this may inadvertently 291193267Sjkim * enable GPEs too early. An example is a rogue GPE that has arrived 292193267Sjkim * during ACPICA initialization - possibly because AML or other code 293193267Sjkim * has enabled the GPE. 294193267Sjkim */ 295193267Sjkim Status = AcpiHwLowDisableGpe (GpeEventInfo); 296193267Sjkim return_ACPI_STATUS (Status); 297129684Snjl} 298129684Snjl 299129684Snjl 300129684Snjl/******************************************************************************* 301129684Snjl * 302206117Sjkim * FUNCTION: AcpiEvLowGetGpeInfo 303206117Sjkim * 304206117Sjkim * PARAMETERS: GpeNumber - Raw GPE number 305206117Sjkim * GpeBlock - A GPE info block 306206117Sjkim * 307206117Sjkim * RETURN: A GPE EventInfo struct. NULL if not a valid GPE (The GpeNumber 308206117Sjkim * is not within the specified GPE block) 309206117Sjkim * 310206117Sjkim * DESCRIPTION: Returns the EventInfo struct associated with this GPE. This is 311206117Sjkim * the low-level implementation of EvGetGpeEventInfo. 312206117Sjkim * 313206117Sjkim ******************************************************************************/ 314206117Sjkim 315206117SjkimACPI_GPE_EVENT_INFO * 316206117SjkimAcpiEvLowGetGpeInfo ( 317206117Sjkim UINT32 GpeNumber, 318206117Sjkim ACPI_GPE_BLOCK_INFO *GpeBlock) 319206117Sjkim{ 320206117Sjkim UINT32 GpeIndex; 321206117Sjkim 322206117Sjkim 323206117Sjkim /* 324206117Sjkim * Validate that the GpeNumber is within the specified GpeBlock. 325206117Sjkim * (Two steps) 326206117Sjkim */ 327206117Sjkim if (!GpeBlock || 328206117Sjkim (GpeNumber < GpeBlock->BlockBaseNumber)) 329206117Sjkim { 330206117Sjkim return (NULL); 331206117Sjkim } 332206117Sjkim 333206117Sjkim GpeIndex = GpeNumber - GpeBlock->BlockBaseNumber; 334206117Sjkim if (GpeIndex >= GpeBlock->GpeCount) 335206117Sjkim { 336206117Sjkim return (NULL); 337206117Sjkim } 338206117Sjkim 339206117Sjkim return (&GpeBlock->EventInfo[GpeIndex]); 340206117Sjkim} 341206117Sjkim 342206117Sjkim 343206117Sjkim/******************************************************************************* 344206117Sjkim * 345114239Snjl * FUNCTION: AcpiEvGetGpeEventInfo 346114239Snjl * 347193267Sjkim * PARAMETERS: GpeDevice - Device node. NULL for GPE0/GPE1 348117521Snjl * GpeNumber - Raw GPE number 349114239Snjl * 350193267Sjkim * RETURN: A GPE EventInfo struct. NULL if not a valid GPE 351114239Snjl * 352117521Snjl * DESCRIPTION: Returns the EventInfo struct associated with this GPE. 353117521Snjl * Validates the GpeBlock and the GpeNumber 354114239Snjl * 355117521Snjl * Should be called only when the GPE lists are semaphore locked 356117521Snjl * and not subject to change. 357114239Snjl * 358114239Snjl ******************************************************************************/ 359114239Snjl 360114239SnjlACPI_GPE_EVENT_INFO * 361114239SnjlAcpiEvGetGpeEventInfo ( 362117521Snjl ACPI_HANDLE GpeDevice, 363114239Snjl UINT32 GpeNumber) 364114239Snjl{ 365117521Snjl ACPI_OPERAND_OBJECT *ObjDesc; 366206117Sjkim ACPI_GPE_EVENT_INFO *GpeInfo; 367193267Sjkim UINT32 i; 368114239Snjl 369114239Snjl 370117521Snjl ACPI_FUNCTION_ENTRY (); 371114239Snjl 372117521Snjl 373117521Snjl /* A NULL GpeBlock means use the FADT-defined GPE block(s) */ 374117521Snjl 375117521Snjl if (!GpeDevice) 376114239Snjl { 377117521Snjl /* Examine GPE Block 0 and 1 (These blocks are permanent) */ 378117521Snjl 379117521Snjl for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++) 380117521Snjl { 381206117Sjkim GpeInfo = AcpiEvLowGetGpeInfo (GpeNumber, 382206117Sjkim AcpiGbl_GpeFadtBlocks[i]); 383206117Sjkim if (GpeInfo) 384117521Snjl { 385206117Sjkim return (GpeInfo); 386117521Snjl } 387117521Snjl } 388117521Snjl 389117521Snjl /* The GpeNumber was not in the range of either FADT GPE block */ 390117521Snjl 391114239Snjl return (NULL); 392114239Snjl } 393114239Snjl 394128212Snjl /* A Non-NULL GpeDevice means this is a GPE Block Device */ 395128212Snjl 396117521Snjl ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) GpeDevice); 397117521Snjl if (!ObjDesc || 398117521Snjl !ObjDesc->Device.GpeBlock) 399114239Snjl { 400117521Snjl return (NULL); 401114239Snjl } 402114239Snjl 403206117Sjkim return (AcpiEvLowGetGpeInfo (GpeNumber, ObjDesc->Device.GpeBlock)); 404114239Snjl} 405114239Snjl 406117521Snjl 407114239Snjl/******************************************************************************* 408114239Snjl * 409114239Snjl * FUNCTION: AcpiEvGpeDetect 410114239Snjl * 411117521Snjl * PARAMETERS: GpeXruptList - Interrupt block for this interrupt. 412117521Snjl * Can have multiple GPE blocks attached. 413114239Snjl * 414114239Snjl * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED 415114239Snjl * 416193267Sjkim * DESCRIPTION: Detect if any GP events have occurred. This function is 417114239Snjl * executed at interrupt level. 418114239Snjl * 419114239Snjl ******************************************************************************/ 420114239Snjl 421114239SnjlUINT32 422117521SnjlAcpiEvGpeDetect ( 423117521Snjl ACPI_GPE_XRUPT_INFO *GpeXruptList) 424114239Snjl{ 425151937Sjkim ACPI_STATUS Status; 426151937Sjkim ACPI_GPE_BLOCK_INFO *GpeBlock; 427151937Sjkim ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; 428114239Snjl UINT32 IntStatus = ACPI_INTERRUPT_NOT_HANDLED; 429114239Snjl UINT8 EnabledStatusByte; 430129684Snjl UINT32 StatusReg; 431129684Snjl UINT32 EnableReg; 432167802Sjkim ACPI_CPU_FLAGS Flags; 433193267Sjkim UINT32 i; 434193267Sjkim UINT32 j; 435114239Snjl 436114239Snjl 437167802Sjkim ACPI_FUNCTION_NAME (EvGpeDetect); 438114239Snjl 439127175Snjl /* Check for the case where there are no GPEs */ 440114239Snjl 441127175Snjl if (!GpeXruptList) 442127175Snjl { 443127175Snjl return (IntStatus); 444127175Snjl } 445127175Snjl 446167802Sjkim /* 447167802Sjkim * We need to obtain the GPE lock for both the data structs and registers 448193267Sjkim * Note: Not necessary to obtain the hardware lock, since the GPE 449193267Sjkim * registers are owned by the GpeLock. 450167802Sjkim */ 451167802Sjkim Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); 452167802Sjkim 453114239Snjl /* Examine all GPE blocks attached to this interrupt level */ 454114239Snjl 455117521Snjl GpeBlock = GpeXruptList->GpeBlockListHead; 456114239Snjl while (GpeBlock) 457114239Snjl { 458114239Snjl /* 459193267Sjkim * Read all of the 8-bit GPE status and enable registers in this GPE 460193267Sjkim * block, saving all of them. Find all currently active GP events. 461114239Snjl */ 462114239Snjl for (i = 0; i < GpeBlock->RegisterCount; i++) 463114239Snjl { 464114239Snjl /* Get the next status/enable pair */ 465114239Snjl 466114239Snjl GpeRegisterInfo = &GpeBlock->RegisterInfo[i]; 467114239Snjl 468117521Snjl /* Read the Status Register */ 469117521Snjl 470197104Sjkim Status = AcpiHwRead (&StatusReg, &GpeRegisterInfo->StatusAddress); 471114239Snjl if (ACPI_FAILURE (Status)) 472114239Snjl { 473117521Snjl goto UnlockAndExit; 474114239Snjl } 475114239Snjl 476117521Snjl /* Read the Enable Register */ 477117521Snjl 478197104Sjkim Status = AcpiHwRead (&EnableReg, &GpeRegisterInfo->EnableAddress); 479114239Snjl if (ACPI_FAILURE (Status)) 480114239Snjl { 481117521Snjl goto UnlockAndExit; 482114239Snjl } 483114239Snjl 484114239Snjl ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, 485138287Smarks "Read GPE Register at GPE%X: Status=%02X, Enable=%02X\n", 486138287Smarks GpeRegisterInfo->BaseGpeNumber, StatusReg, EnableReg)); 487114239Snjl 488151937Sjkim /* Check if there is anything active at all in this register */ 489114239Snjl 490129684Snjl EnabledStatusByte = (UINT8) (StatusReg & EnableReg); 491114239Snjl if (!EnabledStatusByte) 492114239Snjl { 493114239Snjl /* No active GPEs in this register, move on */ 494114239Snjl 495114239Snjl continue; 496114239Snjl } 497114239Snjl 498114239Snjl /* Now look at the individual GPEs in this byte register */ 499114239Snjl 500123315Snjl for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) 501114239Snjl { 502114239Snjl /* Examine one GPE bit */ 503114239Snjl 504167802Sjkim if (EnabledStatusByte & (1 << j)) 505114239Snjl { 506114239Snjl /* 507114239Snjl * Found an active GPE. Dispatch the event to a handler 508114239Snjl * or method. 509114239Snjl */ 510114239Snjl IntStatus |= AcpiEvGpeDispatch ( 511193267Sjkim &GpeBlock->EventInfo[((ACPI_SIZE) i * 512193267Sjkim ACPI_GPE_REGISTER_WIDTH) + j], 513193267Sjkim j + GpeRegisterInfo->BaseGpeNumber); 514114239Snjl } 515114239Snjl } 516114239Snjl } 517114239Snjl 518114239Snjl GpeBlock = GpeBlock->Next; 519114239Snjl } 520114239Snjl 521117521SnjlUnlockAndExit: 522117521Snjl 523151937Sjkim AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); 524114239Snjl return (IntStatus); 525114239Snjl} 526114239Snjl 527114239Snjl 528114239Snjl/******************************************************************************* 529114239Snjl * 530114239Snjl * FUNCTION: AcpiEvAsynchExecuteGpeMethod 531114239Snjl * 532117521Snjl * PARAMETERS: Context (GpeEventInfo) - Info for this GPE 533114239Snjl * 534114239Snjl * RETURN: None 535114239Snjl * 536167802Sjkim * DESCRIPTION: Perform the actual execution of a GPE control method. This 537167802Sjkim * function is called from an invocation of AcpiOsExecute and 538167802Sjkim * therefore does NOT execute at interrupt level - so that 539114239Snjl * the control method itself is not executed in the context of 540117521Snjl * an interrupt handler. 541114239Snjl * 542114239Snjl ******************************************************************************/ 543114239Snjl 544114239Snjlstatic void ACPI_SYSTEM_XFACE 545114239SnjlAcpiEvAsynchExecuteGpeMethod ( 546114239Snjl void *Context) 547114239Snjl{ 548193267Sjkim ACPI_GPE_EVENT_INFO *GpeEventInfo = Context; 549114239Snjl ACPI_STATUS Status; 550193267Sjkim ACPI_GPE_EVENT_INFO *LocalGpeEventInfo; 551167802Sjkim ACPI_EVALUATE_INFO *Info; 552114239Snjl 553114239Snjl 554167802Sjkim ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod); 555114239Snjl 556114239Snjl 557193267Sjkim /* Allocate a local GPE block */ 558193267Sjkim 559193267Sjkim LocalGpeEventInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_EVENT_INFO)); 560193267Sjkim if (!LocalGpeEventInfo) 561193267Sjkim { 562193267Sjkim ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY, 563193267Sjkim "while handling a GPE")); 564193267Sjkim return_VOID; 565193267Sjkim } 566193267Sjkim 567114239Snjl Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); 568114239Snjl if (ACPI_FAILURE (Status)) 569114239Snjl { 570114239Snjl return_VOID; 571114239Snjl } 572114239Snjl 573117521Snjl /* Must revalidate the GpeNumber/GpeBlock */ 574117521Snjl 575117521Snjl if (!AcpiEvValidGpeEvent (GpeEventInfo)) 576117521Snjl { 577117521Snjl Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 578117521Snjl return_VOID; 579117521Snjl } 580117521Snjl 581206117Sjkim /* Update the GPE register masks for return to enabled state */ 582129684Snjl 583206117Sjkim (void) AcpiEvUpdateGpeEnableMasks (GpeEventInfo); 584129684Snjl 585117521Snjl /* 586193267Sjkim * Take a snapshot of the GPE info for this level - we copy the info to 587193267Sjkim * prevent a race condition with RemoveHandler/RemoveBlock. 588117521Snjl */ 589193267Sjkim ACPI_MEMCPY (LocalGpeEventInfo, GpeEventInfo, 590151937Sjkim sizeof (ACPI_GPE_EVENT_INFO)); 591117521Snjl 592114239Snjl Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 593114239Snjl if (ACPI_FAILURE (Status)) 594114239Snjl { 595114239Snjl return_VOID; 596114239Snjl } 597114239Snjl 598129684Snjl /* 599193267Sjkim * Must check for control method type dispatch one more time to avoid a 600193267Sjkim * race with EvGpeInstallHandler 601129684Snjl */ 602193267Sjkim if ((LocalGpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == 603151937Sjkim ACPI_GPE_DISPATCH_METHOD) 604114239Snjl { 605167802Sjkim /* Allocate the evaluation information block */ 606129684Snjl 607167802Sjkim Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); 608167802Sjkim if (!Info) 609167802Sjkim { 610167802Sjkim Status = AE_NO_MEMORY; 611167802Sjkim } 612167802Sjkim else 613167802Sjkim { 614167802Sjkim /* 615167802Sjkim * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx 616167802Sjkim * control method that corresponds to this GPE 617167802Sjkim */ 618193267Sjkim Info->PrefixNode = LocalGpeEventInfo->Dispatch.MethodNode; 619167802Sjkim Info->Flags = ACPI_IGNORE_RETURN_VALUE; 620167802Sjkim 621167802Sjkim Status = AcpiNsEvaluate (Info); 622167802Sjkim ACPI_FREE (Info); 623167802Sjkim } 624167802Sjkim 625114239Snjl if (ACPI_FAILURE (Status)) 626114239Snjl { 627167802Sjkim ACPI_EXCEPTION ((AE_INFO, Status, 628167802Sjkim "while evaluating GPE method [%4.4s]", 629193267Sjkim AcpiUtGetNodeName (LocalGpeEventInfo->Dispatch.MethodNode))); 630114239Snjl } 631114239Snjl } 632114239Snjl 633175256Snjl /* Defer enabling of GPE until all notify handlers are done */ 634193267Sjkim 635193267Sjkim Status = AcpiOsExecute (OSL_NOTIFY_HANDLER, 636193267Sjkim AcpiEvAsynchEnableGpe, LocalGpeEventInfo); 637193267Sjkim if (ACPI_FAILURE (Status)) 638193267Sjkim { 639193267Sjkim ACPI_FREE (LocalGpeEventInfo); 640193267Sjkim } 641175256Snjl return_VOID; 642175256Snjl} 643175256Snjl 644193267Sjkim 645193267Sjkim/******************************************************************************* 646193267Sjkim * 647193267Sjkim * FUNCTION: AcpiEvAsynchEnableGpe 648193267Sjkim * 649193267Sjkim * PARAMETERS: Context (GpeEventInfo) - Info for this GPE 650193267Sjkim * 651193267Sjkim * RETURN: None 652193267Sjkim * 653193267Sjkim * DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to 654193267Sjkim * complete (i.e., finish execution of Notify) 655193267Sjkim * 656193267Sjkim ******************************************************************************/ 657193267Sjkim 658193267Sjkimstatic void ACPI_SYSTEM_XFACE 659175256SnjlAcpiEvAsynchEnableGpe ( 660175256Snjl void *Context) 661175256Snjl{ 662193267Sjkim ACPI_GPE_EVENT_INFO *GpeEventInfo = Context; 663175256Snjl ACPI_STATUS Status; 664175256Snjl 665193267Sjkim 666175256Snjl if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) == 667151937Sjkim ACPI_GPE_LEVEL_TRIGGERED) 668114239Snjl { 669114239Snjl /* 670193267Sjkim * GPE is level-triggered, we clear the GPE status bit after handling 671193267Sjkim * the event. 672114239Snjl */ 673175256Snjl Status = AcpiHwClearGpe (GpeEventInfo); 674114239Snjl if (ACPI_FAILURE (Status)) 675114239Snjl { 676193267Sjkim goto Exit; 677114239Snjl } 678114239Snjl } 679114239Snjl 680114239Snjl /* Enable this GPE */ 681114239Snjl 682175256Snjl (void) AcpiHwWriteGpeEnableReg (GpeEventInfo); 683193267Sjkim 684193267SjkimExit: 685193267Sjkim ACPI_FREE (GpeEventInfo); 686193267Sjkim return; 687114239Snjl} 688114239Snjl 689114239Snjl 690114239Snjl/******************************************************************************* 691114239Snjl * 692114239Snjl * FUNCTION: AcpiEvGpeDispatch 693114239Snjl * 694151937Sjkim * PARAMETERS: GpeEventInfo - Info for this GPE 695117521Snjl * GpeNumber - Number relative to the parent GPE block 696114239Snjl * 697114239Snjl * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED 698114239Snjl * 699114239Snjl * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC) 700117521Snjl * or method (e.g. _Lxx/_Exx) handler. 701114239Snjl * 702117521Snjl * This function executes at interrupt level. 703117521Snjl * 704114239Snjl ******************************************************************************/ 705114239Snjl 706114239SnjlUINT32 707114239SnjlAcpiEvGpeDispatch ( 708117521Snjl ACPI_GPE_EVENT_INFO *GpeEventInfo, 709117521Snjl UINT32 GpeNumber) 710114239Snjl{ 711114239Snjl ACPI_STATUS Status; 712114239Snjl 713114239Snjl 714167802Sjkim ACPI_FUNCTION_TRACE (EvGpeDispatch); 715114239Snjl 716114239Snjl 717167802Sjkim AcpiGpeCount++; 718167802Sjkim 719114239Snjl /* 720193267Sjkim * If edge-triggered, clear the GPE status bit now. Note that 721114239Snjl * level-triggered events are cleared after the GPE is serviced. 722114239Snjl */ 723151937Sjkim if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) == 724151937Sjkim ACPI_GPE_EDGE_TRIGGERED) 725114239Snjl { 726114239Snjl Status = AcpiHwClearGpe (GpeEventInfo); 727114239Snjl if (ACPI_FAILURE (Status)) 728114239Snjl { 729167802Sjkim ACPI_EXCEPTION ((AE_INFO, Status, 730204773Sjkim "Unable to clear GPE[0x%2X]", GpeNumber)); 731151937Sjkim return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); 732114239Snjl } 733114239Snjl } 734114239Snjl 735114239Snjl /* 736167802Sjkim * Dispatch the GPE to either an installed handler, or the control method 737167802Sjkim * associated with this GPE (_Lxx or _Exx). If a handler exists, we invoke 738167802Sjkim * it and do not attempt to run the method. If there is neither a handler 739167802Sjkim * nor a method, we disable this GPE to prevent further such pointless 740167802Sjkim * events from firing. 741114239Snjl */ 742129684Snjl switch (GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) 743114239Snjl { 744129684Snjl case ACPI_GPE_DISPATCH_HANDLER: 745129684Snjl 746131440Smarks /* 747131440Smarks * Invoke the installed handler (at interrupt level) 748193267Sjkim * Ignore return status for now. 749193267Sjkim * TBD: leave GPE disabled on error? 750131440Smarks */ 751131440Smarks (void) GpeEventInfo->Dispatch.Handler->Address ( 752129684Snjl GpeEventInfo->Dispatch.Handler->Context); 753123315Snjl 754123315Snjl /* It is now safe to clear level-triggered events. */ 755123315Snjl 756151937Sjkim if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) == 757151937Sjkim ACPI_GPE_LEVEL_TRIGGERED) 758123315Snjl { 759123315Snjl Status = AcpiHwClearGpe (GpeEventInfo); 760123315Snjl if (ACPI_FAILURE (Status)) 761123315Snjl { 762167802Sjkim ACPI_EXCEPTION ((AE_INFO, Status, 763204773Sjkim "Unable to clear GPE[0x%2X]", GpeNumber)); 764151937Sjkim return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); 765123315Snjl } 766123315Snjl } 767129684Snjl break; 768129684Snjl 769129684Snjl case ACPI_GPE_DISPATCH_METHOD: 770129684Snjl 771114239Snjl /* 772167802Sjkim * Disable the GPE, so it doesn't keep firing before the method has a 773167802Sjkim * chance to run (it runs asynchronously with interrupts enabled). 774114239Snjl */ 775129684Snjl Status = AcpiEvDisableGpe (GpeEventInfo); 776114239Snjl if (ACPI_FAILURE (Status)) 777114239Snjl { 778167802Sjkim ACPI_EXCEPTION ((AE_INFO, Status, 779204773Sjkim "Unable to disable GPE[0x%2X]", GpeNumber)); 780151937Sjkim return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); 781114239Snjl } 782114239Snjl 783126372Snjl /* 784123315Snjl * Execute the method associated with the GPE 785123315Snjl * NOTE: Level-triggered GPEs are cleared after the method completes. 786123315Snjl */ 787167802Sjkim Status = AcpiOsExecute (OSL_GPE_HANDLER, 788151937Sjkim AcpiEvAsynchExecuteGpeMethod, GpeEventInfo); 789151937Sjkim if (ACPI_FAILURE (Status)) 790114239Snjl { 791167802Sjkim ACPI_EXCEPTION ((AE_INFO, Status, 792204773Sjkim "Unable to queue handler for GPE[0x%2X] - event disabled", 793167802Sjkim GpeNumber)); 794114239Snjl } 795129684Snjl break; 796129684Snjl 797129684Snjl default: 798129684Snjl 799206117Sjkim /* 800206117Sjkim * No handler or method to run! 801206117Sjkim * 03/2010: This case should no longer be possible. We will not allow 802206117Sjkim * a GPE to be enabled if it has no handler or method. 803206117Sjkim */ 804167802Sjkim ACPI_ERROR ((AE_INFO, 805204773Sjkim "No handler or method for GPE[0x%2X], disabling event", 806114239Snjl GpeNumber)); 807114239Snjl 808114239Snjl /* 809206117Sjkim * Disable the GPE. The GPE will remain disabled a handler 810206117Sjkim * is installed or ACPICA is restarted. 811114239Snjl */ 812129684Snjl Status = AcpiEvDisableGpe (GpeEventInfo); 813114239Snjl if (ACPI_FAILURE (Status)) 814114239Snjl { 815167802Sjkim ACPI_EXCEPTION ((AE_INFO, Status, 816204773Sjkim "Unable to disable GPE[0x%2X]", GpeNumber)); 817151937Sjkim return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); 818114239Snjl } 819129684Snjl break; 820114239Snjl } 821114239Snjl 822151937Sjkim return_UINT32 (ACPI_INTERRUPT_HANDLED); 823114239Snjl} 824114239Snjl 825