Path: blob/main/sys/contrib/dev/acpica/components/events/evxfgpe.c
48525 views
/******************************************************************************1*2* Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs)3*4*****************************************************************************/56/******************************************************************************7*8* 1. Copyright Notice9*10* Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.11* All rights reserved.12*13* 2. License14*15* 2.1. This is your license from Intel Corp. under its intellectual property16* rights. You may have additional license terms from the party that provided17* you this software, covering your right to use that party's intellectual18* property rights.19*20* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a21* copy of the source code appearing in this file ("Covered Code") an22* irrevocable, perpetual, worldwide license under Intel's copyrights in the23* base code distributed originally by Intel ("Original Intel Code") to copy,24* make derivatives, distribute, use and display any portion of the Covered25* Code in any form, with the right to sublicense such rights; and26*27* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent28* license (with the right to sublicense), under only those claims of Intel29* patents that are infringed by the Original Intel Code, to make, use, sell,30* offer to sell, and import the Covered Code and derivative works thereof31* solely to the minimum extent necessary to exercise the above copyright32* license, and in no event shall the patent license extend to any additions33* to or modifications of the Original Intel Code. No other license or right34* is granted directly or by implication, estoppel or otherwise;35*36* The above copyright and patent license is granted only if the following37* conditions are met:38*39* 3. Conditions40*41* 3.1. Redistribution of Source with Rights to Further Distribute Source.42* Redistribution of source code of any substantial portion of the Covered43* Code or modification with rights to further distribute source must include44* the above Copyright Notice, the above License, this list of Conditions,45* and the following Disclaimer and Export Compliance provision. In addition,46* Licensee must cause all Covered Code to which Licensee contributes to47* contain a file documenting the changes Licensee made to create that Covered48* Code and the date of any change. Licensee must include in that file the49* documentation of any changes made by any predecessor Licensee. Licensee50* must include a prominent statement that the modification is derived,51* directly or indirectly, from Original Intel Code.52*53* 3.2. Redistribution of Source with no Rights to Further Distribute Source.54* Redistribution of source code of any substantial portion of the Covered55* Code or modification without rights to further distribute source must56* include the following Disclaimer and Export Compliance provision in the57* documentation and/or other materials provided with distribution. In58* addition, Licensee may not authorize further sublicense of source of any59* portion of the Covered Code, and must include terms to the effect that the60* license from Licensee to its licensee is limited to the intellectual61* property embodied in the software Licensee provides to its licensee, and62* not to intellectual property embodied in modifications its licensee may63* make.64*65* 3.3. Redistribution of Executable. Redistribution in executable form of any66* substantial portion of the Covered Code or modification must reproduce the67* above Copyright Notice, and the following Disclaimer and Export Compliance68* provision in the documentation and/or other materials provided with the69* distribution.70*71* 3.4. Intel retains all right, title, and interest in and to the Original72* Intel Code.73*74* 3.5. Neither the name Intel nor any other trademark owned or controlled by75* Intel shall be used in advertising or otherwise to promote the sale, use or76* other dealings in products derived from or relating to the Covered Code77* without prior written authorization from Intel.78*79* 4. Disclaimer and Export Compliance80*81* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED82* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE83* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,84* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY85* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY86* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A87* PARTICULAR PURPOSE.88*89* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES90* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR91* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,92* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY93* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL94* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS95* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY96* LIMITED REMEDY.97*98* 4.3. Licensee shall not export, either directly or indirectly, any of this99* software or system incorporating such software without first obtaining any100* required license or other approval from the U. S. Department of Commerce or101* any other agency or department of the United States Government. In the102* event Licensee exports any such software from the United States or103* re-exports any such software from a foreign destination, Licensee shall104* ensure that the distribution and export/re-export of the software is in105* compliance with all laws, regulations, orders, or other restrictions of the106* U.S. Export Administration Regulations. Licensee agrees that neither it nor107* any of its subsidiaries will export/re-export any technical data, process,108* software, or service, directly or indirectly, to any country for which the109* United States government or any agency thereof requires an export license,110* other governmental approval, or letter of assurance, without first obtaining111* such license, approval or letter.112*113*****************************************************************************114*115* Alternatively, you may choose to be licensed under the terms of the116* following license:117*118* Redistribution and use in source and binary forms, with or without119* modification, are permitted provided that the following conditions120* are met:121* 1. Redistributions of source code must retain the above copyright122* notice, this list of conditions, and the following disclaimer,123* without modification.124* 2. Redistributions in binary form must reproduce at minimum a disclaimer125* substantially similar to the "NO WARRANTY" disclaimer below126* ("Disclaimer") and any redistribution must be conditioned upon127* including a substantially similar Disclaimer requirement for further128* binary redistribution.129* 3. Neither the names of the above-listed copyright holders nor the names130* of any contributors may be used to endorse or promote products derived131* from this software without specific prior written permission.132*133* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS134* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT135* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR136* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT137* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,138* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT139* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,140* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY141* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT142* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE143* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.144*145* Alternatively, you may choose to be licensed under the terms of the146* GNU General Public License ("GPL") version 2 as published by the Free147* Software Foundation.148*149*****************************************************************************/150151#define EXPORT_ACPI_INTERFACES152153#include <contrib/dev/acpica/include/acpi.h>154#include <contrib/dev/acpica/include/accommon.h>155#include <contrib/dev/acpica/include/acevents.h>156#include <contrib/dev/acpica/include/acnamesp.h>157158#define _COMPONENT ACPI_EVENTS159ACPI_MODULE_NAME ("evxfgpe")160161162#if (!ACPI_REDUCED_HARDWARE) /* Entire module */163/*******************************************************************************164*165* FUNCTION: AcpiUpdateAllGpes166*167* PARAMETERS: None168*169* RETURN: Status170*171* DESCRIPTION: Complete GPE initialization and enable all GPEs that have172* associated _Lxx or _Exx methods and are not pointed to by any173* device _PRW methods (this indicates that these GPEs are174* generally intended for system or device wakeup. Such GPEs175* have to be enabled directly when the devices whose _PRW176* methods point to them are set up for wakeup signaling.)177*178* NOTE: Should be called after any GPEs are added to the system. Primarily,179* after the system _PRW methods have been run, but also after a GPE Block180* Device has been added or if any new GPE methods have been added via a181* dynamic table load.182*183******************************************************************************/184185ACPI_STATUS186AcpiUpdateAllGpes (187void)188{189ACPI_STATUS Status;190BOOLEAN IsPollingNeeded = FALSE;191192193ACPI_FUNCTION_TRACE (AcpiUpdateAllGpes);194195196Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);197if (ACPI_FAILURE (Status))198{199return_ACPI_STATUS (Status);200}201202if (AcpiGbl_AllGpesInitialized)203{204goto UnlockAndExit;205}206207Status = AcpiEvWalkGpeList (AcpiEvInitializeGpeBlock,208&IsPollingNeeded);209if (ACPI_SUCCESS (Status))210{211AcpiGbl_AllGpesInitialized = TRUE;212}213214UnlockAndExit:215(void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);216217if (IsPollingNeeded && AcpiGbl_AllGpesInitialized)218{219/* Poll GPEs to handle already triggered events */220221AcpiEvGpeDetect (AcpiGbl_GpeXruptListHead);222}223return_ACPI_STATUS (Status);224}225226ACPI_EXPORT_SYMBOL (AcpiUpdateAllGpes)227228229/*******************************************************************************230*231* FUNCTION: AcpiEnableGpe232*233* PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1234* GpeNumber - GPE level within the GPE block235*236* RETURN: Status237*238* DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is239* hardware-enabled.240*241******************************************************************************/242243ACPI_STATUS244AcpiEnableGpe (245ACPI_HANDLE GpeDevice,246UINT32 GpeNumber)247{248ACPI_STATUS Status = AE_BAD_PARAMETER;249ACPI_GPE_EVENT_INFO *GpeEventInfo;250ACPI_CPU_FLAGS Flags;251252253ACPI_FUNCTION_TRACE (AcpiEnableGpe);254255256Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);257258/*259* Ensure that we have a valid GPE number and that there is some way260* of handling the GPE (handler or a GPE method). In other words, we261* won't allow a valid GPE to be enabled if there is no way to handle it.262*/263GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);264if (GpeEventInfo)265{266if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) !=267ACPI_GPE_DISPATCH_NONE)268{269Status = AcpiEvAddGpeReference (GpeEventInfo, TRUE);270if (ACPI_SUCCESS (Status) &&271ACPI_GPE_IS_POLLING_NEEDED (GpeEventInfo))272{273/* Poll edge-triggered GPEs to handle existing events */274275AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);276(void) AcpiEvDetectGpe (277GpeDevice, GpeEventInfo, GpeNumber);278Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);279}280}281else282{283Status = AE_NO_HANDLER;284}285}286287AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);288return_ACPI_STATUS (Status);289}290291ACPI_EXPORT_SYMBOL (AcpiEnableGpe)292293294/*******************************************************************************295*296* FUNCTION: AcpiDisableGpe297*298* PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1299* GpeNumber - GPE level within the GPE block300*301* RETURN: Status302*303* DESCRIPTION: Remove a reference to a GPE. When the last reference is304* removed, only then is the GPE disabled (for runtime GPEs), or305* the GPE mask bit disabled (for wake GPEs)306*307******************************************************************************/308309ACPI_STATUS310AcpiDisableGpe (311ACPI_HANDLE GpeDevice,312UINT32 GpeNumber)313{314ACPI_STATUS Status = AE_BAD_PARAMETER;315ACPI_GPE_EVENT_INFO *GpeEventInfo;316ACPI_CPU_FLAGS Flags;317318319ACPI_FUNCTION_TRACE (AcpiDisableGpe);320321322Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);323324/* Ensure that we have a valid GPE number */325326GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);327if (GpeEventInfo)328{329Status = AcpiEvRemoveGpeReference (GpeEventInfo);330}331332AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);333return_ACPI_STATUS (Status);334}335336ACPI_EXPORT_SYMBOL (AcpiDisableGpe)337338339/*******************************************************************************340*341* FUNCTION: AcpiSetGpe342*343* PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1344* GpeNumber - GPE level within the GPE block345* Action - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE346*347* RETURN: Status348*349* DESCRIPTION: Enable or disable an individual GPE. This function bypasses350* the reference count mechanism used in the AcpiEnableGpe(),351* AcpiDisableGpe() interfaces.352* This API is typically used by the GPE raw handler mode driver353* to switch between the polling mode and the interrupt mode after354* the driver has enabled the GPE.355* The APIs should be invoked in this order:356* AcpiEnableGpe() <- Ensure the reference count > 0357* AcpiSetGpe(ACPI_GPE_DISABLE) <- Enter polling mode358* AcpiSetGpe(ACPI_GPE_ENABLE) <- Leave polling mode359* AcpiDisableGpe() <- Decrease the reference count360*361* Note: If a GPE is shared by 2 silicon components, then both the drivers362* should support GPE polling mode or disabling the GPE for long period363* for one driver may break the other. So use it with care since all364* firmware _Lxx/_Exx handlers currently rely on the GPE interrupt mode.365*366******************************************************************************/367368ACPI_STATUS369AcpiSetGpe (370ACPI_HANDLE GpeDevice,371UINT32 GpeNumber,372UINT8 Action)373{374ACPI_GPE_EVENT_INFO *GpeEventInfo;375ACPI_STATUS Status;376ACPI_CPU_FLAGS Flags;377378379ACPI_FUNCTION_TRACE (AcpiSetGpe);380381382Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);383384/* Ensure that we have a valid GPE number */385386GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);387if (!GpeEventInfo)388{389Status = AE_BAD_PARAMETER;390goto UnlockAndExit;391}392393/* Perform the action */394395switch (Action)396{397case ACPI_GPE_ENABLE:398399Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE);400GpeEventInfo->DisableForDispatch = FALSE;401break;402403case ACPI_GPE_DISABLE:404405Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);406GpeEventInfo->DisableForDispatch = TRUE;407break;408409default:410411Status = AE_BAD_PARAMETER;412break;413}414415UnlockAndExit:416AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);417return_ACPI_STATUS (Status);418}419420ACPI_EXPORT_SYMBOL (AcpiSetGpe)421422423/*******************************************************************************424*425* FUNCTION: AcpiMaskGpe426*427* PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1428* GpeNumber - GPE level within the GPE block429* IsMasked - Whether the GPE is masked or not430*431* RETURN: Status432*433* DESCRIPTION: Unconditionally mask/unmask the an individual GPE, ex., to434* prevent a GPE flooding.435*436******************************************************************************/437438ACPI_STATUS439AcpiMaskGpe (440ACPI_HANDLE GpeDevice,441UINT32 GpeNumber,442BOOLEAN IsMasked)443{444ACPI_GPE_EVENT_INFO *GpeEventInfo;445ACPI_STATUS Status;446ACPI_CPU_FLAGS Flags;447448449ACPI_FUNCTION_TRACE (AcpiMaskGpe);450451452Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);453454/* Ensure that we have a valid GPE number */455456GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);457if (!GpeEventInfo)458{459Status = AE_BAD_PARAMETER;460goto UnlockAndExit;461}462463Status = AcpiEvMaskGpe (GpeEventInfo, IsMasked);464465UnlockAndExit:466AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);467return_ACPI_STATUS (Status);468}469470ACPI_EXPORT_SYMBOL (AcpiMaskGpe)471472473/*******************************************************************************474*475* FUNCTION: AcpiMarkGpeForWake476*477* PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1478* GpeNumber - GPE level within the GPE block479*480* RETURN: Status481*482* DESCRIPTION: Mark a GPE as having the ability to wake the system. Simply483* sets the ACPI_GPE_CAN_WAKE flag.484*485* Some potential callers of AcpiSetupGpeForWake may know in advance that486* there won't be any notify handlers installed for device wake notifications487* from the given GPE (one example is a button GPE in Linux). For these cases,488* AcpiMarkGpeForWake should be used instead of AcpiSetupGpeForWake.489* This will set the ACPI_GPE_CAN_WAKE flag for the GPE without trying to490* setup implicit wake notification for it (since there's no handler method).491*492******************************************************************************/493494ACPI_STATUS495AcpiMarkGpeForWake (496ACPI_HANDLE GpeDevice,497UINT32 GpeNumber)498{499ACPI_GPE_EVENT_INFO *GpeEventInfo;500ACPI_STATUS Status = AE_BAD_PARAMETER;501ACPI_CPU_FLAGS Flags;502503504ACPI_FUNCTION_TRACE (AcpiMarkGpeForWake);505506507Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);508509/* Ensure that we have a valid GPE number */510511GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);512if (GpeEventInfo)513{514/* Mark the GPE as a possible wake event */515516GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;517Status = AE_OK;518}519520AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);521return_ACPI_STATUS (Status);522}523524ACPI_EXPORT_SYMBOL (AcpiMarkGpeForWake)525526527/*******************************************************************************528*529* FUNCTION: AcpiSetupGpeForWake530*531* PARAMETERS: WakeDevice - Device associated with the GPE (via _PRW)532* GpeDevice - Parent GPE Device. NULL for GPE0/GPE1533* GpeNumber - GPE level within the GPE block534*535* RETURN: Status536*537* DESCRIPTION: Mark a GPE as having the ability to wake the system. This538* interface is intended to be used as the host executes the539* _PRW methods (Power Resources for Wake) in the system tables.540* Each _PRW appears under a Device Object (The WakeDevice), and541* contains the info for the wake GPE associated with the542* WakeDevice.543*544******************************************************************************/545546ACPI_STATUS547AcpiSetupGpeForWake (548ACPI_HANDLE WakeDevice,549ACPI_HANDLE GpeDevice,550UINT32 GpeNumber)551{552ACPI_STATUS Status;553ACPI_GPE_EVENT_INFO *GpeEventInfo;554ACPI_NAMESPACE_NODE *DeviceNode;555ACPI_GPE_NOTIFY_INFO *Notify;556ACPI_GPE_NOTIFY_INFO *NewNotify;557ACPI_CPU_FLAGS Flags;558559560ACPI_FUNCTION_TRACE (AcpiSetupGpeForWake);561562563/* Parameter Validation */564565if (!WakeDevice)566{567/*568* By forcing WakeDevice to be valid, we automatically enable the569* implicit notify feature on all hosts.570*/571return_ACPI_STATUS (AE_BAD_PARAMETER);572}573574/* Handle root object case */575576if (WakeDevice == ACPI_ROOT_OBJECT)577{578DeviceNode = AcpiGbl_RootNode;579}580else581{582DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, WakeDevice);583}584585/* Validate WakeDevice is of type Device */586587if (DeviceNode->Type != ACPI_TYPE_DEVICE)588{589return_ACPI_STATUS (AE_BAD_PARAMETER);590}591592/*593* Allocate a new notify object up front, in case it is needed.594* Memory allocation while holding a spinlock is a big no-no595* on some hosts.596*/597NewNotify = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_NOTIFY_INFO));598if (!NewNotify)599{600return_ACPI_STATUS (AE_NO_MEMORY);601}602603Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);604605/* Ensure that we have a valid GPE number */606607GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);608if (!GpeEventInfo)609{610Status = AE_BAD_PARAMETER;611goto UnlockAndExit;612}613614/*615* If there is no method or handler for this GPE, then the616* WakeDevice will be notified whenever this GPE fires. This is617* known as an "implicit notify". Note: The GPE is assumed to be618* level-triggered (for windows compatibility).619*/620if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==621ACPI_GPE_DISPATCH_NONE)622{623/*624* This is the first device for implicit notify on this GPE.625* Just set the flags here, and enter the NOTIFY block below.626*/627GpeEventInfo->Flags =628(ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED);629}630else if (GpeEventInfo->Flags & ACPI_GPE_AUTO_ENABLED)631{632/*633* A reference to this GPE has been added during the GPE block634* initialization, so drop it now to prevent the GPE from being635* permanently enabled and clear its ACPI_GPE_AUTO_ENABLED flag.636*/637(void) AcpiEvRemoveGpeReference (GpeEventInfo);638GpeEventInfo->Flags &= ~ACPI_GPE_AUTO_ENABLED;639}640641/*642* If we already have an implicit notify on this GPE, add643* this device to the notify list.644*/645if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) ==646ACPI_GPE_DISPATCH_NOTIFY)647{648/* Ensure that the device is not already in the list */649650Notify = GpeEventInfo->Dispatch.NotifyList;651while (Notify)652{653if (Notify->DeviceNode == DeviceNode)654{655Status = AE_ALREADY_EXISTS;656goto UnlockAndExit;657}658Notify = Notify->Next;659}660661/* Add this device to the notify list for this GPE */662663NewNotify->DeviceNode = DeviceNode;664NewNotify->Next = GpeEventInfo->Dispatch.NotifyList;665GpeEventInfo->Dispatch.NotifyList = NewNotify;666NewNotify = NULL;667}668669/* Mark the GPE as a possible wake event */670671GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;672Status = AE_OK;673674675UnlockAndExit:676AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);677678/* Delete the notify object if it was not used above */679680if (NewNotify)681{682ACPI_FREE (NewNotify);683}684return_ACPI_STATUS (Status);685}686687ACPI_EXPORT_SYMBOL (AcpiSetupGpeForWake)688689690/*******************************************************************************691*692* FUNCTION: AcpiSetGpeWakeMask693*694* PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1695* GpeNumber - GPE level within the GPE block696* Action - Enable or Disable697*698* RETURN: Status699*700* DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must701* already be marked as a WAKE GPE.702*703******************************************************************************/704705ACPI_STATUS706AcpiSetGpeWakeMask (707ACPI_HANDLE GpeDevice,708UINT32 GpeNumber,709UINT8 Action)710{711ACPI_STATUS Status = AE_OK;712ACPI_GPE_EVENT_INFO *GpeEventInfo;713ACPI_GPE_REGISTER_INFO *GpeRegisterInfo;714ACPI_CPU_FLAGS Flags;715UINT32 RegisterBit;716717718ACPI_FUNCTION_TRACE (AcpiSetGpeWakeMask);719720721Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);722723/*724* Ensure that we have a valid GPE number and that this GPE is in725* fact a wake GPE726*/727GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);728if (!GpeEventInfo)729{730Status = AE_BAD_PARAMETER;731goto UnlockAndExit;732}733734if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE))735{736Status = AE_TYPE;737goto UnlockAndExit;738}739740GpeRegisterInfo = GpeEventInfo->RegisterInfo;741if (!GpeRegisterInfo)742{743Status = AE_NOT_EXIST;744goto UnlockAndExit;745}746747RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo);748749/* Perform the action */750751switch (Action)752{753case ACPI_GPE_ENABLE:754755ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);756break;757758case ACPI_GPE_DISABLE:759760ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);761break;762763default:764765ACPI_ERROR ((AE_INFO, "%u, Invalid action", Action));766Status = AE_BAD_PARAMETER;767break;768}769770UnlockAndExit:771AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);772return_ACPI_STATUS (Status);773}774775ACPI_EXPORT_SYMBOL (AcpiSetGpeWakeMask)776777778/*******************************************************************************779*780* FUNCTION: AcpiClearGpe781*782* PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1783* GpeNumber - GPE level within the GPE block784*785* RETURN: Status786*787* DESCRIPTION: Clear an ACPI event (general purpose)788*789******************************************************************************/790791ACPI_STATUS792AcpiClearGpe (793ACPI_HANDLE GpeDevice,794UINT32 GpeNumber)795{796ACPI_STATUS Status = AE_OK;797ACPI_GPE_EVENT_INFO *GpeEventInfo;798ACPI_CPU_FLAGS Flags;799800801ACPI_FUNCTION_TRACE (AcpiClearGpe);802803804Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);805806/* Ensure that we have a valid GPE number */807808GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);809if (!GpeEventInfo)810{811Status = AE_BAD_PARAMETER;812goto UnlockAndExit;813}814815Status = AcpiHwClearGpe (GpeEventInfo);816817UnlockAndExit:818AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);819return_ACPI_STATUS (Status);820}821822ACPI_EXPORT_SYMBOL (AcpiClearGpe)823824825/*******************************************************************************826*827* FUNCTION: AcpiGetGpeStatus828*829* PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1830* GpeNumber - GPE level within the GPE block831* EventStatus - Where the current status of the event832* will be returned833*834* RETURN: Status835*836* DESCRIPTION: Get the current status of a GPE (signalled/not_signalled)837*838******************************************************************************/839840ACPI_STATUS841AcpiGetGpeStatus (842ACPI_HANDLE GpeDevice,843UINT32 GpeNumber,844ACPI_EVENT_STATUS *EventStatus)845{846ACPI_STATUS Status = AE_OK;847ACPI_GPE_EVENT_INFO *GpeEventInfo;848ACPI_CPU_FLAGS Flags;849850851ACPI_FUNCTION_TRACE (AcpiGetGpeStatus);852853854Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);855856/* Ensure that we have a valid GPE number */857858GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);859if (!GpeEventInfo)860{861Status = AE_BAD_PARAMETER;862goto UnlockAndExit;863}864865/* Obtain status on the requested GPE number */866867Status = AcpiHwGetGpeStatus (GpeEventInfo, EventStatus);868869UnlockAndExit:870AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);871return_ACPI_STATUS (Status);872}873874ACPI_EXPORT_SYMBOL (AcpiGetGpeStatus)875876877/*******************************************************************************878*879* FUNCTION: AcpiDispatchGpe880*881* PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1882* GpeNumber - GPE level within the GPE block883*884* RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED885*886* DESCRIPTION: Detect and dispatch a General Purpose Event to either a function887* (e.g. EC) or method (e.g. _Lxx/_Exx) handler.888*889******************************************************************************/890891UINT32892AcpiDispatchGpe(893ACPI_HANDLE GpeDevice,894UINT32 GpeNumber)895{896ACPI_FUNCTION_TRACE(acpi_dispatch_gpe);897898return (AcpiEvDetectGpe (GpeDevice, NULL, GpeNumber));899}900901ACPI_EXPORT_SYMBOL (AcpiDispatchGpe)902903904/*******************************************************************************905*906* FUNCTION: AcpiFinishGpe907*908* PARAMETERS: GpeDevice - Namespace node for the GPE Block909* (NULL for FADT defined GPEs)910* GpeNumber - GPE level within the GPE block911*912* RETURN: Status913*914* DESCRIPTION: Clear and conditionally re-enable a GPE. This completes the GPE915* processing. Intended for use by asynchronous host-installed916* GPE handlers. The GPE is only re-enabled if the EnableForRun bit917* is set in the GPE info.918*919******************************************************************************/920921ACPI_STATUS922AcpiFinishGpe (923ACPI_HANDLE GpeDevice,924UINT32 GpeNumber)925{926ACPI_GPE_EVENT_INFO *GpeEventInfo;927ACPI_STATUS Status;928ACPI_CPU_FLAGS Flags;929930931ACPI_FUNCTION_TRACE (AcpiFinishGpe);932933934Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);935936/* Ensure that we have a valid GPE number */937938GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);939if (!GpeEventInfo)940{941Status = AE_BAD_PARAMETER;942goto UnlockAndExit;943}944945Status = AcpiEvFinishGpe (GpeEventInfo);946947UnlockAndExit:948AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);949return_ACPI_STATUS (Status);950}951952ACPI_EXPORT_SYMBOL (AcpiFinishGpe)953954955/******************************************************************************956*957* FUNCTION: AcpiDisableAllGpes958*959* PARAMETERS: None960*961* RETURN: Status962*963* DESCRIPTION: Disable and clear all GPEs in all GPE blocks964*965******************************************************************************/966967ACPI_STATUS968AcpiDisableAllGpes (969void)970{971ACPI_STATUS Status;972973974ACPI_FUNCTION_TRACE (AcpiDisableAllGpes);975976977Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);978if (ACPI_FAILURE (Status))979{980return_ACPI_STATUS (Status);981}982983Status = AcpiHwDisableAllGpes ();984(void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);985986return_ACPI_STATUS (Status);987}988989ACPI_EXPORT_SYMBOL (AcpiDisableAllGpes)990991992/******************************************************************************993*994* FUNCTION: AcpiEnableAllRuntimeGpes995*996* PARAMETERS: None997*998* RETURN: Status999*1000* DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks1001*1002******************************************************************************/10031004ACPI_STATUS1005AcpiEnableAllRuntimeGpes (1006void)1007{1008ACPI_STATUS Status;100910101011ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes);101210131014Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);1015if (ACPI_FAILURE (Status))1016{1017return_ACPI_STATUS (Status);1018}10191020Status = AcpiHwEnableAllRuntimeGpes ();1021(void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);10221023return_ACPI_STATUS (Status);1024}10251026ACPI_EXPORT_SYMBOL (AcpiEnableAllRuntimeGpes)102710281029/******************************************************************************1030*1031* FUNCTION: AcpiEnableAllWakeupGpes1032*1033* PARAMETERS: None1034*1035* RETURN: Status1036*1037* DESCRIPTION: Enable all "wakeup" GPEs and disable all of the other GPEs, in1038* all GPE blocks.1039*1040******************************************************************************/10411042ACPI_STATUS1043AcpiEnableAllWakeupGpes (1044void)1045{1046ACPI_STATUS Status;104710481049ACPI_FUNCTION_TRACE (AcpiEnableAllWakeupGpes);105010511052Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);1053if (ACPI_FAILURE (Status))1054{1055return_ACPI_STATUS (Status);1056}10571058Status = AcpiHwEnableAllWakeupGpes ();1059(void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);10601061return_ACPI_STATUS (Status);1062}10631064ACPI_EXPORT_SYMBOL (AcpiEnableAllWakeupGpes)106510661067/******************************************************************************1068*1069* FUNCTION: AcpiAnyGpeStatusSet1070*1071* PARAMETERS: None1072*1073* RETURN: Whether or not the status bit is set for any GPE1074*1075* DESCRIPTION: Check the status bits of all enabled GPEs and return TRUE if any1076* of them is set or FALSE otherwise.1077*1078******************************************************************************/10791080UINT321081AcpiAnyGpeStatusSet (1082void)1083{1084ACPI_STATUS Status;1085UINT8 Ret;108610871088ACPI_FUNCTION_TRACE (AcpiAnyGpeStatusSet);10891090Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);1091if (ACPI_FAILURE (Status))1092{1093return (FALSE);1094}10951096Ret = AcpiHwCheckAllGpes ();1097(void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);10981099return (Ret);1100}11011102ACPI_EXPORT_SYMBOL(AcpiAnyGpeStatusSet)110311041105/*******************************************************************************1106*1107* FUNCTION: AcpiInstallGpeBlock1108*1109* PARAMETERS: GpeDevice - Handle to the parent GPE Block Device1110* GpeBlockAddress - Address and SpaceID1111* RegisterCount - Number of GPE register pairs in the block1112* InterruptNumber - H/W interrupt for the block1113*1114* RETURN: Status1115*1116* DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not1117* enabled here.1118*1119******************************************************************************/11201121ACPI_STATUS1122AcpiInstallGpeBlock (1123ACPI_HANDLE GpeDevice,1124ACPI_GENERIC_ADDRESS *GpeBlockAddress,1125UINT32 RegisterCount,1126UINT32 InterruptNumber)1127{1128ACPI_STATUS Status;1129ACPI_OPERAND_OBJECT *ObjDesc;1130ACPI_NAMESPACE_NODE *Node;1131ACPI_GPE_BLOCK_INFO *GpeBlock;113211331134ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock);113511361137if ((!GpeDevice) ||1138(!GpeBlockAddress) ||1139(!RegisterCount))1140{1141return_ACPI_STATUS (AE_BAD_PARAMETER);1142}11431144Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);1145if (ACPI_FAILURE (Status))1146{1147return_ACPI_STATUS (Status);1148}11491150Node = AcpiNsValidateHandle (GpeDevice);1151if (!Node)1152{1153Status = AE_BAD_PARAMETER;1154goto UnlockAndExit;1155}11561157/* Validate the parent device */11581159if (Node->Type != ACPI_TYPE_DEVICE)1160{1161Status = AE_TYPE;1162goto UnlockAndExit;1163}11641165if (Node->Object)1166{1167Status = AE_ALREADY_EXISTS;1168goto UnlockAndExit;1169}11701171/*1172* For user-installed GPE Block Devices, the GpeBlockBaseNumber1173* is always zero1174*/1175Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress->Address,1176GpeBlockAddress->SpaceId, RegisterCount,11770, InterruptNumber, &GpeBlock);1178if (ACPI_FAILURE (Status))1179{1180goto UnlockAndExit;1181}11821183/* Install block in the DeviceObject attached to the node */11841185ObjDesc = AcpiNsGetAttachedObject (Node);1186if (!ObjDesc)1187{1188/*1189* No object, create a new one (Device nodes do not always have1190* an attached object)1191*/1192ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE);1193if (!ObjDesc)1194{1195Status = AE_NO_MEMORY;1196goto UnlockAndExit;1197}11981199Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE);12001201/* Remove local reference to the object */12021203AcpiUtRemoveReference (ObjDesc);1204if (ACPI_FAILURE (Status))1205{1206goto UnlockAndExit;1207}1208}12091210/* Now install the GPE block in the DeviceObject */12111212ObjDesc->Device.GpeBlock = GpeBlock;121312141215UnlockAndExit:1216(void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);1217return_ACPI_STATUS (Status);1218}12191220ACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock)122112221223/*******************************************************************************1224*1225* FUNCTION: AcpiRemoveGpeBlock1226*1227* PARAMETERS: GpeDevice - Handle to the parent GPE Block Device1228*1229* RETURN: Status1230*1231* DESCRIPTION: Remove a previously installed block of GPE registers1232*1233******************************************************************************/12341235ACPI_STATUS1236AcpiRemoveGpeBlock (1237ACPI_HANDLE GpeDevice)1238{1239ACPI_OPERAND_OBJECT *ObjDesc;1240ACPI_STATUS Status;1241ACPI_NAMESPACE_NODE *Node;124212431244ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock);124512461247if (!GpeDevice)1248{1249return_ACPI_STATUS (AE_BAD_PARAMETER);1250}12511252Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);1253if (ACPI_FAILURE (Status))1254{1255return_ACPI_STATUS (Status);1256}12571258Node = AcpiNsValidateHandle (GpeDevice);1259if (!Node)1260{1261Status = AE_BAD_PARAMETER;1262goto UnlockAndExit;1263}12641265/* Validate the parent device */12661267if (Node->Type != ACPI_TYPE_DEVICE)1268{1269Status = AE_TYPE;1270goto UnlockAndExit;1271}12721273/* Get the DeviceObject attached to the node */12741275ObjDesc = AcpiNsGetAttachedObject (Node);1276if (!ObjDesc ||1277!ObjDesc->Device.GpeBlock)1278{1279return_ACPI_STATUS (AE_NULL_OBJECT);1280}12811282/* Delete the GPE block (but not the DeviceObject) */12831284Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock);1285if (ACPI_SUCCESS (Status))1286{1287ObjDesc->Device.GpeBlock = NULL;1288}12891290UnlockAndExit:1291(void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);1292return_ACPI_STATUS (Status);1293}12941295ACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock)129612971298/*******************************************************************************1299*1300* FUNCTION: AcpiGetGpeDevice1301*1302* PARAMETERS: Index - System GPE index (0-CurrentGpeCount)1303* GpeDevice - Where the parent GPE Device is returned1304*1305* RETURN: Status1306*1307* DESCRIPTION: Obtain the GPE device associated with the input index. A NULL1308* gpe device indicates that the gpe number is contained in one of1309* the FADT-defined gpe blocks. Otherwise, the GPE block device.1310*1311******************************************************************************/13121313ACPI_STATUS1314AcpiGetGpeDevice (1315UINT32 Index,1316ACPI_HANDLE *GpeDevice)1317{1318ACPI_GPE_DEVICE_INFO Info;1319ACPI_STATUS Status;132013211322ACPI_FUNCTION_TRACE (AcpiGetGpeDevice);132313241325if (!GpeDevice)1326{1327return_ACPI_STATUS (AE_BAD_PARAMETER);1328}13291330if (Index >= AcpiCurrentGpeCount)1331{1332return_ACPI_STATUS (AE_NOT_EXIST);1333}13341335/* Setup and walk the GPE list */13361337Info.Index = Index;1338Info.Status = AE_NOT_EXIST;1339Info.GpeDevice = NULL;1340Info.NextBlockBaseIndex = 0;13411342Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info);1343if (ACPI_FAILURE (Status))1344{1345return_ACPI_STATUS (Status);1346}13471348*GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice);1349return_ACPI_STATUS (Info.Status);1350}13511352ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice)13531354#endif /* !ACPI_REDUCED_HARDWARE */135513561357