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