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
vaprobe(reg)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
vaopen(dev)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
vastrategy(bp)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
minvaph(bp)206 minvaph(bp)
207 struct buf *bp;
208 {
209
210 if (bp->b_bcount > vablock)
211 bp->b_bcount = vablock;
212 }
213
214 /*ARGSUSED*/
vawrite(dev,uio)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
vastart(um)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
vadgo(um)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*/
vaioctl(dev,cmd,data,flag)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
vacmd(dev,vcmd)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
vadopio(dev,cmd)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
vatimo(dev)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*/
vaintr(dev)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
vaclose(dev)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
vareset(uban)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
vaselect()468 vaselect()
469 {
470
471 return (1);
472 }
473 #endif
474