summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorPer Fogelstrom <pefo@cvs.openbsd.org>1996-09-17 18:47:32 +0000
committerPer Fogelstrom <pefo@cvs.openbsd.org>1996-09-17 18:47:32 +0000
commit731646b59e36960f043b28fe80157bfa0f6fbdd9 (patch)
tree6ab4e5bc5239fa4f1f1f86c62594ffbe38f365f0 /sys/dev
parent6ede98ec75a3e58ac9ceb1b46c7083ae141542bd (diff)
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.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ic/elink3.c30
1 files 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 = &top;
@@ -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];