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 13644666Sphkstruct pps_state { 13795817Sphk /* Capture information. */ 13895817Sphk struct timehands *capth; 139227789Slstewart struct fftimehands *capffth; 14095817Sphk unsigned capgen; 14195817Sphk unsigned capcount; 14295817Sphk 14395817Sphk /* State information. */ 14495817Sphk pps_params_t ppsparam; 14595817Sphk pps_info_t ppsinfo; 146227789Slstewart pps_info_ffc_t ppsinfo_ffc; 14795817Sphk int kcmode; 14895817Sphk int ppscap; 14995817Sphk struct timecounter *ppstc; 15095817Sphk unsigned ppscount[3]; 15144666Sphk}; 15236941Sphk 15395523Sphkvoid pps_capture(struct pps_state *pps); 15495523Sphkvoid pps_event(struct pps_state *pps, int event); 15592719Salfredvoid pps_init(struct pps_state *pps); 15695817Sphkint pps_ioctl(unsigned long cmd, caddr_t data, struct pps_state *pps); 15792719Salfredvoid hardpps(struct timespec *tsp, long nsec); 15844666Sphk 15955205Speter#else /* !_KERNEL */ 16044666Sphk 16144666Sphkstatic __inline int 16244666Sphktime_pps_create(int filedes, pps_handle_t *handle) 16344666Sphk{ 16444666Sphk int error; 16544666Sphk 16644666Sphk *handle = -1; 16744666Sphk error = ioctl(filedes, PPS_IOC_CREATE, 0); 16844666Sphk if (error < 0) 16944666Sphk return (-1); 17044666Sphk *handle = filedes; 17144666Sphk return (0); 17244666Sphk} 17344666Sphk 17444666Sphkstatic __inline int 17544666Sphktime_pps_destroy(pps_handle_t handle) 17644666Sphk{ 17744666Sphk return (ioctl(handle, PPS_IOC_DESTROY, 0)); 17844666Sphk} 17944666Sphk 18044666Sphkstatic __inline int 18144666Sphktime_pps_setparams(pps_handle_t handle, const pps_params_t *ppsparams) 18244666Sphk{ 18344666Sphk return (ioctl(handle, PPS_IOC_SETPARAMS, ppsparams)); 18444666Sphk} 18544666Sphk 18644666Sphkstatic __inline int 18744666Sphktime_pps_getparams(pps_handle_t handle, pps_params_t *ppsparams) 18844666Sphk{ 18944666Sphk return (ioctl(handle, PPS_IOC_GETPARAMS, ppsparams)); 19044666Sphk} 19144666Sphk 19244666Sphkstatic __inline int 19344666Sphktime_pps_getcap(pps_handle_t handle, int *mode) 19444666Sphk{ 19544666Sphk return (ioctl(handle, PPS_IOC_GETCAP, mode)); 19644666Sphk} 19744666Sphk 19844666Sphkstatic __inline int 19952061Sjhaytime_pps_fetch(pps_handle_t handle, const int tsformat, 20052061Sjhay pps_info_t *ppsinfobuf, const struct timespec *timeout) 20144666Sphk{ 20252061Sjhay int error; 20352061Sjhay struct pps_fetch_args arg; 20452061Sjhay 20552061Sjhay arg.tsformat = tsformat; 20652061Sjhay if (timeout == NULL) { 20752061Sjhay arg.timeout.tv_sec = -1; 20852061Sjhay arg.timeout.tv_nsec = -1; 20952061Sjhay } else 21052061Sjhay arg.timeout = *timeout; 21152061Sjhay error = ioctl(handle, PPS_IOC_FETCH, &arg); 21252061Sjhay *ppsinfobuf = arg.pps_info_buf; 21352061Sjhay return (error); 21444666Sphk} 21544666Sphk 21644666Sphkstatic __inline int 217227789Slstewarttime_pps_fetch_ffc(pps_handle_t handle, const int tsformat, 218227789Slstewart pps_info_ffc_t *ppsinfobuf, const struct timespec *timeout) 219227789Slstewart{ 220227789Slstewart struct pps_fetch_ffc_args arg; 221227789Slstewart int error; 222227789Slstewart 223227789Slstewart arg.tsformat = tsformat; 224227789Slstewart if (timeout == NULL) { 225227789Slstewart arg.timeout.tv_sec = -1; 226227789Slstewart arg.timeout.tv_nsec = -1; 227227789Slstewart } else { 228227789Slstewart arg.timeout = *timeout; 229227789Slstewart } 230227789Slstewart error = ioctl(handle, PPS_IOC_FETCH_FFCOUNTER, &arg); 231227789Slstewart *ppsinfobuf = arg.pps_info_buf_ffc; 232227789Slstewart return (error); 233227789Slstewart} 234227789Slstewart 235227789Slstewartstatic __inline int 23652061Sjhaytime_pps_kcbind(pps_handle_t handle, const int kernel_consumer, 23752061Sjhay const int edge, const int tsformat) 23844666Sphk{ 23952061Sjhay struct pps_kcbind_args arg; 24044666Sphk 24152061Sjhay arg.kernel_consumer = kernel_consumer; 24252061Sjhay arg.edge = edge; 24352061Sjhay arg.tsformat = tsformat; 24452061Sjhay return (ioctl(handle, PPS_IOC_KCBIND, &arg)); 24544666Sphk} 24644666Sphk 24795817Sphk#endif /* KERNEL */ 24895817Sphk 24995817Sphk#endif /* !_SYS_TIMEPPS_H_ */ 250