1 /* $NetBSD: refclock_hopfpci.c,v 1.2 2003/12/04 16:23:37 drochner Exp $ */
6 * - clock driver for hopf 6039 PCI board (GPS or DCF77)
7 * Bernd Altmeier altmeier@atlsoft.de
9 * latest source and further information can be found at:
10 * http://www.ATLSoft.de/ntp
12 * In order to run this driver you have to install and test
13 * the PCI-board driver for your system first.
17 * The driver attempts to open the device /dev/hopf6039 .
18 * The device entry will be made by the installation process of
19 * the kernel module for the PCI-bus board. The driver sources
20 * belongs to the delivery equipment of the PCI-board.
24 * The driver attempts to open the device by calling the function
25 * "OpenHopfDevice()". This function will be installed by the
26 * Device Driver for the PCI-bus board. The driver belongs to the
27 * delivery equipment of the PCI-board.
30 * Start 21.03.2000 Revision: 01.20
31 * changes 22.12.2000 Revision: 01.40 flag1 = 1 sync even if Quarz
39 #if defined(REFCLOCK) && defined(CLOCK_HOPF_PCI)
43 #include "ntp_refclock.h"
44 #include "ntp_unixtime.h"
45 #include "ntp_stdlib.h"
53 # include <sys/ioctl.h>
57 # include "hopf6039.h"
59 # include "hopf_PCI_io.h"
63 * hopfpci interface definitions
65 #define PRECISION (-10) /* precision assumed (1 ms) */
66 #define REFID "hopf" /* reference ID */
67 #define DESCRIPTION "hopf Elektronik PCI radio board"
69 #define NSAMPLES 3 /* stages of median filter */
71 # define DEVICE "/dev/hopf6039" /* device name inode*/
73 # define DEVICE "hopf6039" /* device name WinNT */
76 #define LEWAPWAR 0x20 /* leap second warning bit */
78 #define HOPF_OPMODE 0xC0 /* operation mode mask */
79 #define HOPF_INVALID 0x00 /* no time code available */
80 #define HOPF_INTERNAL 0x40 /* internal clock */
81 #define HOPF_RADIO 0x80 /* radio clock */
82 #define HOPF_RADIOHP 0xC0 /* high precision radio clock */
86 * hopfclock unit control structure.
88 struct hopfclock_unit
{
89 short unit
; /* NTP refclock unit number */
90 char leap_status
; /* leap second flag */
92 int fd
; /* file descr. */
97 static int hopfpci_start (int, struct peer
*);
98 static void hopfpci_shutdown (int, struct peer
*);
99 static void hopfpci_poll (int unit
, struct peer
*);
104 struct refclock refclock_hopfpci
= {
105 hopfpci_start
, /* start up driver */
106 hopfpci_shutdown
, /* shut down driver */
107 hopfpci_poll
, /* transmit poll message */
108 noentry
, /* not used */
109 noentry
, /* initialize driver (not used) */
110 noentry
, /* not used */
111 NOFLAGS
/* not used */
115 * hopfpci_start - attach to hopf PCI board 6039
123 struct refclockproc
*pp
;
124 struct hopfclock_unit
*up
;
127 * Allocate and initialize unit structure
129 up
= (struct hopfclock_unit
*) emalloc(sizeof(struct hopfclock_unit
));
132 msyslog(LOG_ERR
, "hopfPCIClock(%d) emalloc: %m",unit
);
134 printf("hopfPCIClock(%d) emalloc\n",unit
);
138 memset((char *)up
, 0, sizeof(struct hopfclock_unit
));
142 fd
= open(DEVICE
,O_RDWR
); /* try to open hopf clock device */
145 if (!OpenHopfDevice()){
146 msyslog(LOG_ERR
,"Start: %s unit: %d failed!",DEVICE
,unit
);
152 pp
->io
.clock_recv
= noentry
;
153 pp
->io
.srcclock
= (caddr_t
)peer
;
155 pp
->io
.fd
= INVALID_SOCKET
;
156 pp
->unitptr
= (caddr_t
)up
;
158 get_systime(&pp
->lastrec
);
161 * Initialize miscellaneous peer variables
163 if (pp
->unitptr
!=0) {
164 memcpy((char *)&pp
->refid
, REFID
, 4);
165 peer
->precision
= PRECISION
;
166 pp
->clockdesc
= DESCRIPTION
;
168 up
->unit
= (short) unit
;
178 * hopfpci_shutdown - shut down the clock
196 * hopfpci_poll - called by the transmit procedure
204 struct refclockproc
*pp
;
210 ioctl(fd
,HOPF_CLOCK_GET_UTC
,&m_time
);
212 GetHopfSystemTime(&m_time
);
216 pp
->day
= ymd2yd(m_time
.wYear
,m_time
.wMonth
,m_time
.wDay
);
217 pp
->hour
= m_time
.wHour
;
218 pp
->minute
= m_time
.wMinute
;
219 pp
->second
= m_time
.wSecond
;
220 pp
->nsec
= m_time
.wMilliseconds
* 1000000;
221 if (m_time
.wStatus
& LEWAPWAR
)
222 pp
->leap
= LEAP_ADDSECOND
;
224 pp
->leap
= LEAP_NOWARNING
;
226 sprintf(pp
->a_lastcode
,"ST: %02X T: %02d:%02d:%02d.%03ld D: %02d.%02d.%04d",
227 m_time
.wStatus
, pp
->hour
, pp
->minute
, pp
->second
,
228 pp
->nsec
/ 1000000, m_time
.wDay
, m_time
.wMonth
, m_time
.wYear
);
229 pp
->lencode
= (u_short
)strlen(pp
->a_lastcode
);
231 get_systime(&pp
->lastrec
);
234 * If clock has no valid status then report error and exit
236 if ((m_time
.wStatus
& HOPF_OPMODE
) == HOPF_INVALID
) { /* time ok? */
237 refclock_report(peer
, CEVNT_BADTIME
);
238 pp
->leap
= LEAP_NOTINSYNC
;
243 * Test if time is running on internal quarz
244 * if CLK_FLAG1 is set, sychronize even if no radio operation
247 if ((m_time
.wStatus
& HOPF_OPMODE
) == HOPF_INTERNAL
){
248 if ((pp
->sloppyclockflag
& CLK_FLAG1
) == 0) {
249 refclock_report(peer
, CEVNT_BADTIME
);
250 pp
->leap
= LEAP_NOTINSYNC
;
255 if (!refclock_process(pp
)) {
256 refclock_report(peer
, CEVNT_BADTIME
);
259 pp
->lastref
= pp
->lastrec
;
260 refclock_receive(peer
);
261 record_clock_stats(&peer
->srcadr
, pp
->a_lastcode
);
266 int refclock_hopfpci_bs
;
267 #endif /* REFCLOCK */