556 lines
18 KiB
C
556 lines
18 KiB
C
/** @file
|
|
Mailbox Library.
|
|
|
|
@copyright
|
|
INTEL CONFIDENTIAL
|
|
Copyright 2014 - 2020 Intel Corporation.
|
|
|
|
The source code contained or described herein and all documents related to the
|
|
source code ("Material") are owned by Intel Corporation or its suppliers or
|
|
licensors. Title to the Material remains with Intel Corporation or its suppliers
|
|
and licensors. The Material may contain trade secrets and proprietary and
|
|
confidential information of Intel Corporation and its suppliers and licensors,
|
|
and is protected by worldwide copyright and trade secret laws and treaty
|
|
provisions. No part of the Material may be used, copied, reproduced, modified,
|
|
published, uploaded, posted, transmitted, distributed, or disclosed in any way
|
|
without Intel's prior express written permission.
|
|
|
|
No license under any patent, copyright, trade secret or other intellectual
|
|
property right is granted to or conferred upon you by disclosure or delivery
|
|
of the Materials, either expressly, by implication, inducement, estoppel or
|
|
otherwise. Any license under such intellectual property rights must be
|
|
express and approved by Intel in writing.
|
|
|
|
Unless otherwise agreed by Intel in writing, you may not remove or alter
|
|
this notice or any other notice embedded in Materials by Intel or
|
|
Intel's suppliers or licensors in any way.
|
|
|
|
This file contains an 'Intel Peripheral Driver' and is uniquely identified as
|
|
"Intel Reference Module" and is licensed for Intel CPUs and chipsets under
|
|
the terms of your license agreement with Intel or your vendor. This file may
|
|
be modified by the user, subject to additional terms of the license agreement.
|
|
|
|
@par Specification Reference:
|
|
**/
|
|
#include <Uefi.h>
|
|
#include <Library/BaseLib.h>
|
|
#include <Library/CpuLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/IoLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/CpuMailboxLib.h>
|
|
#include <Library/PciSegmentLib.h>
|
|
#include <Library/TimerLib.h>
|
|
#include <Library/CpuCommonLib.h>
|
|
#include <Register/SaRegsHostBridge.h>
|
|
|
|
/**
|
|
Generic Mailbox function for mailbox write commands. This function will
|
|
poll the mailbox interface for control, issue the write request, poll
|
|
for completion, and verify the write was succussful.
|
|
|
|
@param[in] MailboxType
|
|
@param[in] MailboxCommand
|
|
@param[in] MailboxData
|
|
@param[out] *MailboxStatus
|
|
|
|
@retval EFI_STATUS
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
MailboxWrite (
|
|
IN UINT32 MailboxType,
|
|
IN UINT32 MailboxCommand,
|
|
IN UINT32 MailboxData,
|
|
OUT UINT32 *MailboxStatus
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT64 MsrData;
|
|
UINT32 MchBar;
|
|
OC_MAILBOX_FULL OcMailboxFull;
|
|
OC_MAILBOX_FULL OcMailboxFullVerify;
|
|
PCODE_MAILBOX_FULL PcodeMailboxFull;
|
|
PCODE_MAILBOX_FULL PcodeMailboxFullVerify;
|
|
BOOLEAN IsBspInt;
|
|
|
|
IsBspInt = IsBsp ();
|
|
|
|
///
|
|
/// Poll the run/busy to ensure the interface is available
|
|
///
|
|
Status = PollMailboxReady (MailboxType);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
if (IsBspInt) {
|
|
DEBUG ((DEBUG_INFO, "(MAILBOX) Mailbox Write Command = %Xh\n", MailboxCommand));
|
|
DEBUG ((DEBUG_INFO, "(MAILBOX) Mailbox Write Data = %Xh\n", MailboxData));
|
|
}
|
|
|
|
switch (MailboxType) {
|
|
case MAILBOX_TYPE_PCODE:
|
|
///
|
|
/// Copy in Mailbox data and write the PCODE mailbox DATA field
|
|
///
|
|
PcodeMailboxFull.Interface.InterfaceData = MailboxCommand;
|
|
PcodeMailboxFull.Data = MailboxData;
|
|
MchBar = PciSegmentRead32 (PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SA_MC_BUS, SA_MC_DEV, SA_MC_FUN, R_SA_MCHBAR)) & ~BIT0;
|
|
|
|
MmioWrite32 ((MchBar + PCODE_MAILBOX_DATA_OFFSET), PcodeMailboxFull.Data);
|
|
|
|
///
|
|
/// Set the Run/Busy bit to signal mailbox data is ready to process
|
|
///
|
|
PcodeMailboxFull.Interface.Fields.RunBusy = 1;
|
|
MmioWrite32 ((MchBar + PCODE_MAILBOX_INTERFACE_OFFSET), PcodeMailboxFull.Interface.InterfaceData);
|
|
|
|
///
|
|
/// Poll run/busy to indicate the completion of write request
|
|
///
|
|
PollMailboxReady (MailboxType);
|
|
|
|
///
|
|
/// Read the BIOS PCODE mailbox to verify write completion success.
|
|
/// Mailbox protocol requires software to read back the interface twice
|
|
/// to ensure the read results are consistent.
|
|
///
|
|
PcodeMailboxFull.Interface.InterfaceData = MmioRead32 (MchBar + PCODE_MAILBOX_INTERFACE_OFFSET);
|
|
PcodeMailboxFull.Data = MmioRead32 (MchBar + PCODE_MAILBOX_DATA_OFFSET);
|
|
|
|
MicroSecondDelay (MAILBOX_READ_TIMEOUT);
|
|
|
|
///
|
|
/// Read twice to verify data is consitent
|
|
///
|
|
PcodeMailboxFullVerify.Interface.InterfaceData = MmioRead32 (MchBar + PCODE_MAILBOX_INTERFACE_OFFSET);
|
|
PcodeMailboxFullVerify.Data = MmioRead32 (MchBar + PCODE_MAILBOX_DATA_OFFSET);
|
|
|
|
///
|
|
/// If the data is inconsistent, we cannot trust the results
|
|
///
|
|
if (PcodeMailboxFull.Interface.InterfaceData != PcodeMailboxFullVerify.Interface.InterfaceData) {
|
|
if (PcodeMailboxFull.Data != PcodeMailboxFullVerify.Data) {
|
|
if (IsBspInt) {
|
|
DEBUG ((DEBUG_ERROR, "(MAILBOX) Mailbox read data is corrupted.\n"));
|
|
}
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
///
|
|
/// Copy PCODE mailbox completion code
|
|
///
|
|
*MailboxStatus = (UINT32) PcodeMailboxFull.Interface.Fields.Command;
|
|
break;
|
|
|
|
case MAILBOX_TYPE_OC:
|
|
///
|
|
/// Set the Run/Busy bit to signal mailbox data is ready to process
|
|
///
|
|
OcMailboxFull.Interface.InterfaceData = MailboxCommand;
|
|
OcMailboxFull.Data = MailboxData;
|
|
OcMailboxFull.Interface.Fields.RunBusy = 1;
|
|
CopyMem (&MsrData, &OcMailboxFull, sizeof (MsrData));
|
|
|
|
///
|
|
/// Write mailbox command to OC mailbox
|
|
///
|
|
AsmWriteMsr64 (OC_MAILBOX_MSR, MsrData);
|
|
|
|
///
|
|
/// Poll run/busy to indicate the completion of write request
|
|
///
|
|
PollMailboxReady (MailboxType);
|
|
|
|
///
|
|
/// Read the mailbox command from OC mailbox. Read twice to ensure data.
|
|
///
|
|
MsrData = AsmReadMsr64 (OC_MAILBOX_MSR);
|
|
CopyMem (&OcMailboxFull, &MsrData, sizeof (OcMailboxFull));
|
|
|
|
MicroSecondDelay (MAILBOX_READ_TIMEOUT);
|
|
|
|
MsrData = AsmReadMsr64 (OC_MAILBOX_MSR);
|
|
CopyMem (&OcMailboxFullVerify, &MsrData, sizeof (OcMailboxFullVerify));
|
|
|
|
///
|
|
/// If the data is inconsistent, we cannot trust the results
|
|
///
|
|
if (OcMailboxFull.Interface.InterfaceData != OcMailboxFullVerify.Interface.InterfaceData) {
|
|
if (OcMailboxFull.Data != OcMailboxFullVerify.Data) {
|
|
if (IsBspInt) {
|
|
DEBUG ((DEBUG_ERROR, "(MAILBOX) Mailbox read data is corrupted.\n"));
|
|
}
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
///
|
|
/// Copy Overclocking mailbox completion code and read results
|
|
///
|
|
*MailboxStatus = OcMailboxFull.Interface.Fields.CommandCompletion;
|
|
break;
|
|
|
|
case MAILBOX_TYPE_VR_MSR:
|
|
///
|
|
/// Copy in Mailbox data and write the PCODE MSR mailbox DATA field
|
|
///
|
|
PcodeMailboxFull.Interface.InterfaceData = MailboxCommand;
|
|
PcodeMailboxFull.Interface.Fields.RunBusy = 1;
|
|
PcodeMailboxFull.Data = MailboxData;
|
|
|
|
///
|
|
/// Write mailbox command to VR mailbox
|
|
///
|
|
AsmWriteMsr64 (VR_MAILBOX_MSR_DATA, (UINT64) PcodeMailboxFull.Data);
|
|
AsmWriteMsr64 (VR_MAILBOX_MSR_INTERFACE, (UINT64) PcodeMailboxFull.Interface.InterfaceData);
|
|
|
|
///
|
|
/// Poll run/busy to indicate the completion of write request
|
|
///
|
|
PollMailboxReady (MailboxType);
|
|
|
|
///
|
|
/// Read the mailbox command from VR MSR mailbox. Read twice to ensure data.
|
|
///
|
|
MsrData = AsmReadMsr64 (VR_MAILBOX_MSR_INTERFACE);
|
|
CopyMem (&PcodeMailboxFull, &MsrData, sizeof (PcodeMailboxFull));
|
|
|
|
MicroSecondDelay (MAILBOX_READ_TIMEOUT);
|
|
|
|
MsrData = AsmReadMsr64 (VR_MAILBOX_MSR_INTERFACE);
|
|
CopyMem (&PcodeMailboxFullVerify, &MsrData, sizeof (PcodeMailboxFullVerify));
|
|
|
|
///
|
|
/// If the data is inconsistent, we cannot trust the results
|
|
///
|
|
if (PcodeMailboxFull.Interface.InterfaceData != PcodeMailboxFullVerify.Interface.InterfaceData) {
|
|
if (PcodeMailboxFull.Data != PcodeMailboxFullVerify.Data) {
|
|
if (IsBspInt) {
|
|
DEBUG ((DEBUG_ERROR, "(MAILBOX) Mailbox read data is corrupted.\n"));
|
|
}
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
///
|
|
/// Copy Overclocking mailbox completion code and read results
|
|
///
|
|
*MailboxStatus = PcodeMailboxFull.Interface.Fields.Command;
|
|
break;
|
|
|
|
default:
|
|
if (IsBspInt) {
|
|
DEBUG ((DEBUG_ERROR, "(MAILBOX) Unrecognized Mailbox Type.\n"));
|
|
}
|
|
Status = EFI_UNSUPPORTED;
|
|
break;
|
|
}
|
|
|
|
if (IsBspInt) {
|
|
DEBUG ((DEBUG_INFO, "(MAILBOX) Mailbox Status = %2Xh\n", *MailboxStatus));
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Generic Mailbox function for mailbox read commands. This function will write
|
|
the read request, and populate the read results in the output data.
|
|
|
|
@param[in] MailboxType
|
|
@param[in] MailboxCommand
|
|
@param[out] *MailboxDataPtr
|
|
@param[out] *MailboxStatus
|
|
|
|
@retval EFI_STATUS
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
MailboxRead (
|
|
IN UINT32 MailboxType,
|
|
IN UINT32 MailboxCommand,
|
|
OUT UINT32 *MailboxDataPtr,
|
|
OUT UINT32 *MailboxStatus
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT64 MsrData;
|
|
UINT32 MchBar;
|
|
PCODE_MAILBOX_FULL PcodeMailboxFull;
|
|
PCODE_MAILBOX_FULL PcodeMailboxFullVerify;
|
|
OC_MAILBOX_FULL OcMailboxFull;
|
|
OC_MAILBOX_FULL OcMailboxFullVerify;
|
|
BOOLEAN IsBspInt;
|
|
|
|
IsBspInt = IsBsp ();
|
|
|
|
///
|
|
/// Poll the run/busy to ensure the interface is available
|
|
///
|
|
Status = PollMailboxReady (MailboxType);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
if (IsBspInt) {
|
|
DEBUG ((DEBUG_INFO, "(MAILBOX) Mailbox Read Command = %Xh\n", MailboxCommand));
|
|
}
|
|
|
|
switch (MailboxType) {
|
|
case MAILBOX_TYPE_PCODE:
|
|
///
|
|
/// Write the PCODE mailbox read request.
|
|
/// Read requests only require a write to the PCODE interface mailbox.
|
|
/// The read results will be updated in the data mailbox.
|
|
///
|
|
PcodeMailboxFull.Interface.InterfaceData = MailboxCommand;
|
|
PcodeMailboxFull.Interface.Fields.RunBusy = 1;
|
|
MchBar = PciSegmentRead32 (PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SA_MC_BUS, SA_MC_DEV, SA_MC_FUN, R_SA_MCHBAR)) & ~BIT0;
|
|
|
|
MmioWrite32 ((MchBar + PCODE_MAILBOX_INTERFACE_OFFSET), PcodeMailboxFull.Interface.InterfaceData);
|
|
|
|
///
|
|
/// Poll run/busy to indicate the completion of read request
|
|
///
|
|
PollMailboxReady (MailboxType);
|
|
|
|
///
|
|
/// Read the BIOS PCODE mailbox to verify read completion success.
|
|
/// Mailbox protocol requires software to read back the interface twice
|
|
/// to ensure the read results are consistent.
|
|
///
|
|
PcodeMailboxFull.Interface.InterfaceData = MmioRead32 (MchBar + PCODE_MAILBOX_INTERFACE_OFFSET);
|
|
PcodeMailboxFull.Data = MmioRead32 (MchBar + PCODE_MAILBOX_DATA_OFFSET);
|
|
|
|
MicroSecondDelay (MAILBOX_READ_TIMEOUT);
|
|
|
|
///
|
|
/// Read twice to verify data is consitent
|
|
///
|
|
PcodeMailboxFullVerify.Interface.InterfaceData = MmioRead32 (MchBar + PCODE_MAILBOX_INTERFACE_OFFSET);
|
|
PcodeMailboxFullVerify.Data = MmioRead32 (MchBar + PCODE_MAILBOX_DATA_OFFSET);
|
|
|
|
///
|
|
/// If the data is inconsistent, we cannot trust the results
|
|
///
|
|
if (PcodeMailboxFull.Interface.InterfaceData != PcodeMailboxFullVerify.Interface.InterfaceData) {
|
|
if (PcodeMailboxFull.Data != PcodeMailboxFullVerify.Data) {
|
|
if (IsBspInt) {
|
|
DEBUG ((DEBUG_ERROR, "(MAILBOX) Mailbox read data is corrupted.\n"));
|
|
}
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
///
|
|
/// Copy PCODE mailbox completion code and read results
|
|
///
|
|
*MailboxStatus = (UINT32) PcodeMailboxFull.Interface.Fields.Command;
|
|
CopyMem (MailboxDataPtr, &PcodeMailboxFull.Data, sizeof (UINT32));
|
|
break;
|
|
|
|
case MAILBOX_TYPE_OC:
|
|
///
|
|
/// Set the Run/Busy bit to signal mailbox data is ready to process
|
|
///
|
|
OcMailboxFull.Interface.InterfaceData = MailboxCommand;
|
|
OcMailboxFull.Data = *MailboxDataPtr;
|
|
OcMailboxFull.Interface.Fields.RunBusy = 1;
|
|
CopyMem (&MsrData, &OcMailboxFull, sizeof (MsrData));
|
|
|
|
///
|
|
/// Write mailbox command to OC mailbox
|
|
///
|
|
AsmWriteMsr64 (OC_MAILBOX_MSR, MsrData);
|
|
|
|
///
|
|
/// Poll run/busy to indicate the completion of write request
|
|
///
|
|
PollMailboxReady (MailboxType);
|
|
|
|
///
|
|
/// Read the OC mailbox to verify read completion success.
|
|
/// Mailbox protocol requires software to read back the interface twice
|
|
/// to ensure the read results are consistent.
|
|
///
|
|
MsrData = AsmReadMsr64 (OC_MAILBOX_MSR);
|
|
CopyMem (&OcMailboxFull, &MsrData, sizeof (OcMailboxFull));
|
|
|
|
MicroSecondDelay (MAILBOX_READ_TIMEOUT);
|
|
|
|
MsrData = AsmReadMsr64 (OC_MAILBOX_MSR);
|
|
CopyMem (&OcMailboxFullVerify, &MsrData, sizeof (OcMailboxFullVerify));
|
|
|
|
///
|
|
/// If the data is inconsistent, we cannot trust the results
|
|
///
|
|
if (OcMailboxFull.Interface.InterfaceData != OcMailboxFullVerify.Interface.InterfaceData) {
|
|
if (OcMailboxFull.Data != OcMailboxFullVerify.Data) {
|
|
if (IsBspInt) {
|
|
DEBUG ((DEBUG_ERROR, "(MAILBOX) Mailbox read data is corrupted.\n"));
|
|
}
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
///
|
|
/// Copy Overclocking mailbox completion code and read results
|
|
///
|
|
*MailboxStatus = OcMailboxFull.Interface.Fields.CommandCompletion;
|
|
CopyMem (MailboxDataPtr, &OcMailboxFull.Data, sizeof (UINT32));
|
|
break;
|
|
|
|
case MAILBOX_TYPE_VR_MSR:
|
|
///
|
|
/// Set the Run/Busy bit to signal mailbox data is ready to process
|
|
///
|
|
PcodeMailboxFull.Interface.InterfaceData = MailboxCommand;
|
|
PcodeMailboxFull.Data = *MailboxDataPtr;
|
|
PcodeMailboxFull.Interface.Fields.RunBusy = 1;
|
|
|
|
///
|
|
/// Data must be written to BIOS_MAILBOX_DATA before command is written to INTERFACE
|
|
///
|
|
AsmWriteMsr64 (VR_MAILBOX_MSR_DATA, (UINT64) PcodeMailboxFull.Data);
|
|
///
|
|
/// Write mailbox command to VR MSR mailbox
|
|
///
|
|
AsmWriteMsr64 (VR_MAILBOX_MSR_INTERFACE, (UINT64) PcodeMailboxFull.Interface.InterfaceData);
|
|
|
|
///
|
|
/// Poll run/busy to indicate the completion of write request
|
|
///
|
|
PollMailboxReady (MailboxType);
|
|
|
|
///
|
|
/// Read the VR MSR mailbox to verify read completion success.
|
|
/// Mailbox protocol requires software to read back the interface twice
|
|
/// to ensure the read results are consistent.
|
|
///
|
|
MsrData = AsmReadMsr64 (VR_MAILBOX_MSR_INTERFACE);
|
|
CopyMem (&PcodeMailboxFull.Interface.InterfaceData, &MsrData, sizeof (PcodeMailboxFull.Interface));
|
|
MsrData = AsmReadMsr64 (VR_MAILBOX_MSR_DATA);
|
|
CopyMem (&PcodeMailboxFull.Data, &MsrData, sizeof (PcodeMailboxFull.Data));
|
|
|
|
|
|
MicroSecondDelay (MAILBOX_READ_TIMEOUT);
|
|
|
|
MsrData = AsmReadMsr64 (VR_MAILBOX_MSR_INTERFACE);
|
|
CopyMem (&PcodeMailboxFullVerify.Interface.InterfaceData, &MsrData, sizeof (PcodeMailboxFull.Interface));
|
|
MsrData = AsmReadMsr64 (VR_MAILBOX_MSR_DATA);
|
|
CopyMem (&PcodeMailboxFullVerify.Data, &MsrData, sizeof (PcodeMailboxFull.Data));
|
|
|
|
///
|
|
/// If the data is inconsistent, we cannot trust the results
|
|
///
|
|
if (PcodeMailboxFull.Interface.InterfaceData != PcodeMailboxFullVerify.Interface.InterfaceData) {
|
|
if (PcodeMailboxFull.Data != PcodeMailboxFullVerify.Data) {
|
|
if (IsBspInt) {
|
|
DEBUG ((DEBUG_ERROR, "(MAILBOX) Mailbox read data is corrupted.\n"));
|
|
}
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
}
|
|
|
|
///
|
|
/// Copy VR MSR mailbox completion code and read results
|
|
///
|
|
*MailboxStatus = PcodeMailboxFull.Interface.Fields.Command;
|
|
CopyMem (MailboxDataPtr, &PcodeMailboxFull.Data, sizeof (UINT32));
|
|
break;
|
|
|
|
default:
|
|
if (IsBspInt) {
|
|
DEBUG ((DEBUG_ERROR, "(MAILBOX) Unrecognized Mailbox Type.\n"));
|
|
}
|
|
Status = EFI_UNSUPPORTED;
|
|
break;
|
|
}
|
|
|
|
if (IsBspInt) {
|
|
DEBUG ((DEBUG_INFO, "(MAILBOX) Mailbox Status = %2Xh\n", *MailboxStatus));
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Poll the run/busy bit of the mailbox until available or timeout expires.
|
|
|
|
@param[in] MailboxType
|
|
|
|
@retval EFI_STATUS
|
|
- EFI_SUCCESS Command succeeded.
|
|
- EFI_TIMEOUT Command timeout.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PollMailboxReady (
|
|
IN UINT32 MailboxType
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT16 StallCount;
|
|
UINT8 RunBusyBit;
|
|
UINT64 MsrData;
|
|
UINT32 MchBar;
|
|
OC_MAILBOX_FULL OcMailboxFull;
|
|
PCODE_MAILBOX_INTERFACE PcodeMailboxInterface;
|
|
PCODE_MAILBOX_FULL PcodeMailboxFull;
|
|
|
|
Status = EFI_SUCCESS;
|
|
StallCount = 0;
|
|
RunBusyBit = 1;
|
|
|
|
do {
|
|
switch (MailboxType) {
|
|
case MAILBOX_TYPE_PCODE:
|
|
///
|
|
/// Read the MMIO run/busy state
|
|
///
|
|
MchBar = PciSegmentRead32 (PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SA_MC_BUS, SA_MC_DEV, SA_MC_FUN, R_SA_MCHBAR)) & ~BIT0;
|
|
PcodeMailboxInterface.InterfaceData = MmioRead32 (MchBar + PCODE_MAILBOX_INTERFACE_OFFSET);
|
|
RunBusyBit = (UINT8) PcodeMailboxInterface.Fields.RunBusy;
|
|
break;
|
|
|
|
case MAILBOX_TYPE_OC:
|
|
///
|
|
/// Read the OC mailbox run/busy state
|
|
///
|
|
MsrData = AsmReadMsr64 (OC_MAILBOX_MSR);
|
|
CopyMem (&OcMailboxFull.Data, &MsrData, sizeof (OcMailboxFull));
|
|
RunBusyBit = OcMailboxFull.Interface.Fields.RunBusy;
|
|
break;
|
|
|
|
case MAILBOX_TYPE_VR_MSR:
|
|
///
|
|
/// Read the VR mailbox run/busy state
|
|
///
|
|
MsrData = AsmReadMsr64 (VR_MAILBOX_MSR_INTERFACE);
|
|
CopyMem (&PcodeMailboxFull.Interface.InterfaceData, &MsrData, sizeof (PcodeMailboxFull));
|
|
RunBusyBit = (UINT8) PcodeMailboxFull.Interface.Fields.RunBusy;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
//
|
|
// Wait for 1us
|
|
//
|
|
MicroSecondDelay (MAILBOX_WAIT_STALL);
|
|
StallCount++;
|
|
}
|
|
while ((RunBusyBit == 1) && (StallCount < MAILBOX_WAIT_TIMEOUT));
|
|
|
|
if ((RunBusyBit == 1) && (StallCount == MAILBOX_WAIT_TIMEOUT)) {
|
|
if (IsBsp ()) {
|
|
DEBUG ((DEBUG_ERROR, "(MAILBOX) Mailbox interface timed out.\n"));
|
|
}
|
|
Status = EFI_TIMEOUT;
|
|
}
|
|
return Status;
|
|
}
|