Annotation of embedaddon/ntp/ports/winnt/include/timepps.h, revision 1.1.1.1
1.1 misho 1: /***********************************************************************
2: * *
3: * Copyright (c) David L. Mills 1999-2009 *
4: * *
5: * Permission to use, copy, modify, and distribute this software and *
6: * its documentation for any purpose and without fee is hereby *
7: * granted, provided that the above copyright notice appears in all *
8: * copies and that both the copyright notice and this permission *
9: * notice appear in supporting documentation, and that the name *
10: * University of Delaware not be used in advertising or publicity *
11: * pertaining to distribution of the software without specific, *
12: * written prior permission. The University of Delaware makes no *
13: * representations about the suitability this software for any *
14: * purpose. It is provided "as is" without express or implied *
15: * warranty. *
16: * *
17: ***********************************************************************
18: * *
19: * This header file complies with "Pulse-Per-Second API for UNIX-like *
20: * Operating Systems, Version 1.0", rfc2783. Credit is due Jeff Mogul *
21: * and Marc Brett, from whom much of this code was shamelessly stolen. *
22: * *
23: * This modified timepps.h can be used to provide a PPSAPI interface *
24: * to a machine running Windows with one or more backend provider DLLs *
25: * implementing the provider interfaces defined herein. *
26: * *
27: * This Windows version was derived by Dave Hart *
28: * <davehart@davehart.com> from Mills' timepps-Solaris.h *
29: * *
30: ***********************************************************************
31: * *
32: * Some of this include file *
33: * Copyright (c) 1999 by Ulrich Windl, *
34: * based on code by Reg Clemens <reg@dwf.com> *
35: * based on code by Poul-Henning Kamp <phk@FreeBSD.org> *
36: * *
37: ***********************************************************************
38: * *
39: * "THE BEER-WARE LICENSE" (Revision 42): *
40: * <phk@FreeBSD.org> wrote this file. As long as you retain this *
41: * notice you can do whatever you want with this stuff. If we meet some*
42: * day, and you think this stuff is worth it, you can buy me a beer *
43: * in return. Poul-Henning Kamp *
44: * *
45: **********************************************************************/
46:
47: #ifndef TIMEPPS_H
48: #define TIMEPPS_H
49:
50: #include "sys/time.h" /* in ntp ref source declares struct timespec */
51:
52: /*
53: * The following definitions are architecture independent
54: */
55:
56: #define PPS_API_VERS_1 1 /* API version number */
57: #define PPS_JAN_1970 2208988800UL /* 1970 - 1900 in seconds */
58: #define PPS_NANOSECOND 1000000000L /* one nanosecond in decimal */
59: #define PPS_FRAC 4294967296. /* 2^32 as a double */
60: #define PPS_HECTONANOSECONDS 10000000 /* 100ns units in a second */
61: #define PPS_FILETIME_1970 0x019db1ded53e8000 /* unix epoch to Windows */
62:
63: #define PPS_NORMALIZE(x) /* normalize timespec */ \
64: do { \
65: if ((x).tv_nsec >= PPS_NANOSECOND) { \
66: (x).tv_nsec -= PPS_NANOSECOND; \
67: (x).tv_sec++; \
68: } else if ((x).tv_nsec < 0) { \
69: (x).tv_nsec += PPS_NANOSECOND; \
70: (x).tv_sec--; \
71: } \
72: } while (0)
73:
74: #define PPS_TSPECTONTP(x) /* convert timespec to ntp_fp */ \
75: do { \
76: double d_frac; \
77: \
78: d_frac = ((struct timespec)&(x))->tv_nsec \
79: * PPS_FRAC / PPS_NANOSECOND; \
80: (x).integral = ((struct timespec)&(x))->tv_sec \
81: + PPS_JAN_1970; \
82: (x).fractional = (unsigned int)d_frac; \
83: if (d_frac >= PPS_FRAC) \
84: (x).integral++; \
85: } while (0)
86:
87: #define PPS_NTPTOTSPEC(x) /* convert ntp_fp to timespec */ \
88: do { \
89: double d_frac; \
90: \
91: /* careful, doing in place and tv_sec may be 64bit */ \
92: d_frac = (double)((ntp_fp_t *)&(x))->fractional \
93: * PPS_NANOSECOND / PPS_FRAC; \
94: (x).tv_sec = ((ntp_fp_t *)&(x))->integral \
95: - (time_t)PPS_JAN_1970; \
96: (x).tv_nsec = (long)d_frac; \
97: } while (0)
98:
99:
100: /*
101: * Device/implementation parameters (mode)
102: */
103:
104: #define PPS_CAPTUREASSERT 0x01 /* capture assert events */
105: #define PPS_CAPTURECLEAR 0x02 /* capture clear events */
106: #define PPS_CAPTUREBOTH 0x03 /* capture assert and clear events */
107:
108: #define PPS_OFFSETASSERT 0x10 /* apply compensation for assert ev. */
109: #define PPS_OFFSETCLEAR 0x20 /* apply compensation for clear ev. */
110: #define PPS_OFFSETBOTH 0x30 /* apply compensation for both */
111:
112: #define PPS_CANWAIT 0x100 /* Can we wait for an event? */
113: #define PPS_CANPOLL 0x200 /* "This bit is reserved for */
114:
115: /*
116: * Kernel actions (mode)
117: */
118:
119: #define PPS_ECHOASSERT 0x40 /* feed back assert event to output */
120: #define PPS_ECHOCLEAR 0x80 /* feed back clear event to output */
121:
122: /*
123: * Timestamp formats (tsformat)
124: */
125:
126: #define PPS_TSFMT_TSPEC 0x1000 /* select timespec format */
127: #define PPS_TSFMT_NTPFP 0x2000 /* select NTP format */
128: #define PPS_TSFMT_BOTH (PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)
129:
130: /*
131: * Kernel discipline actions (not used in Windows yet)
132: */
133:
134: #define PPS_KC_HARDPPS 0 /* enable kernel consumer */
135: #define PPS_KC_HARDPPS_PLL 1 /* phase-lock mode */
136: #define PPS_KC_HARDPPS_FLL 2 /* frequency-lock mode */
137:
138: /*
139: * Type definitions
140: */
141:
142: typedef unsigned long pps_seq_t; /* sequence number */
143:
144: #pragma warning(push)
145: #pragma warning(disable: 201) /* nonstd extension nameless union */
146:
147: typedef struct ntp_fp {
148: union ntp_fp_sec {
149: unsigned int integral;
150: int s_integral;
151: };
152: unsigned int fractional;
153: } ntp_fp_t; /* NTP-compatible time stamp */
154:
155: #pragma warning(pop)
156:
157: typedef union pps_timeu { /* timestamp format */
158: struct timespec tspec;
159: ntp_fp_t ntpfp;
160: unsigned long longpad[3];
161: } pps_timeu_t; /* generic data type to represent time stamps */
162:
163: /* addition of NTP fixed-point format */
164:
165: #define NTPFP_M_ADD(r_i, r_f, a_i, a_f) /* r += a */ \
166: do { \
167: register u_int32 lo_tmp; \
168: register u_int32 hi_tmp; \
169: \
170: lo_tmp = ((r_f) & 0xffff) + ((a_f) & 0xffff); \
171: hi_tmp = (((r_f) >> 16) & 0xffff) + (((a_f) >> 16) & 0xffff); \
172: if (lo_tmp & 0x10000) \
173: hi_tmp++; \
174: (r_f) = ((hi_tmp & 0xffff) << 16) | (lo_tmp & 0xffff); \
175: \
176: (r_i) += (a_i); \
177: if (hi_tmp & 0x10000) \
178: (r_i)++; \
179: } while (0)
180:
181: #define NTPFP_L_ADDS(r, a) NTPFP_M_ADD((r)->integral, (r)->fractional, \
182: (a)->s_integral, (a)->fractional)
183:
184:
185: /*
186: * Timestamp information structure
187: */
188:
189: typedef struct pps_info {
190: pps_seq_t assert_sequence; /* seq. num. of assert event */
191: pps_seq_t clear_sequence; /* seq. num. of clear event */
192: pps_timeu_t assert_tu; /* time of assert event */
193: pps_timeu_t clear_tu; /* time of clear event */
194: int current_mode; /* current mode bits */
195: } pps_info_t;
196:
197: #define assert_timestamp assert_tu.tspec
198: #define clear_timestamp clear_tu.tspec
199:
200: #define assert_timestamp_ntpfp assert_tu.ntpfp
201: #define clear_timestamp_ntpfp clear_tu.ntpfp
202:
203: /*
204: * Parameter structure
205: */
206:
207: typedef struct pps_params {
208: int api_version; /* API version # */
209: int mode; /* mode bits */
210: pps_timeu_t assert_off_tu; /* offset compensation for assert */
211: pps_timeu_t clear_off_tu; /* offset compensation for clear */
212: } pps_params_t;
213:
214: #define assert_offset assert_off_tu.tspec
215: #define clear_offset clear_off_tu.tspec
216:
217: #define assert_offset_ntpfp assert_off_tu.ntpfp
218: #define clear_offset_ntpfp clear_off_tu.ntpfp
219:
220: /*
221: *------ Here begins the implementation-specific part! ------
222: */
223:
224: #include <windows.h>
225: #include <errno.h>
226: #include <stddef.h> /* offsetof() */
227: #include <io.h> /* _get_osfhandle() */
228:
229: #ifndef EOPNOTSUPP
230: #define EOPNOTSUPP 45
231: #endif
232:
233: typedef UINT_PTR pps_handle_t; /* pps handlebars */
234:
235: #ifndef inline
236: #define inline __inline
237: #endif
238:
239: /*
240: * ntpd on Windows is typically distributed as a binary as few users
241: * have the tools needed to build from source. Rather than build
242: * a single timepps.h for Windows which knows how to talk to all
243: * PPS implementations frozen in time as of compiling, this timepps.h
244: * allows one or more backend providers to be used by naming a DLL
245: * which exports the provider interfaces defined here.
246: */
247: typedef enum ppsapi_magic_tag {
248: PPSAPI_MAGIC_UNIT = 0x70707355, /* ppsU */
249: } ppsapi_magic;
250:
251: typedef struct {
252: struct pps_provider_tag *provider;
253: void * context;/* provider's unit pointer */
254: ppsapi_magic magic; /* to detect invalid handles */
255: pps_params_t params; /* PPS parameters set by user */
256: } pps_unit_t;
257:
258: typedef void (*ppps_ntp_timestamp_from_counter)(
259: ntp_fp_t *result,
260: ULONGLONG Timestamp,
261: ULONGLONG Counterstamp
262: );
263:
264: typedef pps_handle_t (*pcreate_pps_handle)(
265: void * prov_context
266: );
267:
268: /*
269: * ppsapi_prov_init() - exported by backend DLLs
270: *
271: * Return value is pps capabilities available to PPSAPI consumers
272: * via time_pps_getcaps().
273: */
274: #define PPSAPI_TIMEPPS_PROV_VER 2
275:
276: typedef int (WINAPI *pppsapi_prov_init)(
277: int ppsapi_timepps_prov_ver,
278: pcreate_pps_handle create_pps_handle,
279: ppps_ntp_timestamp_from_counter ntp_timestamp_from_counter,
280: char * short_name_buf,
281: size_t short_name_size,
282: char * full_name_buf,
283: size_t full_name_size
284: );
285:
286: typedef int (WINAPI *provtime_pps_create)(
287: HANDLE winhandle, /* user device handle */
288: pps_handle_t *phandle /* returned handle */
289: );
290:
291: typedef int (WINAPI *provtime_pps_destroy)(
292: pps_unit_t * unit,
293: void * context
294: );
295:
296: typedef int (WINAPI *provtime_pps_setparams)(
297: pps_unit_t * unit,
298: void * context,
299: const pps_params_t * params
300: );
301:
302: typedef int (WINAPI *provtime_pps_fetch)(
303: pps_unit_t * unit,
304: void * context,
305: const int tsformat,
306: pps_info_t * pinfo,
307: const struct timespec * timeout
308: );
309:
310: typedef int (WINAPI *provtime_pps_kcbind)(
311: pps_unit_t * unit,
312: void * context,
313: const int kernel_consumer,
314: const int edge,
315: const int tsformat
316: );
317:
318: typedef struct pps_provider_tag {
319: struct pps_provider_tag *next;
320: int caps;
321: char * short_name;
322: char * full_name;
323: provtime_pps_create ptime_pps_create;
324: provtime_pps_destroy ptime_pps_destroy;
325: provtime_pps_setparams ptime_pps_setparams;
326: provtime_pps_fetch ptime_pps_fetch;
327: provtime_pps_kcbind ptime_pps_kcbind;
328: } ppsapi_provider;
329:
330: static ppsapi_provider * g_provider_list;
331: static ppsapi_provider * g_curr_provider;
332:
333:
334: static inline pps_handle_t
335: internal_create_pps_handle(
336: void * prov_context
337: )
338: {
339: pps_unit_t * punit;
340:
341: if (NULL == g_curr_provider) {
342: fprintf(stderr, "create_pps_handle: provider backend called me outside time_pps_create\n");
343: punit = NULL;
344: } else
345: punit = malloc(sizeof(*punit));
346: if (punit != NULL) {
347: punit->provider = g_curr_provider;
348: punit->context = prov_context;
349: punit->magic = PPSAPI_MAGIC_UNIT;
350: memset(&punit->params, 0, sizeof(punit->params));
351: }
352: return (pps_handle_t)punit;
353: }
354:
355: static inline pps_unit_t *
356: unit_from_ppsapi_handle(
357: pps_handle_t handle
358: )
359: {
360: pps_unit_t *punit;
361:
362: punit = (pps_unit_t *)handle;
363: if (PPSAPI_MAGIC_UNIT != punit->magic)
364: punit = NULL;
365: return punit;
366: }
367:
368: /*
369: * ntpd on Windows only looks to errno after finding
370: * GetLastError returns NO_ERROR. To accomodate its
371: * use of msyslog in portable code such as refclock_atom.c,
372: * this implementation always clears the Windows
373: * error code using SetLastError(NO_ERROR) when
374: * returning an errno. This is also a good idea
375: * for any non-ntpd clients as they should rely only
376: * the errno for PPSAPI functions.
377: */
378: #define RETURN_PPS_ERRNO(e) \
379: do { \
380: SetLastError(NO_ERROR); \
381: errno = (e); \
382: return -1; \
383: } while (0)
384:
385:
386: #ifdef OWN_PPS_NTP_TIMESTAMP_FROM_COUNTER
387: extern void pps_ntp_timestamp_from_counter(ntp_fp_t *, ULONGLONG, ULONGLONG);
388: #else
389: /*
390: * helper routine for serialpps.sys ioctl which returns
391: * performance counter "timestamp" as well as a system
392: * FILETIME timestamp. Converts one of the inputs to
393: * NTP fixed-point format.
394: *
395: * You will probably want to supply your own and #define
396: * OWN_PPS_NTP_TIMESTAMP_FROM_COUNTER, as this stub
397: * converts only the low-resolution system timestamp.
398: *
399: * When implementing a provider, use the pointer to this
400: * conversion function supplied to your prov_init(), as
401: * the copy in your DLL will likely be the stub below,
402: * where you want the one provided by the PPSAPI client
403: * such as ntpd.
404: */
405: static inline void
406: pps_ntp_timestamp_from_counter(
407: ntp_fp_t *result,
408: ULONGLONG Timestamp,
409: ULONGLONG Counterstamp)
410: {
411: ULONGLONG BiasedTimestamp;
412:
413: /* convert from 100ns units to NTP fixed point format */
414:
415: BiasedTimestamp = Timestamp - PPS_FILETIME_1970;
416: result->integral = PPS_JAN_1970 +
417: (unsigned)(BiasedTimestamp / PPS_HECTONANOSECONDS);
418: result->fractional =
419: (unsigned) ((BiasedTimestamp % PPS_HECTONANOSECONDS) *
420: (PPS_FRAC / PPS_HECTONANOSECONDS));
421: }
422: #endif
423:
424:
425: static inline int
426: load_pps_provider(
427: char * dllpath
428: )
429: {
430: char short_name[16];
431: char full_name[64];
432: ppsapi_provider * prov;
433: HMODULE hmod;
434: pppsapi_prov_init pprov_init;
435:
436: prov = malloc(sizeof(*prov));
437: if (NULL == prov)
438: return ENOMEM;
439:
440: hmod = LoadLibrary(dllpath);
441: if (NULL == hmod) {
442: fprintf(stderr, "load_pps_provider: LoadLibrary(%s) error %u\n", dllpath, GetLastError());
443: free(prov);
444: return ENOENT;
445: }
446:
447: pprov_init = (pppsapi_prov_init)GetProcAddress(hmod, "ppsapi_prov_init");
448: if (NULL == pprov_init) {
449: fprintf(stderr, "load_pps_provider: entrypoint ppsapi_prov_init not found in %s\n", dllpath);
450: free(prov);
451: FreeLibrary(hmod);
452: return EFAULT;
453: }
454:
455: prov->caps = (*pprov_init)(PPSAPI_TIMEPPS_PROV_VER,
456: &internal_create_pps_handle,
457: &pps_ntp_timestamp_from_counter,
458: short_name, sizeof(short_name),
459: full_name, sizeof(full_name));
460:
461: if (!prov->caps) {
462: free(prov);
463: FreeLibrary(hmod);
464: return EACCES;
465: }
466:
467: prov->short_name = _strdup(short_name);
468: prov->full_name = _strdup(full_name);
469:
470: if (NULL == prov->short_name || !prov->short_name[0]
471: || NULL == prov->full_name || !prov->full_name[0]) {
472:
473: if (prov->short_name)
474: free(prov->short_name);
475: if (prov->full_name)
476: free(prov->full_name);
477: free(prov);
478: FreeLibrary(hmod);
479: return EINVAL;
480: }
481:
482: prov->ptime_pps_create = (provtime_pps_create)
483: GetProcAddress(hmod, "prov_time_pps_create");
484: prov->ptime_pps_destroy = (provtime_pps_destroy)
485: GetProcAddress(hmod, "prov_time_pps_destroy");
486: prov->ptime_pps_setparams = (provtime_pps_setparams)
487: GetProcAddress(hmod, "prov_time_pps_setparams");
488: prov->ptime_pps_fetch = (provtime_pps_fetch)
489: GetProcAddress(hmod, "prov_time_pps_fetch");
490: prov->ptime_pps_kcbind = (provtime_pps_kcbind)
491: GetProcAddress(hmod, "prov_time_pps_kcbind");
492:
493: if (NULL == prov->ptime_pps_create
494: || NULL == prov->ptime_pps_destroy
495: || NULL == prov->ptime_pps_setparams
496: || NULL == prov->ptime_pps_fetch
497: || NULL == prov->ptime_pps_kcbind) {
498:
499: fprintf(stderr, "PPSAPI provider %s missing entrypoint\n",
500: prov->short_name);
501: free(prov->short_name);
502: free(prov->full_name);
503: free(prov);
504: FreeLibrary(hmod);
505: return EINVAL;
506: }
507:
508: fprintf(stderr, "loaded PPSAPI provider %s caps 0x%x provider %p\n",
509: prov->full_name, prov->caps, prov);
510:
511: prov->next = g_provider_list;
512: g_provider_list = prov;
513:
514: return 0;
515: }
516:
517:
518: /*
519: * time_pps_create - create PPS handle from file descriptor
520: *
521: * This is the initial entrypoint of PPSAPI from the client. Note
522: * to maintain source compatibility with Unix, the input file
523: * descriptor really is a descriptor from the C runtime low-numbered
524: * descriptor namespace, though it may have been converted from a
525: * native Windows HANDLE using _open_osfhandle().
526: */
527: static inline int
528: time_pps_create(
529: int filedes,/* device file descriptor */
530: pps_handle_t * phandle /* returned handle */
531: )
532: {
533: HANDLE winhandle;
534: char * dlls;
535: char * dll;
536: char * pch;
537: ppsapi_provider * prov;
538: pps_handle_t ppshandle;
539: int err;
540:
541: if (NULL == phandle)
542: RETURN_PPS_ERRNO(EFAULT);
543:
544: winhandle = (HANDLE)_get_osfhandle(filedes);
545: fprintf(stderr, "time_pps_create(%d) got winhandle %p\n", filedes, winhandle);
546: if (INVALID_HANDLE_VALUE == winhandle)
547: RETURN_PPS_ERRNO(EBADF);
548:
549: /*
550: * For initial testing the list of PPSAPI backend
551: * providers is provided by the environment variable
552: * PPSAPI_DLLS, separated by semicolons such as
553: * PPSAPI_DLLS=c:\ntp\serial_ppsapi.dll;..\parport_ppsapi.dll
554: * There are a million better ways, such as a well-known
555: * registry key under which a value is created for each
556: * provider DLL installed, or even a platform-specific
557: * ntp.conf directive or command-line switch.
558: */
559: dlls = getenv("PPSAPI_DLLS");
560: if (dlls != NULL && NULL == g_provider_list) {
561: dlls = dll = _strdup(dlls);
562: fprintf(stderr, "getenv(PPSAPI_DLLS) gives %s\n", dlls);
563: } else
564: dlls = dll = NULL;
565:
566: while (dll != NULL && dll[0]) {
567: pch = strchr(dll, ';');
568: if (pch != NULL)
569: *pch = 0;
570: err = load_pps_provider(dll);
571: if (err) {
572: fprintf(stderr, "load_pps_provider(%s) got errno %d\n", dll, err);
573: RETURN_PPS_ERRNO(err);
574: }
575: dll = (NULL == pch)
576: ? NULL
577: : pch + 1;
578: }
579:
580: if (NULL != dlls)
581: free(dlls);
582: dlls = dll = NULL;
583:
584: /*
585: * Hand off to each provider in turn until one returns a PPS
586: * handle or they've all declined.
587: */
588: for (prov = g_provider_list; prov != NULL; prov = prov->next) {
589: ppshandle = 0;
590: g_curr_provider = prov;
591: err = (*prov->ptime_pps_create)(winhandle, &ppshandle);
592: g_curr_provider = NULL;
593: fprintf(stderr, "%s prov_time_pps_create(%p) returned %d\n",
594: prov->short_name, winhandle, err);
595: if (!err && ppshandle) {
596: *phandle = ppshandle;
597: return 0;
598: }
599: }
600:
601: fprintf(stderr, "PPSAPI provider list %p\n", g_provider_list);
602:
603: RETURN_PPS_ERRNO(ENOEXEC);
604: }
605:
606:
607: /*
608: * release PPS handle
609: */
610:
611: static inline int
612: time_pps_destroy(
613: pps_handle_t handle
614: )
615: {
616: pps_unit_t * punit;
617: int err;
618:
619: if (!handle)
620: RETURN_PPS_ERRNO(EBADF);
621:
622: punit = unit_from_ppsapi_handle(handle);
623:
624: if (NULL == punit)
625: RETURN_PPS_ERRNO(EBADF);
626:
627: err = (*punit->provider->ptime_pps_destroy)(punit, punit->context);
628:
629: free(punit);
630:
631: if (err)
632: RETURN_PPS_ERRNO(err);
633: else
634: return 0;
635: }
636:
637: /*
638: * set parameters for handle
639: */
640:
641: static inline int
642: time_pps_setparams(
643: pps_handle_t handle,
644: const pps_params_t *params
645: )
646: {
647: pps_unit_t * punit;
648: int err;
649:
650: /*
651: * Check for valid arguments and set parameters.
652: */
653: if (!handle)
654: RETURN_PPS_ERRNO(EBADF);
655:
656: punit = unit_from_ppsapi_handle(handle);
657:
658: if (NULL == punit)
659: RETURN_PPS_ERRNO(EBADF);
660:
661: if (NULL == params)
662: RETURN_PPS_ERRNO(EFAULT);
663:
664: err = (*punit->provider->ptime_pps_setparams)(punit, punit->context, params);
665:
666: if (err)
667: RETURN_PPS_ERRNO(err);
668: else
669: return 0;
670: }
671:
672: /*
673: * get parameters for handle
674: */
675:
676: static inline int
677: time_pps_getparams(
678: pps_handle_t handle,
679: pps_params_t *params_buf
680: )
681: {
682: pps_unit_t * punit;
683:
684: /*
685: * Check for valid arguments and get parameters.
686: */
687: if (!handle)
688: RETURN_PPS_ERRNO(EBADF);
689:
690: punit = unit_from_ppsapi_handle(handle);
691:
692: if (NULL == punit)
693: RETURN_PPS_ERRNO(EBADF);
694:
695: if (NULL == params_buf)
696: RETURN_PPS_ERRNO(EFAULT);
697:
698: *params_buf = punit->params;
699: return 0;
700: }
701:
702:
703: /*
704: * time_pps_getcap - get capabilities for handle
705: */
706: static inline int
707: time_pps_getcap(
708: pps_handle_t handle,
709: int *pmode
710: )
711: {
712: pps_unit_t * punit;
713:
714: /*
715: * Check for valid arguments and get capabilities.
716: */
717: if (!handle)
718: RETURN_PPS_ERRNO(EBADF);
719:
720: punit = unit_from_ppsapi_handle(handle);
721:
722: if (NULL == punit)
723: RETURN_PPS_ERRNO(EBADF);
724:
725: if (NULL == pmode)
726: RETURN_PPS_ERRNO(EFAULT);
727:
728: *pmode = punit->provider->caps;
729: return 0;
730: }
731:
732: /*
733: * Fetch timestamps
734: */
735:
736: static inline int
737: time_pps_fetch(
738: pps_handle_t handle,
739: const int tsformat,
740: pps_info_t * pinfo,
741: const struct timespec * ptimeout
742: )
743: {
744: pps_unit_t * punit;
745: int err;
746:
747: /*
748: * Check for valid arguments and fetch timestamps
749: */
750: if (!handle)
751: RETURN_PPS_ERRNO(EBADF);
752:
753: if (NULL == pinfo)
754: RETURN_PPS_ERRNO(EFAULT);
755:
756: punit = unit_from_ppsapi_handle(handle);
757:
758: if (NULL == punit)
759: RETURN_PPS_ERRNO(EBADF);
760:
761: err = (*punit->provider->ptime_pps_fetch)(punit,
762: punit->context,
763: tsformat,
764: pinfo,
765: ptimeout);
766:
767: if (err)
768: RETURN_PPS_ERRNO(err);
769: else
770: return 0;
771: }
772:
773: /*
774: * time_pps_kcbind - specify kernel consumer
775: *
776: * Not supported so far by Windows.
777: */
778:
779: static inline int
780: time_pps_kcbind(
781: pps_handle_t handle,
782: const int kernel_consumer,
783: const int edge, const int tsformat
784: )
785: {
786: pps_unit_t * punit;
787: int err;
788:
789: if (!handle)
790: RETURN_PPS_ERRNO(EBADF);
791:
792: punit = unit_from_ppsapi_handle(handle);
793:
794: if (NULL == punit)
795: RETURN_PPS_ERRNO(EBADF);
796:
797: err = (*punit->provider->ptime_pps_kcbind)(
798: punit,
799: punit->context,
800: kernel_consumer,
801: edge,
802: tsformat);
803:
804: if (err)
805: RETURN_PPS_ERRNO(err);
806: else
807: return 0;
808: }
809:
810:
811: #endif /* TIMEPPS_H */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>