xref: /csrg-svn/sys/vax/uba/va.c (revision 9784)
1*9784Ssam /*	va.c	4.19	82/12/17	*/
241Sbill 
31938Swnj #include "va.h"
41564Sbill #if NVA > 0
51564Sbill /*
63183Swnj  * Varian printer plotter
71564Sbill  */
8*9784Ssam #include "../machine/pte.h"
9*9784Ssam 
1041Sbill #include "../h/param.h"
1141Sbill #include "../h/dir.h"
1241Sbill #include "../h/user.h"
1341Sbill #include "../h/buf.h"
1441Sbill #include "../h/systm.h"
1541Sbill #include "../h/map.h"
1641Sbill #include "../h/vcmd.h"
179362Smckusick #include "../h/uio.h"
1841Sbill 
199363Smckusick #include "../vaxuba/ubareg.h"
209363Smckusick #include "../vaxuba/ubavar.h"
219363Smckusick 
229364Smckusick int	vadebug = 0;
239364Smckusick #define	dprintf	if(vadebug)printf
249364Smckusick 
25287Sbill unsigned minvaph();
2641Sbill 
2741Sbill #define	VAPRI	(PZERO-1)
2841Sbill 
293183Swnj struct	vadevice {
303183Swnj 	u_short	vaba;			/* buffer address */
313183Swnj 	short	vawc;			/* word count (2's complement) */
3241Sbill 	union {
333183Swnj 		short	Vacsw;		/* control status as word */
343183Swnj 		struct {		/* control status as bytes */
35287Sbill 			char Vacsl;
36287Sbill 			char Vacsh;
37287Sbill 		} vacsr;
38287Sbill 	} vacs;
393183Swnj 	short	vadata;			/* programmed i/o data buffer */
4041Sbill };
4141Sbill 
42287Sbill #define	vacsw	vacs.Vacsw
43287Sbill #define	vacsh	vacs.vacsr.Vacsh
44287Sbill #define	vacsl	vacs.vacsr.Vacsl
45287Sbill 
46287Sbill /* vacsw bits */
473183Swnj #define	VA_ERROR	0100000		/* some error has occurred */
483183Swnj #define	VA_NPRTIMO	0001000		/* DMA timeout error */
493183Swnj #define	VA_NOTREADY	0000400		/* something besides NPRTIMO */
503183Swnj #define	VA_DONE		0000200
513183Swnj #define	VA_IENABLE	0000100		/* interrupt enable */
529362Smckusick #define	VA_DMAGO	0000010		/* DMA go bit */
539364Smckusick #define	VA_DMAGO	0000010		/* DMA go bit */
543183Swnj #define	VA_SUPPLIESLOW	0000004
553183Swnj #define	VA_BOTOFFORM	0000002
563183Swnj #define	VA_BYTEREVERSE	0000001		/* reverse byte order in words */
5741Sbill 
58287Sbill /* vacsh command bytes */
593183Swnj #define	VAPLOT		0000340
603183Swnj #define	VAPRINT		0000100
613183Swnj #define	VAPRINTPLOT	0000160
623183Swnj #define	VAAUTOSTEP	0000244
633183Swnj #define	VANOAUTOSTEP	0000045
643183Swnj #define	VAFORMFEED	0000263
653183Swnj #define	VASLEW		0000265
663183Swnj #define	VASTEP		0000064
6741Sbill 
683183Swnj struct va_softc {
699364Smckusick 	u_char	sc_openf;		/* exclusive open flag */
709364Smckusick 	u_char	sc_iostate;		/* kind of I/O going on */
719364Smckusick #define	VAS_IDLE	0	/* no I/O, free */
729364Smckusick #define	VAS_PIO		1	/* programmed I/O */
739364Smckusick #define	VAS_DMA		2	/* DMA, block pio */
749364Smckusick #define	VAS_WANT	4	/* wakeup when iostate changes */
759364Smckusick 	short	sc_tocnt;		/* time out counter */
769364Smckusick 	short	sc_info;		/* csw passed from vaintr */
779364Smckusick 	int	sc_state;		/* print/plot state of device */
783183Swnj } va_softc[NVA];
7941Sbill 
803183Swnj #define	VAUNIT(dev)	(minor(dev))
813183Swnj 
823183Swnj struct	buf rvabuf[NVA];
833183Swnj 
849364Smckusick int	vaprobe(), vaslave(), vaattach(), vadgo();
853183Swnj struct	uba_device *vadinfo[NVA];
869364Smckusick struct	uba_ctlr *vaminfo[NVA];
879364Smckusick struct	buf vabhdr[NVA];
883183Swnj u_short	vastd[] = { 0764000, 0 };
893183Swnj struct	uba_driver vadriver =
909364Smckusick     { vaprobe, vaslave, vaattach, vadgo, vastd, "vz", vadinfo, "va", vaminfo };
913183Swnj 
923183Swnj vaprobe(reg)
933183Swnj 	caddr_t reg;
9441Sbill {
953183Swnj 	register int br, cvec;		/* value-result */
963183Swnj 	register struct vadevice *vaaddr = (struct vadevice *)reg;
9741Sbill 
989267Smckusick #ifdef lint
999267Smckusick 	br = 0; cvec = br; br = cvec;
1009267Smckusick 	vaintr(0);
1019267Smckusick #endif
1029364Smckusick #ifndef UCBVAX
1033183Swnj 	vaaddr->vacsl = VA_IENABLE;
1043183Swnj 	vaaddr->vaba = 0;
1053183Swnj 	vaaddr->vacsh = VAPLOT;
1069364Smckusick 	vaaddr->vacsl = VA_IENABLE|VA_DMAGO;
1079364Smckusick 	vaaddr->vawc = -1;
1089364Smckusick 	DELAY(10000);
1099361Smckusick 	vaaddr->vacsl = 0;
1109364Smckusick 	vaaddr->vawc = 0;
1119364Smckusick #else
1129364Smckusick 	br=0x14;
1139364Smckusick 	cvec=0170;
1149362Smckusick #endif
1159362Smckusick 	return (sizeof (struct vadevice));
1163183Swnj }
1173183Swnj 
1183183Swnj /*ARGSUSED*/
1199364Smckusick vaslave(ui, reg)
1209364Smckusick 	struct uba_device *ui;
1219364Smckusick 	caddr_t reg;
1229364Smckusick {
1239364Smckusick 
1249364Smckusick 	ui->ui_dk = 0;
1259364Smckusick 	return (ui->ui_unit <= 0);
1269364Smckusick }
1279364Smckusick 
1289364Smckusick /*ARGSUSED*/
1293183Swnj vaattach(ui)
1303183Swnj 	struct uba_device *ui;
1313183Swnj {
1323183Swnj 
1339364Smckusick 	ui->ui_mi->um_tab.b_actf = &vabhdr[ui->ui_unit];
1343183Swnj }
1353183Swnj 
1363183Swnj vaopen(dev)
1373183Swnj 	dev_t dev;
1383183Swnj {
1393183Swnj 	register struct va_softc *sc;
1403183Swnj 	register struct vadevice *vaaddr;
1413183Swnj 	register struct uba_device *ui;
1429363Smckusick 	int error;
1439364Smckusick 	int unit = VAUNIT(dev);
1443183Swnj 
1459392Smckusick 	if (unit >= NVA || (sc = &va_softc[unit])->sc_openf ||
1469392Smckusick 	    (ui = vadinfo[unit]) == 0 || ui->ui_alive == 0)
1479363Smckusick 		return (ENXIO);
1483183Swnj 	vaaddr = (struct vadevice *)ui->ui_addr;
1493183Swnj 	sc->sc_openf = 1;
1503183Swnj 	vaaddr->vawc = 0;
1513183Swnj 	sc->sc_state = 0;
1529364Smckusick 	sc->sc_tocnt = 0;
1539364Smckusick 	sc->sc_iostate = VAS_IDLE;
1543183Swnj 	vaaddr->vacsl = VA_IENABLE;
1553183Swnj 	vatimo(dev);
1569363Smckusick 	error = vacmd(dev, VPRINT);
1579363Smckusick 	if (error)
1583183Swnj 		vaclose(dev);
1599363Smckusick 	return (error);
16041Sbill }
16141Sbill 
16241Sbill vastrategy(bp)
16341Sbill 	register struct buf *bp;
16441Sbill {
1659364Smckusick 	register struct uba_device *ui;
1669364Smckusick 	register struct uba_ctlr *um;
1679364Smckusick 	int s;
16841Sbill 
1699364Smckusick 	dprintf("vastrategy(%x)\n", bp);
1709364Smckusick 	ui = vadinfo[VAUNIT(bp->b_dev)];
1719364Smckusick 	if (ui == 0 || ui->ui_alive == 0) {
1729364Smckusick 		bp->b_flags |= B_ERROR;
1739364Smckusick 		iodone(bp);
1749364Smckusick 		return;
17541Sbill 	}
1769364Smckusick 	s = spl4();
1779364Smckusick 	um = ui->ui_mi;
1789364Smckusick 	bp->b_actf = NULL;
1799364Smckusick 	if (um->um_tab.b_actf->b_actf == NULL)
1809364Smckusick 		um->um_tab.b_actf->b_actf = bp;
1819364Smckusick 	else {
1829364Smckusick 		printf("bp = 0x%x, um->um_tab.b_actf->b_actf = 0x%x\n",
1839364Smckusick 			bp, um->um_tab.b_actf->b_actf);
1849364Smckusick 		panic("vastrategy");
1859364Smckusick 		um->um_tab.b_actf->b_actl->b_forw = bp;
1869364Smckusick 	}
1879364Smckusick 	um->um_tab.b_actf->b_actl = bp;
1889364Smckusick 	bp = um->um_tab.b_actf;
1899364Smckusick 	dprintf("vastrategy: bp=%x actf=%x active=%d\n",
1909364Smckusick 		bp, bp->b_actf, bp->b_active);
1919364Smckusick 	if (bp->b_actf && bp->b_active == 0)
1929364Smckusick 		(void) vastart(um);
1939364Smckusick 	splx(s);
19441Sbill }
19541Sbill 
19641Sbill int	vablock = 16384;
19741Sbill 
19841Sbill unsigned
19941Sbill minvaph(bp)
2003183Swnj 	struct buf *bp;
20141Sbill {
2023183Swnj 
20341Sbill 	if (bp->b_bcount > vablock)
20441Sbill 		bp->b_bcount = vablock;
20541Sbill }
20641Sbill 
20741Sbill /*ARGSUSED*/
2089362Smckusick vawrite(dev, uio)
2093183Swnj 	dev_t dev;
2109362Smckusick 	struct uio *uio;
21141Sbill {
2129267Smckusick 
2139362Smckusick 	if (VAUNIT(dev) > NVA)
2149363Smckusick 		return (ENXIO);
2159363Smckusick 	return (physio(vastrategy, &rvabuf[VAUNIT(dev)], dev, B_WRITE,
2169363Smckusick 		    minvaph, uio));
21741Sbill }
21841Sbill 
2199364Smckusick vastart(um)
2209364Smckusick 	register struct uba_ctlr *um;
22141Sbill {
2229364Smckusick 	struct buf *bp;
2239364Smckusick 	struct vadevice *vaaddr;
2249364Smckusick 	register struct va_softc *sc;
2259364Smckusick 	int unit;
22641Sbill 
2279364Smckusick 	dprintf("vastart(%x), bp=%x\n", um, um->um_tab.b_actf->b_actf);
2289364Smckusick 	if ((bp = um->um_tab.b_actf->b_actf) == NULL)
2299364Smckusick 		return;
2309364Smckusick 	unit = VAUNIT(bp->b_dev);
2319364Smckusick 	sc = &va_softc[unit];
2329364Smckusick 	sc->sc_tocnt = 0;
2339364Smckusick 	while (sc->sc_iostate&VAS_PIO) {
2349364Smckusick 		sc->sc_iostate |= VAS_WANT;
2359364Smckusick 		sleep((caddr_t)&sc->sc_iostate, VAPRI);
2369364Smckusick 	}
2379364Smckusick 	sc->sc_iostate |= VAS_DMA;
2389364Smckusick 	vaaddr = (struct vadevice *)um->um_addr;
2399364Smckusick 	vaaddr->vacsl = 0;
2409364Smckusick 	vaaddr->vawc = -(bp->b_bcount / 2);
2419364Smckusick 	um->um_cmd = VA_DMAGO | VA_IENABLE;
2429364Smckusick 	(void) ubago(vadinfo[unit]);
24341Sbill }
24441Sbill 
2459364Smckusick vadgo(um)
2469364Smckusick 	register struct uba_ctlr *um;
24741Sbill {
2489364Smckusick 	register struct vadevice *vaaddr = (struct vadevice *)um->um_addr;
2499364Smckusick 	register struct buf *bp;
2503183Swnj 
2519364Smckusick 	bp = um->um_tab.b_actf;
2529364Smckusick 	va_softc[VAUNIT(bp->b_actf->b_dev)].sc_tocnt = 0;
2539364Smckusick 	bp->b_active++;
2549364Smckusick 	vaaddr->vaba = um->um_ubinfo;
2559364Smckusick 	vaaddr->vacsl = ((um->um_ubinfo >> 12) & 0x30) | um->um_cmd;
25641Sbill }
25741Sbill 
25841Sbill /*ARGSUSED*/
2599362Smckusick vaioctl(dev, cmd, data, flag)
2609362Smckusick 	register caddr_t data;
26141Sbill {
26241Sbill 	register int vcmd;
2633183Swnj 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
26441Sbill 
26541Sbill 	switch (cmd) {
26641Sbill 
26741Sbill 	case VGETSTATE:
2689362Smckusick 		*(int *)data = sc->sc_state;
2699363Smckusick 		break;
27041Sbill 
27141Sbill 	case VSETSTATE:
2729363Smckusick 		return (vacmd(dev, *(int *)data));
2739363Smckusick 		break;
27441Sbill 
27541Sbill 	default:
2769363Smckusick 		return (ENOTTY);
27741Sbill 	}
2789363Smckusick 	return (0);
27941Sbill }
28041Sbill 
2813183Swnj vacmd(dev, vcmd)
2823183Swnj 	dev_t dev;
2833183Swnj 	int vcmd;
28441Sbill {
2853183Swnj 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
2869363Smckusick 	int error = 0;
2879364Smckusick 	int s, cmd;
2883183Swnj 
2899364Smckusick 	s = spl4();
2909364Smckusick 	while (sc->sc_iostate&VAS_DMA) {
2919364Smckusick 		sc->sc_iostate |= VAS_WANT;
2929364Smckusick 		sleep((caddr_t)&sc->sc_iostate, VAPRI);
2939364Smckusick 	}
2949364Smckusick 	sc->sc_iostate |= VAS_PIO;
2959364Smckusick 	sc->sc_tocnt = 0;
2969364Smckusick 	cmd = 0;
29741Sbill 	switch (vcmd) {
29841Sbill 
29941Sbill 	case VPLOT:
30041Sbill 		/* Must turn on plot AND autostep modes. */
3019364Smckusick 		if (vadopio(dev, VAPLOT))
3029363Smckusick 			error = EIO;
3039364Smckusick 		cmd = VAAUTOSTEP;
30441Sbill 		break;
30541Sbill 
30641Sbill 	case VPRINT:
3079364Smckusick 		cmd = VAPRINT;
30841Sbill 		break;
30941Sbill 
31041Sbill 	case VPRINTPLOT:
3119364Smckusick 		cmd = VAPRINTPLOT;
31241Sbill 		break;
31341Sbill 	}
3143183Swnj 	sc->sc_state = (sc->sc_state & ~(VPLOT|VPRINT|VPRINTPLOT)) | vcmd;
3159364Smckusick 	if (cmd && vadopio(dev, cmd))
3169363Smckusick 		error = EIO;
3179364Smckusick 	sc->sc_iostate &= ~VAS_PIO;
3189364Smckusick 	if (sc->sc_iostate&VAS_WANT) {
3199364Smckusick 		sc->sc_iostate &= ~VAS_WANT;
3209364Smckusick 		wakeup((caddr_t)&sc->sc_iostate);
3219364Smckusick 	}
3229364Smckusick 	splx(s);
3239363Smckusick 	return (error);
32441Sbill }
32541Sbill 
3269364Smckusick vadopio(dev, cmd)
3279364Smckusick 	dev_t dev;
3289364Smckusick 	int cmd;
3299364Smckusick {
3309364Smckusick 	register struct vadevice *vaaddr =
3319364Smckusick 	    (struct vadevice *)vaminfo[VAUNIT(dev)]->um_addr;
3329364Smckusick 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
3339364Smckusick 
3349364Smckusick 	sc->sc_info = 0;
3359364Smckusick 	vaaddr->vacsh = cmd;
3369364Smckusick 	while ((sc->sc_info&(VA_DONE|VA_ERROR)) == 0)
3379364Smckusick 		sleep((caddr_t)&sc->sc_info, VAPRI);
3389364Smckusick 	return (sc->sc_info&VA_ERROR);
3399364Smckusick }
3409364Smckusick 
3413183Swnj vatimo(dev)
3423183Swnj 	dev_t dev;
34341Sbill {
3443183Swnj 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
3453183Swnj 
3463183Swnj 	if (sc->sc_openf)
3479364Smckusick 		timeout(vatimo, (caddr_t)dev, hz/2);
3489364Smckusick 	if (++sc->sc_tocnt < 2)
3499364Smckusick 		return;
3509364Smckusick 	sc->sc_tocnt = 0;
3519364Smckusick 	dprintf("vatimo: calling vaintr\n");
3529267Smckusick 	vaintr(dev);
35341Sbill }
35441Sbill 
35541Sbill /*ARGSUSED*/
35641Sbill vaintr(dev)
3573183Swnj 	dev_t dev;
35841Sbill {
3599364Smckusick 	register struct uba_ctlr *um;
3609364Smckusick 	struct vadevice *vaaddr;
3619364Smckusick 	struct buf *bp;
3629364Smckusick 	register int unit = VAUNIT(dev), e;
3639364Smckusick 	register struct va_softc *sc = &va_softc[unit];
3643183Swnj 
3659364Smckusick 	um = vaminfo[unit];
3669364Smckusick 	vaaddr = (struct vadevice *)um->um_addr;
3679364Smckusick 	e = vaaddr->vacsw;
3689364Smckusick 	dprintf("vaintr: um=0x%x, e=0x%x, b_active %d\n",
3699364Smckusick 		um, e, um->um_tab.b_actf->b_active);
3709364Smckusick 	if ((e&(VA_DONE|VA_ERROR)) == 0)
3719364Smckusick 		return;
3729364Smckusick 	vaaddr->vacsl = 0;
3739364Smckusick 	if ((e&VA_ERROR) && (e&VA_NPRTIMO))
3749364Smckusick 		printf("va%d: npr timeout\n", unit);
3759364Smckusick 	if (sc->sc_iostate&VAS_PIO) {
3769364Smckusick 		sc->sc_info = e;
3779364Smckusick 		wakeup((caddr_t)&sc->sc_info);
3789364Smckusick 		return;
3799364Smckusick 	}
3809364Smckusick 	if (um->um_tab.b_actf->b_active) {
3819364Smckusick 		bp = um->um_tab.b_actf->b_actf;
3829364Smckusick 		if (e&VA_ERROR)
3839364Smckusick 			bp->b_flags |= B_ERROR;
3849364Smckusick 		if (sc->sc_state&VPRINTPLOT) {
3859364Smckusick 			sc->sc_state = (sc->sc_state & ~VPRINTPLOT) | VPLOT;
3869364Smckusick 			vaaddr->vacsh = VAAUTOSTEP;
3879364Smckusick 			return;
3889364Smckusick 		}
3899364Smckusick 		ubadone(um);
3909364Smckusick 		um->um_tab.b_actf->b_active = 0;
3919364Smckusick 		um->um_tab.b_actf->b_actf = bp->b_forw;
3929364Smckusick 		bp->b_active = 0;
3939364Smckusick 		bp->b_errcnt = 0;
3949364Smckusick 		bp->b_resid = 0;
3959364Smckusick 		iodone(bp);
3969364Smckusick 	}
3979364Smckusick 	if (um->um_tab.b_actf->b_actf == 0) {
3989364Smckusick 		sc->sc_iostate &= ~VAS_DMA;
3999364Smckusick 		if (sc->sc_iostate&VAS_WANT) {
4009364Smckusick 			sc->sc_iostate &= ~VAS_WANT;
4019364Smckusick 			wakeup((caddr_t)&sc->sc_iostate);
4029364Smckusick 		}
4039364Smckusick 		return;
4049364Smckusick 	}
4059364Smckusick 	if (um->um_tab.b_actf->b_active == 0)
4069364Smckusick 		vastart(um);
40741Sbill }
40841Sbill 
4093183Swnj vaclose(dev)
4103183Swnj 	dev_t dev;
41141Sbill {
4123183Swnj 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
4133183Swnj 	register struct vadevice *vaaddr =
4143183Swnj 	    (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr;
41541Sbill 
4163183Swnj 	sc->sc_openf = 0;
4173183Swnj 	sc->sc_state = 0;
4189364Smckusick 	if (sc->sc_iostate != VAS_IDLE)
4199364Smckusick 		wakeup((caddr_t)&sc->sc_iostate);
4209364Smckusick 	sc->sc_iostate = VAS_IDLE;
4213183Swnj 	vaaddr->vacsl = 0;
4229364Smckusick 	vaaddr->vawc = 0;
42341Sbill }
424287Sbill 
4253183Swnj vareset(uban)
4263183Swnj 	int uban;
427287Sbill {
4283183Swnj 	register int va11;
4299364Smckusick 	register struct uba_ctlr *um;
4303183Swnj 	register struct vadevice *vaaddr;
4319364Smckusick 	register struct va_softc *sc;
432287Sbill 
4333183Swnj 	for (va11 = 0; va11 < NVA; va11++, sc++) {
4349364Smckusick 		if ((um = vaminfo[va11]) == 0 || um->um_ubanum != uban ||
4359364Smckusick 		    um->um_alive == 0)
4363183Swnj 			continue;
4379364Smckusick 		sc = &va_softc[um->um_ctlr];
4389364Smckusick 		if (sc->sc_openf == 0)
4399364Smckusick 			continue;
4403183Swnj 		printf(" va%d", va11);
4419364Smckusick 		vaaddr = (struct vadevice *)um->um_addr;
4423183Swnj 		vaaddr->vacsl = VA_IENABLE;
4433183Swnj 		if (sc->sc_state & VPLOT) {
4443183Swnj 			vaaddr->vacsh = VAPLOT;
4453183Swnj 			DELAY(10000);
4463183Swnj 			vaaddr->vacsh = VAAUTOSTEP;
4473183Swnj 		} else if (sc->sc_state & VPRINTPLOT)
4483183Swnj 			vaaddr->vacsh = VPRINTPLOT;
4493183Swnj 		else
4503183Swnj 			vaaddr->vacsh = VAPRINTPLOT;
451287Sbill 		DELAY(10000);
4529392Smckusick 		sc->sc_iostate = VAS_IDLE;
4539392Smckusick 		um->um_tab.b_actf->b_active = 0;
4549392Smckusick 		um->um_tab.b_actf->b_actf = um->um_tab.b_actf->b_actl = 0;
4559392Smckusick 		if (um->um_ubinfo) {
4569392Smckusick 			printf("<%d>", (um->um_ubinfo >> 28) & 0xf);
4579392Smckusick 			um->um_ubinfo = 0;
4589392Smckusick 		}
4599364Smckusick 		(void) vastart(um);
460287Sbill 	}
461287Sbill }
4626432Ssam 
4636432Ssam vaselect()
4646432Ssam {
4659363Smckusick 
4666432Ssam 	return (1);
4676432Ssam }
4681564Sbill #endif
469