V8/usr/sys/dev/mg.c
/*
* DR11C for Mergenthaler 202
*/
#include "mg.h"
#if NMG
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/stream.h"
#include "../h/ioctl.h"
#include "../h/pte.h"
#include "../h/map.h"
#include "../h/buf.h"
#include "../h/ubavar.h"
#include "../h/conf.h"
struct device {
unsigned short csr;
unsigned short wbuf;
unsigned short rbuf;
};
struct device *MGADDR;
struct {
char busy;
struct queue *rq;
struct queue *wq;
} mg;
/*
* Hardware control bits
*/
#define CSR0 1
#define CSR1 2
#define REQA 0200
#define REQB 0100000
#define INTA 0100
#define INTB 040
int nodev(), mgopen(), mgclose(), mgoput();
static struct qinit mgrinit = { nodev, NULL, mgopen, mgclose, 0, 0 };
struct qinit mgwinit = { mgoput, NULL, mgopen, mgclose, 200, 100 };
struct streamtab mginfo = { &mgrinit, &mgwinit };
int mgattach(), mgprobe();
struct uba_device *mgstuff[NMG];
u_short mgstd[] = { 0 };
struct uba_driver mgdriver =
{ mgprobe, 0, mgattach, 0, mgstd, "mg", mgstuff };
mgprobe(reg)
caddr_t reg;
{
register int br, cvec;
register struct device *mgaddr = (struct device *)reg;
mg.busy = 0;
mg.rq = mg.wq = NULL;
MGADDR = mgaddr;
mgaddr->csr = INTA;
DELAY(10000);
mgaddr->csr = 0;
return(1);
}
mgattach()
{
}
/*
* comment
*/
mgopen(q, dev)
register struct queue *q;
register dev_t dev;
{
register d, c;
d = minor(dev);
MGADDR->csr |= CSR0 | CSR1;
if(d == 0){
if(mg.rq != NULL) goto bad;
c = MGADDR->rbuf;
MGADDR->csr |= INTB;
mg.rq = q;
} else if(d == 1){
if(mg.wq != NULL) goto bad;
MGADDR->csr |= INTA;
mg.wq = WR(q);
} else {
goto bad;
}
q->ptr = (caddr_t) minor(dev);
WR(q)->ptr = (caddr_t) minor(dev);
return(1);
bad:
return(0);
}
/*
* close MG
*/
mgclose(q)
register struct queue *q;
{
int dev;
dev = (int) q->ptr;
if(dev){
mg.wq = NULL;
} else {
MGADDR->csr &= (~INTB);
/* flush output */;
flushq(WR(q), 1);
mg.rq = NULL;
}
}
/*
* DK receiver interrupt.
*/
mgrint(dev)
{
register struct queue *q;
register struct block *bp;
register c;
q = mg.rq;
c = MGADDR->rbuf;
if(q == NULL) return;
if((q->flag & QFULL) == 0){
putd(q->next->qinfo->putp, q->next, c);
}
}
/*
* MG put procedure
*/
mgoput(q, bp)
register struct queue *q;
register struct block *bp;
{
int s, r, n;
switch(bp->type){
case M_IOCTL:
bp->type = M_IOCNAK;
bp->wptr = bp->rptr;
qreply(q, bp);
return;
case M_FLUSH:
flushq(q, 0);
break;
case M_DATA:
putq(q, bp);
mgstart();
return;
default:
break;
}
freeb(bp);
}
mgtint(dev)
{
mg.busy = 0;
mgstart();
}
mgstart()
{
register c, s;
register struct block *bp;
if(mg.wq == NULL) return;
s = spl6();
if((mg.busy == 0) && mg.wq->count){
bp = getq(mg.wq);
switch(bp->type){
case M_DATA:
MGADDR->wbuf = *bp->rptr++;
mg.busy = 1;
if(bp->rptr >= bp->wptr)
freeb(bp);
else
putbq(mg.wq, bp);
break;
default:
freeb(bp);
break;
}
}
splx(s);
}
#endif