V8/usr/sys/dev/tri.c

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

/*
 * trilog driver
 */

#include "tri.h"
#if NTRI>0
#include "../h/param.h"
#include "../h/dir.h"
#include "../h/user.h"
#include "../h/buf.h"
#include "../h/pte.h"
#include "../h/ubavar.h"
#include "../h/ubareg.h"
#include "../h/systm.h"


#define LPPRI   PZERO+10
#define LPLOWAT 50

struct device {
	short   tricsr, tribuf;
};

#define ERRBIT  0100000
#define BUFSIZ	512
#define LPSIZ	(2*BUFSIZ)

struct tri {
	char	tricbuf[LPSIZ];	/* one buffer, no clist */
	char	*trir,*triw;	/* and two chasing pointers */
	int	tricc;		/* char count to disambiguate */
	char    flag;		/* the case of trir == triw */
} tritab[NTRI];

int tritimeout;

/*
 * flag bits
 */
#define OPEN    010
#define LBUSY   020
#define NOCR    040
#define ASLP    0100
#define ESLP    0200

#define IENABLE 0100
#define DONE    0200

int	triattach(), triprobe();
struct	uba_device *triinfo[NTRI];
u_short	tristd[] = { 0 };
struct	uba_driver tridriver =
	{ triprobe, 0, triattach, 0, tristd, "tri", triinfo };

triprobe(reg)
caddr_t reg;
{
	register int br, cvec;
	register struct device *triaddr = (struct device *)reg;

	triaddr->tricsr = IENABLE;
	triaddr->tribuf = '\0';
	DELAY(10000);
	return(1);
}

triattach()
{
}

triopen(dev, flag)
dev_t dev;
{
	register int s;
	register unit, d;
	int tritimer();
	register struct tri *tri;
	register struct uba_device *ui;

	d = minor(dev);
	unit = d&07;
	tri = &tritab[unit];
	ui = triinfo[unit];
	if (unit>=NTRI || tri->flag || ui->ui_alive==0) {
		u.u_error = ENXIO;
		return;
	}
	tri->flag = (d&077)|OPEN;
	tri->triw = tri->trir = tri->tricbuf;
	tri->tricc = 0;
	while ((((struct device *)ui->ui_addr)->tricsr&DONE) == 0)
		sleep((caddr_t)&lbolt, LPPRI);
	if (tritimeout==0) {
		tritimeout++;
		timeout(tritimer, (caddr_t)0, 10*hz);
	}
}

tritimer()
{
register struct tri *tri;
register unit, flag;

	for (unit=flag=0; unit<NTRI; unit++) {
		tri = &tritab[unit];
		if (tri->flag==0) {
			continue;
		}
		flag++;
		if (tri->flag&ESLP) {
			tri->flag &= ~ESLP;
			triintr(unit);
		}
	}
	if (flag) {
		timeout(tritimer, (caddr_t)0, 10*hz);
	} else {
		tritimeout = 0;
	}
}



triclose(dev)
register dev_t dev;
{
	register unit;
	register struct tri *tri;

	unit = minor(dev)&07;
	tri = &tritab[unit];

	triwait(tri, 0);
	tri->flag = 0;
	((struct device *)triinfo[unit]->ui_addr)->tricsr = 0;
}


triwait(tri, count)
register struct tri *tri;
register count;
{
	register int s, times;
	register r;

	times = 60;
	while (tri->tricc > count) {
		tri->flag |= ASLP;
		r = tsleep((caddr_t)tri, LPPRI, 10);
		if (r==TS_TIME) {
			s = spl4();
			if ((tri->flag&LBUSY)==0)
				triintr(tri-tritab);
			splx(s);
			times--;
			if (times==0) {
				printf ("cpr timeout, buffer flushed\n");
				goto flush;
			}
		}
		if (r==TS_SIG) {
		flush:
			tri->trir = tri->triw = tri->tricbuf;
			tri->tricc = 0;
		}
	}
}

triwrite(dev)
{
	register struct tri *tri;
	register char *p;
	register c, cc;
	register s;
	register char *trir;

	dev = minor(dev);
	tri = &tritab[dev];
	while(u.u_count) {
		trir = tri->trir;
		if (trir > tri->triw)
			cc = trir - tri->triw;
		else if (trir == tri->triw && tri->tricc != 0)
			cc = 0;	/* buffer full */
		else		/* from triw to the end of the buffer */
			cc = tri->tricbuf + LPSIZ - tri->triw;
		if (u.u_count < cc)
			cc = u.u_count;
		if (cc == 0) {	/* buffer must be full */
			s = spl4();
			if ((tri->flag&LBUSY) == 0) {
				triintr(dev);	/* poke it */
			}
			splx(s);
			triwait(tri,LPLOWAT);
		} else {	/* queue up some characters */
			iomove(tri->triw, cc, B_WRITE);
			if ((tri->triw += cc) >= tri->tricbuf + LPSIZ)
				tri->triw = tri->tricbuf;
			tri->tricc += cc;
			s = spl4();
			if ((tri->flag&LBUSY) == 0)
				triintr(dev);
			splx(s);
		}
	}
}


triintr(dev)
register dev;
{
	register struct tri *tri;
	register struct device *addr;
	register c, cc;

	tri = &tritab[dev];
	addr = (struct device *)triinfo[dev]->ui_addr;
	if ((addr->tricsr&DONE)==0) {
		return;
	}
	tri->flag &= ~LBUSY;
	if (addr->tricsr&ERRBIT) {
		addr->tricsr = 0;
		tri->flag &= ~LBUSY;
		tri->flag |= ESLP;
		return;
	}
	cc = 0;
	while (addr->tricsr&DONE && (tri->tricc > 0)) {
		addr->tribuf = *(tri->trir)++;
		if (tri->trir == tri->tricbuf + LPSIZ)
			tri->trir = tri->tricbuf;
		tri->tricc--;
		cc++;
	}
	if (cc) {
		addr->tricsr |= IENABLE;
		tri->flag |= LBUSY;
	}
	if (tri->tricc <= LPLOWAT && tri->flag&ASLP) {
		tri->flag &= ~ASLP;
		wakeup((caddr_t)tri);
	}
}
#endif