/drivers/devman/acpica/events/evevent.c |
---|
0,0 → 1,430 |
/****************************************************************************** |
* |
* Module Name: evevent - Fixed Event handling and dispatch |
* |
*****************************************************************************/ |
/****************************************************************************** |
* |
* 1. Copyright Notice |
* |
* Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. |
* All rights reserved. |
* |
* 2. License |
* |
* 2.1. This is your license from Intel Corp. under its intellectual property |
* rights. You may have additional license terms from the party that provided |
* you this software, covering your right to use that party's intellectual |
* property rights. |
* |
* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a |
* copy of the source code appearing in this file ("Covered Code") an |
* irrevocable, perpetual, worldwide license under Intel's copyrights in the |
* base code distributed originally by Intel ("Original Intel Code") to copy, |
* make derivatives, distribute, use and display any portion of the Covered |
* Code in any form, with the right to sublicense such rights; and |
* |
* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent |
* license (with the right to sublicense), under only those claims of Intel |
* patents that are infringed by the Original Intel Code, to make, use, sell, |
* offer to sell, and import the Covered Code and derivative works thereof |
* solely to the minimum extent necessary to exercise the above copyright |
* license, and in no event shall the patent license extend to any additions |
* to or modifications of the Original Intel Code. No other license or right |
* is granted directly or by implication, estoppel or otherwise; |
* |
* The above copyright and patent license is granted only if the following |
* conditions are met: |
* |
* 3. Conditions |
* |
* 3.1. Redistribution of Source with Rights to Further Distribute Source. |
* Redistribution of source code of any substantial portion of the Covered |
* Code or modification with rights to further distribute source must include |
* the above Copyright Notice, the above License, this list of Conditions, |
* and the following Disclaimer and Export Compliance provision. In addition, |
* Licensee must cause all Covered Code to which Licensee contributes to |
* contain a file documenting the changes Licensee made to create that Covered |
* Code and the date of any change. Licensee must include in that file the |
* documentation of any changes made by any predecessor Licensee. Licensee |
* must include a prominent statement that the modification is derived, |
* directly or indirectly, from Original Intel Code. |
* |
* 3.2. Redistribution of Source with no Rights to Further Distribute Source. |
* Redistribution of source code of any substantial portion of the Covered |
* Code or modification without rights to further distribute source must |
* include the following Disclaimer and Export Compliance provision in the |
* documentation and/or other materials provided with distribution. In |
* addition, Licensee may not authorize further sublicense of source of any |
* portion of the Covered Code, and must include terms to the effect that the |
* license from Licensee to its licensee is limited to the intellectual |
* property embodied in the software Licensee provides to its licensee, and |
* not to intellectual property embodied in modifications its licensee may |
* make. |
* |
* 3.3. Redistribution of Executable. Redistribution in executable form of any |
* substantial portion of the Covered Code or modification must reproduce the |
* above Copyright Notice, and the following Disclaimer and Export Compliance |
* provision in the documentation and/or other materials provided with the |
* distribution. |
* |
* 3.4. Intel retains all right, title, and interest in and to the Original |
* Intel Code. |
* |
* 3.5. Neither the name Intel nor any other trademark owned or controlled by |
* Intel shall be used in advertising or otherwise to promote the sale, use or |
* other dealings in products derived from or relating to the Covered Code |
* without prior written authorization from Intel. |
* |
* 4. Disclaimer and Export Compliance |
* |
* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED |
* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE |
* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, |
* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY |
* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY |
* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A |
* PARTICULAR PURPOSE. |
* |
* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES |
* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR |
* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, |
* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY |
* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL |
* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS |
* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY |
* LIMITED REMEDY. |
* |
* 4.3. Licensee shall not export, either directly or indirectly, any of this |
* software or system incorporating such software without first obtaining any |
* required license or other approval from the U. S. Department of Commerce or |
* any other agency or department of the United States Government. In the |
* event Licensee exports any such software from the United States or |
* re-exports any such software from a foreign destination, Licensee shall |
* ensure that the distribution and export/re-export of the software is in |
* compliance with all laws, regulations, orders, or other restrictions of the |
* U.S. Export Administration Regulations. Licensee agrees that neither it nor |
* any of its subsidiaries will export/re-export any technical data, process, |
* software, or service, directly or indirectly, to any country for which the |
* United States government or any agency thereof requires an export license, |
* other governmental approval, or letter of assurance, without first obtaining |
* such license, approval or letter. |
* |
*****************************************************************************/ |
#include "acpi.h" |
#include "accommon.h" |
#include "acevents.h" |
#define _COMPONENT ACPI_EVENTS |
ACPI_MODULE_NAME ("evevent") |
/* Local prototypes */ |
static ACPI_STATUS |
AcpiEvFixedEventInitialize ( |
void); |
static UINT32 |
AcpiEvFixedEventDispatch ( |
UINT32 Event); |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvInitializeEvents |
* |
* PARAMETERS: None |
* |
* RETURN: Status |
* |
* DESCRIPTION: Initialize global data structures for ACPI events (Fixed, GPE) |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvInitializeEvents ( |
void) |
{ |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (EvInitializeEvents); |
/* |
* Initialize the Fixed and General Purpose Events. This is done prior to |
* enabling SCIs to prevent interrupts from occurring before the handlers |
* are installed. |
*/ |
Status = AcpiEvFixedEventInitialize (); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, |
"Unable to initialize fixed events")); |
return_ACPI_STATUS (Status); |
} |
Status = AcpiEvGpeInitialize (); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, |
"Unable to initialize general purpose events")); |
return_ACPI_STATUS (Status); |
} |
return_ACPI_STATUS (Status); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvInstallFadtGpes |
* |
* PARAMETERS: None |
* |
* RETURN: Status |
* |
* DESCRIPTION: Completes initialization of the FADT-defined GPE blocks |
* (0 and 1). This causes the _PRW methods to be run, so the HW |
* must be fully initialized at this point, including global lock |
* support. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvInstallFadtGpes ( |
void) |
{ |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (EvInstallFadtGpes); |
/* Namespace must be locked */ |
Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); |
if (ACPI_FAILURE (Status)) |
{ |
return (Status); |
} |
/* FADT GPE Block 0 */ |
(void) AcpiEvInitializeGpeBlock ( |
AcpiGbl_FadtGpeDevice, AcpiGbl_GpeFadtBlocks[0]); |
/* FADT GPE Block 1 */ |
(void) AcpiEvInitializeGpeBlock ( |
AcpiGbl_FadtGpeDevice, AcpiGbl_GpeFadtBlocks[1]); |
(void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); |
return_ACPI_STATUS (AE_OK); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvInstallXruptHandlers |
* |
* PARAMETERS: None |
* |
* RETURN: Status |
* |
* DESCRIPTION: Install interrupt handlers for the SCI and Global Lock |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvInstallXruptHandlers ( |
void) |
{ |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (EvInstallXruptHandlers); |
/* Install the SCI handler */ |
Status = AcpiEvInstallSciHandler (); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, |
"Unable to install System Control Interrupt handler")); |
return_ACPI_STATUS (Status); |
} |
/* Install the handler for the Global Lock */ |
Status = AcpiEvInitGlobalLockHandler (); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, |
"Unable to initialize Global Lock handler")); |
return_ACPI_STATUS (Status); |
} |
AcpiGbl_EventsInitialized = TRUE; |
return_ACPI_STATUS (Status); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvFixedEventInitialize |
* |
* PARAMETERS: None |
* |
* RETURN: Status |
* |
* DESCRIPTION: Install the fixed event handlers and disable all fixed events. |
* |
******************************************************************************/ |
static ACPI_STATUS |
AcpiEvFixedEventInitialize ( |
void) |
{ |
UINT32 i; |
ACPI_STATUS Status; |
/* |
* Initialize the structure that keeps track of fixed event handlers and |
* enable the fixed events. |
*/ |
for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) |
{ |
AcpiGbl_FixedEventHandlers[i].Handler = NULL; |
AcpiGbl_FixedEventHandlers[i].Context = NULL; |
/* Disable the fixed event */ |
if (AcpiGbl_FixedEventInfo[i].EnableRegisterId != 0xFF) |
{ |
Status = AcpiWriteBitRegister ( |
AcpiGbl_FixedEventInfo[i].EnableRegisterId, |
ACPI_DISABLE_EVENT); |
if (ACPI_FAILURE (Status)) |
{ |
return (Status); |
} |
} |
} |
return (AE_OK); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvFixedEventDetect |
* |
* PARAMETERS: None |
* |
* RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED |
* |
* DESCRIPTION: Checks the PM status register for active fixed events |
* |
******************************************************************************/ |
UINT32 |
AcpiEvFixedEventDetect ( |
void) |
{ |
UINT32 IntStatus = ACPI_INTERRUPT_NOT_HANDLED; |
UINT32 FixedStatus; |
UINT32 FixedEnable; |
UINT32 i; |
ACPI_FUNCTION_NAME (EvFixedEventDetect); |
/* |
* Read the fixed feature status and enable registers, as all the cases |
* depend on their values. Ignore errors here. |
*/ |
(void) AcpiHwRegisterRead (ACPI_REGISTER_PM1_STATUS, &FixedStatus); |
(void) AcpiHwRegisterRead (ACPI_REGISTER_PM1_ENABLE, &FixedEnable); |
ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, |
"Fixed Event Block: Enable %08X Status %08X\n", |
FixedEnable, FixedStatus)); |
/* |
* Check for all possible Fixed Events and dispatch those that are active |
*/ |
for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) |
{ |
/* Both the status and enable bits must be on for this event */ |
if ((FixedStatus & AcpiGbl_FixedEventInfo[i].StatusBitMask) && |
(FixedEnable & AcpiGbl_FixedEventInfo[i].EnableBitMask)) |
{ |
/* Found an active (signalled) event */ |
AcpiFixedEventCount[i]++; |
IntStatus |= AcpiEvFixedEventDispatch (i); |
} |
} |
return (IntStatus); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvFixedEventDispatch |
* |
* PARAMETERS: Event - Event type |
* |
* RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED |
* |
* DESCRIPTION: Clears the status bit for the requested event, calls the |
* handler that previously registered for the event. |
* |
******************************************************************************/ |
static UINT32 |
AcpiEvFixedEventDispatch ( |
UINT32 Event) |
{ |
ACPI_FUNCTION_ENTRY (); |
/* Clear the status bit */ |
(void) AcpiWriteBitRegister ( |
AcpiGbl_FixedEventInfo[Event].StatusRegisterId, |
ACPI_CLEAR_STATUS); |
/* |
* Make sure we've got a handler. If not, report an error. The event is |
* disabled to prevent further interrupts. |
*/ |
if (NULL == AcpiGbl_FixedEventHandlers[Event].Handler) |
{ |
(void) AcpiWriteBitRegister ( |
AcpiGbl_FixedEventInfo[Event].EnableRegisterId, |
ACPI_DISABLE_EVENT); |
ACPI_ERROR ((AE_INFO, |
"No installed handler for fixed event [0x%08X]", |
Event)); |
return (ACPI_INTERRUPT_NOT_HANDLED); |
} |
/* Invoke the Fixed Event handler */ |
return ((AcpiGbl_FixedEventHandlers[Event].Handler)( |
AcpiGbl_FixedEventHandlers[Event].Context)); |
} |
/drivers/devman/acpica/events/evgpe.c |
---|
0,0 → 1,824 |
/****************************************************************************** |
* |
* Module Name: evgpe - General Purpose Event handling and dispatch |
* |
*****************************************************************************/ |
/****************************************************************************** |
* |
* 1. Copyright Notice |
* |
* Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. |
* All rights reserved. |
* |
* 2. License |
* |
* 2.1. This is your license from Intel Corp. under its intellectual property |
* rights. You may have additional license terms from the party that provided |
* you this software, covering your right to use that party's intellectual |
* property rights. |
* |
* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a |
* copy of the source code appearing in this file ("Covered Code") an |
* irrevocable, perpetual, worldwide license under Intel's copyrights in the |
* base code distributed originally by Intel ("Original Intel Code") to copy, |
* make derivatives, distribute, use and display any portion of the Covered |
* Code in any form, with the right to sublicense such rights; and |
* |
* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent |
* license (with the right to sublicense), under only those claims of Intel |
* patents that are infringed by the Original Intel Code, to make, use, sell, |
* offer to sell, and import the Covered Code and derivative works thereof |
* solely to the minimum extent necessary to exercise the above copyright |
* license, and in no event shall the patent license extend to any additions |
* to or modifications of the Original Intel Code. No other license or right |
* is granted directly or by implication, estoppel or otherwise; |
* |
* The above copyright and patent license is granted only if the following |
* conditions are met: |
* |
* 3. Conditions |
* |
* 3.1. Redistribution of Source with Rights to Further Distribute Source. |
* Redistribution of source code of any substantial portion of the Covered |
* Code or modification with rights to further distribute source must include |
* the above Copyright Notice, the above License, this list of Conditions, |
* and the following Disclaimer and Export Compliance provision. In addition, |
* Licensee must cause all Covered Code to which Licensee contributes to |
* contain a file documenting the changes Licensee made to create that Covered |
* Code and the date of any change. Licensee must include in that file the |
* documentation of any changes made by any predecessor Licensee. Licensee |
* must include a prominent statement that the modification is derived, |
* directly or indirectly, from Original Intel Code. |
* |
* 3.2. Redistribution of Source with no Rights to Further Distribute Source. |
* Redistribution of source code of any substantial portion of the Covered |
* Code or modification without rights to further distribute source must |
* include the following Disclaimer and Export Compliance provision in the |
* documentation and/or other materials provided with distribution. In |
* addition, Licensee may not authorize further sublicense of source of any |
* portion of the Covered Code, and must include terms to the effect that the |
* license from Licensee to its licensee is limited to the intellectual |
* property embodied in the software Licensee provides to its licensee, and |
* not to intellectual property embodied in modifications its licensee may |
* make. |
* |
* 3.3. Redistribution of Executable. Redistribution in executable form of any |
* substantial portion of the Covered Code or modification must reproduce the |
* above Copyright Notice, and the following Disclaimer and Export Compliance |
* provision in the documentation and/or other materials provided with the |
* distribution. |
* |
* 3.4. Intel retains all right, title, and interest in and to the Original |
* Intel Code. |
* |
* 3.5. Neither the name Intel nor any other trademark owned or controlled by |
* Intel shall be used in advertising or otherwise to promote the sale, use or |
* other dealings in products derived from or relating to the Covered Code |
* without prior written authorization from Intel. |
* |
* 4. Disclaimer and Export Compliance |
* |
* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED |
* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE |
* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, |
* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY |
* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY |
* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A |
* PARTICULAR PURPOSE. |
* |
* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES |
* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR |
* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, |
* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY |
* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL |
* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS |
* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY |
* LIMITED REMEDY. |
* |
* 4.3. Licensee shall not export, either directly or indirectly, any of this |
* software or system incorporating such software without first obtaining any |
* required license or other approval from the U. S. Department of Commerce or |
* any other agency or department of the United States Government. In the |
* event Licensee exports any such software from the United States or |
* re-exports any such software from a foreign destination, Licensee shall |
* ensure that the distribution and export/re-export of the software is in |
* compliance with all laws, regulations, orders, or other restrictions of the |
* U.S. Export Administration Regulations. Licensee agrees that neither it nor |
* any of its subsidiaries will export/re-export any technical data, process, |
* software, or service, directly or indirectly, to any country for which the |
* United States government or any agency thereof requires an export license, |
* other governmental approval, or letter of assurance, without first obtaining |
* such license, approval or letter. |
* |
*****************************************************************************/ |
#include "acpi.h" |
#include "accommon.h" |
#include "acevents.h" |
#include "acnamesp.h" |
#define _COMPONENT ACPI_EVENTS |
ACPI_MODULE_NAME ("evgpe") |
/* Local prototypes */ |
static void ACPI_SYSTEM_XFACE |
AcpiEvAsynchExecuteGpeMethod ( |
void *Context); |
static void ACPI_SYSTEM_XFACE |
AcpiEvAsynchEnableGpe ( |
void *Context); |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvUpdateGpeEnableMasks |
* |
* PARAMETERS: GpeEventInfo - GPE to update |
* |
* RETURN: Status |
* |
* DESCRIPTION: Updates GPE register enable masks based upon whether there are |
* references (either wake or run) to this GPE |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvUpdateGpeEnableMasks ( |
ACPI_GPE_EVENT_INFO *GpeEventInfo) |
{ |
ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; |
UINT8 RegisterBit; |
ACPI_FUNCTION_TRACE (EvUpdateGpeEnableMasks); |
GpeRegisterInfo = GpeEventInfo->RegisterInfo; |
if (!GpeRegisterInfo) |
{ |
return_ACPI_STATUS (AE_NOT_EXIST); |
} |
RegisterBit = (UINT8) |
(1 << (GpeEventInfo->GpeNumber - GpeRegisterInfo->BaseGpeNumber)); |
/* Clear the wake/run bits up front */ |
ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, RegisterBit); |
ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForRun, RegisterBit); |
/* Set the mask bits only if there are references to this GPE */ |
if (GpeEventInfo->RuntimeCount) |
{ |
ACPI_SET_BIT (GpeRegisterInfo->EnableForRun, RegisterBit); |
} |
if (GpeEventInfo->WakeupCount) |
{ |
ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, RegisterBit); |
} |
return_ACPI_STATUS (AE_OK); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvEnableGpe |
* |
* PARAMETERS: GpeEventInfo - GPE to enable |
* |
* RETURN: Status |
* |
* DESCRIPTION: Hardware-enable a GPE. Always enables the GPE, regardless |
* of type or number of references. |
* |
* Note: The GPE lock should be already acquired when this function is called. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvEnableGpe ( |
ACPI_GPE_EVENT_INFO *GpeEventInfo) |
{ |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (EvEnableGpe); |
/* |
* We will only allow a GPE to be enabled if it has either an |
* associated method (_Lxx/_Exx) or a handler. Otherwise, the |
* GPE will be immediately disabled by AcpiEvGpeDispatch the |
* first time it fires. |
*/ |
if (!(GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK)) |
{ |
return_ACPI_STATUS (AE_NO_HANDLER); |
} |
/* Ensure the HW enable masks are current */ |
Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
/* Clear the GPE (of stale events) */ |
Status = AcpiHwClearGpe (GpeEventInfo); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
/* Enable the requested GPE */ |
Status = AcpiHwWriteGpeEnableReg (GpeEventInfo); |
return_ACPI_STATUS (Status); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvDisableGpe |
* |
* PARAMETERS: GpeEventInfo - GPE to disable |
* |
* RETURN: Status |
* |
* DESCRIPTION: Hardware-disable a GPE. Always disables the requested GPE, |
* regardless of the type or number of references. |
* |
* Note: The GPE lock should be already acquired when this function is called. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvDisableGpe ( |
ACPI_GPE_EVENT_INFO *GpeEventInfo) |
{ |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (EvDisableGpe); |
/* |
* Note: Always disable the GPE, even if we think that that it is already |
* disabled. It is possible that the AML or some other code has enabled |
* the GPE behind our back. |
*/ |
/* Ensure the HW enable masks are current */ |
Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
/* |
* Always H/W disable this GPE, even if we don't know the GPE type. |
* Simply clear the enable bit for this particular GPE, but do not |
* write out the current GPE enable mask since this may inadvertently |
* enable GPEs too early. An example is a rogue GPE that has arrived |
* during ACPICA initialization - possibly because AML or other code |
* has enabled the GPE. |
*/ |
Status = AcpiHwLowDisableGpe (GpeEventInfo); |
return_ACPI_STATUS (Status); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvLowGetGpeInfo |
* |
* PARAMETERS: GpeNumber - Raw GPE number |
* GpeBlock - A GPE info block |
* |
* RETURN: A GPE EventInfo struct. NULL if not a valid GPE (The GpeNumber |
* is not within the specified GPE block) |
* |
* DESCRIPTION: Returns the EventInfo struct associated with this GPE. This is |
* the low-level implementation of EvGetGpeEventInfo. |
* |
******************************************************************************/ |
ACPI_GPE_EVENT_INFO * |
AcpiEvLowGetGpeInfo ( |
UINT32 GpeNumber, |
ACPI_GPE_BLOCK_INFO *GpeBlock) |
{ |
UINT32 GpeIndex; |
/* |
* Validate that the GpeNumber is within the specified GpeBlock. |
* (Two steps) |
*/ |
if (!GpeBlock || |
(GpeNumber < GpeBlock->BlockBaseNumber)) |
{ |
return (NULL); |
} |
GpeIndex = GpeNumber - GpeBlock->BlockBaseNumber; |
if (GpeIndex >= GpeBlock->GpeCount) |
{ |
return (NULL); |
} |
return (&GpeBlock->EventInfo[GpeIndex]); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvGetGpeEventInfo |
* |
* PARAMETERS: GpeDevice - Device node. NULL for GPE0/GPE1 |
* GpeNumber - Raw GPE number |
* |
* RETURN: A GPE EventInfo struct. NULL if not a valid GPE |
* |
* DESCRIPTION: Returns the EventInfo struct associated with this GPE. |
* Validates the GpeBlock and the GpeNumber |
* |
* Should be called only when the GPE lists are semaphore locked |
* and not subject to change. |
* |
******************************************************************************/ |
ACPI_GPE_EVENT_INFO * |
AcpiEvGetGpeEventInfo ( |
ACPI_HANDLE GpeDevice, |
UINT32 GpeNumber) |
{ |
ACPI_OPERAND_OBJECT *ObjDesc; |
ACPI_GPE_EVENT_INFO *GpeInfo; |
UINT32 i; |
ACPI_FUNCTION_ENTRY (); |
/* A NULL GpeDevice means use the FADT-defined GPE block(s) */ |
if (!GpeDevice) |
{ |
/* Examine GPE Block 0 and 1 (These blocks are permanent) */ |
for (i = 0; i < ACPI_MAX_GPE_BLOCKS; i++) |
{ |
GpeInfo = AcpiEvLowGetGpeInfo (GpeNumber, |
AcpiGbl_GpeFadtBlocks[i]); |
if (GpeInfo) |
{ |
return (GpeInfo); |
} |
} |
/* The GpeNumber was not in the range of either FADT GPE block */ |
return (NULL); |
} |
/* A Non-NULL GpeDevice means this is a GPE Block Device */ |
ObjDesc = AcpiNsGetAttachedObject ((ACPI_NAMESPACE_NODE *) GpeDevice); |
if (!ObjDesc || |
!ObjDesc->Device.GpeBlock) |
{ |
return (NULL); |
} |
return (AcpiEvLowGetGpeInfo (GpeNumber, ObjDesc->Device.GpeBlock)); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvGpeDetect |
* |
* PARAMETERS: GpeXruptList - Interrupt block for this interrupt. |
* Can have multiple GPE blocks attached. |
* |
* RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED |
* |
* DESCRIPTION: Detect if any GP events have occurred. This function is |
* executed at interrupt level. |
* |
******************************************************************************/ |
UINT32 |
AcpiEvGpeDetect ( |
ACPI_GPE_XRUPT_INFO *GpeXruptList) |
{ |
ACPI_STATUS Status; |
ACPI_GPE_BLOCK_INFO *GpeBlock; |
ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; |
UINT32 IntStatus = ACPI_INTERRUPT_NOT_HANDLED; |
UINT8 EnabledStatusByte; |
UINT32 StatusReg; |
UINT32 EnableReg; |
ACPI_CPU_FLAGS Flags; |
UINT32 i; |
UINT32 j; |
ACPI_FUNCTION_NAME (EvGpeDetect); |
/* Check for the case where there are no GPEs */ |
if (!GpeXruptList) |
{ |
return (IntStatus); |
} |
/* |
* We need to obtain the GPE lock for both the data structs and registers |
* Note: Not necessary to obtain the hardware lock, since the GPE |
* registers are owned by the GpeLock. |
*/ |
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
/* Examine all GPE blocks attached to this interrupt level */ |
GpeBlock = GpeXruptList->GpeBlockListHead; |
while (GpeBlock) |
{ |
/* |
* Read all of the 8-bit GPE status and enable registers in this GPE |
* block, saving all of them. Find all currently active GP events. |
*/ |
for (i = 0; i < GpeBlock->RegisterCount; i++) |
{ |
/* Get the next status/enable pair */ |
GpeRegisterInfo = &GpeBlock->RegisterInfo[i]; |
/* Read the Status Register */ |
Status = AcpiHwRead (&StatusReg, &GpeRegisterInfo->StatusAddress); |
if (ACPI_FAILURE (Status)) |
{ |
goto UnlockAndExit; |
} |
/* Read the Enable Register */ |
Status = AcpiHwRead (&EnableReg, &GpeRegisterInfo->EnableAddress); |
if (ACPI_FAILURE (Status)) |
{ |
goto UnlockAndExit; |
} |
ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, |
"Read GPE Register at GPE%X: Status=%02X, Enable=%02X\n", |
GpeRegisterInfo->BaseGpeNumber, StatusReg, EnableReg)); |
/* Check if there is anything active at all in this register */ |
EnabledStatusByte = (UINT8) (StatusReg & EnableReg); |
if (!EnabledStatusByte) |
{ |
/* No active GPEs in this register, move on */ |
continue; |
} |
/* Now look at the individual GPEs in this byte register */ |
for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) |
{ |
/* Examine one GPE bit */ |
if (EnabledStatusByte & (1 << j)) |
{ |
/* |
* Found an active GPE. Dispatch the event to a handler |
* or method. |
*/ |
IntStatus |= AcpiEvGpeDispatch ( |
&GpeBlock->EventInfo[((ACPI_SIZE) i * |
ACPI_GPE_REGISTER_WIDTH) + j], |
j + GpeRegisterInfo->BaseGpeNumber); |
} |
} |
} |
GpeBlock = GpeBlock->Next; |
} |
UnlockAndExit: |
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
return (IntStatus); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvAsynchExecuteGpeMethod |
* |
* PARAMETERS: Context (GpeEventInfo) - Info for this GPE |
* |
* RETURN: None |
* |
* DESCRIPTION: Perform the actual execution of a GPE control method. This |
* function is called from an invocation of AcpiOsExecute and |
* therefore does NOT execute at interrupt level - so that |
* the control method itself is not executed in the context of |
* an interrupt handler. |
* |
******************************************************************************/ |
static void ACPI_SYSTEM_XFACE |
AcpiEvAsynchExecuteGpeMethod ( |
void *Context) |
{ |
ACPI_GPE_EVENT_INFO *GpeEventInfo = Context; |
ACPI_STATUS Status; |
ACPI_GPE_EVENT_INFO *LocalGpeEventInfo; |
ACPI_EVALUATE_INFO *Info; |
ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod); |
/* Allocate a local GPE block */ |
LocalGpeEventInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_EVENT_INFO)); |
if (!LocalGpeEventInfo) |
{ |
ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY, |
"while handling a GPE")); |
return_VOID; |
} |
Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); |
if (ACPI_FAILURE (Status)) |
{ |
return_VOID; |
} |
/* Must revalidate the GpeNumber/GpeBlock */ |
if (!AcpiEvValidGpeEvent (GpeEventInfo)) |
{ |
Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
return_VOID; |
} |
/* Update the GPE register masks for return to enabled state */ |
(void) AcpiEvUpdateGpeEnableMasks (GpeEventInfo); |
/* |
* Take a snapshot of the GPE info for this level - we copy the info to |
* prevent a race condition with RemoveHandler/RemoveBlock. |
*/ |
ACPI_MEMCPY (LocalGpeEventInfo, GpeEventInfo, |
sizeof (ACPI_GPE_EVENT_INFO)); |
Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
if (ACPI_FAILURE (Status)) |
{ |
return_VOID; |
} |
/* |
* Must check for control method type dispatch one more time to avoid a |
* race with EvGpeInstallHandler |
*/ |
if ((LocalGpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == |
ACPI_GPE_DISPATCH_METHOD) |
{ |
/* Allocate the evaluation information block */ |
Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); |
if (!Info) |
{ |
Status = AE_NO_MEMORY; |
} |
else |
{ |
/* |
* Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx |
* control method that corresponds to this GPE |
*/ |
Info->PrefixNode = LocalGpeEventInfo->Dispatch.MethodNode; |
Info->Flags = ACPI_IGNORE_RETURN_VALUE; |
Status = AcpiNsEvaluate (Info); |
ACPI_FREE (Info); |
} |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, |
"while evaluating GPE method [%4.4s]", |
AcpiUtGetNodeName (LocalGpeEventInfo->Dispatch.MethodNode))); |
} |
} |
/* Defer enabling of GPE until all notify handlers are done */ |
Status = AcpiOsExecute (OSL_NOTIFY_HANDLER, |
AcpiEvAsynchEnableGpe, LocalGpeEventInfo); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_FREE (LocalGpeEventInfo); |
} |
return_VOID; |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvAsynchEnableGpe |
* |
* PARAMETERS: Context (GpeEventInfo) - Info for this GPE |
* |
* RETURN: None |
* |
* DESCRIPTION: Asynchronous clear/enable for GPE. This allows the GPE to |
* complete (i.e., finish execution of Notify) |
* |
******************************************************************************/ |
static void ACPI_SYSTEM_XFACE |
AcpiEvAsynchEnableGpe ( |
void *Context) |
{ |
ACPI_GPE_EVENT_INFO *GpeEventInfo = Context; |
ACPI_STATUS Status; |
if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) == |
ACPI_GPE_LEVEL_TRIGGERED) |
{ |
/* |
* GPE is level-triggered, we clear the GPE status bit after handling |
* the event. |
*/ |
Status = AcpiHwClearGpe (GpeEventInfo); |
if (ACPI_FAILURE (Status)) |
{ |
goto Exit; |
} |
} |
/* Enable this GPE */ |
(void) AcpiHwWriteGpeEnableReg (GpeEventInfo); |
Exit: |
ACPI_FREE (GpeEventInfo); |
return; |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvGpeDispatch |
* |
* PARAMETERS: GpeEventInfo - Info for this GPE |
* GpeNumber - Number relative to the parent GPE block |
* |
* RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED |
* |
* DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC) |
* or method (e.g. _Lxx/_Exx) handler. |
* |
* This function executes at interrupt level. |
* |
******************************************************************************/ |
UINT32 |
AcpiEvGpeDispatch ( |
ACPI_GPE_EVENT_INFO *GpeEventInfo, |
UINT32 GpeNumber) |
{ |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (EvGpeDispatch); |
AcpiGpeCount++; |
/* |
* If edge-triggered, clear the GPE status bit now. Note that |
* level-triggered events are cleared after the GPE is serviced. |
*/ |
if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) == |
ACPI_GPE_EDGE_TRIGGERED) |
{ |
Status = AcpiHwClearGpe (GpeEventInfo); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, |
"Unable to clear GPE[0x%2X]", GpeNumber)); |
return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); |
} |
} |
/* |
* Dispatch the GPE to either an installed handler, or the control method |
* associated with this GPE (_Lxx or _Exx). If a handler exists, we invoke |
* it and do not attempt to run the method. If there is neither a handler |
* nor a method, we disable this GPE to prevent further such pointless |
* events from firing. |
*/ |
switch (GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) |
{ |
case ACPI_GPE_DISPATCH_HANDLER: |
/* |
* Invoke the installed handler (at interrupt level) |
* Ignore return status for now. |
* TBD: leave GPE disabled on error? |
*/ |
(void) GpeEventInfo->Dispatch.Handler->Address ( |
GpeEventInfo->Dispatch.Handler->Context); |
/* It is now safe to clear level-triggered events. */ |
if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) == |
ACPI_GPE_LEVEL_TRIGGERED) |
{ |
Status = AcpiHwClearGpe (GpeEventInfo); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, |
"Unable to clear GPE[0x%2X]", GpeNumber)); |
return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); |
} |
} |
break; |
case ACPI_GPE_DISPATCH_METHOD: |
/* |
* Disable the GPE, so it doesn't keep firing before the method has a |
* chance to run (it runs asynchronously with interrupts enabled). |
*/ |
Status = AcpiEvDisableGpe (GpeEventInfo); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, |
"Unable to disable GPE[0x%2X]", GpeNumber)); |
return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); |
} |
/* |
* Execute the method associated with the GPE |
* NOTE: Level-triggered GPEs are cleared after the method completes. |
*/ |
Status = AcpiOsExecute (OSL_GPE_HANDLER, |
AcpiEvAsynchExecuteGpeMethod, GpeEventInfo); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, |
"Unable to queue handler for GPE[0x%2X] - event disabled", |
GpeNumber)); |
} |
break; |
default: |
/* |
* No handler or method to run! |
* 03/2010: This case should no longer be possible. We will not allow |
* a GPE to be enabled if it has no handler or method. |
*/ |
ACPI_ERROR ((AE_INFO, |
"No handler or method for GPE[0x%2X], disabling event", |
GpeNumber)); |
/* |
* Disable the GPE. The GPE will remain disabled a handler |
* is installed or ACPICA is restarted. |
*/ |
Status = AcpiEvDisableGpe (GpeEventInfo); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, |
"Unable to disable GPE[0x%2X]", GpeNumber)); |
return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); |
} |
break; |
} |
return_UINT32 (ACPI_INTERRUPT_HANDLED); |
} |
/drivers/devman/acpica/events/evgpeblk.c |
---|
0,0 → 1,660 |
/****************************************************************************** |
* |
* Module Name: evgpeblk - GPE block creation and initialization. |
* |
*****************************************************************************/ |
/****************************************************************************** |
* |
* 1. Copyright Notice |
* |
* Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. |
* All rights reserved. |
* |
* 2. License |
* |
* 2.1. This is your license from Intel Corp. under its intellectual property |
* rights. You may have additional license terms from the party that provided |
* you this software, covering your right to use that party's intellectual |
* property rights. |
* |
* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a |
* copy of the source code appearing in this file ("Covered Code") an |
* irrevocable, perpetual, worldwide license under Intel's copyrights in the |
* base code distributed originally by Intel ("Original Intel Code") to copy, |
* make derivatives, distribute, use and display any portion of the Covered |
* Code in any form, with the right to sublicense such rights; and |
* |
* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent |
* license (with the right to sublicense), under only those claims of Intel |
* patents that are infringed by the Original Intel Code, to make, use, sell, |
* offer to sell, and import the Covered Code and derivative works thereof |
* solely to the minimum extent necessary to exercise the above copyright |
* license, and in no event shall the patent license extend to any additions |
* to or modifications of the Original Intel Code. No other license or right |
* is granted directly or by implication, estoppel or otherwise; |
* |
* The above copyright and patent license is granted only if the following |
* conditions are met: |
* |
* 3. Conditions |
* |
* 3.1. Redistribution of Source with Rights to Further Distribute Source. |
* Redistribution of source code of any substantial portion of the Covered |
* Code or modification with rights to further distribute source must include |
* the above Copyright Notice, the above License, this list of Conditions, |
* and the following Disclaimer and Export Compliance provision. In addition, |
* Licensee must cause all Covered Code to which Licensee contributes to |
* contain a file documenting the changes Licensee made to create that Covered |
* Code and the date of any change. Licensee must include in that file the |
* documentation of any changes made by any predecessor Licensee. Licensee |
* must include a prominent statement that the modification is derived, |
* directly or indirectly, from Original Intel Code. |
* |
* 3.2. Redistribution of Source with no Rights to Further Distribute Source. |
* Redistribution of source code of any substantial portion of the Covered |
* Code or modification without rights to further distribute source must |
* include the following Disclaimer and Export Compliance provision in the |
* documentation and/or other materials provided with distribution. In |
* addition, Licensee may not authorize further sublicense of source of any |
* portion of the Covered Code, and must include terms to the effect that the |
* license from Licensee to its licensee is limited to the intellectual |
* property embodied in the software Licensee provides to its licensee, and |
* not to intellectual property embodied in modifications its licensee may |
* make. |
* |
* 3.3. Redistribution of Executable. Redistribution in executable form of any |
* substantial portion of the Covered Code or modification must reproduce the |
* above Copyright Notice, and the following Disclaimer and Export Compliance |
* provision in the documentation and/or other materials provided with the |
* distribution. |
* |
* 3.4. Intel retains all right, title, and interest in and to the Original |
* Intel Code. |
* |
* 3.5. Neither the name Intel nor any other trademark owned or controlled by |
* Intel shall be used in advertising or otherwise to promote the sale, use or |
* other dealings in products derived from or relating to the Covered Code |
* without prior written authorization from Intel. |
* |
* 4. Disclaimer and Export Compliance |
* |
* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED |
* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE |
* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, |
* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY |
* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY |
* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A |
* PARTICULAR PURPOSE. |
* |
* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES |
* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR |
* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, |
* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY |
* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL |
* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS |
* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY |
* LIMITED REMEDY. |
* |
* 4.3. Licensee shall not export, either directly or indirectly, any of this |
* software or system incorporating such software without first obtaining any |
* required license or other approval from the U. S. Department of Commerce or |
* any other agency or department of the United States Government. In the |
* event Licensee exports any such software from the United States or |
* re-exports any such software from a foreign destination, Licensee shall |
* ensure that the distribution and export/re-export of the software is in |
* compliance with all laws, regulations, orders, or other restrictions of the |
* U.S. Export Administration Regulations. Licensee agrees that neither it nor |
* any of its subsidiaries will export/re-export any technical data, process, |
* software, or service, directly or indirectly, to any country for which the |
* United States government or any agency thereof requires an export license, |
* other governmental approval, or letter of assurance, without first obtaining |
* such license, approval or letter. |
* |
*****************************************************************************/ |
#include "acpi.h" |
#include "accommon.h" |
#include "acevents.h" |
#include "acnamesp.h" |
#define _COMPONENT ACPI_EVENTS |
ACPI_MODULE_NAME ("evgpeblk") |
/* Local prototypes */ |
static ACPI_STATUS |
AcpiEvInstallGpeBlock ( |
ACPI_GPE_BLOCK_INFO *GpeBlock, |
UINT32 InterruptNumber); |
static ACPI_STATUS |
AcpiEvCreateGpeInfoBlocks ( |
ACPI_GPE_BLOCK_INFO *GpeBlock); |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvInstallGpeBlock |
* |
* PARAMETERS: GpeBlock - New GPE block |
* InterruptNumber - Xrupt to be associated with this |
* GPE block |
* |
* RETURN: Status |
* |
* DESCRIPTION: Install new GPE block with mutex support |
* |
******************************************************************************/ |
static ACPI_STATUS |
AcpiEvInstallGpeBlock ( |
ACPI_GPE_BLOCK_INFO *GpeBlock, |
UINT32 InterruptNumber) |
{ |
ACPI_GPE_BLOCK_INFO *NextGpeBlock; |
ACPI_GPE_XRUPT_INFO *GpeXruptBlock; |
ACPI_STATUS Status; |
ACPI_CPU_FLAGS Flags; |
ACPI_FUNCTION_TRACE (EvInstallGpeBlock); |
Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
GpeXruptBlock = AcpiEvGetGpeXruptBlock (InterruptNumber); |
if (!GpeXruptBlock) |
{ |
Status = AE_NO_MEMORY; |
goto UnlockAndExit; |
} |
/* Install the new block at the end of the list with lock */ |
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
if (GpeXruptBlock->GpeBlockListHead) |
{ |
NextGpeBlock = GpeXruptBlock->GpeBlockListHead; |
while (NextGpeBlock->Next) |
{ |
NextGpeBlock = NextGpeBlock->Next; |
} |
NextGpeBlock->Next = GpeBlock; |
GpeBlock->Previous = NextGpeBlock; |
} |
else |
{ |
GpeXruptBlock->GpeBlockListHead = GpeBlock; |
} |
GpeBlock->XruptBlock = GpeXruptBlock; |
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
UnlockAndExit: |
Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
return_ACPI_STATUS (Status); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvDeleteGpeBlock |
* |
* PARAMETERS: GpeBlock - Existing GPE block |
* |
* RETURN: Status |
* |
* DESCRIPTION: Remove a GPE block |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvDeleteGpeBlock ( |
ACPI_GPE_BLOCK_INFO *GpeBlock) |
{ |
ACPI_STATUS Status; |
ACPI_CPU_FLAGS Flags; |
ACPI_FUNCTION_TRACE (EvInstallGpeBlock); |
Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
/* Disable all GPEs in this block */ |
Status = AcpiHwDisableGpeBlock (GpeBlock->XruptBlock, GpeBlock, NULL); |
if (!GpeBlock->Previous && !GpeBlock->Next) |
{ |
/* This is the last GpeBlock on this interrupt */ |
Status = AcpiEvDeleteGpeXrupt (GpeBlock->XruptBlock); |
if (ACPI_FAILURE (Status)) |
{ |
goto UnlockAndExit; |
} |
} |
else |
{ |
/* Remove the block on this interrupt with lock */ |
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
if (GpeBlock->Previous) |
{ |
GpeBlock->Previous->Next = GpeBlock->Next; |
} |
else |
{ |
GpeBlock->XruptBlock->GpeBlockListHead = GpeBlock->Next; |
} |
if (GpeBlock->Next) |
{ |
GpeBlock->Next->Previous = GpeBlock->Previous; |
} |
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
} |
AcpiCurrentGpeCount -= GpeBlock->GpeCount; |
/* Free the GpeBlock */ |
ACPI_FREE (GpeBlock->RegisterInfo); |
ACPI_FREE (GpeBlock->EventInfo); |
ACPI_FREE (GpeBlock); |
UnlockAndExit: |
Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
return_ACPI_STATUS (Status); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvCreateGpeInfoBlocks |
* |
* PARAMETERS: GpeBlock - New GPE block |
* |
* RETURN: Status |
* |
* DESCRIPTION: Create the RegisterInfo and EventInfo blocks for this GPE block |
* |
******************************************************************************/ |
static ACPI_STATUS |
AcpiEvCreateGpeInfoBlocks ( |
ACPI_GPE_BLOCK_INFO *GpeBlock) |
{ |
ACPI_GPE_REGISTER_INFO *GpeRegisterInfo = NULL; |
ACPI_GPE_EVENT_INFO *GpeEventInfo = NULL; |
ACPI_GPE_EVENT_INFO *ThisEvent; |
ACPI_GPE_REGISTER_INFO *ThisRegister; |
UINT32 i; |
UINT32 j; |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (EvCreateGpeInfoBlocks); |
/* Allocate the GPE register information block */ |
GpeRegisterInfo = ACPI_ALLOCATE_ZEROED ( |
(ACPI_SIZE) GpeBlock->RegisterCount * |
sizeof (ACPI_GPE_REGISTER_INFO)); |
if (!GpeRegisterInfo) |
{ |
ACPI_ERROR ((AE_INFO, |
"Could not allocate the GpeRegisterInfo table")); |
return_ACPI_STATUS (AE_NO_MEMORY); |
} |
/* |
* Allocate the GPE EventInfo block. There are eight distinct GPEs |
* per register. Initialization to zeros is sufficient. |
*/ |
GpeEventInfo = ACPI_ALLOCATE_ZEROED ((ACPI_SIZE) GpeBlock->GpeCount * |
sizeof (ACPI_GPE_EVENT_INFO)); |
if (!GpeEventInfo) |
{ |
ACPI_ERROR ((AE_INFO, |
"Could not allocate the GpeEventInfo table")); |
Status = AE_NO_MEMORY; |
goto ErrorExit; |
} |
/* Save the new Info arrays in the GPE block */ |
GpeBlock->RegisterInfo = GpeRegisterInfo; |
GpeBlock->EventInfo = GpeEventInfo; |
/* |
* Initialize the GPE Register and Event structures. A goal of these |
* tables is to hide the fact that there are two separate GPE register |
* sets in a given GPE hardware block, the status registers occupy the |
* first half, and the enable registers occupy the second half. |
*/ |
ThisRegister = GpeRegisterInfo; |
ThisEvent = GpeEventInfo; |
for (i = 0; i < GpeBlock->RegisterCount; i++) |
{ |
/* Init the RegisterInfo for this GPE register (8 GPEs) */ |
ThisRegister->BaseGpeNumber = (UINT8) (GpeBlock->BlockBaseNumber + |
(i * ACPI_GPE_REGISTER_WIDTH)); |
ThisRegister->StatusAddress.Address = |
GpeBlock->BlockAddress.Address + i; |
ThisRegister->EnableAddress.Address = |
GpeBlock->BlockAddress.Address + i + GpeBlock->RegisterCount; |
ThisRegister->StatusAddress.SpaceId = GpeBlock->BlockAddress.SpaceId; |
ThisRegister->EnableAddress.SpaceId = GpeBlock->BlockAddress.SpaceId; |
ThisRegister->StatusAddress.BitWidth = ACPI_GPE_REGISTER_WIDTH; |
ThisRegister->EnableAddress.BitWidth = ACPI_GPE_REGISTER_WIDTH; |
ThisRegister->StatusAddress.BitOffset = 0; |
ThisRegister->EnableAddress.BitOffset = 0; |
/* Init the EventInfo for each GPE within this register */ |
for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) |
{ |
ThisEvent->GpeNumber = (UINT8) (ThisRegister->BaseGpeNumber + j); |
ThisEvent->RegisterInfo = ThisRegister; |
ThisEvent++; |
} |
/* Disable all GPEs within this register */ |
Status = AcpiHwWrite (0x00, &ThisRegister->EnableAddress); |
if (ACPI_FAILURE (Status)) |
{ |
goto ErrorExit; |
} |
/* Clear any pending GPE events within this register */ |
Status = AcpiHwWrite (0xFF, &ThisRegister->StatusAddress); |
if (ACPI_FAILURE (Status)) |
{ |
goto ErrorExit; |
} |
ThisRegister++; |
} |
return_ACPI_STATUS (AE_OK); |
ErrorExit: |
if (GpeRegisterInfo) |
{ |
ACPI_FREE (GpeRegisterInfo); |
} |
if (GpeEventInfo) |
{ |
ACPI_FREE (GpeEventInfo); |
} |
return_ACPI_STATUS (Status); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvCreateGpeBlock |
* |
* PARAMETERS: GpeDevice - Handle to the parent GPE block |
* GpeBlockAddress - Address and SpaceID |
* RegisterCount - Number of GPE register pairs in the block |
* GpeBlockBaseNumber - Starting GPE number for the block |
* InterruptNumber - H/W interrupt for the block |
* ReturnGpeBlock - Where the new block descriptor is returned |
* |
* RETURN: Status |
* |
* DESCRIPTION: Create and Install a block of GPE registers. All GPEs within |
* the block are disabled at exit. |
* Note: Assumes namespace is locked. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvCreateGpeBlock ( |
ACPI_NAMESPACE_NODE *GpeDevice, |
ACPI_GENERIC_ADDRESS *GpeBlockAddress, |
UINT32 RegisterCount, |
UINT8 GpeBlockBaseNumber, |
UINT32 InterruptNumber, |
ACPI_GPE_BLOCK_INFO **ReturnGpeBlock) |
{ |
ACPI_STATUS Status; |
ACPI_GPE_BLOCK_INFO *GpeBlock; |
ACPI_GPE_WALK_INFO WalkInfo; |
ACPI_FUNCTION_TRACE (EvCreateGpeBlock); |
if (!RegisterCount) |
{ |
return_ACPI_STATUS (AE_OK); |
} |
/* Allocate a new GPE block */ |
GpeBlock = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_BLOCK_INFO)); |
if (!GpeBlock) |
{ |
return_ACPI_STATUS (AE_NO_MEMORY); |
} |
/* Initialize the new GPE block */ |
GpeBlock->Node = GpeDevice; |
GpeBlock->GpeCount = (UINT16) (RegisterCount * ACPI_GPE_REGISTER_WIDTH); |
GpeBlock->RegisterCount = RegisterCount; |
GpeBlock->BlockBaseNumber = GpeBlockBaseNumber; |
ACPI_MEMCPY (&GpeBlock->BlockAddress, GpeBlockAddress, |
sizeof (ACPI_GENERIC_ADDRESS)); |
/* |
* Create the RegisterInfo and EventInfo sub-structures |
* Note: disables and clears all GPEs in the block |
*/ |
Status = AcpiEvCreateGpeInfoBlocks (GpeBlock); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_FREE (GpeBlock); |
return_ACPI_STATUS (Status); |
} |
/* Install the new block in the global lists */ |
Status = AcpiEvInstallGpeBlock (GpeBlock, InterruptNumber); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_FREE (GpeBlock); |
return_ACPI_STATUS (Status); |
} |
/* Find all GPE methods (_Lxx or_Exx) for this block */ |
WalkInfo.GpeBlock = GpeBlock; |
WalkInfo.GpeDevice = GpeDevice; |
WalkInfo.EnableThisGpe = FALSE; |
WalkInfo.ExecuteByOwnerId = FALSE; |
Status = AcpiNsWalkNamespace (ACPI_TYPE_METHOD, GpeDevice, |
ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, |
AcpiEvMatchGpeMethod, NULL, &WalkInfo, NULL); |
/* Return the new block */ |
if (ReturnGpeBlock) |
{ |
(*ReturnGpeBlock) = GpeBlock; |
} |
ACPI_DEBUG_PRINT ((ACPI_DB_INIT, |
"GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n", |
(UINT32) GpeBlock->BlockBaseNumber, |
(UINT32) (GpeBlock->BlockBaseNumber + (GpeBlock->GpeCount - 1)), |
GpeDevice->Name.Ascii, GpeBlock->RegisterCount, |
InterruptNumber)); |
/* Update global count of currently available GPEs */ |
AcpiCurrentGpeCount += GpeBlock->GpeCount; |
return_ACPI_STATUS (AE_OK); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvInitializeGpeBlock |
* |
* PARAMETERS: GpeDevice - Handle to the parent GPE block |
* GpeBlock - Gpe Block info |
* |
* RETURN: Status |
* |
* DESCRIPTION: Initialize and enable a GPE block. First find and run any |
* _PRT methods associated with the block, then enable the |
* appropriate GPEs. |
* Note: Assumes namespace is locked. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvInitializeGpeBlock ( |
ACPI_NAMESPACE_NODE *GpeDevice, |
ACPI_GPE_BLOCK_INFO *GpeBlock) |
{ |
ACPI_STATUS Status; |
ACPI_GPE_EVENT_INFO *GpeEventInfo; |
ACPI_GPE_WALK_INFO WalkInfo; |
UINT32 WakeGpeCount; |
UINT32 GpeEnabledCount; |
UINT32 GpeIndex; |
UINT32 GpeNumber; |
UINT32 i; |
UINT32 j; |
ACPI_FUNCTION_TRACE (EvInitializeGpeBlock); |
/* Ignore a null GPE block (e.g., if no GPE block 1 exists) */ |
if (!GpeBlock) |
{ |
return_ACPI_STATUS (AE_OK); |
} |
/* |
* Runtime option: Should wake GPEs be enabled at runtime? The default |
* is no, they should only be enabled just as the machine goes to sleep. |
*/ |
if (AcpiGbl_LeaveWakeGpesDisabled) |
{ |
/* |
* Differentiate runtime vs wake GPEs, via the _PRW control methods. |
* Each GPE that has one or more _PRWs that reference it is by |
* definition a wake GPE and will not be enabled while the machine |
* is running. |
*/ |
WalkInfo.GpeBlock = GpeBlock; |
WalkInfo.GpeDevice = GpeDevice; |
WalkInfo.ExecuteByOwnerId = FALSE; |
Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, |
ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, |
AcpiEvMatchPrwAndGpe, NULL, &WalkInfo, NULL); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, "While executing _PRW methods")); |
} |
} |
/* |
* Enable all GPEs that have a corresponding method and are not |
* capable of generating wakeups. Any other GPEs within this block |
* must be enabled via the AcpiEnableGpe interface. |
*/ |
WakeGpeCount = 0; |
GpeEnabledCount = 0; |
if (GpeDevice == AcpiGbl_FadtGpeDevice) |
{ |
GpeDevice = NULL; |
} |
for (i = 0; i < GpeBlock->RegisterCount; i++) |
{ |
for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) |
{ |
/* Get the info block for this particular GPE */ |
GpeIndex = (i * ACPI_GPE_REGISTER_WIDTH) + j; |
GpeEventInfo = &GpeBlock->EventInfo[GpeIndex]; |
/* Ignore GPEs that can wake the system */ |
if (GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE) |
{ |
WakeGpeCount++; |
if (AcpiGbl_LeaveWakeGpesDisabled) |
{ |
continue; |
} |
} |
/* Ignore GPEs that have no corresponding _Lxx/_Exx method */ |
if (!(GpeEventInfo->Flags & ACPI_GPE_DISPATCH_METHOD)) |
{ |
continue; |
} |
/* Enable this GPE */ |
GpeNumber = GpeIndex + GpeBlock->BlockBaseNumber; |
Status = AcpiEnableGpe (GpeDevice, GpeNumber, |
ACPI_GPE_TYPE_RUNTIME); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, |
"Could not enable GPE 0x%02X", GpeNumber)); |
continue; |
} |
GpeEnabledCount++; |
} |
} |
if (GpeEnabledCount || WakeGpeCount) |
{ |
ACPI_DEBUG_PRINT ((ACPI_DB_INIT, |
"Enabled %u Runtime GPEs, added %u Wake GPEs in this block\n", |
GpeEnabledCount, WakeGpeCount)); |
} |
return_ACPI_STATUS (AE_OK); |
} |
/drivers/devman/acpica/events/evgpeinit.c |
---|
0,0 → 1,763 |
/****************************************************************************** |
* |
* Module Name: evgpeinit - System GPE initialization and update |
* |
*****************************************************************************/ |
/****************************************************************************** |
* |
* 1. Copyright Notice |
* |
* Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. |
* All rights reserved. |
* |
* 2. License |
* |
* 2.1. This is your license from Intel Corp. under its intellectual property |
* rights. You may have additional license terms from the party that provided |
* you this software, covering your right to use that party's intellectual |
* property rights. |
* |
* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a |
* copy of the source code appearing in this file ("Covered Code") an |
* irrevocable, perpetual, worldwide license under Intel's copyrights in the |
* base code distributed originally by Intel ("Original Intel Code") to copy, |
* make derivatives, distribute, use and display any portion of the Covered |
* Code in any form, with the right to sublicense such rights; and |
* |
* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent |
* license (with the right to sublicense), under only those claims of Intel |
* patents that are infringed by the Original Intel Code, to make, use, sell, |
* offer to sell, and import the Covered Code and derivative works thereof |
* solely to the minimum extent necessary to exercise the above copyright |
* license, and in no event shall the patent license extend to any additions |
* to or modifications of the Original Intel Code. No other license or right |
* is granted directly or by implication, estoppel or otherwise; |
* |
* The above copyright and patent license is granted only if the following |
* conditions are met: |
* |
* 3. Conditions |
* |
* 3.1. Redistribution of Source with Rights to Further Distribute Source. |
* Redistribution of source code of any substantial portion of the Covered |
* Code or modification with rights to further distribute source must include |
* the above Copyright Notice, the above License, this list of Conditions, |
* and the following Disclaimer and Export Compliance provision. In addition, |
* Licensee must cause all Covered Code to which Licensee contributes to |
* contain a file documenting the changes Licensee made to create that Covered |
* Code and the date of any change. Licensee must include in that file the |
* documentation of any changes made by any predecessor Licensee. Licensee |
* must include a prominent statement that the modification is derived, |
* directly or indirectly, from Original Intel Code. |
* |
* 3.2. Redistribution of Source with no Rights to Further Distribute Source. |
* Redistribution of source code of any substantial portion of the Covered |
* Code or modification without rights to further distribute source must |
* include the following Disclaimer and Export Compliance provision in the |
* documentation and/or other materials provided with distribution. In |
* addition, Licensee may not authorize further sublicense of source of any |
* portion of the Covered Code, and must include terms to the effect that the |
* license from Licensee to its licensee is limited to the intellectual |
* property embodied in the software Licensee provides to its licensee, and |
* not to intellectual property embodied in modifications its licensee may |
* make. |
* |
* 3.3. Redistribution of Executable. Redistribution in executable form of any |
* substantial portion of the Covered Code or modification must reproduce the |
* above Copyright Notice, and the following Disclaimer and Export Compliance |
* provision in the documentation and/or other materials provided with the |
* distribution. |
* |
* 3.4. Intel retains all right, title, and interest in and to the Original |
* Intel Code. |
* |
* 3.5. Neither the name Intel nor any other trademark owned or controlled by |
* Intel shall be used in advertising or otherwise to promote the sale, use or |
* other dealings in products derived from or relating to the Covered Code |
* without prior written authorization from Intel. |
* |
* 4. Disclaimer and Export Compliance |
* |
* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED |
* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE |
* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, |
* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY |
* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY |
* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A |
* PARTICULAR PURPOSE. |
* |
* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES |
* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR |
* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, |
* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY |
* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL |
* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS |
* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY |
* LIMITED REMEDY. |
* |
* 4.3. Licensee shall not export, either directly or indirectly, any of this |
* software or system incorporating such software without first obtaining any |
* required license or other approval from the U. S. Department of Commerce or |
* any other agency or department of the United States Government. In the |
* event Licensee exports any such software from the United States or |
* re-exports any such software from a foreign destination, Licensee shall |
* ensure that the distribution and export/re-export of the software is in |
* compliance with all laws, regulations, orders, or other restrictions of the |
* U.S. Export Administration Regulations. Licensee agrees that neither it nor |
* any of its subsidiaries will export/re-export any technical data, process, |
* software, or service, directly or indirectly, to any country for which the |
* United States government or any agency thereof requires an export license, |
* other governmental approval, or letter of assurance, without first obtaining |
* such license, approval or letter. |
* |
*****************************************************************************/ |
#include "acpi.h" |
#include "accommon.h" |
#include "acevents.h" |
#include "acnamesp.h" |
#include "acinterp.h" |
#define _COMPONENT ACPI_EVENTS |
ACPI_MODULE_NAME ("evgpeinit") |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvGpeInitialize |
* |
* PARAMETERS: None |
* |
* RETURN: Status |
* |
* DESCRIPTION: Initialize the GPE data structures and the FADT GPE 0/1 blocks |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvGpeInitialize ( |
void) |
{ |
UINT32 RegisterCount0 = 0; |
UINT32 RegisterCount1 = 0; |
UINT32 GpeNumberMax = 0; |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (EvGpeInitialize); |
Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
/* |
* Initialize the GPE Block(s) defined in the FADT |
* |
* Why the GPE register block lengths are divided by 2: From the ACPI |
* Spec, section "General-Purpose Event Registers", we have: |
* |
* "Each register block contains two registers of equal length |
* GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the |
* GPE0_STS and GPE0_EN registers is equal to half the GPE0_LEN |
* The length of the GPE1_STS and GPE1_EN registers is equal to |
* half the GPE1_LEN. If a generic register block is not supported |
* then its respective block pointer and block length values in the |
* FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need |
* to be the same size." |
*/ |
/* |
* Determine the maximum GPE number for this machine. |
* |
* Note: both GPE0 and GPE1 are optional, and either can exist without |
* the other. |
* |
* If EITHER the register length OR the block address are zero, then that |
* particular block is not supported. |
*/ |
if (AcpiGbl_FADT.Gpe0BlockLength && |
AcpiGbl_FADT.XGpe0Block.Address) |
{ |
/* GPE block 0 exists (has both length and address > 0) */ |
RegisterCount0 = (UINT16) (AcpiGbl_FADT.Gpe0BlockLength / 2); |
GpeNumberMax = (RegisterCount0 * ACPI_GPE_REGISTER_WIDTH) - 1; |
/* Install GPE Block 0 */ |
Status = AcpiEvCreateGpeBlock (AcpiGbl_FadtGpeDevice, |
&AcpiGbl_FADT.XGpe0Block, RegisterCount0, 0, |
AcpiGbl_FADT.SciInterrupt, &AcpiGbl_GpeFadtBlocks[0]); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, |
"Could not create GPE Block 0")); |
} |
} |
if (AcpiGbl_FADT.Gpe1BlockLength && |
AcpiGbl_FADT.XGpe1Block.Address) |
{ |
/* GPE block 1 exists (has both length and address > 0) */ |
RegisterCount1 = (UINT16) (AcpiGbl_FADT.Gpe1BlockLength / 2); |
/* Check for GPE0/GPE1 overlap (if both banks exist) */ |
if ((RegisterCount0) && |
(GpeNumberMax >= AcpiGbl_FADT.Gpe1Base)) |
{ |
ACPI_ERROR ((AE_INFO, |
"GPE0 block (GPE 0 to %u) overlaps the GPE1 block " |
"(GPE %u to %u) - Ignoring GPE1", |
GpeNumberMax, AcpiGbl_FADT.Gpe1Base, |
AcpiGbl_FADT.Gpe1Base + |
((RegisterCount1 * ACPI_GPE_REGISTER_WIDTH) - 1))); |
/* Ignore GPE1 block by setting the register count to zero */ |
RegisterCount1 = 0; |
} |
else |
{ |
/* Install GPE Block 1 */ |
Status = AcpiEvCreateGpeBlock (AcpiGbl_FadtGpeDevice, |
&AcpiGbl_FADT.XGpe1Block, RegisterCount1, |
AcpiGbl_FADT.Gpe1Base, |
AcpiGbl_FADT.SciInterrupt, &AcpiGbl_GpeFadtBlocks[1]); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, |
"Could not create GPE Block 1")); |
} |
/* |
* GPE0 and GPE1 do not have to be contiguous in the GPE number |
* space. However, GPE0 always starts at GPE number zero. |
*/ |
GpeNumberMax = AcpiGbl_FADT.Gpe1Base + |
((RegisterCount1 * ACPI_GPE_REGISTER_WIDTH) - 1); |
} |
} |
/* Exit if there are no GPE registers */ |
if ((RegisterCount0 + RegisterCount1) == 0) |
{ |
/* GPEs are not required by ACPI, this is OK */ |
ACPI_DEBUG_PRINT ((ACPI_DB_INIT, |
"There are no GPE blocks defined in the FADT\n")); |
Status = AE_OK; |
goto Cleanup; |
} |
/* Check for Max GPE number out-of-range */ |
if (GpeNumberMax > ACPI_GPE_MAX) |
{ |
ACPI_ERROR ((AE_INFO, |
"Maximum GPE number from FADT is too large: 0x%X", |
GpeNumberMax)); |
Status = AE_BAD_VALUE; |
goto Cleanup; |
} |
Cleanup: |
(void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); |
return_ACPI_STATUS (AE_OK); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvUpdateGpes |
* |
* PARAMETERS: TableOwnerId - ID of the newly-loaded ACPI table |
* |
* RETURN: None |
* |
* DESCRIPTION: Check for new GPE methods (_Lxx/_Exx) made available as a |
* result of a Load() or LoadTable() operation. If new GPE |
* methods have been installed, register the new methods and |
* enable and runtime GPEs that are associated with them. Also, |
* run any newly loaded _PRW methods in order to discover any |
* new CAN_WAKE GPEs. |
* |
******************************************************************************/ |
void |
AcpiEvUpdateGpes ( |
ACPI_OWNER_ID TableOwnerId) |
{ |
ACPI_GPE_XRUPT_INFO *GpeXruptInfo; |
ACPI_GPE_BLOCK_INFO *GpeBlock; |
ACPI_GPE_WALK_INFO WalkInfo; |
ACPI_STATUS Status = AE_OK; |
UINT32 NewWakeGpeCount = 0; |
/* We will examine only _PRW/_Lxx/_Exx methods owned by this table */ |
WalkInfo.OwnerId = TableOwnerId; |
WalkInfo.ExecuteByOwnerId = TRUE; |
WalkInfo.Count = 0; |
if (AcpiGbl_LeaveWakeGpesDisabled) |
{ |
/* |
* 1) Run any newly-loaded _PRW methods to find any GPEs that |
* can now be marked as CAN_WAKE GPEs. Note: We must run the |
* _PRW methods before we process the _Lxx/_Exx methods because |
* we will enable all runtime GPEs associated with the new |
* _Lxx/_Exx methods at the time we process those methods. |
* |
* Unlock interpreter so that we can run the _PRW methods. |
*/ |
WalkInfo.GpeBlock = NULL; |
WalkInfo.GpeDevice = NULL; |
AcpiExExitInterpreter (); |
Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, |
ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, |
AcpiEvMatchPrwAndGpe, NULL, &WalkInfo, NULL); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, |
"While executing _PRW methods")); |
} |
AcpiExEnterInterpreter (); |
NewWakeGpeCount = WalkInfo.Count; |
} |
/* |
* 2) Find any _Lxx/_Exx GPE methods that have just been loaded. |
* |
* Any GPEs that correspond to new _Lxx/_Exx methods and are not |
* marked as CAN_WAKE are immediately enabled. |
* |
* Examine the namespace underneath each GpeDevice within the |
* GpeBlock lists. |
*/ |
Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); |
if (ACPI_FAILURE (Status)) |
{ |
return; |
} |
WalkInfo.Count = 0; |
WalkInfo.EnableThisGpe = TRUE; |
/* Walk the interrupt level descriptor list */ |
GpeXruptInfo = AcpiGbl_GpeXruptListHead; |
while (GpeXruptInfo) |
{ |
/* Walk all Gpe Blocks attached to this interrupt level */ |
GpeBlock = GpeXruptInfo->GpeBlockListHead; |
while (GpeBlock) |
{ |
WalkInfo.GpeBlock = GpeBlock; |
WalkInfo.GpeDevice = GpeBlock->Node; |
Status = AcpiNsWalkNamespace (ACPI_TYPE_METHOD, |
WalkInfo.GpeDevice, ACPI_UINT32_MAX, |
ACPI_NS_WALK_NO_UNLOCK, AcpiEvMatchGpeMethod, |
NULL, &WalkInfo, NULL); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, |
"While decoding _Lxx/_Exx methods")); |
} |
GpeBlock = GpeBlock->Next; |
} |
GpeXruptInfo = GpeXruptInfo->Next; |
} |
if (WalkInfo.Count || NewWakeGpeCount) |
{ |
ACPI_INFO ((AE_INFO, |
"Enabled %u new runtime GPEs, added %u new wakeup GPEs", |
WalkInfo.Count, NewWakeGpeCount)); |
} |
(void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
return; |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvMatchGpeMethod |
* |
* PARAMETERS: Callback from WalkNamespace |
* |
* RETURN: Status |
* |
* DESCRIPTION: Called from AcpiWalkNamespace. Expects each object to be a |
* control method under the _GPE portion of the namespace. |
* Extract the name and GPE type from the object, saving this |
* information for quick lookup during GPE dispatch. Allows a |
* per-OwnerId evaluation if ExecuteByOwnerId is TRUE in the |
* WalkInfo parameter block. |
* |
* The name of each GPE control method is of the form: |
* "_Lxx" or "_Exx", where: |
* L - means that the GPE is level triggered |
* E - means that the GPE is edge triggered |
* xx - is the GPE number [in HEX] |
* |
* If WalkInfo->ExecuteByOwnerId is TRUE, we only execute examine GPE methods |
* with that owner. |
* If WalkInfo->EnableThisGpe is TRUE, the GPE that is referred to by a GPE |
* method is immediately enabled (Used for Load/LoadTable operators) |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvMatchGpeMethod ( |
ACPI_HANDLE ObjHandle, |
UINT32 Level, |
void *Context, |
void **ReturnValue) |
{ |
ACPI_NAMESPACE_NODE *MethodNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle); |
ACPI_GPE_WALK_INFO *WalkInfo = ACPI_CAST_PTR (ACPI_GPE_WALK_INFO, Context); |
ACPI_GPE_EVENT_INFO *GpeEventInfo; |
ACPI_NAMESPACE_NODE *GpeDevice; |
ACPI_STATUS Status; |
UINT32 GpeNumber; |
char Name[ACPI_NAME_SIZE + 1]; |
UINT8 Type; |
ACPI_FUNCTION_TRACE (EvMatchGpeMethod); |
/* Check if requested OwnerId matches this OwnerId */ |
if ((WalkInfo->ExecuteByOwnerId) && |
(MethodNode->OwnerId != WalkInfo->OwnerId)) |
{ |
return_ACPI_STATUS (AE_OK); |
} |
/* |
* Match and decode the _Lxx and _Exx GPE method names |
* |
* 1) Extract the method name and null terminate it |
*/ |
ACPI_MOVE_32_TO_32 (Name, &MethodNode->Name.Integer); |
Name[ACPI_NAME_SIZE] = 0; |
/* 2) Name must begin with an underscore */ |
if (Name[0] != '_') |
{ |
return_ACPI_STATUS (AE_OK); /* Ignore this method */ |
} |
/* |
* 3) Edge/Level determination is based on the 2nd character |
* of the method name |
* |
* NOTE: Default GPE type is RUNTIME only. Later, if a _PRW object is |
* found that points to this GPE, the ACPI_GPE_CAN_WAKE flag is set. |
*/ |
switch (Name[1]) |
{ |
case 'L': |
Type = ACPI_GPE_LEVEL_TRIGGERED; |
break; |
case 'E': |
Type = ACPI_GPE_EDGE_TRIGGERED; |
break; |
default: |
/* Unknown method type, just ignore it */ |
ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, |
"Ignoring unknown GPE method type: %s " |
"(name not of form _Lxx or _Exx)", Name)); |
return_ACPI_STATUS (AE_OK); |
} |
/* 4) The last two characters of the name are the hex GPE Number */ |
GpeNumber = ACPI_STRTOUL (&Name[2], NULL, 16); |
if (GpeNumber == ACPI_UINT32_MAX) |
{ |
/* Conversion failed; invalid method, just ignore it */ |
ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, |
"Could not extract GPE number from name: %s " |
"(name is not of form _Lxx or _Exx)", Name)); |
return_ACPI_STATUS (AE_OK); |
} |
/* Ensure that we have a valid GPE number for this GPE block */ |
GpeEventInfo = AcpiEvLowGetGpeInfo (GpeNumber, WalkInfo->GpeBlock); |
if (!GpeEventInfo) |
{ |
/* |
* This GpeNumber is not valid for this GPE block, just ignore it. |
* However, it may be valid for a different GPE block, since GPE0 |
* and GPE1 methods both appear under \_GPE. |
*/ |
return_ACPI_STATUS (AE_OK); |
} |
if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == |
ACPI_GPE_DISPATCH_HANDLER) |
{ |
/* If there is already a handler, ignore this GPE method */ |
return_ACPI_STATUS (AE_OK); |
} |
if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == |
ACPI_GPE_DISPATCH_METHOD) |
{ |
/* |
* If there is already a method, ignore this method. But check |
* for a type mismatch (if both the _Lxx AND _Exx exist) |
*/ |
if (Type != (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK)) |
{ |
ACPI_ERROR ((AE_INFO, |
"For GPE 0x%.2X, found both _L%2.2X and _E%2.2X methods", |
GpeNumber, GpeNumber, GpeNumber)); |
} |
return_ACPI_STATUS (AE_OK); |
} |
/* |
* Add the GPE information from above to the GpeEventInfo block for |
* use during dispatch of this GPE. |
*/ |
GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_METHOD); |
GpeEventInfo->Dispatch.MethodNode = MethodNode; |
/* |
* Enable this GPE if requested. This only happens when during the |
* execution of a Load or LoadTable operator. We have found a new |
* GPE method and want to immediately enable the GPE if it is a |
* runtime GPE. |
*/ |
if (WalkInfo->EnableThisGpe) |
{ |
/* Ignore GPEs that can wake the system */ |
if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE) || |
!AcpiGbl_LeaveWakeGpesDisabled) |
{ |
WalkInfo->Count++; |
GpeDevice = WalkInfo->GpeDevice; |
if (GpeDevice == AcpiGbl_FadtGpeDevice) |
{ |
GpeDevice = NULL; |
} |
Status = AcpiEnableGpe (GpeDevice, GpeNumber, |
ACPI_GPE_TYPE_RUNTIME); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, |
"Could not enable GPE 0x%02X", GpeNumber)); |
} |
} |
} |
ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, |
"Registered GPE method %s as GPE number 0x%.2X\n", |
Name, GpeNumber)); |
return_ACPI_STATUS (AE_OK); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvMatchPrwAndGpe |
* |
* PARAMETERS: Callback from WalkNamespace |
* |
* RETURN: Status. NOTE: We ignore errors so that the _PRW walk is |
* not aborted on a single _PRW failure. |
* |
* DESCRIPTION: Called from AcpiWalkNamespace. Expects each object to be a |
* Device. Run the _PRW method. If present, extract the GPE |
* number and mark the GPE as a CAN_WAKE GPE. Allows a |
* per-OwnerId execution if ExecuteByOwnerId is TRUE in the |
* WalkInfo parameter block. |
* |
* If WalkInfo->ExecuteByOwnerId is TRUE, we only execute _PRWs with that |
* owner. |
* If WalkInfo->GpeDevice is NULL, we execute every _PRW found. Otherwise, |
* we only execute _PRWs that refer to the input GpeDevice. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvMatchPrwAndGpe ( |
ACPI_HANDLE ObjHandle, |
UINT32 Level, |
void *Context, |
void **ReturnValue) |
{ |
ACPI_GPE_WALK_INFO *WalkInfo = ACPI_CAST_PTR (ACPI_GPE_WALK_INFO, Context); |
ACPI_NAMESPACE_NODE *GpeDevice; |
ACPI_GPE_BLOCK_INFO *GpeBlock; |
ACPI_NAMESPACE_NODE *TargetGpeDevice; |
ACPI_NAMESPACE_NODE *PrwNode; |
ACPI_GPE_EVENT_INFO *GpeEventInfo; |
ACPI_OPERAND_OBJECT *PkgDesc; |
ACPI_OPERAND_OBJECT *ObjDesc; |
UINT32 GpeNumber; |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (EvMatchPrwAndGpe); |
/* Check for a _PRW method under this device */ |
Status = AcpiNsGetNode (ObjHandle, METHOD_NAME__PRW, |
ACPI_NS_NO_UPSEARCH, &PrwNode); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (AE_OK); |
} |
/* Check if requested OwnerId matches this OwnerId */ |
if ((WalkInfo->ExecuteByOwnerId) && |
(PrwNode->OwnerId != WalkInfo->OwnerId)) |
{ |
return_ACPI_STATUS (AE_OK); |
} |
/* Execute the _PRW */ |
Status = AcpiUtEvaluateObject (PrwNode, NULL, |
ACPI_BTYPE_PACKAGE, &PkgDesc); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (AE_OK); |
} |
/* The returned _PRW package must have at least two elements */ |
if (PkgDesc->Package.Count < 2) |
{ |
goto Cleanup; |
} |
/* Extract pointers from the input context */ |
GpeDevice = WalkInfo->GpeDevice; |
GpeBlock = WalkInfo->GpeBlock; |
/* |
* The _PRW object must return a package, we are only interested |
* in the first element |
*/ |
ObjDesc = PkgDesc->Package.Elements[0]; |
if (ObjDesc->Common.Type == ACPI_TYPE_INTEGER) |
{ |
/* Use FADT-defined GPE device (from definition of _PRW) */ |
TargetGpeDevice = NULL; |
if (GpeDevice) |
{ |
TargetGpeDevice = AcpiGbl_FadtGpeDevice; |
} |
/* Integer is the GPE number in the FADT described GPE blocks */ |
GpeNumber = (UINT32) ObjDesc->Integer.Value; |
} |
else if (ObjDesc->Common.Type == ACPI_TYPE_PACKAGE) |
{ |
/* Package contains a GPE reference and GPE number within a GPE block */ |
if ((ObjDesc->Package.Count < 2) || |
((ObjDesc->Package.Elements[0])->Common.Type != |
ACPI_TYPE_LOCAL_REFERENCE) || |
((ObjDesc->Package.Elements[1])->Common.Type != |
ACPI_TYPE_INTEGER)) |
{ |
goto Cleanup; |
} |
/* Get GPE block reference and decode */ |
TargetGpeDevice = ObjDesc->Package.Elements[0]->Reference.Node; |
GpeNumber = (UINT32) ObjDesc->Package.Elements[1]->Integer.Value; |
} |
else |
{ |
/* Unknown type, just ignore it */ |
goto Cleanup; |
} |
/* Get the GpeEventInfo for this GPE */ |
if (GpeDevice) |
{ |
/* |
* Is this GPE within this block? |
* |
* TRUE if and only if these conditions are true: |
* 1) The GPE devices match. |
* 2) The GPE index(number) is within the range of the Gpe Block |
* associated with the GPE device. |
*/ |
if (GpeDevice != TargetGpeDevice) |
{ |
goto Cleanup; |
} |
GpeEventInfo = AcpiEvLowGetGpeInfo (GpeNumber, GpeBlock); |
} |
else |
{ |
/* GpeDevice is NULL, just match the TargetDevice and GpeNumber */ |
GpeEventInfo = AcpiEvGetGpeEventInfo (TargetGpeDevice, GpeNumber); |
} |
if (GpeEventInfo) |
{ |
if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE)) |
{ |
/* This GPE can wake the system */ |
GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE; |
WalkInfo->Count++; |
} |
} |
Cleanup: |
AcpiUtRemoveReference (PkgDesc); |
return_ACPI_STATUS (AE_OK); |
} |
/drivers/devman/acpica/events/evgpeutil.c |
---|
0,0 → 1,451 |
/****************************************************************************** |
* |
* Module Name: evgpeutil - GPE utilities |
* |
*****************************************************************************/ |
/****************************************************************************** |
* |
* 1. Copyright Notice |
* |
* Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. |
* All rights reserved. |
* |
* 2. License |
* |
* 2.1. This is your license from Intel Corp. under its intellectual property |
* rights. You may have additional license terms from the party that provided |
* you this software, covering your right to use that party's intellectual |
* property rights. |
* |
* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a |
* copy of the source code appearing in this file ("Covered Code") an |
* irrevocable, perpetual, worldwide license under Intel's copyrights in the |
* base code distributed originally by Intel ("Original Intel Code") to copy, |
* make derivatives, distribute, use and display any portion of the Covered |
* Code in any form, with the right to sublicense such rights; and |
* |
* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent |
* license (with the right to sublicense), under only those claims of Intel |
* patents that are infringed by the Original Intel Code, to make, use, sell, |
* offer to sell, and import the Covered Code and derivative works thereof |
* solely to the minimum extent necessary to exercise the above copyright |
* license, and in no event shall the patent license extend to any additions |
* to or modifications of the Original Intel Code. No other license or right |
* is granted directly or by implication, estoppel or otherwise; |
* |
* The above copyright and patent license is granted only if the following |
* conditions are met: |
* |
* 3. Conditions |
* |
* 3.1. Redistribution of Source with Rights to Further Distribute Source. |
* Redistribution of source code of any substantial portion of the Covered |
* Code or modification with rights to further distribute source must include |
* the above Copyright Notice, the above License, this list of Conditions, |
* and the following Disclaimer and Export Compliance provision. In addition, |
* Licensee must cause all Covered Code to which Licensee contributes to |
* contain a file documenting the changes Licensee made to create that Covered |
* Code and the date of any change. Licensee must include in that file the |
* documentation of any changes made by any predecessor Licensee. Licensee |
* must include a prominent statement that the modification is derived, |
* directly or indirectly, from Original Intel Code. |
* |
* 3.2. Redistribution of Source with no Rights to Further Distribute Source. |
* Redistribution of source code of any substantial portion of the Covered |
* Code or modification without rights to further distribute source must |
* include the following Disclaimer and Export Compliance provision in the |
* documentation and/or other materials provided with distribution. In |
* addition, Licensee may not authorize further sublicense of source of any |
* portion of the Covered Code, and must include terms to the effect that the |
* license from Licensee to its licensee is limited to the intellectual |
* property embodied in the software Licensee provides to its licensee, and |
* not to intellectual property embodied in modifications its licensee may |
* make. |
* |
* 3.3. Redistribution of Executable. Redistribution in executable form of any |
* substantial portion of the Covered Code or modification must reproduce the |
* above Copyright Notice, and the following Disclaimer and Export Compliance |
* provision in the documentation and/or other materials provided with the |
* distribution. |
* |
* 3.4. Intel retains all right, title, and interest in and to the Original |
* Intel Code. |
* |
* 3.5. Neither the name Intel nor any other trademark owned or controlled by |
* Intel shall be used in advertising or otherwise to promote the sale, use or |
* other dealings in products derived from or relating to the Covered Code |
* without prior written authorization from Intel. |
* |
* 4. Disclaimer and Export Compliance |
* |
* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED |
* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE |
* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, |
* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY |
* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY |
* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A |
* PARTICULAR PURPOSE. |
* |
* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES |
* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR |
* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, |
* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY |
* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL |
* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS |
* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY |
* LIMITED REMEDY. |
* |
* 4.3. Licensee shall not export, either directly or indirectly, any of this |
* software or system incorporating such software without first obtaining any |
* required license or other approval from the U. S. Department of Commerce or |
* any other agency or department of the United States Government. In the |
* event Licensee exports any such software from the United States or |
* re-exports any such software from a foreign destination, Licensee shall |
* ensure that the distribution and export/re-export of the software is in |
* compliance with all laws, regulations, orders, or other restrictions of the |
* U.S. Export Administration Regulations. Licensee agrees that neither it nor |
* any of its subsidiaries will export/re-export any technical data, process, |
* software, or service, directly or indirectly, to any country for which the |
* United States government or any agency thereof requires an export license, |
* other governmental approval, or letter of assurance, without first obtaining |
* such license, approval or letter. |
* |
*****************************************************************************/ |
#include "acpi.h" |
#include "accommon.h" |
#include "acevents.h" |
#define _COMPONENT ACPI_EVENTS |
ACPI_MODULE_NAME ("evgpeutil") |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvWalkGpeList |
* |
* PARAMETERS: GpeWalkCallback - Routine called for each GPE block |
* Context - Value passed to callback |
* |
* RETURN: Status |
* |
* DESCRIPTION: Walk the GPE lists. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvWalkGpeList ( |
ACPI_GPE_CALLBACK GpeWalkCallback, |
void *Context) |
{ |
ACPI_GPE_BLOCK_INFO *GpeBlock; |
ACPI_GPE_XRUPT_INFO *GpeXruptInfo; |
ACPI_STATUS Status = AE_OK; |
ACPI_CPU_FLAGS Flags; |
ACPI_FUNCTION_TRACE (EvWalkGpeList); |
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
/* Walk the interrupt level descriptor list */ |
GpeXruptInfo = AcpiGbl_GpeXruptListHead; |
while (GpeXruptInfo) |
{ |
/* Walk all Gpe Blocks attached to this interrupt level */ |
GpeBlock = GpeXruptInfo->GpeBlockListHead; |
while (GpeBlock) |
{ |
/* One callback per GPE block */ |
Status = GpeWalkCallback (GpeXruptInfo, GpeBlock, Context); |
if (ACPI_FAILURE (Status)) |
{ |
if (Status == AE_CTRL_END) /* Callback abort */ |
{ |
Status = AE_OK; |
} |
goto UnlockAndExit; |
} |
GpeBlock = GpeBlock->Next; |
} |
GpeXruptInfo = GpeXruptInfo->Next; |
} |
UnlockAndExit: |
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
return_ACPI_STATUS (Status); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvValidGpeEvent |
* |
* PARAMETERS: GpeEventInfo - Info for this GPE |
* |
* RETURN: TRUE if the GpeEvent is valid |
* |
* DESCRIPTION: Validate a GPE event. DO NOT CALL FROM INTERRUPT LEVEL. |
* Should be called only when the GPE lists are semaphore locked |
* and not subject to change. |
* |
******************************************************************************/ |
BOOLEAN |
AcpiEvValidGpeEvent ( |
ACPI_GPE_EVENT_INFO *GpeEventInfo) |
{ |
ACPI_GPE_XRUPT_INFO *GpeXruptBlock; |
ACPI_GPE_BLOCK_INFO *GpeBlock; |
ACPI_FUNCTION_ENTRY (); |
/* No need for spin lock since we are not changing any list elements */ |
/* Walk the GPE interrupt levels */ |
GpeXruptBlock = AcpiGbl_GpeXruptListHead; |
while (GpeXruptBlock) |
{ |
GpeBlock = GpeXruptBlock->GpeBlockListHead; |
/* Walk the GPE blocks on this interrupt level */ |
while (GpeBlock) |
{ |
if ((&GpeBlock->EventInfo[0] <= GpeEventInfo) && |
(&GpeBlock->EventInfo[GpeBlock->GpeCount] > GpeEventInfo)) |
{ |
return (TRUE); |
} |
GpeBlock = GpeBlock->Next; |
} |
GpeXruptBlock = GpeXruptBlock->Next; |
} |
return (FALSE); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvGetGpeXruptBlock |
* |
* PARAMETERS: InterruptNumber - Interrupt for a GPE block |
* |
* RETURN: A GPE interrupt block |
* |
* DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt |
* block per unique interrupt level used for GPEs. Should be |
* called only when the GPE lists are semaphore locked and not |
* subject to change. |
* |
******************************************************************************/ |
ACPI_GPE_XRUPT_INFO * |
AcpiEvGetGpeXruptBlock ( |
UINT32 InterruptNumber) |
{ |
ACPI_GPE_XRUPT_INFO *NextGpeXrupt; |
ACPI_GPE_XRUPT_INFO *GpeXrupt; |
ACPI_STATUS Status; |
ACPI_CPU_FLAGS Flags; |
ACPI_FUNCTION_TRACE (EvGetGpeXruptBlock); |
/* No need for lock since we are not changing any list elements here */ |
NextGpeXrupt = AcpiGbl_GpeXruptListHead; |
while (NextGpeXrupt) |
{ |
if (NextGpeXrupt->InterruptNumber == InterruptNumber) |
{ |
return_PTR (NextGpeXrupt); |
} |
NextGpeXrupt = NextGpeXrupt->Next; |
} |
/* Not found, must allocate a new xrupt descriptor */ |
GpeXrupt = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_XRUPT_INFO)); |
if (!GpeXrupt) |
{ |
return_PTR (NULL); |
} |
GpeXrupt->InterruptNumber = InterruptNumber; |
/* Install new interrupt descriptor with spin lock */ |
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
if (AcpiGbl_GpeXruptListHead) |
{ |
NextGpeXrupt = AcpiGbl_GpeXruptListHead; |
while (NextGpeXrupt->Next) |
{ |
NextGpeXrupt = NextGpeXrupt->Next; |
} |
NextGpeXrupt->Next = GpeXrupt; |
GpeXrupt->Previous = NextGpeXrupt; |
} |
else |
{ |
AcpiGbl_GpeXruptListHead = GpeXrupt; |
} |
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
/* Install new interrupt handler if not SCI_INT */ |
if (InterruptNumber != AcpiGbl_FADT.SciInterrupt) |
{ |
Status = AcpiOsInstallInterruptHandler (InterruptNumber, |
AcpiEvGpeXruptHandler, GpeXrupt); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_ERROR ((AE_INFO, |
"Could not install GPE interrupt handler at level 0x%X", |
InterruptNumber)); |
return_PTR (NULL); |
} |
} |
return_PTR (GpeXrupt); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvDeleteGpeXrupt |
* |
* PARAMETERS: GpeXrupt - A GPE interrupt info block |
* |
* RETURN: Status |
* |
* DESCRIPTION: Remove and free a GpeXrupt block. Remove an associated |
* interrupt handler if not the SCI interrupt. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvDeleteGpeXrupt ( |
ACPI_GPE_XRUPT_INFO *GpeXrupt) |
{ |
ACPI_STATUS Status; |
ACPI_CPU_FLAGS Flags; |
ACPI_FUNCTION_TRACE (EvDeleteGpeXrupt); |
/* We never want to remove the SCI interrupt handler */ |
if (GpeXrupt->InterruptNumber == AcpiGbl_FADT.SciInterrupt) |
{ |
GpeXrupt->GpeBlockListHead = NULL; |
return_ACPI_STATUS (AE_OK); |
} |
/* Disable this interrupt */ |
Status = AcpiOsRemoveInterruptHandler ( |
GpeXrupt->InterruptNumber, AcpiEvGpeXruptHandler); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
/* Unlink the interrupt block with lock */ |
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
if (GpeXrupt->Previous) |
{ |
GpeXrupt->Previous->Next = GpeXrupt->Next; |
} |
else |
{ |
/* No previous, update list head */ |
AcpiGbl_GpeXruptListHead = GpeXrupt->Next; |
} |
if (GpeXrupt->Next) |
{ |
GpeXrupt->Next->Previous = GpeXrupt->Previous; |
} |
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
/* Free the block */ |
ACPI_FREE (GpeXrupt); |
return_ACPI_STATUS (AE_OK); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvDeleteGpeHandlers |
* |
* PARAMETERS: GpeXruptInfo - GPE Interrupt info |
* GpeBlock - Gpe Block info |
* |
* RETURN: Status |
* |
* DESCRIPTION: Delete all Handler objects found in the GPE data structs. |
* Used only prior to termination. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvDeleteGpeHandlers ( |
ACPI_GPE_XRUPT_INFO *GpeXruptInfo, |
ACPI_GPE_BLOCK_INFO *GpeBlock, |
void *Context) |
{ |
ACPI_GPE_EVENT_INFO *GpeEventInfo; |
UINT32 i; |
UINT32 j; |
ACPI_FUNCTION_TRACE (EvDeleteGpeHandlers); |
/* Examine each GPE Register within the block */ |
for (i = 0; i < GpeBlock->RegisterCount; i++) |
{ |
/* Now look at the individual GPEs in this byte register */ |
for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) |
{ |
GpeEventInfo = &GpeBlock->EventInfo[((ACPI_SIZE) i * |
ACPI_GPE_REGISTER_WIDTH) + j]; |
if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == |
ACPI_GPE_DISPATCH_HANDLER) |
{ |
ACPI_FREE (GpeEventInfo->Dispatch.Handler); |
GpeEventInfo->Dispatch.Handler = NULL; |
GpeEventInfo->Flags &= ~ACPI_GPE_DISPATCH_MASK; |
} |
} |
} |
return_ACPI_STATUS (AE_OK); |
} |
/drivers/devman/acpica/events/evmisc.c |
---|
0,0 → 1,740 |
/****************************************************************************** |
* |
* Module Name: evmisc - Miscellaneous event manager support functions |
* |
*****************************************************************************/ |
/****************************************************************************** |
* |
* 1. Copyright Notice |
* |
* Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. |
* All rights reserved. |
* |
* 2. License |
* |
* 2.1. This is your license from Intel Corp. under its intellectual property |
* rights. You may have additional license terms from the party that provided |
* you this software, covering your right to use that party's intellectual |
* property rights. |
* |
* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a |
* copy of the source code appearing in this file ("Covered Code") an |
* irrevocable, perpetual, worldwide license under Intel's copyrights in the |
* base code distributed originally by Intel ("Original Intel Code") to copy, |
* make derivatives, distribute, use and display any portion of the Covered |
* Code in any form, with the right to sublicense such rights; and |
* |
* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent |
* license (with the right to sublicense), under only those claims of Intel |
* patents that are infringed by the Original Intel Code, to make, use, sell, |
* offer to sell, and import the Covered Code and derivative works thereof |
* solely to the minimum extent necessary to exercise the above copyright |
* license, and in no event shall the patent license extend to any additions |
* to or modifications of the Original Intel Code. No other license or right |
* is granted directly or by implication, estoppel or otherwise; |
* |
* The above copyright and patent license is granted only if the following |
* conditions are met: |
* |
* 3. Conditions |
* |
* 3.1. Redistribution of Source with Rights to Further Distribute Source. |
* Redistribution of source code of any substantial portion of the Covered |
* Code or modification with rights to further distribute source must include |
* the above Copyright Notice, the above License, this list of Conditions, |
* and the following Disclaimer and Export Compliance provision. In addition, |
* Licensee must cause all Covered Code to which Licensee contributes to |
* contain a file documenting the changes Licensee made to create that Covered |
* Code and the date of any change. Licensee must include in that file the |
* documentation of any changes made by any predecessor Licensee. Licensee |
* must include a prominent statement that the modification is derived, |
* directly or indirectly, from Original Intel Code. |
* |
* 3.2. Redistribution of Source with no Rights to Further Distribute Source. |
* Redistribution of source code of any substantial portion of the Covered |
* Code or modification without rights to further distribute source must |
* include the following Disclaimer and Export Compliance provision in the |
* documentation and/or other materials provided with distribution. In |
* addition, Licensee may not authorize further sublicense of source of any |
* portion of the Covered Code, and must include terms to the effect that the |
* license from Licensee to its licensee is limited to the intellectual |
* property embodied in the software Licensee provides to its licensee, and |
* not to intellectual property embodied in modifications its licensee may |
* make. |
* |
* 3.3. Redistribution of Executable. Redistribution in executable form of any |
* substantial portion of the Covered Code or modification must reproduce the |
* above Copyright Notice, and the following Disclaimer and Export Compliance |
* provision in the documentation and/or other materials provided with the |
* distribution. |
* |
* 3.4. Intel retains all right, title, and interest in and to the Original |
* Intel Code. |
* |
* 3.5. Neither the name Intel nor any other trademark owned or controlled by |
* Intel shall be used in advertising or otherwise to promote the sale, use or |
* other dealings in products derived from or relating to the Covered Code |
* without prior written authorization from Intel. |
* |
* 4. Disclaimer and Export Compliance |
* |
* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED |
* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE |
* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, |
* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY |
* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY |
* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A |
* PARTICULAR PURPOSE. |
* |
* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES |
* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR |
* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, |
* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY |
* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL |
* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS |
* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY |
* LIMITED REMEDY. |
* |
* 4.3. Licensee shall not export, either directly or indirectly, any of this |
* software or system incorporating such software without first obtaining any |
* required license or other approval from the U. S. Department of Commerce or |
* any other agency or department of the United States Government. In the |
* event Licensee exports any such software from the United States or |
* re-exports any such software from a foreign destination, Licensee shall |
* ensure that the distribution and export/re-export of the software is in |
* compliance with all laws, regulations, orders, or other restrictions of the |
* U.S. Export Administration Regulations. Licensee agrees that neither it nor |
* any of its subsidiaries will export/re-export any technical data, process, |
* software, or service, directly or indirectly, to any country for which the |
* United States government or any agency thereof requires an export license, |
* other governmental approval, or letter of assurance, without first obtaining |
* such license, approval or letter. |
* |
*****************************************************************************/ |
#include "acpi.h" |
#include "accommon.h" |
#include "acevents.h" |
#include "acnamesp.h" |
#include "acinterp.h" |
#define _COMPONENT ACPI_EVENTS |
ACPI_MODULE_NAME ("evmisc") |
/* Local prototypes */ |
static void ACPI_SYSTEM_XFACE |
AcpiEvNotifyDispatch ( |
void *Context); |
static UINT32 |
AcpiEvGlobalLockHandler ( |
void *Context); |
static ACPI_STATUS |
AcpiEvRemoveGlobalLockHandler ( |
void); |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvIsNotifyObject |
* |
* PARAMETERS: Node - Node to check |
* |
* RETURN: TRUE if notifies allowed on this object |
* |
* DESCRIPTION: Check type of node for a object that supports notifies. |
* |
* TBD: This could be replaced by a flag bit in the node. |
* |
******************************************************************************/ |
BOOLEAN |
AcpiEvIsNotifyObject ( |
ACPI_NAMESPACE_NODE *Node) |
{ |
switch (Node->Type) |
{ |
case ACPI_TYPE_DEVICE: |
case ACPI_TYPE_PROCESSOR: |
case ACPI_TYPE_THERMAL: |
/* |
* These are the ONLY objects that can receive ACPI notifications |
*/ |
return (TRUE); |
default: |
return (FALSE); |
} |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvQueueNotifyRequest |
* |
* PARAMETERS: Node - NS node for the notified object |
* NotifyValue - Value from the Notify() request |
* |
* RETURN: Status |
* |
* DESCRIPTION: Dispatch a device notification event to a previously |
* installed handler. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvQueueNotifyRequest ( |
ACPI_NAMESPACE_NODE *Node, |
UINT32 NotifyValue) |
{ |
ACPI_OPERAND_OBJECT *ObjDesc; |
ACPI_OPERAND_OBJECT *HandlerObj = NULL; |
ACPI_GENERIC_STATE *NotifyInfo; |
ACPI_STATUS Status = AE_OK; |
ACPI_FUNCTION_NAME (EvQueueNotifyRequest); |
/* |
* For value 3 (Ejection Request), some device method may need to be run. |
* For value 2 (Device Wake) if _PRW exists, the _PS0 method may need |
* to be run. |
* For value 0x80 (Status Change) on the power button or sleep button, |
* initiate soft-off or sleep operation? |
*/ |
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, |
"Dispatching Notify on [%4.4s] Node %p Value 0x%2.2X (%s)\n", |
AcpiUtGetNodeName (Node), Node, NotifyValue, |
AcpiUtGetNotifyName (NotifyValue))); |
/* Get the notify object attached to the NS Node */ |
ObjDesc = AcpiNsGetAttachedObject (Node); |
if (ObjDesc) |
{ |
/* We have the notify object, Get the right handler */ |
switch (Node->Type) |
{ |
/* Notify allowed only on these types */ |
case ACPI_TYPE_DEVICE: |
case ACPI_TYPE_THERMAL: |
case ACPI_TYPE_PROCESSOR: |
if (NotifyValue <= ACPI_MAX_SYS_NOTIFY) |
{ |
HandlerObj = ObjDesc->CommonNotify.SystemNotify; |
} |
else |
{ |
HandlerObj = ObjDesc->CommonNotify.DeviceNotify; |
} |
break; |
default: |
/* All other types are not supported */ |
return (AE_TYPE); |
} |
} |
/* |
* If there is any handler to run, schedule the dispatcher. |
* Check for: |
* 1) Global system notify handler |
* 2) Global device notify handler |
* 3) Per-device notify handler |
*/ |
if ((AcpiGbl_SystemNotify.Handler && |
(NotifyValue <= ACPI_MAX_SYS_NOTIFY)) || |
(AcpiGbl_DeviceNotify.Handler && |
(NotifyValue > ACPI_MAX_SYS_NOTIFY)) || |
HandlerObj) |
{ |
NotifyInfo = AcpiUtCreateGenericState (); |
if (!NotifyInfo) |
{ |
return (AE_NO_MEMORY); |
} |
if (!HandlerObj) |
{ |
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, |
"Executing system notify handler for Notify (%4.4s, %X) " |
"node %p\n", |
AcpiUtGetNodeName (Node), NotifyValue, Node)); |
} |
NotifyInfo->Common.DescriptorType = ACPI_DESC_TYPE_STATE_NOTIFY; |
NotifyInfo->Notify.Node = Node; |
NotifyInfo->Notify.Value = (UINT16) NotifyValue; |
NotifyInfo->Notify.HandlerObj = HandlerObj; |
Status = AcpiOsExecute ( |
OSL_NOTIFY_HANDLER, AcpiEvNotifyDispatch, NotifyInfo); |
if (ACPI_FAILURE (Status)) |
{ |
AcpiUtDeleteGenericState (NotifyInfo); |
} |
} |
else |
{ |
/* There is no notify handler (per-device or system) for this device */ |
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, |
"No notify handler for Notify (%4.4s, %X) node %p\n", |
AcpiUtGetNodeName (Node), NotifyValue, Node)); |
} |
return (Status); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvNotifyDispatch |
* |
* PARAMETERS: Context - To be passed to the notify handler |
* |
* RETURN: None. |
* |
* DESCRIPTION: Dispatch a device notification event to a previously |
* installed handler. |
* |
******************************************************************************/ |
static void ACPI_SYSTEM_XFACE |
AcpiEvNotifyDispatch ( |
void *Context) |
{ |
ACPI_GENERIC_STATE *NotifyInfo = (ACPI_GENERIC_STATE *) Context; |
ACPI_NOTIFY_HANDLER GlobalHandler = NULL; |
void *GlobalContext = NULL; |
ACPI_OPERAND_OBJECT *HandlerObj; |
ACPI_FUNCTION_ENTRY (); |
/* |
* We will invoke a global notify handler if installed. This is done |
* _before_ we invoke the per-device handler attached to the device. |
*/ |
if (NotifyInfo->Notify.Value <= ACPI_MAX_SYS_NOTIFY) |
{ |
/* Global system notification handler */ |
if (AcpiGbl_SystemNotify.Handler) |
{ |
GlobalHandler = AcpiGbl_SystemNotify.Handler; |
GlobalContext = AcpiGbl_SystemNotify.Context; |
} |
} |
else |
{ |
/* Global driver notification handler */ |
if (AcpiGbl_DeviceNotify.Handler) |
{ |
GlobalHandler = AcpiGbl_DeviceNotify.Handler; |
GlobalContext = AcpiGbl_DeviceNotify.Context; |
} |
} |
/* Invoke the system handler first, if present */ |
if (GlobalHandler) |
{ |
GlobalHandler (NotifyInfo->Notify.Node, NotifyInfo->Notify.Value, |
GlobalContext); |
} |
/* Now invoke the per-device handler, if present */ |
HandlerObj = NotifyInfo->Notify.HandlerObj; |
if (HandlerObj) |
{ |
HandlerObj->Notify.Handler (NotifyInfo->Notify.Node, |
NotifyInfo->Notify.Value, |
HandlerObj->Notify.Context); |
} |
/* All done with the info object */ |
AcpiUtDeleteGenericState (NotifyInfo); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvGlobalLockHandler |
* |
* PARAMETERS: Context - From thread interface, not used |
* |
* RETURN: ACPI_INTERRUPT_HANDLED |
* |
* DESCRIPTION: Invoked directly from the SCI handler when a global lock |
* release interrupt occurs. Attempt to acquire the global lock, |
* if successful, signal the thread waiting for the lock. |
* |
* NOTE: Assumes that the semaphore can be signaled from interrupt level. If |
* this is not possible for some reason, a separate thread will have to be |
* scheduled to do this. |
* |
******************************************************************************/ |
static UINT32 |
AcpiEvGlobalLockHandler ( |
void *Context) |
{ |
BOOLEAN Acquired = FALSE; |
ACPI_STATUS Status; |
/* |
* Attempt to get the lock. |
* |
* If we don't get it now, it will be marked pending and we will |
* take another interrupt when it becomes free. |
*/ |
ACPI_ACQUIRE_GLOBAL_LOCK (AcpiGbl_FACS, Acquired); |
if (Acquired) |
{ |
/* Got the lock, now wake the thread waiting for it */ |
AcpiGbl_GlobalLockAcquired = TRUE; |
/* Send a unit to the semaphore */ |
Status = AcpiOsSignalSemaphore (AcpiGbl_GlobalLockSemaphore, 1); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_ERROR ((AE_INFO, "Could not signal Global Lock semaphore")); |
} |
} |
return (ACPI_INTERRUPT_HANDLED); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvInitGlobalLockHandler |
* |
* PARAMETERS: None |
* |
* RETURN: Status |
* |
* DESCRIPTION: Install a handler for the global lock release event |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvInitGlobalLockHandler ( |
void) |
{ |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (EvInitGlobalLockHandler); |
/* Attempt installation of the global lock handler */ |
Status = AcpiInstallFixedEventHandler (ACPI_EVENT_GLOBAL, |
AcpiEvGlobalLockHandler, NULL); |
/* |
* If the global lock does not exist on this platform, the attempt to |
* enable GBL_STATUS will fail (the GBL_ENABLE bit will not stick). |
* Map to AE_OK, but mark global lock as not present. Any attempt to |
* actually use the global lock will be flagged with an error. |
*/ |
if (Status == AE_NO_HARDWARE_RESPONSE) |
{ |
ACPI_ERROR ((AE_INFO, |
"No response from Global Lock hardware, disabling lock")); |
AcpiGbl_GlobalLockPresent = FALSE; |
return_ACPI_STATUS (AE_OK); |
} |
AcpiGbl_GlobalLockPresent = TRUE; |
return_ACPI_STATUS (Status); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvRemoveGlobalLockHandler |
* |
* PARAMETERS: None |
* |
* RETURN: Status |
* |
* DESCRIPTION: Remove the handler for the Global Lock |
* |
******************************************************************************/ |
static ACPI_STATUS |
AcpiEvRemoveGlobalLockHandler ( |
void) |
{ |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (EvRemoveGlobalLockHandler); |
AcpiGbl_GlobalLockPresent = FALSE; |
Status = AcpiRemoveFixedEventHandler (ACPI_EVENT_GLOBAL, |
AcpiEvGlobalLockHandler); |
return_ACPI_STATUS (Status); |
} |
/****************************************************************************** |
* |
* FUNCTION: AcpiEvAcquireGlobalLock |
* |
* PARAMETERS: Timeout - Max time to wait for the lock, in millisec. |
* |
* RETURN: Status |
* |
* DESCRIPTION: Attempt to gain ownership of the Global Lock. |
* |
* MUTEX: Interpreter must be locked |
* |
* Note: The original implementation allowed multiple threads to "acquire" the |
* Global Lock, and the OS would hold the lock until the last thread had |
* released it. However, this could potentially starve the BIOS out of the |
* lock, especially in the case where there is a tight handshake between the |
* Embedded Controller driver and the BIOS. Therefore, this implementation |
* allows only one thread to acquire the HW Global Lock at a time, and makes |
* the global lock appear as a standard mutex on the OS side. |
* |
*****************************************************************************/ |
ACPI_STATUS |
AcpiEvAcquireGlobalLock ( |
UINT16 Timeout) |
{ |
ACPI_STATUS Status = AE_OK; |
BOOLEAN Acquired = FALSE; |
ACPI_FUNCTION_TRACE (EvAcquireGlobalLock); |
/* |
* Only one thread can acquire the GL at a time, the GlobalLockMutex |
* enforces this. This interface releases the interpreter if we must wait. |
*/ |
Status = AcpiExSystemWaitMutex (AcpiGbl_GlobalLockMutex->Mutex.OsMutex, |
Timeout); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
/* |
* Update the global lock handle and check for wraparound. The handle is |
* only used for the external global lock interfaces, but it is updated |
* here to properly handle the case where a single thread may acquire the |
* lock via both the AML and the AcpiAcquireGlobalLock interfaces. The |
* handle is therefore updated on the first acquire from a given thread |
* regardless of where the acquisition request originated. |
*/ |
AcpiGbl_GlobalLockHandle++; |
if (AcpiGbl_GlobalLockHandle == 0) |
{ |
AcpiGbl_GlobalLockHandle = 1; |
} |
/* |
* Make sure that a global lock actually exists. If not, just treat the |
* lock as a standard mutex. |
*/ |
if (!AcpiGbl_GlobalLockPresent) |
{ |
AcpiGbl_GlobalLockAcquired = TRUE; |
return_ACPI_STATUS (AE_OK); |
} |
/* Attempt to acquire the actual hardware lock */ |
ACPI_ACQUIRE_GLOBAL_LOCK (AcpiGbl_FACS, Acquired); |
if (Acquired) |
{ |
/* We got the lock */ |
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Acquired hardware Global Lock\n")); |
AcpiGbl_GlobalLockAcquired = TRUE; |
return_ACPI_STATUS (AE_OK); |
} |
/* |
* Did not get the lock. The pending bit was set above, and we must now |
* wait until we get the global lock released interrupt. |
*/ |
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Waiting for hardware Global Lock\n")); |
/* |
* Wait for handshake with the global lock interrupt handler. |
* This interface releases the interpreter if we must wait. |
*/ |
Status = AcpiExSystemWaitSemaphore (AcpiGbl_GlobalLockSemaphore, |
ACPI_WAIT_FOREVER); |
return_ACPI_STATUS (Status); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvReleaseGlobalLock |
* |
* PARAMETERS: None |
* |
* RETURN: Status |
* |
* DESCRIPTION: Releases ownership of the Global Lock. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvReleaseGlobalLock ( |
void) |
{ |
BOOLEAN Pending = FALSE; |
ACPI_STATUS Status = AE_OK; |
ACPI_FUNCTION_TRACE (EvReleaseGlobalLock); |
/* Lock must be already acquired */ |
if (!AcpiGbl_GlobalLockAcquired) |
{ |
ACPI_WARNING ((AE_INFO, |
"Cannot release the ACPI Global Lock, it has not been acquired")); |
return_ACPI_STATUS (AE_NOT_ACQUIRED); |
} |
if (AcpiGbl_GlobalLockPresent) |
{ |
/* Allow any thread to release the lock */ |
ACPI_RELEASE_GLOBAL_LOCK (AcpiGbl_FACS, Pending); |
/* |
* If the pending bit was set, we must write GBL_RLS to the control |
* register |
*/ |
if (Pending) |
{ |
Status = AcpiWriteBitRegister ( |
ACPI_BITREG_GLOBAL_LOCK_RELEASE, ACPI_ENABLE_EVENT); |
} |
ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Released hardware Global Lock\n")); |
} |
AcpiGbl_GlobalLockAcquired = FALSE; |
/* Release the local GL mutex */ |
AcpiOsReleaseMutex (AcpiGbl_GlobalLockMutex->Mutex.OsMutex); |
return_ACPI_STATUS (Status); |
} |
/****************************************************************************** |
* |
* FUNCTION: AcpiEvTerminate |
* |
* PARAMETERS: none |
* |
* RETURN: none |
* |
* DESCRIPTION: Disable events and free memory allocated for table storage. |
* |
******************************************************************************/ |
void |
AcpiEvTerminate ( |
void) |
{ |
UINT32 i; |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (EvTerminate); |
if (AcpiGbl_EventsInitialized) |
{ |
/* |
* Disable all event-related functionality. In all cases, on error, |
* print a message but obviously we don't abort. |
*/ |
/* Disable all fixed events */ |
for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++) |
{ |
Status = AcpiDisableEvent (i, 0); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_ERROR ((AE_INFO, |
"Could not disable fixed event %u", (UINT32) i)); |
} |
} |
/* Disable all GPEs in all GPE blocks */ |
Status = AcpiEvWalkGpeList (AcpiHwDisableGpeBlock, NULL); |
/* Remove SCI handler */ |
Status = AcpiEvRemoveSciHandler (); |
if (ACPI_FAILURE(Status)) |
{ |
ACPI_ERROR ((AE_INFO, |
"Could not remove SCI handler")); |
} |
Status = AcpiEvRemoveGlobalLockHandler (); |
if (ACPI_FAILURE(Status)) |
{ |
ACPI_ERROR ((AE_INFO, |
"Could not remove Global Lock handler")); |
} |
} |
/* Deallocate all handler objects installed within GPE info structs */ |
Status = AcpiEvWalkGpeList (AcpiEvDeleteGpeHandlers, NULL); |
/* Return to original mode if necessary */ |
if (AcpiGbl_OriginalMode == ACPI_SYS_MODE_LEGACY) |
{ |
Status = AcpiDisable (); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_WARNING ((AE_INFO, "AcpiDisable failed")); |
} |
} |
return_VOID; |
} |
/drivers/devman/acpica/events/evregion.c |
---|
0,0 → 1,1284 |
/****************************************************************************** |
* |
* Module Name: evregion - ACPI AddressSpace (OpRegion) handler dispatch |
* |
*****************************************************************************/ |
/****************************************************************************** |
* |
* 1. Copyright Notice |
* |
* Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. |
* All rights reserved. |
* |
* 2. License |
* |
* 2.1. This is your license from Intel Corp. under its intellectual property |
* rights. You may have additional license terms from the party that provided |
* you this software, covering your right to use that party's intellectual |
* property rights. |
* |
* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a |
* copy of the source code appearing in this file ("Covered Code") an |
* irrevocable, perpetual, worldwide license under Intel's copyrights in the |
* base code distributed originally by Intel ("Original Intel Code") to copy, |
* make derivatives, distribute, use and display any portion of the Covered |
* Code in any form, with the right to sublicense such rights; and |
* |
* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent |
* license (with the right to sublicense), under only those claims of Intel |
* patents that are infringed by the Original Intel Code, to make, use, sell, |
* offer to sell, and import the Covered Code and derivative works thereof |
* solely to the minimum extent necessary to exercise the above copyright |
* license, and in no event shall the patent license extend to any additions |
* to or modifications of the Original Intel Code. No other license or right |
* is granted directly or by implication, estoppel or otherwise; |
* |
* The above copyright and patent license is granted only if the following |
* conditions are met: |
* |
* 3. Conditions |
* |
* 3.1. Redistribution of Source with Rights to Further Distribute Source. |
* Redistribution of source code of any substantial portion of the Covered |
* Code or modification with rights to further distribute source must include |
* the above Copyright Notice, the above License, this list of Conditions, |
* and the following Disclaimer and Export Compliance provision. In addition, |
* Licensee must cause all Covered Code to which Licensee contributes to |
* contain a file documenting the changes Licensee made to create that Covered |
* Code and the date of any change. Licensee must include in that file the |
* documentation of any changes made by any predecessor Licensee. Licensee |
* must include a prominent statement that the modification is derived, |
* directly or indirectly, from Original Intel Code. |
* |
* 3.2. Redistribution of Source with no Rights to Further Distribute Source. |
* Redistribution of source code of any substantial portion of the Covered |
* Code or modification without rights to further distribute source must |
* include the following Disclaimer and Export Compliance provision in the |
* documentation and/or other materials provided with distribution. In |
* addition, Licensee may not authorize further sublicense of source of any |
* portion of the Covered Code, and must include terms to the effect that the |
* license from Licensee to its licensee is limited to the intellectual |
* property embodied in the software Licensee provides to its licensee, and |
* not to intellectual property embodied in modifications its licensee may |
* make. |
* |
* 3.3. Redistribution of Executable. Redistribution in executable form of any |
* substantial portion of the Covered Code or modification must reproduce the |
* above Copyright Notice, and the following Disclaimer and Export Compliance |
* provision in the documentation and/or other materials provided with the |
* distribution. |
* |
* 3.4. Intel retains all right, title, and interest in and to the Original |
* Intel Code. |
* |
* 3.5. Neither the name Intel nor any other trademark owned or controlled by |
* Intel shall be used in advertising or otherwise to promote the sale, use or |
* other dealings in products derived from or relating to the Covered Code |
* without prior written authorization from Intel. |
* |
* 4. Disclaimer and Export Compliance |
* |
* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED |
* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE |
* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, |
* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY |
* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY |
* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A |
* PARTICULAR PURPOSE. |
* |
* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES |
* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR |
* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, |
* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY |
* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL |
* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS |
* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY |
* LIMITED REMEDY. |
* |
* 4.3. Licensee shall not export, either directly or indirectly, any of this |
* software or system incorporating such software without first obtaining any |
* required license or other approval from the U. S. Department of Commerce or |
* any other agency or department of the United States Government. In the |
* event Licensee exports any such software from the United States or |
* re-exports any such software from a foreign destination, Licensee shall |
* ensure that the distribution and export/re-export of the software is in |
* compliance with all laws, regulations, orders, or other restrictions of the |
* U.S. Export Administration Regulations. Licensee agrees that neither it nor |
* any of its subsidiaries will export/re-export any technical data, process, |
* software, or service, directly or indirectly, to any country for which the |
* United States government or any agency thereof requires an export license, |
* other governmental approval, or letter of assurance, without first obtaining |
* such license, approval or letter. |
* |
*****************************************************************************/ |
#define __EVREGION_C__ |
#include "acpi.h" |
#include "accommon.h" |
#include "acevents.h" |
#include "acnamesp.h" |
#include "acinterp.h" |
#define _COMPONENT ACPI_EVENTS |
ACPI_MODULE_NAME ("evregion") |
/* Local prototypes */ |
static BOOLEAN |
AcpiEvHasDefaultHandler ( |
ACPI_NAMESPACE_NODE *Node, |
ACPI_ADR_SPACE_TYPE SpaceId); |
static ACPI_STATUS |
AcpiEvRegRun ( |
ACPI_HANDLE ObjHandle, |
UINT32 Level, |
void *Context, |
void **ReturnValue); |
static ACPI_STATUS |
AcpiEvInstallHandler ( |
ACPI_HANDLE ObjHandle, |
UINT32 Level, |
void *Context, |
void **ReturnValue); |
/* These are the address spaces that will get default handlers */ |
#define ACPI_NUM_DEFAULT_SPACES 4 |
static UINT8 AcpiGbl_DefaultAddressSpaces[ACPI_NUM_DEFAULT_SPACES] = |
{ |
ACPI_ADR_SPACE_SYSTEM_MEMORY, |
ACPI_ADR_SPACE_SYSTEM_IO, |
ACPI_ADR_SPACE_PCI_CONFIG, |
ACPI_ADR_SPACE_DATA_TABLE |
}; |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvInstallRegionHandlers |
* |
* PARAMETERS: None |
* |
* RETURN: Status |
* |
* DESCRIPTION: Installs the core subsystem default address space handlers. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvInstallRegionHandlers ( |
void) |
{ |
ACPI_STATUS Status; |
UINT32 i; |
ACPI_FUNCTION_TRACE (EvInstallRegionHandlers); |
Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
/* |
* All address spaces (PCI Config, EC, SMBus) are scope dependent and |
* registration must occur for a specific device. |
* |
* In the case of the system memory and IO address spaces there is |
* currently no device associated with the address space. For these we |
* use the root. |
* |
* We install the default PCI config space handler at the root so that |
* this space is immediately available even though the we have not |
* enumerated all the PCI Root Buses yet. This is to conform to the ACPI |
* specification which states that the PCI config space must be always |
* available -- even though we are nowhere near ready to find the PCI root |
* buses at this point. |
* |
* NOTE: We ignore AE_ALREADY_EXISTS because this means that a handler |
* has already been installed (via AcpiInstallAddressSpaceHandler). |
* Similar for AE_SAME_HANDLER. |
*/ |
for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) |
{ |
Status = AcpiEvInstallSpaceHandler (AcpiGbl_RootNode, |
AcpiGbl_DefaultAddressSpaces[i], |
ACPI_DEFAULT_HANDLER, NULL, NULL); |
switch (Status) |
{ |
case AE_OK: |
case AE_SAME_HANDLER: |
case AE_ALREADY_EXISTS: |
/* These exceptions are all OK */ |
Status = AE_OK; |
break; |
default: |
goto UnlockAndExit; |
} |
} |
UnlockAndExit: |
(void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); |
return_ACPI_STATUS (Status); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvHasDefaultHandler |
* |
* PARAMETERS: Node - Namespace node for the device |
* SpaceId - The address space ID |
* |
* RETURN: TRUE if default handler is installed, FALSE otherwise |
* |
* DESCRIPTION: Check if the default handler is installed for the requested |
* space ID. |
* |
******************************************************************************/ |
static BOOLEAN |
AcpiEvHasDefaultHandler ( |
ACPI_NAMESPACE_NODE *Node, |
ACPI_ADR_SPACE_TYPE SpaceId) |
{ |
ACPI_OPERAND_OBJECT *ObjDesc; |
ACPI_OPERAND_OBJECT *HandlerObj; |
/* Must have an existing internal object */ |
ObjDesc = AcpiNsGetAttachedObject (Node); |
if (ObjDesc) |
{ |
HandlerObj = ObjDesc->Device.Handler; |
/* Walk the linked list of handlers for this object */ |
while (HandlerObj) |
{ |
if (HandlerObj->AddressSpace.SpaceId == SpaceId) |
{ |
if (HandlerObj->AddressSpace.HandlerFlags & |
ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) |
{ |
return (TRUE); |
} |
} |
HandlerObj = HandlerObj->AddressSpace.Next; |
} |
} |
return (FALSE); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvInitializeOpRegions |
* |
* PARAMETERS: None |
* |
* RETURN: Status |
* |
* DESCRIPTION: Execute _REG methods for all Operation Regions that have |
* an installed default region handler. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvInitializeOpRegions ( |
void) |
{ |
ACPI_STATUS Status; |
UINT32 i; |
ACPI_FUNCTION_TRACE (EvInitializeOpRegions); |
Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
/* Run the _REG methods for OpRegions in each default address space */ |
for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) |
{ |
/* |
* Make sure the installed handler is the DEFAULT handler. If not the |
* default, the _REG methods will have already been run (when the |
* handler was installed) |
*/ |
if (AcpiEvHasDefaultHandler (AcpiGbl_RootNode, |
AcpiGbl_DefaultAddressSpaces[i])) |
{ |
Status = AcpiEvExecuteRegMethods (AcpiGbl_RootNode, |
AcpiGbl_DefaultAddressSpaces[i]); |
} |
} |
(void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); |
return_ACPI_STATUS (Status); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvExecuteRegMethod |
* |
* PARAMETERS: RegionObj - Region object |
* Function - Passed to _REG: On (1) or Off (0) |
* |
* RETURN: Status |
* |
* DESCRIPTION: Execute _REG method for a region |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvExecuteRegMethod ( |
ACPI_OPERAND_OBJECT *RegionObj, |
UINT32 Function) |
{ |
ACPI_EVALUATE_INFO *Info; |
ACPI_OPERAND_OBJECT *Args[3]; |
ACPI_OPERAND_OBJECT *RegionObj2; |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (EvExecuteRegMethod); |
RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); |
if (!RegionObj2) |
{ |
return_ACPI_STATUS (AE_NOT_EXIST); |
} |
if (RegionObj2->Extra.Method_REG == NULL) |
{ |
return_ACPI_STATUS (AE_OK); |
} |
/* Allocate and initialize the evaluation information block */ |
Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); |
if (!Info) |
{ |
return_ACPI_STATUS (AE_NO_MEMORY); |
} |
Info->PrefixNode = RegionObj2->Extra.Method_REG; |
Info->Pathname = NULL; |
Info->Parameters = Args; |
Info->Flags = ACPI_IGNORE_RETURN_VALUE; |
/* |
* The _REG method has two arguments: |
* |
* Arg0 - Integer: |
* Operation region space ID Same value as RegionObj->Region.SpaceId |
* |
* Arg1 - Integer: |
* connection status 1 for connecting the handler, 0 for disconnecting |
* the handler (Passed as a parameter) |
*/ |
Args[0] = AcpiUtCreateIntegerObject ((UINT64) RegionObj->Region.SpaceId); |
if (!Args[0]) |
{ |
Status = AE_NO_MEMORY; |
goto Cleanup1; |
} |
Args[1] = AcpiUtCreateIntegerObject ((UINT64) Function); |
if (!Args[1]) |
{ |
Status = AE_NO_MEMORY; |
goto Cleanup2; |
} |
Args[2] = NULL; /* Terminate list */ |
/* Execute the method, no return value */ |
ACPI_DEBUG_EXEC ( |
AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Info->PrefixNode, NULL)); |
Status = AcpiNsEvaluate (Info); |
AcpiUtRemoveReference (Args[1]); |
Cleanup2: |
AcpiUtRemoveReference (Args[0]); |
Cleanup1: |
ACPI_FREE (Info); |
return_ACPI_STATUS (Status); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvAddressSpaceDispatch |
* |
* PARAMETERS: RegionObj - Internal region object |
* Function - Read or Write operation |
* RegionOffset - Where in the region to read or write |
* BitWidth - Field width in bits (8, 16, 32, or 64) |
* Value - Pointer to in or out value, must be |
* a full 64-bit integer |
* |
* RETURN: Status |
* |
* DESCRIPTION: Dispatch an address space or operation region access to |
* a previously installed handler. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvAddressSpaceDispatch ( |
ACPI_OPERAND_OBJECT *RegionObj, |
UINT32 Function, |
UINT32 RegionOffset, |
UINT32 BitWidth, |
UINT64 *Value) |
{ |
ACPI_STATUS Status; |
ACPI_ADR_SPACE_HANDLER Handler; |
ACPI_ADR_SPACE_SETUP RegionSetup; |
ACPI_OPERAND_OBJECT *HandlerDesc; |
ACPI_OPERAND_OBJECT *RegionObj2; |
void *RegionContext = NULL; |
ACPI_FUNCTION_TRACE (EvAddressSpaceDispatch); |
RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); |
if (!RegionObj2) |
{ |
return_ACPI_STATUS (AE_NOT_EXIST); |
} |
/* Ensure that there is a handler associated with this region */ |
HandlerDesc = RegionObj->Region.Handler; |
if (!HandlerDesc) |
{ |
ACPI_ERROR ((AE_INFO, |
"No handler for Region [%4.4s] (%p) [%s]", |
AcpiUtGetNodeName (RegionObj->Region.Node), |
RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId))); |
return_ACPI_STATUS (AE_NOT_EXIST); |
} |
/* |
* It may be the case that the region has never been initialized. |
* Some types of regions require special init code |
*/ |
if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)) |
{ |
/* This region has not been initialized yet, do it */ |
RegionSetup = HandlerDesc->AddressSpace.Setup; |
if (!RegionSetup) |
{ |
/* No initialization routine, exit with error */ |
ACPI_ERROR ((AE_INFO, |
"No init routine for region(%p) [%s]", |
RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId))); |
return_ACPI_STATUS (AE_NOT_EXIST); |
} |
/* |
* We must exit the interpreter because the region setup will |
* potentially execute control methods (for example, the _REG method |
* for this region) |
*/ |
AcpiExExitInterpreter (); |
Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE, |
HandlerDesc->AddressSpace.Context, &RegionContext); |
/* Re-enter the interpreter */ |
AcpiExEnterInterpreter (); |
/* Check for failure of the Region Setup */ |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, |
"During region initialization: [%s]", |
AcpiUtGetRegionName (RegionObj->Region.SpaceId))); |
return_ACPI_STATUS (Status); |
} |
/* Region initialization may have been completed by RegionSetup */ |
if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)) |
{ |
RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE; |
if (RegionObj2->Extra.RegionContext) |
{ |
/* The handler for this region was already installed */ |
ACPI_FREE (RegionContext); |
} |
else |
{ |
/* |
* Save the returned context for use in all accesses to |
* this particular region |
*/ |
RegionObj2->Extra.RegionContext = RegionContext; |
} |
} |
} |
/* We have everything we need, we can invoke the address space handler */ |
Handler = HandlerDesc->AddressSpace.Handler; |
ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, |
"Handler %p (@%p) Address %8.8X%8.8X [%s]\n", |
&RegionObj->Region.Handler->AddressSpace, Handler, |
ACPI_FORMAT_NATIVE_UINT (RegionObj->Region.Address + RegionOffset), |
AcpiUtGetRegionName (RegionObj->Region.SpaceId))); |
if (!(HandlerDesc->AddressSpace.HandlerFlags & |
ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) |
{ |
/* |
* For handlers other than the default (supplied) handlers, we must |
* exit the interpreter because the handler *might* block -- we don't |
* know what it will do, so we can't hold the lock on the intepreter. |
*/ |
AcpiExExitInterpreter(); |
} |
/* Call the handler */ |
Status = Handler (Function, |
(RegionObj->Region.Address + RegionOffset), BitWidth, Value, |
HandlerDesc->AddressSpace.Context, RegionObj2->Extra.RegionContext); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, "Returned by Handler for [%s]", |
AcpiUtGetRegionName (RegionObj->Region.SpaceId))); |
} |
if (!(HandlerDesc->AddressSpace.HandlerFlags & |
ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) |
{ |
/* |
* We just returned from a non-default handler, we must re-enter the |
* interpreter |
*/ |
AcpiExEnterInterpreter (); |
} |
return_ACPI_STATUS (Status); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvDetachRegion |
* |
* PARAMETERS: RegionObj - Region Object |
* AcpiNsIsLocked - Namespace Region Already Locked? |
* |
* RETURN: None |
* |
* DESCRIPTION: Break the association between the handler and the region |
* this is a two way association. |
* |
******************************************************************************/ |
void |
AcpiEvDetachRegion( |
ACPI_OPERAND_OBJECT *RegionObj, |
BOOLEAN AcpiNsIsLocked) |
{ |
ACPI_OPERAND_OBJECT *HandlerObj; |
ACPI_OPERAND_OBJECT *ObjDesc; |
ACPI_OPERAND_OBJECT **LastObjPtr; |
ACPI_ADR_SPACE_SETUP RegionSetup; |
void **RegionContext; |
ACPI_OPERAND_OBJECT *RegionObj2; |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (EvDetachRegion); |
RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); |
if (!RegionObj2) |
{ |
return_VOID; |
} |
RegionContext = &RegionObj2->Extra.RegionContext; |
/* Get the address handler from the region object */ |
HandlerObj = RegionObj->Region.Handler; |
if (!HandlerObj) |
{ |
/* This region has no handler, all done */ |
return_VOID; |
} |
/* Find this region in the handler's list */ |
ObjDesc = HandlerObj->AddressSpace.RegionList; |
LastObjPtr = &HandlerObj->AddressSpace.RegionList; |
while (ObjDesc) |
{ |
/* Is this the correct Region? */ |
if (ObjDesc == RegionObj) |
{ |
ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, |
"Removing Region %p from address handler %p\n", |
RegionObj, HandlerObj)); |
/* This is it, remove it from the handler's list */ |
*LastObjPtr = ObjDesc->Region.Next; |
ObjDesc->Region.Next = NULL; /* Must clear field */ |
if (AcpiNsIsLocked) |
{ |
Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); |
if (ACPI_FAILURE (Status)) |
{ |
return_VOID; |
} |
} |
/* Now stop region accesses by executing the _REG method */ |
Status = AcpiEvExecuteRegMethod (RegionObj, 0); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, "from region _REG, [%s]", |
AcpiUtGetRegionName (RegionObj->Region.SpaceId))); |
} |
if (AcpiNsIsLocked) |
{ |
Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); |
if (ACPI_FAILURE (Status)) |
{ |
return_VOID; |
} |
} |
/* |
* If the region has been activated, call the setup handler with |
* the deactivate notification |
*/ |
if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE) |
{ |
RegionSetup = HandlerObj->AddressSpace.Setup; |
Status = RegionSetup (RegionObj, ACPI_REGION_DEACTIVATE, |
HandlerObj->AddressSpace.Context, RegionContext); |
/* Init routine may fail, Just ignore errors */ |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, |
"from region handler - deactivate, [%s]", |
AcpiUtGetRegionName (RegionObj->Region.SpaceId))); |
} |
RegionObj->Region.Flags &= ~(AOPOBJ_SETUP_COMPLETE); |
} |
/* |
* Remove handler reference in the region |
* |
* NOTE: this doesn't mean that the region goes away, the region |
* is just inaccessible as indicated to the _REG method |
* |
* If the region is on the handler's list, this must be the |
* region's handler |
*/ |
RegionObj->Region.Handler = NULL; |
AcpiUtRemoveReference (HandlerObj); |
return_VOID; |
} |
/* Walk the linked list of handlers */ |
LastObjPtr = &ObjDesc->Region.Next; |
ObjDesc = ObjDesc->Region.Next; |
} |
/* If we get here, the region was not in the handler's region list */ |
ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, |
"Cannot remove region %p from address handler %p\n", |
RegionObj, HandlerObj)); |
return_VOID; |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvAttachRegion |
* |
* PARAMETERS: HandlerObj - Handler Object |
* RegionObj - Region Object |
* AcpiNsIsLocked - Namespace Region Already Locked? |
* |
* RETURN: None |
* |
* DESCRIPTION: Create the association between the handler and the region |
* this is a two way association. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvAttachRegion ( |
ACPI_OPERAND_OBJECT *HandlerObj, |
ACPI_OPERAND_OBJECT *RegionObj, |
BOOLEAN AcpiNsIsLocked) |
{ |
ACPI_FUNCTION_TRACE (EvAttachRegion); |
ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, |
"Adding Region [%4.4s] %p to address handler %p [%s]\n", |
AcpiUtGetNodeName (RegionObj->Region.Node), |
RegionObj, HandlerObj, |
AcpiUtGetRegionName (RegionObj->Region.SpaceId))); |
/* Link this region to the front of the handler's list */ |
RegionObj->Region.Next = HandlerObj->AddressSpace.RegionList; |
HandlerObj->AddressSpace.RegionList = RegionObj; |
/* Install the region's handler */ |
if (RegionObj->Region.Handler) |
{ |
return_ACPI_STATUS (AE_ALREADY_EXISTS); |
} |
RegionObj->Region.Handler = HandlerObj; |
AcpiUtAddReference (HandlerObj); |
return_ACPI_STATUS (AE_OK); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvInstallHandler |
* |
* PARAMETERS: WalkNamespace callback |
* |
* DESCRIPTION: This routine installs an address handler into objects that are |
* of type Region or Device. |
* |
* If the Object is a Device, and the device has a handler of |
* the same type then the search is terminated in that branch. |
* |
* This is because the existing handler is closer in proximity |
* to any more regions than the one we are trying to install. |
* |
******************************************************************************/ |
static ACPI_STATUS |
AcpiEvInstallHandler ( |
ACPI_HANDLE ObjHandle, |
UINT32 Level, |
void *Context, |
void **ReturnValue) |
{ |
ACPI_OPERAND_OBJECT *HandlerObj; |
ACPI_OPERAND_OBJECT *NextHandlerObj; |
ACPI_OPERAND_OBJECT *ObjDesc; |
ACPI_NAMESPACE_NODE *Node; |
ACPI_STATUS Status; |
ACPI_FUNCTION_NAME (EvInstallHandler); |
HandlerObj = (ACPI_OPERAND_OBJECT *) Context; |
/* Parameter validation */ |
if (!HandlerObj) |
{ |
return (AE_OK); |
} |
/* Convert and validate the device handle */ |
Node = AcpiNsValidateHandle (ObjHandle); |
if (!Node) |
{ |
return (AE_BAD_PARAMETER); |
} |
/* |
* We only care about regions and objects that are allowed to have |
* address space handlers |
*/ |
if ((Node->Type != ACPI_TYPE_DEVICE) && |
(Node->Type != ACPI_TYPE_REGION) && |
(Node != AcpiGbl_RootNode)) |
{ |
return (AE_OK); |
} |
/* Check for an existing internal object */ |
ObjDesc = AcpiNsGetAttachedObject (Node); |
if (!ObjDesc) |
{ |
/* No object, just exit */ |
return (AE_OK); |
} |
/* Devices are handled different than regions */ |
if (ObjDesc->Common.Type == ACPI_TYPE_DEVICE) |
{ |
/* Check if this Device already has a handler for this address space */ |
NextHandlerObj = ObjDesc->Device.Handler; |
while (NextHandlerObj) |
{ |
/* Found a handler, is it for the same address space? */ |
if (NextHandlerObj->AddressSpace.SpaceId == |
HandlerObj->AddressSpace.SpaceId) |
{ |
ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, |
"Found handler for region [%s] in device %p(%p) " |
"handler %p\n", |
AcpiUtGetRegionName (HandlerObj->AddressSpace.SpaceId), |
ObjDesc, NextHandlerObj, HandlerObj)); |
/* |
* Since the object we found it on was a device, then it |
* means that someone has already installed a handler for |
* the branch of the namespace from this device on. Just |
* bail out telling the walk routine to not traverse this |
* branch. This preserves the scoping rule for handlers. |
*/ |
return (AE_CTRL_DEPTH); |
} |
/* Walk the linked list of handlers attached to this device */ |
NextHandlerObj = NextHandlerObj->AddressSpace.Next; |
} |
/* |
* As long as the device didn't have a handler for this space we |
* don't care about it. We just ignore it and proceed. |
*/ |
return (AE_OK); |
} |
/* Object is a Region */ |
if (ObjDesc->Region.SpaceId != HandlerObj->AddressSpace.SpaceId) |
{ |
/* This region is for a different address space, just ignore it */ |
return (AE_OK); |
} |
/* |
* Now we have a region and it is for the handler's address space type. |
* |
* First disconnect region for any previous handler (if any) |
*/ |
AcpiEvDetachRegion (ObjDesc, FALSE); |
/* Connect the region to the new handler */ |
Status = AcpiEvAttachRegion (HandlerObj, ObjDesc, FALSE); |
return (Status); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvInstallSpaceHandler |
* |
* PARAMETERS: Node - Namespace node for the device |
* SpaceId - The address space ID |
* Handler - Address of the handler |
* Setup - Address of the setup function |
* Context - Value passed to the handler on each access |
* |
* RETURN: Status |
* |
* DESCRIPTION: Install a handler for all OpRegions of a given SpaceId. |
* Assumes namespace is locked |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvInstallSpaceHandler ( |
ACPI_NAMESPACE_NODE *Node, |
ACPI_ADR_SPACE_TYPE SpaceId, |
ACPI_ADR_SPACE_HANDLER Handler, |
ACPI_ADR_SPACE_SETUP Setup, |
void *Context) |
{ |
ACPI_OPERAND_OBJECT *ObjDesc; |
ACPI_OPERAND_OBJECT *HandlerObj; |
ACPI_STATUS Status; |
ACPI_OBJECT_TYPE Type; |
UINT8 Flags = 0; |
ACPI_FUNCTION_TRACE (EvInstallSpaceHandler); |
/* |
* This registration is valid for only the types below and the root. This |
* is where the default handlers get placed. |
*/ |
if ((Node->Type != ACPI_TYPE_DEVICE) && |
(Node->Type != ACPI_TYPE_PROCESSOR) && |
(Node->Type != ACPI_TYPE_THERMAL) && |
(Node != AcpiGbl_RootNode)) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
if (Handler == ACPI_DEFAULT_HANDLER) |
{ |
Flags = ACPI_ADDR_HANDLER_DEFAULT_INSTALLED; |
switch (SpaceId) |
{ |
case ACPI_ADR_SPACE_SYSTEM_MEMORY: |
Handler = AcpiExSystemMemorySpaceHandler; |
Setup = AcpiEvSystemMemoryRegionSetup; |
break; |
case ACPI_ADR_SPACE_SYSTEM_IO: |
Handler = AcpiExSystemIoSpaceHandler; |
Setup = AcpiEvIoSpaceRegionSetup; |
break; |
case ACPI_ADR_SPACE_PCI_CONFIG: |
Handler = AcpiExPciConfigSpaceHandler; |
Setup = AcpiEvPciConfigRegionSetup; |
break; |
case ACPI_ADR_SPACE_CMOS: |
Handler = AcpiExCmosSpaceHandler; |
Setup = AcpiEvCmosRegionSetup; |
break; |
case ACPI_ADR_SPACE_PCI_BAR_TARGET: |
Handler = AcpiExPciBarSpaceHandler; |
Setup = AcpiEvPciBarRegionSetup; |
break; |
case ACPI_ADR_SPACE_DATA_TABLE: |
Handler = AcpiExDataTableSpaceHandler; |
Setup = NULL; |
break; |
default: |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
} |
/* If the caller hasn't specified a setup routine, use the default */ |
if (!Setup) |
{ |
Setup = AcpiEvDefaultRegionSetup; |
} |
/* Check for an existing internal object */ |
ObjDesc = AcpiNsGetAttachedObject (Node); |
if (ObjDesc) |
{ |
/* |
* The attached device object already exists. Make sure the handler |
* is not already installed. |
*/ |
HandlerObj = ObjDesc->Device.Handler; |
/* Walk the handler list for this device */ |
while (HandlerObj) |
{ |
/* Same SpaceId indicates a handler already installed */ |
if (HandlerObj->AddressSpace.SpaceId == SpaceId) |
{ |
if (HandlerObj->AddressSpace.Handler == Handler) |
{ |
/* |
* It is (relatively) OK to attempt to install the SAME |
* handler twice. This can easily happen with the |
* PCI_Config space. |
*/ |
Status = AE_SAME_HANDLER; |
goto UnlockAndExit; |
} |
else |
{ |
/* A handler is already installed */ |
Status = AE_ALREADY_EXISTS; |
} |
goto UnlockAndExit; |
} |
/* Walk the linked list of handlers */ |
HandlerObj = HandlerObj->AddressSpace.Next; |
} |
} |
else |
{ |
ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, |
"Creating object on Device %p while installing handler\n", Node)); |
/* ObjDesc does not exist, create one */ |
if (Node->Type == ACPI_TYPE_ANY) |
{ |
Type = ACPI_TYPE_DEVICE; |
} |
else |
{ |
Type = Node->Type; |
} |
ObjDesc = AcpiUtCreateInternalObject (Type); |
if (!ObjDesc) |
{ |
Status = AE_NO_MEMORY; |
goto UnlockAndExit; |
} |
/* Init new descriptor */ |
ObjDesc->Common.Type = (UINT8) Type; |
/* Attach the new object to the Node */ |
Status = AcpiNsAttachObject (Node, ObjDesc, Type); |
/* Remove local reference to the object */ |
AcpiUtRemoveReference (ObjDesc); |
if (ACPI_FAILURE (Status)) |
{ |
goto UnlockAndExit; |
} |
} |
ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, |
"Installing address handler for region %s(%X) on Device %4.4s %p(%p)\n", |
AcpiUtGetRegionName (SpaceId), SpaceId, |
AcpiUtGetNodeName (Node), Node, ObjDesc)); |
/* |
* Install the handler |
* |
* At this point there is no existing handler. Just allocate the object |
* for the handler and link it into the list. |
*/ |
HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_ADDRESS_HANDLER); |
if (!HandlerObj) |
{ |
Status = AE_NO_MEMORY; |
goto UnlockAndExit; |
} |
/* Init handler obj */ |
HandlerObj->AddressSpace.SpaceId = (UINT8) SpaceId; |
HandlerObj->AddressSpace.HandlerFlags = Flags; |
HandlerObj->AddressSpace.RegionList = NULL; |
HandlerObj->AddressSpace.Node = Node; |
HandlerObj->AddressSpace.Handler = Handler; |
HandlerObj->AddressSpace.Context = Context; |
HandlerObj->AddressSpace.Setup = Setup; |
/* Install at head of Device.AddressSpace list */ |
HandlerObj->AddressSpace.Next = ObjDesc->Device.Handler; |
/* |
* The Device object is the first reference on the HandlerObj. |
* Each region that uses the handler adds a reference. |
*/ |
ObjDesc->Device.Handler = HandlerObj; |
/* |
* Walk the namespace finding all of the regions this |
* handler will manage. |
* |
* Start at the device and search the branch toward |
* the leaf nodes until either the leaf is encountered or |
* a device is detected that has an address handler of the |
* same type. |
* |
* In either case, back up and search down the remainder |
* of the branch |
*/ |
Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX, |
ACPI_NS_WALK_UNLOCK, AcpiEvInstallHandler, NULL, |
HandlerObj, NULL); |
UnlockAndExit: |
return_ACPI_STATUS (Status); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvExecuteRegMethods |
* |
* PARAMETERS: Node - Namespace node for the device |
* SpaceId - The address space ID |
* |
* RETURN: Status |
* |
* DESCRIPTION: Run all _REG methods for the input Space ID; |
* Note: assumes namespace is locked, or system init time. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvExecuteRegMethods ( |
ACPI_NAMESPACE_NODE *Node, |
ACPI_ADR_SPACE_TYPE SpaceId) |
{ |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (EvExecuteRegMethods); |
/* |
* Run all _REG methods for all Operation Regions for this space ID. This |
* is a separate walk in order to handle any interdependencies between |
* regions and _REG methods. (i.e. handlers must be installed for all |
* regions of this Space ID before we can run any _REG methods) |
*/ |
Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX, |
ACPI_NS_WALK_UNLOCK, AcpiEvRegRun, NULL, |
&SpaceId, NULL); |
return_ACPI_STATUS (Status); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvRegRun |
* |
* PARAMETERS: WalkNamespace callback |
* |
* DESCRIPTION: Run _REG method for region objects of the requested spaceID |
* |
******************************************************************************/ |
static ACPI_STATUS |
AcpiEvRegRun ( |
ACPI_HANDLE ObjHandle, |
UINT32 Level, |
void *Context, |
void **ReturnValue) |
{ |
ACPI_OPERAND_OBJECT *ObjDesc; |
ACPI_NAMESPACE_NODE *Node; |
ACPI_ADR_SPACE_TYPE SpaceId; |
ACPI_STATUS Status; |
SpaceId = *ACPI_CAST_PTR (ACPI_ADR_SPACE_TYPE, Context); |
/* Convert and validate the device handle */ |
Node = AcpiNsValidateHandle (ObjHandle); |
if (!Node) |
{ |
return (AE_BAD_PARAMETER); |
} |
/* |
* We only care about regions.and objects that are allowed to have address |
* space handlers |
*/ |
if ((Node->Type != ACPI_TYPE_REGION) && |
(Node != AcpiGbl_RootNode)) |
{ |
return (AE_OK); |
} |
/* Check for an existing internal object */ |
ObjDesc = AcpiNsGetAttachedObject (Node); |
if (!ObjDesc) |
{ |
/* No object, just exit */ |
return (AE_OK); |
} |
/* Object is a Region */ |
if (ObjDesc->Region.SpaceId != SpaceId) |
{ |
/* This region is for a different address space, just ignore it */ |
return (AE_OK); |
} |
Status = AcpiEvExecuteRegMethod (ObjDesc, 1); |
return (Status); |
} |
/drivers/devman/acpica/events/evrgnini.c |
---|
0,0 → 1,799 |
/****************************************************************************** |
* |
* Module Name: evrgnini- ACPI AddressSpace (OpRegion) init |
* |
*****************************************************************************/ |
/****************************************************************************** |
* |
* 1. Copyright Notice |
* |
* Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. |
* All rights reserved. |
* |
* 2. License |
* |
* 2.1. This is your license from Intel Corp. under its intellectual property |
* rights. You may have additional license terms from the party that provided |
* you this software, covering your right to use that party's intellectual |
* property rights. |
* |
* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a |
* copy of the source code appearing in this file ("Covered Code") an |
* irrevocable, perpetual, worldwide license under Intel's copyrights in the |
* base code distributed originally by Intel ("Original Intel Code") to copy, |
* make derivatives, distribute, use and display any portion of the Covered |
* Code in any form, with the right to sublicense such rights; and |
* |
* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent |
* license (with the right to sublicense), under only those claims of Intel |
* patents that are infringed by the Original Intel Code, to make, use, sell, |
* offer to sell, and import the Covered Code and derivative works thereof |
* solely to the minimum extent necessary to exercise the above copyright |
* license, and in no event shall the patent license extend to any additions |
* to or modifications of the Original Intel Code. No other license or right |
* is granted directly or by implication, estoppel or otherwise; |
* |
* The above copyright and patent license is granted only if the following |
* conditions are met: |
* |
* 3. Conditions |
* |
* 3.1. Redistribution of Source with Rights to Further Distribute Source. |
* Redistribution of source code of any substantial portion of the Covered |
* Code or modification with rights to further distribute source must include |
* the above Copyright Notice, the above License, this list of Conditions, |
* and the following Disclaimer and Export Compliance provision. In addition, |
* Licensee must cause all Covered Code to which Licensee contributes to |
* contain a file documenting the changes Licensee made to create that Covered |
* Code and the date of any change. Licensee must include in that file the |
* documentation of any changes made by any predecessor Licensee. Licensee |
* must include a prominent statement that the modification is derived, |
* directly or indirectly, from Original Intel Code. |
* |
* 3.2. Redistribution of Source with no Rights to Further Distribute Source. |
* Redistribution of source code of any substantial portion of the Covered |
* Code or modification without rights to further distribute source must |
* include the following Disclaimer and Export Compliance provision in the |
* documentation and/or other materials provided with distribution. In |
* addition, Licensee may not authorize further sublicense of source of any |
* portion of the Covered Code, and must include terms to the effect that the |
* license from Licensee to its licensee is limited to the intellectual |
* property embodied in the software Licensee provides to its licensee, and |
* not to intellectual property embodied in modifications its licensee may |
* make. |
* |
* 3.3. Redistribution of Executable. Redistribution in executable form of any |
* substantial portion of the Covered Code or modification must reproduce the |
* above Copyright Notice, and the following Disclaimer and Export Compliance |
* provision in the documentation and/or other materials provided with the |
* distribution. |
* |
* 3.4. Intel retains all right, title, and interest in and to the Original |
* Intel Code. |
* |
* 3.5. Neither the name Intel nor any other trademark owned or controlled by |
* Intel shall be used in advertising or otherwise to promote the sale, use or |
* other dealings in products derived from or relating to the Covered Code |
* without prior written authorization from Intel. |
* |
* 4. Disclaimer and Export Compliance |
* |
* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED |
* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE |
* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, |
* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY |
* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY |
* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A |
* PARTICULAR PURPOSE. |
* |
* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES |
* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR |
* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, |
* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY |
* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL |
* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS |
* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY |
* LIMITED REMEDY. |
* |
* 4.3. Licensee shall not export, either directly or indirectly, any of this |
* software or system incorporating such software without first obtaining any |
* required license or other approval from the U. S. Department of Commerce or |
* any other agency or department of the United States Government. In the |
* event Licensee exports any such software from the United States or |
* re-exports any such software from a foreign destination, Licensee shall |
* ensure that the distribution and export/re-export of the software is in |
* compliance with all laws, regulations, orders, or other restrictions of the |
* U.S. Export Administration Regulations. Licensee agrees that neither it nor |
* any of its subsidiaries will export/re-export any technical data, process, |
* software, or service, directly or indirectly, to any country for which the |
* United States government or any agency thereof requires an export license, |
* other governmental approval, or letter of assurance, without first obtaining |
* such license, approval or letter. |
* |
*****************************************************************************/ |
#define __EVRGNINI_C__ |
#include "acpi.h" |
#include "accommon.h" |
#include "acevents.h" |
#include "acnamesp.h" |
#define _COMPONENT ACPI_EVENTS |
ACPI_MODULE_NAME ("evrgnini") |
/* Local prototypes */ |
static BOOLEAN |
AcpiEvIsPciRootBridge ( |
ACPI_NAMESPACE_NODE *Node); |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvSystemMemoryRegionSetup |
* |
* PARAMETERS: Handle - Region we are interested in |
* Function - Start or stop |
* HandlerContext - Address space handler context |
* RegionContext - Region specific context |
* |
* RETURN: Status |
* |
* DESCRIPTION: Setup a SystemMemory operation region |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvSystemMemoryRegionSetup ( |
ACPI_HANDLE Handle, |
UINT32 Function, |
void *HandlerContext, |
void **RegionContext) |
{ |
ACPI_OPERAND_OBJECT *RegionDesc = (ACPI_OPERAND_OBJECT *) Handle; |
ACPI_MEM_SPACE_CONTEXT *LocalRegionContext; |
ACPI_FUNCTION_TRACE (EvSystemMemoryRegionSetup); |
if (Function == ACPI_REGION_DEACTIVATE) |
{ |
if (*RegionContext) |
{ |
LocalRegionContext = (ACPI_MEM_SPACE_CONTEXT *) *RegionContext; |
/* Delete a cached mapping if present */ |
if (LocalRegionContext->MappedLength) |
{ |
AcpiOsUnmapMemory (LocalRegionContext->MappedLogicalAddress, |
LocalRegionContext->MappedLength); |
} |
ACPI_FREE (LocalRegionContext); |
*RegionContext = NULL; |
} |
return_ACPI_STATUS (AE_OK); |
} |
/* Create a new context */ |
LocalRegionContext = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_MEM_SPACE_CONTEXT)); |
if (!(LocalRegionContext)) |
{ |
return_ACPI_STATUS (AE_NO_MEMORY); |
} |
/* Save the region length and address for use in the handler */ |
LocalRegionContext->Length = RegionDesc->Region.Length; |
LocalRegionContext->Address = RegionDesc->Region.Address; |
*RegionContext = LocalRegionContext; |
return_ACPI_STATUS (AE_OK); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvIoSpaceRegionSetup |
* |
* PARAMETERS: Handle - Region we are interested in |
* Function - Start or stop |
* HandlerContext - Address space handler context |
* RegionContext - Region specific context |
* |
* RETURN: Status |
* |
* DESCRIPTION: Setup a IO operation region |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvIoSpaceRegionSetup ( |
ACPI_HANDLE Handle, |
UINT32 Function, |
void *HandlerContext, |
void **RegionContext) |
{ |
ACPI_FUNCTION_TRACE (EvIoSpaceRegionSetup); |
if (Function == ACPI_REGION_DEACTIVATE) |
{ |
*RegionContext = NULL; |
} |
else |
{ |
*RegionContext = HandlerContext; |
} |
return_ACPI_STATUS (AE_OK); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvPciConfigRegionSetup |
* |
* PARAMETERS: Handle - Region we are interested in |
* Function - Start or stop |
* HandlerContext - Address space handler context |
* RegionContext - Region specific context |
* |
* RETURN: Status |
* |
* DESCRIPTION: Setup a PCI_Config operation region |
* |
* MUTEX: Assumes namespace is not locked |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvPciConfigRegionSetup ( |
ACPI_HANDLE Handle, |
UINT32 Function, |
void *HandlerContext, |
void **RegionContext) |
{ |
ACPI_STATUS Status = AE_OK; |
UINT64 PciValue; |
ACPI_PCI_ID *PciId = *RegionContext; |
ACPI_OPERAND_OBJECT *HandlerObj; |
ACPI_NAMESPACE_NODE *ParentNode; |
ACPI_NAMESPACE_NODE *PciRootNode; |
ACPI_NAMESPACE_NODE *PciDeviceNode; |
ACPI_OPERAND_OBJECT *RegionObj = (ACPI_OPERAND_OBJECT *) Handle; |
ACPI_FUNCTION_TRACE (EvPciConfigRegionSetup); |
HandlerObj = RegionObj->Region.Handler; |
if (!HandlerObj) |
{ |
/* |
* No installed handler. This shouldn't happen because the dispatch |
* routine checks before we get here, but we check again just in case. |
*/ |
ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, |
"Attempting to init a region %p, with no handler\n", RegionObj)); |
return_ACPI_STATUS (AE_NOT_EXIST); |
} |
*RegionContext = NULL; |
if (Function == ACPI_REGION_DEACTIVATE) |
{ |
if (PciId) |
{ |
ACPI_FREE (PciId); |
} |
return_ACPI_STATUS (Status); |
} |
ParentNode = RegionObj->Region.Node->Parent; |
/* |
* Get the _SEG and _BBN values from the device upon which the handler |
* is installed. |
* |
* We need to get the _SEG and _BBN objects relative to the PCI BUS device. |
* This is the device the handler has been registered to handle. |
*/ |
/* |
* If the AddressSpace.Node is still pointing to the root, we need |
* to scan upward for a PCI Root bridge and re-associate the OpRegion |
* handlers with that device. |
*/ |
if (HandlerObj->AddressSpace.Node == AcpiGbl_RootNode) |
{ |
/* Start search from the parent object */ |
PciRootNode = ParentNode; |
while (PciRootNode != AcpiGbl_RootNode) |
{ |
/* Get the _HID/_CID in order to detect a RootBridge */ |
if (AcpiEvIsPciRootBridge (PciRootNode)) |
{ |
/* Install a handler for this PCI root bridge */ |
Status = AcpiInstallAddressSpaceHandler ( |
(ACPI_HANDLE) PciRootNode, |
ACPI_ADR_SPACE_PCI_CONFIG, |
ACPI_DEFAULT_HANDLER, NULL, NULL); |
if (ACPI_FAILURE (Status)) |
{ |
if (Status == AE_SAME_HANDLER) |
{ |
/* |
* It is OK if the handler is already installed on the |
* root bridge. Still need to return a context object |
* for the new PCI_Config operation region, however. |
*/ |
Status = AE_OK; |
} |
else |
{ |
ACPI_EXCEPTION ((AE_INFO, Status, |
"Could not install PciConfig handler " |
"for Root Bridge %4.4s", |
AcpiUtGetNodeName (PciRootNode))); |
} |
} |
break; |
} |
PciRootNode = PciRootNode->Parent; |
} |
/* PCI root bridge not found, use namespace root node */ |
} |
else |
{ |
PciRootNode = HandlerObj->AddressSpace.Node; |
} |
/* |
* If this region is now initialized, we are done. |
* (InstallAddressSpaceHandler could have initialized it) |
*/ |
if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE) |
{ |
return_ACPI_STATUS (AE_OK); |
} |
/* Region is still not initialized. Create a new context */ |
PciId = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_PCI_ID)); |
if (!PciId) |
{ |
return_ACPI_STATUS (AE_NO_MEMORY); |
} |
/* |
* For PCI_Config space access, we need the segment, bus, device and |
* function numbers. Acquire them here. |
* |
* Find the parent device object. (This allows the operation region to be |
* within a subscope under the device, such as a control method.) |
*/ |
PciDeviceNode = RegionObj->Region.Node; |
while (PciDeviceNode && (PciDeviceNode->Type != ACPI_TYPE_DEVICE)) |
{ |
PciDeviceNode = PciDeviceNode->Parent; |
} |
if (!PciDeviceNode) |
{ |
ACPI_FREE (PciId); |
return_ACPI_STATUS (AE_AML_OPERAND_TYPE); |
} |
/* |
* Get the PCI device and function numbers from the _ADR object contained |
* in the parent's scope. |
*/ |
Status = AcpiUtEvaluateNumericObject (METHOD_NAME__ADR, |
PciDeviceNode, &PciValue); |
/* |
* The default is zero, and since the allocation above zeroed the data, |
* just do nothing on failure. |
*/ |
if (ACPI_SUCCESS (Status)) |
{ |
PciId->Device = ACPI_HIWORD (ACPI_LODWORD (PciValue)); |
PciId->Function = ACPI_LOWORD (ACPI_LODWORD (PciValue)); |
} |
/* The PCI segment number comes from the _SEG method */ |
Status = AcpiUtEvaluateNumericObject (METHOD_NAME__SEG, |
PciRootNode, &PciValue); |
if (ACPI_SUCCESS (Status)) |
{ |
PciId->Segment = ACPI_LOWORD (PciValue); |
} |
/* The PCI bus number comes from the _BBN method */ |
Status = AcpiUtEvaluateNumericObject (METHOD_NAME__BBN, |
PciRootNode, &PciValue); |
if (ACPI_SUCCESS (Status)) |
{ |
PciId->Bus = ACPI_LOWORD (PciValue); |
} |
/* Complete this device's PciId */ |
AcpiOsDerivePciId (PciRootNode, RegionObj->Region.Node, &PciId); |
*RegionContext = PciId; |
return_ACPI_STATUS (AE_OK); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvIsPciRootBridge |
* |
* PARAMETERS: Node - Device node being examined |
* |
* RETURN: TRUE if device is a PCI/PCI-Express Root Bridge |
* |
* DESCRIPTION: Determine if the input device represents a PCI Root Bridge by |
* examining the _HID and _CID for the device. |
* |
******************************************************************************/ |
static BOOLEAN |
AcpiEvIsPciRootBridge ( |
ACPI_NAMESPACE_NODE *Node) |
{ |
ACPI_STATUS Status; |
ACPI_DEVICE_ID *Hid; |
ACPI_DEVICE_ID_LIST *Cid; |
UINT32 i; |
BOOLEAN Match; |
/* Get the _HID and check for a PCI Root Bridge */ |
Status = AcpiUtExecute_HID (Node, &Hid); |
if (ACPI_FAILURE (Status)) |
{ |
return (FALSE); |
} |
Match = AcpiUtIsPciRootBridge (Hid->String); |
ACPI_FREE (Hid); |
if (Match) |
{ |
return (TRUE); |
} |
/* The _HID did not match. Get the _CID and check for a PCI Root Bridge */ |
Status = AcpiUtExecute_CID (Node, &Cid); |
if (ACPI_FAILURE (Status)) |
{ |
return (FALSE); |
} |
/* Check all _CIDs in the returned list */ |
for (i = 0; i < Cid->Count; i++) |
{ |
if (AcpiUtIsPciRootBridge (Cid->Ids[i].String)) |
{ |
ACPI_FREE (Cid); |
return (TRUE); |
} |
} |
ACPI_FREE (Cid); |
return (FALSE); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvPciBarRegionSetup |
* |
* PARAMETERS: Handle - Region we are interested in |
* Function - Start or stop |
* HandlerContext - Address space handler context |
* RegionContext - Region specific context |
* |
* RETURN: Status |
* |
* DESCRIPTION: Setup a PciBAR operation region |
* |
* MUTEX: Assumes namespace is not locked |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvPciBarRegionSetup ( |
ACPI_HANDLE Handle, |
UINT32 Function, |
void *HandlerContext, |
void **RegionContext) |
{ |
ACPI_FUNCTION_TRACE (EvPciBarRegionSetup); |
return_ACPI_STATUS (AE_OK); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvCmosRegionSetup |
* |
* PARAMETERS: Handle - Region we are interested in |
* Function - Start or stop |
* HandlerContext - Address space handler context |
* RegionContext - Region specific context |
* |
* RETURN: Status |
* |
* DESCRIPTION: Setup a CMOS operation region |
* |
* MUTEX: Assumes namespace is not locked |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvCmosRegionSetup ( |
ACPI_HANDLE Handle, |
UINT32 Function, |
void *HandlerContext, |
void **RegionContext) |
{ |
ACPI_FUNCTION_TRACE (EvCmosRegionSetup); |
return_ACPI_STATUS (AE_OK); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvDefaultRegionSetup |
* |
* PARAMETERS: Handle - Region we are interested in |
* Function - Start or stop |
* HandlerContext - Address space handler context |
* RegionContext - Region specific context |
* |
* RETURN: Status |
* |
* DESCRIPTION: Default region initialization |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvDefaultRegionSetup ( |
ACPI_HANDLE Handle, |
UINT32 Function, |
void *HandlerContext, |
void **RegionContext) |
{ |
ACPI_FUNCTION_TRACE (EvDefaultRegionSetup); |
if (Function == ACPI_REGION_DEACTIVATE) |
{ |
*RegionContext = NULL; |
} |
else |
{ |
*RegionContext = HandlerContext; |
} |
return_ACPI_STATUS (AE_OK); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvInitializeRegion |
* |
* PARAMETERS: RegionObj - Region we are initializing |
* AcpiNsLocked - Is namespace locked? |
* |
* RETURN: Status |
* |
* DESCRIPTION: Initializes the region, finds any _REG methods and saves them |
* for execution at a later time |
* |
* Get the appropriate address space handler for a newly |
* created region. |
* |
* This also performs address space specific initialization. For |
* example, PCI regions must have an _ADR object that contains |
* a PCI address in the scope of the definition. This address is |
* required to perform an access to PCI config space. |
* |
* MUTEX: Interpreter should be unlocked, because we may run the _REG |
* method for this region. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvInitializeRegion ( |
ACPI_OPERAND_OBJECT *RegionObj, |
BOOLEAN AcpiNsLocked) |
{ |
ACPI_OPERAND_OBJECT *HandlerObj; |
ACPI_OPERAND_OBJECT *ObjDesc; |
ACPI_ADR_SPACE_TYPE SpaceId; |
ACPI_NAMESPACE_NODE *Node; |
ACPI_STATUS Status; |
ACPI_NAMESPACE_NODE *MethodNode; |
ACPI_NAME *RegNamePtr = (ACPI_NAME *) METHOD_NAME__REG; |
ACPI_OPERAND_OBJECT *RegionObj2; |
ACPI_FUNCTION_TRACE_U32 (EvInitializeRegion, AcpiNsLocked); |
if (!RegionObj) |
{ |
return_ACPI_STATUS (AE_BAD_PARAMETER); |
} |
if (RegionObj->Common.Flags & AOPOBJ_OBJECT_INITIALIZED) |
{ |
return_ACPI_STATUS (AE_OK); |
} |
RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); |
if (!RegionObj2) |
{ |
return_ACPI_STATUS (AE_NOT_EXIST); |
} |
Node = RegionObj->Region.Node->Parent; |
SpaceId = RegionObj->Region.SpaceId; |
/* Setup defaults */ |
RegionObj->Region.Handler = NULL; |
RegionObj2->Extra.Method_REG = NULL; |
RegionObj->Common.Flags &= ~(AOPOBJ_SETUP_COMPLETE); |
RegionObj->Common.Flags |= AOPOBJ_OBJECT_INITIALIZED; |
/* Find any "_REG" method associated with this region definition */ |
Status = AcpiNsSearchOneScope ( |
*RegNamePtr, Node, ACPI_TYPE_METHOD, &MethodNode); |
if (ACPI_SUCCESS (Status)) |
{ |
/* |
* The _REG method is optional and there can be only one per region |
* definition. This will be executed when the handler is attached |
* or removed |
*/ |
RegionObj2->Extra.Method_REG = MethodNode; |
} |
/* |
* The following loop depends upon the root Node having no parent |
* ie: AcpiGbl_RootNode->ParentEntry being set to NULL |
*/ |
while (Node) |
{ |
/* Check to see if a handler exists */ |
HandlerObj = NULL; |
ObjDesc = AcpiNsGetAttachedObject (Node); |
if (ObjDesc) |
{ |
/* Can only be a handler if the object exists */ |
switch (Node->Type) |
{ |
case ACPI_TYPE_DEVICE: |
HandlerObj = ObjDesc->Device.Handler; |
break; |
case ACPI_TYPE_PROCESSOR: |
HandlerObj = ObjDesc->Processor.Handler; |
break; |
case ACPI_TYPE_THERMAL: |
HandlerObj = ObjDesc->ThermalZone.Handler; |
break; |
case ACPI_TYPE_METHOD: |
/* |
* If we are executing module level code, the original |
* Node's object was replaced by this Method object and we |
* saved the handler in the method object. |
* |
* See AcpiNsExecModuleCode |
*/ |
if (ObjDesc->Method.Flags & AOPOBJ_MODULE_LEVEL) |
{ |
HandlerObj = ObjDesc->Method.Extra.Handler; |
} |
break; |
default: |
/* Ignore other objects */ |
break; |
} |
while (HandlerObj) |
{ |
/* Is this handler of the correct type? */ |
if (HandlerObj->AddressSpace.SpaceId == SpaceId) |
{ |
/* Found correct handler */ |
ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, |
"Found handler %p for region %p in obj %p\n", |
HandlerObj, RegionObj, ObjDesc)); |
Status = AcpiEvAttachRegion (HandlerObj, RegionObj, |
AcpiNsLocked); |
/* |
* Tell all users that this region is usable by |
* running the _REG method |
*/ |
if (AcpiNsLocked) |
{ |
Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
} |
Status = AcpiEvExecuteRegMethod (RegionObj, 1); |
if (AcpiNsLocked) |
{ |
Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
} |
return_ACPI_STATUS (AE_OK); |
} |
/* Try next handler in the list */ |
HandlerObj = HandlerObj->AddressSpace.Next; |
} |
} |
/* This node does not have the handler we need; Pop up one level */ |
Node = Node->Parent; |
} |
/* If we get here, there is no handler for this region */ |
ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, |
"No handler for RegionType %s(%X) (RegionObj %p)\n", |
AcpiUtGetRegionName (SpaceId), SpaceId, RegionObj)); |
return_ACPI_STATUS (AE_NOT_EXIST); |
} |
/drivers/devman/acpica/events/evsci.c |
---|
0,0 → 1,280 |
/******************************************************************************* |
* |
* Module Name: evsci - System Control Interrupt configuration and |
* legacy to ACPI mode state transition functions |
* |
******************************************************************************/ |
/****************************************************************************** |
* |
* 1. Copyright Notice |
* |
* Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. |
* All rights reserved. |
* |
* 2. License |
* |
* 2.1. This is your license from Intel Corp. under its intellectual property |
* rights. You may have additional license terms from the party that provided |
* you this software, covering your right to use that party's intellectual |
* property rights. |
* |
* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a |
* copy of the source code appearing in this file ("Covered Code") an |
* irrevocable, perpetual, worldwide license under Intel's copyrights in the |
* base code distributed originally by Intel ("Original Intel Code") to copy, |
* make derivatives, distribute, use and display any portion of the Covered |
* Code in any form, with the right to sublicense such rights; and |
* |
* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent |
* license (with the right to sublicense), under only those claims of Intel |
* patents that are infringed by the Original Intel Code, to make, use, sell, |
* offer to sell, and import the Covered Code and derivative works thereof |
* solely to the minimum extent necessary to exercise the above copyright |
* license, and in no event shall the patent license extend to any additions |
* to or modifications of the Original Intel Code. No other license or right |
* is granted directly or by implication, estoppel or otherwise; |
* |
* The above copyright and patent license is granted only if the following |
* conditions are met: |
* |
* 3. Conditions |
* |
* 3.1. Redistribution of Source with Rights to Further Distribute Source. |
* Redistribution of source code of any substantial portion of the Covered |
* Code or modification with rights to further distribute source must include |
* the above Copyright Notice, the above License, this list of Conditions, |
* and the following Disclaimer and Export Compliance provision. In addition, |
* Licensee must cause all Covered Code to which Licensee contributes to |
* contain a file documenting the changes Licensee made to create that Covered |
* Code and the date of any change. Licensee must include in that file the |
* documentation of any changes made by any predecessor Licensee. Licensee |
* must include a prominent statement that the modification is derived, |
* directly or indirectly, from Original Intel Code. |
* |
* 3.2. Redistribution of Source with no Rights to Further Distribute Source. |
* Redistribution of source code of any substantial portion of the Covered |
* Code or modification without rights to further distribute source must |
* include the following Disclaimer and Export Compliance provision in the |
* documentation and/or other materials provided with distribution. In |
* addition, Licensee may not authorize further sublicense of source of any |
* portion of the Covered Code, and must include terms to the effect that the |
* license from Licensee to its licensee is limited to the intellectual |
* property embodied in the software Licensee provides to its licensee, and |
* not to intellectual property embodied in modifications its licensee may |
* make. |
* |
* 3.3. Redistribution of Executable. Redistribution in executable form of any |
* substantial portion of the Covered Code or modification must reproduce the |
* above Copyright Notice, and the following Disclaimer and Export Compliance |
* provision in the documentation and/or other materials provided with the |
* distribution. |
* |
* 3.4. Intel retains all right, title, and interest in and to the Original |
* Intel Code. |
* |
* 3.5. Neither the name Intel nor any other trademark owned or controlled by |
* Intel shall be used in advertising or otherwise to promote the sale, use or |
* other dealings in products derived from or relating to the Covered Code |
* without prior written authorization from Intel. |
* |
* 4. Disclaimer and Export Compliance |
* |
* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED |
* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE |
* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, |
* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY |
* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY |
* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A |
* PARTICULAR PURPOSE. |
* |
* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES |
* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR |
* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, |
* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY |
* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL |
* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS |
* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY |
* LIMITED REMEDY. |
* |
* 4.3. Licensee shall not export, either directly or indirectly, any of this |
* software or system incorporating such software without first obtaining any |
* required license or other approval from the U. S. Department of Commerce or |
* any other agency or department of the United States Government. In the |
* event Licensee exports any such software from the United States or |
* re-exports any such software from a foreign destination, Licensee shall |
* ensure that the distribution and export/re-export of the software is in |
* compliance with all laws, regulations, orders, or other restrictions of the |
* U.S. Export Administration Regulations. Licensee agrees that neither it nor |
* any of its subsidiaries will export/re-export any technical data, process, |
* software, or service, directly or indirectly, to any country for which the |
* United States government or any agency thereof requires an export license, |
* other governmental approval, or letter of assurance, without first obtaining |
* such license, approval or letter. |
* |
*****************************************************************************/ |
#include "acpi.h" |
#include "accommon.h" |
#include "acevents.h" |
#define _COMPONENT ACPI_EVENTS |
ACPI_MODULE_NAME ("evsci") |
/* Local prototypes */ |
static UINT32 ACPI_SYSTEM_XFACE |
AcpiEvSciXruptHandler ( |
void *Context); |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvSciXruptHandler |
* |
* PARAMETERS: Context - Calling Context |
* |
* RETURN: Status code indicates whether interrupt was handled. |
* |
* DESCRIPTION: Interrupt handler that will figure out what function or |
* control method to call to deal with a SCI. |
* |
******************************************************************************/ |
static UINT32 ACPI_SYSTEM_XFACE |
AcpiEvSciXruptHandler ( |
void *Context) |
{ |
ACPI_GPE_XRUPT_INFO *GpeXruptList = Context; |
UINT32 InterruptHandled = ACPI_INTERRUPT_NOT_HANDLED; |
ACPI_FUNCTION_TRACE (EvSciXruptHandler); |
/* |
* We are guaranteed by the ACPI CA initialization/shutdown code that |
* if this interrupt handler is installed, ACPI is enabled. |
*/ |
/* |
* Fixed Events: |
* Check for and dispatch any Fixed Events that have occurred |
*/ |
InterruptHandled |= AcpiEvFixedEventDetect (); |
/* |
* General Purpose Events: |
* Check for and dispatch any GPEs that have occurred |
*/ |
InterruptHandled |= AcpiEvGpeDetect (GpeXruptList); |
AcpiSciCount++; |
return_UINT32 (InterruptHandled); |
} |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvGpeXruptHandler |
* |
* PARAMETERS: Context - Calling Context |
* |
* RETURN: Status code indicates whether interrupt was handled. |
* |
* DESCRIPTION: Handler for GPE Block Device interrupts |
* |
******************************************************************************/ |
UINT32 ACPI_SYSTEM_XFACE |
AcpiEvGpeXruptHandler ( |
void *Context) |
{ |
ACPI_GPE_XRUPT_INFO *GpeXruptList = Context; |
UINT32 InterruptHandled = ACPI_INTERRUPT_NOT_HANDLED; |
ACPI_FUNCTION_TRACE (EvGpeXruptHandler); |
/* |
* We are guaranteed by the ACPI CA initialization/shutdown code that |
* if this interrupt handler is installed, ACPI is enabled. |
*/ |
/* GPEs: Check for and dispatch any GPEs that have occurred */ |
InterruptHandled |= AcpiEvGpeDetect (GpeXruptList); |
return_UINT32 (InterruptHandled); |
} |
/****************************************************************************** |
* |
* FUNCTION: AcpiEvInstallSciHandler |
* |
* PARAMETERS: none |
* |
* RETURN: Status |
* |
* DESCRIPTION: Installs SCI handler. |
* |
******************************************************************************/ |
UINT32 |
AcpiEvInstallSciHandler ( |
void) |
{ |
UINT32 Status = AE_OK; |
ACPI_FUNCTION_TRACE (EvInstallSciHandler); |
Status = AcpiOsInstallInterruptHandler ((UINT32) AcpiGbl_FADT.SciInterrupt, |
AcpiEvSciXruptHandler, AcpiGbl_GpeXruptListHead); |
return_ACPI_STATUS (Status); |
} |
/****************************************************************************** |
* |
* FUNCTION: AcpiEvRemoveSciHandler |
* |
* PARAMETERS: none |
* |
* RETURN: E_OK if handler uninstalled OK, E_ERROR if handler was not |
* installed to begin with |
* |
* DESCRIPTION: Remove the SCI interrupt handler. No further SCIs will be |
* taken. |
* |
* Note: It doesn't seem important to disable all events or set the event |
* enable registers to their original values. The OS should disable |
* the SCI interrupt level when the handler is removed, so no more |
* events will come in. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEvRemoveSciHandler ( |
void) |
{ |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (EvRemoveSciHandler); |
/* Just let the OS remove the handler and disable the level */ |
Status = AcpiOsRemoveInterruptHandler ((UINT32) AcpiGbl_FADT.SciInterrupt, |
AcpiEvSciXruptHandler); |
return_ACPI_STATUS (Status); |
} |
/drivers/devman/acpica/events/evxface.c |
---|
0,0 → 1,967 |
/****************************************************************************** |
* |
* Module Name: evxface - External interfaces for ACPI events |
* |
*****************************************************************************/ |
/****************************************************************************** |
* |
* 1. Copyright Notice |
* |
* Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. |
* All rights reserved. |
* |
* 2. License |
* |
* 2.1. This is your license from Intel Corp. under its intellectual property |
* rights. You may have additional license terms from the party that provided |
* you this software, covering your right to use that party's intellectual |
* property rights. |
* |
* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a |
* copy of the source code appearing in this file ("Covered Code") an |
* irrevocable, perpetual, worldwide license under Intel's copyrights in the |
* base code distributed originally by Intel ("Original Intel Code") to copy, |
* make derivatives, distribute, use and display any portion of the Covered |
* Code in any form, with the right to sublicense such rights; and |
* |
* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent |
* license (with the right to sublicense), under only those claims of Intel |
* patents that are infringed by the Original Intel Code, to make, use, sell, |
* offer to sell, and import the Covered Code and derivative works thereof |
* solely to the minimum extent necessary to exercise the above copyright |
* license, and in no event shall the patent license extend to any additions |
* to or modifications of the Original Intel Code. No other license or right |
* is granted directly or by implication, estoppel or otherwise; |
* |
* The above copyright and patent license is granted only if the following |
* conditions are met: |
* |
* 3. Conditions |
* |
* 3.1. Redistribution of Source with Rights to Further Distribute Source. |
* Redistribution of source code of any substantial portion of the Covered |
* Code or modification with rights to further distribute source must include |
* the above Copyright Notice, the above License, this list of Conditions, |
* and the following Disclaimer and Export Compliance provision. In addition, |
* Licensee must cause all Covered Code to which Licensee contributes to |
* contain a file documenting the changes Licensee made to create that Covered |
* Code and the date of any change. Licensee must include in that file the |
* documentation of any changes made by any predecessor Licensee. Licensee |
* must include a prominent statement that the modification is derived, |
* directly or indirectly, from Original Intel Code. |
* |
* 3.2. Redistribution of Source with no Rights to Further Distribute Source. |
* Redistribution of source code of any substantial portion of the Covered |
* Code or modification without rights to further distribute source must |
* include the following Disclaimer and Export Compliance provision in the |
* documentation and/or other materials provided with distribution. In |
* addition, Licensee may not authorize further sublicense of source of any |
* portion of the Covered Code, and must include terms to the effect that the |
* license from Licensee to its licensee is limited to the intellectual |
* property embodied in the software Licensee provides to its licensee, and |
* not to intellectual property embodied in modifications its licensee may |
* make. |
* |
* 3.3. Redistribution of Executable. Redistribution in executable form of any |
* substantial portion of the Covered Code or modification must reproduce the |
* above Copyright Notice, and the following Disclaimer and Export Compliance |
* provision in the documentation and/or other materials provided with the |
* distribution. |
* |
* 3.4. Intel retains all right, title, and interest in and to the Original |
* Intel Code. |
* |
* 3.5. Neither the name Intel nor any other trademark owned or controlled by |
* Intel shall be used in advertising or otherwise to promote the sale, use or |
* other dealings in products derived from or relating to the Covered Code |
* without prior written authorization from Intel. |
* |
* 4. Disclaimer and Export Compliance |
* |
* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED |
* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE |
* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, |
* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY |
* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY |
* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A |
* PARTICULAR PURPOSE. |
* |
* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES |
* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR |
* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, |
* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY |
* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL |
* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS |
* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY |
* LIMITED REMEDY. |
* |
* 4.3. Licensee shall not export, either directly or indirectly, any of this |
* software or system incorporating such software without first obtaining any |
* required license or other approval from the U. S. Department of Commerce or |
* any other agency or department of the United States Government. In the |
* event Licensee exports any such software from the United States or |
* re-exports any such software from a foreign destination, Licensee shall |
* ensure that the distribution and export/re-export of the software is in |
* compliance with all laws, regulations, orders, or other restrictions of the |
* U.S. Export Administration Regulations. Licensee agrees that neither it nor |
* any of its subsidiaries will export/re-export any technical data, process, |
* software, or service, directly or indirectly, to any country for which the |
* United States government or any agency thereof requires an export license, |
* other governmental approval, or letter of assurance, without first obtaining |
* such license, approval or letter. |
* |
*****************************************************************************/ |
#define __EVXFACE_C__ |
#include "acpi.h" |
#include "accommon.h" |
#include "acnamesp.h" |
#include "acevents.h" |
#include "acinterp.h" |
#define _COMPONENT ACPI_EVENTS |
ACPI_MODULE_NAME ("evxface") |
/******************************************************************************* |
* |
* FUNCTION: AcpiInstallExceptionHandler |
* |
* PARAMETERS: Handler - Pointer to the handler function for the |
* event |
* |
* RETURN: Status |
* |
* DESCRIPTION: Saves the pointer to the handler function |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiInstallExceptionHandler ( |
ACPI_EXCEPTION_HANDLER Handler) |
{ |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (AcpiInstallExceptionHandler); |
Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
/* Don't allow two handlers. */ |
if (AcpiGbl_ExceptionHandler) |
{ |
Status = AE_ALREADY_EXISTS; |
goto Cleanup; |
} |
/* Install the handler */ |
AcpiGbl_ExceptionHandler = Handler; |
Cleanup: |
(void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler) |
/******************************************************************************* |
* |
* FUNCTION: AcpiInstallFixedEventHandler |
* |
* PARAMETERS: Event - Event type to enable. |
* Handler - Pointer to the handler function for the |
* event |
* Context - Value passed to the handler on each GPE |
* |
* RETURN: Status |
* |
* DESCRIPTION: Saves the pointer to the handler function and then enables the |
* event. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiInstallFixedEventHandler ( |
UINT32 Event, |
ACPI_EVENT_HANDLER Handler, |
void *Context) |
{ |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (AcpiInstallFixedEventHandler); |
/* Parameter validation */ |
if (Event > ACPI_EVENT_MAX) |
{ |
return_ACPI_STATUS (AE_BAD_PARAMETER); |
} |
Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
/* Don't allow two handlers. */ |
if (NULL != AcpiGbl_FixedEventHandlers[Event].Handler) |
{ |
Status = AE_ALREADY_EXISTS; |
goto Cleanup; |
} |
/* Install the handler before enabling the event */ |
AcpiGbl_FixedEventHandlers[Event].Handler = Handler; |
AcpiGbl_FixedEventHandlers[Event].Context = Context; |
Status = AcpiEnableEvent (Event, 0); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_WARNING ((AE_INFO, "Could not enable fixed event 0x%X", Event)); |
/* Remove the handler */ |
AcpiGbl_FixedEventHandlers[Event].Handler = NULL; |
AcpiGbl_FixedEventHandlers[Event].Context = NULL; |
} |
else |
{ |
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, |
"Enabled fixed event %X, Handler=%p\n", Event, Handler)); |
} |
Cleanup: |
(void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiInstallFixedEventHandler) |
/******************************************************************************* |
* |
* FUNCTION: AcpiRemoveFixedEventHandler |
* |
* PARAMETERS: Event - Event type to disable. |
* Handler - Address of the handler |
* |
* RETURN: Status |
* |
* DESCRIPTION: Disables the event and unregisters the event handler. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiRemoveFixedEventHandler ( |
UINT32 Event, |
ACPI_EVENT_HANDLER Handler) |
{ |
ACPI_STATUS Status = AE_OK; |
ACPI_FUNCTION_TRACE (AcpiRemoveFixedEventHandler); |
/* Parameter validation */ |
if (Event > ACPI_EVENT_MAX) |
{ |
return_ACPI_STATUS (AE_BAD_PARAMETER); |
} |
Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
/* Disable the event before removing the handler */ |
Status = AcpiDisableEvent (Event, 0); |
/* Always Remove the handler */ |
AcpiGbl_FixedEventHandlers[Event].Handler = NULL; |
AcpiGbl_FixedEventHandlers[Event].Context = NULL; |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_WARNING ((AE_INFO, |
"Could not write to fixed event enable register 0x%X", Event)); |
} |
else |
{ |
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Disabled fixed event %X\n", Event)); |
} |
(void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler) |
/******************************************************************************* |
* |
* FUNCTION: AcpiInstallNotifyHandler |
* |
* PARAMETERS: Device - The device for which notifies will be handled |
* HandlerType - The type of handler: |
* ACPI_SYSTEM_NOTIFY: SystemHandler (00-7f) |
* ACPI_DEVICE_NOTIFY: DriverHandler (80-ff) |
* ACPI_ALL_NOTIFY: both system and device |
* Handler - Address of the handler |
* Context - Value passed to the handler on each GPE |
* |
* RETURN: Status |
* |
* DESCRIPTION: Install a handler for notifies on an ACPI device |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiInstallNotifyHandler ( |
ACPI_HANDLE Device, |
UINT32 HandlerType, |
ACPI_NOTIFY_HANDLER Handler, |
void *Context) |
{ |
ACPI_OPERAND_OBJECT *ObjDesc; |
ACPI_OPERAND_OBJECT *NotifyObj; |
ACPI_NAMESPACE_NODE *Node; |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler); |
/* Parameter validation */ |
if ((!Device) || |
(!Handler) || |
(HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE)) |
{ |
return_ACPI_STATUS (AE_BAD_PARAMETER); |
} |
Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
/* Convert and validate the device handle */ |
Node = AcpiNsValidateHandle (Device); |
if (!Node) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
/* |
* Root Object: |
* Registering a notify handler on the root object indicates that the |
* caller wishes to receive notifications for all objects. Note that |
* only one <external> global handler can be regsitered (per notify type). |
*/ |
if (Device == ACPI_ROOT_OBJECT) |
{ |
/* Make sure the handler is not already installed */ |
if (((HandlerType & ACPI_SYSTEM_NOTIFY) && |
AcpiGbl_SystemNotify.Handler) || |
((HandlerType & ACPI_DEVICE_NOTIFY) && |
AcpiGbl_DeviceNotify.Handler)) |
{ |
Status = AE_ALREADY_EXISTS; |
goto UnlockAndExit; |
} |
if (HandlerType & ACPI_SYSTEM_NOTIFY) |
{ |
AcpiGbl_SystemNotify.Node = Node; |
AcpiGbl_SystemNotify.Handler = Handler; |
AcpiGbl_SystemNotify.Context = Context; |
} |
if (HandlerType & ACPI_DEVICE_NOTIFY) |
{ |
AcpiGbl_DeviceNotify.Node = Node; |
AcpiGbl_DeviceNotify.Handler = Handler; |
AcpiGbl_DeviceNotify.Context = Context; |
} |
/* Global notify handler installed */ |
} |
/* |
* All Other Objects: |
* Caller will only receive notifications specific to the target object. |
* Note that only certain object types can receive notifications. |
*/ |
else |
{ |
/* Notifies allowed on this object? */ |
if (!AcpiEvIsNotifyObject (Node)) |
{ |
Status = AE_TYPE; |
goto UnlockAndExit; |
} |
/* Check for an existing internal object */ |
ObjDesc = AcpiNsGetAttachedObject (Node); |
if (ObjDesc) |
{ |
/* Object exists - make sure there's no handler */ |
if (((HandlerType & ACPI_SYSTEM_NOTIFY) && |
ObjDesc->CommonNotify.SystemNotify) || |
((HandlerType & ACPI_DEVICE_NOTIFY) && |
ObjDesc->CommonNotify.DeviceNotify)) |
{ |
Status = AE_ALREADY_EXISTS; |
goto UnlockAndExit; |
} |
} |
else |
{ |
/* Create a new object */ |
ObjDesc = AcpiUtCreateInternalObject (Node->Type); |
if (!ObjDesc) |
{ |
Status = AE_NO_MEMORY; |
goto UnlockAndExit; |
} |
/* Attach new object to the Node */ |
Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type); |
/* Remove local reference to the object */ |
AcpiUtRemoveReference (ObjDesc); |
if (ACPI_FAILURE (Status)) |
{ |
goto UnlockAndExit; |
} |
} |
/* Install the handler */ |
NotifyObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY); |
if (!NotifyObj) |
{ |
Status = AE_NO_MEMORY; |
goto UnlockAndExit; |
} |
NotifyObj->Notify.Node = Node; |
NotifyObj->Notify.Handler = Handler; |
NotifyObj->Notify.Context = Context; |
if (HandlerType & ACPI_SYSTEM_NOTIFY) |
{ |
ObjDesc->CommonNotify.SystemNotify = NotifyObj; |
} |
if (HandlerType & ACPI_DEVICE_NOTIFY) |
{ |
ObjDesc->CommonNotify.DeviceNotify = NotifyObj; |
} |
if (HandlerType == ACPI_ALL_NOTIFY) |
{ |
/* Extra ref if installed in both */ |
AcpiUtAddReference (NotifyObj); |
} |
} |
UnlockAndExit: |
(void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiInstallNotifyHandler) |
/******************************************************************************* |
* |
* FUNCTION: AcpiRemoveNotifyHandler |
* |
* PARAMETERS: Device - The device for which notifies will be handled |
* HandlerType - The type of handler: |
* ACPI_SYSTEM_NOTIFY: SystemHandler (00-7f) |
* ACPI_DEVICE_NOTIFY: DriverHandler (80-ff) |
* ACPI_ALL_NOTIFY: both system and device |
* Handler - Address of the handler |
* |
* RETURN: Status |
* |
* DESCRIPTION: Remove a handler for notifies on an ACPI device |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiRemoveNotifyHandler ( |
ACPI_HANDLE Device, |
UINT32 HandlerType, |
ACPI_NOTIFY_HANDLER Handler) |
{ |
ACPI_OPERAND_OBJECT *NotifyObj; |
ACPI_OPERAND_OBJECT *ObjDesc; |
ACPI_NAMESPACE_NODE *Node; |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (AcpiRemoveNotifyHandler); |
/* Parameter validation */ |
if ((!Device) || |
(!Handler) || |
(HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE)) |
{ |
return_ACPI_STATUS (AE_BAD_PARAMETER); |
} |
Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
/* Convert and validate the device handle */ |
Node = AcpiNsValidateHandle (Device); |
if (!Node) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
/* Root Object */ |
if (Device == ACPI_ROOT_OBJECT) |
{ |
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, |
"Removing notify handler for namespace root object\n")); |
if (((HandlerType & ACPI_SYSTEM_NOTIFY) && |
!AcpiGbl_SystemNotify.Handler) || |
((HandlerType & ACPI_DEVICE_NOTIFY) && |
!AcpiGbl_DeviceNotify.Handler)) |
{ |
Status = AE_NOT_EXIST; |
goto UnlockAndExit; |
} |
if (HandlerType & ACPI_SYSTEM_NOTIFY) |
{ |
AcpiGbl_SystemNotify.Node = NULL; |
AcpiGbl_SystemNotify.Handler = NULL; |
AcpiGbl_SystemNotify.Context = NULL; |
} |
if (HandlerType & ACPI_DEVICE_NOTIFY) |
{ |
AcpiGbl_DeviceNotify.Node = NULL; |
AcpiGbl_DeviceNotify.Handler = NULL; |
AcpiGbl_DeviceNotify.Context = NULL; |
} |
} |
/* All Other Objects */ |
else |
{ |
/* Notifies allowed on this object? */ |
if (!AcpiEvIsNotifyObject (Node)) |
{ |
Status = AE_TYPE; |
goto UnlockAndExit; |
} |
/* Check for an existing internal object */ |
ObjDesc = AcpiNsGetAttachedObject (Node); |
if (!ObjDesc) |
{ |
Status = AE_NOT_EXIST; |
goto UnlockAndExit; |
} |
/* Object exists - make sure there's an existing handler */ |
if (HandlerType & ACPI_SYSTEM_NOTIFY) |
{ |
NotifyObj = ObjDesc->CommonNotify.SystemNotify; |
if (!NotifyObj) |
{ |
Status = AE_NOT_EXIST; |
goto UnlockAndExit; |
} |
if (NotifyObj->Notify.Handler != Handler) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
/* Remove the handler */ |
ObjDesc->CommonNotify.SystemNotify = NULL; |
AcpiUtRemoveReference (NotifyObj); |
} |
if (HandlerType & ACPI_DEVICE_NOTIFY) |
{ |
NotifyObj = ObjDesc->CommonNotify.DeviceNotify; |
if (!NotifyObj) |
{ |
Status = AE_NOT_EXIST; |
goto UnlockAndExit; |
} |
if (NotifyObj->Notify.Handler != Handler) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
/* Remove the handler */ |
ObjDesc->CommonNotify.DeviceNotify = NULL; |
AcpiUtRemoveReference (NotifyObj); |
} |
} |
UnlockAndExit: |
(void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiRemoveNotifyHandler) |
/******************************************************************************* |
* |
* FUNCTION: AcpiInstallGpeHandler |
* |
* PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT |
* defined GPEs) |
* GpeNumber - The GPE number within the GPE block |
* Type - Whether this GPE should be treated as an |
* edge- or level-triggered interrupt. |
* Address - Address of the handler |
* Context - Value passed to the handler on each GPE |
* |
* RETURN: Status |
* |
* DESCRIPTION: Install a handler for a General Purpose Event. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiInstallGpeHandler ( |
ACPI_HANDLE GpeDevice, |
UINT32 GpeNumber, |
UINT32 Type, |
ACPI_EVENT_HANDLER Address, |
void *Context) |
{ |
ACPI_GPE_EVENT_INFO *GpeEventInfo; |
ACPI_HANDLER_INFO *Handler; |
ACPI_STATUS Status; |
ACPI_CPU_FLAGS Flags; |
ACPI_FUNCTION_TRACE (AcpiInstallGpeHandler); |
/* Parameter validation */ |
if ((!Address) || (Type & ~ACPI_GPE_XRUPT_TYPE_MASK)) |
{ |
return_ACPI_STATUS (AE_BAD_PARAMETER); |
} |
Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
/* Ensure that we have a valid GPE number */ |
GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); |
if (!GpeEventInfo) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
/* Make sure that there isn't a handler there already */ |
if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == |
ACPI_GPE_DISPATCH_HANDLER) |
{ |
Status = AE_ALREADY_EXISTS; |
goto UnlockAndExit; |
} |
/* Allocate and init handler object */ |
Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_HANDLER_INFO)); |
if (!Handler) |
{ |
Status = AE_NO_MEMORY; |
goto UnlockAndExit; |
} |
Handler->Address = Address; |
Handler->Context = Context; |
Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode; |
/* Disable the GPE before installing the handler */ |
Status = AcpiEvDisableGpe (GpeEventInfo); |
if (ACPI_FAILURE (Status)) |
{ |
goto UnlockAndExit; |
} |
/* Install the handler */ |
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
GpeEventInfo->Dispatch.Handler = Handler; |
/* Setup up dispatch flags to indicate handler (vs. method) */ |
GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); |
GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_HANDLER); |
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
UnlockAndExit: |
(void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler) |
/******************************************************************************* |
* |
* FUNCTION: AcpiRemoveGpeHandler |
* |
* PARAMETERS: GpeDevice - Namespace node for the GPE (NULL for FADT |
* defined GPEs) |
* GpeNumber - The event to remove a handler |
* Address - Address of the handler |
* |
* RETURN: Status |
* |
* DESCRIPTION: Remove a handler for a General Purpose AcpiEvent. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiRemoveGpeHandler ( |
ACPI_HANDLE GpeDevice, |
UINT32 GpeNumber, |
ACPI_EVENT_HANDLER Address) |
{ |
ACPI_GPE_EVENT_INFO *GpeEventInfo; |
ACPI_HANDLER_INFO *Handler; |
ACPI_STATUS Status; |
ACPI_CPU_FLAGS Flags; |
ACPI_FUNCTION_TRACE (AcpiRemoveGpeHandler); |
/* Parameter validation */ |
if (!Address) |
{ |
return_ACPI_STATUS (AE_BAD_PARAMETER); |
} |
Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
/* Ensure that we have a valid GPE number */ |
GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); |
if (!GpeEventInfo) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
/* Make sure that a handler is indeed installed */ |
if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) != |
ACPI_GPE_DISPATCH_HANDLER) |
{ |
Status = AE_NOT_EXIST; |
goto UnlockAndExit; |
} |
/* Make sure that the installed handler is the same */ |
if (GpeEventInfo->Dispatch.Handler->Address != Address) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
/* Disable the GPE before removing the handler */ |
Status = AcpiEvDisableGpe (GpeEventInfo); |
if (ACPI_FAILURE (Status)) |
{ |
goto UnlockAndExit; |
} |
/* Remove the handler */ |
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
Handler = GpeEventInfo->Dispatch.Handler; |
/* Restore Method node (if any), set dispatch flags */ |
GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode; |
GpeEventInfo->Flags &= ~ACPI_GPE_DISPATCH_MASK; /* Clear bits */ |
if (Handler->MethodNode) |
{ |
GpeEventInfo->Flags |= ACPI_GPE_DISPATCH_METHOD; |
} |
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
/* Now we can free the handler object */ |
ACPI_FREE (Handler); |
UnlockAndExit: |
(void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiRemoveGpeHandler) |
/******************************************************************************* |
* |
* FUNCTION: AcpiAcquireGlobalLock |
* |
* PARAMETERS: Timeout - How long the caller is willing to wait |
* Handle - Where the handle to the lock is returned |
* (if acquired) |
* |
* RETURN: Status |
* |
* DESCRIPTION: Acquire the ACPI Global Lock |
* |
* Note: Allows callers with the same thread ID to acquire the global lock |
* multiple times. In other words, externally, the behavior of the global lock |
* is identical to an AML mutex. On the first acquire, a new handle is |
* returned. On any subsequent calls to acquire by the same thread, the same |
* handle is returned. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiAcquireGlobalLock ( |
UINT16 Timeout, |
UINT32 *Handle) |
{ |
ACPI_STATUS Status; |
if (!Handle) |
{ |
return (AE_BAD_PARAMETER); |
} |
/* Must lock interpreter to prevent race conditions */ |
AcpiExEnterInterpreter (); |
Status = AcpiExAcquireMutexObject (Timeout, |
AcpiGbl_GlobalLockMutex, AcpiOsGetThreadId ()); |
if (ACPI_SUCCESS (Status)) |
{ |
/* Return the global lock handle (updated in AcpiEvAcquireGlobalLock) */ |
*Handle = AcpiGbl_GlobalLockHandle; |
} |
AcpiExExitInterpreter (); |
return (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiAcquireGlobalLock) |
/******************************************************************************* |
* |
* FUNCTION: AcpiReleaseGlobalLock |
* |
* PARAMETERS: Handle - Returned from AcpiAcquireGlobalLock |
* |
* RETURN: Status |
* |
* DESCRIPTION: Release the ACPI Global Lock. The handle must be valid. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiReleaseGlobalLock ( |
UINT32 Handle) |
{ |
ACPI_STATUS Status; |
if (!Handle || (Handle != AcpiGbl_GlobalLockHandle)) |
{ |
return (AE_NOT_ACQUIRED); |
} |
Status = AcpiExReleaseMutexObject (AcpiGbl_GlobalLockMutex); |
return (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiReleaseGlobalLock) |
/drivers/devman/acpica/events/evxfevnt.c |
---|
0,0 → 1,1180 |
/****************************************************************************** |
* |
* Module Name: evxfevnt - External Interfaces, ACPI event disable/enable |
* |
*****************************************************************************/ |
/****************************************************************************** |
* |
* 1. Copyright Notice |
* |
* Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. |
* All rights reserved. |
* |
* 2. License |
* |
* 2.1. This is your license from Intel Corp. under its intellectual property |
* rights. You may have additional license terms from the party that provided |
* you this software, covering your right to use that party's intellectual |
* property rights. |
* |
* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a |
* copy of the source code appearing in this file ("Covered Code") an |
* irrevocable, perpetual, worldwide license under Intel's copyrights in the |
* base code distributed originally by Intel ("Original Intel Code") to copy, |
* make derivatives, distribute, use and display any portion of the Covered |
* Code in any form, with the right to sublicense such rights; and |
* |
* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent |
* license (with the right to sublicense), under only those claims of Intel |
* patents that are infringed by the Original Intel Code, to make, use, sell, |
* offer to sell, and import the Covered Code and derivative works thereof |
* solely to the minimum extent necessary to exercise the above copyright |
* license, and in no event shall the patent license extend to any additions |
* to or modifications of the Original Intel Code. No other license or right |
* is granted directly or by implication, estoppel or otherwise; |
* |
* The above copyright and patent license is granted only if the following |
* conditions are met: |
* |
* 3. Conditions |
* |
* 3.1. Redistribution of Source with Rights to Further Distribute Source. |
* Redistribution of source code of any substantial portion of the Covered |
* Code or modification with rights to further distribute source must include |
* the above Copyright Notice, the above License, this list of Conditions, |
* and the following Disclaimer and Export Compliance provision. In addition, |
* Licensee must cause all Covered Code to which Licensee contributes to |
* contain a file documenting the changes Licensee made to create that Covered |
* Code and the date of any change. Licensee must include in that file the |
* documentation of any changes made by any predecessor Licensee. Licensee |
* must include a prominent statement that the modification is derived, |
* directly or indirectly, from Original Intel Code. |
* |
* 3.2. Redistribution of Source with no Rights to Further Distribute Source. |
* Redistribution of source code of any substantial portion of the Covered |
* Code or modification without rights to further distribute source must |
* include the following Disclaimer and Export Compliance provision in the |
* documentation and/or other materials provided with distribution. In |
* addition, Licensee may not authorize further sublicense of source of any |
* portion of the Covered Code, and must include terms to the effect that the |
* license from Licensee to its licensee is limited to the intellectual |
* property embodied in the software Licensee provides to its licensee, and |
* not to intellectual property embodied in modifications its licensee may |
* make. |
* |
* 3.3. Redistribution of Executable. Redistribution in executable form of any |
* substantial portion of the Covered Code or modification must reproduce the |
* above Copyright Notice, and the following Disclaimer and Export Compliance |
* provision in the documentation and/or other materials provided with the |
* distribution. |
* |
* 3.4. Intel retains all right, title, and interest in and to the Original |
* Intel Code. |
* |
* 3.5. Neither the name Intel nor any other trademark owned or controlled by |
* Intel shall be used in advertising or otherwise to promote the sale, use or |
* other dealings in products derived from or relating to the Covered Code |
* without prior written authorization from Intel. |
* |
* 4. Disclaimer and Export Compliance |
* |
* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED |
* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE |
* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, |
* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY |
* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY |
* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A |
* PARTICULAR PURPOSE. |
* |
* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES |
* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR |
* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, |
* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY |
* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL |
* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS |
* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY |
* LIMITED REMEDY. |
* |
* 4.3. Licensee shall not export, either directly or indirectly, any of this |
* software or system incorporating such software without first obtaining any |
* required license or other approval from the U. S. Department of Commerce or |
* any other agency or department of the United States Government. In the |
* event Licensee exports any such software from the United States or |
* re-exports any such software from a foreign destination, Licensee shall |
* ensure that the distribution and export/re-export of the software is in |
* compliance with all laws, regulations, orders, or other restrictions of the |
* U.S. Export Administration Regulations. Licensee agrees that neither it nor |
* any of its subsidiaries will export/re-export any technical data, process, |
* software, or service, directly or indirectly, to any country for which the |
* United States government or any agency thereof requires an export license, |
* other governmental approval, or letter of assurance, without first obtaining |
* such license, approval or letter. |
* |
*****************************************************************************/ |
#define __EVXFEVNT_C__ |
#include "acpi.h" |
#include "accommon.h" |
#include "acevents.h" |
#include "acnamesp.h" |
#include "actables.h" |
#define _COMPONENT ACPI_EVENTS |
ACPI_MODULE_NAME ("evxfevnt") |
/* Local prototypes */ |
static ACPI_STATUS |
AcpiEvGetGpeDevice ( |
ACPI_GPE_XRUPT_INFO *GpeXruptInfo, |
ACPI_GPE_BLOCK_INFO *GpeBlock, |
void *Context); |
/******************************************************************************* |
* |
* FUNCTION: AcpiEnable |
* |
* PARAMETERS: None |
* |
* RETURN: Status |
* |
* DESCRIPTION: Transfers the system into ACPI mode. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEnable ( |
void) |
{ |
ACPI_STATUS Status = AE_OK; |
ACPI_FUNCTION_TRACE (AcpiEnable); |
/* ACPI tables must be present */ |
if (!AcpiTbTablesLoaded ()) |
{ |
return_ACPI_STATUS (AE_NO_ACPI_TABLES); |
} |
/* Check current mode */ |
if (AcpiHwGetMode() == ACPI_SYS_MODE_ACPI) |
{ |
ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "System is already in ACPI mode\n")); |
} |
else |
{ |
/* Transition to ACPI mode */ |
Status = AcpiHwSetMode (ACPI_SYS_MODE_ACPI); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_ERROR ((AE_INFO, "Could not transition to ACPI mode")); |
return_ACPI_STATUS (Status); |
} |
ACPI_DEBUG_PRINT ((ACPI_DB_INIT, |
"Transition to ACPI mode successful\n")); |
} |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiEnable) |
/******************************************************************************* |
* |
* FUNCTION: AcpiDisable |
* |
* PARAMETERS: None |
* |
* RETURN: Status |
* |
* DESCRIPTION: Transfers the system into LEGACY (non-ACPI) mode. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiDisable ( |
void) |
{ |
ACPI_STATUS Status = AE_OK; |
ACPI_FUNCTION_TRACE (AcpiDisable); |
if (AcpiHwGetMode() == ACPI_SYS_MODE_LEGACY) |
{ |
ACPI_DEBUG_PRINT ((ACPI_DB_INIT, |
"System is already in legacy (non-ACPI) mode\n")); |
} |
else |
{ |
/* Transition to LEGACY mode */ |
Status = AcpiHwSetMode (ACPI_SYS_MODE_LEGACY); |
if (ACPI_FAILURE (Status)) |
{ |
ACPI_ERROR ((AE_INFO, |
"Could not exit ACPI mode to legacy mode")); |
return_ACPI_STATUS (Status); |
} |
ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "ACPI mode disabled\n")); |
} |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiDisable) |
/******************************************************************************* |
* |
* FUNCTION: AcpiEnableEvent |
* |
* PARAMETERS: Event - The fixed eventto be enabled |
* Flags - Reserved |
* |
* RETURN: Status |
* |
* DESCRIPTION: Enable an ACPI event (fixed) |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEnableEvent ( |
UINT32 Event, |
UINT32 Flags) |
{ |
ACPI_STATUS Status = AE_OK; |
UINT32 Value; |
ACPI_FUNCTION_TRACE (AcpiEnableEvent); |
/* Decode the Fixed Event */ |
if (Event > ACPI_EVENT_MAX) |
{ |
return_ACPI_STATUS (AE_BAD_PARAMETER); |
} |
/* |
* Enable the requested fixed event (by writing a one to the enable |
* register bit) |
*/ |
Status = AcpiWriteBitRegister ( |
AcpiGbl_FixedEventInfo[Event].EnableRegisterId, |
ACPI_ENABLE_EVENT); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
/* Make sure that the hardware responded */ |
Status = AcpiReadBitRegister ( |
AcpiGbl_FixedEventInfo[Event].EnableRegisterId, &Value); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
if (Value != 1) |
{ |
ACPI_ERROR ((AE_INFO, |
"Could not enable %s event", AcpiUtGetEventName (Event))); |
return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE); |
} |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiEnableEvent) |
/******************************************************************************* |
* |
* FUNCTION: AcpiEnableGpe |
* |
* PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 |
* GpeNumber - GPE level within the GPE block |
* GpeType - ACPI_GPE_TYPE_RUNTIME or ACPI_GPE_TYPE_WAKE |
* or both |
* |
* RETURN: Status |
* |
* DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is |
* hardware-enabled (for runtime GPEs), or the GPE register mask |
* is updated (for wake GPEs). |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEnableGpe ( |
ACPI_HANDLE GpeDevice, |
UINT32 GpeNumber, |
UINT8 GpeType) |
{ |
ACPI_STATUS Status = AE_OK; |
ACPI_GPE_EVENT_INFO *GpeEventInfo; |
ACPI_CPU_FLAGS Flags; |
ACPI_FUNCTION_TRACE (AcpiEnableGpe); |
/* Parameter validation */ |
if (!GpeType || (GpeType & ~ACPI_GPE_TYPE_WAKE_RUN)) |
{ |
return_ACPI_STATUS (AE_BAD_PARAMETER); |
} |
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
/* Ensure that we have a valid GPE number */ |
GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); |
if (!GpeEventInfo) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
if (GpeType & ACPI_GPE_TYPE_RUNTIME) |
{ |
if (GpeEventInfo->RuntimeCount == ACPI_UINT8_MAX) |
{ |
Status = AE_LIMIT; /* Too many references */ |
goto UnlockAndExit; |
} |
GpeEventInfo->RuntimeCount++; |
if (GpeEventInfo->RuntimeCount == 1) |
{ |
Status = AcpiEvEnableGpe (GpeEventInfo); |
if (ACPI_FAILURE (Status)) |
{ |
GpeEventInfo->RuntimeCount--; |
goto UnlockAndExit; |
} |
} |
} |
if (GpeType & ACPI_GPE_TYPE_WAKE) |
{ |
/* The GPE must have the ability to wake the system */ |
if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE)) |
{ |
Status = AE_TYPE; |
goto UnlockAndExit; |
} |
if (GpeEventInfo->WakeupCount == ACPI_UINT8_MAX) |
{ |
Status = AE_LIMIT; /* Too many references */ |
goto UnlockAndExit; |
} |
/* |
* Update the enable mask on the first wakeup reference. Wake GPEs |
* are only hardware-enabled just before sleeping. |
*/ |
GpeEventInfo->WakeupCount++; |
if (GpeEventInfo->WakeupCount == 1) |
{ |
(void) AcpiEvUpdateGpeEnableMasks (GpeEventInfo); |
} |
} |
UnlockAndExit: |
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiEnableGpe) |
/******************************************************************************* |
* |
* FUNCTION: AcpiDisableGpe |
* |
* PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 |
* GpeNumber - GPE level within the GPE block |
* GpeType - ACPI_GPE_TYPE_RUNTIME or ACPI_GPE_TYPE_WAKE |
* or both |
* |
* RETURN: Status |
* |
* DESCRIPTION: Remove a reference to a GPE. When the last reference is |
* removed, only then is the GPE disabled (for runtime GPEs), or |
* the GPE mask bit disabled (for wake GPEs) |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiDisableGpe ( |
ACPI_HANDLE GpeDevice, |
UINT32 GpeNumber, |
UINT8 GpeType) |
{ |
ACPI_STATUS Status = AE_OK; |
ACPI_GPE_EVENT_INFO *GpeEventInfo; |
ACPI_CPU_FLAGS Flags; |
ACPI_FUNCTION_TRACE (AcpiDisableGpe); |
/* Parameter validation */ |
if (!GpeType || (GpeType & ~ACPI_GPE_TYPE_WAKE_RUN)) |
{ |
return_ACPI_STATUS (AE_BAD_PARAMETER); |
} |
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
/* Ensure that we have a valid GPE number */ |
GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); |
if (!GpeEventInfo) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
/* Hardware-disable a runtime GPE on removal of the last reference */ |
if (GpeType & ACPI_GPE_TYPE_RUNTIME) |
{ |
if (!GpeEventInfo->RuntimeCount) |
{ |
Status = AE_LIMIT; /* There are no references to remove */ |
goto UnlockAndExit; |
} |
GpeEventInfo->RuntimeCount--; |
if (!GpeEventInfo->RuntimeCount) |
{ |
Status = AcpiEvDisableGpe (GpeEventInfo); |
if (ACPI_FAILURE (Status)) |
{ |
GpeEventInfo->RuntimeCount++; |
goto UnlockAndExit; |
} |
} |
} |
/* |
* Update masks for wake GPE on removal of the last reference. |
* No need to hardware-disable wake GPEs here, they are not currently |
* enabled. |
*/ |
if (GpeType & ACPI_GPE_TYPE_WAKE) |
{ |
if (!GpeEventInfo->WakeupCount) |
{ |
Status = AE_LIMIT; /* There are no references to remove */ |
goto UnlockAndExit; |
} |
GpeEventInfo->WakeupCount--; |
if (!GpeEventInfo->WakeupCount) |
{ |
(void) AcpiEvUpdateGpeEnableMasks (GpeEventInfo); |
} |
} |
UnlockAndExit: |
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiDisableGpe) |
/******************************************************************************* |
* |
* FUNCTION: AcpiSetGpe |
* |
* PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 |
* GpeNumber - GPE level within the GPE block |
* Action - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE |
* |
* RETURN: Status |
* |
* DESCRIPTION: Enable or disable an individual GPE. This function bypasses |
* the reference count mechanism used in the AcpiEnableGpe and |
* AcpiDisableGpe interfaces -- and should be used with care. |
* |
* Note: Typically used to disable a runtime GPE for short period of time, |
* then re-enable it, without disturbing the existing reference counts. This |
* is useful, for example, in the Embedded Controller (EC) driver. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiSetGpe ( |
ACPI_HANDLE GpeDevice, |
UINT32 GpeNumber, |
UINT8 Action) |
{ |
ACPI_GPE_EVENT_INFO *GpeEventInfo; |
ACPI_STATUS Status; |
ACPI_CPU_FLAGS Flags; |
ACPI_FUNCTION_TRACE (AcpiSetGpe); |
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
/* Ensure that we have a valid GPE number */ |
GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); |
if (!GpeEventInfo) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
/* Perform the action */ |
switch (Action) |
{ |
case ACPI_GPE_ENABLE: |
Status = AcpiEvEnableGpe (GpeEventInfo); |
break; |
case ACPI_GPE_DISABLE: |
Status = AcpiEvDisableGpe (GpeEventInfo); |
break; |
default: |
Status = AE_BAD_PARAMETER; |
break; |
} |
UnlockAndExit: |
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiSetGpe) |
/******************************************************************************* |
* |
* FUNCTION: AcpiDisableEvent |
* |
* PARAMETERS: Event - The fixed eventto be enabled |
* Flags - Reserved |
* |
* RETURN: Status |
* |
* DESCRIPTION: Disable an ACPI event (fixed) |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiDisableEvent ( |
UINT32 Event, |
UINT32 Flags) |
{ |
ACPI_STATUS Status = AE_OK; |
UINT32 Value; |
ACPI_FUNCTION_TRACE (AcpiDisableEvent); |
/* Decode the Fixed Event */ |
if (Event > ACPI_EVENT_MAX) |
{ |
return_ACPI_STATUS (AE_BAD_PARAMETER); |
} |
/* |
* Disable the requested fixed event (by writing a zero to the enable |
* register bit) |
*/ |
Status = AcpiWriteBitRegister ( |
AcpiGbl_FixedEventInfo[Event].EnableRegisterId, |
ACPI_DISABLE_EVENT); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
Status = AcpiReadBitRegister ( |
AcpiGbl_FixedEventInfo[Event].EnableRegisterId, &Value); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
if (Value != 0) |
{ |
ACPI_ERROR ((AE_INFO, |
"Could not disable %s events", AcpiUtGetEventName (Event))); |
return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE); |
} |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiDisableEvent) |
/******************************************************************************* |
* |
* FUNCTION: AcpiClearEvent |
* |
* PARAMETERS: Event - The fixed event to be cleared |
* |
* RETURN: Status |
* |
* DESCRIPTION: Clear an ACPI event (fixed) |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiClearEvent ( |
UINT32 Event) |
{ |
ACPI_STATUS Status = AE_OK; |
ACPI_FUNCTION_TRACE (AcpiClearEvent); |
/* Decode the Fixed Event */ |
if (Event > ACPI_EVENT_MAX) |
{ |
return_ACPI_STATUS (AE_BAD_PARAMETER); |
} |
/* |
* Clear the requested fixed event (By writing a one to the status |
* register bit) |
*/ |
Status = AcpiWriteBitRegister ( |
AcpiGbl_FixedEventInfo[Event].StatusRegisterId, |
ACPI_CLEAR_STATUS); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiClearEvent) |
/******************************************************************************* |
* |
* FUNCTION: AcpiClearGpe |
* |
* PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 |
* GpeNumber - GPE level within the GPE block |
* |
* RETURN: Status |
* |
* DESCRIPTION: Clear an ACPI event (general purpose) |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiClearGpe ( |
ACPI_HANDLE GpeDevice, |
UINT32 GpeNumber) |
{ |
ACPI_STATUS Status = AE_OK; |
ACPI_GPE_EVENT_INFO *GpeEventInfo; |
ACPI_CPU_FLAGS Flags; |
ACPI_FUNCTION_TRACE (AcpiClearGpe); |
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
/* Ensure that we have a valid GPE number */ |
GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); |
if (!GpeEventInfo) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
Status = AcpiHwClearGpe (GpeEventInfo); |
UnlockAndExit: |
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiClearGpe) |
/******************************************************************************* |
* |
* FUNCTION: AcpiGetEventStatus |
* |
* PARAMETERS: Event - The fixed event |
* EventStatus - Where the current status of the event will |
* be returned |
* |
* RETURN: Status |
* |
* DESCRIPTION: Obtains and returns the current status of the event |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiGetEventStatus ( |
UINT32 Event, |
ACPI_EVENT_STATUS *EventStatus) |
{ |
ACPI_STATUS Status = AE_OK; |
ACPI_FUNCTION_TRACE (AcpiGetEventStatus); |
if (!EventStatus) |
{ |
return_ACPI_STATUS (AE_BAD_PARAMETER); |
} |
/* Decode the Fixed Event */ |
if (Event > ACPI_EVENT_MAX) |
{ |
return_ACPI_STATUS (AE_BAD_PARAMETER); |
} |
/* Get the status of the requested fixed event */ |
Status = AcpiReadBitRegister ( |
AcpiGbl_FixedEventInfo[Event].StatusRegisterId, EventStatus); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiGetEventStatus) |
/******************************************************************************* |
* |
* FUNCTION: AcpiGetGpeStatus |
* |
* PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 |
* GpeNumber - GPE level within the GPE block |
* EventStatus - Where the current status of the event will |
* be returned |
* |
* RETURN: Status |
* |
* DESCRIPTION: Get status of an event (general purpose) |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiGetGpeStatus ( |
ACPI_HANDLE GpeDevice, |
UINT32 GpeNumber, |
ACPI_EVENT_STATUS *EventStatus) |
{ |
ACPI_STATUS Status = AE_OK; |
ACPI_GPE_EVENT_INFO *GpeEventInfo; |
ACPI_CPU_FLAGS Flags; |
ACPI_FUNCTION_TRACE (AcpiGetGpeStatus); |
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); |
/* Ensure that we have a valid GPE number */ |
GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); |
if (!GpeEventInfo) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
/* Obtain status on the requested GPE number */ |
Status = AcpiHwGetGpeStatus (GpeEventInfo, EventStatus); |
UnlockAndExit: |
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiGetGpeStatus) |
/******************************************************************************* |
* |
* FUNCTION: AcpiInstallGpeBlock |
* |
* PARAMETERS: GpeDevice - Handle to the parent GPE Block Device |
* GpeBlockAddress - Address and SpaceID |
* RegisterCount - Number of GPE register pairs in the block |
* InterruptNumber - H/W interrupt for the block |
* |
* RETURN: Status |
* |
* DESCRIPTION: Create and Install a block of GPE registers |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiInstallGpeBlock ( |
ACPI_HANDLE GpeDevice, |
ACPI_GENERIC_ADDRESS *GpeBlockAddress, |
UINT32 RegisterCount, |
UINT32 InterruptNumber) |
{ |
ACPI_STATUS Status; |
ACPI_OPERAND_OBJECT *ObjDesc; |
ACPI_NAMESPACE_NODE *Node; |
ACPI_GPE_BLOCK_INFO *GpeBlock; |
ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock); |
if ((!GpeDevice) || |
(!GpeBlockAddress) || |
(!RegisterCount)) |
{ |
return_ACPI_STATUS (AE_BAD_PARAMETER); |
} |
Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); |
if (ACPI_FAILURE (Status)) |
{ |
return (Status); |
} |
Node = AcpiNsValidateHandle (GpeDevice); |
if (!Node) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
/* |
* For user-installed GPE Block Devices, the GpeBlockBaseNumber |
* is always zero |
*/ |
Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress, RegisterCount, |
0, InterruptNumber, &GpeBlock); |
if (ACPI_FAILURE (Status)) |
{ |
goto UnlockAndExit; |
} |
/* Install block in the DeviceObject attached to the node */ |
ObjDesc = AcpiNsGetAttachedObject (Node); |
if (!ObjDesc) |
{ |
/* |
* No object, create a new one (Device nodes do not always have |
* an attached object) |
*/ |
ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE); |
if (!ObjDesc) |
{ |
Status = AE_NO_MEMORY; |
goto UnlockAndExit; |
} |
Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE); |
/* Remove local reference to the object */ |
AcpiUtRemoveReference (ObjDesc); |
if (ACPI_FAILURE (Status)) |
{ |
goto UnlockAndExit; |
} |
} |
/* Now install the GPE block in the DeviceObject */ |
ObjDesc->Device.GpeBlock = GpeBlock; |
/* Run the _PRW methods and enable the runtime GPEs in the new block */ |
Status = AcpiEvInitializeGpeBlock (Node, GpeBlock); |
UnlockAndExit: |
(void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiInstallGpeBlock) |
/******************************************************************************* |
* |
* FUNCTION: AcpiRemoveGpeBlock |
* |
* PARAMETERS: GpeDevice - Handle to the parent GPE Block Device |
* |
* RETURN: Status |
* |
* DESCRIPTION: Remove a previously installed block of GPE registers |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiRemoveGpeBlock ( |
ACPI_HANDLE GpeDevice) |
{ |
ACPI_OPERAND_OBJECT *ObjDesc; |
ACPI_STATUS Status; |
ACPI_NAMESPACE_NODE *Node; |
ACPI_FUNCTION_TRACE (AcpiRemoveGpeBlock); |
if (!GpeDevice) |
{ |
return_ACPI_STATUS (AE_BAD_PARAMETER); |
} |
Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); |
if (ACPI_FAILURE (Status)) |
{ |
return (Status); |
} |
Node = AcpiNsValidateHandle (GpeDevice); |
if (!Node) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
/* Get the DeviceObject attached to the node */ |
ObjDesc = AcpiNsGetAttachedObject (Node); |
if (!ObjDesc || |
!ObjDesc->Device.GpeBlock) |
{ |
return_ACPI_STATUS (AE_NULL_OBJECT); |
} |
/* Delete the GPE block (but not the DeviceObject) */ |
Status = AcpiEvDeleteGpeBlock (ObjDesc->Device.GpeBlock); |
if (ACPI_SUCCESS (Status)) |
{ |
ObjDesc->Device.GpeBlock = NULL; |
} |
UnlockAndExit: |
(void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiRemoveGpeBlock) |
/******************************************************************************* |
* |
* FUNCTION: AcpiGetGpeDevice |
* |
* PARAMETERS: Index - System GPE index (0-CurrentGpeCount) |
* GpeDevice - Where the parent GPE Device is returned |
* |
* RETURN: Status |
* |
* DESCRIPTION: Obtain the GPE device associated with the input index. A NULL |
* gpe device indicates that the gpe number is contained in one of |
* the FADT-defined gpe blocks. Otherwise, the GPE block device. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiGetGpeDevice ( |
UINT32 Index, |
ACPI_HANDLE *GpeDevice) |
{ |
ACPI_GPE_DEVICE_INFO Info; |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (AcpiGetGpeDevice); |
if (!GpeDevice) |
{ |
return_ACPI_STATUS (AE_BAD_PARAMETER); |
} |
if (Index >= AcpiCurrentGpeCount) |
{ |
return_ACPI_STATUS (AE_NOT_EXIST); |
} |
/* Setup and walk the GPE list */ |
Info.Index = Index; |
Info.Status = AE_NOT_EXIST; |
Info.GpeDevice = NULL; |
Info.NextBlockBaseIndex = 0; |
Status = AcpiEvWalkGpeList (AcpiEvGetGpeDevice, &Info); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
*GpeDevice = ACPI_CAST_PTR (ACPI_HANDLE, Info.GpeDevice); |
return_ACPI_STATUS (Info.Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiGetGpeDevice) |
/******************************************************************************* |
* |
* FUNCTION: AcpiEvGetGpeDevice |
* |
* PARAMETERS: GPE_WALK_CALLBACK |
* |
* RETURN: Status |
* |
* DESCRIPTION: Matches the input GPE index (0-CurrentGpeCount) with a GPE |
* block device. NULL if the GPE is one of the FADT-defined GPEs. |
* |
******************************************************************************/ |
static ACPI_STATUS |
AcpiEvGetGpeDevice ( |
ACPI_GPE_XRUPT_INFO *GpeXruptInfo, |
ACPI_GPE_BLOCK_INFO *GpeBlock, |
void *Context) |
{ |
ACPI_GPE_DEVICE_INFO *Info = Context; |
/* Increment Index by the number of GPEs in this block */ |
Info->NextBlockBaseIndex += GpeBlock->GpeCount; |
if (Info->Index < Info->NextBlockBaseIndex) |
{ |
/* |
* The GPE index is within this block, get the node. Leave the node |
* NULL for the FADT-defined GPEs |
*/ |
if ((GpeBlock->Node)->Type == ACPI_TYPE_DEVICE) |
{ |
Info->GpeDevice = GpeBlock->Node; |
} |
Info->Status = AE_OK; |
return (AE_CTRL_END); |
} |
return (AE_OK); |
} |
/****************************************************************************** |
* |
* FUNCTION: AcpiDisableAllGpes |
* |
* PARAMETERS: None |
* |
* RETURN: Status |
* |
* DESCRIPTION: Disable and clear all GPEs in all GPE blocks |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiDisableAllGpes ( |
void) |
{ |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (AcpiDisableAllGpes); |
Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
Status = AcpiHwDisableAllGpes (); |
(void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
return_ACPI_STATUS (Status); |
} |
/****************************************************************************** |
* |
* FUNCTION: AcpiEnableAllRuntimeGpes |
* |
* PARAMETERS: None |
* |
* RETURN: Status |
* |
* DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiEnableAllRuntimeGpes ( |
void) |
{ |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (AcpiEnableAllRuntimeGpes); |
Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
Status = AcpiHwEnableAllRuntimeGpes (); |
(void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); |
return_ACPI_STATUS (Status); |
} |
/drivers/devman/acpica/events/evxfregn.c |
---|
0,0 → 1,346 |
/****************************************************************************** |
* |
* Module Name: evxfregn - External Interfaces, ACPI Operation Regions and |
* Address Spaces. |
* |
*****************************************************************************/ |
/****************************************************************************** |
* |
* 1. Copyright Notice |
* |
* Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. |
* All rights reserved. |
* |
* 2. License |
* |
* 2.1. This is your license from Intel Corp. under its intellectual property |
* rights. You may have additional license terms from the party that provided |
* you this software, covering your right to use that party's intellectual |
* property rights. |
* |
* 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a |
* copy of the source code appearing in this file ("Covered Code") an |
* irrevocable, perpetual, worldwide license under Intel's copyrights in the |
* base code distributed originally by Intel ("Original Intel Code") to copy, |
* make derivatives, distribute, use and display any portion of the Covered |
* Code in any form, with the right to sublicense such rights; and |
* |
* 2.3. Intel grants Licensee a non-exclusive and non-transferable patent |
* license (with the right to sublicense), under only those claims of Intel |
* patents that are infringed by the Original Intel Code, to make, use, sell, |
* offer to sell, and import the Covered Code and derivative works thereof |
* solely to the minimum extent necessary to exercise the above copyright |
* license, and in no event shall the patent license extend to any additions |
* to or modifications of the Original Intel Code. No other license or right |
* is granted directly or by implication, estoppel or otherwise; |
* |
* The above copyright and patent license is granted only if the following |
* conditions are met: |
* |
* 3. Conditions |
* |
* 3.1. Redistribution of Source with Rights to Further Distribute Source. |
* Redistribution of source code of any substantial portion of the Covered |
* Code or modification with rights to further distribute source must include |
* the above Copyright Notice, the above License, this list of Conditions, |
* and the following Disclaimer and Export Compliance provision. In addition, |
* Licensee must cause all Covered Code to which Licensee contributes to |
* contain a file documenting the changes Licensee made to create that Covered |
* Code and the date of any change. Licensee must include in that file the |
* documentation of any changes made by any predecessor Licensee. Licensee |
* must include a prominent statement that the modification is derived, |
* directly or indirectly, from Original Intel Code. |
* |
* 3.2. Redistribution of Source with no Rights to Further Distribute Source. |
* Redistribution of source code of any substantial portion of the Covered |
* Code or modification without rights to further distribute source must |
* include the following Disclaimer and Export Compliance provision in the |
* documentation and/or other materials provided with distribution. In |
* addition, Licensee may not authorize further sublicense of source of any |
* portion of the Covered Code, and must include terms to the effect that the |
* license from Licensee to its licensee is limited to the intellectual |
* property embodied in the software Licensee provides to its licensee, and |
* not to intellectual property embodied in modifications its licensee may |
* make. |
* |
* 3.3. Redistribution of Executable. Redistribution in executable form of any |
* substantial portion of the Covered Code or modification must reproduce the |
* above Copyright Notice, and the following Disclaimer and Export Compliance |
* provision in the documentation and/or other materials provided with the |
* distribution. |
* |
* 3.4. Intel retains all right, title, and interest in and to the Original |
* Intel Code. |
* |
* 3.5. Neither the name Intel nor any other trademark owned or controlled by |
* Intel shall be used in advertising or otherwise to promote the sale, use or |
* other dealings in products derived from or relating to the Covered Code |
* without prior written authorization from Intel. |
* |
* 4. Disclaimer and Export Compliance |
* |
* 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED |
* HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE |
* IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, |
* INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY |
* UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY |
* IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A |
* PARTICULAR PURPOSE. |
* |
* 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES |
* OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR |
* COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, |
* SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY |
* CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL |
* HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS |
* SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY |
* LIMITED REMEDY. |
* |
* 4.3. Licensee shall not export, either directly or indirectly, any of this |
* software or system incorporating such software without first obtaining any |
* required license or other approval from the U. S. Department of Commerce or |
* any other agency or department of the United States Government. In the |
* event Licensee exports any such software from the United States or |
* re-exports any such software from a foreign destination, Licensee shall |
* ensure that the distribution and export/re-export of the software is in |
* compliance with all laws, regulations, orders, or other restrictions of the |
* U.S. Export Administration Regulations. Licensee agrees that neither it nor |
* any of its subsidiaries will export/re-export any technical data, process, |
* software, or service, directly or indirectly, to any country for which the |
* United States government or any agency thereof requires an export license, |
* other governmental approval, or letter of assurance, without first obtaining |
* such license, approval or letter. |
* |
*****************************************************************************/ |
#define __EVXFREGN_C__ |
#include "acpi.h" |
#include "accommon.h" |
#include "acnamesp.h" |
#include "acevents.h" |
#define _COMPONENT ACPI_EVENTS |
ACPI_MODULE_NAME ("evxfregn") |
/******************************************************************************* |
* |
* FUNCTION: AcpiInstallAddressSpaceHandler |
* |
* PARAMETERS: Device - Handle for the device |
* SpaceId - The address space ID |
* Handler - Address of the handler |
* Setup - Address of the setup function |
* Context - Value passed to the handler on each access |
* |
* RETURN: Status |
* |
* DESCRIPTION: Install a handler for all OpRegions of a given SpaceId. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiInstallAddressSpaceHandler ( |
ACPI_HANDLE Device, |
ACPI_ADR_SPACE_TYPE SpaceId, |
ACPI_ADR_SPACE_HANDLER Handler, |
ACPI_ADR_SPACE_SETUP Setup, |
void *Context) |
{ |
ACPI_NAMESPACE_NODE *Node; |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (AcpiInstallAddressSpaceHandler); |
/* Parameter validation */ |
if (!Device) |
{ |
return_ACPI_STATUS (AE_BAD_PARAMETER); |
} |
Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
/* Convert and validate the device handle */ |
Node = AcpiNsValidateHandle (Device); |
if (!Node) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
/* Install the handler for all Regions for this Space ID */ |
Status = AcpiEvInstallSpaceHandler (Node, SpaceId, Handler, Setup, Context); |
if (ACPI_FAILURE (Status)) |
{ |
goto UnlockAndExit; |
} |
/* Run all _REG methods for this address space */ |
Status = AcpiEvExecuteRegMethods (Node, SpaceId); |
UnlockAndExit: |
(void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiInstallAddressSpaceHandler) |
/******************************************************************************* |
* |
* FUNCTION: AcpiRemoveAddressSpaceHandler |
* |
* PARAMETERS: Device - Handle for the device |
* SpaceId - The address space ID |
* Handler - Address of the handler |
* |
* RETURN: Status |
* |
* DESCRIPTION: Remove a previously installed handler. |
* |
******************************************************************************/ |
ACPI_STATUS |
AcpiRemoveAddressSpaceHandler ( |
ACPI_HANDLE Device, |
ACPI_ADR_SPACE_TYPE SpaceId, |
ACPI_ADR_SPACE_HANDLER Handler) |
{ |
ACPI_OPERAND_OBJECT *ObjDesc; |
ACPI_OPERAND_OBJECT *HandlerObj; |
ACPI_OPERAND_OBJECT *RegionObj; |
ACPI_OPERAND_OBJECT **LastObjPtr; |
ACPI_NAMESPACE_NODE *Node; |
ACPI_STATUS Status; |
ACPI_FUNCTION_TRACE (AcpiRemoveAddressSpaceHandler); |
/* Parameter validation */ |
if (!Device) |
{ |
return_ACPI_STATUS (AE_BAD_PARAMETER); |
} |
Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); |
if (ACPI_FAILURE (Status)) |
{ |
return_ACPI_STATUS (Status); |
} |
/* Convert and validate the device handle */ |
Node = AcpiNsValidateHandle (Device); |
if (!Node || |
((Node->Type != ACPI_TYPE_DEVICE) && |
(Node->Type != ACPI_TYPE_PROCESSOR) && |
(Node->Type != ACPI_TYPE_THERMAL) && |
(Node != AcpiGbl_RootNode))) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
/* Make sure the internal object exists */ |
ObjDesc = AcpiNsGetAttachedObject (Node); |
if (!ObjDesc) |
{ |
Status = AE_NOT_EXIST; |
goto UnlockAndExit; |
} |
/* Find the address handler the user requested */ |
HandlerObj = ObjDesc->Device.Handler; |
LastObjPtr = &ObjDesc->Device.Handler; |
while (HandlerObj) |
{ |
/* We have a handler, see if user requested this one */ |
if (HandlerObj->AddressSpace.SpaceId == SpaceId) |
{ |
/* Handler must be the same as the installed handler */ |
if (HandlerObj->AddressSpace.Handler != Handler) |
{ |
Status = AE_BAD_PARAMETER; |
goto UnlockAndExit; |
} |
/* Matched SpaceId, first dereference this in the Regions */ |
ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, |
"Removing address handler %p(%p) for region %s " |
"on Device %p(%p)\n", |
HandlerObj, Handler, AcpiUtGetRegionName (SpaceId), |
Node, ObjDesc)); |
RegionObj = HandlerObj->AddressSpace.RegionList; |
/* Walk the handler's region list */ |
while (RegionObj) |
{ |
/* |
* First disassociate the handler from the region. |
* |
* NOTE: this doesn't mean that the region goes away |
* The region is just inaccessible as indicated to |
* the _REG method |
*/ |
AcpiEvDetachRegion (RegionObj, TRUE); |
/* |
* Walk the list: Just grab the head because the |
* DetachRegion removed the previous head. |
*/ |
RegionObj = HandlerObj->AddressSpace.RegionList; |
} |
/* Remove this Handler object from the list */ |
*LastObjPtr = HandlerObj->AddressSpace.Next; |
/* Now we can delete the handler object */ |
AcpiUtRemoveReference (HandlerObj); |
goto UnlockAndExit; |
} |
/* Walk the linked list of handlers */ |
LastObjPtr = &HandlerObj->AddressSpace.Next; |
HandlerObj = HandlerObj->AddressSpace.Next; |
} |
/* The handler does not exist */ |
ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, |
"Unable to remove address handler %p for %s(%X), DevNode %p, obj %p\n", |
Handler, AcpiUtGetRegionName (SpaceId), SpaceId, Node, ObjDesc)); |
Status = AE_NOT_EXIST; |
UnlockAndExit: |
(void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); |
return_ACPI_STATUS (Status); |
} |
ACPI_EXPORT_SYMBOL (AcpiRemoveAddressSpaceHandler) |