summaryrefslogtreecommitdiffstats
path: root/cpukit/score/include/sys/timepps.h
blob: 71d74f54ee97fed06242f698182cd78154434990 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
/*-
 * ----------------------------------------------------------------------------
 * "THE BEER-WARE LICENSE" (Revision 42):
 * <phk@FreeBSD.org> wrote this file.  As long as you retain this notice you
 * can do whatever you want with this stuff. If we meet some day, and you think
 * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
 * ----------------------------------------------------------------------------
 *
 * Copyright (c) 2011 The FreeBSD Foundation
 * All rights reserved.
 *
 * Portions of this software were developed by Julien Ridoux at the University
 * of Melbourne under sponsorship from the FreeBSD Foundation.
 *
 * $FreeBSD r277406 2015-01-20T03:54:30Z$
 *
 * The is a FreeBSD version of the RFC 2783 API for Pulse Per Second 
 * timing interfaces.  
 */

#ifndef _SYS_TIMEPPS_H_
#define _SYS_TIMEPPS_H_

#include <sys/_ffcounter.h>
#include <sys/ioccom.h>
#include <sys/time.h>

#define PPS_API_VERS_1	1

typedef int pps_handle_t;	

typedef unsigned pps_seq_t;

typedef struct ntp_fp {
	unsigned int	integral;
	unsigned int	fractional;
} ntp_fp_t;

typedef union pps_timeu {
	struct timespec	tspec;
	ntp_fp_t	ntpfp;
	unsigned long	longpad[3];
} pps_timeu_t;

typedef struct {
	pps_seq_t	assert_sequence;	/* assert event seq # */
	pps_seq_t	clear_sequence;		/* clear event seq # */
	pps_timeu_t	assert_tu;
	pps_timeu_t	clear_tu;
	int		current_mode;		/* current mode bits */
} pps_info_t;

typedef struct {
	pps_seq_t	assert_sequence;	/* assert event seq # */
	pps_seq_t	clear_sequence;		/* clear event seq # */
	pps_timeu_t	assert_tu;
	pps_timeu_t	clear_tu;
	ffcounter	assert_ffcount;		/* ffcounter on assert event */
	ffcounter	clear_ffcount;		/* ffcounter on clear event */
	int		current_mode;		/* current mode bits */
} pps_info_ffc_t;

#define assert_timestamp        assert_tu.tspec
#define clear_timestamp         clear_tu.tspec

#define assert_timestamp_ntpfp  assert_tu.ntpfp
#define clear_timestamp_ntpfp   clear_tu.ntpfp

typedef struct {
	int api_version;			/* API version # */
	int mode;				/* mode bits */
	pps_timeu_t assert_off_tu;
	pps_timeu_t clear_off_tu;
} pps_params_t;

#define assert_offset   assert_off_tu.tspec
#define clear_offset    clear_off_tu.tspec

#define assert_offset_ntpfp     assert_off_tu.ntpfp
#define clear_offset_ntpfp      clear_off_tu.ntpfp


#define PPS_CAPTUREASSERT	0x01
#define PPS_CAPTURECLEAR	0x02
#define PPS_CAPTUREBOTH		0x03

#define PPS_OFFSETASSERT	0x10
#define PPS_OFFSETCLEAR		0x20

#define PPS_ECHOASSERT		0x40
#define PPS_ECHOCLEAR		0x80

#define PPS_CANWAIT		0x100
#define PPS_CANPOLL		0x200

#define PPS_TSFMT_TSPEC		0x1000
#define PPS_TSFMT_NTPFP		0x2000

#define	PPS_TSCLK_FBCK		0x10000
#define	PPS_TSCLK_FFWD		0x20000
#define	PPS_TSCLK_MASK		0x30000

#define PPS_KC_HARDPPS		0
#define PPS_KC_HARDPPS_PLL	1
#define PPS_KC_HARDPPS_FLL	2

struct pps_fetch_args {
	int tsformat;
	pps_info_t	pps_info_buf;
	struct timespec	timeout;
};

struct pps_fetch_ffc_args {
	int		tsformat;
	pps_info_ffc_t	pps_info_buf_ffc;
	struct timespec	timeout;
};

struct pps_kcbind_args {
	int kernel_consumer;
	int edge;
	int tsformat;
};

#define PPS_IOC_CREATE		_IO('1', 1)
#define PPS_IOC_DESTROY		_IO('1', 2)
#define PPS_IOC_SETPARAMS	_IOW('1', 3, pps_params_t)
#define PPS_IOC_GETPARAMS	_IOR('1', 4, pps_params_t)
#define PPS_IOC_GETCAP		_IOR('1', 5, int)
#define PPS_IOC_FETCH		_IOWR('1', 6, struct pps_fetch_args)
#define PPS_IOC_KCBIND		_IOW('1', 7, struct pps_kcbind_args)
#define	PPS_IOC_FETCH_FFCOUNTER	_IOWR('1', 8, struct pps_fetch_ffc_args)

#ifdef _KERNEL

struct pps_state {
	/* Capture information. */
	struct timehands *capth;
	struct fftimehands *capffth;
	unsigned	capgen;
	unsigned	capcount;

	/* State information. */
	pps_params_t	ppsparam;
	pps_info_t	ppsinfo;
	pps_info_ffc_t	ppsinfo_ffc;
	int		kcmode;
	int		ppscap;
	struct timecounter *ppstc;
	unsigned	ppscount[3];
};

void pps_capture(struct pps_state *pps);
void pps_event(struct pps_state *pps, int event);
void pps_init(struct pps_state *pps);
int pps_ioctl(unsigned long cmd, caddr_t data, struct pps_state *pps);
void hardpps(struct timespec *tsp, long nsec);

#else /* !_KERNEL */

static __inline int
time_pps_create(int filedes, pps_handle_t *handle)
{
	int error;

	*handle = -1;
	error = ioctl(filedes, PPS_IOC_CREATE, 0);
	if (error < 0) 
		return (-1);
	*handle = filedes;
	return (0);
}

static __inline int
time_pps_destroy(pps_handle_t handle)
{
	return (ioctl(handle, PPS_IOC_DESTROY, 0));
}

static __inline int
time_pps_setparams(pps_handle_t handle, const pps_params_t *ppsparams)
{
	return (ioctl(handle, PPS_IOC_SETPARAMS, ppsparams));
}

static __inline int
time_pps_getparams(pps_handle_t handle, pps_params_t *ppsparams)
{
	return (ioctl(handle, PPS_IOC_GETPARAMS, ppsparams));
}

static __inline int 
time_pps_getcap(pps_handle_t handle, int *mode)
{
	return (ioctl(handle, PPS_IOC_GETCAP, mode));
}

static __inline int
time_pps_fetch(pps_handle_t handle, const int tsformat,
	pps_info_t *ppsinfobuf, const struct timespec *timeout)
{
	int error;
	struct pps_fetch_args arg;

	arg.tsformat = tsformat;
	if (timeout == NULL) {
		arg.timeout.tv_sec = -1;
		arg.timeout.tv_nsec = -1;
	} else
		arg.timeout = *timeout;
	error = ioctl(handle, PPS_IOC_FETCH, &arg);
	*ppsinfobuf = arg.pps_info_buf;
	return (error);
}

static __inline int
time_pps_fetch_ffc(pps_handle_t handle, const int tsformat,
	pps_info_ffc_t *ppsinfobuf, const struct timespec *timeout)
{
	struct pps_fetch_ffc_args arg;
	int error;

	arg.tsformat = tsformat;
	if (timeout == NULL) {
		arg.timeout.tv_sec = -1;
		arg.timeout.tv_nsec = -1;
	} else {
		arg.timeout = *timeout;
	}
	error = ioctl(handle, PPS_IOC_FETCH_FFCOUNTER, &arg);
	*ppsinfobuf = arg.pps_info_buf_ffc;
	return (error);
}

static __inline int
time_pps_kcbind(pps_handle_t handle, const int kernel_consumer,
	const int edge, const int tsformat)
{
	struct pps_kcbind_args arg;

	arg.kernel_consumer = kernel_consumer;
	arg.edge = edge;
	arg.tsformat = tsformat;
	return (ioctl(handle, PPS_IOC_KCBIND, &arg));
}

#endif /* KERNEL */

#endif /* !_SYS_TIMEPPS_H_ */