diff options
author | roberto <roberto@FreeBSD.org> | 2001-08-29 14:35:15 +0000 |
---|---|---|
committer | roberto <roberto@FreeBSD.org> | 2001-08-29 14:35:15 +0000 |
commit | 40b8e415eb0f835a9dd7a473ddf134ec67877fd7 (patch) | |
tree | 3cfb63f1a112ee17469b17fc1593a88d004ddda6 /contrib/ntp/ntpd/refclock_atom.c | |
parent | a5a8dc6136fcee95f261a31609a25669038c3861 (diff) | |
download | FreeBSD-src-40b8e415eb0f835a9dd7a473ddf134ec67877fd7.zip FreeBSD-src-40b8e415eb0f835a9dd7a473ddf134ec67877fd7.tar.gz |
Virgin import of ntpd 4.1.0
Diffstat (limited to 'contrib/ntp/ntpd/refclock_atom.c')
-rw-r--r-- | contrib/ntp/ntpd/refclock_atom.c | 608 |
1 files changed, 307 insertions, 301 deletions
diff --git a/contrib/ntp/ntpd/refclock_atom.c b/contrib/ntp/ntpd/refclock_atom.c index 764f6e0..56f86b3 100644 --- a/contrib/ntp/ntpd/refclock_atom.c +++ b/contrib/ntp/ntpd/refclock_atom.c @@ -5,8 +5,6 @@ #include <config.h> #endif -#if defined(REFCLOCK) && defined(CLOCK_ATOM) - #include <stdio.h> #include <ctype.h> @@ -16,15 +14,8 @@ #include "ntp_refclock.h" #include "ntp_stdlib.h" -#ifdef HAVE_SYS_TIME_H -# include <sys/time.h> -#endif -#ifdef HAVE_SYS_TERMIOS_H -# include <sys/termios.h> -#endif -#ifdef HAVE_SYS_PPSCLOCK_H -# include <sys/ppsclock.h> -#endif +#if defined(REFCLOCK) && defined(CLOCK_ATOM) + #ifdef HAVE_PPSAPI # ifdef HAVE_TIMEPPS_H # include <timepps.h> @@ -37,120 +28,109 @@ /* * This driver furnishes an interface for pulse-per-second (PPS) signals - * produced by a cesium clock, timing receiver or related equipment. It + * produced by a cesium clock, timing receiver or related equipment. It * can be used to remove accumulated jitter and retime a secondary * server when synchronized to a primary server over a congested, wide- * area network and before redistributing the time to local clients. * - * In order for this driver to work, the local clock must be set to + * Before this driver becomes active, the local clock must be set to * within +-500 ms by another means, such as a radio clock or NTP - * itself. The 1-pps signal is connected via a serial port and gadget - * box consisting of a one-shot flopflop and RS232 level converter. - * Conntection is either via the carrier detect (DCD) lead or via the - * receive data (RD) lead. The incidental jitter using the DCD lead is - * essentially the interrupt latency. The incidental jitter using the RD - * lead has an additional component due to the line sampling clock. When - * operated at 38.4 kbps, this arrangement has a worst-case jitter less - * than 26 us. + * itself. There are two ways to connect the PPS signal, normally at TTL + * levels, to the computer. One is to shift to EIA levels and connect to + * pin 8 (DCD) of a serial port. This requires a level converter and + * may require a one-shot flipflop to lengthen the pulse. The other is + * to connect the PPS signal directly to pin 10 (ACK) of a PC paralell + * port. These methods are architecture dependent. * - * There are four ways in which this driver can be used. They are - * described in decreasing order of merit below. The first way uses the - * ppsapi STREAMS module and the LDISC_PPS line discipline, while the - * second way uses the ppsclock STREAMS module and the LDISC_PPS line - * discipline. Either of these works only for the baseboard serial ports - * of the Sun SPARC IPC and clones. However, the ppsapi uses the - * proposed IETF interface expected to become standard for PPS signals. - * The serial port to be used is specified by the pps command in the - * configuration file. This driver reads the timestamp directly by a - * designated ioctl() system call. + * Both methods require a modified device driver and kernel interface + * compatible with the Pulse-per-Second API for Unix-like Operating + * Systems, Version 1.0, RFC-2783 (PPSAPI). Implementations are + * available for FreeBSD, Linux, SunOS, Solaris and Alpha. However, at + * present only the Alpha implementation provides the full generality of + * the API with multiple PPS drivers and multiple handles per driver. * - * The third way uses the LDISC_CLKPPS line discipline and works for - * any architecture supporting a serial port. If after a few seconds - * this driver finds no ppsclock module configured, it attempts to open - * a serial port device /dev/pps%d, where %d is the unit number, and - * assign the LDISC_CLKPPS line discipline to it. If the line discipline - * fails, no harm is done except the accuracy is reduced somewhat. The - * pulse generator in the gadget box is adjusted to produce a start bit - * of length 26 usec at 38400 bps. Used with the LDISC_CLKPPS line - * discipline, this produces an ASCII DEL character ('\377') followed by - * a timestamp at each seconds epoch. + * In many configurations a single port is used for the radio timecode + * and PPS signal. In order to provide for this configuration and others + * involving dedicated multiple serial/parallel ports, the driver first + * attempts to open the device /dev/pps%d, where %d is the unit number. + * If this fails, the driver attempts to open the device specified by + * the pps configuration command. If a port is to be shared, the pps + * command must be placed before the radio device(s) and the radio + * device(s) must be placed before the PPS driver(s) in the + * configuration file. * - * The fourth way involves an auxiliary radio clock driver which calls - * the PPS driver with a timestamp captured by that driver. This use is - * documented in the source code for the driver(s) involved. Note that - * some drivers collect the sample information themselves before calling - * pps_sample(), and others call knowing only that they are running - * shortly after an on-time tick and they expect to retrieve the PPS - * offset, fudge their result, and insert it into the timestream. + * This driver normally uses the PLL/FLL clock discipline implemented in + * the ntpd code. If kernel support is available, the kernel PLL/FLL + * clock discipline is used instead. The default configuration is not to + * use the kernel PPS discipline, if present. The kernel PPS discipline + * can be enabled using the pps command. * * Fudge Factors * * There are no special fudge factors other than the generic. The fudge - * time1 parameter can be used to compensate for miscellaneous UART and - * OS delays. Allow about 247 us for uart delays at 38400 bps and about - * 1 ms for STREAMS nonsense with older workstations. Velocities may - * vary with modern workstations. + * time1 parameter can be used to compensate for miscellaneous device + * driver and OS delays. */ /* * Interface definitions */ #ifdef HAVE_PPSAPI -extern int pps_assert; +extern int pps_assert; /* selects rising or falling edge */ +extern int pps_hardpps; /* enables the kernel PPS interface */ +#define DEVICE "/dev/pps%d" /* device name and unit */ #endif /* HAVE_PPSAPI */ -#ifdef TTYCLK -#define DEVICE "/dev/pps%d" /* device name and unit */ -#ifdef B38400 -#define SPEED232 B38400 /* uart speed (38400 baud) */ -#else -#define SPEED232 EXTB /* as above */ -#endif -#endif /* TTYCLK */ #define PRECISION (-20) /* precision assumed (about 1 us) */ #define REFID "PPS\0" /* reference ID */ #define DESCRIPTION "PPS Clock Discipline" /* WRU */ +#define NANOSECOND 1000000000 /* one second (ns) */ +#define RANGEGATE 500000 /* range gate (ns) */ +#define ASTAGE 8 /* filter stages */ -#define FLAG_TTY 0x01 /* tty_clk heard from */ -#define FLAG_PPS 0x02 /* ppsclock heard from */ -#define FLAG_AUX 0x04 /* auxiliary PPS source */ - -static struct peer *pps_peer; /* atom driver for auxiliary PPS sources */ - -#ifdef TTYCLK -static void atom_receive P((struct recvbuf *)); -#endif /* TTYCLK */ +static struct peer *pps_peer; /* atom driver for PPS sources */ +#ifdef HAVE_PPSAPI /* - * Unit control structure + * PPS unit control structure */ -struct atomunit { -#ifdef HAVE_PPSAPI - pps_info_t pps_info; /* pps_info control */ -#endif /* HAVE_PPSAPI */ -#ifdef PPS - struct ppsclockev ev; /* ppsclock control */ -#endif /* PPS */ - int flags; /* flags that wave */ +struct ppsunit { + struct timespec ts; /* last timestamp */ + int fddev; /* pps device descriptor */ + pps_params_t pps_params; /* pps parameters */ + pps_info_t pps_info; /* last pps data */ + pps_handle_t handle; /* pps handlebars */ }; +#endif /* HAVE_PPSAPI */ /* * Function prototypes */ static int atom_start P((int, struct peer *)); -static void atom_shutdown P((int, struct peer *)); static void atom_poll P((int, struct peer *)); -#if defined(PPS) || defined(HAVE_PPSAPI) +#ifdef HAVE_PPSAPI +static void atom_shutdown P((int, struct peer *)); +static void atom_control P((int, struct refclockstat *, struct + refclockstat *, struct peer *)); static int atom_pps P((struct peer *)); -#endif /* PPS || HAVE_PPSAPI */ +static int atom_ppsapi P((struct peer *, int, int)); +#endif /* HAVE_PPSAPI */ /* * Transfer vector */ struct refclock refclock_atom = { atom_start, /* start up driver */ +#ifdef HAVE_PPSAPI atom_shutdown, /* shut down driver */ +#else + noentry, /* shut down driver */ +#endif /* HAVE_PPSAPI */ atom_poll, /* transmit poll message */ - noentry, /* not used (old atom_control) */ +#ifdef HAVE_PPSAPI + atom_control, /* fudge control */ +#else + noentry, /* fudge control */ +#endif /* HAVE_PPSAPI */ noentry, /* initialize driver */ noentry, /* not used (old atom_buginfo) */ NOFLAGS /* not used */ @@ -162,74 +142,142 @@ struct refclock refclock_atom = { */ static int atom_start( - int unit, - struct peer *peer + int unit, /* unit number (not used) */ + struct peer *peer /* peer structure pointer */ ) { - register struct atomunit *up; struct refclockproc *pp; - int flags; -#ifdef TTYCLK - int fd = 0; - char device[20]; - int ldisc = LDISC_CLKPPS; -#endif /* TTYCLK */ +#ifdef HAVE_PPSAPI + register struct ppsunit *up; + char device[80]; +#endif /* HAVE_PPSAPI */ + /* + * Allocate and initialize unit structure + */ pps_peer = peer; - flags = 0; + pp = peer->procptr; + peer->precision = PRECISION; + pp->clockdesc = DESCRIPTION; + memcpy((char *)&pp->refid, REFID, 4); + peer->burst = ASTAGE; + peer->stratum = STRATUM_UNSPEC; +#ifdef HAVE_PPSAPI + up = emalloc(sizeof(struct ppsunit)); + memset(up, 0, sizeof(struct ppsunit)); + pp->unitptr = (caddr_t)up; -#ifdef TTYCLK -# if defined(SCO5_CLOCK) - ldisc = LDISC_RAW; /* DCD timestamps without any line discipline */ -# endif /* - * Open serial port. Use LDISC_CLKPPS line discipline only - * if the LDISC_PPS line discipline is not availble, + * Open PPS device. If this fails and some driver has already + * opened the associated radio device, fdpps has the file + * descriptor for it. */ -# if defined(PPS) || defined(HAVE_PPSAPI) - if (fdpps <= 0) -# endif - { - (void)sprintf(device, DEVICE, unit); - if ((fd = refclock_open(device, SPEED232, ldisc)) != 0) - flags |= FLAG_TTY; + sprintf(device, DEVICE, unit); + up->fddev = open(device, O_RDWR, 0777); + if (up->fddev <= 0 && fdpps > 0) { + strcpy(device, pps_device); + up->fddev = fdpps; + } + if (up->fddev <= 0) { + msyslog(LOG_ERR, + "refclock_atom: %s: %m", device); + return (0); } -#endif /* TTYCLK */ /* - * Allocate and initialize unit structure + * Light off the PPSAPI interface. If this PPS device is shared + * with the radio device, take the default options from the pps + * command. This is for legacy purposes. */ - if (!(up = (struct atomunit *)emalloc(sizeof(struct atomunit)))) { -#ifdef TTYCLK - if (flags & FLAG_TTY) - (void) close(fd); -#endif /* TTYCLK */ + if (time_pps_create(up->fddev, &up->handle) < 0) { + msyslog(LOG_ERR, + "refclock_atom: time_pps_create failed: %m"); return (0); } - memset((char *)up, 0, sizeof(struct atomunit)); + return (atom_ppsapi(peer, pps_assert, pps_hardpps)); +#else /* HAVE_PPSAPI */ + return (1); +#endif /* HAVE_PPSAPI */ +} + + +#ifdef HAVE_PPSAPI +/* + * atom_control - fudge control + */ +static void +atom_control( + int unit, /* unit (not used */ + struct refclockstat *in, /* input parameters (not uded) */ + struct refclockstat *out, /* output parameters (not used) */ + struct peer *peer /* peer structure pointer */ + ) +{ + struct refclockproc *pp; + pp = peer->procptr; - pp->unitptr = (caddr_t)up; -#ifdef TTYCLK - if (flags & FLAG_TTY) { - pp->io.clock_recv = atom_receive; - pp->io.srcclock = (caddr_t)peer; - pp->io.datalen = 0; - pp->io.fd = fd; - if (!io_addclock(&pp->io)) { - (void) close(fd); - free(up); + atom_ppsapi(peer, pp->sloppyclockflag & CLK_FLAG2, + pp->sloppyclockflag & CLK_FLAG3); +} + + +/* + * Initialize PPSAPI + */ +int +atom_ppsapi( + struct peer *peer, /* peer structure pointer */ + int enb_clear, /* clear enable */ + int enb_hardpps /* hardpps enable */ + ) +{ + struct refclockproc *pp; + register struct ppsunit *up; + int capability; + + pp = peer->procptr; + up = (struct ppsunit *)pp->unitptr; + if (time_pps_getcap(up->handle, &capability) < 0) { + msyslog(LOG_ERR, + "refclock_atom: time_pps_getcap failed: %m"); + return (0); + } + memset(&up->pps_params, 0, sizeof(pps_params_t)); + if (enb_clear) + up->pps_params.mode = capability & PPS_CAPTURECLEAR; + else + up->pps_params.mode = capability & PPS_CAPTUREASSERT; + if (!up->pps_params.mode) { + msyslog(LOG_ERR, + "refclock_atom: invalid capture edge %d", + pps_assert); + return (0); + } + up->pps_params.mode |= PPS_TSFMT_TSPEC; + if (time_pps_setparams(up->handle, &up->pps_params) < 0) { + msyslog(LOG_ERR, + "refclock_atom: time_pps_setparams failed: %m"); + return (0); + } + if (enb_hardpps) { + if (time_pps_kcbind(up->handle, PPS_KC_HARDPPS, + up->pps_params.mode & ~PPS_TSFMT_TSPEC, + PPS_TSFMT_TSPEC) < 0) { + msyslog(LOG_ERR, + "refclock_atom: time_pps_kcbind failed: %m"); return (0); } + pps_enable = 1; } -#endif /* TTYCLK */ - - /* - * Initialize miscellaneous variables - */ - peer->precision = PRECISION; - pp->clockdesc = DESCRIPTION; - memcpy((char *)&pp->refid, REFID, 4); - up->flags = flags; +#if DEBUG + if (debug) { + time_pps_getparams(up->handle, &up->pps_params); + printf( + "refclock_ppsapi: fd %d capability 0x%x version %d mode 0x%x kern %d\n", + up->fddev, capability, up->pps_params.api_version, + up->pps_params.mode, enb_hardpps); + } +#endif return (1); } @@ -239,181 +287,122 @@ atom_start( */ static void atom_shutdown( - int unit, - struct peer *peer + int unit, /* unit number (not used) */ + struct peer *peer /* peer structure pointer */ ) { - register struct atomunit *up; struct refclockproc *pp; + register struct ppsunit *up; pp = peer->procptr; - up = (struct atomunit *)pp->unitptr; -#ifdef TTYCLK - if (up->flags & FLAG_TTY) - io_closeclock(&pp->io); -#endif /* TTYCLK */ + up = (struct ppsunit *)pp->unitptr; + if (up->fddev > 0) + close(up->fddev); + if (up->handle != 0) + time_pps_destroy(up->handle); if (pps_peer == peer) pps_peer = 0; free(up); } -#if defined(PPS) || defined(HAVE_PPSAPI) /* - * atom_pps - receive data from the LDISC_PPS discipline + * atom_pps - receive data from the PPSAPI interface + * + * This routine is called once per second when the PPSAPI interface is + * present. It snatches the PPS timestamp from the kernel and saves the + * sign-extended fraction in a circular buffer for processing at the + * next poll event. */ static int atom_pps( - struct peer *peer + struct peer *peer /* peer structure pointer */ ) { - register struct atomunit *up; + register struct ppsunit *up; struct refclockproc *pp; -#ifdef HAVE_PPSAPI - struct timespec timeout; -# ifdef HAVE_TIMESPEC - struct timespec ts; -# else - struct timeval ts; -# endif /* HAVE_TIMESPEC */ -#endif /* HAVE_PPSAPI */ - l_fp lftmp; - double doffset; - int i; -#if !defined(HAVE_PPSAPI) - int request = -# ifdef HAVE_CIOGETEV - CIOGETEV -# endif -# ifdef HAVE_TIOCGPPSEV - TIOCGPPSEV -# endif - ; -#endif /* HAVE_PPSAPI */ + pps_info_t pps_info; + struct timespec timeout, ts; + double dtemp; /* - * This routine is called once per second when the LDISC_PPS - * discipline is present. It snatches the pps timestamp from the - * kernel and saves the sign-extended fraction in a circular - * buffer for processing at the next poll event. - */ - pp = peer->procptr; - up = (struct atomunit *)pp->unitptr; - - /* - * Convert the timeval to l_fp and save for billboards. Sign- - * extend the fraction and stash in the buffer. No harm is done - * if previous data are overwritten. If the discipline comes bum - * or the data grow stale, just forget it. Round the nanoseconds - * to microseconds with great care. + * Convert the timespec nanoseconds field to signed double and + * save in the median filter. for billboards. No harm is done if + * previous data are overwritten. If the discipline comes bum or + * the data grow stale, just forget it. A range gate rejects new + * samples if less than a jiggle time from the next second. */ - if (fdpps <= 0) - return (1); -#ifdef HAVE_PPSAPI + pp = peer->procptr; + up = (struct ppsunit *)pp->unitptr; + if (up->handle == 0) + return (-1); timeout.tv_sec = 0; timeout.tv_nsec = 0; - i = up->pps_info.assert_sequence; - if (time_pps_fetch(fdpps, PPS_TSFMT_TSPEC, &up->pps_info, &timeout) - < 0) - return (2); - if (i == up->pps_info.assert_sequence) - return (3); - if (pps_assert) + memcpy(&pps_info, &up->pps_info, sizeof(pps_info_t)); + if (time_pps_fetch(up->handle, PPS_TSFMT_TSPEC, &up->pps_info, + &timeout) < 0) + return (-1); + if (up->pps_params.mode & PPS_CAPTUREASSERT) { + if (pps_info.assert_sequence == + up->pps_info.assert_sequence) + return (1); ts = up->pps_info.assert_timestamp; - else + } else if (up->pps_params.mode & PPS_CAPTURECLEAR) { + if (pps_info.clear_sequence == + up->pps_info.clear_sequence) + return (1); ts = up->pps_info.clear_timestamp; - pp->lastrec.l_ui = ts.tv_sec + JAN_1970; - ts.tv_nsec = (ts.tv_nsec + 500) / 1000; - if (ts.tv_nsec > 1000000) { - ts.tv_nsec -= 1000000; - ts.tv_sec++; + } else { + return (-1); } - TVUTOTSF(ts.tv_nsec, pp->lastrec.l_uf); -#else - i = up->ev.serial; - if (ioctl(fdpps, request, (caddr_t)&up->ev) < 0) - return (2); - if (i == up->ev.serial) - return (3); - pp->lastrec.l_ui = up->ev.tv.tv_sec + JAN_1970; - TVUTOTSF(up->ev.tv.tv_usec, pp->lastrec.l_uf); -#endif /* HAVE_PPSAPI */ - up->flags |= FLAG_PPS; - L_CLR(&lftmp); - L_ADDF(&lftmp, pp->lastrec.l_f); - LFPTOD(&lftmp, doffset); - SAMPLE(-doffset + pp->fudgetime1); + if (!((ts.tv_sec == up->ts.tv_sec && ts.tv_nsec - + up->ts.tv_nsec > NANOSECOND - RANGEGATE) || + (ts.tv_sec - up->ts.tv_sec == 1 && ts.tv_nsec - + up->ts.tv_nsec < RANGEGATE))) { + up->ts = ts; + return (1); + } + up->ts = ts; + pp->lastrec.l_ui = ts.tv_sec + JAN_1970; + dtemp = ts.tv_nsec * FRAC / 1e9; + if (dtemp >= FRAC) + pp->lastrec.l_ui++; + pp->lastrec.l_uf = (u_int32)dtemp; + if (ts.tv_nsec > NANOSECOND / 2) + ts.tv_nsec -= NANOSECOND; + dtemp = -(double)ts.tv_nsec / NANOSECOND; + SAMPLE(dtemp + pp->fudgetime1); +#ifdef DEBUG + if (debug > 1) + printf("atom_pps %f %f\n", dtemp, pp->fudgetime1); +#endif return (0); } -#endif /* PPS || HAVE_PPSAPI */ - -#ifdef TTYCLK -/* - * atom_receive - receive data from the LDISC_CLK discipline - */ -static void -atom_receive( - struct recvbuf *rbufp - ) -{ - register struct atomunit *up; - struct refclockproc *pp; - struct peer *peer; - l_fp lftmp; - double doffset; - - /* - * This routine is called once per second when the serial - * interface is in use. It snatches the timestamp from the - * buffer and saves the sign-extended fraction in a circular - * buffer for processing at the next poll event. - */ - peer = (struct peer *)rbufp->recv_srcclock; - pp = peer->procptr; - up = (struct atomunit *)pp->unitptr; - pp->lencode = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, - &pp->lastrec); +#endif /* HAVE_PPSAPI */ - /* - * Save the timestamp for billboards. Sign-extend the fraction - * and stash in the buffer. No harm is done if previous data are - * overwritten. Do this only if the ppsclock gizmo is not - * working. - */ - if (up->flags & FLAG_PPS) - return; - L_CLR(&lftmp); - L_ADDF(&lftmp, pp->lastrec.l_f); - LFPTOD(&lftmp, doffset); - SAMPLE(-doffset + pp->fudgetime1); -} -#endif /* TTYCLK */ /* * pps_sample - receive PPS data from some other clock driver + * + * This routine is called once per second when the external clock driver + * processes PPS information. It processes the PPS timestamp and saves + * the sign-extended fraction in a circular buffer for processing at the + * next poll event. This works only for a single PPS device. */ int pps_sample( - l_fp *offset + l_fp *offset /* PPS offset */ ) { register struct peer *peer; - register struct atomunit *up; struct refclockproc *pp; l_fp lftmp; double doffset; - /* - * This routine is called once per second when the external - * clock driver processes PPS information. It processes the pps - * timestamp and saves the sign-extended fraction in a circular - * buffer for processing at the next poll event. - */ peer = pps_peer; if (peer == 0) /* nobody home */ - return 1; + return (1); pp = peer->procptr; - up = (struct atomunit *)pp->unitptr; /* * Convert the timeval to l_fp and save for billboards. Sign- @@ -421,7 +410,6 @@ pps_sample( * if previous data are overwritten. If the discipline comes bum * or the data grow stale, just forget it. */ - up->flags |= FLAG_AUX; pp->lastrec = *offset; L_CLR(&lftmp); L_ADDF(&lftmp, pp->lastrec.l_f); @@ -432,63 +420,81 @@ pps_sample( /* * atom_poll - called by the transmit procedure + * + * This routine is called once per second when in burst mode to save PPS + * sample offsets in the median filter. At the end of the burst period + * the samples are processed as a heap and the clock filter updated. */ static void atom_poll( - int unit, - struct peer *peer + int unit, /* unit number (not used) */ + struct peer *peer /* peer structure pointer */ ) { -#if defined(PPS) || defined(HAVE_PPSAPI) - register struct atomunit *up; -#endif /* PPS || HAVE_PPSAPI */ struct refclockproc *pp; +#ifdef HAVE_PPSAPI + int err; +#endif /* HAVE_PPSAPI */ /* - * Accumulate samples in the median filter. At the end of each - * poll interval, do a little bookeeping and process the - * samples. + * Accumulate samples in the median filter. If a noise sample, + * return with no prejudice; if a protocol error, get mean; + * otherwise, cool. At the end of each poll interval, do a + * little bookeeping and process the surviving samples. */ pp = peer->procptr; -#if defined(PPS) || defined(HAVE_PPSAPI) - up = (struct atomunit *)pp->unitptr; - if (!(up->flags & !(FLAG_AUX | FLAG_TTY))) { - int err; - - err = atom_pps(peer); - if (err > 0) { - refclock_report(peer, CEVNT_FAULT); - return; - } - } -#endif /* PPS || HAVE_PPSAPI */ pp->polls++; - if (peer->burst > 0) - return; - if (pp->coderecv == pp->codeproc) { - refclock_report(peer, CEVNT_TIMEOUT); +#ifdef HAVE_PPSAPI + err = atom_pps(peer); + if (err < 0) { + refclock_report(peer, CEVNT_FAULT); return; } +#endif /* HAVE_PPSAPI */ /* - * Valid time (leap bits zero) is returned only if the prefer - * peer has survived the intersection algorithm and within - * clock_max of local time and not too long ago. This ensures - * the pps time is within +-0.5 s of the local time and the - * seconds numbering is unambiguous. + * Valid time is returned only if the prefer peer has survived + * the intersection algorithm and within clock_max of local time + * and not too long ago. This ensures the PPS time is within + * +-0.5 s of the local time and the seconds numbering is + * unambiguous. Note that the leap bits are set no-warning on + * the first valid update and the stratum is set at the prefer + * peer. */ - if (pps_update) { - pp->leap = LEAP_NOWARNING; - } else { - pp->leap = LEAP_NOTINSYNC; + if (peer->burst > 0) + return; + peer->stratum = STRATUM_UNSPEC; + if (pp->codeproc == pp->coderecv) { + refclock_report(peer, CEVNT_TIMEOUT); + peer->burst = ASTAGE; + return; + + } else if (!sys_prefer) { + pp->codeproc = pp->coderecv; + peer->burst = ASTAGE; + return; + + } else if (fabs(sys_prefer->offset) > clock_max) { + pp->codeproc = pp->coderecv; + peer->burst = ASTAGE; return; } - pp->variance = 0; - record_clock_stats(&peer->srcadr, pp->a_lastcode); + peer->stratum = sys_prefer->stratum; + if (peer->stratum <= 1) + peer->refid = pp->refid; + else + peer->refid = peer->srcadr.sin_addr.s_addr; + pp->leap = LEAP_NOWARNING; refclock_receive(peer); - peer->burst = MAXSTAGE; + peer->burst = ASTAGE; } - #else int refclock_atom_bs; +int +pps_sample( + l_fp *offset /* PPS offset */ + ) +{ + return 1; +} #endif /* REFCLOCK */ |