9.4. Generic driver (sg)

See reference W4 for the SCSI Generic (sg) driver documentation. For SCSI standards see reference W1 and for a book on the subject of SCSI programming and pass through mechanisms see reference B3.

Currently the sg documentation focuses on the production version of sg found in the lk 2.2 series. The abridged form is in the file scsi-generic.txt which can also be found in the kernel source at /usr/src/linux/Documentation/scsi-generic.txt. The web site also contains a longer form called scsi-generic_long.txt. This documentation describes what is termed as "version 2" sg.

The sg driver in lk 2.4 has the "version 3" sg driver which adds an additional interface and some new ioctl()s. The most interesting new ioctl() is SG_IO which sends a SCSI command and waits for its response. The additions and differences in the version 3 sg driver are documented on the web site in the file scsi-generic_v3.txt.

The abbreviation "sg" is used within the kernel to refer both to the SCSI generic driver and the scatter-gather capability offered by many modern IO devices (usually associated with DMA). The context usually makes it clear which one is being referred to. As an example, note the contorted sg ioctl() named SG_GET_SG_TABLESIZE where the second "SG" refers to scatter gather.

The public interface for sg is found in the file: /usr/src/linux/include/scsi/sg.h. Depending on the distribution this may or may not contain the same information as /usr/include/scsi/sg.h which is controlled by the GNU library maintainers. If these 2 files are not the same use the former header file. Those writing applications based on sg should see its documentation for more on this matter.

The sg driver registers all SCSI devices (with a current maximum of 256) as they are seen. Each newly registered SCSI device gets allocated the next available minor device number. At least initially this will be the same sequence that devices are displayed in mid level's cat /proc/scsi/scsi. The sg devices device mapping can been seen with cat /proc/scsi/sg/devices or cat /proc/scsi/sg/device_strs. Differences between cat /proc/scsi/scsi and sg orderings will appear when a low level driver is removed (e.g. rmmod aha1542) or when a device is removed with remove-single-device. The sg driver will leave remaining SCSI device mapping to minor device numbers unchanged. This potentially leaves a "hole" in the sg mapping. An example follows:
$ cat /proc/scsi/scsi 
Attached devices: 
Host: scsi0 Channel: 00 Id: 00 Lun: 00
  Vendor: IBM      Model: DNES-309170W     Rev: SA30
  Type:   Direct-Access            ANSI SCSI revision: 03
Host: scsi1 Channel: 00 Id: 02 Lun: 00
  Vendor: PIONEER  Model: DVD-ROM DVD-303  Rev: 1.10
  Type:   CD-ROM                   ANSI SCSI revision: 02
Host: scsi1 Channel: 00 Id: 06 Lun: 00
  Vendor: YAMAHA   Model: CRW4416S         Rev: 1.0g
  Type:   CD-ROM                   ANSI SCSI revision: 02

$ cat /proc/scsi/sg/device_strs 
IBM             DNES-309170W            SA30
PIONEER         DVD-ROM DVD-303         1.10
YAMAHA          CRW4416S                1.0g

$ echo "scsi remove-single-device 1 0 2 0" > /proc/scsi/scsi

$ cat /proc/scsi/scsi 
Attached devices: 
Host: scsi0 Channel: 00 Id: 00 Lun: 00
  Vendor: IBM      Model: DNES-309170W     Rev: SA30
  Type:   Direct-Access            ANSI SCSI revision: 03
Host: scsi1 Channel: 00 Id: 06 Lun: 00
  Vendor: YAMAHA   Model: CRW4416S         Rev: 1.0g
  Type:   CD-ROM                   ANSI SCSI revision: 02

$ cat /proc/scsi/sg/device_strs 
IBM             DNES-309170W            SA30
<no active device>
YAMAHA          CRW4416S                1.0g
Notice how the sg driver maintains the row positions of the remaining devices in the "device_strs" output. So when the Pioneer dvd player is removed, a hole opens up in the sg device mapping which is not reflected in the cat /proc/scsi/scsi output. That "hole" corresponds to the device name /dev/sg1.

The new sg_io_hdr interface includes a data transfer residual count field called "resid". Only some lower level adapters support this feature and those that don't always yield zero in this field. At the time of writing the advansys, aha152x and the sym53c8xx drivers support this feature.

9.4.1. sg boot parameters

The sg driver maintains a reserved buffer for each open file descriptor. The purpose is to guarantee applications that data transfers up to the size of the reserved buffer will not fail for lack of kernel memory. This is important for applications like cdrecord that cannot easily recover (the CDR) from a ENOMEM error.

In the absence of the boot parameter 'sg_def_reserved_size' or the sg module parameter 'def_reserved_size', then each time a sg file descriptor is opened the reserved buffer size is inherited from SG_DEF_RESERVED_SIZE which is defined in include/linux/sg.h.

The SG_DEF_RESERVED_SIZE define value can be overridden by this kernel boot option:
    sg_def_reserved_size=<n>

9.4.2. sg module parameters

When the sg module is loaded the SG_DEF_RESERVED_SIZE define value can be overridden by supplying this option:
    def_reserved_size=<n>

9.4.3. sg proc interface

All the following files are readable by all and produce ASCII output when read. The file 'def_reserved_size' is also writable by root. The ASCII output has been formatted in such a way as to be human and machine readable (and hence a compromise). Use Unix commands of the form cat device_hdrs devices to see the output of tables.

/proc/scsi/sg/debug       [internal state of sg driver]
/proc/scsi/sg/def_reserved_size
                          [like boot/module load parameter]
/proc/scsi/sg/devices     [table of numeric device data]
/proc/scsi/sg/device_hdr  [column headers for sg/devices]
/proc/scsi/sg/device_strs [table of strings from INQUIRY]
/proc/scsi/sg/hosts       [table of numeric host data]
/proc/scsi/sg/host_hdr    [column headers for sg/hosts]
/proc/scsi/sg/host_strs   [table of string ids for hosts]
/proc/scsi/sg/version     [sg version number and date]
All the above files are owned by root and readable by all while def_reserved_size is writable by root. For the devices and device_strs files the first row output corresponds to /dev/sg0 (sg minor device number 0). The second row output corresponds to /dev/sg1, etc. For the hosts and host_strs files the first row output corresponds to host (adapter number) 0, etc. For numeric tables a missing device or host is indicated by a row of "-1" values. For string tables a missing device or host is indicated by a row containing "<no active device/host>".