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