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