diff options
author | briggs <briggs@cvs.openbsd.org> | 1996-09-02 15:50:37 +0000 |
---|---|---|
committer | briggs <briggs@cvs.openbsd.org> | 1996-09-02 15:50:37 +0000 |
commit | a64dba30d8dda4d3d00f553662090e44b77462db (patch) | |
tree | 4bf197412cd18422203045088d44f1a5fa1df7e4 /sys/arch | |
parent | e2ba9557a64f2bbc4aac29ba19a8d7abc497acfb (diff) |
Detect stuck interrupts in the scc (if DIAGNOSTIC) and log it.
Patches from Bill Studenmund <wrstuden@loki.stanford.edu>.
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/mac68k/dev/z8530sc.c | 31 | ||||
-rw-r--r-- | sys/arch/mac68k/dev/z8530sc.h | 22 | ||||
-rw-r--r-- | sys/arch/mac68k/dev/z8530tty.c | 8 | ||||
-rw-r--r-- | sys/arch/mac68k/dev/z8530tty.h | 3 |
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. |