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