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