Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/ic Handle "scsi bus mode change" interrupts on 895 a...
details: https://anonhg.NetBSD.org/src/rev/5ec992748170
branches: trunk
changeset: 487769:5ec992748170
user: bouyer <bouyer%NetBSD.org@localhost>
date: Mon Jun 12 20:13:41 2000 +0000
description:
Handle "scsi bus mode change" interrupts on 895 and higther.
Thanks to Hal Murray for reporting the problem and testing the fix.
diffstat:
sys/dev/ic/siop.c | 29 ++++++++++++++++++++---
sys/dev/ic/siop_common.c | 56 ++++++++++++++++++++++++++++++++++++++++++++-
sys/dev/ic/siopreg.h | 4 ++-
sys/dev/ic/siopvar_common.h | 3 +-
4 files changed, 85 insertions(+), 7 deletions(-)
diffs (173 lines):
diff -r 7ee75c8240cd -r 5ec992748170 sys/dev/ic/siop.c
--- a/sys/dev/ic/siop.c Mon Jun 12 19:49:17 2000 +0000
+++ b/sys/dev/ic/siop.c Mon Jun 12 20:13:41 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: siop.c,v 1.19 2000/06/07 14:40:20 tsutsui Exp $ */
+/* $NetBSD: siop.c,v 1.20 2000/06/12 20:13:41 bouyer Exp $ */
/*
* Copyright (c) 2000 Manuel Bouyer.
@@ -388,8 +388,6 @@
}
}
if (cbdp == NULL) {
- printf("%s: current DSA invalid\n",
- sc->sc_dev.dv_xname);
siop_cmd = NULL;
}
if (istat & ISTAT_DIP) {
@@ -433,6 +431,9 @@
printf("last msg_in=0x%x status=0x%x\n",
siop_cmd->siop_table->msg_in[0],
le32toh(siop_cmd->siop_table->status));
+ else
+ printf("%s: current DSA invalid\n",
+ sc->sc_dev.dv_xname);
need_reset = 1;
}
}
@@ -564,6 +565,26 @@
"command\n", sc->sc_dev.dv_xname);
goto reset;
}
+ if (sist1 & SIST1_SBMC) {
+ /* SCSI bus mode change */
+ if (siop_modechange(sc) == 0 || need_reset == 1)
+ goto reset;
+ if ((istat & ISTAT_DIP) && (dstat & DSTAT_SIR)) {
+ /*
+ * we have a script interrupt, it will
+ * restart the script.
+ */
+ goto scintr;
+ }
+ /*
+ * else we have to restart it ourselve, at the
+ * interrupted instruction.
+ */
+ bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSP,
+ bus_space_read_4(sc->sc_rt, sc->sc_rh,
+ SIOP_DSP) - 8);
+ return 1;
+ }
/* Else it's an unhandled exeption (for now). */
printf("%s: unhandled scsi interrupt, sist0=0x%x sist1=0x%x "
"sstat1=0x%x DSA=0x%x DSP=0x%x\n", sc->sc_dev.dv_xname,
@@ -592,7 +613,7 @@
return 1;
}
-
+scintr:
if ((istat & ISTAT_DIP) && (dstat & DSTAT_SIR)) { /* script interrupt */
irqcode = bus_space_read_4(sc->sc_rt, sc->sc_rh,
SIOP_DSPS);
diff -r 7ee75c8240cd -r 5ec992748170 sys/dev/ic/siop_common.c
--- a/sys/dev/ic/siop_common.c Mon Jun 12 19:49:17 2000 +0000
+++ b/sys/dev/ic/siop_common.c Mon Jun 12 20:13:41 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: siop_common.c,v 1.2 2000/05/15 15:16:59 bouyer Exp $ */
+/* $NetBSD: siop_common.c,v 1.3 2000/06/12 20:13:41 bouyer Exp $ */
/*
* Copyright (c) 2000 Manuel Bouyer.
@@ -478,3 +478,57 @@
}
}
}
+
+int
+siop_modechange(sc)
+ struct siop_softc *sc;
+{
+ int retry;
+ int sist0, sist1, stest2, stest4;
+ for (retry = 0; retry < 5; retry++) {
+ /*
+ * datasheet says to wait 100ms and re-read SIST1,
+ * to check that DIFFSENSE is srable.
+ * We may delay() 5 times for 100ms at interrupt time;
+ * hopefully this will not happen often.
+ */
+ delay(100000);
+ sist0 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SIST0);
+ sist1 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_SIST1);
+ if (sist1 & SIEN1_SBMC)
+ continue; /* we got an irq again */
+ stest4 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_STEST4) &
+ STEST4_MODE_MASK;
+ stest2 = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_STEST2);
+ switch(stest4) {
+ case STEST4_MODE_DIF:
+ printf("%s: switching to differential mode\n",
+ sc->sc_dev.dv_xname);
+ bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST2,
+ stest2 | STEST2_DIF);
+ break;
+ case STEST4_MODE_SE:
+ printf("%s: switching to single-ended mode\n",
+ sc->sc_dev.dv_xname);
+ bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST2,
+ stest2 & ~STEST2_DIF);
+ break;
+ case STEST4_MODE_LVD:
+ printf("%s: switching to LVD mode\n",
+ sc->sc_dev.dv_xname);
+ bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST2,
+ stest2 & ~STEST2_DIF);
+ break;
+ default:
+ printf("%s: invalid SCSI mode 0x%x\n",
+ sc->sc_dev.dv_xname, stest4);
+ return 0;
+ }
+ bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_STEST0,
+ stest4 >> 2);
+ return 1;
+ }
+ printf("%s: timeout waiting for DIFFSENSE to stabilise\n",
+ sc->sc_dev.dv_xname);
+ return 0;
+}
diff -r 7ee75c8240cd -r 5ec992748170 sys/dev/ic/siopreg.h
--- a/sys/dev/ic/siopreg.h Mon Jun 12 19:49:17 2000 +0000
+++ b/sys/dev/ic/siopreg.h Mon Jun 12 20:13:41 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: siopreg.h,v 1.5 2000/05/15 07:48:25 bouyer Exp $ */
+/* $NetBSD: siopreg.h,v 1.6 2000/06/12 20:13:41 bouyer Exp $ */
/*
* Copyright (c) 2000 Manuel Bouyer.
@@ -276,6 +276,7 @@
#define SIEN0_PAR 0x01
#define SIOP_SIEN1 0x41 /* SCSI interrupt enable 1, R/W */
+#define SIEN1_SBMC 0x10 /* 895 only */
#define SIEN1_STO 0x04
#define SIEN1_GEN 0x02
#define SIEN1_HTH 0x01
@@ -291,6 +292,7 @@
#define SIST0_PAR 0x01
#define SIOP_SIST1 0x43 /* SCSI interrut status 1, RO */
+#define SIST1_SBMC 0x10 /* 895 only */
#define SIST1_STO 0x04
#define SIST1_GEN 0x02
#define SIST1_HTH 0x01
diff -r 7ee75c8240cd -r 5ec992748170 sys/dev/ic/siopvar_common.h
--- a/sys/dev/ic/siopvar_common.h Mon Jun 12 19:49:17 2000 +0000
+++ b/sys/dev/ic/siopvar_common.h Mon Jun 12 20:13:41 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: siopvar_common.h,v 1.2 2000/05/23 17:08:07 bouyer Exp $ */
+/* $NetBSD: siopvar_common.h,v 1.3 2000/06/12 20:13:41 bouyer Exp $ */
/*
* Copyright (c) 2000 Manuel Bouyer.
@@ -126,6 +126,7 @@
#define TARF_WIDE 0x01 /* target is wide */
void siop_common_reset __P((struct siop_softc *));
+int siop_modechange __P((struct siop_softc *));
int siop_wdtr_neg __P((struct siop_cmd *siop_cmd));
int siop_sdtr_neg __P((struct siop_cmd *siop_cmd));
Home |
Main Index |
Thread Index |
Old Index