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