xref: /csrg-svn/sys/vax/uba/vp.c (revision 10877)
1*10877Ssam /*	vp.c	4.23	83/02/10	*/
244Sbill 
31939Swnj #include "vp.h"
41565Sbill #if NVP > 0
51565Sbill /*
61565Sbill  * Versatec matrix printer/plotter
71565Sbill  * dma interface driver
83439Swnj  *
93439Swnj  * SETUP NOTES:
103439Swnj  *	Set up both print and plot interrupts to go through the same vector
113439Swnj  *	Give the address of the plcsr register in the config specification
121565Sbill  */
139785Ssam #include "../machine/pte.h"
149785Ssam 
1544Sbill #include "../h/param.h"
1644Sbill #include "../h/dir.h"
1744Sbill #include "../h/user.h"
1844Sbill #include "../h/buf.h"
1944Sbill #include "../h/systm.h"
2044Sbill #include "../h/map.h"
213184Swnj #include "../h/vcmd.h"
227737Sroot #include "../h/uio.h"
23*10877Ssam #include "../h/kernel.h"
2444Sbill 
258484Sroot #include "../vaxuba/ubavar.h"
268484Sroot #include "../vaxuba/ubareg.h"
278484Sroot 
2844Sbill unsigned minvpph();
2944Sbill 
3044Sbill #define	VPPRI	(PZERO-1)
3144Sbill 
323184Swnj struct	vpdevice {
3344Sbill 	short	plbcr;
341903Swnj 	short	pbxaddr;
3544Sbill 	short	prbcr;
363184Swnj 	u_short pbaddr;
3744Sbill 	short	plcsr;
3844Sbill 	short	plbuf;
3944Sbill 	short	prcsr;
403184Swnj 	u_short prbuf;
4144Sbill };
4244Sbill 
433184Swnj #define	VP_ERROR	0100000
443184Swnj #define	VP_DTCINTR	0040000
453184Swnj #define	VP_DMAACT	0020000
463184Swnj #define	VP_READY	0000200
473184Swnj #define	VP_IENABLE	0000100
483184Swnj #define	VP_TERMCOM	0000040
493184Swnj #define	VP_FFCOM	0000020
503184Swnj #define	VP_EOTCOM	0000010
513184Swnj #define	VP_CLRCOM	0000004
523184Swnj #define	VP_RESET	0000002
533184Swnj #define	VP_SPP		0000001
5444Sbill 
553184Swnj struct vp_softc {
563184Swnj 	int	sc_state;
573184Swnj 	int	sc_count;
583184Swnj 	int	sc_bufp;
593184Swnj 	struct	buf *sc_bp;
603184Swnj 	int	sc_ubinfo;
613184Swnj } vp_softc[NVP];
6244Sbill 
633184Swnj /* sc_state bits */
643184Swnj #define	VPSC_BUSY	0001000
653184Swnj #define	VPSC_MODE	0000700
663184Swnj #define	VPSC_SPP	0000400
673184Swnj #define	VPSC_PLOT	0000200
683184Swnj #define	VPSC_PRINT	0000100
693184Swnj #define	VPSC_CMNDS	0000076
703184Swnj #define	VPSC_OPEN	0000001
7144Sbill 
723184Swnj struct	uba_device *vpdinfo[NVP];
7344Sbill 
743184Swnj #define	VPUNIT(dev)	(minor(dev))
753184Swnj 
763184Swnj struct	buf rvpbuf[NVP];
773184Swnj 
783184Swnj int	vpprobe(), vpattach();
793184Swnj struct	uba_device *vpdinfo[NVP];
803184Swnj u_short	vpstd[] = { 0777500, 0 };
813184Swnj struct	uba_driver vpdriver =
823184Swnj     { vpprobe, 0, vpattach, 0, vpstd, "vp", vpdinfo };
833184Swnj 
843184Swnj vpprobe(reg)
853184Swnj 	caddr_t reg;
8644Sbill {
873184Swnj 	register int br, cvec;		/* value-result */
883184Swnj 	register struct vpdevice *vpaddr = (struct vpdevice *)(reg-010);
8944Sbill 
904942Swnj #ifdef lint
914942Swnj 	br = 0; cvec = br; br = cvec;
924942Swnj 	vpintr(0);
934942Swnj #endif
943184Swnj 	vpaddr->prcsr = VP_IENABLE|VP_DTCINTR;
953184Swnj 	vpaddr->pbaddr = 0;
963184Swnj 	vpaddr->pbxaddr = 0;
973439Swnj 	vpaddr->prbcr = 1;
983184Swnj 	DELAY(10000);
993184Swnj 	vpaddr->prcsr = 0;
1006859Ssam #if ERNIE || CAD || UCBVAX
1013439Swnj 	/* UNTIL REWIRED, GET INTERRUPT AT 200 BUT WANT 174 */
1023439Swnj 	if (cvec == 0200) {
1033439Swnj 		printf("vp reset vec from 200 to 174\n");
1043439Swnj 		cvec = 0174;
1053439Swnj 	}
1063439Swnj #endif
1077408Skre 	return (sizeof (struct vpdevice));
1083184Swnj }
1093184Swnj 
1103184Swnj /*ARGSUSED*/
1113184Swnj vpattach(ui)
1123184Swnj 	struct uba_device *ui;
1133184Swnj {
1143184Swnj 
1153184Swnj 	ui->ui_addr -= 010;
1163184Swnj 	ui->ui_physaddr -= 010;
1173184Swnj }
1183184Swnj 
1193184Swnj vpopen(dev)
1203184Swnj 	dev_t dev;
1213184Swnj {
1223184Swnj 	register struct vp_softc *sc;
1233184Swnj 	register struct vpdevice *vpaddr;
1243184Swnj 	register struct uba_device *ui;
1253184Swnj 
1263184Swnj 	if (VPUNIT(dev) >= NVP ||
1273184Swnj 	    ((sc = &vp_softc[minor(dev)])->sc_state&VPSC_OPEN) ||
1288578Sroot 	    (ui = vpdinfo[VPUNIT(dev)]) == 0 || ui->ui_alive == 0)
1298578Sroot 		return (ENXIO);
1303184Swnj 	vpaddr = (struct vpdevice *)ui->ui_addr;
1313184Swnj 	sc->sc_state = VPSC_OPEN|VPSC_PRINT | VP_CLRCOM|VP_RESET;
1323184Swnj 	sc->sc_count = 0;
1333184Swnj 	vpaddr->prcsr = VP_IENABLE|VP_DTCINTR;
1343184Swnj 	vptimo(dev);
1353184Swnj 	while (sc->sc_state & VPSC_CMNDS) {
136134Sbill 		(void) spl4();
1373184Swnj 		if (vpwait(dev)) {
1383184Swnj 			vpclose(dev);
1398578Sroot 			return (EIO);
14044Sbill 		}
1413184Swnj 		vpstart(dev);
142134Sbill 		(void) spl0();
14344Sbill 	}
1448578Sroot 	return (0);
14544Sbill }
14644Sbill 
14744Sbill vpstrategy(bp)
14844Sbill 	register struct buf *bp;
14944Sbill {
15044Sbill 	register int e;
1513184Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(bp->b_dev)];
1523184Swnj 	register struct uba_device *ui = vpdinfo[VPUNIT(bp->b_dev)];
1533184Swnj 	register struct vpdevice *vpaddr = (struct vpdevice *)ui->ui_addr;
15444Sbill 
155134Sbill 	(void) spl4();
1563184Swnj 	while (sc->sc_state & VPSC_BUSY)
1573184Swnj 		sleep((caddr_t)sc, VPPRI);
1583184Swnj 	sc->sc_state |= VPSC_BUSY;
1593184Swnj 	sc->sc_bp = bp;
1603184Swnj 	sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP);
1613184Swnj 	if (e = vpwait(bp->b_dev))
16244Sbill 		goto brkout;
1633184Swnj 	sc->sc_count = bp->b_bcount;
1643184Swnj 	vpstart(bp->b_dev);
1653184Swnj 	while (((sc->sc_state&VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr) & VP_DMAACT)
1663184Swnj 		sleep((caddr_t)sc, VPPRI);
1673184Swnj 	sc->sc_count = 0;
1683184Swnj 	if ((sc->sc_state&VPSC_MODE) == VPSC_SPP)
1693184Swnj 		sc->sc_state = (sc->sc_state &~ VPSC_MODE) | VPSC_PLOT;
170134Sbill 	(void) spl0();
17144Sbill brkout:
1723184Swnj 	ubarelse(ui->ui_ubanum, &sc->sc_ubinfo);
1733184Swnj 	sc->sc_state &= ~VPSC_BUSY;
1743184Swnj 	sc->sc_bp = 0;
1758494Sroot 	if (e)
1768494Sroot 		bp->b_flags |= B_ERROR;
17744Sbill 	iodone(bp);
1783184Swnj 	wakeup((caddr_t)sc);
17944Sbill }
18044Sbill 
18144Sbill int	vpblock = 16384;
18244Sbill 
18344Sbill unsigned
18444Sbill minvpph(bp)
1853184Swnj 	struct buf *bp;
18644Sbill {
18744Sbill 
18844Sbill 	if (bp->b_bcount > vpblock)
18944Sbill 		bp->b_bcount = vpblock;
19044Sbill }
19144Sbill 
19244Sbill /*ARGSUSED*/
1938168Sroot vpwrite(dev, uio)
1943184Swnj 	dev_t dev;
1958168Sroot 	struct uio *uio;
19644Sbill {
19744Sbill 
1987848Sroot 	if (VPUNIT(dev) >= NVP)
1998168Sroot 		return (ENXIO);
2008168Sroot 	return (physio(vpstrategy, &rvpbuf[VPUNIT(dev)], dev, B_WRITE,
2018168Sroot 		    minvpph, uio));
20244Sbill }
20344Sbill 
2043184Swnj vpwait(dev)
2053184Swnj 	dev_t dev;
20644Sbill {
2073184Swnj 	register struct vpdevice *vpaddr =
2083184Swnj 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
2093184Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
2103184Swnj 	register int e;
21144Sbill 
2123184Swnj 	for (;;) {
2133184Swnj 		e = (sc->sc_state & VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr;
2143184Swnj 		if (e & (VP_READY|VP_ERROR))
2153184Swnj 			break;
2163184Swnj 		sleep((caddr_t)sc, VPPRI);
2173184Swnj 	}
2188494Sroot 	/* I WISH I COULD TELL WHETHER AN ERROR INDICATED AN NPR TIMEOUT */
2193184Swnj 	return (e & VP_ERROR);
22044Sbill }
22144Sbill 
2223184Swnj vpstart(dev)
2233184Swnj 	dev_t;
22444Sbill {
2253184Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
2263184Swnj 	register struct vpdevice *vpaddr =
2273184Swnj 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
2283184Swnj 	short bit;
22944Sbill 
2303184Swnj 	if (sc->sc_count) {
2313184Swnj 		vpaddr->pbaddr = sc->sc_ubinfo;
2323184Swnj 		vpaddr->pbxaddr = (sc->sc_ubinfo>>12)&0x30;
2333184Swnj 		if (sc->sc_state & (VPSC_PRINT|VPSC_SPP))
2343184Swnj 			vpaddr->prbcr = sc->sc_count;
23544Sbill 		else
2363184Swnj 			vpaddr->plbcr = sc->sc_count;
23744Sbill 		return;
23844Sbill 	}
23944Sbill 	for (bit = 1; bit != 0; bit <<= 1)
2403184Swnj 		if (sc->sc_state&bit&VPSC_CMNDS) {
2413184Swnj 			vpaddr->plcsr |= bit;
2423184Swnj 			sc->sc_state &= ~bit;
24344Sbill 			return;
24444Sbill 		}
24544Sbill }
24644Sbill 
24744Sbill /*ARGSUSED*/
24844Sbill vpioctl(dev, cmd, addr, flag)
2493184Swnj 	dev_t dev;
2503184Swnj 	int cmd;
25144Sbill 	register caddr_t addr;
2523184Swnj 	int flag;
25344Sbill {
25444Sbill 	register int m;
2553184Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
2563184Swnj 	register struct vpdevice *vpaddr =
2573184Swnj 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
25844Sbill 
25944Sbill 	switch (cmd) {
26044Sbill 
2613184Swnj 	case VGETSTATE:
2623184Swnj 		(void) suword(addr, sc->sc_state);
2638578Sroot 		break;
26444Sbill 
2653184Swnj 	case VSETSTATE:
26644Sbill 		m = fuword(addr);
2678578Sroot 		if (m == -1)
2688578Sroot 			return (EFAULT);
2693184Swnj 		sc->sc_state =
2703184Swnj 		    (sc->sc_state & ~VPSC_MODE) | (m&(VPSC_MODE|VPSC_CMNDS));
27144Sbill 		break;
27244Sbill 
27344Sbill 	default:
2748578Sroot 		return (ENOTTY);
27544Sbill 	}
276134Sbill 	(void) spl4();
2773184Swnj 	(void) vpwait(dev);
2783184Swnj 	if (sc->sc_state&VPSC_SPP)
2793184Swnj 		vpaddr->plcsr |= VP_SPP;
28044Sbill 	else
2813184Swnj 		vpaddr->plcsr &= ~VP_SPP;
2823184Swnj 	sc->sc_count = 0;
2833184Swnj 	while (sc->sc_state & VPSC_CMNDS) {
2843184Swnj 		(void) vpwait(dev);
2853184Swnj 		vpstart(dev);
28644Sbill 	}
287134Sbill 	(void) spl0();
2888578Sroot 	return (0);
28944Sbill }
29044Sbill 
2913184Swnj vptimo(dev)
2923184Swnj 	dev_t dev;
29344Sbill {
2943184Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
29544Sbill 
2963184Swnj 	if (sc->sc_state&VPSC_OPEN)
2973184Swnj 		timeout(vptimo, (caddr_t)dev, hz/10);
2983184Swnj 	vpintr(dev);
29944Sbill }
30044Sbill 
30144Sbill /*ARGSUSED*/
30244Sbill vpintr(dev)
3033184Swnj 	dev_t dev;
30444Sbill {
3053184Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
30644Sbill 
3073184Swnj 	wakeup((caddr_t)sc);
30844Sbill }
30944Sbill 
3103184Swnj vpclose(dev)
3113184Swnj 	dev_t dev;
31244Sbill {
3133184Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
3143184Swnj 	register struct vpdevice *vpaddr =
3153184Swnj 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
31644Sbill 
3173184Swnj 	sc->sc_state = 0;
3183184Swnj 	sc->sc_count = 0;
3193184Swnj 	vpaddr->plcsr = 0;
32044Sbill }
321288Sbill 
3223184Swnj vpreset(uban)
3233184Swnj 	int uban;
324288Sbill {
3253184Swnj 	register int vp11;
3263184Swnj 	register struct uba_device *ui;
3273184Swnj 	register struct vp_softc *sc = vp_softc;
3283184Swnj 	register struct vpdevice *vpaddr;
329288Sbill 
3303184Swnj 	for (vp11 = 0; vp11 < NVP; vp11++, sc++) {
3313184Swnj 		if ((ui = vpdinfo[vp11]) == 0 || ui->ui_alive == 0 ||
3323184Swnj 		    ui->ui_ubanum != uban || (sc->sc_state&VPSC_OPEN) == 0)
3333184Swnj 			continue;
3343184Swnj 		printf(" vp%d", vp11);
3353184Swnj 		vpaddr = (struct vpdevice *)ui->ui_addr;
3363184Swnj 		vpaddr->prcsr = VP_IENABLE|VP_DTCINTR;
3373184Swnj 		if ((sc->sc_state & VPSC_BUSY) == 0)
3383184Swnj 			continue;
3398578Sroot 		sc->sc_ubinfo = 0;
3403184Swnj 		sc->sc_count = sc->sc_bp->b_bcount;
3413184Swnj 		vpstart(sc->sc_bp->b_dev);
342288Sbill 	}
343288Sbill }
3446432Ssam 
3456432Ssam vpselect()
3466432Ssam {
3476432Ssam 	return (1);
3486432Ssam }
3491565Sbill #endif
350