1c0b746e5SOllivier Robert /* refclock_bancomm.c - clock driver for the Datum/Bancomm bc635VME 2c0b746e5SOllivier Robert * Time and Frequency Processor. It requires the BANCOMM bc635VME/ 3c0b746e5SOllivier Robert * bc350VXI Time and Frequency Processor Module Driver for SunOS4.x 4c0b746e5SOllivier Robert * and SunOS5.x UNIX Systems. It has been tested on a UltraSparc 5c0b746e5SOllivier Robert * IIi-cEngine running Solaris 2.6. 6c0b746e5SOllivier Robert * 7c0b746e5SOllivier Robert * Author(s): Ganesh Ramasivan & Gary Cliff, Computing Devices Canada, 8c0b746e5SOllivier Robert * Ottawa, Canada 9c0b746e5SOllivier Robert * 10c0b746e5SOllivier Robert * Date: July 1999 11c0b746e5SOllivier Robert * 12c0b746e5SOllivier Robert * Note(s): The refclock type has been defined as 16. 13c0b746e5SOllivier Robert * 14c0b746e5SOllivier Robert * This program has been modelled after the Bancomm driver 15c0b746e5SOllivier Robert * originally written by R. Schmidt of Time Service, U.S. 16c0b746e5SOllivier Robert * Naval Observatory for a HP-UX machine. Since the original 17c0b746e5SOllivier Robert * authors no longer plan to maintain this code, all 18c0b746e5SOllivier Robert * references to the HP-UX vme2 driver subsystem bave been 19c0b746e5SOllivier Robert * removed. Functions vme_report_event(), vme_receive(), 20c0b746e5SOllivier Robert * vme_control() and vme_buginfo() have been deleted because 21c0b746e5SOllivier Robert * they are no longer being used. 22c0b746e5SOllivier Robert * 23c0b746e5SOllivier Robert * The time on the bc635 TFP must be set to GMT due to the 24c0b746e5SOllivier Robert * fact that NTP makes use of GMT for all its calculations. 25c0b746e5SOllivier Robert * 26c0b746e5SOllivier Robert * Installation of the Datum/Bancomm driver creates the 27c0b746e5SOllivier Robert * device file /dev/btfp0 28c0b746e5SOllivier Robert */ 29c0b746e5SOllivier Robert 30c0b746e5SOllivier Robert #ifdef HAVE_CONFIG_H 31c0b746e5SOllivier Robert #include <config.h> 32c0b746e5SOllivier Robert #endif 33c0b746e5SOllivier Robert 34c0b746e5SOllivier Robert #if defined(REFCLOCK) && defined(CLOCK_BANC) 35c0b746e5SOllivier Robert #include <stdio.h> 36c0b746e5SOllivier Robert #include <syslog.h> 37c0b746e5SOllivier Robert #include <ctype.h> 38c0b746e5SOllivier Robert #include <string.h> 39c0b746e5SOllivier Robert #include <strings.h> 40c0b746e5SOllivier Robert #include <sys/time.h> 41c0b746e5SOllivier Robert 42c0b746e5SOllivier Robert #include "ntpd.h" 43c0b746e5SOllivier Robert #include "ntp_io.h" 44c0b746e5SOllivier Robert #include "ntp_refclock.h" 45c0b746e5SOllivier Robert #include "ntp_unixtime.h" 46c0b746e5SOllivier Robert #include "ntp_stdlib.h" 47c0b746e5SOllivier Robert 48c0b746e5SOllivier Robert /* STUFF BY RES */ 49c0b746e5SOllivier Robert struct btfp_time /* Structure for reading 5 time words */ 50c0b746e5SOllivier Robert /* in one ioctl(2) operation. */ 51c0b746e5SOllivier Robert { 52c0b746e5SOllivier Robert unsigned short btfp_time[5]; /* Time words 0,1,2,3, and 4. (16bit)*/ 53c0b746e5SOllivier Robert }; 54c0b746e5SOllivier Robert 55c0b746e5SOllivier Robert /* SunOS5 ioctl commands definitions.*/ 56c0b746e5SOllivier Robert #define BTFPIOC ( 'b'<< 8 ) 57c0b746e5SOllivier Robert #define IOCIO( l, n ) ( BTFPIOC | n ) 58c0b746e5SOllivier Robert #define IOCIOR( l, n, s ) ( BTFPIOC | n ) 59c0b746e5SOllivier Robert #define IOCIORN( l, n, s ) ( BTFPIOC | n ) 60c0b746e5SOllivier Robert #define IOCIOWN( l, n, s ) ( BTFPIOC | n ) 61c0b746e5SOllivier Robert 62c0b746e5SOllivier Robert /***** Simple ioctl commands *****/ 63c0b746e5SOllivier Robert #define RUNLOCK IOCIOR(b, 19, int ) /* Release Capture Lockout */ 64c0b746e5SOllivier Robert #define RCR0 IOCIOR(b, 22, int ) /* Read control register zero.*/ 65c0b746e5SOllivier Robert #define WCR0 IOCIOWN(b, 23, int) /* Write control register zero*/ 66c0b746e5SOllivier Robert 67c0b746e5SOllivier Robert /***** Compound ioctl commands *****/ 68c0b746e5SOllivier Robert 69c0b746e5SOllivier Robert /* Read all 5 time words in one call. */ 70c0b746e5SOllivier Robert #define READTIME IOCIORN(b, 32, sizeof( struct btfp_time )) 71c0b746e5SOllivier Robert #define VMEFD "/dev/btfp0" 72c0b746e5SOllivier Robert 73c0b746e5SOllivier Robert struct vmedate { /* structure returned by get_vmetime.c */ 74c0b746e5SOllivier Robert unsigned short year; 75c0b746e5SOllivier Robert unsigned short day; 76c0b746e5SOllivier Robert unsigned short hr; 77c0b746e5SOllivier Robert unsigned short mn; 78c0b746e5SOllivier Robert unsigned short sec; 79c0b746e5SOllivier Robert unsigned long frac; 80c0b746e5SOllivier Robert unsigned short status; 81c0b746e5SOllivier Robert }; 82c0b746e5SOllivier Robert 83c0b746e5SOllivier Robert /* END OF STUFF FROM RES */ 84c0b746e5SOllivier Robert 85c0b746e5SOllivier Robert /* 86c0b746e5SOllivier Robert * Definitions 87c0b746e5SOllivier Robert */ 88c0b746e5SOllivier Robert #define MAXUNITS 2 /* max number of VME units */ 89c0b746e5SOllivier Robert 90c0b746e5SOllivier Robert /* 91c0b746e5SOllivier Robert * VME interface parameters. 92c0b746e5SOllivier Robert */ 93c0b746e5SOllivier Robert #define VMEPRECISION (-21) /* precision assumed (1 us) */ 94c0b746e5SOllivier Robert #define USNOREFID "BTFP" /* or whatever */ 95c0b746e5SOllivier Robert #define VMEREFID "BTFP" /* reference id */ 96c0b746e5SOllivier Robert #define VMEDESCRIPTION "Bancomm bc635 TFP" /* who we are */ 97c0b746e5SOllivier Robert #define VMEHSREFID 0x7f7f1000 /* 127.127.16.00 refid hi strata */ 98c0b746e5SOllivier Robert /* clock type 16 is used here */ 99c0b746e5SOllivier Robert #define GMT 0 /* hour offset from Greenwich */ 100c0b746e5SOllivier Robert 101c0b746e5SOllivier Robert /* 102c0b746e5SOllivier Robert * Imported from ntp_timer module 103c0b746e5SOllivier Robert */ 104c0b746e5SOllivier Robert extern u_long current_time; /* current time(s) */ 105c0b746e5SOllivier Robert 106c0b746e5SOllivier Robert /* 107c0b746e5SOllivier Robert * Imported from ntpd module 108c0b746e5SOllivier Robert */ 109c0b746e5SOllivier Robert extern int debug; /* global debug flag */ 110c0b746e5SOllivier Robert 111c0b746e5SOllivier Robert /* 112c0b746e5SOllivier Robert * VME unit control structure. 113c0b746e5SOllivier Robert * Changes made to vmeunit structure. Most members are now available in the 114c0b746e5SOllivier Robert * new refclockproc structure in ntp_refclock.h - 07/99 - Ganesh Ramasivan 115c0b746e5SOllivier Robert */ 116c0b746e5SOllivier Robert struct vmeunit { 117c0b746e5SOllivier Robert struct vmedate vmedata; /* data returned from vme read */ 118c0b746e5SOllivier Robert u_long lasttime; /* last time clock heard from */ 119c0b746e5SOllivier Robert }; 120c0b746e5SOllivier Robert 121c0b746e5SOllivier Robert /* 122c0b746e5SOllivier Robert * Keep the fudge factors separately so they can be set even 123c0b746e5SOllivier Robert * when no clock is configured. 124c0b746e5SOllivier Robert */ 125c0b746e5SOllivier Robert static double fudgefactor[MAXUNITS]; 126c0b746e5SOllivier Robert static u_char stratumtouse[MAXUNITS]; 127c0b746e5SOllivier Robert static u_char sloppyclockflag[MAXUNITS]; 128c0b746e5SOllivier Robert 129c0b746e5SOllivier Robert /* 130c0b746e5SOllivier Robert * Function prototypes 131c0b746e5SOllivier Robert */ 132c0b746e5SOllivier Robert static void vme_init (void); 133c0b746e5SOllivier Robert static int vme_start (int, struct peer *); 134c0b746e5SOllivier Robert static void vme_shutdown (int, struct peer *); 135c0b746e5SOllivier Robert static void vme_receive (struct recvbuf *); 136c0b746e5SOllivier Robert static void vme_poll (int unit, struct peer *); 137c0b746e5SOllivier Robert struct vmedate *get_datumtime(struct vmedate *); 138c0b746e5SOllivier Robert 139c0b746e5SOllivier Robert /* 140c0b746e5SOllivier Robert * Transfer vector 141c0b746e5SOllivier Robert */ 142c0b746e5SOllivier Robert struct refclock refclock_bancomm = { 143c0b746e5SOllivier Robert vme_start, 144c0b746e5SOllivier Robert vme_shutdown, 145c0b746e5SOllivier Robert vme_poll, 146c0b746e5SOllivier Robert noentry, /* not used (old vme_control) */ 147c0b746e5SOllivier Robert vme_init, 148c0b746e5SOllivier Robert noentry, /* not used (old vme_buginfo) */ 149c0b746e5SOllivier Robert NOFLAGS 150c0b746e5SOllivier Robert }; 151c0b746e5SOllivier Robert 152c0b746e5SOllivier Robert int fd_vme; /* file descriptor for ioctls */ 153c0b746e5SOllivier Robert int regvalue; 154c0b746e5SOllivier Robert 155c0b746e5SOllivier Robert /* 156c0b746e5SOllivier Robert * vme_init - initialize internal vme driver data 157c0b746e5SOllivier Robert */ 158c0b746e5SOllivier Robert static void 159c0b746e5SOllivier Robert vme_init(void) 160c0b746e5SOllivier Robert { 161c0b746e5SOllivier Robert register int i; 162c0b746e5SOllivier Robert 163c0b746e5SOllivier Robert /* 164c0b746e5SOllivier Robert * Initialize fudge factors to default. 165c0b746e5SOllivier Robert */ 166c0b746e5SOllivier Robert for (i = 0; i < MAXUNITS; i++) { 167c0b746e5SOllivier Robert fudgefactor[i] = 0.0; 168c0b746e5SOllivier Robert stratumtouse[i] = 0; 169c0b746e5SOllivier Robert sloppyclockflag[i] = 0; 170c0b746e5SOllivier Robert } 171c0b746e5SOllivier Robert } 172c0b746e5SOllivier Robert 173c0b746e5SOllivier Robert /* 174c0b746e5SOllivier Robert * vme_start - open the VME device and initialize data for processing 175c0b746e5SOllivier Robert */ 176c0b746e5SOllivier Robert static int 177c0b746e5SOllivier Robert vme_start( 178c0b746e5SOllivier Robert int unit, 179c0b746e5SOllivier Robert struct peer *peer 180c0b746e5SOllivier Robert ) 181c0b746e5SOllivier Robert { 182c0b746e5SOllivier Robert register struct vmeunit *vme; 183c0b746e5SOllivier Robert struct refclockproc *pp; 184c0b746e5SOllivier Robert int dummy; 185c0b746e5SOllivier Robert char vmedev[20]; 186c0b746e5SOllivier Robert 187c0b746e5SOllivier Robert /* 188c0b746e5SOllivier Robert * Check configuration info. 189c0b746e5SOllivier Robert */ 190c0b746e5SOllivier Robert if (unit >= MAXUNITS) { 191c0b746e5SOllivier Robert msyslog(LOG_ERR, "vme_start: unit %d invalid", unit); 192c0b746e5SOllivier Robert return (0); 193c0b746e5SOllivier Robert } 194c0b746e5SOllivier Robert 195c0b746e5SOllivier Robert /* 196c0b746e5SOllivier Robert * Open VME device 197c0b746e5SOllivier Robert */ 198c0b746e5SOllivier Robert #ifdef DEBUG 199c0b746e5SOllivier Robert 200c0b746e5SOllivier Robert printf("Opening DATUM VME DEVICE \n"); 201c0b746e5SOllivier Robert #endif 202c0b746e5SOllivier Robert if ( (fd_vme = open(VMEFD, O_RDWR)) < 0) { 203c0b746e5SOllivier Robert msyslog(LOG_ERR, "vme_start: failed open of %s: %m", vmedev); 204c0b746e5SOllivier Robert return (0); 205c0b746e5SOllivier Robert } 206c0b746e5SOllivier Robert else { /* Release capture lockout in case it was set from before. */ 207c0b746e5SOllivier Robert if( ioctl( fd_vme, RUNLOCK, &dummy ) ) 208c0b746e5SOllivier Robert msyslog(LOG_ERR, "vme_start: RUNLOCK failed %m"); 209c0b746e5SOllivier Robert 210c0b746e5SOllivier Robert regvalue = 0; /* More esoteric stuff to do... */ 211c0b746e5SOllivier Robert if( ioctl( fd_vme, WCR0, ®value ) ) 212c0b746e5SOllivier Robert msyslog(LOG_ERR, "vme_start: WCR0 failed %m"); 213c0b746e5SOllivier Robert } 214c0b746e5SOllivier Robert 215c0b746e5SOllivier Robert /* 216c0b746e5SOllivier Robert * Allocate unit structure 217c0b746e5SOllivier Robert */ 218c0b746e5SOllivier Robert vme = (struct vmeunit *)emalloc(sizeof(struct vmeunit)); 219c0b746e5SOllivier Robert bzero((char *)vme, sizeof(struct vmeunit)); 220c0b746e5SOllivier Robert 221c0b746e5SOllivier Robert 222c0b746e5SOllivier Robert /* 223c0b746e5SOllivier Robert * Set up the structures 224c0b746e5SOllivier Robert */ 225c0b746e5SOllivier Robert pp = peer->procptr; 226c0b746e5SOllivier Robert pp->unitptr = (caddr_t) vme; 227c0b746e5SOllivier Robert pp->timestarted = current_time; 228c0b746e5SOllivier Robert 229c0b746e5SOllivier Robert pp->io.clock_recv = vme_receive; 230c0b746e5SOllivier Robert pp->io.srcclock = (caddr_t)peer; 231c0b746e5SOllivier Robert pp->io.datalen = 0; 232c0b746e5SOllivier Robert pp->io.fd = fd_vme; 233c0b746e5SOllivier Robert 234c0b746e5SOllivier Robert /* 235c0b746e5SOllivier Robert * All done. Initialize a few random peer variables, then 236c0b746e5SOllivier Robert * return success. Note that root delay and root dispersion are 237c0b746e5SOllivier Robert * always zero for this clock. 238c0b746e5SOllivier Robert */ 239c0b746e5SOllivier Robert pp->leap = LEAP_NOWARNING; 240c0b746e5SOllivier Robert peer->precision = VMEPRECISION; 241c0b746e5SOllivier Robert peer->stratum = stratumtouse[unit]; 242c0b746e5SOllivier Robert memcpy( (char *)&peer->refid, USNOREFID,4); 243c0b746e5SOllivier Robert 244c0b746e5SOllivier Robert peer->refid = htonl(VMEHSREFID); 245c0b746e5SOllivier Robert 246c0b746e5SOllivier Robert return (1); 247c0b746e5SOllivier Robert } 248c0b746e5SOllivier Robert 249c0b746e5SOllivier Robert 250c0b746e5SOllivier Robert /* 251c0b746e5SOllivier Robert * vme_shutdown - shut down a VME clock 252c0b746e5SOllivier Robert */ 253c0b746e5SOllivier Robert static void 254c0b746e5SOllivier Robert vme_shutdown( 255c0b746e5SOllivier Robert int unit, 256c0b746e5SOllivier Robert struct peer *peer 257c0b746e5SOllivier Robert ) 258c0b746e5SOllivier Robert { 259c0b746e5SOllivier Robert register struct vmeunit *vme; 260c0b746e5SOllivier Robert struct refclockproc *pp; 261c0b746e5SOllivier Robert 262c0b746e5SOllivier Robert pp = peer->procptr; 263c0b746e5SOllivier Robert 264c0b746e5SOllivier Robert if (unit >= MAXUNITS) { 265c0b746e5SOllivier Robert msyslog(LOG_ERR, "vme_shutdown: unit %d invalid", unit); 266c0b746e5SOllivier Robert return; 267c0b746e5SOllivier Robert } 268c0b746e5SOllivier Robert 269c0b746e5SOllivier Robert /* 270c0b746e5SOllivier Robert * Tell the I/O module to turn us off. We're history. 271c0b746e5SOllivier Robert */ 272c0b746e5SOllivier Robert vme = (struct vmeunit *)pp->unitptr; 273c0b746e5SOllivier Robert io_closeclock(&pp->io); 274c0b746e5SOllivier Robert pp->unitptr = NULL; 275c0b746e5SOllivier Robert free(vme); 276c0b746e5SOllivier Robert } 277c0b746e5SOllivier Robert 278c0b746e5SOllivier Robert 279c0b746e5SOllivier Robert /* 280c0b746e5SOllivier Robert * vme_receive - receive data from the VME device. 281c0b746e5SOllivier Robert * 282c0b746e5SOllivier Robert * Note: This interface would be interrupt-driven. We don't use that 283c0b746e5SOllivier Robert * now, but include a dummy routine for possible future adventures. 284c0b746e5SOllivier Robert */ 285c0b746e5SOllivier Robert static void 286c0b746e5SOllivier Robert vme_receive( 287c0b746e5SOllivier Robert struct recvbuf *rbufp 288c0b746e5SOllivier Robert ) 289c0b746e5SOllivier Robert { 290c0b746e5SOllivier Robert } 291c0b746e5SOllivier Robert 292c0b746e5SOllivier Robert 293c0b746e5SOllivier Robert /* 294c0b746e5SOllivier Robert * vme_poll - called by the transmit procedure 295c0b746e5SOllivier Robert */ 296c0b746e5SOllivier Robert static void 297c0b746e5SOllivier Robert vme_poll( 298c0b746e5SOllivier Robert int unit, 299c0b746e5SOllivier Robert struct peer *peer 300c0b746e5SOllivier Robert ) 301c0b746e5SOllivier Robert { 302c0b746e5SOllivier Robert struct vmedate *tptr; 303c0b746e5SOllivier Robert struct vmeunit *vme; 304c0b746e5SOllivier Robert struct refclockproc *pp; 305c0b746e5SOllivier Robert time_t tloc; 306c0b746e5SOllivier Robert struct tm *tadr; 307c0b746e5SOllivier Robert 308c0b746e5SOllivier Robert pp = peer->procptr; 309c0b746e5SOllivier Robert vme = (struct vmeunit *)pp->unitptr; /* Here is the structure */ 310c0b746e5SOllivier Robert 311c0b746e5SOllivier Robert tptr = &vme->vmedata; 312c0b746e5SOllivier Robert if ((tptr = get_datumtime(tptr)) == NULL ) { 313c0b746e5SOllivier Robert refclock_report(peer, CEVNT_BADREPLY); 314c0b746e5SOllivier Robert return; 315c0b746e5SOllivier Robert } 316c0b746e5SOllivier Robert 317c0b746e5SOllivier Robert get_systime(&pp->lastrec); 318c0b746e5SOllivier Robert pp->polls++; 319c0b746e5SOllivier Robert vme->lasttime = current_time; 320c0b746e5SOllivier Robert 321c0b746e5SOllivier Robert /* 322c0b746e5SOllivier Robert * Get VME time and convert to timestamp format. 323c0b746e5SOllivier Robert * The year must come from the system clock. 324c0b746e5SOllivier Robert */ 325c0b746e5SOllivier Robert 326c0b746e5SOllivier Robert time(&tloc); 327c0b746e5SOllivier Robert tadr = gmtime(&tloc); 328c0b746e5SOllivier Robert tptr->year = (unsigned short)(tadr->tm_year + 1900); 329c0b746e5SOllivier Robert 330c0b746e5SOllivier Robert 331c0b746e5SOllivier Robert sprintf(pp->a_lastcode, 332c0b746e5SOllivier Robert "%3.3d %2.2d:%2.2d:%2.2d.%.6ld %1d", 333c0b746e5SOllivier Robert tptr->day, 334c0b746e5SOllivier Robert tptr->hr, 335c0b746e5SOllivier Robert tptr->mn, 336c0b746e5SOllivier Robert tptr->sec, 337c0b746e5SOllivier Robert tptr->frac, 338c0b746e5SOllivier Robert tptr->status); 339c0b746e5SOllivier Robert 340c0b746e5SOllivier Robert pp->lencode = (u_short) strlen(pp->a_lastcode); 341c0b746e5SOllivier Robert 342c0b746e5SOllivier Robert pp->day = tptr->day; 343c0b746e5SOllivier Robert pp->hour = tptr->hr; 344c0b746e5SOllivier Robert pp->minute = tptr->mn; 345c0b746e5SOllivier Robert pp->second = tptr->sec; 346c0b746e5SOllivier Robert pp->usec = tptr->frac; 347c0b746e5SOllivier Robert 348c0b746e5SOllivier Robert #ifdef DEBUG 349c0b746e5SOllivier Robert if (debug) 350c0b746e5SOllivier Robert printf("pp: %3d %02d:%02d:%02d.%06ld %1x\n", 351c0b746e5SOllivier Robert pp->day, pp->hour, pp->minute, pp->second, 352c0b746e5SOllivier Robert pp->usec, tptr->status); 353c0b746e5SOllivier Robert #endif 354c0b746e5SOllivier Robert if (tptr->status ) { /* Status 0 is locked to ref., 1 is not */ 355c0b746e5SOllivier Robert refclock_report(peer, CEVNT_BADREPLY); 356c0b746e5SOllivier Robert return; 357c0b746e5SOllivier Robert } 358c0b746e5SOllivier Robert 359c0b746e5SOllivier Robert /* 360c0b746e5SOllivier Robert * Now, compute the reference time value. Use the heavy 361c0b746e5SOllivier Robert * machinery for the seconds and the millisecond field for the 362c0b746e5SOllivier Robert * fraction when present. If an error in conversion to internal 363c0b746e5SOllivier Robert * format is found, the program declares bad data and exits. 364c0b746e5SOllivier Robert * Note that this code does not yet know how to do the years and 365c0b746e5SOllivier Robert * relies on the clock-calendar chip for sanity. 366c0b746e5SOllivier Robert */ 367c0b746e5SOllivier Robert if (!refclock_process(pp)) { 368c0b746e5SOllivier Robert refclock_report(peer, CEVNT_BADTIME); 369c0b746e5SOllivier Robert return; 370c0b746e5SOllivier Robert } 371c0b746e5SOllivier Robert record_clock_stats(&peer->srcadr, pp->a_lastcode); 372c0b746e5SOllivier Robert refclock_receive(peer); 373c0b746e5SOllivier Robert } 374c0b746e5SOllivier Robert 375c0b746e5SOllivier Robert struct vmedate * 376c0b746e5SOllivier Robert get_datumtime(struct vmedate *time_vme) 377c0b746e5SOllivier Robert { 378c0b746e5SOllivier Robert unsigned short status; 379c0b746e5SOllivier Robert char cbuf[7]; 380c0b746e5SOllivier Robert struct btfp_time vts; 381c0b746e5SOllivier Robert 382c0b746e5SOllivier Robert if ( time_vme == (struct vmedate *)NULL) { 383c0b746e5SOllivier Robert time_vme = (struct vmedate *)malloc(sizeof(struct vmedate )); 384c0b746e5SOllivier Robert } 385c0b746e5SOllivier Robert 386c0b746e5SOllivier Robert if( ioctl(fd_vme, READTIME, &vts)) 387c0b746e5SOllivier Robert msyslog(LOG_ERR, "get_datumtime error: %m"); 388c0b746e5SOllivier Robert 389c0b746e5SOllivier Robert /* if you want to actually check the validity of these registers, do a 390c0b746e5SOllivier Robert define of CHECK above this. I didn't find it necessary. - RES 391c0b746e5SOllivier Robert */ 392c0b746e5SOllivier Robert 393c0b746e5SOllivier Robert #ifdef CHECK 394c0b746e5SOllivier Robert 395c0b746e5SOllivier Robert /* Get day */ 396c0b746e5SOllivier Robert sprintf(cbuf,"%3.3x", ((vts.btfp_time[ 0 ] & 0x000f) <<8) + 397c0b746e5SOllivier Robert ((vts.btfp_time[ 1 ] & 0xff00) >> 8)); 398c0b746e5SOllivier Robert 399c0b746e5SOllivier Robert if (isdigit(cbuf[0]) && isdigit(cbuf[1]) && isdigit(cbuf[2]) ) 400c0b746e5SOllivier Robert time_vme->day = (unsigned short)atoi(cbuf); 401c0b746e5SOllivier Robert else 402c0b746e5SOllivier Robert time_vme->day = (unsigned short) 0; 403c0b746e5SOllivier Robert 404c0b746e5SOllivier Robert /* Get hour */ 405c0b746e5SOllivier Robert sprintf(cbuf,"%2.2x", vts.btfp_time[ 1 ] & 0x00ff); 406c0b746e5SOllivier Robert 407c0b746e5SOllivier Robert if (isdigit(cbuf[0]) && isdigit(cbuf[1])) 408c0b746e5SOllivier Robert time_vme->hr = (unsigned short)atoi(cbuf); 409c0b746e5SOllivier Robert else 410c0b746e5SOllivier Robert time_vme->hr = (unsigned short) 0; 411c0b746e5SOllivier Robert 412c0b746e5SOllivier Robert /* Get minutes */ 413c0b746e5SOllivier Robert sprintf(cbuf,"%2.2x", (vts.btfp_time[ 2 ] & 0xff00) >>8); 414c0b746e5SOllivier Robert if (isdigit(cbuf[0]) && isdigit(cbuf[1])) 415c0b746e5SOllivier Robert time_vme->mn = (unsigned short)atoi(cbuf); 416c0b746e5SOllivier Robert else 417c0b746e5SOllivier Robert time_vme->mn = (unsigned short) 0; 418c0b746e5SOllivier Robert 419c0b746e5SOllivier Robert /* Get seconds */ 420c0b746e5SOllivier Robert sprintf(cbuf,"%2.2x", vts.btfp_time[ 2 ] & 0x00ff); 421c0b746e5SOllivier Robert 422c0b746e5SOllivier Robert if (isdigit(cbuf[0]) && isdigit(cbuf[1])) 423c0b746e5SOllivier Robert time_vme->sec = (unsigned short)atoi(cbuf); 424c0b746e5SOllivier Robert else 425c0b746e5SOllivier Robert time_vme->sec = (unsigned short) 0; 426c0b746e5SOllivier Robert 427c0b746e5SOllivier Robert /* Get microseconds. Yes, we ignore the 0.1 microsecond digit so we can 428c0b746e5SOllivier Robert use the TVTOTSF function later on...*/ 429c0b746e5SOllivier Robert 430c0b746e5SOllivier Robert sprintf(cbuf,"%4.4x%2.2x", vts.btfp_time[ 3 ], 431c0b746e5SOllivier Robert vts.btfp_time[ 4 ]>>8); 432c0b746e5SOllivier Robert 433c0b746e5SOllivier Robert if (isdigit(cbuf[0]) && isdigit(cbuf[1]) && isdigit(cbuf[2]) 434c0b746e5SOllivier Robert && isdigit(cbuf[3]) && isdigit(cbuf[4]) && isdigit(cbuf[5])) 435c0b746e5SOllivier Robert time_vme->frac = (u_long) atoi(cbuf); 436c0b746e5SOllivier Robert else 437c0b746e5SOllivier Robert time_vme->frac = (u_long) 0; 438c0b746e5SOllivier Robert #else 439c0b746e5SOllivier Robert 440c0b746e5SOllivier Robert /* DONT CHECK just trust the card */ 441c0b746e5SOllivier Robert 442c0b746e5SOllivier Robert /* Get day */ 443c0b746e5SOllivier Robert sprintf(cbuf,"%3.3x", ((vts.btfp_time[ 0 ] & 0x000f) <<8) + 444c0b746e5SOllivier Robert ((vts.btfp_time[ 1 ] & 0xff00) >> 8)); 445c0b746e5SOllivier Robert time_vme->day = (unsigned short)atoi(cbuf); 446c0b746e5SOllivier Robert 447c0b746e5SOllivier Robert /* Get hour */ 448c0b746e5SOllivier Robert sprintf(cbuf,"%2.2x", vts.btfp_time[ 1 ] & 0x00ff); 449c0b746e5SOllivier Robert 450c0b746e5SOllivier Robert time_vme->hr = (unsigned short)atoi(cbuf); 451c0b746e5SOllivier Robert 452c0b746e5SOllivier Robert /* Get minutes */ 453c0b746e5SOllivier Robert sprintf(cbuf,"%2.2x", (vts.btfp_time[ 2 ] & 0xff00) >>8); 454c0b746e5SOllivier Robert time_vme->mn = (unsigned short)atoi(cbuf); 455c0b746e5SOllivier Robert 456c0b746e5SOllivier Robert /* Get seconds */ 457c0b746e5SOllivier Robert sprintf(cbuf,"%2.2x", vts.btfp_time[ 2 ] & 0x00ff); 458c0b746e5SOllivier Robert time_vme->sec = (unsigned short)atoi(cbuf); 459c0b746e5SOllivier Robert 460c0b746e5SOllivier Robert /* Get microseconds. Yes, we ignore the 0.1 microsecond digit so we can 461c0b746e5SOllivier Robert use the TVTOTSF function later on...*/ 462c0b746e5SOllivier Robert 463c0b746e5SOllivier Robert sprintf(cbuf,"%4.4x%2.2x", vts.btfp_time[ 3 ], 464c0b746e5SOllivier Robert vts.btfp_time[ 4 ]>>8); 465c0b746e5SOllivier Robert 466c0b746e5SOllivier Robert time_vme->frac = (u_long) atoi(cbuf); 467c0b746e5SOllivier Robert 468c0b746e5SOllivier Robert #endif /* CHECK */ 469c0b746e5SOllivier Robert 470c0b746e5SOllivier Robert /* Get status bit */ 471c0b746e5SOllivier Robert status = (vts.btfp_time[0] & 0x0010) >>4; 472c0b746e5SOllivier Robert time_vme->status = status; /* Status=0 if locked to ref. */ 473c0b746e5SOllivier Robert /* Status=1 if flywheeling */ 474c0b746e5SOllivier Robert if (status) { /* lost lock ? */ 475c0b746e5SOllivier Robert return ((void *)NULL); 476c0b746e5SOllivier Robert } 477c0b746e5SOllivier Robert else 478c0b746e5SOllivier Robert return (time_vme); 479c0b746e5SOllivier Robert } 480c0b746e5SOllivier Robert 481c0b746e5SOllivier Robert #else 482c0b746e5SOllivier Robert int refclock_bancomm_bs; 483c0b746e5SOllivier Robert #endif /* REFCLOCK */ 484