aboutsummaryrefslogtreecommitdiff
path: root/ports/winnt/ppsapi/loopback/monolithic-serialpps-timepps.h
diff options
context:
space:
mode:
Diffstat (limited to 'ports/winnt/ppsapi/loopback/monolithic-serialpps-timepps.h')
-rw-r--r--ports/winnt/ppsapi/loopback/monolithic-serialpps-timepps.h714
1 files changed, 0 insertions, 714 deletions
diff --git a/ports/winnt/ppsapi/loopback/monolithic-serialpps-timepps.h b/ports/winnt/ppsapi/loopback/monolithic-serialpps-timepps.h
deleted file mode 100644
index 1007ccdd90c3..000000000000
--- a/ports/winnt/ppsapi/loopback/monolithic-serialpps-timepps.h
+++ /dev/null
@@ -1,714 +0,0 @@
-/***********************************************************************
- * *
- * Copyright (c) David L. Mills 1999-2000 *
- * *
- * Permission to use, copy, modify, and distribute this software and *
- * its documentation for any purpose and with or 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 Windows with a suitably modified *
- * serialpps.sys being used in place of serial.sys. It can *
- * be extended to support a modified parallel port driver once *
- * available. *
- * *
- * This Windows version was derived by Dave Hart *
- * <davehart@davehart.com> from Mills' timepps-Solaris.h *
- * *
- ***********************************************************************
- * *
- * 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 *
- * *
- **********************************************************************/
-
-#ifndef _SYS_TIMEPPS_H_
-#define _SYS_TIMEPPS_H_
-
-/* 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_HECTONANOSECONDS 10000000 /* 100ns units in a second */
-#define PPS_FILETIME_1970 0x019db1ded53e8000 /* unix epoch to Windows */
-
-#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 ntp_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)
-
-#define PPS_NTPTOTSPEC(x) /* convert ntp_fp to timespec */ \
- do { \
- double d_temp; \
- \
- (x).tv_sec -= (time_t)PPS_JAN_1970; \
- d_temp = (double)((x).tv_nsec); \
- d_temp *= PPS_NANOSECOND; \
- d_temp /= PPS_FRAC; \
- (x).tv_nsec = (long)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 Windows yet)
- */
-
-#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 */
-
-#pragma warning(push)
-#pragma warning(disable: 201) /* nonstd extension nameless union */
-
-typedef struct ntp_fp {
- union ntp_fp_sec {
- unsigned int integral;
- int s_integral;
- };
- unsigned int fractional;
-} ntp_fp_t; /* NTP-compatible time stamp */
-
-#pragma warning(pop)
-
-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 */
-
-/* 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, \
- (a)->s_integral, (a)->fractional)
-
-
-/*
- * 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)
-
-typedef struct {
- int filedes; /* file descriptor */
- OVERLAPPED ol; /* caches ol.hEvent for DeviceIoControl */
- 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 <windows.h>
-#include <errno.h>
-
-#ifndef EOPNOTSUPP
-#define EOPNOTSUPP 45
-#endif
-
-typedef struct _OLD_SERIAL_PPS_STAMPS {
- LARGE_INTEGER Timestamp;
- LARGE_INTEGER Counterstamp;
-} OLD_SERIAL_PPS_STAMPS, *POLDSERIAL_PPS_STAMPS;
-
-typedef struct _SERIAL_PPS_STAMPS {
- LARGE_INTEGER Timestamp;
- LARGE_INTEGER Counterstamp;
- DWORD SeqNum;
-} SERIAL_PPS_STAMPS, *PSERIAL_PPS_STAMPS;
-
-#define IOCTL_SERIAL_GET_PPS_STAMPS CTL_CODE(FILE_DEVICE_SERIAL_PORT,114,METHOD_BUFFERED,FILE_ANY_ACCESS)
-
-/* byte offset of member m in struct typedef s */
-#define PPS_OFFSETOF(m,s) (size_t)(&((s *)0)->m)
-
-/*
- * ntpd on Windows only looks to errno after finding
- * GetLastError returns NO_ERROR. To accomodate its
- * use of msyslog in portable code such as refclock_atom.c,
- * this implementation always clears the Windows
- * error code using SetLastError(NO_ERROR) when
- * returning an errno. This is also a good idea
- * for any non-ntpd clients as they should use only
- * the errno for PPSAPI functions.
- */
-#define RETURN_PPS_ERRNO(e) \
-do { \
- SetLastError(NO_ERROR); \
- errno = (e); \
- return -1; \
-} while (0)
-
-
-#ifdef OWN_PPS_NTP_TIMESTAMP_FROM_COUNTER
-extern void pps_ntp_timestamp_from_counter(ntp_fp_t *, ULONGLONG, ULONGLONG);
-#else
-/*
- * helper routine for serialpps.sys ioctl which returns
- * performance counter "timestamp" as well as a system
- * FILETIME timestamp. Converts one of the inputs to
- * NTP fixed-point format.
- */
-static inline void
-pps_ntp_timestamp_from_counter(
- ntp_fp_t *result,
- ULONGLONG Timestamp,
- ULONGLONG Counterstamp)
-{
- ULONGLONG BiasedTimestamp;
-
- /* convert from 100ns units to NTP fixed point format */
-
- BiasedTimestamp = Timestamp - PPS_FILETIME_1970;
- result->integral = PPS_JAN_1970 +
- (unsigned)(BiasedTimestamp / PPS_HECTONANOSECONDS);
- result->fractional =
- (unsigned) ((BiasedTimestamp % PPS_HECTONANOSECONDS) *
- (PPS_FRAC / PPS_HECTONANOSECONDS));
-}
-#endif
-
-
-/*
- * create PPS handle from file descriptor
- */
-
-static inline int
-time_pps_create(
- int filedes, /* file descriptor */
- pps_handle_t *handle /* returned handle */
- )
-{
- OLD_SERIAL_PPS_STAMPS old_pps_stamps;
- DWORD bytes;
- OVERLAPPED ol;
-
- /*
- * Check for valid arguments and attach PPS signal.
- */
-
- if (!handle)
- RETURN_PPS_ERRNO(EFAULT);
-
- if (PPS_OFFSETOF(tspec.tv_nsec, pps_timeu_t) !=
- PPS_OFFSETOF(ntpfp.fractional, pps_timeu_t)) {
- fprintf(stderr,
- "timepps.h needs work, union of \n"
- "unsigned int ntp_fp.integral and\n"
- "time_t timespec.tv_sec accessed\n"
- "interchangeably.\n");
- RETURN_PPS_ERRNO(EFAULT);
- }
-
- /*
- * For this ioctl which will never block, we don't want to go
- * through the overhead of a completion port, so we use an
- * event handle in the overlapped structure with its 1 bit set.
- *
- * From GetQueuedCompletionStatus docs:
- * Even if you have passed the function a file handle associated
- * with a completion port and a valid OVERLAPPED structure, an
- * application can prevent completion port notification. This is
- * done by specifying a valid event handle for the hEvent member
- * of the OVERLAPPED structure, and setting its low-order bit. A
- * valid event handle whose low-order bit is set keeps I/O
- * completion from being queued to the completion port.
- */
-
- ol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- ol.hEvent = (HANDLE) ((ULONG_PTR)ol.hEvent | 1);
-
- if (FALSE == DeviceIoControl(
- (HANDLE)_get_osfhandle(filedes),
- IOCTL_SERIAL_GET_PPS_STAMPS,
- NULL,
- 0,
- &old_pps_stamps,
- sizeof(old_pps_stamps),
- &bytes,
- &ol)
- || sizeof(old_pps_stamps) != bytes) {
-
- /*
- * If you want to write some dead code this could detect the
- * IOCTL being pended, but the driver always has the info
- * instantly, so ERROR_IO_PENDING isn't a concern.
- */
-
- CloseHandle(ol.hEvent);
- fprintf(stderr,
- "time_pps_create: IOCTL_SERIAL_GET_PPS_STAMPS: %d %d\n",
- bytes,
- GetLastError());
- RETURN_PPS_ERRNO(ENXIO);
- }
-
- /*
- * Allocate and initialize default unit structure.
- */
-
- *handle = malloc(sizeof(pps_unit_t));
- if (!(*handle))
- RETURN_PPS_ERRNO(ENOMEM);
-
- memset(*handle, 0, sizeof(pps_unit_t));
- (*handle)->filedes = filedes;
- (*handle)->ol.hEvent = ol.hEvent;
- (*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)
- RETURN_PPS_ERRNO(EBADF);
-
- CloseHandle(handle->ol.hEvent);
- 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)
- RETURN_PPS_ERRNO(EBADF);
-
- if (!params)
- RETURN_PPS_ERRNO(EFAULT);
-
- /*
- * 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)
- RETURN_PPS_ERRNO(EINVAL);
-
- /*
- * only settable modes are PPS_CAPTUREASSERT and PPS_OFFSETASSERT
- */
-
- mode_in = params->mode;
-
- /*
- * 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 (handle->params.assert_offset.tv_sec ||
- handle->params.assert_offset.tv_nsec)
-
- RETURN_PPS_ERRNO(EINVAL);
-
- /*
- * 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,
- * offsetassert, and/or timestamp format bits.
- */
-
- if (mode_in & ~(PPS_CAPTUREASSERT | PPS_OFFSETASSERT |
- PPS_TSFMT_TSPEC | PPS_TSFMT_NTPFP))
- RETURN_PPS_ERRNO(EOPNOTSUPP);
-
- /*
- * ok, ready to go.
- */
-
- mode = handle->params.mode;
- handle->params = *params;
- handle->params.mode = mode | mode_in;
- handle->params.api_version = PPS_API_VERS_1;
- 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)
- RETURN_PPS_ERRNO(EBADF);
-
- if (!params)
- RETURN_PPS_ERRNO(EFAULT);
-
- *params = handle->params;
- 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)
- RETURN_PPS_ERRNO(EBADF);
-
- if (!mode)
- RETURN_PPS_ERRNO(EFAULT);
-
- *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
- )
-{
- SERIAL_PPS_STAMPS pps_stamps;
- pps_info_t infobuf;
- BOOL rc;
- DWORD bytes;
- DWORD lasterr;
-
- /*
- * Check for valid arguments and fetch timestamps
- */
-
- if (!handle)
- RETURN_PPS_ERRNO(EBADF);
-
- if (!ppsinfo)
- RETURN_PPS_ERRNO(EFAULT);
-
- /*
- * 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) {
- *ppsinfo = infobuf;
- return (0);
- }
-
- /*
- * First rev of serialpps.sys didn't support the SeqNum field,
- * support it by simply returning constant 0 for serial in that case.
- */
- pps_stamps.SeqNum = 0;
-
- /*
- * interrogate (hopefully) serialpps.sys
- * if it's the standard serial.sys or another driver,
- * IOCTL_SERIAL_GET_PPS_STAMPS is most likely unknown
- * and will result in ERROR_INVALID_PARAMETER.
- */
- bytes = 0;
-
- rc = DeviceIoControl(
- (HANDLE)_get_osfhandle(handle->filedes),
- IOCTL_SERIAL_GET_PPS_STAMPS,
- NULL,
- 0,
- &pps_stamps,
- sizeof(pps_stamps),
- &bytes,
- &handle->ol);
-
- if (!rc) {
-
- lasterr = GetLastError();
- if (ERROR_INVALID_PARAMETER != lasterr)
- fprintf(stderr, "time_pps_fetch: ioctl err %d\n",
- lasterr);
- RETURN_PPS_ERRNO(EOPNOTSUPP);
-
- } else if (bytes != sizeof(pps_stamps) &&
- bytes != sizeof(OLD_SERIAL_PPS_STAMPS)) {
-
- fprintf(stderr,
- "time_pps_fetch: wanted %d or %d bytes got %d from "
- "IOCTL_SERIAL_GET_PPS_STAMPS 0x%x\n" ,
- sizeof(OLD_SERIAL_PPS_STAMPS),
- sizeof(SERIAL_PPS_STAMPS),
- bytes,
- IOCTL_SERIAL_GET_PPS_STAMPS);
- RETURN_PPS_ERRNO(ENXIO);
- }
-
- /*
- * pps_ntp_timestamp_from_counter takes the two flavors
- * of timestamp we have (counter and system time) and
- * uses whichever it can to give the best NTP fixed-point
- * conversion. In ntpd the Counterstamp is typically
- * used. A stub implementation in this file simply
- * converts from Windows Timestamp to NTP fixed-point.
- */
- pps_ntp_timestamp_from_counter(
- &infobuf.assert_timestamp_ntpfp,
- pps_stamps.Timestamp.QuadPart,
- pps_stamps.Counterstamp.QuadPart);
-
- /*
- * Note that only assert timestamps
- * are captured by this interface.
- */
-
- infobuf.assert_sequence = pps_stamps.SeqNum;
-
- /*
- * Apply offset and translate to specified format
- */
-
- switch (tsformat) {
- case PPS_TSFMT_NTPFP: /* NTP format requires no translation */
- if (handle->params.mode & PPS_OFFSETASSERT) {
- NTPFP_L_ADDS(&infobuf.assert_timestamp_ntpfp,
- &handle->params.assert_offset_ntpfp);
- }
- break;
-
- case PPS_TSFMT_TSPEC: /* timespec format requires conversion to nsecs form */
- PPS_NTPTOTSPEC(infobuf.assert_timestamp);
- 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);
- }
- break;
-
- default:
- RETURN_PPS_ERRNO(EINVAL);
- }
-
- infobuf.current_mode = handle->params.mode;
- *ppsinfo = infobuf;
- return (0);
-}
-
-/*
- * time_pps_kcbind - specify kernel consumer
- *
- * Not supported so far by Windows.
- */
-
-static inline int
-time_pps_kcbind(
- pps_handle_t handle,
- const int kernel_consumer,
- const int edge, const int tsformat
- )
-{
- /*
- * Check for valid arguments before revealing the ugly truth
- */
- if (!handle)
- RETURN_PPS_ERRNO(EBADF);
-
- RETURN_PPS_ERRNO(EOPNOTSUPP);
-}
-
-
-
-#endif /* _SYS_TIMEPPS_H_ */