1 /* tty.c 3.8 06/07/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 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 case TIOCOUTQ: 418 if (copyout((caddr_t)&tp->t_outq.c_cc, addr, sizeof(tp->t_outq.c_cc))) 419 u.u_error = EFAULT; 420 break; 421 422 /* end of locals */ 423 default: 424 return(0); 425 } 426 return(1); 427 } 428 429 /* 430 * Wait for output to drain, then flush input waiting. 431 */ 432 wflushtty(tp) 433 register struct tty *tp; 434 { 435 436 (void) spl5(); 437 while (tp->t_outq.c_cc && tp->t_state&CARR_ON) { 438 (*tp->t_oproc)(tp); 439 tp->t_state |= ASLEEP; 440 sleep((caddr_t)&tp->t_outq, TTOPRI); 441 } 442 flushtty(tp); 443 (void) spl0(); 444 } 445 446 /* 447 * flush all TTY queues 448 */ 449 flushtty(tp) 450 register struct tty *tp; 451 { 452 register s; 453 454 s = spl6(); 455 while (getc(&tp->t_canq) >= 0) 456 ; 457 wakeup((caddr_t)&tp->t_rawq); 458 wakeup((caddr_t)&tp->t_outq); 459 tp->t_state &= ~TTSTOP; 460 (*cdevsw[major(tp->t_dev)].d_stop)(tp); 461 while (getc(&tp->t_outq) >= 0) 462 ; 463 while (getc(&tp->t_rawq) >= 0) 464 ; 465 tp->t_delct = 0; 466 tp->t_rocount = 0; /* local */ 467 tp->t_lstate = 0; 468 splx(s); 469 } 470 471 472 473 /* 474 * transfer raw input list to canonical list, 475 * doing erase-kill processing and handling escapes. 476 * It waits until a full line has been typed in cooked mode, 477 * or until any character has been typed in raw mode. 478 */ 479 canon(tp) 480 register struct tty *tp; 481 { 482 register char *bp; 483 char *bp1; 484 register int c; 485 int mc; 486 int s; 487 488 if ((tp->t_flags&(RAW|CBREAK))==0 && tp->t_delct==0 489 || (tp->t_flags&(RAW|CBREAK))!=0 && tp->t_rawq.c_cc==0) { 490 return(-1); 491 } 492 s = spl0(); 493 loop: 494 bp = &canonb[2]; 495 while ((c=getc(&tp->t_rawq)) >= 0) { 496 if ((tp->t_flags&(RAW|CBREAK))==0) { 497 if (c==0377) { 498 tp->t_delct--; 499 break; 500 } 501 if (bp[-1]!='\\') { 502 if (c==tp->t_erase) { 503 if (bp > &canonb[2]) 504 bp--; 505 continue; 506 } 507 if (c==tp->t_kill) 508 goto loop; 509 if (c==tun.t_eofc) 510 continue; 511 } else { 512 mc = maptab[c]; 513 if (c==tp->t_erase || c==tp->t_kill) 514 mc = c; 515 if (mc && (mc==c || (tp->t_flags&LCASE))) { 516 if (bp[-2] != '\\') 517 c = mc; 518 bp--; 519 } 520 } 521 } 522 *bp++ = c; 523 if (bp>=canonb+CANBSIZ) 524 break; 525 } 526 bp1 = &canonb[2]; 527 (void) b_to_q(bp1, bp-bp1, &tp->t_canq); 528 529 if (tp->t_state&TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) { 530 if (putc(tun.t_startc, &tp->t_outq)==0) { 531 tp->t_state &= ~TBLOCK; 532 ttstart(tp); 533 } 534 tp->t_char = 0; 535 } 536 537 splx(s); 538 return(0); 539 } 540 541 542 /* 543 * block transfer input handler. 544 */ 545 ttyrend(tp, pb, pe) 546 register struct tty *tp; 547 register char *pb, *pe; 548 { 549 int tandem; 550 551 tandem = tp->t_flags&TANDEM; 552 if (tp->t_flags&RAW) { 553 (void) b_to_q(pb, pe-pb, &tp->t_rawq); 554 if (tp->t_chan) 555 (void) sdata(tp->t_chan); else 556 wakeup((caddr_t)&tp->t_rawq); 557 } else { 558 tp->t_flags &= ~TANDEM; 559 while (pb < pe) 560 ttyinput(*pb++, tp); 561 tp->t_flags |= tandem; 562 } 563 if (tandem) 564 ttyblock(tp); 565 } 566 567 /* 568 * Place a character on raw TTY input queue, putting in delimiters 569 * and waking up top half as needed. 570 * Also echo if required. 571 * The arguments are the character and the appropriate 572 * tty structure. 573 */ 574 ttyinput(c, tp) 575 register c; 576 register struct tty *tp; 577 { 578 register int t_flags; 579 register struct chan *cp; 580 581 tk_nin += 1; 582 c &= 0377; 583 t_flags = tp->t_flags; 584 if (t_flags&TANDEM) 585 ttyblock(tp); 586 if ((t_flags&RAW)==0) { 587 c &= 0177; 588 if (tp->t_state&TTSTOP) { 589 if (c==tun.t_startc) { 590 tp->t_state &= ~TTSTOP; 591 ttstart(tp); 592 return; 593 } 594 if (c==tun.t_stopc) 595 return; 596 tp->t_state &= ~TTSTOP; 597 ttstart(tp); 598 } else { 599 if (c==tun.t_stopc) { 600 tp->t_state |= TTSTOP; 601 (*cdevsw[major(tp->t_dev)].d_stop)(tp); 602 return; 603 } 604 if (c==tun.t_startc) 605 return; 606 } 607 if (c==tun.t_quitc || c==tun.t_intrc) { 608 flushtty(tp); 609 c = (c==tun.t_intrc) ? SIGINT:SIGQUIT; 610 if (tp->t_chan) 611 scontrol(tp->t_chan, M_SIG, c); 612 else 613 gsignal(tp->t_pgrp, c); 614 return; 615 } 616 if (c=='\r' && t_flags&CRMOD) 617 c = '\n'; 618 } 619 if (tp->t_rawq.c_cc>TTYHOG) { 620 flushtty(tp); 621 return; 622 } 623 if (t_flags&LCASE && c>='A' && c<='Z') 624 c += 'a'-'A'; 625 (void) putc(c, &tp->t_rawq); 626 if (t_flags&(RAW|CBREAK)||(c=='\n'||c==tun.t_eofc||c==tun.t_brkc)) { 627 if ((t_flags&(RAW|CBREAK))==0 && putc(0377, &tp->t_rawq)==0) 628 tp->t_delct++; 629 if ((cp=tp->t_chan)!=NULL) 630 (void) sdata(cp); else 631 wakeup((caddr_t)&tp->t_rawq); 632 } 633 if (t_flags&ECHO) { 634 ttyoutput(c, tp); 635 if (c==tp->t_kill && (t_flags&(RAW|CBREAK))==0) 636 ttyoutput('\n', tp); 637 ttstart(tp); 638 } 639 } 640 641 642 /* 643 * Send stop character on input overflow. 644 */ 645 ttyblock(tp) 646 register struct tty *tp; 647 { 648 register x; 649 x = q1.c_cc + q2.c_cc; 650 if (q1.c_cc > TTYHOG) { 651 flushtty(tp); 652 tp->t_state &= ~TBLOCK; 653 } 654 if (x >= TTYHOG/2) { 655 if (putc(tun.t_stopc, &tp->t_outq)==0) { 656 tp->t_state |= TBLOCK; 657 tp->t_char++; 658 ttstart(tp); 659 } 660 } 661 } 662 663 /* 664 * put character on TTY output queue, adding delays, 665 * expanding tabs, and handling the CR/NL bit. 666 * It is called both from the top half for output, and from 667 * interrupt level for echoing. 668 * The arguments are the character and the tty structure. 669 */ 670 ttyoutput(c, tp) 671 register c; 672 register struct tty *tp; 673 { 674 register char *colp; 675 register ctype; 676 677 /* 678 * Ignore EOT in normal mode to avoid hanging up 679 * certain terminals. 680 * In raw mode dump the char unchanged. 681 */ 682 if ((tp->t_flags&RAW)==0) { 683 c &= 0177; 684 if ((tp->t_flags&CBREAK)==0 && c==CEOT) 685 return; 686 } else { 687 tk_nout++; 688 (void) putc(c, &tp->t_outq); 689 return; 690 } 691 692 /* 693 * Turn tabs to spaces as required 694 */ 695 if (c=='\t' && (tp->t_flags&TBDELAY)==XTABS) { 696 c = 8 - (tp->t_col & 7); 697 (void) b_to_q(" ", c, &tp->t_outq); 698 tp->t_col += c; 699 tk_nout += c; 700 return; 701 } 702 tk_nout++; 703 /* 704 * for upper-case-only terminals, 705 * generate escapes. 706 */ 707 if (tp->t_flags&LCASE) { 708 colp = "({)}!|^~'`"; 709 while(*colp++) 710 if(c == *colp++) { 711 ttyoutput('\\', tp); 712 c = colp[-2]; 713 break; 714 } 715 if ('a'<=c && c<='z') 716 c += 'A' - 'a'; 717 } 718 /* 719 * turn <nl> to <cr><lf> if desired. 720 */ 721 if (c=='\n' && tp->t_flags&CRMOD) 722 ttyoutput('\r', tp); 723 (void) putc(c, &tp->t_outq); 724 /* 725 * Calculate delays. 726 * The numbers here represent clock ticks 727 * and are not necessarily optimal for all terminals. 728 * The delays are indicated by characters above 0200. 729 * In raw mode there are no delays and the 730 * transmission path is 8 bits wide. 731 */ 732 colp = &tp->t_col; 733 ctype = partab[c]; 734 c = 0; 735 switch (ctype&077) { 736 737 /* ordinary */ 738 case 0: 739 (*colp)++; 740 741 /* non-printing */ 742 case 1: 743 break; 744 745 /* backspace */ 746 case 2: 747 if (*colp) 748 (*colp)--; 749 break; 750 751 /* newline */ 752 case 3: 753 ctype = (tp->t_flags >> 8) & 03; 754 if(ctype == 1) { /* tty 37 */ 755 if (*colp) 756 c = max(((unsigned)*colp>>4) + 3, (unsigned)6); 757 } else 758 if(ctype == 2) { /* vt05 */ 759 c = 6; 760 } 761 *colp = 0; 762 break; 763 764 /* tab */ 765 case 4: 766 ctype = (tp->t_flags >> 10) & 03; 767 if(ctype == 1) { /* tty 37 */ 768 c = 1 - (*colp | ~07); 769 if(c < 5) 770 c = 0; 771 } 772 *colp |= 07; 773 (*colp)++; 774 break; 775 776 /* vertical motion */ 777 case 5: 778 if(tp->t_flags & VTDELAY) /* tty 37 */ 779 c = 0177; 780 break; 781 782 /* carriage return */ 783 case 6: 784 ctype = (tp->t_flags >> 12) & 03; 785 if(ctype == 1) { /* tn 300 */ 786 c = 5; 787 } else if(ctype == 2) { /* ti 700 */ 788 c = 10; 789 } else if(ctype == 3) { /* concept 100 */ 790 int i; 791 for (i= *colp; i<9; i++) 792 (void) putc(0177, &tp->t_outq); 793 } 794 *colp = 0; 795 } 796 if(c) 797 (void) putc(c|0200, &tp->t_outq); 798 } 799 800 /* 801 * Restart typewriter output following a delay 802 * timeout. 803 * The name of the routine is passed to the timeout 804 * subroutine and it is called during a clock interrupt. 805 */ 806 ttrstrt(tp) 807 register struct tty *tp; 808 { 809 810 tp->t_state &= ~TIMEOUT; 811 ttstart(tp); 812 } 813 814 /* 815 * Start output on the typewriter. It is used from the top half 816 * after some characters have been put on the output queue, 817 * from the interrupt routine to transmit the next 818 * character, and after a timeout has finished. 819 */ 820 ttstart(tp) 821 register struct tty *tp; 822 { 823 register s; 824 825 s = spl5(); 826 if((tp->t_state&(TIMEOUT|TTSTOP|BUSY)) == 0) 827 (*tp->t_oproc)(tp); 828 splx(s); 829 } 830 831 /* 832 * Called from device's read routine after it has 833 * calculated the tty-structure given as argument. 834 */ 835 ttread(tp) 836 register struct tty *tp; 837 { 838 register s; 839 840 if ((tp->t_state&CARR_ON)==0) 841 return(-1); 842 s = spl5(); 843 if (tp->t_canq.c_cc==0) 844 while (canon(tp)<0) 845 if (tp->t_chan==NULL) { 846 sleep((caddr_t)&tp->t_rawq, TTIPRI); 847 } else { 848 splx(s); 849 return(0); 850 } 851 splx(s); 852 while (tp->t_canq.c_cc && passc(getc(&tp->t_canq))>=0) 853 ; 854 return(tp->t_rawq.c_cc+tp->t_canq.c_cc); 855 } 856 857 /* 858 * Called from the device's write routine after it has 859 * calculated the tty-structure given as argument. 860 */ 861 caddr_t 862 ttwrite(tp) 863 register struct tty *tp; 864 { 865 /* 866 * THE POSITIONING OF CP, CC, AND CE ARE CRITICAL 867 * AND MUST NOT BE CHANGED WITHOUT PATCHING 868 * THE 'ASM' INLINES BELOW. WATCH OUT. 869 */ 870 register char *cp; 871 register int cc, ce; 872 register i; 873 char obuf[OBUFSIZ]; 874 875 if ((tp->t_state&CARR_ON)==0) 876 return(NULL); 877 while (u.u_count) { 878 cc = MIN(u.u_count, OBUFSIZ); 879 cp = obuf; 880 iomove(cp, (unsigned)cc, B_WRITE); 881 if (u.u_error) 882 break; 883 (void) spl5(); 884 while (tp->t_outq.c_cc > TTHIWAT) { 885 ttstart(tp); 886 tp->t_state |= ASLEEP; 887 if (tp->t_chan) { 888 u.u_base -= cc; 889 u.u_offset -= cc; 890 u.u_count += cc; 891 (void) spl0(); 892 return((caddr_t)&tp->t_outq); 893 } 894 sleep((caddr_t)&tp->t_outq, TTOPRI); 895 } 896 (void) spl0(); 897 if (tp->t_flags&LCASE) { 898 while (cc--) 899 ttyoutput(*cp++,tp); 900 continue; 901 } 902 while (cc) { 903 if (tp->t_flags&RAW) 904 ce=cc; 905 else { 906 #ifdef VAX 907 asm(" scanc r9,(r10),_partab,$077"); 908 asm(" subl3 r0,r9,r8"); 909 #else 910 ce=0; 911 while(((partab[*(cp+ce)]&077)==0)&&(ce<cc)) 912 ce++; 913 #endif 914 if (ce==0) { 915 ttyoutput(*cp++,tp); 916 cc--; 917 goto check; 918 } 919 } 920 i=b_to_q(cp,ce,&tp->t_outq); 921 ce-=i; 922 tk_nout+=ce; 923 tp->t_col+=ce; 924 cp+=ce; 925 cc-=ce; 926 check: 927 if (tp->t_outq.c_cc > TTHIWAT) { 928 (void) spl5(); 929 while (tp->t_outq.c_cc > TTHIWAT) { 930 ttstart(tp); 931 tp->t_state |= ASLEEP; 932 sleep((caddr_t)&tp->t_outq, TTOPRI); 933 } 934 (void) spl0(); 935 } 936 } 937 } 938 ttstart(tp); 939 return(NULL); 940 } 941