Use a single device aligned buffer.

This commit is contained in:
2025-08-22 20:21:43 +01:00
parent e4f55d3b3c
commit ba818d1266
4 changed files with 76 additions and 18 deletions

View File

@@ -64,6 +64,8 @@ partial class Device
_ => ScsiIoctlDirection.Unknown
};
EnsureCapacityAligned((nuint)buffer.Length);
var ioHdr = new SgIoHdrT();
ioHdr.interface_id = 'S';
@@ -71,13 +73,14 @@ partial class Device
ioHdr.mx_sb_len = (byte)SenseBuffer.Length;
ioHdr.dxfer_direction = dir;
ioHdr.dxfer_len = (uint)buffer.Length;
ioHdr.dxferp = Marshal.AllocHGlobal(buffer.Length);
ioHdr.dxferp = (IntPtr)_nativeBuffer;
ioHdr.cmdp = (IntPtr)CdbPtr;
ioHdr.sbp = (IntPtr)SensePtr;
ioHdr.timeout = timeout * 1000;
ioHdr.flags = (uint)SgFlags.DirectIo;
Marshal.Copy(buffer, 0, ioHdr.dxferp, buffer.Length);
// OUT or bidirectional → prefill from managed buffer
if(direction != ScsiDirection.In) buffer.AsSpan().CopyTo(new Span<byte>((void*)_nativeBuffer, buffer.Length));
var cmdStopWatch = new Stopwatch();
cmdStopWatch.Start();
@@ -86,14 +89,13 @@ partial class Device
if(error < 0) error = Marshal.GetLastWin32Error();
Marshal.Copy(ioHdr.dxferp, buffer, 0, buffer.Length);
// IN or bidirectional → copy back into managed buffer
if(direction != ScsiDirection.Out) new Span<byte>((void*)_nativeBuffer, buffer.Length).CopyTo(buffer);
sense |= (ioHdr.info & SgInfo.OkMask) != SgInfo.Ok;
duration = ioHdr.duration > 0 ? ioHdr.duration : cmdStopWatch.Elapsed.TotalMilliseconds;
Marshal.FreeHGlobal(ioHdr.dxferp);
return error;
}

View File

@@ -33,6 +33,7 @@
using System;
using System.Globalization;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using Aaru.CommonTypes.Enums;
using Aaru.CommonTypes.Interop;
@@ -47,14 +48,42 @@ namespace Aaru.Devices.Linux;
/// <inheritdoc />
[SupportedOSPlatform("linux")]
partial class Device : Devices.Device
partial class Device : Devices.Device, IDisposable
{
private const nuint ALIGNMENT = 64;
private nuint _capacity;
/// <summary>Gets the file handle representing this device</summary>
/// <value>The file handle</value>
int _fileDescriptor;
// Persistent, aligned native buffer
private nuint _nativeBuffer;
Device() {}
#region IDisposable Members
public new unsafe void Dispose()
{
if(_nativeBuffer == 0) return;
NativeMemory.AlignedFree((void*)_nativeBuffer);
_nativeBuffer = 0;
_capacity = 0;
}
#endregion
private unsafe void EnsureCapacityAligned(nuint size)
{
if(size <= _capacity) return;
if(_nativeBuffer != 0) NativeMemory.AlignedFree((void*)_nativeBuffer);
_nativeBuffer = (nuint)NativeMemory.AlignedAlloc(size, ALIGNMENT);
_capacity = size;
}
internal new static Device Create(string devicePath, out ErrorNumber errno)
{
errno = ErrorNumber.NoError;

View File

@@ -44,8 +44,8 @@ namespace Aaru.Devices.Windows;
partial class Device
{
/// <inheritdoc />
public override int SendScsiCommand(Span<byte> cdb, ref byte[] buffer, uint timeout, ScsiDirection direction,
out double duration, out bool sense)
public override unsafe int SendScsiCommand(Span<byte> cdb, ref byte[] buffer, uint timeout, ScsiDirection direction,
out double duration, out bool sense)
{
// We need a timeout
if(timeout == 0) timeout = Timeout > 0 ? Timeout : 15;
@@ -62,6 +62,8 @@ partial class Device
_ => ScsiIoctlDirection.Unspecified
};
EnsureCapacityAligned((nuint)buffer.Length);
var sptdSb = new ScsiPassThroughDirectAndSenseBuffer
{
SenseBuf = new byte[32],
@@ -73,7 +75,7 @@ partial class Device
DataIn = dir,
DataTransferLength = (uint)buffer.Length,
TimeOutValue = timeout,
DataBuffer = Marshal.AllocHGlobal(buffer.Length)
DataBuffer = (IntPtr)_nativeBuffer
}
};
@@ -81,11 +83,12 @@ partial class Device
sptdSb.sptd.SenseInfoOffset = (uint)Marshal.SizeOf(sptdSb.sptd);
cdb.CopyTo(sptdSb.sptd.Cdb);
// OUT or BiDir → precopy
if(direction != ScsiDirection.In) buffer.AsSpan().CopyTo(new Span<byte>((void*)_nativeBuffer, buffer.Length));
uint k = 0;
int error = 0;
Marshal.Copy(buffer, 0, sptdSb.sptd.DataBuffer, buffer.Length);
var cmdStopwatch = new Stopwatch();
cmdStopwatch.Start();
@@ -102,7 +105,7 @@ partial class Device
if(hasError) error = Marshal.GetLastWin32Error();
Marshal.Copy(sptdSb.sptd.DataBuffer, buffer, 0, buffer.Length);
if(direction != ScsiDirection.Out) new Span<byte>((void*)_nativeBuffer, buffer.Length).CopyTo(buffer);
sense |= sptdSb.sptd.ScsiStatus != 0;
@@ -110,8 +113,6 @@ partial class Device
duration = cmdStopwatch.Elapsed.TotalMilliseconds;
Marshal.FreeHGlobal(sptdSb.sptd.DataBuffer);
return error;
}

View File

@@ -43,14 +43,40 @@ namespace Aaru.Devices.Windows;
/// <inheritdoc />
[SupportedOSPlatform("windows")]
partial class Device : Devices.Device
partial class Device : Devices.Device, IDisposable
{
private const nuint ALIGNMENT = 64;
private nuint _capacity;
/// <summary>Gets the file handle representing this device</summary>
/// <value>The file handle</value>
SafeFileHandle _fileHandle;
private nuint _nativeBuffer;
Device() {}
#region IDisposable Members
public new unsafe void Dispose()
{
if(_nativeBuffer == 0) return;
NativeMemory.AlignedFree((void*)_nativeBuffer);
_nativeBuffer = 0;
_capacity = 0;
}
#endregion
private unsafe void EnsureCapacityAligned(nuint size)
{
if(size <= _capacity) return;
if(_nativeBuffer != 0) NativeMemory.AlignedFree((void*)_nativeBuffer);
_nativeBuffer = (nuint)NativeMemory.AlignedAlloc(size, ALIGNMENT);
_capacity = size;
}
internal new static Device Create(string devicePath, out ErrorNumber errno)
{
errno = ErrorNumber.NoError;
@@ -102,10 +128,10 @@ partial class Device : Devices.Device
};
IntPtr descriptorPtr = Marshal.AllocHGlobal(1000);
var descriptorB = new byte[1000];
byte[] descriptorB = new byte[1000];
uint returned = 0;
var error = 0;
int error = 0;
bool hasError = !Extern.DeviceIoControlStorageQuery(dev._fileHandle,
WindowsIoctl.IoctlStorageQueryProperty,
@@ -203,7 +229,7 @@ partial class Device : Devices.Device
if(IsSdhci(dev._fileHandle))
{
var sdBuffer = new byte[16];
byte[] sdBuffer = new byte[16];
dev.LastError = dev.SendMmcCommand(MmcCommands.SendCsd,
false,