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