1/*- 2 * SPDX-License-Identifier: Beerware 3 * 4 * ---------------------------------------------------------------------------- 5 * "THE BEER-WARE LICENSE" (Revision 42): 6 * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you 7 * can do whatever you want with this stuff. If we meet some day, and you think 8 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 9 * ---------------------------------------------------------------------------- 10 * 11 * Copyright (c) 2011 The FreeBSD Foundation 12 * 13 * Portions of this software were developed by Julien Ridoux at the University 14 * of Melbourne under sponsorship from the FreeBSD Foundation. 15 * 16 * The is a FreeBSD version of the RFC 2783 API for Pulse Per Second 17 * timing interfaces. 18 */ 19 20#ifndef _SYS_TIMEPPS_H_ 21#define _SYS_TIMEPPS_H_ 22 23#include <sys/_ffcounter.h> 24#include <sys/ioccom.h> 25#include <sys/time.h> 26 27#define PPS_API_VERS_1 1 28 29typedef int pps_handle_t; 30 31typedef unsigned pps_seq_t; 32 33typedef struct ntp_fp { 34 unsigned int integral; 35 unsigned int fractional; 36} ntp_fp_t; 37 38typedef union pps_timeu { 39 struct timespec tspec; 40 ntp_fp_t ntpfp; 41 unsigned long longpad[3]; 42} pps_timeu_t; 43 44typedef struct { 45 pps_seq_t assert_sequence; /* assert event seq # */ 46 pps_seq_t clear_sequence; /* clear event seq # */ 47 pps_timeu_t assert_tu; 48 pps_timeu_t clear_tu; 49 int current_mode; /* current mode bits */ 50} pps_info_t; 51 52typedef struct { 53 pps_seq_t assert_sequence; /* assert event seq # */ 54 pps_seq_t clear_sequence; /* clear event seq # */ 55 pps_timeu_t assert_tu; 56 pps_timeu_t clear_tu; 57 ffcounter assert_ffcount; /* ffcounter on assert event */ 58 ffcounter clear_ffcount; /* ffcounter on clear event */ 59 int current_mode; /* current mode bits */ 60} pps_info_ffc_t; 61 62#define assert_timestamp assert_tu.tspec 63#define clear_timestamp clear_tu.tspec 64 65#define assert_timestamp_ntpfp assert_tu.ntpfp 66#define clear_timestamp_ntpfp clear_tu.ntpfp 67 68typedef struct { 69 int api_version; /* API version # */ 70 int mode; /* mode bits */ 71 pps_timeu_t assert_off_tu; 72 pps_timeu_t clear_off_tu; 73} pps_params_t; 74 75#define assert_offset assert_off_tu.tspec 76#define clear_offset clear_off_tu.tspec 77 78#define assert_offset_ntpfp assert_off_tu.ntpfp 79#define clear_offset_ntpfp clear_off_tu.ntpfp 80 81#define PPS_CAPTUREASSERT 0x01 82#define PPS_CAPTURECLEAR 0x02 83#define PPS_CAPTUREBOTH 0x03 84 85#define PPS_OFFSETASSERT 0x10 86#define PPS_OFFSETCLEAR 0x20 87 88#define PPS_ECHOASSERT 0x40 89#define PPS_ECHOCLEAR 0x80 90 91#define PPS_CANWAIT 0x100 92#define PPS_CANPOLL 0x200 93 94#define PPS_TSFMT_TSPEC 0x1000 95#define PPS_TSFMT_NTPFP 0x2000 96 97#define PPS_TSCLK_FBCK 0x10000 98#define PPS_TSCLK_FFWD 0x20000 99#define PPS_TSCLK_MASK 0x30000 100 101#define PPS_KC_HARDPPS 0 102#define PPS_KC_HARDPPS_PLL 1 103#define PPS_KC_HARDPPS_FLL 2 104 105struct pps_fetch_args { 106 int tsformat; 107 pps_info_t pps_info_buf; 108 struct timespec timeout; 109}; 110 111struct pps_fetch_ffc_args { 112 int tsformat; 113 pps_info_ffc_t pps_info_buf_ffc; 114 struct timespec timeout; 115}; 116 117struct pps_kcbind_args { 118 int kernel_consumer; 119 int edge; 120 int tsformat; 121}; 122 123#define PPS_IOC_CREATE _IO('1', 1) 124#define PPS_IOC_DESTROY _IO('1', 2) 125#define PPS_IOC_SETPARAMS _IOW('1', 3, pps_params_t) 126#define PPS_IOC_GETPARAMS _IOR('1', 4, pps_params_t) 127#define PPS_IOC_GETCAP _IOR('1', 5, int) 128#define PPS_IOC_FETCH _IOWR('1', 6, struct pps_fetch_args) 129#define PPS_IOC_KCBIND _IOW('1', 7, struct pps_kcbind_args) 130#define PPS_IOC_FETCH_FFCOUNTER _IOWR('1', 8, struct pps_fetch_ffc_args) 131 132#ifdef _KERNEL 133 134struct mtx; 135 136#define KCMODE_EDGEMASK 0x03 137#define KCMODE_ABIFLAG 0x80000000 /* Internal use: abi-aware driver. */ 138 139#define PPS_ABI_VERSION 1 140 141#define PPSFLAG_MTX_SPIN 0x01 /* Driver mtx is MTX_SPIN type. */ 142 143struct pps_state { 144 /* Capture information. */ 145 struct timehands *capth; 146 struct fftimehands *capffth; 147 unsigned capgen; 148 unsigned capcount; 149 150 /* State information. */ 151 pps_params_t ppsparam; 152 pps_info_t ppsinfo; 153 pps_info_ffc_t ppsinfo_ffc; 154 int kcmode; 155 int ppscap; 156 struct timecounter *ppstc; 157 unsigned ppscount[3]; 158 /* 159 * The following fields are valid if the driver calls pps_init_abi(). 160 */ 161 uint16_t driver_abi; /* Driver sets before pps_init_abi(). */ 162 uint16_t kernel_abi; /* Kernel sets during pps_init_abi(). */ 163 struct mtx *driver_mtx; /* Optional, valid if non-NULL. */ 164 uint32_t flags; 165}; 166 167void pps_capture(struct pps_state *pps); 168void pps_event(struct pps_state *pps, int event); 169void pps_init(struct pps_state *pps); 170void pps_init_abi(struct pps_state *pps); 171int pps_ioctl(unsigned long cmd, caddr_t data, struct pps_state *pps); 172void hardpps(struct timespec *tsp, long nsec); 173 174#else /* !_KERNEL */ 175 176static __inline int 177time_pps_create(int filedes, pps_handle_t *handle) 178{ 179 int error; 180 181 *handle = -1; 182 error = ioctl(filedes, PPS_IOC_CREATE, 0); 183 if (error < 0) 184 return (-1); 185 *handle = filedes; 186 return (0); 187} 188 189static __inline int 190time_pps_destroy(pps_handle_t handle) 191{ 192 return (ioctl(handle, PPS_IOC_DESTROY, 0)); 193} 194 195static __inline int 196time_pps_setparams(pps_handle_t handle, const pps_params_t *ppsparams) 197{ 198 return (ioctl(handle, PPS_IOC_SETPARAMS, ppsparams)); 199} 200 201static __inline int 202time_pps_getparams(pps_handle_t handle, pps_params_t *ppsparams) 203{ 204 return (ioctl(handle, PPS_IOC_GETPARAMS, ppsparams)); 205} 206 207static __inline int 208time_pps_getcap(pps_handle_t handle, int *mode) 209{ 210 return (ioctl(handle, PPS_IOC_GETCAP, mode)); 211} 212 213static __inline int 214time_pps_fetch(pps_handle_t handle, const int tsformat, 215 pps_info_t *ppsinfobuf, const struct timespec *timeout) 216{ 217 int error; 218 struct pps_fetch_args arg; 219 220 arg.tsformat = tsformat; 221 if (timeout == NULL) { 222 arg.timeout.tv_sec = -1; 223 arg.timeout.tv_nsec = -1; 224 } else 225 arg.timeout = *timeout; 226 error = ioctl(handle, PPS_IOC_FETCH, &arg); 227 *ppsinfobuf = arg.pps_info_buf; 228 return (error); 229} 230 231static __inline int 232time_pps_fetch_ffc(pps_handle_t handle, const int tsformat, 233 pps_info_ffc_t *ppsinfobuf, const struct timespec *timeout) 234{ 235 struct pps_fetch_ffc_args arg; 236 int error; 237 238 arg.tsformat = tsformat; 239 if (timeout == NULL) { 240 arg.timeout.tv_sec = -1; 241 arg.timeout.tv_nsec = -1; 242 } else { 243 arg.timeout = *timeout; 244 } 245 error = ioctl(handle, PPS_IOC_FETCH_FFCOUNTER, &arg); 246 *ppsinfobuf = arg.pps_info_buf_ffc; 247 return (error); 248} 249 250static __inline int 251time_pps_kcbind(pps_handle_t handle, const int kernel_consumer, 252 const int edge, const int tsformat) 253{ 254 struct pps_kcbind_args arg; 255 256 arg.kernel_consumer = kernel_consumer; 257 arg.edge = edge; 258 arg.tsformat = tsformat; 259 return (ioctl(handle, PPS_IOC_KCBIND, &arg)); 260} 261 262#endif /* KERNEL */ 263 264#endif /* !_SYS_TIMEPPS_H_ */ 265