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>