summaryrefslogtreecommitdiff
path: root/sys/arch/mac68k
diff options
context:
space:
mode:
authorbriggs <briggs@cvs.openbsd.org>1996-09-01 18:50:03 +0000
committerbriggs <briggs@cvs.openbsd.org>1996-09-01 18:50:03 +0000
commitf36ffd0fac3dc34d2ac6a3f0e1e48a7aa03e890d (patch)
treebc1eacc00b444e5b2504e282d442a5780f78fb50 /sys/arch/mac68k
parentf97e206a14e1de72ae4f06bf3d728f40f18ed5f6 (diff)
From scottr@netbsd.org:
After servicing an interrupt, check to see that there's not another one pending before we clear the interrupt flag. This avoids a condition where the line appears to go catatonic (which is particularly easily triggered by pppd). From Bill Studenmund <wrstuden@loki.stanford.edu>. XXX - we should probably log this if it gets excessive.
Diffstat (limited to 'sys/arch/mac68k')
-rw-r--r--sys/arch/mac68k/dev/z8530sc.c51
1 files changed, 27 insertions, 24 deletions
diff --git a/sys/arch/mac68k/dev/z8530sc.c b/sys/arch/mac68k/dev/z8530sc.c
index 2447c5233e0..e686614dd96 100644
--- a/sys/arch/mac68k/dev/z8530sc.c
+++ b/sys/arch/mac68k/dev/z8530sc.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: z8530sc.c,v 1.1 1996/05/26 19:02:10 briggs Exp $ */
-/* $NetBSD: z8530sc.c,v 1.1 1996/05/18 18:54:28 briggs Exp $ */
+/* $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 $ */
/*
* Copyright (c) 1994 Gordon W. Ross
@@ -296,39 +296,42 @@ zsc_intr_hard(arg)
register struct zs_chanstate *cs_a;
register struct zs_chanstate *cs_b;
register int rval;
- register u_char rr3;
+ register u_char rr3, rr3a;
cs_a = &zsc->zsc_cs[0];
cs_b = &zsc->zsc_cs[1];
rval = 0;
+ rr3a = 0;
/* Note: only channel A has an RR3 */
- rr3 = zs_read_reg(cs_a, 3);
-
- /* 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);
+ while ((rr3 = zs_read_reg(cs_a, 3))) {
+ /* 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;
+ }
/* Clear interrupt. */
- if (rr3 & (ZSRR3_IP_A_RX | ZSRR3_IP_A_TX | ZSRR3_IP_A_STAT)) {
+ if (rr3a & (ZSRR3_IP_A_RX | ZSRR3_IP_A_TX | ZSRR3_IP_A_STAT)) {
zs_write_csr(cs_a, ZSWR0_CLR_INTR);
rval |= 1;
}
- if (rr3 & (ZSRR3_IP_B_RX | ZSRR3_IP_B_TX | ZSRR3_IP_B_STAT)) {
+ if (rr3a & (ZSRR3_IP_B_RX | ZSRR3_IP_B_TX | ZSRR3_IP_B_STAT)) {
zs_write_csr(cs_b, ZSWR0_CLR_INTR);
rval |= 2;
}