diff options
Diffstat (limited to 'contrib/ntp/ntpd/refclock_hopfpci.c')
-rw-r--r-- | contrib/ntp/ntpd/refclock_hopfpci.c | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/contrib/ntp/ntpd/refclock_hopfpci.c b/contrib/ntp/ntpd/refclock_hopfpci.c new file mode 100644 index 0000000..a9deb21 --- /dev/null +++ b/contrib/ntp/ntpd/refclock_hopfpci.c @@ -0,0 +1,274 @@ +/* + * refclock_hopfpci.c + * + * - clock driver for hopf 6039 PCI board (GPS or DCF77) + * Bernd Altmeier altmeier@atlsoft.de + * + * latest source and further information can be found at: + * http://www.ATLSoft.de/ntp + * + * In order to run this driver you have to install and test + * the PCI-board driver for your system first. + * + * On Linux/UNIX + * + * The driver attempts to open the device /dev/hopf6039 . + * The device entry will be made by the installation process of + * the kernel module for the PCI-bus board. The driver sources + * belongs to the delivery equipment of the PCI-board. + * + * On Windows NT/2000 + * + * The driver attempts to open the device by calling the function + * "OpenHopfDevice()". This function will be installed by the + * Device Driver for the PCI-bus board. The driver belongs to the + * delivery equipment of the PCI-board. + * + * + * Start 21.03.2000 Revision: 01.20 + * changes 22.12.2000 Revision: 01.40 flag1 = 1 sync even if Quarz + * + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#if defined(REFCLOCK) && defined(CLOCK_HOPF_PCI) + +#include "ntpd.h" +#include "ntp_io.h" +#include "ntp_refclock.h" +#include "ntp_unixtime.h" +#include "ntp_stdlib.h" + +#undef fileno +#include <ctype.h> +#undef fileno + +#ifndef SYS_WINNT +# include <sys/ipc.h> +# include <assert.h> +# include <unistd.h> +# include <stdio.h> +# include "hopf6039.h" +#else +# include "hopf_PCI_io.h" +#endif + +/* + * hopfpci interface definitions + */ +#define PRECISION (-10) /* precision assumed (1 ms) */ +#define REFID "hopf" /* reference ID */ +#define DESCRIPTION "hopf Elektronik PCI radio board" + +#define NSAMPLES 3 /* stages of median filter */ +#ifndef SYS_WINNT +# define DEVICE "/dev/hopf6039" /* device name inode*/ +#else +# define DEVICE "hopf6039" /* device name WinNT */ +#endif + +#define LEWAPWAR 0x20 /* leap second warning bit */ + +#define HOPF_OPMODE 0xC0 /* operation mode mask */ +#define HOPF_INVALID 0x00 /* no time code available */ +#define HOPF_INTERNAL 0x40 /* internal clock */ +#define HOPF_RADIO 0x80 /* radio clock */ +#define HOPF_RADIOHP 0xC0 /* high precision radio clock */ + + +/* + * hopfclock unit control structure. + */ +struct hopfclock_unit { + short unit; /* NTP refclock unit number */ + char leap_status; /* leap second flag */ +}; +int fd; /* file descr. */ + +/* + * Function prototypes + */ +static int hopfpci_start (int, struct peer *); +static void hopfpci_shutdown (int, struct peer *); +static void hopfpci_poll (int unit, struct peer *); + +/* + * Transfer vector + */ +struct refclock refclock_hopfpci = { + hopfpci_start, /* start up driver */ + hopfpci_shutdown, /* shut down driver */ + hopfpci_poll, /* transmit poll message */ + noentry, /* not used */ + noentry, /* initialize driver (not used) */ + noentry, /* not used */ + NOFLAGS /* not used */ +}; + +/* + * hopfpci_start - attach to hopf PCI board 6039 + */ +static int +hopfpci_start( + int unit, + struct peer *peer + ) +{ + struct refclockproc *pp; + struct hopfclock_unit *up; + + /* + * Allocate and initialize unit structure + */ + up = (struct hopfclock_unit *) emalloc(sizeof(struct hopfclock_unit)); + + if (!(up)) { + msyslog(LOG_ERR, "hopfPCIClock(%d) emalloc: %m",unit); +#ifdef DEBUG + printf("hopfPCIClock(%d) emalloc\n",unit); +#endif + return (0); + } + memset((char *)up, 0, sizeof(struct hopfclock_unit)); + +#ifndef SYS_WINNT + + fd = open(DEVICE,O_RDWR); /* try to open hopf clock device */ + +#else + if (!OpenHopfDevice()){ + msyslog(LOG_ERR,"Start: %s unit: %d failed!",DEVICE,unit); + return (0); + } +#endif + + pp = peer->procptr; + pp->io.clock_recv = noentry; + pp->io.srcclock = (caddr_t)peer; + pp->io.datalen = 0; + pp->io.fd = -1; + pp->unitptr = (caddr_t)up; + + get_systime(&pp->lastrec); + + /* + * Initialize miscellaneous peer variables + */ + if (pp->unitptr!=0) { + memcpy((char *)&pp->refid, REFID, 4); + peer->precision = PRECISION; + pp->clockdesc = DESCRIPTION; + up->leap_status = 0; + up->unit = (short) unit; + return (1); + } + else { + return 0; + } +} + + +/* + * hopfpci_shutdown - shut down the clock + */ +static void +hopfpci_shutdown( + int unit, + struct peer *peer + ) +{ + struct refclockproc *pp; + register struct hopfpciTime *up; + + pp = peer->procptr; + up = (struct hopfpciTime *)pp->unitptr; + +#ifndef SYS_WINNT + close(fd); +#else + CloseHopfDevice(); +// UnmapViewOfFile (up); +#endif +} + + +/* + * hopfpci_poll - called by the transmit procedure + */ +static void +hopfpci_poll( + int unit, + struct peer *peer + ) +{ + struct refclockproc *pp; + register struct hopfpciTime *up; + HOPFTIME m_time; + + pp = peer->procptr; + up = (struct hopfpciTime *)pp->unitptr; + +#ifndef SYS_WINNT + ioctl(fd,HOPF_CLOCK_GET_UTC,&m_time); +#else + GetHopfSystemTime(&m_time); +#endif + pp->polls++; + + pp->day = ymd2yd(m_time.wYear,m_time.wMonth,m_time.wDay); + pp->hour = m_time.wHour; + pp->minute = m_time.wMinute; + pp->second = m_time.wSecond; + pp->msec=m_time.wMilliseconds; + pp->usec=0; + if (m_time.wStatus & LEWAPWAR) + pp->leap = LEAP_ADDSECOND; + else + pp->leap = LEAP_NOWARNING; + + sprintf(pp->a_lastcode,"ST: %02X T: %02d:%02d:%02d.%03d D: %02d.%02d.%04d", + m_time.wStatus, pp->hour, pp->minute, pp->second, pp->msec, + m_time.wDay, m_time.wMonth, m_time.wYear); + pp->lencode = strlen(pp->a_lastcode); + + get_systime(&pp->lastrec); + + /* + * If clock has no valid status then report error and exit + */ + if ((m_time.wStatus & HOPF_OPMODE) == HOPF_INVALID) { /* time ok? */ + refclock_report(peer, CEVNT_BADTIME); + pp->leap = LEAP_NOTINSYNC; + return; + } + + /* + * Test if time is running on internal quarz + * if CLK_FLAG1 is set, sychronize even if no radio operation + */ + + if ((m_time.wStatus & HOPF_OPMODE) == HOPF_INTERNAL){ + if ((pp->sloppyclockflag & CLK_FLAG1) == 0) { + refclock_report(peer, CEVNT_BADTIME); + pp->leap = LEAP_NOTINSYNC; + return; + } + } + + if (!refclock_process(pp)) { + refclock_report(peer, CEVNT_BADTIME); + return; + } + refclock_receive(peer); + + record_clock_stats(&peer->srcadr, pp->a_lastcode); + + return; +} + +#else +int refclock_hopfpci_bs; +#endif /* REFCLOCK */ |