Mid level

The Linux 2.4 SCSI subsystem HOWTO
Prev | Appendix E. Compile options and System calls including ioctls | Next

# E.1. Mid level

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 idiosyncrasies . [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

## E.1.1. Mid level compile options

None.

## E.1.2. Mid level ioctls

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 <= 16)
                               [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>}

    SCSI_IOCTL_GET_PCI
      Yields the PCI slot name (pci_dev::slot_name) associated with the lower
      level (adapter) driver that controls the current device. Up to 8 characters
      are output to the locations pointed to by 'arg'. If the current device
      is not controlled by a PCI device then errno is set to ENXIO.
      [This ioctl() was introduced in lk 2.4.4]

Prev | Home | Next
Compile options and System calls including ioctls | Up | sd driver