Subject: Re: bge on big endian anyone?
To: Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
From: Garrett D'Amore <garrett_damore@tadpole.com>
List: current-users
Date: 11/22/2005 13:23:22
That didn't fix it -- probably there is another endian error somewhere. 
But the knowledge that bge is known to be busted on big-endian machines
is quite helpful.

It might be worth looking at OpenBSD to see if they have fixes for this,
as well.  I'll check into it later.

    -- Garrett

Izumi Tsutsui wrote:

>In article <4383727A.4020801@tadpole.com>
>garrett_damore@tadpole.com wrote:
>
>  
>
>>I'm trying to get bge working on a big-endian host (MIPS core).  I am
>>not having luck.  Changing the core to little endian makes it work
>>fine.  Is anyone else out there using it with -current on a big endian
>>(or even better yet, big-endian MIPS) host?
>>    
>>
>
>It seems bge(4) lacks byteswap for DMA ops on big endian machines
>even though there are several #ifdef BYTE_ORDER == BIG_ENDIAN statements.
>(it's likely on drivers derived from FreeBSD ;-p)
>
>How about the attached patch? (untested at all)
>---
>Izumi Tsutsui
>
>Index: if_bge.c
>===================================================================
>RCS file: /cvsroot/src/sys/dev/pci/if_bge.c,v
>retrieving revision 1.93
>diff -u -r1.93 if_bge.c
>--- if_bge.c	6 Sep 2005 15:42:21 -0000	1.93
>+++ if_bge.c	22 Nov 2005 20:01:14 -0000
>@@ -909,8 +909,8 @@
> 	bge_set_hostaddr(&r->bge_addr,
> 	    dmamap->dm_segs[0].ds_addr);
> 	r->bge_flags = BGE_RXBDFLAG_END;
>-	r->bge_len = m_new->m_len;
>-	r->bge_idx = i;
>+	r->bge_len = htole16(m_new->m_len);
>+	r->bge_idx = htole16(i);
> 
> 	bus_dmamap_sync(sc->bge_dmatag, sc->bge_ring_map,
> 	    offsetof(struct bge_ring_data, bge_rx_std_ring) +
>@@ -969,9 +969,9 @@
> 	r = &sc->bge_rdata->bge_rx_jumbo_ring[i];
> 	sc->bge_cdata.bge_rx_jumbo_chain[i] = m_new;
> 	bge_set_hostaddr(&r->bge_addr, BGE_JUMBO_DMA_ADDR(sc, m_new));
>-	r->bge_flags = BGE_RXBDFLAG_END|BGE_RXBDFLAG_JUMBO_RING;
>-	r->bge_len = m_new->m_len;
>-	r->bge_idx = i;
>+	r->bge_flags = htole16(BGE_RXBDFLAG_END|BGE_RXBDFLAG_JUMBO_RING);
>+	r->bge_len = htole16(m_new->m_len);
>+	r->bge_idx = htole16(i);
> 
> 	bus_dmamap_sync(sc->bge_dmatag, sc->bge_ring_map,
> 	    offsetof(struct bge_ring_data, bge_rx_jumbo_ring) +
>@@ -2793,15 +2793,15 @@
> 		cur_rx = &sc->bge_rdata->
> 			bge_rx_return_ring[sc->bge_rx_saved_considx];
> 
>-		rxidx = cur_rx->bge_idx;
>+		rxidx = le16toh(cur_rx->bge_idx);
> 		BGE_INC(sc->bge_rx_saved_considx, sc->bge_return_ring_cnt);
> 
>-		if (cur_rx->bge_flags & BGE_RXBDFLAG_JUMBO_RING) {
>+		if (le16toh(cur_rx->bge_flags) & BGE_RXBDFLAG_JUMBO_RING) {
> 			BGE_INC(sc->bge_jumbo, BGE_JUMBO_RX_RING_CNT);
> 			m = sc->bge_cdata.bge_rx_jumbo_chain[rxidx];
> 			sc->bge_cdata.bge_rx_jumbo_chain[rxidx] = NULL;
> 			jumbocnt++;
>-			if (cur_rx->bge_flags & BGE_RXBDFLAG_ERROR) {
>+			if (le16toh(cur_rx->bge_flags) & BGE_RXBDFLAG_ERROR) {
> 				ifp->if_ierrors++;
> 				bge_newbuf_jumbo(sc, sc->bge_jumbo, m);
> 				continue;
>@@ -2819,7 +2819,7 @@
> 			stdcnt++;
> 			dmamap = sc->bge_cdata.bge_rx_std_map[rxidx];
> 			sc->bge_cdata.bge_rx_std_map[rxidx] = 0;
>-			if (cur_rx->bge_flags & BGE_RXBDFLAG_ERROR) {
>+			if (le16toh(cur_rx->bge_flags) & BGE_RXBDFLAG_ERROR) {
> 				ifp->if_ierrors++;
> 				bge_newbuf_std(sc, sc->bge_std, m, dmamap);
> 				continue;
>@@ -2841,12 +2841,12 @@
>                  */
> 		if (sc->bge_rx_alignment_bug) {
> 			memmove(mtod(m, caddr_t) + ETHER_ALIGN, m->m_data,
>-                                cur_rx->bge_len);
>+                                le16toh(cur_rx->bge_len));
> 			m->m_data += ETHER_ALIGN;
> 		}
> #endif
> 
>-		m->m_pkthdr.len = m->m_len = cur_rx->bge_len - ETHER_CRC_LEN;
>+		m->m_pkthdr.len = m->m_len = le16toh(cur_rx->bge_len) - ETHER_CRC_LEN;
> 		m->m_pkthdr.rcvif = ifp;
> 
> #if NBPFILTER > 0
>@@ -2859,18 +2859,18 @@
> 
> 		m->m_pkthdr.csum_flags = M_CSUM_IPv4;
> 
>-		if ((cur_rx->bge_ip_csum ^ 0xffff) != 0)
>+		if ((le16toh(cur_rx->bge_ip_csum) ^ 0xffff) != 0)
> 			m->m_pkthdr.csum_flags |= M_CSUM_IPv4_BAD;
> 		/*
> 		 * Rx transport checksum-offload may also
> 		 * have bugs with packets which, when transmitted,
> 		 * were `runts' requiring padding.
> 		 */
>-		if (cur_rx->bge_flags & BGE_RXBDFLAG_TCP_UDP_CSUM &&
>+		if (le16toh(cur_rx->bge_flags) & BGE_RXBDFLAG_TCP_UDP_CSUM &&
> 		    (/* (sc->_bge_quirks & BGE_QUIRK_SHORT_CKSUM_BUG) == 0 ||*/
> 		     m->m_pkthdr.len >= ETHER_MIN_NOPAD)) {
> 			m->m_pkthdr.csum_data =
>-			    cur_rx->bge_tcp_udp_csum;
>+			    le16toh(cur_rx->bge_tcp_udp_csum);
> 			m->m_pkthdr.csum_flags |=
> 			    (M_CSUM_TCPv4|M_CSUM_UDPv4|
> 			     M_CSUM_DATA|M_CSUM_NO_PSEUDOHDR);
>@@ -2880,8 +2880,8 @@
> 		 * If we received a packet with a vlan tag, pass it
> 		 * to vlan_input() instead of ether_input().
> 		 */
>-		if (cur_rx->bge_flags & BGE_RXBDFLAG_VLAN_TAG)
>-			VLAN_INPUT_TAG(ifp, m, cur_rx->bge_vlan_tag, continue);
>+		if (le16toh(cur_rx->bge_flags) & BGE_RXBDFLAG_VLAN_TAG)
>+			VLAN_INPUT_TAG(ifp, m, le16toh(cur_rx->bge_vlan_tag), continue);
> 
> 		(*ifp->if_input)(ifp, m);
> 	}
>@@ -2940,7 +2940,7 @@
> 
> 		idx = sc->bge_tx_saved_considx;
> 		cur_tx = &sc->bge_rdata->bge_tx_ring[idx];
>-		if (cur_tx->bge_flags & BGE_TXBDFLAG_END)
>+		if (le16toh(cur_tx->bge_flags) & BGE_TXBDFLAG_END)
> 			ifp->if_opackets++;
> 		m = sc->bge_cdata.bge_tx_chain[idx];
> 		if (m != NULL) {
>@@ -3421,14 +3421,14 @@
> 		if (sc->bge_cdata.bge_tx_chain[frag] != NULL)
> 			break;
> 		bge_set_hostaddr(&f->bge_addr, dmamap->dm_segs[i].ds_addr);
>-		f->bge_len = dmamap->dm_segs[i].ds_len;
>-		f->bge_flags = csum_flags;
>+		f->bge_len = htole16(dmamap->dm_segs[i].ds_len);
>+		f->bge_flags = htole16(csum_flags);
> 
> 		if (mtag != NULL) {
>-			f->bge_flags |= BGE_TXBDFLAG_VLAN_TAG;
>-			f->bge_vlan_tag = VLAN_TAG_VALUE(mtag);
>+			f->bge_flags |= htole16(BGE_TXBDFLAG_VLAN_TAG);
>+			f->bge_vlan_tag = htole16(VLAN_TAG_VALUE(mtag));
> 		} else {
>-			f->bge_vlan_tag = 0;
>+			f->bge_vlan_tag = 0; /* no need bswap */
> 		}
> 		/*
> 		 * Sanity check: avoid coming within 16 descriptors
>Index: if_bgereg.h
>===================================================================
>RCS file: /cvsroot/src/sys/dev/pci/if_bgereg.h,v
>retrieving revision 1.26
>diff -u -r1.26 if_bgereg.h
>--- if_bgereg.h	28 Aug 2005 19:24:57 -0000	1.26
>+++ if_bgereg.h	22 Nov 2005 20:01:15 -0000
>@@ -1755,9 +1755,9 @@
> static __inline void
> bge_set_hostaddr(volatile bge_hostaddr *x, bus_addr_t y)
> {
>-	x->bge_addr_lo = y & 0xffffffff;
>+	x->bge_addr_lo = htole32(y & 0xffffffff);
> 	if (sizeof (bus_addr_t) == 8)
>-		x->bge_addr_hi = (u_int64_t)y >> 32;
>+		x->bge_addr_hi = htole32((u_int64_t)y >> 32);
> 	else
> 		x->bge_addr_hi = 0;
> }
>@@ -1769,11 +1769,7 @@
> 	u_int32_t		bge_nicaddr;
> };
> 
>-#if BYTE_ORDER == BIG_ENDIAN
>-#define	BGE_RCB_MAXLEN_FLAGS(maxlen, flags)	((flags) << 16 | (maxlen))
>-#else
> #define	BGE_RCB_MAXLEN_FLAGS(maxlen, flags)	((maxlen) << 16 | (flags))
>-#endif
> 
> #define RCB_WRITE_4(sc, rcb, offset, val) \
> 	bus_space_write_4(sc->bge_btag, sc->bge_bhandle, \
>  
>


-- 
Garrett D'Amore                          http://www.tadpolecomputer.com/
Sr. Staff Engineer          Extending the Power of 64-bit UNIX Computing
Tadpole Computer, Inc.                             Phone: (951) 325-2134