xref: /csrg-svn/sys/vax/uba/vp.c (revision 45810)
123362Smckusick /*
229260Smckusick  * Copyright (c) 1982, 1986 Regents of the University of California.
323362Smckusick  * All rights reserved.  The Berkeley software License Agreement
423362Smckusick  * specifies the terms and conditions for redistribution.
523362Smckusick  *
6*45810Sbostic  *	@(#)vp.c	7.5 (Berkeley) 12/16/90
723362Smckusick  */
844Sbill 
91939Swnj #include "vp.h"
101565Sbill #if NVP > 0
111565Sbill /*
121565Sbill  * Versatec matrix printer/plotter
131565Sbill  * dma interface driver
143439Swnj  *
153439Swnj  * SETUP NOTES:
163439Swnj  *	Set up both print and plot interrupts to go through the same vector
1715074Skarels  *	(or kludge probe to reset second vector to first;
1815074Skarels  *	default 174/200 is already handled).
193439Swnj  *	Give the address of the plcsr register in the config specification
201565Sbill  */
21*45810Sbostic #include "../include/pte.h"
229785Ssam 
23*45810Sbostic #include "sys/param.h"
24*45810Sbostic #include "sys/user.h"
25*45810Sbostic #include "sys/buf.h"
26*45810Sbostic #include "sys/systm.h"
27*45810Sbostic #include "sys/map.h"
28*45810Sbostic #include "sys/ioctl.h"
29*45810Sbostic #include "sys/vcmd.h"
30*45810Sbostic #include "sys/uio.h"
31*45810Sbostic #include "sys/kernel.h"
3244Sbill 
3317086Sbloom #include "ubavar.h"
3417086Sbloom #include "ubareg.h"
358484Sroot 
3644Sbill unsigned minvpph();
3744Sbill 
3815074Skarels #define	VPPRI	(PZERO-1)
3915074Skarels 
4015074Skarels struct	vpdevice {
4115074Skarels 	short	plbcr;
4215074Skarels 	short	pbxaddr;
4315074Skarels 	short	prbcr;
4415074Skarels 	u_short pbaddr;
4515074Skarels 	short	plcsr;
4615074Skarels 	short	plbuf;
4715074Skarels 	short	prcsr;
4815074Skarels 	u_short prbuf;
4915074Skarels };
5015074Skarels 
5115074Skarels #define	VP_ERROR	0100000
5215074Skarels #define	VP_DTCINTR	0040000
5315074Skarels #define	VP_DMAACT	0020000
5415074Skarels #define	VP_READY	0000200
5515074Skarels #define	VP_IENABLE	0000100
5615074Skarels #define	VP_TERMCOM	0000040
5715074Skarels #define	VP_FFCOM	0000020
5815074Skarels #define	VP_EOTCOM	0000010
5915074Skarels #define	VP_CLRCOM	0000004
6015074Skarels #define	VP_RESET	0000002
6115074Skarels #define	VP_SPP		0000001
6215074Skarels 
633184Swnj struct vp_softc {
643184Swnj 	int	sc_state;
653184Swnj 	int	sc_count;
6615074Skarels 	int	sc_bufp;
6715074Skarels 	struct	buf *sc_bp;
6815074Skarels 	int	sc_ubinfo;
693184Swnj } vp_softc[NVP];
7044Sbill 
713184Swnj /* sc_state bits */
7215074Skarels #define	VPSC_BUSY	0001000
733184Swnj #define	VPSC_MODE	0000700
7415074Skarels #define	VPSC_SPP	0000400
7515074Skarels #define	VPSC_PLOT	0000200
7615074Skarels #define	VPSC_PRINT	0000100
773184Swnj #define	VPSC_CMNDS	0000076
7815074Skarels #define	VPSC_OPEN	0000001
7944Sbill 
803184Swnj struct	uba_device *vpdinfo[NVP];
8144Sbill 
823184Swnj #define	VPUNIT(dev)	(minor(dev))
833184Swnj 
843184Swnj struct	buf rvpbuf[NVP];
853184Swnj 
8615074Skarels int	vpprobe(), vpattach();
873184Swnj struct	uba_device *vpdinfo[NVP];
883184Swnj u_short	vpstd[] = { 0777500, 0 };
893184Swnj struct	uba_driver vpdriver =
9015074Skarels     { vpprobe, 0, vpattach, 0, vpstd, "vp", vpdinfo };
913184Swnj 
vpprobe(reg)923184Swnj vpprobe(reg)
933184Swnj 	caddr_t reg;
9444Sbill {
953184Swnj 	register int br, cvec;		/* value-result */
963184Swnj 	register struct vpdevice *vpaddr = (struct vpdevice *)(reg-010);
9744Sbill 
984942Swnj #ifdef lint
994942Swnj 	br = 0; cvec = br; br = cvec;
1004942Swnj 	vpintr(0);
1014942Swnj #endif
1023184Swnj 	vpaddr->prcsr = VP_IENABLE|VP_DTCINTR;
1033184Swnj 	vpaddr->pbaddr = 0;
1043184Swnj 	vpaddr->pbxaddr = 0;
1053439Swnj 	vpaddr->prbcr = 1;
1063184Swnj 	DELAY(10000);
1073184Swnj 	vpaddr->prcsr = 0;
10815074Skarels 	/* GET INTERRUPT AT SECOND VECTOR BUT WANT FIRST */
1093439Swnj 	if (cvec == 0200) {
1103439Swnj 		printf("vp reset vec from 200 to 174\n");
1113439Swnj 		cvec = 0174;
1123439Swnj 	}
1137408Skre 	return (sizeof (struct vpdevice));
1143184Swnj }
1153184Swnj 
1163184Swnj /*ARGSUSED*/
1173184Swnj vpattach(ui)
1183184Swnj 	struct uba_device *ui;
1193184Swnj {
1203184Swnj 
1213184Swnj 	ui->ui_addr -= 010;
1223184Swnj 	ui->ui_physaddr -= 010;
1233184Swnj }
1243184Swnj 
vpopen(dev)1253184Swnj vpopen(dev)
1263184Swnj 	dev_t dev;
1273184Swnj {
1283184Swnj 	register struct vp_softc *sc;
1293184Swnj 	register struct vpdevice *vpaddr;
1303184Swnj 	register struct uba_device *ui;
1313184Swnj 
13215074Skarels 	if (VPUNIT(dev) >= NVP ||
13315074Skarels 	    ((sc = &vp_softc[minor(dev)])->sc_state&VPSC_OPEN) ||
13415074Skarels 	    (ui = vpdinfo[VPUNIT(dev)]) == 0 || ui->ui_alive == 0)
1358578Sroot 		return (ENXIO);
1363184Swnj 	vpaddr = (struct vpdevice *)ui->ui_addr;
13715074Skarels 	sc->sc_state = VPSC_OPEN|VPSC_PRINT | VP_CLRCOM|VP_RESET;
13815074Skarels 	sc->sc_count = 0;
1393184Swnj 	vpaddr->prcsr = VP_IENABLE|VP_DTCINTR;
14015074Skarels 	vptimo(dev);
14115074Skarels 	while (sc->sc_state & VPSC_CMNDS) {
14215074Skarels 		(void) spl4();
14315074Skarels 		if (vpwait(dev)) {
14440728Skarels 			(void) vpclose(dev);
14515074Skarels 			return (EIO);
14615074Skarels 		}
14715074Skarels 		vpstart(dev);
14815074Skarels 		(void) spl0();
14915074Skarels 	}
15015074Skarels 	return (0);
15144Sbill }
15244Sbill 
vpstrategy(bp)15344Sbill vpstrategy(bp)
15444Sbill 	register struct buf *bp;
15544Sbill {
15615074Skarels 	register int e;
1573184Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(bp->b_dev)];
1583184Swnj 	register struct uba_device *ui = vpdinfo[VPUNIT(bp->b_dev)];
1593184Swnj 	register struct vpdevice *vpaddr = (struct vpdevice *)ui->ui_addr;
16044Sbill 
16115074Skarels 	(void) spl4();
16215074Skarels 	while (sc->sc_state & VPSC_BUSY)
16315074Skarels 		sleep((caddr_t)sc, VPPRI);
16415074Skarels 	sc->sc_state |= VPSC_BUSY;
16515074Skarels 	sc->sc_bp = bp;
16615074Skarels 	sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP);
16715074Skarels 	if (e = vpwait(bp->b_dev))
16815074Skarels 		goto brkout;
16915074Skarels 	sc->sc_count = bp->b_bcount;
17015074Skarels 	vpstart(bp->b_dev);
17115074Skarels 	while (((sc->sc_state&VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr) & VP_DMAACT)
17215074Skarels 		sleep((caddr_t)sc, VPPRI);
17315074Skarels 	sc->sc_count = 0;
17415074Skarels 	if ((sc->sc_state&VPSC_MODE) == VPSC_SPP)
17515074Skarels 		sc->sc_state = (sc->sc_state &~ VPSC_MODE) | VPSC_PLOT;
17615074Skarels 	(void) spl0();
17715074Skarels brkout:
17815074Skarels 	ubarelse(ui->ui_ubanum, &sc->sc_ubinfo);
17915074Skarels 	sc->sc_state &= ~VPSC_BUSY;
18015074Skarels 	sc->sc_bp = 0;
18115074Skarels 	if (e)
1828494Sroot 		bp->b_flags |= B_ERROR;
18315074Skarels 	iodone(bp);
18415074Skarels 	wakeup((caddr_t)sc);
18544Sbill }
18644Sbill 
18744Sbill int	vpblock = 16384;
18844Sbill 
18944Sbill unsigned
minvpph(bp)19044Sbill minvpph(bp)
1913184Swnj 	struct buf *bp;
19244Sbill {
19344Sbill 
19444Sbill 	if (bp->b_bcount > vpblock)
19544Sbill 		bp->b_bcount = vpblock;
19644Sbill }
19744Sbill 
19844Sbill /*ARGSUSED*/
vpwrite(dev,uio)1998168Sroot vpwrite(dev, uio)
2003184Swnj 	dev_t dev;
2018168Sroot 	struct uio *uio;
20244Sbill {
20344Sbill 
2047848Sroot 	if (VPUNIT(dev) >= NVP)
2058168Sroot 		return (ENXIO);
2068168Sroot 	return (physio(vpstrategy, &rvpbuf[VPUNIT(dev)], dev, B_WRITE,
2078168Sroot 		    minvpph, uio));
20844Sbill }
20944Sbill 
vpwait(dev)21015074Skarels vpwait(dev)
21115074Skarels 	dev_t dev;
21244Sbill {
21315074Skarels 	register struct vpdevice *vpaddr =
21415074Skarels 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
21515074Skarels 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
21615074Skarels 	register int e;
21744Sbill 
21815074Skarels 	for (;;) {
21915074Skarels 		e = (sc->sc_state & VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr;
22015074Skarels 		if (e & (VP_READY|VP_ERROR))
22115074Skarels 			break;
22215074Skarels 		sleep((caddr_t)sc, VPPRI);
22315074Skarels 	}
22415074Skarels 	/* I WISH I COULD TELL WHETHER AN ERROR INDICATED AN NPR TIMEOUT */
22515074Skarels 	return (e & VP_ERROR);
22644Sbill }
22744Sbill 
22815074Skarels vpstart(dev)
22915074Skarels 	dev_t;
23044Sbill {
23115074Skarels 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
23215074Skarels 	register struct vpdevice *vpaddr =
23315074Skarels 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
23415074Skarels 	short bit;
23544Sbill 
2363184Swnj 	if (sc->sc_count) {
23715074Skarels 		vpaddr->pbaddr = sc->sc_ubinfo;
23815074Skarels 		vpaddr->pbxaddr = (sc->sc_ubinfo>>12)&0x30;
23915074Skarels 		if (sc->sc_state & (VPSC_PRINT|VPSC_SPP))
2403184Swnj 			vpaddr->prbcr = sc->sc_count;
24144Sbill 		else
2423184Swnj 			vpaddr->plbcr = sc->sc_count;
24315074Skarels 		return;
24444Sbill 	}
24515074Skarels 	for (bit = 1; bit != 0; bit <<= 1)
24615074Skarels 		if (sc->sc_state&bit&VPSC_CMNDS) {
24715074Skarels 			vpaddr->plcsr |= bit;
24815074Skarels 			sc->sc_state &= ~bit;
24915074Skarels 			return;
25015074Skarels 		}
25144Sbill }
25244Sbill 
25344Sbill /*ARGSUSED*/
vpioctl(dev,cmd,data,flag)25411815Ssam vpioctl(dev, cmd, data, flag)
25515074Skarels 	dev_t dev;
25615074Skarels 	int cmd;
25711815Ssam 	register caddr_t data;
25815074Skarels 	int flag;
25944Sbill {
2603184Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
26115074Skarels 	register struct vpdevice *vpaddr =
26215074Skarels 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
26344Sbill 
26444Sbill 	switch (cmd) {
26544Sbill 
2663184Swnj 	case VGETSTATE:
26711815Ssam 		*(int *)data = sc->sc_state;
26818611Skarels 		return (0);
26944Sbill 
2703184Swnj 	case VSETSTATE:
27115074Skarels 		sc->sc_state =
27215074Skarels 		    (sc->sc_state & ~VPSC_MODE) |
27315074Skarels 		    ((*(int *)data) & (VPSC_MODE|VPSC_CMNDS));
27415074Skarels 		break;
27544Sbill 
27644Sbill 	default:
2778578Sroot 		return (ENOTTY);
27844Sbill 	}
27915074Skarels 	(void) spl4();
28015074Skarels 	(void) vpwait(dev);
28115074Skarels 	if (sc->sc_state&VPSC_SPP)
28215074Skarels 		vpaddr->plcsr |= VP_SPP;
28315074Skarels 	else
28415074Skarels 		vpaddr->plcsr &= ~VP_SPP;
28515074Skarels 	sc->sc_count = 0;
28615074Skarels 	while (sc->sc_state & VPSC_CMNDS) {
28715074Skarels 		(void) vpwait(dev);
28815074Skarels 		vpstart(dev);
28944Sbill 	}
29015074Skarels 	(void) spl0();
2918578Sroot 	return (0);
29244Sbill }
29344Sbill 
vptimo(dev)2943184Swnj vptimo(dev)
2953184Swnj 	dev_t dev;
29644Sbill {
2973184Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
29844Sbill 
29915074Skarels 	if (sc->sc_state&VPSC_OPEN)
30015074Skarels 		timeout(vptimo, (caddr_t)dev, hz/10);
3013184Swnj 	vpintr(dev);
30244Sbill }
30344Sbill 
30444Sbill /*ARGSUSED*/
vpintr(dev)30544Sbill vpintr(dev)
3063184Swnj 	dev_t dev;
30744Sbill {
30815074Skarels 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
30944Sbill 
31015074Skarels 	wakeup((caddr_t)sc);
31144Sbill }
31244Sbill 
vpclose(dev)3133184Swnj vpclose(dev)
3143184Swnj 	dev_t dev;
31544Sbill {
3163184Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
3173184Swnj 	register struct vpdevice *vpaddr =
3183184Swnj 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
31944Sbill 
3203184Swnj 	sc->sc_state = 0;
32115074Skarels 	sc->sc_count = 0;
3223184Swnj 	vpaddr->plcsr = 0;
32340728Skarels 	return (0);
32444Sbill }
325288Sbill 
vpreset(uban)3263184Swnj vpreset(uban)
3273184Swnj 	int uban;
328288Sbill {
3293184Swnj 	register int vp11;
33015074Skarels 	register struct uba_device *ui;
33115074Skarels 	register struct vp_softc *sc = vp_softc;
3323184Swnj 	register struct vpdevice *vpaddr;
333288Sbill 
3343184Swnj 	for (vp11 = 0; vp11 < NVP; vp11++, sc++) {
33515074Skarels 		if ((ui = vpdinfo[vp11]) == 0 || ui->ui_alive == 0 ||
33615074Skarels 		    ui->ui_ubanum != uban || (sc->sc_state&VPSC_OPEN) == 0)
3373184Swnj 			continue;
3383184Swnj 		printf(" vp%d", vp11);
33915074Skarels 		vpaddr = (struct vpdevice *)ui->ui_addr;
3403184Swnj 		vpaddr->prcsr = VP_IENABLE|VP_DTCINTR;
34115074Skarels 		if ((sc->sc_state & VPSC_BUSY) == 0)
34215074Skarels 			continue;
34315074Skarels 		sc->sc_ubinfo = 0;
34415074Skarels 		sc->sc_count = sc->sc_bp->b_bcount;
34515074Skarels 		vpstart(sc->sc_bp->b_dev);
346288Sbill 	}
347288Sbill }
3486432Ssam 
vpselect()3496432Ssam vpselect()
3506432Ssam {
3516432Ssam 	return (1);
3526432Ssam }
3531565Sbill #endif
354