Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/ic * Make doubly sure that the ep shutdownhooks are ...
details: https://anonhg.NetBSD.org/src/rev/38b9cb049c40
branches: trunk
changeset: 472058:38b9cb049c40
user: jonathan <jonathan%NetBSD.org@localhost>
date: Mon Apr 19 23:26:48 1999 +0000
description:
* Make doubly sure that the ep shutdownhooks are run at splnet() or above.
* Clear the `enabled' bit in the softc so late hardware interrupts
(e.g., just after the full reset) done as part of shutdown) are dropped.
* Eliminate loops that poll forever on S_COMMAND_IN_PROGRESS to complete.
Add inline function with bounded loopcount plus small delay, to avoid
bugs in EISA hardware which never sets S_COMMAND_IN_PROGRESS.
Use for both TX_RESET/RX_RESET/GLOBAL_RESET cmds, and polling for
discard-Rx completion
diffstat:
sys/dev/ic/elink3.c | 87 +++++++++++++++++++++++++++++++++-------------------
1 files changed, 55 insertions(+), 32 deletions(-)
diffs (176 lines):
diff -r fb8147952fe1 -r 38b9cb049c40 sys/dev/ic/elink3.c
--- a/sys/dev/ic/elink3.c Mon Apr 19 23:24:14 1999 +0000
+++ b/sys/dev/ic/elink3.c Mon Apr 19 23:26:48 1999 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: elink3.c,v 1.55 1999/04/13 20:23:52 jonathan Exp $ */
+/* $NetBSD: elink3.c,v 1.56 1999/04/19 23:26:48 jonathan Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -233,8 +233,10 @@
void ep_mii_sendbits __P((struct ep_softc *, u_int32_t, int));
static int epbusyeeprom __P((struct ep_softc *));
-static inline void ep_complete_cmd __P((struct ep_softc *sc,
+static inline void ep_reset_cmd __P((struct ep_softc *sc,
u_int cmd, u_int arg));
+static inline void ep_finish_reset __P((bus_space_tag_t, bus_space_handle_t));
+static inline void ep_discard_rxtop __P((bus_space_tag_t, bus_space_handle_t));
static __inline int ep_w1_reg __P((struct ep_softc *, int));
/*
@@ -265,14 +267,31 @@
}
/*
- * Issue a (reset) command, and be sure it has completed.
- * Used for commands that reset part or all of the board.
+ * Wait for any pending reset to complete.
* On newer hardware we could poll SC_COMMAND_IN_PROGRESS,
* but older hardware doesn't implement it and we must delay.
- * It's easiest to just delay always.
*/
static inline void
-ep_complete_cmd(sc, cmd, arg)
+ep_finish_reset(iot, ioh)
+ bus_space_tag_t iot;
+ bus_space_handle_t ioh;
+
+{
+ register int i;
+
+ for (i = 0; i < 1000; i++) {
+ if (bus_space_read_2(iot, ioh, ELINK_STATUS) & S_COMMAND_IN_PROGRESS)
+ return;
+ DELAY(100);
+ }
+}
+
+/*
+ * Issue a (reset) command, and be sure it has completed.
+ * Used for global reset, TX_RESET, RX_RESET.
+ */
+static inline void
+ep_reset_cmd(sc, cmd, arg)
struct ep_softc *sc;
u_int cmd, arg;
{
@@ -281,14 +300,18 @@
bus_space_write_2(iot, ioh, cmd, arg);
-#ifdef notyet
- /* if this adapter family has S_COMMAND_IN_PROGRESS, use it */
- while (bus_space_read_2(iot, ioh, ELINK_STATUS) & S_COMMAND_IN_PROGRESS)
- ;
- else
-#else
- DELAY(100000); /* need at least 1 ms, but be generous. */
-#endif
+ ep_finish_reset(iot, ioh);
+}
+
+
+static inline void
+ep_discard_rxtop(iot, ioh)
+ register bus_space_tag_t iot;
+ register bus_space_handle_t ioh;
+{
+
+ bus_space_write_2(iot, ioh, ELINK_COMMAND, RX_DISCARD_TOP_PACK);
+ ep_finish_reset(iot, ioh);
}
/*
@@ -471,8 +494,8 @@
/* Establish callback to reset card when we reboot. */
shutdownhook_establish(epshutdown, sc);
- ep_complete_cmd(sc, ELINK_COMMAND, RX_RESET);
- ep_complete_cmd(sc, ELINK_COMMAND, TX_RESET);
+ ep_reset_cmd(sc, ELINK_COMMAND, RX_RESET);
+ ep_reset_cmd(sc, ELINK_COMMAND, TX_RESET);
}
@@ -703,8 +726,9 @@
bus_space_handle_t ioh = sc->sc_ioh;
int i;
- while (bus_space_read_2(iot, ioh, ELINK_STATUS) & S_COMMAND_IN_PROGRESS)
- ;
+ /* Make sure any pending reset has completed before touching board. */
+ ep_finish_reset(iot, ioh);
+
if (sc->bustype != ELINK_BUS_PCI) {
GO_WINDOW(0);
@@ -728,8 +752,8 @@
for (i = 0; i < 6; i++)
bus_space_write_1(iot, ioh, ELINK_W2_RECVMASK_0 + i, 0);
- ep_complete_cmd(sc, ELINK_COMMAND, RX_RESET);
- ep_complete_cmd(sc, ELINK_COMMAND, TX_RESET);
+ ep_reset_cmd(sc, ELINK_COMMAND, RX_RESET);
+ ep_reset_cmd(sc, ELINK_COMMAND, TX_RESET);
GO_WINDOW(1); /* Window 1 is operating window */
for (i = 0; i < 31; i++)
@@ -1505,9 +1529,8 @@
return;
abort:
- bus_space_write_2(iot, ioh, ELINK_COMMAND, RX_DISCARD_TOP_PACK);
- while (bus_space_read_2(iot, ioh, ELINK_STATUS) & S_COMMAND_IN_PROGRESS)
- ;
+ ep_discard_rxtop(iot, ioh);
+
}
struct mbuf *
@@ -1649,9 +1672,7 @@
rv = top;
- bus_space_write_2(iot, ioh, ELINK_COMMAND, RX_DISCARD_TOP_PACK);
- while (bus_space_read_2(iot, ioh, ELINK_STATUS) & S_COMMAND_IN_PROGRESS)
- ;
+ ep_discard_rxtop(iot, ioh);
out:
if (sc->ep_flags & ELINK_FLAGS_USEFIFOBUFFER)
@@ -1821,14 +1842,13 @@
}
bus_space_write_2(iot, ioh, ELINK_COMMAND, RX_DISABLE);
- bus_space_write_2(iot, ioh, ELINK_COMMAND, RX_DISCARD_TOP_PACK);
- while (bus_space_read_2(iot, ioh, ELINK_STATUS) & S_COMMAND_IN_PROGRESS)
- ;
+ ep_discard_rxtop(iot, ioh);
+
bus_space_write_2(iot, ioh, ELINK_COMMAND, TX_DISABLE);
bus_space_write_2(iot, ioh, ELINK_COMMAND, STOP_TRANSCEIVER);
- ep_complete_cmd(sc, ELINK_COMMAND, RX_RESET);
- ep_complete_cmd(sc, ELINK_COMMAND, TX_RESET);
+ ep_reset_cmd(sc, ELINK_COMMAND, RX_RESET);
+ ep_reset_cmd(sc, ELINK_COMMAND, TX_RESET);
bus_space_write_2(iot, ioh, ELINK_COMMAND, C_INTR_LATCH);
bus_space_write_2(iot, ioh, ELINK_COMMAND, SET_RD_0_MASK);
@@ -1847,11 +1867,14 @@
void *arg;
{
register struct ep_softc *sc = arg;
+ int s = splnet();
if (sc->enabled) {
epstop(sc);
- ep_complete_cmd(sc, ELINK_COMMAND, GLOBAL_RESET);
+ ep_reset_cmd(sc, ELINK_COMMAND, GLOBAL_RESET);
+ sc->enabled = 0;
}
+ splx(s);
}
/*
Home |
Main Index |
Thread Index |
Old Index