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