summaryrefslogtreecommitdiffstats
path: root/contrib/ntp/ntpd/refclock_atom.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/ntp/ntpd/refclock_atom.c')
-rw-r--r--contrib/ntp/ntpd/refclock_atom.c504
1 files changed, 0 insertions, 504 deletions
diff --git a/contrib/ntp/ntpd/refclock_atom.c b/contrib/ntp/ntpd/refclock_atom.c
deleted file mode 100644
index 51153ae..0000000
--- a/contrib/ntp/ntpd/refclock_atom.c
+++ /dev/null
@@ -1,504 +0,0 @@
-
-/*
- * refclock_atom - clock driver for 1-pps signals
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <ctype.h>
-
-#include "ntpd.h"
-#include "ntp_io.h"
-#include "ntp_unixtime.h"
-#include "ntp_refclock.h"
-#include "ntp_stdlib.h"
-
-#if defined(REFCLOCK) && defined(CLOCK_ATOM)
-
-#ifdef HAVE_PPSAPI
-# ifdef HAVE_TIMEPPS_H
-# include <timepps.h>
-# else
-# ifdef HAVE_SYS_TIMEPPS_H
-# include <sys/timepps.h>
-# endif
-# endif
-#endif /* HAVE_PPSAPI */
-
-/*
- * This driver furnishes an interface for pulse-per-second (PPS) signals
- * 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.
- *
- * 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. 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.
- *
- * 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.
- *
- * 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.
- *
- * 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 device
- * driver and OS delays.
- */
-/*
- * Interface definitions
- */
-#ifdef HAVE_PPSAPI
-#define DEVICE "/dev/pps%d" /* device name and unit */
-#endif /* HAVE_PPSAPI */
-
-#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 */
-
-static struct peer *pps_peer; /* atom driver for PPS sources */
-
-#ifdef HAVE_PPSAPI
-/*
- * PPS unit control structure
- */
-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_poll P((int, struct peer *));
-#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 *));
-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 */
-#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 */
-};
-
-
-/*
- * atom_start - initialize data for processing
- */
-static int
-atom_start(
- int unit, /* unit number (not used) */
- struct peer *peer /* peer structure pointer */
- )
-{
- struct refclockproc *pp;
-#ifdef HAVE_PPSAPI
- register struct ppsunit *up;
- char device[80];
-#endif /* HAVE_PPSAPI */
-
- /*
- * Allocate and initialize unit structure
- */
- pps_peer = peer;
- pp = peer->procptr;
- peer->precision = PRECISION;
- pp->clockdesc = DESCRIPTION;
- pp->stratum = STRATUM_UNSPEC;
- memcpy((char *)&pp->refid, REFID, 4);
- peer->burst = ASTAGE;
-#ifdef HAVE_PPSAPI
- up = emalloc(sizeof(struct ppsunit));
- memset(up, 0, sizeof(struct ppsunit));
- pp->unitptr = (caddr_t)up;
-
- /*
- * Open PPS device. If this fails and some driver has already
- * opened the associated radio device, fdpps has the file
- * descriptor for it.
- */
- 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);
- }
-
- /*
- * 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 (time_pps_create(up->fddev, &up->handle) < 0) {
- msyslog(LOG_ERR,
- "refclock_atom: time_pps_create failed: %m");
- return (0);
- }
- return (atom_ppsapi(peer, 0, 0));
-#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;
- 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",
- enb_clear);
- 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;
- }
-#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);
-}
-
-
-/*
- * atom_shutdown - shut down the clock
- */
-static void
-atom_shutdown(
- int unit, /* unit number (not used) */
- struct peer *peer /* peer structure pointer */
- )
-{
- struct refclockproc *pp;
- register struct ppsunit *up;
-
- pp = peer->procptr;
- 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);
-}
-
-
-/*
- * 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 /* peer structure pointer */
- )
-{
- register struct ppsunit *up;
- struct refclockproc *pp;
- pps_info_t pps_info;
- struct timespec timeout, ts;
- double dtemp;
-
- /*
- * 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.
- */
- pp = peer->procptr;
- up = (struct ppsunit *)pp->unitptr;
- if (up->handle == 0)
- return (-1);
- timeout.tv_sec = 0;
- timeout.tv_nsec = 0;
- 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 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;
- } else {
- return (-1);
- }
- 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 /* HAVE_PPSAPI */
-
-
-/*
- * 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 /* PPS offset */
- )
-{
- register struct peer *peer;
- struct refclockproc *pp;
- l_fp lftmp;
- double doffset;
-
- peer = pps_peer;
- if (peer == 0) /* nobody home */
- return (1);
- pp = peer->procptr;
-
- /*
- * 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.
- */
- pp->lastrec = *offset;
- L_CLR(&lftmp);
- L_ADDF(&lftmp, pp->lastrec.l_f);
- LFPTOD(&lftmp, doffset);
- SAMPLE(-doffset + pp->fudgetime1);
- return (0);
-}
-
-/*
- * 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, /* unit number (not used) */
- struct peer *peer /* peer structure pointer */
- )
-{
- struct refclockproc *pp;
-#ifdef HAVE_PPSAPI
- int err;
-#endif /* HAVE_PPSAPI */
-
- /*
- * 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;
- pp->polls++;
-#ifdef HAVE_PPSAPI
- err = atom_pps(peer);
- if (err < 0) {
- refclock_report(peer, CEVNT_FAULT);
- return;
- }
-#endif /* HAVE_PPSAPI */
-
- /*
- * 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, unless overriden by a fudge command.
- */
- if (peer->burst > 0)
- return;
- peer->leap = LEAP_NOTINSYNC;
- if (pp->codeproc == pp->coderecv) {
- refclock_report(peer, CEVNT_TIMEOUT);
- peer->burst = ASTAGE;
- return;
-
- } else if (sys_prefer == NULL) {
- 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->leap = LEAP_NOWARNING;
- if (pp->stratum >= STRATUM_UNSPEC)
- peer->stratum = sys_prefer->stratum;
- else
- peer->stratum = pp->stratum;
- if (peer->stratum == STRATUM_REFCLOCK || peer->stratum ==
- STRATUM_UNSPEC)
- peer->refid = pp->refid;
- else
- peer->refid = addr2refid(&sys_prefer->srcadr);
- pp->lastref = pp->lastrec;
- refclock_receive(peer);
- peer->burst = ASTAGE;
-}
-#else
-int refclock_atom_bs;
-int
-pps_sample(
- l_fp *offset /* PPS offset */
- )
-{
- return 1;
-}
-#endif /* REFCLOCK */
OpenPOWER on IntegriCloud