Annotation of embedaddon/ntp/include/timepps-SunOS.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 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>