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