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