]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/ntp/ntpd/refclock_hopfpci.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / ntp / ntpd / refclock_hopfpci.c
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
33 #ifdef HAVE_CONFIG_H
34 # include <config.h>
35 #endif
36
37 #if defined(REFCLOCK) && defined(CLOCK_HOPF_PCI)
38
39 #include "ntpd.h"
40 #include "ntp_io.h"
41 #include "ntp_refclock.h"
42 #include "ntp_unixtime.h"
43 #include "ntp_stdlib.h"
44
45 #undef fileno
46 #include <ctype.h>
47 #undef fileno
48
49 #ifndef SYS_WINNT
50 # include <sys/ipc.h>
51 # include <sys/ioctl.h>
52 # include <assert.h>
53 # include <unistd.h>
54 # include <stdio.h>
55 # include "hopf6039.h"
56 #else
57 # include "hopf_PCI_io.h"
58 #endif
59
60 /*
61  * hopfpci interface definitions
62  */
63 #define PRECISION       (-10)    /* precision assumed (1 ms) */
64 #define REFID           "hopf"   /* reference ID */
65 #define DESCRIPTION     "hopf Elektronik PCI radio board"
66
67 #define NSAMPLES        3       /* stages of median filter */
68 #ifndef SYS_WINNT
69 # define        DEVICE  "/dev/hopf6039"         /* device name inode*/
70 #else
71 # define        DEVICE  "hopf6039"      /* device name WinNT  */
72 #endif
73
74 #define LEWAPWAR        0x20    /* leap second warning bit */
75
76 #define HOPF_OPMODE     0xC0    /* operation mode mask */
77 #define HOPF_INVALID    0x00    /* no time code available */
78 #define HOPF_INTERNAL   0x40    /* internal clock */
79 #define HOPF_RADIO      0x80    /* radio clock */
80 #define HOPF_RADIOHP    0xC0    /* high precision radio clock */
81
82
83 /*
84  * hopfclock unit control structure.
85  */
86 struct hopfclock_unit {
87         short   unit;           /* NTP refclock unit number */
88         char    leap_status;    /* leap second flag */
89 };
90 int     fd;                     /* file descr. */
91
92 /*
93  * Function prototypes
94  */
95 static  int     hopfpci_start       (int, struct peer *);
96 static  void    hopfpci_shutdown    (int, struct peer *);
97 static  void    hopfpci_poll        (int unit, struct peer *);
98
99 /*
100  * Transfer vector
101  */
102 struct  refclock refclock_hopfpci = {
103         hopfpci_start,          /* start up driver */
104         hopfpci_shutdown,       /* shut down driver */
105         hopfpci_poll,           /* transmit poll message */
106         noentry,                /* not used */
107         noentry,                /* initialize driver (not used) */
108         noentry,                /* not used */
109         NOFLAGS                 /* not used */
110 };
111
112 /*
113  * hopfpci_start - attach to hopf PCI board 6039
114  */
115 static int
116 hopfpci_start(
117         int unit,
118         struct peer *peer
119         )
120 {
121         struct refclockproc *pp;
122         struct hopfclock_unit *up;
123
124         /*
125          * Allocate and initialize unit structure
126          */
127         up = emalloc_zero(sizeof(*up));
128
129 #ifndef SYS_WINNT
130
131         fd = open(DEVICE,O_RDWR); /* try to open hopf clock device */
132
133 #else
134         if (!OpenHopfDevice()) {
135                 msyslog(LOG_ERR, "Start: %s unit: %d failed!", DEVICE, unit);
136                 free(up);
137                 return (0);
138         }
139 #endif
140
141         pp = peer->procptr;
142         pp->io.clock_recv = noentry;
143         pp->io.srcclock = peer;
144         pp->io.datalen = 0;
145         pp->io.fd = INVALID_SOCKET;
146         pp->unitptr = up;
147
148         get_systime(&pp->lastrec);
149
150         /*
151          * Initialize miscellaneous peer variables
152          */
153         memcpy((char *)&pp->refid, REFID, 4);
154         peer->precision = PRECISION;
155         pp->clockdesc = DESCRIPTION;
156         up->leap_status = 0;
157         up->unit = (short) unit;
158         return (1);
159 }
160
161
162 /*
163  * hopfpci_shutdown - shut down the clock
164  */
165 static void
166 hopfpci_shutdown(
167         int unit,
168         struct peer *peer
169         )
170 {
171
172 #ifndef SYS_WINNT
173         close(fd);
174 #else
175         CloseHopfDevice();
176 #endif
177         if (NULL != peer->procptr->unitptr)
178                 free(peer->procptr->unitptr);
179 }
180
181
182 /*
183  * hopfpci_poll - called by the transmit procedure
184  */
185 static void
186 hopfpci_poll(
187         int unit,
188         struct peer *peer
189         )
190 {
191         struct refclockproc *pp;
192         HOPFTIME m_time;
193
194         pp = peer->procptr;
195
196 #ifndef SYS_WINNT
197         if (ioctl(fd, HOPF_CLOCK_GET_UTC, &m_time) < 0)
198                 msyslog(LOG_ERR, "HOPF_P(%d): HOPF_CLOCK_GET_UTC: %m",
199                         unit);
200 #else
201         GetHopfSystemTime(&m_time);
202 #endif
203         pp->polls++;
204
205         pp->day    = ymd2yd(m_time.wYear,m_time.wMonth,m_time.wDay);
206         pp->hour   = m_time.wHour;
207         pp->minute = m_time.wMinute;
208         pp->second = m_time.wSecond;
209         pp->nsec   = m_time.wMilliseconds * 1000000;
210         if (m_time.wStatus & LEWAPWAR)
211                 pp->leap = LEAP_ADDSECOND;
212         else
213                 pp->leap = LEAP_NOWARNING;
214
215         snprintf(pp->a_lastcode, sizeof(pp->a_lastcode),
216                  "ST: %02X T: %02d:%02d:%02d.%03ld D: %02d.%02d.%04d",
217                  m_time.wStatus, pp->hour, pp->minute, pp->second,
218                  pp->nsec / 1000000, m_time.wDay, m_time.wMonth,
219                  m_time.wYear);
220         pp->lencode = (u_short)strlen(pp->a_lastcode);
221
222         get_systime(&pp->lastrec);
223
224         /*
225          * If clock has no valid status then report error and exit
226          */
227         if ((m_time.wStatus & HOPF_OPMODE) == HOPF_INVALID) {  /* time ok? */
228                 refclock_report(peer, CEVNT_BADTIME);
229                 pp->leap = LEAP_NOTINSYNC;
230                 return;
231         }
232
233         /*
234          * Test if time is running on internal quarz
235          * if CLK_FLAG1 is set, sychronize even if no radio operation
236          */
237
238         if ((m_time.wStatus & HOPF_OPMODE) == HOPF_INTERNAL){
239                 if ((pp->sloppyclockflag & CLK_FLAG1) == 0) {
240                         refclock_report(peer, CEVNT_BADTIME);
241                         pp->leap = LEAP_NOTINSYNC;
242                         return;
243                 }
244         }
245
246         if (!refclock_process(pp)) {
247                 refclock_report(peer, CEVNT_BADTIME);
248                 return;
249         }
250         pp->lastref = pp->lastrec;
251         refclock_receive(peer);
252         record_clock_stats(&peer->srcadr, pp->a_lastcode);
253         return;
254 }
255
256 #else
257 int refclock_hopfpci_bs;
258 #endif /* REFCLOCK */