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_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_STATUS AcpiMarkGpeForWake ( ACPI_HANDLE GpeDevice, UINT32 GpeNumber) { ACPI_GPE_EVENT_INFO *GpeEventInfo; ACPI_STATUS Status = AE_BAD_PARAMETER; ACPI_CPU_FLAGS Flags; ACPI_FUNCTION_TRACE (AcpiMarkGpeForWake); Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); /* Ensure that we have a valid GPE number */ GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); if (GpeEventInfo) { /* Mark the GPE as a possible wake event */ GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE; Status = AE_OK; } AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); return_ACPI_STATUS (Status); }
void AcpiDbGenerateGpe ( char *GpeArg, char *BlockArg) { UINT32 BlockNumber = 0; UINT32 GpeNumber; ACPI_GPE_EVENT_INFO *GpeEventInfo; GpeNumber = ACPI_STRTOUL (GpeArg, NULL, 0); /* * If no block arg, or block arg == 0 or 1, use the FADT-defined * GPE blocks. */ if (BlockArg) { BlockNumber = ACPI_STRTOUL (BlockArg, NULL, 0); if (BlockNumber == 1) { BlockNumber = 0; } } GpeEventInfo = AcpiEvGetGpeEventInfo (ACPI_TO_POINTER (BlockNumber), GpeNumber); if (!GpeEventInfo) { AcpiOsPrintf ("Invalid GPE\n"); return; } (void) AcpiEvGpeDispatch (NULL, GpeEventInfo, GpeNumber); }
ACPI_STATUS AcpiSetGpeType ( ACPI_HANDLE GpeDevice, UINT32 GpeNumber, UINT8 Type) { ACPI_STATUS Status = AE_OK; ACPI_GPE_EVENT_INFO *GpeEventInfo; ACPI_FUNCTION_TRACE (AcpiSetGpeType); /* Ensure that we have a valid GPE number */ GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); if (!GpeEventInfo) { Status = AE_BAD_PARAMETER; goto UnlockAndExit; } if ((GpeEventInfo->Flags & ACPI_GPE_TYPE_MASK) == Type) { return_ACPI_STATUS (AE_OK); } /* Set the new type (will disable GPE if currently enabled) */ Status = AcpiEvSetGpeType (GpeEventInfo, Type); UnlockAndExit: return_ACPI_STATUS (Status); }
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_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_STATUS AcpiClearEvent ( UINT32 Event, UINT32 Type) { ACPI_STATUS Status = AE_OK; ACPI_GPE_EVENT_INFO *GpeEventInfo; ACPI_FUNCTION_TRACE ("AcpiClearEvent"); /* The Type must be either Fixed Event or GPE */ switch (Type) { case ACPI_EVENT_FIXED: /* Decode the Fixed Event */ if (Event > ACPI_EVENT_MAX) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* * Clear the requested fixed event (By writing a one to the * status register bit) */ Status = AcpiSetRegister (AcpiGbl_FixedEventInfo[Event].StatusRegisterId, 1, ACPI_MTX_LOCK); break; case ACPI_EVENT_GPE: /* Ensure that we have a valid GPE number */ GpeEventInfo = AcpiEvGetGpeEventInfo (Event); if (!GpeEventInfo) { return_ACPI_STATUS (AE_BAD_PARAMETER); } Status = AcpiHwClearGpe (GpeEventInfo); break; default: Status = AE_BAD_PARAMETER; } return_ACPI_STATUS (Status); }
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 = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE); GpeEventInfo->DisableForDispatch = FALSE; break; case ACPI_GPE_DISABLE: Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE); GpeEventInfo->DisableForDispatch = TRUE; break; default: Status = AE_BAD_PARAMETER; break; } UnlockAndExit: AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); return_ACPI_STATUS (Status); }
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_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_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 and that there is some way * of handling the GPE (handler or a GPE method). In other words, we * won't allow a valid GPE to be enabled if there is no way to handle it. */ GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); if (GpeEventInfo) { if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) != ACPI_GPE_DISPATCH_NONE) { Status = AcpiEvAddGpeReference (GpeEventInfo); if (ACPI_SUCCESS (Status) && ACPI_GPE_IS_POLLING_NEEDED (GpeEventInfo)) { /* Poll edge-triggered GPEs to handle existing events */ AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); (void) AcpiEvDetectGpe ( GpeDevice, GpeEventInfo, GpeNumber); Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); } } else { Status = AE_NO_HANDLER; } } AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiGetGpeStatus ( ACPI_HANDLE GpeDevice, UINT32 GpeNumber, UINT32 Flags, ACPI_EVENT_STATUS *EventStatus) { ACPI_STATUS Status = AE_OK; ACPI_GPE_EVENT_INFO *GpeEventInfo; ACPI_FUNCTION_TRACE (AcpiGetGpeStatus); /* Use semaphore lock if not executing at interrupt level */ if (Flags & ACPI_NOT_ISR) { Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } /* Ensure that we have a valid GPE number */ GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); if (!GpeEventInfo) { Status = AE_BAD_PARAMETER; goto UnlockAndExit; } /* Obtain status on the requested GPE number */ Status = AcpiHwGetGpeStatus (GpeEventInfo, EventStatus); UnlockAndExit: if (Flags & ACPI_NOT_ISR) { (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); } return_ACPI_STATUS (Status); }
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 and that there is some way * of handling the GPE (handler or a GPE method). In other words, we * won't allow a valid GPE to be enabled if there is no way to handle it. */ GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); if (GpeEventInfo) { if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) != ACPI_GPE_DISPATCH_NONE) { Status = AcpiEvAddGpeReference (GpeEventInfo); } else { Status = AE_NO_HANDLER; } } AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); return_ACPI_STATUS (Status); }
void AcpiDbGenerateGpe ( char *GpeArg, char *BlockArg) { UINT32 BlockNumber; UINT32 GpeNumber; ACPI_GPE_EVENT_INFO *GpeEventInfo; GpeNumber = ACPI_STRTOUL (GpeArg, NULL, 0); BlockNumber = ACPI_STRTOUL (BlockArg, NULL, 0); GpeEventInfo = AcpiEvGetGpeEventInfo (ACPI_TO_POINTER (BlockNumber), GpeNumber); if (!GpeEventInfo) { AcpiOsPrintf ("Invalid GPE\n"); return; } (void) AcpiEvGpeDispatch (NULL, GpeEventInfo, GpeNumber); }
ACPI_STATUS AcpiEnableGpe ( ACPI_HANDLE GpeDevice, UINT32 GpeNumber, UINT8 GpeType) { ACPI_STATUS Status = AE_OK; ACPI_GPE_EVENT_INFO *GpeEventInfo; ACPI_CPU_FLAGS Flags; ACPI_FUNCTION_TRACE (AcpiEnableGpe); /* Parameter validation */ if (!GpeType || (GpeType & ~ACPI_GPE_TYPE_WAKE_RUN)) { return_ACPI_STATUS (AE_BAD_PARAMETER); } Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); /* Ensure that we have a valid GPE number */ GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); if (!GpeEventInfo) { Status = AE_BAD_PARAMETER; goto UnlockAndExit; } if (GpeType & ACPI_GPE_TYPE_RUNTIME) { if (GpeEventInfo->RuntimeCount == ACPI_UINT8_MAX) { Status = AE_LIMIT; /* Too many references */ goto UnlockAndExit; } GpeEventInfo->RuntimeCount++; if (GpeEventInfo->RuntimeCount == 1) { Status = AcpiEvEnableGpe (GpeEventInfo); if (ACPI_FAILURE (Status)) { GpeEventInfo->RuntimeCount--; goto UnlockAndExit; } } } if (GpeType & ACPI_GPE_TYPE_WAKE) { /* The GPE must have the ability to wake the system */ if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE)) { Status = AE_TYPE; goto UnlockAndExit; } if (GpeEventInfo->WakeupCount == ACPI_UINT8_MAX) { Status = AE_LIMIT; /* Too many references */ goto UnlockAndExit; } /* * Update the enable mask on the first wakeup reference. Wake GPEs * are only hardware-enabled just before sleeping. */ GpeEventInfo->WakeupCount++; if (GpeEventInfo->WakeupCount == 1) { (void) AcpiEvUpdateGpeEnableMasks (GpeEventInfo); } } UnlockAndExit: AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); return_ACPI_STATUS (Status); }
static ACPI_STATUS AcpiEvInstallGpeHandler ( ACPI_HANDLE GpeDevice, UINT32 GpeNumber, UINT32 Type, BOOLEAN IsRawHandler, ACPI_GPE_HANDLER Address, void *Context) { ACPI_GPE_EVENT_INFO *GpeEventInfo; ACPI_GPE_HANDLER_INFO *Handler; ACPI_STATUS Status; ACPI_CPU_FLAGS Flags; ACPI_FUNCTION_TRACE (EvInstallGpeHandler); /* Parameter validation */ if ((!Address) || (Type & ~ACPI_GPE_XRUPT_TYPE_MASK)) { return_ACPI_STATUS (AE_BAD_PARAMETER); } Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* 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 FreeAndExit; } /* Make sure that there isn't a handler there already */ if ((ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == ACPI_GPE_DISPATCH_HANDLER) || (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == ACPI_GPE_DISPATCH_RAW_HANDLER)) { Status = AE_ALREADY_EXISTS; goto FreeAndExit; } 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 (((ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) == ACPI_GPE_DISPATCH_METHOD) || (ACPI_GPE_DISPATCH_TYPE (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 */ GpeEventInfo->Dispatch.Handler = Handler; /* 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 | (IsRawHandler ? ACPI_GPE_DISPATCH_RAW_HANDLER : ACPI_GPE_DISPATCH_HANDLER)); AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); UnlockAndExit: (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); return_ACPI_STATUS (Status); FreeAndExit: AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); ACPI_FREE (Handler); goto UnlockAndExit; }
ACPI_STATUS AcpiRemoveGpeHandler ( ACPI_HANDLE GpeDevice, UINT32 GpeNumber, ACPI_GPE_HANDLER Address) { ACPI_GPE_EVENT_INFO *GpeEventInfo; ACPI_GPE_HANDLER_INFO *Handler; ACPI_STATUS Status; ACPI_CPU_FLAGS Flags; ACPI_FUNCTION_TRACE (AcpiRemoveGpeHandler); /* Parameter validation */ if (!Address) { return_ACPI_STATUS (AE_BAD_PARAMETER); } Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); /* Ensure that we have a valid GPE number */ GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); if (!GpeEventInfo) { Status = AE_BAD_PARAMETER; goto UnlockAndExit; } /* Make sure that a handler is indeed installed */ if ((ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) != ACPI_GPE_DISPATCH_HANDLER) && (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) != ACPI_GPE_DISPATCH_RAW_HANDLER)) { Status = AE_NOT_EXIST; goto UnlockAndExit; } /* Make sure that the installed handler is the same */ if (GpeEventInfo->Dispatch.Handler->Address != Address) { Status = AE_BAD_PARAMETER; goto UnlockAndExit; } /* Remove the handler */ Handler = GpeEventInfo->Dispatch.Handler; GpeEventInfo->Dispatch.Handler = NULL; /* Restore Method node (if any), set dispatch flags */ GpeEventInfo->Dispatch.MethodNode = 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 (((ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) == ACPI_GPE_DISPATCH_METHOD) || (ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) == ACPI_GPE_DISPATCH_NOTIFY)) && Handler->OriginallyEnabled) { (void) AcpiEvAddGpeReference (GpeEventInfo); } AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); /* Make sure all deferred GPE tasks are completed */ AcpiOsWaitEventsComplete (); /* Now we can free the handler object */ ACPI_FREE (Handler); return_ACPI_STATUS (Status); UnlockAndExit: AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiRemoveGpeHandler ( ACPI_HANDLE GpeDevice, UINT32 GpeNumber, ACPI_EVENT_HANDLER Address) { ACPI_GPE_EVENT_INFO *GpeEventInfo; ACPI_HANDLER_INFO *Handler; ACPI_STATUS Status; ACPI_CPU_FLAGS Flags; ACPI_FUNCTION_TRACE (AcpiRemoveGpeHandler); /* Parameter validation */ if (!Address) { return_ACPI_STATUS (AE_BAD_PARAMETER); } Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Ensure that we have a valid GPE number */ GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); if (!GpeEventInfo) { Status = AE_BAD_PARAMETER; goto UnlockAndExit; } /* Make sure that a handler is indeed installed */ if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) != ACPI_GPE_DISPATCH_HANDLER) { Status = AE_NOT_EXIST; goto UnlockAndExit; } /* Make sure that the installed handler is the same */ if (GpeEventInfo->Dispatch.Handler->Address != Address) { Status = AE_BAD_PARAMETER; goto UnlockAndExit; } /* Disable the GPE before removing the handler */ Status = AcpiEvDisableGpe (GpeEventInfo); if (ACPI_FAILURE (Status)) { goto UnlockAndExit; } /* Remove the handler */ Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); Handler = GpeEventInfo->Dispatch.Handler; /* Restore Method node (if any), set dispatch flags */ GpeEventInfo->Dispatch.MethodNode = Handler->MethodNode; GpeEventInfo->Flags &= ~ACPI_GPE_DISPATCH_MASK; /* Clear bits */ if (Handler->MethodNode) { GpeEventInfo->Flags |= ACPI_GPE_DISPATCH_METHOD; } AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); /* Now we can free the handler object */ ACPI_FREE (Handler); UnlockAndExit: (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiInstallGpeHandler ( ACPI_HANDLE GpeDevice, UINT32 GpeNumber, UINT32 Type, ACPI_EVENT_HANDLER Address, void *Context) { ACPI_GPE_EVENT_INFO *GpeEventInfo; ACPI_HANDLER_INFO *Handler; ACPI_STATUS Status; ACPI_CPU_FLAGS Flags; ACPI_FUNCTION_TRACE (AcpiInstallGpeHandler); /* Parameter validation */ if ((!Address) || (Type > ACPI_GPE_XRUPT_TYPE_MASK)) { return_ACPI_STATUS (AE_BAD_PARAMETER); } Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Ensure that we have a valid GPE number */ GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); if (!GpeEventInfo) { Status = AE_BAD_PARAMETER; goto UnlockAndExit; } /* Make sure that there isn't a handler there already */ if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER) { Status = AE_ALREADY_EXISTS; goto UnlockAndExit; } /* Allocate and init handler object */ Handler = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_HANDLER_INFO)); if (!Handler) { Status = AE_NO_MEMORY; goto UnlockAndExit; } Handler->Address = Address; Handler->Context = Context; Handler->MethodNode = GpeEventInfo->Dispatch.MethodNode; /* Disable the GPE before installing the handler */ Status = AcpiEvDisableGpe (GpeEventInfo); if (ACPI_FAILURE (Status)) { goto UnlockAndExit; } /* Install the handler */ Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); GpeEventInfo->Dispatch.Handler = Handler; /* Setup up dispatch flags to indicate handler (vs. method) */ GpeEventInfo->Flags &= ~(ACPI_GPE_XRUPT_TYPE_MASK | ACPI_GPE_DISPATCH_MASK); /* Clear bits */ GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_HANDLER); AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); UnlockAndExit: (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); return_ACPI_STATUS (Status); }
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); }
ACPI_STATUS AcpiDisableEvent ( UINT32 Event, UINT32 Type, UINT32 Flags) { ACPI_STATUS Status = AE_OK; UINT32 Value; ACPI_GPE_EVENT_INFO *GpeEventInfo; ACPI_FUNCTION_TRACE ("AcpiDisableEvent"); /* The Type must be either Fixed Event or GPE */ switch (Type) { case ACPI_EVENT_FIXED: /* Decode the Fixed Event */ if (Event > ACPI_EVENT_MAX) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* * Disable the requested fixed event (by writing a zero to the * enable register bit) */ Status = AcpiSetRegister (AcpiGbl_FixedEventInfo[Event].EnableRegisterId, 0, ACPI_MTX_LOCK); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } Status = AcpiGetRegister (AcpiGbl_FixedEventInfo[Event].EnableRegisterId, &Value, ACPI_MTX_LOCK); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } if (Value != 0) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not disable %s events\n", AcpiUtGetEventName (Event))); return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE); } break; case ACPI_EVENT_GPE: /* Ensure that we have a valid GPE number */ GpeEventInfo = AcpiEvGetGpeEventInfo (Event); if (!GpeEventInfo) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* * Only disable the requested GPE number for wake if specified. * Otherwise, turn it totally off */ if (Flags & ACPI_EVENT_WAKE_DISABLE) { AcpiHwDisableGpeForWakeup (GpeEventInfo); } else { Status = AcpiHwDisableGpe (GpeEventInfo); } break; default: Status = AE_BAD_PARAMETER; } return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiGetEventStatus ( UINT32 Event, UINT32 Type, ACPI_EVENT_STATUS *EventStatus) { ACPI_STATUS Status = AE_OK; ACPI_GPE_EVENT_INFO *GpeEventInfo; ACPI_FUNCTION_TRACE ("AcpiGetEventStatus"); if (!EventStatus) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* The Type must be either Fixed Event or GPE */ switch (Type) { case ACPI_EVENT_FIXED: /* Decode the Fixed Event */ if (Event > ACPI_EVENT_MAX) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Get the status of the requested fixed event */ Status = AcpiGetRegister (AcpiGbl_FixedEventInfo[Event].StatusRegisterId, EventStatus, ACPI_MTX_LOCK); break; case ACPI_EVENT_GPE: /* Ensure that we have a valid GPE number */ GpeEventInfo = AcpiEvGetGpeEventInfo (Event); if (!GpeEventInfo) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Obtain status on the requested GPE number */ Status = AcpiHwGetGpeStatus (Event, EventStatus); break; default: Status = AE_BAD_PARAMETER; } return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiSetupGpeForWake ( ACPI_HANDLE WakeDevice, ACPI_HANDLE GpeDevice, UINT32 GpeNumber) { ACPI_STATUS Status; ACPI_GPE_EVENT_INFO *GpeEventInfo; ACPI_NAMESPACE_NODE *DeviceNode; ACPI_GPE_NOTIFY_INFO *Notify; ACPI_GPE_NOTIFY_INFO *NewNotify; 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); } /* Handle root object case */ if (WakeDevice == ACPI_ROOT_OBJECT) { DeviceNode = AcpiGbl_RootNode; } else { DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, WakeDevice); } /* Validate WakeDevice is of type Device */ if (DeviceNode->Type != ACPI_TYPE_DEVICE) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* * Allocate a new notify object up front, in case it is needed. * Memory allocation while holding a spinlock is a big no-no * on some hosts. */ NewNotify = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_NOTIFY_INFO)); if (!NewNotify) { return_ACPI_STATUS (AE_NO_MEMORY); } 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 there is no method or handler for this GPE, then the * WakeDevice will be notified whenever this GPE fires. This is * known as an "implicit notify". Note: The GPE is assumed to be * level-triggered (for windows compatibility). */ if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == ACPI_GPE_DISPATCH_NONE) { /* * This is the first device for implicit notify on this GPE. * Just set the flags here, and enter the NOTIFY block below. */ GpeEventInfo->Flags = (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED); } /* * If we already have an implicit notify on this GPE, add * this device to the notify list. */ if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == ACPI_GPE_DISPATCH_NOTIFY) { /* Ensure that the device is not already in the list */ Notify = GpeEventInfo->Dispatch.NotifyList; while (Notify) { if (Notify->DeviceNode == DeviceNode) { Status = AE_ALREADY_EXISTS; goto UnlockAndExit; } Notify = Notify->Next; } /* Add this device to the notify list for this GPE */ NewNotify->DeviceNode = DeviceNode; NewNotify->Next = GpeEventInfo->Dispatch.NotifyList; GpeEventInfo->Dispatch.NotifyList = NewNotify; NewNotify = NULL; } /* Mark the GPE as a possible wake event */ GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE; Status = AE_OK; UnlockAndExit: AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); /* Delete the notify object if it was not used above */ if (NewNotify) { ACPI_FREE (NewNotify); } return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiDisableGpe ( ACPI_HANDLE GpeDevice, UINT32 GpeNumber, UINT8 GpeType) { ACPI_STATUS Status = AE_OK; ACPI_GPE_EVENT_INFO *GpeEventInfo; ACPI_CPU_FLAGS Flags; ACPI_FUNCTION_TRACE (AcpiDisableGpe); /* Parameter validation */ if (!GpeType || (GpeType & ~ACPI_GPE_TYPE_WAKE_RUN)) { return_ACPI_STATUS (AE_BAD_PARAMETER); } Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); /* Ensure that we have a valid GPE number */ GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); if (!GpeEventInfo) { Status = AE_BAD_PARAMETER; goto UnlockAndExit; } /* Hardware-disable a runtime GPE on removal of the last reference */ if (GpeType & ACPI_GPE_TYPE_RUNTIME) { if (!GpeEventInfo->RuntimeCount) { Status = AE_LIMIT; /* There are no references to remove */ goto UnlockAndExit; } GpeEventInfo->RuntimeCount--; if (!GpeEventInfo->RuntimeCount) { Status = AcpiEvDisableGpe (GpeEventInfo); if (ACPI_FAILURE (Status)) { GpeEventInfo->RuntimeCount++; goto UnlockAndExit; } } } /* * Update masks for wake GPE on removal of the last reference. * No need to hardware-disable wake GPEs here, they are not currently * enabled. */ if (GpeType & ACPI_GPE_TYPE_WAKE) { if (!GpeEventInfo->WakeupCount) { Status = AE_LIMIT; /* There are no references to remove */ goto UnlockAndExit; } GpeEventInfo->WakeupCount--; if (!GpeEventInfo->WakeupCount) { (void) AcpiEvUpdateGpeEnableMasks (GpeEventInfo); } } UnlockAndExit: AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); return_ACPI_STATUS (Status); }
ACPI_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_STATUS AcpiEnableEvent ( UINT32 Event, UINT32 Type, UINT32 Flags) { ACPI_STATUS Status = AE_OK; UINT32 Value; ACPI_GPE_EVENT_INFO *GpeEventInfo; ACPI_FUNCTION_TRACE ("AcpiEnableEvent"); /* The Type must be either Fixed Event or GPE */ switch (Type) { case ACPI_EVENT_FIXED: /* Decode the Fixed Event */ if (Event > ACPI_EVENT_MAX) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* * Enable the requested fixed event (by writing a one to the * enable register bit) */ Status = AcpiSetRegister (AcpiGbl_FixedEventInfo[Event].EnableRegisterId, 1, ACPI_MTX_LOCK); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Make sure that the hardware responded */ Status = AcpiGetRegister (AcpiGbl_FixedEventInfo[Event].EnableRegisterId, &Value, ACPI_MTX_LOCK); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } if (Value != 1) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not enable %s event\n", AcpiUtGetEventName (Event))); return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE); } break; case ACPI_EVENT_GPE: /* Ensure that we have a valid GPE number */ GpeEventInfo = AcpiEvGetGpeEventInfo (Event); if (!GpeEventInfo) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Enable the requested GPE number */ Status = AcpiHwEnableGpe (GpeEventInfo); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } if (Flags & ACPI_EVENT_WAKE_ENABLE) { AcpiHwEnableGpeForWakeup (GpeEventInfo); } break; default: Status = AE_BAD_PARAMETER; } return_ACPI_STATUS (Status); }