BBN-Vax-TCP/dev/va.c

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

/*	va.c	4.10	81/07/08	*/

#include "va.h"
#if NVA > 0
/*
 * Varian printer plotter
 */
#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/ubareg.h"
#include "../h/ubavar.h"
#include "../h/vcmd.h"

unsigned minvaph();

#define	VAPRI	(PZERO-1)

struct	vadevice {
	u_short	vaba;			/* buffer address */
	short	vawc;			/* word count (2's complement) */
	union {
		short	Vacsw;		/* control status as word */
		struct {		/* control status as bytes */
			char Vacsl;
			char Vacsh;
		} vacsr;
	} vacs;
	short	vadata;			/* programmed i/o data buffer */
};

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

/* vacsw bits */
#define	VA_ERROR	0100000		/* some error has occurred */
#define	VA_NPRTIMO	0001000		/* DMA timeout error */
#define	VA_NOTREADY	0000400		/* something besides NPRTIMO */
#define	VA_DONE		0000200
#define	VA_IENABLE	0000100		/* interrupt enable */
#define	VA_SUPPLIESLOW	0000004
#define	VA_BOTOFFORM	0000002
#define	VA_BYTEREVERSE	0000001		/* reverse byte order in words */

/* vacsh command bytes */
#define	VAPLOT		0000340
#define	VAPRINT		0000100
#define	VAPRINTPLOT	0000160
#define	VAAUTOSTEP	0000244
#define	VANOAUTOSTEP	0000045
#define	VAFORMFEED	0000263
#define	VASLEW		0000265
#define	VASTEP		0000064

struct va_softc {
	char	sc_openf;
	char	sc_busy;
	int	sc_state;
	int	sc_wc;
	struct	buf *sc_bp;
	int	sc_ubinfo;
} va_softc[NVA];

#define	VAUNIT(dev)	(minor(dev))

struct	buf rvabuf[NVA];

int	vaprobe(), vaattach();
struct	uba_device *vadinfo[NVA];
u_short	vastd[] = { 0764000, 0 };
struct	uba_driver vadriver =
    { vaprobe, 0, vaattach, 0, vastd, "va", vadinfo };

vaprobe(reg)
	caddr_t reg;
{
	register int br, cvec;		/* value-result */
	register struct vadevice *vaaddr = (struct vadevice *)reg;

	vaaddr->vacsl = VA_IENABLE;
	vaaddr->vaba = 0;
	vaaddr->vacsh = VAPLOT;
	vaaddr->vacsl = 0;
	vaaddr->vawc = -1;
	DELAY(10000);
	vaaddr->vacsl = 0;
}

/*ARGSUSED*/
vaattach(ui)
	struct uba_device *ui;
{

}

vaopen(dev)
	dev_t dev;
{
	register struct va_softc *sc;
	register struct vadevice *vaaddr;
	register struct uba_device *ui;

	if (VAUNIT(dev) >= NVA || (sc = &va_softc[minor(dev)])->sc_openf ||
	    (ui = vadinfo[VAUNIT(dev)]) == 0 || ui->ui_alive == 0) {
		u.u_error = ENXIO;
		return;
	}
	vaaddr = (struct vadevice *)ui->ui_addr;
	sc->sc_openf = 1;
	vaaddr->vawc = 0;
	sc->sc_wc = 0;
	sc->sc_state = 0;
	vaaddr->vacsl = VA_IENABLE;
	vatimo(dev);
	vacmd(dev, VPRINT);
	if (u.u_error)
		vaclose(dev);
}

vastrategy(bp)
	register struct buf *bp;
{
	register int e;
	register struct va_softc *sc = &va_softc[VAUNIT(bp->b_dev)];
	register struct uba_device *ui = vadinfo[VAUNIT(bp->b_dev)];
	register struct vadevice *vaaddr = (struct vadevice *)ui->ui_addr;

	(void) spl4();
	while (sc->sc_busy)
		sleep((caddr_t)sc, VAPRI);
	sc->sc_busy = 1;
	sc->sc_bp = bp;
	sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP);
	if (e = vawait(bp->b_dev))
		goto brkout;
	sc->sc_wc = -(bp->b_bcount/2);
	vastart(bp->b_dev);
	e = vawait(bp->b_dev);
	sc->sc_wc = 0;
	if (sc->sc_state & VPRINTPLOT) {
		sc->sc_state = (sc->sc_state & ~VPRINTPLOT) | VPLOT;
		vaaddr->vacsh = VAAUTOSTEP;
		e |= vawait(bp->b_dev);
	}
	(void) spl0();
brkout:
	ubarelse(ui->ui_ubanum, &sc->sc_ubinfo);
	sc->sc_bp = 0;
	sc->sc_busy = 0;
	iodone(bp);
	if (e)
		u.u_error = EIO;
	wakeup((caddr_t)sc);
}

int	vablock = 16384;

unsigned
minvaph(bp)
	struct buf *bp;
{

	if (bp->b_bcount > vablock)
		bp->b_bcount = vablock;
}

/*ARGSUSED*/
vawrite(dev)
	dev_t dev;
{

	physio(vastrategy, &rvabuf[VAUNIT(dev)], dev, B_WRITE, minvaph);
}

vawait(dev)
	dev_t dev;
{
	register struct vadevice *vaaddr =
	    (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr;
	register int e;

	while (((e = vaaddr->vacsw) & (VA_DONE|VA_ERROR)) == 0)
		sleep((caddr_t)&va_softc[VAUNIT(dev)], VAPRI);
	if (e & VA_NPRTIMO)
		printf("va%d: npr timeout\n", VAUNIT(dev));
	return (e & VA_ERROR);
}

vastart(dev)
	dev_t;
{
	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
	register struct vadevice *vaaddr =
	    (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr;

	if (sc->sc_wc == 0)
		return;
	vaaddr->vaba = sc->sc_ubinfo;
	vaaddr->vacsl = (sc->sc_ubinfo >> 12) & 0x30;
	vaaddr->vawc = sc->sc_wc;
}

/*ARGSUSED*/
vaioctl(dev, cmd, addr, flag)
	register caddr_t addr;
{
	register int vcmd;
	register struct va_softc *sc = &va_softc[VAUNIT(dev)];

	switch (cmd) {

	case VGETSTATE:
		(void) suword(addr, sc->sc_state);
		return;

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

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

vacmd(dev, vcmd)
	dev_t dev;
	int vcmd;
{
	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
	register struct vadevice *vaaddr =
	    (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr;

	(void) spl4();
	(void) vawait(dev);
	switch (vcmd) {

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

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

	case VPRINTPLOT:
		vaaddr->vacsh = VAPRINTPLOT;
		break;
	}
	sc->sc_state = (sc->sc_state & ~(VPLOT|VPRINT|VPRINTPLOT)) | vcmd;
	if (vawait(dev))
		u.u_error = EIO;
	(void) spl0();
}

vatimo(dev)
	dev_t dev;
{
	register struct va_softc *sc = &va_softc[VAUNIT(dev)];

	if (sc->sc_openf)
		timeout(vatimo, (caddr_t)dev, hz/10);
	vaintr(dev);
}

/*ARGSUSED*/
vaintr(dev)
	dev_t dev;
{
	register struct va_softc *sc = &va_softc[VAUNIT(dev)];

	wakeup((caddr_t)sc);
}

vaclose(dev)
	dev_t dev;
{
	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
	register struct vadevice *vaaddr =
	    (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr;

	sc->sc_openf = 0;
	sc->sc_busy = 0;
	sc->sc_state = 0;
	sc->sc_ubinfo = 0;
	vaaddr->vacsl = 0;
}

vareset(uban)
	int uban;
{
	register int va11;
	register struct uba_device *ui;
	register struct va_softc *sc = va_softc;
	register struct vadevice *vaaddr;

	for (va11 = 0; va11 < NVA; va11++, sc++) {
		if ((ui = vadinfo[va11]) == 0 || ui->ui_alive == 0 ||
		    ui->ui_ubanum != uban || sc->sc_openf == 0)
			continue;
		printf(" va%d", va11);
		vaaddr = (struct vadevice *)ui->ui_addr;
		vaaddr->vacsl = VA_IENABLE;
		if (sc->sc_state & VPLOT) {
			vaaddr->vacsh = VAPLOT;
			DELAY(10000);
			vaaddr->vacsh = VAAUTOSTEP;
		} else if (sc->sc_state & VPRINTPLOT)
			vaaddr->vacsh = VPRINTPLOT;
		else
			vaaddr->vacsh = VAPRINTPLOT;
		DELAY(10000);
		if (sc->sc_busy == 0)
			continue;
		if (sc->sc_ubinfo) {
			printf("<%d>", (sc->sc_ubinfo>>28)&0xf);
			ubarelse(ui->ui_ubanum, &sc->sc_ubinfo);
		}
		sc->sc_ubinfo = ubasetup(ui->ui_ubanum, sc->sc_bp, UBA_NEEDBDP);
		sc->sc_wc = -(sc->sc_bp->b_bcount/2);
		vastart(sc->sc_bp->b_dev);
	}
}
#endif