xref: /original-bsd/sys/vax/uba/vp.c (revision 2ff170e0)
1f01caa4dSmckusick /*
25e4c29cfSmckusick  * Copyright (c) 1982, 1986 Regents of the University of California.
3f01caa4dSmckusick  * All rights reserved.  The Berkeley software License Agreement
4f01caa4dSmckusick  * specifies the terms and conditions for redistribution.
5f01caa4dSmckusick  *
6*2ff170e0Sbostic  *	@(#)vp.c	7.5 (Berkeley) 12/16/90
7f01caa4dSmckusick  */
8b177495dSbill 
916a40936Swnj #include "vp.h"
107d993dedSbill #if NVP > 0
117d993dedSbill /*
127d993dedSbill  * Versatec matrix printer/plotter
137d993dedSbill  * dma interface driver
143a2852a0Swnj  *
153a2852a0Swnj  * SETUP NOTES:
163a2852a0Swnj  *	Set up both print and plot interrupts to go through the same vector
17dd7ba7e3Skarels  *	(or kludge probe to reset second vector to first;
18dd7ba7e3Skarels  *	default 174/200 is already handled).
193a2852a0Swnj  *	Give the address of the plcsr register in the config specification
207d993dedSbill  */
21*2ff170e0Sbostic #include "../include/pte.h"
221a7b9a25Ssam 
23*2ff170e0Sbostic #include "sys/param.h"
24*2ff170e0Sbostic #include "sys/user.h"
25*2ff170e0Sbostic #include "sys/buf.h"
26*2ff170e0Sbostic #include "sys/systm.h"
27*2ff170e0Sbostic #include "sys/map.h"
28*2ff170e0Sbostic #include "sys/ioctl.h"
29*2ff170e0Sbostic #include "sys/vcmd.h"
30*2ff170e0Sbostic #include "sys/uio.h"
31*2ff170e0Sbostic #include "sys/kernel.h"
32b177495dSbill 
337aac53c4Sbloom #include "ubavar.h"
347aac53c4Sbloom #include "ubareg.h"
35b1c32dd2Sroot 
36b177495dSbill unsigned minvpph();
37b177495dSbill 
38dd7ba7e3Skarels #define	VPPRI	(PZERO-1)
39dd7ba7e3Skarels 
40dd7ba7e3Skarels struct	vpdevice {
41dd7ba7e3Skarels 	short	plbcr;
42dd7ba7e3Skarels 	short	pbxaddr;
43dd7ba7e3Skarels 	short	prbcr;
44dd7ba7e3Skarels 	u_short pbaddr;
45dd7ba7e3Skarels 	short	plcsr;
46dd7ba7e3Skarels 	short	plbuf;
47dd7ba7e3Skarels 	short	prcsr;
48dd7ba7e3Skarels 	u_short prbuf;
49dd7ba7e3Skarels };
50dd7ba7e3Skarels 
51dd7ba7e3Skarels #define	VP_ERROR	0100000
52dd7ba7e3Skarels #define	VP_DTCINTR	0040000
53dd7ba7e3Skarels #define	VP_DMAACT	0020000
54dd7ba7e3Skarels #define	VP_READY	0000200
55dd7ba7e3Skarels #define	VP_IENABLE	0000100
56dd7ba7e3Skarels #define	VP_TERMCOM	0000040
57dd7ba7e3Skarels #define	VP_FFCOM	0000020
58dd7ba7e3Skarels #define	VP_EOTCOM	0000010
59dd7ba7e3Skarels #define	VP_CLRCOM	0000004
60dd7ba7e3Skarels #define	VP_RESET	0000002
61dd7ba7e3Skarels #define	VP_SPP		0000001
62dd7ba7e3Skarels 
632d065d45Swnj struct vp_softc {
642d065d45Swnj 	int	sc_state;
652d065d45Swnj 	int	sc_count;
66dd7ba7e3Skarels 	int	sc_bufp;
67dd7ba7e3Skarels 	struct	buf *sc_bp;
68dd7ba7e3Skarels 	int	sc_ubinfo;
692d065d45Swnj } vp_softc[NVP];
70b177495dSbill 
712d065d45Swnj /* sc_state bits */
72dd7ba7e3Skarels #define	VPSC_BUSY	0001000
732d065d45Swnj #define	VPSC_MODE	0000700
74dd7ba7e3Skarels #define	VPSC_SPP	0000400
75dd7ba7e3Skarels #define	VPSC_PLOT	0000200
76dd7ba7e3Skarels #define	VPSC_PRINT	0000100
772d065d45Swnj #define	VPSC_CMNDS	0000076
78dd7ba7e3Skarels #define	VPSC_OPEN	0000001
79b177495dSbill 
802d065d45Swnj struct	uba_device *vpdinfo[NVP];
81b177495dSbill 
822d065d45Swnj #define	VPUNIT(dev)	(minor(dev))
832d065d45Swnj 
842d065d45Swnj struct	buf rvpbuf[NVP];
852d065d45Swnj 
86dd7ba7e3Skarels int	vpprobe(), vpattach();
872d065d45Swnj struct	uba_device *vpdinfo[NVP];
882d065d45Swnj u_short	vpstd[] = { 0777500, 0 };
892d065d45Swnj struct	uba_driver vpdriver =
90dd7ba7e3Skarels     { vpprobe, 0, vpattach, 0, vpstd, "vp", vpdinfo };
912d065d45Swnj 
vpprobe(reg)922d065d45Swnj vpprobe(reg)
932d065d45Swnj 	caddr_t reg;
942d065d45Swnj {
952d065d45Swnj 	register int br, cvec;		/* value-result */
962d065d45Swnj 	register struct vpdevice *vpaddr = (struct vpdevice *)(reg-010);
972d065d45Swnj 
98acc57956Swnj #ifdef lint
99acc57956Swnj 	br = 0; cvec = br; br = cvec;
100acc57956Swnj 	vpintr(0);
101acc57956Swnj #endif
1022d065d45Swnj 	vpaddr->prcsr = VP_IENABLE|VP_DTCINTR;
1032d065d45Swnj 	vpaddr->pbaddr = 0;
1042d065d45Swnj 	vpaddr->pbxaddr = 0;
1053a2852a0Swnj 	vpaddr->prbcr = 1;
1062d065d45Swnj 	DELAY(10000);
1072d065d45Swnj 	vpaddr->prcsr = 0;
108dd7ba7e3Skarels 	/* GET INTERRUPT AT SECOND VECTOR BUT WANT FIRST */
1093a2852a0Swnj 	if (cvec == 0200) {
1103a2852a0Swnj 		printf("vp reset vec from 200 to 174\n");
1113a2852a0Swnj 		cvec = 0174;
1123a2852a0Swnj 	}
1134c931468Skre 	return (sizeof (struct vpdevice));
1142d065d45Swnj }
1152d065d45Swnj 
1162d065d45Swnj /*ARGSUSED*/
1172d065d45Swnj vpattach(ui)
1182d065d45Swnj 	struct uba_device *ui;
119b177495dSbill {
120b177495dSbill 
1212d065d45Swnj 	ui->ui_addr -= 010;
1222d065d45Swnj 	ui->ui_physaddr -= 010;
1232d065d45Swnj }
1242d065d45Swnj 
vpopen(dev)1252d065d45Swnj vpopen(dev)
1262d065d45Swnj 	dev_t dev;
1272d065d45Swnj {
1282d065d45Swnj 	register struct vp_softc *sc;
1292d065d45Swnj 	register struct vpdevice *vpaddr;
1302d065d45Swnj 	register struct uba_device *ui;
1312d065d45Swnj 
132dd7ba7e3Skarels 	if (VPUNIT(dev) >= NVP ||
133dd7ba7e3Skarels 	    ((sc = &vp_softc[minor(dev)])->sc_state&VPSC_OPEN) ||
134dd7ba7e3Skarels 	    (ui = vpdinfo[VPUNIT(dev)]) == 0 || ui->ui_alive == 0)
135855a1f9dSroot 		return (ENXIO);
1362d065d45Swnj 	vpaddr = (struct vpdevice *)ui->ui_addr;
137dd7ba7e3Skarels 	sc->sc_state = VPSC_OPEN|VPSC_PRINT | VP_CLRCOM|VP_RESET;
138dd7ba7e3Skarels 	sc->sc_count = 0;
1392d065d45Swnj 	vpaddr->prcsr = VP_IENABLE|VP_DTCINTR;
140dd7ba7e3Skarels 	vptimo(dev);
141dd7ba7e3Skarels 	while (sc->sc_state & VPSC_CMNDS) {
142dd7ba7e3Skarels 		(void) spl4();
143dd7ba7e3Skarels 		if (vpwait(dev)) {
1441db00297Skarels 			(void) vpclose(dev);
145dd7ba7e3Skarels 			return (EIO);
146dd7ba7e3Skarels 		}
147dd7ba7e3Skarels 		vpstart(dev);
148dd7ba7e3Skarels 		(void) spl0();
149dd7ba7e3Skarels 	}
150dd7ba7e3Skarels 	return (0);
151b177495dSbill }
152b177495dSbill 
vpstrategy(bp)153b177495dSbill vpstrategy(bp)
154b177495dSbill 	register struct buf *bp;
155b177495dSbill {
156dd7ba7e3Skarels 	register int e;
1572d065d45Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(bp->b_dev)];
1582d065d45Swnj 	register struct uba_device *ui = vpdinfo[VPUNIT(bp->b_dev)];
1592d065d45Swnj 	register struct vpdevice *vpaddr = (struct vpdevice *)ui->ui_addr;
160b177495dSbill 
161dd7ba7e3Skarels 	(void) spl4();
162dd7ba7e3Skarels 	while (sc->sc_state & VPSC_BUSY)
163dd7ba7e3Skarels 		sleep((caddr_t)sc, VPPRI);
164dd7ba7e3Skarels 	sc->sc_state |= VPSC_BUSY;
165dd7ba7e3Skarels 	sc->sc_bp = bp;
166dd7ba7e3Skarels 	sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP);
167dd7ba7e3Skarels 	if (e = vpwait(bp->b_dev))
168dd7ba7e3Skarels 		goto brkout;
169dd7ba7e3Skarels 	sc->sc_count = bp->b_bcount;
170dd7ba7e3Skarels 	vpstart(bp->b_dev);
171dd7ba7e3Skarels 	while (((sc->sc_state&VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr) & VP_DMAACT)
172dd7ba7e3Skarels 		sleep((caddr_t)sc, VPPRI);
173dd7ba7e3Skarels 	sc->sc_count = 0;
174dd7ba7e3Skarels 	if ((sc->sc_state&VPSC_MODE) == VPSC_SPP)
175dd7ba7e3Skarels 		sc->sc_state = (sc->sc_state &~ VPSC_MODE) | VPSC_PLOT;
176dd7ba7e3Skarels 	(void) spl0();
177dd7ba7e3Skarels brkout:
178dd7ba7e3Skarels 	ubarelse(ui->ui_ubanum, &sc->sc_ubinfo);
179dd7ba7e3Skarels 	sc->sc_state &= ~VPSC_BUSY;
180dd7ba7e3Skarels 	sc->sc_bp = 0;
181dd7ba7e3Skarels 	if (e)
182738f6459Sroot 		bp->b_flags |= B_ERROR;
183738f6459Sroot 	iodone(bp);
184dd7ba7e3Skarels 	wakeup((caddr_t)sc);
185b177495dSbill }
186b177495dSbill 
187b177495dSbill int	vpblock = 16384;
188b177495dSbill 
189b177495dSbill unsigned
minvpph(bp)190b177495dSbill minvpph(bp)
191b177495dSbill 	struct buf *bp;
192b177495dSbill {
193b177495dSbill 
194b177495dSbill 	if (bp->b_bcount > vpblock)
195b177495dSbill 		bp->b_bcount = vpblock;
196b177495dSbill }
197b177495dSbill 
198b177495dSbill /*ARGSUSED*/
vpwrite(dev,uio)199731660efSroot vpwrite(dev, uio)
2002d065d45Swnj 	dev_t dev;
201731660efSroot 	struct uio *uio;
202b177495dSbill {
203b177495dSbill 
204ea492ea6Sroot 	if (VPUNIT(dev) >= NVP)
205731660efSroot 		return (ENXIO);
206731660efSroot 	return (physio(vpstrategy, &rvpbuf[VPUNIT(dev)], dev, B_WRITE,
207731660efSroot 		    minvpph, uio));
208b177495dSbill }
209b177495dSbill 
vpwait(dev)210dd7ba7e3Skarels vpwait(dev)
211dd7ba7e3Skarels 	dev_t dev;
212b177495dSbill {
213dd7ba7e3Skarels 	register struct vpdevice *vpaddr =
214dd7ba7e3Skarels 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
215dd7ba7e3Skarels 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
216dd7ba7e3Skarels 	register int e;
217b177495dSbill 
218dd7ba7e3Skarels 	for (;;) {
219dd7ba7e3Skarels 		e = (sc->sc_state & VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr;
220dd7ba7e3Skarels 		if (e & (VP_READY|VP_ERROR))
221dd7ba7e3Skarels 			break;
222dd7ba7e3Skarels 		sleep((caddr_t)sc, VPPRI);
223dd7ba7e3Skarels 	}
224dd7ba7e3Skarels 	/* I WISH I COULD TELL WHETHER AN ERROR INDICATED AN NPR TIMEOUT */
225dd7ba7e3Skarels 	return (e & VP_ERROR);
2268c5eff05Ssam }
2278c5eff05Ssam 
228dd7ba7e3Skarels vpstart(dev)
229dd7ba7e3Skarels 	dev_t;
2308c5eff05Ssam {
231dd7ba7e3Skarels 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
232dd7ba7e3Skarels 	register struct vpdevice *vpaddr =
233dd7ba7e3Skarels 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
234dd7ba7e3Skarels 	short bit;
2358c5eff05Ssam 
2362d065d45Swnj 	if (sc->sc_count) {
237dd7ba7e3Skarels 		vpaddr->pbaddr = sc->sc_ubinfo;
238dd7ba7e3Skarels 		vpaddr->pbxaddr = (sc->sc_ubinfo>>12)&0x30;
239dd7ba7e3Skarels 		if (sc->sc_state & (VPSC_PRINT|VPSC_SPP))
2402d065d45Swnj 			vpaddr->prbcr = sc->sc_count;
241b177495dSbill 		else
2422d065d45Swnj 			vpaddr->plbcr = sc->sc_count;
243dd7ba7e3Skarels 		return;
244dd7ba7e3Skarels 	}
245dd7ba7e3Skarels 	for (bit = 1; bit != 0; bit <<= 1)
246dd7ba7e3Skarels 		if (sc->sc_state&bit&VPSC_CMNDS) {
247dd7ba7e3Skarels 			vpaddr->plcsr |= bit;
248dd7ba7e3Skarels 			sc->sc_state &= ~bit;
249dd7ba7e3Skarels 			return;
250b177495dSbill 		}
251b177495dSbill }
252b177495dSbill 
253b177495dSbill /*ARGSUSED*/
vpioctl(dev,cmd,data,flag)254564375aeSsam vpioctl(dev, cmd, data, flag)
255dd7ba7e3Skarels 	dev_t dev;
256dd7ba7e3Skarels 	int cmd;
257564375aeSsam 	register caddr_t data;
258dd7ba7e3Skarels 	int flag;
259b177495dSbill {
2602d065d45Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
261dd7ba7e3Skarels 	register struct vpdevice *vpaddr =
262dd7ba7e3Skarels 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
263b177495dSbill 
264b177495dSbill 	switch (cmd) {
265b177495dSbill 
2662d065d45Swnj 	case VGETSTATE:
267564375aeSsam 		*(int *)data = sc->sc_state;
2687be9ed76Skarels 		return (0);
269b177495dSbill 
2702d065d45Swnj 	case VSETSTATE:
271dd7ba7e3Skarels 		sc->sc_state =
272dd7ba7e3Skarels 		    (sc->sc_state & ~VPSC_MODE) |
273dd7ba7e3Skarels 		    ((*(int *)data) & (VPSC_MODE|VPSC_CMNDS));
274dd7ba7e3Skarels 		break;
275b177495dSbill 
276b177495dSbill 	default:
277855a1f9dSroot 		return (ENOTTY);
278b177495dSbill 	}
279dd7ba7e3Skarels 	(void) spl4();
280dd7ba7e3Skarels 	(void) vpwait(dev);
281dd7ba7e3Skarels 	if (sc->sc_state&VPSC_SPP)
282dd7ba7e3Skarels 		vpaddr->plcsr |= VP_SPP;
2838c5eff05Ssam 	else
284dd7ba7e3Skarels 		vpaddr->plcsr &= ~VP_SPP;
285dd7ba7e3Skarels 	sc->sc_count = 0;
286dd7ba7e3Skarels 	while (sc->sc_state & VPSC_CMNDS) {
287dd7ba7e3Skarels 		(void) vpwait(dev);
288dd7ba7e3Skarels 		vpstart(dev);
2898c5eff05Ssam 	}
290dd7ba7e3Skarels 	(void) spl0();
291dd7ba7e3Skarels 	return (0);
2928c5eff05Ssam }
2938c5eff05Ssam 
vptimo(dev)2942d065d45Swnj vptimo(dev)
2952d065d45Swnj 	dev_t dev;
296b177495dSbill {
2972d065d45Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
298b177495dSbill 
299dd7ba7e3Skarels 	if (sc->sc_state&VPSC_OPEN)
300dd7ba7e3Skarels 		timeout(vptimo, (caddr_t)dev, hz/10);
3012d065d45Swnj 	vpintr(dev);
302b177495dSbill }
303b177495dSbill 
304b177495dSbill /*ARGSUSED*/
vpintr(dev)305b177495dSbill vpintr(dev)
3062d065d45Swnj 	dev_t dev;
307b177495dSbill {
308dd7ba7e3Skarels 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
309b177495dSbill 
310dd7ba7e3Skarels 	wakeup((caddr_t)sc);
311b177495dSbill }
312b177495dSbill 
vpclose(dev)3132d065d45Swnj vpclose(dev)
3142d065d45Swnj 	dev_t dev;
315b177495dSbill {
3162d065d45Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
3172d065d45Swnj 	register struct vpdevice *vpaddr =
3182d065d45Swnj 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
319b177495dSbill 
3202d065d45Swnj 	sc->sc_state = 0;
321dd7ba7e3Skarels 	sc->sc_count = 0;
3222d065d45Swnj 	vpaddr->plcsr = 0;
3231db00297Skarels 	return (0);
324b177495dSbill }
325bd93d430Sbill 
vpreset(uban)3262d065d45Swnj vpreset(uban)
3272d065d45Swnj 	int uban;
328bd93d430Sbill {
3292d065d45Swnj 	register int vp11;
330dd7ba7e3Skarels 	register struct uba_device *ui;
331dd7ba7e3Skarels 	register struct vp_softc *sc = vp_softc;
3322d065d45Swnj 	register struct vpdevice *vpaddr;
333bd93d430Sbill 
3342d065d45Swnj 	for (vp11 = 0; vp11 < NVP; vp11++, sc++) {
335dd7ba7e3Skarels 		if ((ui = vpdinfo[vp11]) == 0 || ui->ui_alive == 0 ||
336dd7ba7e3Skarels 		    ui->ui_ubanum != uban || (sc->sc_state&VPSC_OPEN) == 0)
3372d065d45Swnj 			continue;
3382d065d45Swnj 		printf(" vp%d", vp11);
339dd7ba7e3Skarels 		vpaddr = (struct vpdevice *)ui->ui_addr;
3402d065d45Swnj 		vpaddr->prcsr = VP_IENABLE|VP_DTCINTR;
341dd7ba7e3Skarels 		if ((sc->sc_state & VPSC_BUSY) == 0)
342dd7ba7e3Skarels 			continue;
343dd7ba7e3Skarels 		sc->sc_ubinfo = 0;
344dd7ba7e3Skarels 		sc->sc_count = sc->sc_bp->b_bcount;
345dd7ba7e3Skarels 		vpstart(sc->sc_bp->b_dev);
3462d065d45Swnj 	}
347bd93d430Sbill }
348bc3f32ddSsam 
vpselect()349bc3f32ddSsam vpselect()
350bc3f32ddSsam {
351bc3f32ddSsam 	return (1);
352bc3f32ddSsam }
3537d993dedSbill #endif
354