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