Initial import from FreeBSD RELENG_4:
[dragonfly.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 <assert.h>
52 # include <unistd.h>
53 # include <stdio.h>
54 # include "hopf6039.h"
55 #else
56 # include "hopf_PCI_io.h"
57 #endif
58
59 /*
60  * hopfpci interface definitions
61  */
62 #define PRECISION       (-10)    /* precision assumed (1 ms) */
63 #define REFID           "hopf"   /* reference ID */
64 #define DESCRIPTION     "hopf Elektronik PCI radio board"
65
66 #define NSAMPLES        3       /* stages of median filter */
67 #ifndef SYS_WINNT
68 # define        DEVICE  "/dev/hopf6039"         /* device name inode*/
69 #else
70 # define        DEVICE  "hopf6039"      /* device name WinNT  */
71 #endif
72
73 #define LEWAPWAR        0x20    /* leap second warning bit */
74
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 */
80
81
82 /*
83  * hopfclock unit control structure.
84  */
85 struct hopfclock_unit {
86         short   unit;           /* NTP refclock unit number */
87         char    leap_status;    /* leap second flag */
88 };
89 int     fd;                     /* file descr. */
90
91 /*
92  * Function prototypes
93  */
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 *);
97
98 /*
99  * Transfer vector
100  */
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 */
109 };
110
111 /*
112  * hopfpci_start - attach to hopf PCI board 6039
113  */
114 static int
115 hopfpci_start(
116         int unit,
117         struct peer *peer
118         )
119 {
120         struct refclockproc *pp;
121         struct hopfclock_unit *up;
122
123         /*
124          * Allocate and initialize unit structure
125          */
126         up = (struct hopfclock_unit *) emalloc(sizeof(struct hopfclock_unit));
127
128         if (!(up)) {
129                 msyslog(LOG_ERR, "hopfPCIClock(%d) emalloc: %m",unit);
130 #ifdef DEBUG
131                 printf("hopfPCIClock(%d) emalloc\n",unit);
132 #endif
133                 return (0);
134         }
135         memset((char *)up, 0, sizeof(struct hopfclock_unit));
136
137 #ifndef SYS_WINNT
138
139         fd = open(DEVICE,O_RDWR); /* try to open hopf clock device */
140
141 #else
142         if (!OpenHopfDevice()){
143                 msyslog(LOG_ERR,"Start: %s unit: %d failed!",DEVICE,unit);
144                 return (0);
145         }
146 #endif
147
148         pp = peer->procptr;
149         pp->io.clock_recv = noentry;
150         pp->io.srcclock = (caddr_t)peer;
151         pp->io.datalen = 0;
152         pp->io.fd = -1;
153         pp->unitptr = (caddr_t)up;
154
155         get_systime(&pp->lastrec);
156
157         /*
158          * Initialize miscellaneous peer variables
159          */
160         if (pp->unitptr!=0) {
161                 memcpy((char *)&pp->refid, REFID, 4);
162                 peer->precision = PRECISION;
163                 pp->clockdesc = DESCRIPTION;
164                 up->leap_status = 0;
165                 up->unit = (short) unit;
166                 return (1);
167         }
168         else {
169                 return 0;
170         }
171 }
172
173
174 /*
175  * hopfpci_shutdown - shut down the clock
176  */
177 static void
178 hopfpci_shutdown(
179         int unit,
180         struct peer *peer
181         )
182 {
183         struct refclockproc *pp;
184         register struct hopfpciTime *up;
185
186         pp = peer->procptr;
187         up = (struct hopfpciTime *)pp->unitptr;
188
189 #ifndef SYS_WINNT
190         close(fd);
191 #else
192         CloseHopfDevice();
193 //      UnmapViewOfFile (up);
194 #endif
195 }
196
197
198 /*
199  * hopfpci_poll - called by the transmit procedure
200  */
201 static void
202 hopfpci_poll(
203         int unit,
204         struct peer *peer
205         )
206 {
207         struct refclockproc *pp;
208         register struct hopfpciTime *up;
209         HOPFTIME m_time;
210
211         pp = peer->procptr;
212         up = (struct hopfpciTime *)pp->unitptr;
213
214 #ifndef SYS_WINNT
215         ioctl(fd,HOPF_CLOCK_GET_UTC,&m_time);
216 #else
217         GetHopfSystemTime(&m_time);
218 #endif
219         pp->polls++;
220
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;
226         pp->usec=0;
227         if (m_time.wStatus & LEWAPWAR)
228                 pp->leap = LEAP_ADDSECOND;
229         else
230                 pp->leap = LEAP_NOWARNING;
231
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);
236
237         get_systime(&pp->lastrec);
238
239         /*
240          * If clock has no valid status then report error and exit
241          */
242         if ((m_time.wStatus & HOPF_OPMODE) == HOPF_INVALID) {  /* time ok? */
243                 refclock_report(peer, CEVNT_BADTIME);
244                 pp->leap = LEAP_NOTINSYNC;
245                 return;
246         }
247
248         /*
249          * Test if time is running on internal quarz
250          * if CLK_FLAG1 is set, sychronize even if no radio operation
251          */
252
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;
257                         return;
258                 }
259         }
260
261         if (!refclock_process(pp)) {
262                 refclock_report(peer, CEVNT_BADTIME);
263                 return;
264         }
265         refclock_receive(peer);
266
267         record_clock_stats(&peer->srcadr, pp->a_lastcode);
268
269         return;
270 }
271
272 #else
273 int refclock_hopfpci_bs;
274 #endif /* REFCLOCK */