xref: /csrg-svn/sys/vax/uba/vp.c (revision 3184)
1*3184Swnj /*	vp.c	4.8	81/03/10	*/
244Sbill 
31939Swnj #include "vp.h"
41565Sbill #if NVP > 0
51565Sbill /*
61565Sbill  * Versatec matrix printer/plotter
71565Sbill  * dma interface driver
81565Sbill  */
944Sbill #include "../h/param.h"
1044Sbill #include "../h/dir.h"
1144Sbill #include "../h/user.h"
1244Sbill #include "../h/buf.h"
1344Sbill #include "../h/systm.h"
1444Sbill #include "../h/map.h"
1544Sbill #include "../h/pte.h"
16*3184Swnj #include "../h/ubavar.h"
17*3184Swnj #include "../h/ubareg.h"
18*3184Swnj #include "../h/vcmd.h"
1944Sbill 
2044Sbill unsigned minvpph();
2144Sbill 
2244Sbill #define	VPPRI	(PZERO-1)
2344Sbill 
24*3184Swnj struct	vpdevice {
2544Sbill 	short	plbcr;
261903Swnj 	short	pbxaddr;
2744Sbill 	short	prbcr;
28*3184Swnj 	u_short pbaddr;
2944Sbill 	short	plcsr;
3044Sbill 	short	plbuf;
3144Sbill 	short	prcsr;
32*3184Swnj 	u_short prbuf;
3344Sbill };
3444Sbill 
35*3184Swnj #define	VP_ERROR	0100000
36*3184Swnj #define	VP_DTCINTR	0040000
37*3184Swnj #define	VP_DMAACT	0020000
38*3184Swnj #define	VP_READY	0000200
39*3184Swnj #define	VP_IENABLE	0000100
40*3184Swnj #define	VP_TERMCOM	0000040
41*3184Swnj #define	VP_FFCOM	0000020
42*3184Swnj #define	VP_EOTCOM	0000010
43*3184Swnj #define	VP_CLRCOM	0000004
44*3184Swnj #define	VP_RESET	0000002
45*3184Swnj #define	VP_SPP		0000001
4644Sbill 
47*3184Swnj struct vp_softc {
48*3184Swnj 	int	sc_state;
49*3184Swnj 	int	sc_count;
50*3184Swnj 	int	sc_bufp;
51*3184Swnj 	struct	buf *sc_bp;
52*3184Swnj 	int	sc_ubinfo;
53*3184Swnj } vp_softc[NVP];
5444Sbill 
55*3184Swnj /* sc_state bits */
56*3184Swnj #define	VPSC_BUSY	0001000
57*3184Swnj #define	VPSC_MODE	0000700
58*3184Swnj #define	VPSC_SPP	0000400
59*3184Swnj #define	VPSC_PLOT	0000200
60*3184Swnj #define	VPSC_PRINT	0000100
61*3184Swnj #define	VPSC_CMNDS	0000076
62*3184Swnj #define	VPSC_OPEN	0000001
6344Sbill 
64*3184Swnj struct	uba_device *vpdinfo[NVP];
6544Sbill 
66*3184Swnj #define	VPUNIT(dev)	(minor(dev))
67*3184Swnj 
68*3184Swnj struct	buf rvpbuf[NVP];
69*3184Swnj 
70*3184Swnj int	vpprobe(), vpattach();
71*3184Swnj struct	uba_device *vpdinfo[NVP];
72*3184Swnj u_short	vpstd[] = { 0777500, 0 };
73*3184Swnj struct	uba_driver vpdriver =
74*3184Swnj     { vpprobe, 0, vpattach, 0, vpstd, "vp", vpdinfo };
75*3184Swnj 
76*3184Swnj vpprobe(reg)
77*3184Swnj 	caddr_t reg;
7844Sbill {
79*3184Swnj 	register int br, cvec;		/* value-result */
80*3184Swnj 	register struct vpdevice *vpaddr = (struct vpdevice *)(reg-010);
8144Sbill 
82*3184Swnj 	vpaddr->prcsr = VP_IENABLE|VP_DTCINTR;
83*3184Swnj 	vpaddr->pbaddr = 0;
84*3184Swnj 	vpaddr->pbxaddr = 0;
85*3184Swnj 	vpaddr->plbcr = 1;
86*3184Swnj 	DELAY(10000);
87*3184Swnj 	vpaddr->prcsr = 0;
88*3184Swnj }
89*3184Swnj 
90*3184Swnj /*ARGSUSED*/
91*3184Swnj vpattach(ui)
92*3184Swnj 	struct uba_device *ui;
93*3184Swnj {
94*3184Swnj 
95*3184Swnj 	ui->ui_addr -= 010;
96*3184Swnj 	ui->ui_physaddr -= 010;
97*3184Swnj }
98*3184Swnj 
99*3184Swnj vpopen(dev)
100*3184Swnj 	dev_t dev;
101*3184Swnj {
102*3184Swnj 	register struct vp_softc *sc;
103*3184Swnj 	register struct vpdevice *vpaddr;
104*3184Swnj 	register struct uba_device *ui;
105*3184Swnj 
106*3184Swnj 	if (VPUNIT(dev) >= NVP ||
107*3184Swnj 	    ((sc = &vp_softc[minor(dev)])->sc_state&VPSC_OPEN) ||
108*3184Swnj 	    (ui = vpdinfo[VPUNIT(dev)]) == 0 || ui->ui_alive == 0) {
10944Sbill 		u.u_error = ENXIO;
11044Sbill 		return;
11144Sbill 	}
112*3184Swnj 	vpaddr = (struct vpdevice *)ui->ui_addr;
113*3184Swnj 	sc->sc_state = VPSC_OPEN|VPSC_PRINT | VP_CLRCOM|VP_RESET;
114*3184Swnj 	sc->sc_count = 0;
115*3184Swnj 	vpaddr->prcsr = VP_IENABLE|VP_DTCINTR;
116*3184Swnj 	vptimo(dev);
117*3184Swnj 	while (sc->sc_state & VPSC_CMNDS) {
118134Sbill 		(void) spl4();
119*3184Swnj 		if (vpwait(dev)) {
120*3184Swnj 			vpclose(dev);
12144Sbill 			u.u_error = EIO;
12244Sbill 			return;
12344Sbill 		}
124*3184Swnj 		vpstart(dev);
125134Sbill 		(void) spl0();
12644Sbill 	}
12744Sbill }
12844Sbill 
12944Sbill vpstrategy(bp)
13044Sbill 	register struct buf *bp;
13144Sbill {
13244Sbill 	register int e;
133*3184Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(bp->b_dev)];
134*3184Swnj 	register struct uba_device *ui = vpdinfo[VPUNIT(bp->b_dev)];
135*3184Swnj 	register struct vpdevice *vpaddr = (struct vpdevice *)ui->ui_addr;
13644Sbill 
137134Sbill 	(void) spl4();
138*3184Swnj 	while (sc->sc_state & VPSC_BUSY)
139*3184Swnj 		sleep((caddr_t)sc, VPPRI);
140*3184Swnj 	sc->sc_state |= VPSC_BUSY;
141*3184Swnj 	sc->sc_bp = bp;
142*3184Swnj 	sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP);
143*3184Swnj 	if (e = vpwait(bp->b_dev))
14444Sbill 		goto brkout;
145*3184Swnj 	sc->sc_count = bp->b_bcount;
146*3184Swnj 	vpstart(bp->b_dev);
147*3184Swnj 	while (((sc->sc_state&VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr) & VP_DMAACT)
148*3184Swnj 		sleep((caddr_t)sc, VPPRI);
149*3184Swnj 	sc->sc_count = 0;
150*3184Swnj 	if ((sc->sc_state&VPSC_MODE) == VPSC_SPP)
151*3184Swnj 		sc->sc_state = (sc->sc_state &~ VPSC_MODE) | VPSC_PLOT;
152134Sbill 	(void) spl0();
15344Sbill brkout:
154*3184Swnj 	ubarelse(ui->ui_ubanum, &sc->sc_ubinfo);
155*3184Swnj 	sc->sc_state &= ~VPSC_BUSY;
156*3184Swnj 	sc->sc_bp = 0;
15744Sbill 	iodone(bp);
15844Sbill 	if (e)
15944Sbill 		u.u_error = EIO;
160*3184Swnj 	wakeup((caddr_t)sc);
16144Sbill }
16244Sbill 
16344Sbill int	vpblock = 16384;
16444Sbill 
16544Sbill unsigned
16644Sbill minvpph(bp)
167*3184Swnj 	struct buf *bp;
16844Sbill {
16944Sbill 
17044Sbill 	if (bp->b_bcount > vpblock)
17144Sbill 		bp->b_bcount = vpblock;
17244Sbill }
17344Sbill 
17444Sbill /*ARGSUSED*/
17544Sbill vpwrite(dev)
176*3184Swnj 	dev_t dev;
17744Sbill {
17844Sbill 
179*3184Swnj 	physio(vpstrategy, &rvpbuf[VPUNIT(dev)], dev, B_WRITE, minvpph);
18044Sbill }
18144Sbill 
182*3184Swnj vpwait(dev)
183*3184Swnj 	dev_t dev;
18444Sbill {
185*3184Swnj 	register struct vpdevice *vpaddr =
186*3184Swnj 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
187*3184Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
188*3184Swnj 	register int e;
18944Sbill 
190*3184Swnj 	for (;;) {
191*3184Swnj 		e = (sc->sc_state & VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr;
192*3184Swnj 		if (e & (VP_READY|VP_ERROR))
193*3184Swnj 			break;
194*3184Swnj 		sleep((caddr_t)sc, VPPRI);
195*3184Swnj 	}
196*3184Swnj 	/* I wish i could tell whether an error indicated an npr timeout */
197*3184Swnj 	return (e & VP_ERROR);
19844Sbill }
19944Sbill 
200*3184Swnj vpstart(dev)
201*3184Swnj 	dev_t;
20244Sbill {
203*3184Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
204*3184Swnj 	register struct vpdevice *vpaddr =
205*3184Swnj 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
206*3184Swnj 	short bit;
20744Sbill 
208*3184Swnj 	if (sc->sc_count) {
209*3184Swnj 		vpaddr->pbaddr = sc->sc_ubinfo;
210*3184Swnj 		vpaddr->pbxaddr = (sc->sc_ubinfo>>12)&0x30;
211*3184Swnj 		if (sc->sc_state & (VPSC_PRINT|VPSC_SPP))
212*3184Swnj 			vpaddr->prbcr = sc->sc_count;
21344Sbill 		else
214*3184Swnj 			vpaddr->plbcr = sc->sc_count;
21544Sbill 		return;
21644Sbill 	}
21744Sbill 	for (bit = 1; bit != 0; bit <<= 1)
218*3184Swnj 		if (sc->sc_state&bit&VPSC_CMNDS) {
219*3184Swnj 			vpaddr->plcsr |= bit;
220*3184Swnj 			sc->sc_state &= ~bit;
22144Sbill 			return;
22244Sbill 		}
22344Sbill }
22444Sbill 
22544Sbill /*ARGSUSED*/
22644Sbill vpioctl(dev, cmd, addr, flag)
227*3184Swnj 	dev_t dev;
228*3184Swnj 	int cmd;
22944Sbill 	register caddr_t addr;
230*3184Swnj 	int flag;
23144Sbill {
23244Sbill 	register int m;
233*3184Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
234*3184Swnj 	register struct vpdevice *vpaddr =
235*3184Swnj 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
23644Sbill 
23744Sbill 	switch (cmd) {
23844Sbill 
239*3184Swnj 	case VGETSTATE:
240*3184Swnj 		(void) suword(addr, sc->sc_state);
24144Sbill 		return;
24244Sbill 
243*3184Swnj 	case VSETSTATE:
24444Sbill 		m = fuword(addr);
24544Sbill 		if (m == -1) {
24644Sbill 			u.u_error = EFAULT;
24744Sbill 			return;
24844Sbill 		}
249*3184Swnj 		sc->sc_state =
250*3184Swnj 		    (sc->sc_state & ~VPSC_MODE) | (m&(VPSC_MODE|VPSC_CMNDS));
25144Sbill 		break;
25244Sbill 
25344Sbill 	default:
25444Sbill 		u.u_error = ENOTTY;
25544Sbill 		return;
25644Sbill 	}
257134Sbill 	(void) spl4();
258*3184Swnj 	(void) vpwait(dev);
259*3184Swnj 	if (sc->sc_state&VPSC_SPP)
260*3184Swnj 		vpaddr->plcsr |= VP_SPP;
26144Sbill 	else
262*3184Swnj 		vpaddr->plcsr &= ~VP_SPP;
263*3184Swnj 	sc->sc_count = 0;
264*3184Swnj 	while (sc->sc_state & VPSC_CMNDS) {
265*3184Swnj 		(void) vpwait(dev);
266*3184Swnj 		vpstart(dev);
26744Sbill 	}
268134Sbill 	(void) spl0();
26944Sbill }
27044Sbill 
271*3184Swnj vptimo(dev)
272*3184Swnj 	dev_t dev;
27344Sbill {
274*3184Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
27544Sbill 
276*3184Swnj 	if (sc->sc_state&VPSC_OPEN)
277*3184Swnj 		timeout(vptimo, (caddr_t)dev, hz/10);
278*3184Swnj 	vpintr(dev);
27944Sbill }
28044Sbill 
28144Sbill /*ARGSUSED*/
28244Sbill vpintr(dev)
283*3184Swnj 	dev_t dev;
28444Sbill {
285*3184Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
28644Sbill 
287*3184Swnj 	wakeup((caddr_t)sc);
28844Sbill }
28944Sbill 
290*3184Swnj vpclose(dev)
291*3184Swnj 	dev_t dev;
29244Sbill {
293*3184Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
294*3184Swnj 	register struct vpdevice *vpaddr =
295*3184Swnj 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
29644Sbill 
297*3184Swnj 	sc->sc_state = 0;
298*3184Swnj 	sc->sc_count = 0;
299*3184Swnj 	vpaddr->plcsr = 0;
30044Sbill }
301288Sbill 
302*3184Swnj vpreset(uban)
303*3184Swnj 	int uban;
304288Sbill {
305*3184Swnj 	register int vp11;
306*3184Swnj 	register struct uba_device *ui;
307*3184Swnj 	register struct vp_softc *sc = vp_softc;
308*3184Swnj 	register struct vpdevice *vpaddr;
309288Sbill 
310*3184Swnj 	for (vp11 = 0; vp11 < NVP; vp11++, sc++) {
311*3184Swnj 		if ((ui = vpdinfo[vp11]) == 0 || ui->ui_alive == 0 ||
312*3184Swnj 		    ui->ui_ubanum != uban || (sc->sc_state&VPSC_OPEN) == 0)
313*3184Swnj 			continue;
314*3184Swnj 		printf(" vp%d", vp11);
315*3184Swnj 		vpaddr = (struct vpdevice *)ui->ui_addr;
316*3184Swnj 		vpaddr->prcsr = VP_IENABLE|VP_DTCINTR;
317*3184Swnj 		if ((sc->sc_state & VPSC_BUSY) == 0)
318*3184Swnj 			continue;
319*3184Swnj 		if (sc->sc_ubinfo) {
320*3184Swnj 			printf("<%d>", (sc->sc_ubinfo>>28)&0xf);
321*3184Swnj 			ubarelse(ui->ui_ubanum, &sc->sc_ubinfo);
322*3184Swnj 		}
323*3184Swnj 		sc->sc_count = sc->sc_bp->b_bcount;
324*3184Swnj 		vpstart(sc->sc_bp->b_dev);
325288Sbill 	}
326288Sbill }
3271565Sbill #endif
328