From a108933ea8573068047d34c745f5bd2f91dec4b2 Mon Sep 17 00:00:00 2001 From: li-elvin Date: Fri, 28 May 2010 06:58:59 +0000 Subject: [PATCH] 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 --- MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c | 228 +++++++++++++++---- MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h | 57 +++++ 2 files changed, 244 insertions(+), 41 deletions(-) diff --git a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c index 5202d82d01..7d6d7b0e21 100644 --- a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c +++ b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.c @@ -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. diff --git a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h index 68644f6342..d2f21139c0 100644 --- a/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h +++ b/MdeModulePkg/Bus/Scsi/ScsiDiskDxe/ScsiDisk.h @@ -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. -- 2.39.2