Detect stuck interrupts in the scc (if DIAGNOSTIC) and log it.
authorbriggs <briggs@openbsd.org>
Mon, 2 Sep 1996 15:50:34 +0000 (15:50 +0000)
committerbriggs <briggs@openbsd.org>
Mon, 2 Sep 1996 15:50:34 +0000 (15:50 +0000)
Patches from Bill Studenmund <wrstuden@loki.stanford.edu>.

sys/arch/mac68k/dev/z8530sc.c
sys/arch/mac68k/dev/z8530sc.h
sys/arch/mac68k/dev/z8530tty.c
sys/arch/mac68k/dev/z8530tty.h

index e686614..7c4ac4b 100644 (file)
@@ -1,5 +1,5 @@
-/*     $OpenBSD: z8530sc.c,v 1.2 1996/09/01 18:50:02 briggs Exp $      */
-/*     $NetBSD: z8530sc.c,v 1.2 1996/08/26 14:09:19 scottr Exp $       */
+/*     $OpenBSD: z8530sc.c,v 1.3 1996/09/02 15:50:34 briggs Exp $      */
+/*     $NetBSD: z8530sc.c,v 1.1 1996/05/18 18:54:28 briggs Exp $       */
 
 /*
  * Copyright (c) 1994 Gordon W. Ross
@@ -297,6 +297,10 @@ zsc_intr_hard(arg)
        register struct zs_chanstate *cs_b;
        register int rval;
        register u_char rr3, rr3a;
+#if DIAGNOSTIC
+       register int loopcount;
+       loopcount = ZS_INTERRUPT_CNT;
+#endif
 
        cs_a = &zsc->zsc_cs[0];
        cs_b = &zsc->zsc_cs[1];
@@ -304,27 +308,42 @@ zsc_intr_hard(arg)
        rr3a = 0;
 
        /* Note: only channel A has an RR3 */
-       while ((rr3 = zs_read_reg(cs_a, 3))) {
+       rr3 = zs_read_reg(cs_a, 3);
+
+       while ((rr3 = zs_read_reg(cs_a, ZSRR_IPEND))
+#if DIAGNOSTIC
+                && --loopcount
+#endif
+               ) {
+
                /* Handle receive interrupts first. */
                if (rr3 & ZSRR3_IP_A_RX)
                        (*cs_a->cs_ops->zsop_rxint)(cs_a);
                if (rr3 & ZSRR3_IP_B_RX)
                        (*cs_b->cs_ops->zsop_rxint)(cs_b);
-
+       
                /* Handle status interrupts (i.e. flow control). */
                if (rr3 & ZSRR3_IP_A_STAT)
                        (*cs_a->cs_ops->zsop_stint)(cs_a);
                if (rr3 & ZSRR3_IP_B_STAT)
                        (*cs_b->cs_ops->zsop_stint)(cs_b);
-
+       
                /* Handle transmit done interrupts. */
                if (rr3 & ZSRR3_IP_A_TX)
                        (*cs_a->cs_ops->zsop_txint)(cs_a);
                if (rr3 & ZSRR3_IP_B_TX)
                        (*cs_b->cs_ops->zsop_txint)(cs_b);
-
+       
                rr3a |= rr3;
        }
+#if DIAGNOSTIC
+       if (loopcount == 0) {
+               if (rr3 & (ZSRR3_IP_A_RX | ZSRR3_IP_A_TX | ZSRR3_IP_A_STAT))
+                       cs_a->cs_flags |= ZS_FLAGS_INTERRUPT_OVERRUN;
+               if (rr3 & (ZSRR3_IP_B_RX | ZSRR3_IP_B_TX | ZSRR3_IP_B_STAT))
+                       cs_b->cs_flags |= ZS_FLAGS_INTERRUPT_OVERRUN;
+       }
+#endif
 
        /* Clear interrupt. */
        if (rr3a & (ZSRR3_IP_A_RX | ZSRR3_IP_A_TX | ZSRR3_IP_A_STAT)) {
index ba19bff..4aff44f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: z8530sc.h,v 1.1 1996/05/26 19:02:11 briggs Exp $      */
+/*     $OpenBSD: z8530sc.h,v 1.2 1996/09/02 15:50:35 briggs Exp $      */
 /*     $NetBSD: z8530sc.h,v 1.1 1996/05/18 18:54:30 briggs Exp $       */
 
 /*
@@ -87,10 +87,13 @@ struct zs_chanstate {
        void *cs_private;       /* sub-driver data pointer */
        struct zsops *cs_ops;
 
-       int     cs_defspeed;            /* default baud rate (from PROM) */
-       int cs_pclk_div16;              /* PCLK / 16 used only by kbd & ms kids */
        int     cs_clock_count;         /* how many signal sources available */
        struct zsclksrc cs_clocks[4];   /* info on available signal sources */
+       int     cs_defspeed;            /* default baud rate (from PROM) */
+       int cs_pclk_div16;              /* PCLK / 16 used by zs children w/o multiple
+                                        * baud support - some ports have only
+                                        * one clock source, and some children (kbd & ms)
+                                        * are fixed baud rate */
 
        /*
         * We must keep a copy of the write registers as they are
@@ -118,8 +121,19 @@ struct zs_chanstate {
 
        char    cs_softreq;             /* need soft interrupt call */
        char    cs_chip;                /* type of chip */
-       char    cs__spare; 
+       char    cs_flags;               /* misc. flags */
 };
+#define ZS_INTERRUPT_CNT               10
+#define ZS_FLAGS_INTERRUPT_OVERRUN     0x01
+#define ZS_FLAGS_DEBUG1                        0x10
+       /* The interrupt service routine will now look to see if more interrupts
+        * come in while servicing an interrupt. If so, it keeps servicing
+        * them either to exhaustion or until it's tried ZS_INTERRUPT_CNT times.
+        * If it tries too many times, it flags a ZS_FLAGS_INTERRUPT_OVERRUN.
+        * It shouldn't, but w/o a counter of sorts, we could get hung in an
+        * infinite loop because of sick hardware, or because there's a data
+        * clock fed on one of the inputs. The DEBUG flag is for testing and has
+        * no permanant definition. */
 #define        ZS_ENHANCED_REG 8
        /* cs_Xreg which is used to hold WR7' data; reg 8 is an alias to the
         * data port, so we won't miss its loss. */
index 1a2d787..2ebf29f 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: z8530tty.c,v 1.2 1996/06/08 16:21:13 briggs Exp $     */
+/*     $OpenBSD: z8530tty.c,v 1.3 1996/09/02 15:50:35 briggs Exp $     */
 /*     $NetBSD: z8530tty.c,v 1.3 1996/06/01 00:13:41 scottr Exp $      */
 
 /*
@@ -1321,6 +1321,12 @@ zstty_softint(cs)
                zst->zst_rx_overrun = 0;
                zsoverrun(zst, &zst->zst_rotime, "ring");
        }
+       if (cs->cs_flags & ZS_FLAGS_INTERRUPT_OVERRUN) {
+               (void) splzs();
+               cs->cs_flags &= ~ZS_FLAGS_INTERRUPT_OVERRUN;
+               (void) spltty();
+               zsoverrun(zst, &zst->zst_intotime, "interrupt");
+       }
 
        /*
         * Copy data from the receive ring into the tty layer.
index b292b47..f79ce22 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: z8530tty.h,v 1.1 1996/05/26 19:02:13 briggs Exp $     */
+/*     $OpenBSD: z8530tty.h,v 1.2 1996/09/02 15:50:36 briggs Exp $     */
 /*     $NetBSD: z8530tty.h,v 1.1 1996/05/18 18:54:35 briggs Exp $      */
 
 /*
@@ -92,6 +92,7 @@ struct zstty_softc {
         */
        long    zst_rotime;             /* time of last ring overrun */
        long    zst_fotime;             /* time of last fifo overrun */
+       long    zst_intotime;           /* time of last interrupt overrun */
 
        /*
         * The receive ring buffer.