xref: /csrg-svn/sys/vax/uba/va.c (revision 9363)
1*9363Smckusick /*	va.c	4.13.1.3	82/11/27	*/
241Sbill 
31938Swnj #include "va.h"
41564Sbill #if NVA > 0
51564Sbill /*
63183Swnj  * Varian printer plotter
71564Sbill  */
841Sbill #include "../h/param.h"
941Sbill #include "../h/dir.h"
1041Sbill #include "../h/user.h"
1141Sbill #include "../h/buf.h"
1241Sbill #include "../h/systm.h"
1341Sbill #include "../h/map.h"
1441Sbill #include "../h/pte.h"
1541Sbill #include "../h/vcmd.h"
169362Smckusick #include "../h/uio.h"
1741Sbill 
18*9363Smckusick #include "../vaxuba/ubareg.h"
19*9363Smckusick #include "../vaxuba/ubavar.h"
20*9363Smckusick 
21287Sbill unsigned minvaph();
2241Sbill 
2341Sbill #define	VAPRI	(PZERO-1)
2441Sbill 
253183Swnj struct	vadevice {
263183Swnj 	u_short	vaba;			/* buffer address */
273183Swnj 	short	vawc;			/* word count (2's complement) */
2841Sbill 	union {
293183Swnj 		short	Vacsw;		/* control status as word */
303183Swnj 		struct {		/* control status as bytes */
31287Sbill 			char Vacsl;
32287Sbill 			char Vacsh;
33287Sbill 		} vacsr;
34287Sbill 	} vacs;
353183Swnj 	short	vadata;			/* programmed i/o data buffer */
3641Sbill };
3741Sbill 
38287Sbill #define	vacsw	vacs.Vacsw
39287Sbill #define	vacsh	vacs.vacsr.Vacsh
40287Sbill #define	vacsl	vacs.vacsr.Vacsl
41287Sbill 
42287Sbill /* vacsw bits */
433183Swnj #define	VA_ERROR	0100000		/* some error has occurred */
443183Swnj #define	VA_NPRTIMO	0001000		/* DMA timeout error */
453183Swnj #define	VA_NOTREADY	0000400		/* something besides NPRTIMO */
463183Swnj #define	VA_DONE		0000200
473183Swnj #define	VA_IENABLE	0000100		/* interrupt enable */
489362Smckusick #define	VA_DMAGO	0000010		/* DMA go bit */
493183Swnj #define	VA_SUPPLIESLOW	0000004
503183Swnj #define	VA_BOTOFFORM	0000002
513183Swnj #define	VA_BYTEREVERSE	0000001		/* reverse byte order in words */
5241Sbill 
53287Sbill /* vacsh command bytes */
543183Swnj #define	VAPLOT		0000340
553183Swnj #define	VAPRINT		0000100
563183Swnj #define	VAPRINTPLOT	0000160
573183Swnj #define	VAAUTOSTEP	0000244
583183Swnj #define	VANOAUTOSTEP	0000045
593183Swnj #define	VAFORMFEED	0000263
603183Swnj #define	VASLEW		0000265
613183Swnj #define	VASTEP		0000064
6241Sbill 
633183Swnj struct va_softc {
649361Smckusick 	char	sc_openf;
659361Smckusick 	char	sc_busy;
669361Smckusick 	int	sc_state;
679361Smckusick 	int	sc_wc;
689361Smckusick 	struct	buf *sc_bp;
699361Smckusick 	int	sc_ubinfo;
703183Swnj } va_softc[NVA];
7141Sbill 
723183Swnj #define	VAUNIT(dev)	(minor(dev))
733183Swnj 
743183Swnj struct	buf rvabuf[NVA];
753183Swnj 
769361Smckusick int	vaprobe(), vaattach();
773183Swnj struct	uba_device *vadinfo[NVA];
783183Swnj u_short	vastd[] = { 0764000, 0 };
793183Swnj struct	uba_driver vadriver =
809361Smckusick     { vaprobe, 0, vaattach, 0, vastd, "va", vadinfo };
813183Swnj 
823183Swnj vaprobe(reg)
833183Swnj 	caddr_t reg;
8441Sbill {
853183Swnj 	register int br, cvec;		/* value-result */
863183Swnj 	register struct vadevice *vaaddr = (struct vadevice *)reg;
8741Sbill 
889267Smckusick #ifdef lint
899267Smckusick 	br = 0; cvec = br; br = cvec;
909267Smckusick 	vaintr(0);
919267Smckusick #endif
923183Swnj 	vaaddr->vacsl = VA_IENABLE;
933183Swnj 	vaaddr->vaba = 0;
943183Swnj 	vaaddr->vacsh = VAPLOT;
959362Smckusick #ifndef VARIANGOBIT
969361Smckusick 	vaaddr->vacsl = 0;
979362Smckusick #endif
983183Swnj 	vaaddr->vawc = -1;
999361Smckusick 	DELAY(100000);
1003183Swnj 	vaaddr->vacsl = 0;
1019362Smckusick 	return (sizeof (struct vadevice));
1023183Swnj }
1033183Swnj 
1043183Swnj /*ARGSUSED*/
1053183Swnj vaattach(ui)
1063183Swnj 	struct uba_device *ui;
1073183Swnj {
1083183Swnj 
1093183Swnj }
1103183Swnj 
1113183Swnj vaopen(dev)
1123183Swnj 	dev_t dev;
1133183Swnj {
1143183Swnj 	register struct va_softc *sc;
1153183Swnj 	register struct vadevice *vaaddr;
1163183Swnj 	register struct uba_device *ui;
117*9363Smckusick 	int error;
1183183Swnj 
1199361Smckusick 	if (VAUNIT(dev) >= NVA || (sc = &va_softc[minor(dev)])->sc_openf ||
120*9363Smckusick 	    (ui = vadinfo[VAUNIT(dev)]) == 0 || ui->ui_alive == 0)
121*9363Smckusick 		return (ENXIO);
1223183Swnj 	vaaddr = (struct vadevice *)ui->ui_addr;
1233183Swnj 	sc->sc_openf = 1;
1243183Swnj 	vaaddr->vawc = 0;
1259361Smckusick 	sc->sc_wc = 0;
1263183Swnj 	sc->sc_state = 0;
1273183Swnj 	vaaddr->vacsl = VA_IENABLE;
1283183Swnj 	vatimo(dev);
129*9363Smckusick 	error = vacmd(dev, VPRINT);
130*9363Smckusick 	if (error)
1313183Swnj 		vaclose(dev);
132*9363Smckusick 	return (error);
13341Sbill }
13441Sbill 
13541Sbill vastrategy(bp)
13641Sbill 	register struct buf *bp;
13741Sbill {
1389361Smckusick 	register int e;
1399361Smckusick 	register struct va_softc *sc = &va_softc[VAUNIT(bp->b_dev)];
1409361Smckusick 	register struct uba_device *ui = vadinfo[VAUNIT(bp->b_dev)];
1419361Smckusick 	register struct vadevice *vaaddr = (struct vadevice *)ui->ui_addr;
14241Sbill 
1439361Smckusick 	(void) spl4();
1449361Smckusick 	while (sc->sc_busy)
1459361Smckusick 		sleep((caddr_t)sc, VAPRI);
1469361Smckusick 	sc->sc_busy = 1;
1479361Smckusick 	sc->sc_bp = bp;
1489361Smckusick 	sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP);
1499361Smckusick 	if (e = vawait(bp->b_dev))
1509361Smckusick 		goto brkout;
1519361Smckusick 	sc->sc_wc = -(bp->b_bcount/2);
1529361Smckusick 	vastart(bp->b_dev);
1539361Smckusick 	e = vawait(bp->b_dev);
1549361Smckusick 	sc->sc_wc = 0;
1559361Smckusick 	if (sc->sc_state & VPRINTPLOT) {
1569361Smckusick 		sc->sc_state = (sc->sc_state & ~VPRINTPLOT) | VPLOT;
1579361Smckusick 		vaaddr->vacsh = VAAUTOSTEP;
1589361Smckusick 		e |= vawait(bp->b_dev);
15941Sbill 	}
1609361Smckusick 	(void) spl0();
1619361Smckusick brkout:
1629361Smckusick 	ubarelse(ui->ui_ubanum, &sc->sc_ubinfo);
1639361Smckusick 	sc->sc_bp = 0;
1649361Smckusick 	sc->sc_busy = 0;
165*9363Smckusick 	if (e)
166*9363Smckusick 		bp->b_flags |= B_ERROR;
1679361Smckusick 	iodone(bp);
1689361Smckusick 	wakeup((caddr_t)sc);
16941Sbill }
17041Sbill 
17141Sbill int	vablock = 16384;
17241Sbill 
17341Sbill unsigned
17441Sbill minvaph(bp)
1753183Swnj 	struct buf *bp;
17641Sbill {
1773183Swnj 
17841Sbill 	if (bp->b_bcount > vablock)
17941Sbill 		bp->b_bcount = vablock;
18041Sbill }
18141Sbill 
18241Sbill /*ARGSUSED*/
1839362Smckusick vawrite(dev, uio)
1843183Swnj 	dev_t dev;
1859362Smckusick 	struct uio *uio;
18641Sbill {
1879267Smckusick 
1889362Smckusick 	if (VAUNIT(dev) > NVA)
189*9363Smckusick 		return (ENXIO);
190*9363Smckusick 	return (physio(vastrategy, &rvabuf[VAUNIT(dev)], dev, B_WRITE,
191*9363Smckusick 		    minvaph, uio));
19241Sbill }
19341Sbill 
1949361Smckusick vawait(dev)
1959361Smckusick 	dev_t dev;
19641Sbill {
1979361Smckusick 	register struct vadevice *vaaddr =
1989361Smckusick 	    (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr;
1999361Smckusick 	register int e;
20041Sbill 
2019361Smckusick 	while (((e = vaaddr->vacsw) & (VA_DONE|VA_ERROR)) == 0)
2029361Smckusick 		sleep((caddr_t)&va_softc[VAUNIT(dev)], VAPRI);
2039361Smckusick 	if (e & VA_NPRTIMO)
2049361Smckusick 		printf("va%d: npr timeout\n", VAUNIT(dev));
2059361Smckusick 	return (e & VA_ERROR);
20641Sbill }
20741Sbill 
2089361Smckusick vastart(dev)
2099361Smckusick 	dev_t;
21041Sbill {
2119361Smckusick 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
2129361Smckusick 	register struct vadevice *vaaddr =
2139361Smckusick 	    (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr;
2143183Swnj 
2159361Smckusick 	if (sc->sc_wc == 0)
2169361Smckusick 		return;
2179361Smckusick 	vaaddr->vaba = sc->sc_ubinfo;
2189362Smckusick #ifndef VARIANGOBIT
2199361Smckusick 	vaaddr->vacsl = (sc->sc_ubinfo >> 12) & 0x30;
2209362Smckusick #else
2219362Smckusick 	vaaddr->vacsl = (sc->sc_ubinfo >> 12) & 0x30 | VA_IENABLE | VA_DMAGO;
2229362Smckusick #endif
2239361Smckusick 	vaaddr->vawc = sc->sc_wc;
22441Sbill }
22541Sbill 
22641Sbill /*ARGSUSED*/
2279362Smckusick vaioctl(dev, cmd, data, flag)
2289362Smckusick 	register caddr_t data;
22941Sbill {
23041Sbill 	register int vcmd;
2313183Swnj 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
23241Sbill 
23341Sbill 	switch (cmd) {
23441Sbill 
23541Sbill 	case VGETSTATE:
2369362Smckusick 		*(int *)data = sc->sc_state;
237*9363Smckusick 		break;
23841Sbill 
23941Sbill 	case VSETSTATE:
240*9363Smckusick 		return (vacmd(dev, *(int *)data));
241*9363Smckusick 		break;
24241Sbill 
24341Sbill 	default:
244*9363Smckusick 		return (ENOTTY);
24541Sbill 	}
246*9363Smckusick 	return (0);
24741Sbill }
24841Sbill 
2493183Swnj vacmd(dev, vcmd)
2503183Swnj 	dev_t dev;
2513183Swnj 	int vcmd;
25241Sbill {
2533183Swnj 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
2549361Smckusick 	register struct vadevice *vaaddr =
2559361Smckusick 	    (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr;
256*9363Smckusick 	int error = 0;
2573183Swnj 
2589361Smckusick 	(void) spl4();
2599361Smckusick 	(void) vawait(dev);
26041Sbill 	switch (vcmd) {
26141Sbill 
26241Sbill 	case VPLOT:
26341Sbill 		/* Must turn on plot AND autostep modes. */
2649361Smckusick 		vaaddr->vacsh = VAPLOT;
2659361Smckusick 		if (vawait(dev))
266*9363Smckusick 			error = EIO;
2679361Smckusick 		vaaddr->vacsh = VAAUTOSTEP;
26841Sbill 		break;
26941Sbill 
27041Sbill 	case VPRINT:
2719361Smckusick 		vaaddr->vacsh = VAPRINT;
27241Sbill 		break;
27341Sbill 
27441Sbill 	case VPRINTPLOT:
2759361Smckusick 		vaaddr->vacsh = VAPRINTPLOT;
27641Sbill 		break;
27741Sbill 	}
2783183Swnj 	sc->sc_state = (sc->sc_state & ~(VPLOT|VPRINT|VPRINTPLOT)) | vcmd;
2799361Smckusick 	if (vawait(dev))
280*9363Smckusick 		error = EIO;
2819361Smckusick 	(void) spl0();
282*9363Smckusick 	return (error);
28341Sbill }
28441Sbill 
2853183Swnj vatimo(dev)
2863183Swnj 	dev_t dev;
28741Sbill {
2883183Swnj 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
2893183Swnj 
2903183Swnj 	if (sc->sc_openf)
2919361Smckusick 		timeout(vatimo, (caddr_t)dev, hz/10);
2929267Smckusick 	vaintr(dev);
29341Sbill }
29441Sbill 
29541Sbill /*ARGSUSED*/
29641Sbill vaintr(dev)
2973183Swnj 	dev_t dev;
29841Sbill {
2999361Smckusick 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
3003183Swnj 
3019361Smckusick 	wakeup((caddr_t)sc);
30241Sbill }
30341Sbill 
3043183Swnj vaclose(dev)
3053183Swnj 	dev_t dev;
30641Sbill {
3073183Swnj 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
3083183Swnj 	register struct vadevice *vaaddr =
3093183Swnj 	    (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr;
31041Sbill 
3113183Swnj 	sc->sc_openf = 0;
3129361Smckusick 	sc->sc_busy = 0;
3133183Swnj 	sc->sc_state = 0;
3149361Smckusick 	sc->sc_ubinfo = 0;
3153183Swnj 	vaaddr->vacsl = 0;
31641Sbill }
317287Sbill 
3183183Swnj vareset(uban)
3193183Swnj 	int uban;
320287Sbill {
3213183Swnj 	register int va11;
3229361Smckusick 	register struct uba_device *ui;
3239361Smckusick 	register struct va_softc *sc = va_softc;
3243183Swnj 	register struct vadevice *vaaddr;
325287Sbill 
3263183Swnj 	for (va11 = 0; va11 < NVA; va11++, sc++) {
3279361Smckusick 		if ((ui = vadinfo[va11]) == 0 || ui->ui_alive == 0 ||
3289361Smckusick 		    ui->ui_ubanum != uban || sc->sc_openf == 0)
3293183Swnj 			continue;
3303183Swnj 		printf(" va%d", va11);
3319361Smckusick 		vaaddr = (struct vadevice *)ui->ui_addr;
3323183Swnj 		vaaddr->vacsl = VA_IENABLE;
3333183Swnj 		if (sc->sc_state & VPLOT) {
3343183Swnj 			vaaddr->vacsh = VAPLOT;
3353183Swnj 			DELAY(10000);
3363183Swnj 			vaaddr->vacsh = VAAUTOSTEP;
3373183Swnj 		} else if (sc->sc_state & VPRINTPLOT)
3383183Swnj 			vaaddr->vacsh = VPRINTPLOT;
3393183Swnj 		else
3403183Swnj 			vaaddr->vacsh = VAPRINTPLOT;
341287Sbill 		DELAY(10000);
3429361Smckusick 		if (sc->sc_busy == 0)
3439361Smckusick 			continue;
3449361Smckusick 		sc->sc_ubinfo = ubasetup(ui->ui_ubanum, sc->sc_bp, UBA_NEEDBDP);
3459361Smckusick 		sc->sc_wc = -(sc->sc_bp->b_bcount/2);
3469361Smckusick 		vastart(sc->sc_bp->b_dev);
347287Sbill 	}
348287Sbill }
3496432Ssam 
3506432Ssam vaselect()
3516432Ssam {
352*9363Smckusick 
3536432Ssam 	return (1);
3546432Ssam }
3551564Sbill #endif
356