V9/sys/dev.old/mg.c

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

/*
 * DR11C for Mergenthaler 202
 */
#include "mg.h"
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/stream.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);
}