Annotation of embedaddon/ntp/ntpd/refclock_ulink.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * refclock_ulink - clock driver for Ultralink  WWVB receiver
        !             3:  */
        !             4: 
        !             5: /***********************************************************************
        !             6:  *                                                                     *
        !             7:  * Copyright (c) David L. Mills 1992-1998                              *
        !             8:  *                                                                     *
        !             9:  * Permission to use, copy, modify, and distribute this software and   *
        !            10:  * its documentation for any purpose and without fee is hereby         *
        !            11:  * granted, provided that the above copyright notice appears in all    *
        !            12:  * copies and that both the copyright notice and this permission       *
        !            13:  * notice appear in supporting documentation, and that the name        *
        !            14:  * University of Delaware not be used in advertising or publicity      *
        !            15:  * pertaining to distribution of the software without specific,        *
        !            16:  * written prior permission. The University of Delaware makes no       *
        !            17:  * representations about the suitability this software for any         *
        !            18:  * purpose. It is provided "as is" without express or implied          *
        !            19:  * warranty.                                                           *
        !            20:  **********************************************************************/
        !            21: 
        !            22: #ifdef HAVE_CONFIG_H
        !            23: #include <config.h>
        !            24: #endif
        !            25: 
        !            26: #if defined(REFCLOCK) && defined(CLOCK_ULINK)
        !            27: 
        !            28: #include <stdio.h>
        !            29: #include <ctype.h>
        !            30: 
        !            31: #include "ntpd.h"
        !            32: #include "ntp_io.h"
        !            33: #include "ntp_refclock.h"
        !            34: #include "ntp_stdlib.h"
        !            35: 
        !            36: /* This driver supports ultralink Model 320,325,330,331,332 WWVB radios
        !            37:  *
        !            38:  * this driver was based on the refclock_wwvb.c driver
        !            39:  * in the ntp distribution.
        !            40:  *
        !            41:  * Fudge Factors
        !            42:  *
        !            43:  * fudge flag1 0 don't poll clock
        !            44:  *             1 send poll character
        !            45:  *
        !            46:  * revision history:
        !            47:  *             99/9/09 j.c.lang        original edit's
        !            48:  *             99/9/11 j.c.lang        changed timecode parse to 
        !            49:  *                                      match what the radio actually
        !            50:  *                                      sends. 
        !            51:  *              99/10/11 j.c.lang       added support for continous
        !            52:  *                                      time code mode (dipsw2)
        !            53:  *             99/11/26 j.c.lang       added support for 320 decoder
        !            54:  *                                      (taken from Dave Strout's
        !            55:  *                                      Model 320 driver)
        !            56:  *             99/11/29 j.c.lang       added fudge flag 1 to control
        !            57:  *                                     clock polling
        !            58:  *             99/12/15 j.c.lang       fixed 320 quality flag
        !            59:  *             01/02/21 s.l.smith      fixed 33x quality flag
        !            60:  *                                     added more debugging stuff
        !            61:  *                                     updated 33x time code explanation
        !            62:  *             04/01/23 frank migge    added support for 325 decoder
        !            63:  *                                      (tested with ULM325.F)
        !            64:  *
        !            65:  * Questions, bugs, ideas send to:
        !            66:  *     Joseph C. Lang
        !            67:  *     tcnojl1@earthlink.net
        !            68:  *
        !            69:  *     Dave Strout
        !            70:  *     dstrout@linuxfoundry.com
        !            71:  *
        !            72:  *      Frank Migge
        !            73:  *      frank.migge@oracle.com
        !            74:  *
        !            75:  *
        !            76:  * on the Ultralink model 33X decoder Dip switch 2 controls
        !            77:  * polled or continous timecode 
        !            78:  * set fudge flag1 if using polled (needed for model 320 and 325)
        !            79:  * dont set fudge flag1 if dip switch 2 is set on model 33x decoder
        !            80: */
        !            81: 
        !            82: 
        !            83: /*
        !            84:  * Interface definitions
        !            85:  */
        !            86: #define        DEVICE          "/dev/wwvb%d" /* device name and unit */
        !            87: #define        SPEED232        B9600   /* uart speed (9600 baud) */
        !            88: #define        PRECISION       (-10)   /* precision assumed (about 10 ms) */
        !            89: #define        REFID           "WWVB"  /* reference ID */
        !            90: #define        DESCRIPTION     "Ultralink WWVB Receiver" /* WRU */
        !            91: 
        !            92: #define        LEN33X          32      /* timecode length Model 33X and 325 */
        !            93: #define LEN320         24      /* timecode length Model 320 */
        !            94: 
        !            95: #define        SIGLCHAR33x     'S'     /* signal strength identifier char 325 */
        !            96: #define        SIGLCHAR325     'R'     /* signal strength identifier char 33x */
        !            97: 
        !            98: /*
        !            99:  *  unit control structure
        !           100:  */
        !           101: struct ulinkunit {
        !           102:        u_char  tcswitch;       /* timecode switch */
        !           103:        l_fp    laststamp;      /* last receive timestamp */
        !           104: };
        !           105: 
        !           106: /*
        !           107:  * Function prototypes
        !           108:  */
        !           109: static int     ulink_start     (int, struct peer *);
        !           110: static void    ulink_shutdown  (int, struct peer *);
        !           111: static void    ulink_receive   (struct recvbuf *);
        !           112: static void    ulink_poll      (int, struct peer *);
        !           113: 
        !           114: /*
        !           115:  * Transfer vector
        !           116:  */
        !           117: struct refclock refclock_ulink = {
        !           118:        ulink_start,            /* start up driver */
        !           119:        ulink_shutdown,         /* shut down driver */
        !           120:        ulink_poll,             /* transmit poll message */
        !           121:        noentry,                /* not used  */
        !           122:        noentry,                /* not used  */
        !           123:        noentry,                /* not used  */
        !           124:        NOFLAGS
        !           125: };
        !           126: 
        !           127: 
        !           128: /*
        !           129:  * ulink_start - open the devices and initialize data for processing
        !           130:  */
        !           131: static int
        !           132: ulink_start(
        !           133:        int unit,
        !           134:        struct peer *peer
        !           135:        )
        !           136: {
        !           137:        register struct ulinkunit *up;
        !           138:        struct refclockproc *pp;
        !           139:        int fd;
        !           140:        char device[20];
        !           141: 
        !           142:        /*
        !           143:         * Open serial port. Use CLK line discipline, if available.
        !           144:         */
        !           145:        (void)sprintf(device, DEVICE, unit);
        !           146:        if (!(fd = refclock_open(device, SPEED232, LDISC_CLK)))
        !           147:                return (0);
        !           148: 
        !           149:        /*
        !           150:         * Allocate and initialize unit structure
        !           151:         */
        !           152:        if (!(up = (struct ulinkunit *)
        !           153:              emalloc(sizeof(struct ulinkunit)))) {
        !           154:                (void) close(fd);
        !           155:                return (0);
        !           156:        }
        !           157:        memset((char *)up, 0, sizeof(struct ulinkunit));
        !           158:        pp = peer->procptr;
        !           159:        pp->unitptr = (caddr_t)up;
        !           160:        pp->io.clock_recv = ulink_receive;
        !           161:        pp->io.srcclock = (caddr_t)peer;
        !           162:        pp->io.datalen = 0;
        !           163:        pp->io.fd = fd;
        !           164:        if (!io_addclock(&pp->io)) {
        !           165:                (void) close(fd);
        !           166:                free(up);
        !           167:                return (0);
        !           168:        }
        !           169: 
        !           170:        /*
        !           171:         * Initialize miscellaneous variables
        !           172:         */
        !           173:        peer->precision = PRECISION;
        !           174:        peer->burst = NSTAGE;
        !           175:        pp->clockdesc = DESCRIPTION;
        !           176:        memcpy((char *)&pp->refid, REFID, 4);
        !           177:        return (1);
        !           178: }
        !           179: 
        !           180: 
        !           181: /*
        !           182:  * ulink_shutdown - shut down the clock
        !           183:  */
        !           184: static void
        !           185: ulink_shutdown(
        !           186:        int unit,
        !           187:        struct peer *peer
        !           188:        )
        !           189: {
        !           190:        register struct ulinkunit *up;
        !           191:        struct refclockproc *pp;
        !           192: 
        !           193:        pp = peer->procptr;
        !           194:        up = (struct ulinkunit *)pp->unitptr;
        !           195:        io_closeclock(&pp->io);
        !           196:        free(up);
        !           197: }
        !           198: 
        !           199: 
        !           200: /*
        !           201:  * ulink_receive - receive data from the serial interface
        !           202:  */
        !           203: static void
        !           204: ulink_receive(
        !           205:        struct recvbuf *rbufp
        !           206:        )
        !           207: {
        !           208:        struct ulinkunit *up;
        !           209:        struct refclockproc *pp;
        !           210:        struct peer *peer;
        !           211: 
        !           212:        l_fp    trtmp;          /* arrival timestamp */
        !           213:        int     quality;        /* quality indicator */
        !           214:        int     temp;           /* int temp */
        !           215:        char    syncchar;       /* synchronization indicator */
        !           216:        char    leapchar;       /* leap indicator */
        !           217:        char    modechar;       /* model 320 mode flag */
        !           218:         char   siglchar;       /* model difference between 33x/325 */
        !           219:        char    char_quality[2];        /* temp quality flag */
        !           220: 
        !           221:        /*
        !           222:         * Initialize pointers and read the timecode and timestamp
        !           223:         */
        !           224:        peer = (struct peer *)rbufp->recv_srcclock;
        !           225:        pp = peer->procptr;
        !           226:        up = (struct ulinkunit *)pp->unitptr;
        !           227:        temp = refclock_gtlin(rbufp, pp->a_lastcode, BMAX, &trtmp);
        !           228: 
        !           229:        /*
        !           230:         * Note we get a buffer and timestamp for both a <cr> and <lf>,
        !           231:         * but only the <cr> timestamp is retained. 
        !           232:         */
        !           233:        if (temp == 0) {
        !           234:                if (up->tcswitch == 0) {
        !           235:                        up->tcswitch = 1;
        !           236:                        up->laststamp = trtmp;
        !           237:                } else
        !           238:                    up->tcswitch = 0;
        !           239:                return;
        !           240:        }
        !           241:        pp->lencode = temp;
        !           242:        pp->lastrec = up->laststamp;
        !           243:        up->laststamp = trtmp;
        !           244:        up->tcswitch = 1;
        !           245: #ifdef DEBUG
        !           246:        if (debug)
        !           247:                printf("ulink: timecode %d %s\n", pp->lencode,
        !           248:                    pp->a_lastcode);
        !           249: #endif
        !           250: 
        !           251:        /*
        !           252:         * We get down to business, check the timecode format and decode
        !           253:         * its contents. If the timecode has invalid length or is not in
        !           254:         * proper format, we declare bad format and exit.
        !           255:         */
        !           256:        syncchar = leapchar = modechar = siglchar = ' ';
        !           257:        switch (pp->lencode ) {
        !           258:                case LEN33X:
        !           259: 
        !           260:                /*
        !           261:                  * First we check if the format is 33x or 325:
        !           262:                 *   <CR><LF>S9+D 00 YYYY+DDDUTCS HH:MM:SSL+5 (33x)
        !           263:                 *   <CR><LF>R5_1C00LYYYY+DDDUTCS HH:MM:SSL+5 (325)
        !           264:                 * simply by comparing if the signal level is 'S' or 'R'
        !           265:                  */
        !           266: 
        !           267:                  if (sscanf(pp->a_lastcode, "%c%*31c",
        !           268:                             &siglchar) == 1) {
        !           269: 
        !           270:                     if(siglchar == SIGLCHAR325) {
        !           271: 
        !           272:                           /*
        !           273:                    * decode for a Model 325 decoder.
        !           274:                    * Timecode format from January 23, 2004 datasheet is:
        !           275:                     *
        !           276:                    *   <CR><LF>R5_1C00LYYYY+DDDUTCS HH:MM:SSL+5
        !           277:                     *
        !           278:                    *   R      WWVB decodersignal readability R1 - R5
        !           279:                    *   5      R1 is unreadable, R5 is best
        !           280:                    *   space  a space (0x20)
        !           281:                    *   1      Data bit 0, 1, M (pos mark), or ? (unknown).
        !           282:                    *   C      Reception from either (C)olorado or (H)awaii 
        !           283:                    *   00     Hours since last good WWVB frame sync. Will 
        !           284:                    *          be 00-99
        !           285:                    *   space  Space char (0x20) or (0xa5) if locked to wwvb
        !           286:                    *   YYYY   Current year, 2000-2099
        !           287:                    *   +      Leap year indicator. '+' if a leap year,
        !           288:                    *          a space (0x20) if not.
        !           289:                    *   DDD    Day of year, 000 - 365.
        !           290:                    *   UTC    Timezone (always 'UTC').
        !           291:                    *   S      Daylight savings indicator
        !           292:                    *             S - standard time (STD) in effect
        !           293:                    *             O - during STD to DST day 0000-2400
        !           294:                    *             D - daylight savings time (DST) in effect
        !           295:                    *             I - during DST to STD day 0000-2400
        !           296:                    *   space  Space character (0x20)
        !           297:                    *   HH     Hours 00-23
        !           298:                    *   :      This is the REAL in sync indicator (: = insync)  
        !           299:                    *   MM     Minutes 00-59
        !           300:                    *   :      : = in sync ? = NOT in sync
        !           301:                    *   SS     Seconds 00-59
        !           302:                    *   L      Leap second flag. Changes from space (0x20)
        !           303:                    *          to 'I' or 'D' during month preceding leap
        !           304:                    *          second adjustment. (I)nsert or (D)elete
        !           305:                    *   +5     UT1 correction (sign + digit ))
        !           306:                    */
        !           307: 
        !           308:                       if (sscanf(pp->a_lastcode, 
        !           309:                           "%*2c %*2c%2c%*c%4d%*c%3d%*4c %2d%c%2d:%2d%c%*2c",
        !           310:                          char_quality, &pp->year, &pp->day, 
        !           311:                           &pp->hour, &syncchar, &pp->minute, &pp->second, 
        !           312:                           &leapchar) == 8) { 
        !           313:                
        !           314:                          if (char_quality[0] == '0') {
        !           315:                                quality = 0;
        !           316:                          } else if (char_quality[0] == '0') {
        !           317:                                quality = (char_quality[1] & 0x0f);
        !           318:                          } else  {
        !           319:                                quality = 99;
        !           320:                          }
        !           321: 
        !           322:                          if (leapchar == 'I' ) leapchar = '+';
        !           323:                          if (leapchar == 'D' ) leapchar = '-';
        !           324: 
        !           325:                          /*
        !           326:                          #ifdef DEBUG
        !           327:                          if (debug) {
        !           328:                             printf("ulink: char_quality %c %c\n", 
        !           329:                                     char_quality[0], char_quality[1]);
        !           330:                             printf("ulink: quality %d\n", quality);
        !           331:                             printf("ulink: syncchar %x\n", syncchar);
        !           332:                             printf("ulink: leapchar %x\n", leapchar);
        !           333:                           }
        !           334:                           #endif
        !           335:                           */
        !           336: 
        !           337:                        }
        !           338:                
        !           339:                     } 
        !           340:                     if(siglchar == SIGLCHAR33x) {
        !           341:                 
        !           342:                   /*
        !           343:                    * We got a Model 33X decoder.
        !           344:                    * Timecode format from January 29, 2001 datasheet is:
        !           345:                    *   <CR><LF>S9+D 00 YYYY+DDDUTCS HH:MM:SSL+5
        !           346:                    *   S      WWVB decoder sync indicator. S for in-sync(?)
        !           347:                    *          or N for noisy signal.
        !           348:                    *   9+     RF signal level in S-units, 0-9 followed by
        !           349:                    *          a space (0x20). The space turns to '+' if the
        !           350:                    *          level is over 9.
        !           351:                    *   D      Data bit 0, 1, 2 (position mark), or
        !           352:                    *          3 (unknown).
        !           353:                    *   space  Space character (0x20)
        !           354:                    *   00     Hours since last good WWVB frame sync. Will 
        !           355:                    *          be 00-23 hrs, or '1d' to '7d'. Will be 'Lk'
        !           356:                     *          if currently in sync. 
        !           357:                    *   space  Space character (0x20)
        !           358:                    *   YYYY   Current year, 1990-2089
        !           359:                    *   +      Leap year indicator. '+' if a leap year,
        !           360:                    *          a space (0x20) if not.
        !           361:                    *   DDD    Day of year, 001 - 366.
        !           362:                    *   UTC    Timezone (always 'UTC').
        !           363:                    *   S      Daylight savings indicator
        !           364:                    *             S - standard time (STD) in effect
        !           365:                    *             O - during STD to DST day 0000-2400
        !           366:                    *             D - daylight savings time (DST) in effect
        !           367:                    *             I - during DST to STD day 0000-2400
        !           368:                    *   space  Space character (0x20)
        !           369:                    *   HH     Hours 00-23
        !           370:                    *   :      This is the REAL in sync indicator (: = insync)  
        !           371:                    *   MM     Minutes 00-59
        !           372:                    *   :      : = in sync ? = NOT in sync
        !           373:                    *   SS     Seconds 00-59
        !           374:                    *   L      Leap second flag. Changes from space (0x20)
        !           375:                    *          to '+' or '-' during month preceding leap
        !           376:                    *          second adjustment.
        !           377:                    *   +5     UT1 correction (sign + digit ))
        !           378:                    */
        !           379: 
        !           380:                       if (sscanf(pp->a_lastcode, 
        !           381:                            "%*4c %2c %4d%*c%3d%*4c %2d%c%2d:%2d%c%*2c",
        !           382:                           char_quality, &pp->year, &pp->day, 
        !           383:                            &pp->hour, &syncchar, &pp->minute, &pp->second, 
        !           384:                            &leapchar) == 8) { 
        !           385:                
        !           386:                           if (char_quality[0] == 'L') {
        !           387:                                quality = 0;
        !           388:                           } else if (char_quality[0] == '0') {
        !           389:                                quality = (char_quality[1] & 0x0f);
        !           390:                           } else  {
        !           391:                                quality = 99;
        !           392:                           }
        !           393:        
        !           394:                            /*
        !           395:                            #ifdef DEBUG
        !           396:                           if (debug) {
        !           397:                                printf("ulink: char_quality %c %c\n", 
        !           398:                                         char_quality[0], char_quality[1]);
        !           399:                                printf("ulink: quality %d\n", quality);
        !           400:                                printf("ulink: syncchar %x\n", syncchar);
        !           401:                                printf("ulink: leapchar %x\n", leapchar);
        !           402:                            }
        !           403:                            #endif
        !           404:                            */
        !           405: 
        !           406:                        }
        !           407:                     }
        !           408:                    break;
        !           409:                }
        !           410: 
        !           411:                case LEN320:
        !           412: 
        !           413:                /*
        !           414:                 * Model 320 Decoder
        !           415:                 * The timecode format is:
        !           416:                 *
        !           417:                 *  <cr><lf>SQRYYYYDDD+HH:MM:SS.mmLT<cr>
        !           418:                 *
        !           419:                 * where:
        !           420:                 *
        !           421:                 * S = 'S' -- sync'd in last hour,
        !           422:                 *     '0'-'9' - hours x 10 since last update,
        !           423:                 *     '?' -- not in sync
        !           424:                 * Q = Number of correlating time-frames, from 0 to 5
        !           425:                 * R = 'R' -- reception in progress,
        !           426:                 *     'N' -- Noisy reception,
        !           427:                 *     ' ' -- standby mode
        !           428:                 * YYYY = year from 1990 to 2089
        !           429:                 * DDD = current day from 1 to 366
        !           430:                 * + = '+' if current year is a leap year, else ' '
        !           431:                 * HH = UTC hour 0 to 23
        !           432:                 * MM = Minutes of current hour from 0 to 59
        !           433:                 * SS = Seconds of current minute from 0 to 59
        !           434:                 * mm = 10's milliseconds of the current second from 00 to 99
        !           435:                 * L  = Leap second pending at end of month
        !           436:                 *     'I' = insert, 'D'= delete
        !           437:                 * T  = DST <-> STD transition indicators
        !           438:                 *
        !           439:                 */
        !           440: 
        !           441:                if (sscanf(pp->a_lastcode, "%c%1d%c%4d%3d%*c%2d:%2d:%2d.%2ld%c",
        !           442:                       &syncchar, &quality, &modechar, &pp->year, &pp->day,
        !           443:                       &pp->hour, &pp->minute, &pp->second,
        !           444:                        &pp->nsec, &leapchar) == 10) {
        !           445:                pp->nsec *= 10000000; /* M320 returns 10's of msecs */
        !           446:                if (leapchar == 'I' ) leapchar = '+';
        !           447:                if (leapchar == 'D' ) leapchar = '-';
        !           448:                if (syncchar != '?' ) syncchar = ':';
        !           449: 
        !           450:                break;
        !           451:                }
        !           452: 
        !           453:                default:
        !           454:                refclock_report(peer, CEVNT_BADREPLY);
        !           455:                return;
        !           456:        }
        !           457: 
        !           458:        /*
        !           459:         * Decode quality indicator
        !           460:         * For the 325 & 33x series, the lower the number the "better" 
        !           461:         * the time is. I used the dispersion as the measure of time 
        !           462:         * quality. The quality indicator in the 320 is the number of 
        !           463:         * correlating time frames (the more the better)
        !           464:         */
        !           465: 
        !           466:        /* 
        !           467:         * The spec sheet for the 325 & 33x series states the clock will
        !           468:         * maintain +/-0.002 seconds accuracy when locked to WWVB. This 
        !           469:         * is indicated by 'Lk' in the quality portion of the incoming 
        !           470:         * string. When not in lock, a drift of +/-0.015 seconds should 
        !           471:         * be allowed for.
        !           472:         * With the quality indicator decoding scheme above, the 'Lk' 
        !           473:         * condition will produce a quality value of 0. If the quality 
        !           474:         * indicator starts with '0' then the second character is the 
        !           475:         * number of hours since we were last locked. If the first 
        !           476:         * character is anything other than 'L' or '0' then we have been 
        !           477:         * out of lock for more than 9 hours so we assume the worst and 
        !           478:         * force a quality value that selects the 'default' maximum 
        !           479:         * dispersion. The dispersion values below are what came with the
        !           480:         * driver. They're not unreasonable so they've not been changed.
        !           481:         */
        !           482: 
        !           483:        if (pp->lencode == LEN33X) {
        !           484:                switch (quality) {
        !           485:                        case 0 :
        !           486:                                pp->disp=.002;
        !           487:                                break;
        !           488:                        case 1 :
        !           489:                                pp->disp=.02;
        !           490:                                break;
        !           491:                        case 2 :
        !           492:                                pp->disp=.04;
        !           493:                                break;
        !           494:                        case 3 :
        !           495:                                pp->disp=.08;
        !           496:                                break;
        !           497:                        default:
        !           498:                                pp->disp=MAXDISPERSE;
        !           499:                                break;
        !           500:                }
        !           501:        } else {
        !           502:                switch (quality) {
        !           503:                        case 5 :
        !           504:                                pp->disp=.002;
        !           505:                                break;
        !           506:                        case 4 :
        !           507:                                pp->disp=.02;
        !           508:                                break;
        !           509:                        case 3 :
        !           510:                                pp->disp=.04;
        !           511:                                break;
        !           512:                        case 2 :
        !           513:                                pp->disp=.08;
        !           514:                                break;
        !           515:                        case 1 :
        !           516:                                pp->disp=.16;
        !           517:                                break;
        !           518:                        default:
        !           519:                                pp->disp=MAXDISPERSE;
        !           520:                                break;
        !           521:                }
        !           522: 
        !           523:        }
        !           524: 
        !           525:        /*
        !           526:         * Decode synchronization, and leap characters. If
        !           527:         * unsynchronized, set the leap bits accordingly and exit.
        !           528:         * Otherwise, set the leap bits according to the leap character.
        !           529:         */
        !           530: 
        !           531:        if (syncchar != ':')
        !           532:                pp->leap = LEAP_NOTINSYNC;
        !           533:        else if (leapchar == '+')
        !           534:                pp->leap = LEAP_ADDSECOND;
        !           535:        else if (leapchar == '-')
        !           536:                pp->leap = LEAP_DELSECOND;
        !           537:        else
        !           538:                pp->leap = LEAP_NOWARNING;
        !           539: 
        !           540:        /*
        !           541:         * Process the new sample in the median filter and determine the
        !           542:         * timecode timestamp.
        !           543:         */
        !           544:        if (!refclock_process(pp)) {
        !           545:                refclock_report(peer, CEVNT_BADTIME);
        !           546:        }
        !           547: 
        !           548: }
        !           549: 
        !           550: /*
        !           551:  * ulink_poll - called by the transmit procedure
        !           552:  */
        !           553: 
        !           554: static void
        !           555: ulink_poll(
        !           556:        int unit,
        !           557:        struct peer *peer
        !           558:        )
        !           559: {
        !           560:         struct refclockproc *pp;
        !           561:         char pollchar;
        !           562: 
        !           563:         pp = peer->procptr;
        !           564:         pollchar = 'T';
        !           565:        if (pp->sloppyclockflag & CLK_FLAG1) {
        !           566:                if (write(pp->io.fd, &pollchar, 1) != 1)
        !           567:                        refclock_report(peer, CEVNT_FAULT);
        !           568:                else
        !           569:                    pp->polls++;
        !           570:        }
        !           571:        else
        !           572:                    pp->polls++;
        !           573: 
        !           574:         if (peer->burst > 0)
        !           575:                 return;
        !           576:         if (pp->coderecv == pp->codeproc) {
        !           577:                 refclock_report(peer, CEVNT_TIMEOUT);
        !           578:                 return;
        !           579:         }
        !           580:         pp->lastref = pp->lastrec;
        !           581:        refclock_receive(peer);
        !           582:        record_clock_stats(&peer->srcadr, pp->a_lastcode);
        !           583:         peer->burst = NSTAGE;
        !           584: 
        !           585: }
        !           586: 
        !           587: #else
        !           588: int refclock_ulink_bs;
        !           589: #endif /* REFCLOCK */

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