summaryrefslogtreecommitdiff
path: root/contrib/ntp/ntpd/refclock_bancomm.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/ntp/ntpd/refclock_bancomm.c')
-rw-r--r--contrib/ntp/ntpd/refclock_bancomm.c119
1 files changed, 96 insertions, 23 deletions
diff --git a/contrib/ntp/ntpd/refclock_bancomm.c b/contrib/ntp/ntpd/refclock_bancomm.c
index 49922e39345c..577ad277213c 100644
--- a/contrib/ntp/ntpd/refclock_bancomm.c
+++ b/contrib/ntp/ntpd/refclock_bancomm.c
@@ -60,6 +60,9 @@
#include <stdio.h>
#include <syslog.h>
#include <ctype.h>
+#ifdef HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
struct btfp_time /* Structure for reading 5 time words */
/* in one ioctl(2) operation. */
@@ -74,17 +77,16 @@ struct btfp_time /* Structure for reading 5 time words */
#define IOCIOWN( l, n, s ) ( BTFPIOC | n )
/***** Simple ioctl commands *****/
-#define RUNLOCK IOCIOR(b, 19, int ) /* Release Capture Lockout */
-#define RCR0 IOCIOR(b, 22, int ) /* Read control register zero.*/
-#define WCR0 IOCIOWN(b, 23, int) /* Write control register zero*/
+#define RUNLOCK IOCIOR(b, 19, int ) /* Release Capture Lockout */
+#define RCR0 IOCIOR(b, 22, int ) /* Read control register zero.*/
+#define WCR0 IOCIOWN(b, 23, int) /* Write control register zero*/
/***** Compound ioctl commands *****/
/* Read all 5 time words in one call. */
-#define READTIME IOCIORN(b, 32, sizeof( struct btfp_time ))
-
#if defined(__FreeBSD__)
-#undef READTIME
-#define READTIME _IOR('u', 5, struct btfp_time )
+# define READTIME _IOR('u', 5, struct btfp_time )
+#else
+# define READTIME IOCIORN(b, 32, sizeof( struct btfp_time ))
#endif
/* Solaris specific section */
@@ -165,18 +167,76 @@ static void vme_poll (int unit, struct peer *);
struct vmedate *get_datumtime(struct vmedate *);
void tvme_fill(struct vmedate *, uint32_t btm[2]);
void stfp_time2tvme(struct vmedate *time_vme, struct stfp_time *stfp);
-inline const char *DEVICE_NAME(int n);
+static const char *get_devicename(int n);
+/* [Bug 3558] and [Bug 1674] perlinger@ntp.org says:
+ *
+ * bcReadBinTime() is defined to use two DWORD pointers on Windows and
+ * Linux in the BANCOMM SDK. DWORD is of course Windows-specific
+ * (*shudder*), and it is defined as 'unsigned long' under
+ * Linux/Unix. (*sigh*)
+ *
+ * This creates quite some headache. The size of 'unsigned long' is
+ * platform/compiler/memory-model dependent (LP32 vs LP64 vs LLP64),
+ * while the card itself always creates 32bit time stamps. What a
+ * bummer. And DWORD has tendency to contain 64bit on Win64 (which is
+ * why we have a DWORD32 defined on Win64) so it can be used as
+ * substitute for 'UINT_PTR' in Windows API headers. I won't even try
+ * to comment on that, because anything I have to say will not be civil.
+ *
+ * We work around this by possibly using a wrapper function that makes
+ * the necessary conversions/casts. It might be a bit tricky to
+ * maintain the conditional logic below, but any lingering disease needs
+ * constant care to avoid a breakout.
+ */
+#if defined(__linux__)
+ typedef unsigned long bcBinTimeT;
+# if SIZEOF_LONG == 4
+# define safeReadBinTime bcReadBinTime
+# endif
+#elif defined(SYS_WINNT)
+ typedef DWORD bcBinTimeT;
+# if !defined(_WIN64) || _WIN64 == 0
+# define safeReadBinTime bcReadBinTime
+# endif
+#else
+ typedef uint32_t bcBinTimeT;
+# define safeReadBinTime bcReadBinTime
+#endif
/*
* Define the bc*() functions as weak so we can compile/link without them.
* Only clients with the card will have the proprietary vendor device driver
* and interface library needed for use on Linux/Windows platforms.
*/
-extern uint32_t __attribute__ ((weak)) bcReadBinTime(SYMMT_PCI_HANDLE, uint32_t *, uint32_t*, uint8_t*);
+extern uint32_t __attribute__ ((weak)) bcReadBinTime(SYMMT_PCI_HANDLE, bcBinTimeT*, bcBinTimeT*, uint8_t*);
extern SYMMT_PCI_HANDLE __attribute__ ((weak)) bcStartPci(void);
extern void __attribute__ ((weak)) bcStopPci(SYMMT_PCI_HANDLE);
+/* This is the conversion wrapper for the long/DWORD/uint32_t clash in
+ * reading binary times.
+ */
+#ifndef safeReadBinTime
+static uint32_t
+safeReadBinTime(
+ SYMMT_PCI_HANDLE hnd,
+ uint32_t *pt1,
+ uint32_t *pt2,
+ uint8_t *p3
+ )
+{
+ bcBinTimeT t1, t2;
+ uint32_t rc;
+
+ rc = bcReadBinTime(hnd, &t1, &t2, p3);
+ if (rc != 0) {
+ *pt1 = (uint32_t)t1;
+ *pt2 = (uint32_t)t2;
+ }
+ return rc;
+}
+#endif /* !defined(safeReadBinTime) */
+
/*
* Transfer vector
*/
@@ -195,15 +255,27 @@ int regvalue;
int tfp_type; /* mode selector, indicate platform and driver interface */
SYMMT_PCI_HANDLE stfp_handle;
-/**
- * this macro returns the device name based on
- * the platform we are running on and the device number
+/* This helper function returns the device name based on the platform we
+ * are running on and the device number.
+ *
+ * Uses a static buffer, so the result is valid only to the next call of
+ * this function!
*/
-#if defined(__sun__)
-inline const char *DEVICE_NAME(int n) {static char s[20]={0}; snprintf(s,19,"/dev/stfp%d",n);return s;}
-#else
-inline const char* DEVICE_NAME(int n) {static char s[20]={0}; snprintf(s,19,"/dev/btfp%d",n);return s;}
-#endif /**__sun__**/
+static const char*
+get_devicename(int n)
+{
+
+# if defined(__sun__)
+ static const char * const template ="/dev/stfp%d";
+# else
+ static const char * const template ="/dev/btfp%d";
+# endif
+ static char namebuf[20];
+
+ snprintf(namebuf, sizeof(namebuf), template, n);
+ namebuf[sizeof(namebuf)-1] = '\0'; /* paranoia rulez! */
+ return namebuf;
+}
/*
* vme_start - open the VME device and initialize data for processing
@@ -235,9 +307,9 @@ vme_start(
*/
#ifdef DEBUG
- printf("Opening DATUM DEVICE %s\n",DEVICE_NAME(peer->refclkunit));
+ printf("Opening DATUM DEVICE %s\n",get_devicename(peer->refclkunit));
#endif
- if ( (fd_vme = open(DEVICE_NAME(peer->refclkunit), O_RDWR)) < 0) {
+ if ( (fd_vme = open(get_devicename(peer->refclkunit), O_RDWR)) < 0) {
msyslog(LOG_ERR, "vme_start: failed open of %s: %m", vmedev);
return (0);
}
@@ -433,7 +505,7 @@ get_datumtime(struct vmedate *time_vme)
break;
case 2: /* Linux/Windows, PCI, 2 32bit time words */
- if (bcReadBinTime(stfp_handle, &btm[1], &btm[0], &dmy) == 0) {
+ if (safeReadBinTime(stfp_handle, &btm[1], &btm[0], &dmy) == 0) {
msyslog(LOG_ERR, "get_datumtime error: %m");
return(NULL);
}
@@ -512,10 +584,11 @@ void
tvme_fill(struct vmedate *time_vme, uint32_t btm[2])
{
struct tm maj;
- uint32_t dmaj, dmin;
+ time_t dmaj;
+ uint32_t dmin;
- dmaj = btm[1]; /* syntax sugar */
- dmin = btm[0];
+ dmaj = btm[1]; /* syntax sugar & expansion */
+ dmin = btm[0]; /* just syntax sugar */
gmtime_r(&dmaj, &maj);
time_vme->day = maj.tm_yday+1;