xref: /csrg-svn/sys/vax/uba/va.c (revision 23361)
1*23361Smckusick /*
2*23361Smckusick  * Copyright (c) 1982 Regents of the University of California.
3*23361Smckusick  * All rights reserved.  The Berkeley software License Agreement
4*23361Smckusick  * specifies the terms and conditions for redistribution.
5*23361Smckusick  *
6*23361Smckusick  *	@(#)va.c	6.3 (Berkeley) 06/08/85
7*23361Smckusick  */
841Sbill 
91938Swnj #include "va.h"
101564Sbill #if NVA > 0
111564Sbill /*
123183Swnj  * Varian printer plotter
131564Sbill  */
149784Ssam #include "../machine/pte.h"
159784Ssam 
1617085Sbloom #include "param.h"
1717085Sbloom #include "dir.h"
1817085Sbloom #include "user.h"
1917085Sbloom #include "buf.h"
2017085Sbloom #include "systm.h"
2117085Sbloom #include "map.h"
2217085Sbloom #include "ioctl.h"
2317085Sbloom #include "vcmd.h"
2417085Sbloom #include "uio.h"
2517085Sbloom #include "kernel.h"
2641Sbill 
2717085Sbloom #include "ubareg.h"
2817085Sbloom #include "ubavar.h"
299363Smckusick 
309364Smckusick int	vadebug = 0;
319364Smckusick #define	dprintf	if(vadebug)printf
329364Smckusick 
33287Sbill unsigned minvaph();
3441Sbill 
3541Sbill #define	VAPRI	(PZERO-1)
3641Sbill 
373183Swnj struct	vadevice {
383183Swnj 	u_short	vaba;			/* buffer address */
393183Swnj 	short	vawc;			/* word count (2's complement) */
4041Sbill 	union {
413183Swnj 		short	Vacsw;		/* control status as word */
423183Swnj 		struct {		/* control status as bytes */
43287Sbill 			char Vacsl;
44287Sbill 			char Vacsh;
45287Sbill 		} vacsr;
46287Sbill 	} vacs;
473183Swnj 	short	vadata;			/* programmed i/o data buffer */
4841Sbill };
4941Sbill 
50287Sbill #define	vacsw	vacs.Vacsw
51287Sbill #define	vacsh	vacs.vacsr.Vacsh
52287Sbill #define	vacsl	vacs.vacsr.Vacsl
53287Sbill 
54287Sbill /* vacsw bits */
553183Swnj #define	VA_ERROR	0100000		/* some error has occurred */
563183Swnj #define	VA_NPRTIMO	0001000		/* DMA timeout error */
573183Swnj #define	VA_NOTREADY	0000400		/* something besides NPRTIMO */
583183Swnj #define	VA_DONE		0000200
593183Swnj #define	VA_IENABLE	0000100		/* interrupt enable */
609362Smckusick #define	VA_DMAGO	0000010		/* DMA go bit */
619364Smckusick #define	VA_DMAGO	0000010		/* DMA go bit */
623183Swnj #define	VA_SUPPLIESLOW	0000004
633183Swnj #define	VA_BOTOFFORM	0000002
643183Swnj #define	VA_BYTEREVERSE	0000001		/* reverse byte order in words */
6541Sbill 
66287Sbill /* vacsh command bytes */
673183Swnj #define	VAPLOT		0000340
683183Swnj #define	VAPRINT		0000100
693183Swnj #define	VAPRINTPLOT	0000160
703183Swnj #define	VAAUTOSTEP	0000244
713183Swnj #define	VANOAUTOSTEP	0000045
723183Swnj #define	VAFORMFEED	0000263
733183Swnj #define	VASLEW		0000265
743183Swnj #define	VASTEP		0000064
7541Sbill 
763183Swnj struct va_softc {
779364Smckusick 	u_char	sc_openf;		/* exclusive open flag */
789364Smckusick 	u_char	sc_iostate;		/* kind of I/O going on */
799364Smckusick #define	VAS_IDLE	0	/* no I/O, free */
809364Smckusick #define	VAS_PIO		1	/* programmed I/O */
819364Smckusick #define	VAS_DMA		2	/* DMA, block pio */
829364Smckusick #define	VAS_WANT	4	/* wakeup when iostate changes */
839364Smckusick 	short	sc_tocnt;		/* time out counter */
849364Smckusick 	short	sc_info;		/* csw passed from vaintr */
859364Smckusick 	int	sc_state;		/* print/plot state of device */
863183Swnj } va_softc[NVA];
8741Sbill 
883183Swnj #define	VAUNIT(dev)	(minor(dev))
893183Swnj 
903183Swnj struct	buf rvabuf[NVA];
913183Swnj 
929364Smckusick int	vaprobe(), vaslave(), vaattach(), vadgo();
933183Swnj struct	uba_device *vadinfo[NVA];
949364Smckusick struct	uba_ctlr *vaminfo[NVA];
959364Smckusick struct	buf vabhdr[NVA];
963183Swnj u_short	vastd[] = { 0764000, 0 };
973183Swnj struct	uba_driver vadriver =
989364Smckusick     { vaprobe, vaslave, vaattach, vadgo, vastd, "vz", vadinfo, "va", vaminfo };
993183Swnj 
1003183Swnj vaprobe(reg)
1013183Swnj 	caddr_t reg;
10241Sbill {
1033183Swnj 	register int br, cvec;		/* value-result */
1043183Swnj 	register struct vadevice *vaaddr = (struct vadevice *)reg;
10541Sbill 
1069267Smckusick #ifdef lint
1079267Smckusick 	br = 0; cvec = br; br = cvec;
1089267Smckusick 	vaintr(0);
1099267Smckusick #endif
1109364Smckusick #ifndef UCBVAX
1113183Swnj 	vaaddr->vacsl = VA_IENABLE;
1123183Swnj 	vaaddr->vaba = 0;
1133183Swnj 	vaaddr->vacsh = VAPLOT;
1149364Smckusick 	vaaddr->vacsl = VA_IENABLE|VA_DMAGO;
1159364Smckusick 	vaaddr->vawc = -1;
1169364Smckusick 	DELAY(10000);
1179361Smckusick 	vaaddr->vacsl = 0;
1189364Smckusick 	vaaddr->vawc = 0;
1199364Smckusick #else
1209364Smckusick 	br=0x14;
1219364Smckusick 	cvec=0170;
1229362Smckusick #endif
1239362Smckusick 	return (sizeof (struct vadevice));
1243183Swnj }
1253183Swnj 
1263183Swnj /*ARGSUSED*/
1279364Smckusick vaslave(ui, reg)
1289364Smckusick 	struct uba_device *ui;
1299364Smckusick 	caddr_t reg;
1309364Smckusick {
1319364Smckusick 
1329364Smckusick 	ui->ui_dk = 0;
1339364Smckusick 	return (ui->ui_unit <= 0);
1349364Smckusick }
1359364Smckusick 
1369364Smckusick /*ARGSUSED*/
1373183Swnj vaattach(ui)
1383183Swnj 	struct uba_device *ui;
1393183Swnj {
1403183Swnj 
1419364Smckusick 	ui->ui_mi->um_tab.b_actf = &vabhdr[ui->ui_unit];
1423183Swnj }
1433183Swnj 
1443183Swnj vaopen(dev)
1453183Swnj 	dev_t dev;
1463183Swnj {
1473183Swnj 	register struct va_softc *sc;
1483183Swnj 	register struct vadevice *vaaddr;
1493183Swnj 	register struct uba_device *ui;
1509363Smckusick 	int error;
1519364Smckusick 	int unit = VAUNIT(dev);
1523183Swnj 
1539392Smckusick 	if (unit >= NVA || (sc = &va_softc[unit])->sc_openf ||
1549392Smckusick 	    (ui = vadinfo[unit]) == 0 || ui->ui_alive == 0)
1559363Smckusick 		return (ENXIO);
1563183Swnj 	vaaddr = (struct vadevice *)ui->ui_addr;
1573183Swnj 	sc->sc_openf = 1;
1583183Swnj 	vaaddr->vawc = 0;
1593183Swnj 	sc->sc_state = 0;
1609364Smckusick 	sc->sc_tocnt = 0;
1619364Smckusick 	sc->sc_iostate = VAS_IDLE;
1623183Swnj 	vaaddr->vacsl = VA_IENABLE;
1633183Swnj 	vatimo(dev);
1649363Smckusick 	error = vacmd(dev, VPRINT);
1659363Smckusick 	if (error)
1663183Swnj 		vaclose(dev);
1679363Smckusick 	return (error);
16841Sbill }
16941Sbill 
17041Sbill vastrategy(bp)
17141Sbill 	register struct buf *bp;
17241Sbill {
1739364Smckusick 	register struct uba_device *ui;
1749364Smckusick 	register struct uba_ctlr *um;
1759364Smckusick 	int s;
17641Sbill 
1779364Smckusick 	dprintf("vastrategy(%x)\n", bp);
1789364Smckusick 	ui = vadinfo[VAUNIT(bp->b_dev)];
1799364Smckusick 	if (ui == 0 || ui->ui_alive == 0) {
1809364Smckusick 		bp->b_flags |= B_ERROR;
1819364Smckusick 		iodone(bp);
1829364Smckusick 		return;
18341Sbill 	}
1849364Smckusick 	s = spl4();
1859364Smckusick 	um = ui->ui_mi;
1869364Smckusick 	bp->b_actf = NULL;
1879364Smckusick 	if (um->um_tab.b_actf->b_actf == NULL)
1889364Smckusick 		um->um_tab.b_actf->b_actf = bp;
1899364Smckusick 	else {
1909364Smckusick 		printf("bp = 0x%x, um->um_tab.b_actf->b_actf = 0x%x\n",
1919364Smckusick 			bp, um->um_tab.b_actf->b_actf);
1929364Smckusick 		panic("vastrategy");
1939364Smckusick 		um->um_tab.b_actf->b_actl->b_forw = bp;
1949364Smckusick 	}
1959364Smckusick 	um->um_tab.b_actf->b_actl = bp;
1969364Smckusick 	bp = um->um_tab.b_actf;
1979364Smckusick 	dprintf("vastrategy: bp=%x actf=%x active=%d\n",
1989364Smckusick 		bp, bp->b_actf, bp->b_active);
1999364Smckusick 	if (bp->b_actf && bp->b_active == 0)
2009364Smckusick 		(void) vastart(um);
2019364Smckusick 	splx(s);
20241Sbill }
20341Sbill 
20441Sbill int	vablock = 16384;
20541Sbill 
20641Sbill unsigned
20741Sbill minvaph(bp)
2083183Swnj 	struct buf *bp;
20941Sbill {
2103183Swnj 
21141Sbill 	if (bp->b_bcount > vablock)
21241Sbill 		bp->b_bcount = vablock;
21341Sbill }
21441Sbill 
21541Sbill /*ARGSUSED*/
2169362Smckusick vawrite(dev, uio)
2173183Swnj 	dev_t dev;
2189362Smckusick 	struct uio *uio;
21941Sbill {
2209267Smckusick 
2219362Smckusick 	if (VAUNIT(dev) > NVA)
2229363Smckusick 		return (ENXIO);
2239363Smckusick 	return (physio(vastrategy, &rvabuf[VAUNIT(dev)], dev, B_WRITE,
2249363Smckusick 		    minvaph, uio));
22541Sbill }
22641Sbill 
2279364Smckusick vastart(um)
2289364Smckusick 	register struct uba_ctlr *um;
22941Sbill {
2309364Smckusick 	struct buf *bp;
2319364Smckusick 	struct vadevice *vaaddr;
2329364Smckusick 	register struct va_softc *sc;
2339364Smckusick 	int unit;
23441Sbill 
2359364Smckusick 	dprintf("vastart(%x), bp=%x\n", um, um->um_tab.b_actf->b_actf);
2369364Smckusick 	if ((bp = um->um_tab.b_actf->b_actf) == NULL)
2379364Smckusick 		return;
2389364Smckusick 	unit = VAUNIT(bp->b_dev);
2399364Smckusick 	sc = &va_softc[unit];
2409364Smckusick 	sc->sc_tocnt = 0;
2419364Smckusick 	while (sc->sc_iostate&VAS_PIO) {
2429364Smckusick 		sc->sc_iostate |= VAS_WANT;
2439364Smckusick 		sleep((caddr_t)&sc->sc_iostate, VAPRI);
2449364Smckusick 	}
2459364Smckusick 	sc->sc_iostate |= VAS_DMA;
2469364Smckusick 	vaaddr = (struct vadevice *)um->um_addr;
2479364Smckusick 	vaaddr->vacsl = 0;
2489364Smckusick 	vaaddr->vawc = -(bp->b_bcount / 2);
2499364Smckusick 	um->um_cmd = VA_DMAGO | VA_IENABLE;
2509364Smckusick 	(void) ubago(vadinfo[unit]);
25141Sbill }
25241Sbill 
2539364Smckusick vadgo(um)
2549364Smckusick 	register struct uba_ctlr *um;
25541Sbill {
2569364Smckusick 	register struct vadevice *vaaddr = (struct vadevice *)um->um_addr;
2579364Smckusick 	register struct buf *bp;
2583183Swnj 
2599364Smckusick 	bp = um->um_tab.b_actf;
2609364Smckusick 	va_softc[VAUNIT(bp->b_actf->b_dev)].sc_tocnt = 0;
2619364Smckusick 	bp->b_active++;
2629364Smckusick 	vaaddr->vaba = um->um_ubinfo;
2639364Smckusick 	vaaddr->vacsl = ((um->um_ubinfo >> 12) & 0x30) | um->um_cmd;
26441Sbill }
26541Sbill 
26641Sbill /*ARGSUSED*/
2679362Smckusick vaioctl(dev, cmd, data, flag)
2689362Smckusick 	register caddr_t data;
26941Sbill {
2703183Swnj 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
27141Sbill 
27241Sbill 	switch (cmd) {
27341Sbill 
27441Sbill 	case VGETSTATE:
2759362Smckusick 		*(int *)data = sc->sc_state;
2769363Smckusick 		break;
27741Sbill 
27841Sbill 	case VSETSTATE:
2799363Smckusick 		return (vacmd(dev, *(int *)data));
28041Sbill 
28141Sbill 	default:
2829363Smckusick 		return (ENOTTY);
28341Sbill 	}
2849363Smckusick 	return (0);
28541Sbill }
28641Sbill 
2873183Swnj vacmd(dev, vcmd)
2883183Swnj 	dev_t dev;
2893183Swnj 	int vcmd;
29041Sbill {
2913183Swnj 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
2929363Smckusick 	int error = 0;
2939364Smckusick 	int s, cmd;
2943183Swnj 
2959364Smckusick 	s = spl4();
2969364Smckusick 	while (sc->sc_iostate&VAS_DMA) {
2979364Smckusick 		sc->sc_iostate |= VAS_WANT;
2989364Smckusick 		sleep((caddr_t)&sc->sc_iostate, VAPRI);
2999364Smckusick 	}
3009364Smckusick 	sc->sc_iostate |= VAS_PIO;
3019364Smckusick 	sc->sc_tocnt = 0;
3029364Smckusick 	cmd = 0;
30341Sbill 	switch (vcmd) {
30441Sbill 
30541Sbill 	case VPLOT:
30641Sbill 		/* Must turn on plot AND autostep modes. */
3079364Smckusick 		if (vadopio(dev, VAPLOT))
3089363Smckusick 			error = EIO;
3099364Smckusick 		cmd = VAAUTOSTEP;
31041Sbill 		break;
31141Sbill 
31241Sbill 	case VPRINT:
3139364Smckusick 		cmd = VAPRINT;
31441Sbill 		break;
31541Sbill 
31641Sbill 	case VPRINTPLOT:
3179364Smckusick 		cmd = VAPRINTPLOT;
31841Sbill 		break;
31941Sbill 	}
3203183Swnj 	sc->sc_state = (sc->sc_state & ~(VPLOT|VPRINT|VPRINTPLOT)) | vcmd;
3219364Smckusick 	if (cmd && vadopio(dev, cmd))
3229363Smckusick 		error = EIO;
3239364Smckusick 	sc->sc_iostate &= ~VAS_PIO;
3249364Smckusick 	if (sc->sc_iostate&VAS_WANT) {
3259364Smckusick 		sc->sc_iostate &= ~VAS_WANT;
3269364Smckusick 		wakeup((caddr_t)&sc->sc_iostate);
3279364Smckusick 	}
3289364Smckusick 	splx(s);
3299363Smckusick 	return (error);
33041Sbill }
33141Sbill 
3329364Smckusick vadopio(dev, cmd)
3339364Smckusick 	dev_t dev;
3349364Smckusick 	int cmd;
3359364Smckusick {
3369364Smckusick 	register struct vadevice *vaaddr =
3379364Smckusick 	    (struct vadevice *)vaminfo[VAUNIT(dev)]->um_addr;
3389364Smckusick 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
3399364Smckusick 
3409364Smckusick 	sc->sc_info = 0;
3419364Smckusick 	vaaddr->vacsh = cmd;
3429364Smckusick 	while ((sc->sc_info&(VA_DONE|VA_ERROR)) == 0)
3439364Smckusick 		sleep((caddr_t)&sc->sc_info, VAPRI);
3449364Smckusick 	return (sc->sc_info&VA_ERROR);
3459364Smckusick }
3469364Smckusick 
3473183Swnj vatimo(dev)
3483183Swnj 	dev_t dev;
34941Sbill {
3503183Swnj 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
3513183Swnj 
3523183Swnj 	if (sc->sc_openf)
3539364Smckusick 		timeout(vatimo, (caddr_t)dev, hz/2);
3549364Smckusick 	if (++sc->sc_tocnt < 2)
3559364Smckusick 		return;
3569364Smckusick 	sc->sc_tocnt = 0;
3579364Smckusick 	dprintf("vatimo: calling vaintr\n");
3589267Smckusick 	vaintr(dev);
35941Sbill }
36041Sbill 
36141Sbill /*ARGSUSED*/
36241Sbill vaintr(dev)
3633183Swnj 	dev_t dev;
36441Sbill {
3659364Smckusick 	register struct uba_ctlr *um;
3669364Smckusick 	struct vadevice *vaaddr;
3679364Smckusick 	struct buf *bp;
3689364Smckusick 	register int unit = VAUNIT(dev), e;
3699364Smckusick 	register struct va_softc *sc = &va_softc[unit];
3703183Swnj 
3719364Smckusick 	um = vaminfo[unit];
3729364Smckusick 	vaaddr = (struct vadevice *)um->um_addr;
3739364Smckusick 	e = vaaddr->vacsw;
3749364Smckusick 	dprintf("vaintr: um=0x%x, e=0x%x, b_active %d\n",
3759364Smckusick 		um, e, um->um_tab.b_actf->b_active);
3769364Smckusick 	if ((e&(VA_DONE|VA_ERROR)) == 0)
3779364Smckusick 		return;
3789364Smckusick 	vaaddr->vacsl = 0;
3799364Smckusick 	if ((e&VA_ERROR) && (e&VA_NPRTIMO))
3809364Smckusick 		printf("va%d: npr timeout\n", unit);
3819364Smckusick 	if (sc->sc_iostate&VAS_PIO) {
3829364Smckusick 		sc->sc_info = e;
3839364Smckusick 		wakeup((caddr_t)&sc->sc_info);
3849364Smckusick 		return;
3859364Smckusick 	}
3869364Smckusick 	if (um->um_tab.b_actf->b_active) {
3879364Smckusick 		bp = um->um_tab.b_actf->b_actf;
3889364Smckusick 		if (e&VA_ERROR)
3899364Smckusick 			bp->b_flags |= B_ERROR;
3909364Smckusick 		if (sc->sc_state&VPRINTPLOT) {
3919364Smckusick 			sc->sc_state = (sc->sc_state & ~VPRINTPLOT) | VPLOT;
3929364Smckusick 			vaaddr->vacsh = VAAUTOSTEP;
3939364Smckusick 			return;
3949364Smckusick 		}
3959364Smckusick 		ubadone(um);
3969364Smckusick 		um->um_tab.b_actf->b_active = 0;
3979364Smckusick 		um->um_tab.b_actf->b_actf = bp->b_forw;
3989364Smckusick 		bp->b_active = 0;
3999364Smckusick 		bp->b_errcnt = 0;
4009364Smckusick 		bp->b_resid = 0;
4019364Smckusick 		iodone(bp);
4029364Smckusick 	}
4039364Smckusick 	if (um->um_tab.b_actf->b_actf == 0) {
4049364Smckusick 		sc->sc_iostate &= ~VAS_DMA;
4059364Smckusick 		if (sc->sc_iostate&VAS_WANT) {
4069364Smckusick 			sc->sc_iostate &= ~VAS_WANT;
4079364Smckusick 			wakeup((caddr_t)&sc->sc_iostate);
4089364Smckusick 		}
4099364Smckusick 		return;
4109364Smckusick 	}
4119364Smckusick 	if (um->um_tab.b_actf->b_active == 0)
4129364Smckusick 		vastart(um);
41341Sbill }
41441Sbill 
4153183Swnj vaclose(dev)
4163183Swnj 	dev_t dev;
41741Sbill {
4183183Swnj 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
4193183Swnj 	register struct vadevice *vaaddr =
4203183Swnj 	    (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr;
42141Sbill 
4223183Swnj 	sc->sc_openf = 0;
4233183Swnj 	sc->sc_state = 0;
4249364Smckusick 	if (sc->sc_iostate != VAS_IDLE)
4259364Smckusick 		wakeup((caddr_t)&sc->sc_iostate);
4269364Smckusick 	sc->sc_iostate = VAS_IDLE;
4273183Swnj 	vaaddr->vacsl = 0;
4289364Smckusick 	vaaddr->vawc = 0;
42941Sbill }
430287Sbill 
4313183Swnj vareset(uban)
4323183Swnj 	int uban;
433287Sbill {
4343183Swnj 	register int va11;
4359364Smckusick 	register struct uba_ctlr *um;
4363183Swnj 	register struct vadevice *vaaddr;
4379364Smckusick 	register struct va_softc *sc;
438287Sbill 
4393183Swnj 	for (va11 = 0; va11 < NVA; va11++, sc++) {
4409364Smckusick 		if ((um = vaminfo[va11]) == 0 || um->um_ubanum != uban ||
4419364Smckusick 		    um->um_alive == 0)
4423183Swnj 			continue;
4439364Smckusick 		sc = &va_softc[um->um_ctlr];
4449364Smckusick 		if (sc->sc_openf == 0)
4459364Smckusick 			continue;
4463183Swnj 		printf(" va%d", va11);
4479364Smckusick 		vaaddr = (struct vadevice *)um->um_addr;
4483183Swnj 		vaaddr->vacsl = VA_IENABLE;
4493183Swnj 		if (sc->sc_state & VPLOT) {
4503183Swnj 			vaaddr->vacsh = VAPLOT;
4513183Swnj 			DELAY(10000);
4523183Swnj 			vaaddr->vacsh = VAAUTOSTEP;
4533183Swnj 		} else if (sc->sc_state & VPRINTPLOT)
4543183Swnj 			vaaddr->vacsh = VPRINTPLOT;
4553183Swnj 		else
4563183Swnj 			vaaddr->vacsh = VAPRINTPLOT;
457287Sbill 		DELAY(10000);
4589392Smckusick 		sc->sc_iostate = VAS_IDLE;
4599392Smckusick 		um->um_tab.b_actf->b_active = 0;
4609392Smckusick 		um->um_tab.b_actf->b_actf = um->um_tab.b_actf->b_actl = 0;
4619392Smckusick 		if (um->um_ubinfo) {
4629392Smckusick 			printf("<%d>", (um->um_ubinfo >> 28) & 0xf);
4639392Smckusick 			um->um_ubinfo = 0;
4649392Smckusick 		}
4659364Smckusick 		(void) vastart(um);
466287Sbill 	}
467287Sbill }
4686432Ssam 
4696432Ssam vaselect()
4706432Ssam {
4719363Smckusick 
4726432Ssam 	return (1);
4736432Ssam }
4741564Sbill #endif
475