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

1.1       misho       1: /*
                      2:  * refclock_wwvb - clock driver for Spectracom WWVB and GPS receivers
                      3:  */
                      4: 
                      5: #ifdef HAVE_CONFIG_H
                      6: #include <config.h>
                      7: #endif
                      8: 
                      9: #if defined(REFCLOCK) && defined(CLOCK_SPECTRACOM)
                     10: 
                     11: #include "ntpd.h"
                     12: #include "ntp_io.h"
                     13: #include "ntp_refclock.h"
                     14: #include "ntp_calendar.h"
                     15: #include "ntp_stdlib.h"
                     16: 
                     17: #include <stdio.h>
                     18: #include <ctype.h>
                     19: 
                     20: #ifdef HAVE_PPSAPI
                     21: #include "ppsapi_timepps.h"
                     22: #include "refclock_atom.h"
                     23: #endif /* HAVE_PPSAPI */
                     24: 
                     25: /*
                     26:  * This driver supports the Spectracom Model 8170 and Netclock/2 WWVB
                     27:  * Synchronized Clocks and the Netclock/GPS Master Clock. Both the WWVB
                     28:  * and GPS clocks have proven reliable sources of time; however, the
                     29:  * WWVB clocks have proven vulnerable to high ambient conductive RF
                     30:  * interference. The claimed accuracy of the WWVB clocks is 100 us
                     31:  * relative to the broadcast signal, while the claimed accuracy of the
                     32:  * GPS clock is 50 ns; however, in most cases the actual accuracy is
                     33:  * limited by the resolution of the timecode and the latencies of the
                     34:  * serial interface and operating system.
                     35:  *
                     36:  * The WWVB and GPS clocks should be configured for 24-hour display,
                     37:  * AUTO DST off, time zone 0 (UTC), data format 0 or 2 (see below) and
                     38:  * baud rate 9600. If the clock is to used as the source for the IRIG
                     39:  * Audio Decoder (refclock_irig.c in this distribution), it should be
                     40:  * configured for AM IRIG output and IRIG format 1 (IRIG B with
                     41:  * signature control). The GPS clock can be configured either to respond
                     42:  * to a 'T' poll character or left running continuously. 
                     43:  *
                     44:  * There are two timecode formats used by these clocks. Format 0, which
                     45:  * is available with both the Netclock/2 and 8170, and format 2, which
                     46:  * is available only with the Netclock/2, specially modified 8170 and
                     47:  * GPS.
                     48:  *
                     49:  * Format 0 (22 ASCII printing characters):
                     50:  *
                     51:  * <cr><lf>i  ddd hh:mm:ss TZ=zz<cr><lf>
                     52:  *
                     53:  *     on-time = first <cr>
                     54:  *     hh:mm:ss = hours, minutes, seconds
                     55:  *     i = synchronization flag (' ' = in synch, '?' = out of synch)
                     56:  *
                     57:  * The alarm condition is indicated by other than ' ' at i, which occurs
                     58:  * during initial synchronization and when received signal is lost for
                     59:  * about ten hours.
                     60:  *
                     61:  * Format 2 (24 ASCII printing characters):
                     62:  *
                     63:  * <cr><lf>iqyy ddd hh:mm:ss.fff ld
                     64:  *
                     65:  *     on-time = <cr>
                     66:  *     i = synchronization flag (' ' = in synch, '?' = out of synch)
                     67:  *     q = quality indicator (' ' = locked, 'A'...'D' = unlocked)
                     68:  *     yy = year (as broadcast)
                     69:  *     ddd = day of year
                     70:  *     hh:mm:ss.fff = hours, minutes, seconds, milliseconds
                     71:  *
                     72:  * The alarm condition is indicated by other than ' ' at i, which occurs
                     73:  * during initial synchronization and when received signal is lost for
                     74:  * about ten hours. The unlock condition is indicated by other than ' '
                     75:  * at q.
                     76:  *
                     77:  * The q is normally ' ' when the time error is less than 1 ms and a
                     78:  * character in the set 'A'...'D' when the time error is less than 10,
                     79:  * 100, 500 and greater than 500 ms respectively. The l is normally ' ',
                     80:  * but is set to 'L' early in the month of an upcoming UTC leap second
                     81:  * and reset to ' ' on the first day of the following month. The d is
                     82:  * set to 'S' for standard time 'I' on the day preceding a switch to
                     83:  * daylight time, 'D' for daylight time and 'O' on the day preceding a
                     84:  * switch to standard time. The start bit of the first <cr> is
                     85:  * synchronized to the indicated time as returned.
                     86:  *
                     87:  * This driver does not need to be told which format is in use - it
                     88:  * figures out which one from the length of the message. The driver
                     89:  * makes no attempt to correct for the intrinsic jitter of the radio
                     90:  * itself, which is a known problem with the older radios.
                     91:  *
                     92:  * PPS Signal Processing
                     93:  *
                     94:  * When PPS signal processing is enabled, and when the system clock has
                     95:  * been set by this or another driver and the PPS signal offset is
                     96:  * within 0.4 s of the system clock offset, the PPS signal replaces the
                     97:  * timecode for as long as the PPS signal is active. If for some reason
                     98:  * the PPS signal fails for one or more poll intervals, the driver
                     99:  * reverts to the timecode. If the timecode fails for one or more poll
                    100:  * intervals, the PPS signal is disconnected.
                    101:  *
                    102:  * Fudge Factors
                    103:  *
                    104:  * This driver can retrieve a table of quality data maintained
                    105:  * internally by the Netclock/2 clock. If flag4 of the fudge
                    106:  * configuration command is set to 1, the driver will retrieve this
                    107:  * table and write it to the clockstats file when the first timecode
                    108:  * message of a new day is received.
                    109:  *
                    110:  * PPS calibration fudge time 1: format 0 .003134, format 2 .004034
                    111:  */
                    112: /*
                    113:  * Interface definitions
                    114:  */
                    115: #define        DEVICE          "/dev/wwvb%d" /* device name and unit */
                    116: #define        SPEED232        B9600   /* uart speed (9600 baud) */
                    117: #define        PRECISION       (-13)   /* precision assumed (about 100 us) */
                    118: #define        PPS_PRECISION   (-13)   /* precision assumed (about 100 us) */
                    119: #define        REFID           "WWVB"  /* reference ID */
                    120: #define        DESCRIPTION     "Spectracom WWVB/GPS Receiver" /* WRU */
                    121: 
                    122: #define        LENWWVB0        22      /* format 0 timecode length */
                    123: #define        LENWWVB2        24      /* format 2 timecode length */
                    124: #define LENWWVB3       29      /* format 3 timecode length */
                    125: #define MONLIN         15      /* number of monitoring lines */
                    126: 
                    127: /*
                    128:  * WWVB unit control structure
                    129:  */
                    130: struct wwvbunit {
                    131: #ifdef HAVE_PPSAPI
                    132:        struct refclock_atom atom; /* PPSAPI structure */
                    133:        int     ppsapi_tried;   /* attempt PPSAPI once */
                    134:        int     ppsapi_lit;     /* time_pps_create() worked */
                    135:        int     tcount;         /* timecode sample counter */
                    136:        int     pcount;         /* PPS sample counter */
                    137: #endif /* HAVE_PPSAPI */
                    138:        l_fp    laststamp;      /* last <CR> timestamp */
                    139:        int     prev_eol_cr;    /* was last EOL <CR> (not <LF>)? */
                    140:        u_char  lasthour;       /* last hour (for monitor) */
                    141:        u_char  linect;         /* count ignored lines (for monitor */
                    142: };
                    143: 
                    144: /*
                    145:  * Function prototypes
                    146:  */
                    147: static int     wwvb_start      (int, struct peer *);
                    148: static void    wwvb_shutdown   (int, struct peer *);
                    149: static void    wwvb_receive    (struct recvbuf *);
                    150: static void    wwvb_poll       (int, struct peer *);
                    151: static void    wwvb_timer      (int, struct peer *);
                    152: #ifdef HAVE_PPSAPI
                    153: static void    wwvb_control    (int, const struct refclockstat *,
                    154:                                 struct refclockstat *, struct peer *);
                    155: #define                WWVB_CONTROL    wwvb_control
                    156: #else
                    157: #define                WWVB_CONTROL    noentry
                    158: #endif /* HAVE_PPSAPI */
                    159: 
                    160: /*
                    161:  * Transfer vector
                    162:  */
                    163: struct refclock refclock_wwvb = {
                    164:        wwvb_start,             /* start up driver */
                    165:        wwvb_shutdown,          /* shut down driver */
                    166:        wwvb_poll,              /* transmit poll message */
                    167:        WWVB_CONTROL,           /* fudge set/change notification */
                    168:        noentry,                /* initialize driver (not used) */
                    169:        noentry,                /* not used (old wwvb_buginfo) */
                    170:        wwvb_timer              /* called once per second */
                    171: };
                    172: 
                    173: 
                    174: /*
                    175:  * wwvb_start - open the devices and initialize data for processing
                    176:  */
                    177: static int
                    178: wwvb_start(
                    179:        int unit,
                    180:        struct peer *peer
                    181:        )
                    182: {
                    183:        register struct wwvbunit *up;
                    184:        struct refclockproc *pp;
                    185:        int fd;
                    186:        char device[20];
                    187: 
                    188:        /*
                    189:         * Open serial port. Use CLK line discipline, if available.
                    190:         */
                    191:        snprintf(device, sizeof(device), DEVICE, unit);
                    192:        fd = refclock_open(device, SPEED232, LDISC_CLK);
                    193:        if (fd <= 0)
                    194:                return (0);
                    195: 
                    196:        /*
                    197:         * Allocate and initialize unit structure
                    198:         */
                    199:        up = emalloc_zero(sizeof(*up));
                    200:        pp = peer->procptr;
                    201:        pp->io.clock_recv = wwvb_receive;
                    202:        pp->io.srcclock = (void *)peer;
                    203:        pp->io.datalen = 0;
                    204:        pp->io.fd = fd;
                    205:        if (!io_addclock(&pp->io)) {
                    206:                close(fd);
                    207:                pp->io.fd = -1;
                    208:                free(up);
                    209:                return (0);
                    210:        }
                    211:        pp->unitptr = up;
                    212: 
                    213:        /*
                    214:         * Initialize miscellaneous variables
                    215:         */
                    216:        peer->precision = PRECISION;
                    217:        pp->clockdesc = DESCRIPTION;
                    218:        memcpy(&pp->refid, REFID, 4);
                    219:        return (1);
                    220: }
                    221: 
                    222: 
                    223: /*
                    224:  * wwvb_shutdown - shut down the clock
                    225:  */
                    226: static void
                    227: wwvb_shutdown(
                    228:        int unit,
                    229:        struct peer *peer
                    230:        )
                    231: {
                    232:        register struct wwvbunit *up;
                    233:        struct refclockproc *pp;
                    234: 
                    235:        pp = peer->procptr;
                    236:        up = pp->unitptr;
                    237:        if (-1 != pp->io.fd)
                    238:                io_closeclock(&pp->io);
                    239:        if (NULL != up)
                    240:                free(up);
                    241: }
                    242: 
                    243: 
                    244: /*
                    245:  * wwvb_receive - receive data from the serial interface
                    246:  */
                    247: static void
                    248: wwvb_receive(
                    249:        struct recvbuf *rbufp
                    250:        )
                    251: {
                    252:        struct wwvbunit *up;
                    253:        struct refclockproc *pp;
                    254:        struct peer *peer;
                    255: 
                    256:        l_fp    trtmp;          /* arrival timestamp */
                    257:        int     tz;             /* time zone */
                    258:        int     day, month;     /* ddd conversion */
                    259:        int     temp;           /* int temp */
                    260:        char    syncchar;       /* synchronization indicator */
                    261:        char    qualchar;       /* quality indicator */
                    262:        char    leapchar;       /* leap indicator */
                    263:        char    dstchar;        /* daylight/standard indicator */
                    264:        char    tmpchar;        /* trashbin */
                    265: 
                    266:        /*
                    267:         * Initialize pointers and read the timecode and timestamp
                    268:         */
                    269:        peer = rbufp->recv_peer;
                    270:        pp = peer->procptr;
                    271:        up = pp->unitptr;
                    272:        temp = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &trtmp);
                    273: 
                    274:        /*
                    275:         * Note we get a buffer and timestamp for both a <cr> and <lf>,
                    276:         * but only the <cr> timestamp is retained. Note: in format 0 on
                    277:         * a Netclock/2 or upgraded 8170 the start bit is delayed 100
                    278:         * +-50 us relative to the pps; however, on an unmodified 8170
                    279:         * the start bit can be delayed up to 10 ms. In format 2 the
                    280:         * reading precision is only to the millisecond. Thus, unless
                    281:         * you have a PPS gadget and don't have to have the year, format
                    282:         * 0 provides the lowest jitter.
                    283:         * Save the timestamp of each <CR> in up->laststamp.  Lines with
                    284:         * no characters occur for every <LF>, and for some <CR>s when
                    285:         * format 0 is used. Format 0 starts and ends each cycle with a
                    286:         * <CR><LF> pair, format 2 starts each cycle with its only pair.
                    287:         * The preceding <CR> is the on-time character for both formats.
                    288:         * The timestamp provided with non-empty lines corresponds to
                    289:         * the <CR> following the timecode, which is ultimately not used
                    290:         * with format 0 and is used for the following timecode for
                    291:         * format 2.
                    292:         */
                    293:        if (temp == 0) {
                    294:                if (up->prev_eol_cr) {
                    295:                        DPRINTF(2, ("wwvb: <LF> @ %s\n",
                    296:                                    prettydate(&trtmp)));
                    297:                } else {
                    298:                        up->laststamp = trtmp;
                    299:                        DPRINTF(2, ("wwvb: <CR> @ %s\n", 
                    300:                                    prettydate(&trtmp)));
                    301:                }
                    302:                up->prev_eol_cr = !up->prev_eol_cr;
                    303:                return;
                    304:        }
                    305:        pp->lencode = temp;
                    306:        pp->lastrec = up->laststamp;
                    307:        up->laststamp = trtmp;
                    308:        up->prev_eol_cr = TRUE;
                    309:        DPRINTF(2, ("wwvb: code @ %s\n"
                    310:                    "       using %s minus one char\n",
                    311:                    prettydate(&trtmp), prettydate(&pp->lastrec)));
                    312:        if (L_ISZERO(&pp->lastrec))
                    313:                return;
                    314: 
                    315:        /*
                    316:         * We get down to business, check the timecode format and decode
                    317:         * its contents. This code uses the timecode length to determine
                    318:         * format 0, 2 or 3. If the timecode has invalid length or is
                    319:         * not in proper format, we declare bad format and exit.
                    320:         */
                    321:        syncchar = qualchar = leapchar = dstchar = ' ';
                    322:        tz = 0;
                    323:        switch (pp->lencode) {
                    324: 
                    325:        case LENWWVB0:
                    326: 
                    327:                /*
                    328:                 * Timecode format 0: "I  ddd hh:mm:ss DTZ=nn"
                    329:                 */
                    330:                if (sscanf(pp->a_lastcode,
                    331:                    "%c %3d %2d:%2d:%2d%c%cTZ=%2d",
                    332:                    &syncchar, &pp->day, &pp->hour, &pp->minute,
                    333:                    &pp->second, &tmpchar, &dstchar, &tz) == 8) {
                    334:                        pp->nsec = 0;
                    335:                        break;
                    336:                }
                    337:                goto bad_format;
                    338: 
                    339:        case LENWWVB2:
                    340: 
                    341:                /*
                    342:                 * Timecode format 2: "IQyy ddd hh:mm:ss.mmm LD" */
                    343:                if (sscanf(pp->a_lastcode,
                    344:                    "%c%c %2d %3d %2d:%2d:%2d.%3ld %c",
                    345:                    &syncchar, &qualchar, &pp->year, &pp->day,
                    346:                    &pp->hour, &pp->minute, &pp->second, &pp->nsec,
                    347:                    &leapchar) == 9) {
                    348:                        pp->nsec *= 1000000;
                    349:                        break;
                    350:                }
                    351:                goto bad_format;
                    352: 
                    353:        case LENWWVB3:
                    354: 
                    355:                /*
                    356:                 * Timecode format 3: "0003I yyyymmdd hhmmss+0000SL#"
                    357:                 * WARNING: Undocumented, and the on-time character # is
                    358:                 * not yet handled correctly by this driver.  It may be
                    359:                 * as simple as compensating for an additional 1/960 s.
                    360:                 */
                    361:                if (sscanf(pp->a_lastcode,
                    362:                    "0003%c %4d%2d%2d %2d%2d%2d+0000%c%c",
                    363:                    &syncchar, &pp->year, &month, &day, &pp->hour,
                    364:                    &pp->minute, &pp->second, &dstchar, &leapchar) == 8)
                    365:                    {
                    366:                        pp->day = ymd2yd(pp->year, month, day);
                    367:                        pp->nsec = 0;
                    368:                        break;
                    369:                }
                    370:                goto bad_format;
                    371: 
                    372:        default:
                    373:        bad_format:
                    374: 
                    375:                /*
                    376:                 * Unknown format: If dumping internal table, record
                    377:                 * stats; otherwise, declare bad format.
                    378:                 */
                    379:                if (up->linect > 0) {
                    380:                        up->linect--;
                    381:                        record_clock_stats(&peer->srcadr,
                    382:                            pp->a_lastcode);
                    383:                } else {
                    384:                        refclock_report(peer, CEVNT_BADREPLY);
                    385:                }
                    386:                return;
                    387:        }
                    388: 
                    389:        /*
                    390:         * Decode synchronization, quality and leap characters. If
                    391:         * unsynchronized, set the leap bits accordingly and exit.
                    392:         * Otherwise, set the leap bits according to the leap character.
                    393:         * Once synchronized, the dispersion depends only on the
                    394:         * quality character.
                    395:         */
                    396:        switch (qualchar) {
                    397: 
                    398:            case ' ':
                    399:                pp->disp = .001;
                    400:                pp->lastref = pp->lastrec;
                    401:                break;
                    402: 
                    403:            case 'A':
                    404:                pp->disp = .01;
                    405:                break;
                    406: 
                    407:            case 'B':
                    408:                pp->disp = .1;
                    409:                break;
                    410: 
                    411:            case 'C':
                    412:                pp->disp = .5;
                    413:                break;
                    414: 
                    415:            case 'D':
                    416:                pp->disp = MAXDISPERSE;
                    417:                break;
                    418: 
                    419:            default:
                    420:                pp->disp = MAXDISPERSE;
                    421:                refclock_report(peer, CEVNT_BADREPLY);
                    422:                break;
                    423:        }
                    424:        if (syncchar != ' ')
                    425:                pp->leap = LEAP_NOTINSYNC;
                    426:        else if (leapchar == 'L')
                    427:                pp->leap = LEAP_ADDSECOND;
                    428:        else
                    429:                pp->leap = LEAP_NOWARNING;
                    430: 
                    431:        /*
                    432:         * Process the new sample in the median filter and determine the
                    433:         * timecode timestamp, but only if the PPS is not in control.
                    434:         */
                    435: #ifdef HAVE_PPSAPI
                    436:        up->tcount++;
                    437:        if (peer->flags & FLAG_PPS)
                    438:                return;
                    439: 
                    440: #endif /* HAVE_PPSAPI */
                    441:        if (!refclock_process_f(pp, pp->fudgetime2))
                    442:                refclock_report(peer, CEVNT_BADTIME);
                    443: }
                    444: 
                    445: 
                    446: /*
                    447:  * wwvb_timer - called once per second by the transmit procedure
                    448:  */
                    449: static void
                    450: wwvb_timer(
                    451:        int unit,
                    452:        struct peer *peer
                    453:        )
                    454: {
                    455:        register struct wwvbunit *up;
                    456:        struct refclockproc *pp;
                    457:        char    pollchar;       /* character sent to clock */
                    458:        l_fp    now;
                    459: 
                    460:        /*
                    461:         * Time to poll the clock. The Spectracom clock responds to a
                    462:         * 'T' by returning a timecode in the format(s) specified above.
                    463:         * Note there is no checking on state, since this may not be the
                    464:         * only customer reading the clock. Only one customer need poll
                    465:         * the clock; all others just listen in.
                    466:         */
                    467:        pp = peer->procptr;
                    468:        up = pp->unitptr;
                    469:        if (up->linect > 0)
                    470:                pollchar = 'R';
                    471:        else
                    472:                pollchar = 'T';
                    473:        if (write(pp->io.fd, &pollchar, 1) != 1)
                    474:                refclock_report(peer, CEVNT_FAULT);
                    475: #ifdef DEBUG
                    476:        get_systime(&now);
                    477:        if (debug)
                    478:                printf("%c poll at %s\n", pollchar, prettydate(&now));
                    479: #endif
                    480: #ifdef HAVE_PPSAPI
                    481:        if (up->ppsapi_lit &&
                    482:            refclock_pps(peer, &up->atom, pp->sloppyclockflag) > 0) {
                    483:                up->pcount++,
                    484:                peer->flags |= FLAG_PPS;
                    485:                peer->precision = PPS_PRECISION;
                    486:        }
                    487: #endif /* HAVE_PPSAPI */
                    488: }
                    489: 
                    490: 
                    491: /*
                    492:  * wwvb_poll - called by the transmit procedure
                    493:  */
                    494: static void
                    495: wwvb_poll(
                    496:        int unit,
                    497:        struct peer *peer
                    498:        )
                    499: {
                    500:        register struct wwvbunit *up;
                    501:        struct refclockproc *pp;
                    502: 
                    503:        /*
                    504:         * Sweep up the samples received since the last poll. If none
                    505:         * are received, declare a timeout and keep going.
                    506:         */
                    507:        pp = peer->procptr;
                    508:        up = pp->unitptr;
                    509:        pp->polls++;
                    510: 
                    511:        /*
                    512:         * If the monitor flag is set (flag4), we dump the internal
                    513:         * quality table at the first timecode beginning the day.
                    514:         */
                    515:        if (pp->sloppyclockflag & CLK_FLAG4 && pp->hour <
                    516:            (int)up->lasthour)
                    517:                up->linect = MONLIN;
                    518:        up->lasthour = (u_char)pp->hour;
                    519: 
                    520:        /*
                    521:         * Process median filter samples. If none received, declare a
                    522:         * timeout and keep going.
                    523:         */
                    524: #ifdef HAVE_PPSAPI
                    525:        if (up->pcount == 0) {
                    526:                peer->flags &= ~FLAG_PPS;
                    527:                peer->precision = PRECISION;
                    528:        }
                    529:        if (up->tcount == 0) {
                    530:                pp->coderecv = pp->codeproc;
                    531:                refclock_report(peer, CEVNT_TIMEOUT);
                    532:                return;
                    533:        }
                    534:        up->pcount = up->tcount = 0;
                    535: #else /* HAVE_PPSAPI */
                    536:        if (pp->coderecv == pp->codeproc) {
                    537:                refclock_report(peer, CEVNT_TIMEOUT);
                    538:                return;
                    539:        }
                    540: #endif /* HAVE_PPSAPI */
                    541:        refclock_receive(peer);
                    542:        record_clock_stats(&peer->srcadr, pp->a_lastcode);
                    543: #ifdef DEBUG
                    544:        if (debug)
                    545:                printf("wwvb: timecode %d %s\n", pp->lencode,
                    546:                    pp->a_lastcode);
                    547: #endif
                    548: }
                    549: 
                    550: 
                    551: /*
                    552:  * wwvb_control - fudge parameters have been set or changed
                    553:  */
                    554: #ifdef HAVE_PPSAPI
                    555: static void
                    556: wwvb_control(
                    557:        int unit,
                    558:        const struct refclockstat *in_st,
                    559:        struct refclockstat *out_st,
                    560:        struct peer *peer
                    561:        )
                    562: {
                    563:        register struct wwvbunit *up;
                    564:        struct refclockproc *pp;
                    565:        
                    566:        pp = peer->procptr;
                    567:        up = pp->unitptr;
                    568: 
                    569:        if (!(pp->sloppyclockflag & CLK_FLAG1)) {
                    570:                if (!up->ppsapi_tried)
                    571:                        return;
                    572:                up->ppsapi_tried = 0;
                    573:                if (!up->ppsapi_lit)
                    574:                        return;
                    575:                peer->flags &= ~FLAG_PPS;
                    576:                peer->precision = PRECISION;
                    577:                time_pps_destroy(up->atom.handle);
                    578:                up->atom.handle = 0;
                    579:                up->ppsapi_lit = 0;
                    580:                return;
                    581:        }
                    582: 
                    583:        if (up->ppsapi_tried)
                    584:                return;
                    585:        /*
                    586:         * Light up the PPSAPI interface.
                    587:         */
                    588:        up->ppsapi_tried = 1;
                    589:        if (refclock_ppsapi(pp->io.fd, &up->atom)) {
                    590:                up->ppsapi_lit = 1;
                    591:                return;
                    592:        }
                    593: 
                    594:        NLOG(NLOG_CLOCKINFO)
                    595:                msyslog(LOG_WARNING, "%s flag1 1 but PPSAPI fails",
                    596:                        refnumtoa(&peer->srcadr));
                    597: }
                    598: #endif /* HAVE_PPSAPI */
                    599: 
                    600: #else
                    601: int refclock_wwvb_bs;
                    602: #endif /* REFCLOCK */

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