mirror of https://github.com/acidanthera/audk.git
MdeModulePkg/AtaAtapiPassThru: When D2H FIS received at PIO DATA-IN transfer, check PxTFD.Error register to confirm if there is a real error for better device compatibilities with Qemu and Marvel9230 sata controllers.
Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Reza Jelveh <reza.jelveh@tuhh.de> Signed-off-by: Feng Tian <feng.tian@intel.com> Reviewed-by: A. Sava <asava.dev@gmail.com> Reviewed-by: Star Zeng <Start.Zeng@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16225 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
2cb6eabe0b
commit
43654b1cb9
|
@ -704,6 +704,8 @@ AhciPioTransfer (
|
|||
UINT32 PortTfd;
|
||||
UINT32 PrdCount;
|
||||
BOOLEAN InfiniteWait;
|
||||
BOOLEAN PioFisReceived;
|
||||
BOOLEAN D2hFisReceived;
|
||||
|
||||
if (Timeout == 0) {
|
||||
InfiniteWait = TRUE;
|
||||
|
@ -780,15 +782,31 @@ AhciPioTransfer (
|
|||
Status = EFI_TIMEOUT;
|
||||
Delay = DivU64x32 (Timeout, 1000) + 1;
|
||||
do {
|
||||
PioFisReceived = FALSE;
|
||||
D2hFisReceived = FALSE;
|
||||
Offset = FisBaseAddr + EFI_AHCI_PIO_FIS_OFFSET;
|
||||
|
||||
Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_PIO_SETUP, NULL);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
PioFisReceived = TRUE;
|
||||
}
|
||||
//
|
||||
// According to SATA 2.6 spec section 11.7, D2h FIS means an error encountered.
|
||||
// But Qemu and Marvel 9230 sata controller may just receive a D2h FIS from device
|
||||
// after the transaction is finished successfully.
|
||||
// To get better device compatibilities, we further check if the PxTFD's ERR bit is set.
|
||||
// By this way, we can know if there is a real error happened.
|
||||
//
|
||||
Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;
|
||||
Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_REGISTER_D2H, NULL);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
D2hFisReceived = TRUE;
|
||||
}
|
||||
|
||||
if (PioFisReceived || D2hFisReceived) {
|
||||
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
|
||||
PortTfd = AhciReadReg (PciIo, (UINT32) Offset);
|
||||
//
|
||||
// PxTFD will be updated if there is a D2H or SetupFIS received.
|
||||
// For PIO IN transfer, D2H means a device error. Therefore we only need to check the TFD after receiving a SetupFIS.
|
||||
//
|
||||
if ((PortTfd & EFI_AHCI_PORT_TFD_ERR) != 0) {
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
|
@ -797,23 +815,20 @@ AhciPioTransfer (
|
|||
|
||||
PrdCount = *(volatile UINT32 *) (&(AhciRegisters->AhciCmdList[0].AhciCmdPrdbc));
|
||||
if (PrdCount == DataCount) {
|
||||
Status = EFI_SUCCESS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;
|
||||
Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_REGISTER_D2H, NULL);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Stall for 100 microseconds.
|
||||
//
|
||||
MicroSecondDelay(100);
|
||||
|
||||
Delay--;
|
||||
if (Delay == 0) {
|
||||
Status = EFI_TIMEOUT;
|
||||
}
|
||||
} while (InfiniteWait || (Delay > 0));
|
||||
} else {
|
||||
//
|
||||
|
|
Loading…
Reference in New Issue