Subject: kern/9838: Portability fixes to i82586 driver [PATCH]
To: None <gnats-bugs@gnats.netbsd.org>
From: Ben Harris <bjh21@cam.ac.uk>
List: netbsd-bugs
Date: 04/08/2000 04:39:10
>Number:         9838
>Category:       kern
>Synopsis:       Portability fixes for i82586 driver [PATCH]
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sat Apr 08 02:45:00 PDT 2000
>Closed-Date:
>Last-Modified:
>Originator:     Ben Harris
>Release:        2000-04 sometime (1.4Xish)
>Organization:
	University of Cambridge
>Environment:
Heavily-hacked Acorn BBC A3000 with an Acorn AKA25 Ethernet interface.

>Description:
The i82586 driver in sys/dev/ic/i82586.c makes a few awkward
assumptions.  Notably, it assumes that the memory that's shared between it
and the board can be accessed directly using bus_space operations, and
that it's possible to use 8-bit bus_space operations on it.  On the Acorn
AKA25 (Ether1) card, neither of these is true.  The board's memory is
accessed in 4k pages from the host, and 8-bit accesses will always see the
bottom eight bits of a sixteen-bit word.  This could be fixed with a
custom bus_space, but tidying up the driver looked easier since only a
few functions made these assumptions.

I also found the need for an interrupt hook to be called whenever an
interrupt is acknowledged, as the AKA25 seems to have a latch on the
interrupt line that needs clearing.

There's a small bug in a debugging printf somewhere that forgets to
byte-swap the ethertype before displaying it.

I82586_DEBUG is #defined to 0 in i82586var.h, which makes using it as a
kernel option tricky.

>How-To-Repeat:
See <http://cvs.tartarus.org/netbsd-arm26/sys/arch/arm26/podulebus/if_et.c>
for a front-end driver that needs these changes.

>Fix:
The following patch changes the driver so that it only ever accesses the
shared memory through the access fuction provided by the front-end.  This
doesn't change any speed-critical code, only a few setup functions.  I
haven't touched the bus_space_barriers, as they're a no-op on arm26, so I
couldn't test any changes.

The patch also includes fixes for the other three problems mentioned.  I
added another possible argument to the interrupt hook for acknowledging
interrupts, a call to ntohs at the right moment, and a condition on the
setting of I82586_DEBUG.

This code has been tested on an AKA25, and allows me to mount a root
filesystem over NFS.  Much more testing will need some useful user
processes, but flood pinging the machine doesn't make the driver explode.

The changes haven't been tested on any other i82586 board because I
haven't got any.  They should be checked against at least one before being
committed.

Note that this patch has been modified by hand to remove some lingering
irrelevant changes (using %b in some printfs).  I don't think I messed up
the line numbers.

Index: sys/dev/ic/i82586.c
===================================================================
RCS file: /pub/NetBSD-CVS/syssrc/sys/dev/ic/i82586.c,v
retrieving revision 1.26
diff -u -r1.26 i82586.c
--- i82586.c	2000/03/30 12:45:31	1.26
+++ i82586.c	2000/04/08 00:58:02
@@ -561,6 +561,8 @@
 	bus_space_barrier(sc->bt, sc->bh, 0, 0, BUS_SPACE_BARRIER_READ);
 	status = (sc->ie_bus_read16)(sc, IE_SCB_STATUS(sc->scb));
 	i82586_start_cmd(sc, status & mask, 0, 0, 0);
+	if (sc->intrhook)
+		sc->intrhook(sc, INTR_ACK);
 }
 
 /*
@@ -1235,7 +1237,7 @@
 		printf("%s: frame from ether %s type 0x%x len %d\n",
 			sc->sc_dev.dv_xname,
 			ether_sprintf(eh->ether_shost),
-			(u_int)eh->ether_type,
+			(u_int)ntohs(eh->ether_type),
 			pktlen);
 	}
 #endif
@@ -1446,12 +1448,12 @@
 
 	/* Put in 16-bit mode */
 	off = IE_SCP_BUS_USE(sc->scp);
-	bus_space_write_1(sc->bt, sc->bh, off, 0);
+	(sc->ie_bus_write16)(sc, off, 0);
 	bus_space_barrier(sc->bt, sc->bh, off, 1, BUS_SPACE_BARRIER_WRITE);
 
 	/* Set the ISCP `busy' bit */
 	off = IE_ISCP_BUSY(sc->iscp);
-	bus_space_write_1(sc->bt, sc->bh, off, 1);
+	(sc->ie_bus_write16)(sc, off, 1);
 	bus_space_barrier(sc->bt, sc->bh, off, 1, BUS_SPACE_BARRIER_WRITE);
 
 	if (sc->hwreset)
@@ -1464,7 +1466,7 @@
 	/* Read back the ISCP `busy' bit; it should be clear by now */
 	off = IE_ISCP_BUSY(sc->iscp);
 	bus_space_barrier(sc->bt, sc->bh, off, 1, BUS_SPACE_BARRIER_READ);
-	result = bus_space_read_1(sc->bt, sc->bh, off) == 0;
+	result = (sc->ie_bus_read16)(sc, off) == 0;
 
 	/* Acknowledge any interrupts we may have caused. */
 	ie_ack(sc, IE_ST_WHENCE);
@@ -1742,34 +1744,35 @@
 	int promiscuous, manchester;
 {
 	int cmdresult, status;
+	u_int8_t buf[IE_CMD_CFG_SZ]; /* XXX malloc? */
 
+	*IE_CMD_CFG_CNT(buf)       = 0x0c;
+	*IE_CMD_CFG_FIFO(buf)      = 8;
+        *IE_CMD_CFG_SAVEBAD(buf)   = 0x40;
+	*IE_CMD_CFG_ADDRLEN(buf)   = 0x2e;
+	*IE_CMD_CFG_PRIORITY(buf)  = 0;
+	*IE_CMD_CFG_IFS(buf)       = 0x60;
+	*IE_CMD_CFG_SLOT_LOW(buf)  = 0;
+	*IE_CMD_CFG_SLOT_HIGH(buf) = 0xf2;
+	*IE_CMD_CFG_PROMISC(buf)   = !!promiscuous | manchester << 2;
+	*IE_CMD_CFG_CRSCDT(buf)    = 0;
+	*IE_CMD_CFG_MINLEN(buf)    = 64;
+	*IE_CMD_CFG_JUNK(buf)      = 0xff;
+	sc->memcopyout(sc, buf, cmd, IE_CMD_CFG_SZ);
 	setup_simple_command(sc, IE_CMD_CONFIG, cmd);
-	bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_CNT(cmd), 0x0c);
-	bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_FIFO(cmd), 8);
-	bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_SAVEBAD(cmd), 0x40);
-	bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_ADDRLEN(cmd), 0x2e);
-	bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_PRIORITY(cmd), 0);
-	bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_IFS(cmd), 0x60);
-	bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_SLOT_LOW(cmd), 0);
-	bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_SLOT_HIGH(cmd), 0xf2);
-	bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_PROMISC(cmd),
-					  !!promiscuous | manchester << 2);
-	bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_CRSCDT(cmd), 0);
-	bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_MINLEN(cmd), 64);
-	bus_space_write_1(sc->bt, sc->bh, IE_CMD_CFG_JUNK(cmd), 0xff);
 	bus_space_barrier(sc->bt, sc->bh, cmd, IE_CMD_CFG_SZ,
 			  BUS_SPACE_BARRIER_WRITE);
 
 	cmdresult = i82586_start_cmd(sc, IE_CUC_START, cmd, IE_STAT_COMPL, 0);
 	status = sc->ie_bus_read16(sc, IE_CMD_COMMON_STATUS(cmd));
 	if (cmdresult != 0) {
 		printf("%s: configure command timed out; status %x\n",
 			sc->sc_dev.dv_xname, status);
 		return (0);
 	}
 	if ((status & IE_STAT_OK) == 0) {
 		printf("%s: configure command failed; status %x\n",
 			sc->sc_dev.dv_xname, status);
 		return (0);
 	}
 
Index: sys/dev/ic/i82586var.h
===================================================================
RCS file: /pub/NetBSD-CVS/syssrc/sys/dev/ic/i82586var.h,v
retrieving revision 1.12
diff -u -r1.12 i82586var.h
--- i82586var.h	1999/08/23 12:12:43	1.12
+++ i82586var.h	2000/04/07 21:36:38
@@ -97,7 +97,9 @@
  * This sun version based on i386 version 1.30.
  */
 
+#ifndef I82586_DEBUG
 #define I82586_DEBUG 0
+#endif
 
 /* Debug elements */
 #define	IED_RINT	0x01
@@ -121,6 +123,7 @@
 #define INTR_ENTER	0		/* intr hook called on ISR entry */
 #define INTR_EXIT	1		/* intr hook called on ISR exit */
 #define INTR_LOOP	2		/* intr hook called on ISR loop */
+#define INTR_ACK	3		/* intr hook called on ie_ack */
 
 #define CHIP_PROBE	0		/* reset called from chip probe */
 #define CARD_RESET	1		/* reset called from card reset */

-- 
Ben Harris
Unix Support, University of Cambridge Computing Service.

>Release-Note:
>Audit-Trail:
>Unformatted: