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