2 * ntp_refclock - processing support for reference clocks
10 #include "ntp_unixtime.h"
12 #include "ntp_refclock.h"
13 #include "ntp_stdlib.h"
17 #ifdef HAVE_SYS_IOCTL_H
18 # include <sys/ioctl.h>
19 #endif /* HAVE_SYS_IOCTL_H */
24 # ifdef HAVE_SYS_CLKDEFS_H
25 # include <sys/clkdefs.h>
28 # ifdef HAVE_SYS_SIO_H
33 #ifdef HAVE_PPSCLOCK_H
34 #include <sys/ppsclock.h>
35 #endif /* HAVE_PPSCLOCK_H */
38 #include "ntp_syscall.h"
39 #endif /* KERNEL_PLL */
42 * Reference clock support is provided here by maintaining the fiction
43 * that the clock is actually a peer. As no packets are exchanged with a
44 * reference clock, however, we replace the transmit, receive and packet
45 * procedures with separate code to simulate them. Routines
46 * refclock_transmit() and refclock_receive() maintain the peer
47 * variables in a state analogous to an actual peer and pass reference
48 * clock data on through the filters. Routines refclock_peer() and
49 * refclock_unpeer() are called to initialize and terminate reference
50 * clock associations. A set of utility routines is included to open
51 * serial devices, process sample data, edit input lines to extract
52 * embedded timestamps and to peform various debugging functions.
54 * The main interface used by these routines is the refclockproc
55 * structure, which contains for most drivers the decimal equivalants of
56 * the year, day, month, hour, second and millisecond/microsecond
57 * decoded from the ASCII timecode. Additional information includes the
58 * receive timestamp, exception report, statistics tallies, etc. In
59 * addition, there may be a driver-specific unit structure used for
60 * local control of the device.
62 * The support routines are passed a pointer to the peer structure,
63 * which is used for all peer-specific processing and contains a pointer
64 * to the refclockproc structure, which in turn containes a pointer to
65 * the unit structure, if used. The peer structure is identified by an
66 * interface address in the dotted quad form 127.127.t.u (for now only IPv4
67 * addresses are used, so we need to be sure the address is it), where t is
68 * the clock type and u the unit. Some legacy drivers derive the
69 * refclockproc structure pointer from the table typeunit[type][unit].
70 * This interface is strongly discouraged and may be abandoned in
73 #define MAXUNIT 4 /* max units */
74 #define FUDGEFAC .1 /* fudge correction factor */
76 int fdpps; /* pps file descriptor */
77 int cal_enable; /* enable refclock calibrate */
80 * Type/unit peer index. Used to find the peer structure for control and
81 * debugging. When all clock drivers have been converted to new style,
84 static struct peer *typeunit[REFCLK_MAX + 1][MAXUNIT];
87 * Forward declarations
89 #ifdef QSORT_USES_VOID_P
90 static int refclock_cmpl_fp P((const void *, const void *));
92 static int refclock_cmpl_fp P((const double *, const double *));
93 #endif /* QSORT_USES_VOID_P */
94 static int refclock_sample P((struct refclockproc *));
97 * refclock_report - note the occurance of an event
99 * This routine presently just remembers the report and logs it, but
100 * does nothing heroic for the trap handler. It tries to be a good
101 * citizen and bothers the system log only if things change.
109 struct refclockproc *pp;
114 if (code == CEVNT_BADREPLY)
116 if (code == CEVNT_BADTIME)
118 if (code == CEVNT_TIMEOUT)
120 if (pp->currentstatus != code) {
121 pp->currentstatus = (u_char)code;
122 pp->lastevent = (u_char)code;
123 if (code == CEVNT_FAULT)
125 "clock %s event '%s' (0x%02x)",
126 refnumtoa(&peer->srcadr),
127 ceventstr(code), code);
129 NLOG(NLOG_CLOCKEVENT)
131 "clock %s event '%s' (0x%02x)",
132 refnumtoa(&peer->srcadr),
133 ceventstr(code), code);
138 printf("clock %s event '%s' (0x%02x)\n",
139 refnumtoa(&peer->srcadr),
140 ceventstr(code), code);
146 * init_refclock - initialize the reference clock drivers
148 * This routine calls each of the drivers in turn to initialize internal
149 * variables, if necessary. Most drivers have nothing to say at this
157 for (i = 0; i < (int)num_refclock_conf; i++) {
158 if (refclock_conf[i]->clock_init != noentry)
159 (refclock_conf[i]->clock_init)();
160 for (j = 0; j < MAXUNIT; j++)
167 * refclock_newpeer - initialize and start a reference clock
169 * This routine allocates and initializes the interface structure which
170 * supports a reference clock in the form of an ordinary NTP peer. A
171 * driver-specific support routine completes the initialization, if
172 * used. Default peer variables which identify the clock and establish
173 * its reference ID and stratum are set here. It returns one if success
174 * and zero if the clock address is invalid or already running,
175 * insufficient resources are available or the driver declares a bum
180 struct peer *peer /* peer structure pointer */
183 struct refclockproc *pp;
188 * Check for valid clock address. If already running, shut it
191 if (peer->srcadr.ss_family != AF_INET) {
193 "refclock_newpeer: clock address %s invalid, address family not implemented for refclock",
194 stoa(&peer->srcadr));
197 if (!ISREFCLOCKADR(&peer->srcadr)) {
199 "refclock_newpeer: clock address %s invalid",
200 stoa(&peer->srcadr));
203 clktype = (u_char)REFCLOCKTYPE(&peer->srcadr);
204 unit = REFCLOCKUNIT(&peer->srcadr);
205 if (clktype >= num_refclock_conf || unit >= MAXUNIT ||
206 refclock_conf[clktype]->clock_start == noentry) {
208 "refclock_newpeer: clock type %d invalid\n",
214 * Allocate and initialize interface structure
216 pp = (struct refclockproc *)emalloc(sizeof(struct refclockproc));
219 memset((char *)pp, 0, sizeof(struct refclockproc));
220 typeunit[clktype][unit] = peer;
224 * Initialize structures
226 peer->refclktype = clktype;
227 peer->refclkunit = (u_char)unit;
228 peer->flags |= FLAG_REFCLOCK;
229 peer->maxpoll = peer->minpoll;
230 peer->stratum = STRATUM_REFCLOCK;
232 pp->timestarted = current_time;
235 * Set peer.pmode based on the hmode. For appearances only.
237 switch (peer->hmode) {
239 peer->pmode = MODE_PASSIVE;
243 peer->pmode = MODE_SERVER;
248 * Do driver dependent initialization. The above defaults
249 * can be wiggled, then finish up for consistency.
251 if (!((refclock_conf[clktype]->clock_start)(unit, peer))) {
252 refclock_unpeer(peer);
255 peer->hpoll = peer->minpoll;
256 peer->ppoll = peer->maxpoll;
257 peer->refid = pp->refid;
263 * refclock_unpeer - shut down a clock
267 struct peer *peer /* peer structure pointer */
274 * Wiggle the driver to release its resources, then give back
275 * the interface structure.
279 clktype = peer->refclktype;
280 unit = peer->refclkunit;
281 if (refclock_conf[clktype]->clock_shutdown != noentry)
282 (refclock_conf[clktype]->clock_shutdown)(unit, peer);
289 * refclock_transmit - simulate the transmit procedure
291 * This routine implements the NTP transmit procedure for a reference
292 * clock. This provides a mechanism to call the driver at the NTP poll
293 * interval, as well as provides a reachability mechanism to detect a
294 * broken radio or other madness.
298 struct peer *peer /* peer structure pointer */
305 clktype = peer->refclktype;
306 unit = peer->refclkunit;
310 * This is a ripoff of the peer transmit routine, but
311 * specialized for reference clocks. We do a little less
312 * protocol here and call the driver-specific transmit routine.
314 next = peer->outdate;
315 if (peer->burst == 0) {
319 printf("refclock_transmit: at %ld %s\n",
320 current_time, stoa(&(peer->srcadr)));
324 * Update reachability and poll variables like the
327 oreach = peer->reach;
331 report_event(EVNT_UNREACH, peer);
332 peer->timereachable = current_time;
333 peer_clear(peer, "NONE");
336 if (!(oreach & 0x03)) {
337 clock_filter(peer, 0., 0., MAXDISPERSE);
340 if (peer->flags & FLAG_BURST)
341 peer->burst = NSTAGE;
345 get_systime(&peer->xmt);
346 if (refclock_conf[clktype]->clock_poll != noentry)
347 (refclock_conf[clktype]->clock_poll)(unit, peer);
348 peer->outdate = next;
351 poll_update(peer, 0);
356 * Compare two doubles - used with qsort()
358 #ifdef QSORT_USES_VOID_P
365 const double *dp1 = (const double *)p1;
366 const double *dp2 = (const double *)p2;
387 #endif /* QSORT_USES_VOID_P */
391 * refclock_process_offset - update median filter
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.
398 refclock_process_offset(
399 struct refclockproc *pp, /* refclock structure pointer */
400 l_fp lasttim, /* last timecode timestamp */
401 l_fp lastrec, /* last receive timestamp */
408 pp->lastrec = lastrec;
410 L_SUB(&lftemp, &lastrec);
411 LFPTOD(&lftemp, doffset);
412 SAMPLE(doffset + fudge);
416 * refclock_process - process a sample from the clock
418 * This routine converts the timecode in the form days, hours, minutes,
419 * seconds and milliseconds/microseconds to internal timestamp format,
420 * then constructs a new entry in the median filter circular buffer.
421 * Return success (1) if the data are correct and consistent with the
422 * converntional calendar.
426 struct refclockproc *pp /* refclock structure pointer */
432 * Compute the timecode timestamp from the days, hours, minutes,
433 * seconds and milliseconds/microseconds of the timecode. Use
434 * clocktime() for the aggregate seconds and the msec/usec for
435 * the fraction, when present. Note that this code relies on the
436 * filesystem time for the years and does not use the years of
439 if (!clocktime(pp->day, pp->hour, pp->minute, pp->second, GMT,
440 pp->lastrec.l_ui, &pp->yearstart, &offset.l_ui))
443 DTOLFP(pp->nsec / 1e9, <emp);
444 L_ADD(&offset, <emp);
445 refclock_process_offset(pp, offset, pp->lastrec,
451 * refclock_sample - process a pile of samples from the clock
453 * This routine implements a recursive median filter to suppress spikes
454 * in the data, as well as determine a performance statistic. It
455 * calculates the mean offset and jitter (squares). A time adjustment
456 * fudgetime1 can be added to the final offset to compensate for various
457 * systematic errors. The routine returns the number of samples
458 * processed, which could be zero.
462 struct refclockproc *pp /* refclock structure pointer */
467 double off[MAXSTAGE];
470 * Copy the raw offsets and sort into ascending order. Don't do
471 * anything if the buffer is empty.
474 while (pp->codeproc != pp->coderecv) {
475 pp->codeproc = (pp->codeproc + 1) % MAXSTAGE;
476 off[n] = pp->filter[pp->codeproc];
482 qsort((char *)off, (size_t)n, sizeof(double), refclock_cmpl_fp);
485 * Reject the furthest from the median of the samples until
486 * approximately 60 percent of the samples remain.
489 m = n - (n * 2) / NSTAGE;
490 while ((j - i) > m) {
491 offset = off[(j + i) / 2];
492 if (off[j - 1] - offset < offset - off[i])
493 i++; /* reject low end */
495 j--; /* reject high end */
499 * Determine the offset and jitter.
502 for (k = i; k < j; k++)
504 pp->offset = offset / m;
506 pp->jitter = SQUARE(off[i] - off[j - 1]);
512 "refclock_sample: n %d offset %.6f disp %.6f jitter %.6f\n",
513 n, pp->offset, pp->disp, SQRT(pp->jitter));
520 * refclock_receive - simulate the receive and packet procedures
522 * This routine simulates the NTP receive and packet procedures for a
523 * reference clock. This provides a mechanism in which the ordinary NTP
524 * filter, selection and combining algorithms can be used to suppress
525 * misbehaving radios and to mitigate between them when more than one is
526 * available for backup.
530 struct peer *peer /* peer structure pointer */
533 struct refclockproc *pp;
537 printf("refclock_receive: at %lu %s\n",
538 current_time, stoa(&peer->srcadr));
542 * Do a little sanity dance and update the peer structure. Groom
543 * the median filter samples and give the data to the clock
549 peer->timereceived = current_time;
550 peer->leap = pp->leap;
551 if (peer->leap == LEAP_NOTINSYNC) {
552 refclock_report(peer, CEVNT_FAULT);
556 report_event(EVNT_REACH, peer);
558 peer->reftime = pp->lastref;
559 peer->org = pp->lastrec;
560 peer->rootdispersion = pp->disp;
561 get_systime(&peer->rec);
562 if (!refclock_sample(pp))
564 clock_filter(peer, pp->offset, 0., pp->jitter);
566 record_peer_stats(&peer->srcadr, ctlpeerstatus(peer),
567 peer->offset, peer->delay, clock_phi * (current_time -
568 peer->epoch), SQRT(peer->jitter));
569 if (cal_enable && last_offset < MINDISPERSE) {
571 if (peer != sys_peer || pll_status & STA_PPSTIME)
573 if (peer != sys_peer)
574 #endif /* KERNEL_PLL */
575 pp->fudgetime1 -= pp->offset * FUDGEFAC;
577 pp->fudgetime1 -= pp->fudgetime1 * FUDGEFAC;
582 * refclock_gtlin - groom next input line and extract timestamp
584 * This routine processes the timecode received from the clock and
585 * removes the parity bit and control characters. If a timestamp is
586 * present in the timecode, as produced by the tty_clk STREAMS module,
587 * it returns that as the timestamp; otherwise, it returns the buffer
588 * timestamp. The routine return code is the number of characters in
593 struct recvbuf *rbufp, /* receive buffer pointer */
594 char *lineptr, /* current line pointer */
595 int bmax, /* remaining characters in line */
596 l_fp *tsptr /* pointer to timestamp returned */
599 char *dpt, *dpend, *dp;
605 * Check for the presence of a timestamp left by the tty_clock
606 * module and, if present, use that instead of the buffer
607 * timestamp captured by the I/O routines. We recognize a
608 * timestamp by noting its value is earlier than the buffer
609 * timestamp, but not more than one second earlier.
611 dpt = (char *)rbufp->recv_buffer;
612 dpend = dpt + rbufp->recv_length;
613 trtmp = rbufp->recv_time;
615 if (dpend >= dpt + 8) {
616 if (buftvtots(dpend - 8, &tstmp)) {
617 L_SUB(&trtmp, &tstmp);
618 if (trtmp.l_ui == 0) {
622 "refclock_gtlin: fd %d ldisc %s",
623 rbufp->fd, lfptoa(&trtmp, 6));
625 L_SUB(&trtmp, &tstmp);
626 printf(" sigio %s\n", lfptoa(&trtmp, 6));
632 trtmp = rbufp->recv_time;
637 * Edit timecode to remove control chars. Don't monkey with the
638 * line buffer if the input buffer contains no ASCII printing
641 if (dpend - dpt > bmax - 1)
642 dpend = dpt + bmax - 1;
643 for (dp = lineptr; dpt < dpend; dpt++) {
644 c = (char) (*dpt & 0x7f);
654 printf("refclock_gtlin: fd %d time %s timecode %d %s\n",
655 rbufp->fd, ulfptoa(&trtmp, 6), i, lineptr);
657 printf("refclock_gtlin: fd %d time %s\n",
658 rbufp->fd, ulfptoa(&trtmp, 6));
666 * The following code does not apply to WINNT & VMS ...
668 #if !defined SYS_VXWORKS && !defined SYS_WINNT
669 #if defined(HAVE_TERMIOS) || defined(HAVE_SYSV_TTYS) || defined(HAVE_BSD_TTYS)
672 * refclock_open - open serial port for reference clock
674 * This routine opens a serial port for I/O and sets default options. It
675 * returns the file descriptor if success and zero if failure.
679 char *dev, /* device name pointer */
680 int speed, /* serial port speed (code) */
681 int lflags /* line discipline flags */
689 #endif /* TIOCMGET */
693 * Open serial port and set default options
705 fd = open(dev, omode, 0777);
708 msyslog(LOG_ERR, "refclock_open: %s: %m", dev);
713 * This little jewel lights up the PPS file descriptor if the
714 * device name matches the name in the pps line in the
715 * configuration file. This is so the atom driver can glom onto
716 * the right device. Very silly.
718 if (strcmp(dev, pps_device) == 0)
722 * The following sections initialize the serial line port in
723 * canonical (line-oriented) mode and set the specified line
724 * speed, 8 bits and no parity. The modem control, break, erase
725 * and kill functions are normally disabled. There is a
726 * different section for each terminal interface, as selected at
733 * POSIX serial line parameters (termios interface)
735 if (tcgetattr(fd, ttyp) < 0) {
737 "refclock_open: fd %d tcgetattr: %m", fd);
742 * Set canonical mode and local connection; set specified speed,
743 * 8 bits and no parity; map CR to NL; ignore break.
745 ttyp->c_iflag = IGNBRK | IGNPAR | ICRNL;
747 ttyp->c_cflag = CS8 | CLOCAL | CREAD;
748 (void)cfsetispeed(&ttyb, (u_int)speed);
749 (void)cfsetospeed(&ttyb, (u_int)speed);
750 ttyp->c_lflag = ICANON;
751 for (i = 0; i < NCCS; ++i)
753 ttyp->c_cc[i] = '\0';
759 if (flags & LDISC_RAW) {
762 ttyp->c_cc[VMIN] = 1;
764 #if defined(TIOCMGET) && !defined(SCO5_CLOCK)
766 * If we have modem control, check to see if modem leads are
767 * active; if so, set remote connection. This is necessary for
768 * the kernel pps mods to work.
771 if (ioctl(fd, TIOCMGET, (char *)<emp) < 0)
773 "refclock_open: fd %d TIOCMGET failed: %m", fd);
776 printf("refclock_open: fd %d modem status 0x%lx\n",
779 if (ltemp & TIOCM_DSR)
780 ttyp->c_cflag &= ~CLOCAL;
781 #endif /* TIOCMGET */
782 if (tcsetattr(fd, TCSANOW, ttyp) < 0) {
784 "refclock_open: fd %d TCSANOW failed: %m", fd);
787 if (tcflush(fd, TCIOFLUSH) < 0) {
789 "refclock_open: fd %d TCIOFLUSH failed: %m", fd);
792 #endif /* HAVE_TERMIOS */
794 #ifdef HAVE_SYSV_TTYS
797 * System V serial line parameters (termio interface)
800 if (ioctl(fd, TCGETA, ttyp) < 0) {
802 "refclock_open: fd %d TCGETA failed: %m", fd);
807 * Set canonical mode and local connection; set specified speed,
808 * 8 bits and no parity; map CR to NL; ignore break.
810 ttyp->c_iflag = IGNBRK | IGNPAR | ICRNL;
812 ttyp->c_cflag = speed | CS8 | CLOCAL | CREAD;
813 ttyp->c_lflag = ICANON;
814 ttyp->c_cc[VERASE] = ttyp->c_cc[VKILL] = '\0';
819 if (flags & LDISC_RAW) {
825 * If we have modem control, check to see if modem leads are
826 * active; if so, set remote connection. This is necessary for
827 * the kernel pps mods to work.
830 if (ioctl(fd, TIOCMGET, (char *)<emp) < 0)
832 "refclock_open: fd %d TIOCMGET failed: %m", fd);
835 printf("refclock_open: fd %d modem status %lx\n",
838 if (ltemp & TIOCM_DSR)
839 ttyp->c_cflag &= ~CLOCAL;
840 #endif /* TIOCMGET */
841 if (ioctl(fd, TCSETA, ttyp) < 0) {
843 "refclock_open: fd %d TCSETA failed: %m", fd);
846 #endif /* HAVE_SYSV_TTYS */
851 * 4.3bsd serial line parameters (sgttyb interface)
853 if (ioctl(fd, TIOCGETP, (char *)ttyp) < 0) {
855 "refclock_open: fd %d TIOCGETP %m", fd);
858 ttyp->sg_ispeed = ttyp->sg_ospeed = speed;
859 ttyp->sg_flags = EVENP | ODDP | CRMOD;
860 if (ioctl(fd, TIOCSETP, (char *)ttyp) < 0) {
862 "refclock_open: TIOCSETP failed: %m");
865 #endif /* HAVE_BSD_TTYS */
866 if (!refclock_ioctl(fd, flags)) {
869 "refclock_open: fd %d ioctl failed: %m", fd);
874 #endif /* HAVE_TERMIOS || HAVE_SYSV_TTYS || HAVE_BSD_TTYS */
875 #endif /* SYS_VXWORKS SYS_WINNT */
878 * refclock_ioctl - set serial port control functions
880 * This routine attempts to hide the internal, system-specific details
881 * of serial ports. It can handle POSIX (termios), SYSV (termio) and BSD
882 * (sgtty) interfaces with varying degrees of success. The routine sets
883 * up optional features such as tty_clk. The routine returns 1 if
884 * success and 0 if failure.
888 int fd, /* file descriptor */
889 int flags /* line discipline flags */
892 /* simply return 1 if no UNIX line discipline is supported */
893 #if !defined SYS_VXWORKS && !defined SYS_WINNT
894 #if defined(HAVE_TERMIOS) || defined(HAVE_SYSV_TTYS) || defined(HAVE_BSD_TTYS)
902 printf("refclock_ioctl: fd %d flags 0x%x\n", fd, flags);
906 #if !(defined(HAVE_TERMIOS) || defined(HAVE_BSD_TTYS))
907 if (flags & (LDISC_CLK | LDISC_PPS | LDISC_ACTS)) {
909 "refclock_ioctl: unsupported terminal interface");
912 #endif /* HAVE_TERMIOS HAVE_BSD_TTYS */
918 * The following features may or may not require System V
919 * STREAMS support, depending on the particular implementation.
923 * The TTYCLK option provides timestamping at the driver level.
924 * It requires the tty_clk streams module and System V STREAMS
925 * support. If not available, don't complain.
927 if (flags & (LDISC_CLK | LDISC_CLKPPS | LDISC_ACTS)) {
930 if (ioctl(fd, I_PUSH, "clk") < 0) {
932 "refclock_ioctl: I_PUSH clk failed: %m");
936 if (flags & LDISC_CLKPPS)
938 else if (flags & LDISC_ACTS)
943 if ((rval = ioctl(fd, CLK_SETSTR, str)) < 0)
945 "refclock_ioctl: CLK_SETSTR failed: %m");
947 printf("refclock_ioctl: fd %d CLK_SETSTR %d str %s\n",
953 #endif /* HAVE_TERMIOS || HAVE_SYSV_TTYS || HAVE_BSD_TTYS */
954 #endif /* SYS_VXWORKS SYS_WINNT */
959 * refclock_control - set and/or return clock values
961 * This routine is used mainly for debugging. It returns designated
962 * values from the interface structure that can be displayed using
963 * ntpdc and the clockstat command. It can also be used to initialize
964 * configuration variables, such as fudgetimes, fudgevalues, reference
969 struct sockaddr_storage *srcadr,
970 struct refclockstat *in,
971 struct refclockstat *out
975 struct refclockproc *pp;
980 * Check for valid address and running peer
982 if (srcadr->ss_family != AF_INET)
984 if (!ISREFCLOCKADR(srcadr))
986 clktype = (u_char)REFCLOCKTYPE(srcadr);
987 unit = REFCLOCKUNIT(srcadr);
988 if (clktype >= num_refclock_conf || unit >= MAXUNIT)
990 peer = typeunit[clktype][unit];
993 if (peer->procptr == NULL)
998 * Initialize requested data
1001 if (in->haveflags & CLK_HAVETIME1)
1002 pp->fudgetime1 = in->fudgetime1;
1003 if (in->haveflags & CLK_HAVETIME2)
1004 pp->fudgetime2 = in->fudgetime2;
1005 if (in->haveflags & CLK_HAVEVAL1)
1006 pp->stratum = (u_char) in->fudgeval1;
1007 if (in->haveflags & CLK_HAVEVAL2)
1008 pp->refid = in->fudgeval2;
1009 peer->stratum = pp->stratum;
1010 if (peer->stratum == STRATUM_REFCLOCK || peer->stratum ==
1012 peer->refid = pp->refid;
1014 peer->refid = ((struct
1015 sockaddr_in*)&peer->srcadr)->sin_addr.s_addr;
1016 if (in->haveflags & CLK_HAVEFLAG1) {
1017 pp->sloppyclockflag &= ~CLK_FLAG1;
1018 pp->sloppyclockflag |= in->flags & CLK_FLAG1;
1020 if (in->haveflags & CLK_HAVEFLAG2) {
1021 pp->sloppyclockflag &= ~CLK_FLAG2;
1022 pp->sloppyclockflag |= in->flags & CLK_FLAG2;
1024 if (in->haveflags & CLK_HAVEFLAG3) {
1025 pp->sloppyclockflag &= ~CLK_FLAG3;
1026 pp->sloppyclockflag |= in->flags & CLK_FLAG3;
1028 if (in->haveflags & CLK_HAVEFLAG4) {
1029 pp->sloppyclockflag &= ~CLK_FLAG4;
1030 pp->sloppyclockflag |= in->flags & CLK_FLAG4;
1035 * Readback requested data
1038 out->haveflags = CLK_HAVETIME1 | CLK_HAVEVAL1 |
1039 CLK_HAVEVAL2 | CLK_HAVEFLAG4;
1040 out->fudgetime1 = pp->fudgetime1;
1041 out->fudgetime2 = pp->fudgetime2;
1042 out->fudgeval1 = pp->stratum;
1043 out->fudgeval2 = pp->refid;
1044 out->flags = (u_char) pp->sloppyclockflag;
1046 out->timereset = current_time - pp->timestarted;
1047 out->polls = pp->polls;
1048 out->noresponse = pp->noreply;
1049 out->badformat = pp->badformat;
1050 out->baddata = pp->baddata;
1052 out->lastevent = pp->lastevent;
1053 out->currentstatus = pp->currentstatus;
1054 out->type = pp->type;
1055 out->clockdesc = pp->clockdesc;
1056 out->lencode = pp->lencode;
1057 out->p_lastcode = pp->a_lastcode;
1061 * Give the stuff to the clock
1063 if (refclock_conf[clktype]->clock_control != noentry)
1064 (refclock_conf[clktype]->clock_control)(unit, in, out, peer);
1069 * refclock_buginfo - return debugging info
1071 * This routine is used mainly for debugging. It returns designated
1072 * values from the interface structure that can be displayed using
1073 * ntpdc and the clkbug command.
1077 struct sockaddr_storage *srcadr, /* clock address */
1078 struct refclockbug *bug /* output structure */
1082 struct refclockproc *pp;
1088 * Check for valid address and peer structure
1090 if (srcadr->ss_family != AF_INET)
1092 if (!ISREFCLOCKADR(srcadr))
1094 clktype = (u_char) REFCLOCKTYPE(srcadr);
1095 unit = REFCLOCKUNIT(srcadr);
1096 if (clktype >= num_refclock_conf || unit >= MAXUNIT)
1098 peer = typeunit[clktype][unit];
1104 * Copy structure values
1107 bug->svalues = 0x0000003f;
1108 bug->values[0] = pp->year;
1109 bug->values[1] = pp->day;
1110 bug->values[2] = pp->hour;
1111 bug->values[3] = pp->minute;
1112 bug->values[4] = pp->second;
1113 bug->values[5] = pp->nsec;
1114 bug->values[6] = pp->yearstart;
1115 bug->values[7] = pp->coderecv;
1116 bug->stimes = 0xfffffffc;
1117 bug->times[0] = pp->lastref;
1118 bug->times[1] = pp->lastrec;
1119 for (i = 2; i < (int)bug->ntimes; i++)
1120 DTOLFP(pp->filter[i - 2], &bug->times[i]);
1123 * Give the stuff to the clock
1125 if (refclock_conf[clktype]->clock_buginfo != noentry)
1126 (refclock_conf[clktype]->clock_buginfo)(unit, bug, peer);
1129 #endif /* REFCLOCK */