xref: /original-bsd/sys/vax/uba/vp.c (revision 5b560bbe)
1 /*
2  * Copyright (c) 1982, 1986 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  *
6  *	@(#)vp.c	7.5 (Berkeley) 12/16/90
7  */
8 
9 #include "vp.h"
10 #if NVP > 0
11 /*
12  * Versatec matrix printer/plotter
13  * dma interface driver
14  *
15  * SETUP NOTES:
16  *	Set up both print and plot interrupts to go through the same vector
17  *	(or kludge probe to reset second vector to first;
18  *	default 174/200 is already handled).
19  *	Give the address of the plcsr register in the config specification
20  */
21 #include "../include/pte.h"
22 
23 #include "sys/param.h"
24 #include "sys/user.h"
25 #include "sys/buf.h"
26 #include "sys/systm.h"
27 #include "sys/map.h"
28 #include "sys/ioctl.h"
29 #include "sys/vcmd.h"
30 #include "sys/uio.h"
31 #include "sys/kernel.h"
32 
33 #include "ubavar.h"
34 #include "ubareg.h"
35 
36 unsigned minvpph();
37 
38 #define	VPPRI	(PZERO-1)
39 
40 struct	vpdevice {
41 	short	plbcr;
42 	short	pbxaddr;
43 	short	prbcr;
44 	u_short pbaddr;
45 	short	plcsr;
46 	short	plbuf;
47 	short	prcsr;
48 	u_short prbuf;
49 };
50 
51 #define	VP_ERROR	0100000
52 #define	VP_DTCINTR	0040000
53 #define	VP_DMAACT	0020000
54 #define	VP_READY	0000200
55 #define	VP_IENABLE	0000100
56 #define	VP_TERMCOM	0000040
57 #define	VP_FFCOM	0000020
58 #define	VP_EOTCOM	0000010
59 #define	VP_CLRCOM	0000004
60 #define	VP_RESET	0000002
61 #define	VP_SPP		0000001
62 
63 struct vp_softc {
64 	int	sc_state;
65 	int	sc_count;
66 	int	sc_bufp;
67 	struct	buf *sc_bp;
68 	int	sc_ubinfo;
69 } vp_softc[NVP];
70 
71 /* sc_state bits */
72 #define	VPSC_BUSY	0001000
73 #define	VPSC_MODE	0000700
74 #define	VPSC_SPP	0000400
75 #define	VPSC_PLOT	0000200
76 #define	VPSC_PRINT	0000100
77 #define	VPSC_CMNDS	0000076
78 #define	VPSC_OPEN	0000001
79 
80 struct	uba_device *vpdinfo[NVP];
81 
82 #define	VPUNIT(dev)	(minor(dev))
83 
84 struct	buf rvpbuf[NVP];
85 
86 int	vpprobe(), vpattach();
87 struct	uba_device *vpdinfo[NVP];
88 u_short	vpstd[] = { 0777500, 0 };
89 struct	uba_driver vpdriver =
90     { vpprobe, 0, vpattach, 0, vpstd, "vp", vpdinfo };
91 
92 vpprobe(reg)
93 	caddr_t reg;
94 {
95 	register int br, cvec;		/* value-result */
96 	register struct vpdevice *vpaddr = (struct vpdevice *)(reg-010);
97 
98 #ifdef lint
99 	br = 0; cvec = br; br = cvec;
100 	vpintr(0);
101 #endif
102 	vpaddr->prcsr = VP_IENABLE|VP_DTCINTR;
103 	vpaddr->pbaddr = 0;
104 	vpaddr->pbxaddr = 0;
105 	vpaddr->prbcr = 1;
106 	DELAY(10000);
107 	vpaddr->prcsr = 0;
108 	/* GET INTERRUPT AT SECOND VECTOR BUT WANT FIRST */
109 	if (cvec == 0200) {
110 		printf("vp reset vec from 200 to 174\n");
111 		cvec = 0174;
112 	}
113 	return (sizeof (struct vpdevice));
114 }
115 
116 /*ARGSUSED*/
117 vpattach(ui)
118 	struct uba_device *ui;
119 {
120 
121 	ui->ui_addr -= 010;
122 	ui->ui_physaddr -= 010;
123 }
124 
125 vpopen(dev)
126 	dev_t dev;
127 {
128 	register struct vp_softc *sc;
129 	register struct vpdevice *vpaddr;
130 	register struct uba_device *ui;
131 
132 	if (VPUNIT(dev) >= NVP ||
133 	    ((sc = &vp_softc[minor(dev)])->sc_state&VPSC_OPEN) ||
134 	    (ui = vpdinfo[VPUNIT(dev)]) == 0 || ui->ui_alive == 0)
135 		return (ENXIO);
136 	vpaddr = (struct vpdevice *)ui->ui_addr;
137 	sc->sc_state = VPSC_OPEN|VPSC_PRINT | VP_CLRCOM|VP_RESET;
138 	sc->sc_count = 0;
139 	vpaddr->prcsr = VP_IENABLE|VP_DTCINTR;
140 	vptimo(dev);
141 	while (sc->sc_state & VPSC_CMNDS) {
142 		(void) spl4();
143 		if (vpwait(dev)) {
144 			(void) vpclose(dev);
145 			return (EIO);
146 		}
147 		vpstart(dev);
148 		(void) spl0();
149 	}
150 	return (0);
151 }
152 
153 vpstrategy(bp)
154 	register struct buf *bp;
155 {
156 	register int e;
157 	register struct vp_softc *sc = &vp_softc[VPUNIT(bp->b_dev)];
158 	register struct uba_device *ui = vpdinfo[VPUNIT(bp->b_dev)];
159 	register struct vpdevice *vpaddr = (struct vpdevice *)ui->ui_addr;
160 
161 	(void) spl4();
162 	while (sc->sc_state & VPSC_BUSY)
163 		sleep((caddr_t)sc, VPPRI);
164 	sc->sc_state |= VPSC_BUSY;
165 	sc->sc_bp = bp;
166 	sc->sc_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP);
167 	if (e = vpwait(bp->b_dev))
168 		goto brkout;
169 	sc->sc_count = bp->b_bcount;
170 	vpstart(bp->b_dev);
171 	while (((sc->sc_state&VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr) & VP_DMAACT)
172 		sleep((caddr_t)sc, VPPRI);
173 	sc->sc_count = 0;
174 	if ((sc->sc_state&VPSC_MODE) == VPSC_SPP)
175 		sc->sc_state = (sc->sc_state &~ VPSC_MODE) | VPSC_PLOT;
176 	(void) spl0();
177 brkout:
178 	ubarelse(ui->ui_ubanum, &sc->sc_ubinfo);
179 	sc->sc_state &= ~VPSC_BUSY;
180 	sc->sc_bp = 0;
181 	if (e)
182 		bp->b_flags |= B_ERROR;
183 	iodone(bp);
184 	wakeup((caddr_t)sc);
185 }
186 
187 int	vpblock = 16384;
188 
189 unsigned
190 minvpph(bp)
191 	struct buf *bp;
192 {
193 
194 	if (bp->b_bcount > vpblock)
195 		bp->b_bcount = vpblock;
196 }
197 
198 /*ARGSUSED*/
199 vpwrite(dev, uio)
200 	dev_t dev;
201 	struct uio *uio;
202 {
203 
204 	if (VPUNIT(dev) >= NVP)
205 		return (ENXIO);
206 	return (physio(vpstrategy, &rvpbuf[VPUNIT(dev)], dev, B_WRITE,
207 		    minvpph, uio));
208 }
209 
210 vpwait(dev)
211 	dev_t dev;
212 {
213 	register struct vpdevice *vpaddr =
214 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
215 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
216 	register int e;
217 
218 	for (;;) {
219 		e = (sc->sc_state & VPSC_PLOT) ? vpaddr->plcsr : vpaddr->prcsr;
220 		if (e & (VP_READY|VP_ERROR))
221 			break;
222 		sleep((caddr_t)sc, VPPRI);
223 	}
224 	/* I WISH I COULD TELL WHETHER AN ERROR INDICATED AN NPR TIMEOUT */
225 	return (e & VP_ERROR);
226 }
227 
228 vpstart(dev)
229 	dev_t;
230 {
231 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
232 	register struct vpdevice *vpaddr =
233 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
234 	short bit;
235 
236 	if (sc->sc_count) {
237 		vpaddr->pbaddr = sc->sc_ubinfo;
238 		vpaddr->pbxaddr = (sc->sc_ubinfo>>12)&0x30;
239 		if (sc->sc_state & (VPSC_PRINT|VPSC_SPP))
240 			vpaddr->prbcr = sc->sc_count;
241 		else
242 			vpaddr->plbcr = sc->sc_count;
243 		return;
244 	}
245 	for (bit = 1; bit != 0; bit <<= 1)
246 		if (sc->sc_state&bit&VPSC_CMNDS) {
247 			vpaddr->plcsr |= bit;
248 			sc->sc_state &= ~bit;
249 			return;
250 		}
251 }
252 
253 /*ARGSUSED*/
254 vpioctl(dev, cmd, data, flag)
255 	dev_t dev;
256 	int cmd;
257 	register caddr_t data;
258 	int flag;
259 {
260 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
261 	register struct vpdevice *vpaddr =
262 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
263 
264 	switch (cmd) {
265 
266 	case VGETSTATE:
267 		*(int *)data = sc->sc_state;
268 		return (0);
269 
270 	case VSETSTATE:
271 		sc->sc_state =
272 		    (sc->sc_state & ~VPSC_MODE) |
273 		    ((*(int *)data) & (VPSC_MODE|VPSC_CMNDS));
274 		break;
275 
276 	default:
277 		return (ENOTTY);
278 	}
279 	(void) spl4();
280 	(void) vpwait(dev);
281 	if (sc->sc_state&VPSC_SPP)
282 		vpaddr->plcsr |= VP_SPP;
283 	else
284 		vpaddr->plcsr &= ~VP_SPP;
285 	sc->sc_count = 0;
286 	while (sc->sc_state & VPSC_CMNDS) {
287 		(void) vpwait(dev);
288 		vpstart(dev);
289 	}
290 	(void) spl0();
291 	return (0);
292 }
293 
294 vptimo(dev)
295 	dev_t dev;
296 {
297 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
298 
299 	if (sc->sc_state&VPSC_OPEN)
300 		timeout(vptimo, (caddr_t)dev, hz/10);
301 	vpintr(dev);
302 }
303 
304 /*ARGSUSED*/
305 vpintr(dev)
306 	dev_t dev;
307 {
308 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
309 
310 	wakeup((caddr_t)sc);
311 }
312 
313 vpclose(dev)
314 	dev_t dev;
315 {
316 	register struct vp_softc *sc = &vp_softc[VPUNIT(dev)];
317 	register struct vpdevice *vpaddr =
318 	    (struct vpdevice *)vpdinfo[VPUNIT(dev)]->ui_addr;
319 
320 	sc->sc_state = 0;
321 	sc->sc_count = 0;
322 	vpaddr->plcsr = 0;
323 	return (0);
324 }
325 
326 vpreset(uban)
327 	int uban;
328 {
329 	register int vp11;
330 	register struct uba_device *ui;
331 	register struct vp_softc *sc = vp_softc;
332 	register struct vpdevice *vpaddr;
333 
334 	for (vp11 = 0; vp11 < NVP; vp11++, sc++) {
335 		if ((ui = vpdinfo[vp11]) == 0 || ui->ui_alive == 0 ||
336 		    ui->ui_ubanum != uban || (sc->sc_state&VPSC_OPEN) == 0)
337 			continue;
338 		printf(" vp%d", vp11);
339 		vpaddr = (struct vpdevice *)ui->ui_addr;
340 		vpaddr->prcsr = VP_IENABLE|VP_DTCINTR;
341 		if ((sc->sc_state & VPSC_BUSY) == 0)
342 			continue;
343 		sc->sc_ubinfo = 0;
344 		sc->sc_count = sc->sc_bp->b_bcount;
345 		vpstart(sc->sc_bp->b_dev);
346 	}
347 }
348 
349 vpselect()
350 {
351 	return (1);
352 }
353 #endif
354