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