|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: *
6: * @(#)dz.c 7.1 (Berkeley) 6/5/86
7: */
8:
9: #include "dz.h"
10: #if NDZ > 0
11: /*
12: * DZ-11/DZ-32 Driver
13: *
14: * This driver mimics dh.c; see it for explanation of common code.
15: */
16: #include "bk.h"
17:
18: #include "../machine/pte.h"
19:
20: #include "param.h"
21: #include "systm.h"
22: #include "ioctl.h"
23: #include "tty.h"
24: #include "dir.h"
25: #include "user.h"
26: #include "proc.h"
27: #include "map.h"
28: #include "buf.h"
29: #include "vm.h"
30: #include "conf.h"
31: #include "bkmac.h"
32: #include "file.h"
33: #include "uio.h"
34: #include "kernel.h"
35: #include "syslog.h"
36:
37: #include "pdma.h"
38: #include "ubavar.h"
39: #include "dzreg.h"
40:
41: /*
42: * Driver information for auto-configuration stuff.
43: */
44: int dzprobe(), dzattach(), dzrint();
45: struct uba_device *dzinfo[NDZ];
46: u_short dzstd[] = { 0 };
47: struct uba_driver dzdriver =
48: { dzprobe, 0, dzattach, 0, dzstd, "dz", dzinfo };
49:
50: #define NDZLINE (NDZ*8)
51: #define FASTTIMER (hz/30) /* rate to drain silos, when in use */
52:
53: int dzstart(), dzxint(), dzdma();
54: int ttrstrt();
55: struct tty dz_tty[NDZLINE];
56: int dz_cnt = { NDZLINE };
57: int dzact;
58: int dzsilos; /* mask of dz's with silo in use */
59: int dzchars[NDZ]; /* recent input count */
60: int dzrate[NDZ]; /* smoothed input count */
61: int dztimerintvl; /* time interval for dztimer */
62: int dzhighrate = 100; /* silo on if dzchars > dzhighrate */
63: int dzlowrate = 75; /* silo off if dzrate < dzlowrate */
64:
65: #define dzwait(x) while (((x)->dzlcs & DZ_ACK) == 0)
66:
67: /*
68: * Software copy of dzbrk since it isn't readable
69: */
70: char dz_brk[NDZ];
71: char dzsoftCAR[NDZ];
72: char dz_lnen[NDZ]; /* saved line enable bits for DZ32 */
73:
74: /*
75: * The dz11 doesn't interrupt on carrier transitions, so
76: * we have to use a timer to watch it.
77: */
78: char dz_timer; /* timer started? */
79:
80: /*
81: * Pdma structures for fast output code
82: */
83: struct pdma dzpdma[NDZLINE];
84:
85: char dz_speeds[] =
86: { 0,020,021,022,023,024,0,025,026,027,030,032,034,036,037,0 };
87:
88: #ifndef PORTSELECTOR
89: #define ISPEED B9600
90: #define IFLAGS (EVENP|ODDP|ECHO)
91: #else
92: #define ISPEED B4800
93: #define IFLAGS (EVENP|ODDP)
94: #endif
95:
96: dzprobe(reg)
97: caddr_t reg;
98: {
99: register int br, cvec;
100: register struct dzdevice *dzaddr = (struct dzdevice *)reg;
101:
102: #ifdef lint
103: br = 0; cvec = br; br = cvec;
104: dzrint(0); dzxint((struct tty *)0);
105: #endif
106: dzaddr->dzcsr = DZ_TIE|DZ_MSE|DZ_32;
107: if (dzaddr->dzcsr & DZ_32)
108: dzaddr->dzlnen = 1;
109: else
110: dzaddr->dztcr = 1; /* enable any line */
111: DELAY(100000);
112: dzaddr->dzcsr = DZ_CLR|DZ_32; /* reset everything */
113: if (cvec && cvec != 0x200)
114: cvec -= 4;
115: return (sizeof (struct dzdevice));
116: }
117:
118: dzattach(ui)
119: register struct uba_device *ui;
120: {
121: register struct pdma *pdp = &dzpdma[ui->ui_unit*8];
122: register struct tty *tp = &dz_tty[ui->ui_unit*8];
123: register int cntr;
124: extern dzscan();
125:
126: for (cntr = 0; cntr < 8; cntr++) {
127: pdp->p_addr = (struct dzdevice *)ui->ui_addr;
128: pdp->p_arg = (int)tp;
129: pdp->p_fcn = dzxint;
130: pdp++, tp++;
131: }
132: dzsoftCAR[ui->ui_unit] = ui->ui_flags;
133: if (dz_timer == 0) {
134: dz_timer++;
135: timeout(dzscan, (caddr_t)0, hz);
136: dztimerintvl = FASTTIMER;
137: }
138: }
139:
140: /*ARGSUSED*/
141: dzopen(dev, flag)
142: dev_t dev;
143: {
144: register struct tty *tp;
145: register int unit;
146:
147: unit = minor(dev);
148: if (unit >= dz_cnt || dzpdma[unit].p_addr == 0)
149: return (ENXIO);
150: tp = &dz_tty[unit];
151: tp->t_addr = (caddr_t)&dzpdma[unit];
152: tp->t_oproc = dzstart;
153: if ((tp->t_state & TS_ISOPEN) == 0) {
154: ttychars(tp);
155: #ifndef PORTSELECTOR
156: if (tp->t_ispeed == 0) {
157: #else
158: tp->t_state |= TS_HUPCLS;
159: #endif PORTSELECTOR
160: tp->t_ispeed = ISPEED;
161: tp->t_ospeed = ISPEED;
162: tp->t_flags = IFLAGS;
163: #ifndef PORTSELECTOR
164: }
165: #endif PORTSELECTOR
166: dzparam(unit);
167: } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0)
168: return (EBUSY);
169: (void) dzmctl(dev, DZ_ON, DMSET);
170: (void) spl5();
171: while ((tp->t_state & TS_CARR_ON) == 0) {
172: tp->t_state |= TS_WOPEN;
173: sleep((caddr_t)&tp->t_rawq, TTIPRI);
174: }
175: (void) spl0();
176: return ((*linesw[tp->t_line].l_open)(dev, tp));
177: }
178:
179: /*ARGSUSED*/
180: dzclose(dev, flag)
181: dev_t dev;
182: {
183: register struct tty *tp;
184: register int unit;
185: register struct dzdevice *dzaddr;
186: int dz;
187:
188: unit = minor(dev);
189: dz = unit >> 3;
190: tp = &dz_tty[unit];
191: (*linesw[tp->t_line].l_close)(tp);
192: dzaddr = dzpdma[unit].p_addr;
193: if (dzaddr->dzcsr&DZ_32)
194: (void) dzmctl(dev, DZ_BRK, DMBIC);
195: else
196: dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07)));
197: if ((tp->t_state&(TS_HUPCLS|TS_WOPEN)) || (tp->t_state&TS_ISOPEN) == 0)
198: (void) dzmctl(dev, DZ_OFF, DMSET);
199: ttyclose(tp);
200: }
201:
202: dzread(dev, uio)
203: dev_t dev;
204: struct uio *uio;
205: {
206: register struct tty *tp;
207:
208: tp = &dz_tty[minor(dev)];
209: return ((*linesw[tp->t_line].l_read)(tp, uio));
210: }
211:
212: dzwrite(dev, uio)
213: dev_t dev;
214: struct uio *uio;
215: {
216: register struct tty *tp;
217:
218: tp = &dz_tty[minor(dev)];
219: return ((*linesw[tp->t_line].l_write)(tp, uio));
220: }
221:
222: /*ARGSUSED*/
223: dzrint(dz)
224: int dz;
225: {
226: register struct tty *tp;
227: register int c;
228: register struct dzdevice *dzaddr;
229: register struct tty *tp0;
230: register int unit;
231: int overrun = 0;
232:
233: if ((dzact & (1<<dz)) == 0)
234: return;
235: unit = dz * 8;
236: dzaddr = dzpdma[unit].p_addr;
237: tp0 = &dz_tty[unit];
238: dzaddr->dzcsr &= ~(DZ_RIE|DZ_MIE); /* the manual says this song */
239: dzaddr->dzcsr |= DZ_RIE|DZ_MIE; /* and dance is necessary */
240: while (dzaddr->dzcsr & DZ_MSC) { /* DZ32 modem change interrupt */
241: c = dzaddr->dzmtsr;
242: tp = tp0 + (c&7);
243: if (tp >= &dz_tty[dz_cnt])
244: break;
245: dzaddr->dzlcs = c&7; /* get status of modem lines */
246: dzwait(dzaddr); /* wait for them */
247: if (c & DZ_CD) /* carrier status change? */
248: if (dzaddr->dzlcs & DZ_CD) { /* carrier up? */
249: /* carrier present */
250: (void)(*linesw[tp->t_line].l_modem)(tp, 1);
251: } else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0)
252: dzaddr->dzlcs = DZ_ACK|(c&7);
253: }
254: while ((c = dzaddr->dzrbuf) < 0) { /* char present */
255: dzchars[dz]++;
256: tp = tp0 + ((c>>8)&07);
257: if (tp >= &dz_tty[dz_cnt])
258: continue;
259: if ((tp->t_state & TS_ISOPEN) == 0) {
260: wakeup((caddr_t)&tp->t_rawq);
261: #ifdef PORTSELECTOR
262: if ((tp->t_state&TS_WOPEN) == 0)
263: #endif
264: continue;
265: }
266: if (c&DZ_FE)
267: if (tp->t_flags & RAW)
268: c = 0;
269: else
270: c = tp->t_intrc;
271: if (c&DZ_DO && overrun == 0) {
272: log(LOG_WARNING, "dz%d,%d: silo overflow\n", dz, (c>>8)&7);
273: overrun = 1;
274: }
275: if (c&DZ_PE)
276: if (((tp->t_flags & (EVENP|ODDP)) == EVENP)
277: || ((tp->t_flags & (EVENP|ODDP)) == ODDP))
278: continue;
279: #if NBK > 0
280: if (tp->t_line == NETLDISC) {
281: c &= 0177;
282: BKINPUT(c, tp);
283: } else
284: #endif
285: (*linesw[tp->t_line].l_rint)(c, tp);
286: }
287: }
288:
289: /*ARGSUSED*/
290: dzioctl(dev, cmd, data, flag)
291: dev_t dev;
292: caddr_t data;
293: {
294: register struct tty *tp;
295: register int unit = minor(dev);
296: register int dz = unit >> 3;
297: register struct dzdevice *dzaddr;
298: int error;
299:
300: tp = &dz_tty[unit];
301: error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
302: if (error >= 0)
303: return (error);
304: error = ttioctl(tp, cmd, data, flag);
305: if (error >= 0) {
306: if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLBIS ||
307: cmd == TIOCLBIC || cmd == TIOCLSET)
308: dzparam(unit);
309: return (error);
310: }
311: switch (cmd) {
312:
313: case TIOCSBRK:
314: dzaddr = ((struct pdma *)(tp->t_addr))->p_addr;
315: if (dzaddr->dzcsr&DZ_32)
316: (void) dzmctl(dev, DZ_BRK, DMBIS);
317: else
318: dzaddr->dzbrk = (dz_brk[dz] |= 1 << (unit&07));
319: break;
320:
321: case TIOCCBRK:
322: dzaddr = ((struct pdma *)(tp->t_addr))->p_addr;
323: if (dzaddr->dzcsr&DZ_32)
324: (void) dzmctl(dev, DZ_BRK, DMBIC);
325: else
326: dzaddr->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07)));
327: break;
328:
329: case TIOCSDTR:
330: (void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIS);
331: break;
332:
333: case TIOCCDTR:
334: (void) dzmctl(dev, DZ_DTR|DZ_RTS, DMBIC);
335: break;
336:
337: case TIOCMSET:
338: (void) dzmctl(dev, dmtodz(*(int *)data), DMSET);
339: break;
340:
341: case TIOCMBIS:
342: (void) dzmctl(dev, dmtodz(*(int *)data), DMBIS);
343: break;
344:
345: case TIOCMBIC:
346: (void) dzmctl(dev, dmtodz(*(int *)data), DMBIC);
347: break;
348:
349: case TIOCMGET:
350: *(int *)data = dztodm(dzmctl(dev, 0, DMGET));
351: break;
352:
353: default:
354: return (ENOTTY);
355: }
356: return (0);
357: }
358:
359: dmtodz(bits)
360: register int bits;
361: {
362: register int b;
363:
364: b = (bits >>1) & 0370;
365: if (bits & DML_ST) b |= DZ_ST;
366: if (bits & DML_RTS) b |= DZ_RTS;
367: if (bits & DML_DTR) b |= DZ_DTR;
368: if (bits & DML_LE) b |= DZ_LE;
369: return(b);
370: }
371:
372: dztodm(bits)
373: register int bits;
374: {
375: register int b;
376:
377: b = (bits << 1) & 0360;
378: if (bits & DZ_DSR) b |= DML_DSR;
379: if (bits & DZ_DTR) b |= DML_DTR;
380: if (bits & DZ_ST) b |= DML_ST;
381: if (bits & DZ_RTS) b |= DML_RTS;
382: return(b);
383: }
384:
385: dzparam(unit)
386: register int unit;
387: {
388: register struct tty *tp;
389: register struct dzdevice *dzaddr;
390: register int lpr;
391:
392: tp = &dz_tty[unit];
393: dzaddr = dzpdma[unit].p_addr;
394: if (dzsilos & (1 << (unit >> 3)))
395: dzaddr->dzcsr = DZ_IEN | DZ_SAE;
396: else
397: dzaddr->dzcsr = DZ_IEN;
398: dzact |= (1<<(unit>>3));
399: if (tp->t_ispeed == 0) {
400: (void) dzmctl(unit, DZ_OFF, DMSET); /* hang up line */
401: return;
402: }
403: lpr = (dz_speeds[tp->t_ispeed]<<8) | (unit & 07);
404: if (tp->t_flags & (RAW|LITOUT|PASS8))
405: lpr |= BITS8;
406: else
407: lpr |= (BITS7|PENABLE);
408: if ((tp->t_flags & EVENP) == 0)
409: lpr |= OPAR;
410: if (tp->t_ispeed == B110)
411: lpr |= TWOSB;
412: dzaddr->dzlpr = lpr;
413: }
414:
415: dzxint(tp)
416: register struct tty *tp;
417: {
418: register struct pdma *dp;
419: register dz, unit;
420:
421: dp = (struct pdma *)tp->t_addr;
422: tp->t_state &= ~TS_BUSY;
423: if (tp->t_state & TS_FLUSH)
424: tp->t_state &= ~TS_FLUSH;
425: else {
426: ndflush(&tp->t_outq, dp->p_mem-tp->t_outq.c_cf);
427: dp->p_end = dp->p_mem = tp->t_outq.c_cf;
428: }
429: if (tp->t_line)
430: (*linesw[tp->t_line].l_start)(tp);
431: else
432: dzstart(tp);
433: dz = minor(tp->t_dev) >> 3;
434: unit = minor(tp->t_dev) & 7;
435: if (tp->t_outq.c_cc == 0 || (tp->t_state&TS_BUSY)==0)
436: if (dp->p_addr->dzcsr & DZ_32)
437: dp->p_addr->dzlnen = (dz_lnen[dz] &= ~(1<<unit));
438: else
439: dp->p_addr->dztcr &= ~(1<<unit);
440: }
441:
442: dzstart(tp)
443: register struct tty *tp;
444: {
445: register struct pdma *dp;
446: register struct dzdevice *dzaddr;
447: register int cc;
448: int s, dz, unit;
449:
450: dp = (struct pdma *)tp->t_addr;
451: dzaddr = dp->p_addr;
452: s = spl5();
453: if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
454: goto out;
455: if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
456: if (tp->t_state&TS_ASLEEP) {
457: tp->t_state &= ~TS_ASLEEP;
458: wakeup((caddr_t)&tp->t_outq);
459: }
460: if (tp->t_wsel) {
461: selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
462: tp->t_wsel = 0;
463: tp->t_state &= ~TS_WCOLL;
464: }
465: }
466: if (tp->t_outq.c_cc == 0)
467: goto out;
468: if (tp->t_flags & (RAW|LITOUT))
469: cc = ndqb(&tp->t_outq, 0);
470: else {
471: cc = ndqb(&tp->t_outq, 0200);
472: if (cc == 0) {
473: cc = getc(&tp->t_outq);
474: timeout(ttrstrt, (caddr_t)tp, (cc&0x7f) + 6);
475: tp->t_state |= TS_TIMEOUT;
476: goto out;
477: }
478: }
479: tp->t_state |= TS_BUSY;
480: dp->p_end = dp->p_mem = tp->t_outq.c_cf;
481: dp->p_end += cc;
482: dz = minor(tp->t_dev) >> 3;
483: unit = minor(tp->t_dev) & 7;
484: if (dzaddr->dzcsr & DZ_32)
485: dzaddr->dzlnen = (dz_lnen[dz] |= (1<<unit));
486: else
487: dzaddr->dztcr |= (1<<unit);
488: out:
489: splx(s);
490: }
491:
492: /*
493: * Stop output on a line.
494: */
495: /*ARGSUSED*/
496: dzstop(tp, flag)
497: register struct tty *tp;
498: {
499: register struct pdma *dp;
500: register int s;
501:
502: dp = (struct pdma *)tp->t_addr;
503: s = spl5();
504: if (tp->t_state & TS_BUSY) {
505: dp->p_end = dp->p_mem;
506: if ((tp->t_state&TS_TTSTOP)==0)
507: tp->t_state |= TS_FLUSH;
508: }
509: splx(s);
510: }
511:
512: dzmctl(dev, bits, how)
513: dev_t dev;
514: int bits, how;
515: {
516: register struct dzdevice *dzaddr;
517: register int unit, mbits;
518: int b, s;
519:
520: unit = minor(dev);
521: b = 1<<(unit&7);
522: dzaddr = dzpdma[unit].p_addr;
523: s = spl5();
524: if (dzaddr->dzcsr & DZ_32) {
525: dzwait(dzaddr)
526: DELAY(100); /* IS 100 TOO MUCH? */
527: dzaddr->dzlcs = unit&7;
528: DELAY(100);
529: dzwait(dzaddr)
530: DELAY(100);
531: mbits = dzaddr->dzlcs;
532: mbits &= 0177770;
533: } else {
534: mbits = (dzaddr->dzdtr & b) ? DZ_DTR : 0;
535: mbits |= (dzaddr->dzmsr & b) ? DZ_CD : 0;
536: mbits |= (dzaddr->dztbuf & b) ? DZ_RI : 0;
537: }
538: switch (how) {
539: case DMSET:
540: mbits = bits;
541: break;
542:
543: case DMBIS:
544: mbits |= bits;
545: break;
546:
547: case DMBIC:
548: mbits &= ~bits;
549: break;
550:
551: case DMGET:
552: (void) splx(s);
553: return(mbits);
554: }
555: if (dzaddr->dzcsr & DZ_32) {
556: mbits |= DZ_ACK|(unit&7);
557: dzaddr->dzlcs = mbits;
558: } else {
559: if (mbits & DZ_DTR)
560: dzaddr->dzdtr |= b;
561: else
562: dzaddr->dzdtr &= ~b;
563: }
564: (void) splx(s);
565: return(mbits);
566: }
567:
568: int dztransitions, dzfasttimers; /*DEBUG*/
569: dzscan()
570: {
571: register i;
572: register struct dzdevice *dzaddr;
573: register bit;
574: register struct tty *tp;
575: register car;
576: int olddzsilos = dzsilos;
577: int dztimer();
578:
579: for (i = 0; i < dz_cnt ; i++) {
580: dzaddr = dzpdma[i].p_addr;
581: if (dzaddr == 0)
582: continue;
583: tp = &dz_tty[i];
584: bit = 1<<(i&07);
585: car = 0;
586: if (dzsoftCAR[i>>3]&bit)
587: car = 1;
588: else if (dzaddr->dzcsr & DZ_32) {
589: dzaddr->dzlcs = i&07;
590: dzwait(dzaddr);
591: car = dzaddr->dzlcs & DZ_CD;
592: } else
593: car = dzaddr->dzmsr&bit;
594: if (car) {
595: /* carrier present */
596: if ((tp->t_state & TS_CARR_ON) == 0)
597: (void)(*linesw[tp->t_line].l_modem)(tp, 1);
598: } else if ((tp->t_state&TS_CARR_ON) &&
599: (*linesw[tp->t_line].l_modem)(tp, 0) == 0)
600: dzaddr->dzdtr &= ~bit;
601: }
602: for (i = 0; i < NDZ; i++) {
603: ave(dzrate[i], dzchars[i], 8);
604: if (dzchars[i] > dzhighrate && ((dzsilos & (1 << i)) == 0)) {
605: dzpdma[i << 3].p_addr->dzcsr = DZ_IEN | DZ_SAE;
606: dzsilos |= (1 << i);
607: dztransitions++; /*DEBUG*/
608: } else if ((dzsilos & (1 << i)) && (dzrate[i] < dzlowrate)) {
609: dzpdma[i << 3].p_addr->dzcsr = DZ_IEN;
610: dzsilos &= ~(1 << i);
611: }
612: dzchars[i] = 0;
613: }
614: if (dzsilos && !olddzsilos)
615: timeout(dztimer, (caddr_t)0, dztimerintvl);
616: timeout(dzscan, (caddr_t)0, hz);
617: }
618:
619: dztimer()
620: {
621: register int dz;
622: register int s;
623:
624: if (dzsilos == 0)
625: return;
626: s = spl5();
627: dzfasttimers++; /*DEBUG*/
628: for (dz = 0; dz < NDZ; dz++)
629: if (dzsilos & (1 << dz))
630: dzrint(dz);
631: splx(s);
632: timeout(dztimer, (caddr_t) 0, dztimerintvl);
633: }
634:
635: /*
636: * Reset state of driver if UBA reset was necessary.
637: * Reset parameters and restart transmission on open lines.
638: */
639: dzreset(uban)
640: int uban;
641: {
642: register int unit;
643: register struct tty *tp;
644: register struct uba_device *ui;
645:
646: for (unit = 0; unit < NDZLINE; unit++) {
647: ui = dzinfo[unit >> 3];
648: if (ui == 0 || ui->ui_ubanum != uban || ui->ui_alive == 0)
649: continue;
650: if (unit%8 == 0)
651: printf(" dz%d", unit>>3);
652: tp = &dz_tty[unit];
653: if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
654: dzparam(unit);
655: (void) dzmctl(unit, DZ_ON, DMSET);
656: tp->t_state &= ~TS_BUSY;
657: dzstart(tp);
658: }
659: }
660: }
661: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.