📄 scsi_mid_low_api.txt
字号:
* 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 '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 'done' * callback is executed. Note: the driver may call done before * returning zero, but after it has called 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 done * callback at any time. * * Locks: struct Scsi_Host::host_lock held on entry (with "irqsave") * and is expected to be held on return. * * 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 '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 'done' callback may be invoked before this function returns. * If the '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 * '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_cmnd * scp, void (*done)(struct scsi_cmnd *))/** * release - release all resources associated with given host * @shp: host to be released. * * Return value ignored (could soon be a function returning void). * * Locks: none held * * Calling context: process * * Notes: Invoked from scsi_module.c's exit_this_scsi_driver(). * LLD's implementation of this function should call * scsi_unregister(shp) prior to returning. * Only needed for old-style host templates. * * Defined in: LLD (required in "passive initialization model", * should not be defined in hotplug model) **/ int release(struct Scsi_Host * shp)/** * 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 istypically initialized as a file scope static in a driver's header file. Thatway 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 LLDcontrols. The struct Scsi_Host structure has many members in commonwith "struct scsi_host_template". When a new struct Scsi_Host instanceis created (in scsi_host_alloc() in hosts.c) those common members areinitialized from the driver's struct scsi_host_template instance. Membersof 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. 0 implies scatter gather not supported by host 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_adjust_queue_depth(). unchecked_isa_dma - 1=>only use bottom 16 MB of ram (ISA DMA addressing restriction), 0=>can use full 32 bit (or better) DMA address space use_clustering - 1=>SCSI commands in mid level's queue can be merged, 0=>disallow SCSI command merging 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().The scsi_host structure is defined in include/scsi/scsi_host.hstruct scsi_device------------------Generally, there is one instance of this structure for each SCSI logical uniton a host. Scsi devices connected to a host are uniquely identified by achannel number, target id and logical unit number (lun).The structure is defined in include/scsi/scsi_device.hstruct scsi_cmnd----------------Instances of this structure convey SCSI commands to the LLD and responsesback to the mid level. The SCSI mid level will ensure that no more SCSIcommands become queued against the LLD than are indicated byscsi_adjust_queue_depth() (or struct Scsi_Host::cmd_per_lun). There willbe 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/asm/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 4 related bytes. The SCSI status value is in the LSB. See include/scsi/scsi.h status_byte(), msg_byte(), host_byte() and driver_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 device (i.e. 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'.The scsi_cmnd structure is defined in include/scsi/scsi_cmnd.hLocks=====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 pointeris initialized to point at default_lock. Thereafter lock and unlockoperations performed by the mid level use the struct Scsi_Host::host_lockpointer. Previously drivers could override the host_lock pointer butthis is not allowed anymore.Autosense=========Autosense (or auto-sense) is defined in the SAM-2 document as "theautomatic return of sense data to the application client coincidentwith the completion of a SCSI command" when a status of CHECK CONDITIONoccurs. LLDs should perform autosense. This should be done when the LLDdetects 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 itselfEither way, when a status of CHECK CONDITION is detected, the mid leveldecides 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 (andthis byte is initialized to 0 before each command) then the mid level willissue a REQUEST SENSE command.In the presence of queued commands the "nexus" that maintains sensebuffer data from the command that failed until a following REQUEST SENSEmay get out of synchronization. This is why it is best for the LLDto 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 isone per SCSI host.The older error handling mechanism has been removed. This means theLLD 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/Kconfigfile 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 functionsto 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 steeleye 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 Gilbertdgilbert at interlog dot com21st September 2004
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -