Annotation of embedaddon/ntp/ntpd/refclock_msfees.c, revision 1.1

1.1     ! misho       1: /* refclock_ees - clock driver for the EES M201 receiver */
        !             2: 
        !             3: #ifdef HAVE_CONFIG_H
        !             4: #include <config.h>
        !             5: #endif
        !             6: 
        !             7: #if defined(REFCLOCK) && defined(CLOCK_MSFEES) && defined(PPS)
        !             8: 
        !             9: /* Currently REQUIRES STREAM and PPSCD. CLK and CBREAK modes
        !            10:  * were removed as the code was overly hairy, they weren't in use
        !            11:  * (hence probably didn't work).  Still in RCS file at cl.cam.ac.uk
        !            12:  */
        !            13: 
        !            14: #include "ntpd.h"
        !            15: #include "ntp_io.h"
        !            16: #include "ntp_refclock.h"
        !            17: #include "ntp_unixtime.h"
        !            18: #include "ntp_calendar.h"
        !            19: 
        !            20: #include <ctype.h>
        !            21: #if defined(HAVE_BSD_TTYS)
        !            22: #include <sgtty.h>
        !            23: #endif /* HAVE_BSD_TTYS */
        !            24: #if defined(HAVE_SYSV_TTYS)
        !            25: #include <termio.h>
        !            26: #endif /* HAVE_SYSV_TTYS */
        !            27: #if defined(HAVE_TERMIOS)
        !            28: #include <termios.h>
        !            29: #endif
        !            30: #if defined(STREAM)
        !            31: #include <stropts.h>
        !            32: #endif
        !            33: 
        !            34: #ifdef HAVE_SYS_TERMIOS_H
        !            35: # include <sys/termios.h>
        !            36: #endif
        !            37: #ifdef HAVE_SYS_PPSCLOCK_H
        !            38: # include <sys/ppsclock.h>
        !            39: #endif
        !            40: 
        !            41: #include "ntp_stdlib.h"
        !            42: 
        !            43: int dbg = 0;
        !            44: /*
        !            45:        fudgefactor     = fudgetime1;
        !            46:        os_delay        = fudgetime2;
        !            47:           offset_fudge = os_delay + fudgefactor + inherent_delay;
        !            48:        stratumtouse    = fudgeval1 & 0xf
        !            49:        dbg             = fudgeval2;
        !            50:        sloppyclockflag = flags & CLK_FLAG1;
        !            51:                1         log smoothing summary when processing sample
        !            52:                4         dump the buffer from the clock
        !            53:                8         EIOGETKD the last n uS time stamps
        !            54:        if (flags & CLK_FLAG2 && unitinuse) ees->leaphold = 0;
        !            55:        ees->dump_vals  = flags & CLK_FLAG3;
        !            56:        ees->usealldata = flags & CLK_FLAG4;
        !            57: 
        !            58: 
        !            59:        bug->values[0] = (ees->lasttime) ? current_time - ees->lasttime : 0;
        !            60:        bug->values[1] = (ees->clocklastgood)?current_time-ees->clocklastgood:0;
        !            61:        bug->values[2] = (u_long)ees->status;
        !            62:        bug->values[3] = (u_long)ees->lastevent;
        !            63:        bug->values[4] = (u_long)ees->reason;
        !            64:        bug->values[5] = (u_long)ees->nsamples;
        !            65:        bug->values[6] = (u_long)ees->codestate;
        !            66:        bug->values[7] = (u_long)ees->day;
        !            67:        bug->values[8] = (u_long)ees->hour;
        !            68:        bug->values[9] = (u_long)ees->minute;
        !            69:        bug->values[10] = (u_long)ees->second;
        !            70:        bug->values[11] = (u_long)ees->tz;
        !            71:        bug->values[12] = ees->yearstart;
        !            72:        bug->values[13] = (ees->leaphold > current_time) ?
        !            73:                                ees->leaphold - current_time : 0;
        !            74:        bug->values[14] = inherent_delay[unit].l_uf;
        !            75:        bug->values[15] = offset_fudge[unit].l_uf;
        !            76: 
        !            77:        bug->times[0] = ees->reftime;
        !            78:        bug->times[1] = ees->arrvtime;
        !            79:        bug->times[2] = ees->lastsampletime;
        !            80:        bug->times[3] = ees->offset;
        !            81:        bug->times[4] = ees->lowoffset;
        !            82:        bug->times[5] = ees->highoffset;
        !            83:        bug->times[6] = inherent_delay[unit];
        !            84:        bug->times[8] = os_delay[unit];
        !            85:        bug->times[7] = fudgefactor[unit];
        !            86:        bug->times[9] = offset_fudge[unit];
        !            87:        bug->times[10]= ees->yearstart, 0;
        !            88:        */
        !            89: 
        !            90: /* This should support the use of an EES M201 receiver with RS232
        !            91:  * output (modified to transmit time once per second).
        !            92:  *
        !            93:  * For the format of the message sent by the clock, see the EESM_
        !            94:  * definitions below.
        !            95:  *
        !            96:  * It appears to run free for an integral number of minutes, until the error
        !            97:  * reaches 4mS, at which point it steps at second = 01.
        !            98:  * It appears that sometimes it steps 4mS (say at 7 min interval),
        !            99:  * then the next minute it decides that it was an error, so steps back.
        !           100:  * On the next minute it steps forward again :-(
        !           101:  * This is typically 16.5uS/S then 3975uS at the 4min re-sync,
        !           102:  * or 9.5uS/S then 3990.5uS at a 7min re-sync,
        !           103:  * at which point it may lose the "00" second time stamp.
        !           104:  * I assume that the most accurate time is just AFTER the re-sync.
        !           105:  * Hence remember the last cycle interval,
        !           106:  *
        !           107:  * Can run in any one of:
        !           108:  *
        !           109:  *     PPSCD   PPS signal sets CD which interupts, and grabs the current TOD
        !           110:  *     (sun)           *in the interupt code*, so as to avoid problems with
        !           111:  *                     the STREAMS scheduling.
        !           112:  *
        !           113:  * It appears that it goes 16.5 uS slow each second, then every 4 mins it
        !           114:  * generates no "00" second tick, and gains 3975 uS. Ho Hum ! (93/2/7)
        !           115:  */
        !           116: 
        !           117: /* Definitions */
        !           118: #ifndef        MAXUNITS
        !           119: #define        MAXUNITS        4       /* maximum number of EES units permitted */
        !           120: #endif
        !           121: 
        !           122: #ifndef        EES232
        !           123: #define        EES232  "/dev/ees%d"    /* Device to open to read the data */
        !           124: #endif
        !           125: 
        !           126: /* Other constant stuff */
        !           127: #ifndef        EESPRECISION
        !           128: #define        EESPRECISION    (-10)           /* what the heck - 2**-10 = 1ms */
        !           129: #endif
        !           130: #ifndef        EESREFID
        !           131: #define        EESREFID        "MSF\0"         /* String to identify the clock */
        !           132: #endif
        !           133: #ifndef        EESHSREFID
        !           134: #define        EESHSREFID      (0x7f7f0000 | ((REFCLK_MSF_EES) << 8)) /* Numeric refid */
        !           135: #endif
        !           136: 
        !           137: /* Description of clock */
        !           138: #define        EESDESCRIPTION          "EES M201 MSF Receiver"
        !           139: 
        !           140: /* Speed we run the clock port at. If this is changed the UARTDELAY
        !           141:  * value should be recomputed to suit.
        !           142:  */
        !           143: #ifndef        SPEED232
        !           144: #define        SPEED232        B9600   /* 9600 baud */
        !           145: #endif
        !           146: 
        !           147: /* What is the inherent delay for this mode of working, i.e. when is the
        !           148:  * data time stamped.
        !           149:  */
        !           150: #define        SAFETY_SHIFT    10      /* Split the shift to avoid overflow */
        !           151: #define        BITS_TO_L_FP(bits, baud) \
        !           152: (((((bits)*2 +1) << (FRACTION_PREC-SAFETY_SHIFT)) / (2*baud)) << SAFETY_SHIFT)
        !           153: #define        INH_DELAY_CBREAK        BITS_TO_L_FP(119, 9600)
        !           154: #define        INH_DELAY_PPS           BITS_TO_L_FP(  0, 9600)
        !           155: 
        !           156: #ifndef        STREAM_PP1
        !           157: #define        STREAM_PP1      "ppsclocd\0<-- patch space for module name1 -->"
        !           158: #endif
        !           159: #ifndef        STREAM_PP2
        !           160: #define        STREAM_PP2      "ppsclock\0<-- patch space for module name2 -->"
        !           161: #endif
        !           162: 
        !           163:      /* Offsets of the bytes of the serial line code.  The clock gives
        !           164:  * local time with a GMT/BST indication. The EESM_ definitions
        !           165:  * give offsets into ees->lastcode.
        !           166:  */
        !           167: #define EESM_CSEC       0      /* centiseconds - always zero in our clock  */
        !           168: #define EESM_SEC        1      /* seconds in BCD                           */
        !           169: #define EESM_MIN        2      /* minutes in BCD                           */
        !           170: #define EESM_HOUR       3      /* hours in BCD                             */
        !           171: #define EESM_DAYWK      4      /* day of week (Sun = 0 etc)                */
        !           172: #define EESM_DAY        5      /* day of month in BCD                      */
        !           173: #define EESM_MON        6      /* month in BCD                             */
        !           174: #define EESM_YEAR       7      /* year MOD 100 in BCD                      */
        !           175: #define EESM_LEAP       8      /* 0x0f if leap year, otherwise zero        */
        !           176: #define EESM_BST        9      /* 0x03 if BST, 0x00 if GMT                 */
        !           177: #define EESM_MSFOK     10      /* 0x3f if radio good, otherwise zero       */
        !           178:                                /* followed by a frame alignment byte (0xff) /
        !           179:                                /  which is not put into the lastcode buffer*/
        !           180: 
        !           181: /* Length of the serial time code, in characters.  The first length
        !           182:  * is less the frame alignment byte.
        !           183:  */
        !           184: #define        LENEESPRT       (EESM_MSFOK+1)
        !           185: #define        LENEESCODE      (LENEESPRT+1)
        !           186: 
        !           187:      /* Code state. */
        !           188: #define        EESCS_WAIT      0       /* waiting for start of timecode */
        !           189: #define        EESCS_GOTSOME   1       /* have an incomplete time code buffered */
        !           190: 
        !           191:      /* Default fudge factor and character to receive */
        !           192: #define        DEFFUDGETIME    0       /* Default user supplied fudge factor */
        !           193: #ifndef        DEFOSTIME
        !           194: #define        DEFOSTIME       0       /* Default OS delay -- passed by Make ? */
        !           195: #endif
        !           196: #define        DEFINHTIME      INH_DELAY_PPS /* inherent delay due to sample point*/
        !           197: 
        !           198:      /* Limits on things.  Reduce the number of samples to SAMPLEREDUCE by median
        !           199:  * elimination.  If we're running with an accurate clock, chose the BESTSAMPLE
        !           200:  * as the estimated offset, otherwise average the remainder.
        !           201:  */
        !           202: #define        FULLSHIFT       6                       /* NCODES root 2 */
        !           203: #define NCODES         (1<< FULLSHIFT)         /* 64 */
        !           204: #define        REDUCESHIFT     (FULLSHIFT -1)          /* SAMPLEREDUCE root 2 */
        !           205: 
        !           206:      /* Towards the high ( Why ?) end of half */
        !           207: #define        BESTSAMPLE      ((samplereduce * 3) /4) /* 24 */
        !           208: 
        !           209:      /* Leap hold time.  After a leap second the clock will no longer be
        !           210:  * reliable until it resynchronizes.  Hope 40 minutes is enough. */
        !           211: #define        EESLEAPHOLD     (40 * 60)
        !           212: 
        !           213: #define        EES_STEP_F      (1 << 24) /* the receiver steps in units of about 4ms */
        !           214: #define        EES_STEP_F_GRACE (EES_STEP_F/8) /*Allow for slop of 1/8 which is .5ms*/
        !           215: #define        EES_STEP_NOTE   (1 << 21)/* Log any unexpected jumps, say .5 ms .... */
        !           216: #define        EES_STEP_NOTES  50      /* Only do a limited number */
        !           217: #define        MAX_STEP        16      /* Max number of steps to remember */
        !           218: 
        !           219:      /* debug is a bit mask of debugging that is wanted */
        !           220: #define        DB_SYSLOG_SMPLI         0x0001
        !           221: #define        DB_SYSLOG_SMPLE         0x0002
        !           222: #define        DB_SYSLOG_SMTHI         0x0004
        !           223: #define        DB_SYSLOG_NSMTHE        0x0008
        !           224: #define        DB_SYSLOG_NSMTHI        0x0010
        !           225: #define        DB_SYSLOG_SMTHE         0x0020
        !           226: #define        DB_PRINT_EV             0x0040
        !           227: #define        DB_PRINT_CDT            0x0080
        !           228: #define        DB_PRINT_CDTC           0x0100
        !           229: #define        DB_SYSLOG_KEEPD         0x0800
        !           230: #define        DB_SYSLOG_KEEPE         0x1000
        !           231: #define        DB_LOG_DELTAS           0x2000
        !           232: #define        DB_PRINT_DELTAS         0x4000
        !           233: #define        DB_LOG_AWAITMORE        0x8000
        !           234: #define        DB_LOG_SAMPLES          0x10000
        !           235: #define        DB_NO_PPS               0x20000
        !           236: #define        DB_INC_PPS              0x40000
        !           237: #define        DB_DUMP_DELTAS          0x80000
        !           238: 
        !           239:      struct eesunit {                  /* EES unit control structure. */
        !           240:             struct peer *peer;         /* associated peer structure */
        !           241:             struct refclockio io;              /* given to the I/O handler */
        !           242:             l_fp       reftime;                /* reference time */
        !           243:             l_fp       lastsampletime;         /* time as in txt from last EES msg */
        !           244:             l_fp       arrvtime;               /* Time at which pkt arrived */
        !           245:             l_fp       codeoffsets[NCODES];    /* the time of arrival of 232 codes */
        !           246:             l_fp       offset;                 /* chosen offset        (for clkbug) */
        !           247:             l_fp       lowoffset;              /* lowest sample offset (for clkbug) */
        !           248:             l_fp       highoffset;             /* highest   "     "    (for clkbug) */
        !           249:             char       lastcode[LENEESCODE+6]; /* last time code we received */
        !           250:             u_long     lasttime;               /* last time clock heard from */
        !           251:             u_long     clocklastgood;          /* last time good radio seen */
        !           252:             u_char     lencode;                /* length of code in buffer */
        !           253:             u_char     nsamples;               /* number of samples we've collected */
        !           254:             u_char     codestate;              /* state of 232 code reception */
        !           255:             u_char     unit;                   /* unit number for this guy */
        !           256:             u_char     status;                 /* clock status */
        !           257:             u_char     lastevent;              /* last clock event */
        !           258:             u_char     reason;                 /* reason for last abort */
        !           259:             u_char     hour;                   /* hour of day */
        !           260:             u_char     minute;                 /* minute of hour */
        !           261:             u_char     second;                 /* seconds of minute */
        !           262:             char       tz;                     /* timezone from clock */
        !           263:             u_char     ttytype;                /* method used */
        !           264:             u_char     dump_vals;              /* Should clock values be dumped */
        !           265:             u_char     usealldata;             /* Use ALL samples */
        !           266:             u_short    day;                    /* day of year from last code */
        !           267:             u_long     yearstart;              /* start of current year */
        !           268:             u_long     leaphold;               /* time of leap hold expiry */
        !           269:             u_long     badformat;              /* number of bad format codes */
        !           270:             u_long     baddata;                /* number of invalid time codes */
        !           271:             u_long     timestarted;            /* time we started this */
        !           272:             long       last_pps_no;            /* The serial # of the last PPS */
        !           273:             char       fix_pending;            /* Is a "sync to time" pending ? */
        !           274:             /* Fine tuning - compensate for 4 mS ramping .... */
        !           275:             l_fp       last_l;                 /* last time stamp */
        !           276:             u_char     last_steps[MAX_STEP];   /* Most recent n steps */
        !           277:             int        best_av_step;           /* Best guess at average step */
        !           278:             char       best_av_step_count;     /* # of steps over used above */
        !           279:             char       this_step;              /* Current pos in buffer */
        !           280:             int        last_step_late;         /* How late the last step was (0-59) */
        !           281:             long       jump_fsecs;             /* # of fractions of a sec last jump */
        !           282:             u_long     last_step;              /* time of last step */
        !           283:             int        last_step_secs;         /* Number of seconds in last step */
        !           284:             int        using_ramp;             /* 1 -> noemal, -1 -> over stepped */
        !           285:      };
        !           286: #define        last_sec        last_l.l_ui
        !           287: #define        last_sfsec      last_l.l_f
        !           288: #define        this_uisec      ((ees->arrvtime).l_ui)
        !           289: #define        this_sfsec      ((ees->arrvtime).l_f)
        !           290: #define        msec(x)         ((x) / (1<<22))
        !           291: #define        LAST_STEPS      (sizeof ees->last_steps / sizeof ees->last_steps[0])
        !           292: #define        subms(x)        ((((((x < 0) ? (-(x)) : (x)) % (1<<22))/2) * 625) / (1<<(22 -5)))
        !           293: 
        !           294: /* Bitmask for what methods to try to use -- currently only PPS enabled */
        !           295: #define        T_CBREAK        1
        !           296: #define        T_PPS           8
        !           297: /* macros to test above */
        !           298: #define        is_cbreak(x)    ((x)->ttytype & T_CBREAK)
        !           299: #define        is_pps(x)       ((x)->ttytype & T_PPS)
        !           300: #define        is_any(x)       ((x)->ttytype)
        !           301: 
        !           302: #define        CODEREASON      20      /* reason codes */
        !           303: 
        !           304: /* Data space for the unit structures.  Note that we allocate these on
        !           305:  * the fly, but never give them back. */
        !           306: static struct eesunit *eesunits[MAXUNITS];
        !           307: static u_char unitinuse[MAXUNITS];
        !           308: 
        !           309: /* Keep the fudge factors separately so they can be set even
        !           310:  * when no clock is configured. */
        !           311: static l_fp inherent_delay[MAXUNITS];          /* when time stamp is taken */
        !           312: static l_fp fudgefactor[MAXUNITS];             /* fudgetime1 */
        !           313: static l_fp os_delay[MAXUNITS];                        /* fudgetime2 */
        !           314: static l_fp offset_fudge[MAXUNITS];            /* Sum of above */
        !           315: static u_char stratumtouse[MAXUNITS];
        !           316: static u_char sloppyclockflag[MAXUNITS];
        !           317: 
        !           318: static int deltas[60];
        !           319: 
        !           320: static l_fp acceptable_slop; /* = { 0, 1 << (FRACTION_PREC -2) }; */
        !           321: static l_fp onesec; /* = { 1, 0 }; */
        !           322: 
        !           323: #ifndef        DUMP_BUF_SIZE   /* Size of buffer to be used by dump_buf */
        !           324: #define        DUMP_BUF_SIZE   10112
        !           325: #endif
        !           326: 
        !           327: /* ees_reset - reset the count back to zero */
        !           328: #define        ees_reset(ees) (ees)->nsamples = 0; \
        !           329: (ees)->codestate = EESCS_WAIT
        !           330: 
        !           331: /* ees_event - record and report an event */
        !           332: #define        ees_event(ees, evcode) if ((ees)->status != (u_char)(evcode)) \
        !           333: ees_report_event((ees), (evcode))
        !           334: 
        !           335:      /* Find the precision of the system clock by reading it */
        !           336: #define        USECS   1000000
        !           337: #define        MINSTEP 5       /* some systems increment uS on each call */
        !           338: #define        MAXLOOPS (USECS/9)
        !           339: 
        !           340: /*
        !           341:  * Function prototypes
        !           342:  */
        !           343: 
        !           344: static int     msfees_start    P((int unit, struct peer *peer));
        !           345: static void    msfees_shutdown P((int unit, struct peer *peer));
        !           346: static void    msfees_poll     P((int unit, struct peer *peer));
        !           347: static void    msfees_init     P((void));
        !           348: static void    dump_buf        P((l_fp *coffs, int from, int to, char *text));
        !           349: static void    ees_report_event P((struct eesunit *ees, int code));
        !           350: static void    ees_receive     P((struct recvbuf *rbufp));
        !           351: static void    ees_process     P((struct eesunit *ees));
        !           352: #ifdef QSORT_USES_VOID_P
        !           353: static int     offcompare      P((const void *va, const void *vb));
        !           354: #else
        !           355: static int     offcompare      P((const l_fp *a, const l_fp *b));
        !           356: #endif /* QSORT_USES_VOID_P */
        !           357: 
        !           358: 
        !           359: /*
        !           360:  * Transfer vector
        !           361:  */
        !           362: struct refclock refclock_msfees = {
        !           363:        msfees_start,           /* start up driver */
        !           364:        msfees_shutdown,        /* shut down driver */
        !           365:        msfees_poll,            /* transmit poll message */
        !           366:        noentry,                /* not used */
        !           367:        msfees_init,            /* initialize driver */
        !           368:        noentry,                /* not used */
        !           369:        NOFLAGS                 /* not used */
        !           370: };
        !           371: 
        !           372: 
        !           373: static void
        !           374: dump_buf(
        !           375:        l_fp *coffs,
        !           376:        int from,
        !           377:        int to,
        !           378:        char *text
        !           379:        )
        !           380: {
        !           381:        char buff[DUMP_BUF_SIZE + 80];
        !           382:        int i;
        !           383:        register char *ptr = buff;
        !           384: 
        !           385:        snprintf(buff, sizeof(buff), text);
        !           386:        for (i = from; i < to; i++) {
        !           387:                ptr += strlen(ptr);
        !           388:                if ((ptr - buff) > DUMP_BUF_SIZE) {
        !           389:                        msyslog(LOG_DEBUG, "D: %s", buff);
        !           390:                        ptr = buff;
        !           391:                }
        !           392:                snprintf(ptr, sizeof(buff) - (ptr - buff),
        !           393:                         " %06d", ((int)coffs[i].l_f) / 4295);
        !           394:        }
        !           395:        msyslog(LOG_DEBUG, "D: %s", buff);
        !           396: }
        !           397: 
        !           398: /* msfees_init - initialize internal ees driver data */
        !           399: static void
        !           400: msfees_init(void)
        !           401: {
        !           402:        register int i;
        !           403:        /* Just zero the data arrays */
        !           404:        memset((char *)eesunits, 0, sizeof eesunits);
        !           405:        memset((char *)unitinuse, 0, sizeof unitinuse);
        !           406: 
        !           407:        acceptable_slop.l_ui = 0;
        !           408:        acceptable_slop.l_uf = 1 << (FRACTION_PREC -2);
        !           409: 
        !           410:        onesec.l_ui = 1;
        !           411:        onesec.l_uf = 0;
        !           412: 
        !           413:        /* Initialize fudge factors to default. */
        !           414:        for (i = 0; i < MAXUNITS; i++) {
        !           415:                fudgefactor[i].l_ui     = 0;
        !           416:                fudgefactor[i].l_uf     = DEFFUDGETIME;
        !           417:                os_delay[i].l_ui        = 0;
        !           418:                os_delay[i].l_uf        = DEFOSTIME;
        !           419:                inherent_delay[i].l_ui  = 0;
        !           420:                inherent_delay[i].l_uf  = DEFINHTIME;
        !           421:                offset_fudge[i]         = os_delay[i];
        !           422:                L_ADD(&offset_fudge[i], &fudgefactor[i]);
        !           423:                L_ADD(&offset_fudge[i], &inherent_delay[i]);
        !           424:                stratumtouse[i]         = 0;
        !           425:                sloppyclockflag[i]      = 0;
        !           426:        }
        !           427: }
        !           428: 
        !           429: 
        !           430: /* msfees_start - open the EES devices and initialize data for processing */
        !           431: static int
        !           432: msfees_start(
        !           433:        int unit,
        !           434:        struct peer *peer
        !           435:        )
        !           436: {
        !           437:        register struct eesunit *ees;
        !           438:        register int i;
        !           439:        int fd232 = -1;
        !           440:        char eesdev[20];
        !           441:        struct termios ttyb, *ttyp;
        !           442:        struct refclockproc *pp;
        !           443:        pp = peer->procptr;
        !           444: 
        !           445:        if (unit >= MAXUNITS) {
        !           446:                msyslog(LOG_ERR, "ees clock: unit number %d invalid (max %d)",
        !           447:                        unit, MAXUNITS-1);
        !           448:                return 0;
        !           449:        }
        !           450:        if (unitinuse[unit]) {
        !           451:                msyslog(LOG_ERR, "ees clock: unit number %d in use", unit);
        !           452:                return 0;
        !           453:        }
        !           454: 
        !           455:        /* Unit okay, attempt to open the devices.  We do them both at
        !           456:         * once to make sure we can */
        !           457:        snprintf(eesdev, sizeof(eesdev), EES232, unit);
        !           458: 
        !           459:        fd232 = open(eesdev, O_RDWR, 0777);
        !           460:        if (fd232 == -1) {
        !           461:                msyslog(LOG_ERR, "ees clock: open of %s failed: %m", eesdev);
        !           462:                return 0;
        !           463:        }
        !           464: 
        !           465: #ifdef TIOCEXCL
        !           466:        /* Set for exclusive use */
        !           467:        if (ioctl(fd232, TIOCEXCL, (char *)0) < 0) {
        !           468:                msyslog(LOG_ERR, "ees clock: ioctl(%s, TIOCEXCL): %m", eesdev);
        !           469:                goto screwed;
        !           470:        }
        !           471: #endif
        !           472: 
        !           473:        /* STRIPPED DOWN VERSION: Only PPS CD is supported at the moment */
        !           474: 
        !           475:        /* Set port characteristics.  If we don't have a STREAMS module or
        !           476:         * a clock line discipline, cooked mode is just usable, even though it
        !           477:         * strips the top bit.  The only EES byte which uses the top
        !           478:         * bit is the year, and we don't use that anyway. If we do
        !           479:         * have the line discipline, we choose raw mode, and the
        !           480:         * line discipline code will block up the messages.
        !           481:         */
        !           482: 
        !           483:        /* STIPPED DOWN VERSION: Only PPS CD is supported at the moment */
        !           484: 
        !           485:        ttyp = &ttyb;
        !           486:        if (tcgetattr(fd232, ttyp) < 0) {
        !           487:                msyslog(LOG_ERR, "msfees_start: tcgetattr(%s): %m", eesdev);
        !           488:                goto screwed;
        !           489:        }
        !           490: 
        !           491:        ttyp->c_iflag = IGNBRK|IGNPAR|ICRNL;
        !           492:        ttyp->c_cflag = SPEED232|CS8|CLOCAL|CREAD;
        !           493:        ttyp->c_oflag = 0;
        !           494:        ttyp->c_lflag = ICANON;
        !           495:        ttyp->c_cc[VERASE] = ttyp->c_cc[VKILL] = '\0';
        !           496:        if (tcsetattr(fd232, TCSANOW, ttyp) < 0) {
        !           497:                msyslog(LOG_ERR, "msfees_start: tcsetattr(%s): %m", eesdev);
        !           498:                goto screwed;
        !           499:        }
        !           500: 
        !           501:        if (tcflush(fd232, TCIOFLUSH) < 0) {
        !           502:                msyslog(LOG_ERR, "msfees_start: tcflush(%s): %m", eesdev);
        !           503:                goto screwed;
        !           504:        }
        !           505: 
        !           506:        inherent_delay[unit].l_uf = INH_DELAY_PPS;
        !           507: 
        !           508:        /* offset fudge (how *late* the timestamp is) = fudge + os delays */
        !           509:        offset_fudge[unit] = os_delay[unit];
        !           510:        L_ADD(&offset_fudge[unit], &fudgefactor[unit]);
        !           511:        L_ADD(&offset_fudge[unit], &inherent_delay[unit]);
        !           512: 
        !           513:        /* Looks like this might succeed.  Find memory for the structure.
        !           514:         * Look to see if there are any unused ones, if not we malloc() one.
        !           515:         */
        !           516:        if (eesunits[unit] != 0) /* The one we want is okay */
        !           517:            ees = eesunits[unit];
        !           518:        else {
        !           519:                /* Look for an unused, but allocated struct */
        !           520:                for (i = 0; i < MAXUNITS; i++) {
        !           521:                        if (!unitinuse[i] && eesunits[i] != 0)
        !           522:                            break;
        !           523:                }
        !           524: 
        !           525:                if (i < MAXUNITS) {     /* Reclaim this one */
        !           526:                        ees = eesunits[i];
        !           527:                        eesunits[i] = 0;
        !           528:                }                       /* no spare -- make a new one */
        !           529:                else ees = (struct eesunit *) emalloc(sizeof(struct eesunit));
        !           530:        }
        !           531:        memset((char *)ees, 0, sizeof(struct eesunit));
        !           532:        eesunits[unit] = ees;
        !           533: 
        !           534:        /* Set up the structures */
        !           535:        ees->peer       = peer;
        !           536:        ees->unit       = (u_char)unit;
        !           537:        ees->timestarted= current_time;
        !           538:        ees->ttytype    = 0;
        !           539:        ees->io.clock_recv= ees_receive;
        !           540:        ees->io.srcclock= (caddr_t)ees;
        !           541:        ees->io.datalen = 0;
        !           542:        ees->io.fd      = fd232;
        !           543: 
        !           544:        /* Okay.  Push one of the two (linked into the kernel, or dynamically
        !           545:         * loaded) STREAMS module, and give it to the I/O code to start
        !           546:         * receiving stuff.
        !           547:         */
        !           548: 
        !           549: #ifdef STREAM
        !           550:        {
        !           551:                int rc1;
        !           552:                /* Pop any existing onews first ... */
        !           553:                while (ioctl(fd232, I_POP, 0 ) >= 0) ;
        !           554: 
        !           555:                /* Now try pushing either of the possible modules */
        !           556:                if ((rc1=ioctl(fd232, I_PUSH, STREAM_PP1)) < 0 &&
        !           557:                    ioctl(fd232, I_PUSH, STREAM_PP2) < 0) {
        !           558:                        msyslog(LOG_ERR,
        !           559:                                "ees clock: Push of `%s' and `%s' to %s failed %m",
        !           560:                                STREAM_PP1, STREAM_PP2, eesdev);
        !           561:                        goto screwed;
        !           562:                }
        !           563:                else {
        !           564:                        NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
        !           565:                                msyslog(LOG_INFO, "I: ees clock: PUSHed %s on %s",
        !           566:                                        (rc1 >= 0) ? STREAM_PP1 : STREAM_PP2, eesdev);
        !           567:                        ees->ttytype |= T_PPS;
        !           568:                }
        !           569:        }
        !           570: #endif /* STREAM */
        !           571: 
        !           572:        /* Add the clock */
        !           573:        if (!io_addclock(&ees->io)) {
        !           574:                /* Oh shit.  Just close and return. */
        !           575:                msyslog(LOG_ERR, "ees clock: io_addclock(%s): %m", eesdev);
        !           576:                goto screwed;
        !           577:        }
        !           578: 
        !           579: 
        !           580:        /* All done.  Initialize a few random peer variables, then
        !           581:         * return success. */
        !           582:        peer->precision = sys_precision;
        !           583:        peer->stratum   = stratumtouse[unit];
        !           584:        if (stratumtouse[unit] <= 1) {
        !           585:                memcpy((char *)&pp->refid, EESREFID, 4);
        !           586:                if (unit > 0 && unit < 10)
        !           587:                    ((char *)&pp->refid)[3] = '0' + unit;
        !           588:        } else {
        !           589:                peer->refid = htonl(EESHSREFID);
        !           590:        }
        !           591:        unitinuse[unit] = 1;
        !           592:        pp->unitptr = (caddr_t) &eesunits[unit];
        !           593:        pp->clockdesc = EESDESCRIPTION;
        !           594:        msyslog(LOG_ERR, "ees clock: %s OK on %d", eesdev, unit);
        !           595:        return (1);
        !           596: 
        !           597:     screwed:
        !           598:        if (fd232 != -1)
        !           599:            (void) close(fd232);
        !           600:        return (0);
        !           601: }
        !           602: 
        !           603: 
        !           604: /* msfees_shutdown - shut down a EES clock */
        !           605: static void
        !           606: msfees_shutdown(
        !           607:        int unit,
        !           608:        struct peer *peer
        !           609:        )
        !           610: {
        !           611:        register struct eesunit *ees;
        !           612: 
        !           613:        if (unit >= MAXUNITS) {
        !           614:                msyslog(LOG_ERR,
        !           615:                        "ees clock: INTERNAL ERROR, unit number %d invalid (max %d)",
        !           616:                        unit, MAXUNITS);
        !           617:                return;
        !           618:        }
        !           619:        if (!unitinuse[unit]) {
        !           620:                msyslog(LOG_ERR,
        !           621:                        "ees clock: INTERNAL ERROR, unit number %d not in use", unit);
        !           622:                return;
        !           623:        }
        !           624: 
        !           625:        /* Tell the I/O module to turn us off.  We're history. */
        !           626:        ees = eesunits[unit];
        !           627:        io_closeclock(&ees->io);
        !           628:        unitinuse[unit] = 0;
        !           629: }
        !           630: 
        !           631: 
        !           632: /* ees_report_event - note the occurance of an event */
        !           633: static void
        !           634: ees_report_event(
        !           635:        struct eesunit *ees,
        !           636:        int code
        !           637:        )
        !           638: {
        !           639:        if (ees->status != (u_char)code) {
        !           640:                ees->status = (u_char)code;
        !           641:                if (code != CEVNT_NOMINAL)
        !           642:                    ees->lastevent = (u_char)code;
        !           643:                /* Should report event to trap handler in here.
        !           644:                 * Soon...
        !           645:                 */
        !           646:        }
        !           647: }
        !           648: 
        !           649: 
        !           650: /* ees_receive - receive data from the serial interface on an EES clock */
        !           651: static void
        !           652: ees_receive(
        !           653:        struct recvbuf *rbufp
        !           654:        )
        !           655: {
        !           656:        register int n_sample;
        !           657:        register int day;
        !           658:        register struct eesunit *ees;
        !           659:        register u_char *dpt;           /* Data PoinTeR: move along ... */
        !           660:        register u_char *dpend;         /* Points just *after* last data char */
        !           661:        register char *cp;
        !           662:        l_fp tmp;
        !           663:        int call_pps_sample = 0;
        !           664:        l_fp pps_arrvstamp;
        !           665:        int     sincelast;
        !           666:        int     pps_step = 0;
        !           667:        int     suspect_4ms_step = 0;
        !           668:        struct ppsclockev ppsclockev;
        !           669:        long *ptr = (long *) &ppsclockev;
        !           670:        int rc;
        !           671:        int request;
        !           672: #ifdef HAVE_CIOGETEV
        !           673:        request = CIOGETEV;
        !           674: #endif
        !           675: #ifdef HAVE_TIOCGPPSEV
        !           676:        request = TIOCGPPSEV;
        !           677: #endif
        !           678: 
        !           679:        /* Get the clock this applies to and a pointer to the data */
        !           680:        ees = (struct eesunit *)rbufp->recv_srcclock;
        !           681:        dpt = (u_char *)&rbufp->recv_space;
        !           682:        dpend = dpt + rbufp->recv_length;
        !           683:        if ((dbg & DB_LOG_AWAITMORE) && (rbufp->recv_length != LENEESCODE))
        !           684:            printf("[%d] ", rbufp->recv_length);
        !           685: 
        !           686:        /* Check out our state and process appropriately */
        !           687:        switch (ees->codestate) {
        !           688:            case EESCS_WAIT:
        !           689:                /* Set an initial guess at the timestamp as the recv time.
        !           690:                 * If just running in CBREAK mode, we can't improve this.
        !           691:                 * If we have the CLOCK Line Discipline, PPSCD, or sime such,
        !           692:                 * then we will do better later ....
        !           693:                 */
        !           694:                ees->arrvtime = rbufp->recv_time;
        !           695:                ees->codestate = EESCS_GOTSOME;
        !           696:                ees->lencode = 0;
        !           697:                /*FALLSTHROUGH*/
        !           698: 
        !           699:            case EESCS_GOTSOME:
        !           700:                cp = &(ees->lastcode[ees->lencode]);
        !           701: 
        !           702:                /* Gobble the bytes until the final (possibly stripped) 0xff */
        !           703:                while (dpt < dpend && (*dpt & 0x7f) != 0x7f) {
        !           704:                        *cp++ = (char)*dpt++;
        !           705:                        ees->lencode++;
        !           706:                        /* Oh dear -- too many bytes .. */
        !           707:                        if (ees->lencode > LENEESPRT) {
        !           708:                                NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
        !           709:                                        msyslog(LOG_INFO,
        !           710:                                                "I: ees clock: %d + %d > %d [%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x]",
        !           711:                                                ees->lencode, dpend - dpt, LENEESPRT,
        !           712: #define D(x) (ees->lastcode[x])
        !           713:                                                D(0), D(1), D(2), D(3), D(4), D(5), D(6),
        !           714:                                                D(7), D(8), D(9), D(10), D(11), D(12));
        !           715: #undef D
        !           716:                                ees->badformat++;
        !           717:                                ees->reason = CODEREASON + 1;
        !           718:                                ees_event(ees, CEVNT_BADREPLY);
        !           719:                                ees_reset(ees);
        !           720:                                return;
        !           721:                        }
        !           722:                }
        !           723:                /* Gave up because it was end of the buffer, rather than ff */
        !           724:                if (dpt == dpend) {
        !           725:                        /* Incomplete.  Wait for more. */
        !           726:                        if (dbg & DB_LOG_AWAITMORE)
        !           727:                            msyslog(LOG_INFO,
        !           728:                                    "I: ees clock %d: %p == %p: await more",
        !           729:                                    ees->unit, dpt, dpend);
        !           730:                        return;
        !           731:                }
        !           732: 
        !           733:                /* This shouldn't happen ... ! */
        !           734:                if ((*dpt & 0x7f) != 0x7f) {
        !           735:                        msyslog(LOG_INFO, "I: ees clock: %0x & 0x7f != 0x7f", *dpt);
        !           736:                        ees->badformat++;
        !           737:                        ees->reason = CODEREASON + 2;
        !           738:                        ees_event(ees, CEVNT_BADREPLY);
        !           739:                        ees_reset(ees);
        !           740:                        return;
        !           741:                }
        !           742: 
        !           743:                /* Skip the 0xff */
        !           744:                dpt++;
        !           745: 
        !           746:                /* Finally, got a complete buffer.  Mainline code will
        !           747:                 * continue on. */
        !           748:                cp = ees->lastcode;
        !           749:                break;
        !           750: 
        !           751:            default:
        !           752:                msyslog(LOG_ERR, "ees clock: INTERNAL ERROR: %d state %d",
        !           753:                        ees->unit, ees->codestate);
        !           754:                ees->reason = CODEREASON + 5;
        !           755:                ees_event(ees, CEVNT_FAULT);
        !           756:                ees_reset(ees);
        !           757:                return;
        !           758:        }
        !           759: 
        !           760:        /* Boy!  After all that crap, the lastcode buffer now contains
        !           761:         * something we hope will be a valid time code.  Do length
        !           762:         * checks and sanity checks on constant data.
        !           763:         */
        !           764:        ees->codestate = EESCS_WAIT;
        !           765:        ees->lasttime = current_time;
        !           766:        if (ees->lencode != LENEESPRT) {
        !           767:                ees->badformat++;
        !           768:                ees->reason = CODEREASON + 6;
        !           769:                ees_event(ees, CEVNT_BADREPLY);
        !           770:                ees_reset(ees);
        !           771:                return;
        !           772:        }
        !           773: 
        !           774:        cp = ees->lastcode;
        !           775: 
        !           776:        /* Check that centisecond is zero */
        !           777:        if (cp[EESM_CSEC] != 0) {
        !           778:                ees->baddata++;
        !           779:                ees->reason = CODEREASON + 7;
        !           780:                ees_event(ees, CEVNT_BADREPLY);
        !           781:                ees_reset(ees);
        !           782:                return;
        !           783:        }
        !           784: 
        !           785:        /* Check flag formats */
        !           786:        if (cp[EESM_LEAP] != 0 && cp[EESM_LEAP] != 0x0f) {
        !           787:                ees->badformat++;
        !           788:                ees->reason = CODEREASON + 8;
        !           789:                ees_event(ees, CEVNT_BADREPLY);
        !           790:                ees_reset(ees);
        !           791:                return;
        !           792:        }
        !           793: 
        !           794:        if (cp[EESM_BST] != 0 && cp[EESM_BST] != 0x03) {
        !           795:                ees->badformat++;
        !           796:                ees->reason = CODEREASON + 9;
        !           797:                ees_event(ees, CEVNT_BADREPLY);
        !           798:                ees_reset(ees);
        !           799:                return;
        !           800:        }
        !           801: 
        !           802:        if (cp[EESM_MSFOK] != 0 && cp[EESM_MSFOK] != 0x3f) {
        !           803:                ees->badformat++;
        !           804:                ees->reason = CODEREASON + 10;
        !           805:                ees_event(ees, CEVNT_BADREPLY);
        !           806:                ees_reset(ees);
        !           807:                return;
        !           808:        }
        !           809: 
        !           810:        /* So far, so good.  Compute day, hours, minutes, seconds,
        !           811:         * time zone.  Do range checks on these.
        !           812:         */
        !           813: 
        !           814: #define bcdunpack(val) ( (((val)>>4) & 0x0f) * 10 + ((val) & 0x0f) )
        !           815: #define istrue(x)      ((x)?1:0)
        !           816: 
        !           817:        ees->second  = bcdunpack(cp[EESM_SEC]);  /* second       */
        !           818:        ees->minute  = bcdunpack(cp[EESM_MIN]);  /* minute       */
        !           819:        ees->hour    = bcdunpack(cp[EESM_HOUR]); /* hour         */
        !           820: 
        !           821:        day          = bcdunpack(cp[EESM_DAY]);  /* day of month */
        !           822: 
        !           823:        switch (bcdunpack(cp[EESM_MON])) {       /* month        */
        !           824: 
        !           825:                /*  Add in lengths of all previous months.  Add one more
        !           826:                    if it is a leap year and after February.
        !           827:                */
        !           828:            case 12:    day += NOV;                       /*FALLSTHROUGH*/
        !           829:            case 11:    day += OCT;                       /*FALLSTHROUGH*/
        !           830:            case 10:    day += SEP;                       /*FALLSTHROUGH*/
        !           831:            case  9:    day += AUG;                       /*FALLSTHROUGH*/
        !           832:            case  8:    day += JUL;                       /*FALLSTHROUGH*/
        !           833:            case  7:    day += JUN;                       /*FALLSTHROUGH*/
        !           834:            case  6:    day += MAY;                       /*FALLSTHROUGH*/
        !           835:            case  5:    day += APR;                       /*FALLSTHROUGH*/
        !           836:            case  4:    day += MAR;                       /*FALLSTHROUGH*/
        !           837:            case  3:    day += FEB;
        !           838:                if (istrue(cp[EESM_LEAP])) day++; /*FALLSTHROUGH*/
        !           839:            case  2:    day += JAN;                       /*FALLSTHROUGH*/
        !           840:            case  1:    break;
        !           841:            default:    ees->baddata++;
        !           842:                ees->reason = CODEREASON + 11;
        !           843:                ees_event(ees, CEVNT_BADDATE);
        !           844:                ees_reset(ees);
        !           845:                return;
        !           846:        }
        !           847: 
        !           848:        ees->day     = day;
        !           849: 
        !           850:        /* Get timezone. The clocktime routine wants the number
        !           851:         * of hours to add to the delivered time to get UT.
        !           852:         * Currently -1 if BST flag set, 0 otherwise.  This
        !           853:         * is the place to tweak things if double summer time
        !           854:         * ever happens.
        !           855:         */
        !           856:        ees->tz      = istrue(cp[EESM_BST]) ? -1 : 0;
        !           857: 
        !           858:        if (ees->day > 366 || ees->day < 1 ||
        !           859:            ees->hour > 23 || ees->minute > 59 || ees->second > 59) {
        !           860:                ees->baddata++;
        !           861:                ees->reason = CODEREASON + 12;
        !           862:                ees_event(ees, CEVNT_BADDATE);
        !           863:                ees_reset(ees);
        !           864:                return;
        !           865:        }
        !           866: 
        !           867:        n_sample = ees->nsamples;
        !           868: 
        !           869:        /* Now, compute the reference time value: text -> tmp.l_ui */
        !           870:        if (!clocktime(ees->day, ees->hour, ees->minute, ees->second,
        !           871:                       ees->tz, rbufp->recv_time.l_ui, &ees->yearstart,
        !           872:                       &tmp.l_ui)) {
        !           873:                ees->baddata++;
        !           874:                ees->reason = CODEREASON + 13;
        !           875:                ees_event(ees, CEVNT_BADDATE);
        !           876:                ees_reset(ees);
        !           877:                return;
        !           878:        }
        !           879:        tmp.l_uf = 0;
        !           880: 
        !           881:        /*  DON'T use ees->arrvtime -- it may be < reftime */
        !           882:        ees->lastsampletime = tmp;
        !           883: 
        !           884:        /* If we are synchronised to the radio, update the reference time.
        !           885:         * Also keep a note of when clock was last good.
        !           886:         */
        !           887:        if (istrue(cp[EESM_MSFOK])) {
        !           888:                ees->reftime = tmp;
        !           889:                ees->clocklastgood = current_time;
        !           890:        }
        !           891: 
        !           892: 
        !           893:        /* Compute the offset.  For the fractional part of the
        !           894:         * offset we use the expected delay for the message.
        !           895:         */
        !           896:        ees->codeoffsets[n_sample].l_ui = tmp.l_ui;
        !           897:        ees->codeoffsets[n_sample].l_uf = 0;
        !           898: 
        !           899:        /* Number of seconds since the last step */
        !           900:        sincelast = this_uisec - ees->last_step;
        !           901: 
        !           902:        memset((char *) &ppsclockev, 0, sizeof ppsclockev);
        !           903: 
        !           904:        rc = ioctl(ees->io.fd, request, (char *) &ppsclockev);
        !           905:        if (dbg & DB_PRINT_EV) fprintf(stderr,
        !           906:                                         "[%x] CIOGETEV u%d %d (%x %d) gave %d (%d): %08lx %08lx %ld\n",
        !           907:                                         DB_PRINT_EV, ees->unit, ees->io.fd, request, is_pps(ees),
        !           908:                                         rc, errno, ptr[0], ptr[1], ptr[2]);
        !           909: 
        !           910:        /* If we managed to get the time of arrival, process the info */
        !           911:        if (rc >= 0) {
        !           912:                int conv = -1;
        !           913:                pps_step = ppsclockev.serial - ees->last_pps_no;
        !           914: 
        !           915:                /* Possible that PPS triggered, but text message didn't */
        !           916:                if (pps_step == 2) msyslog(LOG_ERR, "pps step = 2 @ %02d", ees->second);
        !           917:                if (pps_step == 2 && ees->second == 1) suspect_4ms_step |= 1;
        !           918:                if (pps_step == 2 && ees->second == 2) suspect_4ms_step |= 4;
        !           919: 
        !           920:                /* allow for single loss of PPS only */
        !           921:                if (pps_step != 1 && pps_step != 2)
        !           922:                    fprintf(stderr, "PPS step: %d too far off %ld (%d)\n",
        !           923:                            ppsclockev.serial, ees->last_pps_no, pps_step);
        !           924:                else if (!buftvtots((char *) &(ppsclockev.tv), &pps_arrvstamp))
        !           925:                    fprintf(stderr, "buftvtots failed\n");
        !           926:                else {  /* if ((ABS(time difference) - 0.25) < 0)
        !           927:                         * then believe it ...
        !           928:                         */
        !           929:                        l_fp diff;
        !           930:                        diff = pps_arrvstamp;
        !           931:                        conv = 0;
        !           932:                        L_SUB(&diff, &ees->arrvtime);
        !           933:                        if (dbg & DB_PRINT_CDT)
        !           934:                            printf("[%x] Have %lx.%08lx and %lx.%08lx -> %lx.%08lx @ %s",
        !           935:                                   DB_PRINT_CDT, (long)ees->arrvtime.l_ui, (long)ees->arrvtime.l_uf,
        !           936:                                   (long)pps_arrvstamp.l_ui, (long)pps_arrvstamp.l_uf,
        !           937:                                   (long)diff.l_ui, (long)diff.l_uf,
        !           938:                                   ctime(&(ppsclockev.tv.tv_sec)));
        !           939:                        if (L_ISNEG(&diff)) M_NEG(diff.l_ui, diff.l_uf);
        !           940:                        L_SUB(&diff, &acceptable_slop);
        !           941:                        if (L_ISNEG(&diff)) {   /* AOK -- pps_sample */
        !           942:                                ees->arrvtime = pps_arrvstamp;
        !           943:                                conv++;
        !           944:                                call_pps_sample++;
        !           945:                        }
        !           946:                        /* Some loss of some signals around sec = 1 */
        !           947:                        else if (ees->second == 1) {
        !           948:                                diff = pps_arrvstamp;
        !           949:                                L_ADD(&diff, &onesec);
        !           950:                                L_SUB(&diff, &ees->arrvtime);
        !           951:                                if (L_ISNEG(&diff)) M_NEG(diff.l_ui, diff.l_uf);
        !           952:                                L_SUB(&diff, &acceptable_slop);
        !           953:                                msyslog(LOG_ERR, "Have sec==1 slip %ds a=%08x-p=%08x -> %x.%08x (u=%d) %s",
        !           954:                                        pps_arrvstamp.l_ui - ees->arrvtime.l_ui,
        !           955:                                        pps_arrvstamp.l_uf,
        !           956:                                        ees->arrvtime.l_uf,
        !           957:                                        diff.l_ui, diff.l_uf,
        !           958:                                        (int)ppsclockev.tv.tv_usec,
        !           959:                                        ctime(&(ppsclockev.tv.tv_sec)));
        !           960:                                if (L_ISNEG(&diff)) {   /* AOK -- pps_sample */
        !           961:                                        suspect_4ms_step |= 2;
        !           962:                                        ees->arrvtime = pps_arrvstamp;
        !           963:                                        L_ADD(&ees->arrvtime, &onesec);
        !           964:                                        conv++;
        !           965:                                        call_pps_sample++;
        !           966:                                }
        !           967:                        }
        !           968:                }
        !           969:                ees->last_pps_no = ppsclockev.serial;
        !           970:                if (dbg & DB_PRINT_CDTC)
        !           971:                    printf(
        !           972:                            "[%x] %08lx %08lx %d u%d (%d %d)\n",
        !           973:                            DB_PRINT_CDTC, (long)pps_arrvstamp.l_ui,
        !           974:                            (long)pps_arrvstamp.l_uf, conv, ees->unit,
        !           975:                            call_pps_sample, pps_step);
        !           976:        }
        !           977: 
        !           978:        /* See if there has been a 4ms jump at a minute boundry */
        !           979:        {       l_fp    delta;
        !           980: #define        delta_isec      delta.l_ui
        !           981: #define        delta_ssec      delta.l_i
        !           982: #define        delta_sfsec     delta.l_f
        !           983:        long    delta_f_abs;
        !           984: 
        !           985:        delta.l_i = ees->arrvtime.l_i;
        !           986:        delta.l_f = ees->arrvtime.l_f;
        !           987: 
        !           988:        L_SUB(&delta, &ees->last_l);
        !           989:        delta_f_abs = delta_sfsec;
        !           990:        if (delta_f_abs < 0) delta_f_abs = -delta_f_abs;
        !           991: 
        !           992:        /* Dump the deltas each minute */
        !           993:        if (dbg & DB_DUMP_DELTAS)
        !           994:        {       
        !           995:                if (/*0 <= ees->second && */
        !           996:                    ees->second < COUNTOF(deltas))
        !           997:                        deltas[ees->second] = delta_sfsec;
        !           998:        /* Dump on second 1, as second 0 sometimes missed */
        !           999:        if (ees->second == 1) {
        !          1000:                char text[16 * COUNTOF(deltas)];
        !          1001:                char *cptr=text;
        !          1002:                int i;
        !          1003:                for (i = 0; i < COUNTOF(deltas); i++) {
        !          1004:                        snprintf(cptr, sizeof(text) / COUNTOF(deltas),
        !          1005:                                " %d.%04d", msec(deltas[i]),
        !          1006:                                subms(deltas[i]));
        !          1007:                        cptr += strlen(cptr);
        !          1008:                }
        !          1009:                msyslog(LOG_ERR, "Deltas: %d.%04d<->%d.%04d: %s",
        !          1010:                        msec(EES_STEP_F - EES_STEP_F_GRACE), subms(EES_STEP_F - EES_STEP_F_GRACE),
        !          1011:                        msec(EES_STEP_F + EES_STEP_F_GRACE), subms(EES_STEP_F + EES_STEP_F_GRACE),
        !          1012:                        text+1);
        !          1013:                for (i=0; i<((sizeof deltas) / (sizeof deltas[0])); i++) deltas[i] = 0;
        !          1014:        }
        !          1015:        }
        !          1016: 
        !          1017:        /* Lets see if we have a 4 mS step at a minute boundaary */
        !          1018:        if (    ((EES_STEP_F - EES_STEP_F_GRACE) < delta_f_abs) &&
        !          1019:                (delta_f_abs < (EES_STEP_F + EES_STEP_F_GRACE)) &&
        !          1020:                (ees->second == 0 || ees->second == 1 || ees->second == 2) &&
        !          1021:                (sincelast < 0 || sincelast > 122)
        !          1022:                ) {     /* 4ms jump at min boundry */
        !          1023:                int old_sincelast;
        !          1024:                int count=0;
        !          1025:                int sum = 0;
        !          1026:                /* Yes -- so compute the ramp time */
        !          1027:                if (ees->last_step == 0) sincelast = 0;
        !          1028:                old_sincelast = sincelast;
        !          1029: 
        !          1030:                /* First time in, just set "ees->last_step" */
        !          1031:                if(ees->last_step) {
        !          1032:                        int other_step = 0;
        !          1033:                        int third_step = 0;
        !          1034:                        int this_step = (sincelast + (60 /2)) / 60;
        !          1035:                        int p_step = ees->this_step;
        !          1036:                        int p;
        !          1037:                        ees->last_steps[p_step] = this_step;
        !          1038:                        p= p_step;
        !          1039:                        p_step++;
        !          1040:                        if (p_step >= LAST_STEPS) p_step = 0;
        !          1041:                        ees->this_step = p_step;
        !          1042:                                /* Find the "average" interval */
        !          1043:                        while (p != p_step) {
        !          1044:                                int this = ees->last_steps[p];
        !          1045:                                if (this == 0) break;
        !          1046:                                if (this != this_step) {
        !          1047:                                        if (other_step == 0 && (
        !          1048:                                                this== (this_step +2) ||
        !          1049:                                                this== (this_step -2) ||
        !          1050:                                                this== (this_step +1) ||
        !          1051:                                                this== (this_step -1)))
        !          1052:                                            other_step = this;
        !          1053:                                        if (other_step != this) {
        !          1054:                                                int idelta = (this_step - other_step);
        !          1055:                                                if (idelta < 0) idelta = - idelta;
        !          1056:                                                if (third_step == 0 && (
        !          1057:                                                        (idelta == 1) ? (
        !          1058:                                                                this == (other_step +1) ||
        !          1059:                                                                this == (other_step -1) ||
        !          1060:                                                                this == (this_step +1) ||
        !          1061:                                                                this == (this_step -1))
        !          1062:                                                        :
        !          1063:                                                        (
        !          1064:                                                                this == (this_step + other_step)/2
        !          1065:                                                                )
        !          1066:                                                        )) third_step = this;
        !          1067:                                                if (third_step != this) break;
        !          1068:                                        }
        !          1069:                                }
        !          1070:                                sum += this;
        !          1071:                                p--;
        !          1072:                                if (p < 0) p += LAST_STEPS;
        !          1073:                                count++;
        !          1074:                        }
        !          1075:                        msyslog(LOG_ERR, "MSF%d: %d: This=%d (%d), other=%d/%d, sum=%d, count=%d, pps_step=%d, suspect=%x", ees->unit, p, ees->last_steps[p], this_step, other_step, third_step, sum, count, pps_step, suspect_4ms_step);
        !          1076:                        if (count != 0) sum = ((sum * 60) + (count /2)) / count;
        !          1077: #define        SV(x) (ees->last_steps[(x + p_step) % LAST_STEPS])
        !          1078:                        msyslog(LOG_ERR, "MSF%d: %x steps %d: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
        !          1079:                                ees->unit, suspect_4ms_step, p_step, SV(0), SV(1), SV(2), SV(3), SV(4), SV(5), SV(6),
        !          1080:                                SV(7), SV(8), SV(9), SV(10), SV(11), SV(12), SV(13), SV(14), SV(15));
        !          1081:                        printf("MSF%d: steps %d: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
        !          1082:                               ees->unit, p_step, SV(0), SV(1), SV(2), SV(3), SV(4), SV(5), SV(6),
        !          1083:                               SV(7), SV(8), SV(9), SV(10), SV(11), SV(12), SV(13), SV(14), SV(15));
        !          1084: #undef SV
        !          1085:                        ees->jump_fsecs = delta_sfsec;
        !          1086:                        ees->using_ramp = 1;
        !          1087:                        if (sincelast > 170)
        !          1088:                            ees->last_step_late += sincelast - ((sum) ? sum : ees->last_step_secs);
        !          1089:                        else ees->last_step_late = 30;
        !          1090:                        if (ees->last_step_late < -60 || ees->last_step_late > 120) ees->last_step_late = 30;
        !          1091:                        if (ees->last_step_late < 0) ees->last_step_late = 0;
        !          1092:                        if (ees->last_step_late >= 60) ees->last_step_late = 59;
        !          1093:                        sincelast = 0;
        !          1094:                }
        !          1095:                else {  /* First time in -- just save info */
        !          1096:                        ees->last_step_late = 30;
        !          1097:                        ees->jump_fsecs = delta_sfsec;
        !          1098:                        ees->using_ramp = 1;
        !          1099:                        sum = 4 * 60;
        !          1100:                }
        !          1101:                ees->last_step = this_uisec;
        !          1102:                printf("MSF%d: d=%3ld.%04ld@%d :%d:%d:$%d:%d:%d\n",
        !          1103:                       ees->unit, (long)msec(delta_sfsec), (long)subms(delta_sfsec),
        !          1104:                       ees->second, old_sincelast, ees->last_step_late, count, sum,
        !          1105:                       ees->last_step_secs);
        !          1106:                msyslog(LOG_ERR, "MSF%d: d=%3d.%04d@%d :%d:%d:%d:%d:%d",
        !          1107:                        ees->unit, msec(delta_sfsec), subms(delta_sfsec), ees->second,
        !          1108:                        old_sincelast, ees->last_step_late, count, sum, ees->last_step_secs);
        !          1109:                if (sum) ees->last_step_secs = sum;
        !          1110:        }
        !          1111:        /* OK, so not a 4ms step at a minute boundry */
        !          1112:        else {
        !          1113:                if (suspect_4ms_step) msyslog(LOG_ERR,
        !          1114:                                              "MSF%d: suspect = %x, but delta of %d.%04d [%d.%04d<%d.%04d<%d.%04d: %d %d]",
        !          1115:                                              ees->unit, suspect_4ms_step, msec(delta_sfsec), subms(delta_sfsec),
        !          1116:                                              msec(EES_STEP_F - EES_STEP_F_GRACE),
        !          1117:                                              subms(EES_STEP_F - EES_STEP_F_GRACE),
        !          1118:                                              (int)msec(delta_f_abs),
        !          1119:                                              (int)subms(delta_f_abs),
        !          1120:                                              msec(EES_STEP_F + EES_STEP_F_GRACE),
        !          1121:                                              subms(EES_STEP_F + EES_STEP_F_GRACE),
        !          1122:                                              ees->second,
        !          1123:                                              sincelast);
        !          1124:                if ((delta_f_abs > EES_STEP_NOTE) && ees->last_l.l_i) {
        !          1125:                        static int ees_step_notes = EES_STEP_NOTES;
        !          1126:                        if (ees_step_notes > 0) {
        !          1127:                                ees_step_notes--;
        !          1128:                                printf("MSF%d: D=%3ld.%04ld@%02d :%d%s\n",
        !          1129:                                       ees->unit, (long)msec(delta_sfsec), (long)subms(delta_sfsec),
        !          1130:                                       ees->second, sincelast, ees_step_notes ? "" : " -- NO MORE !");
        !          1131:                                msyslog(LOG_ERR, "MSF%d: D=%3d.%04d@%02d :%d%s",
        !          1132:                                        ees->unit, msec(delta_sfsec), subms(delta_sfsec), ees->second, (ees->last_step) ? sincelast : -1, ees_step_notes ? "" : " -- NO MORE !");
        !          1133:                        }
        !          1134:                }
        !          1135:        }
        !          1136:        }
        !          1137:        ees->last_l = ees->arrvtime;
        !          1138: 
        !          1139:        /* IF we have found that it's ramping
        !          1140:         * && it's within twice the expected ramp period
        !          1141:         * && there is a non zero step size (avoid /0 !)
        !          1142:         * THEN we twiddle things
        !          1143:         */
        !          1144:        if (ees->using_ramp &&
        !          1145:            sincelast < (ees->last_step_secs)*2 &&
        !          1146:            ees->last_step_secs)
        !          1147:        {       long    sec_of_ramp = sincelast + ees->last_step_late;
        !          1148:        long    fsecs;
        !          1149:        l_fp    inc;
        !          1150: 
        !          1151:        /* Ramp time may vary, so may ramp for longer than last time */
        !          1152:        if (sec_of_ramp > (ees->last_step_secs + 120))
        !          1153:            sec_of_ramp =  ees->last_step_secs;
        !          1154: 
        !          1155:        /* sec_of_ramp * ees->jump_fsecs may overflow 2**32 */
        !          1156:        fsecs = sec_of_ramp * (ees->jump_fsecs /  ees->last_step_secs);
        !          1157: 
        !          1158:        if (dbg & DB_LOG_DELTAS) msyslog(LOG_ERR,
        !          1159:                                           "[%x] MSF%d: %3ld/%03d -> d=%11ld (%d|%ld)",
        !          1160:                                           DB_LOG_DELTAS,
        !          1161:                                           ees->unit, sec_of_ramp, ees->last_step_secs, fsecs,
        !          1162:                                           pps_arrvstamp.l_f, pps_arrvstamp.l_f + fsecs);
        !          1163:        if (dbg & DB_PRINT_DELTAS) printf(
        !          1164:                "MSF%d: %3ld/%03d -> d=%11ld (%ld|%ld)\n",
        !          1165:                ees->unit, sec_of_ramp, ees->last_step_secs, fsecs,
        !          1166:                (long)pps_arrvstamp.l_f, pps_arrvstamp.l_f + fsecs);
        !          1167: 
        !          1168:        /* Must sign extend the result */
        !          1169:        inc.l_i = (fsecs < 0) ? -1 : 0;
        !          1170:        inc.l_f = fsecs;
        !          1171:        if (dbg & DB_INC_PPS)
        !          1172:        {       L_SUB(&pps_arrvstamp, &inc);
        !          1173:        L_SUB(&ees->arrvtime, &inc);
        !          1174:        }
        !          1175:        else
        !          1176:        {       L_ADD(&pps_arrvstamp, &inc);
        !          1177:        L_ADD(&ees->arrvtime, &inc);
        !          1178:        }
        !          1179:        }
        !          1180:        else {
        !          1181:                if (dbg & DB_LOG_DELTAS) msyslog(LOG_ERR,
        !          1182:                                                   "[%x] MSF%d: ees->using_ramp=%d, sincelast=%x / %x, ees->last_step_secs=%x",
        !          1183:                                                   DB_LOG_DELTAS,
        !          1184:                                                   ees->unit, ees->using_ramp,
        !          1185:                                                   sincelast,
        !          1186:                                                   (ees->last_step_secs)*2,
        !          1187:                                                   ees->last_step_secs);
        !          1188:                if (dbg & DB_PRINT_DELTAS) printf(
        !          1189:                        "[%x] MSF%d: ees->using_ramp=%d, sincelast=%x / %x, ees->last_step_secs=%x\n",
        !          1190:                        DB_LOG_DELTAS,
        !          1191:                        ees->unit, ees->using_ramp,
        !          1192:                        sincelast,
        !          1193:                        (ees->last_step_secs)*2,
        !          1194:                        ees->last_step_secs);
        !          1195:        }
        !          1196: 
        !          1197:        L_SUB(&ees->arrvtime, &offset_fudge[ees->unit]);
        !          1198:        L_SUB(&pps_arrvstamp, &offset_fudge[ees->unit]);
        !          1199: 
        !          1200:        if (call_pps_sample && !(dbg & DB_NO_PPS)) {
        !          1201:                /* Sigh -- it expects its args negated */
        !          1202:                L_NEG(&pps_arrvstamp);
        !          1203:                /*
        !          1204:                 * I had to disable this here, since it appears there is no pointer to the
        !          1205:                 * peer structure.
        !          1206:                 *
        !          1207:                 (void) pps_sample(peer, &pps_arrvstamp);
        !          1208:                */
        !          1209:        }
        !          1210: 
        !          1211:        /* Subtract off the local clock time stamp */
        !          1212:        L_SUB(&ees->codeoffsets[n_sample], &ees->arrvtime);
        !          1213:        if (dbg & DB_LOG_SAMPLES) msyslog(LOG_ERR,
        !          1214:                                            "MSF%d: [%x] %d (ees: %d %d) (pps: %d %d)%s",
        !          1215:                                            ees->unit, DB_LOG_DELTAS, n_sample,
        !          1216:                                            ees->codeoffsets[n_sample].l_f,
        !          1217:                                            ees->codeoffsets[n_sample].l_f / 4295,
        !          1218:                                            pps_arrvstamp.l_f,
        !          1219:                                            pps_arrvstamp.l_f /4295,
        !          1220:                                            (dbg & DB_NO_PPS) ? " [no PPS]" : "");
        !          1221: 
        !          1222:        if (ees->nsamples++ == NCODES-1) ees_process(ees);
        !          1223: 
        !          1224:        /* Done! */
        !          1225: }
        !          1226: 
        !          1227: 
        !          1228: /* offcompare - auxiliary comparison routine for offset sort */
        !          1229: 
        !          1230: #ifdef QSORT_USES_VOID_P
        !          1231: static int
        !          1232: offcompare(
        !          1233:        const void *va,
        !          1234:        const void *vb
        !          1235:        )
        !          1236: {
        !          1237:        const l_fp *a = (const l_fp *)va;
        !          1238:        const l_fp *b = (const l_fp *)vb;
        !          1239:        return(L_ISGEQ(a, b) ? (L_ISEQU(a, b) ? 0 : 1) : -1);
        !          1240: }
        !          1241: #else
        !          1242: static int
        !          1243: offcompare(
        !          1244:        const l_fp *a,
        !          1245:        const l_fp *b
        !          1246:        )
        !          1247: {
        !          1248:        return(L_ISGEQ(a, b) ? (L_ISEQU(a, b) ? 0 : 1) : -1);
        !          1249: }
        !          1250: #endif /* QSORT_USES_VOID_P */
        !          1251: 
        !          1252: 
        !          1253: /* ees_process - process a pile of samples from the clock */
        !          1254: static void
        !          1255: ees_process(
        !          1256:        struct eesunit *ees
        !          1257:        )
        !          1258: {
        !          1259:        static int last_samples = -1;
        !          1260:        register int i, j;
        !          1261:        register int noff;
        !          1262:        register l_fp *coffs = ees->codeoffsets;
        !          1263:        l_fp offset, tmp;
        !          1264:        double dispersion;      /* ++++ */
        !          1265:        int lostsync, isinsync;
        !          1266:        int samples = ees->nsamples;
        !          1267:        int samplelog = 0;      /* keep "gcc -Wall" happy ! */
        !          1268:        int samplereduce = (samples + 1) / 2;
        !          1269:        double doffset;
        !          1270: 
        !          1271:        /* Reset things to zero so we don't have to worry later */
        !          1272:        ees_reset(ees);
        !          1273: 
        !          1274:        if (sloppyclockflag[ees->unit]) {
        !          1275:                samplelog = (samples <  2) ? 0 :
        !          1276:                        (samples <  5) ? 1 :
        !          1277:                        (samples <  9) ? 2 :
        !          1278:                        (samples < 17) ? 3 :
        !          1279:                        (samples < 33) ? 4 : 5;
        !          1280:                samplereduce = (1 << samplelog);
        !          1281:        }
        !          1282: 
        !          1283:        if (samples != last_samples &&
        !          1284:            ((samples != (last_samples-1)) || samples < 3)) {
        !          1285:                msyslog(LOG_ERR, "Samples=%d (%d), samplereduce=%d ....",
        !          1286:                        samples, last_samples, samplereduce);
        !          1287:                last_samples = samples;
        !          1288:        }
        !          1289:        if (samples < 1) return;
        !          1290: 
        !          1291:        /* If requested, dump the raw data we have in the buffer */
        !          1292:        if (ees->dump_vals) dump_buf(coffs, 0, samples, "Raw  data  is:");
        !          1293: 
        !          1294:        /* Sort the offsets, trim off the extremes, then choose one. */
        !          1295:        qsort(
        !          1296: #ifdef QSORT_USES_VOID_P
        !          1297:            (void *)
        !          1298: #else
        !          1299:            (char *)
        !          1300: #endif
        !          1301:            coffs, (size_t)samples, sizeof(l_fp), offcompare);
        !          1302: 
        !          1303:        noff = samples;
        !          1304:        i = 0;
        !          1305:        while ((noff - i) > samplereduce) {
        !          1306:                /* Trim off the sample which is further away
        !          1307:                 * from the median.  We work this out by doubling
        !          1308:                 * the median, subtracting off the end samples, and
        !          1309:                 * looking at the sign of the answer, using the
        !          1310:                 * identity (c-b)-(b-a) == 2*b-a-c
        !          1311:                 */
        !          1312:                tmp = coffs[(noff + i)/2];
        !          1313:                L_ADD(&tmp, &tmp);
        !          1314:                L_SUB(&tmp, &coffs[i]);
        !          1315:                L_SUB(&tmp, &coffs[noff-1]);
        !          1316:                if (L_ISNEG(&tmp)) noff--; else i++;
        !          1317:        }
        !          1318: 
        !          1319:        /* If requested, dump the reduce data we have in the buffer */
        !          1320:        if (ees->dump_vals) dump_buf(coffs, i, noff, "Reduced    to:");
        !          1321: 
        !          1322:        /* What we do next depends on the setting of the sloppy clock flag.
        !          1323:         * If it is on, average the remainder to derive our estimate.
        !          1324:         * Otherwise, just pick a representative value from the remaining stuff
        !          1325:         */
        !          1326:        if (sloppyclockflag[ees->unit]) {
        !          1327:                offset.l_ui = offset.l_uf = 0;
        !          1328:                for (j = i; j < noff; j++)
        !          1329:                    L_ADD(&offset, &coffs[j]);
        !          1330:                for (j = samplelog; j > 0; j--)
        !          1331:                    L_RSHIFTU(&offset);
        !          1332:        }
        !          1333:        else offset = coffs[i+BESTSAMPLE];
        !          1334: 
        !          1335:        /* Compute the dispersion as the difference between the
        !          1336:         * lowest and highest offsets that remain in the
        !          1337:         * consideration list.
        !          1338:         *
        !          1339:         * It looks like MOST clocks have MOD (max error), so halve it !
        !          1340:         */
        !          1341:        tmp = coffs[noff-1];
        !          1342:        L_SUB(&tmp, &coffs[i]);
        !          1343: #define        FRACT_SEC(n) ((1 << 30) / (n/2))
        !          1344:        dispersion = LFPTOFP(&tmp) / 2; /* ++++ */
        !          1345:        if (dbg & (DB_SYSLOG_SMPLI | DB_SYSLOG_SMPLE)) msyslog(
        !          1346:                (dbg & DB_SYSLOG_SMPLE) ? LOG_ERR : LOG_INFO,
        !          1347:                "I: [%x] Offset=%06d (%d), disp=%f%s [%d], %d %d=%d %d:%d %d=%d %d",
        !          1348:                dbg & (DB_SYSLOG_SMPLI | DB_SYSLOG_SMPLE),
        !          1349:                offset.l_f / 4295, offset.l_f,
        !          1350:                (dispersion * 1526) / 100,
        !          1351:                (sloppyclockflag[ees->unit]) ? " by averaging" : "",
        !          1352:                FRACT_SEC(10) / 4295,
        !          1353:                (coffs[0].l_f) / 4295,
        !          1354:                i,
        !          1355:                (coffs[i].l_f) / 4295,
        !          1356:                (coffs[samples/2].l_f) / 4295,
        !          1357:                (coffs[i+BESTSAMPLE].l_f) / 4295,
        !          1358:                noff-1,
        !          1359:                (coffs[noff-1].l_f) / 4295,
        !          1360:                (coffs[samples-1].l_f) / 4295);
        !          1361: 
        !          1362:        /* Are we playing silly wotsits ?
        !          1363:         * If we are using all data, see if there is a "small" delta,
        !          1364:         * and if so, blurr this with 3/4 of the delta from the last value
        !          1365:         */
        !          1366:        if (ees->usealldata && ees->offset.l_uf) {
        !          1367:                long diff = (long) (ees->offset.l_uf - offset.l_uf);
        !          1368: 
        !          1369:                /* is the delta small enough ? */
        !          1370:                if ((- FRACT_SEC(100)) < diff && diff < FRACT_SEC(100)) {
        !          1371:                        int samd = (64 * 4) / samples;
        !          1372:                        long new;
        !          1373:                        if (samd < 2) samd = 2;
        !          1374:                        new = offset.l_uf + ((diff * (samd -1)) / samd);
        !          1375: 
        !          1376:                        /* Sign change -> need to fix up int part */
        !          1377:                        if ((new & 0x80000000) !=
        !          1378:                            (((long) offset.l_uf) & 0x80000000))
        !          1379:                        {       NLOG(NLOG_CLOCKINFO) /* conditional if clause for conditional syslog */
        !          1380:                                        msyslog(LOG_INFO, "I: %lx != %lx (%lx %lx), so add %d",
        !          1381:                                                new & 0x80000000,
        !          1382:                                                ((long) offset.l_uf) & 0x80000000,
        !          1383:                                                new, (long) offset.l_uf,
        !          1384:                                                (new < 0) ? -1 : 1);
        !          1385:                                offset.l_ui += (new < 0) ? -1 : 1;
        !          1386:                        }
        !          1387:                        dispersion /= 4;
        !          1388:                        if (dbg & (DB_SYSLOG_SMTHI | DB_SYSLOG_SMTHE)) msyslog(
        !          1389:                                (dbg & DB_SYSLOG_SMTHE) ? LOG_ERR : LOG_INFO,
        !          1390:                                "I: [%x] Smooth data: %ld -> %ld, dispersion now %f",
        !          1391:                                dbg & (DB_SYSLOG_SMTHI | DB_SYSLOG_SMTHE),
        !          1392:                                ((long) offset.l_uf) / 4295, new / 4295,
        !          1393:                                (dispersion * 1526) / 100);
        !          1394:                        offset.l_uf = (unsigned long) new;
        !          1395:                }
        !          1396:                else if (dbg & (DB_SYSLOG_NSMTHI | DB_SYSLOG_NSMTHE)) msyslog(
        !          1397:                        (dbg & DB_SYSLOG_NSMTHE) ? LOG_ERR : LOG_INFO,
        !          1398:                        "[%x] No smooth as delta not %d < %ld < %d",
        !          1399:                        dbg & (DB_SYSLOG_NSMTHI | DB_SYSLOG_NSMTHE),
        !          1400:                        - FRACT_SEC(100), diff, FRACT_SEC(100));
        !          1401:        }
        !          1402:        else if (dbg & (DB_SYSLOG_NSMTHI | DB_SYSLOG_NSMTHE)) msyslog(
        !          1403:                (dbg & DB_SYSLOG_NSMTHE) ? LOG_ERR : LOG_INFO,
        !          1404:                "I: [%x] No smooth as flag=%x and old=%x=%d (%d:%d)",
        !          1405:                dbg & (DB_SYSLOG_NSMTHI | DB_SYSLOG_NSMTHE),
        !          1406:                ees->usealldata, ees->offset.l_f, ees->offset.l_uf,
        !          1407:                offset.l_f, ees->offset.l_f - offset.l_f);
        !          1408: 
        !          1409:        /* Collect offset info for debugging info */
        !          1410:        ees->offset = offset;
        !          1411:        ees->lowoffset = coffs[i];
        !          1412:        ees->highoffset = coffs[noff-1];
        !          1413: 
        !          1414:        /* Determine synchronization status.  Can be unsync'd either
        !          1415:         * by a report from the clock or by a leap hold.
        !          1416:         *
        !          1417:         * Loss of the radio signal for a short time does not cause
        !          1418:         * us to go unsynchronised, since the receiver keeps quite
        !          1419:         * good time on its own.  The spec says 20ms in 4 hours; the
        !          1420:         * observed drift in our clock (Cambridge) is about a second
        !          1421:         * a day, but even that keeps us within the inherent tolerance
        !          1422:         * of the clock for about 15 minutes. Observation shows that
        !          1423:         * the typical "short" outage is 3 minutes, so to allow us
        !          1424:         * to ride out those, we will give it 5 minutes.
        !          1425:         */
        !          1426:        lostsync = current_time - ees->clocklastgood > 300 ? 1 : 0;
        !          1427:        isinsync = (lostsync || ees->leaphold > current_time) ? 0 : 1;
        !          1428: 
        !          1429:        /* Done.  Use time of last good, synchronised code as the
        !          1430:         * reference time, and lastsampletime as the receive time.
        !          1431:         */
        !          1432:        if (ees->fix_pending) {
        !          1433:                msyslog(LOG_ERR, "MSF%d: fix_pending=%d -> jump %x.%08x\n",
        !          1434:                        ees->fix_pending, ees->unit, offset.l_i, offset.l_f);
        !          1435:                ees->fix_pending = 0;
        !          1436:        }
        !          1437:        LFPTOD(&offset, doffset);
        !          1438:        refclock_receive(ees->peer);
        !          1439:        ees_event(ees, lostsync ? CEVNT_PROP : CEVNT_NOMINAL);
        !          1440: }
        !          1441: 
        !          1442: /* msfees_poll - called by the transmit procedure */
        !          1443: static void
        !          1444: msfees_poll(
        !          1445:        int unit,
        !          1446:        struct peer *peer
        !          1447:        )
        !          1448: {
        !          1449:        if (unit >= MAXUNITS) {
        !          1450:                msyslog(LOG_ERR, "ees clock poll: INTERNAL: unit %d invalid",
        !          1451:                        unit);
        !          1452:                return;
        !          1453:        }
        !          1454:        if (!unitinuse[unit]) {
        !          1455:                msyslog(LOG_ERR, "ees clock poll: INTERNAL: unit %d unused",
        !          1456:                        unit);
        !          1457:                return;
        !          1458:        }
        !          1459: 
        !          1460:        ees_process(eesunits[unit]);
        !          1461: 
        !          1462:        if ((current_time - eesunits[unit]->lasttime) > 150)
        !          1463:            ees_event(eesunits[unit], CEVNT_FAULT);
        !          1464: }
        !          1465: 
        !          1466: 
        !          1467: #else
        !          1468: int refclock_msfees_bs;
        !          1469: #endif /* REFCLOCK */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>