diff options
author | njl <njl@FreeBSD.org> | 2003-04-29 18:39:29 +0000 |
---|---|---|
committer | njl <njl@FreeBSD.org> | 2003-04-29 18:39:29 +0000 |
commit | 0f552762e45d65746b7b1ee44d8ca1b52bf83450 (patch) | |
tree | 4f870813153015b497486f4e5b8eaf0bb08c4bad /sys/contrib/dev/acpica/evevent.c | |
parent | 2b17a8d498a3e4598c19121ab1fad3e7ced2c699 (diff) | |
download | FreeBSD-src-0f552762e45d65746b7b1ee44d8ca1b52bf83450.zip FreeBSD-src-0f552762e45d65746b7b1ee44d8ca1b52bf83450.tar.gz |
Import of Intel ACPI 20030228 vendor distribution
Diffstat (limited to 'sys/contrib/dev/acpica/evevent.c')
-rw-r--r-- | sys/contrib/dev/acpica/evevent.c | 738 |
1 files changed, 12 insertions, 726 deletions
diff --git a/sys/contrib/dev/acpica/evevent.c b/sys/contrib/dev/acpica/evevent.c index fe4bc56..76e8aa2 100644 --- a/sys/contrib/dev/acpica/evevent.c +++ b/sys/contrib/dev/acpica/evevent.c @@ -1,7 +1,7 @@ /****************************************************************************** * - * Module Name: evevent - Fixed and General Purpose Even handling and dispatch - * $Revision: 96 $ + * Module Name: evevent - Fixed Event handling and dispatch + * $Revision: 108 $ * *****************************************************************************/ @@ -9,7 +9,7 @@ * * 1. Copyright Notice * - * Some or all of this work - Copyright (c) 1999 - 2002, Intel Corp. + * Some or all of this work - Copyright (c) 1999 - 2003, Intel Corp. * All rights reserved. * * 2. License @@ -116,7 +116,6 @@ #include "acpi.h" #include "acevents.h" -#include "acnamesp.h" #define _COMPONENT ACPI_EVENTS ACPI_MODULE_NAME ("evevent") @@ -154,13 +153,13 @@ AcpiEvInitialize ( /* * Initialize the Fixed and General Purpose AcpiEvents prior. This is - * done prior to enabling SCIs to prevent interrupts from occuring + * done prior to enabling SCIs to prevent interrupts from occurring * before handers are installed. */ Status = AcpiEvFixedEventInitialize (); if (ACPI_FAILURE (Status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_FATAL, + ACPI_REPORT_ERROR (( "Unable to initialize fixed events, %s\n", AcpiFormatException (Status))); return_ACPI_STATUS (Status); @@ -169,7 +168,7 @@ AcpiEvInitialize ( Status = AcpiEvGpeInitialize (); if (ACPI_FAILURE (Status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_FATAL, + ACPI_REPORT_ERROR (( "Unable to initialize general purpose events, %s\n", AcpiFormatException (Status))); return_ACPI_STATUS (Status); @@ -187,7 +186,7 @@ AcpiEvInitialize ( * * RETURN: Status * - * DESCRIPTION: Install handlers for the SCI, Global Lock, and GPEs. + * DESCRIPTION: Install interrupt handlers for the SCI and Global Lock * ******************************************************************************/ @@ -206,29 +205,18 @@ AcpiEvHandlerInitialize ( Status = AcpiEvInstallSciHandler (); if (ACPI_FAILURE (Status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_FATAL, + ACPI_REPORT_ERROR (( "Unable to install System Control Interrupt Handler, %s\n", AcpiFormatException (Status))); return_ACPI_STATUS (Status); } - /* Install handlers for control method GPE handlers (_Lxx, _Exx) */ - - Status = AcpiEvInitGpeControlMethods (); - if (ACPI_FAILURE (Status)) - { - ACPI_DEBUG_PRINT ((ACPI_DB_FATAL, - "Unable to initialize GPE control methods, %s\n", - AcpiFormatException (Status))); - return_ACPI_STATUS (Status); - } - /* Install the handler for the Global Lock */ Status = AcpiEvInitGlobalLockHandler (); if (ACPI_FAILURE (Status)) { - ACPI_DEBUG_PRINT ((ACPI_DB_FATAL, + ACPI_REPORT_ERROR (( "Unable to initialize Global Lock handler, %s\n", AcpiFormatException (Status))); return_ACPI_STATUS (Status); @@ -255,7 +243,7 @@ ACPI_STATUS AcpiEvFixedEventInitialize ( void) { - NATIVE_UINT i; + ACPI_NATIVE_UINT i; ACPI_STATUS Status; @@ -304,7 +292,7 @@ AcpiEvFixedEventDetect ( UINT32 IntStatus = ACPI_INTERRUPT_NOT_HANDLED; UINT32 FixedStatus; UINT32 FixedEnable; - NATIVE_UINT_MAX32 i; + ACPI_NATIVE_UINT i; ACPI_FUNCTION_NAME ("EvFixedEventDetect"); @@ -333,7 +321,7 @@ AcpiEvFixedEventDetect ( { /* Found an active (signalled) event */ - IntStatus |= AcpiEvFixedEventDispatch (i); + IntStatus |= AcpiEvFixedEventDispatch ((UINT32) i); } } @@ -391,705 +379,3 @@ AcpiEvFixedEventDispatch ( } -/******************************************************************************* - * - * FUNCTION: AcpiEvGpeInitialize - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Initialize the GPE data structures - * - ******************************************************************************/ - -ACPI_STATUS -AcpiEvGpeInitialize (void) -{ - NATIVE_UINT_MAX32 i; - NATIVE_UINT_MAX32 j; - UINT32 GpeBlock; - UINT32 GpeRegister; - UINT32 GpeNumberIndex; - UINT32 GpeNumber; - ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; - ACPI_STATUS Status; - - - ACPI_FUNCTION_TRACE ("EvGpeInitialize"); - - - /* - * Initialize the GPE Block globals - * - * 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." - */ - AcpiGbl_GpeBlockInfo[0].AddressSpaceId = AcpiGbl_FADT->XGpe0Blk.AddressSpaceId; - AcpiGbl_GpeBlockInfo[1].AddressSpaceId = AcpiGbl_FADT->XGpe1Blk.AddressSpaceId; - - AcpiGbl_GpeBlockInfo[0].RegisterCount = (UINT16) ACPI_DIV_16 (AcpiGbl_FADT->XGpe0Blk.RegisterBitWidth); - AcpiGbl_GpeBlockInfo[1].RegisterCount = (UINT16) ACPI_DIV_16 (AcpiGbl_FADT->XGpe1Blk.RegisterBitWidth); - - AcpiGbl_GpeBlockInfo[0].BlockAddress = &AcpiGbl_FADT->XGpe0Blk; - AcpiGbl_GpeBlockInfo[1].BlockAddress = &AcpiGbl_FADT->XGpe1Blk; - - AcpiGbl_GpeBlockInfo[0].BlockBaseNumber = 0; - AcpiGbl_GpeBlockInfo[1].BlockBaseNumber = AcpiGbl_FADT->Gpe1Base; - - /* Warn and exit if there are no GPE registers */ - - AcpiGbl_GpeRegisterCount = AcpiGbl_GpeBlockInfo[0].RegisterCount + - AcpiGbl_GpeBlockInfo[1].RegisterCount; - if (!AcpiGbl_GpeRegisterCount) - { - ACPI_REPORT_WARNING (("There are no GPE blocks defined in the FADT\n")); - return_ACPI_STATUS (AE_OK); - } - - /* - * Determine the maximum GPE number for this machine. - * Note: both GPE0 and GPE1 are optional, and either can exist without - * the other - */ - if (AcpiGbl_GpeBlockInfo[0].RegisterCount) - { - /* GPE block 0 exists */ - - AcpiGbl_GpeNumberMax = ACPI_MUL_8 (AcpiGbl_GpeBlockInfo[0].RegisterCount) - 1; - } - - if (AcpiGbl_GpeBlockInfo[1].RegisterCount) - { - /* GPE block 1 exists */ - - /* Check for GPE0/GPE1 overlap (if both banks exist) */ - - if ((AcpiGbl_GpeBlockInfo[0].RegisterCount) && - (AcpiGbl_GpeNumberMax >= AcpiGbl_FADT->Gpe1Base)) - { - ACPI_REPORT_ERROR (( - "GPE0 block (GPE 0 to %d) overlaps the GPE1 block (GPE %d to %d)\n", - AcpiGbl_GpeNumberMax, AcpiGbl_FADT->Gpe1Base, - AcpiGbl_FADT->Gpe1Base + (ACPI_MUL_8 (AcpiGbl_GpeBlockInfo[1].RegisterCount) - 1))); - return_ACPI_STATUS (AE_BAD_VALUE); - } - - /* - * GPE0 and GPE1 do not have to be contiguous in the GPE number space, - * But, GPE0 always starts at zero. - */ - 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 number-to-index translation table */ - - AcpiGbl_GpeNumberToIndex = ACPI_MEM_CALLOCATE ( - sizeof (ACPI_GPE_INDEX_INFO) * - ((ACPI_SIZE) AcpiGbl_GpeNumberMax + 1)); - if (!AcpiGbl_GpeNumberToIndex) - { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Could not allocate the GpeNumberToIndex table\n")); - return_ACPI_STATUS (AE_NO_MEMORY); - } - - /* Set the Gpe index table to GPE_INVALID */ - - ACPI_MEMSET (AcpiGbl_GpeNumberToIndex, (int) ACPI_GPE_INVALID, - sizeof (ACPI_GPE_INDEX_INFO) * ((ACPI_SIZE) AcpiGbl_GpeNumberMax + 1)); - - /* Allocate the GPE register information block */ - - AcpiGbl_GpeRegisterInfo = ACPI_MEM_CALLOCATE ( - (ACPI_SIZE) AcpiGbl_GpeRegisterCount * - sizeof (ACPI_GPE_REGISTER_INFO)); - if (!AcpiGbl_GpeRegisterInfo) - { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Could not allocate the GpeRegisterInfo table\n")); - goto ErrorExit1; - } - - /* - * Allocate the GPE dispatch handler block. There are eight distinct GPEs - * per register. Initialization to zeros is sufficient. - */ - AcpiGbl_GpeNumberInfo = ACPI_MEM_CALLOCATE ( - (ACPI_SIZE) 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; - } - - /* - * 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 (GpeBlock = 0; GpeBlock < ACPI_MAX_GPE_BLOCKS; GpeBlock++) - { - for (i = 0; i < AcpiGbl_GpeBlockInfo[GpeBlock].RegisterCount; i++) - { - GpeRegisterInfo = &AcpiGbl_GpeRegisterInfo[GpeRegister]; - - /* Init the Register info for this entire GPE register (8 GPEs) */ - - GpeRegisterInfo->BaseGpeNumber = (UINT8) (AcpiGbl_GpeBlockInfo[GpeBlock].BlockBaseNumber - + (ACPI_MUL_8 (i))); - - ACPI_STORE_ADDRESS (GpeRegisterInfo->StatusAddress.Address, - (ACPI_GET_ADDRESS (AcpiGbl_GpeBlockInfo[GpeBlock].BlockAddress->Address) - + i)); - - ACPI_STORE_ADDRESS (GpeRegisterInfo->EnableAddress.Address, - (ACPI_GET_ADDRESS (AcpiGbl_GpeBlockInfo[GpeBlock].BlockAddress->Address) - + i - + AcpiGbl_GpeBlockInfo[GpeBlock].RegisterCount)); - - GpeRegisterInfo->StatusAddress.AddressSpaceId = AcpiGbl_GpeBlockInfo[GpeBlock].AddressSpaceId; - GpeRegisterInfo->EnableAddress.AddressSpaceId = AcpiGbl_GpeBlockInfo[GpeBlock].AddressSpaceId; - GpeRegisterInfo->StatusAddress.RegisterBitWidth = 8; - GpeRegisterInfo->EnableAddress.RegisterBitWidth = 8; - GpeRegisterInfo->StatusAddress.RegisterBitOffset = 8; - GpeRegisterInfo->EnableAddress.RegisterBitOffset = 8; - - /* Init the Index mapping info for each GPE number within this register */ - - for (j = 0; j < 8; j++) - { - GpeNumber = GpeRegisterInfo->BaseGpeNumber + j; - AcpiGbl_GpeNumberToIndex[GpeNumber].NumberIndex = (UINT8) GpeNumberIndex; - - AcpiGbl_GpeNumberInfo[GpeNumberIndex].BitMask = AcpiGbl_DecodeTo8bit[j]; - GpeNumberIndex++; - } - - /* - * Clear the status/enable registers. Note that status registers - * are cleared by writing a '1', while enable registers are cleared - * by writing a '0'. - */ - Status = AcpiHwLowLevelWrite (8, 0x00, &GpeRegisterInfo->EnableAddress, 0); - if (ACPI_FAILURE (Status)) - { - return_ACPI_STATUS (Status); - } - - Status = AcpiHwLowLevelWrite (8, 0xFF, &GpeRegisterInfo->StatusAddress, 0); - if (ACPI_FAILURE (Status)) - { - return_ACPI_STATUS (Status); - } - - GpeRegister++; - } - - if (i) - { - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "GPE Block%d: %X registers at %8.8X%8.8X\n", - (INT32) GpeBlock, AcpiGbl_GpeBlockInfo[0].RegisterCount, - ACPI_HIDWORD (ACPI_GET_ADDRESS (AcpiGbl_GpeBlockInfo[GpeBlock].BlockAddress->Address)), - ACPI_LODWORD (ACPI_GET_ADDRESS (AcpiGbl_GpeBlockInfo[GpeBlock].BlockAddress->Address)))); - - ACPI_REPORT_INFO (("GPE Block%d defined as GPE%d to GPE%d\n", - (INT32) GpeBlock, - (UINT32) AcpiGbl_GpeBlockInfo[GpeBlock].BlockBaseNumber, - (UINT32) (AcpiGbl_GpeBlockInfo[GpeBlock].BlockBaseNumber + - ((AcpiGbl_GpeBlockInfo[GpeBlock].RegisterCount * 8) -1)))); - } - } - - 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); -} - - -/******************************************************************************* - * - * FUNCTION: AcpiEvSaveMethodInfo - * - * PARAMETERS: None - * - * RETURN: None - * - * DESCRIPTION: Called from AcpiWalkNamespace. Expects each object to be a - * control method under the _GPE portion of the namespace. - * Extract the name and GPE type from the object, saving this - * information for quick lookup during GPE dispatch - * - * The name of each GPE control method is of the form: - * "_Lnn" or "_Enn" - * Where: - * L - means that the GPE is level triggered - * E - means that the GPE is edge triggered - * nn - is the GPE number [in HEX] - * - ******************************************************************************/ - -static ACPI_STATUS -AcpiEvSaveMethodInfo ( - ACPI_HANDLE ObjHandle, - UINT32 Level, - void *ObjDesc, - void **ReturnValue) -{ - UINT32 GpeNumber; - UINT32 GpeNumberIndex; - NATIVE_CHAR Name[ACPI_NAME_SIZE + 1]; - UINT8 Type; - ACPI_STATUS Status; - - - ACPI_FUNCTION_NAME ("EvSaveMethodInfo"); - - - /* Extract the name from the object and convert to a string */ - - ACPI_MOVE_UNALIGNED32_TO_32 (Name, - &((ACPI_NAMESPACE_NODE *) ObjHandle)->Name.Integer); - Name[ACPI_NAME_SIZE] = 0; - - /* - * Edge/Level determination is based on the 2nd character of the method name - */ - switch (Name[1]) - { - case 'L': - Type = ACPI_EVENT_LEVEL_TRIGGERED; - break; - - case 'E': - Type = ACPI_EVENT_EDGE_TRIGGERED; - break; - - default: - /* Unknown method type, just ignore it! */ - - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Unknown GPE method type: %s (name not of form _Lnn or _Enn)\n", - Name)); - return (AE_OK); - } - - /* Convert the last two characters of the name to the GPE Number */ - - GpeNumber = ACPI_STRTOUL (&Name[2], NULL, 16); - if (GpeNumber == ACPI_UINT32_MAX) - { - /* Conversion failed; invalid method, just ignore it */ - - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, - "Could not extract GPE number from name: %s (name not of form _Lnn or _Enn)\n", - Name)); - return (AE_OK); - } - - /* Get GPE index and ensure that we have a valid GPE number */ - - GpeNumberIndex = AcpiEvGetGpeNumberIndex (GpeNumber); - if (GpeNumberIndex == ACPI_GPE_INVALID) - { - /* Not valid, all we can do here is ignore it */ - - return (AE_OK); - } - - /* - * Now we can add this information to the GpeInfo block - * for use during dispatch of this GPE. - */ - AcpiGbl_GpeNumberInfo [GpeNumberIndex].Type = Type; - AcpiGbl_GpeNumberInfo [GpeNumberIndex].MethodHandle = ObjHandle; - - /* - * Enable the GPE (SCIs should be disabled at this point) - */ - Status = AcpiHwEnableGpe (GpeNumber); - if (ACPI_FAILURE (Status)) - { - return (Status); - } - - ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Registered GPE method %s as GPE number %X\n", - Name, GpeNumber)); - return (AE_OK); -} - - -/******************************************************************************* - * - * FUNCTION: AcpiEvInitGpeControlMethods - * - * PARAMETERS: None - * - * RETURN: Status - * - * DESCRIPTION: Obtain the control methods associated with the GPEs. - * NOTE: Must be called AFTER namespace initialization! - * - ******************************************************************************/ - -ACPI_STATUS -AcpiEvInitGpeControlMethods (void) -{ - ACPI_STATUS Status; - - - ACPI_FUNCTION_TRACE ("EvInitGpeControlMethods"); - - - /* Get a permanent handle to the _GPE object */ - - Status = AcpiGetHandle (NULL, "\\_GPE", &AcpiGbl_GpeObjHandle); - if (ACPI_FAILURE (Status)) - { - return_ACPI_STATUS (Status); - } - - /* Traverse the namespace under \_GPE to find all methods there */ - - Status = AcpiWalkNamespace (ACPI_TYPE_METHOD, AcpiGbl_GpeObjHandle, - ACPI_UINT32_MAX, AcpiEvSaveMethodInfo, - NULL, NULL); - - return_ACPI_STATUS (Status); -} - - -/******************************************************************************* - * - * FUNCTION: AcpiEvGpeDetect - * - * PARAMETERS: None - * - * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED - * - * DESCRIPTION: Detect if any GP events have occurred. This function is - * executed at interrupt level. - * - ******************************************************************************/ - -UINT32 -AcpiEvGpeDetect (void) -{ - UINT32 IntStatus = ACPI_INTERRUPT_NOT_HANDLED; - UINT32 i; - UINT32 j; - UINT8 EnabledStatusByte; - UINT8 BitMask; - ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; - UINT32 InValue; - ACPI_STATUS Status; - - - ACPI_FUNCTION_NAME ("EvGpeDetect"); - - - /* - * Read all of the 8-bit GPE status and enable registers - * in both of the register blocks, saving all of it. - * Find all currently active GP events. - */ - for (i = 0; i < AcpiGbl_GpeRegisterCount; i++) - { - GpeRegisterInfo = &AcpiGbl_GpeRegisterInfo[i]; - - Status = AcpiHwLowLevelRead (8, &InValue, &GpeRegisterInfo->StatusAddress, 0); - GpeRegisterInfo->Status = (UINT8) InValue; - if (ACPI_FAILURE (Status)) - { - return (ACPI_INTERRUPT_NOT_HANDLED); - } - - Status = AcpiHwLowLevelRead (8, &InValue, &GpeRegisterInfo->EnableAddress, 0); - GpeRegisterInfo->Enable = (UINT8) InValue; - if (ACPI_FAILURE (Status)) - { - return (ACPI_INTERRUPT_NOT_HANDLED); - } - - ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, - "GPE block at %8.8X%8.8X - Values: Enable %02X Status %02X\n", - ACPI_HIDWORD (ACPI_GET_ADDRESS (GpeRegisterInfo->EnableAddress.Address)), - ACPI_LODWORD (ACPI_GET_ADDRESS (GpeRegisterInfo->EnableAddress.Address)), - GpeRegisterInfo->Enable, - GpeRegisterInfo->Status)); - - /* First check if there is anything active at all in this register */ - - EnabledStatusByte = (UINT8) (GpeRegisterInfo->Status & - GpeRegisterInfo->Enable); - if (!EnabledStatusByte) - { - /* No active GPEs in this register, move on */ - - continue; - } - - /* Now look at the individual GPEs in this byte register */ - - for (j = 0, BitMask = 1; j < 8; j++, BitMask <<= 1) - { - /* Examine one GPE bit */ - - if (EnabledStatusByte & BitMask) - { - /* - * Found an active GPE. Dispatch the event to a handler - * or method. - */ - IntStatus |= AcpiEvGpeDispatch ( - GpeRegisterInfo->BaseGpeNumber + j); - } - } - } - - return (IntStatus); -} - - -/******************************************************************************* - * - * FUNCTION: AcpiEvAsynchExecuteGpeMethod - * - * PARAMETERS: GpeNumber - The 0-based GPE number - * - * RETURN: None - * - * DESCRIPTION: Perform the actual execution of a GPE control method. This - * function is called from an invocation of AcpiOsQueueForExecution - * (and therefore does NOT execute at interrupt level) so that - * the control method itself is not executed in the context of - * the SCI interrupt handler. - * - ******************************************************************************/ - -static void ACPI_SYSTEM_XFACE -AcpiEvAsynchExecuteGpeMethod ( - void *Context) -{ - UINT32 GpeNumber = (UINT32) ACPI_TO_INTEGER (Context); - UINT32 GpeNumberIndex; - ACPI_GPE_NUMBER_INFO GpeInfo; - ACPI_STATUS Status; - - - ACPI_FUNCTION_TRACE ("EvAsynchExecuteGpeMethod"); - - - GpeNumberIndex = AcpiEvGetGpeNumberIndex (GpeNumber); - if (GpeNumberIndex == ACPI_GPE_INVALID) - { - return_VOID; - } - - /* - * Take a snapshot of the GPE info for this level - we copy the - * info to prevent a race condition with RemoveHandler. - */ - Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); - if (ACPI_FAILURE (Status)) - { - return_VOID; - } - - GpeInfo = AcpiGbl_GpeNumberInfo [GpeNumberIndex]; - Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS); - if (ACPI_FAILURE (Status)) - { - return_VOID; - } - - if (GpeInfo.MethodHandle) - { - /* - * Invoke the GPE Method (_Lxx, _Exx): - * (Evaluate the _Lxx/_Exx control method that corresponds to this GPE.) - */ - Status = AcpiNsEvaluateByHandle (GpeInfo.MethodHandle, NULL, NULL); - if (ACPI_FAILURE (Status)) - { - ACPI_REPORT_ERROR (("%s while evaluating GPE%X method\n", - AcpiFormatException (Status), GpeNumber)); - } - } - - if (GpeInfo.Type & ACPI_EVENT_LEVEL_TRIGGERED) - { - /* - * GPE is level-triggered, we clear the GPE status bit after handling - * the event. - */ - Status = AcpiHwClearGpe (GpeNumber); - if (ACPI_FAILURE (Status)) - { - return_VOID; - } - } - - /* - * Enable the GPE. - */ - (void) AcpiHwEnableGpe (GpeNumber); - return_VOID; -} - - -/******************************************************************************* - * - * FUNCTION: AcpiEvGpeDispatch - * - * PARAMETERS: GpeNumber - The 0-based GPE number - * - * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED - * - * DESCRIPTION: Dispatch a General Purpose Event to either a function (e.g. EC) - * or method (e.g. _Lxx/_Exx) handler. This function executes - * at interrupt level. - * - ******************************************************************************/ - -UINT32 -AcpiEvGpeDispatch ( - UINT32 GpeNumber) -{ - UINT32 GpeNumberIndex; - ACPI_GPE_NUMBER_INFO *GpeInfo; - ACPI_STATUS Status; - - - ACPI_FUNCTION_TRACE ("EvGpeDispatch"); - - - GpeNumberIndex = AcpiEvGetGpeNumberIndex (GpeNumber); - if (GpeNumberIndex == ACPI_GPE_INVALID) - { - ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "GPE[%X] is not a valid event\n", GpeNumber)); - return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); - } - - /* - * We don't have to worry about mutex on GpeInfo because we are - * executing at interrupt level. - */ - GpeInfo = &AcpiGbl_GpeNumberInfo [GpeNumberIndex]; - - /* - * 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) - { - Status = AcpiHwClearGpe (GpeNumber); - if (ACPI_FAILURE (Status)) - { - ACPI_REPORT_ERROR (("AcpiEvGpeDispatch: Unable to clear GPE[%X]\n", GpeNumber)); - return_VALUE (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 the level to - * prevent further events from coming in here. - */ - if (GpeInfo->Handler) - { - /* Invoke the installed handler (at interrupt level) */ - - GpeInfo->Handler (GpeInfo->Context); - } - else if (GpeInfo->MethodHandle) - { - /* - * Disable GPE, so it doesn't keep firing before the method has a - * chance to run. - */ - Status = AcpiHwDisableGpe (GpeNumber); - if (ACPI_FAILURE (Status)) - { - ACPI_REPORT_ERROR (("AcpiEvGpeDispatch: Unable to disable GPE[%X]\n", GpeNumber)); - return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); - } - - /* - * 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], event is disabled\n", GpeNumber)); - } - } - else - { - /* No handler or method to run! */ - - ACPI_REPORT_ERROR (("AcpiEvGpeDispatch: No handler or method for GPE[%X], disabling event\n", GpeNumber)); - - /* - * Disable the GPE. The GPE will remain disabled until the ACPI - * Core Subsystem is restarted, or the handler is reinstalled. - */ - Status = AcpiHwDisableGpe (GpeNumber); - if (ACPI_FAILURE (Status)) - { - ACPI_REPORT_ERROR (("AcpiEvGpeDispatch: Unable to disable GPE[%X]\n", GpeNumber)); - return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); - } - } - - /* - * It is now safe to clear level-triggered evnets. - */ - if (GpeInfo->Type & ACPI_EVENT_LEVEL_TRIGGERED) - { - Status = AcpiHwClearGpe (GpeNumber); - if (ACPI_FAILURE (Status)) - { - ACPI_REPORT_ERROR (("AcpiEvGpeDispatch: Unable to clear GPE[%X]\n", GpeNumber)); - return_VALUE (ACPI_INTERRUPT_NOT_HANDLED); - } - } - - return_VALUE (ACPI_INTERRUPT_HANDLED); -} |