ATA pass through needs buffer position to be relative to structure so use accordingly.

This commit is contained in:
2017-09-07 16:48:25 +01:00
parent 8cc805f031
commit 95e0d3f596
3 changed files with 135 additions and 103 deletions

View File

@@ -112,12 +112,16 @@ namespace DiscImageChef.Devices.Windows
if(buffer == null) if(buffer == null)
return -1; return -1;
GCHandle hd = GCHandle.Alloc(buffer); uint offsetForBuffer = (uint)(Marshal.SizeOf(typeof(AtaPassThroughDirect)) + Marshal.SizeOf(typeof(uint)));
AtaPassThroughDirect aptd = new AtaPassThroughDirect AtaPassThroughDirectWithBuffer aptd_buf = new AtaPassThroughDirectWithBuffer
{
aptd = new AtaPassThroughDirect
{ {
TimeOutValue = timeout, TimeOutValue = timeout,
DataBuffer = Marshal.AllocHGlobal(buffer.Length), DataBuffer = (IntPtr)offsetForBuffer,
Length = (ushort)Marshal.SizeOf(typeof(AtaPassThroughDirect)),
DataTransferLength = (uint)buffer.Length,
PreviousTaskFile = new AtaTaskFile(), PreviousTaskFile = new AtaTaskFile(),
CurrentTaskFile = new AtaTaskFile CurrentTaskFile = new AtaTaskFile
{ {
@@ -129,13 +133,14 @@ namespace DiscImageChef.Devices.Windows
SectorCount = registers.sectorCount, SectorCount = registers.sectorCount,
SectorNumber = registers.sector SectorNumber = registers.sector
} }
},
dataBuffer = new byte[64 * 512]
}; };
aptd.Length = (ushort)Marshal.SizeOf(aptd);
if(protocol == AtaProtocol.PioIn || protocol == AtaProtocol.UDmaIn || protocol == AtaProtocol.Dma) if (protocol == AtaProtocol.PioIn || protocol == AtaProtocol.UDmaIn || protocol == AtaProtocol.Dma)
aptd.AtaFlags = AtaFlags.DataIn; aptd_buf.aptd.AtaFlags = AtaFlags.DataIn;
else if(protocol == AtaProtocol.PioOut || protocol == AtaProtocol.UDmaOut) else if(protocol == AtaProtocol.PioOut || protocol == AtaProtocol.UDmaOut)
aptd.AtaFlags = AtaFlags.DataOut; aptd_buf.aptd.AtaFlags = AtaFlags.DataOut;
switch(protocol) switch(protocol)
{ {
@@ -144,37 +149,40 @@ namespace DiscImageChef.Devices.Windows
case AtaProtocol.FPDma: case AtaProtocol.FPDma:
case AtaProtocol.UDmaIn: case AtaProtocol.UDmaIn:
case AtaProtocol.UDmaOut: case AtaProtocol.UDmaOut:
aptd.AtaFlags |= AtaFlags.DMA; aptd_buf.aptd.AtaFlags |= AtaFlags.DMA;
break; break;
} }
// Unknown if needed
aptd_buf.aptd.AtaFlags |= AtaFlags.DrdyRequired;
uint k = 0; uint k = 0;
int error = 0; int error = 0;
Marshal.Copy(buffer, 0, aptd.DataBuffer, buffer.Length); Array.Copy(buffer, 0, aptd_buf.dataBuffer, 0, buffer.Length);
DateTime start = DateTime.Now; DateTime start = DateTime.Now;
sense = !Extern.DeviceIoControlAta(fd, WindowsIoctl.IOCTL_ATA_PASS_THROUGH, ref aptd, (uint)Marshal.SizeOf(aptd), ref aptd, sense = !Extern.DeviceIoControlAta(fd, WindowsIoctl.IOCTL_ATA_PASS_THROUGH, ref aptd_buf, (uint)Marshal.SizeOf(aptd_buf), ref aptd_buf,
(uint)Marshal.SizeOf(aptd), ref k, IntPtr.Zero); (uint)Marshal.SizeOf(aptd_buf), ref k, IntPtr.Zero);
DateTime end = DateTime.Now; DateTime end = DateTime.Now;
if(sense) if(sense)
error = Marshal.GetLastWin32Error(); error = Marshal.GetLastWin32Error();
Marshal.Copy(aptd.DataBuffer, buffer, 0, buffer.Length); Array.Copy(aptd_buf.dataBuffer, 0, buffer, 0, buffer.Length);
duration = (end - start).TotalMilliseconds; duration = (end - start).TotalMilliseconds;
Marshal.FreeHGlobal(aptd.DataBuffer); errorRegisters.command = aptd_buf.aptd.CurrentTaskFile.Command;
errorRegisters.cylinderHigh = aptd_buf.aptd.CurrentTaskFile.CylinderHigh;
errorRegisters.cylinderLow = aptd_buf.aptd.CurrentTaskFile.CylinderLow;
errorRegisters.deviceHead = aptd_buf.aptd.CurrentTaskFile.DeviceHead;
errorRegisters.error = aptd_buf.aptd.CurrentTaskFile.Error;
errorRegisters.sector = aptd_buf.aptd.CurrentTaskFile.SectorNumber;
errorRegisters.sectorCount = aptd_buf.aptd.CurrentTaskFile.SectorCount;
errorRegisters.status = aptd_buf.aptd.CurrentTaskFile.Status;
errorRegisters.command = aptd.CurrentTaskFile.Command; sense = errorRegisters.error != 0 || (errorRegisters.status & 0xA5) != 0;
errorRegisters.cylinderHigh = aptd.CurrentTaskFile.CylinderHigh;
errorRegisters.cylinderLow = aptd.CurrentTaskFile.CylinderLow;
errorRegisters.deviceHead = aptd.CurrentTaskFile.DeviceHead;
errorRegisters.error = aptd.CurrentTaskFile.Error;
errorRegisters.sector = aptd.CurrentTaskFile.SectorNumber;
errorRegisters.sectorCount = aptd.CurrentTaskFile.SectorCount;
errorRegisters.status = aptd.CurrentTaskFile.Status;
return error; return error;
} }
@@ -189,12 +197,15 @@ namespace DiscImageChef.Devices.Windows
if(buffer == null) if(buffer == null)
return -1; return -1;
GCHandle hd = GCHandle.Alloc(buffer); uint offsetForBuffer = (uint)(Marshal.SizeOf(typeof(AtaPassThroughDirect)) + Marshal.SizeOf(typeof(uint)));
AtaPassThroughDirect aptd = new AtaPassThroughDirect AtaPassThroughDirectWithBuffer aptd_buf = new AtaPassThroughDirectWithBuffer
{
aptd = new AtaPassThroughDirect
{ {
TimeOutValue = timeout, TimeOutValue = timeout,
DataBuffer = Marshal.AllocHGlobal(buffer.Length), DataBuffer = (IntPtr)offsetForBuffer,
Length = (ushort)Marshal.SizeOf(typeof(AtaPassThroughDirect)),
PreviousTaskFile = new AtaTaskFile(), PreviousTaskFile = new AtaTaskFile(),
CurrentTaskFile = new AtaTaskFile CurrentTaskFile = new AtaTaskFile
{ {
@@ -206,13 +217,14 @@ namespace DiscImageChef.Devices.Windows
SectorCount = registers.sectorCount, SectorCount = registers.sectorCount,
SectorNumber = registers.lbaLow SectorNumber = registers.lbaLow
} }
},
dataBuffer = new byte[64 * 512]
}; };
aptd.Length = (ushort)Marshal.SizeOf(aptd);
if(protocol == AtaProtocol.PioIn || protocol == AtaProtocol.UDmaIn || protocol == AtaProtocol.Dma) if(protocol == AtaProtocol.PioIn || protocol == AtaProtocol.UDmaIn || protocol == AtaProtocol.Dma)
aptd.AtaFlags = AtaFlags.DataIn; aptd_buf.aptd.AtaFlags = AtaFlags.DataIn;
else if(protocol == AtaProtocol.PioOut || protocol == AtaProtocol.UDmaOut) else if(protocol == AtaProtocol.PioOut || protocol == AtaProtocol.UDmaOut)
aptd.AtaFlags = AtaFlags.DataOut; aptd_buf.aptd.AtaFlags = AtaFlags.DataOut;
switch(protocol) switch(protocol)
{ {
@@ -221,37 +233,40 @@ namespace DiscImageChef.Devices.Windows
case AtaProtocol.FPDma: case AtaProtocol.FPDma:
case AtaProtocol.UDmaIn: case AtaProtocol.UDmaIn:
case AtaProtocol.UDmaOut: case AtaProtocol.UDmaOut:
aptd.AtaFlags |= AtaFlags.DMA; aptd_buf.aptd.AtaFlags |= AtaFlags.DMA;
break; break;
} }
// Unknown if needed
aptd_buf.aptd.AtaFlags |= AtaFlags.DrdyRequired;
uint k = 0; uint k = 0;
int error = 0; int error = 0;
Marshal.Copy(buffer, 0, aptd.DataBuffer, buffer.Length); Array.Copy(buffer, 0, aptd_buf.dataBuffer, 0, buffer.Length);
DateTime start = DateTime.Now; DateTime start = DateTime.Now;
sense = !Extern.DeviceIoControlAta(fd, WindowsIoctl.IOCTL_ATA_PASS_THROUGH, ref aptd, (uint)Marshal.SizeOf(aptd), ref aptd, sense = !Extern.DeviceIoControlAta(fd, WindowsIoctl.IOCTL_ATA_PASS_THROUGH, ref aptd_buf, (uint)Marshal.SizeOf(aptd_buf), ref aptd_buf,
(uint)Marshal.SizeOf(aptd), ref k, IntPtr.Zero); (uint)Marshal.SizeOf(aptd_buf), ref k, IntPtr.Zero);
DateTime end = DateTime.Now; DateTime end = DateTime.Now;
if(sense) if(sense)
error = Marshal.GetLastWin32Error(); error = Marshal.GetLastWin32Error();
Marshal.Copy(aptd.DataBuffer, buffer, 0, buffer.Length); Array.Copy(aptd_buf.dataBuffer, 0, buffer, 0, buffer.Length);
duration = (end - start).TotalMilliseconds; duration = (end - start).TotalMilliseconds;
Marshal.FreeHGlobal(aptd.DataBuffer); errorRegisters.command = aptd_buf.aptd.CurrentTaskFile.Command;
errorRegisters.lbaHigh = aptd_buf.aptd.CurrentTaskFile.CylinderHigh;
errorRegisters.lbaMid = aptd_buf.aptd.CurrentTaskFile.CylinderLow;
errorRegisters.deviceHead = aptd_buf.aptd.CurrentTaskFile.DeviceHead;
errorRegisters.error = aptd_buf.aptd.CurrentTaskFile.Error;
errorRegisters.lbaLow = aptd_buf.aptd.CurrentTaskFile.SectorNumber;
errorRegisters.sectorCount = aptd_buf.aptd.CurrentTaskFile.SectorCount;
errorRegisters.status = aptd_buf.aptd.CurrentTaskFile.Status;
errorRegisters.command = aptd.CurrentTaskFile.Command; sense = errorRegisters.error != 0 || (errorRegisters.status & 0xA5) != 0;
errorRegisters.lbaHigh = aptd.CurrentTaskFile.CylinderHigh;
errorRegisters.lbaMid = aptd.CurrentTaskFile.CylinderLow;
errorRegisters.deviceHead = aptd.CurrentTaskFile.DeviceHead;
errorRegisters.error = aptd.CurrentTaskFile.Error;
errorRegisters.lbaLow = aptd.CurrentTaskFile.SectorNumber;
errorRegisters.sectorCount = aptd.CurrentTaskFile.SectorCount;
errorRegisters.status = aptd.CurrentTaskFile.Status;
return error; return error;
} }
@@ -266,12 +281,15 @@ namespace DiscImageChef.Devices.Windows
if(buffer == null) if(buffer == null)
return -1; return -1;
GCHandle hd = GCHandle.Alloc(buffer); uint offsetForBuffer = (uint)(Marshal.SizeOf(typeof(AtaPassThroughDirect)) + Marshal.SizeOf(typeof(uint)));
AtaPassThroughDirect aptd = new AtaPassThroughDirect AtaPassThroughDirectWithBuffer aptd_buf = new AtaPassThroughDirectWithBuffer
{
aptd = new AtaPassThroughDirect
{ {
TimeOutValue = timeout, TimeOutValue = timeout,
DataBuffer = Marshal.AllocHGlobal(buffer.Length), DataBuffer = (IntPtr)offsetForBuffer,
Length = (ushort)Marshal.SizeOf(typeof(AtaPassThroughDirect)),
PreviousTaskFile = new AtaTaskFile PreviousTaskFile = new AtaTaskFile
{ {
CylinderHigh = (byte)((registers.lbaHigh & 0xFF00) >> 8), CylinderHigh = (byte)((registers.lbaHigh & 0xFF00) >> 8),
@@ -290,13 +308,14 @@ namespace DiscImageChef.Devices.Windows
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]
}; };
aptd.Length = (ushort)Marshal.SizeOf(aptd);
if(protocol == AtaProtocol.PioIn || protocol == AtaProtocol.UDmaIn || protocol == AtaProtocol.Dma) if(protocol == AtaProtocol.PioIn || protocol == AtaProtocol.UDmaIn || protocol == AtaProtocol.Dma)
aptd.AtaFlags = AtaFlags.DataIn; aptd_buf.aptd.AtaFlags = AtaFlags.DataIn;
else if(protocol == AtaProtocol.PioOut || protocol == AtaProtocol.UDmaOut) else if(protocol == AtaProtocol.PioOut || protocol == AtaProtocol.UDmaOut)
aptd.AtaFlags = AtaFlags.DataOut; aptd_buf.aptd.AtaFlags = AtaFlags.DataOut;
switch(protocol) switch(protocol)
{ {
@@ -305,37 +324,40 @@ namespace DiscImageChef.Devices.Windows
case AtaProtocol.FPDma: case AtaProtocol.FPDma:
case AtaProtocol.UDmaIn: case AtaProtocol.UDmaIn:
case AtaProtocol.UDmaOut: case AtaProtocol.UDmaOut:
aptd.AtaFlags |= AtaFlags.DMA; aptd_buf.aptd.AtaFlags |= AtaFlags.DMA;
break; break;
} }
// Unknown if needed
aptd_buf.aptd.AtaFlags |= AtaFlags.DrdyRequired;
uint k = 0; uint k = 0;
int error = 0; int error = 0;
Marshal.Copy(buffer, 0, aptd.DataBuffer, buffer.Length); Array.Copy(buffer, 0, aptd_buf.dataBuffer, 0, buffer.Length);
DateTime start = DateTime.Now; DateTime start = DateTime.Now;
sense = !Extern.DeviceIoControlAta(fd, WindowsIoctl.IOCTL_ATA_PASS_THROUGH, ref aptd, (uint)Marshal.SizeOf(aptd), ref aptd, sense = !Extern.DeviceIoControlAta(fd, WindowsIoctl.IOCTL_ATA_PASS_THROUGH, ref aptd_buf, (uint)Marshal.SizeOf(aptd_buf), ref aptd_buf,
(uint)Marshal.SizeOf(aptd), ref k, IntPtr.Zero); (uint)Marshal.SizeOf(aptd_buf), ref k, IntPtr.Zero);
DateTime end = DateTime.Now; DateTime end = DateTime.Now;
if(sense) if(sense)
error = Marshal.GetLastWin32Error(); error = Marshal.GetLastWin32Error();
Marshal.Copy(aptd.DataBuffer, buffer, 0, buffer.Length); Array.Copy(aptd_buf.dataBuffer, 0, buffer, 0, buffer.Length);
duration = (end - start).TotalMilliseconds; duration = (end - start).TotalMilliseconds;
Marshal.FreeHGlobal(aptd.DataBuffer); errorRegisters.sectorCount = (ushort)((aptd_buf.aptd.PreviousTaskFile.SectorCount << 8) + aptd_buf.aptd.CurrentTaskFile.SectorCount);
errorRegisters.lbaLow = (ushort)((aptd_buf.aptd.PreviousTaskFile.SectorNumber << 8) + aptd_buf.aptd.CurrentTaskFile.SectorNumber);
errorRegisters.lbaMid = (ushort)((aptd_buf.aptd.PreviousTaskFile.CylinderLow << 8) + aptd_buf.aptd.CurrentTaskFile.CylinderLow);
errorRegisters.lbaHigh = (ushort)((aptd_buf.aptd.PreviousTaskFile.CylinderHigh << 8) + aptd_buf.aptd.CurrentTaskFile.CylinderHigh);
errorRegisters.command = aptd_buf.aptd.CurrentTaskFile.Command;
errorRegisters.deviceHead = aptd_buf.aptd.CurrentTaskFile.DeviceHead;
errorRegisters.error = aptd_buf.aptd.CurrentTaskFile.Error;
errorRegisters.status = aptd_buf.aptd.CurrentTaskFile.Status;
errorRegisters.sectorCount = (ushort)((aptd.PreviousTaskFile.SectorCount << 8) + aptd.CurrentTaskFile.SectorCount); sense = errorRegisters.error != 0 || (errorRegisters.status & 0xA5) != 0;
errorRegisters.lbaLow = (ushort)((aptd.PreviousTaskFile.SectorNumber << 8) + aptd.CurrentTaskFile.SectorNumber);
errorRegisters.lbaMid = (ushort)((aptd.PreviousTaskFile.CylinderLow << 8) + aptd.CurrentTaskFile.CylinderLow);
errorRegisters.lbaHigh = (ushort)((aptd.PreviousTaskFile.CylinderHigh << 8) + aptd.CurrentTaskFile.CylinderHigh);
errorRegisters.command = aptd.CurrentTaskFile.Command;
errorRegisters.deviceHead = aptd.CurrentTaskFile.DeviceHead;
errorRegisters.error = aptd.CurrentTaskFile.Error;
errorRegisters.status = aptd.CurrentTaskFile.Status;
return error; return error;
} }

View File

@@ -66,9 +66,9 @@ namespace DiscImageChef.Devices.Windows
internal static extern bool DeviceIoControlAta( internal static extern bool DeviceIoControlAta(
SafeFileHandle hDevice, SafeFileHandle hDevice,
WindowsIoctl IoControlCode, WindowsIoctl IoControlCode,
ref AtaPassThroughDirect InBuffer, ref AtaPassThroughDirectWithBuffer InBuffer,
uint nInBufferSize, uint nInBufferSize,
ref AtaPassThroughDirect OutBuffer, ref AtaPassThroughDirectWithBuffer OutBuffer,
uint nOutBufferSize, uint nOutBufferSize,
ref uint pBytesReturned, ref uint pBytesReturned,
IntPtr Overlapped IntPtr Overlapped

View File

@@ -74,6 +74,7 @@ namespace DiscImageChef.Devices.Windows
/// <summary> /// <summary>
/// Indicates transfer direction and kind of operation /// Indicates transfer direction and kind of operation
/// </summary> /// </summary>
[MarshalAs(UnmanagedType.U2)]
public AtaFlags AtaFlags; public AtaFlags AtaFlags;
/// <summary> /// <summary>
/// Indicates IDE port or bus, set by driver /// Indicates IDE port or bus, set by driver
@@ -104,7 +105,7 @@ namespace DiscImageChef.Devices.Windows
/// </summary> /// </summary>
public uint ReservedAsUlong; public uint ReservedAsUlong;
/// <summary> /// <summary>
/// Pointer to data buffer /// Pointer to data buffer relative to start of this structure
/// </summary> /// </summary>
public IntPtr DataBuffer; public IntPtr DataBuffer;
/// <summary> /// <summary>
@@ -117,6 +118,15 @@ namespace DiscImageChef.Devices.Windows
public AtaTaskFile CurrentTaskFile; public AtaTaskFile CurrentTaskFile;
} }
[StructLayout(LayoutKind.Sequential)]
struct AtaPassThroughDirectWithBuffer
{
public AtaPassThroughDirect aptd;
public uint filler;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 64 * 512)]
public byte[] dataBuffer;
}
[StructLayout(LayoutKind.Explicit)] [StructLayout(LayoutKind.Explicit)]
struct AtaTaskFile struct AtaTaskFile
{ {