code:
.. SPDX-License-Identifier: GPL-2.0

=============================================
SCSI mid_level - lower_level driver interface
=============================================

Introduction
============
This document outlines the interface between the Linux SCSI mid level and
SCSI lower level drivers. Lower level drivers (LLDs) are variously called
host bus adapter (HBA) drivers and host drivers (HD). A "host" in this
context is a bridge between a computer IO bus (e.g. PCI or ISA) and a
single SCSI initiator port on a SCSI transport. An "initiator" port
(SCSI terminology, see SAM-3 at http://www.t10.org) sends SCSI commands
to "target" SCSI ports (e.g. disks). There can be many LLDs in a running
system, but only one per hardware type. Most LLDs can control one or more
SCSI HBAs. Some HBAs contain multiple hosts.

In some cases the SCSI transport is an external bus that already has
its own subsystem in Linux (e.g. USB and ieee1394). In such cases the
SCSI subsystem LLD is a software bridge to the other driver subsystem.
Examples are the usb-storage driver (found in the drivers/usb/storage
directory) and the ieee1394/sbp2 driver (found in the drivers/ieee1394
directory).

For example, the aic7xxx LLD controls Adaptec SCSI parallel interface
(SPI) controllers based on that company's 7xxx chip series. The aic7xxx
LLD can be built into the kernel or loaded as a module. There can only be
one aic7xxx LLD running in a Linux system but it may be controlling many
HBAs. These HBAs might be either on PCI daughter-boards or built into
the motherboard (or both). Some aic7xxx based HBAs are dual controllers
and thus represent two hosts. Like most modern HBAs, each aic7xxx host
has its own PCI device address. [The one-to-one correspondence between
a SCSI host and a PCI device is common but not required (e.g. with
ISA adapters).]

The SCSI mid level isolates an LLD from other layers such as the SCSI
upper layer drivers and the block layer.

This version of the document roughly matches linux kernel version 2.6.8 .

Documentation
=============
There is a SCSI documentation directory within the kernel source tree,
typically Documentation/scsi . Most documents are in plain
(i.e. ASCII) text. This file is named scsi_mid_low_api.txt and can be
found in that directory. A more recent copy of this document may be found
at http://web.archive.org/web/20070107183357rn_1/sg.torque.net/scsi/.
Many LLDs are documented there (e.g. aic7xxx.txt). The SCSI mid-level is
briefly described in scsi.txt which contains a url to a document
describing the SCSI subsystem in the lk 2.4 series. Two upper level
drivers have documents in that directory: st.txt (SCSI tape driver) and
scsi-generic.txt (for the sg driver).

Some documentation (or urls) for LLDs may be found in the C source code
or in the same directory as the C source code. For example to find a url
about the USB mass storage driver see the
/usr/src/linux/drivers/usb/storage directory.

Driver structure
================
Traditionally an LLD for the SCSI subsystem has been at least two files in
the drivers/scsi directory. For example, a driver called "xyz" has a header
file "xyz.h" and a source file "xyz.c". [Actually there is no good reason
why this couldn't all be in one file; the header file is superfluous.] Some
drivers that have been ported to several operating systems have more than
two files. For example the aic7xxx driver has separate files for generic
and OS-specific code (e.g. FreeBSD and Linux). Such drivers tend to have
their own directory under the drivers/scsi directory.

When a new LLD is being added to Linux, the following files (found in the
drivers/scsi directory) will need some attention: Makefile and Kconfig .
It is probably best to study how existing LLDs are organized.

As the 2.5 series development kernels evolve into the 2.6 series
production series, changes are being introduced into this interface. An
example of this is driver initialization code where there are now 2 models
available. The older one, similar to what was found in the lk 2.4 series,
is based on hosts that are detected at HBA driver load time. This will be
referred to the "passive" initialization model. The newer model allows HBAs
to be hot plugged (and unplugged) during the lifetime of the LLD and will
be referred to as the "hotplug" initialization model. The newer model is
preferred as it can handle both traditional SCSI equipment that is
permanently connected as well as modern "SCSI" devices (e.g. USB or
IEEE 1394 connected digital cameras) that are hotplugged. Both
initialization models are discussed in the following sections.

An LLD interfaces to the SCSI subsystem several ways:

  a) directly invoking functions supplied by the mid level
  b) passing a set of function pointers to a registration function
     supplied by the mid level. The mid level will then invoke these
     functions at some point in the future. The LLD will supply
     implementations of these functions.
  c) direct access to instances of well known data structures maintained
     by the mid level

Those functions in group a) are listed in a section entitled "Mid level
supplied functions" below.

Those functions in group b) are listed in a section entitled "Interface
functions" below. Their function pointers are placed in the members of
"struct scsi_host_template", an instance of which is passed to
scsi_host_alloc() [#]_.  Those interface functions that the LLD does not
wish to supply should have NULL placed in the corresponding member of
struct scsi_host_template.  Defining an instance of struct
scsi_host_template at file scope will cause NULL to be  placed in function
pointer members not explicitly initialized.

Those usages in group c) should be handled with care, especially in a
"hotplug" environment. LLDs should be aware of the lifetime of instances
that are shared with the mid level and other layers.

All functions defined within an LLD and all data defined at file scope
should be static. For example the slave_alloc() function in an LLD
called "xxx" could be defined as
``static int xxx_slave_alloc(struct scsi_device * sdev) { /* code */ }``

.. [#] the scsi_host_alloc() function is a replacement for the rather vaguely
       named scsi_register() function in most situations.

Hotplug initialization model
============================
In this model an LLD controls when SCSI hosts are introduced and removed
from the SCSI subsystem. Hosts can be introduced as early as driver
initialization and removed as late as driver shutdown. Typically a driver
will respond to a sysfs probe() callback that indicates an HBA has been
detected. After confirming that the new device is one that the LLD wants
to control, the LLD will initialize the HBA and then register a new host
with the SCSI mid level.

During LLD initialization the driver should register itself with the
appropriate IO bus on which it expects to find HBA(s) (e.g. the PCI bus).
This can probably be done via sysfs. Any driver parameters (especially
those that are writable after the driver is loaded) could also be
registered with sysfs at this point. The SCSI mid level first becomes
aware of an LLD when that LLD registers its first HBA.

At some later time, the LLD becomes aware of an HBA and what follows
is a typical sequence of calls between the LLD and the mid level.
This example shows the mid level scanning the newly introduced HBA for 3
scsi devices of which only the first 2 respond::

	HBA PROBE: assume 2 SCSI devices found in scan
    LLD                   mid level                    LLD
    ===-------------------=========--------------------===------
    scsi_host_alloc()  -->
    scsi_add_host()  ---->
    scsi_scan_host()  -------+
			    |
			slave_alloc()
			slave_configure() -->  scsi_change_queue_depth()
			    |
			slave_alloc()
			slave_configure()
			    |
			slave_alloc()   ***
			slave_destroy() ***

    *** For scsi devices that the mid level tries to scan but do not
	respond, a slave_alloc(), slave_destroy() pair is called.

If the LLD wants to adjust the default queue settings, it can invoke
scsi_change_queue_depth() in its slave_configure() routine.

When an HBA is being removed it could be as part of an orderly shutdown
associated with the LLD module being unloaded (e.g. with the "rmmod"
command) or in response to a "hot unplug" indicated by sysfs()'s
remove() callback being invoked. In either case, the sequence is the
same::

	    HBA REMOVE: assume 2 SCSI devices attached
    LLD                      mid level                 LLD
    ===----------------------=========-----------------===------
    scsi_remove_host() ---------+
				|
			slave_destroy()
			slave_destroy()
    scsi_host_put()

It may be useful for a LLD to keep track of struct Scsi_Host instances
(a pointer is returned by scsi_host_alloc()). Such instances are "owned"
by the mid-level.  struct Scsi_Host instances are freed from
scsi_host_put() when the reference count hits zero.

Hot unplugging an HBA that controls a disk which is processing SCSI
commands on a mounted file system is an interesting situation. Reference
counting logic is being introduced into the mid level to cope with many
of the issues involved. See the section on reference counting below.

The hotplug concept may be extended to SCSI devices. Currently, when an
HBA is added, the scsi_scan_host() function causes a scan for SCSI devices
attached to the HBA's SCSI transport. On newer SCSI transports the HBA
may become aware of a new SCSI device _after_ the scan has completed.
An LLD can use this sequence to make the mid level aware of a SCSI device::

		    SCSI DEVICE hotplug
    LLD                   mid level                    LLD
    ===-------------------=========--------------------===------
    scsi_add_device()  ------+
			    |
			slave_alloc()
			slave_configure()   [--> scsi_change_queue_depth()]

In a similar fashion, an LLD may become aware that a SCSI device has been
removed (unplugged) or the connection to it has been interrupted. Some
existing SCSI transports (e.g. SPI) may not become aware that a SCSI
device has been removed until a subsequent SCSI command fails which will
probably cause that device to be set offline by the mid level. An LLD that
detects the removal of a SCSI device can instigate its removal from
upper layers with this sequence::

		    SCSI DEVICE hot unplug
    LLD                      mid level                 LLD
    ===----------------------=========-----------------===------
    scsi_remove_device() -------+
				|
			slave_destroy()

It may be useful for an LLD to keep track of struct scsi_device instances
(a pointer is passed as the parameter to slave_alloc() and
slave_configure() callbacks). Such instances are "owned" by the mid-level.
struct scsi_device instances are freed after slave_destroy().

Reference Counting
==================
The Scsi_Host structure has had reference counting infrastructure added.
This effectively spreads the ownership of struct Scsi_Host instances
across the various SCSI layers which use them. Previously such instances
were exclusively owned by the mid level. LLDs would not usually need to
directly manipulate these reference counts but there may be some cases
where they do.

There are 3 reference counting functions of interest associated with
struct Scsi_Host:

  - scsi_host_alloc():
	returns a pointer to new instance of struct
        Scsi_Host which has its reference count ^^ set to 1

  - scsi_host_get():
	adds 1 to the reference count of the given instance

  - scsi_host_put():
	decrements 1 from the reference count of the given
        instance. If the reference count reaches 0 then the given instance
        is freed

The scsi_device structure has had reference counting infrastructure added.
This effectively spreads the ownership of struct scsi_device instances
across the various SCSI layers which use them. Previously such instances
were exclusively owned by the mid level. See the access functions declared
towards the end of include/scsi/scsi_device.h . If an LLD wants to keep
a copy of a pointer to a scsi_device instance it should use scsi_device_get()
to bump its reference count. When it is finished with the pointer it can
use scsi_device_put() to decrement its reference count (and potentially
delete it).

.. Note::

   struct Scsi_Host actually has 2 reference counts which are manipulated
   in parallel by these functions.

Conventions
===========
First, Linus Torvalds's thoughts on C coding style can be found in the
Documentation/process/coding-style.rst file.

Also, most C99 enhancements are encouraged to the extent they are supported
by the relevant gcc compilers. So C99 style structure and array
initializers are encouraged where appropriate. Don't go too far,
VLAs are not properly supported yet.  An exception to this is the use of
``//`` style comments; ``/*...*/`` comments are still preferred in Linux.

Well written, tested and documented code, need not be re-formatted to
comply with the above conventions. For example, the aic7xxx driver
comes to Linux from FreeBSD and Adaptec's own labs. No doubt FreeBSD
and Adaptec have their own coding conventions.

Mid level supplied functions
============================
These functions are supplied by the SCSI mid level for use by LLDs.
The names (i.e. entry points) of these functions are exported
so an LLD that is a module can access them. The kernel will
arrange for the SCSI mid level to be loaded and initialized before any LLD
is initialized. The functions below are listed alphabetically and their
names all start with ``scsi_``.

Summary:

  - scsi_add_device - creates new scsi device (lu) instance
  - scsi_add_host - perform sysfs registration and set up transport class
  - scsi_change_queue_depth - change the queue depth on a SCSI device
  - scsi_bios_ptable - return copy of block device's partition table
  - scsi_block_requests - prevent further commands being queued to given host
  - scsi_host_alloc - return a new scsi_host instance whose refcount==1
  - scsi_host_get - increments Scsi_Host instance's refcount
  - scsi_host_put - decrements Scsi_Host instance's refcount (free if 0)
  - scsi_register - create and register a scsi host adapter instance.
  - scsi_remove_device - detach and remove a SCSI device
  - scsi_remove_host - detach and remove all SCSI devices owned by host
  - scsi_report_bus_reset - report scsi _bus_ reset observed
  - scsi_scan_host - scan SCSI bus
  - scsi_track_queue_full - track successive QUEUE_FULL events
  - scsi_unblock_requests - allow further commands to be queued to given host
  - scsi_unregister - [calls scsi_host_put()]

Details::

    /**
    * scsi_add_device - creates new scsi device (lu) instance
    * @shost:   pointer to scsi host instance
    * @channel: channel number (rarely other than 0)
    * @id:      target id number
    * @lun:     logical unit number
    *
    *      Returns pointer to new struct scsi_device instance or
    *      ERR_PTR(-ENODEV) (or some other bent pointer) if something is
    *      wrong (e.g. no lu responds at given address)
    *
    *      Might block: yes
    *
    *      Notes: This call is usually performed internally during a scsi
    *      bus scan when an HBA is added (i.e. scsi_scan_host()). So it
    *      should only be called if the HBA becomes aware of a new scsi
    *      device (lu) after scsi_scan_host() has completed. If successful
    *      this call can lead to slave_alloc() and slave_configure() callbacks
    *      into the LLD.
    *
    *      Defined in: drivers/scsi/scsi_scan.c
    **/
    struct scsi_device * scsi_add_device(struct Scsi_Host *shost,
					unsigned int channel,
					unsigned int id, unsigned int lun)

    /**
    * scsi_add_host - perform sysfs registration and set up transport class
    * @shost:   pointer to scsi host instance
    * @dev:     pointer to struct device of type scsi class
    *
    *      Returns 0 on success, negative errno of failure (e.g. -ENOMEM)
    *
    *      Might block: no
    *
    *      Notes: Only required in "hotplug initialization model" after a
    *      successful call to scsi_host_alloc().  This function does not
    *	scan the bus; this can be done by calling scsi_scan_host() or
    *	in some other transport-specific way.  The LLD must set up
    *	the transport template before calling this function and may only
    *	access the transport class data after this function has been called.
    *
    *      Defined in: drivers/scsi/hosts.c
    **/
    int scsi_add_host(struct Scsi_Host *shost, struct device * dev)

    /**
    * scsi_change_queue_depth - allow LLD to change queue depth on a SCSI device
    * @sdev:       pointer to SCSI device to change queue depth on
    * @tags        Number of tags allowed if tagged queuing enabled,
    *              or number of commands the LLD can queue up
    *              in non-tagged mode (as per cmd_per_lun).
    *
    *      Returns nothing
    *
    *      Might block: no
    *
    *      Notes: Can be invoked any time on a SCSI device controlled by this
    *      LLD. [Specifically during and after slave_configure() and prior to
    *      slave_destroy().] Can safely be invoked from interrupt code.
    *
    *      Defined in: drivers/scsi/scsi.c [see source code for more notes]
    *
    **/
    int scsi_change_queue_depth(struct scsi_device *sdev, int tags)

    /**
    * scsi_bios_ptable - return copy of block device's partition table
    * @dev:        pointer to block device
    *
    *      Returns pointer to partition table, or NULL for failure
    *
    *      Might block: yes
    *
    *      Notes: Caller owns memory returned (free with kfree() )
    *
    *      Defined in: drivers/scsi/scsicam.c
    **/
    unsigned char *scsi_bios_ptable(struct block_device *dev)

    /**
    * scsi_block_requests - prevent further commands being queued to given host
    *
    * @shost: pointer to host to block commands on
    *
    *      Returns nothing
    *
    *      Might block: no
    *
    *      Notes: There is no timer nor any other means by which the requests
    *      get unblocked other than the LLD calling scsi_unblock_requests().
    *
    *      Defined in: drivers/scsi/scsi_lib.c
    **/
    void scsi_block_requests(struct Scsi_Host * shost)

    /**
    * scsi_host_alloc - create a scsi host adapter instance and perform basic
    *                   initialization.
    * @sht:        pointer to scsi host template
    * @privsize:   extra bytes to allocate in hostdata array (which is the
    *              last member of the returned Scsi_Host instance)
    *
    *      Returns pointer to new Scsi_Host instance or NULL on failure
    *
    *      Might block: yes
    *
    *      Notes: When this call returns to the LLD, the SCSI bus scan on
    *      this host has _not_ yet been done.
    *      The hostdata array (by default zero length) is a per host scratch
    *      area for the LLD's exclusive use.
    *      Both associated refcounting objects have their refcount set to 1.
    *      Full registration (in sysfs) and a bus scan are performed later when
    *      scsi_add_host() and scsi_scan_host() are called.
    *
    *      Defined in: drivers/scsi/hosts.c .
    **/
    struct Scsi_Host * scsi_host_alloc(struct scsi_host_template * sht,
				    int privsize)

    /**
    * scsi_host_get - increment Scsi_Host instance refcount
    * @shost:   pointer to struct Scsi_Host instance
    *
    *      Returns nothing
    *
    *      Might block: currently may block but may be changed to not block
    *
    *      Notes: Actually increments the counts in two sub-objects
    *
    *      Defined in: drivers/scsi/hosts.c
    **/
    void scsi_host_get(struct Scsi_Host *shost)

    /**
    * scsi_host_put - decrement Scsi_Host instance refcount, free if 0
    * @shost:   pointer to struct Scsi_Host instance
    *
    *      Returns nothing
    *
    *      Might block: currently may block but may be changed to not block
    *
    *      Notes: Actually decrements the counts in two sub-objects. If the
    *      latter refcount reaches 0, the Scsi_Host instance is freed.
    *      The LLD need not worry exactly when the Scsi_Host instance is
    *      freed, it just shouldn't access the instance after it has balanced
    *      out its refcount usage.
    *
    *      Defined in: drivers/scsi/hosts.c
    **/
    void scsi_host_put(struct Scsi_Host *shost)

    /**
    * scsi_register - create and register a scsi host adapter instance.
    * @sht:        pointer to scsi host template
    * @privsize:   extra bytes to allocate in hostdata array (which is the
    *              last member of the returned Scsi_Host instance)
    *
    *      Returns pointer to new Scsi_Host instance or NULL on failure
    *
    *      Might block: yes
    *
    *      Notes: When this call returns to the LLD, the SCSI bus scan on
    *      this host has _not_ yet been done.
    *      The hostdata array (by default zero length) is a per host scratch
    *      area for the LLD.
    *
    *      Defined in: drivers/scsi/hosts.c .
    **/
    struct Scsi_Host * scsi_register(struct scsi_host_template * sht,
				    int privsize)

    /**
    * scsi_remove_device - detach and remove a SCSI device
    * @sdev:      a pointer to a scsi device instance
    *
    *      Returns value: 0 on success, -EINVAL if device not attached
    *
    *      Might block: yes
    *
    *      Notes: If an LLD becomes aware that a scsi device (lu) has
    *      been removed but its host is still present then it can request
    *      the removal of that scsi device. If successful this call will
    *      lead to the slave_destroy() callback being invoked. sdev is an
    *      invalid pointer after this call.
    *
    *      Defined in: drivers/scsi/scsi_sysfs.c .
    **/
    int scsi_remove_device(struct scsi_device *sdev)

    /**
    * scsi_remove_host - detach and remove all SCSI devices owned by host
    * @shost:      a pointer to a scsi host instance
    *
    *      Returns value: 0 on success, 1 on failure (e.g. LLD busy ??)
    *
    *      Might block: yes
    *
    *      Notes: Should only be invoked if the "hotplug initialization
    *      model" is being used. It should be called _prior_ to
    *      scsi_unregister().
    *
    *      Defined in: drivers/scsi/hosts.c .
    **/
    int scsi_remove_host(struct Scsi_Host *shost)

    /**
    * scsi_report_bus_reset - report scsi _bus_ reset observed
    * @shost: a pointer to a scsi host involved
    * @channel: channel (within) host on which scsi bus reset occurred
    *
    *      Returns nothing
    *
    *      Might block: no
    *
    *      Notes: This only needs to be called if the reset is one which
    *      originates from an unknown location.  Resets originated by the
    *      mid level itself don't need to call this, but there should be
    *      no harm.  The main purpose of this is to make sure that a
    *      CHECK_CONDITION is properly treated.
    *
    *      Defined in: drivers/scsi/scsi_error.c .
    **/
    void scsi_report_bus_reset(struct Scsi_Host * shost, int channel)

    /**
    * scsi_scan_host - scan SCSI bus
    * @shost: a pointer to a scsi host instance
    *
    *	Might block: yes
    *
    *	Notes: Should be called after scsi_add_host()
    *
    *	Defined in: drivers/scsi/scsi_scan.c
    **/
    void scsi_scan_host(struct Scsi_Host *shost)

    /**
    * scsi_track_queue_full - track successive QUEUE_FULL events on given
    *                      device to determine if and when there is a need
    *                      to adjust the queue depth on the device.
    * @sdev:  pointer to SCSI device instance
    * @depth: Current number of outstanding SCSI commands on this device,
    *         not counting the one returned as QUEUE_FULL.
    *
    *      Returns 0  - no change needed
    *              >0 - adjust queue depth to this new depth
    *              -1 - drop back to untagged operation using host->cmd_per_lun
    *                   as the untagged command depth
    *
    *      Might block: no
    *
    *      Notes: LLDs may call this at any time and we will do "The Right
    *              Thing"; interrupt context safe.
    *
    *      Defined in: drivers/scsi/scsi.c .
    **/
    int scsi_track_queue_full(struct scsi_device *sdev, int depth)

    /**
    * scsi_unblock_requests - allow further commands to be queued to given host
    *
    * @shost: pointer to host to unblock commands on
    *
    *      Returns nothing
    *
    *      Might block: no
    *
    *      Defined in: drivers/scsi/scsi_lib.c .
    **/
    void scsi_unblock_requests(struct Scsi_Host * shost)

    /**
    * scsi_unregister - unregister and free memory used by host instance
    * @shp:        pointer to scsi host instance to unregister.
    *
    *      Returns nothing
    *
    *      Might block: no
    *
    *      Notes: Should not be invoked if the "hotplug initialization
    *      model" is being used. Called internally by exit_this_scsi_driver()
    *      in the "passive initialization model". Hence a LLD has no need to
    *      call this function directly.
    *
    *      Defined in: drivers/scsi/hosts.c .
    **/
    void scsi_unregister(struct Scsi_Host * shp)

Interface Functions
===================
Interface functions are supplied (defined) by LLDs and their function
pointers are placed in an instance of struct scsi_host_template which
is passed to scsi_host_alloc() [or scsi_register() / init_this_scsi_driver()].
Some are mandatory. Interface functions should be declared static. The
accepted convention is that driver "xyz" will declare its slave_configure()
function as::

    static int xyz_slave_configure(struct scsi_device * sdev);

and so forth for all interface functions listed below.

A pointer to this function should be placed in the 'slave_configure' member
of a "struct scsi_host_template" instance. A pointer to such an instance
should be passed to the mid level's scsi_host_alloc() [or scsi_register() /
init_this_scsi_driver()].

The interface functions are also described in the include/scsi/scsi_host.h
file immediately above their definition point in "struct scsi_host_template".
In some cases more detail is given in scsi_host.h than below.

The interface functions are listed below in alphabetical order.

Summary:

  - bios_param - fetch head, sector, cylinder info for a disk
  - eh_timed_out - notify the host that a command timer expired
  - eh_abort_handler - abort given command
  - eh_bus_reset_handler - issue SCSI bus reset
  - eh_device_reset_handler - issue SCSI device reset
  - eh_host_reset_handler - reset host (host bus adapter)
  - info - supply information about given host
  - ioctl - driver can respond to ioctls
  - proc_info - supports /proc/scsi/{driver_name}/{host_no}
  - queuecommand - queue scsi command, invoke 'done' on completion
  - slave_alloc - prior to any commands being sent to a new device
  - slave_configure - driver fine tuning for given device after attach
  - slave_destroy - given device is about to be shut down

Details::

    /**
    *      bios_param - fetch head, sector, cylinder info for a disk
    *      @sdev: pointer to scsi device context (defined in
    *             include/scsi/scsi_device.h)
    *      @bdev: pointer to block device context (defined in fs.h)
    *      @capacity:  device size (in 512 byte sectors)
    *      @params: three element array to place output:
    *              params[0] number of heads (max 255)
    *              params[1] number of sectors (max 63)
    *              params[2] number of cylinders
    *
    *      Return value is ignored
    *
    *      Locks: none
    *
    *      Calling context: process (sd)
    *
    *      Notes: an arbitrary geometry (based on READ CAPACITY) is used
    *      if this function is not provided. The params array is
    *      pre-initialized with made up values just in case this function
    *      doesn't output anything.
    *
    *      Optionally defined in: LLD
    **/
	int bios_param(struct scsi_device * sdev, struct block_device *bdev,
		    sector_t capacity, int params[3])

    /**
    *      eh_timed_out - The timer for the command has just fired
    *      @scp: identifies command timing out
    *
    *      Returns:
    *
    *      EH_HANDLED:             I fixed the error, please complete the command
    *      EH_RESET_TIMER:         I need more time, reset the timer and
    *                              begin counting again
    *      EH_NOT_HANDLED          Begin normal error recovery
    *
    *
    *      Locks: None held
    *
    *      Calling context: interrupt
    *
    *      Notes: This is to give the LLD an opportunity to do local recovery.
    *      This recovery is limited to determining if the outstanding command
    *      will ever complete.  You may not abort and restart the command from
    *      this callback.
    *
    *      Optionally defined in: LLD
    **/
	int eh_timed_out(struct scsi_cmnd * scp)

    /**
    *      eh_abort_handler - abort command associated with scp
    *      @scp: identifies command to be aborted
    *
    *      Returns SUCCESS if command aborted else FAILED
    *
    *      Locks: None held
    *
    *      Calling context: kernel thread
    *
    *      Notes: If 'no_async_abort' is defined this callback
    *  	will be invoked from scsi_eh thread. No other commands
    *	will then be queued on current host during eh.
    *	Otherwise it will be called whenever scsi_timeout()
    *      is called due to a command timeout.
    *
    *      Optionally defined in: LLD
    **/
	int eh_abort_handler(struct scsi_cmnd * scp)

    /**
    *      eh_bus_reset_handler - issue SCSI bus reset
    *      @scp: SCSI bus that contains this device should be reset
    *
    *      Returns SUCCESS if command aborted else FAILED
    *
    *      Locks: None held
    *
    *      Calling context: kernel thread
    *
    *      Notes: Invoked from scsi_eh thread. No other commands will be
    *      queued on current host during eh.
    *
    *      Optionally defined in: LLD
    **/
	int eh_bus_reset_handler(struct scsi_cmnd * scp)

    /**
    *      eh_device_reset_handler - issue SCSI device reset
    *      @scp: identifies SCSI device to be reset
    *
    *      Returns SUCCESS if command aborted else FAILED
    *
    *      Locks: None held
    *
    *      Calling context: kernel thread
    *
    *      Notes: Invoked from scsi_eh thread. No other commands will be
    *      queued on current host during eh.
    *
    *      Optionally defined in: LLD
    **/
	int eh_device_reset_handler(struct scsi_cmnd * scp)

    /**
    *      eh_host_reset_handler - reset host (host bus adapter)
    *      @scp: SCSI host that contains this device should be reset
    *
    *      Returns SUCCESS if command aborted else FAILED
    *
    *      Locks: None held
    *
    *      Calling context: kernel thread
    *
    *      Notes: Invoked from scsi_eh thread. No other commands will be
    *      queued on current host during eh.
    *      With the default eh_strategy in place, if none of the _abort_,
    *      _device_reset_, _bus_reset_ or this eh handler function are
    *      defined (or they all return FAILED) then the device in question
    *      will be set offline whenever eh is invoked.
    *
    *      Optionally defined in: LLD
    **/
	int eh_host_reset_handler(struct scsi_cmnd * scp)

    /**
    *      info - supply information about given host: driver name plus data
    *             to distinguish given host
    *      @shp: host to supply information about
    *
    *      Return ASCII null terminated string. [This driver is assumed to
    *      manage the memory pointed to and maintain it, typically for the
    *      lifetime of this host.]
    *
    *      Locks: none
    *
    *      Calling context: process
    *
    *      Notes: Often supplies PCI or ISA information such as IO addresses
    *      and interrupt numbers. If not supplied struct Scsi_Host::name used
    *      instead. It is assumed the returned information fits on one line
    *      (i.e. does not included embedded newlines).
    *      The SCSI_IOCTL_PROBE_HOST ioctl yields the string returned by this
    *      function (or struct Scsi_Host::name if this function is not
    *      available).
    *      In a similar manner, init_this_scsi_driver() outputs to the console
    *      each host's "info" (or name) for the driver it is registering.
    *      Also if proc_info() is not supplied, the output of this function
    *      is used instead.
    *
    *      Optionally defined in: LLD
    **/
	const char * info(struct Scsi_Host * shp)

    /**
    *      ioctl - driver can respond to ioctls
    *      @sdp: device that ioctl was issued for
    *      @cmd: ioctl number
    *      @arg: pointer to read or write data from. Since it points to
    *            user space, should use appropriate kernel functions
    *            (e.g. copy_from_user() ). In the Unix style this argument
    *            can also be viewed as an unsigned long.
    *
    *      Returns negative "errno" value when there is a problem. 0 or a
    *      positive value indicates success and is returned to the user space.
    *
    *      Locks: none
    *
    *      Calling context: process
    *
    *      Notes: The SCSI subsystem uses a "trickle down" ioctl model.
    *      The user issues an ioctl() against an upper level driver
    *      (e.g. /dev/sdc) and if the upper level driver doesn't recognize
    *      the 'cmd' then it is passed to the SCSI mid level. If the SCSI
    *      mid level does not recognize it, then the LLD that controls
    *      the device receives the ioctl. According to recent Unix standards
    *      unsupported ioctl() 'cmd' numbers should return -ENOTTY.
    *
    *      Optionally defined in: LLD
    **/
	int ioctl(struct scsi_device *sdp, int cmd, void *arg)

    /**
    *      proc_info - supports /proc/scsi/{driver_name}/{host_no}
    *      @buffer: anchor point to output to (0==writeto1_read0) or fetch from
    *               (1==writeto1_read0).
    *      @start: where "interesting" data is written to. Ignored when
    *              1==writeto1_read0.
    *      @offset: offset within buffer 0==writeto1_read0 is actually
    *               interested in. Ignored when 1==writeto1_read0 .
    *      @length: maximum (or actual) extent of buffer
    *      @host_no: host number of interest (struct Scsi_Host::host_no)
    *      @writeto1_read0: 1 -> data coming from user space towards driver
    *                            (e.g. "echo some_string > /proc/scsi/xyz/2")
    *                       0 -> user what data from this driver
    *                            (e.g. "cat /proc/scsi/xyz/2")
    *
    *      Returns length when 1==writeto1_read0. Otherwise number of chars
    *      output to buffer past offset.
    *
    *      Locks: none held
    *
    *      Calling context: process
    *
    *      Notes: Driven from scsi_proc.c which interfaces to proc_fs. proc_fs
    *      support can now be configured out of the scsi subsystem.
    *
    *      Optionally defined in: LLD
    **/
	int proc_info(char * buffer, char ** start, off_t offset,
		    int length, int host_no, int writeto1_read0)

    /**
    *      queuecommand - queue scsi command, invoke scp->scsi_done on completion
    *      @shost: pointer to the scsi host object
    *      @scp: pointer to scsi command object
    *
    *      Returns 0 on success.
    *
    *      If there's a failure, return either:
    *
    *      SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or
    *      SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full
    *
    *      On both of these returns, the mid-layer will requeue the I/O
    *
    *      - if the return is SCSI_MLQUEUE_DEVICE_BUSY, only that particular
    *      device will be paused, and it will be unpaused when a command to
    *      the device returns (or after a brief delay if there are no more
    *      outstanding commands to it).  Commands to other devices continue
    *      to be processed normally.
    *
    *      - if the return is SCSI_MLQUEUE_HOST_BUSY, all I/O to the host
    *      is paused and will be unpaused when any command returns from
    *      the host (or after a brief delay if there are no outstanding
    *      commands to the host).
    *
    *      For compatibility with earlier versions of queuecommand, any
    *      other return value is treated the same as
    *      SCSI_MLQUEUE_HOST_BUSY.
    *
    *      Other types of errors that are detected immediately may be
    *      flagged by setting scp->result to an appropriate value,
    *      invoking the scp->scsi_done callback, and then returning 0
    *      from this function. If the command is not performed
    *      immediately (and the LLD is starting (or will start) the given
    *      command) then this function should place 0 in scp->result and
    *      return 0.
    *
    *      Command ownership.  If the driver returns zero, it owns the
    *      command and must take responsibility for ensuring the
    *      scp->scsi_done callback is executed.  Note: the driver may
    *      call scp->scsi_done before returning zero, but after it has
    *      called scp->scsi_done, it may not return any value other than
    *      zero.  If the driver makes a non-zero return, it must not
    *      execute the command's scsi_done callback at any time.
    *
    *      Locks: up to and including 2.6.36, struct Scsi_Host::host_lock
    *             held on entry (with "irqsave") and is expected to be
    *             held on return. From 2.6.37 onwards, queuecommand is
    *             called without any locks held.
    *
    *      Calling context: in interrupt (soft irq) or process context
    *
    *      Notes: This function should be relatively fast. Normally it
    *      will not wait for IO to complete. Hence the scp->scsi_done
    *      callback is invoked (often directly from an interrupt service
    *      routine) some time after this function has returned. In some
    *      cases (e.g. pseudo adapter drivers that manufacture the
    *      response to a SCSI INQUIRY) the scp->scsi_done callback may be
    *      invoked before this function returns.  If the scp->scsi_done
    *      callback is not invoked within a certain period the SCSI mid
    *      level will commence error processing.  If a status of CHECK
    *      CONDITION is placed in "result" when the scp->scsi_done
    *      callback is invoked, then the LLD driver should perform
    *      autosense and fill in the struct scsi_cmnd::sense_buffer
    *      array. The scsi_cmnd::sense_buffer array is zeroed prior to
    *      the mid level queuing a command to an LLD.
    *
    *      Defined in: LLD
    **/
	int queuecommand(struct Scsi_Host *shost, struct scsi_cmnd * scp)

    /**
    *      slave_alloc -   prior to any commands being sent to a new device
    *                      (i.e. just prior to scan) this call is made
    *      @sdp: pointer to new device (about to be scanned)
    *
    *      Returns 0 if ok. Any other return is assumed to be an error and
    *      the device is ignored.
    *
    *      Locks: none
    *
    *      Calling context: process
    *
    *      Notes: Allows the driver to allocate any resources for a device
    *      prior to its initial scan. The corresponding scsi device may not
    *      exist but the mid level is just about to scan for it (i.e. send
    *      and INQUIRY command plus ...). If a device is found then
    *      slave_configure() will be called while if a device is not found
    *      slave_destroy() is called.
    *      For more details see the include/scsi/scsi_host.h file.
    *
    *      Optionally defined in: LLD
    **/
	int slave_alloc(struct scsi_device *sdp)

    /**
    *      slave_configure - driver fine tuning for given device just after it
    *                     has been first scanned (i.e. it responded to an
    *                     INQUIRY)
    *      @sdp: device that has just been attached
    *
    *      Returns 0 if ok. Any other return is assumed to be an error and
    *      the device is taken offline. [offline devices will _not_ have
    *      slave_destroy() called on them so clean up resources.]
    *
    *      Locks: none
    *
    *      Calling context: process
    *
    *      Notes: Allows the driver to inspect the response to the initial
    *      INQUIRY done by the scanning code and take appropriate action.
    *      For more details see the include/scsi/scsi_host.h file.
    *
    *      Optionally defined in: LLD
    **/
	int slave_configure(struct scsi_device *sdp)

    /**
    *      slave_destroy - given device is about to be shut down. All
    *                      activity has ceased on this device.
    *      @sdp: device that is about to be shut down
    *
    *      Returns nothing
    *
    *      Locks: none
    *
    *      Calling context: process
    *
    *      Notes: Mid level structures for given device are still in place
    *      but are about to be torn down. Any per device resources allocated
    *      by this driver for given device should be freed now. No further
    *      commands will be sent for this sdp instance. [However the device
    *      could be re-attached in the future in which case a new instance
    *      of struct scsi_device would be supplied by future slave_alloc()
    *      and slave_configure() calls.]
    *
    *      Optionally defined in: LLD
    **/
	void slave_destroy(struct scsi_device *sdp)

Data Structures
===============
struct scsi_host_template
-------------------------
There is one "struct scsi_host_template" instance per LLD [#]_. It is
typically initialized as a file scope static in a driver's header file. That
way members that are not explicitly initialized will be set to 0 or NULL.
Member of interest:

    name
		 - name of driver (may contain spaces, please limit to
                   less than 80 characters)

    proc_name
		 - name used in "/proc/scsi/<proc_name>/<host_no>" and
                   by sysfs in one of its "drivers" directories. Hence
                   "proc_name" should only contain characters acceptable
                   to a Unix file name.

   ``(*queuecommand)()``
		 - primary callback that the mid level uses to inject
                   SCSI commands into an LLD.

The structure is defined and commented in include/scsi/scsi_host.h

.. [#] In extreme situations a single driver may have several instances
       if it controls several different classes of hardware (e.g. an LLD
       that handles both ISA and PCI cards and has a separate instance of
       struct scsi_host_template for each class).

struct Scsi_Host
----------------
There is one struct Scsi_Host instance per host (HBA) that an LLD
controls. The struct Scsi_Host structure has many members in common
with "struct scsi_host_template". When a new struct Scsi_Host instance
is created (in scsi_host_alloc() in hosts.c) those common members are
initialized from the driver's struct scsi_host_template instance. Members
of interest:

    host_no
		 - system wide unique number that is used for identifying
                   this host. Issued in ascending order from 0.
    can_queue
		 - must be greater than 0; do not send more than can_queue
                   commands to the adapter.
    this_id
		 - scsi id of host (scsi initiator) or -1 if not known
    sg_tablesize
		 - maximum scatter gather elements allowed by host.
                   Set this to SG_ALL or less to avoid chained SG lists.
                   Must be at least 1.
    max_sectors
		 - maximum number of sectors (usually 512 bytes) allowed
                   in a single SCSI command. The default value of 0 leads
                   to a setting of SCSI_DEFAULT_MAX_SECTORS (defined in
                   scsi_host.h) which is currently set to 1024. So for a
                   disk the maximum transfer size is 512 KB when max_sectors
                   is not defined. Note that this size may not be sufficient
                   for disk firmware uploads.
    cmd_per_lun
		 - maximum number of commands that can be queued on devices
                   controlled by the host. Overridden by LLD calls to
                   scsi_change_queue_depth().
    no_async_abort
		 - 1=>Asynchronous aborts are not supported
		 - 0=>Timed-out commands will be aborted asynchronously
    hostt
		 - pointer to driver's struct scsi_host_template from which
                   this struct Scsi_Host instance was spawned
    hostt->proc_name
		 - name of LLD. This is the driver name that sysfs uses
    transportt
		 - pointer to driver's struct scsi_transport_template instance
                   (if any). FC and SPI transports currently supported.
    sh_list
		 - a double linked list of pointers to all struct Scsi_Host
                   instances (currently ordered by ascending host_no)
    my_devices
		 - a double linked list of pointers to struct scsi_device
                   instances that belong to this host.
    hostdata[0]
		 - area reserved for LLD at end of struct Scsi_Host. Size
                   is set by the second argument (named 'xtr_bytes') to
                   scsi_host_alloc() or scsi_register().
    vendor_id
		 - a unique value that identifies the vendor supplying
                   the LLD for the Scsi_Host.  Used most often in validating
                   vendor-specific message requests.  Value consists of an
                   identifier type and a vendor-specific value.
                   See scsi_netlink.h for a description of valid formats.

The scsi_host structure is defined in include/scsi/scsi_host.h

struct scsi_device
------------------
Generally, there is one instance of this structure for each SCSI logical unit
on a host. Scsi devices connected to a host are uniquely identified by a
channel number, target id and logical unit number (lun).
The structure is defined in include/scsi/scsi_device.h

struct scsi_cmnd
----------------
Instances of this structure convey SCSI commands to the LLD and responses
back to the mid level. The SCSI mid level will ensure that no more SCSI
commands become queued against the LLD than are indicated by
scsi_change_queue_depth() (or struct Scsi_Host::cmd_per_lun). There will
be at least one instance of struct scsi_cmnd available for each SCSI device.
Members of interest:

    cmnd
		 - array containing SCSI command
    cmnd_len
		 - length (in bytes) of SCSI command
    sc_data_direction
		 - direction of data transfer in data phase. See
                   "enum dma_data_direction" in include/linux/dma-mapping.h
    request_bufflen
		 - number of data bytes to transfer (0 if no data phase)
    use_sg
		 - ==0 -> no scatter gather list, hence transfer data
                          to/from request_buffer
                 - >0 ->  scatter gather list (actually an array) in
                          request_buffer with use_sg elements
    request_buffer
		   - either contains data buffer or scatter gather list
                     depending on the setting of use_sg. Scatter gather
                     elements are defined by 'struct scatterlist' found
                     in include/linux/scatterlist.h .
    done
		 - function pointer that should be invoked by LLD when the
                   SCSI command is completed (successfully or otherwise).
                   Should only be called by an LLD if the LLD has accepted
                   the command (i.e. queuecommand() returned or will return
                   0). The LLD may invoke 'done'  prior to queuecommand()
                   finishing.
    result
		 - should be set by LLD prior to calling 'done'. A value
                   of 0 implies a successfully completed command (and all
                   data (if any) has been transferred to or from the SCSI
                   target device). 'result' is a 32 bit unsigned integer that
                   can be viewed as 2 related bytes. The SCSI status value is
                   in the LSB. See include/scsi/scsi.h status_byte() and
                   host_byte() macros and related constants.
    sense_buffer
		 - an array (maximum size: SCSI_SENSE_BUFFERSIZE bytes) that
                   should be written when the SCSI status (LSB of 'result')
                   is set to CHECK_CONDITION (2). When CHECK_CONDITION is
                   set, if the top nibble of sense_buffer[0] has the value 7
                   then the mid level will assume the sense_buffer array
                   contains a valid SCSI sense buffer; otherwise the mid
                   level will issue a REQUEST_SENSE SCSI command to
                   retrieve the sense buffer. The latter strategy is error
                   prone in the presence of command queuing so the LLD should
                   always "auto-sense".
    device
		 - pointer to scsi_device object that this command is
                   associated with.
    resid
		 - an LLD should set this signed integer to the requested
                   transfer length (i.e. 'request_bufflen') less the number
                   of bytes that are actually transferred. 'resid' is
                   preset to 0 so an LLD can ignore it if it cannot detect
                   underruns (overruns should be rare). If possible an LLD
                   should set 'resid' prior to invoking 'done'. The most
                   interesting case is data transfers from a SCSI target
                   device (e.g. READs) that underrun.
    underflow
		 - LLD should place (DID_ERROR << 16) in 'result' if
                   actual number of bytes transferred is less than this
                   figure. Not many LLDs implement this check and some that
                   do just output an error message to the log rather than
                   report a DID_ERROR. Better for an LLD to implement
                   'resid'.

It is recommended that a LLD set 'resid' on data transfers from a SCSI
target device (e.g. READs). It is especially important that 'resid' is set
when such data transfers have sense keys of MEDIUM ERROR and HARDWARE ERROR
(and possibly RECOVERED ERROR). In these cases if a LLD is in doubt how much
data has been received then the safest approach is to indicate no bytes have
been received. For example: to indicate that no valid data has been received
a LLD might use these helpers::

    scsi_set_resid(SCpnt, scsi_bufflen(SCpnt));

where 'SCpnt' is a pointer to a scsi_cmnd object. To indicate only three 512
bytes blocks has been received 'resid' could be set like this::

    scsi_set_resid(SCpnt, scsi_bufflen(SCpnt) - (3 * 512));

The scsi_cmnd structure is defined in include/scsi/scsi_cmnd.h

Locks
=====
Each struct Scsi_Host instance has a spin_lock called struct
Scsi_Host::default_lock which is initialized in scsi_host_alloc() [found in
hosts.c]. Within the same function the struct Scsi_Host::host_lock pointer
is initialized to point at default_lock.  Thereafter lock and unlock
operations performed by the mid level use the struct Scsi_Host::host_lock
pointer.  Previously drivers could override the host_lock pointer but
this is not allowed anymore.

Autosense
=========
Autosense (or auto-sense) is defined in the SAM-2 document as "the
automatic return of sense data to the application client coincident
with the completion of a SCSI command" when a status of CHECK CONDITION
occurs. LLDs should perform autosense. This should be done when the LLD
detects a CHECK CONDITION status by either:

    a) instructing the SCSI protocol (e.g. SCSI Parallel Interface (SPI))
       to perform an extra data in phase on such responses
    b) or, the LLD issuing a REQUEST SENSE command itself

Either way, when a status of CHECK CONDITION is detected, the mid level
decides whether the LLD has performed autosense by checking struct
scsi_cmnd::sense_buffer[0] . If this byte has an upper nibble of 7 (or 0xf)
then autosense is assumed to have taken place. If it has another value (and
this byte is initialized to 0 before each command) then the mid level will
issue a REQUEST SENSE command.

In the presence of queued commands the "nexus" that maintains sense
buffer data from the command that failed until a following REQUEST SENSE
may get out of synchronization. This is why it is best for the LLD
to perform autosense.

Changes since lk 2.4 series
===========================
io_request_lock has been replaced by several finer grained locks. The lock
relevant to LLDs is struct Scsi_Host::host_lock and there is
one per SCSI host.

The older error handling mechanism has been removed. This means the
LLD interface functions abort() and reset() have been removed.
The struct scsi_host_template::use_new_eh_code flag has been removed.

In the 2.4 series the SCSI subsystem configuration descriptions were
aggregated with the configuration descriptions from all other Linux
subsystems in the Documentation/Configure.help file. In the 2.6 series,
the SCSI subsystem now has its own (much smaller) drivers/scsi/Kconfig
file that contains both configuration and help information.

struct SHT has been renamed to struct scsi_host_template.

Addition of the "hotplug initialization model" and many extra functions
to support it.

Credits
=======
The following people have contributed to this document:

	- Mike Anderson <andmike at us dot ibm dot com>
	- James Bottomley <James dot Bottomley at hansenpartnership dot com>
	- Patrick Mansfield <patmans at us dot ibm dot com>
	- Christoph Hellwig <hch at infradead dot org>
	- Doug Ledford <dledford at redhat dot com>
	- Andries Brouwer <Andries dot Brouwer at cwi dot nl>
	- Randy Dunlap <rdunlap at xenotime dot net>
	- Alan Stern <stern at rowland dot harvard dot edu>

Douglas Gilbert
dgilbert at interlog dot com

21st September 2004


code:
.. SPDX-License-Identifier: GPL-2.0

SCSI RDMA (SRP) transport class diagram
=======================================

.. kernel-figure:: rport_state_diagram.dot

repo_name: angery/linux


code:
digraph srp_initiator {
	node [shape = doublecircle]; running lost;
	node [shape = circle];

	{
	  rank = min;
	  running_rta	[ label = "running;\nreconnect\ntimer\nactive" ];
	};
	running		[ label = "running;\nreconnect\ntimer\nstopped" ];
	blocked;
	failfast	[ label = "fail I/O\nfast" ];
	lost;

	running -> running_rta		[ label = "fast_io_fail_tmo = off and\ndev_loss_tmo = off;\nsrp_start_tl_fail_timers()" ];
	running_rta -> running		[ label = "fast_io_fail_tmo = off and\ndev_loss_tmo = off;\nreconnecting succeeded" ];
	running -> blocked		[ label = "fast_io_fail_tmo >= 0 or\ndev_loss_tmo >= 0;\nsrp_start_tl_fail_timers()" ];
	running -> failfast		[ label = "fast_io_fail_tmo = off and\ndev_loss_tmo = off;\nreconnecting failed\n" ];
	blocked -> failfast		[ label = "fast_io_fail_tmo\nexpired or\nreconnecting\nfailed" ];
	blocked -> lost			[ label = "dev_loss_tmo\nexpired or\nsrp_stop_rport_timers()" ];
	failfast -> lost		[ label = "dev_loss_tmo\nexpired or\nsrp_stop_rport_timers()" ];
	blocked -> running		[ label = "reconnecting\nsucceeded" ];
	failfast -> failfast		[ label = "reconnecting\nfailed" ];
	failfast -> running		[ label = "reconnecting\nsucceeded" ];
	running -> lost			[ label = "srp_stop_rport_timers()" ];
	running_rta -> lost		[ label = "srp_stop_rport_timers()" ];
}


code:
.. SPDX-License-Identifier: GPL-2.0

======================================
Linux SCSI Disk Driver (sd) Parameters
======================================

cache_type (RW)
---------------
Enable/disable drive write & read cache.

===========================   === ===   ===========   ==========
 cache_type string            WCE RCD   Write cache   Read cache
===========================   === ===   ===========   ==========
 write through                0   0     off           on
 none                         0   1     off           off
 write back                   1   0     on            on
 write back, no read (daft)   1   1     on            off
===========================   === ===   ===========   ==========

To set cache type to "write back" and save this setting to the drive::

  # echo "write back" > cache_type

To modify the caching mode without making the change persistent, prepend
"temporary " to the cache type string. E.g.::

  # echo "temporary write back" > cache_type


code:
.. SPDX-License-Identifier: GPL-2.0

==============================================
SMARTPQI - Microchip Smart Storage SCSI driver
==============================================

This file describes the smartpqi SCSI driver for Microchip
(http://www.microchip.com) PQI controllers. The smartpqi driver
is the next generation SCSI driver for Microchip Corp. The smartpqi
driver is the first SCSI driver to implement the PQI queuing model.

The smartpqi driver will replace the aacraid driver for Adaptec Series 9
controllers. Customers running an older kernel (Pre-4.9) using an Adaptec
Series 9 controller will have to configure the smartpqi driver or their
volumes will not be added to the OS.

For Microchip smartpqi controller support, enable the smartpqi driver
when configuring the kernel.

For more information on the PQI Queuing Interface, please see:

- http://www.t10.org/drafts.htm
- http://www.t10.org/members/w_pqi2.htm

Supported devices
=================
<Controller names to be added as they become publicly available.>

smartpqi specific entries in /sys
=================================

smartpqi host attributes
------------------------
  - /sys/class/scsi_host/host*/rescan
  - /sys/class/scsi_host/host*/driver_version

  The host rescan attribute is a write only attribute. Writing to this
  attribute will trigger the driver to scan for new, changed, or removed
  devices and notify the SCSI mid-layer of any changes detected.

  The version attribute is read-only and will return the driver version
  and the controller firmware version.
  For example::

              driver: 0.9.13-370
              firmware: 0.01-522

smartpqi sas device attributes
------------------------------
  HBA devices are added to the SAS transport layer. These attributes are
  automatically added by the SAS transport layer.

  /sys/class/sas_device/end_device-X:X/sas_address
  /sys/class/sas_device/end_device-X:X/enclosure_identifier
  /sys/class/sas_device/end_device-X:X/scsi_target_id

smartpqi specific ioctls
========================

  For compatibility with applications written for the cciss protocol.

  CCISS_DEREGDISK, CCISS_REGNEWDISK, CCISS_REGNEWD
	The above three ioctls all do exactly the same thing, which is to cause the driver
	to rescan for new devices.  This does exactly the same thing as writing to the
	smartpqi specific host "rescan" attribute.

  CCISS_GETPCIINFO
	Returns PCI domain, bus, device and function and "board ID" (PCI subsystem ID).

  CCISS_GETDRIVVER
	Returns driver version in three bytes encoded as::

	  (DRIVER_MAJOR << 28) | (DRIVER_MINOR << 24) | (DRIVER_RELEASE << 16) | DRIVER_REVISION;

  CCISS_PASSTHRU
	Allows "BMIC" and "CISS" commands to be passed through to the Smart Storage Array.
	These are used extensively by the SSA Array Configuration Utility, SNMP storage
	agents, etc.


code:
.. SPDX-License-Identifier: GPL-2.0

====================
The SCSI Tape Driver
====================

This file contains brief information about the SCSI tape driver.
The driver is currently maintained by Kai Mäkisara (email
Kai.Makisara@kolumbus.fi)

Last modified: Tue Feb  9 21:54:16 2016 by kai.makisara

Basics
======

The driver is generic, i.e., it does not contain any code tailored
to any specific tape drive. The tape parameters can be specified with
one of the following three methods:

1. Each user can specify the tape parameters he/she wants to use
directly with ioctls. This is administratively a very simple and
flexible method and applicable to single-user workstations. However,
in a multiuser environment the next user finds the tape parameters in
state the previous user left them.

2. The system manager (root) can define default values for some tape
parameters, like block size and density using the MTSETDRVBUFFER ioctl.
These parameters can be programmed to come into effect either when a
new tape is loaded into the drive or if writing begins at the
beginning of the tape. The second method is applicable if the tape
drive performs auto-detection of the tape format well (like some
QIC-drives). The result is that any tape can be read, writing can be
continued using existing format, and the default format is used if
the tape is rewritten from the beginning (or a new tape is written
for the first time). The first method is applicable if the drive
does not perform auto-detection well enough and there is a single
"sensible" mode for the device. An example is a DAT drive that is
used only in variable block mode (I don't know if this is sensible
or not :-).

The user can override the parameters defined by the system
manager. The changes persist until the defaults again come into
effect.

3. By default, up to four modes can be defined and selected using the minor
number (bits 5 and 6). The number of modes can be changed by changing
ST_NBR_MODE_BITS in st.h. Mode 0 corresponds to the defaults discussed
above. Additional modes are dormant until they are defined by the
system manager (root). When specification of a new mode is started,
the configuration of mode 0 is used to provide a starting point for
definition of the new mode.

Using the modes allows the system manager to give the users choices
over some of the buffering parameters not directly accessible to the
users (buffered and asynchronous writes). The modes also allow choices
between formats in multi-tape operations (the explicitly overridden
parameters are reset when a new tape is loaded).

If more than one mode is used, all modes should contain definitions
for the same set of parameters.

Many Unices contain internal tables that associate different modes to
supported devices. The Linux SCSI tape driver does not contain such
tables (and will not do that in future). Instead of that, a utility
program can be made that fetches the inquiry data sent by the device,
scans its database, and sets up the modes using the ioctls. Another
alternative is to make a small script that uses mt to set the defaults
tailored to the system.

The driver supports fixed and variable block size (within buffer
limits). Both the auto-rewind (minor equals device number) and
non-rewind devices (minor is 128 + device number) are implemented.

In variable block mode, the byte count in write() determines the size
of the physical block on tape. When reading, the drive reads the next
tape block and returns to the user the data if the read() byte count
is at least the block size. Otherwise, error ENOMEM is returned.

In fixed block mode, the data transfer between the drive and the
driver is in multiples of the block size. The write() byte count must
be a multiple of the block size. This is not required when reading but
may be advisable for portability.

Support is provided for changing the tape partition and partitioning
of the tape with one or two partitions. By default support for
partitioned tape is disabled for each driver and it can be enabled
with the ioctl MTSETDRVBUFFER.

By default the driver writes one filemark when the device is closed after
writing and the last operation has been a write. Two filemarks can be
optionally written. In both cases end of data is signified by
returning zero bytes for two consecutive reads.

Writing filemarks without the immediate bit set in the SCSI command block acts
as a synchronization point, i.e., all remaining data form the drive buffers is
written to tape before the command returns. This makes sure that write errors
are caught at that point, but this takes time. In some applications, several
consecutive files must be written fast. The MTWEOFI operation can be used to
write the filemarks without flushing the drive buffer. Writing filemark at
close() is always flushing the drive buffers. However, if the previous
operation is MTWEOFI, close() does not write a filemark. This can be used if
the program wants to close/open the tape device between files and wants to
skip waiting.

If rewind, offline, bsf, or seek is done and previous tape operation was
write, a filemark is written before moving tape.

The compile options are defined in the file linux/drivers/scsi/st_options.h.

4. If the open option O_NONBLOCK is used, open succeeds even if the
drive is not ready. If O_NONBLOCK is not used, the driver waits for
the drive to become ready. If this does not happen in ST_BLOCK_SECONDS
seconds, open fails with the errno value EIO. With O_NONBLOCK the
device can be opened for writing even if there is a write protected
tape in the drive (commands trying to write something return error if
attempted).

Minor Numbers
=============

The tape driver currently supports up to 2^17 drives if 4 modes for
each drive are used.

The minor numbers consist of the following bit fields::

    dev_upper non-rew mode dev-lower
    20 -  8     7    6 5  4      0

The non-rewind bit is always bit 7 (the uppermost bit in the lowermost
byte). The bits defining the mode are below the non-rewind bit. The
remaining bits define the tape device number. This numbering is
backward compatible with the numbering used when the minor number was
only 8 bits wide.

Sysfs Support
=============

The driver creates the directory /sys/class/scsi_tape and populates it with
directories corresponding to the existing tape devices. There are autorewind
and non-rewind entries for each mode. The names are stxy and nstxy, where x
is the tape number and y a character corresponding to the mode (none, l, m,
a). For example, the directories for the first tape device are (assuming four
modes): st0  nst0  st0l  nst0l  st0m  nst0m  st0a  nst0a.

Each directory contains the entries: default_blksize  default_compression
default_density  defined  dev  device  driver. The file 'defined' contains 1
if the mode is defined and zero if not defined. The files 'default_*' contain
the defaults set by the user. The value -1 means the default is not set. The
file 'dev' contains the device numbers corresponding to this device. The links
'device' and 'driver' point to the SCSI device and driver entries.

Each directory also contains the entry 'options' which shows the currently
enabled driver and mode options. The value in the file is a bit mask where the
bit definitions are the same as those used with MTSETDRVBUFFER in setting the
options.

A link named 'tape' is made from the SCSI device directory to the class
directory corresponding to the mode 0 auto-rewind device (e.g., st0).

Sysfs and Statistics for Tape Devices
=====================================

The st driver maintains statistics for tape drives inside the sysfs filesystem.
The following method can be used to locate the statistics that are
available (assuming that sysfs is mounted at /sys):

1. Use opendir(3) on the directory /sys/class/scsi_tape
2. Use readdir(3) to read the directory contents
3. Use regcomp(3)/regexec(3) to match directory entries to the extended
   regular expression "^st[0-9]+$"
4. Access the statistics from the /sys/class/scsi_tape/<match>/stats
   directory (where <match> is a directory entry from /sys/class/scsi_tape
   that matched the extended regular expression)

The reason for using this approach is that all the character devices
pointing to the same tape drive use the same statistics. That means
that st0 would have the same statistics as nst0.

The directory contains the following statistics files:

1.  in_flight
      - The number of I/Os currently outstanding to this device.
2.  io_ns
      - The amount of time spent waiting (in nanoseconds) for all I/O
        to complete (including read and write). This includes tape movement
        commands such as seeking between file or set marks and implicit tape
        movement such as when rewind on close tape devices are used.
3.  other_cnt
      - The number of I/Os issued to the tape drive other than read or
        write commands. The time taken to complete these commands uses the
        following calculation io_ms-read_ms-write_ms.
4.  read_byte_cnt
      - The number of bytes read from the tape drive.
5.  read_cnt
      - The number of read requests issued to the tape drive.
6.  read_ns
      - The amount of time (in nanoseconds) spent waiting for read
        requests to complete.
7.  write_byte_cnt
      - The number of bytes written to the tape drive.
8.  write_cnt
      - The number of write requests issued to the tape drive.
9.  write_ns
      - The amount of time (in nanoseconds) spent waiting for write
        requests to complete.
10. resid_cnt
      - The number of times during a read or write we found
	the residual amount to be non-zero. This should mean that a program
	is issuing a read larger thean the block size on tape. For write
	not all data made it to tape.

.. Note::

   The in_flight value is incremented when an I/O starts the I/O
   itself is not added to the statistics until it completes.

The total of read_cnt, write_cnt, and other_cnt may not total to the same
value as iodone_cnt at the device level. The tape statistics only count
I/O issued via the st module.

When read the statistics may not be temporally consistent while I/O is in
progress. The individual values are read and written to atomically however
when reading them back via sysfs they may be in the process of being
updated when starting an I/O or when it is completed.

The value shown in in_flight is incremented before any statstics are
updated and decremented when an I/O completes after updating statistics.
The value of in_flight is 0 when there are no I/Os outstanding that are
issued by the st driver. Tape statistics do not take into account any
I/O performed via the sg device.

BSD and Sys V Semantics
=======================

The user can choose between these two behaviours of the tape driver by
defining the value of the symbol ST_SYSV. The semantics differ when a
file being read is closed. The BSD semantics leaves the tape where it
currently is whereas the SYS V semantics moves the tape past the next
filemark unless the filemark has just been crossed.

The default is BSD semantics.

Buffering
=========

The driver tries to do transfers directly to/from user space. If this
is not possible, a driver buffer allocated at run-time is used. If
direct i/o is not possible for the whole transfer, the driver buffer
is used (i.e., bounce buffers for individual pages are not
used). Direct i/o can be impossible because of several reasons, e.g.:

- one or more pages are at addresses not reachable by the HBA
- the number of pages in the transfer exceeds the number of
  scatter/gather segments permitted by the HBA
- one or more pages can't be locked into memory (should not happen in
  any reasonable situation)

The size of the driver buffers is always at least one tape block. In fixed
block mode, the minimum buffer size is defined (in 1024 byte units) by
ST_FIXED_BUFFER_BLOCKS. With small block size this allows buffering of
several blocks and using one SCSI read or write to transfer all of the
blocks. Buffering of data across write calls in fixed block mode is
allowed if ST_BUFFER_WRITES is non-zero and direct i/o is not used.
Buffer allocation uses chunks of memory having sizes 2^n * (page
size). Because of this the actual buffer size may be larger than the
minimum allowable buffer size.

NOTE that if direct i/o is used, the small writes are not buffered. This may
cause a surprise when moving from 2.4. There small writes (e.g., tar without
-b option) may have had good throughput but this is not true any more with
2.6. Direct i/o can be turned off to solve this problem but a better solution
is to use bigger write() byte counts (e.g., tar -b 64).

Asynchronous writing. Writing the buffer contents to the tape is
started and the write call returns immediately. The status is checked
at the next tape operation. Asynchronous writes are not done with
direct i/o and not in fixed block mode.

Buffered writes and asynchronous writes may in some rare cases cause
problems in multivolume operations if there is not enough space on the
tape after the early-warning mark to flush the driver buffer.

Read ahead for fixed block mode (ST_READ_AHEAD). Filling the buffer is
attempted even if the user does not want to get all of the data at
this read command. Should be disabled for those drives that don't like
a filemark to truncate a read request or that don't like backspacing.

Scatter/gather buffers (buffers that consist of chunks non-contiguous
in the physical memory) are used if contiguous buffers can't be
allocated. To support all SCSI adapters (including those not
supporting scatter/gather), buffer allocation is using the following
three kinds of chunks:

1. The initial segment that is used for all SCSI adapters including
   those not supporting scatter/gather. The size of this buffer will be
   (PAGE_SIZE << ST_FIRST_ORDER) bytes if the system can give a chunk of
   this size (and it is not larger than the buffer size specified by
   ST_BUFFER_BLOCKS). If this size is not available, the driver halves
   the size and tries again until the size of one page. The default
   settings in st_options.h make the driver to try to allocate all of the
   buffer as one chunk.
2. The scatter/gather segments to fill the specified buffer size are
   allocated so that as many segments as possible are used but the number
   of segments does not exceed ST_FIRST_SG.
3. The remaining segments between ST_MAX_SG (or the module parameter
   max_sg_segs) and the number of segments used in phases 1 and 2
   are used to extend the buffer at run-time if this is necessary. The
   number of scatter/gather segments allowed for the SCSI adapter is not
   exceeded if it is smaller than the maximum number of scatter/gather
   segments specified. If the maximum number allowed for the SCSI adapter
   is smaller than the number of segments used in phases 1 and 2,
   extending the buffer will always fail.

EOM Behaviour When Writing
==========================

When the end of medium early warning is encountered, the current write
is finished and the number of bytes is returned. The next write
returns -1 and errno is set to ENOSPC. To enable writing a trailer,
the next write is allowed to proceed and, if successful, the number of
bytes is returned. After this, -1 and the number of bytes are
alternately returned until the physical end of medium (or some other
error) is encountered.

Module Parameters
=================

The buffer size, write threshold, and the maximum number of allocated buffers
are configurable when the driver is loaded as a module. The keywords are:

========================== ===========================================
buffer_kbs=xxx             the buffer size for fixed block mode is set
			   to xxx kilobytes
write_threshold_kbs=xxx    the write threshold in kilobytes set to xxx
max_sg_segs=xxx		   the maximum number of scatter/gather
			   segments
try_direct_io=x		   try direct transfer between user buffer and
			   tape drive if this is non-zero
========================== ===========================================

Note that if the buffer size is changed but the write threshold is not
set, the write threshold is set to the new buffer size - 2 kB.

Boot Time Configuration
=======================

If the driver is compiled into the kernel, the same parameters can be
also set using, e.g., the LILO command line. The preferred syntax is
to use the same keyword used when loading as module but prepended
with 'st.'. For instance, to set the maximum number of scatter/gather
segments, the parameter 'st.max_sg_segs=xx' should be used (xx is the
number of scatter/gather segments).

For compatibility, the old syntax from early 2.5 and 2.4 kernel
versions is supported. The same keywords can be used as when loading
the driver as module. If several parameters are set, the keyword-value
pairs are separated with a comma (no spaces allowed). A colon can be
used instead of the equal mark. The definition is prepended by the
string st=. Here is an example::

	st=buffer_kbs:64,write_threshold_kbs:60

The following syntax used by the old kernel versions is also supported::

           st=aa[,bb[,dd]]

where:

  - aa is the buffer size for fixed block mode in 1024 byte units
  - bb is the write threshold in 1024 byte units
  - dd is the maximum number of scatter/gather segments

IOCTLs
======

The tape is positioned and the drive parameters are set with ioctls
defined in mtio.h The tape control program 'mt' uses these ioctls. Try
to find an mt that supports all of the Linux SCSI tape ioctls and
opens the device for writing if the tape contents will be modified
(look for a package mt-st* from the Linux ftp sites; the GNU mt does
not open for writing for, e.g., erase).

The supported ioctls are:

The following use the structure mtop:

MTFSF
	Space forward over count filemarks. Tape positioned after filemark.
MTFSFM
	As above but tape positioned before filemark.
MTBSF
	Space backward over count filemarks. Tape positioned before
        filemark.
MTBSFM
	As above but ape positioned after filemark.
MTFSR
	Space forward over count records.
MTBSR
	Space backward over count records.
MTFSS
	Space forward over count setmarks.
MTBSS
	Space backward over count setmarks.
MTWEOF
	Write count filemarks.
MTWEOFI
	Write count filemarks with immediate bit set (i.e., does not
	wait until data is on tape)
MTWSM
	Write count setmarks.
MTREW
	Rewind tape.
MTOFFL
	Set device off line (often rewind plus eject).
MTNOP
	Do nothing except flush the buffers.
MTRETEN
	Re-tension tape.
MTEOM
	Space to end of recorded data.
MTERASE
	Erase tape. If the argument is zero, the short erase command
	is used. The long erase command is used with all other values
	of the argument.
MTSEEK
	Seek to tape block count. Uses Tandberg-compatible seek (QFA)
        for SCSI-1 drives and SCSI-2 seek for SCSI-2 drives. The file and
	block numbers in the status are not valid after a seek.
MTSETBLK
	Set the drive block size. Setting to zero sets the drive into
        variable block mode (if applicable).
MTSETDENSITY
	Sets the drive density code to arg. See drive
        documentation for available codes.
MTLOCK and MTUNLOCK
	Explicitly lock/unlock the tape drive door.
MTLOAD and MTUNLOAD
	Explicitly load and unload the tape. If the
	command argument x is between MT_ST_HPLOADER_OFFSET + 1 and
	MT_ST_HPLOADER_OFFSET + 6, the number x is used sent to the
	drive with the command and it selects the tape slot to use of
	HP C1553A changer.
MTCOMPRESSION
	Sets compressing or uncompressing drive mode using the
	SCSI mode page 15. Note that some drives other methods for
	control of compression. Some drives (like the Exabytes) use
	density codes for compression control. Some drives use another
	mode page but this page has not been implemented in the
	driver. Some drives without compression capability will accept
	any compression mode without error.
MTSETPART
	Moves the tape to the partition given by the argument at the
	next tape operation. The block at which the tape is positioned
	is the block where the tape was previously positioned in the
	new active partition unless the next tape operation is
	MTSEEK. In this case the tape is moved directly to the block
	specified by MTSEEK. MTSETPART is inactive unless
	MT_ST_CAN_PARTITIONS set.
MTMKPART
	Formats the tape with one partition (argument zero) or two
	partitions (argument non-zero). If the argument is positive,
	it specifies the size of partition 1 in megabytes. For DDS
	drives and several early drives this is the physically first
	partition of the tape. If the argument is negative, its absolute
	value specifies the size of partition 0 in megabytes. This is
	the physically first partition of many later drives, like the
	LTO drives from LTO-5 upwards. The drive has to support partitions
	with size specified by the initiator. Inactive unless
	MT_ST_CAN_PARTITIONS set.
MTSETDRVBUFFER
	Is used for several purposes. The command is obtained from count
        with mask MT_SET_OPTIONS, the low order bits are used as argument.
	This command is only allowed for the superuser (root). The
	subcommands are:

	* 0
           The drive buffer option is set to the argument. Zero means
           no buffering.
        * MT_ST_BOOLEANS
           Sets the buffering options. The bits are the new states
           (enabled/disabled) the following options (in the
	   parenthesis is specified whether the option is global or
	   can be specified differently for each mode):

	     MT_ST_BUFFER_WRITES
		write buffering (mode)
	     MT_ST_ASYNC_WRITES
		asynchronous writes (mode)
             MT_ST_READ_AHEAD
		read ahead (mode)
             MT_ST_TWO_FM
		writing of two filemarks (global)
	     MT_ST_FAST_EOM
		using the SCSI spacing to EOD (global)
	     MT_ST_AUTO_LOCK
		automatic locking of the drive door (global)
             MT_ST_DEF_WRITES
		the defaults are meant only for writes (mode)
	     MT_ST_CAN_BSR
		backspacing over more than one records can
		be used for repositioning the tape (global)
	     MT_ST_NO_BLKLIMS
		the driver does not ask the block limits
		from the drive (block size can be changed only to
		variable) (global)
	     MT_ST_CAN_PARTITIONS
		enables support for partitioned
		tapes (global)
	     MT_ST_SCSI2LOGICAL
		the logical block number is used in
		the MTSEEK and MTIOCPOS for SCSI-2 drives instead of
		the device dependent address. It is recommended to set
		this flag unless there are tapes using the device
		dependent (from the old times) (global)
	     MT_ST_SYSV
		sets the SYSV semantics (mode)
	     MT_ST_NOWAIT
		enables immediate mode (i.e., don't wait for
	        the command to finish) for some commands (e.g., rewind)
	     MT_ST_NOWAIT_EOF
		enables immediate filemark mode (i.e. when
	        writing a filemark, don't wait for it to complete). Please
		see the BASICS note about MTWEOFI with respect to the
		possible dangers of writing immediate filemarks.
	     MT_ST_SILI
		enables setting the SILI bit in SCSI commands when
		reading in variable block mode to enhance performance when
		reading blocks shorter than the byte count; set this only
		if you are sure that the drive supports SILI and the HBA
		correctly returns transfer residuals
	     MT_ST_DEBUGGING
		debugging (global; debugging must be
		compiled into the driver)

	* MT_ST_SETBOOLEANS, MT_ST_CLEARBOOLEANS
	   Sets or clears the option bits.
        * MT_ST_WRITE_THRESHOLD
           Sets the write threshold for this device to kilobytes
           specified by the lowest bits.
	* MT_ST_DEF_BLKSIZE
	   Defines the default block size set automatically. Value
	   0xffffff means that the default is not used any more.
	* MT_ST_DEF_DENSITY, MT_ST_DEF_DRVBUFFER
	   Used to set or clear the density (8 bits), and drive buffer
	   state (3 bits). If the value is MT_ST_CLEAR_DEFAULT
	   (0xfffff) the default will not be used any more. Otherwise
	   the lowermost bits of the value contain the new value of
	   the parameter.
	* MT_ST_DEF_COMPRESSION
	   The compression default will not be used if the value of
	   the lowermost byte is 0xff. Otherwise the lowermost bit
	   contains the new default. If the bits 8-15 are set to a
	   non-zero number, and this number is not 0xff, the number is
	   used as the compression algorithm. The value
	   MT_ST_CLEAR_DEFAULT can be used to clear the compression
	   default.
	* MT_ST_SET_TIMEOUT
	   Set the normal timeout in seconds for this device. The
	   default is 900 seconds (15 minutes). The timeout should be
	   long enough for the retries done by the device while
	   reading/writing.
	* MT_ST_SET_LONG_TIMEOUT
	   Set the long timeout that is used for operations that are
	   known to take a long time. The default is 14000 seconds
	   (3.9 hours). For erase this value is further multiplied by
	   eight.
	* MT_ST_SET_CLN
	   Set the cleaning request interpretation parameters using
	   the lowest 24 bits of the argument. The driver can set the
	   generic status bit GMT_CLN if a cleaning request bit pattern
	   is found from the extended sense data. Many drives set one or
	   more bits in the extended sense data when the drive needs
	   cleaning. The bits are device-dependent. The driver is
	   given the number of the sense data byte (the lowest eight
	   bits of the argument; must be >= 18 (values 1 - 17
	   reserved) and <= the maximum requested sense data sixe),
	   a mask to select the relevant bits (the bits 9-16), and the
	   bit pattern (bits 17-23). If the bit pattern is zero, one
	   or more bits under the mask indicate cleaning request. If
	   the pattern is non-zero, the pattern must match the masked
	   sense data byte.

	   (The cleaning bit is set if the additional sense code and
	   qualifier 00h 17h are seen regardless of the setting of
	   MT_ST_SET_CLN.)

The following ioctl uses the structure mtpos:

MTIOCPOS
	Reads the current position from the drive. Uses
        Tandberg-compatible QFA for SCSI-1 drives and the SCSI-2
        command for the SCSI-2 drives.

The following ioctl uses the structure mtget to return the status:

MTIOCGET
	Returns some status information.
        The file number and block number within file are returned. The
        block is -1 when it can't be determined (e.g., after MTBSF).
        The drive type is either MTISSCSI1 or MTISSCSI2.
        The number of recovered errors since the previous status call
        is stored in the lower word of the field mt_erreg.
        The current block size and the density code are stored in the field
        mt_dsreg (shifts for the subfields are MT_ST_BLKSIZE_SHIFT and
        MT_ST_DENSITY_SHIFT).
	The GMT_xxx status bits reflect the drive status. GMT_DR_OPEN
	is set if there is no tape in the drive. GMT_EOD means either
	end of recorded data or end of tape. GMT_EOT means end of tape.

Miscellaneous Compile Options
=============================

The recovered write errors are considered fatal if ST_RECOVERED_WRITE_FATAL
is defined.

The maximum number of tape devices is determined by the define
ST_MAX_TAPES. If more tapes are detected at driver initialization, the
maximum is adjusted accordingly.

Immediate return from tape positioning SCSI commands can be enabled by
defining ST_NOWAIT. If this is defined, the user should take care that
the next tape operation is not started before the previous one has
finished. The drives and SCSI adapters should handle this condition
gracefully, but some drive/adapter combinations are known to hang the
SCSI bus in this case.

The MTEOM command is by default implemented as spacing over 32767
filemarks. With this method the file number in the status is
correct. The user can request using direct spacing to EOD by setting
ST_FAST_EOM 1 (or using the MT_ST_OPTIONS ioctl). In this case the file
number will be invalid.

When using read ahead or buffered writes the position within the file
may not be correct after the file is closed (correct position may
require backspacing over more than one record). The correct position
within file can be obtained if ST_IN_FILE_POS is defined at compile
time or the MT_ST_CAN_BSR bit is set for the drive with an ioctl.
(The driver always backs over a filemark crossed by read ahead if the
user does not request data that far.)

Debugging Hints
===============

Debugging code is now compiled in by default but debugging is turned off
with the kernel module parameter debug_flag defaulting to 0.  Debugging
can still be switched on and off with an ioctl.  To enable debug at
module load time add debug_flag=1 to the module load options, the
debugging output is not voluminous. Debugging can also be enabled
and disabled by writing a '0' (disable) or '1' (enable) to the sysfs
file /sys/bus/scsi/drivers/st/debug_flag.

If the tape seems to hang, I would be very interested to hear where
the driver is waiting. With the command 'ps -l' you can see the state
of the process using the tape. If the state is D, the process is
waiting for something. The field WCHAN tells where the driver is
waiting. If you have the current System.map in the correct place (in
/boot for the procps I use) or have updated /etc/psdatabase (for kmem
ps), ps writes the function name in the WCHAN field. If not, you have
to look up the function from System.map.

Note also that the timeouts are very long compared to most other
drivers. This means that the Linux driver may appear hung although the
real reason is that the tape firmware has got confused.


code:
.. SPDX-License-Identifier: GPL-2.0

=======================
The sym53c500_cs Driver
=======================

The sym53c500_cs driver originated as an add-on to David Hinds' pcmcia-cs
package, and was written by Tom Corner (tcorner@via.at).  A rewrite was
long overdue, and the current version addresses the following concerns:

	(1) extensive kernel changes between 2.4 and 2.6.
	(2) deprecated PCMCIA support outside the kernel.

All the USE_BIOS code has been ripped out.  It was never used, and could
not have worked anyway.  The USE_DMA code is likewise gone.  Many thanks
to YOKOTA Hiroshi (nsp_cs driver) and David Hinds (qlogic_cs driver) for
the code fragments I shamelessly adapted for this work.  Thanks also to
Christoph Hellwig for his patient tutelage while I stumbled about.

The Symbios Logic 53c500 chip was used in the "newer" (circa 1997) version
of the New Media Bus Toaster PCMCIA SCSI controller.  Presumably there are
other products using this chip, but I've never laid eyes (much less hands)
on one.

Through the years, there have been a number of downloads of the pcmcia-cs
version of this driver, and I guess it worked for those users.  It worked
for Tom Corner, and it works for me.  Your mileage will probably vary.

Bob Tracy (rct@frus.com)