V10/sys/io/vplot.c

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

/*
 * Versatec model 122 matrix printer/plotter
 * dma interface driver
 *
 */
#include "sys/param.h"
#include "sys/conf.h"
#include "sys/user.h"
#include "sys/buf.h"
#include "sys/ubaddr.h"

#include "sys/vplot.h"
#include "sys/vplotcmd.h"

struct device {
	short	csr;
	short	buf;
};

#define	ERROR		0100000
#define	SPP		0020000
#define	BTCNT		0010000
#define	ADDR		0004000
#define	PP		0002000
#define	SWPBT		0001000
#define	READY		0000200
#define	IENABLE		0000100
#define XMEM		0000060
#define xmem(a)		(((a) >> 12) & XMEM)
#define	REMOTE		0000016
#define	GO		0000001

#define MASK		(SPP|PP|SWPBT|REMOTE)

#define	RESET		(06 << 1)

/*
 * config glue
 */
int vplotopen(), vplotclose(), vplotwrite(), vplotioctl();

extern struct vplot vplot[];
extern struct ubaddr vplotaddr[];
extern int vplotcnt;
struct cdevsw vplotcdev =
	cdinit(vplotopen, vplotclose, nodev, vplotwrite, vplotioctl);

#define	VPLOTPRI	(PZERO-1)

vplotopen(d, f)
{
	register int dev;
	register struct vplot *vp;

	if((dev = minor(d)) >= vplotcnt) {
		u.u_error = ENODEV;
		return;
	}
	if((vp = &vplot[dev])->open) {
		u.u_error = EBUSY;
		return;
	}
	if((vp->addr = (struct device *)ubaddr(&vplotaddr[dev])) == 0
	  || ubbadaddr(vplotaddr[dev].ubno, (caddr_t)vp->addr, sizeof(u_short))) {
		printf("vplot%d absent\n", dev);
		u.u_error = ENODEV;
		return;
	}
	vp->open = 1;
	vp->addr->csr = RESET;
	if(vplotwait(vp)) {
		u.u_error = ENXIO;
		vplotclose(d);
		return;
	}
	vp->addr->csr |= IENABLE;
	vplottimo(vp);
	if(u.u_error)
		vplotclose(d);
}

vplotclose(d)
{
	register struct vplot *vp = &vplot[minor(d)];

	vp->open = 0;
	vp->addr->csr = 0;
}

vplotstrategy(bp)
register struct buf *bp;
{
	register struct vplot *vp = &vplot[minor(bp->b_dev)];
	register ubm_t ubm;
	register uaddr_t uaddr;
	register int cc, e, s;

	s = spl4();
	(void) vplotwait(vp);
	ubm = ubmbuf(vplotaddr[minor(bp->b_dev)].ubno, bp, UBDP|USLP);
	uaddr = ubadbuf(vplotaddr[minor(bp->b_dev)].ubno, bp, ubm);
	if(e = vplotwait(vp))
		goto out;
	if((cc = -(bp->b_bcount)) != 0) {
		vp->addr->csr |= IENABLE | ADDR;
		vp->addr->csr &= ~BTCNT;
		vp->addr->buf = uaddr;
		vp->addr->csr |= BTCNT;
		vp->addr->buf = cc;
		vp->addr->csr |= xmem(uaddr) | GO;
	}
	e = vplotwait(vp);
out:
	(void) splx(s);
	ubmfree(vplotaddr[minor(bp->b_dev)].ubno, ubm);
	if(e)
		bp->b_flags |= B_ERROR;
	iodone(bp);
}

int	vplotblock = 16384;

unsigned
minvplotph(bp)
struct buf *bp;
{
	if(bp->b_bcount > vplotblock)
		bp->b_bcount = vplotblock;
}

/*ARGSUSED*/
vplotwrite(d)
{
	if(u.u_count == 0)
		return;
	physio(vplotstrategy, &vplot[minor(d)].buf, d, B_WRITE, minvplotph);
}

vplotwait(vp)
register struct vplot *vp;
{
	register int e;

	for(;;) {
		if(vp->addr->csr & (ERROR|READY))
			break;
		if(tsleep((caddr_t)vp, VPLOTPRI, HZ) != TS_OK)
			break;
	}
	if((vp->addr->csr & ERROR) == 0)
		return 0;
	/* Check for NXM - ERROR remains 1 if NOT NXM) */
	vp->addr->csr &= ~ERROR;
	if((e = (vp->addr->csr & ERROR)) == 0)
		printf("vplot%d: NXM\n", vp - vplot);
	return e;
}

/*ARGSUSED*/
vplotioctl(dev, cmd, addr, flag)
caddr_t addr;
{
	register struct vplot *vp = &vplot[minor(dev)];
	u_short csr;
	int m;

	switch(cmd) {

	case VGETSTATE:
		m = vp->addr->csr;
		if(copyout((caddr_t)&m, addr, sizeof(m)))
			u.u_error = EFAULT;
		break;

	case VSETSTATE:
		if(copyin(addr, (caddr_t)&m, sizeof(m))) {
			u.u_error = EFAULT;
			return;
		}
		(void) spl4();
		csr = (vp->addr->csr & ~MASK) | (m & MASK);
		vp->addr->csr = csr;
		if(vplotwait(vp))
			u.u_error = EIO;
		(void) spl0();
		break;

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

vplottimo(vp)
register struct vplot *vp;
{
	if(vp->open)
		timeout(vplottimo, (caddr_t)vp, HZ/10);
	vplot0int(vp - vplot);
}

vplot0int(d)
{
	wakeup((caddr_t)&vplot[d]);
}