📄 if_enp.c
字号:
/* * Copyright (c) 1988 Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Computer Consoles 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. * * @(#)if_enp.c 7.8 (Berkeley) 12/16/90 */#include "enp.h"#if NENP > 0/* * CMC ENP-20 Ethernet 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/vmmac.h"#include "sys/ioctl.h"#include "sys/errno.h"#include "sys/vmparam.h"#include "sys/syslog.h"#include "sys/uio.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/ip_var.h"#include "netinet/if_ether.h"#endif#ifdef NS#include "netns/ns.h"#include "netns/ns_if.h"#endif#include "../include/cpu.h"#include "../include/pte.h"#include "../include/mtpr.h"#include "../vba/vbavar.h"#include "../if/if_enpreg.h"#define ENPSTART 0xf02000 /* standard enp start addr */#define ENPUNIT(dev) (minor(dev)) /* for enp ram devices *//* macros for dealing with longs in i/o space */#define ENPGETLONG(a) ((((u_short *)(a))[0] << 16)|(((u_short *)(a))[1]))#define ENPSETLONG(a,v) \ { register u_short *wp = (u_short *)(a); \ wp[0] = ((u_short *)&(v))[0]; wp[1] = ((u_short *)&(v))[1];}int enpprobe(), enpattach(), enpintr();long enpstd[] = { 0xfff41000, 0xfff61000, 0 };struct vba_device *enpinfo[NENP];struct vba_driver enpdriver = { enpprobe, 0, enpattach, 0, enpstd, "enp", enpinfo, "enp-20", 0 };int enpinit(), enpioctl(), enpreset(), enpoutput(), enpstart();struct mbuf *enpget();/* * Ethernet software status per interface. * * Each interface is referenced by a network interface structure, * es_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... */struct enp_softc { struct arpcom es_ac; /* common ethernet structures */#define es_if es_ac.ac_if#define es_addr es_ac.ac_enaddr short es_ivec; /* interrupt vector */} enp_softc[NENP]; extern struct ifnet loif;enpprobe(reg, vi) caddr_t reg; struct vba_device *vi;{ register br, cvec; /* must be r12, r11 */ register struct enpdevice *addr = (struct enpdevice *)reg; struct enp_softc *es = &enp_softc[vi->ui_unit];#ifdef lint br = 0; cvec = br; br = cvec; enpintr(0);#endif if (badaddr((caddr_t)addr, 2) || badaddr((caddr_t)&addr->enp_ram[0], 2)) return (0); es->es_ivec = --vi->ui_hd->vh_lastiv; addr->enp_state = S_ENPRESET; /* reset by VERSAbus reset */ br = 0x14, cvec = es->es_ivec; /* XXX */ return (sizeof (struct enpdevice));}/* * Interface exists: make available by filling in network interface * record. System will initialize the interface when it is ready * to accept packets. */enpattach(ui) register struct vba_device *ui;{ struct enp_softc *es = &enp_softc[ui->ui_unit]; register struct ifnet *ifp = &es->es_if; ifp->if_unit = ui->ui_unit; ifp->if_name = "enp"; ifp->if_mtu = ETHERMTU; ifp->if_init = enpinit; ifp->if_ioctl = enpioctl; ifp->if_output = ether_output; ifp->if_start = enpstart; ifp->if_reset = enpreset; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; if_attach(ifp);}/* * Reset of interface after "system" reset. */enpreset(unit, vban) int unit, vban;{ register struct vba_device *ui; if (unit >= NENP || (ui = enpinfo[unit]) == 0 || ui->ui_alive == 0 || ui->ui_vbanum != vban) return; printf(" enp%d", unit); enpinit(unit);}/* * Initialization of interface; clear recorded pending operations. */enpinit(unit) int unit;{ struct enp_softc *es = &enp_softc[unit]; register struct vba_device *ui = enpinfo[unit]; struct enpdevice *addr; register struct ifnet *ifp = &es->es_if; int s; if (ifp->if_addrlist == (struct ifaddr *)0) return; if ((ifp->if_flags & IFF_RUNNING) == 0) { addr = (struct enpdevice *)ui->ui_addr; s = splimp(); RESET_ENP(addr); DELAY(200000); es->es_if.if_flags |= IFF_RUNNING; splx(s); }}/* * Ethernet interface interrupt. */enpintr(unit) int unit;{ register struct enpdevice *addr; register BCB *bcbp; addr = (struct enpdevice *)enpinfo[unit]->ui_addr;#if ENP == 30 if (!IS_ENP_INTR(addr)) return; ACK_ENP_INTR(addr);#endif while ((bcbp = (BCB *)ringget((RING *)&addr->enp_tohost )) != 0) { enpread(&enp_softc[unit], bcbp); (void) ringput((RING *)&addr->enp_enpfree, bcbp); }}/* * Read input packet, examine its packet type, and enqueue it. */enpread(es, bcbp) struct enp_softc *es; register BCB *bcbp;{ register struct ether_header *enp; struct mbuf *m; int s, len, off, resid; es->es_if.if_ipackets++; /* * Get input data length. * Get pointer to ethernet header (in input buffer). * Deal with trailer protocol: if type is PUP trailer * get true type from first 16-bit word past data. * Remember that type was trailer by setting off. */ len = bcbp->b_msglen - sizeof (struct ether_header); enp = (struct ether_header *)ENPGETLONG(&bcbp->b_addr);#define enpdataaddr(enp, off, type) \ ((type)(((caddr_t)(((char *)enp)+sizeof (struct ether_header))+(off)))) enp->ether_type = ntohs((u_short)enp->ether_type); if (enp->ether_type >= ETHERTYPE_TRAIL && enp->ether_type < ETHERTYPE_TRAIL+ETHERTYPE_NTRAILER) { off = (enp->ether_type - ETHERTYPE_TRAIL) * 512; if (off >= ETHERMTU) return; enp->ether_type = ntohs(*enpdataaddr(enp, off, u_short *)); resid = ntohs(*(enpdataaddr(enp, off+2, u_short *))); if (off + resid > len) return; len = off + resid; } else off = 0; if (len == 0) return; /* * Pull packet off interface. Off is nonzero if packet * has trailing header; enpget will then force this header * information to be at the front. */ m = enpget((u_char *)enp, len, off, &es->es_if); if (m == 0) return; ether_input(&es->es_if, enp, m);}enpstart(ifp) struct ifnet *ifp;{ if (enpput(ifp)) return (ENOBUFS); else return (0);}/* * Routine to copy from mbuf chain to transmitter buffer on the VERSAbus. */enpput(ifp)struct ifnet *ifp;{ register BCB *bcbp; register struct enpdevice *addr; register struct mbuf *mp; register u_char *bp; register u_int len; int unit = ifp->if_unit, ret = 1; struct mbuf *m; addr = (struct enpdevice *)enpinfo[unit]->ui_addr;again: if (ringempty((RING *)&addr->enp_hostfree)) { /* ifp->if_flags |= IFF_OACTIVE; */ return (ret); } IF_DEQUEUE(&ifp->if_snd, m); if (m == 0) { ifp->if_flags &= ~IFF_OACTIVE; return (0); } bcbp = (BCB *)ringget((RING *)&addr->enp_hostfree); bcbp->b_len = 0; bp = (u_char *)ENPGETLONG(&bcbp->b_addr); for (mp = m; mp; mp = mp->m_next) { len = mp->m_len; if (len == 0) continue; enpcopy(mtod(mp, u_char *), bp, len); bp += len; bcbp->b_len += len; } bcbp->b_len = max(ETHERMIN+sizeof (struct ether_header), bcbp->b_len); bcbp->b_reserved = 0; if (ringput((RING *)&addr->enp_toenp, bcbp) == 1) INTR_ENP(addr); m_freem(m); ret = 0; goto again;}/* * Routine to copy from VERSAbus memory into mbufs. * * Warning: This makes the fairly safe assumption that * mbufs have even lengths. */struct mbuf *enpget(rxbuf, totlen, off, ifp) u_char *rxbuf; int totlen, off; struct ifnet *ifp;{ register u_char *cp; register struct mbuf *m; struct mbuf *top = 0, **mp = ⊤ int len; u_char *packet_end; rxbuf += sizeof (struct ether_header); cp = rxbuf; packet_end = cp + totlen; if (off) { off += 2 * sizeof(u_short); totlen -= 2 *sizeof(u_short); cp = rxbuf + off;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -