]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
Cleanup from Dave Mills
authorHarlan Stenn <stenn@ntp.org>
Sat, 2 Oct 2004 07:56:39 +0000 (03:56 -0400)
committerHarlan Stenn <stenn@ntp.org>
Sat, 2 Oct 2004 07:56:39 +0000 (03:56 -0400)
bk: 415e5f37nb-iKQVDJssX04Nptoiegw

include/ntp_refclock.h
include/ntpd.h
ntpd/ntp_config.c
ntpd/ntp_loopfilter.c
ntpd/ntp_proto.c
ntpd/ntp_refclock.c
ntpd/ntp_request.c
ntpd/refclock_acts.c
ntpd/refclock_wwvb.c

index 7a625f74eb6e4cdb5d28a310e5692bff4be2d010..0fcde55cb9ff1849d96c1459dc989ff1cb4f8a5a 100644 (file)
@@ -170,6 +170,7 @@ struct refclockbug {
 #define LDISC_CHU      0x8     /* depredated */
 #define LDISC_PPS      0x10    /* ppsclock, ppsapi */
 #define LDISC_RAW      0x20    /* raw binary */
+#define LDISC_ECHO     0x40    /* enable echo */
 
 struct refclockproc {
        struct  refclockio io;  /* I/O handler structure */
@@ -254,15 +255,16 @@ extern    void    refclock_buginfo P((struct sockaddr_storage *,
 extern void    refclock_control P((struct sockaddr_storage *,
                                    struct refclockstat *,
                                    struct refclockstat *));
-extern int     refclock_open   P((char *, int, int));
+extern int     refclock_open   P((char *, u_int, u_int));
+extern int     refclock_setup  P((int, u_int, u_int));
 extern void    refclock_timer  P((struct peer *));
 extern void    refclock_transmit P((struct peer *));
-extern int     refclock_ioctl  P((int, int));
+extern int     refclock_ioctl  P((int, u_int));
 extern         int     refclock_process P((struct refclockproc *));
 extern         void    refclock_process_offset P((struct refclockproc *, l_fp, l_fp, double));
 extern void    refclock_report P((struct peer *, int));
-extern int     refclock_gtlin  P((struct recvbuf *, char *, int,
-                                   l_fp *));
+extern int     refclock_gtlin  P((struct recvbuf *, char *, int, l_fp *));
+extern int     refclock_gtraw  P((struct recvbuf *, char *, int, l_fp *));
 #endif /* REFCLOCK */
 
 #endif /* NTP_REFCLOCK_H */
index b59975bd165a92d1b8c8b4c32ed1a7ad266e6cd7..616161b640ff32500d5ed60049fdae79cf7402ad 100644 (file)
@@ -312,7 +312,6 @@ extern int  forground_process;      /* run the process in the forground */
 extern u_char  sys_poll;               /* system poll interval (log2 s) */
 extern int     state;                  /* clock discipline state */
 extern int     tc_counter;             /* poll-adjust counter */
-extern u_long  last_time;              /* time of last clock update (s) */
 extern double  last_offset;            /* last clock offset (s) */
 extern double  allan_xpt;              /* Allan intercept (s) */
 extern double  clock_jitter;           /* clock jitter (s) */
index b643cbd7df88ba5bb11e14ad062e550dc36d3c13..49fa569dffde64eeccbcd6622a439fc24c96a4dd 100644 (file)
@@ -692,7 +692,10 @@ getconfig(
                        
                        peerversion = NTP_VERSION;
                        minpoll = NTP_MINDPOLL;
-                       maxpoll = NTP_MAXDPOLL;
+                       if (!ISREFCLOCKADR(&peeraddr))
+                               maxpoll = NTP_MAXDPOLL;
+                       else
+                               maxpoll = minpoll;
                        peerkey = 0;
                        peerkeystr = (u_char *)"*";
                        peerflags = 0;
index 90d3a1fba4d0e756ed640c18dba86c412bd8496a..9fd776ba75cbb5274ed4e06fba5932f474617890 100644 (file)
@@ -120,9 +120,10 @@ static double clock_offset;        /* current offset (s) */
 double clock_jitter;           /* offset jitter (s) */
 double drift_comp;             /* frequency (s/s) */
 double clock_stability;        /* frequency stability (s/s) */
-u_long last_time;              /* last clock update time (s) */
-u_long pps_control;            /* last pps sample time */
-static void rstclock P((int, double)); /* transition function */
+u_long sys_clocktime;          /* last system clock update */
+u_long pps_control;            /* last pps update */
+
+static void rstclock P((int, u_long, double)); /* transition function */
 
 #ifdef KERNEL_PLL
 struct timex ntv;              /* kernel API parameters */
@@ -181,7 +182,7 @@ init_loopfilter(void)
         * Initialize state variables. Initially, we expect no drift
         * file, so set the state to S_NSET.
         */
-       rstclock(S_NSET, 0);
+       rstclock(S_NSET, 0, 0);
        clock_jitter = LOGTOD(sys_precision);
 }
 
@@ -321,7 +322,7 @@ local_clock(
         * stepped. 
         */
        clock_frequency = flladj = plladj = 0;
-       mu = sys_clocktime - last_time;
+       mu = peer->epoch - sys_clocktime;
        rval = 1;
        if (fabs(fp_offset) > clock_max && clock_max > 0) {
                switch (state) {
@@ -388,12 +389,12 @@ local_clock(
                        sys_poll = NTP_MINPOLL;
                        rval = 2;
                        if (state == S_NSET) {
-                               rstclock(S_FREQ, 0);
+                               rstclock(S_FREQ, peer->epoch, 0);
                                return (rval);
                        }
                        break;
                }
-               rstclock(S_SYNC, 0);
+               rstclock(S_SYNC, peer->epoch, 0);
        } else {
                switch (state) {
 
@@ -405,7 +406,7 @@ local_clock(
                 */
                case S_NSET:
                        clock_offset = fp_offset;
-                       rstclock(S_FREQ, fp_offset);
+                       rstclock(S_FREQ, peer->epoch, fp_offset);
                        return (0);
 
                /*
@@ -441,30 +442,30 @@ local_clock(
                        /*
                         * The FLL and PLL frequency gain constants
                         * depend on the poll interval and Allan
-                        * intercept. The PLL constant is calculated
-                        * throughout the poll interval range, but the
-                        * update interval is clamped so as not to
-                        * exceed the poll interval. The FLL gain is
-                        * zero below one-half the Allan intercept and
-                        * unity at MAXPOLL. It decreases as 1 /
-                        * (MAXPOLL + 1 - poll interval) in a feeble
-                        * effort to match the loop stiffness to the
-                        * Allan wobble. Particularly for the PLL, these
-                        * measures allow oversampling, but not
-                        * undersampling and insure stability even when
-                        * the rules of fair engagement are broken.
+                        * intercept. The FLL is not used below one-half
+                        * the Allan intercept. Above that the loop gain
+                        * increases in steps to 1 / CLOCK_AVG. 
                         */
                        if (ULOGTOD(sys_poll) > allan_xpt / 2) {
                                dtemp = CLOCK_FLL - sys_poll;
+                               if (dtemp < CLOCK_AVG)
+                                       dtemp = CLOCK_AVG;
                                flladj = (fp_offset - clock_offset) /
                                    (max(mu, allan_xpt) * dtemp);
                        }
+
+                       /*
+                        * For the PLL the integration interval
+                        * (numerator) is the minimum of the update
+                        * interval and poll interval. This allows
+                        * oversampling, but not undersampling.
+                        */ 
                        etemp = min(mu, (u_long)ULOGTOD(sys_poll));
                        dtemp = 4 * CLOCK_PLL * ULOGTOD(sys_poll);
                        plladj = fp_offset * etemp / (dtemp * dtemp);
                        break;
                }
-               rstclock(S_SYNC, fp_offset);
+               rstclock(S_SYNC, peer->epoch, fp_offset);
        }
 
 #ifdef KERNEL_PLL
@@ -722,10 +723,14 @@ adj_host_clock(
                return;
 
        /*
-        * Implement the phase and frequency adjustments. Note the
-        * black art formerly practiced here has been whitewashed.
+        * Implement the phase and frequency adjustments. The gain
+        * factor (denominator) is not allowed to increase beyond the
+        * Allan intercept. It doesn't make sense to average phase noise
+        * beyond this point and it helps to damp residual offset at the
+        * longer poll intervals.
         */
-       adjustment = clock_offset / (CLOCK_PLL * ULOGTOD(sys_poll));
+       adjustment = clock_offset / (CLOCK_PLL * min(ULOGTOD(sys_poll),
+           allan_xpt));
        clock_offset -= adjustment;
        adj_systime(adjustment + drift_comp);
 #endif /* LOCKCLOCK */
@@ -739,18 +744,19 @@ adj_host_clock(
  */
 static void
 rstclock(
-       int trans,              /* new state */
-       double offset           /* last offset */
+       int     trans,          /* new state */
+       u_long  update,         /* new update time */
+       double  offset          /* new offset */
        )
 {
        state = trans;
-       last_time = sys_clocktime;
+       sys_clocktime = update;
        last_base = offset - clock_offset;
        last_offset = clock_offset = offset;
 #ifdef DEBUG
        if (debug)
-               printf("local_clock: time %lu clock %.6f offset %.6f freq %.3f state %d\n",
-                   last_time, last_base, last_offset, drift_comp *
+               printf("local_clock: time %lu base %.6f offset %.6f freq %.3f state %d\n",
+                   sys_clocktime, last_base, last_offset, drift_comp *
                    1e6, trans);
 #endif
 }
@@ -875,7 +881,7 @@ loop_config(
                 */
                if (freq <= NTP_MAXFREQ && freq >= -NTP_MAXFREQ) {
                        drift_comp = freq;
-                       rstclock(S_FSET, 0);
+                       rstclock(S_FSET, 0, 0);
                } else {
                        drift_comp = 0;
                }
@@ -939,7 +945,7 @@ loop_config(
 
        case LOOP_FREQ:                 /* initial frequency */ 
                drift_comp = freq / 1e6;
-               rstclock(S_FSET, 0);
+               rstclock(S_FSET, 0, 0);
                break;
        }
 }
index cbe67105fd8f5502218cf72edfaefdb02cc6f5ee..01fb9cd34a43da35c4bd0f48b8983822aabbf9f7 100644 (file)
@@ -1318,14 +1318,10 @@ clock_update(void)
                sys_poll = sys_peer->minpoll;
        if (sys_poll > sys_peer->maxpoll)
                sys_poll = sys_peer->maxpoll;
-#ifdef REFCLOCK
-       if (!(sys_peer->flags & FLAG_REFCLOCK))
-               poll_update(sys_peer, sys_poll);
-#endif /* REFCLOCK */
+       poll_update(sys_peer, sys_poll);
        if (sys_peer->epoch <= sys_clocktime)
                return;
 
-       sys_clocktime = sys_peer->epoch;
 #ifdef DEBUG
        if (debug)
                printf("clock_update: at %ld assoc %d \n", current_time,
@@ -1567,6 +1563,7 @@ peer_clear(
        peer->estbdelay = sys_bdelay;
        peer->hpoll = peer->minpoll;
        peer->ppoll = peer->maxpoll;
+       peer->disp = MAXDISPERSE;
        peer->jitter = SQRT(MAXDISPERSE);
        peer->epoch = current_time;
 #ifdef REFCLOCK
index faa9ddea9be0520f2f50c475a3bc6731474f3e6f..de3dfc9013b8974f47998974eaf0542fdc790d72 100644 (file)
@@ -68,6 +68,7 @@
  */
 #define MAXUNIT        4       /* max units */
 #define FUDGEFAC       .1      /* fudge correction factor */
+#define LF             0x0a    /* ASCII LF */
 
 #ifdef PPS
 int    fdpps;                  /* ppsclock legacy */
@@ -122,23 +123,16 @@ refclock_report(
                pp->lastevent = (u_char)code;
                if (code == CEVNT_FAULT)
                        msyslog(LOG_ERR,
-                               "clock %s event '%s' (0x%02x)",
-                               refnumtoa(&peer->srcadr),
-                               ceventstr(code), code);
+                           "clock %s event '%s' (0x%02x)",
+                           refnumtoa(&peer->srcadr),
+                           ceventstr(code), code);
                else {
-                       NLOG(NLOG_CLOCKEVENT)
-                               msyslog(LOG_INFO,
-                               "clock %s event '%s' (0x%02x)",
-                               refnumtoa(&peer->srcadr),
-                               ceventstr(code), code);
+                       NLOG(NLOG_CLOCKEVENT)msyslog(LOG_INFO,
+                           "clock %s event '%s' (0x%02x)",
+                           refnumtoa(&peer->srcadr),
+                           ceventstr(code), code);
                }
        }
-#ifdef DEBUG
-       if (debug)
-               printf("clock %s event '%s' (0x%02x)\n",
-                       refnumtoa(&peer->srcadr),
-                       ceventstr(code), code);
-#endif
 }
 
 
@@ -581,11 +575,10 @@ refclock_receive(
        pp = peer->procptr;
        peer->received++;
        peer->timereceived = current_time;
-       peer->leap = pp->leap;
-       if (peer->leap == LEAP_NOTINSYNC) {
+       if (peer->leap != LEAP_NOTINSYNC && pp->leap !=
+           LEAP_NOTINSYNC)
                refclock_report(peer, CEVNT_FAULT);
-               return;
-       }
+       peer->leap = pp->leap;
        if (!peer->reach)
                report_event(EVNT_REACH, peer);
        peer->reach |= 1;
@@ -618,24 +611,69 @@ refclock_receive(
  * refclock_gtlin - groom next input line and extract timestamp
  *
  * This routine processes the timecode received from the clock and
- * removes the parity bit and control characters. If a timestamp is
- * present in the timecode, as produced by the tty_clk STREAMS module,
- * it returns that as the timestamp; otherwise, it returns the buffer
- *  timestamp. The routine return code is the number of characters in
- * the line.
+ * strips the parity bit and control characters. It returns the number
+ * of characters in the line followed by a NULL character ('\0'), which
+ * is not included in the count. In case of an empty line, the previous
+ * line is preserved.
  */
 int
 refclock_gtlin(
        struct recvbuf *rbufp,  /* receive buffer pointer */
-       char *lineptr,          /* current line pointer */
-       int bmax,               /* remaining characters in line */
-       l_fp *tsptr             /* pointer to timestamp returned */
+       char    *lineptr,       /* current line pointer */
+       int     bmax,           /* remaining characters in line */
+       l_fp    *tsptr          /* pointer to timestamp returned */
        )
 {
-       char *dpt, *dpend, *dp;
-       int i;
-       l_fp trtmp, tstmp;
-       char c;
+       char    s[BMAX];
+       char    *dpt, *dpend, *dp;
+
+       dpt = s;
+       dpend = s + refclock_gtraw(rbufp, s, BMAX - 1, tsptr);
+       if (dpend - dpt > bmax - 1)
+               dpend = dpt + bmax - 1;
+       for (dp = lineptr; dpt < dpend; dpt++) {
+               char    c;
+
+               c = *dpt & 0x7f;
+               if (c >= 0x20 && c < 0x7f)
+                       *dp++ = c;
+       }
+       if (dp == lineptr)
+               return (0);
+
+       *dp = '\0';
+       return (dp - lineptr);
+}
+
+
+/*
+ * refclock_gtraw - get next line/chunk of data
+ *
+ * This routine returns the raw data received from the clock in both
+ * canonical or raw modes. The terminal interface routines map CR to LF.
+ * In canonical mode this results in two lines, one containing data
+ * followed by LF and another containing only LF. In raw mode the
+ * interface routines can deliver arbitraty chunks of data from one
+ * character to a maximum specified by the calling routine. In either
+ * mode the routine returns the number of characters in the line
+ * followed by a NULL character ('\0'), which is not included in the
+ * count.
+ *
+ * If a timestamp is present in the timecode, as produced by the tty_clk
+ * STREAMS module, it returns that as the timestamp; otherwise, it
+ * returns the buffer timestamp.
+ */
+int
+refclock_gtraw(
+       struct recvbuf *rbufp,  /* receive buffer pointer */
+       char    *lineptr,       /* current line pointer */
+       int     bmax,           /* remaining characters in line */
+       l_fp    *tsptr          /* pointer to timestamp returned */
+       )
+{
+       char    *dpt, *dpend, *dp;
+       l_fp    trtmp, tstmp;
+       int     i;
 
        /*
         * Check for the presence of a timestamp left by the tty_clock
@@ -647,7 +685,6 @@ refclock_gtlin(
        dpt = (char *)rbufp->recv_buffer;
        dpend = dpt + rbufp->recv_length;
        trtmp = rbufp->recv_time;
-
        if (dpend >= dpt + 8) {
                if (buftvtots(dpend - 8, &tstmp)) {
                        L_SUB(&trtmp, &tstmp);
@@ -672,29 +709,19 @@ refclock_gtlin(
        }
 
        /*
-        * Edit timecode to remove control chars. Don't monkey with the
-        * line buffer if the input buffer contains no ASCII printing
-        * characters.
+        * Copy the raw buffer to the user string. The string is padded
+        * with a NULL, which is not included in the character count.
         */
        if (dpend - dpt > bmax - 1)
                dpend = dpt + bmax - 1;
-       for (dp = lineptr; dpt < dpend; dpt++) {
-               c = (char) (*dpt & 0x7f);
-               if (c >= ' ')
-                       *dp++ = c;
-       }
+       for (dp = lineptr; dpt < dpend; dpt++)
+               *dp++ = *dpt;
+       *dp = '\0';
        i = dp - lineptr;
-       if (i > 0)
-               *dp = '\0';
 #ifdef DEBUG
-       if (debug > 1) {
-               if (i > 0)
-                       printf("refclock_gtlin: fd %d time %s timecode %d %s\n",
-                           rbufp->fd, ulfptoa(&trtmp, 6), i, lineptr);
-               else
-                       printf("refclock_gtlin: fd %d time %s\n",
-                           rbufp->fd, ulfptoa(&trtmp, 6));
-       }
+       if (debug > 1)
+               printf("refclock_gtraw: fd %d time %s timecode %d %s\n",
+                   rbufp->fd, ulfptoa(&trtmp, 6), i, lineptr);
 #endif
        *tsptr = trtmp;
        return (i);
@@ -715,24 +742,17 @@ refclock_gtlin(
  */
 int
 refclock_open(
-       char *dev,              /* device name pointer */
-       int speed,              /* serial port speed (code) */
-       int lflags              /* line discipline flags */
+       char    *dev,           /* device name pointer */
+       u_int   speed,          /* serial port speed (code) */
+       u_int   lflags          /* line discipline flags */
        )
 {
-       int fd, i;
-       int flags;
-       TTY ttyb, *ttyp;
-#ifdef TIOCMGET
-       u_long ltemp;
-#endif /* TIOCMGET */
-       int omode;
+       int     fd;
+       int     omode;
 
        /*
         * Open serial port and set default options
         */
-       flags = lflags;
-
        omode = O_RDWR;
 #ifdef O_NONBLOCK
        omode |= O_NONBLOCK;
@@ -742,32 +762,54 @@ refclock_open(
 #endif
 
        fd = open(dev, omode, 0777);
-
        if (fd < 0) {
-               msyslog(LOG_ERR, "refclock_open: %s: %m", dev);
+               msyslog(LOG_ERR, "refclock_open %s: %m", dev);
                return (0);
        }
+       if (!refclock_setup(fd, speed, lflags)) {
+               close(fd);
+               return (0);
+       }
+       if (!refclock_ioctl(fd, lflags)) {
+               close(fd);
+               return (0);
+       }
+       return (fd);
+}
+
+/*
+ * refclock_setup - initialize terminal interface structure
+ */
+int
+refclock_setup(
+       int     fd,             /* file descriptor */
+       u_int   speed,          /* serial port speed (code) */
+       u_int   lflags          /* line discipline flags */
+       )
+{
+       int     i;
+       TTY     ttyb, *ttyp;
 #ifdef PPS
        fdpps = fd;             /* ppsclock legacy */
 #endif /* PPS */
 
        /*
-        * The following sections initialize the serial line port in
-        * canonical (line-oriented) mode and set the specified line
-        * speed, 8 bits and no parity. The modem control, break, erase
-        * and kill functions are normally disabled. There is a
-        * different section for each terminal interface, as selected at
-        * compile time.
+        * By default, the serial line port is initialized in canonical
+        * (line-oriented) mode at specified line speed, 8 bits and no
+        * parity. LF ends the line and CR is mapped to LF. The break,
+        * erase and kill functions are disabled. There is a different
+        * section for each terminal interface, as selected at compile
+        * time. The flag bits can be used to set raw mode and echo.
         */
        ttyp = &ttyb;
-
 #ifdef HAVE_TERMIOS
+
        /*
         * POSIX serial line parameters (termios interface)
         */
        if (tcgetattr(fd, ttyp) < 0) {
                msyslog(LOG_ERR,
-                       "refclock_open: fd %d tcgetattr: %m", fd);
+                       "refclock_setup fd %d tcgetattr: %m", fd);
                return (0);
        }
 
@@ -775,51 +817,50 @@ refclock_open(
         * Set canonical mode and local connection; set specified speed,
         * 8 bits and no parity; map CR to NL; ignore break.
         */
-       ttyp->c_iflag = IGNBRK | IGNPAR | ICRNL;
-       ttyp->c_oflag = 0;
-       ttyp->c_cflag = CS8 | CLOCAL | CREAD;
-       (void)cfsetispeed(&ttyb, (u_int)speed);
-       (void)cfsetospeed(&ttyb, (u_int)speed);
-       ttyp->c_lflag = ICANON;
-       for (i = 0; i < NCCS; ++i)
-       {
-               ttyp->c_cc[i] = '\0';
+       if (speed) {
+               u_int   ltemp = 0;
+
+               ttyp->c_iflag = IGNBRK | IGNPAR | ICRNL;
+               ttyp->c_oflag = 0;
+               ttyp->c_cflag = CS8 | CLOCAL | CREAD;
+               cfsetispeed(&ttyb, speed);
+               cfsetospeed(&ttyb, speed);
+               for (i = 0; i < NCCS; ++i)
+                       ttyp->c_cc[i] = '\0';
+
+#if defined(TIOCMGET) && !defined(SCO5_CLOCK)
+
+               /*
+                * If we have modem control, check to see if modem leads
+                * are active; if so, set remote connection. This is
+                * necessary for the kernel pps mods to work.
+                */
+               if (ioctl(fd, TIOCMGET, (char *)&ltemp) < 0)
+                       msyslog(LOG_ERR,
+                           "refclock_setup fd %d TIOCMGET: %m", fd);
+#ifdef DEBUG
+               if (debug)
+                       printf("refclock_setup fd %d modem status: 0x%x\n",
+                           fd, ltemp);
+#endif
+               if (ltemp & TIOCM_DSR)
+                       ttyp->c_cflag &= ~CLOCAL;
+#endif /* TIOCMGET */
        }
 
        /*
-        * Some special cases
+        * Set raw and echo modes. These can be changed on-fly.
         */
-       if (flags & LDISC_RAW) {
-               ttyp->c_iflag = 0;
+       ttyp->c_lflag = ICANON;
+       if (lflags & LDISC_RAW) {
                ttyp->c_lflag = 0;
                ttyp->c_cc[VMIN] = 1;
        }
-#if defined(TIOCMGET) && !defined(SCO5_CLOCK)
-       /*
-        * If we have modem control, check to see if modem leads are
-        * active; if so, set remote connection. This is necessary for
-        * the kernel pps mods to work.
-        */
-       ltemp = 0;
-       if (ioctl(fd, TIOCMGET, (char *)&ltemp) < 0)
-               msyslog(LOG_ERR,
-                       "refclock_open: fd %d TIOCMGET failed: %m", fd);
-#ifdef DEBUG
-       if (debug)
-               printf("refclock_open: fd %d modem status 0x%lx\n",
-                   fd, ltemp);
-#endif
-       if (ltemp & TIOCM_DSR)
-               ttyp->c_cflag &= ~CLOCAL;
-#endif /* TIOCMGET */
+       if (lflags & LDISC_ECHO)
+               ttyp->c_lflag |= ECHO;
        if (tcsetattr(fd, TCSANOW, ttyp) < 0) {
                msyslog(LOG_ERR,
-                   "refclock_open: fd %d TCSANOW failed: %m", fd);
-               return (0);
-       }
-       if (tcflush(fd, TCIOFLUSH) < 0) {
-               msyslog(LOG_ERR,
-                   "refclock_open: fd %d TCIOFLUSH failed: %m", fd);
+                   "refclock_setup fd %d TCSANOW: %m", fd);
                return (0);
        }
 #endif /* HAVE_TERMIOS */
@@ -832,7 +873,7 @@ refclock_open(
         */
        if (ioctl(fd, TCGETA, ttyp) < 0) {
                msyslog(LOG_ERR,
-                   "refclock_open: fd %d TCGETA failed: %m", fd);
+                   "refclock_setup fd %d TCGETA: %m", fd);
                return (0);
        }
 
@@ -840,40 +881,46 @@ refclock_open(
         * Set canonical mode and local connection; set specified speed,
         * 8 bits and no parity; map CR to NL; ignore break.
         */
-       ttyp->c_iflag = IGNBRK | IGNPAR | ICRNL;
-       ttyp->c_oflag = 0;
-       ttyp->c_cflag = speed | CS8 | CLOCAL | CREAD;
-       ttyp->c_lflag = ICANON;
-       ttyp->c_cc[VERASE] = ttyp->c_cc[VKILL] = '\0';
+       if (speed) {
+               u_int   ltemp = 0;
+
+               ttyp->c_iflag = IGNBRK | IGNPAR | ICRNL;
+               ttyp->c_oflag = 0;
+               ttyp->c_cflag = speed | CS8 | CLOCAL | CREAD;
+               for (i = 0; i < NCCS; ++i)
+                       ttyp->c_cc[i] = '\0';
+
+#if defined(TIOCMGET) && !defined(SCO5_CLOCK)
+
+               /*
+                * If we have modem control, check to see if modem leads
+                * are active; if so, set remote connection. This is
+                * necessary for the kernel pps mods to work.
+                */
+               if (ioctl(fd, TIOCMGET, (char *)&ltemp) < 0)
+                       msyslog(LOG_ERR,
+                           "refclock_setup fd %d TIOCMGET: %m", fd);
+#ifdef DEBUG
+               if (debug)
+                       printf("refclock_setup fd %d modem status: %x\n",
+                           fd, ltemp);
+#endif
+               if (ltemp & TIOCM_DSR)
+                       ttyp->c_cflag &= ~CLOCAL;
+#endif /* TIOCMGET */
+       }
 
        /*
-        * Some special cases
+        * Set raw and echo modes. These can be changed on-fly.
         */
-       if (flags & LDISC_RAW) {
-               ttyp->c_iflag = 0;
+       ttyp->c_lflag = ICANON;
+       if (lflags & LDISC_RAW) {
                ttyp->c_lflag = 0;
+               ttyp->c_cc[VMIN] = 1;
        }
-#ifdef TIOCMGET
-       /*
-        * If we have modem control, check to see if modem leads are
-        * active; if so, set remote connection. This is necessary for
-        * the kernel pps mods to work.
-        */
-       ltemp = 0;
-       if (ioctl(fd, TIOCMGET, (char *)&ltemp) < 0)
-               msyslog(LOG_ERR,
-                   "refclock_open: fd %d TIOCMGET failed: %m", fd);
-#ifdef DEBUG
-       if (debug)
-               printf("refclock_open: fd %d modem status %lx\n",
-                   fd, ltemp);
-#endif
-       if (ltemp & TIOCM_DSR)
-               ttyp->c_cflag &= ~CLOCAL;
-#endif /* TIOCMGET */
        if (ioctl(fd, TCSETA, ttyp) < 0) {
                msyslog(LOG_ERR,
-                   "refclock_open: fd %d TCSETA failed: %m", fd);
+                   "refclock_setup fd %d TCSETA: %m", fd);
                return (0);
        }
 #endif /* HAVE_SYSV_TTYS */
@@ -885,24 +932,19 @@ refclock_open(
         */
        if (ioctl(fd, TIOCGETP, (char *)ttyp) < 0) {
                msyslog(LOG_ERR,
-                   "refclock_open: fd %d TIOCGETP %m", fd);
+                   "refclock_setup fd %d TIOCGETP: %m", fd);
                return (0);
        }
-       ttyp->sg_ispeed = ttyp->sg_ospeed = speed;
+       if (speed)
+               ttyp->sg_ispeed = ttyp->sg_ospeed = speed;
        ttyp->sg_flags = EVENP | ODDP | CRMOD;
        if (ioctl(fd, TIOCSETP, (char *)ttyp) < 0) {
                msyslog(LOG_ERR,
-                   "refclock_open: TIOCSETP failed: %m");
+                   "refclock_setup TIOCSETP: %m");
                return (0);
        }
 #endif /* HAVE_BSD_TTYS */
-       if (!refclock_ioctl(fd, flags)) {
-               (void)close(fd);
-               msyslog(LOG_ERR,
-                   "refclock_open: fd %d ioctl failed: %m", fd);
-               return (0);
-       }
-       return (fd);
+       return(1);
 }
 #endif /* HAVE_TERMIOS || HAVE_SYSV_TTYS || HAVE_BSD_TTYS */
 #endif /* SYS_VXWORKS SYS_WINNT */
@@ -919,68 +961,51 @@ refclock_open(
  */
 int
 refclock_ioctl(
-       int fd,                 /* file descriptor */
-       int flags               /* line discipline flags */
+       int     fd,             /* file descriptor */
+       u_int   lflags          /* line discipline flags */
        )
 {
-       /* simply return 1 if no UNIX line discipline is supported */
+       /*
+        * simply return 1 if no UNIX line discipline is supported
+        */
 #if !defined SYS_VXWORKS && !defined SYS_WINNT
 #if defined(HAVE_TERMIOS) || defined(HAVE_SYSV_TTYS) || defined(HAVE_BSD_TTYS)
 
-#ifdef TTYCLK
-       TTY ttyb, *ttyp;
-#endif /* TTYCLK */
-
 #ifdef DEBUG
        if (debug)
-               printf("refclock_ioctl: fd %d flags 0x%x\n", fd, flags);
+               printf("refclock_ioctl: fd %d flags 0x%x\n", fd,
+                   lflags);
 #endif
-       if (flags == 0)
-               return (1);
-#if !(defined(HAVE_TERMIOS) || defined(HAVE_BSD_TTYS))
-       if (flags & (LDISC_CLK | LDISC_PPS | LDISC_ACTS)) {
-               msyslog(LOG_ERR,
-                       "refclock_ioctl: unsupported terminal interface");
-               return (0);
-       }
-#endif /* HAVE_TERMIOS HAVE_BSD_TTYS */
 #ifdef TTYCLK
-       ttyp = &ttyb;
-#endif /* TTYCLK */
 
-       /*
-        * The following features may or may not require System V
-        * STREAMS support, depending on the particular implementation.
-        */
-#if defined(TTYCLK)
        /*
         * The TTYCLK option provides timestamping at the driver level.
         * It requires the tty_clk streams module and System V STREAMS
         * support. If not available, don't complain.
         */
-       if (flags & (LDISC_CLK | LDISC_CLKPPS | LDISC_ACTS)) {
+       if (lflags & (LDISC_CLK | LDISC_CLKPPS | LDISC_ACTS)) {
                int rval = 0;
 
                if (ioctl(fd, I_PUSH, "clk") < 0) {
                        msyslog(LOG_NOTICE,
-                           "refclock_ioctl: I_PUSH clk failed: %m");
+                           "refclock_ioctl fd %d I_PUSH: %m", fd);
+                       return (0);
+#ifdef CLK_SETSTR
                } else {
                        char *str;
 
-                       if (flags & LDISC_CLKPPS)
+                       if (lflags & LDISC_CLKPPS)
                                str = "\377";
-                       else if (flags & LDISC_ACTS)
+                       else if (lflags & LDISC_ACTS)
                                str = "*";
                        else
                                str = "\n";
-#ifdef CLK_SETSTR
-                       if ((rval = ioctl(fd, CLK_SETSTR, str)) < 0)
+                       if (ioctl(fd, CLK_SETSTR, str) < 0) {
                                msyslog(LOG_ERR,
-                                   "refclock_ioctl: CLK_SETSTR failed: %m");
-                       if (debug)
-                               printf("refclock_ioctl: fd %d CLK_SETSTR %d str %s\n",
-                                   fd, rval, str);
-#endif
+                                   "refclock_ioctl fd %d CLK_SETSTR: %m", fd);
+                               return (0);
+                       }
+#endif /*CLK_SETSTR */
                }
        }
 #endif /* TTYCLK */
index b8b40506deff215b319703953ba7b0a83f783ee7..2ca67fd5d336a3915044b0c6cdc115fe2d95cb25 100644 (file)
@@ -1248,7 +1248,7 @@ loop_info(
        extern double last_offset;
        extern double drift_comp;
        extern int tc_counter;
-       extern u_long last_time;
+       extern u_long sys_clocktime;
 
        li = (struct info_loop *)prepare_pkt(srcadr, inter, inpkt,
            sizeof(struct info_loop));
@@ -1258,7 +1258,7 @@ loop_info(
        DTOLFP(drift_comp * 1e6, &ltmp);
        HTONL_FP(&ltmp, &li->drift_comp);
        li->compliance = htonl((u_int32)(tc_counter));
-       li->watchdog_timer = htonl((u_int32)(current_time - last_time));
+       li->watchdog_timer = htonl((u_int32)(current_time - sys_clocktime));
 
        (void) more_pkt();
        flush_pkt();
index 95994eb2e30e03c5a683689ca242ecbbbae45bb0..96446b9dd05cf9f6976b62e55a950d46ddbdf88a 100644 (file)
  * use as backup when neither a radio clock nor connectivity to Internet
  * time servers is available.
  *
- * For best results the propagation delay due to the individual modem
- * and telephone circuit must be known. The ACTS echo-delay measurement
- * scheme no longer works, so corrections due to propagation delay must
- * be determined by other means. Systematic corrections range from 200
- * to 400 milliseconds, depending on the particular service and call
- * routing. Variations from call to call can reach 100 miliseconds and
- * between messages during a call from a few milliseconds to 50
- * milliseconds or more.
- *
- * This driver requires a 1200-bps modem with a Hayes-compatible command
+ * This driver requires a 9600-bps modem with a Hayes-compatible command
  * set and control over the modem data terminal ready (DTR) control
  * line. The modem setup string is hard-coded in the driver and may
- * require changes for nonstandard modems or special circumstances. The
- * calling program is initiated by setting fudge flag1. This can be done
- * using ntpdc, either manually or via a cron job. In auto mode, flag1
- * is set at each poll event. In backup mode, flag1 is set at each poll
- * event, but only if the prefer peer is unreachable.
+ * require changes for nonstandard modems or special circumstances.
  *
- * When flag1 is set, the calling program dials each number listed in
- * the phones command of the configuration file in turn. The number is
- * specified by the Hayes ATDT prefix followed by the number itself,
- * including the prefix and long-distance digits and delay code, if
- * necessary. The flag1 is reset and the calling program terminated if
- * (a) a valid clock update has been determined, (b) no more numbers
- * remain in the list, (c) a device fault or timeout occurs or (d) fudge
- * flag1 is reset manually using ntpdc.
+ * The calling program is initiated by setting fudge flag1, either
+ * manually or automatically. When flag1 is set, the calling program
+ * dials each number listed in the phones command of the configuration
+ * file in turn. The number is specified by the Hayes ATDT prefix
+ * followed by the number itself, including the prefix and long-distance
+ * digits and delay code, if necessary. The flag1 is reset and the
+ * calling program terminated if (a) a valid clock update has been
+ * determined, (b) no more numbers remain in the list, (c) a device
+ * fault or timeout occurs or (d) fudge flag1 is reset manually.
  *
  * The driver is transparent to each of the modem time services and
  * Spectracom radios. It selects the parsing algorithm depending on the
@@ -97,8 +85,9 @@
  * 47999 90-04-18 21:39:16 50 0 +.1 045.0 UTC(NIST) *
  * ...
  *
- * MJD, DST, DUT1, msADV and UTC are not used by this driver. The "*" is
- * the on-time marker.
+ * MJD, DST, DUT1 and UTC are not used by this driver. The "*" or "#" is
+ * the on-time markers echoed by the driver and used by NIST to measure
+ * and correct for the propagation delay.
  *
  * US Naval Observatory (USNO)
  *
  * PTB: +49 531 512038 (Germany)
  * NPL: 0906 851 6333 (UK only)
  *
- * Data format
+ * Data format (see the documentation for phone numbers and formats.)
  *
  * 1995-01-23 20:58:51 MEZ  10402303260219950123195849740+40000500
  *
  * Interface definitions
  */
 #define        DEVICE          "/dev/acts%d" /* device name and unit */
+#define        SPEED232        B9600   /* uart speed (9600 baud) */
 #define        PRECISION       (-10)   /* precision assumed (about 1 ms) */
 #define LOCKFILE       "/var/spool/locks/LCK..cua%d"
 #define DESCRIPTION    "Automated Computer Time Service" /* WRU */
 #define REFID          "NONE"  /* default reference ID */
-#define MSGCNT         10      /* we need this many messages */
-#define SMAX           80      /* max string length */
+#define MSGCNT         20      /* max message count */
+#define SMAX           80      /* max clockstats line length */
 
 /*
  * Calling program modes
 #define REFWWVB                "WWVB"  /* WWVB reference ID */
 #define        LENWWVB0        22      /* WWVB format 0 */
 #define        LENWWVB2        24      /* WWVB format 2 */
+#define LF             0x0a    /* ASCII LF */
 
 /*
  * Modem setup strings. These may have to be changed for some modems.
  *
  * AT  command prefix
- * B1  initiate call negotiation using Bell 212A
+ * B1  US answer tone
  * &C1 enable carrier detect
  * &D2 hang up and return to command mode on DTR transition
  * E0  modem command echo disabled
 #define WAIT           2       /* DTR timeout */
 #define MODEM          3       /* modem timeout */
 #define ANSWER         60      /* answer timeout */
-#define CONNECT                10      /* first message timeout */
-#define TIMECODE       20      /* all messages timeout */
+#define CONNECT                10      /* first valid message timeout */
+#define TIMECODE       30      /* all valid messages timeout */
 
 /*
  * State machine codes
@@ -207,6 +198,7 @@ struct actsunit {
        int     retry;          /* retry index */
        int     msgcnt;         /* count of messages received */
        l_fp    tstamp;         /* on-time timestamp */
+       char    *bufptr;        /* buffer pointer */
 };
 
 /*
@@ -215,6 +207,7 @@ struct actsunit {
 static int     acts_start      P((int, struct peer *));
 static void    acts_shutdown   P((int, struct peer *));
 static void    acts_receive    P((struct recvbuf *));
+static void    acts_message    P((struct peer *));
 static void    acts_poll       P((int, struct peer *));
 static void    acts_timeout    P((struct peer *));
 static void    acts_disc       P((struct peer *));
@@ -269,6 +262,7 @@ acts_start (
        pp->clockdesc = DESCRIPTION;
        memcpy((char *)&pp->refid, REFID, 4);
        peer->sstclktype = CTL_SST_TS_TELEPHONE;
+       up->bufptr = pp->a_lastcode;
        return (1);
 }
 
@@ -304,9 +298,57 @@ acts_receive (
        struct actsunit *up;
        struct refclockproc *pp;
        struct peer *peer;
+       char    tbuf[BMAX];
+       char    *tptr;
+
+       /*
+        * Initialize pointers and read the timecode and timestamp. Note
+        * we are in raw mode and victim of whatever the terminal
+        * interfact kicks up; so, we have to reassemble messages from
+        * arbitrary fragments. Capture the timecode at the beginning of
+        * the message and at the '*' on-time character.
+        */
+       peer = (struct peer *)rbufp->recv_srcclock;
+       pp = peer->procptr;
+       up = (struct actsunit *)pp->unitptr;
+       pp->lencode = refclock_gtraw(rbufp, tbuf, BMAX - (up->bufptr -
+           pp->a_lastcode), &pp->lastrec);
+       for (tptr = tbuf; *tptr != '\0'; tptr++) {
+               if (*tptr == LF) {
+                       if (up->bufptr == pp->a_lastcode) {
+                               up->tstamp = pp->lastrec;
+                               continue;
+
+                       } else {
+                               *up->bufptr = '\0';
+                               acts_message(peer);
+                               up->bufptr = pp->a_lastcode;
+                       }
+               } else {
+                       *up->bufptr++ = *tptr;
+                       if (*tptr == '*' || *tptr == '#') {
+                               up->tstamp = pp->lastrec;
+                               write(pp->io.fd, tptr, 1);
+                       }
+               }
+       }
+}
+
+
+/*
+ * acts_message - process message
+ */
+void
+acts_message(
+       struct peer *peer
+       )
+{
+       struct actsunit *up;
+       struct refclockproc *pp;
+       char    tbuf[SMAX];
+       u_int   len;
        int     day;            /* day of the month */
        int     month;          /* month of the year */
-
        u_long  mjd;            /* Modified Julian Day */
        double  dut1;           /* DUT adjustment */
        double  msADV;          /* ACTS transmit advance (ms) */
@@ -322,24 +364,11 @@ acts_receive (
        char    dstchar;        /* WWVB daylight/savings indicator */
        u_int   dst;            /* ACTS daylight/standard time */
 
-       int     len;
-       char    tbuf[SMAX];     /* monitor buffer */
-
-       /*
-        * Initialize pointers and read the timecode and timestamp.
-        */
-       peer = (struct peer *)rbufp->recv_srcclock;
        pp = peer->procptr;
        up = (struct actsunit *)pp->unitptr;
-       pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode, BMAX,
-               &pp->lastrec);
-       if (pp->lencode == 0) {
-               up->tstamp = pp->lastrec;
-               return;
-       }
-       pp->a_lastcode[pp->lencode] = '\0';
-       sprintf(tbuf, "acts: (%d %d) %d %s", up->state, up->timer,
-           pp->lencode, pp->a_lastcode);
+       len = strlen(pp->a_lastcode);
+       sprintf(tbuf, "acts: (%d %d) %d %s", up->state, up->timer, len,
+           pp->a_lastcode);
 #ifdef DEBUG
        if (debug)
                printf("%s\n", tbuf);
@@ -403,13 +432,14 @@ acts_receive (
         * occasional errors due noise are forgivable.
         */
        pp->nsec = 0;
-       switch(pp->lencode) {
+       switch(len) {
 
        /*
-        * USNO on-time '*' on a line by itself.
+        * For USNO format on-time character '*', which is on a line by
+        * itself. By sure a timecode has been received.
         */
        case 1:
-               if (*pp->a_lastcode == '*' && up->msgcnt > 0)
+               if (*pp->a_lastcode == '*' && up->state == S_MSG) 
                        break;
 
                return;
@@ -427,6 +457,19 @@ acts_receive (
                        refclock_report(peer, CEVNT_BADREPLY);
                        return;
                }
+
+               /*
+                * Reset the timer and wait until NIST has calculated
+                * roundtrip delay.
+                */
+               if (up->state != S_MSG) {
+                       up->state = S_MSG;
+                       up->timer = TIMECODE;
+               }
+               if (flag != '#')
+                       return;
+
+               pp->lastrec = up->tstamp;
                pp->day = ymd2yd(pp->year, month, day);
                if (leap == 1)
                        pp->leap = LEAP_ADDSECOND;
@@ -448,6 +491,14 @@ acts_receive (
                        refclock_report(peer, CEVNT_BADREPLY);
                        return;
                }
+
+               /*
+                * Reset the timer and wait for the on-time character.
+                */
+               if (up->state != S_MSG) {
+                       up->state = S_MSG;
+                       up->timer = TIMECODE;
+               }
                pp->lastrec = up->tstamp;
                memcpy(&pp->refid, REFUSNO, 4);
                if (up->msgcnt == 0)
@@ -467,6 +518,14 @@ acts_receive (
                        refclock_report(peer, CEVNT_BADREPLY);
                        return;
                }
+
+               /*
+                * Reset the timer and wait for the on-time character.
+                */
+               if (up->state != S_MSG) {
+                       up->state = S_MSG;
+                       up->timer = TIMECODE;
+               }
                pp->lastrec = up->tstamp;
                if (leapmonth == month) {
                        if (leapdir == '+')
@@ -507,10 +566,10 @@ acts_receive (
         */
        case LENWWVB2:
                if (sscanf(pp->a_lastcode,
-                   "%c%c%2d %3d %2d:%2d:%2d.%3ld %c%c",
+                   "%c%c%2d %3d %2d:%2d:%2d.%3ld%c%c%c",
                    &synchar, &qualchar, &pp->year, &pp->day,
                    &pp->hour, &pp->minute, &pp->second, &pp->nsec,
-                   &leapchar, &dstchar) != 9) {
+                   &dstchar, &leapchar, &dstchar) != 11) {
                        refclock_report(peer, CEVNT_BADREPLY);
                        return;
                }
@@ -539,14 +598,17 @@ acts_receive (
 
        /*
         * The fudge time1 value is added to each sample by the main
-        * line routines. We collect a maximum of MSGCNT samples or
-        * until timeout.
+        * line routines. Note that we use the median filter only when
+        * the dispersion has receeded below the threshold.
         */
        if (refclock_process(pp)) {
                pp->lastref = pp->lastrec;
-               refclock_receive(peer);
-               up->state = S_MSG;
-               up->timer = TIMECODE;
+               if (peer->disp > MAXDISTANCE)
+                       refclock_receive(peer);
+               if (up->state != S_MSG) {
+                       up->state = S_MSG;
+                       up->timer = TIMECODE;
+               }
        } else {
                refclock_report(peer, CEVNT_BADTIME);
        }
@@ -689,18 +751,12 @@ acts_timeout(
                }
 
                /*
-                * Open device and light up a discipline if present. We
-                * use 1200 baud for modem, 9600 baud for direct
-                * connect.
+                * Open device and light up a discipline if present.
                 */
                if (!pp->io.fd) {
                        sprintf(device, DEVICE, up->unit);
-                       if (pp->sloppyclockflag & CLK_FLAG3)
-                               fd = refclock_open(device, B9600,
-                                   LDISC_ACTS);
-                       else
-                               fd = refclock_open(device, B1200,
-                                   LDISC_ACTS);
+                       fd = refclock_open(device, SPEED232,
+                           LDISC_ACTS | LDISC_RAW);
                        if (fd < 0) {
                                msyslog(LOG_ERR,
                                    "acts: device open fails");
@@ -808,6 +864,7 @@ acts_disc (
         * number, fold the tent and go home.
         */
        if (up->msgcnt > 0) {
+               refclock_receive(peer);
                up->retry = 0;
        } else {
                up->retry++;
@@ -846,12 +903,17 @@ acts_disc (
                }
 
        }
+
+       /*
+        * If there are more numbers to dial or the modem is not in
+        * command mode, retry after a short wait.
+        */
        up->msgcnt = 0;
-       up->state = S_IDLE;
-       if (up->retry > 0)
+       up->timer = 0;
+       up->bufptr = pp->a_lastcode;
+       if (up->retry > 0 || up->state == S_OK)
                up->timer = MODEM;
-       else
-               up->timer = 0;
+       up->state = S_IDLE;
 }
 
 #else
index 96aba2d58aecba6b5ef0f6a836e01e35267e3078..51f64ccacb75253cf811d6c881a37a14e0376649 100644 (file)
  * WWVB unit control structure
  */
 struct wwvbunit {
-       u_char  tcswitch;       /* timecode switch */
        l_fp    laststamp;      /* last receive timestamp */
        u_char  lasthour;       /* last hour (for monitor) */
        u_char  linect;         /* count ignored lines (for monitor */
@@ -157,7 +156,7 @@ wwvb_start(
        /*
         * Open serial port. Use CLK line discipline, if available.
         */
-       (void)sprintf(device, DEVICE, unit);
+       sprintf(device, DEVICE, unit);
        if (!(fd = refclock_open(device, SPEED232, LDISC_CLK)))
                return (0);
 
@@ -166,7 +165,7 @@ wwvb_start(
         */
        if (!(up = (struct wwvbunit *)
              emalloc(sizeof(struct wwvbunit)))) {
-               (void) close(fd);
+               close(fd);
                return (0);
        }
        memset((char *)up, 0, sizeof(struct wwvbunit));
@@ -177,7 +176,7 @@ wwvb_start(
        pp->io.datalen = 0;
        pp->io.fd = fd;
        if (!io_addclock(&pp->io)) {
-               (void) close(fd);
+               close(fd);
                free(up);
                return (0);
        }
@@ -253,17 +252,11 @@ wwvb_receive(
         * 0 provides the lowest jitter.
         */
        if (temp == 0) {
-               if (up->tcswitch == 0) {
-                       up->tcswitch = 1;
-                       up->laststamp = trtmp;
-               } else
-                   up->tcswitch = 0;
+               up->laststamp = trtmp;
                return;
        }
        pp->lencode = temp;
        pp->lastrec = up->laststamp;
-       up->laststamp = trtmp;
-       up->tcswitch = 1;
 
        /*
         * We get down to business, check the timecode format and decode