xref: /original-bsd/sys/vax/uba/vp.c (revision 1a7b9a25)
1*1a7b9a25Ssam /*	vp.c	4.22	82/12/17	*/
2b177495dSbill 
316a40936Swnj #include "vp.h"
47d993dedSbill #if NVP > 0
57d993dedSbill /*
67d993dedSbill  * Versatec matrix printer/plotter
77d993dedSbill  * dma interface driver
83a2852a0Swnj  *
93a2852a0Swnj  * SETUP NOTES:
103a2852a0Swnj  *	Set up both print and plot interrupts to go through the same vector
113a2852a0Swnj  *	Give the address of the plcsr register in the config specification
127d993dedSbill  */
13*1a7b9a25Ssam #include "../machine/pte.h"
14*1a7b9a25Ssam 
15b177495dSbill #include "../h/param.h"
16b177495dSbill #include "../h/dir.h"
17b177495dSbill #include "../h/user.h"
18b177495dSbill #include "../h/buf.h"
19b177495dSbill #include "../h/systm.h"
20b177495dSbill #include "../h/map.h"
212d065d45Swnj #include "../h/vcmd.h"
228ad11d3dSroot #include "../h/uio.h"
23b177495dSbill 
24b1c32dd2Sroot #include "../vaxuba/ubavar.h"
25b1c32dd2Sroot #include "../vaxuba/ubareg.h"
26b1c32dd2Sroot 
27b177495dSbill unsigned minvpph();
28b177495dSbill 
29b177495dSbill #define	VPPRI	(PZERO-1)
30b177495dSbill 
312d065d45Swnj struct	vpdevice {
32b177495dSbill 	short	plbcr;
33f87bbbe0Swnj 	short	pbxaddr;
34b177495dSbill 	short	prbcr;
352d065d45Swnj 	u_short pbaddr;
36b177495dSbill 	short	plcsr;
37b177495dSbill 	short	plbuf;
38b177495dSbill 	short	prcsr;
392d065d45Swnj 	u_short prbuf;
40b177495dSbill };
41b177495dSbill 
422d065d45Swnj #define	VP_ERROR	0100000
432d065d45Swnj #define	VP_DTCINTR	0040000
442d065d45Swnj #define	VP_DMAACT	0020000
452d065d45Swnj #define	VP_READY	0000200
462d065d45Swnj #define	VP_IENABLE	0000100
472d065d45Swnj #define	VP_TERMCOM	0000040
482d065d45Swnj #define	VP_FFCOM	0000020
492d065d45Swnj #define	VP_EOTCOM	0000010
502d065d45Swnj #define	VP_CLRCOM	0000004
512d065d45Swnj #define	VP_RESET	0000002
522d065d45Swnj #define	VP_SPP		0000001
53b177495dSbill 
542d065d45Swnj struct vp_softc {
552d065d45Swnj 	int	sc_state;
562d065d45Swnj 	int	sc_count;
572d065d45Swnj 	int	sc_bufp;
582d065d45Swnj 	struct	buf *sc_bp;
592d065d45Swnj 	int	sc_ubinfo;
602d065d45Swnj } vp_softc[NVP];
61b177495dSbill 
622d065d45Swnj /* sc_state bits */
632d065d45Swnj #define	VPSC_BUSY	0001000
642d065d45Swnj #define	VPSC_MODE	0000700
652d065d45Swnj #define	VPSC_SPP	0000400
662d065d45Swnj #define	VPSC_PLOT	0000200
672d065d45Swnj #define	VPSC_PRINT	0000100
682d065d45Swnj #define	VPSC_CMNDS	0000076
692d065d45Swnj #define	VPSC_OPEN	0000001
70b177495dSbill 
712d065d45Swnj struct	uba_device *vpdinfo[NVP];
72b177495dSbill 
732d065d45Swnj #define	VPUNIT(dev)	(minor(dev))
742d065d45Swnj 
752d065d45Swnj struct	buf rvpbuf[NVP];
762d065d45Swnj 
772d065d45Swnj int	vpprobe(), vpattach();
782d065d45Swnj struct	uba_device *vpdinfo[NVP];
792d065d45Swnj u_short	vpstd[] = { 0777500, 0 };
802d065d45Swnj struct	uba_driver vpdriver =
812d065d45Swnj     { vpprobe, 0, vpattach, 0, vpstd, "vp", vpdinfo };
822d065d45Swnj 
832d065d45Swnj vpprobe(reg)
842d065d45Swnj 	caddr_t reg;
852d065d45Swnj {
862d065d45Swnj 	register int br, cvec;		/* value-result */
872d065d45Swnj 	register struct vpdevice *vpaddr = (struct vpdevice *)(reg-010);
882d065d45Swnj 
89acc57956Swnj #ifdef lint
90acc57956Swnj 	br = 0; cvec = br; br = cvec;
91acc57956Swnj 	vpintr(0);
92acc57956Swnj #endif
932d065d45Swnj 	vpaddr->prcsr = VP_IENABLE|VP_DTCINTR;
942d065d45Swnj 	vpaddr->pbaddr = 0;
952d065d45Swnj 	vpaddr->pbxaddr = 0;
963a2852a0Swnj 	vpaddr->prbcr = 1;
972d065d45Swnj 	DELAY(10000);
982d065d45Swnj 	vpaddr->prcsr = 0;
992fc095daSsam #if ERNIE || CAD || UCBVAX
1003a2852a0Swnj 	/* UNTIL REWIRED, GET INTERRUPT AT 200 BUT WANT 174 */
1013a2852a0Swnj 	if (cvec == 0200) {
1023a2852a0Swnj 		printf("vp reset vec from 200 to 174\n");
1033a2852a0Swnj 		cvec = 0174;
1043a2852a0Swnj 	}
1053a2852a0Swnj #endif
1064c931468Skre 	return (sizeof (struct vpdevice));
1072d065d45Swnj }
1082d065d45Swnj 
1092d065d45Swnj /*ARGSUSED*/
1102d065d45Swnj vpattach(ui)
1112d065d45Swnj 	struct uba_device *ui;
112b177495dSbill {
113b177495dSbill 
1142d065d45Swnj 	ui->ui_addr -= 010;
1152d065d45Swnj 	ui->ui_physaddr -= 010;
1162d065d45Swnj }
1172d065d45Swnj 
1182d065d45Swnj vpopen(dev)
1192d065d45Swnj 	dev_t dev;
1202d065d45Swnj {
1212d065d45Swnj 	register struct vp_softc *sc;
1222d065d45Swnj 	register struct vpdevice *vpaddr;
1232d065d45Swnj 	register struct uba_device *ui;
1242d065d45Swnj 
1252d065d45Swnj 	if (VPUNIT(dev) >= NVP ||
1262d065d45Swnj 	    ((sc = &vp_softc[minor(dev)])->sc_state&VPSC_OPEN) ||
127855a1f9dSroot 	    (ui = vpdinfo[VPUNIT(dev)]) == 0 || ui->ui_alive == 0)
128855a1f9dSroot 		return (ENXIO);
1292d065d45Swnj 	vpaddr = (struct vpdevice *)ui->ui_addr;
1302d065d45Swnj 	sc->sc_state = VPSC_OPEN|VPSC_PRINT | VP_CLRCOM|VP_RESET;
1312d065d45Swnj 	sc->sc_count = 0;
1322d065d45Swnj 	vpaddr->prcsr = VP_IENABLE|VP_DTCINTR;
1332d065d45Swnj 	vptimo(dev);
1342d065d45Swnj 	while (sc->sc_state & VPSC_CMNDS) {
135bea55ee8Sbill 		(void) spl4();
1362d065d45Swnj 		if (vpwait(dev)) {
1372d065d45Swnj 			vpclose(dev);
138855a1f9dSroot 			return (EIO);
139b177495dSbill 		}
1402d065d45Swnj 		vpstart(dev);
141bea55ee8Sbill 		(void) spl0();
142b177495dSbill 	}
143855a1f9dSroot 	return (0);
144b177495dSbill }
145b177495dSbill 
146b177495dSbill vpstrategy(bp)
147b177495dSbill 	register struct buf *bp;
148b177495dSbill {
149b177495dSbill 	register int e;
1502d065d45Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(bp->b_dev)];
1512d065d45Swnj 	register struct uba_device *ui = vpdinfo[VPUNIT(bp->b_dev)];
1522d065d45Swnj 	register struct vpdevice *vpaddr = (struct vpdevice *)ui->ui_addr;
153b177495dSbill 
154bea55ee8Sbill 	(void) spl4();
1552d065d45Swnj 	while (sc->sc_state & VPSC_BUSY)
1562d065d45Swnj 		sleep((caddr_t)sc, VPPRI);
1572d065d45Swnj 	sc->sc_state |= VPSC_BUSY;
1582d065d45Swnj 	sc->sc_bp = bp;
1592d065d45Swnj 	sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP);
1602d065d45Swnj 	if (e = vpwait(bp->b_dev))
161b177495dSbill 		goto brkout;
1622d065d45Swnj 	sc->sc_count = bp->b_bcount;
1632d065d45Swnj 	vpstart(bp->b_dev);
1642d065d45Swnj 	while (((sc->sc_state&VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr) & VP_DMAACT)
1652d065d45Swnj 		sleep((caddr_t)sc, VPPRI);
1662d065d45Swnj 	sc->sc_count = 0;
1672d065d45Swnj 	if ((sc->sc_state&VPSC_MODE) == VPSC_SPP)
1682d065d45Swnj 		sc->sc_state = (sc->sc_state &~ VPSC_MODE) | VPSC_PLOT;
169bea55ee8Sbill 	(void) spl0();
170b177495dSbill brkout:
1712d065d45Swnj 	ubarelse(ui->ui_ubanum, &sc->sc_ubinfo);
1722d065d45Swnj 	sc->sc_state &= ~VPSC_BUSY;
1732d065d45Swnj 	sc->sc_bp = 0;
174b177495dSbill 	if (e)
175738f6459Sroot 		bp->b_flags |= B_ERROR;
176738f6459Sroot 	iodone(bp);
1772d065d45Swnj 	wakeup((caddr_t)sc);
178b177495dSbill }
179b177495dSbill 
180b177495dSbill int	vpblock = 16384;
181b177495dSbill 
182b177495dSbill unsigned
183b177495dSbill minvpph(bp)
184b177495dSbill 	struct buf *bp;
185b177495dSbill {
186b177495dSbill 
187b177495dSbill 	if (bp->b_bcount > vpblock)
188b177495dSbill 		bp->b_bcount = vpblock;
189b177495dSbill }
190b177495dSbill 
191b177495dSbill /*ARGSUSED*/
192731660efSroot vpwrite(dev, uio)
1932d065d45Swnj 	dev_t dev;
194731660efSroot 	struct uio *uio;
195b177495dSbill {
196b177495dSbill 
197ea492ea6Sroot 	if (VPUNIT(dev) >= NVP)
198731660efSroot 		return (ENXIO);
199731660efSroot 	return (physio(vpstrategy, &rvpbuf[VPUNIT(dev)], dev, B_WRITE,
200731660efSroot 		    minvpph, uio));
201b177495dSbill }
202b177495dSbill 
2032d065d45Swnj vpwait(dev)
2042d065d45Swnj 	dev_t dev;
205b177495dSbill {
2062d065d45Swnj 	register struct vpdevice *vpaddr =
2072d065d45Swnj 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
2082d065d45Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
2092d065d45Swnj 	register int e;
210b177495dSbill 
2112d065d45Swnj 	for (;;) {
2122d065d45Swnj 		e = (sc->sc_state & VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr;
2132d065d45Swnj 		if (e & (VP_READY|VP_ERROR))
2142d065d45Swnj 			break;
2152d065d45Swnj 		sleep((caddr_t)sc, VPPRI);
2162d065d45Swnj 	}
217738f6459Sroot 	/* I WISH I COULD TELL WHETHER AN ERROR INDICATED AN NPR TIMEOUT */
2182d065d45Swnj 	return (e & VP_ERROR);
219b177495dSbill }
220b177495dSbill 
2212d065d45Swnj vpstart(dev)
2222d065d45Swnj 	dev_t;
223b177495dSbill {
2242d065d45Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
2252d065d45Swnj 	register struct vpdevice *vpaddr =
2262d065d45Swnj 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
2272d065d45Swnj 	short bit;
228b177495dSbill 
2292d065d45Swnj 	if (sc->sc_count) {
2302d065d45Swnj 		vpaddr->pbaddr = sc->sc_ubinfo;
2312d065d45Swnj 		vpaddr->pbxaddr = (sc->sc_ubinfo>>12)&0x30;
2322d065d45Swnj 		if (sc->sc_state & (VPSC_PRINT|VPSC_SPP))
2332d065d45Swnj 			vpaddr->prbcr = sc->sc_count;
234b177495dSbill 		else
2352d065d45Swnj 			vpaddr->plbcr = sc->sc_count;
236b177495dSbill 		return;
237b177495dSbill 	}
238b177495dSbill 	for (bit = 1; bit != 0; bit <<= 1)
2392d065d45Swnj 		if (sc->sc_state&bit&VPSC_CMNDS) {
2402d065d45Swnj 			vpaddr->plcsr |= bit;
2412d065d45Swnj 			sc->sc_state &= ~bit;
242b177495dSbill 			return;
243b177495dSbill 		}
244b177495dSbill }
245b177495dSbill 
246b177495dSbill /*ARGSUSED*/
247b177495dSbill vpioctl(dev, cmd, addr, flag)
2482d065d45Swnj 	dev_t dev;
2492d065d45Swnj 	int cmd;
250b177495dSbill 	register caddr_t addr;
2512d065d45Swnj 	int flag;
252b177495dSbill {
253b177495dSbill 	register int m;
2542d065d45Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
2552d065d45Swnj 	register struct vpdevice *vpaddr =
2562d065d45Swnj 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
257b177495dSbill 
258b177495dSbill 	switch (cmd) {
259b177495dSbill 
2602d065d45Swnj 	case VGETSTATE:
2612d065d45Swnj 		(void) suword(addr, sc->sc_state);
262855a1f9dSroot 		break;
263b177495dSbill 
2642d065d45Swnj 	case VSETSTATE:
265b177495dSbill 		m = fuword(addr);
266855a1f9dSroot 		if (m == -1)
267855a1f9dSroot 			return (EFAULT);
2682d065d45Swnj 		sc->sc_state =
2692d065d45Swnj 		    (sc->sc_state & ~VPSC_MODE) | (m&(VPSC_MODE|VPSC_CMNDS));
270b177495dSbill 		break;
271b177495dSbill 
272b177495dSbill 	default:
273855a1f9dSroot 		return (ENOTTY);
274b177495dSbill 	}
275bea55ee8Sbill 	(void) spl4();
2762d065d45Swnj 	(void) vpwait(dev);
2772d065d45Swnj 	if (sc->sc_state&VPSC_SPP)
2782d065d45Swnj 		vpaddr->plcsr |= VP_SPP;
279b177495dSbill 	else
2802d065d45Swnj 		vpaddr->plcsr &= ~VP_SPP;
2812d065d45Swnj 	sc->sc_count = 0;
2822d065d45Swnj 	while (sc->sc_state & VPSC_CMNDS) {
2832d065d45Swnj 		(void) vpwait(dev);
2842d065d45Swnj 		vpstart(dev);
285b177495dSbill 	}
286bea55ee8Sbill 	(void) spl0();
287855a1f9dSroot 	return (0);
288b177495dSbill }
289b177495dSbill 
2902d065d45Swnj vptimo(dev)
2912d065d45Swnj 	dev_t dev;
292b177495dSbill {
2932d065d45Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
294b177495dSbill 
2952d065d45Swnj 	if (sc->sc_state&VPSC_OPEN)
2962d065d45Swnj 		timeout(vptimo, (caddr_t)dev, hz/10);
2972d065d45Swnj 	vpintr(dev);
298b177495dSbill }
299b177495dSbill 
300b177495dSbill /*ARGSUSED*/
301b177495dSbill vpintr(dev)
3022d065d45Swnj 	dev_t dev;
303b177495dSbill {
3042d065d45Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
305b177495dSbill 
3062d065d45Swnj 	wakeup((caddr_t)sc);
307b177495dSbill }
308b177495dSbill 
3092d065d45Swnj vpclose(dev)
3102d065d45Swnj 	dev_t dev;
311b177495dSbill {
3122d065d45Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
3132d065d45Swnj 	register struct vpdevice *vpaddr =
3142d065d45Swnj 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
315b177495dSbill 
3162d065d45Swnj 	sc->sc_state = 0;
3172d065d45Swnj 	sc->sc_count = 0;
3182d065d45Swnj 	vpaddr->plcsr = 0;
319b177495dSbill }
320bd93d430Sbill 
3212d065d45Swnj vpreset(uban)
3222d065d45Swnj 	int uban;
323bd93d430Sbill {
3242d065d45Swnj 	register int vp11;
3252d065d45Swnj 	register struct uba_device *ui;
3262d065d45Swnj 	register struct vp_softc *sc = vp_softc;
3272d065d45Swnj 	register struct vpdevice *vpaddr;
328bd93d430Sbill 
3292d065d45Swnj 	for (vp11 = 0; vp11 < NVP; vp11++, sc++) {
3302d065d45Swnj 		if ((ui = vpdinfo[vp11]) == 0 || ui->ui_alive == 0 ||
3312d065d45Swnj 		    ui->ui_ubanum != uban || (sc->sc_state&VPSC_OPEN) == 0)
3322d065d45Swnj 			continue;
3332d065d45Swnj 		printf(" vp%d", vp11);
3342d065d45Swnj 		vpaddr = (struct vpdevice *)ui->ui_addr;
3352d065d45Swnj 		vpaddr->prcsr = VP_IENABLE|VP_DTCINTR;
3362d065d45Swnj 		if ((sc->sc_state & VPSC_BUSY) == 0)
3372d065d45Swnj 			continue;
338855a1f9dSroot 		sc->sc_ubinfo = 0;
3392d065d45Swnj 		sc->sc_count = sc->sc_bp->b_bcount;
3402d065d45Swnj 		vpstart(sc->sc_bp->b_dev);
3412d065d45Swnj 	}
342bd93d430Sbill }
343bc3f32ddSsam 
344bc3f32ddSsam vpselect()
345bc3f32ddSsam {
346bc3f32ddSsam 	return (1);
347bc3f32ddSsam }
3487d993dedSbill #endif
349