Subject: kern/9602: le(4) support big-endian machine.
To: None <gnats-bugs@gnats.netbsd.org>
From: NONAKA Kimihiro <aw9k-nnk@asahi-net.or.jp>
List: netbsd-bugs
Date: 03/11/2000 13:24:44
>Number:         9602
>Category:       kern
>Synopsis:       le(4) support big-endian machine.
>Confidential:   no
>Severity:       non-critical
>Priority:       high
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sat Mar 11 13:24:00 2000
>Last-Modified:
>Originator:     NONAKA Kimihiro
>Organization:
>Release:        NetBSD-current 20000215
>Environment:
System: NetBSD natsumi 1.4T NetBSD 1.4T (NATSUMI) #606: Sun Mar 12 04:20:09 JST 2000 nonaka@koharu:/usr/src/sys/arch/prep/compile/NATSUMI prep

>Description:
	Currently le(4) don't support big-endian machine.

>How-To-Repeat:
	Use le(4) with big-endian machine.

>Fix:
	Apply the following patch.

--- sys/dev/ic/am79900.c.orig	Sun Mar 12 04:17:28 2000
+++ sys/dev/ic/am79900.c	Sun Mar 12 04:16:52 2000
@@ -68,6 +68,8 @@
 #include <net/bpfdesc.h>
 #endif
 
+#include <machine/endian.h>
+
 #include <dev/ic/lancereg.h>
 #include <dev/ic/lancevar.h>
 #include <dev/ic/am79900reg.h>
@@ -98,6 +100,18 @@
 
 #define	ifp	(&sc->sc_ethercom.ec_if)
 
+#if BYTE_ORDER == BIG_ENDIAN
+#define	desc_htole(m)							\
+do {									\
+	m.__CONCAT(m,1) = htole32(m.__CONCAT(m,1));			\
+	m.__CONCAT(m,2) = htole32(m.__CONCAT(m,2));			\
+} while (0)
+#define	desc_letoh(m)	desc_htole(m)
+#else
+#define	desc_htole(m)
+#define	desc_letoh(m)
+#endif
+
 void
 am79900_config(sc)
 	struct am79900_softc *sc;
@@ -150,6 +164,7 @@
 
 	init.init_mode |= ((ffs(sc->sc_ntbuf) - 1) << 28)
 	  | ((ffs(sc->sc_nrbuf) - 1) << 20);
+	init.init_mode = htole32(init.init_mode);
 
 	/*
 	 * Update our private copy of the Ethernet address.
@@ -158,19 +173,28 @@
 	bcopy(LLADDR(ifp->if_sadl), sc->sc_enaddr, 6);
 	myaddr = sc->sc_enaddr;
 
-	init.init_padr[0] = myaddr[0] | (myaddr[1] << 8)
-	  | (myaddr[2] << 16) | (myaddr[3] << 24);
-	init.init_padr[1] = myaddr[4] | (myaddr[5] << 8);
+	init.init_padr[0] = htole32(myaddr[0] | (myaddr[1] << 8)
+	  | (myaddr[2] << 16) | (myaddr[3] << 24));
+	init.init_padr[1] = htole32(myaddr[4] | (myaddr[5] << 8));
+
 	lance_setladrf(&sc->sc_ethercom, init.init_ladrf);
+	init.init_ladrf[0] = htole16(init.init_ladrf[0]);
+	init.init_ladrf[1] = htole16(init.init_ladrf[1]);
+	init.init_ladrf[2] = htole16(init.init_ladrf[2]);
+	init.init_ladrf[3] = htole16(init.init_ladrf[3]);
+	*(u_int32_t *)(&init.init_ladrf[0]) =
+	    htole32(*(u_int32_t *)(&init.init_ladrf[0]));
+	*(u_int32_t *)(&init.init_ladrf[2]) =
+	    htole32(*(u_int32_t *)(&init.init_ladrf[2]));
 
 	sc->sc_last_rd = 0;
 	sc->sc_first_td = sc->sc_last_td = sc->sc_no_td = 0;
 
 	a = sc->sc_addr + LE_RMDADDR(sc, 0);
-	init.init_rdra = a;
+	init.init_rdra = htole32(a);
 
 	a = sc->sc_addr + LE_TMDADDR(sc, 0);
-	init.init_tdra = a;
+	init.init_tdra = htole32(a);
 
 	(*sc->sc_copytodesc)(sc, &init, LE_INITADDR(sc), sizeof(init));
 
@@ -179,10 +203,11 @@
 	 */
 	for (bix = 0; bix < sc->sc_nrbuf; bix++) {
 		a = sc->sc_addr + LE_RBUFADDR(sc, bix);
-		rmd.rmd0 = a;
+		rmd.rmd0 = htole32(a);
 		rmd.rmd1 = LE_R1_OWN | LE_R1_ONES | (-LEBLEN & 0xfff);
 		rmd.rmd2 = 0;
 		rmd.rmd3 = 0;
+		desc_htole(rmd);
 		(*sc->sc_copytodesc)(sc, &rmd, LE_RMDADDR(sc, bix),
 		    sizeof(rmd));
 	}
@@ -192,10 +217,11 @@
 	 */
 	for (bix = 0; bix < sc->sc_ntbuf; bix++) {
 		a = sc->sc_addr + LE_TBUFADDR(sc, bix);
-		tmd.tmd0 = a;
+		tmd.tmd0 = htole32(a);
 		tmd.tmd1 = LE_T1_ONES;
 		tmd.tmd2 = 0;
 		tmd.tmd3 = 0;
+		desc_htole(tmd);
 		(*sc->sc_copytodesc)(sc, &tmd, LE_TMDADDR(sc, bix),
 		    sizeof(tmd));
 	}
@@ -215,6 +241,7 @@
 	for (;;) {
 		rp = LE_RMDADDR(sc, bix);
 		(*sc->sc_copyfromdesc)(sc, &rmd, rp, sizeof(rmd));
+		desc_letoh(rmd);
 
 		if (rmd.rmd1 & LE_R1_OWN)
 			break;
@@ -257,6 +284,7 @@
 		rmd.rmd1 = LE_R1_OWN | LE_R1_ONES | (-LEBLEN & 0xfff);
 		rmd.rmd2 = 0;
 		rmd.rmd3 = 0;
+		desc_htole(rmd);
 		(*sc->sc_copytodesc)(sc, &rmd, rp, sizeof(rmd));
 
 #ifdef LEDEBUG
@@ -264,7 +292,7 @@
 			printf("sc->sc_last_rd = %x, rmd: "
 			       "adr %08x, flags/blen %08x\n",
 				sc->sc_last_rd,
-				rmd.rmd0, rmd.rmd1);
+				le32toh(rmd.rmd0), rmd.rmd1);
 #endif
 
 		if (++bix == sc->sc_nrbuf)
@@ -289,12 +317,13 @@
 
 		(*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, bix),
 		    sizeof(tmd));
+		desc_letoh(tmd);
 
 #ifdef LEDEBUG
 		if (sc->sc_debug)
 			printf("trans tmd: "
 			    "adr %08x, flags/blen %08x\n",
-			    tmd.tmd0, tmd.tmd1);
+			    le32toh(tmd.tmd0), tmd.tmd1);
 #endif
 
 		if (tmd.tmd1 & LE_T1_OWN)
@@ -460,6 +489,7 @@
 	for (;;) {
 		rp = LE_TMDADDR(sc, bix);
 		(*sc->sc_copyfromdesc)(sc, &tmd, rp, sizeof(tmd));
+		desc_letoh(tmd);
 
 		if (tmd.tmd1 & LE_T1_OWN) {
 			ifp->if_flags |= IFF_OACTIVE;
@@ -498,7 +528,7 @@
 		tmd.tmd1 = LE_T1_OWN | LE_T1_STP | LE_T1_ENP | LE_T1_ONES | (-len & 0xfff);
 		tmd.tmd2 = 0;
 		tmd.tmd3 = 0;
-
+		desc_htole(tmd);
 		(*sc->sc_copytodesc)(sc, &tmd, rp, sizeof(tmd));
 
 #ifdef LEDEBUG
@@ -515,7 +545,6 @@
 			ifp->if_flags |= IFF_OACTIVE;
 			break;
 		}
-
 	}
 
 	sc->sc_last_td = bix;
@@ -532,13 +561,16 @@
 	struct ether_header eh;
 
 	(*sc->sc_copyfromdesc)(sc, &rmd, LE_RMDADDR(sc, no), sizeof(rmd));
+	desc_letoh(rmd);
+
 	len = (rmd.rmd2  & 0xfff) - 4;
+	printf("%s: am79900_recv_print\n", sc->sc_dev.dv_xname);
 	printf("%s: receive buffer %d, len = %d\n", sc->sc_dev.dv_xname, no,
 	    len);
 	printf("%s: status %04x\n", sc->sc_dev.dv_xname,
 	    (*sc->sc_rdcsr)(sc, LE_CSR0));
 	printf("%s: adr %08x, flags/blen %08x\n",
-	    sc->sc_dev.dv_xname, rmd.rmd0, rmd.rmd1);
+	    sc->sc_dev.dv_xname, le32toh(rmd.rmd0), rmd.rmd1);
 	if (len >= sizeof(eh)) {
 		(*sc->sc_copyfrombuf)(sc, &eh, LE_RBUFADDR(sc, no), sizeof(eh));
 		printf("%s: dst %s", sc->sc_dev.dv_xname,
@@ -558,13 +590,16 @@
 	struct ether_header eh;
 
 	(*sc->sc_copyfromdesc)(sc, &tmd, LE_TMDADDR(sc, no), sizeof(tmd));
-	len = -(tmd.tmd1 & 0xfff);
+	desc_letoh(tmd);
+
+	len = -(tmd.tmd1 & 0xffff);
+	printf("%s: am79900_xmit_print\n", sc->sc_dev.dv_xname);
 	printf("%s: transmit buffer %d, len = %d\n", sc->sc_dev.dv_xname, no,
 	    len);
 	printf("%s: status %04x\n", sc->sc_dev.dv_xname,
 	    (*sc->sc_rdcsr)(sc, LE_CSR0));
 	printf("%s: adr %08x, flags/blen %08x\n",
-	    sc->sc_dev.dv_xname, tmd.tmd0, tmd.tmd1);
+	    sc->sc_dev.dv_xname, le32toh(tmd.tmd0), tmd.tmd1);
 	if (len >= sizeof(eh)) {
 		(*sc->sc_copyfrombuf)(sc, &eh, LE_TBUFADDR(sc, no), sizeof(eh));
 		printf("%s: dst %s", sc->sc_dev.dv_xname,
>Audit-Trail:
>Unformatted: