summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorbriggs <briggs@cvs.openbsd.org>1996-09-02 15:50:37 +0000
committerbriggs <briggs@cvs.openbsd.org>1996-09-02 15:50:37 +0000
commita64dba30d8dda4d3d00f553662090e44b77462db (patch)
tree4bf197412cd18422203045088d44f1a5fa1df7e4 /sys
parente2ba9557a64f2bbc4aac29ba19a8d7abc497acfb (diff)
Detect stuck interrupts in the scc (if DIAGNOSTIC) and log it.
Patches from Bill Studenmund <wrstuden@loki.stanford.edu>.
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/mac68k/dev/z8530sc.c31
-rw-r--r--sys/arch/mac68k/dev/z8530sc.h22
-rw-r--r--sys/arch/mac68k/dev/z8530tty.c8
-rw-r--r--sys/arch/mac68k/dev/z8530tty.h3
4 files changed, 52 insertions, 12 deletions
diff --git a/sys/arch/mac68k/dev/z8530sc.c b/sys/arch/mac68k/dev/z8530sc.c
index e686614dd96..7c4ac4b4dbb 100644
--- a/sys/arch/mac68k/dev/z8530sc.c
+++ b/sys/arch/mac68k/dev/z8530sc.c
@@ -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)) {
diff --git a/sys/arch/mac68k/dev/z8530sc.h b/sys/arch/mac68k/dev/z8530sc.h
index ba19bff490d..4aff44f723b 100644
--- a/sys/arch/mac68k/dev/z8530sc.h
+++ b/sys/arch/mac68k/dev/z8530sc.h
@@ -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. */
diff --git a/sys/arch/mac68k/dev/z8530tty.c b/sys/arch/mac68k/dev/z8530tty.c
index 1a2d7876152..2ebf29f0465 100644
--- a/sys/arch/mac68k/dev/z8530tty.c
+++ b/sys/arch/mac68k/dev/z8530tty.c
@@ -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.
diff --git a/sys/arch/mac68k/dev/z8530tty.h b/sys/arch/mac68k/dev/z8530tty.h
index b292b474edb..f79ce22466f 100644
--- a/sys/arch/mac68k/dev/z8530tty.h
+++ b/sys/arch/mac68k/dev/z8530tty.h
@@ -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.