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

@ -2,7 +2,7 @@
This file implements ATA_PASSTHRU_PROCTOCOL and EXT_SCSI_PASSTHRU_PROTOCOL interfaces This file implements ATA_PASSTHRU_PROCTOCOL and EXT_SCSI_PASSTHRU_PROTOCOL interfaces
for managed ATA controllers. for managed ATA controllers.
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 This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License 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 which accompanies this distribution. The full text of the license may be found at
@ -1831,6 +1831,57 @@ AtaPassThruResetDevice (
return EFI_SUCCESS; return EFI_SUCCESS;
} }
/**
Sumbit ATAPI request sense command.
@param[in] This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
@param[in] Target The Target is an array of size TARGET_MAX_BYTES and it represents
the id of the SCSI device to send the SCSI Request Packet. Each
transport driver may choose to utilize a subset of this size to suit the needs
of transport target representation. For example, a Fibre Channel driver
may use only 8 bytes (WWN) to represent an FC target.
@param[in] Lun The LUN of the SCSI device to send the SCSI Request Packet.
@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_EXT_SCSI_PASS_THRU_PROTOCOL *This,
IN UINT8 *Target,
IN UINT64 Lun,
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 = ExtScsiPassThruPassThru (This, Target, Lun, &Packet, NULL);
return Status;
}
/** /**
Sends a SCSI Request Packet to a SCSI device that is attached to the SCSI channel. This function Sends a SCSI Request Packet to a SCSI device that is attached to the SCSI channel. This function
supports both blocking I/O and nonblocking I/O. The blocking I/O functionality is required, and the supports both blocking I/O and nonblocking I/O. The blocking I/O functionality is required, and the
@ -1889,7 +1940,12 @@ ExtScsiPassThruPassThru (
EFI_ATA_HC_WORK_MODE Mode; EFI_ATA_HC_WORK_MODE Mode;
LIST_ENTRY *Node; LIST_ENTRY *Node;
EFI_ATA_DEVICE_INFO *DeviceInfo; EFI_ATA_DEVICE_INFO *DeviceInfo;
BOOLEAN SenseReq;
EFI_SCSI_SENSE_DATA *PtrSenseData;
UINTN SenseDataLen;
EFI_STATUS SenseStatus;
SenseDataLen = 0;
Instance = EXT_SCSI_PASS_THRU_PRIVATE_DATA_FROM_THIS (This); Instance = EXT_SCSI_PASS_THRU_PRIVATE_DATA_FROM_THIS (This);
if ((Packet == NULL) || (Packet->Cdb == NULL)) { if ((Packet == NULL) || (Packet->Cdb == NULL)) {
@ -1904,6 +1960,10 @@ ExtScsiPassThruPassThru (
return EFI_INVALID_PARAMETER; return EFI_INVALID_PARAMETER;
} }
if ((Packet->SenseDataLength != 0) && (Packet->SenseData == NULL)) {
return EFI_INVALID_PARAMETER;
}
if ((This->Mode->IoAlign > 1) && !IS_ALIGNED(Packet->InDataBuffer, This->Mode->IoAlign)) { if ((This->Mode->IoAlign > 1) && !IS_ALIGNED(Packet->InDataBuffer, This->Mode->IoAlign)) {
return EFI_INVALID_PARAMETER; return EFI_INVALID_PARAMETER;
} }
@ -1951,6 +2011,10 @@ ExtScsiPassThruPassThru (
// //
if (*((UINT8*)Packet->Cdb) == ATA_CMD_IDENTIFY_DEVICE) { if (*((UINT8*)Packet->Cdb) == ATA_CMD_IDENTIFY_DEVICE) {
CopyMem (Packet->InDataBuffer, DeviceInfo->IdentifyData, sizeof (EFI_IDENTIFY_DATA)); CopyMem (Packet->InDataBuffer, DeviceInfo->IdentifyData, sizeof (EFI_IDENTIFY_DATA));
//
// For IDENTIFY DEVICE cmd, we don't need to get sense data.
//
Packet->SenseDataLength = 0;
return EFI_SUCCESS; return EFI_SUCCESS;
} }
@ -1976,6 +2040,46 @@ ExtScsiPassThruPassThru (
break; break;
} }
//
// If the cmd doesn't get executed correctly, then check sense data.
//
if (EFI_ERROR (Status) && (Packet->SenseDataLength != 0) && (*((UINT8*)Packet->Cdb) != ATA_CMD_REQUEST_SENSE)) {
PtrSenseData = AllocateAlignedPages (EFI_SIZE_TO_PAGES (sizeof (EFI_SCSI_SENSE_DATA)), This->Mode->IoAlign);
if (PtrSenseData == NULL) {
return EFI_DEVICE_ERROR;
}
for (SenseReq = TRUE; SenseReq;) {
SenseStatus = AtaPacketRequestSense (
This,
Target,
Lun,
PtrSenseData,
sizeof (EFI_SCSI_SENSE_DATA),
Packet->Timeout
);
if (EFI_ERROR (SenseStatus)) {
break;
}
CopyMem ((UINT8*)Packet->SenseData + SenseDataLen, PtrSenseData, sizeof (EFI_SCSI_SENSE_DATA));
SenseDataLen += sizeof (EFI_SCSI_SENSE_DATA);
//
// no more sense key or number of sense keys exceeds predefined,
// skip the loop.
//
if ((PtrSenseData->Sense_Key == EFI_SCSI_SK_NO_SENSE) ||
(SenseDataLen + sizeof (EFI_SCSI_SENSE_DATA) > Packet->SenseDataLength)) {
SenseReq = FALSE;
}
}
FreeAlignedPages (PtrSenseData, EFI_SIZE_TO_PAGES (sizeof (EFI_SCSI_SENSE_DATA)));
}
//
// Update the SenseDataLength field to the data length received.
//
Packet->SenseDataLength = (UINT8)SenseDataLen;
return Status; return Status;
} }

View File

@ -1,7 +1,7 @@
/** @file /** @file
Header file for AHCI mode of ATA host controller. 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 This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License 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 which accompanies this distribution. The full text of the license may be found at
@ -1941,56 +1941,6 @@ AtaPacketReadWrite (
return Status; 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 This function is used to send out ATAPI commands conforms to the Packet Command
with PIO Data In Protocol. with PIO Data In Protocol.
@ -2017,7 +1967,6 @@ AtaPacketCommandExecute (
IN EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet IN EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
) )
{ {
EFI_STATUS PacketCommandStatus;
EFI_ATA_COMMAND_BLOCK AtaCommandBlock; EFI_ATA_COMMAND_BLOCK AtaCommandBlock;
EFI_STATUS Status; EFI_STATUS Status;
UINT8 Count; UINT8 Count;
@ -2083,7 +2032,7 @@ AtaPacketCommandExecute (
// Read/Write the data of ATAPI Command // Read/Write the data of ATAPI Command
// //
if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) { if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {
PacketCommandStatus = AtaPacketReadWrite ( Status = AtaPacketReadWrite (
PciIo, PciIo,
IdeRegisters, IdeRegisters,
Packet->InDataBuffer, Packet->InDataBuffer,
@ -2092,7 +2041,7 @@ AtaPacketCommandExecute (
Packet->Timeout Packet->Timeout
); );
} else { } else {
PacketCommandStatus = AtaPacketReadWrite ( Status = AtaPacketReadWrite (
PciIo, PciIo,
IdeRegisters, IdeRegisters,
Packet->OutDataBuffer, Packet->OutDataBuffer,
@ -2102,37 +2051,7 @@ AtaPacketCommandExecute (
); );
} }
if (!EFI_ERROR (PacketCommandStatus)) { return Status;
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;
} }

View File

@ -1279,40 +1279,46 @@ DetectMediaParsingSenseKeys (
ScsiDiskDevice->BlkIo.Media->MediaPresent = FALSE; ScsiDiskDevice->BlkIo.Media->MediaPresent = FALSE;
ScsiDiskDevice->BlkIo.Media->LastBlock = 0; ScsiDiskDevice->BlkIo.Media->LastBlock = 0;
*Action = ACTION_NO_ACTION; *Action = ACTION_NO_ACTION;
DEBUG ((EFI_D_VERBOSE, "ScsiDisk: ScsiDiskIsNoMedia\n"));
return EFI_SUCCESS; return EFI_SUCCESS;
} }
if (ScsiDiskIsMediaChange (SenseData, NumberOfSenseKeys)) { if (ScsiDiskIsMediaChange (SenseData, NumberOfSenseKeys)) {
ScsiDiskDevice->BlkIo.Media->MediaId++; ScsiDiskDevice->BlkIo.Media->MediaId++;
DEBUG ((EFI_D_VERBOSE, "ScsiDisk: ScsiDiskIsMediaChange!\n"));
return EFI_SUCCESS; return EFI_SUCCESS;
} }
if (ScsiDiskIsResetBefore (SenseData, NumberOfSenseKeys)) { if (ScsiDiskIsResetBefore (SenseData, NumberOfSenseKeys)) {
*Action = ACTION_RETRY_COMMAND_LATER; *Action = ACTION_RETRY_COMMAND_LATER;
DEBUG ((EFI_D_VERBOSE, "ScsiDisk: ScsiDiskIsResetBefore!\n"));
return EFI_SUCCESS; return EFI_SUCCESS;
} }
if (ScsiDiskIsMediaError (SenseData, NumberOfSenseKeys)) { if (ScsiDiskIsMediaError (SenseData, NumberOfSenseKeys)) {
ScsiDiskDevice->BlkIo.Media->MediaPresent = FALSE; DEBUG ((EFI_D_VERBOSE, "ScsiDisk: ScsiDiskIsMediaError\n"));
ScsiDiskDevice->BlkIo.Media->LastBlock = 0; *Action = ACTION_RETRY_WITH_BACKOFF_ALGO;
*Action = ACTION_NO_ACTION;
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
} }
if (ScsiDiskIsHardwareError (SenseData, NumberOfSenseKeys)) { 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; return EFI_DEVICE_ERROR;
} }
if (!ScsiDiskIsDriveReady (SenseData, NumberOfSenseKeys, &RetryLater)) { if (!ScsiDiskIsDriveReady (SenseData, NumberOfSenseKeys, &RetryLater)) {
if (RetryLater) { if (RetryLater) {
*Action = ACTION_RETRY_COMMAND_LATER; *Action = ACTION_RETRY_COMMAND_LATER;
DEBUG ((EFI_D_VERBOSE, "ScsiDisk: ScsiDiskDriveNotReady!\n"));
return EFI_SUCCESS; return EFI_SUCCESS;
} }
*Action = ACTION_NO_ACTION; *Action = ACTION_NO_ACTION;
return EFI_DEVICE_ERROR; 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; return EFI_SUCCESS;
} }
@ -1618,9 +1624,14 @@ ScsiDiskRequestSenseKeys (
*NumberOfSenseKeys = 0; *NumberOfSenseKeys = 0;
*SenseDataArray = ScsiDiskDevice->SenseData; *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;) { for (SenseReq = TRUE; SenseReq;) {
ZeroMem (PtrSenseData, sizeof (EFI_SCSI_SENSE_DATA));
Status = ScsiRequestSenseCommand ( Status = ScsiRequestSenseCommand (
ScsiDiskDevice->ScsiIo, ScsiDiskDevice->ScsiIo,
SCSI_DISK_TIMEOUT, SCSI_DISK_TIMEOUT,
@ -1651,12 +1662,15 @@ ScsiDiskRequestSenseKeys (
if (EFI_ERROR (FallStatus)) { if (EFI_ERROR (FallStatus)) {
if (*NumberOfSenseKeys != 0) { if (*NumberOfSenseKeys != 0) {
*NeedRetry = FALSE; *NeedRetry = FALSE;
return EFI_SUCCESS; Status = EFI_SUCCESS;
goto EXIT;
} else { } else {
return EFI_DEVICE_ERROR; Status = EFI_DEVICE_ERROR;
goto EXIT;
} }
} }
CopyMem (ScsiDiskDevice->SenseData + *NumberOfSenseKeys, PtrSenseData, SenseDataLength);
(*NumberOfSenseKeys) += 1; (*NumberOfSenseKeys) += 1;
// //
@ -1667,9 +1681,11 @@ ScsiDiskRequestSenseKeys (
(*NumberOfSenseKeys == ScsiDiskDevice->SenseDataNumber)) { (*NumberOfSenseKeys == ScsiDiskDevice->SenseDataNumber)) {
SenseReq = FALSE; 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 Index;
UINT8 MaxRetry; UINT8 MaxRetry;
BOOLEAN NeedRetry; BOOLEAN NeedRetry;
EFI_SCSI_SENSE_DATA *SenseData;
UINTN NumberOfSenseKeys;
SenseData = NULL;
NumberOfSenseKeys = 0;
Status = EFI_SUCCESS; Status = EFI_SUCCESS;
@ -1855,8 +1866,6 @@ ScsiDiskReadSectors (
Status = ScsiDiskRead10 ( Status = ScsiDiskRead10 (
ScsiDiskDevice, ScsiDiskDevice,
&NeedRetry, &NeedRetry,
&SenseData,
&NumberOfSenseKeys,
Timeout, Timeout,
PtrBuffer, PtrBuffer,
&ByteCount, &ByteCount,
@ -1867,8 +1876,6 @@ ScsiDiskReadSectors (
Status = ScsiDiskRead16 ( Status = ScsiDiskRead16 (
ScsiDiskDevice, ScsiDiskDevice,
&NeedRetry, &NeedRetry,
&SenseData,
&NumberOfSenseKeys,
Timeout, Timeout,
PtrBuffer, PtrBuffer,
&ByteCount, &ByteCount,
@ -1934,11 +1941,6 @@ ScsiDiskWriteSectors (
UINT8 Index; UINT8 Index;
UINT8 MaxRetry; UINT8 MaxRetry;
BOOLEAN NeedRetry; BOOLEAN NeedRetry;
EFI_SCSI_SENSE_DATA *SenseData;
UINTN NumberOfSenseKeys;
SenseData = NULL;
NumberOfSenseKeys = 0;
Status = EFI_SUCCESS; Status = EFI_SUCCESS;
@ -2008,8 +2010,6 @@ ScsiDiskWriteSectors (
Status = ScsiDiskWrite10 ( Status = ScsiDiskWrite10 (
ScsiDiskDevice, ScsiDiskDevice,
&NeedRetry, &NeedRetry,
&SenseData,
&NumberOfSenseKeys,
Timeout, Timeout,
PtrBuffer, PtrBuffer,
&ByteCount, &ByteCount,
@ -2020,8 +2020,6 @@ ScsiDiskWriteSectors (
Status = ScsiDiskWrite16 ( Status = ScsiDiskWrite16 (
ScsiDiskDevice, ScsiDiskDevice,
&NeedRetry, &NeedRetry,
&SenseData,
&NumberOfSenseKeys,
Timeout, Timeout,
PtrBuffer, PtrBuffer,
&ByteCount, &ByteCount,
@ -2060,13 +2058,11 @@ ScsiDiskWriteSectors (
@param ScsiDiskDevice The pointer of ScsiDiskDevice @param ScsiDiskDevice The pointer of ScsiDiskDevice
@param NeedRetry The pointer of flag indicates if needs retry if error happens @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 Timeout The time to complete the command
@param DataBuffer The buffer to fill with the read out data @param DataBuffer The buffer to fill with the read out data
@param DataLength The length of buffer @param DataLength The length of buffer
@param StartLba The start logic block address @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 ScsiRead10Command().
**/ **/
@ -2074,13 +2070,11 @@ EFI_STATUS
ScsiDiskRead10 ( ScsiDiskRead10 (
IN SCSI_DISK_DEV *ScsiDiskDevice, IN SCSI_DISK_DEV *ScsiDiskDevice,
OUT BOOLEAN *NeedRetry, OUT BOOLEAN *NeedRetry,
OUT EFI_SCSI_SENSE_DATA **SenseDataArray, OPTIONAL
OUT UINTN *NumberOfSenseKeys,
IN UINT64 Timeout, IN UINT64 Timeout,
OUT UINT8 *DataBuffer, OUT UINT8 *DataBuffer,
IN OUT UINT32 *DataLength, IN OUT UINT32 *DataLength,
IN UINT32 StartLba, IN UINT32 StartLba,
IN UINT32 SectorSize IN UINT32 SectorCount
) )
{ {
UINT8 SenseDataLength; UINT8 SenseDataLength;
@ -2090,8 +2084,16 @@ ScsiDiskRead10 (
UINT8 TargetStatus; UINT8 TargetStatus;
UINTN Action; 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; *NeedRetry = FALSE;
*NumberOfSenseKeys = 0;
Action = ACTION_NO_ACTION; Action = ACTION_NO_ACTION;
SenseDataLength = (UINT8) (ScsiDiskDevice->SenseDataNumber * sizeof (EFI_SCSI_SENSE_DATA)); SenseDataLength = (UINT8) (ScsiDiskDevice->SenseDataNumber * sizeof (EFI_SCSI_SENSE_DATA));
ReturnStatus = ScsiRead10Command ( ReturnStatus = ScsiRead10Command (
@ -2104,7 +2106,7 @@ ScsiDiskRead10 (
DataBuffer, DataBuffer,
DataLength, DataLength,
StartLba, StartLba,
SectorSize SectorCount
); );
if (ReturnStatus == EFI_NOT_READY) { if (ReturnStatus == EFI_NOT_READY) {
@ -2145,14 +2147,26 @@ ScsiDiskRead10 (
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
} }
if (TargetStatus == EFI_EXT_SCSI_STATUS_TARGET_CHECK_CONDITION) { if ((TargetStatus == EFI_EXT_SCSI_STATUS_TARGET_CHECK_CONDITION) || (EFI_ERROR (ReturnStatus))) {
DEBUG ((EFI_D_VERBOSE, "ScsiDiskRead10: Check Condition happened!\n")); DEBUG ((EFI_D_ERROR, "ScsiDiskRead10: Check Condition happened!\n"));
Status = DetectMediaParsingSenseKeys (ScsiDiskDevice, ScsiDiskDevice->SenseData, SenseDataLength / sizeof (EFI_SCSI_SENSE_DATA), &Action); Status = DetectMediaParsingSenseKeys (ScsiDiskDevice, ScsiDiskDevice->SenseData, SenseDataLength / sizeof (EFI_SCSI_SENSE_DATA), &Action);
if (EFI_ERROR (Status)) { if (Action == ACTION_RETRY_COMMAND_LATER) {
return Status;
} else if (Action == ACTION_RETRY_COMMAND_LATER) {
*NeedRetry = TRUE; *NeedRetry = TRUE;
return EFI_DEVICE_ERROR; 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 { } else {
*NeedRetry = FALSE; *NeedRetry = FALSE;
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
@ -2168,13 +2182,11 @@ ScsiDiskRead10 (
@param ScsiDiskDevice The pointer of ScsiDiskDevice @param ScsiDiskDevice The pointer of ScsiDiskDevice
@param NeedRetry The pointer of flag indicates if needs retry if error happens @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 Timeout The time to complete the command
@param DataBuffer The buffer to fill with the read out data @param DataBuffer The buffer to fill with the read out data
@param DataLength The length of buffer @param DataLength The length of buffer
@param StartLba The start logic block address @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 ScsiWrite10Command().
@ -2183,13 +2195,11 @@ EFI_STATUS
ScsiDiskWrite10 ( ScsiDiskWrite10 (
IN SCSI_DISK_DEV *ScsiDiskDevice, IN SCSI_DISK_DEV *ScsiDiskDevice,
OUT BOOLEAN *NeedRetry, OUT BOOLEAN *NeedRetry,
OUT EFI_SCSI_SENSE_DATA **SenseDataArray, OPTIONAL
OUT UINTN *NumberOfSenseKeys,
IN UINT64 Timeout, IN UINT64 Timeout,
IN UINT8 *DataBuffer, IN UINT8 *DataBuffer,
IN OUT UINT32 *DataLength, IN OUT UINT32 *DataLength,
IN UINT32 StartLba, IN UINT32 StartLba,
IN UINT32 SectorSize IN UINT32 SectorCount
) )
{ {
EFI_STATUS Status; EFI_STATUS Status;
@ -2199,8 +2209,16 @@ ScsiDiskWrite10 (
UINT8 TargetStatus; UINT8 TargetStatus;
UINTN Action; 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; *NeedRetry = FALSE;
*NumberOfSenseKeys = 0;
Action = ACTION_NO_ACTION; Action = ACTION_NO_ACTION;
SenseDataLength = (UINT8) (ScsiDiskDevice->SenseDataNumber * sizeof (EFI_SCSI_SENSE_DATA)); SenseDataLength = (UINT8) (ScsiDiskDevice->SenseDataNumber * sizeof (EFI_SCSI_SENSE_DATA));
ReturnStatus = ScsiWrite10Command ( ReturnStatus = ScsiWrite10Command (
@ -2213,7 +2231,7 @@ ScsiDiskWrite10 (
DataBuffer, DataBuffer,
DataLength, DataLength,
StartLba, StartLba,
SectorSize SectorCount
); );
if (ReturnStatus == EFI_NOT_READY) { if (ReturnStatus == EFI_NOT_READY) {
*NeedRetry = TRUE; *NeedRetry = TRUE;
@ -2253,14 +2271,26 @@ ScsiDiskWrite10 (
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
} }
if (TargetStatus == EFI_EXT_SCSI_STATUS_TARGET_CHECK_CONDITION) { if ((TargetStatus == EFI_EXT_SCSI_STATUS_TARGET_CHECK_CONDITION) || (EFI_ERROR (ReturnStatus))) {
DEBUG ((EFI_D_VERBOSE, "ScsiDiskWrite10: Check Condition happened!\n")); DEBUG ((EFI_D_ERROR, "ScsiDiskWrite10: Check Condition happened!\n"));
Status = DetectMediaParsingSenseKeys (ScsiDiskDevice, ScsiDiskDevice->SenseData, SenseDataLength / sizeof (EFI_SCSI_SENSE_DATA), &Action); Status = DetectMediaParsingSenseKeys (ScsiDiskDevice, ScsiDiskDevice->SenseData, SenseDataLength / sizeof (EFI_SCSI_SENSE_DATA), &Action);
if (EFI_ERROR (Status)) { if (Action == ACTION_RETRY_COMMAND_LATER) {
return Status;
} else if (Action == ACTION_RETRY_COMMAND_LATER) {
*NeedRetry = TRUE; *NeedRetry = TRUE;
return EFI_DEVICE_ERROR; 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 { } else {
*NeedRetry = FALSE; *NeedRetry = FALSE;
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
@ -2276,27 +2306,23 @@ ScsiDiskWrite10 (
@param ScsiDiskDevice The pointer of ScsiDiskDevice @param ScsiDiskDevice The pointer of ScsiDiskDevice
@param NeedRetry The pointer of flag indicates if needs retry if error happens @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 Timeout The time to complete the command
@param DataBuffer The buffer to fill with the read out data @param DataBuffer The buffer to fill with the read out data
@param DataLength The length of buffer @param DataLength The length of buffer
@param StartLba The start logic block address @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 EFI_STATUS
ScsiDiskRead16 ( ScsiDiskRead16 (
IN SCSI_DISK_DEV *ScsiDiskDevice, IN SCSI_DISK_DEV *ScsiDiskDevice,
OUT BOOLEAN *NeedRetry, OUT BOOLEAN *NeedRetry,
OUT EFI_SCSI_SENSE_DATA **SenseDataArray, OPTIONAL
OUT UINTN *NumberOfSenseKeys,
IN UINT64 Timeout, IN UINT64 Timeout,
OUT UINT8 *DataBuffer, OUT UINT8 *DataBuffer,
IN OUT UINT32 *DataLength, IN OUT UINT32 *DataLength,
IN UINT64 StartLba, IN UINT64 StartLba,
IN UINT32 SectorSize IN UINT32 SectorCount
) )
{ {
UINT8 SenseDataLength; UINT8 SenseDataLength;
@ -2306,8 +2332,16 @@ ScsiDiskRead16 (
UINT8 TargetStatus; UINT8 TargetStatus;
UINTN Action; 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; *NeedRetry = FALSE;
*NumberOfSenseKeys = 0;
Action = ACTION_NO_ACTION; Action = ACTION_NO_ACTION;
SenseDataLength = (UINT8) (ScsiDiskDevice->SenseDataNumber * sizeof (EFI_SCSI_SENSE_DATA)); SenseDataLength = (UINT8) (ScsiDiskDevice->SenseDataNumber * sizeof (EFI_SCSI_SENSE_DATA));
ReturnStatus = ScsiRead16Command ( ReturnStatus = ScsiRead16Command (
@ -2320,7 +2354,7 @@ ScsiDiskRead16 (
DataBuffer, DataBuffer,
DataLength, DataLength,
StartLba, StartLba,
SectorSize SectorCount
); );
if (ReturnStatus == EFI_NOT_READY) { if (ReturnStatus == EFI_NOT_READY) {
*NeedRetry = TRUE; *NeedRetry = TRUE;
@ -2360,14 +2394,26 @@ ScsiDiskRead16 (
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
} }
if (TargetStatus == EFI_EXT_SCSI_STATUS_TARGET_CHECK_CONDITION) { if ((TargetStatus == EFI_EXT_SCSI_STATUS_TARGET_CHECK_CONDITION) || (EFI_ERROR (ReturnStatus))) {
DEBUG ((EFI_D_VERBOSE, "ScsiDiskRead16: Check Condition happened!\n")); DEBUG ((EFI_D_ERROR, "ScsiDiskRead16: Check Condition happened!\n"));
Status = DetectMediaParsingSenseKeys (ScsiDiskDevice, ScsiDiskDevice->SenseData, SenseDataLength / sizeof (EFI_SCSI_SENSE_DATA), &Action); Status = DetectMediaParsingSenseKeys (ScsiDiskDevice, ScsiDiskDevice->SenseData, SenseDataLength / sizeof (EFI_SCSI_SENSE_DATA), &Action);
if (EFI_ERROR (Status)) { if (Action == ACTION_RETRY_COMMAND_LATER) {
return Status;
} else if (Action == ACTION_RETRY_COMMAND_LATER) {
*NeedRetry = TRUE; *NeedRetry = TRUE;
return EFI_DEVICE_ERROR; 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 { } else {
*NeedRetry = FALSE; *NeedRetry = FALSE;
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
@ -2383,28 +2429,24 @@ ScsiDiskRead16 (
@param ScsiDiskDevice The pointer of ScsiDiskDevice @param ScsiDiskDevice The pointer of ScsiDiskDevice
@param NeedRetry The pointer of flag indicates if needs retry if error happens @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 Timeout The time to complete the command
@param DataBuffer The buffer to fill with the read out data @param DataBuffer The buffer to fill with the read out data
@param DataLength The length of buffer @param DataLength The length of buffer
@param StartLba The start logic block address @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 EFI_STATUS
ScsiDiskWrite16 ( ScsiDiskWrite16 (
IN SCSI_DISK_DEV *ScsiDiskDevice, IN SCSI_DISK_DEV *ScsiDiskDevice,
OUT BOOLEAN *NeedRetry, OUT BOOLEAN *NeedRetry,
OUT EFI_SCSI_SENSE_DATA **SenseDataArray, OPTIONAL
OUT UINTN *NumberOfSenseKeys,
IN UINT64 Timeout, IN UINT64 Timeout,
IN UINT8 *DataBuffer, IN UINT8 *DataBuffer,
IN OUT UINT32 *DataLength, IN OUT UINT32 *DataLength,
IN UINT64 StartLba, IN UINT64 StartLba,
IN UINT32 SectorSize IN UINT32 SectorCount
) )
{ {
EFI_STATUS Status; EFI_STATUS Status;
@ -2414,8 +2456,16 @@ ScsiDiskWrite16 (
UINT8 TargetStatus; UINT8 TargetStatus;
UINTN Action; 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; *NeedRetry = FALSE;
*NumberOfSenseKeys = 0;
Action = ACTION_NO_ACTION; Action = ACTION_NO_ACTION;
SenseDataLength = (UINT8) (ScsiDiskDevice->SenseDataNumber * sizeof (EFI_SCSI_SENSE_DATA)); SenseDataLength = (UINT8) (ScsiDiskDevice->SenseDataNumber * sizeof (EFI_SCSI_SENSE_DATA));
ReturnStatus = ScsiWrite16Command ( ReturnStatus = ScsiWrite16Command (
@ -2428,7 +2478,7 @@ ScsiDiskWrite16 (
DataBuffer, DataBuffer,
DataLength, DataLength,
StartLba, StartLba,
SectorSize SectorCount
); );
if (ReturnStatus == EFI_NOT_READY) { if (ReturnStatus == EFI_NOT_READY) {
*NeedRetry = TRUE; *NeedRetry = TRUE;
@ -2468,14 +2518,26 @@ ScsiDiskWrite16 (
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;
} }
if (TargetStatus == EFI_EXT_SCSI_STATUS_TARGET_CHECK_CONDITION) { if ((TargetStatus == EFI_EXT_SCSI_STATUS_TARGET_CHECK_CONDITION) || (EFI_ERROR (ReturnStatus))) {
DEBUG ((EFI_D_VERBOSE, "ScsiDiskWrite16: Check Condition happened!\n")); DEBUG ((EFI_D_ERROR, "ScsiDiskWrite16: Check Condition happened!\n"));
Status = DetectMediaParsingSenseKeys (ScsiDiskDevice, ScsiDiskDevice->SenseData, SenseDataLength / sizeof (EFI_SCSI_SENSE_DATA), &Action); Status = DetectMediaParsingSenseKeys (ScsiDiskDevice, ScsiDiskDevice->SenseData, SenseDataLength / sizeof (EFI_SCSI_SENSE_DATA), &Action);
if (EFI_ERROR (Status)) { if (Action == ACTION_RETRY_COMMAND_LATER) {
return Status;
} else if (Action == ACTION_RETRY_COMMAND_LATER) {
*NeedRetry = TRUE; *NeedRetry = TRUE;
return EFI_DEVICE_ERROR; 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 { } else {
*NeedRetry = FALSE; *NeedRetry = FALSE;
return EFI_DEVICE_ERROR; return EFI_DEVICE_ERROR;

View File

@ -1,7 +1,7 @@
/** @file /** @file
Header file for SCSI Disk Driver. Header file for SCSI Disk Driver.
Copyright (c) 2004 - 2013, Intel Corporation. All rights reserved.<BR> Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License 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 which accompanies this distribution. The full text of the license may be found at
@ -93,6 +93,7 @@ extern EFI_COMPONENT_NAME2_PROTOCOL gScsiDiskComponentName2;
#define ACTION_NO_ACTION 0x00 #define ACTION_NO_ACTION 0x00
#define ACTION_READ_CAPACITY 0x01 #define ACTION_READ_CAPACITY 0x01
#define ACTION_RETRY_COMMAND_LATER 0x02 #define ACTION_RETRY_COMMAND_LATER 0x02
#define ACTION_RETRY_WITH_BACKOFF_ALGO 0x03
#define SCSI_COMMAND_VERSION_1 0x01 #define SCSI_COMMAND_VERSION_1 0x01
#define SCSI_COMMAND_VERSION_2 0x02 #define SCSI_COMMAND_VERSION_2 0x02
@ -717,17 +718,15 @@ ScsiDiskWriteSectors (
); );
/** /**
Submit Read command. Submit Read(10) command.
@param ScsiDiskDevice The pointer of ScsiDiskDevice @param ScsiDiskDevice The pointer of ScsiDiskDevice
@param NeedRetry The pointer of flag indicates if needs retry if error happens @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 Timeout The time to complete the command
@param DataBuffer The buffer to fill with the read out data @param DataBuffer The buffer to fill with the read out data
@param DataLength The length of buffer @param DataLength The length of buffer
@param StartLba The start logic block address @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 ScsiRead10Command().
**/ **/
@ -735,27 +734,23 @@ EFI_STATUS
ScsiDiskRead10 ( ScsiDiskRead10 (
IN SCSI_DISK_DEV *ScsiDiskDevice, IN SCSI_DISK_DEV *ScsiDiskDevice,
OUT BOOLEAN *NeedRetry, OUT BOOLEAN *NeedRetry,
OUT EFI_SCSI_SENSE_DATA **SenseDataArray, OPTIONAL
OUT UINTN *NumberOfSenseKeys,
IN UINT64 Timeout, IN UINT64 Timeout,
OUT UINT8 *DataBuffer, OUT UINT8 *DataBuffer,
IN OUT UINT32 *DataLength, IN OUT UINT32 *DataLength,
IN UINT32 StartLba, IN UINT32 StartLba,
IN UINT32 SectorSize IN UINT32 SectorCount
); );
/** /**
Submit Write Command. Submit Write(10) Command.
@param ScsiDiskDevice The pointer of ScsiDiskDevice @param ScsiDiskDevice The pointer of ScsiDiskDevice
@param NeedRetry The pointer of flag indicates if needs retry if error happens @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 Timeout The time to complete the command
@param DataBuffer The buffer to fill with the read out data @param DataBuffer The buffer to fill with the read out data
@param DataLength The length of buffer @param DataLength The length of buffer
@param StartLba The start logic block address @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 ScsiWrite10Command().
@ -764,13 +759,11 @@ EFI_STATUS
ScsiDiskWrite10 ( ScsiDiskWrite10 (
IN SCSI_DISK_DEV *ScsiDiskDevice, IN SCSI_DISK_DEV *ScsiDiskDevice,
OUT BOOLEAN *NeedRetry, OUT BOOLEAN *NeedRetry,
OUT EFI_SCSI_SENSE_DATA **SenseDataArray, OPTIONAL
OUT UINTN *NumberOfSenseKeys,
IN UINT64 Timeout, IN UINT64 Timeout,
IN UINT8 *DataBuffer, IN UINT8 *DataBuffer,
IN OUT UINT32 *DataLength, IN OUT UINT32 *DataLength,
IN UINT32 StartLba, IN UINT32 StartLba,
IN UINT32 SectorSize IN UINT32 SectorCount
); );
/** /**
@ -778,27 +771,23 @@ ScsiDiskWrite10 (
@param ScsiDiskDevice The pointer of ScsiDiskDevice @param ScsiDiskDevice The pointer of ScsiDiskDevice
@param NeedRetry The pointer of flag indicates if needs retry if error happens @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 Timeout The time to complete the command
@param DataBuffer The buffer to fill with the read out data @param DataBuffer The buffer to fill with the read out data
@param DataLength The length of buffer @param DataLength The length of buffer
@param StartLba The start logic block address @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 EFI_STATUS
ScsiDiskRead16 ( ScsiDiskRead16 (
IN SCSI_DISK_DEV *ScsiDiskDevice, IN SCSI_DISK_DEV *ScsiDiskDevice,
OUT BOOLEAN *NeedRetry, OUT BOOLEAN *NeedRetry,
OUT EFI_SCSI_SENSE_DATA **SenseDataArray, OPTIONAL
OUT UINTN *NumberOfSenseKeys,
IN UINT64 Timeout, IN UINT64 Timeout,
OUT UINT8 *DataBuffer, OUT UINT8 *DataBuffer,
IN OUT UINT32 *DataLength, IN OUT UINT32 *DataLength,
IN UINT64 StartLba, IN UINT64 StartLba,
IN UINT32 SectorSize IN UINT32 SectorCount
); );
/** /**
@ -806,28 +795,24 @@ ScsiDiskRead16 (
@param ScsiDiskDevice The pointer of ScsiDiskDevice @param ScsiDiskDevice The pointer of ScsiDiskDevice
@param NeedRetry The pointer of flag indicates if needs retry if error happens @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 Timeout The time to complete the command
@param DataBuffer The buffer to fill with the read out data @param DataBuffer The buffer to fill with the read out data
@param DataLength The length of buffer @param DataLength The length of buffer
@param StartLba The start logic block address @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 EFI_STATUS
ScsiDiskWrite16 ( ScsiDiskWrite16 (
IN SCSI_DISK_DEV *ScsiDiskDevice, IN SCSI_DISK_DEV *ScsiDiskDevice,
OUT BOOLEAN *NeedRetry, OUT BOOLEAN *NeedRetry,
OUT EFI_SCSI_SENSE_DATA **SenseDataArray, OPTIONAL
OUT UINTN *NumberOfSenseKeys,
IN UINT64 Timeout, IN UINT64 Timeout,
IN UINT8 *DataBuffer, IN UINT8 *DataBuffer,
IN OUT UINT32 *DataLength, IN OUT UINT32 *DataLength,
IN UINT64 StartLba, IN UINT64 StartLba,
IN UINT32 SectorSize IN UINT32 SectorCount
); );
/** /**