if_de.c revision 6295
138494Sobrien/*- 2174313Sobrien * Copyright (c) 1994 Matt Thomas (thomas@lkg.dec.com) 338494Sobrien * All rights reserved. 438494Sobrien * 538494Sobrien * Redistribution and use in source and binary forms, with or without 638494Sobrien * modification, are permitted provided that the following conditions 738494Sobrien * are met: 838494Sobrien * 1. Redistributions of source code must retain the above copyright 938494Sobrien * notice, this list of conditions and the following disclaimer. 1038494Sobrien * 2. The name of the author may not be used to endorse or promote products 1138494Sobrien * derived from this software withough specific prior written permission 1238494Sobrien * 1338494Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1438494Sobrien * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1538494Sobrien * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1638494Sobrien * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1738494Sobrien * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1838494Sobrien * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1938494Sobrien * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2042633Sobrien * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2138494Sobrien * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2238494Sobrien * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2338494Sobrien * 2438494Sobrien * $Id: if_de.c,v 1.15 1995/02/02 13:12:13 davidg Exp $ 2538494Sobrien * 2638494Sobrien */ 2738494Sobrien 2838494Sobrien/* 2938494Sobrien * DEC DC21040 PCI Ethernet Controller 3038494Sobrien * 3138494Sobrien * Written by Matt Thomas 3238494Sobrien * BPF support code stolen directly from if_ec.c 3338494Sobrien * 3438494Sobrien * This driver supports the DEC DE435 or any other PCI 3538494Sobrien * board which support DC21040. 3638494Sobrien */ 3738494Sobrien 3838494Sobrien#include "de.h" 3938494Sobrien#if NDE > 0 40174313Sobrien 4138494Sobrien#include <sys/param.h> 4238494Sobrien#include <sys/systm.h> 4338494Sobrien#include <sys/mbuf.h> 4438494Sobrien#include <sys/protosw.h> 4538494Sobrien#include <sys/socket.h> 4638494Sobrien#include <sys/ioctl.h> 4738494Sobrien#include <sys/errno.h> 4838494Sobrien#include <sys/malloc.h> 4938494Sobrien#include <sys/kernel.h> 5038494Sobrien#include <machine/clock.h> 5138494Sobrien 5238494Sobrien#include <net/if.h> 5338494Sobrien#include <net/if_types.h> 5438494Sobrien#include <net/if_dl.h> 5538494Sobrien#include <net/route.h> 5638494Sobrien 5738494Sobrien#include "bpfilter.h" 5838494Sobrien#if NBPFILTER > 0 5938494Sobrien#include <net/bpf.h> 6038494Sobrien#include <net/bpfdesc.h> 6138494Sobrien#endif 6238494Sobrien 6382801Sobrien#ifdef INET 6438494Sobrien#include <netinet/in.h> 6538494Sobrien#include <netinet/in_systm.h> 6638494Sobrien#include <netinet/in_var.h> 6738494Sobrien#include <netinet/ip.h> 6838494Sobrien#include <netinet/if_ether.h> 6938494Sobrien#endif 7038494Sobrien 7138494Sobrien#ifdef NS 7238494Sobrien#include <netns/ns.h> 7338494Sobrien#include <netns/ns_if.h> 7438494Sobrien#endif 7538494Sobrien 7638494Sobrien#include <vm/vm.h> 7738494Sobrien#include <vm/vm_kern.h> 7838494Sobrien#include <vm/vm_param.h> 7938494Sobrien 8038494Sobrien 8138494Sobrien#include <pci.h> 8238494Sobrien#if NPCI > 0 8338494Sobrien#include <pci/pcivar.h> 8438494Sobrien#endif 8538494Sobrien 8638494Sobrien#include <pci/dc21040.h> 8738494Sobrien 8838494Sobrien/* 8938494Sobrien * This module supports the DEC DC21040 PCI Ethernet Controller. 9038494Sobrien */ 9138494Sobrien 9238494Sobrientypedef struct { 9338494Sobrien unsigned long addr; 9438494Sobrien unsigned long length; 9538494Sobrien} tulip_addrvec_t; 9638494Sobrien 9738494Sobrientypedef struct { 9838494Sobrien tulip_desc_t *ri_first; 9938494Sobrien tulip_desc_t *ri_last; 10038494Sobrien tulip_desc_t *ri_nextin; 10138494Sobrien tulip_desc_t *ri_nextout; 10238494Sobrien int ri_max; 10338494Sobrien int ri_free; 104174313Sobrien} tulip_ringinfo_t; 105174313Sobrien 10638494Sobrientypedef struct { 10738494Sobrien volatile tulip_uint32_t *csr_busmode; /* CSR0 */ 10838494Sobrien volatile tulip_uint32_t *csr_txpoll; /* CSR1 */ 10938494Sobrien volatile tulip_uint32_t *csr_rxpoll; /* CSR2 */ 11038494Sobrien volatile tulip_uint32_t *csr_rxlist; /* CSR3 */ 11138494Sobrien volatile tulip_uint32_t *csr_txlist; /* CSR4 */ 11238494Sobrien volatile tulip_uint32_t *csr_status; /* CSR5 */ 11338494Sobrien volatile tulip_uint32_t *csr_command; /* CSR6 */ 11438494Sobrien volatile tulip_uint32_t *csr_intr; /* CSR7 */ 11538494Sobrien volatile tulip_uint32_t *csr_missed_frame; /* CSR8 */ 11638494Sobrien volatile tulip_sint32_t *csr_enetrom; /* CSR9 */ 11738494Sobrien volatile tulip_uint32_t *csr_reserved; /* CSR10 */ 11838494Sobrien volatile tulip_uint32_t *csr_full_duplex; /* CSR11 */ 11938494Sobrien volatile tulip_uint32_t *csr_sia_status; /* CSR12 */ 12038494Sobrien volatile tulip_uint32_t *csr_sia_connectivity; /* CSR13 */ 12138494Sobrien volatile tulip_uint32_t *csr_sia_tx_rx; /* CSR14 */ 122174313Sobrien volatile tulip_uint32_t *csr_sia_general; /* CSR15 */ 12338494Sobrien} tulip_regfile_t; 12438494Sobrien 12538494Sobrien/* 12638494Sobrien * The DC21040 has a stupid restriction in that the receive 12738494Sobrien * buffers must be longword aligned. But since Ethernet 12838494Sobrien * headers are not a multiple of longwords in size this forces 129174313Sobrien * the data to non-longword aligned. Since IP requires the 130174313Sobrien * data to be longword aligned, we need to copy it after it has 13138494Sobrien * been DMA'ed in our memory. 13238494Sobrien * 13338494Sobrien * Since we have to copy it anyways, we might as well as allocate 13438494Sobrien * dedicated receive space for the input. This allows to use a 13538494Sobrien * small receive buffer size and more ring entries to be able to 13638494Sobrien * better keep with a flood of tiny Ethernet packets. 13738494Sobrien * 13838494Sobrien * The receive space MUST ALWAYS be a multiple of the page size. 13938494Sobrien * And the number of receive descriptors multiplied by the size 14038494Sobrien * of the receive buffers must equal the recevive space. This 14138494Sobrien * is so that we can manipulate the page tables so that even if a 142174313Sobrien * packet wraps around the end of the receive space, we can 14338494Sobrien * treat it as virtually contiguous. 14438494Sobrien */ 14538494Sobrien#define TULIP_RXBUFSIZE 512 14638494Sobrien#define TULIP_RXDESCS 128 14738494Sobrien#define TULIP_RXSPACE (TULIP_RXBUFSIZE * TULIP_RXDESCS) 14838494Sobrien#define TULIP_TXDESCS 128 14938494Sobrien 15038494Sobrientypedef struct { 15138494Sobrien struct arpcom tulip_ac; 15238494Sobrien tulip_regfile_t tulip_csrs; 15338494Sobrien vm_offset_t tulip_rxspace; 15438494Sobrien unsigned tulip_flags; 15538494Sobrien#define TULIP_WANTSETUP 0x01 15638494Sobrien#define TULIP_WANTHASH 0x02 15738494Sobrien#define TULIP_DOINGSETUP 0x04 15838494Sobrien#define TULIP_ALTPHYS 0x08 /* use AUI */ 15938494Sobrien unsigned char tulip_rombuf[32]; 16038494Sobrien tulip_uint32_t tulip_setupbuf[192/sizeof(tulip_uint32_t)]; 16138494Sobrien tulip_uint32_t tulip_setupdata[192/sizeof(tulip_uint32_t)]; 16238494Sobrien tulip_uint32_t tulip_intrmask; 16338494Sobrien tulip_uint32_t tulip_cmdmode; 16438494Sobrien tulip_uint32_t tulip_revinfo; 16582801Sobrien#if NBPFILTER > 0 16638494Sobrien caddr_t tulip_bpf; /* BPF context */ 16782801Sobrien#endif 16882801Sobrien struct ifqueue tulip_txq; 16982801Sobrien tulip_ringinfo_t tulip_rxinfo; 170174313Sobrien tulip_ringinfo_t tulip_txinfo; 17182801Sobrien} tulip_softc_t; 17282801Sobrien 17382801Sobrien#ifndef IFF_ALTPHYS 17482801Sobrien#define IFF_ALTPHYS IFF_LINK0 /* In case it isn't defined */ 17582801Sobrien#endif 17682801Sobrientypedef enum { TULIP_DC21040, TULIP_DC21140 } tulip_chipid_t; 17782801Sobrienconst char *tulip_chipdescs[] = { 178174313Sobrien "DC21040 [10Mb/s]", 179174313Sobrien "DC21140 [100Mb/s]", 180174313Sobrien}; 181174313Sobrien 18282801Sobrientulip_softc_t *tulips[NDE]; 18382801Sobrientulip_chipid_t tulip_chipids[NDE]; 184174313Sobrien 18582801Sobrien#define tulip_if tulip_ac.ac_if 18682801Sobrien#define tulip_unit tulip_ac.ac_if.if_unit 18782801Sobrien#define tulip_name tulip_ac.ac_if.if_name 18882801Sobrien#define tulip_hwaddr tulip_ac.ac_enaddr 18982801Sobrien 19082801Sobrien#define TULIP_CRC32_POLY 0xEDB88320UL /* CRC-32 Poly -- Little Endian */ 19138494Sobrien#define TULIP_CHECK_RXCRC 0 19238494Sobrien#define TULIP_MAX_TXSEG 30 19338494Sobrien 19438494Sobrien#define TULIP_ADDREQUAL(a1, a2) \ 19538494Sobrien (((u_short *)a1)[0] == ((u_short *)a2)[0] \ 19638494Sobrien && ((u_short *)a1)[1] == ((u_short *)a2)[1] \ 19738494Sobrien && ((u_short *)a1)[2] == ((u_short *)a2)[2]) 19838494Sobrien#define TULIP_ADDRBRDCST(a1) \ 19938494Sobrien (((u_short *)a1)[0] == 0xFFFFU \ 20038494Sobrien && ((u_short *)a1)[1] == 0xFFFFU \ 20138494Sobrien && ((u_short *)a1)[2] == 0xFFFFU) 20238494Sobrien 20382801Sobrienstatic void tulip_start(struct ifnet *ifp); 20438494Sobrienstatic void tulip_addr_filter(tulip_softc_t *sc); 20538494Sobrien 20638494Sobrien#if __FreeBSD__ > 1 207174313Sobrien#define TULIP_IFRESET_ARGS int unit 20838494Sobrien#define TULIP_RESET(sc) tulip_reset((sc)->tulip_unit) 20938494Sobrien#else 21038494Sobrien#define TULIP_IFRESET_ARGS int unit, int uban 21138494Sobrien#define TULIP_RESET(sc) tulip_reset((sc)->tulip_unit, 0) 21238494Sobrien#endif 21338494Sobrien 21438494Sobrienstatic void 21538494Sobrientulip_reset( 21638494Sobrien TULIP_IFRESET_ARGS) 21738494Sobrien{ 21838494Sobrien tulip_softc_t *sc = tulips[unit]; 21938494Sobrien tulip_ringinfo_t *ri; 22038494Sobrien tulip_desc_t *di; 22138494Sobrien vm_offset_t vmoff; 22238494Sobrien 22338494Sobrien *sc->tulip_csrs.csr_busmode = TULIP_BUSMODE_SWRESET; 22438494Sobrien DELAY(10); /* Wait 10 microsends (actually 50 PCI cycles but at 22538494Sobrien 33MHz that comes to two microseconds but wait a 22638494Sobrien bit longer anyways) */ 22738494Sobrien 22838494Sobrien /* 22938494Sobrien * Use the 23038494Sobrien */ 23138494Sobrien *sc->tulip_csrs.csr_sia_connectivity = TULIP_SIACONN_RESET; 23238494Sobrien if (sc->tulip_if.if_flags & IFF_ALTPHYS) { 23338494Sobrien if ((sc->tulip_flags & TULIP_ALTPHYS) == 0) 23438494Sobrien printf("%s%d: enabling Thinwire/AUI port\n", 23538494Sobrien sc->tulip_if.if_name, sc->tulip_if.if_unit); 23638494Sobrien *sc->tulip_csrs.csr_sia_connectivity = TULIP_SIACONN_AUI; 23738494Sobrien sc->tulip_flags |= TULIP_ALTPHYS; 23838494Sobrien } else { 23938494Sobrien if (sc->tulip_flags & TULIP_ALTPHYS) 240174313Sobrien printf("%s%d: enabling 10baseT/UTP port\n", 24138494Sobrien sc->tulip_if.if_name, sc->tulip_if.if_unit); 24238494Sobrien *sc->tulip_csrs.csr_sia_connectivity = TULIP_SIACONN_10BASET; 24338494Sobrien sc->tulip_flags &= ~TULIP_ALTPHYS; 24438494Sobrien } 24538494Sobrien *sc->tulip_csrs.csr_txlist = vtophys(&sc->tulip_txinfo.ri_first[0]); 24638494Sobrien *sc->tulip_csrs.csr_rxlist = vtophys(&sc->tulip_rxinfo.ri_first[0]); 24738494Sobrien *sc->tulip_csrs.csr_intr = 0; 24838494Sobrien *sc->tulip_csrs.csr_busmode = 0x4800; 24938494Sobrien 25038494Sobrien sc->tulip_txq.ifq_maxlen = TULIP_TXDESCS; 25138494Sobrien /* 25238494Sobrien * Free all the mbufs that were on the transmit ring. 25338494Sobrien */ 25438494Sobrien for (;;) { 25538494Sobrien struct mbuf *m; 25638494Sobrien IF_DEQUEUE(&sc->tulip_txq, m); 25738494Sobrien if (m == NULL) 25838494Sobrien break; 25938494Sobrien m_freem(m); 26038494Sobrien } 26138494Sobrien 26238494Sobrien ri = &sc->tulip_txinfo; 26338494Sobrien ri->ri_nextin = ri->ri_nextout = ri->ri_first; 26438494Sobrien ri->ri_free = ri->ri_max; 26538494Sobrien for (di = ri->ri_first; di < ri->ri_last; di++) 26638494Sobrien di->d_status = 0; 26738494Sobrien 26838494Sobrien /* 26938494Sobrien * We need to collect all the mbufs were on the 27038494Sobrien * receive ring before we reinit it either to put 27138494Sobrien * them back on or to know if we have to allocate 27238494Sobrien * more. 27338494Sobrien */ 27438494Sobrien ri = &sc->tulip_rxinfo; 27538494Sobrien ri->ri_nextin = ri->ri_nextout = ri->ri_first; 27638494Sobrien ri->ri_free = ri->ri_max; 27738494Sobrien for (vmoff = vtophys(sc->tulip_rxspace), di = ri->ri_first; 27838494Sobrien di < ri->ri_last; di++, vmoff += TULIP_RXBUFSIZE) { 27938494Sobrien di->d_status |= TULIP_DSTS_OWNER; 28038494Sobrien di->d_length1 = TULIP_RXBUFSIZE; di->d_addr1 = vmoff; 28138494Sobrien di->d_length2 = 0; di->d_addr2 = 0; 28238494Sobrien } 28338494Sobrien 28438494Sobrien sc->tulip_intrmask = TULIP_STS_NORMALINTR|TULIP_STS_RXINTR|TULIP_STS_TXINTR 28538494Sobrien |TULIP_STS_ABNRMLINTR|TULIP_STS_SYSERROR|TULIP_STS_TXSTOPPED 28638494Sobrien |TULIP_STS_TXBABBLE|TULIP_STS_LINKFAIL|TULIP_STS_RXSTOPPED; 28738494Sobrien sc->tulip_flags &= ~(TULIP_DOINGSETUP|TULIP_WANTSETUP); 28838494Sobrien tulip_addr_filter(sc); 28938494Sobrien} 29038494Sobrien 29138494Sobrienstatic void 29238494Sobrientulip_init( 29338494Sobrien int unit) 29438494Sobrien{ 29538494Sobrien tulip_softc_t *sc = tulips[unit]; 29638494Sobrien 29738494Sobrien if (sc->tulip_if.if_flags & IFF_UP) { 29838494Sobrien sc->tulip_if.if_flags |= IFF_RUNNING; 29938494Sobrien if (sc->tulip_if.if_flags & IFF_PROMISC) { 30038494Sobrien sc->tulip_cmdmode |= TULIP_CMD_PROMISCUOUS; 30138494Sobrien } else { 30238494Sobrien sc->tulip_cmdmode &= ~TULIP_CMD_PROMISCUOUS; 30338494Sobrien if (sc->tulip_if.if_flags & IFF_ALLMULTI) { 30442633Sobrien sc->tulip_cmdmode |= TULIP_CMD_ALLMULTI; 30538494Sobrien } else { 30638494Sobrien sc->tulip_cmdmode &= ~TULIP_CMD_ALLMULTI; 30738494Sobrien } 30838494Sobrien } 30938494Sobrien sc->tulip_cmdmode |= TULIP_CMD_TXRUN; 31038494Sobrien if ((sc->tulip_flags & TULIP_WANTSETUP) == 0) { 31138494Sobrien sc->tulip_cmdmode |= TULIP_CMD_RXRUN; 31238494Sobrien sc->tulip_intrmask |= TULIP_STS_RXSTOPPED; 31338494Sobrien } else { 31438494Sobrien sc->tulip_intrmask &= ~TULIP_STS_RXSTOPPED; 31538494Sobrien tulip_start(&sc->tulip_if); 31638494Sobrien } 31738494Sobrien sc->tulip_cmdmode |= TULIP_CMD_THRSHLD160; 31842633Sobrien sc->tulip_cmdmode |= TULIP_CMD_CAPTREFFCT; 31938494Sobrien *sc->tulip_csrs.csr_intr = sc->tulip_intrmask; 32038494Sobrien *sc->tulip_csrs.csr_command = sc->tulip_cmdmode; 32138494Sobrien } else { 32238494Sobrien TULIP_RESET(sc); 32382801Sobrien sc->tulip_if.if_flags &= ~IFF_RUNNING; 32438494Sobrien } 32582801Sobrien} 32682801Sobrien 32782801Sobrien 32882801Sobrien#if TULIP_CHECK_RXCRC 32938494Sobrienstatic unsigned 33038494Sobrientulip_crc32( 33138494Sobrien u_char *addr, 33238494Sobrien int len) 33338494Sobrien{ 33438494Sobrien unsigned int crc = 0xFFFFFFFF; 33538494Sobrien static unsigned int crctbl[256]; 33638494Sobrien int idx; 33738494Sobrien static int done; 33838494Sobrien /* 33938494Sobrien * initialize the multicast address CRC table 34038494Sobrien */ 34138494Sobrien for (idx = 0; !done && idx < 256; idx++) { 34238494Sobrien unsigned int tmp = idx; 34338494Sobrien tmp = (tmp >> 1) ^ (tmp & 1 ? TULIP_CRC32_POLY : 0); /* XOR */ 34438494Sobrien tmp = (tmp >> 1) ^ (tmp & 1 ? TULIP_CRC32_POLY : 0); /* XOR */ 34538494Sobrien tmp = (tmp >> 1) ^ (tmp & 1 ? TULIP_CRC32_POLY : 0); /* XOR */ 34638494Sobrien tmp = (tmp >> 1) ^ (tmp & 1 ? TULIP_CRC32_POLY : 0); /* XOR */ 34738494Sobrien tmp = (tmp >> 1) ^ (tmp & 1 ? TULIP_CRC32_POLY : 0); /* XOR */ 34838494Sobrien tmp = (tmp >> 1) ^ (tmp & 1 ? TULIP_CRC32_POLY : 0); /* XOR */ 34938494Sobrien tmp = (tmp >> 1) ^ (tmp & 1 ? TULIP_CRC32_POLY : 0); /* XOR */ 35038494Sobrien tmp = (tmp >> 1) ^ (tmp & 1 ? TULIP_CRC32_POLY : 0); /* XOR */ 35138494Sobrien crctbl[idx] = tmp; 35238494Sobrien } 35338494Sobrien done = 1; 35438494Sobrien 35538494Sobrien while (len-- > 0) 35638494Sobrien crc = (crc >> 8) ^ crctbl[*addr++] ^ crctbl[crc & 0xFF]; 35738494Sobrien 35838494Sobrien return crc; 35938494Sobrien} 36038494Sobrien#endif 36138494Sobrien 36238494Sobrienstatic void 36338494Sobrientulip_rx_intr( 36438494Sobrien tulip_softc_t *sc) 36538494Sobrien{ 36638494Sobrien tulip_ringinfo_t *ri = &sc->tulip_rxinfo; 36738494Sobrien struct ifnet *ifp = &sc->tulip_if; 36838494Sobrien 36938494Sobrien for (;;) { 37038494Sobrien tulip_desc_t *eop; 37138494Sobrien int total_len, ndescs; 37238494Sobrien caddr_t bufaddr = (caddr_t) sc->tulip_rxspace; 37338494Sobrien 37438494Sobrien for (ndescs = 1, eop = ri->ri_nextin;; ndescs++) { 37538494Sobrien if (((volatile tulip_desc_t *) eop)->d_status & TULIP_DSTS_OWNER) 37638494Sobrien return; 37738494Sobrien 37838494Sobrien if (eop->d_status & TULIP_DSTS_RxLASTDESC) 37938494Sobrien break; 38038494Sobrien if (++eop == ri->ri_last) 38138494Sobrien eop = ri->ri_first; 38238494Sobrien } 38338494Sobrien 38438494Sobrien bufaddr += TULIP_RXBUFSIZE * (ri->ri_nextin - ri->ri_first); 38538494Sobrien total_len = ((eop->d_status >> 16) & 0x7FF) - 4; 38638494Sobrien 38738494Sobrien if ((eop->d_status & TULIP_DSTS_ERRSUM) == 0) { 38838494Sobrien struct ether_header eh; 38938494Sobrien struct mbuf *m; 39082801Sobrien 39182801Sobrien#if TULIP_CHECK_RXCRC 39282801Sobrien unsigned crc = tulip_crc32(bufaddr, total_len); 39382801Sobrien if (~crc != *((unsigned *) &bufaddr[total_len])) { 39438494Sobrien printf("de0: bad rx crc: %08x [rx] != %08x\n", 39538494Sobrien *((unsigned *) &bufaddr[total_len]), ~crc); 39638494Sobrien goto next; 39738494Sobrien } 39838494Sobrien#endif 39938494Sobrien eh = *(struct ether_header *) bufaddr; 40038494Sobrien#if NBPFILTER > 0 40138494Sobrien if (sc->tulip_bpf != NULL) { 40238494Sobrien bpf_tap(sc->tulip_bpf, bufaddr, total_len); 40338494Sobrien if ((eh.ether_dhost[0] & 1) == 0 && 40438494Sobrien !TULIP_ADDREQUAL(eh.ether_dhost, sc->tulip_ac.ac_enaddr)) 40538494Sobrien goto next; 40682801Sobrien } else if (!TULIP_ADDREQUAL(eh.ether_dhost, sc->tulip_ac.ac_enaddr) 40782801Sobrien && !TULIP_ADDRBRDCST(eh.ether_dhost)) { 40882801Sobrien goto next; 40982801Sobrien } 41051300Sobrien#endif 41138494Sobrien MGETHDR(m, M_DONTWAIT, MT_DATA); 41238494Sobrien if (m != NULL) { 41338494Sobrien m->m_pkthdr.rcvif = ifp; 41451300Sobrien total_len -= sizeof(eh); 41538494Sobrien if (total_len > MHLEN) { 41638494Sobrien MCLGET(m, M_DONTWAIT); 41738494Sobrien if ((m->m_flags & M_EXT) == 0) { 41838494Sobrien m_freem(m); 41938494Sobrien ifp->if_ierrors++; 42038494Sobrien goto next; 42138494Sobrien } 42238494Sobrien } 42338494Sobrien bcopy(bufaddr + sizeof(eh), mtod(m, caddr_t), total_len); 42438494Sobrien m->m_len = m->m_pkthdr.len = total_len; 42538494Sobrien ether_input(ifp, &eh, m); 42638494Sobrien } else { 42738494Sobrien ifp->if_ierrors++; 42838494Sobrien } 42938494Sobrien } else { 43038494Sobrien ifp->if_ierrors++; 43138494Sobrien } 43238494Sobriennext: 43342633Sobrien ifp->if_ipackets++; 43442633Sobrien while (ndescs-- > 0) { 43538494Sobrien ri->ri_nextin->d_status |= TULIP_DSTS_OWNER; 43638494Sobrien if (++ri->ri_nextin == ri->ri_last) 437174313Sobrien ri->ri_nextin = ri->ri_first; 438174313Sobrien } 43938494Sobrien } 44038494Sobrien} 44138494Sobrien 44238494Sobrienstatic int 44338494Sobrientulip_tx_intr( 44438494Sobrien tulip_softc_t *sc) 44538494Sobrien{ 44638494Sobrien tulip_ringinfo_t *ri = &sc->tulip_txinfo; 44738494Sobrien struct mbuf *m; 44838494Sobrien int xmits = 0; 44938494Sobrien 45038494Sobrien while (ri->ri_free < ri->ri_max) { 45138494Sobrien if (((volatile tulip_desc_t *) ri->ri_nextin)->d_status & TULIP_DSTS_OWNER) 45238494Sobrien break; 45338494Sobrien 45482801Sobrien if (ri->ri_nextin->d_flag & TULIP_DFLAG_TxLASTSEG) { 45538494Sobrien if (ri->ri_nextin->d_flag & TULIP_DFLAG_TxSETUPPKT) { 45638494Sobrien /* 45738494Sobrien * We've just finished processing a setup packet. 45838494Sobrien * Mark that we can finished it. If there's not 45938494Sobrien * another pending, startup the TULIP receiver. 46038494Sobrien * Make sure we ack the RXSTOPPED so we won't get 46138494Sobrien * an abormal interrupt indication. 46238494Sobrien */ 46342633Sobrien sc->tulip_flags &= ~TULIP_DOINGSETUP; 46438494Sobrien if ((sc->tulip_flags & TULIP_WANTSETUP) == 0) { 46538494Sobrien sc->tulip_cmdmode |= TULIP_CMD_RXRUN; 46638494Sobrien sc->tulip_intrmask |= TULIP_STS_RXSTOPPED; 46738494Sobrien *sc->tulip_csrs.csr_status = TULIP_STS_RXSTOPPED; 46838494Sobrien *sc->tulip_csrs.csr_command = sc->tulip_cmdmode; 46938494Sobrien *sc->tulip_csrs.csr_intr = sc->tulip_intrmask; 47038494Sobrien } 47138494Sobrien } else { 47238494Sobrien IF_DEQUEUE(&sc->tulip_txq, m); 47338494Sobrien m_freem(m); 47438494Sobrien sc->tulip_if.if_collisions += 47538494Sobrien (ri->ri_nextin->d_status & TULIP_DSTS_TxCOLLMASK) 47638494Sobrien >> TULIP_DSTS_V_TxCOLLCNT; 47738494Sobrien if (ri->ri_nextin->d_status & TULIP_DSTS_ERRSUM) 47842633Sobrien sc->tulip_if.if_oerrors++; 47942633Sobrien xmits++; 48038494Sobrien } 48138494Sobrien } 48242633Sobrien 48342633Sobrien if (++ri->ri_nextin == ri->ri_last) 48438494Sobrien ri->ri_nextin = ri->ri_first; 48538494Sobrien ri->ri_free++; 48638494Sobrien sc->tulip_if.if_flags &= ~IFF_OACTIVE; 48738494Sobrien } 48838494Sobrien sc->tulip_if.if_opackets += xmits; 48938494Sobrien return xmits; 49038494Sobrien} 49138494Sobrien 49238494Sobrienstatic int 49338494Sobrientulip_txsegment( 49438494Sobrien tulip_softc_t *sc, 49538494Sobrien struct mbuf *m, 49638494Sobrien tulip_addrvec_t *avp, 49738494Sobrien size_t maxseg) 49842633Sobrien{ 49942633Sobrien int segcnt; 50038494Sobrien 50138494Sobrien for (segcnt = 0; m; m = m->m_next) { 50238494Sobrien int len = m->m_len; 50338494Sobrien caddr_t addr = mtod(m, caddr_t); 50438494Sobrien unsigned clsize = CLBYTES - (((u_long) addr) & (CLBYTES-1)); 50538494Sobrien 50638494Sobrien while (len > 0) { 50738494Sobrien unsigned slen = min(len, clsize); 50838494Sobrien if (segcnt < maxseg) { 50938494Sobrien avp->addr = vtophys(addr); 51038494Sobrien avp->length = slen; 51138494Sobrien } 51238494Sobrien len -= slen; 51338494Sobrien addr += slen; 51442633Sobrien clsize = CLBYTES; 51542633Sobrien avp++; 51638494Sobrien segcnt++; 51738494Sobrien } 51838494Sobrien } 51938494Sobrien if (segcnt >= maxseg) { 52038494Sobrien printf("%s%d: tulip_txsegment: extremely fragmented packet encountered (%d segments)\n", 52138494Sobrien sc->tulip_name, sc->tulip_unit, segcnt); 52238494Sobrien return -1; 52338494Sobrien } 52438494Sobrien avp->addr = 0; 52538494Sobrien avp->length = 0; 52638494Sobrien return segcnt; 52738494Sobrien} 52838494Sobrien 52938494Sobrienstatic void 53042633Sobrientulip_start( 53142633Sobrien struct ifnet *ifp) 53238494Sobrien{ 53338494Sobrien tulip_softc_t *sc = (tulip_softc_t *) ifp; 53438494Sobrien struct ifqueue *ifq = &ifp->if_snd; 53538494Sobrien tulip_ringinfo_t *ri = &sc->tulip_txinfo; 53638494Sobrien tulip_desc_t *sop, *eop; 53782801Sobrien struct mbuf *m; 53882801Sobrien tulip_addrvec_t addrvec[TULIP_MAX_TXSEG+1], *avp; 53982801Sobrien int segcnt; 54082801Sobrien tulip_uint32_t d_status; 54182801Sobrien 54282801Sobrien if ((ifp->if_flags & IFF_RUNNING) == 0) 54382801Sobrien return; 544174313Sobrien 545174313Sobrien for (;;) { 54682801Sobrien if (sc->tulip_flags & TULIP_WANTSETUP) { 54782801Sobrien if ((sc->tulip_flags & TULIP_DOINGSETUP) || ri->ri_free == 1) { 54882801Sobrien ifp->if_flags |= IFF_OACTIVE; 54982801Sobrien return; 55082801Sobrien } 55182801Sobrien bcopy(sc->tulip_setupdata, sc->tulip_setupbuf, 55282801Sobrien sizeof(sc->tulip_setupbuf)); 55382801Sobrien sc->tulip_flags &= ~TULIP_WANTSETUP; 55482801Sobrien sc->tulip_flags |= TULIP_DOINGSETUP; 555174313Sobrien ri->ri_free--; 55682801Sobrien ri->ri_nextout->d_flag &= TULIP_DFLAG_ENDRING|TULIP_DFLAG_CHAIN; 55782801Sobrien ri->ri_nextout->d_flag |= TULIP_DFLAG_TxFIRSTSEG|TULIP_DFLAG_TxLASTSEG 55882801Sobrien |TULIP_DFLAG_TxSETUPPKT|TULIP_DFLAG_TxWANTINTR; 55982801Sobrien if (sc->tulip_flags & TULIP_WANTHASH) 56082801Sobrien ri->ri_nextout->d_flag |= TULIP_DFLAG_TxHASHFILT; 56182801Sobrien ri->ri_nextout->d_length1 = sizeof(sc->tulip_setupbuf); 56282801Sobrien ri->ri_nextout->d_addr1 = vtophys(sc->tulip_setupbuf); 56382801Sobrien ri->ri_nextout->d_length2 = 0; 56482801Sobrien ri->ri_nextout->d_addr2 = 0; 56582801Sobrien ri->ri_nextout->d_status = TULIP_DSTS_OWNER; 56638494Sobrien *sc->tulip_csrs.csr_txpoll = 1; 56738494Sobrien /* 56838494Sobrien * Advance the ring for the next transmit packet. 56938494Sobrien */ 57038494Sobrien if (++ri->ri_nextout == ri->ri_last) 57138494Sobrien ri->ri_nextout = ri->ri_first; 57238494Sobrien } 57338494Sobrien 57438494Sobrien IF_DEQUEUE(ifq, m); 57538494Sobrien if (m == NULL) 57638494Sobrien break; 57738494Sobrien 57838494Sobrien /* 57938494Sobrien * First find out how many and which different pages 58042633Sobrien * the mbuf data occupies. Then check to see if we 58142633Sobrien * have enough descriptor space in our transmit ring 58238494Sobrien * to actually send it. 58338494Sobrien */ 58438494Sobrien segcnt = tulip_txsegment(sc, m, addrvec, 58538494Sobrien min(ri->ri_max - 1, TULIP_MAX_TXSEG)); 58638494Sobrien if (segcnt < 0) { 58738494Sobrien struct mbuf *m0; 58838494Sobrien MGETHDR(m0, M_DONTWAIT, MT_DATA); 58938494Sobrien if (m0 != NULL) { 59038494Sobrien if (m->m_pkthdr.len > MHLEN) { 59138494Sobrien MCLGET(m0, M_DONTWAIT); 59238494Sobrien if ((m0->m_flags & M_EXT) == 0) { 59338494Sobrien m_freem(m); 59442633Sobrien continue; 59542633Sobrien } 59638494Sobrien } 59738494Sobrien m_copydata(m, 0, m0->m_pkthdr.len, mtod(m0, caddr_t)); 59838494Sobrien m0->m_pkthdr.len = m0->m_len = m->m_pkthdr.len; 59938494Sobrien m_freem(m); 60038494Sobrien IF_PREPEND(ifq, m0); 60138494Sobrien continue; 60238494Sobrien } else { 60338494Sobrien m_freem(m); 60438494Sobrien continue; 60538494Sobrien } 60638494Sobrien } 60738494Sobrien if (ri->ri_free - 2 <= (segcnt + 1) >> 1) 60842633Sobrien break; 60938494Sobrien 61038494Sobrien ri->ri_free -= (segcnt + 1) >> 1; 61138494Sobrien /* 61238494Sobrien * Now we fill in our transmit descriptors. This is 61338494Sobrien * a bit reminiscent of going on the Ark two by two 61438494Sobrien * since each descriptor for the TULIP can describe 61538494Sobrien * two buffers. So we advance through the address 61638494Sobrien * vector two entries at a time to to fill each 61738494Sobrien * descriptor. Clear the first and last segment bits 61838494Sobrien * in each descriptor (actually just clear everything 61938494Sobrien * but the end-of-ring or chain bits) to make sure 62038494Sobrien * we don't get messed up by previously sent packets. 62138494Sobrien */ 62238494Sobrien sop = ri->ri_nextout; 62338494Sobrien d_status = 0; 62438494Sobrien avp = addrvec; 62538494Sobrien do { 62638494Sobrien eop = ri->ri_nextout; 62738494Sobrien eop->d_flag &= TULIP_DFLAG_ENDRING|TULIP_DFLAG_CHAIN; 62838494Sobrien eop->d_status = d_status; 62938494Sobrien eop->d_addr1 = avp->addr; eop->d_length1 = avp->length; avp++; 63038494Sobrien eop->d_addr2 = avp->addr; eop->d_length2 = avp->length; avp++; 63138494Sobrien d_status = TULIP_DSTS_OWNER; 63238494Sobrien if (++ri->ri_nextout == ri->ri_last) 63338494Sobrien ri->ri_nextout = ri->ri_first; 63438494Sobrien } while ((segcnt -= 2) > 0); 63538494Sobrien#if NBPFILTER > 0 63638494Sobrien if (sc->tulip_bpf != NULL) 63738494Sobrien bpf_mtap(sc->tulip_bpf, m); 63838494Sobrien#endif 63938494Sobrien /* 64042633Sobrien * The descriptors have been filled in. Mark the first 64138494Sobrien * and last segments, indicate we want a transmit complete 64238494Sobrien * interrupt, give the descriptors to the TULIP, and tell 64338494Sobrien * it to transmit! 64442633Sobrien */ 64538494Sobrien 64638494Sobrien IF_ENQUEUE(&sc->tulip_txq, m); 64738494Sobrien eop->d_flag |= TULIP_DFLAG_TxLASTSEG|TULIP_DFLAG_TxWANTINTR; 64838494Sobrien sop->d_flag |= TULIP_DFLAG_TxFIRSTSEG; 64938494Sobrien sop->d_status = TULIP_DSTS_OWNER; 65038494Sobrien 65138494Sobrien *sc->tulip_csrs.csr_txpoll = 1; 65238494Sobrien } 65338494Sobrien if (m != NULL) { 65438494Sobrien ifp->if_flags |= IFF_OACTIVE; 65538494Sobrien IF_PREPEND(ifq, m); 65638494Sobrien } 65738494Sobrien} 65838494Sobrien 65942633Sobrienstatic int 66038494Sobrientulip_intr( 66138494Sobrien tulip_softc_t *sc) 66238494Sobrien{ 66338494Sobrien tulip_uint32_t csr; 66438494Sobrien 66538494Sobrien while ((csr = *sc->tulip_csrs.csr_status) & (TULIP_STS_NORMALINTR|TULIP_STS_ABNRMLINTR)) { 66638494Sobrien *sc->tulip_csrs.csr_status = csr & sc->tulip_intrmask; 66738494Sobrien 66838494Sobrien if (csr & TULIP_STS_SYSERROR) { 669174313Sobrien if ((csr & TULIP_STS_ERRORMASK) == TULIP_STS_ERR_PARITY) { 67038494Sobrien TULIP_RESET(sc); 671174313Sobrien tulip_init(sc->tulip_unit); 67238494Sobrien return 1; 67338494Sobrien } 67438494Sobrien } 67538494Sobrien if (csr & TULIP_STS_ABNRMLINTR) { 67638494Sobrien printf("%s%d: abnormal interrupt: 0x%05x [0x%05x]\n", 67738494Sobrien sc->tulip_name, sc->tulip_unit, csr, csr & sc->tulip_intrmask); 67838494Sobrien *sc->tulip_csrs.csr_command = sc->tulip_cmdmode; 67938494Sobrien } 68038494Sobrien if (csr & TULIP_STS_RXINTR) 68138494Sobrien tulip_rx_intr(sc); 68238494Sobrien if (sc->tulip_txinfo.ri_free < sc->tulip_txinfo.ri_max) { 68338494Sobrien tulip_tx_intr(sc); 68438494Sobrien tulip_start(&sc->tulip_if); 68542633Sobrien } 68638494Sobrien } 68738494Sobrien return 1; 68838494Sobrien} 68938494Sobrien 69038494Sobrien/* 69142633Sobrien * This is the standard method of reading the DEC Address ROMS. 69238494Sobrien */ 693static int 694tulip_read_macaddr( 695 tulip_softc_t *sc) 696{ 697 int cksum, rom_cksum, idx; 698 tulip_sint32_t csr; 699 unsigned char tmpbuf[8]; 700 static u_char testpat[] = { 0xFF, 0, 0x55, 0xAA, 0xFF, 0, 0x55, 0xAA }; 701 702 *sc->tulip_csrs.csr_enetrom = 1; 703 for (idx = 0; idx < 32; idx++) { 704 int cnt = 0; 705 while ((csr = *sc->tulip_csrs.csr_enetrom) < 0 && cnt < 10000) 706 cnt++; 707 sc->tulip_rombuf[idx] = csr & 0xFF; 708 } 709 710 if (bcmp(&sc->tulip_rombuf[0], &sc->tulip_rombuf[16], 8) != 0) { 711 /* 712 * Some folks don't use the standard ethernet rom format 713 * but instead just put the address in the first 6 bytes 714 * of the rom and let the rest be all 0xffs. (Can we say 715 * ZNYX???) 716 */ 717 for (idx = 6; idx < 32; idx++) { 718 if (sc->tulip_rombuf[idx] != 0xFF) 719 return -4; 720 } 721 /* 722 * Make sure the address is not multicast or locally assigned 723 * that the OUI is not 00-00-00. 724 */ 725 if ((sc->tulip_rombuf[0] & 3) != 0) 726 return -4; 727 if (sc->tulip_rombuf[0] == 0 && sc->tulip_rombuf[1] == 0 728 && sc->tulip_rombuf[2] == 0) 729 return -4; 730 bcopy(sc->tulip_rombuf, sc->tulip_hwaddr, 6); 731 return 0; 732 } 733 if (bcmp(&sc->tulip_rombuf[24], testpat, 8) != 0) 734 return -3; 735 736 tmpbuf[0] = sc->tulip_rombuf[15]; tmpbuf[1] = sc->tulip_rombuf[14]; 737 tmpbuf[2] = sc->tulip_rombuf[13]; tmpbuf[3] = sc->tulip_rombuf[12]; 738 tmpbuf[4] = sc->tulip_rombuf[11]; tmpbuf[5] = sc->tulip_rombuf[10]; 739 tmpbuf[6] = sc->tulip_rombuf[9]; tmpbuf[7] = sc->tulip_rombuf[8]; 740 if (bcmp(&sc->tulip_rombuf[0], tmpbuf, 8) != 0) 741 return -2; 742 743 bcopy(sc->tulip_rombuf, sc->tulip_hwaddr, 6); 744 745 cksum = *(u_short *) &sc->tulip_hwaddr[0]; 746 cksum *= 2; 747 if (cksum > 65535) cksum -= 65535; 748 cksum += *(u_short *) &sc->tulip_hwaddr[2]; 749 if (cksum > 65535) cksum -= 65535; 750 cksum *= 2; 751 if (cksum > 65535) cksum -= 65535; 752 cksum += *(u_short *) &sc->tulip_hwaddr[4]; 753 if (cksum >= 65535) cksum -= 65535; 754 755 rom_cksum = *(u_short *) &sc->tulip_rombuf[6]; 756 757 if (cksum != rom_cksum) 758 return -1; 759 return 0; 760} 761 762static unsigned 763tulip_mchash( 764 unsigned char *mca) 765{ 766 u_int idx, bit, data, crc = 0xFFFFFFFFUL; 767 768#ifdef __alpha 769 for (data = *(__unaligned u_long *) mca, bit = 0; bit < 48; bit++, data >>= 7701) 771 crc = (crc >> 1) ^ (((crc ^ data) & 1) ? TULIP_CRC32_POLY : 0); 772#else 773 for (idx = 0; idx < 6; idx++) 774 for (data = *mca++, bit = 0; bit < 8; bit++, data >>= 1) 775 crc = (crc >> 1) ^ (((crc ^ data) & 1) ? TULIP_CRC32_POLY : 0); 776#endif 777 return crc & 0x1FF; 778} 779 780static void 781tulip_addr_filter( 782 tulip_softc_t *sc) 783{ 784 tulip_uint32_t *sp = sc->tulip_setupdata; 785 struct ether_multistep step; 786 struct ether_multi *enm; 787 int i; 788 789 sc->tulip_flags &= ~TULIP_WANTHASH; 790 sc->tulip_flags |= TULIP_WANTSETUP; 791 sc->tulip_cmdmode &= ~TULIP_CMD_RXRUN; 792 sc->tulip_intrmask &= ~TULIP_STS_RXSTOPPED; 793 if (sc->tulip_ac.ac_multicnt > 14) { 794 unsigned hash; 795 /* 796 * If we have more than 14 multicasts, we have 797 * go into hash perfect mode (512 bit multicast 798 * hash and one perfect hardware). 799 */ 800 801 bzero(sc->tulip_setupdata, sizeof(sc->tulip_setupdata)); 802 hash = tulip_mchash(etherbroadcastaddr); 803 sp[hash >> 4] |= 1 << (hash & 0xF); 804 ETHER_FIRST_MULTI(step, &sc->tulip_ac, enm); 805 while (enm != NULL) { 806 hash = tulip_mchash(enm->enm_addrlo); 807 sp[hash >> 4] |= 1 << (hash & 0xF); 808 ETHER_NEXT_MULTI(step, enm); 809 } 810 sc->tulip_cmdmode |= TULIP_WANTHASH; 811 sp[40] = ((u_short *) sc->tulip_ac.ac_enaddr)[0]; 812 sp[41] = ((u_short *) sc->tulip_ac.ac_enaddr)[1]; 813 sp[42] = ((u_short *) sc->tulip_ac.ac_enaddr)[2]; 814 } else { 815 /* 816 * Else can get perfect filtering for 16 addresses. 817 */ 818 i = 0; 819 ETHER_FIRST_MULTI(step, &sc->tulip_ac, enm); 820 for (; enm != NULL; i++) { 821 *sp++ = ((u_short *) enm->enm_addrlo)[0]; 822 *sp++ = ((u_short *) enm->enm_addrlo)[1]; 823 *sp++ = ((u_short *) enm->enm_addrlo)[2]; 824 ETHER_NEXT_MULTI(step, enm); 825 } 826 /* 827 * If an IP address is enabled, turn on broadcast 828 */ 829 if (sc->tulip_ac.ac_ipaddr.s_addr != 0) { 830 i++; 831 *sp++ = 0xFFFF; 832 *sp++ = 0xFFFF; 833 *sp++ = 0xFFFF; 834 } 835 /* 836 * Pad the rest with our hardware address 837 */ 838 for (; i < 16; i++) { 839 *sp++ = ((u_short *) sc->tulip_ac.ac_enaddr)[0]; 840 *sp++ = ((u_short *) sc->tulip_ac.ac_enaddr)[1]; 841 *sp++ = ((u_short *) sc->tulip_ac.ac_enaddr)[2]; 842 } 843 } 844} 845 846/*extern void arp_ifinit(struct arpcom *, struct ifaddr*);*/ 847 848static int 849tulip_ioctl( 850 struct ifnet *ifp, 851 int cmd, 852 caddr_t data) 853{ 854 tulip_softc_t *sc = tulips[ifp->if_unit]; 855 struct ifaddr *ifa = (struct ifaddr *)data; 856 struct ifreq *ifr = (struct ifreq *) data; 857 int s, error = 0; 858 859 s = splimp(); 860 861 switch (cmd) { 862 case SIOCSIFADDR: { 863 864 ifp->if_flags |= IFF_UP; 865 switch(ifa->ifa_addr->sa_family) { 866#ifdef INET 867 case AF_INET: { 868 ((struct arpcom *)ifp)->ac_ipaddr = IA_SIN(ifa)->sin_addr; 869 tulip_addr_filter(sc); /* reset multicast filtering */ 870 (*ifp->if_init)(ifp->if_unit); 871 arp_ifinit((struct arpcom *)ifp, ifa); 872 break; 873 } 874#endif /* INET */ 875 876#ifdef NS 877 /* This magic copied from if_is.c; I don't use XNS, 878 * so I have no way of telling if this actually 879 * works or not. 880 */ 881 case AF_NS: { 882 struct ns_addr *ina = &(IA_SNS(ifa)->sns_addr); 883 if (ns_nullhost(*ina)) { 884 ina->x_host = *(union ns_host *)(sc->tulip_ac.ac_enaddr); 885 } else { 886 ifp->if_flags &= ~IFF_RUNNING; 887 bcopy((caddr_t)ina->x_host.c_host, 888 (caddr_t)sc->tulip_ac.ac_enaddr, 889 sizeof sc->tulip_ac.ac_enaddr); 890 } 891 892 (*ifp->if_init)(ifp->if_unit); 893 break; 894 } 895#endif /* NS */ 896 897 default: { 898 (*ifp->if_init)(ifp->if_unit); 899 break; 900 } 901 } 902 break; 903 } 904 905 case SIOCSIFFLAGS: { 906 /* 907 * Changing the connection forces a reset. 908 */ 909 if (sc->tulip_flags & TULIP_ALTPHYS) { 910 if ((ifp->if_flags & IFF_ALTPHYS) == 0) 911 TULIP_RESET(sc); 912 } else { 913 if (ifp->if_flags & IFF_ALTPHYS) 914 TULIP_RESET(sc); 915 } 916 (*ifp->if_init)(ifp->if_unit); 917 break; 918 } 919 920 case SIOCADDMULTI: 921 case SIOCDELMULTI: { 922 /* 923 * Update multicast listeners 924 */ 925 if (cmd == SIOCADDMULTI) 926 error = ether_addmulti(ifr, &sc->tulip_ac); 927 else 928 error = ether_delmulti(ifr, &sc->tulip_ac); 929 930 if (error == ENETRESET) { 931 tulip_addr_filter(sc); /* reset multicast filtering */ 932 (*ifp->if_init)(ifp->if_unit); 933 error = 0; 934 } 935 break; 936 } 937 case SIOCSIFMTU: 938 /* 939 * Set the interface MTU. 940 */ 941 if (ifr->ifr_mtu > ETHERMTU) { 942 error = EINVAL; 943 } else { 944 ifp->if_mtu = ifr->ifr_mtu; 945 } 946 break; 947 948 default: { 949 error = EINVAL; 950 break; 951 } 952 } 953 954 splx(s); 955 return error; 956} 957 958static void 959tulip_attach( 960 tulip_softc_t *sc) 961{ 962 struct ifnet *ifp = &sc->tulip_if; 963 int cnt; 964 965 ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; 966 967 *sc->tulip_csrs.csr_sia_connectivity = 0; 968 *sc->tulip_csrs.csr_sia_connectivity = TULIP_SIACONN_10BASET; 969 for (cnt = 0; cnt < 240000; cnt++) { 970 if ((*sc->tulip_csrs.csr_sia_status & TULIP_SIASTS_LINKFAIL) == 0) 971 break; 972 DELAY(10); 973 } 974 if (*sc->tulip_csrs.csr_sia_status & TULIP_SIASTS_LINKFAIL) { 975 ifp->if_flags |= IFF_ALTPHYS; 976 } else { 977 sc->tulip_flags |= TULIP_ALTPHYS; 978 } 979 TULIP_RESET(sc); 980 981 ifp->if_init = tulip_init; 982 ifp->if_ioctl = tulip_ioctl; 983 ifp->if_output = ether_output; 984 ifp->if_reset = tulip_reset; 985 ifp->if_start = tulip_start; 986 987 printf("%s%d: %s pass %d.%d ethernet address %s\n", 988 sc->tulip_name, sc->tulip_unit, 989 tulip_chipdescs[tulip_chipids[sc->tulip_unit]], 990 (sc->tulip_revinfo & 0xF0) >> 4, 991 sc->tulip_revinfo & 0x0F, 992 ether_sprintf(sc->tulip_hwaddr)); 993 994 if_attach(ifp); 995 996#if NBPFILTER > 0 997 bpfattach(&sc->tulip_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header)); 998#endif 999} 1000 1001static void 1002tulip_initcsrs( 1003 tulip_softc_t *sc, 1004 volatile tulip_uint32_t *va_csrs, 1005 size_t csr_size) 1006{ 1007 sc->tulip_csrs.csr_busmode = va_csrs + 0 * csr_size; 1008 sc->tulip_csrs.csr_txpoll = va_csrs + 1 * csr_size; 1009 sc->tulip_csrs.csr_rxpoll = va_csrs + 2 * csr_size; 1010 sc->tulip_csrs.csr_rxlist = va_csrs + 3 * csr_size; 1011 sc->tulip_csrs.csr_txlist = va_csrs + 4 * csr_size; 1012 sc->tulip_csrs.csr_status = va_csrs + 5 * csr_size; 1013 sc->tulip_csrs.csr_command = va_csrs + 6 * csr_size; 1014 sc->tulip_csrs.csr_intr = va_csrs + 7 * csr_size; 1015 sc->tulip_csrs.csr_missed_frame = va_csrs + 8 * csr_size; 1016 sc->tulip_csrs.csr_enetrom = va_csrs + 9 * csr_size; 1017 sc->tulip_csrs.csr_reserved = va_csrs + 10 * csr_size; 1018 sc->tulip_csrs.csr_full_duplex = va_csrs + 11 * csr_size; 1019 sc->tulip_csrs.csr_sia_status = va_csrs + 12 * csr_size; 1020 sc->tulip_csrs.csr_sia_connectivity = va_csrs + 13 * csr_size; 1021 sc->tulip_csrs.csr_sia_tx_rx = va_csrs + 14 * csr_size; 1022 sc->tulip_csrs.csr_sia_general = va_csrs + 15 * csr_size; 1023} 1024 1025static void 1026tulip_initring( 1027 tulip_softc_t *sc, 1028 tulip_ringinfo_t *ri, 1029 tulip_desc_t *descs, 1030 int ndescs) 1031{ 1032 ri->ri_max = ndescs; 1033 ri->ri_first = descs; 1034 ri->ri_last = ri->ri_first + ri->ri_max; 1035 bzero((caddr_t) ri->ri_first, sizeof(ri->ri_first[0]) * ri->ri_max); 1036 ri->ri_last[-1].d_flag = TULIP_DFLAG_ENDRING; 1037} 1038 1039#if NPCI > 0 1040/* 1041 * This is the PCI configuration support. Since the DC21040 is available 1042 * on both EISA and PCI boards, one must be careful in how defines the 1043 * DC21040 in the config file. 1044 */ 1045static char* tulip_pci_probe (pcici_t config_id, pcidi_t device_id); 1046static void tulip_pci_attach(pcici_t config_id, int unit); 1047static u_long tulip_count; 1048 1049struct pci_device dedevice = { 1050 "de", 1051 tulip_pci_probe, 1052 tulip_pci_attach, 1053 &tulip_count, 1054}; 1055 1056DATA_SET (pcidevice_set, dedevice); 1057 1058#define PCI_CFID 0x00 /* Configuration ID */ 1059#define PCI_CFCS 0x04 /* Configurtion Command/Status */ 1060#define PCI_CFRV 0x08 /* Configuration Revision */ 1061#define PCI_CFLT 0x0c /* Configuration Latency Timer */ 1062#define PCI_CBIO 0x10 /* Configuration Base IO Address */ 1063#define PCI_CBMA 0x14 /* Configuration Base Memory Address */ 1064#define PCI_CFIT 0x3c /* Configuration Interrupt */ 1065#define PCI_CFDA 0x40 /* Configuration Driver Area */ 1066 1067#define TULIP_PCI_CSRSIZE (8 / sizeof(tulip_uint32_t)) 1068static char* 1069tulip_pci_probe( 1070 pcici_t config_id, 1071 pcidi_t device_id) 1072{ 1073 int idx; 1074 for (idx = 0; idx < NDE; idx++) { 1075 if (tulips[idx] == NULL) { 1076 if (device_id == 0x00021011ul) { 1077 tulip_chipids[idx] = TULIP_DC21040; 1078 return "Digital DC21040 Ethernet"; 1079 } 1080 if (device_id == 0x00091011ul) { 1081 tulip_chipids[idx] = TULIP_DC21140; 1082 return "Digital DC21140 Fast Ethernet"; 1083 } 1084 return NULL; 1085 } 1086 } 1087 return NULL; 1088} 1089 1090static void 1091tulip_pci_attach( 1092 pcici_t config_id, 1093 int unit) 1094{ 1095 tulip_softc_t *sc; 1096 int retval, idx; 1097 vm_offset_t va_csrs, pa_csrs; 1098 tulip_desc_t *rxdescs, *txdescs; 1099 1100 sc = (tulip_softc_t *) malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT); 1101 if (sc == NULL) 1102 return; 1103 1104 rxdescs = (tulip_desc_t *) 1105 malloc(sizeof(tulip_desc_t) * TULIP_RXDESCS, M_DEVBUF, M_NOWAIT); 1106 if (rxdescs == NULL) { 1107 free((caddr_t) sc, M_DEVBUF); 1108 return; 1109 } 1110 1111 txdescs = (tulip_desc_t *) 1112 malloc(sizeof(tulip_desc_t) * TULIP_TXDESCS, M_DEVBUF, M_NOWAIT); 1113 if (txdescs == NULL) { 1114 free((caddr_t) rxdescs, M_DEVBUF); 1115 free((caddr_t) sc, M_DEVBUF); 1116 return; 1117 } 1118 1119 bzero(sc, sizeof(*sc)); /* Zero out the softc*/ 1120 sc->tulip_rxspace = vm_page_alloc_contig(TULIP_RXSPACE + NBPG, 0, 0xffffffff, PAGE_SIZE); 1121 /* 1122 * We've allocated an extra page of receive space so we can double map 1123 * the first page of the receive space into the page after the last page 1124 * of the receive space. This means that even if a receive wraps around 1125 * the end of the receive space, it will still virtually contiguous and 1126 * that greatly simplifies the recevie logic. 1127 */ 1128 pmap_enter(pmap_kernel(), sc->tulip_rxspace + TULIP_RXSPACE, 1129 vtophys(sc->tulip_rxspace), VM_PROT_READ|VM_PROT_WRITE, TRUE); 1130 1131 sc->tulip_unit = unit; 1132 sc->tulip_name = "de"; 1133 retval = pci_map_mem(config_id, PCI_CBMA, &va_csrs, &pa_csrs); 1134 if (!retval) { 1135 kmem_free(kernel_map, sc->tulip_rxspace, TULIP_RXSPACE + NBPG); 1136 free((caddr_t) txdescs, M_DEVBUF); 1137 free((caddr_t) rxdescs, M_DEVBUF); 1138 free((caddr_t) sc, M_DEVBUF); 1139 return; 1140 } 1141 tulips[unit] = sc; 1142 tulip_initcsrs(sc, (volatile tulip_uint32_t *) va_csrs, TULIP_PCI_CSRSIZE); 1143 tulip_initring(sc, &sc->tulip_rxinfo, rxdescs, TULIP_RXDESCS); 1144 tulip_initring(sc, &sc->tulip_txinfo, txdescs, TULIP_TXDESCS); 1145 sc->tulip_revinfo = pci_conf_read(config_id, PCI_CFRV); 1146 if ((retval = tulip_read_macaddr(sc)) < 0) { 1147 printf("de%d: can't read ENET ROM (why=%d) (", sc->tulip_unit, retval); 1148 for (idx = 0; idx < 32; idx++) 1149 printf("%02x", sc->tulip_rombuf[idx]); 1150 printf("\n"); 1151 printf("%s%d: %s pass %d.%d ethernet address %s\n", 1152 sc->tulip_name, sc->tulip_unit, 1153 tulip_chipdescs[tulip_chipids[sc->tulip_unit]], 1154 (sc->tulip_revinfo & 0xF0) >> 4, sc->tulip_revinfo & 0x0F, 1155 "unknown"); 1156 } else { 1157 TULIP_RESET(sc); 1158 tulip_attach(sc); 1159 pci_map_int (config_id, tulip_intr, (void*) sc, &net_imask); 1160 } 1161} 1162#endif /* NPCI > 0 */ 1163#endif /* NDE > 0 */ 1164