xref: /csrg-svn/sys/vax/uba/vp.c (revision 3439)
1*3439Swnj /*	vp.c	4.9	81/04/02	*/
244Sbill 
31939Swnj #include "vp.h"
41565Sbill #if NVP > 0
51565Sbill /*
61565Sbill  * Versatec matrix printer/plotter
71565Sbill  * dma interface driver
8*3439Swnj  *
9*3439Swnj  * SETUP NOTES:
10*3439Swnj  *	Set up both print and plot interrupts to go through the same vector
11*3439Swnj  *	Give the address of the plcsr register in the config specification
121565Sbill  */
1344Sbill #include "../h/param.h"
1444Sbill #include "../h/dir.h"
1544Sbill #include "../h/user.h"
1644Sbill #include "../h/buf.h"
1744Sbill #include "../h/systm.h"
1844Sbill #include "../h/map.h"
1944Sbill #include "../h/pte.h"
203184Swnj #include "../h/ubavar.h"
213184Swnj #include "../h/ubareg.h"
223184Swnj #include "../h/vcmd.h"
2344Sbill 
2444Sbill unsigned minvpph();
2544Sbill 
2644Sbill #define	VPPRI	(PZERO-1)
2744Sbill 
283184Swnj struct	vpdevice {
2944Sbill 	short	plbcr;
301903Swnj 	short	pbxaddr;
3144Sbill 	short	prbcr;
323184Swnj 	u_short pbaddr;
3344Sbill 	short	plcsr;
3444Sbill 	short	plbuf;
3544Sbill 	short	prcsr;
363184Swnj 	u_short prbuf;
3744Sbill };
3844Sbill 
393184Swnj #define	VP_ERROR	0100000
403184Swnj #define	VP_DTCINTR	0040000
413184Swnj #define	VP_DMAACT	0020000
423184Swnj #define	VP_READY	0000200
433184Swnj #define	VP_IENABLE	0000100
443184Swnj #define	VP_TERMCOM	0000040
453184Swnj #define	VP_FFCOM	0000020
463184Swnj #define	VP_EOTCOM	0000010
473184Swnj #define	VP_CLRCOM	0000004
483184Swnj #define	VP_RESET	0000002
493184Swnj #define	VP_SPP		0000001
5044Sbill 
513184Swnj struct vp_softc {
523184Swnj 	int	sc_state;
533184Swnj 	int	sc_count;
543184Swnj 	int	sc_bufp;
553184Swnj 	struct	buf *sc_bp;
563184Swnj 	int	sc_ubinfo;
573184Swnj } vp_softc[NVP];
5844Sbill 
593184Swnj /* sc_state bits */
603184Swnj #define	VPSC_BUSY	0001000
613184Swnj #define	VPSC_MODE	0000700
623184Swnj #define	VPSC_SPP	0000400
633184Swnj #define	VPSC_PLOT	0000200
643184Swnj #define	VPSC_PRINT	0000100
653184Swnj #define	VPSC_CMNDS	0000076
663184Swnj #define	VPSC_OPEN	0000001
6744Sbill 
683184Swnj struct	uba_device *vpdinfo[NVP];
6944Sbill 
703184Swnj #define	VPUNIT(dev)	(minor(dev))
713184Swnj 
723184Swnj struct	buf rvpbuf[NVP];
733184Swnj 
743184Swnj int	vpprobe(), vpattach();
753184Swnj struct	uba_device *vpdinfo[NVP];
763184Swnj u_short	vpstd[] = { 0777500, 0 };
773184Swnj struct	uba_driver vpdriver =
783184Swnj     { vpprobe, 0, vpattach, 0, vpstd, "vp", vpdinfo };
793184Swnj 
803184Swnj vpprobe(reg)
813184Swnj 	caddr_t reg;
8244Sbill {
833184Swnj 	register int br, cvec;		/* value-result */
843184Swnj 	register struct vpdevice *vpaddr = (struct vpdevice *)(reg-010);
8544Sbill 
863184Swnj 	vpaddr->prcsr = VP_IENABLE|VP_DTCINTR;
873184Swnj 	vpaddr->pbaddr = 0;
883184Swnj 	vpaddr->pbxaddr = 0;
89*3439Swnj 	vpaddr->prbcr = 1;
903184Swnj 	DELAY(10000);
913184Swnj 	vpaddr->prcsr = 0;
92*3439Swnj #ifdef ERNIE
93*3439Swnj 	/* UNTIL REWIRED, GET INTERRUPT AT 200 BUT WANT 174 */
94*3439Swnj 	if (cvec == 0200) {
95*3439Swnj 		printf("vp reset vec from 200 to 174\n");
96*3439Swnj 		cvec = 0174;
97*3439Swnj 	}
98*3439Swnj #endif
993184Swnj }
1003184Swnj 
1013184Swnj /*ARGSUSED*/
1023184Swnj vpattach(ui)
1033184Swnj 	struct uba_device *ui;
1043184Swnj {
1053184Swnj 
1063184Swnj 	ui->ui_addr -= 010;
1073184Swnj 	ui->ui_physaddr -= 010;
1083184Swnj }
1093184Swnj 
1103184Swnj vpopen(dev)
1113184Swnj 	dev_t dev;
1123184Swnj {
1133184Swnj 	register struct vp_softc *sc;
1143184Swnj 	register struct vpdevice *vpaddr;
1153184Swnj 	register struct uba_device *ui;
1163184Swnj 
1173184Swnj 	if (VPUNIT(dev) >= NVP ||
1183184Swnj 	    ((sc = &vp_softc[minor(dev)])->sc_state&VPSC_OPEN) ||
1193184Swnj 	    (ui = vpdinfo[VPUNIT(dev)]) == 0 || ui->ui_alive == 0) {
12044Sbill 		u.u_error = ENXIO;
12144Sbill 		return;
12244Sbill 	}
1233184Swnj 	vpaddr = (struct vpdevice *)ui->ui_addr;
1243184Swnj 	sc->sc_state = VPSC_OPEN|VPSC_PRINT | VP_CLRCOM|VP_RESET;
1253184Swnj 	sc->sc_count = 0;
1263184Swnj 	vpaddr->prcsr = VP_IENABLE|VP_DTCINTR;
1273184Swnj 	vptimo(dev);
1283184Swnj 	while (sc->sc_state & VPSC_CMNDS) {
129134Sbill 		(void) spl4();
1303184Swnj 		if (vpwait(dev)) {
1313184Swnj 			vpclose(dev);
13244Sbill 			u.u_error = EIO;
13344Sbill 			return;
13444Sbill 		}
1353184Swnj 		vpstart(dev);
136134Sbill 		(void) spl0();
13744Sbill 	}
13844Sbill }
13944Sbill 
14044Sbill vpstrategy(bp)
14144Sbill 	register struct buf *bp;
14244Sbill {
14344Sbill 	register int e;
1443184Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(bp->b_dev)];
1453184Swnj 	register struct uba_device *ui = vpdinfo[VPUNIT(bp->b_dev)];
1463184Swnj 	register struct vpdevice *vpaddr = (struct vpdevice *)ui->ui_addr;
14744Sbill 
148134Sbill 	(void) spl4();
1493184Swnj 	while (sc->sc_state & VPSC_BUSY)
1503184Swnj 		sleep((caddr_t)sc, VPPRI);
1513184Swnj 	sc->sc_state |= VPSC_BUSY;
1523184Swnj 	sc->sc_bp = bp;
1533184Swnj 	sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP);
1543184Swnj 	if (e = vpwait(bp->b_dev))
15544Sbill 		goto brkout;
1563184Swnj 	sc->sc_count = bp->b_bcount;
1573184Swnj 	vpstart(bp->b_dev);
1583184Swnj 	while (((sc->sc_state&VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr) & VP_DMAACT)
1593184Swnj 		sleep((caddr_t)sc, VPPRI);
1603184Swnj 	sc->sc_count = 0;
1613184Swnj 	if ((sc->sc_state&VPSC_MODE) == VPSC_SPP)
1623184Swnj 		sc->sc_state = (sc->sc_state &~ VPSC_MODE) | VPSC_PLOT;
163134Sbill 	(void) spl0();
16444Sbill brkout:
1653184Swnj 	ubarelse(ui->ui_ubanum, &sc->sc_ubinfo);
1663184Swnj 	sc->sc_state &= ~VPSC_BUSY;
1673184Swnj 	sc->sc_bp = 0;
16844Sbill 	iodone(bp);
16944Sbill 	if (e)
17044Sbill 		u.u_error = EIO;
1713184Swnj 	wakeup((caddr_t)sc);
17244Sbill }
17344Sbill 
17444Sbill int	vpblock = 16384;
17544Sbill 
17644Sbill unsigned
17744Sbill minvpph(bp)
1783184Swnj 	struct buf *bp;
17944Sbill {
18044Sbill 
18144Sbill 	if (bp->b_bcount > vpblock)
18244Sbill 		bp->b_bcount = vpblock;
18344Sbill }
18444Sbill 
18544Sbill /*ARGSUSED*/
18644Sbill vpwrite(dev)
1873184Swnj 	dev_t dev;
18844Sbill {
18944Sbill 
1903184Swnj 	physio(vpstrategy, &rvpbuf[VPUNIT(dev)], dev, B_WRITE, minvpph);
19144Sbill }
19244Sbill 
1933184Swnj vpwait(dev)
1943184Swnj 	dev_t dev;
19544Sbill {
1963184Swnj 	register struct vpdevice *vpaddr =
1973184Swnj 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
1983184Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
1993184Swnj 	register int e;
20044Sbill 
2013184Swnj 	for (;;) {
2023184Swnj 		e = (sc->sc_state & VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr;
2033184Swnj 		if (e & (VP_READY|VP_ERROR))
2043184Swnj 			break;
2053184Swnj 		sleep((caddr_t)sc, VPPRI);
2063184Swnj 	}
2073184Swnj 	/* I wish i could tell whether an error indicated an npr timeout */
2083184Swnj 	return (e & VP_ERROR);
20944Sbill }
21044Sbill 
2113184Swnj vpstart(dev)
2123184Swnj 	dev_t;
21344Sbill {
2143184Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
2153184Swnj 	register struct vpdevice *vpaddr =
2163184Swnj 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
2173184Swnj 	short bit;
21844Sbill 
2193184Swnj 	if (sc->sc_count) {
2203184Swnj 		vpaddr->pbaddr = sc->sc_ubinfo;
2213184Swnj 		vpaddr->pbxaddr = (sc->sc_ubinfo>>12)&0x30;
2223184Swnj 		if (sc->sc_state & (VPSC_PRINT|VPSC_SPP))
2233184Swnj 			vpaddr->prbcr = sc->sc_count;
22444Sbill 		else
2253184Swnj 			vpaddr->plbcr = sc->sc_count;
22644Sbill 		return;
22744Sbill 	}
22844Sbill 	for (bit = 1; bit != 0; bit <<= 1)
2293184Swnj 		if (sc->sc_state&bit&VPSC_CMNDS) {
2303184Swnj 			vpaddr->plcsr |= bit;
2313184Swnj 			sc->sc_state &= ~bit;
23244Sbill 			return;
23344Sbill 		}
23444Sbill }
23544Sbill 
23644Sbill /*ARGSUSED*/
23744Sbill vpioctl(dev, cmd, addr, flag)
2383184Swnj 	dev_t dev;
2393184Swnj 	int cmd;
24044Sbill 	register caddr_t addr;
2413184Swnj 	int flag;
24244Sbill {
24344Sbill 	register int m;
2443184Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
2453184Swnj 	register struct vpdevice *vpaddr =
2463184Swnj 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
24744Sbill 
24844Sbill 	switch (cmd) {
24944Sbill 
2503184Swnj 	case VGETSTATE:
2513184Swnj 		(void) suword(addr, sc->sc_state);
25244Sbill 		return;
25344Sbill 
2543184Swnj 	case VSETSTATE:
25544Sbill 		m = fuword(addr);
25644Sbill 		if (m == -1) {
25744Sbill 			u.u_error = EFAULT;
25844Sbill 			return;
25944Sbill 		}
2603184Swnj 		sc->sc_state =
2613184Swnj 		    (sc->sc_state & ~VPSC_MODE) | (m&(VPSC_MODE|VPSC_CMNDS));
26244Sbill 		break;
26344Sbill 
26444Sbill 	default:
26544Sbill 		u.u_error = ENOTTY;
26644Sbill 		return;
26744Sbill 	}
268134Sbill 	(void) spl4();
2693184Swnj 	(void) vpwait(dev);
2703184Swnj 	if (sc->sc_state&VPSC_SPP)
2713184Swnj 		vpaddr->plcsr |= VP_SPP;
27244Sbill 	else
2733184Swnj 		vpaddr->plcsr &= ~VP_SPP;
2743184Swnj 	sc->sc_count = 0;
2753184Swnj 	while (sc->sc_state & VPSC_CMNDS) {
2763184Swnj 		(void) vpwait(dev);
2773184Swnj 		vpstart(dev);
27844Sbill 	}
279134Sbill 	(void) spl0();
28044Sbill }
28144Sbill 
2823184Swnj vptimo(dev)
2833184Swnj 	dev_t dev;
28444Sbill {
2853184Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
28644Sbill 
2873184Swnj 	if (sc->sc_state&VPSC_OPEN)
2883184Swnj 		timeout(vptimo, (caddr_t)dev, hz/10);
2893184Swnj 	vpintr(dev);
29044Sbill }
29144Sbill 
29244Sbill /*ARGSUSED*/
29344Sbill vpintr(dev)
2943184Swnj 	dev_t dev;
29544Sbill {
2963184Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
29744Sbill 
2983184Swnj 	wakeup((caddr_t)sc);
29944Sbill }
30044Sbill 
3013184Swnj vpclose(dev)
3023184Swnj 	dev_t dev;
30344Sbill {
3043184Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
3053184Swnj 	register struct vpdevice *vpaddr =
3063184Swnj 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
30744Sbill 
3083184Swnj 	sc->sc_state = 0;
3093184Swnj 	sc->sc_count = 0;
3103184Swnj 	vpaddr->plcsr = 0;
31144Sbill }
312288Sbill 
3133184Swnj vpreset(uban)
3143184Swnj 	int uban;
315288Sbill {
3163184Swnj 	register int vp11;
3173184Swnj 	register struct uba_device *ui;
3183184Swnj 	register struct vp_softc *sc = vp_softc;
3193184Swnj 	register struct vpdevice *vpaddr;
320288Sbill 
3213184Swnj 	for (vp11 = 0; vp11 < NVP; vp11++, sc++) {
3223184Swnj 		if ((ui = vpdinfo[vp11]) == 0 || ui->ui_alive == 0 ||
3233184Swnj 		    ui->ui_ubanum != uban || (sc->sc_state&VPSC_OPEN) == 0)
3243184Swnj 			continue;
3253184Swnj 		printf(" vp%d", vp11);
3263184Swnj 		vpaddr = (struct vpdevice *)ui->ui_addr;
3273184Swnj 		vpaddr->prcsr = VP_IENABLE|VP_DTCINTR;
3283184Swnj 		if ((sc->sc_state & VPSC_BUSY) == 0)
3293184Swnj 			continue;
3303184Swnj 		if (sc->sc_ubinfo) {
3313184Swnj 			printf("<%d>", (sc->sc_ubinfo>>28)&0xf);
3323184Swnj 			ubarelse(ui->ui_ubanum, &sc->sc_ubinfo);
3333184Swnj 		}
3343184Swnj 		sc->sc_count = sc->sc_bp->b_bcount;
3353184Swnj 		vpstart(sc->sc_bp->b_dev);
336288Sbill 	}
337288Sbill }
3381565Sbill #endif
339