diff options
-rw-r--r-- | sys/dev/de/if_de.c | 412 | ||||
-rw-r--r-- | sys/pci/dc21040.h | 18 | ||||
-rw-r--r-- | sys/pci/if_de.c | 412 |
3 files changed, 640 insertions, 202 deletions
diff --git a/sys/dev/de/if_de.c b/sys/dev/de/if_de.c index 64b1095..0c84b65 100644 --- a/sys/dev/de/if_de.c +++ b/sys/dev/de/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.22 1995/04/17 08:16:14 davidg Exp $ + * $Id: if_de.c,v 1.12 1995/05/05 19:44:06 thomas Exp $ * */ @@ -32,12 +32,14 @@ * BPF support code stolen directly from if_ec.c * * This driver supports the DEC DE435 or any other PCI - * board which support DC21040. + * board which support DC21040 or DC21140 (mostly). */ #define __IF_DE_C__ "pl2 95/03/21" +#ifndef __bsdi__ #include "de.h" -#if NDE > 0 +#endif +#if NDE > 0 || defined(__bsdi__) #include <sys/param.h> #include <sys/systm.h> @@ -49,8 +51,13 @@ #include <sys/malloc.h> #include <sys/kernel.h> #include <sys/proc.h> /* only for declaration of wakeup() used by vm.h */ +#if defined(__FreeBSD__) #include <sys/devconf.h> #include <machine/clock.h> +#endif +#if defined(__bsdi__) +#include <sys/device.h> +#endif #include <net/if.h> #include <net/if_types.h> @@ -80,13 +87,22 @@ #include <vm/vm_kern.h> #include <vm/vm_param.h> - +#if defined(__FreeBSD__) #include <pci.h> #if NPCI > 0 #include <pci/pcivar.h> +#include <pci/dc21040.h> +#endif #endif -#include <pci/dc21040.h> +#if defined(__bsdi__) +#include <i386/pci/pci.h> +#include <i386/pci/dc21040.h> +#include <i386/isa/isa.h> +#include <i386/isa/icu.h> +#include <i386/isa/dma.h> +#include <i386/isa/isavar.h> +#endif /* * This module supports @@ -168,7 +184,8 @@ typedef struct { typedef enum { TULIP_DC21040_GENERIC, TULIP_DC21140_DEC_EB, - TULIP_DC21140_DEC_DE500 + TULIP_DC21140_DEC_DE500, + TULIP_DC21140_COGENT_EM100 } tulip_board_t; typedef struct _tulip_softc_t tulip_softc_t; @@ -180,8 +197,15 @@ typedef struct { void (*bd_media_select)(tulip_softc_t *sc); } tulip_boardsw_t; +typedef enum { TULIP_DC21040, TULIP_DC21140, TULIP_DC21041 } tulip_chipid_t; struct _tulip_softc_t { +#if defined(__bsdi__) + struct device tulip_dev; /* base device */ + struct isadev tulip_id; /* ISA device */ + struct intrhand tulip_ih; /* intrrupt vectoring */ + struct atshutdown tulip_ats; /* shutdown routine */ +#endif struct arpcom tulip_ac; tulip_regfile_t tulip_csrs; unsigned tulip_flags; @@ -195,8 +219,9 @@ struct _tulip_softc_t { tulip_uint32_t tulip_intrmask; tulip_uint32_t tulip_cmdmode; tulip_uint32_t tulip_revinfo; + tulip_chipid_t tulip_chipid; const tulip_boardsw_t *tulip_boardsw; -#if NBPFILTER > 0 +#if NBPFILTER > 0 && !defined(__bsdi__) && !defined(__FreeBSD__) caddr_t tulip_bpf; /* BPF context */ #endif struct ifqueue tulip_txq; @@ -206,17 +231,26 @@ struct _tulip_softc_t { }; #ifndef IFF_ALTPHYS -#define IFF_ALTPHYS IFF_LINK2 /* In case it isn't defined */ +#define IFF_ALTPHYS IFF_LINK0 /* In case it isn't defined */ #endif -typedef enum { TULIP_DC21040, TULIP_DC21140, TULIP_DC21041 } tulip_chipid_t; const char *tulip_chipdescs[] = { "DC21040 [10Mb/s]", "DC21140 [10-100Mb/s]", "DC21041 [10Mb/s]" }; +#if defined(__FreeBSD__) +typedef void ifnet_ret_t; tulip_softc_t *tulips[NDE]; -tulip_chipid_t tulip_chipids[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; +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 @@ -236,11 +270,11 @@ tulip_chipid_t tulip_chipids[NDE]; && ((u_short *)a1)[1] == 0xFFFFU \ && ((u_short *)a1)[2] == 0xFFFFU) -static void tulip_start(struct ifnet *ifp); +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 +#if __FreeBSD__ > 1 || defined(__bsdi__) #define TULIP_IFRESET_ARGS int unit #define TULIP_RESET(sc) tulip_reset((sc)->tulip_unit) #else @@ -339,20 +373,57 @@ static const tulip_boardsw_t tulip_dc21140_eb_boardsw = { tulip_dc21140_evalboard_media_select }; + +static int +tulip_dc21140_cogent_em100_media_probe( + tulip_softc_t *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; + return 1; +} + +static void +tulip_dc21140_cogent_em100_media_select( + tulip_softc_t *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; + 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); + sc->tulip_cmdmode |= TULIP_CMD_PORTSELECT + |TULIP_CMD_PCSFUNCTION|TULIP_CMD_SCRAMBLER; + sc->tulip_cmdmode &= ~TULIP_CMD_TXTHRSHLDCTL; + sc->tulip_flags |= TULIP_ALTPHYS; +} + +static const tulip_boardsw_t tulip_dc21140_cogent_em100_boardsw = { + TULIP_DC21140_COGENT_EM100, + "Cogent EM100", + tulip_dc21140_cogent_em100_media_probe, + tulip_dc21140_cogent_em100_media_select +}; + static int tulip_dc21140_de500_media_probe( tulip_softc_t *sc) { *sc->tulip_csrs.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; + 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; DELAY(1000000); - return (*sc->tulip_csrs.csr_gp & TULIP_GP_DE500_NOTOK_100) == 0; + return (*sc->tulip_csrs.csr_gp & TULIP_GP_DE500_NOTOK_100) != 0; } static void @@ -389,11 +460,11 @@ static const tulip_boardsw_t tulip_dc21140_de500_boardsw = { tulip_dc21140_de500_media_select }; -static void +static ifnet_ret_t tulip_reset( TULIP_IFRESET_ARGS) { - tulip_softc_t *sc = tulips[unit]; + tulip_softc_t *sc = TULIP_UNIT_TO_SOFTC(unit); tulip_ringinfo_t *ri; tulip_desc_t *di; @@ -460,11 +531,11 @@ tulip_reset( tulip_addr_filter(sc); } -static void +static ifnet_ret_t tulip_init( int unit) { - tulip_softc_t *sc = tulips[unit]; + tulip_softc_t *sc = TULIP_UNIT_TO_SOFTC(unit); if (sc->tulip_if.if_flags & IFF_UP) { sc->tulip_if.if_flags |= IFF_RUNNING; @@ -606,6 +677,9 @@ tulip_rx_intr( m->m_pkthdr.rcvif = ifp; m->m_data += sizeof(struct ether_header); m->m_len = m->m_pkthdr.len = total_len; +#if defined(__bsdi__) + eh.ether_type = ntohs(eh.ether_type); +#endif ether_input(ifp, &eh, m); m = m0; } else { @@ -718,11 +792,11 @@ tulip_txsegment( return segcnt; } -static void +static ifnet_ret_t tulip_start( struct ifnet *ifp) { - tulip_softc_t *sc = (tulip_softc_t *) 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; @@ -783,10 +857,11 @@ tulip_start( MCLGET(m0, M_DONTWAIT); if ((m0->m_flags & M_EXT) == 0) { m_freem(m); + m_freem(m0); continue; } } - m_copydata(m, 0, m0->m_pkthdr.len, mtod(m0, caddr_t)); + 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); @@ -1000,7 +1075,7 @@ tulip_read_macaddr( unsigned char tmpbuf[8]; static u_char testpat[] = { 0xFF, 0, 0x55, 0xAA, 0xFF, 0, 0x55, 0xAA }; - if (tulip_chipids[sc->tulip_unit] == TULIP_DC21040) { + if (sc->tulip_chipid == TULIP_DC21040) { *sc->tulip_csrs.csr_enetrom = 1; sc->tulip_boardsw = &tulip_dc21040_boardsw; for (idx = 0; idx < 32; idx++) { @@ -1014,7 +1089,7 @@ tulip_read_macaddr( * Assume all DC21140 board are compatible with the * DEC 10/100 evaluation board. Not really valid but ... */ - if (tulip_chipids[sc->tulip_unit] == TULIP_DC21140) + if (sc->tulip_chipid == TULIP_DC21140) sc->tulip_boardsw = &tulip_dc21140_eb_boardsw; tulip_read_srom(sc); if (tulip_srom_crcok(sc->tulip_rombuf)) { @@ -1082,6 +1157,16 @@ tulip_read_macaddr( if (cksum != rom_cksum) return -1; + + if (sc->tulip_chipid == TULIP_DC21140) { + if (sc->tulip_hwaddr[0] == TULIP_OUI_COGENT_0 + && sc->tulip_hwaddr[1] == TULIP_OUI_COGENT_1 + && sc->tulip_hwaddr[2] == TULIP_OUI_COGENT_2) { + if (sc->tulip_rombuf[32] == TULIP_COGENT_EM100_ID) + sc->tulip_boardsw = &tulip_dc21140_cogent_em100_boardsw; + } + } + return 0; } @@ -1159,7 +1244,7 @@ tulip_ioctl( int cmd, caddr_t data) { - tulip_softc_t *sc = tulips[ifp->if_unit]; + tulip_softc_t *sc = TULIP_UNIT_TO_SOFTC(ifp->if_unit); struct ifaddr *ifa = (struct ifaddr *)data; struct ifreq *ifr = (struct ifreq *) data; int s, error = 0; @@ -1176,7 +1261,10 @@ tulip_ioctl( ((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__) arp_ifinit((struct arpcom *)ifp, ifa); +#endif + arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); break; } #endif /* INET */ @@ -1242,6 +1330,7 @@ tulip_ioctl( } break; } +#if defined(SIOCSIFMTU) case SIOCSIFMTU: /* * Set the interface MTU. @@ -1252,6 +1341,7 @@ tulip_ioctl( ifp->if_mtu = ifr->ifr_mtu; } break; +#endif default: { error = EINVAL; @@ -1269,29 +1359,30 @@ tulip_attach( { struct ifnet *ifp = &sc->tulip_if; - if ((*sc->tulip_boardsw->bd_media_probe)(sc)) { - ifp->if_flags |= IFF_ALTPHYS; - } else { - sc->tulip_flags |= TULIP_ALTPHYS; - } - - TULIP_RESET(sc); - 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_reset = tulip_reset; ifp->if_start = tulip_start; - printf("%s%d: %s%s pass %d.%d Ethernet address %s\n", - sc->tulip_name, sc->tulip_unit, +#ifndef __bsdi__ + printf("%s%d", sc->tulip_name, sc->tulip_unit); +#endif + printf(": %s%s pass %d.%d Ethernet address %s\n", sc->tulip_boardsw->bd_description, - tulip_chipdescs[tulip_chipids[sc->tulip_unit]], + tulip_chipdescs[sc->tulip_chipid], (sc->tulip_revinfo & 0xF0) >> 4, sc->tulip_revinfo & 0x0F, ether_sprintf(sc->tulip_hwaddr)); + if ((*sc->tulip_boardsw->bd_media_probe)(sc)) { + ifp->if_flags |= IFF_ALTPHYS; + } else { + sc->tulip_flags |= TULIP_ALTPHYS; + } + + TULIP_RESET(sc); + if_attach(ifp); #if NBPFILTER > 0 @@ -1314,20 +1405,16 @@ tulip_initcsrs( sc->tulip_csrs.csr_command = va_csrs + 6 * csr_size; sc->tulip_csrs.csr_intr = va_csrs + 7 * csr_size; sc->tulip_csrs.csr_missed_frame = va_csrs + 8 * csr_size; - if (tulip_chipids[sc->tulip_unit] == TULIP_DC21040) { - sc->tulip_csrs.csr_enetrom = va_csrs + 9 * csr_size; + if (sc->tulip_chipid == TULIP_DC21040) { + sc->tulip_csrs.csr_enetrom = (tulip_sint32_t *) va_csrs + 9 * csr_size; sc->tulip_csrs.csr_reserved = va_csrs + 10 * csr_size; sc->tulip_csrs.csr_full_duplex = va_csrs + 11 * csr_size; sc->tulip_csrs.csr_sia_status = va_csrs + 12 * csr_size; sc->tulip_csrs.csr_sia_connectivity = va_csrs + 13 * csr_size; sc->tulip_csrs.csr_sia_tx_rx = va_csrs + 14 * csr_size; sc->tulip_csrs.csr_sia_general = va_csrs + 15 * csr_size; - } else if (tulip_chipids[sc->tulip_unit] == TULIP_DC21140) { - if (sc->tulip_revinfo < 0x10) - sc->tulip_csrs.csr_enetrom = va_csrs + 9 * csr_size; - else - sc->tulip_csrs.csr_srom_mii = va_csrs + 9 * csr_size; - + } else if (sc->tulip_chipid == TULIP_DC21140 || sc->tulip_chipid == TULIP_DC21041) { + sc->tulip_csrs.csr_srom_mii = va_csrs + 9 * csr_size; sc->tulip_csrs.csr_gp_timer = va_csrs + 11 * csr_size; sc->tulip_csrs.csr_gp = va_csrs + 12 * csr_size; sc->tulip_csrs.csr_watchdog = va_csrs + 15 * csr_size; @@ -1348,26 +1435,11 @@ tulip_initring( ri->ri_last[-1].d_flag = TULIP_DFLAG_ENDRING; } -#if NPCI > 0 /* * This is the PCI configuration support. Since the DC21040 is available * on both EISA and PCI boards, one must be careful in how defines the * DC21040 in the config file. */ -static char* tulip_pci_probe (pcici_t config_id, pcidi_t device_id); -static void tulip_pci_attach(pcici_t config_id, int unit); -static u_long tulip_pci_count; -static int tulip_pci_shutdown(struct kern_devconf *, int); - -struct pci_device dedevice = { - "de", - tulip_pci_probe, - tulip_pci_attach, - &tulip_pci_count, - tulip_pci_shutdown, -}; - -DATA_SET (pcidevice_set, dedevice); #define PCI_CFID 0x00 /* Configuration ID */ #define PCI_CFCS 0x04 /* Configurtion Command/Status */ @@ -1379,65 +1451,206 @@ DATA_SET (pcidevice_set, dedevice); #define PCI_CFDA 0x40 /* Configuration Driver Area */ #define TULIP_PCI_CSRSIZE (8 / sizeof(tulip_uint32_t)) + +#if defined(__FreeBSD__) + +#define TULIP_PCI_ATTACH_ARGS pcici_t config_id, int unit + +static int +tulip_pci_shutdown( + struct kern_devconf *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; + DELAY(10); /* Wait 10 microsends (actually 50 PCI cycles but at + 33MHz that comes to two microseconds but wait a + bit longer anyways) */ + } + (void) dev_detach(kdc); + return 0; +} + static char* tulip_pci_probe( pcici_t config_id, pcidi_t device_id) { - if (device_id == 0x00021011ul) { - if (tulip_pci_count < NDE) - tulip_chipids[tulip_pci_count] = TULIP_DC21040; + if (device_id == 0x00021011ul) return "Digital DC21040 Ethernet"; - } - if (device_id == 0x00141011ul) { - if (tulip_pci_count < NDE) - tulip_chipids[tulip_pci_count] = TULIP_DC21041; + if (device_id == 0x00141011ul) return "Digital DC21041 Ethernet"; - } - if (device_id == 0x00091011ul) { - if (tulip_pci_count < NDE) - tulip_chipids[tulip_pci_count] = TULIP_DC21140; + if (device_id == 0x00091011ul) return "Digital DC21140 Fast Ethernet"; - } return NULL; } +static void tulip_pci_attach(TULIP_PCI_ATTACH_ARGS); +static u_long tulip_pci_count; + +struct pci_device dedevice = { + "de", + tulip_pci_probe, + tulip_pci_attach, + &tulip_pci_count, + tulip_pci_shutdown, +}; + +DATA_SET (pcidevice_set, dedevice); +#endif /* __FreeBSD__ */ + +#if defined(__bsdi__) +#define TULIP_PCI_ATTACH_ARGS struct device *parent, struct device *self, void *aux + +static void +tulip_pci_shutdown( + void *arg) +{ + tulip_softc_t *sc = (tulip_softc_t *) arg; + *sc->tulip_csrs.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) */ +} + +static int +tulip_pci_match( + pci_devaddr_t *pa) +{ + int irq; + unsigned id; + + id = pci_inl(pa, PCI_VENDOR_ID); + if ((id & 0xFFFF) != 0x1011) + return 0; + id >>= 16; + if (id != 2 && id != 9 && id != 0x14) + return 0; + irq = pci_inl(pa, PCI_I_PIN) & 0xFF; + if (irq == 0 || irq >= 16) + return 0; + + return 1; +} + +int +tulip_pci_probe( + struct device *parent, + struct cfdata *cf, + void *aux) +{ + struct isa_attach_args *ia = (struct isa_attach_args *) aux; + unsigned irq; + pci_devaddr_t *pa; + + pa = pci_scan(tulip_pci_match); + if (pa == NULL) + return 0; + + irq = (1 << (pci_inl(pa, PCI_I_PIN) & 0xFF)); + + if (ia->ia_irq != IRQUNK && irq != ia->ia_irq) { + printf("fpa%d: error: desired IRQ of %d does not match device's actual IRQ of %d,\n", + cf->cf_unit, + ffs(ia->ia_irq) - 1, ffs(irq) - 1); + return 0; + } + if (ia->ia_irq == IRQUNK) { + if ((irq = isa_irqalloc(irq)) == 0) + return 0; + ia->ia_irq = irq; + } + + /* PCI bus masters don't use host DMA channels */ + ia->ia_drq = DRQNONE; + + /* Get the memory base address; assume the BIOS set it up correctly */ + ia->ia_maddr = (caddr_t) (pci_inl(pa, PCI_CBMA) & ~7); + pci_outl(pa, PCI_CBMA, 0xFFFFFFFF); + ia->ia_msize = ((~pci_inl(pa, PCI_CBMA)) | 7) + 1; + pci_outl(pa, PCI_CBMA, (int) ia->ia_maddr); + + /* Disable I/O space access */ + pci_outl(pa, PCI_COMMAND, pci_inl(pa, PCI_COMMAND) & ~1); + ia->ia_iobase = 0; + ia->ia_iosize = 0; + + ia->ia_aux = (void *) pa; + return 1; +} + +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 /* __bsdi__ */ + static void tulip_pci_attach( - pcici_t config_id, - int unit) + TULIP_PCI_ATTACH_ARGS) { +#if defined(__FreeBSD__) tulip_softc_t *sc; - int retval, idx, revinfo; +#endif +#if defined(__bsdi__) + tulip_softc_t *sc = (tulip_softc_t *) self; + struct isa_attach_args *ia = (struct isa_attach_args *) aux; + pci_devaddr_t *pa = (pci_devaddr_t *) ia->ia_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; + tulip_chipid_t chipid; +#if defined(__FreeBSD__) if (unit >= NDE) { printf("de%d: not configured; kernel is built for only %d device%s.\n", unit, NDE, NDE == 1 ? "" : "s"); return; } +#endif +#if defined(__FreeBSD__) revinfo = pci_conf_read(config_id, PCI_CFRV) & 0xFF; - if (tulip_chipids[unit] == TULIP_DC21040 && revinfo < 0x20) { - printf("de%d: not configured; DC21040 pass 2.0 required (%d.%d found)\n", + id = pci_conf_read(config_id, PCI_CFID); +#endif +#if defined(__bsdi__) + revinfo = pci_inl(pa, PCI_CFRV) & 0xFF; + id = pci_inl(pa, PCI_CFID); +#endif + + if (id == 0x00021011ul) chipid = TULIP_DC21040; + else if (id == 0x00091011) chipid = TULIP_DC21140; + else if (id == 0x00141011) chipid = TULIP_DC21041; + 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); return; - } else if (tulip_chipids[unit] == TULIP_DC21140 && revinfo < 0x11) { + } 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); return; } - +#if defined(__FreeBSD__) sc = (tulip_softc_t *) malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT); if (sc == NULL) return; + bzero(sc, sizeof(*sc)); /* Zero out the softc*/ +#endif rxdescs = (tulip_desc_t *) malloc(sizeof(tulip_desc_t) * TULIP_RXDESCS, M_DEVBUF, M_NOWAIT); if (rxdescs == NULL) { +#if defined(__FreeBSD__) free((caddr_t) sc, M_DEVBUF); +#endif return; } @@ -1445,14 +1658,16 @@ tulip_pci_attach( malloc(sizeof(tulip_desc_t) * TULIP_TXDESCS, M_DEVBUF, M_NOWAIT); if (txdescs == NULL) { free((caddr_t) rxdescs, M_DEVBUF); +#if defined(__FreeBSD__) free((caddr_t) sc, M_DEVBUF); +#endif return; } - bzero(sc, sizeof(*sc)); /* Zero out the softc*/ - + sc->tulip_chipid = chipid; sc->tulip_unit = unit; sc->tulip_name = "de"; +#if defined(__FreeBSD__) retval = pci_map_mem(config_id, PCI_CBMA, &va_csrs, &pa_csrs); if (!retval) { free((caddr_t) txdescs, M_DEVBUF); @@ -1461,7 +1676,11 @@ tulip_pci_attach( return; } tulips[unit] = sc; - sc->tulip_revinfo = pci_conf_read(config_id, PCI_CFRV) & 0xFF; +#endif +#if defined(__bsdi__) + va_csrs = (vm_offset_t) mapphys((vm_offset_t) ia->ia_maddr, ia->ia_msize); +#endif + sc->tulip_revinfo = revinfo; tulip_initcsrs(sc, (volatile tulip_uint32_t *) va_csrs, TULIP_PCI_CSRSIZE); tulip_initring(sc, &sc->tulip_rxinfo, rxdescs, TULIP_RXDESCS); tulip_initring(sc, &sc->tulip_txinfo, txdescs, TULIP_TXDESCS); @@ -1473,31 +1692,26 @@ tulip_pci_attach( printf("%s%d: %s%s pass %d.%d Ethernet address %s\n", sc->tulip_name, sc->tulip_unit, (sc->tulip_boardsw != NULL ? sc->tulip_boardsw->bd_description : ""), - tulip_chipdescs[tulip_chipids[sc->tulip_unit]], + tulip_chipdescs[sc->tulip_chipid], (sc->tulip_revinfo & 0xF0) >> 4, sc->tulip_revinfo & 0x0F, "unknown"); } else { TULIP_RESET(sc); tulip_attach(sc); +#if defined(__FreeBSD__) pci_map_int (config_id, tulip_intr, (void*) sc, &net_imask); - } -} +#endif +#if defined(__bsdi__) + isa_establish(&sc->tulip_id, &sc->tulip_dev); -static int -tulip_pci_shutdown( - struct kern_devconf *kdc, - int force) -{ - if (kdc->kdc_unit < NDE) { - tulip_softc_t *sc = tulips[kdc->kdc_unit]; - *sc->tulip_csrs.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_ih.ih_fun = tulip_intr; + sc->tulip_ih.ih_arg = (void *)sc; + intr_establish(ia->ia_irq, &sc->tulip_ih, DV_NET); + + sc->tulip_ats.func = tulip_pci_shutdown; + sc->tulip_ats.arg = (void *) sc; + atshutdown(&sc->tulip_ats, ATSH_ADD); +#endif } - (void) dev_detach(kdc); - return 0; } - -#endif /* NPCI > 0 */ #endif /* NDE > 0 */ diff --git a/sys/pci/dc21040.h b/sys/pci/dc21040.h index f1a715e..cda354c 100644 --- a/sys/pci/dc21040.h +++ b/sys/pci/dc21040.h @@ -21,12 +21,11 @@ * (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: dc21040.h,v 1.2 1995/04/09 04:46:14 davidg Exp $ + * $Id: dc21040.h,v 1.3 1995/05/05 19:44:34 thomas Exp $ * * $Log: dc21040.h,v $ - * Revision 1.2 1995/04/09 04:46:14 davidg - * From Matt Thomas: Added support for 100Mb cards (such as the DEC DE-500-XA - * and SMC 9332). + * Revision 1.3 1995/05/05 19:44:34 thomas + * cogent em100 support * * Revision 1.1 1994/10/01 20:16:45 wollman * Add Matt Thomas's DC21040 PCI Ethernet driver. (This is turning out @@ -265,6 +264,17 @@ typedef struct { #define TULIP_GP_DE500_NOTOK_100 0x00000040L #define TULIP_GP_DE500_HALFDUPLEX 0x00000008L #define TULIP_GP_DE500_FORCE_100 0x00000001L + +/* + * These are the defintitions used for the Cogent EM100 + * DC21140 board. + */ +#define TULIP_GP_EM100_PINS 0x0000013F /* General Purpose Pin directions */ +#define TULIP_GP_EM100_INIT 0x00000009 /* No loopback --- point-to-point */ +#define TULIP_OUI_COGENT_0 0x00 +#define TULIP_OUI_COGENT_1 0x00 +#define TULIP_OUI_COGENT_2 0x94 +#define TULIP_COGENT_EM100_ID 0x12 /* * SROM definitions for the DC21140 and DC21041. */ diff --git a/sys/pci/if_de.c b/sys/pci/if_de.c index 64b1095..0c84b65 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.22 1995/04/17 08:16:14 davidg Exp $ + * $Id: if_de.c,v 1.12 1995/05/05 19:44:06 thomas Exp $ * */ @@ -32,12 +32,14 @@ * BPF support code stolen directly from if_ec.c * * This driver supports the DEC DE435 or any other PCI - * board which support DC21040. + * board which support DC21040 or DC21140 (mostly). */ #define __IF_DE_C__ "pl2 95/03/21" +#ifndef __bsdi__ #include "de.h" -#if NDE > 0 +#endif +#if NDE > 0 || defined(__bsdi__) #include <sys/param.h> #include <sys/systm.h> @@ -49,8 +51,13 @@ #include <sys/malloc.h> #include <sys/kernel.h> #include <sys/proc.h> /* only for declaration of wakeup() used by vm.h */ +#if defined(__FreeBSD__) #include <sys/devconf.h> #include <machine/clock.h> +#endif +#if defined(__bsdi__) +#include <sys/device.h> +#endif #include <net/if.h> #include <net/if_types.h> @@ -80,13 +87,22 @@ #include <vm/vm_kern.h> #include <vm/vm_param.h> - +#if defined(__FreeBSD__) #include <pci.h> #if NPCI > 0 #include <pci/pcivar.h> +#include <pci/dc21040.h> +#endif #endif -#include <pci/dc21040.h> +#if defined(__bsdi__) +#include <i386/pci/pci.h> +#include <i386/pci/dc21040.h> +#include <i386/isa/isa.h> +#include <i386/isa/icu.h> +#include <i386/isa/dma.h> +#include <i386/isa/isavar.h> +#endif /* * This module supports @@ -168,7 +184,8 @@ typedef struct { typedef enum { TULIP_DC21040_GENERIC, TULIP_DC21140_DEC_EB, - TULIP_DC21140_DEC_DE500 + TULIP_DC21140_DEC_DE500, + TULIP_DC21140_COGENT_EM100 } tulip_board_t; typedef struct _tulip_softc_t tulip_softc_t; @@ -180,8 +197,15 @@ typedef struct { void (*bd_media_select)(tulip_softc_t *sc); } tulip_boardsw_t; +typedef enum { TULIP_DC21040, TULIP_DC21140, TULIP_DC21041 } tulip_chipid_t; struct _tulip_softc_t { +#if defined(__bsdi__) + struct device tulip_dev; /* base device */ + struct isadev tulip_id; /* ISA device */ + struct intrhand tulip_ih; /* intrrupt vectoring */ + struct atshutdown tulip_ats; /* shutdown routine */ +#endif struct arpcom tulip_ac; tulip_regfile_t tulip_csrs; unsigned tulip_flags; @@ -195,8 +219,9 @@ struct _tulip_softc_t { tulip_uint32_t tulip_intrmask; tulip_uint32_t tulip_cmdmode; tulip_uint32_t tulip_revinfo; + tulip_chipid_t tulip_chipid; const tulip_boardsw_t *tulip_boardsw; -#if NBPFILTER > 0 +#if NBPFILTER > 0 && !defined(__bsdi__) && !defined(__FreeBSD__) caddr_t tulip_bpf; /* BPF context */ #endif struct ifqueue tulip_txq; @@ -206,17 +231,26 @@ struct _tulip_softc_t { }; #ifndef IFF_ALTPHYS -#define IFF_ALTPHYS IFF_LINK2 /* In case it isn't defined */ +#define IFF_ALTPHYS IFF_LINK0 /* In case it isn't defined */ #endif -typedef enum { TULIP_DC21040, TULIP_DC21140, TULIP_DC21041 } tulip_chipid_t; const char *tulip_chipdescs[] = { "DC21040 [10Mb/s]", "DC21140 [10-100Mb/s]", "DC21041 [10Mb/s]" }; +#if defined(__FreeBSD__) +typedef void ifnet_ret_t; tulip_softc_t *tulips[NDE]; -tulip_chipid_t tulip_chipids[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; +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 @@ -236,11 +270,11 @@ tulip_chipid_t tulip_chipids[NDE]; && ((u_short *)a1)[1] == 0xFFFFU \ && ((u_short *)a1)[2] == 0xFFFFU) -static void tulip_start(struct ifnet *ifp); +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 +#if __FreeBSD__ > 1 || defined(__bsdi__) #define TULIP_IFRESET_ARGS int unit #define TULIP_RESET(sc) tulip_reset((sc)->tulip_unit) #else @@ -339,20 +373,57 @@ static const tulip_boardsw_t tulip_dc21140_eb_boardsw = { tulip_dc21140_evalboard_media_select }; + +static int +tulip_dc21140_cogent_em100_media_probe( + tulip_softc_t *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; + return 1; +} + +static void +tulip_dc21140_cogent_em100_media_select( + tulip_softc_t *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; + 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); + sc->tulip_cmdmode |= TULIP_CMD_PORTSELECT + |TULIP_CMD_PCSFUNCTION|TULIP_CMD_SCRAMBLER; + sc->tulip_cmdmode &= ~TULIP_CMD_TXTHRSHLDCTL; + sc->tulip_flags |= TULIP_ALTPHYS; +} + +static const tulip_boardsw_t tulip_dc21140_cogent_em100_boardsw = { + TULIP_DC21140_COGENT_EM100, + "Cogent EM100", + tulip_dc21140_cogent_em100_media_probe, + tulip_dc21140_cogent_em100_media_select +}; + static int tulip_dc21140_de500_media_probe( tulip_softc_t *sc) { *sc->tulip_csrs.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; + 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; DELAY(1000000); - return (*sc->tulip_csrs.csr_gp & TULIP_GP_DE500_NOTOK_100) == 0; + return (*sc->tulip_csrs.csr_gp & TULIP_GP_DE500_NOTOK_100) != 0; } static void @@ -389,11 +460,11 @@ static const tulip_boardsw_t tulip_dc21140_de500_boardsw = { tulip_dc21140_de500_media_select }; -static void +static ifnet_ret_t tulip_reset( TULIP_IFRESET_ARGS) { - tulip_softc_t *sc = tulips[unit]; + tulip_softc_t *sc = TULIP_UNIT_TO_SOFTC(unit); tulip_ringinfo_t *ri; tulip_desc_t *di; @@ -460,11 +531,11 @@ tulip_reset( tulip_addr_filter(sc); } -static void +static ifnet_ret_t tulip_init( int unit) { - tulip_softc_t *sc = tulips[unit]; + tulip_softc_t *sc = TULIP_UNIT_TO_SOFTC(unit); if (sc->tulip_if.if_flags & IFF_UP) { sc->tulip_if.if_flags |= IFF_RUNNING; @@ -606,6 +677,9 @@ tulip_rx_intr( m->m_pkthdr.rcvif = ifp; m->m_data += sizeof(struct ether_header); m->m_len = m->m_pkthdr.len = total_len; +#if defined(__bsdi__) + eh.ether_type = ntohs(eh.ether_type); +#endif ether_input(ifp, &eh, m); m = m0; } else { @@ -718,11 +792,11 @@ tulip_txsegment( return segcnt; } -static void +static ifnet_ret_t tulip_start( struct ifnet *ifp) { - tulip_softc_t *sc = (tulip_softc_t *) 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; @@ -783,10 +857,11 @@ tulip_start( MCLGET(m0, M_DONTWAIT); if ((m0->m_flags & M_EXT) == 0) { m_freem(m); + m_freem(m0); continue; } } - m_copydata(m, 0, m0->m_pkthdr.len, mtod(m0, caddr_t)); + 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); @@ -1000,7 +1075,7 @@ tulip_read_macaddr( unsigned char tmpbuf[8]; static u_char testpat[] = { 0xFF, 0, 0x55, 0xAA, 0xFF, 0, 0x55, 0xAA }; - if (tulip_chipids[sc->tulip_unit] == TULIP_DC21040) { + if (sc->tulip_chipid == TULIP_DC21040) { *sc->tulip_csrs.csr_enetrom = 1; sc->tulip_boardsw = &tulip_dc21040_boardsw; for (idx = 0; idx < 32; idx++) { @@ -1014,7 +1089,7 @@ tulip_read_macaddr( * Assume all DC21140 board are compatible with the * DEC 10/100 evaluation board. Not really valid but ... */ - if (tulip_chipids[sc->tulip_unit] == TULIP_DC21140) + if (sc->tulip_chipid == TULIP_DC21140) sc->tulip_boardsw = &tulip_dc21140_eb_boardsw; tulip_read_srom(sc); if (tulip_srom_crcok(sc->tulip_rombuf)) { @@ -1082,6 +1157,16 @@ tulip_read_macaddr( if (cksum != rom_cksum) return -1; + + if (sc->tulip_chipid == TULIP_DC21140) { + if (sc->tulip_hwaddr[0] == TULIP_OUI_COGENT_0 + && sc->tulip_hwaddr[1] == TULIP_OUI_COGENT_1 + && sc->tulip_hwaddr[2] == TULIP_OUI_COGENT_2) { + if (sc->tulip_rombuf[32] == TULIP_COGENT_EM100_ID) + sc->tulip_boardsw = &tulip_dc21140_cogent_em100_boardsw; + } + } + return 0; } @@ -1159,7 +1244,7 @@ tulip_ioctl( int cmd, caddr_t data) { - tulip_softc_t *sc = tulips[ifp->if_unit]; + tulip_softc_t *sc = TULIP_UNIT_TO_SOFTC(ifp->if_unit); struct ifaddr *ifa = (struct ifaddr *)data; struct ifreq *ifr = (struct ifreq *) data; int s, error = 0; @@ -1176,7 +1261,10 @@ tulip_ioctl( ((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__) arp_ifinit((struct arpcom *)ifp, ifa); +#endif + arpwhohas((struct arpcom *)ifp, &IA_SIN(ifa)->sin_addr); break; } #endif /* INET */ @@ -1242,6 +1330,7 @@ tulip_ioctl( } break; } +#if defined(SIOCSIFMTU) case SIOCSIFMTU: /* * Set the interface MTU. @@ -1252,6 +1341,7 @@ tulip_ioctl( ifp->if_mtu = ifr->ifr_mtu; } break; +#endif default: { error = EINVAL; @@ -1269,29 +1359,30 @@ tulip_attach( { struct ifnet *ifp = &sc->tulip_if; - if ((*sc->tulip_boardsw->bd_media_probe)(sc)) { - ifp->if_flags |= IFF_ALTPHYS; - } else { - sc->tulip_flags |= TULIP_ALTPHYS; - } - - TULIP_RESET(sc); - 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_reset = tulip_reset; ifp->if_start = tulip_start; - printf("%s%d: %s%s pass %d.%d Ethernet address %s\n", - sc->tulip_name, sc->tulip_unit, +#ifndef __bsdi__ + printf("%s%d", sc->tulip_name, sc->tulip_unit); +#endif + printf(": %s%s pass %d.%d Ethernet address %s\n", sc->tulip_boardsw->bd_description, - tulip_chipdescs[tulip_chipids[sc->tulip_unit]], + tulip_chipdescs[sc->tulip_chipid], (sc->tulip_revinfo & 0xF0) >> 4, sc->tulip_revinfo & 0x0F, ether_sprintf(sc->tulip_hwaddr)); + if ((*sc->tulip_boardsw->bd_media_probe)(sc)) { + ifp->if_flags |= IFF_ALTPHYS; + } else { + sc->tulip_flags |= TULIP_ALTPHYS; + } + + TULIP_RESET(sc); + if_attach(ifp); #if NBPFILTER > 0 @@ -1314,20 +1405,16 @@ tulip_initcsrs( sc->tulip_csrs.csr_command = va_csrs + 6 * csr_size; sc->tulip_csrs.csr_intr = va_csrs + 7 * csr_size; sc->tulip_csrs.csr_missed_frame = va_csrs + 8 * csr_size; - if (tulip_chipids[sc->tulip_unit] == TULIP_DC21040) { - sc->tulip_csrs.csr_enetrom = va_csrs + 9 * csr_size; + if (sc->tulip_chipid == TULIP_DC21040) { + sc->tulip_csrs.csr_enetrom = (tulip_sint32_t *) va_csrs + 9 * csr_size; sc->tulip_csrs.csr_reserved = va_csrs + 10 * csr_size; sc->tulip_csrs.csr_full_duplex = va_csrs + 11 * csr_size; sc->tulip_csrs.csr_sia_status = va_csrs + 12 * csr_size; sc->tulip_csrs.csr_sia_connectivity = va_csrs + 13 * csr_size; sc->tulip_csrs.csr_sia_tx_rx = va_csrs + 14 * csr_size; sc->tulip_csrs.csr_sia_general = va_csrs + 15 * csr_size; - } else if (tulip_chipids[sc->tulip_unit] == TULIP_DC21140) { - if (sc->tulip_revinfo < 0x10) - sc->tulip_csrs.csr_enetrom = va_csrs + 9 * csr_size; - else - sc->tulip_csrs.csr_srom_mii = va_csrs + 9 * csr_size; - + } else if (sc->tulip_chipid == TULIP_DC21140 || sc->tulip_chipid == TULIP_DC21041) { + sc->tulip_csrs.csr_srom_mii = va_csrs + 9 * csr_size; sc->tulip_csrs.csr_gp_timer = va_csrs + 11 * csr_size; sc->tulip_csrs.csr_gp = va_csrs + 12 * csr_size; sc->tulip_csrs.csr_watchdog = va_csrs + 15 * csr_size; @@ -1348,26 +1435,11 @@ tulip_initring( ri->ri_last[-1].d_flag = TULIP_DFLAG_ENDRING; } -#if NPCI > 0 /* * This is the PCI configuration support. Since the DC21040 is available * on both EISA and PCI boards, one must be careful in how defines the * DC21040 in the config file. */ -static char* tulip_pci_probe (pcici_t config_id, pcidi_t device_id); -static void tulip_pci_attach(pcici_t config_id, int unit); -static u_long tulip_pci_count; -static int tulip_pci_shutdown(struct kern_devconf *, int); - -struct pci_device dedevice = { - "de", - tulip_pci_probe, - tulip_pci_attach, - &tulip_pci_count, - tulip_pci_shutdown, -}; - -DATA_SET (pcidevice_set, dedevice); #define PCI_CFID 0x00 /* Configuration ID */ #define PCI_CFCS 0x04 /* Configurtion Command/Status */ @@ -1379,65 +1451,206 @@ DATA_SET (pcidevice_set, dedevice); #define PCI_CFDA 0x40 /* Configuration Driver Area */ #define TULIP_PCI_CSRSIZE (8 / sizeof(tulip_uint32_t)) + +#if defined(__FreeBSD__) + +#define TULIP_PCI_ATTACH_ARGS pcici_t config_id, int unit + +static int +tulip_pci_shutdown( + struct kern_devconf *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; + DELAY(10); /* Wait 10 microsends (actually 50 PCI cycles but at + 33MHz that comes to two microseconds but wait a + bit longer anyways) */ + } + (void) dev_detach(kdc); + return 0; +} + static char* tulip_pci_probe( pcici_t config_id, pcidi_t device_id) { - if (device_id == 0x00021011ul) { - if (tulip_pci_count < NDE) - tulip_chipids[tulip_pci_count] = TULIP_DC21040; + if (device_id == 0x00021011ul) return "Digital DC21040 Ethernet"; - } - if (device_id == 0x00141011ul) { - if (tulip_pci_count < NDE) - tulip_chipids[tulip_pci_count] = TULIP_DC21041; + if (device_id == 0x00141011ul) return "Digital DC21041 Ethernet"; - } - if (device_id == 0x00091011ul) { - if (tulip_pci_count < NDE) - tulip_chipids[tulip_pci_count] = TULIP_DC21140; + if (device_id == 0x00091011ul) return "Digital DC21140 Fast Ethernet"; - } return NULL; } +static void tulip_pci_attach(TULIP_PCI_ATTACH_ARGS); +static u_long tulip_pci_count; + +struct pci_device dedevice = { + "de", + tulip_pci_probe, + tulip_pci_attach, + &tulip_pci_count, + tulip_pci_shutdown, +}; + +DATA_SET (pcidevice_set, dedevice); +#endif /* __FreeBSD__ */ + +#if defined(__bsdi__) +#define TULIP_PCI_ATTACH_ARGS struct device *parent, struct device *self, void *aux + +static void +tulip_pci_shutdown( + void *arg) +{ + tulip_softc_t *sc = (tulip_softc_t *) arg; + *sc->tulip_csrs.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) */ +} + +static int +tulip_pci_match( + pci_devaddr_t *pa) +{ + int irq; + unsigned id; + + id = pci_inl(pa, PCI_VENDOR_ID); + if ((id & 0xFFFF) != 0x1011) + return 0; + id >>= 16; + if (id != 2 && id != 9 && id != 0x14) + return 0; + irq = pci_inl(pa, PCI_I_PIN) & 0xFF; + if (irq == 0 || irq >= 16) + return 0; + + return 1; +} + +int +tulip_pci_probe( + struct device *parent, + struct cfdata *cf, + void *aux) +{ + struct isa_attach_args *ia = (struct isa_attach_args *) aux; + unsigned irq; + pci_devaddr_t *pa; + + pa = pci_scan(tulip_pci_match); + if (pa == NULL) + return 0; + + irq = (1 << (pci_inl(pa, PCI_I_PIN) & 0xFF)); + + if (ia->ia_irq != IRQUNK && irq != ia->ia_irq) { + printf("fpa%d: error: desired IRQ of %d does not match device's actual IRQ of %d,\n", + cf->cf_unit, + ffs(ia->ia_irq) - 1, ffs(irq) - 1); + return 0; + } + if (ia->ia_irq == IRQUNK) { + if ((irq = isa_irqalloc(irq)) == 0) + return 0; + ia->ia_irq = irq; + } + + /* PCI bus masters don't use host DMA channels */ + ia->ia_drq = DRQNONE; + + /* Get the memory base address; assume the BIOS set it up correctly */ + ia->ia_maddr = (caddr_t) (pci_inl(pa, PCI_CBMA) & ~7); + pci_outl(pa, PCI_CBMA, 0xFFFFFFFF); + ia->ia_msize = ((~pci_inl(pa, PCI_CBMA)) | 7) + 1; + pci_outl(pa, PCI_CBMA, (int) ia->ia_maddr); + + /* Disable I/O space access */ + pci_outl(pa, PCI_COMMAND, pci_inl(pa, PCI_COMMAND) & ~1); + ia->ia_iobase = 0; + ia->ia_iosize = 0; + + ia->ia_aux = (void *) pa; + return 1; +} + +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 /* __bsdi__ */ + static void tulip_pci_attach( - pcici_t config_id, - int unit) + TULIP_PCI_ATTACH_ARGS) { +#if defined(__FreeBSD__) tulip_softc_t *sc; - int retval, idx, revinfo; +#endif +#if defined(__bsdi__) + tulip_softc_t *sc = (tulip_softc_t *) self; + struct isa_attach_args *ia = (struct isa_attach_args *) aux; + pci_devaddr_t *pa = (pci_devaddr_t *) ia->ia_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; + tulip_chipid_t chipid; +#if defined(__FreeBSD__) if (unit >= NDE) { printf("de%d: not configured; kernel is built for only %d device%s.\n", unit, NDE, NDE == 1 ? "" : "s"); return; } +#endif +#if defined(__FreeBSD__) revinfo = pci_conf_read(config_id, PCI_CFRV) & 0xFF; - if (tulip_chipids[unit] == TULIP_DC21040 && revinfo < 0x20) { - printf("de%d: not configured; DC21040 pass 2.0 required (%d.%d found)\n", + id = pci_conf_read(config_id, PCI_CFID); +#endif +#if defined(__bsdi__) + revinfo = pci_inl(pa, PCI_CFRV) & 0xFF; + id = pci_inl(pa, PCI_CFID); +#endif + + if (id == 0x00021011ul) chipid = TULIP_DC21040; + else if (id == 0x00091011) chipid = TULIP_DC21140; + else if (id == 0x00141011) chipid = TULIP_DC21041; + 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); return; - } else if (tulip_chipids[unit] == TULIP_DC21140 && revinfo < 0x11) { + } 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); return; } - +#if defined(__FreeBSD__) sc = (tulip_softc_t *) malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT); if (sc == NULL) return; + bzero(sc, sizeof(*sc)); /* Zero out the softc*/ +#endif rxdescs = (tulip_desc_t *) malloc(sizeof(tulip_desc_t) * TULIP_RXDESCS, M_DEVBUF, M_NOWAIT); if (rxdescs == NULL) { +#if defined(__FreeBSD__) free((caddr_t) sc, M_DEVBUF); +#endif return; } @@ -1445,14 +1658,16 @@ tulip_pci_attach( malloc(sizeof(tulip_desc_t) * TULIP_TXDESCS, M_DEVBUF, M_NOWAIT); if (txdescs == NULL) { free((caddr_t) rxdescs, M_DEVBUF); +#if defined(__FreeBSD__) free((caddr_t) sc, M_DEVBUF); +#endif return; } - bzero(sc, sizeof(*sc)); /* Zero out the softc*/ - + sc->tulip_chipid = chipid; sc->tulip_unit = unit; sc->tulip_name = "de"; +#if defined(__FreeBSD__) retval = pci_map_mem(config_id, PCI_CBMA, &va_csrs, &pa_csrs); if (!retval) { free((caddr_t) txdescs, M_DEVBUF); @@ -1461,7 +1676,11 @@ tulip_pci_attach( return; } tulips[unit] = sc; - sc->tulip_revinfo = pci_conf_read(config_id, PCI_CFRV) & 0xFF; +#endif +#if defined(__bsdi__) + va_csrs = (vm_offset_t) mapphys((vm_offset_t) ia->ia_maddr, ia->ia_msize); +#endif + sc->tulip_revinfo = revinfo; tulip_initcsrs(sc, (volatile tulip_uint32_t *) va_csrs, TULIP_PCI_CSRSIZE); tulip_initring(sc, &sc->tulip_rxinfo, rxdescs, TULIP_RXDESCS); tulip_initring(sc, &sc->tulip_txinfo, txdescs, TULIP_TXDESCS); @@ -1473,31 +1692,26 @@ tulip_pci_attach( printf("%s%d: %s%s pass %d.%d Ethernet address %s\n", sc->tulip_name, sc->tulip_unit, (sc->tulip_boardsw != NULL ? sc->tulip_boardsw->bd_description : ""), - tulip_chipdescs[tulip_chipids[sc->tulip_unit]], + tulip_chipdescs[sc->tulip_chipid], (sc->tulip_revinfo & 0xF0) >> 4, sc->tulip_revinfo & 0x0F, "unknown"); } else { TULIP_RESET(sc); tulip_attach(sc); +#if defined(__FreeBSD__) pci_map_int (config_id, tulip_intr, (void*) sc, &net_imask); - } -} +#endif +#if defined(__bsdi__) + isa_establish(&sc->tulip_id, &sc->tulip_dev); -static int -tulip_pci_shutdown( - struct kern_devconf *kdc, - int force) -{ - if (kdc->kdc_unit < NDE) { - tulip_softc_t *sc = tulips[kdc->kdc_unit]; - *sc->tulip_csrs.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_ih.ih_fun = tulip_intr; + sc->tulip_ih.ih_arg = (void *)sc; + intr_establish(ia->ia_irq, &sc->tulip_ih, DV_NET); + + sc->tulip_ats.func = tulip_pci_shutdown; + sc->tulip_ats.arg = (void *) sc; + atshutdown(&sc->tulip_ats, ATSH_ADD); +#endif } - (void) dev_detach(kdc); - return 0; } - -#endif /* NPCI > 0 */ #endif /* NDE > 0 */ |