Annotation of embedaddon/ntp/include/timepps-SCO.h, revision 1.1.1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>