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

📄 if_dpv.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
字号:
#ifndef lintstatic char *sccsid = "@(#)if_dpv.c	4.1	ULTRIX	7/2/90";#endif lint/************************************************************************ *									* *			Copyright (c) 1985 by				* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************/#include "dpv.h"#if NDPV > 0 || defined(BINARY)/* *   Driver for the DPV-11, a synchronous character-oriented data  *	communications device, supported here for the bisync protocol. * *   Written  by	U. Sinkewicz		4/10/85 *//************************************************************************* *			Modification History * *   August 18, 1986	U. Sinkewicz *			Reset routine did not initialize every dpv device *			on the bus.  Changed NDPV to nNDPV in dpvreset *			routine. *************************************************************************/#include "../data/if_dpv_data.c"int dpvdebug = 1;extern struct protosw *iftype_to_proto(), *iffamily_to_proto();/* extern struct timeval time; *//*  * Driver information for autoconfigure. */int	dpvprobe(), dpvattach(), dpvrint(), dpvxint(), dpvinit();struct dpvdevice *dpvaddr;struct	uba_device   *dpvinfo[NDPV];u_short	dpvstd[] = { 0 };struct uba_driver	dpvdriver =	 { dpvprobe, 0, dpvattach, 0, dpvstd, "dpv", dpvinfo };#define DPVUNIT(x)	minor(x)int dpvoutput(), dpvinput(), dpvreset(), dpvioctl();/* * Probe routine.  Generate an interrupt, wait around for the cpu to * service it, and reset the device registers. */dpvprobe(reg)caddr_t reg;{	register struct dpvdevice *dpvaddr = (struct dpvdevice *)reg;#ifdef lint	dpvrint(0); dpvxint(0);#endif	dpvaddr->pcscr = RESET;	dpvaddr->pcscr = TXITEN | TRAEN;	DELAY(100000);	dpvaddr->pcscr = 0;	if (cvec && cvec != 0x200){		cvec -= 4;	}	return(1);	/* return (sizeof (struct dpvdevice)); */}/* * Fill in the network interface record.  The system will initialize the * interface when it is ready to accept packets. */dpvattach(ui)struct uba_device *ui;{	register struct dpv_softc *ds = &dpv_softc[ui->ui_unit];ds->dpv_if.if_unit = ui->ui_unit;ds->dpv_if.if_name = "dpv";ds->dpv_if.if_init = dpvinit;ds->dpv_if.if_output = dpvoutput;ds->dpv_if.if_ioctl = dpvioctl;ds->dpv_if.if_reset = dpvreset;if_attach(&ds->dpv_if);}/* * Reset state of driver if a unibus reset occurrs.   */dpvreset(unit, uban)int unit, uban;{	register struct uba_device *ui;	register struct dpvdevice *addr;	if (unit >= nNDPV || (ui = dpvinfo[unit])== 0 || ui->ui_alive == 0 ||		ui->ui_ubanum != uban)		return;	addr->pcscr = RESET;	addr->pcsar = 0;	addr->rxcsr = 0;	printf("dpv%d\n",unit);	dpvinit(unit);}/* * Initialize the device and unibus usage. */dpvinit(unit)int unit;{	register struct dpv_softc *ds = &dpv_softc[unit];	struct uba_device *ui = dpvinfo[unit];	register struct dpvdevice *addr = (struct dpvdevice *)ui->ui_addr;	int s, i;	/* Dpvinit is called at boot time and at unibus reset. */	if (ds->dpv_if.if_addrlist == (struct ifaddr *)0){		return; 	}	/*	 * Allow receive interrupt when CTS comes up and set up for	 * dialing.	 */	addr->pcsar = PROTO;	addr->pcscr = 0;	addr->rxcsr = RXITEN | DTR;	/* 	 * Initialize the counter in the software context structure and	 * clear the buffer.	 */	ds->counter = 0;	for (i=0; i<DPVSIZE; i++)		ds->buf[i] = NULL;	ds->state = DPVINIT;	ds->crc = (unsigned short)0;}dpvoutput(ifp, m0, dst)	register struct ifnet *ifp;	struct mbuf *m0;	struct sockaddr *dst;{	struct mbuf *m;	register struct dpv_softc *ds = &dpv_softc[ifp->if_unit];	struct protosw *pr;	int s, i, error;	m = m0;	/* 	 * Initialize the counter in the software context structure and	 * clear the buffer.	 */	ds->counter = 0;	for (i=0; i<DPVSIZE; i++)		ds->buf[i] = NULL;	ds->state = DPVREADY;	/*	 * Queue the mbuf message onto the interface.	 */	s = splimp();	if (IF_QFULL (&ifp->if_snd)){		IF_DROP(&ifp->if_snd);		splx(s);		m_freem(m);		return(ENOBUFS);	}	/*	 * Put the entire packet onto the send queue 	 */	IF_ENQUEUE(&ifp->if_snd,m);	splx(s);	ds->state = DPVREADY;	dpvstart(ifp->if_unit);	return(0);}/* * DPV start routine.  Should be called at priority 5. */dpvstart(dev)dev_t dev;{	int unit = DPVUNIT(dev);	struct uba_device *ui = dpvinfo[unit];	register struct dpv_softc *ds = &dpv_softc[unit];	register struct dpvdevice *addr = (struct dpvdevice *)ui->ui_addr;	struct mbuf *m, *mp;	unsigned char c;	int i; 		/* counter */	int j = 0;  	/* counter */	int s;	struct bsc_data *bdata;	int len;	s = splimp();	IF_DEQUEUE(&ds->dpv_if.if_snd, m);		if ( m == 0){			ds->state = DPVDONE;			splx(s);			m_freem(m);			ds->counter = 0;			ds->len = 0;			return(0);		}		bdata = mtod(m, struct bsc_data *);	/* 	 * Copy from the mbuf to storage.	 */	ds->len = 0;  /* len is how much mbuf data is in ds */	ds->counter = 0; /* counter is index in buf when taking data from ds */	len = (unsigned)m->m_len;loop:	for ( i=0; i<len; i++)		ds->buf[j++] = bdata->data[i];	if ( m->m_next != NULL ){		mp = m->m_next;		len = (unsigned)mp->m_len;		bdata = mtod(mp, struct bsc_data *);		m = mp;		goto loop;	}	ds->len = j;	splx(s);	ds->state = DPVPRETNS;	/* 	 * Reset the device here because if it's a retranxmit you	 * need to disable receive interrupts from the device.	 */  	addr->pcsar = PROTO | NOCRC | SYNC;	addr->rxcsr = DSITEN | RXITEN | RTS | DTR;	if (addr->rxcsr & CTS){		addr->pcscr = TXITEN | TRAEN;		addr->tdsr = TSOM | (0377 & SYNC);	}} /* * Transmit interrupt routine.  Take characters from the buffer provided * by the start routine and put them in the device's transmit buffer. */dpvxint(unit)int unit;{	struct uba_device *ui = dpvinfo[unit];	register struct dpvdevice *addr = (struct dpvdevice *)ui->ui_addr;	register struct dpv_softc *ds = &dpv_softc[unit];	unsigned char	c;	int i;	if ( ds->state == DPVPRETNS){		ds->state = DPVWRITE;		ds->counter = 0;		addr->tdsr = TSOM | (0377 & SYNC);		return(0);	}	/* This should never happen. */	if ( ds->state == DPVINIT){		addr->tdsr = TSOM | (0377 & PAD);		return(0);	}	/* Now get ready to receive data. */	if ( ds->state == DPVDONE){		for (i=0; i<DPVSIZE; i++)			ds->buf[i] = NULL;		ds->counter = 0;		ds->len = 0;			ds->state = DPVREADY;		addr->pcsar = PROTO | NOCRC | SYNC;		addr->pcscr = 0;		addr->tdsr = TEOM;		addr->rxcsr = DSITEN | RXITEN | RCVEN | DTR;		return(0);	}				if( ds->state == DPVWRITE){		i = ds->counter;		c = ds->buf[i];		ds->counter++;		if ( ds->counter == ds->len )			ds->state = DPVDONE;		addr->tdsr = (0377 & c);		return(0);	}}dpvread(unit)int unit;{	struct uba_device *ui = dpvinfo[unit];	register struct dpv_softc *ds = &dpv_softc[ui->ui_unit];	register struct dpvdevice *addr = (struct dpvdevice *)ui->ui_addr;	struct ifqueue *inq;	register struct mbuf *m, *m_head;	int i, j, temp, len;	struct bsc_data *bm;	int s;	/*	 * If done with a text receive, reset the crc flags.	 * Copy the ds->buf[] data into an mbuf, schedule an interrupt,	 * and queue the new mbuf onto the receive queue.	 */	MGET(m_head, M_DONTWAIT, MT_DATA);	if ( m_head == NULL){		panic(" no mbufs available\n");		}	m = m_head;	/* Now copy from array ds->buf into the mbuf */	m->m_len = MLEN;	m->m_off = MMAXOFF - m->m_len;	bm = mtod(m, struct bsc_data *);	j = 0;	temp = ds->counter;loop1:	len = m->m_len;	if ( temp <= len){		for ( i=0; i < temp; i++)			bm->data[i] = ds->buf[j++];		m->m_len = temp;		m->m_next = 0;	}else{		for ( i=0; i < len; i++)			bm->data[i] = ds->buf[j++];		temp = temp - len;		MGET(m->m_next, M_DONTWAIT, MT_DATA);			if ( m->m_next == NULL){				panic("dpvread - no mbufs available\n");			}		m = m->m_next;		m->m_len = MLEN;		m->m_off = MMAXOFF - m->m_len;		bm = mtod(m, struct bsc_data *);		goto loop1;	}	schednetisr(NETISR_BSC);	s = splimp();	inq = &bscintrq;	if (IF_QFULL (inq)){		cprintf(" QFULL\n");		IF_DROP(inq);			m_freem(m_head);		return;	}	IF_ENQUEUE(inq,m_head);	splx(s);	/* 	 * Clear the old buffer	 */	for (i=0; i<DPVSIZE; i++)		ds->buf[i] = NULL;	ds->counter = 0;	ds->len = 0;	ds->state = DPVREADY;	ds->crc = (unsigned short)0;	addr->pcsar = PROTO | NOCRC | SYNC;	addr->rxcsr = DSITEN | RXITEN | DTR;	addr->pcscr = 0;}dpvrint(unit)int unit;{	unsigned short	tmp;	unsigned char c;	struct uba_device *ui = dpvinfo[unit];	register struct dpvdevice *addr = (struct dpvdevice *)ui->ui_addr;	register struct dpv_softc *ds = &dpv_softc[ui->ui_unit];	struct ifqueue *inq;	int i;	tmp = addr->rdsr;	c = tmp;	if  (ds->state == DPVPRETNS) {		if (addr->rxcsr & CTS){			addr->pcsar = PROTO | NOCRC | SYNC;			addr->rxcsr = RTS | DTR;			addr->pcscr = TXITEN | TRAEN;			addr->tdsr = TSOM | (0377 & SYNC);			return(0);		}else			return(0);	}	if (ds->state == DPVREADY) {		if (addr->rxcsr & CTS) {			addr->pcsar = PROTO | NOCRC | SYNC;			addr->rxcsr = RTS | DTR;			addr->pcscr = TXITEN | TRAEN;			addr->tdsr = TSOM | (0377 & SYNC);			return(0);		}		if (addr->rxcsr & CARRIER) {			ds->state = DPVREAD;			ds->counter = 0;			addr->pcsar = PROTO | NOCRC | SYNC; 			addr->pcscr = 0;			addr->rxcsr = RXITEN | RCVEN | DTR;			return(0);		}else			return(0);		}	/* 	 * Store the character locally.  Then	 * see if the character is a control character.  If so, write the	 * buffer out.	 */	switch (c){	case PAD:		i = ds->counter;		if ( ds->buf[i-1] == DLE ){			ds->buf[i] = c;			ds->counter++;			break;		}		if (( ds->buf[i-1] == ETB ) || (ds->buf[i-2] == ETB)){			ds->buf[i] = c;			ds->counter++;			break;		}		if (( ds->buf[i-1] == ETX ) || (ds->buf[i-2] == ETX)){			ds->buf[i] = c;			ds->counter++;			break;		}		if (( ds->buf[i-1] == IUS ) || (ds->buf[i-2] == IUS)){			ds->buf[i] = c;			ds->counter++;			break;		}		ds->state = DPVDONE;		addr->pcsar = PROTO | NOCRC | SYNC;		addr->pcscr = 0;		addr->rxcsr = DTR;		break;	default:		i = ds->counter;		ds->buf[i] = c;		ds->counter++;	}	if (ds->state == DPVDONE)		dpvread(unit);	return(0);}/* * Process an ioctl request.  Routine changed 9/18 to coincide with * tcp/ip subnetrouting changes. */dpvioctl(ifp, cmd, data)	register struct ifnet *ifp;	int cmd;	caddr_t data;{	int s = splimp(), error = 0;		switch (cmd) {		case SIOCSIFADDR:		dpvinit(ifp->if_unit);		ifp->if_flags |= IFF_UP;		break;	default:		error = EINVAL;	}	splx(s);	return(error);}#endif

⌨️ 快捷键说明

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