4.1cBSD/a/sys/vaxuba/va.c

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

/*	va.c	4.21	83/03/10	*/

#include "va.h"
#if NVA > 0
/*
 * Varian printer plotter
 */
#include "../machine/pte.h"

#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/ioctl.h"
#include "../h/vcmd.h"
#include "../h/uio.h"
#include "../h/kernel.h"

#include "../vaxuba/ubareg.h"
#include "../vaxuba/ubavar.h"

int	vadebug = 0;
#define	dprintf	if(vadebug)printf

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_DMAGO	0000010		/* DMA go bit */
#define	VA_DMAGO	0000010		/* DMA go bit */
#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 {
	u_char	sc_openf;		/* exclusive open flag */
	u_char	sc_iostate;		/* kind of I/O going on */
#define	VAS_IDLE	0	/* no I/O, free */
#define	VAS_PIO		1	/* programmed I/O */
#define	VAS_DMA		2	/* DMA, block pio */
#define	VAS_WANT	4	/* wakeup when iostate changes */
	short	sc_tocnt;		/* time out counter */
	short	sc_info;		/* csw passed from vaintr */
	int	sc_state;		/* print/plot state of device */
} va_softc[NVA];

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

struct	buf rvabuf[NVA];

int	vaprobe(), vaslave(), vaattach(), vadgo();
struct	uba_device *vadinfo[NVA];
struct	uba_ctlr *vaminfo[NVA];
struct	buf vabhdr[NVA];
u_short	vastd[] = { 0764000, 0 };
struct	uba_driver vadriver =
    { vaprobe, vaslave, vaattach, vadgo, vastd, "vz", vadinfo, "va", vaminfo };

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

#ifdef lint
	br = 0; cvec = br; br = cvec;
	vaintr(0);
#endif
#ifndef UCBVAX
	vaaddr->vacsl = VA_IENABLE;
	vaaddr->vaba = 0;
	vaaddr->vacsh = VAPLOT;
	vaaddr->vacsl = VA_IENABLE|VA_DMAGO;
	vaaddr->vawc = -1;
	DELAY(10000);
	vaaddr->vacsl = 0;
	vaaddr->vawc = 0;
#else
	br=0x14;
	cvec=0170;
#endif
	return (sizeof (struct vadevice));
}

/*ARGSUSED*/
vaslave(ui, reg)
	struct uba_device *ui;
	caddr_t reg;
{

	ui->ui_dk = 0;
	return (ui->ui_unit <= 0);
}

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

	ui->ui_mi->um_tab.b_actf = &vabhdr[ui->ui_unit];
}

vaopen(dev)
	dev_t dev;
{
	register struct va_softc *sc;
	register struct vadevice *vaaddr;
	register struct uba_device *ui;
	int error;
	int unit = VAUNIT(dev);

	if (unit >= NVA || (sc = &va_softc[unit])->sc_openf ||
	    (ui = vadinfo[unit]) == 0 || ui->ui_alive == 0)
		return (ENXIO);
	vaaddr = (struct vadevice *)ui->ui_addr;
	sc->sc_openf = 1;
	vaaddr->vawc = 0;
	sc->sc_state = 0;
	sc->sc_tocnt = 0;
	sc->sc_iostate = VAS_IDLE;
	vaaddr->vacsl = VA_IENABLE;
	vatimo(dev);
	error = vacmd(dev, VPRINT);
	if (error)
		vaclose(dev);
	return (error);
}

vastrategy(bp)
	register struct buf *bp;
{
	register struct uba_device *ui;
	register struct uba_ctlr *um;
	int s;

	dprintf("vastrategy(%x)\n", bp);
	ui = vadinfo[VAUNIT(bp->b_dev)];
	if (ui == 0 || ui->ui_alive == 0) {
		bp->b_flags |= B_ERROR;
		iodone(bp);
		return;
	}
	s = spl4();
	um = ui->ui_mi;
	bp->b_actf = NULL;
	if (um->um_tab.b_actf->b_actf == NULL)
		um->um_tab.b_actf->b_actf = bp;
	else {
		printf("bp = 0x%x, um->um_tab.b_actf->b_actf = 0x%x\n",
			bp, um->um_tab.b_actf->b_actf);
		panic("vastrategy");
		um->um_tab.b_actf->b_actl->b_forw = bp;
	}
	um->um_tab.b_actf->b_actl = bp;
	bp = um->um_tab.b_actf;
	dprintf("vastrategy: bp=%x actf=%x active=%d\n",
		bp, bp->b_actf, bp->b_active);
	if (bp->b_actf && bp->b_active == 0)
		(void) vastart(um);
	splx(s);
}

int	vablock = 16384;

unsigned
minvaph(bp)
	struct buf *bp;
{

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

/*ARGSUSED*/
vawrite(dev, uio)
	dev_t dev;
	struct uio *uio;
{

	if (VAUNIT(dev) > NVA)
		return (ENXIO);
	return (physio(vastrategy, &rvabuf[VAUNIT(dev)], dev, B_WRITE,
		    minvaph, uio));
}

vastart(um)
	register struct uba_ctlr *um;
{
	struct buf *bp;
	struct vadevice *vaaddr;
	register struct va_softc *sc;
	int unit;

	dprintf("vastart(%x), bp=%x\n", um, um->um_tab.b_actf->b_actf);
	if ((bp = um->um_tab.b_actf->b_actf) == NULL)
		return;
	unit = VAUNIT(bp->b_dev);
	sc = &va_softc[unit];
	sc->sc_tocnt = 0;
	while (sc->sc_iostate&VAS_PIO) {
		sc->sc_iostate |= VAS_WANT;
		sleep((caddr_t)&sc->sc_iostate, VAPRI);
	}
	sc->sc_iostate |= VAS_DMA;
	vaaddr = (struct vadevice *)um->um_addr;
	vaaddr->vacsl = 0;
	vaaddr->vawc = -(bp->b_bcount / 2);
	um->um_cmd = VA_DMAGO | VA_IENABLE;
	(void) ubago(vadinfo[unit]);
}

vadgo(um)
	register struct uba_ctlr *um;
{
	register struct vadevice *vaaddr = (struct vadevice *)um->um_addr;
	register struct buf *bp;

	bp = um->um_tab.b_actf;
	va_softc[VAUNIT(bp->b_actf->b_dev)].sc_tocnt = 0;
	bp->b_active++;
	vaaddr->vaba = um->um_ubinfo;
	vaaddr->vacsl = ((um->um_ubinfo >> 12) & 0x30) | um->um_cmd;
}

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

	switch (cmd) {

	case VGETSTATE:
		*(int *)data = sc->sc_state;
		break;

	case VSETSTATE:
		return (vacmd(dev, *(int *)data));
		break;

	default:
		return (ENOTTY);
	}
	return (0);
}

vacmd(dev, vcmd)
	dev_t dev;
	int vcmd;
{
	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
	int error = 0;
	int s, cmd;

	s = spl4();
	while (sc->sc_iostate&VAS_DMA) {
		sc->sc_iostate |= VAS_WANT;
		sleep((caddr_t)&sc->sc_iostate, VAPRI);
	}
	sc->sc_iostate |= VAS_PIO;
	sc->sc_tocnt = 0;
	cmd = 0;
	switch (vcmd) {

	case VPLOT:
		/* Must turn on plot AND autostep modes. */
		if (vadopio(dev, VAPLOT))
			error = EIO;
		cmd = VAAUTOSTEP;
		break;

	case VPRINT:
		cmd = VAPRINT;
		break;

	case VPRINTPLOT:
		cmd = VAPRINTPLOT;
		break;
	}
	sc->sc_state = (sc->sc_state & ~(VPLOT|VPRINT|VPRINTPLOT)) | vcmd;
	if (cmd && vadopio(dev, cmd))
		error = EIO;
	sc->sc_iostate &= ~VAS_PIO;
	if (sc->sc_iostate&VAS_WANT) {
		sc->sc_iostate &= ~VAS_WANT;
		wakeup((caddr_t)&sc->sc_iostate);
	}
	splx(s);
	return (error);
}

vadopio(dev, cmd)
	dev_t dev;
	int cmd;
{
	register struct vadevice *vaaddr =
	    (struct vadevice *)vaminfo[VAUNIT(dev)]->um_addr;
	register struct va_softc *sc = &va_softc[VAUNIT(dev)];

	sc->sc_info = 0;
	vaaddr->vacsh = cmd;
	while ((sc->sc_info&(VA_DONE|VA_ERROR)) == 0)
		sleep((caddr_t)&sc->sc_info, VAPRI);
	return (sc->sc_info&VA_ERROR);
}

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

	if (sc->sc_openf)
		timeout(vatimo, (caddr_t)dev, hz/2);
	if (++sc->sc_tocnt < 2)
		return;
	sc->sc_tocnt = 0;
	dprintf("vatimo: calling vaintr\n");
	vaintr(dev);
}

/*ARGSUSED*/
vaintr(dev)
	dev_t dev;
{
	register struct uba_ctlr *um;
	struct vadevice *vaaddr;
	struct buf *bp;
	register int unit = VAUNIT(dev), e;
	register struct va_softc *sc = &va_softc[unit];

	um = vaminfo[unit];
	vaaddr = (struct vadevice *)um->um_addr;
	e = vaaddr->vacsw;
	dprintf("vaintr: um=0x%x, e=0x%x, b_active %d\n",
		um, e, um->um_tab.b_actf->b_active);
	if ((e&(VA_DONE|VA_ERROR)) == 0)
		return;
	vaaddr->vacsl = 0;
	if ((e&VA_ERROR) && (e&VA_NPRTIMO))
		printf("va%d: npr timeout\n", unit);
	if (sc->sc_iostate&VAS_PIO) {
		sc->sc_info = e;
		wakeup((caddr_t)&sc->sc_info);
		return;
	}
	if (um->um_tab.b_actf->b_active) {
		bp = um->um_tab.b_actf->b_actf;
		if (e&VA_ERROR)
			bp->b_flags |= B_ERROR;
		if (sc->sc_state&VPRINTPLOT) {
			sc->sc_state = (sc->sc_state & ~VPRINTPLOT) | VPLOT;
			vaaddr->vacsh = VAAUTOSTEP;
			return;
		}
		ubadone(um);
		um->um_tab.b_actf->b_active = 0;
		um->um_tab.b_actf->b_actf = bp->b_forw;
		bp->b_active = 0;
		bp->b_errcnt = 0;
		bp->b_resid = 0;
		iodone(bp);
	}
	if (um->um_tab.b_actf->b_actf == 0) {
		sc->sc_iostate &= ~VAS_DMA;
		if (sc->sc_iostate&VAS_WANT) {
			sc->sc_iostate &= ~VAS_WANT;
			wakeup((caddr_t)&sc->sc_iostate);
		}
		return;
	}
	if (um->um_tab.b_actf->b_active == 0)
		vastart(um);
}

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_state = 0;
	if (sc->sc_iostate != VAS_IDLE)
		wakeup((caddr_t)&sc->sc_iostate);
	sc->sc_iostate = VAS_IDLE;
	vaaddr->vacsl = 0;
	vaaddr->vawc = 0;
}

vareset(uban)
	int uban;
{
	register int va11;
	register struct uba_ctlr *um;
	register struct vadevice *vaaddr;
	register struct va_softc *sc;

	for (va11 = 0; va11 < NVA; va11++, sc++) {
		if ((um = vaminfo[va11]) == 0 || um->um_ubanum != uban ||
		    um->um_alive == 0)
			continue;
		sc = &va_softc[um->um_ctlr];
		if (sc->sc_openf == 0)
			continue;
		printf(" va%d", va11);
		vaaddr = (struct vadevice *)um->um_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);
		sc->sc_iostate = VAS_IDLE;
		um->um_tab.b_actf->b_active = 0;
		um->um_tab.b_actf->b_actf = um->um_tab.b_actf->b_actl = 0;
		if (um->um_ubinfo) {
			printf("<%d>", (um->um_ubinfo >> 28) & 0xf);
			um->um_ubinfo = 0;
		}
		(void) vastart(um);
	}
}

vaselect()
{

	return (1);
}
#endif