The following header files in the kernel source are relevant to the mid
level:
/usr/src/linux/include/scsi/scsi.h
/usr/src/linux/include/scsi/scsi_ioctl.h |
These files are meant for applications to use (other than parts in
a __KERNEL__ conditional compilation block). They may also be found in
/usr/include/scsi directory but it is best not to trust these versions as
they are maintained with the glibc library and may lag the kernel version
being used. Usually in Linux systems /usr/include/linux
can be relied upon to be a symbolic link to the kernel source's include
area (typically /usr/src/linux/include/linux). This
symbolic link can be used to include the correct scsi_ioctl.h using the following trick: #include <linux/../scsi/scsi_ioctl.h>
This include file: /usr/src/linux/drivers/scsi/scsi.h
is the key internal header file for the SCSI subsystem. As such it will not
be discussed here other than to point out it has the same file name (but
it's in a different directory) as the include file mentioned at the beginning
of this section. This sometimes causes confusion.
The mid level drivers/scsi/scsi_scan.c file
maintains an array of known SCSI devices with idiosyncracies. [This was known as the "black list" but that was considered
to judgmental.] The array is called "device_list". The various value are:
BLIST_NOLUN only probe lun 0
BLIST_FORCELUN force all 8 luns to be probed
BLIST_BORKEN passes through broken flag to lower
level driver
BLIST_KEY sends magical MODE SENSE (pc=0x2e) to
unlock device
BLIST_SINGLELUN only allow IO on one lun at a time
BLIST_NOTQ disable tagged queuing
BLIST_SPARSELUN keep going after lun not found
BLIST_MAX5LUN only probe up to lun 5
BLIST_ISDISK override INQUIRY's type with disk (direct
access) type
BLIST_ISROM override INQUIRY's type with ROM
See the following files:
/usr/src/linux/include/scsi/scsi.h |
Note that the SCSI status constants defined in include/scsi/scsi.h are
shifted 1 bit right from the values in the SCSI standards:
scsi.h constant value SCSI 2 standard value
----------------------------------------------------
CHECK_CONDITION 0x1 0x2
CHECK_GOOD 0x2 0x4
BUSY 0x4 0x8
.... |
Summary of ioctl()s follow:
SCSI_IOCTL_SEND_COMMAND
This interface is deprecated - users should use
the scsi generic (sg) interface instead, as this
is a more flexible approach to performing
generic SCSI commands on a device.
The structure that we are passed should look like:
struct sdata {
unsigned int inlen; [i] Length of data written to device
unsigned int outlen; [i] Length of data read from device
unsigned char cmd[x]; [i] SCSI command (6 <= x <= 12)
[o] Data read from device starts here
[o] On error, sense buffer starts here
unsigned char wdata[y]; [i] Data written to device starts here
};
Notes:
- The SCSI command length is determined by examining
the 1st byte of the given command. There is no way
to override this.
- Data transfers are limited to PAGE_SIZE (4K on
i386, 8K on alpha).
- The length (x + y) must be at least OMAX_SB_LEN
bytes long to accommodate the sense buffer when
an error occurs. The sense buffer is truncated to
OMAX_SB_LEN (16) bytes so that old code will not
be surprised.
- If a Unix error occurs (e.g. ENOMEM) then the user
will receive a negative return and the Unix error
code in 'errno'. If the SCSI command succeeds then
0 is returned. Positive numbers returned are the
compacted SCSI error codes (4 bytes in one int)
where the lowest byte is the SCSI status. See the
drivers/scsi/scsi.h file for more information on this.
SCSI_IOCTL_GET_IDLUN
This ioctl takes a pointer to a "struct scsi_idlun" object
as its third argument. The "struct scsi_idlun" definition
is found in <scsi/scsi.h>. It gets populated with scsi
host, channel, device id and lun data for the given device.
Unfortunately that header file "hides" that structure
behind a "#ifdef __KERNEL__" block. To use this, that
structure needs to be replicated in the user's program.
Something like:
typedef struct my_scsi_idlun {
int four_in_one; /* 4 separate bytes of info
compacted into 1 int */
int host_unique_id; /* distinguishes adapter cards from
same supplier */
} My_scsi_idlun;
"four_in_one" is made up as follows:
(scsi_device_id | (lun << 8) | (channel << 16) |
(host << 24))
These 4 components are assumed (or masked) to be 1 byte each.
SCSI_IOCTL_GET_BUS_NUMBER
In lk 2.2 and earlier this ioctl was needed to get the
host number. During lk 2.3 development the
SCSI_IOCTL_GET_IDLUN ioctl was changed to include this
information. Hence this ioctl is only needed for
backward compatibility.
SCSI_IOCTL_TAGGED_ENABLE
Probably a remnant of the past when the mid level
addressed such issues. Now this functionality is
controlled by the lower level drivers. Best ignored.
SCSI_IOCTL_TAGGED_DISABLE
See comment for SCSI_IOCTL_TAGGED_ENABLE.
SCSI_IOCTL_PROBE_HOST
This ioctl expects its 3rd argument to be a pointer to
a union that looks like this:
union probe_host {
unsigned int length; /* [i] max length of
output ASCII string */
char str[length]; /* [o] N.B. may need '\0'
appended */
};
The host associated with the device's fd either has a
host dependent information string or failing that its
name, output into the given structure. Note that the
output starts at the beginning of given structure
(overwriting the input length). N.B. A trailing '\0'
may need to be put on the output string if it has been
truncated by the input length. A return value of 1
indicates the host is present, 0 indicates that the
host isn't present (how can that happen?) and a
negative value indicates an error.
SCSI_IOCTL_DOORLOCK
SCSI_IOCTL_DOORUNLOCK
SCSI_IOCTL_TEST_UNIT_READY
Returns 0 if the unit (device) is ready, a positive
number if it is not or a negative number when there
is an OS error.
SCSI_IOCTL_START_UNIT
SCSI_IOCTL_STOP_UNIT
SCSI_EMULATED_HOST {same as SG_EMULATED_HOST <new>} |