summaryrefslogtreecommitdiffstats
path: root/contrib/ntp/ntpd/refclock_bancomm.c
diff options
context:
space:
mode:
authorroberto <roberto@FreeBSD.org>1999-12-09 13:01:21 +0000
committerroberto <roberto@FreeBSD.org>1999-12-09 13:01:21 +0000
commitef64b99e8412f2273dd2e8b3291c2f78ffc4667f (patch)
treefc0cfa1aab0ff6b228f511b410733ef4f35d1ead /contrib/ntp/ntpd/refclock_bancomm.c
downloadFreeBSD-src-ef64b99e8412f2273dd2e8b3291c2f78ffc4667f.zip
FreeBSD-src-ef64b99e8412f2273dd2e8b3291c2f78ffc4667f.tar.gz
Virgin import of ntpd 4.0.98f
Diffstat (limited to 'contrib/ntp/ntpd/refclock_bancomm.c')
-rw-r--r--contrib/ntp/ntpd/refclock_bancomm.c483
1 files changed, 483 insertions, 0 deletions
diff --git a/contrib/ntp/ntpd/refclock_bancomm.c b/contrib/ntp/ntpd/refclock_bancomm.c
new file mode 100644
index 0000000..95c211b
--- /dev/null
+++ b/contrib/ntp/ntpd/refclock_bancomm.c
@@ -0,0 +1,483 @@
+/* refclock_bancomm.c - clock driver for the Datum/Bancomm bc635VME
+ * Time and Frequency Processor. It requires the BANCOMM bc635VME/
+ * bc350VXI Time and Frequency Processor Module Driver for SunOS4.x
+ * and SunOS5.x UNIX Systems. It has been tested on a UltraSparc
+ * IIi-cEngine running Solaris 2.6.
+ *
+ * Author(s): Ganesh Ramasivan & Gary Cliff, Computing Devices Canada,
+ * Ottawa, Canada
+ *
+ * Date: July 1999
+ *
+ * Note(s): The refclock type has been defined as 16.
+ *
+ * This program has been modelled after the Bancomm driver
+ * originally written by R. Schmidt of Time Service, U.S.
+ * Naval Observatory for a HP-UX machine. Since the original
+ * authors no longer plan to maintain this code, all
+ * references to the HP-UX vme2 driver subsystem bave been
+ * removed. Functions vme_report_event(), vme_receive(),
+ * vme_control() and vme_buginfo() have been deleted because
+ * they are no longer being used.
+ *
+ * The time on the bc635 TFP must be set to GMT due to the
+ * fact that NTP makes use of GMT for all its calculations.
+ *
+ * Installation of the Datum/Bancomm driver creates the
+ * device file /dev/btfp0
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#if defined(REFCLOCK) && defined(CLOCK_BANC)
+#include <stdio.h>
+#include <syslog.h>
+#include <ctype.h>
+#include <string.h>
+#include <strings.h>
+#include <sys/time.h>
+
+#include "ntpd.h"
+#include "ntp_io.h"
+#include "ntp_refclock.h"
+#include "ntp_unixtime.h"
+#include "ntp_stdlib.h"
+
+/* STUFF BY RES */
+struct btfp_time /* Structure for reading 5 time words */
+ /* in one ioctl(2) operation. */
+{
+ unsigned short btfp_time[5]; /* Time words 0,1,2,3, and 4. (16bit)*/
+};
+
+/* SunOS5 ioctl commands definitions.*/
+#define BTFPIOC ( 'b'<< 8 )
+#define IOCIO( l, n ) ( BTFPIOC | n )
+#define IOCIOR( l, n, s ) ( BTFPIOC | n )
+#define IOCIORN( l, n, s ) ( BTFPIOC | n )
+#define IOCIOWN( l, n, s ) ( BTFPIOC | n )
+
+/***** Simple ioctl commands *****/
+#define RUNLOCK IOCIOR(b, 19, int ) /* Release Capture Lockout */
+#define RCR0 IOCIOR(b, 22, int ) /* Read control register zero.*/
+#define WCR0 IOCIOWN(b, 23, int) /* Write control register zero*/
+
+/***** Compound ioctl commands *****/
+
+/* Read all 5 time words in one call. */
+#define READTIME IOCIORN(b, 32, sizeof( struct btfp_time ))
+#define VMEFD "/dev/btfp0"
+
+struct vmedate { /* structure returned by get_vmetime.c */
+ unsigned short year;
+ unsigned short day;
+ unsigned short hr;
+ unsigned short mn;
+ unsigned short sec;
+ unsigned long frac;
+ unsigned short status;
+};
+
+/* END OF STUFF FROM RES */
+
+/*
+ * Definitions
+ */
+#define MAXUNITS 2 /* max number of VME units */
+
+/*
+ * VME interface parameters.
+ */
+#define VMEPRECISION (-21) /* precision assumed (1 us) */
+#define USNOREFID "BTFP" /* or whatever */
+#define VMEREFID "BTFP" /* reference id */
+#define VMEDESCRIPTION "Bancomm bc635 TFP" /* who we are */
+#define VMEHSREFID 0x7f7f1000 /* 127.127.16.00 refid hi strata */
+/* clock type 16 is used here */
+#define GMT 0 /* hour offset from Greenwich */
+
+/*
+ * Imported from ntp_timer module
+ */
+extern u_long current_time; /* current time(s) */
+
+/*
+ * Imported from ntpd module
+ */
+extern int debug; /* global debug flag */
+
+/*
+ * VME unit control structure.
+ * Changes made to vmeunit structure. Most members are now available in the
+ * new refclockproc structure in ntp_refclock.h - 07/99 - Ganesh Ramasivan
+ */
+struct vmeunit {
+ struct vmedate vmedata; /* data returned from vme read */
+ u_long lasttime; /* last time clock heard from */
+};
+
+/*
+ * Keep the fudge factors separately so they can be set even
+ * when no clock is configured.
+ */
+static double fudgefactor[MAXUNITS];
+static u_char stratumtouse[MAXUNITS];
+static u_char sloppyclockflag[MAXUNITS];
+
+/*
+ * Function prototypes
+ */
+static void vme_init (void);
+static int vme_start (int, struct peer *);
+static void vme_shutdown (int, struct peer *);
+static void vme_receive (struct recvbuf *);
+static void vme_poll (int unit, struct peer *);
+struct vmedate *get_datumtime(struct vmedate *);
+
+/*
+ * Transfer vector
+ */
+struct refclock refclock_bancomm = {
+ vme_start,
+ vme_shutdown,
+ vme_poll,
+ noentry, /* not used (old vme_control) */
+ vme_init,
+ noentry, /* not used (old vme_buginfo) */
+ NOFLAGS
+};
+
+int fd_vme; /* file descriptor for ioctls */
+int regvalue;
+
+/*
+ * vme_init - initialize internal vme driver data
+ */
+static void
+vme_init(void)
+{
+ register int i;
+
+ /*
+ * Initialize fudge factors to default.
+ */
+ for (i = 0; i < MAXUNITS; i++) {
+ fudgefactor[i] = 0.0;
+ stratumtouse[i] = 0;
+ sloppyclockflag[i] = 0;
+ }
+}
+
+/*
+ * vme_start - open the VME device and initialize data for processing
+ */
+static int
+vme_start(
+ int unit,
+ struct peer *peer
+ )
+{
+ register struct vmeunit *vme;
+ struct refclockproc *pp;
+ int dummy;
+ char vmedev[20];
+
+ /*
+ * Check configuration info.
+ */
+ if (unit >= MAXUNITS) {
+ msyslog(LOG_ERR, "vme_start: unit %d invalid", unit);
+ return (0);
+ }
+
+ /*
+ * Open VME device
+ */
+#ifdef DEBUG
+
+ printf("Opening DATUM VME DEVICE \n");
+#endif
+ if ( (fd_vme = open(VMEFD, O_RDWR)) < 0) {
+ msyslog(LOG_ERR, "vme_start: failed open of %s: %m", vmedev);
+ return (0);
+ }
+ else { /* Release capture lockout in case it was set from before. */
+ if( ioctl( fd_vme, RUNLOCK, &dummy ) )
+ msyslog(LOG_ERR, "vme_start: RUNLOCK failed %m");
+
+ regvalue = 0; /* More esoteric stuff to do... */
+ if( ioctl( fd_vme, WCR0, &regvalue ) )
+ msyslog(LOG_ERR, "vme_start: WCR0 failed %m");
+ }
+
+ /*
+ * Allocate unit structure
+ */
+ vme = (struct vmeunit *)emalloc(sizeof(struct vmeunit));
+ bzero((char *)vme, sizeof(struct vmeunit));
+
+
+ /*
+ * Set up the structures
+ */
+ pp = peer->procptr;
+ pp->unitptr = (caddr_t) vme;
+ pp->timestarted = current_time;
+
+ pp->io.clock_recv = vme_receive;
+ pp->io.srcclock = (caddr_t)peer;
+ pp->io.datalen = 0;
+ pp->io.fd = fd_vme;
+
+ /*
+ * All done. Initialize a few random peer variables, then
+ * return success. Note that root delay and root dispersion are
+ * always zero for this clock.
+ */
+ pp->leap = LEAP_NOWARNING;
+ peer->precision = VMEPRECISION;
+ peer->stratum = stratumtouse[unit];
+ memcpy( (char *)&peer->refid, USNOREFID,4);
+
+ peer->refid = htonl(VMEHSREFID);
+
+ return (1);
+}
+
+
+/*
+ * vme_shutdown - shut down a VME clock
+ */
+static void
+vme_shutdown(
+ int unit,
+ struct peer *peer
+ )
+{
+ register struct vmeunit *vme;
+ struct refclockproc *pp;
+
+ pp = peer->procptr;
+
+ if (unit >= MAXUNITS) {
+ msyslog(LOG_ERR, "vme_shutdown: unit %d invalid", unit);
+ return;
+ }
+
+ /*
+ * Tell the I/O module to turn us off. We're history.
+ */
+ vme = (struct vmeunit *)pp->unitptr;
+ io_closeclock(&pp->io);
+ pp->unitptr = NULL;
+ free(vme);
+}
+
+
+/*
+ * vme_receive - receive data from the VME device.
+ *
+ * Note: This interface would be interrupt-driven. We don't use that
+ * now, but include a dummy routine for possible future adventures.
+ */
+static void
+vme_receive(
+ struct recvbuf *rbufp
+ )
+{
+}
+
+
+/*
+ * vme_poll - called by the transmit procedure
+ */
+static void
+vme_poll(
+ int unit,
+ struct peer *peer
+ )
+{
+ struct vmedate *tptr;
+ struct vmeunit *vme;
+ struct refclockproc *pp;
+ time_t tloc;
+ struct tm *tadr;
+
+ pp = peer->procptr;
+ vme = (struct vmeunit *)pp->unitptr; /* Here is the structure */
+
+ tptr = &vme->vmedata;
+ if ((tptr = get_datumtime(tptr)) == NULL ) {
+ refclock_report(peer, CEVNT_BADREPLY);
+ return;
+ }
+
+ get_systime(&pp->lastrec);
+ pp->polls++;
+ vme->lasttime = current_time;
+
+ /*
+ * Get VME time and convert to timestamp format.
+ * The year must come from the system clock.
+ */
+
+ time(&tloc);
+ tadr = gmtime(&tloc);
+ tptr->year = (unsigned short)(tadr->tm_year + 1900);
+
+
+ sprintf(pp->a_lastcode,
+ "%3.3d %2.2d:%2.2d:%2.2d.%.6ld %1d",
+ tptr->day,
+ tptr->hr,
+ tptr->mn,
+ tptr->sec,
+ tptr->frac,
+ tptr->status);
+
+ pp->lencode = (u_short) strlen(pp->a_lastcode);
+
+ pp->day = tptr->day;
+ pp->hour = tptr->hr;
+ pp->minute = tptr->mn;
+ pp->second = tptr->sec;
+ pp->usec = tptr->frac;
+
+#ifdef DEBUG
+ if (debug)
+ printf("pp: %3d %02d:%02d:%02d.%06ld %1x\n",
+ pp->day, pp->hour, pp->minute, pp->second,
+ pp->usec, tptr->status);
+#endif
+ if (tptr->status ) { /* Status 0 is locked to ref., 1 is not */
+ refclock_report(peer, CEVNT_BADREPLY);
+ return;
+ }
+
+ /*
+ * Now, compute the reference time value. Use the heavy
+ * machinery for the seconds and the millisecond field for the
+ * fraction when present. If an error in conversion to internal
+ * format is found, the program declares bad data and exits.
+ * Note that this code does not yet know how to do the years and
+ * relies on the clock-calendar chip for sanity.
+ */
+ if (!refclock_process(pp)) {
+ refclock_report(peer, CEVNT_BADTIME);
+ return;
+ }
+ record_clock_stats(&peer->srcadr, pp->a_lastcode);
+ refclock_receive(peer);
+}
+
+struct vmedate *
+get_datumtime(struct vmedate *time_vme)
+{
+ unsigned short status;
+ char cbuf[7];
+ struct btfp_time vts;
+
+ if ( time_vme == (struct vmedate *)NULL) {
+ time_vme = (struct vmedate *)malloc(sizeof(struct vmedate ));
+ }
+
+ if( ioctl(fd_vme, READTIME, &vts))
+ msyslog(LOG_ERR, "get_datumtime error: %m");
+
+ /* if you want to actually check the validity of these registers, do a
+ define of CHECK above this. I didn't find it necessary. - RES
+ */
+
+#ifdef CHECK
+
+ /* Get day */
+ sprintf(cbuf,"%3.3x", ((vts.btfp_time[ 0 ] & 0x000f) <<8) +
+ ((vts.btfp_time[ 1 ] & 0xff00) >> 8));
+
+ if (isdigit(cbuf[0]) && isdigit(cbuf[1]) && isdigit(cbuf[2]) )
+ time_vme->day = (unsigned short)atoi(cbuf);
+ else
+ time_vme->day = (unsigned short) 0;
+
+ /* Get hour */
+ sprintf(cbuf,"%2.2x", vts.btfp_time[ 1 ] & 0x00ff);
+
+ if (isdigit(cbuf[0]) && isdigit(cbuf[1]))
+ time_vme->hr = (unsigned short)atoi(cbuf);
+ else
+ time_vme->hr = (unsigned short) 0;
+
+ /* Get minutes */
+ sprintf(cbuf,"%2.2x", (vts.btfp_time[ 2 ] & 0xff00) >>8);
+ if (isdigit(cbuf[0]) && isdigit(cbuf[1]))
+ time_vme->mn = (unsigned short)atoi(cbuf);
+ else
+ time_vme->mn = (unsigned short) 0;
+
+ /* Get seconds */
+ sprintf(cbuf,"%2.2x", vts.btfp_time[ 2 ] & 0x00ff);
+
+ if (isdigit(cbuf[0]) && isdigit(cbuf[1]))
+ time_vme->sec = (unsigned short)atoi(cbuf);
+ else
+ time_vme->sec = (unsigned short) 0;
+
+ /* Get microseconds. Yes, we ignore the 0.1 microsecond digit so we can
+ use the TVTOTSF function later on...*/
+
+ sprintf(cbuf,"%4.4x%2.2x", vts.btfp_time[ 3 ],
+ vts.btfp_time[ 4 ]>>8);
+
+ if (isdigit(cbuf[0]) && isdigit(cbuf[1]) && isdigit(cbuf[2])
+ && isdigit(cbuf[3]) && isdigit(cbuf[4]) && isdigit(cbuf[5]))
+ time_vme->frac = (u_long) atoi(cbuf);
+ else
+ time_vme->frac = (u_long) 0;
+#else
+
+ /* DONT CHECK just trust the card */
+
+ /* Get day */
+ sprintf(cbuf,"%3.3x", ((vts.btfp_time[ 0 ] & 0x000f) <<8) +
+ ((vts.btfp_time[ 1 ] & 0xff00) >> 8));
+ time_vme->day = (unsigned short)atoi(cbuf);
+
+ /* Get hour */
+ sprintf(cbuf,"%2.2x", vts.btfp_time[ 1 ] & 0x00ff);
+
+ time_vme->hr = (unsigned short)atoi(cbuf);
+
+ /* Get minutes */
+ sprintf(cbuf,"%2.2x", (vts.btfp_time[ 2 ] & 0xff00) >>8);
+ time_vme->mn = (unsigned short)atoi(cbuf);
+
+ /* Get seconds */
+ sprintf(cbuf,"%2.2x", vts.btfp_time[ 2 ] & 0x00ff);
+ time_vme->sec = (unsigned short)atoi(cbuf);
+
+ /* Get microseconds. Yes, we ignore the 0.1 microsecond digit so we can
+ use the TVTOTSF function later on...*/
+
+ sprintf(cbuf,"%4.4x%2.2x", vts.btfp_time[ 3 ],
+ vts.btfp_time[ 4 ]>>8);
+
+ time_vme->frac = (u_long) atoi(cbuf);
+
+#endif /* CHECK */
+
+ /* Get status bit */
+ status = (vts.btfp_time[0] & 0x0010) >>4;
+ time_vme->status = status; /* Status=0 if locked to ref. */
+ /* Status=1 if flywheeling */
+ if (status) { /* lost lock ? */
+ return ((void *)NULL);
+ }
+ else
+ return (time_vme);
+}
+
+#else
+int refclock_bancomm_bs;
+#endif /* REFCLOCK */
OpenPOWER on IntegriCloud