From hao!cires!david Mon Nov 25 19:33:46 1985
From: hao!cires!david
Date: Mon, 25 Nov 85 14:50:27 mst
To: hao!seismo!bostic

Also, I've attached a fast Tektronix driver that seems to work -- the only
change I made from the old USGS version was to add the UCB_DEVERR stuff.
It doesn't autoconfigure so l.s and c.c have to be modified appropriately.

Thanks again for your help,
	David

------------- cut here for fast_tek.c --------------
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/dir.h>
#include <sys/user.h>
#include <sys/tty.h>
#include <sys/proc.h>
#include <sys/buf.h>

/*
 *	fast_tty:
 *		Special device driver to utilize the USGS fast
 *		tektronix interface (DR11-B to Minibus). Essentially,
 *		the tektronix is connected by both a serial line
 *		and a parallel line. If the output requires no
 *		translation, then raw dma from the user's buffer is
 *		done via the dr11-b. Ordinary output and input are
 *		routed through the serial line and the serial line's
 *		device driver.The association table of which serial
 *		line goes with which parallel unit is given in conf.c
 */

#define NDR11	1	/* number of fast tty's */
#define DRPRI	(PZERO+20)
#define SYN	026	/* ascii "syn" char-- invisable to tek's */
/* drst control bits */
#define GO	1
#define WRITE	0400	/* actually unused */
#define IE	0100
/* internal state bits */
#define ACTIVE	1	/* output via dr11-b */
#define ODDB	2	/* single byte output via dr11-b */

struct	device
{
	int	drwc;
	caddr_t	drba;
	int	drst;
	int	drdb;
}	*fast_dr[NDR11] = { 0172410 };

/* last number (11) in following line is tty port mapping */
dev_t	fast_map[NDR11] = { (4<<8)+11 };

struct {
	int state;
	int bc;
}	fast[NDR11];
int wd;

struct buf	fast_buf;
extern fast_start();

fast_open(dev, flag)
dev_t	dev;
int	flag;
{

	int	d;

	d=minor(dev);
	if(d >= NDR11) {
		u.u_error = ENXIO;
		return;
	}

	(*cdevsw[major(fast_map[d])].d_open)(fast_map[d],flag);
	fast[d].state = 0;
	fast_buf.b_flags = B_DONE;
}

fast_close(dev,flag)
dev_t	dev;
int	flag;
{
	int	d;

	d = minor(dev);

	fast[d].state = 0;
	(*cdevsw[major(fast_map[d])].d_close)(fast_map[d],flag);
}


fast_read(dev)
dev_t	dev;
{
	register d;

	d = minor(dev);
	(*cdevsw[major(fast_map[d])].d_read)(fast_map[d]);
}

fast_write(dev, uio)
dev_t	dev;
struct uio *uio;
{
	register d;
	register struct device *addr;

	d = minor(dev);

	if(fast[d].state&ACTIVE)
	{
		addr = fast_dr[d];
		if(u.u_base&1)
		{	/* odd base address */
			wd = fuword(u.u_base)& ~0377 + SYN;
			fast[d].state |= ODDB;
			addr->drba = &wd;
			addr->drwc = -1;
			addr->drst = WRITE+GO+IE;
			while( fast[d].state&ODDB)
				sleep((caddr_t)&fast[d].state,DRPRI);
			u.u_base++; u.u_count--;
		}
		if(u.u_count)
		{
			fast[d].bc = u.u_count;
			if(u.u_count&1)
				u.u_count++;
			physio(fast_start, &fast_buf, dev, B_WRITE, uio);
		}
	}
	else
	{	/* do it via the serial line */
		(*cdevsw[major(fast_map[d])].d_write)(fast_map[d]);
	}
}

fast_ioctl(dev, cmd, addr, flag)
dev_t	dev;
int	cmd;
caddr_t	addr;
int	flag;
{

	switch(cmd)
	{

	case ('x'<<8)+0:
		fast[minor(dev)].state = ACTIVE;
		break;

	case ('x'<<8)+1:
		fast[minor(dev)].state = 0;
		break;

	default:
		(*cdevsw[major(fast_map[minor(dev)])].d_ioctl)
			(fast_map[minor(dev)], cmd, addr, flag);
	}
}
 
fast_start(bp)
register struct buf *bp;
{
	register struct device *addr;

	if(bp->b_flags&B_PHYS)
		mapalloc(bp);
	addr=fast_dr[minor(bp->b_dev)];
	addr->drba = bp->b_un.b_addr;
	addr->drwc = - (bp->b_bcount>>1);
	addr->drst =  ((bp->b_xmem&3)<<4)+IE+WRITE+GO;
}

fast_intr(dev)
dev_t	dev;
{
	register struct device *addr;
	register struct buf *bp = &fast_buf;

	addr = fast_dr[dev];

	if(addr->drst <0)
#ifdef	UCB_DEVERR
	{
		harderr(bp, "fast");
		printf("st=%o wc=%o\n", addr->drst, addr->drwc);
	}
#else
		deverror(bp, addr->drst, addr->drwc);
#endif	UCB_DEVERR
	if(fast[dev].state&ODDB)
	{
		fast[dev].state &= ~ODDB;
		wakeup(&fast[dev].state);
	}
	else
		iodone(bp);
	addr->drst=0;   /* resets dr11b status, ewh, cires 5-29-80 */
}
