summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_tc.c
diff options
context:
space:
mode:
authorlstewart <lstewart@FreeBSD.org>2011-11-21 13:34:29 +0000
committerlstewart <lstewart@FreeBSD.org>2011-11-21 13:34:29 +0000
commit09887e1dc59517a663f8c91773f1c14f4fdf069d (patch)
treea4ba0cb7247e0f91775a586bd52518db93b7fe95 /sys/kern/kern_tc.c
parentb95134ea01e46b282074a03ea01be1fc9d95a328 (diff)
downloadFreeBSD-src-09887e1dc59517a663f8c91773f1c14f4fdf069d.zip
FreeBSD-src-09887e1dc59517a663f8c91773f1c14f4fdf069d.tar.gz
- Add Pulse-Per-Second timestamping using raw ffcounter and corresponding
ffclock time in seconds. - Add IOCTL to retrieve ffclock timestamps from userland. Committed on behalf of Julien Ridoux and Darryl Veitch from the University of Melbourne, Australia, as part of the FreeBSD Foundation funded "Feed-Forward Clock Synchronization Algorithms" project. For more information, see http://www.synclab.org/radclock/ Submitted by: Julien Ridoux (jridoux at unimelb edu au)
Diffstat (limited to 'sys/kern/kern_tc.c')
-rw-r--r--sys/kern/kern_tc.c65
1 files changed, 65 insertions, 0 deletions
diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c
index 66e26d0..e5db8d9 100644
--- a/sys/kern/kern_tc.c
+++ b/sys/kern/kern_tc.c
@@ -1365,6 +1365,9 @@ pps_ioctl(u_long cmd, caddr_t data, struct pps_state *pps)
{
pps_params_t *app;
struct pps_fetch_args *fapi;
+#ifdef FFCLOCK
+ struct pps_fetch_ffc_args *fapi_ffc;
+#endif
#ifdef PPS_SYNC
struct pps_kcbind_args *kapi;
#endif
@@ -1379,6 +1382,11 @@ pps_ioctl(u_long cmd, caddr_t data, struct pps_state *pps)
app = (pps_params_t *)data;
if (app->mode & ~pps->ppscap)
return (EINVAL);
+#ifdef FFCLOCK
+ /* Ensure only a single clock is selected for ffc timestamp. */
+ if ((app->mode & PPS_TSCLK_MASK) == PPS_TSCLK_MASK)
+ return (EINVAL);
+#endif
pps->ppsparam = *app;
return (0);
case PPS_IOC_GETPARAMS:
@@ -1398,6 +1406,31 @@ pps_ioctl(u_long cmd, caddr_t data, struct pps_state *pps)
pps->ppsinfo.current_mode = pps->ppsparam.mode;
fapi->pps_info_buf = pps->ppsinfo;
return (0);
+#ifdef FFCLOCK
+ case PPS_IOC_FETCH_FFCOUNTER:
+ fapi_ffc = (struct pps_fetch_ffc_args *)data;
+ if (fapi_ffc->tsformat && fapi_ffc->tsformat !=
+ PPS_TSFMT_TSPEC)
+ return (EINVAL);
+ if (fapi_ffc->timeout.tv_sec || fapi_ffc->timeout.tv_nsec)
+ return (EOPNOTSUPP);
+ pps->ppsinfo_ffc.current_mode = pps->ppsparam.mode;
+ fapi_ffc->pps_info_buf_ffc = pps->ppsinfo_ffc;
+ /* Overwrite timestamps if feedback clock selected. */
+ switch (pps->ppsparam.mode & PPS_TSCLK_MASK) {
+ case PPS_TSCLK_FBCK:
+ fapi_ffc->pps_info_buf_ffc.assert_timestamp =
+ pps->ppsinfo.assert_timestamp;
+ fapi_ffc->pps_info_buf_ffc.clear_timestamp =
+ pps->ppsinfo.clear_timestamp;
+ break;
+ case PPS_TSCLK_FFWD:
+ break;
+ default:
+ break;
+ }
+ return (0);
+#endif /* FFCLOCK */
case PPS_IOC_KCBIND:
#ifdef PPS_SYNC
kapi = (struct pps_kcbind_args *)data;
@@ -1426,6 +1459,9 @@ pps_init(struct pps_state *pps)
pps->ppscap |= PPS_OFFSETASSERT;
if (pps->ppscap & PPS_CAPTURECLEAR)
pps->ppscap |= PPS_OFFSETCLEAR;
+#ifdef FFCLOCK
+ pps->ppscap |= PPS_TSCLK_MASK;
+#endif
}
void
@@ -1437,6 +1473,9 @@ pps_capture(struct pps_state *pps)
th = timehands;
pps->capgen = th->th_generation;
pps->capth = th;
+#ifdef FFCLOCK
+ pps->capffth = fftimehands;
+#endif
pps->capcount = th->th_counter->tc_get_timecount(th->th_counter);
if (pps->capgen != th->th_generation)
pps->capgen = 0;
@@ -1450,6 +1489,11 @@ pps_event(struct pps_state *pps, int event)
u_int tcount, *pcount;
int foff, fhard;
pps_seq_t *pseq;
+#ifdef FFCLOCK
+ struct timespec *tsp_ffc;
+ pps_seq_t *pseq_ffc;
+ ffcounter *ffcount;
+#endif
KASSERT(pps != NULL, ("NULL pps pointer in pps_event"));
/* If the timecounter was wound up underneath us, bail out. */
@@ -1464,6 +1508,11 @@ pps_event(struct pps_state *pps, int event)
fhard = pps->kcmode & PPS_CAPTUREASSERT;
pcount = &pps->ppscount[0];
pseq = &pps->ppsinfo.assert_sequence;
+#ifdef FFCLOCK
+ ffcount = &pps->ppsinfo_ffc.assert_ffcount;
+ tsp_ffc = &pps->ppsinfo_ffc.assert_timestamp;
+ pseq_ffc = &pps->ppsinfo_ffc.assert_sequence;
+#endif
} else {
tsp = &pps->ppsinfo.clear_timestamp;
osp = &pps->ppsparam.clear_offset;
@@ -1471,6 +1520,11 @@ pps_event(struct pps_state *pps, int event)
fhard = pps->kcmode & PPS_CAPTURECLEAR;
pcount = &pps->ppscount[1];
pseq = &pps->ppsinfo.clear_sequence;
+#ifdef FFCLOCK
+ ffcount = &pps->ppsinfo_ffc.clear_ffcount;
+ tsp_ffc = &pps->ppsinfo_ffc.clear_timestamp;
+ pseq_ffc = &pps->ppsinfo_ffc.clear_sequence;
+#endif
}
/*
@@ -1507,6 +1561,17 @@ pps_event(struct pps_state *pps, int event)
tsp->tv_sec -= 1;
}
}
+
+#ifdef FFCLOCK
+ *ffcount = pps->capffth->tick_ffcount + tcount;
+ bt = pps->capffth->tick_time;
+ ffclock_convert_delta(tcount, pps->capffth->cest.period, &bt);
+ bintime_add(&bt, &pps->capffth->tick_time);
+ bintime2timespec(&bt, &ts);
+ (*pseq_ffc)++;
+ *tsp_ffc = ts;
+#endif
+
#ifdef PPS_SYNC
if (fhard) {
uint64_t scale;
OpenPOWER on IntegriCloud