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: