svn commit: r42406 - head/en_US.ISO8859-1/books/arch-handbook/scsi

Warren Block wblock at FreeBSD.org
Wed Jul 24 02:20:37 UTC 2013


Author: wblock
Date: Wed Jul 24 02:20:36 2013
New Revision: 42406
URL: http://svnweb.freebsd.org/changeset/doc/42406

Log:
  Whitespace-only fixes.  Translators, please ignore.

Modified:
  head/en_US.ISO8859-1/books/arch-handbook/scsi/chapter.xml

Modified: head/en_US.ISO8859-1/books/arch-handbook/scsi/chapter.xml
==============================================================================
--- head/en_US.ISO8859-1/books/arch-handbook/scsi/chapter.xml	Wed Jul 24 00:16:05 2013	(r42405)
+++ head/en_US.ISO8859-1/books/arch-handbook/scsi/chapter.xml	Wed Jul 24 02:20:36 2013	(r42406)
@@ -9,16 +9,16 @@
   <chapterinfo>
     <authorgroup>
       <author>
-        <firstname>Sergey</firstname>
-    	<surname>Babkin</surname>
-        <contrib>Written by </contrib>
+	<firstname>Sergey</firstname>
+	<surname>Babkin</surname>
+	<contrib>Written by </contrib>
       </author>
     </authorgroup>
     <authorgroup>
       <author>
-        <firstname>Murray</firstname>
-    	<surname>Stokely</surname>
-        <contrib>Modifications for Handbook made by </contrib>
+	<firstname>Murray</firstname>
+	<surname>Stokely</surname>
+	<contrib>Modifications for Handbook made by </contrib>
       </author>
     </authorgroup>
   </chapterinfo>
@@ -34,69 +34,79 @@
       protocol.  Much of the information in this document was
       extracted from the drivers:</para>
 
-     <itemizedlist>
+    <itemizedlist>
 
-       <listitem><para>ncr (<filename>/sys/pci/ncr.c</filename>) by
-         Wolfgang Stanglmeier and Stefan Esser</para></listitem>
+      <listitem><para>ncr (<filename>/sys/pci/ncr.c</filename>) by
+	Wolfgang Stanglmeier and Stefan Esser</para></listitem>
 
-       <listitem><para>sym (<filename>/sys/dev/sym/sym_hipd.c</filename>) by
-         Gerard Roudier</para></listitem>
+      <listitem>
+	<para>sym (<filename>/sys/dev/sym/sym_hipd.c</filename>) by
+	  Gerard Roudier</para>
+      </listitem>
 
-       <listitem><para>aic7xxx
-         (<filename>/sys/dev/aic7xxx/aic7xxx.c</filename>) by Justin
-         T. Gibbs</para></listitem>
-
-     </itemizedlist>
-
-   <para>and from the CAM code itself (by Justin T. Gibbs, see
-     <filename>/sys/cam/*</filename>).  When some solution looked the
-     most logical and was essentially verbatim extracted from the code
-     by Justin T. Gibbs, I marked it as <quote>recommended</quote>.</para>
-
-   <para>The document is illustrated with examples in
-     pseudo-code. Although sometimes the examples have many details
-     and look like real code, it is still pseudo-code.  It was written
-     to demonstrate the concepts in an understandable way.  For a real
-     driver other approaches may be more modular and efficient.  It
-     also abstracts from the hardware details, as well as issues that
-     would cloud the demonstrated concepts or that are supposed to be
-     described in the other chapters of the developers handbook. Such
-     details are commonly shown as calls to functions with descriptive
-     names, comments or pseudo-statements. Fortunately real life
-     full-size examples with all the details can be found in the real
-     drivers.</para>
+      <listitem>
+	<para>aic7xxx
+	  (<filename>/sys/dev/aic7xxx/aic7xxx.c</filename>) by Justin
+	  T. Gibbs</para>
+      </listitem>
+    </itemizedlist>
 
+    <para>and from the CAM code itself (by Justin T. Gibbs, see
+      <filename>/sys/cam/*</filename>).  When some solution looked the
+      most logical and was essentially verbatim extracted from the
+      code by Justin T. Gibbs, I marked it as
+      <quote>recommended</quote>.</para>
+
+    <para>The document is illustrated with examples in
+      pseudo-code.  Although sometimes the examples have many details
+      and look like real code, it is still pseudo-code.  It was
+      written to demonstrate the concepts in an understandable way.
+      For a real driver other approaches may be more modular and
+      efficient.  It also abstracts from the hardware details, as well
+      as issues that would cloud the demonstrated concepts or that are
+      supposed to be described in the other chapters of the developers
+      handbook.  Such details are commonly shown as calls to functions
+      with descriptive names, comments or pseudo-statements.
+      Fortunately real life full-size examples with all the details
+      can be found in the real drivers.</para>
   </sect1>
 
   <sect1 id="scsi-general">
     <title>General Architecture</title>
 
-    <indexterm><primary>Common Access Method (CAM)</primary></indexterm>
+    <indexterm>
+      <primary>Common Access Method (CAM)</primary>
+    </indexterm>
 
-    <para>CAM stands for Common Access Method. It is a generic way to
-      address the I/O buses in a SCSI-like way. This allows a
+    <para>CAM stands for Common Access Method.  It is a generic way to
+      address the I/O buses in a SCSI-like way.  This allows a
       separation of the generic device drivers from the drivers
-      controlling the I/O bus: for example the disk driver becomes able
-      to control disks on both SCSI, IDE, and/or any other bus so the
-      disk driver portion does not have to be rewritten (or copied and
-      modified) for every new I/O bus. Thus the two most important
-      active entities are:</para>
+      controlling the I/O bus: for example the disk driver becomes
+      able to control disks on both SCSI, IDE, and/or any other bus so
+      the disk driver portion does not have to be rewritten (or copied
+      and modified) for every new I/O bus.  Thus the two most
+      important active entities are:</para>
 
     <indexterm><primary>CD-ROM</primary></indexterm>
     <indexterm><primary>tape</primary></indexterm>
     <indexterm><primary>IDE</primary></indexterm>
     <itemizedlist>
-      <listitem><para><emphasis>Peripheral Modules</emphasis> -  a
-        driver for peripheral devices (disk, tape, CD-ROM,
-        etc.)</para></listitem>
-      <listitem><para><emphasis>SCSI Interface Modules </emphasis>(SIM)
-        - a Host Bus Adapter drivers for connecting to an I/O bus such
-        as SCSI or IDE.</para></listitem>
+      <listitem>
+	<para><emphasis>Peripheral Modules</emphasis> - a
+	  driver for peripheral devices (disk, tape, CD-ROM,
+	  etc.)</para>
+      </listitem>
+
+      <listitem>
+	<para><emphasis>SCSI Interface Modules </emphasis>(SIM) - a
+	  Host Bus Adapter drivers for connecting to an I/O bus such
+	  as SCSI or IDE.</para>
+      </listitem>
     </itemizedlist>
 
     <para>A peripheral driver receives requests from the OS, converts
       them to a sequence of SCSI commands and passes these SCSI
-      commands to a SCSI Interface Module. The SCSI Interface Module
+      commands to a SCSI Interface Module.  The SCSI Interface Module
       is responsible for passing these commands to the actual hardware
       (or if the actual hardware is not SCSI but, for example, IDE
       then also converting the SCSI commands to the native commands of
@@ -109,7 +119,7 @@
     <para>A typical SIM driver needs to include the following
       CAM-related header files:</para>
 
-<programlisting>#include <cam/cam.h>
+    <programlisting>#include <cam/cam.h>
 #include <cam/cam_ccb.h>
 #include <cam/cam_sim.h>
 #include <cam/cam_xpt_sim.h>
@@ -117,9 +127,9 @@
 #include <cam/scsi/scsi_all.h></programlisting>
 
     <para>The first thing each SIM driver must do is register itself
-      with the CAM subsystem. This is done during the driver's
+      with the CAM subsystem.  This is done during the driver's
       <function>xxx_attach()</function> function (here and further
-      xxx_ is used to denote the unique driver name prefix). The
+      xxx_ is used to denote the unique driver name prefix).  The
       <function>xxx_attach()</function> function itself is called by
       the system bus auto-configuration code which we do not describe
       here.</para>
@@ -127,22 +137,23 @@
     <para>This is achieved in multiple steps: first it is necessary to
       allocate the queue of requests associated with this SIM:</para>
 
-<programlisting>    struct cam_devq *devq;
+    <programlisting>    struct cam_devq *devq;
 
     if(( devq = cam_simq_alloc(SIZE) )==NULL) {
         error; /* some code to handle the error */
     }</programlisting>
 
-    <para>Here <literal>SIZE</literal> is the size of the queue to be allocated, maximal
-      number of requests it could contain. It is the number of requests
-      that the SIM driver can handle in parallel on one SCSI
-      card. Commonly it can be calculated as:</para>
+    <para>Here <literal>SIZE</literal> is the size of the queue to be
+      allocated, maximal number of requests it could contain.  It is
+      the number of requests that the SIM driver can handle in
+      parallel on one SCSI card.  Commonly it can be calculated
+      as:</para>
 
-<programlisting>SIZE = NUMBER_OF_SUPPORTED_TARGETS * MAX_SIMULTANEOUS_COMMANDS_PER_TARGET</programlisting>
+    <programlisting>SIZE = NUMBER_OF_SUPPORTED_TARGETS * MAX_SIMULTANEOUS_COMMANDS_PER_TARGET</programlisting>
 
     <para>Next we create a descriptor of our SIM:</para>
 
-<programlisting>    struct cam_sim *sim;
+    <programlisting>    struct cam_sim *sim;
 
     if(( sim = cam_sim_alloc(action_func, poll_func, driver_name,
             softc, unit, max_dev_transactions,
@@ -155,10 +166,10 @@
       free the <structname>devq</structname> also because we can do
       nothing else with it and we want to conserve memory.</para>
 
-    <para>If a SCSI card has multiple SCSI buses<indexterm>
-      <primary>SCSI</primary><secondary>bus</secondary></indexterm>
-      on it then each bus requires its own <structname>cam_sim</structname>
-      structure.</para>
+    <para>If a SCSI card has multiple SCSI
+      buses<indexterm><primary>SCSI</primary><secondary>bus</secondary></indexterm>
+      on it then each bus requires its own
+      <structname>cam_sim</structname> structure.</para>
 
     <para>An interesting question is what to do if a SCSI card has
       more than one SCSI bus, do we need one
@@ -167,71 +178,86 @@
       either way, as the driver's author prefers.</para>
 
     <para>The arguments are:</para>
-      <itemizedlist>
 
-        <listitem><para><function>action_func</function> - pointer to
-          the driver's <function>xxx_action</function> function.
-	  <funcsynopsis><funcprototype>
-	  <funcdef>static void
-            <function>xxx_action</function>
-	  </funcdef>
-	    <paramdef>
-	      <parameter>struct cam_sim *sim</parameter>,
-  	      <parameter>union ccb *ccb</parameter>
-	    </paramdef>
-	  </funcprototype></funcsynopsis>
-	  </para></listitem>
-
-        <listitem><para><function>poll_func</function> - pointer to
-          the driver's <function>xxx_poll()</function>
-	  <funcsynopsis><funcprototype>
-	  <funcdef>static void
-	    <function>xxx_poll</function>
-	  </funcdef>
-	    <paramdef>
-	      <parameter>struct cam_sim *sim</parameter>
-	    </paramdef>
-	  </funcprototype></funcsynopsis>
-	  </para></listitem>
-
-        <listitem><para>driver_name - the name of the actual driver,
-          such as <quote>ncr</quote> or <quote>wds</quote>.</para></listitem>
-
-        <listitem><para><structname>softc</structname> - pointer to the
-          driver's internal descriptor for this SCSI card. This
-          pointer will be used by the driver in future to get private
-          data.</para></listitem>
-
-        <listitem><para>unit - the controller unit number, for example
-          for controller <quote>wds0</quote> this number will be
-          0</para></listitem>
-
-        <listitem><para>max_dev_transactions - maximal number of
-          simultaneous transactions per SCSI target in the non-tagged
-          mode. This value will be almost universally equal to 1, with
-          possible exceptions only for the non-SCSI cards. Also the
-          drivers that hope to take advantage by preparing one
-          transaction while another one is executed may set it to 2
-          but this does not seem to be worth the
-          complexity.</para></listitem>
-
-        <listitem><para>max_tagged_dev_transactions - the same thing,
-          but in the tagged mode.  Tags are the SCSI way to initiate
-          multiple transactions on a device: each transaction is
-          assigned a unique tag and the transaction is sent to the
-          device. When the device completes some transaction it sends
-          back the result together with the tag so that the SCSI
-          adapter (and the driver) can tell which transaction was
-          completed. This argument is also known as the maximal tag
-          depth. It depends on the abilities of the SCSI
-          adapter.</para></listitem>
-      </itemizedlist>
+    <itemizedlist>
+      <listitem>
+	<para><function>action_func</function> - pointer to
+	  the driver's <function>xxx_action</function> function.
+	  <funcsynopsis>
+	    <funcprototype>
+	      <funcdef>static void
+		<function>xxx_action</function>
+	      </funcdef>
+	      <paramdef>
+		<parameter>struct cam_sim *sim</parameter>,
+		<parameter>union ccb *ccb</parameter>
+	      </paramdef>
+	    </funcprototype>
+	  </funcsynopsis></para>
+      </listitem>
+
+      <listitem>
+	<para><function>poll_func</function> - pointer to
+	  the driver's <function>xxx_poll()</function>
+	  <funcsynopsis>
+	    <funcprototype>
+	      <funcdef>static void
+		<function>xxx_poll</function>
+	      </funcdef>
+	      <paramdef>
+		<parameter>struct cam_sim *sim</parameter>
+	      </paramdef>
+	    </funcprototype>
+	  </funcsynopsis></para>
+      </listitem>
+
+      <listitem>
+	<para>driver_name - the name of the actual driver,
+	  such as <quote>ncr</quote> or
+	  <quote>wds</quote>.</para>
+      </listitem>
+
+      <listitem>
+	<para><structname>softc</structname> - pointer to the driver's
+	  internal descriptor for this SCSI card.  This pointer will
+	  be used by the driver in future to get private
+	  data.</para>
+      </listitem>
+
+      <listitem>
+	<para>unit - the controller unit number, for example
+	  for controller <quote>wds0</quote> this number will be
+	  0</para>
+      </listitem>
+
+      <listitem>
+	<para>max_dev_transactions - maximal number of simultaneous
+	  transactions per SCSI target in the non-tagged mode.  This
+	  value will be almost universally equal to 1, with possible
+	  exceptions only for the non-SCSI cards.  Also the drivers
+	  that hope to take advantage by preparing one transaction
+	  while another one is executed may set it to 2 but this does
+	  not seem to be worth the complexity.</para>
+      </listitem>
+
+      <listitem>
+	<para>max_tagged_dev_transactions - the same thing, but in the
+	  tagged mode.  Tags are the SCSI way to initiate multiple
+	  transactions on a device: each transaction is assigned a
+	  unique tag and the transaction is sent to the device.  When
+	  the device completes some transaction it sends back the
+	  result together with the tag so that the SCSI adapter (and
+	  the driver) can tell which transaction was completed.  This
+	  argument is also known as the maximal tag depth.  It depends
+	  on the abilities of the SCSI adapter.</para>
+      </listitem>
+
+    </itemizedlist>
 
     <para>Finally we register the SCSI buses associated with our SCSI
-      adapter<indexterm><primary>SCSI</primary><secondary>adapter</secondary>
-      </indexterm>:</para>
+      adapter<indexterm><primary>SCSI</primary><secondary>adapter</secondary></indexterm>:</para>
 
-<programlisting>    if(xpt_bus_register(sim, bus_number) != CAM_SUCCESS) {
+    <programlisting>    if(xpt_bus_register(sim, bus_number) != CAM_SUCCESS) {
         cam_sim_free(sim, /*free_devq*/ TRUE);
         error; /* some code to handle the error */
     }</programlisting>
@@ -240,38 +266,38 @@
       SCSI bus (i.e., we consider a card with multiple buses as
       multiple cards with one bus each) then the bus number will
       always be 0, otherwise each bus on the SCSI card should be get a
-      distinct number. Each bus needs its own separate structure
+      distinct number.  Each bus needs its own separate structure
       cam_sim.</para>
 
     <para>After that our controller is completely hooked to the CAM
-      system. The value of <structname>devq</structname> can be
+      system.  The value of <structname>devq</structname> can be
       discarded now: sim will be passed as an argument in all further
       calls from CAM and devq can be derived from it.</para>
 
-    <para>CAM provides the framework for such asynchronous
-      events. Some events originate from the lower levels (the SIM
-      drivers), some events originate from the peripheral drivers,
-      some events originate from the CAM subsystem itself.  Any driver
-      can register callbacks for some types of the asynchronous
-      events, so that it would be notified if these events
-      occur.</para>
+    <para>CAM provides the framework for such asynchronous events.
+      Some events originate from the lower levels (the SIM drivers),
+      some events originate from the peripheral drivers, some events
+      originate from the CAM subsystem itself.  Any driver can
+      register callbacks for some types of the asynchronous events, so
+      that it would be notified if these events occur.</para>
 
-    <para>A typical example of such an event is a device reset. Each
+    <para>A typical example of such an event is a device reset.  Each
       transaction and event identifies the devices to which it applies
-      by the means of <quote>path</quote>. The target-specific events normally
-      occur during a transaction with this device. So the path from
-      that transaction may be re-used to report this event (this is
-      safe because the event path is copied in the event reporting
-      routine but not deallocated nor passed anywhere further). Also
-      it is safe to allocate paths dynamically at any time including
-      the interrupt routines, although that incurs certain overhead,
-      and a possible problem with this approach is that there may be
-      no free memory at that time.  For a bus reset event we need to
-      define a wildcard path including all devices on the bus.  So we
-      can create the path for the future bus reset events in advance
-      and avoid problems with the future memory shortage:</para>
+      by the means of <quote>path</quote>.  The target-specific events
+      normally occur during a transaction with this device.  So the
+      path from that transaction may be re-used to report this event
+      (this is safe because the event path is copied in the event
+      reporting routine but not deallocated nor passed anywhere
+      further).  Also it is safe to allocate paths dynamically at any
+      time including the interrupt routines, although that incurs
+      certain overhead, and a possible problem with this approach is
+      that there may be no free memory at that time.  For a bus reset
+      event we need to define a wildcard path including all devices on
+      the bus.  So we can create the path for the future bus reset
+      events in advance and avoid problems with the future memory
+      shortage:</para>
 
-<programlisting>    struct cam_path *path;
+    <programlisting>    struct cam_path *path;
 
     if(xpt_create_path(&path, /*periph*/NULL,
                 cam_sim_path(sim), CAM_TARGET_WILDCARD,
@@ -287,39 +313,47 @@
     <para>As you can see the path includes:</para>
 
     <itemizedlist>
-      <listitem><para>ID of the peripheral driver (NULL here because we have
-        none)</para></listitem>
+      <listitem>
+	<para>ID of the peripheral driver (NULL here because we have
+	  none)</para>
+      </listitem>
 
-      <listitem><para>ID of the SIM driver
-        (<function>cam_sim_path(sim)</function>)</para></listitem>
+      <listitem>
+	<para>ID of the SIM driver
+	  (<function>cam_sim_path(sim)</function>)</para>
+      </listitem>
 
-      <listitem><para>SCSI target number of the device (CAM_TARGET_WILDCARD
-        means <quote>all devices</quote>)</para></listitem>
+      <listitem>
+	<para>SCSI target number of the device (CAM_TARGET_WILDCARD
+	  means <quote>all devices</quote>)</para>
+      </listitem>
 
-      <listitem><para>SCSI LUN number of the subdevice (CAM_LUN_WILDCARD means
-        <quote>all LUNs</quote>)</para></listitem>
+      <listitem>
+	<para>SCSI LUN number of the subdevice (CAM_LUN_WILDCARD means
+	  <quote>all LUNs</quote>)</para>
+      </listitem>
     </itemizedlist>
 
-    <para>If the driver can not allocate this path it will not be able to
-      work normally, so in that case we dismantle that SCSI
+    <para>If the driver can not allocate this path it will not be able
+      to work normally, so in that case we dismantle that SCSI
       bus.</para>
 
     <para>And we save the path pointer in the
-      <structname>softc</structname> structure for future use. After
+      <structname>softc</structname> structure for future use.  After
       that we save the value of sim (or we can also discard it on the
       exit from <function>xxx_probe()</function> if we wish).</para>
 
-    <para>That is all for a minimalistic initialization. To do things
-      right there is one more issue left. </para>
+    <para>That is all for a minimalistic initialization.  To do things
+      right there is one more issue left.</para>
 
     <para>For a SIM driver there is one particularly interesting
-      event: when a target device is considered lost. In this case
+      event: when a target device is considered lost.  In this case
       resetting the SCSI negotiations with this device may be a good
-      idea. So we register a callback for this event with CAM. The
+      idea.  So we register a callback for this event with CAM.  The
       request is passed to CAM by requesting CAM action on a CAM
       control block for this type of request:</para>
 
-<programlisting>    struct ccb_setasync csa;
+    <programlisting>    struct ccb_setasync csa;
 
     xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5);
     csa.ccb_h.func_code = XPT_SASYNC_CB;
@@ -332,59 +366,71 @@
       and <function>xxx_poll()</function> driver entry points.</para>
 
     <para>
-    <funcsynopsis><funcprototype>
-      <funcdef>static void
-      <function>xxx_action</function>
-      </funcdef>
-      <paramdef>
-        <parameter>struct cam_sim *sim</parameter>,
-        <parameter>union ccb *ccb</parameter>
-      </paramdef>
-    </funcprototype></funcsynopsis>
-    </para>
-
-    <para>Do some action on request of the CAM subsystem. Sim
-      describes the SIM for the request, CCB is the request
-      itself. CCB stands for <quote>CAM Control Block</quote>. It is a union of
-      many specific instances, each describing arguments for some type
-      of transactions. All of these instances share the CCB header
-      where the common part of arguments is stored.</para>
+      <funcsynopsis>
+	<funcprototype>
+	  <funcdef>static void
+	    <function>xxx_action</function>
+	  </funcdef>
+	  <paramdef>
+	    <parameter>struct cam_sim *sim</parameter>,
+	    <parameter>union ccb *ccb</parameter>
+	  </paramdef>
+	</funcprototype>
+      </funcsynopsis></para>
+
+    <para>Do some action on request of the CAM subsystem.  Sim
+      describes the SIM for the request, CCB is the request itself.
+      CCB stands for <quote>CAM Control Block</quote>.  It is a union
+      of many specific instances, each describing arguments for some
+      type of transactions.  All of these instances share the CCB
+      header where the common part of arguments is stored.</para>
 
     <para>CAM supports the SCSI controllers working in both initiator
-      (<quote>normal</quote>) mode and target (simulating a SCSI device) mode. Here
-      we only consider the part relevant to the initiator mode.</para>
+      (<quote>normal</quote>) mode and target (simulating a SCSI
+      device) mode.  Here we only consider the part relevant to the
+      initiator mode.</para>
 
     <para>There are a few function and macros (in other words,
-      methods) defined to access the public data in the struct sim:</para>
+      methods) defined to access the public data in the struct
+      sim:</para>
 
     <itemizedlist>
-      <listitem><para><function>cam_sim_path(sim)</function> - the
-      path ID (see above)</para></listitem>
+      <listitem>
+	<para><function>cam_sim_path(sim)</function> - the path ID
+	  (see above)</para>
+      </listitem>
 
-      <listitem><para><function>cam_sim_name(sim)</function> - the
-      name of the sim</para></listitem>
+      <listitem>
+	<para><function>cam_sim_name(sim)</function> - the name of the
+	  sim</para>
+      </listitem>
 
-      <listitem><para><function>cam_sim_softc(sim)</function> - the
-      pointer to the softc (driver private data)
-      structure</para></listitem>
+      <listitem>
+	<para><function>cam_sim_softc(sim)</function> - the pointer to
+	  the softc (driver private data) structure</para>
+      </listitem>
 
-      <listitem><para><function> cam_sim_unit(sim)</function> - the
-      unit number</para></listitem>
+      <listitem>
+	<para><function> cam_sim_unit(sim)</function> - the unit
+	  number</para>
+      </listitem>
 
-      <listitem><para><function> cam_sim_bus(sim)</function> - the bus
-      ID</para></listitem>
+      <listitem>
+	<para><function> cam_sim_bus(sim)</function> - the bus
+	  ID</para>
+      </listitem>
     </itemizedlist>
 
-    <para>To identify the device, <function>xxx_action()</function> can
-      get the unit number and pointer to its structure softc using
+    <para>To identify the device, <function>xxx_action()</function>
+      can get the unit number and pointer to its structure softc using
       these functions.</para>
 
     <para>The type of request is stored in
-      <structfield>ccb->ccb_h.func_code</structfield>. So generally
-      <function>xxx_action()</function> consists of a big
+      <structfield>ccb->ccb_h.func_code</structfield>.  So
+      generally <function>xxx_action()</function> consists of a big
       switch:</para>
 
-<programlisting>    struct xxx_softc *softc = (struct xxx_softc *) cam_sim_softc(sim);
+    <programlisting>    struct xxx_softc *softc = (struct xxx_softc *) cam_sim_softc(sim);
     struct ccb_hdr *ccb_h = &ccb->ccb_h;
     int unit = cam_sim_unit(sim);
     int bus = cam_sim_bus(sim);
@@ -400,9 +446,9 @@
 
     <para>As can be seen from the default case (if an unknown command
       was received) the return code of the command is set into
-      <structfield>ccb->ccb_h.status</structfield> and the completed
-      CCB is returned back to CAM by calling
-      <function>xpt_done(ccb)</function>. </para>
+      <structfield>ccb->ccb_h.status</structfield> and the
+      completed CCB is returned back to CAM by calling
+      <function>xpt_done(ccb)</function>.</para>
 
     <para><function>xpt_done()</function> does not have to be called
       from <function>xxx_action()</function>: For example an I/O
@@ -413,55 +459,61 @@
       handling routine.</para>
 
     <para>Actually, the CCB status is not only assigned as a return
-      code but a CCB has some status all the time. Before CCB is
+      code but a CCB has some status all the time.  Before CCB is
       passed to the <function>xxx_action()</function> routine it gets
       the status CCB_REQ_INPROG meaning that it is in progress.  There
       are a surprising number of status values defined in
       <filename>/sys/cam/cam.h</filename> which should be able to
       represent the status of a request in great detail.  More
-      interesting yet, the status is in fact a <quote>bitwise or</quote> of an
-      enumerated status value (the lower 6 bits) and possible
-      additional flag-like bits (the upper bits).  The enumerated
-      values will be discussed later in more detail.  The summary of
-      them can be found in the Errors Summary section.  The possible
-      status flags are:</para>
+      interesting yet, the status is in fact a <quote>bitwise
+      or</quote> of an enumerated status value (the lower 6 bits) and
+      possible additional flag-like bits (the upper bits).  The
+      enumerated values will be discussed later in more detail.  The
+      summary of them can be found in the Errors Summary section.  The
+      possible status flags are:</para>
 
     <itemizedlist>
+      <listitem>
+	<para><emphasis>CAM_DEV_QFRZN</emphasis> - if the SIM driver
+	  gets a serious error (for example, the device does not
+	  respond to the selection or breaks the SCSI protocol) when
+	  processing a CCB it should freeze the request queue by
+	  calling <function>xpt_freeze_simq()</function>, return the
+	  other enqueued but not processed yet CCBs for this device
+	  back to the CAM queue, then set this flag for the
+	  troublesome CCB and call <function>xpt_done()</function>.
+	  This flag causes the CAM subsystem to unfreeze the queue
+	  after it handles the error.</para>
+      </listitem>
 
-      <listitem><para><emphasis>CAM_DEV_QFRZN</emphasis> - if the
-        SIM driver gets a serious error (for example, the device does
-        not respond to the selection or breaks the SCSI protocol) when
-        processing a CCB it should freeze the request queue by calling
-        <function>xpt_freeze_simq()</function>, return the other
-        enqueued but not processed yet CCBs for this device back to
-        the CAM queue, then set this flag for the troublesome CCB and
-        call <function>xpt_done()</function>. This flag causes the CAM
-        subsystem to unfreeze the queue after it handles the
-        error.</para></listitem>
-
-      <listitem><para><emphasis>CAM_AUTOSNS_VALID</emphasis> - if
-        the device returned an error condition and the flag
-        CAM_DIS_AUTOSENSE is not set in CCB the SIM driver must
-        execute the REQUEST SENSE command automatically to extract the
-        sense (extended error information) data from the device. If
-        this attempt was successful the sense data should be saved in
-        the CCB and this flag set.</para></listitem>
-
-      <listitem><para><emphasis>CAM_RELEASE_SIMQ</emphasis> - like
-        CAM_DEV_QFRZN but used in case there is some problem (or
-        resource shortage) with the SCSI controller itself. Then all
-        the future requests to the controller should be stopped by
-        <function>xpt_freeze_simq()</function>.  The controller queue
-        will be restarted after the SIM driver overcomes the shortage
-        and informs CAM by returning some CCB with this flag
-        set.</para></listitem>
-
-      <listitem><para><emphasis>CAM_SIM_QUEUED</emphasis> - when SIM
-        puts a CCB into its request queue this flag should be set (and
-        removed when this CCB gets dequeued before being returned back
-        to CAM). This flag is not used anywhere in the CAM code now,
-        so its purpose is purely diagnostic.</para></listitem>
+      <listitem>
+	<para><emphasis>CAM_AUTOSNS_VALID</emphasis> - if the
+	  device returned an error condition and the flag
+	  CAM_DIS_AUTOSENSE is not set in CCB the SIM driver must
+	  execute the REQUEST SENSE command automatically to extract
+	  the sense (extended error information) data from the device.
+	  If this attempt was successful the sense data should be
+	  saved in the CCB and this flag set.</para>
+      </listitem>
 
+      <listitem>
+	<para><emphasis>CAM_RELEASE_SIMQ</emphasis> - like
+	  CAM_DEV_QFRZN but used in case there is some problem (or
+	  resource shortage) with the SCSI controller itself.  Then
+	  all the future requests to the controller should be stopped
+	  by <function>xpt_freeze_simq()</function>.  The controller
+	  queue will be restarted after the SIM driver overcomes the
+	  shortage and informs CAM by returning some CCB with this
+	  flag set.</para>
+      </listitem>
+
+      <listitem>
+	<para><emphasis>CAM_SIM_QUEUED</emphasis> - when SIM puts a
+	  CCB into its request queue this flag should be set (and
+	  removed when this CCB gets dequeued before being returned
+	  back to CAM).  This flag is not used anywhere in the CAM
+	  code now, so its purpose is purely diagnostic.</para>
+      </listitem>
     </itemizedlist>
 
     <para>The function <function>xxx_action()</function> is not
@@ -475,126 +527,159 @@
     <para>The CCB header contains the following fields:</para>
 
     <itemizedlist>
+      <listitem>
+	<para><emphasis>path</emphasis> - path ID for the
+	  request</para>
+      </listitem>
 
-      <listitem><para><emphasis>path</emphasis> - path ID for the
-      request</para></listitem>
+      <listitem>
+	<para><emphasis>target_id</emphasis> - target device ID for
+	  the request</para>
+      </listitem>
 
-      <listitem><para><emphasis>target_id</emphasis> - target device
-      ID for the request</para></listitem>
+      <listitem>
+	<para><emphasis>target_lun</emphasis> - LUN ID of the target
+	  device</para>
+      </listitem>
 
-      <listitem><para><emphasis>target_lun</emphasis> - LUN ID of
-      the target device</para></listitem>
+      <listitem>
+	<para><emphasis>timeout</emphasis> - timeout interval for this
+	  command, in milliseconds</para>
+      </listitem>
 
-      <listitem><para><emphasis>timeout</emphasis> - timeout
-      interval for this command, in milliseconds</para></listitem>
-
-      <listitem><para><emphasis>timeout_ch</emphasis> - a
-      convenience place for the SIM driver to store the timeout handle
-      (the CAM subsystem itself does not make any assumptions about
-      it)</para></listitem>
-
-      <listitem><para><emphasis>flags</emphasis> - various bits of
-      information about the request spriv_ptr0, spriv_ptr1 - fields
-      reserved for private use by the SIM driver (such as linking to
-      the SIM queues or SIM private control blocks); actually, they
-      exist as unions: spriv_ptr0 and spriv_ptr1 have the type (void
-      *), spriv_field0 and spriv_field1 have the type unsigned long,
-      sim_priv.entries[0].bytes and sim_priv.entries[1].bytes are byte
-      arrays of the size consistent with the other incarnations of the
-      union and sim_priv.bytes is one array, twice
-      bigger.</para></listitem>
+      <listitem>
+	<para><emphasis>timeout_ch</emphasis> - a convenience place
+	  for the SIM driver to store the timeout handle (the CAM
+	  subsystem itself does not make any assumptions about
+	  it)</para>
+      </listitem>
 
+      <listitem>
+	<para><emphasis>flags</emphasis> - various bits of information
+	  about the request spriv_ptr0, spriv_ptr1 - fields reserved
+	  for private use by the SIM driver (such as linking to the
+	  SIM queues or SIM private control blocks); actually, they
+	  exist as unions: spriv_ptr0 and spriv_ptr1 have the type
+	  (void *), spriv_field0 and spriv_field1 have the type
+	  unsigned long, sim_priv.entries[0].bytes and
+	  sim_priv.entries[1].bytes are byte arrays of the size
+	  consistent with the other incarnations of the union and
+	  sim_priv.bytes is one array, twice bigger.</para>
+      </listitem>
     </itemizedlist>
 
     <para>The recommended way of using the SIM private fields of CCB
       is to define some meaningful names for them and use these
       meaningful names in the driver, like:</para>
 
-<programlisting>#define ccb_some_meaningful_name    sim_priv.entries[0].bytes
+    <programlisting>#define ccb_some_meaningful_name    sim_priv.entries[0].bytes
 #define ccb_hcb spriv_ptr1 /* for hardware control block */</programlisting>
 
     <para>The most common initiator mode requests are:</para>
+
     <itemizedlist>
-      <listitem><para><emphasis>XPT_SCSI_IO</emphasis> - execute an
-      I/O transaction</para>
+      <listitem>
+	<para><emphasis>XPT_SCSI_IO</emphasis> - execute an I/O
+	  transaction</para>
+
+	<para>The instance <quote>struct ccb_scsiio csio</quote> of
+	  the union ccb is used to transfer the arguments.  They
+	  are:</para>
+
+	<itemizedlist>
+	  <listitem>
+	    <para><emphasis>cdb_io</emphasis> - pointer to the SCSI
+	      command buffer or the buffer itself</para>
+	  </listitem>
+
+	  <listitem>
+	    <para><emphasis>cdb_len</emphasis> - SCSI command
+	      length</para>
+	  </listitem>
+
+	  <listitem>
+	    <para><emphasis>data_ptr</emphasis> - pointer to the data
+	      buffer (gets a bit complicated if scatter/gather is
+	      used)</para>
+	  </listitem>
+
+	  <listitem>
+	    <para><emphasis>dxfer_len</emphasis> - length of the data
+	      to transfer</para>
+	  </listitem>
+
+	  <listitem>
+	    <para><emphasis>sglist_cnt</emphasis> - counter of the
+	      scatter/gather segments</para>
+	  </listitem>
+
+	  <listitem>
+	    <para><emphasis>scsi_status</emphasis> - place to return
+	      the SCSI status</para>
+	  </listitem>
+
+	  <listitem>
+	    <para><emphasis>sense_data</emphasis> - buffer for the
+	      SCSI sense information if the command returns an error
+	      (the SIM driver is supposed to run the REQUEST SENSE
+	      command automatically in this case if the CCB flag
+	      CAM_DIS_AUTOSENSE is not set)</para>
+	  </listitem>
+
+	  <listitem>
+	    <para><emphasis>sense_len</emphasis> - the length of that
+	      buffer (if it happens to be higher than size of
+	      sense_data the SIM driver must silently assume the
+	      smaller value) resid, sense_resid - if the transfer of
+	      data or SCSI sense returned an error these are the
+	      returned counters of the residual (not transferred)
+	      data.  They do not seem to be especially meaningful, so
+	      in a case when they are difficult to compute (say,
+	      counting bytes in the SCSI controller's FIFO buffer) an
+	      approximate value will do as well.  For a successfully
+	      completed transfer they must be set to
+	      zero.</para>
+	  </listitem>
+
+	  <listitem>
+	    <para><emphasis>tag_action</emphasis> - the kind of tag to
+	      use:</para>
+
+	    <itemizedlist>
+	      <listitem>
+		<para>CAM_TAG_ACTION_NONE - do not use tags for this
+		  transaction</para>
+	      </listitem>
+
+	      <listitem>
+		<para>MSG_SIMPLE_Q_TAG, MSG_HEAD_OF_Q_TAG,
+		  MSG_ORDERED_Q_TAG - value equal to the appropriate
+		  tag message (see /sys/cam/scsi/scsi_message.h); this
+		  gives only the tag type, the SIM driver must assign
+		  the tag value itself</para>
+	      </listitem>
+	    </itemizedlist>
+	  </listitem>
+	</itemizedlist>
 
-      <para>The instance <quote>struct ccb_scsiio csio</quote> of the union ccb is
-        used to transfer the arguments. They are:</para>
+	<para>The general logic of handling this request is the
+	  following:</para>
 
-      <itemizedlist>
-        <listitem><para><emphasis>cdb_io</emphasis> - pointer to
-          the SCSI command buffer or the buffer
-  	  itself</para></listitem>
-
-	<listitem><para><emphasis>cdb_len</emphasis> - SCSI
-	  command length</para></listitem>
-
-	<listitem><para><emphasis>data_ptr</emphasis> - pointer to
-	  the data buffer (gets a bit complicated if scatter/gather is
-	  used)</para></listitem>
-
-	<listitem><para><emphasis>dxfer_len</emphasis> - length of
-	  the data to transfer</para></listitem>
-
-	<listitem><para><emphasis>sglist_cnt</emphasis> - counter
-	  of the scatter/gather segments</para></listitem>
-
-	<listitem><para><emphasis>scsi_status</emphasis> - place
-	  to return the SCSI status</para></listitem>
-
-	<listitem><para><emphasis>sense_data</emphasis> - buffer
-          for the SCSI sense information if the command returns an
-          error (the SIM driver is supposed to run the REQUEST SENSE
-          command automatically in this case if the CCB flag
-          CAM_DIS_AUTOSENSE is not set)</para></listitem>
-
-	<listitem><para><emphasis>sense_len</emphasis> - the
-          length of that buffer (if it happens to be higher than size
-          of sense_data the SIM driver must silently assume the
-          smaller value) resid, sense_resid - if the transfer of data
-          or SCSI sense returned an error these are the returned
-          counters of the residual (not transferred) data. They do not
-          seem to be especially meaningful, so in a case when they are
-          difficult to compute (say, counting bytes in the SCSI
-          controller's FIFO buffer) an approximate value will do as
-          well. For a successfully completed transfer they must be set
-          to zero.</para></listitem>
-
-	<listitem><para><emphasis>tag_action</emphasis> - the kind
-	  of tag to use:</para>
-
-	  <itemizedlist>
-	  <listitem><para>CAM_TAG_ACTION_NONE - do not use tags for this
-	  transaction</para></listitem>
-	  <listitem><para>MSG_SIMPLE_Q_TAG, MSG_HEAD_OF_Q_TAG,
-	  MSG_ORDERED_Q_TAG - value equal to the appropriate tag
-	  message (see /sys/cam/scsi/scsi_message.h); this gives only
-	  the tag type, the SIM driver must assign the tag value
-	  itself</para></listitem>
-	  </itemizedlist>
-
-	  </listitem>
-
-      </itemizedlist>
-
-      <para>The general logic of handling this request is the
-        following:</para>
-
-      <para>The first thing to do is to check for possible races, to
-        make sure that the command did not get aborted when it was
-        sitting in the queue:</para>
+	<para>The first thing to do is to check for possible races, to
+	  make sure that the command did not get aborted when it was
+	  sitting in the queue:</para>
 
-<programlisting>    struct ccb_scsiio *csio = &ccb->csio;
+	<programlisting>    struct ccb_scsiio *csio = &ccb->csio;
 
     if ((ccb_h->status & CAM_STATUS_MASK) != CAM_REQ_INPROG) {
         xpt_done(ccb);
         return;
     }</programlisting>
 
-      <para>Also we check that the device is supported at all by our
-        controller:</para>
+	<para>Also we check that the device is supported at all by our
+	  controller:</para>
 
-<programlisting>    if(ccb_h->target_id > OUR_MAX_SUPPORTED_TARGET_ID
+	<programlisting>    if(ccb_h->target_id > OUR_MAX_SUPPORTED_TARGET_ID
     || cch_h->target_id == OUR_SCSI_CONTROLLERS_OWN_ID) {
         ccb_h->status = CAM_TID_INVALID;
         xpt_done(ccb);
@@ -606,18 +691,20 @@
         return;
     }</programlisting>
 
-      <para>Then allocate whatever data structures (such as
-        card-dependent hardware control block<indexterm>
-	<primary>hardware control block</primary></indexterm>) we need
-	to process this request. If we can not then freeze the SIM queue and
-	remember that we have a pending operation, return the CCB back and ask
-        CAM to re-queue it. Later when the resources become available
-        the SIM queue must be unfrozen by returning a ccb with the
-        <literal>CAM_SIMQ_RELEASE</literal> bit set in its status. Otherwise, if all went
-        well, link the CCB with the hardware control block (HCB) and
-        mark it as queued.</para>
+	<para>Then allocate whatever data structures (such as
+	  card-dependent hardware control
+	  block<indexterm><primary>hardware control
+	    block</primary></indexterm>) we need to process this
+	  request.  If we can not then freeze the SIM queue and
+	  remember that we have a pending operation, return the CCB
+	  back and ask CAM to re-queue it.  Later when the resources
+	  become available the SIM queue must be unfrozen by returning
+	  a ccb with the <literal>CAM_SIMQ_RELEASE</literal> bit set
+	  in its status.  Otherwise, if all went well, link the CCB
+	  with the hardware control block (HCB) and mark it as
+	  queued.</para>
 
-<programlisting>    struct xxx_hcb *hcb = allocate_hcb(softc, unit, bus);
+	<programlisting>    struct xxx_hcb *hcb = allocate_hcb(softc, unit, bus);
 
     if(hcb == NULL) {
         softc->flags |= RESOURCE_SHORTAGE;
@@ -630,44 +717,49 @@

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-doc-all mailing list