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