On Linux use direct SG_IO.

This commit is contained in:
2018-04-02 23:10:13 +01:00
parent 2201c2b98d
commit 2bde9bf1b8

View File

@@ -56,7 +56,8 @@ namespace DiscImageChef.Devices.Linux
/// <c>True</c> if SCSI error returned non-OK status and <paramref name="senseBuffer" /> contains SCSI
/// sense
/// </param>
internal static int SendScsiCommand(int fd, byte[] cdb, ref byte[] buffer, out byte[] senseBuffer, uint timeout,
internal static int SendScsiCommand(int fd, byte[] cdb, ref byte[] buffer,
out byte[] senseBuffer, uint timeout,
ScsiIoctlDirection direction, out double duration, out bool sense)
{
senseBuffer = null;
@@ -78,6 +79,7 @@ namespace DiscImageChef.Devices.Linux
ioHdr.cmdp = Marshal.AllocHGlobal(cdb.Length);
ioHdr.sbp = Marshal.AllocHGlobal(senseBuffer.Length);
ioHdr.timeout = timeout * 1000;
ioHdr.flags = (uint)SgFlags.DirectIo;
Marshal.Copy(buffer, 0, ioHdr.dxferp, buffer.Length);
Marshal.Copy(cdb, 0, ioHdr.cmdp, cdb.Length);
@@ -141,9 +143,11 @@ namespace DiscImageChef.Devices.Linux
/// <param name="protocol">ATA protocol to use</param>
/// <param name="transferRegister">Which register contains the transfer count</param>
/// <param name="transferBlocks">Set to <c>true</c> if the transfer count is in blocks, otherwise it is in bytes</param>
internal static int SendAtaCommand(int fd, AtaRegistersChs registers, out AtaErrorRegistersChs errorRegisters,
internal static int SendAtaCommand(int fd, AtaRegistersChs registers,
out AtaErrorRegistersChs errorRegisters,
AtaProtocol protocol, AtaTransferRegister transferRegister,
ref byte[] buffer, uint timeout, bool transferBlocks, out double duration,
ref byte[] buffer, uint timeout, bool transferBlocks,
out double duration,
out bool sense)
{
duration = 0;
@@ -183,7 +187,8 @@ namespace DiscImageChef.Devices.Linux
cdb[13] = registers.DeviceHead;
cdb[14] = registers.Command;
int error = SendScsiCommand(fd, cdb, ref buffer, out byte[] senseBuffer, timeout,
int error = SendScsiCommand(fd, cdb, ref buffer,
out byte[] senseBuffer, timeout,
AtaProtocolToScsiDirection(protocol), out duration, out sense);
if(senseBuffer.Length < 22 || senseBuffer[8] != 0x09 && senseBuffer[9] != 0x0C) return error;
@@ -218,8 +223,10 @@ namespace DiscImageChef.Devices.Linux
/// <param name="transferBlocks">Set to <c>true</c> if the transfer count is in blocks, otherwise it is in bytes</param>
internal static int SendAtaCommand(int fd, AtaRegistersLba28 registers,
out AtaErrorRegistersLba28 errorRegisters, AtaProtocol protocol,
AtaTransferRegister transferRegister, ref byte[] buffer, uint timeout,
bool transferBlocks, out double duration, out bool sense)
AtaTransferRegister transferRegister, ref byte[] buffer,
uint timeout,
bool transferBlocks, out double duration,
out bool sense)
{
duration = 0;
sense = false;
@@ -258,7 +265,8 @@ namespace DiscImageChef.Devices.Linux
cdb[13] = registers.DeviceHead;
cdb[14] = registers.Command;
int error = SendScsiCommand(fd, cdb, ref buffer, out byte[] senseBuffer, timeout,
int error = SendScsiCommand(fd, cdb, ref buffer,
out byte[] senseBuffer, timeout,
AtaProtocolToScsiDirection(protocol), out duration, out sense);
if(senseBuffer.Length < 22 || senseBuffer[8] != 0x09 && senseBuffer[9] != 0x0C) return error;
@@ -293,8 +301,10 @@ namespace DiscImageChef.Devices.Linux
/// <param name="transferBlocks">Set to <c>true</c> if the transfer count is in blocks, otherwise it is in bytes</param>
internal static int SendAtaCommand(int fd, AtaRegistersLba48 registers,
out AtaErrorRegistersLba48 errorRegisters, AtaProtocol protocol,
AtaTransferRegister transferRegister, ref byte[] buffer, uint timeout,
bool transferBlocks, out double duration, out bool sense)
AtaTransferRegister transferRegister, ref byte[] buffer,
uint timeout,
bool transferBlocks, out double duration,
out bool sense)
{
duration = 0;
sense = false;
@@ -339,7 +349,8 @@ namespace DiscImageChef.Devices.Linux
cdb[13] = registers.DeviceHead;
cdb[14] = registers.Command;
int error = SendScsiCommand(fd, cdb, ref buffer, out byte[] senseBuffer, timeout,
int error = SendScsiCommand(fd, cdb, ref buffer,
out byte[] senseBuffer, timeout,
AtaProtocolToScsiDirection(protocol), out duration, out sense);
if(senseBuffer.Length < 22 || senseBuffer[8] != 0x09 && senseBuffer[9] != 0x0C) return error;
@@ -377,9 +388,12 @@ namespace DiscImageChef.Devices.Linux
/// <param name="argument">Command argument</param>
/// <param name="response">Response registers</param>
/// <param name="blockSize">Size of block in bytes</param>
internal static int SendMmcCommand(int fd, MmcCommands command, bool write, bool isApplication, MmcFlags flags,
uint argument, uint blockSize, uint blocks, ref byte[] buffer,
out uint[] response, out double duration, out bool sense, uint timeout = 0)
internal static int SendMmcCommand(int fd, MmcCommands command, bool write,
bool isApplication, MmcFlags flags,
uint argument, uint blockSize, uint blocks,
ref byte[] buffer,
out uint[] response, out double duration, out bool sense,
uint timeout = 0)
{
response = null;
duration = 0;
@@ -403,6 +417,7 @@ namespace DiscImageChef.Devices.Linux
ioCmd.data_timeout_ns = timeout * 1000000000;
ioCmd.cmd_timeout_ms = timeout * 1000;
}
ioCmd.data_ptr = (ulong)bufPtr;
Marshal.Copy(buffer, 0, bufPtr, buffer.Length);