📄 evgpeblk.c
字号:
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 (ACPI_GET_OBJECT_TYPE (ObjDesc) == 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 (ACPI_GET_OBJECT_TYPE (ObjDesc) == ACPI_TYPE_PACKAGE) { /* Package contains a GPE reference and GPE number within a GPE block */ if ((ObjDesc->Package.Count < 2) || (ACPI_GET_OBJECT_TYPE (ObjDesc->Package.Elements[0]) != ACPI_TYPE_LOCAL_REFERENCE) || (ACPI_GET_OBJECT_TYPE (ObjDesc->Package.Elements[1]) != 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 iff 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);}/******************************************************************************* * * FUNCTION: AcpiEvGetGpeXruptBlock * * PARAMETERS: InterruptNumber - Interrupt for a GPE block * * RETURN: A GPE interrupt block * * DESCRIPTION: Get or Create a GPE interrupt block. There is one interrupt * block per unique interrupt level used for GPEs. * Should be called only when the GPE lists are semaphore locked * and not subject to change. * ******************************************************************************/static ACPI_GPE_XRUPT_INFO *AcpiEvGetGpeXruptBlock ( UINT32 InterruptNumber){ 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) { return_PTR (NextGpeXrupt); } NextGpeXrupt = NextGpeXrupt->Next; } /* Not found, must allocate a new xrupt descriptor */ GpeXrupt = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_XRUPT_INFO)); if (!GpeXrupt) { return_PTR (NULL); } 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_ERROR ((AE_INFO, "Could not install GPE interrupt handler at level 0x%X", InterruptNumber)); return_PTR (NULL); } } return_PTR (GpeXrupt);}/******************************************************************************* * * FUNCTION: AcpiEvDeleteGpeXrupt * * PARAMETERS: GpeXrupt - A GPE interrupt info block * * RETURN: Status * * DESCRIPTION: Remove and free a GpeXrupt block. Remove an associated * interrupt handler if not the SCI interrupt. * ******************************************************************************/static ACPI_STATUSAcpiEvDeleteGpeXrupt ( ACPI_GPE_XRUPT_INFO *GpeXrupt){ ACPI_STATUS Status; ACPI_CPU_FLAGS Flags; ACPI_FUNCTION_TRACE (EvDeleteGpeXrupt); /* We never want to remove the SCI interrupt handler */ if (GpeXrupt->InterruptNumber == AcpiGbl_FADT.SciInterrupt) { GpeXrupt->GpeBlockListHead = NULL; return_ACPI_STATUS (AE_OK); } /* Disable this interrupt */ Status = AcpiOsRemoveInterruptHandler ( GpeXrupt->InterruptNumber, AcpiEvGpeXruptHandler); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Unlink the interrupt block with lock */ Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); if (GpeXrupt->Previous) { GpeXrupt->Previous->Next = GpeXrupt->Next; } else { /* No previous, update list head */ AcpiGbl_GpeXruptListHead = GpeXrupt->Next; } if (GpeXrupt->Next) { GpeXrupt->Next->Previous = GpeXrupt->Previous; } AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); /* Free the block */ ACPI_FREE (GpeXrupt); return_ACPI_STATUS (AE_OK);}/******************************************************************************* * * FUNCTION: AcpiEvInstallGpeBlock * * PARAMETERS: GpeBlock - New GPE block * InterruptNumber - Xrupt to be associated with this GPE block * * RETURN: Status * * DESCRIPTION: Install new GPE block with mutex support * ******************************************************************************/static ACPI_STATUSAcpiEvInstallGpeBlock ( ACPI_GPE_BLOCK_INFO *GpeBlock, UINT32 InterruptNumber){ ACPI_GPE_BLOCK_INFO *NextGpeBlock; ACPI_GPE_XRUPT_INFO *GpeXruptBlock; ACPI_STATUS Status; ACPI_CPU_FLAGS Flags; ACPI_FUNCTION_TRACE (EvInstallGpeBlock); Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } GpeXruptBlock = AcpiEvGetGpeXruptBlock (InterruptNumber); if (!GpeXruptBlock) { Status = AE_NO_MEMORY; goto UnlockAndExit; } /* Install the new block at the end of the list with lock */ Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); if (GpeXruptBlock->GpeBlockListHead) { NextGpeBlock = GpeXruptBlock->GpeBlockListHead; while (NextGpeBlock->Next) { NextGpeBlock = NextGpeBlock->Next; } NextGpeBlock->Next = GpeBlock; GpeBlock->Previous = NextGpeBlock; } else { GpeXruptBlock->GpeBlockListHead = GpeBlock; } GpeBlock->XruptBlock = GpeXruptBlock; AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);UnlockAndExit: Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS); return_ACPI_STATUS (Status);}/******************************************************************************* * * FUNCTION: AcpiEvDeleteGpeBlock * * PARAMETERS: GpeBlock - Existing GPE block * * RETURN: Status * * DESCRIPTION: Remove a GPE block * ******************************************************************************/ACPI_STATUSAcpiEvDeleteGpeBlock ( 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); 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); } /* Free the GpeBlock */ ACPI_FREE (GpeBlock->RegisterInfo); ACPI_FREE (GpeBlock->EventInfo); ACPI_FREE (GpeBlock);UnlockAndExit: Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS); return_ACPI_STATUS (Status);}/******************************************************************************* * * FUNCTION: AcpiEvCreateGpeInfoBlocks * * PARAMETERS: GpeBlock - New GPE block * * RETURN: Status * * DESCRIPTION: Create the RegisterInfo and EventInfo blocks for this GPE block * ******************************************************************************/static ACPI_STATUSAcpiEvCreateGpeInfoBlocks ( ACPI_GPE_BLOCK_INFO *GpeBlock){ ACPI_GPE_REGISTER_INFO *GpeRegisterInfo = NULL; ACPI_GPE_EVENT_INFO *GpeEventInfo = NULL; ACPI_GPE_EVENT_INFO *ThisEvent; ACPI_GPE_REGISTER_INFO *ThisRegister; ACPI_NATIVE_UINT i; ACPI_NATIVE_UINT j; ACPI_STATUS Status; ACPI_FUNCTION_TRACE (EvCreateGpeInfoBlocks); /* Allocate the GPE register information block */ GpeRegisterInfo = ACPI_ALLOCATE_ZEROED ( (ACPI_SIZE) GpeBlock->RegisterCount * sizeof (ACPI_GPE_REGISTER_INFO)); if (!GpeRegisterInfo) { ACPI_ERROR ((AE_INFO, "Could not allocate the GpeRegisterInfo table")); return_ACPI_STATUS (AE_NO_MEMORY); } /* * Allocate the GPE EventInfo block. There are eight distinct GPEs * per register. Initialization to zeros is sufficient. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -