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 */ 275