xref: /csrg-svn/sys/vax/uba/va.c (revision 9364)
1*9364Smckusick /*	va.c	4.17	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 
189363Smckusick #include "../vaxuba/ubareg.h"
199363Smckusick #include "../vaxuba/ubavar.h"
209363Smckusick 
21*9364Smckusick int	vadebug = 0;
22*9364Smckusick #define	dprintf	if(vadebug)printf
23*9364Smckusick 
24287Sbill unsigned minvaph();
2541Sbill 
2641Sbill #define	VAPRI	(PZERO-1)
2741Sbill 
283183Swnj struct	vadevice {
293183Swnj 	u_short	vaba;			/* buffer address */
303183Swnj 	short	vawc;			/* word count (2's complement) */
3141Sbill 	union {
323183Swnj 		short	Vacsw;		/* control status as word */
333183Swnj 		struct {		/* control status as bytes */
34287Sbill 			char Vacsl;
35287Sbill 			char Vacsh;
36287Sbill 		} vacsr;
37287Sbill 	} vacs;
383183Swnj 	short	vadata;			/* programmed i/o data buffer */
3941Sbill };
4041Sbill 
41287Sbill #define	vacsw	vacs.Vacsw
42287Sbill #define	vacsh	vacs.vacsr.Vacsh
43287Sbill #define	vacsl	vacs.vacsr.Vacsl
44287Sbill 
45287Sbill /* vacsw bits */
463183Swnj #define	VA_ERROR	0100000		/* some error has occurred */
473183Swnj #define	VA_NPRTIMO	0001000		/* DMA timeout error */
483183Swnj #define	VA_NOTREADY	0000400		/* something besides NPRTIMO */
493183Swnj #define	VA_DONE		0000200
503183Swnj #define	VA_IENABLE	0000100		/* interrupt enable */
519362Smckusick #define	VA_DMAGO	0000010		/* DMA go bit */
52*9364Smckusick #define	VA_DMAGO	0000010		/* DMA go bit */
533183Swnj #define	VA_SUPPLIESLOW	0000004
543183Swnj #define	VA_BOTOFFORM	0000002
553183Swnj #define	VA_BYTEREVERSE	0000001		/* reverse byte order in words */
5641Sbill 
57287Sbill /* vacsh command bytes */
583183Swnj #define	VAPLOT		0000340
593183Swnj #define	VAPRINT		0000100
603183Swnj #define	VAPRINTPLOT	0000160
613183Swnj #define	VAAUTOSTEP	0000244
623183Swnj #define	VANOAUTOSTEP	0000045
633183Swnj #define	VAFORMFEED	0000263
643183Swnj #define	VASLEW		0000265
653183Swnj #define	VASTEP		0000064
6641Sbill 
673183Swnj struct va_softc {
68*9364Smckusick 	u_char	sc_openf;		/* exclusive open flag */
69*9364Smckusick 	u_char	sc_iostate;		/* kind of I/O going on */
70*9364Smckusick #define	VAS_IDLE	0	/* no I/O, free */
71*9364Smckusick #define	VAS_PIO		1	/* programmed I/O */
72*9364Smckusick #define	VAS_DMA		2	/* DMA, block pio */
73*9364Smckusick #define	VAS_WANT	4	/* wakeup when iostate changes */
74*9364Smckusick 	short	sc_tocnt;		/* time out counter */
75*9364Smckusick 	short	sc_info;		/* csw passed from vaintr */
76*9364Smckusick 	int	sc_state;		/* print/plot state of device */
773183Swnj } va_softc[NVA];
7841Sbill 
793183Swnj #define	VAUNIT(dev)	(minor(dev))
803183Swnj 
813183Swnj struct	buf rvabuf[NVA];
823183Swnj 
83*9364Smckusick int	vaprobe(), vaslave(), vaattach(), vadgo();
843183Swnj struct	uba_device *vadinfo[NVA];
85*9364Smckusick struct	uba_ctlr *vaminfo[NVA];
86*9364Smckusick struct	buf vabhdr[NVA];
873183Swnj u_short	vastd[] = { 0764000, 0 };
883183Swnj struct	uba_driver vadriver =
89*9364Smckusick     { vaprobe, vaslave, vaattach, vadgo, vastd, "vz", vadinfo, "va", vaminfo };
903183Swnj 
913183Swnj vaprobe(reg)
923183Swnj 	caddr_t reg;
9341Sbill {
943183Swnj 	register int br, cvec;		/* value-result */
953183Swnj 	register struct vadevice *vaaddr = (struct vadevice *)reg;
9641Sbill 
979267Smckusick #ifdef lint
989267Smckusick 	br = 0; cvec = br; br = cvec;
999267Smckusick 	vaintr(0);
1009267Smckusick #endif
101*9364Smckusick #ifndef UCBVAX
1023183Swnj 	vaaddr->vacsl = VA_IENABLE;
1033183Swnj 	vaaddr->vaba = 0;
1043183Swnj 	vaaddr->vacsh = VAPLOT;
105*9364Smckusick 	vaaddr->vacsl = VA_IENABLE|VA_DMAGO;
106*9364Smckusick 	vaaddr->vawc = -1;
107*9364Smckusick 	DELAY(10000);
1089361Smckusick 	vaaddr->vacsl = 0;
109*9364Smckusick 	vaaddr->vawc = 0;
110*9364Smckusick #else
111*9364Smckusick 	br=0x14;
112*9364Smckusick 	cvec=0170;
1139362Smckusick #endif
1149362Smckusick 	return (sizeof (struct vadevice));
1153183Swnj }
1163183Swnj 
1173183Swnj /*ARGSUSED*/
118*9364Smckusick vaslave(ui, reg)
119*9364Smckusick 	struct uba_device *ui;
120*9364Smckusick 	caddr_t reg;
121*9364Smckusick {
122*9364Smckusick 
123*9364Smckusick 	ui->ui_dk = 0;
124*9364Smckusick 	return (ui->ui_unit <= 0);
125*9364Smckusick }
126*9364Smckusick 
127*9364Smckusick /*ARGSUSED*/
1283183Swnj vaattach(ui)
1293183Swnj 	struct uba_device *ui;
1303183Swnj {
1313183Swnj 
132*9364Smckusick 	ui->ui_mi->um_tab.b_actf = &vabhdr[ui->ui_unit];
1333183Swnj }
1343183Swnj 
1353183Swnj vaopen(dev)
1363183Swnj 	dev_t dev;
1373183Swnj {
1383183Swnj 	register struct va_softc *sc;
1393183Swnj 	register struct vadevice *vaaddr;
1403183Swnj 	register struct uba_device *ui;
1419363Smckusick 	int error;
142*9364Smckusick 	int unit = VAUNIT(dev);
1433183Swnj 
1449363Smckusick 	    (ui = vadinfo[VAUNIT(dev)]) == 0 || ui->ui_alive == 0)
1459363Smckusick 		return (ENXIO);
1463183Swnj 	vaaddr = (struct vadevice *)ui->ui_addr;
1473183Swnj 	sc->sc_openf = 1;
1483183Swnj 	vaaddr->vawc = 0;
1493183Swnj 	sc->sc_state = 0;
150*9364Smckusick 	sc->sc_tocnt = 0;
151*9364Smckusick 	sc->sc_iostate = VAS_IDLE;
1523183Swnj 	vaaddr->vacsl = VA_IENABLE;
1533183Swnj 	vatimo(dev);
1549363Smckusick 	error = vacmd(dev, VPRINT);
1559363Smckusick 	if (error)
1563183Swnj 		vaclose(dev);
1579363Smckusick 	return (error);
15841Sbill }
15941Sbill 
16041Sbill vastrategy(bp)
16141Sbill 	register struct buf *bp;
16241Sbill {
163*9364Smckusick 	register struct uba_device *ui;
164*9364Smckusick 	register struct uba_ctlr *um;
165*9364Smckusick 	int s;
16641Sbill 
167*9364Smckusick 	dprintf("vastrategy(%x)\n", bp);
168*9364Smckusick 	ui = vadinfo[VAUNIT(bp->b_dev)];
169*9364Smckusick 	if (ui == 0 || ui->ui_alive == 0) {
170*9364Smckusick 		bp->b_flags |= B_ERROR;
171*9364Smckusick 		iodone(bp);
172*9364Smckusick 		return;
17341Sbill 	}
174*9364Smckusick 	s = spl4();
175*9364Smckusick 	um = ui->ui_mi;
176*9364Smckusick 	bp->b_actf = NULL;
177*9364Smckusick 	if (um->um_tab.b_actf->b_actf == NULL)
178*9364Smckusick 		um->um_tab.b_actf->b_actf = bp;
179*9364Smckusick 	else {
180*9364Smckusick 		printf("bp = 0x%x, um->um_tab.b_actf->b_actf = 0x%x\n",
181*9364Smckusick 			bp, um->um_tab.b_actf->b_actf);
182*9364Smckusick 		panic("vastrategy");
183*9364Smckusick 		um->um_tab.b_actf->b_actl->b_forw = bp;
184*9364Smckusick 	}
185*9364Smckusick 	um->um_tab.b_actf->b_actl = bp;
186*9364Smckusick 	bp = um->um_tab.b_actf;
187*9364Smckusick 	dprintf("vastrategy: bp=%x actf=%x active=%d\n",
188*9364Smckusick 		bp, bp->b_actf, bp->b_active);
189*9364Smckusick 	if (bp->b_actf && bp->b_active == 0)
190*9364Smckusick 		(void) vastart(um);
191*9364Smckusick 	splx(s);
19241Sbill }
19341Sbill 
19441Sbill int	vablock = 16384;
19541Sbill 
19641Sbill unsigned
19741Sbill minvaph(bp)
1983183Swnj 	struct buf *bp;
19941Sbill {
2003183Swnj 
20141Sbill 	if (bp->b_bcount > vablock)
20241Sbill 		bp->b_bcount = vablock;
20341Sbill }
20441Sbill 
20541Sbill /*ARGSUSED*/
2069362Smckusick vawrite(dev, uio)
2073183Swnj 	dev_t dev;
2089362Smckusick 	struct uio *uio;
20941Sbill {
2109267Smckusick 
2119362Smckusick 	if (VAUNIT(dev) > NVA)
2129363Smckusick 		return (ENXIO);
2139363Smckusick 	return (physio(vastrategy, &rvabuf[VAUNIT(dev)], dev, B_WRITE,
2149363Smckusick 		    minvaph, uio));
21541Sbill }
21641Sbill 
217*9364Smckusick vastart(um)
218*9364Smckusick 	register struct uba_ctlr *um;
21941Sbill {
220*9364Smckusick 	struct buf *bp;
221*9364Smckusick 	struct vadevice *vaaddr;
222*9364Smckusick 	register struct va_softc *sc;
223*9364Smckusick 	int unit;
22441Sbill 
225*9364Smckusick 	dprintf("vastart(%x), bp=%x\n", um, um->um_tab.b_actf->b_actf);
226*9364Smckusick 	if ((bp = um->um_tab.b_actf->b_actf) == NULL)
227*9364Smckusick 		return;
228*9364Smckusick 	unit = VAUNIT(bp->b_dev);
229*9364Smckusick 	sc = &va_softc[unit];
230*9364Smckusick 	sc->sc_tocnt = 0;
231*9364Smckusick 	while (sc->sc_iostate&VAS_PIO) {
232*9364Smckusick 		sc->sc_iostate |= VAS_WANT;
233*9364Smckusick 		sleep((caddr_t)&sc->sc_iostate, VAPRI);
234*9364Smckusick 	}
235*9364Smckusick 	sc->sc_iostate |= VAS_DMA;
236*9364Smckusick 	vaaddr = (struct vadevice *)um->um_addr;
237*9364Smckusick 	vaaddr->vacsl = 0;
238*9364Smckusick 	vaaddr->vawc = -(bp->b_bcount / 2);
239*9364Smckusick 	um->um_cmd = VA_DMAGO | VA_IENABLE;
240*9364Smckusick 	(void) ubago(vadinfo[unit]);
24141Sbill }
24241Sbill 
243*9364Smckusick vadgo(um)
244*9364Smckusick 	register struct uba_ctlr *um;
24541Sbill {
246*9364Smckusick 	register struct vadevice *vaaddr = (struct vadevice *)um->um_addr;
247*9364Smckusick 	register struct buf *bp;
2483183Swnj 
249*9364Smckusick 	bp = um->um_tab.b_actf;
250*9364Smckusick 	va_softc[VAUNIT(bp->b_actf->b_dev)].sc_tocnt = 0;
251*9364Smckusick 	bp->b_active++;
252*9364Smckusick 	vaaddr->vaba = um->um_ubinfo;
253*9364Smckusick 	vaaddr->vacsl = ((um->um_ubinfo >> 12) & 0x30) | um->um_cmd;
25441Sbill }
25541Sbill 
25641Sbill /*ARGSUSED*/
2579362Smckusick vaioctl(dev, cmd, data, flag)
2589362Smckusick 	register caddr_t data;
25941Sbill {
26041Sbill 	register int vcmd;
2613183Swnj 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
26241Sbill 
26341Sbill 	switch (cmd) {
26441Sbill 
26541Sbill 	case VGETSTATE:
2669362Smckusick 		*(int *)data = sc->sc_state;
2679363Smckusick 		break;
26841Sbill 
26941Sbill 	case VSETSTATE:
2709363Smckusick 		return (vacmd(dev, *(int *)data));
2719363Smckusick 		break;
27241Sbill 
27341Sbill 	default:
2749363Smckusick 		return (ENOTTY);
27541Sbill 	}
2769363Smckusick 	return (0);
27741Sbill }
27841Sbill 
2793183Swnj vacmd(dev, vcmd)
2803183Swnj 	dev_t dev;
2813183Swnj 	int vcmd;
28241Sbill {
2833183Swnj 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
2849363Smckusick 	int error = 0;
285*9364Smckusick 	int s, cmd;
2863183Swnj 
287*9364Smckusick 	s = spl4();
288*9364Smckusick 	while (sc->sc_iostate&VAS_DMA) {
289*9364Smckusick 		sc->sc_iostate |= VAS_WANT;
290*9364Smckusick 		sleep((caddr_t)&sc->sc_iostate, VAPRI);
291*9364Smckusick 	}
292*9364Smckusick 	sc->sc_iostate |= VAS_PIO;
293*9364Smckusick 	sc->sc_tocnt = 0;
294*9364Smckusick 	cmd = 0;
29541Sbill 	switch (vcmd) {
29641Sbill 
29741Sbill 	case VPLOT:
29841Sbill 		/* Must turn on plot AND autostep modes. */
299*9364Smckusick 		if (vadopio(dev, VAPLOT))
3009363Smckusick 			error = EIO;
301*9364Smckusick 		cmd = VAAUTOSTEP;
30241Sbill 		break;
30341Sbill 
30441Sbill 	case VPRINT:
305*9364Smckusick 		cmd = VAPRINT;
30641Sbill 		break;
30741Sbill 
30841Sbill 	case VPRINTPLOT:
309*9364Smckusick 		cmd = VAPRINTPLOT;
31041Sbill 		break;
31141Sbill 	}
3123183Swnj 	sc->sc_state = (sc->sc_state & ~(VPLOT|VPRINT|VPRINTPLOT)) | vcmd;
313*9364Smckusick 	if (cmd && vadopio(dev, cmd))
3149363Smckusick 		error = EIO;
315*9364Smckusick 	sc->sc_iostate &= ~VAS_PIO;
316*9364Smckusick 	if (sc->sc_iostate&VAS_WANT) {
317*9364Smckusick 		sc->sc_iostate &= ~VAS_WANT;
318*9364Smckusick 		wakeup((caddr_t)&sc->sc_iostate);
319*9364Smckusick 	}
320*9364Smckusick 	splx(s);
3219363Smckusick 	return (error);
32241Sbill }
32341Sbill 
324*9364Smckusick vadopio(dev, cmd)
325*9364Smckusick 	dev_t dev;
326*9364Smckusick 	int cmd;
327*9364Smckusick {
328*9364Smckusick 	register struct vadevice *vaaddr =
329*9364Smckusick 	    (struct vadevice *)vaminfo[VAUNIT(dev)]->um_addr;
330*9364Smckusick 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
331*9364Smckusick 
332*9364Smckusick 	sc->sc_info = 0;
333*9364Smckusick 	vaaddr->vacsh = cmd;
334*9364Smckusick 	while ((sc->sc_info&(VA_DONE|VA_ERROR)) == 0)
335*9364Smckusick 		sleep((caddr_t)&sc->sc_info, VAPRI);
336*9364Smckusick 	return (sc->sc_info&VA_ERROR);
337*9364Smckusick }
338*9364Smckusick 
3393183Swnj vatimo(dev)
3403183Swnj 	dev_t dev;
34141Sbill {
3423183Swnj 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
3433183Swnj 
3443183Swnj 	if (sc->sc_openf)
345*9364Smckusick 		timeout(vatimo, (caddr_t)dev, hz/2);
346*9364Smckusick 	if (++sc->sc_tocnt < 2)
347*9364Smckusick 		return;
348*9364Smckusick 	sc->sc_tocnt = 0;
349*9364Smckusick 	dprintf("vatimo: calling vaintr\n");
3509267Smckusick 	vaintr(dev);
35141Sbill }
35241Sbill 
35341Sbill /*ARGSUSED*/
35441Sbill vaintr(dev)
3553183Swnj 	dev_t dev;
35641Sbill {
357*9364Smckusick 	register struct uba_ctlr *um;
358*9364Smckusick 	struct vadevice *vaaddr;
359*9364Smckusick 	struct buf *bp;
360*9364Smckusick 	register int unit = VAUNIT(dev), e;
361*9364Smckusick 	register struct va_softc *sc = &va_softc[unit];
3623183Swnj 
363*9364Smckusick 	um = vaminfo[unit];
364*9364Smckusick 	vaaddr = (struct vadevice *)um->um_addr;
365*9364Smckusick 	e = vaaddr->vacsw;
366*9364Smckusick 	dprintf("vaintr: um=0x%x, e=0x%x, b_active %d\n",
367*9364Smckusick 		um, e, um->um_tab.b_actf->b_active);
368*9364Smckusick 	if ((e&(VA_DONE|VA_ERROR)) == 0)
369*9364Smckusick 		return;
370*9364Smckusick 	vaaddr->vacsl = 0;
371*9364Smckusick 	if ((e&VA_ERROR) && (e&VA_NPRTIMO))
372*9364Smckusick 		printf("va%d: npr timeout\n", unit);
373*9364Smckusick 	if (sc->sc_iostate&VAS_PIO) {
374*9364Smckusick 		sc->sc_info = e;
375*9364Smckusick 		wakeup((caddr_t)&sc->sc_info);
376*9364Smckusick 		return;
377*9364Smckusick 	}
378*9364Smckusick 	if (um->um_tab.b_actf->b_active) {
379*9364Smckusick 		bp = um->um_tab.b_actf->b_actf;
380*9364Smckusick 		if (e&VA_ERROR)
381*9364Smckusick 			bp->b_flags |= B_ERROR;
382*9364Smckusick 		if (sc->sc_state&VPRINTPLOT) {
383*9364Smckusick 			sc->sc_state = (sc->sc_state & ~VPRINTPLOT) | VPLOT;
384*9364Smckusick 			vaaddr->vacsh = VAAUTOSTEP;
385*9364Smckusick 			return;
386*9364Smckusick 		}
387*9364Smckusick 		ubadone(um);
388*9364Smckusick 		um->um_tab.b_actf->b_active = 0;
389*9364Smckusick 		um->um_tab.b_actf->b_actf = bp->b_forw;
390*9364Smckusick 		bp->b_active = 0;
391*9364Smckusick 		bp->b_errcnt = 0;
392*9364Smckusick 		bp->b_resid = 0;
393*9364Smckusick 		iodone(bp);
394*9364Smckusick 	}
395*9364Smckusick 	if (um->um_tab.b_actf->b_actf == 0) {
396*9364Smckusick 		sc->sc_iostate &= ~VAS_DMA;
397*9364Smckusick 		if (sc->sc_iostate&VAS_WANT) {
398*9364Smckusick 			sc->sc_iostate &= ~VAS_WANT;
399*9364Smckusick 			wakeup((caddr_t)&sc->sc_iostate);
400*9364Smckusick 		}
401*9364Smckusick 		return;
402*9364Smckusick 	}
403*9364Smckusick 	if (um->um_tab.b_actf->b_active == 0)
404*9364Smckusick 		vastart(um);
40541Sbill }
40641Sbill 
4073183Swnj vaclose(dev)
4083183Swnj 	dev_t dev;
40941Sbill {
4103183Swnj 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
4113183Swnj 	register struct vadevice *vaaddr =
4123183Swnj 	    (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr;
41341Sbill 
4143183Swnj 	sc->sc_openf = 0;
4153183Swnj 	sc->sc_state = 0;
416*9364Smckusick 	if (sc->sc_iostate != VAS_IDLE)
417*9364Smckusick 		wakeup((caddr_t)&sc->sc_iostate);
418*9364Smckusick 	sc->sc_iostate = VAS_IDLE;
4193183Swnj 	vaaddr->vacsl = 0;
420*9364Smckusick 	vaaddr->vawc = 0;
42141Sbill }
422287Sbill 
4233183Swnj vareset(uban)
4243183Swnj 	int uban;
425287Sbill {
4263183Swnj 	register int va11;
427*9364Smckusick 	register struct uba_ctlr *um;
4283183Swnj 	register struct vadevice *vaaddr;
429*9364Smckusick 	register struct va_softc *sc;
430287Sbill 
4313183Swnj 	for (va11 = 0; va11 < NVA; va11++, sc++) {
432*9364Smckusick 		if ((um = vaminfo[va11]) == 0 || um->um_ubanum != uban ||
433*9364Smckusick 		    um->um_alive == 0)
4343183Swnj 			continue;
435*9364Smckusick 		sc = &va_softc[um->um_ctlr];
436*9364Smckusick 		if (sc->sc_openf == 0)
437*9364Smckusick 			continue;
4383183Swnj 		printf(" va%d", va11);
439*9364Smckusick 		vaaddr = (struct vadevice *)um->um_addr;
4403183Swnj 		vaaddr->vacsl = VA_IENABLE;
4413183Swnj 		if (sc->sc_state & VPLOT) {
4423183Swnj 			vaaddr->vacsh = VAPLOT;
4433183Swnj 			DELAY(10000);
4443183Swnj 			vaaddr->vacsh = VAAUTOSTEP;
4453183Swnj 		} else if (sc->sc_state & VPRINTPLOT)
4463183Swnj 			vaaddr->vacsh = VPRINTPLOT;
4473183Swnj 		else
4483183Swnj 			vaaddr->vacsh = VAPRINTPLOT;
449287Sbill 		DELAY(10000);
450*9364Smckusick 		(void) vastart(um);
451287Sbill 	}
452287Sbill }
4536432Ssam 
4546432Ssam vaselect()
4556432Ssam {
4569363Smckusick 
4576432Ssam 	return (1);
4586432Ssam }
4591564Sbill #endif
460