/contrib/ntp/ntpd/refclock_hopfpci.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 265 lines · 163 code · 37 blank · 65 comment · 13 complexity · 39d34d6cecf7325fed7712528d5c9260 MD5 · raw file

  1. /*
  2. * refclock_hopfpci.c
  3. *
  4. * - clock driver for hopf 6039 PCI board (GPS or DCF77)
  5. * Bernd Altmeier altmeier@atlsoft.de
  6. *
  7. * latest source and further information can be found at:
  8. * http://www.ATLSoft.de/ntp
  9. *
  10. * In order to run this driver you have to install and test
  11. * the PCI-board driver for your system first.
  12. *
  13. * On Linux/UNIX
  14. *
  15. * The driver attempts to open the device /dev/hopf6039 .
  16. * The device entry will be made by the installation process of
  17. * the kernel module for the PCI-bus board. The driver sources
  18. * belongs to the delivery equipment of the PCI-board.
  19. *
  20. * On Windows NT/2000
  21. *
  22. * The driver attempts to open the device by calling the function
  23. * "OpenHopfDevice()". This function will be installed by the
  24. * Device Driver for the PCI-bus board. The driver belongs to the
  25. * delivery equipment of the PCI-board.
  26. *
  27. *
  28. * Start 21.03.2000 Revision: 01.20
  29. * changes 22.12.2000 Revision: 01.40 flag1 = 1 sync even if Quarz
  30. *
  31. */
  32. #ifdef HAVE_CONFIG_H
  33. # include <config.h>
  34. #endif
  35. #if defined(REFCLOCK) && defined(CLOCK_HOPF_PCI)
  36. #include "ntpd.h"
  37. #include "ntp_io.h"
  38. #include "ntp_refclock.h"
  39. #include "ntp_unixtime.h"
  40. #include "ntp_stdlib.h"
  41. #undef fileno
  42. #include <ctype.h>
  43. #undef fileno
  44. #ifndef SYS_WINNT
  45. # include <sys/ipc.h>
  46. # include <sys/ioctl.h>
  47. # include <assert.h>
  48. # include <unistd.h>
  49. # include <stdio.h>
  50. # include "hopf6039.h"
  51. #else
  52. # include "hopf_PCI_io.h"
  53. #endif
  54. /*
  55. * hopfpci interface definitions
  56. */
  57. #define PRECISION (-10) /* precision assumed (1 ms) */
  58. #define REFID "hopf" /* reference ID */
  59. #define DESCRIPTION "hopf Elektronik PCI radio board"
  60. #define NSAMPLES 3 /* stages of median filter */
  61. #ifndef SYS_WINNT
  62. # define DEVICE "/dev/hopf6039" /* device name inode*/
  63. #else
  64. # define DEVICE "hopf6039" /* device name WinNT */
  65. #endif
  66. #define LEWAPWAR 0x20 /* leap second warning bit */
  67. #define HOPF_OPMODE 0xC0 /* operation mode mask */
  68. #define HOPF_INVALID 0x00 /* no time code available */
  69. #define HOPF_INTERNAL 0x40 /* internal clock */
  70. #define HOPF_RADIO 0x80 /* radio clock */
  71. #define HOPF_RADIOHP 0xC0 /* high precision radio clock */
  72. /*
  73. * hopfclock unit control structure.
  74. */
  75. struct hopfclock_unit {
  76. short unit; /* NTP refclock unit number */
  77. char leap_status; /* leap second flag */
  78. };
  79. int fd; /* file descr. */
  80. /*
  81. * Function prototypes
  82. */
  83. static int hopfpci_start (int, struct peer *);
  84. static void hopfpci_shutdown (int, struct peer *);
  85. static void hopfpci_poll (int unit, struct peer *);
  86. /*
  87. * Transfer vector
  88. */
  89. struct refclock refclock_hopfpci = {
  90. hopfpci_start, /* start up driver */
  91. hopfpci_shutdown, /* shut down driver */
  92. hopfpci_poll, /* transmit poll message */
  93. noentry, /* not used */
  94. noentry, /* initialize driver (not used) */
  95. noentry, /* not used */
  96. NOFLAGS /* not used */
  97. };
  98. /*
  99. * hopfpci_start - attach to hopf PCI board 6039
  100. */
  101. static int
  102. hopfpci_start(
  103. int unit,
  104. struct peer *peer
  105. )
  106. {
  107. struct refclockproc *pp;
  108. struct hopfclock_unit *up;
  109. /*
  110. * Allocate and initialize unit structure
  111. */
  112. up = (struct hopfclock_unit *) emalloc(sizeof(struct hopfclock_unit));
  113. if (!(up)) {
  114. msyslog(LOG_ERR, "hopfPCIClock(%d) emalloc: %m",unit);
  115. #ifdef DEBUG
  116. printf("hopfPCIClock(%d) emalloc\n",unit);
  117. #endif
  118. return (0);
  119. }
  120. memset((char *)up, 0, sizeof(struct hopfclock_unit));
  121. #ifndef SYS_WINNT
  122. fd = open(DEVICE,O_RDWR); /* try to open hopf clock device */
  123. #else
  124. if (!OpenHopfDevice()){
  125. msyslog(LOG_ERR,"Start: %s unit: %d failed!",DEVICE,unit);
  126. return (0);
  127. }
  128. #endif
  129. pp = peer->procptr;
  130. pp->io.clock_recv = noentry;
  131. pp->io.srcclock = (caddr_t)peer;
  132. pp->io.datalen = 0;
  133. pp->io.fd = INVALID_SOCKET;
  134. pp->unitptr = (caddr_t)up;
  135. get_systime(&pp->lastrec);
  136. /*
  137. * Initialize miscellaneous peer variables
  138. */
  139. if (pp->unitptr!=0) {
  140. memcpy((char *)&pp->refid, REFID, 4);
  141. peer->precision = PRECISION;
  142. pp->clockdesc = DESCRIPTION;
  143. up->leap_status = 0;
  144. up->unit = (short) unit;
  145. return (1);
  146. }
  147. else {
  148. return 0;
  149. }
  150. }
  151. /*
  152. * hopfpci_shutdown - shut down the clock
  153. */
  154. static void
  155. hopfpci_shutdown(
  156. int unit,
  157. struct peer *peer
  158. )
  159. {
  160. #ifndef SYS_WINNT
  161. close(fd);
  162. #else
  163. CloseHopfDevice();
  164. #endif
  165. }
  166. /*
  167. * hopfpci_poll - called by the transmit procedure
  168. */
  169. static void
  170. hopfpci_poll(
  171. int unit,
  172. struct peer *peer
  173. )
  174. {
  175. struct refclockproc *pp;
  176. HOPFTIME m_time;
  177. pp = peer->procptr;
  178. #ifndef SYS_WINNT
  179. ioctl(fd,HOPF_CLOCK_GET_UTC,&m_time);
  180. #else
  181. GetHopfSystemTime(&m_time);
  182. #endif
  183. pp->polls++;
  184. pp->day = ymd2yd(m_time.wYear,m_time.wMonth,m_time.wDay);
  185. pp->hour = m_time.wHour;
  186. pp->minute = m_time.wMinute;
  187. pp->second = m_time.wSecond;
  188. pp->nsec = m_time.wMilliseconds * 1000000;
  189. if (m_time.wStatus & LEWAPWAR)
  190. pp->leap = LEAP_ADDSECOND;
  191. else
  192. pp->leap = LEAP_NOWARNING;
  193. sprintf(pp->a_lastcode,"ST: %02X T: %02d:%02d:%02d.%03ld D: %02d.%02d.%04d",
  194. m_time.wStatus, pp->hour, pp->minute, pp->second,
  195. pp->nsec / 1000000, m_time.wDay, m_time.wMonth, m_time.wYear);
  196. pp->lencode = (u_short)strlen(pp->a_lastcode);
  197. get_systime(&pp->lastrec);
  198. /*
  199. * If clock has no valid status then report error and exit
  200. */
  201. if ((m_time.wStatus & HOPF_OPMODE) == HOPF_INVALID) { /* time ok? */
  202. refclock_report(peer, CEVNT_BADTIME);
  203. pp->leap = LEAP_NOTINSYNC;
  204. return;
  205. }
  206. /*
  207. * Test if time is running on internal quarz
  208. * if CLK_FLAG1 is set, sychronize even if no radio operation
  209. */
  210. if ((m_time.wStatus & HOPF_OPMODE) == HOPF_INTERNAL){
  211. if ((pp->sloppyclockflag & CLK_FLAG1) == 0) {
  212. refclock_report(peer, CEVNT_BADTIME);
  213. pp->leap = LEAP_NOTINSYNC;
  214. return;
  215. }
  216. }
  217. if (!refclock_process(pp)) {
  218. refclock_report(peer, CEVNT_BADTIME);
  219. return;
  220. }
  221. pp->lastref = pp->lastrec;
  222. refclock_receive(peer);
  223. record_clock_stats(&peer->srcadr, pp->a_lastcode);
  224. return;
  225. }
  226. #else
  227. int refclock_hopfpci_bs;
  228. #endif /* REFCLOCK */