1 /* $NetBSD: ntp_refclock.c,v 1.4 2012/02/01 20:48:01 kardel Exp $ */ 2 3 /* 4 * ntp_refclock - processing support for reference clocks 5 */ 6 #ifdef HAVE_CONFIG_H 7 # include <config.h> 8 #endif 9 10 #include "ntpd.h" 11 #include "ntp_io.h" 12 #include "ntp_unixtime.h" 13 #include "ntp_tty.h" 14 #include "ntp_refclock.h" 15 #include "ntp_stdlib.h" 16 #include "ntp_assert.h" 17 18 #include <stdio.h> 19 20 #ifdef HAVE_SYS_IOCTL_H 21 # include <sys/ioctl.h> 22 #endif /* HAVE_SYS_IOCTL_H */ 23 24 #ifdef REFCLOCK 25 26 #ifdef TTYCLK 27 # ifdef HAVE_SYS_CLKDEFS_H 28 # include <sys/clkdefs.h> 29 # include <stropts.h> 30 # endif 31 # ifdef HAVE_SYS_SIO_H 32 # include <sys/sio.h> 33 # endif 34 #endif /* TTYCLK */ 35 36 #ifdef KERNEL_PLL 37 #include "ntp_syscall.h" 38 #endif /* KERNEL_PLL */ 39 40 #ifdef HAVE_PPSAPI 41 #include "ppsapi_timepps.h" 42 #include "refclock_atom.h" 43 #endif /* HAVE_PPSAPI */ 44 45 /* 46 * Reference clock support is provided here by maintaining the fiction 47 * that the clock is actually a peer. As no packets are exchanged with 48 * a reference clock, however, we replace the transmit, receive and 49 * packet procedures with separate code to simulate them. Routines 50 * refclock_transmit() and refclock_receive() maintain the peer 51 * variables in a state analogous to an actual peer and pass reference 52 * clock data on through the filters. Routines refclock_peer() and 53 * refclock_unpeer() are called to initialize and terminate reference 54 * clock associations. A set of utility routines is included to open 55 * serial devices, process sample data, edit input lines to extract 56 * embedded timestamps and to perform various debugging functions. 57 * 58 * The main interface used by these routines is the refclockproc 59 * structure, which contains for most drivers the decimal equivalants 60 * of the year, day, month, hour, second and millisecond/microsecond 61 * decoded from the ASCII timecode. Additional information includes 62 * the receive timestamp, exception report, statistics tallies, etc. 63 * In addition, there may be a driver-specific unit structure used for 64 * local control of the device. 65 * 66 * The support routines are passed a pointer to the peer structure, 67 * which is used for all peer-specific processing and contains a 68 * pointer to the refclockproc structure, which in turn contains a 69 * pointer to the unit structure, if used. The peer structure is 70 * identified by an interface address in the dotted quad form 71 * 127.127.t.u, where t is the clock type and u the unit. 72 */ 73 #define FUDGEFAC .1 /* fudge correction factor */ 74 #define LF 0x0a /* ASCII LF */ 75 76 #ifdef PPS 77 int fdpps; /* ppsclock legacy */ 78 #endif /* PPS */ 79 80 int cal_enable; /* enable refclock calibrate */ 81 82 /* 83 * Forward declarations 84 */ 85 #ifdef QSORT_USES_VOID_P 86 static int refclock_cmpl_fp (const void *, const void *); 87 #else 88 static int refclock_cmpl_fp (const double *, const double *); 89 #endif /* QSORT_USES_VOID_P */ 90 static int refclock_sample (struct refclockproc *); 91 92 93 /* 94 * refclock_report - note the occurance of an event 95 * 96 * This routine presently just remembers the report and logs it, but 97 * does nothing heroic for the trap handler. It tries to be a good 98 * citizen and bothers the system log only if things change. 99 */ 100 void 101 refclock_report( 102 struct peer *peer, 103 int code 104 ) 105 { 106 struct refclockproc *pp; 107 108 pp = peer->procptr; 109 if (pp == NULL) 110 return; 111 112 switch (code) { 113 114 case CEVNT_TIMEOUT: 115 pp->noreply++; 116 break; 117 118 case CEVNT_BADREPLY: 119 pp->badformat++; 120 break; 121 122 case CEVNT_FAULT: 123 break; 124 125 case CEVNT_BADDATE: 126 case CEVNT_BADTIME: 127 pp->baddata++; 128 break; 129 130 default: 131 /* ignore others */ 132 break; 133 } 134 if (pp->lastevent < 15) 135 pp->lastevent++; 136 if (pp->currentstatus != code) { 137 pp->currentstatus = (u_char)code; 138 report_event(PEVNT_CLOCK, peer, ceventstr(code)); 139 } 140 } 141 142 143 /* 144 * init_refclock - initialize the reference clock drivers 145 * 146 * This routine calls each of the drivers in turn to initialize internal 147 * variables, if necessary. Most drivers have nothing to say at this 148 * point. 149 */ 150 void 151 init_refclock(void) 152 { 153 int i; 154 155 for (i = 0; i < (int)num_refclock_conf; i++) 156 if (refclock_conf[i]->clock_init != noentry) 157 (refclock_conf[i]->clock_init)(); 158 } 159 160 161 /* 162 * refclock_newpeer - initialize and start a reference clock 163 * 164 * This routine allocates and initializes the interface structure which 165 * supports a reference clock in the form of an ordinary NTP peer. A 166 * driver-specific support routine completes the initialization, if 167 * used. Default peer variables which identify the clock and establish 168 * its reference ID and stratum are set here. It returns one if success 169 * and zero if the clock address is invalid or already running, 170 * insufficient resources are available or the driver declares a bum 171 * rap. 172 */ 173 int 174 refclock_newpeer( 175 struct peer *peer /* peer structure pointer */ 176 ) 177 { 178 struct refclockproc *pp; 179 u_char clktype; 180 int unit; 181 182 /* 183 * Check for valid clock address. If already running, shut it 184 * down first. 185 */ 186 if (!ISREFCLOCKADR(&peer->srcadr)) { 187 msyslog(LOG_ERR, 188 "refclock_newpeer: clock address %s invalid", 189 stoa(&peer->srcadr)); 190 return (0); 191 } 192 clktype = (u_char)REFCLOCKTYPE(&peer->srcadr); 193 unit = REFCLOCKUNIT(&peer->srcadr); 194 if (clktype >= num_refclock_conf || 195 refclock_conf[clktype]->clock_start == noentry) { 196 msyslog(LOG_ERR, 197 "refclock_newpeer: clock type %d invalid\n", 198 clktype); 199 return (0); 200 } 201 202 /* 203 * Allocate and initialize interface structure 204 */ 205 pp = emalloc(sizeof(*pp)); 206 memset(pp, 0, sizeof(*pp)); 207 peer->procptr = pp; 208 209 /* 210 * Initialize structures 211 */ 212 peer->refclktype = clktype; 213 peer->refclkunit = (u_char)unit; 214 peer->flags |= FLAG_REFCLOCK; 215 peer->leap = LEAP_NOTINSYNC; 216 peer->stratum = STRATUM_REFCLOCK; 217 peer->ppoll = peer->maxpoll; 218 pp->type = clktype; 219 pp->timestarted = current_time; 220 221 /* 222 * Set peer.pmode based on the hmode. For appearances only. 223 */ 224 switch (peer->hmode) { 225 case MODE_ACTIVE: 226 peer->pmode = MODE_PASSIVE; 227 break; 228 229 default: 230 peer->pmode = MODE_SERVER; 231 break; 232 } 233 234 /* 235 * Do driver dependent initialization. The above defaults 236 * can be wiggled, then finish up for consistency. 237 */ 238 if (!((refclock_conf[clktype]->clock_start)(unit, peer))) { 239 refclock_unpeer(peer); 240 return (0); 241 } 242 peer->refid = pp->refid; 243 return (1); 244 } 245 246 247 /* 248 * refclock_unpeer - shut down a clock 249 */ 250 void 251 refclock_unpeer( 252 struct peer *peer /* peer structure pointer */ 253 ) 254 { 255 u_char clktype; 256 int unit; 257 258 /* 259 * Wiggle the driver to release its resources, then give back 260 * the interface structure. 261 */ 262 if (NULL == peer->procptr) 263 return; 264 265 clktype = peer->refclktype; 266 unit = peer->refclkunit; 267 if (refclock_conf[clktype]->clock_shutdown != noentry) 268 (refclock_conf[clktype]->clock_shutdown)(unit, peer); 269 free(peer->procptr); 270 peer->procptr = NULL; 271 } 272 273 274 /* 275 * refclock_timer - called once per second for housekeeping. 276 */ 277 void 278 refclock_timer( 279 struct peer *peer /* peer structure pointer */ 280 ) 281 { 282 u_char clktype; 283 int unit; 284 285 clktype = peer->refclktype; 286 unit = peer->refclkunit; 287 if (refclock_conf[clktype]->clock_timer != noentry) 288 (refclock_conf[clktype]->clock_timer)(unit, peer); 289 } 290 291 292 /* 293 * refclock_transmit - simulate the transmit procedure 294 * 295 * This routine implements the NTP transmit procedure for a reference 296 * clock. This provides a mechanism to call the driver at the NTP poll 297 * interval, as well as provides a reachability mechanism to detect a 298 * broken radio or other madness. 299 */ 300 void 301 refclock_transmit( 302 struct peer *peer /* peer structure pointer */ 303 ) 304 { 305 u_char clktype; 306 int unit; 307 308 clktype = peer->refclktype; 309 unit = peer->refclkunit; 310 peer->sent++; 311 get_systime(&peer->xmt); 312 313 /* 314 * This is a ripoff of the peer transmit routine, but 315 * specialized for reference clocks. We do a little less 316 * protocol here and call the driver-specific transmit routine. 317 */ 318 if (peer->burst == 0) { 319 u_char oreach; 320 #ifdef DEBUG 321 if (debug) 322 printf("refclock_transmit: at %ld %s\n", 323 current_time, stoa(&(peer->srcadr))); 324 #endif 325 326 /* 327 * Update reachability and poll variables like the 328 * network code. 329 */ 330 oreach = peer->reach & 0xfe; 331 peer->reach <<= 1; 332 if (!(peer->reach & 0x0f)) 333 clock_filter(peer, 0., 0., MAXDISPERSE); 334 peer->outdate = current_time; 335 if (!peer->reach) { 336 if (oreach) { 337 report_event(PEVNT_UNREACH, peer, NULL); 338 peer->timereachable = current_time; 339 } 340 } else { 341 if (peer->flags & FLAG_BURST) 342 peer->burst = NSTAGE; 343 } 344 } else { 345 peer->burst--; 346 } 347 if (refclock_conf[clktype]->clock_poll != noentry) 348 (refclock_conf[clktype]->clock_poll)(unit, peer); 349 poll_update(peer, peer->hpoll); 350 } 351 352 353 /* 354 * Compare two doubles - used with qsort() 355 */ 356 static int 357 refclock_cmpl_fp( 358 const void *p1, 359 const void *p2 360 ) 361 { 362 const double *dp1 = (const double *)p1; 363 const double *dp2 = (const double *)p2; 364 365 if (*dp1 < *dp2) 366 return -1; 367 if (*dp1 > *dp2) 368 return 1; 369 return 0; 370 } 371 372 373 /* 374 * refclock_process_offset - update median filter 375 * 376 * This routine uses the given offset and timestamps to construct a new 377 * entry in the median filter circular buffer. Samples that overflow the 378 * filter are quietly discarded. 379 */ 380 void 381 refclock_process_offset( 382 struct refclockproc *pp, /* refclock structure pointer */ 383 l_fp lasttim, /* last timecode timestamp */ 384 l_fp lastrec, /* last receive timestamp */ 385 double fudge 386 ) 387 { 388 l_fp lftemp; 389 double doffset; 390 391 pp->lastrec = lastrec; 392 lftemp = lasttim; 393 L_SUB(&lftemp, &lastrec); 394 LFPTOD(&lftemp, doffset); 395 SAMPLE(doffset + fudge); 396 } 397 398 399 /* 400 * refclock_process - process a sample from the clock 401 * refclock_process_f - refclock_process with other than time1 fudge 402 * 403 * This routine converts the timecode in the form days, hours, minutes, 404 * seconds and milliseconds/microseconds to internal timestamp format, 405 * then constructs a new entry in the median filter circular buffer. 406 * Return success (1) if the data are correct and consistent with the 407 * converntional calendar. 408 * 409 * Important for PPS users: Normally, the pp->lastrec is set to the 410 * system time when the on-time character is received and the pp->year, 411 * ..., pp->second decoded and the seconds fraction pp->nsec in 412 * nanoseconds). When a PPS offset is available, pp->nsec is forced to 413 * zero and the fraction for pp->lastrec is set to the PPS offset. 414 */ 415 int 416 refclock_process_f( 417 struct refclockproc *pp, /* refclock structure pointer */ 418 double fudge 419 ) 420 { 421 l_fp offset, ltemp; 422 423 /* 424 * Compute the timecode timestamp from the days, hours, minutes, 425 * seconds and milliseconds/microseconds of the timecode. Use 426 * clocktime() for the aggregate seconds and the msec/usec for 427 * the fraction, when present. Note that this code relies on the 428 * filesystem time for the years and does not use the years of 429 * the timecode. 430 */ 431 if (!clocktime(pp->day, pp->hour, pp->minute, pp->second, GMT, 432 pp->lastrec.l_ui, &pp->yearstart, &offset.l_ui)) 433 return (0); 434 435 offset.l_uf = 0; 436 DTOLFP(pp->nsec / 1e9, <emp); 437 L_ADD(&offset, <emp); 438 refclock_process_offset(pp, offset, pp->lastrec, fudge); 439 return (1); 440 } 441 442 443 int 444 refclock_process( 445 struct refclockproc *pp /* refclock structure pointer */ 446 ) 447 { 448 return refclock_process_f(pp, pp->fudgetime1); 449 } 450 451 452 /* 453 * refclock_sample - process a pile of samples from the clock 454 * 455 * This routine implements a recursive median filter to suppress spikes 456 * in the data, as well as determine a performance statistic. It 457 * calculates the mean offset and RMS jitter. A time adjustment 458 * fudgetime1 can be added to the final offset to compensate for various 459 * systematic errors. The routine returns the number of samples 460 * processed, which could be zero. 461 */ 462 static int 463 refclock_sample( 464 struct refclockproc *pp /* refclock structure pointer */ 465 ) 466 { 467 size_t i, j, k, m, n; 468 double off[MAXSTAGE]; 469 double offset; 470 471 /* 472 * Copy the raw offsets and sort into ascending order. Don't do 473 * anything if the buffer is empty. 474 */ 475 n = 0; 476 while (pp->codeproc != pp->coderecv) { 477 pp->codeproc = (pp->codeproc + 1) % MAXSTAGE; 478 off[n] = pp->filter[pp->codeproc]; 479 n++; 480 } 481 if (n == 0) 482 return (0); 483 484 if (n > 1) 485 qsort((void *)off, n, sizeof(off[0]), refclock_cmpl_fp); 486 487 /* 488 * Reject the furthest from the median of the samples until 489 * approximately 60 percent of the samples remain. 490 */ 491 i = 0; j = n; 492 m = n - (n * 4) / 10; 493 while ((j - i) > m) { 494 offset = off[(j + i) / 2]; 495 if (off[j - 1] - offset < offset - off[i]) 496 i++; /* reject low end */ 497 else 498 j--; /* reject high end */ 499 } 500 501 /* 502 * Determine the offset and jitter. 503 */ 504 pp->offset = 0; 505 pp->jitter = 0; 506 for (k = i; k < j; k++) { 507 pp->offset += off[k]; 508 if (k > i) 509 pp->jitter += SQUARE(off[k] - off[k - 1]); 510 } 511 pp->offset /= m; 512 pp->jitter = max(SQRT(pp->jitter / m), LOGTOD(sys_precision)); 513 #ifdef DEBUG 514 if (debug) 515 printf( 516 "refclock_sample: n %d offset %.6f disp %.6f jitter %.6f\n", 517 (int)n, pp->offset, pp->disp, pp->jitter); 518 #endif 519 return (int)n; 520 } 521 522 523 /* 524 * refclock_receive - simulate the receive and packet procedures 525 * 526 * This routine simulates the NTP receive and packet procedures for a 527 * reference clock. This provides a mechanism in which the ordinary NTP 528 * filter, selection and combining algorithms can be used to suppress 529 * misbehaving radios and to mitigate between them when more than one is 530 * available for backup. 531 */ 532 void 533 refclock_receive( 534 struct peer *peer /* peer structure pointer */ 535 ) 536 { 537 struct refclockproc *pp; 538 539 #ifdef DEBUG 540 if (debug) 541 printf("refclock_receive: at %lu %s\n", 542 current_time, stoa(&peer->srcadr)); 543 #endif 544 545 /* 546 * Do a little sanity dance and update the peer structure. Groom 547 * the median filter samples and give the data to the clock 548 * filter. 549 */ 550 pp = peer->procptr; 551 peer->leap = pp->leap; 552 if (peer->leap == LEAP_NOTINSYNC) 553 return; 554 555 peer->received++; 556 peer->timereceived = current_time; 557 if (!peer->reach) { 558 report_event(PEVNT_REACH, peer, NULL); 559 peer->timereachable = current_time; 560 } 561 peer->reach |= 1; 562 peer->reftime = pp->lastref; 563 peer->aorg = pp->lastrec; 564 peer->rootdisp = pp->disp; 565 get_systime(&peer->dst); 566 if (!refclock_sample(pp)) 567 return; 568 569 clock_filter(peer, pp->offset, 0., pp->jitter); 570 if (cal_enable && fabs(last_offset) < sys_mindisp && sys_peer != 571 NULL) { 572 if (sys_peer->refclktype == REFCLK_ATOM_PPS && 573 peer->refclktype != REFCLK_ATOM_PPS) 574 pp->fudgetime1 -= pp->offset * FUDGEFAC; 575 } 576 } 577 578 579 /* 580 * refclock_gtlin - groom next input line and extract timestamp 581 * 582 * This routine processes the timecode received from the clock and 583 * strips the parity bit and control characters. It returns the number 584 * of characters in the line followed by a NULL character ('\0'), which 585 * is not included in the count. In case of an empty line, the previous 586 * line is preserved. 587 */ 588 int 589 refclock_gtlin( 590 struct recvbuf *rbufp, /* receive buffer pointer */ 591 char *lineptr, /* current line pointer */ 592 int bmax, /* remaining characters in line */ 593 l_fp *tsptr /* pointer to timestamp returned */ 594 ) 595 { 596 char s[BMAX]; 597 char *dpt, *dpend, *dp; 598 599 dpt = s; 600 dpend = s + refclock_gtraw(rbufp, s, BMAX - 1, tsptr); 601 if (dpend - dpt > bmax - 1) 602 dpend = dpt + bmax - 1; 603 for (dp = lineptr; dpt < dpend; dpt++) { 604 char c; 605 606 c = *dpt & 0x7f; 607 if (c >= 0x20 && c < 0x7f) 608 *dp++ = c; 609 } 610 if (dp == lineptr) 611 return (0); 612 613 *dp = '\0'; 614 return (dp - lineptr); 615 } 616 617 618 /* 619 * refclock_gtraw - get next line/chunk of data 620 * 621 * This routine returns the raw data received from the clock in both 622 * canonical or raw modes. The terminal interface routines map CR to LF. 623 * In canonical mode this results in two lines, one containing data 624 * followed by LF and another containing only LF. In raw mode the 625 * interface routines can deliver arbitraty chunks of data from one 626 * character to a maximum specified by the calling routine. In either 627 * mode the routine returns the number of characters in the line 628 * followed by a NULL character ('\0'), which is not included in the 629 * count. 630 * 631 * If a timestamp is present in the timecode, as produced by the tty_clk 632 * STREAMS module, it returns that as the timestamp; otherwise, it 633 * returns the buffer timestamp. 634 */ 635 int 636 refclock_gtraw( 637 struct recvbuf *rbufp, /* receive buffer pointer */ 638 char *lineptr, /* current line pointer */ 639 int bmax, /* remaining characters in line */ 640 l_fp *tsptr /* pointer to timestamp returned */ 641 ) 642 { 643 char *dpt, *dpend, *dp; 644 l_fp trtmp, tstmp; 645 int i; 646 647 /* 648 * Check for the presence of a timestamp left by the tty_clock 649 * module and, if present, use that instead of the buffer 650 * timestamp captured by the I/O routines. We recognize a 651 * timestamp by noting its value is earlier than the buffer 652 * timestamp, but not more than one second earlier. 653 */ 654 dpt = (char *)rbufp->recv_buffer; 655 dpend = dpt + rbufp->recv_length; 656 trtmp = rbufp->recv_time; 657 if (dpend >= dpt + 8) { 658 if (buftvtots(dpend - 8, &tstmp)) { 659 L_SUB(&trtmp, &tstmp); 660 if (trtmp.l_ui == 0) { 661 #ifdef DEBUG 662 if (debug > 1) { 663 printf( 664 "refclock_gtlin: fd %d ldisc %s", 665 rbufp->fd, lfptoa(&trtmp, 666 6)); 667 get_systime(&trtmp); 668 L_SUB(&trtmp, &tstmp); 669 printf(" sigio %s\n", 670 lfptoa(&trtmp, 6)); 671 } 672 #endif 673 dpend -= 8; 674 trtmp = tstmp; 675 } else 676 trtmp = rbufp->recv_time; 677 } 678 } 679 680 /* 681 * Copy the raw buffer to the user string. The string is padded 682 * with a NULL, which is not included in the character count. 683 */ 684 if (dpend - dpt > bmax - 1) 685 dpend = dpt + bmax - 1; 686 for (dp = lineptr; dpt < dpend; dpt++) 687 *dp++ = *dpt; 688 *dp = '\0'; 689 i = dp - lineptr; 690 #ifdef DEBUG 691 if (debug > 1) 692 printf("refclock_gtraw: fd %d time %s timecode %d %s\n", 693 rbufp->fd, ulfptoa(&trtmp, 6), i, lineptr); 694 #endif 695 *tsptr = trtmp; 696 return (i); 697 } 698 699 700 /* 701 * The following code does not apply to WINNT & VMS ... 702 */ 703 #if !defined SYS_VXWORKS && !defined SYS_WINNT 704 #if defined(HAVE_TERMIOS) || defined(HAVE_SYSV_TTYS) || defined(HAVE_BSD_TTYS) 705 706 /* 707 * refclock_open - open serial port for reference clock 708 * 709 * This routine opens a serial port for I/O and sets default options. It 710 * returns the file descriptor if success and zero if failure. 711 */ 712 int 713 refclock_open( 714 char *dev, /* device name pointer */ 715 u_int speed, /* serial port speed (code) */ 716 u_int lflags /* line discipline flags */ 717 ) 718 { 719 int fd; 720 int omode; 721 #ifdef O_NONBLOCK 722 char trash[128]; /* litter bin for old input data */ 723 #endif 724 725 /* 726 * Open serial port and set default options 727 */ 728 omode = O_RDWR; 729 #ifdef O_NONBLOCK 730 omode |= O_NONBLOCK; 731 #endif 732 #ifdef O_NOCTTY 733 omode |= O_NOCTTY; 734 #endif 735 736 fd = open(dev, omode, 0777); 737 if (fd < 0) { 738 msyslog(LOG_ERR, "refclock_open %s: %m", dev); 739 return (0); 740 } 741 NTP_INSIST(fd != 0); 742 if (!refclock_setup(fd, speed, lflags)) { 743 close(fd); 744 return (0); 745 } 746 if (!refclock_ioctl(fd, lflags)) { 747 close(fd); 748 return (0); 749 } 750 #ifdef O_NONBLOCK 751 /* 752 * We want to make sure there is no pending trash in the input 753 * buffer. Since we have non-blocking IO available, this is a 754 * good moment to read and dump all available outdated stuff 755 * that might have become toxic for the driver. 756 */ 757 while (read(fd, trash, sizeof(trash)) > 0 || errno == EINTR) 758 /*NOP*/; 759 #endif 760 return (fd); 761 } 762 763 764 /* 765 * refclock_setup - initialize terminal interface structure 766 */ 767 int 768 refclock_setup( 769 int fd, /* file descriptor */ 770 u_int speed, /* serial port speed (code) */ 771 u_int lflags /* line discipline flags */ 772 ) 773 { 774 int i; 775 TTY ttyb, *ttyp; 776 #ifdef PPS 777 fdpps = fd; /* ppsclock legacy */ 778 #endif /* PPS */ 779 780 /* 781 * By default, the serial line port is initialized in canonical 782 * (line-oriented) mode at specified line speed, 8 bits and no 783 * parity. LF ends the line and CR is mapped to LF. The break, 784 * erase and kill functions are disabled. There is a different 785 * section for each terminal interface, as selected at compile 786 * time. The flag bits can be used to set raw mode and echo. 787 */ 788 ttyp = &ttyb; 789 #ifdef HAVE_TERMIOS 790 791 /* 792 * POSIX serial line parameters (termios interface) 793 */ 794 if (tcgetattr(fd, ttyp) < 0) { 795 msyslog(LOG_ERR, 796 "refclock_setup fd %d tcgetattr: %m", fd); 797 return (0); 798 } 799 800 /* 801 * Set canonical mode and local connection; set specified speed, 802 * 8 bits and no parity; map CR to NL; ignore break. 803 */ 804 if (speed) { 805 u_int ltemp = 0; 806 807 ttyp->c_iflag = IGNBRK | IGNPAR | ICRNL; 808 ttyp->c_oflag = 0; 809 ttyp->c_cflag = CS8 | CLOCAL | CREAD; 810 if (lflags & LDISC_7O1) { 811 /* HP Z3801A needs 7-bit, odd parity */ 812 ttyp->c_cflag = CS7 | PARENB | PARODD | CLOCAL | CREAD; 813 } 814 cfsetispeed(&ttyb, speed); 815 cfsetospeed(&ttyb, speed); 816 for (i = 0; i < NCCS; ++i) 817 ttyp->c_cc[i] = '\0'; 818 819 #if defined(TIOCMGET) && !defined(SCO5_CLOCK) 820 821 /* 822 * If we have modem control, check to see if modem leads 823 * are active; if so, set remote connection. This is 824 * necessary for the kernel pps mods to work. 825 */ 826 if (ioctl(fd, TIOCMGET, (char *)<emp) < 0) 827 msyslog(LOG_ERR, 828 "refclock_setup fd %d TIOCMGET: %m", fd); 829 #ifdef DEBUG 830 if (debug) 831 printf("refclock_setup fd %d modem status: 0x%x\n", 832 fd, ltemp); 833 #endif 834 if (ltemp & TIOCM_DSR && lflags & LDISC_REMOTE) 835 ttyp->c_cflag &= ~CLOCAL; 836 #endif /* TIOCMGET */ 837 } 838 839 /* 840 * Set raw and echo modes. These can be changed on-fly. 841 */ 842 ttyp->c_lflag = ICANON; 843 if (lflags & LDISC_RAW) { 844 ttyp->c_lflag = 0; 845 ttyp->c_iflag = 0; 846 ttyp->c_cc[VMIN] = 1; 847 } 848 if (lflags & LDISC_ECHO) 849 ttyp->c_lflag |= ECHO; 850 if (tcsetattr(fd, TCSANOW, ttyp) < 0) { 851 msyslog(LOG_ERR, 852 "refclock_setup fd %d TCSANOW: %m", fd); 853 return (0); 854 } 855 856 /* 857 * flush input and output buffers to discard any outdated stuff 858 * that might have become toxic for the driver. Failing to do so 859 * is logged, but we keep our fingers crossed otherwise. 860 */ 861 if (tcflush(fd, TCIOFLUSH) < 0) 862 msyslog(LOG_ERR, "refclock_setup fd %d tcflush(): %m", fd); 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 */ 960 int 961 refclock_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 */ 1025 void 1026 refclock_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, 0); 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 */ 1124 void 1125 refclock_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, 0); 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 */ 1186 int 1187 refclock_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 */ 1209 int 1210 refclock_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 */ 1260 int 1261 refclock_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 = (u_int32)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