1139825Simp/*- 236739Sphk * ---------------------------------------------------------------------------- 336739Sphk * "THE BEER-WARE LICENSE" (Revision 42): 436739Sphk * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you 536739Sphk * can do whatever you want with this stuff. If we meet some day, and you think 636739Sphk * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 736739Sphk * ---------------------------------------------------------------------------- 836739Sphk * 9227789Slstewart * Copyright (c) 2011 The FreeBSD Foundation 10227789Slstewart * All rights reserved. 11227789Slstewart * 12227789Slstewart * Portions of this software were developed by Julien Ridoux at the University 13227789Slstewart * of Melbourne under sponsorship from the FreeBSD Foundation. 14227789Slstewart * 1550477Speter * $FreeBSD$ 1636739Sphk * 17122967Sphk * The is a FreeBSD version of the RFC 2783 API for Pulse Per Second 18122967Sphk * timing interfaces. 1936739Sphk */ 2036739Sphk 2136739Sphk#ifndef _SYS_TIMEPPS_H_ 2236739Sphk#define _SYS_TIMEPPS_H_ 2336739Sphk 24227789Slstewart#include <sys/_ffcounter.h> 2536739Sphk#include <sys/ioccom.h> 2695817Sphk#include <sys/time.h> 2736739Sphk 2852061Sjhay#define PPS_API_VERS_1 1 2952061Sjhay 3036739Sphktypedef int pps_handle_t; 3136739Sphk 3236739Sphktypedef unsigned pps_seq_t; 3336739Sphk 3436938Sphktypedef struct ntp_fp { 3536938Sphk unsigned int integral; 3636938Sphk unsigned int fractional; 3736938Sphk} ntp_fp_t; 3836938Sphk 3936938Sphktypedef union pps_timeu { 4036938Sphk struct timespec tspec; 4136938Sphk ntp_fp_t ntpfp; 4252061Sjhay unsigned long longpad[3]; 4336938Sphk} pps_timeu_t; 4436938Sphk 4536739Sphktypedef struct { 4636938Sphk pps_seq_t assert_sequence; /* assert event seq # */ 4736938Sphk pps_seq_t clear_sequence; /* clear event seq # */ 4836938Sphk pps_timeu_t assert_tu; 4936938Sphk pps_timeu_t clear_tu; 5036938Sphk int current_mode; /* current mode bits */ 5136739Sphk} pps_info_t; 5236739Sphk 53227789Slstewarttypedef struct { 54227789Slstewart pps_seq_t assert_sequence; /* assert event seq # */ 55227789Slstewart pps_seq_t clear_sequence; /* clear event seq # */ 56227789Slstewart pps_timeu_t assert_tu; 57227789Slstewart pps_timeu_t clear_tu; 58227789Slstewart ffcounter assert_ffcount; /* ffcounter on assert event */ 59227789Slstewart ffcounter clear_ffcount; /* ffcounter on clear event */ 60227789Slstewart int current_mode; /* current mode bits */ 61227789Slstewart} pps_info_ffc_t; 62227789Slstewart 6336938Sphk#define assert_timestamp assert_tu.tspec 6436938Sphk#define clear_timestamp clear_tu.tspec 6536938Sphk 6636938Sphk#define assert_timestamp_ntpfp assert_tu.ntpfp 6736938Sphk#define clear_timestamp_ntpfp clear_tu.ntpfp 6836938Sphk 6936739Sphktypedef struct { 7052061Sjhay int api_version; /* API version # */ 7136938Sphk int mode; /* mode bits */ 7236938Sphk pps_timeu_t assert_off_tu; 7336938Sphk pps_timeu_t clear_off_tu; 7436739Sphk} pps_params_t; 7536739Sphk 7636938Sphk#define assert_offset assert_off_tu.tspec 7736938Sphk#define clear_offset clear_off_tu.tspec 7836938Sphk 7936938Sphk#define assert_offset_ntpfp assert_off_tu.ntpfp 8036938Sphk#define clear_offset_ntpfp clear_off_tu.ntpfp 8136938Sphk 8236938Sphk 8336739Sphk#define PPS_CAPTUREASSERT 0x01 8437110Sphk#define PPS_CAPTURECLEAR 0x02 8536739Sphk#define PPS_CAPTUREBOTH 0x03 8636739Sphk 8736938Sphk#define PPS_OFFSETASSERT 0x10 8836938Sphk#define PPS_OFFSETCLEAR 0x20 8936938Sphk 9036739Sphk#define PPS_ECHOASSERT 0x40 9136739Sphk#define PPS_ECHOCLEAR 0x80 9236739Sphk 9336739Sphk#define PPS_CANWAIT 0x100 9452061Sjhay#define PPS_CANPOLL 0x200 9536739Sphk 9636938Sphk#define PPS_TSFMT_TSPEC 0x1000 9736938Sphk#define PPS_TSFMT_NTPFP 0x2000 9836938Sphk 99227789Slstewart#define PPS_TSCLK_FBCK 0x10000 100227789Slstewart#define PPS_TSCLK_FFWD 0x20000 101227789Slstewart#define PPS_TSCLK_MASK 0x30000 102227789Slstewart 10352061Sjhay#define PPS_KC_HARDPPS 0 10452061Sjhay#define PPS_KC_HARDPPS_PLL 1 10552061Sjhay#define PPS_KC_HARDPPS_FLL 2 10652061Sjhay 10752061Sjhaystruct pps_fetch_args { 10852061Sjhay int tsformat; 10952061Sjhay pps_info_t pps_info_buf; 11036739Sphk struct timespec timeout; 11136739Sphk}; 11236739Sphk 113227789Slstewartstruct pps_fetch_ffc_args { 114227789Slstewart int tsformat; 115227789Slstewart pps_info_ffc_t pps_info_buf_ffc; 116227789Slstewart struct timespec timeout; 117227789Slstewart}; 118227789Slstewart 11952061Sjhaystruct pps_kcbind_args { 12052061Sjhay int kernel_consumer; 12152061Sjhay int edge; 12252061Sjhay int tsformat; 12352061Sjhay}; 12452061Sjhay 12536739Sphk#define PPS_IOC_CREATE _IO('1', 1) 12636739Sphk#define PPS_IOC_DESTROY _IO('1', 2) 12736739Sphk#define PPS_IOC_SETPARAMS _IOW('1', 3, pps_params_t) 12836739Sphk#define PPS_IOC_GETPARAMS _IOR('1', 4, pps_params_t) 12936739Sphk#define PPS_IOC_GETCAP _IOR('1', 5, int) 13052061Sjhay#define PPS_IOC_FETCH _IOWR('1', 6, struct pps_fetch_args) 13152061Sjhay#define PPS_IOC_KCBIND _IOW('1', 7, struct pps_kcbind_args) 132227789Slstewart#define PPS_IOC_FETCH_FFCOUNTER _IOWR('1', 8, struct pps_fetch_ffc_args) 13336739Sphk 13455205Speter#ifdef _KERNEL 13595817Sphk 136283341Sianstruct mtx; 137283341Sian 138283341Sian#define KCMODE_EDGEMASK 0x03 139283341Sian#define KCMODE_ABIFLAG 0x80000000 /* Internal use: abi-aware driver. */ 140283341Sian 141283341Sian#define PPS_ABI_VERSION 1 142283341Sian 143283341Sian#define PPSFLAG_MTX_SPIN 0x01 /* Driver mtx is MTX_SPIN type. */ 144283341Sian 14544666Sphkstruct pps_state { 14695817Sphk /* Capture information. */ 14795817Sphk struct timehands *capth; 148227789Slstewart struct fftimehands *capffth; 14995817Sphk unsigned capgen; 15095817Sphk unsigned capcount; 15195817Sphk 15295817Sphk /* State information. */ 15395817Sphk pps_params_t ppsparam; 15495817Sphk pps_info_t ppsinfo; 155227789Slstewart pps_info_ffc_t ppsinfo_ffc; 15695817Sphk int kcmode; 15795817Sphk int ppscap; 15895817Sphk struct timecounter *ppstc; 15995817Sphk unsigned ppscount[3]; 160283341Sian /* 161283341Sian * The following fields are valid if the driver calls pps_init_abi(). 162283341Sian */ 163283341Sian uint16_t driver_abi; /* Driver sets before pps_init_abi(). */ 164283341Sian uint16_t kernel_abi; /* Kernel sets during pps_init_abi(). */ 165283341Sian struct mtx *driver_mtx; /* Optional, valid if non-NULL. */ 166283341Sian uint32_t flags; 16744666Sphk}; 16836941Sphk 16995523Sphkvoid pps_capture(struct pps_state *pps); 17095523Sphkvoid pps_event(struct pps_state *pps, int event); 17192719Salfredvoid pps_init(struct pps_state *pps); 172283341Sianvoid pps_init_abi(struct pps_state *pps); 17395817Sphkint pps_ioctl(unsigned long cmd, caddr_t data, struct pps_state *pps); 17492719Salfredvoid hardpps(struct timespec *tsp, long nsec); 17544666Sphk 17655205Speter#else /* !_KERNEL */ 17744666Sphk 17844666Sphkstatic __inline int 17944666Sphktime_pps_create(int filedes, pps_handle_t *handle) 18044666Sphk{ 18144666Sphk int error; 18244666Sphk 18344666Sphk *handle = -1; 18444666Sphk error = ioctl(filedes, PPS_IOC_CREATE, 0); 18544666Sphk if (error < 0) 18644666Sphk return (-1); 18744666Sphk *handle = filedes; 18844666Sphk return (0); 18944666Sphk} 19044666Sphk 19144666Sphkstatic __inline int 19244666Sphktime_pps_destroy(pps_handle_t handle) 19344666Sphk{ 19444666Sphk return (ioctl(handle, PPS_IOC_DESTROY, 0)); 19544666Sphk} 19644666Sphk 19744666Sphkstatic __inline int 19844666Sphktime_pps_setparams(pps_handle_t handle, const pps_params_t *ppsparams) 19944666Sphk{ 20044666Sphk return (ioctl(handle, PPS_IOC_SETPARAMS, ppsparams)); 20144666Sphk} 20244666Sphk 20344666Sphkstatic __inline int 20444666Sphktime_pps_getparams(pps_handle_t handle, pps_params_t *ppsparams) 20544666Sphk{ 20644666Sphk return (ioctl(handle, PPS_IOC_GETPARAMS, ppsparams)); 20744666Sphk} 20844666Sphk 20944666Sphkstatic __inline int 21044666Sphktime_pps_getcap(pps_handle_t handle, int *mode) 21144666Sphk{ 21244666Sphk return (ioctl(handle, PPS_IOC_GETCAP, mode)); 21344666Sphk} 21444666Sphk 21544666Sphkstatic __inline int 21652061Sjhaytime_pps_fetch(pps_handle_t handle, const int tsformat, 21752061Sjhay pps_info_t *ppsinfobuf, const struct timespec *timeout) 21844666Sphk{ 21952061Sjhay int error; 22052061Sjhay struct pps_fetch_args arg; 22152061Sjhay 22252061Sjhay arg.tsformat = tsformat; 22352061Sjhay if (timeout == NULL) { 22452061Sjhay arg.timeout.tv_sec = -1; 22552061Sjhay arg.timeout.tv_nsec = -1; 22652061Sjhay } else 22752061Sjhay arg.timeout = *timeout; 22852061Sjhay error = ioctl(handle, PPS_IOC_FETCH, &arg); 22952061Sjhay *ppsinfobuf = arg.pps_info_buf; 23052061Sjhay return (error); 23144666Sphk} 23244666Sphk 23344666Sphkstatic __inline int 234227789Slstewarttime_pps_fetch_ffc(pps_handle_t handle, const int tsformat, 235227789Slstewart pps_info_ffc_t *ppsinfobuf, const struct timespec *timeout) 236227789Slstewart{ 237227789Slstewart struct pps_fetch_ffc_args arg; 238227789Slstewart int error; 239227789Slstewart 240227789Slstewart arg.tsformat = tsformat; 241227789Slstewart if (timeout == NULL) { 242227789Slstewart arg.timeout.tv_sec = -1; 243227789Slstewart arg.timeout.tv_nsec = -1; 244227789Slstewart } else { 245227789Slstewart arg.timeout = *timeout; 246227789Slstewart } 247227789Slstewart error = ioctl(handle, PPS_IOC_FETCH_FFCOUNTER, &arg); 248227789Slstewart *ppsinfobuf = arg.pps_info_buf_ffc; 249227789Slstewart return (error); 250227789Slstewart} 251227789Slstewart 252227789Slstewartstatic __inline int 25352061Sjhaytime_pps_kcbind(pps_handle_t handle, const int kernel_consumer, 25452061Sjhay const int edge, const int tsformat) 25544666Sphk{ 25652061Sjhay struct pps_kcbind_args arg; 25744666Sphk 25852061Sjhay arg.kernel_consumer = kernel_consumer; 25952061Sjhay arg.edge = edge; 26052061Sjhay arg.tsformat = tsformat; 26152061Sjhay return (ioctl(handle, PPS_IOC_KCBIND, &arg)); 26244666Sphk} 26344666Sphk 26495817Sphk#endif /* KERNEL */ 26595817Sphk 26695817Sphk#endif /* !_SYS_TIMEPPS_H_ */ 267