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