Scsi Read (10) and Write (10) with The Scsi Generic Interface

SCSI Read (10) and Write (10) with the SCSI Generic Interface

In SCSI, the units of the LBA and the transfer length are in blocks, sometimes called sectors. This is almost always 512 bytes. So, you can't read or write just 32 bytes. At a minimum, you'll have to do 512 bytes == one block. This one point is most of what you need to fix.

Your transfer length is zero in your scsi_write implementation, so it's not actually going to write any data.

You should use different buffers for the CDB and the write/read data. I suspect that confusion about these buffers is leading your implementation to write past the end of one of your statically-allocated arrays and over your ReadBuffer. Run it under valgrind and see what shows up.

And lastly, a lot could go wrong in whatever is in handle_scsi_cmd. It can be tricky to set up the data transfer... in particular, make sure you're straight on which way the data is going in the I/O header's dxfer_direction: SG_DXFER_TO_DEV for write, SG_DXFER_FROM_DEV for read.

Check out this example of how to do a read(16). This is more along the lines of what you're trying to accomplish.

https://github.com/hreinecke/sg3_utils/blob/master/examples/sg_simple16.c

SCSI generic write() thread safe?

Read and write should be by definition safe but:

1) Reading and writing, does it happen on the same file descriptor. If not, the open file table in your system can have multiple offsets, resulting in data read and write in an inconsistent way.

2) If you have a block of data that has to be written to your disk, do you use write in a for loop? This is not safe, because other read or write operations can be started between two write calls. Have a look at readv and writev to atomically write big data blocks.

COMPARE AND WRITE on umapped block?

When a block is unmapped it is equal to all zeroes. You should perform all your commands that read or compare data with this block as it was just zeroes.

Meaning of the PMI bit in the SCSI READ CAPACITY command

This is actually out in SBC-3 too now, as of revision 28 (January, 2011) You can see the change here: (sign up required) http://www.t10.org/cgi-bin/ac.pl?t=d&f=11-010r0.pdf . So, you're talking SBC-2 compatibility.

Anyway, I don't think you'll ever see these fields set in practice. But, for the sake of completeness, you may wish to incorporate some additional error handling.

  1. Fail the request if PMI is zero, but the initiator specified an LBA.
  2. Fail the request if the LBA specified in the CDB is greater than the last LBA of your disk.

Presuming your implementation always knows what the capacity of your disk is, then there should never be a "substantial vendor specific delay". You can read the standard, then, as "return information on the last logical block after that specified in the LOGICAL BLOCK ADDRESS field". This should simply be the last LBA of your disk.

To answer your questions directly: when PMI is set, and an LBA is specified, you should report the last LBA on your disk, subject to the above error handling. And, you only need to look at the LBA field to do the error handling.

For SCSI, was there a change to the definition of ADDITIONAL LENGTH?

It is just worded in a more general way:

"If the information being transferred to the Data-In Buffer includes fields containing counts of the number of bytes in some or all of the data, then the contents of these fields shall not
be altered to reflect the truncation"

Get Device max links speed with scsi cmd

According to SPL-4, you many use SMP DISCOVER function or SCSI MODE SENSE page 19h Protocol Specific Port, subpage 01h Phy Control And Discover.

For link speed, you should use NEGOTIATED LOGICAL LINK RATE. The max link speed are HARDWARE MAXIMUM PHYSICAL LINK RATE (physical limitation) and PROGRAMMED MAXIMUM PHYSICAL LINK RATE (configured by PHY CONTROL function)

This is the example of using SMP DISCOVER way:

[fge@el7 ~]$ sudo smp_discover /dev/bsg/expander-0\:0
phy 0:T:attached:[500015535990a300:00 t(SATA)] 3 Gbps
phy 1:T:attached:[500015535990a301:00 t(SATA)] 3 Gbps
phy 2:T:attached:[500015535990a302:00 t(SATA)] 1.5 Gbps
phy 3:T:attached:[500015535990a303:00 t(SATA)] 3 Gbps
phy 4:T:attached:[500015535990a304:00 t(SATA)] 3 Gbps
phy 5:T:attached:[500015535990a305:00 t(SATA)] 3 Gbps
phy 6:T:attached:[500015535990a306:00 t(SATA)] 3 Gbps
phy 7:T:attached:[500015535990a307:00 t(SATA)] 3 Gbps
phy 8:T:attached:[500015535990a308:00 t(SATA)] 3 Gbps
phy 9:T:attached:[500015535990a309:00 t(SATA)] 3 Gbps
phy 10:T:attached:[500015535990a30a:00 t(SATA)] 3 Gbps
phy 11:T:attached:[500015535990a30b:00 t(SATA)] 3 Gbps
phy 12:T:attached:[500015535990a30c:00 t(SATA)] 3 Gbps
phy 13:T:attached:[500015535990a30d:00 t(SATA)] 3 Gbps
phy 14:T:attached:[50014ee5aaab876f:01 t(SSP)] 3 Gbps
phy 15:T:attached:[500015535990a30f:00 t(SATA)] 3 Gbps
phy 16:S:attached:[5d4ae520995f8200:03 i(SSP+STP+SMP)] 3 Gbps
phy 20:T:attached:[500015535956633f:16 exp i(SMP) t(SMP)] 3 Gbps
phy 21:T:attached:[500015535956633f:17 exp i(SMP) t(SMP)] 3 Gbps
phy 22:T:attached:[500015535956633f:18 exp i(SMP) t(SMP)] 3 Gbps
phy 23:T:attached:[500015535956633f:19 exp i(SMP) t(SMP)] 3 Gbps
phy 24:D:attached:[500015535990a33e:24 V i(SSP) t(SSP)] 3 Gbps

send SCSI commands using C#

You have a few options

1- Use p/invoke (platform invoke) interoperability. Using this you can do one of two things. Either use p/invoke to call the Win32 api from .NET, alternatively you can write a C dll that exports a simplified interface to control the device and then interop to this dll.

2- You could use managed C++, and create a library that you can call from C#.

3- You could wrap your C code as a COM object and use COM interop from C#.

Since you presumably have some working C code, I think the easiest would be to create a DLL that exports a easy to invoke interface and then use P/Invoke to call that from C#



Related Topics



Leave a reply



Submit