compilable first uba autoconf version
[unix-history] / usr / src / sys / vax / uba / dz.c
CommitLineData
3f3a34c3 1/* dz.c 4.10 %G% */
5074fa57 2
66b4fb09 3#include "dz.h"
a5cc519e 4#if NDZ11 > 0
5074fa57
BJ
5/*
6 * DZ-11 Driver
7 */
8#include "../h/param.h"
9#include "../h/systm.h"
10#include "../h/tty.h"
11#include "../h/dir.h"
12#include "../h/user.h"
13#include "../h/map.h"
14#include "../h/pte.h"
3f3a34c3 15#include "../h/buf.h"
5074fa57
BJ
16#include "../h/uba.h"
17#include "../h/conf.h"
18#include "../h/pdma.h"
771d8988 19#include "../h/bk.h"
cc343d94 20#include "../h/file.h"
1b05b375 21#include "../h/mx.h"
d3ebf5ee
BJ
22
23/*
24 * When running dz's using only SAE (silo alarm) on input
25 * it is necessary to call dzrint() at clock interrupt time.
26 * This is unsafe unless spl5()s in tty code are changed to
27 * spl6()s to block clock interrupts. Note that the dh driver
28 * currently in use works the same way as the dz, even though
29 * we could try to more intelligently manage its silo.
30 * Thus don't take this out if you have no dz's unless you
31 * change clock.c and dhtimer().
3f3a34c3
BJ
32 *
33 * SHOULD RATHER QUEUE SOFTWARE INTERRUPT AT CLOCK TIME.
d3ebf5ee
BJ
34 */
35#define spl5 spl6
5074fa57 36
3f3a34c3
BJ
37int dzcntrlr(), dzslave(), dzrint();
38struct uba_dinfo *dzinfo[NDZ11];
39u_short dzstd[] = { 0 };
40int (*dzivec[])() = { dzrint, 0 }; /* omit dzxint so we can do it here */
41struct uba_driver dzdriver =
42 { dzcntrlr, dzslave, (int (*)())0, 0, 0, dzstd, dzinfo, dzivec };
43
3f988b2a 44#define NDZ (NDZ11*8)
5074fa57
BJ
45
46#define BITS7 020
47#define BITS8 030
48#define TWOSB 040
49#define PENABLE 0100
50#define OPAR 0200
51#define MSE 040 /* Master Scan Enable */
52#define RIE 0100 /* Receiver Interrupt Enable */
9dca4f86
BJ
53#define SAE 010000 /* Silo Alarm Enable */
54#define TIE 040000 /* Transmit Interrupt Enable */
55#define DZ_IEN (MSE+RIE+TIE+SAE)
5074fa57
BJ
56#define PERROR 010000
57#define FRERROR 020000
9dca4f86 58#define OVERRUN 040000
5074fa57
BJ
59#define SSPEED 7 /* std speed = 300 baud */
60
5074fa57
BJ
61#define dzlpr dzrbuf
62#define dzmsr dzbrk
63#define ON 1
64#define OFF 0
65
66int dzstart();
67int dzxint();
3f3a34c3 68int dzdma();
771d8988 69int ttrstrt();
5074fa57
BJ
70struct tty dz_tty[NDZ];
71int dz_cnt = { NDZ };
9dca4f86 72int dzact;
5074fa57
BJ
73
74struct device {
75 short dzcsr;
76 short dzrbuf;
77 char dztcr;
78 char dzdtr;
79 char dztbuf;
80 char dzbrk;
81};
82
3f3a34c3 83struct pdma dzpdma[NDZ];
5074fa57 84char dz_timer;
3f3a34c3
BJ
85char dz_speeds[] =
86 { 0,020,021,022,023,024,0,025,026,027,030,032,034,036,0,0 };
87char dz_brk[NDZ11];
5074fa57 88
3f3a34c3
BJ
89dzcntrlr(ui, reg)
90 struct uba_dinfo *ui;
91 caddr_t reg;
92{
93
94 ((struct device *)reg)->dzcsr |= IENABLE;
95 /* get it to interrupt */
96}
97
98dzslave(ui, reg, slaveno, uban)
99 register struct uba_dinfo *ui;
100 caddr_t reg;
101{
102 register struct pdma *pdp = &dzpdma[ui->ui_unit*8];
103 register struct tty *tp = &dz_tty[ui->ui_unit*8];
104 register int cnt;
105 register int *urk = (int *)(&reg - 24); /* white magic */
106 caddr_t cp;
107 int urk2;
108
109 for (cnt = 0; cnt < 8; cnt++) {
110 pdp->p_addr = (struct device *)reg;
111 pdp->p_arg = (int)tp;
112 pdp->p_fcn = dzxint;
113 pdp++, tp++;
114 }
115 if ((cp = calloc(12)) == 0)
116 panic("dz iv nm\n");
117 uba_hd[uban].uh_vec[*urk] = (int (*)())cp; /* more white magic */
118 *cp++ = 0xbb; *cp++ = 0xff; *cp++ = 0xd0; /* black magic */
119 *cp++ = ui->ui_unit&0x3f; *cp++ = 0x50;
120 *cp++ = 0x17; *cp++ = 0x9f;
121 urk2 = (int)dzdma;
122 for (cnt = 0; cnt < 4; cnt++)
123 *cp++ = urk2, urk2 >>= 4; /* the spell ends */
124 return (1);
125}
126
5074fa57 127/*ARGSUSED*/
3f3a34c3
BJ
128dzopen(dev, flag)
129 dev_t dev;
5074fa57
BJ
130{
131 register struct tty *tp;
3f3a34c3 132 register int unit;
5074fa57
BJ
133 extern dzscan();
134
3f3a34c3
BJ
135 unit = minor(dev);
136 if (unit >= dz_cnt || dzpdma[unit].p_addr == 0) {
5074fa57
BJ
137 u.u_error = ENXIO;
138 return;
139 }
140 if (dz_timer == 0) {
141 dz_timer++;
142 timeout(dzscan, (caddr_t)0, 60);
143 }
3f3a34c3
BJ
144 tp = &dz_tty[unit];
145 tp->t_addr = (caddr_t)&dzpdma[unit];
5074fa57
BJ
146 tp->t_oproc = dzstart;
147 tp->t_iproc = NULL;
148 tp->t_state |= WOPEN;
149 if ((tp->t_state & ISOPEN) == 0) {
150 ttychars(tp);
151 tp->t_ospeed = tp->t_ispeed = SSPEED;
152 tp->t_flags = ODDP|EVENP|ECHO;
153 /*tp->t_state |= HUPCLS;*/
3f3a34c3 154 dzparam(unit);
5074fa57
BJ
155 } else if (tp->t_state&XCLUDE && u.u_uid != 0) {
156 u.u_error = EBUSY;
157 return;
158 }
3f3a34c3 159 dzmodem(unit, ON);
771d8988 160 (void) spl5();
5074fa57
BJ
161 while ((tp->t_state & CARR_ON) == 0) {
162 tp->t_state |= WOPEN;
163 sleep((caddr_t)&tp->t_rawq, TTIPRI);
164 }
771d8988 165 (void) spl0();
3f3a34c3 166 (*linesw[tp->t_line].l_open)(dev, tp);
5074fa57
BJ
167}
168
3f3a34c3
BJ
169/*ARGSUSED*/
170dzclose(dev, flag)
171 dev_t dev;
5074fa57
BJ
172{
173 register struct tty *tp;
3f3a34c3
BJ
174 register int unit;
175 int dz;
5074fa57 176
3f3a34c3
BJ
177 unit = minor(dev);
178 dz = unit >> 3;
179 tp = &dz_tty[unit];
5074fa57 180 (*linesw[tp->t_line].l_close)(tp);
e60fc718 181 ((struct pdma *)(tp->t_addr))->p_addr->dzbrk =
3f3a34c3 182 (dz_brk[dz] &= ~(1 << (unit&07)));
5074fa57 183 if (tp->t_state & HUPCLS)
3f3a34c3 184 dzmodem(unit, OFF);
5074fa57
BJ
185 ttyclose(tp);
186}
187
3f3a34c3
BJ
188dzread(dev)
189 dev_t dev;
5074fa57
BJ
190{
191 register struct tty *tp;
192
3f3a34c3 193 tp = &dz_tty[minor(dev)];
5074fa57
BJ
194 (*linesw[tp->t_line].l_read)(tp);
195}
196
3f3a34c3
BJ
197dzwrite(dev)
198 dev_t dev;
5074fa57
BJ
199{
200 register struct tty *tp;
201
3f3a34c3 202 tp = &dz_tty[minor(dev)];
5074fa57
BJ
203 (*linesw[tp->t_line].l_write)(tp);
204}
205
9dca4f86 206/*ARGSUSED*/
3f3a34c3
BJ
207dzrint(dz)
208 int dz;
5074fa57
BJ
209{
210 register struct tty *tp;
211 register int c;
212 register struct device *dzaddr;
9dca4f86 213 register struct tty *tp0;
3f3a34c3 214 register int unit;
5c6adb3e 215 int s;
5074fa57 216
5c6adb3e 217 s = spl6(); /* see comment in clock.c */
9dca4f86 218 /* as long as we are here, service them all */
3f3a34c3
BJ
219 for (unit = 0; unit < NDZ; unit += 8) {
220 if ((dzact & (1<<(unit>>3))) == 0)
5074fa57 221 continue;
3f3a34c3
BJ
222 dzaddr = dzpdma[unit].p_addr;
223 tp0 = &dz_tty[unit];
9dca4f86
BJ
224 while ((c = dzaddr->dzrbuf) < 0) { /* char present */
225 tp = tp0 + ((c>>8)&07);
226 if (tp >= &dz_tty[dz_cnt])
5074fa57 227 continue;
9dca4f86
BJ
228 if ((tp->t_state & ISOPEN) == 0) {
229 wakeup((caddr_t)&tp->t_rawq);
230 continue;
231 }
232 if (c&FRERROR)
233 /* framing error = break */
234 if (tp->t_flags & RAW)
235 c = 0; /* null for getty */
236 else
dc44829a
BJ
237#ifdef IIASA
238 continue;
239#else
1c17c385 240 c = tun.t_intrc;
dc44829a 241#endif
9dca4f86
BJ
242 if (c&OVERRUN)
243 printf("o");
244 if (c&PERROR)
245 /* parity error */
246 if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
247 || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
248 continue;
5c6adb3e 249 if (tp->t_line == NETLDISC) {
771d8988 250 c &= 0177;
dc44829a 251 BKINPUT(c, tp);
771d8988 252 } else
771d8988 253 (*linesw[tp->t_line].l_rint)(c, tp);
9dca4f86 254 }
5074fa57 255 }
5c6adb3e 256 splx(s);
5074fa57
BJ
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:
3f3a34c3 286 dzmodem(unit, ON);
dc44829a
BJ
287 break;
288 case TIOCCDTR:
3f3a34c3 289 dzmodem(unit, 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) {
3f3a34c3 308 dzmodem(unit, OFF); /* hang up line */
5074fa57
BJ
309 return;
310 }
3f3a34c3 311 lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07);
3f988b2a 312#ifndef IIASA
be5b7974 313 if ((tp->t_local&LLITOUT) || (tp->t_flags&RAW))
5074fa57
BJ
314 lpr |= BITS8;
315 else
316 lpr |= (BITS7|PENABLE);
317 if ((tp->t_flags & EVENP) == 0)
318 lpr |= OPAR;
3f988b2a
BJ
319#else IIASA
320 if ((tp->t_flags & (EVENP|ODDP)) == (EVENP|ODDP))
321 lpr |= BITS8;
322 else if (tp->t_flags & EVENP)
323 lpr |= (BITS7|PENABLE);
324 else if (tp->t_flags & ODDP)
325 lpr |= (BITS7|OPAR|PENABLE);
326 else
327 lpr |= BITS7;
328#endif IIASA
5074fa57
BJ
329 if (tp->t_ispeed == 3)
330 lpr |= TWOSB; /* 110 baud: 2 stop bits */
331 dzaddr->dzlpr = lpr;
332}
333
334dzxint(tp)
3f3a34c3 335 register struct tty *tp;
5074fa57
BJ
336{
337 register struct pdma *dp;
d3ebf5ee
BJ
338 register s;
339 s = spl6(); /* block the clock */
5074fa57 340
3f3a34c3 341 dp = (struct pdma *)tp->t_addr;
5074fa57
BJ
342 tp->t_state &= ~BUSY;
343 if (tp->t_state & FLUSH)
344 tp->t_state &= ~FLUSH;
345 else
46014098 346 ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
5074fa57
BJ
347 if (tp->t_line)
348 (*linesw[tp->t_line].l_start)(tp);
349 else
350 dzstart(tp);
351 if (tp->t_outq.c_cc == 0 || (tp->t_state&BUSY)==0)
3f3a34c3 352 dp->p_addr->dztcr &= ~(1 << (minor(tp->t_dev)&07));
d3ebf5ee 353 splx(s);
5074fa57
BJ
354}
355
356dzstart(tp)
3f3a34c3 357 register struct tty *tp;
5074fa57
BJ
358{
359 register struct pdma *dp;
360 register struct device *dzaddr;
3f3a34c3
BJ
361 register int cc;
362 int s;
5074fa57 363
3f3a34c3 364 dp = (struct pdma *)tp->t_addr;
5074fa57 365 dzaddr = dp->p_addr;
3f3a34c3 366 s = spl5();
5074fa57
BJ
367 if (tp->t_state & (TIMEOUT|BUSY|TTSTOP))
368 goto out;
b25a5292 369 if (tp->t_state&ASLEEP && tp->t_outq.c_cc <= TTLOWAT(tp)) {
5074fa57
BJ
370 tp->t_state &= ~ASLEEP;
371 if (tp->t_chan)
372 mcstart(tp->t_chan, (caddr_t)&tp->t_outq);
373 else
374 wakeup((caddr_t)&tp->t_outq);
375 }
376 if (tp->t_outq.c_cc == 0)
377 goto out;
378 if (tp->t_flags&RAW)
379 cc = ndqb(&tp->t_outq, 0);
380 else {
381 cc = ndqb(&tp->t_outq, 0200);
382 if (cc == 0) {
383 cc = getc(&tp->t_outq);
384 timeout(ttrstrt, (caddr_t)tp, (cc&0177) + 6);
385 tp->t_state |= TIMEOUT;
386 goto out;
387 }
388 }
389 tp->t_state |= BUSY;
390 dp->p_end = dp->p_mem = tp->t_outq.c_cf;
391 dp->p_end += cc;
3f3a34c3
BJ
392 dzaddr->dztcr |= 1 << (minor(tp->t_dev) & 07);
393out:
394 splx(s);
5074fa57
BJ
395}
396
397/*
398 * Stop output on a line.
399 * Assume call is made at spl6.
400 */
401/*ARGSUSED*/
402dzstop(tp, flag)
3f3a34c3 403 register struct tty *tp;
5074fa57
BJ
404{
405 register struct pdma *dp;
406 register int s;
407
3f3a34c3 408 dp = (struct pdma *)tp->t_addr;
5074fa57
BJ
409 s = spl6();
410 if (tp->t_state & BUSY) {
411 dp->p_end = dp->p_mem;
3f3a34c3 412 if ((tp->t_state&TTSTOP)==0)
5074fa57 413 tp->t_state |= FLUSH;
5074fa57
BJ
414 }
415 splx(s);
416}
417
3f3a34c3
BJ
418dzmodem(unit, flag)
419 register int unit;
5074fa57
BJ
420{
421 register struct device *dzaddr;
422 register char bit;
423
3f3a34c3
BJ
424 dzaddr = dzpdma[unit].p_addr;
425 bit = 1<<(unit&07);
5074fa57
BJ
426 if (flag == OFF)
427 dzaddr->dzdtr &= ~bit;
428 else
429 dzaddr->dzdtr |= bit;
430}
431
432dzscan()
433{
434 register i;
435 register struct device *dzaddr;
436 register bit;
437 register struct tty *tp;
438
439 for (i = 0; i < dz_cnt ; i++) {
440 dzaddr = dzpdma[i].p_addr;
441 tp = &dz_tty[i];
442 bit = 1<<(i&07);
0ff318b2 443 if (dzaddr->dzmsr & bit || (i == 6 || i == 7)) {
5074fa57
BJ
444 /* carrier present */
445 if ((tp->t_state & CARR_ON) == 0) {
446 wakeup((caddr_t)&tp->t_rawq);
447 tp->t_state |= CARR_ON;
448 }
449 } else {
3f3a34c3 450 if ((tp->t_state&CARR_ON) && (tp->t_local&LNOHANG)==0) {
5074fa57 451 /* carrier lost */
3f988b2a 452 if (tp->t_state&ISOPEN) {
dc44829a 453 gsignal(tp->t_pgrp, SIGHUP);
160cf9ed 454 gsignal(tp->t_pgrp, SIGCONT);
dc44829a 455 dzaddr->dzdtr &= ~bit;
cc343d94 456 flushtty(tp, FREAD|FWRITE);
dc44829a
BJ
457 }
458 tp->t_state &= ~CARR_ON;
5074fa57 459 }
5074fa57
BJ
460 }
461 }
462 timeout(dzscan, (caddr_t)0, 2*HZ);
463}
9dca4f86
BJ
464
465dztimer()
466{
467
468 dzrint(0);
469}
46014098
BJ
470
471/*
472 * Reset state of driver if UBA reset was necessary.
0072a3c2 473 * Reset parameters and restart transmission on open lines.
46014098 474 */
3f3a34c3 475dzreset(uban)
46014098 476{
3f3a34c3 477 register int unit;
46014098
BJ
478 register struct tty *tp;
479
3f3a34c3
BJ
480 /*** WE SHOULD LOOK TO SEE IF WE CARE ABOUT UBA BEING RESET ***/
481
46014098 482 printf(" dz");
3f3a34c3
BJ
483 for (unit = 0; unit < NDZ; unit++) {
484 tp = &dz_tty[unit];
46014098 485 if (tp->t_state & (ISOPEN|WOPEN)) {
3f3a34c3
BJ
486 dzparam(unit);
487 dzmodem(unit, ON);
0072a3c2
BJ
488 tp->t_state &= ~BUSY;
489 dzstart(tp);
46014098
BJ
490 }
491 }
492 dztimer();
46014098 493}
a5cc519e 494#endif