ACPI_STATUS AcpiEvWalkGpeList ( ACPI_GPE_CALLBACK GpeWalkCallback, void *Context) { ACPI_GPE_BLOCK_INFO *GpeBlock; ACPI_GPE_XRUPT_INFO *GpeXruptInfo; ACPI_STATUS Status = AE_OK; ACPI_CPU_FLAGS Flags; ACPI_FUNCTION_TRACE (EvWalkGpeList); Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); /* Walk the interrupt level descriptor list */ GpeXruptInfo = AcpiGbl_GpeXruptListHead; while (GpeXruptInfo) { /* Walk all Gpe Blocks attached to this interrupt level */ GpeBlock = GpeXruptInfo->GpeBlockListHead; while (GpeBlock) { /* One callback per GPE block */ Status = GpeWalkCallback (GpeXruptInfo, GpeBlock, Context); if (ACPI_FAILURE (Status)) { if (Status == AE_CTRL_END) /* Callback abort */ { Status = AE_OK; } goto UnlockAndExit; } GpeBlock = GpeBlock->Next; } GpeXruptInfo = GpeXruptInfo->Next; } 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 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); }
static UINT32 AcpiEvGlobalLockHandler ( void *Context) { ACPI_STATUS Status; ACPI_CPU_FLAGS Flags; Flags = AcpiOsAcquireLock (AcpiGbl_GlobalLockPendingLock); /* * If a request for the global lock is not actually pending, * we are done. This handles "spurious" global lock interrupts * which are possible (and have been seen) with bad BIOSs. */ if (!AcpiGbl_GlobalLockPending) { goto CleanupAndExit; } /* * Send a unit to the global lock semaphore. The actual acquisition * of the global lock will be performed by the waiting thread. */ Status = AcpiOsSignalSemaphore (AcpiGbl_GlobalLockSemaphore, 1); if (ACPI_FAILURE (Status)) { ACPI_ERROR ((AE_INFO, "Could not signal Global Lock semaphore")); } AcpiGbl_GlobalLockPending = FALSE; CleanupAndExit: AcpiOsReleaseLock (AcpiGbl_GlobalLockPendingLock, Flags); return (ACPI_INTERRUPT_HANDLED); }
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); } else { Status = AE_NO_HANDLER; } } AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); return_ACPI_STATUS (Status); }
UINT32 AcpiEvSciDispatch ( void) { ACPI_SCI_HANDLER_INFO *SciHandler; ACPI_CPU_FLAGS Flags; UINT32 IntStatus = ACPI_INTERRUPT_NOT_HANDLED; ACPI_FUNCTION_NAME (EvSciDispatch); /* Are there any host-installed SCI handlers? */ if (!AcpiGbl_SciHandlerList) { return (IntStatus); } Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); /* Invoke all host-installed SCI handlers */ SciHandler = AcpiGbl_SciHandlerList; while (SciHandler) { /* Invoke the installed handler (at interrupt level) */ IntStatus |= SciHandler->Address ( SciHandler->Context); SciHandler = SciHandler->Next; } AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); return (IntStatus); }
ACPI_STATUS AcpiEvRemoveAllSciHandlers ( void) { ACPI_SCI_HANDLER_INFO *SciHandler; ACPI_CPU_FLAGS Flags; ACPI_STATUS Status; ACPI_FUNCTION_TRACE (EvRemoveAllSciHandlers); /* Just let the OS remove the handler and disable the level */ Status = AcpiOsRemoveInterruptHandler ((UINT32) AcpiGbl_FADT.SciInterrupt, AcpiEvSciXruptHandler); if (!AcpiGbl_SciHandlerList) { return (Status); } Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); /* Free all host-installed SCI handlers */ while (AcpiGbl_SciHandlerList) { SciHandler = AcpiGbl_SciHandlerList; AcpiGbl_SciHandlerList = SciHandler->Next; ACPI_FREE (SciHandler); } AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiHwClearAcpiStatus ( void) { ACPI_STATUS Status; ACPI_CPU_FLAGS LockFlags = 0; ACPI_FUNCTION_TRACE (HwClearAcpiStatus); ACPI_DEBUG_PRINT ((ACPI_DB_IO, "About to write %04X to %8.8X%8.8X\n", ACPI_BITMASK_ALL_FIXED_STATUS, ACPI_FORMAT_UINT64 (AcpiGbl_XPm1aStatus.Address))); LockFlags = AcpiOsAcquireLock (AcpiGbl_HardwareLock); /* Clear the fixed events in PM1 A/B */ Status = AcpiHwRegisterWrite (ACPI_REGISTER_PM1_STATUS, ACPI_BITMASK_ALL_FIXED_STATUS); AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags); if (ACPI_FAILURE (Status)) { goto Exit; } /* Clear the GPE Bits in all GPE registers in all GPE blocks */ Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL); Exit: return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiInstallSciHandler ( ACPI_SCI_HANDLER Address, void *Context) { ACPI_SCI_HANDLER_INFO *NewSciHandler; ACPI_SCI_HANDLER_INFO *SciHandler; ACPI_CPU_FLAGS Flags; ACPI_STATUS Status; ACPI_FUNCTION_TRACE (AcpiInstallSciHandler); if (!Address) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Allocate and init a handler object */ NewSciHandler = ACPI_ALLOCATE (sizeof (ACPI_SCI_HANDLER_INFO)); if (!NewSciHandler) { return_ACPI_STATUS (AE_NO_MEMORY); } NewSciHandler->Address = Address; NewSciHandler->Context = Context; Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); if (ACPI_FAILURE (Status)) { goto Exit; } /* Lock list during installation */ Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); SciHandler = AcpiGbl_SciHandlerList; /* Ensure handler does not already exist */ while (SciHandler) { if (Address == SciHandler->Address) { Status = AE_ALREADY_EXISTS; goto UnlockAndExit; } SciHandler = SciHandler->Next; } /* Install the new handler into the global list (at head) */ NewSciHandler->Next = AcpiGbl_SciHandlerList; AcpiGbl_SciHandlerList = NewSciHandler; UnlockAndExit: AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); Exit: if (ACPI_FAILURE (Status)) { ACPI_FREE (NewSciHandler); } return_ACPI_STATUS (Status); }
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 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); }
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); /* 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 AcpiEvDeleteGpeBlock ( ACPI_GPE_BLOCK_INFO *GpeBlock) { ACPI_STATUS Status; ACPI_CPU_FLAGS Flags; ACPI_FUNCTION_TRACE (EvInstallGpeBlock); Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Disable all GPEs in this block */ Status = AcpiHwDisableGpeBlock (GpeBlock->XruptBlock, GpeBlock, NULL); if (!GpeBlock->Previous && !GpeBlock->Next) { /* This is the last GpeBlock on this interrupt */ Status = AcpiEvDeleteGpeXrupt (GpeBlock->XruptBlock); if (ACPI_FAILURE (Status)) { goto UnlockAndExit; } } else { /* Remove the block on this interrupt with lock */ Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); if (GpeBlock->Previous) { GpeBlock->Previous->Next = GpeBlock->Next; } else { GpeBlock->XruptBlock->GpeBlockListHead = GpeBlock->Next; } if (GpeBlock->Next) { GpeBlock->Next->Previous = GpeBlock->Previous; } AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); } AcpiCurrentGpeCount -= GpeBlock->GpeCount; /* Free the GpeBlock */ ACPI_FREE (GpeBlock->RegisterInfo); ACPI_FREE (GpeBlock->EventInfo); ACPI_FREE (GpeBlock); UnlockAndExit: Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 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 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 AcpiRemoveSciHandler ( ACPI_SCI_HANDLER Address) { ACPI_SCI_HANDLER_INFO *PrevSciHandler; ACPI_SCI_HANDLER_INFO *NextSciHandler; ACPI_CPU_FLAGS Flags; ACPI_STATUS Status; ACPI_FUNCTION_TRACE (AcpiRemoveSciHandler); if (!Address) { return_ACPI_STATUS (AE_BAD_PARAMETER); } Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Remove the SCI handler with lock */ Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); PrevSciHandler = NULL; NextSciHandler = AcpiGbl_SciHandlerList; while (NextSciHandler) { if (NextSciHandler->Address == Address) { /* Unlink and free the SCI handler info block */ if (PrevSciHandler) { PrevSciHandler->Next = NextSciHandler->Next; } else { AcpiGbl_SciHandlerList = NextSciHandler->Next; } AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); ACPI_FREE (NextSciHandler); goto UnlockAndExit; } PrevSciHandler = NextSciHandler; NextSciHandler = NextSciHandler->Next; } AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); Status = AE_NOT_EXIST; UnlockAndExit: (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); 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 AcpiEvAcquireGlobalLock ( UINT16 Timeout) { ACPI_CPU_FLAGS Flags; ACPI_STATUS Status; BOOLEAN Acquired = FALSE; ACPI_FUNCTION_TRACE (EvAcquireGlobalLock); /* * Only one thread can acquire the GL at a time, the GlobalLockMutex * enforces this. This interface releases the interpreter if we must wait. */ Status = AcpiExSystemWaitMutex (AcpiGbl_GlobalLockMutex->Mutex.OsMutex, Timeout); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* * Update the global lock handle and check for wraparound. The handle is * only used for the external global lock interfaces, but it is updated * here to properly handle the case where a single thread may acquire the * lock via both the AML and the AcpiAcquireGlobalLock interfaces. The * handle is therefore updated on the first acquire from a given thread * regardless of where the acquisition request originated. */ AcpiGbl_GlobalLockHandle++; if (AcpiGbl_GlobalLockHandle == 0) { AcpiGbl_GlobalLockHandle = 1; } /* * Make sure that a global lock actually exists. If not, just * treat the lock as a standard mutex. */ if (!AcpiGbl_GlobalLockPresent) { AcpiGbl_GlobalLockAcquired = TRUE; return_ACPI_STATUS (AE_OK); } Flags = AcpiOsAcquireLock (AcpiGbl_GlobalLockPendingLock); do { /* Attempt to acquire the actual hardware lock */ ACPI_ACQUIRE_GLOBAL_LOCK (AcpiGbl_FACS, Acquired); if (Acquired) { AcpiGbl_GlobalLockAcquired = TRUE; ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Acquired hardware Global Lock\n")); break; } /* * Did not get the lock. The pending bit was set above, and * we must now wait until we receive the global lock * released interrupt. */ AcpiGbl_GlobalLockPending = TRUE; AcpiOsReleaseLock (AcpiGbl_GlobalLockPendingLock, Flags); ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Waiting for hardware Global Lock\n")); /* * Wait for handshake with the global lock interrupt handler. * This interface releases the interpreter if we must wait. */ Status = AcpiExSystemWaitSemaphore (AcpiGbl_GlobalLockSemaphore, ACPI_WAIT_FOREVER); Flags = AcpiOsAcquireLock (AcpiGbl_GlobalLockPendingLock); } while (ACPI_SUCCESS (Status)); AcpiGbl_GlobalLockPending = FALSE; AcpiOsReleaseLock (AcpiGbl_GlobalLockPendingLock, Flags); return_ACPI_STATUS (Status); }
UINT32 AcpiEvGpeDetect ( ACPI_GPE_XRUPT_INFO *GpeXruptList) { ACPI_STATUS Status; ACPI_GPE_BLOCK_INFO *GpeBlock; ACPI_NAMESPACE_NODE *GpeDevice; ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; ACPI_GPE_EVENT_INFO *GpeEventInfo; UINT32 GpeNumber; ACPI_GPE_HANDLER_INFO *GpeHandlerInfo; UINT32 IntStatus = ACPI_INTERRUPT_NOT_HANDLED; UINT8 EnabledStatusByte; UINT32 StatusReg; UINT32 EnableReg; ACPI_CPU_FLAGS Flags; UINT32 i; UINT32 j; ACPI_FUNCTION_NAME (EvGpeDetect); /* Check for the case where there are no GPEs */ if (!GpeXruptList) { return (IntStatus); } /* * We need to obtain the GPE lock for both the data structs and registers * Note: Not necessary to obtain the hardware lock, since the GPE * registers are owned by the GpeLock. */ Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); /* Examine all GPE blocks attached to this interrupt level */ GpeBlock = GpeXruptList->GpeBlockListHead; while (GpeBlock) { GpeDevice = GpeBlock->Node; /* * Read all of the 8-bit GPE status and enable registers in this GPE * block, saving all of them. Find all currently active GP events. */ for (i = 0; i < GpeBlock->RegisterCount; i++) { /* Get the next status/enable pair */ GpeRegisterInfo = &GpeBlock->RegisterInfo[i]; /* * Optimization: If there are no GPEs enabled within this * register, we can safely ignore the entire register. */ if (!(GpeRegisterInfo->EnableForRun | GpeRegisterInfo->EnableForWake)) { ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, "Ignore disabled registers for GPE %02X-%02X: " "RunEnable=%02X, WakeEnable=%02X\n", GpeRegisterInfo->BaseGpeNumber, GpeRegisterInfo->BaseGpeNumber + (ACPI_GPE_REGISTER_WIDTH - 1), GpeRegisterInfo->EnableForRun, GpeRegisterInfo->EnableForWake)); continue; } /* Read the Status Register */ Status = AcpiHwRead (&StatusReg, &GpeRegisterInfo->StatusAddress); if (ACPI_FAILURE (Status)) { goto UnlockAndExit; } /* Read the Enable Register */ Status = AcpiHwRead (&EnableReg, &GpeRegisterInfo->EnableAddress); if (ACPI_FAILURE (Status)) { goto UnlockAndExit; } ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, "Read registers for GPE %02X-%02X: Status=%02X, Enable=%02X, " "RunEnable=%02X, WakeEnable=%02X\n", GpeRegisterInfo->BaseGpeNumber, GpeRegisterInfo->BaseGpeNumber + (ACPI_GPE_REGISTER_WIDTH - 1), StatusReg, EnableReg, GpeRegisterInfo->EnableForRun, GpeRegisterInfo->EnableForWake)); /* Check if there is anything active at all in this register */ EnabledStatusByte = (UINT8) (StatusReg & EnableReg); if (!EnabledStatusByte) { /* No active GPEs in this register, move on */ continue; } /* Now look at the individual GPEs in this byte register */ for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { /* Examine one GPE bit */ GpeEventInfo = &GpeBlock->EventInfo[((ACPI_SIZE) i * ACPI_GPE_REGISTER_WIDTH) + j]; GpeNumber = j + GpeRegisterInfo->BaseGpeNumber; if (EnabledStatusByte & (1 << j)) { /* Invoke global event handler if present */ AcpiGpeCount++; if (AcpiGbl_GlobalEventHandler) { AcpiGbl_GlobalEventHandler (ACPI_EVENT_TYPE_GPE, GpeDevice, GpeNumber, AcpiGbl_GlobalEventHandlerContext); } /* Found an active GPE */ if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == ACPI_GPE_DISPATCH_RAW_HANDLER) { /* Dispatch the event to a raw handler */ GpeHandlerInfo = GpeEventInfo->Dispatch.Handler; /* * There is no protection around the namespace node * and the GPE handler to ensure a safe destruction * because: * 1. The namespace node is expected to always * exist after loading a table. * 2. The GPE handler is expected to be flushed by * AcpiOsWaitEventsComplete() before the * destruction. */ AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); IntStatus |= GpeHandlerInfo->Address ( GpeDevice, GpeNumber, GpeHandlerInfo->Context); Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); } else { /* * Dispatch the event to a standard handler or * method. */ IntStatus |= AcpiEvGpeDispatch (GpeDevice, GpeEventInfo, GpeNumber); } } } } GpeBlock = GpeBlock->Next; } UnlockAndExit: AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); return (IntStatus); }
ACPI_STATUS AcpiEvGetGpeXruptBlock ( UINT32 InterruptNumber, ACPI_GPE_XRUPT_INFO **GpeXruptBlock) { ACPI_GPE_XRUPT_INFO *NextGpeXrupt; ACPI_GPE_XRUPT_INFO *GpeXrupt; ACPI_STATUS Status; ACPI_CPU_FLAGS Flags; ACPI_FUNCTION_TRACE (EvGetGpeXruptBlock); /* No need for lock since we are not changing any list elements here */ NextGpeXrupt = AcpiGbl_GpeXruptListHead; while (NextGpeXrupt) { if (NextGpeXrupt->InterruptNumber == InterruptNumber) { *GpeXruptBlock = NextGpeXrupt; return_ACPI_STATUS (AE_OK); } NextGpeXrupt = NextGpeXrupt->Next; } /* Not found, must allocate a new xrupt descriptor */ GpeXrupt = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_XRUPT_INFO)); if (!GpeXrupt) { return_ACPI_STATUS (AE_NO_MEMORY); } GpeXrupt->InterruptNumber = InterruptNumber; /* Install new interrupt descriptor with spin lock */ Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); if (AcpiGbl_GpeXruptListHead) { NextGpeXrupt = AcpiGbl_GpeXruptListHead; while (NextGpeXrupt->Next) { NextGpeXrupt = NextGpeXrupt->Next; } NextGpeXrupt->Next = GpeXrupt; GpeXrupt->Previous = NextGpeXrupt; } else { AcpiGbl_GpeXruptListHead = GpeXrupt; } AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); /* Install new interrupt handler if not SCI_INT */ if (InterruptNumber != AcpiGbl_FADT.SciInterrupt) { Status = AcpiOsInstallInterruptHandler (InterruptNumber, AcpiEvGpeXruptHandler, GpeXrupt); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "Could not install GPE interrupt handler at level 0x%X", InterruptNumber)); return_ACPI_STATUS (Status); } } *GpeXruptBlock = GpeXrupt; return_ACPI_STATUS (AE_OK); }
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); }
UINT32 AcpiEvGpeDetect ( ACPI_GPE_XRUPT_INFO *GpeXruptList) { ACPI_STATUS Status; ACPI_GPE_BLOCK_INFO *GpeBlock; ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; UINT32 IntStatus = ACPI_INTERRUPT_NOT_HANDLED; UINT8 EnabledStatusByte; UINT32 StatusReg; UINT32 EnableReg; ACPI_CPU_FLAGS Flags; UINT32 i; UINT32 j; ACPI_FUNCTION_NAME (EvGpeDetect); /* Check for the case where there are no GPEs */ if (!GpeXruptList) { return (IntStatus); } /* * We need to obtain the GPE lock for both the data structs and registers * Note: Not necessary to obtain the hardware lock, since the GPE * registers are owned by the GpeLock. */ Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); /* Examine all GPE blocks attached to this interrupt level */ GpeBlock = GpeXruptList->GpeBlockListHead; while (GpeBlock) { /* * Read all of the 8-bit GPE status and enable registers in this GPE * block, saving all of them. Find all currently active GP events. */ for (i = 0; i < GpeBlock->RegisterCount; i++) { /* Get the next status/enable pair */ GpeRegisterInfo = &GpeBlock->RegisterInfo[i]; /* * Optimization: If there are no GPEs enabled within this * register, we can safely ignore the entire register. */ if (!(GpeRegisterInfo->EnableForRun | GpeRegisterInfo->EnableForWake)) { ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, "Ignore disabled registers for GPE %02X-%02X: " "RunEnable=%02X, WakeEnable=%02X\n", GpeRegisterInfo->BaseGpeNumber, GpeRegisterInfo->BaseGpeNumber + (ACPI_GPE_REGISTER_WIDTH - 1), GpeRegisterInfo->EnableForRun, GpeRegisterInfo->EnableForWake)); continue; } /* Read the Status Register */ Status = AcpiHwRead (&StatusReg, &GpeRegisterInfo->StatusAddress); if (ACPI_FAILURE (Status)) { goto UnlockAndExit; } /* Read the Enable Register */ Status = AcpiHwRead (&EnableReg, &GpeRegisterInfo->EnableAddress); if (ACPI_FAILURE (Status)) { goto UnlockAndExit; } ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, "Read registers for GPE %02X-%02X: Status=%02X, Enable=%02X, " "RunEnable=%02X, WakeEnable=%02X\n", GpeRegisterInfo->BaseGpeNumber, GpeRegisterInfo->BaseGpeNumber + (ACPI_GPE_REGISTER_WIDTH - 1), StatusReg, EnableReg, GpeRegisterInfo->EnableForRun, GpeRegisterInfo->EnableForWake)); /* Check if there is anything active at all in this register */ EnabledStatusByte = (UINT8) (StatusReg & EnableReg); if (!EnabledStatusByte) { /* No active GPEs in this register, move on */ continue; } /* Now look at the individual GPEs in this byte register */ for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { /* Examine one GPE bit */ if (EnabledStatusByte & (1 << j)) { /* * Found an active GPE. Dispatch the event to a handler * or method. */ IntStatus |= AcpiEvGpeDispatch (GpeBlock->Node, &GpeBlock->EventInfo[((ACPI_SIZE) i * ACPI_GPE_REGISTER_WIDTH) + j], j + GpeRegisterInfo->BaseGpeNumber); } } } GpeBlock = GpeBlock->Next; } UnlockAndExit: AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); return (IntStatus); }
static void AcpiUtUpdateRefCount ( ACPI_OPERAND_OBJECT *Object, UINT32 Action) { UINT16 OriginalCount; UINT16 NewCount = 0; ACPI_CPU_FLAGS LockFlags; ACPI_FUNCTION_NAME (UtUpdateRefCount); if (!Object) { return; } /* * Always get the reference count lock. Note: Interpreter and/or * Namespace is not always locked when this function is called. */ LockFlags = AcpiOsAcquireLock (AcpiGbl_ReferenceCountLock); OriginalCount = Object->Common.ReferenceCount; /* Perform the reference count action (increment, decrement) */ switch (Action) { case REF_INCREMENT: NewCount = OriginalCount + 1; Object->Common.ReferenceCount = NewCount; AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags); /* The current reference count should never be zero here */ if (!OriginalCount) { ACPI_WARNING ((AE_INFO, "Obj %p, Reference Count was zero before increment\n", Object)); } ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Obj %p Type %.2X Refs %.2X [Incremented]\n", Object, Object->Common.Type, NewCount)); break; case REF_DECREMENT: /* The current reference count must be non-zero */ if (OriginalCount) { NewCount = OriginalCount - 1; Object->Common.ReferenceCount = NewCount; } AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags); if (!OriginalCount) { ACPI_WARNING ((AE_INFO, "Obj %p, Reference Count is already zero, cannot decrement\n", Object)); } ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Obj %p Type %.2X Refs %.2X [Decremented]\n", Object, Object->Common.Type, NewCount)); /* Actually delete the object on a reference count of zero */ if (NewCount == 0) { AcpiUtDeleteInternalObj (Object); } break; default: AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags); ACPI_ERROR ((AE_INFO, "Unknown Reference Count action (0x%X)", Action)); return; } /* * Sanity check the reference count, for debug purposes only. * (A deleted object will have a huge reference count) */ if (NewCount > ACPI_MAX_REFERENCE_COUNT) { ACPI_WARNING ((AE_INFO, "Large Reference Count (0x%X) in object %p, Type=0x%.2X", NewCount, Object, Object->Common.Type)); } }
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); }