Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/ic Do simple tagged queueing, enabled by default.



details:   https://anonhg.NetBSD.org/src/rev/7a346fa02cbb
branches:  trunk
changeset: 484104:7a346fa02cbb
user:      fvdl <fvdl%NetBSD.org@localhost>
date:      Sat Mar 25 19:52:12 2000 +0000

description:
Do simple tagged queueing, enabled by default.

diffstat:

 sys/dev/ic/aic7xxx.c |  103 ++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 90 insertions(+), 13 deletions(-)

diffs (193 lines):

diff -r d2d01c8038ee -r 7a346fa02cbb sys/dev/ic/aic7xxx.c
--- a/sys/dev/ic/aic7xxx.c      Sat Mar 25 19:05:45 2000 +0000
+++ b/sys/dev/ic/aic7xxx.c      Sat Mar 25 19:52:12 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: aic7xxx.c,v 1.44 2000/03/23 07:01:29 thorpej Exp $     */
+/*     $NetBSD: aic7xxx.c,v 1.45 2000/03/25 19:52:12 fvdl Exp $        */
 
 /*
  * Generic driver for the aic7xxx based adaptec SCSI controllers
@@ -34,7 +34,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx.c,v 1.41 2000/02/09 21:24:58 gibbs Exp $
+ * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx.c,v 1.42 2000/03/18 22:28:18 gibbs Exp $
  */
 /*
  * A few notes on features of the driver.
@@ -325,6 +325,8 @@
 static __inline struct scsipi_xfer *ahc_first_xs(struct ahc_softc *);
 static __inline void ahc_swap_hscb(struct hardware_scb *);
 static __inline void ahc_swap_sg(struct ahc_dma_seg *);
+static void ahc_check_tags(struct ahc_softc *, struct scsipi_xfer *);
+static int ahc_istagged_device(struct ahc_softc *, struct scsipi_xfer *);
 
 #if defined(AHC_DEBUG) && 0
 static void ahc_dumptinfo(struct ahc_softc *, struct ahc_initiator_tinfo *);
@@ -353,8 +355,9 @@
        while (xs != NULL) {
                target = xs->sc_link->scsipi_scsi.target;
                if (ahc->devqueue_blocked[target] == 0 &&
-                   ahc_index_busy_tcl(ahc, XS_TCL(ahc, xs), FALSE) ==
-                       SCB_LIST_NULL)
+                   (!ahc_istagged_device(ahc, xs) &&
+                    ahc_index_busy_tcl(ahc, XS_TCL(ahc, xs), FALSE) ==
+                   SCB_LIST_NULL))
                        break;
                xs = TAILQ_NEXT(xs, adapter_q);
        }
@@ -808,8 +811,8 @@
  */
 #define AHC_SYNCRATE_DT                0
 #define AHC_SYNCRATE_ULTRA2    1
-#define AHC_SYNCRATE_ULTRA     2
-#define AHC_SYNCRATE_FAST      5
+#define AHC_SYNCRATE_ULTRA     3
+#define AHC_SYNCRATE_FAST      6
 static struct ahc_syncrate ahc_syncrates[] = {
       /* ultra2    fast/ultra  period     rate */
        { 0x42,      0x000,      9,      "80.0" },
@@ -3340,7 +3343,8 @@
         * XXX if we are holding two commands per lun, 
         *     send the next command.
         */
-       ahc_index_busy_tcl(ahc, scb->hscb->tcl, /*unbusy*/TRUE);
+       if (!(scb->hscb->control & TAG_ENB))
+               ahc_index_busy_tcl(ahc, scb->hscb->tcl, /*unbusy*/TRUE);
 
        /*
         * If the recovery SCB completes, we have to be
@@ -3420,6 +3424,7 @@
                splx(s);
        } else {
                xs->xs_status |= XS_STS_DONE;
+               ahc_check_tags(ahc, xs);
                scsipi_done(xs);
        }
 
@@ -3887,10 +3892,11 @@
         * private queue to wait for our turn.
         */
        tcl = XS_TCL(ahc, xs);
-
+       
        if (ahc->queue_blocked ||
            ahc->devqueue_blocked[xs->sc_link->scsipi_scsi.target] ||
-           ahc_index_busy_tcl(ahc, tcl, FALSE) != SCB_LIST_NULL) {
+           (!ahc_istagged_device(ahc, xs) &&
+            ahc_index_busy_tcl(ahc, tcl, FALSE) != SCB_LIST_NULL)) {
                if (dontqueue) {
                        splx(s);
                        xs->error = XS_DRIVER_STUFFUP;
@@ -3965,7 +3971,8 @@
        tcl = XS_TCL(ahc, xs);
 
 #ifdef DIAGNOSTIC
-       if (ahc_index_busy_tcl(ahc, tcl, FALSE) != SCB_LIST_NULL)
+       if (!ahc_istagged_device(ahc, xs) &&
+           ahc_index_busy_tcl(ahc, tcl, FALSE) != SCB_LIST_NULL)
                panic("ahc: queuing for busy target");
 #endif
        
@@ -3973,7 +3980,10 @@
        hscb = scb->hscb;
        hscb->tcl = tcl;
 
-       ahc_busy_tcl(ahc, scb);
+       if (ahc_istagged_device(ahc, xs))
+               scb->hscb->control |= MSG_SIMPLE_Q_TAG;
+       else
+               ahc_busy_tcl(ahc, scb);
 
        splx(s);
  
@@ -4075,7 +4085,8 @@
         * be aborted.
         */
        if (xs->xs_status & XS_STS_DONE) {
-               ahc_index_busy_tcl(ahc, scb->hscb->tcl, TRUE);
+               if (!ahc_istagged_device(ahc, xs))
+                       ahc_index_busy_tcl(ahc, scb->hscb->tcl, TRUE);
                if (nsegments != 0)
                        bus_dmamap_unload(ahc->parent_dmat, scb->dmamap);
                ahcfreescb(ahc, scb);
@@ -4205,7 +4216,8 @@
                            (xs->xs_control & XS_CTL_NOSLEEP) ?
                            BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
                if (error) {
-                       ahc_index_busy_tcl(ahc, hscb->tcl, TRUE);
+                       if (!ahc_istagged_device(ahc, xs))
+                               ahc_index_busy_tcl(ahc, hscb->tcl, TRUE);
                        return (TRY_AGAIN_LATER);       /* XXX fvdl */
                }
                error = ahc_execute_scb(scb,
@@ -5564,3 +5576,68 @@
            tinfo->user.offset, tinfo->user.ppr_flags);
 }
 #endif
+
+static void
+ahc_check_tags(struct ahc_softc *ahc, struct scsipi_xfer *xs)
+{
+       struct scsipi_inquiry_data *inq;
+       struct ahc_devinfo devinfo;
+       int target_id, our_id;
+
+       if (xs->cmd->opcode != INQUIRY || xs->error != XS_NOERROR)
+               return;
+
+       target_id = xs->sc_link->scsipi_scsi.target;
+       our_id = SIM_SCSI_ID(ahc, xs->sc_link);
+
+       /*
+        * Sneak a look at the results of the SCSI Inquiry
+        * command and see if we can do Tagged queing.  This
+        * should really be done by the higher level drivers.
+        */
+       inq = (struct scsipi_inquiry_data *)xs->data;
+       if ((inq->flags & SID_CmdQue) && !(ahc_istagged_device(ahc, xs))) {
+               printf("%s: target %d using tagged queuing\n",
+                       ahc_name(ahc), xs->sc_link->scsipi_scsi.target);
+
+               ahc_compile_devinfo(&devinfo,
+                   our_id, target_id, xs->sc_link->scsipi_scsi.lun,    
+                   SIM_CHANNEL(ahc, xs->sc_link), ROLE_INITIATOR);
+               ahc_set_tags(ahc, &devinfo, TRUE);
+
+               if (ahc->scb_data->maxhscbs >= 16 ||
+                   (ahc->flags & AHC_PAGESCBS)) {
+                       /* Default to 8 tags */
+                       xs->sc_link->openings += 6;
+               } else {
+                       /*
+                        * Default to 4 tags on whimpy
+                        * cards that don't have much SCB
+                        * space and can't page.  This prevents
+                        * a single device from hogging all
+                        * slots.  We should really have a better
+                        * way of providing fairness.
+                        */
+                       xs->sc_link->openings += 2;
+               }
+       }
+}
+
+static int
+ahc_istagged_device(struct ahc_softc *ahc, struct scsipi_xfer *xs)
+{
+       char channel;
+       u_int our_id, target;
+       struct tmode_tstate *tstate;
+       struct ahc_devinfo devinfo;
+
+       channel = SIM_CHANNEL(ahc, xs->sc_link);
+       our_id = SIM_SCSI_ID(ahc, xs->sc_link);
+       target = xs->sc_link->scsipi_scsi.target;
+       (void)ahc_fetch_transinfo(ahc, channel, our_id, target, &tstate);
+
+       ahc_compile_devinfo(&devinfo, our_id, target,
+           xs->sc_link->scsipi_scsi.lun, channel, ROLE_INITIATOR);
+
+       return (tstate->tagenable & devinfo.target_mask);
+}



Home | Main Index | Thread Index | Old Index