Annotation of embedaddon/ntp/ntpd/refclock_tpro.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * refclock_tpro - clock driver for the KSI/Odetics TPRO-S IRIG-B reader
                      3:  */
                      4: 
                      5: #ifdef HAVE_CONFIG_H
                      6: #include <config.h>
                      7: #endif
                      8: 
                      9: #if defined(REFCLOCK) && defined(CLOCK_TPRO)
                     10: 
                     11: #include "ntpd.h"
                     12: #include "ntp_io.h"
                     13: #include "ntp_refclock.h"
                     14: #include "ntp_unixtime.h"
                     15: #include "sys/tpro.h"
                     16: #include "ntp_stdlib.h"
                     17: 
                     18: #include <stdio.h>
                     19: #include <ctype.h>
                     20: 
                     21: /*
                     22:  * This driver supports the KSI/Odetecs TPRO-S IRIG-B reader and TPRO-
                     23:  * SAT GPS receiver for the Sun Microsystems SBus. It requires that the
                     24:  * tpro.o device driver be installed and loaded.
                     25:  */ 
                     26: 
                     27: /*
                     28:  * TPRO interface definitions
                     29:  */
                     30: #define        DEVICE           "/dev/tpro%d" /* device name and unit */
                     31: #define        PRECISION       (-20)   /* precision assumed (1 us) */
                     32: #define        REFID           "IRIG"  /* reference ID */
                     33: #define        DESCRIPTION     "KSI/Odetics TPRO/S IRIG Interface" /* WRU */
                     34: 
                     35: /*
                     36:  * Unit control structure
                     37:  */
                     38: struct tprounit {
                     39:        struct  tproval tprodata; /* data returned from tpro read */
                     40: };
                     41: 
                     42: /*
                     43:  * Function prototypes
                     44:  */
                     45: static int     tpro_start      (int, struct peer *);
                     46: static void    tpro_shutdown   (int, struct peer *);
                     47: static void    tpro_poll       (int unit, struct peer *);
                     48: 
                     49: /*
                     50:  * Transfer vector
                     51:  */
                     52: struct refclock refclock_tpro = {
                     53:        tpro_start,             /* start up driver */
                     54:        tpro_shutdown,          /* shut down driver */
                     55:        tpro_poll,              /* transmit poll message */
                     56:        noentry,                /* not used (old tpro_control) */
                     57:        noentry,                /* initialize driver (not used) */
                     58:        noentry,                /* not used (old tpro_buginfo) */
                     59:        NOFLAGS                 /* not used */
                     60: };
                     61: 
                     62: 
                     63: /*
                     64:  * tpro_start - open the TPRO device and initialize data for processing
                     65:  */
                     66: static int
                     67: tpro_start(
                     68:        int unit,
                     69:        struct peer *peer
                     70:        )
                     71: {
                     72:        register struct tprounit *up;
                     73:        struct refclockproc *pp;
                     74:        char device[20];
                     75:        int fd;
                     76: 
                     77:        /*
                     78:         * Open TPRO device
                     79:         */
                     80:        snprintf(device, sizeof(device), DEVICE, unit);
                     81:        fd = open(device, O_RDONLY | O_NDELAY, 0777);
                     82:        if (fd == -1) {
                     83:                msyslog(LOG_ERR, "tpro_start: open of %s: %m", device);
                     84:                return (0);
                     85:        }
                     86: 
                     87:        /*
                     88:         * Allocate and initialize unit structure
                     89:         */
                     90:        up = emalloc(sizeof(*up));
                     91:        memset(up, 0, sizeof(*up));
                     92:        pp = peer->procptr;
                     93:        pp->io.clock_recv = noentry;
                     94:        pp->io.srcclock = (caddr_t)peer;
                     95:        pp->io.datalen = 0;
                     96:        pp->io.fd = fd;
                     97:        pp->unitptr = (caddr_t)up;
                     98: 
                     99:        /*
                    100:         * Initialize miscellaneous peer variables
                    101:         */
                    102:        peer->precision = PRECISION;
                    103:        peer->burst = NSTAGE;
                    104:        pp->clockdesc = DESCRIPTION;
                    105:        memcpy((char *)&pp->refid, REFID, 4);
                    106:        return (1);
                    107: }
                    108: 
                    109: 
                    110: /*
                    111:  * tpro_shutdown - shut down the clock
                    112:  */
                    113: static void
                    114: tpro_shutdown(
                    115:        int unit,
                    116:        struct peer *peer
                    117:        )
                    118: {
                    119:        register struct tprounit *up;
                    120:        struct refclockproc *pp;
                    121: 
                    122:        pp = peer->procptr;
                    123:        up = (struct tprounit *)pp->unitptr;
                    124:        io_closeclock(&pp->io);
                    125:        if (NULL != up)
                    126:                free(up);
                    127: }
                    128: 
                    129: 
                    130: /*
                    131:  * tpro_poll - called by the transmit procedure
                    132:  */
                    133: static void
                    134: tpro_poll(
                    135:        int unit,
                    136:        struct peer *peer
                    137:        )
                    138: {
                    139:        register struct tprounit *up;
                    140:        struct refclockproc *pp;
                    141:        struct tproval *tp;
                    142: 
                    143:        /*
                    144:         * This is the main routine. It snatches the time from the TPRO
                    145:         * board and tacks on a local timestamp.
                    146:         */
                    147:        pp = peer->procptr;
                    148:        up = (struct tprounit *)pp->unitptr;
                    149: 
                    150:        tp = &up->tprodata;
                    151:        if (read(pp->io.fd, (char *)tp, sizeof(struct tproval)) < 0) {
                    152:                refclock_report(peer, CEVNT_FAULT);
                    153:                return;
                    154:        }
                    155:        get_systime(&pp->lastrec);
                    156:        pp->polls++;
                    157: 
                    158:        /*
                    159:         * We get down to business, check the timecode format and decode
                    160:         * its contents. If the timecode has invalid length or is not in
                    161:         * proper format, we declare bad format and exit. Note: we
                    162:         * can't use the sec/usec conversion produced by the driver,
                    163:         * since the year may be suspect. All format error checking is
                    164:         * done by the sprintf() and sscanf() routines.
                    165:         *
                    166:         * Note that the refclockproc usec member has now become nsec.
                    167:         * We could either multiply the read-in usec value by 1000 or
                    168:         * we could pad the written string appropriately and read the
                    169:         * resulting value in already scaled.
                    170:         */
                    171:        snprintf(pp->a_lastcode, sizeof(pp->a_lastcode),
                    172:                 "%1x%1x%1x %1x%1x:%1x%1x:%1x%1x.%1x%1x%1x%1x%1x%1x %1x",
                    173:                 tp->day100, tp->day10, tp->day1, tp->hour10, tp->hour1,
                    174:                 tp->min10, tp->min1, tp->sec10, tp->sec1, tp->ms100,
                    175:                 tp->ms10, tp->ms1, tp->usec100, tp->usec10, tp->usec1,
                    176:                 tp->status);
                    177:        pp->lencode = strlen(pp->a_lastcode);
                    178: #ifdef DEBUG
                    179:        if (debug)
                    180:                printf("tpro: time %s timecode %d %s\n",
                    181:                   ulfptoa(&pp->lastrec, 6), pp->lencode,
                    182:                   pp->a_lastcode);
                    183: #endif
                    184:        if (sscanf(pp->a_lastcode, "%3d %2d:%2d:%2d.%6ld", &pp->day,
                    185:            &pp->hour, &pp->minute, &pp->second, &pp->nsec)
                    186:            != 5) {
                    187:                refclock_report(peer, CEVNT_BADTIME);
                    188:                return;
                    189:        }
                    190:        pp->nsec *= 1000;       /* Convert usec to nsec */
                    191:        if (!tp->status & 0x3)
                    192:                pp->leap = LEAP_NOTINSYNC;
                    193:        else
                    194:                pp->leap = LEAP_NOWARNING;
                    195:        if (!refclock_process(pp)) {
                    196:                refclock_report(peer, CEVNT_BADTIME);
                    197:                return;
                    198:        }
                    199:        if (peer->burst > 0)
                    200:                return;
                    201:        if (pp->coderecv == pp->codeproc) {
                    202:                refclock_report(peer, CEVNT_TIMEOUT);
                    203:                return;
                    204:        }
                    205:        pp->lastref = pp->lastrec;
                    206:        record_clock_stats(&peer->srcadr, pp->a_lastcode);
                    207:        refclock_receive(peer);
                    208:        peer->burst = NSTAGE;
                    209: }
                    210: 
                    211: #else
                    212: int refclock_tpro_bs;
                    213: #endif /* REFCLOCK */

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