summaryrefslogtreecommitdiffstats
path: root/sys/contrib/dev/acpica/evevent.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/dev/acpica/evevent.c')
-rw-r--r--sys/contrib/dev/acpica/evevent.c650
1 files changed, 345 insertions, 305 deletions
diff --git a/sys/contrib/dev/acpica/evevent.c b/sys/contrib/dev/acpica/evevent.c
index 20c9953..b11adce 100644
--- a/sys/contrib/dev/acpica/evevent.c
+++ b/sys/contrib/dev/acpica/evevent.c
@@ -1,8 +1,7 @@
/******************************************************************************
*
- * Module Name: evevent - Fixed and General Purpose AcpiEvent
- * handling and dispatch
- * $Revision: 54 $
+ * Module Name: evevent - Fixed and General Purpose Even handling and dispatch
+ * $Revision: 69 $
*
*****************************************************************************/
@@ -10,7 +9,7 @@
*
* 1. Copyright Notice
*
- * Some or all of this work - Copyright (c) 1999, 2000, 2001, Intel Corp.
+ * Some or all of this work - Copyright (c) 1999 - 2002, Intel Corp.
* All rights reserved.
*
* 2. License
@@ -121,7 +120,7 @@
#include "acnamesp.h"
#define _COMPONENT ACPI_EVENTS
- MODULE_NAME ("evevent")
+ ACPI_MODULE_NAME ("evevent")
/*******************************************************************************
@@ -132,9 +131,7 @@
*
* RETURN: Status
*
- * DESCRIPTION: Ensures that the system control interrupt (SCI) is properly
- * configured, disables SCI event sources, installs the SCI
- * handler
+ * DESCRIPTION: Initialize global data structures for events.
*
******************************************************************************/
@@ -145,7 +142,7 @@ AcpiEvInitialize (
ACPI_STATUS Status;
- FUNCTION_TRACE ("EvInitialize");
+ ACPI_FUNCTION_TRACE ("EvInitialize");
/* Make sure we have ACPI tables */
@@ -164,23 +161,55 @@ AcpiEvInitialize (
Status = AcpiEvFixedEventInitialize ();
if (ACPI_FAILURE (Status))
{
- ACPI_DEBUG_PRINT ((ACPI_DB_FATAL, "Unable to initialize fixed events.\n"));
+ ACPI_DEBUG_PRINT ((ACPI_DB_FATAL,
+ "Unable to initialize fixed events, %s\n",
+ AcpiFormatException (Status)));
return_ACPI_STATUS (Status);
}
Status = AcpiEvGpeInitialize ();
if (ACPI_FAILURE (Status))
{
- ACPI_DEBUG_PRINT ((ACPI_DB_FATAL, "Unable to initialize general purpose events.\n"));
+ ACPI_DEBUG_PRINT ((ACPI_DB_FATAL,
+ "Unable to initialize general purpose events, %s\n",
+ AcpiFormatException (Status)));
return_ACPI_STATUS (Status);
}
+ return_ACPI_STATUS (Status);
+}
+
+
+/*******************************************************************************
+ *
+ * FUNCTION: AcpiEvHandlerInitialize
+ *
+ * PARAMETERS: None
+ *
+ * RETURN: Status
+ *
+ * DESCRIPTION: Install handlers for the SCI, Global Lock, and GPEs.
+ *
+ ******************************************************************************/
+
+ACPI_STATUS
+AcpiEvHandlerInitialize (
+ void)
+{
+ ACPI_STATUS Status;
+
+
+ ACPI_FUNCTION_TRACE ("EvInitialize");
+
+
/* Install the SCI handler */
Status = AcpiEvInstallSciHandler ();
if (ACPI_FAILURE (Status))
{
- ACPI_DEBUG_PRINT ((ACPI_DB_FATAL, "Unable to install System Control Interrupt Handler\n"));
+ ACPI_DEBUG_PRINT ((ACPI_DB_FATAL,
+ "Unable to install System Control Interrupt Handler, %s\n",
+ AcpiFormatException (Status)));
return_ACPI_STATUS (Status);
}
@@ -189,7 +218,9 @@ AcpiEvInitialize (
Status = AcpiEvInitGpeControlMethods ();
if (ACPI_FAILURE (Status))
{
- ACPI_DEBUG_PRINT ((ACPI_DB_FATAL, "Unable to initialize Gpe control methods\n"));
+ ACPI_DEBUG_PRINT ((ACPI_DB_FATAL,
+ "Unable to initialize GPE control methods, %s\n",
+ AcpiFormatException (Status)));
return_ACPI_STATUS (Status);
}
@@ -198,7 +229,9 @@ AcpiEvInitialize (
Status = AcpiEvInitGlobalLockHandler ();
if (ACPI_FAILURE (Status))
{
- ACPI_DEBUG_PRINT ((ACPI_DB_FATAL, "Unable to initialize Global Lock handler\n"));
+ ACPI_DEBUG_PRINT ((ACPI_DB_FATAL,
+ "Unable to initialize Global Lock handler, %s\n",
+ AcpiFormatException (Status)));
return_ACPI_STATUS (Status);
}
@@ -214,29 +247,34 @@ AcpiEvInitialize (
*
* RETURN: Status
*
- * DESCRIPTION: Initialize the Fixed AcpiEvent data structures
+ * DESCRIPTION: Install the fixed event handlers and enable the fixed events.
*
******************************************************************************/
ACPI_STATUS
-AcpiEvFixedEventInitialize(void)
+AcpiEvFixedEventInitialize (
+ void)
{
NATIVE_UINT i;
- /* Initialize the structure that keeps track of fixed event handlers */
-
+ /*
+ * Initialize the structure that keeps track of fixed event handlers
+ * and enable the fixed events.
+ */
for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++)
{
AcpiGbl_FixedEventHandlers[i].Handler = NULL;
AcpiGbl_FixedEventHandlers[i].Context = NULL;
- }
- AcpiHwRegisterBitAccess (ACPI_WRITE, ACPI_MTX_LOCK, TMR_EN, 0);
- AcpiHwRegisterBitAccess (ACPI_WRITE, ACPI_MTX_LOCK, GBL_EN, 0);
- AcpiHwRegisterBitAccess (ACPI_WRITE, ACPI_MTX_LOCK, PWRBTN_EN, 0);
- AcpiHwRegisterBitAccess (ACPI_WRITE, ACPI_MTX_LOCK, SLPBTN_EN, 0);
- AcpiHwRegisterBitAccess (ACPI_WRITE, ACPI_MTX_LOCK, RTC_EN, 0);
+ /* Enable the fixed event */
+
+ if (AcpiGbl_FixedEventInfo[i].EnableRegisterId != 0xFF)
+ {
+ AcpiHwBitRegisterWrite (AcpiGbl_FixedEventInfo[i].EnableRegisterId,
+ 0, ACPI_MTX_LOCK);
+ }
+ }
return (AE_OK);
}
@@ -255,57 +293,43 @@ AcpiEvFixedEventInitialize(void)
******************************************************************************/
UINT32
-AcpiEvFixedEventDetect (void)
+AcpiEvFixedEventDetect (
+ void)
{
- UINT32 IntStatus = INTERRUPT_NOT_HANDLED;
- UINT32 StatusRegister;
- UINT32 EnableRegister;
+ UINT32 IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
+ UINT32 GpeStatus;
+ UINT32 GpeEnable;
+ NATIVE_UINT i;
- PROC_NAME ("EvFixedEventDetect");
+ ACPI_FUNCTION_NAME ("EvFixedEventDetect");
/*
* Read the fixed feature status and enable registers, as all the cases
* depend on their values.
*/
- StatusRegister = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, PM1_STS);
- EnableRegister = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, PM1_EN);
+ GpeStatus = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_STATUS);
+ GpeEnable = AcpiHwRegisterRead (ACPI_MTX_DO_NOT_LOCK, ACPI_REGISTER_PM1_ENABLE);
ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
"Fixed AcpiEvent Block: Enable %08X Status %08X\n",
- EnableRegister, StatusRegister));
-
- /* Power management timer roll over */
+ GpeEnable, GpeStatus));
- if ((StatusRegister & ACPI_STATUS_PMTIMER) &&
- (EnableRegister & ACPI_ENABLE_PMTIMER))
- {
- IntStatus |= AcpiEvFixedEventDispatch (ACPI_EVENT_PMTIMER);
- }
-
- /* Global event (BIOS wants the global lock) */
-
- if ((StatusRegister & ACPI_STATUS_GLOBAL) &&
- (EnableRegister & ACPI_ENABLE_GLOBAL))
- {
- IntStatus |= AcpiEvFixedEventDispatch (ACPI_EVENT_GLOBAL);
- }
-
- /* Power button event */
-
- if ((StatusRegister & ACPI_STATUS_POWER_BUTTON) &&
- (EnableRegister & ACPI_ENABLE_POWER_BUTTON))
+ /*
+ * Check for all possible Fixed Events and dispatch those that are active
+ */
+ for (i = 0; i < ACPI_NUM_FIXED_EVENTS; i++)
{
- IntStatus |= AcpiEvFixedEventDispatch (ACPI_EVENT_POWER_BUTTON);
- }
+ /* Both the status and enable bits must be on for this event */
- /* Sleep button event */
+ if ((GpeStatus & AcpiGbl_FixedEventInfo[i].StatusBitMask) &&
+ (GpeEnable & AcpiGbl_FixedEventInfo[i].EnableBitMask))
+ {
+ /* Found an active (signalled) event */
- if ((StatusRegister & ACPI_STATUS_SLEEP_BUTTON) &&
- (EnableRegister & ACPI_ENABLE_SLEEP_BUTTON))
- {
- IntStatus |= AcpiEvFixedEventDispatch (ACPI_EVENT_SLEEP_BUTTON);
+ IntStatus |= AcpiEvFixedEventDispatch (i);
+ }
}
return (IntStatus);
@@ -329,42 +353,15 @@ UINT32
AcpiEvFixedEventDispatch (
UINT32 Event)
{
- UINT32 RegisterId;
- FUNCTION_ENTRY ();
+ ACPI_FUNCTION_ENTRY ();
/* Clear the status bit */
- switch (Event)
- {
- case ACPI_EVENT_PMTIMER:
- RegisterId = TMR_STS;
- break;
-
- case ACPI_EVENT_GLOBAL:
- RegisterId = GBL_STS;
- break;
-
- case ACPI_EVENT_POWER_BUTTON:
- RegisterId = PWRBTN_STS;
- break;
-
- case ACPI_EVENT_SLEEP_BUTTON:
- RegisterId = SLPBTN_STS;
- break;
-
- case ACPI_EVENT_RTC:
- RegisterId = RTC_STS;
- break;
-
- default:
- return 0;
- break;
- }
-
- AcpiHwRegisterBitAccess (ACPI_WRITE, ACPI_MTX_DO_NOT_LOCK, RegisterId, 1);
+ AcpiHwBitRegisterWrite (AcpiGbl_FixedEventInfo[Event].StatusRegisterId,
+ 1, ACPI_MTX_DO_NOT_LOCK);
/*
* Make sure we've got a handler. If not, report an error.
@@ -372,19 +369,17 @@ AcpiEvFixedEventDispatch (
*/
if (NULL == AcpiGbl_FixedEventHandlers[Event].Handler)
{
- RegisterId = (PM1_EN | REGISTER_BIT_ID(RegisterId));
+ AcpiHwBitRegisterWrite (AcpiGbl_FixedEventInfo[Event].EnableRegisterId,
+ 0, ACPI_MTX_DO_NOT_LOCK);
- AcpiHwRegisterBitAccess (ACPI_WRITE, ACPI_MTX_DO_NOT_LOCK,
- RegisterId, 0);
-
- REPORT_ERROR (
+ ACPI_REPORT_ERROR (
("EvGpeDispatch: No installed handler for fixed event [%08X]\n",
Event));
- return (INTERRUPT_NOT_HANDLED);
+ return (ACPI_INTERRUPT_NOT_HANDLED);
}
- /* Invoke the handler */
+ /* Invoke the Fixed Event handler */
return ((AcpiGbl_FixedEventHandlers[Event].Handler)(
AcpiGbl_FixedEventHandlers[Event].Context));
@@ -406,145 +401,181 @@ AcpiEvFixedEventDispatch (
ACPI_STATUS
AcpiEvGpeInitialize (void)
{
- UINT32 i;
- UINT32 j;
- UINT32 RegisterIndex;
+ NATIVE_UINT i;
+ NATIVE_UINT j;
+ NATIVE_UINT GpeBlock;
+ UINT32 GpeRegister;
+ UINT32 GpeNumberIndex;
UINT32 GpeNumber;
- UINT16 Gpe0RegisterCount;
- UINT16 Gpe1RegisterCount;
+ ACPI_GPE_REGISTER_INFO *GpeRegisterInfo;
+
+ ACPI_FUNCTION_TRACE ("EvGpeInitialize");
- FUNCTION_TRACE ("EvGpeInitialize");
/*
- * Set up various GPE counts
+ * Initialize the GPE Block globals
*
- * You may ask,why are the GPE register block lengths divided by 2?
- * From the ACPI 2.0 Spec, section, 4.7.1.6 General-Purpose Event
- * Registers, we have,
+ * Why the GPE register block lengths divided by 2: From the ACPI Spec,
+ * section "General-Purpose Event Registers", we have:
*
* "Each register block contains two registers of equal length
- * GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the
- * GPE0_STS and GPE0_EN registers is equal to half the GPE0_LEN
- * The length of the GPE1_STS and GPE1_EN registers is equal to
- * half the GPE1_LEN. If a generic register block is not supported
- * then its respective block pointer and block length values in the
- * FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need
- * to be the same size."
+ * GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the
+ * GPE0_STS and GPE0_EN registers is equal to half the GPE0_LEN
+ * The length of the GPE1_STS and GPE1_EN registers is equal to
+ * half the GPE1_LEN. If a generic register block is not supported
+ * then its respective block pointer and block length values in the
+ * FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need
+ * to be the same size."
*/
- Gpe0RegisterCount = (UINT16) DIV_2 (AcpiGbl_FADT->Gpe0BlkLen);
- Gpe1RegisterCount = (UINT16) DIV_2 (AcpiGbl_FADT->Gpe1BlkLen);
- AcpiGbl_GpeRegisterCount = Gpe0RegisterCount + Gpe1RegisterCount;
+ AcpiGbl_GpeBlockInfo[0].RegisterCount = (UINT16) ACPI_DIV_2 (AcpiGbl_FADT->Gpe0BlkLen);
+ AcpiGbl_GpeBlockInfo[1].RegisterCount = (UINT16) ACPI_DIV_2 (AcpiGbl_FADT->Gpe1BlkLen);
+ AcpiGbl_GpeBlockInfo[0].BlockAddress = (UINT16) ACPI_GET_ADDRESS (AcpiGbl_FADT->XGpe0Blk.Address);
+ AcpiGbl_GpeBlockInfo[1].BlockAddress = (UINT16) ACPI_GET_ADDRESS (AcpiGbl_FADT->XGpe1Blk.Address);
+
+ AcpiGbl_GpeBlockInfo[0].BlockBaseNumber = 0;
+ AcpiGbl_GpeBlockInfo[1].BlockBaseNumber = AcpiGbl_FADT->Gpe1Base;
+
+ AcpiGbl_GpeRegisterCount = AcpiGbl_GpeBlockInfo[0].RegisterCount +
+ AcpiGbl_GpeBlockInfo[1].RegisterCount;
if (!AcpiGbl_GpeRegisterCount)
{
- REPORT_WARNING (("Zero GPEs are defined in the FADT\n"));
+ ACPI_REPORT_WARNING (("Zero GPEs are defined in the FADT\n"));
return_ACPI_STATUS (AE_OK);
}
- /*
- * Allocate the Gpe information block
- */
- AcpiGbl_GpeRegisters = ACPI_MEM_CALLOCATE (AcpiGbl_GpeRegisterCount *
- sizeof (ACPI_GPE_REGISTERS));
- if (!AcpiGbl_GpeRegisters)
+ /* Determine the maximum GPE number for this machine */
+
+ AcpiGbl_GpeNumberMax = ACPI_MUL_8 (AcpiGbl_GpeBlockInfo[0].RegisterCount) - 1;
+
+ if (AcpiGbl_GpeBlockInfo[1].RegisterCount)
{
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
- "Could not allocate the GpeRegisters block\n"));
- return_ACPI_STATUS (AE_NO_MEMORY);
+ /* Check for GPE0/GPE1 overlap */
+
+ if (AcpiGbl_GpeNumberMax >= AcpiGbl_FADT->Gpe1Base)
+ {
+ ACPI_REPORT_ERROR (("GPE0 block overlaps the GPE1 block\n"));
+ return_ACPI_STATUS (AE_BAD_VALUE);
+ }
+
+ /* GPE0 and GPE1 do not have to be contiguous in the GPE number space */
+
+ AcpiGbl_GpeNumberMax = AcpiGbl_FADT->Gpe1Base + (ACPI_MUL_8 (AcpiGbl_GpeBlockInfo[1].RegisterCount) - 1);
+ }
+
+ /* Check for Max GPE number out-of-range */
+
+ if (AcpiGbl_GpeNumberMax > ACPI_GPE_MAX)
+ {
+ ACPI_REPORT_ERROR (("Maximum GPE number from FADT is too large: 0x%X\n", AcpiGbl_GpeNumberMax));
+ return_ACPI_STATUS (AE_BAD_VALUE);
}
/*
- * Allocate the Gpe dispatch handler block
- * There are eight distinct GP events per register.
- * Initialization to zeros is sufficient
+ * Allocate the GPE number-to-index translation table
*/
- AcpiGbl_GpeInfo = ACPI_MEM_CALLOCATE (MUL_8 (AcpiGbl_GpeRegisterCount) *
- sizeof (ACPI_GPE_LEVEL_INFO));
- if (!AcpiGbl_GpeInfo)
+ AcpiGbl_GpeNumberToIndex = ACPI_MEM_CALLOCATE (sizeof (ACPI_GPE_INDEX_INFO) *
+ (AcpiGbl_GpeNumberMax + 1));
+ if (!AcpiGbl_GpeNumberToIndex)
{
- ACPI_MEM_FREE (AcpiGbl_GpeRegisters);
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not allocate the GpeInfo block\n"));
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+ "Could not allocate the GpeNumberToIndex table\n"));
return_ACPI_STATUS (AE_NO_MEMORY);
}
- /* Set the Gpe validation table to GPE_INVALID */
+ /* Set the Gpe index table to GPE_INVALID */
- MEMSET (AcpiGbl_GpeValid, (int) ACPI_GPE_INVALID, ACPI_NUM_GPE);
+ ACPI_MEMSET (AcpiGbl_GpeNumberToIndex, (int) ACPI_GPE_INVALID,
+ sizeof (ACPI_GPE_INDEX_INFO) * (AcpiGbl_GpeNumberMax + 1));
/*
- * Initialize the Gpe information and validation blocks. A goal of these
- * blocks is to hide the fact that there are two separate GPE register sets
- * In a given block, the status registers occupy the first half, and
- * the enable registers occupy the second half.
+ * Allocate the GPE register information block
*/
-
- /* GPE Block 0 */
-
- RegisterIndex = 0;
-
- for (i = 0; i < Gpe0RegisterCount; i++)
+ AcpiGbl_GpeRegisterInfo = ACPI_MEM_CALLOCATE (AcpiGbl_GpeRegisterCount *
+ sizeof (ACPI_GPE_REGISTER_INFO));
+ if (!AcpiGbl_GpeRegisterInfo)
{
- AcpiGbl_GpeRegisters[RegisterIndex].StatusAddr =
- (UINT16) (ACPI_GET_ADDRESS (AcpiGbl_FADT->XGpe0Blk.Address) + i);
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+ "Could not allocate the GpeRegisterInfo table\n"));
+ goto ErrorExit1;
+ }
- AcpiGbl_GpeRegisters[RegisterIndex].EnableAddr =
- (UINT16) (ACPI_GET_ADDRESS (AcpiGbl_FADT->XGpe0Blk.Address) + i + Gpe0RegisterCount);
+ /*
+ * Allocate the GPE dispatch handler block. There are eight distinct GPEs
+ * per register. Initialization to zeros is sufficient.
+ */
+ AcpiGbl_GpeNumberInfo = ACPI_MEM_CALLOCATE (ACPI_MUL_8 (AcpiGbl_GpeRegisterCount) *
+ sizeof (ACPI_GPE_NUMBER_INFO));
+ if (!AcpiGbl_GpeNumberInfo)
+ {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not allocate the GpeNumberInfo table\n"));
+ goto ErrorExit2;
+ }
- AcpiGbl_GpeRegisters[RegisterIndex].GpeBase = (UINT8) MUL_8 (i);
+ /*
+ * Initialize the GPE information and validation tables. A goal of these
+ * tables is to hide the fact that there are two separate GPE register sets
+ * in a given gpe hardware block, the status registers occupy the first half,
+ * and the enable registers occupy the second half. Another goal is to hide
+ * the fact that there may be multiple GPE hardware blocks.
+ */
+ GpeRegister = 0;
+ GpeNumberIndex = 0;
- for (j = 0; j < 8; j++)
+ for (GpeBlock = 0; GpeBlock < ACPI_MAX_GPE_BLOCKS; GpeBlock++)
+ {
+ for (i = 0; i < AcpiGbl_GpeBlockInfo[GpeBlock].RegisterCount; i++)
{
- GpeNumber = AcpiGbl_GpeRegisters[RegisterIndex].GpeBase + j;
- AcpiGbl_GpeValid[GpeNumber] = (UINT8) RegisterIndex;
- }
+ GpeRegisterInfo = &AcpiGbl_GpeRegisterInfo[GpeRegister];
- /*
- * Clear the status/enable registers. Note that status registers
- * are cleared by writing a '1', while enable registers are cleared
- * by writing a '0'.
- */
- AcpiOsWritePort (AcpiGbl_GpeRegisters[RegisterIndex].EnableAddr, 0x00, 8);
- AcpiOsWritePort (AcpiGbl_GpeRegisters[RegisterIndex].StatusAddr, 0xFF, 8);
+ /* Init the Register info for this entire GPE register (8 GPEs) */
- RegisterIndex++;
- }
+ GpeRegisterInfo->BaseGpeNumber = (UINT8) (AcpiGbl_GpeBlockInfo[GpeBlock].BlockBaseNumber + (ACPI_MUL_8 (i)));
+ GpeRegisterInfo->StatusAddr = (UINT16) (AcpiGbl_GpeBlockInfo[GpeBlock].BlockAddress + i);
+ GpeRegisterInfo->EnableAddr = (UINT16) (AcpiGbl_GpeBlockInfo[GpeBlock].BlockAddress + i +
+ AcpiGbl_GpeBlockInfo[GpeBlock].RegisterCount);
- /* GPE Block 1 */
+ /* Init the Index mapping info for each GPE number within this register */
- for (i = 0; i < Gpe1RegisterCount; i++)
- {
- AcpiGbl_GpeRegisters[RegisterIndex].StatusAddr =
- (UINT16) (ACPI_GET_ADDRESS (AcpiGbl_FADT->XGpe1Blk.Address) + i);
+ for (j = 0; j < 8; j++)
+ {
+ GpeNumber = GpeRegisterInfo->BaseGpeNumber + j;
+ AcpiGbl_GpeNumberToIndex[GpeNumber].NumberIndex = (UINT8) GpeNumberIndex;
- AcpiGbl_GpeRegisters[RegisterIndex].EnableAddr =
- (UINT16) (ACPI_GET_ADDRESS (AcpiGbl_FADT->XGpe1Blk.Address) + i + Gpe1RegisterCount);
+ AcpiGbl_GpeNumberInfo[GpeNumberIndex].BitMask = AcpiGbl_DecodeTo8bit[i];
+ GpeNumberIndex++;
+ }
- AcpiGbl_GpeRegisters[RegisterIndex].GpeBase =
- (UINT8) (AcpiGbl_FADT->Gpe1Base + MUL_8 (i));
+ /*
+ * Clear the status/enable registers. Note that status registers
+ * are cleared by writing a '1', while enable registers are cleared
+ * by writing a '0'.
+ */
+ AcpiOsWritePort (GpeRegisterInfo->EnableAddr, 0x00, 8);
+ AcpiOsWritePort (GpeRegisterInfo->StatusAddr, 0xFF, 8);
- for (j = 0; j < 8; j++)
- {
- GpeNumber = AcpiGbl_GpeRegisters[RegisterIndex].GpeBase + j;
- AcpiGbl_GpeValid[GpeNumber] = (UINT8) RegisterIndex;
+ GpeRegister++;
}
-
- /*
- * Clear the status/enable registers. Note that status registers
- * are cleared by writing a '1', while enable registers are cleared
- * by writing a '0'.
- */
- AcpiOsWritePort (AcpiGbl_GpeRegisters[RegisterIndex].EnableAddr, 0x00, 8);
- AcpiOsWritePort (AcpiGbl_GpeRegisters[RegisterIndex].StatusAddr, 0xFF, 8);
-
- RegisterIndex++;
}
ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "GPE registers: %X@%8.8X%8.8X (Blk0) %X@%8.8X%8.8X (Blk1)\n",
- Gpe0RegisterCount, HIDWORD(AcpiGbl_FADT->XGpe0Blk.Address), LODWORD(AcpiGbl_FADT->XGpe0Blk.Address),
- Gpe1RegisterCount, HIDWORD(AcpiGbl_FADT->XGpe1Blk.Address), LODWORD(AcpiGbl_FADT->XGpe1Blk.Address)));
+ AcpiGbl_GpeBlockInfo[0].RegisterCount,
+ ACPI_HIDWORD (AcpiGbl_FADT->XGpe0Blk.Address), ACPI_LODWORD (AcpiGbl_FADT->XGpe0Blk.Address),
+ AcpiGbl_GpeBlockInfo[1].RegisterCount,
+ ACPI_HIDWORD (AcpiGbl_FADT->XGpe1Blk.Address), ACPI_LODWORD (AcpiGbl_FADT->XGpe1Blk.Address)));
return_ACPI_STATUS (AE_OK);
+
+
+ /* Error cleanup */
+
+ErrorExit2:
+ ACPI_MEM_FREE (AcpiGbl_GpeRegisterInfo);
+
+ErrorExit1:
+ ACPI_MEM_FREE (AcpiGbl_GpeNumberToIndex);
+ return_ACPI_STATUS (AE_NO_MEMORY);
}
@@ -566,7 +597,7 @@ AcpiEvGpeInitialize (void)
* Where:
* L - means that the GPE is level triggered
* E - means that the GPE is edge triggered
- * nn - is the GPE number
+ * nn - is the GPE number [in HEX]
*
******************************************************************************/
@@ -578,31 +609,34 @@ AcpiEvSaveMethodInfo (
void **ReturnValue)
{
UINT32 GpeNumber;
+ UINT32 GpeNumberIndex;
NATIVE_CHAR Name[ACPI_NAME_SIZE + 1];
UINT8 Type;
- PROC_NAME ("EvSaveMethodInfo");
+ ACPI_FUNCTION_NAME ("EvSaveMethodInfo");
/* Extract the name from the object and convert to a string */
- MOVE_UNALIGNED32_TO_32 (Name, &((ACPI_NAMESPACE_NODE *) ObjHandle)->Name);
+ ACPI_MOVE_UNALIGNED32_TO_32 (Name,
+ &((ACPI_NAMESPACE_NODE *) ObjHandle)->Name);
Name[ACPI_NAME_SIZE] = 0;
/*
- * Edge/Level determination is based on the 2nd INT8 of the method name
+ * Edge/Level determination is based on the 2nd character of the method name
*/
- if (Name[1] == 'L')
+ switch (Name[1])
{
+ case 'L':
Type = ACPI_EVENT_LEVEL_TRIGGERED;
- }
- else if (Name[1] == 'E')
- {
+ break;
+
+ case 'E':
Type = ACPI_EVENT_EDGE_TRIGGERED;
- }
- else
- {
+ break;
+
+ default:
/* Unknown method type, just ignore it! */
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
@@ -611,9 +645,9 @@ AcpiEvSaveMethodInfo (
return (AE_OK);
}
- /* Convert the last two characters of the name to the Gpe Number */
+ /* Convert the last two characters of the name to the GPE Number */
- GpeNumber = STRTOUL (&Name[2], NULL, 16);
+ GpeNumber = ACPI_STRTOUL (&Name[2], NULL, 16);
if (GpeNumber == ACPI_UINT32_MAX)
{
/* Conversion failed; invalid method, just ignore it */
@@ -624,9 +658,10 @@ AcpiEvSaveMethodInfo (
return (AE_OK);
}
- /* Ensure that we have a valid GPE number */
+ /* Get GPE index and ensure that we have a valid GPE number */
- if (AcpiGbl_GpeValid[GpeNumber] == ACPI_GPE_INVALID)
+ GpeNumberIndex = AcpiEvGetGpeNumberIndex (GpeNumber);
+ if (GpeNumberIndex == ACPI_GPE_INVALID)
{
/* Not valid, all we can do here is ignore it */
@@ -637,8 +672,8 @@ AcpiEvSaveMethodInfo (
* Now we can add this information to the GpeInfo block
* for use during dispatch of this GPE.
*/
- AcpiGbl_GpeInfo [GpeNumber].Type = Type;
- AcpiGbl_GpeInfo [GpeNumber].MethodHandle = ObjHandle;
+ AcpiGbl_GpeNumberInfo [GpeNumberIndex].Type = Type;
+ AcpiGbl_GpeNumberInfo [GpeNumberIndex].MethodHandle = ObjHandle;
/*
* Enable the GPE (SCIs should be disabled at this point)
@@ -657,10 +692,9 @@ AcpiEvSaveMethodInfo (
*
* PARAMETERS: None
*
- * RETURN: None
+ * RETURN: Status
*
* DESCRIPTION: Obtain the control methods associated with the GPEs.
- *
* NOTE: Must be called AFTER namespace initialization!
*
******************************************************************************/
@@ -671,7 +705,7 @@ AcpiEvInitGpeControlMethods (void)
ACPI_STATUS Status;
- FUNCTION_TRACE ("EvInitGpeControlMethods");
+ ACPI_FUNCTION_TRACE ("EvInitGpeControlMethods");
/* Get a permanent handle to the _GPE object */
@@ -700,21 +734,23 @@ AcpiEvInitGpeControlMethods (void)
*
* RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
*
- * DESCRIPTION: Detect if any GP events have occurred
+ * DESCRIPTION: Detect if any GP events have occurred. This function is
+ * executed at interrupt level.
*
******************************************************************************/
UINT32
AcpiEvGpeDetect (void)
{
- UINT32 IntStatus = INTERRUPT_NOT_HANDLED;
+ UINT32 IntStatus = ACPI_INTERRUPT_NOT_HANDLED;
UINT32 i;
UINT32 j;
UINT8 EnabledStatusByte;
UINT8 BitMask;
+ ACPI_GPE_REGISTER_INFO *GpeRegisterInfo;
- PROC_NAME ("EvGpeDetect");
+ ACPI_FUNCTION_NAME ("EvGpeDetect");
/*
@@ -724,23 +760,24 @@ AcpiEvGpeDetect (void)
*/
for (i = 0; i < AcpiGbl_GpeRegisterCount; i++)
{
- AcpiOsReadPort (AcpiGbl_GpeRegisters[i].StatusAddr,
- &AcpiGbl_GpeRegisters[i].Status, 8);
+ GpeRegisterInfo = &AcpiGbl_GpeRegisterInfo[i];
- AcpiOsReadPort (AcpiGbl_GpeRegisters[i].EnableAddr,
- &AcpiGbl_GpeRegisters[i].Enable, 8);
+ AcpiOsReadPort (GpeRegisterInfo->StatusAddr,
+ &GpeRegisterInfo->Status, 8);
+
+ AcpiOsReadPort (GpeRegisterInfo->EnableAddr,
+ &GpeRegisterInfo->Enable, 8);
ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS,
"GPE block at %X - Enable %08X Status %08X\n",
- AcpiGbl_GpeRegisters[i].EnableAddr,
- AcpiGbl_GpeRegisters[i].Status,
- AcpiGbl_GpeRegisters[i].Enable));
+ GpeRegisterInfo->EnableAddr,
+ GpeRegisterInfo->Status,
+ GpeRegisterInfo->Enable));
/* First check if there is anything active at all in this register */
- EnabledStatusByte = (UINT8) (AcpiGbl_GpeRegisters[i].Status &
- AcpiGbl_GpeRegisters[i].Enable);
-
+ EnabledStatusByte = (UINT8) (GpeRegisterInfo->Status &
+ GpeRegisterInfo->Enable);
if (!EnabledStatusByte)
{
/* No active GPEs in this register, move on */
@@ -761,7 +798,7 @@ AcpiEvGpeDetect (void)
* or method.
*/
IntStatus |= AcpiEvGpeDispatch (
- AcpiGbl_GpeRegisters[i].GpeBase + j);
+ GpeRegisterInfo->BaseGpeNumber + j);
}
}
}
@@ -774,7 +811,7 @@ AcpiEvGpeDetect (void)
*
* FUNCTION: AcpiEvAsynchExecuteGpeMethod
*
- * PARAMETERS: GpeNumber - The 0-based Gpe number
+ * PARAMETERS: GpeNumber - The 0-based GPE number
*
* RETURN: None
*
@@ -790,37 +827,50 @@ static void
AcpiEvAsynchExecuteGpeMethod (
void *Context)
{
- UINT32 GpeNumber = (UINT32) Context;
- ACPI_GPE_LEVEL_INFO GpeInfo;
+ UINT32 GpeNumber = (UINT32) ACPI_TO_INTEGER (Context);
+ UINT32 GpeNumberIndex;
+ ACPI_GPE_NUMBER_INFO GpeInfo;
- FUNCTION_TRACE ("EvAsynchExecuteGpeMethod");
+ ACPI_FUNCTION_TRACE ("EvAsynchExecuteGpeMethod");
- /*
- * Take a snapshot of the GPE info for this level
- */
- AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
- GpeInfo = AcpiGbl_GpeInfo [GpeNumber];
- AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
+ GpeNumberIndex = AcpiEvGetGpeNumberIndex (GpeNumber);
+ if (GpeNumberIndex == ACPI_GPE_INVALID)
+ {
+ return_VOID;
+ }
/*
- * Method Handler (_Lxx, _Exx):
- * ----------------------------
- * Evaluate the _Lxx/_Exx control method that corresponds to this GPE.
+ * Take a snapshot of the GPE info for this level - we copy the
+ * info to prevent a race condition with RemoveHandler.
*/
+ if (ACPI_FAILURE (AcpiUtAcquireMutex (ACPI_MTX_EVENTS)))
+ {
+ return_VOID;
+ }
+
+ GpeInfo = AcpiGbl_GpeNumberInfo [GpeNumberIndex];
+ if (ACPI_FAILURE (AcpiUtReleaseMutex (ACPI_MTX_EVENTS)))
+ {
+ return_VOID;
+ }
+
if (GpeInfo.MethodHandle)
{
+ /*
+ * Invoke the GPE Method (_Lxx, _Exx):
+ * (Evaluate the _Lxx/_Exx control method that corresponds to this GPE.)
+ */
AcpiNsEvaluateByHandle (GpeInfo.MethodHandle, NULL, NULL);
}
- /*
- * Level-Triggered?
- * ----------------
- * If level-triggered we clear the GPE status bit after handling the event.
- */
if (GpeInfo.Type & ACPI_EVENT_LEVEL_TRIGGERED)
{
+ /*
+ * GPE is level-triggered, we clear the GPE status bit after handling
+ * the event.
+ */
AcpiHwClearGpe (GpeNumber);
}
@@ -828,7 +878,6 @@ AcpiEvAsynchExecuteGpeMethod (
* Enable the GPE.
*/
AcpiHwEnableGpe (GpeNumber);
-
return_VOID;
}
@@ -837,18 +886,13 @@ AcpiEvAsynchExecuteGpeMethod (
*
* FUNCTION: AcpiEvGpeDispatch
*
- * PARAMETERS: GpeNumber - The 0-based Gpe number
+ * PARAMETERS: GpeNumber - The 0-based GPE number
*
* RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
*
- * DESCRIPTION: Handle and dispatch a General Purpose AcpiEvent.
- * Clears the status bit for the requested event.
- *
- * TBD: [Investigate] is this still valid or necessary:
- * The Gpe handler differs from the fixed events in that it clears the enable
- * bit rather than the status bit to clear the interrupt. This allows
- * software outside of interrupt context to determine what caused the SCI and
- * dispatch the correct AML.
+ * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC)
+ * or method (e.g. _Lxx/_Exx) handler. This function executes
+ * at interrupt level.
*
******************************************************************************/
@@ -856,90 +900,86 @@ UINT32
AcpiEvGpeDispatch (
UINT32 GpeNumber)
{
- ACPI_GPE_LEVEL_INFO GpeInfo;
+ UINT32 GpeNumberIndex;
+ ACPI_GPE_NUMBER_INFO *GpeInfo;
- FUNCTION_TRACE ("EvGpeDispatch");
+ ACPI_FUNCTION_TRACE ("EvGpeDispatch");
- /*
- * Valid GPE number?
- */
- if (AcpiGbl_GpeValid[GpeNumber] == ACPI_GPE_INVALID)
+ GpeNumberIndex = AcpiEvGetGpeNumberIndex (GpeNumber);
+ if (GpeNumberIndex == ACPI_GPE_INVALID)
{
- ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid GPE bit [%X].\n", GpeNumber));
- return_VALUE (INTERRUPT_NOT_HANDLED);
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid event, GPE[%X].\n", GpeNumber));
+ return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
}
/*
- * Disable the GPE.
+ * We don't have to worry about mutex on GpeInfo because we are
+ * executing at interrupt level.
*/
- AcpiHwDisableGpe (GpeNumber);
-
- GpeInfo = AcpiGbl_GpeInfo [GpeNumber];
+ GpeInfo = &AcpiGbl_GpeNumberInfo [GpeNumberIndex];
/*
- * Edge-Triggered?
- * ---------------
* If edge-triggered, clear the GPE status bit now. Note that
* level-triggered events are cleared after the GPE is serviced.
*/
- if (GpeInfo.Type & ACPI_EVENT_EDGE_TRIGGERED)
+ if (GpeInfo->Type & ACPI_EVENT_EDGE_TRIGGERED)
{
AcpiHwClearGpe (GpeNumber);
}
- /*
- * Function Handler (e.g. EC)?
- */
- if (GpeInfo.Handler)
- {
- /* Invoke function handler (at interrupt level). */
-
- GpeInfo.Handler (GpeInfo.Context);
-
- /* Level-Triggered? */
-
- if (GpeInfo.Type & ACPI_EVENT_LEVEL_TRIGGERED)
- {
- AcpiHwClearGpe (GpeNumber);
- }
-
- /* Enable GPE */
-
- AcpiHwEnableGpe (GpeNumber);
- }
/*
- * Method Handler (e.g. _Exx/_Lxx)?
+ * 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 the level to
+ * prevent further events from coming in here.
*/
- else if (GpeInfo.MethodHandle)
+ if (GpeInfo->Handler)
+ {
+ /* Invoke the installed handler (at interrupt level) */
+
+ GpeInfo->Handler (GpeInfo->Context);
+ }
+ else if (GpeInfo->MethodHandle)
{
- if (ACPI_FAILURE(AcpiOsQueueForExecution (OSD_PRIORITY_GPE,
- AcpiEvAsynchExecuteGpeMethod, (void*) GpeNumber)))
+ /*
+ * Execute the method associated with the GPE.
+ */
+ if (ACPI_FAILURE (AcpiOsQueueForExecution (OSD_PRIORITY_GPE,
+ AcpiEvAsynchExecuteGpeMethod,
+ ACPI_TO_POINTER (GpeNumber))))
{
+ ACPI_REPORT_ERROR (("AcpiEvGpeDispatch: Unable to queue handler for GPE[%X], disabling event\n", GpeNumber));
+
/*
- * Shoudn't occur, but if it does report an error. Note that
- * the GPE will remain disabled until the ACPI Core Subsystem
- * is restarted, or the handler is removed/reinstalled.
+ * Disable the GPE on error. The GPE will remain disabled until the ACPI
+ * Core Subsystem is restarted, or the handler is reinstalled.
*/
- REPORT_ERROR (("AcpiEvGpeDispatch: Unable to queue handler for GPE bit [%X]\n", GpeNumber));
+ AcpiHwDisableGpe (GpeNumber);
}
}
-
- /*
- * No Handler? Report an error and leave the GPE disabled.
- */
else
{
- REPORT_ERROR (("AcpiEvGpeDispatch: No installed handler for GPE [%X]\n", GpeNumber));
+ /* No handler or method to run! */
- /* Level-Triggered? */
+ ACPI_REPORT_ERROR (("AcpiEvGpeDispatch: No handler or method for GPE[%X], disabling event\n", GpeNumber));
- if (GpeInfo.Type & ACPI_EVENT_LEVEL_TRIGGERED)
- {
- AcpiHwClearGpe (GpeNumber);
- }
+ /*
+ * Disable the GPE. The GPE will remain disabled until the ACPI
+ * Core Subsystem is restarted, or the handler is reinstalled.
+ */
+ AcpiHwDisableGpe (GpeNumber);
+ }
+
+ /*
+ * It is now safe to clear level-triggered evnets.
+ */
+ if (GpeInfo->Type & ACPI_EVENT_LEVEL_TRIGGERED)
+ {
+ AcpiHwClearGpe (GpeNumber);
}
- return_VALUE (INTERRUPT_HANDLED);
+ return_VALUE (ACPI_INTERRUPT_HANDLED);
}
OpenPOWER on IntegriCloud