File:  [CSRG BSD Unix] / 41BSD / sys / dev / va.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 16:12:53 2018 UTC (8 years, 1 month ago) by root
Branches: MAIN, BSD
CVS tags: HEAD, BSD41
BSD 4.1

/*	va.c	4.1	11/9/80	*/

#include "../conf/va.h"
#if NVA > 0
/*
 * Benson-Varian 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"
#include "../h/map.h"
#include "../h/pte.h"
#include "../h/uba.h"
#include "../h/vcmd.h"

int	vabdp = 1;

unsigned minvaph();

#define	VAPRI	(PZERO-1)

#define	ushort	unsigned short
struct	varegs {
	ushort	vaba;
	short	vawc;
	union {
		short	Vacsw;
		struct {
			char Vacsl;
			char Vacsh;
		} vacsr;
	} vacs;
	short	vadata;
};

#define	vacsw	vacs.Vacsw
#define	vacsh	vacs.vacsr.Vacsh
#define	vacsl	vacs.vacsr.Vacsl

/* vacsw bits */
#define	ERROR		0100000		/* Some error has occurred */
#define	NPRTIMO		01000		/* DMA timeout error */
#define	NOTREADY	0400		/* Something besides NPRTIMO */
#define	DONE		0200
#define	IENABLE		0100		/* Interrupt enable */
#define	SUPPLIESLOW	04
#define	BOTOFFORM	02
#define	BYTEREVERSE	01		/* Reverse byte order in words */

/* vacsh command bytes */
#define	VAPLOT		0340
#define	VAPRINT		0100
#define	VAPRINTPLOT	0160
#define	VAAUTOSTEP	0244
#define	VANOAUTOSTEP	0045		/* unused */
#define	VAFORMFEED	0263		/* unused */
#define	VASLEW		0265		/* unused */
#define	VASTEP		0064		/* unused */

struct {
	char	va_open;
	char	va_busy;
	int	va_state;	/* State: bits are commands in vcmd.h. */
	int	va_wc;
	int	va_bufp;
	struct	buf *va_bp;
} va11;
int	va_ubinfo;

struct	buf rvabuf;		/* Used by physio for a buffer. */

vaopen()
{

	if (va11.va_open) {
		u.u_error = ENXIO;
		return;
	}
	va11.va_open = 1;
	VAADDR->vawc = 0;
	va11.va_wc = 0;
	va11.va_state = 0;
	VAADDR->vacsl = IENABLE;
	vatimo();
	vacmd(VPRINT);
	if (u.u_error)
		vaclose();
}

vastrategy(bp)
	register struct buf *bp;
{
	register int e;

	(void) spl4();
	while (va11.va_busy)
		sleep((caddr_t)&va11, VAPRI);
	va11.va_busy = 1;
	va11.va_bp = bp;
	va_ubinfo = ubasetup(bp, vabdp);
	va11.va_bufp = va_ubinfo & 0x3ffff;
	if (e = vaerror(DONE))
		goto brkout;
	va11.va_wc = -(bp->b_bcount/2);
	vastart();
	e = vaerror(DONE);	/* Wait for DMA to complete */
	va11.va_wc = 0;
	va11.va_bufp = 0;

	/*
	 * After printing a line of characters, VPRINTPLOT mode essentially
	 * reverts to VPLOT mode, plotting things until a new mode is set.
	 * This change is indicated by sending a VAAUTOSTEP command to
	 * the va.  We also change va_state to reflect this effective
	 * mode change.
	 */
	if (va11.va_state & VPRINTPLOT) {
		va11.va_state = (va11.va_state & ~VPRINTPLOT) | VPLOT;
		VAADDR->vacsh = VAAUTOSTEP;
		e |= vaerror(DONE);
	}
	(void) spl0();
brkout:
	ubafree(va_ubinfo), va_ubinfo = 0;
	va11.va_bp = 0;
	va11.va_busy = 0;
	iodone(bp);
	if (e)
		u.u_error = EIO;
	wakeup((caddr_t)&va11);
}

int	vablock = 16384;

unsigned
minvaph(bp)
struct buf *bp;
{
	if (bp->b_bcount > vablock)
		bp->b_bcount = vablock;
}

/*ARGSUSED*/
vawrite(dev)
{
	physio(vastrategy, &rvabuf, dev, B_WRITE, minvaph);
}

/*
 * Vaerror waits until bit or ERROR gets set, then returns non-zero if
 * if it was ERROR that was set.
 */
vaerror(bit)
{
	register int e;

	while ((e = VAADDR->vacsw & (bit|ERROR)) == 0)
		sleep((caddr_t)&va11, VAPRI);
	return (e & ERROR);
}

vastart()
{
	if (va11.va_wc) {
		VAADDR->vaba = va11.va_bufp;
		VAADDR->vawc = va11.va_wc;
		return;
	}
}

/*ARGSUSED*/
vaioctl(dev, cmd, addr, flag)
	register caddr_t addr;
{
	register int vcmd;

	switch (cmd) {

	case VGETSTATE:
		(void) suword(addr, va11.va_state);
		return;

	case VSETSTATE:
		vcmd = fuword(addr);
		if (vcmd == -1) {	
			u.u_error = EFAULT;
			return;
		}
		vacmd(vcmd);
		return;

	default:
		u.u_error = ENOTTY;	/* Not a legal ioctl cmd. */
		return;
	}
}

/*
 * Send a command code to the va, and wait for it to complete.
 * If an error occurs, u.u_error is set to EIO.
 * In any case, update va11.va_state.
 */
vacmd(vcmd)
{
	(void) spl4();
	(void) vaerror(DONE);		/* Wait for va to be ready */
	switch (vcmd) {

	case VPLOT:
		/* Must turn on plot AND autostep modes. */
		VAADDR->vacsh = VAPLOT;
		if (vaerror(DONE))
			u.u_error = EIO;
		VAADDR->vacsh = VAAUTOSTEP;
		break;

	case VPRINT:
		VAADDR->vacsh = VAPRINT;
		break;

	case VPRINTPLOT:
		VAADDR->vacsh = VAPRINTPLOT;
		break;
	}
	va11.va_state =
		(va11.va_state & ~(VPLOT | VPRINT | VPRINTPLOT)) | vcmd;

	if (vaerror(DONE))	/* Wait for command to complete. */
		u.u_error = EIO;
	(void) spl0();
}

vatimo()
{
	if (va11.va_open)
		timeout(vatimo, (caddr_t)0, HZ/10);
	vaintr(0);
}

/*ARGSUSED*/
vaintr(dev)
{
	wakeup((caddr_t)&va11);
}

vaclose()
{

	va11.va_open = 0;
	va11.va_busy = 0;
	va11.va_state = 0;
	va11.va_wc = 0;
	va11.va_bufp = 0;
	VAADDR->vacsl = 0;
}

#define	DELAY(N)	{ register int d; d = N; while (--d > 0); }

vareset()
{

	if (va11.va_open == 0)
		return;
	printf(" va");
	VAADDR->vacsl = IENABLE;
	if (va11.va_state & VPLOT) {
		VAADDR->vacsh = VAPLOT;
		DELAY(10000);
		VAADDR->vacsh = VAAUTOSTEP;
	} else if (va11.va_state & VPRINTPLOT)
		VAADDR->vacsh = VPRINTPLOT;
	else
		VAADDR->vacsh = VAPRINTPLOT;
	DELAY(10000);
	if (va11.va_busy == 0)
		return;
	if (va_ubinfo) {
		printf("<%d>", (va_ubinfo>>28)&0xf);
		ubafree(va_ubinfo), va_ubinfo = 0;
	}
	/* This code belongs in vastart() */
	va_ubinfo = ubasetup(va11.va_bp, vabdp);
	va11.va_bufp = va_ubinfo & 0x3ffff;
	va11.va_wc = (-va11.va_bp->b_bcount/2);
	/* End badly placed code */
	vastart();
}
#endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.