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