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