1*39Sbill /* tty.c 3.1 10/14/12 */ 2*39Sbill 3*39Sbill /* 4*39Sbill * general TTY subroutines 5*39Sbill */ 6*39Sbill #include "../h/param.h" 7*39Sbill #include "../h/systm.h" 8*39Sbill #include "../h/dir.h" 9*39Sbill #include "../h/user.h" 10*39Sbill #include "../h/tty.h" 11*39Sbill #include "../h/proc.h" 12*39Sbill #include "../h/mx.h" 13*39Sbill #include "../h/inode.h" 14*39Sbill #include "../h/file.h" 15*39Sbill #include "../h/reg.h" 16*39Sbill #include "../h/conf.h" 17*39Sbill #include "../h/buf.h" 18*39Sbill 19*39Sbill char partab[]; 20*39Sbill 21*39Sbill 22*39Sbill /* 23*39Sbill * Input mapping table-- if an entry is non-zero, when the 24*39Sbill * corresponding character is typed preceded by "\" the escape 25*39Sbill * sequence is replaced by the table value. Mostly used for 26*39Sbill * upper-case only terminals. 27*39Sbill */ 28*39Sbill 29*39Sbill char maptab[] ={ 30*39Sbill 000,000,000,000,000,000,000,000, 31*39Sbill 000,000,000,000,000,000,000,000, 32*39Sbill 000,000,000,000,000,000,000,000, 33*39Sbill 000,000,000,000,000,000,000,000, 34*39Sbill 000,'|',000,000,000,000,000,'`', 35*39Sbill '{','}',000,000,000,000,000,000, 36*39Sbill 000,000,000,000,000,000,000,000, 37*39Sbill 000,000,000,000,000,000,000,000, 38*39Sbill 000,000,000,000,000,000,000,000, 39*39Sbill 000,000,000,000,000,000,000,000, 40*39Sbill 000,000,000,000,000,000,000,000, 41*39Sbill 000,000,000,000,000,000,'~',000, 42*39Sbill 000,'A','B','C','D','E','F','G', 43*39Sbill 'H','I','J','K','L','M','N','O', 44*39Sbill 'P','Q','R','S','T','U','V','W', 45*39Sbill 'X','Y','Z',000,000,000,000,000, 46*39Sbill }; 47*39Sbill 48*39Sbill 49*39Sbill /* 50*39Sbill * shorthand 51*39Sbill */ 52*39Sbill #define q1 tp->t_rawq 53*39Sbill #define q2 tp->t_canq 54*39Sbill #define q3 tp->t_outq 55*39Sbill #define q4 tp->t_un.t_ctlq 56*39Sbill 57*39Sbill #define OBUFSIZ 100 58*39Sbill 59*39Sbill /* 60*39Sbill * routine called on first teletype open. 61*39Sbill * establishes a process group for distribution 62*39Sbill * of quits and interrupts from the tty. 63*39Sbill */ 64*39Sbill ttyopen(dev, tp) 65*39Sbill dev_t dev; 66*39Sbill register struct tty *tp; 67*39Sbill { 68*39Sbill register struct proc *pp; 69*39Sbill 70*39Sbill pp = u.u_procp; 71*39Sbill tp->t_dev = dev; 72*39Sbill if(pp->p_pgrp == 0) { 73*39Sbill u.u_ttyp = tp; 74*39Sbill u.u_ttyd = dev; 75*39Sbill if (tp->t_pgrp==0) 76*39Sbill tp->t_pgrp = pp->p_pid; 77*39Sbill pp->p_pgrp = tp->t_pgrp; 78*39Sbill } 79*39Sbill tp->t_state &= ~WOPEN; 80*39Sbill tp->t_state |= ISOPEN; 81*39Sbill } 82*39Sbill 83*39Sbill 84*39Sbill /* 85*39Sbill * set default control characters. 86*39Sbill */ 87*39Sbill ttychars(tp) 88*39Sbill register struct tty *tp; 89*39Sbill { 90*39Sbill tun.t_intrc = CINTR; 91*39Sbill tun.t_quitc = CQUIT; 92*39Sbill tun.t_startc = CSTART; 93*39Sbill tun.t_stopc = CSTOP; 94*39Sbill tun.t_eofc = CEOT; 95*39Sbill tun.t_brkc = CBRK; 96*39Sbill tp->t_erase = CERASE; 97*39Sbill tp->t_kill = CKILL; 98*39Sbill } 99*39Sbill 100*39Sbill /* 101*39Sbill * clean tp on last close 102*39Sbill */ 103*39Sbill ttyclose(tp) 104*39Sbill register struct tty *tp; 105*39Sbill { 106*39Sbill 107*39Sbill tp->t_pgrp = 0; 108*39Sbill wflushtty(tp); 109*39Sbill tp->t_state = 0; 110*39Sbill } 111*39Sbill 112*39Sbill /* 113*39Sbill * stty/gtty writearound 114*39Sbill */ 115*39Sbill stty() 116*39Sbill { 117*39Sbill u.u_arg[2] = u.u_arg[1]; 118*39Sbill u.u_arg[1] = TIOCSETP; 119*39Sbill ioctl(); 120*39Sbill } 121*39Sbill 122*39Sbill gtty() 123*39Sbill { 124*39Sbill u.u_arg[2] = u.u_arg[1]; 125*39Sbill u.u_arg[1] = TIOCGETP; 126*39Sbill ioctl(); 127*39Sbill } 128*39Sbill 129*39Sbill /* 130*39Sbill * ioctl system call 131*39Sbill * Check legality, execute common code, and switch out to individual 132*39Sbill * device routine. 133*39Sbill */ 134*39Sbill ioctl() 135*39Sbill { 136*39Sbill register struct file *fp; 137*39Sbill register struct inode *ip; 138*39Sbill register struct a { 139*39Sbill int fdes; 140*39Sbill int cmd; 141*39Sbill caddr_t cmarg; 142*39Sbill } *uap; 143*39Sbill register dev_t dev; 144*39Sbill register fmt; 145*39Sbill 146*39Sbill uap = (struct a *)u.u_ap; 147*39Sbill if ((fp = getf(uap->fdes)) == NULL) 148*39Sbill return; 149*39Sbill if (uap->cmd==FIOCLEX) { 150*39Sbill u.u_pofile[uap->fdes] |= EXCLOSE; 151*39Sbill return; 152*39Sbill } 153*39Sbill if (uap->cmd==FIONCLEX) { 154*39Sbill u.u_pofile[uap->fdes] &= ~EXCLOSE; 155*39Sbill return; 156*39Sbill } 157*39Sbill ip = fp->f_inode; 158*39Sbill fmt = ip->i_mode & IFMT; 159*39Sbill if (fmt != IFCHR && fmt != IFMPC) { 160*39Sbill u.u_error = ENOTTY; 161*39Sbill return; 162*39Sbill } 163*39Sbill dev = ip->i_un.i_rdev; 164*39Sbill u.u_r.r_val1 = 0; 165*39Sbill (*cdevsw[major(dev)].d_ioctl)(dev, uap->cmd, uap->cmarg, fp->f_flag); 166*39Sbill } 167*39Sbill 168*39Sbill /* 169*39Sbill * Common code for several tty ioctl commands 170*39Sbill */ 171*39Sbill ttioccomm(com, tp, addr, dev) 172*39Sbill register struct tty *tp; 173*39Sbill caddr_t addr; 174*39Sbill { 175*39Sbill unsigned t; 176*39Sbill struct ttiocb iocb; 177*39Sbill extern int nldisp; 178*39Sbill 179*39Sbill switch(com) { 180*39Sbill 181*39Sbill /* 182*39Sbill * get discipline number 183*39Sbill */ 184*39Sbill case TIOCGETD: 185*39Sbill t = tp->t_line; 186*39Sbill if (copyout((caddr_t)&t, addr, sizeof(t))) 187*39Sbill u.u_error = EFAULT; 188*39Sbill break; 189*39Sbill 190*39Sbill /* 191*39Sbill * set line discipline 192*39Sbill */ 193*39Sbill case TIOCSETD: 194*39Sbill if (copyin(addr, (caddr_t)&t, sizeof(t))) { 195*39Sbill u.u_error = EFAULT; 196*39Sbill break; 197*39Sbill } 198*39Sbill if (t >= nldisp) { 199*39Sbill u.u_error = ENXIO; 200*39Sbill break; 201*39Sbill } 202*39Sbill if (tp->t_line) 203*39Sbill (*linesw[tp->t_line].l_close)(tp); 204*39Sbill if (t) 205*39Sbill (*linesw[t].l_open)(dev, tp, addr); 206*39Sbill if (u.u_error==0) 207*39Sbill tp->t_line = t; 208*39Sbill break; 209*39Sbill 210*39Sbill /* 211*39Sbill * prevent more opens on channel 212*39Sbill */ 213*39Sbill case TIOCEXCL: 214*39Sbill tp->t_state |= XCLUDE; 215*39Sbill break; 216*39Sbill 217*39Sbill case TIOCNXCL: 218*39Sbill tp->t_state &= ~XCLUDE; 219*39Sbill break; 220*39Sbill 221*39Sbill /* 222*39Sbill * Set new parameters 223*39Sbill */ 224*39Sbill case TIOCSETP: 225*39Sbill wflushtty(tp); 226*39Sbill case TIOCSETN: 227*39Sbill if (copyin(addr, (caddr_t)&iocb, sizeof(iocb))) { 228*39Sbill u.u_error = EFAULT; 229*39Sbill return(1); 230*39Sbill } 231*39Sbill VOID spl5(); 232*39Sbill while (canon(tp)>=0) 233*39Sbill ; 234*39Sbill if ((tp->t_state&SPEEDS)==0) { 235*39Sbill tp->t_ispeed = iocb.ioc_ispeed; 236*39Sbill tp->t_ospeed = iocb.ioc_ospeed; 237*39Sbill } 238*39Sbill tp->t_erase = iocb.ioc_erase; 239*39Sbill tp->t_kill = iocb.ioc_kill; 240*39Sbill tp->t_flags = iocb.ioc_flags; 241*39Sbill VOID spl0(); 242*39Sbill break; 243*39Sbill 244*39Sbill /* 245*39Sbill * send current parameters to user 246*39Sbill */ 247*39Sbill case TIOCGETP: 248*39Sbill iocb.ioc_ispeed = tp->t_ispeed; 249*39Sbill iocb.ioc_ospeed = tp->t_ospeed; 250*39Sbill iocb.ioc_erase = tp->t_erase; 251*39Sbill iocb.ioc_kill = tp->t_kill; 252*39Sbill iocb.ioc_flags = tp->t_flags; 253*39Sbill if (copyout((caddr_t)&iocb, addr, sizeof(iocb))) 254*39Sbill u.u_error = EFAULT; 255*39Sbill break; 256*39Sbill 257*39Sbill /* 258*39Sbill * Hang up line on last close 259*39Sbill */ 260*39Sbill 261*39Sbill case TIOCHPCL: 262*39Sbill tp->t_state |= HUPCLS; 263*39Sbill break; 264*39Sbill 265*39Sbill case TIOCFLUSH: 266*39Sbill flushtty(tp); 267*39Sbill break; 268*39Sbill 269*39Sbill /* 270*39Sbill * ioctl entries to line discipline 271*39Sbill */ 272*39Sbill case DIOCSETP: 273*39Sbill case DIOCGETP: 274*39Sbill (*linesw[tp->t_line].l_ioctl)(com, tp, addr); 275*39Sbill break; 276*39Sbill 277*39Sbill /* 278*39Sbill * set and fetch special characters 279*39Sbill */ 280*39Sbill case TIOCSETC: 281*39Sbill if (copyin(addr, (caddr_t)&tun, sizeof(struct tc))) 282*39Sbill u.u_error = EFAULT; 283*39Sbill break; 284*39Sbill 285*39Sbill case TIOCGETC: 286*39Sbill if (copyout((caddr_t)&tun, addr, sizeof(struct tc))) 287*39Sbill u.u_error = EFAULT; 288*39Sbill break; 289*39Sbill 290*39Sbill default: 291*39Sbill return(0); 292*39Sbill } 293*39Sbill return(1); 294*39Sbill } 295*39Sbill 296*39Sbill /* 297*39Sbill * Wait for output to drain, then flush input waiting. 298*39Sbill */ 299*39Sbill wflushtty(tp) 300*39Sbill register struct tty *tp; 301*39Sbill { 302*39Sbill 303*39Sbill VOID spl5(); 304*39Sbill while (tp->t_outq.c_cc && tp->t_state&CARR_ON) { 305*39Sbill (*tp->t_oproc)(tp); 306*39Sbill tp->t_state |= ASLEEP; 307*39Sbill sleep((caddr_t)&tp->t_outq, TTOPRI); 308*39Sbill } 309*39Sbill flushtty(tp); 310*39Sbill VOID spl0(); 311*39Sbill } 312*39Sbill 313*39Sbill /* 314*39Sbill * flush all TTY queues 315*39Sbill */ 316*39Sbill flushtty(tp) 317*39Sbill register struct tty *tp; 318*39Sbill { 319*39Sbill register s; 320*39Sbill 321*39Sbill while (getc(&tp->t_canq) >= 0) 322*39Sbill ; 323*39Sbill wakeup((caddr_t)&tp->t_rawq); 324*39Sbill wakeup((caddr_t)&tp->t_outq); 325*39Sbill s = spl6(); 326*39Sbill tp->t_state &= ~TTSTOP; 327*39Sbill (*cdevsw[major(tp->t_dev)].d_stop)(tp); 328*39Sbill while (getc(&tp->t_outq) >= 0) 329*39Sbill ; 330*39Sbill while (getc(&tp->t_rawq) >= 0) 331*39Sbill ; 332*39Sbill tp->t_delct = 0; 333*39Sbill splx(s); 334*39Sbill } 335*39Sbill 336*39Sbill 337*39Sbill 338*39Sbill /* 339*39Sbill * transfer raw input list to canonical list, 340*39Sbill * doing erase-kill processing and handling escapes. 341*39Sbill * It waits until a full line has been typed in cooked mode, 342*39Sbill * or until any character has been typed in raw mode. 343*39Sbill */ 344*39Sbill canon(tp) 345*39Sbill register struct tty *tp; 346*39Sbill { 347*39Sbill register char *bp; 348*39Sbill char *bp1; 349*39Sbill register int c; 350*39Sbill int mc; 351*39Sbill int s; 352*39Sbill 353*39Sbill if ((tp->t_flags&(RAW|CBREAK))==0 && tp->t_delct==0 354*39Sbill || (tp->t_flags&(RAW|CBREAK))!=0 && tp->t_rawq.c_cc==0) { 355*39Sbill return(-1); 356*39Sbill } 357*39Sbill s = spl0(); 358*39Sbill loop: 359*39Sbill bp = &canonb[2]; 360*39Sbill while ((c=getc(&tp->t_rawq)) >= 0) { 361*39Sbill if ((tp->t_flags&(RAW|CBREAK))==0) { 362*39Sbill if (c==0377) { 363*39Sbill tp->t_delct--; 364*39Sbill break; 365*39Sbill } 366*39Sbill if (bp[-1]!='\\') { 367*39Sbill if (c==tp->t_erase) { 368*39Sbill if (bp > &canonb[2]) 369*39Sbill bp--; 370*39Sbill continue; 371*39Sbill } 372*39Sbill if (c==tp->t_kill) 373*39Sbill goto loop; 374*39Sbill if (c==tun.t_eofc) 375*39Sbill continue; 376*39Sbill } else { 377*39Sbill mc = maptab[c]; 378*39Sbill if (c==tp->t_erase || c==tp->t_kill) 379*39Sbill mc = c; 380*39Sbill if (mc && (mc==c || (tp->t_flags&LCASE))) { 381*39Sbill if (bp[-2] != '\\') 382*39Sbill c = mc; 383*39Sbill bp--; 384*39Sbill } 385*39Sbill } 386*39Sbill } 387*39Sbill *bp++ = c; 388*39Sbill if (bp>=canonb+CANBSIZ) 389*39Sbill break; 390*39Sbill } 391*39Sbill bp1 = &canonb[2]; 392*39Sbill VOID b_to_q(bp1, bp-bp1, &tp->t_canq); 393*39Sbill 394*39Sbill if (tp->t_state&TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) { 395*39Sbill if (putc(tun.t_startc, &tp->t_outq)==0) { 396*39Sbill tp->t_state &= ~TBLOCK; 397*39Sbill ttstart(tp); 398*39Sbill } 399*39Sbill tp->t_char = 0; 400*39Sbill } 401*39Sbill 402*39Sbill splx(s); 403*39Sbill return(0); 404*39Sbill } 405*39Sbill 406*39Sbill 407*39Sbill /* 408*39Sbill * block transfer input handler. 409*39Sbill */ 410*39Sbill ttyrend(tp, pb, pe) 411*39Sbill register struct tty *tp; 412*39Sbill register char *pb, *pe; 413*39Sbill { 414*39Sbill int tandem; 415*39Sbill 416*39Sbill tandem = tp->t_flags&TANDEM; 417*39Sbill if (tp->t_flags&RAW) { 418*39Sbill VOID b_to_q(pb, pe-pb, &tp->t_rawq); 419*39Sbill if (tp->t_chan) 420*39Sbill VOID sdata(tp->t_chan); else 421*39Sbill wakeup((caddr_t)&tp->t_rawq); 422*39Sbill } else { 423*39Sbill tp->t_flags &= ~TANDEM; 424*39Sbill while (pb < pe) 425*39Sbill ttyinput(*pb++, tp); 426*39Sbill tp->t_flags |= tandem; 427*39Sbill } 428*39Sbill if (tandem) 429*39Sbill ttyblock(tp); 430*39Sbill } 431*39Sbill 432*39Sbill /* 433*39Sbill * Place a character on raw TTY input queue, putting in delimiters 434*39Sbill * and waking up top half as needed. 435*39Sbill * Also echo if required. 436*39Sbill * The arguments are the character and the appropriate 437*39Sbill * tty structure. 438*39Sbill */ 439*39Sbill ttyinput(c, tp) 440*39Sbill register c; 441*39Sbill register struct tty *tp; 442*39Sbill { 443*39Sbill register int t_flags; 444*39Sbill register struct chan *cp; 445*39Sbill 446*39Sbill tk_nin += 1; 447*39Sbill c &= 0377; 448*39Sbill t_flags = tp->t_flags; 449*39Sbill if (t_flags&TANDEM) 450*39Sbill ttyblock(tp); 451*39Sbill if ((t_flags&RAW)==0) { 452*39Sbill c &= 0177; 453*39Sbill if (tp->t_state&TTSTOP) { 454*39Sbill if (c==tun.t_startc) { 455*39Sbill tp->t_state &= ~TTSTOP; 456*39Sbill ttstart(tp); 457*39Sbill return; 458*39Sbill } 459*39Sbill if (c==tun.t_stopc) 460*39Sbill return; 461*39Sbill tp->t_state &= ~TTSTOP; 462*39Sbill ttstart(tp); 463*39Sbill } else { 464*39Sbill if (c==tun.t_stopc) { 465*39Sbill tp->t_state |= TTSTOP; 466*39Sbill (*cdevsw[major(tp->t_dev)].d_stop)(tp); 467*39Sbill return; 468*39Sbill } 469*39Sbill if (c==tun.t_startc) 470*39Sbill return; 471*39Sbill } 472*39Sbill if (c==tun.t_quitc || c==tun.t_intrc) { 473*39Sbill flushtty(tp); 474*39Sbill c = (c==tun.t_intrc) ? SIGINT:SIGQUIT; 475*39Sbill if (tp->t_chan) 476*39Sbill scontrol(tp->t_chan, M_SIG, c); 477*39Sbill else 478*39Sbill signal(tp->t_pgrp, c); 479*39Sbill return; 480*39Sbill } 481*39Sbill if (c=='\r' && t_flags&CRMOD) 482*39Sbill c = '\n'; 483*39Sbill } 484*39Sbill if (tp->t_rawq.c_cc>TTYHOG) { 485*39Sbill flushtty(tp); 486*39Sbill return; 487*39Sbill } 488*39Sbill if (t_flags&LCASE && c>='A' && c<='Z') 489*39Sbill c += 'a'-'A'; 490*39Sbill VOID putc(c, &tp->t_rawq); 491*39Sbill if (t_flags&(RAW|CBREAK)||(c=='\n'||c==tun.t_eofc||c==tun.t_brkc)) { 492*39Sbill if ((t_flags&(RAW|CBREAK))==0 && putc(0377, &tp->t_rawq)==0) 493*39Sbill tp->t_delct++; 494*39Sbill if ((cp=tp->t_chan)!=NULL) 495*39Sbill VOID sdata(cp); else 496*39Sbill wakeup((caddr_t)&tp->t_rawq); 497*39Sbill } 498*39Sbill if (t_flags&ECHO) { 499*39Sbill ttyoutput(c, tp); 500*39Sbill if (c==tp->t_kill && (t_flags&(RAW|CBREAK))==0) 501*39Sbill ttyoutput('\n', tp); 502*39Sbill ttstart(tp); 503*39Sbill } 504*39Sbill } 505*39Sbill 506*39Sbill 507*39Sbill /* 508*39Sbill * Send stop character on input overflow. 509*39Sbill */ 510*39Sbill ttyblock(tp) 511*39Sbill register struct tty *tp; 512*39Sbill { 513*39Sbill register x; 514*39Sbill x = q1.c_cc + q2.c_cc; 515*39Sbill if (q1.c_cc > TTYHOG) { 516*39Sbill flushtty(tp); 517*39Sbill tp->t_state &= ~TBLOCK; 518*39Sbill } 519*39Sbill if (x >= TTYHOG/2) { 520*39Sbill if (putc(tun.t_stopc, &tp->t_outq)==0) { 521*39Sbill tp->t_state |= TBLOCK; 522*39Sbill tp->t_char++; 523*39Sbill ttstart(tp); 524*39Sbill } 525*39Sbill } 526*39Sbill } 527*39Sbill 528*39Sbill /* 529*39Sbill * put character on TTY output queue, adding delays, 530*39Sbill * expanding tabs, and handling the CR/NL bit. 531*39Sbill * It is called both from the top half for output, and from 532*39Sbill * interrupt level for echoing. 533*39Sbill * The arguments are the character and the tty structure. 534*39Sbill */ 535*39Sbill ttyoutput(c, tp) 536*39Sbill register c; 537*39Sbill register struct tty *tp; 538*39Sbill { 539*39Sbill register char *colp; 540*39Sbill register ctype; 541*39Sbill 542*39Sbill tk_nout++; 543*39Sbill /* 544*39Sbill * Ignore EOT in normal mode to avoid hanging up 545*39Sbill * certain terminals. 546*39Sbill * In raw mode dump the char unchanged. 547*39Sbill */ 548*39Sbill 549*39Sbill if ((tp->t_flags&RAW)==0) { 550*39Sbill c &= 0177; 551*39Sbill if ((tp->t_flags&CBREAK)==0 && c==CEOT) 552*39Sbill return; 553*39Sbill } else { 554*39Sbill VOID putc(c, &tp->t_outq); 555*39Sbill return; 556*39Sbill } 557*39Sbill 558*39Sbill /* 559*39Sbill * Turn tabs to spaces as required 560*39Sbill */ 561*39Sbill if (c=='\t' && (tp->t_flags&TBDELAY)==XTABS) { 562*39Sbill c = 8; 563*39Sbill do 564*39Sbill ttyoutput(' ', tp); 565*39Sbill while (--c >= 0 && tp->t_col&07); 566*39Sbill return; 567*39Sbill } 568*39Sbill /* 569*39Sbill * for upper-case-only terminals, 570*39Sbill * generate escapes. 571*39Sbill */ 572*39Sbill if (tp->t_flags&LCASE) { 573*39Sbill colp = "({)}!|^~'`"; 574*39Sbill while(*colp++) 575*39Sbill if(c == *colp++) { 576*39Sbill ttyoutput('\\', tp); 577*39Sbill c = colp[-2]; 578*39Sbill break; 579*39Sbill } 580*39Sbill if ('a'<=c && c<='z') 581*39Sbill c += 'A' - 'a'; 582*39Sbill } 583*39Sbill /* 584*39Sbill * turn <nl> to <cr><lf> if desired. 585*39Sbill */ 586*39Sbill if (c=='\n' && tp->t_flags&CRMOD) 587*39Sbill ttyoutput('\r', tp); 588*39Sbill VOID putc(c, &tp->t_outq); 589*39Sbill /* 590*39Sbill * Calculate delays. 591*39Sbill * The numbers here represent clock ticks 592*39Sbill * and are not necessarily optimal for all terminals. 593*39Sbill * The delays are indicated by characters above 0200. 594*39Sbill * In raw mode there are no delays and the 595*39Sbill * transmission path is 8 bits wide. 596*39Sbill */ 597*39Sbill colp = &tp->t_col; 598*39Sbill ctype = partab[c]; 599*39Sbill c = 0; 600*39Sbill switch (ctype&077) { 601*39Sbill 602*39Sbill /* ordinary */ 603*39Sbill case 0: 604*39Sbill (*colp)++; 605*39Sbill 606*39Sbill /* non-printing */ 607*39Sbill case 1: 608*39Sbill break; 609*39Sbill 610*39Sbill /* backspace */ 611*39Sbill case 2: 612*39Sbill if (*colp) 613*39Sbill (*colp)--; 614*39Sbill break; 615*39Sbill 616*39Sbill /* newline */ 617*39Sbill case 3: 618*39Sbill ctype = (tp->t_flags >> 8) & 03; 619*39Sbill if(ctype == 1) { /* tty 37 */ 620*39Sbill if (*colp) 621*39Sbill c = max(((unsigned)*colp>>4) + 3, (unsigned)6); 622*39Sbill } else 623*39Sbill if(ctype == 2) { /* vt05 */ 624*39Sbill c = 6; 625*39Sbill } 626*39Sbill *colp = 0; 627*39Sbill break; 628*39Sbill 629*39Sbill /* tab */ 630*39Sbill case 4: 631*39Sbill ctype = (tp->t_flags >> 10) & 03; 632*39Sbill if(ctype == 1) { /* tty 37 */ 633*39Sbill c = 1 - (*colp | ~07); 634*39Sbill if(c < 5) 635*39Sbill c = 0; 636*39Sbill } 637*39Sbill *colp |= 07; 638*39Sbill (*colp)++; 639*39Sbill break; 640*39Sbill 641*39Sbill /* vertical motion */ 642*39Sbill case 5: 643*39Sbill if(tp->t_flags & VTDELAY) /* tty 37 */ 644*39Sbill c = 0177; 645*39Sbill break; 646*39Sbill 647*39Sbill /* carriage return */ 648*39Sbill case 6: 649*39Sbill ctype = (tp->t_flags >> 12) & 03; 650*39Sbill if(ctype == 1) { /* tn 300 */ 651*39Sbill c = 5; 652*39Sbill } else if(ctype == 2) { /* ti 700 */ 653*39Sbill c = 10; 654*39Sbill } else if(ctype == 3) { /* concept 100 */ 655*39Sbill int i; 656*39Sbill for (i= *colp; i<9; i++) 657*39Sbill VOID putc(0177, &tp->t_outq); 658*39Sbill } 659*39Sbill *colp = 0; 660*39Sbill } 661*39Sbill if(c) 662*39Sbill VOID putc(c|0200, &tp->t_outq); 663*39Sbill } 664*39Sbill 665*39Sbill /* 666*39Sbill * Restart typewriter output following a delay 667*39Sbill * timeout. 668*39Sbill * The name of the routine is passed to the timeout 669*39Sbill * subroutine and it is called during a clock interrupt. 670*39Sbill */ 671*39Sbill ttrstrt(tp) 672*39Sbill register struct tty *tp; 673*39Sbill { 674*39Sbill 675*39Sbill tp->t_state &= ~TIMEOUT; 676*39Sbill ttstart(tp); 677*39Sbill } 678*39Sbill 679*39Sbill /* 680*39Sbill * Start output on the typewriter. It is used from the top half 681*39Sbill * after some characters have been put on the output queue, 682*39Sbill * from the interrupt routine to transmit the next 683*39Sbill * character, and after a timeout has finished. 684*39Sbill */ 685*39Sbill ttstart(tp) 686*39Sbill register struct tty *tp; 687*39Sbill { 688*39Sbill register s; 689*39Sbill 690*39Sbill s = spl5(); 691*39Sbill if((tp->t_state&(TIMEOUT|TTSTOP|BUSY)) == 0) 692*39Sbill (*tp->t_oproc)(tp); 693*39Sbill splx(s); 694*39Sbill } 695*39Sbill 696*39Sbill /* 697*39Sbill * Called from device's read routine after it has 698*39Sbill * calculated the tty-structure given as argument. 699*39Sbill */ 700*39Sbill ttread(tp) 701*39Sbill register struct tty *tp; 702*39Sbill { 703*39Sbill register s; 704*39Sbill 705*39Sbill if ((tp->t_state&CARR_ON)==0) 706*39Sbill return(-1); 707*39Sbill s = spl5(); 708*39Sbill if (tp->t_canq.c_cc==0) 709*39Sbill while (canon(tp)<0) 710*39Sbill if (tp->t_chan==NULL) { 711*39Sbill sleep((caddr_t)&tp->t_rawq, TTIPRI); 712*39Sbill } else { 713*39Sbill splx(s); 714*39Sbill return(0); 715*39Sbill } 716*39Sbill splx(s); 717*39Sbill while (tp->t_canq.c_cc && passc(getc(&tp->t_canq))>=0) 718*39Sbill ; 719*39Sbill return(tp->t_rawq.c_cc+tp->t_canq.c_cc); 720*39Sbill } 721*39Sbill 722*39Sbill /* 723*39Sbill * Called from the device's write routine after it has 724*39Sbill * calculated the tty-structure given as argument. 725*39Sbill */ 726*39Sbill caddr_t 727*39Sbill ttwrite(tp) 728*39Sbill register struct tty *tp; 729*39Sbill { 730*39Sbill /* 731*39Sbill * THE POSITIONING OF CP, CC, AND CE ARE CRITICAL 732*39Sbill * AND MUST NOT BE CHANGED WITHOUT PATCHING 733*39Sbill * THE 'ASM' INLINES BELOW. WATCH OUT. 734*39Sbill */ 735*39Sbill register char *cp; 736*39Sbill register int cc, ce; 737*39Sbill register i; 738*39Sbill char obuf[OBUFSIZ]; 739*39Sbill 740*39Sbill if ((tp->t_state&CARR_ON)==0) 741*39Sbill return(NULL); 742*39Sbill while (u.u_count) { 743*39Sbill cc = MIN(u.u_count, OBUFSIZ); 744*39Sbill cp = obuf; 745*39Sbill iomove(cp, (unsigned)cc, B_WRITE); 746*39Sbill if (u.u_error) 747*39Sbill break; 748*39Sbill VOID spl5(); 749*39Sbill while (tp->t_outq.c_cc > TTHIWAT) { 750*39Sbill ttstart(tp); 751*39Sbill tp->t_state |= ASLEEP; 752*39Sbill if (tp->t_chan) { 753*39Sbill u.u_base -= cc; 754*39Sbill u.u_offset -= cc; 755*39Sbill u.u_count += cc; 756*39Sbill VOID spl0(); 757*39Sbill return((caddr_t)&tp->t_outq); 758*39Sbill } 759*39Sbill sleep((caddr_t)&tp->t_outq, TTOPRI); 760*39Sbill } 761*39Sbill VOID spl0(); 762*39Sbill if (tp->t_flags&LCASE) { 763*39Sbill while (cc--) 764*39Sbill ttyoutput(*cp++,tp); 765*39Sbill continue; 766*39Sbill } 767*39Sbill while (cc) { 768*39Sbill if (tp->t_flags&RAW) 769*39Sbill ce=cc; 770*39Sbill else { 771*39Sbill #ifdef VAX 772*39Sbill asm(" scanc r9,(r10),_partab,$077"); 773*39Sbill asm(" subl3 r0,r9,r8"); 774*39Sbill #else 775*39Sbill ce=0; 776*39Sbill while(((partab[*(cp+ce)]&077)==0)&&(ce<cc)) 777*39Sbill ce++; 778*39Sbill #endif 779*39Sbill if (ce==0) { 780*39Sbill ttyoutput(*cp++,tp); 781*39Sbill cc--; 782*39Sbill continue; 783*39Sbill } 784*39Sbill } 785*39Sbill i=b_to_q(cp,ce,&tp->t_outq); 786*39Sbill ce-=i; 787*39Sbill tk_nout+=ce; 788*39Sbill tp->t_col+=ce; 789*39Sbill cp+=ce; 790*39Sbill cc-=ce; 791*39Sbill if (i) { 792*39Sbill VOID spl5(); 793*39Sbill while (tp->t_outq.c_cc > TTHIWAT) { 794*39Sbill ttstart(tp); 795*39Sbill tp->t_state |= ASLEEP; 796*39Sbill sleep((caddr_t)&tp->t_outq, TTOPRI); 797*39Sbill } 798*39Sbill VOID spl0(); 799*39Sbill } 800*39Sbill } 801*39Sbill } 802*39Sbill ttstart(tp); 803*39Sbill return(NULL); 804*39Sbill } 805