if_de.c revision 11070
13278Swollman/*- 27689Sdg * Copyright (c) 1994, 1995 Matt Thomas (matt@lkg.dec.com) 33278Swollman * All rights reserved. 43278Swollman * 53278Swollman * Redistribution and use in source and binary forms, with or without 63278Swollman * modification, are permitted provided that the following conditions 73278Swollman * are met: 83278Swollman * 1. Redistributions of source code must retain the above copyright 93278Swollman * notice, this list of conditions and the following disclaimer. 103278Swollman * 2. The name of the author may not be used to endorse or promote products 113278Swollman * derived from this software withough specific prior written permission 123278Swollman * 133278Swollman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 143278Swollman * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 153278Swollman * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 163278Swollman * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 173278Swollman * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 183278Swollman * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 193278Swollman * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 203278Swollman * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 213278Swollman * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 223278Swollman * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 233278Swollman * 2411070Sdg * $Id: if_de.c,v 1.30 1995/06/28 05:46:19 davidg Exp $ 253278Swollman * 263278Swollman */ 273278Swollman 283278Swollman/* 293278Swollman * DEC DC21040 PCI Ethernet Controller 303278Swollman * 313278Swollman * Written by Matt Thomas 323278Swollman * BPF support code stolen directly from if_ec.c 333278Swollman * 343278Swollman * This driver supports the DEC DE435 or any other PCI 3511070Sdg * board which support DC21040, DC21041, or DC21140 (mostly). 363278Swollman */ 373278Swollman 388754Sdg#if defined(__FreeBSD__) 394772Sdg#include "de.h" 408296Sdg#endif 418754Sdg#if NDE > 0 || !defined(__FreeBSD__) 423278Swollman 434772Sdg#include <sys/param.h> 444772Sdg#include <sys/systm.h> 454772Sdg#include <sys/mbuf.h> 464772Sdg#include <sys/protosw.h> 474772Sdg#include <sys/socket.h> 484772Sdg#include <sys/ioctl.h> 494772Sdg#include <sys/errno.h> 504772Sdg#include <sys/malloc.h> 516132Sdg#include <sys/kernel.h> 527089Sse#include <sys/proc.h> /* only for declaration of wakeup() used by vm.h */ 538296Sdg#if defined(__FreeBSD__) 547104Sdg#include <sys/devconf.h> 556132Sdg#include <machine/clock.h> 568754Sdg#elif defined(__bsdi__) || defined(__NetBSD__) 578296Sdg#include <sys/device.h> 588296Sdg#endif 593278Swollman 603278Swollman#include <net/if.h> 613278Swollman#include <net/if_types.h> 623278Swollman#include <net/if_dl.h> 633278Swollman#include <net/route.h> 643278Swollman 654772Sdg#include "bpfilter.h" 663278Swollman#if NBPFILTER > 0 673278Swollman#include <net/bpf.h> 683278Swollman#include <net/bpfdesc.h> 693278Swollman#endif 703278Swollman 713278Swollman#ifdef INET 723278Swollman#include <netinet/in.h> 733278Swollman#include <netinet/in_systm.h> 743278Swollman#include <netinet/in_var.h> 753278Swollman#include <netinet/ip.h> 763278Swollman#include <netinet/if_ether.h> 773278Swollman#endif 783278Swollman 793278Swollman#ifdef NS 803278Swollman#include <netns/ns.h> 813278Swollman#include <netns/ns_if.h> 823278Swollman#endif 833278Swollman 843278Swollman#include <vm/vm.h> 853278Swollman#include <vm/vm_kern.h> 863278Swollman#include <vm/vm_param.h> 873278Swollman 888296Sdg#if defined(__FreeBSD__) 893278Swollman#include <pci.h> 903278Swollman#if NPCI > 0 916132Sdg#include <pci/pcivar.h> 928296Sdg#include <pci/dc21040.h> 933278Swollman#endif 9411070Sdg#endif /* __FreeBSD__ */ 956132Sdg 968296Sdg#if defined(__bsdi__) 978296Sdg#include <i386/pci/pci.h> 9811070Sdg#include <i386/pci/ic/dc21040.h> 998296Sdg#include <i386/isa/isa.h> 1008296Sdg#include <i386/isa/icu.h> 1018296Sdg#include <i386/isa/dma.h> 1028296Sdg#include <i386/isa/isavar.h> 10311070Sdg#include <eisa.h> 10411070Sdg#if NEISA > 0 10511070Sdg#include <i386/eisa/eisa.h> 10611070Sdg#define TULIP_EISA 1078296Sdg#endif 10811070Sdg#endif /* __bsdi__ */ 1093278Swollman 1108754Sdg#if defined(__NetBSD__) 1118754Sdg#include <dev/pci/pcivar.h> 11211070Sdg#include <dev/ic/dc21040reg.h> 11311070Sdg#if defined(__i386__) 11411070Sdg#include <i386/isa/isa_machdep.h> 1158754Sdg#endif 11611070Sdg#endif /* __NetBSD__ */ 1178754Sdg 1183278Swollman/* 11911070Sdg * Intel CPUs should use I/O mapped access. 12011070Sdg * (NetBSD doesn't support it yet) 12111070Sdg */ 12211070Sdg#if defined(__i386__) && !defined(__NetBSD__) 12311070Sdg#define TULIP_IOMAPPED 12411070Sdg#endif 12511070Sdg 12611070Sdg/* 1277689Sdg * This module supports 1287689Sdg * the DEC DC21040 PCI Ethernet Controller. 12911070Sdg * the DEC DC21041 PCI Ethernet Controller. 1307689Sdg * the DEC DC21140 PCI Fast Ethernet Controller. 1313278Swollman */ 1323278Swollman 1333278Swollmantypedef struct { 1343278Swollman tulip_desc_t *ri_first; 1353278Swollman tulip_desc_t *ri_last; 1363278Swollman tulip_desc_t *ri_nextin; 1373278Swollman tulip_desc_t *ri_nextout; 1383278Swollman int ri_max; 1393278Swollman int ri_free; 1403278Swollman} tulip_ringinfo_t; 1413278Swollman 14211070Sdg#ifdef TULIP_IOMAPPED 14311070Sdgtypedef tulip_uint16_t tulip_csrptr_t; 1447689Sdg 14511070Sdg#define TULIP_EISA_CSRSIZE 16 14611070Sdg#define TULIP_EISA_CSROFFSET 0 14711070Sdg#define TULIP_PCI_CSRSIZE 8 14811070Sdg#define TULIP_PCI_CSROFFSET 0 1497689Sdg 15011070Sdg#define TULIP_READ_CSR(sc, csr) (inl((sc)->tulip_csrs.csr)) 15111070Sdg#define TULIP_WRITE_CSR(sc, csr, val) outl((sc)->tulip_csrs.csr, val) 1527689Sdg 15311070Sdg#define TULIP_READ_CSRBYTE(sc, csr) (inb((sc)->tulip_csrs.csr)) 15411070Sdg#define TULIP_WRITE_CSRBYTE(sc, csr, val) outb((sc)->tulip_csrs.csr, val) 1557689Sdg 15611070Sdg#else /* TULIP_IOMAPPED */ 1573278Swollman 15811070Sdgtypedef volatile tulip_uint32_t *tulip_csrptr_t; 15911070Sdg 16011070Sdg#if defined(__alpha__) 16111070Sdg#define TULIP_PCI_CSRSIZE (256 / sizeof(tulip_uint32_t)) 16211070Sdg#define TULIP_PCI_CSROFFSET (24 / sizeof(tulip_uint32_t)) 16311070Sdg#elif defined(__i386__) 16411070Sdg#define TULIP_PCI_CSRSIZE (8 / sizeof(tulip_uint32_t)) 16511070Sdg#define TULIP_PCI_CSROFFSET 0 16611070Sdg#endif 16711070Sdg 1683278Swollman/* 1698754Sdg * macros to read and write CSRs. Note that the "0 +" in 1708754Sdg * READ_CSR is to prevent the macro from being an lvalue 1718754Sdg * and WRITE_CSR shouldn't be assigned from. 1728754Sdg */ 1738754Sdg#define TULIP_READ_CSR(sc, csr) (0 + *(sc)->tulip_csrs.csr) 1748754Sdg#ifndef __alpha__ 1758754Sdg#define TULIP_WRITE_CSR(sc, csr, val) \ 1768754Sdg ((void)(*(sc)->tulip_csrs.csr = (val))) 1778754Sdg#else 1788754Sdg#define TULIP_WRITE_CSR(sc, csr, val) \ 1798754Sdg ((void)(*(sc)->tulip_csrs.csr = (val), MB())) 1808754Sdg#endif 1818754Sdg 18211070Sdg#endif /* TULIP_IOMAPPED */ 18311070Sdg 18411070Sdgtypedef struct { 18511070Sdg tulip_csrptr_t csr_busmode; /* CSR0 */ 18611070Sdg tulip_csrptr_t csr_txpoll; /* CSR1 */ 18711070Sdg tulip_csrptr_t csr_rxpoll; /* CSR2 */ 18811070Sdg tulip_csrptr_t csr_rxlist; /* CSR3 */ 18911070Sdg tulip_csrptr_t csr_txlist; /* CSR4 */ 19011070Sdg tulip_csrptr_t csr_status; /* CSR5 */ 19111070Sdg tulip_csrptr_t csr_command; /* CSR6 */ 19211070Sdg tulip_csrptr_t csr_intr; /* CSR7 */ 19311070Sdg tulip_csrptr_t csr_missed_frame; /* CSR8 */ 19411070Sdg 19511070Sdg /* DC21040 specific registers */ 19611070Sdg 19711070Sdg tulip_csrptr_t csr_enetrom; /* CSR9 */ 19811070Sdg tulip_csrptr_t csr_reserved; /* CSR10 */ 19911070Sdg tulip_csrptr_t csr_full_duplex; /* CSR11 */ 20011070Sdg 20111070Sdg /* DC21040/DC21041 common registers */ 20211070Sdg 20311070Sdg tulip_csrptr_t csr_sia_status; /* CSR12 */ 20411070Sdg tulip_csrptr_t csr_sia_connectivity; /* CSR13 */ 20511070Sdg tulip_csrptr_t csr_sia_tx_rx; /* CSR14 */ 20611070Sdg tulip_csrptr_t csr_sia_general; /* CSR15 */ 20711070Sdg 20811070Sdg /* DC21140/DC21041 common registers */ 20911070Sdg 21011070Sdg tulip_csrptr_t csr_srom_mii; /* CSR9 */ 21111070Sdg tulip_csrptr_t csr_gp_timer; /* CSR11 */ 21211070Sdg 21311070Sdg /* DC21140 specific registers */ 21411070Sdg 21511070Sdg tulip_csrptr_t csr_gp; /* CSR12 */ 21611070Sdg tulip_csrptr_t csr_watchdog; /* CSR15 */ 21711070Sdg 21811070Sdg /* DC21041 specific registers */ 21911070Sdg 22011070Sdg tulip_csrptr_t csr_bootrom; /* CSR10 */ 22111070Sdg} tulip_regfile_t; 22211070Sdg 2238754Sdg/* 2243278Swollman * The DC21040 has a stupid restriction in that the receive 2253278Swollman * buffers must be longword aligned. But since Ethernet 2263278Swollman * headers are not a multiple of longwords in size this forces 2273278Swollman * the data to non-longword aligned. Since IP requires the 2284772Sdg * data to be longword aligned, we need to copy it after it has 2293278Swollman * been DMA'ed in our memory. 2303278Swollman * 2313278Swollman * Since we have to copy it anyways, we might as well as allocate 2323278Swollman * dedicated receive space for the input. This allows to use a 2333278Swollman * small receive buffer size and more ring entries to be able to 2344772Sdg * better keep with a flood of tiny Ethernet packets. 2353278Swollman * 2363278Swollman * The receive space MUST ALWAYS be a multiple of the page size. 2373278Swollman * And the number of receive descriptors multiplied by the size 2383278Swollman * of the receive buffers must equal the recevive space. This 2394772Sdg * is so that we can manipulate the page tables so that even if a 24011070Sdg * packet wraps around the end of the receive space, we can 2413278Swollman * treat it as virtually contiguous. 2427689Sdg * 2437689Sdg * The above used to be true (the stupid restriction is still true) 2447689Sdg * but we gone to directly DMA'ing into MBUFs because with 100Mb 2457689Sdg * cards the copying is just too much of a hit. 2463278Swollman */ 2478754Sdg#if defined(__alpha__) 2488754Sdg#define TULIP_COPY_RXDATA 1 2498754Sdg#endif 2508754Sdg 2517689Sdg#define TULIP_RXDESCS 16 2523278Swollman#define TULIP_TXDESCS 128 2537689Sdg#define TULIP_RXQ_TARGET 8 2543278Swollman 2557791Sdgtypedef enum { 2567791Sdg TULIP_DC21040_GENERIC, 25711070Sdg TULIP_DC21040_ZX314_MASTER, 25811070Sdg TULIP_DC21040_ZX314_SLAVE, 2597791Sdg TULIP_DC21140_DEC_EB, 2608296Sdg TULIP_DC21140_DEC_DE500, 26111070Sdg TULIP_DC21140_COGENT_EM100, 26211070Sdg TULIP_DC21140_ZNYX_ZX34X, 26311070Sdg TULIP_DC21041_GENERIC, 26411070Sdg TULIP_DC21041_DE450 2657791Sdg} tulip_board_t; 2667791Sdg 2677791Sdgtypedef struct _tulip_softc_t tulip_softc_t; 2687791Sdg 2693278Swollmantypedef struct { 2707791Sdg tulip_board_t bd_type; 2717791Sdg const char *bd_description; 2727791Sdg int (*bd_media_probe)(tulip_softc_t *sc); 2737791Sdg void (*bd_media_select)(tulip_softc_t *sc); 2747791Sdg} tulip_boardsw_t; 2757791Sdg 27611070Sdgtypedef enum { 27711070Sdg TULIP_DC21040, TULIP_DC21140, 27811070Sdg TULIP_DC21041, TULIP_DE425, 27911070Sdg TULIP_CHIPID_UNKNOWN 28011070Sdg} tulip_chipid_t; 2817791Sdg 28211070Sdgtypedef enum { 28311070Sdg TULIP_PROBE_INACTIVE, TULIP_PROBE_10BASET, TULIP_PROBE_AUI, 28411070Sdg TULIP_PROBE_BNC 28511070Sdg} tulip_probe_state_t; 28611070Sdg 28711070Sdgtypedef enum { 28811070Sdg TULIP_MEDIA_UNKNOWN, TULIP_MEDIA_10BASET, 28911070Sdg TULIP_MEDIA_BNC, TULIP_MEDIA_AUI, 29011070Sdg TULIP_MEDIA_BNCAUI, TULIP_MEDIA_100BASET 29111070Sdg} tulip_media_t; 29211070Sdg 2937791Sdgstruct _tulip_softc_t { 2948296Sdg#if defined(__bsdi__) 2958296Sdg struct device tulip_dev; /* base device */ 2968296Sdg struct isadev tulip_id; /* ISA device */ 2978296Sdg struct intrhand tulip_ih; /* intrrupt vectoring */ 29811070Sdg struct atshutdown tulip_ats; /* shutdown hook */ 2998296Sdg#endif 3008754Sdg#if defined(__NetBSD__) 3018754Sdg struct device tulip_dev; /* base device */ 3028754Sdg void *tulip_ih; /* intrrupt vectoring */ 30311070Sdg void *tulip_ats; /* shutdown hook */ 3048754Sdg#endif 3053278Swollman struct arpcom tulip_ac; 3063278Swollman tulip_regfile_t tulip_csrs; 3073278Swollman unsigned tulip_flags; 30811070Sdg#define TULIP_WANTSETUP 0x0001 30911070Sdg#define TULIP_WANTHASH 0x0002 31011070Sdg#define TULIP_DOINGSETUP 0x0004 31111070Sdg#define TULIP_ALTPHYS 0x0008 /* use AUI */ 31211070Sdg#define TULIP_TXPROBE_ACTIVE 0x0010 31311070Sdg#define TULIP_TXPROBE_OK 0x0020 31411070Sdg#define TULIP_INRESET 0x0040 31511070Sdg#define TULIP_WANTRXACT 0x0080 31611070Sdg#define TULIP_SLAVEDROM 0x0100 31711070Sdg#define TULIP_ROMOK 0x0200 3187689Sdg unsigned char tulip_rombuf[128]; 3193278Swollman tulip_uint32_t tulip_setupbuf[192/sizeof(tulip_uint32_t)]; 3203278Swollman tulip_uint32_t tulip_setupdata[192/sizeof(tulip_uint32_t)]; 3213278Swollman tulip_uint32_t tulip_intrmask; 3223278Swollman tulip_uint32_t tulip_cmdmode; 3233278Swollman tulip_uint32_t tulip_revinfo; 32411070Sdg tulip_uint32_t tulip_gpticks; 32511070Sdg /* tulip_uint32_t tulip_bus; XXX */ 32611070Sdg tulip_media_t tulip_media; 32711070Sdg tulip_probe_state_t tulip_probe_state; 3288296Sdg tulip_chipid_t tulip_chipid; 3297791Sdg const tulip_boardsw_t *tulip_boardsw; 33011070Sdg tulip_softc_t *tulip_slaves; 3313278Swollman struct ifqueue tulip_txq; 3327689Sdg struct ifqueue tulip_rxq; 3333278Swollman tulip_ringinfo_t tulip_rxinfo; 3343278Swollman tulip_ringinfo_t tulip_txinfo; 3357791Sdg}; 3363278Swollman 3373278Swollman#ifndef IFF_ALTPHYS 3388296Sdg#define IFF_ALTPHYS IFF_LINK0 /* In case it isn't defined */ 3393278Swollman#endif 34011070Sdgstatic const char *tulip_chipdescs[] = { 3413543Sse "DC21040 [10Mb/s]", 3427791Sdg "DC21140 [10-100Mb/s]", 34311070Sdg "DC21041 [10Mb/s]", 34411070Sdg#if defined(TULIP_EISA) 34511070Sdg "DE425 [10Mb/s]" 34611070Sdg#endif 3473543Sse}; 3483543Sse 3498296Sdg#if defined(__FreeBSD__) 3508296Sdgtypedef void ifnet_ret_t; 3518754Sdgtypedef int ioctl_cmd_t; 3523278Swollmantulip_softc_t *tulips[NDE]; 3538296Sdg#define TULIP_UNIT_TO_SOFTC(unit) (tulips[unit]) 3548296Sdg#endif 3558296Sdg#if defined(__bsdi__) 3568296Sdgtypedef int ifnet_ret_t; 3578754Sdgtypedef int ioctl_cmd_t; 3588296Sdgextern struct cfdriver decd; 3598296Sdg#define TULIP_UNIT_TO_SOFTC(unit) ((tulip_softc_t *) decd.cd_devs[unit]) 36011070Sdg#define TULIP_BURSTSIZE(unit) 3 3618296Sdg#endif 3628754Sdg#if defined(__NetBSD__) 3638754Sdgtypedef void ifnet_ret_t; 3648754Sdgtypedef u_long ioctl_cmd_t; 3658754Sdgextern struct cfdriver decd; 3668754Sdg#define TULIP_UNIT_TO_SOFTC(unit) ((tulip_softc_t *) decd.cd_devs[unit]) 3678754Sdg#endif 3683278Swollman 36911070Sdg#ifndef TULIP_BURSTSIZE 37011070Sdg#define TULIP_BURSTSIZE(unit) 3 37111070Sdg#endif 37211070Sdg 3733278Swollman#define tulip_if tulip_ac.ac_if 3743278Swollman#define tulip_unit tulip_ac.ac_if.if_unit 3753278Swollman#define tulip_name tulip_ac.ac_if.if_name 3768754Sdg#define tulip_bpf tulip_ac.ac_if.if_bpf 3773278Swollman#define tulip_hwaddr tulip_ac.ac_enaddr 3783278Swollman 3793278Swollman#define TULIP_CRC32_POLY 0xEDB88320UL /* CRC-32 Poly -- Little Endian */ 3803278Swollman#define TULIP_CHECK_RXCRC 0 3814772Sdg#define TULIP_MAX_TXSEG 30 3823278Swollman 3833278Swollman#define TULIP_ADDREQUAL(a1, a2) \ 3843278Swollman (((u_short *)a1)[0] == ((u_short *)a2)[0] \ 3854772Sdg && ((u_short *)a1)[1] == ((u_short *)a2)[1] \ 3864772Sdg && ((u_short *)a1)[2] == ((u_short *)a2)[2]) 3873278Swollman#define TULIP_ADDRBRDCST(a1) \ 3883278Swollman (((u_short *)a1)[0] == 0xFFFFU \ 3894772Sdg && ((u_short *)a1)[1] == 0xFFFFU \ 3904772Sdg && ((u_short *)a1)[2] == 0xFFFFU) 3913278Swollman 3928296Sdgstatic ifnet_ret_t tulip_start(struct ifnet *ifp); 3937689Sdgstatic void tulip_rx_intr(tulip_softc_t *sc); 3943278Swollmanstatic void tulip_addr_filter(tulip_softc_t *sc); 3953278Swollman 3967791Sdg 3977791Sdgstatic int 3987791Sdgtulip_dc21040_media_probe( 3998754Sdg tulip_softc_t * const sc) 4007791Sdg{ 4017791Sdg int cnt; 4027791Sdg 4038754Sdg TULIP_WRITE_CSR(sc, csr_sia_connectivity, 0); 4048754Sdg TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_SIACONN_10BASET); 4057791Sdg for (cnt = 0; cnt < 2400; cnt++) { 4068754Sdg if ((TULIP_READ_CSR(sc, csr_sia_status) & TULIP_SIASTS_LINKFAIL) == 0) 4077791Sdg break; 4087791Sdg DELAY(1000); 4097791Sdg } 4108754Sdg return (TULIP_READ_CSR(sc, csr_sia_status) & TULIP_SIASTS_LINKFAIL) != 0; 4117791Sdg} 4127791Sdg 4133278Swollmanstatic void 4147791Sdgtulip_dc21040_media_select( 4158754Sdg tulip_softc_t * const sc) 4167791Sdg{ 41711070Sdg sc->tulip_cmdmode |= TULIP_CMD_CAPTREFFCT|TULIP_CMD_THRSHLD160; 4188754Sdg TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_SIACONN_RESET); 4197791Sdg if (sc->tulip_if.if_flags & IFF_ALTPHYS) { 4207791Sdg if ((sc->tulip_flags & TULIP_ALTPHYS) == 0) 4217791Sdg printf("%s%d: enabling Thinwire/AUI port\n", 4227791Sdg sc->tulip_if.if_name, sc->tulip_if.if_unit); 4238754Sdg TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_SIACONN_AUI); 4247791Sdg sc->tulip_flags |= TULIP_ALTPHYS; 4257791Sdg } else { 4267791Sdg if (sc->tulip_flags & TULIP_ALTPHYS) 4277791Sdg printf("%s%d: enabling 10baseT/UTP port\n", 4287791Sdg sc->tulip_if.if_name, sc->tulip_if.if_unit); 4298754Sdg TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_SIACONN_10BASET); 4307791Sdg sc->tulip_flags &= ~TULIP_ALTPHYS; 43111070Sdg sc->tulip_media = TULIP_MEDIA_10BASET; 4327791Sdg } 4337791Sdg} 4347791Sdg 4357791Sdgstatic const tulip_boardsw_t tulip_dc21040_boardsw = { 4367791Sdg TULIP_DC21040_GENERIC, 4377791Sdg "", 4387791Sdg tulip_dc21040_media_probe, 4397791Sdg tulip_dc21040_media_select 4407791Sdg}; 4417791Sdg 4427791Sdgstatic int 44311070Sdgtulip_zx314_media_probe( 44411070Sdg tulip_softc_t * const sc) 44511070Sdg{ 44611070Sdg TULIP_WRITE_CSR(sc, csr_sia_connectivity, 0); 44711070Sdg TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_SIACONN_10BASET); 44811070Sdg return 0; 44911070Sdg} 45011070Sdg 45111070Sdgstatic void 45211070Sdgtulip_zx314_media_select( 45311070Sdg tulip_softc_t * const sc) 45411070Sdg{ 45511070Sdg sc->tulip_cmdmode |= TULIP_CMD_CAPTREFFCT|TULIP_CMD_THRSHLD160; 45611070Sdg TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_SIACONN_RESET); 45711070Sdg if (sc->tulip_flags & TULIP_ALTPHYS) 45811070Sdg printf("%s%d: enabling 10baseT/UTP port\n", 45911070Sdg sc->tulip_if.if_name, sc->tulip_if.if_unit); 46011070Sdg TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_SIACONN_10BASET); 46111070Sdg sc->tulip_flags &= ~TULIP_ALTPHYS; 46211070Sdg sc->tulip_media = TULIP_MEDIA_10BASET; 46311070Sdg} 46411070Sdg 46511070Sdg 46611070Sdgstatic const tulip_boardsw_t tulip_dc21040_zx314_master_boardsw = { 46711070Sdg TULIP_DC21040_ZX314_MASTER, 46811070Sdg "ZNYX ZX314 ", 46911070Sdg tulip_zx314_media_probe, 47011070Sdg tulip_zx314_media_select 47111070Sdg}; 47211070Sdg 47311070Sdgstatic const tulip_boardsw_t tulip_dc21040_zx314_slave_boardsw = { 47411070Sdg TULIP_DC21040_ZX314_SLAVE, 47511070Sdg "ZNYX ZX314 ", 47611070Sdg tulip_zx314_media_probe, 47711070Sdg tulip_zx314_media_select 47811070Sdg}; 47911070Sdg 48011070Sdgstatic int 4817791Sdgtulip_dc21140_evalboard_media_probe( 4828754Sdg tulip_softc_t * const sc) 4837791Sdg{ 4848754Sdg TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_EB_PINS); 4858754Sdg TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_EB_INIT); 4868754Sdg TULIP_WRITE_CSR(sc, csr_command, 4878754Sdg TULIP_READ_CSR(sc, csr_command) | TULIP_CMD_PORTSELECT | 4888754Sdg TULIP_CMD_PCSFUNCTION | TULIP_CMD_SCRAMBLER | TULIP_CMD_MUSTBEONE); 4898754Sdg TULIP_WRITE_CSR(sc, csr_command, 4908754Sdg TULIP_READ_CSR(sc, csr_command) & ~TULIP_CMD_TXTHRSHLDCTL); 4917791Sdg DELAY(1000000); 4928754Sdg return (TULIP_READ_CSR(sc, csr_gp) & TULIP_GP_EB_OK100) != 0; 4937791Sdg} 4947791Sdg 4957791Sdgstatic void 4967791Sdgtulip_dc21140_evalboard_media_select( 4978754Sdg tulip_softc_t * const sc) 4987791Sdg{ 4997791Sdg sc->tulip_cmdmode |= TULIP_CMD_STOREFWD|TULIP_CMD_MUSTBEONE; 5008754Sdg TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_EB_PINS); 5018754Sdg TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_EB_INIT); 5027791Sdg if (sc->tulip_if.if_flags & IFF_ALTPHYS) { 5037791Sdg if ((sc->tulip_flags & TULIP_ALTPHYS) == 0) 5047791Sdg printf("%s%d: enabling 100baseTX UTP port\n", 5057791Sdg sc->tulip_if.if_name, sc->tulip_if.if_unit); 5067791Sdg sc->tulip_cmdmode |= TULIP_CMD_PORTSELECT 5077791Sdg |TULIP_CMD_PCSFUNCTION|TULIP_CMD_SCRAMBLER; 5087791Sdg sc->tulip_cmdmode &= ~TULIP_CMD_TXTHRSHLDCTL; 5097791Sdg sc->tulip_flags |= TULIP_ALTPHYS; 51011070Sdg sc->tulip_media = TULIP_MEDIA_100BASET; 5117791Sdg } else { 5127791Sdg if (sc->tulip_flags & TULIP_ALTPHYS) 5137791Sdg printf("%s%d: enabling 10baseT UTP port\n", 5147791Sdg sc->tulip_if.if_name, sc->tulip_if.if_unit); 5157791Sdg sc->tulip_cmdmode &= ~(TULIP_CMD_PORTSELECT 5167791Sdg |TULIP_CMD_PCSFUNCTION|TULIP_CMD_SCRAMBLER); 5177791Sdg sc->tulip_cmdmode |= TULIP_CMD_TXTHRSHLDCTL; 5187791Sdg sc->tulip_flags &= ~TULIP_ALTPHYS; 51911070Sdg sc->tulip_media = TULIP_MEDIA_10BASET; 5207791Sdg } 5217791Sdg} 5227791Sdg 5237791Sdgstatic const tulip_boardsw_t tulip_dc21140_eb_boardsw = { 5247791Sdg TULIP_DC21140_DEC_EB, 5257791Sdg "", 5267791Sdg tulip_dc21140_evalboard_media_probe, 5277791Sdg tulip_dc21140_evalboard_media_select 5287791Sdg}; 5297791Sdg 5307791Sdgstatic int 5318296Sdgtulip_dc21140_cogent_em100_media_probe( 5328754Sdg tulip_softc_t * const sc) 5338296Sdg{ 5348754Sdg TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_EM100_PINS); 5358754Sdg TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_EM100_INIT); 5368754Sdg TULIP_WRITE_CSR(sc, csr_command, 5378754Sdg TULIP_READ_CSR(sc, csr_command) | TULIP_CMD_PORTSELECT | 5388754Sdg TULIP_CMD_PCSFUNCTION | TULIP_CMD_SCRAMBLER | TULIP_CMD_MUSTBEONE); 5398754Sdg TULIP_WRITE_CSR(sc, csr_command, 5408754Sdg TULIP_READ_CSR(sc, csr_command) & ~TULIP_CMD_TXTHRSHLDCTL); 5418296Sdg return 1; 5428296Sdg} 5438296Sdg 5448296Sdgstatic void 5458296Sdgtulip_dc21140_cogent_em100_media_select( 5468754Sdg tulip_softc_t * const sc) 5478296Sdg{ 5488296Sdg sc->tulip_cmdmode |= TULIP_CMD_STOREFWD|TULIP_CMD_MUSTBEONE; 5498754Sdg TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_EM100_PINS); 5508754Sdg TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_EM100_INIT); 5518296Sdg if ((sc->tulip_flags & TULIP_ALTPHYS) == 0) 5528296Sdg printf("%s%d: enabling 100baseTX UTP port\n", 5538296Sdg sc->tulip_if.if_name, sc->tulip_if.if_unit); 5548296Sdg sc->tulip_cmdmode |= TULIP_CMD_PORTSELECT 5558296Sdg |TULIP_CMD_PCSFUNCTION|TULIP_CMD_SCRAMBLER; 5568296Sdg sc->tulip_cmdmode &= ~TULIP_CMD_TXTHRSHLDCTL; 5578296Sdg sc->tulip_flags |= TULIP_ALTPHYS; 55811070Sdg sc->tulip_media = TULIP_MEDIA_100BASET; 5598296Sdg} 5608296Sdg 5618296Sdgstatic const tulip_boardsw_t tulip_dc21140_cogent_em100_boardsw = { 5628296Sdg TULIP_DC21140_COGENT_EM100, 56311070Sdg "Cogent EM100 ", 5648296Sdg tulip_dc21140_cogent_em100_media_probe, 5658296Sdg tulip_dc21140_cogent_em100_media_select 5668296Sdg}; 5678296Sdg 56811070Sdg 5698296Sdgstatic int 57011070Sdgtulip_dc21140_znyx_zx34x_media_probe( 57111070Sdg tulip_softc_t * const sc) 57211070Sdg{ 57311070Sdg TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_ZX34X_PINS); 57411070Sdg TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_ZX34X_INIT); 57511070Sdg TULIP_WRITE_CSR(sc, csr_command, 57611070Sdg TULIP_READ_CSR(sc, csr_command) | TULIP_CMD_PORTSELECT | 57711070Sdg TULIP_CMD_PCSFUNCTION | TULIP_CMD_SCRAMBLER | TULIP_CMD_MUSTBEONE); 57811070Sdg TULIP_WRITE_CSR(sc, csr_command, 57911070Sdg TULIP_READ_CSR(sc, csr_command) & ~TULIP_CMD_TXTHRSHLDCTL); 58011070Sdg DELAY(1000000); 58111070Sdg 58211070Sdg return (TULIP_READ_CSR(sc, csr_gp) & TULIP_GP_ZX34X_OK10); 58311070Sdg} 58411070Sdg 58511070Sdgstatic void 58611070Sdgtulip_dc21140_znyx_zx34x_media_select( 58711070Sdg tulip_softc_t * const sc) 58811070Sdg{ 58911070Sdg sc->tulip_cmdmode |= TULIP_CMD_STOREFWD|TULIP_CMD_MUSTBEONE; 59011070Sdg TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_ZX34X_PINS); 59111070Sdg TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_ZX34X_INIT); 59211070Sdg if (sc->tulip_if.if_flags & IFF_ALTPHYS) { 59311070Sdg if ((sc->tulip_flags & TULIP_ALTPHYS) == 0) 59411070Sdg printf("%s%d: enabling 100baseTX UTP port\n", 59511070Sdg sc->tulip_if.if_name, sc->tulip_if.if_unit); 59611070Sdg sc->tulip_cmdmode |= TULIP_CMD_PORTSELECT 59711070Sdg |TULIP_CMD_PCSFUNCTION|TULIP_CMD_SCRAMBLER; 59811070Sdg sc->tulip_cmdmode &= ~TULIP_CMD_TXTHRSHLDCTL; 59911070Sdg sc->tulip_flags |= TULIP_ALTPHYS; 60011070Sdg sc->tulip_media = TULIP_MEDIA_100BASET; 60111070Sdg } else { 60211070Sdg if (sc->tulip_flags & TULIP_ALTPHYS) 60311070Sdg printf("%s%d: enabling 10baseT UTP port\n", 60411070Sdg sc->tulip_if.if_name, sc->tulip_if.if_unit); 60511070Sdg sc->tulip_cmdmode &= ~(TULIP_CMD_PORTSELECT 60611070Sdg |TULIP_CMD_PCSFUNCTION|TULIP_CMD_SCRAMBLER); 60711070Sdg sc->tulip_cmdmode |= TULIP_CMD_TXTHRSHLDCTL; 60811070Sdg sc->tulip_flags &= ~TULIP_ALTPHYS; 60911070Sdg sc->tulip_media = TULIP_MEDIA_10BASET; 61011070Sdg } 61111070Sdg} 61211070Sdg 61311070Sdgstatic const tulip_boardsw_t tulip_dc21140_znyx_zx34x_boardsw = { 61411070Sdg TULIP_DC21140_ZNYX_ZX34X, 61511070Sdg "ZNYX ZX34X ", 61611070Sdg tulip_dc21140_znyx_zx34x_media_probe, 61711070Sdg tulip_dc21140_znyx_zx34x_media_select 61811070Sdg}; 61911070Sdg 62011070Sdgstatic int 6217791Sdgtulip_dc21140_de500_media_probe( 6228754Sdg tulip_softc_t * const sc) 6237791Sdg{ 6248754Sdg TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_DE500_PINS); 6258296Sdg DELAY(1000); 6268754Sdg TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_DE500_HALFDUPLEX); 6278754Sdg if ((TULIP_READ_CSR(sc, csr_gp) & 6288754Sdg (TULIP_GP_DE500_NOTOK_100|TULIP_GP_DE500_NOTOK_10)) != 6298754Sdg (TULIP_GP_DE500_NOTOK_100|TULIP_GP_DE500_NOTOK_10)) 6308754Sdg return (TULIP_READ_CSR(sc, csr_gp) & TULIP_GP_DE500_NOTOK_100) != 0; 6318754Sdg TULIP_WRITE_CSR(sc, csr_gp, 6328754Sdg TULIP_GP_DE500_HALFDUPLEX|TULIP_GP_DE500_FORCE_100); 6338754Sdg TULIP_WRITE_CSR(sc, csr_command, 6348754Sdg TULIP_READ_CSR(sc, csr_command) | TULIP_CMD_PORTSELECT | 6358754Sdg TULIP_CMD_PCSFUNCTION | TULIP_CMD_SCRAMBLER | TULIP_CMD_MUSTBEONE); 6368754Sdg TULIP_WRITE_CSR(sc, csr_command, 6378754Sdg TULIP_READ_CSR(sc, csr_command) & ~TULIP_CMD_TXTHRSHLDCTL); 6387791Sdg DELAY(1000000); 6398754Sdg return (TULIP_READ_CSR(sc, csr_gp) & TULIP_GP_DE500_NOTOK_100) != 0; 6407791Sdg} 6417791Sdg 6427791Sdgstatic void 6437791Sdgtulip_dc21140_de500_media_select( 6448754Sdg tulip_softc_t * const sc) 6457791Sdg{ 6467791Sdg sc->tulip_cmdmode |= TULIP_CMD_STOREFWD|TULIP_CMD_MUSTBEONE; 6478754Sdg TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_DE500_PINS); 6487791Sdg if (sc->tulip_if.if_flags & IFF_ALTPHYS) { 6497791Sdg if ((sc->tulip_flags & TULIP_ALTPHYS) == 0) 6507791Sdg printf("%s%d: enabling 100baseTX UTP port\n", 6517791Sdg sc->tulip_if.if_name, sc->tulip_if.if_unit); 6527791Sdg sc->tulip_cmdmode |= TULIP_CMD_PORTSELECT 6537791Sdg |TULIP_CMD_PCSFUNCTION|TULIP_CMD_SCRAMBLER; 6547791Sdg sc->tulip_cmdmode &= ~TULIP_CMD_TXTHRSHLDCTL; 6557791Sdg sc->tulip_flags |= TULIP_ALTPHYS; 65611070Sdg sc->tulip_media = TULIP_MEDIA_100BASET; 6578754Sdg TULIP_WRITE_CSR(sc, csr_gp, 6588754Sdg TULIP_GP_DE500_HALFDUPLEX|TULIP_GP_DE500_FORCE_100); 6597791Sdg } else { 6607791Sdg if (sc->tulip_flags & TULIP_ALTPHYS) 6617791Sdg printf("%s%d: enabling 10baseT UTP port\n", 6627791Sdg sc->tulip_if.if_name, sc->tulip_if.if_unit); 6637791Sdg sc->tulip_cmdmode &= ~(TULIP_CMD_PORTSELECT 6647791Sdg |TULIP_CMD_PCSFUNCTION|TULIP_CMD_SCRAMBLER); 6657791Sdg sc->tulip_cmdmode |= TULIP_CMD_TXTHRSHLDCTL; 6667791Sdg sc->tulip_flags &= ~TULIP_ALTPHYS; 66711070Sdg sc->tulip_media = TULIP_MEDIA_10BASET; 6688754Sdg TULIP_WRITE_CSR(sc, csr_gp, TULIP_GP_DE500_HALFDUPLEX); 6697791Sdg } 6707791Sdg} 6717791Sdg 6727791Sdgstatic const tulip_boardsw_t tulip_dc21140_de500_boardsw = { 6737791Sdg TULIP_DC21140_DEC_DE500, "Digital DE500 ", 6747791Sdg tulip_dc21140_de500_media_probe, 6757791Sdg tulip_dc21140_de500_media_select 6767791Sdg}; 6777791Sdg 67811070Sdgstatic int 67911070Sdgtulip_dc21041_media_probe( 68011070Sdg tulip_softc_t * const sc) 68111070Sdg{ 68211070Sdg return 0; 68311070Sdg} 68411070Sdg 6858754Sdgstatic void 68611070Sdgtulip_dc21041_media_select( 68711070Sdg tulip_softc_t * const sc) 68811070Sdg{ 68911070Sdg sc->tulip_cmdmode |= TULIP_CMD_CAPTREFFCT|TULIP_CMD_ENHCAPTEFFCT 69011070Sdg /* |TULIP_CMD_FULLDUPLEX */ |TULIP_CMD_THRSHLD160; 69111070Sdg sc->tulip_intrmask |= TULIP_STS_NORMALINTR|TULIP_STS_GPTIMEOUT 69211070Sdg |TULIP_STS_ABNRMLINTR|TULIP_STS_LINKPASS|TULIP_STS_LINKFAIL; 69311070Sdg if (sc->tulip_if.if_flags & IFF_ALTPHYS) { 69411070Sdg if ((sc->tulip_flags & TULIP_ALTPHYS) == 0) { 69511070Sdg sc->tulip_media = TULIP_MEDIA_UNKNOWN; 69611070Sdg sc->tulip_flags &= ~(TULIP_TXPROBE_OK|TULIP_TXPROBE_ACTIVE); 69711070Sdg sc->tulip_flags |= TULIP_ALTPHYS|TULIP_WANTRXACT; 69811070Sdg sc->tulip_probe_state = TULIP_PROBE_INACTIVE; 69911070Sdg } 70011070Sdg } else { 70111070Sdg if (sc->tulip_flags & TULIP_ALTPHYS) { 70211070Sdg sc->tulip_media = TULIP_MEDIA_UNKNOWN; 70311070Sdg sc->tulip_flags &= ~(TULIP_TXPROBE_OK|TULIP_TXPROBE_ACTIVE|TULIP_ALTPHYS); 70411070Sdg sc->tulip_flags |= TULIP_WANTRXACT; 70511070Sdg sc->tulip_probe_state = TULIP_PROBE_INACTIVE; 70611070Sdg } 70711070Sdg } 70811070Sdg 70911070Sdg if (TULIP_READ_CSR(sc, csr_sia_status) & TULIP_SIASTS_LINKFAIL) { 71011070Sdg if (sc->tulip_media == TULIP_MEDIA_10BASET) { 71111070Sdg sc->tulip_media = TULIP_MEDIA_UNKNOWN; 71211070Sdg } else if (sc->tulip_media == TULIP_MEDIA_BNC) { 71311070Sdg sc->tulip_intrmask &= ~TULIP_STS_GPTIMEOUT; 71411070Sdg TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_SIACONN_RESET); 71511070Sdg TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_DC21041_SIACONN_BNC); 71611070Sdg TULIP_WRITE_CSR(sc, csr_sia_tx_rx, TULIP_DC21041_SIATXRX_BNC); 71711070Sdg TULIP_WRITE_CSR(sc, csr_sia_general, TULIP_DC21041_SIAGEN_BNC); 71811070Sdg return; 71911070Sdg } else if (sc->tulip_media == TULIP_MEDIA_AUI) { 72011070Sdg sc->tulip_intrmask &= ~TULIP_STS_GPTIMEOUT; 72111070Sdg TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_SIACONN_RESET); 72211070Sdg TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_DC21041_SIACONN_AUI); 72311070Sdg TULIP_WRITE_CSR(sc, csr_sia_tx_rx, TULIP_DC21041_SIATXRX_AUI); 72411070Sdg TULIP_WRITE_CSR(sc, csr_sia_general, TULIP_DC21041_SIAGEN_AUI); 72511070Sdg return; 72611070Sdg } 72711070Sdg 72811070Sdg switch (sc->tulip_probe_state) { 72911070Sdg case TULIP_PROBE_INACTIVE: { 73011070Sdg TULIP_WRITE_CSR(sc, csr_command, sc->tulip_cmdmode); 73111070Sdg sc->tulip_if.if_flags |= IFF_OACTIVE; 73211070Sdg sc->tulip_gpticks = 200; 73311070Sdg sc->tulip_probe_state = TULIP_PROBE_10BASET; 73411070Sdg TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_SIACONN_RESET); 73511070Sdg TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_DC21041_SIACONN_10BASET); 73611070Sdg TULIP_WRITE_CSR(sc, csr_sia_tx_rx, TULIP_DC21041_SIATXRX_10BASET); 73711070Sdg TULIP_WRITE_CSR(sc, csr_sia_general, TULIP_DC21041_SIAGEN_10BASET); 73811070Sdg TULIP_WRITE_CSR(sc, csr_gp_timer, 12000000 / 204800); /* 120 ms */ 73911070Sdg break; 74011070Sdg } 74111070Sdg case TULIP_PROBE_10BASET: { 74211070Sdg if (--sc->tulip_gpticks > 0) { 74311070Sdg if ((TULIP_READ_CSR(sc, csr_sia_status) & TULIP_SIASTS_OTHERRXACTIVITY) == 0) { 74411070Sdg TULIP_WRITE_CSR(sc, csr_gp_timer, 12000000 / 204800); /* 120 ms */ 74511070Sdg TULIP_WRITE_CSR(sc, csr_intr, sc->tulip_intrmask); 74611070Sdg break; 74711070Sdg } 74811070Sdg } 74911070Sdg sc->tulip_gpticks = 4; 75011070Sdg if (TULIP_READ_CSR(sc, csr_sia_status) & TULIP_SIASTS_OTHERRXACTIVITY) { 75111070Sdg sc->tulip_probe_state = TULIP_PROBE_BNC; 75211070Sdg TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_SIACONN_RESET); 75311070Sdg TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_DC21041_SIACONN_BNC); 75411070Sdg TULIP_WRITE_CSR(sc, csr_sia_tx_rx, TULIP_DC21041_SIATXRX_BNC); 75511070Sdg TULIP_WRITE_CSR(sc, csr_sia_general, TULIP_DC21041_SIAGEN_BNC); 75611070Sdg TULIP_WRITE_CSR(sc, csr_gp_timer, 100000000 / 204800); /* 100 ms */ 75711070Sdg } else { 75811070Sdg sc->tulip_probe_state = TULIP_PROBE_AUI; 75911070Sdg TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_SIACONN_RESET); 76011070Sdg TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_DC21041_SIACONN_AUI); 76111070Sdg TULIP_WRITE_CSR(sc, csr_sia_tx_rx, TULIP_DC21041_SIATXRX_AUI); 76211070Sdg TULIP_WRITE_CSR(sc, csr_sia_general, TULIP_DC21041_SIAGEN_AUI); 76311070Sdg TULIP_WRITE_CSR(sc, csr_gp_timer, 100000000 / 204800); /* 100 ms */ 76411070Sdg } 76511070Sdg break; 76611070Sdg } 76711070Sdg case TULIP_PROBE_BNC: 76811070Sdg case TULIP_PROBE_AUI: { 76911070Sdg if (sc->tulip_flags & TULIP_TXPROBE_OK) { 77011070Sdg sc->tulip_intrmask &= ~TULIP_STS_GPTIMEOUT; 77111070Sdg sc->tulip_flags &= ~(TULIP_TXPROBE_OK|TULIP_TXPROBE_ACTIVE); 77211070Sdg TULIP_WRITE_CSR(sc, csr_gp_timer, 0); /* disable */ 77311070Sdg if ((sc->tulip_probe_state == TULIP_PROBE_AUI 77411070Sdg && sc->tulip_media != TULIP_MEDIA_AUI) 77511070Sdg || (sc->tulip_probe_state == TULIP_PROBE_BNC 77611070Sdg && sc->tulip_media != TULIP_MEDIA_AUI)) { 77711070Sdg printf("%s%d: enabling %s port\n", 77811070Sdg sc->tulip_if.if_name, sc->tulip_if.if_unit, 77911070Sdg sc->tulip_probe_state == TULIP_PROBE_BNC 78011070Sdg ? "Thinwire/BNC" : "AUI"); 78111070Sdg if (sc->tulip_probe_state == TULIP_PROBE_AUI) 78211070Sdg sc->tulip_media = TULIP_MEDIA_AUI; 78311070Sdg else if (sc->tulip_probe_state == TULIP_PROBE_BNC) 78411070Sdg sc->tulip_media = TULIP_MEDIA_BNC; 78511070Sdg } 78611070Sdg sc->tulip_probe_state = TULIP_PROBE_INACTIVE; 78711070Sdg break; 78811070Sdg } 78911070Sdg if ((sc->tulip_flags & TULIP_WANTRXACT) == 0 79011070Sdg || (TULIP_READ_CSR(sc, csr_sia_status) & TULIP_SIASTS_RXACTIVITY)) { 79111070Sdg if ((sc->tulip_flags & TULIP_TXPROBE_ACTIVE) == 0) { 79211070Sdg struct mbuf *m; 79311070Sdg /* 79411070Sdg * Before we are sure this is the right media we need 79511070Sdg * to send a small packet to make sure there's carrier. 79611070Sdg * Strangely, BNC and AUI will 'see" receive data if 79711070Sdg * either is connected so the transmit is the only way 79811070Sdg * to verify the connectivity. 79911070Sdg */ 80011070Sdg MGETHDR(m, M_DONTWAIT, MT_DATA); 80111070Sdg if (m == NULL) { 80211070Sdg TULIP_WRITE_CSR(sc, csr_gp_timer, 100000000 / 204800); /* 100 ms */ 80311070Sdg break; 80411070Sdg } 80511070Sdg /* 80611070Sdg * Construct a LLC TEST message which will point to ourselves. 80711070Sdg */ 80811070Sdg bcopy(sc->tulip_hwaddr, mtod(m, struct ether_header *)->ether_dhost, 6); 80911070Sdg bcopy(sc->tulip_hwaddr, mtod(m, struct ether_header *)->ether_shost, 6); 81011070Sdg mtod(m, struct ether_header *)->ether_type = htons(3); 81111070Sdg mtod(m, unsigned char *)[14] = 0; 81211070Sdg mtod(m, unsigned char *)[15] = 0; 81311070Sdg mtod(m, unsigned char *)[16] = 0xE3; /* LLC Class1 TEST (no poll) */ 81411070Sdg m->m_len = m->m_pkthdr.len = sizeof(struct ether_header) + 3; 81511070Sdg /* 81611070Sdg * send it! 81711070Sdg */ 81811070Sdg sc->tulip_flags |= TULIP_TXPROBE_ACTIVE; 81911070Sdg sc->tulip_flags &= ~TULIP_TXPROBE_OK; 82011070Sdg sc->tulip_cmdmode |= TULIP_CMD_TXRUN; 82111070Sdg TULIP_WRITE_CSR(sc, csr_command, sc->tulip_cmdmode); 82211070Sdg IF_PREPEND(&sc->tulip_if.if_snd, m); 82311070Sdg tulip_start(&sc->tulip_if); 82411070Sdg break; 82511070Sdg } 82611070Sdg sc->tulip_flags &= ~TULIP_TXPROBE_ACTIVE; 82711070Sdg } 82811070Sdg /* 82911070Sdg * Take 2 passes through before deciding to not 83011070Sdg * wait for receive activity. Then take another 83111070Sdg * two passes before spitting out a warning. 83211070Sdg */ 83311070Sdg if (sc->tulip_gpticks > 0 && --sc->tulip_gpticks == 0) { 83411070Sdg if (sc->tulip_flags & TULIP_WANTRXACT) { 83511070Sdg sc->tulip_flags &= ~TULIP_WANTRXACT; 83611070Sdg sc->tulip_gpticks = 4; 83711070Sdg } else { 83811070Sdg printf("%s%d: autosense failed: cable problem?\n", 83911070Sdg sc->tulip_name, sc->tulip_unit); 84011070Sdg } 84111070Sdg } 84211070Sdg /* 84311070Sdg * Since this media failed to probe, try the other one. 84411070Sdg */ 84511070Sdg if (sc->tulip_probe_state == TULIP_PROBE_AUI) { 84611070Sdg sc->tulip_probe_state = TULIP_PROBE_BNC; 84711070Sdg TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_SIACONN_RESET); 84811070Sdg TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_DC21041_SIACONN_BNC); 84911070Sdg TULIP_WRITE_CSR(sc, csr_sia_tx_rx, TULIP_DC21041_SIATXRX_BNC); 85011070Sdg TULIP_WRITE_CSR(sc, csr_sia_general, TULIP_DC21041_SIAGEN_BNC); 85111070Sdg TULIP_WRITE_CSR(sc, csr_gp_timer, 100000000 / 204800); /* 100 ms */ 85211070Sdg } else { 85311070Sdg sc->tulip_probe_state = TULIP_PROBE_AUI; 85411070Sdg TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_SIACONN_RESET); 85511070Sdg TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_DC21041_SIACONN_AUI); 85611070Sdg TULIP_WRITE_CSR(sc, csr_sia_tx_rx, TULIP_DC21041_SIATXRX_AUI); 85711070Sdg TULIP_WRITE_CSR(sc, csr_sia_general, TULIP_DC21041_SIAGEN_AUI); 85811070Sdg TULIP_WRITE_CSR(sc, csr_gp_timer, 100000000 / 204800); /* 100 ms */ 85911070Sdg } 86011070Sdg TULIP_WRITE_CSR(sc, csr_intr, sc->tulip_intrmask); 86111070Sdg break; 86211070Sdg } 86311070Sdg } 86411070Sdg } else { 86511070Sdg /* 86611070Sdg * If the link has passed LinkPass, 10baseT is the 86711070Sdg * proper media to use. 86811070Sdg */ 86911070Sdg if (sc->tulip_media != TULIP_MEDIA_10BASET) 87011070Sdg printf("%s%d: enabling 10baseT/UTP port\n", 87111070Sdg sc->tulip_if.if_name, sc->tulip_if.if_unit); 87211070Sdg if (sc->tulip_media != TULIP_MEDIA_10BASET 87311070Sdg || (sc->tulip_flags & TULIP_INRESET)) { 87411070Sdg sc->tulip_media = TULIP_MEDIA_10BASET; 87511070Sdg TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_SIACONN_RESET); 87611070Sdg TULIP_WRITE_CSR(sc, csr_sia_connectivity, TULIP_DC21041_SIACONN_10BASET); 87711070Sdg TULIP_WRITE_CSR(sc, csr_sia_tx_rx, TULIP_DC21041_SIATXRX_10BASET); 87811070Sdg TULIP_WRITE_CSR(sc, csr_sia_general, TULIP_DC21041_SIAGEN_10BASET); 87911070Sdg } 88011070Sdg TULIP_WRITE_CSR(sc, csr_gp_timer, 0); /* disable */ 88111070Sdg sc->tulip_gpticks = 1; 88211070Sdg sc->tulip_probe_state = TULIP_PROBE_10BASET; 88311070Sdg sc->tulip_intrmask &= ~TULIP_STS_GPTIMEOUT; 88411070Sdg sc->tulip_if.if_flags &= ~IFF_OACTIVE; 88511070Sdg } 88611070Sdg TULIP_WRITE_CSR(sc, csr_intr, sc->tulip_intrmask); 88711070Sdg} 88811070Sdg 88911070Sdgstatic const tulip_boardsw_t tulip_dc21041_boardsw = { 89011070Sdg TULIP_DC21041_GENERIC, 89111070Sdg "", 89211070Sdg tulip_dc21041_media_probe, 89311070Sdg tulip_dc21041_media_select 89411070Sdg}; 89511070Sdg 89611070Sdgstatic const tulip_boardsw_t tulip_dc21041_de450_boardsw = { 89711070Sdg TULIP_DC21041_DE450, 89811070Sdg "Digital DE450 ", 89911070Sdg tulip_dc21041_media_probe, 90011070Sdg tulip_dc21041_media_select 90111070Sdg}; 90211070Sdg 90311070Sdgstatic void 9043278Swollmantulip_reset( 9058754Sdg tulip_softc_t * const sc) 9063278Swollman{ 9073278Swollman tulip_ringinfo_t *ri; 9083278Swollman tulip_desc_t *di; 9093278Swollman 9108754Sdg TULIP_WRITE_CSR(sc, csr_busmode, TULIP_BUSMODE_SWRESET); 91111070Sdg DELAY(10); /* Wait 10 microsends (actually 50 PCI cycles but at 9123278Swollman 33MHz that comes to two microseconds but wait a 9133278Swollman bit longer anyways) */ 9143278Swollman 91511070Sdg sc->tulip_flags |= TULIP_INRESET; 91611070Sdg sc->tulip_intrmask = 0; 91711070Sdg TULIP_WRITE_CSR(sc, csr_intr, sc->tulip_intrmask); 9187791Sdg 9198754Sdg TULIP_WRITE_CSR(sc, csr_txlist, vtophys(&sc->tulip_txinfo.ri_first[0])); 9208754Sdg TULIP_WRITE_CSR(sc, csr_rxlist, vtophys(&sc->tulip_rxinfo.ri_first[0])); 9218754Sdg TULIP_WRITE_CSR(sc, csr_busmode, 92211070Sdg ((1 << TULIP_BURSTSIZE(sc->tulip_unit)) << 8)|TULIP_BUSMODE_CACHE_ALIGN8 9238754Sdg |(BYTE_ORDER != LITTLE_ENDIAN ? TULIP_BUSMODE_BIGENDIAN : 0)); 9243278Swollman 9253278Swollman sc->tulip_txq.ifq_maxlen = TULIP_TXDESCS; 9263278Swollman /* 9273278Swollman * Free all the mbufs that were on the transmit ring. 9283278Swollman */ 9293278Swollman for (;;) { 9303278Swollman struct mbuf *m; 9313278Swollman IF_DEQUEUE(&sc->tulip_txq, m); 9323278Swollman if (m == NULL) 9333278Swollman break; 9343278Swollman m_freem(m); 9353278Swollman } 9363278Swollman 9373278Swollman ri = &sc->tulip_txinfo; 9383278Swollman ri->ri_nextin = ri->ri_nextout = ri->ri_first; 9393278Swollman ri->ri_free = ri->ri_max; 9403278Swollman for (di = ri->ri_first; di < ri->ri_last; di++) 9413278Swollman di->d_status = 0; 9423278Swollman 9433278Swollman /* 94411070Sdg * We need to collect all the mbufs were on the 9453278Swollman * receive ring before we reinit it either to put 9463278Swollman * them back on or to know if we have to allocate 9473278Swollman * more. 9483278Swollman */ 9493278Swollman ri = &sc->tulip_rxinfo; 9503278Swollman ri->ri_nextin = ri->ri_nextout = ri->ri_first; 9513278Swollman ri->ri_free = ri->ri_max; 9527689Sdg for (di = ri->ri_first; di < ri->ri_last; di++) { 9537689Sdg di->d_status = 0; 9547689Sdg di->d_length1 = 0; di->d_addr1 = 0; 9553278Swollman di->d_length2 = 0; di->d_addr2 = 0; 9563278Swollman } 9577689Sdg for (;;) { 9587689Sdg struct mbuf *m; 9597689Sdg IF_DEQUEUE(&sc->tulip_rxq, m); 9607689Sdg if (m == NULL) 9617689Sdg break; 9627689Sdg m_freem(m); 9637689Sdg } 9643278Swollman 96511070Sdg (*sc->tulip_boardsw->bd_media_select)(sc); 96611070Sdg 96711070Sdg sc->tulip_intrmask |= TULIP_STS_NORMALINTR|TULIP_STS_RXINTR|TULIP_STS_TXINTR 9683278Swollman |TULIP_STS_ABNRMLINTR|TULIP_STS_SYSERROR|TULIP_STS_TXSTOPPED 9693278Swollman |TULIP_STS_TXBABBLE|TULIP_STS_LINKFAIL|TULIP_STS_RXSTOPPED; 97011070Sdg sc->tulip_flags &= ~(TULIP_DOINGSETUP|TULIP_WANTSETUP|TULIP_INRESET); 9713278Swollman tulip_addr_filter(sc); 9723278Swollman} 9733278Swollman 9748754Sdgstatic void 9753278Swollmantulip_init( 9768754Sdg tulip_softc_t * const sc) 9773278Swollman{ 9783278Swollman if (sc->tulip_if.if_flags & IFF_UP) { 9793278Swollman sc->tulip_if.if_flags |= IFF_RUNNING; 9803278Swollman if (sc->tulip_if.if_flags & IFF_PROMISC) { 9813278Swollman sc->tulip_cmdmode |= TULIP_CMD_PROMISCUOUS; 9823278Swollman } else { 9833278Swollman sc->tulip_cmdmode &= ~TULIP_CMD_PROMISCUOUS; 9843278Swollman if (sc->tulip_if.if_flags & IFF_ALLMULTI) { 9853278Swollman sc->tulip_cmdmode |= TULIP_CMD_ALLMULTI; 9863278Swollman } else { 9873278Swollman sc->tulip_cmdmode &= ~TULIP_CMD_ALLMULTI; 9883278Swollman } 9893278Swollman } 9903278Swollman sc->tulip_cmdmode |= TULIP_CMD_TXRUN; 9913278Swollman if ((sc->tulip_flags & TULIP_WANTSETUP) == 0) { 9927689Sdg tulip_rx_intr(sc); 9933278Swollman sc->tulip_cmdmode |= TULIP_CMD_RXRUN; 9943278Swollman sc->tulip_intrmask |= TULIP_STS_RXSTOPPED; 9953278Swollman } else { 9963278Swollman sc->tulip_intrmask &= ~TULIP_STS_RXSTOPPED; 9973278Swollman tulip_start(&sc->tulip_if); 9983278Swollman } 9998754Sdg TULIP_WRITE_CSR(sc, csr_intr, sc->tulip_intrmask); 10008754Sdg TULIP_WRITE_CSR(sc, csr_command, sc->tulip_cmdmode); 10013278Swollman } else { 10028754Sdg tulip_reset(sc); 10033278Swollman sc->tulip_if.if_flags &= ~IFF_RUNNING; 10043278Swollman } 10053278Swollman} 10063278Swollman 10073278Swollman 10083278Swollman#if TULIP_CHECK_RXCRC 10093278Swollmanstatic unsigned 10103278Swollmantulip_crc32( 10113278Swollman u_char *addr, 10123278Swollman int len) 10133278Swollman{ 10143278Swollman unsigned int crc = 0xFFFFFFFF; 10153278Swollman static unsigned int crctbl[256]; 10163278Swollman int idx; 10173278Swollman static int done; 10183278Swollman /* 10193278Swollman * initialize the multicast address CRC table 10203278Swollman */ 10213278Swollman for (idx = 0; !done && idx < 256; idx++) { 10223278Swollman unsigned int tmp = idx; 10233278Swollman tmp = (tmp >> 1) ^ (tmp & 1 ? TULIP_CRC32_POLY : 0); /* XOR */ 10243278Swollman tmp = (tmp >> 1) ^ (tmp & 1 ? TULIP_CRC32_POLY : 0); /* XOR */ 10253278Swollman tmp = (tmp >> 1) ^ (tmp & 1 ? TULIP_CRC32_POLY : 0); /* XOR */ 10263278Swollman tmp = (tmp >> 1) ^ (tmp & 1 ? TULIP_CRC32_POLY : 0); /* XOR */ 10273278Swollman tmp = (tmp >> 1) ^ (tmp & 1 ? TULIP_CRC32_POLY : 0); /* XOR */ 10283278Swollman tmp = (tmp >> 1) ^ (tmp & 1 ? TULIP_CRC32_POLY : 0); /* XOR */ 10293278Swollman tmp = (tmp >> 1) ^ (tmp & 1 ? TULIP_CRC32_POLY : 0); /* XOR */ 10303278Swollman tmp = (tmp >> 1) ^ (tmp & 1 ? TULIP_CRC32_POLY : 0); /* XOR */ 10313278Swollman crctbl[idx] = tmp; 10323278Swollman } 10333278Swollman done = 1; 10343278Swollman 10353278Swollman while (len-- > 0) 10363278Swollman crc = (crc >> 8) ^ crctbl[*addr++] ^ crctbl[crc & 0xFF]; 10373278Swollman 10383278Swollman return crc; 10393278Swollman} 10403278Swollman#endif 10413278Swollman 10423278Swollmanstatic void 10433278Swollmantulip_rx_intr( 10448754Sdg tulip_softc_t * const sc) 10453278Swollman{ 10468754Sdg tulip_ringinfo_t * const ri = &sc->tulip_rxinfo; 10478754Sdg struct ifnet * const ifp = &sc->tulip_if; 10483278Swollman 10494322Sdg for (;;) { 10507689Sdg struct ether_header eh; 10517689Sdg tulip_desc_t *eop = ri->ri_nextin; 10527689Sdg int total_len = 0; 10537689Sdg struct mbuf *m = NULL; 10547689Sdg int accept = 0; 10553278Swollman 10567689Sdg if (sc->tulip_rxq.ifq_len < TULIP_RXQ_TARGET) 10577689Sdg goto queue_mbuf; 10587689Sdg 10597689Sdg if (((volatile tulip_desc_t *) eop)->d_status & TULIP_DSTS_OWNER) 10607689Sdg break; 106111070Sdg 10623278Swollman total_len = ((eop->d_status >> 16) & 0x7FF) - 4; 10637689Sdg IF_DEQUEUE(&sc->tulip_rxq, m); 10643278Swollman if ((eop->d_status & TULIP_DSTS_ERRSUM) == 0) { 10653278Swollman 10663278Swollman#if TULIP_CHECK_RXCRC 10677689Sdg unsigned crc = tulip_crc32(mtod(m, unsigned char *), total_len); 10683278Swollman if (~crc != *((unsigned *) &bufaddr[total_len])) { 10698754Sdg printf("%s%d: bad rx crc: %08x [rx] != %08x\n", 10708754Sdg sc->tulip_name, sc->tulip_unit, 10713278Swollman *((unsigned *) &bufaddr[total_len]), ~crc); 10723278Swollman goto next; 10733278Swollman } 10743278Swollman#endif 10757689Sdg eh = *mtod(m, struct ether_header *); 10763278Swollman#if NBPFILTER > 0 10778754Sdg if (sc->tulip_bpf != NULL) 10787689Sdg bpf_tap(sc->tulip_bpf, mtod(m, caddr_t), total_len); 10798754Sdg#endif 10808754Sdg if ((sc->tulip_if.if_flags & IFF_PROMISC) 10818754Sdg && (eh.ether_dhost[0] & 1) == 0 10828754Sdg && !TULIP_ADDREQUAL(eh.ether_dhost, sc->tulip_ac.ac_enaddr)) 10833278Swollman goto next; 10847689Sdg accept = 1; 10858754Sdg total_len -= sizeof(struct ether_header); 10863278Swollman } else { 10874322Sdg ifp->if_ierrors++; 10883278Swollman } 10897689Sdg next: 10904322Sdg ifp->if_ipackets++; 10917689Sdg if (++ri->ri_nextin == ri->ri_last) 10927689Sdg ri->ri_nextin = ri->ri_first; 10937689Sdg queue_mbuf: 10947689Sdg /* 10957689Sdg * Either we are priming the TULIP with mbufs (m == NULL) 10967689Sdg * or we are about to accept an mbuf for the upper layers 10977689Sdg * so we need to allocate an mbuf to replace it. If we 10987689Sdg * can't replace, then count it as an input error and reuse 10997689Sdg * the mbuf. 11007689Sdg */ 11017689Sdg if (accept || m == NULL) { 11027689Sdg struct mbuf *m0; 11037689Sdg MGETHDR(m0, M_DONTWAIT, MT_DATA); 11047689Sdg if (m0 != NULL) { 11058754Sdg#if defined(TULIP_COPY_RXDATA) 11068754Sdg if (!accept || total_len >= MHLEN) { 11078754Sdg#endif 11088754Sdg MCLGET(m0, M_DONTWAIT); 11098754Sdg if ((m0->m_flags & M_EXT) == 0) { 11108754Sdg m_freem(m0); 11118754Sdg m0 = NULL; 11128754Sdg } 11138754Sdg#if defined(TULIP_COPY_RXDATA) 11147689Sdg } 11158754Sdg#endif 11167689Sdg } 11177689Sdg if (accept) { 11187689Sdg if (m0 != NULL) { 11198296Sdg#if defined(__bsdi__) 11208296Sdg eh.ether_type = ntohs(eh.ether_type); 11218296Sdg#endif 11228754Sdg#if !defined(TULIP_COPY_RXDATA) 11238754Sdg m->m_data += sizeof(struct ether_header); 11248754Sdg m->m_len = m->m_pkthdr.len = total_len; 11258754Sdg m->m_pkthdr.rcvif = ifp; 11267689Sdg ether_input(ifp, &eh, m); 11277689Sdg m = m0; 11288754Sdg#else 11298754Sdg bcopy(mtod(m, caddr_t) + sizeof(struct ether_header), 11308754Sdg mtod(m0, caddr_t), total_len); 11318754Sdg m0->m_len = m0->m_pkthdr.len = total_len; 11328754Sdg m0->m_pkthdr.rcvif = ifp; 11338754Sdg ether_input(ifp, &eh, m0); 11348754Sdg#endif 11357689Sdg } else { 11367689Sdg ifp->if_ierrors++; 11377689Sdg } 11387689Sdg } else { 11397689Sdg m = m0; 11407689Sdg } 11413278Swollman } 11427689Sdg if (m == NULL) 11437689Sdg break; 11447689Sdg /* 11457689Sdg * Now give the buffer to the TULIP and save in our 11467689Sdg * receive queue. 11477689Sdg */ 11487689Sdg ri->ri_nextout->d_length1 = MCLBYTES - 4; 11497689Sdg ri->ri_nextout->d_addr1 = vtophys(mtod(m, caddr_t)); 11507689Sdg ri->ri_nextout->d_status = TULIP_DSTS_OWNER; 11517689Sdg if (++ri->ri_nextout == ri->ri_last) 11527689Sdg ri->ri_nextout = ri->ri_first; 11537689Sdg IF_ENQUEUE(&sc->tulip_rxq, m); 11543278Swollman } 11553278Swollman} 11563278Swollman 11573278Swollmanstatic int 11583278Swollmantulip_tx_intr( 11598754Sdg tulip_softc_t * const sc) 11603278Swollman{ 11618754Sdg tulip_ringinfo_t * const ri = &sc->tulip_txinfo; 11623278Swollman struct mbuf *m; 11633278Swollman int xmits = 0; 11643278Swollman 11653278Swollman while (ri->ri_free < ri->ri_max) { 11663278Swollman if (((volatile tulip_desc_t *) ri->ri_nextin)->d_status & TULIP_DSTS_OWNER) 11673278Swollman break; 11683278Swollman 11693278Swollman if (ri->ri_nextin->d_flag & TULIP_DFLAG_TxLASTSEG) { 11703278Swollman if (ri->ri_nextin->d_flag & TULIP_DFLAG_TxSETUPPKT) { 11713278Swollman /* 11723278Swollman * We've just finished processing a setup packet. 11733278Swollman * Mark that we can finished it. If there's not 11743278Swollman * another pending, startup the TULIP receiver. 11754772Sdg * Make sure we ack the RXSTOPPED so we won't get 11764772Sdg * an abormal interrupt indication. 11773278Swollman */ 11783278Swollman sc->tulip_flags &= ~TULIP_DOINGSETUP; 11793278Swollman if ((sc->tulip_flags & TULIP_WANTSETUP) == 0) { 11807689Sdg tulip_rx_intr(sc); 11813278Swollman sc->tulip_cmdmode |= TULIP_CMD_RXRUN; 11823278Swollman sc->tulip_intrmask |= TULIP_STS_RXSTOPPED; 11838754Sdg TULIP_WRITE_CSR(sc, csr_status, TULIP_STS_RXSTOPPED); 11848754Sdg TULIP_WRITE_CSR(sc, csr_command, sc->tulip_cmdmode); 11858754Sdg TULIP_WRITE_CSR(sc, csr_intr, sc->tulip_intrmask); 11863278Swollman } 11873278Swollman } else { 11883278Swollman IF_DEQUEUE(&sc->tulip_txq, m); 11893278Swollman m_freem(m); 11903278Swollman xmits++; 119111070Sdg if (sc->tulip_flags & TULIP_TXPROBE_ACTIVE) { 119211070Sdg if ((ri->ri_nextin->d_status & (TULIP_DSTS_TxNOCARR|TULIP_DSTS_TxEXCCOLL)) == 0) 119311070Sdg sc->tulip_flags |= TULIP_TXPROBE_OK; 119411070Sdg (*sc->tulip_boardsw->bd_media_select)(sc); 119511070Sdg } else { 119611070Sdg sc->tulip_if.if_collisions += 119711070Sdg (ri->ri_nextin->d_status & TULIP_DSTS_TxCOLLMASK) 119811070Sdg >> TULIP_DSTS_V_TxCOLLCNT; 119911070Sdg if (ri->ri_nextin->d_status & TULIP_DSTS_ERRSUM) 120011070Sdg sc->tulip_if.if_oerrors++; 120111070Sdg } 12023278Swollman } 12033278Swollman } 12043278Swollman 12053278Swollman if (++ri->ri_nextin == ri->ri_last) 12063278Swollman ri->ri_nextin = ri->ri_first; 12073278Swollman ri->ri_free++; 12083278Swollman sc->tulip_if.if_flags &= ~IFF_OACTIVE; 12093278Swollman } 12103278Swollman sc->tulip_if.if_opackets += xmits; 12113278Swollman return xmits; 12123278Swollman} 12133278Swollman 12148296Sdgstatic ifnet_ret_t 12153278Swollmantulip_start( 12168754Sdg struct ifnet * const ifp) 12173278Swollman{ 12188754Sdg tulip_softc_t * const sc = TULIP_UNIT_TO_SOFTC(ifp->if_unit); 12198754Sdg struct ifqueue * const ifq = &ifp->if_snd; 12208754Sdg tulip_ringinfo_t * const ri = &sc->tulip_txinfo; 12219349Sdg struct mbuf *m, *m0, *next_m0; 12223278Swollman 122311070Sdg if ((ifp->if_flags & IFF_RUNNING) == 0 122411070Sdg && (sc->tulip_flags & TULIP_TXPROBE_ACTIVE) == 0) 12253278Swollman return; 12263278Swollman 12273278Swollman for (;;) { 12288754Sdg tulip_desc_t *eop, *nextout; 12298754Sdg int segcnt, free, recopy; 12308754Sdg tulip_uint32_t d_status; 12318754Sdg 12323278Swollman if (sc->tulip_flags & TULIP_WANTSETUP) { 12333278Swollman if ((sc->tulip_flags & TULIP_DOINGSETUP) || ri->ri_free == 1) { 12343278Swollman ifp->if_flags |= IFF_OACTIVE; 12353278Swollman return; 12363278Swollman } 12373278Swollman bcopy(sc->tulip_setupdata, sc->tulip_setupbuf, 12383278Swollman sizeof(sc->tulip_setupbuf)); 12393278Swollman sc->tulip_flags &= ~TULIP_WANTSETUP; 12403278Swollman sc->tulip_flags |= TULIP_DOINGSETUP; 12413278Swollman ri->ri_free--; 12423278Swollman ri->ri_nextout->d_flag &= TULIP_DFLAG_ENDRING|TULIP_DFLAG_CHAIN; 12433278Swollman ri->ri_nextout->d_flag |= TULIP_DFLAG_TxFIRSTSEG|TULIP_DFLAG_TxLASTSEG 12443278Swollman |TULIP_DFLAG_TxSETUPPKT|TULIP_DFLAG_TxWANTINTR; 12453278Swollman if (sc->tulip_flags & TULIP_WANTHASH) 12463278Swollman ri->ri_nextout->d_flag |= TULIP_DFLAG_TxHASHFILT; 12473278Swollman ri->ri_nextout->d_length1 = sizeof(sc->tulip_setupbuf); 12483278Swollman ri->ri_nextout->d_addr1 = vtophys(sc->tulip_setupbuf); 12493278Swollman ri->ri_nextout->d_length2 = 0; 12503278Swollman ri->ri_nextout->d_addr2 = 0; 12513278Swollman ri->ri_nextout->d_status = TULIP_DSTS_OWNER; 12528754Sdg TULIP_WRITE_CSR(sc, csr_txpoll, 1); 12533278Swollman /* 12543278Swollman * Advance the ring for the next transmit packet. 12553278Swollman */ 12563278Swollman if (++ri->ri_nextout == ri->ri_last) 12573278Swollman ri->ri_nextout = ri->ri_first; 12588754Sdg /* 12598754Sdg * Make sure the next descriptor is owned by us since it 12608754Sdg * may have been set up above if we ran out of room in the 12618754Sdg * ring. 12628754Sdg */ 12638754Sdg ri->ri_nextout->d_status = 0; 12643278Swollman } 12658754Sdg 12663278Swollman IF_DEQUEUE(ifq, m); 12673278Swollman if (m == NULL) 12683278Swollman break; 12693278Swollman 12703278Swollman /* 12718754Sdg * Now we try to fill in our transmit descriptors. This is 12728754Sdg * a bit reminiscent of going on the Ark two by two 12738754Sdg * since each descriptor for the TULIP can describe 12748754Sdg * two buffers. So we advance through packet filling 12758754Sdg * each of the two entries at a time to to fill each 12768754Sdg * descriptor. Clear the first and last segment bits 12778754Sdg * in each descriptor (actually just clear everything 12788754Sdg * but the end-of-ring or chain bits) to make sure 12798754Sdg * we don't get messed up by previously sent packets. 12808754Sdg * 12818754Sdg * We may fail to put the entire packet on the ring if 12828754Sdg * there is either not enough ring entries free or if the 12838754Sdg * packet has more than MAX_TXSEG segments. In the former 12848754Sdg * case we will just wait for the ring to empty. In the 12858754Sdg * latter case we have to recopy. 12863278Swollman */ 12878754Sdg d_status = 0; 12888754Sdg recopy = 0; 12898754Sdg eop = nextout = ri->ri_nextout; 12908754Sdg m0 = m; 12918754Sdg segcnt = 0; 12928754Sdg free = ri->ri_free; 12938754Sdg do { 12948754Sdg int len = m0->m_len; 12958754Sdg caddr_t addr = mtod(m0, caddr_t); 12968754Sdg unsigned clsize = CLBYTES - (((u_long) addr) & (CLBYTES-1)); 12978754Sdg 12989349Sdg next_m0 = m0->m_next; 12998754Sdg while (len > 0) { 13008754Sdg unsigned slen = min(len, clsize); 13018754Sdg 13028754Sdg segcnt++; 13038754Sdg if (segcnt > TULIP_MAX_TXSEG) { 13048754Sdg recopy = 1; 13059349Sdg next_m0 = NULL; /* to break out of outside loop */ 13068754Sdg break; 13078754Sdg } 13088754Sdg if (segcnt & 1) { 13098754Sdg if (--free == 0) { 13108754Sdg /* 13118754Sdg * There's no more room but since nothing 13128754Sdg * has been committed at this point, just 13138754Sdg * show output is active, put back the 13148754Sdg * mbuf and return. 13158754Sdg */ 13168754Sdg ifp->if_flags |= IFF_OACTIVE; 13178754Sdg IF_PREPEND(ifq, m); 13188754Sdg return; 13198754Sdg } 13208754Sdg eop = nextout; 13218754Sdg if (++nextout == ri->ri_last) 13228754Sdg nextout = ri->ri_first; 13238754Sdg eop->d_flag &= TULIP_DFLAG_ENDRING|TULIP_DFLAG_CHAIN; 13248754Sdg eop->d_status = d_status; 13258754Sdg eop->d_addr1 = vtophys(addr); eop->d_length1 = slen; 13268754Sdg } else { 13278754Sdg /* 13288754Sdg * Fill in second half of descriptor 13298754Sdg */ 13308754Sdg eop->d_addr2 = vtophys(addr); eop->d_length2 = slen; 13318754Sdg } 13328754Sdg d_status = TULIP_DSTS_OWNER; 13338754Sdg len -= slen; 13348754Sdg addr += slen; 13358754Sdg clsize = CLBYTES; 13368754Sdg } 13379349Sdg } while ((m0 = next_m0) != NULL); 13388754Sdg 13398754Sdg /* 13408754Sdg * The packet exceeds the number of transmit buffer 13418754Sdg * entries that we can use for one packet, so we have 13428754Sdg * recopy it into one mbuf and then try again. 13438754Sdg */ 13448754Sdg if (recopy) { 13453278Swollman MGETHDR(m0, M_DONTWAIT, MT_DATA); 13463278Swollman if (m0 != NULL) { 13473278Swollman if (m->m_pkthdr.len > MHLEN) { 13483278Swollman MCLGET(m0, M_DONTWAIT); 13493278Swollman if ((m0->m_flags & M_EXT) == 0) { 13503278Swollman m_freem(m); 13518296Sdg m_freem(m0); 13523278Swollman continue; 13533278Swollman } 13543278Swollman } 13558296Sdg m_copydata(m, 0, m->m_pkthdr.len, mtod(m0, caddr_t)); 13563278Swollman m0->m_pkthdr.len = m0->m_len = m->m_pkthdr.len; 13573278Swollman IF_PREPEND(ifq, m0); 13583278Swollman } 13598754Sdg m_freem(m); 13608754Sdg continue; 13613278Swollman } 13623278Swollman 13633278Swollman /* 13648754Sdg * The descriptors have been filled in. Now get ready 13658754Sdg * to transmit. 13663278Swollman */ 13674772Sdg#if NBPFILTER > 0 13688754Sdg if (sc->tulip_bpf != NULL) 13698754Sdg bpf_mtap(sc->tulip_bpf, m); 13704772Sdg#endif 13718754Sdg IF_ENQUEUE(&sc->tulip_txq, m); 13728754Sdg 13733278Swollman /* 13748754Sdg * Make sure the next descriptor after this packet is owned 13758754Sdg * by us since it may have been set up above if we ran out 13768754Sdg * of room in the ring. 13778754Sdg */ 13788754Sdg nextout->d_status = 0; 13798754Sdg 13808754Sdg /* 13818754Sdg * If we only used the first segment of the last descriptor, 13828754Sdg * make sure the second segment will not be used. 13838754Sdg */ 13848754Sdg if (segcnt & 1) { 13858754Sdg eop->d_addr2 = 0; 13868754Sdg eop->d_length2 = 0; 13878754Sdg } 13888754Sdg 13898754Sdg /* 13908754Sdg * Mark the last and first segments, indicate we want a transmit 13918754Sdg * complete interrupt, give the descriptors to the TULIP, and tell 13923278Swollman * it to transmit! 13933278Swollman */ 13943278Swollman eop->d_flag |= TULIP_DFLAG_TxLASTSEG|TULIP_DFLAG_TxWANTINTR; 13953278Swollman 13968754Sdg /* 13978754Sdg * Note that ri->ri_nextout is still the start of the packet 13988754Sdg * and until we set the OWNER bit, we can still back out of 13998754Sdg * everything we have done. 14008754Sdg */ 14018754Sdg ri->ri_nextout->d_flag |= TULIP_DFLAG_TxFIRSTSEG; 14028754Sdg ri->ri_nextout->d_status = TULIP_DSTS_OWNER; 14038754Sdg 14048754Sdg /* 14058754Sdg * This advances the ring for us. 14068754Sdg */ 14078754Sdg ri->ri_nextout = nextout; 14088754Sdg ri->ri_free = free; 14098754Sdg 14108754Sdg TULIP_WRITE_CSR(sc, csr_txpoll, 1); 14113278Swollman } 14123278Swollman if (m != NULL) { 14133278Swollman ifp->if_flags |= IFF_OACTIVE; 14143278Swollman IF_PREPEND(ifq, m); 14153278Swollman } 14163278Swollman} 14173278Swollman 14183278Swollmanstatic int 14193278Swollmantulip_intr( 14208754Sdg void *arg) 14213278Swollman{ 142211070Sdg tulip_softc_t * sc = (tulip_softc_t *) arg; 14233278Swollman tulip_uint32_t csr; 142411070Sdg#if defined(__bsdi__) 142511070Sdg int progress = 1; 142611070Sdg#else 142711070Sdg int progress = 0; 142811070Sdg#endif 14293278Swollman 143011070Sdg do { 143111070Sdg while ((csr = TULIP_READ_CSR(sc, csr_status)) & (TULIP_STS_NORMALINTR|TULIP_STS_ABNRMLINTR)) { 143211070Sdg progress = 1; 143311070Sdg TULIP_WRITE_CSR(sc, csr_status, csr & sc->tulip_intrmask); 14343278Swollman 143511070Sdg if (csr & TULIP_STS_SYSERROR) { 143611070Sdg if ((csr & TULIP_STS_ERRORMASK) == TULIP_STS_ERR_PARITY) { 143711070Sdg tulip_reset(sc); 143811070Sdg tulip_init(sc); 143911070Sdg break; 144011070Sdg } 14413278Swollman } 144211070Sdg if (csr & (TULIP_STS_GPTIMEOUT|TULIP_STS_LINKPASS|TULIP_STS_LINKFAIL)) { 144311070Sdg if (sc->tulip_chipid == TULIP_DC21041) { 144411070Sdg (*sc->tulip_boardsw->bd_media_select)(sc); 144511070Sdg if (csr & (TULIP_STS_LINKPASS|TULIP_STS_LINKFAIL)) 144611070Sdg csr &= ~TULIP_STS_ABNRMLINTR; 144711070Sdg } 144811070Sdg } 144911070Sdg if (csr & TULIP_STS_ABNRMLINTR) { 145011070Sdg printf("%s%d: abnormal interrupt: 0x%05x [0x%05x]\n", 145111070Sdg sc->tulip_name, sc->tulip_unit, csr, csr & sc->tulip_intrmask); 145211070Sdg TULIP_WRITE_CSR(sc, csr_command, sc->tulip_cmdmode); 145311070Sdg } 145411070Sdg if (csr & TULIP_STS_RXINTR) 145511070Sdg tulip_rx_intr(sc); 145611070Sdg if (sc->tulip_txinfo.ri_free < sc->tulip_txinfo.ri_max) { 145711070Sdg tulip_tx_intr(sc); 145811070Sdg tulip_start(&sc->tulip_if); 145911070Sdg } 14603278Swollman } 146111070Sdg } while ((sc = sc->tulip_slaves) != NULL); 146211070Sdg return progress; 14633278Swollman} 14643278Swollman 14653278Swollman/* 14667689Sdg * 14677689Sdg */ 14687689Sdg 14698754Sdgstatic void 14707689Sdgtulip_delay_300ns( 14718754Sdg tulip_softc_t * const sc) 14727689Sdg{ 14738754Sdg TULIP_READ_CSR(sc, csr_busmode); TULIP_READ_CSR(sc, csr_busmode); 14748754Sdg TULIP_READ_CSR(sc, csr_busmode); TULIP_READ_CSR(sc, csr_busmode); 14757689Sdg 14768754Sdg TULIP_READ_CSR(sc, csr_busmode); TULIP_READ_CSR(sc, csr_busmode); 14778754Sdg TULIP_READ_CSR(sc, csr_busmode); TULIP_READ_CSR(sc, csr_busmode); 14787689Sdg 14798754Sdg TULIP_READ_CSR(sc, csr_busmode); TULIP_READ_CSR(sc, csr_busmode); 14808754Sdg TULIP_READ_CSR(sc, csr_busmode); TULIP_READ_CSR(sc, csr_busmode); 14817689Sdg} 14827689Sdg 14838754Sdg#define EMIT do { TULIP_WRITE_CSR(sc, csr_srom_mii, csr); tulip_delay_300ns(sc); } while (0) 14847689Sdg 14858754Sdgstatic void 14867689Sdgtulip_idle_srom( 14878754Sdg tulip_softc_t * const sc) 14887689Sdg{ 14897689Sdg unsigned bit, csr; 149011070Sdg 149111070Sdg csr = SROMSEL | SROMRD; EMIT; 14927689Sdg csr ^= SROMCS; EMIT; 14937689Sdg csr ^= SROMCLKON; EMIT; 14947689Sdg 14957689Sdg /* 14967689Sdg * Write 25 cycles of 0 which will force the SROM to be idle. 14977689Sdg */ 14987689Sdg for (bit = 3 + SROM_BITWIDTH + 16; bit > 0; bit--) { 14997689Sdg csr ^= SROMCLKOFF; EMIT; /* clock low; data not valid */ 15007689Sdg csr ^= SROMCLKON; EMIT; /* clock high; data valid */ 15017689Sdg } 15027689Sdg csr ^= SROMCLKOFF; EMIT; 15037689Sdg csr ^= SROMCS; EMIT; EMIT; 15047689Sdg csr = 0; EMIT; 15057689Sdg} 15067689Sdg 150711070Sdg 15088754Sdgstatic void 15097689Sdgtulip_read_srom( 15108754Sdg tulip_softc_t * const sc) 151111070Sdg{ 151211070Sdg int idx; 15137689Sdg const unsigned bitwidth = SROM_BITWIDTH; 15147689Sdg const unsigned cmdmask = (SROMCMD_RD << bitwidth); 15157689Sdg const unsigned msb = 1 << (bitwidth + 3 - 1); 15167689Sdg unsigned lastidx = (1 << bitwidth) - 1; 15177689Sdg 15187689Sdg tulip_idle_srom(sc); 15197689Sdg 15207689Sdg for (idx = 0; idx <= lastidx; idx++) { 15217689Sdg unsigned lastbit, data, bits, bit, csr; 15227689Sdg csr = SROMSEL | SROMRD; EMIT; 15237689Sdg csr ^= SROMCSON; EMIT; 15247689Sdg csr ^= SROMCLKON; EMIT; 152511070Sdg 15267689Sdg lastbit = 0; 15277689Sdg for (bits = idx|cmdmask, bit = bitwidth + 3; bit > 0; bit--, bits <<= 1) { 15287689Sdg const unsigned thisbit = bits & msb; 15297689Sdg csr ^= SROMCLKOFF; EMIT; /* clock low; data not valid */ 15307689Sdg if (thisbit != lastbit) { 15317689Sdg csr ^= SROMDOUT; EMIT; /* clock low; invert data */ 15327689Sdg } 15337689Sdg csr ^= SROMCLKON; EMIT; /* clock high; data valid */ 15347689Sdg lastbit = thisbit; 15357689Sdg } 15367689Sdg csr ^= SROMCLKOFF; EMIT; 15377689Sdg 15387689Sdg for (data = 0, bits = 0; bits < 16; bits++) { 15397689Sdg data <<= 1; 154011070Sdg csr ^= SROMCLKON; EMIT; /* clock high; data valid */ 15418754Sdg data |= TULIP_READ_CSR(sc, csr_srom_mii) & SROMDIN ? 1 : 0; 15427689Sdg csr ^= SROMCLKOFF; EMIT; /* clock low; data not valid */ 15437689Sdg } 15447689Sdg sc->tulip_rombuf[idx*2] = data & 0xFF; 15457689Sdg sc->tulip_rombuf[idx*2+1] = data >> 8; 15467689Sdg csr = SROMSEL | SROMRD; EMIT; 15477689Sdg csr = 0; EMIT; 15487689Sdg } 15497689Sdg} 15507791Sdg 15518754Sdg#define tulip_mchash(mca) (tulip_crc32(mca, 6) & 0x1FF) 15527791Sdg#define tulip_srom_crcok(databuf) ( \ 155311070Sdg ((tulip_crc32(databuf, 126) & 0xFFFF) ^ 0xFFFF)== \ 15547791Sdg ((databuf)[126] | ((databuf)[127] << 8))) 15557689Sdg 15567791Sdgstatic unsigned 15577791Sdgtulip_crc32( 15587791Sdg const unsigned char *databuf, 15597791Sdg size_t datalen) 15607791Sdg{ 15617791Sdg u_int idx, bit, data, crc = 0xFFFFFFFFUL; 15627791Sdg 15637791Sdg for (idx = 0; idx < datalen; idx++) 15647791Sdg for (data = *databuf++, bit = 0; bit < 8; bit++, data >>= 1) 15657791Sdg crc = (crc >> 1) ^ (((crc ^ data) & 1) ? TULIP_CRC32_POLY : 0); 15667791Sdg return crc; 15677791Sdg} 15687791Sdg 15697791Sdg 15707689Sdg/* 157111070Sdg * This deals with the vagaries of the address roms and the 157211070Sdg * brain-deadness that various vendors commit in using them. 15733278Swollman */ 15743278Swollmanstatic int 15753278Swollmantulip_read_macaddr( 15763278Swollman tulip_softc_t *sc) 15773278Swollman{ 15783278Swollman int cksum, rom_cksum, idx; 157911070Sdg tulip_uint32_t csr; 15803278Swollman unsigned char tmpbuf[8]; 15818754Sdg static const u_char testpat[] = { 0xFF, 0, 0x55, 0xAA, 0xFF, 0, 0x55, 0xAA }; 15823278Swollman 15838296Sdg if (sc->tulip_chipid == TULIP_DC21040) { 15848754Sdg TULIP_WRITE_CSR(sc, csr_enetrom, 1); 15857689Sdg for (idx = 0; idx < 32; idx++) { 15867689Sdg int cnt = 0; 158711070Sdg while (((csr = TULIP_READ_CSR(sc, csr_enetrom)) & 0x80000000L) && cnt < 10000) 15887689Sdg cnt++; 15897689Sdg sc->tulip_rombuf[idx] = csr & 0xFF; 15907689Sdg } 159111070Sdg sc->tulip_boardsw = &tulip_dc21040_boardsw; 159211070Sdg#if defined(TULIP_EISA) 159311070Sdg } else if (sc->tulip_chipid == TULIP_DE425) { 159411070Sdg int cnt; 159511070Sdg for (idx = 0, cnt = 0; idx < sizeof(testpat) && cnt < 32; cnt++) { 159611070Sdg tmpbuf[idx] = TULIP_READ_CSRBYTE(sc, csr_enetrom); 159711070Sdg if (tmpbuf[idx] == testpat[idx]) 159811070Sdg ++idx; 159911070Sdg else 160011070Sdg idx = 0; 160111070Sdg } 160211070Sdg for (idx = 0; idx < 32; idx++) 160311070Sdg sc->tulip_rombuf[idx] = TULIP_READ_CSRBYTE(sc, csr_enetrom); 160411070Sdg sc->tulip_boardsw = &tulip_dc21040_boardsw; 160511070Sdg#endif /* TULIP_EISA */ 16067689Sdg } else { 160711070Sdg int new_srom_fmt = 0; 16087791Sdg /* 16097791Sdg * Assume all DC21140 board are compatible with the 161011070Sdg * DEC 10/100 evaluation board. Not really valid but 161111070Sdg * it's the best we can do until every one switches to 161211070Sdg * the new SROM format. 16137791Sdg */ 16148296Sdg if (sc->tulip_chipid == TULIP_DC21140) 16157791Sdg sc->tulip_boardsw = &tulip_dc21140_eb_boardsw; 161611070Sdg /* 161711070Sdg * Thankfully all DC21041's act the same. 161811070Sdg */ 161911070Sdg if (sc->tulip_chipid == TULIP_DC21041) 162011070Sdg sc->tulip_boardsw = &tulip_dc21041_boardsw; 16217689Sdg tulip_read_srom(sc); 16227791Sdg if (tulip_srom_crcok(sc->tulip_rombuf)) { 16237791Sdg /* 162411070Sdg * SROM CRC is valid therefore it must be in the 162511070Sdg * new format. 162611070Sdg */ 162711070Sdg new_srom_fmt = 1; 162811070Sdg } else if (sc->tulip_rombuf[126] == 0xff && sc->tulip_rombuf[127] == 0xFF) { 162911070Sdg /* 163011070Sdg * No checksum is present. See if the SROM id checks out; 163111070Sdg * the first 18 bytes should be 0 followed by a 1 followed 163211070Sdg * by the number of adapters (which we don't deal with yet). 163311070Sdg */ 163411070Sdg for (idx = 0; idx < 18; idx++) { 163511070Sdg if (sc->tulip_rombuf[idx] != 0) 163611070Sdg break; 163711070Sdg } 163811070Sdg if (idx == 18 && sc->tulip_rombuf[18] == 1 && sc->tulip_rombuf[19] != 0) 163911070Sdg new_srom_fmt = 2; 164011070Sdg } 164111070Sdg if (new_srom_fmt) { 164211070Sdg /* 16437791Sdg * New SROM format. Copy out the Ethernet address. 16447791Sdg * If it contains a DE500-XA string, then it must be 16457791Sdg * a DE500-XA. 16467791Sdg */ 16477791Sdg bcopy(sc->tulip_rombuf + 20, sc->tulip_hwaddr, 6); 16487791Sdg if (bcmp(sc->tulip_rombuf + 29, "DE500-XA", 8) == 0) 16497791Sdg sc->tulip_boardsw = &tulip_dc21140_de500_boardsw; 165011070Sdg if (bcmp(sc->tulip_rombuf + 29, "DE450", 5) == 0) 165111070Sdg sc->tulip_boardsw = &tulip_dc21041_de450_boardsw; 16527791Sdg if (sc->tulip_boardsw == NULL) 16537791Sdg return -6; 165411070Sdg sc->tulip_flags |= TULIP_ROMOK; 16557791Sdg return 0; 16567791Sdg } 16573278Swollman } 16583278Swollman 16597791Sdg 16604772Sdg if (bcmp(&sc->tulip_rombuf[0], &sc->tulip_rombuf[16], 8) != 0) { 16614772Sdg /* 16624772Sdg * Some folks don't use the standard ethernet rom format 16634772Sdg * but instead just put the address in the first 6 bytes 16644772Sdg * of the rom and let the rest be all 0xffs. (Can we say 16654772Sdg * ZNYX???) 16664772Sdg */ 16674772Sdg for (idx = 6; idx < 32; idx++) { 16684772Sdg if (sc->tulip_rombuf[idx] != 0xFF) 16694772Sdg return -4; 16704772Sdg } 16714772Sdg /* 16724772Sdg * Make sure the address is not multicast or locally assigned 16734772Sdg * that the OUI is not 00-00-00. 16744772Sdg */ 16754772Sdg if ((sc->tulip_rombuf[0] & 3) != 0) 16764772Sdg return -4; 16774772Sdg if (sc->tulip_rombuf[0] == 0 && sc->tulip_rombuf[1] == 0 16784772Sdg && sc->tulip_rombuf[2] == 0) 16794772Sdg return -4; 16804772Sdg bcopy(sc->tulip_rombuf, sc->tulip_hwaddr, 6); 168111070Sdg sc->tulip_flags |= TULIP_ROMOK; 168211070Sdg if (sc->tulip_hwaddr[0] == TULIP_OUI_ZNYX_0 168311070Sdg && sc->tulip_hwaddr[1] == TULIP_OUI_ZNYX_1 168411070Sdg && sc->tulip_hwaddr[2] == TULIP_OUI_ZNYX_2 168511070Sdg && (sc->tulip_hwaddr[3] & ~3) == 0xF0) { 168611070Sdg /* 168711070Sdg * Now if the OUI is ZNYX and hwaddr[3] == 0xF0 .. 0xF3 168811070Sdg * then it's a ZX314 Master port. 168911070Sdg */ 169011070Sdg sc->tulip_boardsw = &tulip_dc21040_zx314_master_boardsw; 169111070Sdg } 16924772Sdg return 0; 169311070Sdg } else { 169411070Sdg /* 169511070Sdg * A number of makers of multiport boards (ZNYX and Cogent) 169611070Sdg * only put on one address ROM on their DC21040 boards. So 169711070Sdg * if the ROM is all zeros and this is a DC21040, look at the 169811070Sdg * previous configured boards (as long as they are on the same 169911070Sdg * PCI bus and the bus number is non-zero) until we find the 170011070Sdg * master board with address ROM. We then use its address ROM 170111070Sdg * as the base for this board. (we add our relative board 170211070Sdg * to the last byte of its address). 170311070Sdg */ 170411070Sdg if (sc->tulip_chipid == TULIP_DC21040 /* && sc->tulip_bus != 0 XXX */) { 170511070Sdg for (idx = 0; idx < 32; idx++) { 170611070Sdg if (sc->tulip_rombuf[idx] != 0) 170711070Sdg break; 170811070Sdg } 170911070Sdg if (idx == 32) { 171011070Sdg int root_unit; 171111070Sdg tulip_softc_t *root_sc = NULL; 171211070Sdg for (root_unit = sc->tulip_unit - 1; root_unit >= 0; root_unit--) { 171311070Sdg root_sc = TULIP_UNIT_TO_SOFTC(root_unit); 171411070Sdg if (root_sc == NULL || (root_sc->tulip_flags & (TULIP_ROMOK|TULIP_SLAVEDROM)) == TULIP_ROMOK) 171511070Sdg break; 171611070Sdg root_sc = NULL; 171711070Sdg } 171811070Sdg if (root_sc != NULL 171911070Sdg /* && root_sc->tulip_bus == sc->tulip_bus XXX */) { 172011070Sdg bcopy(root_sc->tulip_hwaddr, sc->tulip_hwaddr, 6); 172111070Sdg sc->tulip_hwaddr[5] += sc->tulip_unit - root_sc->tulip_unit; 172211070Sdg sc->tulip_flags |= TULIP_SLAVEDROM; 172311070Sdg if (root_sc->tulip_boardsw->bd_type == TULIP_DC21040_ZX314_MASTER) { 172411070Sdg sc->tulip_boardsw = &tulip_dc21040_zx314_slave_boardsw; 172511070Sdg /* 172611070Sdg * Now for a truly disgusting kludge: all 4 DC21040s on 172711070Sdg * the ZX314 share the same INTA line so the mapping 172811070Sdg * setup by the BIOS on the PCI bridge is worthless. 172911070Sdg * Rather than reprogramming the value in the config 173011070Sdg * register, we will handle this internally. 173111070Sdg */ 173211070Sdg sc->tulip_slaves = root_sc->tulip_slaves; 173311070Sdg root_sc->tulip_slaves = sc; 173411070Sdg } 173511070Sdg return 0; 173611070Sdg } 173711070Sdg } 173811070Sdg } 17394772Sdg } 174011070Sdg 174111070Sdg /* 174211070Sdg * This is the standard DEC address ROM test. 174311070Sdg */ 174411070Sdg 17453278Swollman if (bcmp(&sc->tulip_rombuf[24], testpat, 8) != 0) 17463278Swollman return -3; 17473278Swollman 17483278Swollman tmpbuf[0] = sc->tulip_rombuf[15]; tmpbuf[1] = sc->tulip_rombuf[14]; 17493278Swollman tmpbuf[2] = sc->tulip_rombuf[13]; tmpbuf[3] = sc->tulip_rombuf[12]; 17503278Swollman tmpbuf[4] = sc->tulip_rombuf[11]; tmpbuf[5] = sc->tulip_rombuf[10]; 17513278Swollman tmpbuf[6] = sc->tulip_rombuf[9]; tmpbuf[7] = sc->tulip_rombuf[8]; 17523278Swollman if (bcmp(&sc->tulip_rombuf[0], tmpbuf, 8) != 0) 17533278Swollman return -2; 17543278Swollman 17553278Swollman bcopy(sc->tulip_rombuf, sc->tulip_hwaddr, 6); 17563278Swollman 17573278Swollman cksum = *(u_short *) &sc->tulip_hwaddr[0]; 17583278Swollman cksum *= 2; 17593278Swollman if (cksum > 65535) cksum -= 65535; 17603278Swollman cksum += *(u_short *) &sc->tulip_hwaddr[2]; 17613278Swollman if (cksum > 65535) cksum -= 65535; 17623278Swollman cksum *= 2; 17633278Swollman if (cksum > 65535) cksum -= 65535; 17643278Swollman cksum += *(u_short *) &sc->tulip_hwaddr[4]; 17653278Swollman if (cksum >= 65535) cksum -= 65535; 17663278Swollman 17673278Swollman rom_cksum = *(u_short *) &sc->tulip_rombuf[6]; 176811070Sdg 17693278Swollman if (cksum != rom_cksum) 17703278Swollman return -1; 17718296Sdg 177211070Sdg /* 177311070Sdg * Check for various boards based on OUI. Did I say braindead? 177411070Sdg */ 177511070Sdg 17768296Sdg if (sc->tulip_chipid == TULIP_DC21140) { 17778296Sdg if (sc->tulip_hwaddr[0] == TULIP_OUI_COGENT_0 17788296Sdg && sc->tulip_hwaddr[1] == TULIP_OUI_COGENT_1 17798296Sdg && sc->tulip_hwaddr[2] == TULIP_OUI_COGENT_2) { 17808296Sdg if (sc->tulip_rombuf[32] == TULIP_COGENT_EM100_ID) 17818296Sdg sc->tulip_boardsw = &tulip_dc21140_cogent_em100_boardsw; 17828296Sdg } 178311070Sdg if (sc->tulip_hwaddr[0] == TULIP_OUI_ZNYX_0 178411070Sdg && sc->tulip_hwaddr[1] == TULIP_OUI_ZNYX_1 178511070Sdg && sc->tulip_hwaddr[2] == TULIP_OUI_ZNYX_2) { 178611070Sdg /* this at least works for the zx342 from Znyx */ 178711070Sdg sc->tulip_boardsw = &tulip_dc21140_znyx_zx34x_boardsw; 178811070Sdg } 17898296Sdg } 17908296Sdg 179111070Sdg sc->tulip_flags |= TULIP_ROMOK; 17923278Swollman return 0; 17933278Swollman} 17943278Swollman 17953278Swollmanstatic void 17963278Swollmantulip_addr_filter( 17978754Sdg tulip_softc_t * const sc) 17983278Swollman{ 17993278Swollman tulip_uint32_t *sp = sc->tulip_setupdata; 18003278Swollman struct ether_multistep step; 18013278Swollman struct ether_multi *enm; 18023278Swollman int i; 18033278Swollman 18043278Swollman sc->tulip_flags &= ~TULIP_WANTHASH; 18053278Swollman sc->tulip_flags |= TULIP_WANTSETUP; 18063278Swollman sc->tulip_cmdmode &= ~TULIP_CMD_RXRUN; 18073278Swollman sc->tulip_intrmask &= ~TULIP_STS_RXSTOPPED; 18083278Swollman if (sc->tulip_ac.ac_multicnt > 14) { 18093278Swollman unsigned hash; 18103278Swollman /* 18113278Swollman * If we have more than 14 multicasts, we have 18123278Swollman * go into hash perfect mode (512 bit multicast 18133278Swollman * hash and one perfect hardware). 18143278Swollman */ 18153278Swollman 18163278Swollman bzero(sc->tulip_setupdata, sizeof(sc->tulip_setupdata)); 18173278Swollman hash = tulip_mchash(etherbroadcastaddr); 18183278Swollman sp[hash >> 4] |= 1 << (hash & 0xF); 18193278Swollman ETHER_FIRST_MULTI(step, &sc->tulip_ac, enm); 18203278Swollman while (enm != NULL) { 18213278Swollman hash = tulip_mchash(enm->enm_addrlo); 18223278Swollman sp[hash >> 4] |= 1 << (hash & 0xF); 18233278Swollman ETHER_NEXT_MULTI(step, enm); 18243278Swollman } 18258754Sdg sc->tulip_flags |= TULIP_WANTHASH; 182611070Sdg sp[39] = ((u_short *) sc->tulip_ac.ac_enaddr)[0]; 182711070Sdg sp[40] = ((u_short *) sc->tulip_ac.ac_enaddr)[1]; 18287689Sdg sp[41] = ((u_short *) sc->tulip_ac.ac_enaddr)[2]; 18293278Swollman } else { 18303278Swollman /* 18313278Swollman * Else can get perfect filtering for 16 addresses. 18323278Swollman */ 18333278Swollman i = 0; 18343278Swollman ETHER_FIRST_MULTI(step, &sc->tulip_ac, enm); 18353278Swollman for (; enm != NULL; i++) { 183611070Sdg *sp++ = ((u_short *) enm->enm_addrlo)[0]; 183711070Sdg *sp++ = ((u_short *) enm->enm_addrlo)[1]; 18383278Swollman *sp++ = ((u_short *) enm->enm_addrlo)[2]; 18393278Swollman ETHER_NEXT_MULTI(step, enm); 18403278Swollman } 18413278Swollman /* 184211070Sdg * Add the broadcast address. 18433278Swollman */ 184411070Sdg i++; 184511070Sdg *sp++ = 0xFFFF; 184611070Sdg *sp++ = 0xFFFF; 184711070Sdg *sp++ = 0xFFFF; 18483278Swollman /* 18493278Swollman * Pad the rest with our hardware address 18503278Swollman */ 18513278Swollman for (; i < 16; i++) { 185211070Sdg *sp++ = ((u_short *) sc->tulip_ac.ac_enaddr)[0]; 185311070Sdg *sp++ = ((u_short *) sc->tulip_ac.ac_enaddr)[1]; 18543278Swollman *sp++ = ((u_short *) sc->tulip_ac.ac_enaddr)[2]; 18553278Swollman } 18563278Swollman } 18573278Swollman} 18583278Swollman 18593278Swollmanstatic int 18603278Swollmantulip_ioctl( 18618754Sdg struct ifnet * const ifp, 18628754Sdg ioctl_cmd_t cmd, 18633278Swollman caddr_t data) 18643278Swollman{ 18658754Sdg tulip_softc_t * const sc = TULIP_UNIT_TO_SOFTC(ifp->if_unit); 18664437Sdg struct ifaddr *ifa = (struct ifaddr *)data; 18674437Sdg struct ifreq *ifr = (struct ifreq *) data; 18683278Swollman int s, error = 0; 18693278Swollman 18703278Swollman s = splimp(); 18713278Swollman 18723278Swollman switch (cmd) { 18733278Swollman case SIOCSIFADDR: { 18743278Swollman 18753278Swollman ifp->if_flags |= IFF_UP; 18763278Swollman switch(ifa->ifa_addr->sa_family) { 18773278Swollman#ifdef INET 18783278Swollman case AF_INET: { 187911070Sdg sc->tulip_ac.ac_ipaddr = IA_SIN(ifa)->sin_addr; 18808754Sdg tulip_init(sc); 18818754Sdg#if defined(__FreeBSD__) || defined(__NetBSD__) 188211070Sdg arp_ifinit(&sc->tulip_ac, ifa); 18838754Sdg#elif defined(__bsdi__) 188411070Sdg arpwhohas(&sc->tulip_ac, &IA_SIN(ifa)->sin_addr); 18858296Sdg#endif 18863278Swollman break; 18873278Swollman } 18883278Swollman#endif /* INET */ 18893278Swollman 18903278Swollman#ifdef NS 18918754Sdg /* 18928754Sdg * This magic copied from if_is.c; I don't use XNS, 18933278Swollman * so I have no way of telling if this actually 18943278Swollman * works or not. 18953278Swollman */ 18963278Swollman case AF_NS: { 18973278Swollman struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); 18983278Swollman if (ns_nullhost(*ina)) { 18993278Swollman ina->x_host = *(union ns_host *)(sc->tulip_ac.ac_enaddr); 19003278Swollman } else { 19013278Swollman ifp->if_flags &= ~IFF_RUNNING; 19023278Swollman bcopy((caddr_t)ina->x_host.c_host, 19033278Swollman (caddr_t)sc->tulip_ac.ac_enaddr, 19043278Swollman sizeof sc->tulip_ac.ac_enaddr); 19053278Swollman } 19063278Swollman 19078754Sdg tulip_init(sc); 19083278Swollman break; 19093278Swollman } 19103278Swollman#endif /* NS */ 19113278Swollman 19123278Swollman default: { 19138754Sdg tulip_init(sc); 19143278Swollman break; 19153278Swollman } 19163278Swollman } 19173278Swollman break; 19183278Swollman } 19193278Swollman 19203278Swollman case SIOCSIFFLAGS: { 19213278Swollman /* 19223278Swollman * Changing the connection forces a reset. 19233278Swollman */ 19243278Swollman if (sc->tulip_flags & TULIP_ALTPHYS) { 19253278Swollman if ((ifp->if_flags & IFF_ALTPHYS) == 0) 19268754Sdg tulip_reset(sc); 19273278Swollman } else { 19283278Swollman if (ifp->if_flags & IFF_ALTPHYS) 19298754Sdg tulip_reset(sc); 19303278Swollman } 19318754Sdg tulip_init(sc); 19323278Swollman break; 19333278Swollman } 19343278Swollman 19353278Swollman case SIOCADDMULTI: 19363278Swollman case SIOCDELMULTI: { 19373278Swollman /* 19383278Swollman * Update multicast listeners 19393278Swollman */ 19403278Swollman if (cmd == SIOCADDMULTI) 19414437Sdg error = ether_addmulti(ifr, &sc->tulip_ac); 19423278Swollman else 19434437Sdg error = ether_delmulti(ifr, &sc->tulip_ac); 19443278Swollman 19453278Swollman if (error == ENETRESET) { 19463278Swollman tulip_addr_filter(sc); /* reset multicast filtering */ 19478754Sdg tulip_init(sc); 19483278Swollman error = 0; 19493278Swollman } 19503278Swollman break; 19513278Swollman } 19528296Sdg#if defined(SIOCSIFMTU) 19538754Sdg#if !defined(ifr_mtu) 19548754Sdg#define ifr_mtu ifr_metric 19558754Sdg#endif 19564437Sdg case SIOCSIFMTU: 19574437Sdg /* 19584437Sdg * Set the interface MTU. 19594437Sdg */ 19604437Sdg if (ifr->ifr_mtu > ETHERMTU) { 19614437Sdg error = EINVAL; 196211070Sdg break; 19634437Sdg } 196411070Sdg ifp->if_mtu = ifr->ifr_mtu; 19654437Sdg break; 19668296Sdg#endif 19673278Swollman 19683278Swollman default: { 19693278Swollman error = EINVAL; 19703278Swollman break; 19713278Swollman } 19723278Swollman } 19733278Swollman 19743278Swollman splx(s); 19753278Swollman return error; 19763278Swollman} 19773278Swollman 19783278Swollmanstatic void 19793278Swollmantulip_attach( 19808754Sdg tulip_softc_t * const sc) 19813278Swollman{ 19828754Sdg struct ifnet * const ifp = &sc->tulip_if; 19833278Swollman 19847791Sdg ifp->if_flags = IFF_BROADCAST|IFF_SIMPLEX|IFF_NOTRAILERS|IFF_MULTICAST; 19853278Swollman ifp->if_ioctl = tulip_ioctl; 19863278Swollman ifp->if_output = ether_output; 19873278Swollman ifp->if_start = tulip_start; 198811070Sdg 19898754Sdg#ifdef __FreeBSD__ 19908296Sdg printf("%s%d", sc->tulip_name, sc->tulip_unit); 19918296Sdg#endif 199211070Sdg printf(": %s%s pass %d.%d Ethernet address %s\n", 19937791Sdg sc->tulip_boardsw->bd_description, 19948296Sdg tulip_chipdescs[sc->tulip_chipid], 19953278Swollman (sc->tulip_revinfo & 0xF0) >> 4, 19963278Swollman sc->tulip_revinfo & 0x0F, 19973278Swollman ether_sprintf(sc->tulip_hwaddr)); 19983278Swollman 19998296Sdg if ((*sc->tulip_boardsw->bd_media_probe)(sc)) { 20008296Sdg ifp->if_flags |= IFF_ALTPHYS; 20018296Sdg } else { 20028296Sdg sc->tulip_flags |= TULIP_ALTPHYS; 20038296Sdg } 20048296Sdg 20058754Sdg tulip_reset(sc); 20068296Sdg 20074322Sdg if_attach(ifp); 20088754Sdg#if defined(__NetBSD__) 20098754Sdg ether_ifattach(ifp); 20108754Sdg#endif 20114322Sdg 20123278Swollman#if NBPFILTER > 0 20133278Swollman bpfattach(&sc->tulip_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); 20143278Swollman#endif 20153278Swollman} 20163278Swollman 20173278Swollmanstatic void 20183278Swollmantulip_initcsrs( 20198754Sdg tulip_softc_t * const sc, 202011070Sdg tulip_csrptr_t csr_base, 20213278Swollman size_t csr_size) 20223278Swollman{ 202311070Sdg sc->tulip_csrs.csr_busmode = csr_base + 0 * csr_size; 202411070Sdg sc->tulip_csrs.csr_txpoll = csr_base + 1 * csr_size; 202511070Sdg sc->tulip_csrs.csr_rxpoll = csr_base + 2 * csr_size; 202611070Sdg sc->tulip_csrs.csr_rxlist = csr_base + 3 * csr_size; 202711070Sdg sc->tulip_csrs.csr_txlist = csr_base + 4 * csr_size; 202811070Sdg sc->tulip_csrs.csr_status = csr_base + 5 * csr_size; 202911070Sdg sc->tulip_csrs.csr_command = csr_base + 6 * csr_size; 203011070Sdg sc->tulip_csrs.csr_intr = csr_base + 7 * csr_size; 203111070Sdg sc->tulip_csrs.csr_missed_frame = csr_base + 8 * csr_size; 20328296Sdg if (sc->tulip_chipid == TULIP_DC21040) { 203311070Sdg sc->tulip_csrs.csr_enetrom = csr_base + 9 * csr_size; 203411070Sdg sc->tulip_csrs.csr_reserved = csr_base + 10 * csr_size; 203511070Sdg sc->tulip_csrs.csr_full_duplex = csr_base + 11 * csr_size; 203611070Sdg sc->tulip_csrs.csr_sia_status = csr_base + 12 * csr_size; 203711070Sdg sc->tulip_csrs.csr_sia_connectivity = csr_base + 13 * csr_size; 203811070Sdg sc->tulip_csrs.csr_sia_tx_rx = csr_base + 14 * csr_size; 203911070Sdg sc->tulip_csrs.csr_sia_general = csr_base + 15 * csr_size; 204011070Sdg#if defined(TULIP_EISA) 204111070Sdg } else if (sc->tulip_chipid == TULIP_DE425) { 204211070Sdg sc->tulip_csrs.csr_enetrom = csr_base + DE425_ENETROM_OFFSET; 204311070Sdg sc->tulip_csrs.csr_reserved = csr_base + 10 * csr_size; 204411070Sdg sc->tulip_csrs.csr_full_duplex = csr_base + 11 * csr_size; 204511070Sdg sc->tulip_csrs.csr_sia_status = csr_base + 12 * csr_size; 204611070Sdg sc->tulip_csrs.csr_sia_connectivity = csr_base + 13 * csr_size; 204711070Sdg sc->tulip_csrs.csr_sia_tx_rx = csr_base + 14 * csr_size; 204811070Sdg sc->tulip_csrs.csr_sia_general = csr_base + 15 * csr_size; 204911070Sdg#endif /* TULIP_EISA */ 205011070Sdg } else if (sc->tulip_chipid == TULIP_DC21140) { 205111070Sdg sc->tulip_csrs.csr_srom_mii = csr_base + 9 * csr_size; 205211070Sdg sc->tulip_csrs.csr_gp_timer = csr_base + 11 * csr_size; 205311070Sdg sc->tulip_csrs.csr_gp = csr_base + 12 * csr_size; 205411070Sdg sc->tulip_csrs.csr_watchdog = csr_base + 15 * csr_size; 205511070Sdg } else if (sc->tulip_chipid == TULIP_DC21041) { 205611070Sdg sc->tulip_csrs.csr_srom_mii = csr_base + 9 * csr_size; 205711070Sdg sc->tulip_csrs.csr_bootrom = csr_base + 10 * csr_size; 205811070Sdg sc->tulip_csrs.csr_gp_timer = csr_base + 11 * csr_size; 205911070Sdg sc->tulip_csrs.csr_sia_status = csr_base + 12 * csr_size; 206011070Sdg sc->tulip_csrs.csr_sia_connectivity = csr_base + 13 * csr_size; 206111070Sdg sc->tulip_csrs.csr_sia_tx_rx = csr_base + 14 * csr_size; 206211070Sdg sc->tulip_csrs.csr_sia_general = csr_base + 15 * csr_size; 20637689Sdg } 20643278Swollman} 20653278Swollman 20663278Swollmanstatic void 20673278Swollmantulip_initring( 20688754Sdg tulip_softc_t * const sc, 20698754Sdg tulip_ringinfo_t * const ri, 20703278Swollman tulip_desc_t *descs, 20713278Swollman int ndescs) 20723278Swollman{ 20733278Swollman ri->ri_max = ndescs; 20743278Swollman ri->ri_first = descs; 20753278Swollman ri->ri_last = ri->ri_first + ri->ri_max; 20763278Swollman bzero((caddr_t) ri->ri_first, sizeof(ri->ri_first[0]) * ri->ri_max); 20773278Swollman ri->ri_last[-1].d_flag = TULIP_DFLAG_ENDRING; 20783278Swollman} 20793278Swollman 20803278Swollman/* 20813278Swollman * This is the PCI configuration support. Since the DC21040 is available 20823278Swollman * on both EISA and PCI boards, one must be careful in how defines the 20833278Swollman * DC21040 in the config file. 20843278Swollman */ 20853278Swollman 20863278Swollman#define PCI_CFID 0x00 /* Configuration ID */ 20873278Swollman#define PCI_CFCS 0x04 /* Configurtion Command/Status */ 20883278Swollman#define PCI_CFRV 0x08 /* Configuration Revision */ 20893278Swollman#define PCI_CFLT 0x0c /* Configuration Latency Timer */ 20903278Swollman#define PCI_CBIO 0x10 /* Configuration Base IO Address */ 20913278Swollman#define PCI_CBMA 0x14 /* Configuration Base Memory Address */ 20923278Swollman#define PCI_CFIT 0x3c /* Configuration Interrupt */ 20933278Swollman#define PCI_CFDA 0x40 /* Configuration Driver Area */ 20943278Swollman 209511070Sdg#if defined(TULIP_EISA) 209611070Sdgstatic const int tulip_eisa_irqs[4] = { IRQ5, IRQ9, IRQ10, IRQ11 }; 20978754Sdg#endif 20988296Sdg 20998296Sdg#if defined(__FreeBSD__) 21008296Sdg 21018296Sdg#define TULIP_PCI_ATTACH_ARGS pcici_t config_id, int unit 21028296Sdg 21038296Sdgstatic int 21048296Sdgtulip_pci_shutdown( 21058754Sdg struct kern_devconf * const kdc, 21068296Sdg int force) 21078296Sdg{ 21088296Sdg if (kdc->kdc_unit < NDE) { 21098754Sdg tulip_softc_t * const sc = TULIP_UNIT_TO_SOFTC(kdc->kdc_unit); 21108754Sdg TULIP_WRITE_CSR(sc, csr_busmode, TULIP_BUSMODE_SWRESET); 211111070Sdg DELAY(10); /* Wait 10 microsends (actually 50 PCI cycles but at 21128296Sdg 33MHz that comes to two microseconds but wait a 21138296Sdg bit longer anyways) */ 21148296Sdg } 21158296Sdg (void) dev_detach(kdc); 21168296Sdg return 0; 21178296Sdg} 21188296Sdg 21193533Ssestatic char* 21203278Swollmantulip_pci_probe( 21213533Sse pcici_t config_id, 21223533Sse pcidi_t device_id) 21233278Swollman{ 212411070Sdg if (PCI_VENDORID(device_id) != DEC_VENDORID) 212511070Sdg return NULL; 212611070Sdg if (PCI_CHIPID(device_id) == DC21040_CHIPID) 21277689Sdg return "Digital DC21040 Ethernet"; 212811070Sdg if (PCI_CHIPID(device_id) == DC21041_CHIPID) 21297689Sdg return "Digital DC21041 Ethernet"; 213011070Sdg if (PCI_CHIPID(device_id) == DC21140_CHIPID) 21317689Sdg return "Digital DC21140 Fast Ethernet"; 21323543Sse return NULL; 21333278Swollman} 21343278Swollman 21358296Sdgstatic void tulip_pci_attach(TULIP_PCI_ATTACH_ARGS); 21368296Sdgstatic u_long tulip_pci_count; 21378296Sdg 21388296Sdgstruct pci_device dedevice = { 21398296Sdg "de", 21408296Sdg tulip_pci_probe, 21418296Sdg tulip_pci_attach, 21428296Sdg &tulip_pci_count, 21438296Sdg tulip_pci_shutdown, 21448296Sdg}; 21458296Sdg 21468296SdgDATA_SET (pcidevice_set, dedevice); 21478296Sdg#endif /* __FreeBSD__ */ 21488296Sdg 21498296Sdg#if defined(__bsdi__) 215011070Sdg#define TULIP_PCI_ATTACH_ARGS struct device * const parent, struct device * const self, void * const aux 21518296Sdg 21523533Ssestatic void 215311070Sdgtulip_shutdown( 21548296Sdg void *arg) 21558296Sdg{ 21568754Sdg tulip_softc_t * const sc = (tulip_softc_t *) arg; 21578754Sdg TULIP_WRITE_CSR(sc, csr_busmode, TULIP_BUSMODE_SWRESET); 215811070Sdg DELAY(10); /* Wait 10 microsends (actually 50 PCI cycles but at 21598296Sdg 33MHz that comes to two microseconds but wait a 21608296Sdg bit longer anyways) */ 21618296Sdg} 21628296Sdg 21638296Sdgstatic int 21648296Sdgtulip_pci_match( 21658296Sdg pci_devaddr_t *pa) 21668296Sdg{ 21678296Sdg int irq; 21688296Sdg unsigned id; 21698296Sdg 21708296Sdg id = pci_inl(pa, PCI_VENDOR_ID); 217111070Sdg if (PCI_VENDORID(id) != DEC_VENDORID) 21728296Sdg return 0; 217311070Sdg id = PCI_CHIPID(id); 217411070Sdg if (id != DC21040_CHIPID && id != DC21041_CHIPID && id != DC21140_CHIPID) 21758296Sdg return 0; 217611070Sdg irq = pci_inl(pa, PCI_I_LINE) & 0xFF; 217711070Sdg if (irq == 0 || irq >= 16) { 217811070Sdg printf("de?: invalid IRQ %d; skipping\n", irq); 21798296Sdg return 0; 218011070Sdg } 21818296Sdg return 1; 21828296Sdg} 21838296Sdg 21848754Sdgstatic int 218511070Sdgtulip_probe( 21868296Sdg struct device *parent, 21878296Sdg struct cfdata *cf, 21888296Sdg void *aux) 21898296Sdg{ 21908754Sdg struct isa_attach_args * const ia = (struct isa_attach_args *) aux; 219111070Sdg unsigned irq, slot; 21928296Sdg pci_devaddr_t *pa; 21938296Sdg 219411070Sdg#if defined(TULIP_EISA) 219511070Sdg if ((slot = eisa_match(cf, ia)) != 0) { 219611070Sdg unsigned tmp; 219711070Sdg ia->ia_iobase = slot << 12; 219811070Sdg ia->ia_iosize = EISA_NPORT; 219911070Sdg eisa_slotalloc(slot); 220011070Sdg tmp = inb(ia->ia_iobase + DE425_CFG0); 220111070Sdg irq = tulip_eisa_irqs[(tmp >> 1) & 0x03]; 220211070Sdg /* 220311070Sdg * Until BSD/OS likes level interrupts, force 220411070Sdg * the DE425 into edge-triggered mode. 220511070Sdg */ 220611070Sdg if ((tmp & 1) == 0) 220711070Sdg outb(ia->ia_iobase + DE425_CFG0, tmp | 1); 220811070Sdg /* 220911070Sdg * CBIO needs to map to the EISA slot 221011070Sdg * enable I/O access and Master 221111070Sdg */ 221211070Sdg outl(ia->ia_iobase + DE425_CBIO, ia->ia_iobase); 221311070Sdg outl(ia->ia_iobase + DE425_CFCS, 5 | inl(ia->ia_iobase + DE425_CFCS)); 221411070Sdg ia->ia_aux = NULL; 221511070Sdg } else { 221611070Sdg#endif /* TULIP_EISA */ 221711070Sdg pa = pci_scan(tulip_pci_match); 221811070Sdg if (pa == NULL) 221911070Sdg return 0; 22208296Sdg 222111070Sdg irq = (1 << (pci_inl(pa, PCI_I_LINE) & 0xFF)); 22228296Sdg 222311070Sdg /* Get the base address; assume the BIOS set it up correctly */ 222411070Sdg#if defined(TULIP_IOMAPPED) 222511070Sdg ia->ia_maddr = NULL; 222611070Sdg ia->ia_msize = 0; 222711070Sdg ia->ia_iobase = pci_inl(pa, PCI_CBIO) & ~7; 222811070Sdg pci_outl(pa, PCI_CBIO, 0xFFFFFFFF); 222911070Sdg ia->ia_iosize = ((~pci_inl(pa, PCI_CBIO)) | 7) + 1; 223011070Sdg pci_outl(pa, PCI_CBIO, (int) ia->ia_iobase); 223111070Sdg 223211070Sdg /* Disable memory space access */ 223311070Sdg pci_outl(pa, PCI_COMMAND, pci_inl(pa, PCI_COMMAND) & ~2); 223411070Sdg#else 223511070Sdg ia->ia_maddr = (caddr_t) (pci_inl(pa, PCI_CBMA) & ~7); 223611070Sdg pci_outl(pa, PCI_CBMA, 0xFFFFFFFF); 223711070Sdg ia->ia_msize = ((~pci_inl(pa, PCI_CBMA)) | 7) + 1; 223811070Sdg pci_outl(pa, PCI_CBMA, (int) ia->ia_maddr); 223911070Sdg ia->ia_iobase = 0; 224011070Sdg ia->ia_iosize = 0; 224111070Sdg 224211070Sdg /* Disable I/O space access */ 224311070Sdg pci_outl(pa, PCI_COMMAND, pci_inl(pa, PCI_COMMAND) & ~1); 224411070Sdg#endif /* TULIP_IOMAPPED */ 224511070Sdg 224611070Sdg ia->ia_aux = (void *) pa; 224711070Sdg#if defined(TULIP_EISA) 224811070Sdg } 224911070Sdg#endif 225011070Sdg 225111070Sdg /* PCI bus masters don't use host DMA channels */ 225211070Sdg ia->ia_drq = DRQNONE; 225311070Sdg 22548296Sdg if (ia->ia_irq != IRQUNK && irq != ia->ia_irq) { 225511070Sdg printf("de%d: error: desired IRQ of %d does not match device's actual IRQ of %d,\n", 22568296Sdg cf->cf_unit, 22578296Sdg ffs(ia->ia_irq) - 1, ffs(irq) - 1); 22588296Sdg return 0; 22598296Sdg } 226011070Sdg if (ia->ia_irq == IRQUNK && (ia->ia_irq = isa_irqalloc(irq)) == 0) { 226111070Sdg printf("de%d: warning: IRQ %d is shared\n", cf->cf_unit, ffs(irq) - 1); 22628296Sdg ia->ia_irq = irq; 22638296Sdg } 22648296Sdg return 1; 22658296Sdg} 22668296Sdg 22678296Sdgstatic void tulip_pci_attach(TULIP_PCI_ATTACH_ARGS); 22688296Sdg 226911070Sdg#if defined(TULIP_EISA) 227011070Sdgstatic char *tulip_eisa_ids[] = { 227111070Sdg "DEC4250", 227211070Sdg NULL 227311070Sdg}; 227411070Sdg#endif 227511070Sdg 22768296Sdgstruct cfdriver decd = { 227711070Sdg 0, "de", tulip_probe, tulip_pci_attach, DV_IFNET, sizeof(tulip_softc_t), 227811070Sdg#if defined(TULIP_EISA) 227911070Sdg tulip_eisa_ids 228011070Sdg#endif 22818296Sdg}; 22828296Sdg 22838296Sdg#endif /* __bsdi__ */ 22848754Sdg 22858754Sdg#if defined(__NetBSD__) 228611070Sdg#define TULIP_PCI_ATTACH_ARGS struct device * const parent, struct device * const self, void * const aux 22878296Sdg 22888296Sdgstatic void 22898754Sdgtulip_pci_shutdown( 22908754Sdg void *arg) 22918754Sdg{ 22928754Sdg tulip_softc_t * const sc = (tulip_softc_t *) arg; 22938754Sdg TULIP_WRITE_CSR(sc, csr_busmode, TULIP_BUSMODE_SWRESET); 229411070Sdg DELAY(10); /* Wait 10 microsends (actually 50 PCI cycles but at 22958754Sdg 33MHz that comes to two microseconds but wait a 22968754Sdg bit longer anyways) */ 22978754Sdg} 22988754Sdg 22998754Sdgstatic int 23008754Sdgtulip_pci_probe( 23018754Sdg struct device *parent, 23028754Sdg void *match, 23038754Sdg void *aux) 23048754Sdg{ 23058754Sdg struct pci_attach_args *pa = (struct pci_attach_args *) aux; 23068754Sdg 230711070Sdg if (PCI_VENDORID(pa->pa_id) != DEC_VENDORID) 230811070Sdg return 0; 230911070Sdg if (PCI_CHIPID(pa->pa_id) == DC21040_CHIPID 231011070Sdg || PCI_CHIPID(pa->pa_id) == DC21041_CHIPID 231111070Sdg || PCI_CHIPID(pa->pa_id) == DC21140_CHIPID) 23128754Sdg return 1; 23138754Sdg 23148754Sdg return 0; 23158754Sdg} 23168754Sdg 23178754Sdgstatic void tulip_pci_attach(TULIP_PCI_ATTACH_ARGS); 23188754Sdg 23198754Sdgstruct cfdriver decd = { 23208754Sdg 0, "de", tulip_pci_probe, tulip_pci_attach, DV_IFNET, sizeof(tulip_softc_t) 23218754Sdg}; 23228754Sdg 23238754Sdg#endif /* __NetBSD__ */ 23248754Sdg 23258754Sdgstatic void 23263278Swollmantulip_pci_attach( 23278296Sdg TULIP_PCI_ATTACH_ARGS) 23283278Swollman{ 23298296Sdg#if defined(__FreeBSD__) 23303278Swollman tulip_softc_t *sc; 23318296Sdg#endif 23328296Sdg#if defined(__bsdi__) 23338754Sdg tulip_softc_t * const sc = (tulip_softc_t *) self; 23348754Sdg struct isa_attach_args * const ia = (struct isa_attach_args *) aux; 23358296Sdg pci_devaddr_t *pa = (pci_devaddr_t *) ia->ia_aux; 23368296Sdg int unit = sc->tulip_dev.dv_unit; 23378296Sdg#endif 23388754Sdg#if defined(__NetBSD__) 23398754Sdg tulip_softc_t * const sc = (tulip_softc_t *) self; 23408754Sdg struct pci_attach_args * const pa = (struct pci_attach_args *) aux; 23418754Sdg int unit = sc->tulip_dev.dv_unit; 23428754Sdg#endif 23438296Sdg int retval, idx, revinfo, id; 234411070Sdg#if !defined(TULIP_IOMAPPED) && !defined(__bsdi__) 234511070Sdg vm_offset_t pa_csrs; 234611070Sdg#endif 234711070Sdg unsigned csroffset = TULIP_PCI_CSROFFSET; 234811070Sdg unsigned csrsize = TULIP_PCI_CSRSIZE; 234911070Sdg tulip_csrptr_t csr_base; 23503278Swollman tulip_desc_t *rxdescs, *txdescs; 235111070Sdg tulip_chipid_t chipid = TULIP_CHIPID_UNKNOWN; 23523278Swollman 23538296Sdg#if defined(__FreeBSD__) 23547689Sdg if (unit >= NDE) { 23557689Sdg printf("de%d: not configured; kernel is built for only %d device%s.\n", 23567689Sdg unit, NDE, NDE == 1 ? "" : "s"); 23577689Sdg return; 23587689Sdg } 23598296Sdg#endif 23607689Sdg 23618296Sdg#if defined(__FreeBSD__) 23627791Sdg revinfo = pci_conf_read(config_id, PCI_CFRV) & 0xFF; 23638296Sdg id = pci_conf_read(config_id, PCI_CFID); 23648296Sdg#endif 23658296Sdg#if defined(__bsdi__) 236611070Sdg if (pa != NULL) { 236711070Sdg revinfo = pci_inl(pa, PCI_CFRV) & 0xFF; 236811070Sdg id = pci_inl(pa, PCI_CFID); 236911070Sdg#if defined(TULIP_EISA) 237011070Sdg } else { 237111070Sdg revinfo = inl(ia->ia_iobase + DE425_CFRV) & 0xFF; 237211070Sdg csroffset = TULIP_EISA_CSROFFSET; 237311070Sdg csrsize = TULIP_EISA_CSRSIZE; 237411070Sdg chipid = TULIP_DE425; 23758296Sdg#endif 237611070Sdg } 237711070Sdg#endif 23788754Sdg#if defined(__NetBSD__) 23798754Sdg revinfo = pci_conf_read(pa->pa_tag, PCI_CFRV) & 0xFF; 23808754Sdg id = pa->pa_id; 23818754Sdg#endif 23828296Sdg 238311070Sdg if (PCI_VENDORID(id) == DEC_VENDORID) { 238411070Sdg if (PCI_CHIPID(id) == DC21040_CHIPID) chipid = TULIP_DC21040; 238511070Sdg else if (PCI_CHIPID(id) == DC21140_CHIPID) chipid = TULIP_DC21140; 238611070Sdg else if (PCI_CHIPID(id) == DC21041_CHIPID) chipid = TULIP_DC21041; 238711070Sdg } 238811070Sdg if (chipid == TULIP_CHIPID_UNKNOWN) 238911070Sdg return; 23908296Sdg 239111070Sdg if ((chipid == TULIP_DC21040 || chipid == TULIP_DE425) && revinfo < 0x20) { 23928754Sdg#ifdef __FreeBSD__ 23938754Sdg printf("de%d", unit); 23948754Sdg#endif 23958754Sdg printf(": not configured; DC21040 pass 2.0 required (%d.%d found)\n", 23968754Sdg revinfo >> 4, revinfo & 0x0f); 23977791Sdg return; 23988296Sdg } else if (chipid == TULIP_DC21140 && revinfo < 0x11) { 23998754Sdg#ifdef __FreeBSD__ 24008754Sdg printf("de%d", unit); 24018754Sdg#endif 24028754Sdg printf(": not configured; DC21140 pass 1.1 required (%d.%d found)\n", 24038754Sdg revinfo >> 4, revinfo & 0x0f); 24047791Sdg return; 24057791Sdg } 24067791Sdg 24078296Sdg#if defined(__FreeBSD__) 24083278Swollman sc = (tulip_softc_t *) malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT); 24093278Swollman if (sc == NULL) 24103533Sse return; 24118296Sdg bzero(sc, sizeof(*sc)); /* Zero out the softc*/ 24128296Sdg#endif 24133278Swollman 24143278Swollman rxdescs = (tulip_desc_t *) 24153278Swollman malloc(sizeof(tulip_desc_t) * TULIP_RXDESCS, M_DEVBUF, M_NOWAIT); 24163278Swollman if (rxdescs == NULL) { 24178296Sdg#if defined(__FreeBSD__) 24183278Swollman free((caddr_t) sc, M_DEVBUF); 24198296Sdg#endif 24203533Sse return; 24213278Swollman } 24223278Swollman 24233278Swollman txdescs = (tulip_desc_t *) 24243278Swollman malloc(sizeof(tulip_desc_t) * TULIP_TXDESCS, M_DEVBUF, M_NOWAIT); 24253278Swollman if (txdescs == NULL) { 24263278Swollman free((caddr_t) rxdescs, M_DEVBUF); 24278296Sdg#if defined(__FreeBSD__) 24283278Swollman free((caddr_t) sc, M_DEVBUF); 24298296Sdg#endif 24303533Sse return; 24313278Swollman } 24323278Swollman 24338296Sdg sc->tulip_chipid = chipid; 24343278Swollman sc->tulip_unit = unit; 24353278Swollman sc->tulip_name = "de"; 243611070Sdg sc->tulip_revinfo = revinfo; 24378296Sdg#if defined(__FreeBSD__) 243811070Sdg#if defined(TULIP_IOMAPPED) 243911070Sdg retval = pci_map_port(config_id, PCI_CBIO, &csr_base); 244011070Sdg#else 244111070Sdg retval = pci_map_mem(config_id, PCI_CBMA, (vm_offset_t *) &csr_base, &pa_csrs); 244211070Sdg#endif 24433533Sse if (!retval) { 24443278Swollman free((caddr_t) txdescs, M_DEVBUF); 24453278Swollman free((caddr_t) rxdescs, M_DEVBUF); 24463278Swollman free((caddr_t) sc, M_DEVBUF); 24473533Sse return; 24483278Swollman } 24493278Swollman tulips[unit] = sc; 245011070Sdg#endif /* __FreeBSD__ */ 245111070Sdg 24528296Sdg#if defined(__bsdi__) 245311070Sdg#if defined(TULIP_IOMAPPED) 245411070Sdg csr_base = ia->ia_iobase; 245511070Sdg#else 245611070Sdg csr_base = (vm_offset_t) mapphys((vm_offset_t) ia->ia_maddr, ia->ia_msize); 24578296Sdg#endif 245811070Sdg#endif /* __bsdi__ */ 245911070Sdg 24608754Sdg#if defined(__NetBSD__) 246111070Sdg#if defined(TULIP_IOMAPPED) 246211070Sdg retval = pci_map_io(pa->pa_tag, PCI_CBIO, &csr_base); 246311070Sdg#else 246411070Sdg retval = pci_map_mem(pa->pa_tag, PCI_CBMA, (vm_offset_t *) &csr_base, &pa_csrs); 246511070Sdg#endif 246611070Sdg if (retval) { 24678754Sdg free((caddr_t) txdescs, M_DEVBUF); 24688754Sdg free((caddr_t) rxdescs, M_DEVBUF); 24698754Sdg return; 24708754Sdg } 247111070Sdg#endif /* __NetBSD__ */ 247211070Sdg 247311070Sdg tulip_initcsrs(sc, csr_base + csroffset, csrsize); 24743278Swollman tulip_initring(sc, &sc->tulip_rxinfo, rxdescs, TULIP_RXDESCS); 24753278Swollman tulip_initring(sc, &sc->tulip_txinfo, txdescs, TULIP_TXDESCS); 24763278Swollman if ((retval = tulip_read_macaddr(sc)) < 0) { 24778754Sdg#ifdef __FreeBSD__ 24788754Sdg printf("%s%d", sc->tulip_name, sc->tulip_unit); 24798754Sdg#endif 24808754Sdg printf(": can't read ENET ROM (why=%d) (", retval); 24813278Swollman for (idx = 0; idx < 32; idx++) 24823278Swollman printf("%02x", sc->tulip_rombuf[idx]); 24833278Swollman printf("\n"); 24847791Sdg printf("%s%d: %s%s pass %d.%d Ethernet address %s\n", 24853278Swollman sc->tulip_name, sc->tulip_unit, 24867791Sdg (sc->tulip_boardsw != NULL ? sc->tulip_boardsw->bd_description : ""), 24878296Sdg tulip_chipdescs[sc->tulip_chipid], 24883278Swollman (sc->tulip_revinfo & 0xF0) >> 4, sc->tulip_revinfo & 0x0F, 24893278Swollman "unknown"); 24903278Swollman } else { 249111070Sdg /* 249211070Sdg * Make sure there won't be any interrupts or such... 249311070Sdg */ 249411070Sdg TULIP_WRITE_CSR(sc, csr_busmode, TULIP_BUSMODE_SWRESET); 249511070Sdg DELAY(10); /* Wait 10 microsends (actually 50 PCI cycles but at 249611070Sdg 33MHz that comes to two microseconds but wait a 249711070Sdg bit longer anyways) */ 24988754Sdg#if defined(__NetBSD__) 249911070Sdg if (sc->tulip_boardsw->bd_type != TULIP_DC21040_ZX314_SLAVE) { 250011070Sdg sc->tulip_ih = pci_map_int(pa->pa_tag, PCI_IPL_NET, tulip_intr, sc); 250111070Sdg if (sc->tulip_ih == NULL) { 250211070Sdg printf("%s%d: couldn't map interrupt\n", 250311070Sdg sc->tulip_name, sc->tulip_unit); 250411070Sdg return; 250511070Sdg } 250611070Sdg#if defined(__i386__) 250711070Sdg /* gross but netbsd won't print the irq otherwise */ 250811070Sdg printf(" irq %d", ((struct intrhand *) sc->tulip_ih)->ih_irq); 250911070Sdg#endif 251011070Sdg } 251111070Sdg sc->tulip_ats = shutdownhook_establish(tulip_pci_shutdown, sc); 251211070Sdg if (sc->tulip_ats == NULL) 251311070Sdg printf("%s%d: warning: couldn't establish shutdown hook\n", 25148754Sdg sc->tulip_name, sc->tulip_unit); 25158754Sdg#endif 25168296Sdg#if defined(__FreeBSD__) 251711070Sdg if (sc->tulip_boardsw->bd_type != TULIP_DC21040_ZX314_SLAVE) 251811070Sdg pci_map_int (config_id, tulip_intr, (void*) sc, &net_imask); 25198296Sdg#endif 25208296Sdg#if defined(__bsdi__) 252111070Sdg if (sc->tulip_boardsw->bd_type != TULIP_DC21040_ZX314_SLAVE) { 252211070Sdg isa_establish(&sc->tulip_id, &sc->tulip_dev); 25237104Sdg 252411070Sdg sc->tulip_ih.ih_fun = tulip_intr; 252511070Sdg sc->tulip_ih.ih_arg = (void *)sc; 252611070Sdg intr_establish(ia->ia_irq, &sc->tulip_ih, DV_NET); 252711070Sdg } 25288296Sdg 252911070Sdg sc->tulip_ats.func = tulip_shutdown; 25308296Sdg sc->tulip_ats.arg = (void *) sc; 25318296Sdg atshutdown(&sc->tulip_ats, ATSH_ADD); 25328296Sdg#endif 253311070Sdg tulip_reset(sc); 253411070Sdg tulip_attach(sc); 25357689Sdg } 25367104Sdg} 25373278Swollman#endif /* NDE > 0 */ 2538