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