summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorFederico G. Schwindt <fgsch@cvs.openbsd.org>2000-06-17 18:03:12 +0000
committerFederico G. Schwindt <fgsch@cvs.openbsd.org>2000-06-17 18:03:12 +0000
commit944785ea9ea0d0acfc51ebf684f957346346de6e (patch)
tree00b5db6e8e1aaa8ec8e50734fed0679f28da908f /sys/dev
parent3486ceb04e66405b06be9d342c5c5b71f6d27bc6 (diff)
Add support for AMD 53c974.
>From NetBSD.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ic/ncr53c9x.c104
-rw-r--r--sys/dev/ic/ncr53c9xreg.h7
-rw-r--r--sys/dev/ic/ncr53c9xvar.h41
3 files changed, 102 insertions, 50 deletions
diff --git a/sys/dev/ic/ncr53c9x.c b/sys/dev/ic/ncr53c9x.c
index c7eddbd1fbe..fb280889e43 100644
--- a/sys/dev/ic/ncr53c9x.c
+++ b/sys/dev/ic/ncr53c9x.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ncr53c9x.c,v 1.7 2000/06/12 06:10:45 fgsch Exp $ */
+/* $OpenBSD: ncr53c9x.c,v 1.8 2000/06/17 18:03:11 fgsch Exp $ */
/* $NetBSD: ncr53c9x.c,v 1.26 1998/05/26 23:17:34 thorpej Exp $ */
/*
@@ -140,6 +140,7 @@ const char *ncr53c9x_variant_names[] = {
"ESP406",
"FAS408",
"FAS216",
+ "AM53C974",
};
/*
@@ -221,18 +222,6 @@ ncr53c9x_attach(sc, adapter, dev)
* Now try to attach all the sub-devices
*/
config_found(&sc->sc_dev, &sc->sc_link, scsiprint);
-
- /*
- * Enable interupts from the SCSI core
- */
- if ((sc->sc_rev == NCR_VARIANT_ESP406) ||
- (sc->sc_rev == NCR_VARIANT_FAS408)) {
- NCR_PIOREGS(sc);
- NCR_WRITE_REG(sc, NCR_CFG5, NCRCFG5_SINT |
- NCR_READ_REG(sc, NCR_CFG5));
- NCR_SCSIREGS(sc);
- }
-
}
/*
@@ -260,7 +249,9 @@ ncr53c9x_reset(sc)
switch (sc->sc_rev) {
case NCR_VARIANT_ESP406:
case NCR_VARIANT_FAS408:
- NCR_SCSIREGS(sc);
+ NCR_WRITE_REG(sc, NCR_CFG5, sc->sc_cfg5 | NCRCFG5_SINT);
+ NCR_WRITE_REG(sc, NCR_CFG4, sc->sc_cfg4);
+ case NCR_VARIANT_AM53C974:
case NCR_VARIANT_FAS216:
case NCR_VARIANT_NCR53C94:
case NCR_VARIANT_NCR53C96:
@@ -283,6 +274,9 @@ ncr53c9x_reset(sc)
NCR_WRITE_REG(sc, NCR_SYNCOFF, 0);
NCR_WRITE_REG(sc, NCR_TIMEOUT, sc->sc_timeout);
}
+
+ if (sc->sc_rev == NCR_VARIANT_AM53C974)
+ NCR_WRITE_REG(sc, NCR_AMDCFG4, sc->sc_cfg4);
}
/*
@@ -432,8 +426,23 @@ ncr53c9x_setsync(sc, ti)
* put the chip in Fast SCSI mode.
*/
if (ti->period <= 50)
- cfg3 |= NCRCFG3_FSCSI;
+ /*
+ * There are (at least) 4 variations of the
+ * configuration 3 register. The drive attach
+ * routine sets the appropriate bit to put the
+ * chip into Fast SCSI mode so that it doesn't
+ * have to be figured out here each time.
+ */
+ cfg3 |= sc->sc_cfg3_fscsi;
}
+
+ /*
+ * Am53c974 requires different SYNCTP values when the
+ * FSCSI bit is off.
+ */
+ if (sc->sc_rev == NCR_VARIANT_AM53C974 &&
+ (cfg3 & NCRAMDCFG3_FSCSI) == 0)
+ synctp--;
} else {
syncoff = 0;
synctp = 0;
@@ -466,6 +475,7 @@ ncr53c9x_select(sc, ecb)
int tiflags = ti->flags;
u_char *cmd;
int clen;
+ size_t dmasize;
NCR_TRACE(("[ncr53c9x_select(t%d,l%d,cmd:%x)] ",
target, lun, ecb->cmd.cmd.opcode));
@@ -488,9 +498,46 @@ ncr53c9x_select(sc, ecb)
NCR_WRITE_REG(sc, NCR_SELID, target);
ncr53c9x_setsync(sc, ti);
- if (ncr53c9x_dmaselect && (tiflags & T_NEGOTIATE) == 0) {
- size_t dmasize;
+ if (ecb->flags & ECB_SENSE) {
+ /*
+ * For REQUEST SENSE, we should not send an IDENTIFY or
+ * otherwise mangle the target. There should be no MESSAGE IN
+ * phase.
+ */
+ if (ncr53c9x_dmaselect) {
+ /* setup DMA transfer for command */
+ dmasize = clen = ecb->clen;
+ sc->sc_cmdlen = clen;
+ sc->sc_cmdp = (caddr_t)&ecb->cmd + 1;
+ NCRDMA_SETUP(sc, &sc->sc_cmdp, &sc->sc_cmdlen, 0,
+ &dmasize);
+ /* Program the SCSI counter */
+ NCR_WRITE_REG(sc, NCR_TCL, dmasize);
+ NCR_WRITE_REG(sc, NCR_TCM, dmasize >> 8);
+ if (sc->sc_cfg2 & NCRCFG2_FE) {
+ NCR_WRITE_REG(sc, NCR_TCH, dmasize >> 16);
+ }
+
+ /* load the count in */
+ NCRCMD(sc, NCRCMD_NOP|NCRCMD_DMA);
+
+ /* And get the targets attention */
+ NCRCMD(sc, NCRCMD_SELNATN | NCRCMD_DMA);
+ NCRDMA_GO(sc);
+ } else {
+ /* Now the command into the FIFO */
+ cmd = (u_char *)&ecb->cmd.cmd;
+ clen = ecb->clen;
+ while (clen--)
+ NCR_WRITE_REG(sc, NCR_FIFO, *cmd++);
+
+ NCRCMD(sc, NCRCMD_SELNATN);
+ }
+ return;
+ }
+
+ if (ncr53c9x_dmaselect && (tiflags & T_NEGOTIATE) == 0) {
ecb->cmd.id =
MSG_IDENTIFY(lun, (tiflags & T_RSELECTOFF)?0:1);
@@ -1347,9 +1394,10 @@ ncr53c9x_msgout(sc)
*/
int sdebug = 0;
int
-ncr53c9x_intr(sc)
- register struct ncr53c9x_softc *sc;
+ncr53c9x_intr(arg)
+ void *arg;
{
+ register struct ncr53c9x_softc *sc = arg;
register struct ncr53c9x_ecb *ecb;
register struct scsi_link *sc_link;
struct ncr53c9x_tinfo *ti;
@@ -1362,12 +1410,13 @@ ncr53c9x_intr(sc)
return (0);
again:
- /* and what do the registers day... */
+ /* and what do the registers say... */
ncr53c9x_readregs(sc);
sc->sc_intrcnt.ev_count++;
/*
+ * At the moment, only a SCSI Bus Reset or Illegal
* Command are classed as errors. A disconnect is a
* valid condition, and we let the code check is the
* "NCR_BUSFREE_OK" flag was set before declaring it
@@ -1424,7 +1473,7 @@ again:
ecb->xs->error = XS_TIMEOUT;
ncr53c9x_done(sc, ecb);
}
- return (1);
+ return (1);
}
if (sc->sc_espintr & NCRINTR_ILL) {
@@ -1610,7 +1659,7 @@ again:
case NCR_SBR:
printf("%s: waiting for SCSI Bus Reset to happen\n",
sc->sc_dev.dv_xname);
- return (1);
+ return (1);
case NCR_RESELECTED:
/*
@@ -1693,7 +1742,7 @@ printf("<<RESELECT CONT'd>>");
sc->sc_espstat,
sc->sc_espstep,
sc->sc_prevphase);
- ncr53c9x_init(sc, 1);
+ ncr53c9x_init(sc, 1);
return (1);
}
sc->sc_selid = NCR_READ_REG(sc, NCR_FIFO);
@@ -1781,8 +1830,8 @@ printf("<<RESELECT CONT'd>>");
break;
} else if ((NCR_READ_REG(sc, NCR_FFLAG)
& NCRFIFO_FF) == 0) {
- /* Hope for the best.. */
- break;
+ /* Hope for the best.. */
+ break;
}
printf("(%s:%d:%d): selection failed;"
" %d left in FIFO "
@@ -1800,6 +1849,7 @@ printf("<<RESELECT CONT'd>>");
case 2:
/* Select stuck at Command Phase */
NCRCMD(sc, NCRCMD_FLUSH);
+ break;
case 4:
if (ncr53c9x_dmaselect &&
sc->sc_cmdlen != 0)
@@ -1861,9 +1911,10 @@ printf("<<RESELECT CONT'd>>");
}
if ((NCR_READ_REG(sc, NCR_FFLAG)
& NCRFIFO_FF) != 2) {
+ /* Drop excess bytes from the queue */
int i = (NCR_READ_REG(sc, NCR_FFLAG)
& NCRFIFO_FF) - 2;
- while (i--)
+ while (i-- > 0)
(void) NCR_READ_REG(sc, NCR_FIFO);
}
ecb->stat = NCR_READ_REG(sc, NCR_FIFO);
@@ -2020,6 +2071,7 @@ printf("<<RESELECT CONT'd>>");
sc->sc_flags |= NCR_ICCS;
NCRCMD(sc, NCRCMD_ICCS);
sc->sc_prevphase = STATUS_PHASE;
+ goto shortcut; /* i.e. expect status results soon */
break;
case INVALID_PHASE:
break;
diff --git a/sys/dev/ic/ncr53c9xreg.h b/sys/dev/ic/ncr53c9xreg.h
index 521fc9724b9..b4aee50e0fa 100644
--- a/sys/dev/ic/ncr53c9xreg.h
+++ b/sys/dev/ic/ncr53c9xreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ncr53c9xreg.h,v 1.3 2000/06/12 06:39:36 fgsch Exp $ */
+/* $OpenBSD: ncr53c9xreg.h,v 1.4 2000/06/17 18:03:11 fgsch Exp $ */
/* $NetBSD: ncr53c9xreg.h,v 1.4 1997/05/17 20:56:55 pk Exp $ */
/*
@@ -184,11 +184,6 @@
#define NCRCFG4_RSVD 0x7b /* reserved */
#define NCRCFG4_ACTNEG 0x04 /* Active negation */
-#define NCR_SCSIREGS(sc) do { NCR_WRITE_REG(sc, NCR_CFG4, \
- ~NCRCFG4_CRS1 & NCR_READ_REG(sc, NCR_CFG4)); } while(0)
-#define NCR_PIOREGS(sc) do { NCR_WRITE_REG(sc, NCR_CFG4, \
- NCRCFG4_CRS1 | NCR_READ_REG(sc, NCR_CFG4)); } while(0)
-
/*
The following registers are only on the ESP406/FAS408. The
documentation refers to them as "Control Register Set #1".
diff --git a/sys/dev/ic/ncr53c9xvar.h b/sys/dev/ic/ncr53c9xvar.h
index 39c277ef60b..481bdf3af54 100644
--- a/sys/dev/ic/ncr53c9xvar.h
+++ b/sys/dev/ic/ncr53c9xvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ncr53c9xvar.h,v 1.5 1998/09/02 06:09:28 deraadt Exp $ */
+/* $OpenBSD: ncr53c9xvar.h,v 1.6 2000/06/17 18:03:11 fgsch Exp $ */
/* $NetBSD: ncr53c9xvar.h,v 1.13 1998/05/26 23:17:34 thorpej Exp $ */
/*-
@@ -87,7 +87,8 @@
#define NCR_VARIANT_ESP406 5
#define NCR_VARIANT_FAS408 6
#define NCR_VARIANT_FAS216 7
-#define NCR_VARIANT_MAX 8
+#define NCR_VARIANT_AM53C974 8
+#define NCR_VARIANT_MAX 9
/*
* ECB. Holds additional information for each SCSI command Comments: We
@@ -242,6 +243,9 @@ struct ncr53c9x_softc {
u_char sc_cfg1; /* Config 1 */
u_char sc_cfg2; /* Config 2, not ESP100 */
u_char sc_cfg3; /* Config 3, only ESP200 */
+ u_char sc_cfg3_fscsi; /* Chip specific FSCSI bit */
+ u_char sc_cfg4; /* Config 4 */
+ u_char sc_cfg5; /* Config 5 */
u_char sc_ccf; /* Clock Conversion */
u_char sc_timeout;
@@ -256,19 +260,19 @@ struct ncr53c9x_softc {
ready_list,
nexus_list;
- struct ncr53c9x_ecb *sc_nexus; /* current command */
- struct ncr53c9x_ecb sc_ecb[3*8]; /* three per target */
+ struct ncr53c9x_ecb *sc_nexus; /* Current command */
+ struct ncr53c9x_ecb sc_ecb[3*8]; /* Three per target */
struct ncr53c9x_tinfo sc_tinfo[8];
/* Data about the current nexus (updated for every cmd switch) */
- caddr_t sc_dp; /* Current data pointer */
- ssize_t sc_dleft; /* Data left to transfer */
+ caddr_t sc_dp; /* Current data pointer */
+ ssize_t sc_dleft; /* Data left to transfer */
/* Adapter state */
- int sc_phase; /* Copy of what bus phase we are in */
- int sc_prevphase; /* Copy of what bus phase we were in */
- u_char sc_state; /* State applicable to the adapter */
- u_char sc_flags;
+ int sc_phase; /* Copy of what bus phase we are in */
+ int sc_prevphase; /* Copy of what bus phase we were in */
+ u_char sc_state; /* State applicable to the adapter */
+ u_char sc_flags; /* See below */
u_char sc_selid;
u_char sc_lastcmd;
@@ -286,13 +290,13 @@ struct ncr53c9x_softc {
caddr_t sc_cmdp; /* Command pointer (for DMAed commands) */
size_t sc_cmdlen; /* Size of command in transit */
- /* hardware/openprom stuff */
- int sc_freq; /* Freq in MHz */
- int sc_id; /* our scsi id */
- int sc_rev; /* esp revision */
- int sc_features; /* chip features */
- int sc_minsync; /* minimum sync period / 4 */
- int sc_maxxfer; /* maximum transfer size */
+ /* Hardware attributes */
+ int sc_freq; /* SCSI bus frequency in MHz */
+ int sc_id; /* Our SCSI id */
+ int sc_rev; /* Chip revision */
+ int sc_features; /* Chip features */
+ int sc_minsync; /* Minimum sync period / 4 */
+ int sc_maxxfer; /* Maximum transfer size */
};
/* values for sc_state */
@@ -393,6 +397,7 @@ void ncr53c9x_attach __P((struct ncr53c9x_softc *,
struct scsi_adapter *, struct scsi_device *));
int ncr53c9x_scsi_cmd __P((struct scsi_xfer *));
void ncr53c9x_reset __P((struct ncr53c9x_softc *));
-int ncr53c9x_intr __P((struct ncr53c9x_softc *));
+int ncr53c9x_intr __P((void *));
+void ncr53c9x_init __P((struct ncr53c9x_softc *, int));
extern int ncr53c9x_dmaselect;