Make the xl and pn drivers work on FreeBSD/alpha and add them to

sys/alpha/conf/GENERIC.

Note: the PNIC ignores the lower few bits of the RX buffer DMA address,
which means we have to add yet another kludge to make it happy. Since
we can't offset the packet data, we copy the first few bytes of the
received data into a separate mbuf with proper alignment. This puts
the IP header where it needs to be to prevent unaligned accesses.

Also modified the PNIC driver to use a non-interrupt driven TX
strategy. This improves performance somewhat on x86/SMP systems where
interrupt delivery doesn't seem to be as fast with an SMP kernel as
with a UP kernel.
This commit is contained in:
Bill Paul 1999-03-27 20:41:25 +00:00
parent fa93788041
commit 8fe2c75e31
6 changed files with 123 additions and 65 deletions

View File

@ -11,7 +11,7 @@
# device lines is present in the ./LINT configuration file. If you are
# in doubt as to the purpose or necessity of a line, check first in LINT.
#
# $Id: GENERIC,v 1.14 1999/01/18 20:26:50 gallatin Exp $
# $Id: GENERIC,v 1.15 1999/01/23 16:53:26 dfr Exp $
machine "alpha"
cpu "EV4"
@ -100,6 +100,8 @@ device sio1 at isa0 port "IO_COM2" irq 3 flags 0x50
device de0
device fxp0
device le0
device pn0
device xl0
pseudo-device loop
pseudo-device ether

View File

@ -11,7 +11,7 @@
# device lines is present in the ./LINT configuration file. If you are
# in doubt as to the purpose or necessity of a line, check first in LINT.
#
# $Id: GENERIC,v 1.14 1999/01/18 20:26:50 gallatin Exp $
# $Id: GENERIC,v 1.15 1999/01/23 16:53:26 dfr Exp $
machine "alpha"
cpu "EV4"
@ -100,6 +100,8 @@ device sio1 at isa0 port "IO_COM2" irq 3 flags 0x50
device de0
device fxp0
device le0
device pn0
device xl0
pseudo-device loop
pseudo-device ether

View File

@ -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_pn.c,v 1.37 1999/02/26 07:49:31 wpaul Exp $
* $Id: if_pn.c,v 1.41 1999/03/27 20:32:32 wpaul Exp $
*/
/*
@ -97,7 +97,7 @@
#ifndef lint
static const char rcsid[] =
"$Id: if_pn.c,v 1.37 1999/02/26 07:49:31 wpaul Exp $";
"$Id: if_pn.c,v 1.41 1999/03/27 20:32:32 wpaul Exp $";
#endif
/*
@ -855,7 +855,12 @@ pn_attach(config_id, unit)
printf ("pn%d: couldn't map ports\n", unit);
goto fail;
}
#ifdef __i386__
sc->pn_btag = I386_BUS_SPACE_IO;
#endif
#ifdef __alpha__
sc->pn_btag = ALPHA_BUS_SPACE_IO;
#endif
#else
if (!(command & PCIM_CMD_MEMEN)) {
printf("pn%d: failed to enable memory mapping!\n", unit);
@ -867,7 +872,12 @@ pn_attach(config_id, unit)
goto fail;
}
sc->pn_bhandle = vbase;
#ifdef __i386__
sc->pn_btag = I386_BUS_SPACE_MEM;
#endif
#ifdef __alpha__
sc->pn_btag = ALPHA_BUS_SPACE_MEM;
#endif
#endif
/* Allocate interrupt */
@ -1246,6 +1256,9 @@ static void pn_rxeof(sc)
while(!((rxstat = sc->pn_cdata.pn_rx_head->pn_ptr->pn_status) &
PN_RXSTAT_OWN)) {
#ifdef __alpha__
struct mbuf *m0 = NULL;
#endif
cur_rx = sc->pn_cdata.pn_rx_head;
sc->pn_cdata.pn_rx_head = cur_rx->pn_nextdesc;
@ -1305,10 +1318,51 @@ static void pn_rxeof(sc)
continue;
}
#ifdef __alpha__
/*
* Grrrr! On the alpha platform, the start of the
* packet data must be longword aligned so that ip_input()
* doesn't perform any unaligned accesses when it tries
* to fiddle with the IP header. But the PNIC is stupid
* and wants RX buffers to start on longword boundaries.
* So we can't just shift the DMA address over a few
* bytes to alter the payload alignment. Instead, we
* have to chop out ethernet and IP header parts of
* the packet and place then in a separate mbuf with
* the alignment fixed up properly.
*
* As if this chip wasn't broken enough already.
*/
MGETHDR(m0, M_DONTWAIT, MT_DATA);
if (m0 == NULL) {
ifp->if_ierrors++;
cur_rx->pn_ptr->pn_status = PN_RXSTAT;
cur_rx->pn_ptr->pn_ctl = PN_RXCTL_RLINK | PN_RXLEN;
bzero((char *)mtod(cur_rx->pn_mbuf, char *), MCLBYTES);
continue;
}
m0->m_data += 2;
if (total_len <= (MHLEN - 2)) {
bcopy(mtod(m, caddr_t), mtod(m0, caddr_t), total_len); m_freem(m);
m = m0;
m->m_pkthdr.len = m->m_len = total_len;
} else {
bcopy(mtod(m, caddr_t), mtod(m0, caddr_t), (MHLEN - 2));
m->m_len = total_len - (MHLEN - 2);
m->m_data += (MHLEN - 2);
m0->m_next = m;
m0->m_len = (MHLEN - 2);
m = m0;
m->m_pkthdr.len = total_len;
}
#else
m->m_pkthdr.len = m->m_len = total_len;
#endif
ifp->if_ipackets++;
eh = mtod(m, struct ether_header *);
m->m_pkthdr.rcvif = ifp;
m->m_pkthdr.len = m->m_len = total_len;
#if NBPFILTER > 0
/*
* Handle BPF listeners. Let the BPF user see the packet, but
@ -1377,7 +1431,7 @@ static void pn_txeof(sc)
cur_tx = sc->pn_cdata.pn_tx_head;
txstat = PN_TXSTATUS(cur_tx);
if ((txstat & PN_TXSTAT_OWN) || txstat == PN_UNSENT)
if (txstat & PN_TXSTAT_OWN)
break;
if (txstat & PN_TXSTAT_ERRSUM) {
@ -1424,12 +1478,6 @@ static void pn_txeoc(sc)
sc->pn_cdata.pn_tx_tail = NULL;
if (sc->pn_want_auto)
pn_autoneg_mii(sc, PN_FLAG_SCHEDDELAY, 1);
} else {
if (PN_TXOWN(sc->pn_cdata.pn_tx_head) == PN_UNSENT) {
PN_TXOWN(sc->pn_cdata.pn_tx_head) = PN_TXSTAT_OWN;
ifp->if_timer = 5;
CSR_WRITE_4(sc, PN_TXSTART, 0xFFFFFFFF);
}
}
return;
@ -1588,7 +1636,7 @@ static int pn_encap(sc, c, m_head)
c->pn_mbuf = m_head;
c->pn_lastdesc = frag - 1;
PN_TXCTL(c) |= PN_TXCTL_LASTFRAG;
PN_TXCTL(c) |= PN_TXCTL_LASTFRAG|PN_TXCTL_FINT;
PN_TXNEXT(c) = vtophys(&c->pn_nextdesc->pn_ptr->pn_frag[0]);
return(0);
@ -1649,6 +1697,8 @@ static void pn_start(ifp)
if (ifp->if_bpf)
bpf_mtap(ifp, cur_tx->pn_mbuf);
#endif
PN_TXOWN(cur_tx) = PN_TXSTAT_OWN;
CSR_WRITE_4(sc, PN_TXSTART, 0xFFFFFFFF);
}
/*
@ -1657,23 +1707,10 @@ static void pn_start(ifp)
if (cur_tx == NULL)
return;
/*
* Place the request for the upload interrupt
* in the last descriptor in the chain. This way, if
* we're chaining several packets at once, we'll only
* get an interupt once for the whole chain rather than
* once for each packet.
*/
PN_TXCTL(cur_tx) |= PN_TXCTL_FINT;
sc->pn_cdata.pn_tx_tail = cur_tx;
if (sc->pn_cdata.pn_tx_head == NULL) {
if (sc->pn_cdata.pn_tx_head == NULL)
sc->pn_cdata.pn_tx_head = start_tx;
PN_TXOWN(start_tx) = PN_TXSTAT_OWN;
CSR_WRITE_4(sc, PN_TXSTART, 0xFFFFFFFF);
} else {
PN_TXOWN(start_tx) = PN_UNSENT;
}
/*
* Set a timeout in case the chip goes out to lunch.

View File

@ -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_pnreg.h,v 1.17 1999/02/26 07:49:31 wpaul Exp $
* $Id: if_pnreg.h,v 1.21 1999/03/27 20:08:53 wpaul Exp $
*/
/*
@ -367,8 +367,6 @@ struct pn_txdesc {
#define PN_TXOWN(x) x->pn_ptr->pn_frag[0].pn_status
#define PN_UNSENT 0x12344321
struct pn_list_data {
struct pn_desc pn_rx_list[PN_RX_LIST_CNT];
struct pn_txdesc pn_tx_list[PN_TX_LIST_CNT];
@ -458,7 +456,7 @@ struct pn_softc {
#define CSR_WRITE_4(sc, reg, val) \
bus_space_write_4(sc->pn_btag, sc->pn_bhandle, reg, val)
#define CSR_WRITE_2(sc, reg, val) \
bus_space_write_2(sc->pn_btag, sc->pn_bbhandle, reg, val)
bus_space_write_2(sc->pn_btag, sc->pn_bhandle, reg, val)
#define CSR_WRITE_1(sc, reg, val) \
bus_space_write_1(sc->pn_btag, sc->pn_bhandle, reg, val)
@ -651,3 +649,9 @@ struct pn_softc {
#define PHY_BMSR_LINKSTAT 0x0004
#define PHY_BMSR_JABBER 0x0002
#define PHY_BMSR_EXTENDED 0x0001
#ifdef __alpha__
#undef vtophys
#define vtophys(va) (pmap_kextract(((vm_offset_t) (va))) \
+ 1*1024*1024*1024)
#endif

View File

@ -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_xl.c,v 1.24 1999/02/11 23:59:29 wpaul Exp $
* $Id: if_xl.c,v 1.68 1999/03/27 20:35:14 wpaul Exp $
*/
/*
@ -107,6 +107,9 @@
#include <vm/vm.h> /* for vtophys */
#include <vm/pmap.h> /* for vtophys */
#include <machine/clock.h> /* for DELAY */
#include <machine/bus_memio.h>
#include <machine/bus_pio.h>
#include <machine/bus.h>
#include <pci/pcireg.h>
#include <pci/pcivar.h>
@ -147,7 +150,7 @@
#if !defined(lint)
static const char rcsid[] =
"$Id: if_xl.c,v 1.24 1999/02/11 23:59:29 wpaul Exp $";
"$Id: if_xl.c,v 1.68 1999/03/27 20:35:14 wpaul Exp $";
#endif
/*
@ -1387,7 +1390,18 @@ xl_attach(config_id, unit)
goto fail;
}
sc->iobase = pci_conf_read(config_id, XL_PCI_LOIO) & 0xFFFFFFE0;
if (!pci_map_port(config_id, XL_PCI_LOIO,
(u_short *)&(sc->xl_bhandle))) {
printf ("xl%d: couldn't map port\n", unit);
goto fail;
}
#ifdef __i386__
sc->xl_btag = I386_BUS_SPACE_IO;
#endif
#ifdef __alpha__
sc->xl_btag = ALPHA_BUS_SPACE_IO;
#endif
#else
if (!(command & PCIM_CMD_MEMEN)) {
printf("xl%d: failed to enable memory mapping!\n", unit);
@ -1398,7 +1412,13 @@ xl_attach(config_id, unit)
printf ("xl%d: couldn't map memory\n", unit);
goto fail;
}
sc->csr = (volatile caddr_t)vbase;
sc->xl_bhandle = vbase;
#ifdef __i386__
sc->xl_btag = I386_BUS_SPACE_MEM;
#endif
#ifdef __alpha__
sc->xl_btag = ALPHA_BUS_SPACE_MEM;
#endif
#endif
/* Allocate interrupt */
@ -1768,6 +1788,11 @@ static int xl_newbuf(sc, c)
return(ENOBUFS);
}
#ifdef __alpha__
/* Force longword alignment for packet payload to pacify alpha. */
m_new->m_data += 2;
#endif
c->xl_mbuf = m_new;
c->xl_ptr->xl_status = 0;
c->xl_ptr->xl_frag.xl_addr = vtophys(mtod(m_new, caddr_t));

View File

@ -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_xlreg.h,v 1.19 1998/10/22 15:35:06 wpaul Exp $
* $Id: if_xlreg.h,v 1.20 1999/03/27 20:10:10 wpaul Exp $
*/
#define XL_EE_READ 0x0080 /* read, 5 bit address */
@ -539,10 +539,8 @@ struct xl_mii_frame {
struct xl_softc {
struct arpcom arpcom; /* interface info */
struct ifmedia ifmedia; /* media info */
u_int32_t iobase; /* pointer to PIO space */
#ifndef XL_USEIOSPACE
volatile caddr_t csr; /* pointer to register map */
#endif
bus_space_handle_t xl_bhandle;
bus_space_tag_t xl_btag;
struct xl_type *xl_info; /* 3Com adapter info */
struct xl_type *xl_pinfo; /* phy info */
u_int8_t xl_unit; /* interface number */
@ -586,35 +584,19 @@ struct xl_stats {
/*
* register space access macros
*/
#ifdef XL_USEIOSPACE
#define CSR_WRITE_4(sc, reg, val) \
outl(sc->iobase + (u_int32_t)(reg), val)
bus_space_write_4(sc->xl_btag, sc->xl_bhandle, reg, val)
#define CSR_WRITE_2(sc, reg, val) \
outw(sc->iobase + (u_int32_t)(reg), val)
bus_space_write_2(sc->xl_btag, sc->xl_bhandle, reg, val)
#define CSR_WRITE_1(sc, reg, val) \
outb(sc->iobase + (u_int32_t)(reg), val)
bus_space_write_1(sc->xl_btag, sc->xl_bhandle, reg, val)
#define CSR_READ_4(sc, reg) \
inl(sc->iobase + (u_int32_t)(reg))
#define CSR_READ_2(sc, reg) \
inw(sc->iobase + (u_int32_t)(reg))
#define CSR_READ_1(sc, reg) \
inb(sc->iobase + (u_int32_t)(reg))
#else
#define CSR_WRITE_4(sc, reg, val) \
((*(u_int32_t*)((sc)->csr + (u_int32_t)(reg))) = (u_int32_t)(val))
#define CSR_WRITE_2(sc, reg, val) \
((*(u_int16_t*)((sc)->csr + (u_int32_t)(reg))) = (u_int16_t)(val))
#define CSR_WRITE_1(sc, reg, val) \
((*(u_int8_t*)((sc)->csr + (u_int32_t)(reg))) = (u_int8_t)(val))
#define CSR_READ_4(sc, reg) \
(*(u_int32_t *)((sc)->csr + (u_int32_t)(reg)))
#define CSR_READ_2(sc, reg) \
(*(u_int16_t *)((sc)->csr + (u_int32_t)(reg)))
#define CSR_READ_1(sc, reg) \
(*(u_int8_t *)((sc)->csr + (u_int32_t)(reg)))
#endif
#define CSR_READ_4(sc, reg) \
bus_space_read_4(sc->xl_btag, sc->xl_bhandle, reg)
#define CSR_READ_2(sc, reg) \
bus_space_read_2(sc->xl_btag, sc->xl_bhandle, reg)
#define CSR_READ_1(sc, reg) \
bus_space_read_1(sc->xl_btag, sc->xl_bhandle, reg)
#define XL_SEL_WIN(x) \
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_WINSEL | x)
@ -822,3 +804,9 @@ struct xl_stats {
#define PHY_BMSR_LINKSTAT 0x0004
#define PHY_BMSR_JABBER 0x0002
#define PHY_BMSR_EXTENDED 0x0001
#ifdef __alpha__
#undef vtophys
#define vtophys(va) (pmap_kextract(((vm_offset_t) (va))) \
+ 1*1024*1024*1024)
#endif