V8/usr/sys/dev/tri.c
/*
* 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