xref: /original-bsd/sys/vax/uba/va.c (revision abb30312)
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  *	@(#)va.c	7.4 (Berkeley) 12/16/90
7  */
8 
9 #include "va.h"
10 #if NVA > 0
11 /*
12  * Varian printer plotter
13  */
14 #include "../include/pte.h"
15 
16 #include "sys/param.h"
17 #include "sys/user.h"
18 #include "sys/buf.h"
19 #include "sys/systm.h"
20 #include "sys/map.h"
21 #include "sys/ioctl.h"
22 #include "sys/vcmd.h"
23 #include "sys/uio.h"
24 #include "sys/kernel.h"
25 
26 #include "ubareg.h"
27 #include "ubavar.h"
28 
29 int	vadebug = 0;
30 #define	dprintf	if(vadebug)printf
31 
32 unsigned minvaph();
33 
34 #define	VAPRI	(PZERO-1)
35 
36 struct	vadevice {
37 	u_short	vaba;			/* buffer address */
38 	short	vawc;			/* word count (2's complement) */
39 	union {
40 		short	Vacsw;		/* control status as word */
41 		struct {		/* control status as bytes */
42 			char Vacsl;
43 			char Vacsh;
44 		} vacsr;
45 	} vacs;
46 	short	vadata;			/* programmed i/o data buffer */
47 };
48 
49 #define	vacsw	vacs.Vacsw
50 #define	vacsh	vacs.vacsr.Vacsh
51 #define	vacsl	vacs.vacsr.Vacsl
52 
53 /* vacsw bits */
54 #define	VA_ERROR	0100000		/* some error has occurred */
55 #define	VA_NPRTIMO	0001000		/* DMA timeout error */
56 #define	VA_NOTREADY	0000400		/* something besides NPRTIMO */
57 #define	VA_DONE		0000200
58 #define	VA_IENABLE	0000100		/* interrupt enable */
59 #define	VA_DMAGO	0000010		/* DMA go bit */
60 #define	VA_DMAGO	0000010		/* DMA go bit */
61 #define	VA_SUPPLIESLOW	0000004
62 #define	VA_BOTOFFORM	0000002
63 #define	VA_BYTEREVERSE	0000001		/* reverse byte order in words */
64 
65 /* vacsh command bytes */
66 #define	VAPLOT		0000340
67 #define	VAPRINT		0000100
68 #define	VAPRINTPLOT	0000160
69 #define	VAAUTOSTEP	0000244
70 #define	VANOAUTOSTEP	0000045
71 #define	VAFORMFEED	0000263
72 #define	VASLEW		0000265
73 #define	VASTEP		0000064
74 
75 struct va_softc {
76 	u_char	sc_openf;		/* exclusive open flag */
77 	u_char	sc_iostate;		/* kind of I/O going on */
78 #define	VAS_IDLE	0	/* no I/O, free */
79 #define	VAS_PIO		1	/* programmed I/O */
80 #define	VAS_DMA		2	/* DMA, block pio */
81 #define	VAS_WANT	4	/* wakeup when iostate changes */
82 	short	sc_tocnt;		/* time out counter */
83 	short	sc_info;		/* csw passed from vaintr */
84 	int	sc_state;		/* print/plot state of device */
85 } va_softc[NVA];
86 
87 #define	VAUNIT(dev)	(minor(dev))
88 
89 struct	buf rvabuf[NVA];
90 
91 int	vaprobe(), vaslave(), vaattach(), vadgo();
92 struct	uba_device *vadinfo[NVA];
93 struct	uba_ctlr *vaminfo[NVA];
94 struct	buf vabhdr[NVA];
95 u_short	vastd[] = { 0764000, 0 };
96 struct	uba_driver vadriver =
97     { vaprobe, vaslave, vaattach, vadgo, vastd, "vz", vadinfo, "va", vaminfo };
98 
99 vaprobe(reg)
100 	caddr_t reg;
101 {
102 	register int br, cvec;		/* value-result */
103 	register struct vadevice *vaaddr = (struct vadevice *)reg;
104 
105 #ifdef lint
106 	br = 0; cvec = br; br = cvec;
107 	vaintr(0);
108 #endif
109 #ifndef UCBVAX
110 	vaaddr->vacsl = VA_IENABLE;
111 	vaaddr->vaba = 0;
112 	vaaddr->vacsh = VAPLOT;
113 	vaaddr->vacsl = VA_IENABLE|VA_DMAGO;
114 	vaaddr->vawc = -1;
115 	DELAY(10000);
116 	vaaddr->vacsl = 0;
117 	vaaddr->vawc = 0;
118 #else
119 	br=0x14;
120 	cvec=0170;
121 #endif
122 	return (sizeof (struct vadevice));
123 }
124 
125 /*ARGSUSED*/
126 vaslave(ui, reg)
127 	struct uba_device *ui;
128 	caddr_t reg;
129 {
130 
131 	ui->ui_dk = 0;
132 	return (ui->ui_unit <= 0);
133 }
134 
135 /*ARGSUSED*/
136 vaattach(ui)
137 	struct uba_device *ui;
138 {
139 
140 	ui->ui_mi->um_tab.b_actf = &vabhdr[ui->ui_unit];
141 }
142 
143 vaopen(dev)
144 	dev_t dev;
145 {
146 	register struct va_softc *sc;
147 	register struct vadevice *vaaddr;
148 	register struct uba_device *ui;
149 	int error;
150 	int unit = VAUNIT(dev);
151 
152 	if (unit >= NVA || (sc = &va_softc[unit])->sc_openf ||
153 	    (ui = vadinfo[unit]) == 0 || ui->ui_alive == 0)
154 		return (ENXIO);
155 	vaaddr = (struct vadevice *)ui->ui_addr;
156 	sc->sc_openf = 1;
157 	vaaddr->vawc = 0;
158 	sc->sc_state = 0;
159 	sc->sc_tocnt = 0;
160 	sc->sc_iostate = VAS_IDLE;
161 	vaaddr->vacsl = VA_IENABLE;
162 	vatimo(dev);
163 	error = vacmd(dev, VPRINT);
164 	if (error)
165 		vaclose(dev);
166 	return (error);
167 }
168 
169 vastrategy(bp)
170 	register struct buf *bp;
171 {
172 	register struct uba_device *ui;
173 	register struct uba_ctlr *um;
174 	int s;
175 
176 	dprintf("vastrategy(%x)\n", bp);
177 	ui = vadinfo[VAUNIT(bp->b_dev)];
178 	if (ui == 0 || ui->ui_alive == 0) {
179 		bp->b_flags |= B_ERROR;
180 		iodone(bp);
181 		return;
182 	}
183 	s = spl4();
184 	um = ui->ui_mi;
185 	bp->b_actf = NULL;
186 	if (um->um_tab.b_actf->b_actf == NULL)
187 		um->um_tab.b_actf->b_actf = bp;
188 	else {
189 		printf("bp = 0x%x, um->um_tab.b_actf->b_actf = 0x%x\n",
190 			bp, um->um_tab.b_actf->b_actf);
191 		panic("vastrategy");
192 		um->um_tab.b_actf->b_actl->b_forw = bp;
193 	}
194 	um->um_tab.b_actf->b_actl = bp;
195 	bp = um->um_tab.b_actf;
196 	dprintf("vastrategy: bp=%x actf=%x active=%d\n",
197 		bp, bp->b_actf, bp->b_active);
198 	if (bp->b_actf && bp->b_active == 0)
199 		(void) vastart(um);
200 	splx(s);
201 }
202 
203 int	vablock = 16384;
204 
205 unsigned
206 minvaph(bp)
207 	struct buf *bp;
208 {
209 
210 	if (bp->b_bcount > vablock)
211 		bp->b_bcount = vablock;
212 }
213 
214 /*ARGSUSED*/
215 vawrite(dev, uio)
216 	dev_t dev;
217 	struct uio *uio;
218 {
219 
220 	if (VAUNIT(dev) > NVA)
221 		return (ENXIO);
222 	return (physio(vastrategy, &rvabuf[VAUNIT(dev)], dev, B_WRITE,
223 		    minvaph, uio));
224 }
225 
226 vastart(um)
227 	register struct uba_ctlr *um;
228 {
229 	struct buf *bp;
230 	struct vadevice *vaaddr;
231 	register struct va_softc *sc;
232 	int unit;
233 
234 	dprintf("vastart(%x), bp=%x\n", um, um->um_tab.b_actf->b_actf);
235 	if ((bp = um->um_tab.b_actf->b_actf) == NULL)
236 		return;
237 	unit = VAUNIT(bp->b_dev);
238 	sc = &va_softc[unit];
239 	sc->sc_tocnt = 0;
240 	while (sc->sc_iostate&VAS_PIO) {
241 		sc->sc_iostate |= VAS_WANT;
242 		sleep((caddr_t)&sc->sc_iostate, VAPRI);
243 	}
244 	sc->sc_iostate |= VAS_DMA;
245 	vaaddr = (struct vadevice *)um->um_addr;
246 	vaaddr->vacsl = 0;
247 	vaaddr->vawc = -(bp->b_bcount / 2);
248 	um->um_cmd = VA_DMAGO | VA_IENABLE;
249 	(void) ubago(vadinfo[unit]);
250 }
251 
252 vadgo(um)
253 	register struct uba_ctlr *um;
254 {
255 	register struct vadevice *vaaddr = (struct vadevice *)um->um_addr;
256 	register struct buf *bp;
257 
258 	bp = um->um_tab.b_actf;
259 	va_softc[VAUNIT(bp->b_actf->b_dev)].sc_tocnt = 0;
260 	bp->b_active++;
261 	vaaddr->vaba = um->um_ubinfo;
262 	vaaddr->vacsl = ((um->um_ubinfo >> 12) & 0x30) | um->um_cmd;
263 }
264 
265 /*ARGSUSED*/
266 vaioctl(dev, cmd, data, flag)
267 	register caddr_t data;
268 {
269 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
270 
271 	switch (cmd) {
272 
273 	case VGETSTATE:
274 		*(int *)data = sc->sc_state;
275 		break;
276 
277 	case VSETSTATE:
278 		return (vacmd(dev, *(int *)data));
279 
280 	default:
281 		return (ENOTTY);
282 	}
283 	return (0);
284 }
285 
286 vacmd(dev, vcmd)
287 	dev_t dev;
288 	int vcmd;
289 {
290 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
291 	int error = 0;
292 	int s, cmd;
293 
294 	s = spl4();
295 	while (sc->sc_iostate&VAS_DMA) {
296 		sc->sc_iostate |= VAS_WANT;
297 		sleep((caddr_t)&sc->sc_iostate, VAPRI);
298 	}
299 	sc->sc_iostate |= VAS_PIO;
300 	sc->sc_tocnt = 0;
301 	cmd = 0;
302 	switch (vcmd) {
303 
304 	case VPLOT:
305 		/* Must turn on plot AND autostep modes. */
306 		if (vadopio(dev, VAPLOT))
307 			error = EIO;
308 		cmd = VAAUTOSTEP;
309 		break;
310 
311 	case VPRINT:
312 		cmd = VAPRINT;
313 		break;
314 
315 	case VPRINTPLOT:
316 		cmd = VAPRINTPLOT;
317 		break;
318 	}
319 	sc->sc_state = (sc->sc_state & ~(VPLOT|VPRINT|VPRINTPLOT)) | vcmd;
320 	if (cmd && vadopio(dev, cmd))
321 		error = EIO;
322 	sc->sc_iostate &= ~VAS_PIO;
323 	if (sc->sc_iostate&VAS_WANT) {
324 		sc->sc_iostate &= ~VAS_WANT;
325 		wakeup((caddr_t)&sc->sc_iostate);
326 	}
327 	splx(s);
328 	return (error);
329 }
330 
331 vadopio(dev, cmd)
332 	dev_t dev;
333 	int cmd;
334 {
335 	register struct vadevice *vaaddr =
336 	    (struct vadevice *)vaminfo[VAUNIT(dev)]->um_addr;
337 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
338 
339 	sc->sc_info = 0;
340 	vaaddr->vacsh = cmd;
341 	while ((sc->sc_info&(VA_DONE|VA_ERROR)) == 0)
342 		sleep((caddr_t)&sc->sc_info, VAPRI);
343 	return (sc->sc_info&VA_ERROR);
344 }
345 
346 vatimo(dev)
347 	dev_t dev;
348 {
349 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
350 
351 	if (sc->sc_openf)
352 		timeout(vatimo, (caddr_t)dev, hz/2);
353 	if (++sc->sc_tocnt < 2)
354 		return;
355 	sc->sc_tocnt = 0;
356 	dprintf("vatimo: calling vaintr\n");
357 	vaintr(dev);
358 }
359 
360 /*ARGSUSED*/
361 vaintr(dev)
362 	dev_t dev;
363 {
364 	register struct uba_ctlr *um;
365 	struct vadevice *vaaddr;
366 	struct buf *bp;
367 	register int unit = VAUNIT(dev), e;
368 	register struct va_softc *sc = &va_softc[unit];
369 
370 	um = vaminfo[unit];
371 	vaaddr = (struct vadevice *)um->um_addr;
372 	e = vaaddr->vacsw;
373 	dprintf("vaintr: um=0x%x, e=0x%x, b_active %d\n",
374 		um, e, um->um_tab.b_actf->b_active);
375 	if ((e&(VA_DONE|VA_ERROR)) == 0)
376 		return;
377 	vaaddr->vacsl = 0;
378 	if ((e&VA_ERROR) && (e&VA_NPRTIMO))
379 		printf("va%d: npr timeout\n", unit);
380 	if (sc->sc_iostate&VAS_PIO) {
381 		sc->sc_info = e;
382 		wakeup((caddr_t)&sc->sc_info);
383 		return;
384 	}
385 	if (um->um_tab.b_actf->b_active) {
386 		bp = um->um_tab.b_actf->b_actf;
387 		if (e&VA_ERROR)
388 			bp->b_flags |= B_ERROR;
389 		if (sc->sc_state&VPRINTPLOT) {
390 			sc->sc_state = (sc->sc_state & ~VPRINTPLOT) | VPLOT;
391 			vaaddr->vacsh = VAAUTOSTEP;
392 			return;
393 		}
394 		ubadone(um);
395 		um->um_tab.b_actf->b_active = 0;
396 		um->um_tab.b_actf->b_actf = bp->b_forw;
397 		bp->b_active = 0;
398 		bp->b_errcnt = 0;
399 		bp->b_resid = 0;
400 		iodone(bp);
401 	}
402 	if (um->um_tab.b_actf->b_actf == 0) {
403 		sc->sc_iostate &= ~VAS_DMA;
404 		if (sc->sc_iostate&VAS_WANT) {
405 			sc->sc_iostate &= ~VAS_WANT;
406 			wakeup((caddr_t)&sc->sc_iostate);
407 		}
408 		return;
409 	}
410 	if (um->um_tab.b_actf->b_active == 0)
411 		vastart(um);
412 }
413 
414 vaclose(dev)
415 	dev_t dev;
416 {
417 	register struct va_softc *sc = &va_softc[VAUNIT(dev)];
418 	register struct vadevice *vaaddr =
419 	    (struct vadevice *)vadinfo[VAUNIT(dev)]->ui_addr;
420 
421 	sc->sc_openf = 0;
422 	sc->sc_state = 0;
423 	if (sc->sc_iostate != VAS_IDLE)
424 		wakeup((caddr_t)&sc->sc_iostate);
425 	sc->sc_iostate = VAS_IDLE;
426 	vaaddr->vacsl = 0;
427 	vaaddr->vawc = 0;
428 }
429 
430 vareset(uban)
431 	int uban;
432 {
433 	register int va11;
434 	register struct uba_ctlr *um;
435 	register struct vadevice *vaaddr;
436 	register struct va_softc *sc;
437 
438 	for (va11 = 0; va11 < NVA; va11++, sc++) {
439 		if ((um = vaminfo[va11]) == 0 || um->um_ubanum != uban ||
440 		    um->um_alive == 0)
441 			continue;
442 		sc = &va_softc[um->um_ctlr];
443 		if (sc->sc_openf == 0)
444 			continue;
445 		printf(" va%d", va11);
446 		vaaddr = (struct vadevice *)um->um_addr;
447 		vaaddr->vacsl = VA_IENABLE;
448 		if (sc->sc_state & VPLOT) {
449 			vaaddr->vacsh = VAPLOT;
450 			DELAY(10000);
451 			vaaddr->vacsh = VAAUTOSTEP;
452 		} else if (sc->sc_state & VPRINTPLOT)
453 			vaaddr->vacsh = VPRINTPLOT;
454 		else
455 			vaaddr->vacsh = VAPRINTPLOT;
456 		DELAY(10000);
457 		sc->sc_iostate = VAS_IDLE;
458 		um->um_tab.b_actf->b_active = 0;
459 		um->um_tab.b_actf->b_actf = um->um_tab.b_actf->b_actl = 0;
460 		if (um->um_ubinfo) {
461 			printf("<%d>", (um->um_ubinfo >> 28) & 0xf);
462 			um->um_ubinfo = 0;
463 		}
464 		(void) vastart(um);
465 	}
466 }
467 
468 vaselect()
469 {
470 
471 	return (1);
472 }
473 #endif
474