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