home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / x / xntp3.zip / kernel / tty_chu.c < prev    next >
C/C++ Source or Header  |  1989-11-08  |  6KB  |  277 lines

  1. /*
  2.  * tty_chu.c - CHU line driver
  3.  */
  4.  
  5. #include "chu.h"
  6. #if NCHU > 0
  7.  
  8. #include "../h/param.h"
  9. #include "../h/types.h"
  10. #include "../h/systm.h"
  11. #include "../h/dir.h"
  12. #include "../h/user.h"
  13. #include "../h/ioctl.h"
  14. #include "../h/tty.h"
  15. #include "../h/proc.h"
  16. #include "../h/file.h"
  17. #include "../h/conf.h"
  18. #include "../h/buf.h"
  19. #include "../h/uio.h"
  20.  
  21. #include "../h/chudefs.h"
  22.  
  23. /*
  24.  * Line discipline for receiving CHU time codes.
  25.  * Does elementary noise elimination, takes time stamps after
  26.  * the arrival of each character, returns a buffer full of the
  27.  * received 10 character code and the associated time stamps.
  28.  */
  29. #define    NUMCHUBUFS    3
  30.  
  31. struct chudata {
  32.     u_char used;        /* Set to 1 when structure in use */
  33.     u_char lastindex;    /* least recently used buffer */
  34.     u_char curindex;    /* buffer to use */
  35.     u_char sleeping;    /* set to 1 when we're sleeping on a buffer */
  36.     struct chucode chubuf[NUMCHUBUFS];
  37. } chu_data[NCHU];
  38.  
  39. /*
  40.  * Number of microseconds we allow between
  41.  * character arrivals.  The speed is 300 baud
  42.  * so this should be somewhat more than 30 msec
  43.  */
  44. #define    CHUMAXUSEC    (50*1000)    /* 50 msec */
  45.  
  46. int chu_debug = 0;
  47.  
  48. /*
  49.  * Open as CHU time discipline.  Called when discipline changed
  50.  * with ioctl, and changes the interpretation of the information
  51.  * in the tty structure.
  52.  */
  53. /*ARGSUSED*/
  54. chuopen(dev, tp)
  55.     dev_t dev;
  56.     register struct tty *tp;
  57. {
  58.     register struct chudata *chu;
  59.  
  60.     /*
  61.      * Don't allow multiple opens.  This will also protect us
  62.      * from someone opening /dev/tty
  63.      */
  64.     if (tp->t_line == CHULDISC)
  65.         return (EBUSY);
  66.     ttywflush(tp);
  67.     for (chu = chu_data; chu < &chu_data[NCHU]; chu++)
  68.         if (!chu->used)
  69.             break;
  70.     if (chu >= &chu[NCHU])
  71.         return (EBUSY);
  72.     chu->used++;
  73.     chu->lastindex = chu->curindex = 0;
  74.     chu->sleeping = 0;
  75.     chu->chubuf[0].ncodechars = 0;
  76.     tp->T_LINEP = (caddr_t) chu;
  77.     return (0);
  78. }
  79.  
  80. /*
  81.  * Break down... called when discipline changed or from device
  82.  * close routine.
  83.  */
  84. chuclose(tp)
  85.     register struct tty *tp;
  86. {
  87.     register int s = spl5();
  88.  
  89.     ((struct chudata *) tp->T_LINEP)->used = 0;
  90.     tp->t_cp = 0;
  91.     tp->t_inbuf = 0;
  92.     tp->t_rawq.c_cc = 0;        /* clear queues -- paranoid */
  93.     tp->t_canq.c_cc = 0;
  94.     tp->t_line = 0;            /* paranoid: avoid races */
  95.     splx(s);
  96. }
  97.  
  98. /*
  99.  * Read a CHU buffer.  Sleep on the current buffer
  100.  */
  101. churead(tp, uio)
  102.     register struct tty *tp;
  103.     struct uio *uio;
  104. {
  105.     register struct chudata *chu;
  106.     register struct chucode *chucode;
  107.     register int s;
  108.  
  109.     if ((tp->t_state&TS_CARR_ON)==0)
  110.         return (EIO);
  111.  
  112.     chu = (struct chudata *) (tp->T_LINEP);
  113.  
  114.     s = spl5();
  115.     chucode = &(chu->chubuf[chu->lastindex]);
  116.     while (chu->curindex == chu->lastindex) {
  117.         chu->sleeping = 1;
  118.         sleep((caddr_t)chucode, TTIPRI);
  119.     }
  120.     chu->sleeping = 0;
  121.     if (++(chu->lastindex) >= NUMCHUBUFS)
  122.         chu->lastindex = 0;
  123.     splx(s);
  124.  
  125.     return (uiomove((caddr_t)chucode, sizeof(*chucode), UIO_READ, uio));
  126. }
  127.  
  128. /*
  129.  * Low level character input routine.
  130.  * If the character looks okay, grab a time stamp.  If the stuff in
  131.  * the buffer is too old, dump it and start fresh.  If the character is
  132.  * non-BCDish, everything in the buffer too.
  133.  */
  134. chuinput(c, tp)
  135.     register int c;
  136.     register struct tty *tp;
  137. {
  138.     register struct chudata *chu = (struct chudata *) tp->T_LINEP;
  139.     register struct chucode *chuc;
  140.     register int i;
  141.     long sec, usec;
  142.     struct timeval tv;
  143.  
  144.     /*
  145.      * Do a check on the BSDness of the character.  This delays
  146.      * the time stamp a bit but saves a fair amount of overhead
  147.      * when the static is bad.
  148.      */
  149.     if (((c) & 0xf) > 9 || (((c)>>4) & 0xf) > 9) {
  150.         chuc = &(chu->chubuf[chu->curindex]);
  151.         chuc->ncodechars = 0;    /* blow all previous away */
  152.         return;
  153.     }
  154.  
  155.     /*
  156.      * Call microtime() to get the current time of day
  157.      */
  158.     microtime(&tv);
  159.  
  160.     /*
  161.      * Compute the difference in this character's time stamp
  162.      * and the last.  If it exceeds the margin, blow away all
  163.      * the characters currently in the buffer.
  164.      */
  165.     chuc = &(chu->chubuf[chu->curindex]);
  166.     i = (int)chuc->ncodechars;
  167.     if (i > 0) {
  168.         sec = tv.tv_sec - chuc->codetimes[i-1].tv_sec;
  169.         usec = tv.tv_usec - chuc->codetimes[i-1].tv_usec;
  170.         if (usec < 0) {
  171.             sec -= 1;
  172.             usec += 1000000;
  173.         }
  174.         if (sec != 0 || usec > CHUMAXUSEC) {
  175.             i = 0;
  176.             chuc->ncodechars = 0;
  177.         }
  178.     }
  179.  
  180.     /*
  181.      * Store the character.  If we're done, have to tell someone
  182.      */
  183.     chuc->codechars[i] = (u_char)c;
  184.     chuc->codetimes[i] = tv;
  185.  
  186.     if (++i < NCHUCHARS) {
  187.         /*
  188.          * Not much to do here.  Save the count and wait
  189.          * for another character.
  190.          */
  191.         chuc->ncodechars = (u_char)i;
  192.     } else {
  193.         /*
  194.          * Mark this buffer full and point at next.  If the
  195.          * next buffer is full we overwrite it by bumping the
  196.          * next pointer.
  197.          */
  198.         chuc->ncodechars = NCHUCHARS;
  199.         if (++(chu->curindex) >= NUMCHUBUFS)
  200.             chu->curindex = 0;
  201.         if (chu->curindex == chu->lastindex)
  202.             if (++(chu->lastindex) >= NUMCHUBUFS)
  203.                 chu->lastindex = 0;
  204.         chu->chubuf[chu->curindex].ncodechars = 0;
  205.  
  206.         /*
  207.          * Wake up anyone sleeping on this.  Also wake up
  208.          * selectors and/or deliver a SIGIO as required.
  209.          */
  210.         if (tp->t_rsel) {
  211.             selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL);
  212.             tp->t_state &= ~TS_RCOLL;
  213.             tp->t_rsel = 0;
  214.         }
  215.         if (tp->t_state & TS_ASYNC)
  216.             gsignal(tp->t_pgrp, SIGIO);
  217.         if (chu->sleeping)
  218.             (void) wakeup((caddr_t)chuc);
  219.     }
  220. }
  221.  
  222. /*
  223.  * Handle ioctls.  We reject all tty-style except those that
  224.  * change the line discipline.
  225.  */
  226. chuioctl(tp, cmd, data, flag)
  227.     struct tty *tp;
  228.     int cmd;
  229.     caddr_t data;
  230.     int flag;
  231. {
  232.  
  233.     if ((cmd>>8) != 't')
  234.         return (-1);
  235.     switch (cmd) {
  236.     case TIOCSETD:
  237.     case TIOCGETD:
  238.     case TIOCGETP:
  239.     case TIOCGETC:
  240.         return (-1);
  241.     }
  242.     return (ENOTTY);    /* not quite appropriate */
  243. }
  244.  
  245.  
  246. chuselect(dev, rw)
  247.     dev_t dev;
  248.     int rw;
  249. {
  250.     register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)];
  251.     struct chudata *chu;
  252.     int s = spl5();
  253.  
  254.     chu = (struct chudata *) (tp->T_LINEP);
  255.  
  256.     switch (rw) {
  257.  
  258.     case FREAD:
  259.         if (chu->curindex != chu->lastindex)
  260.             goto win;
  261.         if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait)
  262.             tp->t_state |= TS_RCOLL;
  263.         else
  264.             tp->t_rsel = u.u_procp;
  265.         break;
  266.  
  267.     case FWRITE:
  268.         goto win;
  269.     }
  270.     splx(s);
  271.     return (0);
  272. win:
  273.     splx(s);
  274.     return (1);
  275. }
  276. #endif NCHU
  277.