V7M/sys/dev/vp.c

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

/*
 *  Versatec matrix printer/plotter 
 *  dma interface driver
 */

#include "../h/param.h"
#include "../h/dir.h"
#include "../h/user.h"
#include "../h/buf.h"
#include "../h/systm.h"

#define	VPPRI	(PZERO+8)

/* device registers */
struct vpregs {
	int	plbcr;
	int	fill;
	int	prbcr;
	caddr_t	pbaddr;
	int	plcsr;
	int	plbuf;
	int	prcsr;
	caddr_t	prbuf;
};

#define	VPADDR	((struct vpregs *)0177500)

/* status bits */
#define	ERROR	0100000
#define	DTCINTR	040000
#define	DMAACT	020000
#define	READY	0200
#define	IENABLE	0100
#define TERMCOM	040
#define	FFCOM	020
#define	EOTCOM	010
#define	CLRCOM	04
#define	RESET	02
#define	SPP	01

struct {
	int	vp_state;
	int	vp_count;
	struct	buf	*vp_buf;
	caddr_t	vp_bufp;
}	vp11;

/*states */
#define	ISOPEN	01
#define	CMNDS	076
#define	MODE	0700
#define	PRINT	0100
#define	PLOT	0200
#define	PPLOT	0400
#define	BUSY	01000

vpopen()
{
	if (vp11.vp_state & ISOPEN) {
		u.u_error = ENXIO;
		return;
	}
	vp11.vp_state = ISOPEN | PRINT | CLRCOM | FFCOM | RESET;
	vp11.vp_count = 0;
	vp11.vp_buf = geteblk();
	vp11.vp_bufp = vp11.vp_buf->b_un.b_addr;
	VPADDR->prcsr = IENABLE | DTCINTR;
	vptimo();
	while(vp11.vp_state & CMNDS) {
		spl4();
		if (vperror(READY)) {
			vpclose();
			u.u_error = EIO;
			return;
		}
		vpstart();
		spl0();
	}
}

vpwrite()
{
	register int i, e;

	if (u.u_count == 0)
		return;
	spl4();
	while(vp11.vp_state & BUSY)
		sleep((caddr_t)&vp11, VPPRI);
	vp11.vp_state |= BUSY;
	spl0();
	while(i = vp11.vp_count = min(512,u.u_count)) {
		u.u_offset = 0;		/* Make even, speed up iomove */
		iomove(vp11.vp_buf->b_un.b_addr, i, B_WRITE);
		spl4();
		if (e = vperror(READY))
			break;
		vpstart();
		while ((vp11.vp_state&PLOT?VPADDR->plcsr:VPADDR->prcsr)&DMAACT)
			sleep((caddr_t)&vp11, VPPRI);
		if ((vp11.vp_state&MODE) == PPLOT)
			vp11.vp_state = vp11.vp_state&~MODE | PLOT;
		spl0();
	}
	vp11.vp_state &= ~BUSY;
	if (e)
		u.u_error = EIO;
	wakeup((caddr_t)&vp11);
}

vperror(bit)
{
	register state, e;

	state = vp11.vp_state&PLOT;
	while((e=(state?VPADDR->plcsr:VPADDR->prcsr) & (bit|ERROR)) == 0)
		sleep((caddr_t)&vp11, VPPRI);
	return(e&ERROR);
}

vpstart()
{
	register bit;

	if (vp11.vp_count) {
		VPADDR->pbaddr = vp11.vp_bufp;
		if (vp11.vp_state & (PRINT|PPLOT))
			VPADDR->prbcr = vp11.vp_count;
		else
			VPADDR->plbcr = vp11.vp_count;
		return;
	}
	for (bit=1; bit!=0; bit <<= 1)
		if (vp11.vp_state&bit&CMNDS) {
			VPADDR->plcsr |= bit;
			vp11.vp_state &= ~bit;
			return;
		}
}

vpioctl(dev, cmd, addr, flag)
register caddr_t addr;
{
	register m;

	switch(cmd) {

	/* get mode */
	case ('v'<<8)+0:
		suword(addr, vp11.vp_state);
		return;

	/* set mode */
	case ('v'<<8)+1:
		m = fuword(addr);
		if (m == -1) {
			u.u_error = EFAULT;
			return;
		}
		spl4();
		vperror(READY);
		vp11.vp_state = (vp11.vp_state & ~MODE) | (m&(MODE|CMNDS));
		if (vp11.vp_state&PPLOT)
			VPADDR->plcsr |= SPP;
		else
			VPADDR->plcsr &= ~SPP;
		vp11.vp_count = 0;
		while(CMNDS & vp11.vp_state) {
			vperror(READY);
			vpstart();
		}
		spl0();
		return;

	default:
		u.u_error = ENOTTY;
		return;
	}
}

vptimo()
{
	if (vp11.vp_state&ISOPEN)
		timeout(vptimo, (caddr_t)0, HZ/10);
	vpintr(0);
}

vpintr(dev)
{
	wakeup((caddr_t)&vp11);
}

vpclose()
{
	brelse(vp11.vp_buf);
	vp11.vp_state = 0;
	vp11.vp_count = 0;
	vp11.vp_buf = 0;
	vp11.vp_bufp = 0;
	VPADDR->plcsr = 0;
}