File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / ntpd / refclock_tt560.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:08:37 2012 UTC (12 years, 1 month ago) by misho
Branches: ntp, MAIN
CVS tags: v4_2_6p5p0, v4_2_6p5, HEAD
ntp 4.2.6p5

    1: /*
    2:  * refclock_tt560 - clock driver for the TrueTime 560 IRIG-B decoder
    3:  */
    4: 
    5: #ifdef HAVE_CONFIG_H
    6: #include <config.h>
    7: #endif
    8: 
    9: #if defined(REFCLOCK) && defined(CLOCK_TT560)
   10: 
   11: #include "ntpd.h"
   12: #include "ntp_io.h"
   13: #include "ntp_refclock.h"
   14: #include "ntp_unixtime.h"
   15: #include "sys/tt560_api.h"
   16: #include "ntp_stdlib.h"
   17: 
   18: #include <stdio.h>
   19: #include <ctype.h>
   20: 
   21: /*
   22:  * This driver supports the TrueTime 560 IRIG-B decoder for the PCI bus.
   23:  */ 
   24: 
   25: /*
   26:  * TT560 interface definitions
   27:  */
   28: #define	DEVICE		 "/dev/tt560%d" /* device name and unit */
   29: #define	PRECISION	(-20)	/* precision assumed (1 us) */
   30: #define	REFID		"IRIG"	/* reference ID */
   31: #define	DESCRIPTION	"TrueTime 560 IRIG-B PCI Decoder"
   32: 
   33: /*
   34:  * Unit control structure
   35:  */
   36: struct tt560unit {
   37: 	tt_mem_space_t	 *tt_mem;	/* mapped address of PCI board */
   38: 	time_freeze_reg_t tt560rawt;	/* data returned from PCI board */
   39: };
   40: 
   41: typedef union byteswap_u
   42: {
   43:     unsigned int long_word;
   44:     unsigned char byte[4];
   45: } byteswap_t;
   46: 
   47: /*
   48:  * Function prototypes
   49:  */
   50: static	int	tt560_start	(int, struct peer *);
   51: static	void	tt560_shutdown	(int, struct peer *);
   52: static	void	tt560_poll	(int unit, struct peer *);
   53: 
   54: /*
   55:  * Transfer vector
   56:  */
   57: struct	refclock refclock_tt560 = {
   58: 	tt560_start,		/* clock_start    */
   59: 	tt560_shutdown,		/* clock_shutdown */
   60: 	tt560_poll,		/* clock_poll     */
   61: 	noentry,		/* clock_control (not used) */
   62: 	noentry,		/* clock_init    (not used) */
   63: 	noentry,		/* clock_buginfo (not used) */
   64: 	NOFLAGS			/* clock_flags   (not used) */
   65: };
   66: 
   67: 
   68: /*
   69:  * tt560_start - open the TT560 device and initialize data for processing
   70:  */
   71: static int
   72: tt560_start(
   73: 	int unit,
   74: 	struct peer *peer
   75: 	)
   76: {
   77: 	register struct tt560unit *up;
   78: 	struct refclockproc *pp;
   79: 	char device[20];
   80: 	int     fd;
   81:         caddr_t membase;
   82: 
   83: 	/*
   84: 	 * Open TT560 device
   85: 	 */
   86: 	(void)sprintf(device, DEVICE, unit);
   87: 	fd = open(device, O_RDWR);
   88: 	if (fd == -1) {
   89: 		msyslog(LOG_ERR, "tt560_start: open of %s: %m", device);
   90: 		return (0);
   91: 	}
   92: 
   93: 	/*
   94: 	 * Map the device registers into user space.
   95: 	 */
   96: 	membase = mmap ((caddr_t) 0, TTIME_MEMORY_SIZE,
   97: 			PROT_READ | PROT_WRITE,
   98: 			MAP_SHARED, fd, (off_t)0);
   99: 
  100: 	if (membase == (caddr_t) -1) {
  101: 		msyslog(LOG_ERR, "tt560_start: mapping of %s: %m", device);
  102: 		(void) close(fd);
  103: 		return (0);
  104: 	}
  105: 
  106: 	/*
  107: 	 * Allocate and initialize unit structure
  108: 	 */
  109: 	if (!(up = (struct tt560unit *) emalloc(sizeof(struct tt560unit)))) {
  110: 		(void) close(fd);
  111: 		return (0);
  112: 	}
  113: 	memset((char *)up, 0, sizeof(struct tt560unit));
  114: 	up->tt_mem = (tt_mem_space_t *)membase;
  115: 	pp = peer->procptr;
  116: 	pp->io.clock_recv = noentry;
  117: 	pp->io.srcclock = (caddr_t)peer;
  118: 	pp->io.datalen = 0;
  119: 	pp->io.fd = fd;
  120: 	pp->unitptr = (caddr_t)up;
  121: 
  122: 	/*
  123: 	 * Initialize miscellaneous peer variables
  124: 	 */
  125: 	peer->precision = PRECISION;
  126: 	peer->burst = NSTAGE;
  127: 	pp->clockdesc = DESCRIPTION;
  128: 	memcpy((char *)&pp->refid, REFID, 4);
  129: 	return (1);
  130: }
  131: 
  132: 
  133: /*
  134:  * tt560_shutdown - shut down the clock
  135:  */
  136: static void
  137: tt560_shutdown(
  138: 	int unit,
  139: 	struct peer *peer
  140: 	)
  141: {
  142: 	register struct tt560unit *up;
  143: 	struct refclockproc *pp;
  144: 
  145: 	pp = peer->procptr;
  146: 	up = (struct tt560unit *)pp->unitptr;
  147: 	io_closeclock(&pp->io);
  148: 	free(up);
  149: }
  150: 
  151: 
  152: /*
  153:  * tt560_poll - called by the transmit procedure
  154:  */
  155: static void
  156: tt560_poll(
  157: 	int unit,
  158: 	struct peer *peer
  159: 	)
  160: {
  161: 	register struct tt560unit *up;
  162: 	struct refclockproc       *pp;
  163: 	time_freeze_reg_t         *tp;
  164: 	tt_mem_space_t            *mp;
  165: 
  166: 	int i;
  167: 	unsigned int *p_time_t, *tt_mem_t;
  168: 
  169: 	/*
  170: 	 * This is the main routine. It snatches the time from the TT560
  171: 	 * board and tacks on a local timestamp.
  172: 	 */
  173: 	pp = peer->procptr;
  174: 	up = (struct tt560unit *)pp->unitptr;
  175: 	mp = up->tt_mem;
  176: 	tp = &up->tt560rawt;
  177: 
  178: 	p_time_t = (unsigned int *)tp;
  179: 	tt_mem_t = (unsigned int *)&mp->time_freeze_reg;
  180: 
  181: 	*tt_mem_t = 0;		/* update the time freeze register */
  182: 				/* and copy time stamp to memory */
  183: 	for (i=0; i < TIME_FREEZE_REG_LEN; i++) {
  184: 	    *p_time_t = byte_swap(*tt_mem_t);
  185: 	     p_time_t++;
  186: 	     tt_mem_t++;
  187: 	}
  188: 
  189: 	get_systime(&pp->lastrec);
  190: 	pp->polls++;
  191: 
  192: 	/*
  193: 	 * We get down to business, check the timecode format and decode
  194: 	 * its contents. If the timecode has invalid length or is not in
  195: 	 * proper format, we declare bad format and exit. Note: we
  196: 	 * can't use the sec/usec conversion produced by the driver,
  197: 	 * since the year may be suspect. All format error checking is
  198: 	 * done by the sprintf() and sscanf() routines.
  199: 	 */
  200: 	sprintf(pp->a_lastcode,
  201: 	    "%1x%1x%1x %1x%1x:%1x%1x:%1x%1x.%1x%1x%1x%1x%1x%1x %1x",
  202: 	    tp->hun_day,  tp->tens_day,  tp->unit_day,
  203: 	                  tp->tens_hour, tp->unit_hour,
  204: 	                  tp->tens_min,  tp->unit_min,
  205: 	                  tp->tens_sec,  tp->unit_sec,
  206: 	    tp->hun_ms,   tp->tens_ms,   tp->unit_ms,
  207: 	    tp->hun_us,   tp->tens_us,   tp->unit_us,
  208: 	    tp->status);
  209: 	    pp->lencode = strlen(pp->a_lastcode);
  210: #ifdef DEBUG
  211: 	if (debug)
  212: 		printf("tt560: time %s timecode %d %s\n",
  213: 		   ulfptoa(&pp->lastrec, 6), pp->lencode,
  214: 		   pp->a_lastcode);
  215: #endif
  216: 	if (sscanf(pp->a_lastcode, "%3d %2d:%2d:%2d.%6ld", 
  217:                   &pp->day, &pp->hour, &pp->minute, &pp->second, &pp->usec)
  218: 	    != 5) {
  219: 		refclock_report(peer, CEVNT_BADTIME);
  220: 		return;
  221: 	}
  222: 	if ((tp->status & 0x6) != 0x6)
  223: 		pp->leap = LEAP_NOTINSYNC;
  224: 	else
  225: 		pp->leap = LEAP_NOWARNING;
  226: 	if (!refclock_process(pp)) {
  227: 		refclock_report(peer, CEVNT_BADTIME);
  228: 		return;
  229: 	}
  230: 	if (peer->burst > 0)
  231: 		return;
  232: 	if (pp->coderecv == pp->codeproc) {
  233: 		refclock_report(peer, CEVNT_TIMEOUT);
  234: 		return;
  235: 	}
  236: 	record_clock_stats(&peer->srcadr, pp->a_lastcode);
  237: 	refclock_receive(peer);
  238: 	peer->burst = NSTAGE;
  239: }
  240: 
  241: /******************************************************************
  242:  *
  243:  *  byte_swap
  244:  *
  245:  *  Inputs: 32 bit integer
  246:  *
  247:  *  Output: byte swapped 32 bit integer.
  248:  *
  249:  *  This routine is used to compensate for the byte alignment
  250:  *  differences between big-endian and little-endian integers.
  251:  *
  252:  ******************************************************************/
  253: static unsigned int
  254: byte_swap(unsigned int input_num)
  255: {
  256:     byteswap_t    byte_swap;
  257:     unsigned char temp;
  258: 
  259:     byte_swap.long_word = input_num;
  260: 
  261:     temp              = byte_swap.byte[3];
  262:     byte_swap.byte[3] = byte_swap.byte[0];
  263:     byte_swap.byte[0] = temp;
  264: 
  265:     temp              = byte_swap.byte[2];
  266:     byte_swap.byte[2] = byte_swap.byte[1];
  267:     byte_swap.byte[1] = temp;
  268: 
  269:     return (byte_swap.long_word);
  270: }
  271: 
  272: #else
  273: int refclock_tt560_bs;
  274: #endif /* REFCLOCK */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>