summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>1999-03-11 15:09:51 +0000
committerphk <phk@FreeBSD.org>1999-03-11 15:09:51 +0000
commit1542a4a4974b31d78a2115e37a802c377265be93 (patch)
tree59c54f6ab6826395ea6c20a6d0d12cb2be4bc943
parent9c47f49734c0ff3b3d666a5a7a2bb329444223f1 (diff)
downloadFreeBSD-src-1542a4a4974b31d78a2115e37a802c377265be93.zip
FreeBSD-src-1542a4a4974b31d78a2115e37a802c377265be93.tar.gz
Make even more of the PPSAPI implementations generic.
FLL support in hardpps() Various magic shuffles and improved comments Style fixes from Bruce.
-rw-r--r--sys/dev/ppbus/pps.c75
-rw-r--r--sys/kern/kern_clock.c199
-rw-r--r--sys/kern/kern_ntptime.c51
-rw-r--r--sys/kern/kern_tc.c199
-rw-r--r--sys/pci/xrpu.c79
-rw-r--r--sys/sys/systm.h4
-rw-r--r--sys/sys/time.h3
-rw-r--r--sys/sys/timepps.h85
-rw-r--r--sys/sys/timetc.h3
-rw-r--r--sys/sys/timex.h27
10 files changed, 448 insertions, 277 deletions
diff --git a/sys/dev/ppbus/pps.c b/sys/dev/ppbus/pps.c
index 24be094..f507143 100644
--- a/sys/dev/ppbus/pps.c
+++ b/sys/dev/ppbus/pps.c
@@ -6,7 +6,7 @@
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
* ----------------------------------------------------------------------------
*
- * $Id: pps.c,v 1.12 1998/12/07 21:58:16 archie Exp $
+ * $Id: pps.c,v 1.13 1999/01/30 15:35:39 nsouch Exp $
*
* This driver implements a draft-mogul-pps-api-02.txt PPS source.
*
@@ -16,7 +16,6 @@
*/
#include "opt_devfs.h"
-#include "opt_ntp.h"
#include <sys/param.h>
#include <sys/kernel.h>
@@ -36,20 +35,11 @@
static struct pps_data {
int pps_unit;
struct ppb_device pps_dev;
- pps_params_t ppsparam;
- pps_info_t ppsinfo;
+ struct pps_state pps;
} *softc[NPPS];
-static int ppscap =
- PPS_CAPTUREASSERT |
-#ifdef PPS_SYNC
- PPS_HARDPPSONASSERT |
-#endif /* PPS_SYNC */
- PPS_OFFSETASSERT |
- PPS_ECHOASSERT |
- PPS_TSFMT_TSPEC;
-
static int npps;
+static pps_devsw_installed = 0;
/*
* Make ourselves visible as a ppbus driver
@@ -77,6 +67,7 @@ static struct cdevsw pps_cdevsw =
seltrue, nommap, nostrat, PPS_NAME,
NULL, -1 };
+
static struct ppb_device *
ppsprobe(struct ppb_data *ppb)
{
@@ -99,12 +90,16 @@ ppsprobe(struct ppb_data *ppb)
sc->pps_dev.name = ppsdriver.name;
sc->pps_dev.intr = ppsintr;
+ sc->pps.ppscap = PPS_CAPTUREASSERT | PPS_ECHOASSERT;
+ pps_init(&sc->pps);
return (&sc->pps_dev);
}
static int
ppsattach(struct ppb_device *dev)
{
+ dev_t devt;
+
/*
* Report ourselves
*/
@@ -116,7 +111,11 @@ ppsattach(struct ppb_device *dev)
dev->id_unit, DV_CHR,
UID_ROOT, GID_WHEEL, 0600, PPS_NAME "%d", dev->id_unit);
#endif
-
+ if( ! pps_devsw_installed ) {
+ devt = makedev(CDEV_MAJOR, 0);
+ cdevsw_add(&devt, &pps_cdevsw, NULL);
+ pps_devsw_installed = 1;
+ }
return (1);
}
@@ -145,7 +144,7 @@ ppsclose(dev_t dev, int flags, int fmt, struct proc *p)
{
struct pps_data *sc = softc[minor(dev)];
- sc->ppsparam.mode = 0;
+ sc->pps.ppsparam.mode = 0; /* PHK ??? */
ppb_wdtr(&sc->pps_dev, 0);
ppb_wctr(&sc->pps_dev, 0);
@@ -158,32 +157,17 @@ static void
ppsintr(int unit)
{
struct pps_data *sc = softc[unit];
- struct timespec tc;
+ struct timecounter *tc;
+ unsigned count;
- nanotime(&tc);
+ tc = timecounter;
+ count = timecounter->tc_get_timecount(tc);
if (!(ppb_rstr(&sc->pps_dev) & nACK))
return;
- if (sc->ppsparam.mode & PPS_ECHOASSERT)
+ if (sc->pps.ppsparam.mode & PPS_ECHOASSERT)
ppb_wctr(&sc->pps_dev, IRQENABLE | AUTOFEED);
- if (sc->ppsparam.mode & PPS_OFFSETASSERT) {
- timespecadd(&tc, &sc->ppsparam.assert_offset);
- if (tc.tv_nsec < 0) {
- tc.tv_sec--;
- tc.tv_nsec += 1000000000;
- }
- }
- sc->ppsinfo.assert_timestamp = tc;
- sc->ppsinfo.assert_sequence++;
-#ifdef PPS_SYNC
- if (sc->ppsparam.mode & PPS_HARDPPSONASSERT) {
- struct timeval tv;
-
- tv.tv_sec = tc.tv_sec;
- tv.tv_usec = tc.tv_nsec / 1000;
- hardpps(&tv, tv.tv_usec);
- }
-#endif /* PPS_SYNC */
- if (sc->ppsparam.mode & PPS_ECHOASSERT)
+ pps_event(&sc->pps, tc, count, PPS_CAPTUREASSERT);
+ if (sc->pps.ppsparam.mode & PPS_ECHOASSERT)
ppb_wctr(&sc->pps_dev, IRQENABLE);
}
@@ -192,21 +176,6 @@ ppsioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
{
struct pps_data *sc = softc[minor(dev)];
- return (std_pps_ioctl(cmd, data, &sc->ppsparam, &sc->ppsinfo, ppscap));
-}
-
-static pps_devsw_installed = 0;
-
-static void
-pps_drvinit(void *unused)
-{
- dev_t dev;
-
- if( ! pps_devsw_installed ) {
- dev = makedev(CDEV_MAJOR, 0);
- cdevsw_add(&dev, &pps_cdevsw, NULL);
- pps_devsw_installed = 1;
- }
+ return (pps_ioctl(cmd, data, &sc->pps));
}
-SYSINIT(ppsdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,pps_drvinit,NULL)
diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c
index 1c536ee..da424e5 100644
--- a/sys/kern/kern_clock.c
+++ b/sys/kern/kern_clock.c
@@ -37,9 +37,11 @@
* SUCH DAMAGE.
*
* @(#)kern_clock.c 8.5 (Berkeley) 1/21/94
- * $Id: kern_clock.c,v 1.88 1999/02/19 19:34:49 luoqi Exp $
+ * $Id: kern_clock.c,v 1.89 1999/03/08 12:35:58 phk Exp $
*/
+#include "opt_ntp.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/dkstat.h>
@@ -50,6 +52,7 @@
#include <sys/resourcevar.h>
#include <sys/signalvar.h>
#include <sys/timex.h>
+#include <sys/timepps.h>
#include <vm/vm.h>
#include <sys/lock.h>
#include <vm/pmap.h>
@@ -509,11 +512,14 @@ tco_delta(struct timecounter *tc)
}
/*
- * We have four functions for looking at the clock, two for microseconds
- * and two for nanoseconds. For each there is fast but less precise
- * version "get{nano|micro}time" which will return a time which is up
- * to 1/HZ previous to the call, whereas the raw version "{nano|micro}time"
- * will return a timestamp which is as precise as possible.
+ * We have eight functions for looking at the clock, four for
+ * microseconds and four for nanoseconds. For each there is fast
+ * but less precise version "get{nano|micro}[up]time" which will
+ * return a time which is up to 1/HZ previous to the call, whereas
+ * the raw version "{nano|micro}[up]time" will return a timestamp
+ * which is as precise as possible. The "up" variants return the
+ * time relative to system boot, these are well suited for time
+ * interval measurements.
*/
void
@@ -583,29 +589,6 @@ nanotime(struct timespec *ts)
}
void
-timecounter_timespec(unsigned count, struct timespec *ts)
-{
- u_int64_t delta;
- struct timecounter *tc;
-
- tc = (struct timecounter *)timecounter;
- ts->tv_sec = tc->tc_offset_sec;
- count -= tc->tc_offset_count;
- count &= tc->tc_counter_mask;
- delta = tc->tc_offset_nano;
- delta += ((u_int64_t)count * tc->tc_scale_nano_f);
- delta >>= 32;
- delta += ((u_int64_t)count * tc->tc_scale_nano_i);
- delta += boottime.tv_usec * 1000;
- ts->tv_sec += boottime.tv_sec;
- while (delta >= 1000000000) {
- delta -= 1000000000;
- ts->tv_sec++;
- }
- ts->tv_nsec = delta;
-}
-
-void
getmicrouptime(struct timeval *tvp)
{
struct timecounter *tc;
@@ -805,8 +788,6 @@ tco_forward(int force)
while (tc->tc_offset_nano >= 1000000000ULL << 32) {
tc->tc_offset_nano -= 1000000000ULL << 32;
tc->tc_offset_sec++;
- tc->tc_frequency = tc->tc_tweak->tc_frequency;
- tc->tc_adjustment = tc->tc_tweak->tc_adjustment;
ntp_update_second(tc); /* XXX only needed if xntpd runs */
tco_setscales(tc);
force++;
@@ -832,35 +813,149 @@ tco_forward(int force)
timecounter = tc;
}
-static int
-sysctl_kern_timecounter_frequency SYSCTL_HANDLER_ARGS
+SYSCTL_NODE(_kern, OID_AUTO, timecounter, CTLFLAG_RW, 0, "");
+
+SYSCTL_INT(_kern_timecounter, KERN_ARGMAX, method, CTLFLAG_RW, &tco_method, 0,
+ "This variable determines the method used for updating timecounters. "
+ "If the default algorithm (0) fails with \"calcru negative...\" messages "
+ "try the alternate algorithm (1) which handles bad hardware better."
+
+);
+
+
+int
+pps_ioctl(u_long cmd, caddr_t data, struct pps_state *pps)
{
+ pps_params_t *app;
+ pps_info_t *api;
+
+ switch (cmd) {
+ case PPS_IOC_CREATE:
+ return (0);
+ case PPS_IOC_DESTROY:
+ return (0);
+ case PPS_IOC_SETPARAMS:
+ app = (pps_params_t *)data;
+ if (app->mode & ~pps->ppscap)
+ return (EINVAL);
+ pps->ppsparam = *app;
+ return (0);
+ case PPS_IOC_GETPARAMS:
+ app = (pps_params_t *)data;
+ *app = pps->ppsparam;
+ return (0);
+ case PPS_IOC_GETCAP:
+ *(int*)data = pps->ppscap;
+ return (0);
+ case PPS_IOC_FETCH:
+ api = (pps_info_t *)data;
+ pps->ppsinfo.current_mode = pps->ppsparam.mode;
+ *api = pps->ppsinfo;
+ return (0);
+ case PPS_IOC_WAIT:
+ return (EOPNOTSUPP);
+ default:
+ return (ENOTTY);
+ }
+}
- return (sysctl_handle_opaque(oidp,
- &timecounter->tc_tweak->tc_frequency,
- sizeof(timecounter->tc_tweak->tc_frequency), req));
+void
+pps_init(struct pps_state *pps)
+{
+ pps->ppscap |= PPS_TSFMT_TSPEC;
+ if (pps->ppscap & PPS_CAPTUREASSERT)
+ pps->ppscap |= PPS_OFFSETASSERT;
+ if (pps->ppscap & PPS_CAPTURECLEAR)
+ pps->ppscap |= PPS_OFFSETCLEAR;
+#ifdef PPS_SYNC
+ if (pps->ppscap & PPS_CAPTUREASSERT)
+ pps->ppscap |= PPS_HARDPPSONASSERT;
+ if (pps->ppscap & PPS_CAPTURECLEAR)
+ pps->ppscap |= PPS_HARDPPSONCLEAR;
+#endif
}
-static int
-sysctl_kern_timecounter_adjustment SYSCTL_HANDLER_ARGS
+void
+pps_event(struct pps_state *pps, struct timecounter *tc, unsigned count, int event)
{
+ struct timespec ts, *tsp, *osp;
+ u_int64_t delta;
+ unsigned tcount, *pcount;
+ int foff, fhard;
+ pps_seq_t *pseq;
+
+ /* Things would be easier with arrays... */
+ if (event == PPS_CAPTUREASSERT) {
+ tsp = &pps->ppsinfo.assert_timestamp;
+ osp = &pps->ppsparam.assert_offset;
+ foff = pps->ppsparam.mode & PPS_OFFSETASSERT;
+ fhard = pps->ppsparam.mode & PPS_HARDPPSONASSERT;
+ pcount = &pps->ppscount[0];
+ pseq = &pps->ppsinfo.assert_sequence;
+ } else {
+ tsp = &pps->ppsinfo.clear_timestamp;
+ osp = &pps->ppsparam.clear_offset;
+ foff = pps->ppsparam.mode & PPS_OFFSETCLEAR;
+ fhard = pps->ppsparam.mode & PPS_HARDPPSONCLEAR;
+ pcount = &pps->ppscount[1];
+ pseq = &pps->ppsinfo.clear_sequence;
+ }
- return (sysctl_handle_opaque(oidp,
- &timecounter->tc_tweak->tc_adjustment,
- sizeof(timecounter->tc_tweak->tc_adjustment), req));
-}
+ /* The timecounter changed: bail */
+ if (!pps->ppstc ||
+ pps->ppstc->tc_name != tc->tc_name ||
+ tc->tc_name != timecounter->tc_name) {
+ pps->ppstc = tc;
+ *pcount = count;
+ return;
+ }
-SYSCTL_NODE(_kern, OID_AUTO, timecounter, CTLFLAG_RW, 0, "");
+ /* Now, make sure we have the right instance */
+ tc = timecounter;
-SYSCTL_INT(_kern_timecounter, KERN_ARGMAX, method, CTLFLAG_RW, &tco_method, 0,
- "This variable determines the method used for updating timecounters. "
- "If the default algorithm (0) fails with \"calcru negative...\" messages "
- "try the alternate algorithm (1) which handles bad hardware better."
+ /* Nothing really happened */
+ if (*pcount == count)
+ return;
-);
+ *pcount = count;
-SYSCTL_PROC(_kern_timecounter, OID_AUTO, frequency, CTLTYPE_INT | CTLFLAG_RW,
- 0, sizeof(u_int), sysctl_kern_timecounter_frequency, "I", "");
+ /* Convert the count to timespec */
+ ts.tv_sec = tc->tc_offset_sec;
+ tcount = count - tc->tc_offset_count;
+ tcount &= tc->tc_counter_mask;
+ delta = tc->tc_offset_nano;
+ delta += ((u_int64_t)tcount * tc->tc_scale_nano_f);
+ delta >>= 32;
+ delta += ((u_int64_t)tcount * tc->tc_scale_nano_i);
+ delta += boottime.tv_usec * 1000;
+ ts.tv_sec += boottime.tv_sec;
+ while (delta >= 1000000000) {
+ delta -= 1000000000;
+ ts.tv_sec++;
+ }
+ ts.tv_nsec = delta;
+
+ (*pseq)++;
+ *tsp = ts;
+
+ if (foff) {
+ timespecadd(tsp, osp);
+ if (tsp->tv_nsec < 0) {
+ tsp->tv_nsec += 1000000000;
+ tsp->tv_sec -= 1;
+ }
+ }
+#ifdef PPS_SYNC
+ if (fhard) {
+ /* magic, at its best... */
+ tcount = count - pps->ppscount[2];
+ pps->ppscount[2] = count;
+ tcount &= tc->tc_counter_mask;
+ delta = ((u_int64_t)tcount * tc->tc_tweak->tc_scale_nano_f);
+ delta >>= 32;
+ delta += ((u_int64_t)tcount * tc->tc_tweak->tc_scale_nano_i);
+ hardpps(tsp, delta);
+ }
+#endif
+}
-SYSCTL_PROC(_kern_timecounter, OID_AUTO, adjustment, CTLTYPE_INT | CTLFLAG_RW,
- 0, sizeof(int), sysctl_kern_timecounter_adjustment, "I", "");
diff --git a/sys/kern/kern_ntptime.c b/sys/kern/kern_ntptime.c
index ec98387..56ad6ff 100644
--- a/sys/kern/kern_ntptime.c
+++ b/sys/kern/kern_ntptime.c
@@ -18,7 +18,7 @@
/*
* Adapted from the original sources for FreeBSD and timecounters by:
- * Poul-Henning Kamp <phk@FreeBSD.org>
+ * Poul-Henning Kamp <phk@FreeBSD.org>.
*
* The 32bit version of the "LP" macros seems a bit past its "sell by"
* date so I have retained only the 64bit version and included it directly
@@ -27,11 +27,10 @@
* Only minor changes done to interface with the timecounters over in
* sys/kern/kern_clock.c. Some of the comments below may be (even more)
* confusing and/or plain wrong in that context.
- *
- * The PPS_SYNC/hardpps() is currently not supported.
- *
*/
+#include "opt_ntp.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/sysproto.h>
@@ -167,7 +166,6 @@ struct ppstime {
static struct ppstime pps_tf[3]; /* phase median filter */
static struct ppstime pps_filt; /* phase offset */
static l_fp pps_freq; /* scaled frequency offset (ns/s) */
-static long pps_lastfreq; /* last scaled freq offset (ns/s) */
static long pps_offacc; /* offset accumulator */
static long pps_jitter; /* scaled time dispersion (ns) */
static long pps_stabil; /* scaled frequency dispersion (ns/s) */
@@ -382,7 +380,7 @@ void
ntp_update_second(struct timecounter *tcp)
{
u_int32_t *newsec;
- l_fp ftemp, time_adj; /* 32/64-bit temporary */
+ l_fp ftemp, time_adj; /* 32/64-bit temporaries */
newsec = &tcp->tc_offset_sec;
time_maxerror += MAXFREQ / 1000;
@@ -654,16 +652,17 @@ hardpps(tsp, nsec)
* boundary during the last second, so correct the tick. Very
* intricate.
*/
- u_nsec = nsec - pps_lastcount;
- pps_lastcount = nsec;
+ u_nsec = nsec;
if (u_nsec > (NANOSECOND >> 1))
u_nsec -= NANOSECOND;
else if (u_nsec < -(NANOSECOND >> 1))
u_nsec += NANOSECOND;
+#if 0
if (u_nsec > (time_tick >> 1))
u_nsec -= time_tick;
else if (u_nsec < -(time_tick >> 1))
u_nsec += time_tick;
+#endif
pps_tf[0].count = pps_tf[1].count + u_nsec;
if (v_nsec > MAXFREQ) {
return;
@@ -812,39 +811,3 @@ hardpps(tsp, nsec)
time_freq = pps_freq;
}
#endif /* PPS_SYNC */
-
-int
-std_pps_ioctl(u_long cmd, caddr_t data, pps_params_t *pp, pps_info_t *pi, int ppscap)
-{
- pps_params_t *app;
- pps_info_t *api;
-
- switch (cmd) {
- case PPS_IOC_CREATE:
- return (0);
- case PPS_IOC_DESTROY:
- return (0);
- case PPS_IOC_SETPARAMS:
- app = (pps_params_t *)data;
- if (app->mode & ~ppscap)
- return (EINVAL);
- *pp = *app;
- return (0);
- case PPS_IOC_GETPARAMS:
- app = (pps_params_t *)data;
- *app = *pp;
- return (0);
- case PPS_IOC_GETCAP:
- *(int*)data = ppscap;
- return (0);
- case PPS_IOC_FETCH:
- api = (pps_info_t *)data;
- *api = *pi;
- pi->current_mode = pp->mode;
- return (0);
- case PPS_IOC_WAIT:
- return (EOPNOTSUPP);
- default:
- return (ENODEV);
- }
-}
diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c
index 1c536ee..da424e5 100644
--- a/sys/kern/kern_tc.c
+++ b/sys/kern/kern_tc.c
@@ -37,9 +37,11 @@
* SUCH DAMAGE.
*
* @(#)kern_clock.c 8.5 (Berkeley) 1/21/94
- * $Id: kern_clock.c,v 1.88 1999/02/19 19:34:49 luoqi Exp $
+ * $Id: kern_clock.c,v 1.89 1999/03/08 12:35:58 phk Exp $
*/
+#include "opt_ntp.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/dkstat.h>
@@ -50,6 +52,7 @@
#include <sys/resourcevar.h>
#include <sys/signalvar.h>
#include <sys/timex.h>
+#include <sys/timepps.h>
#include <vm/vm.h>
#include <sys/lock.h>
#include <vm/pmap.h>
@@ -509,11 +512,14 @@ tco_delta(struct timecounter *tc)
}
/*
- * We have four functions for looking at the clock, two for microseconds
- * and two for nanoseconds. For each there is fast but less precise
- * version "get{nano|micro}time" which will return a time which is up
- * to 1/HZ previous to the call, whereas the raw version "{nano|micro}time"
- * will return a timestamp which is as precise as possible.
+ * We have eight functions for looking at the clock, four for
+ * microseconds and four for nanoseconds. For each there is fast
+ * but less precise version "get{nano|micro}[up]time" which will
+ * return a time which is up to 1/HZ previous to the call, whereas
+ * the raw version "{nano|micro}[up]time" will return a timestamp
+ * which is as precise as possible. The "up" variants return the
+ * time relative to system boot, these are well suited for time
+ * interval measurements.
*/
void
@@ -583,29 +589,6 @@ nanotime(struct timespec *ts)
}
void
-timecounter_timespec(unsigned count, struct timespec *ts)
-{
- u_int64_t delta;
- struct timecounter *tc;
-
- tc = (struct timecounter *)timecounter;
- ts->tv_sec = tc->tc_offset_sec;
- count -= tc->tc_offset_count;
- count &= tc->tc_counter_mask;
- delta = tc->tc_offset_nano;
- delta += ((u_int64_t)count * tc->tc_scale_nano_f);
- delta >>= 32;
- delta += ((u_int64_t)count * tc->tc_scale_nano_i);
- delta += boottime.tv_usec * 1000;
- ts->tv_sec += boottime.tv_sec;
- while (delta >= 1000000000) {
- delta -= 1000000000;
- ts->tv_sec++;
- }
- ts->tv_nsec = delta;
-}
-
-void
getmicrouptime(struct timeval *tvp)
{
struct timecounter *tc;
@@ -805,8 +788,6 @@ tco_forward(int force)
while (tc->tc_offset_nano >= 1000000000ULL << 32) {
tc->tc_offset_nano -= 1000000000ULL << 32;
tc->tc_offset_sec++;
- tc->tc_frequency = tc->tc_tweak->tc_frequency;
- tc->tc_adjustment = tc->tc_tweak->tc_adjustment;
ntp_update_second(tc); /* XXX only needed if xntpd runs */
tco_setscales(tc);
force++;
@@ -832,35 +813,149 @@ tco_forward(int force)
timecounter = tc;
}
-static int
-sysctl_kern_timecounter_frequency SYSCTL_HANDLER_ARGS
+SYSCTL_NODE(_kern, OID_AUTO, timecounter, CTLFLAG_RW, 0, "");
+
+SYSCTL_INT(_kern_timecounter, KERN_ARGMAX, method, CTLFLAG_RW, &tco_method, 0,
+ "This variable determines the method used for updating timecounters. "
+ "If the default algorithm (0) fails with \"calcru negative...\" messages "
+ "try the alternate algorithm (1) which handles bad hardware better."
+
+);
+
+
+int
+pps_ioctl(u_long cmd, caddr_t data, struct pps_state *pps)
{
+ pps_params_t *app;
+ pps_info_t *api;
+
+ switch (cmd) {
+ case PPS_IOC_CREATE:
+ return (0);
+ case PPS_IOC_DESTROY:
+ return (0);
+ case PPS_IOC_SETPARAMS:
+ app = (pps_params_t *)data;
+ if (app->mode & ~pps->ppscap)
+ return (EINVAL);
+ pps->ppsparam = *app;
+ return (0);
+ case PPS_IOC_GETPARAMS:
+ app = (pps_params_t *)data;
+ *app = pps->ppsparam;
+ return (0);
+ case PPS_IOC_GETCAP:
+ *(int*)data = pps->ppscap;
+ return (0);
+ case PPS_IOC_FETCH:
+ api = (pps_info_t *)data;
+ pps->ppsinfo.current_mode = pps->ppsparam.mode;
+ *api = pps->ppsinfo;
+ return (0);
+ case PPS_IOC_WAIT:
+ return (EOPNOTSUPP);
+ default:
+ return (ENOTTY);
+ }
+}
- return (sysctl_handle_opaque(oidp,
- &timecounter->tc_tweak->tc_frequency,
- sizeof(timecounter->tc_tweak->tc_frequency), req));
+void
+pps_init(struct pps_state *pps)
+{
+ pps->ppscap |= PPS_TSFMT_TSPEC;
+ if (pps->ppscap & PPS_CAPTUREASSERT)
+ pps->ppscap |= PPS_OFFSETASSERT;
+ if (pps->ppscap & PPS_CAPTURECLEAR)
+ pps->ppscap |= PPS_OFFSETCLEAR;
+#ifdef PPS_SYNC
+ if (pps->ppscap & PPS_CAPTUREASSERT)
+ pps->ppscap |= PPS_HARDPPSONASSERT;
+ if (pps->ppscap & PPS_CAPTURECLEAR)
+ pps->ppscap |= PPS_HARDPPSONCLEAR;
+#endif
}
-static int
-sysctl_kern_timecounter_adjustment SYSCTL_HANDLER_ARGS
+void
+pps_event(struct pps_state *pps, struct timecounter *tc, unsigned count, int event)
{
+ struct timespec ts, *tsp, *osp;
+ u_int64_t delta;
+ unsigned tcount, *pcount;
+ int foff, fhard;
+ pps_seq_t *pseq;
+
+ /* Things would be easier with arrays... */
+ if (event == PPS_CAPTUREASSERT) {
+ tsp = &pps->ppsinfo.assert_timestamp;
+ osp = &pps->ppsparam.assert_offset;
+ foff = pps->ppsparam.mode & PPS_OFFSETASSERT;
+ fhard = pps->ppsparam.mode & PPS_HARDPPSONASSERT;
+ pcount = &pps->ppscount[0];
+ pseq = &pps->ppsinfo.assert_sequence;
+ } else {
+ tsp = &pps->ppsinfo.clear_timestamp;
+ osp = &pps->ppsparam.clear_offset;
+ foff = pps->ppsparam.mode & PPS_OFFSETCLEAR;
+ fhard = pps->ppsparam.mode & PPS_HARDPPSONCLEAR;
+ pcount = &pps->ppscount[1];
+ pseq = &pps->ppsinfo.clear_sequence;
+ }
- return (sysctl_handle_opaque(oidp,
- &timecounter->tc_tweak->tc_adjustment,
- sizeof(timecounter->tc_tweak->tc_adjustment), req));
-}
+ /* The timecounter changed: bail */
+ if (!pps->ppstc ||
+ pps->ppstc->tc_name != tc->tc_name ||
+ tc->tc_name != timecounter->tc_name) {
+ pps->ppstc = tc;
+ *pcount = count;
+ return;
+ }
-SYSCTL_NODE(_kern, OID_AUTO, timecounter, CTLFLAG_RW, 0, "");
+ /* Now, make sure we have the right instance */
+ tc = timecounter;
-SYSCTL_INT(_kern_timecounter, KERN_ARGMAX, method, CTLFLAG_RW, &tco_method, 0,
- "This variable determines the method used for updating timecounters. "
- "If the default algorithm (0) fails with \"calcru negative...\" messages "
- "try the alternate algorithm (1) which handles bad hardware better."
+ /* Nothing really happened */
+ if (*pcount == count)
+ return;
-);
+ *pcount = count;
-SYSCTL_PROC(_kern_timecounter, OID_AUTO, frequency, CTLTYPE_INT | CTLFLAG_RW,
- 0, sizeof(u_int), sysctl_kern_timecounter_frequency, "I", "");
+ /* Convert the count to timespec */
+ ts.tv_sec = tc->tc_offset_sec;
+ tcount = count - tc->tc_offset_count;
+ tcount &= tc->tc_counter_mask;
+ delta = tc->tc_offset_nano;
+ delta += ((u_int64_t)tcount * tc->tc_scale_nano_f);
+ delta >>= 32;
+ delta += ((u_int64_t)tcount * tc->tc_scale_nano_i);
+ delta += boottime.tv_usec * 1000;
+ ts.tv_sec += boottime.tv_sec;
+ while (delta >= 1000000000) {
+ delta -= 1000000000;
+ ts.tv_sec++;
+ }
+ ts.tv_nsec = delta;
+
+ (*pseq)++;
+ *tsp = ts;
+
+ if (foff) {
+ timespecadd(tsp, osp);
+ if (tsp->tv_nsec < 0) {
+ tsp->tv_nsec += 1000000000;
+ tsp->tv_sec -= 1;
+ }
+ }
+#ifdef PPS_SYNC
+ if (fhard) {
+ /* magic, at its best... */
+ tcount = count - pps->ppscount[2];
+ pps->ppscount[2] = count;
+ tcount &= tc->tc_counter_mask;
+ delta = ((u_int64_t)tcount * tc->tc_tweak->tc_scale_nano_f);
+ delta >>= 32;
+ delta += ((u_int64_t)tcount * tc->tc_tweak->tc_scale_nano_i);
+ hardpps(tsp, delta);
+ }
+#endif
+}
-SYSCTL_PROC(_kern_timecounter, OID_AUTO, adjustment, CTLTYPE_INT | CTLFLAG_RW,
- 0, sizeof(int), sysctl_kern_timecounter_adjustment, "I", "");
diff --git a/sys/pci/xrpu.c b/sys/pci/xrpu.c
index 25a90a4..a6964bd 100644
--- a/sys/pci/xrpu.c
+++ b/sys/pci/xrpu.c
@@ -6,7 +6,7 @@
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
* ----------------------------------------------------------------------------
*
- * $Id: xrpu.c,v 1.5 1998/12/14 06:32:58 dillon Exp $
+ * $Id: xrpu.c,v 1.6 1999/01/12 01:42:43 eivind Exp $
*
* A very simple device driver for PCI cards based on Xilinx 6200 series
* FPGA/RPU devices. Current Functionality is to allow you to open and
@@ -17,6 +17,8 @@
*
*/
+#include "opt_devfs.h"
+
#include "xrpu.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -24,7 +26,9 @@
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/timepps.h>
+#ifdef DEFVFS
#include <sys/devfsext.h>
+#endif
#include <sys/xrpuio.h>
#include <pci/pcireg.h>
#include <pci/pcivar.h>
@@ -64,13 +68,8 @@ static struct softc {
u_int *virbase62;
struct timecounter tc;
u_int *trigger, *latch, dummy;
- struct {
- pps_params_t params;
- pps_info_t info;
- int cap;
- u_int *assert, last_assert;
- u_int *clear, last_clear;
- } pps[XRPU_MAX_PPS];
+ struct pps_state pps[XRPU_MAX_PPS];
+ u_int *assert[XRPU_MAX_PPS], *clear[XRPU_MAX_PPS];
} *softc[NXRPU];
static unsigned
@@ -90,45 +89,21 @@ xrpu_poll_pps(struct timecounter *tc)
unsigned count1, ppscount;
for (i = 0; i < XRPU_MAX_PPS; i++) {
- if (sc->pps[i].assert) {
- ppscount = *(sc->pps[i].assert) & tc->tc_counter_mask;
+ if (sc->assert[i]) {
+ ppscount = *(sc->assert[i]) & tc->tc_counter_mask;
do {
count1 = ppscount;
- ppscount = *(sc->pps[i].assert) & tc->tc_counter_mask;
+ ppscount = *(sc->assert[i]) & tc->tc_counter_mask;
} while (ppscount != count1);
- if (ppscount != sc->pps[i].last_assert) {
- timecounter_timespec(ppscount, &sc->pps[i].info.assert_timestamp);
- if (sc->pps[i].params.mode & PPS_OFFSETASSERT) {
- timespecadd(&sc->pps[i].info.assert_timestamp,
- &sc->pps[i].params.assert_offset);
- if (sc->pps[i].info.assert_timestamp.tv_nsec < 0) {
- sc->pps[i].info.assert_timestamp.tv_nsec += 1000000000;
- sc->pps[i].info.assert_timestamp.tv_sec -= 1;
- }
- }
- sc->pps[i].info.assert_sequence++;
- sc->pps[i].last_assert = ppscount;
- }
+ pps_event(&sc->pps[i], &sc->tc, ppscount, PPS_CAPTUREASSERT);
}
- if (sc->pps[i].clear) {
- ppscount = *(sc->pps[i].clear) & tc->tc_counter_mask;
+ if (sc->clear[i]) {
+ ppscount = *(sc->clear[i]) & tc->tc_counter_mask;
do {
count1 = ppscount;
- ppscount = *(sc->pps[i].clear) & tc->tc_counter_mask;
+ ppscount = *(sc->clear[i]) & tc->tc_counter_mask;
} while (ppscount != count1);
- if (ppscount != sc->pps[i].last_clear) {
- timecounter_timespec(ppscount, &sc->pps[i].info.clear_timestamp);
- if (sc->pps[i].params.mode & PPS_OFFSETASSERT) {
- timespecadd(&sc->pps[i].info.clear_timestamp,
- &sc->pps[i].params.clear_offset);
- if (sc->pps[i].info.clear_timestamp.tv_nsec < 0) {
- sc->pps[i].info.clear_timestamp.tv_nsec += 1000000000;
- sc->pps[i].info.clear_timestamp.tv_sec -= 1;
- }
- }
- sc->pps[i].info.clear_sequence++;
- sc->pps[i].last_clear = ppscount;
- }
+ pps_event(&sc->pps[i], &sc->tc, ppscount, PPS_CAPTURECLEAR);
}
}
}
@@ -164,10 +139,7 @@ xrpu_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *pr)
i = dev2pps(dev);
if (i < 0 || i >= XRPU_MAX_PPS)
return ENODEV;
- if (!sc->pps[i].cap)
- return ENODEV;
- error = std_pps_ioctl(cmd, arg, &sc->pps[i].params,
- &sc->pps[i].info, sc->pps[i].cap);
+ error = pps_ioctl(cmd, arg, &sc->pps[i]);
return (error);
}
@@ -191,17 +163,20 @@ xrpu_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *pr)
if (xt->xt_pps[i].xt_addr_assert == 0
&& xt->xt_pps[i].xt_addr_clear == 0)
continue;
- devfs_add_devswf(&xrpudevsw, (i+1)<<16, DV_CHR, UID_ROOT, GID_WHEEL, 0600,
- "xpps%d", i);
- /* DEVFS */
+#ifdef DEVFS
+ devfs_add_devswf(&xrpudevsw, (i+1)<<16, DV_CHR, UID_ROOT, GID_WHEEL,
+ 0600, "xpps%d", i);
+#endif
+ sc->pps[i].ppscap = 0;
if (xt->xt_pps[i].xt_addr_assert) {
- sc->pps[i].assert = sc->virbase62 + xt->xt_pps[i].xt_addr_assert;
- sc->pps[i].cap |= PPS_CAPTUREASSERT | PPS_OFFSETASSERT;
+ sc->assert[i] = sc->virbase62 + xt->xt_pps[i].xt_addr_assert;
+ sc->pps[i].ppscap |= PPS_CAPTUREASSERT;
}
if (xt->xt_pps[i].xt_addr_clear) {
- sc->pps[i].clear = sc->virbase62 + xt->xt_pps[i].xt_addr_clear;
- sc->pps[i].cap |= PPS_CAPTURECLEAR | PPS_OFFSETCLEAR;
+ sc->clear[i] = sc->virbase62 + xt->xt_pps[i].xt_addr_clear;
+ sc->pps[i].ppscap |= PPS_CAPTURECLEAR;
}
+ pps_init(&sc->pps[i]);
}
sc->mode = TIMECOUNTER;
init_timecounter(&sc->tc);
@@ -266,6 +241,8 @@ xrpu_attach (pcici_t tag, int unit)
if (!unit)
cdevsw_add(&cdev, &xrpudevsw, NULL);
+#ifdef DEVFS
devfs_add_devswf(&xrpudevsw, 0, DV_CHR, UID_ROOT, GID_WHEEL, 0600,
"xrpu%d", unit);
+#endif
}
diff --git a/sys/sys/systm.h b/sys/sys/systm.h
index 5724747..99539f1 100644
--- a/sys/sys/systm.h
+++ b/sys/sys/systm.h
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)systm.h 8.7 (Berkeley) 3/29/95
- * $Id: systm.h,v 1.85 1999/01/28 00:57:54 dillon Exp $
+ * $Id: systm.h,v 1.86 1999/03/05 19:27:22 bde Exp $
*/
#ifndef _SYS_SYSTM_H_
@@ -160,8 +160,6 @@ void startprofclock __P((struct proc *));
void stopprofclock __P((struct proc *));
void setstatclockrate __P((int hzrate));
-void hardpps __P((struct timeval *tvp, long usec));
-
char *getenv __P((char *name));
int getenv_int __P((char *name, int *data));
extern char *kern_envp;
diff --git a/sys/sys/time.h b/sys/sys/time.h
index e117c74..712fffe 100644
--- a/sys/sys/time.h
+++ b/sys/sys/time.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)time.h 8.5 (Berkeley) 5/4/95
- * $Id: time.h,v 1.35 1998/12/15 17:38:32 des Exp $
+ * $Id: time.h,v 1.36 1999/03/08 12:36:14 phk Exp $
*/
#ifndef _SYS_TIME_H_
@@ -277,7 +277,6 @@ void microtime __P((struct timeval *tv));
void nanouptime __P((struct timespec *ts));
void nanotime __P((struct timespec *ts));
void set_timecounter __P((struct timespec *ts));
-void timecounter_timespec __P((unsigned count, struct timespec *ts));
void timevaladd __P((struct timeval *, struct timeval *));
void timevalsub __P((struct timeval *, struct timeval *));
int tvtohz __P((struct timeval *));
diff --git a/sys/sys/timepps.h b/sys/sys/timepps.h
index cc0e9ff..ba752d7 100644
--- a/sys/sys/timepps.h
+++ b/sys/sys/timepps.h
@@ -6,7 +6,7 @@
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
* ----------------------------------------------------------------------------
*
- * $Id: timepps.h,v 1.3 1998/06/13 09:30:24 phk Exp $
+ * $Id: timepps.h,v 1.4 1998/06/22 21:09:10 phk Exp $
*
* The is a FreeBSD protype version of the "draft-mogul-pps-api-02.txt"
* specification for Pulse Per Second timing interfaces.
@@ -92,8 +92,85 @@ struct pps_wait_args {
#define PPS_IOC_WAIT _IOWR('1', 6, struct pps_wait_args)
#ifdef KERNEL
-int std_pps_ioctl __P((u_long cmd, caddr_t data, pps_params_t *pp,
- pps_info_t *pi, int ppscap));
+struct pps_state {
+ pps_params_t ppsparam;
+ pps_info_t ppsinfo;
+ int ppscap;
+ struct timecounter *ppstc;
+ unsigned ppscount[3];
+};
-#endif /* KERNEL */
+void pps_event __P((struct pps_state *pps, struct timecounter *tc, unsigned count, int event));
+void pps_init __P((struct pps_state *pps));
+int pps_ioctl __P((u_long cmd, caddr_t data, struct pps_state *pps));
+void hardpps __P((struct timespec *tsp, long nsec));
+
+#else /* !KERNEL */
+
+int time_pps_create(int filedes, pps_handle_t *handle);
+int time_pps_destroy(pps_handle_t handle);
+int time_pps_setparams(pps_handle_t handle, const pps_params_t *ppsparams);
+int time_pps_getparams(pps_handle_t handle, pps_params_t *ppsparams);
+int time_pps_getcap(pps_handle_t handle, int *mode);
+int time_pps_fetch(pps_handle_t handle, pps_info_t *ppsinfobuf);
+int time_pps_wait(pps_handle_t handle, const struct timespec *timeout,
+ pps_info_t *ppsinfobuf);
+
+static __inline int
+time_pps_create(int filedes, pps_handle_t *handle)
+{
+ int error;
+
+ *handle = -1;
+ error = ioctl(filedes, PPS_IOC_CREATE, 0);
+ if (error < 0)
+ return (-1);
+ *handle = filedes;
+ return (0);
+}
+
+static __inline int
+time_pps_destroy(pps_handle_t handle)
+{
+ return (ioctl(handle, PPS_IOC_DESTROY, 0));
+}
+
+static __inline int
+time_pps_setparams(pps_handle_t handle, const pps_params_t *ppsparams)
+{
+ return (ioctl(handle, PPS_IOC_SETPARAMS, ppsparams));
+}
+
+static __inline int
+time_pps_getparams(pps_handle_t handle, pps_params_t *ppsparams)
+{
+ return (ioctl(handle, PPS_IOC_GETPARAMS, ppsparams));
+}
+
+static __inline int
+time_pps_getcap(pps_handle_t handle, int *mode)
+{
+ return (ioctl(handle, PPS_IOC_GETCAP, mode));
+}
+
+static __inline int
+time_pps_fetch(pps_handle_t handle, pps_info_t *ppsinfobuf)
+{
+ return (ioctl(handle, PPS_IOC_FETCH, ppsinfobuf));
+}
+
+static __inline int
+time_pps_wait(pps_handle_t handle, const struct timespec *timeout,
+ pps_info_t *ppsinfobuf)
+{
+ int error;
+ struct pps_wait_args arg;
+
+ arg.timeout = *timeout;
+ error = ioctl(handle, PPS_IOC_WAIT, &arg);
+ *ppsinfobuf = arg.pps_info_buf;
+ return (error);
+}
+
+#endif /* !KERNEL */
#endif /* _SYS_TIMEPPS_H_ */
diff --git a/sys/sys/timetc.h b/sys/sys/timetc.h
index e117c74..712fffe 100644
--- a/sys/sys/timetc.h
+++ b/sys/sys/timetc.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)time.h 8.5 (Berkeley) 5/4/95
- * $Id: time.h,v 1.35 1998/12/15 17:38:32 des Exp $
+ * $Id: time.h,v 1.36 1999/03/08 12:36:14 phk Exp $
*/
#ifndef _SYS_TIME_H_
@@ -277,7 +277,6 @@ void microtime __P((struct timeval *tv));
void nanouptime __P((struct timespec *ts));
void nanotime __P((struct timespec *ts));
void set_timecounter __P((struct timespec *ts));
-void timecounter_timespec __P((unsigned count, struct timespec *ts));
void timevaladd __P((struct timeval *, struct timeval *));
void timevalsub __P((struct timeval *, struct timeval *));
int tvtohz __P((struct timeval *));
diff --git a/sys/sys/timex.h b/sys/sys/timex.h
index a829045..af926d3 100644
--- a/sys/sys/timex.h
+++ b/sys/sys/timex.h
@@ -59,14 +59,11 @@
*
* SYNOPSIS
* #include <sys/timex.h>
- * #include <sys/syscall.h>
*
- * int syscall(SYS_ntp_gettime, tptr);
- * int SYS_ntp_gettime;
- * struct ntptimeval *tptr;
+ * int ntp_gettime(struct ntptimeval *ntv);
*
* DESCRIPTION
- * The time returned by ntp_gettime() is in a timeval structure,
+ * The time returned by ntp_gettime() is in a timespec structure,
* but may be in either microsecond (seconds and microseconds) or
* nanosecond (seconds and nanoseconds) format. The particular
* format in use is determined by the STA_NANO bit of the status
@@ -80,6 +77,7 @@
* #include <sys/syscall.h>
*
* int syscall(SYS_ntp_adjtime, tptr);
+ * int SYS_ntp_adjtime;
* struct timex *tptr;
*
* DESCRIPTION
@@ -89,7 +87,7 @@
* further information.
*/
#ifndef _SYS_TIMEX_H_
-#define _SYS_TIMEX_H_ 1
+#define _SYS_TIMEX_H_
#ifndef MSDOS /* Microsoft specific */
#include <sys/syscall.h>
@@ -171,7 +169,7 @@
* nanoseconds if not.
*/
struct ntptimeval {
- struct timespec time; /* current time (ns) (ro) */
+ struct timespec time; /* current time (ns/us) (ro) */
long maxerror; /* maximum error (us) (ro) */
long esterror; /* estimated error (us) (ro) */
int time_state; /* time status */
@@ -214,16 +212,17 @@ struct timex {
#ifdef __FreeBSD__
#ifdef KERNEL
-void ntp_update_second __P((struct timecounter *tc));
-#else
+struct timecounter;
+void ntp_update_second __P((struct timecounter *tc));
+#else /* !KERNEL */
#include <sys/cdefs.h>
__BEGIN_DECLS
-extern int ntp_gettime __P((struct ntptimeval *));
-extern int ntp_adjtime __P((struct timex *));
+int ntp_adjtime __P((struct timex *));
+int ntp_gettime __P((struct ntptimeval *));
__END_DECLS
-
-#endif /* not KERNEL */
+#endif /* KERNEL */
#endif /* __FreeBSD__ */
-#endif /* _SYS_TIMEX_H_ */
+
+#endif /* !_SYS_TIMEX_H_ */
OpenPOWER on IntegriCloud