|
|
1.1 ! root 1: /* ! 2: * DZ-11 driver ! 3: * ------------ ! 4: * ! 5: * Written to handle single dz - `carrier'|`ring' support non-existent ! 6: * ! 7: * Piers Lauder ! 8: * SYDNEY UNIVERSITY ! 9: * July 1977 ! 10: * ! 11: * Re-written to handle multiple dz's and `carrier'|`ring'. ! 12: * ! 13: * Ian Johnstone ! 14: * UNSW ! 15: * December 1977 ! 16: * January 1978 ! 17: * ! 18: * General tidy up, new comments etc. Removal of ifdefs ! 19: * for CARRIER and RING. If you don't want them, tough. ! 20: * ! 21: * Chris Maltby ! 22: * Basser October 1979 ! 23: */ ! 24: ! 25: ! 26: /* ( no messages ) ! 27: #define MESSAGES ! 28: /* ! 29: * Define this if you want parity and framing errors ! 30: * to be logged (via printf). It can be very wordy. ! 31: */ ! 32: ! 33: #define INTR_ON_BREAK ! 34: /* ! 35: * Define this to translate framing errors (breaks) ! 36: * to CINTR for terminals which lack a DEL key. ! 37: * Can be nasty if you get lots of line errors. ! 38: */ ! 39: ! 40: /* (not DEBUG) ! 41: #define DEBUG ! 42: /* ! 43: * Define to debug info for dialup lines. ! 44: * costs approximately 128 bytes ! 45: */ ! 46: ! 47: #include "../defines.h" ! 48: #include "../param.h" ! 49: #ifdef DEBUG ! 50: #ifdef AUSAML ! 51: #include "../lnode.h" ! 52: #endif AUSAML ! 53: #include "../systm.h" ! 54: #endif DEBUG ! 55: #include "../conf.h" ! 56: #include "../user.h" ! 57: #include "../tty.h" ! 58: #include "../proc.h" ! 59: ! 60: ! 61: #define NDZ 2 /* number of DZ-11s */ ! 62: #define NLINES 8*NDZ /* total number of lines */ ! 63: #define TSCANRATE 2 /* dzscan called every 2 tics */ ! 64: /* Must be >= 2 always */ ! 65: ! 66: #define RESPONDTIME (25*HZ) /* Carrier must be raised inside this */ ! 67: #define CARRIERTIME (1*HZ) /* Carrier must drop for this before hangup */ ! 68: ! 69: #define FLUSHTIME 5 /* time required to allow hardware buffered ! 70: * characters to flush before setting speed */ ! 71: ! 72: #define SSPEED 12 /* standard speed 4800 bd */ ! 73: ! 74: struct dz /* one for each dz-11 */ ! 75: { ! 76: int *dzaddr; /* dz device address */ ! 77: char sopen; /* bit set for single open lines */ ! 78: char carrier; /* bits set for carrier controlled lines */ ! 79: char ring; /* bits set for lines with dial in modems */ ! 80: char active; /* bits set for active dialup lines */ ! 81: char openl; /* bits set for open lines */ ! 82: unsigned pyerrors; /* count of of parity errors on input */ ! 83: unsigned overrors; /* count of of overrun errors on input */ ! 84: } ! 85: dz[NDZ] ! 86: { ! 87: /* dzaddr sopen carr ring */ ! 88: { 0160040, 0002, 0077, 0074 }, ! 89: { 0160050, 0000, 0000, 0000 } ! 90: }; ! 91: int dzscanning; /* set when scanning for input and modem change */ ! 92: ! 93: /* ! 94: * DZ11 register layout ! 95: */ ! 96: ! 97: struct dzr_read ! 98: { ! 99: int dzcsr; /* r/w */ ! 100: int dzrbuf; /* no bit, byte, or tst ops */ ! 101: char dztcr; /* r/w */ ! 102: char dzdtr; /* r/w */ ! 103: char dzring; ! 104: char dzcarr; ! 105: }; ! 106: ! 107: struct dzr_write ! 108: { ! 109: int dzcsr; /* r/w */ ! 110: int dzlpr; /* no bit or byte ops */ ! 111: char dztcr; /* r/w */ ! 112: char dzdtr; /* r/w */ ! 113: char dztbuf; /* no bit ops */ ! 114: char dzbrk; /* no bit ops */ ! 115: }; ! 116: ! 117: /* ! 118: * register control bits ! 119: */ ! 120: #define TRDY 0100000 /* dzcsr */ ! 121: #define TIE 040000 ! 122: #define SA 020000 ! 123: #define SAE 010000 ! 124: #define TLINE 03400 ! 125: #define RDONE 0200 ! 126: #define RIE 0100 ! 127: #define MSE 040 ! 128: #define CLR 020 ! 129: ! 130: #define RCVR_ON 010000 /* dzlpr */ ! 131: #define S9600 07000 ! 132: #define S300 02400 ! 133: #define S134_5 01400 ! 134: #define S110 01000 ! 135: #define ODD_PAR 0300 ! 136: #define EVN_PAR 0100 ! 137: #define TWOSBIT 040 ! 138: #define C8BIT 030 ! 139: #define C7BIT 020 ! 140: #define C6BIT 010 ! 141: /* ! 142: #define IBM2741 RCVR_ON|S134_5|ODD_PAR|C6BIT /* if you must */ ! 143: ! 144: #define RERROR 070000 /* dzrbuf */ ! 145: #define OVR_RUN 040000 ! 146: #define FRAME 020000 ! 147: #define PARITY 010000 ! 148: #define LINE_NO 03400 ! 149: ! 150: /* ! 151: * table to map UNIX standard speeds to DZ11 speeds ! 152: * illegal speeds are ignored. ! 153: */ ! 154: char dzspeedmap[16] ! 155: { ! 156: 0 /* 0 - zero */ ! 157: , 020 /* 1 - 50 */ ! 158: , 021 /* 2 - 75 */ ! 159: , 022 /* 3 - 110 */ ! 160: , 023 /* 4 - 134.5 */ ! 161: , 024 /* 5 - 150 */ ! 162: ,0200 /* 6 - 200 -- ## ILLEGAL ## */ ! 163: , 025 /* 7 - 300 */ ! 164: , 026 /* 8 - 600 */ ! 165: , 027 /* 9 - 1200 */ ! 166: , 030 /* 10 - 1800 */ ! 167: , 032 /* 11 - 2400 */ ! 168: , 034 /* 12 - 4800 */ ! 169: , 036 /* 13 - 9600 */ ! 170: , 031 /* 14 - ext A - maps to 2000 */ ! 171: , 037 /* 15 - ext B - maps to 19200 */ ! 172: }; ! 173: ! 174: ! 175: ! 176: struct tty dz11[NLINES]; ! 177: ! 178: char dzdelays[NLINES]; /* Count of clock ticks for per-line ! 179: * delays. Count of <= 0 means no delay. ! 180: * Reduces requirement of timeouts. ! 181: */ ! 182: ! 183: int dzringt[NLINES]; /* Delay counts for modem control */ ! 184: ! 185: /* ! 186: * open a DZ11 line ! 187: */ ! 188: dzopen(dev, flag) ! 189: { ! 190: register struct tty *tp; ! 191: register struct dz *dzp; ! 192: register int t_bit; ! 193: extern dzstart(), dzscan(); ! 194: ! 195: ! 196: if(dev.d_minor >= NLINES) ! 197: { ! 198: u.u_error = ENXIO; ! 199: return; ! 200: } ! 201: dzp = &dz[dev.d_minor>>3]; ! 202: t_bit = (1<<(dev.d_minor&07)); ! 203: if((dzp->sopen&t_bit) && (dzp->openl&t_bit)) ! 204: { ! 205: u.u_error = EOPENFAIL; ! 206: return; ! 207: } ! 208: tp = &dz11[dev.d_minor]; ! 209: if(u.u_procp->p_ttyp == 0) ! 210: u.u_procp->p_ttyp = tp; ! 211: if((tp->t_state&ISOPEN) == 0) ! 212: { ! 213: tp->t_dev = dev; ! 214: tp->t_addr = &dzstart; ! 215: tp->t_speeds = SSPEED|(SSPEED<<8); ! 216: tp->t_flags = ODDP|EVENP|XTABS|RAW; ! 217: tp->t_erase = CERASE; ! 218: tp->t_kill = CKILL; ! 219: if(dzp->openl == 0) ! 220: dzp->dzaddr->dzcsr =| (TIE|RIE|SAE|MSE); /* reciever interrupt every 16 chars */ ! 221: dzp->openl =| t_bit; ! 222: spl5(); ! 223: if(dzscanning == 0) ! 224: dzscan(); /* start scanning */ ! 225: if(!(dzp->ring&t_bit) && !(dzp->carrier&t_bit)) ! 226: dzp->dzaddr->dzdtr =| t_bit; /* turn on DTR for non-dialup lines */ ! 227: else ! 228: { ! 229: # ifdef DEBUG ! 230: printf("%d wo%d\n", time.loint, dev.d_minor); ! 231: # endif DEBUG ! 232: while(!(dzp->dzaddr->dzcarr&t_bit)) ! 233: { ! 234: tp->t_state =| WOPEN; ! 235: sleep(&tp->t_rawq, TTIPRI); ! 236: } ! 237: # ifdef DEBUG ! 238: printf("%d op%d\n", time.loint, dev.d_minor); ! 239: # endif DEBUG ! 240: } ! 241: spl0(); ! 242: tp->t_state = (ISOPEN|CARR_ON|SSTART); ! 243: dzparam(tp, 1); ! 244: } ! 245: } ! 246: ! 247: ! 248: /* ! 249: * scan open lines for: ! 250: * 1. modem status changes ! 251: * 2. process timeouts as dictated by dzdelays ! 252: * 3. input by calling dzrint ! 253: */ ! 254: dzscan() /* at spl5 */ ! 255: { ! 256: register struct dz *dzp; ! 257: struct tty *tp; ! 258: int *p; ! 259: extern dzstart(), dzrint(), dzscan(); ! 260: # define openring (dzp->openl & dzp->ring) ! 261: # define opencarrier (dzp->openl & dzp->carrier) ! 262: ! 263: /* ! 264: * scan open dialup/carrier lines. ! 265: */ ! 266: tp = &dz11[0]; ! 267: p = &dzringt[0]; ! 268: for(dzp = dz; dzp < &dz[NDZ]; dzp++) ! 269: { ! 270: register int *dzaddr; ! 271: char scanl, scanc; ! 272: ! 273: dzaddr = dzp->dzaddr; ! 274: if((scanl = openring) | (scanc = opencarrier)) ! 275: { ! 276: register int t_bit; ! 277: ! 278: for(t_bit = 1; t_bit&0377; t_bit =<< 1, tp++, p++) ! 279: { ! 280: if(scanl&t_bit) ! 281: { ! 282: /* this is an open `dialup' line */ ! 283: if(dzp->active&t_bit) ! 284: { ! 285: if(!(dzaddr->dzcarr&t_bit)) ! 286: { ! 287: if(*p == 0) ! 288: *p = CARRIERTIME; ! 289: else if((*p =- TSCANRATE) <= 0) ! 290: { ! 291: *p = 0; /* disable */ ! 292: # ifdef DEBUG ! 293: printf("%d hu%d\n", time.loint, tp->t_dev.d_minor); ! 294: # endif DEBUG ! 295: dzaddr->dzdtr =& ~t_bit; /* hang up the phone */ ! 296: signal(tp, SIGHUP); ! 297: flushtty(tp); ! 298: dzaddr->dztcr =& ~t_bit; /* disable transmit */ ! 299: dzp->active =& ~t_bit; ! 300: } ! 301: } ! 302: else ! 303: { ! 304: if(tp->t_state&WOPEN) ! 305: wakeup(&tp->t_rawq); ! 306: *p = 0; ! 307: if(!(tp->t_state&TIMEOUT) && (tp->t_outq.c_cc)) ! 308: dzaddr->dztcr =| t_bit; ! 309: } ! 310: } ! 311: else ! 312: { ! 313: if(!(dzaddr->dzdtr&t_bit) && (dzaddr->dzring&t_bit)) ! 314: { ! 315: dzaddr->dzdtr =| t_bit; /* answer the phone */ ! 316: *p = RESPONDTIME; ! 317: dzp->active =| t_bit; ! 318: # ifdef DEBUG ! 319: printf("%d ap%d\n", time.loint, tp->t_dev.d_minor); ! 320: # endif DEBUG ! 321: } ! 322: } ! 323: } ! 324: else if((scanc&t_bit) && (dzaddr->dzcarr&t_bit)) ! 325: { /* carrier only line */ ! 326: if(tp->t_state&WOPEN) ! 327: { ! 328: dzaddr->dzdtr =| t_bit; ! 329: wakeup(&tp->t_rawq); ! 330: } ! 331: else if((!(tp->t_state&TIMEOUT)) && (tp->t_outq.c_cc)) ! 332: dzaddr->dztcr =| t_bit; ! 333: } ! 334: } ! 335: } ! 336: else ! 337: { ! 338: tp =+ 8; p =+ 8; /* in the case where no dialup/carrier lines on current dz */ ! 339: } ! 340: } ! 341: ! 342: /* ! 343: * process timeouts for each line ! 344: */ ! 345: ! 346: { ! 347: register i; ! 348: ! 349: for(i = 0; i < NLINES; i++) ! 350: if((dzdelays[i] > 0) && (--dzdelays[i] <= 0)) ! 351: { ! 352: dz11[i].t_state =& ~TIMEOUT; ! 353: dzstart(&dz11[i]); ! 354: } ! 355: } ! 356: ! 357: /* ! 358: * scan each dz for input ! 359: */ ! 360: ! 361: dzrint(0); ! 362: ! 363: /* ! 364: * restart scanning if necessary ! 365: */ ! 366: ! 367: dzp = dz; ! 368: do ! 369: { ! 370: if(dzp->openl) ! 371: { ! 372: dzscanning = timeout(&dzscan, 0, TSCANRATE); ! 373: return; ! 374: } ! 375: dzp++; ! 376: } while(dzp < &dz[NDZ]); ! 377: dzscanning = 0; ! 378: } ! 379: ! 380: /* ! 381: * close a DZ11 line ! 382: */ ! 383: dzclose(dev) ! 384: { ! 385: register struct tty *tp; ! 386: register t_bit; ! 387: register struct dz *dzp; ! 388: ! 389: tp = &dz11[dev.d_minor]; ! 390: wflushtty(tp); ! 391: tp->t_state = SSTART; ! 392: dzp = &dz[dev.d_minor>>3]; ! 393: t_bit = 1<<(dev.d_minor&07); ! 394: if(dzp->ring&t_bit) ! 395: { ! 396: if(tp->t_flags&HUPCL) ! 397: dzp->dzaddr->dzdtr =& ~t_bit; /* hang up the phone */ ! 398: } ! 399: else ! 400: { ! 401: dzp->dzaddr->dzdtr =& ~t_bit; /* turn off dtr for non-dialup lines */ ! 402: } ! 403: if((dzp->openl =& ~t_bit) == 0) ! 404: dzp->dzaddr->dzcsr = 0; /* disable receive on final close */ ! 405: } ! 406: ! 407: ! 408: ! 409: /* ! 410: * read from a DZ11 line ! 411: */ ! 412: dzread(dev) ! 413: { ! 414: ttread(&dz11[dev.d_minor]); ! 415: } ! 416: ! 417: ! 418: ! 419: /* ! 420: * write on a DZ11 line ! 421: */ ! 422: dzwrite(dev) ! 423: { ! 424: ttwrite(&dz11[dev.d_minor]); ! 425: } ! 426: ! 427: ! 428: ! 429: /* ! 430: * stty/gtty for DZ11 ! 431: */ ! 432: dzsgtty(dev, av) ! 433: int *av; ! 434: { ! 435: register struct tty *tp; ! 436: ! 437: if((av == 0) && (dzspeedmap[u.u_arg[0]&017] < 0)) ! 438: { ! 439: u.u_error = ENXIO; /* illegal speed */ ! 440: return; ! 441: } ! 442: tp = &dz11[dev.d_minor]; ! 443: if(ttystty(tp, av)) ! 444: return; ! 445: dzparam(tp, 1); ! 446: } ! 447: ! 448: ! 449: ! 450: /* ! 451: * set parameters from open or stty into DZ hardware registers ! 452: */ ! 453: dzparam(tp, dflag) ! 454: register struct tty *tp; ! 455: { ! 456: register lpr, x; ! 457: extern wakeup(); ! 458: ! 459: ! 460: lpr = dzspeedmap[tp->t_speeds&017]<<8; ! 461: ! 462: #ifdef IBM2741 ! 463: if(lpr == (RCVR_ON|S134_5)) ! 464: lpr = IBM2741; ! 465: else ! 466: { ! 467: #endif IBM2741 ! 468: if(lpr == (RCVR_ON|S110)) ! 469: lpr =| TWOSBIT; ! 470: ! 471: if((x = tp->t_flags)&EVENP) ! 472: if((x&ODDP) == 0) ! 473: lpr =| (EVN_PAR|C7BIT); ! 474: else ! 475: lpr =| C8BIT; ! 476: else if(x&ODDP) ! 477: lpr =| (ODD_PAR|C7BIT); ! 478: else ! 479: lpr =| C8BIT; ! 480: #ifdef IBM2741 ! 481: } ! 482: #endif IBM2741 ! 483: ! 484: if(dflag) ! 485: { ! 486: /* delay only if it is permissible */ ! 487: #ifndef DELAY ! 488: timeout(&wakeup, tp, FLUSHTIME); /* wakeup in 5 tics */ ! 489: sleep(tp, TTOPRI); /* delay while controller flushes */ ! 490: #else ! 491: delay(FLUSHTIME); /* hang 5 */ ! 492: #endif DELAY ! 493: } ! 494: ! 495: dz[tp->t_dev.d_minor>>3].dzaddr->dzlpr = lpr|(tp->t_dev.d_minor&07); ! 496: } ! 497: ! 498: ! 499: ! 500: /* ! 501: * start (restart) transmission on a DZ11 line ! 502: */ ! 503: dzstart(tp) ! 504: register struct tty *tp; ! 505: { ! 506: register t_bit; ! 507: register struct dz *dzp; ! 508: ! 509: ! 510: t_bit = 1<<(tp->t_dev.d_minor&07); ! 511: dzp = &dz[tp->t_dev.d_minor>>3]; ! 512: if((!(dzp->carrier&t_bit)) || (dzp->dzaddr->dzcarr&t_bit)) ! 513: dzp->dzaddr->dztcr =| t_bit; ! 514: } ! 515: ! 516: ! 517: /* ! 518: * DZ11 transmitter interrupt. ! 519: * ! 520: * Scan every line on each dz. ! 521: * Commencing with the device that caused ! 522: * dzxint to be called. ! 523: */ ! 524: dzxint(dev) ! 525: { ! 526: register struct tty *tp; ! 527: register c; ! 528: register struct dzr_read *dzaddr; ! 529: struct dz *dzp; ! 530: struct tty *dzbase; ! 531: int t_bit, lino, i, n; ! 532: ! 533: n = dev.d_minor; ! 534: for(i = 0; i < NDZ; i++) ! 535: { ! 536: dzaddr = (dzp = &dz[n])->dzaddr; ! 537: dzbase = &dz11[n*8]; ! 538: while((c = dzaddr->dzcsr) < 0) /* xmit line ready */ ! 539: { ! 540: t_bit = 1<<(lino = (c>>8)&07); ! 541: ! 542: tp = &dzbase[lino]; ! 543: ! 544: if((!(dzp->carrier&t_bit) || (dzaddr->dzcarr&t_bit)) && (c = getc(&tp->t_outq)) >= 0) ! 545: if(c <= 0177 || tp->t_flags == RAW) ! 546: dzaddr->dztbuf = c; ! 547: else ! 548: { ! 549: dzaddr->dztcr =& ~t_bit; ! 550: tp->t_state =| TIMEOUT; ! 551: dzdelays[tp-dz11] = ((c&0177)+(TSCANRATE-1))/TSCANRATE+1; /* set up timeout */ ! 552: continue; ! 553: } ! 554: else ! 555: dzaddr->dztcr =& ~t_bit; ! 556: ! 557: #ifdef TTY_HISPEED ! 558: if(tp->t_outq.c_cc <= ((tp->t_speeds&017) > B1200?TTHSLOWAT:TTLOWAT) && (tp->t_state&ASLEEP)) ! 559: #else ! 560: if(tp->t_outq.c_cc <= TTLOWAT && (tp->t_state&ASLEEP)) ! 561: #endif TTY_HISPEED ! 562: { ! 563: tp->t_state =& ~ASLEEP; ! 564: wakeup(&tp->t_outq); ! 565: } ! 566: } ! 567: if(++n >= NDZ) ! 568: n = 0; ! 569: } ! 570: } ! 571: ! 572: ! 573: ! 574: /* ! 575: * DZ11 receiver interrupt ! 576: * ! 577: * Scan each dz commencing with the ! 578: * particular device that caused this call. ! 579: * Storing each charater as it comes. ! 580: */ ! 581: dzrint(dev) ! 582: { ! 583: register struct tty *tp; ! 584: register c; ! 585: register struct dzr_read *dzaddr; ! 586: struct dz *dzp; ! 587: struct tty *dzbase; ! 588: int i, n, lino, t_bit; ! 589: ! 590: n = dev.d_minor; ! 591: for(i = 0; i < NDZ; i++) ! 592: { ! 593: dzp = &dz[n]; ! 594: if(dzp->openl) ! 595: { ! 596: dzbase = &dz11[n*8]; ! 597: while((c = dzp->dzaddr->dzrbuf) < 0) /* char present in silo */ ! 598: { ! 599: tp = &dzbase[lino = ((c>>8)&07)]; ! 600: t_bit = 1<<lino; ! 601: if(c&RERROR) ! 602: { ! 603: if(c&OVR_RUN) ! 604: { ! 605: dzp->overrors++; ! 606: # ifdef MESSAGES ! 607: printf("over run on dz %d/%d\n", n, lino); ! 608: # endif MESSAGES ! 609: } ! 610: if(c&FRAME) /* break */ ! 611: if(tp->t_flags&RAW) ! 612: c = 0; /* null ( for getty ) */ ! 613: else ! 614: # ifdef INTR_ON_BREAK ! 615: c = CINTR; /* del for NCRs. */ ! 616: # else ! 617: continue; /* ignore framing errors if not raw */ ! 618: # endif INTR_ON_BREAK ! 619: else if(c&PARITY) ! 620: { ! 621: dzp->pyerrors++; ! 622: # ifdef MESSAGES ! 623: printf("parity on dz %d/%d\n", n, lino); ! 624: # endif MESSAGES ! 625: continue; /* throw away bad chars */ ! 626: } ! 627: } ! 628: if((!(dzp->carrier&t_bit)) || (dzp->dzaddr->dzcarr&t_bit)) ! 629: ttyinput(c, tp); ! 630: } ! 631: } ! 632: if(++n >= NDZ) ! 633: n = 0; ! 634: } ! 635: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.