|
|
1.1 ! root 1: /* ttyold.c 4.1 11/9/80 */ ! 2: ! 3: /* ! 4: * general TTY subroutines ! 5: */ ! 6: #include "../h/param.h" ! 7: #include "../h/systm.h" ! 8: #include "../h/dir.h" ! 9: #include "../h/user.h" ! 10: #include "../h/tty.h" ! 11: #include "../h/proc.h" ! 12: #include "../h/mx.h" ! 13: #include "../h/inode.h" ! 14: #include "../h/file.h" ! 15: #include "../h/reg.h" ! 16: #include "../h/conf.h" ! 17: #include "../h/buf.h" ! 18: #include "../h/dk.h" ! 19: ! 20: char partab[]; ! 21: ! 22: /* ! 23: * When running dz's using only SAE (silo alarm) on input ! 24: * it is necessary to call dzrint() at clock interrupt time. ! 25: * This is unsafe unless spl5()s in tty code are changed to ! 26: * spl6()s to block clock interrupts. Note that the dh driver ! 27: * currently in use works the same way as the dz, even though ! 28: * we could try to more intelligently manage its silo. ! 29: * Thus don't take this out if you have no dz's unless you ! 30: * change clock.c and dhtimer(). ! 31: */ ! 32: #define spl5 spl6 ! 33: ! 34: /* ! 35: * Input mapping table-- if an entry is non-zero, when the ! 36: * corresponding character is typed preceded by "\" the escape ! 37: * sequence is replaced by the table value. Mostly used for ! 38: * upper-case only terminals. ! 39: */ ! 40: char maptab[]; ! 41: ! 42: #define OBUFSIZ 100 ! 43: ! 44: /* ! 45: * routine called on first teletype open. ! 46: * establishes a process group for distribution ! 47: * of quits and interrupts from the tty. ! 48: */ ! 49: ttyopen(dev, tp) ! 50: dev_t dev; ! 51: register struct tty *tp; ! 52: { ! 53: register struct proc *pp; ! 54: ! 55: pp = u.u_procp; ! 56: tp->t_dev = dev; ! 57: if(pp->p_pgrp == 0) { ! 58: u.u_ttyp = tp; ! 59: u.u_ttyd = dev; ! 60: if (tp->t_pgrp == 0) ! 61: tp->t_pgrp = pp->p_pid; ! 62: pp->p_pgrp = tp->t_pgrp; ! 63: } ! 64: tp->t_state &= ~WOPEN; ! 65: tp->t_state |= ISOPEN; ! 66: tp->t_line = 0; /* conservative */ ! 67: } ! 68: ! 69: /* ! 70: * clean tp on last close ! 71: */ ! 72: ttyclose(tp) ! 73: register struct tty *tp; ! 74: { ! 75: ! 76: tp->t_pgrp = 0; ! 77: wflushtty(tp); ! 78: tp->t_state = 0; ! 79: tp->t_line = 0; ! 80: } ! 81: ! 82: /* ! 83: * transfer raw input list to canonical list, ! 84: * doing erase-kill processing and handling escapes. ! 85: * It waits until a full line has been typed in cooked mode, ! 86: * or until any character has been typed in raw mode. ! 87: */ ! 88: canon(tp) ! 89: register struct tty *tp; ! 90: { ! 91: register char *bp; ! 92: char *bp1; ! 93: register int c; ! 94: int mc; ! 95: int s; ! 96: ! 97: if ((tp->t_flags&(RAW|CBREAK))==0 && tp->t_delct==0 ! 98: || (tp->t_flags&(RAW|CBREAK))!=0 && tp->t_rawq.c_cc==0) { ! 99: return(-1); ! 100: } ! 101: s = spl0(); ! 102: loop: ! 103: bp = &canonb[2]; ! 104: while ((c=getc(&tp->t_rawq)) >= 0) { ! 105: if ((tp->t_flags&(RAW|CBREAK))==0) { ! 106: if (c==0377) { ! 107: tp->t_delct--; ! 108: break; ! 109: } ! 110: if (bp[-1]!='\\') { ! 111: if (c==tp->t_erase) { ! 112: if (bp > &canonb[2]) ! 113: bp--; ! 114: continue; ! 115: } ! 116: if (c==tp->t_kill) ! 117: goto loop; ! 118: if (c==tun.t_eofc) ! 119: continue; ! 120: } else { ! 121: mc = maptab[c]; ! 122: if (c==tp->t_erase || c==tp->t_kill) ! 123: mc = c; ! 124: if (mc && (mc==c || (tp->t_flags&LCASE))) { ! 125: if (bp[-2] != '\\') ! 126: c = mc; ! 127: bp--; ! 128: } ! 129: } ! 130: } ! 131: *bp++ = c; ! 132: if (bp>=canonb+CANBSIZ) ! 133: break; ! 134: } ! 135: bp1 = &canonb[2]; ! 136: (void) b_to_q(bp1, bp-bp1, &tp->t_canq); ! 137: ! 138: if (tp->t_state&TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) { ! 139: if (putc(tun.t_startc, &tp->t_outq)==0) { ! 140: tp->t_state &= ~TBLOCK; ! 141: ttstart(tp); ! 142: } ! 143: tp->t_char = 0; ! 144: } ! 145: ! 146: splx(s); ! 147: return(0); ! 148: } ! 149: ! 150: ! 151: /* ! 152: * block transfer input handler. ! 153: */ ! 154: ttyrend(tp, pb, pe) ! 155: register struct tty *tp; ! 156: register char *pb, *pe; ! 157: { ! 158: int tandem; ! 159: ! 160: tandem = tp->t_flags&TANDEM; ! 161: if (tp->t_flags&RAW) { ! 162: (void) b_to_q(pb, pe-pb, &tp->t_rawq); ! 163: if (tp->t_chan) ! 164: (void) sdata(tp->t_chan); else ! 165: wakeup((caddr_t)&tp->t_rawq); ! 166: } else { ! 167: tp->t_flags &= ~TANDEM; ! 168: while (pb < pe) ! 169: ttyinput(*pb++, tp); ! 170: tp->t_flags |= tandem; ! 171: } ! 172: if (tandem) ! 173: ttyblock(tp); ! 174: } ! 175: ! 176: /* ! 177: * Place a character on raw TTY input queue, putting in delimiters ! 178: * and waking up top half as needed. ! 179: * Also echo if required. ! 180: * The arguments are the character and the appropriate ! 181: * tty structure. ! 182: */ ! 183: ttyinput(c, tp) ! 184: register c; ! 185: register struct tty *tp; ! 186: { ! 187: register int t_flags; ! 188: register struct chan *cp; ! 189: ! 190: tk_nin += 1; ! 191: c &= 0377; ! 192: t_flags = tp->t_flags; ! 193: if (t_flags&TANDEM) ! 194: ttyblock(tp); ! 195: if ((t_flags&RAW)==0) { ! 196: c &= 0177; ! 197: if (tp->t_state&TTSTOP) { ! 198: if (c==tun.t_startc) { ! 199: tp->t_state &= ~TTSTOP; ! 200: ttstart(tp); ! 201: return; ! 202: } ! 203: if (c==tun.t_stopc) ! 204: return; ! 205: tp->t_state &= ~TTSTOP; ! 206: ttstart(tp); ! 207: } else { ! 208: if (c==tun.t_stopc) { ! 209: tp->t_state |= TTSTOP; ! 210: (*cdevsw[major(tp->t_dev)].d_stop)(tp); ! 211: return; ! 212: } ! 213: if (c==tun.t_startc) ! 214: return; ! 215: } ! 216: if (c==tun.t_quitc || c==tun.t_intrc) { ! 217: flushtty(tp, FREAD|FWRITE); ! 218: c = (c==tun.t_intrc) ? SIGINT:SIGQUIT; ! 219: if (tp->t_chan) ! 220: scontrol(tp->t_chan, M_SIG, c); ! 221: else ! 222: gsignal(tp->t_pgrp, c); ! 223: return; ! 224: } ! 225: if (c=='\r' && t_flags&CRMOD) ! 226: c = '\n'; ! 227: } ! 228: if (tp->t_rawq.c_cc>TTYHOG) { ! 229: flushtty(tp, FREAD|FWRITE); ! 230: return; ! 231: } ! 232: if (t_flags&LCASE && c>='A' && c<='Z') ! 233: c += 'a'-'A'; ! 234: (void) putc(c, &tp->t_rawq); ! 235: if (t_flags&(RAW|CBREAK)||(c=='\n'||c==tun.t_eofc||c==tun.t_brkc)) { ! 236: if ((t_flags&(RAW|CBREAK))==0 && putc(0377, &tp->t_rawq)==0) ! 237: tp->t_delct++; ! 238: if ((cp=tp->t_chan)!=NULL) ! 239: (void) sdata(cp); else ! 240: wakeup((caddr_t)&tp->t_rawq); ! 241: } ! 242: if (t_flags&ECHO) { ! 243: ttyoutput(c, tp); ! 244: if (c==tp->t_kill && (t_flags&(RAW|CBREAK))==0) ! 245: ttyoutput('\n', tp); ! 246: ttstart(tp); ! 247: } ! 248: } ! 249: ! 250: /* ! 251: * put character on TTY output queue, adding delays, ! 252: * expanding tabs, and handling the CR/NL bit. ! 253: * It is called both from the top half for output, and from ! 254: * interrupt level for echoing. ! 255: * The arguments are the character and the tty structure. ! 256: */ ! 257: ttyoutput(c, tp) ! 258: register c; ! 259: register struct tty *tp; ! 260: { ! 261: register char *colp; ! 262: register ctype; ! 263: ! 264: /* ! 265: * Ignore EOT in normal mode to avoid hanging up ! 266: * certain terminals. ! 267: * In raw mode dump the char unchanged. ! 268: */ ! 269: if ((tp->t_flags&RAW)==0) { ! 270: c &= 0177; ! 271: if ((tp->t_flags&CBREAK)==0 && c==CEOT) ! 272: return; ! 273: } else { ! 274: tk_nout++; ! 275: (void) putc(c, &tp->t_outq); ! 276: return; ! 277: } ! 278: ! 279: /* ! 280: * Turn tabs to spaces as required ! 281: */ ! 282: if (c=='\t' && (tp->t_flags&TBDELAY)==XTABS) { ! 283: c = 8 - (tp->t_col & 7); ! 284: (void) b_to_q(" ", c, &tp->t_outq); ! 285: tp->t_col += c; ! 286: tk_nout += c; ! 287: return; ! 288: } ! 289: tk_nout++; ! 290: /* ! 291: * for upper-case-only terminals, ! 292: * generate escapes. ! 293: */ ! 294: if (tp->t_flags&LCASE) { ! 295: colp = "({)}!|^~'`"; ! 296: while(*colp++) ! 297: if(c == *colp++) { ! 298: ttyoutput('\\', tp); ! 299: c = colp[-2]; ! 300: break; ! 301: } ! 302: if ('a'<=c && c<='z') ! 303: c += 'A' - 'a'; ! 304: } ! 305: /* ! 306: * turn <nl> to <cr><lf> if desired. ! 307: */ ! 308: if (c=='\n' && tp->t_flags&CRMOD) ! 309: ttyoutput('\r', tp); ! 310: (void) putc(c, &tp->t_outq); ! 311: /* ! 312: * Calculate delays. ! 313: * The numbers here represent clock ticks ! 314: * and are not necessarily optimal for all terminals. ! 315: * The delays are indicated by characters above 0200. ! 316: * In raw mode there are no delays and the ! 317: * transmission path is 8 bits wide. ! 318: */ ! 319: colp = &tp->t_col; ! 320: ctype = partab[c]; ! 321: c = 0; ! 322: switch (ctype&077) { ! 323: ! 324: /* ordinary */ ! 325: case 0: ! 326: (*colp)++; ! 327: ! 328: /* non-printing */ ! 329: case 1: ! 330: break; ! 331: ! 332: /* backspace */ ! 333: case 2: ! 334: if (*colp) ! 335: (*colp)--; ! 336: break; ! 337: ! 338: /* newline */ ! 339: case 3: ! 340: ctype = (tp->t_flags >> 8) & 03; ! 341: if(ctype == 1) { /* tty 37 */ ! 342: if (*colp) ! 343: c = max(((unsigned)*colp>>4) + 3, (unsigned)6); ! 344: } else ! 345: if(ctype == 2) { /* vt05 */ ! 346: c = 6; ! 347: } ! 348: *colp = 0; ! 349: break; ! 350: ! 351: /* tab */ ! 352: case 4: ! 353: ctype = (tp->t_flags >> 10) & 03; ! 354: if(ctype == 1) { /* tty 37 */ ! 355: c = 1 - (*colp | ~07); ! 356: if(c < 5) ! 357: c = 0; ! 358: } ! 359: *colp |= 07; ! 360: (*colp)++; ! 361: break; ! 362: ! 363: /* vertical motion */ ! 364: case 5: ! 365: if(tp->t_flags & VTDELAY) /* tty 37 */ ! 366: c = 0177; ! 367: break; ! 368: ! 369: /* carriage return */ ! 370: case 6: ! 371: ctype = (tp->t_flags >> 12) & 03; ! 372: if(ctype == 1) { /* tn 300 */ ! 373: c = 5; ! 374: } else if(ctype == 2) { /* ti 700 */ ! 375: c = 10; ! 376: } else if(ctype == 3) { /* concept 100 */ ! 377: int i; ! 378: if ((i = *colp) >= 0) ! 379: for (; i<9; i++) ! 380: (void) putc(0177, &tp->t_outq); ! 381: } ! 382: *colp = 0; ! 383: } ! 384: if(c) ! 385: (void) putc(c|0200, &tp->t_outq); ! 386: } ! 387: ! 388: /* ! 389: * Called from device's read routine after it has ! 390: * calculated the tty-structure given as argument. ! 391: */ ! 392: ttread(tp) ! 393: register struct tty *tp; ! 394: { ! 395: register s; ! 396: ! 397: if ((tp->t_state&CARR_ON)==0) ! 398: return(-1); ! 399: s = spl5(); ! 400: if (tp->t_canq.c_cc==0) ! 401: while (canon(tp)<0) ! 402: if (tp->t_chan==NULL) { ! 403: sleep((caddr_t)&tp->t_rawq, TTIPRI); ! 404: } else { ! 405: splx(s); ! 406: return(0); ! 407: } ! 408: splx(s); ! 409: while (tp->t_canq.c_cc && passc(getc(&tp->t_canq))>=0) ! 410: ; ! 411: return(tp->t_rawq.c_cc+tp->t_canq.c_cc); ! 412: } ! 413: ! 414: /* ! 415: * Called from the device's write routine after it has ! 416: * calculated the tty-structure given as argument. ! 417: */ ! 418: caddr_t ! 419: ttwrite(tp) ! 420: register struct tty *tp; ! 421: { ! 422: /* ! 423: * THE POSITIONING OF CP, CC, AND CE ARE CRITICAL ! 424: * AND MUST NOT BE CHANGED WITHOUT PATCHING ! 425: * THE 'ASM' INLINES BELOW. WATCH OUT. ! 426: */ ! 427: register char *cp; ! 428: register int cc, ce; ! 429: register i; ! 430: char obuf[OBUFSIZ]; ! 431: int hiwat = TTHIWAT(tp); ! 432: ! 433: if ((tp->t_state&CARR_ON)==0) ! 434: return(NULL); ! 435: while (u.u_count) { ! 436: cc = MIN(u.u_count, OBUFSIZ); ! 437: cp = obuf; ! 438: iomove(cp, (unsigned)cc, B_WRITE); ! 439: if (u.u_error) ! 440: break; ! 441: (void) spl5(); ! 442: while (tp->t_outq.c_cc > hiwat) { ! 443: ttstart(tp); ! 444: tp->t_state |= ASLEEP; ! 445: if (tp->t_chan) { ! 446: u.u_base -= cc; ! 447: u.u_offset -= cc; ! 448: u.u_count += cc; ! 449: (void) spl0(); ! 450: return((caddr_t)&tp->t_outq); ! 451: } ! 452: sleep((caddr_t)&tp->t_outq, TTOPRI); ! 453: } ! 454: (void) spl0(); ! 455: if (tp->t_flags&LCASE) { ! 456: while (cc--) ! 457: ttyoutput(*cp++,tp); ! 458: continue; ! 459: } ! 460: while (cc) { ! 461: if (tp->t_flags&RAW) ! 462: ce=cc; ! 463: else { ! 464: #ifdef VAX ! 465: asm(" scanc r9,(r10),_partab,$077"); ! 466: asm(" subl3 r0,r9,r8"); ! 467: #else ! 468: ce=0; ! 469: while(((partab[*(unsigned char *)(cp+ce)]&077)==0)&&(ce<cc)) ! 470: ce++; ! 471: #endif ! 472: if (ce==0) { ! 473: ttyoutput(*cp++,tp); ! 474: cc--; ! 475: goto check; ! 476: } ! 477: } ! 478: i=b_to_q(cp,ce,&tp->t_outq); ! 479: ce-=i; ! 480: tk_nout+=ce; ! 481: tp->t_col+=ce; ! 482: cp+=ce; ! 483: cc-=ce; ! 484: check: ! 485: if (tp->t_outq.c_cc > hiwat) { ! 486: (void) spl5(); ! 487: while (tp->t_outq.c_cc > hiwat) { ! 488: ttstart(tp); ! 489: tp->t_state |= ASLEEP; ! 490: sleep((caddr_t)&tp->t_outq, TTOPRI); ! 491: } ! 492: (void) spl0(); ! 493: } ! 494: } ! 495: } ! 496: ttstart(tp); ! 497: return(NULL); ! 498: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.