1: #
   2: /*
   3:  */
   4: 
   5: /*
   6:  * general TTY subroutines
   7:  */
   8: #include "../param.h"
   9: #include "../systm.h"
  10: #include "../user.h"
  11: #include "../tty.h"
  12: #include "../proc.h"
  13: #include "../inode.h"
  14: #include "../file.h"
  15: #include "../reg.h"
  16: #include "../conf.h"
  17: 
  18: /*
  19:  * Input mapping table-- if an entry is non-zero, when the
  20:  * corresponding character is typed preceded by "\" the escape
  21:  * sequence is replaced by the table value.  Mostly used for
  22:  * upper-case only terminals.
  23:  */
  24: char    maptab[]
  25: {
  26:     000,000,000,000,004,000,000,000,
  27:     000,000,000,000,000,000,000,000,
  28:     000,000,000,000,000,000,000,000,
  29:     000,000,000,000,000,000,000,000,
  30:     000,'|',000,'#',000,000,000,'`',
  31:     '{','}',000,000,000,000,000,000,
  32:     000,000,000,000,000,000,000,000,
  33:     000,000,000,000,000,000,000,000,
  34:     '@',000,000,000,000,000,000,000,
  35:     000,000,000,000,000,000,000,000,
  36:     000,000,000,000,000,000,000,000,
  37:     000,000,000,000,000,000,'~',000,
  38:     000,'A','B','C','D','E','F','G',
  39:     'H','I','J','K','L','M','N','O',
  40:     'P','Q','R','S','T','U','V','W',
  41:     'X','Y','Z',000,000,000,000,000,
  42: };
  43: 
  44: /*
  45:  * The actual structure of a clist block manipulated by
  46:  * getc and putc (mch.s)
  47:  */
  48: struct cblock {
  49:     struct cblock *c_next;
  50:     char info[6];
  51: };
  52: 
  53: /* The character lists-- space for 6*NCLIST characters */
  54: struct cblock cfree[NCLIST];
  55: /* List head for unused character blocks. */
  56: struct cblock *cfreelist;
  57: 
  58: /*
  59:  * structure of device registers for KL, DL, and DC
  60:  * interfaces-- more particularly, those for which the
  61:  * SSTART bit is off and can be treated by general routines
  62:  * (that is, not DH).
  63:  */
  64: struct {
  65:     int ttrcsr;
  66:     int ttrbuf;
  67:     int tttcsr;
  68:     int tttbuf;
  69: };
  70: 
  71: /*
  72:  * The routine implementing the gtty system call.
  73:  * Just call lower level routine and pass back values.
  74:  */
  75: gtty()
  76: {
  77:     int v[3];
  78:     register *up, *vp;
  79: 
  80:     vp = v;
  81:     sgtty(vp);
  82:     if (u.u_error)
  83:         return;
  84:     up = u.u_arg[0];
  85:     suword(up, *vp++);
  86:     suword(++up, *vp++);
  87:     suword(++up, *vp++);
  88: }
  89: 
  90: /*
  91:  * The routine implementing the stty system call.
  92:  * Read in values and call lower level.
  93:  */
  94: stty()
  95: {
  96:     register int *up;
  97: 
  98:     up = u.u_arg[0];
  99:     u.u_arg[0] = fuword(up);
 100:     u.u_arg[1] = fuword(++up);
 101:     u.u_arg[2] = fuword(++up);
 102:     sgtty(0);
 103: }
 104: 
 105: /*
 106:  * Stuff common to stty and gtty.
 107:  * Check legality and switch out to individual
 108:  * device routine.
 109:  * v  is 0 for stty; the parameters are taken from u.u_arg[].
 110:  * c  is non-zero for gtty and is the place in which the device
 111:  * routines place their information.
 112:  */
 113: sgtty(v)
 114: int *v;
 115: {
 116:     register struct file *fp;
 117:     register struct inode *ip;
 118: 
 119:     if ((fp = getf(u.u_ar0[R0])) == NULL)
 120:         return;
 121:     ip = fp->f_inode;
 122:     if ((ip->i_mode&IFMT) != IFCHR) {
 123:         u.u_error = ENOTTY;
 124:         return;
 125:     }
 126:     (*cdevsw[ip->i_addr[0].d_major].d_sgtty)(ip->i_addr[0], v);
 127: }
 128: 
 129: /*
 130:  * Wait for output to drain, then flush input waiting.
 131:  */
 132: wflushtty(atp)
 133: struct tty *atp;
 134: {
 135:     register struct tty *tp;
 136: 
 137:     tp = atp;
 138:     spl5();
 139:     while (tp->t_outq.c_cc) {
 140:         tp->t_state =| ASLEEP;
 141:         sleep(&tp->t_outq, TTOPRI);
 142:     }
 143:     flushtty(tp);
 144:     spl0();
 145: }
 146: 
 147: /*
 148:  * Initialize clist by freeing all character blocks, then count
 149:  * number of character devices. (Once-only routine)
 150:  */
 151: cinit()
 152: {
 153:     register int ccp;
 154:     register struct cblock *cp;
 155:     register struct cdevsw *cdp;
 156: 
 157:     ccp = cfree;
 158:     for (cp=(ccp+07)&~07; cp <= &cfree[NCLIST-1]; cp++) {
 159:         cp->c_next = cfreelist;
 160:         cfreelist = cp;
 161:     }
 162:     ccp = 0;
 163:     for(cdp = cdevsw; cdp->d_open; cdp++)
 164:         ccp++;
 165:     nchrdev = ccp;
 166: }
 167: 
 168: /*
 169:  * flush all TTY queues
 170:  */
 171: flushtty(atp)
 172: struct tty *atp;
 173: {
 174:     register struct tty *tp;
 175:     register int sps;
 176: 
 177:     tp = atp;
 178:     while (getc(&tp->t_canq) >= 0);
 179:     while (getc(&tp->t_outq) >= 0);
 180:     wakeup(&tp->t_rawq);
 181:     wakeup(&tp->t_outq);
 182:     sps = PS->integ;
 183:     spl5();
 184:     while (getc(&tp->t_rawq) >= 0);
 185:     tp->t_delct = 0;
 186:     PS->integ = sps;
 187: }
 188: 
 189: /*
 190:  * transfer raw input list to canonical list,
 191:  * doing erase-kill processing and handling escapes.
 192:  * It waits until a full line has been typed in cooked mode,
 193:  * or until any character has been typed in raw mode.
 194:  */
 195: canon(atp)
 196: struct tty *atp;
 197: {
 198:     register char *bp;
 199:     char *bp1;
 200:     register struct tty *tp;
 201:     register int c;
 202: 
 203:     tp = atp;
 204:     spl5();
 205:     while (tp->t_delct==0) {
 206:         if ((tp->t_state&CARR_ON)==0)
 207:             return(0);
 208:         sleep(&tp->t_rawq, TTIPRI);
 209:     }
 210:     spl0();
 211: loop:
 212:     bp = &canonb[2];
 213:     while ((c=getc(&tp->t_rawq)) >= 0) {
 214:         if (c==0377) {
 215:             tp->t_delct--;
 216:             break;
 217:         }
 218:         if ((tp->t_flags&RAW)==0) {
 219:             if (bp[-1]!='\\') {
 220:                 if (c==tp->t_erase) {
 221:                     if (bp > &canonb[2])
 222:                         bp--;
 223:                     continue;
 224:                 }
 225:                 if (c==tp->t_kill)
 226:                     goto loop;
 227:                 if (c==CEOT)
 228:                     continue;
 229:             } else
 230:             if (maptab[c] && (maptab[c]==c || (tp->t_flags&LCASE))) {
 231:                 if (bp[-2] != '\\')
 232:                     c = maptab[c];
 233:                 bp--;
 234:             }
 235:         }
 236:         *bp++ = c;
 237:         if (bp>=canonb+CANBSIZ)
 238:             break;
 239:     }
 240:     bp1 = bp;
 241:     bp = &canonb[2];
 242:     c = &tp->t_canq;
 243:     while (bp<bp1)
 244:         putc(*bp++, c);
 245:     return(1);
 246: }
 247: 
 248: /*
 249:  * Place a character on raw TTY input queue, putting in delimiters
 250:  * and waking up top half as needed.
 251:  * Also echo if required.
 252:  * The arguments are the character and the appropriate
 253:  * tty structure.
 254:  */
 255: ttyinput(ac, atp)
 256: struct tty *atp;
 257: {
 258:     register int t_flags, c;
 259:     register struct tty *tp;
 260: 
 261:     tp = atp;
 262:     c = ac;
 263:     t_flags = tp->t_flags;
 264:     if ((c =& 0177) == '\r' && t_flags&CRMOD)
 265:         c = '\n';
 266:     if ((t_flags&RAW)==0 && (c==CQUIT || c==CINTR)) {
 267:         signal(tp, c==CINTR? SIGINT:SIGQIT);
 268:         flushtty(tp);
 269:         return;
 270:     }
 271:     if (tp->t_rawq.c_cc>=TTYHOG) {
 272:         flushtty(tp);
 273:         return;
 274:     }
 275:     if (t_flags&LCASE && c>='A' && c<='Z')
 276:         c =+ 'a'-'A';
 277:     putc(c, &tp->t_rawq);
 278:     if (t_flags&RAW || c=='\n' || c==004) {
 279:         wakeup(&tp->t_rawq);
 280:         if (putc(0377, &tp->t_rawq)==0)
 281:             tp->t_delct++;
 282:     }
 283:     if (t_flags&ECHO) {
 284:         ttyoutput(c, tp);
 285:         ttstart(tp);
 286:     }
 287: }
 288: 
 289: /*
 290:  * put character on TTY output queue, adding delays,
 291:  * expanding tabs, and handling the CR/NL bit.
 292:  * It is called both from the top half for output, and from
 293:  * interrupt level for echoing.
 294:  * The arguments are the character and the tty structure.
 295:  */
 296: ttyoutput(ac, tp)
 297: struct tty *tp;
 298: {
 299:     register int c;
 300:     register struct tty *rtp;
 301:     register char *colp;
 302:     int ctype;
 303: 
 304:     rtp = tp;
 305:     c = ac&0177;
 306:     /*
 307: 	 * Ignore EOT in normal mode to avoid hanging up
 308: 	 * certain terminals.
 309: 	 */
 310:     if (c==004 && (rtp->t_flags&RAW)==0)
 311:         return;
 312:     /*
 313: 	 * Turn tabs to spaces as required
 314: 	 */
 315:     if (c=='\t' && rtp->t_flags&XTABS) {
 316:         do
 317:             ttyoutput(' ', rtp);
 318:         while (rtp->t_col&07);
 319:         return;
 320:     }
 321:     /*
 322: 	 * for upper-case-only terminals,
 323: 	 * generate escapes.
 324: 	 */
 325:     if (rtp->t_flags&LCASE) {
 326:         colp = "({)}!|^~'`";
 327:         while(*colp++)
 328:             if(c == *colp++) {
 329:                 ttyoutput('\\', rtp);
 330:                 c = colp[-2];
 331:                 break;
 332:             }
 333:         if ('a'<=c && c<='z')
 334:             c =+ 'A' - 'a';
 335:     }
 336:     /*
 337: 	 * turn <nl> to <cr><lf> if desired.
 338: 	 */
 339:     if (c=='\n' && rtp->t_flags&CRMOD)
 340:         ttyoutput('\r', rtp);
 341:     if (putc(c, &rtp->t_outq))
 342:         return;
 343:     /*
 344: 	 * Calculate delays.
 345: 	 * The numbers here represent clock ticks
 346: 	 * and are not necessarily optimal for all terminals.
 347: 	 * The delays are indicated by characters above 0200,
 348: 	 * thus (unfortunately) restricting the transmission
 349: 	 * path to 7 bits.
 350: 	 */
 351:     colp = &rtp->t_col;
 352:     ctype = partab[c];
 353:     c = 0;
 354:     switch (ctype&077) {
 355: 
 356:     /* ordinary */
 357:     case 0:
 358:         (*colp)++;
 359: 
 360:     /* non-printing */
 361:     case 1:
 362:         break;
 363: 
 364:     /* backspace */
 365:     case 2:
 366:         if (*colp)
 367:             (*colp)--;
 368:         break;
 369: 
 370:     /* newline */
 371:     case 3:
 372:         ctype = (rtp->t_flags >> 8) & 03;
 373:         if(ctype == 1) { /* tty 37 */
 374:             if (*colp)
 375:                 c = max((*colp>>4) + 3, 6);
 376:         } else
 377:         if(ctype == 2) { /* vt05 */
 378:             c = 6;
 379:         }
 380:         *colp = 0;
 381:         break;
 382: 
 383:     /* tab */
 384:     case 4:
 385:         ctype = (rtp->t_flags >> 10) & 03;
 386:         if(ctype == 1) { /* tty 37 */
 387:             c = 1 - (*colp | ~07);
 388:             if(c < 5)
 389:                 c = 0;
 390:         }
 391:         *colp =| 07;
 392:         (*colp)++;
 393:         break;
 394: 
 395:     /* vertical motion */
 396:     case 5:
 397:         if(rtp->t_flags & VTDELAY) /* tty 37 */
 398:             c = 0177;
 399:         break;
 400: 
 401:     /* carriage return */
 402:     case 6:
 403:         ctype = (rtp->t_flags >> 12) & 03;
 404:         if(ctype == 1) { /* tn 300 */
 405:             c = 5;
 406:         } else
 407:         if(ctype == 2) { /* ti 700 */
 408:             c = 10;
 409:         }
 410:         *colp = 0;
 411:     }
 412:     if(c)
 413:         putc(c|0200, &rtp->t_outq);
 414: }
 415: 
 416: /*
 417:  * Restart typewriter output following a delay
 418:  * timeout.
 419:  * The name of the routine is passed to the timeout
 420:  * subroutine and it is called during a clock interrupt.
 421:  */
 422: ttrstrt(atp)
 423: {
 424:     register struct tty *tp;
 425: 
 426:     tp = atp;
 427:     tp->t_state =& ~TIMEOUT;
 428:     ttstart(tp);
 429: }
 430: 
 431: /*
 432:  * Start output on the typewriter. It is used from the top half
 433:  * after some characters have been put on the output queue,
 434:  * from the interrupt routine to transmit the next
 435:  * character, and after a timeout has finished.
 436:  * If the SSTART bit is off for the tty the work is done here,
 437:  * using the protocol of the single-line interfaces (KL, DL, DC);
 438:  * otherwise the address word of the tty structure is
 439:  * taken to be the name of the device-dependent startup routine.
 440:  */
 441: ttstart(atp)
 442: struct tty *atp;
 443: {
 444:     register int *addr, c;
 445:     register struct tty *tp;
 446:     struct { int (*func)(); };
 447: 
 448:     tp = atp;
 449:     addr = tp->t_addr;
 450:     if (tp->t_state&SSTART) {
 451:         (*addr.func)(tp);
 452:         return;
 453:     }
 454:     if ((addr->tttcsr&DONE)==0 || tp->t_state&TIMEOUT)
 455:         return;
 456:     if ((c=getc(&tp->t_outq)) >= 0) {
 457:         if (c<=0177)
 458:             addr->tttbuf = c | (partab[c]&0200);
 459:         else {
 460:             timeout(ttrstrt, tp, c&0177);
 461:             tp->t_state =| TIMEOUT;
 462:         }
 463:     }
 464: }
 465: 
 466: /*
 467:  * Called from device's read routine after it has
 468:  * calculated the tty-structure given as argument.
 469:  * The pc is backed up for the duration of this call.
 470:  * In case of a caught interrupt, an RTI will re-execute.
 471:  */
 472: ttread(atp)
 473: struct tty *atp;
 474: {
 475:     register struct tty *tp;
 476: 
 477:     tp = atp;
 478:     if ((tp->t_state&CARR_ON)==0)
 479:         return;
 480:     if (tp->t_canq.c_cc || canon(tp))
 481:         while (tp->t_canq.c_cc && passc(getc(&tp->t_canq))>=0);
 482: }
 483: 
 484: /*
 485:  * Called from the device's write routine after it has
 486:  * calculated the tty-structure given as argument.
 487:  */
 488: ttwrite(atp)
 489: struct tty *atp;
 490: {
 491:     register struct tty *tp;
 492:     register int c;
 493: 
 494:     tp = atp;
 495:     if ((tp->t_state&CARR_ON)==0)
 496:         return;
 497:     while ((c=cpass())>=0) {
 498:         spl5();
 499:         while (tp->t_outq.c_cc > TTHIWAT) {
 500:             ttstart(tp);
 501:             tp->t_state =| ASLEEP;
 502:             sleep(&tp->t_outq, TTOPRI);
 503:         }
 504:         spl0();
 505:         ttyoutput(c, tp);
 506:     }
 507:     ttstart(tp);
 508: }
 509: 
 510: /*
 511:  * Common code for gtty and stty functions on typewriters.
 512:  * If v is non-zero then gtty is being done and information is
 513:  * passed back therein;
 514:  * if it is zero stty is being done and the input information is in the
 515:  * u_arg array.
 516:  */
 517: ttystty(atp, av)
 518: int *atp, *av;
 519: {
 520:     register  *tp, *v;
 521: 
 522:     tp = atp;
 523:     if(v = av) {
 524:         *v++ = tp->t_speeds;
 525:         v->lobyte = tp->t_erase;
 526:         v->hibyte = tp->t_kill;
 527:         v[1] = tp->t_flags;
 528:         return(1);
 529:     }
 530:     wflushtty(tp);
 531:     v = u.u_arg;
 532:     tp->t_speeds = *v++;
 533:     tp->t_erase = v->lobyte;
 534:     tp->t_kill = v->hibyte;
 535:     tp->t_flags = v[1];
 536:     return(0);
 537: }

Defined functions

canon defined in line 195; used 1 times
cinit defined in line 151; used 1 times
flushtty defined in line 171; used 5 times
gtty defined in line 75; never used
sgtty defined in line 113; used 2 times
stty defined in line 94; never used
ttread defined in line 472; used 3 times
ttrstrt defined in line 422; used 4 times
ttstart defined in line 441; used 6 times
ttwrite defined in line 488; used 3 times
ttyinput defined in line 255; used 3 times
ttyoutput defined in line 296; used 5 times
ttystty defined in line 517; used 3 times
wflushtty defined in line 132; used 4 times

Defined variables

cfree defined in line 54; used 2 times
cfreelist defined in line 56; used 9 times
maptab defined in line 24; used 3 times

Defined struct's

cblock defined in line 48; used 8 times
Last modified: 1975-07-17
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1535
Valid CSS Valid XHTML 1.0 Strict