Annotation of embedaddon/ntp/ports/winnt/include/timepps.h, revision 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>