Send buffer to SDHCI before sending command in Windows.

This commit is contained in:
2019-10-27 20:44:32 +00:00
parent c58161478d
commit a7aeb0bba6

View File

@@ -40,7 +40,7 @@ using Microsoft.Win32.SafeHandles;
namespace DiscImageChef.Devices.Windows namespace DiscImageChef.Devices.Windows
{ {
[SuppressMessage("ReSharper", "UnusedParameter.Global")] [SuppressMessage("ReSharper", "UnusedParameter.Global")]
static class Command internal static class Command
{ {
/// <summary> /// <summary>
/// Sends a SCSI command /// Sends a SCSI command
@@ -58,46 +58,46 @@ namespace DiscImageChef.Devices.Windows
/// sense /// sense
/// </param> /// </param>
internal static int SendScsiCommand(SafeFileHandle fd, byte[] cdb, ref byte[] buffer, internal static int SendScsiCommand(SafeFileHandle fd, byte[] cdb, ref byte[] buffer,
out byte[] senseBuffer, out byte[] senseBuffer,
uint timeout, ScsiIoctlDirection direction, out double duration, uint timeout, ScsiIoctlDirection direction, out double duration,
out bool sense) out bool sense)
{ {
senseBuffer = null; senseBuffer = null;
duration = 0; duration = 0;
sense = false; sense = false;
if(buffer == null) return -1; if (buffer == null) return -1;
ScsiPassThroughDirectAndSenseBuffer sptdSb = new ScsiPassThroughDirectAndSenseBuffer var sptdSb = new ScsiPassThroughDirectAndSenseBuffer
{ {
SenseBuf = new byte[32], SenseBuf = new byte[32],
sptd = new ScsiPassThroughDirect sptd = new ScsiPassThroughDirect
{ {
Cdb = new byte[16], Cdb = new byte[16],
CdbLength = (byte)cdb.Length, CdbLength = (byte) cdb.Length,
SenseInfoLength = 32, SenseInfoLength = 32,
DataIn = direction, DataIn = direction,
DataTransferLength = (uint)buffer.Length, DataTransferLength = (uint) buffer.Length,
TimeOutValue = timeout, TimeOutValue = timeout,
DataBuffer = Marshal.AllocHGlobal(buffer.Length) DataBuffer = Marshal.AllocHGlobal(buffer.Length)
} }
}; };
sptdSb.sptd.Length = (ushort)Marshal.SizeOf(sptdSb.sptd); sptdSb.sptd.Length = (ushort) Marshal.SizeOf(sptdSb.sptd);
sptdSb.sptd.SenseInfoOffset = (uint)Marshal.SizeOf(sptdSb.sptd); sptdSb.sptd.SenseInfoOffset = (uint) Marshal.SizeOf(sptdSb.sptd);
Array.Copy(cdb, sptdSb.sptd.Cdb, cdb.Length); Array.Copy(cdb, sptdSb.sptd.Cdb, cdb.Length);
uint k = 0; uint k = 0;
int error = 0; var error = 0;
Marshal.Copy(buffer, 0, sptdSb.sptd.DataBuffer, buffer.Length); Marshal.Copy(buffer, 0, sptdSb.sptd.DataBuffer, buffer.Length);
DateTime start = DateTime.Now; var start = DateTime.Now;
bool hasError = !Extern.DeviceIoControlScsi(fd, WindowsIoctl.IoctlScsiPassThroughDirect, ref sptdSb, var hasError = !Extern.DeviceIoControlScsi(fd, WindowsIoctl.IoctlScsiPassThroughDirect, ref sptdSb,
(uint)Marshal.SizeOf(sptdSb), ref sptdSb, (uint) Marshal.SizeOf(sptdSb), ref sptdSb,
(uint)Marshal.SizeOf(sptdSb), ref k, IntPtr.Zero); (uint) Marshal.SizeOf(sptdSb), ref k, IntPtr.Zero);
DateTime end = DateTime.Now; var end = DateTime.Now;
if(hasError) error = Marshal.GetLastWin32Error(); if (hasError) error = Marshal.GetLastWin32Error();
Marshal.Copy(sptdSb.sptd.DataBuffer, buffer, 0, buffer.Length); Marshal.Copy(sptdSb.sptd.DataBuffer, buffer, 0, buffer.Length);
@@ -125,43 +125,43 @@ namespace DiscImageChef.Devices.Windows
/// <param name="registers">Registers to send to drive</param> /// <param name="registers">Registers to send to drive</param>
/// <param name="errorRegisters">Registers returned by drive</param> /// <param name="errorRegisters">Registers returned by drive</param>
/// <param name="protocol">ATA protocol to use</param> /// <param name="protocol">ATA protocol to use</param>
internal static int SendAtaCommand(SafeFileHandle fd, AtaRegistersChs registers, internal static int SendAtaCommand(SafeFileHandle fd, AtaRegistersChs registers,
out AtaErrorRegistersChs errorRegisters, AtaProtocol protocol, out AtaErrorRegistersChs errorRegisters, AtaProtocol protocol,
ref byte[] buffer, uint timeout, ref byte[] buffer, uint timeout,
out double duration, out bool sense) out double duration, out bool sense)
{ {
duration = 0; duration = 0;
sense = false; sense = false;
errorRegisters = new AtaErrorRegistersChs(); errorRegisters = new AtaErrorRegistersChs();
if(buffer == null) return -1; if (buffer == null) return -1;
uint offsetForBuffer = (uint)(Marshal.SizeOf(typeof(AtaPassThroughDirect)) + Marshal.SizeOf(typeof(uint))); var offsetForBuffer = (uint) (Marshal.SizeOf(typeof(AtaPassThroughEx)) + Marshal.SizeOf(typeof(uint)));
AtaPassThroughDirectWithBuffer aptdBuf = new AtaPassThroughDirectWithBuffer var aptdBuf = new AtaPassThroughExBuffer
{ {
aptd = new AtaPassThroughDirect aptd = new AtaPassThroughEx
{ {
TimeOutValue = timeout, TimeOutValue = timeout,
DataBuffer = (IntPtr)offsetForBuffer, DataBufferOffset = (IntPtr) offsetForBuffer,
Length = (ushort)Marshal.SizeOf(typeof(AtaPassThroughDirect)), Length = (ushort) Marshal.SizeOf(typeof(AtaPassThroughEx)),
DataTransferLength = (uint)buffer.Length, DataTransferLength = (uint) buffer.Length,
PreviousTaskFile = new AtaTaskFile(), PreviousTaskFile = new AtaTaskFile(),
CurrentTaskFile = new AtaTaskFile CurrentTaskFile = new AtaTaskFile
{ {
Command = registers.Command, Command = registers.Command,
CylinderHigh = registers.CylinderHigh, CylinderHigh = registers.CylinderHigh,
CylinderLow = registers.CylinderLow, CylinderLow = registers.CylinderLow,
DeviceHead = registers.DeviceHead, DeviceHead = registers.DeviceHead,
Features = registers.Feature, Features = registers.Feature,
SectorCount = registers.SectorCount, SectorCount = registers.SectorCount,
SectorNumber = registers.Sector SectorNumber = registers.Sector
} }
}, },
dataBuffer = new byte[64 * 512] dataBuffer = new byte[64 * 512]
}; };
switch(protocol) switch (protocol)
{ {
case AtaProtocol.PioIn: case AtaProtocol.PioIn:
case AtaProtocol.UDmaIn: case AtaProtocol.UDmaIn:
@@ -174,7 +174,7 @@ namespace DiscImageChef.Devices.Windows
break; break;
} }
switch(protocol) switch (protocol)
{ {
case AtaProtocol.Dma: case AtaProtocol.Dma:
case AtaProtocol.DmaQueued: case AtaProtocol.DmaQueued:
@@ -188,30 +188,30 @@ namespace DiscImageChef.Devices.Windows
// Unknown if needed // Unknown if needed
aptdBuf.aptd.AtaFlags |= AtaFlags.DrdyRequired; aptdBuf.aptd.AtaFlags |= AtaFlags.DrdyRequired;
uint k = 0; uint k = 0;
int error = 0; var error = 0;
Array.Copy(buffer, 0, aptdBuf.dataBuffer, 0, buffer.Length); Array.Copy(buffer, 0, aptdBuf.dataBuffer, 0, buffer.Length);
DateTime start = DateTime.Now; var start = DateTime.Now;
sense = !Extern.DeviceIoControlAta(fd, WindowsIoctl.IoctlAtaPassThrough, ref aptdBuf, sense = !Extern.DeviceIoControlAta(fd, WindowsIoctl.IoctlAtaPassThrough, ref aptdBuf,
(uint)Marshal.SizeOf(aptdBuf), ref aptdBuf, (uint) Marshal.SizeOf(aptdBuf), ref aptdBuf,
(uint)Marshal.SizeOf(aptdBuf), ref k, IntPtr.Zero); (uint) Marshal.SizeOf(aptdBuf), ref k, IntPtr.Zero);
DateTime end = DateTime.Now; var end = DateTime.Now;
if(sense) error = Marshal.GetLastWin32Error(); if (sense) error = Marshal.GetLastWin32Error();
Array.Copy(aptdBuf.dataBuffer, 0, buffer, 0, buffer.Length); Array.Copy(aptdBuf.dataBuffer, 0, buffer, 0, buffer.Length);
duration = (end - start).TotalMilliseconds; duration = (end - start).TotalMilliseconds;
errorRegisters.CylinderHigh = aptdBuf.aptd.CurrentTaskFile.CylinderHigh; errorRegisters.CylinderHigh = aptdBuf.aptd.CurrentTaskFile.CylinderHigh;
errorRegisters.CylinderLow = aptdBuf.aptd.CurrentTaskFile.CylinderLow; errorRegisters.CylinderLow = aptdBuf.aptd.CurrentTaskFile.CylinderLow;
errorRegisters.DeviceHead = aptdBuf.aptd.CurrentTaskFile.DeviceHead; errorRegisters.DeviceHead = aptdBuf.aptd.CurrentTaskFile.DeviceHead;
errorRegisters.Error = aptdBuf.aptd.CurrentTaskFile.Error; errorRegisters.Error = aptdBuf.aptd.CurrentTaskFile.Error;
errorRegisters.Sector = aptdBuf.aptd.CurrentTaskFile.SectorNumber; errorRegisters.Sector = aptdBuf.aptd.CurrentTaskFile.SectorNumber;
errorRegisters.SectorCount = aptdBuf.aptd.CurrentTaskFile.SectorCount; errorRegisters.SectorCount = aptdBuf.aptd.CurrentTaskFile.SectorCount;
errorRegisters.Status = aptdBuf.aptd.CurrentTaskFile.Status; errorRegisters.Status = aptdBuf.aptd.CurrentTaskFile.Status;
sense = errorRegisters.Error != 0 || (errorRegisters.Status & 0xA5) != 0; sense = errorRegisters.Error != 0 || (errorRegisters.Status & 0xA5) != 0;
@@ -230,43 +230,43 @@ namespace DiscImageChef.Devices.Windows
/// <param name="registers">Registers to send to drive</param> /// <param name="registers">Registers to send to drive</param>
/// <param name="errorRegisters">Registers returned by drive</param> /// <param name="errorRegisters">Registers returned by drive</param>
/// <param name="protocol">ATA protocol to use</param> /// <param name="protocol">ATA protocol to use</param>
internal static int SendAtaCommand(SafeFileHandle fd, AtaRegistersLba28 registers, internal static int SendAtaCommand(SafeFileHandle fd, AtaRegistersLba28 registers,
out AtaErrorRegistersLba28 errorRegisters, AtaProtocol protocol, out AtaErrorRegistersLba28 errorRegisters, AtaProtocol protocol,
ref byte[] buffer, uint timeout, ref byte[] buffer, uint timeout,
out double duration, out bool sense) out double duration, out bool sense)
{ {
duration = 0; duration = 0;
sense = false; sense = false;
errorRegisters = new AtaErrorRegistersLba28(); errorRegisters = new AtaErrorRegistersLba28();
if(buffer == null) return -1; if (buffer == null) return -1;
uint offsetForBuffer = (uint)(Marshal.SizeOf(typeof(AtaPassThroughDirect)) + Marshal.SizeOf(typeof(uint))); var offsetForBuffer = (uint) (Marshal.SizeOf(typeof(AtaPassThroughEx)) + Marshal.SizeOf(typeof(uint)));
AtaPassThroughDirectWithBuffer aptdBuf = new AtaPassThroughDirectWithBuffer var aptdBuf = new AtaPassThroughExBuffer
{ {
aptd = new AtaPassThroughDirect aptd = new AtaPassThroughEx
{ {
TimeOutValue = timeout, TimeOutValue = timeout,
DataBuffer = (IntPtr)offsetForBuffer, DataBufferOffset = (IntPtr) offsetForBuffer,
Length = (ushort)Marshal.SizeOf(typeof(AtaPassThroughDirect)), Length = (ushort) Marshal.SizeOf(typeof(AtaPassThroughEx)),
DataTransferLength = (uint)buffer.Length, DataTransferLength = (uint) buffer.Length,
PreviousTaskFile = new AtaTaskFile(), PreviousTaskFile = new AtaTaskFile(),
CurrentTaskFile = new AtaTaskFile CurrentTaskFile = new AtaTaskFile
{ {
Command = registers.Command, Command = registers.Command,
CylinderHigh = registers.LbaHigh, CylinderHigh = registers.LbaHigh,
CylinderLow = registers.LbaMid, CylinderLow = registers.LbaMid,
DeviceHead = registers.DeviceHead, DeviceHead = registers.DeviceHead,
Features = registers.Feature, Features = registers.Feature,
SectorCount = registers.SectorCount, SectorCount = registers.SectorCount,
SectorNumber = registers.LbaLow SectorNumber = registers.LbaLow
} }
}, },
dataBuffer = new byte[64 * 512] dataBuffer = new byte[64 * 512]
}; };
switch(protocol) switch (protocol)
{ {
case AtaProtocol.PioIn: case AtaProtocol.PioIn:
case AtaProtocol.UDmaIn: case AtaProtocol.UDmaIn:
@@ -279,7 +279,7 @@ namespace DiscImageChef.Devices.Windows
break; break;
} }
switch(protocol) switch (protocol)
{ {
case AtaProtocol.Dma: case AtaProtocol.Dma:
case AtaProtocol.DmaQueued: case AtaProtocol.DmaQueued:
@@ -293,30 +293,30 @@ namespace DiscImageChef.Devices.Windows
// Unknown if needed // Unknown if needed
aptdBuf.aptd.AtaFlags |= AtaFlags.DrdyRequired; aptdBuf.aptd.AtaFlags |= AtaFlags.DrdyRequired;
uint k = 0; uint k = 0;
int error = 0; var error = 0;
Array.Copy(buffer, 0, aptdBuf.dataBuffer, 0, buffer.Length); Array.Copy(buffer, 0, aptdBuf.dataBuffer, 0, buffer.Length);
DateTime start = DateTime.Now; var start = DateTime.Now;
sense = !Extern.DeviceIoControlAta(fd, WindowsIoctl.IoctlAtaPassThrough, ref aptdBuf, sense = !Extern.DeviceIoControlAta(fd, WindowsIoctl.IoctlAtaPassThrough, ref aptdBuf,
(uint)Marshal.SizeOf(aptdBuf), ref aptdBuf, (uint) Marshal.SizeOf(aptdBuf), ref aptdBuf,
(uint)Marshal.SizeOf(aptdBuf), ref k, IntPtr.Zero); (uint) Marshal.SizeOf(aptdBuf), ref k, IntPtr.Zero);
DateTime end = DateTime.Now; var end = DateTime.Now;
if(sense) error = Marshal.GetLastWin32Error(); if (sense) error = Marshal.GetLastWin32Error();
Array.Copy(aptdBuf.dataBuffer, 0, buffer, 0, buffer.Length); Array.Copy(aptdBuf.dataBuffer, 0, buffer, 0, buffer.Length);
duration = (end - start).TotalMilliseconds; duration = (end - start).TotalMilliseconds;
errorRegisters.LbaHigh = aptdBuf.aptd.CurrentTaskFile.CylinderHigh; errorRegisters.LbaHigh = aptdBuf.aptd.CurrentTaskFile.CylinderHigh;
errorRegisters.LbaMid = aptdBuf.aptd.CurrentTaskFile.CylinderLow; errorRegisters.LbaMid = aptdBuf.aptd.CurrentTaskFile.CylinderLow;
errorRegisters.DeviceHead = aptdBuf.aptd.CurrentTaskFile.DeviceHead; errorRegisters.DeviceHead = aptdBuf.aptd.CurrentTaskFile.DeviceHead;
errorRegisters.Error = aptdBuf.aptd.CurrentTaskFile.Error; errorRegisters.Error = aptdBuf.aptd.CurrentTaskFile.Error;
errorRegisters.LbaLow = aptdBuf.aptd.CurrentTaskFile.SectorNumber; errorRegisters.LbaLow = aptdBuf.aptd.CurrentTaskFile.SectorNumber;
errorRegisters.SectorCount = aptdBuf.aptd.CurrentTaskFile.SectorCount; errorRegisters.SectorCount = aptdBuf.aptd.CurrentTaskFile.SectorCount;
errorRegisters.Status = aptdBuf.aptd.CurrentTaskFile.Status; errorRegisters.Status = aptdBuf.aptd.CurrentTaskFile.Status;
sense = errorRegisters.Error != 0 || (errorRegisters.Status & 0xA5) != 0; sense = errorRegisters.Error != 0 || (errorRegisters.Status & 0xA5) != 0;
@@ -335,51 +335,51 @@ namespace DiscImageChef.Devices.Windows
/// <param name="registers">Registers to send to drive</param> /// <param name="registers">Registers to send to drive</param>
/// <param name="errorRegisters">Registers returned by drive</param> /// <param name="errorRegisters">Registers returned by drive</param>
/// <param name="protocol">ATA protocol to use</param> /// <param name="protocol">ATA protocol to use</param>
internal static int SendAtaCommand(SafeFileHandle fd, AtaRegistersLba48 registers, internal static int SendAtaCommand(SafeFileHandle fd, AtaRegistersLba48 registers,
out AtaErrorRegistersLba48 errorRegisters, AtaProtocol protocol, out AtaErrorRegistersLba48 errorRegisters, AtaProtocol protocol,
ref byte[] buffer, uint timeout, ref byte[] buffer, uint timeout,
out double duration, out bool sense) out double duration, out bool sense)
{ {
duration = 0; duration = 0;
sense = false; sense = false;
errorRegisters = new AtaErrorRegistersLba48(); errorRegisters = new AtaErrorRegistersLba48();
if(buffer == null) return -1; if (buffer == null) return -1;
uint offsetForBuffer = (uint)(Marshal.SizeOf(typeof(AtaPassThroughDirect)) + Marshal.SizeOf(typeof(uint))); var offsetForBuffer = (uint) (Marshal.SizeOf(typeof(AtaPassThroughEx)) + Marshal.SizeOf(typeof(uint)));
AtaPassThroughDirectWithBuffer aptdBuf = new AtaPassThroughDirectWithBuffer var aptdBuf = new AtaPassThroughExBuffer
{ {
aptd = new AtaPassThroughDirect aptd = new AtaPassThroughEx
{ {
TimeOutValue = timeout, TimeOutValue = timeout,
DataBuffer = (IntPtr)offsetForBuffer, DataBufferOffset = (IntPtr) offsetForBuffer,
Length = (ushort)Marshal.SizeOf(typeof(AtaPassThroughDirect)), Length = (ushort) Marshal.SizeOf(typeof(AtaPassThroughEx)),
DataTransferLength = (uint)buffer.Length, DataTransferLength = (uint) buffer.Length,
PreviousTaskFile = PreviousTaskFile =
new AtaTaskFile new AtaTaskFile
{ {
CylinderHigh = (byte)((registers.LbaHigh & 0xFF00) >> 8), CylinderHigh = (byte) ((registers.LbaHigh & 0xFF00) >> 8),
CylinderLow = (byte)((registers.LbaMid & 0xFF00) >> 8), CylinderLow = (byte) ((registers.LbaMid & 0xFF00) >> 8),
Features = (byte)((registers.Feature & 0xFF00) >> 8), Features = (byte) ((registers.Feature & 0xFF00) >> 8),
SectorCount = (byte)((registers.SectorCount & 0xFF00) >> 8), SectorCount = (byte) ((registers.SectorCount & 0xFF00) >> 8),
SectorNumber = (byte)((registers.LbaLow & 0xFF00) >> 8) SectorNumber = (byte) ((registers.LbaLow & 0xFF00) >> 8)
}, },
CurrentTaskFile = new AtaTaskFile CurrentTaskFile = new AtaTaskFile
{ {
Command = registers.Command, Command = registers.Command,
CylinderHigh = (byte)(registers.LbaHigh & 0xFF), CylinderHigh = (byte) (registers.LbaHigh & 0xFF),
CylinderLow = (byte)(registers.LbaMid & 0xFF), CylinderLow = (byte) (registers.LbaMid & 0xFF),
DeviceHead = registers.DeviceHead, DeviceHead = registers.DeviceHead,
Features = (byte)(registers.Feature & 0xFF), Features = (byte) (registers.Feature & 0xFF),
SectorCount = (byte)(registers.SectorCount & 0xFF), SectorCount = (byte) (registers.SectorCount & 0xFF),
SectorNumber = (byte)(registers.LbaLow & 0xFF) SectorNumber = (byte) (registers.LbaLow & 0xFF)
} }
}, },
dataBuffer = new byte[64 * 512] dataBuffer = new byte[64 * 512]
}; };
switch(protocol) switch (protocol)
{ {
case AtaProtocol.PioIn: case AtaProtocol.PioIn:
case AtaProtocol.UDmaIn: case AtaProtocol.UDmaIn:
@@ -392,7 +392,7 @@ namespace DiscImageChef.Devices.Windows
break; break;
} }
switch(protocol) switch (protocol)
{ {
case AtaProtocol.Dma: case AtaProtocol.Dma:
case AtaProtocol.DmaQueued: case AtaProtocol.DmaQueued:
@@ -403,37 +403,39 @@ namespace DiscImageChef.Devices.Windows
break; break;
} }
aptdBuf.aptd.AtaFlags |= AtaFlags.ExtendedCommand;
// Unknown if needed // Unknown if needed
aptdBuf.aptd.AtaFlags |= AtaFlags.DrdyRequired; aptdBuf.aptd.AtaFlags |= AtaFlags.DrdyRequired;
uint k = 0; uint k = 0;
int error = 0; var error = 0;
Array.Copy(buffer, 0, aptdBuf.dataBuffer, 0, buffer.Length); Array.Copy(buffer, 0, aptdBuf.dataBuffer, 0, buffer.Length);
DateTime start = DateTime.Now; var start = DateTime.Now;
sense = !Extern.DeviceIoControlAta(fd, WindowsIoctl.IoctlAtaPassThrough, ref aptdBuf, sense = !Extern.DeviceIoControlAta(fd, WindowsIoctl.IoctlAtaPassThrough, ref aptdBuf,
(uint)Marshal.SizeOf(aptdBuf), ref aptdBuf, (uint) Marshal.SizeOf(aptdBuf), ref aptdBuf,
(uint)Marshal.SizeOf(aptdBuf), ref k, IntPtr.Zero); (uint) Marshal.SizeOf(aptdBuf), ref k, IntPtr.Zero);
DateTime end = DateTime.Now; var end = DateTime.Now;
if(sense) error = Marshal.GetLastWin32Error(); if (sense) error = Marshal.GetLastWin32Error();
Array.Copy(aptdBuf.dataBuffer, 0, buffer, 0, buffer.Length); Array.Copy(aptdBuf.dataBuffer, 0, buffer, 0, buffer.Length);
duration = (end - start).TotalMilliseconds; duration = (end - start).TotalMilliseconds;
errorRegisters.SectorCount = (ushort)((aptdBuf.aptd.PreviousTaskFile.SectorCount << 8) + errorRegisters.SectorCount = (ushort) ((aptdBuf.aptd.PreviousTaskFile.SectorCount << 8) +
aptdBuf.aptd.CurrentTaskFile.SectorCount); aptdBuf.aptd.CurrentTaskFile.SectorCount);
errorRegisters.LbaLow = (ushort)((aptdBuf.aptd.PreviousTaskFile.SectorNumber << 8) + errorRegisters.LbaLow = (ushort) ((aptdBuf.aptd.PreviousTaskFile.SectorNumber << 8) +
aptdBuf.aptd.CurrentTaskFile.SectorNumber); aptdBuf.aptd.CurrentTaskFile.SectorNumber);
errorRegisters.LbaMid = (ushort)((aptdBuf.aptd.PreviousTaskFile.CylinderLow << 8) + errorRegisters.LbaMid = (ushort) ((aptdBuf.aptd.PreviousTaskFile.CylinderLow << 8) +
aptdBuf.aptd.CurrentTaskFile.CylinderLow); aptdBuf.aptd.CurrentTaskFile.CylinderLow);
errorRegisters.LbaHigh = (ushort)((aptdBuf.aptd.PreviousTaskFile.CylinderHigh << 8) + errorRegisters.LbaHigh = (ushort) ((aptdBuf.aptd.PreviousTaskFile.CylinderHigh << 8) +
aptdBuf.aptd.CurrentTaskFile.CylinderHigh); aptdBuf.aptd.CurrentTaskFile.CylinderHigh);
errorRegisters.DeviceHead = aptdBuf.aptd.CurrentTaskFile.DeviceHead; errorRegisters.DeviceHead = aptdBuf.aptd.CurrentTaskFile.DeviceHead;
errorRegisters.Error = aptdBuf.aptd.CurrentTaskFile.Error; errorRegisters.Error = aptdBuf.aptd.CurrentTaskFile.Error;
errorRegisters.Status = aptdBuf.aptd.CurrentTaskFile.Status; errorRegisters.Status = aptdBuf.aptd.CurrentTaskFile.Status;
sense = errorRegisters.Error != 0 || (errorRegisters.Status & 0xA5) != 0; sense = errorRegisters.Error != 0 || (errorRegisters.Status & 0xA5) != 0;
@@ -445,15 +447,15 @@ namespace DiscImageChef.Devices.Windows
/// </summary> /// </summary>
/// <param name="deviceHandle">Device handle</param> /// <param name="deviceHandle">Device handle</param>
/// <returns>Device number</returns> /// <returns>Device number</returns>
static uint GetDeviceNumber(SafeFileHandle deviceHandle) private static uint GetDeviceNumber(SafeFileHandle deviceHandle)
{ {
StorageDeviceNumber sdn = new StorageDeviceNumber {deviceNumber = -1}; var sdn = new StorageDeviceNumber {deviceNumber = -1};
uint k = 0; uint k = 0;
if(!Extern.DeviceIoControlGetDeviceNumber(deviceHandle, WindowsIoctl.IoctlStorageGetDeviceNumber, if (!Extern.DeviceIoControlGetDeviceNumber(deviceHandle, WindowsIoctl.IoctlStorageGetDeviceNumber,
IntPtr.Zero, 0, ref sdn, (uint)Marshal.SizeOf(sdn), ref k, IntPtr.Zero, 0, ref sdn, (uint) Marshal.SizeOf(sdn), ref k,
IntPtr.Zero)) return uint.MaxValue; IntPtr.Zero)) return uint.MaxValue;
return (uint)sdn.deviceNumber; return (uint) sdn.deviceNumber;
} }
/// <summary> /// <summary>
@@ -463,11 +465,12 @@ namespace DiscImageChef.Devices.Windows
/// <returns><c>true</c> if SDHCI, false otherwise</returns> /// <returns><c>true</c> if SDHCI, false otherwise</returns>
internal static bool IsSdhci(SafeFileHandle fd) internal static bool IsSdhci(SafeFileHandle fd)
{ {
SffdiskQueryDeviceProtocolData queryData1 = new SffdiskQueryDeviceProtocolData(); var queryData1 = new SffdiskQueryDeviceProtocolData();
queryData1.size = (ushort)Marshal.SizeOf(queryData1); queryData1.size = (ushort) Marshal.SizeOf(queryData1);
Extern.DeviceIoControl(fd, WindowsIoctl.IoctlSffdiskQueryDeviceProtocol, IntPtr.Zero, 0, ref queryData1, Extern.DeviceIoControl(fd, WindowsIoctl.IoctlSffdiskQueryDeviceProtocol, IntPtr.Zero, 0, ref queryData1,
queryData1.size, out _, IntPtr.Zero); queryData1.size, out _, IntPtr.Zero);
return queryData1.protocolGuid.Equals(Consts.GuidSffProtocolSd); return queryData1.protocolGuid.Equals(Consts.GuidSffProtocolSd) ||
queryData1.protocolGuid.Equals(Consts.GuidSffProtocolMmc);
} }
/// <summary> /// <summary>
@@ -488,57 +491,60 @@ namespace DiscImageChef.Devices.Windows
/// <param name="response">Response registers</param> /// <param name="response">Response registers</param>
/// <param name="blockSize">Size of block in bytes</param> /// <param name="blockSize">Size of block in bytes</param>
internal static int SendMmcCommand(SafeFileHandle fd, MmcCommands command, bool write, internal static int SendMmcCommand(SafeFileHandle fd, MmcCommands command, bool write,
bool isApplication, bool isApplication,
MmcFlags flags, uint argument, uint blockSize, MmcFlags flags, uint argument, uint blockSize,
uint blocks, uint blocks,
ref byte[] buffer, out uint[] response, out double duration, ref byte[] buffer, out uint[] response, out double duration,
out bool sense, out bool sense,
uint timeout = 0) uint timeout = 0)
{ {
SffdiskDeviceCommandData commandData = new SffdiskDeviceCommandData(); var commandData = new SffdiskDeviceCommandData();
SdCmdDescriptor commandDescriptor = new SdCmdDescriptor(); var commandDescriptor = new SdCmdDescriptor();
commandData.size = (ushort)Marshal.SizeOf(commandData); commandData.size = (ushort) Marshal.SizeOf(commandData);
commandData.command = SffdiskDcmd.DeviceCommand; commandData.command = SffdiskDcmd.DeviceCommand;
commandData.protocolArgumentSize = (ushort)Marshal.SizeOf(commandDescriptor); commandData.protocolArgumentSize = (ushort) Marshal.SizeOf(commandDescriptor);
commandData.deviceDataBufferSize = blockSize * blocks; commandData.deviceDataBufferSize = blockSize * blocks;
commandDescriptor.commandCode = (byte)command; commandDescriptor.commandCode = (byte) command;
commandDescriptor.cmdClass = isApplication ? SdCommandClass.AppCmd : SdCommandClass.Standard; commandDescriptor.cmdClass = isApplication ? SdCommandClass.AppCmd : SdCommandClass.Standard;
commandDescriptor.transferDirection = write ? SdTransferDirection.Write : SdTransferDirection.Read; commandDescriptor.transferDirection = write ? SdTransferDirection.Write : SdTransferDirection.Read;
commandDescriptor.transferType = flags.HasFlag(MmcFlags.CommandAdtc) commandDescriptor.transferType = flags.HasFlag(MmcFlags.CommandAdtc)
? SdTransferType.SingleBlock ? SdTransferType.SingleBlock
: SdTransferType.CmdOnly; : SdTransferType.CmdOnly;
commandDescriptor.responseType = 0; commandDescriptor.responseType = 0;
if(flags.HasFlag(MmcFlags.ResponseR1) || flags.HasFlag(MmcFlags.ResponseSpiR1)) if (flags.HasFlag(MmcFlags.ResponseR1) || flags.HasFlag(MmcFlags.ResponseSpiR1))
commandDescriptor.responseType = SdResponseType.R1; commandDescriptor.responseType = SdResponseType.R1;
if(flags.HasFlag(MmcFlags.ResponseR1B) || flags.HasFlag(MmcFlags.ResponseSpiR1B)) if (flags.HasFlag(MmcFlags.ResponseR1B) || flags.HasFlag(MmcFlags.ResponseSpiR1B))
commandDescriptor.responseType = SdResponseType.R1b; commandDescriptor.responseType = SdResponseType.R1b;
if(flags.HasFlag(MmcFlags.ResponseR2) || flags.HasFlag(MmcFlags.ResponseSpiR2)) if (flags.HasFlag(MmcFlags.ResponseR2) || flags.HasFlag(MmcFlags.ResponseSpiR2))
commandDescriptor.responseType = SdResponseType.R2; commandDescriptor.responseType = SdResponseType.R2;
if(flags.HasFlag(MmcFlags.ResponseR3) || flags.HasFlag(MmcFlags.ResponseSpiR3)) if (flags.HasFlag(MmcFlags.ResponseR3) || flags.HasFlag(MmcFlags.ResponseSpiR3))
commandDescriptor.responseType = SdResponseType.R3; commandDescriptor.responseType = SdResponseType.R3;
if(flags.HasFlag(MmcFlags.ResponseR4) || flags.HasFlag(MmcFlags.ResponseSpiR4)) if (flags.HasFlag(MmcFlags.ResponseR4) || flags.HasFlag(MmcFlags.ResponseSpiR4))
commandDescriptor.responseType = SdResponseType.R4; commandDescriptor.responseType = SdResponseType.R4;
if(flags.HasFlag(MmcFlags.ResponseR5) || flags.HasFlag(MmcFlags.ResponseSpiR5)) if (flags.HasFlag(MmcFlags.ResponseR5) || flags.HasFlag(MmcFlags.ResponseSpiR5))
commandDescriptor.responseType = SdResponseType.R5; commandDescriptor.responseType = SdResponseType.R5;
if(flags.HasFlag(MmcFlags.ResponseR6)) commandDescriptor.responseType = SdResponseType.R6; if (flags.HasFlag(MmcFlags.ResponseR6)) commandDescriptor.responseType = SdResponseType.R6;
byte[] commandB = new byte[commandData.size + commandData.protocolArgumentSize + var commandB = new byte[commandData.size + commandData.protocolArgumentSize +
commandData.deviceDataBufferSize]; commandData.deviceDataBufferSize];
IntPtr hBuf = Marshal.AllocHGlobal(commandB.Length);
Array.Copy(buffer, 0, commandB, commandData.size + commandData.protocolArgumentSize, buffer.Length);
var hBuf = Marshal.AllocHGlobal(commandB.Length);
Marshal.StructureToPtr(commandData, hBuf, true); Marshal.StructureToPtr(commandData, hBuf, true);
IntPtr descriptorOffset = IntPtr.Add(hBuf, commandData.size); var descriptorOffset = IntPtr.Add(hBuf, commandData.size);
Marshal.StructureToPtr(commandDescriptor, descriptorOffset, true); Marshal.StructureToPtr(commandDescriptor, descriptorOffset, true);
Marshal.Copy(hBuf, commandB, 0, commandB.Length); Marshal.Copy(hBuf, commandB, 0, commandB.Length);
Marshal.FreeHGlobal(hBuf); Marshal.FreeHGlobal(hBuf);
int error = 0; var error = 0;
DateTime start = DateTime.Now; var start = DateTime.Now;
sense = !Extern.DeviceIoControl(fd, WindowsIoctl.IoctlSffdiskDeviceCommand, commandB, (uint)commandB.Length, sense = !Extern.DeviceIoControl(fd, WindowsIoctl.IoctlSffdiskDeviceCommand, commandB,
commandB, (uint)commandB.Length, out _, IntPtr.Zero); (uint) commandB.Length,
DateTime end = DateTime.Now; commandB, (uint) commandB.Length, out _, IntPtr.Zero);
var end = DateTime.Now;
if(sense) error = Marshal.GetLastWin32Error(); if (sense) error = Marshal.GetLastWin32Error();
buffer = new byte[blockSize * blocks]; buffer = new byte[blockSize * blocks];
Buffer.BlockCopy(commandB, commandB.Length - buffer.Length, buffer, 0, buffer.Length); Buffer.BlockCopy(commandB, commandB.Length - buffer.Length, buffer, 0, buffer.Length);