mirror of
https://github.com/acpica/acpica/
synced 2024-12-26 04:16:58 +03:00
GPE support code overhaul and enhancement.
Contains the complete overhaul of the GPE support code including removal of _PRW execution, improved handling of wake GPEs, new external interfaces, and implicit notify support. ACPICA BZ 858, 870,877. Matthew Garrett, Lin Ming, Bob Moore, Rafael Wysocki. Note: This support is committed as a single patch here because of multiple patch backporting from Linux and the resulting interdependency issues. See the ACPICA reference for full documentation.
This commit is contained in:
parent
1d96aaf67d
commit
3bc77e86ae
@ -61,6 +61,7 @@ OBJS = \
|
||||
evsci.o \
|
||||
evxface.o \
|
||||
evxfevnt.o \
|
||||
evxfgpe.o \
|
||||
evxfregn.o \
|
||||
exconfig.o \
|
||||
exconvrt.o \
|
||||
@ -317,6 +318,9 @@ evxface.o : $(ACPICA_CORE)/events/evxface.c
|
||||
evxfevnt.o : $(ACPICA_CORE)/events/evxfevnt.c
|
||||
$(COMPILE)
|
||||
|
||||
evxfgpe.o : $(ACPICA_CORE)/events/evxfgpe.c
|
||||
$(COMPILE)
|
||||
|
||||
evxfregn.o : $(ACPICA_CORE)/events/evxfregn.c
|
||||
$(COMPILE)
|
||||
|
||||
|
@ -56,6 +56,7 @@ OBJS = \
|
||||
evsci.o \
|
||||
evxface.o \
|
||||
evxfevnt.o \
|
||||
evxfgpe.o \
|
||||
evxfregn.o \
|
||||
exconfig.o \
|
||||
exconvrt.o \
|
||||
@ -312,6 +313,9 @@ evxface.o : $(ACPICA_CORE)/events/evxface.c
|
||||
evxfevnt.o : $(ACPICA_CORE)/events/evxfevnt.c
|
||||
$(COMPILE)
|
||||
|
||||
evxfgpe.o : $(ACPICA_CORE)/events/evxfgpe.c
|
||||
$(COMPILE)
|
||||
|
||||
evxfregn.o : $(ACPICA_CORE)/events/evxfregn.c
|
||||
$(COMPILE)
|
||||
|
||||
|
@ -2071,7 +2071,7 @@ AcpiDbGenerateGpe (
|
||||
return;
|
||||
}
|
||||
|
||||
(void) AcpiEvGpeDispatch (GpeEventInfo, GpeNumber);
|
||||
(void) AcpiEvGpeDispatch (NULL, GpeEventInfo, GpeNumber);
|
||||
}
|
||||
|
||||
|
||||
|
@ -896,7 +896,8 @@ AcpiDbDisplayGpes (
|
||||
GpeIndex = (i * ACPI_GPE_REGISTER_WIDTH) + j;
|
||||
GpeEventInfo = &GpeBlock->EventInfo[GpeIndex];
|
||||
|
||||
if (!(GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK))
|
||||
if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
|
||||
ACPI_GPE_DISPATCH_NONE)
|
||||
{
|
||||
/* This GPE is not used (no method or handler), ignore it */
|
||||
|
||||
@ -906,8 +907,7 @@ AcpiDbDisplayGpes (
|
||||
AcpiOsPrintf (
|
||||
" GPE %.2X: %p RunRefs %2.2X Flags %2.2X (",
|
||||
GpeBlock->BlockBaseNumber + GpeIndex, GpeEventInfo,
|
||||
GpeEventInfo->RuntimeCount,
|
||||
GpeEventInfo->Flags);
|
||||
GpeEventInfo->RuntimeCount, GpeEventInfo->Flags);
|
||||
|
||||
/* Decode the flags byte */
|
||||
|
||||
@ -931,14 +931,17 @@ AcpiDbDisplayGpes (
|
||||
|
||||
switch (GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK)
|
||||
{
|
||||
case ACPI_GPE_DISPATCH_NOT_USED:
|
||||
case ACPI_GPE_DISPATCH_NONE:
|
||||
AcpiOsPrintf ("NotUsed");
|
||||
break;
|
||||
case ACPI_GPE_DISPATCH_METHOD:
|
||||
AcpiOsPrintf ("Method");
|
||||
break;
|
||||
case ACPI_GPE_DISPATCH_HANDLER:
|
||||
AcpiOsPrintf ("Handler");
|
||||
break;
|
||||
case ACPI_GPE_DISPATCH_METHOD:
|
||||
AcpiOsPrintf ("Method");
|
||||
case ACPI_GPE_DISPATCH_NOTIFY:
|
||||
AcpiOsPrintf ("Notify");
|
||||
break;
|
||||
default:
|
||||
AcpiOsPrintf ("UNKNOWN: %X",
|
||||
|
@ -178,54 +178,6 @@ AcpiEvInitializeEvents (
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* 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
|
||||
@ -366,9 +318,17 @@ AcpiEvFixedEventDetect (
|
||||
if ((FixedStatus & AcpiGbl_FixedEventInfo[i].StatusBitMask) &&
|
||||
(FixedEnable & AcpiGbl_FixedEventInfo[i].EnableBitMask))
|
||||
{
|
||||
/* Found an active (signalled) event */
|
||||
|
||||
/*
|
||||
* Found an active (signalled) event. Invoke global event
|
||||
* handler if present.
|
||||
*/
|
||||
AcpiFixedEventCount[i]++;
|
||||
if (AcpiGbl_GlobalEventHandler)
|
||||
{
|
||||
AcpiGbl_GlobalEventHandler (ACPI_EVENT_TYPE_FIXED, NULL,
|
||||
i, AcpiGbl_GlobalEventHandlerContext);
|
||||
}
|
||||
|
||||
IntStatus |= AcpiEvFixedEventDispatch (i);
|
||||
}
|
||||
}
|
||||
|
@ -202,12 +202,13 @@ AcpiEvEnableGpe (
|
||||
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* We will only allow a GPE to be enabled if it has either an associated
|
||||
* method (_Lxx/_Exx) or a handler, or is using the implicit notify
|
||||
* feature. Otherwise, the GPE will be immediately disabled by
|
||||
* AcpiEvGpeDispatch the first time it fires.
|
||||
*/
|
||||
if (!(GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK))
|
||||
if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
|
||||
ACPI_GPE_DISPATCH_NONE)
|
||||
{
|
||||
return_ACPI_STATUS (AE_NO_HANDLER);
|
||||
}
|
||||
@ -227,6 +228,104 @@ AcpiEvEnableGpe (
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: AcpiEvAddGpeReference
|
||||
*
|
||||
* PARAMETERS: GpeEventInfo - Add a reference to this GPE
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
|
||||
* hardware-enabled.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiEvAddGpeReference (
|
||||
ACPI_GPE_EVENT_INFO *GpeEventInfo)
|
||||
{
|
||||
ACPI_STATUS Status = AE_OK;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE (EvAddGpeReference);
|
||||
|
||||
|
||||
if (GpeEventInfo->RuntimeCount == ACPI_UINT8_MAX)
|
||||
{
|
||||
return_ACPI_STATUS (AE_LIMIT);
|
||||
}
|
||||
|
||||
GpeEventInfo->RuntimeCount++;
|
||||
if (GpeEventInfo->RuntimeCount == 1)
|
||||
{
|
||||
/* Enable on first reference */
|
||||
|
||||
Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo);
|
||||
if (ACPI_SUCCESS (Status))
|
||||
{
|
||||
Status = AcpiEvEnableGpe (GpeEventInfo);
|
||||
}
|
||||
|
||||
if (ACPI_FAILURE (Status))
|
||||
{
|
||||
GpeEventInfo->RuntimeCount--;
|
||||
}
|
||||
}
|
||||
|
||||
return_ACPI_STATUS (Status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: AcpiEvRemoveGpeReference
|
||||
*
|
||||
* PARAMETERS: GpeEventInfo - Remove a reference to this GPE
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Remove a reference to a GPE. When the last reference is
|
||||
* removed, the GPE is hardware-disabled.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiEvRemoveGpeReference (
|
||||
ACPI_GPE_EVENT_INFO *GpeEventInfo)
|
||||
{
|
||||
ACPI_STATUS Status = AE_OK;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE (EvRemoveGpeReference);
|
||||
|
||||
|
||||
if (!GpeEventInfo->RuntimeCount)
|
||||
{
|
||||
return_ACPI_STATUS (AE_LIMIT);
|
||||
}
|
||||
|
||||
GpeEventInfo->RuntimeCount--;
|
||||
if (!GpeEventInfo->RuntimeCount)
|
||||
{
|
||||
/* Disable on last reference */
|
||||
|
||||
Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo);
|
||||
if (ACPI_SUCCESS (Status))
|
||||
{
|
||||
Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
|
||||
}
|
||||
|
||||
if (ACPI_FAILURE (Status))
|
||||
{
|
||||
GpeEventInfo->RuntimeCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return_ACPI_STATUS (Status);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: AcpiEvLowGetGpeInfo
|
||||
@ -412,7 +511,7 @@ AcpiEvGpeDetect (
|
||||
}
|
||||
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
|
||||
"Read GPE Register at GPE%X: Status=%02X, Enable=%02X\n",
|
||||
"Read GPE Register at GPE%02X: Status=%02X, Enable=%02X\n",
|
||||
GpeRegisterInfo->BaseGpeNumber, StatusReg, EnableReg));
|
||||
|
||||
/* Check if there is anything active at all in this register */
|
||||
@ -437,7 +536,7 @@ AcpiEvGpeDetect (
|
||||
* Found an active GPE. Dispatch the event to a handler
|
||||
* or method.
|
||||
*/
|
||||
IntStatus |= AcpiEvGpeDispatch (
|
||||
IntStatus |= AcpiEvGpeDispatch (GpeBlock->Node,
|
||||
&GpeBlock->EventInfo[((ACPI_SIZE) i *
|
||||
ACPI_GPE_REGISTER_WIDTH) + j],
|
||||
j + GpeRegisterInfo->BaseGpeNumber);
|
||||
@ -521,13 +620,27 @@ AcpiEvAsynchExecuteGpeMethod (
|
||||
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)
|
||||
/* Do the correct dispatch - normal method or implicit notify */
|
||||
|
||||
switch (LocalGpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK)
|
||||
{
|
||||
case ACPI_GPE_DISPATCH_NOTIFY:
|
||||
|
||||
/*
|
||||
* Implicit notify.
|
||||
* Dispatch a DEVICE_WAKE notify to the appropriate handler.
|
||||
* NOTE: the request is queued for execution after this method
|
||||
* completes. The notify handlers are NOT invoked synchronously
|
||||
* from this thread -- because handlers may in turn run other
|
||||
* control methods.
|
||||
*/
|
||||
Status = AcpiEvQueueNotifyRequest (
|
||||
LocalGpeEventInfo->Dispatch.DeviceNode,
|
||||
ACPI_NOTIFY_DEVICE_WAKE);
|
||||
break;
|
||||
|
||||
case ACPI_GPE_DISPATCH_METHOD:
|
||||
|
||||
/* Allocate the evaluation information block */
|
||||
|
||||
Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
|
||||
@ -538,8 +651,8 @@ AcpiEvAsynchExecuteGpeMethod (
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx
|
||||
* control method that corresponds to this GPE
|
||||
* 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;
|
||||
@ -554,6 +667,11 @@ AcpiEvAsynchExecuteGpeMethod (
|
||||
"while evaluating GPE method [%4.4s]",
|
||||
AcpiUtGetNodeName (LocalGpeEventInfo->Dispatch.MethodNode)));
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return_VOID; /* Should never happen */
|
||||
}
|
||||
|
||||
/* Defer enabling of GPE until all notify handlers are done */
|
||||
@ -573,6 +691,7 @@ AcpiEvAsynchExecuteGpeMethod (
|
||||
* FUNCTION: AcpiEvAsynchEnableGpe
|
||||
*
|
||||
* PARAMETERS: Context (GpeEventInfo) - Info for this GPE
|
||||
* Callback from AcpiOsExecute
|
||||
*
|
||||
* RETURN: None
|
||||
*
|
||||
@ -586,41 +705,66 @@ 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;
|
||||
}
|
||||
}
|
||||
(void) AcpiEvFinishGpe (GpeEventInfo);
|
||||
|
||||
/*
|
||||
* Enable this GPE, conditionally. This means that the GPE will only be
|
||||
* physically enabled if the EnableForRun bit is set in the EventInfo
|
||||
*/
|
||||
(void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_CONDITIONAL_ENABLE);
|
||||
|
||||
Exit:
|
||||
ACPI_FREE (GpeEventInfo);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: AcpiEvFinishGpe
|
||||
*
|
||||
* PARAMETERS: GpeEventInfo - Info for this GPE
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Clear/Enable a GPE. Common code that is used after execution
|
||||
* of a GPE method or a synchronous or asynchronous GPE handler.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiEvFinishGpe (
|
||||
ACPI_GPE_EVENT_INFO *GpeEventInfo)
|
||||
{
|
||||
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))
|
||||
{
|
||||
return (Status);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable this GPE, conditionally. This means that the GPE will
|
||||
* only be physically enabled if the EnableForRun bit is set
|
||||
* in the EventInfo.
|
||||
*/
|
||||
(void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_CONDITIONAL_ENABLE);
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: AcpiEvGpeDispatch
|
||||
*
|
||||
* PARAMETERS: GpeEventInfo - Info for this GPE
|
||||
* GpeNumber - Number relative to the parent GPE block
|
||||
* PARAMETERS: GpeDevice - Device node. NULL for GPE0/GPE1
|
||||
* GpeEventInfo - Info for this GPE
|
||||
* GpeNumber - Number relative to the parent GPE block
|
||||
*
|
||||
* RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
|
||||
*
|
||||
@ -633,16 +777,25 @@ Exit:
|
||||
|
||||
UINT32
|
||||
AcpiEvGpeDispatch (
|
||||
ACPI_NAMESPACE_NODE *GpeDevice,
|
||||
ACPI_GPE_EVENT_INFO *GpeEventInfo,
|
||||
UINT32 GpeNumber)
|
||||
{
|
||||
ACPI_STATUS Status;
|
||||
UINT32 ReturnValue;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE (EvGpeDispatch);
|
||||
|
||||
|
||||
/* Invoke global event handler if present */
|
||||
|
||||
AcpiGpeCount++;
|
||||
if (AcpiGbl_GlobalEventHandler)
|
||||
{
|
||||
AcpiGbl_GlobalEventHandler (ACPI_EVENT_TYPE_GPE, GpeDevice,
|
||||
GpeNumber, AcpiGbl_GlobalEventHandlerContext);
|
||||
}
|
||||
|
||||
/*
|
||||
* If edge-triggered, clear the GPE status bit now. Note that
|
||||
@ -655,58 +808,55 @@ AcpiEvGpeDispatch (
|
||||
if (ACPI_FAILURE (Status))
|
||||
{
|
||||
ACPI_EXCEPTION ((AE_INFO, Status,
|
||||
"Unable to clear GPE[0x%2X]", GpeNumber));
|
||||
"Unable to clear GPE%02X", 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.
|
||||
* Always disable the GPE so that it does not keep firing before
|
||||
* any asynchronous activity completes (either from the execution
|
||||
* of a GPE method or an asynchronous GPE handler.)
|
||||
*
|
||||
* If there is no handler or method to run, just disable the
|
||||
* GPE and leave it disabled permanently to prevent further such
|
||||
* pointless events from firing.
|
||||
*/
|
||||
Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
|
||||
if (ACPI_FAILURE (Status))
|
||||
{
|
||||
ACPI_EXCEPTION ((AE_INFO, Status,
|
||||
"Unable to disable GPE%02X", 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, leave the GPE
|
||||
* disabled.
|
||||
*/
|
||||
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);
|
||||
/* Invoke the installed handler (at interrupt level) */
|
||||
|
||||
/* It is now safe to clear level-triggered events. */
|
||||
ReturnValue = GpeEventInfo->Dispatch.Handler->Address (
|
||||
GpeDevice, GpeNumber,
|
||||
GpeEventInfo->Dispatch.Handler->Context);
|
||||
|
||||
if ((GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK) ==
|
||||
ACPI_GPE_LEVEL_TRIGGERED)
|
||||
/* If requested, clear (if level-triggered) and reenable the GPE */
|
||||
|
||||
if (ReturnValue & ACPI_REENABLE_GPE)
|
||||
{
|
||||
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);
|
||||
}
|
||||
(void) AcpiEvFinishGpe (GpeEventInfo);
|
||||
}
|
||||
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 = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
|
||||
if (ACPI_FAILURE (Status))
|
||||
{
|
||||
ACPI_EXCEPTION ((AE_INFO, Status,
|
||||
"Unable to disable GPE[0x%2X]", GpeNumber));
|
||||
return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
|
||||
}
|
||||
case ACPI_GPE_DISPATCH_NOTIFY:
|
||||
|
||||
/*
|
||||
* Execute the method associated with the GPE
|
||||
@ -717,7 +867,7 @@ AcpiEvGpeDispatch (
|
||||
if (ACPI_FAILURE (Status))
|
||||
{
|
||||
ACPI_EXCEPTION ((AE_INFO, Status,
|
||||
"Unable to queue handler for GPE[0x%2X] - event disabled",
|
||||
"Unable to queue handler for GPE%02X - event disabled",
|
||||
GpeNumber));
|
||||
}
|
||||
break;
|
||||
@ -730,20 +880,8 @@ AcpiEvGpeDispatch (
|
||||
* 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",
|
||||
"No handler or method for GPE%02X, disabling event",
|
||||
GpeNumber));
|
||||
|
||||
/*
|
||||
* Disable the GPE. The GPE will remain disabled until a handler
|
||||
* is installed or ACPICA is restarted.
|
||||
*/
|
||||
Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
|
||||
if (ACPI_FAILURE (Status))
|
||||
{
|
||||
ACPI_EXCEPTION ((AE_INFO, Status,
|
||||
"Unable to disable GPE[0x%2X]", GpeNumber));
|
||||
return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -467,6 +467,7 @@ AcpiEvCreateGpeBlock (
|
||||
|
||||
GpeBlock->Node = GpeDevice;
|
||||
GpeBlock->GpeCount = (UINT16) (RegisterCount * ACPI_GPE_REGISTER_WIDTH);
|
||||
GpeBlock->Initialized = FALSE;
|
||||
GpeBlock->RegisterCount = RegisterCount;
|
||||
GpeBlock->BlockBaseNumber = GpeBlockBaseNumber;
|
||||
|
||||
@ -493,11 +494,12 @@ AcpiEvCreateGpeBlock (
|
||||
return_ACPI_STATUS (Status);
|
||||
}
|
||||
|
||||
AcpiGbl_AllGpesInitialized = FALSE;
|
||||
|
||||
/* 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,
|
||||
@ -529,30 +531,26 @@ AcpiEvCreateGpeBlock (
|
||||
*
|
||||
* FUNCTION: AcpiEvInitializeGpeBlock
|
||||
*
|
||||
* PARAMETERS: GpeDevice - Handle to the parent GPE block
|
||||
* GpeBlock - Gpe Block info
|
||||
* PARAMETERS: ACPI_GPE_CALLBACK
|
||||
*
|
||||
* 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.
|
||||
* DESCRIPTION: Initialize and enable a GPE block. Enable GPEs that have
|
||||
* associated methods.
|
||||
* Note: Assumes namespace is locked.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiEvInitializeGpeBlock (
|
||||
ACPI_NAMESPACE_NODE *GpeDevice,
|
||||
ACPI_GPE_BLOCK_INFO *GpeBlock)
|
||||
ACPI_GPE_XRUPT_INFO *GpeXruptInfo,
|
||||
ACPI_GPE_BLOCK_INFO *GpeBlock,
|
||||
void *Ignored)
|
||||
{
|
||||
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;
|
||||
|
||||
@ -560,51 +558,22 @@ AcpiEvInitializeGpeBlock (
|
||||
ACPI_FUNCTION_TRACE (EvInitializeGpeBlock);
|
||||
|
||||
|
||||
/* Ignore a null GPE block (e.g., if no GPE block 1 exists) */
|
||||
|
||||
if (!GpeBlock)
|
||||
/*
|
||||
* Ignore a null GPE block (e.g., if no GPE block 1 exists), and
|
||||
* any GPE blocks that have been initialized already.
|
||||
*/
|
||||
if (!GpeBlock || GpeBlock->Initialized)
|
||||
{
|
||||
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.
|
||||
* Enable all GPEs that have a corresponding method and have the
|
||||
* ACPI_GPE_CAN_WAKE flag unset. Any other GPEs within this block
|
||||
* must be enabled via the acpi_enable_gpe() interface.
|
||||
*/
|
||||
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++)
|
||||
@ -613,45 +582,24 @@ AcpiEvInitializeGpeBlock (
|
||||
|
||||
GpeIndex = (i * ACPI_GPE_REGISTER_WIDTH) + j;
|
||||
GpeEventInfo = &GpeBlock->EventInfo[GpeIndex];
|
||||
GpeNumber = GpeIndex + GpeBlock->BlockBaseNumber;
|
||||
|
||||
/*
|
||||
* If the GPE has already been enabled for runtime
|
||||
* signalling, make sure that it remains enabled, but
|
||||
* do not increment its reference count.
|
||||
* Ignore GPEs that have no corresponding _Lxx/_Exx method
|
||||
* and GPEs that are used to wake the system
|
||||
*/
|
||||
if (GpeEventInfo->RuntimeCount)
|
||||
{
|
||||
Status = AcpiEvEnableGpe (GpeEventInfo);
|
||||
goto Enabled;
|
||||
}
|
||||
|
||||
/* 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))
|
||||
if (((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_NONE) ||
|
||||
((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER) ||
|
||||
(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Enable this GPE */
|
||||
|
||||
Status = AcpiEnableGpe (GpeDevice, GpeNumber);
|
||||
Enabled:
|
||||
Status = AcpiEvAddGpeReference (GpeEventInfo);
|
||||
if (ACPI_FAILURE (Status))
|
||||
{
|
||||
ACPI_EXCEPTION ((AE_INFO, Status,
|
||||
"Could not enable GPE 0x%02X", GpeNumber));
|
||||
"Could not enable GPE 0x%02X",
|
||||
GpeIndex + GpeBlock->BlockBaseNumber));
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -659,13 +607,13 @@ Enabled:
|
||||
}
|
||||
}
|
||||
|
||||
if (GpeEnabledCount || WakeGpeCount)
|
||||
if (GpeEnabledCount)
|
||||
{
|
||||
ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
|
||||
"Enabled %u Runtime GPEs, added %u Wake GPEs in this block\n",
|
||||
GpeEnabledCount, WakeGpeCount));
|
||||
"Enabled %u GPEs in this block\n", GpeEnabledCount));
|
||||
}
|
||||
|
||||
GpeBlock->Initialized = TRUE;
|
||||
return_ACPI_STATUS (AE_OK);
|
||||
}
|
||||
|
||||
|
@ -118,12 +118,28 @@
|
||||
#include "accommon.h"
|
||||
#include "acevents.h"
|
||||
#include "acnamesp.h"
|
||||
#include "acinterp.h"
|
||||
|
||||
#define _COMPONENT ACPI_EVENTS
|
||||
ACPI_MODULE_NAME ("evgpeinit")
|
||||
|
||||
|
||||
/*
|
||||
* Note: History of _PRW support in ACPICA
|
||||
*
|
||||
* Originally (2000 - 2010), the GPE initialization code performed a walk of
|
||||
* the entire namespace to execute the _PRW methods and detect all GPEs
|
||||
* capable of waking the system.
|
||||
*
|
||||
* As of 10/2010, the _PRW method execution has been removed since it is
|
||||
* actually unnecessary. The host OS must in fact execute all _PRW methods
|
||||
* in order to identify the device/power-resource dependencies. We now put
|
||||
* the onus on the host OS to identify the wake GPEs as part of this process
|
||||
* and to inform ACPICA of these GPEs via the AcpiSetupGpeForWake interface. This
|
||||
* not only reduces the complexity of the ACPICA initialization code, but in
|
||||
* some cases (on systems with very large namespaces) it should reduce the
|
||||
* kernel boot time as well.
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: AcpiEvGpeInitialize
|
||||
@ -288,10 +304,7 @@ Cleanup:
|
||||
*
|
||||
* 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.
|
||||
* methods have been installed, register the new methods.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
@ -303,49 +316,13 @@ AcpiEvUpdateGpes (
|
||||
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.
|
||||
* 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.
|
||||
* Any GPEs that correspond to new _Lxx/_Exx methods are immediately
|
||||
* enabled.
|
||||
*
|
||||
* Examine the namespace underneath each GpeDevice within the
|
||||
* GpeBlock lists.
|
||||
@ -357,7 +334,8 @@ AcpiEvUpdateGpes (
|
||||
}
|
||||
|
||||
WalkInfo.Count = 0;
|
||||
WalkInfo.EnableThisGpe = TRUE;
|
||||
WalkInfo.OwnerId = TableOwnerId;
|
||||
WalkInfo.ExecuteByOwnerId = TRUE;
|
||||
|
||||
/* Walk the interrupt level descriptor list */
|
||||
|
||||
@ -388,11 +366,9 @@ AcpiEvUpdateGpes (
|
||||
GpeXruptInfo = GpeXruptInfo->Next;
|
||||
}
|
||||
|
||||
if (WalkInfo.Count || NewWakeGpeCount)
|
||||
if (WalkInfo.Count)
|
||||
{
|
||||
ACPI_INFO ((AE_INFO,
|
||||
"Enabled %u new runtime GPEs, added %u new wakeup GPEs",
|
||||
WalkInfo.Count, NewWakeGpeCount));
|
||||
ACPI_INFO ((AE_INFO, "Enabled %u new GPEs", WalkInfo.Count));
|
||||
}
|
||||
|
||||
(void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
|
||||
@ -422,9 +398,7 @@ AcpiEvUpdateGpes (
|
||||
* 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)
|
||||
* with that owner.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
@ -438,8 +412,6 @@ AcpiEvMatchGpeMethod (
|
||||
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;
|
||||
@ -474,9 +446,6 @@ AcpiEvMatchGpeMethod (
|
||||
/*
|
||||
* 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])
|
||||
{
|
||||
@ -551,212 +520,12 @@ AcpiEvMatchGpeMethod (
|
||||
* Add the GPE information from above to the GpeEventInfo block for
|
||||
* use during dispatch of this GPE.
|
||||
*/
|
||||
GpeEventInfo->Flags &= ~(ACPI_GPE_DISPATCH_MASK);
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -239,6 +239,51 @@ AcpiEvValidGpeEvent (
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
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: AcpiEvGetGpeXruptBlock
|
||||
|
@ -175,6 +175,66 @@ Cleanup:
|
||||
ACPI_EXPORT_SYMBOL (AcpiInstallExceptionHandler)
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: AcpiInstallGlobalEventHandler
|
||||
*
|
||||
* PARAMETERS: Handler - Pointer to the global event handler function
|
||||
* Context - Value passed to the handler on each event
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Saves the pointer to the handler function. The global handler
|
||||
* is invoked upon each incoming GPE and Fixed Event. It is
|
||||
* invoked at interrupt level at the time of the event dispatch.
|
||||
* Can be used to update event counters, etc.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiInstallGlobalEventHandler (
|
||||
ACPI_GBL_EVENT_HANDLER Handler,
|
||||
void *Context)
|
||||
{
|
||||
ACPI_STATUS Status;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE (AcpiInstallGlobalEventHandler);
|
||||
|
||||
|
||||
/* Parameter validation */
|
||||
|
||||
if (!Handler)
|
||||
{
|
||||
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 (AcpiGbl_GlobalEventHandler)
|
||||
{
|
||||
Status = AE_ALREADY_EXISTS;
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
AcpiGbl_GlobalEventHandler = Handler;
|
||||
AcpiGbl_GlobalEventHandlerContext = Context;
|
||||
|
||||
|
||||
Cleanup:
|
||||
(void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
|
||||
return_ACPI_STATUS (Status);
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL (AcpiInstallGlobalEventHandler)
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: AcpiInstallFixedEventHandler
|
||||
@ -691,11 +751,11 @@ AcpiInstallGpeHandler (
|
||||
ACPI_HANDLE GpeDevice,
|
||||
UINT32 GpeNumber,
|
||||
UINT32 Type,
|
||||
ACPI_EVENT_HANDLER Address,
|
||||
ACPI_GPE_HANDLER Address,
|
||||
void *Context)
|
||||
{
|
||||
ACPI_GPE_EVENT_INFO *GpeEventInfo;
|
||||
ACPI_HANDLER_INFO *Handler;
|
||||
ACPI_GPE_HANDLER_INFO *Handler;
|
||||
ACPI_STATUS Status;
|
||||
ACPI_CPU_FLAGS Flags;
|
||||
|
||||
@ -716,13 +776,24 @@ AcpiInstallGpeHandler (
|
||||
return_ACPI_STATUS (Status);
|
||||
}
|
||||
|
||||
/* Allocate and init handler object (before lock) */
|
||||
|
||||
Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_HANDLER_INFO));
|
||||
if (!Handler)
|
||||
{
|
||||
Status = AE_NO_MEMORY;
|
||||
goto UnlockAndExit;
|
||||
}
|
||||
|
||||
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
|
||||
|
||||
/* Ensure that we have a valid GPE number */
|
||||
|
||||
GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
|
||||
if (!GpeEventInfo)
|
||||
{
|
||||
Status = AE_BAD_PARAMETER;
|
||||
goto UnlockAndExit;
|
||||
goto FreeAndExit;
|
||||
}
|
||||
|
||||
/* Make sure that there isn't a handler there already */
|
||||
@ -731,28 +802,40 @@ AcpiInstallGpeHandler (
|
||||
ACPI_GPE_DISPATCH_HANDLER)
|
||||
{
|
||||
Status = AE_ALREADY_EXISTS;
|
||||
goto UnlockAndExit;
|
||||
goto FreeAndExit;
|
||||
}
|
||||
|
||||
/* 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->Address = Address;
|
||||
Handler->Context = Context;
|
||||
Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode;
|
||||
Handler->OriginalFlags = (UINT8) (GpeEventInfo->Flags &
|
||||
(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK));
|
||||
|
||||
/*
|
||||
* If the GPE is associated with a method, it may have been enabled
|
||||
* automatically during initialization, in which case it has to be
|
||||
* disabled now to avoid spurious execution of the handler.
|
||||
*/
|
||||
if (((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) ||
|
||||
(Handler->OriginalFlags & ACPI_GPE_DISPATCH_NOTIFY)) &&
|
||||
GpeEventInfo->RuntimeCount)
|
||||
{
|
||||
Handler->OriginallyEnabled = TRUE;
|
||||
(void) AcpiEvRemoveGpeReference (GpeEventInfo);
|
||||
|
||||
/* Sanity check of original type against new type */
|
||||
|
||||
if (Type != (UINT32) (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK))
|
||||
{
|
||||
ACPI_WARNING ((AE_INFO, "GPE type mismatch (level/edge)"));
|
||||
}
|
||||
}
|
||||
|
||||
/* Install the handler */
|
||||
|
||||
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
|
||||
GpeEventInfo->Dispatch.Handler = Handler;
|
||||
|
||||
/* Setup up dispatch flags to indicate handler (vs. method) */
|
||||
/* Setup up dispatch flags to indicate handler (vs. method/notify) */
|
||||
|
||||
GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
|
||||
GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_HANDLER);
|
||||
@ -763,6 +846,11 @@ AcpiInstallGpeHandler (
|
||||
UnlockAndExit:
|
||||
(void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
|
||||
return_ACPI_STATUS (Status);
|
||||
|
||||
FreeAndExit:
|
||||
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
|
||||
ACPI_FREE (Handler);
|
||||
goto UnlockAndExit;
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler)
|
||||
@ -787,10 +875,10 @@ ACPI_STATUS
|
||||
AcpiRemoveGpeHandler (
|
||||
ACPI_HANDLE GpeDevice,
|
||||
UINT32 GpeNumber,
|
||||
ACPI_EVENT_HANDLER Address)
|
||||
ACPI_GPE_HANDLER Address)
|
||||
{
|
||||
ACPI_GPE_EVENT_INFO *GpeEventInfo;
|
||||
ACPI_HANDLER_INFO *Handler;
|
||||
ACPI_GPE_HANDLER_INFO *Handler;
|
||||
ACPI_STATUS Status;
|
||||
ACPI_CPU_FLAGS Flags;
|
||||
|
||||
@ -811,6 +899,8 @@ AcpiRemoveGpeHandler (
|
||||
return_ACPI_STATUS (Status);
|
||||
}
|
||||
|
||||
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
|
||||
|
||||
/* Ensure that we have a valid GPE number */
|
||||
|
||||
GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
|
||||
@ -839,18 +929,25 @@ AcpiRemoveGpeHandler (
|
||||
|
||||
/* 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_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK);
|
||||
GpeEventInfo->Flags |= Handler->OriginalFlags;
|
||||
|
||||
/*
|
||||
* If the GPE was previously associated with a method and it was
|
||||
* enabled, it should be enabled at this point to restore the
|
||||
* post-initialization configuration.
|
||||
*/
|
||||
if ((Handler->OriginalFlags & ACPI_GPE_DISPATCH_METHOD) &&
|
||||
Handler->OriginallyEnabled)
|
||||
{
|
||||
GpeEventInfo->Flags |= ACPI_GPE_DISPATCH_METHOD;
|
||||
(void) AcpiEvAddGpeReference (GpeEventInfo);
|
||||
}
|
||||
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
|
||||
|
||||
/* Now we can free the handler object */
|
||||
|
||||
@ -858,6 +955,7 @@ AcpiRemoveGpeHandler (
|
||||
|
||||
|
||||
UnlockAndExit:
|
||||
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
|
||||
(void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
|
||||
return_ACPI_STATUS (Status);
|
||||
}
|
||||
|
@ -118,21 +118,11 @@
|
||||
|
||||
#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);
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
@ -305,292 +295,11 @@ AcpiEnableEvent (
|
||||
ACPI_EXPORT_SYMBOL (AcpiEnableEvent)
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: AcpiGpeWakeup
|
||||
*
|
||||
* PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
|
||||
* GpeNumber - GPE level within the GPE block
|
||||
* Action - Enable or Disable
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Set or clear the GPE's wakeup enable mask bit.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiGpeWakeup (
|
||||
ACPI_HANDLE GpeDevice,
|
||||
UINT32 GpeNumber,
|
||||
UINT8 Action)
|
||||
{
|
||||
ACPI_STATUS Status = AE_OK;
|
||||
ACPI_GPE_EVENT_INFO *GpeEventInfo;
|
||||
ACPI_GPE_REGISTER_INFO *GpeRegisterInfo;
|
||||
ACPI_CPU_FLAGS Flags;
|
||||
UINT32 RegisterBit;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE (AcpiGpeWakeup);
|
||||
|
||||
|
||||
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
|
||||
|
||||
/* Ensure that we have a valid GPE number */
|
||||
|
||||
GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
|
||||
if (!GpeEventInfo)
|
||||
{
|
||||
Status = AE_BAD_PARAMETER;
|
||||
goto UnlockAndExit;
|
||||
}
|
||||
|
||||
GpeRegisterInfo = GpeEventInfo->RegisterInfo;
|
||||
if (!GpeRegisterInfo)
|
||||
{
|
||||
Status = AE_NOT_EXIST;
|
||||
goto UnlockAndExit;
|
||||
}
|
||||
|
||||
RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo);
|
||||
|
||||
/* Perform the action */
|
||||
|
||||
switch (Action)
|
||||
{
|
||||
case ACPI_GPE_ENABLE:
|
||||
ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
|
||||
break;
|
||||
|
||||
case ACPI_GPE_DISABLE:
|
||||
ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
|
||||
break;
|
||||
|
||||
default:
|
||||
ACPI_ERROR ((AE_INFO, "%u, Invalid action", Action));
|
||||
Status = AE_BAD_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
UnlockAndExit:
|
||||
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
|
||||
return_ACPI_STATUS (Status);
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL (AcpiGpeWakeup)
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: AcpiEnableGpe
|
||||
*
|
||||
* PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
|
||||
* GpeNumber - GPE level within the GPE block
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
|
||||
* hardware-enabled.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiEnableGpe (
|
||||
ACPI_HANDLE GpeDevice,
|
||||
UINT32 GpeNumber)
|
||||
{
|
||||
ACPI_STATUS Status = AE_OK;
|
||||
ACPI_GPE_EVENT_INFO *GpeEventInfo;
|
||||
ACPI_CPU_FLAGS Flags;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE (AcpiEnableGpe);
|
||||
|
||||
|
||||
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 (GpeEventInfo->RuntimeCount == ACPI_UINT8_MAX)
|
||||
{
|
||||
Status = AE_LIMIT; /* Too many references */
|
||||
goto UnlockAndExit;
|
||||
}
|
||||
|
||||
GpeEventInfo->RuntimeCount++;
|
||||
if (GpeEventInfo->RuntimeCount == 1)
|
||||
{
|
||||
Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo);
|
||||
if (ACPI_SUCCESS (Status))
|
||||
{
|
||||
Status = AcpiEvEnableGpe (GpeEventInfo);
|
||||
}
|
||||
if (ACPI_FAILURE (Status))
|
||||
{
|
||||
GpeEventInfo->RuntimeCount--;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
ACPI_STATUS Status = AE_OK;
|
||||
ACPI_GPE_EVENT_INFO *GpeEventInfo;
|
||||
ACPI_CPU_FLAGS Flags;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE (AcpiDisableGpe);
|
||||
|
||||
|
||||
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 (!GpeEventInfo->RuntimeCount)
|
||||
{
|
||||
Status = AE_LIMIT; /* There are no references to remove */
|
||||
goto UnlockAndExit;
|
||||
}
|
||||
|
||||
GpeEventInfo->RuntimeCount--;
|
||||
if (!GpeEventInfo->RuntimeCount)
|
||||
{
|
||||
Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo);
|
||||
if (ACPI_SUCCESS (Status))
|
||||
{
|
||||
Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
|
||||
}
|
||||
if (ACPI_FAILURE (Status))
|
||||
{
|
||||
GpeEventInfo->RuntimeCount++;
|
||||
}
|
||||
}
|
||||
|
||||
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 = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
|
||||
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
|
||||
* PARAMETERS: Event - The fixed event to be disabled
|
||||
* Flags - Reserved
|
||||
*
|
||||
* RETURN: Status
|
||||
@ -693,53 +402,6 @@ AcpiClearEvent (
|
||||
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
|
||||
@ -788,400 +450,3 @@ AcpiGetEventStatus (
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
|
962
source/components/events/evxfgpe.c
Normal file
962
source/components/events/evxfgpe.c
Normal file
@ -0,0 +1,962 @@
|
||||
/******************************************************************************
|
||||
*
|
||||
* Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs)
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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 __EVXFGPE_C__
|
||||
|
||||
#include "acpi.h"
|
||||
#include "accommon.h"
|
||||
#include "acevents.h"
|
||||
#include "acnamesp.h"
|
||||
|
||||
#define _COMPONENT ACPI_EVENTS
|
||||
ACPI_MODULE_NAME ("evxfgpe")
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: AcpiUpdateAllGpes
|
||||
*
|
||||
* PARAMETERS: None
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Complete GPE initialization and enable all GPEs that have
|
||||
* associated _Lxx or _Exx methods and are not pointed to by any
|
||||
* device _PRW methods (this indicates that these GPEs are
|
||||
* generally intended for system or device wakeup. Such GPEs
|
||||
* have to be enabled directly when the devices whose _PRW
|
||||
* methods point to them are set up for wakeup signaling.)
|
||||
*
|
||||
* NOTE: Should be called after any GPEs are added to the system. Primarily,
|
||||
* after the system _PRW methods have been run, but also after a GPE Block
|
||||
* Device has been added or if any new GPE methods have been added via a
|
||||
* dynamic table load.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiUpdateAllGpes (
|
||||
void)
|
||||
{
|
||||
ACPI_STATUS Status;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE (AcpiUpdateGpes);
|
||||
|
||||
|
||||
Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
|
||||
if (ACPI_FAILURE (Status))
|
||||
{
|
||||
return_ACPI_STATUS (Status);
|
||||
}
|
||||
|
||||
if (AcpiGbl_AllGpesInitialized)
|
||||
{
|
||||
goto UnlockAndExit;
|
||||
}
|
||||
|
||||
Status = AcpiEvWalkGpeList (AcpiEvInitializeGpeBlock, NULL);
|
||||
if (ACPI_SUCCESS (Status))
|
||||
{
|
||||
AcpiGbl_AllGpesInitialized = TRUE;
|
||||
}
|
||||
|
||||
UnlockAndExit:
|
||||
(void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
|
||||
return_ACPI_STATUS (Status);
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL (AcpiUpdateAllGpes)
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: AcpiEnableGpe
|
||||
*
|
||||
* PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
|
||||
* GpeNumber - GPE level within the GPE block
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
|
||||
* hardware-enabled.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiEnableGpe (
|
||||
ACPI_HANDLE GpeDevice,
|
||||
UINT32 GpeNumber)
|
||||
{
|
||||
ACPI_STATUS Status = AE_BAD_PARAMETER;
|
||||
ACPI_GPE_EVENT_INFO *GpeEventInfo;
|
||||
ACPI_CPU_FLAGS Flags;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE (AcpiEnableGpe);
|
||||
|
||||
|
||||
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
|
||||
|
||||
/* Ensure that we have a valid GPE number */
|
||||
|
||||
GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
|
||||
if (GpeEventInfo)
|
||||
{
|
||||
Status = AcpiEvAddGpeReference (GpeEventInfo);
|
||||
}
|
||||
|
||||
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
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
ACPI_STATUS Status = AE_BAD_PARAMETER;
|
||||
ACPI_GPE_EVENT_INFO *GpeEventInfo;
|
||||
ACPI_CPU_FLAGS Flags;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE (AcpiDisableGpe);
|
||||
|
||||
|
||||
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
|
||||
|
||||
/* Ensure that we have a valid GPE number */
|
||||
|
||||
GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
|
||||
if (GpeEventInfo)
|
||||
{
|
||||
Status = AcpiEvRemoveGpeReference (GpeEventInfo);
|
||||
}
|
||||
|
||||
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 = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE);
|
||||
break;
|
||||
|
||||
default:
|
||||
Status = AE_BAD_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
UnlockAndExit:
|
||||
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
|
||||
return_ACPI_STATUS (Status);
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL (AcpiSetGpe)
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: AcpiSetupGpeForWake
|
||||
*
|
||||
* PARAMETERS: WakeDevice - Device associated with the GPE (via _PRW)
|
||||
* GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
|
||||
* GpeNumber - GPE level within the GPE block
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Mark a GPE as having the ability to wake the system. This
|
||||
* interface is intended to be used as the host executes the
|
||||
* _PRW methods (Power Resources for Wake) in the system tables.
|
||||
* Each _PRW appears under a Device Object (The WakeDevice), and
|
||||
* contains the info for the wake GPE associated with the
|
||||
* WakeDevice.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiSetupGpeForWake (
|
||||
ACPI_HANDLE WakeDevice,
|
||||
ACPI_HANDLE GpeDevice,
|
||||
UINT32 GpeNumber)
|
||||
{
|
||||
ACPI_STATUS Status = AE_BAD_PARAMETER;
|
||||
ACPI_GPE_EVENT_INFO *GpeEventInfo;
|
||||
ACPI_NAMESPACE_NODE *DeviceNode;
|
||||
ACPI_CPU_FLAGS Flags;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE (AcpiSetupGpeForWake);
|
||||
|
||||
|
||||
/* Parameter Validation */
|
||||
|
||||
if (!WakeDevice)
|
||||
{
|
||||
/*
|
||||
* By forcing WakeDevice to be valid, we automatically enable the
|
||||
* implicit notify feature on all hosts.
|
||||
*/
|
||||
return_ACPI_STATUS (AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
/* Validate WakeDevice is of type Device */
|
||||
|
||||
DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, WakeDevice);
|
||||
if (DeviceNode->Type != ACPI_TYPE_DEVICE)
|
||||
{
|
||||
return_ACPI_STATUS (AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
|
||||
|
||||
/* Ensure that we have a valid GPE number */
|
||||
|
||||
GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
|
||||
if (GpeEventInfo)
|
||||
{
|
||||
/*
|
||||
* If there is no method or handler for this GPE, then the
|
||||
* WakeDevice will be notified whenever this GPE fires (aka
|
||||
* "implicit notify") Note: The GPE is assumed to be
|
||||
* level-triggered (for windows compatibility).
|
||||
*/
|
||||
if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) ==
|
||||
ACPI_GPE_DISPATCH_NONE)
|
||||
{
|
||||
GpeEventInfo->Flags =
|
||||
(ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED);
|
||||
GpeEventInfo->Dispatch.DeviceNode = DeviceNode;
|
||||
}
|
||||
|
||||
GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE;
|
||||
Status = AE_OK;
|
||||
}
|
||||
|
||||
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
|
||||
return_ACPI_STATUS (Status);
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL (AcpiSetupGpeForWake)
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* FUNCTION: AcpiSetGpeWakeMask
|
||||
*
|
||||
* PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1
|
||||
* GpeNumber - GPE level within the GPE block
|
||||
* Action - Enable or Disable
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must
|
||||
* already be marked as a WAKE GPE.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiSetGpeWakeMask (
|
||||
ACPI_HANDLE GpeDevice,
|
||||
UINT32 GpeNumber,
|
||||
UINT8 Action)
|
||||
{
|
||||
ACPI_STATUS Status = AE_OK;
|
||||
ACPI_GPE_EVENT_INFO *GpeEventInfo;
|
||||
ACPI_GPE_REGISTER_INFO *GpeRegisterInfo;
|
||||
ACPI_CPU_FLAGS Flags;
|
||||
UINT32 RegisterBit;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE (AcpiSetGpeWakeMask);
|
||||
|
||||
|
||||
Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
|
||||
|
||||
/*
|
||||
* Ensure that we have a valid GPE number and that this GPE is in
|
||||
* fact a wake GPE
|
||||
*/
|
||||
GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber);
|
||||
if (!GpeEventInfo)
|
||||
{
|
||||
Status = AE_BAD_PARAMETER;
|
||||
goto UnlockAndExit;
|
||||
}
|
||||
|
||||
if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE))
|
||||
{
|
||||
Status = AE_TYPE;
|
||||
goto UnlockAndExit;
|
||||
}
|
||||
|
||||
GpeRegisterInfo = GpeEventInfo->RegisterInfo;
|
||||
if (!GpeRegisterInfo)
|
||||
{
|
||||
Status = AE_NOT_EXIST;
|
||||
goto UnlockAndExit;
|
||||
}
|
||||
|
||||
RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo);
|
||||
|
||||
/* Perform the action */
|
||||
|
||||
switch (Action)
|
||||
{
|
||||
case ACPI_GPE_ENABLE:
|
||||
ACPI_SET_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
|
||||
break;
|
||||
|
||||
case ACPI_GPE_DISABLE:
|
||||
ACPI_CLEAR_BIT (GpeRegisterInfo->EnableForWake, (UINT8) RegisterBit);
|
||||
break;
|
||||
|
||||
default:
|
||||
ACPI_ERROR ((AE_INFO, "%u, Invalid action", Action));
|
||||
Status = AE_BAD_PARAMETER;
|
||||
break;
|
||||
}
|
||||
|
||||
UnlockAndExit:
|
||||
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
|
||||
return_ACPI_STATUS (Status);
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL (AcpiSetGpeWakeMask)
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* 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: 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 the current status of a GPE (signalled/not_signalled)
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
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: AcpiFinishGpe
|
||||
*
|
||||
* PARAMETERS: GpeDevice - Namespace node for the GPE Block
|
||||
* (NULL for FADT defined GPEs)
|
||||
* GpeNumber - GPE level within the GPE block
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Clear and conditionally reenable a GPE. This completes the GPE
|
||||
* processing. Intended for use by asynchronous host-installed
|
||||
* GPE handlers. The GPE is only reenabled if the EnableForRun bit
|
||||
* is set in the GPE info.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiFinishGpe (
|
||||
ACPI_HANDLE GpeDevice,
|
||||
UINT32 GpeNumber)
|
||||
{
|
||||
ACPI_GPE_EVENT_INFO *GpeEventInfo;
|
||||
ACPI_STATUS Status;
|
||||
ACPI_CPU_FLAGS Flags;
|
||||
|
||||
|
||||
ACPI_FUNCTION_TRACE (AcpiFinishGpe);
|
||||
|
||||
|
||||
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 = AcpiEvFinishGpe (GpeEventInfo);
|
||||
|
||||
UnlockAndExit:
|
||||
AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
|
||||
return_ACPI_STATUS (Status);
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL (AcpiFinishGpe)
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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);
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL (AcpiDisableAllGpes)
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* 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);
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL (AcpiEnableAllRuntimeGpes)
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
*
|
||||
* 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. The GPEs are not
|
||||
* enabled here.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
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;
|
||||
|
||||
|
||||
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)
|
@ -206,8 +206,11 @@ AcpiExAddTable (
|
||||
AcpiNsExecModuleCodeList ();
|
||||
AcpiExEnterInterpreter ();
|
||||
|
||||
/* Update GPEs for any new _PRW or _Lxx/_Exx methods. Ignore errors */
|
||||
|
||||
/*
|
||||
* Update GPEs for any new _Lxx/_Exx methods. Ignore errors. The host is
|
||||
* responsible for discovering any new wake GPEs by running _PRW methods
|
||||
* that may have been loaded by this table.
|
||||
*/
|
||||
Status = AcpiTbGetOwnerId (TableIndex, &OwnerId);
|
||||
if (ACPI_SUCCESS (Status))
|
||||
{
|
||||
|
@ -895,6 +895,7 @@ AcpiUtInitGlobals (
|
||||
|
||||
/* GPE support */
|
||||
|
||||
AcpiGbl_AllGpesInitialized = FALSE;
|
||||
AcpiGbl_GpeXruptListHead = NULL;
|
||||
AcpiGbl_GpeFadtBlocks[0] = NULL;
|
||||
AcpiGbl_GpeFadtBlocks[1] = NULL;
|
||||
@ -908,6 +909,7 @@ AcpiUtInitGlobals (
|
||||
AcpiGbl_InitHandler = NULL;
|
||||
AcpiGbl_TableHandler = NULL;
|
||||
AcpiGbl_InterfaceHandler = NULL;
|
||||
AcpiGbl_GlobalEventHandler = NULL;
|
||||
|
||||
/* Global Lock support */
|
||||
|
||||
|
@ -411,27 +411,6 @@ AcpiInitializeObjects (
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize the GPE blocks defined in the FADT (GPE block 0 and 1).
|
||||
* The runtime GPEs are enabled here.
|
||||
*
|
||||
* This is where the _PRW methods are executed for the GPEs. These
|
||||
* methods can only be executed after the SCI and Global Lock handlers are
|
||||
* installed and initialized.
|
||||
*
|
||||
* GPEs can only be enabled after the _REG, _STA, and _INI methods have
|
||||
* been run. This ensures that all Operation Regions and all Devices have
|
||||
* been initialized and are ready.
|
||||
*/
|
||||
if (!(Flags & ACPI_NO_EVENT_INIT))
|
||||
{
|
||||
Status = AcpiEvInstallFadtGpes ();
|
||||
if (ACPI_FAILURE (Status))
|
||||
{
|
||||
return (Status);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Empty the caches (delete the cached objects) on the assumption that
|
||||
* the table load filled them up more than they will be at runtime --
|
||||
|
@ -128,10 +128,6 @@ ACPI_STATUS
|
||||
AcpiEvInstallXruptHandlers (
|
||||
void);
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiEvInstallFadtGpes (
|
||||
void);
|
||||
|
||||
UINT32
|
||||
AcpiEvFixedEventDetect (
|
||||
void);
|
||||
@ -181,6 +177,14 @@ ACPI_STATUS
|
||||
AcpiEvEnableGpe (
|
||||
ACPI_GPE_EVENT_INFO *GpeEventInfo);
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiEvAddGpeReference (
|
||||
ACPI_GPE_EVENT_INFO *GpeEventInfo);
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiEvRemoveGpeReference (
|
||||
ACPI_GPE_EVENT_INFO *GpeEventInfo);
|
||||
|
||||
ACPI_GPE_EVENT_INFO *
|
||||
AcpiEvGetGpeEventInfo (
|
||||
ACPI_HANDLE GpeDevice,
|
||||
@ -191,6 +195,10 @@ AcpiEvLowGetGpeInfo (
|
||||
UINT32 GpeNumber,
|
||||
ACPI_GPE_BLOCK_INFO *GpeBlock);
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiEvFinishGpe (
|
||||
ACPI_GPE_EVENT_INFO *GpeEventInfo);
|
||||
|
||||
|
||||
/*
|
||||
* evgpeblk - Upper-level GPE block support
|
||||
@ -206,8 +214,9 @@ AcpiEvCreateGpeBlock (
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiEvInitializeGpeBlock (
|
||||
ACPI_NAMESPACE_NODE *GpeDevice,
|
||||
ACPI_GPE_BLOCK_INFO *GpeBlock);
|
||||
ACPI_GPE_XRUPT_INFO *GpeXruptInfo,
|
||||
ACPI_GPE_BLOCK_INFO *GpeBlock,
|
||||
void *Context);
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiEvDeleteGpeBlock (
|
||||
@ -215,6 +224,7 @@ AcpiEvDeleteGpeBlock (
|
||||
|
||||
UINT32
|
||||
AcpiEvGpeDispatch (
|
||||
ACPI_NAMESPACE_NODE *GpeDevice,
|
||||
ACPI_GPE_EVENT_INFO *GpeEventInfo,
|
||||
UINT32 GpeNumber);
|
||||
|
||||
@ -236,13 +246,6 @@ AcpiEvMatchGpeMethod (
|
||||
void *Context,
|
||||
void **ReturnValue);
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiEvMatchPrwAndGpe (
|
||||
ACPI_HANDLE ObjHandle,
|
||||
UINT32 Level,
|
||||
void *Context,
|
||||
void **ReturnValue);
|
||||
|
||||
/*
|
||||
* evgpeutil - GPE utilities
|
||||
*/
|
||||
@ -255,6 +258,12 @@ BOOLEAN
|
||||
AcpiEvValidGpeEvent (
|
||||
ACPI_GPE_EVENT_INFO *GpeEventInfo);
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiEvGetGpeDevice (
|
||||
ACPI_GPE_XRUPT_INFO *GpeXruptInfo,
|
||||
ACPI_GPE_BLOCK_INFO *GpeBlock,
|
||||
void *Context);
|
||||
|
||||
ACPI_GPE_XRUPT_INFO *
|
||||
AcpiEvGetGpeXruptBlock (
|
||||
UINT32 InterruptNumber);
|
||||
|
@ -173,13 +173,6 @@ UINT8 ACPI_INIT_GLOBAL (AcpiGbl_AllMethodsSerialized, FALSE);
|
||||
*/
|
||||
UINT8 ACPI_INIT_GLOBAL (AcpiGbl_CreateOsiMethod, TRUE);
|
||||
|
||||
/*
|
||||
* Disable wakeup GPEs during runtime? Default is TRUE because WAKE and
|
||||
* RUNTIME GPEs should never be shared, and WAKE GPEs should typically only
|
||||
* be enabled just before going to sleep.
|
||||
*/
|
||||
UINT8 ACPI_INIT_GLOBAL (AcpiGbl_LeaveWakeGpesDisabled, TRUE);
|
||||
|
||||
/*
|
||||
* Optionally use default values for the ACPI register widths. Set this to
|
||||
* TRUE to use the defaults, if an FADT contains incorrect widths/lengths.
|
||||
@ -434,10 +427,13 @@ ACPI_EXTERN UINT8 AcpiGbl_SleepTypeB;
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
extern ACPI_FIXED_EVENT_INFO AcpiGbl_FixedEventInfo[ACPI_NUM_FIXED_EVENTS];
|
||||
ACPI_EXTERN ACPI_FIXED_EVENT_HANDLER AcpiGbl_FixedEventHandlers[ACPI_NUM_FIXED_EVENTS];
|
||||
ACPI_EXTERN UINT8 AcpiGbl_AllGpesInitialized;
|
||||
ACPI_EXTERN ACPI_GPE_XRUPT_INFO *AcpiGbl_GpeXruptListHead;
|
||||
ACPI_EXTERN ACPI_GPE_BLOCK_INFO *AcpiGbl_GpeFadtBlocks[ACPI_MAX_GPE_BLOCKS];
|
||||
ACPI_EXTERN ACPI_GBL_EVENT_HANDLER AcpiGbl_GlobalEventHandler;
|
||||
ACPI_EXTERN void *AcpiGbl_GlobalEventHandlerContext;
|
||||
ACPI_EXTERN ACPI_FIXED_EVENT_HANDLER AcpiGbl_FixedEventHandlers[ACPI_NUM_FIXED_EVENTS];
|
||||
extern ACPI_FIXED_EVENT_INFO AcpiGbl_FixedEventInfo[ACPI_NUM_FIXED_EVENTS];
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
|
@ -537,18 +537,25 @@ typedef struct acpi_predefined_data
|
||||
|
||||
/* Dispatch info for each GPE -- either a method or handler, cannot be both */
|
||||
|
||||
typedef struct acpi_handler_info
|
||||
typedef struct acpi_gpe_handler_info
|
||||
{
|
||||
ACPI_EVENT_HANDLER Address; /* Address of handler, if any */
|
||||
ACPI_GPE_HANDLER Address; /* Address of handler, if any */
|
||||
void *Context; /* Context to be passed to handler */
|
||||
ACPI_NAMESPACE_NODE *MethodNode; /* Method node for this GPE level (saved) */
|
||||
UINT8 OriginalFlags; /* Original (pre-handler) GPE info */
|
||||
BOOLEAN OriginallyEnabled; /* True if GPE was originally enabled */
|
||||
|
||||
} ACPI_HANDLER_INFO;
|
||||
} ACPI_GPE_HANDLER_INFO;
|
||||
|
||||
/*
|
||||
* GPE dispatch info. At any time, the GPE can have at most one type
|
||||
* of dispatch - Method, Handler, or Implicit Notify.
|
||||
*/
|
||||
typedef union acpi_gpe_dispatch_info
|
||||
{
|
||||
ACPI_NAMESPACE_NODE *MethodNode; /* Method node for this GPE level */
|
||||
struct acpi_handler_info *Handler;
|
||||
struct acpi_gpe_handler_info *Handler; /* Installed GPE handler */
|
||||
ACPI_NAMESPACE_NODE *DeviceNode; /* Parent _PRW device for implicit notify */
|
||||
|
||||
} ACPI_GPE_DISPATCH_INFO;
|
||||
|
||||
@ -594,6 +601,7 @@ typedef struct acpi_gpe_block_info
|
||||
UINT32 RegisterCount; /* Number of register pairs in block */
|
||||
UINT16 GpeCount; /* Number of individual GPEs in block */
|
||||
UINT8 BlockBaseNumber;/* Base GPE number for this block */
|
||||
BOOLEAN Initialized; /* TRUE if this block is initialized */
|
||||
|
||||
} ACPI_GPE_BLOCK_INFO;
|
||||
|
||||
@ -614,7 +622,6 @@ typedef struct acpi_gpe_walk_info
|
||||
ACPI_GPE_BLOCK_INFO *GpeBlock;
|
||||
UINT16 Count;
|
||||
ACPI_OWNER_ID OwnerId;
|
||||
BOOLEAN EnableThisGpe;
|
||||
BOOLEAN ExecuteByOwnerId;
|
||||
|
||||
} ACPI_GPE_WALK_INFO;
|
||||
|
@ -142,7 +142,6 @@ extern UINT32 AcpiDbgLayer;
|
||||
extern UINT8 AcpiGbl_EnableInterpreterSlack;
|
||||
extern UINT8 AcpiGbl_AllMethodsSerialized;
|
||||
extern UINT8 AcpiGbl_CreateOsiMethod;
|
||||
extern UINT8 AcpiGbl_LeaveWakeGpesDisabled;
|
||||
extern UINT8 AcpiGbl_UseDefaultRegisterWidths;
|
||||
extern ACPI_NAME AcpiGbl_TraceMethodName;
|
||||
extern UINT32 AcpiGbl_TraceFlags;
|
||||
@ -152,7 +151,7 @@ extern UINT8 AcpiGbl_TruncateIoAddresses;
|
||||
|
||||
|
||||
/*
|
||||
* Global interfaces
|
||||
* Initialization
|
||||
*/
|
||||
ACPI_STATUS
|
||||
AcpiInitializeTables (
|
||||
@ -176,10 +175,10 @@ ACPI_STATUS
|
||||
AcpiTerminate (
|
||||
void);
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiSubsystemStatus (
|
||||
void);
|
||||
|
||||
/*
|
||||
* Miscellaneous global interfaces
|
||||
*/
|
||||
ACPI_STATUS
|
||||
AcpiEnable (
|
||||
void);
|
||||
@ -188,6 +187,10 @@ ACPI_STATUS
|
||||
AcpiDisable (
|
||||
void);
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiSubsystemStatus (
|
||||
void);
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiGetSystemInfo (
|
||||
ACPI_BUFFER *RetBuffer);
|
||||
@ -212,6 +215,7 @@ ACPI_STATUS
|
||||
AcpiRemoveInterface (
|
||||
ACPI_STRING InterfaceName);
|
||||
|
||||
|
||||
/*
|
||||
* ACPI Memory management
|
||||
*/
|
||||
@ -380,6 +384,11 @@ AcpiInstallInitializationHandler (
|
||||
ACPI_INIT_HANDLER Handler,
|
||||
UINT32 Function);
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiInstallGlobalEventHandler (
|
||||
ACPI_GBL_EVENT_HANDLER Handler,
|
||||
void *Context);
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiInstallFixedEventHandler (
|
||||
UINT32 AcpiEvent,
|
||||
@ -391,6 +400,20 @@ AcpiRemoveFixedEventHandler (
|
||||
UINT32 AcpiEvent,
|
||||
ACPI_EVENT_HANDLER Handler);
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiInstallGpeHandler (
|
||||
ACPI_HANDLE GpeDevice,
|
||||
UINT32 GpeNumber,
|
||||
UINT32 Type,
|
||||
ACPI_GPE_HANDLER Address,
|
||||
void *Context);
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiRemoveGpeHandler (
|
||||
ACPI_HANDLE GpeDevice,
|
||||
UINT32 GpeNumber,
|
||||
ACPI_GPE_HANDLER Address);
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiInstallNotifyHandler (
|
||||
ACPI_HANDLE Device,
|
||||
@ -418,20 +441,6 @@ AcpiRemoveAddressSpaceHandler (
|
||||
ACPI_ADR_SPACE_TYPE SpaceId,
|
||||
ACPI_ADR_SPACE_HANDLER Handler);
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiInstallGpeHandler (
|
||||
ACPI_HANDLE GpeDevice,
|
||||
UINT32 GpeNumber,
|
||||
UINT32 Type,
|
||||
ACPI_EVENT_HANDLER Address,
|
||||
void *Context);
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiRemoveGpeHandler (
|
||||
ACPI_HANDLE GpeDevice,
|
||||
UINT32 GpeNumber,
|
||||
ACPI_EVENT_HANDLER Address);
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiInstallExceptionHandler (
|
||||
ACPI_EXCEPTION_HANDLER Handler);
|
||||
@ -442,7 +451,7 @@ AcpiInstallInterfaceHandler (
|
||||
|
||||
|
||||
/*
|
||||
* Event interfaces
|
||||
* Global Lock interfaces
|
||||
*/
|
||||
ACPI_STATUS
|
||||
AcpiAcquireGlobalLock (
|
||||
@ -453,6 +462,10 @@ ACPI_STATUS
|
||||
AcpiReleaseGlobalLock (
|
||||
UINT32 Handle);
|
||||
|
||||
|
||||
/*
|
||||
* Fixed Event interfaces
|
||||
*/
|
||||
ACPI_STATUS
|
||||
AcpiEnableEvent (
|
||||
UINT32 Event,
|
||||
@ -474,13 +487,11 @@ AcpiGetEventStatus (
|
||||
|
||||
|
||||
/*
|
||||
* GPE Interfaces
|
||||
* General Purpose Event (GPE) Interfaces
|
||||
*/
|
||||
ACPI_STATUS
|
||||
AcpiSetGpe (
|
||||
ACPI_HANDLE GpeDevice,
|
||||
UINT32 GpeNumber,
|
||||
UINT8 Action);
|
||||
AcpiUpdateAllGpes (
|
||||
void);
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiEnableGpe (
|
||||
@ -498,7 +509,24 @@ AcpiClearGpe (
|
||||
UINT32 GpeNumber);
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiGpeWakeup (
|
||||
AcpiSetGpe (
|
||||
ACPI_HANDLE GpeDevice,
|
||||
UINT32 GpeNumber,
|
||||
UINT8 Action);
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiFinishGpe (
|
||||
ACPI_HANDLE GpeDevice,
|
||||
UINT32 GpeNumber);
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiSetupGpeForWake (
|
||||
ACPI_HANDLE ParentDevice,
|
||||
ACPI_HANDLE GpeDevice,
|
||||
UINT32 GpeNumber);
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiSetGpeWakeMask (
|
||||
ACPI_HANDLE GpeDevice,
|
||||
UINT32 GpeNumber,
|
||||
UINT8 Action);
|
||||
|
@ -738,25 +738,26 @@ typedef UINT32 ACPI_EVENT_STATUS;
|
||||
|
||||
/*
|
||||
* GPE info flags - Per GPE
|
||||
* +-------+---+-+-+
|
||||
* | 7:4 |3:2|1|0|
|
||||
* +-------+---+-+-+
|
||||
* | | | |
|
||||
* | | | +--- Interrupt type: edge or level triggered
|
||||
* | | +----- GPE can wake the system
|
||||
* | +-------- Type of dispatch:to method, handler, or none
|
||||
* +-------------- <Reserved>
|
||||
* +-------+-+-+---+
|
||||
* | 7:4 |3|2|1:0|
|
||||
* +-------+-+-+---+
|
||||
* | | | |
|
||||
* | | | +-- Type of dispatch:to method, handler, notify, or none
|
||||
* | | +----- Interrupt type: edge or level triggered
|
||||
* | +------- Is a Wake GPE
|
||||
* +------------ <Reserved>
|
||||
*/
|
||||
#define ACPI_GPE_XRUPT_TYPE_MASK (UINT8) 0x01
|
||||
#define ACPI_GPE_LEVEL_TRIGGERED (UINT8) 0x01
|
||||
#define ACPI_GPE_DISPATCH_NONE (UINT8) 0x00
|
||||
#define ACPI_GPE_DISPATCH_METHOD (UINT8) 0x01
|
||||
#define ACPI_GPE_DISPATCH_HANDLER (UINT8) 0x02
|
||||
#define ACPI_GPE_DISPATCH_NOTIFY (UINT8) 0x03
|
||||
#define ACPI_GPE_DISPATCH_MASK (UINT8) 0x03
|
||||
|
||||
#define ACPI_GPE_LEVEL_TRIGGERED (UINT8) 0x04
|
||||
#define ACPI_GPE_EDGE_TRIGGERED (UINT8) 0x00
|
||||
#define ACPI_GPE_XRUPT_TYPE_MASK (UINT8) 0x04
|
||||
|
||||
#define ACPI_GPE_CAN_WAKE (UINT8) 0x02
|
||||
|
||||
#define ACPI_GPE_DISPATCH_MASK (UINT8) 0x0C
|
||||
#define ACPI_GPE_DISPATCH_HANDLER (UINT8) 0x04
|
||||
#define ACPI_GPE_DISPATCH_METHOD (UINT8) 0x08
|
||||
#define ACPI_GPE_DISPATCH_NOT_USED (UINT8) 0x00
|
||||
#define ACPI_GPE_CAN_WAKE (UINT8) 0x08
|
||||
|
||||
/*
|
||||
* Flags for GPE and Lock interfaces
|
||||
@ -1014,10 +1015,26 @@ typedef void
|
||||
/*
|
||||
* Various handlers and callback procedures
|
||||
*/
|
||||
typedef
|
||||
void (*ACPI_GBL_EVENT_HANDLER) (
|
||||
UINT32 EventType,
|
||||
ACPI_HANDLE Device,
|
||||
UINT32 EventNumber,
|
||||
void *Context);
|
||||
|
||||
#define ACPI_EVENT_TYPE_GPE 0
|
||||
#define ACPI_EVENT_TYPE_FIXED 1
|
||||
|
||||
typedef
|
||||
UINT32 (*ACPI_EVENT_HANDLER) (
|
||||
void *Context);
|
||||
|
||||
typedef
|
||||
UINT32 (*ACPI_GPE_HANDLER) (
|
||||
ACPI_HANDLE GpeDevice,
|
||||
UINT32 GpeNumber,
|
||||
void *Context);
|
||||
|
||||
typedef
|
||||
void (*ACPI_NOTIFY_HANDLER) (
|
||||
ACPI_HANDLE Device,
|
||||
@ -1098,6 +1115,11 @@ UINT32 (*ACPI_INTERFACE_HANDLER) (
|
||||
#define ACPI_INTERRUPT_NOT_HANDLED 0x00
|
||||
#define ACPI_INTERRUPT_HANDLED 0x01
|
||||
|
||||
/* GPE handler return values */
|
||||
|
||||
#define ACPI_REENABLE_GPE 0x80
|
||||
|
||||
|
||||
/* Length of 32-bit EISAID values when converted back to a string */
|
||||
|
||||
#define ACPI_EISAID_STRING_SIZE 8 /* Includes null terminator */
|
||||
|
@ -250,6 +250,15 @@ AeRegionHandler (
|
||||
|
||||
UINT32
|
||||
AeGpeHandler (
|
||||
ACPI_HANDLE GpeDevice,
|
||||
UINT32 GpeNumber,
|
||||
void *Context);
|
||||
|
||||
void
|
||||
AeGlobalEventHandler (
|
||||
UINT32 Type,
|
||||
ACPI_HANDLE GpeDevice,
|
||||
UINT32 EventNumber,
|
||||
void *Context);
|
||||
|
||||
#endif /* _AECOMMON */
|
||||
|
@ -586,6 +586,9 @@ AeMiscellaneousTests (
|
||||
Status = AcpiEnableEvent (ACPI_EVENT_GLOBAL, 0);
|
||||
AE_CHECK_OK (AcpiEnableEvent, Status);
|
||||
|
||||
Status = AcpiInstallGlobalEventHandler (AeGlobalEventHandler, NULL);
|
||||
AE_CHECK_OK (AcpiInstallGlobalEventHandler, Status);
|
||||
|
||||
/*
|
||||
* GPEs: Handlers, enable/disable, etc.
|
||||
*/
|
||||
@ -634,6 +637,20 @@ AeMiscellaneousTests (
|
||||
Status = AcpiInstallGpeHandler (NULL, 5, ACPI_GPE_EDGE_TRIGGERED, AeGpeHandler, NULL);
|
||||
AE_CHECK_OK (AcpiInstallGpeHandler, Status);
|
||||
|
||||
Status = AcpiGetHandle (NULL, "\\_SB", &Handle);
|
||||
AE_CHECK_OK (AcpiGetHandle, Status);
|
||||
|
||||
Status = AcpiSetupGpeForWake (Handle, NULL, 5);
|
||||
AE_CHECK_OK (AcpiSetupGpeForWake, Status);
|
||||
|
||||
Status = AcpiSetGpeWakeMask (NULL, 5, ACPI_GPE_ENABLE);
|
||||
AE_CHECK_OK (AcpiGpeWakeup, Status);
|
||||
|
||||
Status = AcpiSetupGpeForWake (Handle, NULL, 6);
|
||||
AE_CHECK_OK (AcpiSetupGpeForWake, Status);
|
||||
|
||||
Status = AcpiSetupGpeForWake (Handle, NULL, 9);
|
||||
AE_CHECK_OK (AcpiSetupGpeForWake, Status);
|
||||
|
||||
Status = AcpiInstallGpeHandler (NULL, 0x19, ACPI_GPE_LEVEL_TRIGGERED, AeGpeHandler, NULL);
|
||||
AE_CHECK_OK (AcpiInstallGpeHandler, Status);
|
||||
@ -653,6 +670,10 @@ AeMiscellaneousTests (
|
||||
|
||||
AfInstallGpeBlock ();
|
||||
|
||||
/* Here is where the GPEs are actually "enabled" */
|
||||
|
||||
Status = AcpiUpdateAllGpes ();
|
||||
AE_CHECK_OK (AcpiUpdateAllGpes, Status);
|
||||
|
||||
Status = AcpiGetHandle (NULL, "RSRC", &Handle);
|
||||
if (ACPI_SUCCESS (Status))
|
||||
|
@ -428,13 +428,18 @@ AeTableHandler (
|
||||
void *Table,
|
||||
void *Context)
|
||||
{
|
||||
ACPI_STATUS Status;
|
||||
|
||||
|
||||
if (Event > ACPI_NUM_TABLE_EVENTS)
|
||||
{
|
||||
Event = ACPI_NUM_TABLE_EVENTS;
|
||||
}
|
||||
|
||||
/* TBD: could dump entire table header, need a header dump routine */
|
||||
/* Enable any GPEs associated with newly-loaded GPE methods */
|
||||
|
||||
Status = AcpiUpdateAllGpes ();
|
||||
AE_CHECK_OK (AcpiUpdateAllGpes, Status);
|
||||
|
||||
printf ("[AcpiExec] Table Event %s, [%4.4s] %p\n",
|
||||
TableEvents[Event], ((ACPI_TABLE_HEADER *) Table)->Signature, Table);
|
||||
@ -446,16 +451,61 @@ AeTableHandler (
|
||||
*
|
||||
* FUNCTION: AeGpeHandler
|
||||
*
|
||||
* DESCRIPTION: GPE handler for acpiexec
|
||||
* DESCRIPTION: Common GPE handler for acpiexec
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
UINT32
|
||||
AeGpeHandler (
|
||||
ACPI_HANDLE GpeDevice,
|
||||
UINT32 GpeNumber,
|
||||
void *Context)
|
||||
{
|
||||
AcpiOsPrintf ("Received a GPE at handler\n");
|
||||
return (0);
|
||||
ACPI_NAMESPACE_NODE *DeviceNode = (ACPI_NAMESPACE_NODE *) GpeDevice;
|
||||
|
||||
|
||||
AcpiOsPrintf ("[AcpiExec] GPE Handler received GPE%02X (GPE block %4.4s)\n",
|
||||
GpeNumber, GpeDevice ? DeviceNode->Name.Ascii : "FADT");
|
||||
|
||||
return (ACPI_REENABLE_GPE);
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: AeGlobalEventHandler
|
||||
*
|
||||
* DESCRIPTION: Global GPE/Fixed event handler
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
void
|
||||
AeGlobalEventHandler (
|
||||
UINT32 Type,
|
||||
ACPI_HANDLE Device,
|
||||
UINT32 EventNumber,
|
||||
void *Context)
|
||||
{
|
||||
char *TypeName;
|
||||
|
||||
|
||||
switch (Type)
|
||||
{
|
||||
case ACPI_EVENT_TYPE_GPE:
|
||||
TypeName = "GPE";
|
||||
break;
|
||||
|
||||
case ACPI_EVENT_TYPE_FIXED:
|
||||
TypeName = "FixedEvent";
|
||||
break;
|
||||
|
||||
default:
|
||||
TypeName = "UNKNOWN";
|
||||
break;
|
||||
}
|
||||
|
||||
AcpiOsPrintf ("[AcpiExec] Global Event Handler received: Type %s Number %.2X Dev %p\n",
|
||||
TypeName, EventNumber, Device);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user