MdeModulePkg/AtaAtapiPassThru: update AtaStatusBlock after cmd exec
AhciDumpPortStatus doesn't fully populate all the fields of AtaStatusBlock after completing command execution, which may bring issue if someone depends on the return status. Cc: Star Zeng <star.zeng@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Feng Tian <feng.tian@intel.com> Reviewed-by: Star Zeng <star.zeng@intel.com>
This commit is contained in:
@@ -371,6 +371,7 @@ AhciClearPortStatus (
|
|||||||
in the Status Register, the Error Register's value is also be dumped.
|
in the Status Register, the Error Register's value is also be dumped.
|
||||||
|
|
||||||
@param PciIo The PCI IO protocol instance.
|
@param PciIo The PCI IO protocol instance.
|
||||||
|
@param AhciRegisters The pointer to the EFI_AHCI_REGISTERS.
|
||||||
@param Port The number of port.
|
@param Port The number of port.
|
||||||
@param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
|
@param AtaStatusBlock A pointer to EFI_ATA_STATUS_BLOCK data structure.
|
||||||
|
|
||||||
@@ -379,24 +380,42 @@ VOID
|
|||||||
EFIAPI
|
EFIAPI
|
||||||
AhciDumpPortStatus (
|
AhciDumpPortStatus (
|
||||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||||
|
IN EFI_AHCI_REGISTERS *AhciRegisters,
|
||||||
IN UINT8 Port,
|
IN UINT8 Port,
|
||||||
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock
|
IN OUT EFI_ATA_STATUS_BLOCK *AtaStatusBlock
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
UINT32 Offset;
|
UINTN Offset;
|
||||||
UINT32 Data;
|
UINT32 Data;
|
||||||
|
UINTN FisBaseAddr;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
ASSERT (PciIo != NULL);
|
ASSERT (PciIo != NULL);
|
||||||
|
|
||||||
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
|
|
||||||
Data = AhciReadReg (PciIo, Offset);
|
|
||||||
|
|
||||||
if (AtaStatusBlock != NULL) {
|
if (AtaStatusBlock != NULL) {
|
||||||
ZeroMem (AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
|
ZeroMem (AtaStatusBlock, sizeof (EFI_ATA_STATUS_BLOCK));
|
||||||
|
|
||||||
AtaStatusBlock->AtaStatus = (UINT8)Data;
|
FisBaseAddr = (UINTN)AhciRegisters->AhciRFis + Port * sizeof (EFI_AHCI_RECEIVED_FIS);
|
||||||
if ((AtaStatusBlock->AtaStatus & BIT0) != 0) {
|
Offset = FisBaseAddr + EFI_AHCI_D2H_FIS_OFFSET;
|
||||||
AtaStatusBlock->AtaError = (UINT8)(Data >> 8);
|
|
||||||
|
Status = AhciCheckMemSet (Offset, EFI_AHCI_FIS_TYPE_MASK, EFI_AHCI_FIS_REGISTER_D2H, NULL);
|
||||||
|
if (!EFI_ERROR (Status)) {
|
||||||
|
//
|
||||||
|
// If D2H FIS is received, update StatusBlock with its content.
|
||||||
|
//
|
||||||
|
CopyMem (AtaStatusBlock, (UINT8 *)Offset, sizeof (EFI_ATA_STATUS_BLOCK));
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// If D2H FIS is not received, only update Status & Error field through PxTFD
|
||||||
|
// as there is no other way to get the content of the Shadow Register Block.
|
||||||
|
//
|
||||||
|
Offset = EFI_AHCI_PORT_START + Port * EFI_AHCI_PORT_REG_WIDTH + EFI_AHCI_PORT_TFD;
|
||||||
|
Data = AhciReadReg (PciIo, (UINT32)Offset);
|
||||||
|
|
||||||
|
AtaStatusBlock->AtaStatus = (UINT8)Data;
|
||||||
|
if ((AtaStatusBlock->AtaStatus & BIT0) != 0) {
|
||||||
|
AtaStatusBlock->AtaError = (UINT8)(Data >> 8);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -866,7 +885,7 @@ Exit:
|
|||||||
Map
|
Map
|
||||||
);
|
);
|
||||||
|
|
||||||
AhciDumpPortStatus (PciIo, Port, AtaStatusBlock);
|
AhciDumpPortStatus (PciIo, AhciRegisters, Port, AtaStatusBlock);
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
@@ -1085,7 +1104,7 @@ Exit:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AhciDumpPortStatus (PciIo, Port, AtaStatusBlock);
|
AhciDumpPortStatus (PciIo, AhciRegisters, Port, AtaStatusBlock);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1201,7 +1220,7 @@ Exit:
|
|||||||
Timeout
|
Timeout
|
||||||
);
|
);
|
||||||
|
|
||||||
AhciDumpPortStatus (PciIo, Port, AtaStatusBlock);
|
AhciDumpPortStatus (PciIo, AhciRegisters, Port, AtaStatusBlock);
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user