|
|
1.1 ! root 1: /* ! 2: * DZ-11 driver ! 3: * ------------ ! 4: * ! 5: * OPTIMIZED dz driver to handle multiple dzs as efficiently ! 6: * as possible. The efficiency is gained by disabling all ! 7: * dz transmitter interrupts and using a KW11-P to generate ! 8: * suitable interrupts. Carrier is supported but not Ring. ! 9: * ! 10: * Ian Johnstone UNSW ! 11: * May 1979 ! 12: */ ! 13: ! 14: #include "../defines.h" ! 15: #include "../param.h" ! 16: #include "../conf.h" ! 17: #include "../user.h" ! 18: #include "../tty.h" ! 19: #include "../proc.h" ! 20: ! 21: #define NDZ 7 /* no. of dz-11s */ ! 22: ! 23: #define NDZLIN 8 /* no. of lines per dz DO NOT ALTER */ ! 24: #define NLINES (NDZLIN*NDZ) /* total no. of lines available */ ! 25: ! 26: #define SSPEED 11 /* standard speed 2400 bd */ ! 27: ! 28: #define CLOCK 0172540 /* kw11-p lives here */ ! 29: ! 30: struct ! 31: { ! 32: int csr; /* control and status */ ! 33: #define GO 0101 /* down, single, 100K, run */ ! 34: unsigned counter; /* counter */ ! 35: }; ! 36: ! 37: struct tty dz11[NLINES]; /* tty structures for this dz */ ! 38: ! 39: struct dz /* one for each dz-11 */ ! 40: { ! 41: int *dzaddr; /* control registers for this dz */ ! 42: char nocarr; /* set for lines WITHOUT carrier */ ! 43: char sopen; /* set for lines with exclusive use */ ! 44: struct tty *ttys[NDZLIN]; /* address of tty structs this dz */ ! 45: /* that is only ONE `open' allowed */ ! 46: char openl; /* flags for open lines */ ! 47: char closl; /* flags to indicate closing lines */ ! 48: char xmit; /* set for lines to transmit on */ ! 49: unsigned pyerrors; /* number of parity errors on input */ ! 50: unsigned overrors; /* number of overrun errors on input */ ! 51: int closet[NDZLIN]; /* handle closing via this field */ ! 52: } ! 53: dz[NDZ] ! 54: { ! 55: { ! 56: 0160100, 0377, 0000, ! 57: &dz11[000],&dz11[001],&dz11[002],&dz11[003], ! 58: &dz11[004],&dz11[005],&dz11[006],&dz11[007] ! 59: }, ! 60: { ! 61: 0160110, 0007, 0000, ! 62: &dz11[010],&dz11[011],&dz11[012],&dz11[013], ! 63: &dz11[014],&dz11[015],&dz11[016],&dz11[017] ! 64: }, ! 65: { ! 66: 0160120, 0320, 0020, ! 67: &dz11[020],&dz11[021],&dz11[022],&dz11[023], ! 68: &dz11[024],&dz11[025],&dz11[026],&dz11[027] ! 69: }, ! 70: { ! 71: 0160130, 0000, 0000, ! 72: &dz11[030],&dz11[031],&dz11[032],&dz11[033], ! 73: &dz11[034],&dz11[035],&dz11[036],&dz11[037] ! 74: }, ! 75: { ! 76: 0160140, 0000, 0000, ! 77: &dz11[040],&dz11[041],&dz11[042],&dz11[043], ! 78: &dz11[044],&dz11[045],&dz11[046],&dz11[047] ! 79: }, ! 80: { ! 81: 0160150, 0360, 0100, ! 82: &dz11[050],&dz11[051],&dz11[052],&dz11[053], ! 83: &dz11[054],&dz11[055],&dz11[056],&dz11[057] ! 84: }, ! 85: { ! 86: 0160160, 0110, 0013, ! 87: &dz11[060],&dz11[061],&dz11[062],&dz11[063], ! 88: &dz11[064],&dz11[065],&dz11[066],&dz11[067] ! 89: }, ! 90: /* ! 91: { ! 92: 0160170, 0377, 0000, ! 93: &dz11[070],&dz11[071],&dz11[072],&dz11[073], ! 94: &dz11[074],&dz11[075],&dz11[076],&dz11[077] ! 95: } ! 96: */ ! 97: }; ! 98: ! 99: int dzopenc; /* equal to total number of 'open' lines */ ! 100: ! 101: int dzrcvscan; /* when <= 0 scan receiver silos */ ! 102: ! 103: char dzbitab[NDZLIN] /* convert line numbers to bit pattern */ ! 104: { ! 105: 0001, 0002, 0004, 0010, 0020, 0040, 0100, 0200 ! 106: }; ! 107: ! 108: #define SPLDZ spl5 /* dz interrupts at this priority */ ! 109: ! 110: /* ! 111: * DZ11 register layout ! 112: */ ! 113: struct dzr_read ! 114: { ! 115: int dzcsr; /* r/w */ ! 116: int dzrbuf; /* no bit, byte, or tst ops */ ! 117: char dztcr; /* r/w */ ! 118: char dzdtr; /* r/w */ ! 119: char dzring; ! 120: char dzcarr; ! 121: }; ! 122: struct dzr_write ! 123: { ! 124: int dzcsr; ! 125: int dzlpr; /* no bit or byte ops */ ! 126: char dztcr; ! 127: char dzdtr; ! 128: char dztbuf; /* no bit ops */ ! 129: char dzbrk; /* no bit ops */ ! 130: }; ! 131: /* ! 132: * register control bits ! 133: */ ! 134: #define SAE 010000 /* dzcsr */ ! 135: #define RIE 0100 ! 136: #define MSE 040 ! 137: #define RCVR_ON 010000 /* dzlpr */ ! 138: #define ODD_PAR 0300 ! 139: #define EVN_PAR 0100 ! 140: #define TWOSBIT 040 ! 141: #define C8BIT 030 ! 142: #define C7BIT 020 ! 143: #define RERROR 070000 /* dzrbuf */ ! 144: #define OVR_RUN 040000 ! 145: #define FRAME 020000 ! 146: #define PARITY 010000 ! 147: ! 148: /* ! 149: * Table to map UNIX standard speeds to DZ11 speeds. ! 150: * Illegal speeds are ignored, and are indicated by 0200 bit. ! 151: */ ! 152: char dzspeedmap[16] ! 153: { ! 154: 0200 /* 0 - zero */ ! 155: , 0220 /* 1 - 50 */ ! 156: , 0221 /* 2 - 75 */ ! 157: , 0222 /* 3 - 110 */ ! 158: , 0223 /* 4 - 134.5 */ ! 159: , 0224 /* 5 - 150 */ ! 160: , 0200 /* 6 - ILLEGAL */ ! 161: #define LOWSPEED 7 /* lowest speed allowed on dz */ ! 162: , 025 /* 7 - 300 */ ! 163: , 026 /* 8 - 600 */ ! 164: , 027 /* 9 - 1200 */ ! 165: , 0230 /* 10 - 1800 */ ! 166: , 032 /* 11 - 2400 */ ! 167: , 034 /* 12 - 4800 */ ! 168: , 036 /* 13 - 9600 */ ! 169: , 0231 /* 14 - ext A - maps to 2000 */ ! 170: , 0237 /* 15 - ext B - maps to 19200 */ ! 171: }; ! 172: ! 173: /* ! 174: * Table to map UNIX standard speeds to time between interrupts for ! 175: * a line running at that speed. The value in the table is multiplied ! 176: * by 10 to get a value in microseconds. A nominal 20 microseconds ! 177: * is subtracted to make up for interrupt overhead. ! 178: */ ! 179: ! 180: unsigned dzmicmap[16] ! 181: { ! 182: 0 /* 0 - zero */ ! 183: , 19998 /* 1 - 50 */ ! 184: , 13331 /* 2 - 75 */ ! 185: , 9088 /* 3 - 110 */ ! 186: , 7433 /* 4 - 134.5 */ ! 187: , 6665 /* 5 - 150 */ ! 188: , 0 /* 6 - ILLEGAL */ ! 189: , 3331 /* 7 - 300 */ ! 190: , 1665 /* 8 - 600 */ ! 191: , 831 /* 9 - 1200 */ ! 192: , 554 /* 10 - 1800 */ ! 193: , 415 /* 11 - 2400 */ ! 194: , 206 /* 12 - 4800 */ ! 195: , 102 /* 13 - 9600 */ ! 196: , 498 /* 14 - ext A - maps to 2000 */ ! 197: , 50 /* 15 - ext B - maps to 19200 */ ! 198: }; ! 199: ! 200: /* ! 201: * open a DZ11 line ! 202: */ ! 203: dzopen(dev, flag) ! 204: { ! 205: extern dzstart(); ! 206: register struct tty *tp; ! 207: register struct dz *dzp; ! 208: register lino; ! 209: ! 210: lino = dev.d_minor; ! 211: if(lino >= NLINES) ! 212: { ! 213: u.u_error = ENXIO; ! 214: return; ! 215: } ! 216: dzp = &dz[lino>>3]; ! 217: if(!fkword(dzp->dzaddr)) /* fix036 */ ! 218: { ! 219: u.u_error = ENXIO; ! 220: return; ! 221: } /* fix036 */ ! 222: tp = &dz11[lino]; ! 223: lino =& 07; ! 224: ! 225: if( (dzp->sopen&dzbitab[lino]) && (dzp->openl&dzbitab[lino]) ) ! 226: { ! 227: u.u_error = EOPENFAIL; ! 228: return; ! 229: } ! 230: ! 231: if(u.u_procp->p_ttyp == 0) ! 232: u.u_procp->p_ttyp = tp; ! 233: ! 234: SPLDZ(); ! 235: ! 236: if( (dzp->openl&dzbitab[lino]) == 0 ) ! 237: { ! 238: tp->t_dev = dev; ! 239: tp->t_state = (ISOPEN|CARR_ON|SSTART); ! 240: tp->t_addr = &dzstart; ! 241: tp->t_speeds = SSPEED|(SSPEED<<8); ! 242: tp->t_flags = ODDP|EVENP|XTABS|RAW; ! 243: tp->t_erase = CERASE; ! 244: tp->t_kill = CKILL; ! 245: ! 246: dzparam(tp); ! 247: ! 248: if(dzp->openl == 0) ! 249: dzp->dzaddr->dzcsr =| (RIE|SAE|MSE); /* init */ ! 250: ! 251: dzp->openl =| dzbitab[lino]; ! 252: ! 253: if(dzopenc++ == 0) ! 254: dzxint(); /* start transmitting */ ! 255: ! 256: } ! 257: else ! 258: dzp->closl =& ~dzbitab[lino]; ! 259: spl0(); ! 260: } ! 261: ! 262: /* ! 263: * close a DZ11 line ! 264: */ ! 265: dzclose(dev) ! 266: { ! 267: register struct tty *tp; ! 268: register struct dz *dzp; ! 269: register lino; ! 270: ! 271: lino = dev.d_minor; ! 272: dzp = &dz[lino>>3]; ! 273: tp = &dz11[lino]; ! 274: lino =& 07; ! 275: ! 276: dzp->closet[lino] = tp->t_outq.c_cc << 1; /* time for close */ ! 277: dzp->closl =| dzbitab[lino]; ! 278: dzp->xmit =| dzbitab[lino]; /* start transmitting */ ! 279: dzp->dzaddr->dztcr =| dzbitab[lino]; /* start transmitting */ ! 280: } ! 281: ! 282: /* ! 283: * read from a DZ11 line ! 284: */ ! 285: dzread(dev) ! 286: { ! 287: ttread( &dz11[dev.d_minor] ); ! 288: } ! 289: ! 290: /* ! 291: * write on a DZ11 line ! 292: */ ! 293: dzwrite(dev) ! 294: { ! 295: ttwrite( &dz11[dev.d_minor] ); ! 296: } ! 297: ! 298: /* ! 299: * stty/gtty for DZ11 ! 300: */ ! 301: dzsgtty(dev, av) ! 302: { ! 303: register struct tty *tp; ! 304: ! 305: if((av == 0) && (dzspeedmap[u.u_arg[0]&017] < 0)) ! 306: { ! 307: u.u_error = ENXIO; /* illegal speed */ ! 308: return; ! 309: } ! 310: tp = &dz11[dev.d_minor]; ! 311: if(ttystty(tp, av)) ! 312: return; ! 313: dzparam(tp); ! 314: } ! 315: ! 316: /* ! 317: * set parameters from open or stty into DZ hardware registers ! 318: */ ! 319: dzparam(tp) ! 320: register struct tty *tp; ! 321: { ! 322: register lpr, x; ! 323: extern wakeup(); ! 324: ! 325: lpr = dzspeedmap[tp->t_speeds&017]<<8; ! 326: ! 327: if((x = tp->t_flags)&EVENP) ! 328: if((x&ODDP) == 0) ! 329: lpr =| (EVN_PAR|C7BIT); ! 330: else ! 331: lpr =| C8BIT; ! 332: else if(x&ODDP) ! 333: lpr =| (ODD_PAR|C7BIT); ! 334: else ! 335: lpr =| C8BIT; ! 336: ! 337: /* set new speed, char currently in uart may be screwed */ ! 338: ! 339: dz[tp->t_dev.d_minor>>3].dzaddr->dzlpr = lpr|(tp->t_dev.d_minor&07); ! 340: } ! 341: /* ! 342: * dz start routine ! 343: */ ! 344: dzstart(tp) /* at SPLDZ */ ! 345: struct tty *tp; ! 346: { ! 347: register lino = tp->t_dev.d_minor; ! 348: register struct dz *dzp; ! 349: ! 350: dzp = &dz[lino>>3]; ! 351: lino =& 07; ! 352: dzp->xmit =| dzbitab[lino]; /* start transmitting */ ! 353: dzp->dzaddr->dztcr =| dzbitab[lino]; /* start transmitting */ ! 354: } ! 355: ! 356: /* ! 357: * DZ11 transmitter interrupt. ! 358: * ! 359: * Scan every line on each dz. Internal dz limitations ! 360: * force this scan to take an unusual form. One line ! 361: * from each dz is serviced each scan until no dz requires ! 362: * service. This is less efficient than servicing ! 363: * entirely a dz prior to scanning the next dz but it ! 364: * it is necessary. ! 365: * ! 366: * dzxint is not actually invoked by a dz interrupt ! 367: * rather it is invoked by a clock interrupt. ! 368: * to drive multiple dz's efficiently utilizing dz ! 369: * transmitter interrupts is just NOT possible. ! 370: */ ! 371: int dzxc; ! 372: dzxint() /* at SPLDZ */ ! 373: { ! 374: extern ttrstrt(); ! 375: register struct dz *dzp; ! 376: int hspeed = LOWSPEED; /* to determine clock speed */ ! 377: int flag; /* control dz scanning */ ! 378: ! 379: dzxc++; /* count */ ! 380: if( dzopenc == 0 ) return; /* stop if inactive */ ! 381: ! 382: /* scan every dz for characters to transmit */ ! 383: ! 384: do ! 385: { ! 386: for(dzp = &dz[0], flag=0; dzp < &dz[NDZ]; dzp++ ) ! 387: { ! 388: register struct tty *tp; ! 389: register struct dzr_read *dza = dzp->dzaddr; ! 390: int lino, t_bit; ! 391: ! 392: if((lino = dza->dzcsr.hibyte) < 0) /* xmit ?? */ ! 393: { ! 394: lino =& 07; /* isolate line number */ ! 395: tp = dzp->ttys[lino]; ! 396: t_bit = dzbitab[lino]; /* bit mask, not line number */ ! 397: flag++; /* note service */ ! 398: if( (dzp->closl & t_bit) ! 399: && ((--(dzp->closet[lino]) <= 0) || (tp->t_outq.c_cc == 0)) ) ! 400: { ! 401: /* line closed, no time or chars left */ ! 402: flushtty(tp); ! 403: tp->t_state = SSTART; ! 404: dzp->closl =& ~t_bit; ! 405: dzp->openl =& ~t_bit; ! 406: dzp->xmit =& ~t_bit; ! 407: dza->dztcr =& ~t_bit; ! 408: dza->dzdtr =& ~t_bit; ! 409: if( (dzp->closl==0) && (dzp->openl==0) ) ! 410: dza->dzcsr = 0; ! 411: if( --dzopenc == 0 ) ! 412: return; ! 413: } ! 414: else if(tp->t_outq.c_cc == 0) ! 415: { ! 416: dzp->xmit =& ~t_bit; ! 417: dza->dztcr =& ~t_bit; ! 418: } ! 419: else if((dzp->nocarr&t_bit)||(dza->dzcarr&t_bit)) ! 420: { ! 421: int c = getc(&tp->t_outq); ! 422: if( c <= 0177 || tp->t_flags == RAW ) ! 423: { ! 424: /* transmit the char for this line */ ! 425: dza->dztbuf = c; ! 426: if( tp->t_speeds.lobyte > hspeed ) ! 427: hspeed = tp->t_speeds.lobyte; ! 428: } ! 429: else ! 430: { ! 431: dzp->xmit =& ~t_bit; ! 432: dza->dztcr =& ~t_bit; ! 433: timeout( &ttrstrt, tp, c&0177 ); ! 434: tp->t_state =| TIMEOUT; ! 435: } ! 436: /* if low water mark then want more */ ! 437: if( tp->t_state&ASLEEP ! 438: && tp->t_outq.c_cc <= TTLOWAT ) ! 439: { ! 440: tp->t_state =& ~ASLEEP; ! 441: wakeup(&tp->t_outq); ! 442: } ! 443: } ! 444: else ! 445: { ! 446: dza->dztcr =& ~t_bit; ! 447: } ! 448: } ! 449: } ! 450: } while( flag ); ! 451: ! 452: /* finalize state of DZs prior to exitting */ ! 453: ! 454: for(dzp = &dz[0]; dzp < &dz[NDZ]; dzp++ ) ! 455: { ! 456: register struct dzr_read *dza = dzp->dzaddr; ! 457: ! 458: /* dtr to reflect state of carrier, for carrier lines */ ! 459: ! 460: dza->dzdtr = (dza->dzcarr | dzp->nocarr) & dzp->openl; ! 461: ! 462: /* Enable all lines still with characters to send */ ! 463: ! 464: dza->dztcr = dzp->xmit; ! 465: } ! 466: ! 467: /* setup for next interrupt */ ! 468: ! 469: CLOCK->counter = dzmicmap[hspeed]; /* count in 10microseconds */ ! 470: CLOCK->csr = GO; ! 471: ! 472: /* call dzrint if needed */ ! 473: ! 474: if( dzrcvscan <= 0 ) ! 475: dzrint(0); ! 476: dzrcvscan =- dzmicmap[hspeed]; ! 477: } ! 478: ! 479: /* ! 480: * DZ11 receiver interrupt ! 481: * ! 482: * Scan each dz commencing with the particular device that caused this call ! 483: * Scan at least every dzmicmap[LOWSPEED] microseconds. ! 484: */ ! 485: dzrint(dev) ! 486: { ! 487: register struct tty *tp; ! 488: register struct dz *dzp; ! 489: register int lino; ! 490: int i, c; ! 491: ! 492: for(dzp = &dz[dev], i = 0; i < NDZ; i++) ! 493: { ! 494: while((c = dzp->dzaddr->dzrbuf) < 0) /* char present in silo */ ! 495: { ! 496: lino = c.hibyte; lino =& 07; ! 497: if( ((dzp->nocarr&dzbitab[lino]) == 0 ) ! 498: && ((dzp->dzaddr->dzcarr&dzbitab[lino]) == 0 )) continue; ! 499: if( (dzp->openl&dzbitab[lino]) == 0 ) continue; ! 500: tp = dzp->ttys[lino]; ! 501: if(c&RERROR) ! 502: { ! 503: if( (c & FRAME) && (tp->t_flags & RAW ) ) ! 504: ttyinput(0, tp); /* break for getty */ ! 505: else if(c & OVR_RUN) ! 506: dzp->overrors++; ! 507: else if(c & PARITY) ! 508: dzp->pyerrors++; ! 509: } ! 510: else ! 511: { ! 512: ttyinput(c, tp); ! 513: } ! 514: } ! 515: if( ++dzp >= &dz[NDZ] ) dzp = &dz[0]; ! 516: } ! 517: dzrcvscan = dzmicmap[LOWSPEED]; ! 518: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.