@@ -175,8 +175,35 @@ public LunInfo GetInfo(long lun)
175175 return new LunInfo ( targetInfo , lun , resp . DeviceType , resp . Removable , resp . VendorId , resp . ProductId , resp . ProductRevision ) ;
176176 }
177177
178+ private bool _no16support ;
179+
178180 /// <summary>
179- /// Gets the capacity of a particular LUN.
181+ /// Gets the capacity of a particular LUN. First attempts
182+ /// to get 64 bit capacity and if that is not supported by
183+ /// target, gets 32 bit capacity instead.
184+ /// </summary>
185+ /// <param name="lun">The LUN to query.</param>
186+ /// <returns>The LUN's capacity.</returns>
187+ public LunCapacity GetCapacity ( long lun )
188+ {
189+ if ( ! _no16support )
190+ {
191+ try
192+ {
193+ return ReadCapacity16 ( lun ) ;
194+ }
195+ catch
196+ {
197+ }
198+
199+ _no16support = true ;
200+ }
201+
202+ return ReadCapacity10 ( lun ) ;
203+ }
204+
205+ /// <summary>
206+ /// Gets the 32 bit capacity of a particular LUN.
180207 /// </summary>
181208 /// <param name="lun">The LUN to query.</param>
182209 /// <returns>The LUN's capacity.</returns>
@@ -197,7 +224,7 @@ public LunCapacity ReadCapacity10(long lun)
197224 }
198225
199226 /// <summary>
200- /// Gets the capacity of a particular LUN.
227+ /// Gets the 64 bit capacity of a particular LUN.
201228 /// </summary>
202229 /// <param name="lun">The LUN to query.</param>
203230 /// <returns>The LUN's capacity.</returns>
@@ -212,6 +239,8 @@ public LunCapacity ReadCapacity16(long lun)
212239 throw new InvalidProtocolException ( "Truncated response" ) ;
213240 }
214241
242+ _no16support = false ;
243+
215244 // READ CAPACITY returns the address of the LAST logical block (zero-indexed)
216245 // So the actual count is last_block_address + 1
217246 return new LunCapacity ( resp . NumLogicalBlocks + 1L , ( int ) resp . LogicalBlockSize ) ;
@@ -246,10 +275,18 @@ public Disk OpenDisk(long lun, FileAccess access)
246275 /// <param name="blockCount">The number of blocks to read.</param>
247276 /// <param name="buffer">The buffer to fill.</param>
248277 /// <returns>The number of bytes read.</returns>
249- public int Read ( long lun , long startBlock , short blockCount , Span < byte > buffer )
278+ public int Read ( long lun , long startBlock , int blockCount , Span < byte > buffer )
250279 {
251- var cmd = checked ( new ScsiReadCommand ( ( ulong ) lun , ( uint ) startBlock , ( ushort ) blockCount ) ) ;
252- return Send ( cmd , default , buffer ) ;
280+ if ( startBlock + blockCount > uint . MaxValue || blockCount > ushort . MaxValue )
281+ {
282+ var cmd = checked ( new ScsiRead16Command ( ( ulong ) lun , startBlock , blockCount ) ) ;
283+ return Send ( cmd , default , buffer ) ;
284+ }
285+ else
286+ {
287+ var cmd = checked ( new ScsiRead10Command ( ( ulong ) lun , ( uint ) startBlock , ( ushort ) blockCount ) ) ;
288+ return Send ( cmd , default , buffer ) ;
289+ }
253290 }
254291
255292 /// <summary>
@@ -261,10 +298,18 @@ public int Read(long lun, long startBlock, short blockCount, Span<byte> buffer)
261298 /// <param name="buffer">The buffer to fill.</param>
262299 /// <param name="cancellationToken"></param>
263300 /// <returns>The number of bytes read.</returns>
264- public ValueTask < int > ReadAsync ( long lun , long startBlock , short blockCount , Memory < byte > buffer , CancellationToken cancellationToken )
301+ public ValueTask < int > ReadAsync ( long lun , long startBlock , int blockCount , Memory < byte > buffer , CancellationToken cancellationToken )
265302 {
266- var cmd = checked ( new ScsiReadCommand ( ( ulong ) lun , ( uint ) startBlock , ( ushort ) blockCount ) ) ;
267- return SendAsync ( cmd , default , buffer , cancellationToken ) ;
303+ if ( startBlock + blockCount > uint . MaxValue || blockCount > ushort . MaxValue )
304+ {
305+ var cmd = checked ( new ScsiRead16Command ( ( ulong ) lun , startBlock , blockCount ) ) ;
306+ return SendAsync ( cmd , default , buffer , cancellationToken ) ;
307+ }
308+ else
309+ {
310+ var cmd = checked ( new ScsiRead10Command ( ( ulong ) lun , ( uint ) startBlock , ( ushort ) blockCount ) ) ;
311+ return SendAsync ( cmd , default , buffer , cancellationToken ) ;
312+ }
268313 }
269314
270315 /// <summary>
@@ -275,10 +320,18 @@ public ValueTask<int> ReadAsync(long lun, long startBlock, short blockCount, Mem
275320 /// <param name="blockCount">The number of blocks to write.</param>
276321 /// <param name="blockSize">The size of each block (must match the actual LUN geometry).</param>
277322 /// <param name="buffer">The data to write.</param>
278- public void Write ( long lun , long startBlock , short blockCount , int blockSize , ReadOnlySpan < byte > buffer )
323+ public int Write ( long lun , long startBlock , int blockCount , int blockSize , ReadOnlySpan < byte > buffer )
279324 {
280- var cmd = checked ( new ScsiWriteCommand ( ( ulong ) lun , ( uint ) startBlock , ( ushort ) blockCount ) ) ;
281- Send ( cmd , buffer . Slice ( 0 , blockCount * blockSize ) , default ) ;
325+ if ( startBlock + blockCount > uint . MaxValue || blockCount > ushort . MaxValue )
326+ {
327+ var cmd = checked ( new ScsiWrite16Command ( ( ulong ) lun , startBlock , blockCount ) ) ;
328+ return Send ( cmd , buffer . Slice ( 0 , blockCount * blockSize ) , default ) ;
329+ }
330+ else
331+ {
332+ var cmd = checked ( new ScsiWrite10Command ( ( ulong ) lun , ( uint ) startBlock , ( ushort ) blockCount ) ) ;
333+ return Send ( cmd , buffer . Slice ( 0 , blockCount * blockSize ) , default ) ;
334+ }
282335 }
283336
284337 /// <summary>
@@ -290,10 +343,18 @@ public void Write(long lun, long startBlock, short blockCount, int blockSize, Re
290343 /// <param name="blockSize">The size of each block (must match the actual LUN geometry).</param>
291344 /// <param name="buffer">The data to write.</param>
292345 /// <param name="cancellationToken"></param>
293- public ValueTask WriteAsync ( long lun , long startBlock , short blockCount , int blockSize , ReadOnlyMemory < byte > buffer , CancellationToken cancellationToken )
346+ public ValueTask < int > WriteAsync ( long lun , long startBlock , int blockCount , int blockSize , ReadOnlyMemory < byte > buffer , CancellationToken cancellationToken )
294347 {
295- var cmd = checked ( new ScsiWriteCommand ( ( ulong ) lun , ( uint ) startBlock , ( ushort ) blockCount ) ) ;
296- return new ( SendAsync ( cmd , buffer . Slice ( 0 , blockCount * blockSize ) , default , cancellationToken ) . AsTask ( ) ) ;
348+ if ( startBlock + blockCount > uint . MaxValue || blockCount > ushort . MaxValue )
349+ {
350+ var cmd = checked ( new ScsiWrite16Command ( ( ulong ) lun , startBlock , blockCount ) ) ;
351+ return SendAsync ( cmd , buffer . Slice ( 0 , blockCount * blockSize ) , default , cancellationToken ) ;
352+ }
353+ else
354+ {
355+ var cmd = checked ( new ScsiWrite10Command ( ( ulong ) lun , ( uint ) startBlock , ( ushort ) blockCount ) ) ;
356+ return SendAsync ( cmd , buffer . Slice ( 0 , blockCount * blockSize ) , default , cancellationToken ) ;
357+ }
297358 }
298359
299360 /// <summary>
0 commit comments