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>