new format of error prints; no more FLAKEY UP resets
[unix-history] / usr / src / sys / vax / uba / dz.c
CommitLineData
b19fe459 1/* dz.c 4.20 %G% */
5074fa57 2
66b4fb09 3#include "dz.h"
a3cb8f60 4#if NDZ > 0
88d5b764 5#define DELAY(i) { register int j = i; while (--j > 0); }
5074fa57
BJ
6/*
7 * DZ-11 Driver
7e00c42b
BJ
8 *
9 * This driver mimics dh.c; see it for explanation of common code.
5074fa57 10 */
e2c4935e 11#include "bk.h"
5074fa57
BJ
12#include "../h/param.h"
13#include "../h/systm.h"
14#include "../h/tty.h"
15#include "../h/dir.h"
16#include "../h/user.h"
17#include "../h/map.h"
18#include "../h/pte.h"
3f3a34c3 19#include "../h/buf.h"
7e286c72 20#include "../h/vm.h"
5074fa57
BJ
21#include "../h/uba.h"
22#include "../h/conf.h"
23#include "../h/pdma.h"
771d8988 24#include "../h/bk.h"
cc343d94 25#include "../h/file.h"
1b05b375 26#include "../h/mx.h"
d3ebf5ee 27
7e00c42b
BJ
28/*
29 * Driver information for auto-configuration stuff.
30 */
71236e46 31int dzprobe(), dzattach(), dzrint();
a3cb8f60 32struct uba_dinfo *dzinfo[NDZ];
3f3a34c3 33u_short dzstd[] = { 0 };
3f3a34c3 34struct uba_driver dzdriver =
71236e46 35 { dzprobe, 0, dzattach, 0, dzstd, "dz", dzinfo };
3f3a34c3 36
a3cb8f60 37#define NDZLINE (NDZ*8)
5074fa57 38
7e00c42b
BJ
39/*
40 * Registers and bits
41 */
42
43/* Bits in dzlpr */
88d5b764
BJ
44#define BITS7 020
45#define BITS8 030
46#define TWOSB 040
47#define PENABLE 0100
48#define OPAR 0200
5074fa57 49
7e00c42b
BJ
50/* Bits in dzrbuf */
51#define DZ_PE 010000
52#define DZ_FE 020000
53#define DZ_DO 040000
54
55/* Bits in dzcsr */
56#define DZ_CLR 020 /* Reset dz */
57#define DZ_MSE 040 /* Master Scan Enable */
58#define DZ_RIE 0100 /* Receiver Interrupt Enable */
59#define DZ_SAE 010000 /* Silo Alarm Enable */
60#define DZ_TIE 040000 /* Transmit Interrupt Enable */
61#define DZ_IEN (DZ_MSE+DZ_RIE+DZ_TIE+DZ_SAE)
62
63/* Flags for modem-control */
64#define DZ_ON 1
65#define DZ_OFF 0
5074fa57 66
7e00c42b 67int dzstart(), dzxint(), dzdma();
771d8988 68int ttrstrt();
a3cb8f60
BJ
69struct tty dz_tty[NDZLINE];
70int dz_cnt = { NDZLINE };
9dca4f86 71int dzact;
5074fa57
BJ
72
73struct device {
7e00c42b
BJ
74 short dzcsr; /* control-status register */
75 short dzrbuf; /* receiver buffer */
76#define dzlpr dzrbuf /* line parameter reg is write of dzrbuf */
77 char dztcr; /* transmit control register */
78 char dzdtr; /* data terminal ready */
79 char dztbuf; /* transmit buffer */
80 char dzbrk; /* break control */
81#define dzmsr dzbrk /* modem status register */
5074fa57 82};
7e00c42b
BJ
83/*
84 * Software copy of dzbrk since it isn't readable
85 */
a3cb8f60
BJ
86char dz_brk[NDZ];
87char dzsoftCAR[NDZ];
5074fa57 88
7e00c42b
BJ
89/*
90 * The dz doesn't interrupt on carrier transitions, so
91 * we have to use a timer to watch it.
92 */
93char dz_timer; /* timer started? */
94
95/*
96 * Pdma structures for fast output code
97 */
a3cb8f60 98struct pdma dzpdma[NDZLINE];
7e00c42b 99
3f3a34c3
BJ
100char dz_speeds[] =
101 { 0,020,021,022,023,024,0,025,026,027,030,032,034,036,0,0 };
5074fa57 102
71236e46 103dzprobe(reg)
3f3a34c3
BJ
104 caddr_t reg;
105{
88d5b764
BJ
106 register int br, cvec;
107 register struct device *dzaddr = (struct device *)reg;
3f3a34c3 108
71236e46
BJ
109#ifdef lint
110 br = 0; br = cvec; cvec = br;
111#endif
7e00c42b 112 dzaddr->dzcsr = DZ_TIE|DZ_MSE;
5aa9d5ea 113 dzaddr->dztcr = 1; /* enable any line */
88d5b764 114 DELAY(100000);
7e00c42b 115 dzaddr->dzcsr = DZ_CLR; /* reset everything */
88d5b764
BJ
116 if (cvec && cvec != 0x200)
117 cvec -= 4;
118 return (1);
3f3a34c3
BJ
119}
120
71236e46 121dzattach(ui)
3f3a34c3 122 register struct uba_dinfo *ui;
3f3a34c3
BJ
123{
124 register struct pdma *pdp = &dzpdma[ui->ui_unit*8];
125 register struct tty *tp = &dz_tty[ui->ui_unit*8];
71236e46 126 register int cntr;
a3cb8f60 127 extern dzscan();
3f3a34c3 128
71236e46
BJ
129 for (cntr = 0; cntr < 8; cntr++) {
130 pdp->p_addr = (struct device *)ui->ui_addr;
3f3a34c3
BJ
131 pdp->p_arg = (int)tp;
132 pdp->p_fcn = dzxint;
133 pdp++, tp++;
134 }
7e286c72 135 dzsoftCAR[ui->ui_unit] = ui->ui_flags;
be2b272c
BJ
136 if (dz_timer == 0) {
137 dz_timer++;
7780575a 138 timeout(dzscan, (caddr_t)0, hz);
be2b272c 139 }
3f3a34c3
BJ
140 return (1);
141}
142
5074fa57 143/*ARGSUSED*/
3f3a34c3
BJ
144dzopen(dev, flag)
145 dev_t dev;
5074fa57
BJ
146{
147 register struct tty *tp;
3f3a34c3 148 register int unit;
5074fa57 149
3f3a34c3
BJ
150 unit = minor(dev);
151 if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) {
5074fa57
BJ
152 u.u_error = ENXIO;
153 return;
154 }
3f3a34c3
BJ
155 tp = &dz_tty[unit];
156 tp->t_addr = (caddr_t)&dzpdma[unit];
5074fa57
BJ
157 tp->t_oproc = dzstart;
158 tp->t_iproc = NULL;
159 tp->t_state |= WOPEN;
160 if ((tp->t_state & ISOPEN) == 0) {
161 ttychars(tp);
7e00c42b 162 tp->t_ospeed = tp->t_ispeed = B300;
5074fa57 163 tp->t_flags = ODDP|EVENP|ECHO;
7e00c42b 164 /* tp->t_state |= HUPCLS; */
3f3a34c3 165 dzparam(unit);
5074fa57
BJ
166 } else if (tp->t_state&XCLUDE && u.u_uid != 0) {
167 u.u_error = EBUSY;
168 return;
169 }
7e00c42b 170 dzmodem(unit, DZ_ON);
771d8988 171 (void) spl5();
5074fa57
BJ
172 while ((tp->t_state & CARR_ON) == 0) {
173 tp->t_state |= WOPEN;
174 sleep((caddr_t)&tp->t_rawq, TTIPRI);
175 }
771d8988 176 (void) spl0();
3f3a34c3 177 (*linesw[tp->t_line].l_open)(dev, tp);
5074fa57
BJ
178}
179
3f3a34c3
BJ
180/*ARGSUSED*/
181dzclose(dev, flag)
182 dev_t dev;
5074fa57
BJ
183{
184 register struct tty *tp;
3f3a34c3
BJ
185 register int unit;
186 int dz;
5074fa57 187
3f3a34c3
BJ
188 unit = minor(dev);
189 dz = unit >> 3;
190 tp = &dz_tty[unit];
5074fa57 191 (*linesw[tp->t_line].l_close)(tp);
e60fc718 192 ((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
3f3a34c3 193 (dz_brk[dz] &= ~(1 << (unit&07)));
5074fa57 194 if (tp->t_state & HUPCLS)
7e00c42b 195 dzmodem(unit, DZ_OFF);
5074fa57
BJ
196 ttyclose(tp);
197}
198
3f3a34c3
BJ
199dzread(dev)
200 dev_t dev;
5074fa57
BJ
201{
202 register struct tty *tp;
203
3f3a34c3 204 tp = &dz_tty[minor(dev)];
5074fa57
BJ
205 (*linesw[tp->t_line].l_read)(tp);
206}
207
3f3a34c3
BJ
208dzwrite(dev)
209 dev_t dev;
5074fa57
BJ
210{
211 register struct tty *tp;
212
3f3a34c3 213 tp = &dz_tty[minor(dev)];
5074fa57
BJ
214 (*linesw[tp->t_line].l_write)(tp);
215}
216
9dca4f86 217/*ARGSUSED*/
3f3a34c3
BJ
218dzrint(dz)
219 int dz;
5074fa57
BJ
220{
221 register struct tty *tp;
222 register int c;
223 register struct device *dzaddr;
9dca4f86 224 register struct tty *tp0;
3f3a34c3 225 register int unit;
b19fe459 226 int overrun = 0;
5074fa57 227
88d5b764
BJ
228 if ((dzact & (1<<dz)) == 0)
229 return;
230 unit = dz * 8;
231 dzaddr = dzpdma[unit].p_addr;
232 tp0 = &dz_tty[unit];
233 while ((c = dzaddr->dzrbuf) < 0) { /* char present */
234 tp = tp0 + ((c>>8)&07);
235 if (tp >= &dz_tty[dz_cnt])
236 continue;
237 if ((tp->t_state & ISOPEN) == 0) {
238 wakeup((caddr_t)&tp->t_rawq);
5074fa57 239 continue;
9dca4f86 240 }
7e00c42b 241 if (c&DZ_FE)
88d5b764 242 if (tp->t_flags & RAW)
7e00c42b 243 c = 0;
88d5b764
BJ
244 else
245 c = tun.t_intrc;
b19fe459
BJ
246 if (c&DZ_DO && overrun == 0) {
247 printf("dz%d: silo overflow\n", dz);
248 overrun = 1;
249 }
7e00c42b 250 if (c&DZ_PE)
88d5b764
BJ
251 if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
252 || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
253 continue;
e2c4935e 254#if NBK > 0
88d5b764
BJ
255 if (tp->t_line == NETLDISC) {
256 c &= 0177;
257 BKINPUT(c, tp);
258 } else
e2c4935e 259#endif
88d5b764 260 (*linesw[tp->t_line].l_rint)(c, tp);
5074fa57
BJ
261 }
262}
263
264/*ARGSUSED*/
265dzioctl(dev, cmd, addr, flag)
3f3a34c3
BJ
266 dev_t dev;
267 caddr_t addr;
5074fa57
BJ
268{
269 register struct tty *tp;
3f3a34c3
BJ
270 register int unit = minor(dev);
271 register int dz = unit >> 3;
5074fa57 272
3f3a34c3 273 tp = &dz_tty[unit];
771d8988
BJ
274 cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
275 if (cmd == 0)
276 return;
c3277147 277 if (ttioctl(tp, cmd, addr, flag)) {
5074fa57 278 if (cmd==TIOCSETP || cmd==TIOCSETN)
3f3a34c3 279 dzparam(unit);
dc44829a 280 } else switch(cmd) {
3f3a34c3 281
dc44829a 282 case TIOCSBRK:
3f988b2a 283 ((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
3f3a34c3 284 (dz_brk[dz] |= 1 << (unit&07));
dc44829a
BJ
285 break;
286 case TIOCCBRK:
3f988b2a 287 ((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
3f3a34c3 288 (dz_brk[dz] &= ~(1 << (unit&07)));
dc44829a
BJ
289 break;
290 case TIOCSDTR:
7e00c42b 291 dzmodem(unit, DZ_ON);
dc44829a
BJ
292 break;
293 case TIOCCDTR:
7e00c42b 294 dzmodem(unit, DZ_OFF);
dc44829a
BJ
295 break;
296 default:
5074fa57 297 u.u_error = ENOTTY;
dc44829a 298 }
5074fa57
BJ
299}
300
3f3a34c3
BJ
301dzparam(unit)
302 register int unit;
5074fa57
BJ
303{
304 register struct tty *tp;
305 register struct device *dzaddr;
3f3a34c3 306 register int lpr;
5074fa57 307
3f3a34c3
BJ
308 tp = &dz_tty[unit];
309 dzaddr = dzpdma[unit].p_addr;
5074fa57 310 dzaddr->dzcsr = DZ_IEN;
3f3a34c3 311 dzact |= (1<<(unit>>3));
5074fa57 312 if (tp->t_ispeed == 0) {
7e00c42b 313 dzmodem(unit, DZ_OFF); /* hang up line */
5074fa57
BJ
314 return;
315 }
3f3a34c3 316 lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07);
be5b7974 317 if ((tp->t_local&LLITOUT) || (tp->t_flags&RAW))
5074fa57
BJ
318 lpr |= BITS8;
319 else
320 lpr |= (BITS7|PENABLE);
321 if ((tp->t_flags & EVENP) == 0)
322 lpr |= OPAR;
7e00c42b
BJ
323 if (tp->t_ispeed == B110)
324 lpr |= TWOSB;
5074fa57
BJ
325 dzaddr->dzlpr = lpr;
326}
327
328dzxint(tp)
3f3a34c3 329 register struct tty *tp;
5074fa57
BJ
330{
331 register struct pdma *dp;
d3ebf5ee 332 register s;
5074fa57 333
7e00c42b 334 s = spl5(); /* block pdma interrupts */
3f3a34c3 335 dp = (struct pdma *)tp->t_addr;
5074fa57
BJ
336 tp->t_state &= ~BUSY;
337 if (tp->t_state & FLUSH)
338 tp->t_state &= ~FLUSH;
339 else
46014098 340 ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
5074fa57
BJ
341 if (tp->t_line)
342 (*linesw[tp->t_line].l_start)(tp);
343 else
344 dzstart(tp);
345 if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0)
3f3a34c3 346 dp->p_addr->dztcr &= ~(1 << (minor(tp->t_dev)&07));
d3ebf5ee 347 splx(s);
5074fa57
BJ
348}
349
350dzstart(tp)
3f3a34c3 351 register struct tty *tp;
5074fa57
BJ
352{
353 register struct pdma *dp;
354 register struct device *dzaddr;
3f3a34c3
BJ
355 register int cc;
356 int s;
5074fa57 357
3f3a34c3 358 dp = (struct pdma *)tp->t_addr;
5074fa57 359 dzaddr = dp->p_addr;
3f3a34c3 360 s = spl5();
5074fa57
BJ
361 if (tp->t_state & (TIMEOUT|BUSY|TTSTOP))
362 goto out;
b25a5292 363 if (tp->t_state&ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) {
5074fa57
BJ
364 tp->t_state &= ~ASLEEP;
365 if (tp->t_chan)
366 mcstart(tp->t_chan, (caddr_t)&tp->t_outq);
367 else
368 wakeup((caddr_t)&tp->t_outq);
369 }
370 if (tp->t_outq.c_cc == 0)
371 goto out;
372 if (tp->t_flags&RAW)
373 cc = ndqb(&tp->t_outq, 0);
374 else {
375 cc = ndqb(&tp->t_outq, 0200);
376 if (cc == 0) {
377 cc = getc(&tp->t_outq);
7e00c42b 378 timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6);
5074fa57
BJ
379 tp->t_state |= TIMEOUT;
380 goto out;
381 }
382 }
383 tp->t_state |= BUSY;
384 dp->p_end = dp->p_mem = tp->t_outq.c_cf;
385 dp->p_end += cc;
7e00c42b 386 dzaddr->dztcr |= 1 << (minor(tp->t_dev) & 07); /* force intr */
3f3a34c3
BJ
387out:
388 splx(s);
5074fa57
BJ
389}
390
391/*
392 * Stop output on a line.
5074fa57
BJ
393 */
394/*ARGSUSED*/
395dzstop(tp, flag)
3f3a34c3 396 register struct tty *tp;
5074fa57
BJ
397{
398 register struct pdma *dp;
399 register int s;
400
3f3a34c3 401 dp = (struct pdma *)tp->t_addr;
88d5b764 402 s = spl5();
5074fa57
BJ
403 if (tp->t_state & BUSY) {
404 dp->p_end = dp->p_mem;
3f3a34c3 405 if ((tp->t_state&TTSTOP)==0)
5074fa57 406 tp->t_state |= FLUSH;
5074fa57
BJ
407 }
408 splx(s);
409}
410
3f3a34c3
BJ
411dzmodem(unit, flag)
412 register int unit;
5074fa57
BJ
413{
414 register struct device *dzaddr;
415 register char bit;
416
3f3a34c3
BJ
417 dzaddr = dzpdma[unit].p_addr;
418 bit = 1<<(unit&07);
7e00c42b 419 if (flag == DZ_OFF)
5074fa57
BJ
420 dzaddr->dzdtr &= ~bit;
421 else
422 dzaddr->dzdtr |= bit;
423}
424
425dzscan()
426{
427 register i;
428 register struct device *dzaddr;
429 register bit;
430 register struct tty *tp;
431
432 for (i = 0; i < dz_cnt ; i++) {
433 dzaddr = dzpdma[i].p_addr;
be2b272c
BJ
434 if (dzaddr == 0)
435 continue;
5074fa57
BJ
436 tp = &dz_tty[i];
437 bit = 1<<(i&07);
71236e46 438 if ((dzsoftCAR[i>>3]&bit) || (dzaddr->dzmsr&bit)) {
5074fa57
BJ
439 /* carrier present */
440 if ((tp->t_state & CARR_ON) == 0) {
441 wakeup((caddr_t)&tp->t_rawq);
442 tp->t_state |= CARR_ON;
443 }
444 } else {
7e00c42b
BJ
445 if ((tp->t_state&CARR_ON) &&
446 (tp->t_local&LNOHANG)==0) {
5074fa57 447 /* carrier lost */
3f988b2a 448 if (tp->t_state&ISOPEN) {
dc44829a 449 gsignal(tp->t_pgrp, SIGHUP);
160cf9ed 450 gsignal(tp->t_pgrp, SIGCONT);
dc44829a 451 dzaddr->dzdtr &= ~bit;
cc343d94 452 flushtty(tp, FREAD|FWRITE);
dc44829a
BJ
453 }
454 tp->t_state &= ~CARR_ON;
5074fa57 455 }
5074fa57
BJ
456 }
457 }
7780575a 458 timeout(dzscan, (caddr_t)0, 2*hz);
5074fa57 459}
9dca4f86
BJ
460
461dztimer()
462{
88d5b764 463 int dz;
9dca4f86 464
a3cb8f60 465 for (dz = 0; dz < NDZ; dz++)
88d5b764 466 dzrint(dz);
9dca4f86 467}
46014098
BJ
468
469/*
470 * Reset state of driver if UBA reset was necessary.
0072a3c2 471 * Reset parameters and restart transmission on open lines.
46014098 472 */
3f3a34c3 473dzreset(uban)
5aa9d5ea 474 int uban;
46014098 475{
3f3a34c3 476 register int unit;
46014098 477 register struct tty *tp;
5aa9d5ea 478 register struct uba_dinfo *ui;
46014098 479
a3cb8f60 480 for (unit = 0; unit < NDZLINE; unit++) {
5aa9d5ea
RE
481 ui = dzinfo[unit >> 3];
482 if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0)
483 continue;
b19fe459
BJ
484 if (unit%8 == 0)
485 printf(" dz%d", unit>>3);
3f3a34c3 486 tp = &dz_tty[unit];
46014098 487 if (tp->t_state & (ISOPEN|WOPEN)) {
3f3a34c3 488 dzparam(unit);
7e00c42b 489 dzmodem(unit, DZ_ON);
0072a3c2
BJ
490 tp->t_state &= ~BUSY;
491 dzstart(tp);
46014098
BJ
492 }
493 }
494 dztimer();
46014098 495}
a5cc519e 496#endif