📄 if_ec.c
字号:
/* * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)if_ec.c 8.1 (Berkeley) 6/11/93 *//* WARNING -- THIS DRIVER DOES NOT WORK YET -- It is merely a sketch */#include "ec.h"#if NEC > 0/* * Intel 82586/3com Etherlink II controller. */#include <sys/param.h>#include <sys/systm.h>#include <sys/mbuf.h>#include <sys/buf.h>#include <sys/protosw.h>#include <sys/socket.h>#include <sys/syslog.h>#include <sys/ioctl.h>#include <sys/errno.h>#include <net/if.h>#include <net/netisr.h>#include <net/route.h>#ifdef INET#include <netinet/in.h>#include <netinet/in_systm.h>#include <netinet/in_var.h>#include <netinet/ip.h>#include <netinet/if_ether.h>#endif#ifdef NS#include <netns/ns.h>#include <netns/ns_if.h>#endif#ifdef ISOextern char all_es_snpa[], all_is_snpa[], all_l1is_snpa[], all_l2is_snpa[];#endif#include <i386/isa/if_ecreg.h>#if NBPFILTER > 0#include <net/bpf.h>#include <net/bpfdesc.h>#endifint ecdebug = 1; /* console error messages */int ecintr(), ecinit(), ecioctl(), ecstart(), ether_output();int ecattach(), ecprobe(), ecreset(), ecwatchdog();void ec_idpattern(), ec_reset_all(), ec_getnmdata(), ecread();struct mbuf *m_devget();extern struct ifnet loif;struct ec_82586params ec_82586defaults = { 11, 0xc8, ECMINSIZE, 0x2e, 0, 0x60, 0, 2, 0, 0, 0x40}; /* 2e == no source insert *//* * Ethernet software status per interface. * * Each interface is referenced by a network interface structure, * sc_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... */struct ec_softc { struct arpcom sc_ac; /* common Ethernet structures */#define sc_if sc_ac.ac_if /* network-visible interface */#define sc_addr sc_ac.ac_enaddr /* hardware Ethernet address */ caddr_t sc_device; /* e.g. isa_device */ caddr_t sc_bpf; /* for packet filter */ struct ec_ports *sc_ports; /* control ports for this unit */ struct ec_mem *sc_hmem; /* Host addr for shared memory */ struct ec_mem *sc_dmem; /* Device (chip) addr for shared mem */ int sc_msize; /* How much memory is mapped? */ int sc_iflags; /* copy of sc_if.if_flags for state */ int sc_rxnum; /* Last receiver dx we looked at */ int sc_txnum; /* Last tranmistter dx we stomped on */ int sc_txcnt; /* Number of packets queued for tx*/ int sc_xint; /* errors */ int sc_txbusy; /* we're confused */ int sc_uflo; /* DMA Late */ int sc_runt; /* too short */ int sc_txbad; int sc_rxlen;} ec_softc[NEC];#include <i386/isa/isa_device.h>struct isa_driver ecdriver = { ecprobe, ecattach, "ec",};#define TIMO 10000 /* used in ec_uprim */ecprobe(id) register struct isa_device *id;{ int unit = id->id_unit, msize = id->id_msize; struct ec_ports *reg = (struct ec_ports *)id->id_iobase; register struct ec_softc *ec = ec_softc + unit; u_char data[6]; ec_reset_all(); bzero((caddr_t)data, sizeof(data)); ec_getnmdata(reg, R_ECID, data); if (bcmp((caddr_t)data, "*3COM*", sizeof(data)) != 0) { if (ecdebug) { printf("ecprobe: ec%d not matched: %s\n", unit, ether_sprintf(data)); } return 0; } ec_getnmdata(reg, R_ETHER, ec->sc_addr); ec_getnmdata(reg, R_REV, data); ec->sc_hmem = (struct ec_mem *) (id->id_maddr); ec->sc_dmem = (struct ec_mem *) (0x10000 - msize); ec->sc_msize = msize; ec->sc_device = (caddr_t) id; ec->sc_ports = reg; printf("ec%d: hardware address %s, rev info %s\n", unit, ether_sprintf(ec->sc_addr), ether_sprintf(data)); return 1;}voidec_idpattern(){ int i = 255, n; register caddr_t p = (caddr_t)0x100; for (n = 255; n > 0; n--) { outb(p, i); if ((i <<= 1) & 0x100) i ^= 0xe7; }}voidec_reset_all(){ register caddr_t p = (caddr_t)0x100; outb(p, 0); ec_idpattern(); outb(p, 0);}extern int cpuspeed;#define ECWR(p, e, d) outb(&(p->e), d)#define ECRD(p, e) inb(&(p->e))#define SET_CA ECWR(ec->sc_ports, port_ca, 0)#define UNLATCH_INT ECWR(ec->sc_ports, port_ic, 0);voidec_getnmdata(p, which, data)register struct ec_ports *p;int which;register u_char *data;{ register int i; ECWR(p, creg, which); DELAY(2); for (i = 0; i < 6; i++) { DELAY(2); data[i] = ECRD(p, data[i]); }}ecreset(unit) register int unit;{ register struct ec_softc *ec = &ec_softc[unit]; struct ec_ports *p = ec->sc_ports; struct ec_mem *hmem = ec->sc_hmem; int timo; ECWR(p, creg, R_LPB); DELAY(10); if ((ec->sc_if.if_flags & IFF_RUNNING) == 0) return 0; if (ecdebug) printf("ec%dreset\n", unit); ec_meminit(ec); ECWR(p, creg, R_NORST); DELAY(10); hmem->iscp.busy = 1; ECWR(p, port_ca, 0); DELAY(10); for (timo = TIMO; hmem->iscp.busy; ) timo--; if (timo == 0) { printf("ec(%d)reset: iscp failed\n", unit); return 0; } hmem->scb.command = CU_START; ECWR(p, port_ca, 0); DELAY(10); for (timo = TIMO; (hmem->scb.status & CU_STATE) == CUS_ACTIVE;) timo--; if (timo == 0 || (hmem->scb.status & CU_STATE) != CUS_IDLE) { printf("ec(%d)reset: setup failed\n", unit); return 0; } ECWR(p, port_ic, 0); DELAY(10); ECWR(p, creg, R_NORST|R_IEN); hmem->scb.command = RU_START | (hmem->scb.status & 0xf000); ECWR(p, port_ca, 0); DELAY(10); ec->sc_if.if_timer = 5; return 0; /* Keep GCC Happy! */}/* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. */ecattach(id) register struct isa_device *id;{ int unit = id->id_unit; struct ec_softc *ec = &ec_softc[unit]; struct ifnet *ifp = &ec->sc_if; ifp->if_unit = unit; ifp->if_name = "ec"; ifp->if_mtu = ETHERMTU; ifp->if_init = ecinit; ifp->if_init = ecreset; ifp->if_ioctl = ecioctl; ifp->if_watchdog = ecwatchdog; ifp->if_output = ether_output; ifp->if_start = ecstart; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;#if NBPFILTER > 0 bpfattach(&ec->sc_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));#endif if_attach(ifp); return (1);}#define OFF(e) ((u_short)&(((struct ec_mem *)0)->e))ec_meminit(ec) register struct ec_softc *ec;{ register struct ec_mem *hmem = ec->sc_hmem; register int i; struct ec_rfd *rc = hmem->rcom; struct ec_transmit *tc = hmem->tcom; caddr_t cp; bzero((caddr_t)hmem, ec->sc_msize); *(struct ec_mem **) (ec->sc_msize - 4 + (caddr_t)ec->sc_hmem) = ec->sc_dmem; hmem->iscp.scb_off = OFF(scb); hmem->iscp.scb_base = (caddr_t)ec->sc_dmem; hmem->scb.rfa_off = OFF(rcom[0]); hmem->scb.cbl_off = OFF(config); hmem->config.com1 = COM1_CONFIGURE; bcopy((caddr_t)&ec_82586defaults, (caddr_t)&hmem->config.modes, sizeof(hmem->config.modes));#if NBPFILTER > 0 if (ec->sc_if.if_flags & IFF_PROMISC) hmem->config.modes.promisc |= M_PROMISC;#endif hmem->config.next_off = OFF(iasetup); bcopy((caddr_t)ec->sc_addr, (caddr_t)hmem->iasetup.srcaddr, 6);#ifndef ISO hmem->iasetup.com1 = COM1_IASETUP | COM1_S | COM1_EL;#else hmem->iasetup.com1 = COM1_IASETUP; hmem->iasetup.next_off = OFF(mcsetup); hmem->mcsetup.com1 = COM1_MCSETUP | COM1_S | COM1_EL; hmem->mcsetup.count = 24; cp = (caddr_t)hmem->txbuf[0]; bcopy((caddr_t)all_es_snpa, cp, 6); cp += 6; bcopy((caddr_t)all_is_snpa, cp, 6); cp += 6; bcopy((caddr_t)all_l1is_snpa, cp, 6); cp += 6; bcopy((caddr_t)all_l2is_snpa, cp, 6); cp += 6;#endif for (i = 0; i < NTXBUF; i++) { tc->tbd_off = OFF(tcom[i].count); tc->buffer = ec->sc_dmem->txbuf[i]; (tc++)->com1 = COM1_TRANSMIT | COM1_S | COM1_EL | COM1_I; } for (i = 0; i < NRXBUF; i++) { rc->next_off = OFF(rcom[i + 1]); rc->rbd_off = OFF(rcom[i].count); rc->buffer = ec->sc_dmem->rxbuf[i]; (rc++)->size = ECMTU | COM1_EL; } (--rc)->next_off = OFF(rcom[0]);}/* * Initialization of interface */ecinit(unit) int unit;{ register struct ifnet *ifp = &ec_softc[unit].sc_if; register struct ifaddr *ifa; int s; /* not yet, if address still unknown */ for (ifa = ifp->if_addrlist;; ifa = ifa->ifa_next) if (ifa == 0) return 0; else if (ifa->ifa_addr && ifa->ifa_addr->sa_family != AF_LINK) break; if ((ifp->if_flags & IFF_RUNNING) == 0) { s = splimp(); ifp->if_flags |= IFF_RUNNING; ecreset(unit); (void) ecstart(ifp); splx(s); } return 0;}/* * Timeout: for now check for a transmit command taking more than 10 seconds. */ecwatchdog(unit) int unit;{ register struct ec_softc *ec = ec_softc + unit; if (ec->sc_iflags & IFF_OACTIVE) { ec->sc_if.if_flags &= ~IFF_RUNNING; ecinit(unit); } else if (ec->sc_txcnt > 0) ec->sc_iflags |= IFF_OACTIVE; ec->sc_if.if_timer = 5;}ec_txstart(ec)register struct ec_softc *ec;{ struct ec_mem *hmem = ec->sc_hmem; int i; if ((i = ec->sc_txnum - ec->sc_txcnt) < 0) i += NTXBUF; hmem->scb.cbl_off = OFF(tcom[i]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -