diff options
Diffstat (limited to 'Documentation/scsi/scsi_mid_low_api.txt')
-rw-r--r-- | Documentation/scsi/scsi_mid_low_api.txt | 1546 |
1 files changed, 1546 insertions, 0 deletions
diff --git a/Documentation/scsi/scsi_mid_low_api.txt b/Documentation/scsi/scsi_mid_low_api.txt new file mode 100644 index 00000000000..1f24129a309 --- /dev/null +++ b/Documentation/scsi/scsi_mid_low_api.txt @@ -0,0 +1,1546 @@ + 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 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() --------+ + | + slave_alloc() + slave_configure() --> scsi_adjust_queue_depth() + | + slave_alloc() + slave_configure() + | + slave_alloc() *** + slave_destroy() *** +------------------------------------------------------------ + +If the LLD wants to adjust the default queue settings, it can invoke +scsi_adjust_queue_depth() in its slave_configure() routine. + +*** For scsi devices that the mid level tries to scan but do not + respond, a slave_alloc(), slave_destroy() pair is called. + +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_add_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_adjust_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(). + + +Passive initialization model +============================ +These older LLDs include a file called "scsi_module.c" [yes the ".c" is a +little surprising] in their source code. For that file to work an +instance of struct scsi_host_template with the name "driver_template" +needs to be defined. Here is a typical code sequence used in this model: + static struct scsi_host_template driver_template = { + ... + }; + #include "scsi_module.c" + +The scsi_module.c file contains two functions: + - init_this_scsi_driver() which is executed when the LLD is + initialized (i.e. boot time or module load time) + - exit_this_scsi_driver() which is executed when the LLD is shut + down (i.e. module unload time) +Note: since these functions are tagged with __init and __exit qualifiers +an LLD should not call them explicitly (since the kernel does that). + +Here is an example of an initialization sequence when two hosts are +detected (so detect() returns 2) and the SCSI bus scan on each host +finds 1 SCSI device (and a second device does not respond). + +LLD mid level LLD +===----------------------=========-----------------===------ +init_this_scsi_driver() ----+ + | + detect() -----------------+ + | | + | scsi_register() + | scsi_register() + | + slave_alloc() + slave_configure() --> scsi_adjust_queue_depth() + slave_alloc() *** + slave_destroy() *** + | + slave_alloc() + slave_configure() + slave_alloc() *** + slave_destroy() *** +------------------------------------------------------------ + +The mid level invokes scsi_adjust_queue_depth() with tagged queuing off and +"cmd_per_lun" for that host as the queue length. These settings can be +overridden by a slave_configure() supplied by the LLD. + +*** For scsi devices that the mid level tries to scan but do not + respond, a slave_alloc(), slave_destroy() pair is called. + +Here is an LLD shutdown sequence: + +LLD mid level LLD +===----------------------=========-----------------===------ +exit_this_scsi_driver() ----+ + | + slave_destroy() + release() --> scsi_unregister() + | + slave_destroy() + release() --> scsi_unregister() +------------------------------------------------------------ + +An LLD need not define slave_destroy() (i.e. it is optional). + +The shortcoming of the "passive initialization model" is that host +registration and de-registration are (typically) tied to LLD initialization +and shutdown. Once the LLD is initialized then a new host that appears +(e.g. via hotplugging) cannot easily be added without a redundant +driver shutdown and re-initialization. It may be possible to write an LLD +that uses both initialization models. + + +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). + +^^ 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/CodingStyle file. + +Next, there is a movement to "outlaw" typedefs introducing synonyms for +struct tags. Both can be still found in the SCSI subsystem, but +the typedefs have been moved to a single file, scsi_typedefs.h to +make their future removal easier, for example: +"typedef struct scsi_host_template Scsi_Host_Template;" + +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_activate_tcq - turn on tag command queueing + scsi_add_device - creates new scsi device (lu) instance + scsi_add_host - perform sysfs registration and SCSI bus scan. + scsi_add_timer - (re-)start timer on a SCSI command. + scsi_adjust_queue_depth - change the queue depth on a SCSI device + scsi_assign_lock - replace default host_lock with given lock + scsi_bios_ptable - return copy of block device's partition table + scsi_block_requests - prevent further commands being queued to given host + scsi_deactivate_tcq - turn off tag command queueing + scsi_delete_timer - cancel timer on a SCSI command. + 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_partsize - parse partition table into cylinders, heads + sectors + 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_set_device - place device reference in host structure + scsi_to_pci_dma_dir - convert SCSI subsystem direction flag to PCI + scsi_to_sbus_dma_dir - convert SCSI subsystem direction flag to SBUS + 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_activate_tcq - turn on tag command queueing ("ordered" task attribute) + * @sdev: device to turn on TCQ for + * @depth: queue depth + * + * Returns nothing + * + * Might block: no + * + * Notes: Eventually, it is hoped depth would be the maximum depth + * the device could cope with and the real queue depth + * would be adjustable from 0 to depth. + * + * Defined (inline) in: include/scsi/scsi_tcq.h + **/ +void scsi_activate_tcq(struct scsi_device *sdev, int depth) + + +/** + * 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_add_host()). So it + * should only be called if the HBA becomes aware of a new scsi + * device (lu) after scsi_add_host() has completed. If successful + * this call we 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 SCSI bus scan. + * @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(). + * + * Defined in: drivers/scsi/hosts.c + **/ +int scsi_add_host(struct Scsi_Host *shost, struct device * dev) + + +/** + * scsi_add_timer - (re-)start timer on a SCSI command. + * @scmd: pointer to scsi command instance + * @timeout: duration of timeout in "jiffies" + * @complete: pointer to function to call if timeout expires + * + * Returns nothing + * + * Might block: no + * + * Notes: Each scsi command has its own timer, and as it is added + * to the queue, we set up the timer. When the command completes, + * we cancel the timer. An LLD can use this function to change + * the existing timeout value. + * + * Defined in: drivers/scsi/scsi_error.c + **/ +void scsi_add_timer(struct scsi_cmnd *scmd, int timeout, + void (*complete)(struct scsi_cmnd *)) + + +/** + * scsi_adjust_queue_depth - allow LLD to change queue depth on a SCSI device + * @sdev: pointer to SCSI device to change queue depth on + * @tagged: 0 - no tagged queuing + * MSG_SIMPLE_TAG - simple tagged queuing + * MSG_ORDERED_TAG - ordered tagged queuing + * @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. Actual + * queue depth change may be delayed until the next command is being + * processed. See also scsi_activate_tcq() and scsi_deactivate_tcq(). + * + * Defined in: drivers/scsi/scsi.c [see source code for more notes] + * + **/ +void scsi_adjust_queue_depth(struct scsi_device * sdev, int tagged, + int tags) + + +/** + * scsi_assign_lock - replace default host_lock with given lock + * @shost: a pointer to a scsi host instance + * @lock: pointer to lock to replace host_lock for this host + * + * Returns nothing + * + * Might block: no + * + * Defined in: include/scsi/scsi_host.h . + **/ +void scsi_assign_lock(struct Scsi_Host *shost, spinlock_t *lock) + + +/** + * 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_deactivate_tcq - turn off tag command queueing + * @sdev: device to turn off TCQ for + * @depth: queue depth (stored in sdev) + * + * Returns nothing + * + * Might block: no + * + * Defined (inline) in: include/scsi/scsi_tcq.h + **/ +void scsi_deactivate_tcq(struct scsi_device *sdev, int depth) + + +/** + * scsi_delete_timer - cancel timer on a SCSI command. + * @scmd: pointer to scsi command instance + * + * Returns 1 if able to cancel timer else 0 (i.e. too late or already + * cancelled). + * + * Might block: no [may in the future if it invokes del_timer_sync()] + * + * Notes: All commands issued by upper levels already have a timeout + * associated with them. An LLD can use this function to cancel the + * timer. + * + * Defined in: drivers/scsi/scsi_error.c + **/ +int scsi_delete_timer(struct scsi_cmnd *scmd) + + +/** + * 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() is 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_partsize - parse partition table into cylinders, heads + sectors + * @buf: pointer to partition table + * @capacity: size of (total) disk in 512 byte sectors + * @cyls: outputs number of cylinders calculated via this pointer + * @hds: outputs number of heads calculated via this pointer + * @secs: outputs number of sectors calculated via this pointer + * + * Returns 0 on success, -1 on failure + * + * Might block: no + * + * Notes: Caller owns memory returned (free with kfree() ) + * + * Defined in: drivers/scsi/scsicam.c + **/ +int scsi_partsize(unsigned char *buf, unsigned long capacity, + unsigned int *cyls, unsigned int *hds, unsigned int *secs) + + +/** + * 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_set_device - place device reference in host structure + * @shost: a pointer to a scsi host instance + * @pdev: pointer to device instance to assign + * + * Returns nothing + * + * Might block: no + * + * Defined in: include/scsi/scsi_host.h . + **/ +void scsi_set_device(struct Scsi_Host * shost, struct device * dev) + + +/** + * scsi_to_pci_dma_dir - convert SCSI subsystem direction flag to PCI + * @scsi_data_direction: SCSI subsystem direction flag + * + * Returns DMA_TO_DEVICE given SCSI_DATA_WRITE, + * DMA_FROM_DEVICE given SCSI_DATA_READ + * DMA_BIDIRECTIONAL given SCSI_DATA_UNKNOWN + * else returns DMA_NONE + * + * Might block: no + * + * Notes: The SCSI subsystem now uses the same values for these + * constants as the PCI subsystem so this function is a nop. + * The recommendation is not to use this conversion function anymore + * (in the 2.6 kernel series) as it is not needed. + * + * Defined in: drivers/scsi/scsi.h . + **/ +int scsi_to_pci_dma_dir(unsigned char scsi_data_direction) + + +/** + * scsi_to_sbus_dma_dir - convert SCSI subsystem direction flag to SBUS + * @scsi_data_direction: SCSI subsystem direction flag + * + * Returns DMA_TO_DEVICE given SCSI_DATA_WRITE, + * FROM_DEVICE given SCSI_DATA_READ + * DMA_BIDIRECTIONAL given SCSI_DATA_UNKNOWN + * else returns DMA_NONE + * + * Notes: The SCSI subsystem now uses the same values for these + * constants as the SBUS subsystem so this function is a nop. + * The recommendation is not to use this conversion function anymore + * (in the 2.6 kernel series) as it is not needed. + * + * Might block: no + * + * Defined in: drivers/scsi/scsi.h . + **/ +int scsi_to_sbus_dma_dir(unsigned char scsi_data_direction) + + +/** + * 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(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 + detect - detects HBAs this driver wants to control + 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) + eh_strategy_handler - driver supplied alternate to scsi_unjam_host() + 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 + release - release all resources associated with given host + 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]) + + +/** + * detect - detects HBAs this driver wants to control + * @shtp: host template for this driver. + * + * Returns number of hosts this driver wants to control. 0 means no + * suitable hosts found. + * + * Locks: none held + * + * Calling context: process [invoked from init_this_scsi_driver()] + * + * Notes: First function called from the SCSI mid level on this + * driver. Upper level drivers (e.g. sd) may not (yet) be present. + * For each host found, this method should call scsi_register() + * [see hosts.c]. + * + * Defined in: LLD (required if "passive initialization mode" is used, + * not invoked in "hotplug initia |