diff --git a/src/db/drvTS.c b/src/db/drvTS.c index cc3c85905..48054baf5 100644 --- a/src/db/drvTS.c +++ b/src/db/drvTS.c @@ -66,17 +66,12 @@ /* functions used by this driver */ static long TSgetUnixTime(struct timespec*); +static long TSinitClockFromUnix(void); static long TSgetMasterTime(struct timespec*); -static long TSgetBroadcastAddr(int soc, struct sockaddr*); -static int TSgetSocket(int port, struct sockaddr_in* sin); -static int TSgetBroadcastSocket(int port, struct sockaddr_in* sin); static void TSsyncServer(); static void TSsyncClient(); static long TSasyncClient(); static long TSsyncTheTime(struct timespec* cts, struct timespec* ts); -static long TSgetData(char* buf, int buf_size, int soc, - struct sockaddr* to_sin, struct sockaddr* from_sin, - struct timespec* round_trip); static void TSaddStamp( struct timespec* result, struct timespec* op1, struct timespec* op2); static void TSwdIncTime(); @@ -96,6 +91,14 @@ static long TSstartSyncClient(); static long TSstartAsyncClient(); static long TSstartStampServer(); static long TSuserGetJunk(int event_number,struct timespec* sp); +/* network utilities*/ +static long TSgetBroadcastAddr(int soc, struct sockaddr*); +static int TSgetNtpSocketAddr(struct sockaddr_in *sin); +static int TSgetSocket(int port, struct sockaddr_in* sin); +static int TSgetBroadcastSocket(int port, struct sockaddr_in* sin); +static long TSgetData(char* buf, int buf_size, int soc, + struct sockaddr* to_sin, struct sockaddr* from_sin, + struct timespec* round_trip); /* event system and time clock functions */ static long (*TSregisterEventHandler)(int Card, void(*func)()); @@ -134,7 +137,8 @@ TSinfo TSdata = 0,NULL, TS_SYNC_RATE_SEC,TS_CLOCK_RATE_HZ,0,TS_TIME_OUT_MS,0, TS_MASTER_PORT,TS_SLAVE_PORT,1,0,0,0,0, - NULL, {NULL}, {NULL} + NULL, {NULL}, {NULL}, + 0,0,10 }; extern char* sysBootLine; @@ -175,6 +179,7 @@ unsigned long TSepochNtpToUnix(struct timespec* ts) unsigned long nfssecs = (unsigned long)ts->tv_sec; unsigned long secs = 0; + if(!TSinitialized) TSinit(); /*If high order bit is not set then nfssecs has overflowed */ if(!(nfssecs & 0x80000000ul)) { /*secs = nfssecs - TS_1900_TO_VXWORKS_EPOCH + 2**32 */ @@ -281,6 +286,10 @@ long TSreport() if(TSdata.has_direct_time) printf("Event system has time directly available\n"); + printf("syncReportThreshold %lu milliseconds\n", + TSdata.syncReportThreshold); + printf("syncUnixReportThreshold %lu milliseconds\n", + TSdata.syncUnixReportThreshold); return 0; } @@ -586,7 +595,7 @@ long TSinit(void) if(TSdata.master_timing_IOC) { /* master */ - if(TSsetClockFromUnix()<0) + if(TSinitClockFromUnix()<0) { /* bad, cannot get time - accessing starts ticking */ struct timespec tp; @@ -620,7 +629,7 @@ long TSinit(void) else { /* slave */ - if(TSsetClockFromUnix()<0) + if(TSinitClockFromUnix()<0) { struct timespec tp; clock_gettime(CLOCK_REALTIME,&tp); @@ -747,14 +756,13 @@ static void TSwdIncTime() /*increment the time stamp at a 60 Hz rate*/ return; } +/* TSwdIncTimeSync called at interrupt level! */ static void TSwdIncTimeSync() { wdStart(wd,1, (FUNCPTR)TSwdIncTimeSync,NULL); TSaccurateTimeStamp(&TSdata.event_table[0]); } -/* following are all interrupt service routines */ - /* TSeventHandler() - receive events from event system; update the event table @@ -778,6 +786,7 @@ static void TSeventHandler(int Card,int EventNum,unsigned long Ticks) } #endif + /* calculate a time stamp from the Tick count */ ts.tv_sec = Ticks / TSdata.clock_hz; ts.tv_nsec = (Ticks - (ts.tv_sec * TSdata.clock_hz)) * TSdata.clock_conv; @@ -855,38 +864,18 @@ static void TSerrorHandler(int Card, int ErrorNum) static long TSgetUnixTime(struct timespec* ts) { - BOOT_PARAMS bootParms; unsigned long buf_data,timeValue; TS_NTP buf_ntp; struct sockaddr_in sin; int soc; - char host_addr[BOOT_ADDR_LEN]; - int status; - Debug0(2,"in TSgetUnixTime()\n"); - if(envGetConfigParam(&EPICS_TS_NTP_INET,BOOT_ADDR_LEN,host_addr)==NULL || - strlen(host_addr)==0) - { - /* use boot host if the environment variable not set */ - bootStringToStruct(sysBootLine,&bootParms); - /* bootParms.had = host IP address */ - strncpy(host_addr,bootParms.had,BOOT_ADDR_LEN); + soc = TSgetNtpSocketAddr(&sin); + if(soc<0) { + TSdata.async_type=TS_async_none; + return -1; } - if( (soc=TSgetSocket(0,&sin)) <0) - { Debug0(1,"TSgetsocket failed\n"); return -1; } /* set up for ntp transaction to boot server */ - Debug(5,"host addr = %s\n",host_addr); - - /* well known registered NTP port - or whatever port they specify */ - status = aToIPAddr (host_addr, UDP_NTP_PORT, &sin); - if (status) { - Debug0(2,"bad host name or IP address\n"); - TSdata.async_type=TS_async_none; - close(soc); - return -1; - } - TSdata.async_type=TS_async_ntp; memset(&buf_ntp,0,sizeof(buf_ntp)); buf_ntp.info[0]=0x0b; @@ -929,6 +918,48 @@ static long TSgetUnixTime(struct timespec* ts) close(soc); return 0; } +/* + TSinitClockFromUnix() - query the time from boot server and set the + vxworks clock. +*/ +static long TSinitClockFromUnix(void) +{ + struct timespec tp; + int key; + unsigned long ulongtemp; + + if(!TSinitialized) TSinit(); + Debug0(3,"in TSinitClockFromUnix()\n"); + + if(TSgetUnixTime(&tp)!=0) return -1; + + ulongtemp = TSepochNtpToUnix(&tp); + tp.tv_sec = (long)ulongtemp; + + if(MAKE_DEBUG>=9) + printf("set time: %9.9lu.%9.9lu\n", tp.tv_sec,tp.tv_nsec); + + /* set the vxWorks clock to the correct time */ + if(clock_settime(CLOCK_REALTIME,&tp)<0) + { Debug0(1,"clock_settime failed\n"); } + + /* adjust time to use the EPICS EPOCH of 1990 */ + /* this is wrong if leap seconds accounted for */ + ulongtemp = TSepochUnixToEpics(&tp); + tp.tv_sec = ulongtemp; + + key=intLock(); + TSdata.mask |= TS_STAMP_FROM_UNIX; + TSdata.event_table[TSdata.sync_event]=tp; + TSdata.event_table[0]=tp; + intUnlock(key); + if(MAKE_DEBUG>=9) + printf("epics time: %9.9lu.%9.9lu\n", + TSdata.event_table[TSdata.sync_event].tv_sec, + TSdata.event_table[TSdata.sync_event].tv_nsec); + + return 0; +} /* TSgetMasterTime() - query the master timing IOC for it's current time @@ -1006,46 +1037,19 @@ static long TSgetMasterTime(struct timespec* tsp) } /* - TSsetClockFromUnix() - query the time from boot server and set the - vxworks clock. + TSsetClockFromUnix() - make next sync event get time from unix */ long TSsetClockFromUnix(void) { - struct timespec tp; - int key; - unsigned long ulongtemp; - - if(!TSinitialized) TSinit(); - Debug0(3,"in TSsetClockFromUnix()\n"); - - if(TSgetUnixTime(&tp)!=0) return -1; - - ulongtemp = TSepochNtpToUnix(&tp); - tp.tv_sec = (long)ulongtemp; - - if(MAKE_DEBUG>=9) - printf("set time: %9.9lu.%9.9lu\n", tp.tv_sec,tp.tv_nsec); - - /* set the vxWorks clock to the correct time */ - if(clock_settime(CLOCK_REALTIME,&tp)<0) - { Debug0(1,"clock_settime failed\n"); } - - /* adjust time to use the EPICS EPOCH of 1990 */ - /* this is wrong if leap seconds accounted for */ - ulongtemp = TSepochUnixToEpics(&tp); - tp.tv_sec = ulongtemp; - - /* set the EPICS event time table sync entry (current time) */ - key=intLock(); - TSdata.event_table[TSdata.sync_event]=tp; - TSdata.event_table[0]=tp; - intUnlock(key); - - if(MAKE_DEBUG>=9) - printf("epics time: %9.9lu.%9.9lu\n", - TSdata.event_table[TSdata.sync_event].tv_sec, - TSdata.event_table[TSdata.sync_event].tv_nsec); + TSdata.mask |= TS_STAMP_FROM_UNIX; + return 0; +} +long TSsetSyncReportThreshold( + unsigned long syncMilliseconds,unsigned long syncUnixMilliseconds) +{ + TSdata.syncReportThreshold = syncMilliseconds; + TSdata.syncUnixReportThreshold = syncUnixMilliseconds; return 0; } @@ -1078,83 +1082,6 @@ static long TSsetClockFromMaster() } /**************************************************************************/ -/* broadcast socket creation utilites */ -/**************************************************************************/ - -/* - TSgetBroadcastSocket() - return a broadcast socket for a port, return - a sockaddr also. -*/ -static int TSgetBroadcastSocket(int port, struct sockaddr_in* sin) -{ - int on=1; - int soc; - - sin->sin_port=htons(port); - sin->sin_family=AF_INET; - sin->sin_addr.s_addr=htonl(INADDR_ANY); - if( (soc=socket(AF_INET,SOCK_DGRAM,0)) < 0 ) - { perror("socket create failed"); return -1; } - - setsockopt(soc,SOL_SOCKET,SO_BROADCAST,(char*)&on,sizeof(on)); - - if( bind(soc,(struct sockaddr*)sin,sizeof(struct sockaddr_in)) < 0 ) - { perror("socket bind failed"); close(soc); return -1; } - - if( TSgetBroadcastAddr(soc,(struct sockaddr*)sin) < 0 ) return -1; - return soc; -} - -/* - TSgetBroadcastAddr() - Determine the broadcast address, this is - directly from the Sun Network Programmer's guide. -*/ -static long TSgetBroadcastAddr(int soc, struct sockaddr* sin) -{ - struct ifconf ifc; - struct ifreq* ifr; - struct ifreq* save; - char buf[BUFSIZ]; - int tot,i; - - ifc.ifc_len = sizeof(buf); - ifc.ifc_buf = buf; - if(ioctl(soc,SIOCGIFCONF,(int)&ifc) < 0) - { perror("ioctl SIOCGIFCONF failed"); return -1; } - - ifr = ifc.ifc_req; - tot = ifc.ifc_len/sizeof(struct ifreq); - save=(struct ifreq*)NULL; - i=0; - do - { - if(ifr->ifr_addr.sa_family==AF_INET) - { - if(ioctl(soc,SIOCGIFFLAGS,(int)ifr)<0) - { perror("ioctl SIOCGIFFLAGS failed"); return -1; } - - if( (ifr->ifr_flags&IFF_UP) && - !(ifr->ifr_flags&IFF_LOOPBACK) && - (ifr->ifr_flags&IFF_BROADCAST)) - { save=ifr; } - } - /*ifreq_size is defined in osiSock.h*/ - ifr = (struct ifreq*)((char *)ifr + ifreq_size(ifr)); - } while( !save && ++iifr_broadaddr, - sizeof(save->ifr_broadaddr)); - } - else - { Debug0(1,"no broadcast address found\n"); return -1; } - return 0; -} - -/**************************************************************************/ /* time stamp utility routines */ /**************************************************************************/ @@ -1220,16 +1147,22 @@ long TSstartSyncServer() static void TSsyncServer() { TSstampTrans stran; - struct sockaddr_in sin; - int soc; + struct sockaddr_in sinBroadcast; + int socBroadcast; + struct sockaddr_in sinNtp; + int socNtp; + unsigned long mask; + int setStampFromUnix; - if( (soc=TSgetBroadcastSocket(0,&sin)) <0) + if( (socBroadcast=TSgetBroadcastSocket(0,&sinBroadcast)) <0) { Debug0(1,"TSgetBroadcastSocket failed\n"); return; } - sin.sin_port = htons(TSdata.slave_port); + sinBroadcast.sin_port = htons(TSdata.slave_port); stran.type=(TStype)htonl(TS_sync_msg); stran.magic=htonl(TS_MAGIC); stran.sync_rate=htonl(TSdata.sync_rate); stran.clock_hz=htonl(TSdata.clock_hz); + socNtp = TSgetNtpSocketAddr(&sinNtp); + if(socNtp<0) TSprintf("TSsyncServer TSgetNtpSocketAddr failed\n"); while(1) { /* wait for a sync to occur */ @@ -1251,17 +1184,71 @@ static void TSsyncServer() TSdata.event_table[TSdata.sync_event].tv_sec=ts.tv_sec; intUnlock(key); } + /* Use while so that errors can break out of while*/ + setStampFromUnix = 0; + while(TSdata.mask & TS_STAMP_FROM_UNIX) { + TS_NTP buf_ntp; + struct timespec tp; + unsigned long ulongtemp; + int key; + unsigned long ticksStart,ticksEnd; + + if(socNtp<0) { + TSprintf("TSsyncServer cant contact NTP server\n"); + break; + } + TSgetTicks(0,&ticksStart); + memset(&buf_ntp,0,sizeof(buf_ntp)); + buf_ntp.info[0]=0x0b; + if(TSgetData((char*)&buf_ntp,sizeof(buf_ntp),socNtp, + (struct sockaddr*)&sinNtp,0,0) < 0) { + TSprintf("TSsyncServer TSgetData for NTP failed\n"); + break; + } + tp.tv_sec = ntohl(buf_ntp.transmit_ts.tv_sec); + ulongtemp = ntohl(buf_ntp.transmit_ts.tv_nsec); + tp.tv_nsec = TSfractionToNano(ulongtemp); + ulongtemp = TSepochNtpToUnix(&tp); + tp.tv_sec = (long)ulongtemp; + TSgetTicks(0,&ticksEnd); + if(ticksEnd TS_MAX_TICKS_GET_NTP) { + TSprintf("TSsyncServer NTP TSgetData took %lu clock ticks\n", + (ticksEnd - ticksStart)); + break; + } + setStampFromUnix = 1; + if(clock_settime(CLOCK_REALTIME,&tp)<0) { + TSprintf("TSsyncServer clock_settime failed\n"); + } + ulongtemp = TSepochUnixToEpics(&tp); + tp.tv_sec = ulongtemp; + key=intLock(); + TSdata.event_table[TSdata.sync_event]=tp; + TSdata.event_table[0]=tp; + intUnlock(key); + break; + } stran.master_time.tv_sec= htonl(TSdata.event_table[TSdata.sync_event].tv_sec); stran.master_time.tv_nsec= htonl(TSdata.event_table[TSdata.sync_event].tv_nsec); - if(sendto(soc,(char*)&stran,sizeof(stran),0, - (struct sockaddr*)&sin,sizeof(sin))<0) + mask = TSdata.mask; + if(!setStampFromUnix) mask &= ~TS_STAMP_FROM_UNIX; + stran.mask = htonl(mask); + if(setStampFromUnix)TSdata.mask &= ~TS_STAMP_FROM_UNIX; + stran.syncReportThreshold = htonl(TSdata.syncReportThreshold); + stran.syncUnixReportThreshold = htonl(TSdata.syncUnixReportThreshold); + if(sendto(socBroadcast,(char*)&stran,sizeof(stran),0, + (struct sockaddr*)&sinBroadcast,sizeof(sinBroadcast))<0) { perror("sendto failed"); } Debug(8,"time send secs = %lu\n",stran.master_time.tv_sec); Debug(8,"time send nsecs = %lu\n",stran.master_time.tv_nsec); } - close(soc); + close(socBroadcast); return; } @@ -1285,40 +1272,19 @@ long TSstartAsyncClient() */ static long TSasyncClient() { - BOOT_PARAMS bootParms; TSstampTrans stran; TS_NTP buf_ntp; struct sockaddr_in sin_unix,sin_bc,sin_master; int count,soc_unix,soc_master,soc_bc,buf_size; struct timespec ts,diff_time,cts,curr_time; unsigned long nsecs; - char host_addr[BOOT_ADDR_LEN]; - int status; - Debug0(2,"in TSasyncClient()\n"); - - /* could open two sockets here, one to contact unix, one to find master */ - - /*------socket for unix server----------*/ - if(envGetConfigParam(&EPICS_TS_NTP_INET,BOOT_ADDR_LEN,host_addr)==NULL - || strlen(host_addr)==0) - { - /* use boot host if the environment variable not set */ - bootStringToStruct(sysBootLine,&bootParms); - /* bootParms.had = host IP address */ - strncpy(host_addr,bootParms.had,BOOT_ADDR_LEN); + soc_unix = TSgetNtpSocketAddr(&sin_unix); + if(soc_unix<0) { + printf("TSasyncClient TSgetNtpSocketAddr failed\n"); + return -1; } - if( (soc_unix=TSgetSocket(0,&sin_unix)) <0) - { Debug0(1,"TSgetSocket failed\n"); return -1; } - - status = aToIPAddr (host_addr, UDP_NTP_PORT, &sin_unix); - if (status) { - Debug0(2,"bad host name or IP address\n"); - close (soc_unix); - return -1; - } - /*------socket for finding master----------*/ if( (soc_bc=TSgetBroadcastSocket(0,&sin_bc)) <0) { Debug0(1,"TSgetBroadcastSocket failed\n"); close(soc_unix); return -1; } @@ -1463,6 +1429,7 @@ static void TSsyncClient() struct sockaddr fs; int num,mlen,soc,fl; struct timespec mast_time; + struct timespec mytime; fd_set readfds; int key; @@ -1479,6 +1446,12 @@ static void TSsyncClient() { Debug0(1,"TSgetSocket failed\n"); return; } while(1) { + unsigned long mask; + unsigned long syncReportThreshold; + unsigned long syncUnixReportThreshold; + double reportThreshold; + double unixReportThreshold; + FD_ZERO(&readfds); FD_SET(soc,&readfds); @@ -1489,6 +1462,7 @@ static void TSsyncClient() if(num==ERROR) { perror("select failed"); continue; } fl = sizeof(fs); + memset(&stran,0,sizeof(stran)); if((mlen=recvfrom(soc,(char*)&stran,sizeof(stran),0,&fs,&fl))<0) { perror("recvfrom failed"); continue; } @@ -1497,30 +1471,44 @@ static void TSsyncClient() TSprintf("TSsyncClient: invalid packet received\n"); continue; } - - /* get the master time out of packet */ + mask = ntohl(stran.mask); + syncReportThreshold = ntohl(stran.syncReportThreshold); + syncUnixReportThreshold = ntohl(stran.syncUnixReportThreshold); + if(TSdata.syncReportThreshold>syncReportThreshold) + syncReportThreshold = TSdata.syncReportThreshold; + if(TSdata.syncUnixReportThreshold>syncUnixReportThreshold) + syncUnixReportThreshold = TSdata.syncUnixReportThreshold; mast_time.tv_sec=ntohl(stran.master_time.tv_sec); mast_time.tv_nsec=ntohl(stran.master_time.tv_nsec); - - Debug0(6,"Received sync request from master\n"); - if(MAKE_DEBUG>=8) - { - printf("time received=%9.9lu.%9.9lu\n", - mast_time.tv_sec,mast_time.tv_nsec); - } - + reportThreshold = (double)syncReportThreshold/1000.0; + unixReportThreshold = (double)syncUnixReportThreshold/1000.0; + mytime = TSdata.event_table[TSdata.sync_event]; /* verify the sync event with this one */ - if( TSdata.event_table[TSdata.sync_event].tv_sec!=mast_time.tv_sec - || TSdata.event_table[TSdata.sync_event].tv_nsec!=mast_time.tv_nsec) + if(mytime.tv_sec!=mast_time.tv_sec || mytime.tv_nsec!=mast_time.tv_nsec) { - TSprintf("sync Slave not in sync: %lu,%lu != %lu,%lu\n", - TSdata.event_table[TSdata.sync_event].tv_sec, - TSdata.event_table[TSdata.sync_event].tv_nsec, - mast_time.tv_sec, mast_time.tv_nsec); + int dir; + struct timespec diffFromMaster; + double timeDiff; + + dir = TScalcDiff(&mytime, &mast_time,&diffFromMaster); + timeDiff = diffFromMaster.tv_sec; + timeDiff += diffFromMaster.tv_nsec/(double)TS_BILLION; + if(dir<0) timeDiff = -timeDiff; key=intLock(); TSdata.event_table[TSdata.sync_event].tv_sec=mast_time.tv_sec; TSdata.event_table[TSdata.sync_event].tv_nsec=mast_time.tv_nsec; intUnlock(key); + if(mask&TS_STAMP_FROM_UNIX) { + if(fabs(timeDiff) >= unixReportThreshold) { + TSprintf("TSasynClient: Time checked with NTP via master, " + "adjusted by %f seconds.\n",timeDiff); + } + } else { + if(fabs(timeDiff) >= reportThreshold) { + TSprintf("TSasynClient: Time checked with master, " + "adjusted by %f seconds\n",timeDiff); + } + } } } close(soc); @@ -1605,12 +1593,16 @@ long TScurrentTimeStamp(struct timespec* sp) } /* get the current time from time stamp support software */ +/* can be called from interrupt level !!*/ long TSaccurateTimeStamp(struct timespec* sp) { struct timespec ts; unsigned long ticks; - if(!TSinitialized) TSinit(); + if(!TSinitialized) { + logMsg("TSaccurateTimeStamp called but !TSinitialized\n",0,0,0,0,0,0); + return -1; + } if(TSdata.has_direct_time==1) { TSgetTime(sp); @@ -1619,7 +1611,6 @@ long TSaccurateTimeStamp(struct timespec* sp) TSgetTicks(0,&ticks); /* add in the board time */ *sp = TSdata.event_table[TSdata.sync_event]; - /* calculate a time stamp from the tick count */ ts.tv_sec = ticks / TSdata.clock_hz; ts.tv_nsec=(ticks-(ts.tv_sec*TSdata.clock_hz))*TSdata.clock_conv; @@ -1703,9 +1694,83 @@ static long TScalcDiff(struct timespec* a, return dir; } -/**************************************************************************/ -/* more routines for managing sockets */ -/**************************************************************************/ +/* network utilities*/ +/* + TSgetBroadcastAddr() - Determine the broadcast address, this is + directly from the Sun Network Programmer's guide. +*/ +static long TSgetBroadcastAddr(int soc, struct sockaddr* sin) +{ + struct ifconf ifc; + struct ifreq* ifr; + struct ifreq* save; + char buf[BUFSIZ]; + int tot,i; + + ifc.ifc_len = sizeof(buf); + ifc.ifc_buf = buf; + if(ioctl(soc,SIOCGIFCONF,(int)&ifc) < 0) + { perror("ioctl SIOCGIFCONF failed"); return -1; } + + ifr = ifc.ifc_req; + tot = ifc.ifc_len/sizeof(struct ifreq); + save=(struct ifreq*)NULL; + i=0; + do + { + if(ifr->ifr_addr.sa_family==AF_INET) + { + if(ioctl(soc,SIOCGIFFLAGS,(int)ifr)<0) + { perror("ioctl SIOCGIFFLAGS failed"); return -1; } + + if( (ifr->ifr_flags&IFF_UP) && + !(ifr->ifr_flags&IFF_LOOPBACK) && + (ifr->ifr_flags&IFF_BROADCAST)) + { save=ifr; } + } + /*ifreq_size is defined in osiSock.h*/ + ifr = (struct ifreq*)((char *)ifr + ifreq_size(ifr)); + } while( !save && ++iifr_broadaddr, + sizeof(save->ifr_broadaddr)); + } + else + { Debug0(1,"no broadcast address found\n"); return -1; } + return 0; +} + +static int TSgetNtpSocketAddr(struct sockaddr_in *sin) +{ + char host_addr[BOOT_ADDR_LEN]; + BOOT_PARAMS bootParms; + int status; + int soc; + + if(envGetConfigParam(&EPICS_TS_NTP_INET,BOOT_ADDR_LEN,host_addr)==NULL + || strlen(host_addr)==0) { + /* use boot host if the environment variable not set */ + bootStringToStruct(sysBootLine,&bootParms); + /* bootParms.had = host IP address */ + strncpy(host_addr,bootParms.had,BOOT_ADDR_LEN); + } + if( (soc=TSgetSocket(0,sin)) <0) { + TSprintf("TSgetNtpSocketAddrn TSgetsocket failed\n"); + return -1; + } + /* well known registered NTP port - or whatever port they specify */ + status = aToIPAddr (host_addr, UDP_NTP_PORT, sin); + if (status) { + TSprintf("TSgetNtpSocketAddr aToIPAddr failed\n"); + close(soc); + return -1; + } + return soc; +} /* get a UDP socket for a port, return a sockaddr for it. */ static int TSgetSocket(int port, struct sockaddr_in* sin) @@ -1724,6 +1789,30 @@ static int TSgetSocket(int port, struct sockaddr_in* sin) return soc; } +/* + TSgetBroadcastSocket() - return a broadcast socket for a port, return + a sockaddr also. +*/ +static int TSgetBroadcastSocket(int port, struct sockaddr_in* sin) +{ + int on=1; + int soc; + + sin->sin_port=htons(port); + sin->sin_family=AF_INET; + sin->sin_addr.s_addr=htonl(INADDR_ANY); + if( (soc=socket(AF_INET,SOCK_DGRAM,0)) < 0 ) + { perror("socket create failed"); return -1; } + + setsockopt(soc,SOL_SOCKET,SO_BROADCAST,(char*)&on,sizeof(on)); + + if( bind(soc,(struct sockaddr*)sin,sizeof(struct sockaddr_in)) < 0 ) + { perror("socket bind failed"); close(soc); return -1; } + + if( TSgetBroadcastAddr(soc,(struct sockaddr*)sin) < 0 ) return -1; + return soc; +} + /* attempt to get data from a socket after sending a request to it. 0ptionally return round trip time and the sockaddr of the responsedent. */ @@ -1813,6 +1902,7 @@ void TSprintRealTime() { struct timespec tp; + if(!TSinitialized) TSinit(); TSgetTime(&tp); printf("real time clock = %lu,%lu\n",tp.tv_sec,tp.tv_nsec); printf("EPICS clock = %lu,%lu\n", @@ -1826,6 +1916,7 @@ void TSprintTimeStamp(int num) { struct timespec tp; + if(!TSinitialized) TSinit(); TSgetTimeStamp(num,&tp); printf("event %d occurred: %lu.%lu\n",num,tp.tv_sec,tp.tv_nsec); return; @@ -1836,6 +1927,7 @@ void TSprintCurrentTime() { struct timespec tp; + if(!TSinitialized) TSinit(); TScurrentTimeStamp(&tp); printf("Current Event System time: %lu.%lu\n",tp.tv_sec,tp.tv_nsec); TSaccurateTimeStamp(&tp); @@ -1848,6 +1940,7 @@ void TSprintUnixTime() { struct timespec ts; + if(!TSinitialized) TSinit(); if(TSgetUnixTime(&ts)!=0) { printf("Could not get Unix time\n"); @@ -1862,6 +1955,7 @@ void TSprintMasterTime() { struct timespec ts; + if(!TSinitialized) TSinit(); if(TSgetMasterTime(&ts)!=0) { printf("Could not get Unix time\n"); diff --git a/src/include/drvTS.h b/src/include/drvTS.h index 044137db3..0e05e6085 100644 --- a/src/include/drvTS.h +++ b/src/include/drvTS.h @@ -39,6 +39,10 @@ #define TS_TIME_OUT_MS 250 #define TS_SECS_ASYNC_TRY_MASTER (60*5) /* every five minutes */ #define TS_SECS_SYNC_TRY_MASTER (60*1) /* every one minute */ +#define TS_MAX_TICKS_GET_NTP 10 + +/*mask values for TSstampTrans.mask and TSinfo.mask */ +#define TS_STAMP_FROM_UNIX 0x0001 #define UDP_TIME_PORT 37 #define UDP_NTP_PORT 123 @@ -78,6 +82,9 @@ struct TSstampTransStruct { struct timespec unix_time; /* time using 1900 epoch */ unsigned long sync_rate; /* master sends sync at this rate */ unsigned long clock_hz; /* master clock this frequency (tick rate) */ + unsigned long mask; /*extra info*/ + unsigned long syncReportThreshold; /*for sync errors*/ + unsigned long syncUnixReportThreshold; /*for TS_STAMP_FROM_UNIXerrors*/ }; typedef struct TSstampTransStruct TSstampTrans; @@ -106,6 +113,9 @@ struct TSinfoStruct { struct sockaddr hunt; /* broadcast address info */ struct sockaddr master; /* socket info for contacting master */ + unsigned long mask; /*extra info*/ + unsigned long syncReportThreshold; /*for sync errors*/ + unsigned long syncUnixReportThreshold; /*for TS_STAMP_FROM_UNIXerrors*/ }; typedef struct TSinfoStruct TSinfo; @@ -127,6 +137,8 @@ TS_EXTERN void TSconfigure(int master, int sync_rate_sec, int clock_rate_hz, int master_port, int slave_port, unsigned long millisecond_request_time_out, int type); TS_EXTERN long TSsetClockFromUnix(void); +TS_EXTERN long TSsetSyncReportThreshold( + unsigned long syncMilliseconds,unsigned long syncUnixMilliseconds); #ifndef TS_DRIVER TS_EXTERN TSinfo TSdata;