ACPI_STATUS AcpiHwEnableRuntimeGpeBlock ( ACPI_GPE_XRUPT_INFO *GpeXruptInfo, ACPI_GPE_BLOCK_INFO *GpeBlock, void *Context) { UINT32 i; ACPI_STATUS Status; /* NOTE: assumes that all GPEs are currently disabled */ /* Examine each GPE Register within the block */ for (i = 0; i < GpeBlock->RegisterCount; i++) { if (!GpeBlock->RegisterInfo[i].EnableForRun) { continue; } /* Enable all "runtime" GPEs in this register */ Status = AcpiHwWrite (GpeBlock->RegisterInfo[i].EnableForRun, &GpeBlock->RegisterInfo[i].EnableAddress); if (ACPI_FAILURE (Status)) { return (Status); } } return (AE_OK); }
static ACPI_STATUS AcpiHwEnableWakeupGpeBlock ( ACPI_GPE_XRUPT_INFO *GpeXruptInfo, ACPI_GPE_BLOCK_INFO *GpeBlock, void *Context) { UINT32 i; ACPI_STATUS Status; /* Examine each GPE Register within the block */ for (i = 0; i < GpeBlock->RegisterCount; i++) { if (!GpeBlock->RegisterInfo[i].EnableForWake) { continue; } /* Enable all "wake" GPEs in this register */ Status = AcpiHwWrite (GpeBlock->RegisterInfo[i].EnableForWake, &GpeBlock->RegisterInfo[i].EnableAddress); if (ACPI_FAILURE (Status)) { return (Status); } } return (AE_OK); }
ACPI_STATUS AcpiHwClearGpe ( ACPI_GPE_EVENT_INFO *GpeEventInfo) { ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; ACPI_STATUS Status; UINT32 RegisterBit; ACPI_FUNCTION_ENTRY (); /* Get the info block for the entire GPE register */ GpeRegisterInfo = GpeEventInfo->RegisterInfo; if (!GpeRegisterInfo) { return (AE_NOT_EXIST); } /* * Write a one to the appropriate bit in the status register to * clear this GPE. */ RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo); Status = AcpiHwWrite (RegisterBit, &GpeRegisterInfo->StatusAddress); return (Status); }
ACPI_STATUS AcpiHwClearGpeBlock ( ACPI_GPE_XRUPT_INFO *GpeXruptInfo, ACPI_GPE_BLOCK_INFO *GpeBlock, void *Context) { UINT32 i; ACPI_STATUS Status; /* Examine each GPE Register within the block */ for (i = 0; i < GpeBlock->RegisterCount; i++) { /* Clear status on all GPEs in this register */ Status = AcpiHwWrite (0xFF, &GpeBlock->RegisterInfo[i].StatusAddress); if (ACPI_FAILURE (Status)) { return (Status); } } return (AE_OK); }
static ACPI_STATUS AcpiHwGpeEnableWrite ( UINT8 EnableMask, ACPI_GPE_REGISTER_INFO *GpeRegisterInfo) { ACPI_STATUS Status; GpeRegisterInfo->EnableMask = EnableMask; Status = AcpiHwWrite (EnableMask, &GpeRegisterInfo->EnableAddress); return (Status); }
ACPI_STATUS AcpiHwWritePm1Control ( UINT32 Pm1aControl, UINT32 Pm1bControl) { ACPI_STATUS Status; ACPI_FUNCTION_TRACE (HwWritePm1Control); Status = AcpiHwWrite (Pm1aControl, &AcpiGbl_FADT.XPm1aControlBlock); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } if (AcpiGbl_FADT.XPm1bControlBlock.Address) { Status = AcpiHwWrite (Pm1bControl, &AcpiGbl_FADT.XPm1bControlBlock); } return_ACPI_STATUS (Status); }
static ACPI_STATUS AcpiHwWriteMultiple ( UINT32 Value, ACPI_GENERIC_ADDRESS *RegisterA, ACPI_GENERIC_ADDRESS *RegisterB) { ACPI_STATUS Status; /* The first register is always required */ Status = AcpiHwWrite (Value, RegisterA); if (ACPI_FAILURE (Status)) { return (Status); } /* * Second register is optional * * No bit shifting or clearing is necessary, because of how the PM1 * registers are defined in the ACPI specification: * * "Although the bits can be split between the two register blocks (each * register block has a unique pointer within the FADT), the bit positions * are maintained. The register block with unimplemented bits (that is, * those implemented in the other register block) always returns zeros, * and writes have no side effects" */ if (RegisterB->Address) { Status = AcpiHwWrite (Value, RegisterB); } return (Status); }
static ACPI_STATUS AcpiEvCreateGpeInfoBlocks ( 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; UINT32 i; UINT32 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. */ GpeEventInfo = ACPI_ALLOCATE_ZEROED ((ACPI_SIZE) GpeBlock->GpeCount * 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 = (UINT16) (GpeBlock->BlockBaseNumber + (i * ACPI_GPE_REGISTER_WIDTH)); ThisRegister->StatusAddress.Address = GpeBlock->Address + i; ThisRegister->EnableAddress.Address = GpeBlock->Address + i + GpeBlock->RegisterCount; ThisRegister->StatusAddress.SpaceId = GpeBlock->SpaceId; ThisRegister->EnableAddress.SpaceId = GpeBlock->SpaceId; ThisRegister->StatusAddress.BitWidth = ACPI_GPE_REGISTER_WIDTH; ThisRegister->EnableAddress.BitWidth = ACPI_GPE_REGISTER_WIDTH; ThisRegister->StatusAddress.BitOffset = 0; ThisRegister->EnableAddress.BitOffset = 0; /* 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 = AcpiHwWrite (0x00, &ThisRegister->EnableAddress); if (ACPI_FAILURE (Status)) { goto ErrorExit; } /* Clear any pending GPE events within this register */ Status = AcpiHwWrite (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); }
ACPI_STATUS AcpiHwLowSetGpe ( ACPI_GPE_EVENT_INFO *GpeEventInfo, UINT32 Action) { ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; ACPI_STATUS Status; UINT32 EnableMask; UINT32 RegisterBit; ACPI_FUNCTION_ENTRY (); /* Get the info block for the entire GPE register */ GpeRegisterInfo = GpeEventInfo->RegisterInfo; if (!GpeRegisterInfo) { return (AE_NOT_EXIST); } /* Get current value of the enable register that contains this GPE */ Status = AcpiHwRead (&EnableMask, &GpeRegisterInfo->EnableAddress); if (ACPI_FAILURE (Status)) { return (Status); } /* Set or clear just the bit that corresponds to this GPE */ RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo, GpeRegisterInfo); switch (Action) { case ACPI_GPE_CONDITIONAL_ENABLE: /* Only enable if the EnableForRun bit is set */ if (!(RegisterBit & GpeRegisterInfo->EnableForRun)) { return (AE_BAD_PARAMETER); } /*lint -fallthrough */ case ACPI_GPE_ENABLE: ACPI_SET_BIT (EnableMask, RegisterBit); break; case ACPI_GPE_DISABLE: ACPI_CLEAR_BIT (EnableMask, RegisterBit); break; default: ACPI_ERROR ((AE_INFO, "Invalid GPE Action, %u\n", Action)); return (AE_BAD_PARAMETER); } /* Write the updated enable mask */ Status = AcpiHwWrite (EnableMask, &GpeRegisterInfo->EnableAddress); return (Status); }
ACPI_STATUS AcpiHwRegisterWrite ( UINT32 RegisterId, UINT32 Value) { ACPI_STATUS Status; UINT32 ReadValue; ACPI_FUNCTION_TRACE (HwRegisterWrite); switch (RegisterId) { case ACPI_REGISTER_PM1_STATUS: /* PM1 A/B: 16-bit access each */ /* * Handle the "ignored" bit in PM1 Status. According to the ACPI * specification, ignored bits are to be preserved when writing. * Normally, this would mean a read/modify/write sequence. However, * preserving a bit in the status register is different. Writing a * one clears the status, and writing a zero preserves the status. * Therefore, we must always write zero to the ignored bit. * * This behavior is clarified in the ACPI 4.0 specification. */ Value &= ~ACPI_PM1_STATUS_PRESERVED_BITS; Status = AcpiHwWriteMultiple (Value, &AcpiGbl_XPm1aStatus, &AcpiGbl_XPm1bStatus); break; case ACPI_REGISTER_PM1_ENABLE: /* PM1 A/B: 16-bit access each */ Status = AcpiHwWriteMultiple (Value, &AcpiGbl_XPm1aEnable, &AcpiGbl_XPm1bEnable); break; case ACPI_REGISTER_PM1_CONTROL: /* PM1 A/B: 16-bit access each */ /* * Perform a read first to preserve certain bits (per ACPI spec) * Note: This includes SCI_EN, we never want to change this bit */ Status = AcpiHwReadMultiple (&ReadValue, &AcpiGbl_FADT.XPm1aControlBlock, &AcpiGbl_FADT.XPm1bControlBlock); if (ACPI_FAILURE (Status)) { goto Exit; } /* Insert the bits to be preserved */ ACPI_INSERT_BITS (Value, ACPI_PM1_CONTROL_PRESERVED_BITS, ReadValue); /* Now we can write the data */ Status = AcpiHwWriteMultiple (Value, &AcpiGbl_FADT.XPm1aControlBlock, &AcpiGbl_FADT.XPm1bControlBlock); break; case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ /* * For control registers, all reserved bits must be preserved, * as per the ACPI spec. */ Status = AcpiHwRead (&ReadValue, &AcpiGbl_FADT.XPm2ControlBlock); if (ACPI_FAILURE (Status)) { goto Exit; } /* Insert the bits to be preserved */ ACPI_INSERT_BITS (Value, ACPI_PM2_CONTROL_PRESERVED_BITS, ReadValue); Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPm2ControlBlock); break; case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ Status = AcpiHwWrite (Value, &AcpiGbl_FADT.XPmTimerBlock); break; case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ /* SMI_CMD is currently always in IO space */ Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand, Value, 8); break; default: ACPI_ERROR ((AE_INFO, "Unknown Register ID: 0x%X", RegisterId)); Status = AE_BAD_PARAMETER; break; } Exit: return_ACPI_STATUS (Status); }