Annotation of embedaddon/ntp/ntpd/refclock_tt560.c, revision 1.1
1.1 ! misho 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>