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