V10/sys/md/conscomet.c

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

/*
 * VAX-11/750 console driver
 * this is probably the simplest version
 */
#include "sys/param.h"
#include "sys/stream.h"
#include "sys/ttyio.h"
#include "sys/cons.h"
#include "sys/mtpr.h"
#include "sys/conf.h"

/*
 * state bits
 */
#define	TTSTOP	01
#define	BUSY	02
#define	TIMEOUT	04

char	cnstate;
struct	queue	*cnrq;
struct	queue	*cnwq;

long	cnopen();
int	cnclose(), cnoput(), nodev();

static struct qinit cnrinit = { nodev, NULL, cnopen, cnclose, 0, 0 };
static struct qinit cnwinit = { cnoput, NULL, cnopen, cnclose, 200, 100 };
struct streamtab cnstream = { &cnrinit, &cnwinit };
struct cdevsw cncdev = cstrinit(&cnstream);

long
cnopen(qp, dev)
register struct queue *qp;
{
	cnrq = qp;
	cnwq = WR(qp);
	mtpr(RXCS, mfpr(RXCS)|RXCS_IE);
	return(1);
}

cnclose(qp)
struct queue *qp;
{
	cnrq = NULL;
	cnwq = NULL;
}

/*
 * Console write put routine
 */
cnoput(q, bp)
register struct queue *q;
register struct block *bp;
{
	register struct ttydevb *sp;

	switch(bp->type) {

	case M_IOCTL:		/* just acknowledge */
		sp = (struct ttydevb *)stiodata(bp);
		switch (stiocom(bp)) {

		case TIOCGDEV:
			sp->ispeed = sp->ospeed = B9600;
			bp->wptr = bp->rptr + sizeof(struct ttydevb) + STIOCHDR;
			bp->type = M_IOCACK;
			qreply(q, bp);
			return;
		case TIOCSDEV:
			bp->wptr = bp->rptr;
			bp->type = M_IOCACK;
			qreply(q, bp);
			return;
		default:
			bp->type = M_IOCNAK;
			bp->wptr = bp->rptr;
			qreply(q, bp);
			return;
		}

	case M_STOP:
		cnstate |= TTSTOP;
		break;

	case M_START:
		cnstate &= ~TTSTOP;
		cnstart();
		break;

	case M_FLUSH:
		flushq(q, 0);
		break;

	case M_DELAY:
	case M_DATA:
		if (bp->rptr >= bp->wptr)
			break;
		putq(q, bp);
		cnstart();
		return;
	
	default:		/* not handled; just toss */
		break;
	}
	freeb(bp);
}

/*
 * Console receive interrupt
 */
/*ARGSUSED*/
cnrint(dev)
{
	register int c;

	c = mfpr(RXDB);
	if (c&RXDB_ID || cnrq==NULL)
		return;
	if ((cnrq->next->flag & QFULL) == 0)
		putd(cnrq->next->qinfo->putp, cnrq->next, c);
}


/*
 * Transmitter interrupt
 */
/*ARGSUSED*/
cnxint(dev)
{
	cnstate &= ~BUSY;
	mtpr(TXCS, mfpr(TXCS)&~TXCS_IE);
	cnstart();
}

cntime()
{
	cnstate &= ~TIMEOUT;
	cnstart();
}

cnstart()
{
	register s;
	register struct block *bp;

	if (cnwq==NULL)
		return;
	s = spl6();
	if ((cnstate & (TIMEOUT|BUSY|TTSTOP))==0 && cnwq->count) {
		bp = getq(cnwq);
		switch (bp->type) {

		case M_DATA:
			mtpr(TXDB, *bp->rptr++);
			mtpr(TXCS, mfpr(TXCS)|TXCS_IE);
			cnstate |= BUSY;
			if (bp->rptr >= bp->wptr)
				freeb(bp);
			else
				putbq(cnwq, bp);
			break;

		case M_DELAY:
			timeout(cntime, (caddr_t)NULL, (int)*bp->rptr);
			cnstate |= TIMEOUT;
		default:	/* flow through */
			freeb(bp);
			break;
		}
	}
	splx(s);
}

/*
 * Print a character on console.
 * Attempts to save and restore device
 * status.
 */
cnputc(c)
register c;
{
	register s, timo;

	timo = 30000;
	/*
	 * Try waiting for the console tty to come ready,
	 * otherwise give up after a reasonable time.
	 */
	while((mfpr(TXCS)&TXCS_RDY) == 0)
		if(--timo == 0)
			return;
	if(c == 0)
		return;
	s = mfpr(TXCS);
	mtpr(TXCS, 0);
	mtpr(TXDB, c&0xff);
	if(c == '\n')
		cnputc('\r');
	cnputc(0);
	mtpr(TXCS, s);
}