/contrib/ntp/kernel/tty_chu.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 276 lines · 175 code · 31 blank · 70 comment · 34 complexity · 170faa1cdf4dc93336873598760fef06 MD5 · raw file

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