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