diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c index 34f4c362ceb9..d862f396c32d 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; + 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; - 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); - } + 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 34f4c362ceb9..d862f396c32d 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; + 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; - 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); - } + 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 58e562f3612d..84f1c05a6fbe 100644 --- a/sys/sys/timepps.h +++ b/sys/sys/timepps.h @@ -22,6 +22,8 @@ #include +#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,23 +162,34 @@ time_pps_getcap(pps_handle_t handle, int *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) +time_pps_fetch(pps_handle_t handle, const int tsformat, + pps_info_t *ppsinfobuf, const struct timespec *timeout) { int error; - struct pps_wait_args arg; + struct pps_fetch_args arg; - arg.timeout = *timeout; - error = ioctl(handle, PPS_IOC_WAIT, &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_kcbind(pps_handle_t handle, const int kernel_consumer, + const int edge, const int tsformat) +{ + struct pps_kcbind_args arg; + + arg.kernel_consumer = kernel_consumer; + arg.edge = edge; + arg.tsformat = tsformat; + return (ioctl(handle, PPS_IOC_KCBIND, &arg)); +} + #endif /* !KERNEL */ #endif /* _SYS_TIMEPPS_H_ */