If SCSI version support Read/Write (16) command, use both commands to access disk especially for above 2TB.

git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10550 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
li-elvin 2010-05-28 06:58:59 +00:00
parent a24faca37a
commit a108933ea8
2 changed files with 244 additions and 41 deletions

View File

@ -1591,7 +1591,6 @@ ScsiDiskReadSectors (
)
{
UINTN BlocksRemaining;
UINT32 Lba32;
UINT8 *PtrBuffer;
UINT32 BlockSize;
UINT32 ByteCount;
@ -1604,6 +1603,7 @@ ScsiDiskReadSectors (
BOOLEAN NeedRetry;
EFI_SCSI_SENSE_DATA *SenseData;
UINTN NumberOfSenseKeys;
UINT8 ScsiVersion;
SenseData = NULL;
NumberOfSenseKeys = 0;
@ -1612,21 +1612,28 @@ ScsiDiskReadSectors (
BlocksRemaining = NumberOfBlocks;
BlockSize = ScsiDiskDevice->BlkIo.Media->BlockSize;
ScsiVersion = (UINT8)(ScsiDiskDevice->InquiryData.Version & 0x03);
//
// limit the data bytes that can be transferred by one Read(10) Command
// limit the data bytes that can be transferred by one Read(10) or Read(16) Command
//
MaxBlock = 65536;
if (ScsiVersion < SCSI_COMMAND_VERSION_3) {
MaxBlock = 65535;
} else {
MaxBlock = 4294967295;
}
PtrBuffer = Buffer;
Lba32 = (UINT32) Lba;
while (BlocksRemaining > 0) {
if (BlocksRemaining <= MaxBlock) {
SectorCount = (UINT16) BlocksRemaining;
if (ScsiVersion < SCSI_COMMAND_VERSION_3) {
SectorCount = (UINT16) BlocksRemaining;
} else {
SectorCount = (UINT32) BlocksRemaining;
}
} else {
SectorCount = MaxBlock;
}
@ -1635,18 +1642,31 @@ ScsiDiskReadSectors (
MaxRetry = 2;
for (Index = 0; Index < MaxRetry; Index++) {
Status = ScsiDiskRead10 (
ScsiDiskDevice,
&NeedRetry,
&SenseData,
&NumberOfSenseKeys,
Timeout,
PtrBuffer,
&ByteCount,
Lba32,
SectorCount
);
if (ScsiVersion >= SCSI_COMMAND_VERSION_3) {
Status = ScsiDiskRead16 (
ScsiDiskDevice,
&NeedRetry,
&SenseData,
&NumberOfSenseKeys,
Timeout,
PtrBuffer,
&ByteCount,
Lba,
SectorCount
);
} else {
Status = ScsiDiskRead10 (
ScsiDiskDevice,
&NeedRetry,
&SenseData,
&NumberOfSenseKeys,
Timeout,
PtrBuffer,
&ByteCount,
(UINT32) Lba,
SectorCount
);
}
if (!EFI_ERROR (Status)) {
break;
}
@ -1666,7 +1686,7 @@ ScsiDiskReadSectors (
//
SectorCount = ByteCount / BlockSize;
Lba32 += SectorCount;
Lba += SectorCount;
PtrBuffer = PtrBuffer + SectorCount * BlockSize;
BlocksRemaining -= SectorCount;
}
@ -1695,7 +1715,6 @@ ScsiDiskWriteSectors (
)
{
UINTN BlocksRemaining;
UINT32 Lba32;
UINT8 *PtrBuffer;
UINT32 BlockSize;
UINT32 ByteCount;
@ -1708,6 +1727,7 @@ ScsiDiskWriteSectors (
BOOLEAN NeedRetry;
EFI_SCSI_SENSE_DATA *SenseData;
UINTN NumberOfSenseKeys;
UINT8 ScsiVersion;
SenseData = NULL;
NumberOfSenseKeys = 0;
@ -1716,21 +1736,28 @@ ScsiDiskWriteSectors (
BlocksRemaining = NumberOfBlocks;
BlockSize = ScsiDiskDevice->BlkIo.Media->BlockSize;
ScsiVersion = (UINT8)(ScsiDiskDevice->InquiryData.Version & 0x03);
//
// limit the data bytes that can be transferred by one Write(10) Command
// limit the data bytes that can be transferred by one Read(10) or Read(16) Command
//
MaxBlock = 65536;
if (ScsiVersion < SCSI_COMMAND_VERSION_3) {
MaxBlock = 65535;
} else {
MaxBlock = 4294967295;
}
PtrBuffer = Buffer;
Lba32 = (UINT32) Lba;
while (BlocksRemaining > 0) {
if (BlocksRemaining <= MaxBlock) {
SectorCount = (UINT16) BlocksRemaining;
if (ScsiVersion < SCSI_COMMAND_VERSION_3) {
SectorCount = (UINT16) BlocksRemaining;
} else {
SectorCount = (UINT32) BlocksRemaining;
}
} else {
SectorCount = MaxBlock;
}
@ -1738,17 +1765,31 @@ ScsiDiskWriteSectors (
Timeout = EFI_TIMER_PERIOD_SECONDS (2);
MaxRetry = 2;
for (Index = 0; Index < MaxRetry; Index++) {
Status = ScsiDiskWrite10 (
ScsiDiskDevice,
&NeedRetry,
&SenseData,
&NumberOfSenseKeys,
Timeout,
PtrBuffer,
&ByteCount,
Lba32,
SectorCount
);
if (ScsiVersion >= SCSI_COMMAND_VERSION_3) {
Status = ScsiDiskWrite16 (
ScsiDiskDevice,
&NeedRetry,
&SenseData,
&NumberOfSenseKeys,
Timeout,
PtrBuffer,
&ByteCount,
Lba,
SectorCount
);
} else {
Status = ScsiDiskWrite10 (
ScsiDiskDevice,
&NeedRetry,
&SenseData,
&NumberOfSenseKeys,
Timeout,
PtrBuffer,
&ByteCount,
(UINT32) Lba,
SectorCount
);
}
if (!EFI_ERROR (Status)) {
break;
}
@ -1766,7 +1807,7 @@ ScsiDiskWriteSectors (
//
SectorCount = ByteCount / BlockSize;
Lba32 += SectorCount;
Lba += SectorCount;
PtrBuffer = PtrBuffer + SectorCount * BlockSize;
BlocksRemaining -= SectorCount;
}
@ -1776,7 +1817,7 @@ ScsiDiskWriteSectors (
/**
Submit Read command.
Submit Read(10) command.
@param ScsiDiskDevice The pointer of ScsiDiskDevice
@param NeedRetry The pointer of flag indicates if needs retry if error happens
@ -1828,7 +1869,7 @@ ScsiDiskRead10 (
/**
Submit Write Command.
Submit Write(10) Command.
@param ScsiDiskDevice The pointer of ScsiDiskDevice
@param NeedRetry The pointer of flag indicates if needs retry if error happens
@ -1880,6 +1921,111 @@ ScsiDiskWrite10 (
}
/**
Submit Read(16) command.
@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
@return EFI_STATUS is returned by calling ScsiRead10Command().
**/
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
)
{
UINT8 SenseDataLength;
EFI_STATUS Status;
UINT8 HostAdapterStatus;
UINT8 TargetStatus;
*NeedRetry = FALSE;
*NumberOfSenseKeys = 0;
SenseDataLength = 0;
Status = ScsiRead16Command (
ScsiDiskDevice->ScsiIo,
Timeout,
NULL,
&SenseDataLength,
&HostAdapterStatus,
&TargetStatus,
DataBuffer,
DataLength,
StartLba,
SectorSize
);
return Status;
}
/**
Submit Write(16) Command.
@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
@return EFI_STATUS is returned by calling ScsiWrite10Command().
**/
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
)
{
EFI_STATUS Status;
UINT8 SenseDataLength;
UINT8 HostAdapterStatus;
UINT8 TargetStatus;
*NeedRetry = FALSE;
*NumberOfSenseKeys = 0;
SenseDataLength = 0;
Status = ScsiWrite16Command (
ScsiDiskDevice->ScsiIo,
Timeout,
NULL,
&SenseDataLength,
&HostAdapterStatus,
&TargetStatus,
DataBuffer,
DataLength,
StartLba,
SectorSize
);
return Status;
}
/**
Check sense key to find if media presents.

View File

@ -764,6 +764,63 @@ ScsiDiskWrite10 (
IN UINT32 SectorSize
);
/**
Submit Read(16) command.
@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
@return EFI_STATUS is returned by calling ScsiRead10Command().
**/
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
);
/**
Submit Write(16) Command.
@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
@return EFI_STATUS is returned by calling ScsiWrite10Command().
**/
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
);
/**
Get information from media read capacity command.