Copyright © 2007 Linux Foundation
This documentation is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For more details see the file COPYING in the source distribution of Linux.
Table of Contents
Table of Contents
Once upon a time, the Small Computer Systems Interface defined both a parallel I/O bus and a data protocol to connect a wide variety of peripherals (disk drives, tape drives, modems, printers, scanners, optical drives, test equipment, and medical devices) to a host computer.
Although the old parallel (fast/wide/ultra) SCSI bus has largely fallen out of use, the SCSI command set is more widely used than ever to communicate with devices over a number of different busses.
The SCSI protocol is a big-endian peer-to-peer packet based protocol. SCSI commands are 6, 10, 12, or 16 bytes long, often followed by an associated data payload.
SCSI commands can be transported over just about any kind of bus, and are the default protocol for storage devices attached to USB, SATA, SAS, Fibre Channel, FireWire, and ATAPI devices. SCSI packets are also commonly exchanged over Infiniband, I20, TCP/IP (iSCSI), even Parallel ports.
The SCSI subsystem uses a three layer design, with upper, mid, and low layers. Every operation involving the SCSI subsystem (such as reading a sector from a disk) uses one driver at each of the 3 levels: one upper layer driver, one lower layer driver, and the SCSI midlayer.
The SCSI upper layer provides the interface between userspace and the kernel, in the form of block and char device nodes for I/O and ioctl(). The SCSI lower layer contains drivers for specific hardware devices.
In between is the SCSI mid-layer, analogous to a network routing layer such as the IPv4 stack. The SCSI mid-layer routes a packet based data protocol between the upper layer's /dev nodes and the corresponding devices in the lower layer. It manages command queues, provides error handling and power management functions, and responds to ioctl() requests.
Table of Contents
The upper layer supports the user-kernel interface by providing device nodes.
Table of Contents
shost_for_each_device — iterate over all devices of a host
fsfuncshost_for_each_device ( | sdev, | |
shost) ; |
sdev
; shost
;__shost_for_each_device — iterate over all devices of a host (UNLOCKED)
fsfunc__shost_for_each_device ( | sdev, | |
shost) ; |
sdev
; shost
;Main file for the SCSI midlayer.
scsi_device_type — Return 17 char string indicating device type.
const char * fsfuncscsi_device_type ( | type) ; |
unsigned type
;__scsi_get_command — Allocate a struct scsi_cmnd
struct scsi_cmnd * fsfunc__scsi_get_command ( | shost, | |
gfp_mask) ; |
struct Scsi_Host * shost
;gfp_t gfp_mask
;scsi_get_command — Allocate and setup a scsi command block
struct scsi_cmnd * fsfuncscsi_get_command ( | dev, | |
gfp_mask) ; |
struct scsi_device * dev
;gfp_t gfp_mask
;__scsi_put_command — Free a struct scsi_cmnd
void fsfunc__scsi_put_command ( | shost, | |
cmd, | ||
dev) ; |
struct Scsi_Host * shost
;struct scsi_cmnd * cmd
;struct device * dev
;scsi_put_command — Free a scsi command block
void fsfuncscsi_put_command ( | cmd) ; |
struct scsi_cmnd * cmd
;scsi_allocate_command — get a fully allocated SCSI command
struct scsi_cmnd * fsfuncscsi_allocate_command ( | gfp_mask) ; |
gfp_t gfp_mask
;This function is for use outside of the normal host based pools. It allocates the relevant command and takes an additional reference on the pool it used. This function *must* be paired with scsi_free_command which also has the identical mask, otherwise the free pool counts will eventually go wrong and you'll trigger a bug.
This function should *only* be used by drivers that need a static command allocation at start of day for internal functions.
scsi_free_command — free a command allocated by scsi_allocate_command
void fsfuncscsi_free_command ( | gfp_mask, | |
cmd) ; |
gfp_t gfp_mask
;struct scsi_cmnd * cmd
;scsi_cmd_get_serial — Assign a serial number to a command
void fsfuncscsi_cmd_get_serial ( | host, | |
cmd) ; |
struct Scsi_Host * host
;struct scsi_cmnd * cmd
;scsi_finish_command — cleanup and pass command back to upper layer
void fsfuncscsi_finish_command ( | cmd) ; |
struct scsi_cmnd * cmd
;scsi_adjust_queue_depth — Let low level drivers change a device's queue depth
void fsfuncscsi_adjust_queue_depth ( | sdev, | |
tagged, | ||
tags) ; |
struct scsi_device * sdev
;int tagged
;int tags
;scsi_track_queue_full — track QUEUE_FULL events to adjust queue depth
int fsfuncscsi_track_queue_full ( | sdev, | |
depth) ; |
struct scsi_device * sdev
;int depth
;sdev
SCSI Device in question
depth
Current number of outstanding SCSI commands on this device, not counting the one returned as QUEUE_FULL.
This function will track successive QUEUE_FULL events on a specific SCSI device to determine if and when there is a need to adjust the queue depth on the device.
scsi_get_vpd_page — Get Vital Product Data from a SCSI device
int fsfuncscsi_get_vpd_page ( | sdev, | |
page, | ||
buf, | ||
buf_len) ; |
struct scsi_device * sdev
;u8 page
;unsigned char * buf
;int buf_len
;sdev
The device to ask
page
Which Vital Product Data to return
buf
where to store the VPD
buf_len
number of bytes in the VPD buffer area
SCSI devices may optionally supply Vital Product Data. Each 'page'
of VPD is defined in the appropriate SCSI document (eg SPC, SBC).
If the device supports this VPD page, this routine returns a pointer
to a buffer containing the data from that page. The caller is
responsible for calling kfree
on this pointer when it is no longer
needed. If we cannot retrieve the VPD page this routine returns NULL
.
scsi_report_opcode — Find out if a given command opcode is supported
int fsfuncscsi_report_opcode ( | sdev, | |
buffer, | ||
len, | ||
opcode) ; |
struct scsi_device * sdev
;unsigned char * buffer
;unsigned int len
;unsigned char opcode
;scsi_device_get — get an additional reference to a scsi_device
int fsfuncscsi_device_get ( | sdev) ; |
struct scsi_device * sdev
;scsi_device_put — release a reference to a scsi_device
void fsfuncscsi_device_put ( | sdev) ; |
struct scsi_device * sdev
;starget_for_each_device — helper to walk all devices of a target
void fsfuncstarget_for_each_device ( | starget, | |
data, | ||
fn) ; |
struct scsi_target * starget
;void * data
;void (*fn)
(
struct scsi_device *, void *)
;__starget_for_each_device — helper to walk all devices of a target (UNLOCKED)
void fsfunc__starget_for_each_device ( | starget, | |
data, | ||
fn) ; |
struct scsi_target * starget
;void * data
;void (*fn)
(
struct scsi_device *, void *)
;starget
target whose devices we want to iterate over.
data
parameter for callback fn
()
fn
callback function that is invoked for each device
__scsi_device_lookup_by_target — find a device given the target (UNLOCKED)
struct scsi_device * fsfunc__scsi_device_lookup_by_target ( | starget, | |
lun) ; |
struct scsi_target * starget
;uint lun
;scsi_device_lookup_by_target — find a device given the target
struct scsi_device * fsfuncscsi_device_lookup_by_target ( | starget, | |
lun) ; |
struct scsi_target * starget
;uint lun
;__scsi_device_lookup — find a device given the host (UNLOCKED)
struct scsi_device * fsfunc__scsi_device_lookup ( | shost, | |
channel, | ||
id, | ||
lun) ; |
struct Scsi_Host * shost
;uint channel
;uint id
;uint lun
;shost
SCSI host pointer
channel
SCSI channel (zero if only one channel)
id
SCSI target number (physical unit number)
lun
SCSI Logical Unit Number
scsi_device_lookup — find a device given the host
struct scsi_device * fsfuncscsi_device_lookup ( | shost, | |
channel, | ||
id, | ||
lun) ; |
struct Scsi_Host * shost
;uint channel
;uint id
;uint lun
;SCSI Common Access Method support functions, for use with HDIO_GETGEO, etc.
scsi_bios_ptable — Read PC partition table out of first sector of device.
unsigned char * fsfuncscsi_bios_ptable ( | dev) ; |
struct block_device * dev
;scsicam_bios_param — Determine geometry of a disk in cylinders/heads/sectors.
int fsfuncscsicam_bios_param ( | bdev, | |
capacity, | ||
ip) ; |
struct block_device * bdev
;sector_t capacity
;int * ip
;bdev
which device
capacity
size of the disk in sectors
ip
return value: ip[0]=heads, ip[1]=sectors, ip[2]=cylinders
scsi_partsize — Parse cylinders/heads/sectors from PC partition table
int fsfuncscsi_partsize ( | buf, | |
capacity, | ||
cyls, | ||
hds, | ||
secs) ; |
unsigned char * buf
;unsigned long capacity
;unsigned int * cyls
;unsigned int * hds
;unsigned int * secs
;buf
partition table, see scsi_bios_ptable
capacity
size of the disk in sectors
cyls
put cylinders here
hds
put heads here
secs
put sectors here
Common SCSI error/timeout handling routines.
scsi_schedule_eh — schedule EH for SCSI host
void fsfuncscsi_schedule_eh ( | shost) ; |
struct Scsi_Host * shost
;scsi_block_when_processing_errors — Prevent cmds from being queued.
int fsfuncscsi_block_when_processing_errors ( | sdev) ; |
struct scsi_device * sdev
;scsi_eh_prep_cmnd — Save a scsi command info as part of error recovery
void fsfuncscsi_eh_prep_cmnd ( | scmd, | |
ses, | ||
cmnd, | ||
cmnd_size, | ||
sense_bytes) ; |
struct scsi_cmnd * scmd
;struct scsi_eh_save * ses
;unsigned char * cmnd
;int cmnd_size
;unsigned sense_bytes
;scmd
SCSI command structure to hijack
ses
structure to save restore information
cmnd
CDB to send. Can be NULL if no new cmnd is needed
cmnd_size
size in bytes of cmnd
(must be <= BLK_MAX_CDB)
sense_bytes
size of sense data to copy. or 0 (if != 0 cmnd
is ignored)
This function is used to save a scsi command information before re-execution
as part of the error recovery process. If sense_bytes
is 0 the command
sent must be one that does not transfer any data. If sense_bytes
!= 0
cmnd
is ignored and this functions sets up a REQUEST_SENSE command
and cmnd buffers to read sense_bytes
into scmd
->sense_buffer.
scsi_eh_restore_cmnd — Restore a scsi command info as part of error recovery
void fsfuncscsi_eh_restore_cmnd ( | scmd, | |
ses) ; |
struct scsi_cmnd * scmd
;struct scsi_eh_save * ses
;scsi_eh_finish_cmd — Handle a cmd that eh is finished with.
void fsfuncscsi_eh_finish_cmd ( | scmd, | |
done_q) ; |
struct scsi_cmnd * scmd
;struct list_head * done_q
;We don't want to use the normal command completion while we are are still handling errors - it may cause other commands to be queued, and that would disturb what we are doing. Thus we really want to keep a list of pending commands for final completion, and once we are ready to leave error handling we handle completion for real.
scsi_eh_get_sense — Get device sense data.
int fsfuncscsi_eh_get_sense ( | work_q, | |
done_q) ; |
struct list_head * work_q
;struct list_head * done_q
;See if we need to request sense information. if so, then get it now, so we have a better idea of what to do.
This has the unfortunate side effect that if a shost adapter does not automatically request sense information, we end up shutting it down before we request it.
All drivers should request sense information internally these days, so for now all I have to say is tough noogies if you end up in here.
scsi_eh_ready_devs — check device ready state and recover if not.
void fsfuncscsi_eh_ready_devs ( | shost, | |
work_q, | ||
done_q) ; |
struct Scsi_Host * shost
;struct list_head * work_q
;struct list_head * done_q
;scsi_eh_flush_done_q — finish processed commands or retry them.
void fsfuncscsi_eh_flush_done_q ( | done_q) ; |
struct list_head * done_q
;scsi_normalize_sense — normalize main elements from either fixed or descriptor sense data format into a common format.
int fsfuncscsi_normalize_sense ( | sense_buffer, | |
sb_len, | ||
sshdr) ; |
const u8 * sense_buffer
;int sb_len
;struct scsi_sense_hdr * sshdr
;sense_buffer
byte array containing sense data returned by device
sb_len
number of valid bytes in sense_buffer
sshdr
pointer to instance of structure that common elements are written to.
scsi_sense_desc_find — search for a given descriptor type in descriptor sense data format.
const u8 * fsfuncscsi_sense_desc_find ( | sense_buffer, | |
sb_len, | ||
desc_type) ; |
const u8 * sense_buffer
;int sb_len
;int desc_type
;scsi_get_sense_info_fld — get information field from sense data (either fixed or descriptor format)
int fsfuncscsi_get_sense_info_fld ( | sense_buffer, | |
sb_len, | ||
info_out) ; |
const u8 * sense_buffer
;int sb_len
;u64 * info_out
;Manage scsi_dev_info_list, which tracks blacklisted and whitelisted devices.
scsi_dev_info_list_add — add one dev_info list entry.
int fsfuncscsi_dev_info_list_add ( | compatible, | |
vendor, | ||
model, | ||
strflags, | ||
flags) ; |
int compatible
;char * vendor
;char * model
;char * strflags
;int flags
;compatible
if true, null terminate short strings. Otherwise space pad.
vendor
vendor string
model
model (product) string
strflags
integer string
flags
if strflags NULL, use this flag value
scsi_dev_info_list_add_str — parse dev_list and add to the scsi_dev_info_list.
int fsfuncscsi_dev_info_list_add_str ( | dev_list) ; |
char * dev_list
;scsi_get_device_flags — get device specific flags from the dynamic device list.
int fsfuncscsi_get_device_flags ( | sdev, | |
vendor, | ||
model) ; |
struct scsi_device * sdev
;const unsigned char * vendor
;const unsigned char * model
;Handle ioctl() calls for SCSI devices.
scsi_ioctl — Dispatch ioctl to scsi device
int fsfuncscsi_ioctl ( | sdev, | |
cmd, | ||
arg) ; |
struct scsi_device * sdev
;int cmd
;void __user * arg
;SCSI queuing library.
scsi_execute — insert request and wait for the result
int fsfuncscsi_execute ( | sdev, | |
cmd, | ||
data_direction, | ||
buffer, | ||
bufflen, | ||
sense, | ||
timeout, | ||
retries, | ||
flags, | ||
resid) ; |
struct scsi_device * sdev
;const unsigned char * cmd
;int data_direction
;void * buffer
;unsigned bufflen
;unsigned char * sense
;int timeout
;int retries
;int flags
;int * resid
;scsi_mode_select — issue a mode select
int fsfuncscsi_mode_select ( | sdev, | |
pf, | ||
sp, | ||
modepage, | ||
buffer, | ||
len, | ||
timeout, | ||
retries, | ||
data, | ||
sshdr) ; |
struct scsi_device * sdev
;int pf
;int sp
;int modepage
;unsigned char * buffer
;int len
;int timeout
;int retries
;struct scsi_mode_data * data
;struct scsi_sense_hdr * sshdr
;sdev
SCSI device to be queried
pf
Page format bit (1 == standard, 0 == vendor specific)
sp
Save page bit (0 == don't save, 1 == save)
modepage
mode page being requested
buffer
request buffer (may not be smaller than eight bytes)
len
length of request buffer.
timeout
command timeout
retries
number of retries before failing
data
returns a structure abstracting the mode header data
sshdr
place to put sense data (or NULL if no sense to be collected). must be SCSI_SENSE_BUFFERSIZE big.
scsi_mode_sense — issue a mode sense, falling back from 10 to six bytes if necessary.
int fsfuncscsi_mode_sense ( | sdev, | |
dbd, | ||
modepage, | ||
buffer, | ||
len, | ||
timeout, | ||
retries, | ||
data, | ||
sshdr) ; |
struct scsi_device * sdev
;int dbd
;int modepage
;unsigned char * buffer
;int len
;int timeout
;int retries
;struct scsi_mode_data * data
;struct scsi_sense_hdr * sshdr
;sdev
SCSI device to be queried
dbd
set if mode sense will allow block descriptors to be returned
modepage
mode page being requested
buffer
request buffer (may not be smaller than eight bytes)
len
length of request buffer.
timeout
command timeout
retries
number of retries before failing
data
returns a structure abstracting the mode header data
sshdr
place to put sense data (or NULL if no sense to be collected). must be SCSI_SENSE_BUFFERSIZE big.
scsi_test_unit_ready — test if unit is ready
int fsfuncscsi_test_unit_ready ( | sdev, | |
timeout, | ||
retries, | ||
sshdr_external) ; |
struct scsi_device * sdev
;int timeout
;int retries
;struct scsi_sense_hdr * sshdr_external
;scsi_device_set_state — Take the given device through the device state model.
int fsfuncscsi_device_set_state ( | sdev, | |
state) ; |
struct scsi_device * sdev
;enum scsi_device_state state
;sdev_evt_send — send asserted event to uevent thread
void fsfuncsdev_evt_send ( | sdev, | |
evt) ; |
struct scsi_device * sdev
;struct scsi_event * evt
;sdev_evt_alloc — allocate a new scsi event
struct scsi_event * fsfuncsdev_evt_alloc ( | evt_type, | |
gfpflags) ; |
enum scsi_device_event evt_type
;gfp_t gfpflags
;sdev_evt_send_simple — send asserted event to uevent thread
void fsfuncsdev_evt_send_simple ( | sdev, | |
evt_type, | ||
gfpflags) ; |
struct scsi_device * sdev
;enum scsi_device_event evt_type
;gfp_t gfpflags
;scsi_device_quiesce — Block user issued commands.
int fsfuncscsi_device_quiesce ( | sdev) ; |
struct scsi_device * sdev
;This works by trying to transition to the SDEV_QUIESCE state (which must be a legal transition). When the device is in this state, only special requests will be accepted, all others will be deferred. Since special requests may also be requeued requests, a successful return doesn't guarantee the device will be totally quiescent.
Must be called with user context, may sleep.
Returns zero if unsuccessful or an error if not.
scsi_device_resume — Restart user issued commands to a quiesced device.
void fsfuncscsi_device_resume ( | sdev) ; |
struct scsi_device * sdev
;scsi_internal_device_block — internal function to put a device temporarily into the SDEV_BLOCK state
int fsfuncscsi_internal_device_block ( | sdev) ; |
struct scsi_device * sdev
;scsi_internal_device_unblock — resume a device after a block request
int fsfuncscsi_internal_device_unblock ( | sdev, | |
new_state) ; |
struct scsi_device * sdev
;enum scsi_device_state new_state
;scsi_kmap_atomic_sg — find and atomically map an sg-elemnt
void * fsfuncscsi_kmap_atomic_sg ( | sgl, | |
sg_count, | ||
offset, | ||
len) ; |
struct scatterlist * sgl
;int sg_count
;size_t * offset
;size_t * len
;SCSI library functions depending on DMA (map and unmap scatter-gather lists).
The file drivers/scsi/scsi_module.c contains legacy support for old-style host templates. It should never be used by any new driver.
The functions in this file provide an interface between the PROC file system and the SCSI device drivers It is mainly used for debugging, statistics and to pass information directly to the lowlevel driver. I.E. plumbing to manage /proc/scsi/*
scsi_proc_hostdir_add — Create directory in /proc for a scsi host
void fsfuncscsi_proc_hostdir_add ( | sht) ; |
struct scsi_host_template * sht
;scsi_proc_hostdir_rm — remove directory in /proc for a scsi host
void fsfuncscsi_proc_hostdir_rm ( | sht) ; |
struct scsi_host_template * sht
;scsi_proc_host_add — Add entry for this host to appropriate /proc dir
void fsfuncscsi_proc_host_add ( | shost) ; |
struct Scsi_Host * shost
;scsi_proc_host_rm — remove this host's entry from /proc
void fsfuncscsi_proc_host_rm ( | shost) ; |
struct Scsi_Host * shost
;proc_print_scsidevice — return data about this host
int fsfuncproc_print_scsidevice ( | dev, | |
data) ; |
struct device * dev
;void * data
;scsi_add_single_device — Respond to user request to probe for/add device
int fsfuncscsi_add_single_device ( | host, | |
channel, | ||
id, | ||
lun) ; |
uint host
;uint channel
;uint id
;uint lun
;host
user-supplied decimal integer
channel
user-supplied decimal integer
id
user-supplied decimal integer
lun
user-supplied decimal integer
scsi_remove_single_device — Respond to user request to remove a device
int fsfuncscsi_remove_single_device ( | host, | |
channel, | ||
id, | ||
lun) ; |
uint host
;uint channel
;uint id
;uint lun
;proc_scsi_write — handle writes to /proc/scsi/scsi
ssize_t fsfuncproc_scsi_write ( | file, | |
buf, | ||
length, | ||
ppos) ; |
struct file * file
;const char __user * buf
;size_t length
;loff_t * ppos
;proc_scsi_open — glue function
int fsfuncproc_scsi_open ( | inode, | |
file) ; |
struct inode * inode
;struct file * file
;Infrastructure to provide async events from transports to userspace via netlink, using a single NETLINK_SCSITRANSPORT protocol for all transports. See the original patch submission for more details.
scsi_nl_rcv_msg — Receive message handler.
void fsfuncscsi_nl_rcv_msg ( | skb) ; |
struct sk_buff * skb
;Scan a host to determine which (if any) devices are attached. The general scanning/probing algorithm is as follows, exceptions are made to it depending on device specific flags, compilation options, and global variable (boot or module load time) settings. A specific LUN is scanned via an INQUIRY command; if the LUN has a device attached, a scsi_device is allocated and setup for it. For every id of every channel on the given host, start by scanning LUN 0. Skip hosts that don't respond at all to a scan of LUN 0. Otherwise, if LUN 0 has a device attached, allocate and setup a scsi_device for it. If target is SCSI-3 or up, issue a REPORT LUN, and scan all of the LUNs returned by the REPORT LUN; else, sequentially scan LUNs up until some maximum is reached, or a LUN is seen that cannot have a device attached to it.
scsi_complete_async_scans — Wait for asynchronous scans to complete
int fsfuncscsi_complete_async_scans ( | void) ; |
void
;scsi_unlock_floptical — unlock device via a special MODE SENSE command
void fsfuncscsi_unlock_floptical ( | sdev, | |
result) ; |
struct scsi_device * sdev
;unsigned char * result
;scsi_alloc_sdev — allocate and setup a scsi_Device
struct scsi_device * fsfuncscsi_alloc_sdev ( | starget, | |
lun, | ||
hostdata) ; |
struct scsi_target * starget
;unsigned int lun
;void * hostdata
;starget
which target to allocate a scsi_device for
lun
which lun
hostdata
usually NULL and set by ->slave_alloc instead
scsi_alloc_target — allocate a new or find an existing target
struct scsi_target * fsfuncscsi_alloc_target ( | parent, | |
channel, | ||
id) ; |
struct device * parent
;int channel
;uint id
;scsi_target_reap — check to see if target is in use and destroy if not
void fsfuncscsi_target_reap ( | starget) ; |
struct scsi_target * starget
;sanitize_inquiry_string — remove non-graphical chars from an INQUIRY result string
void fsfuncsanitize_inquiry_string ( | s, | |
len) ; |
unsigned char * s
;int len
;The SCSI spec says that INQUIRY vendor, product, and revision strings must consist entirely of graphic ASCII characters, padded on the right with spaces. Since not all devices obey this rule, we will replace non-graphic or non-ASCII characters with spaces. Exception: a NUL character is interpreted as a string terminator, so all the following characters are set to spaces.
scsi_probe_lun — probe a single LUN using a SCSI INQUIRY
int fsfuncscsi_probe_lun ( | sdev, | |
inq_result, | ||
result_len, | ||
bflags) ; |
struct scsi_device * sdev
;unsigned char * inq_result
;int result_len
;int * bflags
;scsi_add_lun — allocate and fully initialze a scsi_device
int fsfuncscsi_add_lun ( | sdev, | |
inq_result, | ||
bflags, | ||
async) ; |
struct scsi_device * sdev
;unsigned char * inq_result
;int * bflags
;int async
;scsi_inq_str — print INQUIRY data from min to max index, strip trailing whitespace
unsigned char * fsfuncscsi_inq_str ( | buf, | |
inq, | ||
first, | ||
end) ; |
unsigned char * buf
;unsigned char * inq
;unsigned first
;unsigned end
;scsi_probe_and_add_lun — probe a LUN, if a LUN is found add it
int fsfuncscsi_probe_and_add_lun ( | starget, | |
lun, | ||
bflagsp, | ||
sdevp, | ||
rescan, | ||
hostdata) ; |
struct scsi_target * starget
;uint lun
;int * bflagsp
;struct scsi_device ** sdevp
;int rescan
;void * hostdata
;starget
pointer to target device structure
lun
LUN of target device
bflagsp
store bflags here if not NULL
sdevp
probe the LUN corresponding to this scsi_device
rescan
if nonzero skip some code only needed on first scan
hostdata
passed to scsi_alloc_sdev
scsi_sequential_lun_scan — sequentially scan a SCSI target
void fsfuncscsi_sequential_lun_scan ( | starget, | |
bflags, | ||
scsi_level, | ||
rescan) ; |
struct scsi_target * starget
;int bflags
;int scsi_level
;int rescan
;scsi_report_lun_scan — Scan using SCSI REPORT LUN results
int fsfuncscsi_report_lun_scan ( | starget, | |
bflags, | ||
rescan) ; |
struct scsi_target * starget
;int bflags
;int rescan
;starget
which target
bflags
Zero or a mix of BLIST_NOLUN, BLIST_REPORTLUN2, or BLIST_NOREPORTLUN
rescan
nonzero if we can skip code only needed on first scan
Fast scanning for modern (SCSI-3) devices by sending a REPORT LUN command. Scan the resulting list of LUNs by calling scsi_probe_and_add_lun.
If BLINK_REPORTLUN2 is set, scan a target that supports more than 8 LUNs even if it's older than SCSI-3. If BLIST_NOREPORTLUN is set, return 1 always. If BLIST_NOLUN is set, return 0 always. If starget->no_report_luns is set, return 1 always.
scsi_prep_async_scan — prepare for an async scan
struct async_scan_data * fsfuncscsi_prep_async_scan ( | shost) ; |
struct Scsi_Host * shost
;Set up the sysctl entry: "/dev/scsi/logging_level" (DEV_SCSI_LOGGING_LEVEL) which sets/returns scsi_logging_level.
SCSI sysfs interface routines.
scsi_remove_device — unregister a device from the scsi bus
void fsfuncscsi_remove_device ( | sdev) ; |
struct scsi_device * sdev
;mid to lowlevel SCSI driver interface
scsi_host_set_state — Take the given host through the host state model.
int fsfuncscsi_host_set_state ( | shost, | |
state) ; |
struct Scsi_Host * shost
;enum scsi_host_state state
;scsi_remove_host — remove a scsi host
void fsfuncscsi_remove_host ( | shost) ; |
struct Scsi_Host * shost
;scsi_add_host_with_dma — add a scsi host with dma device
int fsfuncscsi_add_host_with_dma ( | shost, | |
dev, | ||
dma_dev) ; |
struct Scsi_Host * shost
;struct device * dev
;struct device * dma_dev
;shost
scsi host pointer to add
dev
a struct device of type scsi class
dma_dev
dma device for the host
scsi_host_alloc — register a scsi host adapter instance.
struct Scsi_Host * fsfuncscsi_host_alloc ( | sht, | |
privsize) ; |
struct scsi_host_template * sht
;int privsize
;scsi_host_lookup — get a reference to a Scsi_Host by host no
struct Scsi_Host * fsfuncscsi_host_lookup ( | hostnum) ; |
unsigned short hostnum
;scsi_host_get — inc a Scsi_Host ref count
struct Scsi_Host * fsfuncscsi_host_get ( | shost) ; |
struct Scsi_Host * shost
;scsi_host_put — dec a Scsi_Host ref count
void fsfuncscsi_host_put ( | shost) ; |
struct Scsi_Host * shost
;Transport classes are service libraries for drivers in the SCSI lower layer, which expose transport attributes in sysfs.
The file drivers/scsi/scsi_transport_fc.c defines transport attributes for Fibre Channel.
fc_get_event_number — Obtain the next sequential FC event number
u32 fsfuncfc_get_event_number ( | void) ; |
void
;fc_host_post_event — called to post an even on an fc_host.
void fsfuncfc_host_post_event ( | shost, | |
event_number, | ||
event_code, | ||
event_data) ; |
struct Scsi_Host * shost
;u32 event_number
;enum fc_host_event_code event_code
;u32 event_data
;fc_host_post_vendor_event — called to post a vendor unique event on an fc_host
void fsfuncfc_host_post_vendor_event ( | shost, | |
event_number, | ||
data_len, | ||
data_buf, | ||
vendor_id) ; |
struct Scsi_Host * shost
;u32 event_number
;u32 data_len
;char * data_buf
;u64 vendor_id
;fc_remove_host — called to terminate any fc_transport-related elements for a scsi host.
void fsfuncfc_remove_host ( | shost) ; |
struct Scsi_Host * shost
;
This routine is expected to be called immediately preceding the
a driver's call to scsi_remove_host
.
fc_remote_port_add — notify fc transport of the existence of a remote FC port.
struct fc_rport * fsfuncfc_remote_port_add ( | shost, | |
channel, | ||
ids) ; |
struct Scsi_Host * shost
;int channel
;struct fc_rport_identifiers * ids
;shost
scsi host the remote port is connected to.
channel
Channel on shost port connected to.
ids
The world wide names, fc address, and FC4 port roles for the remote port.
The LLDD calls this routine to notify the transport of the existence of a remote port. The LLDD provides the unique identifiers (wwpn,wwn) of the port, it's FC address (port_id), and the FC4 roles that are active for the port.
For ports that are FCP targets (aka scsi targets), the FC transport maintains consistent target id bindings on behalf of the LLDD. A consistent target id binding is an assignment of a target id to a remote port identifier, which persists while the scsi host is attached. The remote port can disappear, then later reappear, and it's target id assignment remains the same. This allows for shifts in FC addressing (if binding by wwpn or wwnn) with no apparent changes to the scsi subsystem which is based on scsi host number and target id values. Bindings are only valid during the attachment of the scsi host. If the host detaches, then later re-attaches, target id bindings may change.
This routine is responsible for returning a remote port structure. The routine will search the list of remote ports it maintains internally on behalf of consistent target id mappings. If found, the remote port structure will be reused. Otherwise, a new remote port structure will be allocated.
Whenever a remote port is allocated, a new fc_remote_port class device is created.
Should not be called from interrupt context.
fc_remote_port_delete — notifies the fc transport that a remote port is no longer in existence.
void fsfuncfc_remote_port_delete ( | rport) ; |
struct fc_rport * rport
;The LLDD calls this routine to notify the transport that a remote port is no longer part of the topology. Note: Although a port may no longer be part of the topology, it may persist in the remote ports displayed by the fc_host. We do this under 2 conditions: 1) If the port was a scsi target, we delay its deletion by “blocking” it. This allows the port to temporarily disappear, then reappear without disrupting the SCSI device tree attached to it. During the “blocked” period the port will still exist. 2) If the port was a scsi target and disappears for longer than we expect, we'll delete the port and the tear down the SCSI device tree attached to it. However, we want to semi-persist the target id assigned to that port if it eventually does exist. The port structure will remain (although with minimal information) so that the target id bindings remails.
If the remote port is not an FCP Target, it will be fully torn down and deallocated, including the fc_remote_port class device.
If the remote port is an FCP Target, the port will be placed in a temporary blocked state. From the LLDD's perspective, the rport no longer exists. From the SCSI midlayer's perspective, the SCSI target exists, but all sdevs on it are blocked from further I/O. The following is then expected.
If the remote port does not return (signaled by a LLDD call to
fc_remote_port_add
) within the dev_loss_tmo timeout, then the
scsi target is removed - killing all outstanding i/o and removing the
scsi devices attached ot it. The port structure will be marked Not
Present and be partially cleared, leaving only enough information to
recognize the remote port relative to the scsi target id binding if
it later appears. The port will remain as long as there is a valid
binding (e.g. until the user changes the binding type or unloads the
scsi host with the binding).
If the remote port returns within the dev_loss_tmo value (and matches according to the target id binding type), the port structure will be reused. If it is no longer a SCSI target, the target will be torn down. If it continues to be a SCSI target, then the target will be unblocked (allowing i/o to be resumed), and a scan will be activated to ensure that all luns are detected.
Called from normal process context only - cannot be called from interrupt.
fc_remote_port_rolechg — notifies the fc transport that the roles on a remote may have changed.
void fsfuncfc_remote_port_rolechg ( | rport, | |
roles) ; |
struct fc_rport * rport
;u32 roles
;The LLDD calls this routine to notify the transport that the roles on a remote port may have changed. The largest effect of this is if a port now becomes a FCP Target, it must be allocated a scsi target id. If the port is no longer a FCP target, any scsi target id value assigned to it will persist in case the role changes back to include FCP Target. No changes in the scsi midlayer will be invoked if the role changes (in the expectation that the role will be resumed. If it doesn't normal error processing will take place).
Should not be called from interrupt context.
fc_block_scsi_eh — Block SCSI eh thread for blocked fc_rport
int fsfuncfc_block_scsi_eh ( | cmnd) ; |
struct scsi_cmnd * cmnd
;This routine can be called from a FC LLD scsi_eh callback. It blocks the scsi_eh thread until the fc_rport leaves the FC_PORTSTATE_BLOCKED, or the fast_io_fail_tmo fires. This is necessary to avoid the scsi_eh failing recovery actions for blocked rports which would lead to offlined SCSI devices.
fc_vport_create — Admin App or LLDD requests creation of a vport
struct fc_vport * fsfuncfc_vport_create ( | shost, | |
channel, | ||
ids) ; |
struct Scsi_Host * shost
;int channel
;struct fc_vport_identifiers * ids
;The file drivers/scsi/scsi_transport_iscsi.c defines transport attributes for the iSCSI class, which sends SCSI packets over TCP/IP connections.
iscsi_create_flashnode_sess — Add flashnode session entry in sysfs
struct iscsi_bus_flash_session * fsfunciscsi_create_flashnode_sess ( | shost, | |
index, | ||
transport, | ||
dd_size) ; |
struct Scsi_Host * shost
;int index
;struct iscsi_transport * transport
;int dd_size
;iscsi_create_flashnode_conn — Add flashnode conn entry in sysfs
struct iscsi_bus_flash_conn * fsfunciscsi_create_flashnode_conn ( | shost, | |
fnode_sess, | ||
transport, | ||
dd_size) ; |
struct Scsi_Host * shost
;struct iscsi_bus_flash_session * fnode_sess
;struct iscsi_transport * transport
;int dd_size
;iscsi_is_flashnode_conn_dev — verify passed device is to be flashnode conn
int fsfunciscsi_is_flashnode_conn_dev ( | dev, | |
data) ; |
struct device * dev
;void * data
;iscsi_find_flashnode_sess — finds flashnode session entry
struct device * fsfunciscsi_find_flashnode_sess ( | shost, | |
data, | ||
fn) ; |
struct Scsi_Host * shost
;void * data
;int (*fn)
(
struct device *dev, void *data)
;shost
pointer to host data
data
pointer to data containing value to use for comparison
fn
function pointer that does actual comparison
iscsi_find_flashnode_conn — finds flashnode connection entry
struct device * fsfunciscsi_find_flashnode_conn ( | fnode_sess) ; |
struct iscsi_bus_flash_session * fnode_sess
;iscsi_destroy_flashnode_sess — destory flashnode session entry
void fsfunciscsi_destroy_flashnode_sess ( | fnode_sess) ; |
struct iscsi_bus_flash_session * fnode_sess
;iscsi_destroy_all_flashnode — destory all flashnode session entries
void fsfunciscsi_destroy_all_flashnode ( | shost) ; |
struct Scsi_Host * shost
;iscsi_scan_finished — helper to report when running scans are done
int fsfunciscsi_scan_finished ( | shost, | |
time) ; |
struct Scsi_Host * shost
;unsigned long time
;iscsi_block_scsi_eh — block scsi eh until session state has transistioned
int fsfunciscsi_block_scsi_eh ( | cmd) ; |
struct scsi_cmnd * cmd
;iscsi_unblock_session — set a session as logged in and start IO.
void fsfunciscsi_unblock_session ( | session) ; |
struct iscsi_cls_session * session
;iscsi_create_session — create iscsi class session
struct iscsi_cls_session * fsfunciscsi_create_session ( | shost, | |
transport, | ||
dd_size, | ||
target_id) ; |
struct Scsi_Host * shost
;struct iscsi_transport * transport
;int dd_size
;unsigned int target_id
;iscsi_destroy_session — destroy iscsi session
int fsfunciscsi_destroy_session ( | session) ; |
struct iscsi_cls_session * session
;iscsi_create_conn — create iscsi class connection
struct iscsi_cls_conn * fsfunciscsi_create_conn ( | session, | |
dd_size, | ||
cid) ; |
struct iscsi_cls_session * session
;int dd_size
;uint32_t cid
;This can be called from a LLD or iscsi_transport. The connection is child of the session so cid must be unique for all connections on the session.
Since we do not support MCS, cid will normally be zero. In some cases for software iscsi we could be trying to preallocate a connection struct in which case there could be two connection structs and cid would be non-zero.
The file drivers/scsi/scsi_transport_sas.c defines transport attributes for Serial Attached SCSI, a variant of SATA aimed at large high-end systems.
The SAS transport class contains common code to deal with SAS HBAs, an aproximated representation of SAS topologies in the driver model, and various sysfs attributes to expose these topologies and management interfaces to userspace.
In addition to the basic SCSI core objects this transport class introduces two additional intermediate objects: The SAS PHY as represented by struct sas_phy defines an "outgoing" PHY on a SAS HBA or Expander, and the SAS remote PHY represented by struct sas_rphy defines an "incoming" PHY on a SAS Expander or end device. Note that this is purely a software concept, the underlying hardware for a PHY and a remote PHY is the exactly the same.
There is no concept of a SAS port in this code, users can see what PHYs form a wide port based on the port_identifier attribute, which is the same for all PHYs in a port.
sas_remove_children — tear down a devices SAS data structures
void fsfuncsas_remove_children ( | dev) ; |
struct device * dev
;sas_remove_host — tear down a Scsi_Host's SAS data structures
void fsfuncsas_remove_host ( | shost) ; |
struct Scsi_Host * shost
;sas_tlr_supported — checking TLR bit in vpd 0x90
unsigned int fsfuncsas_tlr_supported ( | sdev) ; |
struct scsi_device * sdev
;sas_disable_tlr — setting TLR flags
void fsfuncsas_disable_tlr ( | sdev) ; |
struct scsi_device * sdev
;sas_enable_tlr — setting TLR flags
void fsfuncsas_enable_tlr ( | sdev) ; |
struct scsi_device * sdev
;sas_phy_alloc — allocates and initialize a SAS PHY structure
struct sas_phy * fsfuncsas_phy_alloc ( | parent, | |
number) ; |
struct device * parent
;int number
;sas_phy_add — add a SAS PHY to the device hierarchy
int fsfuncsas_phy_add ( | phy) ; |
struct sas_phy * phy
;scsi_is_sas_phy — check if a struct device represents a SAS PHY
int fsfuncscsi_is_sas_phy ( | dev) ; |
const struct device * dev
;sas_port_add — add a SAS port to the device hierarchy
int fsfuncsas_port_add ( | port) ; |
struct sas_port * port
;sas_port_free — free a SAS PORT
void fsfuncsas_port_free ( | port) ; |
struct sas_port * port
;sas_port_delete — remove SAS PORT
void fsfuncsas_port_delete ( | port) ; |
struct sas_port * port
;scsi_is_sas_port — check if a struct device represents a SAS port
int fsfuncscsi_is_sas_port ( | dev) ; |
const struct device * dev
;sas_port_get_phy — try to take a reference on a port member
struct sas_phy * fsfuncsas_port_get_phy ( | port) ; |
struct sas_port * port
;sas_port_add_phy — add another phy to a port to form a wide port
void fsfuncsas_port_add_phy ( | port, | |
phy) ; |
struct sas_port * port
;struct sas_phy * phy
;When a port is initially created, it is empty (has no phys). All ports must have at least one phy to operated, and all wide ports must have at least two. The current code makes no difference between ports and wide ports, but the only object that can be connected to a remote device is a port, so ports must be formed on all devices with phys if they're connected to anything.
sas_port_delete_phy — remove a phy from a port or wide port
void fsfuncsas_port_delete_phy ( | port, | |
phy) ; |
struct sas_port * port
;struct sas_phy * phy
;sas_end_device_alloc — allocate an rphy for an end device
struct sas_rphy * fsfuncsas_end_device_alloc ( | parent) ; |
struct sas_port * parent
;sas_expander_alloc — allocate an rphy for an end device
struct sas_rphy * fsfuncsas_expander_alloc ( | parent, | |
type) ; |
struct sas_port * parent
;enum sas_device_type type
;sas_rphy_add — add a SAS remote PHY to the device hierarchy
int fsfuncsas_rphy_add ( | rphy) ; |
struct sas_rphy * rphy
;sas_rphy_free — free a SAS remote PHY
void fsfuncsas_rphy_free ( | rphy) ; |
struct sas_rphy * rphy
;sas_rphy_delete — remove and free SAS remote PHY
void fsfuncsas_rphy_delete ( | rphy) ; |
struct sas_rphy * rphy
;sas_rphy_unlink — unlink SAS remote PHY
void fsfuncsas_rphy_unlink ( | rphy) ; |
struct sas_rphy * rphy
;sas_rphy_remove — remove SAS remote PHY
void fsfuncsas_rphy_remove ( | rphy) ; |
struct sas_rphy * rphy
;scsi_is_sas_rphy — check if a struct device represents a SAS remote PHY
int fsfuncscsi_is_sas_rphy ( | dev) ; |
const struct device * dev
;The SATA transport is handled by libata, which has its own book of documentation in this directory.
The file drivers/scsi/scsi_transport_spi.c defines transport attributes for traditional (fast/wide/ultra) SCSI busses.
spi_schedule_dv_device — schedule domain validation to occur on the device
void fsfuncspi_schedule_dv_device ( | sdev) ; |
struct scsi_device * sdev
;The file drivers/scsi/scsi_transport_srp.c defines transport attributes for SCSI over Remote Direct Memory Access.
srp_rport_add — add a SRP remote port to the device hierarchy
struct srp_rport * fsfuncsrp_rport_add ( | shost, | |
ids) ; |
struct Scsi_Host * shost
;struct srp_rport_identifiers * ids
;srp_rport_del — remove a SRP remote port
void fsfuncsrp_rport_del ( | rport) ; |
struct srp_rport * rport
;srp_remove_host — tear down a Scsi_Host's SRP data structures
void fsfuncsrp_remove_host ( | shost) ; |
struct Scsi_Host * shost
;Table of Contents
Many modern device controllers use the SCSI command set as a protocol to communicate with their devices through many different types of physical connections.
In SCSI language a bus capable of carrying SCSI commands is called a "transport", and a controller connecting to such a bus is called a "host bus adapter" (HBA).
The file drivers/scsi/scsi_debug.c simulates a host adapter with a variable number of disks (or disk like devices) attached, sharing a common amount of RAM. Does a lot of checking to make sure that we are not getting blocks mixed up, and panics the kernel if anything out of the ordinary is seen.
To be more realistic, the simulated devices have the transport attributes of SAS disks.
For documentation see http://sg.danny.cz/sg/sdebug26.html