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

📄 if_qe.c

📁 open bsd vax module -if function
💻 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 * Digital Equipment Corp. * * 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_qe.c	7.21 (Berkeley) 5/4/92 *//* from  @(#)if_qe.c	1.15	(ULTRIX)	4/16/86 *//**************************************************************** *								* *        Licensed from Digital Equipment Corporation 		* *                       Copyright (c) 				* *               Digital Equipment Corporation			* *                   Maynard, Massachusetts 			* *                         1985, 1986 				* *                    All rights reserved. 			* *								* *        The Information in this software is subject to change * *   without notice and should not be construed as a commitment * *   by  Digital  Equipment  Corporation.   Digital   makes  no * *   representations about the suitability of this software for * *   any purpose.  It is supplied "As Is" without expressed  or * *   implied  warranty. 					* *								* *        If the Regents of the University of California or its * *   licensees modify the software in a manner creating  	* *   derivative copyright rights, appropriate copyright  	* *   legends may be placed on the derivative work in addition   * *   to that set forth above. 					* *								* ****************************************************************//* --------------------------------------------------------------------- * Modification History * * 15-Apr-86  -- afd *	Rename "unused_multi" to "qunused_multi" for extending Generic *	kernel to MicroVAXen. * * 18-mar-86  -- jaw     br/cvec changed to NOT use registers. * * 12 March 86 -- Jeff Chase *	Modified to handle the new MCLGET macro *	Changed if_qe_data.c to use more receive buffers *	Added a flag to poke with adb to log qe_restarts on console * * 19 Oct 85 -- rjl *	Changed the watch dog timer from 30 seconds to 3.  VMS is using * 	less than 1 second in their's. Also turned the printf into an *	mprintf. * *  09/16/85 -- Larry Cohen * 		Add 43bsd alpha tape changes for subnet routing * *  1 Aug 85 -- rjl *	Panic on a non-existent memory interrupt and the case where a packet *	was chained.  The first should never happen because non-existant *	memory interrupts cause a bus reset. The second should never happen *	because we hang 2k input buffers on the device. * *  1 Aug 85 -- rich *      Fixed the broadcast loopback code to handle Clusters without *      wedging the system. * *  27 Feb. 85 -- ejf *	Return default hardware address on ioctl request. * *  12 Feb. 85 -- ejf *	Added internal extended loopback capability. * *  27 Dec. 84 -- rjl *	Fixed bug that caused every other transmit descriptor to be used *	instead of every descriptor. * *  21 Dec. 84 -- rjl *	Added watchdog timer to mask hardware bug that causes device lockup. * *  18 Dec. 84 -- rjl *	Reworked driver to use q-bus mapping routines.  MicroVAX-I now does *	copying instead of m-buf shuffleing. *	A number of deficencies in the hardware/firmware were compensated *	for. See comments in qestart and qerint. * *  14 Nov. 84 -- jf *	Added usage counts for multicast addresses. *	Updated general protocol support to allow access to the Ethernet *	header. * *  04 Oct. 84 -- jf *	Added support for new ioctls to add and delete multicast addresses *	and set the physical address. *	Add support for general protocols. * *  14 Aug. 84 -- rjl *	Integrated Shannon changes. (allow arp above 1024 and ? ) * *  13 Feb. 84 -- rjl * *	Initial version of driver. derived from IL driver. * * --------------------------------------------------------------------- */#include "qe.h"#if	NQE > 0/* * Digital Q-BUS to NI Adapter */#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/syslog.h"#include "sys/time.h"#include "sys/kernel.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#ifdef ISO#include "netiso/iso.h"#include "netiso/iso_var.h"extern char all_es_snpa[], all_is_snpa[], all_l1is_snpa[], all_l2is_snpa[];#endif#include "../include/pte.h"#include "../include/cpu.h"#include "../include/mtpr.h"#include "if_qereg.h"#include "if_uba.h"#include "../uba/ubareg.h"#include "../uba/ubavar.h"#if NQE == 1 && !defined(QNIVERT)#define NRCV	15	 		/* Receive descriptors		*/#else#define NRCV	10	 		/* Receive descriptors		*/#endif#define NXMT	5	 		/* Transmit descriptors		*/#define NTOT	(NXMT + NRCV)#define	QETIMEOUT	2		/* transmit timeout, must be > 1 */#define QESLOWTIMEOUT	40		/* timeout when no xmits in progress */#define MINDATA 60/* * Ethernet software status per interface. * * Each interface is referenced by a network interface structure, * qe_if, which the routing code uses to locate the interface. * This structure contains the output queue for the interface, its address, ... */struct	qe_softc {	struct	arpcom qe_ac;		/* Ethernet common part 	*/#define	qe_if	qe_ac.ac_if		/* network-visible interface 	*/#define	qe_addr	qe_ac.ac_enaddr		/* hardware Ethernet address 	*/	struct	ifubinfo qe_uba;	/* Q-bus resources 		*/	struct	ifrw qe_ifr[NRCV];	/*	for receive buffers;	*/	struct	ifxmt qe_ifw[NXMT];	/*	for xmit buffers;	*/	int	qe_flags;		/* software state		*/#define	QEF_RUNNING	0x01#define	QEF_SETADDR	0x02#define QEF_FASTTIMEO	0x04	int	setupaddr;		/* mapping info for setup pkts  */	int	ipl;			/* interrupt priority		*/	struct	qe_ring *rringaddr;	/* mapping info for rings	*/	struct	qe_ring *tringaddr;	/*       ""			*/	struct	qe_ring rring[NRCV+1];	/* Receive ring descriptors 	*/	struct	qe_ring tring[NXMT+1];	/* Transmit ring descriptors 	*/	u_char	setup_pkt[16][8];	/* Setup packet			*/	int	rindex;			/* Receive index		*/	int	tindex;			/* Transmit index		*/	int	otindex;		/* Old transmit index		*/	int	qe_intvec;		/* Interrupt vector 		*/	struct	qedevice *addr;		/* device addr			*/	int 	setupqueued;		/* setup packet queued		*/	int	nxmit;			/* Transmits in progress	*/	int	qe_restarts;		/* timeouts			*/} qe_softc[NQE];struct	uba_device *qeinfo[NQE];extern struct timeval time;int	qeprobe(), qeattach(), qeintr(), qetimeout();int	qeinit(), qeioctl(), qereset(), qestart();u_short qestd[] = { 0 };struct	uba_driver qedriver =	{ qeprobe, 0, qeattach, 0, qestd, "qe", qeinfo };#define	QEUNIT(x)	minor(x)/* * The deqna shouldn't receive more than ETHERMTU + sizeof(struct ether_header) * but will actually take in up to 2048 bytes. To guard against the receiver * chaining buffers (which we aren't prepared to handle) we allocate 2kb * size buffers. */#define MAXPACKETSIZE 2048		/* Should really be ETHERMTU	*//* * Probe the QNA to see if it's there */qeprobe(reg, ui)	caddr_t reg;	struct uba_device *ui;{	register int br, cvec;		/* r11, r10 value-result */	register struct qedevice *addr = (struct qedevice *)reg;	register struct qe_ring *rp;	register struct qe_ring *prp; 	/* physical rp 		*/	register int i;	register struct qe_softc *sc = &qe_softc[ui->ui_unit];#ifdef lint	br = 0; cvec = br; br = cvec;	qeintr(0);#endif	/*	 * The QNA interrupts on i/o operations. To do an I/O operation	 * we have to setup the interface by transmitting a setup  packet.	 */	addr->qe_csr = QE_RESET;	addr->qe_csr &= ~QE_RESET;	addr->qe_vector = (uba_hd[numuba].uh_lastiv -= 4);	/*	 * Map the communications area and the setup packet.	 */	sc->setupaddr =		uballoc(0, (caddr_t)sc->setup_pkt, sizeof(sc->setup_pkt), 0);	sc->rringaddr = (struct qe_ring *) uballoc(0, (caddr_t)sc->rring,		sizeof(struct qe_ring) * (NTOT+2), 0);	prp = (struct qe_ring *)UBAI_ADDR((int)sc->rringaddr);	/*	 * The QNA will loop the setup packet back to the receive ring	 * for verification, therefore we initialize the first	 * receive & transmit ring descriptors and link the setup packet	 * to them.	 */	qeinitdesc(sc->tring, (caddr_t)UBAI_ADDR(sc->setupaddr),	    sizeof(sc->setup_pkt));	qeinitdesc(sc->rring, (caddr_t)UBAI_ADDR(sc->setupaddr),	    sizeof(sc->setup_pkt));	rp = (struct qe_ring *)sc->tring;	rp->qe_setup = 1;	rp->qe_eomsg = 1;	rp->qe_flag = rp->qe_status1 = QE_NOTYET;	rp->qe_valid = 1;	rp = (struct qe_ring *)sc->rring;	rp->qe_flag = rp->qe_status1 = QE_NOTYET;	rp->qe_valid = 1;	/*	 * Get the addr off of the interface and place it into the setup	 * packet. This code looks strange due to the fact that the address	 * is placed in the setup packet in col. major order.	 */	for( i = 0 ; i < 6 ; i++ )		sc->setup_pkt[i][1] = addr->qe_sta_addr[i];	qesetup( sc );	/*	 * Start the interface and wait for the packet.	 */	(void) spl6();	addr->qe_csr = QE_INT_ENABLE | QE_XMIT_INT | QE_RCV_INT;	addr->qe_rcvlist_lo = (short)prp;	addr->qe_rcvlist_hi = (short)((int)prp >> 16);	prp += NRCV+1;	addr->qe_xmtlist_lo = (short)prp;	addr->qe_xmtlist_hi = (short)((int)prp >> 16);	DELAY(10000);	/*	 * All done with the bus resources.	 */	ubarelse(0, &sc->setupaddr);	ubarelse(0, (int *)&sc->rringaddr);	sc->ipl = br = qbgetpri();	return( sizeof(struct qedevice) );}/* * Interface exists: make available by filling in network interface * record.  System will initialize the interface when it is ready * to accept packets. */qeattach(ui)	struct uba_device *ui;{	register struct qe_softc *sc = &qe_softc[ui->ui_unit];	register struct ifnet *ifp = &sc->qe_if;	register struct qedevice *addr = (struct qedevice *)ui->ui_addr;	register int i;	ifp->if_unit = ui->ui_unit;	ifp->if_name = "qe";	ifp->if_mtu = ETHERMTU;	/*	 * The Deqna is cable of transmitting broadcasts, but	 * doesn't listen to its own.	 */	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;	/*	 * Read the address from the prom and save it.	 */	for( i=0 ; i<6 ; i++ )		sc->setup_pkt[i][1] = sc->qe_addr[i] = addr->qe_sta_addr[i] & 0xff;	addr->qe_vector |= 1;	printf("qe%d: %s, hardware address %s\n", ui->ui_unit,		addr->qe_vector&01 ? "delqa":"deqna",		ether_sprintf(sc->qe_addr));	addr->qe_vector &= ~1;	/*	 * Save the vector for initialization at reset time.	 */	sc->qe_intvec = addr->qe_vector;	ifp->if_init = qeinit;	ifp->if_output = ether_output;	ifp->if_start = qestart;	ifp->if_ioctl = qeioctl;	ifp->if_reset = qereset;	ifp->if_watchdog = qetimeout;	sc->qe_uba.iff_flags = UBA_CANTWAIT;	if_attach(ifp);}/* * Reset of interface after UNIBUS reset. * If interface is on specified uba, reset its state. */qereset(unit, uban)	int unit, uban;{	register struct uba_device *ui;	if (unit >= NQE || (ui = qeinfo[unit]) == 0 || ui->ui_alive == 0 ||		ui->ui_ubanum != uban)		return;	printf(" qe%d", unit);	qe_softc[unit].qe_if.if_flags &= ~IFF_RUNNING;	qeinit(unit);}/* * Initialization of interface. */qeinit(unit)	int unit;{	register struct qe_softc *sc = &qe_softc[unit];	register struct uba_device *ui = qeinfo[unit];	register struct qedevice *addr = (struct qedevice *)ui->ui_addr;	register struct ifnet *ifp = &sc->qe_if;	register i;	int s;	/* address not known */	if (ifp->if_addrlist == (struct ifaddr *)0)			return;	if (sc->qe_flags & QEF_RUNNING)		return;	if ((ifp->if_flags & IFF_RUNNING) == 0) {		/*		 * map the communications area onto the device		 */		i = uballoc(0, (caddr_t)sc->rring,		    sizeof(struct qe_ring) * (NTOT+2), 0);		if (i == 0)			goto fail;		sc->rringaddr = (struct qe_ring *)UBAI_ADDR(i);		sc->tringaddr = sc->rringaddr + NRCV + 1;		i = uballoc(0, (caddr_t)sc->setup_pkt,		    sizeof(sc->setup_pkt), 0);		if (i == 0)			goto fail;		sc->setupaddr =	UBAI_ADDR(i);		/*		 * init buffers and maps		 */		if (if_ubaminit(&sc->qe_uba, ui->ui_ubanum,		    sizeof (struct ether_header), (int)btoc(MAXPACKETSIZE),		    sc->qe_ifr, NRCV, sc->qe_ifw, NXMT) == 0) {	fail:			printf("qe%d: can't allocate uba resources\n", unit);			sc->qe_if.if_flags &= ~IFF_UP;			return;		}	}	/*	 * Init the buffer descriptors and indexes for each of the lists and	 * loop them back to form a ring.	 */	for (i = 0; i < NRCV; i++) {		qeinitdesc( &sc->rring[i],		    (caddr_t)UBAI_ADDR(sc->qe_ifr[i].ifrw_info), MAXPACKETSIZE);		sc->rring[i].qe_flag = sc->rring[i].qe_status1 = QE_NOTYET;		sc->rring[i].qe_valid = 1;	}	qeinitdesc(&sc->rring[i], (caddr_t)NULL, 0);	sc->rring[i].qe_addr_lo = (short)sc->rringaddr;	sc->rring[i].qe_addr_hi = (short)((int)sc->rringaddr >> 16);	sc->rring[i].qe_chain = 1;	sc->rring[i].qe_flag = sc->rring[i].qe_status1 = QE_NOTYET;	sc->rring[i].qe_valid = 1;	for( i = 0 ; i <= NXMT ; i++ )		qeinitdesc(&sc->tring[i], (caddr_t)NULL, 0);	i--;	sc->tring[i].qe_addr_lo = (short)sc->tringaddr;	sc->tring[i].qe_addr_hi = (short)((int)sc->tringaddr >> 16);	sc->tring[i].qe_chain = 1;	sc->tring[i].qe_flag = sc->tring[i].qe_status1 = QE_NOTYET;	sc->tring[i].qe_valid = 1;	sc->nxmit = sc->otindex = sc->tindex = sc->rindex = 0;	/*	 * Take the interface out of reset, program the vector,	 * enable interrupts, and tell the world we are up.	 */	s = splimp();	addr->qe_vector = sc->qe_intvec;	sc->addr = addr;	addr->qe_csr = QE_RCV_ENABLE | QE_INT_ENABLE | QE_XMIT_INT |	    QE_RCV_INT | QE_ILOOP;

⌨️ 快捷键说明

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