From 4ded1c1fa0bc21c61f91a2dbe864835986745121 Mon Sep 17 00:00:00 2001 From: roberto Date: Sun, 17 Aug 2008 17:37:33 +0000 Subject: Flatten the dist and various 4.n.n trees in preparation of future ntp imports. --- contrib/ntp/ntpd/refclock_arc.c | 1529 --------------------------------------- 1 file changed, 1529 deletions(-) delete mode 100644 contrib/ntp/ntpd/refclock_arc.c (limited to 'contrib/ntp/ntpd/refclock_arc.c') diff --git a/contrib/ntp/ntpd/refclock_arc.c b/contrib/ntp/ntpd/refclock_arc.c deleted file mode 100644 index f556da6..0000000 --- a/contrib/ntp/ntpd/refclock_arc.c +++ /dev/null @@ -1,1529 +0,0 @@ -/* - * refclock_arc - clock driver for ARCRON MSF/DCF/WWVB receivers - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#if defined(REFCLOCK) && defined(CLOCK_ARCRON_MSF) -static const char arc_version[] = { "V1.3 2003/02/21" }; - -/* define PRE_NTP420 for compatibility to previous versions of NTP (at least - to 4.1.0 */ -#undef PRE_NTP420 - -#ifndef ARCRON_NOT_KEEN -#define ARCRON_KEEN 1 /* Be keen, and trusting of the clock, if defined. */ -#endif - -#ifndef ARCRON_NOT_MULTIPLE_SAMPLES -#define ARCRON_MULTIPLE_SAMPLES 1 /* Use all timestamp bytes as samples. */ -#endif - -#ifndef ARCRON_NOT_LEAPSECOND_KEEN -#ifndef ARCRON_LEAPSECOND_KEEN -#undef ARCRON_LEAPSECOND_KEEN /* Respond quickly to leap seconds: doesn't work yet. */ -#endif -#endif - -/* -Code by Derek Mulcahy, , 1997. -Modifications by Damon Hart-Davis, , 1997. -Modifications by Paul Alfille, , 2003. -Modifications by Christopher Price, , 2003. - - -THIS CODE IS SUPPLIED AS IS, WITH NO WARRANTY OF ANY KIND. USE AT -YOUR OWN RISK. - -Orginally developed and used with ntp3-5.85 by Derek Mulcahy. - -Built against ntp3-5.90 on Solaris 2.5 using gcc 2.7.2. - -This code may be freely copied and used and incorporated in other -systems providing the disclaimer and notice of authorship are -reproduced. - -------------------------------------------------------------------------------- - -Christopher's notes: - -MAJOR CHANGES SINCE V1.2 -======================== - 1) Applied patch by Andrey Bray - 2001-02-17 comp.protocols.time.ntp - - 2) Added WWVB support via clock mode command, localtime/UTC time configured - via flag1=(0=UTC, 1=localtime) - - 3) Added ignore resync request via flag2=(0=resync, 1=ignore resync) - - 4) Added simplified conversion from localtime to UTC with dst/bst translation - - 5) Added average signal quality poll - - 6) Fixed a badformat error when no code is available due to stripping - \n & \r's - - 7) Fixed a badformat error when clearing lencode & memset a_lastcode in poll - routine - - 8) Lots of code cleanup, including standardized DEBUG macros and removal - of unused code - -------------------------------------------------------------------------------- - -Author's original note: - -I enclose my ntp driver for the Galleon Systems Arc MSF receiver. - -It works (after a fashion) on both Solaris-1 and Solaris-2. - -I am currently using ntp3-5.85. I have been running the code for -about 7 months without any problems. Even coped with the change to BST! - -I had to do some funky things to read from the clock because it uses the -power from the receive lines to drive the transmit lines. This makes the -code look a bit stupid but it works. I also had to put in some delays to -allow for the turnaround time from receive to transmit. These delays -are between characters when requesting a time stamp so that shouldn't affect -the results too drastically. - -... - -The bottom line is that it works but could easily be improved. You are -free to do what you will with the code. I haven't been able to determine -how good the clock is. I think that this requires a known good clock -to compare it against. - -------------------------------------------------------------------------------- - -Damon's notes for adjustments: - -MAJOR CHANGES SINCE V1.0 -======================== - 1) Removal of pollcnt variable that made the clock go permanently - off-line once two time polls failed to gain responses. - - 2) Avoiding (at least on Solaris-2) terminal becoming the controlling - terminal of the process when we do a low-level open(). - - 3) Additional logic (conditional on ARCRON_LEAPSECOND_KEEN being - defined) to try to resync quickly after a potential leap-second - insertion or deletion. - - 4) Code significantly slimmer at run-time than V1.0. - - -GENERAL -======= - - 1) The C preprocessor symbol to have the clock built has been changed - from ARC to ARCRON_MSF to CLOCK_ARCRON_MSF to minimise the - possiblity of clashes with other symbols in the future. - - 2) PRECISION should be -4/-5 (63ms/31ms) for the following reasons: - - a) The ARC documentation claims the internal clock is (only) - accurate to about 20ms relative to Rugby (plus there must be - noticable drift and delay in the ms range due to transmission - delays and changing atmospheric effects). This clock is not - designed for ms accuracy as NTP has spoilt us all to expect. - - b) The clock oscillator looks like a simple uncompensated quartz - crystal of the sort used in digital watches (ie 32768Hz) which - can have large temperature coefficients and drifts; it is not - clear if this oscillator is properly disciplined to the MSF - transmission, but as the default is to resync only once per - *day*, we can imagine that it is not, and is free-running. We - can minimise drift by resyncing more often (at the cost of - reduced battery life), but drift/wander may still be - significant. - - c) Note that the bit time of 3.3ms adds to the potential error in - the the clock timestamp, since the bit clock of the serial link - may effectively be free-running with respect to the host clock - and the MSF clock. Actually, the error is probably 1/16th of - the above, since the input data is probably sampled at at least - 16x the bit rate. - - By keeping the clock marked as not very precise, it will have a - fairly large dispersion, and thus will tend to be used as a - `backup' time source and sanity checker, which this clock is - probably ideal for. For an isolated network without other time - sources, this clock can probably be expected to provide *much* - better than 1s accuracy, which will be fine. - - By default, PRECISION is set to -4, but experience, especially at a - particular geographic location with a particular clock, may allow - this to be altered to -5. (Note that skews of +/- 10ms are to be - expected from the clock from time-to-time.) This improvement of - reported precision can be instigated by setting flag3 to 1, though - the PRECISION will revert to the normal value while the clock - signal quality is unknown whatever the flag3 setting. - - IN ANY CASE, BE SURE TO SET AN APPROPRIATE FUDGE FACTOR TO REMOVE - ANY RESIDUAL SKEW, eg: - - server 127.127.27.0 # ARCRON MSF radio clock unit 0. - # Fudge timestamps by about 20ms. - fudge 127.127.27.0 time1 0.020 - - You will need to observe your system's behaviour, assuming you have - some other NTP source to compare it with, to work out what the - fudge factor should be. For my Sun SS1 running SunOS 4.1.3_U1 with - my MSF clock with my distance from the MSF transmitter, +20ms - seemed about right, after some observation. - - 3) REFID has been made "MSFa" to reflect the MSF time source and the - ARCRON receiver. - - 4) DEFAULT_RESYNC_TIME is the time in seconds (by default) before - forcing a resync since the last attempt. This is picked to give a - little less than an hour between resyncs and to try to avoid - clashing with any regular event at a regular time-past-the-hour - which might cause systematic errors. - - The INITIAL_RESYNC_DELAY is to avoid bothering the clock and - running down its batteries unnecesarily if ntpd is going to crash - or be killed or reconfigured quickly. If ARCRON_KEEN is defined - then this period is long enough for (with normal polling rates) - enough time samples to have been taken to allow ntpd to sync to - the clock before the interruption for the clock to resync to MSF. - This avoids ntpd syncing to another peer first and then - almost immediately hopping to the MSF clock. - - The RETRY_RESYNC_TIME is used before rescheduling a resync after a - resync failed to reveal a statisfatory signal quality (too low or - unknown). - - 5) The clock seems quite jittery, so I have increased the - median-filter size from the typical (previous) value of 3. I - discard up to half the results in the filter. It looks like maybe - 1 sample in 10 or so (maybe less) is a spike, so allow the median - filter to discard at least 10% of its entries or 1 entry, whichever - is greater. - - 6) Sleeping *before* each character sent to the unit to allow required - inter-character time but without introducting jitter and delay in - handling the response if possible. - - 7) If the flag ARCRON_KEEN is defined, take time samples whenever - possible, even while resyncing, etc. We rely, in this case, on the - clock always giving us a reasonable time or else telling us in the - status byte at the end of the timestamp that it failed to sync to - MSF---thus we should never end up syncing to completely the wrong - time. - - 8) If the flag ARCRON_OWN_FILTER is defined, use own versions of - refclock median-filter routines to get round small bug in 3-5.90 - code which does not return the median offset. XXX Removed this - bit due NTP Version 4 upgrade - dlm. - - 9) We would appear to have a year-2000 problem with this clock since - it returns only the two least-significant digits of the year. But - ntpd ignores the year and uses the local-system year instead, so - this is in fact not a problem. Nevertheless, we attempt to do a - sensible thing with the dates, wrapping them into a 100-year - window. - - 10)Logs stats information that can be used by Derek's Tcl/Tk utility - to show the status of the clock. - - 11)The clock documentation insists that the number of bits per - character to be sent to the clock, and sent by it, is 11, including - one start bit and two stop bits. The data format is either 7+even - or 8+none. - - -TO-DO LIST -========== - - * Eliminate use of scanf(), and maybe sprintf(). - - * Allow user setting of resync interval to trade battery life for - accuracy; maybe could be done via fudge factor or unit number. - - * Possibly note the time since the last resync of the MSF clock to - MSF as the age of the last reference timestamp, ie trust the - clock's oscillator not very much... - - * Add very slow auto-adjustment up to a value of +/- time2 to correct - for long-term errors in the clock value (time2 defaults to 0 so the - correction would be disabled by default). - - * Consider trying to use the tty_clk/ppsclock support. - - * Possibly use average or maximum signal quality reported during - resync, rather than just the last one, which may be atypical. - -*/ - - -/* Notes for HKW Elektronik GmBH Radio clock driver */ -/* Author Lyndon David, Sentinet Ltd, Feb 1997 */ -/* These notes seem also to apply usefully to the ARCRON clock. */ - -/* The HKW clock module is a radio receiver tuned into the Rugby */ -/* MSF time signal tranmitted on 60 kHz. The clock module connects */ -/* to the computer via a serial line and transmits the time encoded */ -/* in 15 bytes at 300 baud 7 bits two stop bits even parity */ - -/* Clock communications, from the datasheet */ -/* All characters sent to the clock are echoed back to the controlling */ -/* device. */ -/* Transmit time/date information */ -/* syntax ASCII o */ -/* Character o may be replaced if neccesary by a character whose code */ -/* contains the lowest four bits f(hex) eg */ -/* syntax binary: xxxx1111 00001101 */ - -/* DHD note: -You have to wait for character echo + 10ms before sending next character. -*/ - -/* The clock replies to this command with a sequence of 15 characters */ -/* which contain the complete time and a final making 16 characters */ -/* in total. */ -/* The RC computer clock will not reply immediately to this command because */ -/* the start bit edge of the first reply character marks the beginning of */ -/* the second. So the RC Computer Clock will reply to this command at the */ -/* start of the next second */ -/* The characters have the following meaning */ -/* 1. hours tens */ -/* 2. hours units */ -/* 3. minutes tens */ -/* 4. minutes units */ -/* 5. seconds tens */ -/* 6. seconds units */ -/* 7. day of week 1-monday 7-sunday */ -/* 8. day of month tens */ -/* 9. day of month units */ -/* 10. month tens */ -/* 11. month units */ -/* 12. year tens */ -/* 13. year units */ -/* 14. BST/UTC status */ -/* bit 7 parity */ -/* bit 6 always 0 */ -/* bit 5 always 1 */ -/* bit 4 always 1 */ -/* bit 3 always 0 */ -/* bit 2 =1 if UTC is in effect, complementary to the BST bit */ -/* bit 1 =1 if BST is in effect, according to the BST bit */ -/* bit 0 BST/UTC change impending bit=1 in case of change impending */ -/* 15. status */ -/* bit 7 parity */ -/* bit 6 always 0 */ -/* bit 5 always 1 */ -/* bit 4 always 1 */ -/* bit 3 =1 if low battery is detected */ -/* bit 2 =1 if the very last reception attempt failed and a valid */ -/* time information already exists (bit0=1) */ -/* =0 if the last reception attempt was successful */ -/* bit 1 =1 if at least one reception since 2:30 am was successful */ -/* =0 if no reception attempt since 2:30 am was successful */ -/* bit 0 =1 if the RC Computer Clock contains valid time information */ -/* This bit is zero after reset and one after the first */ -/* successful reception attempt */ - -/* DHD note: -Also note g command which confirms that a resync is in progress, and -if so what signal quality (0--5) is available. -Also note h command which starts a resync to MSF signal. -*/ - - -#include "ntpd.h" -#include "ntp_io.h" -#include "ntp_refclock.h" -#include "ntp_calendar.h" -#include "ntp_stdlib.h" - -#include -#include - -#if defined(HAVE_BSD_TTYS) -#include -#endif /* HAVE_BSD_TTYS */ - -#if defined(HAVE_SYSV_TTYS) -#include -#endif /* HAVE_SYSV_TTYS */ - -#if defined(HAVE_TERMIOS) -#include -#endif - -/* - * This driver supports the ARCRON MSF/DCF/WWVB Radio Controlled Clock - */ - -/* - * Interface definitions - */ -#define DEVICE "/dev/arc%d" /* Device name and unit. */ -#define SPEED B300 /* UART speed (300 baud) */ -#define PRECISION (-4) /* Precision (~63 ms). */ -#define HIGHPRECISION (-5) /* If things are going well... */ -#define REFID "MSFa" /* Reference ID. */ -#define REFID_MSF "MSF" /* Reference ID. */ -#define REFID_DCF77 "DCF" /* Reference ID. */ -#define REFID_WWVB "WWVB" /* Reference ID. */ -#define DESCRIPTION "ARCRON MSF/DCF/WWVB Receiver" - -#ifdef PRE_NTP420 -#define MODE ttlmax -#else -#define MODE ttl -#endif - -#define LENARC 16 /* Format `o' timecode length. */ - -#define BITSPERCHAR 11 /* Bits per character. */ -#define BITTIME 0x0DA740E /* Time for 1 bit at 300bps. */ -#define CHARTIME10 0x8888888 /* Time for 10-bit char at 300bps. */ -#define CHARTIME11 0x962FC96 /* Time for 11-bit char at 300bps. */ -#define CHARTIME /* Time for char at 300bps. */ \ -( (BITSPERCHAR == 11) ? CHARTIME11 : ( (BITSPERCHAR == 10) ? CHARTIME10 : \ - (BITSPERCHAR * BITTIME) ) ) - - /* Allow for UART to accept char half-way through final stop bit. */ -#define INITIALOFFSET (u_int32)(-BITTIME/2) - - /* - charoffsets[x] is the time after the start of the second that byte - x (with the first byte being byte 1) is received by the UART, - assuming that the initial edge of the start bit of the first byte - is on-time. The values are represented as the fractional part of - an l_fp. - - We store enough values to have the offset of each byte including - the trailing \r, on the assumption that the bytes follow one - another without gaps. - */ - static const u_int32 charoffsets[LENARC+1] = { -#if BITSPERCHAR == 11 /* Usual case. */ - /* Offsets computed as accurately as possible... */ - 0, - INITIALOFFSET + 0x0962fc96, /* 1 chars, 11 bits */ - INITIALOFFSET + 0x12c5f92c, /* 2 chars, 22 bits */ - INITIALOFFSET + 0x1c28f5c3, /* 3 chars, 33 bits */ - INITIALOFFSET + 0x258bf259, /* 4 chars, 44 bits */ - INITIALOFFSET + 0x2eeeeeef, /* 5 chars, 55 bits */ - INITIALOFFSET + 0x3851eb85, /* 6 chars, 66 bits */ - INITIALOFFSET + 0x41b4e81b, /* 7 chars, 77 bits */ - INITIALOFFSET + 0x4b17e4b1, /* 8 chars, 88 bits */ - INITIALOFFSET + 0x547ae148, /* 9 chars, 99 bits */ - INITIALOFFSET + 0x5dddddde, /* 10 chars, 110 bits */ - INITIALOFFSET + 0x6740da74, /* 11 chars, 121 bits */ - INITIALOFFSET + 0x70a3d70a, /* 12 chars, 132 bits */ - INITIALOFFSET + 0x7a06d3a0, /* 13 chars, 143 bits */ - INITIALOFFSET + 0x8369d037, /* 14 chars, 154 bits */ - INITIALOFFSET + 0x8ccccccd, /* 15 chars, 165 bits */ - INITIALOFFSET + 0x962fc963 /* 16 chars, 176 bits */ -#else - /* Offsets computed with a small rounding error... */ - 0, - INITIALOFFSET + 1 * CHARTIME, - INITIALOFFSET + 2 * CHARTIME, - INITIALOFFSET + 3 * CHARTIME, - INITIALOFFSET + 4 * CHARTIME, - INITIALOFFSET + 5 * CHARTIME, - INITIALOFFSET + 6 * CHARTIME, - INITIALOFFSET + 7 * CHARTIME, - INITIALOFFSET + 8 * CHARTIME, - INITIALOFFSET + 9 * CHARTIME, - INITIALOFFSET + 10 * CHARTIME, - INITIALOFFSET + 11 * CHARTIME, - INITIALOFFSET + 12 * CHARTIME, - INITIALOFFSET + 13 * CHARTIME, - INITIALOFFSET + 14 * CHARTIME, - INITIALOFFSET + 15 * CHARTIME, - INITIALOFFSET + 16 * CHARTIME -#endif - }; - -#define DEFAULT_RESYNC_TIME (57*60) /* Gap between resync attempts (s). */ -#define RETRY_RESYNC_TIME (27*60) /* Gap to emergency resync attempt. */ -#ifdef ARCRON_KEEN -#define INITIAL_RESYNC_DELAY 500 /* Delay before first resync. */ -#else -#define INITIAL_RESYNC_DELAY 50 /* Delay before first resync. */ -#endif - - static const int moff[12] = -{ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; -/* Flags for a raw open() of the clock serial device. */ -#ifdef O_NOCTTY /* Good, we can avoid tty becoming controlling tty. */ -#define OPEN_FLAGS (O_RDWR | O_NOCTTY) -#else /* Oh well, it may not matter... */ -#define OPEN_FLAGS (O_RDWR) -#endif - - -/* Length of queue of command bytes to be sent. */ -#define CMDQUEUELEN 4 /* Enough for two cmds + each \r. */ -/* Queue tick time; interval in seconds between chars taken off queue. */ -/* Must be >= 2 to allow o\r response to come back uninterrupted. */ -#define QUEUETICK 2 /* Allow o\r reply to finish. */ - -/* - * ARC unit control structure - */ -struct arcunit { - l_fp lastrec; /* Time tag for the receive time (system). */ - int status; /* Clock status. */ - - int quality; /* Quality of reception 0--5 for unit. */ - /* We may also use the values -1 or 6 internally. */ - u_long quality_stamp; /* Next time to reset quality average. */ - - u_long next_resync; /* Next resync time (s) compared to current_time. */ - int resyncing; /* Resync in progress if true. */ - - /* In the outgoing queue, cmdqueue[0] is next to be sent. */ - char cmdqueue[CMDQUEUELEN+1]; /* Queue of outgoing commands + \0. */ - - u_long saved_flags; /* Saved fudge flags. */ -}; - -#ifdef ARCRON_LEAPSECOND_KEEN -/* The flag `possible_leap' is set non-zero when any MSF unit - thinks a leap-second may have happened. - - Set whenever we receive a valid time sample in the first hour of - the first day of the first/seventh months. - - Outside the special hour this value is unconditionally set - to zero by the receive routine. - - On finding itself in this timeslot, as long as the value is - non-negative, the receive routine sets it to a positive value to - indicate a resync to MSF should be performed. - - In the poll routine, if this value is positive and we are not - already resyncing (eg from a sync that started just before - midnight), start resyncing and set this value negative to - indicate that a leap-triggered resync has been started. Having - set this negative prevents the receive routine setting it - positive and thus prevents multiple resyncs during the witching - hour. - */ -static int possible_leap = 0; /* No resync required by default. */ -#endif - -#if 0 -static void dummy_event_handler P((struct peer *)); -static void arc_event_handler P((struct peer *)); -#endif /* 0 */ - -#define QUALITY_UNKNOWN -1 /* Indicates unknown clock quality. */ -#define MIN_CLOCK_QUALITY 0 /* Min quality clock will return. */ -#define MIN_CLOCK_QUALITY_OK 3 /* Min quality for OK reception. */ -#define MAX_CLOCK_QUALITY 5 /* Max quality clock will return. */ - -/* - * Function prototypes - */ -static int arc_start P((int, struct peer *)); -static void arc_shutdown P((int, struct peer *)); -static void arc_receive P((struct recvbuf *)); -static void arc_poll P((int, struct peer *)); - -/* - * Transfer vector - */ -struct refclock refclock_arc = { - arc_start, /* start up driver */ - arc_shutdown, /* shut down driver */ - arc_poll, /* transmit poll message */ - noentry, /* not used (old arc_control) */ - noentry, /* initialize driver (not used) */ - noentry, /* not used (old arc_buginfo) */ - NOFLAGS /* not used */ -}; - -/* Queue us up for the next tick. */ -#define ENQUEUE(up) \ - do { \ - peer->nextaction = current_time + QUEUETICK; \ - } while(0) - -/* Placeholder event handler---does nothing safely---soaks up loose tick. */ -static void -dummy_event_handler( - struct peer *peer - ) -{ -#ifdef DEBUG - if(debug) { printf("arc: dummy_event_handler() called.\n"); } -#endif -} - -/* -Normal event handler. - -Take first character off queue and send to clock if not a null. - -Shift characters down and put a null on the end. - -We assume that there is no parallelism so no race condition, but even -if there is nothing bad will happen except that we might send some bad -data to the clock once in a while. -*/ -static void -arc_event_handler( - struct peer *peer - ) -{ - struct refclockproc *pp = peer->procptr; - register struct arcunit *up = (struct arcunit *)pp->unitptr; - int i; - char c; -#ifdef DEBUG - if(debug > 2) { printf("arc: arc_event_handler() called.\n"); } -#endif - - c = up->cmdqueue[0]; /* Next char to be sent. */ - /* Shift down characters, shifting trailing \0 in at end. */ - for(i = 0; i < CMDQUEUELEN; ++i) - { up->cmdqueue[i] = up->cmdqueue[i+1]; } - - /* Don't send '\0' characters. */ - if(c != '\0') { - if(write(pp->io.fd, &c, 1) != 1) { - msyslog(LOG_NOTICE, "ARCRON: write to fd %d failed", pp->io.fd); - } -#ifdef DEBUG - else if(debug) { printf("arc: sent `%2.2x', fd %d.\n", c, pp->io.fd); } -#endif - } - - ENQUEUE(up); -} - -/* - * arc_start - open the devices and initialize data for processing - */ -static int -arc_start( - int unit, - struct peer *peer - ) -{ - register struct arcunit *up; - struct refclockproc *pp; - int fd; - char device[20]; -#ifdef HAVE_TERMIOS - struct termios arg; -#endif - - msyslog(LOG_NOTICE, "ARCRON: %s: opening unit %d", arc_version, unit); -#ifdef DEBUG - if(debug) { - printf("arc: %s: attempt to open unit %d.\n", arc_version, unit); - } -#endif - - /* Prevent a ridiculous device number causing overflow of device[]. */ - if((unit < 0) || (unit > 255)) { return(0); } - - /* - * Open serial port. Use CLK line discipline, if available. - */ - (void)sprintf(device, DEVICE, unit); - if (!(fd = refclock_open(device, SPEED, LDISC_CLK))) - return(0); -#ifdef DEBUG - if(debug) { printf("arc: unit %d using open().\n", unit); } -#endif - fd = open(device, OPEN_FLAGS); - if(fd < 0) { -#ifdef DEBUG - if(debug) { printf("arc: failed [open()] to open %s.\n", device); } -#endif - return(0); - } - - fcntl(fd, F_SETFL, 0); /* clear the descriptor flags */ -#ifdef DEBUG - if(debug) - { printf("arc: opened RS232 port with file descriptor %d.\n", fd); } -#endif - -#ifdef HAVE_TERMIOS - - arg.c_iflag = IGNBRK | ISTRIP; - arg.c_oflag = 0; - arg.c_cflag = B300 | CS8 | CREAD | CLOCAL | CSTOPB; - arg.c_lflag = 0; - arg.c_cc[VMIN] = 1; - arg.c_cc[VTIME] = 0; - - tcsetattr(fd, TCSANOW, &arg); - -#else - - msyslog(LOG_ERR, "ARCRON: termios not supported in this driver"); - (void)close(fd); - - return 0; - -#endif - - up = (struct arcunit *) emalloc(sizeof(struct arcunit)); - if(!up) { (void) close(fd); return(0); } - /* Set structure to all zeros... */ - memset((char *)up, 0, sizeof(struct arcunit)); - pp = peer->procptr; - pp->io.clock_recv = arc_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); return(0); } - pp->unitptr = (caddr_t)up; - - /* - * Initialize miscellaneous variables - */ - peer->precision = PRECISION; - peer->stratum = 2; /* Default to stratum 2 not 0. */ - pp->clockdesc = DESCRIPTION; - if (peer->MODE > 3) { - msyslog(LOG_NOTICE, "ARCRON: Invalid mode %d", peer->MODE); - return 0; - } -#ifdef DEBUG - if(debug) { printf("arc: mode = %d.\n", peer->MODE); } -#endif - switch (peer->MODE) { - case 1: - memcpy((char *)&pp->refid, REFID_MSF, 4); - break; - case 2: - memcpy((char *)&pp->refid, REFID_DCF77, 4); - break; - case 3: - memcpy((char *)&pp->refid, REFID_WWVB, 4); - break; - default: - memcpy((char *)&pp->refid, REFID, 4); - break; - } - /* Spread out resyncs so that they should remain separated. */ - up->next_resync = current_time + INITIAL_RESYNC_DELAY + (67*unit)%1009; - -#if 0 /* Not needed because of zeroing of arcunit structure... */ - up->resyncing = 0; /* Not resyncing yet. */ - up->saved_flags = 0; /* Default is all flags off. */ - /* Clear send buffer out... */ - { - int i; - for(i = CMDQUEUELEN; i >= 0; --i) { up->cmdqueue[i] = '\0'; } - } -#endif - -#ifdef ARCRON_KEEN - up->quality = QUALITY_UNKNOWN; /* Trust the clock immediately. */ -#else - up->quality = MIN_CLOCK_QUALITY;/* Don't trust the clock yet. */ -#endif - - peer->action = arc_event_handler; - - ENQUEUE(up); - - return(1); -} - - -/* - * arc_shutdown - shut down the clock - */ -static void -arc_shutdown( - int unit, - struct peer *peer - ) -{ - register struct arcunit *up; - struct refclockproc *pp; - - peer->action = dummy_event_handler; - - pp = peer->procptr; - up = (struct arcunit *)pp->unitptr; - io_closeclock(&pp->io); - free(up); -} - -/* -Compute space left in output buffer. -*/ -static int -space_left( - register struct arcunit *up - ) -{ - int spaceleft; - - /* Compute space left in buffer after any pending output. */ - for(spaceleft = 0; spaceleft < CMDQUEUELEN; ++spaceleft) - { if(up->cmdqueue[CMDQUEUELEN - 1 - spaceleft] != '\0') { break; } } - return(spaceleft); -} - -/* -Send command by copying into command buffer as far forward as possible, -after any pending output. - -Indicate an error by returning 0 if there is not space for the command. -*/ -static int -send_slow( - register struct arcunit *up, - int fd, - const char *s - ) -{ - int sl = strlen(s); - int spaceleft = space_left(up); - -#ifdef DEBUG - if(debug > 1) { printf("arc: spaceleft = %d.\n", spaceleft); } -#endif - if(spaceleft < sl) { /* Should not normally happen... */ -#ifdef DEBUG - msyslog(LOG_NOTICE, "ARCRON: send-buffer overrun (%d/%d)", - sl, spaceleft); -#endif - return(0); /* FAILED! */ - } - - /* Copy in the command to be sent. */ - while(*s) { up->cmdqueue[CMDQUEUELEN - spaceleft--] = *s++; } - - return(1); -} - - -/* Macro indicating action we will take for different quality values. */ -#define quality_action(q) \ -(((q) == QUALITY_UNKNOWN) ? "UNKNOWN, will use clock anyway" : \ - (((q) < MIN_CLOCK_QUALITY_OK) ? "TOO POOR, will not use clock" : \ - "OK, will use clock")) - - /* - * arc_receive - receive data from the serial interface - */ - static void -arc_receive( - struct recvbuf *rbufp - ) -{ - register struct arcunit *up; - struct refclockproc *pp; - struct peer *peer; - char c; - int i, n, wday, month, flags, status; - int arc_last_offset; - static int quality_average = 0; - static int quality_sum = 0; - static int quality_polls = 0; - - /* - * Initialize pointers and read the timecode and timestamp - */ - peer = (struct peer *)rbufp->recv_srcclock; - pp = peer->procptr; - up = (struct arcunit *)pp->unitptr; - - - /* - If the command buffer is empty, and we are resyncing, insert a - g\r quality request into it to poll for signal quality again. - */ - if((up->resyncing) && (space_left(up) == CMDQUEUELEN)) { -#ifdef DEBUG - if(debug > 1) { printf("arc: inserting signal-quality poll.\n"); } -#endif - send_slow(up, pp->io.fd, "g\r"); - } - - /* - The `arc_last_offset' is the offset in lastcode[] of the last byte - received, and which we assume actually received the input - timestamp. - - (When we get round to using tty_clk and it is available, we - assume that we will receive the whole timecode with the - trailing \r, and that that \r will be timestamped. But this - assumption also works if receive the characters one-by-one.) - */ - arc_last_offset = pp->lencode+rbufp->recv_length - 1; - - /* - We catch a timestamp iff: - - * The command code is `o' for a timestamp. - - * If ARCRON_MULTIPLE_SAMPLES is undefined then we must have - exactly char in the buffer (the command code) so that we - only sample the first character of the timecode as our - `on-time' character. - - * The first character in the buffer is not the echoed `\r' - from the `o` command (so if we are to timestamp an `\r' it - must not be first in the receive buffer with lencode==1. - (Even if we had other characters following it, we probably - would have a premature timestamp on the '\r'.) - - * We have received at least one character (I cannot imagine - how it could be otherwise, but anyway...). - */ - c = rbufp->recv_buffer[0]; - if((pp->a_lastcode[0] == 'o') && -#ifndef ARCRON_MULTIPLE_SAMPLES - (pp->lencode == 1) && -#endif - ((pp->lencode != 1) || (c != '\r')) && - (arc_last_offset >= 1)) { - /* Note that the timestamp should be corrected if >1 char rcvd. */ - l_fp timestamp; - timestamp = rbufp->recv_time; -#ifdef DEBUG - if(debug) { /* Show \r as `R', other non-printing char as `?'. */ - printf("arc: stamp -->%c<-- (%d chars rcvd)\n", - ((c == '\r') ? 'R' : (isgraph((int)c) ? c : '?')), - rbufp->recv_length); - } -#endif - - /* - Now correct timestamp by offset of last byte received---we - subtract from the receive time the delay implied by the - extra characters received. - - Reject the input if the resulting code is too long, but - allow for the trailing \r, normally not used but a good - handle for tty_clk or somesuch kernel timestamper. - */ - if(arc_last_offset > LENARC) { -#ifdef DEBUG - if(debug) { - printf("arc: input code too long (%d cf %d); rejected.\n", - arc_last_offset, LENARC); - } -#endif - pp->lencode = 0; - refclock_report(peer, CEVNT_BADREPLY); - return; - } - - L_SUBUF(×tamp, charoffsets[arc_last_offset]); -#ifdef DEBUG - if(debug > 1) { - printf( - "arc: %s%d char(s) rcvd, the last for lastcode[%d]; -%sms offset applied.\n", - ((rbufp->recv_length > 1) ? "*** " : ""), - rbufp->recv_length, - arc_last_offset, - mfptoms((unsigned long)0, - charoffsets[arc_last_offset], - 1)); - } -#endif - -#ifdef ARCRON_MULTIPLE_SAMPLES - /* - If taking multiple samples, capture the current adjusted - sample iff: - - * No timestamp has yet been captured (it is zero), OR - - * This adjusted timestamp is earlier than the one already - captured, on the grounds that this one suffered less - delay in being delivered to us and is more accurate. - - */ - if(L_ISZERO(&(up->lastrec)) || - L_ISGEQ(&(up->lastrec), ×tamp)) -#endif - { -#ifdef DEBUG - if(debug > 1) { - printf("arc: system timestamp captured.\n"); -#ifdef ARCRON_MULTIPLE_SAMPLES - if(!L_ISZERO(&(up->lastrec))) { - l_fp diff; - diff = up->lastrec; - L_SUB(&diff, ×tamp); - printf("arc: adjusted timestamp by -%sms.\n", - mfptoms(diff.l_i, diff.l_f, 3)); - } -#endif - } -#endif - up->lastrec = timestamp; - } - - } - - /* Just in case we still have lots of rubbish in the buffer... */ - /* ...and to avoid the same timestamp being reused by mistake, */ - /* eg on receipt of the \r coming in on its own after the */ - /* timecode. */ - if(pp->lencode >= LENARC) { -#ifdef DEBUG - if(debug && (rbufp->recv_buffer[0] != '\r')) - { printf("arc: rubbish in pp->a_lastcode[].\n"); } -#endif - pp->lencode = 0; - return; - } - - /* Append input to code buffer, avoiding overflow. */ - for(i = 0; i < rbufp->recv_length; i++) { - if(pp->lencode >= LENARC) { break; } /* Avoid overflow... */ - c = rbufp->recv_buffer[i]; - - /* Drop trailing '\r's and drop `h' command echo totally. */ - if(c != '\r' && c != 'h') { pp->a_lastcode[pp->lencode++] = c; } - - /* - If we've just put an `o' in the lastcode[0], clear the - timestamp in anticipation of a timecode arriving soon. - - We would expect to get to process this before any of the - timecode arrives. - */ - if((c == 'o') && (pp->lencode == 1)) { - L_CLR(&(up->lastrec)); -#ifdef DEBUG - if(debug > 1) { printf("arc: clearing timestamp.\n"); } -#endif - } - } - if (pp->lencode == 0) return; - - /* Handle a quality message. */ - if(pp->a_lastcode[0] == 'g') { - int r, q; - - if(pp->lencode < 3) { return; } /* Need more data... */ - r = (pp->a_lastcode[1] & 0x7f); /* Strip parity. */ - q = (pp->a_lastcode[2] & 0x7f); /* Strip parity. */ - if(((q & 0x70) != 0x30) || ((q & 0xf) > MAX_CLOCK_QUALITY) || - ((r & 0x70) != 0x30)) { - /* Badly formatted response. */ -#ifdef DEBUG - if(debug) { printf("arc: bad `g' response %2x %2x.\n", r, q); } -#endif - return; - } - if(r == '3') { /* Only use quality value whilst sync in progress. */ - if (up->quality_stamp < current_time) { - struct calendar cal; - l_fp new_stamp; - - get_systime (&new_stamp); - caljulian (new_stamp.l_ui, &cal); - up->quality_stamp = - current_time + 60 - cal.second + 5; - quality_sum = 0; - quality_polls = 0; - } - quality_sum += (q & 0xf); - quality_polls++; - quality_average = (quality_sum / quality_polls); -#ifdef DEBUG - if(debug) { printf("arc: signal quality %d (%d).\n", quality_average, (q & 0xf)); } -#endif - } else if( /* (r == '2') && */ up->resyncing) { - up->quality = quality_average; -#ifdef DEBUG - if(debug) - { - printf("arc: sync finished, signal quality %d: %s\n", - up->quality, - quality_action(up->quality)); - } -#endif - msyslog(LOG_NOTICE, - "ARCRON: sync finished, signal quality %d: %s", - up->quality, - quality_action(up->quality)); - up->resyncing = 0; /* Resync is over. */ - quality_average = 0; - quality_sum = 0; - quality_polls = 0; - -#ifdef ARCRON_KEEN - /* Clock quality dubious; resync earlier than usual. */ - if((up->quality == QUALITY_UNKNOWN) || - (up->quality < MIN_CLOCK_QUALITY_OK)) - { up->next_resync = current_time + RETRY_RESYNC_TIME; } -#endif - } - pp->lencode = 0; - return; - } - - /* Stop now if this is not a timecode message. */ - if(pp->a_lastcode[0] != 'o') { - pp->lencode = 0; - refclock_report(peer, CEVNT_BADREPLY); - return; - } - - /* If we don't have enough data, wait for more... */ - if(pp->lencode < LENARC) { return; } - - - /* WE HAVE NOW COLLECTED ONE TIMESTAMP (phew)... */ -#ifdef DEBUG - if(debug > 1) { printf("arc: NOW HAVE TIMESTAMP...\n"); } -#endif - - /* But check that we actually captured a system timestamp on it. */ - if(L_ISZERO(&(up->lastrec))) { -#ifdef DEBUG - if(debug) { printf("arc: FAILED TO GET SYSTEM TIMESTAMP\n"); } -#endif - pp->lencode = 0; - refclock_report(peer, CEVNT_BADREPLY); - return; - } - /* - Append a mark of the clock's received signal quality for the - benefit of Derek Mulcahy's Tcl/Tk utility (we map the `unknown' - quality value to `6' for his s/w) and terminate the string for - sure. This should not go off the buffer end. - */ - pp->a_lastcode[pp->lencode] = ((up->quality == QUALITY_UNKNOWN) ? - '6' : ('0' + up->quality)); - pp->a_lastcode[pp->lencode + 1] = '\0'; /* Terminate for printf(). */ - -#ifdef PRE_NTP420 - /* We don't use the micro-/milli- second part... */ - pp->usec = 0; - pp->msec = 0; -#else - /* We don't use the nano-second part... */ - pp->nsec = 0; -#endif - n = sscanf(pp->a_lastcode, "o%2d%2d%2d%1d%2d%2d%2d%1d%1d", - &pp->hour, &pp->minute, &pp->second, - &wday, &pp->day, &month, &pp->year, &flags, &status); - - /* Validate format and numbers. */ - if(n != 9) { -#ifdef DEBUG - /* Would expect to have caught major problems already... */ - if(debug) { printf("arc: badly formatted data.\n"); } -#endif - pp->lencode = 0; - refclock_report(peer, CEVNT_BADREPLY); - return; - } - /* - Validate received values at least enough to prevent internal - array-bounds problems, etc. - */ - if((pp->hour < 0) || (pp->hour > 23) || - (pp->minute < 0) || (pp->minute > 59) || - (pp->second < 0) || (pp->second > 60) /*Allow for leap seconds.*/ || - (wday < 1) || (wday > 7) || - (pp->day < 1) || (pp->day > 31) || - (month < 1) || (month > 12) || - (pp->year < 0) || (pp->year > 99)) { - /* Data out of range. */ - pp->lencode = 0; - refclock_report(peer, CEVNT_BADREPLY); - return; - } - - - if(peer->MODE == 0) { /* compatiblity to original version */ - int bst = flags; - /* Check that BST/UTC bits are the complement of one another. */ - if(!(bst & 2) == !(bst & 4)) { - pp->lencode = 0; - refclock_report(peer, CEVNT_BADREPLY); - return; - } - } - if(status & 0x8) { msyslog(LOG_NOTICE, "ARCRON: battery low"); } - - /* Year-2000 alert! */ - /* Attempt to wrap 2-digit date into sensible window. */ - if(pp->year < YEAR_PIVOT) { pp->year += 100; } /* Y2KFixes */ - pp->year += 1900; /* use full four-digit year */ /* Y2KFixes */ - /* - Attempt to do the right thing by screaming that the code will - soon break when we get to the end of its useful life. What a - hero I am... PLEASE FIX LEAP-YEAR AND WRAP CODE IN 209X! - */ - if(pp->year >= YEAR_PIVOT+2000-2 ) { /* Y2KFixes */ - /*This should get attention B^> */ - msyslog(LOG_NOTICE, - "ARCRON: fix me! EITHER YOUR DATE IS BADLY WRONG or else I will break soon!"); - } -#ifdef DEBUG - if(debug) { - printf("arc: n=%d %02d:%02d:%02d %02d/%02d/%04d %1d %1d\n", - n, - pp->hour, pp->minute, pp->second, - pp->day, month, pp->year, flags, status); - } -#endif - - /* - The status value tested for is not strictly supported by the - clock spec since the value of bit 2 (0x4) is claimed to be - undefined for MSF, yet does seem to indicate if the last resync - was successful or not. - */ - pp->leap = LEAP_NOWARNING; - status &= 0x7; - if(status == 0x3) { - if(status != up->status) - { msyslog(LOG_NOTICE, "ARCRON: signal acquired"); } - } else { - if(status != up->status) { - msyslog(LOG_NOTICE, "ARCRON: signal lost"); - pp->leap = LEAP_NOTINSYNC; /* MSF clock is free-running. */ - up->status = status; - pp->lencode = 0; - refclock_report(peer, CEVNT_FAULT); - return; - } - } - up->status = status; - - if (peer->MODE == 0) { /* compatiblity to original version */ - int bst = flags; - - pp->day += moff[month - 1]; - - if(isleap_4(pp->year) && month > 2) { pp->day++; }/* Y2KFixes */ - - /* Convert to UTC if required */ - if(bst & 2) { - pp->hour--; - if (pp->hour < 0) { - pp->hour = 23; - pp->day--; - /* If we try to wrap round the year - * (BST on 1st Jan), reject.*/ - if(pp->day < 0) { - pp->lencode = 0; - refclock_report(peer, CEVNT_BADTIME); - return; - } - } - } - } - - if(peer->MODE > 0) { - if(pp->sloppyclockflag & CLK_FLAG1) { - struct tm local; - struct tm *gmtp; - time_t unixtime; - - /* - * Convert to GMT for sites that distribute localtime. - * This means we have to do Y2K conversion on the - * 2-digit year; otherwise, we get the time wrong. - */ - - local.tm_year = pp->year-1900; - local.tm_mon = month-1; - local.tm_mday = pp->day; - local.tm_hour = pp->hour; - local.tm_min = pp->minute; - local.tm_sec = pp->second; - switch (peer->MODE) { - case 1: - local.tm_isdst = (flags & 2); - break; - case 2: - local.tm_isdst = (flags & 2); - break; - case 3: - switch (flags & 3) { - case 0: /* It is unclear exactly when the - Arcron changes from DST->ST and - ST->DST. Testing has shown this - to be irregular. For the time - being, let the OS decide. */ - local.tm_isdst = 0; -#ifdef DEBUG - if (debug) - printf ("arc: DST = 00 (0)\n"); -#endif - break; - case 1: /* dst->st time */ - local.tm_isdst = -1; -#ifdef DEBUG - if (debug) - printf ("arc: DST = 01 (1)\n"); -#endif - break; - case 2: /* st->dst time */ - local.tm_isdst = -1; -#ifdef DEBUG - if (debug) - printf ("arc: DST = 10 (2)\n"); -#endif - break; - case 3: /* dst time */ - local.tm_isdst = 1; -#ifdef DEBUG - if (debug) - printf ("arc: DST = 11 (3)\n"); -#endif - break; - } - break; - default: - msyslog(LOG_NOTICE, "ARCRON: Invalid mode %d", - peer->MODE); - return; - break; - } - unixtime = mktime (&local); - if ((gmtp = gmtime (&unixtime)) == NULL) - { - pp->lencode = 0; - refclock_report (peer, CEVNT_FAULT); - return; - } - pp->year = gmtp->tm_year+1900; - month = gmtp->tm_mon+1; - pp->day = ymd2yd(pp->year,month,gmtp->tm_mday); - /* pp->day = gmtp->tm_yday; */ - pp->hour = gmtp->tm_hour; - pp->minute = gmtp->tm_min; - pp->second = gmtp->tm_sec; -#ifdef DEBUG - if (debug) - { - printf ("arc: time is %04d/%02d/%02d %02d:%02d:%02d UTC\n", - pp->year,month,gmtp->tm_mday,pp->hour,pp->minute, - pp->second); - } -#endif - } else - { - /* - * For more rational sites distributing UTC - */ - pp->day = ymd2yd(pp->year,month,pp->day); - } - } - - if (peer->MODE == 0) { /* compatiblity to original version */ - /* If clock signal quality is - * unknown, revert to default PRECISION...*/ - if(up->quality == QUALITY_UNKNOWN) { - peer->precision = PRECISION; - } else { /* ...else improve precision if flag3 is set... */ - peer->precision = ((pp->sloppyclockflag & CLK_FLAG3) ? - HIGHPRECISION : PRECISION); - } - } else { - if ((status == 0x3) && (pp->sloppyclockflag & CLK_FLAG2)) { - peer->precision = ((pp->sloppyclockflag & CLK_FLAG3) ? - HIGHPRECISION : PRECISION); - } else if (up->quality == QUALITY_UNKNOWN) { - peer->precision = PRECISION; - } else { - peer->precision = ((pp->sloppyclockflag & CLK_FLAG3) ? - HIGHPRECISION : PRECISION); - } - } - - /* Notice and log any change (eg from initial defaults) for flags. */ - if(up->saved_flags != pp->sloppyclockflag) { -#ifdef DEBUG - msyslog(LOG_NOTICE, "ARCRON: flags enabled: %s%s%s%s", - ((pp->sloppyclockflag & CLK_FLAG1) ? "1" : "."), - ((pp->sloppyclockflag & CLK_FLAG2) ? "2" : "."), - ((pp->sloppyclockflag & CLK_FLAG3) ? "3" : "."), - ((pp->sloppyclockflag & CLK_FLAG4) ? "4" : ".")); - /* Note effects of flags changing... */ - if(debug) { - printf("arc: PRECISION = %d.\n", peer->precision); - } -#endif - up->saved_flags = pp->sloppyclockflag; - } - - /* Note time of last believable timestamp. */ - pp->lastrec = up->lastrec; - -#ifdef ARCRON_LEAPSECOND_KEEN - /* Find out if a leap-second might just have happened... - (ie is this the first hour of the first day of Jan or Jul?) - */ - if((pp->hour == 0) && - (pp->day == 1) && - ((month == 1) || (month == 7))) { - if(possible_leap >= 0) { - /* A leap may have happened, and no resync has started yet...*/ - possible_leap = 1; - } - } else { - /* Definitely not leap-second territory... */ - possible_leap = 0; - } -#endif - - if (!refclock_process(pp)) { - pp->lencode = 0; - refclock_report(peer, CEVNT_BADTIME); - return; - } - record_clock_stats(&peer->srcadr, pp->a_lastcode); - refclock_receive(peer); -} - - -/* request_time() sends a time request to the clock with given peer. */ -/* This automatically reports a fault if necessary. */ -/* No data should be sent after this until arc_poll() returns. */ -static void request_time P((int, struct peer *)); -static void -request_time( - int unit, - struct peer *peer - ) -{ - struct refclockproc *pp = peer->procptr; - register struct arcunit *up = (struct arcunit *)pp->unitptr; -#ifdef DEBUG - if(debug) { printf("arc: unit %d: requesting time.\n", unit); } -#endif - if (!send_slow(up, pp->io.fd, "o\r")) { -#ifdef DEBUG - if (debug) { - printf("arc: unit %d: problem sending", unit); - } -#endif - pp->lencode = 0; - refclock_report(peer, CEVNT_FAULT); - return; - } - pp->polls++; -} - -/* - * arc_poll - called by the transmit procedure - */ -static void -arc_poll( - int unit, - struct peer *peer - ) -{ - register struct arcunit *up; - struct refclockproc *pp; - int resync_needed; /* Should we start a resync? */ - - pp = peer->procptr; - up = (struct arcunit *)pp->unitptr; -#if 0 - pp->lencode = 0; - memset(pp->a_lastcode, 0, sizeof(pp->a_lastcode)); -#endif - -#if 0 - /* Flush input. */ - tcflush(pp->io.fd, TCIFLUSH); -#endif - - /* Resync if our next scheduled resync time is here or has passed. */ - resync_needed = ( !(pp->sloppyclockflag & CLK_FLAG2) && - (up->next_resync <= current_time) ); - -#ifdef ARCRON_LEAPSECOND_KEEN - /* - Try to catch a potential leap-second insertion or deletion quickly. - - In addition to the normal NTP fun of clocks that don't report - leap-seconds spooking their hosts, this clock does not even - sample the radio sugnal the whole time, so may miss a - leap-second insertion or deletion for up to a whole sample - time. - - To try to minimise this effect, if in the first few minutes of - the day immediately following a leap-second-insertion point - (ie in the first hour of the first day of the first and sixth - months), and if the last resync was in the previous day, and a - resync is not already in progress, resync the clock - immediately. - - */ - if((possible_leap > 0) && /* Must be 00:XX 01/0{1,7}/XXXX. */ - (!up->resyncing)) { /* No resync in progress yet. */ - resync_needed = 1; - possible_leap = -1; /* Prevent multiple resyncs. */ - msyslog(LOG_NOTICE,"ARCRON: unit %d: checking for leap second",unit); - } -#endif - - /* Do a resync if required... */ - if(resync_needed) { - /* First, reset quality value to `unknown' so we can detect */ - /* when a quality message has been responded to by this */ - /* being set to some other value. */ - up->quality = QUALITY_UNKNOWN; - - /* Note that we are resyncing... */ - up->resyncing = 1; - - /* Now actually send the resync command and an immediate poll. */ -#ifdef DEBUG - if(debug) { printf("arc: sending resync command (h\\r).\n"); } -#endif - msyslog(LOG_NOTICE, "ARCRON: unit %d: sending resync command", unit); - send_slow(up, pp->io.fd, "h\r"); - - /* Schedule our next resync... */ - up->next_resync = current_time + DEFAULT_RESYNC_TIME; - - /* Drop through to request time if appropriate. */ - } - - /* If clock quality is too poor to trust, indicate a fault. */ - /* If quality is QUALITY_UNKNOWN and ARCRON_KEEN is defined,*/ - /* we'll cross our fingers and just hope that the thing */ - /* synced so quickly we did not catch it---we'll */ - /* double-check the clock is OK elsewhere. */ - if( -#ifdef ARCRON_KEEN - (up->quality != QUALITY_UNKNOWN) && -#else - (up->quality == QUALITY_UNKNOWN) || -#endif - (up->quality < MIN_CLOCK_QUALITY_OK)) { -#ifdef DEBUG - if(debug) { - printf("arc: clock quality %d too poor.\n", up->quality); - } -#endif - pp->lencode = 0; - refclock_report(peer, CEVNT_FAULT); - return; - } - /* This is the normal case: request a timestamp. */ - request_time(unit, peer); -} - -#else -int refclock_arc_bs; -#endif -- cgit v1.1