summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/mac68k/dev/scsi96.c188
-rw-r--r--sys/arch/mac68k/include/scsi96reg.h5
2 files changed, 123 insertions, 70 deletions
diff --git a/sys/arch/mac68k/dev/scsi96.c b/sys/arch/mac68k/dev/scsi96.c
index 3b354d4e9b1..0f86217fb20 100644
--- a/sys/arch/mac68k/dev/scsi96.c
+++ b/sys/arch/mac68k/dev/scsi96.c
@@ -1,5 +1,4 @@
-/* $OpenBSD: scsi96.c,v 1.3 1996/05/26 18:35:34 briggs Exp $ */
-/* $NetBSD: scsi96.c,v 1.17 1996/05/05 06:17:19 briggs Exp $ */
+/* $NetBSD: scsi96.c,v 1.21 1996/10/13 03:21:29 christos Exp $ */
/*
* Copyright (C) 1994 Allen K. Briggs
@@ -28,12 +27,6 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-/*
- * WARNING! This is a non-working driver at the moment!
- * That means it does not work! Contact Allen Briggs
- * (briggs@mail.vt.edu) for current status of this driver.
- */
-
#include <sys/types.h>
#include <sys/malloc.h>
#include <sys/param.h>
@@ -45,6 +38,7 @@
#include <sys/device.h>
#include <scsi/scsi_all.h>
#include <scsi/scsi_debug.h>
+#include <scsi/scsi_message.h>
#include <scsi/scsiconf.h>
#include <machine/scsi96reg.h>
@@ -57,8 +51,7 @@
#endif
extern vm_offset_t SCSIBase;
-static volatile unsigned char *ncr53c96base =
-(volatile unsigned char *) 0xF000; /* Offset from IOBase */
+static volatile unsigned char *ncr53c96base;
struct ncr53c96_softc {
struct device sc_dev;
@@ -68,8 +61,9 @@ struct ncr53c96_softc {
struct scsi_link sc_link;
};
#define WAIT_FOR(reg, val) { \
- int timeo=100000; \
+ int timeo=10000; \
while (!(reg & val)) { \
+ delay(100); \
if (!(--timeo)) { \
printf("scsi96: WAIT_FOR timeout.\n"); \
goto have_error; \
@@ -80,10 +74,12 @@ struct ncr53c96_softc {
static void ncr53c96_minphys(struct buf * bp);
static int ncr53c96_scsi_cmd(struct scsi_xfer * xs);
-static int ncr53c96_show_scsi_cmd(struct scsi_xfer * xs);
+/* static int ncr53c96_show_scsi_cmd(struct scsi_xfer * xs); */
static int ncr53c96_reset_target(int adapter, int target);
static int ncr53c96_poll(int adapter, int timeout);
static int ncr53c96_send_cmd(struct scsi_xfer * xs);
+static int scsiprint __P((void *, char *));
+static void resetchip __P((void));
struct scsi_adapter ncr53c96_switch = {
ncr53c96_scsi_cmd, /* scsi_cmd() */
@@ -111,16 +107,6 @@ struct cfdriver ncr96scsi_cd = {
NULL, "ncr96scsi", DV_DULL, NULL, 0
};
-static int ncr96_print __P((void *, char *));
-static int
-ncr96_print(aux, name)
- void *aux;
- char *name;
-{
- /* printf("%s: (sc_link = 0x%x)", name, (int) aux); return UNCONF; */
- return UNCONF;
-}
-
static int
ncr96probe(parent, match, aux)
struct device *parent;
@@ -129,40 +115,52 @@ ncr96probe(parent, match, aux)
{
static int probed = 0;
- return 0;
if (!mac68k_machine.scsi96) {
return 0;
}
if (!probed) {
probed = 1;
- ncr53c96base += SCSIBase;
+ ncr53c96base = (volatile u_char *)SCSIBase;
}
return 1;
}
+static int
+scsiprint(auxp, name)
+ void *auxp;
+ char *name;
+{
+ if (name == NULL)
+ return (UNCONF);
+ return (QUIET);
+}
+
static void
ncr96attach(parent, dev, aux)
struct device *parent, *dev;
void *aux;
{
- int unit = dev->dv_unit;
struct ncr53c96_softc *ncr53c96;
ncr53c96 = (struct ncr53c96_softc *) dev;
- ncr53c96->sc_link.scsibus = unit;
+ ncr53c96->sc_link.adapter_softc = ncr53c96;
ncr53c96->sc_link.adapter_target = 7;
ncr53c96->sc_link.adapter = &ncr53c96_switch;
ncr53c96->sc_link.device = &ncr53c96_dev;
ncr53c96->sc_link.openings = 1;
#ifdef SCSIDEBUG
- ncr53c96->sc_link.flags = SDEV_DB1 | SDEV_DB2 /* | SDEV_DB3 | SDEV_DB4 */ ;
+ ncr53c96->sc_link.flags = 0 /* SDEV_DB1 | SDEV_DB2 | SDEV_DB3 | SDEV_DB4 */ ;
+#else
+ ncr53c96->sc_link.flags = 0;
#endif
+ resetchip();
+
printf("\n");
- config_found(dev, &(ncr53c96->sc_link), ncr96_print);
+ config_found(dev, &(ncr53c96->sc_link), scsiprint);
/*
* Enable IRQ and DRQ interrupts.
@@ -256,6 +254,7 @@ ncr53c96_scsi_cmd(struct scsi_xfer * xs)
*/
}
+#if 0
static int
ncr53c96_show_scsi_cmd(struct scsi_xfer * xs)
{
@@ -279,6 +278,7 @@ ncr53c96_show_scsi_cmd(struct scsi_xfer * xs)
}
return 0;
}
+#endif
/*
* Actual chip control.
@@ -320,27 +320,46 @@ ncr53c96_poll(int adapter, int timeout)
return 0;
}
+static void
+resetchip(void)
+{
+ struct ncr53c96regs *ncr = (struct ncr53c96regs *) ncr53c96base;
+
+ ncr->cmdreg = NCR96_CMD_RESETDEV;
+ delay(25);
+ ncr->cmdreg = NCR96_CMD_NOOP;
+ delay(25);
+ ncr->clkfactorreg = 5; /* Is this right? */
+ delay(25);
+
+ ncr->soffsetreg = 0; /* make sure we use async xfers */
+ ncr->stimreg = 0x99; /* Value corresponding to clkfactorreg of 5 */
+ ncr->ctrlreg1 = 0x7; /* Our ID */
+ ncr->ctrlreg2 = 0;
+ ncr->ctrlreg3 = NCR96_C3_LBTM;
+}
+
static int
do_send_cmd(struct scsi_xfer * xs)
{
struct ncr53c96regs *ncr = (struct ncr53c96regs *) ncr53c96base;
u_char *cmd;
int i, stat, is, intr;
- int msg, phase;
+ int msg, phase, ds=0;
xs->resid = 0;
i = (int) ncr->statreg; /* clear interrupts */
+ i = (int) ncr->instreg;
ncr->cmdreg = NCR96_CMD_CLRFIFO; /* and fifo */
+ ncr->sdidreg = xs->sc_link->target;
+ ncr->fifo = MSG_IDENTIFY(xs->sc_link->lun, 0);
cmd = (u_char *) xs->cmd;
for (i = 0; i < xs->cmdlen; i++)
ncr->fifo = *cmd++;
- ncr->tcreg_lsb = xs->cmdlen;
+ ncr->tcreg_lsb = xs->cmdlen + 1;
ncr->tcreg_msb = 0;
- ncr->stimreg = 122; /* XXX */
- ncr->sdidreg = xs->sc_link->target;
-/* ncr->ctrlreg1 = 0x47; from the mac -- inherited*/
- ncr->cmdreg = NCR96_CMD_SEL;
+ ncr->cmdreg = NCR96_CMD_SELATN;
WAIT_FOR(ncr->statreg, NCR96_STAT_INT);
@@ -348,48 +367,78 @@ do_send_cmd(struct scsi_xfer * xs)
is = ncr->isreg;
intr = ncr->instreg;
if ((is & 0x07) != 0x4 || intr != 0x18) {
- if ((is & 0x7) != 0x0 || intr != 0x20) {
+ if ((is & 0x7) == 2 && intr == 0x18) {
+ /* Target selected, but invalid LUN */
+ resetchip();
+ xs->error = XS_SELTIMEOUT;
+ return COMPLETE;
+ } else if ((is & 0x7) != 0x0 || intr != 0x20) {
printf("scsi96: stat = 0x%x, is = 0x%x, intr = 0x%x\n",
stat, is, intr);
+ goto have_error;
}
- goto have_error;
+ xs->error = XS_SELTIMEOUT;
+ return COMPLETE;
}
+ ds = 1;
+/*
printf("scsi96: before loop: stat = 0x%x, is = 0x%x, intr = 0x%x, "
"datalen = %d\n", stat, is, intr, xs->datalen);
+*/
phase = ncr->statreg & NCR96_STAT_PHASE;
if (((phase == 0x01) || (phase == 0x00)) && xs->datalen) {
- printf("data = %p, datalen = 0x%x.\n", xs->data, xs->datalen);
+ /* printf("data = %p, datalen = 0x%x.\n", xs->data, xs->datalen); */
stat = ncr->statreg;
is = ncr->isreg;
intr = ncr->instreg;
- printf("entering info xfer...stat = 0x%x, is = 0x%x, intr = 0x%x\n",
- stat, is, intr);
+ /* printf("entering info xfer...stat = 0x%x, is = 0x%x, intr = 0x%x\n",
+ stat, is, intr); */
ncr->tcreg_lsb = (xs->datalen & 0xff);
ncr->tcreg_msb = (xs->datalen >> 8) & 0xff;
- ncr->cmdreg = 0x80 | NCR96_CMD_INFOXFER;
- printf("rem... %d.\n", ncr->tcreg_lsb | (ncr->tcreg_msb << 8));
+/* ncr->cmdreg = 0x80 | NCR96_CMD_INFOXFER; */
+ /* printf("rem... %d.\n", ncr->tcreg_lsb | (ncr->tcreg_msb << 8)); */
i = 0;
while (i < xs->datalen) {
- int d, stat;
+ int d, stat, newphase;
+
+ ncr->cmdreg = NCR96_CMD_INFOXFER;
- WAIT_FOR(ncr->statreg, NCR96_STAT_INT);
+ if (phase == 1) {
+ WAIT_FOR(ncr->statreg, NCR96_STAT_INT);
- stat = ncr->statreg;
+ stat = ncr->statreg;
+ newphase = stat & NCR96_STAT_PHASE;
- for (d = 1000000; d && !(via_reg(VIA2, vIFR) & 0x01); d--);
- if (d <= 0)
- printf("read timeout.\n");
- d = ncr->fifostatereg & NCR96_CF_MASK;
+ d = ncr->fifostatereg & NCR96_CF_MASK;
+
+ while (d--) {
+ xs->data[i++] = ncr->fifo;
+ /* printf("0x%x,", xs->data[i - 1]);*/
+ }
+ } else {
+ /* printf("out %02x ", xs->data[i]); */
+ ncr->fifo = xs->data[i++];
+ WAIT_FOR(ncr->statreg, NCR96_STAT_INT);
- while (d--) {
- xs->data[i++] = ncr->fifo;
- printf("0x%x,", xs->data[i - 1]);
+ stat = ncr->statreg;
+ newphase = stat & NCR96_STAT_PHASE;
}
intr = ncr->instreg;
- printf("\nin loop. stat = 0x%x, intr = 0x%x",
- stat, intr);
- printf("rem... %d.\n", ncr->tcreg_lsb | (ncr->tcreg_msb << 8));
+
+#if 0
+ if (phase == 0)
+ printf("in loop. stat = 0x%x, intr = 0x%x\n",
+ stat, intr);
+#endif
+
+ if ((i != xs->datalen) && (phase != newphase)) {
+ intr = ncr->instreg;
+ if (phase == 0)
+ printf("Unexpected phase change during data out from %d to %d, got %d of %d\n", phase, newphase, i, xs->datalen);
+ break;
+ }
+
}
/* } else {
WAIT_FOR(ncr->statreg, NCR96_STAT_INT); */
@@ -397,8 +446,14 @@ do_send_cmd(struct scsi_xfer * xs)
stat = ncr->statreg;
is = ncr->isreg;
intr = ncr->instreg;
+/*
printf("past loop...stat = 0x%x, is = 0x%x, intr = 0x%x\n",
stat, is, intr);
+*/
+
+ phase = stat & NCR96_STAT_PHASE;
+ if (phase != 3)
+ printf("Expected to be in phase 3, but in phase %d\n", phase);
ncr->cmdreg = NCR96_CMD_ICCS;
@@ -411,6 +466,10 @@ do_send_cmd(struct scsi_xfer * xs)
xs->status = ncr->fifo;
msg = ncr->fifo;
+/*
+ printf("got Status %d, Message %d, stat = 0x%x, is = 0x%x, intr = 0x%x\n", xs->status, msg, stat, is, intr);
+*/
+
ncr->cmdreg = NCR96_CMD_MSGACC;
WAIT_FOR(ncr->statreg, NCR96_STAT_INT);
@@ -418,10 +477,15 @@ do_send_cmd(struct scsi_xfer * xs)
stat = ncr->statreg;
is = ncr->isreg;
intr = ncr->instreg;
- if (intr == 0x20 && stat == 0x90)
+ if ((intr == 0x20) && (stat & 0x80)) {
+ xs->error = XS_NOERROR;
return COMPLETE;
+ }
have_error:
+ printf("Driver stuffup...stat=0x%x, is=0x%x, intr=0x%x, ds=%d\n",
+ stat, is, intr, ds);
+ resetchip();
xs->error = XS_DRIVER_STUFFUP;
return COMPLETE;
}
@@ -429,17 +493,5 @@ have_error:
static int
ncr53c96_send_cmd(struct scsi_xfer * xs)
{
- int r = COMPLETE;
-
- if (xs->sc_link->target >= 5)
- ncr53c96_show_scsi_cmd(xs);
- switch (xs->cmd->opcode) {
- case 0: /* TUN */
- case 0x12: /* INQUIRY */
- r = do_send_cmd(xs);
- default:
- xs->error = XS_DRIVER_STUFFUP;
- r = COMPLETE;
- }
- return r;
+ return do_send_cmd(xs);
}
diff --git a/sys/arch/mac68k/include/scsi96reg.h b/sys/arch/mac68k/include/scsi96reg.h
index 28397cf1a9c..7ea41515a62 100644
--- a/sys/arch/mac68k/include/scsi96reg.h
+++ b/sys/arch/mac68k/include/scsi96reg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: scsi96reg.h,v 1.3 1996/05/26 18:36:03 briggs Exp $ */
+/* $OpenBSD: scsi96reg.h,v 1.4 1996/10/23 04:52:03 briggs Exp $ */
/* $NetBSD: scsi96reg.h,v 1.5 1996/05/05 06:18:02 briggs Exp $ */
/*
@@ -52,6 +52,7 @@ struct ncr53c96regs {
v_uchar isreg; /* internal state reg */
PAD(pad6);
v_uchar fifostatereg; /* fifo state reg */
+#define soffsetreg fifostatereg
PAD(pad7);
v_uchar ctrlreg1; /* control register 1 */
PAD(pad8);
@@ -166,7 +167,7 @@ struct ncr53c96regs {
#define NCR96_CNTLREG3 0xC /* Control register three. R/W */
#define NCR96_C3_LBTM 0x04 /* Last byte transfer mode */
-#define NCR96_C3_MDM 0x02 /* Modity DMA mode */
+#define NCR96_C3_MDM 0x02 /* Modify DMA mode */
#define NCR96_C3_BS8 0x01 /* Burst Size 8 */
#define NCR96_DALREG 0xF /* Data alignment register. W */