From 504b8ae8d6e52a13ec244635f3526201a072f414 Mon Sep 17 00:00:00 2001 From: pefo Date: Tue, 17 Sep 1996 18:47:31 +0000 Subject: [PATCH] This driver and some other ether drivers violates the alignment of struct ether_header by placing it's start on a non 32bit int boundary. On processor with alignment restrictions (like MIPS) this will fail badly. This is the first driver to have been fixed. The fix is to copy the ether header to a separate buffer instead of into the mbuf. --- sys/dev/ic/elink3.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/sys/dev/ic/elink3.c b/sys/dev/ic/elink3.c index 8d51ec0467f..e7a4a0eb4c0 100644 --- a/sys/dev/ic/elink3.c +++ b/sys/dev/ic/elink3.c @@ -84,7 +84,7 @@ void epstart __P((struct ifnet *)); void epwatchdog __P((struct ifnet *)); void epreset __P((struct ep_softc *)); void epread __P((struct ep_softc *)); -struct mbuf *epget __P((struct ep_softc *, int)); +struct mbuf *epget __P((struct ep_softc *, struct ether_header *, int)); void epmbuffill __P((void *)); void epmbufempty __P((struct ep_softc *)); void epsetfilter __P((struct ep_softc *)); @@ -580,7 +580,7 @@ epread(sc) bus_io_handle_t ioh = sc->sc_ioh; struct ifnet *ifp = &sc->sc_arpcom.ac_if; struct mbuf *m; - struct ether_header *eh; + struct ether_header eh; int len; len = bus_io_read_2(bc, ioh, EP_W1_RX_STATUS); @@ -620,7 +620,7 @@ again: len &= RX_BYTES_MASK; /* Lower 11 bits = RX bytes. */ /* Pull packet off interface. */ - m = epget(sc, len); + m = epget(sc, &eh, len); if (m == 0) { ifp->if_ierrors++; goto abort; @@ -628,9 +628,6 @@ again: ++ifp->if_ipackets; - /* We assume the header fit entirely in one mbuf. */ - eh = mtod(m, struct ether_header *); - #if NBPFILTER > 0 /* * Check if there's a BPF listener on this interface. @@ -645,18 +642,16 @@ again: * mode, we have to check if this packet is really ours. */ if ((ifp->if_flags & IFF_PROMISC) && - (eh->ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */ - bcmp(eh->ether_dhost, sc->sc_arpcom.ac_enaddr, - sizeof(eh->ether_dhost)) != 0) { + (eh.ether_dhost[0] & 1) == 0 && /* !mcast and !bcast */ + bcmp(eh.ether_dhost, sc->sc_arpcom.ac_enaddr, + sizeof(eh.ether_dhost)) != 0) { m_freem(m); return; } } #endif - /* We assume the header fit entirely in one mbuf. */ - m_adj(m, sizeof(struct ether_header)); - ether_input(ifp, eh, m); + ether_input(ifp, &eh, m); /* * In periods of high traffic we can actually receive enough @@ -696,8 +691,9 @@ abort: } struct mbuf * -epget(sc, totlen) +epget(sc, eh, totlen) struct ep_softc *sc; + struct ether_header *eh; int totlen; { bus_chipset_tag_t bc = sc->sc_bc; @@ -723,7 +719,6 @@ epget(sc, totlen) m->m_flags = M_PKTHDR; } m->m_pkthdr.rcvif = ifp; - m->m_pkthdr.len = totlen; len = MHLEN; top = 0; mp = ⊤ @@ -735,6 +730,13 @@ epget(sc, totlen) */ sh = splhigh(); + if(totlen > sizeof(struct ether_header)) { + bus_io_read_multi_2(bc, ioh, + EP_W1_RX_PIO_RD_1, eh, sizeof(struct ether_header) / 2); + totlen -= sizeof(struct ether_header); + } + m->m_pkthdr.len = totlen; + while (totlen > 0) { if (top) { m = sc->mb[sc->next_mb]; -- 2.20.1