Commit fe4470bb authored by Alessandro Rubini's avatar Alessandro Rubini

support changing UTC/TAI offset

This patch adds support for modifying the utc/tai offset. The
"set" time operation, when called with a NULL pointer to the time
structure, will do the operation in its own arch-specific way.
Signed-off-by: Alessandro Rubini's avatarAlessandro Rubini <rubini@gnudd.com>
parent c842f754
......@@ -155,7 +155,7 @@ extern struct pp_network_operations unix_net_ops;
* Time operations, like network operations above, are encapsulated.
* They may live in their own time-<name> subdirectory.
*
* Maybe this structure will need updating, to pass ppi as well
* If "set" receives a NULL time value, it should update the TAI offset.
*/
struct pp_time_operations {
int (*get)(struct pp_instance *ppi, TimeInternal *t);
......
......@@ -61,10 +61,12 @@ static void s1(struct pp_instance *ppi, MsgHeader *hdr, MsgAnnounce *ann)
/* Timeproperties DS */
prop->timeSource = ann->timeSource;
if (prop->currentUtcOffset != ann->currentUtcOffset)
if (prop->currentUtcOffset != ann->currentUtcOffset) {
pp_diag(ppi, bmc, 1, "New UTC offset: %i\n",
ann->currentUtcOffset);
prop->currentUtcOffset = ann->currentUtcOffset;
prop->currentUtcOffset = ann->currentUtcOffset;
ppi->t_ops->set(ppi, NULL);
}
/* FIXME: can't we just copy the bit keeping values? */
prop->currentUtcOffsetValid = ((hdr->flagField[1] & FFB_UTCV) != 0);
......
......@@ -29,6 +29,19 @@ static int bare_time_set(struct pp_instance *ppi, TimeInternal *t)
{
struct bare_timeval tv;
if (!t) { /* Change the network notion of the utc/tai offset */
struct bare_timex t;
t.modes = MOD_TAI;
t.constant = DSPRO(ppi)->currentUtcOffset;
if (sys_adjtimex(&t) < 0)
pp_diag(ppi, time, 1, "Can't change TAI offset");
else
pp_diag(ppi, time, 1, "New TAI offset: %i\n",
DSPRO(ppi)->currentUtcOffset);
return 0;
}
/* UTC = TAI - 34 */
tv.tv_sec = t->seconds - DSPRO(ppi)->currentUtcOffset;
tv.tv_usec = t->nanoseconds / 1000;
......
......@@ -12,6 +12,10 @@
#include <sys/timex.h>
#include <ppsi/ppsi.h>
#ifndef MOD_TAI
#define MOD_TAI 0x80
#endif
static void clock_fatal_error(char *context)
{
pp_error("failure in \"%s\": %s\n.Exiting.\n", context,
......@@ -34,10 +38,22 @@ static int unix_time_get(struct pp_instance *ppi, TimeInternal *t)
return 0;
}
static int32_t unix_time_set(struct pp_instance *ppi, TimeInternal *t)
static int unix_time_set(struct pp_instance *ppi, TimeInternal *t)
{
struct timespec tp;
if (!t) { /* Change the network notion of the utc/tai offset */
struct timex t;
t.modes = MOD_TAI;
t.constant = DSPRO(ppi)->currentUtcOffset;
if (adjtimex(&t) < 0)
clock_fatal_error("change TAI offset");
pp_diag(ppi, time, 1, "New TAI offset: %i\n",
DSPRO(ppi)->currentUtcOffset);
return 0;
}
/* UTC = TAI - 34 */
tp.tv_sec = t->seconds - DSPRO(ppi)->currentUtcOffset;
tp.tv_nsec = t->nanoseconds;
......
......@@ -29,6 +29,9 @@ static int wrpc_time_set(struct pp_instance *ppi, TimeInternal *t)
uint64_t sec;
unsigned long nsec;
if (!t) /* tai offset changed. We don't have it in wrpc-sw */
return 0;
sec = t->seconds;
nsec = t->nanoseconds;
......
......@@ -195,15 +195,17 @@ static int wrs_time_get(struct pp_instance *ppi, TimeInternal *t)
return rval;
}
static int32_t wrs_time_set(struct pp_instance *ppi, TimeInternal *t)
static int wrs_time_set(struct pp_instance *ppi, TimeInternal *t)
{
TimeInternal diff;
/*
* This is almost unused in ppsi, only proto-standard/servo.c
* calls it, at initialization time, when the offset is bigger
* than one second. Run this transient by just adjusting the
* WR seconds. Later on it will fix the nanos by ->adjust
* than one second. Or ...
*/
if (!t) /* ... when the utc/tai offset changes, if t is NULL */
return unix_time_ops.set(ppi, t);
pp_diag(ppi, time, 1, "%s: (weird) %9li.%09li\n", __func__,
(long)t->seconds, (long)t->nanoseconds);
/* We have no way to get the WR time, currently. So use our T3 */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment