Merge ACPICA 20101209.

This commit is contained in:
Jung-uk Kim 2010-12-15 23:48:45 +00:00
commit 5a77b11bd3
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=216471
36 changed files with 1831 additions and 1385 deletions

View File

@ -195,6 +195,7 @@ contrib/dev/acpica/events/evrgnini.c optional acpi
contrib/dev/acpica/events/evsci.c optional acpi
contrib/dev/acpica/events/evxface.c optional acpi
contrib/dev/acpica/events/evxfevnt.c optional acpi
contrib/dev/acpica/events/evxfgpe.c optional acpi
contrib/dev/acpica/events/evxfregn.c optional acpi
contrib/dev/acpica/executer/exconfig.c optional acpi
contrib/dev/acpica/executer/exconvrt.c optional acpi

View File

@ -1,3 +1,75 @@
----------------------------------------
09 December 2010. Summary of changes for version 20101209:
This release is available at www.acpica.org/downloads
1) ACPI CA Core Subsystem:
Completed the major overhaul of the GPE support code that was begun in July
2010. Major features include: removal of _PRW execution in ACPICA (host
executes _PRWs anyway), cleanup of "wake" GPE interfaces and processing,
changes to existing interfaces, simplification of GPE handler operation, and
a handful of new interfaces:
AcpiUpdateAllGpes
AcpiFinishGpe
AcpiSetupGpeForWake
AcpiSetGpeWakeMask
One new file, evxfgpe.c to consolidate all external GPE interfaces.
See the ACPICA Programmer Reference for full details and programming
information. See the new section 4.4 "General Purpose Event (GPE) Support"
for a full overview, and section 8.7 "ACPI General Purpose Event Management"
for programming details. ACPICA BZ 858,870,877. Matthew Garrett, Lin Ming,
Bob Moore, Rafael Wysocki.
Implemented a new GPE feature for Windows compatibility, the "Implicit Wake
GPE Notify". This feature will automatically issue a Notify(2) on a device
when a Wake GPE is received if there is no corresponding GPE method or
handler. ACPICA BZ 870.
Fixed a problem with the Scope() operator during table parse and load phase.
During load phase (table load or method execution), the scope operator should
not enter the target into the namespace. Instead, it should open a new scope
at the target location. Linux BZ 19462, ACPICA BZ 882.
Example Code and Data Size: These are the sizes for the OS-independent
acpica.lib produced by the Microsoft Visual C++ 6.0 32-bit compiler. The
debug version of the code includes the debug output trace mechanism and has a
much larger code and data size.
Previous Release:
Non-Debug Version: 89.8K Code, 18.9K Data, 108.7K Total
Debug Version: 166.6K Code, 52.1K Data, 218.7K Total
Current Release:
Non-Debug Version: 89.9K Code, 19.0K Data, 108.9K Total
Debug Version: 166.3K Code, 52.1K Data, 218.4K Total
2) iASL Compiler/Disassembler and Tools:
iASL: Relax the alphanumeric restriction on _CID strings. These strings are
"bus-specific" per the ACPI specification, and therefore any characters are
acceptable. The only checks that can be performed are for a null string and
perhaps for a leading asterisk. ACPICA BZ 886.
iASL: Fixed a problem where a syntax error that caused a premature EOF
condition on the source file emitted a very confusing error message. The
premature EOF is now detected correctly. ACPICA BZ 891.
Disassembler: Decode the AccessSize within a Generic Address Structure (byte
access, word access, etc.) Note, this field does not allow arbitrary bit
access, the size is encoded as 1=byte, 2=word, 3=dword, and 4=qword.
New: AcpiNames utility - Example namespace dump utility. Shows an example of
ACPICA configuration for a minimal namespace dump utility. Uses table and
namespace managers, but no AML interpreter. Does not add any functionality
over AcpiExec, it is a subset of AcpiExec. The purpose is to show how to
partition and configure ACPICA. ACPICA BZ 883.
AML Debugger: Increased the debugger buffer size for method return objects.
Was 4K, increased to 16K. Also enhanced error messages for debugger method
execution, including the buffer overflow case.
----------------------------------------
13 October 2010. Summary of changes for version 20101013:

View File

@ -295,6 +295,19 @@ static const char *AcpiDmFadtProfiles[] =
"Unknown Profile Type"
};
#define ACPI_GAS_WIDTH_RESERVED 5
static const char *AcpiDmGasAccessWidth[] =
{
"Undefined/Legacy",
"Byte Access:8",
"Word Access:16",
"DWord Access:32",
"QWord Access:64",
"Unknown Width Encoding"
};
/*******************************************************************************
*
* ACPI Table Data, indexed by signature.
@ -669,6 +682,7 @@ AcpiDmDumpTable (
case ACPI_DMT_UINT8:
case ACPI_DMT_CHKSUM:
case ACPI_DMT_SPACEID:
case ACPI_DMT_ACCWIDTH:
case ACPI_DMT_IVRS:
case ACPI_DMT_MADT:
case ACPI_DMT_SRAT:
@ -884,6 +898,19 @@ AcpiDmDumpTable (
AcpiOsPrintf ("%2.2X (%s)\n", *Target, AcpiUtGetRegionName (*Target));
break;
case ACPI_DMT_ACCWIDTH:
/* Encoded Access Width */
Temp8 = *Target;
if (Temp8 > ACPI_GAS_WIDTH_RESERVED)
{
Temp8 = ACPI_GAS_WIDTH_RESERVED;
}
AcpiOsPrintf ("%2.2X (%s)\n", Temp8, AcpiDmGasAccessWidth[Temp8]);
break;
case ACPI_DMT_GAS:
/* Generic Address Structure */

View File

@ -282,7 +282,7 @@ ACPI_DMTABLE_INFO AcpiDmTableInfoGas[] =
{ACPI_DMT_SPACEID, ACPI_GAS_OFFSET (SpaceId), "Space ID", 0},
{ACPI_DMT_UINT8, ACPI_GAS_OFFSET (BitWidth), "Bit Width", 0},
{ACPI_DMT_UINT8, ACPI_GAS_OFFSET (BitOffset), "Bit Offset", 0},
{ACPI_DMT_UINT8, ACPI_GAS_OFFSET (AccessWidth), "Access Width", 0},
{ACPI_DMT_ACCWIDTH, ACPI_GAS_OFFSET (AccessWidth), "Encoded Access Width", 0},
{ACPI_DMT_UINT64, ACPI_GAS_OFFSET (Address), "Address", 0},
ACPI_DMT_TERMINATOR
};

View File

@ -684,19 +684,45 @@ AnCheckId (
UINT32 AlphaPrefixLength;
/* Only care about string versions of _HID/_CID (integers are legal) */
if (Op->Asl.ParseOpcode != PARSEOP_STRING_LITERAL)
{
return;
}
/* For both _HID and _CID, the string must be non-null */
Length = strlen (Op->Asl.Value.String);
if (!Length)
{
AslError (ASL_ERROR, ASL_MSG_NULL_STRING,
Op, NULL);
return;
}
/*
* If _HID/_CID is a string, all characters must be alphanumeric.
* One of the things we want to catch here is the use of
* a leading asterisk in the string -- an odd construct
* that certain platform manufacturers are fond of.
* One of the things we want to catch here is the use of a leading
* asterisk in the string -- an odd construct that certain platform
* manufacturers are fond of. Technically, a leading asterisk is OK
* for _CID, but a valid use of this has not been seen.
*/
if (*Op->Asl.Value.String == '*')
{
AslError (ASL_ERROR, ASL_MSG_LEADING_ASTERISK,
Op, Op->Asl.Value.String);
return;
}
/* _CID strings are bus-specific, no more checks can be performed */
if (Type == ASL_TYPE_CID)
{
return;
}
/* For _HID, all characters must be alphanumeric */
for (i = 0; Op->Asl.Value.String[i]; i++)
{
if (!isalnum ((int) Op->Asl.Value.String[i]))
@ -707,13 +733,6 @@ AnCheckId (
}
}
if (Type == ASL_TYPE_CID)
{
/* _CID strings are bus-specific, no more checks can be performed */
return;
}
/* _HID String must be of the form "XXX####" or "ACPI####" */
if ((Length < 7) || (Length > 8))

View File

@ -241,6 +241,8 @@ AePrintException (
UINT32 ErrorColumn;
FILE *OutputFile;
FILE *SourceFile;
long FileSize;
BOOLEAN PrematureEOF = FALSE;
if (Gbl_NoErrors)
@ -289,6 +291,19 @@ AePrintException (
SourceFile = Gbl_Files[ASL_FILE_INPUT].Handle;
}
if (SourceFile)
{
/* Determine if the error occurred at source file EOF */
fseek (SourceFile, 0, SEEK_END);
FileSize = ftell (SourceFile);
if ((long) Enode->LogicalByteOffset >= FileSize)
{
PrematureEOF = TRUE;
}
}
if (Header)
{
fprintf (OutputFile, "%s", Header);
@ -307,33 +322,42 @@ AePrintException (
fprintf (OutputFile, " %6u: ", Enode->LineNumber);
/*
* Seek to the offset in the combined source file, read the source
* line, and write it to the output.
* If not at EOF, get the corresponding source code line and
* display it. Don't attempt this if we have a premature EOF
* condition.
*/
Actual = fseek (SourceFile, (long) Enode->LogicalByteOffset,
(int) SEEK_SET);
if (Actual)
if (!PrematureEOF)
{
fprintf (OutputFile,
"[*** iASL: Seek error on source code temp file %s ***]",
Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Filename);
}
else
{
RActual = fread (&SourceByte, 1, 1, SourceFile);
if (!RActual)
/*
* Seek to the offset in the combined source file, read
* the source line, and write it to the output.
*/
Actual = fseek (SourceFile, (long) Enode->LogicalByteOffset,
(int) SEEK_SET);
if (Actual)
{
fprintf (OutputFile,
"[*** iASL: Read error on source code temp file %s ***]",
"[*** iASL: Seek error on source code temp file %s ***]",
Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Filename);
}
else while (RActual && SourceByte && (SourceByte != '\n'))
else
{
fwrite (&SourceByte, 1, 1, OutputFile);
RActual = fread (&SourceByte, 1, 1, SourceFile);
if (!RActual)
{
fprintf (OutputFile,
"[*** iASL: Read error on source code temp file %s ***]",
Gbl_Files[ASL_FILE_SOURCE_OUTPUT].Filename);
}
else while (RActual && SourceByte && (SourceByte != '\n'))
{
fwrite (&SourceByte, 1, 1, OutputFile);
RActual = fread (&SourceByte, 1, 1, SourceFile);
}
}
}
fprintf (OutputFile, "\n");
}
}
@ -376,7 +400,7 @@ AePrintException (
ExtraMessage = NULL;
}
if (Gbl_VerboseErrors)
if (Gbl_VerboseErrors && !PrematureEOF)
{
SourceColumn = Enode->Column + Enode->FilenameLength + 6 + 2;
ErrorColumn = ASL_ERROR_LEVEL_LENGTH + 5 + 2 + 1;
@ -406,6 +430,11 @@ AePrintException (
fprintf (OutputFile, " (%s)", ExtraMessage);
}
if (PrematureEOF)
{
fprintf (OutputFile, " and premature End-Of-File");
}
fprintf (OutputFile, "\n");
if (Gbl_VerboseErrors)
{

View File

@ -258,6 +258,9 @@ typedef enum
ASL_MSG_NULL_DESCRIPTOR,
ASL_MSG_UPPER_CASE,
ASL_MSG_HID_LENGTH,
ASL_MSG_NULL_STRING,
ASL_MSG_LEADING_ASTERISK,
ASL_MSG_INVALID_FIELD_NAME,
ASL_MSG_INTEGER_SIZE,
ASL_MSG_INVALID_HEX_INTEGER,
@ -382,7 +385,7 @@ char *AslMessages [] = {
/* ASL_MSG_VENDOR_LIST */ "Too many vendor data bytes (7 max)",
/* ASL_MSG_WRITE */ "Could not write file",
/* ASL_MSG_MULTIPLE_DEFAULT */ "More than one Default statement within Switch construct",
/* ASL_MSG_TIMEOUT */ "Possible operator timeout is ignored",
/* ASL_MSG_TIMEOUT */ "Result is not used, possible operator timeout will be missed",
/* ASL_MSG_RESULT_NOT_USED */ "Result is not used, operator has no effect",
/* ASL_MSG_NOT_REFERENCED */ "Namespace object is not referenced",
/* ASL_MSG_NON_ZERO */ "Operand evaluates to zero",
@ -403,6 +406,8 @@ char *AslMessages [] = {
/* ASL_MSG_NULL_DESCRIPTOR */ "Min/Max/Length/Gran are all zero, but no resource tag",
/* ASL_MSG_UPPER_CASE */ "Non-hex letters must be upper case",
/* ASL_MSG_HID_LENGTH */ "_HID string must be exactly 7 or 8 characters",
/* ASL_MSG_NULL_STRING */ "Invalid zero-length (null) string",
/* ASL_MSG_LEADING_ASTERISK */ "Invalid leading asterisk",
/* These messages are used by the data table compiler only */

View File

@ -573,6 +573,7 @@ DtGetFieldLength (
case ACPI_DMT_UINT8:
case ACPI_DMT_CHKSUM:
case ACPI_DMT_SPACEID:
case ACPI_DMT_ACCWIDTH:
case ACPI_DMT_IVRS:
case ACPI_DMT_MADT:
case ACPI_DMT_SRAT:

View File

@ -2075,7 +2075,7 @@ AcpiDbGenerateGpe (
return;
}
(void) AcpiEvGpeDispatch (GpeEventInfo, GpeNumber);
(void) AcpiEvGpeDispatch (NULL, GpeEventInfo, GpeNumber);
}

View File

@ -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",

View File

@ -180,6 +180,9 @@ AcpiDbExecuteMethod (
ACPI_DEVICE_INFO *ObjInfo;
ACPI_FUNCTION_TRACE (DbExecuteMethod);
if (AcpiGbl_DbOutputToFile && !AcpiDbgLevel)
{
AcpiOsPrintf ("Warning: debug output is not enabled!\n");
@ -190,7 +193,7 @@ AcpiDbExecuteMethod (
Status = AcpiGetHandle (NULL, Info->Pathname, &Handle);
if (ACPI_FAILURE (Status))
{
return (Status);
return_ACPI_STATUS (Status);
}
/* Get the object info for number of method parameters */
@ -198,7 +201,7 @@ AcpiDbExecuteMethod (
Status = AcpiGetObjectInfo (Handle, &ObjInfo);
if (ACPI_FAILURE (Status))
{
return (Status);
return_ACPI_STATUS (Status);
}
ParamObjects.Pointer = NULL;
@ -269,7 +272,20 @@ AcpiDbExecuteMethod (
AcpiGbl_CmSingleStep = FALSE;
AcpiGbl_MethodExecuting = FALSE;
return (Status);
if (ACPI_FAILURE (Status))
{
ACPI_EXCEPTION ((AE_INFO, Status,
"while executing %s from debugger", Info->Pathname));
if (Status == AE_BUFFER_OVERFLOW)
{
ACPI_ERROR ((AE_INFO,
"Possible overflow of internal debugger buffer (size 0x%X needed 0x%X)",
ACPI_DEBUG_BUFFER_SIZE, (UINT32) ReturnObj->Length));
}
}
return_ACPI_STATUS (Status);
}

View File

@ -400,10 +400,26 @@ AcpiDsExecBeginOp (
* we must enter this object into the namespace. The created
* object is temporary and will be deleted upon completion of
* the execution of this method.
*
* Note 10/2010: Except for the Scope() op. This opcode does
* not actually create a new object, it refers to an existing
* object. However, for Scope(), we want to indeed open a
* new scope.
*/
Status = AcpiDsLoad2BeginOp (WalkState, NULL);
if (Op->Common.AmlOpcode != AML_SCOPE_OP)
{
Status = AcpiDsLoad2BeginOp (WalkState, NULL);
}
else
{
Status = AcpiDsScopeStackPush (Op->Named.Node,
Op->Named.Node->Type, WalkState);
if (ACPI_FAILURE (Status))
{
return_ACPI_STATUS (Status);
}
}
}
break;

View File

@ -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);
}
}

View File

@ -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 @@ AcpiEvAsynchEnableGpe (
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;
}

View File

@ -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 @@ AcpiEvInitializeGpeBlock (
}
}
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);
}

View File

@ -118,12 +118,28 @@
#include <contrib/dev/acpica/include/accommon.h>
#include <contrib/dev/acpica/include/acevents.h>
#include <contrib/dev/acpica/include/acnamesp.h>
#include <contrib/dev/acpica/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 @@ AcpiEvGpeInitialize (
*
* 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);
}

View File

@ -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

View File

@ -175,6 +175,66 @@ AcpiInstallExceptionHandler (
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);
}

View File

@ -118,21 +118,11 @@
#include <contrib/dev/acpica/include/acpi.h>
#include <contrib/dev/acpica/include/accommon.h>
#include <contrib/dev/acpica/include/acevents.h>
#include <contrib/dev/acpica/include/acnamesp.h>
#include <contrib/dev/acpica/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);
}

View 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 <contrib/dev/acpica/include/acpi.h>
#include <contrib/dev/acpica/include/accommon.h>
#include <contrib/dev/acpica/include/acevents.h>
#include <contrib/dev/acpica/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)

View File

@ -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))
{

View File

@ -117,7 +117,7 @@
#define __ACDEBUG_H__
#define ACPI_DEBUG_BUFFER_SIZE 4196
#define ACPI_DEBUG_BUFFER_SIZE 0x4000 /* 16K buffer for return objects */
typedef struct CommandInfo
{

View File

@ -189,6 +189,7 @@ typedef const struct acpi_dmtable_info
#define ACPI_DMT_EINJINST 38
#define ACPI_DMT_ERSTACT 39
#define ACPI_DMT_ERSTINST 40
#define ACPI_DMT_ACCWIDTH 41
typedef

View File

@ -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);

View File

@ -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];
/*****************************************************************************

View File

@ -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;

View File

@ -120,7 +120,7 @@
/* Current ACPICA subsystem version in YYYYMMDD format */
#define ACPI_CA_VERSION 0x20101013
#define ACPI_CA_VERSION 0x20101209
#include <contrib/dev/acpica/include/actypes.h>
#include <contrib/dev/acpica/include/actbl.h>
@ -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);

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 --

View File

@ -664,6 +664,12 @@ acpi_attach(device_t dev)
if (!acpi_disabled("bus"))
acpi_probe_children(dev);
/* Update all GPEs and enable runtime GPEs. */
status = AcpiUpdateAllGpes();
if (ACPI_FAILURE(status))
device_printf(dev, "Could not update all GPEs: %s\n",
AcpiFormatException(status));
/* Allow sleep request after a while. */
timeout(acpi_sleep_enable, sc, hz * ACPI_MINIMUM_AWAKETIME);
@ -1670,6 +1676,7 @@ acpi_probe_order(ACPI_HANDLE handle, int *order)
static ACPI_STATUS
acpi_probe_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status)
{
struct acpi_prw_data prw;
ACPI_OBJECT_TYPE type;
ACPI_HANDLE h;
device_t bus, child;
@ -1699,6 +1706,8 @@ acpi_probe_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status)
if (strcmp(handle_str, "\\_SB_") == 0 ||
strcmp(handle_str, "\\_TZ_") == 0)
break;
if (acpi_parse_prw(handle, &prw) == 0)
AcpiSetupGpeForWake(handle, prw.gpe_handle, prw.gpe_bit);
/* FALLTHROUGH */
case ACPI_TYPE_PROCESSOR:
case ACPI_TYPE_THERMAL:
@ -2597,14 +2606,16 @@ acpi_wake_set_enable(device_t dev, int enable)
flags = acpi_get_flags(dev);
if (enable) {
status = AcpiGpeWakeup(prw.gpe_handle, prw.gpe_bit, ACPI_GPE_ENABLE);
status = AcpiSetGpeWakeMask(prw.gpe_handle, prw.gpe_bit,
ACPI_GPE_ENABLE);
if (ACPI_FAILURE(status)) {
device_printf(dev, "enable wake failed\n");
return (ENXIO);
}
acpi_set_flags(dev, flags | ACPI_FLAG_WAKE_ENABLED);
} else {
status = AcpiGpeWakeup(prw.gpe_handle, prw.gpe_bit, ACPI_GPE_DISABLE);
status = AcpiSetGpeWakeMask(prw.gpe_handle, prw.gpe_bit,
ACPI_GPE_DISABLE);
if (ACPI_FAILURE(status)) {
device_printf(dev, "disable wake failed\n");
return (ENXIO);
@ -2634,7 +2645,7 @@ acpi_wake_sleep_prep(ACPI_HANDLE handle, int sstate)
* and set _PSW.
*/
if (sstate > prw.lowest_wake) {
AcpiGpeWakeup(prw.gpe_handle, prw.gpe_bit, ACPI_GPE_DISABLE);
AcpiSetGpeWakeMask(prw.gpe_handle, prw.gpe_bit, ACPI_GPE_DISABLE);
if (bootverbose)
device_printf(dev, "wake_prep disabled wake for %s (S%d)\n",
acpi_name(handle), sstate);
@ -2671,7 +2682,7 @@ acpi_wake_run_prep(ACPI_HANDLE handle, int sstate)
* clear _PSW and turn off any power resources it used.
*/
if (sstate > prw.lowest_wake) {
AcpiGpeWakeup(prw.gpe_handle, prw.gpe_bit, ACPI_GPE_ENABLE);
AcpiSetGpeWakeMask(prw.gpe_handle, prw.gpe_bit, ACPI_GPE_ENABLE);
if (bootverbose)
device_printf(dev, "run_prep re-enabled %s\n", acpi_name(handle));
} else {

View File

@ -168,7 +168,7 @@ acpi_button_attach(device_t dev)
acpi_wake_set_enable(dev, 1);
if (acpi_parse_prw(sc->button_handle, &prw) == 0)
AcpiEnableGpe(prw.gpe_handle, prw.gpe_bit);
return_VALUE (0);
}

View File

@ -218,7 +218,7 @@ EcUnlock(struct acpi_ec_softc *sc)
AcpiReleaseGlobalLock(sc->ec_glkhandle);
}
static uint32_t EcGpeHandler(void *Context);
static UINT32 EcGpeHandler(ACPI_HANDLE, UINT32, void *);
static ACPI_STATUS EcSpaceSetup(ACPI_HANDLE Region, UINT32 Function,
void *Context, void **return_Context);
static ACPI_STATUS EcSpaceHandler(UINT32 Function,
@ -498,7 +498,7 @@ acpi_ec_attach(device_t dev)
*/
ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES, "attaching GPE handler\n"));
Status = AcpiInstallGpeHandler(sc->ec_gpehandle, sc->ec_gpebit,
ACPI_GPE_EDGE_TRIGGERED, &EcGpeHandler, sc);
ACPI_GPE_EDGE_TRIGGERED, EcGpeHandler, sc);
if (ACPI_FAILURE(Status)) {
device_printf(dev, "can't install GPE handler for %s - %s\n",
acpi_name(sc->ec_handle), AcpiFormatException(Status));
@ -529,7 +529,7 @@ acpi_ec_attach(device_t dev)
return (0);
error:
AcpiRemoveGpeHandler(sc->ec_gpehandle, sc->ec_gpebit, &EcGpeHandler);
AcpiRemoveGpeHandler(sc->ec_gpehandle, sc->ec_gpebit, EcGpeHandler);
AcpiRemoveAddressSpaceHandler(sc->ec_handle, ACPI_ADR_SPACE_EC,
EcSpaceHandler);
if (sc->ec_csr_res)
@ -690,8 +690,8 @@ EcGpeQueryHandler(void *Context)
* The GPE handler is called when IBE/OBF or SCI events occur. We are
* called from an unknown lock context.
*/
static uint32_t
EcGpeHandler(void *Context)
static UINT32
EcGpeHandler(ACPI_HANDLE GpeDevice, UINT32 GpeNumber, void *Context)
{
struct acpi_ec_softc *sc = Context;
ACPI_STATUS Status;
@ -722,7 +722,12 @@ EcGpeHandler(void *Context)
else
printf("EcGpeHandler: queuing GPE query handler failed\n");
}
return (0);
/*
* XXX jkim
* AcpiFinishGpe() should be used at the necessary places.
*/
return (ACPI_REENABLE_GPE);
}
static ACPI_STATUS

View File

@ -39,7 +39,7 @@ SRCS+= dmresrcs.c dmutils.c dmwalk.c
SRCS+= dsfield.c dsinit.c dsmethod.c dsmthdat.c dsobject.c dsopcode.c
SRCS+= dsutils.c dswexec.c dswload.c dswscope.c dswstate.c
SRCS+= evevent.c evgpe.c evgpeblk.c evgpeinit.c evgpeutil.c evmisc.c
SRCS+= evregion.c evrgnini.c evsci.c evxface.c evxfevnt.c evxfregn.c
SRCS+= evregion.c evrgnini.c evsci.c evxface.c evxfevnt.c evxfgpe.c evxfregn.c
SRCS+= exconfig.c exconvrt.c excreate.c exdebug.c exdump.c exfield.c
SRCS+= exfldio.c exmisc.c exmutex.c exnames.c exoparg1.c exoparg2.c
SRCS+= exoparg3.c exoparg6.c exprep.c exregion.c exresnte.c exresolv.c

View File

@ -15,7 +15,7 @@ SRCS+= dmbuffer.c dmnames.c dmobject.c dmopcode.c dmresrc.c \
# events
SRCS+= evevent.c evgpe.c evgpeblk.c evgpeinit.c evgpeutil.c \
evmisc.c evregion.c evrgnini.c evsci.c evxface.c \
evxfevnt.c evxfregn.c
evxfevnt.c evxfgpe.c evxfregn.c
# hardware
SRCS+= hwacpi.c hwgpe.c hwpci.c hwregs.c hwsleep.c hwvalid.c \