xref: /netbsd-src/external/bsd/ntp/dist/include/timepps-SCO.h (revision cdfa2a7ef92791ba9db70a584a1d904730e6fb46)
1*cdfa2a7eSchristos /*	$NetBSD: timepps-SCO.h,v 1.5 2020/05/25 20:47:20 christos Exp $	*/
2abb0f93cSkardel 
3abb0f93cSkardel /***********************************************************************
4abb0f93cSkardel  *								       *
5abb0f93cSkardel  * Copyright (c) David L. Mills 1999-2000			       *
6abb0f93cSkardel  *								       *
7abb0f93cSkardel  * Permission to use, copy, modify, and distribute this software and   *
88585484eSchristos  * its documentation for any purpose and with or without fee is hereby *
9abb0f93cSkardel  * granted, provided that the above copyright notice appears in all    *
10abb0f93cSkardel  * copies and that both the copyright notice and this permission       *
11abb0f93cSkardel  * notice appear in supporting documentation, and that the name        *
12abb0f93cSkardel  * University of Delaware not be used in advertising or publicity      *
13abb0f93cSkardel  * pertaining to distribution of the software without specific,        *
14abb0f93cSkardel  * written prior permission. The University of Delaware makes no       *
15abb0f93cSkardel  * representations about the suitability this software for any	       *
16abb0f93cSkardel  * purpose. It is provided "as is" without express or implied          *
17abb0f93cSkardel  * warranty.							       *
18abb0f93cSkardel  *								       *
19abb0f93cSkardel  ***********************************************************************
20abb0f93cSkardel  *								       *
21abb0f93cSkardel  * This header file complies with "Pulse-Per-Second API for UNIX-like  *
22abb0f93cSkardel  * Operating Systems, Version 1.0", rfc2783. Credit is due Jeff Mogul  *
23abb0f93cSkardel  * and Marc Brett, from whom much of this code was shamelessly stolen. *
24abb0f93cSkardel  *								       *
25abb0f93cSkardel  * this modified timepps.h can be used to provide a PPSAPI interface   *
26abb0f93cSkardel  * to a machine running SCO Unix.				       *
27abb0f93cSkardel  *								       *
28abb0f93cSkardel  ***********************************************************************
29abb0f93cSkardel  *								       *
30abb0f93cSkardel  * A full PPSAPI interface to the SCO Unix kernel would be better, but *
31abb0f93cSkardel  * this at least removes the necessity for special coding from the NTP *
32abb0f93cSkardel  * NTP drivers. 						       *
33abb0f93cSkardel  *								       *
34abb0f93cSkardel  ***********************************************************************
35abb0f93cSkardel  *								       *
36abb0f93cSkardel  * Some of this include file					       *
37abb0f93cSkardel  * Copyright (c) 1999 by Ulrich Windl,				       *
38abb0f93cSkardel  *	based on code by Reg Clemens <reg@dwf.com>		       *
39abb0f93cSkardel  *		based on code by Poul-Henning Kamp <phk@FreeBSD.org>   *
40abb0f93cSkardel  *								       *
41abb0f93cSkardel  ***********************************************************************
42abb0f93cSkardel  *								       *
43abb0f93cSkardel  * "THE BEER-WARE LICENSE" (Revision 42):                              *
44abb0f93cSkardel  * <phk@FreeBSD.org> wrote this file.  As long as you retain this      *
45abb0f93cSkardel  * notice you can do whatever you want with this stuff. If we meet some*
46abb0f93cSkardel  * day, and you think this stuff is worth it, you can buy me a beer    *
47abb0f93cSkardel  * in return.	Poul-Henning Kamp				       *
48abb0f93cSkardel  *								       *
49abb0f93cSkardel  **********************************************************************/
50abb0f93cSkardel 
51abb0f93cSkardel /*SCO UNIX version, TIOCDCDTIMESTAMP assumed to exist. */
52abb0f93cSkardel 
53abb0f93cSkardel #ifndef _SYS_TIMEPPS_H_
54abb0f93cSkardel #define _SYS_TIMEPPS_H_
55abb0f93cSkardel 
56abb0f93cSkardel #include <termios.h>	/* to get TIOCDCDTIMESTAMP */
57abb0f93cSkardel 
58abb0f93cSkardel /* Implementation note: the logical states ``assert'' and ``clear''
59abb0f93cSkardel  * are implemented in terms of the UART register, i.e. ``assert''
60abb0f93cSkardel  * means the bit is set.
61abb0f93cSkardel  */
62abb0f93cSkardel 
63abb0f93cSkardel /*
64abb0f93cSkardel  * The following definitions are architecture independent
65abb0f93cSkardel  */
66abb0f93cSkardel 
67abb0f93cSkardel #define PPS_API_VERS_1	1		/* API version number */
68abb0f93cSkardel #define PPS_JAN_1970	2208988800UL	/* 1970 - 1900 in seconds */
69abb0f93cSkardel #define PPS_NANOSECOND	1000000000L	/* one nanosecond in decimal */
70abb0f93cSkardel #define PPS_FRAC	4294967296.	/* 2^32 as a double */
71abb0f93cSkardel 
72abb0f93cSkardel #define PPS_NORMALIZE(x)	/* normalize timespec */ \
73abb0f93cSkardel 	do { \
74abb0f93cSkardel 		if ((x).tv_nsec >= PPS_NANOSECOND) { \
75abb0f93cSkardel 			(x).tv_nsec -= PPS_NANOSECOND; \
76abb0f93cSkardel 			(x).tv_sec++; \
77abb0f93cSkardel 		} else if ((x).tv_nsec < 0) { \
78abb0f93cSkardel 			(x).tv_nsec += PPS_NANOSECOND; \
79abb0f93cSkardel 			(x).tv_sec--; \
80abb0f93cSkardel 		} \
81abb0f93cSkardel 	} while (0)
82abb0f93cSkardel 
83abb0f93cSkardel #define PPS_TSPECTONTP(x)	/* convert timespec to l_fp */ \
84abb0f93cSkardel 	do { \
85abb0f93cSkardel 		double d_temp; \
86abb0f93cSkardel 	\
87abb0f93cSkardel 		(x).integral += (unsigned int)PPS_JAN_1970; \
88abb0f93cSkardel 		d_temp = (x).fractional * PPS_FRAC / PPS_NANOSECOND; \
89abb0f93cSkardel 		if (d_temp >= PPS_FRAC) \
90abb0f93cSkardel 			(x).integral++; \
91abb0f93cSkardel 		(x).fractional = (unsigned int)d_temp; \
92abb0f93cSkardel 	} while (0)
93abb0f93cSkardel 
94abb0f93cSkardel /*
95abb0f93cSkardel  * Device/implementation parameters (mode)
96abb0f93cSkardel  */
97abb0f93cSkardel 
98abb0f93cSkardel #define PPS_CAPTUREASSERT	0x01	/* capture assert events */
99abb0f93cSkardel #define PPS_CAPTURECLEAR	0x02	/* capture clear events */
100abb0f93cSkardel #define PPS_CAPTUREBOTH 	0x03	/* capture assert and clear events */
101abb0f93cSkardel 
102abb0f93cSkardel #define PPS_OFFSETASSERT	0x10	/* apply compensation for assert ev. */
103abb0f93cSkardel #define PPS_OFFSETCLEAR 	0x20	/* apply compensation for clear ev. */
104abb0f93cSkardel #define PPS_OFFSETBOTH		0x30	/* apply compensation for both */
105abb0f93cSkardel 
106abb0f93cSkardel #define PPS_CANWAIT		0x100	/* Can we wait for an event? */
107abb0f93cSkardel #define PPS_CANPOLL		0x200	/* "This bit is reserved for */
108abb0f93cSkardel 
109abb0f93cSkardel /*
110abb0f93cSkardel  * Kernel actions (mode)
111abb0f93cSkardel  */
112abb0f93cSkardel 
113abb0f93cSkardel #define PPS_ECHOASSERT		0x40	/* feed back assert event to output */
114abb0f93cSkardel #define PPS_ECHOCLEAR		0x80	/* feed back clear event to output */
115abb0f93cSkardel 
116abb0f93cSkardel /*
117abb0f93cSkardel  * Timestamp formats (tsformat)
118abb0f93cSkardel  */
119abb0f93cSkardel 
120abb0f93cSkardel #define PPS_TSFMT_TSPEC 	0x1000	/* select timespec format */
121abb0f93cSkardel #define PPS_TSFMT_NTPFP 	0x2000	/* select NTP format */
122abb0f93cSkardel 
123abb0f93cSkardel /*
124abb0f93cSkardel  * Kernel discipline actions (not used in Solaris)
125abb0f93cSkardel  */
126abb0f93cSkardel 
127abb0f93cSkardel #define PPS_KC_HARDPPS		0	/* enable kernel consumer */
128abb0f93cSkardel #define PPS_KC_HARDPPS_PLL	1	/* phase-lock mode */
129abb0f93cSkardel #define PPS_KC_HARDPPS_FLL	2	/* frequency-lock mode */
130abb0f93cSkardel 
131abb0f93cSkardel /*
132abb0f93cSkardel  * Type definitions
133abb0f93cSkardel  */
134abb0f93cSkardel 
135abb0f93cSkardel typedef unsigned long pps_seq_t;	/* sequence number */
136abb0f93cSkardel 
137abb0f93cSkardel typedef struct ntp_fp {
138abb0f93cSkardel 	unsigned int	integral;
139abb0f93cSkardel 	unsigned int	fractional;
140abb0f93cSkardel } ntp_fp_t;				/* NTP-compatible time stamp */
141abb0f93cSkardel 
142abb0f93cSkardel typedef union pps_timeu {		/* timestamp format */
143abb0f93cSkardel 	struct timespec tspec;
144abb0f93cSkardel 	ntp_fp_t	ntpfp;
145abb0f93cSkardel 	unsigned long	longpad[3];
146abb0f93cSkardel } pps_timeu_t;				/* generic data type to represent time stamps */
147abb0f93cSkardel 
148abb0f93cSkardel /*
149abb0f93cSkardel  * Timestamp information structure
150abb0f93cSkardel  */
151abb0f93cSkardel 
152abb0f93cSkardel typedef struct pps_info {
153abb0f93cSkardel 	pps_seq_t	assert_sequence;	/* seq. num. of assert event */
154abb0f93cSkardel 	pps_seq_t	clear_sequence; 	/* seq. num. of clear event */
155abb0f93cSkardel 	pps_timeu_t	assert_tu;		/* time of assert event */
156abb0f93cSkardel 	pps_timeu_t	clear_tu;		/* time of clear event */
157abb0f93cSkardel 	int		current_mode;		/* current mode bits */
158abb0f93cSkardel } pps_info_t;
159abb0f93cSkardel 
160abb0f93cSkardel #define assert_timestamp	assert_tu.tspec
161abb0f93cSkardel #define clear_timestamp 	clear_tu.tspec
162abb0f93cSkardel 
163abb0f93cSkardel #define assert_timestamp_ntpfp	assert_tu.ntpfp
164abb0f93cSkardel #define clear_timestamp_ntpfp	clear_tu.ntpfp
165abb0f93cSkardel 
166abb0f93cSkardel /*
167abb0f93cSkardel  * Parameter structure
168abb0f93cSkardel  */
169abb0f93cSkardel 
170abb0f93cSkardel typedef struct pps_params {
171abb0f93cSkardel 	int		api_version;	/* API version # */
172abb0f93cSkardel 	int		mode;		/* mode bits */
173abb0f93cSkardel 	pps_timeu_t assert_off_tu;	/* offset compensation for assert */
174abb0f93cSkardel 	pps_timeu_t clear_off_tu;	/* offset compensation for clear */
175abb0f93cSkardel } pps_params_t;
176abb0f93cSkardel 
177abb0f93cSkardel #define assert_offset		assert_off_tu.tspec
178abb0f93cSkardel #define clear_offset		clear_off_tu.tspec
179abb0f93cSkardel 
180abb0f93cSkardel #define assert_offset_ntpfp	assert_off_tu.ntpfp
181abb0f93cSkardel #define clear_offset_ntpfp	clear_off_tu.ntpfp
182abb0f93cSkardel 
183abb0f93cSkardel /*
184abb0f93cSkardel  * The following definitions are architecture-dependent
185abb0f93cSkardel  */
186abb0f93cSkardel 
187abb0f93cSkardel #define PPS_CAP (PPS_CAPTUREASSERT | PPS_OFFSETASSERT | PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)
188abb0f93cSkardel #define PPS_RO	(PPS_CANWAIT | PPS_CANPOLL | PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)
189abb0f93cSkardel 
190abb0f93cSkardel typedef struct {
191abb0f93cSkardel 	int filedes;		/* file descriptor */
192abb0f93cSkardel 	pps_params_t params;	/* PPS parameters set by user */
193abb0f93cSkardel 	struct timeval	tv_save;
194abb0f93cSkardel 	pps_seq_t serial;
195abb0f93cSkardel } pps_unit_t;
196abb0f93cSkardel 
197abb0f93cSkardel typedef pps_unit_t* pps_handle_t; /* pps handlebars */
198abb0f93cSkardel 
199abb0f93cSkardel /*
200abb0f93cSkardel  *------ Here begins the implementation-specific part! ------
201abb0f93cSkardel  */
202abb0f93cSkardel 
203abb0f93cSkardel #include <errno.h>
204abb0f93cSkardel 
205abb0f93cSkardel /*
206abb0f93cSkardel  * create PPS handle from file descriptor
207abb0f93cSkardel  */
208abb0f93cSkardel 
209abb0f93cSkardel static inline int
time_pps_create(int filedes,pps_handle_t * handle)210abb0f93cSkardel time_pps_create(
211abb0f93cSkardel 	int filedes,		/* file descriptor */
212abb0f93cSkardel 	pps_handle_t *handle	/* returned handle */
213abb0f93cSkardel 	)
214abb0f93cSkardel {
215abb0f93cSkardel 	int one = 1;
216abb0f93cSkardel 
217abb0f93cSkardel 	/*
218abb0f93cSkardel 	 * Check for valid arguments and attach PPS signal.
219abb0f93cSkardel 	 */
220abb0f93cSkardel 
221abb0f93cSkardel 	if (!handle) {
222abb0f93cSkardel 		errno = EFAULT;
223abb0f93cSkardel 		return (-1);	/* null pointer */
224abb0f93cSkardel 	}
225abb0f93cSkardel 
226abb0f93cSkardel 	/*
227abb0f93cSkardel 	 * Allocate and initialize default unit structure.
228abb0f93cSkardel 	 */
229abb0f93cSkardel 
230abb0f93cSkardel 	*handle = malloc(sizeof(pps_unit_t));
231abb0f93cSkardel 	if (!(*handle)) {
232abb0f93cSkardel 		errno = EBADF;
233abb0f93cSkardel 		return (-1);	/* what, no memory? */
234abb0f93cSkardel 	}
235abb0f93cSkardel 
236abb0f93cSkardel 	memset(*handle, 0, sizeof(pps_unit_t));
237abb0f93cSkardel 	(*handle)->filedes = filedes;
238abb0f93cSkardel 	(*handle)->params.api_version = PPS_API_VERS_1;
239abb0f93cSkardel 	(*handle)->params.mode = PPS_CAPTUREASSERT | PPS_TSFMT_TSPEC;
240abb0f93cSkardel 	return (0);
241abb0f93cSkardel }
242abb0f93cSkardel 
243abb0f93cSkardel /*
244abb0f93cSkardel  * release PPS handle
245abb0f93cSkardel  */
246abb0f93cSkardel 
247abb0f93cSkardel static inline int
time_pps_destroy(pps_handle_t handle)248abb0f93cSkardel time_pps_destroy(
249abb0f93cSkardel 	pps_handle_t handle
250abb0f93cSkardel 	)
251abb0f93cSkardel {
252abb0f93cSkardel 	/*
253abb0f93cSkardel 	 * Check for valid arguments and detach PPS signal.
254abb0f93cSkardel 	 */
255abb0f93cSkardel 
256abb0f93cSkardel 	if (!handle) {
257abb0f93cSkardel 		errno = EBADF;
258abb0f93cSkardel 		return (-1);	/* bad handle */
259abb0f93cSkardel 	}
260abb0f93cSkardel 	free(handle);
261abb0f93cSkardel 	return (0);
262abb0f93cSkardel }
263abb0f93cSkardel 
264abb0f93cSkardel /*
265abb0f93cSkardel  * set parameters for handle
266abb0f93cSkardel  */
267abb0f93cSkardel 
268abb0f93cSkardel static inline int
time_pps_setparams(pps_handle_t handle,const pps_params_t * params)269abb0f93cSkardel time_pps_setparams(
270abb0f93cSkardel 	pps_handle_t handle,
271abb0f93cSkardel 	const pps_params_t *params
272abb0f93cSkardel 	)
273abb0f93cSkardel {
274abb0f93cSkardel 	int	mode, mode_in;
275abb0f93cSkardel 	/*
276abb0f93cSkardel 	 * Check for valid arguments and set parameters.
277abb0f93cSkardel 	 */
278abb0f93cSkardel 
279abb0f93cSkardel 	if (!handle) {
280abb0f93cSkardel 		errno = EBADF;
281abb0f93cSkardel 		return (-1);	/* bad handle */
282abb0f93cSkardel 	}
283abb0f93cSkardel 
284abb0f93cSkardel 	if (!params) {
285abb0f93cSkardel 		errno = EFAULT;
286abb0f93cSkardel 		return (-1);	/* bad argument */
287abb0f93cSkardel 	}
288abb0f93cSkardel 
289abb0f93cSkardel 	/*
290abb0f93cSkardel 	 * There was no reasonable consensu in the API working group.
291abb0f93cSkardel 	 * I require `api_version' to be set!
292abb0f93cSkardel 	 */
293abb0f93cSkardel 
294abb0f93cSkardel 	if (params->api_version != PPS_API_VERS_1) {
295abb0f93cSkardel 		errno = EINVAL;
296abb0f93cSkardel 		return(-1);
297abb0f93cSkardel 	}
298abb0f93cSkardel 
299abb0f93cSkardel 	/*
300abb0f93cSkardel 	 * only settable modes are PPS_CAPTUREASSERT and PPS_OFFSETASSERT
301abb0f93cSkardel 	 */
302abb0f93cSkardel 
303abb0f93cSkardel 	mode_in = params->mode;
304abb0f93cSkardel 
305abb0f93cSkardel 	/* turn off read-only bits */
306abb0f93cSkardel 
307abb0f93cSkardel 	mode_in &= ~PPS_RO;
308abb0f93cSkardel 
309abb0f93cSkardel 	/* test remaining bits, should only have captureassert and/or offsetassert */
310abb0f93cSkardel 
311abb0f93cSkardel 	if (mode_in & ~(PPS_CAPTUREASSERT | PPS_OFFSETASSERT)) {
312abb0f93cSkardel 		errno = EOPNOTSUPP;
313abb0f93cSkardel 		return(-1);
314abb0f93cSkardel 	}
315abb0f93cSkardel 
316abb0f93cSkardel 	/*
317abb0f93cSkardel 	 * ok, ready to go.
318abb0f93cSkardel 	 */
319abb0f93cSkardel 
320abb0f93cSkardel 	mode = handle->params.mode;
321abb0f93cSkardel 	memcpy(&handle->params, params, sizeof(pps_params_t));
322abb0f93cSkardel 	handle->params.api_version = PPS_API_VERS_1;
323abb0f93cSkardel 	handle->params.mode = mode | mode_in;
324abb0f93cSkardel 	return (0);
325abb0f93cSkardel }
326abb0f93cSkardel 
327abb0f93cSkardel /*
328abb0f93cSkardel  * get parameters for handle
329abb0f93cSkardel  */
330abb0f93cSkardel 
331abb0f93cSkardel static inline int
time_pps_getparams(pps_handle_t handle,pps_params_t * params)332abb0f93cSkardel time_pps_getparams(
333abb0f93cSkardel 	pps_handle_t handle,
334abb0f93cSkardel 	pps_params_t *params
335abb0f93cSkardel 	)
336abb0f93cSkardel {
337abb0f93cSkardel 	/*
338abb0f93cSkardel 	 * Check for valid arguments and get parameters.
339abb0f93cSkardel 	 */
340abb0f93cSkardel 
341abb0f93cSkardel 	if (!handle) {
342abb0f93cSkardel 		errno = EBADF;
343abb0f93cSkardel 		return (-1);	/* bad handle */
344abb0f93cSkardel 	}
345abb0f93cSkardel 
346abb0f93cSkardel 	if (!params) {
347abb0f93cSkardel 		errno = EFAULT;
348abb0f93cSkardel 		return (-1);	/* bad argument */
349abb0f93cSkardel 	}
350abb0f93cSkardel 
351abb0f93cSkardel 	memcpy(params, &handle->params, sizeof(pps_params_t));
352abb0f93cSkardel 	return (0);
353abb0f93cSkardel }
354abb0f93cSkardel 
355abb0f93cSkardel /* (
356abb0f93cSkardel  * get capabilities for handle
357abb0f93cSkardel  */
358abb0f93cSkardel 
359abb0f93cSkardel static inline int
time_pps_getcap(pps_handle_t handle,int * mode)360abb0f93cSkardel time_pps_getcap(
361abb0f93cSkardel 	pps_handle_t handle,
362abb0f93cSkardel 	int *mode
363abb0f93cSkardel 	)
364abb0f93cSkardel {
365abb0f93cSkardel 	/*
366abb0f93cSkardel 	 * Check for valid arguments and get capabilities.
367abb0f93cSkardel 	 */
368abb0f93cSkardel 
369abb0f93cSkardel 	if (!handle) {
370abb0f93cSkardel 		errno = EBADF;
371abb0f93cSkardel 		return (-1);	/* bad handle */
372abb0f93cSkardel 	}
373abb0f93cSkardel 
374abb0f93cSkardel 	if (!mode) {
375abb0f93cSkardel 		errno = EFAULT;
376abb0f93cSkardel 		return (-1);	/* bad argument */
377abb0f93cSkardel 	}
378abb0f93cSkardel 	*mode = PPS_CAP;
379abb0f93cSkardel 	return (0);
380abb0f93cSkardel }
381abb0f93cSkardel 
382abb0f93cSkardel /*
383abb0f93cSkardel  * Fetch timestamps
384abb0f93cSkardel  */
385abb0f93cSkardel 
386abb0f93cSkardel static inline int
time_pps_fetch(pps_handle_t handle,const int tsformat,pps_info_t * ppsinfo,const struct timespec * timeout)387abb0f93cSkardel time_pps_fetch(
388abb0f93cSkardel 	pps_handle_t handle,
389abb0f93cSkardel 	const int tsformat,
390abb0f93cSkardel 	pps_info_t *ppsinfo,
391abb0f93cSkardel 	const struct timespec *timeout
392abb0f93cSkardel 	)
393abb0f93cSkardel {
394abb0f93cSkardel 	struct timeval tv;
395abb0f93cSkardel 	pps_info_t infobuf;
396abb0f93cSkardel 
397abb0f93cSkardel 	/*
398abb0f93cSkardel 	 * Check for valid arguments and fetch timestamps
399abb0f93cSkardel 	 */
400abb0f93cSkardel 
401abb0f93cSkardel 	if (!handle) {
402abb0f93cSkardel 		errno = EBADF;
403abb0f93cSkardel 		return (-1);	/* bad handle */
404abb0f93cSkardel 	}
405abb0f93cSkardel 
406abb0f93cSkardel 	if (!ppsinfo) {
407abb0f93cSkardel 		errno = EFAULT;
408abb0f93cSkardel 		return (-1);	/* bad argument */
409abb0f93cSkardel 	}
410abb0f93cSkardel 
411abb0f93cSkardel 	/*
412abb0f93cSkardel 	 * nb. PPS_CANWAIT is NOT set by the implementation, we can totally
413abb0f93cSkardel 	 * ignore the timeout variable.
414abb0f93cSkardel 	 */
415abb0f93cSkardel 
416abb0f93cSkardel 	memset(&infobuf, 0, sizeof(infobuf));
417abb0f93cSkardel 
418abb0f93cSkardel 	/*
419abb0f93cSkardel 	 * if not captureassert, nothing to return.
420abb0f93cSkardel 	 */
421abb0f93cSkardel 
422abb0f93cSkardel 	if (!handle->params.mode & PPS_CAPTUREASSERT) {
423abb0f93cSkardel 		memcpy(ppsinfo, &infobuf, sizeof(pps_info_t));
424abb0f93cSkardel 		return (0);
425abb0f93cSkardel 	}
426abb0f93cSkardel 
427abb0f93cSkardel 	if (ioctl(instance->filedes, TIOCDCDTIMESTAMP, &tv) < 0) {
428abb0f93cSkardel 		perror("time_pps_fetch:");
429abb0f93cSkardel 		errno = EOPNOTSUPP;
430abb0f93cSkardel 		return(-1);
431abb0f93cSkardel 	}
432abb0f93cSkardel 
433abb0f93cSkardel 	/*
434abb0f93cSkardel 	 * fake serial here
435abb0f93cSkardel 	 */
436abb0f93cSkardel 
437abb0f93cSkardel 	if (tv.tv_sec != handle->tv_save.tv_sec || tv.tv_usec != handle->tv_save.tv_usec) {
438abb0f93cSkardel 		handle->tv_save = tv;
439abb0f93cSkardel 		handle->serial++;
440abb0f93cSkardel 	}
441abb0f93cSkardel 
442abb0f93cSkardel 	/*
443abb0f93cSkardel 	 * Apply offsets as specified. Note that only assert timestamps
444abb0f93cSkardel 	 * are captured by this interface.
445abb0f93cSkardel 	 */
446abb0f93cSkardel 
447abb0f93cSkardel 	infobuf.assert_sequence = handle->serial;
448abb0f93cSkardel 	infobuf.assert_timestamp.tv_sec = tv.tv_sec;
449abb0f93cSkardel 	infobuf.assert_timestamp.tv_nsec = tv.tv_usec * 1000;
450abb0f93cSkardel 
451abb0f93cSkardel 	if (handle->params.mode & PPS_OFFSETASSERT) {
452abb0f93cSkardel 		infobuf.assert_timestamp.tv_sec  += handle->params.assert_offset.tv_sec;
453abb0f93cSkardel 		infobuf.assert_timestamp.tv_nsec += handle->params.assert_offset.tv_nsec;
454abb0f93cSkardel 		PPS_NORMALIZE(infobuf.assert_timestamp);
455abb0f93cSkardel 	}
456abb0f93cSkardel 
457abb0f93cSkardel 	/*
458abb0f93cSkardel 	 * Translate to specified format
459abb0f93cSkardel 	 */
460abb0f93cSkardel 
461abb0f93cSkardel 	switch (tsformat) {
462abb0f93cSkardel 	case PPS_TSFMT_TSPEC:
463abb0f93cSkardel 		break;		 /* timespec format requires no translation */
464abb0f93cSkardel 
465abb0f93cSkardel 	case PPS_TSFMT_NTPFP:	/* NTP format requires conversion to fraction form */
466abb0f93cSkardel 		PPS_TSPECTONTP(infobuf.assert_timestamp_ntpfp);
467abb0f93cSkardel 		break;
468abb0f93cSkardel 
469abb0f93cSkardel 	default:
470abb0f93cSkardel 		errno = EINVAL;
471abb0f93cSkardel 		return (-1);
472abb0f93cSkardel 	}
473abb0f93cSkardel 
474abb0f93cSkardel 	infobuf.current_mode = handle->params.mode;
475abb0f93cSkardel 	memcpy(ppsinfo, &infobuf, sizeof(pps_info_t));
476abb0f93cSkardel 	return (0);
477abb0f93cSkardel }
478abb0f93cSkardel 
479abb0f93cSkardel /*
480abb0f93cSkardel  * specify kernel consumer
481abb0f93cSkardel  */
482abb0f93cSkardel 
483abb0f93cSkardel static inline int
time_pps_kcbind(pps_handle_t handle,const int kernel_consumer,const int edge,const int tsformat)484abb0f93cSkardel time_pps_kcbind(
485abb0f93cSkardel 	pps_handle_t handle,
486abb0f93cSkardel 	const int kernel_consumer,
487abb0f93cSkardel 	const int edge, const int tsformat
488abb0f93cSkardel 	)
489abb0f93cSkardel {
490abb0f93cSkardel 	/*
491abb0f93cSkardel 	 * Check for valid arguments and bind kernel consumer
492abb0f93cSkardel 	 */
493abb0f93cSkardel 	if (!handle) {
494abb0f93cSkardel 		errno = EBADF;
495abb0f93cSkardel 		return (-1);	/* bad handle */
496abb0f93cSkardel 	}
497abb0f93cSkardel 	if (geteuid() != 0) {
498abb0f93cSkardel 		errno = EPERM;
499abb0f93cSkardel 		return (-1);	/* must be superuser */
500abb0f93cSkardel 	}
501abb0f93cSkardel 	errno = EOPNOTSUPP;
502abb0f93cSkardel 	return(-1);
503abb0f93cSkardel }
504abb0f93cSkardel 
505abb0f93cSkardel #endif /* _SYS_TIMEPPS_H_ */
506