summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
diff options
context:
space:
mode:
authorTian, Feng <feng.tian@intel.com>2014-04-30 03:36:14 +0000
committererictian <erictian@6f19259b-4bc3-4df7-8a09-765794883524>2014-04-30 03:36:14 +0000
commit73a9e82214f3b0935c8f05efa00a0997763f7294 (patch)
tree45bda992820eb971d10403b1900c653e40273feb /MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
parent56dea5e177b4d9fc7e25b32c2e25963ad4068116 (diff)
downloadedk2-platforms-73a9e82214f3b0935c8f05efa00a0997763f7294.tar.xz
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
Diffstat (limited to 'MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c')
-rw-r--r--MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c224
1 files changed, 143 insertions, 81 deletions
diff --git a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
index 0eb1036e46..e5dd6b9c4d 100644
--- a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
+++ b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c
@@ -1279,40 +1279,46 @@ DetectMediaParsingSenseKeys (
ScsiDiskDevice->BlkIo.Media->MediaPresent = FALSE;
ScsiDiskDevice->BlkIo.Media->LastBlock = 0;
*Action = ACTION_NO_ACTION;
+ DEBUG ((EFI_D_VERBOSE, "ScsiDisk: ScsiDiskIsNoMedia\n"));
return EFI_SUCCESS;
}
if (ScsiDiskIsMediaChange (SenseData, NumberOfSenseKeys)) {
ScsiDiskDevice->BlkIo.Media->MediaId++;
+ DEBUG ((EFI_D_VERBOSE, "ScsiDisk: ScsiDiskIsMediaChange!\n"));
return EFI_SUCCESS;
}
if (ScsiDiskIsResetBefore (SenseData, NumberOfSenseKeys)) {
*Action = ACTION_RETRY_COMMAND_LATER;
+ DEBUG ((EFI_D_VERBOSE, "ScsiDisk: ScsiDiskIsResetBefore!\n"));
return EFI_SUCCESS;
}
if (ScsiDiskIsMediaError (SenseData, NumberOfSenseKeys)) {
- ScsiDiskDevice->BlkIo.Media->MediaPresent = FALSE;
- ScsiDiskDevice->BlkIo.Media->LastBlock = 0;
- *Action = ACTION_NO_ACTION;
+ DEBUG ((EFI_D_VERBOSE, "ScsiDisk: ScsiDiskIsMediaError\n"));
+ *Action = ACTION_RETRY_WITH_BACKOFF_ALGO;
return EFI_DEVICE_ERROR;
}
if (ScsiDiskIsHardwareError (SenseData, NumberOfSenseKeys)) {
- *Action = ACTION_NO_ACTION;
+ DEBUG ((EFI_D_VERBOSE, "ScsiDisk: ScsiDiskIsHardwareError\n"));
+ *Action = ACTION_RETRY_WITH_BACKOFF_ALGO;
return EFI_DEVICE_ERROR;
}
if (!ScsiDiskIsDriveReady (SenseData, NumberOfSenseKeys, &RetryLater)) {
if (RetryLater) {
*Action = ACTION_RETRY_COMMAND_LATER;
+ DEBUG ((EFI_D_VERBOSE, "ScsiDisk: ScsiDiskDriveNotReady!\n"));
return EFI_SUCCESS;
}
*Action = ACTION_NO_ACTION;
return EFI_DEVICE_ERROR;
}
+ *Action = ACTION_RETRY_WITH_BACKOFF_ALGO;
+ DEBUG ((EFI_D_VERBOSE, "ScsiDisk: Sense Key = 0x%x ASC = 0x%x!\n", SenseData->Sense_Key, SenseData->Addnl_Sense_Code));
return EFI_SUCCESS;
}
@@ -1618,9 +1624,14 @@ ScsiDiskRequestSenseKeys (
*NumberOfSenseKeys = 0;
*SenseDataArray = ScsiDiskDevice->SenseData;
- PtrSenseData = ScsiDiskDevice->SenseData;
+ Status = EFI_SUCCESS;
+ PtrSenseData = AllocateAlignedBuffer (ScsiDiskDevice, sizeof (EFI_SCSI_SENSE_DATA));
+ if (PtrSenseData == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
for (SenseReq = TRUE; SenseReq;) {
+ ZeroMem (PtrSenseData, sizeof (EFI_SCSI_SENSE_DATA));
Status = ScsiRequestSenseCommand (
ScsiDiskDevice->ScsiIo,
SCSI_DISK_TIMEOUT,
@@ -1651,12 +1662,15 @@ ScsiDiskRequestSenseKeys (
if (EFI_ERROR (FallStatus)) {
if (*NumberOfSenseKeys != 0) {
*NeedRetry = FALSE;
- return EFI_SUCCESS;
+ Status = EFI_SUCCESS;
+ goto EXIT;
} else {
- return EFI_DEVICE_ERROR;
+ Status = EFI_DEVICE_ERROR;
+ goto EXIT;
}
}
+ CopyMem (ScsiDiskDevice->SenseData + *NumberOfSenseKeys, PtrSenseData, SenseDataLength);
(*NumberOfSenseKeys) += 1;
//
@@ -1667,9 +1681,11 @@ ScsiDiskRequestSenseKeys (
(*NumberOfSenseKeys == ScsiDiskDevice->SenseDataNumber)) {
SenseReq = FALSE;
}
- PtrSenseData += 1;
}
- return EFI_SUCCESS;
+
+EXIT:
+ FreeAlignedBuffer (PtrSenseData, sizeof (EFI_SCSI_SENSE_DATA));
+ return Status;
}
@@ -1780,11 +1796,6 @@ ScsiDiskReadSectors (
UINT8 Index;
UINT8 MaxRetry;
BOOLEAN NeedRetry;
- EFI_SCSI_SENSE_DATA *SenseData;
- UINTN NumberOfSenseKeys;
-
- SenseData = NULL;
- NumberOfSenseKeys = 0;
Status = EFI_SUCCESS;
@@ -1855,8 +1866,6 @@ ScsiDiskReadSectors (
Status = ScsiDiskRead10 (
ScsiDiskDevice,
&NeedRetry,
- &SenseData,
- &NumberOfSenseKeys,
Timeout,
PtrBuffer,
&ByteCount,
@@ -1867,8 +1876,6 @@ ScsiDiskReadSectors (
Status = ScsiDiskRead16 (
ScsiDiskDevice,
&NeedRetry,
- &SenseData,
- &NumberOfSenseKeys,
Timeout,
PtrBuffer,
&ByteCount,
@@ -1934,11 +1941,6 @@ ScsiDiskWriteSectors (
UINT8 Index;
UINT8 MaxRetry;
BOOLEAN NeedRetry;
- EFI_SCSI_SENSE_DATA *SenseData;
- UINTN NumberOfSenseKeys;
-
- SenseData = NULL;
- NumberOfSenseKeys = 0;
Status = EFI_SUCCESS;
@@ -2008,8 +2010,6 @@ ScsiDiskWriteSectors (
Status = ScsiDiskWrite10 (
ScsiDiskDevice,
&NeedRetry,
- &SenseData,
- &NumberOfSenseKeys,
Timeout,
PtrBuffer,
&ByteCount,
@@ -2020,8 +2020,6 @@ ScsiDiskWriteSectors (
Status = ScsiDiskWrite16 (
ScsiDiskDevice,
&NeedRetry,
- &SenseData,
- &NumberOfSenseKeys,
Timeout,
PtrBuffer,
&ByteCount,
@@ -2060,13 +2058,11 @@ ScsiDiskWriteSectors (
@param ScsiDiskDevice The pointer of ScsiDiskDevice
@param NeedRetry The pointer of flag indicates if needs retry if error happens
- @param SenseDataArray NOT used yet in this function
- @param NumberOfSenseKeys The number of sense key
@param Timeout The time to complete the command
@param DataBuffer The buffer to fill with the read out data
@param DataLength The length of buffer
@param StartLba The start logic block address
- @param SectorSize The size of sector
+ @param SectorCount The number of blocks to read
@return EFI_STATUS is returned by calling ScsiRead10Command().
**/
@@ -2074,13 +2070,11 @@ EFI_STATUS
ScsiDiskRead10 (
IN SCSI_DISK_DEV *ScsiDiskDevice,
OUT BOOLEAN *NeedRetry,
- OUT EFI_SCSI_SENSE_DATA **SenseDataArray, OPTIONAL
- OUT UINTN *NumberOfSenseKeys,
IN UINT64 Timeout,
OUT UINT8 *DataBuffer,
IN OUT UINT32 *DataLength,
IN UINT32 StartLba,
- IN UINT32 SectorSize
+ IN UINT32 SectorCount
)
{
UINT8 SenseDataLength;
@@ -2090,8 +2084,16 @@ ScsiDiskRead10 (
UINT8 TargetStatus;
UINTN Action;
+ //
+ // Implement a backoff algorithem to resolve some compatibility issues that
+ // some SCSI targets or ATAPI devices couldn't correctly response reading/writing
+ // big data in a single operation.
+ // This algorithem will at first try to execute original request. If the request fails
+ // with media error sense data or else, it will reduce the transfer length to half and
+ // try again till the operation succeeds or fails with one sector transfer length.
+ //
+BackOff:
*NeedRetry = FALSE;
- *NumberOfSenseKeys = 0;
Action = ACTION_NO_ACTION;
SenseDataLength = (UINT8) (ScsiDiskDevice->SenseDataNumber * sizeof (EFI_SCSI_SENSE_DATA));
ReturnStatus = ScsiRead10Command (
@@ -2104,7 +2106,7 @@ ScsiDiskRead10 (
DataBuffer,
DataLength,
StartLba,
- SectorSize
+ SectorCount
);
if (ReturnStatus == EFI_NOT_READY) {
@@ -2145,14 +2147,26 @@ ScsiDiskRead10 (
return EFI_DEVICE_ERROR;
}
- if (TargetStatus == EFI_EXT_SCSI_STATUS_TARGET_CHECK_CONDITION) {
- DEBUG ((EFI_D_VERBOSE, "ScsiDiskRead10: Check Condition happened!\n"));
+ if ((TargetStatus == EFI_EXT_SCSI_STATUS_TARGET_CHECK_CONDITION) || (EFI_ERROR (ReturnStatus))) {
+ DEBUG ((EFI_D_ERROR, "ScsiDiskRead10: Check Condition happened!\n"));
Status = DetectMediaParsingSenseKeys (ScsiDiskDevice, ScsiDiskDevice->SenseData, SenseDataLength / sizeof (EFI_SCSI_SENSE_DATA), &Action);
- if (EFI_ERROR (Status)) {
- return Status;
- } else if (Action == ACTION_RETRY_COMMAND_LATER) {
+ if (Action == ACTION_RETRY_COMMAND_LATER) {
*NeedRetry = TRUE;
return EFI_DEVICE_ERROR;
+ } else if (Action == ACTION_RETRY_WITH_BACKOFF_ALGO) {
+ if (SectorCount <= 1) {
+ //
+ // Jump out if the operation still fails with one sector transfer length.
+ //
+ *NeedRetry = FALSE;
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Try again with half length if the sense data shows we need to retry.
+ //
+ SectorCount >>= 1;
+ *DataLength = SectorCount * ScsiDiskDevice->BlkIo.Media->BlockSize;
+ goto BackOff;
} else {
*NeedRetry = FALSE;
return EFI_DEVICE_ERROR;
@@ -2168,13 +2182,11 @@ ScsiDiskRead10 (
@param ScsiDiskDevice The pointer of ScsiDiskDevice
@param NeedRetry The pointer of flag indicates if needs retry if error happens
- @param SenseDataArray NOT used yet in this function
- @param NumberOfSenseKeys The number of sense key
@param Timeout The time to complete the command
@param DataBuffer The buffer to fill with the read out data
@param DataLength The length of buffer
@param StartLba The start logic block address
- @param SectorSize The size of sector
+ @param SectorCount The number of blocks to write
@return EFI_STATUS is returned by calling ScsiWrite10Command().
@@ -2183,13 +2195,11 @@ EFI_STATUS
ScsiDiskWrite10 (
IN SCSI_DISK_DEV *ScsiDiskDevice,
OUT BOOLEAN *NeedRetry,
- OUT EFI_SCSI_SENSE_DATA **SenseDataArray, OPTIONAL
- OUT UINTN *NumberOfSenseKeys,
IN UINT64 Timeout,
IN UINT8 *DataBuffer,
IN OUT UINT32 *DataLength,
IN UINT32 StartLba,
- IN UINT32 SectorSize
+ IN UINT32 SectorCount
)
{
EFI_STATUS Status;
@@ -2199,8 +2209,16 @@ ScsiDiskWrite10 (
UINT8 TargetStatus;
UINTN Action;
+ //
+ // Implement a backoff algorithem to resolve some compatibility issues that
+ // some SCSI targets or ATAPI devices couldn't correctly response reading/writing
+ // big data in a single operation.
+ // This algorithem will at first try to execute original request. If the request fails
+ // with media error sense data or else, it will reduce the transfer length to half and
+ // try again till the operation succeeds or fails with one sector transfer length.
+ //
+BackOff:
*NeedRetry = FALSE;
- *NumberOfSenseKeys = 0;
Action = ACTION_NO_ACTION;
SenseDataLength = (UINT8) (ScsiDiskDevice->SenseDataNumber * sizeof (EFI_SCSI_SENSE_DATA));
ReturnStatus = ScsiWrite10Command (
@@ -2213,7 +2231,7 @@ ScsiDiskWrite10 (
DataBuffer,
DataLength,
StartLba,
- SectorSize
+ SectorCount
);
if (ReturnStatus == EFI_NOT_READY) {
*NeedRetry = TRUE;
@@ -2253,14 +2271,26 @@ ScsiDiskWrite10 (
return EFI_DEVICE_ERROR;
}
- if (TargetStatus == EFI_EXT_SCSI_STATUS_TARGET_CHECK_CONDITION) {
- DEBUG ((EFI_D_VERBOSE, "ScsiDiskWrite10: Check Condition happened!\n"));
+ if ((TargetStatus == EFI_EXT_SCSI_STATUS_TARGET_CHECK_CONDITION) || (EFI_ERROR (ReturnStatus))) {
+ DEBUG ((EFI_D_ERROR, "ScsiDiskWrite10: Check Condition happened!\n"));
Status = DetectMediaParsingSenseKeys (ScsiDiskDevice, ScsiDiskDevice->SenseData, SenseDataLength / sizeof (EFI_SCSI_SENSE_DATA), &Action);
- if (EFI_ERROR (Status)) {
- return Status;
- } else if (Action == ACTION_RETRY_COMMAND_LATER) {
+ if (Action == ACTION_RETRY_COMMAND_LATER) {
*NeedRetry = TRUE;
return EFI_DEVICE_ERROR;
+ } else if (Action == ACTION_RETRY_WITH_BACKOFF_ALGO) {
+ if (SectorCount <= 1) {
+ //
+ // Jump out if the operation still fails with one sector transfer length.
+ //
+ *NeedRetry = FALSE;
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Try again with half length if the sense data shows we need to retry.
+ //
+ SectorCount >>= 1;
+ *DataLength = SectorCount * ScsiDiskDevice->BlkIo.Media->BlockSize;
+ goto BackOff;
} else {
*NeedRetry = FALSE;
return EFI_DEVICE_ERROR;
@@ -2276,27 +2306,23 @@ ScsiDiskWrite10 (
@param ScsiDiskDevice The pointer of ScsiDiskDevice
@param NeedRetry The pointer of flag indicates if needs retry if error happens
- @param SenseDataArray NOT used yet in this function
- @param NumberOfSenseKeys The number of sense key
@param Timeout The time to complete the command
@param DataBuffer The buffer to fill with the read out data
@param DataLength The length of buffer
@param StartLba The start logic block address
- @param SectorSize The size of sector
+ @param SectorCount The number of blocks to read
- @return EFI_STATUS is returned by calling ScsiRead10Command().
+ @return EFI_STATUS is returned by calling ScsiRead16Command().
**/
EFI_STATUS
ScsiDiskRead16 (
IN SCSI_DISK_DEV *ScsiDiskDevice,
OUT BOOLEAN *NeedRetry,
- OUT EFI_SCSI_SENSE_DATA **SenseDataArray, OPTIONAL
- OUT UINTN *NumberOfSenseKeys,
IN UINT64 Timeout,
OUT UINT8 *DataBuffer,
IN OUT UINT32 *DataLength,
IN UINT64 StartLba,
- IN UINT32 SectorSize
+ IN UINT32 SectorCount
)
{
UINT8 SenseDataLength;
@@ -2306,8 +2332,16 @@ ScsiDiskRead16 (
UINT8 TargetStatus;
UINTN Action;
+ //
+ // Implement a backoff algorithem to resolve some compatibility issues that
+ // some SCSI targets or ATAPI devices couldn't correctly response reading/writing
+ // big data in a single operation.
+ // This algorithem will at first try to execute original request. If the request fails
+ // with media error sense data or else, it will reduce the transfer length to half and
+ // try again till the operation succeeds or fails with one sector transfer length.
+ //
+BackOff:
*NeedRetry = FALSE;
- *NumberOfSenseKeys = 0;
Action = ACTION_NO_ACTION;
SenseDataLength = (UINT8) (ScsiDiskDevice->SenseDataNumber * sizeof (EFI_SCSI_SENSE_DATA));
ReturnStatus = ScsiRead16Command (
@@ -2320,7 +2354,7 @@ ScsiDiskRead16 (
DataBuffer,
DataLength,
StartLba,
- SectorSize
+ SectorCount
);
if (ReturnStatus == EFI_NOT_READY) {
*NeedRetry = TRUE;
@@ -2360,14 +2394,26 @@ ScsiDiskRead16 (
return EFI_DEVICE_ERROR;
}
- if (TargetStatus == EFI_EXT_SCSI_STATUS_TARGET_CHECK_CONDITION) {
- DEBUG ((EFI_D_VERBOSE, "ScsiDiskRead16: Check Condition happened!\n"));
+ if ((TargetStatus == EFI_EXT_SCSI_STATUS_TARGET_CHECK_CONDITION) || (EFI_ERROR (ReturnStatus))) {
+ DEBUG ((EFI_D_ERROR, "ScsiDiskRead16: Check Condition happened!\n"));
Status = DetectMediaParsingSenseKeys (ScsiDiskDevice, ScsiDiskDevice->SenseData, SenseDataLength / sizeof (EFI_SCSI_SENSE_DATA), &Action);
- if (EFI_ERROR (Status)) {
- return Status;
- } else if (Action == ACTION_RETRY_COMMAND_LATER) {
+ if (Action == ACTION_RETRY_COMMAND_LATER) {
*NeedRetry = TRUE;
return EFI_DEVICE_ERROR;
+ } else if (Action == ACTION_RETRY_WITH_BACKOFF_ALGO) {
+ if (SectorCount <= 1) {
+ //
+ // Jump out if the operation still fails with one sector transfer length.
+ //
+ *NeedRetry = FALSE;
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Try again with half length if the sense data shows we need to retry.
+ //
+ SectorCount >>= 1;
+ *DataLength = SectorCount * ScsiDiskDevice->BlkIo.Media->BlockSize;
+ goto BackOff;
} else {
*NeedRetry = FALSE;
return EFI_DEVICE_ERROR;
@@ -2383,28 +2429,24 @@ ScsiDiskRead16 (
@param ScsiDiskDevice The pointer of ScsiDiskDevice
@param NeedRetry The pointer of flag indicates if needs retry if error happens
- @param SenseDataArray NOT used yet in this function
- @param NumberOfSenseKeys The number of sense key
@param Timeout The time to complete the command
@param DataBuffer The buffer to fill with the read out data
@param DataLength The length of buffer
@param StartLba The start logic block address
- @param SectorSize The size of sector
+ @param SectorCount The number of blocks to write
- @return EFI_STATUS is returned by calling ScsiWrite10Command().
+ @return EFI_STATUS is returned by calling ScsiWrite16Command().
**/
EFI_STATUS
ScsiDiskWrite16 (
IN SCSI_DISK_DEV *ScsiDiskDevice,
OUT BOOLEAN *NeedRetry,
- OUT EFI_SCSI_SENSE_DATA **SenseDataArray, OPTIONAL
- OUT UINTN *NumberOfSenseKeys,
IN UINT64 Timeout,
IN UINT8 *DataBuffer,
IN OUT UINT32 *DataLength,
IN UINT64 StartLba,
- IN UINT32 SectorSize
+ IN UINT32 SectorCount
)
{
EFI_STATUS Status;
@@ -2414,8 +2456,16 @@ ScsiDiskWrite16 (
UINT8 TargetStatus;
UINTN Action;
+ //
+ // Implement a backoff algorithem to resolve some compatibility issues that
+ // some SCSI targets or ATAPI devices couldn't correctly response reading/writing
+ // big data in a single operation.
+ // This algorithem will at first try to execute original request. If the request fails
+ // with media error sense data or else, it will reduce the transfer length to half and
+ // try again till the operation succeeds or fails with one sector transfer length.
+ //
+BackOff:
*NeedRetry = FALSE;
- *NumberOfSenseKeys = 0;
Action = ACTION_NO_ACTION;
SenseDataLength = (UINT8) (ScsiDiskDevice->SenseDataNumber * sizeof (EFI_SCSI_SENSE_DATA));
ReturnStatus = ScsiWrite16Command (
@@ -2428,7 +2478,7 @@ ScsiDiskWrite16 (
DataBuffer,
DataLength,
StartLba,
- SectorSize
+ SectorCount
);
if (ReturnStatus == EFI_NOT_READY) {
*NeedRetry = TRUE;
@@ -2468,14 +2518,26 @@ ScsiDiskWrite16 (
return EFI_DEVICE_ERROR;
}
- if (TargetStatus == EFI_EXT_SCSI_STATUS_TARGET_CHECK_CONDITION) {
- DEBUG ((EFI_D_VERBOSE, "ScsiDiskWrite16: Check Condition happened!\n"));
+ if ((TargetStatus == EFI_EXT_SCSI_STATUS_TARGET_CHECK_CONDITION) || (EFI_ERROR (ReturnStatus))) {
+ DEBUG ((EFI_D_ERROR, "ScsiDiskWrite16: Check Condition happened!\n"));
Status = DetectMediaParsingSenseKeys (ScsiDiskDevice, ScsiDiskDevice->SenseData, SenseDataLength / sizeof (EFI_SCSI_SENSE_DATA), &Action);
- if (EFI_ERROR (Status)) {
- return Status;
- } else if (Action == ACTION_RETRY_COMMAND_LATER) {
+ if (Action == ACTION_RETRY_COMMAND_LATER) {
*NeedRetry = TRUE;
return EFI_DEVICE_ERROR;
+ } else if (Action == ACTION_RETRY_WITH_BACKOFF_ALGO) {
+ if (SectorCount <= 1) {
+ //
+ // Jump out if the operation still fails with one sector transfer length.
+ //
+ *NeedRetry = FALSE;
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Try again with half length if the sense data shows we need to retry.
+ //
+ SectorCount >>= 1;
+ *DataLength = SectorCount * ScsiDiskDevice->BlkIo.Media->BlockSize;
+ goto BackOff;
} else {
*NeedRetry = FALSE;
return EFI_DEVICE_ERROR;