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