MdeModulePkg/ScsiDisk: Using back-off algorithm to dynamically adjust transfer length in a single SCSI/ATAPI transfer to reach best device compatibility.

Besides this, the patch also fixed:
1) Wrong return value in SenseDataLength field of packet field of EFI_EXT_SCSI_PASS_THRU protocol, it should reflect real sense data length we got.
2) Wrong logic in ScsiDiskRequestSenseKeys that the logic makes SenseData pointer unaligned compared with BlockIo.Media.IoAlign field.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Tian, Feng <feng.tian@intel.com>
Reviewed-by: Zeng, Star <star.zeng@intel.com>
Reviewed-by: Fu, Siyuan <siyuan.fu@intel.com>

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15491 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Tian, Feng
2014-04-30 03:36:14 +00:00
committed by erictian
parent 56dea5e177
commit 73a9e82214
4 changed files with 284 additions and 214 deletions

View File

@@ -1,7 +1,7 @@
/** @file
Header file for AHCI mode of ATA host controller.
Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
@@ -1941,56 +1941,6 @@ AtaPacketReadWrite (
return Status;
}
/**
Sumbit ATAPI request sense command.
@param[in] PciIo Pointer to the EFI_PCI_IO_PROTOCOL instance
@param[in] IdeRegisters Pointer to EFI_IDE_REGISTERS which is used to
store the IDE i/o port registers' base addresses
@param[in] Channel The channel number of device.
@param[in] Device The device number of device.
@param[in] SenseData A pointer to store sense data.
@param[in] SenseDataLength The sense data length.
@param[in] Timeout The timeout value to execute this cmd, uses 100ns as a unit.
@retval EFI_SUCCESS Send out the ATAPI packet command successfully.
@retval EFI_DEVICE_ERROR The device failed to send data.
**/
EFI_STATUS
EFIAPI
AtaPacketRequestSense (
IN EFI_PCI_IO_PROTOCOL *PciIo,
IN EFI_IDE_REGISTERS *IdeRegisters,
IN UINT8 Channel,
IN UINT8 Device,
IN VOID *SenseData,
IN UINT8 SenseDataLength,
IN UINT64 Timeout
)
{
EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET Packet;
UINT8 Cdb[12];
EFI_STATUS Status;
ZeroMem (&Packet, sizeof (EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET));
ZeroMem (Cdb, 12);
Cdb[0] = ATA_CMD_REQUEST_SENSE;
Cdb[4] = SenseDataLength;
Packet.Timeout = Timeout;
Packet.Cdb = Cdb;
Packet.CdbLength = 12;
Packet.DataDirection = EFI_EXT_SCSI_DATA_DIRECTION_READ;
Packet.InDataBuffer = SenseData;
Packet.InTransferLength = SenseDataLength;
Status = AtaPacketCommandExecute (PciIo, IdeRegisters, Channel, Device, &Packet);
return Status;
}
/**
This function is used to send out ATAPI commands conforms to the Packet Command
with PIO Data In Protocol.
@@ -2017,7 +1967,6 @@ AtaPacketCommandExecute (
IN EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
)
{
EFI_STATUS PacketCommandStatus;
EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
EFI_STATUS Status;
UINT8 Count;
@@ -2083,56 +2032,26 @@ AtaPacketCommandExecute (
// Read/Write the data of ATAPI Command
//
if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
PacketCommandStatus = AtaPacketReadWrite (
PciIo,
IdeRegisters,
Packet->InDataBuffer,
Packet->InTransferLength,
TRUE,
Packet->Timeout
);
Status = AtaPacketReadWrite (
PciIo,
IdeRegisters,
Packet->InDataBuffer,
Packet->InTransferLength,
TRUE,
Packet->Timeout
);
} else {
PacketCommandStatus = AtaPacketReadWrite (
PciIo,
IdeRegisters,
Packet->OutDataBuffer,
Packet->OutTransferLength,
FALSE,
Packet->Timeout
);
Status = AtaPacketReadWrite (
PciIo,
IdeRegisters,
Packet->OutDataBuffer,
Packet->OutTransferLength,
FALSE,
Packet->Timeout
);
}
if (!EFI_ERROR (PacketCommandStatus)) {
return PacketCommandStatus;
}
//
// Return SenseData if PacketCommandStatus matches
// the following return codes.
//
if ((PacketCommandStatus == EFI_BAD_BUFFER_SIZE) ||
(PacketCommandStatus == EFI_DEVICE_ERROR) ||
(PacketCommandStatus == EFI_TIMEOUT)) {
//
// avoid submit request sense command continuously.
//
if ((Packet->SenseData == NULL) || (((UINT8 *)Packet->Cdb)[0] == ATA_CMD_REQUEST_SENSE)) {
return PacketCommandStatus;
}
AtaPacketRequestSense (
PciIo,
IdeRegisters,
Channel,
Device,
Packet->SenseData,
Packet->SenseDataLength,
Packet->Timeout
);
}
return PacketCommandStatus;
return Status;
}