⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 if_enp.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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 = &top;	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 + -