13f31c649SGarrett Wollman /****************************************************************************** 23f31c649SGarrett Wollman * * 33f31c649SGarrett Wollman * Copyright (c) David L. Mills 1993, 1994 * 43f31c649SGarrett Wollman * * 53f31c649SGarrett Wollman * Permission to use, copy, modify, and distribute this software and its * 63f31c649SGarrett Wollman * documentation for any purpose and without fee is hereby granted, provided * 73f31c649SGarrett Wollman * that the above copyright notice appears in all copies and that both the * 83f31c649SGarrett Wollman * copyright notice and this permission notice appear in supporting * 93f31c649SGarrett Wollman * documentation, and that the name University of Delaware not be used in * 103f31c649SGarrett Wollman * advertising or publicity pertaining to distribution of the software * 113f31c649SGarrett Wollman * without specific, written prior permission. The University of Delaware * 123f31c649SGarrett Wollman * makes no representations about the suitability this software for any * 133f31c649SGarrett Wollman * purpose. It is provided "as is" without express or implied warranty. * 143f31c649SGarrett Wollman * * 153f31c649SGarrett Wollman ******************************************************************************/ 163f31c649SGarrett Wollman 173f31c649SGarrett Wollman /* 183f31c649SGarrett Wollman * Modification history kern_ntptime.c 193f31c649SGarrett Wollman * 20885bd8e4SJohn Hay * 24 Sep 94 David L. Mills 21885bd8e4SJohn Hay * Tightened code at exits. 22885bd8e4SJohn Hay * 233f31c649SGarrett Wollman * 24 Mar 94 David L. Mills 243f31c649SGarrett Wollman * Revised syscall interface to include new variables for PPS 253f31c649SGarrett Wollman * time discipline. 263f31c649SGarrett Wollman * 273f31c649SGarrett Wollman * 14 Feb 94 David L. Mills 283f31c649SGarrett Wollman * Added code for external clock 293f31c649SGarrett Wollman * 303f31c649SGarrett Wollman * 28 Nov 93 David L. Mills 313f31c649SGarrett Wollman * Revised frequency scaling to conform with adjusted parameters 323f31c649SGarrett Wollman * 333f31c649SGarrett Wollman * 17 Sep 93 David L. Mills 343f31c649SGarrett Wollman * Created file 353f31c649SGarrett Wollman */ 363f31c649SGarrett Wollman /* 373f31c649SGarrett Wollman * ntp_gettime(), ntp_adjtime() - precision time interface for SunOS 38885bd8e4SJohn Hay * V4.1.1 and V4.1.3 393f31c649SGarrett Wollman * 403f31c649SGarrett Wollman * These routines consitute the Network Time Protocol (NTP) interfaces 413f31c649SGarrett Wollman * for user and daemon application programs. The ntp_gettime() routine 423f31c649SGarrett Wollman * provides the time, maximum error (synch distance) and estimated error 433f31c649SGarrett Wollman * (dispersion) to client user application programs. The ntp_adjtime() 443f31c649SGarrett Wollman * routine is used by the NTP daemon to adjust the system clock to an 453f31c649SGarrett Wollman * externally derived time. The time offset and related variables set by 463f31c649SGarrett Wollman * this routine are used by hardclock() to adjust the phase and 473f31c649SGarrett Wollman * frequency of the phase-lock loop which controls the system clock. 483f31c649SGarrett Wollman */ 49e0d781f3SEivind Eklund 50e0d781f3SEivind Eklund #include "opt_ntp.h" 51e0d781f3SEivind Eklund 523f31c649SGarrett Wollman #include <sys/param.h> 533f31c649SGarrett Wollman #include <sys/systm.h> 54d2d3e875SBruce Evans #include <sys/sysproto.h> 553f31c649SGarrett Wollman #include <sys/kernel.h> 563f31c649SGarrett Wollman #include <sys/proc.h> 573f31c649SGarrett Wollman #include <sys/timex.h> 58938ee3ceSPoul-Henning Kamp #include <sys/timepps.h> 593f31c649SGarrett Wollman #include <sys/sysctl.h> 603f31c649SGarrett Wollman 613f31c649SGarrett Wollman /* 626f70df15SPoul-Henning Kamp * Phase/frequency-lock loop (PLL/FLL) definitions 636f70df15SPoul-Henning Kamp * 646f70df15SPoul-Henning Kamp * The following variables are read and set by the ntp_adjtime() system 656f70df15SPoul-Henning Kamp * call. 666f70df15SPoul-Henning Kamp * 676f70df15SPoul-Henning Kamp * time_state shows the state of the system clock, with values defined 686f70df15SPoul-Henning Kamp * in the timex.h header file. 696f70df15SPoul-Henning Kamp * 706f70df15SPoul-Henning Kamp * time_status shows the status of the system clock, with bits defined 716f70df15SPoul-Henning Kamp * in the timex.h header file. 726f70df15SPoul-Henning Kamp * 736f70df15SPoul-Henning Kamp * time_offset is used by the PLL/FLL to adjust the system time in small 746f70df15SPoul-Henning Kamp * increments. 756f70df15SPoul-Henning Kamp * 766f70df15SPoul-Henning Kamp * time_constant determines the bandwidth or "stiffness" of the PLL. 776f70df15SPoul-Henning Kamp * 786f70df15SPoul-Henning Kamp * time_tolerance determines maximum frequency error or tolerance of the 796f70df15SPoul-Henning Kamp * CPU clock oscillator and is a property of the architecture; however, 806f70df15SPoul-Henning Kamp * in principle it could change as result of the presence of external 816f70df15SPoul-Henning Kamp * discipline signals, for instance. 826f70df15SPoul-Henning Kamp * 836f70df15SPoul-Henning Kamp * time_precision is usually equal to the kernel tick variable; however, 846f70df15SPoul-Henning Kamp * in cases where a precision clock counter or external clock is 856f70df15SPoul-Henning Kamp * available, the resolution can be much less than this and depend on 866f70df15SPoul-Henning Kamp * whether the external clock is working or not. 876f70df15SPoul-Henning Kamp * 886f70df15SPoul-Henning Kamp * time_maxerror is initialized by a ntp_adjtime() call and increased by 896f70df15SPoul-Henning Kamp * the kernel once each second to reflect the maximum error 906f70df15SPoul-Henning Kamp * bound growth. 916f70df15SPoul-Henning Kamp * 926f70df15SPoul-Henning Kamp * time_esterror is set and read by the ntp_adjtime() call, but 936f70df15SPoul-Henning Kamp * otherwise not used by the kernel. 943f31c649SGarrett Wollman */ 956f70df15SPoul-Henning Kamp static int time_status = STA_UNSYNC; /* clock status bits */ 966f70df15SPoul-Henning Kamp static int time_state = TIME_OK; /* clock state */ 976f70df15SPoul-Henning Kamp static long time_offset = 0; /* time offset (us) */ 986f70df15SPoul-Henning Kamp static long time_constant = 0; /* pll time constant */ 996f70df15SPoul-Henning Kamp static long time_tolerance = MAXFREQ; /* frequency tolerance (scaled ppm) */ 1006f70df15SPoul-Henning Kamp static long time_precision = 1; /* clock precision (us) */ 1016f70df15SPoul-Henning Kamp static long time_maxerror = MAXPHASE; /* maximum error (us) */ 1026f70df15SPoul-Henning Kamp static long time_esterror = MAXPHASE; /* estimated error (us) */ 1037ec73f64SPoul-Henning Kamp static int time_daemon = 0; /* No timedaemon active */ 1046f70df15SPoul-Henning Kamp 1056f70df15SPoul-Henning Kamp /* 1066f70df15SPoul-Henning Kamp * The following variables establish the state of the PLL/FLL and the 1076f70df15SPoul-Henning Kamp * residual time and frequency offset of the local clock. The scale 1086f70df15SPoul-Henning Kamp * factors are defined in the timex.h header file. 1096f70df15SPoul-Henning Kamp * 1106f70df15SPoul-Henning Kamp * time_phase and time_freq are the phase increment and the frequency 1116f70df15SPoul-Henning Kamp * increment, respectively, of the kernel time variable at each tick of 1126f70df15SPoul-Henning Kamp * the clock. 1136f70df15SPoul-Henning Kamp * 1146f70df15SPoul-Henning Kamp * time_freq is set via ntp_adjtime() from a value stored in a file when 1156f70df15SPoul-Henning Kamp * the synchronization daemon is first started. Its value is retrieved 1166f70df15SPoul-Henning Kamp * via ntp_adjtime() and written to the file about once per hour by the 1176f70df15SPoul-Henning Kamp * daemon. 1186f70df15SPoul-Henning Kamp * 1196f70df15SPoul-Henning Kamp * time_adj is the adjustment added to the value of tick at each timer 1206f70df15SPoul-Henning Kamp * interrupt and is recomputed from time_phase and time_freq at each 1216f70df15SPoul-Henning Kamp * seconds rollover. 1226f70df15SPoul-Henning Kamp * 1236f70df15SPoul-Henning Kamp * time_reftime is the second's portion of the system time on the last 1246f70df15SPoul-Henning Kamp * call to ntp_adjtime(). It is used to adjust the time_freq variable 1256f70df15SPoul-Henning Kamp * and to increase the time_maxerror as the time since last update 1266f70df15SPoul-Henning Kamp * increases. 1276f70df15SPoul-Henning Kamp */ 1286f70df15SPoul-Henning Kamp long time_phase = 0; /* phase offset (scaled us) */ 1296f70df15SPoul-Henning Kamp static long time_freq = 0; /* frequency offset (scaled ppm) */ 1306f70df15SPoul-Henning Kamp long time_adj = 0; /* tick adjust (scaled 1 / hz) */ 1316f70df15SPoul-Henning Kamp static long time_reftime = 0; /* time at last adjustment (s) */ 1323f31c649SGarrett Wollman 1333f31c649SGarrett Wollman #ifdef PPS_SYNC 1343f31c649SGarrett Wollman /* 1356f70df15SPoul-Henning Kamp * The following variables are used only if the kernel PPS discipline 1366f70df15SPoul-Henning Kamp * code is configured (PPS_SYNC). The scale factors are defined in the 1376f70df15SPoul-Henning Kamp * timex.h header file. 1386f70df15SPoul-Henning Kamp * 1396f70df15SPoul-Henning Kamp * pps_time contains the time at each calibration interval, as read by 1406f70df15SPoul-Henning Kamp * microtime(). pps_count counts the seconds of the calibration 1416f70df15SPoul-Henning Kamp * interval, the duration of which is nominally pps_shift in powers of 1426f70df15SPoul-Henning Kamp * two. 1436f70df15SPoul-Henning Kamp * 1446f70df15SPoul-Henning Kamp * pps_offset is the time offset produced by the time median filter 1456f70df15SPoul-Henning Kamp * pps_tf[], while pps_jitter is the dispersion (jitter) measured by 1466f70df15SPoul-Henning Kamp * this filter. 1476f70df15SPoul-Henning Kamp * 1486f70df15SPoul-Henning Kamp * pps_freq is the frequency offset produced by the frequency median 1496f70df15SPoul-Henning Kamp * filter pps_ff[], while pps_stabil is the dispersion (wander) measured 1506f70df15SPoul-Henning Kamp * by this filter. 1516f70df15SPoul-Henning Kamp * 1526f70df15SPoul-Henning Kamp * pps_usec is latched from a high resolution counter or external clock 1536f70df15SPoul-Henning Kamp * at pps_time. Here we want the hardware counter contents only, not the 1546f70df15SPoul-Henning Kamp * contents plus the time_tv.usec as usual. 1556f70df15SPoul-Henning Kamp * 1566f70df15SPoul-Henning Kamp * pps_valid counts the number of seconds since the last PPS update. It 1576f70df15SPoul-Henning Kamp * is used as a watchdog timer to disable the PPS discipline should the 1586f70df15SPoul-Henning Kamp * PPS signal be lost. 1596f70df15SPoul-Henning Kamp * 1606f70df15SPoul-Henning Kamp * pps_glitch counts the number of seconds since the beginning of an 1616f70df15SPoul-Henning Kamp * offset burst more than tick/2 from current nominal offset. It is used 1626f70df15SPoul-Henning Kamp * mainly to suppress error bursts due to priority conflicts between the 1636f70df15SPoul-Henning Kamp * PPS interrupt and timer interrupt. 1646f70df15SPoul-Henning Kamp * 1656f70df15SPoul-Henning Kamp * pps_intcnt counts the calibration intervals for use in the interval- 1666f70df15SPoul-Henning Kamp * adaptation algorithm. It's just too complicated for words. 1673f31c649SGarrett Wollman */ 1686f70df15SPoul-Henning Kamp static struct timeval pps_time; /* kernel time at last interval */ 1696f70df15SPoul-Henning Kamp static long pps_offset = 0; /* pps time offset (us) */ 1706f70df15SPoul-Henning Kamp static long pps_jitter = MAXTIME; /* pps time dispersion (jitter) (us) */ 1716f70df15SPoul-Henning Kamp static long pps_tf[] = {0, 0, 0}; /* pps time offset median filter (us) */ 1726f70df15SPoul-Henning Kamp static long pps_freq = 0; /* frequency offset (scaled ppm) */ 1736f70df15SPoul-Henning Kamp static long pps_stabil = MAXFREQ; /* frequency dispersion (scaled ppm) */ 1746f70df15SPoul-Henning Kamp static long pps_ff[] = {0, 0, 0}; /* frequency offset median filter */ 1756f70df15SPoul-Henning Kamp static long pps_usec = 0; /* microsec counter at last interval */ 1766f70df15SPoul-Henning Kamp static long pps_valid = PPS_VALID; /* pps signal watchdog counter */ 1776f70df15SPoul-Henning Kamp static int pps_glitch = 0; /* pps signal glitch counter */ 1786f70df15SPoul-Henning Kamp static int pps_count = 0; /* calibration interval counter (s) */ 1796f70df15SPoul-Henning Kamp static int pps_shift = PPS_SHIFT; /* interval duration (s) (shift) */ 1806f70df15SPoul-Henning Kamp static int pps_intcnt = 0; /* intervals at current duration */ 1816f70df15SPoul-Henning Kamp 1826f70df15SPoul-Henning Kamp /* 1836f70df15SPoul-Henning Kamp * PPS signal quality monitors 1846f70df15SPoul-Henning Kamp * 1856f70df15SPoul-Henning Kamp * pps_jitcnt counts the seconds that have been discarded because the 1866f70df15SPoul-Henning Kamp * jitter measured by the time median filter exceeds the limit MAXTIME 1876f70df15SPoul-Henning Kamp * (100 us). 1886f70df15SPoul-Henning Kamp * 1896f70df15SPoul-Henning Kamp * pps_calcnt counts the frequency calibration intervals, which are 1906f70df15SPoul-Henning Kamp * variable from 4 s to 256 s. 1916f70df15SPoul-Henning Kamp * 1926f70df15SPoul-Henning Kamp * pps_errcnt counts the calibration intervals which have been discarded 1936f70df15SPoul-Henning Kamp * because the wander exceeds the limit MAXFREQ (100 ppm) or where the 1946f70df15SPoul-Henning Kamp * calibration interval jitter exceeds two ticks. 1956f70df15SPoul-Henning Kamp * 1966f70df15SPoul-Henning Kamp * pps_stbcnt counts the calibration intervals that have been discarded 1976f70df15SPoul-Henning Kamp * because the frequency wander exceeds the limit MAXFREQ / 4 (25 us). 1986f70df15SPoul-Henning Kamp */ 1996f70df15SPoul-Henning Kamp static long pps_jitcnt = 0; /* jitter limit exceeded */ 2006f70df15SPoul-Henning Kamp static long pps_calcnt = 0; /* calibration intervals */ 2016f70df15SPoul-Henning Kamp static long pps_errcnt = 0; /* calibration errors */ 2026f70df15SPoul-Henning Kamp static long pps_stbcnt = 0; /* stability limit exceeded */ 2033f31c649SGarrett Wollman #endif /* PPS_SYNC */ 2043f31c649SGarrett Wollman 205938ee3ceSPoul-Henning Kamp static void hardupdate __P((int64_t offset, int prescaled)); 2066f70df15SPoul-Henning Kamp 2076f70df15SPoul-Henning Kamp /* 2086f70df15SPoul-Henning Kamp * hardupdate() - local clock update 2096f70df15SPoul-Henning Kamp * 2106f70df15SPoul-Henning Kamp * This routine is called by ntp_adjtime() to update the local clock 2116f70df15SPoul-Henning Kamp * phase and frequency. The implementation is of an adaptive-parameter, 2126f70df15SPoul-Henning Kamp * hybrid phase/frequency-lock loop (PLL/FLL). The routine computes new 2136f70df15SPoul-Henning Kamp * time and frequency offset estimates for each call. If the kernel PPS 2146f70df15SPoul-Henning Kamp * discipline code is configured (PPS_SYNC), the PPS signal itself 2156f70df15SPoul-Henning Kamp * determines the new time offset, instead of the calling argument. 2166f70df15SPoul-Henning Kamp * Presumably, calls to ntp_adjtime() occur only when the caller 2176f70df15SPoul-Henning Kamp * believes the local clock is valid within some bound (+-128 ms with 2186f70df15SPoul-Henning Kamp * NTP). If the caller's time is far different than the PPS time, an 2196f70df15SPoul-Henning Kamp * argument will ensue, and it's not clear who will lose. 2206f70df15SPoul-Henning Kamp * 2216f70df15SPoul-Henning Kamp * For uncompensated quartz crystal oscillatores and nominal update 2226f70df15SPoul-Henning Kamp * intervals less than 1024 s, operation should be in phase-lock mode 2236f70df15SPoul-Henning Kamp * (STA_FLL = 0), where the loop is disciplined to phase. For update 2246f70df15SPoul-Henning Kamp * intervals greater than thiss, operation should be in frequency-lock 2256f70df15SPoul-Henning Kamp * mode (STA_FLL = 1), where the loop is disciplined to frequency. 2266f70df15SPoul-Henning Kamp * 2276f70df15SPoul-Henning Kamp * Note: splclock() is in effect. 2286f70df15SPoul-Henning Kamp */ 2296f70df15SPoul-Henning Kamp static void 230938ee3ceSPoul-Henning Kamp hardupdate(offset, prescaled) 231938ee3ceSPoul-Henning Kamp int64_t offset; 232938ee3ceSPoul-Henning Kamp int prescaled; 2336f70df15SPoul-Henning Kamp { 234938ee3ceSPoul-Henning Kamp long mtemp; 235938ee3ceSPoul-Henning Kamp int64_t ltemp; 2366f70df15SPoul-Henning Kamp 2376f70df15SPoul-Henning Kamp if (!(time_status & STA_PLL) && !(time_status & STA_PPSTIME)) 2386f70df15SPoul-Henning Kamp return; 239938ee3ceSPoul-Henning Kamp if (prescaled) 2406f70df15SPoul-Henning Kamp ltemp = offset; 241938ee3ceSPoul-Henning Kamp else 242938ee3ceSPoul-Henning Kamp ltemp = offset << SHIFT_UPDATE; 2436f70df15SPoul-Henning Kamp #ifdef PPS_SYNC 2446f70df15SPoul-Henning Kamp if (time_status & STA_PPSTIME && time_status & STA_PPSSIGNAL) 245938ee3ceSPoul-Henning Kamp ltemp = pps_offset << SHIFT_UPDATE; 2466f70df15SPoul-Henning Kamp #endif /* PPS_SYNC */ 2476f70df15SPoul-Henning Kamp 2486f70df15SPoul-Henning Kamp /* 2496f70df15SPoul-Henning Kamp * Scale the phase adjustment and clamp to the operating range. 2506f70df15SPoul-Henning Kamp */ 251938ee3ceSPoul-Henning Kamp if (ltemp > (MAXPHASE << SHIFT_UPDATE)) 2526f70df15SPoul-Henning Kamp time_offset = MAXPHASE << SHIFT_UPDATE; 253938ee3ceSPoul-Henning Kamp else if (ltemp < -(MAXPHASE << SHIFT_UPDATE)) 2546f70df15SPoul-Henning Kamp time_offset = -(MAXPHASE << SHIFT_UPDATE); 2556f70df15SPoul-Henning Kamp else 256938ee3ceSPoul-Henning Kamp time_offset = ltemp; 2576f70df15SPoul-Henning Kamp 2586f70df15SPoul-Henning Kamp /* 2596f70df15SPoul-Henning Kamp * Select whether the frequency is to be controlled and in which 2606f70df15SPoul-Henning Kamp * mode (PLL or FLL). Clamp to the operating range. Ugly 2616f70df15SPoul-Henning Kamp * multiply/divide should be replaced someday. 2626f70df15SPoul-Henning Kamp */ 2636f70df15SPoul-Henning Kamp if (time_status & STA_FREQHOLD || time_reftime == 0) 264227ee8a1SPoul-Henning Kamp time_reftime = time_second; 265227ee8a1SPoul-Henning Kamp mtemp = time_second - time_reftime; 266227ee8a1SPoul-Henning Kamp time_reftime = time_second; 2676f70df15SPoul-Henning Kamp if (time_status & STA_FLL) { 2686f70df15SPoul-Henning Kamp if (mtemp >= MINSEC) { 2696f70df15SPoul-Henning Kamp ltemp = ((time_offset / mtemp) << (SHIFT_USEC - 2706f70df15SPoul-Henning Kamp SHIFT_UPDATE)); 2716f70df15SPoul-Henning Kamp if (ltemp < 0) 2726f70df15SPoul-Henning Kamp time_freq -= -ltemp >> SHIFT_KH; 2736f70df15SPoul-Henning Kamp else 2746f70df15SPoul-Henning Kamp time_freq += ltemp >> SHIFT_KH; 2756f70df15SPoul-Henning Kamp } 2766f70df15SPoul-Henning Kamp } else { 2776f70df15SPoul-Henning Kamp if (mtemp < MAXSEC) { 278938ee3ceSPoul-Henning Kamp ltemp = time_offset * mtemp; 2796f70df15SPoul-Henning Kamp if (ltemp < 0) 280938ee3ceSPoul-Henning Kamp time_freq -= -ltemp >> ((int64_t)time_constant + 2816f70df15SPoul-Henning Kamp time_constant + SHIFT_KF - 282938ee3ceSPoul-Henning Kamp SHIFT_USEC + SHIFT_UPDATE); 2836f70df15SPoul-Henning Kamp else 284938ee3ceSPoul-Henning Kamp time_freq += ltemp >> ((int64_t)time_constant + 2856f70df15SPoul-Henning Kamp time_constant + SHIFT_KF - 286938ee3ceSPoul-Henning Kamp SHIFT_USEC + SHIFT_UPDATE); 2876f70df15SPoul-Henning Kamp } 2886f70df15SPoul-Henning Kamp } 2896f70df15SPoul-Henning Kamp if (time_freq > time_tolerance) 2906f70df15SPoul-Henning Kamp time_freq = time_tolerance; 2916f70df15SPoul-Henning Kamp else if (time_freq < -time_tolerance) 2926f70df15SPoul-Henning Kamp time_freq = -time_tolerance; 2936f70df15SPoul-Henning Kamp } 2946f70df15SPoul-Henning Kamp 2957ec73f64SPoul-Henning Kamp /* 2967ec73f64SPoul-Henning Kamp * On rollover of the second the phase adjustment to be used for 2977ec73f64SPoul-Henning Kamp * the next second is calculated. Also, the maximum error is 2987ec73f64SPoul-Henning Kamp * increased by the tolerance. If the PPS frequency discipline 2997ec73f64SPoul-Henning Kamp * code is present, the phase is increased to compensate for the 3007ec73f64SPoul-Henning Kamp * CPU clock oscillator frequency error. 3017ec73f64SPoul-Henning Kamp * 3027ec73f64SPoul-Henning Kamp * On a 32-bit machine and given parameters in the timex.h 3037ec73f64SPoul-Henning Kamp * header file, the maximum phase adjustment is +-512 ms and 3047ec73f64SPoul-Henning Kamp * maximum frequency offset is a tad less than) +-512 ppm. On a 3057ec73f64SPoul-Henning Kamp * 64-bit machine, you shouldn't need to ask. 3067ec73f64SPoul-Henning Kamp */ 3076f70df15SPoul-Henning Kamp void 3087ec73f64SPoul-Henning Kamp ntp_update_second(struct timecounter *tc) 3096f70df15SPoul-Henning Kamp { 3107ec73f64SPoul-Henning Kamp u_int32_t *newsec; 3116f70df15SPoul-Henning Kamp long ltemp; 3126f70df15SPoul-Henning Kamp 3137ec73f64SPoul-Henning Kamp if (!time_daemon) 3147ec73f64SPoul-Henning Kamp return; 3157ec73f64SPoul-Henning Kamp 316a58f0f8eSPoul-Henning Kamp newsec = &tc->tc_offset_sec; 3176f70df15SPoul-Henning Kamp time_maxerror += time_tolerance >> SHIFT_USEC; 3186f70df15SPoul-Henning Kamp 3196f70df15SPoul-Henning Kamp /* 3206f70df15SPoul-Henning Kamp * Compute the phase adjustment for the next second. In 3216f70df15SPoul-Henning Kamp * PLL mode, the offset is reduced by a fixed factor 3226f70df15SPoul-Henning Kamp * times the time constant. In FLL mode the offset is 3236f70df15SPoul-Henning Kamp * used directly. In either mode, the maximum phase 3246f70df15SPoul-Henning Kamp * adjustment for each second is clamped so as to spread 3256f70df15SPoul-Henning Kamp * the adjustment over not more than the number of 3266f70df15SPoul-Henning Kamp * seconds between updates. 3276f70df15SPoul-Henning Kamp */ 3286f70df15SPoul-Henning Kamp if (time_offset < 0) { 3296f70df15SPoul-Henning Kamp ltemp = -time_offset; 3306f70df15SPoul-Henning Kamp if (!(time_status & STA_FLL)) 3316f70df15SPoul-Henning Kamp ltemp >>= SHIFT_KG + time_constant; 3326f70df15SPoul-Henning Kamp if (ltemp > (MAXPHASE / MINSEC) << SHIFT_UPDATE) 3336f70df15SPoul-Henning Kamp ltemp = (MAXPHASE / MINSEC) << SHIFT_UPDATE; 3346f70df15SPoul-Henning Kamp time_offset += ltemp; 3357ec73f64SPoul-Henning Kamp time_adj = -ltemp << (SHIFT_SCALE - SHIFT_UPDATE); 3366f70df15SPoul-Henning Kamp } else { 3376f70df15SPoul-Henning Kamp ltemp = time_offset; 3386f70df15SPoul-Henning Kamp if (!(time_status & STA_FLL)) 3396f70df15SPoul-Henning Kamp ltemp >>= SHIFT_KG + time_constant; 3406f70df15SPoul-Henning Kamp if (ltemp > (MAXPHASE / MINSEC) << SHIFT_UPDATE) 3416f70df15SPoul-Henning Kamp ltemp = (MAXPHASE / MINSEC) << SHIFT_UPDATE; 3426f70df15SPoul-Henning Kamp time_offset -= ltemp; 3437ec73f64SPoul-Henning Kamp time_adj = ltemp << (SHIFT_SCALE - SHIFT_UPDATE); 3446f70df15SPoul-Henning Kamp } 3456f70df15SPoul-Henning Kamp 3466f70df15SPoul-Henning Kamp /* 3476f70df15SPoul-Henning Kamp * Compute the frequency estimate and additional phase 3486f70df15SPoul-Henning Kamp * adjustment due to frequency error for the next 3496f70df15SPoul-Henning Kamp * second. When the PPS signal is engaged, gnaw on the 3506f70df15SPoul-Henning Kamp * watchdog counter and update the frequency computed by 3516f70df15SPoul-Henning Kamp * the pll and the PPS signal. 3526f70df15SPoul-Henning Kamp */ 3536f70df15SPoul-Henning Kamp #ifdef PPS_SYNC 3546f70df15SPoul-Henning Kamp pps_valid++; 3556f70df15SPoul-Henning Kamp if (pps_valid == PPS_VALID) { 3566f70df15SPoul-Henning Kamp pps_jitter = MAXTIME; 3576f70df15SPoul-Henning Kamp pps_stabil = MAXFREQ; 3586f70df15SPoul-Henning Kamp time_status &= ~(STA_PPSSIGNAL | STA_PPSJITTER | 3596f70df15SPoul-Henning Kamp STA_PPSWANDER | STA_PPSERROR); 3606f70df15SPoul-Henning Kamp } 3616f70df15SPoul-Henning Kamp ltemp = time_freq + pps_freq; 3626f70df15SPoul-Henning Kamp #else 3636f70df15SPoul-Henning Kamp ltemp = time_freq; 3646f70df15SPoul-Henning Kamp #endif /* PPS_SYNC */ 3656f70df15SPoul-Henning Kamp if (ltemp < 0) 3667ec73f64SPoul-Henning Kamp time_adj -= -ltemp << (SHIFT_SCALE - SHIFT_USEC); 3676f70df15SPoul-Henning Kamp else 3687ec73f64SPoul-Henning Kamp time_adj += ltemp << (SHIFT_SCALE - SHIFT_USEC); 3696f70df15SPoul-Henning Kamp 370a58f0f8eSPoul-Henning Kamp tc->tc_adjustment = time_adj; 3716f70df15SPoul-Henning Kamp 3726f70df15SPoul-Henning Kamp /* XXX - this is really bogus, but can't be fixed until 3736f70df15SPoul-Henning Kamp xntpd's idea of the system clock is fixed to know how 3746f70df15SPoul-Henning Kamp the user wants leap seconds handled; in the mean time, 3756f70df15SPoul-Henning Kamp we assume that users of NTP are running without proper 3766f70df15SPoul-Henning Kamp leap second support (this is now the default anyway) */ 3776f70df15SPoul-Henning Kamp /* 3786f70df15SPoul-Henning Kamp * Leap second processing. If in leap-insert state at 3796f70df15SPoul-Henning Kamp * the end of the day, the system clock is set back one 3806f70df15SPoul-Henning Kamp * second; if in leap-delete state, the system clock is 3816f70df15SPoul-Henning Kamp * set ahead one second. The microtime() routine or 3826f70df15SPoul-Henning Kamp * external clock driver will insure that reported time 3836f70df15SPoul-Henning Kamp * is always monotonic. The ugly divides should be 3846f70df15SPoul-Henning Kamp * replaced. 3856f70df15SPoul-Henning Kamp */ 3866f70df15SPoul-Henning Kamp switch (time_state) { 3876f70df15SPoul-Henning Kamp 3886f70df15SPoul-Henning Kamp case TIME_OK: 3896f70df15SPoul-Henning Kamp if (time_status & STA_INS) 3906f70df15SPoul-Henning Kamp time_state = TIME_INS; 3916f70df15SPoul-Henning Kamp else if (time_status & STA_DEL) 3926f70df15SPoul-Henning Kamp time_state = TIME_DEL; 3936f70df15SPoul-Henning Kamp break; 3946f70df15SPoul-Henning Kamp 3956f70df15SPoul-Henning Kamp case TIME_INS: 3966f70df15SPoul-Henning Kamp if ((*newsec) % 86400 == 0) { 3976f70df15SPoul-Henning Kamp (*newsec)--; 3986f70df15SPoul-Henning Kamp time_state = TIME_OOP; 3996f70df15SPoul-Henning Kamp } 4006f70df15SPoul-Henning Kamp break; 4016f70df15SPoul-Henning Kamp 4026f70df15SPoul-Henning Kamp case TIME_DEL: 4036f70df15SPoul-Henning Kamp if (((*newsec) + 1) % 86400 == 0) { 4046f70df15SPoul-Henning Kamp (*newsec)++; 4056f70df15SPoul-Henning Kamp time_state = TIME_WAIT; 4066f70df15SPoul-Henning Kamp } 4076f70df15SPoul-Henning Kamp break; 4086f70df15SPoul-Henning Kamp 4096f70df15SPoul-Henning Kamp case TIME_OOP: 4106f70df15SPoul-Henning Kamp time_state = TIME_WAIT; 4116f70df15SPoul-Henning Kamp break; 4126f70df15SPoul-Henning Kamp 4136f70df15SPoul-Henning Kamp case TIME_WAIT: 4146f70df15SPoul-Henning Kamp if (!(time_status & (STA_INS | STA_DEL))) 4156f70df15SPoul-Henning Kamp time_state = TIME_OK; 4166f70df15SPoul-Henning Kamp break; 4176f70df15SPoul-Henning Kamp } 4186f70df15SPoul-Henning Kamp } 4199ada5a50SPoul-Henning Kamp 420a52752a4SPoul-Henning Kamp static int 421a52752a4SPoul-Henning Kamp ntp_sysctl SYSCTL_HANDLER_ARGS 4223f31c649SGarrett Wollman { 4233f31c649SGarrett Wollman struct timeval atv; 4243f31c649SGarrett Wollman struct ntptimeval ntv; 4253f31c649SGarrett Wollman int s; 4263f31c649SGarrett Wollman 4273f31c649SGarrett Wollman s = splclock(); 4283f31c649SGarrett Wollman microtime(&atv); 4293f31c649SGarrett Wollman ntv.time = atv; 4303f31c649SGarrett Wollman ntv.maxerror = time_maxerror; 4313f31c649SGarrett Wollman ntv.esterror = time_esterror; 4323f31c649SGarrett Wollman splx(s); 4333f31c649SGarrett Wollman 4343f31c649SGarrett Wollman ntv.time_state = time_state; 4353f31c649SGarrett Wollman 4363f31c649SGarrett Wollman /* 4373f31c649SGarrett Wollman * Status word error decode. If any of these conditions 4383f31c649SGarrett Wollman * occur, an error is returned, instead of the status 4393f31c649SGarrett Wollman * word. Most applications will care only about the fact 4403f31c649SGarrett Wollman * the system clock may not be trusted, not about the 4413f31c649SGarrett Wollman * details. 4423f31c649SGarrett Wollman * 4433f31c649SGarrett Wollman * Hardware or software error 4443f31c649SGarrett Wollman */ 4453f31c649SGarrett Wollman if (time_status & (STA_UNSYNC | STA_CLOCKERR)) { 4463f31c649SGarrett Wollman ntv.time_state = TIME_ERROR; 4473f31c649SGarrett Wollman } 4483f31c649SGarrett Wollman 4493f31c649SGarrett Wollman /* 4503f31c649SGarrett Wollman * PPS signal lost when either time or frequency 4513f31c649SGarrett Wollman * synchronization requested 4523f31c649SGarrett Wollman */ 4533f31c649SGarrett Wollman if (time_status & (STA_PPSFREQ | STA_PPSTIME) && 4543f31c649SGarrett Wollman !(time_status & STA_PPSSIGNAL)) { 4553f31c649SGarrett Wollman ntv.time_state = TIME_ERROR; 4563f31c649SGarrett Wollman } 4573f31c649SGarrett Wollman 4583f31c649SGarrett Wollman /* 4593f31c649SGarrett Wollman * PPS jitter exceeded when time synchronization 4603f31c649SGarrett Wollman * requested 4613f31c649SGarrett Wollman */ 4623f31c649SGarrett Wollman if (time_status & STA_PPSTIME && 4633f31c649SGarrett Wollman time_status & STA_PPSJITTER) { 4643f31c649SGarrett Wollman ntv.time_state = TIME_ERROR; 4653f31c649SGarrett Wollman } 4663f31c649SGarrett Wollman 4673f31c649SGarrett Wollman /* 4683f31c649SGarrett Wollman * PPS wander exceeded or calibration error when 4693f31c649SGarrett Wollman * frequency synchronization requested 4703f31c649SGarrett Wollman */ 4713f31c649SGarrett Wollman if (time_status & STA_PPSFREQ && 4723f31c649SGarrett Wollman time_status & (STA_PPSWANDER | STA_PPSERROR)) { 4733f31c649SGarrett Wollman ntv.time_state = TIME_ERROR; 4743f31c649SGarrett Wollman } 475a52752a4SPoul-Henning Kamp return (sysctl_handle_opaque(oidp, &ntv, sizeof ntv, req)); 4763f31c649SGarrett Wollman } 4773f31c649SGarrett Wollman 478a52752a4SPoul-Henning Kamp SYSCTL_NODE(_kern, KERN_NTP_PLL, ntp_pll, CTLFLAG_RW, 0, 479a52752a4SPoul-Henning Kamp "NTP kernel PLL related stuff"); 480a52752a4SPoul-Henning Kamp SYSCTL_PROC(_kern_ntp_pll, NTP_PLL_GETTIME, gettime, CTLTYPE_OPAQUE|CTLFLAG_RD, 481946bb7a2SPoul-Henning Kamp 0, sizeof(struct ntptimeval) , ntp_sysctl, "S,ntptimeval", ""); 482a52752a4SPoul-Henning Kamp 4833f31c649SGarrett Wollman /* 4843f31c649SGarrett Wollman * ntp_adjtime() - NTP daemon application interface 4853f31c649SGarrett Wollman */ 486d2d3e875SBruce Evans #ifndef _SYS_SYSPROTO_H_ 4873f31c649SGarrett Wollman struct ntp_adjtime_args { 4883f31c649SGarrett Wollman struct timex *tp; 4893f31c649SGarrett Wollman }; 490d2d3e875SBruce Evans #endif 4913f31c649SGarrett Wollman 4923f31c649SGarrett Wollman int 493cb226aaaSPoul-Henning Kamp ntp_adjtime(struct proc *p, struct ntp_adjtime_args *uap) 4943f31c649SGarrett Wollman { 4953f31c649SGarrett Wollman struct timex ntv; 4963f31c649SGarrett Wollman int modes; 4973f31c649SGarrett Wollman int s; 4983f31c649SGarrett Wollman int error; 4993f31c649SGarrett Wollman 5007ec73f64SPoul-Henning Kamp time_daemon = 1; 5017ec73f64SPoul-Henning Kamp 5023f31c649SGarrett Wollman error = copyin((caddr_t)uap->tp, (caddr_t)&ntv, sizeof(ntv)); 5033f31c649SGarrett Wollman if (error) 5043f31c649SGarrett Wollman return error; 5053f31c649SGarrett Wollman 5063f31c649SGarrett Wollman /* 5073f31c649SGarrett Wollman * Update selected clock variables - only the superuser can 5083f31c649SGarrett Wollman * change anything. Note that there is no error checking here on 5093f31c649SGarrett Wollman * the assumption the superuser should know what it is doing. 5103f31c649SGarrett Wollman */ 5113f31c649SGarrett Wollman modes = ntv.modes; 5123f31c649SGarrett Wollman if ((modes != 0) 5133f31c649SGarrett Wollman && (error = suser(p->p_cred->pc_ucred, &p->p_acflag))) 5143f31c649SGarrett Wollman return error; 5153f31c649SGarrett Wollman 5163f31c649SGarrett Wollman s = splclock(); 5173f31c649SGarrett Wollman if (modes & MOD_FREQUENCY) 5183f31c649SGarrett Wollman #ifdef PPS_SYNC 5193f31c649SGarrett Wollman time_freq = ntv.freq - pps_freq; 5203f31c649SGarrett Wollman #else /* PPS_SYNC */ 5213f31c649SGarrett Wollman time_freq = ntv.freq; 5223f31c649SGarrett Wollman #endif /* PPS_SYNC */ 5233f31c649SGarrett Wollman if (modes & MOD_MAXERROR) 5243f31c649SGarrett Wollman time_maxerror = ntv.maxerror; 5253f31c649SGarrett Wollman if (modes & MOD_ESTERROR) 5263f31c649SGarrett Wollman time_esterror = ntv.esterror; 5273f31c649SGarrett Wollman if (modes & MOD_STATUS) { 5283f31c649SGarrett Wollman time_status &= STA_RONLY; 5293f31c649SGarrett Wollman time_status |= ntv.status & ~STA_RONLY; 5303f31c649SGarrett Wollman } 5313f31c649SGarrett Wollman if (modes & MOD_TIMECONST) 5323f31c649SGarrett Wollman time_constant = ntv.constant; 5333f31c649SGarrett Wollman if (modes & MOD_OFFSET) 534938ee3ceSPoul-Henning Kamp hardupdate(ntv.offset, modes & MOD_DOSCALE); 5353f31c649SGarrett Wollman 536938ee3ceSPoul-Henning Kamp ntv.modes |= MOD_CANSCALE; 5373f31c649SGarrett Wollman /* 5383f31c649SGarrett Wollman * Retrieve all clock variables 5393f31c649SGarrett Wollman */ 540938ee3ceSPoul-Henning Kamp if (modes & MOD_DOSCALE) 541938ee3ceSPoul-Henning Kamp ntv.offset = time_offset; 542938ee3ceSPoul-Henning Kamp else if (time_offset < 0) 5433f31c649SGarrett Wollman ntv.offset = -(-time_offset >> SHIFT_UPDATE); 5443f31c649SGarrett Wollman else 5453f31c649SGarrett Wollman ntv.offset = time_offset >> SHIFT_UPDATE; 5463f31c649SGarrett Wollman #ifdef PPS_SYNC 5473f31c649SGarrett Wollman ntv.freq = time_freq + pps_freq; 5483f31c649SGarrett Wollman #else /* PPS_SYNC */ 5493f31c649SGarrett Wollman ntv.freq = time_freq; 5503f31c649SGarrett Wollman #endif /* PPS_SYNC */ 5513f31c649SGarrett Wollman ntv.maxerror = time_maxerror; 5523f31c649SGarrett Wollman ntv.esterror = time_esterror; 5533f31c649SGarrett Wollman ntv.status = time_status; 5543f31c649SGarrett Wollman ntv.constant = time_constant; 5553f31c649SGarrett Wollman ntv.precision = time_precision; 5563f31c649SGarrett Wollman ntv.tolerance = time_tolerance; 5573f31c649SGarrett Wollman #ifdef PPS_SYNC 5583f31c649SGarrett Wollman ntv.shift = pps_shift; 5593f31c649SGarrett Wollman ntv.ppsfreq = pps_freq; 5603f31c649SGarrett Wollman ntv.jitter = pps_jitter >> PPS_AVG; 5613f31c649SGarrett Wollman ntv.stabil = pps_stabil; 5623f31c649SGarrett Wollman ntv.calcnt = pps_calcnt; 5633f31c649SGarrett Wollman ntv.errcnt = pps_errcnt; 5643f31c649SGarrett Wollman ntv.jitcnt = pps_jitcnt; 5653f31c649SGarrett Wollman ntv.stbcnt = pps_stbcnt; 5663f31c649SGarrett Wollman #endif /* PPS_SYNC */ 5673f31c649SGarrett Wollman (void)splx(s); 5683f31c649SGarrett Wollman 5693f31c649SGarrett Wollman error = copyout((caddr_t)&ntv, (caddr_t)uap->tp, sizeof(ntv)); 5703f31c649SGarrett Wollman if (!error) { 5713f31c649SGarrett Wollman /* 5723f31c649SGarrett Wollman * Status word error decode. See comments in 5733f31c649SGarrett Wollman * ntp_gettime() routine. 5743f31c649SGarrett Wollman */ 575cb226aaaSPoul-Henning Kamp p->p_retval[0] = time_state; 5763f31c649SGarrett Wollman if (time_status & (STA_UNSYNC | STA_CLOCKERR)) 577cb226aaaSPoul-Henning Kamp p->p_retval[0] = TIME_ERROR; 5783f31c649SGarrett Wollman if (time_status & (STA_PPSFREQ | STA_PPSTIME) && 5793f31c649SGarrett Wollman !(time_status & STA_PPSSIGNAL)) 580cb226aaaSPoul-Henning Kamp p->p_retval[0] = TIME_ERROR; 5813f31c649SGarrett Wollman if (time_status & STA_PPSTIME && 5823f31c649SGarrett Wollman time_status & STA_PPSJITTER) 583cb226aaaSPoul-Henning Kamp p->p_retval[0] = TIME_ERROR; 5843f31c649SGarrett Wollman if (time_status & STA_PPSFREQ && 5853f31c649SGarrett Wollman time_status & (STA_PPSWANDER | STA_PPSERROR)) 586cb226aaaSPoul-Henning Kamp p->p_retval[0] = TIME_ERROR; 5873f31c649SGarrett Wollman } 5883f31c649SGarrett Wollman return error; 5893f31c649SGarrett Wollman } 5903f31c649SGarrett Wollman 5916f70df15SPoul-Henning Kamp #ifdef PPS_SYNC 5923f31c649SGarrett Wollman 5939ada5a50SPoul-Henning Kamp /* We need this ugly monster twice, so let's macroize it. */ 5946f70df15SPoul-Henning Kamp 5956f70df15SPoul-Henning Kamp #define MEDIAN3X(a, m, s, i1, i2, i3) \ 5966f70df15SPoul-Henning Kamp do { \ 5976f70df15SPoul-Henning Kamp m = a[i2]; \ 5986f70df15SPoul-Henning Kamp s = a[i1] - a[i3]; \ 5996f70df15SPoul-Henning Kamp } while (0) 6006f70df15SPoul-Henning Kamp 6016f70df15SPoul-Henning Kamp #define MEDIAN3(a, m, s) \ 6026f70df15SPoul-Henning Kamp do { \ 6036f70df15SPoul-Henning Kamp if (a[0] > a[1]) { \ 6046f70df15SPoul-Henning Kamp if (a[1] > a[2]) \ 6056f70df15SPoul-Henning Kamp MEDIAN3X(a, m, s, 0, 1, 2); \ 6066f70df15SPoul-Henning Kamp else if (a[2] > a[0]) \ 6076f70df15SPoul-Henning Kamp MEDIAN3X(a, m, s, 2, 0, 1); \ 6086f70df15SPoul-Henning Kamp else \ 6096f70df15SPoul-Henning Kamp MEDIAN3X(a, m, s, 0, 2, 1); \ 6106f70df15SPoul-Henning Kamp } else { \ 6116f70df15SPoul-Henning Kamp if (a[2] > a[1]) \ 6126f70df15SPoul-Henning Kamp MEDIAN3X(a, m, s, 2, 1, 0); \ 6136f70df15SPoul-Henning Kamp else if (a[0] > a[2]) \ 6146f70df15SPoul-Henning Kamp MEDIAN3X(a, m, s, 1, 0, 2); \ 6156f70df15SPoul-Henning Kamp else \ 6166f70df15SPoul-Henning Kamp MEDIAN3X(a, m, s, 1, 2, 0); \ 6176f70df15SPoul-Henning Kamp } \ 6186f70df15SPoul-Henning Kamp } while (0) 6196f70df15SPoul-Henning Kamp 6206f70df15SPoul-Henning Kamp /* 6216f70df15SPoul-Henning Kamp * hardpps() - discipline CPU clock oscillator to external PPS signal 6226f70df15SPoul-Henning Kamp * 6236f70df15SPoul-Henning Kamp * This routine is called at each PPS interrupt in order to discipline 6246f70df15SPoul-Henning Kamp * the CPU clock oscillator to the PPS signal. It measures the PPS phase 6256f70df15SPoul-Henning Kamp * and leaves it in a handy spot for the hardclock() routine. It 6266f70df15SPoul-Henning Kamp * integrates successive PPS phase differences and calculates the 6276f70df15SPoul-Henning Kamp * frequency offset. This is used in hardclock() to discipline the CPU 6286f70df15SPoul-Henning Kamp * clock oscillator so that intrinsic frequency error is cancelled out. 6296f70df15SPoul-Henning Kamp * The code requires the caller to capture the time and hardware counter 6306f70df15SPoul-Henning Kamp * value at the on-time PPS signal transition. 6316f70df15SPoul-Henning Kamp * 6326f70df15SPoul-Henning Kamp * Note that, on some Unix systems, this routine runs at an interrupt 6336f70df15SPoul-Henning Kamp * priority level higher than the timer interrupt routine hardclock(). 6346f70df15SPoul-Henning Kamp * Therefore, the variables used are distinct from the hardclock() 6356f70df15SPoul-Henning Kamp * variables, except for certain exceptions: The PPS frequency pps_freq 6366f70df15SPoul-Henning Kamp * and phase pps_offset variables are determined by this routine and 6376f70df15SPoul-Henning Kamp * updated atomically. The time_tolerance variable can be considered a 6386f70df15SPoul-Henning Kamp * constant, since it is infrequently changed, and then only when the 6396f70df15SPoul-Henning Kamp * PPS signal is disabled. The watchdog counter pps_valid is updated 6406f70df15SPoul-Henning Kamp * once per second by hardclock() and is atomically cleared in this 6416f70df15SPoul-Henning Kamp * routine. 6426f70df15SPoul-Henning Kamp */ 6436f70df15SPoul-Henning Kamp void 6446f70df15SPoul-Henning Kamp hardpps(tvp, p_usec) 6456f70df15SPoul-Henning Kamp struct timeval *tvp; /* time at PPS */ 6466f70df15SPoul-Henning Kamp long p_usec; /* hardware counter at PPS */ 6476f70df15SPoul-Henning Kamp { 6486f70df15SPoul-Henning Kamp long u_usec, v_usec, bigtick; 6496f70df15SPoul-Henning Kamp long cal_sec, cal_usec; 6506f70df15SPoul-Henning Kamp 6516f70df15SPoul-Henning Kamp /* 6526f70df15SPoul-Henning Kamp * An occasional glitch can be produced when the PPS interrupt 6536f70df15SPoul-Henning Kamp * occurs in the hardclock() routine before the time variable is 6546f70df15SPoul-Henning Kamp * updated. Here the offset is discarded when the difference 6556f70df15SPoul-Henning Kamp * between it and the last one is greater than tick/2, but not 6566f70df15SPoul-Henning Kamp * if the interval since the first discard exceeds 30 s. 6576f70df15SPoul-Henning Kamp */ 6586f70df15SPoul-Henning Kamp time_status |= STA_PPSSIGNAL; 6596f70df15SPoul-Henning Kamp time_status &= ~(STA_PPSJITTER | STA_PPSWANDER | STA_PPSERROR); 6606f70df15SPoul-Henning Kamp pps_valid = 0; 6616f70df15SPoul-Henning Kamp u_usec = -tvp->tv_usec; 6626f70df15SPoul-Henning Kamp if (u_usec < -500000) 6636f70df15SPoul-Henning Kamp u_usec += 1000000; 6646f70df15SPoul-Henning Kamp v_usec = pps_offset - u_usec; 6656f70df15SPoul-Henning Kamp if (v_usec < 0) 6666f70df15SPoul-Henning Kamp v_usec = -v_usec; 6676f70df15SPoul-Henning Kamp if (v_usec > (tick >> 1)) { 6686f70df15SPoul-Henning Kamp if (pps_glitch > MAXGLITCH) { 6696f70df15SPoul-Henning Kamp pps_glitch = 0; 6706f70df15SPoul-Henning Kamp pps_tf[2] = u_usec; 6716f70df15SPoul-Henning Kamp pps_tf[1] = u_usec; 6726f70df15SPoul-Henning Kamp } else { 6736f70df15SPoul-Henning Kamp pps_glitch++; 6746f70df15SPoul-Henning Kamp u_usec = pps_offset; 6756f70df15SPoul-Henning Kamp } 6766f70df15SPoul-Henning Kamp } else 6776f70df15SPoul-Henning Kamp pps_glitch = 0; 6786f70df15SPoul-Henning Kamp 6796f70df15SPoul-Henning Kamp /* 6806f70df15SPoul-Henning Kamp * A three-stage median filter is used to help deglitch the pps 6816f70df15SPoul-Henning Kamp * time. The median sample becomes the time offset estimate; the 6826f70df15SPoul-Henning Kamp * difference between the other two samples becomes the time 6836f70df15SPoul-Henning Kamp * dispersion (jitter) estimate. 6846f70df15SPoul-Henning Kamp */ 6856f70df15SPoul-Henning Kamp pps_tf[2] = pps_tf[1]; 6866f70df15SPoul-Henning Kamp pps_tf[1] = pps_tf[0]; 6876f70df15SPoul-Henning Kamp pps_tf[0] = u_usec; 6886f70df15SPoul-Henning Kamp MEDIAN3(pps_tf, pps_offset, v_usec); 6896f70df15SPoul-Henning Kamp if (v_usec > MAXTIME) 6906f70df15SPoul-Henning Kamp pps_jitcnt++; 6916f70df15SPoul-Henning Kamp v_usec = (v_usec << PPS_AVG) - pps_jitter; 6926f70df15SPoul-Henning Kamp if (v_usec < 0) 6936f70df15SPoul-Henning Kamp pps_jitter -= -v_usec >> PPS_AVG; 6946f70df15SPoul-Henning Kamp else 6956f70df15SPoul-Henning Kamp pps_jitter += v_usec >> PPS_AVG; 6966f70df15SPoul-Henning Kamp if (pps_jitter > (MAXTIME >> 1)) 6976f70df15SPoul-Henning Kamp time_status |= STA_PPSJITTER; 6986f70df15SPoul-Henning Kamp 6996f70df15SPoul-Henning Kamp /* 7006f70df15SPoul-Henning Kamp * During the calibration interval adjust the starting time when 7016f70df15SPoul-Henning Kamp * the tick overflows. At the end of the interval compute the 7026f70df15SPoul-Henning Kamp * duration of the interval and the difference of the hardware 7036f70df15SPoul-Henning Kamp * counters at the beginning and end of the interval. This code 7046f70df15SPoul-Henning Kamp * is deliciously complicated by the fact valid differences may 7056f70df15SPoul-Henning Kamp * exceed the value of tick when using long calibration 7066f70df15SPoul-Henning Kamp * intervals and small ticks. Note that the counter can be 7076f70df15SPoul-Henning Kamp * greater than tick if caught at just the wrong instant, but 7086f70df15SPoul-Henning Kamp * the values returned and used here are correct. 7096f70df15SPoul-Henning Kamp */ 7106f70df15SPoul-Henning Kamp bigtick = (long)tick << SHIFT_USEC; 7116f70df15SPoul-Henning Kamp pps_usec -= pps_freq; 7126f70df15SPoul-Henning Kamp if (pps_usec >= bigtick) 7136f70df15SPoul-Henning Kamp pps_usec -= bigtick; 7146f70df15SPoul-Henning Kamp if (pps_usec < 0) 7156f70df15SPoul-Henning Kamp pps_usec += bigtick; 7166f70df15SPoul-Henning Kamp pps_time.tv_sec++; 7176f70df15SPoul-Henning Kamp pps_count++; 7186f70df15SPoul-Henning Kamp if (pps_count < (1 << pps_shift)) 7196f70df15SPoul-Henning Kamp return; 7206f70df15SPoul-Henning Kamp pps_count = 0; 7216f70df15SPoul-Henning Kamp pps_calcnt++; 7226f70df15SPoul-Henning Kamp u_usec = p_usec << SHIFT_USEC; 7236f70df15SPoul-Henning Kamp v_usec = pps_usec - u_usec; 7246f70df15SPoul-Henning Kamp if (v_usec >= bigtick >> 1) 7256f70df15SPoul-Henning Kamp v_usec -= bigtick; 7266f70df15SPoul-Henning Kamp if (v_usec < -(bigtick >> 1)) 7276f70df15SPoul-Henning Kamp v_usec += bigtick; 7286f70df15SPoul-Henning Kamp if (v_usec < 0) 7296f70df15SPoul-Henning Kamp v_usec = -(-v_usec >> pps_shift); 7306f70df15SPoul-Henning Kamp else 7316f70df15SPoul-Henning Kamp v_usec = v_usec >> pps_shift; 7326f70df15SPoul-Henning Kamp pps_usec = u_usec; 7336f70df15SPoul-Henning Kamp cal_sec = tvp->tv_sec; 7346f70df15SPoul-Henning Kamp cal_usec = tvp->tv_usec; 7356f70df15SPoul-Henning Kamp cal_sec -= pps_time.tv_sec; 7366f70df15SPoul-Henning Kamp cal_usec -= pps_time.tv_usec; 7376f70df15SPoul-Henning Kamp if (cal_usec < 0) { 7386f70df15SPoul-Henning Kamp cal_usec += 1000000; 7396f70df15SPoul-Henning Kamp cal_sec--; 7406f70df15SPoul-Henning Kamp } 7416f70df15SPoul-Henning Kamp pps_time = *tvp; 7426f70df15SPoul-Henning Kamp 7436f70df15SPoul-Henning Kamp /* 7446f70df15SPoul-Henning Kamp * Check for lost interrupts, noise, excessive jitter and 7456f70df15SPoul-Henning Kamp * excessive frequency error. The number of timer ticks during 7466f70df15SPoul-Henning Kamp * the interval may vary +-1 tick. Add to this a margin of one 7476f70df15SPoul-Henning Kamp * tick for the PPS signal jitter and maximum frequency 7486f70df15SPoul-Henning Kamp * deviation. If the limits are exceeded, the calibration 7496f70df15SPoul-Henning Kamp * interval is reset to the minimum and we start over. 7506f70df15SPoul-Henning Kamp */ 7516f70df15SPoul-Henning Kamp u_usec = (long)tick << 1; 7526f70df15SPoul-Henning Kamp if (!((cal_sec == -1 && cal_usec > (1000000 - u_usec)) 7536f70df15SPoul-Henning Kamp || (cal_sec == 0 && cal_usec < u_usec)) 7546f70df15SPoul-Henning Kamp || v_usec > time_tolerance || v_usec < -time_tolerance) { 7556f70df15SPoul-Henning Kamp pps_errcnt++; 7566f70df15SPoul-Henning Kamp pps_shift = PPS_SHIFT; 7576f70df15SPoul-Henning Kamp pps_intcnt = 0; 7586f70df15SPoul-Henning Kamp time_status |= STA_PPSERROR; 7596f70df15SPoul-Henning Kamp return; 7606f70df15SPoul-Henning Kamp } 7616f70df15SPoul-Henning Kamp 7626f70df15SPoul-Henning Kamp /* 7636f70df15SPoul-Henning Kamp * A three-stage median filter is used to help deglitch the pps 7646f70df15SPoul-Henning Kamp * frequency. The median sample becomes the frequency offset 7656f70df15SPoul-Henning Kamp * estimate; the difference between the other two samples 7666f70df15SPoul-Henning Kamp * becomes the frequency dispersion (stability) estimate. 7676f70df15SPoul-Henning Kamp */ 7686f70df15SPoul-Henning Kamp pps_ff[2] = pps_ff[1]; 7696f70df15SPoul-Henning Kamp pps_ff[1] = pps_ff[0]; 7706f70df15SPoul-Henning Kamp pps_ff[0] = v_usec; 7716f70df15SPoul-Henning Kamp MEDIAN3(pps_ff, u_usec, v_usec); 7726f70df15SPoul-Henning Kamp 7736f70df15SPoul-Henning Kamp /* 7746f70df15SPoul-Henning Kamp * Here the frequency dispersion (stability) is updated. If it 7756f70df15SPoul-Henning Kamp * is less than one-fourth the maximum (MAXFREQ), the frequency 7766f70df15SPoul-Henning Kamp * offset is updated as well, but clamped to the tolerance. It 7776f70df15SPoul-Henning Kamp * will be processed later by the hardclock() routine. 7786f70df15SPoul-Henning Kamp */ 7796f70df15SPoul-Henning Kamp v_usec = (v_usec >> 1) - pps_stabil; 7806f70df15SPoul-Henning Kamp if (v_usec < 0) 7816f70df15SPoul-Henning Kamp pps_stabil -= -v_usec >> PPS_AVG; 7826f70df15SPoul-Henning Kamp else 7836f70df15SPoul-Henning Kamp pps_stabil += v_usec >> PPS_AVG; 7846f70df15SPoul-Henning Kamp if (pps_stabil > MAXFREQ >> 2) { 7856f70df15SPoul-Henning Kamp pps_stbcnt++; 7866f70df15SPoul-Henning Kamp time_status |= STA_PPSWANDER; 7876f70df15SPoul-Henning Kamp return; 7886f70df15SPoul-Henning Kamp } 7896f70df15SPoul-Henning Kamp if (time_status & STA_PPSFREQ) { 7906f70df15SPoul-Henning Kamp if (u_usec < 0) { 7916f70df15SPoul-Henning Kamp pps_freq -= -u_usec >> PPS_AVG; 7926f70df15SPoul-Henning Kamp if (pps_freq < -time_tolerance) 7936f70df15SPoul-Henning Kamp pps_freq = -time_tolerance; 7946f70df15SPoul-Henning Kamp u_usec = -u_usec; 7956f70df15SPoul-Henning Kamp } else { 7966f70df15SPoul-Henning Kamp pps_freq += u_usec >> PPS_AVG; 7976f70df15SPoul-Henning Kamp if (pps_freq > time_tolerance) 7986f70df15SPoul-Henning Kamp pps_freq = time_tolerance; 7996f70df15SPoul-Henning Kamp } 8006f70df15SPoul-Henning Kamp } 8016f70df15SPoul-Henning Kamp 8026f70df15SPoul-Henning Kamp /* 8036f70df15SPoul-Henning Kamp * Here the calibration interval is adjusted. If the maximum 8046f70df15SPoul-Henning Kamp * time difference is greater than tick / 4, reduce the interval 8056f70df15SPoul-Henning Kamp * by half. If this is not the case for four consecutive 8066f70df15SPoul-Henning Kamp * intervals, double the interval. 8076f70df15SPoul-Henning Kamp */ 8086f70df15SPoul-Henning Kamp if (u_usec << pps_shift > bigtick >> 2) { 8096f70df15SPoul-Henning Kamp pps_intcnt = 0; 8106f70df15SPoul-Henning Kamp if (pps_shift > PPS_SHIFT) 8116f70df15SPoul-Henning Kamp pps_shift--; 8126f70df15SPoul-Henning Kamp } else if (pps_intcnt >= 4) { 8136f70df15SPoul-Henning Kamp pps_intcnt = 0; 8146f70df15SPoul-Henning Kamp if (pps_shift < PPS_SHIFTMAX) 8156f70df15SPoul-Henning Kamp pps_shift++; 8166f70df15SPoul-Henning Kamp } else 8176f70df15SPoul-Henning Kamp pps_intcnt++; 8186f70df15SPoul-Henning Kamp } 8199ada5a50SPoul-Henning Kamp 8206f70df15SPoul-Henning Kamp #endif /* PPS_SYNC */ 821938ee3ceSPoul-Henning Kamp 822938ee3ceSPoul-Henning Kamp int 823938ee3ceSPoul-Henning Kamp std_pps_ioctl(u_long cmd, caddr_t data, pps_params_t *pp, pps_info_t *pi, int ppscap) 824938ee3ceSPoul-Henning Kamp { 825938ee3ceSPoul-Henning Kamp pps_params_t *app; 826938ee3ceSPoul-Henning Kamp pps_info_t *api; 827938ee3ceSPoul-Henning Kamp 828938ee3ceSPoul-Henning Kamp switch (cmd) { 829938ee3ceSPoul-Henning Kamp case PPS_IOC_CREATE: 830938ee3ceSPoul-Henning Kamp return (0); 831938ee3ceSPoul-Henning Kamp case PPS_IOC_DESTROY: 832938ee3ceSPoul-Henning Kamp return (0); 833938ee3ceSPoul-Henning Kamp case PPS_IOC_SETPARAMS: 834938ee3ceSPoul-Henning Kamp app = (pps_params_t *)data; 835938ee3ceSPoul-Henning Kamp if (app->mode & ~ppscap) 836938ee3ceSPoul-Henning Kamp return (EINVAL); 837938ee3ceSPoul-Henning Kamp *pp = *app; 838938ee3ceSPoul-Henning Kamp return (0); 839938ee3ceSPoul-Henning Kamp case PPS_IOC_GETPARAMS: 840938ee3ceSPoul-Henning Kamp app = (pps_params_t *)data; 841938ee3ceSPoul-Henning Kamp *app = *pp; 842938ee3ceSPoul-Henning Kamp return (0); 843938ee3ceSPoul-Henning Kamp case PPS_IOC_GETCAP: 844938ee3ceSPoul-Henning Kamp *(int*)data = ppscap; 845938ee3ceSPoul-Henning Kamp return (0); 846938ee3ceSPoul-Henning Kamp case PPS_IOC_FETCH: 847938ee3ceSPoul-Henning Kamp api = (pps_info_t *)data; 848938ee3ceSPoul-Henning Kamp *api = *pi; 849938ee3ceSPoul-Henning Kamp pi->current_mode = pp->mode; 850938ee3ceSPoul-Henning Kamp return (0); 851938ee3ceSPoul-Henning Kamp case PPS_IOC_WAIT: 852938ee3ceSPoul-Henning Kamp return (EOPNOTSUPP); 853938ee3ceSPoul-Henning Kamp default: 854938ee3ceSPoul-Henning Kamp return (ENODEV); 855938ee3ceSPoul-Henning Kamp } 856938ee3ceSPoul-Henning Kamp } 857