xref: /csrg-svn/sys/vax/uba/va.c (revision 3183)
1*3183Swnj /*	va.c	4.9	81/03/10	*/
241Sbill 
31938Swnj #include "va.h"
41564Sbill #if NVA > 0
51564Sbill /*
6*3183Swnj  * 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"
15*3183Swnj #include "../h/ubareg.h"
16*3183Swnj #include "../h/ubavar.h"
1741Sbill #include "../h/vcmd.h"
1841Sbill 
19287Sbill unsigned minvaph();
2041Sbill 
2141Sbill #define	VAPRI	(PZERO-1)
2241Sbill 
23*3183Swnj struct	vadevice {
24*3183Swnj 	u_short	vaba;			/* buffer address */
25*3183Swnj 	short	vawc;			/* word count (2's complement) */
2641Sbill 	union {
27*3183Swnj 		short	Vacsw;		/* control status as word */
28*3183Swnj 		struct {		/* control status as bytes */
29287Sbill 			char Vacsl;
30287Sbill 			char Vacsh;
31287Sbill 		} vacsr;
32287Sbill 	} vacs;
33*3183Swnj 	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 */
41*3183Swnj #define	VA_ERROR	0100000		/* some error has occurred */
42*3183Swnj #define	VA_NPRTIMO	0001000		/* DMA timeout error */
43*3183Swnj #define	VA_NOTREADY	0000400		/* something besides NPRTIMO */
44*3183Swnj #define	VA_DONE		0000200
45*3183Swnj #define	VA_IENABLE	0000100		/* interrupt enable */
46*3183Swnj #define	VA_SUPPLIESLOW	0000004
47*3183Swnj #define	VA_BOTOFFORM	0000002
48*3183Swnj #define	VA_BYTEREVERSE	0000001		/* reverse byte order in words */
4941Sbill 
50287Sbill /* vacsh command bytes */
51*3183Swnj #define	VAPLOT		0000340
52*3183Swnj #define	VAPRINT		0000100
53*3183Swnj #define	VAPRINTPLOT	0000160
54*3183Swnj #define	VAAUTOSTEP	0000244
55*3183Swnj #define	VANOAUTOSTEP	0000045
56*3183Swnj #define	VAFORMFEED	0000263
57*3183Swnj #define	VASLEW		0000265
58*3183Swnj #define	VASTEP		0000064
5941Sbill 
60*3183Swnj struct va_softc {
61*3183Swnj 	char	sc_openf;
62*3183Swnj 	char	sc_busy;
63*3183Swnj 	int	sc_state;
64*3183Swnj 	int	sc_wc;
65*3183Swnj 	struct	buf *sc_bp;
66*3183Swnj 	int	sc_ubinfo;
67*3183Swnj } va_softc[NVA];
6841Sbill 
69*3183Swnj struct	uba_device *vadinfo[NVA];
7041Sbill 
71*3183Swnj #define	VAUNIT(dev)	(minor(dev))
72*3183Swnj 
73*3183Swnj struct	buf rvabuf[NVA];
74*3183Swnj 
75*3183Swnj int	vaprobe(), vaattach();
76*3183Swnj struct	uba_device *vadinfo[NVA];
77*3183Swnj u_short	vastd[] = { 0764000, 0 };
78*3183Swnj struct	uba_driver vadriver =
79*3183Swnj     { vaprobe, 0, vaattach, 0, vastd, "va", vadinfo };
80*3183Swnj 
81*3183Swnj vaprobe(reg)
82*3183Swnj 	caddr_t reg;
8341Sbill {
84*3183Swnj 	register int br, cvec;		/* value-result */
85*3183Swnj 	register struct vadevice *vaaddr = (struct vadevice *)reg;
8641Sbill 
87*3183Swnj 	vaaddr->vacsl = VA_IENABLE;
88*3183Swnj 	vaaddr->vaba = 0;
89*3183Swnj 	vaaddr->vacsh = VAPLOT;
90*3183Swnj 	vaaddr->vacsl = 0;
91*3183Swnj 	vaaddr->vawc = -1;
92*3183Swnj 	DELAY(10000);
93*3183Swnj 	vaaddr->vacsl = 0;
94*3183Swnj }
95*3183Swnj 
96*3183Swnj /*ARGSUSED*/
97*3183Swnj vaattach(ui)
98*3183Swnj 	struct uba_device *ui;
99*3183Swnj {
100*3183Swnj 
101*3183Swnj }
102*3183Swnj 
103*3183Swnj vaopen(dev)
104*3183Swnj 	dev_t dev;
105*3183Swnj {
106*3183Swnj 	register struct va_softc *sc;
107*3183Swnj 	register struct vadevice *vaaddr;
108*3183Swnj 	register struct uba_device *ui;
109*3183Swnj 
110*3183Swnj 	if (VAUNIT(dev) >= NVA || (sc = &va_softc[minor(dev)])->sc_openf ||
111*3183Swnj 	    (ui = vadinfo[VAUNIT(dev)]) == 0 || ui->ui_alive == 0) {
11241Sbill 		u.u_error = ENXIO;
11341Sbill 		return;
11441Sbill 	}
115*3183Swnj 	vaaddr = (struct vadevice *)ui->ui_addr;
116*3183Swnj 	sc->sc_openf = 1;
117*3183Swnj 	vaaddr->vawc = 0;
118*3183Swnj 	sc->sc_wc = 0;
119*3183Swnj 	sc->sc_state = 0;
120*3183Swnj 	vaaddr->vacsl = VA_IENABLE;
121*3183Swnj 	vatimo(dev);
122*3183Swnj 	vacmd(dev, VPRINT);
12341Sbill 	if (u.u_error)
124*3183Swnj 		vaclose(dev);
12541Sbill }
12641Sbill 
12741Sbill vastrategy(bp)
12841Sbill 	register struct buf *bp;
12941Sbill {
13041Sbill 	register int e;
131*3183Swnj 	register struct va_softc *sc = &va_softc[VAUNIT(bp->b_dev)];
132*3183Swnj 	register struct uba_device *ui = vadinfo[VAUNIT(bp->b_dev)];
133*3183Swnj 	register struct vadevice *vaaddr = (struct vadevice *)ui->ui_addr;
13441Sbill 
135133Sbill 	(void) spl4();
136*3183Swnj 	while (sc->sc_busy)
137*3183Swnj 		sleep((caddr_t)sc, VAPRI);
138*3183Swnj 	sc->sc_busy = 1;
139*3183Swnj 	sc->sc_bp = bp;
140*3183Swnj 	sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP);
141*3183Swnj 	if (e = vawait(bp->b_dev))
14241Sbill 		goto brkout;
143*3183Swnj 	sc->sc_wc = -(bp->b_bcount/2);
144*3183Swnj 	vastart(bp->b_dev);
145*3183Swnj 	e = vawait(bp->b_dev);
146*3183Swnj 	sc->sc_wc = 0;
147*3183Swnj 	if (sc->sc_state & VPRINTPLOT) {
148*3183Swnj 		sc->sc_state = (sc->sc_state & ~VPRINTPLOT) | VPLOT;
149*3183Swnj 		vaaddr->vacsh = VAAUTOSTEP;
150*3183Swnj 		e |= vawait(bp->b_dev);
15141Sbill 	}
152133Sbill 	(void) spl0();
15341Sbill brkout:
154*3183Swnj 	ubarelse(ui->ui_ubanum, &sc->sc_ubinfo);
155*3183Swnj 	sc->sc_bp = 0;
156*3183Swnj 	sc->sc_busy = 0;
15741Sbill 	iodone(bp);
15841Sbill 	if (e)
15941Sbill 		u.u_error = EIO;
160*3183Swnj 	wakeup((caddr_t)sc);
16141Sbill }
16241Sbill 
16341Sbill int	vablock = 16384;
16441Sbill 
16541Sbill unsigned
16641Sbill minvaph(bp)
167*3183Swnj 	struct buf *bp;
16841Sbill {
169*3183Swnj 
17041Sbill 	if (bp->b_bcount > vablock)
17141Sbill 		bp->b_bcount = vablock;
17241Sbill }
17341Sbill 
17441Sbill /*ARGSUSED*/
17541Sbill vawrite(dev)
176*3183Swnj 	dev_t dev;
17741Sbill {
178*3183Swnj 
179*3183Swnj 	physio(vastrategy, &rvabuf[VAUNIT(dev)], dev, B_WRITE, minvaph);
18041Sbill }
18141Sbill 
182*3183Swnj vawait(dev)
183*3183Swnj 	dev_t dev;
18441Sbill {
185*3183Swnj 	register struct vadevice *vaaddr =
186*3183Swnj 	    (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr;
18741Sbill 	register int e;
18841Sbill 
189*3183Swnj 	while (((e = vaaddr->vacsw) & (VA_DONE|VA_ERROR)) == 0)
190*3183Swnj 		sleep((caddr_t)&va_softc[VAUNIT(dev)], VAPRI);
191*3183Swnj 	if (e & VA_NPRTIMO)
192*3183Swnj 		printf("va%d: npr timeout\n", VAUNIT(dev));
193*3183Swnj 	return (e & VA_ERROR);
19441Sbill }
19541Sbill 
196*3183Swnj vastart(dev)
197*3183Swnj 	dev_t;
19841Sbill {
199*3183Swnj 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
200*3183Swnj 	register struct vadevice *vaaddr =
201*3183Swnj 	    (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr;
202*3183Swnj 
203*3183Swnj 	if (sc->sc_wc == 0)
20441Sbill 		return;
205*3183Swnj 	vaaddr->vaba = sc->sc_ubinfo;
206*3183Swnj 	vaaddr->vacsl = (sc->sc_ubinfo >> 12) & 0x30;
207*3183Swnj 	vaaddr->vawc = sc->sc_wc;
20841Sbill }
20941Sbill 
21041Sbill /*ARGSUSED*/
21141Sbill vaioctl(dev, cmd, addr, flag)
21241Sbill 	register caddr_t addr;
21341Sbill {
21441Sbill 	register int vcmd;
215*3183Swnj 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
21641Sbill 
21741Sbill 	switch (cmd) {
21841Sbill 
21941Sbill 	case VGETSTATE:
220*3183Swnj 		(void) suword(addr, sc->sc_state);
22141Sbill 		return;
22241Sbill 
22341Sbill 	case VSETSTATE:
22441Sbill 		vcmd = fuword(addr);
22541Sbill 		if (vcmd == -1) {
22641Sbill 			u.u_error = EFAULT;
22741Sbill 			return;
22841Sbill 		}
229*3183Swnj 		vacmd(dev, vcmd);
23041Sbill 		return;
23141Sbill 
23241Sbill 	default:
233*3183Swnj 		u.u_error = ENOTTY;
23441Sbill 		return;
23541Sbill 	}
23641Sbill }
23741Sbill 
238*3183Swnj vacmd(dev, vcmd)
239*3183Swnj 	dev_t dev;
240*3183Swnj 	int vcmd;
24141Sbill {
242*3183Swnj 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
243*3183Swnj 	register struct vadevice *vaaddr =
244*3183Swnj 	    (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr;
245*3183Swnj 
246133Sbill 	(void) spl4();
247*3183Swnj 	(void) vawait(dev);
24841Sbill 	switch (vcmd) {
24941Sbill 
25041Sbill 	case VPLOT:
25141Sbill 		/* Must turn on plot AND autostep modes. */
252*3183Swnj 		vaaddr->vacsh = VAPLOT;
253*3183Swnj 		if (vawait(dev))
25441Sbill 			u.u_error = EIO;
255*3183Swnj 		vaaddr->vacsh = VAAUTOSTEP;
25641Sbill 		break;
25741Sbill 
25841Sbill 	case VPRINT:
259*3183Swnj 		vaaddr->vacsh = VAPRINT;
26041Sbill 		break;
26141Sbill 
26241Sbill 	case VPRINTPLOT:
263*3183Swnj 		vaaddr->vacsh = VAPRINTPLOT;
26441Sbill 		break;
26541Sbill 	}
266*3183Swnj 	sc->sc_state = (sc->sc_state & ~(VPLOT|VPRINT|VPRINTPLOT)) | vcmd;
267*3183Swnj 	if (vawait(dev))
26841Sbill 		u.u_error = EIO;
269133Sbill 	(void) spl0();
27041Sbill }
27141Sbill 
272*3183Swnj vatimo(dev)
273*3183Swnj 	dev_t dev;
27441Sbill {
275*3183Swnj 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
276*3183Swnj 
277*3183Swnj 	if (sc->sc_openf)
278*3183Swnj 		timeout(vatimo, (caddr_t)dev, hz/10);
279*3183Swnj 	vaintr(dev);
28041Sbill }
28141Sbill 
28241Sbill /*ARGSUSED*/
28341Sbill vaintr(dev)
284*3183Swnj 	dev_t dev;
28541Sbill {
286*3183Swnj 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
287*3183Swnj 
288*3183Swnj 	wakeup((caddr_t)sc);
28941Sbill }
29041Sbill 
291*3183Swnj vaclose(dev)
292*3183Swnj 	dev_t dev;
29341Sbill {
294*3183Swnj 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
295*3183Swnj 	register struct vadevice *vaaddr =
296*3183Swnj 	    (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr;
29741Sbill 
298*3183Swnj 	sc->sc_openf = 0;
299*3183Swnj 	sc->sc_busy = 0;
300*3183Swnj 	sc->sc_state = 0;
301*3183Swnj 	sc->sc_ubinfo = 0;
302*3183Swnj 	vaaddr->vacsl = 0;
30341Sbill }
304287Sbill 
305*3183Swnj vareset(uban)
306*3183Swnj 	int uban;
307287Sbill {
308*3183Swnj 	register int va11;
309*3183Swnj 	register struct uba_device *ui;
310*3183Swnj 	register struct va_softc *sc = va_softc;
311*3183Swnj 	register struct vadevice *vaaddr;
312287Sbill 
313*3183Swnj 	for (va11 = 0; va11 < NVA; va11++, sc++) {
314*3183Swnj 		if ((ui = vadinfo[va11]) == 0 || ui->ui_alive == 0 ||
315*3183Swnj 		    ui->ui_ubanum != uban || sc->sc_openf == 0)
316*3183Swnj 			continue;
317*3183Swnj 		printf(" va%d", va11);
318*3183Swnj 		vaaddr = (struct vadevice *)ui->ui_addr;
319*3183Swnj 		vaaddr->vacsl = VA_IENABLE;
320*3183Swnj 		if (sc->sc_state & VPLOT) {
321*3183Swnj 			vaaddr->vacsh = VAPLOT;
322*3183Swnj 			DELAY(10000);
323*3183Swnj 			vaaddr->vacsh = VAAUTOSTEP;
324*3183Swnj 		} else if (sc->sc_state & VPRINTPLOT)
325*3183Swnj 			vaaddr->vacsh = VPRINTPLOT;
326*3183Swnj 		else
327*3183Swnj 			vaaddr->vacsh = VAPRINTPLOT;
328287Sbill 		DELAY(10000);
329*3183Swnj 		if (sc->sc_busy == 0)
330*3183Swnj 			continue;
331*3183Swnj 		if (sc->sc_ubinfo) {
332*3183Swnj 			printf("<%d>", (sc->sc_ubinfo>>28)&0xf);
333*3183Swnj 			ubarelse(ui->ui_ubanum, &sc->sc_ubinfo);
334*3183Swnj 		}
335*3183Swnj 		sc->sc_ubinfo = ubasetup(ui->ui_ubanum, sc->sc_bp, UBA_NEEDBDP);
336*3183Swnj 		sc->sc_wc = -(sc->sc_bp->b_bcount/2);
337*3183Swnj 		vastart(sc->sc_bp->b_dev);
338287Sbill 	}
339287Sbill }
3401564Sbill #endif
341