📄 evgpeblk.c
字号:
GpeEventInfo = ACPI_ALLOCATE_ZEROED ( ((ACPI_SIZE) GpeBlock->RegisterCount * ACPI_GPE_REGISTER_WIDTH) * sizeof (ACPI_GPE_EVENT_INFO)); if (!GpeEventInfo) { ACPI_ERROR ((AE_INFO, "Could not allocate the GpeEventInfo table")); Status = AE_NO_MEMORY; goto ErrorExit; } /* Save the new Info arrays in the GPE block */ GpeBlock->RegisterInfo = GpeRegisterInfo; GpeBlock->EventInfo = GpeEventInfo; /* * Initialize the GPE Register and Event structures. A goal of these * tables is to hide the fact that there are two separate GPE register sets * in a given GPE hardware block, the status registers occupy the first half, * and the enable registers occupy the second half. */ ThisRegister = GpeRegisterInfo; ThisEvent = GpeEventInfo; for (i = 0; i < GpeBlock->RegisterCount; i++) { /* Init the RegisterInfo for this GPE register (8 GPEs) */ ThisRegister->BaseGpeNumber = (UINT8) (GpeBlock->BlockBaseNumber + (i * ACPI_GPE_REGISTER_WIDTH)); ThisRegister->StatusAddress.Address = GpeBlock->BlockAddress.Address + i; ThisRegister->EnableAddress.Address = GpeBlock->BlockAddress.Address + i + GpeBlock->RegisterCount; ThisRegister->StatusAddress.SpaceId = GpeBlock->BlockAddress.SpaceId; ThisRegister->EnableAddress.SpaceId = GpeBlock->BlockAddress.SpaceId; ThisRegister->StatusAddress.BitWidth = ACPI_GPE_REGISTER_WIDTH; ThisRegister->EnableAddress.BitWidth = ACPI_GPE_REGISTER_WIDTH; ThisRegister->StatusAddress.BitOffset = ACPI_GPE_REGISTER_WIDTH; ThisRegister->EnableAddress.BitOffset = ACPI_GPE_REGISTER_WIDTH; /* Init the EventInfo for each GPE within this register */ for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { ThisEvent->GpeNumber = (UINT8) (ThisRegister->BaseGpeNumber + j); ThisEvent->RegisterInfo = ThisRegister; ThisEvent++; } /* Disable all GPEs within this register */ Status = AcpiHwLowLevelWrite (ACPI_GPE_REGISTER_WIDTH, 0x00, &ThisRegister->EnableAddress); if (ACPI_FAILURE (Status)) { goto ErrorExit; } /* Clear any pending GPE events within this register */ Status = AcpiHwLowLevelWrite (ACPI_GPE_REGISTER_WIDTH, 0xFF, &ThisRegister->StatusAddress); if (ACPI_FAILURE (Status)) { goto ErrorExit; } ThisRegister++; } return_ACPI_STATUS (AE_OK);ErrorExit: if (GpeRegisterInfo) { ACPI_FREE (GpeRegisterInfo); } if (GpeEventInfo) { ACPI_FREE (GpeEventInfo); } return_ACPI_STATUS (Status);}/******************************************************************************* * * FUNCTION: AcpiEvCreateGpeBlock * * PARAMETERS: GpeDevice - Handle to the parent GPE block * GpeBlockAddress - Address and SpaceID * RegisterCount - Number of GPE register pairs in the block * GpeBlockBaseNumber - Starting GPE number for the block * InterruptNumber - H/W interrupt for the block * ReturnGpeBlock - Where the new block descriptor is returned * * RETURN: Status * * DESCRIPTION: Create and Install a block of GPE registers. All GPEs within * the block are disabled at exit. * Note: Assumes namespace is locked. * ******************************************************************************/ACPI_STATUSAcpiEvCreateGpeBlock ( ACPI_NAMESPACE_NODE *GpeDevice, ACPI_GENERIC_ADDRESS *GpeBlockAddress, UINT32 RegisterCount, UINT8 GpeBlockBaseNumber, UINT32 InterruptNumber, ACPI_GPE_BLOCK_INFO **ReturnGpeBlock){ ACPI_STATUS Status; ACPI_GPE_BLOCK_INFO *GpeBlock; ACPI_FUNCTION_TRACE (EvCreateGpeBlock); if (!RegisterCount) { return_ACPI_STATUS (AE_OK); } /* Allocate a new GPE block */ GpeBlock = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_BLOCK_INFO)); if (!GpeBlock) { return_ACPI_STATUS (AE_NO_MEMORY); } /* Initialize the new GPE block */ GpeBlock->Node = GpeDevice; GpeBlock->RegisterCount = RegisterCount; GpeBlock->BlockBaseNumber = GpeBlockBaseNumber; ACPI_MEMCPY (&GpeBlock->BlockAddress, GpeBlockAddress, sizeof (ACPI_GENERIC_ADDRESS)); /* * Create the RegisterInfo and EventInfo sub-structures * Note: disables and clears all GPEs in the block */ Status = AcpiEvCreateGpeInfoBlocks (GpeBlock); if (ACPI_FAILURE (Status)) { ACPI_FREE (GpeBlock); return_ACPI_STATUS (Status); } /* Install the new block in the global lists */ Status = AcpiEvInstallGpeBlock (GpeBlock, InterruptNumber); if (ACPI_FAILURE (Status)) { ACPI_FREE (GpeBlock); return_ACPI_STATUS (Status); } /* Find all GPE methods (_Lxx, _Exx) for this block */ Status = AcpiNsWalkNamespace (ACPI_TYPE_METHOD, GpeDevice, ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, AcpiEvSaveMethodInfo, GpeBlock, NULL); /* Return the new block */ if (ReturnGpeBlock) { (*ReturnGpeBlock) = GpeBlock; } ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n", (UINT32) GpeBlock->BlockBaseNumber, (UINT32) (GpeBlock->BlockBaseNumber + ((GpeBlock->RegisterCount * ACPI_GPE_REGISTER_WIDTH) -1)), GpeDevice->Name.Ascii, GpeBlock->RegisterCount, InterruptNumber)); return_ACPI_STATUS (AE_OK);}/******************************************************************************* * * FUNCTION: AcpiEvInitializeGpeBlock * * PARAMETERS: GpeDevice - Handle to the parent GPE block * GpeBlock - Gpe Block info * * RETURN: Status * * DESCRIPTION: Initialize and enable a GPE block. First find and run any * _PRT methods associated with the block, then enable the * appropriate GPEs. * Note: Assumes namespace is locked. * ******************************************************************************/ACPI_STATUSAcpiEvInitializeGpeBlock ( ACPI_NAMESPACE_NODE *GpeDevice, ACPI_GPE_BLOCK_INFO *GpeBlock){ ACPI_STATUS Status; ACPI_GPE_EVENT_INFO *GpeEventInfo; ACPI_GPE_WALK_INFO GpeInfo; UINT32 WakeGpeCount; UINT32 GpeEnabledCount; ACPI_NATIVE_UINT i; ACPI_NATIVE_UINT j; ACPI_FUNCTION_TRACE (EvInitializeGpeBlock); /* Ignore a null GPE block (e.g., if no GPE block 1 exists) */ if (!GpeBlock) { return_ACPI_STATUS (AE_OK); } /* * Runtime option: Should wake GPEs be enabled at runtime? The default * is no, they should only be enabled just as the machine goes to sleep. */ if (AcpiGbl_LeaveWakeGpesDisabled) { /* * Differentiate runtime vs wake GPEs, via the _PRW control methods. * Each GPE that has one or more _PRWs that reference it is by * definition a wake GPE and will not be enabled while the machine * is running. */ GpeInfo.GpeBlock = GpeBlock; GpeInfo.GpeDevice = GpeDevice; Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, AcpiEvMatchPrwAndGpe, &GpeInfo, NULL); } /* * Enable all GPEs in this block that have these attributes: * 1) are "runtime" or "run/wake" GPEs, and * 2) have a corresponding _Lxx or _Exx method * * Any other GPEs within this block must be enabled via the AcpiEnableGpe() * external interface. */ WakeGpeCount = 0; GpeEnabledCount = 0; for (i = 0; i < GpeBlock->RegisterCount; i++) { for (j = 0; j < 8; j++) { /* Get the info block for this particular GPE */ GpeEventInfo = &GpeBlock->EventInfo[(i * ACPI_GPE_REGISTER_WIDTH) + j]; if (((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_METHOD) && (GpeEventInfo->Flags & ACPI_GPE_TYPE_RUNTIME)) { GpeEnabledCount++; } if (GpeEventInfo->Flags & ACPI_GPE_TYPE_WAKE) { WakeGpeCount++; } } } ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "Found %u Wake, Enabled %u Runtime GPEs in this block\n", WakeGpeCount, GpeEnabledCount)); /* Enable all valid runtime GPEs found above */ Status = AcpiHwEnableRuntimeGpeBlock (NULL, GpeBlock); if (ACPI_FAILURE (Status)) { ACPI_ERROR ((AE_INFO, "Could not enable GPEs in GpeBlock %p", GpeBlock)); } return_ACPI_STATUS (Status);}/******************************************************************************* * * FUNCTION: AcpiEvGpeInitialize * * PARAMETERS: None * * RETURN: Status * * DESCRIPTION: Initialize the GPE data structures * ******************************************************************************/ACPI_STATUSAcpiEvGpeInitialize ( void){ UINT32 RegisterCount0 = 0; UINT32 RegisterCount1 = 0; UINT32 GpeNumberMax = 0; ACPI_STATUS Status; ACPI_FUNCTION_TRACE (EvGpeInitialize); Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* * Initialize the GPE Block(s) defined in the FADT * * Why the GPE register block lengths are divided by 2: From the ACPI Spec, * section "General-Purpose Event Registers", we have: * * "Each register block contains two registers of equal length * GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the * GPE0_STS and GPE0_EN registers is equal to half the GPE0_LEN * The length of the GPE1_STS and GPE1_EN registers is equal to * half the GPE1_LEN. If a generic register block is not supported * then its respective block pointer and block length values in the * FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need * to be the same size." */ /* * Determine the maximum GPE number for this machine. * * Note: both GPE0 and GPE1 are optional, and either can exist without * the other. * * If EITHER the register length OR the block address are zero, then that * particular block is not supported. */ if (AcpiGbl_FADT.Gpe0BlockLength && AcpiGbl_FADT.XGpe0Block.Address) { /* GPE block 0 exists (has both length and address > 0) */ RegisterCount0 = (UINT16) (AcpiGbl_FADT.Gpe0BlockLength / 2); GpeNumberMax = (RegisterCount0 * ACPI_GPE_REGISTER_WIDTH) - 1; /* Install GPE Block 0 */ Status = AcpiEvCreateGpeBlock (AcpiGbl_FadtGpeDevice, &AcpiGbl_FADT.XGpe0Block, RegisterCount0, 0, AcpiGbl_FADT.SciInterrupt, &AcpiGbl_GpeFadtBlocks[0]); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "Could not create GPE Block 0")); } } if (AcpiGbl_FADT.Gpe1BlockLength && AcpiGbl_FADT.XGpe1Block.Address) { /* GPE block 1 exists (has both length and address > 0) */ RegisterCount1 = (UINT16) (AcpiGbl_FADT.Gpe1BlockLength / 2); /* Check for GPE0/GPE1 overlap (if both banks exist) */ if ((RegisterCount0) && (GpeNumberMax >= AcpiGbl_FADT.Gpe1Base)) { ACPI_ERROR ((AE_INFO, "GPE0 block (GPE 0 to %d) overlaps the GPE1 block (GPE %d to %d) - Ignoring GPE1", GpeNumberMax, AcpiGbl_FADT.Gpe1Base, AcpiGbl_FADT.Gpe1Base + ((RegisterCount1 * ACPI_GPE_REGISTER_WIDTH) - 1))); /* Ignore GPE1 block by setting the register count to zero */ RegisterCount1 = 0; } else { /* Install GPE Block 1 */ Status = AcpiEvCreateGpeBlock (AcpiGbl_FadtGpeDevice, &AcpiGbl_FADT.XGpe1Block, RegisterCount1, AcpiGbl_FADT.Gpe1Base, AcpiGbl_FADT.SciInterrupt, &AcpiGbl_GpeFadtBlocks[1]); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "Could not create GPE Block 1")); } /* * GPE0 and GPE1 do not have to be contiguous in the GPE number * space. However, GPE0 always starts at GPE number zero. */ GpeNumberMax = AcpiGbl_FADT.Gpe1Base + ((RegisterCount1 * ACPI_GPE_REGISTER_WIDTH) - 1); } } /* Exit if there are no GPE registers */ if ((RegisterCount0 + RegisterCount1) == 0) { /* GPEs are not required by ACPI, this is OK */ ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "There are no GPE blocks defined in the FADT\n")); Status = AE_OK; goto Cleanup; } /* Check for Max GPE number out-of-range */ if (GpeNumberMax > ACPI_GPE_MAX) { ACPI_ERROR ((AE_INFO, "Maximum GPE number from FADT is too large: 0x%X", GpeNumberMax)); Status = AE_BAD_VALUE; goto Cleanup; }Cleanup: (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (AE_OK);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -