/** * Restores the context of a 'conditional' PCI device. * * This traverses the provided register list restoring PCI registers when appropriate. * * @param[in] StdHeader AMD standard header config param. * @param[in] Device 'conditional' PCI device to restore. * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or * AMD_S3LATE_RESTORE. * @param[in,out] OrMask Current buffer pointer of raw register values. * */ VOID RestoreConditionalPciDevice ( IN AMD_CONFIG_PARAMS *StdHeader, IN CONDITIONAL_PCI_DEVICE_DESCRIPTOR *Device, IN CALL_POINTS CallPoint, IN OUT VOID **OrMask ) { UINT8 RegSizeInBytes; UINT8 SpecialCaseIndex; UINT8 *IntermediatePtr; UINT8 BootMode; UINT16 i; UINT32 Socket; UINT32 Module; UINT32 RegValueRead; UINT32 RegValueWrite; UINT32 AndMask; ACCESS_WIDTH AccessWidth; AGESA_STATUS IgnoredSts; PCI_ADDR PciAddress; CPCI_REGISTER_BLOCK_HEADER *RegisterHdr; GetSocketModuleOfNode ((UINT32) Device->Node, &Socket, &Module, StdHeader); GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredSts); if (CallPoint == INIT_RESUME) { MemFS3GetCPciDeviceRegisterList (Device, &RegisterHdr, StdHeader); } else { S3GetCPciDeviceRegisterList (Device, &RegisterHdr, StdHeader); } BootMode = S3_RESUME_MODE; if (StdHeader->Func == AMD_INIT_POST) { BootMode = RESTORE_TRAINING_MODE | CAPSULE_REBOOT_MODE; } for (i = 0; i < RegisterHdr->NumRegisters; i++) { if (((Device->Mask1 & RegisterHdr->RegisterList[i].Mask1) != 0) && ((Device->Mask2 & RegisterHdr->RegisterList[i].Mask2) != 0)) { PciAddress.Address.Function = RegisterHdr->RegisterList[i].Function; PciAddress.Address.Register = RegisterHdr->RegisterList[i].Offset; RegSizeInBytes = RegisterHdr->RegisterList[i].Type.RegisterSize; switch (RegSizeInBytes) { case 1: AndMask = 0xFFFFFFFF & ((UINT8) RegisterHdr->RegisterList[i].AndMask); RegValueWrite = **(UINT8 **)OrMask; AccessWidth = AccessS3SaveWidth8; break; case 2: AndMask = 0xFFFFFFFF & ((UINT16) RegisterHdr->RegisterList[i].AndMask); RegValueWrite = **(UINT16 **)OrMask; AccessWidth = AccessS3SaveWidth16; break; case 3: // In this case, we don't need to restore a register. We just need to call a special // function to do certain things in the save and resume sequence. // This should not be used in a non-special case. AndMask = 0; RegValueWrite = 0; RegSizeInBytes = 0; AccessWidth = 0; break; default: AndMask = RegisterHdr->RegisterList[i].AndMask; RegSizeInBytes = 4; RegValueWrite = **(UINT32 **)OrMask; AccessWidth = AccessS3SaveWidth32; break; } if ((RegisterHdr->RegisterList[i].BootMode == 0) || ((BootMode & RegisterHdr->RegisterList[i].BootMode) != 0)) { // Do not restore the register if not in the right boot mode // Pointer to the saved data buffer still needs to be adjusted as data will be saved regardless of boot mode if (RegisterHdr->RegisterList[i].Type.SpecialCaseFlag == 0) { LibAmdPciRead (AccessWidth, PciAddress, &RegValueRead, StdHeader); RegValueWrite |= RegValueRead & (~AndMask); LibAmdPciWrite (AccessWidth, PciAddress, &RegValueWrite, StdHeader); } else { SpecialCaseIndex = RegisterHdr->RegisterList[i].Type.SpecialCaseIndex; if (AndMask != 0) { RegisterHdr->SpecialCases[SpecialCaseIndex].Save (AccessWidth, PciAddress, &RegValueRead, StdHeader); RegValueWrite |= RegValueRead & (~AndMask); } RegisterHdr->SpecialCases[SpecialCaseIndex].Restore (AccessWidth, PciAddress, &RegValueWrite, StdHeader); } IDS_OPTION_HOOK (IDS_AFTER_RESTORING_PCI_REG, RegisterHdr, StdHeader); } IntermediatePtr = (UINT8 *) *OrMask; *OrMask = &IntermediatePtr[RegSizeInBytes]; if ((RegSizeInBytes == 0) && (RegValueWrite == RESTART_FROM_BEGINNING_LIST)) { // Restart from the beginning of the register list i = 0xFFFF; } } } }
/** * Saves the context of a 'conditional' PCI device. * * This traverses the provided register list saving PCI registers when appropriate. * * @param[in] StdHeader AMD standard header config param. * @param[in] Device 'conditional' PCI device to restore. * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or * AMD_S3LATE_RESTORE. * @param[in,out] OrMask Current buffer pointer of raw register values. * */ VOID SaveConditionalPciDevice ( IN AMD_CONFIG_PARAMS *StdHeader, IN CONDITIONAL_PCI_DEVICE_DESCRIPTOR *Device, IN CALL_POINTS CallPoint, IN OUT VOID **OrMask ) { UINT8 RegSizeInBytes; UINT8 SpecialCaseIndex; UINT8 *IntermediatePtr; UINT16 i; UINT32 Socket; UINT32 Module; UINT32 AndMask; ACCESS_WIDTH AccessWidth; AGESA_STATUS IgnoredSts; PCI_ADDR PciAddress; CPCI_REGISTER_BLOCK_HEADER *RegisterHdr; GetSocketModuleOfNode ((UINT32) Device->Node, &Socket, &Module, StdHeader); GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredSts); if (CallPoint == INIT_RESUME) { MemFS3GetCPciDeviceRegisterList (Device, &RegisterHdr, StdHeader); } else { S3GetCPciDeviceRegisterList (Device, &RegisterHdr, StdHeader); } for (i = 0; i < RegisterHdr->NumRegisters; i++) { if (((Device->Mask1 & RegisterHdr->RegisterList[i].Mask1) != 0) && ((Device->Mask2 & RegisterHdr->RegisterList[i].Mask2) != 0)) { PciAddress.Address.Function = RegisterHdr->RegisterList[i].Function; PciAddress.Address.Register = RegisterHdr->RegisterList[i].Offset; RegSizeInBytes = RegisterHdr->RegisterList[i].Type.RegisterSize; switch (RegSizeInBytes) { case 1: AndMask = 0xFFFFFFFF & ((UINT8) RegisterHdr->RegisterList[i].AndMask); AccessWidth = AccessS3SaveWidth8; break; case 2: AndMask = 0xFFFFFFFF & ((UINT16) RegisterHdr->RegisterList[i].AndMask); AccessWidth = AccessS3SaveWidth16; break; case 3: // In this case, we don't need to save a register. We just need to call a special // function to do certain things in the save and resume sequence. // This should not be used in a non-special case. AndMask = 0; RegSizeInBytes = 0; AccessWidth = 0; break; default: AndMask = RegisterHdr->RegisterList[i].AndMask; RegSizeInBytes = 4; AccessWidth = AccessS3SaveWidth32; break; } if (RegisterHdr->RegisterList[i].Type.SpecialCaseFlag == 0) { ASSERT ((AndMask != 0) && (RegSizeInBytes != 0) && (AccessWidth != 0)); LibAmdPciRead (AccessWidth, PciAddress, *OrMask, StdHeader); } else { SpecialCaseIndex = RegisterHdr->RegisterList[i].Type.SpecialCaseIndex; RegisterHdr->SpecialCases[SpecialCaseIndex].Save (AccessWidth, PciAddress, *OrMask, StdHeader); } if (AndMask != 0) { // If AndMask is 0, then it is a not-care. Don't need to apply it to the OrMask **((UINT32 **) OrMask) &= AndMask; } if ((RegSizeInBytes == 0) && (**((UINT32 **) OrMask) == RESTART_FROM_BEGINNING_LIST)) { // Restart from the beginning of the register list i = 0xFFFF; } IntermediatePtr = (UINT8 *) *OrMask; *OrMask = &IntermediatePtr[RegSizeInBytes]; // += RegSizeInBytes; } } }
/** * Determines the maximum amount of space required to store all raw register * values for the given device list. * * This traverses the entire device list, and calculates the worst case size * of each device in the device list. * * @param[in] DeviceList Beginning of the device list. * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or * AMD_S3LATE_RESTORE. * @param[in] StdHeader AMD standard header config param. * * @retval Size in bytes required for storing all registers. */ UINT32 GetWorstCaseContextSize ( IN DEVICE_BLOCK_HEADER *DeviceList, IN CALL_POINTS CallPoint, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 WorstCaseSize; DEVICE_DESCRIPTORS Device; UINT16 i; REGISTER_BLOCK_HEADERS RegisterHdr; WorstCaseSize = DeviceList->RelativeOrMaskOffset; Device.CommonDeviceHeader = (DEVICE_DESCRIPTOR *) &DeviceList[1]; // Process Device List for (i = 0; i < DeviceList->NumDevices; i++) { switch (Device.CommonDeviceHeader->Type) { case DEV_TYPE_PCI_PRE_ESR: // PRE_ESR and post ESR take the same amount of space case DEV_TYPE_PCI: if (CallPoint == INIT_RESUME) { MemFS3GetPciDeviceRegisterList (Device.PciDevice, &RegisterHdr.PciRegisters, StdHeader); } else { S3GetPciDeviceRegisterList (Device.PciDevice, &RegisterHdr.PciRegisters, StdHeader); } WorstCaseSize += (RegisterHdr.PciRegisters->NumRegisters * 4); Device.PciDevice++; break; case DEV_TYPE_CPCI_PRE_ESR: // PRE_ESR and post ESR take the same amount of space case DEV_TYPE_CPCI: if (CallPoint == INIT_RESUME) { MemFS3GetCPciDeviceRegisterList (Device.CPciDevice, &RegisterHdr.CPciRegisters, StdHeader); } else { S3GetCPciDeviceRegisterList (Device.CPciDevice, &RegisterHdr.CPciRegisters, StdHeader); } WorstCaseSize += (RegisterHdr.CPciRegisters->NumRegisters * 4); Device.CPciDevice++; break; case DEV_TYPE_MSR_PRE_ESR: // PRE_ESR and post ESR take the same amount of space case DEV_TYPE_MSR: if (CallPoint == INIT_RESUME) { MemFS3GetMsrDeviceRegisterList (Device.MsrDevice, &RegisterHdr.MsrRegisters, StdHeader); } else { S3GetMsrDeviceRegisterList (Device.MsrDevice, &RegisterHdr.MsrRegisters, StdHeader); } WorstCaseSize += (RegisterHdr.MsrRegisters->NumRegisters * 8); Device.MsrDevice++; break; case DEV_TYPE_CMSR_PRE_ESR: // PRE_ESR and post ESR take the same amount of space case DEV_TYPE_CMSR: if (CallPoint == INIT_RESUME) { MemFS3GetCMsrDeviceRegisterList (Device.CMsrDevice, &RegisterHdr.CMsrRegisters, StdHeader); } else { S3GetCMsrDeviceRegisterList (Device.CMsrDevice, &RegisterHdr.CMsrRegisters, StdHeader); } WorstCaseSize += (RegisterHdr.CMsrRegisters->NumRegisters * 8); Device.CMsrDevice++; break; default: ASSERT (FALSE); } } return (WorstCaseSize); }
/** * Restores the context of a 'conditional' PCI device. * * This traverses the provided register list restoring PCI registers when appropriate. * * @param[in] StdHeader AMD standard header config param. * @param[in] Device 'conditional' PCI device to restore. * @param[in] CallPoint Indicates whether this is AMD_INIT_RESUME or * AMD_S3LATE_RESTORE. * @param[in,out] OrMask Current buffer pointer of raw register values. * */ VOID RestoreConditionalPciDevice ( IN AMD_CONFIG_PARAMS *StdHeader, IN CONDITIONAL_PCI_DEVICE_DESCRIPTOR *Device, IN CALL_POINTS CallPoint, IN OUT VOID **OrMask ) { UINT8 RegSizeInBytes; UINT8 SpecialCaseIndex; UINT8 *IntermediatePtr; UINT16 i; UINT32 Socket; UINT32 Module; UINT32 RegValueRead; UINT32 RegValueWrite; UINT32 AndMask; ACCESS_WIDTH AccessWidth; AGESA_STATUS IgnoredSts; PCI_ADDR PciAddress; CPCI_REGISTER_BLOCK_HEADER *RegisterHdr; GetSocketModuleOfNode ((UINT32) Device->Node, &Socket, &Module, StdHeader); GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredSts); if (CallPoint == INIT_RESUME) { MemFS3GetCPciDeviceRegisterList (Device, &RegisterHdr, StdHeader); } else { S3GetCPciDeviceRegisterList (Device, &RegisterHdr, StdHeader); } for (i = 0; i < RegisterHdr->NumRegisters; i++) { if (((Device->Mask1 & RegisterHdr->RegisterList[i].Mask1) != 0) && ((Device->Mask2 & RegisterHdr->RegisterList[i].Mask2) != 0)) { PciAddress.Address.Function = RegisterHdr->RegisterList[i].Function; PciAddress.Address.Register = RegisterHdr->RegisterList[i].Offset; RegSizeInBytes = RegisterHdr->RegisterList[i].Type.RegisterSize; switch (RegSizeInBytes) { case 1: AndMask = 0xFFFFFFFF & ((UINT8) RegisterHdr->RegisterList[i].AndMask); RegValueWrite = **(UINT8 **)OrMask; AccessWidth = AccessS3SaveWidth8; break; case 2: AndMask = 0xFFFFFFFF & ((UINT16) RegisterHdr->RegisterList[i].AndMask); RegValueWrite = **(UINT16 **)OrMask; AccessWidth = AccessS3SaveWidth16; break; default: AndMask = RegisterHdr->RegisterList[i].AndMask; RegSizeInBytes = 4; RegValueWrite = **(UINT32 **)OrMask; AccessWidth = AccessS3SaveWidth32; break; } if (RegisterHdr->RegisterList[i].Type.SpecialCaseFlag == 0) { LibAmdPciRead (AccessWidth, PciAddress, &RegValueRead, StdHeader); RegValueWrite |= RegValueRead & (~AndMask); LibAmdPciWrite (AccessWidth, PciAddress, &RegValueWrite, StdHeader); } else { SpecialCaseIndex = RegisterHdr->RegisterList[i].Type.SpecialCaseIndex; RegisterHdr->SpecialCases[SpecialCaseIndex].Save (AccessWidth, PciAddress, &RegValueRead, StdHeader); RegValueWrite |= RegValueRead & (~AndMask); RegisterHdr->SpecialCases[SpecialCaseIndex].Restore (AccessWidth, PciAddress, &RegValueWrite, StdHeader); } IntermediatePtr = (UINT8 *) *OrMask; *OrMask = &IntermediatePtr[RegSizeInBytes]; } } }