📄 if_en.c
字号:
/* * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc. * * 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. * * from: $Hdr: if_en.c,v 4.300 91/06/09 06:25:54 root Rel41 $ SONY * * @(#)if_en.c 8.1 (Berkeley) 6/11/93 */#include "en.h"#include "rawether.h"#include "bpfilter.h"#if NEN > 0/* * Interlan Ethernet Communications Controller interface */#include <sys/types.h>#include <machine/pte.h>#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/ioctl.h>#include <sys/errno.h>#include <sys/time.h>#include <sys/cdefs.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#include <news3400/if/if_news.h>#include <news3400/if/if_en.h>#ifdef CPU_SINGLE#include <news3400/hbdev/hbvar.h>#define iop_device hb_device#define iop_driver hb_driver#define ii_unit hi_unit#define ii_intr hi_intr#define ii_alive hi_alive#else#include <news3400/iop/iopvar.h>#endifint enprobe(), enattach(), enrint(), enxint();struct mbuf *m_devget();#ifdef CPU_SINGLEstruct hb_device *eninfo[NEN];struct hb_driver endriver = { enprobe, 0, enattach, 0, 0, "en", eninfo };#elsestruct iop_device *eninfo[NEN];struct iop_driver endriver = { enprobe, 0, enattach, 0, "en", eninfo };#endif#define ENUNIT(x) minor(x)int eninit(),enioctl(),enreset(),enwatch(),enstart();int endebug = 0;struct ether_addr { u_char addr[6];};extern struct ifnet loif;struct en_softc en_softc[NEN];#if NBPFILTER > 0#include <net/bpf.h>#endifenprobe(ii) struct iop_device *ii;{ return (en_probe(ii));}/* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. A STATUS command is done to get the ethernet * address and other interesting data. */enattach(ii) register struct iop_device *ii;{ register struct en_softc *es = &en_softc[ii->ii_unit]; register struct ifnet *ifp = &es->es_if; extern char *ether_sprintf(); en_attach(ii->ii_unit); printf("en%d: hardware address %s\n", ii->ii_unit, ether_sprintf((u_char *)es->es_addr)); ifp->if_unit = ii->ii_unit; ifp->if_name = "en"; ifp->if_mtu = ETHERMTU; ifp->if_init = eninit; ifp->if_ioctl = enioctl; ifp->if_output = ether_output;#ifdef NOTDEF /* KU:XXX if_reset is obsolete */ ifp->if_reset = enreset;#endif ifp->if_start = enstart; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;#if NBPFILTER > 0 bpfattach(&es->es_bpf, ifp, DLT_EN10MB, sizeof(struct ether_header));#endif if_attach(ifp);}/* * Reset of interface after IOP reset. */enreset(unit) int unit;{ register struct iop_device *ii; if (unit >= NEN || (ii = eninfo[unit]) == 0 || ii->ii_alive == 0) return; printf(" en%d", unit); en_softc[unit].es_if.if_flags &= ~(IFF_RUNNING|IFF_OACTIVE); en_softc[unit].es_flags &= ~ENF_RUNNING; eninit(unit);}/* * Initialization of interface; clear recorded pending * operations, and reinitialize IOP usage. */eninit(unit) int unit;{ register struct en_softc *es = &en_softc[unit]; register struct ifnet *ifp = &es->es_if; int s; /* not yet, if address still unknown */ if (ifp->if_addrlist == (struct ifaddr *)0) return; if (es->es_flags & ENF_RUNNING) return; if ((ifp->if_flags & IFF_RUNNING) == 0) { if (if_newsinit(&es->es_ifnews, sizeof (struct en_rheader), (int)btoc(ETHERMTU)) == 0) { printf("en%d: can't initialize\n", unit); es->es_if.if_flags &= ~IFF_UP; return; } ifp->if_watchdog = enwatch; es->es_interval = ENWATCHINTERVAL; ifp->if_timer = es->es_interval; s = splimp(); en_init(unit); splx(s); } es->es_if.if_flags |= IFF_RUNNING|IFF_NOTRAILERS; es->es_flags |= ENF_RUNNING;}/* * Start output on interface. * Get another datagram to send off of the interface queue, * and map it to the interface before starting the output. */enstart(ifp) register struct ifnet *ifp;{ int unit = ifp->if_unit, len; register struct en_softc *es = &en_softc[unit]; register struct mbuf *m; int s; IF_DEQUEUE(&es->es_if.if_snd, m); if (m == 0) return(0);#ifdef CPU_SINGLE es->es_ifnews.ifn_waddr = (caddr_t)get_xmit_buffer(unit);#endif len = if_wnewsput(&es->es_ifnews, m); /* * Ensure minimum packet length. * This makes the safe assumtion that there are no virtual holes * after the data. * For security, it might be wise to zero out the added bytes, * but we're mainly interested in speed at the moment. */ if (len - sizeof(struct ether_header) < ETHERMIN) len = ETHERMIN + sizeof(struct ether_header); s = splclock(); /* KU:XXX should be gone */ en_start(unit, len); es->es_if.if_flags |= IFF_OACTIVE; (void) splx(s); /* KU:XXX */#if NBPFILTER > 0 /* * If bpf is listening on this interface, let it * see the packet before we commit it to the wire. */ if (es->es_bpf) {#ifdef CPU_SINGLE bpf_tap(es->es_bpf, es->es_ifnews.ifn_waddr, len);#else bpf_mtap(es->es_bpf, m);#endif }#endif /* NBPFILTER > 0 */ return(0);}/* * Transmit done interrupt. */_enxint(unit, error, collision) int unit; int error, collision;{ register struct en_softc *es = &en_softc[unit];#ifdef notyet /* KU:XXX */ intrcnt[INTR_ETHER0 + unit]++;#endif if ((es->es_if.if_flags & IFF_OACTIVE) == 0) { printf("en%d: stray xmit interrupt\n", unit); return; } else { es->es_if.if_flags &= ~IFF_OACTIVE; es->es_if.if_opackets++; } if (error) es->es_if.if_oerrors++; if (collision) es->es_if.if_collisions++; enstart(&es->es_if);}/* * Ethernet interface receiver interrupt. * If input error just drop packet. * Otherwise purge input buffered data path and examine * packet to determine type. If can't determine length * from type, then have to drop packet. Othewise decapsulate * packet based on type and pass to type specific higher-level * input routine. */_enrint(unit, len) int unit; register int len;{ register struct en_softc *es = &en_softc[unit]; register struct en_rheader *en; struct mbuf *m; int off, resid, s; int type; register struct ensw *esp; extern struct mbuf *if_rnewsget();#if defined(mips) && defined(CPU_SINGLE) int bxcopy();#endif#ifdef notyet /* KU:XXX */ intrcnt[INTR_ETHER0 + unit]++;#endif es->es_if.if_ipackets++; if ((es->es_flags & ENF_RUNNING) == 0) return; en = (struct en_rheader *)(es->es_ifnews.ifn_raddr); if (len < ETHERMIN || len > ETHERMTU) { es->es_if.if_ierrors++; return; }#if NBPFILTER > 0 /* * Check if there's a bpf filter listening on this interface. * If so, hand off the raw packet to enet. */ if (es->es_bpf) { bpf_tap(es->es_bpf, es->es_ifnews.ifn_raddr, len + sizeof(struct en_rheader)); /* * Note that the interface cannot be in promiscuous mode if * there are no bpf listeners. And if we are in promiscuous * mode, we have to check if this packet is really ours. * * XXX This test does not support multicasts. */ if ((es->es_if.if_flags & IFF_PROMISC) && bcmp(en->enr_dhost, es->es_addr, sizeof(en->enr_dhost)) != 0 && bcmp(en->enr_dhost, etherbroadcastaddr, sizeof(en->enr_dhost)) != 0) return; }#endif /* NBPFILTER > 0 */ /* * Deal with trailer protocol: if type is trailer type * get true type from first 16-bit word past data. * Remember that type was trailer by setting off. */ en->enr_type = ntohs((u_short)en->enr_type);#define endataaddr(en, off, type) ((type)(((caddr_t)((en)+1)+(off)))) if (en->enr_type >= ETHERTYPE_TRAIL &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -