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 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); }
static ACPI_STATUS AcpiEvMatchPrwAndGpe ( ACPI_HANDLE ObjHandle, UINT32 Level, void *Info, void **ReturnValue) { ACPI_GPE_WALK_INFO *GpeInfo = (void *) Info; ACPI_NAMESPACE_NODE *GpeDevice; ACPI_GPE_BLOCK_INFO *GpeBlock; ACPI_NAMESPACE_NODE *TargetGpeDevice; 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 = AcpiUtEvaluateObject (ObjHandle, METHOD_NAME__PRW, ACPI_BTYPE_PACKAGE, &PkgDesc); if (ACPI_FAILURE (Status)) { /* Ignore all errors from _PRW, we don't want to abort the subsystem */ 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 = GpeInfo->GpeDevice; GpeBlock = GpeInfo->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 = 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; } /* * 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) && (GpeNumber >= GpeBlock->BlockBaseNumber) && (GpeNumber < GpeBlock->BlockBaseNumber + (GpeBlock->RegisterCount * 8))) { GpeEventInfo = &GpeBlock->EventInfo[GpeNumber - GpeBlock->BlockBaseNumber]; /* Mark GPE for WAKE-ONLY but WAKE_DISABLED */ GpeEventInfo->Flags &= ~(ACPI_GPE_WAKE_ENABLED | ACPI_GPE_RUN_ENABLED); Status = AcpiEvSetGpeType (GpeEventInfo, ACPI_GPE_TYPE_WAKE); if (ACPI_FAILURE (Status)) { goto Cleanup; } Status = AcpiEvUpdateGpeEnableMasks (GpeEventInfo, ACPI_GPE_DISABLE); } Cleanup: AcpiUtRemoveReference (PkgDesc); return_ACPI_STATUS (AE_OK); }