name changes
[unix-history] / usr / src / sys / vax / uba / dz.c
CommitLineData
be2b272c 1/* dz.c 4.16 %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"
7e286c72 19#include "../h/vm.h"
5074fa57
BJ
20#include "../h/uba.h"
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();
3f3a34c3
BJ
31struct uba_dinfo *dzinfo[NDZ11];
32u_short dzstd[] = { 0 };
3f3a34c3 33struct uba_driver dzdriver =
71236e46 34 { dzprobe, 0, dzattach, 0, dzstd, "dz", dzinfo };
3f3a34c3 35
88d5b764 36#define NDZ (NDZ11*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();
5074fa57
BJ
68struct tty dz_tty[NDZ];
69int dz_cnt = { NDZ };
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 */
85char dz_brk[NDZ11];
7e286c72 86char dzsoftCAR[NDZ11];
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 */
3f3a34c3 97struct pdma dzpdma[NDZ];
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
BJ
108#ifdef lint
109 br = 0; br = cvec; cvec = br;
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)
3f3a34c3 121 register struct uba_dinfo *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;
3f3a34c3 126
71236e46
BJ
127 for (cntr = 0; cntr < 8; cntr++) {
128 pdp->p_addr = (struct device *)ui->ui_addr;
3f3a34c3
BJ
129 pdp->p_arg = (int)tp;
130 pdp->p_fcn = dzxint;
131 pdp++, tp++;
132 }
7e286c72 133 dzsoftCAR[ui->ui_unit] = ui->ui_flags;
be2b272c
BJ
134 if (dz_timer == 0) {
135 dz_timer++;
136 timeout(dzscan, (caddr_t)0, HZ);
137 }
3f3a34c3
BJ
138 return (1);
139}
140
5074fa57 141/*ARGSUSED*/
3f3a34c3
BJ
142dzopen(dev, flag)
143 dev_t dev;
5074fa57
BJ
144{
145 register struct tty *tp;
3f3a34c3 146 register int unit;
5074fa57
BJ
147 extern dzscan();
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;
5074fa57 225
88d5b764
BJ
226 if ((dzact & (1<<dz)) == 0)
227 return;
228 unit = dz * 8;
229 dzaddr = dzpdma[unit].p_addr;
230 tp0 = &dz_tty[unit];
231 while ((c = dzaddr->dzrbuf) < 0) { /* char present */
232 tp = tp0 + ((c>>8)&07);
233 if (tp >= &dz_tty[dz_cnt])
234 continue;
235 if ((tp->t_state & ISOPEN) == 0) {
236 wakeup((caddr_t)&tp->t_rawq);
5074fa57 237 continue;
9dca4f86 238 }
7e00c42b 239 if (c&DZ_FE)
88d5b764 240 if (tp->t_flags & RAW)
7e00c42b 241 c = 0;
88d5b764
BJ
242 else
243 c = tun.t_intrc;
7e00c42b 244 if (c&DZ_DO)
88d5b764 245 printf("o");
7e00c42b 246 if (c&DZ_PE)
88d5b764
BJ
247 if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
248 || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
249 continue;
250 if (tp->t_line == NETLDISC) {
251 c &= 0177;
252 BKINPUT(c, tp);
253 } else
254 (*linesw[tp->t_line].l_rint)(c, tp);
5074fa57
BJ
255 }
256}
257
258/*ARGSUSED*/
259dzioctl(dev, cmd, addr, flag)
3f3a34c3
BJ
260 dev_t dev;
261 caddr_t addr;
5074fa57
BJ
262{
263 register struct tty *tp;
3f3a34c3
BJ
264 register int unit = minor(dev);
265 register int dz = unit >> 3;
5074fa57 266
3f3a34c3 267 tp = &dz_tty[unit];
771d8988
BJ
268 cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
269 if (cmd == 0)
270 return;
c3277147 271 if (ttioctl(tp, cmd, addr, flag)) {
5074fa57 272 if (cmd==TIOCSETP || cmd==TIOCSETN)
3f3a34c3 273 dzparam(unit);
dc44829a 274 } else switch(cmd) {
3f3a34c3 275
dc44829a 276 case TIOCSBRK:
3f988b2a 277 ((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
3f3a34c3 278 (dz_brk[dz] |= 1 << (unit&07));
dc44829a
BJ
279 break;
280 case TIOCCBRK:
3f988b2a 281 ((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
3f3a34c3 282 (dz_brk[dz] &= ~(1 << (unit&07)));
dc44829a
BJ
283 break;
284 case TIOCSDTR:
7e00c42b 285 dzmodem(unit, DZ_ON);
dc44829a
BJ
286 break;
287 case TIOCCDTR:
7e00c42b 288 dzmodem(unit, DZ_OFF);
dc44829a
BJ
289 break;
290 default:
5074fa57 291 u.u_error = ENOTTY;
dc44829a 292 }
5074fa57
BJ
293}
294
3f3a34c3
BJ
295dzparam(unit)
296 register int unit;
5074fa57
BJ
297{
298 register struct tty *tp;
299 register struct device *dzaddr;
3f3a34c3 300 register int lpr;
5074fa57 301
3f3a34c3
BJ
302 tp = &dz_tty[unit];
303 dzaddr = dzpdma[unit].p_addr;
5074fa57 304 dzaddr->dzcsr = DZ_IEN;
3f3a34c3 305 dzact |= (1<<(unit>>3));
5074fa57 306 if (tp->t_ispeed == 0) {
7e00c42b 307 dzmodem(unit, DZ_OFF); /* hang up line */
5074fa57
BJ
308 return;
309 }
3f3a34c3 310 lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07);
be5b7974 311 if ((tp->t_local&LLITOUT) || (tp->t_flags&RAW))
5074fa57
BJ
312 lpr |= BITS8;
313 else
314 lpr |= (BITS7|PENABLE);
315 if ((tp->t_flags & EVENP) == 0)
316 lpr |= OPAR;
7e00c42b
BJ
317 if (tp->t_ispeed == B110)
318 lpr |= TWOSB;
5074fa57
BJ
319 dzaddr->dzlpr = lpr;
320}
321
322dzxint(tp)
3f3a34c3 323 register struct tty *tp;
5074fa57
BJ
324{
325 register struct pdma *dp;
d3ebf5ee 326 register s;
5074fa57 327
7e00c42b 328 s = spl5(); /* block pdma interrupts */
3f3a34c3 329 dp = (struct pdma *)tp->t_addr;
5074fa57
BJ
330 tp->t_state &= ~BUSY;
331 if (tp->t_state & FLUSH)
332 tp->t_state &= ~FLUSH;
333 else
46014098 334 ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
5074fa57
BJ
335 if (tp->t_line)
336 (*linesw[tp->t_line].l_start)(tp);
337 else
338 dzstart(tp);
339 if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0)
3f3a34c3 340 dp->p_addr->dztcr &= ~(1 << (minor(tp->t_dev)&07));
d3ebf5ee 341 splx(s);
5074fa57
BJ
342}
343
344dzstart(tp)
3f3a34c3 345 register struct tty *tp;
5074fa57
BJ
346{
347 register struct pdma *dp;
348 register struct device *dzaddr;
3f3a34c3
BJ
349 register int cc;
350 int s;
5074fa57 351
3f3a34c3 352 dp = (struct pdma *)tp->t_addr;
5074fa57 353 dzaddr = dp->p_addr;
3f3a34c3 354 s = spl5();
5074fa57
BJ
355 if (tp->t_state & (TIMEOUT|BUSY|TTSTOP))
356 goto out;
b25a5292 357 if (tp->t_state&ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) {
5074fa57
BJ
358 tp->t_state &= ~ASLEEP;
359 if (tp->t_chan)
360 mcstart(tp->t_chan, (caddr_t)&tp->t_outq);
361 else
362 wakeup((caddr_t)&tp->t_outq);
363 }
364 if (tp->t_outq.c_cc == 0)
365 goto out;
366 if (tp->t_flags&RAW)
367 cc = ndqb(&tp->t_outq, 0);
368 else {
369 cc = ndqb(&tp->t_outq, 0200);
370 if (cc == 0) {
371 cc = getc(&tp->t_outq);
7e00c42b 372 timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6);
5074fa57
BJ
373 tp->t_state |= TIMEOUT;
374 goto out;
375 }
376 }
377 tp->t_state |= BUSY;
378 dp->p_end = dp->p_mem = tp->t_outq.c_cf;
379 dp->p_end += cc;
7e00c42b 380 dzaddr->dztcr |= 1 << (minor(tp->t_dev) & 07); /* force intr */
3f3a34c3
BJ
381out:
382 splx(s);
5074fa57
BJ
383}
384
385/*
386 * Stop output on a line.
5074fa57
BJ
387 */
388/*ARGSUSED*/
389dzstop(tp, flag)
3f3a34c3 390 register struct tty *tp;
5074fa57
BJ
391{
392 register struct pdma *dp;
393 register int s;
394
3f3a34c3 395 dp = (struct pdma *)tp->t_addr;
88d5b764 396 s = spl5();
5074fa57
BJ
397 if (tp->t_state & BUSY) {
398 dp->p_end = dp->p_mem;
3f3a34c3 399 if ((tp->t_state&TTSTOP)==0)
5074fa57 400 tp->t_state |= FLUSH;
5074fa57
BJ
401 }
402 splx(s);
403}
404
3f3a34c3
BJ
405dzmodem(unit, flag)
406 register int unit;
5074fa57
BJ
407{
408 register struct device *dzaddr;
409 register char bit;
410
3f3a34c3
BJ
411 dzaddr = dzpdma[unit].p_addr;
412 bit = 1<<(unit&07);
7e00c42b 413 if (flag == DZ_OFF)
5074fa57
BJ
414 dzaddr->dzdtr &= ~bit;
415 else
416 dzaddr->dzdtr |= bit;
417}
418
419dzscan()
420{
421 register i;
422 register struct device *dzaddr;
423 register bit;
424 register struct tty *tp;
425
426 for (i = 0; i < dz_cnt ; i++) {
427 dzaddr = dzpdma[i].p_addr;
be2b272c
BJ
428 if (dzaddr == 0)
429 continue;
5074fa57
BJ
430 tp = &dz_tty[i];
431 bit = 1<<(i&07);
71236e46 432 if ((dzsoftCAR[i>>3]&bit) || (dzaddr->dzmsr&bit)) {
5074fa57
BJ
433 /* carrier present */
434 if ((tp->t_state & CARR_ON) == 0) {
435 wakeup((caddr_t)&tp->t_rawq);
436 tp->t_state |= CARR_ON;
437 }
438 } else {
7e00c42b
BJ
439 if ((tp->t_state&CARR_ON) &&
440 (tp->t_local&LNOHANG)==0) {
5074fa57 441 /* carrier lost */
3f988b2a 442 if (tp->t_state&ISOPEN) {
dc44829a 443 gsignal(tp->t_pgrp, SIGHUP);
160cf9ed 444 gsignal(tp->t_pgrp, SIGCONT);
dc44829a 445 dzaddr->dzdtr &= ~bit;
cc343d94 446 flushtty(tp, FREAD|FWRITE);
dc44829a
BJ
447 }
448 tp->t_state &= ~CARR_ON;
5074fa57 449 }
5074fa57
BJ
450 }
451 }
452 timeout(dzscan, (caddr_t)0, 2*HZ);
453}
9dca4f86
BJ
454
455dztimer()
456{
88d5b764 457 int dz;
9dca4f86 458
88d5b764
BJ
459 for (dz = 0; dz < NDZ11; dz++)
460 dzrint(dz);
9dca4f86 461}
46014098
BJ
462
463/*
464 * Reset state of driver if UBA reset was necessary.
0072a3c2 465 * Reset parameters and restart transmission on open lines.
46014098 466 */
3f3a34c3 467dzreset(uban)
5aa9d5ea 468 int uban;
46014098 469{
3f3a34c3 470 register int unit;
46014098 471 register struct tty *tp;
5aa9d5ea
RE
472 register struct uba_dinfo *ui;
473 int any = 0;
46014098 474
3f3a34c3 475 for (unit = 0; unit < NDZ; unit++) {
5aa9d5ea
RE
476 ui = dzinfo[unit >> 3];
477 if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0)
478 continue;
479 if (any == 0) {
480 printf(" dz");
481 any++;
482 }
3f3a34c3 483 tp = &dz_tty[unit];
46014098 484 if (tp->t_state & (ISOPEN|WOPEN)) {
3f3a34c3 485 dzparam(unit);
7e00c42b 486 dzmodem(unit, DZ_ON);
0072a3c2
BJ
487 tp->t_state &= ~BUSY;
488 dzstart(tp);
46014098
BJ
489 }
490 }
491 dztimer();
46014098 492}
a5cc519e 493#endif