Linux Kernel 2.6 series
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 or MCA 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://www.torque.net/scsi/scsi_mid_low_api.txt.gz .
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.
The Linux kernel source Documentation/DocBook/scsidrivers.tmpl file
refers to this file. With the appropriate DocBook tool-set, this permits
users to generate html, ps and pdf renderings of information within this
file (e.g. the interface functions).
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. The scsi_register()
and scsi_unregister() functions remain to support legacy LLDs that use
the passive initialization model.
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