243 lines
5.4 KiB
C
243 lines
5.4 KiB
C
/*
|
|
chronyd/chronyc - Programs for keeping computer clocks accurate.
|
|
|
|
**********************************************************************
|
|
* Copyright (C) Richard P. Curnow 1997-2002
|
|
* Copyright (C) Miroslav Lichvar 2011
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of version 2 of the GNU General Public License as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
**********************************************************************
|
|
|
|
=======================================================================
|
|
|
|
This is a wrapper around the Linux adjtimex system call. It isolates the
|
|
inclusion of <linux/adjtimex.h> from the need to include other header files,
|
|
many of which conflict with those in <linux/...> on some recent distributions
|
|
(as of Jul 2000) using kernels around 2.2.16 onwards.
|
|
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#ifdef LINUX
|
|
|
|
#define _LOOSE_KERNEL_NAMES
|
|
|
|
#include "chrony_timex.h"
|
|
#include "wrap_adjtimex.h"
|
|
|
|
static int status = 0;
|
|
|
|
int
|
|
TMX_SetTick(long tick)
|
|
{
|
|
struct timex txc;
|
|
txc.modes = ADJ_TICK;
|
|
txc.tick = tick;
|
|
|
|
return adjtimex(&txc);
|
|
}
|
|
|
|
int
|
|
TMX_ApplyOffset(long *offset)
|
|
{
|
|
struct timex txc;
|
|
int result;
|
|
|
|
txc.modes = ADJ_OFFSET_SINGLESHOT;
|
|
txc.offset = *offset;
|
|
result = adjtimex(&txc);
|
|
*offset = txc.offset;
|
|
return result;
|
|
}
|
|
|
|
int
|
|
TMX_SetFrequency(double *freq, long tick)
|
|
{
|
|
struct timex txc;
|
|
|
|
txc.modes = ADJ_TICK | ADJ_FREQUENCY | ADJ_STATUS;
|
|
|
|
txc.freq = (long)(*freq * (double)(1 << SHIFT_USEC));
|
|
*freq = txc.freq / (double)(1 << SHIFT_USEC);
|
|
txc.tick = tick;
|
|
txc.status = status;
|
|
|
|
if (!(status & STA_UNSYNC)) {
|
|
/* maxerror has to be reset periodically to prevent kernel
|
|
from enabling UNSYNC flag */
|
|
txc.modes |= ADJ_MAXERROR;
|
|
txc.maxerror = 0;
|
|
}
|
|
|
|
return adjtimex(&txc);
|
|
}
|
|
|
|
int
|
|
TMX_GetFrequency(double *freq)
|
|
{
|
|
struct timex txc;
|
|
int result;
|
|
txc.modes = 0; /* pure read */
|
|
result = adjtimex(&txc);
|
|
*freq = txc.freq / (double)(1 << SHIFT_USEC);
|
|
return result;
|
|
}
|
|
|
|
int
|
|
TMX_GetOffsetLeftOld(long *offset)
|
|
{
|
|
struct timex txc;
|
|
int result;
|
|
txc.modes = 0; /* pure read */
|
|
result = adjtimex(&txc);
|
|
*offset = txc.offset;
|
|
return result;
|
|
}
|
|
|
|
int
|
|
TMX_GetOffsetLeft(long *offset)
|
|
{
|
|
struct timex txc;
|
|
int result;
|
|
txc.modes = ADJ_OFFSET_SS_READ;
|
|
result = adjtimex(&txc);
|
|
*offset = txc.offset;
|
|
return result;
|
|
}
|
|
|
|
int
|
|
TMX_ReadCurrentParams(struct tmx_params *params)
|
|
{
|
|
struct timex txc;
|
|
int result;
|
|
|
|
txc.modes = 0; /* pure read */
|
|
result = adjtimex(&txc);
|
|
|
|
params->tick = txc.tick;
|
|
params->offset = txc.offset;
|
|
params->freq = txc.freq;
|
|
params->dfreq = txc.freq / (double)(1 << SHIFT_USEC);
|
|
params->maxerror = txc.maxerror;
|
|
params->esterror = txc.esterror;
|
|
|
|
params->sta_pll = !!(txc.status & STA_PLL);
|
|
params->sta_ppsfreq = !!(txc.status & STA_PPSFREQ);
|
|
params->sta_ppstime = !!(txc.status & STA_PPSTIME);
|
|
params->sta_fll = !!(txc.status & STA_FLL);
|
|
params->sta_ins = !!(txc.status & STA_INS);
|
|
params->sta_del = !!(txc.status & STA_DEL);
|
|
params->sta_unsync = !!(txc.status & STA_UNSYNC);
|
|
params->sta_freqhold = !!(txc.status & STA_FREQHOLD);
|
|
params->sta_ppssignal = !!(txc.status & STA_PPSSIGNAL);
|
|
params->sta_ppsjitter = !!(txc.status & STA_PPSJITTER);
|
|
params->sta_ppswander = !!(txc.status & STA_PPSWANDER);
|
|
params->sta_ppserror = !!(txc.status & STA_PPSERROR);
|
|
params->sta_clockerr = !!(txc.status & STA_CLOCKERR);
|
|
|
|
params->constant = txc.constant;
|
|
params->precision = txc.precision;
|
|
params->tolerance = txc.tolerance;
|
|
params->ppsfreq = txc.ppsfreq;
|
|
params->jitter = txc.jitter;
|
|
params->shift = txc.shift;
|
|
params->stabil = txc.stabil;
|
|
params->jitcnt = txc.jitcnt;
|
|
params->calcnt = txc.calcnt;
|
|
params->errcnt = txc.errcnt;
|
|
params->stbcnt = txc.stbcnt;
|
|
|
|
return result;
|
|
}
|
|
|
|
int
|
|
TMX_SetLeap(int leap)
|
|
{
|
|
struct timex txc;
|
|
|
|
status &= ~(STA_INS | STA_DEL);
|
|
|
|
if (leap > 0) {
|
|
status |= STA_INS;
|
|
} else if (leap < 0) {
|
|
status |= STA_DEL;
|
|
}
|
|
|
|
txc.modes = ADJ_STATUS;
|
|
txc.status = status;
|
|
|
|
return adjtimex(&txc);
|
|
}
|
|
|
|
int TMX_SetSync(int sync)
|
|
{
|
|
struct timex txc;
|
|
|
|
if (sync) {
|
|
status &= ~STA_UNSYNC;
|
|
} else {
|
|
status |= STA_UNSYNC;
|
|
}
|
|
|
|
txc.modes = ADJ_STATUS;
|
|
txc.status = status;
|
|
|
|
return adjtimex(&txc);
|
|
}
|
|
|
|
int
|
|
TMX_EnableNanoPLL(void)
|
|
{
|
|
struct timex txc;
|
|
int result;
|
|
|
|
txc.modes = ADJ_STATUS | ADJ_OFFSET | ADJ_TIMECONST | ADJ_NANO;
|
|
txc.status = STA_PLL | STA_FREQHOLD;
|
|
txc.offset = 0;
|
|
txc.constant = 0;
|
|
result = adjtimex(&txc);
|
|
if (result < 0 || !(txc.status & STA_NANO) || txc.offset || txc.constant)
|
|
return -1;
|
|
|
|
status |= STA_PLL | STA_FREQHOLD;
|
|
return result;
|
|
}
|
|
|
|
int
|
|
TMX_ApplyPLLOffset(long offset)
|
|
{
|
|
struct timex txc;
|
|
|
|
txc.modes = ADJ_OFFSET | ADJ_TIMECONST | ADJ_NANO;
|
|
txc.offset = offset;
|
|
txc.constant = 0;
|
|
return adjtimex(&txc);
|
|
}
|
|
|
|
int
|
|
TMX_GetPLLOffsetLeft(long *offset)
|
|
{
|
|
struct timex txc;
|
|
int result;
|
|
|
|
txc.modes = 0;
|
|
result = adjtimex(&txc);
|
|
*offset = txc.offset;
|
|
return result;
|
|
}
|
|
|
|
#endif
|
|
|