4 * - clock driver for hopf 6039 PCI board (GPS or DCF77)
5 * Bernd Altmeier altmeier@atlsoft.de
7 * latest source and further information can be found at:
8 * http://www.ATLSoft.de/ntp
10 * In order to run this driver you have to install and test
11 * the PCI-board driver for your system first.
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.
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.
28 * Start 21.03.2000 Revision: 01.20
29 * changes 22.12.2000 Revision: 01.40 flag1 = 1 sync even if Quarz
37 #if defined(REFCLOCK) && defined(CLOCK_HOPF_PCI)
41 #include "ntp_refclock.h"
42 #include "ntp_unixtime.h"
43 #include "ntp_stdlib.h"
54 # include "hopf6039.h"
56 # include "hopf_PCI_io.h"
60 * hopfpci interface definitions
62 #define PRECISION (-10) /* precision assumed (1 ms) */
63 #define REFID "hopf" /* reference ID */
64 #define DESCRIPTION "hopf Elektronik PCI radio board"
66 #define NSAMPLES 3 /* stages of median filter */
68 # define DEVICE "/dev/hopf6039" /* device name inode*/
70 # define DEVICE "hopf6039" /* device name WinNT */
73 #define LEWAPWAR 0x20 /* leap second warning bit */
75 #define HOPF_OPMODE 0xC0 /* operation mode mask */
76 #define HOPF_INVALID 0x00 /* no time code available */
77 #define HOPF_INTERNAL 0x40 /* internal clock */
78 #define HOPF_RADIO 0x80 /* radio clock */
79 #define HOPF_RADIOHP 0xC0 /* high precision radio clock */
83 * hopfclock unit control structure.
85 struct hopfclock_unit {
86 short unit; /* NTP refclock unit number */
87 char leap_status; /* leap second flag */
89 int fd; /* file descr. */
94 static int hopfpci_start (int, struct peer *);
95 static void hopfpci_shutdown (int, struct peer *);
96 static void hopfpci_poll (int unit, struct peer *);
101 struct refclock refclock_hopfpci = {
102 hopfpci_start, /* start up driver */
103 hopfpci_shutdown, /* shut down driver */
104 hopfpci_poll, /* transmit poll message */
105 noentry, /* not used */
106 noentry, /* initialize driver (not used) */
107 noentry, /* not used */
108 NOFLAGS /* not used */
112 * hopfpci_start - attach to hopf PCI board 6039
120 struct refclockproc *pp;
121 struct hopfclock_unit *up;
124 * Allocate and initialize unit structure
126 up = (struct hopfclock_unit *) emalloc(sizeof(struct hopfclock_unit));
129 msyslog(LOG_ERR, "hopfPCIClock(%d) emalloc: %m",unit);
131 printf("hopfPCIClock(%d) emalloc\n",unit);
135 memset((char *)up, 0, sizeof(struct hopfclock_unit));
139 fd = open(DEVICE,O_RDWR); /* try to open hopf clock device */
142 if (!OpenHopfDevice()){
143 msyslog(LOG_ERR,"Start: %s unit: %d failed!",DEVICE,unit);
149 pp->io.clock_recv = noentry;
150 pp->io.srcclock = (caddr_t)peer;
153 pp->unitptr = (caddr_t)up;
155 get_systime(&pp->lastrec);
158 * Initialize miscellaneous peer variables
160 if (pp->unitptr!=0) {
161 memcpy((char *)&pp->refid, REFID, 4);
162 peer->precision = PRECISION;
163 pp->clockdesc = DESCRIPTION;
165 up->unit = (short) unit;
175 * hopfpci_shutdown - shut down the clock
183 struct refclockproc *pp;
184 register struct hopfpciTime *up;
187 up = (struct hopfpciTime *)pp->unitptr;
193 // UnmapViewOfFile (up);
199 * hopfpci_poll - called by the transmit procedure
207 struct refclockproc *pp;
208 register struct hopfpciTime *up;
212 up = (struct hopfpciTime *)pp->unitptr;
215 ioctl(fd,HOPF_CLOCK_GET_UTC,&m_time);
217 GetHopfSystemTime(&m_time);
221 pp->day = ymd2yd(m_time.wYear,m_time.wMonth,m_time.wDay);
222 pp->hour = m_time.wHour;
223 pp->minute = m_time.wMinute;
224 pp->second = m_time.wSecond;
225 pp->msec=m_time.wMilliseconds;
227 if (m_time.wStatus & LEWAPWAR)
228 pp->leap = LEAP_ADDSECOND;
230 pp->leap = LEAP_NOWARNING;
232 sprintf(pp->a_lastcode,"ST: %02X T: %02d:%02d:%02d.%03d D: %02d.%02d.%04d",
233 m_time.wStatus, pp->hour, pp->minute, pp->second, pp->msec,
234 m_time.wDay, m_time.wMonth, m_time.wYear);
235 pp->lencode = strlen(pp->a_lastcode);
237 get_systime(&pp->lastrec);
240 * If clock has no valid status then report error and exit
242 if ((m_time.wStatus & HOPF_OPMODE) == HOPF_INVALID) { /* time ok? */
243 refclock_report(peer, CEVNT_BADTIME);
244 pp->leap = LEAP_NOTINSYNC;
249 * Test if time is running on internal quarz
250 * if CLK_FLAG1 is set, sychronize even if no radio operation
253 if ((m_time.wStatus & HOPF_OPMODE) == HOPF_INTERNAL){
254 if ((pp->sloppyclockflag & CLK_FLAG1) == 0) {
255 refclock_report(peer, CEVNT_BADTIME);
256 pp->leap = LEAP_NOTINSYNC;
261 if (!refclock_process(pp)) {
262 refclock_report(peer, CEVNT_BADTIME);
265 refclock_receive(peer);
267 record_clock_stats(&peer->srcadr, pp->a_lastcode);
273 int refclock_hopfpci_bs;
274 #endif /* REFCLOCK */