working dm code
[unix-history] / usr / src / sys / vax / uba / dz.c
CommitLineData
7e00c42b 1/* dz.c 4.13 %G% */
5074fa57 2
66b4fb09 3#include "dz.h"
a5cc519e 4#if NDZ11 > 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
BJ
10 */
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"
5074fa57
BJ
19#include "../h/uba.h"
20#include "../h/conf.h"
21#include "../h/pdma.h"
771d8988 22#include "../h/bk.h"
cc343d94 23#include "../h/file.h"
1b05b375 24#include "../h/mx.h"
d3ebf5ee 25
7e00c42b
BJ
26/*
27 * Driver information for auto-configuration stuff.
28 */
3f3a34c3
BJ
29int dzcntrlr(), dzslave(), dzrint();
30struct uba_dinfo *dzinfo[NDZ11];
31u_short dzstd[] = { 0 };
3f3a34c3 32struct uba_driver dzdriver =
88d5b764 33 { dzcntrlr, dzslave, 0, 0, dzstd, "dz", dzinfo };
3f3a34c3 34
88d5b764 35#define NDZ (NDZ11*8)
5074fa57 36
7e00c42b
BJ
37/*
38 * Registers and bits
39 */
40
41/* Bits in dzlpr */
88d5b764
BJ
42#define BITS7 020
43#define BITS8 030
44#define TWOSB 040
45#define PENABLE 0100
46#define OPAR 0200
5074fa57 47
7e00c42b
BJ
48/* Bits in dzrbuf */
49#define DZ_PE 010000
50#define DZ_FE 020000
51#define DZ_DO 040000
52
53/* Bits in dzcsr */
54#define DZ_CLR 020 /* Reset dz */
55#define DZ_MSE 040 /* Master Scan Enable */
56#define DZ_RIE 0100 /* Receiver Interrupt Enable */
57#define DZ_SAE 010000 /* Silo Alarm Enable */
58#define DZ_TIE 040000 /* Transmit Interrupt Enable */
59#define DZ_IEN (DZ_MSE+DZ_RIE+DZ_TIE+DZ_SAE)
60
61/* Flags for modem-control */
62#define DZ_ON 1
63#define DZ_OFF 0
5074fa57 64
7e00c42b 65int dzstart(), dzxint(), dzdma();
771d8988 66int ttrstrt();
5074fa57
BJ
67struct tty dz_tty[NDZ];
68int dz_cnt = { NDZ };
9dca4f86 69int dzact;
5074fa57
BJ
70
71struct device {
7e00c42b
BJ
72 short dzcsr; /* control-status register */
73 short dzrbuf; /* receiver buffer */
74#define dzlpr dzrbuf /* line parameter reg is write of dzrbuf */
75 char dztcr; /* transmit control register */
76 char dzdtr; /* data terminal ready */
77 char dztbuf; /* transmit buffer */
78 char dzbrk; /* break control */
79#define dzmsr dzbrk /* modem status register */
5074fa57 80};
7e00c42b
BJ
81/*
82 * Software copy of dzbrk since it isn't readable
83 */
84char dz_brk[NDZ11];
5074fa57 85
7e00c42b
BJ
86/*
87 * The dz doesn't interrupt on carrier transitions, so
88 * we have to use a timer to watch it.
89 */
90char dz_timer; /* timer started? */
91
92/*
93 * Pdma structures for fast output code
94 */
3f3a34c3 95struct pdma dzpdma[NDZ];
7e00c42b 96
3f3a34c3
BJ
97char dz_speeds[] =
98 { 0,020,021,022,023,024,0,025,026,027,030,032,034,036,0,0 };
5074fa57 99
3f3a34c3
BJ
100dzcntrlr(ui, reg)
101 struct uba_dinfo *ui;
102 caddr_t reg;
103{
88d5b764
BJ
104 register int br, cvec;
105 register struct device *dzaddr = (struct device *)reg;
3f3a34c3 106
7e00c42b 107 dzaddr->dzcsr = DZ_TIE|DZ_MSE;
5aa9d5ea 108 dzaddr->dztcr = 1; /* enable any line */
88d5b764 109 DELAY(100000);
7e00c42b 110 dzaddr->dzcsr = DZ_CLR; /* reset everything */
88d5b764
BJ
111 if (cvec && cvec != 0x200)
112 cvec -= 4;
113 return (1);
3f3a34c3
BJ
114}
115
7e00c42b
BJ
116/*
117 * Called by auto-configure to initialize good dz's;
118 * set up pdma structures.
119 */
3f3a34c3
BJ
120dzslave(ui, reg, slaveno, uban)
121 register struct uba_dinfo *ui;
122 caddr_t reg;
123{
124 register struct pdma *pdp = &dzpdma[ui->ui_unit*8];
125 register struct tty *tp = &dz_tty[ui->ui_unit*8];
126 register int cnt;
3f3a34c3
BJ
127
128 for (cnt = 0; cnt < 8; cnt++) {
129 pdp->p_addr = (struct device *)reg;
130 pdp->p_arg = (int)tp;
131 pdp->p_fcn = dzxint;
132 pdp++, tp++;
133 }
3f3a34c3
BJ
134 return (1);
135}
136
5074fa57 137/*ARGSUSED*/
3f3a34c3
BJ
138dzopen(dev, flag)
139 dev_t dev;
5074fa57
BJ
140{
141 register struct tty *tp;
3f3a34c3 142 register int unit;
5074fa57
BJ
143 extern dzscan();
144
3f3a34c3
BJ
145 unit = minor(dev);
146 if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) {
5074fa57
BJ
147 u.u_error = ENXIO;
148 return;
149 }
150 if (dz_timer == 0) {
151 dz_timer++;
7e00c42b 152 timeout(dzscan, (caddr_t)0, HZ);
5074fa57 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;
5c6adb3e 225 int s;
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;
7e00c42b 245 if (c&DZ_DO)
88d5b764 246 printf("o");
7e00c42b 247 if (c&DZ_PE)
88d5b764
BJ
248 if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
249 || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
250 continue;
251 if (tp->t_line == NETLDISC) {
252 c &= 0177;
253 BKINPUT(c, tp);
254 } else
255 (*linesw[tp->t_line].l_rint)(c, tp);
5074fa57
BJ
256 }
257}
258
259/*ARGSUSED*/
260dzioctl(dev, cmd, addr, flag)
3f3a34c3
BJ
261 dev_t dev;
262 caddr_t addr;
5074fa57
BJ
263{
264 register struct tty *tp;
3f3a34c3
BJ
265 register int unit = minor(dev);
266 register int dz = unit >> 3;
5074fa57 267
3f3a34c3 268 tp = &dz_tty[unit];
771d8988
BJ
269 cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
270 if (cmd == 0)
271 return;
c3277147 272 if (ttioctl(tp, cmd, addr, flag)) {
5074fa57 273 if (cmd==TIOCSETP || cmd==TIOCSETN)
3f3a34c3 274 dzparam(unit);
dc44829a 275 } else switch(cmd) {
3f3a34c3 276
dc44829a 277 case TIOCSBRK:
3f988b2a 278 ((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
3f3a34c3 279 (dz_brk[dz] |= 1 << (unit&07));
dc44829a
BJ
280 break;
281 case TIOCCBRK:
3f988b2a 282 ((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
3f3a34c3 283 (dz_brk[dz] &= ~(1 << (unit&07)));
dc44829a
BJ
284 break;
285 case TIOCSDTR:
7e00c42b 286 dzmodem(unit, DZ_ON);
dc44829a
BJ
287 break;
288 case TIOCCDTR:
7e00c42b 289 dzmodem(unit, DZ_OFF);
dc44829a
BJ
290 break;
291 default:
5074fa57 292 u.u_error = ENOTTY;
dc44829a 293 }
5074fa57
BJ
294}
295
3f3a34c3
BJ
296dzparam(unit)
297 register int unit;
5074fa57
BJ
298{
299 register struct tty *tp;
300 register struct device *dzaddr;
3f3a34c3 301 register int lpr;
5074fa57 302
3f3a34c3
BJ
303 tp = &dz_tty[unit];
304 dzaddr = dzpdma[unit].p_addr;
5074fa57 305 dzaddr->dzcsr = DZ_IEN;
3f3a34c3 306 dzact |= (1<<(unit>>3));
5074fa57 307 if (tp->t_ispeed == 0) {
7e00c42b 308 dzmodem(unit, DZ_OFF); /* hang up line */
5074fa57
BJ
309 return;
310 }
3f3a34c3 311 lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07);
be5b7974 312 if ((tp->t_local&LLITOUT) || (tp->t_flags&RAW))
5074fa57
BJ
313 lpr |= BITS8;
314 else
315 lpr |= (BITS7|PENABLE);
316 if ((tp->t_flags & EVENP) == 0)
317 lpr |= OPAR;
7e00c42b
BJ
318 if (tp->t_ispeed == B110)
319 lpr |= TWOSB;
5074fa57
BJ
320 dzaddr->dzlpr = lpr;
321}
322
323dzxint(tp)
3f3a34c3 324 register struct tty *tp;
5074fa57
BJ
325{
326 register struct pdma *dp;
d3ebf5ee 327 register s;
5074fa57 328
7e00c42b 329 s = spl5(); /* block pdma interrupts */
3f3a34c3 330 dp = (struct pdma *)tp->t_addr;
5074fa57
BJ
331 tp->t_state &= ~BUSY;
332 if (tp->t_state & FLUSH)
333 tp->t_state &= ~FLUSH;
334 else
46014098 335 ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
5074fa57
BJ
336 if (tp->t_line)
337 (*linesw[tp->t_line].l_start)(tp);
338 else
339 dzstart(tp);
340 if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0)
3f3a34c3 341 dp->p_addr->dztcr &= ~(1 << (minor(tp->t_dev)&07));
d3ebf5ee 342 splx(s);
5074fa57
BJ
343}
344
345dzstart(tp)
3f3a34c3 346 register struct tty *tp;
5074fa57
BJ
347{
348 register struct pdma *dp;
349 register struct device *dzaddr;
3f3a34c3
BJ
350 register int cc;
351 int s;
5074fa57 352
3f3a34c3 353 dp = (struct pdma *)tp->t_addr;
5074fa57 354 dzaddr = dp->p_addr;
3f3a34c3 355 s = spl5();
5074fa57
BJ
356 if (tp->t_state & (TIMEOUT|BUSY|TTSTOP))
357 goto out;
b25a5292 358 if (tp->t_state&ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) {
5074fa57
BJ
359 tp->t_state &= ~ASLEEP;
360 if (tp->t_chan)
361 mcstart(tp->t_chan, (caddr_t)&tp->t_outq);
362 else
363 wakeup((caddr_t)&tp->t_outq);
364 }
365 if (tp->t_outq.c_cc == 0)
366 goto out;
367 if (tp->t_flags&RAW)
368 cc = ndqb(&tp->t_outq, 0);
369 else {
370 cc = ndqb(&tp->t_outq, 0200);
371 if (cc == 0) {
372 cc = getc(&tp->t_outq);
7e00c42b 373 timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6);
5074fa57
BJ
374 tp->t_state |= TIMEOUT;
375 goto out;
376 }
377 }
378 tp->t_state |= BUSY;
379 dp->p_end = dp->p_mem = tp->t_outq.c_cf;
380 dp->p_end += cc;
7e00c42b 381 dzaddr->dztcr |= 1 << (minor(tp->t_dev) & 07); /* force intr */
3f3a34c3
BJ
382out:
383 splx(s);
5074fa57
BJ
384}
385
386/*
387 * Stop output on a line.
5074fa57
BJ
388 */
389/*ARGSUSED*/
390dzstop(tp, flag)
3f3a34c3 391 register struct tty *tp;
5074fa57
BJ
392{
393 register struct pdma *dp;
394 register int s;
395
3f3a34c3 396 dp = (struct pdma *)tp->t_addr;
88d5b764 397 s = spl5();
5074fa57
BJ
398 if (tp->t_state & BUSY) {
399 dp->p_end = dp->p_mem;
3f3a34c3 400 if ((tp->t_state&TTSTOP)==0)
5074fa57 401 tp->t_state |= FLUSH;
5074fa57
BJ
402 }
403 splx(s);
404}
405
3f3a34c3
BJ
406dzmodem(unit, flag)
407 register int unit;
5074fa57
BJ
408{
409 register struct device *dzaddr;
410 register char bit;
411
3f3a34c3
BJ
412 dzaddr = dzpdma[unit].p_addr;
413 bit = 1<<(unit&07);
7e00c42b 414 if (flag == DZ_OFF)
5074fa57
BJ
415 dzaddr->dzdtr &= ~bit;
416 else
417 dzaddr->dzdtr |= bit;
418}
419
420dzscan()
421{
422 register i;
423 register struct device *dzaddr;
424 register bit;
425 register struct tty *tp;
426
427 for (i = 0; i < dz_cnt ; i++) {
428 dzaddr = dzpdma[i].p_addr;
429 tp = &dz_tty[i];
430 bit = 1<<(i&07);
5aa9d5ea
RE
431#ifdef BERT
432 if (dzaddr->dzmsr & bit || i == 6 || i == 7) {
433#else
434 if (dzaddr->dzmsr & bit) {
435#endif
5074fa57
BJ
436 /* carrier present */
437 if ((tp->t_state & CARR_ON) == 0) {
438 wakeup((caddr_t)&tp->t_rawq);
439 tp->t_state |= CARR_ON;
440 }
441 } else {
7e00c42b
BJ
442 if ((tp->t_state&CARR_ON) &&
443 (tp->t_local&LNOHANG)==0) {
5074fa57 444 /* carrier lost */
3f988b2a 445 if (tp->t_state&ISOPEN) {
dc44829a 446 gsignal(tp->t_pgrp, SIGHUP);
160cf9ed 447 gsignal(tp->t_pgrp, SIGCONT);
dc44829a 448 dzaddr->dzdtr &= ~bit;
cc343d94 449 flushtty(tp, FREAD|FWRITE);
dc44829a
BJ
450 }
451 tp->t_state &= ~CARR_ON;
5074fa57 452 }
5074fa57
BJ
453 }
454 }
455 timeout(dzscan, (caddr_t)0, 2*HZ);
456}
9dca4f86
BJ
457
458dztimer()
459{
88d5b764 460 int dz;
9dca4f86 461
88d5b764
BJ
462 for (dz = 0; dz < NDZ11; dz++)
463 dzrint(dz);
9dca4f86 464}
46014098
BJ
465
466/*
467 * Reset state of driver if UBA reset was necessary.
0072a3c2 468 * Reset parameters and restart transmission on open lines.
46014098 469 */
3f3a34c3 470dzreset(uban)
5aa9d5ea 471 int uban;
46014098 472{
3f3a34c3 473 register int unit;
46014098 474 register struct tty *tp;
5aa9d5ea
RE
475 register struct uba_dinfo *ui;
476 int any = 0;
46014098 477
3f3a34c3 478 for (unit = 0; unit < NDZ; unit++) {
5aa9d5ea
RE
479 ui = dzinfo[unit >> 3];
480 if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0)
481 continue;
482 if (any == 0) {
483 printf(" dz");
484 any++;
485 }
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