Add smc91cxx_copy_tx_frame(), based on the version in cs89x0.c, to deal
with misaligned mbufs.
This commit is contained in:
parent
85fe6200b5
commit
ee37eef012
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: smc91cxx.c,v 1.42 2002/09/24 02:30:15 bsh Exp $ */
|
||||
/* $NetBSD: smc91cxx.c,v 1.43 2002/09/28 10:24:46 scw Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1997 The NetBSD Foundation, Inc.
|
||||
@ -78,7 +78,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: smc91cxx.c,v 1.42 2002/09/24 02:30:15 bsh Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: smc91cxx.c,v 1.43 2002/09/28 10:24:46 scw Exp $");
|
||||
|
||||
#include "opt_inet.h"
|
||||
#include "opt_ccitt.h"
|
||||
@ -214,6 +214,7 @@ void smc91cxx_init __P((struct smc91cxx_softc *));
|
||||
void smc91cxx_read __P((struct smc91cxx_softc *));
|
||||
void smc91cxx_reset __P((struct smc91cxx_softc *));
|
||||
void smc91cxx_start __P((struct ifnet *));
|
||||
void smc91cxx_copy_tx_frame __P((struct smc91cxx_softc *, struct mbuf *));
|
||||
void smc91cxx_resume __P((struct smc91cxx_softc *));
|
||||
void smc91cxx_stop __P((struct smc91cxx_softc *));
|
||||
void smc91cxx_watchdog __P((struct ifnet *));
|
||||
@ -582,7 +583,7 @@ smc91cxx_start(ifp)
|
||||
bus_space_tag_t bst = sc->sc_bst;
|
||||
bus_space_handle_t bsh = sc->sc_bsh;
|
||||
u_int len;
|
||||
struct mbuf *m, *top;
|
||||
struct mbuf *m;
|
||||
u_int16_t length, npages;
|
||||
u_int8_t packetno;
|
||||
int timo, pad;
|
||||
@ -603,7 +604,7 @@ smc91cxx_start(ifp)
|
||||
* number of bytes. Below, we assume that the packet length
|
||||
* is even.
|
||||
*/
|
||||
for (len = 0, top = m; m != NULL; m = m->m_next)
|
||||
for (len = 0; m != NULL; m = m->m_next)
|
||||
len += m->m_len;
|
||||
pad = (len & 1);
|
||||
|
||||
@ -696,17 +697,7 @@ smc91cxx_start(ifp)
|
||||
/*
|
||||
* Push the packet out to the card.
|
||||
*/
|
||||
for (top = m; m != NULL; m = m->m_next) {
|
||||
/* Words... */
|
||||
if (m->m_len > 1)
|
||||
bus_space_write_multi_stream_2(bst, bsh, DATA_REG_W,
|
||||
mtod(m, u_int16_t *), m->m_len >> 1);
|
||||
|
||||
/* ...and the remaining byte, if any. */
|
||||
if (m->m_len & 1)
|
||||
bus_space_write_1(bst, bsh, DATA_REG_B,
|
||||
*(u_int8_t *)(mtod(m, u_int8_t *) + (m->m_len - 1)));
|
||||
}
|
||||
smc91cxx_copy_tx_frame(sc, m);
|
||||
|
||||
#ifdef SMC91CXX_SW_PAD
|
||||
/*
|
||||
@ -742,11 +733,11 @@ smc91cxx_start(ifp)
|
||||
#if NBPFILTER > 0
|
||||
/* Hand off a copy to the bpf. */
|
||||
if (ifp->if_bpf)
|
||||
bpf_mtap(ifp->if_bpf, top);
|
||||
bpf_mtap(ifp->if_bpf, m);
|
||||
#endif
|
||||
|
||||
ifp->if_opackets++;
|
||||
m_freem(top);
|
||||
m_freem(m);
|
||||
|
||||
readcheck:
|
||||
/*
|
||||
@ -758,6 +749,86 @@ smc91cxx_start(ifp)
|
||||
goto again;
|
||||
}
|
||||
|
||||
/*
|
||||
* Squirt a (possibly misaligned) mbuf to the device
|
||||
*/
|
||||
void
|
||||
smc91cxx_copy_tx_frame(sc, m0)
|
||||
struct smc91cxx_softc *sc;
|
||||
struct mbuf *m0;
|
||||
{
|
||||
bus_space_tag_t bst = sc->sc_bst;
|
||||
bus_space_handle_t bsh = sc->sc_bsh;
|
||||
struct mbuf *m;
|
||||
int len, leftover;
|
||||
u_int16_t dbuf;
|
||||
u_int8_t *p;
|
||||
#ifdef DIAGNOSTIC
|
||||
u_int8_t *lim;
|
||||
#endif
|
||||
|
||||
/* start out with no leftover data */
|
||||
leftover = 0;
|
||||
dbuf = 0;
|
||||
|
||||
/* Process the chain of mbufs */
|
||||
for (m = m0; m != NULL; m = m->m_next) {
|
||||
/*
|
||||
* Process all of the data in a single mbuf.
|
||||
*/
|
||||
p = mtod(m, u_int8_t *);
|
||||
len = m->m_len;
|
||||
#ifdef DIAGNOSTIC
|
||||
lim = p + len;
|
||||
#endif
|
||||
|
||||
while (len > 0) {
|
||||
if (leftover) {
|
||||
/*
|
||||
* Data left over (from mbuf or realignment).
|
||||
* Buffer the next byte, and write it and
|
||||
* the leftover data out.
|
||||
*/
|
||||
dbuf |= *p++ << 8;
|
||||
len--;
|
||||
bus_space_write_2(bst, bsh, DATA_REG_W, dbuf);
|
||||
leftover = 0;
|
||||
} else if ((long) p & 1) {
|
||||
/*
|
||||
* Misaligned data. Buffer the next byte.
|
||||
*/
|
||||
dbuf = *p++;
|
||||
len--;
|
||||
leftover = 1;
|
||||
} else {
|
||||
/*
|
||||
* Aligned data. This is the case we like.
|
||||
*
|
||||
* Write-region out as much as we can, then
|
||||
* buffer the remaining byte (if any).
|
||||
*/
|
||||
leftover = len & 1;
|
||||
len &= ~1;
|
||||
bus_space_write_multi_stream_2(bst, bsh,
|
||||
DATA_REG_W, (u_int16_t *)p, len >> 1);
|
||||
p += len;
|
||||
|
||||
if (leftover)
|
||||
dbuf = *p++;
|
||||
len = 0;
|
||||
}
|
||||
}
|
||||
if (len < 0)
|
||||
panic("smc91cxx_copy_tx_frame: negative len");
|
||||
#ifdef DIAGNOSTIC
|
||||
if (p != lim)
|
||||
panic("smc91cxx_copy_tx_frame: p != lim");
|
||||
#endif
|
||||
}
|
||||
if (leftover)
|
||||
bus_space_write_1(bst, bsh, DATA_REG_B, dbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupt service routine.
|
||||
*/
|
||||
@ -1059,9 +1130,11 @@ smc91cxx_read(sc)
|
||||
*data = bus_space_read_1(bst, bsh, DATA_REG_B);
|
||||
}
|
||||
} else {
|
||||
u_int8_t *dp;
|
||||
|
||||
m->m_data = (caddr_t) ALIGN(mtod(m, caddr_t));
|
||||
eh = mtod(m, struct ether_header *);
|
||||
data = mtod(m, u_int8_t *);
|
||||
dp = data = mtod(m, u_int8_t *);
|
||||
if (packetlen > 3)
|
||||
bus_space_read_multi_stream_4(bst, bsh, DATA_REG_W,
|
||||
(u_int32_t *)data, packetlen >> 2);
|
||||
@ -1090,6 +1163,8 @@ smc91cxx_read(sc)
|
||||
}
|
||||
}
|
||||
|
||||
m->m_pkthdr.len = m->m_len = packetlen;
|
||||
|
||||
#if NBPFILTER > 0
|
||||
/*
|
||||
* Hand the packet off to bpf listeners.
|
||||
@ -1098,7 +1173,6 @@ smc91cxx_read(sc)
|
||||
bpf_mtap(ifp->if_bpf, m);
|
||||
#endif
|
||||
|
||||
m->m_pkthdr.len = m->m_len = packetlen;
|
||||
(*ifp->if_input)(ifp, m);
|
||||
|
||||
out:
|
||||
|
Loading…
Reference in New Issue
Block a user