home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / 2014.11.minnie.tuhs.org.tar / minnie.tuhs.org / UnixArchive / PDP-11 / Trees / V6 / usr / sys / dmr / tty.c < prev    next >
C/C++ Source or Header  |  1975-07-17  |  10KB  |  538 lines

  1. #
  2. /*
  3.  */
  4.  
  5. /*
  6.  * general TTY subroutines
  7.  */
  8. #include "../param.h"
  9. #include "../systm.h"
  10. #include "../user.h"
  11. #include "../tty.h"
  12. #include "../proc.h"
  13. #include "../inode.h"
  14. #include "../file.h"
  15. #include "../reg.h"
  16. #include "../conf.h"
  17.  
  18. /*
  19.  * Input mapping table-- if an entry is non-zero, when the
  20.  * corresponding character is typed preceded by "\" the escape
  21.  * sequence is replaced by the table value.  Mostly used for
  22.  * upper-case only terminals.
  23.  */
  24. char    maptab[]
  25. {
  26.     000,000,000,000,004,000,000,000,
  27.     000,000,000,000,000,000,000,000,
  28.     000,000,000,000,000,000,000,000,
  29.     000,000,000,000,000,000,000,000,
  30.     000,'|',000,'#',000,000,000,'`',
  31.     '{','}',000,000,000,000,000,000,
  32.     000,000,000,000,000,000,000,000,
  33.     000,000,000,000,000,000,000,000,
  34.     '@',000,000,000,000,000,000,000,
  35.     000,000,000,000,000,000,000,000,
  36.     000,000,000,000,000,000,000,000,
  37.     000,000,000,000,000,000,'~',000,
  38.     000,'A','B','C','D','E','F','G',
  39.     'H','I','J','K','L','M','N','O',
  40.     'P','Q','R','S','T','U','V','W',
  41.     'X','Y','Z',000,000,000,000,000,
  42. };
  43.  
  44. /*
  45.  * The actual structure of a clist block manipulated by
  46.  * getc and putc (mch.s)
  47.  */
  48. struct cblock {
  49.     struct cblock *c_next;
  50.     char info[6];
  51. };
  52.  
  53. /* The character lists-- space for 6*NCLIST characters */
  54. struct cblock cfree[NCLIST];
  55. /* List head for unused character blocks. */
  56. struct cblock *cfreelist;
  57.  
  58. /*
  59.  * structure of device registers for KL, DL, and DC
  60.  * interfaces-- more particularly, those for which the
  61.  * SSTART bit is off and can be treated by general routines
  62.  * (that is, not DH).
  63.  */
  64. struct {
  65.     int ttrcsr;
  66.     int ttrbuf;
  67.     int tttcsr;
  68.     int tttbuf;
  69. };
  70.  
  71. /*
  72.  * The routine implementing the gtty system call.
  73.  * Just call lower level routine and pass back values.
  74.  */
  75. gtty()
  76. {
  77.     int v[3];
  78.     register *up, *vp;
  79.  
  80.     vp = v;
  81.     sgtty(vp);
  82.     if (u.u_error)
  83.         return;
  84.     up = u.u_arg[0];
  85.     suword(up, *vp++);
  86.     suword(++up, *vp++);
  87.     suword(++up, *vp++);
  88. }
  89.  
  90. /*
  91.  * The routine implementing the stty system call.
  92.  * Read in values and call lower level.
  93.  */
  94. stty()
  95. {
  96.     register int *up;
  97.  
  98.     up = u.u_arg[0];
  99.     u.u_arg[0] = fuword(up);
  100.     u.u_arg[1] = fuword(++up);
  101.     u.u_arg[2] = fuword(++up);
  102.     sgtty(0);
  103. }
  104.  
  105. /*
  106.  * Stuff common to stty and gtty.
  107.  * Check legality and switch out to individual
  108.  * device routine.
  109.  * v  is 0 for stty; the parameters are taken from u.u_arg[].
  110.  * c  is non-zero for gtty and is the place in which the device
  111.  * routines place their information.
  112.  */
  113. sgtty(v)
  114. int *v;
  115. {
  116.     register struct file *fp;
  117.     register struct inode *ip;
  118.  
  119.     if ((fp = getf(u.u_ar0[R0])) == NULL)
  120.         return;
  121.     ip = fp->f_inode;
  122.     if ((ip->i_mode&IFMT) != IFCHR) {
  123.         u.u_error = ENOTTY;
  124.         return;
  125.     }
  126.     (*cdevsw[ip->i_addr[0].d_major].d_sgtty)(ip->i_addr[0], v);
  127. }
  128.  
  129. /*
  130.  * Wait for output to drain, then flush input waiting.
  131.  */
  132. wflushtty(atp)
  133. struct tty *atp;
  134. {
  135.     register struct tty *tp;
  136.  
  137.     tp = atp;
  138.     spl5();
  139.     while (tp->t_outq.c_cc) {
  140.         tp->t_state =| ASLEEP;
  141.         sleep(&tp->t_outq, TTOPRI);
  142.     }
  143.     flushtty(tp);
  144.     spl0();
  145. }
  146.  
  147. /*
  148.  * Initialize clist by freeing all character blocks, then count
  149.  * number of character devices. (Once-only routine)
  150.  */
  151. cinit()
  152. {
  153.     register int ccp;
  154.     register struct cblock *cp;
  155.     register struct cdevsw *cdp;
  156.  
  157.     ccp = cfree;
  158.     for (cp=(ccp+07)&~07; cp <= &cfree[NCLIST-1]; cp++) {
  159.         cp->c_next = cfreelist;
  160.         cfreelist = cp;
  161.     }
  162.     ccp = 0;
  163.     for(cdp = cdevsw; cdp->d_open; cdp++)
  164.         ccp++;
  165.     nchrdev = ccp;
  166. }
  167.  
  168. /*
  169.  * flush all TTY queues
  170.  */
  171. flushtty(atp)
  172. struct tty *atp;
  173. {
  174.     register struct tty *tp;
  175.     register int sps;
  176.  
  177.     tp = atp;
  178.     while (getc(&tp->t_canq) >= 0);
  179.     while (getc(&tp->t_outq) >= 0);
  180.     wakeup(&tp->t_rawq);
  181.     wakeup(&tp->t_outq);
  182.     sps = PS->integ;
  183.     spl5();
  184.     while (getc(&tp->t_rawq) >= 0);
  185.     tp->t_delct = 0;
  186.     PS->integ = sps;
  187. }
  188.  
  189. /*
  190.  * transfer raw input list to canonical list,
  191.  * doing erase-kill processing and handling escapes.
  192.  * It waits until a full line has been typed in cooked mode,
  193.  * or until any character has been typed in raw mode.
  194.  */
  195. canon(atp)
  196. struct tty *atp;
  197. {
  198.     register char *bp;
  199.     char *bp1;
  200.     register struct tty *tp;
  201.     register int c;
  202.  
  203.     tp = atp;
  204.     spl5();
  205.     while (tp->t_delct==0) {
  206.         if ((tp->t_state&CARR_ON)==0)
  207.             return(0);
  208.         sleep(&tp->t_rawq, TTIPRI);
  209.     }
  210.     spl0();
  211. loop:
  212.     bp = &canonb[2];
  213.     while ((c=getc(&tp->t_rawq)) >= 0) {
  214.         if (c==0377) {
  215.             tp->t_delct--;
  216.             break;
  217.         }
  218.         if ((tp->t_flags&RAW)==0) {
  219.             if (bp[-1]!='\\') {
  220.                 if (c==tp->t_erase) {
  221.                     if (bp > &canonb[2])
  222.                         bp--;
  223.                     continue;
  224.                 }
  225.                 if (c==tp->t_kill)
  226.                     goto loop;
  227.                 if (c==CEOT)
  228.                     continue;
  229.             } else
  230.             if (maptab[c] && (maptab[c]==c || (tp->t_flags&LCASE))) {
  231.                 if (bp[-2] != '\\')
  232.                     c = maptab[c];
  233.                 bp--;
  234.             }
  235.         }
  236.         *bp++ = c;
  237.         if (bp>=canonb+CANBSIZ)
  238.             break;
  239.     }
  240.     bp1 = bp;
  241.     bp = &canonb[2];
  242.     c = &tp->t_canq;
  243.     while (bp<bp1)
  244.         putc(*bp++, c);
  245.     return(1);
  246. }
  247.  
  248. /*
  249.  * Place a character on raw TTY input queue, putting in delimiters
  250.  * and waking up top half as needed.
  251.  * Also echo if required.
  252.  * The arguments are the character and the appropriate
  253.  * tty structure.
  254.  */
  255. ttyinput(ac, atp)
  256. struct tty *atp;
  257. {
  258.     register int t_flags, c;
  259.     register struct tty *tp;
  260.  
  261.     tp = atp;
  262.     c = ac;
  263.     t_flags = tp->t_flags;
  264.     if ((c =& 0177) == '\r' && t_flags&CRMOD)
  265.         c = '\n';
  266.     if ((t_flags&RAW)==0 && (c==CQUIT || c==CINTR)) {
  267.         signal(tp, c==CINTR? SIGINT:SIGQIT);
  268.         flushtty(tp);
  269.         return;
  270.     }
  271.     if (tp->t_rawq.c_cc>=TTYHOG) {
  272.         flushtty(tp);
  273.         return;
  274.     }
  275.     if (t_flags&LCASE && c>='A' && c<='Z')
  276.         c =+ 'a'-'A';
  277.     putc(c, &tp->t_rawq);
  278.     if (t_flags&RAW || c=='\n' || c==004) {
  279.         wakeup(&tp->t_rawq);
  280.         if (putc(0377, &tp->t_rawq)==0)
  281.             tp->t_delct++;
  282.     }
  283.     if (t_flags&ECHO) {
  284.         ttyoutput(c, tp);
  285.         ttstart(tp);
  286.     }
  287. }
  288.  
  289. /*
  290.  * put character on TTY output queue, adding delays,
  291.  * expanding tabs, and handling the CR/NL bit.
  292.  * It is called both from the top half for output, and from
  293.  * interrupt level for echoing.
  294.  * The arguments are the character and the tty structure.
  295.  */
  296. ttyoutput(ac, tp)
  297. struct tty *tp;
  298. {
  299.     register int c;
  300.     register struct tty *rtp;
  301.     register char *colp;
  302.     int ctype;
  303.  
  304.     rtp = tp;
  305.     c = ac&0177;
  306.     /*
  307.      * Ignore EOT in normal mode to avoid hanging up
  308.      * certain terminals.
  309.      */
  310.     if (c==004 && (rtp->t_flags&RAW)==0)
  311.         return;
  312.     /*
  313.      * Turn tabs to spaces as required
  314.      */
  315.     if (c=='\t' && rtp->t_flags&XTABS) {
  316.         do
  317.             ttyoutput(' ', rtp);
  318.         while (rtp->t_col&07);
  319.         return;
  320.     }
  321.     /*
  322.      * for upper-case-only terminals,
  323.      * generate escapes.
  324.      */
  325.     if (rtp->t_flags&LCASE) {
  326.         colp = "({)}!|^~'`";
  327.         while(*colp++)
  328.             if(c == *colp++) {
  329.                 ttyoutput('\\', rtp);
  330.                 c = colp[-2];
  331.                 break;
  332.             }
  333.         if ('a'<=c && c<='z')
  334.             c =+ 'A' - 'a';
  335.     }
  336.     /*
  337.      * turn <nl> to <cr><lf> if desired.
  338.      */
  339.     if (c=='\n' && rtp->t_flags&CRMOD)
  340.         ttyoutput('\r', rtp);
  341.     if (putc(c, &rtp->t_outq))
  342.         return;
  343.     /*
  344.      * Calculate delays.
  345.      * The numbers here represent clock ticks
  346.      * and are not necessarily optimal for all terminals.
  347.      * The delays are indicated by characters above 0200,
  348.      * thus (unfortunately) restricting the transmission
  349.      * path to 7 bits.
  350.      */
  351.     colp = &rtp->t_col;
  352.     ctype = partab[c];
  353.     c = 0;
  354.     switch (ctype&077) {
  355.  
  356.     /* ordinary */
  357.     case 0:
  358.         (*colp)++;
  359.  
  360.     /* non-printing */
  361.     case 1:
  362.         break;
  363.  
  364.     /* backspace */
  365.     case 2:
  366.         if (*colp)
  367.             (*colp)--;
  368.         break;
  369.  
  370.     /* newline */
  371.     case 3:
  372.         ctype = (rtp->t_flags >> 8) & 03;
  373.         if(ctype == 1) { /* tty 37 */
  374.             if (*colp)
  375.                 c = max((*colp>>4) + 3, 6);
  376.         } else
  377.         if(ctype == 2) { /* vt05 */
  378.             c = 6;
  379.         }
  380.         *colp = 0;
  381.         break;
  382.  
  383.     /* tab */
  384.     case 4:
  385.         ctype = (rtp->t_flags >> 10) & 03;
  386.         if(ctype == 1) { /* tty 37 */
  387.             c = 1 - (*colp | ~07);
  388.             if(c < 5)
  389.                 c = 0;
  390.         }
  391.         *colp =| 07;
  392.         (*colp)++;
  393.         break;
  394.  
  395.     /* vertical motion */
  396.     case 5:
  397.         if(rtp->t_flags & VTDELAY) /* tty 37 */
  398.             c = 0177;
  399.         break;
  400.  
  401.     /* carriage return */
  402.     case 6:
  403.         ctype = (rtp->t_flags >> 12) & 03;
  404.         if(ctype == 1) { /* tn 300 */
  405.             c = 5;
  406.         } else
  407.         if(ctype == 2) { /* ti 700 */
  408.             c = 10;
  409.         }
  410.         *colp = 0;
  411.     }
  412.     if(c)
  413.         putc(c|0200, &rtp->t_outq);
  414. }
  415.  
  416. /*
  417.  * Restart typewriter output following a delay
  418.  * timeout.
  419.  * The name of the routine is passed to the timeout
  420.  * subroutine and it is called during a clock interrupt.
  421.  */
  422. ttrstrt(atp)
  423. {
  424.     register struct tty *tp;
  425.  
  426.     tp = atp;
  427.     tp->t_state =& ~TIMEOUT;
  428.     ttstart(tp);
  429. }
  430.  
  431. /*
  432.  * Start output on the typewriter. It is used from the top half
  433.  * after some characters have been put on the output queue,
  434.  * from the interrupt routine to transmit the next
  435.  * character, and after a timeout has finished.
  436.  * If the SSTART bit is off for the tty the work is done here,
  437.  * using the protocol of the single-line interfaces (KL, DL, DC);
  438.  * otherwise the address word of the tty structure is
  439.  * taken to be the name of the device-dependent startup routine.
  440.  */
  441. ttstart(atp)
  442. struct tty *atp;
  443. {
  444.     register int *addr, c;
  445.     register struct tty *tp;
  446.     struct { int (*func)(); };
  447.  
  448.     tp = atp;
  449.     addr = tp->t_addr;
  450.     if (tp->t_state&SSTART) {
  451.         (*addr.func)(tp);
  452.         return;
  453.     }
  454.     if ((addr->tttcsr&DONE)==0 || tp->t_state&TIMEOUT)
  455.         return;
  456.     if ((c=getc(&tp->t_outq)) >= 0) {
  457.         if (c<=0177)
  458.             addr->tttbuf = c | (partab[c]&0200);
  459.         else {
  460.             timeout(ttrstrt, tp, c&0177);
  461.             tp->t_state =| TIMEOUT;
  462.         }
  463.     }
  464. }
  465.  
  466. /*
  467.  * Called from device's read routine after it has
  468.  * calculated the tty-structure given as argument.
  469.  * The pc is backed up for the duration of this call.
  470.  * In case of a caught interrupt, an RTI will re-execute.
  471.  */
  472. ttread(atp)
  473. struct tty *atp;
  474. {
  475.     register struct tty *tp;
  476.  
  477.     tp = atp;
  478.     if ((tp->t_state&CARR_ON)==0)
  479.         return;
  480.     if (tp->t_canq.c_cc || canon(tp))
  481.         while (tp->t_canq.c_cc && passc(getc(&tp->t_canq))>=0);
  482. }
  483.  
  484. /*
  485.  * Called from the device's write routine after it has
  486.  * calculated the tty-structure given as argument.
  487.  */
  488. ttwrite(atp)
  489. struct tty *atp;
  490. {
  491.     register struct tty *tp;
  492.     register int c;
  493.  
  494.     tp = atp;
  495.     if ((tp->t_state&CARR_ON)==0)
  496.         return;
  497.     while ((c=cpass())>=0) {
  498.         spl5();
  499.         while (tp->t_outq.c_cc > TTHIWAT) {
  500.             ttstart(tp);
  501.             tp->t_state =| ASLEEP;
  502.             sleep(&tp->t_outq, TTOPRI);
  503.         }
  504.         spl0();
  505.         ttyoutput(c, tp);
  506.     }
  507.     ttstart(tp);
  508. }
  509.  
  510. /*
  511.  * Common code for gtty and stty functions on typewriters.
  512.  * If v is non-zero then gtty is being done and information is
  513.  * passed back therein;
  514.  * if it is zero stty is being done and the input information is in the
  515.  * u_arg array.
  516.  */
  517. ttystty(atp, av)
  518. int *atp, *av;
  519. {
  520.     register  *tp, *v;
  521.  
  522.     tp = atp;
  523.     if(v = av) {
  524.         *v++ = tp->t_speeds;
  525.         v->lobyte = tp->t_erase;
  526.         v->hibyte = tp->t_kill;
  527.         v[1] = tp->t_flags;
  528.         return(1);
  529.     }
  530.     wflushtty(tp);
  531.     v = u.u_arg;
  532.     tp->t_speeds = *v++;
  533.     tp->t_erase = v->lobyte;
  534.     tp->t_kill = v->hibyte;
  535.     tp->t_flags = v[1];
  536.     return(0);
  537. }
  538.