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