1/*- 2 * ---------------------------------------------------------------------------- 3 * "THE BEER-WARE LICENSE" (Revision 42): 4 * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you 5 * can do whatever you want with this stuff. If we meet some day, and you think 6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 7 * ---------------------------------------------------------------------------- 8 * 9 * $FreeBSD$ 10 * 11 * The is a FreeBSD version of the RFC 2783 API for Pulse Per Second 12 * timing interfaces. 13 */ 14 15#ifndef _SYS_TIMEPPS_H_ 16#define _SYS_TIMEPPS_H_ 17 18#include <sys/ioccom.h> 19#include <sys/time.h> 20 21#define PPS_API_VERS_1 1 22 23typedef int pps_handle_t; 24 25typedef unsigned pps_seq_t; 26 27typedef struct ntp_fp { 28 unsigned int integral; 29 unsigned int fractional; 30} ntp_fp_t; 31 32typedef union pps_timeu { 33 struct timespec tspec; 34 ntp_fp_t ntpfp; 35 unsigned long longpad[3]; 36} pps_timeu_t; 37 38typedef struct { 39 pps_seq_t assert_sequence; /* assert event seq # */ 40 pps_seq_t clear_sequence; /* clear event seq # */ 41 pps_timeu_t assert_tu; 42 pps_timeu_t clear_tu; 43 int current_mode; /* current mode bits */ 44} pps_info_t; 45 46#define assert_timestamp assert_tu.tspec 47#define clear_timestamp clear_tu.tspec 48 49#define assert_timestamp_ntpfp assert_tu.ntpfp 50#define clear_timestamp_ntpfp clear_tu.ntpfp 51 52typedef struct { 53 int api_version; /* API version # */ 54 int mode; /* mode bits */ 55 pps_timeu_t assert_off_tu; 56 pps_timeu_t clear_off_tu; 57} pps_params_t; 58 59#define assert_offset assert_off_tu.tspec 60#define clear_offset clear_off_tu.tspec 61 62#define assert_offset_ntpfp assert_off_tu.ntpfp 63#define clear_offset_ntpfp clear_off_tu.ntpfp 64 65 66#define PPS_CAPTUREASSERT 0x01 67#define PPS_CAPTURECLEAR 0x02 68#define PPS_CAPTUREBOTH 0x03 69 70#define PPS_OFFSETASSERT 0x10 71#define PPS_OFFSETCLEAR 0x20 72 73#define PPS_ECHOASSERT 0x40 74#define PPS_ECHOCLEAR 0x80 75 76#define PPS_CANWAIT 0x100 77#define PPS_CANPOLL 0x200 78 79#define PPS_TSFMT_TSPEC 0x1000 80#define PPS_TSFMT_NTPFP 0x2000 81 82#define PPS_KC_HARDPPS 0 83#define PPS_KC_HARDPPS_PLL 1 84#define PPS_KC_HARDPPS_FLL 2 85 86struct pps_fetch_args { 87 int tsformat; 88 pps_info_t pps_info_buf; 89 struct timespec timeout; 90}; 91 92struct pps_kcbind_args { 93 int kernel_consumer; 94 int edge; 95 int tsformat; 96}; 97 98#define PPS_IOC_CREATE _IO('1', 1) 99#define PPS_IOC_DESTROY _IO('1', 2) 100#define PPS_IOC_SETPARAMS _IOW('1', 3, pps_params_t) 101#define PPS_IOC_GETPARAMS _IOR('1', 4, pps_params_t) 102#define PPS_IOC_GETCAP _IOR('1', 5, int) 103#define PPS_IOC_FETCH _IOWR('1', 6, struct pps_fetch_args) 104#define PPS_IOC_KCBIND _IOW('1', 7, struct pps_kcbind_args) 105 106#ifdef _KERNEL 107 108struct pps_state { 109 /* Capture information. */ 110 struct timehands *capth; 111 unsigned capgen; 112 unsigned capcount; 113 114 /* State information. */ 115 pps_params_t ppsparam; 116 pps_info_t ppsinfo; 117 int kcmode; 118 int ppscap; 119 struct timecounter *ppstc; 120 unsigned ppscount[3]; 121}; 122 123void pps_capture(struct pps_state *pps); 124void pps_event(struct pps_state *pps, int event); 125void pps_init(struct pps_state *pps); 126int pps_ioctl(unsigned long cmd, caddr_t data, struct pps_state *pps); 127void hardpps(struct timespec *tsp, long nsec); 128 129#else /* !_KERNEL */ 130 131static __inline int 132time_pps_create(int filedes, pps_handle_t *handle) 133{ 134 int error; 135 136 *handle = -1; 137 error = ioctl(filedes, PPS_IOC_CREATE, 0); 138 if (error < 0) 139 return (-1); 140 *handle = filedes; 141 return (0); 142} 143 144static __inline int 145time_pps_destroy(pps_handle_t handle) 146{ 147 return (ioctl(handle, PPS_IOC_DESTROY, 0)); 148} 149 150static __inline int 151time_pps_setparams(pps_handle_t handle, const pps_params_t *ppsparams) 152{ 153 return (ioctl(handle, PPS_IOC_SETPARAMS, ppsparams)); 154} 155 156static __inline int 157time_pps_getparams(pps_handle_t handle, pps_params_t *ppsparams) 158{ 159 return (ioctl(handle, PPS_IOC_GETPARAMS, ppsparams)); 160} 161 162static __inline int 163time_pps_getcap(pps_handle_t handle, int *mode) 164{ 165 return (ioctl(handle, PPS_IOC_GETCAP, mode)); 166} 167 168static __inline int 169time_pps_fetch(pps_handle_t handle, const int tsformat, 170 pps_info_t *ppsinfobuf, const struct timespec *timeout) 171{ 172 int error; 173 struct pps_fetch_args arg; 174 175 arg.tsformat = tsformat; 176 if (timeout == NULL) { 177 arg.timeout.tv_sec = -1; 178 arg.timeout.tv_nsec = -1; 179 } else 180 arg.timeout = *timeout; 181 error = ioctl(handle, PPS_IOC_FETCH, &arg); 182 *ppsinfobuf = arg.pps_info_buf; 183 return (error); 184} 185 186static __inline int 187time_pps_kcbind(pps_handle_t handle, const int kernel_consumer, 188 const int edge, const int tsformat) 189{ 190 struct pps_kcbind_args arg; 191 192 arg.kernel_consumer = kernel_consumer; 193 arg.edge = edge; 194 arg.tsformat = tsformat; 195 return (ioctl(handle, PPS_IOC_KCBIND, &arg)); 196} 197 198#endif /* KERNEL */ 199 200#endif /* !_SYS_TIMEPPS_H_ */ 201