1/* 2 * ntp_refclock - processing support for reference clocks 3 */ 4#ifdef HAVE_CONFIG_H 5# include <config.h> 6#endif 7 8#include "ntpd.h" 9#include "ntp_io.h" 10#include "ntp_unixtime.h" 11#include "ntp_tty.h" 12#include "ntp_refclock.h" 13#include "ntp_stdlib.h" 14 15#include <stdio.h> 16 17#ifdef HAVE_SYS_IOCTL_H 18# include <sys/ioctl.h> 19#endif /* HAVE_SYS_IOCTL_H */ 20 21#ifdef REFCLOCK 22 23#ifdef TTYCLK 24# ifdef HAVE_SYS_CLKDEFS_H 25# include <sys/clkdefs.h> 26# include <stropts.h> 27# endif 28# ifdef HAVE_SYS_SIO_H 29# include <sys/sio.h> 30# endif 31#endif /* TTYCLK */ 32 33#ifdef KERNEL_PLL 34#include "ntp_syscall.h" 35#endif /* KERNEL_PLL */ 36 37#ifdef HAVE_PPSAPI 38#include "ppsapi_timepps.h" 39#include "refclock_atom.h" 40#endif /* HAVE_PPSAPI */ 41 42/* 43 * Reference clock support is provided here by maintaining the fiction 44 * that the clock is actually a peer. As no packets are exchanged with 45 * a reference clock, however, we replace the transmit, receive and 46 * packet procedures with separate code to simulate them. Routines 47 * refclock_transmit() and refclock_receive() maintain the peer 48 * variables in a state analogous to an actual peer and pass reference 49 * clock data on through the filters. Routines refclock_peer() and 50 * refclock_unpeer() are called to initialize and terminate reference 51 * clock associations. A set of utility routines is included to open 52 * serial devices, process sample data, edit input lines to extract 53 * embedded timestamps and to perform various debugging functions. 54 * 55 * The main interface used by these routines is the refclockproc 56 * structure, which contains for most drivers the decimal equivalants 57 * of the year, day, month, hour, second and millisecond/microsecond 58 * decoded from the ASCII timecode. Additional information includes 59 * the receive timestamp, exception report, statistics tallies, etc. 60 * In addition, there may be a driver-specific unit structure used for 61 * local control of the device. 62 * 63 * The support routines are passed a pointer to the peer structure, 64 * which is used for all peer-specific processing and contains a 65 * pointer to the refclockproc structure, which in turn contains a 66 * pointer to the unit structure, if used. The peer structure is 67 * identified by an interface address in the dotted quad form 68 * 127.127.t.u, where t is the clock type and u the unit. 69 */ 70#define FUDGEFAC .1 /* fudge correction factor */ 71#define LF 0x0a /* ASCII LF */ 72 73#ifdef PPS 74int fdpps; /* ppsclock legacy */ 75#endif /* PPS */ 76 77int cal_enable; /* enable refclock calibrate */ 78 79/* 80 * Forward declarations 81 */ 82#ifdef QSORT_USES_VOID_P 83static int refclock_cmpl_fp (const void *, const void *); 84#else 85static int refclock_cmpl_fp (const double *, const double *); 86#endif /* QSORT_USES_VOID_P */ 87static int refclock_sample (struct refclockproc *); 88 89 90/* 91 * refclock_report - note the occurance of an event 92 * 93 * This routine presently just remembers the report and logs it, but 94 * does nothing heroic for the trap handler. It tries to be a good 95 * citizen and bothers the system log only if things change. 96 */ 97void 98refclock_report( 99 struct peer *peer, 100 int code 101 ) 102{ 103 struct refclockproc *pp; 104 105 pp = peer->procptr; 106 if (pp == NULL) 107 return; 108 109 switch (code) { 110 111 case CEVNT_TIMEOUT: 112 pp->noreply++; 113 break; 114 115 case CEVNT_BADREPLY: 116 pp->badformat++; 117 break; 118 119 case CEVNT_FAULT: 120 break; 121 122 case CEVNT_BADDATE: 123 case CEVNT_BADTIME: 124 pp->baddata++; 125 break; 126 127 default: 128 /* ignore others */ 129 break; 130 } 131 if (pp->lastevent < 15) 132 pp->lastevent++; 133 if (pp->currentstatus != code) { 134 pp->currentstatus = (u_char)code; 135 report_event(PEVNT_CLOCK, peer, ceventstr(code)); 136 } 137} 138 139 140/* 141 * init_refclock - initialize the reference clock drivers 142 * 143 * This routine calls each of the drivers in turn to initialize internal 144 * variables, if necessary. Most drivers have nothing to say at this 145 * point. 146 */ 147void 148init_refclock(void) 149{ 150 int i; 151 152 for (i = 0; i < (int)num_refclock_conf; i++) 153 if (refclock_conf[i]->clock_init != noentry) 154 (refclock_conf[i]->clock_init)(); 155} 156 157 158/* 159 * refclock_newpeer - initialize and start a reference clock 160 * 161 * This routine allocates and initializes the interface structure which 162 * supports a reference clock in the form of an ordinary NTP peer. A 163 * driver-specific support routine completes the initialization, if 164 * used. Default peer variables which identify the clock and establish 165 * its reference ID and stratum are set here. It returns one if success 166 * and zero if the clock address is invalid or already running, 167 * insufficient resources are available or the driver declares a bum 168 * rap. 169 */ 170int 171refclock_newpeer( 172 struct peer *peer /* peer structure pointer */ 173 ) 174{ 175 struct refclockproc *pp; 176 u_char clktype; 177 int unit; 178 179 /* 180 * Check for valid clock address. If already running, shut it 181 * down first. 182 */ 183 if (!ISREFCLOCKADR(&peer->srcadr)) { 184 msyslog(LOG_ERR, 185 "refclock_newpeer: clock address %s invalid", 186 stoa(&peer->srcadr)); 187 return (0); 188 } 189 clktype = (u_char)REFCLOCKTYPE(&peer->srcadr); 190 unit = REFCLOCKUNIT(&peer->srcadr); 191 if (clktype >= num_refclock_conf || 192 refclock_conf[clktype]->clock_start == noentry) { 193 msyslog(LOG_ERR, 194 "refclock_newpeer: clock type %d invalid\n", 195 clktype); 196 return (0); 197 } 198 199 /* 200 * Allocate and initialize interface structure 201 */ 202 pp = emalloc(sizeof(*pp)); 203 memset(pp, 0, sizeof(*pp)); 204 peer->procptr = pp; 205 206 /* 207 * Initialize structures 208 */ 209 peer->refclktype = clktype; 210 peer->refclkunit = (u_char)unit; 211 peer->flags |= FLAG_REFCLOCK; 212 peer->leap = LEAP_NOTINSYNC; 213 peer->stratum = STRATUM_REFCLOCK; 214 peer->ppoll = peer->maxpoll; 215 pp->type = clktype; 216 pp->timestarted = current_time; 217 218 /* 219 * Set peer.pmode based on the hmode. For appearances only. 220 */ 221 switch (peer->hmode) { 222 case MODE_ACTIVE: 223 peer->pmode = MODE_PASSIVE; 224 break; 225 226 default: 227 peer->pmode = MODE_SERVER; 228 break; 229 } 230 231 /* 232 * Do driver dependent initialization. The above defaults 233 * can be wiggled, then finish up for consistency. 234 */ 235 if (!((refclock_conf[clktype]->clock_start)(unit, peer))) { 236 refclock_unpeer(peer); 237 return (0); 238 } 239 peer->refid = pp->refid; 240 return (1); 241} 242 243 244/* 245 * refclock_unpeer - shut down a clock 246 */ 247void 248refclock_unpeer( 249 struct peer *peer /* peer structure pointer */ 250 ) 251{ 252 u_char clktype; 253 int unit; 254 255 /* 256 * Wiggle the driver to release its resources, then give back 257 * the interface structure. 258 */ 259 if (NULL == peer->procptr) 260 return; 261 262 clktype = peer->refclktype; 263 unit = peer->refclkunit; 264 if (refclock_conf[clktype]->clock_shutdown != noentry) 265 (refclock_conf[clktype]->clock_shutdown)(unit, peer); 266 free(peer->procptr); 267 peer->procptr = NULL; 268} 269 270 271/* 272 * refclock_timer - called once per second for housekeeping. 273 */ 274void 275refclock_timer( 276 struct peer *peer /* peer structure pointer */ 277 ) 278{ 279 u_char clktype; 280 int unit; 281 282 clktype = peer->refclktype; 283 unit = peer->refclkunit; 284 if (refclock_conf[clktype]->clock_timer != noentry) 285 (refclock_conf[clktype]->clock_timer)(unit, peer); 286} 287 288 289/* 290 * refclock_transmit - simulate the transmit procedure 291 * 292 * This routine implements the NTP transmit procedure for a reference 293 * clock. This provides a mechanism to call the driver at the NTP poll 294 * interval, as well as provides a reachability mechanism to detect a 295 * broken radio or other madness. 296 */ 297void 298refclock_transmit( 299 struct peer *peer /* peer structure pointer */ 300 ) 301{ 302 u_char clktype; 303 int unit; 304 305 clktype = peer->refclktype; 306 unit = peer->refclkunit; 307 peer->sent++; 308 get_systime(&peer->xmt); 309 310 /* 311 * This is a ripoff of the peer transmit routine, but 312 * specialized for reference clocks. We do a little less 313 * protocol here and call the driver-specific transmit routine. 314 */ 315 if (peer->burst == 0) { 316 u_char oreach; 317#ifdef DEBUG 318 if (debug) 319 printf("refclock_transmit: at %ld %s\n", 320 current_time, stoa(&(peer->srcadr))); 321#endif 322 323 /* 324 * Update reachability and poll variables like the 325 * network code. 326 */ 327 oreach = peer->reach & 0xfe; 328 peer->reach <<= 1; 329 if (!(peer->reach & 0x0f)) 330 clock_filter(peer, 0., 0., MAXDISPERSE); 331 peer->outdate = current_time; 332 if (!peer->reach) { 333 if (oreach) { 334 report_event(PEVNT_UNREACH, peer, NULL); 335 peer->timereachable = current_time; 336 } 337 } else { 338 if (peer->flags & FLAG_BURST) 339 peer->burst = NSTAGE; 340 } 341 } else { 342 peer->burst--; 343 } 344 if (refclock_conf[clktype]->clock_poll != noentry) 345 (refclock_conf[clktype]->clock_poll)(unit, peer); 346 poll_update(peer, peer->hpoll); 347} 348 349 350/* 351 * Compare two doubles - used with qsort() 352 */ 353#ifdef QSORT_USES_VOID_P 354static int 355refclock_cmpl_fp( 356 const void *p1, 357 const void *p2 358 ) 359{ 360 const double *dp1 = (const double *)p1; 361 const double *dp2 = (const double *)p2; 362 363 if (*dp1 < *dp2) 364 return (-1); 365 366 if (*dp1 > *dp2) 367 return (1); 368 369 return (0); 370} 371 372#else 373static int 374refclock_cmpl_fp( 375 const double *dp1, 376 const double *dp2 377 ) 378{ 379 if (*dp1 < *dp2) 380 return (-1); 381 382 if (*dp1 > *dp2) 383 return (1); 384 385 return (0); 386} 387#endif /* QSORT_USES_VOID_P */ 388 389 390/* 391 * refclock_process_offset - update median filter 392 * 393 * This routine uses the given offset and timestamps to construct a new 394 * entry in the median filter circular buffer. Samples that overflow the 395 * filter are quietly discarded. 396 */ 397void 398refclock_process_offset( 399 struct refclockproc *pp, /* refclock structure pointer */ 400 l_fp lasttim, /* last timecode timestamp */ 401 l_fp lastrec, /* last receive timestamp */ 402 double fudge 403 ) 404{ 405 l_fp lftemp; 406 double doffset; 407 408 pp->lastrec = lastrec; 409 lftemp = lasttim; 410 L_SUB(&lftemp, &lastrec); 411 LFPTOD(&lftemp, doffset); 412 SAMPLE(doffset + fudge); 413} 414 415 416/* 417 * refclock_process - process a sample from the clock 418 * refclock_process_f - refclock_process with other than time1 fudge 419 * 420 * This routine converts the timecode in the form days, hours, minutes, 421 * seconds and milliseconds/microseconds to internal timestamp format, 422 * then constructs a new entry in the median filter circular buffer. 423 * Return success (1) if the data are correct and consistent with the 424 * converntional calendar. 425 * 426 * Important for PPS users: Normally, the pp->lastrec is set to the 427 * system time when the on-time character is received and the pp->year, 428 * ..., pp->second decoded and the seconds fraction pp->nsec in 429 * nanoseconds). When a PPS offset is available, pp->nsec is forced to 430 * zero and the fraction for pp->lastrec is set to the PPS offset. 431 */ 432int 433refclock_process_f( 434 struct refclockproc *pp, /* refclock structure pointer */ 435 double fudge 436 ) 437{ 438 l_fp offset, ltemp; 439 440 /* 441 * Compute the timecode timestamp from the days, hours, minutes, 442 * seconds and milliseconds/microseconds of the timecode. Use 443 * clocktime() for the aggregate seconds and the msec/usec for 444 * the fraction, when present. Note that this code relies on the 445 * filesystem time for the years and does not use the years of 446 * the timecode. 447 */ 448 if (!clocktime(pp->day, pp->hour, pp->minute, pp->second, GMT, 449 pp->lastrec.l_ui, &pp->yearstart, &offset.l_ui)) 450 return (0); 451 452 offset.l_uf = 0; 453 DTOLFP(pp->nsec / 1e9, <emp); 454 L_ADD(&offset, <emp); 455 refclock_process_offset(pp, offset, pp->lastrec, fudge); 456 return (1); 457} 458 459 460int 461refclock_process( 462 struct refclockproc *pp /* refclock structure pointer */ 463) 464{ 465 return refclock_process_f(pp, pp->fudgetime1); 466} 467 468 469/* 470 * refclock_sample - process a pile of samples from the clock 471 * 472 * This routine implements a recursive median filter to suppress spikes 473 * in the data, as well as determine a performance statistic. It 474 * calculates the mean offset and RMS jitter. A time adjustment 475 * fudgetime1 can be added to the final offset to compensate for various 476 * systematic errors. The routine returns the number of samples 477 * processed, which could be zero. 478 */ 479static int 480refclock_sample( 481 struct refclockproc *pp /* refclock structure pointer */ 482 ) 483{ 484 int i, j, k, m, n; 485 double off[MAXSTAGE]; 486 double offset; 487 488 /* 489 * Copy the raw offsets and sort into ascending order. Don't do 490 * anything if the buffer is empty. 491 */ 492 n = 0; 493 while (pp->codeproc != pp->coderecv) { 494 pp->codeproc = (pp->codeproc + 1) % MAXSTAGE; 495 off[n] = pp->filter[pp->codeproc]; 496 n++; 497 } 498 if (n == 0) 499 return (0); 500 501 if (n > 1) 502 qsort( 503#ifdef QSORT_USES_VOID_P 504 (void *) 505#else 506 (char *) 507#endif 508 off, (size_t)n, sizeof(double), refclock_cmpl_fp); 509 510 /* 511 * Reject the furthest from the median of the samples until 512 * approximately 60 percent of the samples remain. 513 */ 514 i = 0; j = n; 515 m = n - (n * 4) / 10; 516 while ((j - i) > m) { 517 offset = off[(j + i) / 2]; 518 if (off[j - 1] - offset < offset - off[i]) 519 i++; /* reject low end */ 520 else 521 j--; /* reject high end */ 522 } 523 524 /* 525 * Determine the offset and jitter. 526 */ 527 pp->offset = 0; 528 pp->jitter = 0; 529 for (k = i; k < j; k++) { 530 pp->offset += off[k]; 531 if (k > i) 532 pp->jitter += SQUARE(off[k] - off[k - 1]); 533 } 534 pp->offset /= m; 535 pp->jitter = max(SQRT(pp->jitter / m), LOGTOD(sys_precision)); 536#ifdef DEBUG 537 if (debug) 538 printf( 539 "refclock_sample: n %d offset %.6f disp %.6f jitter %.6f\n", 540 n, pp->offset, pp->disp, pp->jitter); 541#endif 542 return (n); 543} 544 545 546/* 547 * refclock_receive - simulate the receive and packet procedures 548 * 549 * This routine simulates the NTP receive and packet procedures for a 550 * reference clock. This provides a mechanism in which the ordinary NTP 551 * filter, selection and combining algorithms can be used to suppress 552 * misbehaving radios and to mitigate between them when more than one is 553 * available for backup. 554 */ 555void 556refclock_receive( 557 struct peer *peer /* peer structure pointer */ 558 ) 559{ 560 struct refclockproc *pp; 561 562#ifdef DEBUG 563 if (debug) 564 printf("refclock_receive: at %lu %s\n", 565 current_time, stoa(&peer->srcadr)); 566#endif 567 568 /* 569 * Do a little sanity dance and update the peer structure. Groom 570 * the median filter samples and give the data to the clock 571 * filter. 572 */ 573 pp = peer->procptr; 574 peer->leap = pp->leap; 575 if (peer->leap == LEAP_NOTINSYNC) 576 return; 577 578 peer->received++; 579 peer->timereceived = current_time; 580 if (!peer->reach) { 581 report_event(PEVNT_REACH, peer, NULL); 582 peer->timereachable = current_time; 583 } 584 peer->reach |= 1; 585 peer->reftime = pp->lastref; 586 peer->aorg = pp->lastrec; 587 peer->rootdisp = pp->disp; 588 get_systime(&peer->dst); 589 if (!refclock_sample(pp)) 590 return; 591 592 clock_filter(peer, pp->offset, 0., pp->jitter); 593 if (cal_enable && fabs(last_offset) < sys_mindisp && sys_peer != 594 NULL) { 595 if (sys_peer->refclktype == REFCLK_ATOM_PPS && 596 peer->refclktype != REFCLK_ATOM_PPS) 597 pp->fudgetime1 -= pp->offset * FUDGEFAC; 598 } 599} 600 601 602/* 603 * refclock_gtlin - groom next input line and extract timestamp 604 * 605 * This routine processes the timecode received from the clock and 606 * strips the parity bit and control characters. It returns the number 607 * of characters in the line followed by a NULL character ('\0'), which 608 * is not included in the count. In case of an empty line, the previous 609 * line is preserved. 610 */ 611int 612refclock_gtlin( 613 struct recvbuf *rbufp, /* receive buffer pointer */ 614 char *lineptr, /* current line pointer */ 615 int bmax, /* remaining characters in line */ 616 l_fp *tsptr /* pointer to timestamp returned */ 617 ) 618{ 619 char s[BMAX]; 620 char *dpt, *dpend, *dp; 621 622 dpt = s; 623 dpend = s + refclock_gtraw(rbufp, s, BMAX - 1, tsptr); 624 if (dpend - dpt > bmax - 1) 625 dpend = dpt + bmax - 1; 626 for (dp = lineptr; dpt < dpend; dpt++) { 627 char c; 628 629 c = *dpt & 0x7f; 630 if (c >= 0x20 && c < 0x7f) 631 *dp++ = c; 632 } 633 if (dp == lineptr) 634 return (0); 635 636 *dp = '\0'; 637 return (dp - lineptr); 638} 639 640 641/* 642 * refclock_gtraw - get next line/chunk of data 643 * 644 * This routine returns the raw data received from the clock in both 645 * canonical or raw modes. The terminal interface routines map CR to LF. 646 * In canonical mode this results in two lines, one containing data 647 * followed by LF and another containing only LF. In raw mode the 648 * interface routines can deliver arbitraty chunks of data from one 649 * character to a maximum specified by the calling routine. In either 650 * mode the routine returns the number of characters in the line 651 * followed by a NULL character ('\0'), which is not included in the 652 * count. 653 * 654 * If a timestamp is present in the timecode, as produced by the tty_clk 655 * STREAMS module, it returns that as the timestamp; otherwise, it 656 * returns the buffer timestamp. 657 */ 658int 659refclock_gtraw( 660 struct recvbuf *rbufp, /* receive buffer pointer */ 661 char *lineptr, /* current line pointer */ 662 int bmax, /* remaining characters in line */ 663 l_fp *tsptr /* pointer to timestamp returned */ 664 ) 665{ 666 char *dpt, *dpend, *dp; 667 l_fp trtmp, tstmp; 668 int i; 669 670 /* 671 * Check for the presence of a timestamp left by the tty_clock 672 * module and, if present, use that instead of the buffer 673 * timestamp captured by the I/O routines. We recognize a 674 * timestamp by noting its value is earlier than the buffer 675 * timestamp, but not more than one second earlier. 676 */ 677 dpt = (char *)rbufp->recv_buffer; 678 dpend = dpt + rbufp->recv_length; 679 trtmp = rbufp->recv_time; 680 if (dpend >= dpt + 8) { 681 if (buftvtots(dpend - 8, &tstmp)) { 682 L_SUB(&trtmp, &tstmp); 683 if (trtmp.l_ui == 0) { 684#ifdef DEBUG 685 if (debug > 1) { 686 printf( 687 "refclock_gtlin: fd %d ldisc %s", 688 rbufp->fd, lfptoa(&trtmp, 689 6)); 690 get_systime(&trtmp); 691 L_SUB(&trtmp, &tstmp); 692 printf(" sigio %s\n", 693 lfptoa(&trtmp, 6)); 694 } 695#endif 696 dpend -= 8; 697 trtmp = tstmp; 698 } else 699 trtmp = rbufp->recv_time; 700 } 701 } 702 703 /* 704 * Copy the raw buffer to the user string. The string is padded 705 * with a NULL, which is not included in the character count. 706 */ 707 if (dpend - dpt > bmax - 1) 708 dpend = dpt + bmax - 1; 709 for (dp = lineptr; dpt < dpend; dpt++) 710 *dp++ = *dpt; 711 *dp = '\0'; 712 i = dp - lineptr; 713#ifdef DEBUG 714 if (debug > 1) 715 printf("refclock_gtraw: fd %d time %s timecode %d %s\n", 716 rbufp->fd, ulfptoa(&trtmp, 6), i, lineptr); 717#endif 718 *tsptr = trtmp; 719 return (i); 720} 721 722 723/* 724 * The following code does not apply to WINNT & VMS ... 725 */ 726#if !defined SYS_VXWORKS && !defined SYS_WINNT 727#if defined(HAVE_TERMIOS) || defined(HAVE_SYSV_TTYS) || defined(HAVE_BSD_TTYS) 728 729/* 730 * refclock_open - open serial port for reference clock 731 * 732 * This routine opens a serial port for I/O and sets default options. It 733 * returns the file descriptor if success and zero if failure. 734 */ 735int 736refclock_open( 737 char *dev, /* device name pointer */ 738 u_int speed, /* serial port speed (code) */ 739 u_int lflags /* line discipline flags */ 740 ) 741{ 742 int fd; 743 int omode; 744 745 /* 746 * Open serial port and set default options 747 */ 748 omode = O_RDWR; 749#ifdef O_NONBLOCK 750 omode |= O_NONBLOCK; 751#endif 752#ifdef O_NOCTTY 753 omode |= O_NOCTTY; 754#endif 755 756 fd = open(dev, omode, 0777); 757 if (fd < 0) { 758 msyslog(LOG_ERR, "refclock_open %s: %m", dev); 759 return (0); 760 } 761 if (!refclock_setup(fd, speed, lflags)) { 762 close(fd); 763 return (0); 764 } 765 if (!refclock_ioctl(fd, lflags)) { 766 close(fd); 767 return (0); 768 } 769 return (fd); 770} 771 772/* 773 * refclock_setup - initialize terminal interface structure 774 */ 775int 776refclock_setup( 777 int fd, /* file descriptor */ 778 u_int speed, /* serial port speed (code) */ 779 u_int lflags /* line discipline flags */ 780 ) 781{ 782 int i; 783 TTY ttyb, *ttyp; 784#ifdef PPS 785 fdpps = fd; /* ppsclock legacy */ 786#endif /* PPS */ 787 788 /* 789 * By default, the serial line port is initialized in canonical 790 * (line-oriented) mode at specified line speed, 8 bits and no 791 * parity. LF ends the line and CR is mapped to LF. The break, 792 * erase and kill functions are disabled. There is a different 793 * section for each terminal interface, as selected at compile 794 * time. The flag bits can be used to set raw mode and echo. 795 */ 796 ttyp = &ttyb; 797#ifdef HAVE_TERMIOS 798 799 /* 800 * POSIX serial line parameters (termios interface) 801 */ 802 if (tcgetattr(fd, ttyp) < 0) { 803 msyslog(LOG_ERR, 804 "refclock_setup fd %d tcgetattr: %m", fd); 805 return (0); 806 } 807 808 /* 809 * Set canonical mode and local connection; set specified speed, 810 * 8 bits and no parity; map CR to NL; ignore break. 811 */ 812 if (speed) { 813 u_int ltemp = 0; 814 815 ttyp->c_iflag = IGNBRK | IGNPAR | ICRNL; 816 ttyp->c_oflag = 0; 817 ttyp->c_cflag = CS8 | CLOCAL | CREAD; 818 if (lflags & LDISC_7O1) { 819 /* HP Z3801A needs 7-bit, odd parity */ 820 ttyp->c_cflag = CS7 | PARENB | PARODD | CLOCAL | CREAD; 821 } 822 cfsetispeed(&ttyb, speed); 823 cfsetospeed(&ttyb, speed); 824 for (i = 0; i < NCCS; ++i) 825 ttyp->c_cc[i] = '\0'; 826 827#if defined(TIOCMGET) && !defined(SCO5_CLOCK) 828 829 /* 830 * If we have modem control, check to see if modem leads 831 * are active; if so, set remote connection. This is 832 * necessary for the kernel pps mods to work. 833 */ 834 if (ioctl(fd, TIOCMGET, (char *)<emp) < 0) 835 msyslog(LOG_ERR, 836 "refclock_setup fd %d TIOCMGET: %m", fd); 837#ifdef DEBUG 838 if (debug) 839 printf("refclock_setup fd %d modem status: 0x%x\n", 840 fd, ltemp); 841#endif 842 if (ltemp & TIOCM_DSR && lflags & LDISC_REMOTE) 843 ttyp->c_cflag &= ~CLOCAL; 844#endif /* TIOCMGET */ 845 } 846 847 /* 848 * Set raw and echo modes. These can be changed on-fly. 849 */ 850 ttyp->c_lflag = ICANON; 851 if (lflags & LDISC_RAW) { 852 ttyp->c_lflag = 0; 853 ttyp->c_iflag = 0; 854 ttyp->c_cc[VMIN] = 1; 855 } 856 if (lflags & LDISC_ECHO) 857 ttyp->c_lflag |= ECHO; 858 if (tcsetattr(fd, TCSANOW, ttyp) < 0) { 859 msyslog(LOG_ERR, 860 "refclock_setup fd %d TCSANOW: %m", fd); 861 return (0); 862 } 863#endif /* HAVE_TERMIOS */ 864 865#ifdef HAVE_SYSV_TTYS 866 867 /* 868 * System V serial line parameters (termio interface) 869 * 870 */ 871 if (ioctl(fd, TCGETA, ttyp) < 0) { 872 msyslog(LOG_ERR, 873 "refclock_setup fd %d TCGETA: %m", fd); 874 return (0); 875 } 876 877 /* 878 * Set canonical mode and local connection; set specified speed, 879 * 8 bits and no parity; map CR to NL; ignore break. 880 */ 881 if (speed) { 882 u_int ltemp = 0; 883 884 ttyp->c_iflag = IGNBRK | IGNPAR | ICRNL; 885 ttyp->c_oflag = 0; 886 ttyp->c_cflag = speed | CS8 | CLOCAL | CREAD; 887 for (i = 0; i < NCCS; ++i) 888 ttyp->c_cc[i] = '\0'; 889 890#if defined(TIOCMGET) && !defined(SCO5_CLOCK) 891 892 /* 893 * If we have modem control, check to see if modem leads 894 * are active; if so, set remote connection. This is 895 * necessary for the kernel pps mods to work. 896 */ 897 if (ioctl(fd, TIOCMGET, (char *)<emp) < 0) 898 msyslog(LOG_ERR, 899 "refclock_setup fd %d TIOCMGET: %m", fd); 900#ifdef DEBUG 901 if (debug) 902 printf("refclock_setup fd %d modem status: %x\n", 903 fd, ltemp); 904#endif 905 if (ltemp & TIOCM_DSR) 906 ttyp->c_cflag &= ~CLOCAL; 907#endif /* TIOCMGET */ 908 } 909 910 /* 911 * Set raw and echo modes. These can be changed on-fly. 912 */ 913 ttyp->c_lflag = ICANON; 914 if (lflags & LDISC_RAW) { 915 ttyp->c_lflag = 0; 916 ttyp->c_iflag = 0; 917 ttyp->c_cc[VMIN] = 1; 918 } 919 if (ioctl(fd, TCSETA, ttyp) < 0) { 920 msyslog(LOG_ERR, 921 "refclock_setup fd %d TCSETA: %m", fd); 922 return (0); 923 } 924#endif /* HAVE_SYSV_TTYS */ 925 926#ifdef HAVE_BSD_TTYS 927 928 /* 929 * 4.3bsd serial line parameters (sgttyb interface) 930 */ 931 if (ioctl(fd, TIOCGETP, (char *)ttyp) < 0) { 932 msyslog(LOG_ERR, 933 "refclock_setup fd %d TIOCGETP: %m", fd); 934 return (0); 935 } 936 if (speed) 937 ttyp->sg_ispeed = ttyp->sg_ospeed = speed; 938 ttyp->sg_flags = EVENP | ODDP | CRMOD; 939 if (ioctl(fd, TIOCSETP, (char *)ttyp) < 0) { 940 msyslog(LOG_ERR, 941 "refclock_setup TIOCSETP: %m"); 942 return (0); 943 } 944#endif /* HAVE_BSD_TTYS */ 945 return(1); 946} 947#endif /* HAVE_TERMIOS || HAVE_SYSV_TTYS || HAVE_BSD_TTYS */ 948#endif /* SYS_VXWORKS SYS_WINNT */ 949 950 951/* 952 * refclock_ioctl - set serial port control functions 953 * 954 * This routine attempts to hide the internal, system-specific details 955 * of serial ports. It can handle POSIX (termios), SYSV (termio) and BSD 956 * (sgtty) interfaces with varying degrees of success. The routine sets 957 * up optional features such as tty_clk. The routine returns 1 if 958 * success and 0 if failure. 959 */ 960int 961refclock_ioctl( 962 int fd, /* file descriptor */ 963 u_int lflags /* line discipline flags */ 964 ) 965{ 966 /* 967 * simply return 1 if no UNIX line discipline is supported 968 */ 969#if !defined SYS_VXWORKS && !defined SYS_WINNT 970#if defined(HAVE_TERMIOS) || defined(HAVE_SYSV_TTYS) || defined(HAVE_BSD_TTYS) 971 972#ifdef DEBUG 973 if (debug) 974 printf("refclock_ioctl: fd %d flags 0x%x\n", fd, 975 lflags); 976#endif 977#ifdef TTYCLK 978 979 /* 980 * The TTYCLK option provides timestamping at the driver level. 981 * It requires the tty_clk streams module and System V STREAMS 982 * support. If not available, don't complain. 983 */ 984 if (lflags & (LDISC_CLK | LDISC_CLKPPS | LDISC_ACTS)) { 985 int rval = 0; 986 987 if (ioctl(fd, I_PUSH, "clk") < 0) { 988 msyslog(LOG_NOTICE, 989 "refclock_ioctl fd %d I_PUSH: %m", fd); 990 return (0); 991#ifdef CLK_SETSTR 992 } else { 993 char *str; 994 995 if (lflags & LDISC_CLKPPS) 996 str = "\377"; 997 else if (lflags & LDISC_ACTS) 998 str = "*"; 999 else 1000 str = "\n"; 1001 if (ioctl(fd, CLK_SETSTR, str) < 0) { 1002 msyslog(LOG_ERR, 1003 "refclock_ioctl fd %d CLK_SETSTR: %m", fd); 1004 return (0); 1005 } 1006#endif /*CLK_SETSTR */ 1007 } 1008 } 1009#endif /* TTYCLK */ 1010#endif /* HAVE_TERMIOS || HAVE_SYSV_TTYS || HAVE_BSD_TTYS */ 1011#endif /* SYS_VXWORKS SYS_WINNT */ 1012 return (1); 1013} 1014 1015 1016/* 1017 * refclock_control - set and/or return clock values 1018 * 1019 * This routine is used mainly for debugging. It returns designated 1020 * values from the interface structure that can be displayed using 1021 * ntpdc and the clockstat command. It can also be used to initialize 1022 * configuration variables, such as fudgetimes, fudgevalues, reference 1023 * ID and stratum. 1024 */ 1025void 1026refclock_control( 1027 sockaddr_u *srcadr, 1028 struct refclockstat *in, 1029 struct refclockstat *out 1030 ) 1031{ 1032 struct peer *peer; 1033 struct refclockproc *pp; 1034 u_char clktype; 1035 int unit; 1036 1037 /* 1038 * Check for valid address and running peer 1039 */ 1040 if (!ISREFCLOCKADR(srcadr)) 1041 return; 1042 1043 clktype = (u_char)REFCLOCKTYPE(srcadr); 1044 unit = REFCLOCKUNIT(srcadr); 1045 1046 peer = findexistingpeer(srcadr, NULL, -1); 1047 1048 if (NULL == peer || NULL == peer->procptr) 1049 return; 1050 1051 pp = peer->procptr; 1052 1053 /* 1054 * Initialize requested data 1055 */ 1056 if (in != 0) { 1057 if (in->haveflags & CLK_HAVETIME1) 1058 pp->fudgetime1 = in->fudgetime1; 1059 if (in->haveflags & CLK_HAVETIME2) 1060 pp->fudgetime2 = in->fudgetime2; 1061 if (in->haveflags & CLK_HAVEVAL1) 1062 peer->stratum = pp->stratum = (u_char)in->fudgeval1; 1063 if (in->haveflags & CLK_HAVEVAL2) 1064 peer->refid = pp->refid = in->fudgeval2; 1065 if (in->haveflags & CLK_HAVEFLAG1) { 1066 pp->sloppyclockflag &= ~CLK_FLAG1; 1067 pp->sloppyclockflag |= in->flags & CLK_FLAG1; 1068 } 1069 if (in->haveflags & CLK_HAVEFLAG2) { 1070 pp->sloppyclockflag &= ~CLK_FLAG2; 1071 pp->sloppyclockflag |= in->flags & CLK_FLAG2; 1072 } 1073 if (in->haveflags & CLK_HAVEFLAG3) { 1074 pp->sloppyclockflag &= ~CLK_FLAG3; 1075 pp->sloppyclockflag |= in->flags & CLK_FLAG3; 1076 } 1077 if (in->haveflags & CLK_HAVEFLAG4) { 1078 pp->sloppyclockflag &= ~CLK_FLAG4; 1079 pp->sloppyclockflag |= in->flags & CLK_FLAG4; 1080 } 1081 } 1082 1083 /* 1084 * Readback requested data 1085 */ 1086 if (out != 0) { 1087 out->haveflags = CLK_HAVETIME1 | CLK_HAVEVAL1 | 1088 CLK_HAVEVAL2 | CLK_HAVEFLAG4; 1089 out->fudgetime1 = pp->fudgetime1; 1090 out->fudgetime2 = pp->fudgetime2; 1091 out->fudgeval1 = pp->stratum; 1092 out->fudgeval2 = pp->refid; 1093 out->flags = (u_char) pp->sloppyclockflag; 1094 1095 out->timereset = current_time - pp->timestarted; 1096 out->polls = pp->polls; 1097 out->noresponse = pp->noreply; 1098 out->badformat = pp->badformat; 1099 out->baddata = pp->baddata; 1100 1101 out->lastevent = pp->lastevent; 1102 out->currentstatus = pp->currentstatus; 1103 out->type = pp->type; 1104 out->clockdesc = pp->clockdesc; 1105 out->lencode = (u_short)pp->lencode; 1106 out->p_lastcode = pp->a_lastcode; 1107 } 1108 1109 /* 1110 * Give the stuff to the clock 1111 */ 1112 if (refclock_conf[clktype]->clock_control != noentry) 1113 (refclock_conf[clktype]->clock_control)(unit, in, out, peer); 1114} 1115 1116 1117/* 1118 * refclock_buginfo - return debugging info 1119 * 1120 * This routine is used mainly for debugging. It returns designated 1121 * values from the interface structure that can be displayed using 1122 * ntpdc and the clkbug command. 1123 */ 1124void 1125refclock_buginfo( 1126 sockaddr_u *srcadr, /* clock address */ 1127 struct refclockbug *bug /* output structure */ 1128 ) 1129{ 1130 struct peer *peer; 1131 struct refclockproc *pp; 1132 int clktype; 1133 int unit; 1134 unsigned u; 1135 1136 /* 1137 * Check for valid address and peer structure 1138 */ 1139 if (!ISREFCLOCKADR(srcadr)) 1140 return; 1141 1142 clktype = (u_char) REFCLOCKTYPE(srcadr); 1143 unit = REFCLOCKUNIT(srcadr); 1144 1145 peer = findexistingpeer(srcadr, NULL, -1); 1146 1147 if (NULL == peer || NULL == peer->procptr) 1148 return; 1149 1150 pp = peer->procptr; 1151 1152 /* 1153 * Copy structure values 1154 */ 1155 bug->nvalues = 8; 1156 bug->svalues = 0x0000003f; 1157 bug->values[0] = pp->year; 1158 bug->values[1] = pp->day; 1159 bug->values[2] = pp->hour; 1160 bug->values[3] = pp->minute; 1161 bug->values[4] = pp->second; 1162 bug->values[5] = pp->nsec; 1163 bug->values[6] = pp->yearstart; 1164 bug->values[7] = pp->coderecv; 1165 bug->stimes = 0xfffffffc; 1166 bug->times[0] = pp->lastref; 1167 bug->times[1] = pp->lastrec; 1168 for (u = 2; u < bug->ntimes; u++) 1169 DTOLFP(pp->filter[u - 2], &bug->times[u]); 1170 1171 /* 1172 * Give the stuff to the clock 1173 */ 1174 if (refclock_conf[clktype]->clock_buginfo != noentry) 1175 (refclock_conf[clktype]->clock_buginfo)(unit, bug, peer); 1176} 1177 1178 1179#ifdef HAVE_PPSAPI 1180/* 1181 * refclock_ppsapi - initialize/update ppsapi 1182 * 1183 * This routine is called after the fudge command to open the PPSAPI 1184 * interface for later parameter setting after the fudge command. 1185 */ 1186int 1187refclock_ppsapi( 1188 int fddev, /* fd device */ 1189 struct refclock_atom *ap /* atom structure pointer */ 1190 ) 1191{ 1192 if (ap->handle == 0) { 1193 if (time_pps_create(fddev, &ap->handle) < 0) { 1194 msyslog(LOG_ERR, 1195 "refclock_ppsapi: time_pps_create: %m"); 1196 return (0); 1197 } 1198 } 1199 return (1); 1200} 1201 1202 1203/* 1204 * refclock_params - set ppsapi parameters 1205 * 1206 * This routine is called to set the PPSAPI parameters after the fudge 1207 * command. 1208 */ 1209int 1210refclock_params( 1211 int mode, /* mode bits */ 1212 struct refclock_atom *ap /* atom structure pointer */ 1213 ) 1214{ 1215 memset(&ap->pps_params, 0, sizeof(pps_params_t)); 1216 ap->pps_params.api_version = PPS_API_VERS_1; 1217 1218 /* 1219 * Solaris serial ports provide PPS pulse capture only on the 1220 * assert edge. FreeBSD serial ports provide capture on the 1221 * clear edge, while FreeBSD parallel ports provide capture 1222 * on the assert edge. Your mileage may vary. 1223 */ 1224 if (mode & CLK_FLAG2) 1225 ap->pps_params.mode = PPS_TSFMT_TSPEC | PPS_CAPTURECLEAR; 1226 else 1227 ap->pps_params.mode = PPS_TSFMT_TSPEC | PPS_CAPTUREASSERT; 1228 if (time_pps_setparams(ap->handle, &ap->pps_params) < 0) { 1229 msyslog(LOG_ERR, 1230 "refclock_params: time_pps_setparams: %m"); 1231 return (0); 1232 } 1233 1234 /* 1235 * If flag3 is lit, select the kernel PPS. 1236 */ 1237 if (mode & CLK_FLAG3) { 1238 if (time_pps_kcbind(ap->handle, PPS_KC_HARDPPS, 1239 ap->pps_params.mode & ~PPS_TSFMT_TSPEC, 1240 PPS_TSFMT_TSPEC) < 0) { 1241 if (errno != EOPNOTSUPP) { 1242 msyslog(LOG_ERR, 1243 "refclock_params: time_pps_kcbind: %m"); 1244 return (0); 1245 } 1246 } 1247 pps_enable = 1; 1248 } 1249 return (1); 1250} 1251 1252 1253/* 1254 * refclock_pps - called once per second 1255 * 1256 * This routine is called once per second. It snatches the PPS 1257 * timestamp from the kernel and saves the sign-extended fraction in 1258 * a circular buffer for processing at the next poll event. 1259 */ 1260int 1261refclock_pps( 1262 struct peer *peer, /* peer structure pointer */ 1263 struct refclock_atom *ap, /* atom structure pointer */ 1264 int mode /* mode bits */ 1265 ) 1266{ 1267 struct refclockproc *pp; 1268 pps_info_t pps_info; 1269 struct timespec timeout; 1270 double dtemp; 1271 1272 /* 1273 * We require the clock to be synchronized before setting the 1274 * parameters. When the parameters have been set, fetch the 1275 * most recent PPS timestamp. 1276 */ 1277 pp = peer->procptr; 1278 if (ap->handle == 0) 1279 return (0); 1280 1281 if (ap->pps_params.mode == 0 && sys_leap != LEAP_NOTINSYNC) { 1282 if (refclock_params(pp->sloppyclockflag, ap) < 1) 1283 return (0); 1284 } 1285 timeout.tv_sec = 0; 1286 timeout.tv_nsec = 0; 1287 memset(&pps_info, 0, sizeof(pps_info_t)); 1288 if (time_pps_fetch(ap->handle, PPS_TSFMT_TSPEC, &pps_info, 1289 &timeout) < 0) { 1290 refclock_report(peer, CEVNT_FAULT); 1291 return (0); 1292 } 1293 timeout = ap->ts; 1294 if (ap->pps_params.mode & PPS_CAPTUREASSERT) 1295 ap->ts = pps_info.assert_timestamp; 1296 else if (ap->pps_params.mode & PPS_CAPTURECLEAR) 1297 ap->ts = pps_info.clear_timestamp; 1298 else 1299 return (0); 1300 1301 /* 1302 * There can be zero, one or two PPS pulses between polls, 1303 * depending on the poll interval relative to the PPS interval. 1304 * The pulse must be newer and within the range gate relative 1305 * to the last pulse. 1306 */ 1307 if (ap->ts.tv_sec <= timeout.tv_sec || abs(ap->ts.tv_nsec - 1308 timeout.tv_nsec) > RANGEGATE) 1309 return (0); 1310 1311 /* 1312 * Convert to signed fraction offset and stuff in median filter. 1313 */ 1314 pp->lastrec.l_ui = ap->ts.tv_sec + JAN_1970; 1315 dtemp = ap->ts.tv_nsec / 1e9; 1316 pp->lastrec.l_uf = (u_int32)(dtemp * FRAC); 1317 if (dtemp > .5) 1318 dtemp -= 1.; 1319 SAMPLE(-dtemp + pp->fudgetime1); 1320#ifdef DEBUG 1321 if (debug > 1) 1322 printf("refclock_pps: %lu %f %f\n", current_time, 1323 dtemp, pp->fudgetime1); 1324#endif 1325 return (1); 1326} 1327#endif /* HAVE_PPSAPI */ 1328#endif /* REFCLOCK */ 1329