diff options
author | wpaul <wpaul@FreeBSD.org> | 1999-06-19 20:17:38 +0000 |
---|---|---|
committer | wpaul <wpaul@FreeBSD.org> | 1999-06-19 20:17:38 +0000 |
commit | bf694850c4689290cec3f73afa21c3d54a733785 (patch) | |
tree | b5b94aab1c3a43010b6e31b634fbeef81ab6fae0 /sys/pci/if_rl.c | |
parent | ff773191969ea0eb35218ab5f90ca57d05cff015 (diff) | |
download | FreeBSD-src-bf694850c4689290cec3f73afa21c3d54a733785.zip FreeBSD-src-bf694850c4689290cec3f73afa21c3d54a733785.tar.gz |
Fix up the RealTek 8139 driver to work on FreeBSD/alpha. This involves a
few changes:
- there was a bug in rl_list_tx_init(): it was calculating the registers
to initialize incorrectly. Not a problem on the x86 where unaligned
access are allowed, but a problem on the alpha.
- set rl_btag accordingly depending on the machine type
- rl_rxeof() needs to be sure to longword-align the packet data. This
is a little tricky since we copy the data out of the receive buffer
using m_devget(), however there's no way to tell m_devget() to fill
in the mbufs starting at a particular offset. To get around this,
we tell m_devget to copy bytes+2 bytes starting at offset offset-2. This
results in the proper alignment, and we can trim off the two leading
bytes afterwards with m_adj(). We also allocate some extra space before
the start of the receive buffer so that we don't get into trouble in
the case where offset == 0.
- redefine vtophys() in if_rlreg.h for the alpha.
Making this chipset work on the alpha is sort of the inverse of putting
a jet engine on a rowboat (putting a propeller on a 747?) but when
you can get these things for $5 a pop, it's hard to stop people from
buying them.
Diffstat (limited to 'sys/pci/if_rl.c')
-rw-r--r-- | sys/pci/if_rl.c | 46 |
1 files changed, 38 insertions, 8 deletions
diff --git a/sys/pci/if_rl.c b/sys/pci/if_rl.c index b73d6ae..5b0ac24 100644 --- a/sys/pci/if_rl.c +++ b/sys/pci/if_rl.c @@ -29,7 +29,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: if_rl.c,v 1.15 1999/05/09 17:06:58 peter Exp $ + * $Id: if_rl.c,v 1.32 1999/06/19 20:01:32 wpaul Exp wpaul $ */ /* @@ -127,7 +127,7 @@ #ifndef lint static const char rcsid[] = - "$Id: if_rl.c,v 1.15 1999/05/09 17:06:58 peter Exp $"; + "$Id: if_rl.c,v 1.32 1999/06/19 20:01:32 wpaul Exp wpaul $"; #endif /* @@ -1080,7 +1080,12 @@ rl_attach(config_id, unit) printf ("rl%d: couldn't map ports\n", unit); goto fail; } +#ifdef __i386__ sc->rl_btag = I386_BUS_SPACE_IO; +#endif +#ifdef __alpha__ + sc->rl_btag = ALPHA_BUS_SPACE_IO; +#endif #else if (!(command & PCIM_CMD_MEMEN)) { printf("rl%d: failed to enable memory mapping!\n", unit); @@ -1091,7 +1096,12 @@ rl_attach(config_id, unit) printf ("rl%d: couldn't map memory\n", unit); goto fail; } +#ifdef __i386__ sc->rl_btag = I386_BUS_SPACE_MEM; +#endif +#ifdef __alpha__ + sc->rl_btag = ALPHA_BUS_SPACE_MEM; +#endif sc->rl_bhandle = vbase; #endif @@ -1135,7 +1145,7 @@ rl_attach(config_id, unit) goto fail; } - sc->rl_cdata.rl_rx_buf = contigmalloc(RL_RXBUFLEN + 16, M_DEVBUF, + sc->rl_cdata.rl_rx_buf = contigmalloc(RL_RXBUFLEN + 32, M_DEVBUF, M_NOWAIT, 0x100000, 0xffffffff, PAGE_SIZE, 0); if (sc->rl_cdata.rl_rx_buf == NULL) { @@ -1144,6 +1154,10 @@ rl_attach(config_id, unit) goto fail; } + /* Leave a few bytes before the start of the RX ring buffer. */ + sc->rl_cdata.rl_rx_buf_ptr = sc->rl_cdata.rl_rx_buf; + sc->rl_cdata.rl_rx_buf += sizeof(u_int64_t); + ifp = &sc->arpcom.ac_if; ifp->if_softc = sc; ifp->if_unit = unit; @@ -1242,7 +1256,8 @@ static int rl_list_tx_init(sc) cd = &sc->rl_cdata; for (i = 0; i < RL_TX_LIST_CNT; i++) { cd->rl_tx_chain[i] = NULL; - CSR_WRITE_4(sc, RL_TXADDR0 + i, 0x0000000); + CSR_WRITE_4(sc, + RL_TXADDR0 + (i * sizeof(u_int32_t)), 0x0000000); } sc->rl_cdata.cur_tx = 0; @@ -1267,6 +1282,16 @@ static int rl_list_tx_init(sc) * the status word) is also 32-bit aligned. The frame length is in the * first 16 bits of the status word; the lower 15 bits correspond with * the 'rx status register' mentioned in the datasheet. + * + * Note: to make the Alpha happy, the frame payload needs to be aligned + * on a 32-bit boundary. To achieve this, we cheat a bit by copying from + * the ring buffer starting at an address two bytes before the actual + * data location. We can then shave off the first two bytes using m_adj(). + * The reason we do this is because m_devget() doesn't let us specify an + * offset into the mbuf storage space, so we have to artificially create + * one. The ring is allocated in such a way that there are a few unused + * bytes of space preceecing it so that it will be safe for us to do the + * 2-byte backstep even if reading from the ring at offset 0. */ static void rl_rxeof(sc) struct rl_softc *sc; @@ -1355,23 +1380,28 @@ static void rl_rxeof(sc) wrap = (sc->rl_cdata.rl_rx_buf + RL_RXBUFLEN) - rxbufpos; if (total_len > wrap) { - m = m_devget(rxbufpos, wrap, 0, ifp, NULL); + m = m_devget(rxbufpos - RL_ETHER_ALIGN, + wrap + RL_ETHER_ALIGN, 0, ifp, NULL); if (m == NULL) { ifp->if_ierrors++; printf("rl%d: out of mbufs, tried to " "copy %d bytes\n", sc->rl_unit, wrap); } - else + else { + m_adj(m, RL_ETHER_ALIGN); m_copyback(m, wrap, total_len - wrap, sc->rl_cdata.rl_rx_buf); + } cur_rx = (total_len - wrap + ETHER_CRC_LEN); } else { - m = m_devget(rxbufpos, total_len, 0, ifp, NULL); + m = m_devget(rxbufpos - RL_ETHER_ALIGN, + total_len + RL_ETHER_ALIGN, 0, ifp, NULL); if (m == NULL) { ifp->if_ierrors++; printf("rl%d: out of mbufs, tried to " "copy %d bytes\n", sc->rl_unit, total_len); - } + } else + m_adj(m, RL_ETHER_ALIGN); cur_rx += total_len + 4 + ETHER_CRC_LEN; } |