diff options
Diffstat (limited to 'contrib/ntp/include/timepps-SunOS.h')
-rw-r--r-- | contrib/ntp/include/timepps-SunOS.h | 504 |
1 files changed, 504 insertions, 0 deletions
diff --git a/contrib/ntp/include/timepps-SunOS.h b/contrib/ntp/include/timepps-SunOS.h new file mode 100644 index 0000000..6cd166e --- /dev/null +++ b/contrib/ntp/include/timepps-SunOS.h @@ -0,0 +1,504 @@ +/*********************************************************************** + * * + * Copyright (c) David L. Mills 1999-2000 * + * * + * Permission to use, copy, modify, and distribute this software and * + * its documentation for any purpose and without fee is hereby * + * granted, provided that the above copyright notice appears in all * + * copies and that both the copyright notice and this permission * + * notice appear in supporting documentation, and that the name * + * University of Delaware not be used in advertising or publicity * + * pertaining to distribution of the software without specific, * + * written prior permission. The University of Delaware makes no * + * representations about the suitability this software for any * + * purpose. It is provided "as is" without express or implied * + * warranty. * + * * + *********************************************************************** + * * + * This header file complies with "Pulse-Per-Second API for UNIX-like * + * Operating Systems, Version 1.0", rfc2783. Credit is due Jeff Mogul * + * and Marc Brett, from whom much of this code was shamelessly stolen. * + * * + * this modified timepps.h can be used to provide a PPSAPI interface * + * to a machine running SunOS. * + * * + *********************************************************************** + * * + * A full PPSAPI interface to the SunOS kernel would be better, but * + * this at least removes the necessity for special coding from the NTP * + * NTP drivers. * + * * + *********************************************************************** + * * + * Some of this include file * + * Copyright (c) 1999 by Ulrich Windl, * + * based on code by Reg Clemens <reg@dwf.com> * + * based on code by Poul-Henning Kamp <phk@FreeBSD.org> * + * * + *********************************************************************** + * * + * "THE BEER-WARE LICENSE" (Revision 42): * + * <phk@FreeBSD.org> wrote this file. As long as you retain this * + * notice you can do whatever you want with this stuff. If we meet some* + * day, and you think this stuff is worth it, you can buy me a beer * + * in return. Poul-Henning Kamp * + * * + **********************************************************************/ + +/* SunOS version, CIOGETEV assumed to exist for SunOS */ + +#ifndef _SYS_TIMEPPS_H_ +#define _SYS_TIMEPPS_H_ + +#include <termios.h> /* to get CIOGETEV */ + +/* Implementation note: the logical states ``assert'' and ``clear'' + * are implemented in terms of the UART register, i.e. ``assert'' + * means the bit is set. + */ + +/* + * The following definitions are architecture independent + */ + +#define PPS_API_VERS_1 1 /* API version number */ +#define PPS_JAN_1970 2208988800UL /* 1970 - 1900 in seconds */ +#define PPS_NANOSECOND 1000000000L /* one nanosecond in decimal */ +#define PPS_FRAC 4294967296. /* 2^32 as a double */ + +#define PPS_NORMALIZE(x) /* normalize timespec */ \ + do { \ + if ((x).tv_nsec >= PPS_NANOSECOND) { \ + (x).tv_nsec -= PPS_NANOSECOND; \ + (x).tv_sec++; \ + } else if ((x).tv_nsec < 0) { \ + (x).tv_nsec += PPS_NANOSECOND; \ + (x).tv_sec--; \ + } \ + } while (0) + +#define PPS_TSPECTONTP(x) /* convert timespec to l_fp */ \ + do { \ + double d_temp; \ + \ + (x).integral += (unsigned int)PPS_JAN_1970; \ + d_temp = (x).fractional * PPS_FRAC / PPS_NANOSECOND; \ + if (d_temp >= PPS_FRAC) \ + (x).integral++; \ + (x).fractional = (unsigned int)d_temp; \ + } while (0) + +/* + * Device/implementation parameters (mode) + */ + +#define PPS_CAPTUREASSERT 0x01 /* capture assert events */ +#define PPS_CAPTURECLEAR 0x02 /* capture clear events */ +#define PPS_CAPTUREBOTH 0x03 /* capture assert and clear events */ + +#define PPS_OFFSETASSERT 0x10 /* apply compensation for assert ev. */ +#define PPS_OFFSETCLEAR 0x20 /* apply compensation for clear ev. */ +#define PPS_OFFSETBOTH 0x30 /* apply compensation for both */ + +#define PPS_CANWAIT 0x100 /* Can we wait for an event? */ +#define PPS_CANPOLL 0x200 /* "This bit is reserved for */ + +/* + * Kernel actions (mode) + */ + +#define PPS_ECHOASSERT 0x40 /* feed back assert event to output */ +#define PPS_ECHOCLEAR 0x80 /* feed back clear event to output */ + +/* + * Timestamp formats (tsformat) + */ + +#define PPS_TSFMT_TSPEC 0x1000 /* select timespec format */ +#define PPS_TSFMT_NTPFP 0x2000 /* select NTP format */ + +/* + * Kernel discipline actions (not used in SunOS) + */ + +#define PPS_KC_HARDPPS 0 /* enable kernel consumer */ +#define PPS_KC_HARDPPS_PLL 1 /* phase-lock mode */ +#define PPS_KC_HARDPPS_FLL 2 /* frequency-lock mode */ + +/* + * Type definitions + */ + +typedef unsigned long pps_seq_t; /* sequence number */ + +typedef struct ntp_fp { + unsigned int integral; + unsigned int fractional; +} ntp_fp_t; /* NTP-compatible time stamp */ + +typedef union pps_timeu { /* timestamp format */ + struct timespec tspec; + ntp_fp_t ntpfp; + unsigned long longpad[3]; +} pps_timeu_t; /* generic data type to represent time stamps */ + +/* + * Timestamp information structure + */ + +typedef struct pps_info { + pps_seq_t assert_sequence; /* seq. num. of assert event */ + pps_seq_t clear_sequence; /* seq. num. of clear event */ + pps_timeu_t assert_tu; /* time of assert event */ + pps_timeu_t clear_tu; /* time of clear event */ + int current_mode; /* current mode bits */ +} pps_info_t; + +#define assert_timestamp assert_tu.tspec +#define clear_timestamp clear_tu.tspec + +#define assert_timestamp_ntpfp assert_tu.ntpfp +#define clear_timestamp_ntpfp clear_tu.ntpfp + +/* + * Parameter structure + */ + +typedef struct pps_params { + int api_version; /* API version # */ + int mode; /* mode bits */ + pps_timeu_t assert_off_tu; /* offset compensation for assert */ + pps_timeu_t clear_off_tu; /* offset compensation for clear */ +} pps_params_t; + +#define assert_offset assert_off_tu.tspec +#define clear_offset clear_off_tu.tspec + +#define assert_offset_ntpfp assert_off_tu.ntpfp +#define clear_offset_ntpfp clear_off_tu.ntpfp + +/* + * The following definitions are architecture-dependent + */ + +#define PPS_CAP (PPS_CAPTUREASSERT | PPS_OFFSETASSERT | PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP) +#define PPS_RO (PPS_CANWAIT | PPS_CANPOLL | PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP) + +typedef struct { + int filedes; /* file descriptor */ + pps_params_t params; /* PPS parameters set by user */ +} pps_unit_t; + +typedef pps_unit_t* pps_handle_t; /* pps handlebars */ + +/* + *------ Here begins the implementation-specific part! ------ + */ + +#include <errno.h> + +/* + * create PPS handle from file descriptor + */ + +static inline int +time_pps_create( + int filedes, /* file descriptor */ + pps_handle_t *handle /* returned handle */ + ) +{ + /* + * Check for valid arguments and attach PPS signal. + */ + + if (!handle) { + errno = EFAULT; + return (-1); /* null pointer */ + } + + if (ioctl(filedes, I_PUSH, "ppsclock") < 0) { + perror("time_pps_create: I_PUSH ppsclock failed"); + return (-1); + } + + /* + * Allocate and initialize default unit structure. + */ + + *handle = malloc(sizeof(pps_unit_t)); + if (!(*handle)) { + errno = EBADF; + return (-1); /* what, no memory? */ + } + + memset(*handle, 0, sizeof(pps_unit_t)); + (*handle)->filedes = filedes; + (*handle)->params.api_version = PPS_API_VERS_1; + (*handle)->params.mode = PPS_CAPTUREASSERT | PPS_TSFMT_TSPEC; + return (0); +} + +/* + * release PPS handle + */ + +static inline int +time_pps_destroy( + pps_handle_t handle + ) +{ + /* + * Check for valid arguments and detach PPS signal. + */ + + if (!handle) { + errno = EBADF; + return (-1); /* bad handle */ + } + free(handle); + return (0); +} + +/* + * set parameters for handle + */ + +static inline int +time_pps_setparams( + pps_handle_t handle, + const pps_params_t *params + ) +{ + int mode, mode_in; + /* + * Check for valid arguments and set parameters. + */ + + if (!handle) { + errno = EBADF; + return (-1); /* bad handle */ + } + + if (!params) { + errno = EFAULT; + return (-1); /* bad argument */ + } + + /* + * There was no reasonable consensu in the API working group. + * I require `api_version' to be set! + */ + + if (params->api_version != PPS_API_VERS_1) { + errno = EINVAL; + return(-1); + } + + /* + * only settable modes are PPS_CAPTUREASSERT and PPS_OFFSETASSERT + */ + + mode_in = params->mode; + + /* turn off read-only bits */ + + mode_in &= ~PPS_RO; + + /* test remaining bits, should only have captureassert and/or offsetassert */ + + if (mode_in & ~(PPS_CAPTUREASSERT | PPS_OFFSETASSERT)) { + errno = EOPNOTSUPP; + return(-1); + } + + /* + * ok, ready to go. + */ + + mode = handle->params.mode; + memcpy(&handle->params, params, sizeof(pps_params_t)); + handle->params.api_version = PPS_API_VERS_1; + handle->params.mode = mode | mode_in; + return (0); +} + +/* + * get parameters for handle + */ + +static inline int +time_pps_getparams( + pps_handle_t handle, + pps_params_t *params + ) +{ + /* + * Check for valid arguments and get parameters. + */ + + if (!handle) { + errno = EBADF; + return (-1); /* bad handle */ + } + + if (!params) { + errno = EFAULT; + return (-1); /* bad argument */ + } + + memcpy(params, &handle->params, sizeof(pps_params_t)); + return (0); +} + +/* ( + * get capabilities for handle + */ + +static inline int +time_pps_getcap( + pps_handle_t handle, + int *mode + ) +{ + /* + * Check for valid arguments and get capabilities. + */ + + if (!handle) { + errno = EBADF; + return (-1); /* bad handle */ + } + + if (!mode) { + errno = EFAULT; + return (-1); /* bad argument */ + } + *mode = PPS_CAP; + return (0); +} + +/* + * Fetch timestamps + */ + +static inline int +time_pps_fetch( + pps_handle_t handle, + const int tsformat, + pps_info_t *ppsinfo, + const struct timespec *timeout + ) +{ + struct ppsclockev { + struct timeval tv; + u_int serial; + } ev; + pps_info_t infobuf; + + /* + * Check for valid arguments and fetch timestamps + */ + + if (!handle) { + errno = EBADF; + return (-1); /* bad handle */ + } + + if (!ppsinfo) { + errno = EFAULT; + return (-1); /* bad argument */ + } + + /* + * nb. PPS_CANWAIT is NOT set by the implementation, we can totally + * ignore the timeout variable. + */ + + memset(&infobuf, 0, sizeof(infobuf)); + + /* + * if not captureassert, nothing to return. + */ + + if (!handle->params.mode & PPS_CAPTUREASSERT) { + memcpy(ppsinfo, &infobuf, sizeof(pps_info_t)); + return (0); + } + +#if defined(__STDC__) +#define CIOGETEV _IOR('C', 0, struct ppsclockev) /* get last pps event */ +#else +#define CIOGETEV _IOR(C, 0, struct ppsclockev) /* get last pps event */ +#endif + + if (ioctl(handle->filedes, CIOGETEV, (caddr_t) &ev) < 0) { + perror("time_pps_fetch:"); + errno = EOPNOTSUPP; + return(-1); + } + + /* + * Apply offsets as specified. Note that only assert timestamps + * are captured by this interface. + */ + + infobuf.assert_sequence = ev.serial; + infobuf.assert_timestamp.tv_sec = ev.tv.tv_sec; + infobuf.assert_timestamp.tv_nsec = ev.tv.tv_usec * 1000; + + if (handle->params.mode & PPS_OFFSETASSERT) { + infobuf.assert_timestamp.tv_sec += handle->params.assert_offset.tv_sec; + infobuf.assert_timestamp.tv_nsec += handle->params.assert_offset.tv_nsec; + PPS_NORMALIZE(infobuf.assert_timestamp); + } + + /* + * Translate to specified format + */ + + switch (tsformat) { + case PPS_TSFMT_TSPEC: + break; /* timespec format requires no translation */ + + case PPS_TSFMT_NTPFP: /* NTP format requires conversion to fraction form */ + PPS_TSPECTONTP(infobuf.assert_timestamp_ntpfp); + break; + + default: + errno = EINVAL; + return (-1); + } + + infobuf.current_mode = handle->params.mode; + memcpy(ppsinfo, &infobuf, sizeof(pps_info_t)); + return (0); +} + +/* + * specify kernel consumer + */ + +static inline int +time_pps_kcbind( + pps_handle_t handle, + const int kernel_consumer, + const int edge, const int tsformat + ) +{ + /* + * Check for valid arguments and bind kernel consumer + */ + if (!handle) { + errno = EBADF; + return (-1); /* bad handle */ + } + if (geteuid() != 0) { + errno = EPERM; + return (-1); /* must be superuser */ + } + errno = EOPNOTSUPP; + return(-1); +} + +#endif /* _SYS_TIMEPPS_H_ */ |