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>