diff options
author | dg <dg@FreeBSD.org> | 1995-05-26 02:02:44 +0000 |
---|---|---|
committer | dg <dg@FreeBSD.org> | 1995-05-26 02:02:44 +0000 |
commit | d625c1c9dab8c2c73107c39871be390c282a8037 (patch) | |
tree | c5dced0bb62a33507696d375b3a3ce07d8678010 /sys/pci | |
parent | b73bae1345f99e90b86b4670f3299598e0e82e25 (diff) | |
download | FreeBSD-src-d625c1c9dab8c2c73107c39871be390c282a8037.zip FreeBSD-src-d625c1c9dab8c2c73107c39871be390c282a8037.tar.gz |
Fixed bugs in multicast address handling (flag was set in wrong register,
etc.). The tulip_start routine was rewritten to use less stack space (I've
been having problems with wcarchive overflowing the stack and this should
help a little). This version also has preliminary NetBSD support.
Rod Grimes helped in testing this version of the driver. Thanks Rod. It's
additionally been extensively tested here and on wcarchive.
Submitted by: Matt Thomas
Diffstat (limited to 'sys/pci')
-rw-r--r-- | sys/pci/if_de.c | 693 |
1 files changed, 427 insertions, 266 deletions
diff --git a/sys/pci/if_de.c b/sys/pci/if_de.c index 8b708f0..2767cce 100644 --- a/sys/pci/if_de.c +++ b/sys/pci/if_de.c @@ -21,7 +21,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: if_de.c,v 1.25 1995/05/22 05:51:41 davidg Exp $ + * $Id: if_de.c,v 1.26 1995/05/22 13:32:24 davidg Exp $ * */ @@ -35,11 +35,10 @@ * board which support DC21040 or DC21140 (mostly). */ -#define __IF_DE_C__ "pl2 95/03/21" -#ifndef __bsdi__ +#if defined(__FreeBSD__) #include "de.h" #endif -#if NDE > 0 || defined(__bsdi__) +#if NDE > 0 || !defined(__FreeBSD__) #include <sys/param.h> #include <sys/systm.h> @@ -54,8 +53,7 @@ #if defined(__FreeBSD__) #include <sys/devconf.h> #include <machine/clock.h> -#endif -#if defined(__bsdi__) +#elif defined(__bsdi__) || defined(__NetBSD__) #include <sys/device.h> #endif @@ -104,6 +102,11 @@ #include <i386/isa/isavar.h> #endif +#if defined(__NetBSD__) +#include <dev/pci/pcivar.h> +#include <dev/ic/dc21040.h> +#endif + /* * This module supports * the DEC DC21040 PCI Ethernet Controller. @@ -154,6 +157,20 @@ typedef struct { } tulip_regfile_t; /* + * macros to read and write CSRs. Note that the "0 +" in + * READ_CSR is to prevent the macro from being an lvalue + * and WRITE_CSR shouldn't be assigned from. + */ +#define TULIP_READ_CSR(sc, csr) (0 + *(sc)->tulip_csrs.csr) +#ifndef __alpha__ +#define TULIP_WRITE_CSR(sc, csr, val) \ + ((void)(*(sc)->tulip_csrs.csr = (val))) +#else +#define TULIP_WRITE_CSR(sc, csr, val) \ + ((void)(*(sc)->tulip_csrs.csr = (val), MB())) +#endif + +/* * The DC21040 has a stupid restriction in that the receive * buffers must be longword aligned. But since Ethernet * headers are not a multiple of longwords in size this forces @@ -177,6 +194,11 @@ typedef struct { * but we gone to directly DMA'ing into MBUFs because with 100Mb * cards the copying is just too much of a hit. */ +#if defined(__alpha__) +#define TULIP_COPY_RXDATA 1 +#endif + + #define TULIP_RXDESCS 16 #define TULIP_TXDESCS 128 #define TULIP_RXQ_TARGET 8 @@ -206,6 +228,11 @@ struct _tulip_softc_t { struct intrhand tulip_ih; /* intrrupt vectoring */ struct atshutdown tulip_ats; /* shutdown routine */ #endif +#if defined(__NetBSD__) + struct device tulip_dev; /* base device */ + void *tulip_ih; /* intrrupt vectoring */ + /* XXX no shutdown routine? */ +#endif struct arpcom tulip_ac; tulip_regfile_t tulip_csrs; unsigned tulip_flags; @@ -221,9 +248,6 @@ struct _tulip_softc_t { tulip_uint32_t tulip_revinfo; tulip_chipid_t tulip_chipid; const tulip_boardsw_t *tulip_boardsw; -#if NBPFILTER > 0 && !defined(__bsdi__) && !defined(__FreeBSD__) - caddr_t tulip_bpf; /* BPF context */ -#endif struct ifqueue tulip_txq; struct ifqueue tulip_rxq; tulip_ringinfo_t tulip_rxinfo; @@ -233,7 +257,7 @@ struct _tulip_softc_t { #ifndef IFF_ALTPHYS #define IFF_ALTPHYS IFF_LINK0 /* In case it isn't defined */ #endif -const char *tulip_chipdescs[] = { +static const char *tulip_chipdescs[] = { "DC21040 [10Mb/s]", "DC21140 [10-100Mb/s]", "DC21041 [10Mb/s]" @@ -241,20 +265,27 @@ const char *tulip_chipdescs[] = { #if defined(__FreeBSD__) typedef void ifnet_ret_t; +typedef int ioctl_cmd_t; tulip_softc_t *tulips[NDE]; #define TULIP_UNIT_TO_SOFTC(unit) (tulips[unit]) -#define tulip_bpf tulip_ac.ac_if.if_bpf #endif #if defined(__bsdi__) typedef int ifnet_ret_t; +typedef int ioctl_cmd_t; +extern struct cfdriver decd; +#define TULIP_UNIT_TO_SOFTC(unit) ((tulip_softc_t *) decd.cd_devs[unit]) +#endif +#if defined(__NetBSD__) +typedef void ifnet_ret_t; +typedef u_long ioctl_cmd_t; extern struct cfdriver decd; #define TULIP_UNIT_TO_SOFTC(unit) ((tulip_softc_t *) decd.cd_devs[unit]) -#define tulip_bpf tulip_ac.ac_if.if_bpf #endif #define tulip_if tulip_ac.ac_if #define tulip_unit tulip_ac.ac_if.if_unit #define tulip_name tulip_ac.ac_if.if_name +#define tulip_bpf tulip_ac.ac_if.if_bpf #define tulip_hwaddr tulip_ac.ac_enaddr #define TULIP_CRC32_POLY 0xEDB88320UL /* CRC-32 Poly -- Little Endian */ @@ -274,48 +305,40 @@ static ifnet_ret_t tulip_start(struct ifnet *ifp); static void tulip_rx_intr(tulip_softc_t *sc); static void tulip_addr_filter(tulip_softc_t *sc); -#if __FreeBSD__ > 1 || defined(__bsdi__) -#define TULIP_IFRESET_ARGS int unit -#define TULIP_RESET(sc) tulip_reset((sc)->tulip_unit) -#else -#define TULIP_IFRESET_ARGS int unit, int uban -#define TULIP_RESET(sc) tulip_reset((sc)->tulip_unit, 0) -#endif - static int tulip_dc21040_media_probe( - tulip_softc_t *sc) + tulip_softc_t * const sc) { int cnt; - *sc->tulip_csrs.csr_sia_connectivity = 0; - *sc->tulip_csrs.csr_sia_connectivity = TULIP_SIACONN_10BASET; + TULIP_WRITE_CSR(sc, csr_sia_connectivity, 0); + TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_SIACONN_10BASET); for (cnt = 0; cnt < 2400; cnt++) { - if ((*sc->tulip_csrs.csr_sia_status & TULIP_SIASTS_LINKFAIL) == 0) + if ((TULIP_READ_CSR(sc, csr_sia_status) & TULIP_SIASTS_LINKFAIL) == 0) break; DELAY(1000); } - return (*sc->tulip_csrs.csr_sia_status & TULIP_SIASTS_LINKFAIL) != 0; + return (TULIP_READ_CSR(sc, csr_sia_status) & TULIP_SIASTS_LINKFAIL) != 0; } static void tulip_dc21040_media_select( - tulip_softc_t *sc) + tulip_softc_t * const sc) { sc->tulip_cmdmode |= TULIP_CMD_CAPTREFFCT; - *sc->tulip_csrs.csr_sia_connectivity = TULIP_SIACONN_RESET; + TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_SIACONN_RESET); if (sc->tulip_if.if_flags & IFF_ALTPHYS) { if ((sc->tulip_flags & TULIP_ALTPHYS) == 0) printf("%s%d: enabling Thinwire/AUI port\n", sc->tulip_if.if_name, sc->tulip_if.if_unit); - *sc->tulip_csrs.csr_sia_connectivity = TULIP_SIACONN_AUI; + TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_SIACONN_AUI); sc->tulip_flags |= TULIP_ALTPHYS; } else { if (sc->tulip_flags & TULIP_ALTPHYS) printf("%s%d: enabling 10baseT/UTP port\n", sc->tulip_if.if_name, sc->tulip_if.if_unit); - *sc->tulip_csrs.csr_sia_connectivity = TULIP_SIACONN_10BASET; + TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_SIACONN_10BASET); sc->tulip_flags &= ~TULIP_ALTPHYS; } } @@ -329,24 +352,26 @@ static const tulip_boardsw_t tulip_dc21040_boardsw = { static int tulip_dc21140_evalboard_media_probe( - tulip_softc_t *sc) + tulip_softc_t * const sc) { - *sc->tulip_csrs.csr_gp = TULIP_GP_EB_PINS; - *sc->tulip_csrs.csr_gp = TULIP_GP_EB_INIT; - *sc->tulip_csrs.csr_command |= TULIP_CMD_PORTSELECT - |TULIP_CMD_PCSFUNCTION|TULIP_CMD_SCRAMBLER|TULIP_CMD_MUSTBEONE; - *sc->tulip_csrs.csr_command &= ~TULIP_CMD_TXTHRSHLDCTL; + TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_EB_PINS); + TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_EB_INIT); + TULIP_WRITE_CSR(sc, csr_command, + TULIP_READ_CSR(sc, csr_command) | TULIP_CMD_PORTSELECT | + TULIP_CMD_PCSFUNCTION | TULIP_CMD_SCRAMBLER | TULIP_CMD_MUSTBEONE); + TULIP_WRITE_CSR(sc, csr_command, + TULIP_READ_CSR(sc, csr_command) & ~TULIP_CMD_TXTHRSHLDCTL); DELAY(1000000); - return (*sc->tulip_csrs.csr_gp & TULIP_GP_EB_OK100) != 0; + return (TULIP_READ_CSR(sc, csr_gp) & TULIP_GP_EB_OK100) != 0; } static void tulip_dc21140_evalboard_media_select( - tulip_softc_t *sc) + tulip_softc_t * const sc) { sc->tulip_cmdmode |= TULIP_CMD_STOREFWD|TULIP_CMD_MUSTBEONE; - *sc->tulip_csrs.csr_gp = TULIP_GP_EB_PINS; - *sc->tulip_csrs.csr_gp = TULIP_GP_EB_INIT; + TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_EB_PINS); + TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_EB_INIT); if (sc->tulip_if.if_flags & IFF_ALTPHYS) { if ((sc->tulip_flags & TULIP_ALTPHYS) == 0) printf("%s%d: enabling 100baseTX UTP port\n", @@ -376,23 +401,25 @@ static const tulip_boardsw_t tulip_dc21140_eb_boardsw = { static int tulip_dc21140_cogent_em100_media_probe( - tulip_softc_t *sc) + tulip_softc_t * const sc) { - *sc->tulip_csrs.csr_gp = TULIP_GP_EM100_PINS; - *sc->tulip_csrs.csr_gp = TULIP_GP_EM100_INIT; - *sc->tulip_csrs.csr_command |= TULIP_CMD_PORTSELECT - |TULIP_CMD_PCSFUNCTION|TULIP_CMD_SCRAMBLER|TULIP_CMD_MUSTBEONE; - *sc->tulip_csrs.csr_command &= ~TULIP_CMD_TXTHRSHLDCTL; + TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_EM100_PINS); + TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_EM100_INIT); + TULIP_WRITE_CSR(sc, csr_command, + TULIP_READ_CSR(sc, csr_command) | TULIP_CMD_PORTSELECT | + TULIP_CMD_PCSFUNCTION | TULIP_CMD_SCRAMBLER | TULIP_CMD_MUSTBEONE); + TULIP_WRITE_CSR(sc, csr_command, + TULIP_READ_CSR(sc, csr_command) & ~TULIP_CMD_TXTHRSHLDCTL); return 1; } static void tulip_dc21140_cogent_em100_media_select( - tulip_softc_t *sc) + tulip_softc_t * const sc) { sc->tulip_cmdmode |= TULIP_CMD_STOREFWD|TULIP_CMD_MUSTBEONE; - *sc->tulip_csrs.csr_gp = TULIP_GP_EM100_PINS; - *sc->tulip_csrs.csr_gp = TULIP_GP_EM100_INIT; + TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_EM100_PINS); + TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_EM100_INIT); if ((sc->tulip_flags & TULIP_ALTPHYS) == 0) printf("%s%d: enabling 100baseTX UTP port\n", sc->tulip_if.if_name, sc->tulip_if.if_unit); @@ -411,27 +438,32 @@ static const tulip_boardsw_t tulip_dc21140_cogent_em100_boardsw = { static int tulip_dc21140_de500_media_probe( - tulip_softc_t *sc) + tulip_softc_t * const sc) { - *sc->tulip_csrs.csr_gp = TULIP_GP_DE500_PINS; + TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_DE500_PINS); DELAY(1000); - *sc->tulip_csrs.csr_gp = TULIP_GP_DE500_HALFDUPLEX; - if ((*sc->tulip_csrs.csr_gp & (TULIP_GP_DE500_NOTOK_100|TULIP_GP_DE500_NOTOK_10)) != (TULIP_GP_DE500_NOTOK_100|TULIP_GP_DE500_NOTOK_10)) - return (*sc->tulip_csrs.csr_gp & TULIP_GP_DE500_NOTOK_100) != 0; - *sc->tulip_csrs.csr_gp = TULIP_GP_DE500_HALFDUPLEX|TULIP_GP_DE500_FORCE_100; - *sc->tulip_csrs.csr_command |= TULIP_CMD_PORTSELECT - |TULIP_CMD_PCSFUNCTION|TULIP_CMD_SCRAMBLER|TULIP_CMD_MUSTBEONE; - *sc->tulip_csrs.csr_command &= ~TULIP_CMD_TXTHRSHLDCTL; + TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_DE500_HALFDUPLEX); + if ((TULIP_READ_CSR(sc, csr_gp) & + (TULIP_GP_DE500_NOTOK_100|TULIP_GP_DE500_NOTOK_10)) != + (TULIP_GP_DE500_NOTOK_100|TULIP_GP_DE500_NOTOK_10)) + return (TULIP_READ_CSR(sc, csr_gp) & TULIP_GP_DE500_NOTOK_100) != 0; + TULIP_WRITE_CSR(sc, csr_gp, + TULIP_GP_DE500_HALFDUPLEX|TULIP_GP_DE500_FORCE_100); + TULIP_WRITE_CSR(sc, csr_command, + TULIP_READ_CSR(sc, csr_command) | TULIP_CMD_PORTSELECT | + TULIP_CMD_PCSFUNCTION | TULIP_CMD_SCRAMBLER | TULIP_CMD_MUSTBEONE); + TULIP_WRITE_CSR(sc, csr_command, + TULIP_READ_CSR(sc, csr_command) & ~TULIP_CMD_TXTHRSHLDCTL); DELAY(1000000); - return (*sc->tulip_csrs.csr_gp & TULIP_GP_DE500_NOTOK_100) != 0; + return (TULIP_READ_CSR(sc, csr_gp) & TULIP_GP_DE500_NOTOK_100) != 0; } static void tulip_dc21140_de500_media_select( - tulip_softc_t *sc) + tulip_softc_t * const sc) { sc->tulip_cmdmode |= TULIP_CMD_STOREFWD|TULIP_CMD_MUSTBEONE; - *sc->tulip_csrs.csr_gp = TULIP_GP_DE500_PINS; + TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_DE500_PINS); if (sc->tulip_if.if_flags & IFF_ALTPHYS) { if ((sc->tulip_flags & TULIP_ALTPHYS) == 0) printf("%s%d: enabling 100baseTX UTP port\n", @@ -440,8 +472,8 @@ tulip_dc21140_de500_media_select( |TULIP_CMD_PCSFUNCTION|TULIP_CMD_SCRAMBLER; sc->tulip_cmdmode &= ~TULIP_CMD_TXTHRSHLDCTL; sc->tulip_flags |= TULIP_ALTPHYS; - *sc->tulip_csrs.csr_gp = TULIP_GP_DE500_HALFDUPLEX - |TULIP_GP_DE500_FORCE_100; + TULIP_WRITE_CSR(sc, csr_gp, + TULIP_GP_DE500_HALFDUPLEX|TULIP_GP_DE500_FORCE_100); } else { if (sc->tulip_flags & TULIP_ALTPHYS) printf("%s%d: enabling 10baseT UTP port\n", @@ -450,7 +482,7 @@ tulip_dc21140_de500_media_select( |TULIP_CMD_PCSFUNCTION|TULIP_CMD_SCRAMBLER); sc->tulip_cmdmode |= TULIP_CMD_TXTHRSHLDCTL; sc->tulip_flags &= ~TULIP_ALTPHYS; - *sc->tulip_csrs.csr_gp = TULIP_GP_DE500_HALFDUPLEX; + TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_DE500_HALFDUPLEX); } } @@ -460,29 +492,26 @@ static const tulip_boardsw_t tulip_dc21140_de500_boardsw = { tulip_dc21140_de500_media_select }; -static ifnet_ret_t +static void tulip_reset( - TULIP_IFRESET_ARGS) + tulip_softc_t * const sc) { - tulip_softc_t *sc = TULIP_UNIT_TO_SOFTC(unit); tulip_ringinfo_t *ri; tulip_desc_t *di; - *sc->tulip_csrs.csr_busmode = TULIP_BUSMODE_SWRESET; + TULIP_WRITE_CSR(sc, csr_busmode, TULIP_BUSMODE_SWRESET); DELAY(10); /* Wait 10 microsends (actually 50 PCI cycles but at 33MHz that comes to two microseconds but wait a bit longer anyways) */ (*sc->tulip_boardsw->bd_media_select)(sc); - *sc->tulip_csrs.csr_txlist = vtophys(&sc->tulip_txinfo.ri_first[0]); - *sc->tulip_csrs.csr_rxlist = vtophys(&sc->tulip_rxinfo.ri_first[0]); - *sc->tulip_csrs.csr_intr = 0; - *sc->tulip_csrs.csr_busmode = TULIP_BUSMODE_BURSTLEN_8LW - |TULIP_BUSMODE_CACHE_ALIGN8 - |(BYTE_ORDER != LITTLE_ENDIAN - ? TULIP_BUSMODE_BIGENDIAN - : 0); + TULIP_WRITE_CSR(sc, csr_txlist, vtophys(&sc->tulip_txinfo.ri_first[0])); + TULIP_WRITE_CSR(sc, csr_rxlist, vtophys(&sc->tulip_rxinfo.ri_first[0])); + TULIP_WRITE_CSR(sc, csr_intr, 0); + TULIP_WRITE_CSR(sc, csr_busmode, + TULIP_BUSMODE_BURSTLEN_8LW|TULIP_BUSMODE_CACHE_ALIGN8 + |(BYTE_ORDER != LITTLE_ENDIAN ? TULIP_BUSMODE_BIGENDIAN : 0)); sc->tulip_txq.ifq_maxlen = TULIP_TXDESCS; /* @@ -531,12 +560,10 @@ tulip_reset( tulip_addr_filter(sc); } -static ifnet_ret_t +static void tulip_init( - int unit) + tulip_softc_t * const sc) { - tulip_softc_t *sc = TULIP_UNIT_TO_SOFTC(unit); - if (sc->tulip_if.if_flags & IFF_UP) { sc->tulip_if.if_flags |= IFF_RUNNING; if (sc->tulip_if.if_flags & IFF_PROMISC) { @@ -559,10 +586,10 @@ tulip_init( tulip_start(&sc->tulip_if); } sc->tulip_cmdmode |= TULIP_CMD_THRSHLD160; - *sc->tulip_csrs.csr_intr = sc->tulip_intrmask; - *sc->tulip_csrs.csr_command = sc->tulip_cmdmode; + TULIP_WRITE_CSR(sc, csr_intr, sc->tulip_intrmask); + TULIP_WRITE_CSR(sc, csr_command, sc->tulip_cmdmode); } else { - TULIP_RESET(sc); + tulip_reset(sc); sc->tulip_if.if_flags &= ~IFF_RUNNING; } } @@ -604,10 +631,10 @@ tulip_crc32( static void tulip_rx_intr( - tulip_softc_t *sc) + tulip_softc_t * const sc) { - tulip_ringinfo_t *ri = &sc->tulip_rxinfo; - struct ifnet *ifp = &sc->tulip_if; + tulip_ringinfo_t * const ri = &sc->tulip_rxinfo; + struct ifnet * const ifp = &sc->tulip_if; for (;;) { struct ether_header eh; @@ -629,22 +656,23 @@ tulip_rx_intr( #if TULIP_CHECK_RXCRC unsigned crc = tulip_crc32(mtod(m, unsigned char *), total_len); if (~crc != *((unsigned *) &bufaddr[total_len])) { - printf("de0: bad rx crc: %08x [rx] != %08x\n", + printf("%s%d: bad rx crc: %08x [rx] != %08x\n", + sc->tulip_name, sc->tulip_unit, *((unsigned *) &bufaddr[total_len]), ~crc); goto next; } #endif eh = *mtod(m, struct ether_header *); #if NBPFILTER > 0 - if (sc->tulip_bpf != NULL) { + if (sc->tulip_bpf != NULL) bpf_tap(sc->tulip_bpf, mtod(m, caddr_t), total_len); - if (sc->tulip_if.if_flags & IFF_PROMISC && - (eh.ether_dhost[0] & 1) == 0 && - !TULIP_ADDREQUAL(eh.ether_dhost, sc->tulip_ac.ac_enaddr)) - goto next; - } #endif + if ((sc->tulip_if.if_flags & IFF_PROMISC) + && (eh.ether_dhost[0] & 1) == 0 + && !TULIP_ADDREQUAL(eh.ether_dhost, sc->tulip_ac.ac_enaddr)) + goto next; accept = 1; + total_len -= sizeof(struct ether_header); } else { ifp->if_ierrors++; } @@ -664,23 +692,36 @@ tulip_rx_intr( struct mbuf *m0; MGETHDR(m0, M_DONTWAIT, MT_DATA); if (m0 != NULL) { - MCLGET(m0, M_DONTWAIT); - if ((m0->m_flags & M_EXT) == 0) { - m_freem(m0); - m0 = NULL; +#if defined(TULIP_COPY_RXDATA) + if (!accept || total_len >= MHLEN) { +#endif + MCLGET(m0, M_DONTWAIT); + if ((m0->m_flags & M_EXT) == 0) { + m_freem(m0); + m0 = NULL; + } +#if defined(TULIP_COPY_RXDATA) } +#endif } if (accept) { if (m0 != NULL) { - m->m_pkthdr.rcvif = ifp; - m->m_data += sizeof(struct ether_header); - m->m_len = m->m_pkthdr.len = total_len - - sizeof(struct ether_header); #if defined(__bsdi__) eh.ether_type = ntohs(eh.ether_type); #endif +#if !defined(TULIP_COPY_RXDATA) + m->m_data += sizeof(struct ether_header); + m->m_len = m->m_pkthdr.len = total_len; + m->m_pkthdr.rcvif = ifp; ether_input(ifp, &eh, m); m = m0; +#else + bcopy(mtod(m, caddr_t) + sizeof(struct ether_header), + mtod(m0, caddr_t), total_len); + m0->m_len = m0->m_pkthdr.len = total_len; + m0->m_pkthdr.rcvif = ifp; + ether_input(ifp, &eh, m0); +#endif } else { ifp->if_ierrors++; } @@ -705,9 +746,9 @@ tulip_rx_intr( static int tulip_tx_intr( - tulip_softc_t *sc) + tulip_softc_t * const sc) { - tulip_ringinfo_t *ri = &sc->tulip_txinfo; + tulip_ringinfo_t * const ri = &sc->tulip_txinfo; struct mbuf *m; int xmits = 0; @@ -729,9 +770,9 @@ tulip_tx_intr( tulip_rx_intr(sc); sc->tulip_cmdmode |= TULIP_CMD_RXRUN; sc->tulip_intrmask |= TULIP_STS_RXSTOPPED; - *sc->tulip_csrs.csr_status = TULIP_STS_RXSTOPPED; - *sc->tulip_csrs.csr_command = sc->tulip_cmdmode; - *sc->tulip_csrs.csr_intr = sc->tulip_intrmask; + TULIP_WRITE_CSR(sc, csr_status, TULIP_STS_RXSTOPPED); + TULIP_WRITE_CSR(sc, csr_command, sc->tulip_cmdmode); + TULIP_WRITE_CSR(sc, csr_intr, sc->tulip_intrmask); } } else { IF_DEQUEUE(&sc->tulip_txq, m); @@ -754,61 +795,23 @@ tulip_tx_intr( return xmits; } -static int -tulip_txsegment( - tulip_softc_t *sc, - struct mbuf *m, - tulip_addrvec_t *avp, - size_t maxseg) -{ - int segcnt; - - for (segcnt = 0; m; m = m->m_next) { - int len = m->m_len; - caddr_t addr = mtod(m, caddr_t); - unsigned clsize = CLBYTES - (((u_long) addr) & (CLBYTES-1)); - - while (len > 0) { - unsigned slen = min(len, clsize); - if (segcnt < maxseg) { - avp->addr = vtophys(addr); - avp->length = slen; - } - len -= slen; - addr += slen; - clsize = CLBYTES; - avp++; - segcnt++; - } - } - if (segcnt >= maxseg) { - printf("%s%d: tulip_txsegment: extremely fragmented packet encountered (%d segments)\n", - sc->tulip_name, sc->tulip_unit, segcnt); - return -1; - } - avp->addr = 0; - avp->length = 0; - return segcnt; -} - static ifnet_ret_t tulip_start( - struct ifnet *ifp) + struct ifnet * const ifp) { - tulip_softc_t *sc = TULIP_UNIT_TO_SOFTC(ifp->if_unit); - struct ifqueue *ifq = &ifp->if_snd; - tulip_ringinfo_t *ri = &sc->tulip_txinfo; - tulip_desc_t *sop, *eop; - struct mbuf *m; - static tulip_addrvec_t addrvec[TULIP_MAX_TXSEG+1]; - tulip_addrvec_t *avp; - int segcnt; - tulip_uint32_t d_status; + tulip_softc_t * const sc = TULIP_UNIT_TO_SOFTC(ifp->if_unit); + struct ifqueue * const ifq = &ifp->if_snd; + tulip_ringinfo_t * const ri = &sc->tulip_txinfo; + struct mbuf *m, *m0; if ((ifp->if_flags & IFF_RUNNING) == 0) return; for (;;) { + tulip_desc_t *eop, *nextout; + int segcnt, free, recopy; + tulip_uint32_t d_status; + if (sc->tulip_flags & TULIP_WANTSETUP) { if ((sc->tulip_flags & TULIP_DOINGSETUP) || ri->ri_free == 1) { ifp->if_flags |= IFF_OACTIVE; @@ -829,28 +832,98 @@ tulip_start( ri->ri_nextout->d_length2 = 0; ri->ri_nextout->d_addr2 = 0; ri->ri_nextout->d_status = TULIP_DSTS_OWNER; - *sc->tulip_csrs.csr_txpoll = 1; + TULIP_WRITE_CSR(sc, csr_txpoll, 1); /* * Advance the ring for the next transmit packet. */ if (++ri->ri_nextout == ri->ri_last) ri->ri_nextout = ri->ri_first; + /* + * Make sure the next descriptor is owned by us since it + * may have been set up above if we ran out of room in the + * ring. + */ + ri->ri_nextout->d_status = 0; } - + IF_DEQUEUE(ifq, m); if (m == NULL) break; /* - * First find out how many and which different pages - * the mbuf data occupies. Then check to see if we - * have enough descriptor space in our transmit ring - * to actually send it. + * Now we try to fill in our transmit descriptors. This is + * a bit reminiscent of going on the Ark two by two + * since each descriptor for the TULIP can describe + * two buffers. So we advance through packet filling + * each of the two entries at a time to to fill each + * descriptor. Clear the first and last segment bits + * in each descriptor (actually just clear everything + * but the end-of-ring or chain bits) to make sure + * we don't get messed up by previously sent packets. + * + * We may fail to put the entire packet on the ring if + * there is either not enough ring entries free or if the + * packet has more than MAX_TXSEG segments. In the former + * case we will just wait for the ring to empty. In the + * latter case we have to recopy. */ - segcnt = tulip_txsegment(sc, m, addrvec, - min(ri->ri_max - 1, TULIP_MAX_TXSEG)); - if (segcnt < 0) { - struct mbuf *m0; + d_status = 0; + recopy = 0; + eop = nextout = ri->ri_nextout; + m0 = m; + segcnt = 0; + free = ri->ri_free; + do { + int len = m0->m_len; + caddr_t addr = mtod(m0, caddr_t); + unsigned clsize = CLBYTES - (((u_long) addr) & (CLBYTES-1)); + + while (len > 0) { + unsigned slen = min(len, clsize); + + segcnt++; + if (segcnt > TULIP_MAX_TXSEG) { + recopy = 1; + m0 = NULL; /* to break out of outside loop */ + break; + } + if (segcnt & 1) { + if (--free == 0) { + /* + * There's no more room but since nothing + * has been committed at this point, just + * show output is active, put back the + * mbuf and return. + */ + ifp->if_flags |= IFF_OACTIVE; + IF_PREPEND(ifq, m); + return; + } + eop = nextout; + if (++nextout == ri->ri_last) + nextout = ri->ri_first; + eop->d_flag &= TULIP_DFLAG_ENDRING|TULIP_DFLAG_CHAIN; + eop->d_status = d_status; + eop->d_addr1 = vtophys(addr); eop->d_length1 = slen; + } else { + /* + * Fill in second half of descriptor + */ + eop->d_addr2 = vtophys(addr); eop->d_length2 = slen; + } + d_status = TULIP_DSTS_OWNER; + len -= slen; + addr += slen; + clsize = CLBYTES; + } + } while ((m0 = m0->m_next) != NULL); + + /* + * The packet exceeds the number of transmit buffer + * entries that we can use for one packet, so we have + * recopy it into one mbuf and then try again. + */ + if (recopy) { MGETHDR(m0, M_DONTWAIT, MT_DATA); if (m0 != NULL) { if (m->m_pkthdr.len > MHLEN) { @@ -863,59 +936,60 @@ tulip_start( } m_copydata(m, 0, m->m_pkthdr.len, mtod(m0, caddr_t)); m0->m_pkthdr.len = m0->m_len = m->m_pkthdr.len; - m_freem(m); IF_PREPEND(ifq, m0); - continue; - } else { - m_freem(m); - continue; } + m_freem(m); + continue; } - if (ri->ri_free - 2 <= (segcnt + 1) >> 1) - break; - ri->ri_free -= (segcnt + 1) >> 1; /* - * Now we fill in our transmit descriptors. This is - * a bit reminiscent of going on the Ark two by two - * since each descriptor for the TULIP can describe - * two buffers. So we advance through the address - * vector two entries at a time to to fill each - * descriptor. Clear the first and last segment bits - * in each descriptor (actually just clear everything - * but the end-of-ring or chain bits) to make sure - * we don't get messed up by previously sent packets. + * The descriptors have been filled in. Now get ready + * to transmit. */ - sop = ri->ri_nextout; - d_status = 0; - avp = addrvec; - do { - eop = ri->ri_nextout; - eop->d_flag &= TULIP_DFLAG_ENDRING|TULIP_DFLAG_CHAIN; - eop->d_status = d_status; - eop->d_addr1 = avp->addr; eop->d_length1 = avp->length; avp++; - eop->d_addr2 = avp->addr; eop->d_length2 = avp->length; avp++; - d_status = TULIP_DSTS_OWNER; - if (++ri->ri_nextout == ri->ri_last) - ri->ri_nextout = ri->ri_first; - } while ((segcnt -= 2) > 0); #if NBPFILTER > 0 - if (sc->tulip_bpf != NULL) - bpf_mtap(sc->tulip_bpf, m); + if (sc->tulip_bpf != NULL) + bpf_mtap(sc->tulip_bpf, m); #endif + IF_ENQUEUE(&sc->tulip_txq, m); + /* - * The descriptors have been filled in. Mark the first - * and last segments, indicate we want a transmit complete - * interrupt, give the descriptors to the TULIP, and tell - * it to transmit! + * Make sure the next descriptor after this packet is owned + * by us since it may have been set up above if we ran out + * of room in the ring. */ + nextout->d_status = 0; - IF_ENQUEUE(&sc->tulip_txq, m); + /* + * If we only used the first segment of the last descriptor, + * make sure the second segment will not be used. + */ + if (segcnt & 1) { + eop->d_addr2 = 0; + eop->d_length2 = 0; + } + + /* + * Mark the last and first segments, indicate we want a transmit + * complete interrupt, give the descriptors to the TULIP, and tell + * it to transmit! + */ eop->d_flag |= TULIP_DFLAG_TxLASTSEG|TULIP_DFLAG_TxWANTINTR; - sop->d_flag |= TULIP_DFLAG_TxFIRSTSEG; - sop->d_status = TULIP_DSTS_OWNER; - *sc->tulip_csrs.csr_txpoll = 1; + /* + * Note that ri->ri_nextout is still the start of the packet + * and until we set the OWNER bit, we can still back out of + * everything we have done. + */ + ri->ri_nextout->d_flag |= TULIP_DFLAG_TxFIRSTSEG; + ri->ri_nextout->d_status = TULIP_DSTS_OWNER; + + /* + * This advances the ring for us. + */ + ri->ri_nextout = nextout; + ri->ri_free = free; + + TULIP_WRITE_CSR(sc, csr_txpoll, 1); } if (m != NULL) { ifp->if_flags |= IFF_OACTIVE; @@ -925,26 +999,27 @@ tulip_start( static int tulip_intr( - tulip_softc_t *sc) + void *arg) { + tulip_softc_t * const sc = (tulip_softc_t *) arg; tulip_uint32_t csr; int progress=0; - while ((csr = *sc->tulip_csrs.csr_status) & (TULIP_STS_NORMALINTR|TULIP_STS_ABNRMLINTR)) { + while ((csr = TULIP_READ_CSR(sc, csr_status)) & (TULIP_STS_NORMALINTR|TULIP_STS_ABNRMLINTR)) { progress = 1; - *sc->tulip_csrs.csr_status = csr & sc->tulip_intrmask; + TULIP_WRITE_CSR(sc, csr_status, csr & sc->tulip_intrmask); if (csr & TULIP_STS_SYSERROR) { if ((csr & TULIP_STS_ERRORMASK) == TULIP_STS_ERR_PARITY) { - TULIP_RESET(sc); - tulip_init(sc->tulip_unit); + tulip_reset(sc); + tulip_init(sc); break; } } if (csr & TULIP_STS_ABNRMLINTR) { printf("%s%d: abnormal interrupt: 0x%05x [0x%05x]\n", sc->tulip_name, sc->tulip_unit, csr, csr & sc->tulip_intrmask); - *sc->tulip_csrs.csr_command = sc->tulip_cmdmode; + TULIP_WRITE_CSR(sc, csr_command, sc->tulip_cmdmode); } if (csr & TULIP_STS_RXINTR) tulip_rx_intr(sc); @@ -960,26 +1035,25 @@ tulip_intr( * */ -void +static void tulip_delay_300ns( - tulip_softc_t *sc) + tulip_softc_t * const sc) { - *sc->tulip_csrs.csr_busmode; *sc->tulip_csrs.csr_busmode; - *sc->tulip_csrs.csr_busmode; *sc->tulip_csrs.csr_busmode; + TULIP_READ_CSR(sc, csr_busmode); TULIP_READ_CSR(sc, csr_busmode); + TULIP_READ_CSR(sc, csr_busmode); TULIP_READ_CSR(sc, csr_busmode); - *sc->tulip_csrs.csr_busmode; *sc->tulip_csrs.csr_busmode; - *sc->tulip_csrs.csr_busmode; *sc->tulip_csrs.csr_busmode; + TULIP_READ_CSR(sc, csr_busmode); TULIP_READ_CSR(sc, csr_busmode); + TULIP_READ_CSR(sc, csr_busmode); TULIP_READ_CSR(sc, csr_busmode); - *sc->tulip_csrs.csr_busmode; *sc->tulip_csrs.csr_busmode; - *sc->tulip_csrs.csr_busmode; *sc->tulip_csrs.csr_busmode; + TULIP_READ_CSR(sc, csr_busmode); TULIP_READ_CSR(sc, csr_busmode); + TULIP_READ_CSR(sc, csr_busmode); TULIP_READ_CSR(sc, csr_busmode); } -#define EMIT do { *sc->tulip_csrs.csr_srom_mii = csr; tulip_delay_300ns(sc); } while (0) +#define EMIT do { TULIP_WRITE_CSR(sc, csr_srom_mii, csr); tulip_delay_300ns(sc); } while (0) - -void +static void tulip_idle_srom( - tulip_softc_t *sc) + tulip_softc_t * const sc) { unsigned bit, csr; @@ -1000,9 +1074,9 @@ tulip_idle_srom( } -void +static void tulip_read_srom( - tulip_softc_t *sc) + tulip_softc_t * const sc) { int idx; const unsigned bitwidth = SROM_BITWIDTH; @@ -1033,7 +1107,7 @@ tulip_read_srom( for (data = 0, bits = 0; bits < 16; bits++) { data <<= 1; csr ^= SROMCLKON; EMIT; /* clock high; data valid */ - data |= *sc->tulip_csrs.csr_srom_mii & SROMDIN ? 1 : 0; + data |= TULIP_READ_CSR(sc, csr_srom_mii) & SROMDIN ? 1 : 0; csr ^= SROMCLKOFF; EMIT; /* clock low; data not valid */ } sc->tulip_rombuf[idx*2] = data & 0xFF; @@ -1043,7 +1117,7 @@ tulip_read_srom( } } -#define tulip_mchash(mca) ((tulip_crc32(mca, 6) >> 23) & 0x1FF) +#define tulip_mchash(mca) (tulip_crc32(mca, 6) & 0x1FF) #define tulip_srom_crcok(databuf) ( \ (tulip_crc32(databuf, 126) & 0xFFFF) == \ ((databuf)[126] | ((databuf)[127] << 8))) @@ -1072,14 +1146,14 @@ tulip_read_macaddr( int cksum, rom_cksum, idx; tulip_sint32_t csr; unsigned char tmpbuf[8]; - static u_char testpat[] = { 0xFF, 0, 0x55, 0xAA, 0xFF, 0, 0x55, 0xAA }; + static const u_char testpat[] = { 0xFF, 0, 0x55, 0xAA, 0xFF, 0, 0x55, 0xAA }; if (sc->tulip_chipid == TULIP_DC21040) { - *sc->tulip_csrs.csr_enetrom = 1; + TULIP_WRITE_CSR(sc, csr_enetrom, 1); sc->tulip_boardsw = &tulip_dc21040_boardsw; for (idx = 0; idx < 32; idx++) { int cnt = 0; - while ((csr = *sc->tulip_csrs.csr_enetrom) < 0 && cnt < 10000) + while ((csr = TULIP_READ_CSR(sc, csr_enetrom)) < 0 && cnt < 10000) cnt++; sc->tulip_rombuf[idx] = csr & 0xFF; } @@ -1171,7 +1245,7 @@ tulip_read_macaddr( static void tulip_addr_filter( - tulip_softc_t *sc) + tulip_softc_t * const sc) { tulip_uint32_t *sp = sc->tulip_setupdata; struct ether_multistep step; @@ -1199,7 +1273,7 @@ tulip_addr_filter( sp[hash >> 4] |= 1 << (hash & 0xF); ETHER_NEXT_MULTI(step, enm); } - sc->tulip_cmdmode |= TULIP_WANTHASH; + sc->tulip_flags |= TULIP_WANTHASH; sp[39] = ((u_short *) sc->tulip_ac.ac_enaddr)[0]; sp[40] = ((u_short *) sc->tulip_ac.ac_enaddr)[1]; sp[41] = ((u_short *) sc->tulip_ac.ac_enaddr)[2]; @@ -1239,11 +1313,11 @@ tulip_addr_filter( static int tulip_ioctl( - struct ifnet *ifp, - int cmd, + struct ifnet * const ifp, + ioctl_cmd_t cmd, caddr_t data) { - tulip_softc_t *sc = TULIP_UNIT_TO_SOFTC(ifp->if_unit); + tulip_softc_t * const sc = TULIP_UNIT_TO_SOFTC(ifp->if_unit); struct ifaddr *ifa = (struct ifaddr *)data; struct ifreq *ifr = (struct ifreq *) data; int s, error = 0; @@ -1259,17 +1333,19 @@ tulip_ioctl( case AF_INET: { ((struct arpcom *)ifp)->ac_ipaddr = IA_SIN(ifa)->sin_addr; tulip_addr_filter(sc); /* reset multicast filtering */ - (*ifp->if_init)(ifp->if_unit); -#if defined(__FreeBSD__) + tulip_init(sc); +#if defined(__FreeBSD__) || defined(__NetBSD__) arp_ifinit((struct arpcom *)ifp, ifa); -#endif +#elif defined(__bsdi__) arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); +#endif break; } #endif /* INET */ #ifdef NS - /* This magic copied from if_is.c; I don't use XNS, + /* + * This magic copied from if_is.c; I don't use XNS, * so I have no way of telling if this actually * works or not. */ @@ -1284,13 +1360,13 @@ tulip_ioctl( sizeof sc->tulip_ac.ac_enaddr); } - (*ifp->if_init)(ifp->if_unit); + tulip_init(sc); break; } #endif /* NS */ default: { - (*ifp->if_init)(ifp->if_unit); + tulip_init(sc); break; } } @@ -1303,12 +1379,12 @@ tulip_ioctl( */ if (sc->tulip_flags & TULIP_ALTPHYS) { if ((ifp->if_flags & IFF_ALTPHYS) == 0) - TULIP_RESET(sc); + tulip_reset(sc); } else { if (ifp->if_flags & IFF_ALTPHYS) - TULIP_RESET(sc); + tulip_reset(sc); } - (*ifp->if_init)(ifp->if_unit); + tulip_init(sc); break; } @@ -1324,12 +1400,15 @@ tulip_ioctl( if (error == ENETRESET) { tulip_addr_filter(sc); /* reset multicast filtering */ - (*ifp->if_init)(ifp->if_unit); + tulip_init(sc); error = 0; } break; } #if defined(SIOCSIFMTU) +#if !defined(ifr_mtu) +#define ifr_mtu ifr_metric +#endif case SIOCSIFMTU: /* * Set the interface MTU. @@ -1354,17 +1433,16 @@ tulip_ioctl( static void tulip_attach( - tulip_softc_t *sc) + tulip_softc_t * const sc) { - struct ifnet *ifp = &sc->tulip_if; + struct ifnet * const ifp = &sc->tulip_if; ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_NOTRAILERS|IFF_MULTICAST; - ifp->if_init = tulip_init; ifp->if_ioctl = tulip_ioctl; ifp->if_output = ether_output; ifp->if_start = tulip_start; -#ifndef __bsdi__ +#ifdef __FreeBSD__ printf("%s%d", sc->tulip_name, sc->tulip_unit); #endif printf(": %s%s pass %d.%d Ethernet address %s\n", @@ -1380,9 +1458,12 @@ tulip_attach( sc->tulip_flags |= TULIP_ALTPHYS; } - TULIP_RESET(sc); + tulip_reset(sc); if_attach(ifp); +#if defined(__NetBSD__) + ether_ifattach(ifp); +#endif #if NBPFILTER > 0 bpfattach(&sc->tulip_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); @@ -1391,7 +1472,7 @@ tulip_attach( static void tulip_initcsrs( - tulip_softc_t *sc, + tulip_softc_t * const sc, volatile tulip_uint32_t *va_csrs, size_t csr_size) { @@ -1422,8 +1503,8 @@ tulip_initcsrs( static void tulip_initring( - tulip_softc_t *sc, - tulip_ringinfo_t *ri, + tulip_softc_t * const sc, + tulip_ringinfo_t * const ri, tulip_desc_t *descs, int ndescs) { @@ -1449,7 +1530,13 @@ tulip_initring( #define PCI_CFIT 0x3c /* Configuration Interrupt */ #define PCI_CFDA 0x40 /* Configuration Driver Area */ +#if defined(__alpha__) +#define TULIP_PCI_CSRSIZE (256 / sizeof(tulip_uint32_t)) +#define TULIP_PCI_CSROFFSET (24 / sizeof(tulip_uint32_t)) +#elif defined(__i386__) #define TULIP_PCI_CSRSIZE (8 / sizeof(tulip_uint32_t)) +#define TULIP_PCI_CSROFFSET 0 +#endif #if defined(__FreeBSD__) @@ -1457,12 +1544,12 @@ tulip_initring( static int tulip_pci_shutdown( - struct kern_devconf *kdc, + struct kern_devconf * const kdc, int force) { if (kdc->kdc_unit < NDE) { - tulip_softc_t *sc = TULIP_UNIT_TO_SOFTC(kdc->kdc_unit); - *sc->tulip_csrs.csr_busmode = TULIP_BUSMODE_SWRESET; + tulip_softc_t * const sc = TULIP_UNIT_TO_SOFTC(kdc->kdc_unit); + TULIP_WRITE_CSR(sc, csr_busmode, TULIP_BUSMODE_SWRESET); DELAY(10); /* Wait 10 microsends (actually 50 PCI cycles but at 33MHz that comes to two microseconds but wait a bit longer anyways) */ @@ -1506,8 +1593,8 @@ static void tulip_pci_shutdown( void *arg) { - tulip_softc_t *sc = (tulip_softc_t *) arg; - *sc->tulip_csrs.csr_busmode = TULIP_BUSMODE_SWRESET; + tulip_softc_t * const sc = (tulip_softc_t *) arg; + TULIP_WRITE_CSR(sc, csr_busmode, TULIP_BUSMODE_SWRESET); DELAY(10); /* Wait 10 microsends (actually 50 PCI cycles but at 33MHz that comes to two microseconds but wait a bit longer anyways) */ @@ -1533,13 +1620,13 @@ tulip_pci_match( return 1; } -int +static int tulip_pci_probe( struct device *parent, struct cfdata *cf, void *aux) { - struct isa_attach_args *ia = (struct isa_attach_args *) aux; + struct isa_attach_args * const ia = (struct isa_attach_args *) aux; unsigned irq; pci_devaddr_t *pa; @@ -1586,7 +1673,47 @@ struct cfdriver decd = { }; #endif /* __bsdi__ */ + +#if defined(__NetBSD__) +#define TULIP_PCI_ATTACH_ARGS struct device *parent, struct device *self, void *aux + +#if 0 /* XXX! */ +static void +tulip_pci_shutdown( + void *arg) +{ + tulip_softc_t * const sc = (tulip_softc_t *) arg; + TULIP_WRITE_CSR(sc, csr_busmode, TULIP_BUSMODE_SWRESET); + DELAY(10); /* Wait 10 microsends (actually 50 PCI cycles but at + 33MHz that comes to two microseconds but wait a + bit longer anyways) */ +} +#endif + +static int +tulip_pci_probe( + struct device *parent, + void *match, + void *aux) +{ + struct pci_attach_args *pa = (struct pci_attach_args *) aux; + + if (pa->pa_id == 0x00021011ul + || pa->pa_id == 0x00141011ul + || pa->pa_id == 0x00091011ul) + return 1; + return 0; +} + +static void tulip_pci_attach(TULIP_PCI_ATTACH_ARGS); + +struct cfdriver decd = { + 0, "de", tulip_pci_probe, tulip_pci_attach, DV_IFNET, sizeof(tulip_softc_t) +}; + +#endif /* __NetBSD__ */ + static void tulip_pci_attach( TULIP_PCI_ATTACH_ARGS) @@ -1595,11 +1722,16 @@ tulip_pci_attach( tulip_softc_t *sc; #endif #if defined(__bsdi__) - tulip_softc_t *sc = (tulip_softc_t *) self; - struct isa_attach_args *ia = (struct isa_attach_args *) aux; + tulip_softc_t * const sc = (tulip_softc_t *) self; + struct isa_attach_args * const ia = (struct isa_attach_args *) aux; pci_devaddr_t *pa = (pci_devaddr_t *) ia->ia_aux; int unit = sc->tulip_dev.dv_unit; #endif +#if defined(__NetBSD__) + tulip_softc_t * const sc = (tulip_softc_t *) self; + struct pci_attach_args * const pa = (struct pci_attach_args *) aux; + int unit = sc->tulip_dev.dv_unit; +#endif int retval, idx, revinfo, id; vm_offset_t va_csrs, pa_csrs; tulip_desc_t *rxdescs, *txdescs; @@ -1621,6 +1753,10 @@ tulip_pci_attach( revinfo = pci_inl(pa, PCI_CFRV) & 0xFF; id = pci_inl(pa, PCI_CFID); #endif +#if defined(__NetBSD__) + revinfo = pci_conf_read(pa->pa_tag, PCI_CFRV) & 0xFF; + id = pa->pa_id; +#endif if (id == 0x00021011ul) chipid = TULIP_DC21040; else if (id == 0x00091011) chipid = TULIP_DC21140; @@ -1628,12 +1764,18 @@ tulip_pci_attach( else return; if (chipid == TULIP_DC21040 && revinfo < 0x20) { - printf("de%d: not configured; DC21040 pass 2.3 required (%d.%d found)\n", - unit, revinfo >> 4, revinfo & 0x0f); +#ifdef __FreeBSD__ + printf("de%d", unit); +#endif + printf(": not configured; DC21040 pass 2.0 required (%d.%d found)\n", + revinfo >> 4, revinfo & 0x0f); return; } else if (chipid == TULIP_DC21140 && revinfo < 0x11) { - printf("de%d: not configured; DC21140 pass 1.1 required (%d.%d found)\n", - unit, revinfo >> 4, revinfo & 0x0f); +#ifdef __FreeBSD__ + printf("de%d", unit); +#endif + printf(": not configured; DC21140 pass 1.1 required (%d.%d found)\n", + revinfo >> 4, revinfo & 0x0f); return; } @@ -1679,12 +1821,23 @@ tulip_pci_attach( #if defined(__bsdi__) va_csrs = (vm_offset_t) mapphys((vm_offset_t) ia->ia_maddr, ia->ia_msize); #endif +#if defined(__NetBSD__) + if (pci_map_mem(pa->pa_tag, PCI_CBMA, &va_csrs, &pa_csrs)) { + free((caddr_t) txdescs, M_DEVBUF); + free((caddr_t) rxdescs, M_DEVBUF); + return; + } +#endif sc->tulip_revinfo = revinfo; - tulip_initcsrs(sc, (volatile tulip_uint32_t *) va_csrs, TULIP_PCI_CSRSIZE); + tulip_initcsrs(sc, ((volatile tulip_uint32_t *) va_csrs) + TULIP_PCI_CSROFFSET, + TULIP_PCI_CSRSIZE); tulip_initring(sc, &sc->tulip_rxinfo, rxdescs, TULIP_RXDESCS); tulip_initring(sc, &sc->tulip_txinfo, txdescs, TULIP_TXDESCS); if ((retval = tulip_read_macaddr(sc)) < 0) { - printf("de%d: can't read ENET ROM (why=%d) (", sc->tulip_unit, retval); +#ifdef __FreeBSD__ + printf("%s%d", sc->tulip_name, sc->tulip_unit); +#endif + printf(": can't read ENET ROM (why=%d) (", retval); for (idx = 0; idx < 32; idx++) printf("%02x", sc->tulip_rombuf[idx]); printf("\n"); @@ -1695,8 +1848,16 @@ tulip_pci_attach( (sc->tulip_revinfo & 0xF0) >> 4, sc->tulip_revinfo & 0x0F, "unknown"); } else { - TULIP_RESET(sc); + tulip_reset(sc); tulip_attach(sc); +#if defined(__NetBSD__) + sc->tulip_ih = pci_map_int(pa->pa_tag, PCI_IPL_NET, tulip_intr, sc); + if (sc->tulip_ih == NULL) { + printf("%s%d: couldn't map interrupt\n", + sc->tulip_name, sc->tulip_unit); + return; + } +#endif #if defined(__FreeBSD__) pci_map_int (config_id, tulip_intr, (void*) sc, &net_imask); #endif |