Esempio n. 1
0
/**
 * Restores the context of a PCI device.
 *
 * This traverses the provided register list restoring PCI registers.
 *
 * @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
RestorePciDevice (
  IN       AMD_CONFIG_PARAMS     *StdHeader,
  IN       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  AndMask;
  UINT32  RegValueRead;
  UINT32  RegValueWrite;
  ACCESS_WIDTH AccessWidth;
  AGESA_STATUS IgnoredSts;
  PCI_ADDR PciAddress;
  PCI_REGISTER_BLOCK_HEADER *RegisterHdr;

  GetSocketModuleOfNode ((UINT32) Device->Node,
                               &Socket,
                               &Module,
                               StdHeader);
  GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredSts);

  if (CallPoint == INIT_RESUME) {
    MemFS3GetPciDeviceRegisterList (Device, &RegisterHdr, StdHeader);
  } else {
    S3GetPciDeviceRegisterList (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++) {
    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) {
        ASSERT ((AndMask != 0) && (RegSizeInBytes != 0) && (AccessWidth != 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]; // += RegSizeInBytes;
    if ((RegSizeInBytes == 0) && (RegValueWrite == RESTART_FROM_BEGINNING_LIST)) {
      // Restart from the beginning of the register list
      i = 0xFFFF;
    }
  }
}
Esempio n. 2
0
/**
 * Saves the context of a PCI device.
 *
 * This traverses the provided register list saving PCI registers.
 *
 * @param[in]     StdHeader      AMD standard header config param.
 * @param[in]     Device         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
SavePciDevice (
  IN       AMD_CONFIG_PARAMS     *StdHeader,
  IN       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;
  PCI_REGISTER_BLOCK_HEADER *RegisterHdr;

  GetSocketModuleOfNode ((UINT32) Device->Node,
                               &Socket,
                               &Module,
                               StdHeader);
  GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredSts);

  if (CallPoint == INIT_RESUME) {
    MemFS3GetPciDeviceRegisterList (Device, &RegisterHdr, StdHeader);
  } else {
    S3GetPciDeviceRegisterList (Device, &RegisterHdr, StdHeader);
  }

  for (i = 0; i < RegisterHdr->NumRegisters; i++) {
    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;
  }
}
Esempio n. 3
0
/**
 * 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);
}
Esempio n. 4
0
File: S3.c Progetto: Godkey/coreboot
/**
 * Restores the context of a PCI device.
 *
 * This traverses the provided register list restoring PCI registers.
 *
 * @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
RestorePciDevice (
  IN       AMD_CONFIG_PARAMS     *StdHeader,
  IN       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;
  UINT32  RegValueRead;
  UINT32  RegValueWrite;
  ACCESS_WIDTH AccessWidth;
  AGESA_STATUS IgnoredSts;
  PCI_ADDR PciAddress;
  PCI_REGISTER_BLOCK_HEADER *RegisterHdr;

  GetSocketModuleOfNode ((UINT32) Device->Node,
                               &Socket,
                               &Module,
                               StdHeader);
  GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredSts);

  if (CallPoint == INIT_RESUME) {
    MemFS3GetPciDeviceRegisterList (Device, &RegisterHdr, StdHeader);
  } else {
    S3GetPciDeviceRegisterList (Device, &RegisterHdr, StdHeader);
  }

  for (i = 0; i < RegisterHdr->NumRegisters; i++) {
    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]; // += RegSizeInBytes;
  }
}