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