            Notes on Linux's SG driver version 2.1.39
            -----------------------------------------
                                                        20010329

Introduction
============
The SCSI Generic driver (sg) is one of the four "high level" SCSI device
drivers along with sd, st and sr (disk, tape and CDROM respectively). Sg
is more generalized (but lower level) than its siblings and tends to be
used on SCSI devices that don't fit into the already serviced categories.
Thus sg is used for scanners, cd writers and reading audio cds digitally
amongst other things.

These are notes on the Linux SCSI generic packet device driver (sg)
describing version 2.1.39 . The original driver was written by Lawrence
Foard and remained in place with minimal changes since circa 1992.
Version 2 of this driver remains backward compatible (binary and
source **) with the original. It adds scatter gather, command queuing,
per file descriptor sequencing, asynchronous notification and better
error reporting.

This is an abridged version of the sg documentation that is targeted
at the linux/Documentation directory. The full document can be found
at http://www.torque.net/sg/p/scsi-generic_long.txt .

The Linux 2.4 series kernels have now been released. Lk 2.4 contains
an upgraded "version 3" sg driver which is described in a supplementary
document at http://www.torque.net/sg/p/scsi-generic_v3.txt .

The interface and usage of the original sg driver have been documented
by Heiko Eissfeldt in a HOWTO called SCSI-Programming-HOWTO. My copy
of the document is version 1.5 dated 7th May 1996. It can found at
ftp://sunsite.unc.edu/pub/Linux/docs/HOWTO-SCSI-Programming-HOWTO .
A copy of this document can be found at:
http://www.torque.net/sg/p/original/HOWTO-SCSI-Programming-HOWTO.txt .

** It is possible to write applications that perform differently
depending on whether they are using the original or this version of
the sg device driver. The author is not aware of any useful
pre-existing applications that have problems with version 2.


Architecture
============
The SCSI generic packet device driver (sg) is a character based device.
It is one of the four high level device driver in the SCSI sub-system;
the others are sd (for direct-access devices - disks), st (for tapes)
and sr (for data cdroms). Sd and sr are block devices while st (like sg)
is a character device.

The unifying layer of the SCSI sub-system is the so-called mid-level.
Below that are the "low level" drivers which are the drivers for the
various adapters supported by Linux. Also at this level are pseudo
adapter drivers such as ide-scsi which converts the SCSI protocol to
ATAPI (which are similar to one another) for use by IDE devices.

Since sg is a character device it supports the traditional Unix
system calls of open(), close(), read(), write() and ioctl(). Two other
related system calls: poll() and fcntl() are added to this list and
how they interact with the sg device driver is documented later.

An SG device is accessed by write()ing SCSI commands plus any associated
outgoing data to it; the resulting status codes and any incoming data are
then obtained by a read() call. The device can be opened O_NONBLOCK
(non-blocking) and poll() used to monitor its progress. The device may be
opened O_EXCL which excludes other "sg" users from this device (but not
"sd", "st" or "sr" users). The buffer given to the write() call is made
up as follows:
        - struct sg_header image (see below)
        - scsi command (6, 10 or 12 bytes long)
        - data to be written to the device (if any)

The buffer received from the corresponding read() call contains:
        - struct sg_header image (check status/errors + sense_buffer)
        - data read back from device (if any)

The given SCSI command has its LUN field overwritten by the LUN value of
the associated sg device that has been open()ed.

SCSI commands are only attempted once (i.e. there are no internal
retries). If appropriate (e.g. a SCSI READ) the data buffer is copied back
to user space irrespective of the values of the various SCSI related
error/status codes. [Some adapters that use an old error interface in
the SCSI mid level ignore the retry count and retry certain errors.]


sg_header
=========
This is the name of the control structure that conveys information
about the length of data to be read/written by the associated SCSI
command. It also conveys error and status information from the
read() call. An instance of this structure is the first thing that
is placed in the data buffers of both write() and read().

In its original form it looked like this:
struct sg_header {
    int pack_len;
    int reply_len;
    int pack_id;
    int result;
    unsigned int twelve_byte:1;
    unsigned int other_flags:31;
    unsigned char sense_buffer[16];
}; /* this structure is 36 bytes long */

The 'pack_len' is bizarre and ends up having the 'reply_len' put in it
(perhaps it had a use at some stage). Even though it looks like an
input variable, it is not read by sg internally (only written).

The 'reply_len' is the length of the data the corresponding read()
will/should request (including the sg_header).

The 'pack_id' is not acted upon by the sg device driver but is conveyed
back to the corresponding read() so it can be used for sequencing by an
application.

The 'result' is also bizarre, turning certain types of host codes to 0 (no
error), EBUSY or EIO. With better error reporting now available, the
'result' is best ignored.

The 'twelve_byte' field overrides the internal SCSI command length detection
algorithm for group 6 and 7 commands (ie when 1st byte >= 0xc0) and forces
a command length of 12 bytes.
The command length detection algorithm is as follows:
Group:  0    1    2    3    4    5    6    7
Length: 6   10   10   12   12   12   10   10

'other_flags' was originally documented as "not used" but some current
applications assume it has 0 placed in it.

The 'sense_buffer' is the first 16 bytes of SCSI sense buffer that is
returned when the target returns a SCSI status code of CHECK_CONDITION
or COMMAND_TERMINATED [or (driver_status & DRIVER_SENSE) is true]. This
buffer should be at least 18 bytes long and arguably 32 bytes; unfortunately
this is unlikely to happen in the 2.2.x series of kernels.


The new sg_header offered in this driver is:
#define SG_MAX_SENSE 16
struct sg_header
{
    int pack_len;    /* [o] reply_len (ie useless) ignored as input */
    int reply_len;   /* [i] max length of expected reply (inc. sg_header) */
    int pack_id;     /* [io] id number of packet (use ints >= 0) */
    int result;      /* [o] 0==ok, else (+ve) Unix errno (best ignored) */
    unsigned int twelve_byte:1;
        /* [i] Force 12 byte command length for group 6 & 7 commands  */
    unsigned int target_status:5;   /* [o] scsi status from target */
    unsigned int host_status:8;     /* [o] host status (see "DID" codes) */
    unsigned int driver_status:8;   /* [o] driver status+suggestion */
    unsigned int other_flags:10;    /* unused */
    unsigned char sense_buffer[SG_MAX_SENSE]; /* [o] Output in 3 cases:
           when target_status is CHECK_CONDITION or
           when target_status is COMMAND_TERMINATED or
           when (driver_status & DRIVER_SENSE) is true. */
};      /* This structure is 36 bytes long on i386 */

Firstly the new header is binary compatible with the original. This is
important for keeping existing apps working without recompilation.

Only those elements (or fields) that are new or in some way different
from the original are documented below.

'pack_id' becomes input to a read() when ioctl(sg_fd, SG_SET_FORCE_PACK_ID,
&one) is active. A 'pack_id' of -1 is interpreted as fetch the oldest
waiting packet; any other value will cause the read() to wait (or yield
EAGAIN) until a packet with that 'pack_id' becomes available. In all cases
the value of 'pack_id' available after a read() is the value given to that
variable in the prior, corresponding write().

The SCSI command length can now be given directly using the SG_NEXT_CMD_LEN
ioctl().

The 'target_status' field is always output and is the (masked and shifted
1 bit right) SCSI status code from the target device. The allowable
values are (found in <scsi/scsi.h>):
/* N.B. 1 bit offset from usual SCSI status values */
#define GOOD                 0x00
#define CHECK_CONDITION      0x01
#define CONDITION_GOOD       0x02
#define BUSY                 0x04
#define INTERMEDIATE_GOOD    0x08
#define INTERMEDIATE_C_GOOD  0x0a
#define RESERVATION_CONFLICT 0x0c
#define COMMAND_TERMINATED   0x11
#define QUEUE_FULL           0x14
When the 'target_status' is CHECK_CONDITION or COMMAND_TERMINATED the
'sense_buffer' is output. Note that when (driver_status & DRIVER_SENSE)
is true then the 'sense_buffer' is also output (this seems to occur when
the ide-scsi emulation is used). When the 'sense_buffer' is output the
SCSI Sense Key can be found at (sense_buffer[2] & 0x0f) .

The 'host_status' field is always output and has the following values
whose "defines" are not visible outside the kernel. A copy of these
defines can be found in sg_err.h (see the utilities section):
#define DID_OK          0x00 /* NO error                                */
#define DID_NO_CONNECT  0x01 /* Couldn't connect before timeout period  */
#define DID_BUS_BUSY    0x02 /* BUS stayed busy through time out period */
#define DID_TIME_OUT    0x03 /* TIMED OUT for other reason              */
#define DID_BAD_TARGET  0x04 /* BAD target, device not responding?      */
#define DID_ABORT       0x05 /* Told to abort for some other reason     */
#define DID_PARITY      0x06 /* Parity error                            */
#define DID_ERROR       0x07 /* Internal error [DMA underrun on aic7xxx]*/
#define DID_RESET       0x08 /* Reset by somebody.                      */
#define DID_BAD_INTR    0x09 /* Got an interrupt we weren't expecting.  */
#define DID_PASSTHROUGH 0x0a /* Force command past mid-layer            */
#define DID_SOFT_ERROR  0x0b /* The low level driver wants a retry      */

The 'driver_status' field is always output. When ('driver_status' &
DRIVER_SENSE) is true the 'sense_buffer' is also output. A copy of these
defines can be found in sg_err.h (see the utilities section):
#define DRIVER_OK           0x00 /* Typically no suggestion */
#define DRIVER_BUSY         0x01
#define DRIVER_SOFT         0x02
#define DRIVER_MEDIA        0x03
#define DRIVER_ERROR        0x04
#define DRIVER_INVALID      0x05
#define DRIVER_TIMEOUT      0x06
#define DRIVER_HARD         0x07
#define DRIVER_SENSE        0x08 /* Implies sense_buffer output */
/* above status 'or'ed with one of the following suggestions */
#define SUGGEST_RETRY       0x10
#define SUGGEST_ABORT       0x20
#define SUGGEST_REMAP       0x30
#define SUGGEST_DIE         0x40
#define SUGGEST_SENSE       0x80

'other_flags' still remains as a 10 bit field (reduced from 31 bits), so
code that places 0 in it will still be happy. It is not used.


System Calls
============
What follows are descriptions of the characteristics of the standard
Unix operating system calls when applied to a SCSI generic device
using this version of the device driver.

open(const char * filename, int flags)
--------------------------------------
The filename should be an 'sg' device such as
/dev/sg[0,1,2,...]
/dev/sg[a-z]             <<< now deprecated >>>
or a symbolic link to one of these. [Devfs has its own sub-directory for
sg devices with entries like: /dev/scsi/host1/bus2/target3/lun4/generic .]
It seems as though SCSI devices are allocated to sg minor numbers in the
same order as they appear in 'cat /proc/scsi/scsi'. Sg is a "character"
based Linux device driver.  This means it has an open/close/read/write/ioctl
type interface.

Flags can be either O_RDONLY or O_RDWR or-ed with either
O_EXCL          waits for other opens on sg device to be closed before
                proceeding. If O_NONBLOCK is set then yields EBUSY when
                someone else has the sg device open. The combination of
                O_RDONLY and O_EXCL is disallowed.
O_NONBLOCK      Sets non-blocking mode. Calls that would otherwise block
                yield EAGAIN (eg read() ) or EBUSY (eg open() ).

The original version of sg did not allow the O_RDONLY (yielding a EACCES
error). This version allows it for accessing ioctls (e.g. doing an sg
device scan with the SG_GET_SCSI_ID ioctl) but write()s will not be
allowed. These flags are found in <fcntl.h> .

By default, sequencing is per file descriptor in this version of sg. This
means, for example that 2 processes can independently manipulate the same
sg device at the same time. This may or may not make sense depending on
the application: 2 processes (logically) reading from the same direct access
device (ie a disk) is ok while running 2 instances of cd writing software
on the same device at the same time probably wouldn't be a good idea. The
previous version of sg supported only per device sequencing and this can
still be selected with the SG_SET_MERGE_FD,1 ioctl().

The driver will attempt to reserve SG_DEF_RESERVED_SIZE bytes (32KBytes in
the current sg.h) on open(). The size of this reserved buffer can
subsequently be modified with the SG_SET_RESERVED_SIZE ioctl(). In both
cases these are requests subject to various dynamic constraints. The actual
amount of memory obtained can be found by the SG_GET_RESERVED_SIZE ioctl().
The reserved buffer will be used if:
    -  it is not already in use (eg when command queuing is in use)
    -  a write() does not call for a buffer size larger than the
       reserved size.

Returns a file descriptor if >= 0 , otherwise -1 implies an error.

Error codes (value in 'errno' after -1 returned):
EACCES          Either the user doesn't have appropriate permissions on
                'filename' or attempted to use both O_RDONLY and O_EXCL
EBUSY           O_NONBLOCK set and some user of this sg device has O_EXCL
                set while someone is already using this device
EINTR           while waiting for an "exclusive" lock to clear, a signal
                is received, just try again ...
ENODEV          sg not compiled into kernel or the kernel cannot find the
                sg module (or it can't initialize itself (low memory??))
ENOENT          given filename not found
ENOMEM          An attempt to get memory to store this open's context
                failed (this was _not_ a request to reserve DMA memory)
ENXIO           either there is no attached device corresponding to given
                filename or scsi sub-system is currently processing some
                error (eg doing a device reset) or the sg driver/module
                removed or corrupted


write(int sg_fd, const void * buffer, size_t count)
---------------------------------------------------
Even though sg is a character-based device driver it sends and receives
packets to/from the associated scsi device. Write() is used to send a
packet containing 2 mandatory parts and 1 optional part. The mandatory
parts are:
  - a control block (an instance of struct sg_header)
  - a SCSI command (6, 10 or 12 bytes long)
The optional part is:
  - outgoing data (eg if a SCSI write command is being sent)
These should appear as one contiguous string in the buffer given to
write() in the above order with no pad characters.

If a write() accepts this packet then at some later time the user should
call a read() to get the result of the SCSI command. The previous sg
driver enforced a strict write()/read()/write()/read() regime so that a
second write() would block until first read() was finished. This sg
driver relaxes that condition and thereby allows command queuing
(limit is SG_MAX_QUEUE (16) outstanding packets per file descriptor).
However, for backward compatibility, command queuing is turned off
by default (#define SG_DEF_COMMAND_Q 0 in sg.h). This can be changed
via the SG_SET_COMMAND_Q ioctl() [or by recompiling after changing
the above define to 1].

In this sg driver a write() should return more or less immediately.

Returns number of bytes written if > 0 , otherwise -1 implies an error.

Error codes (value in 'errno' after -1 returned):
EACCES          opened with RD_ONLY flag
EAGAIN          SCSI mid-level out of command blocks (rare), try again.
                This is more likely to happen when queuing commands,
                so wait a bit (eg usleep(10000) ) before trying again
EDOM            a) command queuing off: a packet is already queued
                b) command queuing on: too many packets queued
                   (SG_MAX_QUEUE exceeded)
EFAULT          'buffer' for 'count' bytes is an invalid memory range
EIO             a) incoming buffer too short. It should be at least
                   (6 + sizeof(struct sg_header))==42 bytes long
                b) SCSI command length given in SG_NEXT_CMD_LEN too long
                c) reply_len negative
ENOMEM          can't get memory for DMA. Take evasive action ...
ENXIO           either scsi sub-system is currently processing some error
                (eg doing a device reset) or the sg driver/module removed
                or corrupted


read(int sg_fd, void * buffer, size_t count)
--------------------------------------------
Read() is used to receive a packet containing 1 mandatory part and 1
optional part. The mandatory part is:
  - a control block (an instance of struct sg_header)
The optional part is:
  - incoming data (eg if a SCSI read command was sent by earlier write() )
The buffer given to a read() and its corresponding count should be
sufficient to accommodate this packet to avoid truncation. Truncation occurs
if count < sg_header::replylen .

By default, read() will return the oldest packet queued up. If the
SG_SET_FORCE_PACK_ID,1 ioctl() is active then read() will attempt to
fetch the packet whose pack_id (given earlier to write()) matches the
sg_header::pack_id given to this read(). If not available it will either
wait or yield EAGAIN. As a special case, -1 in sg_header::pack_id given
to read() will match the oldest packet.

Returns number of bytes read if > 0 , otherwise -1 implies an error.
Unfortunately the return value in the non-error case is simply the
same as the count argument. It is not the actual number of bytes
DMA-ed by the SCSI device. This driver is currently unable to provide
such an underrun indication.

If the SCSI device reports an error then a REQUEST SENSE is automatically
done and the output is placed in the sense_buffer array which is in the
control block. This action is sometimes called "auto-sense".

Error codes (value in 'errno' after -1 returned):
EAGAIN          either no waiting packet or requested packet is not
                available while O_NONBLOCK flag was set
EFAULT          'buffer' for 'count' bytes is an invalid memory range
EINTR           while waiting for a packet, a signal is received, just
                try again ...
EIO             if the 'count' given to read() is < sizeof(struct sg_header)
                and the 'result' element in sg_header is non-zero. Not a
                recommended error reporting technique
ENXIO           either scsi sub-system is currently processing some error
                (eg doing a device reset) or the sg driver/module removed
                or corrupted


close(int sg_fd)
----------------
Preferably a close() should be done after all issued write()s have had
their corresponding read() calls completed. Unfortunately this is not
always possible. The semantics of close() in Unix are to return more
or less immediately (ie not wait on any event) so the driver needs to
arrange for an orderly cleanup of those packets that are still "in
flight".

A process that has an open file descriptor to an sg device may be aborted
(eg by a kill signal). In this case, the kernel automatically calls close
(which is called 'sg_release()' in the version 2 driver) to facilitate
the cleanup mentioned above.

A problem persists in version 2.1.39 if the sg driver is a module and is
removed while packets are still "in flight".

Returns 0 if successful, otherwise -1 implies an error.

Error codes (value in 'errno' after -1 returned):
ENXIO           sg driver/module removed or corrupted

ioctl(int sg_fd, int command, ...)  [sg specific]
-------------------------------------------------
Ken Thompson (or perhaps some other Unix luminary) described ioctl() as
the "garbage bin of Unix". This driver compounds the situation by adding
more ...
If a ioctl command is not recognized by sg (and the various lower levels
that it may pass the command on to) then the error EINVAL occurs. If an
invalid address is given (in the 3rd argument) then the error EFAULT occurs.

Those commands with an appended "+" are new in version 2.

Those commands with an appended "W" are only accessible from file
descriptors opened with O_RDWR. They will yield EACCES otherwise.

SG_GET_TIMEOUT:
Ignores its 3rd argument and _returns_ the timeout value (which will be
>= 0 ). The unit of this timeout is "jiffies" which are currently 10
millisecond intervals on i386 (less on an alpha). Linux supplies
a manifest constant HZ which is the number of "jiffies" in 1 second.

SG_SET_TIMEOUT:
Assumes 3rd argument points to an int containing the new timeout value
for this file descriptor. The unit is a "jiffy". Packets that are
already "in flight" will not be affected. The default value is set
on open() and is SG_DEFAULT_TIMEOUT (defined in sg.h). This default is
currently 1 minute and may not be long enough for formats. Negative
values will yield an EIO error.

SG_EMULATED_HOST:
Assumes 3rd argument points to an int and outputs a flag indicating
whether the host (adapter) is connected to a real SCSI bus or is an
emulated one (eg ide-scsi device driver). A value of 1 means emulated
while 0 is not.

SG_SET_TRANSFORM  W:
Only is meaningful when SG_EMULATED host has yielded 1 (i.e. the low-level
is the ide-scsi device driver); otherwise an EINVAL error occurs. The
default state is to _not_ transform SCSI commands to the corresponding
ATAPI commands but pass them straight through as is. [Only certain classes
of SCSI commands need to be transformed to their ATAPI equivalents.]
The third argument is interpreted as an integer. When it is non-zero then
a flag is set inside the ide-scsi driver that transforms subsequent
commands sent to this driver. When zero is passed as the 3rd argument to
this ioctl then the flag within the ide-scsi driver is cleared and
subsequent commands are not transformed. Beware, this state will affect
all devices (and hence all related sg file descriptors) associated with
this ide-scsi "bus".

SG_GET_TRANSFORM:
Third argument is ignored. Only is meaningful when SG_EMULATED host has
yielded 1 (ie the low-level is the ide-scsi device driver); otherwise
an EINVAL error occurs. Returns 0 to indicate _not_ transforming SCSI
to ATAPI commands (default). Returns 1 when it is transforming them.

SG_SET_FORCE_LOW_DMA +:
Assumes 3rd argument points to an int containing 0 or 1. 0 (default)
means sg decides whether to use memory above 16 Mbyte level (on i386)
based on the host adapter being used by this SCSI device. Typically
PCI SCSI adapters will indicate they can DMA to the whole 32 bit address
space.
If 1 is given then the host adapter is overridden and only memory below
the 16MB level is used for DMA. A requirement for this should be
extremely rare. If the "reserved" buffer allocated on open() is not in
use then it will be de-allocated and re-allocated under the 16MB level
(and the latter operation could fail yielding ENOMEM).
Only the current file descriptor is affected.

SG_GET_LOW_DMA +:
Assumes 3rd argument points to an int and places 0 or 1 in it. 0
indicates the whole 32 bit address space is being used for DMA transfers
on this file descriptor. 1 indicates the memory below the 16MB level
(on i386) is being used (and this may be the case because the host
adapters setting has been overridden by SG_SET_FORCE_LOW_DMA,1 .

SG_GET_SCSI_ID +:
Assumes 3rd argument is pointing to an object of type Sg_scsi_id (see
sg.h) and populates it. That structure contains ints for host_no,
channel, scsi_id, lun, scsi_type, allowable commands per lun and
queue_depth. Most of this information is available from other sources
(eg SCSI_IOCTL_GET_IDLUN and SCSI_IOCTL_GET_BUS_NUMBER) but tends to be
awkward to collect.
Allowable commands per lun and queue_depth give an insight to the
command queuing capabilities of the adapters and the device. The latter
overrides the former (logically) and the former is only of interest
if it is equal to queue_depth which probably indicates the device
does not support queueing commands (e.g. most scanners).

SG_SET_FORCE_PACK_ID +:
Assumes 3rd argument is pointing to an int. 0 (default) instructs read()
to return the oldest (written) packet if multiple packets are
waiting to be read (when command queuing is being used).
1 instructs read() to view the sg_header::pack_id as input and return the
oldest packet matching that pack_id or wait until it arrives (or yield
EAGAIN if O_NONBLOCK is in force). As a special case the pack_id of -1
given to read() in the mode will match the oldest packet.
Only the current file descriptor is affected by this command.

SG_GET_PACK_ID +:
Assumes 3rd argument points to an int and places the pack_id of the
oldest (written) packet in it. If no packet is waiting to be read then
yields -1.

SG_GET_NUM_WAITING +:
Assumes 3rd argument points to an int and places the number of packets
waiting to be read in it.

SG_GET_SG_TABLESIZE +:
Assumes 3rd argument points to an int and places the maximum number of
scatter gather elements supported by the host adapter. 0 indicates that
the adapter does support scatter gather.

SG_SET_RESERVED_SIZE +W:
Assumes 3rd argument is pointing to an int. That value will be used to
request a new reserved buffer of that size. The previous reserved buffer
is freed (if it is not in use; if it was in use -EBUSY is returned).
A new reserved buffer is then allocated and its actual size can be found by
calling the SG_GET_RESERVED_SIZE ioctl(). The reserved buffer is then used
for DMA purposes by subsequent write() commands if it is not already in
use and if the write() is not calling for a buffer size larger than that
reserved. The reserved buffer may well be a series of kernel buffers if the
adapter supports scatter-gather. Large buffers can be requested (eg 1 MB).

SG_GET_RESERVED_SIZE +:
Assumes 3rd argument points to an int and places the size in bytes of
the reserved buffer from open() or the most recent SG_SET_RESERVED_SIZE
ioctl() call on this fd.  The result can be 0 if memory is very tight. In
this case it may not be wise to attempt something like burning a CD on
this file descriptor.

SG_SET_MERGE_FD +W:
Assumes 3rd argument is pointing to an int. 0 (the default) causes all
subsequent sequencing to be per file descriptor. 1 causes all subsequent
sequencing to be per device. If this command tries to change the current
state and there is one or more _other_ file descriptors using this sg
device then an EBUSY error occurs. Per device sequencing was the original
semantics and allowed, for example different processes to "share" the
device, one perhaps write()ing with the other one read()ing. This command
is supplied if anyone needs those semantics. Per file descriptor
sequencing, perhaps with the use of the O_EXCL flag, seems more sensible.

SG_GET_MERGE_FD +:
Assumes 3rd argument points to an int and places 0 or 1 in it. 0 implies
sequencing is per file descriptor. 1 implies sequencing is per device
(original sg driver's semantics).

SG_SET_COMMAND_Q +:
Assumes 3rd argument is pointing to an int. 0 (current default, set by
SG_DEF_COMMAND_Q in sg.h) disables command queuing. Attempts to write()
a packet while one is already queued will result in a EDOM error.
1 turns command queuing on.
Changing the queuing state only affects write()s done after the change.
Only the current file descriptor is affected by this command.

SG_GET_COMMAND_Q +:
Assumes 3rd argument points to an int and places 0 or 1 in it. 0 implies
that command queuing is off on this file descriptor. 1 implies command
queuing is on.

SG_SET_UNDERRUN_FLAG +:
Assumes 3rd argument is pointing to an int. 0 (current default, set by
SG_DEF_UNDERRUN_FLAG in sg.h) requests underruns be ignored. 1 requests
that underruns be flagged. [The only low level driver that acts on this
at the moment is the aic7xxx which yields a DID_ERROR error on underrun.]
Only the current file descriptor is affected by this command (unless
"per device" sequencing has been selected).

SG_GET_UNDERRUN_FLAG +:
Assumes 3rd argument points to an int and places 0 or 1 in it. 0 implies
that underruns are not being reported. 1 implies that underruns are being
reported (see SG_SET_UNDERRUN_FLAG for more details).

SG_NEXT_CMD_LEN +:
Assumes 3rd argument is pointing to an int. The value of the int (if > 0)
will be used as the SCSI command length of the next SCSI command sent to
a write() on this fd. After that write() the SCSI command length logic is
reset to use automatic length detection (ie depending on SCSI command group
and the 'twelve_byte' field). If the current SCSI command length maximum of
12 is exceeded then the affected write() will yield an EDOM error.
Giving this ioctl() a value of 0 will set automatic length detection for
the next write(). N.B. Only the following write() on this fd is affected by
this ioctl().

SG_GET_VERSION_NUM +:
Assumes 3rd argument points to an int. The version number is then placed
in that int. A sg version such as 2.1.36 will yield "20136" from this ioctl.

SG_SCSI_RESET +:
Assumes 3rd argument points to an int. Unfortunately doesn't currently
do much (may in the future after other issues are resolved). Yields an
EBUSY error if the SCSI bus or the associated device is being reset
when this ioctl() is called, otherwise returns 0.
N.B. In some recent distributions there is a patch to the SCSI mid level
code that activates this ioctl. Check your distribution.

SG_SET_DEBUG +:
Assumes 3rd argument is pointing to an int. 0 (default) turns debugging
off. Values > 0 cause the SCSI sense buffer to be decoded and output
to the console/log when a SCSI device error occurs. Values > 8 cause
the current sg device driver's state to be output to the console/log
(this is a "one off" effect).
If you need a _lot_ of the SCSI sub-system debug information (mainly from
the mid-level) then try 'echo "scsi dump 0" > /proc/scsi/scsi' and lots of
debug will appear in your console/log.


poll(struct pollfd * udfds, unsigned int nfds, int timeout_ms)
--------------------------------------------------------------
This is a native call in Linux 2.2 but most of its capabilities are available
through the older select() call. Given a choice poll() should probably be
used. Typically poll() is used when a sg scsi device is open()ed O_NONBLOCK
for polling; and optionally with asynchronous notification as well using
the fcntl() system call (below) and the SIGPOLL (aka SIGIO) signal.
Only if something drastically is wrong (eg file handle gone stale) will
POLLERR ever be set. POLLPRI, POLLHUP and POLLNVAL are never set.
POLLIN is set when there is one or more packets waiting to be read.
When POLLIN is set it implies that a read() will not block (nor yield
EAGAIN in non-blocking mode) but return a packet immediately.
POLLOUT (aka POLLWRNORM) is set when write() is able to accept a packet
(ie will _not_ yield an EDOM error). The setting of POLLOUT is affected
by the SG_SET_COMMAND_Q state: if the state is on then POLLOUT will remain
set until the number of queued packets reaches SG_MAX_QUEUE, if the
state is off then POLLOUT is only set when no packets are queued.
Note that a packet can be queued after write()ing but not available to be
read(); this typically happens when a SCSI read command is issued while
the data is being retrieved.
Poll() is per file descriptor unless SG_SET_MERGE_FD is set in which case
it is per device.


fcntl(int sg_fd, int cmd) or fcntl(int sg_fd, int cmd, long arg)
----------------------------------------------------------------
There are several uses for this system call in association with a sg
file descriptor. The following pseudo code shows code that is useful for
scanning the sg devices, taking care not to be caught in a wait for
an O_EXCL lock by another process, and when the appropriate device is
found, switching to normal blocked io. A working example of this logic
is in the sg_scan utility program.

open("/dev/sg0", O_RDONLY | O_NONBLOCK)
/* check device, EBUSY means some other process has O_EXCL lock on it */
/* when the device you want is found then ... */
flags = fcntl(sg_fd, F_GETFL)
fcntl(sg_fd, F_SETFL, flags & (~ O_NONBLOCK))
/* since, for simple apps, it is easier to use normal blocked io */


Some work has to be done in Linux to set up for asynchronous notification.
This is a non-blocking mode of operation in which, when the driver receives
data back from a device so that a read() can be done, it sends a SIGPOLL
(aka SIGIO) signal to the owning process. A working example of this logic
is in the sg_poll test program.

sigemptyset(&sig_set)
sigaddset(&sig_set, SIGPOLL)
sigaction(SIGPOLL, &s_action, 0)
fcntl(sg_fd, F_SETOWN, getpid())
flags = fcntl(sg_fd, F_GETFL);
fcntl(sg_fd, F_SETFL, flags | O_ASYNC)


Utility and Test Programs
=========================
See the README file in the sg_utils<date>.tgz tarball. Look on the
http://www.torque.net/sg website for the latest version.

Briefly, that tarball contains the following utilities:
sg_dd512        'dd' like program that assumes 512 byte blocks size
sg_dd2048       'dd' like program that assumes 2048 byte blocks size
sg_dd2352       'dd' like program that assumes 2352 byte blocks size
sgq_dd512       like 'sg_dd512' but does command queuing on "if"
sgp_dd          probably the most flexible 'dd' variant. It uses POSIX
                threads, block size set by "bs=..." plus other options.
sg_scan         outputs information (optionally Inquiry) on SCSI devices
sg_rbuf         tests SCSI bus transfer speed (without physical IO)
sg_whoami       outputs info (optionally capacity) of given SCSI device
sginfo          outputs "mode" information about SCSI devices (it is a
                  re-port of the scsiinfo program onto the sg interface)

It also contains the following test programs:
sg_debug        outputs sg driver state to console/log file
sg_poll         tests asynchronous notification
sg_runt_ex      example run time selection program for application authors
sg_simple1      example program first time users
sg_simple2      like sg_simple1 but with more primitive error processing
sg_inquiry      does a SCSI Inquiry command (from original HOWTO)
sg_tst_med      checks presence of media (from original HOWTO)

There are also 2 source files (sg_err.[hc]) for outputting and categorizing
SCSI 2 errors and warnings. This code is used by most of the above
utility and test programs.

The following programs: sg_dd512, sg_dd2048, sg_dd2352, sg_scan, sg_runt_ex,
sg_rbuf, sg_tst_med, sg_inquiry and sginfo, can be compiled either for this
new sg driver _or_ the original sg driver (in 2.0 or 2.2 series kernels).
sg_runt_ex can be run on 2.0, 2.2 or 2.3 series kernels even if it is
compiled on a different series (eg compiled on 2.0, run on 2.2).


Header files
============
User applications need to find the correct "sg.h" header file matching
their kernel in order to write code using the sg device driver. This is
sometimes more difficult than it should be. The correct "sg.h" will usually
be found at /usr/src/linux/include/scsi/sg.h . Another important header
file is "scsi.h" which will be in the same directory.

When "#include <scsi/sg.h>" is written in an application then this refers
to the file /usr/include/scsi/sg.h . A problem sometimes arises because
the files in the /usr/include/scsi directory are controlled by the GNU
library people who maintain glibc. Unfortunately these 2 versions of
the sg.h header file are not always in sync. [This was the case in Redhat
6.0 and 6.1 .] Glibc 2.1.3 and later versions should get this right.

If this is a problem, the user may need to copy sg.h (and scsi.h) from
the kernel source includes to /usr/include scsi. If the user can change
the effected source code then another approach is to rely on the fact that
/usr/src/linux is a symbolic link to /usr/src/linux/include/linux and
change the sg.h include to look like:
    #include <linux/../scsi/sg.h>
This solution is used by the author of cdparanoia (Monty) in his application.

[Former scsi generic documents suggested adding a symbolic link to
bypass this problem but that is not popular with the glibc maintainers.
I would like to thank Andreas Jaeger <aj@suse.de> for his contributions
on this subject.]


Extra information in scsi-generic_long.txt
==========================================
This document is an abridged form of a more comprehensive document called
scsi-generic_long.txt (see www.torque.net/sg/p/scsi-generic_long.txt).

The longer document contains additional sections on:
   - memory issues
   - ioctl()s in common with sd, st + sr
   - distinguishing the original from the new driver
   - SG_BIG_BUFF and friends
   - shortcomings
   - future directions
   - an appendix with some SCSI 2 information in it


References
==========
http://www.t10.org      Very important site for SCSI related information.
                        Contains SCSI 2 and 3 draft standards.
http://www.andante.org/scsi.html
                        This is Eric Youngdale's site. Eric is primarily
                        responsible for the Linux SCSI architecture and
                        its mid-level implementation.
http://www.kernel.dk    Jens Axboe's site for Linux cdrom matters including
                        the SCSI "sr" driver.
http://www.torque.net/sg
                        My site with sg related information.
newsgroup:linux-scsi@vger.kernel.org
                        Newsgroup for Linux related SCSI matters
/usr/src/linux/MAINTAINERS
                        This is a file in the Linux kernel source that
                        contains up to date information about who maintains
                        what and where information can be found. Links to
                        SCSI adapter information are also here.


Conclusion
==========
The SCSI generic packet device driver attempts to make as few assumptions
as possible about the device it is connected to while giving applications
using it as much flexibility as possible on the SCSI command level. Sg
needs to hide the "messy" kernel related details while protecting
the integrity of the kernel against sg "abuse". Some of these aims are
contradictory and some compromises need to be made. For example: should
a sg based application be able to reset a SCSI bus when that could cause
collateral damage to a disk holding the root file system? There is no
easy answer to this and many other related questions.

If you have any suggestion about sg (or improving (the accuracy of) this
document) please contact me.


Douglas Gilbert
dgilbert@interlog.com
