Ultrix-3.1/sys/dev/du.c

Compare this file to the similar file:
Show the results in this format:


/**********************************************************************
 *   Copyright (c) Digital Equipment Corporation 1984, 1985, 1986.    *
 *   All Rights Reserved. 					      *
 *   Reference "/usr/src/COPYRIGHT" for applicable restrictions.      *
 **********************************************************************/

/*
 * SCCSID: @(#)du.c	3.0	4/21/86
 */
/*
 * DU-11 Synchronous interface driver
 *
 * Modified for V7M-11, never tested !!!
 * Fred Canter 7/15/83
 * Modified for ULTRIX-11 mapped out buffers,
 * still never tested !!!
 * Dave Borman 9/10/84
 */

#include <sys/param.h>
#include <sys/systm.h>
#include <sys/dir.h>
#include <sys/user.h>
#include <sys/buf.h>
#include <sys/devmaj.h>
#include <sys/seg.h>

int	hz;		/* line frequency, see c.c */

/* device registers */
struct dureg {
	int	rxcsr, rxdbuf;
#define	parcsr	rxdbuf
	int	txcsr, txdbuf;
};

struct du {
	struct dureg	*du_addr;
	int		du_state;
	struct proc	*du_proc;
	struct buf	*du_buf;
	caddr_t		du_bufb;
	caddr_t		du_bufp;
	int		du_nxmit;
	int		du_timer;
} du[];					/* see also c.c */
int	ndu;		/* number of units, see c.c */
int	io_csr[];	/* CSR address, see c.c */


#define	DONE	0200
#define	IE	0100
#define	SIE	040
#define CTS	020000
#define	CARRIER	010000
#define	RCVACT	04000
#define	DSR	01000
#define STRIP	0400
#define SCH	020
#define RTS	04
#define	DTR	02
#define MR	0400
#define SEND	020
#define	HALF	010

#define	READ	0
#define	WRITE	1
#define PWRIT	2

#define	DUPRI	(PZERO+1)

duopen(dev)
register dev;
{
	int dutimeout();
	register struct du *dp;
	register struct dureg *lp;
	register int i;

	if(du[0].du_addr == NULL) {	/* init CSR address, one time only */
		for(i=0; i<ndu; i++) {
			lp = (struct dureg *)io_csr[DU_RMAJ];
			lp += i;
			du[i].du_addr = lp;
		}
	}
	dev = minor(dev);
	if (dev >= ndu ||
	   ((dp = &du[dev])->du_proc!=NULL && dp->du_proc!=u.u_procp)) {
		u.u_error = ENXIO;
		return;
	}
	dp->du_proc = u.u_procp;
	lp = dp->du_addr;
	if (dp->du_buf==NULL) {
		dp->du_buf = geteblk();
		dp->du_bufp = mapin(dp->du_buf);
		mapout(dp->du_buf);
		dp->du_state = WRITE;
		lp->txcsr = MR;
		lp->parcsr = 035026;		/* Sync Int, 7 bits, even parity, sync=026 */
		timeout(dutimeout, (caddr_t)dp, hz);
		duturn(dp);
	}
}

duclose(dev)
{
	register struct du *dp;
	register struct dureg *lp;

	dp = &du[minor(dev)];
	lp = dp->du_addr;
	lp->rxcsr = 0;
	lp->txcsr = 0;
	dp->du_timer = 0;
	dp->du_proc = 0;
	if (dp->du_buf != NULL) {
		brelse(dp->du_buf);
		dp->du_buf = NULL;
	}
}

duread(dev)
{
	register char *bp;
	register struct du *dp;
	register int pri;
	caddr_t	offset;

	dp = &du[minor(dev)];
	bp = dp->du_bufb;
	for(;;) {
		if(duwait(dev))
			return;
		if (dp->du_bufp > bp)
			break;
		pri = spl6();
		if (dp->du_timer <= 1) {
			splx(pri);
			return;
		}
		sleep((caddr_t)dp, DUPRI);
		splx(pri);
	}
	u.u_offset = 0;
	offset = mapin(dp->du_buf);
#ifdef	notdef
	iomove(dp->du_bufb, (int)min(u.u_count, (unsigned)(dp->du_bufp-bp)), B_READ);
#else	notdef
	{
		long paddr;
		paddr = (((long)(*KDSA5))<<6L) +
				(long)(((unsigned)offset)&077);
		pimove(paddr, (int)min(u.u_count, (unsigned)(dp->du_bufp-bp)), B_READ);
	}
#endif	notdef
	mapout(dp->du_buf);
}

duwrite(dev)
{
	register struct du *dp;
	register struct dureg *lp;
	register int pri;
	caddr_t	offset;

	dev = minor(dev);
	dp = &du[dev];
	if (u.u_count==0 || duwait(dev))
		return;
	dp->du_bufp = dp->du_bufb;
	dp->du_state = PWRIT;
	dp->du_addr->rxcsr &= ~SCH;
	dp->du_addr->rxcsr = SIE|RTS|DTR;
	if (u.u_count > BSIZE)
		u.u_count = BSIZE;
	dp->du_nxmit = u.u_count;
	u.u_offset = 0;
	offset = mapin(dp->du_buf);
#ifdef	notdef
	iomove(dp->du_bufb, (int)u.u_count, B_WRITE);
#else	notdef
	{
		long paddr;
		paddr = (((long)(*KDSA5))<<6L) +
				(long)(((unsigned)offset)&077);
		pimove(paddr, (int)u.u_count, B_WRITE);
	}
#endif	notdef
	mapout(dp->du_buf);
	lp = dp->du_addr;
	dp->du_timer = 10;
	pri = spl6();
	while((lp->rxcsr&CTS)==0)
		sleep((caddr_t)dp, DUPRI);
	if (dp->du_state != WRITE) {
		dp->du_state = WRITE;
		lp->txcsr = IE|SIE|SEND|HALF;
		dustart(dev);
	}
	splx(pri);
}

duwait(dev)
{
	register struct du *dp;
	register struct dureg *lp;
	register int pri;

	dp = &du[minor(dev)];
	lp = dp->du_addr;
	for(;;) {
		if ((lp->rxcsr&DSR)==0 || dp->du_buf==0) {
			u.u_error = EIO;
			return(1);
		}
		pri = spl6();
		if (dp->du_state==READ &&
			((lp->rxcsr&RCVACT)==0)) {
			splx(pri);
			return(0);
		}
		sleep((caddr_t)dp, DUPRI);
		splx(pri);
	}
}

dustart(dev)
{
	register struct du *dp;
	register struct dureg *lp;

	dp = &du[minor(dev)];
	lp = dp->du_addr;
	dp->du_timer = 10;
	if (dp->du_nxmit > 0) {
		dp->du_nxmit--;
		mapin(dp->du_buf);
		lp->txdbuf = *dp->du_bufp++;
		mapout(dp->du_buf);
	} else {
		duturn(dp);
	}
}

durint(dev)
{
	register struct du *dp;
	register c, s;
	int dustat;

	dp = &du[minor(dev)];
	dustat = dp->du_addr->rxcsr;
	if(dustat<0) {
		if((dustat&CARRIER)==0 && dp->du_state==READ)
			duturn(dp);
		else
			wakeup((caddr_t)dp);
	} else
	if(dustat&DONE) {
		dp->du_addr->rxcsr = IE|SIE|SCH|DTR;
		c = s = dp->du_addr->rxdbuf;
		c &= 0177;
		if(s<0)
			c |= 0200;
		if (dp->du_bufp < dp->du_bufb+BSIZE) {
			mapin(dp->du_buf);
			*dp->du_bufp++ = c;
			mapout(dp->du_buf);
		}
	}
}

duxint(dev)
{
	register struct du *dp;
	register struct dureg *lp;
	register int dustat;

	dp = &du[minor(dev)];
	lp = dp->du_addr;
	dustat = lp->txcsr;
	if(dustat<0)
		duturn(dp);
	else if(dustat&DONE)
		dustart(dev);
}

duturn(dp)
register struct du *dp;
{
	register struct dureg *lp;

	lp = dp->du_addr;
	if (dp->du_state!=READ) {
		dp->du_state = READ;
		dp->du_timer = 10;
		dp->du_bufp = dp->du_bufb;
	}
	lp->txcsr = HALF;
	lp->rxcsr &= ~SCH;
	lp->rxcsr = STRIP|IE|SIE|SCH|DTR;
	wakeup((caddr_t)dp);
}

dutimeout(dp)
register struct du *dp;
{
	if (dp->du_timer == 0)
		return;
	if (--dp->du_timer == 0) {
		duturn(dp);
		dp->du_timer = 1;
	}
	timeout(dutimeout, (caddr_t)dp, hz);
}