diff options
Diffstat (limited to 'include/timepps-Solaris.h')
-rw-r--r-- | include/timepps-Solaris.h | 154 |
1 files changed, 111 insertions, 43 deletions
diff --git a/include/timepps-Solaris.h b/include/timepps-Solaris.h index da8fd9403c71..73faa5e08745 100644 --- a/include/timepps-Solaris.h +++ b/include/timepps-Solaris.h @@ -1,6 +1,6 @@ /*********************************************************************** * * - * Copyright (c) David L. Mills 1999-2000 * + * Copyright (c) David L. Mills 1999-2009 * * * * Permission to use, copy, modify, and distribute this software and * * its documentation for any purpose and without fee is hereby * @@ -178,20 +178,39 @@ typedef struct pps_params { #define assert_offset_ntpfp assert_off_tu.ntpfp #define clear_offset_ntpfp clear_off_tu.ntpfp +/* addition of NTP fixed-point format */ + +#define NTPFP_M_ADD(r_i, r_f, a_i, a_f) /* r += a */ \ + do { \ + register u_int32 lo_tmp; \ + register u_int32 hi_tmp; \ + \ + lo_tmp = ((r_f) & 0xffff) + ((a_f) & 0xffff); \ + hi_tmp = (((r_f) >> 16) & 0xffff) + (((a_f) >> 16) & 0xffff); \ + if (lo_tmp & 0x10000) \ + hi_tmp++; \ + (r_f) = ((hi_tmp & 0xffff) << 16) | (lo_tmp & 0xffff); \ + \ + (r_i) += (a_i); \ + if (hi_tmp & 0x10000) \ + (r_i)++; \ + } while (0) + +#define NTPFP_L_ADDS(r, a) NTPFP_M_ADD((r)->integral, (r)->fractional, \ + (int)(a)->integral, (a)->fractional) + /* * 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) +#define PPS_RO (PPS_CANWAIT | PPS_CANPOLL) 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! ------ */ @@ -199,6 +218,13 @@ typedef pps_unit_t* pps_handle_t; /* pps handlebars */ #include <errno.h> /* + * pps handlebars, which are required to be an opaque scalar. This + * implementation uses the handle as a pointer so it must be large + * enough. uintptr_t is as large as a pointer. + */ +typedef uintptr_t pps_handle_t; + +/* * create PPS handle from file descriptor */ @@ -208,6 +234,7 @@ time_pps_create( pps_handle_t *handle /* returned handle */ ) { + pps_unit_t *punit; int one = 1; /* @@ -228,16 +255,18 @@ time_pps_create( * Allocate and initialize default unit structure. */ - *handle = malloc(sizeof(pps_unit_t)); - if (!(*handle)) { - errno = EBADF; + punit = malloc(sizeof(*punit)); + if (NULL == punit) { + errno = ENOMEM; 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; + memset(punit, 0, sizeof(*punit)); + punit->filedes = filedes; + punit->params.api_version = PPS_API_VERS_1; + punit->params.mode = PPS_CAPTUREASSERT | PPS_TSFMT_TSPEC; + + *handle = (pps_handle_t)punit; return (0); } @@ -250,6 +279,8 @@ time_pps_destroy( pps_handle_t handle ) { + pps_unit_t *punit; + /* * Check for valid arguments and detach PPS signal. */ @@ -258,7 +289,8 @@ time_pps_destroy( errno = EBADF; return (-1); /* bad handle */ } - free(handle); + punit = (pps_unit_t *)handle; + free(punit); return (0); } @@ -272,7 +304,8 @@ time_pps_setparams( const pps_params_t *params ) { - int mode, mode_in; + pps_unit_t * punit; + int mode, mode_in; /* * Check for valid arguments and set parameters. */ @@ -302,14 +335,42 @@ time_pps_setparams( */ mode_in = params->mode; + punit = (pps_unit_t *)handle; + + /* + * Only one of the time formats may be selected + * if a nonzero assert offset is supplied. + */ + if ((mode_in & (PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)) == + (PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)) { + + if (punit->params.assert_offset.tv_sec || + punit->params.assert_offset.tv_nsec) { + + errno = EINVAL; + return(-1); + } + + /* + * If no offset was specified but both time + * format flags are used consider it harmless + * but turn off PPS_TSFMT_NTPFP so getparams + * will not show both formats lit. + */ + mode_in &= ~PPS_TSFMT_NTPFP; + } /* turn off read-only bits */ mode_in &= ~PPS_RO; - /* test remaining bits, should only have captureassert and/or offsetassert */ + /* + * test remaining bits, should only have captureassert, + * offsetassert, and/or timestamp format bits. + */ - if (mode_in & ~(PPS_CAPTUREASSERT | PPS_OFFSETASSERT)) { + if (mode_in & ~(PPS_CAPTUREASSERT | PPS_OFFSETASSERT | + PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP)) { errno = EOPNOTSUPP; return(-1); } @@ -318,10 +379,10 @@ time_pps_setparams( * 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; + mode = punit->params.mode; + memcpy(&punit->params, params, sizeof(punit->params)); + punit->params.api_version = PPS_API_VERS_1; + punit->params.mode = mode | mode_in; return (0); } @@ -335,6 +396,8 @@ time_pps_getparams( pps_params_t *params ) { + pps_unit_t * punit; + /* * Check for valid arguments and get parameters. */ @@ -349,11 +412,12 @@ time_pps_getparams( return (-1); /* bad argument */ } - memcpy(params, &handle->params, sizeof(pps_params_t)); + punit = (pps_unit_t *)handle; + memcpy(params, &punit->params, sizeof(params)); return (0); } -/* ( +/* * get capabilities for handle */ @@ -397,7 +461,8 @@ time_pps_fetch( u_int serial; } ev; - pps_info_t infobuf; + pps_info_t infobuf; + pps_unit_t * punit; /* * Check for valid arguments and fetch timestamps @@ -419,56 +484,58 @@ time_pps_fetch( */ memset(&infobuf, 0, sizeof(infobuf)); + punit = (pps_unit_t *)handle; /* * if not captureassert, nothing to return. */ - if (!handle->params.mode & PPS_CAPTUREASSERT) { - memcpy(ppsinfo, &infobuf, sizeof(pps_info_t)); + if (!punit->params.mode & PPS_CAPTUREASSERT) { + memcpy(ppsinfo, &infobuf, sizeof(*ppsinfo)); return (0); } - if (ioctl(handle->filedes, TIOCGPPSEV, (caddr_t) &ev) < 0) { + if (ioctl(punit->filedes, TIOCGPPSEV, (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 + * Translate to specified format then apply offset */ switch (tsformat) { case PPS_TSFMT_TSPEC: - break; /* timespec format requires no translation */ + /* timespec format requires no conversion */ + if (punit->params.mode & PPS_OFFSETASSERT) { + infobuf.assert_timestamp.tv_sec += + punit->params.assert_offset.tv_sec; + infobuf.assert_timestamp.tv_nsec += + punit->params.assert_offset.tv_nsec; + PPS_NORMALIZE(infobuf.assert_timestamp); + } + break; - case PPS_TSFMT_NTPFP: /* NTP format requires conversion to fraction form */ + case PPS_TSFMT_NTPFP: + /* NTP format requires conversion to fraction form */ PPS_TSPECTONTP(infobuf.assert_timestamp_ntpfp); - break; + if (punit->params.mode & PPS_OFFSETASSERT) + NTPFP_L_ADDS(&infobuf.assert_timestamp_ntpfp, + &punit->params.assert_offset_ntpfp); + break; default: errno = EINVAL; return (-1); } - infobuf.current_mode = handle->params.mode; - memcpy(ppsinfo, &infobuf, sizeof(pps_info_t)); + infobuf.current_mode = punit->params.mode; + memcpy(ppsinfo, &infobuf, sizeof(*ppsinfo)); return (0); } @@ -480,7 +547,8 @@ static inline int time_pps_kcbind( pps_handle_t handle, const int kernel_consumer, - const int edge, const int tsformat + const int edge, + const int tsformat ) { /* |