154359Sroberto/*
254359Sroberto * ntp_loopfilter.c - implements the NTP loop filter algorithm
354359Sroberto *
4132451Sroberto * ATTENTION: Get approval from Dave Mills on all changes to this file!
5132451Sroberto *
654359Sroberto */
754359Sroberto#ifdef HAVE_CONFIG_H
854359Sroberto# include <config.h>
954359Sroberto#endif
1054359Sroberto
11285612Sdelphij#ifdef USE_SNPRINTB
12285612Sdelphij# include <util.h>
13285612Sdelphij#endif
1482498Sroberto#include "ntpd.h"
1582498Sroberto#include "ntp_io.h"
1682498Sroberto#include "ntp_unixtime.h"
1782498Sroberto#include "ntp_stdlib.h"
1882498Sroberto
19285612Sdelphij#include <limits.h>
2054359Sroberto#include <stdio.h>
2154359Sroberto#include <ctype.h>
2254359Sroberto
2354359Sroberto#include <signal.h>
2454359Sroberto#include <setjmp.h>
2554359Sroberto
2654359Sroberto#ifdef KERNEL_PLL
2754359Sroberto#include "ntp_syscall.h"
2854359Sroberto#endif /* KERNEL_PLL */
2954359Sroberto
3054359Sroberto/*
3154359Sroberto * This is an implementation of the clock discipline algorithm described
3254359Sroberto * in UDel TR 97-4-3, as amended. It operates as an adaptive parameter,
3354359Sroberto * hybrid phase/frequency-lock loop. A number of sanity checks are
3454359Sroberto * included to protect against timewarps, timespikes and general mayhem.
3554359Sroberto * All units are in s and s/s, unless noted otherwise.
3654359Sroberto */
37132451Sroberto#define CLOCK_MAX	.128	/* default step threshold (s) */
38285612Sdelphij#define CLOCK_MINSTEP	300.	/* default stepout threshold (s) */
39132451Sroberto#define CLOCK_PANIC	1000.	/* default panic threshold (s) */
4082498Sroberto#define	CLOCK_PHI	15e-6	/* max frequency error (s/s) */
41182007Sroberto#define CLOCK_PLL	16.	/* PLL loop gain (log2) */
42182007Sroberto#define CLOCK_AVG	8.	/* parameter averaging constant */
43285612Sdelphij#define CLOCK_FLL	.25	/* FLL loop gain */
44285612Sdelphij#define	CLOCK_FLOOR	.0005	/* startup offset floor (s) */
45285612Sdelphij#define	CLOCK_ALLAN	11	/* Allan intercept (log2 s) */
4654359Sroberto#define CLOCK_LIMIT	30	/* poll-adjust threshold */
4754359Sroberto#define CLOCK_PGATE	4.	/* poll-adjust gate */
48106163Sroberto#define PPS_MAXAGE	120	/* kernel pps signal timeout (s) */
49285612Sdelphij#define	FREQTOD(x)	((x) / 65536e6) /* NTP to double */
50285612Sdelphij#define	DTOFREQ(x)	((int32)((x) * 65536e6)) /* double to NTP */
5154359Sroberto
5254359Sroberto/*
5354359Sroberto * Clock discipline state machine. This is used to control the
5454359Sroberto * synchronization behavior during initialization and following a
5582498Sroberto * timewarp.
5682498Sroberto *
57182007Sroberto *	State	< step		> step		Comments
58285612Sdelphij *	========================================================
59285612Sdelphij *	NSET	FREQ		step, FREQ	freq not set
6082498Sroberto *
61285612Sdelphij *	FSET	SYNC		step, SYNC	freq set
6282498Sroberto *
63285612Sdelphij *	FREQ	if (mu < 900)	if (mu < 900)	set freq direct
64182007Sroberto *		    ignore	    ignore
65182007Sroberto *		else		else
66182007Sroberto *		    freq, SYNC	    freq, step, SYNC
6782498Sroberto *
68285612Sdelphij *	SYNC	SYNC		SPIK, ignore	adjust phase/freq
69285612Sdelphij *
70285612Sdelphij *	SPIK	SYNC		if (mu < 900)	adjust phase/freq
71182007Sroberto *				    ignore
72285612Sdelphij *				step, SYNC
7354359Sroberto */
7454359Sroberto/*
7554359Sroberto * Kernel PLL/PPS state machine. This is used with the kernel PLL
76285612Sdelphij * modifications described in the documentation.
7754359Sroberto *
7854359Sroberto * If kernel support for the ntp_adjtime() system call is available, the
7954359Sroberto * ntp_control flag is set. The ntp_enable and kern_enable flags can be
8054359Sroberto * set at configuration time or run time using ntpdc. If ntp_enable is
81182007Sroberto * false, the discipline loop is unlocked and no corrections of any kind
8254359Sroberto * are made. If both ntp_control and kern_enable are set, the kernel
8354359Sroberto * support is used as described above; if false, the kernel is bypassed
84182007Sroberto * entirely and the daemon discipline used instead.
8554359Sroberto *
86182007Sroberto * There have been three versions of the kernel discipline code. The
87182007Sroberto * first (microkernel) now in Solaris discipilnes the microseconds. The
88182007Sroberto * second and third (nanokernel) disciplines the clock in nanoseconds.
89182007Sroberto * These versions are identifed if the symbol STA_PLL is present in the
90182007Sroberto * header file /usr/include/sys/timex.h. The third and current version
91182007Sroberto * includes TAI offset and is identified by the symbol NTP_API with
92182007Sroberto * value 4.
93182007Sroberto *
94285612Sdelphij * Each PPS time/frequency discipline can be enabled by the atom driver
95285612Sdelphij * or another driver. If enabled, the STA_PPSTIME and STA_FREQ bits are
96285612Sdelphij * set in the kernel status word; otherwise, these bits are cleared.
97285612Sdelphij * These bits are also cleard if the kernel reports an error.
9854359Sroberto *
9954359Sroberto * If an external clock is present, the clock driver sets STA_CLK in the
10054359Sroberto * status word. When the local clock driver sees this bit, it updates
10154359Sroberto * via this routine, which then calls ntp_adjtime() with the STA_PLL bit
10254359Sroberto * set to zero, in which case the system clock is not adjusted. This is
10354359Sroberto * also a signal for the external clock driver to discipline the system
104285612Sdelphij * clock. Unless specified otherwise, all times are in seconds.
10554359Sroberto */
10654359Sroberto/*
10782498Sroberto * Program variables that can be tinkered.
10882498Sroberto */
109285612Sdelphijdouble	clock_max_back = CLOCK_MAX;	/* step threshold */
110285612Sdelphijdouble	clock_max_fwd =  CLOCK_MAX;	/* step threshold */
111285612Sdelphijdouble	clock_minstep = CLOCK_MINSTEP; /* stepout threshold */
112285612Sdelphijdouble	clock_panic = CLOCK_PANIC; /* panic threshold */
11382498Srobertodouble	clock_phi = CLOCK_PHI;	/* dispersion rate (s/s) */
114285612Sdelphiju_char	allan_xpt = CLOCK_ALLAN; /* Allan intercept (log2 s) */
11582498Sroberto
11682498Sroberto/*
11754359Sroberto * Program variables
11854359Sroberto */
119285612Sdelphijstatic double clock_offset;	/* offset */
120285612Sdelphijdouble	clock_jitter;		/* offset jitter */
121182007Srobertodouble	drift_comp;		/* frequency (s/s) */
122285612Sdelphijstatic double init_drift_comp; /* initial frequency (PPM) */
123182007Srobertodouble	clock_stability;	/* frequency stability (wander) (s/s) */
124285612Sdelphijdouble	clock_codec;		/* audio codec frequency (samples/s) */
125285612Sdelphijstatic u_long clock_epoch;	/* last update */
126285612Sdelphiju_int	sys_tai;		/* TAI offset from UTC */
127285612Sdelphijstatic int loop_started;	/* TRUE after LOOP_DRIFTINIT */
128285612Sdelphijstatic void rstclock (int, double); /* transition function */
129285612Sdelphijstatic double direct_freq(double); /* direct set frequency */
130285612Sdelphijstatic void set_freq(double);	/* set frequency */
131285612Sdelphij#ifndef PATH_MAX
132285612Sdelphij# define PATH_MAX MAX_PATH
133285612Sdelphij#endif
134285612Sdelphijstatic char relative_path[PATH_MAX + 1]; /* relative path per recursive make */
135285612Sdelphijstatic char *this_file = NULL;
13654359Sroberto
13754359Sroberto#ifdef KERNEL_PLL
138285612Sdelphijstatic struct timex ntv;	/* ntp_adjtime() parameters */
139285612Sdelphijint	pll_status;		/* last kernel status bits */
140285612Sdelphij#if defined(STA_NANO) && NTP_API == 4
141285612Sdelphijstatic u_int loop_tai;		/* last TAI offset */
142285612Sdelphij#endif /* STA_NANO */
143285612Sdelphijstatic	void	start_kern_loop(void);
144285612Sdelphijstatic	void	stop_kern_loop(void);
14554359Sroberto#endif /* KERNEL_PLL */
14654359Sroberto
14754359Sroberto/*
14854359Sroberto * Clock state machine control flags
14954359Sroberto */
150285612Sdelphijint	ntp_enable = TRUE;	/* clock discipline enabled */
15154359Srobertoint	pll_control;		/* kernel support available */
152285612Sdelphijint	kern_enable = TRUE;	/* kernel support enabled */
153285612Sdelphijint	hardpps_enable;		/* kernel PPS discipline enabled */
15454359Srobertoint	ext_enable;		/* external clock enabled */
15582498Srobertoint	pps_stratum;		/* pps stratum */
156285612Sdelphijint	kernel_status;		/* from ntp_adjtime */
157285612Sdelphijint	force_step_once = FALSE; /* always step time once at startup (-G) */
158285612Sdelphijint	mode_ntpdate = FALSE;	/* exit on first clock set (-q) */
159285612Sdelphijint	freq_cnt;		/* initial frequency clamp */
160285612Sdelphijint	freq_set;		/* initial set frequency switch */
16154359Sroberto
16254359Sroberto/*
16354359Sroberto * Clock state machine variables
16454359Sroberto */
165285612Sdelphijint	state = 0;		/* clock discipline state */
166285612Sdelphiju_char	sys_poll;		/* time constant/poll (log2 s) */
167182007Srobertoint	tc_counter;		/* jiggle counter */
168182007Srobertodouble	last_offset;		/* last offset (s) */
16954359Sroberto
17082498Sroberto/*
17182498Sroberto * Huff-n'-puff filter variables
17282498Sroberto */
17382498Srobertostatic double *sys_huffpuff;	/* huff-n'-puff filter */
17482498Srobertostatic int sys_hufflen;		/* huff-n'-puff filter stages */
17582498Srobertostatic int sys_huffptr;		/* huff-n'-puff filter pointer */
17682498Srobertostatic double sys_mindly;	/* huff-n'-puff filter min delay */
17782498Sroberto
17854359Sroberto#if defined(KERNEL_PLL)
17954359Sroberto/* Emacs cc-mode goes nuts if we split the next line... */
18054359Sroberto#define MOD_BITS (MOD_OFFSET | MOD_MAXERROR | MOD_ESTERROR | \
18154359Sroberto    MOD_STATUS | MOD_TIMECONST)
18282498Sroberto#ifdef SIGSYS
183285612Sdelphijstatic void pll_trap (int);	/* configuration trap */
18454359Srobertostatic struct sigaction sigsys;	/* current sigaction status */
18554359Srobertostatic struct sigaction newsigsys; /* new sigaction status */
18654359Srobertostatic sigjmp_buf env;		/* environment var. for pll_trap() */
18754359Sroberto#endif /* SIGSYS */
18854359Sroberto#endif /* KERNEL_PLL */
18954359Sroberto
190285612Sdelphijstatic void
191285612Sdelphijsync_status(const char *what, int ostatus, int nstatus)
192285612Sdelphij{
193285612Sdelphij	char obuf[256], nbuf[256], tbuf[1024];
194285612Sdelphij#if defined(USE_SNPRINTB) && defined (STA_FMT)
195285612Sdelphij	snprintb(obuf, sizeof(obuf), STA_FMT, ostatus);
196285612Sdelphij	snprintb(nbuf, sizeof(nbuf), STA_FMT, nstatus);
197285612Sdelphij#else
198285612Sdelphij	snprintf(obuf, sizeof(obuf), "%04x", ostatus);
199285612Sdelphij	snprintf(nbuf, sizeof(nbuf), "%04x", nstatus);
200285612Sdelphij#endif
201285612Sdelphij	snprintf(tbuf, sizeof(tbuf), "%s status: %s -> %s", what, obuf, nbuf);
202285612Sdelphij	report_event(EVNT_KERN, NULL, tbuf);
203285612Sdelphij}
204285612Sdelphij
20554359Sroberto/*
206285612Sdelphij * file_name - return pointer to non-relative portion of this C file pathname
207285612Sdelphij */
208285612Sdelphijstatic char *file_name(void)
209285612Sdelphij{
210285612Sdelphij	if (this_file == NULL) {
211285612Sdelphij	    (void)strncpy(relative_path, __FILE__, PATH_MAX);
212285612Sdelphij	    for (this_file=relative_path;
213285612Sdelphij		*this_file && ! isalnum((unsigned char)*this_file);
214285612Sdelphij		this_file++) ;
215285612Sdelphij	}
216285612Sdelphij	return this_file;
217285612Sdelphij}
218285612Sdelphij
219285612Sdelphij/*
22054359Sroberto * init_loopfilter - initialize loop filter data
22154359Sroberto */
22254359Srobertovoid
22354359Srobertoinit_loopfilter(void)
22454359Sroberto{
22554359Sroberto	/*
226285612Sdelphij	 * Initialize state variables.
22754359Sroberto	 */
228285612Sdelphij	sys_poll = ntp_minpoll;
229182007Sroberto	clock_jitter = LOGTOD(sys_precision);
230285612Sdelphij	freq_cnt = (int)clock_minstep;
23154359Sroberto}
23254359Sroberto
233285612Sdelphij#ifdef KERNEL_PLL
23454359Sroberto/*
235285612Sdelphij * ntp_adjtime_error_handler - process errors from ntp_adjtime
236285612Sdelphij */
237285612Sdelphijstatic void
238285612Sdelphijntp_adjtime_error_handler(
239285612Sdelphij	const char *caller,	/* name of calling function */
240285612Sdelphij	struct timex *ptimex,	/* pointer to struct timex */
241285612Sdelphij	int ret,		/* return value from ntp_adjtime */
242285612Sdelphij	int saved_errno,	/* value of errno when ntp_adjtime returned */
243285612Sdelphij	int pps_call,		/* ntp_adjtime call was PPS-related */
244285612Sdelphij	int tai_call,		/* ntp_adjtime call was TAI-related */
245285612Sdelphij	int line		/* line number of ntp_adjtime call */
246285612Sdelphij	)
247285612Sdelphij{
248285612Sdelphij	char des[1024] = "";	/* Decoded Error Status */
249285612Sdelphij
250285612Sdelphij	switch (ret) {
251285612Sdelphij	    case -1:
252285612Sdelphij		switch (saved_errno) {
253285612Sdelphij		    case EFAULT:
254285612Sdelphij			msyslog(LOG_ERR, "%s: %s line %d: invalid struct timex pointer: 0x%lx",
255285612Sdelphij			    caller, file_name(), line,
256285612Sdelphij			    (long)((void *)ptimex)
257285612Sdelphij			);
258285612Sdelphij		    break;
259285612Sdelphij		    case EINVAL:
260285612Sdelphij			msyslog(LOG_ERR, "%s: %s line %d: invalid struct timex \"constant\" element value: %ld",
261285612Sdelphij			    caller, file_name(), line,
262285612Sdelphij			    (long)(ptimex->constant)
263285612Sdelphij			);
264285612Sdelphij		    break;
265285612Sdelphij		    case EPERM:
266285612Sdelphij			if (tai_call) {
267285612Sdelphij			    errno = saved_errno;
268285612Sdelphij			    msyslog(LOG_ERR,
269285612Sdelphij				"%s: ntp_adjtime(TAI) failed: %m",
270285612Sdelphij				caller);
271285612Sdelphij			}
272285612Sdelphij			errno = saved_errno;
273285612Sdelphij			msyslog(LOG_ERR, "%s: %s line %d: ntp_adjtime: %m",
274285612Sdelphij			    caller, file_name(), line
275285612Sdelphij			);
276285612Sdelphij		    break;
277285612Sdelphij		    default:
278285612Sdelphij			msyslog(LOG_NOTICE, "%s: %s line %d: unhandled errno value %d after failed ntp_adjtime call",
279285612Sdelphij			    caller, file_name(), line,
280285612Sdelphij			    saved_errno
281285612Sdelphij			);
282285612Sdelphij		    break;
283285612Sdelphij		}
284285612Sdelphij	    break;
285285612Sdelphij#ifdef TIME_OK
286285612Sdelphij	    case TIME_OK: /* 0: synchronized, no leap second warning */
287285612Sdelphij		/* msyslog(LOG_INFO, "kernel reports time is synchronized normally"); */
288285612Sdelphij	    break;
289285612Sdelphij#else
290285612Sdelphij# warning TIME_OK is not defined
291285612Sdelphij#endif
292285612Sdelphij#ifdef TIME_INS
293285612Sdelphij	    case TIME_INS: /* 1: positive leap second warning */
294285612Sdelphij		msyslog(LOG_INFO, "kernel reports leap second insertion scheduled");
295285612Sdelphij	    break;
296285612Sdelphij#else
297285612Sdelphij# warning TIME_INS is not defined
298285612Sdelphij#endif
299285612Sdelphij#ifdef TIME_DEL
300285612Sdelphij	    case TIME_DEL: /* 2: negative leap second warning */
301285612Sdelphij		msyslog(LOG_INFO, "kernel reports leap second deletion scheduled");
302285612Sdelphij	    break;
303285612Sdelphij#else
304285612Sdelphij# warning TIME_DEL is not defined
305285612Sdelphij#endif
306285612Sdelphij#ifdef TIME_OOP
307285612Sdelphij	    case TIME_OOP: /* 3: leap second in progress */
308285612Sdelphij		msyslog(LOG_INFO, "kernel reports leap second in progress");
309285612Sdelphij	    break;
310285612Sdelphij#else
311285612Sdelphij# warning TIME_OOP is not defined
312285612Sdelphij#endif
313285612Sdelphij#ifdef TIME_WAIT
314285612Sdelphij	    case TIME_WAIT: /* 4: leap second has occured */
315285612Sdelphij		msyslog(LOG_INFO, "kernel reports leap second has occurred");
316285612Sdelphij	    break;
317285612Sdelphij#else
318285612Sdelphij# warning TIME_WAIT is not defined
319285612Sdelphij#endif
320285612Sdelphij#ifdef TIME_ERROR
321285612Sdelphij#if 0
322285612Sdelphij
323285612Sdelphijfrom the reference implementation of ntp_gettime():
324285612Sdelphij
325285612Sdelphij		// Hardware or software error
326285612Sdelphij        if ((time_status & (STA_UNSYNC | STA_CLOCKERR))
327285612Sdelphij
328285612Sdelphij	/*
329285612Sdelphij         * PPS signal lost when either time or frequency synchronization
330285612Sdelphij         * requested
331285612Sdelphij         */
332285612Sdelphij	|| (time_status & (STA_PPSFREQ | STA_PPSTIME)
333285612Sdelphij	    && !(time_status & STA_PPSSIGNAL))
334285612Sdelphij
335285612Sdelphij        /*
336285612Sdelphij         * PPS jitter exceeded when time synchronization requested
337285612Sdelphij         */
338285612Sdelphij	|| (time_status & STA_PPSTIME &&
339285612Sdelphij            time_status & STA_PPSJITTER)
340285612Sdelphij
341285612Sdelphij        /*
342285612Sdelphij         * PPS wander exceeded or calibration error when frequency
343285612Sdelphij         * synchronization requested
344285612Sdelphij         */
345285612Sdelphij	|| (time_status & STA_PPSFREQ &&
346285612Sdelphij            time_status & (STA_PPSWANDER | STA_PPSERROR)))
347285612Sdelphij                return (TIME_ERROR);
348285612Sdelphij
349285612Sdelphijor, from ntp_adjtime():
350285612Sdelphij
351285612Sdelphij	if (  (time_status & (STA_UNSYNC | STA_CLOCKERR))
352285612Sdelphij	    || (time_status & (STA_PPSFREQ | STA_PPSTIME)
353285612Sdelphij		&& !(time_status & STA_PPSSIGNAL))
354285612Sdelphij	    || (time_status & STA_PPSTIME
355285612Sdelphij		&& time_status & STA_PPSJITTER)
356285612Sdelphij	    || (time_status & STA_PPSFREQ
357285612Sdelphij		&& time_status & (STA_PPSWANDER | STA_PPSERROR))
358285612Sdelphij	   )
359285612Sdelphij		return (TIME_ERROR);
360285612Sdelphij#endif
361285612Sdelphij
362285612Sdelphij	    case TIME_ERROR: /* 5: unsynchronized, or loss of synchronization */
363285612Sdelphij				/* error (see status word) */
364285612Sdelphij
365285612Sdelphij		if (ptimex->status & STA_UNSYNC)
366285612Sdelphij			snprintf(des, sizeof(des), "%s%sClock Unsynchronized",
367285612Sdelphij				des, (*des) ? "; " : "");
368285612Sdelphij
369285612Sdelphij		if (ptimex->status & STA_CLOCKERR)
370285612Sdelphij			snprintf(des, sizeof(des), "%s%sClock Error",
371285612Sdelphij				des, (*des) ? "; " : "");
372285612Sdelphij
373285612Sdelphij		if (!(ptimex->status & STA_PPSSIGNAL)
374285612Sdelphij		    && ptimex->status & STA_PPSFREQ)
375285612Sdelphij			snprintf(des, sizeof(des), "%s%sPPS Frequency Sync wanted but no PPS",
376285612Sdelphij				des, (*des) ? "; " : "");
377285612Sdelphij
378285612Sdelphij		if (!(ptimex->status & STA_PPSSIGNAL)
379285612Sdelphij		    && ptimex->status & STA_PPSTIME)
380285612Sdelphij			snprintf(des, sizeof(des), "%s%sPPS Time Sync wanted but no PPS signal",
381285612Sdelphij				des, (*des) ? "; " : "");
382285612Sdelphij
383285612Sdelphij		if (   ptimex->status & STA_PPSTIME
384285612Sdelphij		    && ptimex->status & STA_PPSJITTER)
385285612Sdelphij			snprintf(des, sizeof(des), "%s%sPPS Time Sync wanted but PPS Jitter exceeded",
386285612Sdelphij				des, (*des) ? "; " : "");
387285612Sdelphij
388285612Sdelphij		if (   ptimex->status & STA_PPSFREQ
389285612Sdelphij		    && ptimex->status & STA_PPSWANDER)
390285612Sdelphij			snprintf(des, sizeof(des), "%s%sPPS Frequency Sync wanted but PPS Wander exceeded",
391285612Sdelphij				des, (*des) ? "; " : "");
392285612Sdelphij
393285612Sdelphij		if (   ptimex->status & STA_PPSFREQ
394285612Sdelphij		    && ptimex->status & STA_PPSERROR)
395285612Sdelphij			snprintf(des, sizeof(des), "%s%sPPS Frequency Sync wanted but Calibration error detected",
396285612Sdelphij				des, (*des) ? "; " : "");
397285612Sdelphij
398285612Sdelphij		if (pps_call && !(ptimex->status & STA_PPSSIGNAL))
399285612Sdelphij			report_event(EVNT_KERN, NULL,
400285612Sdelphij			    "no PPS signal");
401285612Sdelphij		DPRINTF(1, ("kernel loop status %#x (%s)\n",
402285612Sdelphij			ptimex->status, des));
403285612Sdelphij		/*
404285612Sdelphij		 * This code may be returned when ntp_adjtime() has just
405285612Sdelphij		 * been called for the first time, quite a while after
406285612Sdelphij		 * startup, when ntpd just starts to discipline the kernel
407285612Sdelphij		 * time. In this case the occurrence of this message
408285612Sdelphij		 * can be pretty confusing.
409285612Sdelphij		 *
410285612Sdelphij		 * HMS: How about a message when we begin kernel processing:
411285612Sdelphij		 *    Determining kernel clock state...
412285612Sdelphij		 * so an initial TIME_ERROR message is less confising,
413285612Sdelphij		 * or skipping the first message (ugh),
414285612Sdelphij		 * or ???
415285612Sdelphij		 * msyslog(LOG_INFO, "kernel reports time synchronization lost");
416285612Sdelphij		 */
417285612Sdelphij		msyslog(LOG_INFO, "kernel reports TIME_ERROR: %#x: %s",
418285612Sdelphij			ptimex->status, des);
419285612Sdelphij	    break;
420285612Sdelphij#else
421285612Sdelphij# warning TIME_ERROR is not defined
422285612Sdelphij#endif
423285612Sdelphij	    default:
424285612Sdelphij		msyslog(LOG_NOTICE, "%s: %s line %d: unhandled return value %d from ntp_adjtime() in %s at line %d",
425285612Sdelphij		    caller, file_name(), line,
426285612Sdelphij		    ret,
427285612Sdelphij		    __func__, __LINE__
428285612Sdelphij		);
429285612Sdelphij	    break;
430285612Sdelphij	}
431285612Sdelphij	return;
432285612Sdelphij}
433285612Sdelphij#endif
434285612Sdelphij
435285612Sdelphij/*
436182007Sroberto * local_clock - the NTP logical clock loop filter.
437132451Sroberto *
438182007Sroberto * Return codes:
439182007Sroberto * -1	update ignored: exceeds panic threshold
440182007Sroberto * 0	update ignored: popcorn or exceeds step threshold
441182007Sroberto * 1	clock was slewed
442182007Sroberto * 2	clock was stepped
443182007Sroberto *
444132451Sroberto * LOCKCLOCK: The only thing this routine does is set the
445285612Sdelphij * sys_rootdisp variable equal to the peer dispersion.
44654359Sroberto */
44754359Srobertoint
44854359Srobertolocal_clock(
449182007Sroberto	struct	peer *peer,	/* synch source peer structure */
450182007Sroberto	double	fp_offset	/* clock offset (s) */
45154359Sroberto	)
45254359Sroberto{
453182007Sroberto	int	rval;		/* return code */
454285612Sdelphij	int	osys_poll;	/* old system poll */
455285612Sdelphij	int	ntp_adj_ret;	/* returned by ntp_adjtime */
456285612Sdelphij	double	mu;		/* interval since last update */
457285612Sdelphij	double	clock_frequency; /* clock frequency */
458182007Sroberto	double	dtemp, etemp;	/* double temps */
459285612Sdelphij	char	tbuf[80];	/* report buffer */
46054359Sroberto
461293650Sglebius	(void)ntp_adj_ret; /* not always used below... */
46282498Sroberto	/*
463182007Sroberto	 * If the loop is opened or the NIST LOCKCLOCK is in use,
464182007Sroberto	 * monitor and record the offsets anyway in order to determine
465182007Sroberto	 * the open-loop response and then go home.
46682498Sroberto	 */
467293650Sglebius#ifndef LOCKCLOCK
468293650Sglebius	if (!ntp_enable)
469293650Sglebius#endif /* not LOCKCLOCK */
470285612Sdelphij	{
471182007Sroberto		record_loop_stats(fp_offset, drift_comp, clock_jitter,
47282498Sroberto		    clock_stability, sys_poll);
47382498Sroberto		return (0);
47482498Sroberto	}
47554359Sroberto
476285612Sdelphij#ifndef LOCKCLOCK
47754359Sroberto	/*
47882498Sroberto	 * If the clock is way off, panic is declared. The clock_panic
47982498Sroberto	 * defaults to 1000 s; if set to zero, the panic will never
48082498Sroberto	 * occur. The allow_panic defaults to FALSE, so the first panic
48182498Sroberto	 * will exit. It can be set TRUE by a command line option, in
48282498Sroberto	 * which case the clock will be set anyway and time marches on.
483182007Sroberto	 * But, allow_panic will be set FALSE when the update is less
484182007Sroberto	 * than the step threshold; so, subsequent panics will exit.
48554359Sroberto	 */
48682498Sroberto	if (fabs(fp_offset) > clock_panic && clock_panic > 0 &&
48782498Sroberto	    !allow_panic) {
488285612Sdelphij		snprintf(tbuf, sizeof(tbuf),
489285612Sdelphij		    "%+.0f s; set clock manually within %.0f s.",
49082498Sroberto		    fp_offset, clock_panic);
491285612Sdelphij		report_event(EVNT_SYSFAULT, NULL, tbuf);
49254359Sroberto		return (-1);
49354359Sroberto	}
49482498Sroberto
495293650Sglebius	allow_panic = FALSE;
496293650Sglebius
49754359Sroberto	/*
498285612Sdelphij	 * This section simulates ntpdate. If the offset exceeds the
499285612Sdelphij	 * step threshold (128 ms), step the clock to that time and
500285612Sdelphij	 * exit. Otherwise, slew the clock to that time and exit. Note
501285612Sdelphij	 * that the slew will persist and eventually complete beyond the
502285612Sdelphij	 * life of this program. Note that while ntpdate is active, the
503285612Sdelphij	 * terminal does not detach, so the termination message prints
504285612Sdelphij	 * directly to the terminal.
50582498Sroberto	 */
50682498Sroberto	if (mode_ntpdate) {
507285612Sdelphij		if (  ( fp_offset > clock_max_fwd  && clock_max_fwd  > 0)
508285612Sdelphij		   || (-fp_offset > clock_max_back && clock_max_back > 0)) {
50982498Sroberto			step_systime(fp_offset);
510285612Sdelphij			msyslog(LOG_NOTICE, "ntpd: time set %+.6f s",
511285612Sdelphij			    fp_offset);
512132451Sroberto			printf("ntpd: time set %+.6fs\n", fp_offset);
51382498Sroberto		} else {
51482498Sroberto			adj_systime(fp_offset);
515285612Sdelphij			msyslog(LOG_NOTICE, "ntpd: time slew %+.6f s",
51682498Sroberto			    fp_offset);
517132451Sroberto			printf("ntpd: time slew %+.6fs\n", fp_offset);
51882498Sroberto		}
519182007Sroberto		record_loop_stats(fp_offset, drift_comp, clock_jitter,
52082498Sroberto		    clock_stability, sys_poll);
52182498Sroberto		exit (0);
52282498Sroberto	}
52382498Sroberto
52482498Sroberto	/*
52582498Sroberto	 * The huff-n'-puff filter finds the lowest delay in the recent
52682498Sroberto	 * interval. This is used to correct the offset by one-half the
52782498Sroberto	 * difference between the sample delay and minimum delay. This
52882498Sroberto	 * is most effective if the delays are highly assymetric and
52982498Sroberto	 * clockhopping is avoided and the clock frequency wander is
53082498Sroberto	 * relatively small.
53182498Sroberto	 */
532285612Sdelphij	if (sys_huffpuff != NULL) {
53382498Sroberto		if (peer->delay < sys_huffpuff[sys_huffptr])
53482498Sroberto			sys_huffpuff[sys_huffptr] = peer->delay;
53582498Sroberto		if (peer->delay < sys_mindly)
53682498Sroberto			sys_mindly = peer->delay;
53782498Sroberto		if (fp_offset > 0)
53882498Sroberto			dtemp = -(peer->delay - sys_mindly) / 2;
53982498Sroberto		else
54082498Sroberto			dtemp = (peer->delay - sys_mindly) / 2;
54182498Sroberto		fp_offset += dtemp;
542293650Sglebius		DPRINTF(1, ("local_clock: size %d mindly %.6f huffpuff %.6f\n",
543293650Sglebius			    sys_hufflen, sys_mindly, dtemp));
54482498Sroberto	}
54582498Sroberto
54682498Sroberto	/*
547285612Sdelphij	 * Clock state machine transition function which defines how the
548285612Sdelphij	 * system reacts to large phase and frequency excursion. There
549285612Sdelphij	 * are two main regimes: when the offset exceeds the step
550285612Sdelphij	 * threshold (128 ms) and when it does not. Under certain
551285612Sdelphij	 * conditions updates are suspended until the stepout theshold
552285612Sdelphij	 * (900 s) is exceeded. See the documentation on how these
553285612Sdelphij	 * thresholds interact with commands and command line options.
554182007Sroberto	 *
555285612Sdelphij	 * Note the kernel is disabled if step is disabled or greater
556285612Sdelphij	 * than 0.5 s or in ntpdate mode.
55754359Sroberto	 */
558285612Sdelphij	osys_poll = sys_poll;
559285612Sdelphij	if (sys_poll < peer->minpoll)
560285612Sdelphij		sys_poll = peer->minpoll;
561285612Sdelphij	if (sys_poll > peer->maxpoll)
562285612Sdelphij		sys_poll = peer->maxpoll;
563285612Sdelphij	mu = current_time - clock_epoch;
564285612Sdelphij	clock_frequency = drift_comp;
565182007Sroberto	rval = 1;
566285612Sdelphij	if (  ( fp_offset > clock_max_fwd  && clock_max_fwd  > 0)
567285612Sdelphij	   || (-fp_offset > clock_max_back && clock_max_back > 0)
568285612Sdelphij	   || force_step_once ) {
569285612Sdelphij		if (force_step_once) {
570285612Sdelphij			force_step_once = FALSE;  /* we want this only once after startup */
571285612Sdelphij			msyslog(LOG_NOTICE, "Doing intital time step" );
572285612Sdelphij		}
573285612Sdelphij
57454359Sroberto		switch (state) {
57554359Sroberto
57654359Sroberto		/*
577289997Sglebius		 * In SYNC state we ignore the first outlier and switch
578285612Sdelphij		 * to SPIK state.
57954359Sroberto		 */
580285612Sdelphij		case EVNT_SYNC:
581285612Sdelphij			snprintf(tbuf, sizeof(tbuf), "%+.6f s",
582285612Sdelphij			    fp_offset);
583285612Sdelphij			report_event(EVNT_SPIK, NULL, tbuf);
584285612Sdelphij			state = EVNT_SPIK;
58554359Sroberto			return (0);
58654359Sroberto
58754359Sroberto		/*
588289997Sglebius		 * In FREQ state we ignore outliers and inlyers. At the
589289997Sglebius		 * first outlier after the stepout threshold, compute
590285612Sdelphij		 * the apparent frequency correction and step the phase.
59154359Sroberto		 */
592285612Sdelphij		case EVNT_FREQ:
59382498Sroberto			if (mu < clock_minstep)
59454359Sroberto				return (0);
595182007Sroberto
596285612Sdelphij			clock_frequency = direct_freq(fp_offset);
597182007Sroberto
598285612Sdelphij			/* fall through to EVNT_SPIK */
59954359Sroberto
60054359Sroberto		/*
601289997Sglebius		 * In SPIK state we ignore succeeding outliers until
602182007Sroberto		 * either an inlyer is found or the stepout threshold is
603182007Sroberto		 * exceeded.
60454359Sroberto		 */
605285612Sdelphij		case EVNT_SPIK:
606182007Sroberto			if (mu < clock_minstep)
607182007Sroberto				return (0);
608182007Sroberto
60954359Sroberto			/* fall through to default */
61054359Sroberto
61154359Sroberto		/*
612285612Sdelphij		 * We get here by default in NSET and FSET states and
613285612Sdelphij		 * from above in FREQ or SPIK states.
614182007Sroberto		 *
615285612Sdelphij		 * In NSET state an initial frequency correction is not
616285612Sdelphij		 * available, usually because the frequency file has not
617285612Sdelphij		 * yet been written. Since the time is outside the step
618285612Sdelphij		 * threshold, the clock is stepped. The frequency will
619285612Sdelphij		 * be set directly following the stepout interval.
620182007Sroberto		 *
621285612Sdelphij		 * In FSET state the initial frequency has been set from
622285612Sdelphij		 * the frequency file. Since the time is outside the
623285612Sdelphij		 * step threshold, the clock is stepped immediately,
624182007Sroberto		 * rather than after the stepout interval. Guys get
625285612Sdelphij		 * nervous if it takes 15 minutes to set the clock for
626182007Sroberto		 * the first time.
627182007Sroberto		 *
628285612Sdelphij		 * In FREQ and SPIK states the stepout threshold has
629182007Sroberto		 * expired and the phase is still above the step
630182007Sroberto		 * threshold. Note that a single spike greater than the
631285612Sdelphij		 * step threshold is always suppressed, even with a
632285612Sdelphij		 * long time constant.
633285612Sdelphij		 */
63454359Sroberto		default:
635285612Sdelphij			snprintf(tbuf, sizeof(tbuf), "%+.6f s",
636285612Sdelphij			    fp_offset);
637285612Sdelphij			report_event(EVNT_CLOCKRESET, NULL, tbuf);
638132451Sroberto			step_systime(fp_offset);
639132451Sroberto			reinit_timer();
640182007Sroberto			tc_counter = 0;
641182007Sroberto			clock_jitter = LOGTOD(sys_precision);
642182007Sroberto			rval = 2;
643285612Sdelphij			if (state == EVNT_NSET) {
644285612Sdelphij				rstclock(EVNT_FREQ, 0);
645182007Sroberto				return (rval);
646182007Sroberto			}
64754359Sroberto			break;
64854359Sroberto		}
649285612Sdelphij		rstclock(EVNT_SYNC, 0);
65054359Sroberto	} else {
651182007Sroberto		/*
652182007Sroberto		 * The offset is less than the step threshold. Calculate
653182007Sroberto		 * the jitter as the exponentially weighted offset
654182007Sroberto		 * differences.
655285612Sdelphij		 */
656182007Sroberto		etemp = SQUARE(clock_jitter);
657182007Sroberto		dtemp = SQUARE(max(fabs(fp_offset - last_offset),
658182007Sroberto		    LOGTOD(sys_precision)));
659182007Sroberto		clock_jitter = SQRT(etemp + (dtemp - etemp) /
660182007Sroberto		    CLOCK_AVG);
66154359Sroberto		switch (state) {
66254359Sroberto
66354359Sroberto		/*
664285612Sdelphij		 * In NSET state this is the first update received and
665182007Sroberto		 * the frequency has not been initialized. Adjust the
666182007Sroberto		 * phase, but do not adjust the frequency until after
667182007Sroberto		 * the stepout threshold.
668182007Sroberto		 */
669285612Sdelphij		case EVNT_NSET:
670285612Sdelphij			adj_systime(fp_offset);
671285612Sdelphij			rstclock(EVNT_FREQ, fp_offset);
672182007Sroberto			break;
673182007Sroberto
674182007Sroberto		/*
675285612Sdelphij		 * In FREQ state ignore updates until the stepout
676285612Sdelphij		 * threshold. After that, compute the new frequency, but
677285612Sdelphij		 * do not adjust the frequency until the holdoff counter
678285612Sdelphij		 * decrements to zero.
67954359Sroberto		 */
680285612Sdelphij		case EVNT_FREQ:
68182498Sroberto			if (mu < clock_minstep)
68254359Sroberto				return (0);
683182007Sroberto
684285612Sdelphij			clock_frequency = direct_freq(fp_offset);
685285612Sdelphij			/* fall through */
68654359Sroberto
68754359Sroberto		/*
688285612Sdelphij		 * We get here by default in FSET, SPIK and SYNC states.
689285612Sdelphij		 * Here compute the frequency update due to PLL and FLL
690285612Sdelphij		 * contributions. Note, we avoid frequency discipline at
691285612Sdelphij		 * startup until the initial transient has subsided.
69254359Sroberto		 */
69354359Sroberto		default:
694285612Sdelphij			if (freq_cnt == 0) {
69554359Sroberto
696285612Sdelphij				/*
697285612Sdelphij				 * The FLL and PLL frequency gain constants
698285612Sdelphij				 * depend on the time constant and Allan
699285612Sdelphij				 * intercept. The PLL is always used, but
700285612Sdelphij				 * becomes ineffective above the Allan intercept
701285612Sdelphij				 * where the FLL becomes effective.
702285612Sdelphij				 */
703285612Sdelphij				if (sys_poll >= allan_xpt)
704309008Sdelphij					clock_frequency +=
705309008Sdelphij					      (fp_offset - clock_offset)
706309008Sdelphij					    / ( max(ULOGTOD(sys_poll), mu)
707309008Sdelphij					       * CLOCK_FLL);
708285612Sdelphij
709285612Sdelphij				/*
710285612Sdelphij				 * The PLL frequency gain (numerator) depends on
711285612Sdelphij				 * the minimum of the update interval and Allan
712285612Sdelphij				 * intercept. This reduces the PLL gain when the
713285612Sdelphij				 * FLL becomes effective.
714285612Sdelphij				 */
715285612Sdelphij				etemp = min(ULOGTOD(allan_xpt), mu);
716285612Sdelphij				dtemp = 4 * CLOCK_PLL * ULOGTOD(sys_poll);
717309008Sdelphij				clock_frequency +=
718309008Sdelphij				    fp_offset * etemp / (dtemp * dtemp);
719132451Sroberto			}
720285612Sdelphij			rstclock(EVNT_SYNC, fp_offset);
721285612Sdelphij			if (fabs(fp_offset) < CLOCK_FLOOR)
722285612Sdelphij				freq_cnt = 0;
72354359Sroberto			break;
72454359Sroberto		}
72554359Sroberto	}
72654359Sroberto
727132451Sroberto#ifdef KERNEL_PLL
72854359Sroberto	/*
72954359Sroberto	 * This code segment works when clock adjustments are made using
73054359Sroberto	 * precision time kernel support and the ntp_adjtime() system
73154359Sroberto	 * call. This support is available in Solaris 2.6 and later,
73254359Sroberto	 * Digital Unix 4.0 and later, FreeBSD, Linux and specially
73354359Sroberto	 * modified kernels for HP-UX 9 and Ultrix 4. In the case of the
73454359Sroberto	 * DECstation 5000/240 and Alpha AXP, additional kernel
73554359Sroberto	 * modifications provide a true microsecond clock and nanosecond
73654359Sroberto	 * clock, respectively.
737182007Sroberto	 *
738182007Sroberto	 * Important note: The kernel discipline is used only if the
739182007Sroberto	 * step threshold is less than 0.5 s, as anything higher can
740182007Sroberto	 * lead to overflow problems. This might occur if some misguided
741182007Sroberto	 * lad set the step threshold to something ridiculous.
74254359Sroberto	 */
743285612Sdelphij	if (pll_control && kern_enable && freq_cnt == 0) {
74454359Sroberto
74554359Sroberto		/*
74654359Sroberto		 * We initialize the structure for the ntp_adjtime()
74754359Sroberto		 * system call. We have to convert everything to
74854359Sroberto		 * microseconds or nanoseconds first. Do not update the
74954359Sroberto		 * system variables if the ext_enable flag is set. In
75054359Sroberto		 * this case, the external clock driver will update the
75154359Sroberto		 * variables, which will be read later by the local
75254359Sroberto		 * clock driver. Afterwards, remember the time and
75354359Sroberto		 * frequency offsets for jitter and stability values and
754182007Sroberto		 * to update the frequency file.
75554359Sroberto		 */
756285612Sdelphij		ZERO(ntv);
75754359Sroberto		if (ext_enable) {
75854359Sroberto			ntv.modes = MOD_STATUS;
75954359Sroberto		} else {
760182007Sroberto#ifdef STA_NANO
761182007Sroberto			ntv.modes = MOD_BITS | MOD_NANO;
762182007Sroberto#else /* STA_NANO */
76354359Sroberto			ntv.modes = MOD_BITS;
764182007Sroberto#endif /* STA_NANO */
76554359Sroberto			if (clock_offset < 0)
76654359Sroberto				dtemp = -.5;
76754359Sroberto			else
76854359Sroberto				dtemp = .5;
769182007Sroberto#ifdef STA_NANO
770182007Sroberto			ntv.offset = (int32)(clock_offset * 1e9 +
771182007Sroberto			    dtemp);
772182007Sroberto			ntv.constant = sys_poll;
773182007Sroberto#else /* STA_NANO */
774182007Sroberto			ntv.offset = (int32)(clock_offset * 1e6 +
775182007Sroberto			    dtemp);
776182007Sroberto			ntv.constant = sys_poll - 4;
777182007Sroberto#endif /* STA_NANO */
778285612Sdelphij			if (ntv.constant < 0)
779285612Sdelphij				ntv.constant = 0;
780182007Sroberto
781182007Sroberto			ntv.esterror = (u_int32)(clock_jitter * 1e6);
78254359Sroberto			ntv.maxerror = (u_int32)((sys_rootdelay / 2 +
783285612Sdelphij			    sys_rootdisp) * 1e6);
78454359Sroberto			ntv.status = STA_PLL;
78554359Sroberto
78654359Sroberto			/*
787285612Sdelphij			 * Enable/disable the PPS if requested.
78854359Sroberto			 */
789285612Sdelphij			if (hardpps_enable) {
790285612Sdelphij				ntv.status |= (STA_PPSTIME | STA_PPSFREQ);
791285612Sdelphij				if (!(pll_status & STA_PPSTIME))
792285612Sdelphij					sync_status("PPS enabled",
793285612Sdelphij						pll_status,
794285612Sdelphij						ntv.status);
79582498Sroberto			} else {
796285612Sdelphij				ntv.status &= ~(STA_PPSTIME | STA_PPSFREQ);
797285612Sdelphij				if (pll_status & STA_PPSTIME)
798285612Sdelphij					sync_status("PPS disabled",
799285612Sdelphij						pll_status,
800285612Sdelphij						ntv.status);
80182498Sroberto			}
802285612Sdelphij			if (sys_leap == LEAP_ADDSECOND)
803285612Sdelphij				ntv.status |= STA_INS;
804285612Sdelphij			else if (sys_leap == LEAP_DELSECOND)
805285612Sdelphij				ntv.status |= STA_DEL;
80654359Sroberto		}
80754359Sroberto
80854359Sroberto		/*
80982498Sroberto		 * Pass the stuff to the kernel. If it squeals, turn off
810285612Sdelphij		 * the pps. In any case, fetch the kernel offset,
811285612Sdelphij		 * frequency and jitter.
81254359Sroberto		 */
813285612Sdelphij		ntp_adj_ret = ntp_adjtime(&ntv);
814285612Sdelphij		/*
815285612Sdelphij		 * A squeal is a return status < 0, or a state change.
816285612Sdelphij		 */
817285612Sdelphij		if ((0 > ntp_adj_ret) || (ntp_adj_ret != kernel_status)) {
818285612Sdelphij			kernel_status = ntp_adj_ret;
819285612Sdelphij			ntp_adjtime_error_handler(__func__, &ntv, ntp_adj_ret, errno, hardpps_enable, 0, __LINE__ - 1);
82054359Sroberto		}
82154359Sroberto		pll_status = ntv.status;
822182007Sroberto#ifdef STA_NANO
823182007Sroberto		clock_offset = ntv.offset / 1e9;
824182007Sroberto#else /* STA_NANO */
825182007Sroberto		clock_offset = ntv.offset / 1e6;
826182007Sroberto#endif /* STA_NANO */
827285612Sdelphij		clock_frequency = FREQTOD(ntv.freq);
82854359Sroberto
82954359Sroberto		/*
83082498Sroberto		 * If the kernel PPS is lit, monitor its performance.
83154359Sroberto		 */
83254359Sroberto		if (ntv.status & STA_PPSTIME) {
833182007Sroberto#ifdef STA_NANO
834182007Sroberto			clock_jitter = ntv.jitter / 1e9;
835182007Sroberto#else /* STA_NANO */
836182007Sroberto			clock_jitter = ntv.jitter / 1e6;
837182007Sroberto#endif /* STA_NANO */
83854359Sroberto		}
839285612Sdelphij
840285612Sdelphij#if defined(STA_NANO) && NTP_API == 4
841182007Sroberto		/*
842285612Sdelphij		 * If the TAI changes, update the kernel TAI.
843182007Sroberto		 */
844285612Sdelphij		if (loop_tai != sys_tai) {
845285612Sdelphij			loop_tai = sys_tai;
846285612Sdelphij			ntv.modes = MOD_TAI;
847285612Sdelphij			ntv.constant = sys_tai;
848285612Sdelphij			if ((ntp_adj_ret = ntp_adjtime(&ntv)) != 0) {
849285612Sdelphij			    ntp_adjtime_error_handler(__func__, &ntv, ntp_adj_ret, errno, 0, 1, __LINE__ - 1);
850285612Sdelphij			}
851285612Sdelphij		}
852285612Sdelphij#endif /* STA_NANO */
85354359Sroberto	}
85454359Sroberto#endif /* KERNEL_PLL */
855182007Sroberto
85654359Sroberto	/*
857182007Sroberto	 * Clamp the frequency within the tolerance range and calculate
858285612Sdelphij	 * the frequency difference since the last update.
85954359Sroberto	 */
860182007Sroberto	if (fabs(clock_frequency) > NTP_MAXFREQ)
861285612Sdelphij		msyslog(LOG_NOTICE,
862182007Sroberto		    "frequency error %.0f PPM exceeds tolerance %.0f PPM",
863182007Sroberto		    clock_frequency * 1e6, NTP_MAXFREQ * 1e6);
864182007Sroberto	dtemp = SQUARE(clock_frequency - drift_comp);
865182007Sroberto	if (clock_frequency > NTP_MAXFREQ)
86682498Sroberto		drift_comp = NTP_MAXFREQ;
867182007Sroberto	else if (clock_frequency < -NTP_MAXFREQ)
86882498Sroberto		drift_comp = -NTP_MAXFREQ;
869132451Sroberto	else
870182007Sroberto		drift_comp = clock_frequency;
87154359Sroberto
872182007Sroberto	/*
873285612Sdelphij	 * Calculate the wander as the exponentially weighted RMS
874285612Sdelphij	 * frequency differences. Record the change for the frequency
875285612Sdelphij	 * file update.
876182007Sroberto	 */
877132451Sroberto	etemp = SQUARE(clock_stability);
878132451Sroberto	clock_stability = SQRT(etemp + (dtemp - etemp) / CLOCK_AVG);
879132451Sroberto
88054359Sroberto	/*
881285612Sdelphij	 * Here we adjust the time constant by comparing the current
882182007Sroberto	 * offset with the clock jitter. If the offset is less than the
883182007Sroberto	 * clock jitter times a constant, then the averaging interval is
884182007Sroberto	 * increased, otherwise it is decreased. A bit of hysteresis
885285612Sdelphij	 * helps calm the dance. Works best using burst mode. Don't
886285612Sdelphij	 * fiddle with the poll during the startup clamp period.
88754359Sroberto	 */
888285612Sdelphij	if (freq_cnt > 0) {
889285612Sdelphij		tc_counter = 0;
890285612Sdelphij	} else if (fabs(clock_offset) < CLOCK_PGATE * clock_jitter) {
891182007Sroberto		tc_counter += sys_poll;
892182007Sroberto		if (tc_counter > CLOCK_LIMIT) {
893182007Sroberto			tc_counter = CLOCK_LIMIT;
894182007Sroberto			if (sys_poll < peer->maxpoll) {
895182007Sroberto				tc_counter = 0;
896182007Sroberto				sys_poll++;
89754359Sroberto			}
898182007Sroberto		}
899182007Sroberto	} else {
900182007Sroberto		tc_counter -= sys_poll << 1;
901182007Sroberto		if (tc_counter < -CLOCK_LIMIT) {
902182007Sroberto			tc_counter = -CLOCK_LIMIT;
903182007Sroberto			if (sys_poll > peer->minpoll) {
904182007Sroberto				tc_counter = 0;
905182007Sroberto				sys_poll--;
90654359Sroberto			}
90754359Sroberto		}
90854359Sroberto	}
90954359Sroberto
91054359Sroberto	/*
911285612Sdelphij	 * If the time constant has changed, update the poll variables.
912285612Sdelphij	 */
913285612Sdelphij	if (osys_poll != sys_poll)
914285612Sdelphij		poll_update(peer, sys_poll);
915285612Sdelphij
916285612Sdelphij	/*
917182007Sroberto	 * Yibbidy, yibbbidy, yibbidy; that'h all folks.
91854359Sroberto	 */
919182007Sroberto	record_loop_stats(clock_offset, drift_comp, clock_jitter,
92082498Sroberto	    clock_stability, sys_poll);
921293650Sglebius	DPRINTF(1, ("local_clock: offset %.9f jit %.9f freq %.3f stab %.3f poll %d\n",
922285612Sdelphij		    clock_offset, clock_jitter, drift_comp * 1e6,
923293650Sglebius		    clock_stability * 1e6, sys_poll));
924182007Sroberto	return (rval);
925293650Sglebius#endif /* not LOCKCLOCK */
92654359Sroberto}
92754359Sroberto
92854359Sroberto
92954359Sroberto/*
93054359Sroberto * adj_host_clock - Called once every second to update the local clock.
931132451Sroberto *
932132451Sroberto * LOCKCLOCK: The only thing this routine does is increment the
933285612Sdelphij * sys_rootdisp variable.
93454359Sroberto */
93554359Srobertovoid
93654359Srobertoadj_host_clock(
93754359Sroberto	void
93854359Sroberto	)
93954359Sroberto{
940285612Sdelphij	double	offset_adj;
941285612Sdelphij	double	freq_adj;
94254359Sroberto
94354359Sroberto	/*
94454359Sroberto	 * Update the dispersion since the last update. In contrast to
94554359Sroberto	 * NTPv3, NTPv4 does not declare unsynchronized after one day,
94654359Sroberto	 * since the dispersion check serves this function. Also,
94754359Sroberto	 * since the poll interval can exceed one day, the old test
948285612Sdelphij	 * would be counterproductive. During the startup clamp period, the
949285612Sdelphij	 * time constant is clamped at 2.
95054359Sroberto	 */
951285612Sdelphij	sys_rootdisp += clock_phi;
952132451Sroberto#ifndef LOCKCLOCK
953285612Sdelphij	if (!ntp_enable || mode_ntpdate)
954285612Sdelphij		return;
95554359Sroberto	/*
956285612Sdelphij	 * Determine the phase adjustment. The gain factor (denominator)
957285612Sdelphij	 * increases with poll interval, so is dominated by the FLL
958285612Sdelphij	 * above the Allan intercept. Note the reduced time constant at
959285612Sdelphij	 * startup.
960182007Sroberto	 */
961285612Sdelphij	if (state != EVNT_SYNC) {
962285612Sdelphij		offset_adj = 0.;
963285612Sdelphij	} else if (freq_cnt > 0) {
964285612Sdelphij		offset_adj = clock_offset / (CLOCK_PLL * ULOGTOD(1));
965285612Sdelphij		freq_cnt--;
966285612Sdelphij#ifdef KERNEL_PLL
967285612Sdelphij	} else if (pll_control && kern_enable) {
968285612Sdelphij		offset_adj = 0.;
969285612Sdelphij#endif /* KERNEL_PLL */
970285612Sdelphij	} else {
971285612Sdelphij		offset_adj = clock_offset / (CLOCK_PLL * ULOGTOD(sys_poll));
972285612Sdelphij	}
973182007Sroberto
974182007Sroberto	/*
975285612Sdelphij	 * If the kernel discipline is enabled the frequency correction
976285612Sdelphij	 * drift_comp has already been engaged via ntp_adjtime() in
977285612Sdelphij	 * set_freq().  Otherwise it is a component of the adj_systime()
978285612Sdelphij	 * offset.
97954359Sroberto	 */
980285612Sdelphij#ifdef KERNEL_PLL
981285612Sdelphij	if (pll_control && kern_enable)
982285612Sdelphij		freq_adj = 0.;
983285612Sdelphij	else
984285612Sdelphij#endif /* KERNEL_PLL */
985285612Sdelphij		freq_adj = drift_comp;
98654359Sroberto
987285612Sdelphij	/* Bound absolute value of total adjustment to NTP_MAXFREQ. */
988285612Sdelphij	if (offset_adj + freq_adj > NTP_MAXFREQ)
989285612Sdelphij		offset_adj = NTP_MAXFREQ - freq_adj;
990285612Sdelphij	else if (offset_adj + freq_adj < -NTP_MAXFREQ)
991285612Sdelphij		offset_adj = -NTP_MAXFREQ - freq_adj;
992285612Sdelphij
993285612Sdelphij	clock_offset -= offset_adj;
99454359Sroberto	/*
995285612Sdelphij	 * Windows port adj_systime() must be called each second,
996285612Sdelphij	 * even if the argument is zero, to ease emulation of
997285612Sdelphij	 * adjtime() using Windows' slew API which controls the rate
998285612Sdelphij	 * but does not automatically stop slewing when an offset
999285612Sdelphij	 * has decayed to zero.
100054359Sroberto	 */
1001293650Sglebius	DEBUG_INSIST(enable_panic_check == TRUE);
1002293650Sglebius	enable_panic_check = FALSE;
1003285612Sdelphij	adj_systime(offset_adj + freq_adj);
1004293650Sglebius	enable_panic_check = TRUE;
1005132451Sroberto#endif /* LOCKCLOCK */
100654359Sroberto}
100754359Sroberto
100854359Sroberto
100954359Sroberto/*
1010285612Sdelphij * Clock state machine. Enter new state and set state variables.
101154359Sroberto */
101254359Srobertostatic void
101354359Srobertorstclock(
1014182007Sroberto	int	trans,		/* new state */
1015182007Sroberto	double	offset		/* new offset */
101654359Sroberto	)
101754359Sroberto{
1018293650Sglebius	DPRINTF(2, ("rstclock: mu %lu state %d poll %d count %d\n",
1019285612Sdelphij		    current_time - clock_epoch, trans, sys_poll,
1020293650Sglebius		    tc_counter));
1021285612Sdelphij	if (trans != state && trans != EVNT_FSET)
1022285612Sdelphij		report_event(trans, NULL, NULL);
1023182007Sroberto	state = trans;
1024182007Sroberto	last_offset = clock_offset = offset;
1025285612Sdelphij	clock_epoch = current_time;
102682498Sroberto}
102754359Sroberto
102854359Sroberto
102982498Sroberto/*
1030285612Sdelphij * calc_freq - calculate frequency directly
1031285612Sdelphij *
1032285612Sdelphij * This is very carefully done. When the offset is first computed at the
1033285612Sdelphij * first update, a residual frequency component results. Subsequently,
1034285612Sdelphij * updates are suppresed until the end of the measurement interval while
1035285612Sdelphij * the offset is amortized. At the end of the interval the frequency is
1036285612Sdelphij * calculated from the current offset, residual offset, length of the
1037285612Sdelphij * interval and residual frequency component. At the same time the
1038285612Sdelphij * frequenchy file is armed for update at the next hourly stats.
1039285612Sdelphij */
1040285612Sdelphijstatic double
1041285612Sdelphijdirect_freq(
1042285612Sdelphij	double	fp_offset
1043285612Sdelphij	)
1044285612Sdelphij{
1045285612Sdelphij	set_freq(fp_offset / (current_time - clock_epoch));
1046285612Sdelphij
1047285612Sdelphij	return drift_comp;
1048285612Sdelphij}
1049285612Sdelphij
1050285612Sdelphij
1051285612Sdelphij/*
1052285612Sdelphij * set_freq - set clock frequency correction
1053285612Sdelphij *
1054285612Sdelphij * Used to step the frequency correction at startup, possibly again once
1055285612Sdelphij * the frequency is measured (that is, transitioning from EVNT_NSET to
1056285612Sdelphij * EVNT_FSET), and finally to switch between daemon and kernel loop
1057285612Sdelphij * discipline at runtime.
1058285612Sdelphij *
1059285612Sdelphij * When the kernel loop discipline is available but the daemon loop is
1060285612Sdelphij * in use, the kernel frequency correction is disabled (set to 0) to
1061285612Sdelphij * ensure drift_comp is applied by only one of the loops.
1062285612Sdelphij */
1063285612Sdelphijstatic void
1064285612Sdelphijset_freq(
1065285612Sdelphij	double	freq		/* frequency update */
1066285612Sdelphij	)
1067285612Sdelphij{
1068285612Sdelphij	const char *	loop_desc;
1069285612Sdelphij	int ntp_adj_ret;
1070285612Sdelphij
1071293650Sglebius	(void)ntp_adj_ret; /* not always used below... */
1072285612Sdelphij	drift_comp = freq;
1073285612Sdelphij	loop_desc = "ntpd";
1074285612Sdelphij#ifdef KERNEL_PLL
1075285612Sdelphij	if (pll_control) {
1076285612Sdelphij		ZERO(ntv);
1077285612Sdelphij		ntv.modes = MOD_FREQUENCY;
1078285612Sdelphij		if (kern_enable) {
1079285612Sdelphij			loop_desc = "kernel";
1080285612Sdelphij			ntv.freq = DTOFREQ(drift_comp);
1081285612Sdelphij		}
1082285612Sdelphij		if ((ntp_adj_ret = ntp_adjtime(&ntv)) != 0) {
1083285612Sdelphij		    ntp_adjtime_error_handler(__func__, &ntv, ntp_adj_ret, errno, 0, 0, __LINE__ - 1);
1084285612Sdelphij		}
1085285612Sdelphij	}
1086285612Sdelphij#endif /* KERNEL_PLL */
1087285612Sdelphij	mprintf_event(EVNT_FSET, NULL, "%s %.3f PPM", loop_desc,
1088285612Sdelphij	    drift_comp * 1e6);
1089285612Sdelphij}
1090285612Sdelphij
1091285612Sdelphij
1092285612Sdelphij#ifdef KERNEL_PLL
1093285612Sdelphijstatic void
1094285612Sdelphijstart_kern_loop(void)
1095285612Sdelphij{
1096285612Sdelphij	static int atexit_done;
1097285612Sdelphij	int ntp_adj_ret;
1098285612Sdelphij
1099285612Sdelphij	pll_control = TRUE;
1100285612Sdelphij	ZERO(ntv);
1101285612Sdelphij	ntv.modes = MOD_BITS;
1102338531Sdelphij	ntv.status = STA_PLL | STA_UNSYNC;
1103338531Sdelphij	ntv.maxerror = MAXDISPERSE * 1.0e6;
1104338531Sdelphij	ntv.esterror = MAXDISPERSE * 1.0e6;
1105338531Sdelphij	ntv.constant = sys_poll;
1106338531Sdelphij	/*             ^^^^^^^^ why is it that here constant is
1107338531Sdelphij	 * unconditionally set to sys_poll, whereas elsewhere is is
1108338531Sdelphij	 * modified depending on nanosecond vs. microsecond kernel?
1109338531Sdelphij	 */
1110285612Sdelphij#ifdef SIGSYS
1111285612Sdelphij	/*
1112285612Sdelphij	 * Use sigsetjmp() to save state and then call ntp_adjtime(); if
1113285612Sdelphij	 * it fails, then pll_trap() will set pll_control FALSE before
1114285612Sdelphij	 * returning control using siglogjmp().
1115285612Sdelphij	 */
1116285612Sdelphij	newsigsys.sa_handler = pll_trap;
1117285612Sdelphij	newsigsys.sa_flags = 0;
1118285612Sdelphij	if (sigaction(SIGSYS, &newsigsys, &sigsys)) {
1119285612Sdelphij		msyslog(LOG_ERR, "sigaction() trap SIGSYS: %m");
1120285612Sdelphij		pll_control = FALSE;
1121285612Sdelphij	} else {
1122285612Sdelphij		if (sigsetjmp(env, 1) == 0) {
1123285612Sdelphij			if ((ntp_adj_ret = ntp_adjtime(&ntv)) != 0) {
1124285612Sdelphij			    ntp_adjtime_error_handler(__func__, &ntv, ntp_adj_ret, errno, 0, 0, __LINE__ - 1);
1125285612Sdelphij			}
1126285612Sdelphij		}
1127285612Sdelphij		if (sigaction(SIGSYS, &sigsys, NULL)) {
1128285612Sdelphij			msyslog(LOG_ERR,
1129285612Sdelphij			    "sigaction() restore SIGSYS: %m");
1130285612Sdelphij			pll_control = FALSE;
1131285612Sdelphij		}
1132285612Sdelphij	}
1133285612Sdelphij#else /* SIGSYS */
1134285612Sdelphij	if ((ntp_adj_ret = ntp_adjtime(&ntv)) != 0) {
1135285612Sdelphij	    ntp_adjtime_error_handler(__func__, &ntv, ntp_adj_ret, errno, 0, 0, __LINE__ - 1);
1136285612Sdelphij	}
1137285612Sdelphij#endif /* SIGSYS */
1138285612Sdelphij
1139285612Sdelphij	/*
1140285612Sdelphij	 * Save the result status and light up an external clock
1141285612Sdelphij	 * if available.
1142285612Sdelphij	 */
1143285612Sdelphij	pll_status = ntv.status;
1144285612Sdelphij	if (pll_control) {
1145285612Sdelphij		if (!atexit_done) {
1146285612Sdelphij			atexit_done = TRUE;
1147285612Sdelphij			atexit(&stop_kern_loop);
1148285612Sdelphij		}
1149285612Sdelphij#ifdef STA_NANO
1150285612Sdelphij		if (pll_status & STA_CLK)
1151285612Sdelphij			ext_enable = TRUE;
1152285612Sdelphij#endif /* STA_NANO */
1153285612Sdelphij		report_event(EVNT_KERN, NULL,
1154285612Sdelphij	  	    "kernel time sync enabled");
1155285612Sdelphij	}
1156285612Sdelphij}
1157285612Sdelphij#endif	/* KERNEL_PLL */
1158285612Sdelphij
1159285612Sdelphij
1160285612Sdelphij#ifdef KERNEL_PLL
1161285612Sdelphijstatic void
1162285612Sdelphijstop_kern_loop(void)
1163285612Sdelphij{
1164285612Sdelphij	if (pll_control && kern_enable)
1165285612Sdelphij		report_event(EVNT_KERN, NULL,
1166285612Sdelphij		    "kernel time sync disabled");
1167285612Sdelphij}
1168285612Sdelphij#endif	/* KERNEL_PLL */
1169285612Sdelphij
1170285612Sdelphij
1171285612Sdelphij/*
1172285612Sdelphij * select_loop() - choose kernel or daemon loop discipline.
1173285612Sdelphij */
1174285612Sdelphijvoid
1175285612Sdelphijselect_loop(
1176285612Sdelphij	int	use_kern_loop
1177285612Sdelphij	)
1178285612Sdelphij{
1179285612Sdelphij	if (kern_enable == use_kern_loop)
1180285612Sdelphij		return;
1181285612Sdelphij#ifdef KERNEL_PLL
1182285612Sdelphij	if (pll_control && !use_kern_loop)
1183285612Sdelphij		stop_kern_loop();
1184285612Sdelphij#endif
1185285612Sdelphij	kern_enable = use_kern_loop;
1186285612Sdelphij#ifdef KERNEL_PLL
1187285612Sdelphij	if (pll_control && use_kern_loop)
1188285612Sdelphij		start_kern_loop();
1189285612Sdelphij#endif
1190285612Sdelphij	/*
1191285612Sdelphij	 * If this loop selection change occurs after initial startup,
1192285612Sdelphij	 * call set_freq() to switch the frequency compensation to or
1193285612Sdelphij	 * from the kernel loop.
1194285612Sdelphij	 */
1195285612Sdelphij#ifdef KERNEL_PLL
1196285612Sdelphij	if (pll_control && loop_started)
1197285612Sdelphij		set_freq(drift_comp);
1198285612Sdelphij#endif
1199285612Sdelphij}
1200285612Sdelphij
1201285612Sdelphij
1202285612Sdelphij/*
120382498Sroberto * huff-n'-puff filter
120482498Sroberto */
120582498Srobertovoid
1206285612Sdelphijhuffpuff(void)
120782498Sroberto{
120882498Sroberto	int i;
120954359Sroberto
121082498Sroberto	if (sys_huffpuff == NULL)
121182498Sroberto		return;
1212182007Sroberto
121382498Sroberto	sys_huffptr = (sys_huffptr + 1) % sys_hufflen;
121482498Sroberto	sys_huffpuff[sys_huffptr] = 1e9;
121582498Sroberto	sys_mindly = 1e9;
121682498Sroberto	for (i = 0; i < sys_hufflen; i++) {
121782498Sroberto		if (sys_huffpuff[i] < sys_mindly)
121882498Sroberto			sys_mindly = sys_huffpuff[i];
121954359Sroberto	}
122054359Sroberto}
122154359Sroberto
122254359Sroberto
122354359Sroberto/*
122454359Sroberto * loop_config - configure the loop filter
1225132451Sroberto *
1226132451Sroberto * LOCKCLOCK: The LOOP_DRIFTINIT and LOOP_DRIFTCOMP cases are no-ops.
122754359Sroberto */
122854359Srobertovoid
122954359Srobertoloop_config(
1230285612Sdelphij	int	item,
1231285612Sdelphij	double	freq
123254359Sroberto	)
123354359Sroberto{
1234285612Sdelphij	int	i;
1235285612Sdelphij	double	ftemp;
123654359Sroberto
1237293650Sglebius	DPRINTF(2, ("loop_config: item %d freq %f\n", item, freq));
123854359Sroberto	switch (item) {
123954359Sroberto
1240285612Sdelphij	/*
1241285612Sdelphij	 * We first assume the kernel supports the ntp_adjtime()
1242285612Sdelphij	 * syscall. If that syscall works, initialize the kernel time
1243285612Sdelphij	 * variables. Otherwise, continue leaving no harm behind.
1244285612Sdelphij	 */
124582498Sroberto	case LOOP_DRIFTINIT:
1246132451Sroberto#ifndef LOCKCLOCK
124754359Sroberto#ifdef KERNEL_PLL
1248182007Sroberto		if (mode_ntpdate)
1249132451Sroberto			break;
1250132451Sroberto
1251285612Sdelphij		start_kern_loop();
125282498Sroberto#endif /* KERNEL_PLL */
125354359Sroberto
125482498Sroberto		/*
1255285612Sdelphij		 * Initialize frequency if given; otherwise, begin frequency
1256285612Sdelphij		 * calibration phase.
125782498Sroberto		 */
1258285612Sdelphij		ftemp = init_drift_comp / 1e6;
1259285612Sdelphij		if (ftemp > NTP_MAXFREQ)
1260285612Sdelphij			ftemp = NTP_MAXFREQ;
1261285612Sdelphij		else if (ftemp < -NTP_MAXFREQ)
1262285612Sdelphij			ftemp = -NTP_MAXFREQ;
1263285612Sdelphij		set_freq(ftemp);
1264285612Sdelphij		if (freq_set)
1265285612Sdelphij			rstclock(EVNT_FSET, 0);
1266285612Sdelphij		else
1267285612Sdelphij			rstclock(EVNT_NSET, 0);
1268285612Sdelphij		loop_started = TRUE;
1269132451Sroberto#endif /* LOCKCLOCK */
127082498Sroberto		break;
127182498Sroberto
1272182007Sroberto	case LOOP_KERN_CLEAR:
1273285612Sdelphij#if 0		/* XXX: needs more review, and how can we get here? */
1274182007Sroberto#ifndef LOCKCLOCK
1275285612Sdelphij# ifdef KERNEL_PLL
1276285612Sdelphij		if (pll_control && kern_enable) {
1277182007Sroberto			memset((char *)&ntv, 0, sizeof(ntv));
1278285612Sdelphij			ntv.modes = MOD_STATUS;
1279182007Sroberto			ntv.status = STA_UNSYNC;
1280182007Sroberto			ntp_adjtime(&ntv);
1281285612Sdelphij			sync_status("kernel time sync disabled",
1282285612Sdelphij				pll_status,
1283285612Sdelphij				ntv.status);
1284182007Sroberto		   }
1285285612Sdelphij# endif /* KERNEL_PLL */
1286182007Sroberto#endif /* LOCKCLOCK */
1287285612Sdelphij#endif
1288182007Sroberto		break;
1289182007Sroberto
129082498Sroberto	/*
1291285612Sdelphij	 * Tinker command variables for Ulrich Windl. Very dangerous.
129282498Sroberto	 */
1293285612Sdelphij	case LOOP_ALLAN:	/* Allan intercept (log2) (allan) */
1294285612Sdelphij		allan_xpt = (u_char)freq;
129582498Sroberto		break;
129682498Sroberto
1297285612Sdelphij	case LOOP_CODEC:	/* audio codec frequency (codec) */
1298285612Sdelphij		clock_codec = freq / 1e6;
129982498Sroberto		break;
130082498Sroberto
1301285612Sdelphij	case LOOP_PHI:		/* dispersion threshold (dispersion) */
1302285612Sdelphij		clock_phi = freq / 1e6;
130382498Sroberto		break;
130482498Sroberto
1305285612Sdelphij	case LOOP_FREQ:		/* initial frequency (freq) */
1306285612Sdelphij		init_drift_comp = freq;
1307285612Sdelphij		freq_set++;
130882498Sroberto		break;
130982498Sroberto
1310285612Sdelphij	case LOOP_HUFFPUFF:	/* huff-n'-puff length (huffpuff) */
131182498Sroberto		if (freq < HUFFPUFF)
131282498Sroberto			freq = HUFFPUFF;
131382498Sroberto		sys_hufflen = (int)(freq / HUFFPUFF);
1314316069Sdelphij		sys_huffpuff = eallocarray(sys_hufflen, sizeof(sys_huffpuff[0]));
131582498Sroberto		for (i = 0; i < sys_hufflen; i++)
131682498Sroberto			sys_huffpuff[i] = 1e9;
131782498Sroberto		sys_mindly = 1e9;
131882498Sroberto		break;
1319132451Sroberto
1320285612Sdelphij	case LOOP_PANIC:	/* panic threshold (panic) */
1321285612Sdelphij		clock_panic = freq;
1322132451Sroberto		break;
1323285612Sdelphij
1324285612Sdelphij	case LOOP_MAX:		/* step threshold (step) */
1325285612Sdelphij		clock_max_fwd = clock_max_back = freq;
1326285612Sdelphij		if (freq == 0 || freq > 0.5)
1327285612Sdelphij			select_loop(FALSE);
1328285612Sdelphij		break;
1329285612Sdelphij
1330285612Sdelphij	case LOOP_MAX_BACK:	/* step threshold (step) */
1331285612Sdelphij		clock_max_back = freq;
1332285612Sdelphij		/*
1333285612Sdelphij		 * Leave using the kernel discipline code unless both
1334285612Sdelphij		 * limits are massive.  This assumes the reason to stop
1335285612Sdelphij		 * using it is that it's pointless, not that it goes wrong.
1336285612Sdelphij		 */
1337285612Sdelphij		if (  (clock_max_back == 0 || clock_max_back > 0.5)
1338285612Sdelphij		   || (clock_max_fwd  == 0 || clock_max_fwd  > 0.5))
1339285612Sdelphij			select_loop(FALSE);
1340285612Sdelphij		break;
1341285612Sdelphij
1342285612Sdelphij	case LOOP_MAX_FWD:	/* step threshold (step) */
1343285612Sdelphij		clock_max_fwd = freq;
1344285612Sdelphij		if (  (clock_max_back == 0 || clock_max_back > 0.5)
1345285612Sdelphij		   || (clock_max_fwd  == 0 || clock_max_fwd  > 0.5))
1346285612Sdelphij			select_loop(FALSE);
1347285612Sdelphij		break;
1348285612Sdelphij
1349285612Sdelphij	case LOOP_MINSTEP:	/* stepout threshold (stepout) */
1350285612Sdelphij		if (freq < CLOCK_MINSTEP)
1351285612Sdelphij			clock_minstep = CLOCK_MINSTEP;
1352285612Sdelphij		else
1353285612Sdelphij			clock_minstep = freq;
1354285612Sdelphij		break;
1355285612Sdelphij
1356285612Sdelphij	case LOOP_TICK:		/* tick increment (tick) */
1357285612Sdelphij		set_sys_tick_precision(freq);
1358285612Sdelphij		break;
1359285612Sdelphij
1360285612Sdelphij	case LOOP_LEAP:		/* not used, fall through */
1361285612Sdelphij	default:
1362285612Sdelphij		msyslog(LOG_NOTICE,
1363285612Sdelphij		    "loop_config: unsupported option %d", item);
136454359Sroberto	}
136554359Sroberto}
136654359Sroberto
136754359Sroberto
136854359Sroberto#if defined(KERNEL_PLL) && defined(SIGSYS)
136954359Sroberto/*
137054359Sroberto * _trap - trap processor for undefined syscalls
137154359Sroberto *
137254359Sroberto * This nugget is called by the kernel when the SYS_ntp_adjtime()
137354359Sroberto * syscall bombs because the silly thing has not been implemented in
137454359Sroberto * the kernel. In this case the phase-lock loop is emulated by
137554359Sroberto * the stock adjtime() syscall and a lot of indelicate abuse.
137654359Sroberto */
137754359Srobertostatic RETSIGTYPE
137854359Srobertopll_trap(
137954359Sroberto	int arg
138054359Sroberto	)
138154359Sroberto{
1382285612Sdelphij	pll_control = FALSE;
138354359Sroberto	siglongjmp(env, 1);
138454359Sroberto}
138554359Sroberto#endif /* KERNEL_PLL && SIGSYS */
1386