xref: /csrg-svn/sys/vax/uba/va.c (revision 9361)
1*9361Smckusick /*	va.c	4.13.1.1	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"
153183Swnj #include "../h/ubareg.h"
163183Swnj #include "../h/ubavar.h"
1741Sbill #include "../h/vcmd.h"
1841Sbill 
19287Sbill unsigned minvaph();
2041Sbill 
2141Sbill #define	VAPRI	(PZERO-1)
2241Sbill 
233183Swnj struct	vadevice {
243183Swnj 	u_short	vaba;			/* buffer address */
253183Swnj 	short	vawc;			/* word count (2's complement) */
2641Sbill 	union {
273183Swnj 		short	Vacsw;		/* control status as word */
283183Swnj 		struct {		/* control status as bytes */
29287Sbill 			char Vacsl;
30287Sbill 			char Vacsh;
31287Sbill 		} vacsr;
32287Sbill 	} vacs;
333183Swnj 	short	vadata;			/* programmed i/o data buffer */
3441Sbill };
3541Sbill 
36287Sbill #define	vacsw	vacs.Vacsw
37287Sbill #define	vacsh	vacs.vacsr.Vacsh
38287Sbill #define	vacsl	vacs.vacsr.Vacsl
39287Sbill 
40287Sbill /* vacsw bits */
413183Swnj #define	VA_ERROR	0100000		/* some error has occurred */
423183Swnj #define	VA_NPRTIMO	0001000		/* DMA timeout error */
433183Swnj #define	VA_NOTREADY	0000400		/* something besides NPRTIMO */
443183Swnj #define	VA_DONE		0000200
453183Swnj #define	VA_IENABLE	0000100		/* interrupt enable */
463183Swnj #define	VA_SUPPLIESLOW	0000004
473183Swnj #define	VA_BOTOFFORM	0000002
483183Swnj #define	VA_BYTEREVERSE	0000001		/* reverse byte order in words */
4941Sbill 
50287Sbill /* vacsh command bytes */
513183Swnj #define	VAPLOT		0000340
523183Swnj #define	VAPRINT		0000100
533183Swnj #define	VAPRINTPLOT	0000160
543183Swnj #define	VAAUTOSTEP	0000244
553183Swnj #define	VANOAUTOSTEP	0000045
563183Swnj #define	VAFORMFEED	0000263
573183Swnj #define	VASLEW		0000265
583183Swnj #define	VASTEP		0000064
5941Sbill 
603183Swnj struct va_softc {
61*9361Smckusick 	char	sc_openf;
62*9361Smckusick 	char	sc_busy;
63*9361Smckusick 	int	sc_state;
64*9361Smckusick 	int	sc_wc;
65*9361Smckusick 	struct	buf *sc_bp;
66*9361Smckusick 	int	sc_ubinfo;
673183Swnj } va_softc[NVA];
6841Sbill 
693183Swnj #define	VAUNIT(dev)	(minor(dev))
703183Swnj 
713183Swnj struct	buf rvabuf[NVA];
723183Swnj 
73*9361Smckusick int	vaprobe(), vaattach();
743183Swnj struct	uba_device *vadinfo[NVA];
753183Swnj u_short	vastd[] = { 0764000, 0 };
763183Swnj struct	uba_driver vadriver =
77*9361Smckusick     { vaprobe, 0, vaattach, 0, vastd, "va", vadinfo };
783183Swnj 
793183Swnj vaprobe(reg)
803183Swnj 	caddr_t reg;
8141Sbill {
823183Swnj 	register int br, cvec;		/* value-result */
833183Swnj 	register struct vadevice *vaaddr = (struct vadevice *)reg;
8441Sbill 
859267Smckusick #ifdef lint
869267Smckusick 	br = 0; cvec = br; br = cvec;
879267Smckusick 	vaintr(0);
889267Smckusick #endif
893183Swnj 	vaaddr->vacsl = VA_IENABLE;
903183Swnj 	vaaddr->vaba = 0;
913183Swnj 	vaaddr->vacsh = VAPLOT;
92*9361Smckusick 	vaaddr->vacsl = 0;
933183Swnj 	vaaddr->vawc = -1;
94*9361Smckusick 	DELAY(100000);
953183Swnj 	vaaddr->vacsl = 0;
963183Swnj }
973183Swnj 
983183Swnj /*ARGSUSED*/
993183Swnj vaattach(ui)
1003183Swnj 	struct uba_device *ui;
1013183Swnj {
1023183Swnj 
1033183Swnj }
1043183Swnj 
1053183Swnj vaopen(dev)
1063183Swnj 	dev_t dev;
1073183Swnj {
1083183Swnj 	register struct va_softc *sc;
1093183Swnj 	register struct vadevice *vaaddr;
1103183Swnj 	register struct uba_device *ui;
1113183Swnj 
112*9361Smckusick 	if (VAUNIT(dev) >= NVA || (sc = &va_softc[minor(dev)])->sc_openf ||
113*9361Smckusick 	    (ui = vadinfo[VAUNIT(dev)]) == 0 || ui->ui_alive == 0) {
11441Sbill 		u.u_error = ENXIO;
11541Sbill 		return;
11641Sbill 	}
1173183Swnj 	vaaddr = (struct vadevice *)ui->ui_addr;
1183183Swnj 	sc->sc_openf = 1;
1193183Swnj 	vaaddr->vawc = 0;
120*9361Smckusick 	sc->sc_wc = 0;
1213183Swnj 	sc->sc_state = 0;
1223183Swnj 	vaaddr->vacsl = VA_IENABLE;
1233183Swnj 	vatimo(dev);
1243183Swnj 	vacmd(dev, VPRINT);
12541Sbill 	if (u.u_error)
1263183Swnj 		vaclose(dev);
12741Sbill }
12841Sbill 
12941Sbill vastrategy(bp)
13041Sbill 	register struct buf *bp;
13141Sbill {
132*9361Smckusick 	register int e;
133*9361Smckusick 	register struct va_softc *sc = &va_softc[VAUNIT(bp->b_dev)];
134*9361Smckusick 	register struct uba_device *ui = vadinfo[VAUNIT(bp->b_dev)];
135*9361Smckusick 	register struct vadevice *vaaddr = (struct vadevice *)ui->ui_addr;
13641Sbill 
137*9361Smckusick 	(void) spl4();
138*9361Smckusick 	while (sc->sc_busy)
139*9361Smckusick 		sleep((caddr_t)sc, VAPRI);
140*9361Smckusick 	sc->sc_busy = 1;
141*9361Smckusick 	sc->sc_bp = bp;
142*9361Smckusick 	sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP);
143*9361Smckusick 	if (e = vawait(bp->b_dev))
144*9361Smckusick 		goto brkout;
145*9361Smckusick 	sc->sc_wc = -(bp->b_bcount/2);
146*9361Smckusick 	vastart(bp->b_dev);
147*9361Smckusick 	e = vawait(bp->b_dev);
148*9361Smckusick 	sc->sc_wc = 0;
149*9361Smckusick 	if (sc->sc_state & VPRINTPLOT) {
150*9361Smckusick 		sc->sc_state = (sc->sc_state & ~VPRINTPLOT) | VPLOT;
151*9361Smckusick 		vaaddr->vacsh = VAAUTOSTEP;
152*9361Smckusick 		e |= vawait(bp->b_dev);
15341Sbill 	}
154*9361Smckusick 	(void) spl0();
155*9361Smckusick brkout:
156*9361Smckusick 	ubarelse(ui->ui_ubanum, &sc->sc_ubinfo);
157*9361Smckusick 	sc->sc_bp = 0;
158*9361Smckusick 	sc->sc_busy = 0;
159*9361Smckusick 	iodone(bp);
160*9361Smckusick 	if (e)
161*9361Smckusick 		u.u_error = EIO;
162*9361Smckusick 	wakeup((caddr_t)sc);
16341Sbill }
16441Sbill 
16541Sbill int	vablock = 16384;
16641Sbill 
16741Sbill unsigned
16841Sbill minvaph(bp)
1693183Swnj 	struct buf *bp;
17041Sbill {
1713183Swnj 
17241Sbill 	if (bp->b_bcount > vablock)
17341Sbill 		bp->b_bcount = vablock;
17441Sbill }
17541Sbill 
17641Sbill /*ARGSUSED*/
17741Sbill vawrite(dev)
1783183Swnj 	dev_t dev;
17941Sbill {
1809267Smckusick 
1813183Swnj 	physio(vastrategy, &rvabuf[VAUNIT(dev)], dev, B_WRITE, minvaph);
18241Sbill }
18341Sbill 
184*9361Smckusick vawait(dev)
185*9361Smckusick 	dev_t dev;
18641Sbill {
187*9361Smckusick 	register struct vadevice *vaaddr =
188*9361Smckusick 	    (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr;
189*9361Smckusick 	register int e;
19041Sbill 
191*9361Smckusick 	while (((e = vaaddr->vacsw) & (VA_DONE|VA_ERROR)) == 0)
192*9361Smckusick 		sleep((caddr_t)&va_softc[VAUNIT(dev)], VAPRI);
193*9361Smckusick 	if (e & VA_NPRTIMO)
194*9361Smckusick 		printf("va%d: npr timeout\n", VAUNIT(dev));
195*9361Smckusick 	return (e & VA_ERROR);
19641Sbill }
19741Sbill 
198*9361Smckusick vastart(dev)
199*9361Smckusick 	dev_t;
20041Sbill {
201*9361Smckusick 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
202*9361Smckusick 	register struct vadevice *vaaddr =
203*9361Smckusick 	    (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr;
2043183Swnj 
205*9361Smckusick 	if (sc->sc_wc == 0)
206*9361Smckusick 		return;
207*9361Smckusick 	vaaddr->vaba = sc->sc_ubinfo;
208*9361Smckusick 	vaaddr->vacsl = (sc->sc_ubinfo >> 12) & 0x30;
209*9361Smckusick 	vaaddr->vawc = sc->sc_wc;
21041Sbill }
21141Sbill 
21241Sbill /*ARGSUSED*/
21341Sbill vaioctl(dev, cmd, addr, flag)
21441Sbill 	register caddr_t addr;
21541Sbill {
21641Sbill 	register int vcmd;
2173183Swnj 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
21841Sbill 
21941Sbill 	switch (cmd) {
22041Sbill 
22141Sbill 	case VGETSTATE:
2223183Swnj 		(void) suword(addr, sc->sc_state);
22341Sbill 		return;
22441Sbill 
22541Sbill 	case VSETSTATE:
22641Sbill 		vcmd = fuword(addr);
22741Sbill 		if (vcmd == -1) {
22841Sbill 			u.u_error = EFAULT;
22941Sbill 			return;
23041Sbill 		}
2313183Swnj 		vacmd(dev, vcmd);
23241Sbill 		return;
23341Sbill 
23441Sbill 	default:
2353183Swnj 		u.u_error = ENOTTY;
23641Sbill 		return;
23741Sbill 	}
23841Sbill }
23941Sbill 
2403183Swnj vacmd(dev, vcmd)
2413183Swnj 	dev_t dev;
2423183Swnj 	int vcmd;
24341Sbill {
2443183Swnj 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
245*9361Smckusick 	register struct vadevice *vaaddr =
246*9361Smckusick 	    (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr;
2473183Swnj 
248*9361Smckusick 	(void) spl4();
249*9361Smckusick 	(void) vawait(dev);
25041Sbill 	switch (vcmd) {
25141Sbill 
25241Sbill 	case VPLOT:
25341Sbill 		/* Must turn on plot AND autostep modes. */
254*9361Smckusick 		vaaddr->vacsh = VAPLOT;
255*9361Smckusick 		if (vawait(dev))
25641Sbill 			u.u_error = EIO;
257*9361Smckusick 		vaaddr->vacsh = VAAUTOSTEP;
25841Sbill 		break;
25941Sbill 
26041Sbill 	case VPRINT:
261*9361Smckusick 		vaaddr->vacsh = VAPRINT;
26241Sbill 		break;
26341Sbill 
26441Sbill 	case VPRINTPLOT:
265*9361Smckusick 		vaaddr->vacsh = VAPRINTPLOT;
26641Sbill 		break;
26741Sbill 	}
2683183Swnj 	sc->sc_state = (sc->sc_state & ~(VPLOT|VPRINT|VPRINTPLOT)) | vcmd;
269*9361Smckusick 	if (vawait(dev))
27041Sbill 		u.u_error = EIO;
271*9361Smckusick 	(void) spl0();
27241Sbill }
27341Sbill 
2743183Swnj vatimo(dev)
2753183Swnj 	dev_t dev;
27641Sbill {
2773183Swnj 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
2783183Swnj 
2793183Swnj 	if (sc->sc_openf)
280*9361Smckusick 		timeout(vatimo, (caddr_t)dev, hz/10);
2819267Smckusick 	vaintr(dev);
28241Sbill }
28341Sbill 
28441Sbill /*ARGSUSED*/
28541Sbill vaintr(dev)
2863183Swnj 	dev_t dev;
28741Sbill {
288*9361Smckusick 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
2893183Swnj 
290*9361Smckusick 	wakeup((caddr_t)sc);
29141Sbill }
29241Sbill 
2933183Swnj vaclose(dev)
2943183Swnj 	dev_t dev;
29541Sbill {
2963183Swnj 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
2973183Swnj 	register struct vadevice *vaaddr =
2983183Swnj 	    (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr;
29941Sbill 
3003183Swnj 	sc->sc_openf = 0;
301*9361Smckusick 	sc->sc_busy = 0;
3023183Swnj 	sc->sc_state = 0;
303*9361Smckusick 	sc->sc_ubinfo = 0;
3043183Swnj 	vaaddr->vacsl = 0;
30541Sbill }
306287Sbill 
3073183Swnj vareset(uban)
3083183Swnj 	int uban;
309287Sbill {
3103183Swnj 	register int va11;
311*9361Smckusick 	register struct uba_device *ui;
312*9361Smckusick 	register struct va_softc *sc = va_softc;
3133183Swnj 	register struct vadevice *vaaddr;
314287Sbill 
3153183Swnj 	for (va11 = 0; va11 < NVA; va11++, sc++) {
316*9361Smckusick 		if ((ui = vadinfo[va11]) == 0 || ui->ui_alive == 0 ||
317*9361Smckusick 		    ui->ui_ubanum != uban || sc->sc_openf == 0)
3183183Swnj 			continue;
3193183Swnj 		printf(" va%d", va11);
320*9361Smckusick 		vaaddr = (struct vadevice *)ui->ui_addr;
3213183Swnj 		vaaddr->vacsl = VA_IENABLE;
3223183Swnj 		if (sc->sc_state & VPLOT) {
3233183Swnj 			vaaddr->vacsh = VAPLOT;
3243183Swnj 			DELAY(10000);
3253183Swnj 			vaaddr->vacsh = VAAUTOSTEP;
3263183Swnj 		} else if (sc->sc_state & VPRINTPLOT)
3273183Swnj 			vaaddr->vacsh = VPRINTPLOT;
3283183Swnj 		else
3293183Swnj 			vaaddr->vacsh = VAPRINTPLOT;
330287Sbill 		DELAY(10000);
331*9361Smckusick 		if (sc->sc_busy == 0)
332*9361Smckusick 			continue;
333*9361Smckusick 		if (sc->sc_ubinfo) {
334*9361Smckusick 			printf("<%d>", (sc->sc_ubinfo>>28)&0xf);
335*9361Smckusick 			ubarelse(ui->ui_ubanum, &sc->sc_ubinfo);
3363183Swnj 		}
337*9361Smckusick 		sc->sc_ubinfo = ubasetup(ui->ui_ubanum, sc->sc_bp, UBA_NEEDBDP);
338*9361Smckusick 		sc->sc_wc = -(sc->sc_bp->b_bcount/2);
339*9361Smckusick 		vastart(sc->sc_bp->b_dev);
340287Sbill 	}
341287Sbill }
3426432Ssam 
3436432Ssam vaselect()
3446432Ssam {
3456432Ssam 	return (1);
3466432Ssam }
3471564Sbill #endif
348