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