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