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