Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/ic Add TAG QUEUE support to the ncr53c9x driver.



details:   https://anonhg.NetBSD.org/src/rev/d2aafc15a669
branches:  trunk
changeset: 499807:d2aafc15a669
user:      eeh <eeh%NetBSD.org@localhost>
date:      Thu Nov 30 00:19:25 2000 +0000

description:
Add TAG QUEUE support to the ncr53c9x driver.

diffstat:

 sys/dev/ic/ncr53c9x.c    |  658 ++++++++++++++++++++++++++++++++++++++--------
 sys/dev/ic/ncr53c9xvar.h |   97 ++++--
 2 files changed, 604 insertions(+), 151 deletions(-)

diffs (truncated from 1288 to 300 lines):

diff -r a9fc2f689794 -r d2aafc15a669 sys/dev/ic/ncr53c9x.c
--- a/sys/dev/ic/ncr53c9x.c     Thu Nov 30 00:04:08 2000 +0000
+++ b/sys/dev/ic/ncr53c9x.c     Thu Nov 30 00:19:25 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ncr53c9x.c,v 1.53 2000/11/13 15:24:22 pk Exp $ */
+/*     $NetBSD: ncr53c9x.c,v 1.54 2000/11/30 00:19:25 eeh Exp $        */
 
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -89,6 +89,7 @@
 #include <sys/proc.h>
 #include <sys/user.h>
 #include <sys/queue.h>
+#include <sys/pool.h>
 #include <sys/scsiio.h>
 
 #include <dev/scsipi/scsi_all.h>
@@ -102,11 +103,14 @@
 #include <dev/ic/ncr53c9xvar.h>
 
 int ncr53c9x_debug = 0; /*NCR_SHOWPHASE|NCR_SHOWMISC|NCR_SHOWTRAC|NCR_SHOWCMDS;*/
+#ifdef DEBUG
+int ncr53c9x_notag = 0;
+#endif
 
 /*static*/ void        ncr53c9x_readregs       __P((struct ncr53c9x_softc *));
 /*static*/ void        ncr53c9x_select         __P((struct ncr53c9x_softc *,
                                            struct ncr53c9x_ecb *));
-/*static*/ int ncr53c9x_reselect       __P((struct ncr53c9x_softc *, int));
+/*static*/ int ncr53c9x_reselect       __P((struct ncr53c9x_softc *, int, int, int));
 /*static*/ void        ncr53c9x_scsi_reset     __P((struct ncr53c9x_softc *));
 /*static*/ int ncr53c9x_poll           __P((struct ncr53c9x_softc *,
                                            struct scsipi_xfer *, int));
@@ -116,6 +120,7 @@
 /*static*/ void        ncr53c9x_msgin          __P((struct ncr53c9x_softc *));
 /*static*/ void        ncr53c9x_msgout         __P((struct ncr53c9x_softc *));
 /*static*/ void        ncr53c9x_timeout        __P((void *arg));
+/*static*/ void        ncr53c9x_watch          __P((void *arg));
 /*static*/ void        ncr53c9x_abort          __P((struct ncr53c9x_softc *,
                                            struct ncr53c9x_ecb *));
 /*static*/ void ncr53c9x_dequeue       __P((struct ncr53c9x_softc *,
@@ -132,6 +137,10 @@
 static inline int ncr53c9x_stp2cpb     __P((struct ncr53c9x_softc *, int));
 static inline void ncr53c9x_setsync    __P((struct ncr53c9x_softc *,
                                            struct ncr53c9x_tinfo *));
+static struct ncr53c9x_linfo *ncr53c9x_lunsearch __P((struct ncr53c9x_tinfo *,
+                                                            int64_t lun));
+static int ecb_pool_initialized = 0;
+static struct pool ecb_pool;
 
 /*
  * Names for the NCR53c9x variants, correspnding to the variant tags
@@ -166,6 +175,21 @@
 };
 
 /*
+ * Search linked list for LUN info by LUN id.
+ */
+static struct ncr53c9x_linfo *
+ncr53c9x_lunsearch(ti, lun)
+       struct ncr53c9x_tinfo *ti;
+       int64_t lun;
+{
+       struct ncr53c9x_linfo *li;
+       LIST_FOREACH(li, &ti->luns, link) 
+               if (li->lun == lun)
+                       return (li);
+       return (NULL);
+}
+
+/*
  * Attach this instance, and then all the sub-devices
  */
 void
@@ -175,6 +199,7 @@
        struct scsipi_device *device;
 {
 
+       callout_init(&sc->sc_watchdog);
        /*
         * Allocate SCSI message buffers.
         * Front-ends can override allocation to avoid alignment
@@ -234,7 +259,7 @@
        sc->sc_link.scsipi_scsi.adapter_target = sc->sc_id;
        sc->sc_link.adapter = (adapter) ? adapter : &ncr53c9x_adapter;
        sc->sc_link.device = (device) ? device : &ncr53c9x_device;
-       sc->sc_link.openings = 2;
+       sc->sc_link.openings = 32;
        sc->sc_link.scsipi_scsi.max_target = 7;
        sc->sc_link.scsipi_scsi.max_lun = 7;
        sc->sc_link.type = BUS_SCSI;
@@ -260,6 +285,7 @@
        sc->sc_child = config_found(&sc->sc_dev, &sc->sc_link, scsiprint);
 
        scsipi_adapter_delref(&sc->sc_link);
+       callout_reset(&sc->sc_watchdog, 60*hz, ncr53c9x_watch, sc);
 }
 
 int
@@ -359,33 +385,58 @@
        int doreset;
 {
        struct ncr53c9x_ecb *ecb;
-       int r;
+       struct ncr53c9x_linfo *li;
+       int i, r;
 
        NCR_TRACE(("[NCR_INIT(%d)] ", doreset));
 
+       if (!ecb_pool_initialized) {
+               /* All instances share this pool */
+               pool_init(&ecb_pool, sizeof(struct ncr53c9x_ecb), 0, 0, 0, 
+                         "ncr53c9x_ecb", 0, NULL, NULL, 0);
+               ecb_pool_initialized = 1;
+       }
+
        if (sc->sc_state == 0) {
                /* First time through; initialize. */
+
                TAILQ_INIT(&sc->ready_list);
-               TAILQ_INIT(&sc->nexus_list);
-               TAILQ_INIT(&sc->free_list);
                sc->sc_nexus = NULL;
-               ecb = sc->sc_ecb;
-               bzero(ecb, sizeof(sc->sc_ecb));
-               for (r = 0; r < sizeof(sc->sc_ecb) / sizeof(*ecb); r++) {
-                       TAILQ_INSERT_TAIL(&sc->free_list, ecb, chain);
-                       ecb++;
+               bzero(sc->sc_tinfo, sizeof(sc->sc_tinfo));
+               for (r=0; r<NCR_NTARG; r++) {
+                       LIST_INIT(&sc->sc_tinfo[r].luns);
                }
-               bzero(sc->sc_tinfo, sizeof(sc->sc_tinfo));
        } else {
                /* Cancel any active commands. */
                sc->sc_state = NCR_CLEANING;
+               sc->sc_msgify = 0;
                if ((ecb = sc->sc_nexus) != NULL) {
                        ecb->xs->error = XS_TIMEOUT;
                        ncr53c9x_done(sc, ecb);
                }
-               while ((ecb = sc->nexus_list.tqh_first) != NULL) {
-                       ecb->xs->error = XS_TIMEOUT;
-                       ncr53c9x_done(sc, ecb);
+               /* Cancel outstanding disconnected commands on each LUN */
+               for (r=0; r<8; r++) {
+                       LIST_FOREACH(li, &sc->sc_tinfo[r].luns, link) {
+                               if ((ecb = li->untagged)) {
+                                       li->untagged = NULL;
+                                       /* 
+                                        * XXXXXXX
+                                        *
+                                        * Should we terminate a command 
+                                        * that never reached the disk? 
+                                        */
+                                       li->busy = 0;
+                                       ecb->xs->error = XS_TIMEOUT;
+                                       ncr53c9x_done(sc, ecb);
+                               }
+                               for (i=0; i<256; i++)
+                                       if ((ecb = li->queued[i])) {
+                                               li->queued[i] = NULL;
+                                               ecb->xs->error = XS_TIMEOUT;
+                                               ncr53c9x_done(sc, ecb);
+                                       }
+                               li->used = 0;
+                       }
                }
        }
 
@@ -399,10 +450,14 @@
                struct ncr53c9x_tinfo *ti = &sc->sc_tinfo[r];
 /* XXX - config flags per target: low bits: no reselect; high bits: no synch */
 
-               ti->flags = (((sc->sc_cfflags & (1<<(r+8))) != 0)
-                               ? T_SYNCHOFF : 0) |
-                               ((sc->sc_cfflags & (1<<r)) ? T_RSELECTOFF : 0) |
-                               T_NEED_TO_RESET;
+               ti->flags = ((sc->sc_cfflags & (1<<(r+16))) ? T_TAGOFF : 0) |
+                       ((sc->sc_minsync && !(sc->sc_cfflags & (1<<(r+8))))
+                        ? T_SYNCHOFF : 0) |
+                       ((sc->sc_cfflags & (1<<r)) ? T_RSELECTOFF : 0) |
+                       T_NEED_TO_RESET;
+#ifdef DEBUG
+               if (ncr53c9x_notag) ti->flags |= T_TAGOFF;
+#endif
                ti->period = sc->sc_minsync;
                ti->offset = 0;
        }
@@ -534,11 +589,10 @@
        int clen;
        size_t dmasize;
 
-       NCR_TRACE(("[ncr53c9x_select(t%d,l%d,cmd:%x)] ",
-                  target, lun, ecb->cmd.cmd.opcode));
+       NCR_TRACE(("[ncr53c9x_select(t%d,l%d,cmd:%x,tag:%x,%x)] ",
+                  target, lun, ecb->cmd.cmd.opcode, ecb->tag[0], ecb->tag[1]));
 
        sc->sc_state = NCR_SELECTING;
-
        /*
         * Schedule the timeout now, the first time we will go away
         * expecting to come back due to an interrupt, because it is
@@ -572,7 +626,7 @@
                        /* setup DMA transfer for command */
                        dmasize = clen = ecb->clen;
                        sc->sc_cmdlen = clen;
-                       sc->sc_cmdp = (caddr_t)&ecb->cmd + 1;
+                       sc->sc_cmdp = (caddr_t)&ecb->cmd.cmd;
                        NCRDMA_SETUP(sc, &sc->sc_cmdp, &sc->sc_cmdlen, 0, &dmasize);
        
                        /* Program the SCSI counter */
@@ -589,7 +643,7 @@
                        NCRCMD(sc, NCRCMD_SELNATN | NCRCMD_DMA);
                        NCRDMA_GO(sc);
                } else {
-                       /* Now the command into the FIFO */
+                       /* Now get the command into the FIFO */
                        cmd = (u_char *)&ecb->cmd.cmd;
                        clen = ecb->clen;
                        while (clen--)
@@ -600,14 +654,26 @@
                return;
        }
 
+       if (ecb->tag[0]) {
+               /* We'll use tags */
+               ecb->cmd.msg[0] = MSG_IDENTIFY(lun, 1);
+               ecb->cmd.msg[1] = ecb->tag[0];
+               ecb->cmd.msg[2] = ecb->tag[1];
+               cmd = (u_char *)&ecb->cmd.msg[0];
+               clen = ecb->clen + 3;
+       } else {
+               ecb->cmd.msg[2] = 
+                       MSG_IDENTIFY(lun, (tiflags & T_RSELECTOFF)?0:1);
+               cmd = (u_char *)&ecb->cmd.msg[2];
+               clen = ecb->clen + 1;
+       }
+
        if (ncr53c9x_dmaselect && (tiflags & T_NEGOTIATE) == 0) {
-               ecb->cmd.id = 
-                   MSG_IDENTIFY(lun, (tiflags & T_RSELECTOFF)?0:1);
 
                /* setup DMA transfer for command */
-               dmasize = clen = ecb->clen + 1;
+               dmasize = clen;
                sc->sc_cmdlen = clen;
-               sc->sc_cmdp = (caddr_t)&ecb->cmd;
+               sc->sc_cmdp = cmd;
                NCRDMA_SETUP(sc, &sc->sc_cmdp, &sc->sc_cmdlen, 0, &dmasize);
 
                /* Program the SCSI counter */
@@ -621,7 +687,10 @@
                NCRCMD(sc, NCRCMD_NOP|NCRCMD_DMA);
 
                /* And get the targets attention */
-               NCRCMD(sc, NCRCMD_SELATN | NCRCMD_DMA);
+               if (ecb->tag[0])
+                       NCRCMD(sc, NCRCMD_SELATN3 | NCRCMD_DMA);
+               else
+                       NCRCMD(sc, NCRCMD_SELATN | NCRCMD_DMA);
                NCRDMA_GO(sc);
                return;
        }
@@ -630,8 +699,8 @@
         * Who am I. This is where we tell the target that we are
         * happy for it to disconnect etc.
         */
-       NCR_WRITE_REG(sc, NCR_FIFO,
-                     MSG_IDENTIFY(lun, (tiflags & T_RSELECTOFF)?0:1));
+       NCR_WRITE_REG(sc, NCR_FIFO, *cmd++);
+       clen --;
 
        if (ti->flags & T_NEGOTIATE) {
                /* Arbitrate, select and stop after IDENTIFY message */
@@ -639,14 +708,23 @@
                return;
        }
 
-       /* Now the command into the FIFO */
-       cmd = (u_char *)&ecb->cmd.cmd;
-       clen = ecb->clen;
+       /* If we want to send a tag, get it into the fifo */
+       if (ecb->tag[0]) {
+               NCR_WRITE_REG(sc, NCR_FIFO, *cmd++);
+               clen --;
+               NCR_WRITE_REG(sc, NCR_FIFO, *cmd++);
+               clen --;
+       }
+
+       /* Now get the command into the FIFO */
        while (clen--)
                NCR_WRITE_REG(sc, NCR_FIFO, *cmd++);
 
        /* And get the targets attention */
-       NCRCMD(sc, NCRCMD_SELATN);
+       if (ecb->tag[0])
+               NCRCMD(sc, NCRCMD_SELATN3 | NCRCMD_DMA);
+       else
+               NCRCMD(sc, NCRCMD_SELATN | NCRCMD_DMA);



Home | Main Index | Thread Index | Old Index