xref: /csrg-svn/sys/vax/uba/vp.c (revision 18611)
1*18611Skarels /*	vp.c	6.5	85/04/10	*/
244Sbill 
31939Swnj #include "vp.h"
41565Sbill #if NVP > 0
51565Sbill /*
61565Sbill  * Versatec matrix printer/plotter
71565Sbill  * dma interface driver
83439Swnj  *
93439Swnj  * SETUP NOTES:
103439Swnj  *	Set up both print and plot interrupts to go through the same vector
1115074Skarels  *	(or kludge probe to reset second vector to first;
1215074Skarels  *	default 174/200 is already handled).
133439Swnj  *	Give the address of the plcsr register in the config specification
141565Sbill  */
159785Ssam #include "../machine/pte.h"
169785Ssam 
1717086Sbloom #include "param.h"
1817086Sbloom #include "dir.h"
1917086Sbloom #include "user.h"
2017086Sbloom #include "buf.h"
2117086Sbloom #include "systm.h"
2217086Sbloom #include "map.h"
2317086Sbloom #include "ioctl.h"
2417086Sbloom #include "vcmd.h"
2517086Sbloom #include "uio.h"
2617086Sbloom #include "kernel.h"
2744Sbill 
2817086Sbloom #include "ubavar.h"
2917086Sbloom #include "ubareg.h"
308484Sroot 
3144Sbill unsigned minvpph();
3244Sbill 
3315074Skarels #define	VPPRI	(PZERO-1)
3415074Skarels 
3515074Skarels struct	vpdevice {
3615074Skarels 	short	plbcr;
3715074Skarels 	short	pbxaddr;
3815074Skarels 	short	prbcr;
3915074Skarels 	u_short pbaddr;
4015074Skarels 	short	plcsr;
4115074Skarels 	short	plbuf;
4215074Skarels 	short	prcsr;
4315074Skarels 	u_short prbuf;
4415074Skarels };
4515074Skarels 
4615074Skarels #define	VP_ERROR	0100000
4715074Skarels #define	VP_DTCINTR	0040000
4815074Skarels #define	VP_DMAACT	0020000
4915074Skarels #define	VP_READY	0000200
5015074Skarels #define	VP_IENABLE	0000100
5115074Skarels #define	VP_TERMCOM	0000040
5215074Skarels #define	VP_FFCOM	0000020
5315074Skarels #define	VP_EOTCOM	0000010
5415074Skarels #define	VP_CLRCOM	0000004
5515074Skarels #define	VP_RESET	0000002
5615074Skarels #define	VP_SPP		0000001
5715074Skarels 
583184Swnj struct vp_softc {
593184Swnj 	int	sc_state;
603184Swnj 	int	sc_count;
6115074Skarels 	int	sc_bufp;
6215074Skarels 	struct	buf *sc_bp;
6315074Skarels 	int	sc_ubinfo;
643184Swnj } vp_softc[NVP];
6544Sbill 
663184Swnj /* sc_state bits */
6715074Skarels #define	VPSC_BUSY	0001000
683184Swnj #define	VPSC_MODE	0000700
6915074Skarels #define	VPSC_SPP	0000400
7015074Skarels #define	VPSC_PLOT	0000200
7115074Skarels #define	VPSC_PRINT	0000100
723184Swnj #define	VPSC_CMNDS	0000076
7315074Skarels #define	VPSC_OPEN	0000001
7444Sbill 
753184Swnj struct	uba_device *vpdinfo[NVP];
7644Sbill 
773184Swnj #define	VPUNIT(dev)	(minor(dev))
783184Swnj 
793184Swnj struct	buf rvpbuf[NVP];
803184Swnj 
8115074Skarels int	vpprobe(), vpattach();
823184Swnj struct	uba_device *vpdinfo[NVP];
833184Swnj u_short	vpstd[] = { 0777500, 0 };
843184Swnj struct	uba_driver vpdriver =
8515074Skarels     { vpprobe, 0, vpattach, 0, vpstd, "vp", vpdinfo };
863184Swnj 
873184Swnj vpprobe(reg)
883184Swnj 	caddr_t reg;
8944Sbill {
903184Swnj 	register int br, cvec;		/* value-result */
913184Swnj 	register struct vpdevice *vpaddr = (struct vpdevice *)(reg-010);
9244Sbill 
934942Swnj #ifdef lint
944942Swnj 	br = 0; cvec = br; br = cvec;
954942Swnj 	vpintr(0);
964942Swnj #endif
973184Swnj 	vpaddr->prcsr = VP_IENABLE|VP_DTCINTR;
983184Swnj 	vpaddr->pbaddr = 0;
993184Swnj 	vpaddr->pbxaddr = 0;
1003439Swnj 	vpaddr->prbcr = 1;
1013184Swnj 	DELAY(10000);
1023184Swnj 	vpaddr->prcsr = 0;
10315074Skarels 	/* GET INTERRUPT AT SECOND VECTOR BUT WANT FIRST */
1043439Swnj 	if (cvec == 0200) {
1053439Swnj 		printf("vp reset vec from 200 to 174\n");
1063439Swnj 		cvec = 0174;
1073439Swnj 	}
1087408Skre 	return (sizeof (struct vpdevice));
1093184Swnj }
1103184Swnj 
1113184Swnj /*ARGSUSED*/
1123184Swnj vpattach(ui)
1133184Swnj 	struct uba_device *ui;
1143184Swnj {
1153184Swnj 
1163184Swnj 	ui->ui_addr -= 010;
1173184Swnj 	ui->ui_physaddr -= 010;
1183184Swnj }
1193184Swnj 
1203184Swnj vpopen(dev)
1213184Swnj 	dev_t dev;
1223184Swnj {
1233184Swnj 	register struct vp_softc *sc;
1243184Swnj 	register struct vpdevice *vpaddr;
1253184Swnj 	register struct uba_device *ui;
1263184Swnj 
12715074Skarels 	if (VPUNIT(dev) >= NVP ||
12815074Skarels 	    ((sc = &vp_softc[minor(dev)])->sc_state&VPSC_OPEN) ||
12915074Skarels 	    (ui = vpdinfo[VPUNIT(dev)]) == 0 || ui->ui_alive == 0)
1308578Sroot 		return (ENXIO);
1313184Swnj 	vpaddr = (struct vpdevice *)ui->ui_addr;
13215074Skarels 	sc->sc_state = VPSC_OPEN|VPSC_PRINT | VP_CLRCOM|VP_RESET;
13315074Skarels 	sc->sc_count = 0;
1343184Swnj 	vpaddr->prcsr = VP_IENABLE|VP_DTCINTR;
13515074Skarels 	vptimo(dev);
13615074Skarels 	while (sc->sc_state & VPSC_CMNDS) {
13715074Skarels 		(void) spl4();
13815074Skarels 		if (vpwait(dev)) {
13915074Skarels 			vpclose(dev);
14015074Skarels 			return (EIO);
14115074Skarels 		}
14215074Skarels 		vpstart(dev);
14315074Skarels 		(void) spl0();
14415074Skarels 	}
14515074Skarels 	return (0);
14644Sbill }
14744Sbill 
14844Sbill vpstrategy(bp)
14944Sbill 	register struct buf *bp;
15044Sbill {
15115074Skarels 	register int e;
1523184Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(bp->b_dev)];
1533184Swnj 	register struct uba_device *ui = vpdinfo[VPUNIT(bp->b_dev)];
1543184Swnj 	register struct vpdevice *vpaddr = (struct vpdevice *)ui->ui_addr;
15544Sbill 
15615074Skarels 	(void) spl4();
15715074Skarels 	while (sc->sc_state & VPSC_BUSY)
15815074Skarels 		sleep((caddr_t)sc, VPPRI);
15915074Skarels 	sc->sc_state |= VPSC_BUSY;
16015074Skarels 	sc->sc_bp = bp;
16115074Skarels 	sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP);
16215074Skarels 	if (e = vpwait(bp->b_dev))
16315074Skarels 		goto brkout;
16415074Skarels 	sc->sc_count = bp->b_bcount;
16515074Skarels 	vpstart(bp->b_dev);
16615074Skarels 	while (((sc->sc_state&VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr) & VP_DMAACT)
16715074Skarels 		sleep((caddr_t)sc, VPPRI);
16815074Skarels 	sc->sc_count = 0;
16915074Skarels 	if ((sc->sc_state&VPSC_MODE) == VPSC_SPP)
17015074Skarels 		sc->sc_state = (sc->sc_state &~ VPSC_MODE) | VPSC_PLOT;
17115074Skarels 	(void) spl0();
17215074Skarels brkout:
17315074Skarels 	ubarelse(ui->ui_ubanum, &sc->sc_ubinfo);
17415074Skarels 	sc->sc_state &= ~VPSC_BUSY;
17515074Skarels 	sc->sc_bp = 0;
17615074Skarels 	if (e)
1778494Sroot 		bp->b_flags |= B_ERROR;
17815074Skarels 	iodone(bp);
17915074Skarels 	wakeup((caddr_t)sc);
18044Sbill }
18144Sbill 
18244Sbill int	vpblock = 16384;
18344Sbill 
18444Sbill unsigned
18544Sbill minvpph(bp)
1863184Swnj 	struct buf *bp;
18744Sbill {
18844Sbill 
18944Sbill 	if (bp->b_bcount > vpblock)
19044Sbill 		bp->b_bcount = vpblock;
19144Sbill }
19244Sbill 
19344Sbill /*ARGSUSED*/
1948168Sroot vpwrite(dev, uio)
1953184Swnj 	dev_t dev;
1968168Sroot 	struct uio *uio;
19744Sbill {
19844Sbill 
1997848Sroot 	if (VPUNIT(dev) >= NVP)
2008168Sroot 		return (ENXIO);
2018168Sroot 	return (physio(vpstrategy, &rvpbuf[VPUNIT(dev)], dev, B_WRITE,
2028168Sroot 		    minvpph, uio));
20344Sbill }
20444Sbill 
20515074Skarels vpwait(dev)
20615074Skarels 	dev_t dev;
20744Sbill {
20815074Skarels 	register struct vpdevice *vpaddr =
20915074Skarels 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
21015074Skarels 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
21115074Skarels 	register int e;
21244Sbill 
21315074Skarels 	for (;;) {
21415074Skarels 		e = (sc->sc_state & VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr;
21515074Skarels 		if (e & (VP_READY|VP_ERROR))
21615074Skarels 			break;
21715074Skarels 		sleep((caddr_t)sc, VPPRI);
21815074Skarels 	}
21915074Skarels 	/* I WISH I COULD TELL WHETHER AN ERROR INDICATED AN NPR TIMEOUT */
22015074Skarels 	return (e & VP_ERROR);
22144Sbill }
22244Sbill 
22315074Skarels vpstart(dev)
22415074Skarels 	dev_t;
22544Sbill {
22615074Skarels 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
22715074Skarels 	register struct vpdevice *vpaddr =
22815074Skarels 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
22915074Skarels 	short bit;
23044Sbill 
2313184Swnj 	if (sc->sc_count) {
23215074Skarels 		vpaddr->pbaddr = sc->sc_ubinfo;
23315074Skarels 		vpaddr->pbxaddr = (sc->sc_ubinfo>>12)&0x30;
23415074Skarels 		if (sc->sc_state & (VPSC_PRINT|VPSC_SPP))
2353184Swnj 			vpaddr->prbcr = sc->sc_count;
23644Sbill 		else
2373184Swnj 			vpaddr->plbcr = sc->sc_count;
23815074Skarels 		return;
23944Sbill 	}
24015074Skarels 	for (bit = 1; bit != 0; bit <<= 1)
24115074Skarels 		if (sc->sc_state&bit&VPSC_CMNDS) {
24215074Skarels 			vpaddr->plcsr |= bit;
24315074Skarels 			sc->sc_state &= ~bit;
24415074Skarels 			return;
24515074Skarels 		}
24644Sbill }
24744Sbill 
24844Sbill /*ARGSUSED*/
24911815Ssam vpioctl(dev, cmd, data, flag)
25015074Skarels 	dev_t dev;
25115074Skarels 	int cmd;
25211815Ssam 	register caddr_t data;
25315074Skarels 	int flag;
25444Sbill {
25515074Skarels 	register int m;
2563184Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
25715074Skarels 	register struct vpdevice *vpaddr =
25815074Skarels 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
25944Sbill 
26044Sbill 	switch (cmd) {
26144Sbill 
2623184Swnj 	case VGETSTATE:
26311815Ssam 		*(int *)data = sc->sc_state;
264*18611Skarels 		return (0);
26544Sbill 
2663184Swnj 	case VSETSTATE:
26715074Skarels 		sc->sc_state =
26815074Skarels 		    (sc->sc_state & ~VPSC_MODE) |
26915074Skarels 		    ((*(int *)data) & (VPSC_MODE|VPSC_CMNDS));
27015074Skarels 		break;
27144Sbill 
27244Sbill 	default:
2738578Sroot 		return (ENOTTY);
27444Sbill 	}
27515074Skarels 	(void) spl4();
27615074Skarels 	(void) vpwait(dev);
27715074Skarels 	if (sc->sc_state&VPSC_SPP)
27815074Skarels 		vpaddr->plcsr |= VP_SPP;
27915074Skarels 	else
28015074Skarels 		vpaddr->plcsr &= ~VP_SPP;
28115074Skarels 	sc->sc_count = 0;
28215074Skarels 	while (sc->sc_state & VPSC_CMNDS) {
28315074Skarels 		(void) vpwait(dev);
28415074Skarels 		vpstart(dev);
28544Sbill 	}
28615074Skarels 	(void) spl0();
2878578Sroot 	return (0);
28844Sbill }
28944Sbill 
2903184Swnj vptimo(dev)
2913184Swnj 	dev_t dev;
29244Sbill {
2933184Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
29444Sbill 
29515074Skarels 	if (sc->sc_state&VPSC_OPEN)
29615074Skarels 		timeout(vptimo, (caddr_t)dev, hz/10);
2973184Swnj 	vpintr(dev);
29844Sbill }
29944Sbill 
30044Sbill /*ARGSUSED*/
30144Sbill vpintr(dev)
3023184Swnj 	dev_t dev;
30344Sbill {
30415074Skarels 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
30544Sbill 
30615074Skarels 	wakeup((caddr_t)sc);
30744Sbill }
30844Sbill 
3093184Swnj vpclose(dev)
3103184Swnj 	dev_t dev;
31144Sbill {
3123184Swnj 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
3133184Swnj 	register struct vpdevice *vpaddr =
3143184Swnj 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
31544Sbill 
3163184Swnj 	sc->sc_state = 0;
31715074Skarels 	sc->sc_count = 0;
3183184Swnj 	vpaddr->plcsr = 0;
31944Sbill }
320288Sbill 
3213184Swnj vpreset(uban)
3223184Swnj 	int uban;
323288Sbill {
3243184Swnj 	register int vp11;
32515074Skarels 	register struct uba_device *ui;
32615074Skarels 	register struct vp_softc *sc = vp_softc;
3273184Swnj 	register struct vpdevice *vpaddr;
328288Sbill 
3293184Swnj 	for (vp11 = 0; vp11 < NVP; vp11++, sc++) {
33015074Skarels 		if ((ui = vpdinfo[vp11]) == 0 || ui->ui_alive == 0 ||
33115074Skarels 		    ui->ui_ubanum != uban || (sc->sc_state&VPSC_OPEN) == 0)
3323184Swnj 			continue;
3333184Swnj 		printf(" vp%d", vp11);
33415074Skarels 		vpaddr = (struct vpdevice *)ui->ui_addr;
3353184Swnj 		vpaddr->prcsr = VP_IENABLE|VP_DTCINTR;
33615074Skarels 		if ((sc->sc_state & VPSC_BUSY) == 0)
33715074Skarels 			continue;
33815074Skarels 		sc->sc_ubinfo = 0;
33915074Skarels 		sc->sc_count = sc->sc_bp->b_bcount;
34015074Skarels 		vpstart(sc->sc_bp->b_dev);
341288Sbill 	}
342288Sbill }
3436432Ssam 
3446432Ssam vpselect()
3456432Ssam {
3466432Ssam 	return (1);
3476432Ssam }
3481565Sbill #endif
349