diff options
author | Federico G. Schwindt <fgsch@cvs.openbsd.org> | 2000-06-17 18:03:12 +0000 |
---|---|---|
committer | Federico G. Schwindt <fgsch@cvs.openbsd.org> | 2000-06-17 18:03:12 +0000 |
commit | 944785ea9ea0d0acfc51ebf684f957346346de6e (patch) | |
tree | 00b5db6e8e1aaa8ec8e50734fed0679f28da908f /sys/dev | |
parent | 3486ceb04e66405b06be9d342c5c5b71f6d27bc6 (diff) |
Add support for AMD 53c974.
>From NetBSD.
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/ic/ncr53c9x.c | 104 | ||||
-rw-r--r-- | sys/dev/ic/ncr53c9xreg.h | 7 | ||||
-rw-r--r-- | sys/dev/ic/ncr53c9xvar.h | 41 |
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; |