summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/kern/kern_clock.c96
-rw-r--r--sys/kern/kern_tc.c96
-rw-r--r--sys/sys/timepps.h60
3 files changed, 150 insertions, 102 deletions
diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c
index 34f4c36..d862f39 100644
--- a/sys/kern/kern_clock.c
+++ b/sys/kern/kern_clock.c
@@ -479,7 +479,7 @@ statclock(frame)
rss = pgtok(vmspace_resident_count(vm));
if (ru->ru_maxrss < rss)
ru->ru_maxrss = rss;
- }
+ }
}
}
@@ -869,37 +869,56 @@ SYSCTL_PROC(_kern_timecounter, OID_AUTO, hardware, CTLTYPE_STRING | CTLFLAG_RW,
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);
- }
+ pps_params_t *app;
+ struct pps_fetch_args *fapi;
+ struct pps_kcbind_args *kapi;
+
+ 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;
+ app->api_version = PPS_API_VERS_1;
+ return (0);
+ case PPS_IOC_GETCAP:
+ *(int*)data = pps->ppscap;
+ return (0);
+ case PPS_IOC_FETCH:
+ fapi = (struct pps_fetch_args *)data;
+ if (fapi->tsformat && fapi->tsformat != PPS_TSFMT_TSPEC)
+ return (EINVAL);
+ if (fapi->timeout.tv_sec || fapi->timeout.tv_nsec)
+ return (EOPNOTSUPP);
+ pps->ppsinfo.current_mode = pps->ppsparam.mode;
+ fapi->pps_info_buf = pps->ppsinfo;
+ return (0);
+ case PPS_IOC_KCBIND:
+#ifdef PPS_SYNC
+ kapi = (struct pps_kcbind_args *)data;
+ /* XXX Only root should be able to do this */
+ if (kapi->tsformat && kapi->tsformat != PPS_TSFMT_TSPEC)
+ return (EINVAL);
+ if (kapi->kernel_consumer != PPS_KC_HARDPPS)
+ return (EINVAL);
+ if (kapi->edge & ~pps->ppscap)
+ return (EINVAL);
+ pps->kcmode = kapi->edge;
+ return (0);
+#else
+ return (EOPNOTSUPP);
+#endif
+ default:
+ return (ENOTTY);
+ }
}
void
@@ -910,12 +929,6 @@ pps_init(struct pps_state *pps)
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
}
void
@@ -932,14 +945,14 @@ pps_event(struct pps_state *pps, struct timecounter *tc, unsigned count, int eve
tsp = &pps->ppsinfo.assert_timestamp;
osp = &pps->ppsparam.assert_offset;
foff = pps->ppsparam.mode & PPS_OFFSETASSERT;
- fhard = pps->ppsparam.mode & PPS_HARDPPSONASSERT;
+ fhard = pps->kcmode & PPS_CAPTUREASSERT;
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;
+ fhard = pps->kcmode & PPS_CAPTURECLEAR;
pcount = &pps->ppscount[1];
pseq = &pps->ppsinfo.clear_sequence;
}
@@ -977,7 +990,7 @@ pps_event(struct pps_state *pps, struct timecounter *tc, unsigned count, int eve
(*pseq)++;
*tsp = ts;
-
+
if (foff) {
timespecadd(tsp, osp);
if (tsp->tv_nsec < 0) {
@@ -998,4 +1011,3 @@ pps_event(struct pps_state *pps, struct timecounter *tc, unsigned count, int eve
}
#endif
}
-
diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c
index 34f4c36..d862f39 100644
--- a/sys/kern/kern_tc.c
+++ b/sys/kern/kern_tc.c
@@ -479,7 +479,7 @@ statclock(frame)
rss = pgtok(vmspace_resident_count(vm));
if (ru->ru_maxrss < rss)
ru->ru_maxrss = rss;
- }
+ }
}
}
@@ -869,37 +869,56 @@ SYSCTL_PROC(_kern_timecounter, OID_AUTO, hardware, CTLTYPE_STRING | CTLFLAG_RW,
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);
- }
+ pps_params_t *app;
+ struct pps_fetch_args *fapi;
+ struct pps_kcbind_args *kapi;
+
+ 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;
+ app->api_version = PPS_API_VERS_1;
+ return (0);
+ case PPS_IOC_GETCAP:
+ *(int*)data = pps->ppscap;
+ return (0);
+ case PPS_IOC_FETCH:
+ fapi = (struct pps_fetch_args *)data;
+ if (fapi->tsformat && fapi->tsformat != PPS_TSFMT_TSPEC)
+ return (EINVAL);
+ if (fapi->timeout.tv_sec || fapi->timeout.tv_nsec)
+ return (EOPNOTSUPP);
+ pps->ppsinfo.current_mode = pps->ppsparam.mode;
+ fapi->pps_info_buf = pps->ppsinfo;
+ return (0);
+ case PPS_IOC_KCBIND:
+#ifdef PPS_SYNC
+ kapi = (struct pps_kcbind_args *)data;
+ /* XXX Only root should be able to do this */
+ if (kapi->tsformat && kapi->tsformat != PPS_TSFMT_TSPEC)
+ return (EINVAL);
+ if (kapi->kernel_consumer != PPS_KC_HARDPPS)
+ return (EINVAL);
+ if (kapi->edge & ~pps->ppscap)
+ return (EINVAL);
+ pps->kcmode = kapi->edge;
+ return (0);
+#else
+ return (EOPNOTSUPP);
+#endif
+ default:
+ return (ENOTTY);
+ }
}
void
@@ -910,12 +929,6 @@ pps_init(struct pps_state *pps)
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
}
void
@@ -932,14 +945,14 @@ pps_event(struct pps_state *pps, struct timecounter *tc, unsigned count, int eve
tsp = &pps->ppsinfo.assert_timestamp;
osp = &pps->ppsparam.assert_offset;
foff = pps->ppsparam.mode & PPS_OFFSETASSERT;
- fhard = pps->ppsparam.mode & PPS_HARDPPSONASSERT;
+ fhard = pps->kcmode & PPS_CAPTUREASSERT;
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;
+ fhard = pps->kcmode & PPS_CAPTURECLEAR;
pcount = &pps->ppscount[1];
pseq = &pps->ppsinfo.clear_sequence;
}
@@ -977,7 +990,7 @@ pps_event(struct pps_state *pps, struct timecounter *tc, unsigned count, int eve
(*pseq)++;
*tsp = ts;
-
+
if (foff) {
timespecadd(tsp, osp);
if (tsp->tv_nsec < 0) {
@@ -998,4 +1011,3 @@ pps_event(struct pps_state *pps, struct timecounter *tc, unsigned count, int eve
}
#endif
}
-
diff --git a/sys/sys/timepps.h b/sys/sys/timepps.h
index 58e562f..84f1c05 100644
--- a/sys/sys/timepps.h
+++ b/sys/sys/timepps.h
@@ -22,6 +22,8 @@
#include <sys/ioccom.h>
+#define PPS_API_VERS_1 1
+
typedef int pps_handle_t;
typedef unsigned pps_seq_t;
@@ -34,7 +36,7 @@ typedef struct ntp_fp {
typedef union pps_timeu {
struct timespec tspec;
ntp_fp_t ntpfp;
- unsigned long longpair[2];
+ unsigned long longpad[3];
} pps_timeu_t;
typedef struct {
@@ -52,6 +54,7 @@ typedef struct {
#define clear_timestamp_ntpfp clear_tu.ntpfp
typedef struct {
+ int api_version; /* API version # */
int mode; /* mode bits */
pps_timeu_t assert_off_tu;
pps_timeu_t clear_off_tu;
@@ -71,20 +74,29 @@ typedef struct {
#define PPS_OFFSETASSERT 0x10
#define PPS_OFFSETCLEAR 0x20
-#define PPS_HARDPPSONASSERT 0x04
-#define PPS_HARDPPSONCLEAR 0x08
-
#define PPS_ECHOASSERT 0x40
#define PPS_ECHOCLEAR 0x80
#define PPS_CANWAIT 0x100
+#define PPS_CANPOLL 0x200
#define PPS_TSFMT_TSPEC 0x1000
#define PPS_TSFMT_NTPFP 0x2000
-struct pps_wait_args {
- struct timespec timeout;
+#define PPS_KC_HARDPPS 0
+#define PPS_KC_HARDPPS_PLL 1
+#define PPS_KC_HARDPPS_FLL 2
+
+struct pps_fetch_args {
+ int tsformat;
pps_info_t pps_info_buf;
+ struct timespec timeout;
+};
+
+struct pps_kcbind_args {
+ int kernel_consumer;
+ int edge;
+ int tsformat;
};
#define PPS_IOC_CREATE _IO('1', 1)
@@ -92,13 +104,14 @@ struct pps_wait_args {
#define PPS_IOC_SETPARAMS _IOW('1', 3, pps_params_t)
#define PPS_IOC_GETPARAMS _IOR('1', 4, pps_params_t)
#define PPS_IOC_GETCAP _IOR('1', 5, int)
-#define PPS_IOC_FETCH _IOWR('1', 6, pps_info_t)
-#define PPS_IOC_WAIT _IOWR('1', 6, struct pps_wait_args)
+#define PPS_IOC_FETCH _IOWR('1', 6, struct pps_fetch_args)
+#define PPS_IOC_KCBIND _IOW('1', 7, struct pps_kcbind_args)
#ifdef KERNEL
struct pps_state {
pps_params_t ppsparam;
pps_info_t ppsinfo;
+ int kcmode;
int ppscap;
struct timecounter *ppstc;
unsigned ppscount[3];
@@ -149,22 +162,33 @@ time_pps_getcap(pps_handle_t handle, int *mode)
}
static __inline int
-time_pps_fetch(pps_handle_t handle, pps_info_t *ppsinfobuf)
+time_pps_fetch(pps_handle_t handle, const int tsformat,
+ pps_info_t *ppsinfobuf, const struct timespec *timeout)
{
- return (ioctl(handle, PPS_IOC_FETCH, ppsinfobuf));
+ int error;
+ struct pps_fetch_args arg;
+
+ arg.tsformat = tsformat;
+ if (timeout == NULL) {
+ arg.timeout.tv_sec = -1;
+ arg.timeout.tv_nsec = -1;
+ } else
+ arg.timeout = *timeout;
+ error = ioctl(handle, PPS_IOC_FETCH, &arg);
+ *ppsinfobuf = arg.pps_info_buf;
+ return (error);
}
static __inline int
-time_pps_wait(pps_handle_t handle, const struct timespec *timeout,
- pps_info_t *ppsinfobuf)
+time_pps_kcbind(pps_handle_t handle, const int kernel_consumer,
+ const int edge, const int tsformat)
{
- int error;
- struct pps_wait_args arg;
+ struct pps_kcbind_args arg;
- arg.timeout = *timeout;
- error = ioctl(handle, PPS_IOC_WAIT, &arg);
- *ppsinfobuf = arg.pps_info_buf;
- return (error);
+ arg.kernel_consumer = kernel_consumer;
+ arg.edge = edge;
+ arg.tsformat = tsformat;
+ return (ioctl(handle, PPS_IOC_KCBIND, &arg));
}
#endif /* !KERNEL */
OpenPOWER on IntegriCloud