xref: /csrg-svn/sys/vax/uba/va.c (revision 9267)
1*9267Smckusick /*	va.c	4.15	82/11/16	*/
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 
19*9267Smckusick int	vadebug = 1;
20*9267Smckusick #define	dprintf	if(vadebug)printf
21*9267Smckusick 
22287Sbill unsigned minvaph();
2341Sbill 
2441Sbill #define	VAPRI	(PZERO-1)
2541Sbill 
263183Swnj struct	vadevice {
273183Swnj 	u_short	vaba;			/* buffer address */
283183Swnj 	short	vawc;			/* word count (2's complement) */
2941Sbill 	union {
303183Swnj 		short	Vacsw;		/* control status as word */
313183Swnj 		struct {		/* control status as bytes */
32287Sbill 			char Vacsl;
33287Sbill 			char Vacsh;
34287Sbill 		} vacsr;
35287Sbill 	} vacs;
363183Swnj 	short	vadata;			/* programmed i/o data buffer */
3741Sbill };
3841Sbill 
39287Sbill #define	vacsw	vacs.Vacsw
40287Sbill #define	vacsh	vacs.vacsr.Vacsh
41287Sbill #define	vacsl	vacs.vacsr.Vacsl
42287Sbill 
43287Sbill /* vacsw bits */
443183Swnj #define	VA_ERROR	0100000		/* some error has occurred */
453183Swnj #define	VA_NPRTIMO	0001000		/* DMA timeout error */
463183Swnj #define	VA_NOTREADY	0000400		/* something besides NPRTIMO */
473183Swnj #define	VA_DONE		0000200
483183Swnj #define	VA_IENABLE	0000100		/* interrupt enable */
49*9267Smckusick #define	VA_DMAGO	0000010		/* DMA go bit */
503183Swnj #define	VA_SUPPLIESLOW	0000004
513183Swnj #define	VA_BOTOFFORM	0000002
523183Swnj #define	VA_BYTEREVERSE	0000001		/* reverse byte order in words */
5341Sbill 
54287Sbill /* vacsh command bytes */
553183Swnj #define	VAPLOT		0000340
563183Swnj #define	VAPRINT		0000100
573183Swnj #define	VAPRINTPLOT	0000160
583183Swnj #define	VAAUTOSTEP	0000244
593183Swnj #define	VANOAUTOSTEP	0000045
603183Swnj #define	VAFORMFEED	0000263
613183Swnj #define	VASLEW		0000265
623183Swnj #define	VASTEP		0000064
6341Sbill 
643183Swnj struct va_softc {
65*9267Smckusick 	u_char	sc_openf;		/* exclusive open flag */
66*9267Smckusick 	u_char	sc_iostate;		/* kind of I/O going on */
67*9267Smckusick #define	VAS_IDLE	0	/* no I/O, free */
68*9267Smckusick #define	VAS_PIO		1	/* programmed I/O */
69*9267Smckusick #define	VAS_DMA		2	/* DMA, block pio */
70*9267Smckusick #define	VAS_WANT	4	/* wakeup when iostate changes */
71*9267Smckusick 	short	sc_tocnt;		/* time out counter */
72*9267Smckusick 	short	sc_info;		/* csw passed from vaintr */
73*9267Smckusick 	int	sc_state;		/* print/plot state of device */
743183Swnj } va_softc[NVA];
7541Sbill 
763183Swnj #define	VAUNIT(dev)	(minor(dev))
773183Swnj 
783183Swnj struct	buf rvabuf[NVA];
793183Swnj 
80*9267Smckusick int	vaprobe(), vaslave(), vaattach(), vadgo();
813183Swnj struct	uba_device *vadinfo[NVA];
82*9267Smckusick struct	uba_ctlr *vaminfo[NVA];
833183Swnj u_short	vastd[] = { 0764000, 0 };
843183Swnj struct	uba_driver vadriver =
85*9267Smckusick     { vaprobe, vaslave, vaattach, vadgo, vastd, "vz", vadinfo, "va", vaminfo };
863183Swnj 
873183Swnj vaprobe(reg)
883183Swnj 	caddr_t reg;
8941Sbill {
903183Swnj 	register int br, cvec;		/* value-result */
913183Swnj 	register struct vadevice *vaaddr = (struct vadevice *)reg;
9241Sbill 
93*9267Smckusick #ifdef lint
94*9267Smckusick 	br = 0; cvec = br; br = cvec;
95*9267Smckusick 	vaintr(0);
96*9267Smckusick #endif
979266Smckusick #ifndef UCBVAX
983183Swnj 	vaaddr->vacsl = VA_IENABLE;
993183Swnj 	vaaddr->vaba = 0;
1003183Swnj 	vaaddr->vacsh = VAPLOT;
1019266Smckusick 	vaaddr->vacsl = VA_IENABLE|VA_DMAGO;
1023183Swnj 	vaaddr->vawc = -1;
1039266Smckusick 	DELAY(10000);
1043183Swnj 	vaaddr->vacsl = 0;
1059266Smckusick 	vaaddr->vawc = 0;
1069266Smckusick #else
1079266Smckusick 	br=0x14;
1089266Smckusick 	cvec=0170;
1099266Smckusick #endif
1103183Swnj }
1113183Swnj 
1123183Swnj /*ARGSUSED*/
113*9267Smckusick vaslave(ui, reg)
114*9267Smckusick 	struct uba_device *ui;
115*9267Smckusick 	caddr_t reg;
116*9267Smckusick {
117*9267Smckusick 
118*9267Smckusick 	ui->ui_dk = 0;
119*9267Smckusick 	return (ui->ui_unit <= 0);
120*9267Smckusick }
121*9267Smckusick 
122*9267Smckusick /*ARGSUSED*/
1233183Swnj vaattach(ui)
1243183Swnj 	struct uba_device *ui;
1253183Swnj {
1263183Swnj 
1273183Swnj }
1283183Swnj 
1293183Swnj vaopen(dev)
1303183Swnj 	dev_t dev;
1313183Swnj {
1323183Swnj 	register struct va_softc *sc;
1333183Swnj 	register struct vadevice *vaaddr;
1343183Swnj 	register struct uba_device *ui;
135*9267Smckusick 	int unit = VAUNIT(dev);
1363183Swnj 
137*9267Smckusick 	if (unit >= NVA || (sc = &va_softc[unit])->sc_openf ||
138*9267Smckusick 	    (ui = vadinfo[unit]) == 0 || ui->ui_alive == 0) {
13941Sbill 		u.u_error = ENXIO;
14041Sbill 		return;
14141Sbill 	}
1423183Swnj 	vaaddr = (struct vadevice *)ui->ui_addr;
1433183Swnj 	sc->sc_openf = 1;
1443183Swnj 	vaaddr->vawc = 0;
1453183Swnj 	sc->sc_state = 0;
1469266Smckusick 	sc->sc_tocnt = 0;
147*9267Smckusick 	sc->sc_iostate = VAS_IDLE;
1483183Swnj 	vaaddr->vacsl = VA_IENABLE;
1493183Swnj 	vatimo(dev);
1503183Swnj 	vacmd(dev, VPRINT);
15141Sbill 	if (u.u_error)
1523183Swnj 		vaclose(dev);
15341Sbill }
15441Sbill 
15541Sbill vastrategy(bp)
15641Sbill 	register struct buf *bp;
15741Sbill {
158*9267Smckusick 	register struct uba_device *ui;
159*9267Smckusick 	register struct uba_ctlr *um;
160*9267Smckusick 	int s;
16141Sbill 
162*9267Smckusick dprintf("vastrategy(%x)\n", bp);
163*9267Smckusick 	ui = vadinfo[VAUNIT(bp->b_dev)];
164*9267Smckusick 	if (ui == 0 || ui->ui_alive == 0) {
165*9267Smckusick 		bp->b_flags |= B_ERROR;
166*9267Smckusick 		iodone(bp);
167*9267Smckusick 		return;
16841Sbill 	}
169*9267Smckusick 	s = spl4();
170*9267Smckusick 	um = ui->ui_mi;
171*9267Smckusick 	if (um->um_tab.b_actf == NULL)
172*9267Smckusick 		um->um_tab.b_actf = bp;
173*9267Smckusick 	else
174*9267Smckusick 		um->um_tab.b_actl->b_forw = bp;
175*9267Smckusick 	um->um_tab.b_actl = bp;
176*9267Smckusick 	bp = &um->um_tab;
177*9267Smckusick dprintf("vastrategy: bp=%x actf=%x active=%x\n", bp, bp->b_actf, bp->b_active);
178*9267Smckusick 	if (bp->b_actf && bp->b_active == 0)
179*9267Smckusick 		(void) vastart(um);
180*9267Smckusick 	splx(s);
18141Sbill }
18241Sbill 
18341Sbill int	vablock = 16384;
18441Sbill 
18541Sbill unsigned
18641Sbill minvaph(bp)
1873183Swnj 	struct buf *bp;
18841Sbill {
1893183Swnj 
19041Sbill 	if (bp->b_bcount > vablock)
19141Sbill 		bp->b_bcount = vablock;
19241Sbill }
19341Sbill 
19441Sbill /*ARGSUSED*/
19541Sbill vawrite(dev)
1963183Swnj 	dev_t dev;
19741Sbill {
198*9267Smckusick 
1993183Swnj 	physio(vastrategy, &rvabuf[VAUNIT(dev)], dev, B_WRITE, minvaph);
20041Sbill }
20141Sbill 
202*9267Smckusick vastart(um)
203*9267Smckusick 	register struct uba_ctlr *um;
20441Sbill {
205*9267Smckusick 	struct buf *bp;
206*9267Smckusick 	struct vadevice *vaaddr;
207*9267Smckusick 	register struct va_softc *sc;
208*9267Smckusick 	int unit;
20941Sbill 
210*9267Smckusick dprintf("vastart(%x), bp=%x\n", um, um->um_tab.b_actf);
211*9267Smckusick 	if ((bp = um->um_tab.b_actf) == NULL)
212*9267Smckusick 		return;
213*9267Smckusick 	um->um_tab.b_active++;
214*9267Smckusick 	unit = VAUNIT(bp->b_dev);
215*9267Smckusick 	sc = &va_softc[unit];
216*9267Smckusick 	while (sc->sc_iostate&VAS_PIO) {
217*9267Smckusick 		sc->sc_iostate |= VAS_WANT;
218*9267Smckusick 		sleep((caddr_t)&sc->sc_iostate, VAPRI);
2199266Smckusick 	}
220*9267Smckusick 	sc->sc_iostate |= VAS_DMA;
221*9267Smckusick 	vaaddr = (struct vadevice *)um->um_addr;
222*9267Smckusick 	vaaddr->vacsl = 0;
223*9267Smckusick 	vaaddr->vawc = -(bp->b_bcount / 2);
224*9267Smckusick 	um->um_cmd = VA_DMAGO | VA_IENABLE;
225*9267Smckusick 	(void) ubago(vadinfo[unit]);
22641Sbill }
22741Sbill 
228*9267Smckusick vadgo(um)
229*9267Smckusick 	register struct uba_ctlr *um;
23041Sbill {
231*9267Smckusick 	register struct vadevice *vaaddr = (struct vadevice *)um->um_addr;
232*9267Smckusick 	u_short i;
233*9267Smckusick 	short j;
2343183Swnj 
235*9267Smckusick 	i = um->um_ubinfo;
236*9267Smckusick 	j = ((um->um_ubinfo >> 12) & 0x30) | um->um_cmd;
237*9267Smckusick dprintf("vadgo: vaba 0x%x, vacsl 0%o, vawc 0x%x\n", i, j, vaaddr->vawc);
238*9267Smckusick 	vaaddr->vaba = um->um_ubinfo;
239*9267Smckusick 	vaaddr->vacsl = ((um->um_ubinfo >> 12) & 0x30) | um->um_cmd;
24041Sbill }
24141Sbill 
24241Sbill /*ARGSUSED*/
24341Sbill vaioctl(dev, cmd, addr, flag)
24441Sbill 	register caddr_t addr;
24541Sbill {
24641Sbill 	register int vcmd;
2473183Swnj 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
24841Sbill 
24941Sbill 	switch (cmd) {
25041Sbill 
25141Sbill 	case VGETSTATE:
2523183Swnj 		(void) suword(addr, sc->sc_state);
25341Sbill 		return;
25441Sbill 
25541Sbill 	case VSETSTATE:
25641Sbill 		vcmd = fuword(addr);
25741Sbill 		if (vcmd == -1) {
25841Sbill 			u.u_error = EFAULT;
25941Sbill 			return;
26041Sbill 		}
2613183Swnj 		vacmd(dev, vcmd);
26241Sbill 		return;
26341Sbill 
26441Sbill 	default:
2653183Swnj 		u.u_error = ENOTTY;
26641Sbill 		return;
26741Sbill 	}
26841Sbill }
26941Sbill 
2703183Swnj vacmd(dev, vcmd)
2713183Swnj 	dev_t dev;
2723183Swnj 	int vcmd;
27341Sbill {
2743183Swnj 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
275*9267Smckusick 	int s, cmd;
2763183Swnj 
277*9267Smckusick 	s = spl4();
278*9267Smckusick 	while (sc->sc_iostate&VAS_DMA) {
279*9267Smckusick 		sc->sc_iostate |= VAS_WANT;
280*9267Smckusick 		sleep((caddr_t)&sc->sc_iostate, VAPRI);
281*9267Smckusick 	}
282*9267Smckusick 	sc->sc_iostate |= VAS_PIO;
2839266Smckusick 	sc->sc_tocnt = 0;
284*9267Smckusick 	cmd = 0;
28541Sbill 	switch (vcmd) {
28641Sbill 
28741Sbill 	case VPLOT:
28841Sbill 		/* Must turn on plot AND autostep modes. */
289*9267Smckusick 		if (vadopio(dev, VAPLOT))
29041Sbill 			u.u_error = EIO;
291*9267Smckusick 		cmd = VAAUTOSTEP;
29241Sbill 		break;
29341Sbill 
29441Sbill 	case VPRINT:
295*9267Smckusick 		cmd = VAPRINT;
29641Sbill 		break;
29741Sbill 
29841Sbill 	case VPRINTPLOT:
299*9267Smckusick 		cmd = VAPRINTPLOT;
30041Sbill 		break;
30141Sbill 	}
3023183Swnj 	sc->sc_state = (sc->sc_state & ~(VPLOT|VPRINT|VPRINTPLOT)) | vcmd;
303*9267Smckusick 	if (cmd && vadopio(dev, cmd))
30441Sbill 		u.u_error = EIO;
305*9267Smckusick 	sc->sc_iostate &= ~VAS_PIO;
306*9267Smckusick 	if (sc->sc_iostate&VAS_WANT) {
307*9267Smckusick 		sc->sc_iostate &= ~VAS_WANT;
308*9267Smckusick 		wakeup((caddr_t)&sc->sc_iostate);
309*9267Smckusick 	}
310*9267Smckusick 	splx(s);
31141Sbill }
31241Sbill 
313*9267Smckusick vadopio(dev, cmd)
314*9267Smckusick 	dev_t dev;
315*9267Smckusick 	int cmd;
316*9267Smckusick {
317*9267Smckusick 	register struct vadevice *vaaddr =
318*9267Smckusick 	    (struct vadevice *)vaminfo[VAUNIT(dev)]->um_addr;
319*9267Smckusick 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
320*9267Smckusick 
321*9267Smckusick 	sc->sc_info = 0;
322*9267Smckusick 	vaaddr->vacsh = cmd;
323*9267Smckusick 	while ((sc->sc_info&(VA_DONE|VA_ERROR)) == 0)
324*9267Smckusick 		sleep((caddr_t)&sc->sc_info, VAPRI);
325*9267Smckusick 	return (sc->sc_info&VA_ERROR);
326*9267Smckusick }
327*9267Smckusick 
3283183Swnj vatimo(dev)
3293183Swnj 	dev_t dev;
33041Sbill {
3313183Swnj 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
3323183Swnj 
3333183Swnj 	if (sc->sc_openf)
3349266Smckusick 		timeout(vatimo, (caddr_t)dev, hz/2);
335*9267Smckusick 	if (++sc->sc_tocnt < 2)
336*9267Smckusick 		return;
337*9267Smckusick 	sc->sc_tocnt = 0;
338*9267Smckusick dprintf("vatimo: calling vaintr\n");
339*9267Smckusick 	vaintr(dev);
34041Sbill }
34141Sbill 
34241Sbill /*ARGSUSED*/
34341Sbill vaintr(dev)
3443183Swnj 	dev_t dev;
34541Sbill {
346*9267Smckusick 	register struct uba_ctlr *um;
347*9267Smckusick 	struct vadevice *vaaddr;
348*9267Smckusick 	struct buf *bp;
349*9267Smckusick 	register int unit = VAUNIT(dev), e;
350*9267Smckusick 	register struct va_softc *sc = &va_softc[unit];
3513183Swnj 
352*9267Smckusick 	um = vaminfo[unit];
353*9267Smckusick 	vaaddr = (struct vadevice *)um->um_addr;
354*9267Smckusick 	e = vaaddr->vacsw;
355*9267Smckusick dprintf("vaintr: um=%x, e=%x\n", um, e);
356*9267Smckusick 	if ((e&(VA_DONE|VA_ERROR)) == 0)
357*9267Smckusick 		return;
358*9267Smckusick 	vaaddr->vacsl = 0;
359*9267Smckusick 	if ((e&VA_ERROR) && (e&VA_NPRTIMO))
360*9267Smckusick 		printf("va%d: npr timeout\n", unit);
361*9267Smckusick 	if (sc->sc_iostate&VAS_PIO) {
362*9267Smckusick 		sc->sc_info = e;
363*9267Smckusick 		wakeup((caddr_t)&sc->sc_info);
364*9267Smckusick 		return;
365*9267Smckusick 	}
366*9267Smckusick 	if (um->um_tab.b_active) {
367*9267Smckusick 		bp = um->um_tab.b_actf;
368*9267Smckusick 		if (e&VA_ERROR)
369*9267Smckusick 			bp->b_flags |= B_ERROR;
370*9267Smckusick 		if (sc->sc_state&VPRINTPLOT) {
371*9267Smckusick 			sc->sc_state = (sc->sc_state & ~VPRINTPLOT) | VPLOT;
372*9267Smckusick 			vaaddr->vacsh = VAAUTOSTEP;
373*9267Smckusick 			return;
374*9267Smckusick 		}
375*9267Smckusick 	}
376*9267Smckusick 	ubadone(um);
377*9267Smckusick 	if (um->um_tab.b_active) {
378*9267Smckusick 		um->um_tab.b_active = 0;
379*9267Smckusick 		um->um_tab.b_actf = bp->b_forw;
380*9267Smckusick 		bp->b_active = 0;
381*9267Smckusick 		bp->b_errcnt = 0;
382*9267Smckusick 		bp->b_resid = 0;
383*9267Smckusick 		iodone(bp);
384*9267Smckusick 	}
385*9267Smckusick 	if (um->um_tab.b_actf == 0) {
386*9267Smckusick 		sc->sc_iostate &= ~VAS_DMA;
387*9267Smckusick 		if (sc->sc_iostate&VAS_WANT) {
388*9267Smckusick 			sc->sc_iostate &= ~VAS_WANT;
389*9267Smckusick 			wakeup((caddr_t)&sc->sc_iostate);
390*9267Smckusick 		}
391*9267Smckusick 		return;
392*9267Smckusick 	}
393*9267Smckusick 	if (um->um_tab.b_active == 0)
394*9267Smckusick 		vastart(um);
39541Sbill }
39641Sbill 
3973183Swnj vaclose(dev)
3983183Swnj 	dev_t dev;
39941Sbill {
4003183Swnj 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
4013183Swnj 	register struct vadevice *vaaddr =
4023183Swnj 	    (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr;
40341Sbill 
4043183Swnj 	sc->sc_openf = 0;
4053183Swnj 	sc->sc_state = 0;
406*9267Smckusick 	if (sc->sc_iostate != VAS_IDLE)
407*9267Smckusick 		wakeup((caddr_t)&sc->sc_iostate);
408*9267Smckusick 	sc->sc_iostate = VAS_IDLE;
4093183Swnj 	vaaddr->vacsl = 0;
4109266Smckusick 	vaaddr->vawc = 0;
41141Sbill }
412287Sbill 
4133183Swnj vareset(uban)
4143183Swnj 	int uban;
415287Sbill {
4163183Swnj 	register int va11;
417*9267Smckusick 	register struct uba_ctlr *um;
4183183Swnj 	register struct vadevice *vaaddr;
419*9267Smckusick 	register struct va_softc *sc;
420287Sbill 
4213183Swnj 	for (va11 = 0; va11 < NVA; va11++, sc++) {
422*9267Smckusick 		if ((um = vaminfo[va11]) == 0 || um->um_ubanum != uban ||
423*9267Smckusick 		    um->um_alive == 0)
4243183Swnj 			continue;
425*9267Smckusick 		sc = &va_softc[um->um_ctlr];
426*9267Smckusick 		if (sc->sc_openf == 0)
427*9267Smckusick 			continue;
4283183Swnj 		printf(" va%d", va11);
429*9267Smckusick 		vaaddr = (struct vadevice *)um->um_addr;
4303183Swnj 		vaaddr->vacsl = VA_IENABLE;
4313183Swnj 		if (sc->sc_state & VPLOT) {
4323183Swnj 			vaaddr->vacsh = VAPLOT;
4333183Swnj 			DELAY(10000);
4343183Swnj 			vaaddr->vacsh = VAAUTOSTEP;
4353183Swnj 		} else if (sc->sc_state & VPRINTPLOT)
4363183Swnj 			vaaddr->vacsh = VPRINTPLOT;
4373183Swnj 		else
4383183Swnj 			vaaddr->vacsh = VAPRINTPLOT;
439287Sbill 		DELAY(10000);
440*9267Smckusick 		sc->sc_iostate = VAS_IDLE;
441*9267Smckusick 		um->um_tab.b_active = 0;
442*9267Smckusick 		um->um_tab.b_actf = um->um_tab.b_actl = 0;
443*9267Smckusick 		if (um->um_ubinfo) {
444*9267Smckusick 			printf("<%d>", (um->um_ubinfo >> 28) & 0xf);
445*9267Smckusick 			ubadone(um);
4463183Swnj 		}
447*9267Smckusick 		(void) vastart(um);
448287Sbill 	}
449287Sbill }
4506432Ssam 
4516432Ssam vaselect()
4526432Ssam {
4536432Ssam 	return (1);
4546432Ssam }
4551564Sbill #endif
456