1: /* 2: * SCCS id @(#)dz.c 2.1 (Berkeley) 8/5/83 3: */ 4: 5: #include "dz.h" 6: #if NDZ > 0 7: #include "param.h" 8: #include <sys/systm.h> 9: #include <sys/dir.h> 10: #include <sys/user.h> 11: #include <sys/tty.h> 12: #include <sys/file.h> 13: #include <sys/conf.h> 14: #include <sys/dzreg.h> 15: #ifdef DZ_PDMA 16: #include <sys/pdma.h> 17: #endif 18: 19: #ifdef DZ_SOFTCAR 20: #define DZLINE(dev) (minor(dev) & 0177) 21: #else 22: #define DZLINE(dev) minor(dev) 23: #endif 24: 25: #define NDZLINE (NDZ * 8) 26: int ndz11 = NDZLINE; /* Only for pstat */ 27: struct tty dz11[NDZLINE]; 28: #ifdef DZ_PDMA 29: struct pdma dzpdma[NDZLINE]; 30: bool_t dz_init; 31: #endif 32: 33: struct dzdevice *dz_addr[NDZ]; 34: 35: char dz_speeds[] = { 36: 0, 020, 021, 022, 023, 024, 0, 025, 37: 026, 027, 030, 032, 034, 036, 0, 0, 38: }; 39: 40: #ifdef DZ_IOCTL 41: char dz_brk[NDZ]; /* software copy of dzbrk */ 42: #endif 43: 44: dzattach(addr, unit) 45: struct dzdevice *addr; 46: { 47: if ((unsigned) unit >= NDZ) 48: return 0; 49: dz_addr[unit] = addr; 50: return 1; 51: } 52: 53: /*ARGSUSED*/ 54: dzopen(dev, flag) 55: register dev_t dev; 56: { 57: register unit; 58: register struct tty *tp; 59: extern dzstart(); 60: int s; 61: 62: #ifdef DZ_PDMA 63: if (dz_init == 0) { 64: register struct pdma *dp; 65: 66: dz_init = 1; 67: tp = dz11; 68: dp = dzpdma; 69: for (unit = 0; unit < NDZLINE; unit++, dp++) { 70: dp->p_addr = dz_addr[unit >> 3]; 71: dp->p_arg = tp++; 72: } 73: } 74: #endif 75: unit = DZLINE(dev); 76: if (unit >= NDZLINE || (dz_addr[unit >> 3] == 0)) { 77: u.u_error = ENXIO; 78: return; 79: } 80: tp = &dz11[unit]; 81: if (tp->t_state & XCLUDE && u.u_uid != 0) { 82: u.u_error = EBUSY; 83: return; 84: } 85: if ((tp->t_state & (ISOPEN | WOPEN)) == 0) { 86: tp->t_oproc = dzstart; 87: tp->t_iproc = NULL; 88: ttychars(tp); 89: tp->t_ispeed = B300; 90: tp->t_ospeed = B300; 91: tp->t_flags = ODDP | EVENP | ECHO; 92: tp->t_line = DFLT_LDISC; 93: #ifdef DZ_PDMA 94: tp->t_addr = &dzpdma[unit]; 95: #endif 96: dzparam(unit); 97: } 98: dzmodem(unit, DZ_ON); 99: #ifdef DZ_SOFTCAR 100: if (dev & 0200) 101: tp->t_state |= CARR_ON; 102: else 103: #endif 104: { 105: s = spl6(); 106: while ((tp->t_state & CARR_ON) == 0) { 107: tp->t_state |= WOPEN; 108: sleep((caddr_t) &tp->t_rawq, TTIPRI); 109: } 110: splx(s); 111: } 112: ttyopen(dev, tp); 113: } 114: 115: /*ARGSUSED*/ 116: dzclose(dev, flag) 117: dev_t dev; 118: { 119: register struct tty *tp; 120: register unit; 121: #ifdef DZ_IOCTL 122: register dz; 123: #endif 124: 125: unit = DZLINE(dev); 126: tp = &dz11[unit]; 127: #ifdef DZ_IOCTL 128: dz = unit >> 3; 129: dz_addr[dz]->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07))); 130: #endif 131: if (tp->t_state & HUPCLS) 132: dzmodem(unit, DZ_OFF); 133: ttyclose(tp); 134: } 135: 136: dzread(dev) 137: register dev_t dev; 138: { 139: register struct tty *tp; 140: 141: tp = &dz11[DZLINE(dev)]; 142: (*linesw[tp->t_line].l_read)(tp); 143: } 144: 145: dzwrite(dev) 146: register dev_t dev; 147: { 148: register struct tty *tp; 149: 150: tp = &dz11[DZLINE(dev)]; 151: (*linesw[tp->t_line].l_write)(tp); 152: } 153: 154: dzioctl(dev, cmd, addr, flag) 155: dev_t dev; 156: int cmd; 157: caddr_t addr; 158: int flag; 159: { 160: register unit; 161: register struct tty *tp; 162: #ifdef DZ_IOCTL 163: register dz; 164: #endif 165: 166: unit = DZLINE(dev); 167: tp = &dz11[unit]; 168: #ifdef DZ_IOCTL 169: dz = unit >> 3; 170: #endif 171: switch (ttioctl(tp, cmd, addr, flag)) { 172: case TIOCSETP: 173: case TIOCSETN: 174: dzparam(unit); 175: break; 176: #ifdef DZ_IOCTL 177: case TIOCSBRK: 178: dz_addr[dz]->dzbrk = (dz_brk[dz] |= (1 << (unit&07))); 179: break; 180: case TIOCCBRK: 181: dz_addr[dz]->dzbrk = (dz_brk[dz] &= ~(1 << (unit&07))); 182: break; 183: case TIOCSDTR: 184: dzmodem(unit, DZ_ON); 185: break; 186: case TIOCCDTR: 187: dzmodem(unit, DZ_OFF); 188: break; 189: #endif 190: default: 191: u.u_error = ENOTTY; 192: case 0: 193: break; 194: } 195: } 196: 197: dzparam(unit) 198: int unit; 199: { 200: register struct tty *tp; 201: register struct dzdevice *addr; 202: register lpr; 203: static dz_timer; 204: void dzscan(); 205: #ifdef DZ_SILO 206: void dzrscan(); 207: #endif 208: 209: tp = &dz11[unit]; 210: addr = dz_addr[unit >> 3]; 211: addr->dzcsr = DZ_IEN; 212: if (dz_timer == 0) { 213: dz_timer++; 214: timeout(dzscan, (caddr_t) 0, 1); 215: #ifdef DZ_SILO 216: timeout(dzrscan, (caddr_t)0, SILOSCANRATE); 217: #endif 218: } 219: if (tp->t_ispeed == 0) { /* Hang up line */ 220: dzmodem(unit, DZ_OFF); 221: return; 222: } 223: lpr = (dz_speeds[tp->t_ispeed] << 8) | (unit & 07); 224: #ifdef UCB_NTTY 225: if ((tp->t_local & LLITOUT) || (tp->t_flags & RAW)) 226: #else 227: if (tp->t_flags & RAW) 228: #endif 229: lpr |= BITS8; 230: else 231: lpr |= BITS7 | PENABLE; 232: if ((tp->t_flags & EVENP) == 0) 233: lpr |= OPAR; 234: if (tp->t_ispeed == B110) 235: lpr |= TWOSB; 236: addr->dzlpr = lpr; 237: } 238: 239: dzrint(dz) 240: int dz; 241: { 242: register struct tty *tp; 243: register c; 244: register struct dzdevice *addr; 245: struct tty *tp0; 246: int overrun = 0; 247: #ifdef DZ_SILO 248: int s; 249: 250: s = spl6(); 251: #endif 252: if ((unsigned) dz >= NDZ) 253: return; 254: addr = dz_addr[dz]; 255: tp0 = &dz11[dz << 3]; 256: while ((c = addr->dzrbuf) < 0) { /* char. present */ 257: tp = tp0 + ((c >> 8) & 07); 258: if (tp >= &dz11[NDZLINE]) 259: continue; 260: if((tp->t_state & ISOPEN) == 0) { 261: wakeup((caddr_t) &tp->t_rawq); 262: continue; 263: } 264: #ifdef TEXAS_AUTOBAUD 265: if (image_mode(tp)) 266: c &= ~(DZ_FE|DZ_PE); 267: #endif 268: if (c & DZ_FE) 269: if (tp->t_flags & RAW) 270: c = 0; 271: else 272: c = tun.t_intrc; 273: if (c & DZ_DO && overrun == 0) { 274: printf("dz%d: silo overflow\n", dz); 275: overrun = 1; 276: } 277: if (c & DZ_PE) 278: if ((tp->t_flags & (EVENP|ODDP)) == EVENP 279: || (tp->t_flags & (EVENP|ODDP)) == ODDP) 280: continue; 281: (*linesw[tp->t_line].l_input)(c, tp); 282: } 283: #ifdef DZ_SILO 284: splx(s); 285: #endif 286: } 287: 288: #ifdef DZ_PDMA 289: /* 290: * dzxint is called from dzdma after the last of the characters set up 291: * has been sent. 292: */ 293: dzxint(tp) 294: register struct tty *tp; 295: { 296: register struct pdma *dp; 297: 298: dp = (struct pdma *) tp->t_addr; 299: tp->t_state &= ~BUSY; 300: if (tp->t_state & FLUSH) 301: tp->t_state &= ~FLUSH; 302: else 303: ndflush(&tp->t_outq, dp->p_mem - tp->t_outq.c_cf); 304: dzstart(tp); 305: if ((tp->t_outq.c_cc == 0) || (tp->t_state & BUSY) == 0) 306: dp->p_addr->dztcr &= ~(1 << (DZLINE(tp->t_dev) & 07)); 307: } 308: 309: #else DZ_PDMA 310: dzxint(dz) 311: int dz; 312: { 313: register struct tty *tp, *tp0; 314: register struct dzdevice *addr; 315: 316: addr = dz_addr[dz]; 317: tp0 = &dz11[dz << 3]; 318: while(addr->dzcsr < 0) { 319: tp = tp0 + ((addr->dzcsr >> 8) & 07); 320: addr->dztbuf = tp->t_char; 321: tp->t_state &= ~BUSY; 322: dzstart(tp); 323: } 324: } 325: #endif DZ_PDMA 326: 327: dzstart(tp) 328: register struct tty *tp; 329: { 330: #ifdef DZ_PDMA 331: register struct pdma *dp; 332: register cc; 333: int s; 334: struct dzdevice *addr; 335: extern ttrstrt(); 336: 337: dp = (struct pdma *) tp->t_addr; 338: addr = dp->p_addr; 339: s = spl5(); 340: if (tp->t_state & (TIMEOUT | BUSY | TTSTOP)) 341: goto out; 342: if (tp->t_outq.c_cc<=TTLOWAT(tp)) { 343: if (tp->t_state & ASLEEP) { 344: tp->t_state &= ~ASLEEP; 345: #if MPX_FILS 346: if (tp->t_chan) 347: mcstart(tp->t_chan, (caddr_t) &tp->t_outq); 348: else 349: #endif 350: wakeup((caddr_t) &tp->t_outq); 351: } 352: #ifdef UCB_NET 353: if (tp->t_wsel) { 354: selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 355: tp->t_wsel = 0; 356: tp->t_state &= ~TS_WCOLL; 357: } 358: #endif 359: } 360: if (tp->t_outq.c_cc == 0) 361: goto out; 362: if ((tp->t_flags & RAW) 363: #ifdef UCB_NTTY 364: || (tp->t_local & LLITOUT) 365: #endif 366: ) 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); 372: timeout(ttrstrt, (caddr_t) tp, (cc & 0177) + 6); 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; 380: addr->dztcr |= 1 << ((DZLINE(tp->t_dev) & 07)); 381: out: 382: splx(s); 383: 384: 385: #else DZ_PDMA 386: register unit, c; 387: int s; 388: struct dzdevice *addr; 389: extern ttrstrt(); 390: 391: unit = (int) (tp - dz11); 392: addr = dz_addr[unit >> 3]; 393: unit = 1 << (unit & 07); 394: s = spl5(); 395: if (tp->t_state & (TIMEOUT | BUSY)) 396: goto out; 397: if (tp->t_state & TTSTOP) { 398: addr->dztcr &= ~unit; 399: goto out; 400: } 401: if ((c=getc(&tp->t_outq)) >= 0) { 402: if (c >= 0200 && (tp->t_flags & RAW) == 0 403: #ifdef UCB_NTTY 404: && (tp->t_local & LLITOUT) == 0) 405: #endif 406: { 407: addr->dztcr &= ~unit; 408: tp->t_state |= TIMEOUT; 409: timeout(ttrstrt, (caddr_t) tp, (c & 0177) + 6); 410: } else 411: { 412: tp->t_char = c; 413: tp->t_state |= BUSY; 414: addr->dztcr |= unit; 415: } 416: if (tp->t_outq.c_cc<=TTLOWAT(tp)) { 417: if (tp->t_state & ASLEEP) { 418: tp->t_state &= ~ASLEEP; 419: #if MPX_FILS 420: if (tp->t_chan) 421: mcstart(tp->t_chan, (caddr_t) &tp->t_outq); 422: else 423: #endif 424: wakeup((caddr_t) &tp->t_outq); 425: } 426: #ifdef UCB_NET 427: if (tp->t_wsel) { 428: selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 429: tp->t_wsel = 0; 430: tp->t_state &= ~TS_WCOLL; 431: } 432: #endif 433: } 434: } else 435: addr->dztcr &= ~unit; 436: out: 437: splx(s); 438: #endif DZ_PDMA 439: } 440: 441: #ifdef DZ_PDMA 442: /*ARGSUSED*/ 443: dzstop(tp, flag) 444: register struct tty *tp; 445: { 446: register struct pdma *dp; 447: register int s; 448: 449: dp = (struct pdma *) tp->t_addr; 450: s = spl5(); 451: if (tp->t_state & BUSY) { 452: dp->p_end = dp->p_mem; 453: if ((tp->t_state & TTSTOP) == 0) 454: tp->t_state |= FLUSH; 455: } 456: splx(s); 457: } 458: #endif 459: 460: dzmodem(unit, flag) 461: register unit; 462: { 463: register struct dzdevice *addr; 464: register bit; 465: 466: addr = dz_addr[unit >> 3]; 467: bit = 1 << (unit & 07); 468: if (flag == DZ_OFF) 469: addr->dzdtr &= ~bit; 470: else 471: addr->dzdtr |= bit; 472: } 473: 474: dzscan() 475: { 476: register unit; 477: register struct dzdevice *addr; 478: register struct tty *tp; 479: char bit; 480: 481: for (unit = 0; unit < NDZLINE; unit++) { 482: addr = dz_addr[unit >> 3]; 483: tp = &dz11[unit]; 484: bit = 1 << (unit & 07); 485: if (addr->dzcar & bit) { 486: /* carrier present */ 487: if ((tp->t_state & CARR_ON) == 0) { 488: wakeup((caddr_t) &tp->t_rawq); 489: tp->t_state |= CARR_ON; 490: } 491: } else 492: { 493: if ((tp->t_state & CARR_ON) 494: #ifdef DZ_SOFTCAR 495: && ((tp->t_dev & 0200) == 0) 496: #endif 497: #ifdef UCB_NTTY 498: && ((tp->t_local & LNOHANG) == 0) 499: #endif 500: ) { 501: /* carrier lost */ 502: if (tp->t_state & ISOPEN) { 503: gsignal(tp->t_pgrp, SIGHUP); 504: addr->dzdtr &= ~bit; 505: flushtty(tp, FREAD | FWRITE); 506: } 507: tp->t_state &= ~CARR_ON; 508: } 509: } 510: } 511: timeout(dzscan, (caddr_t) 0, 2 * hz); 512: } 513: 514: #ifdef DZ_SILO 515: dzrscan() 516: { 517: register dz; 518: register struct dzdevice *addr; 519: 520: for (dz = 0; dz < NDZ; dz++) { 521: addr = dz_addr[dz]; 522: if (addr->dzcsr & DZ_RDO) 523: dzrint(dz); 524: } 525: timeout(dzrscan, (caddr_t)0, SILOSCANRATE); 526: }; 527: #endif DZ_SILO 528: #endif NDZ