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

📄 if_ace.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_ace.c	7.8 (Berkeley) 12/16/90 *//* * ACC VERSAbus Ethernet controller */#include "ace.h"#if NACE > 0#include "sys/param.h"#include "sys/systm.h"#include "sys/malloc.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 "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 "../if/if_acereg.h"#include "../vba/vbavar.h"int	aceprobe(), aceattach(), acerint(), acecint(), acestart();struct	vba_device *aceinfo[NACE];long	acestd[] = { 0 };struct	vba_driver acedriver =    { aceprobe, 0, aceattach, 0, acestd, "ace", aceinfo, "v/eiu", 0 };int	aceinit(), aceoutput(), aceioctl(), acereset();struct	mbuf *aceget();/* * Ethernet software status per interface. * * Each interface is referenced by a network interface structure, * is_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... */struct	ace_softc {	struct	arpcom is_ac;		/* Ethernet common part	*/#define	is_if	is_ac.ac_if		/* network-visible interface */#define	is_addr	is_ac.ac_enaddr		/* hardware Ethernet address */	short	is_flags;#define	ACEF_OACTIVE	0x1		/* output is active */#define	ACEF_RCVPENDING	0x2		/* start rcv in acecint	*/	short	is_promiscuous;		/* true is enabled */	short	is_segboundry;		/* first TX Seg in dpm */	short	is_eictr;		/* Rx segment tracking ctr */	short	is_eoctr;		/* Tx segment tracking ctr */	short	is_txnext;		/* Next available Tx segment */	short	is_currnd;		/* current random backoff */	struct	ace_stats is_stats;	/* holds board statistics */	short	is_xcnt;		/* count xmitted segments to be acked 					   by the controller */	long	is_ivec;		/* autoconfig interrupt vector base */	struct	pte *is_map;		/* pte map for dual ported memory */	caddr_t	is_dpm;			/* address of mapped memory */} ace_softc[NACE];extern	struct ifnet loif;aceprobe(reg, vi)	caddr_t reg;	struct vba_device *vi;{	register br, cvec;		/* must be r12, r11 */	struct acedevice *ap = (struct acedevice *)reg;	struct ace_softc *is = &ace_softc[vi->ui_unit];#ifdef lint	br = 0; cvec = br; br = cvec;	acerint(0); acecint(0);#endif	if (badaddr(reg, 2))		return (0);	movow(&ap->csr, CSR_RESET);	DELAY(10000);#ifdef notdef	/*	 * Select two spaces for the interrupts aligned to an	 * eight vector boundary and fitting in 8 bits (as	 * required by the controller) -- YECH.  The controller	 * will be notified later at initialization time.	 */	if ((vi->ui_hd->vh_lastiv -= 2) > 0xff)		vi->ui_hd->vh_lastiv  = 0x200;	is->is_ivec = vi->ui_hd->vh_lastiv = vi->ui_hd->vh_lastiv &~ 0x7;#else	is->is_ivec = 0x90+vi->ui_unit*8;#endif	br = 0x14, cvec = is->is_ivec;		/* XXX */	return (sizeof (*ap));}/* * Interface exists: make available by filling in network interface * record.  System will initialize the interface when it is ready * to accept packets. */aceattach(ui)	struct vba_device *ui;{	register short unit = ui->ui_unit;	register struct ace_softc *is = &ace_softc[unit];	register struct ifnet *ifp = &is->is_if;	register struct acedevice *addr = (struct acedevice *)ui->ui_addr;	register short *wp, i;	ifp->if_unit = unit;	ifp->if_name = "ace";	ifp->if_mtu = ETHERMTU;	/*	 * Get station's addresses and set multicast hash table.	 */	for (wp = (short *)addr->station, i = 0; i < 6; i++)		is->is_addr[i] = ~*wp++;	printf("ace%d: hardware address %s\n", unit,	    ether_sprintf(is->is_addr));	is->is_promiscuous = 0;	for (wp = (short *)addr->hash, i =  0; i < 8; i++)		movow(wp++, ~0xf); 	movow(&addr->bcastena[0], ~0xffff); 	movow(&addr->bcastena[1], ~0xffff);	/*	 * Allocate and map dual ported VERSAbus memory.	 */	if (vbmemalloc(32, (caddr_t)ui->ui_flags,	    &is->is_map, &is->is_dpm) == 0) {		printf("ace%d: can't allocate VERSAbus memory map\n", unit);		return;	}	ifp->if_init = aceinit;	ifp->if_output = ether_output;	ifp->if_start = acestart;	ifp->if_ioctl = aceioctl;	ifp->if_reset = acereset;	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;	if_attach(ifp);}/* * Reset of interface after "system" reset. */acereset(unit, vban)	int unit, vban;{	register struct vba_device *ui;	if (unit >= NACE || (ui = aceinfo[unit]) == 0 || ui->ui_alive == 0 ||	    ui->ui_vbanum != vban)		return;	printf(" ace%d", unit);	aceinit(unit);}/* * Initialization of interface; clear recorded pending operations */aceinit(unit)	int unit;{	register struct ace_softc *is = &ace_softc[unit];	register struct vba_device *ui = aceinfo[unit];	register struct acedevice *addr;	register short Csr;	register int s;	if (is->is_if.if_addrlist == (struct ifaddr *)0)		return;	if ((is->is_if.if_flags & IFF_RUNNING) == 0) {		/*		 * Reset the controller, initialize the recieve buffers,		 * and turn the controller on again and set board online.		 */		addr = (struct acedevice *)ui->ui_addr;		s = splimp();		movow(&addr->csr, CSR_RESET);		DELAY(10000);		/*		 * Clean up dpm since the controller might		 * jumble dpm after reset.		 */		acesetup(unit);		movow(&addr->csr, CSR_GO);		Csr = addr->csr;		if (Csr & CSR_ACTIVE) {			movow(&addr->ivct, is->is_ivec);			Csr |= CSR_IENA | is->is_promiscuous;			movow(&addr->csr, Csr);			is->is_flags = 0;			is->is_xcnt = 0;			is->is_if.if_flags |= IFF_RUNNING;		}		splx(s);	}	if (is->is_if.if_snd.ifq_head)		acestart(&is->is_if);}/* * Start output on interface. * Get another datagram to send off of the interface queue, * and map it to the interface before starting the output. */acestart(ifp)	register struct ifnet *ifp;{	register struct tx_segment *txs;	register long len;	register int s;	struct mbuf *m;	short retries;#define	is ((struct ace_softc *)ifp)again:	txs = (struct tx_segment*)(is->is_dpm + (is->is_txnext << 11));	if (txs->tx_csr & TCS_TBFULL) {		is->is_stats.tx_busy++;		ifp->if_flags |= IFF_OACTIVE;		return (0);	}	s = splimp();	IF_DEQUEUE(&ifp->if_snd, m);	splx(s);	if (m == 0) {		ifp->if_flags &= ~IFF_OACTIVE;		return (0);	}	len = aceput(txs->tx_data, m);	retries = txs->tx_csr & TCS_RTC;	if (retries > 0)		acebakoff(is, txs, retries);	/*	 * 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);	if (++is->is_txnext > SEG_MAX) 		is->is_txnext = is->is_segboundry;	ifp->if_opackets++;	is->is_xcnt++;	len = (len & 0x7fff) | TCS_TBFULL;	movow(txs, len);	goto again;#undef is}/* * Transmit done interrupt. */acecint(unit)	int unit;{	register struct ace_softc *is = &ace_softc[unit];	register struct tx_segment *txseg;	short eostat;	if (is->is_xcnt <= 0)  {		log(LOG_ERR, "ace%d: stray xmit interrupt, xcnt %d\n",		    unit, is->is_xcnt);		is->is_xcnt = 0;		if (is->is_if.if_snd.ifq_head)			acestart(&is->is_if);		return;	}	is->is_xcnt--;	txseg = (struct tx_segment *)((is->is_eoctr << 11) + is->is_dpm);	eostat = txseg->tx_csr;	if ((eostat & TCS_TBFULL) == 0) {		is->is_stats.tx_retries += eostat & TCS_RTC;		if (eostat & TCS_RTFAIL)  {			is->is_stats.tx_discarded++;			is->is_if.if_oerrors++;		} else 			is->is_stats.tx_datagrams++;		if (++is->is_eoctr >= 16)			is->is_eoctr = is->is_segboundry; 	} 	if (is->is_if.if_snd.ifq_head)		acestart(&is->is_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. */acerint(unit)	int unit;{	register struct ace_softc *is = &ace_softc[unit];	register struct ifqueue *inq;	register struct ether_header *ace;	register struct rx_segment *rxseg;	int len, s, off, resid;	struct mbuf *m;	short eistat;	if ((is->is_if.if_flags&IFF_RUNNING) == 0)		return;again:	rxseg = (struct rx_segment *)((is->is_eictr << 11) + is->is_dpm);	eistat = rxseg->rx_csr;	if ((eistat & RCS_RBFULL) == 0)		return;	is->is_if.if_ipackets++;	if (++is->is_eictr >= is->is_segboundry) 		is->is_eictr = 0;	len = eistat & RCS_RBC;

⌨️ 快捷键说明

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