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

📄 if_ne.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/*- * Copyright (c) 1990, 1991 William F. Jolitz. * Copyright (c) 1990, 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_ne.c	8.1 (Berkeley) 6/11/93 *//* * NE2000 Ethernet driver * * Parts inspired from Tim Tucker's if_wd driver for the wd8003, * insight on the ne2000 gained from Robert Clements PC/FTP driver. */#include "ne.h"#if NNE > 0#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/syslog.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#include <i386/isa/isa_device.h>#include <i386/isa/if_nereg.h>#include <i386/isa/icu.h>int	neprobe(), neattach(), neintr();int	nestart(),neinit(), ether_output(), neioctl();struct	isa_driver nedriver = {	neprobe, neattach, "ne",};struct	mbuf *neget();#define ETHER_MIN_LEN 64#define ETHER_MAX_LEN 1536/* * Ethernet software status per interface. * * Each interface is referenced by a network interface structure, * ns_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... */struct	ne_softc {	struct	arpcom ns_ac;		/* Ethernet common part */#define	ns_if	ns_ac.ac_if		/* network-visible interface */#define	ns_addr	ns_ac.ac_enaddr		/* hardware Ethernet address */	int	ns_flags;#define	DSF_LOCK	1		/* block re-entering enstart */	int	ns_oactive ;	int	ns_mask ;	int	ns_ba;			/* byte addr in buffer ram of inc pkt */	int	ns_cur;			/* current page being filled */	struct	prhdr	ns_ph;		/* hardware header of incoming packet*/	struct	ether_header ns_eh;	/* header of incoming packet */	u_char	ns_pb[2048 /*ETHERMTU+sizeof(long)*/];} ne_softc[NNE] ;#define	ENBUFSIZE	(sizeof(struct ether_header) + ETHERMTU + 2 + ETHER_MIN_LEN)int nec;u_short boarddata[16]; neprobe(dvp)	struct isa_device *dvp;{	int val,i,s;	register struct ne_softc *ns = &ne_softc[0];#ifdef lint	neintr(0);#endif	nec = dvp->id_iobase;	s = splimp();	/* Reset the bastard */	val = inb(nec+ne_reset);	DELAY(2000000);	outb(nec+ne_reset,val);	outb(nec+ds_cmd, DSCM_STOP|DSCM_NODMA);		i = 1000000;	while ((inb(nec+ds0_isr)&DSIS_RESET) == 0 && i-- > 0);	if (i < 0) return (0);	outb(nec+ds0_isr, 0xff);	/* Word Transfers, Burst Mode Select, Fifo at 8 bytes */	outb(nec+ds0_dcr, DSDC_WTS|DSDC_BMS|DSDC_FT1);	outb(nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP);	DELAY(10000);	/* Check cmd reg and fail if not right */	if ((i=inb(nec+ds_cmd)) != (DSCM_NODMA|DSCM_PG0|DSCM_STOP))		return(0);	outb(nec+ds0_tcr, 0);	outb(nec+ds0_rcr, DSRC_MON);	outb(nec+ds0_pstart, RBUF/DS_PGSIZE);	outb(nec+ds0_pstop, RBUFEND/DS_PGSIZE);	outb(nec+ds0_bnry, RBUFEND/DS_PGSIZE);	outb(nec+ds0_imr, 0);	outb(nec+ds0_isr, 0);	outb(nec+ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP);	outb(nec+ds1_curr, RBUF/DS_PGSIZE);	outb(nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP);#ifdef NEDEBUG#define	PAT(n)	(0xa55a + 37*(n))#define	RCON	37	{	int i, rom, pat;		rom=1;		printf("ne ram ");				for (i = 0; i < 0xfff0; i+=4) {			pat = PAT(i);			neput(&pat,i,4);			nefetch(&pat,i,4);			if (pat == PAT(i)) {				if (rom) {					rom=0;					printf(" %x", i);				}			} else {				if (!rom) {					rom=1;					printf("..%x ", i);				}			}			pat=0;			neput(&pat,i,4);		}		printf("\n");	}#endif	/* Extract board address */	nefetch ((caddr_t)boarddata, 0, sizeof(boarddata));	for(i=0; i < 6; i++)  ns->ns_addr[i] = boarddata[i];	splx(s);	return (1);}/* * Fetch from onboard ROM/RAM */nefetch (up, ad, len) caddr_t up; {	u_char cmd;	cmd = inb(nec+ds_cmd);	outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);	/* Setup remote dma */	outb (nec+ds0_isr, DSIS_RDC);	outb (nec+ds0_rbcr0, len);	outb (nec+ds0_rbcr1, len>>8);	outb (nec+ds0_rsar0, ad);	outb (nec+ds0_rsar1, ad>>8);	/* Execute & extract from card */	outb (nec+ds_cmd, DSCM_RREAD|DSCM_PG0|DSCM_START);	insw (nec+ne_data, up, len/2);	/* Wait till done, then shutdown feature */	while ((inb (nec+ds0_isr) & DSIS_RDC) == 0) ;	outb (nec+ds0_isr, DSIS_RDC);	outb (nec+ds_cmd, cmd);}/* * Put to onboard RAM */neput (up, ad, len) caddr_t up; {	u_char cmd;	cmd = inb(nec+ds_cmd);	outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);	/* Setup for remote dma */	outb (nec+ds0_isr, DSIS_RDC);	if(len&1) len++;		/* roundup to words */	outb (nec+ds0_rbcr0, len);	outb (nec+ds0_rbcr1, len>>8);	outb (nec+ds0_rsar0, ad);	outb (nec+ds0_rsar1, ad>>8);	/* Execute & stuff to card */	outb (nec+ds_cmd, DSCM_RWRITE|DSCM_PG0|DSCM_START);	outsw (nec+ne_data, up, len/2);		/* Wait till done, then shutdown feature */	while ((inb (nec+ds0_isr) & DSIS_RDC) == 0) ;	outb (nec+ds0_isr, DSIS_RDC);	outb (nec+ds_cmd, cmd);}/* * Reset of interface. */nereset(unit, uban)	int unit, uban;{	if (unit >= NNE)		return;	printf("ne%d: reset\n", unit);	ne_softc[unit].ns_flags &= ~DSF_LOCK;	neinit(unit);} /* * Interface exists: make available by filling in network interface * record.  System will initialize the interface when it is ready * to accept packets.  We get the ethernet address here. */neattach(dvp)	struct isa_device *dvp;{	int unit = dvp->id_unit;	register struct ne_softc *ns = &ne_softc[unit];	register struct ifnet *ifp = &ns->ns_if;	ifp->if_unit = unit;	ifp->if_name = nedriver.name ;	ifp->if_mtu = ETHERMTU;	printf (" ethernet address %s", ether_sprintf(ns->ns_addr)) ;	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS;	ifp->if_init = neinit;	ifp->if_output = ether_output;	ifp->if_start = nestart;	ifp->if_ioctl = neioctl;	ifp->if_reset = nereset;	ifp->if_watchdog = 0;	if_attach(ifp);}/* * Initialization of interface; set up initialization block * and transmit/receive descriptor rings. */neinit(unit)	int unit;{	register struct ne_softc *ns = &ne_softc[unit];	struct ifnet *ifp = &ns->ns_if;	int s;	register i; char *cp; 	if (ifp->if_addrlist == (struct ifaddr *)0) return;	if (ifp->if_flags & IFF_RUNNING) return;	s = splimp();	/* set physical address on ethernet */	outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP);	for (i=0 ; i < 6 ; i++) outb(nec+ds1_par0+i,ns->ns_addr[i]);	/* clr logical address hash filter for now */	for (i=0 ; i < 8 ; i++) outb(nec+ds1_mar0+i,0xff);	/* init regs */	outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_STOP);	outb (nec+ds0_rbcr0, 0);	outb (nec+ds0_rbcr1, 0);	outb (nec+ds0_imr, 0);	outb (nec+ds0_isr, 0xff);	/* Word Transfers, Burst Mode Select, Fifo at 8 bytes */	outb(nec+ds0_dcr, DSDC_WTS|DSDC_BMS|DSDC_FT1);	outb(nec+ds0_tcr, 0);	outb (nec+ds0_rcr, DSRC_MON);	outb (nec+ds0_tpsr, 0);	outb(nec+ds0_pstart, RBUF/DS_PGSIZE);	outb(nec+ds0_pstop, RBUFEND/DS_PGSIZE);	outb(nec+ds0_bnry, RBUF/DS_PGSIZE);	outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG1|DSCM_STOP);	outb(nec+ds1_curr, RBUF/DS_PGSIZE);	ns->ns_cur = RBUF/DS_PGSIZE;	outb (nec+ds_cmd, DSCM_NODMA|DSCM_PG0|DSCM_START);	outb (nec+ds0_rcr, DSRC_AB);	outb(nec+ds0_dcr, DSDC_WTS|DSDC_BMS|DSDC_FT1);	outb (nec+ds0_imr, 0xff);	ns->ns_if.if_flags |= IFF_RUNNING;	ns->ns_oactive = 0; ns->ns_mask = ~0;	nestart(ifp);	splx(s);}/* * Setup output on interface. * Get another datagram to send off of the interface queue, * and map it to the interface before starting the output. * called only at splimp or interrupt level. */nestart(ifp)	struct ifnet *ifp;{	register struct ne_softc *ns = &ne_softc[ifp->if_unit];	struct mbuf *m0, *m;	int buffer;	int len = 0, i, total,t;	/*	 * The DS8390 has only one transmit buffer, if it is busy we	 * must wait until the transmit interrupt completes.	 */	outb(nec+ds_cmd,DSCM_NODMA|DSCM_START);	if (ns->ns_flags & DSF_LOCK)		return;	if (inb(nec+ds_cmd) & DSCM_TRANS)		return;	if ((ns->ns_if.if_flags & IFF_RUNNING) == 0)		return;	IF_DEQUEUE(&ns->ns_if.if_snd, m); 	if (m == 0)		return;	/*	 * Copy the mbuf chain into the transmit buffer	 */	ns->ns_flags |= DSF_LOCK;	/* prevent entering nestart */	buffer = TBUF; len = i = 0;	t = 0;	for (m0 = m; m != 0; m = m->m_next)		t += m->m_len;			m = m0;	total = t;	for (m0 = m; m != 0; ) {				if (m->m_len&1 && t > m->m_len) {			neput(mtod(m, caddr_t), buffer, m->m_len - 1);			t -= m->m_len - 1;			buffer += m->m_len - 1;			m->m_data += m->m_len - 1;			m->m_len = 1;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -