Annotation of embedaddon/ntp/include/timepps-SunOS.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 SunOS.                                        *
        !            25:  *                                                                    *
        !            26:  ***********************************************************************
        !            27:  *                                                                    *
        !            28:  * A full PPSAPI interface to the SunOS 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: /* SunOS version, CIOGETEV assumed to exist for SunOS */
        !            50: 
        !            51: #ifndef _SYS_TIMEPPS_H_
        !            52: #define _SYS_TIMEPPS_H_
        !            53: 
        !            54: #include <termios.h>   /* to get CIOGETEV */
        !            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 SunOS)
        !           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: } pps_unit_t;
        !           192: 
        !           193: typedef pps_unit_t* pps_handle_t; /* pps handlebars */
        !           194: 
        !           195: /*
        !           196:  *------ Here begins the implementation-specific part! ------
        !           197:  */
        !           198: 
        !           199: #include <errno.h>
        !           200: 
        !           201: /*
        !           202:  * create PPS handle from file descriptor
        !           203:  */
        !           204: 
        !           205: static inline int
        !           206: time_pps_create(
        !           207:        int filedes,            /* file descriptor */
        !           208:        pps_handle_t *handle    /* returned handle */
        !           209:        )
        !           210: {
        !           211:        /*
        !           212:         * Check for valid arguments and attach PPS signal.
        !           213:         */
        !           214: 
        !           215:        if (!handle) {
        !           216:                errno = EFAULT;
        !           217:                return (-1);    /* null pointer */
        !           218:        }
        !           219: 
        !           220:        if (ioctl(filedes, I_PUSH, "ppsclock") < 0) {
        !           221:                perror("time_pps_create: I_PUSH ppsclock failed");
        !           222:                return (-1);
        !           223:        }
        !           224: 
        !           225:        /*
        !           226:         * Allocate and initialize default unit structure.
        !           227:         */
        !           228: 
        !           229:        *handle = malloc(sizeof(pps_unit_t));
        !           230:        if (!(*handle)) {
        !           231:                errno = EBADF;
        !           232:                return (-1);    /* what, no memory? */
        !           233:        }
        !           234: 
        !           235:        memset(*handle, 0, sizeof(pps_unit_t));
        !           236:        (*handle)->filedes = filedes;
        !           237:        (*handle)->params.api_version = PPS_API_VERS_1;
        !           238:        (*handle)->params.mode = PPS_CAPTUREASSERT | PPS_TSFMT_TSPEC;
        !           239:        return (0);
        !           240: }
        !           241: 
        !           242: /*
        !           243:  * release PPS handle
        !           244:  */
        !           245: 
        !           246: static inline int
        !           247: time_pps_destroy(
        !           248:        pps_handle_t handle
        !           249:        )
        !           250: {
        !           251:        /*
        !           252:         * Check for valid arguments and detach PPS signal.
        !           253:         */
        !           254: 
        !           255:        if (!handle) {
        !           256:                errno = EBADF;
        !           257:                return (-1);    /* bad handle */
        !           258:        }
        !           259:        free(handle);
        !           260:        return (0);
        !           261: }
        !           262: 
        !           263: /*
        !           264:  * set parameters for handle
        !           265:  */
        !           266: 
        !           267: static inline int
        !           268: time_pps_setparams(
        !           269:        pps_handle_t handle,
        !           270:        const pps_params_t *params
        !           271:        )
        !           272: {
        !           273:        int     mode, mode_in;
        !           274:        /*
        !           275:         * Check for valid arguments and set parameters.
        !           276:         */
        !           277: 
        !           278:        if (!handle) {
        !           279:                errno = EBADF;
        !           280:                return (-1);    /* bad handle */
        !           281:        }
        !           282: 
        !           283:        if (!params) {
        !           284:                errno = EFAULT;
        !           285:                return (-1);    /* bad argument */
        !           286:        }
        !           287: 
        !           288:        /*
        !           289:         * There was no reasonable consensu in the API working group.
        !           290:         * I require `api_version' to be set!
        !           291:         */
        !           292: 
        !           293:        if (params->api_version != PPS_API_VERS_1) {
        !           294:                errno = EINVAL;
        !           295:                return(-1);
        !           296:        }
        !           297: 
        !           298:        /*
        !           299:         * only settable modes are PPS_CAPTUREASSERT and PPS_OFFSETASSERT
        !           300:         */
        !           301: 
        !           302:        mode_in = params->mode;
        !           303: 
        !           304:        /* turn off read-only bits */
        !           305: 
        !           306:        mode_in &= ~PPS_RO;
        !           307: 
        !           308:        /* test remaining bits, should only have captureassert and/or offsetassert */
        !           309: 
        !           310:        if (mode_in & ~(PPS_CAPTUREASSERT | PPS_OFFSETASSERT)) {
        !           311:                errno = EOPNOTSUPP;
        !           312:                return(-1);
        !           313:        }
        !           314: 
        !           315:        /*
        !           316:         * ok, ready to go.
        !           317:         */
        !           318: 
        !           319:        mode = handle->params.mode;
        !           320:        memcpy(&handle->params, params, sizeof(pps_params_t));
        !           321:        handle->params.api_version = PPS_API_VERS_1;
        !           322:        handle->params.mode = mode | mode_in;
        !           323:        return (0);
        !           324: }
        !           325: 
        !           326: /*
        !           327:  * get parameters for handle
        !           328:  */
        !           329: 
        !           330: static inline int
        !           331: time_pps_getparams(
        !           332:        pps_handle_t handle,
        !           333:        pps_params_t *params
        !           334:        )
        !           335: {
        !           336:        /*
        !           337:         * Check for valid arguments and get parameters.
        !           338:         */
        !           339: 
        !           340:        if (!handle) {
        !           341:                errno = EBADF;
        !           342:                return (-1);    /* bad handle */
        !           343:        }
        !           344: 
        !           345:        if (!params) {
        !           346:                errno = EFAULT;
        !           347:                return (-1);    /* bad argument */
        !           348:        }
        !           349: 
        !           350:        memcpy(params, &handle->params, sizeof(pps_params_t));
        !           351:        return (0);
        !           352: }
        !           353: 
        !           354: /* (
        !           355:  * get capabilities for handle
        !           356:  */
        !           357: 
        !           358: static inline int
        !           359: time_pps_getcap(
        !           360:        pps_handle_t handle,
        !           361:        int *mode
        !           362:        )
        !           363: {
        !           364:        /*
        !           365:         * Check for valid arguments and get capabilities.
        !           366:         */
        !           367: 
        !           368:        if (!handle) {
        !           369:                errno = EBADF;
        !           370:                return (-1);    /* bad handle */
        !           371:        }
        !           372: 
        !           373:        if (!mode) {
        !           374:                errno = EFAULT;
        !           375:                return (-1);    /* bad argument */
        !           376:        }
        !           377:        *mode = PPS_CAP;
        !           378:        return (0);
        !           379: }
        !           380: 
        !           381: /*
        !           382:  * Fetch timestamps
        !           383:  */
        !           384: 
        !           385: static inline int
        !           386: time_pps_fetch(
        !           387:        pps_handle_t handle,
        !           388:        const int tsformat,
        !           389:        pps_info_t *ppsinfo,
        !           390:        const struct timespec *timeout
        !           391:        )
        !           392: {
        !           393:        struct ppsclockev {
        !           394:                struct timeval tv;
        !           395:                u_int serial;
        !           396:        } ev;
        !           397:        pps_info_t infobuf;
        !           398: 
        !           399:        /*
        !           400:         * Check for valid arguments and fetch timestamps
        !           401:         */
        !           402: 
        !           403:        if (!handle) {
        !           404:                errno = EBADF;
        !           405:                return (-1);    /* bad handle */
        !           406:        }
        !           407: 
        !           408:        if (!ppsinfo) {
        !           409:                errno = EFAULT;
        !           410:                return (-1);    /* bad argument */
        !           411:        }
        !           412: 
        !           413:        /*
        !           414:         * nb. PPS_CANWAIT is NOT set by the implementation, we can totally
        !           415:         * ignore the timeout variable.
        !           416:         */
        !           417: 
        !           418:        memset(&infobuf, 0, sizeof(infobuf));
        !           419: 
        !           420:        /*
        !           421:         * if not captureassert, nothing to return.
        !           422:         */
        !           423: 
        !           424:        if (!handle->params.mode & PPS_CAPTUREASSERT) {
        !           425:                memcpy(ppsinfo, &infobuf, sizeof(pps_info_t));
        !           426:                return (0);
        !           427:        }
        !           428: 
        !           429: #if defined(__STDC__)
        !           430: #define CIOGETEV       _IOR('C', 0, struct ppsclockev) /* get last pps event */
        !           431: #else
        !           432: #define CIOGETEV       _IOR(C, 0, struct ppsclockev)   /* get last pps event */
        !           433: #endif
        !           434: 
        !           435:        if (ioctl(handle->filedes, CIOGETEV, (caddr_t) &ev) < 0) {
        !           436:                perror("time_pps_fetch:");
        !           437:                errno = EOPNOTSUPP;
        !           438:                return(-1);
        !           439:        }
        !           440: 
        !           441:        /*
        !           442:         * Apply offsets as specified. Note that only assert timestamps
        !           443:         * are captured by this interface.
        !           444:         */
        !           445: 
        !           446:        infobuf.assert_sequence = ev.serial;
        !           447:        infobuf.assert_timestamp.tv_sec = ev.tv.tv_sec;
        !           448:        infobuf.assert_timestamp.tv_nsec = ev.tv.tv_usec * 1000;
        !           449: 
        !           450:        if (handle->params.mode & PPS_OFFSETASSERT) {
        !           451:                infobuf.assert_timestamp.tv_sec  += handle->params.assert_offset.tv_sec;
        !           452:                infobuf.assert_timestamp.tv_nsec += handle->params.assert_offset.tv_nsec;
        !           453:                PPS_NORMALIZE(infobuf.assert_timestamp);
        !           454:        }
        !           455: 
        !           456:        /*
        !           457:         * Translate to specified format
        !           458:         */
        !           459: 
        !           460:        switch (tsformat) {
        !           461:        case PPS_TSFMT_TSPEC:
        !           462:                break;           /* timespec format requires no translation */
        !           463: 
        !           464:        case PPS_TSFMT_NTPFP:   /* NTP format requires conversion to fraction form */
        !           465:                PPS_TSPECTONTP(infobuf.assert_timestamp_ntpfp);
        !           466:                break;
        !           467: 
        !           468:        default:
        !           469:                errno = EINVAL;
        !           470:                return (-1);
        !           471:        }
        !           472: 
        !           473:        infobuf.current_mode = handle->params.mode;
        !           474:        memcpy(ppsinfo, &infobuf, sizeof(pps_info_t));
        !           475:        return (0);
        !           476: }
        !           477: 
        !           478: /*
        !           479:  * specify kernel consumer
        !           480:  */
        !           481: 
        !           482: static inline int
        !           483: time_pps_kcbind(
        !           484:        pps_handle_t handle,
        !           485:        const int kernel_consumer,
        !           486:        const int edge, const int tsformat
        !           487:        )
        !           488: {
        !           489:        /*
        !           490:         * Check for valid arguments and bind kernel consumer
        !           491:         */
        !           492:        if (!handle) {
        !           493:                errno = EBADF;
        !           494:                return (-1);    /* bad handle */
        !           495:        }
        !           496:        if (geteuid() != 0) {
        !           497:                errno = EPERM;
        !           498:                return (-1);    /* must be superuser */
        !           499:        }
        !           500:        errno = EOPNOTSUPP;
        !           501:        return(-1);
        !           502: }
        !           503: 
        !           504: #endif /* _SYS_TIMEPPS_H_ */

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