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:
Feng Tian
2016-10-31 13:46:08 +08:00
parent 73152f19c0
commit a7b3f90f8a

View File

@@ -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;
} }