ACPI_STATUS AcpiInstallGpeBlock ( ACPI_HANDLE GpeDevice, ACPI_GENERIC_ADDRESS *GpeBlockAddress, UINT32 RegisterCount, UINT32 InterruptNumber) { ACPI_STATUS Status; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_NAMESPACE_NODE *Node; ACPI_GPE_BLOCK_INFO *GpeBlock; ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock); if ((!GpeDevice) || (!GpeBlockAddress) || (!RegisterCount)) { return_ACPI_STATUS (AE_BAD_PARAMETER); } Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } Node = AcpiNsValidateHandle (GpeDevice); if (!Node) { Status = AE_BAD_PARAMETER; goto UnlockAndExit; } /* Validate the parent device */ if (Node->Type != ACPI_TYPE_DEVICE) { Status = AE_TYPE; goto UnlockAndExit; } if (Node->Object) { Status = AE_ALREADY_EXISTS; goto UnlockAndExit; } /* * For user-installed GPE Block Devices, the GpeBlockBaseNumber * is always zero */ Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress->Address, GpeBlockAddress->SpaceId, RegisterCount, 0, InterruptNumber, &GpeBlock); if (ACPI_FAILURE (Status)) { goto UnlockAndExit; } /* Install block in the DeviceObject attached to the node */ ObjDesc = AcpiNsGetAttachedObject (Node); if (!ObjDesc) { /* * No object, create a new one (Device nodes do not always have * an attached object) */ ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE); if (!ObjDesc) { Status = AE_NO_MEMORY; goto UnlockAndExit; } Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE); /* Remove local reference to the object */ AcpiUtRemoveReference (ObjDesc); if (ACPI_FAILURE (Status)) { goto UnlockAndExit; } } /* Now install the GPE block in the DeviceObject */ ObjDesc->Device.GpeBlock = GpeBlock; UnlockAndExit: (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiEvGpeInitialize ( void) { UINT32 RegisterCount0 = 0; UINT32 RegisterCount1 = 0; UINT32 GpeNumberMax = 0; ACPI_STATUS Status; ACPI_FUNCTION_TRACE (EvGpeInitialize); ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "Initializing General Purpose Events (GPEs):\n")); 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 %u) overlaps the GPE1 block " "(GPE %u to %u) - 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; } Cleanup: (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (AE_OK); }