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