Blame SOURCES/ntp-4.2.6p5-tsyncdriver.patch

edcb74
diff -up ntp-4.2.6p5/config.h.in.tsyncdriver ntp-4.2.6p5/config.h.in
edcb74
--- ntp-4.2.6p5/config.h.in.tsyncdriver	2011-12-25 00:32:51.000000000 +0100
edcb74
+++ ntp-4.2.6p5/config.h.in	2017-09-19 11:01:08.267218957 +0200
edcb74
@@ -159,6 +159,9 @@
edcb74
 /* Zyfer GPStarplus */
edcb74
 #undef CLOCK_ZYFER
edcb74
 
edcb74
+/* Spectracom TSYNC PCI */
edcb74
+#undef CLOCK_TSYNCPCI
edcb74
+
edcb74
 /* Enable ntpd debugging code? */
edcb74
 #undef DEBUG
edcb74
 
edcb74
diff -up ntp-4.2.6p5/configure.tsyncdriver ntp-4.2.6p5/configure
edcb74
--- ntp-4.2.6p5/configure.tsyncdriver	2011-12-25 00:31:17.000000000 +0100
edcb74
+++ ntp-4.2.6p5/configure	2017-09-19 11:01:08.334221167 +0200
edcb74
@@ -22827,6 +22827,7 @@ esac
edcb74
 $as_echo "$ans" >&6; }
edcb74
 
edcb74
 
edcb74
+$as_echo "#define CLOCK_TSYNCPCI 1" >>confdefs.h
edcb74
 
edcb74
 
edcb74
 
edcb74
diff -up ntp-4.2.6p5/html/drivers/driver45.html.tsyncdriver ntp-4.2.6p5/html/drivers/driver45.html
edcb74
--- ntp-4.2.6p5/html/drivers/driver45.html.tsyncdriver	2017-09-19 11:01:08.269219023 +0200
edcb74
+++ ntp-4.2.6p5/html/drivers/driver45.html	2017-09-19 11:01:08.269219023 +0200
edcb74
@@ -0,0 +1,32 @@
edcb74
+
edcb74
+
edcb74
+<html>
edcb74
+
edcb74
+  <head>
edcb74
+    <meta http-equiv="content-type" content="text/html;charset=iso-8859-1">
edcb74
+    <title>Spectracom TSYNC PCI</title>
edcb74
+    <link href="scripts/style.css" type="text/css" rel="stylesheet">
edcb74
+  </head>
edcb74
+
edcb74
+  <body>
edcb74
+    

Spectracom TSYNC PCI

edcb74
+

Last update:

edcb74
+  26-Mar-2012  05:10
edcb74
+  UTC

edcb74
+    
edcb74
+    

Synopsis

edcb74
+    Address: 127.127.45.u
edcb74
+    Reference ID: one of <tt>GPS</tt>, <tt>IRIG</tt>, <tt>HVQ</tt>, <tt>FREQ</tt>, <tt>ACTS</tt>, <tt>PPS</tt>, <tt>PTP</tt>, <tt>ACT</tt>, <tt>USR</tt>, <tt>LOCL</tt>
edcb74
+    Driver ID: <tt>Spectracom TSYNC PCI</tt>
edcb74
+    Driver Port: <tt>/dev/tsyncpciu</tt>
edcb74
+    Features: <tt>(none)</tt>
edcb74
+    

Description

edcb74
+    

This driver supports the

edcb74
+	href="http://www.spectracomcorp.com/ProductsServices/TimingSynchronization/BuslevelTiming">Spectracom TSYNC PCI receiver.

edcb74
+    

Additional Information

edcb74
+    

Reference Clock Drivers

edcb74
+    
edcb74
+    <script type="text/javascript" language="javascript" src="scripts/footer.txt"></script>
edcb74
+  </body>
edcb74
+
edcb74
+</html>
edcb74
diff -up ntp-4.2.6p5/html/refclock.html.tsyncdriver ntp-4.2.6p5/html/refclock.html
edcb74
--- ntp-4.2.6p5/html/refclock.html.tsyncdriver	2009-12-09 08:36:36.000000000 +0100
edcb74
+++ ntp-4.2.6p5/html/refclock.html	2017-09-19 11:01:08.269219023 +0200
edcb74
@@ -82,9 +82,10 @@
edcb74
 			
  • Type 42 Zyfer GPStarplus Receiver
  • edcb74
     			
  • Type 43 RIPE NCC interface for Trimble Palisade
  • edcb74
     			
  • Type 44 NeoClock4X - DCF77 / TDF serial line
  • edcb74
    +			
  • Type 45 Spectracom TSYNC PCI
  • edcb74
     		
    edcb74
     		
    edcb74
     		<script type="text/javascript" language="javascript" src="scripts/footer.txt"></script>
    edcb74
     	</body>
    edcb74
     
    edcb74
    -</html>
    edcb74
    \ No newline at end of file
    edcb74
    +</html>
    edcb74
    diff -up ntp-4.2.6p5/include/ntp.h.tsyncdriver ntp-4.2.6p5/include/ntp.h
    edcb74
    --- ntp-4.2.6p5/include/ntp.h.tsyncdriver	2017-09-19 11:01:08.246218264 +0200
    edcb74
    +++ ntp-4.2.6p5/include/ntp.h	2017-09-19 11:01:08.269219023 +0200
    edcb74
    @@ -525,7 +525,8 @@ struct peer {
    edcb74
     #define REFCLK_ZYFER		42	/* Zyfer GPStarplus receiver  */
    edcb74
     #define REFCLK_RIPENCC		43	/* RIPE NCC Trimble driver */
    edcb74
     #define REFCLK_NEOCLOCK4X	44	/* NeoClock4X DCF77 or TDF receiver */
    edcb74
    -#define REFCLK_MAX		44	/* NeoClock4X DCF77 or TDF receiver */
    edcb74
    +#define REFCLK_TSYNCPCI		45	/* Spectracom TSYNC PCI timing board */
    edcb74
    +#define REFCLK_MAX		45	/* Spectracom TSYNC PCI timing board */
    edcb74
     
    edcb74
     
    edcb74
     /*
    edcb74
    diff -up ntp-4.2.6p5/libntp/clocktypes.c.tsyncdriver ntp-4.2.6p5/libntp/clocktypes.c
    edcb74
    --- ntp-4.2.6p5/libntp/clocktypes.c.tsyncdriver	2009-12-09 08:36:37.000000000 +0100
    edcb74
    +++ ntp-4.2.6p5/libntp/clocktypes.c	2017-09-19 11:01:08.270219055 +0200
    edcb74
    @@ -100,6 +100,8 @@ struct clktype clktypes[] = {
    edcb74
     	  "GPS_RIPENCC" },
    edcb74
     	{ REFCLK_NEOCLOCK4X,	"NeoClock4X DCF77 / TDF receiver (44)",
    edcb74
     	  "NEOCLK4X"},
    edcb74
    +	{ REFCLK_TSYNCPCI,	"Spectracom TSYNC PCI timing board (45)",
    edcb74
    +	  "PCI_TSYNC"},
    edcb74
     	{ -1,			"", "" }
    edcb74
     };
    edcb74
     
    edcb74
    diff -up ntp-4.2.6p5/ntpd/Makefile.in.tsyncdriver ntp-4.2.6p5/ntpd/Makefile.in
    edcb74
    --- ntp-4.2.6p5/ntpd/Makefile.in.tsyncdriver	2011-12-25 00:31:11.000000000 +0100
    edcb74
    +++ ntp-4.2.6p5/ntpd/Makefile.in	2017-09-19 11:01:08.270219055 +0200
    edcb74
    @@ -97,6 +97,7 @@ am_libntpd_a_OBJECTS = ntp_control.$(OBJ
    edcb74
     	refclock_tpro.$(OBJEXT) refclock_true.$(OBJEXT) \
    edcb74
     	refclock_tt560.$(OBJEXT) refclock_ulink.$(OBJEXT) \
    edcb74
     	refclock_wwv.$(OBJEXT) refclock_wwvb.$(OBJEXT) \
    edcb74
    +	refclock_tsyncpci.$(OBJEXT) \
    edcb74
     	refclock_zyfer.$(OBJEXT) $(am__objects_1)
    edcb74
     libntpd_a_OBJECTS = $(am_libntpd_a_OBJECTS)
    edcb74
     am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" \
    edcb74
    @@ -499,6 +500,7 @@ libntpd_a_SOURCES = \
    edcb74
     	refclock_wwv.c		\
    edcb74
     	refclock_wwvb.c		\
    edcb74
     	refclock_zyfer.c	\
    edcb74
    +	refclock_tsyncpci.c	\
    edcb74
     	$(NULL)
    edcb74
     
    edcb74
     all: $(BUILT_SOURCES)
    edcb74
    @@ -734,6 +736,7 @@ distclean-compile:
    edcb74
     @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_wwv.Po@am__quote@
    edcb74
     @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_wwvb.Po@am__quote@
    edcb74
     @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_zyfer.Po@am__quote@
    edcb74
    +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/refclock_tsyncpci.Po@am__quote@
    edcb74
     
    edcb74
     .c.o:
    edcb74
     @am__fastdepCC_TRUE@	$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
    edcb74
    diff -up ntp-4.2.6p5/ntpd/ntp_control.c.tsyncdriver ntp-4.2.6p5/ntpd/ntp_control.c
    edcb74
    --- ntp-4.2.6p5/ntpd/ntp_control.c.tsyncdriver	2017-09-19 11:01:08.266218923 +0200
    edcb74
    +++ ntp-4.2.6p5/ntpd/ntp_control.c	2017-09-19 11:01:08.270219055 +0200
    edcb74
    @@ -419,6 +419,7 @@ static u_char clocktypes[] = {
    edcb74
     	CTL_SST_TS_UHF,		/* REFCLK_ZYFER (42) */
    edcb74
     	CTL_SST_TS_UHF,		/* REFCLK_RIPENCC (43) */
    edcb74
     	CTL_SST_TS_UHF,		/* REFCLK_NEOCLOCK4X (44) */
    edcb74
    +	CTL_SST_TS_UHF,		/* REFCLK_TSYNCPCI (45) */
    edcb74
     };
    edcb74
     
    edcb74
     
    edcb74
    diff -up ntp-4.2.6p5/ntpd/refclock_conf.c.tsyncdriver ntp-4.2.6p5/ntpd/refclock_conf.c
    edcb74
    --- ntp-4.2.6p5/ntpd/refclock_conf.c.tsyncdriver	2011-01-04 02:57:27.000000000 +0100
    edcb74
    +++ ntp-4.2.6p5/ntpd/refclock_conf.c	2017-09-19 11:01:08.270219055 +0200
    edcb74
    @@ -258,6 +258,12 @@ extern	struct refclock	refclock_neoclock
    edcb74
     #define	refclock_neoclock4x	refclock_none
    edcb74
     #endif
    edcb74
     
    edcb74
    +#ifdef CLOCK_TSYNCPCI
    edcb74
    +extern struct refclock refclock_tsyncpci;
    edcb74
    +#else
    edcb74
    +#define refclock_tsyncpci refclock_none
    edcb74
    +#endif
    edcb74
    +
    edcb74
     /*
    edcb74
      * Order is clock_start(), clock_shutdown(), clock_poll(),
    edcb74
      * clock_control(), clock_init(), clock_buginfo, clock_flags;
    edcb74
    @@ -309,7 +315,8 @@ struct refclock * const refclock_conf[]
    edcb74
     	&refclock_tt560,	/* 41 REFCLK_TT560 */
    edcb74
     	&refclock_zyfer,	/* 42 REFCLK_ZYFER */
    edcb74
     	&refclock_ripencc,	/* 43 REFCLK_RIPENCC */
    edcb74
    -	&refclock_neoclock4x    /* 44 REFCLK_NEOCLOCK4X */
    edcb74
    +	&refclock_neoclock4x,	/* 44 REFCLK_NEOCLOCK4X */
    edcb74
    +	&refclock_tsyncpci	/* 45 REFCLK_TSYNCPCI */
    edcb74
     };
    edcb74
     
    edcb74
     u_char num_refclock_conf = sizeof(refclock_conf)/sizeof(struct refclock *);
    edcb74
    diff -up ntp-4.2.6p5/ntpd/refclock_tsyncpci.c.tsyncdriver ntp-4.2.6p5/ntpd/refclock_tsyncpci.c
    edcb74
    --- ntp-4.2.6p5/ntpd/refclock_tsyncpci.c.tsyncdriver	2017-09-19 11:01:08.271219088 +0200
    edcb74
    +++ ntp-4.2.6p5/ntpd/refclock_tsyncpci.c	2017-09-19 11:04:55.261709585 +0200
    edcb74
    @@ -0,0 +1,922 @@
    edcb74
    +/*******************************************************************************
    edcb74
    +*
    edcb74
    +*  Module  : refclock_tsyncpci.c
    edcb74
    +*  Date    : 09/08/08
    edcb74
    +*  Purpose : Implements a reference clock driver for the NTP daemon.  This
    edcb74
    +*            reference clock driver provides a means to communicate with
    edcb74
    +*            the Spectracom TSYNC PCI timing devices and use them as a time
    edcb74
    +*            source.
    edcb74
    +*
    edcb74
    +*  (C) Copyright 2008 Spectracom Corporation
    edcb74
    +*
    edcb74
    +*  This software is provided by Spectracom Corporation 'as is' and
    edcb74
    +*  any express or implied warranties, including, but not limited to, the
    edcb74
    +*  implied warranties of merchantability and fitness for a particular purpose
    edcb74
    +*  are disclaimed.  In no event shall Spectracom Corporation be liable
    edcb74
    +*  for any direct, indirect, incidental, special, exemplary, or consequential
    edcb74
    +*  damages (including, but not limited to, procurement of substitute goods
    edcb74
    +*  or services; loss of use, data, or profits; or business interruption)
    edcb74
    +*  however caused and on any theory of liability, whether in contract, strict
    edcb74
    +*  liability, or tort (including negligence or otherwise) arising in any way
    edcb74
    +*  out of the use of this software, even if advised of the possibility of
    edcb74
    +*  such damage.
    edcb74
    +*
    edcb74
    +*  This software is released for distribution according to the NTP copyright
    edcb74
    +*  and license contained in html/copyright.html of NTP source.
    edcb74
    +*
    edcb74
    +*******************************************************************************/
    edcb74
    +#ifdef HAVE_CONFIG_H
    edcb74
    +#include <config.h>
    edcb74
    +#endif
    edcb74
    +
    edcb74
    +#if defined(REFCLOCK) && defined(CLOCK_TSYNCPCI)
    edcb74
    +
    edcb74
    +#include <asm/ioctl.h>
    edcb74
    +#ifdef HAVE_SYS_IOCTL_H
    edcb74
    +# include <sys/ioctl.h>
    edcb74
    +#endif
    edcb74
    +
    edcb74
    +#include <stdio.h>
    edcb74
    +#include <ctype.h>
    edcb74
    +#include <netinet/in.h>
    edcb74
    +
    edcb74
    +
    edcb74
    +#include "ntpd.h"
    edcb74
    +#include "ntp_io.h"
    edcb74
    +#include "ntp_refclock.h"
    edcb74
    +#include "ntp_unixtime.h"
    edcb74
    +#include "ntp_stdlib.h"
    edcb74
    +#include "ntp_calendar.h"
    edcb74
    +
    edcb74
    +
    edcb74
    +/*******************************************************************************
    edcb74
    +**
    edcb74
    +** This driver supports the Spectracom TSYNC PCI GPS receiver.  It requires
    edcb74
    +** that the tsyncpci.o device driver be installed and loaded.
    edcb74
    +**
    edcb74
    +*******************************************************************************/
    edcb74
    +
    edcb74
    +#define TSYNC_PCI_REVISION "1.11"
    edcb74
    +
    edcb74
    +/*
    edcb74
    +** TPRO interface definitions
    edcb74
    +*/
    edcb74
    +#define DEVICE      "/dev/tsyncpci"             /* device name */
    edcb74
    +#define PRECISION   (-20)                       /* precision assumed (1 us) */
    edcb74
    +#define DESCRIPTION "Spectracom TSYNC-PCI"      /* WRU */
    edcb74
    +
    edcb74
    +#define SECONDS_1900_TO_1970 (2208988800U)
    edcb74
    +
    edcb74
    +#define TSYNC_REF_IID               (0x2500)    // SS CAI, REF IID
    edcb74
    +#define TSYNC_REF_DEST_ID           (0x0001)    // KTS Firmware
    edcb74
    +#define TSYNC_REF_IN_PYLD_OFF       (0)
    edcb74
    +#define TSYNC_REF_IN_LEN            (0)
    edcb74
    +#define TSYNC_REF_OUT_PYLD_OFF      (0)
    edcb74
    +#define TSYNC_REF_OUT_LEN           (8)
    edcb74
    +#define TSYNC_REF_MAX_OUT_LEN       (16)
    edcb74
    +#define TSYNC_REF_PYLD_LEN          (TSYNC_REF_IN_LEN +                     \
    edcb74
    +                                     TSYNC_REF_MAX_OUT_LEN)
    edcb74
    +#define TSYNC_REF_LEN               (4)
    edcb74
    +#define TSYNC_REF_LOCAL             ("LOCL")
    edcb74
    +
    edcb74
    +#define TSYNC_TMSCL_IID              (0x2301)    // CS CAI, TIMESCALE IID
    edcb74
    +#define TSYNC_TMSCL_DEST_ID          (0x0001)    // KTS Firmware
    edcb74
    +#define TSYNC_TMSCL_IN_PYLD_OFF      (0)
    edcb74
    +#define TSYNC_TMSCL_IN_LEN           (0)
    edcb74
    +#define TSYNC_TMSCL_OUT_PYLD_OFF     (0)
    edcb74
    +#define TSYNC_TMSCL_OUT_LEN          (4)
    edcb74
    +#define TSYNC_TMSCL_MAX_OUT_LEN      (12)
    edcb74
    +#define TSYNC_TMSCL_PYLD_LEN         (TSYNC_TMSCL_IN_LEN +                    \
    edcb74
    +                                     TSYNC_TMSCL_MAX_OUT_LEN)
    edcb74
    +
    edcb74
    +#define TSYNC_LEAP_IID              (0x2307)    // CS CAI, LEAP SEC IID
    edcb74
    +#define TSYNC_LEAP_DEST_ID          (0x0001)    // KTS Firmware
    edcb74
    +#define TSYNC_LEAP_IN_PYLD_OFF      (0)
    edcb74
    +#define TSYNC_LEAP_IN_LEN           (0)
    edcb74
    +#define TSYNC_LEAP_OUT_PYLD_OFF     (0)
    edcb74
    +#define TSYNC_LEAP_OUT_LEN          (28)
    edcb74
    +#define TSYNC_LEAP_MAX_OUT_LEN      (36)
    edcb74
    +#define TSYNC_LEAP_PYLD_LEN         (TSYNC_LEAP_IN_LEN +                    \
    edcb74
    +                                     TSYNC_LEAP_MAX_OUT_LEN)
    edcb74
    +
    edcb74
    +// These define the base date/time of the system clock.  The system time will
    edcb74
    +// be tracked as the number of seconds from this date/time.
    edcb74
    +#define TSYNC_TIME_BASE_YEAR        (1970) // earliest acceptable year
    edcb74
    +#define TSYNC_SECS_PER_MIN          (60)
    edcb74
    +#define TSYNC_MINS_PER_HR           (60)
    edcb74
    +#define TSYNC_HRS_PER_DAY           (24)
    edcb74
    +#define TSYNC_DAYS_PER_YR           (365)
    edcb74
    +#define TSYNC_DAYS_PER_LYR          (366)
    edcb74
    +#define TSYNC_SECS_PER_HR           (TSYNC_MINS_PER_HR  * TSYNC_SECS_PER_MIN)
    edcb74
    +#define TSYNC_SECS_PER_DAY          (TSYNC_HRS_PER_DAY  * TSYNC_SECS_PER_HR)
    edcb74
    +#define TSYNC_SECS_PER_YR           (TSYNC_DAYS_PER_YR  * TSYNC_SECS_PER_DAY)
    edcb74
    +#define TSYNC_SECS_PER_LYR          (TSYNC_DAYS_PER_LYR * TSYNC_SECS_PER_DAY)
    edcb74
    +
    edcb74
    +
    edcb74
    +#define TSYNC_LCL_STRATUM           (0)
    edcb74
    +
    edcb74
    +/*
    edcb74
    +** TSYNC Time Scales type
    edcb74
    +*/
    edcb74
    +typedef enum
    edcb74
    +{
    edcb74
    +    TIME_SCALE_UTC    = 0,   // Universal Coordinated Time
    edcb74
    +    TIME_SCALE_TAI    = 1,   // International Atomic Time
    edcb74
    +    TIME_SCALE_GPS    = 2,   // Global Positioning System
    edcb74
    +    TIME_SCALE_LOCAL  = 3,   // UTC w/local rules for time zone and DST
    edcb74
    +    NUM_TIME_SCALES   = 4,   // Number of time scales
    edcb74
    +
    edcb74
    +    TIME_SCALE_MAX    = 15   // Maximum number of timescales
    edcb74
    +
    edcb74
    +} TIME_SCALE;
    edcb74
    +
    edcb74
    +/*
    edcb74
    +** TSYNC Board Object
    edcb74
    +*/
    edcb74
    +typedef struct BoardObj {
    edcb74
    +
    edcb74
    +  int            file_descriptor;
    edcb74
    +  unsigned short devid;
    edcb74
    +  unsigned short options;
    edcb74
    +  unsigned char  firmware[5];
    edcb74
    +  unsigned char  FPGA[5];
    edcb74
    +  unsigned char  driver[7];
    edcb74
    +
    edcb74
    +} BoardObj;
    edcb74
    +
    edcb74
    +/*
    edcb74
    +** TSYNC Time Object
    edcb74
    +*/
    edcb74
    +typedef struct TimeObj {
    edcb74
    +
    edcb74
    +  unsigned char  syncOption;  /* -M option */
    edcb74
    +  unsigned int   secsDouble;  /* seconds floating pt */
    edcb74
    +  unsigned char  seconds;     /* seconds whole num */
    edcb74
    +  unsigned char  minutes;
    edcb74
    +  unsigned char  hours;
    edcb74
    +  unsigned short days;
    edcb74
    +  unsigned short year;
    edcb74
    +  unsigned short flags;      /* bit 2 SYNC, bit 1 TCODE; all others 0 */
    edcb74
    +
    edcb74
    +} TimeObj;
    edcb74
    +
    edcb74
    +/*
    edcb74
    +** NTP Time Object
    edcb74
    +*/
    edcb74
    +typedef struct NtpTimeObj {
    edcb74
    +
    edcb74
    +    TimeObj        timeObj;
    edcb74
    +    struct timeval tv;
    edcb74
    +    unsigned int   refId;
    edcb74
    +
    edcb74
    +} NtpTimeObj;
    edcb74
    +/*
    edcb74
    +** TSYNC Supervisor Reference Object
    edcb74
    +*/
    edcb74
    +typedef struct ReferenceObj {
    edcb74
    +
    edcb74
    +    char time[TSYNC_REF_LEN];
    edcb74
    +    char pps[TSYNC_REF_LEN];
    edcb74
    +
    edcb74
    +} ReferenceObj;
    edcb74
    +
    edcb74
    +/*
    edcb74
    +** TSYNC Seconds Time Object
    edcb74
    +*/
    edcb74
    +typedef struct SecTimeObj
    edcb74
    +{
    edcb74
    +    unsigned int seconds;
    edcb74
    +    unsigned int ns;
    edcb74
    +}
    edcb74
    +SecTimeObj;
    edcb74
    +
    edcb74
    +/*
    edcb74
    +** TSYNC DOY Time Object
    edcb74
    +*/
    edcb74
    +typedef struct DoyTimeObj
    edcb74
    +{
    edcb74
    +    unsigned int year;
    edcb74
    +    unsigned int doy;
    edcb74
    +    unsigned int hour;
    edcb74
    +    unsigned int minute;
    edcb74
    +    unsigned int second;
    edcb74
    +    unsigned int ns;
    edcb74
    +}
    edcb74
    +DoyTimeObj;
    edcb74
    +
    edcb74
    +/*
    edcb74
    +** TSYNC Leap Second Object
    edcb74
    +*/
    edcb74
    +typedef struct LeapSecondObj
    edcb74
    +{
    edcb74
    +    int        offset;
    edcb74
    +    DoyTimeObj utcDate;
    edcb74
    +}
    edcb74
    +LeapSecondObj;
    edcb74
    +
    edcb74
    +/*
    edcb74
    + * structures for ioctl interactions with driver
    edcb74
    + */
    edcb74
    +#define DI_PAYLOADS_STARTER_LENGTH 4
    edcb74
    +typedef struct ioctl_trans_di {
    edcb74
    +
    edcb74
    +    // input parameters
    edcb74
    +    uint16_t        dest;
    edcb74
    +    uint16_t        iid;
    edcb74
    +
    edcb74
    +    uint32_t        inPayloadOffset;
    edcb74
    +    uint32_t        inLength;
    edcb74
    +    uint32_t        outPayloadOffset;
    edcb74
    +    uint32_t        maxOutLength;
    edcb74
    +
    edcb74
    +    // output parameters
    edcb74
    +    uint32_t        actualOutLength;
    edcb74
    +    int32_t         status;
    edcb74
    +
    edcb74
    +    // Input and output
    edcb74
    +
    edcb74
    +    // The payloads field MUST be last in ioctl_trans_di.
    edcb74
    +    uint8_t         payloads[DI_PAYLOADS_STARTER_LENGTH];
    edcb74
    +
    edcb74
    +}ioctl_trans_di;
    edcb74
    +
    edcb74
    +/*
    edcb74
    + * structure for looking up a reference ID from a reference name
    edcb74
    + */
    edcb74
    +typedef struct
    edcb74
    +{
    edcb74
    +    const char* pRef;           // KTS Reference Name
    edcb74
    +    const char* pRefId;         // NTP Reference ID
    edcb74
    +
    edcb74
    +} RefIdLookup;
    edcb74
    +
    edcb74
    +/*
    edcb74
    + * unit control structure
    edcb74
    + */
    edcb74
    +typedef struct  {
    edcb74
    +    uint32_t refPrefer;         // Reference prefer flag
    edcb74
    +    uint32_t refId;             // Host peer reference ID
    edcb74
    +    uint8_t  refStratum;        // Host peer reference stratum
    edcb74
    +
    edcb74
    +} TsyncUnit;
    edcb74
    +
    edcb74
    +/*
    edcb74
    +**  Function prototypes
    edcb74
    +*/
    edcb74
    +static void tsync_poll     (int unit, struct peer *);
    edcb74
    +static void tsync_shutdown (int, struct peer *);
    edcb74
    +static int  tsync_start    (int, struct peer *);
    edcb74
    +
    edcb74
    +/*
    edcb74
    +**  Helper functions
    edcb74
    +*/
    edcb74
    +static void ApplyTimeOffset    (DoyTimeObj* pDt, int off);
    edcb74
    +static void SecTimeFromDoyTime (SecTimeObj* pSt, DoyTimeObj* pDt);
    edcb74
    +static void DoyTimeFromSecTime (DoyTimeObj* pDt, SecTimeObj* pSt);
    edcb74
    +
    edcb74
    +/*
    edcb74
    +**  Transfer vector
    edcb74
    +*/
    edcb74
    +struct refclock refclock_tsyncpci = {
    edcb74
    +    tsync_start,    /* start up driver */
    edcb74
    +    tsync_shutdown, /* shut down driver */
    edcb74
    +    tsync_poll,     /* transmit poll message */
    edcb74
    +    noentry,        /* not used (old tsync_control) */
    edcb74
    +    noentry,        /* initialize driver (not used) */
    edcb74
    +    noentry,        /* not used (old tsync_buginfo) */
    edcb74
    +    NOFLAGS         /* not used */
    edcb74
    +};
    edcb74
    +
    edcb74
    +/*
    edcb74
    + * Reference ID lookup table
    edcb74
    + */
    edcb74
    +static RefIdLookup RefIdLookupTbl[] =
    edcb74
    +{
    edcb74
    +    {"gps",  "GPS"},
    edcb74
    +    {"ir",   "IRIG"},
    edcb74
    +    {"hvq",  "HVQ"},
    edcb74
    +    {"frq",  "FREQ"},
    edcb74
    +    {"mdm",  "ACTS"},
    edcb74
    +    {"epp",  "PPS"},
    edcb74
    +    {"ptp",  "PTP"},
    edcb74
    +    {"asc",  "ATC"},
    edcb74
    +    {"hst0", "USER"},
    edcb74
    +    {"hst",  TSYNC_REF_LOCAL},
    edcb74
    +    {"self", TSYNC_REF_LOCAL},
    edcb74
    +    {NULL,   NULL}
    edcb74
    +};
    edcb74
    +
    edcb74
    +/*******************************************************************************
    edcb74
    +**          IOCTL DEFINITIONS
    edcb74
    +*******************************************************************************/
    edcb74
    +#define IOCTL_TPRO_ID            't'
    edcb74
    +#define IOCTL_TPRO_OPEN          _IOWR(IOCTL_TPRO_ID, 0,  BoardObj)
    edcb74
    +#define IOCTL_TPRO_GET_NTP_TIME  _IOWR(IOCTL_TPRO_ID, 25, NtpTimeObj)
    edcb74
    +#define IOCTL_TSYNC_GET          _IOWR(IOCTL_TPRO_ID, 26, ioctl_trans_di)
    edcb74
    +
    edcb74
    +/******************************************************************************
    edcb74
    + *
    edcb74
    + * Function:    tsync_start()
    edcb74
    + * Description: Used to intialize the Spectracom TSYNC reference driver.
    edcb74
    + *
    edcb74
    + * Parameters:
    edcb74
    + *     IN:  unit - not used.
    edcb74
    + *         *peer - pointer to this reference clock's peer structure
    edcb74
    + *     Returns: 0 - unsuccessful
    edcb74
    + *              1 - successful
    edcb74
    + *
    edcb74
    +*******************************************************************************/
    edcb74
    +static int tsync_start(int unit, struct peer *peer)
    edcb74
    +{
    edcb74
    +    struct refclockproc *pp;
    edcb74
    +    TsyncUnit           *up;
    edcb74
    +
    edcb74
    +
    edcb74
    +    /*
    edcb74
    +    **  initialize reference clock and peer parameters
    edcb74
    +    */
    edcb74
    +    pp                = peer->procptr;
    edcb74
    +    pp->clockdesc     = DESCRIPTION;
    edcb74
    +    pp->io.clock_recv = noentry;
    edcb74
    +    pp->io.srcclock   = (caddr_t)peer;
    edcb74
    +    pp->io.datalen    = 0;
    edcb74
    +    peer->precision   = PRECISION;
    edcb74
    +
    edcb74
    +    // Allocate and initialize unit structure
    edcb74
    +    if (!(up = (TsyncUnit*)emalloc(sizeof(TsyncUnit))))
    edcb74
    +    {
    edcb74
    +        return (0);
    edcb74
    +    }
    edcb74
    +
    edcb74
    +    // Store reference preference
    edcb74
    +    up->refPrefer = peer->flags & FLAG_PREFER;
    edcb74
    +
    edcb74
    +    // Initialize reference stratum level and ID
    edcb74
    +    up->refStratum = STRATUM_UNSPEC;
    edcb74
    +    strncpy((char *)&up->refId, TSYNC_REF_LOCAL, TSYNC_REF_LEN);
    edcb74
    +
    edcb74
    +    // Attach unit structure
    edcb74
    +    pp->unitptr = (caddr_t)up;
    edcb74
    +
    edcb74
    +    /* Declare our refId as local in the beginning because we do not know
    edcb74
    +     * what our actual refid is yet.
    edcb74
    +     */
    edcb74
    +    strncpy((char *)&pp->refid, TSYNC_REF_LOCAL, TSYNC_REF_LEN);
    edcb74
    +
    edcb74
    +    return (1);
    edcb74
    +
    edcb74
    +} /* End - tsync_start() */
    edcb74
    +
    edcb74
    +/*******************************************************************************
    edcb74
    +**
    edcb74
    +** Function:    tsync_shutdown()
    edcb74
    +** Description: Handles anything related to shutting down the reference clock
    edcb74
    +**              driver. Nothing at this point in time.
    edcb74
    +**
    edcb74
    +** Parameters:
    edcb74
    +**     IN:  unit - not used.
    edcb74
    +**         *peer - pointer to this reference clock's peer structure
    edcb74
    +**     Returns: none.
    edcb74
    +**
    edcb74
    +*******************************************************************************/
    edcb74
    +static void tsync_shutdown(int unit, struct peer *peer)
    edcb74
    +{
    edcb74
    +
    edcb74
    +} /* End - tsync_shutdown() */
    edcb74
    +
    edcb74
    +/******************************************************************************
    edcb74
    + *
    edcb74
    + * Function:    tsync_poll()
    edcb74
    + * Description: Retrieve time from the TSYNC device.
    edcb74
    + *
    edcb74
    + * Parameters:
    edcb74
    + *     IN:  unit - not used.
    edcb74
    + *         *peer - pointer to this reference clock's peer structure
    edcb74
    + *     Returns: none.
    edcb74
    + *
    edcb74
    +*******************************************************************************/
    edcb74
    +static void tsync_poll(int unit, struct peer *peer)
    edcb74
    +{
    edcb74
    +    char                 device[32];
    edcb74
    +    struct refclockproc *pp;
    edcb74
    +    struct calendar      jt;
    edcb74
    +    TsyncUnit           *up;
    edcb74
    +    unsigned char        synch;
    edcb74
    +    double               seconds;
    edcb74
    +    int                  err;
    edcb74
    +    int                  err1;
    edcb74
    +    int                  err2;
    edcb74
    +    int                  err3;
    edcb74
    +    int                  i;
    edcb74
    +    int                  j;
    edcb74
    +    unsigned int         itAllocationLength;
    edcb74
    +    unsigned int         itAllocationLength1;
    edcb74
    +    unsigned int         itAllocationLength2;
    edcb74
    +    NtpTimeObj           TimeContext;
    edcb74
    +    BoardObj             hBoard;
    edcb74
    +    char                 timeRef[TSYNC_REF_LEN + 1];
    edcb74
    +    char                 ppsRef [TSYNC_REF_LEN + 1];
    edcb74
    +    TIME_SCALE           tmscl = TIME_SCALE_UTC;
    edcb74
    +    LeapSecondObj        leapSec;
    edcb74
    +    ioctl_trans_di      *it;
    edcb74
    +    ioctl_trans_di      *it1;
    edcb74
    +    ioctl_trans_di      *it2;
    edcb74
    +    l_fp                 offset;
    edcb74
    +    l_fp                 ltemp;
    edcb74
    +    ReferenceObj *	 pRefObj;
    edcb74
    +
    edcb74
    +
    edcb74
    +    /* Construct the device name */
    edcb74
    +    sprintf(device, "%s%d", DEVICE, (int)peer->refclkunit);
    edcb74
    +
    edcb74
    +    printf("Polling device number %d...\n", (int)peer->refclkunit);
    edcb74
    +
    edcb74
    +    /* Open the TSYNC device */
    edcb74
    +    hBoard.file_descriptor = open(device, O_RDONLY | O_NDELAY, 0777);
    edcb74
    +
    edcb74
    +    /* If error opening TSYNC device... */
    edcb74
    +    if (hBoard.file_descriptor < 0)
    edcb74
    +    {
    edcb74
    +        msyslog(LOG_ERR, "Couldn't open device");
    edcb74
    +        return;
    edcb74
    +    }
    edcb74
    +
    edcb74
    +    /* If error while initializing the board... */
    edcb74
    +    if (ioctl(hBoard.file_descriptor, IOCTL_TPRO_OPEN, &hBoard) < 0)
    edcb74
    +    {
    edcb74
    +        msyslog(LOG_ERR, "Couldn't initialize device");
    edcb74
    +        close(hBoard.file_descriptor);
    edcb74
    +        return;
    edcb74
    +    }
    edcb74
    +
    edcb74
    +    /* Allocate memory for ioctl message */
    edcb74
    +    itAllocationLength =
    edcb74
    +        (sizeof(ioctl_trans_di) - DI_PAYLOADS_STARTER_LENGTH) +
    edcb74
    +        TSYNC_REF_IN_LEN + TSYNC_REF_MAX_OUT_LEN;
    edcb74
    +
    edcb74
    +    it = (ioctl_trans_di*)alloca(itAllocationLength);
    edcb74
    +    if (it == NULL) {
    edcb74
    +        msyslog(LOG_ERR, "Couldn't allocate transaction memory - Reference");
    edcb74
    +        return;
    edcb74
    +    }
    edcb74
    +
    edcb74
    +    /* Build SS_GetRef ioctl message */
    edcb74
    +    it->dest             = TSYNC_REF_DEST_ID;
    edcb74
    +    it->iid              = TSYNC_REF_IID;
    edcb74
    +    it->inPayloadOffset  = TSYNC_REF_IN_PYLD_OFF;
    edcb74
    +    it->inLength         = TSYNC_REF_IN_LEN;
    edcb74
    +    it->outPayloadOffset = TSYNC_REF_OUT_PYLD_OFF;
    edcb74
    +    it->maxOutLength     = TSYNC_REF_MAX_OUT_LEN;
    edcb74
    +    it->actualOutLength  = 0;
    edcb74
    +    it->status           = 0;
    edcb74
    +    memset(it->payloads, 0, TSYNC_REF_MAX_OUT_LEN);
    edcb74
    +
    edcb74
    +    /* Read the reference from the TSYNC-PCI device */
    edcb74
    +    err = ioctl(hBoard.file_descriptor,
    edcb74
    +                 IOCTL_TSYNC_GET,
    edcb74
    +                (char *)it);
    edcb74
    +
    edcb74
    +    /* Allocate memory for ioctl message */
    edcb74
    +    itAllocationLength1 =
    edcb74
    +        (sizeof(ioctl_trans_di) - DI_PAYLOADS_STARTER_LENGTH) +
    edcb74
    +        TSYNC_TMSCL_IN_LEN + TSYNC_TMSCL_MAX_OUT_LEN;
    edcb74
    +
    edcb74
    +    it1 = (ioctl_trans_di*)alloca(itAllocationLength1);
    edcb74
    +    if (it1 == NULL) {
    edcb74
    +        msyslog(LOG_ERR, "Couldn't allocate transaction memory - Time Scale");
    edcb74
    +        return;
    edcb74
    +    }
    edcb74
    +
    edcb74
    +    /* Build CS_GetTimeScale ioctl message */
    edcb74
    +    it1->dest             = TSYNC_TMSCL_DEST_ID;
    edcb74
    +    it1->iid              = TSYNC_TMSCL_IID;
    edcb74
    +    it1->inPayloadOffset  = TSYNC_TMSCL_IN_PYLD_OFF;
    edcb74
    +    it1->inLength         = TSYNC_TMSCL_IN_LEN;
    edcb74
    +    it1->outPayloadOffset = TSYNC_TMSCL_OUT_PYLD_OFF;
    edcb74
    +    it1->maxOutLength     = TSYNC_TMSCL_MAX_OUT_LEN;
    edcb74
    +    it1->actualOutLength  = 0;
    edcb74
    +    it1->status           = 0;
    edcb74
    +    memset(it1->payloads, 0, TSYNC_TMSCL_MAX_OUT_LEN);
    edcb74
    +
    edcb74
    +    /* Read the Time Scale info from the TSYNC-PCI device */
    edcb74
    +    err1 = ioctl(hBoard.file_descriptor,
    edcb74
    +                 IOCTL_TSYNC_GET,
    edcb74
    +                 (char *)it1);
    edcb74
    +
    edcb74
    +    /* Allocate memory for ioctl message */
    edcb74
    +    itAllocationLength2 =
    edcb74
    +        (sizeof(ioctl_trans_di) - DI_PAYLOADS_STARTER_LENGTH) +
    edcb74
    +        TSYNC_LEAP_IN_LEN + TSYNC_LEAP_MAX_OUT_LEN;
    edcb74
    +
    edcb74
    +    it2 = (ioctl_trans_di*)alloca(itAllocationLength2);
    edcb74
    +    if (it2 == NULL) {
    edcb74
    +        msyslog(LOG_ERR, "Couldn't allocate transaction memory - Leap Second");
    edcb74
    +        return;
    edcb74
    +    }
    edcb74
    +
    edcb74
    +    /* Build CS_GetLeapSec ioctl message */
    edcb74
    +    it2->dest             = TSYNC_LEAP_DEST_ID;
    edcb74
    +    it2->iid              = TSYNC_LEAP_IID;
    edcb74
    +    it2->inPayloadOffset  = TSYNC_LEAP_IN_PYLD_OFF;
    edcb74
    +    it2->inLength         = TSYNC_LEAP_IN_LEN;
    edcb74
    +    it2->outPayloadOffset = TSYNC_LEAP_OUT_PYLD_OFF;
    edcb74
    +    it2->maxOutLength     = TSYNC_LEAP_MAX_OUT_LEN;
    edcb74
    +    it2->actualOutLength  = 0;
    edcb74
    +    it2->status           = 0;
    edcb74
    +    memset(it2->payloads, 0, TSYNC_LEAP_MAX_OUT_LEN);
    edcb74
    +
    edcb74
    +    /* Read the leap seconds info from the TSYNC-PCI device */
    edcb74
    +    err2 = ioctl(hBoard.file_descriptor,
    edcb74
    +                 IOCTL_TSYNC_GET,
    edcb74
    +                 (char *)it2);
    edcb74
    +
    edcb74
    +    pp = peer->procptr;
    edcb74
    +    up = (TsyncUnit*)pp->unitptr;
    edcb74
    +
    edcb74
    +    /* Read the time from the TSYNC-PCI device */
    edcb74
    +    err3 = ioctl(hBoard.file_descriptor,
    edcb74
    +                 IOCTL_TPRO_GET_NTP_TIME,
    edcb74
    +                 (char *)&TimeContext);
    edcb74
    +
    edcb74
    +    /* Close the TSYNC device */
    edcb74
    +    close(hBoard.file_descriptor);
    edcb74
    +
    edcb74
    +    // Check for errors
    edcb74
    +    if ((err < 0) ||(err1 < 0) || (err2 < 0) || (err3 < 0) ||
    edcb74
    +        (it->status != 0) || (it1->status != 0) || (it2->status != 0) ||
    edcb74
    +        (it->actualOutLength  != TSYNC_REF_OUT_LEN) ||
    edcb74
    +        (it1->actualOutLength != TSYNC_TMSCL_OUT_LEN) ||
    edcb74
    +        (it2->actualOutLength != TSYNC_LEAP_OUT_LEN)) {
    edcb74
    +        refclock_report(peer, CEVNT_FAULT);
    edcb74
    +        return;
    edcb74
    +    }
    edcb74
    +
    edcb74
    +    // Extract reference identifiers from ioctl payload
    edcb74
    +    memset(timeRef, '\0', sizeof(timeRef));
    edcb74
    +    memset(ppsRef, '\0', sizeof(ppsRef));
    edcb74
    +    pRefObj = (void *)it->payloads;
    edcb74
    +    memcpy(timeRef, pRefObj->time, TSYNC_REF_LEN);
    edcb74
    +    memcpy(ppsRef, pRefObj->pps, TSYNC_REF_LEN);
    edcb74
    +
    edcb74
    +    // Extract the Clock Service Time Scale and convert to correct byte order
    edcb74
    +    memcpy(&tmscl, it1->payloads, sizeof(tmscl));
    edcb74
    +    tmscl = ntohl(tmscl);
    edcb74
    +
    edcb74
    +    // Extract leap second info from ioctl payload and perform byte swapping
    edcb74
    +    for (i = 0; i < (sizeof(leapSec) / 4); i++)
    edcb74
    +    {
    edcb74
    +        for (j = 0; j < 4; j++)
    edcb74
    +        {
    edcb74
    +            ((unsigned char*)&leapSec)[(i * 4) + j] =
    edcb74
    +                    ((unsigned char*)(it2->payloads))[(i * 4) + (3 - j)];
    edcb74
    +        }
    edcb74
    +    }
    edcb74
    +
    edcb74
    +    // Determine time reference ID from reference name
    edcb74
    +    for (i = 0; RefIdLookupTbl[i].pRef != NULL; i++)
    edcb74
    +    {
    edcb74
    +       // Search RefID table
    edcb74
    +       if (strstr(timeRef, RefIdLookupTbl[i].pRef) != NULL)
    edcb74
    +       {
    edcb74
    +          // Found the matching string
    edcb74
    +          break;
    edcb74
    +       }
    edcb74
    +    }
    edcb74
    +
    edcb74
    +    // Determine pps reference ID from reference name
    edcb74
    +    for (j = 0; RefIdLookupTbl[j].pRef != NULL; j++)
    edcb74
    +    {
    edcb74
    +       // Search RefID table
    edcb74
    +       if (strstr(ppsRef, RefIdLookupTbl[j].pRef) != NULL)
    edcb74
    +       {
    edcb74
    +          // Found the matching string
    edcb74
    +          break;
    edcb74
    +       }
    edcb74
    +    }
    edcb74
    +
    edcb74
    +    // Determine synchronization state from flags
    edcb74
    +    synch = (TimeContext.timeObj.flags == 0x4) ? 1 : 0;
    edcb74
    +
    edcb74
    +    // Pull seconds information from time object
    edcb74
    +    seconds = (double) (TimeContext.timeObj.secsDouble);
    edcb74
    +    seconds /= (double) 1000000.0;
    edcb74
    +
    edcb74
    +    /*
    edcb74
    +    ** Convert the number of microseconds to double and then place in the
    edcb74
    +    ** peer's last received long floating point format.
    edcb74
    +    */
    edcb74
    +    DTOLFP(((double)TimeContext.tv.tv_usec / 1000000.0), &pp->lastrec);
    edcb74
    +
    edcb74
    +    /*
    edcb74
    +    ** The specTimeStamp is the number of seconds since 1/1/1970, while the
    edcb74
    +    ** peer's lastrec time should be compatible with NTP which is seconds since
    edcb74
    +    ** 1/1/1900.  So Add the number of seconds between 1900 and 1970 to the
    edcb74
    +    ** specTimeStamp and place in the peer's lastrec long floating point struct.
    edcb74
    +    */
    edcb74
    +    pp->lastrec.Ul_i.Xl_ui += (unsigned int)TimeContext.tv.tv_sec +
    edcb74
    +                                            SECONDS_1900_TO_1970;
    edcb74
    +
    edcb74
    +    pp->polls++;
    edcb74
    +
    edcb74
    +    /*
    edcb74
    +    **  set the reference clock object
    edcb74
    +    */
    edcb74
    +    sprintf(pp->a_lastcode, "%03d %02d:%02d:%02.6f",
    edcb74
    +            TimeContext.timeObj.days, TimeContext.timeObj.hours,
    edcb74
    +            TimeContext.timeObj.minutes, seconds);
    edcb74
    +
    edcb74
    +    pp->lencode = strlen (pp->a_lastcode);
    edcb74
    +    pp->day     = TimeContext.timeObj.days;
    edcb74
    +    pp->hour    = TimeContext.timeObj.hours;
    edcb74
    +    pp->minute  = TimeContext.timeObj.minutes;
    edcb74
    +    pp->second  = (int) seconds;
    edcb74
    +    seconds     = (seconds - (double) (pp->second / 1.0)) * 1000000000;
    edcb74
    +    pp->nsec    = (long) seconds;
    edcb74
    +
    edcb74
    +    /*
    edcb74
    +    **  calculate year start
    edcb74
    +    */
    edcb74
    +    jt.year       = TimeContext.timeObj.year;
    edcb74
    +    jt.yearday    = 1;
    edcb74
    +    jt.monthday   = 1;
    edcb74
    +    jt.month      = 1;
    edcb74
    +    jt.hour       = 0;
    edcb74
    +    jt.minute     = 0;
    edcb74
    +    jt.second     = 0;
    edcb74
    +    pp->yearstart = caltontp(&jt;;
    edcb74
    +
    edcb74
    +    // Calculate and report reference clock offset
    edcb74
    +    offset.l_ui = (long)(((pp->day - 1) * 24) + pp->hour + GMT);
    edcb74
    +    offset.l_ui = (offset.l_ui * 60) + (long)pp->minute;
    edcb74
    +    offset.l_ui = (offset.l_ui * 60) + (long)pp->second;
    edcb74
    +    offset.l_ui = offset.l_ui + (long)pp->yearstart;
    edcb74
    +    offset.l_uf = 0;
    edcb74
    +    DTOLFP(pp->nsec / 1e9, &ltemp);
    edcb74
    +    L_ADD(&offset, &ltemp);
    edcb74
    +    refclock_process_offset(pp, offset, pp->lastrec,
    edcb74
    +                            pp->fudgetime1);
    edcb74
    +
    edcb74
    +    // KTS in sync
    edcb74
    +    if (synch) {
    edcb74
    +        // Subtract leap second info by one second to determine effective day
    edcb74
    +        ApplyTimeOffset(&(leapSec.utcDate), -1);
    edcb74
    +
    edcb74
    +        // If there is a leap second today and the KTS is using a time scale
    edcb74
    +        // which handles leap seconds then
    edcb74
    +        if ((tmscl != TIME_SCALE_GPS) && (tmscl != TIME_SCALE_TAI) &&
    edcb74
    +            (leapSec.utcDate.year == (unsigned int)TimeContext.timeObj.year) &&
    edcb74
    +            (leapSec.utcDate.doy  == (unsigned int)TimeContext.timeObj.days))
    edcb74
    +        {
    edcb74
    +            // If adding a second
    edcb74
    +            if (leapSec.offset == 1)
    edcb74
    +            {
    edcb74
    +                pp->leap = LEAP_ADDSECOND;
    edcb74
    +            }
    edcb74
    +            // Else if removing a second
    edcb74
    +            else if (leapSec.offset == -1)
    edcb74
    +            {
    edcb74
    +                pp->leap = LEAP_DELSECOND;
    edcb74
    +            }
    edcb74
    +            // Else report no leap second pending (no handling of offsets
    edcb74
    +            // other than +1 or -1)
    edcb74
    +            else
    edcb74
    +            {
    edcb74
    +                pp->leap = LEAP_NOWARNING;
    edcb74
    +            }
    edcb74
    +        }
    edcb74
    +        // Else report no leap second pending
    edcb74
    +        else
    edcb74
    +        {
    edcb74
    +            pp->leap = LEAP_NOWARNING;
    edcb74
    +        }
    edcb74
    +
    edcb74
    +        peer->leap = pp->leap;
    edcb74
    +        refclock_report(peer, CEVNT_NOMINAL);
    edcb74
    +
    edcb74
    +        // If reference name reported, then not in holdover
    edcb74
    +        if ((RefIdLookupTbl[i].pRef != NULL) &&
    edcb74
    +            (RefIdLookupTbl[j].pRef != NULL))
    edcb74
    +        {
    edcb74
    +            // Determine if KTS being synchronized by host (identified as
    edcb74
    +            // "LOCL")
    edcb74
    +            if ((strcmp(RefIdLookupTbl[i].pRefId, TSYNC_REF_LOCAL) == 0) ||
    edcb74
    +                (strcmp(RefIdLookupTbl[j].pRefId, TSYNC_REF_LOCAL) == 0))
    edcb74
    +            {
    edcb74
    +                // Clear prefer flag
    edcb74
    +                peer->flags &= ~FLAG_PREFER;
    edcb74
    +
    edcb74
    +                // Set reference clock stratum level as unusable
    edcb74
    +                pp->stratum   = STRATUM_UNSPEC;
    edcb74
    +                peer->stratum = pp->stratum;
    edcb74
    +
    edcb74
    +                // If a valid peer is available
    edcb74
    +                if ((sys_peer != NULL) && (sys_peer != peer))
    edcb74
    +                {
    edcb74
    +                    // Store reference peer stratum level and ID
    edcb74
    +                    up->refStratum = sys_peer->stratum;
    edcb74
    +                    up->refId      = addr2refid(&sys_peer->srcadr);
    edcb74
    +                }
    edcb74
    +            }
    edcb74
    +            else
    edcb74
    +            {
    edcb74
    +                // Restore prefer flag
    edcb74
    +                peer->flags |= up->refPrefer;
    edcb74
    +
    edcb74
    +                // Store reference stratum as local clock
    edcb74
    +                up->refStratum = TSYNC_LCL_STRATUM;
    edcb74
    +                strncpy((char *)&up->refId, RefIdLookupTbl[j].pRefId,
    edcb74
    +                    TSYNC_REF_LEN);
    edcb74
    +
    edcb74
    +                // Set reference clock stratum level as local clock
    edcb74
    +                pp->stratum   = TSYNC_LCL_STRATUM;
    edcb74
    +                peer->stratum = pp->stratum;
    edcb74
    +            }
    edcb74
    +
    edcb74
    +            // Update reference name
    edcb74
    +            strncpy((char *)&pp->refid, RefIdLookupTbl[j].pRefId,
    edcb74
    +                TSYNC_REF_LEN);
    edcb74
    +            peer->refid = pp->refid;
    edcb74
    +        }
    edcb74
    +        // Else in holdover
    edcb74
    +        else
    edcb74
    +        {
    edcb74
    +            // Restore prefer flag
    edcb74
    +            peer->flags |= up->refPrefer;
    edcb74
    +
    edcb74
    +            // Update reference ID to saved ID
    edcb74
    +            pp->refid   = up->refId;
    edcb74
    +            peer->refid = pp->refid;
    edcb74
    +
    edcb74
    +            // Update stratum level to saved stratum level
    edcb74
    +            pp->stratum   = up->refStratum;
    edcb74
    +            peer->stratum = pp->stratum;
    edcb74
    +        }
    edcb74
    +    }
    edcb74
    +    // Else KTS not in sync
    edcb74
    +    else {
    edcb74
    +        // Place local identifier in peer RefID
    edcb74
    +        strncpy((char *)&pp->refid, TSYNC_REF_LOCAL, TSYNC_REF_LEN);
    edcb74
    +        peer->refid = pp->refid;
    edcb74
    +
    edcb74
    +        // Report not in sync
    edcb74
    +        pp->leap   = LEAP_NOTINSYNC;
    edcb74
    +        peer->leap = pp->leap;
    edcb74
    +    }
    edcb74
    +
    edcb74
    +    if (pp->coderecv == pp->codeproc) {
    edcb74
    +        refclock_report(peer, CEVNT_TIMEOUT);
    edcb74
    +        return;
    edcb74
    +    }
    edcb74
    +
    edcb74
    +    record_clock_stats(&peer->srcadr, pp->a_lastcode);
    edcb74
    +    refclock_receive(peer);
    edcb74
    +
    edcb74
    +    /* Increment the number of times the reference has been polled */
    edcb74
    +    pp->polls++;
    edcb74
    +
    edcb74
    +} /* End - tsync_poll() */
    edcb74
    +
    edcb74
    +
    edcb74
    +////////////////////////////////////////////////////////////////////////////////
    edcb74
    +// Function:    ApplyTimeOffset
    edcb74
    +// Description: The ApplyTimeOffset function adds an offset (in seconds) to a
    edcb74
    +//              specified date and time.  The specified date and time is passed
    edcb74
    +//              back after being modified.
    edcb74
    +//
    edcb74
    +// Assumptions: 1. Every fourth year is a leap year.  Therefore, this function
    edcb74
    +//                 is only accurate through Feb 28, 2100.
    edcb74
    +////////////////////////////////////////////////////////////////////////////////
    edcb74
    +void ApplyTimeOffset(DoyTimeObj* pDt, int off)
    edcb74
    +{
    edcb74
    +    SecTimeObj st;                  // Time, in seconds
    edcb74
    +
    edcb74
    +
    edcb74
    +    // Convert date and time to seconds
    edcb74
    +    SecTimeFromDoyTime(&st, pDt);
    edcb74
    +
    edcb74
    +    // Apply offset
    edcb74
    +    st.seconds = (int)((signed long long)st.seconds + (signed long long)off);
    edcb74
    +
    edcb74
    +    // Convert seconds to date and time
    edcb74
    +    DoyTimeFromSecTime(pDt, &st);
    edcb74
    +
    edcb74
    +} // End ApplyTimeOffset
    edcb74
    +
    edcb74
    +
    edcb74
    +////////////////////////////////////////////////////////////////////////////////
    edcb74
    +// Function:    SecTimeFromDoyTime
    edcb74
    +// Description: The SecTimeFromDoyTime function converts a specified date
    edcb74
    +//              and time into a count of seconds since the base time.  This
    edcb74
    +//              function operates across the range Base Time to Max Time for
    edcb74
    +//              the system.
    edcb74
    +//
    edcb74
    +// Assumptions: 1. A leap year is any year evenly divisible by 4.  Therefore,
    edcb74
    +//                 this function is only accurate through Feb 28, 2100.
    edcb74
    +//              2. Conversion does not account for leap seconds.
    edcb74
    +////////////////////////////////////////////////////////////////////////////////
    edcb74
    +void SecTimeFromDoyTime(SecTimeObj* pSt, DoyTimeObj* pDt)
    edcb74
    +{
    edcb74
    +    unsigned int yrs;               // Years
    edcb74
    +    unsigned int lyrs;              // Leap years
    edcb74
    +
    edcb74
    +
    edcb74
    +    // Start with accumulated time of 0
    edcb74
    +    pSt->seconds  = 0;
    edcb74
    +
    edcb74
    +    // Calculate the number of years and leap years
    edcb74
    +    yrs           = pDt->year - TSYNC_TIME_BASE_YEAR;
    edcb74
    +    lyrs          = (yrs + 1) / 4;
    edcb74
    +
    edcb74
    +    // Convert leap years and years
    edcb74
    +    pSt->seconds += lyrs           * TSYNC_SECS_PER_LYR;
    edcb74
    +    pSt->seconds += (yrs - lyrs)   * TSYNC_SECS_PER_YR;
    edcb74
    +
    edcb74
    +    // Convert days, hours, minutes and seconds
    edcb74
    +    pSt->seconds += (pDt->doy - 1) * TSYNC_SECS_PER_DAY;
    edcb74
    +    pSt->seconds += pDt->hour      * TSYNC_SECS_PER_HR;
    edcb74
    +    pSt->seconds += pDt->minute    * TSYNC_SECS_PER_MIN;
    edcb74
    +    pSt->seconds += pDt->second;
    edcb74
    +
    edcb74
    +    // Copy the subseconds count
    edcb74
    +    pSt->ns       = pDt->ns;
    edcb74
    +
    edcb74
    +} // End SecTimeFromDoyTime
    edcb74
    +
    edcb74
    +
    edcb74
    +////////////////////////////////////////////////////////////////////////////////
    edcb74
    +// Function:    DoyTimeFromSecTime
    edcb74
    +// Description: The DoyTimeFromSecTime function converts a specified count
    edcb74
    +//              of seconds since the start of our base time into a SecTimeObj
    edcb74
    +//              structure.
    edcb74
    +//
    edcb74
    +// Assumptions: 1. A leap year is any year evenly divisible by 4.  Therefore,
    edcb74
    +//                 this function is only accurate through Feb 28, 2100.
    edcb74
    +//              2. Conversion does not account for leap seconds.
    edcb74
    +////////////////////////////////////////////////////////////////////////////////
    edcb74
    +void DoyTimeFromSecTime(DoyTimeObj* pDt, SecTimeObj* pSt)
    edcb74
    +{
    edcb74
    +    signed long long secs;          // Seconds accumulator variable
    edcb74
    +    unsigned int     yrs;           // Years accumulator variable
    edcb74
    +    unsigned int     doys;          // Days accumulator variable
    edcb74
    +    unsigned int     hrs;           // Hours accumulator variable
    edcb74
    +    unsigned int     mins;          // Minutes accumulator variable
    edcb74
    +
    edcb74
    +
    edcb74
    +    // Convert the seconds count into a signed 64-bit number for calculations
    edcb74
    +    secs  = (signed long long)(pSt->seconds);
    edcb74
    +
    edcb74
    +    // Calculate the number of 4 year chunks
    edcb74
    +    yrs   = (unsigned int)((secs /
    edcb74
    +                           ((TSYNC_SECS_PER_YR * 3) + TSYNC_SECS_PER_LYR)) * 4);
    edcb74
    +    secs %= ((TSYNC_SECS_PER_YR * 3) + TSYNC_SECS_PER_LYR);
    edcb74
    +
    edcb74
    +    // If there is at least a normal year worth of time left
    edcb74
    +    if (secs >= TSYNC_SECS_PER_YR)
    edcb74
    +    {
    edcb74
    +        // Increment the number of years and subtract a normal year of time
    edcb74
    +        yrs++;
    edcb74
    +        secs -= TSYNC_SECS_PER_YR;
    edcb74
    +    }
    edcb74
    +
    edcb74
    +    // If there is still at least a normal year worth of time left
    edcb74
    +    if (secs >= TSYNC_SECS_PER_YR)
    edcb74
    +    {
    edcb74
    +        // Increment the number of years and subtract a normal year of time
    edcb74
    +        yrs++;
    edcb74
    +        secs -= TSYNC_SECS_PER_YR;
    edcb74
    +    }
    edcb74
    +
    edcb74
    +    // If there is still at least a leap year worth of time left
    edcb74
    +    if (secs >= TSYNC_SECS_PER_LYR)
    edcb74
    +    {
    edcb74
    +        // Increment the number of years and subtract a leap year of time
    edcb74
    +        yrs++;
    edcb74
    +        secs -= TSYNC_SECS_PER_LYR;
    edcb74
    +    }
    edcb74
    +
    edcb74
    +    // Calculate the day of year as the number of days left, then add 1
    edcb74
    +    // because months start on the 1st.
    edcb74
    +    doys  = (unsigned int)((secs / TSYNC_SECS_PER_DAY) + 1);
    edcb74
    +    secs %= TSYNC_SECS_PER_DAY;
    edcb74
    +
    edcb74
    +    // Calculate the hour
    edcb74
    +    hrs   = (unsigned int)(secs / TSYNC_SECS_PER_HR);
    edcb74
    +    secs %= TSYNC_SECS_PER_HR;
    edcb74
    +
    edcb74
    +    // Calculate the minute
    edcb74
    +    mins  = (unsigned int)(secs / TSYNC_SECS_PER_MIN);
    edcb74
    +    secs %= TSYNC_SECS_PER_MIN;
    edcb74
    +
    edcb74
    +    // Fill in the doytime structure
    edcb74
    +    pDt->year   = yrs + TSYNC_TIME_BASE_YEAR;
    edcb74
    +    pDt->doy    = doys;
    edcb74
    +    pDt->hour   = hrs;
    edcb74
    +    pDt->minute = mins;
    edcb74
    +    pDt->second = (unsigned int)secs;
    edcb74
    +    pDt->ns     = pSt->ns;
    edcb74
    +
    edcb74
    +} // End DoyTimeFromSecTime
    edcb74
    +
    edcb74
    +#else
    edcb74
    +int refclock_tsyncpci_bs;
    edcb74
    +#endif /* REFCLOCK */