ACPI_STATUS AcpiEvAddGpeReference ( ACPI_GPE_EVENT_INFO *GpeEventInfo) { ACPI_STATUS Status = AE_OK; ACPI_FUNCTION_TRACE (EvAddGpeReference); if (GpeEventInfo->RuntimeCount == ACPI_UINT8_MAX) { return_ACPI_STATUS (AE_LIMIT); } GpeEventInfo->RuntimeCount++; if (GpeEventInfo->RuntimeCount == 1) { /* Enable on first reference */ Status = AcpiEvUpdateGpeEnableMask (GpeEventInfo); if (ACPI_SUCCESS (Status)) { Status = AcpiEvEnableGpe (GpeEventInfo); } if (ACPI_FAILURE (Status)) { GpeEventInfo->RuntimeCount--; } } 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); }
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, UINT32 Flags) { ACPI_STATUS Status = AE_OK; ACPI_GPE_EVENT_INFO *GpeEventInfo; ACPI_FUNCTION_TRACE (AcpiEnableGpe); /* 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; } /* Perform the enable */ Status = AcpiEvEnableGpe (GpeEventInfo, TRUE); UnlockAndExit: if (Flags & ACPI_NOT_ISR) { (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); }
static ACPI_STATUS AcpiEvSaveMethodInfo ( ACPI_HANDLE ObjHandle, UINT32 Level, void *ObjDesc, void **ReturnValue) { ACPI_GPE_BLOCK_INFO *GpeBlock = (void *) ObjDesc; ACPI_GPE_EVENT_INFO *GpeEventInfo; UINT32 GpeNumber; char Name[ACPI_NAME_SIZE + 1]; UINT8 Type; ACPI_STATUS Status; ACPI_FUNCTION_TRACE (EvSaveMethodInfo); /* * _Lxx and _Exx GPE method support * * 1) Extract the name from the object and convert to a string */ ACPI_MOVE_32_TO_32 ( Name, &((ACPI_NAMESPACE_NODE *) ObjHandle)->Name.Integer); Name[ACPI_NAME_SIZE] = 0; /* * 2) Edge/Level determination is based on the 2nd character * of the method name * * NOTE: Default GPE type is RUNTIME. May be changed later to WAKE * if a _PRW object is found that points to this GPE. */ switch (Name[1]) { case 'L': Type = ACPI_GPE_LEVEL_TRIGGERED; break; case 'E': Type = ACPI_GPE_EDGE_TRIGGERED; break; default: /* Unknown method type, just ignore it! */ ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Ignoring unknown GPE method type: %s " "(name not of form _Lxx or _Exx)", Name)); return_ACPI_STATUS (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_LOAD, "Could not extract GPE number from name: %s " "(name is not of form _Lxx or _Exx)", Name)); return_ACPI_STATUS (AE_OK); } /* Ensure that we have a valid GPE number for this GPE block */ if ((GpeNumber < GpeBlock->BlockBaseNumber) || (GpeNumber >= (GpeBlock->BlockBaseNumber + (GpeBlock->RegisterCount * 8)))) { /* * Not valid for this GPE block, just ignore it. However, it may be * valid for a different GPE block, since GPE0 and GPE1 methods both * appear under \_GPE. */ return_ACPI_STATUS (AE_OK); } /* * Now we can add this information to the GpeEventInfo block for use * during dispatch of this GPE. Default type is RUNTIME, although this may * change when the _PRW methods are executed later. */ GpeEventInfo = &GpeBlock->EventInfo[GpeNumber - GpeBlock->BlockBaseNumber]; GpeEventInfo->Flags = (UINT8) (Type | ACPI_GPE_DISPATCH_METHOD | ACPI_GPE_TYPE_RUNTIME); GpeEventInfo->Dispatch.MethodNode = (ACPI_NAMESPACE_NODE *) ObjHandle; /* Update enable mask, but don't enable the HW GPE as of yet */ Status = AcpiEvEnableGpe (GpeEventInfo, FALSE); ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Registered GPE method %s as GPE number 0x%.2X\n", Name, GpeNumber)); return_ACPI_STATUS (Status); }