/src/ntp-dev/ntpd/refclock_hopfpci.c
Line | Count | Source (jump to first uncovered line) |
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 | 0 | #define PRECISION (-10) /* precision assumed (1 ms) */ |
64 | 0 | #define REFID "hopf" /* reference ID */ |
65 | 0 | #define DESCRIPTION "hopf Elektronik PCI radio board" |
66 | | |
67 | | #define NSAMPLES 3 /* stages of median filter */ |
68 | | #ifndef SYS_WINNT |
69 | 0 | # define DEVICE "/dev/hopf6039" /* device name inode*/ |
70 | | #else |
71 | | # define DEVICE "hopf6039" /* device name WinNT */ |
72 | | #endif |
73 | | |
74 | 0 | #define LEWAPWAR 0x20 /* leap second warning bit */ |
75 | | |
76 | 0 | #define HOPF_OPMODE 0xC0 /* operation mode mask */ |
77 | 0 | #define HOPF_INVALID 0x00 /* no time code available */ |
78 | 0 | #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 | 0 | { |
121 | 0 | struct refclockproc *pp; |
122 | 0 | struct hopfclock_unit *up; |
123 | | |
124 | | /* |
125 | | * Allocate and initialize unit structure |
126 | | */ |
127 | 0 | up = emalloc_zero(sizeof(*up)); |
128 | |
|
129 | 0 | #ifndef SYS_WINNT |
130 | |
|
131 | 0 | 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 | 0 | pp = peer->procptr; |
142 | 0 | pp->io.clock_recv = noentry; |
143 | 0 | pp->io.srcclock = peer; |
144 | 0 | pp->io.datalen = 0; |
145 | 0 | pp->io.fd = INVALID_SOCKET; |
146 | 0 | pp->unitptr = up; |
147 | |
|
148 | 0 | get_systime(&pp->lastrec); |
149 | | |
150 | | /* |
151 | | * Initialize miscellaneous peer variables |
152 | | */ |
153 | 0 | memcpy((char *)&pp->refid, REFID, 4); |
154 | 0 | peer->precision = PRECISION; |
155 | 0 | pp->clockdesc = DESCRIPTION; |
156 | 0 | up->leap_status = 0; |
157 | 0 | up->unit = (short) unit; |
158 | 0 | return (1); |
159 | 0 | } |
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 | 0 | { |
171 | |
|
172 | 0 | #ifndef SYS_WINNT |
173 | 0 | close(fd); |
174 | | #else |
175 | | CloseHopfDevice(); |
176 | | #endif |
177 | 0 | if (NULL != peer->procptr->unitptr) |
178 | 0 | free(peer->procptr->unitptr); |
179 | 0 | } |
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 | 0 | { |
191 | 0 | struct refclockproc *pp; |
192 | 0 | HOPFTIME m_time; |
193 | |
|
194 | 0 | pp = peer->procptr; |
195 | |
|
196 | 0 | #ifndef SYS_WINNT |
197 | 0 | if (ioctl(fd, HOPF_CLOCK_GET_UTC, &m_time) < 0) |
198 | 0 | msyslog(LOG_ERR, "HOPF_P(%d): HOPF_CLOCK_GET_UTC: %m", |
199 | 0 | unit); |
200 | | #else |
201 | | GetHopfSystemTime(&m_time); |
202 | | #endif |
203 | 0 | pp->polls++; |
204 | |
|
205 | 0 | pp->day = ymd2yd(m_time.wYear,m_time.wMonth,m_time.wDay); |
206 | 0 | pp->hour = m_time.wHour; |
207 | 0 | pp->minute = m_time.wMinute; |
208 | 0 | pp->second = m_time.wSecond; |
209 | 0 | pp->nsec = m_time.wMilliseconds * 1000000; |
210 | 0 | if (m_time.wStatus & LEWAPWAR) |
211 | 0 | pp->leap = LEAP_ADDSECOND; |
212 | 0 | else |
213 | 0 | pp->leap = LEAP_NOWARNING; |
214 | |
|
215 | 0 | snprintf(pp->a_lastcode, sizeof(pp->a_lastcode), |
216 | 0 | "ST: %02X T: %02d:%02d:%02d.%03ld D: %02d.%02d.%04d", |
217 | 0 | m_time.wStatus, pp->hour, pp->minute, pp->second, |
218 | 0 | pp->nsec / 1000000, m_time.wDay, m_time.wMonth, |
219 | 0 | m_time.wYear); |
220 | 0 | pp->lencode = (u_short)strlen(pp->a_lastcode); |
221 | |
|
222 | 0 | get_systime(&pp->lastrec); |
223 | | |
224 | | /* |
225 | | * If clock has no valid status then report error and exit |
226 | | */ |
227 | 0 | if ((m_time.wStatus & HOPF_OPMODE) == HOPF_INVALID) { /* time ok? */ |
228 | 0 | refclock_report(peer, CEVNT_BADTIME); |
229 | 0 | pp->leap = LEAP_NOTINSYNC; |
230 | 0 | return; |
231 | 0 | } |
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 | 0 | if ((m_time.wStatus & HOPF_OPMODE) == HOPF_INTERNAL){ |
239 | 0 | if ((pp->sloppyclockflag & CLK_FLAG1) == 0) { |
240 | 0 | refclock_report(peer, CEVNT_BADTIME); |
241 | 0 | pp->leap = LEAP_NOTINSYNC; |
242 | 0 | return; |
243 | 0 | } |
244 | 0 | } |
245 | | |
246 | 0 | if (!refclock_process(pp)) { |
247 | 0 | refclock_report(peer, CEVNT_BADTIME); |
248 | 0 | return; |
249 | 0 | } |
250 | 0 | pp->lastref = pp->lastrec; |
251 | 0 | refclock_receive(peer); |
252 | 0 | record_clock_stats(&peer->srcadr, pp->a_lastcode); |
253 | 0 | return; |
254 | 0 | } |
255 | | |
256 | | #else |
257 | | int refclock_hopfpci_bs; |
258 | | #endif /* REFCLOCK */ |