diff --git a/DiscImageChef.Devices/ChangeLog b/DiscImageChef.Devices/ChangeLog index a558984a..24dc49e5 100644 --- a/DiscImageChef.Devices/ChangeLog +++ b/DiscImageChef.Devices/ChangeLog @@ -1,3 +1,11 @@ +2015-11-23 Natalia Portillo + + * Device/ScsiCommands.cs: + Implemented SCSI READ CAPACITY(16). + + * Enums.cs: + Added SCSI SERVICE ACTIONs. + 2015-11-23 Natalia Portillo * Device/ScsiCommands.cs: diff --git a/DiscImageChef.Devices/Device/ScsiCommands.cs b/DiscImageChef.Devices/Device/ScsiCommands.cs index 126fdf35..7dcce897 100644 --- a/DiscImageChef.Devices/Device/ScsiCommands.cs +++ b/DiscImageChef.Devices/Device/ScsiCommands.cs @@ -569,7 +569,7 @@ namespace DiscImageChef.Devices /// Sends the SCSI READ CAPACITY command /// /// true if the command failed and contains the sense buffer. - /// Buffer where the SCSI GET CONFIGURATION response will be stored + /// Buffer where the SCSI READ CAPACITY response will be stored /// Sense buffer. /// Timeout in seconds. /// Duration in milliseconds it took for the device to execute the command. @@ -582,7 +582,7 @@ namespace DiscImageChef.Devices /// Sends the SCSI READ CAPACITY command /// /// true if the command failed and contains the sense buffer. - /// Buffer where the SCSI GET CONFIGURATION response will be stored + /// Buffer where the SCSI READ CAPACITY response will be stored /// Sense buffer. /// Indicates that is relative to current medium position /// Address where information is requested from, only valid if is set @@ -617,6 +617,67 @@ namespace DiscImageChef.Devices return sense; } + + /// + /// Sends the SCSI READ CAPACITY(16) command + /// + /// true if the command failed and contains the sense buffer. + /// Buffer where the SCSI READ CAPACITY(16) response will be stored + /// Sense buffer. + /// Timeout in seconds. + /// Duration in milliseconds it took for the device to execute the command. + public bool ReadCapacity16(out byte[] buffer, out byte[] senseBuffer, uint timeout, out double duration) + { + return ReadCapacity16(out buffer, out senseBuffer, 0, false, timeout, out duration); + } + + /// + /// Sends the SCSI READ CAPACITY(16) command + /// + /// true if the command failed and contains the sense buffer. + /// Buffer where the SCSI READ CAPACITY(16) response will be stored + /// Sense buffer. + /// Address where information is requested from, only valid if is set + /// If set, it is requesting partial media capacity + /// Timeout in seconds. + /// Duration in milliseconds it took for the device to execute the command. + public bool ReadCapacity16(out byte[] buffer, out byte[] senseBuffer, ulong address, bool PMI, uint timeout, out double duration) + { + senseBuffer = new byte[32]; + byte[] cdb = new byte[16]; + buffer = new byte[32]; + bool sense; + + cdb[0] = (byte)ScsiCommands.ServiceActionIn; + cdb[1] = (byte)ScsiServiceActions.ReadCapacity16; + + if (PMI) + { + cdb[14] = 0x01; + byte[] temp = BitConverter.GetBytes(address); + cdb[2] = temp[7]; + cdb[3] = temp[6]; + cdb[4] = temp[5]; + cdb[5] = temp[4]; + cdb[6] = temp[3]; + cdb[7] = temp[2]; + cdb[8] = temp[1]; + cdb[9] = temp[0]; + } + + cdb[10] = (byte)((buffer.Length & 0xFF000000) >> 24); + cdb[11] = (byte)((buffer.Length & 0xFF0000) >> 16); + cdb[12] = (byte)((buffer.Length & 0xFF00) >> 8); + cdb[13] = (byte)(buffer.Length & 0xFF); + + + lastError = SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration, out sense); + error = lastError != 0; + + DicConsole.DebugWriteLine("SCSI Device", "READ CAPACITY(16) took {0} ms.", duration); + + return sense; + } } } diff --git a/DiscImageChef.Devices/Enums.cs b/DiscImageChef.Devices/Enums.cs index 264b92d3..d3cc5ea9 100644 --- a/DiscImageChef.Devices/Enums.cs +++ b/DiscImageChef.Devices/Enums.cs @@ -2984,5 +2984,39 @@ namespace DiscImageChef.Devices /// PAC = 0x30 } + + public enum ScsiServiceActions : byte + { + // SERVICE ACTION IN + + /// + /// Requests parameter data describing provisioning status for the specified LBA + /// SBC-3 rev. 25 + /// + GetLBAStatus = 0x12, + /// + /// Gets device capacity + /// SBC-2 rev. 4 + /// + ReadCapacity16 = 0x10, + /// + /// Reads blocks from device in a vendor-specific way that should include the ECC alongside the data + /// SBC-2 rev. 4 + /// + ReadLong16 = 0x11, + /// + /// Requests information indicating the user data segments on the ports and LUNs to access them + /// SBC-3 rev. 25 + /// + ReportReferrals = 0x13, + + // SERVICE ACTION OUT + + /// + /// Writes blocks to the device with a vendor specified format that shall include the ECC alongside the data + /// SBC-2 rev. 4 + /// + WriteLong16 = ReadLong16 + } }