Subject: Re: ep driver lossage
To: Jason Thorpe <thorpej@nas.nasa.gov>
From: Jonathan Stone <jonathan@DSG.Stanford.EDU>
List: tech-net
Date: 04/13/1999 13:35:32
hi Jason,

Below is the kludged-up patch i sent various people for testing, which
should be enough to identify the problem.

Polling for command_complete with a timeout is nicer; I'm not sure how
to do it without adding overhead to cardss that do implement it, tho.
Did you mean something simple like
    
	for (i = 0; i < 1000; i++) {
		if (bus_space_read_2(iot, ioh, ELINK_STATUS) & S_COMMAND_IN_PROGRESS)
			break;
		DELAY(100);
	}

or something fancier?




--- elink3.c	Tue Apr 13 13:03:06 1999
+++ elink3.c.jrs-shutdown-hack	Tue Apr 13 12:55:19 1999
@@ -224,6 +224,14 @@
 					u_int cmd, u_int arg));
 static __inline int ep_w1_reg __P((struct ep_softc *, int));
 
+/* 
+ * How long to delay when waiting for a reset to complete. (We cannot
+ * use S_COMMAND_IN_PROGRESS since some older boards do not implement
+ * that on RESET commands).  Documentation says we need at least 1 ms,
+ * but be generous for original 3c509 boards.
+ */
+#define ELINK_RESET_DELAY	100000
+
 /*
  * Some chips (3c515 [Corkscrew] and 3c574 [RoadRunner]) have
  * Window 1 registers offset!
@@ -274,7 +282,7 @@
 		;
 	else
 #else
-	DELAY(100000);	/* need at least 1 ms, but be generous. */
+	DELAY(ELINK_RESET_DELAY);	/* need at least 1 ms, be generous. */
 #endif
 }
 
@@ -690,8 +698,15 @@
 	bus_space_handle_t ioh = sc->sc_ioh;
 	int i;
 
+#if 0	/*
+	 * cannot use S_COMMAND_IN_PROGRESS, since we may be in a RESET,
+	 * and some boards do not implement it there. See ep_complete_cmd().
+	 */
 	while (bus_space_read_2(iot, ioh, ELINK_STATUS) & S_COMMAND_IN_PROGRESS)
 		;
+#else
+	DELAY(ELINK_RESET_DELAY);
+#endif
 
 	if (sc->bustype != ELINK_BUS_PCI) {
 		GO_WINDOW(0);
@@ -1836,8 +1851,11 @@
 	register struct ep_softc *sc = arg;
 
 	if (sc->enabled) {
+		int s = splnet();
+
 		epstop(sc);
 		ep_complete_cmd(sc, ELINK_COMMAND, GLOBAL_RESET);
+		splx(s);
 	}
 }