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

1.1     ! misho       1: /* refclock_bancomm.c - clock driver for the  Datum/Bancomm bc635VME 
        !             2:  * Time and Frequency Processor. It requires the BANCOMM bc635VME/
        !             3:  * bc350VXI Time and Frequency Processor Module Driver for SunOS4.x 
        !             4:  * and SunOS5.x UNIX Systems. It has been tested on a UltraSparc 
        !             5:  * IIi-cEngine running Solaris 2.6.
        !             6:  * 
        !             7:  * Author(s):  Ganesh Ramasivan & Gary Cliff, Computing Devices Canada,
        !             8:  *             Ottawa, Canada
        !             9:  *
        !            10:  * Date:       July 1999
        !            11:  *
        !            12:  * Note(s):    The refclock type has been defined as 16.
        !            13:  *
        !            14:  *             This program has been modelled after the Bancomm driver
        !            15:  *             originally written by R. Schmidt of Time Service, U.S. 
        !            16:  *             Naval Observatory for a HP-UX machine. Since the original
        !            17:  *             authors no longer plan to maintain this code, all 
        !            18:  *             references to the HP-UX vme2 driver subsystem bave been
        !            19:  *             removed. Functions vme_report_event(), vme_receive(), 
        !            20:  *             vme_control() and vme_buginfo() have been deleted because
        !            21:  *             they are no longer being used.
        !            22:  *
        !            23:  *     04/28/2005 Rob Neal 
        !            24:  *             Modified to add support for Symmetricom bc637PCI-U Time & 
        !            25:  *             Frequency Processor. 
        !            26:  *     2/21/2007 Ali Ghorashi
        !            27:  *             Modified to add support for Symmetricom bc637PCI-U Time & 
        !            28:  *             Frequency Processor on Solaris.
        !            29:  *             Tested on Solaris 10 with a bc635 card.
        !            30:  *
        !            31:  *             Card bus type (VME/VXI or PCI) and environment are specified via the
        !            32:  *             "mode" keyword on the server command in ntp.conf.
        !            33:  *             server 127.127.16.u prefer mode M
        !            34:  *             where u is the id (usually 0) of the entry in /dev (/dev/stfp0)
        !            35:  *     
        !            36:  *             and M is one of the following modes: 
        !            37:  *             1               : FreeBSD PCI 635/637.
        !            38:  *             2               : Linux or Windows PCI 635/637.
        !            39:  *             3               : Solaris PCI 635/637
        !            40:  *             not specified, or other number: 
        !            41:  *                             : Assumed to be VME/VXI legacy Bancomm card on Solaris.
        !            42:  *             Linux and Windows platforms require Symmetricoms' proprietary driver
        !            43:  *             for the TFP card.
        !            44:  *             Solaris requires Symmetricom's driver and its header file (freely distributed) to 
        !            45:  *             be installed and running.
        !            46:  */
        !            47: 
        !            48: #ifdef HAVE_CONFIG_H
        !            49: #include <config.h>
        !            50: #endif
        !            51: 
        !            52: #if defined(REFCLOCK) && defined(CLOCK_BANC) 
        !            53: 
        !            54: #include "ntpd.h"
        !            55: #include "ntp_io.h"
        !            56: #include "ntp_refclock.h"
        !            57: #include "ntp_unixtime.h"
        !            58: #include "ntp_stdlib.h"
        !            59: 
        !            60: #include <stdio.h>
        !            61: #include <syslog.h>
        !            62: #include <ctype.h>
        !            63: 
        !            64: struct btfp_time                /* Structure for reading 5 time words   */
        !            65:                                 /* in one ioctl(2) operation.           */
        !            66: {
        !            67:        unsigned short btfp_time[5];  /* Time words 0,1,2,3, and 4. (16bit)*/
        !            68: };
        !            69: /* SunOS5 ioctl commands definitions.*/
        !            70: #define BTFPIOC            ( 'b'<< 8 )
        !            71: #define IOCIO( l, n )      ( BTFPIOC | n )
        !            72: #define IOCIOR( l, n, s )  ( BTFPIOC | n )
        !            73: #define IOCIORN( l, n, s ) ( BTFPIOC | n )
        !            74: #define IOCIOWN( l, n, s ) ( BTFPIOC | n )
        !            75: 
        !            76: /***** Simple ioctl commands *****/
        !            77: #define RUNLOCK        IOCIOR(b, 19, int )  /* Release Capture Lockout */
        !            78: #define RCR0           IOCIOR(b, 22, int )  /* Read control register zero.*/
        !            79: #define        WCR0            IOCIOWN(b, 23, int)          /* Write control register zero*/
        !            80: /***** Compound ioctl commands *****/
        !            81: 
        !            82: /* Read all 5 time words in one call.   */
        !            83: #define READTIME       IOCIORN(b, 32, sizeof( struct btfp_time ))
        !            84: 
        !            85: #if defined(__FreeBSD__) 
        !            86: #undef  READTIME
        !            87: #define READTIME       _IOR('u', 5, struct btfp_time )
        !            88: #endif 
        !            89: 
        !            90: /* Solaris specific section */
        !            91: struct stfp_tm {
        !            92:        int32_t tm_sec; 
        !            93:        int32_t tm_min;
        !            94:        int32_t tm_hour;
        !            95:        int32_t tm_mday;
        !            96:        int32_t tm_mon;
        !            97:        int32_t tm_year;
        !            98:        int32_t tm_wday;
        !            99:        int32_t tm_yday;
        !           100:        int32_t tm_isdst;
        !           101: };
        !           102: 
        !           103: struct stfp_time {
        !           104:        struct stfp_tm  tm;
        !           105:        int32_t         usec;                   /* usec 0 - 999999 */
        !           106:        int32_t         hnsec;                  /* hnsec 0 - 9 (hundreds of nsecs) */
        !           107:        int32_t         status;
        !           108: };
        !           109: 
        !           110: #define SELTIMEFORMAT  2       
        !           111: #      define TIME_DECIMAL 0
        !           112: #      define TIME_BINARY      1
        !           113: 
        !           114: #if defined(__sun__)
        !           115: #undef READTIME
        !           116: #define READTIME               9
        !           117: #endif /** __sun___ **/
        !           118: /* end solaris specific section */
        !           119: 
        !           120: struct vmedate {                          /* structure returned by get_vmetime.c */
        !           121:        unsigned short year;
        !           122:        unsigned short day;
        !           123:        unsigned short hr;
        !           124:        unsigned short mn;
        !           125:        unsigned short sec;
        !           126:        long frac;
        !           127:        unsigned short status;
        !           128: };
        !           129: 
        !           130: typedef void *SYMMT_PCI_HANDLE;
        !           131: 
        !           132: /*
        !           133:  * VME interface parameters. 
        !           134:  */
        !           135: #define VMEPRECISION    (-21)   /* precision assumed (1 us) */
        !           136: #define USNOREFID       "BTFP"  /* or whatever */
        !           137: #define VMEREFID        "BTFP"  /* reference id */
        !           138: #define VMEDESCRIPTION  "Bancomm bc635 TFP" /* who we are */
        !           139: #define VMEHSREFID      0x7f7f1000 /* 127.127.16.00 refid hi strata */
        !           140: /* clock type 16 is used here  */
        !           141: #define GMT            0       /* hour offset from Greenwich */
        !           142: 
        !           143: /*
        !           144:  * Imported from ntp_timer module
        !           145:  */
        !           146: extern u_long current_time;     /* current time(s) */
        !           147: 
        !           148: /*
        !           149:  * Imported from ntpd module
        !           150:  */
        !           151: extern volatile int debug;               /* global debug flag */
        !           152: 
        !           153: /*
        !           154:  * VME unit control structure.
        !           155:  * Changes made to vmeunit structure. Most members are now available in the 
        !           156:  * new refclockproc structure in ntp_refclock.h - 07/99 - Ganesh Ramasivan
        !           157:  */
        !           158: struct vmeunit {
        !           159:        struct vmedate vmedata; /* data returned from vme read */
        !           160:        u_long lasttime;        /* last time clock heard from */
        !           161: };
        !           162: 
        !           163: /*
        !           164:  * Function prototypes
        !           165:  */
        !           166: static  int     vme_start       (int, struct peer *);
        !           167: static  void    vme_shutdown    (int, struct peer *);
        !           168: static  void    vme_receive     (struct recvbuf *);
        !           169: static  void    vme_poll        (int unit, struct peer *);
        !           170: struct vmedate *get_datumtime(struct vmedate *);       
        !           171: void   tvme_fill(struct vmedate *, uint32_t btm[2]);
        !           172: void   stfp_time2tvme(struct vmedate *time_vme, struct stfp_time *stfp);
        !           173: inline const char *DEVICE_NAME(int n);
        !           174: 
        !           175: 
        !           176: /*
        !           177:  * Define the bc*() functions as weak so we can compile/link without them.
        !           178:  * Only clients with the card will have the proprietary vendor device driver
        !           179:  * and interface library needed for use on Linux/Windows platforms.
        !           180:  */
        !           181: extern uint32_t __attribute__ ((weak)) bcReadBinTime(SYMMT_PCI_HANDLE, uint32_t *, uint32_t*, uint8_t*);
        !           182: extern SYMMT_PCI_HANDLE __attribute__ ((weak)) bcStartPci(void);
        !           183: extern void __attribute__ ((weak)) bcStopPci(SYMMT_PCI_HANDLE);
        !           184: 
        !           185: /*
        !           186:  * Transfer vector
        !           187:  */
        !           188: struct  refclock refclock_bancomm = {
        !           189:        vme_start,              /* start up driver */
        !           190:        vme_shutdown,           /* shut down driver */
        !           191:        vme_poll,               /* transmit poll message */
        !           192:        noentry,                /* not used (old vme_control) */
        !           193:        noentry,                /* initialize driver */ 
        !           194:        noentry,                /* not used (old vme_buginfo) */ 
        !           195:        NOFLAGS                 /* not used */
        !           196: };
        !           197: 
        !           198: int fd_vme;  /* file descriptor for ioctls */
        !           199: int regvalue;
        !           200: int tfp_type;  /* mode selector, indicate platform and driver interface */
        !           201: SYMMT_PCI_HANDLE stfp_handle;
        !           202: 
        !           203: /** 
        !           204:  * this macro returns the device name based on
        !           205:  * the platform we are running on and the device number
        !           206:  */
        !           207: #if defined(__sun__)
        !           208: inline const char *DEVICE_NAME(int n) {static char s[20]={0}; snprintf(s,19,"/dev/stfp%d",n);return s;}
        !           209: #else
        !           210: inline const char* DEVICE_NAME(int n) {static char s[20]={0}; snprintf(s,19,"/dev/btfp%d",n);return s;}
        !           211: #endif /**__sun__**/
        !           212: 
        !           213: /*
        !           214:  * vme_start - open the VME device and initialize data for processing
        !           215:  */
        !           216: static int
        !           217: vme_start(
        !           218:        int unit,
        !           219:        struct peer *peer
        !           220:        )
        !           221: {
        !           222:        register struct vmeunit *vme;
        !           223:        struct refclockproc *pp;
        !           224:        int dummy;
        !           225:        char vmedev[20];
        !           226:        
        !           227:        tfp_type = (int)(peer->ttl);
        !           228:        switch (tfp_type) {             
        !           229:                case 1:
        !           230:                case 3:
        !           231:                        break;
        !           232:                case 2:
        !           233:                        stfp_handle = bcStartPci();     /* init the card in lin/win */
        !           234:                        break;
        !           235:                default:
        !           236:                        break;
        !           237:        }
        !           238:        /*
        !           239:         * Open VME device
        !           240:         */
        !           241: #ifdef DEBUG
        !           242: 
        !           243:        printf("Opening DATUM DEVICE %s\n",DEVICE_NAME(peer->refclkunit));
        !           244: #endif
        !           245:        if ( (fd_vme = open(DEVICE_NAME(peer->refclkunit), O_RDWR)) < 0) {
        !           246:                msyslog(LOG_ERR, "vme_start: failed open of %s: %m", vmedev);
        !           247:                return (0);
        !           248:        }
        !           249:        else  { 
        !           250:                switch (tfp_type) {
        !           251:                        case 1: break;
        !           252:                        case 2: break;
        !           253:                        case 3:break;
        !           254:                        default: 
        !           255:                                /* Release capture lockout in case it was set before. */
        !           256:                                if( ioctl( fd_vme, RUNLOCK, &dummy ) )
        !           257:                                msyslog(LOG_ERR, "vme_start: RUNLOCK failed %m");
        !           258: 
        !           259:                                regvalue = 0; /* More esoteric stuff to do... */
        !           260:                                if( ioctl( fd_vme, WCR0, &regvalue ) )
        !           261:                                msyslog(LOG_ERR, "vme_start: WCR0 failed %m");
        !           262:                                break;
        !           263:                }
        !           264:        }
        !           265: 
        !           266:        /*
        !           267:         * Allocate unit structure
        !           268:         */
        !           269:        vme = (struct vmeunit *)emalloc(sizeof(struct vmeunit));
        !           270:        bzero((char *)vme, sizeof(struct vmeunit));
        !           271: 
        !           272: 
        !           273:        /*
        !           274:         * Set up the structures
        !           275:         */
        !           276:        pp = peer->procptr;
        !           277:        pp->unitptr = (caddr_t) vme;
        !           278:        pp->timestarted = current_time;
        !           279: 
        !           280:        pp->io.clock_recv = vme_receive;
        !           281:        pp->io.srcclock = (caddr_t)peer;
        !           282:        pp->io.datalen = 0;
        !           283:        pp->io.fd = fd_vme;
        !           284: 
        !           285:        /*
        !           286:         * All done.  Initialize a few random peer variables, then
        !           287:         * return success. Note that root delay and root dispersion are
        !           288:         * always zero for this clock.
        !           289:         */
        !           290:        peer->precision = VMEPRECISION;
        !           291:        memcpy(&pp->refid, USNOREFID,4);
        !           292:        return (1);
        !           293: }
        !           294: 
        !           295: 
        !           296: /*
        !           297:  * vme_shutdown - shut down a VME clock
        !           298:  */
        !           299: static void
        !           300: vme_shutdown(
        !           301:        int unit, 
        !           302:        struct peer *peer
        !           303:        )
        !           304: {
        !           305:        register struct vmeunit *vme;
        !           306:        struct refclockproc *pp;
        !           307: 
        !           308:        /*
        !           309:         * Tell the I/O module to turn us off.  We're history.
        !           310:         */
        !           311:        pp = peer->procptr;
        !           312:        vme = (struct vmeunit *)pp->unitptr;
        !           313:        io_closeclock(&pp->io);
        !           314:        pp->unitptr = NULL;
        !           315:        if (NULL != vme)
        !           316:                free(vme);
        !           317:        if (tfp_type == 2)
        !           318:                bcStopPci(stfp_handle); 
        !           319: }
        !           320: 
        !           321: 
        !           322: /*
        !           323:  * vme_receive - receive data from the VME device.
        !           324:  *
        !           325:  * Note: This interface would be interrupt-driven. We don't use that
        !           326:  * now, but include a dummy routine for possible future adventures.
        !           327:  */
        !           328: static void
        !           329: vme_receive(
        !           330:        struct recvbuf *rbufp
        !           331:        )
        !           332: {
        !           333: }
        !           334: 
        !           335: 
        !           336: /*
        !           337:  * vme_poll - called by the transmit procedure
        !           338:  */
        !           339: static void
        !           340: vme_poll(
        !           341:        int unit,
        !           342:        struct peer *peer
        !           343:        )
        !           344: {
        !           345:        struct vmedate *tptr; 
        !           346:        struct vmeunit *vme;
        !           347:        struct refclockproc *pp;
        !           348:        time_t tloc;
        !           349:        struct tm *tadr;
        !           350:         
        !           351:        pp = peer->procptr;      
        !           352:        vme = (struct vmeunit *)pp->unitptr;        /* Here is the structure */
        !           353: 
        !           354:        tptr = &vme->vmedata; 
        !           355:        if ((tptr = get_datumtime(tptr)) == NULL ) {
        !           356:                refclock_report(peer, CEVNT_BADREPLY);
        !           357:                return;
        !           358:        }
        !           359: 
        !           360:        get_systime(&pp->lastrec);
        !           361:        pp->polls++;
        !           362:        vme->lasttime = current_time;
        !           363: 
        !           364:        /*
        !           365:         * Get VME time and convert to timestamp format. 
        !           366:         * The year must come from the system clock.
        !           367:         */
        !           368:        
        !           369:          time(&tloc);
        !           370:          tadr = gmtime(&tloc);
        !           371:          tptr->year = (unsigned short)(tadr->tm_year + 1900);
        !           372: 
        !           373:        snprintf(pp->a_lastcode,
        !           374:                 sizeof(pp->a_lastcode),
        !           375:                 "%3.3d %2.2d:%2.2d:%2.2d.%.6ld %1d",
        !           376:                 tptr->day, 
        !           377:                 tptr->hr, 
        !           378:                 tptr->mn,
        !           379:                 tptr->sec, 
        !           380:                 tptr->frac, 
        !           381:                 tptr->status);
        !           382: 
        !           383:        pp->lencode = (u_short) strlen(pp->a_lastcode);
        !           384: 
        !           385:        pp->day =  tptr->day;
        !           386:        pp->hour =   tptr->hr;
        !           387:        pp->minute =  tptr->mn;
        !           388:        pp->second =  tptr->sec;
        !           389:        pp->nsec =   tptr->frac;        
        !           390: 
        !           391: #ifdef DEBUG
        !           392:        if (debug)
        !           393:            printf("pp: %3d %02d:%02d:%02d.%06ld %1x\n",
        !           394:                   pp->day, pp->hour, pp->minute, pp->second,
        !           395:                   pp->nsec, tptr->status);
        !           396: #endif
        !           397:        if (tptr->status ) {       /*  Status 0 is locked to ref., 1 is not */
        !           398:                refclock_report(peer, CEVNT_BADREPLY);
        !           399:                return;
        !           400:        }
        !           401: 
        !           402:        /*
        !           403:         * Now, compute the reference time value. Use the heavy
        !           404:         * machinery for the seconds and the millisecond field for the
        !           405:         * fraction when present. If an error in conversion to internal
        !           406:         * format is found, the program declares bad data and exits.
        !           407:         * Note that this code does not yet know how to do the years and
        !           408:         * relies on the clock-calendar chip for sanity.
        !           409:         */
        !           410:        if (!refclock_process(pp)) {
        !           411:                refclock_report(peer, CEVNT_BADTIME);
        !           412:                return;
        !           413:        }
        !           414:        pp->lastref = pp->lastrec;
        !           415:        refclock_receive(peer);
        !           416:        record_clock_stats(&peer->srcadr, pp->a_lastcode);
        !           417: }
        !           418: 
        !           419: struct vmedate *
        !           420: get_datumtime(struct vmedate *time_vme)
        !           421: {
        !           422:        char cbuf[7];
        !           423:        struct btfp_time vts;
        !           424:        uint32_t btm[2];
        !           425:        uint8_t dmy;
        !           426:        struct stfp_time stfpm;
        !           427:        
        !           428:        if (time_vme == NULL)
        !           429:                time_vme = emalloc(sizeof(*time_vme));
        !           430: 
        !           431:        switch (tfp_type) {
        !           432:                case 1:                         /* BSD, PCI, 2 32bit time words */
        !           433:                        if (ioctl(fd_vme, READTIME, &btm)) {
        !           434:                        msyslog(LOG_ERR, "get_bc63x error: %m");
        !           435:                                return(NULL);
        !           436:                        }
        !           437:                        tvme_fill(time_vme, btm);
        !           438:                        break;
        !           439: 
        !           440:                case 2:                         /* Linux/Windows, PCI, 2 32bit time words */
        !           441:                        if (bcReadBinTime(stfp_handle, &btm[1], &btm[0], &dmy) == 0) {
        !           442:                        msyslog(LOG_ERR, "get_datumtime error: %m"); 
        !           443:                                return(NULL);
        !           444:                        }
        !           445:                        tvme_fill(time_vme, btm);
        !           446:                        break;
        !           447:                        
        !           448:                case 3: /** solaris **/
        !           449:                        memset(&stfpm,0,sizeof(stfpm));
        !           450:                        
        !           451:                        /* we need the time in decimal format */
        !           452:                        /* Here we rudely assume that we are the only user of the driver.
        !           453:                         * Other programs will have to set their own time format before reading 
        !           454:                         * the time.
        !           455:                         */
        !           456:                        if(ioctl (fd_vme, SELTIMEFORMAT, TIME_DECIMAL)){        
        !           457:                                        msyslog(LOG_ERR, "Could not set time format\n");
        !           458:                                        return (NULL);  
        !           459:                        }
        !           460:                        /* read the time */
        !           461:                        if (ioctl(fd_vme, READTIME, &stfpm)) {
        !           462:                                msyslog(LOG_ERR, "ioctl error: %m");
        !           463:                                return(NULL);
        !           464:                        }
        !           465:                        stfp_time2tvme(time_vme,  &stfpm);
        !           466:                        break;                  
        !           467: 
        !           468:                default:                        /* legacy bancomm card */
        !           469: 
        !           470:                        if (ioctl(fd_vme, READTIME, &vts)) {
        !           471:                                msyslog(LOG_ERR,
        !           472:                                        "get_datumtime error: %m");
        !           473:                                return(NULL);
        !           474:                        }
        !           475:                        /* Get day */
        !           476:                        snprintf(cbuf, sizeof(cbuf), "%3.3x",
        !           477:                                 ((vts.btfp_time[ 0 ] & 0x000f) << 8) +
        !           478:                                  ((vts.btfp_time[ 1 ] & 0xff00) >> 8));  
        !           479:                        time_vme->day = (unsigned short)atoi(cbuf);
        !           480: 
        !           481:                        /* Get hour */
        !           482:                        snprintf(cbuf, sizeof(cbuf), "%2.2x",
        !           483:                                 vts.btfp_time[ 1 ] & 0x00ff);
        !           484:                        time_vme->hr = (unsigned short)atoi(cbuf);
        !           485: 
        !           486:                        /* Get minutes */
        !           487:                        snprintf(cbuf, sizeof(cbuf), "%2.2x",
        !           488:                                 (vts.btfp_time[ 2 ] & 0xff00) >> 8);
        !           489:                        time_vme->mn = (unsigned short)atoi(cbuf);
        !           490: 
        !           491:                        /* Get seconds */
        !           492:                        snprintf(cbuf, sizeof(cbuf), "%2.2x",
        !           493:                                 vts.btfp_time[ 2 ] & 0x00ff);
        !           494:                        time_vme->sec = (unsigned short)atoi(cbuf);
        !           495: 
        !           496:                        /* Get microseconds.  Yes, we ignore the 0.1 microsecond digit so
        !           497:                                 we can use the TVTOTSF function  later on...*/
        !           498: 
        !           499:                        snprintf(cbuf, sizeof(cbuf), "%4.4x%2.2x",
        !           500:                                 vts.btfp_time[ 3 ],
        !           501:                                 vts.btfp_time[ 4 ] >> 8);
        !           502:                        time_vme->frac = (u_long) atoi(cbuf);
        !           503: 
        !           504:                        /* Get status bit */
        !           505:                        time_vme->status = (vts.btfp_time[0] & 0x0010) >> 4;
        !           506: 
        !           507:                        break;
        !           508:        }
        !           509: 
        !           510:        if (time_vme->status) 
        !           511:                return ((void *)NULL);
        !           512:        else
        !           513:            return (time_vme);
        !           514: }
        !           515: /* Assign values to time_vme struct. Mostly for readability */
        !           516: void
        !           517: tvme_fill(struct vmedate *time_vme, uint32_t btm[2])
        !           518: {
        !           519:        struct tm maj;
        !           520:        uint32_t dmaj, dmin;
        !           521: 
        !           522:        dmaj = btm[1];                  /* syntax sugar */
        !           523:        dmin = btm[0];
        !           524: 
        !           525:        gmtime_r(&dmaj, &maj);
        !           526:        time_vme->day  = maj.tm_yday+1;
        !           527:        time_vme->hr   = maj.tm_hour;
        !           528:        time_vme->mn   = maj.tm_min;
        !           529:        time_vme->sec  = maj.tm_sec;
        !           530:        time_vme->frac = (dmin & 0x000fffff) * 1000; 
        !           531:        time_vme->frac += ((dmin & 0x00f00000) >> 20) * 100;
        !           532:        time_vme->status = (dmin & 0x01000000) >> 24;
        !           533:        return;
        !           534: }
        !           535: 
        !           536: 
        !           537: /* Assign values to time_vme struct. Mostly for readability */
        !           538: void
        !           539: stfp_time2tvme(struct vmedate *time_vme, struct stfp_time *stfp)
        !           540: {
        !           541: 
        !           542:        time_vme->day  = stfp->tm.tm_yday+1;
        !           543:        time_vme->hr   = stfp->tm.tm_hour;
        !           544:        time_vme->mn   = stfp->tm.tm_min;
        !           545:        time_vme->sec  = stfp->tm.tm_sec;
        !           546:        time_vme->frac = stfp->usec*1000;  
        !           547:        time_vme->frac += stfp->hnsec * 100;
        !           548:        time_vme->status = stfp->status;
        !           549:        return;
        !           550: }
        !           551: #else
        !           552: int refclock_bancomm_bs;
        !           553: #endif /* REFCLOCK */

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