📄 writingscsi driver.htm
字号:
<html><head><title>Writing a SCSI Device Driver</title>
<link rel="owner" href="mailto:">
<script language="JavaScript">
<!-- hide this
function help(message) {
self.status = message;
return true;
}
// stop hiding -->
</script></head>
<body>
<strong>The
HyperNews <a href="http://tldp.org/LDP/khg/HyperNews/get/khg.html">Linux KHG</a>
Discussion Pages</strong>
<hr>
<h3>Writing a SCSI Device Driver</h3>
<p>Copyright (C) 1993 Rickard E. Faith (faith@cs.unc.edu).<br>
Written at the University of North Carolina, 1993, for COMP-291.
The information contained herein comes with ABSOLUTELY NO WARRANTY.<br>
All rights reserved. Permission is granted to make and
distribute verbatim copies of this paper provided the copyright
notice and this permission notice are preserved on all copies.
</p><p><font size="-2">This is (with the author's explicit permission)
a modified copy of the original document. If you wish to
reproduce this document, you are advised to get the
original version by ftp from
<a href="ftp://ftp.cs.unc.edu/pub/users/faith/papers/scsi.paper.tar.gz">
ftp://ftp.cs.unc.edu/pub/users/faith/papers/scsi.paper.tar.gz</a></font>
</p><p><b>[Note that this document has not been revised since its
copyright date of 1993. Most things still apply, but some of the
facts like the list of currently supported SCSI host adaptors are
rather out of date by now.]</b>
</p><h4>Why You Want to Write a SCSI Driver</h4>
<p>Currently, the Linux kernel contains drivers for the
following SCSI host adapters: Adaptec 1542, Adaptec 1740,
Future Domain TMC-1660/TMC-1680, Seagate ST-01/ST-02, UltraStor
14F, and Western Digital WD-7000. You may want to write your
own driver for an unsupported host adapter. You may also want
to re-write or update one of the existing drivers.
</p><h4>What is SCSI?</h4>
The foreword to the SCSI-2 standard draft [ANS] gives a
succinct definition of the Small Computer System Interface and briefly
explains how SCSI-2 is related to SCSI-1 and CCS:
<blockquote>
The SCSI protocol is designed to provide an efficient peer-to-peer I/O
bus with up to 8 devices, including one or more hosts. Data may be
transferred asynchronously at rates that only depend on device
implementation and cable length. Synchronous data transfers are
supported at rates up to 10 mega-transfers per second. With the 32 bit
wide data transfer option, data rates of up to 40 megabytes per second
are possible.
<p>SCSI-2 includes command sets for magnetic and optical disks, tapes,
printers, processors, CD-ROMs, scanners, medium changers, and
communications devices.
</p><p>In 1985, when the first SCSI standard was being finalized as an
American National Standard, several manufacturers approached the X3T9.2
Task Group. They wanted to increase the mandatory requirements of SCSI
and to define further features for direct-access devices. Rather than
delay the SCSI standard, X3T9.2 formed an ad hoc group to develop a
working paper that was eventually called the Common Command Set
(CCS). Many disk products were designed using this working paper in
conjunction with the SCSI standard.
</p><p>In parallel with the development of the CCS working paper, X3T9.2 began
work on an enhanced SCSI standard which was named SCSI-2. SCSI-2
included the results of the CCS working paper and extended them to all
device types. It also added caching commands, performance enhancement
features, and other functions that X3T9.2 deemed worthwhile. While
SCSI-2 has gone well beyond the original SCSI standard (now referred to
as SCSI-1), it retains a high degree of compatibility with SCSI-1
devices.
</p></blockquote>
<h4>SCSI phases</h4>
<a name="sec:status"></a>
<a name="sec:message"></a>
The ``SCSI bus'' transfers data and state information between
interconnected SCSI devices. A single transaction between an ``initiator''
and a ``target'' can involve up to 8 distinct ``phases.'' These phases are
almost entirely determined by the target (e.g., the hard disk drive). The
current phase can be determined from an examination of five SCSI bus
signals, as shown in this table [LXT91, p. 57].
<table border="1">
<tbody><tr><td>-SEL</td><td>-BSY</td><td>-MSG</td><td>-C/D</td><td>-I/O</td><td>PHASE</td></tr>
<tr><td>HI</td><td>HI</td><td>?</td><td>?</td><td>?</td><td>BUS FREE</td></tr>
<tr><td>HI</td><td>LO</td><td>?</td><td>?</td><td>?</td><td>ARBITRATION</td></tr>
<tr><td>I</td><td>I&T</td><td>?</td><td>?</td><td>?</td><td>SELECTION</td></tr>
<tr><td>T</td><td>I&T</td><td>?</td><td>?</td><td>?</td><td>RESELECTION</td></tr>
<tr><td>HI</td><td>LO</td><td>HI</td><td>HI</td><td>HI</td><td>DATA OUT</td></tr>
<tr><td>HI</td><td>LO</td><td>HI</td><td>HI</td><td>LO</td><td>DATA IN</td></tr>
<tr><td>HI</td><td>LO</td><td>HI</td><td>LO</td><td>HI</td><td>COMMAND</td></tr>
<tr><td>HI</td><td>LO</td><td>HI</td><td>LO</td><td>LO</td><td>STATUS</td></tr>
<tr><td>HI</td><td>LO</td><td>LO</td><td>LO</td><td>HI</td><td>MESSAGE OUT</td></tr>
<tr><td>HI</td><td>LO</td><td>LO</td><td>LO</td><td>LO</td><td>MESSAGE IN</td></tr>
</tbody></table><font size="-3">I = Initiator Asserts, T = Target Asserts, ? = HI or LO</font>
<p>Some controllers (notably the inexpensive Seagate
controller) require direct manipulation of the SCSI bus--other
controllers automatically handle these low-level details. Each
of the eight phases will be described in detail.
</p><dl>
<dt>BUS FREE Phase
</dt><dd>The BUS FREE phase indicates that the SCSI bus is
idle and is not currently being used.
</dd><dt>ARBITRATION Phase
</dt><dd>The ARBITRATION phase is entered when a SCSI
device attempts to gain control of the SCSI bus. Arbitration can start
only if the bus was previously in the BUS FREE phase. During
arbitration, the arbitrating device asserts its SCSI ID on the DATA
BUS. For example, if the arbitrating device's SCSI ID is 2, then the
device will assert <tt>0x04</tt>. If multiple devices attempt
simultaneous arbitration, the device with the highest SCSI ID will win.
Although ARBITRATION is optional in the SCSI-1 standard, it is a required
phase in the SCSI-2 standard.
</dd><dt>SELECTION Phase
</dt><dd>After ARBITRATION, the arbitrating device (now
called the initiator) asserts the SCSI ID of the target on the DATA
BUS. The target, if present, will acknowledge the selection by raising
the -BSY line. This line remains active as long as the target is
connected to the initiator.
</dd><dt>RESELECTION Phase
</dt><dd>The SCSI protocol allows a device to disconnect
from the bus while processing a request. When the device is ready, it
reconnects to the host adapter. The RESELECTION phase is identical to
the SELECTION phase, with the exception that it is used by the
disconnected target to reconnect to the original initiator. Drivers
which do not currently support RESELECTION do not allow the SCSI target
to disconnect. RESELECTION should be supported by all drivers, however,
so that multiple SCSI devices can simultaneously process commands. This
allows dramatically increased throughput due to interleaved I/O requests.
</dd><dt>COMMAND Phase
</dt><dd>During this phase, 6, 10, or 12 bytes of command
information are transferred from the initiator to the target.
</dd><dt>DATA OUT and DATA IN Phases
</dt><dd>During these phases, data are
transferred between the initiator and the target. For example, the DATA
OUT phase transfers data from the host adapter to the disk drive. The
DATA IN phase transfers data from the disk drive to the host adapter. If
the SCSI command does not require data transfer, then neither phase is
entered.
</dd><dt>STATUS Phase
</dt><dd>This phase is entered after completion of all commands,
and allows the target to send a status byte to the initiator. There are
nine valid status bytes, as shown in the table below
[ANS, p. 77]. Note that since bits 1-5 (bit 0 is the
least significant bit) are used for the status code (the other
bits are reserved), the status byte should be masked with <tt>0x3e</tt>
before being examined.
<table border="1">
<tbody><tr><th>Value*</th><th>Status</th></tr>
<tr><td>0x00</td><td>GOOD</td></tr>
<tr><td>0x02</td><td>CHECK CONDITION</td></tr>
<tr><td>0x04</td><td>CONDITION MET</td></tr>
<tr><td>0x08</td><td>BUSY</td></tr>
<tr><td>0x10</td><td>INTERMEDIATE</td></tr>
<tr><td>0x14</td><td>INTERMEDIATE-CONDITION MET</td></tr>
<tr><td>0x18</td><td>RESERVATION CONFLICT</td></tr>
<tr><td>0x22</td><td>COMMAND TERMINATED</td></tr>
<tr><td>0x28</td><td>QUEUE FULL</td></tr>
</tbody></table><font size="-3">*After masking with 0x3e</font>
<p>The meanings of the three most important status codes are outlined below:
</p><dl>
<dt>GOOD
</dt><dd>The operation completed successfully.
</dd><dt>CHECK CONDITION
</dt><dd>An error occurred. The REQUEST SENSE command
should be used to find out more information about the error (see
<a href="#sec:scsi.commands">SCSI Commands</a>).
</dd><dt>BUSY
</dt><dd>The device was unable to accept a command. This may occur
during a self-test or shortly after power-up.
</dd></dl>
</dd><dt>MESSAGE OUT and MESSAGE IN Phases
</dt><dd>Additional information is
transferred between the target and the initiator. This information may
regard the status of an outstanding command, or may be a request for a
change of protocol. Multiple MESSAGE IN and MESSAGE OUT phases may occur
during a single SCSI transaction. If RESELECTION is supported, the
driver must be able to correctly process the SAVE DATA POINTERS, RESTORE
POINTERS, and DISCONNECT messages. Although required by the SCSI-2
standard, some devices do not automatically send a SAVE DATA POINTERS
message prior to a DISCONNECT message.
</dd></dl>
<h4>SCSI Commands</h4>
<a name="sec:scsi.commands"></a>
<p>Each SCSI command is 6, 10, or 12 bytes long. The following commands must
be well understood by a SCSI driver developer.
</p><dl>
<dt>REQUEST SENSE
</dt><dd>Whenever a command returns a CHECK CONDITION status,
the high-level Linux SCSI code automatically obtains more information
about the error by executing the REQUEST SENSE. This command returns a
sense key and a sense code (called the ``additional sense code,'' or ASC,
in the SCSI-2 standard [ANS]). Some SCSI devices may
also report an ``additional sense code qualifier'' (ASCQ). The 16
possible sense keys are described in the next table. For
information on the ASC and ASCQ, please refer to the SCSI standard
[ANS] or to a SCSI device technical manual.
<table border="1">
<tbody><tr><th>Sense Key</th><th>Description</th></tr>
<tr><td><tt>0x00</tt></td><td>NO SENSE</td></tr>
<tr><td><tt>0x01</tt></td><td>RECOVERED ERROR</td></tr>
<tr><td><tt>0x02</tt></td><td>NOT READY</td></tr>
<tr><td><tt>0x03</tt></td><td>MEDIUM ERROR</td></tr>
<tr><td><tt>0x04</tt></td><td>HARDWARE ERROR</td></tr>
<tr><td><tt>0x05</tt></td><td>ILLEGAL REQUEST</td></tr>
<tr><td><tt>0x06</tt></td><td>UNIT ATTENTION</td></tr>
<tr><td><tt>0x07</tt></td><td>DATA PROTECT</td></tr>
<tr><td><tt>0x08</tt></td><td>BLANK CHECK</td></tr>
<tr><td><tt>0x09</tt></td><td>(Vendor specific error)</td></tr>
<tr><td><tt>0x0a</tt></td><td>COPY ABORTED</td></tr>
<tr><td><tt>0x0b</tt></td><td>ABORTED COMMAND</td></tr>
<tr><td><tt>0x0c</tt></td><td>EQUAL</td></tr>
<tr><td><tt>0x0d</tt></td><td>VOLUME OVERFLOW</td></tr>
<tr><td><tt>0x0e</tt></td><td>MISCOMPARE</td></tr>
<tr><td><tt>0x0f</tt></td><td>RESERVED</td></tr>
</tbody></table>
</dd><dt>TEST UNIT READY
</dt><dd>This command is used to test the target's status.
If the target can accept a medium-access command (e.g., a READ or a
WRITE), the command returns with a GOOD status. Otherwise, the command
returns with a CHECK CONDITION status and a sense key of NOT READY.
This response usually indicates that the target is completing power-on
self-tests.
</dd><dt>INQUIRY
</dt><dd>This command returns the target's make, model, and device
type. The high-level Linux code uses this command to differentiate
among magnetic disks, optical disks, and tape drives (the high-level code
currently does not support printers, processors, or juke boxes).
</dd><dt>READ and WRITE
</dt><dd>These commands are used to transfer data from and to
the target. You should be sure your driver can support simpler commands,
such as TEST UNIT READY and INQUIRY, before attempting to use the READ and
WRITE commands.
</dd></dl>
<h4>Getting Started</h4>
<p>The author of a low-level device driver will need to have an
understanding of how interruptions are handled by the kernel.
At minimum, the kernel functions that disable (<tt>cli()</tt>)
and enable (<tt>sti()</tt>) interruptions should be understood.
The scheduling functions (e.g., <tt>schedule()</tt>,
<tt>sleepon()</tt>, and <tt>wakeup()</tt>) may also be needed
by some drivers. A detailed explanation of these functions can
be found in <a href="http://tldp.org/LDP/khg/HyperNews/get/devices/reference.html">Supporting Functions</a>.
</p><h4>Before You Begin: Gathering Tools</h4>
<p>Before you begin to write a SCSI driver for Linux, you will
need to obtain several resources.
</p><p>The most important is a bootable Linux system--preferably
one which boots from an IDE, RLL, or MFM hard disk. During the
development of your new SCSI driver, you will rebuild the
kernel and reboot your system many times. Programming errors
may result in the destruction of data on your SCSI drive
<i>and</i> on your non-SCSI drive. <i>Back up your system
before you begin</i>.
</p><p>The installed Linux system can be quite minimal: the GCC
compiler distribution (including libraries and the binary
utilities), an editor, and the kernel source are all you need.
Additional tools like <tt>od</tt>, <tt>hexdump</tt>, and
<tt>less</tt> will be quite helpful. All of these tools will
fit on an inexpensive 20-30~MB hard disk. (A used 20 MB MFM
hard disk and controller should cost less than US$100.)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -