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