diff options
author | roberto <roberto@FreeBSD.org> | 2008-08-17 17:37:33 +0000 |
---|---|---|
committer | roberto <roberto@FreeBSD.org> | 2008-08-17 17:37:33 +0000 |
commit | 4ded1c1fa0bc21c61f91a2dbe864835986745121 (patch) | |
tree | 16d100fbc9dae63888d48b464e471ba0e5065193 /contrib/ntp/ntpd/ntp_refclock.c | |
parent | 8b5a86d4fda08a9c68231415812edcb26be52f79 (diff) | |
download | FreeBSD-src-4ded1c1fa0bc21c61f91a2dbe864835986745121.zip FreeBSD-src-4ded1c1fa0bc21c61f91a2dbe864835986745121.tar.gz |
Flatten the dist and various 4.n.n trees in preparation of future ntp imports.
Diffstat (limited to 'contrib/ntp/ntpd/ntp_refclock.c')
-rw-r--r-- | contrib/ntp/ntpd/ntp_refclock.c | 1129 |
1 files changed, 0 insertions, 1129 deletions
diff --git a/contrib/ntp/ntpd/ntp_refclock.c b/contrib/ntp/ntpd/ntp_refclock.c deleted file mode 100644 index 172fbda..0000000 --- a/contrib/ntp/ntpd/ntp_refclock.c +++ /dev/null @@ -1,1129 +0,0 @@ -/* - * ntp_refclock - processing support for reference clocks - */ -#ifdef HAVE_CONFIG_H -# include <config.h> -#endif - -#include "ntpd.h" -#include "ntp_io.h" -#include "ntp_unixtime.h" -#include "ntp_tty.h" -#include "ntp_refclock.h" -#include "ntp_stdlib.h" - -#include <stdio.h> - -#ifdef HAVE_SYS_IOCTL_H -# include <sys/ioctl.h> -#endif /* HAVE_SYS_IOCTL_H */ - -#ifdef REFCLOCK - -#ifdef TTYCLK -# ifdef HAVE_SYS_CLKDEFS_H -# include <sys/clkdefs.h> -# include <stropts.h> -# endif -# ifdef HAVE_SYS_SIO_H -# include <sys/sio.h> -# endif -#endif /* TTYCLK */ - -#ifdef HAVE_PPSCLOCK_H -#include <sys/ppsclock.h> -#endif /* HAVE_PPSCLOCK_H */ - -#ifdef KERNEL_PLL -#include "ntp_syscall.h" -#endif /* KERNEL_PLL */ - -/* - * Reference clock support is provided here by maintaining the fiction - * that the clock is actually a peer. As no packets are exchanged with a - * reference clock, however, we replace the transmit, receive and packet - * procedures with separate code to simulate them. Routines - * refclock_transmit() and refclock_receive() maintain the peer - * variables in a state analogous to an actual peer and pass reference - * clock data on through the filters. Routines refclock_peer() and - * refclock_unpeer() are called to initialize and terminate reference - * clock associations. A set of utility routines is included to open - * serial devices, process sample data, edit input lines to extract - * embedded timestamps and to peform various debugging functions. - * - * The main interface used by these routines is the refclockproc - * structure, which contains for most drivers the decimal equivalants of - * the year, day, month, hour, second and millisecond/microsecond - * decoded from the ASCII timecode. Additional information includes the - * receive timestamp, exception report, statistics tallies, etc. In - * addition, there may be a driver-specific unit structure used for - * local control of the device. - * - * The support routines are passed a pointer to the peer structure, - * which is used for all peer-specific processing and contains a pointer - * to the refclockproc structure, which in turn containes a pointer to - * the unit structure, if used. The peer structure is identified by an - * interface address in the dotted quad form 127.127.t.u (for now only IPv4 - * addresses are used, so we need to be sure the address is it), where t is - * the clock type and u the unit. Some legacy drivers derive the - * refclockproc structure pointer from the table typeunit[type][unit]. - * This interface is strongly discouraged and may be abandoned in - * future. - */ -#define MAXUNIT 4 /* max units */ -#define FUDGEFAC .1 /* fudge correction factor */ - -int fdpps; /* pps file descriptor */ -int cal_enable; /* enable refclock calibrate */ - -/* - * Type/unit peer index. Used to find the peer structure for control and - * debugging. When all clock drivers have been converted to new style, - * this dissapears. - */ -static struct peer *typeunit[REFCLK_MAX + 1][MAXUNIT]; - -/* - * Forward declarations - */ -#ifdef QSORT_USES_VOID_P -static int refclock_cmpl_fp P((const void *, const void *)); -#else -static int refclock_cmpl_fp P((const double *, const double *)); -#endif /* QSORT_USES_VOID_P */ -static int refclock_sample P((struct refclockproc *)); - -/* - * refclock_report - note the occurance of an event - * - * This routine presently just remembers the report and logs it, but - * does nothing heroic for the trap handler. It tries to be a good - * citizen and bothers the system log only if things change. - */ -void -refclock_report( - struct peer *peer, - int code - ) -{ - struct refclockproc *pp; - - pp = peer->procptr; - if (pp == NULL) - return; - if (code == CEVNT_BADREPLY) - pp->badformat++; - if (code == CEVNT_BADTIME) - pp->baddata++; - if (code == CEVNT_TIMEOUT) - pp->noreply++; - if (pp->currentstatus != code) { - pp->currentstatus = (u_char)code; - pp->lastevent = (u_char)code; - if (code == CEVNT_FAULT) - msyslog(LOG_ERR, - "clock %s event '%s' (0x%02x)", - refnumtoa(&peer->srcadr), - ceventstr(code), code); - else { - NLOG(NLOG_CLOCKEVENT) - msyslog(LOG_INFO, - "clock %s event '%s' (0x%02x)", - refnumtoa(&peer->srcadr), - ceventstr(code), code); - } - } -#ifdef DEBUG - if (debug) - printf("clock %s event '%s' (0x%02x)\n", - refnumtoa(&peer->srcadr), - ceventstr(code), code); -#endif -} - - -/* - * init_refclock - initialize the reference clock drivers - * - * This routine calls each of the drivers in turn to initialize internal - * variables, if necessary. Most drivers have nothing to say at this - * point. - */ -void -init_refclock(void) -{ - int i, j; - - for (i = 0; i < (int)num_refclock_conf; i++) { - if (refclock_conf[i]->clock_init != noentry) - (refclock_conf[i]->clock_init)(); - for (j = 0; j < MAXUNIT; j++) - typeunit[i][j] = 0; - } -} - - -/* - * refclock_newpeer - initialize and start a reference clock - * - * This routine allocates and initializes the interface structure which - * supports a reference clock in the form of an ordinary NTP peer. A - * driver-specific support routine completes the initialization, if - * used. Default peer variables which identify the clock and establish - * its reference ID and stratum are set here. It returns one if success - * and zero if the clock address is invalid or already running, - * insufficient resources are available or the driver declares a bum - * rap. - */ -int -refclock_newpeer( - struct peer *peer /* peer structure pointer */ - ) -{ - struct refclockproc *pp; - u_char clktype; - int unit; - - /* - * Check for valid clock address. If already running, shut it - * down first. - */ - if (peer->srcadr.ss_family != AF_INET) { - msyslog(LOG_ERR, - "refclock_newpeer: clock address %s invalid, address family not implemented for refclock", - stoa(&peer->srcadr)); - return (0); - } - if (!ISREFCLOCKADR(&peer->srcadr)) { - msyslog(LOG_ERR, - "refclock_newpeer: clock address %s invalid", - stoa(&peer->srcadr)); - return (0); - } - clktype = (u_char)REFCLOCKTYPE(&peer->srcadr); - unit = REFCLOCKUNIT(&peer->srcadr); - if (clktype >= num_refclock_conf || unit >= MAXUNIT || - refclock_conf[clktype]->clock_start == noentry) { - msyslog(LOG_ERR, - "refclock_newpeer: clock type %d invalid\n", - clktype); - return (0); - } - - /* - * Allocate and initialize interface structure - */ - pp = (struct refclockproc *)emalloc(sizeof(struct refclockproc)); - if (pp == NULL) - return (0); - memset((char *)pp, 0, sizeof(struct refclockproc)); - typeunit[clktype][unit] = peer; - peer->procptr = pp; - - /* - * Initialize structures - */ - peer->refclktype = clktype; - peer->refclkunit = (u_char)unit; - peer->flags |= FLAG_REFCLOCK; - peer->maxpoll = peer->minpoll; - peer->stratum = STRATUM_REFCLOCK; - pp->type = clktype; - pp->timestarted = current_time; - - /* - * Set peer.pmode based on the hmode. For appearances only. - */ - switch (peer->hmode) { - case MODE_ACTIVE: - peer->pmode = MODE_PASSIVE; - break; - - default: - peer->pmode = MODE_SERVER; - break; - } - - /* - * Do driver dependent initialization. The above defaults - * can be wiggled, then finish up for consistency. - */ - if (!((refclock_conf[clktype]->clock_start)(unit, peer))) { - refclock_unpeer(peer); - return (0); - } - peer->hpoll = peer->minpoll; - peer->ppoll = peer->maxpoll; - peer->refid = pp->refid; - return (1); -} - - -/* - * refclock_unpeer - shut down a clock - */ -void -refclock_unpeer( - struct peer *peer /* peer structure pointer */ - ) -{ - u_char clktype; - int unit; - - /* - * Wiggle the driver to release its resources, then give back - * the interface structure. - */ - if (!peer->procptr) - return; - clktype = peer->refclktype; - unit = peer->refclkunit; - if (refclock_conf[clktype]->clock_shutdown != noentry) - (refclock_conf[clktype]->clock_shutdown)(unit, peer); - free(peer->procptr); - peer->procptr = 0; -} - - -/* - * refclock_transmit - simulate the transmit procedure - * - * This routine implements the NTP transmit procedure for a reference - * clock. This provides a mechanism to call the driver at the NTP poll - * interval, as well as provides a reachability mechanism to detect a - * broken radio or other madness. - */ -void -refclock_transmit( - struct peer *peer /* peer structure pointer */ - ) -{ - u_char clktype; - int unit; - u_long next; - - clktype = peer->refclktype; - unit = peer->refclkunit; - peer->sent++; - - /* - * This is a ripoff of the peer transmit routine, but - * specialized for reference clocks. We do a little less - * protocol here and call the driver-specific transmit routine. - */ - next = peer->outdate; - if (peer->burst == 0) { - u_char oreach; -#ifdef DEBUG - if (debug) - printf("refclock_transmit: at %ld %s\n", - current_time, stoa(&(peer->srcadr))); -#endif - - /* - * Update reachability and poll variables like the - * network code. - */ - oreach = peer->reach; - peer->reach <<= 1; - if (!peer->reach) { - if (oreach) { - report_event(EVNT_UNREACH, peer); - peer->timereachable = current_time; - peer_clear(peer, "NONE"); - } - } else { - if (!(oreach & 0x03)) { - clock_filter(peer, 0., 0., MAXDISPERSE); - clock_select(); - } - if (peer->flags & FLAG_BURST) - peer->burst = NSTAGE; - } - next = current_time; - } - get_systime(&peer->xmt); - if (refclock_conf[clktype]->clock_poll != noentry) - (refclock_conf[clktype]->clock_poll)(unit, peer); - peer->outdate = next; - if (peer->burst > 0) - peer->burst--; - poll_update(peer, 0); -} - - -/* - * Compare two doubles - used with qsort() - */ -#ifdef QSORT_USES_VOID_P -static int -refclock_cmpl_fp( - const void *p1, - const void *p2 - ) -{ - const double *dp1 = (const double *)p1; - const double *dp2 = (const double *)p2; - - if (*dp1 < *dp2) - return (-1); - if (*dp1 > *dp2) - return (1); - return (0); -} -#else -static int -refclock_cmpl_fp( - const double *dp1, - const double *dp2 - ) -{ - if (*dp1 < *dp2) - return (-1); - if (*dp1 > *dp2) - return (1); - return (0); -} -#endif /* QSORT_USES_VOID_P */ - - -/* - * refclock_process_offset - update median filter - * - * This routine uses the given offset and timestamps to construct a new - * entry in the median filter circular buffer. Samples that overflow the - * filter are quietly discarded. - */ -void -refclock_process_offset( - struct refclockproc *pp, /* refclock structure pointer */ - l_fp lasttim, /* last timecode timestamp */ - l_fp lastrec, /* last receive timestamp */ - double fudge - ) -{ - l_fp lftemp; - double doffset; - - pp->lastrec = lastrec; - lftemp = lasttim; - L_SUB(&lftemp, &lastrec); - LFPTOD(&lftemp, doffset); - SAMPLE(doffset + fudge); -} - -/* - * refclock_process - process a sample from the clock - * - * This routine converts the timecode in the form days, hours, minutes, - * seconds and milliseconds/microseconds to internal timestamp format, - * then constructs a new entry in the median filter circular buffer. - * Return success (1) if the data are correct and consistent with the - * converntional calendar. -*/ -int -refclock_process( - struct refclockproc *pp /* refclock structure pointer */ - ) -{ - l_fp offset, ltemp; - - /* - * Compute the timecode timestamp from the days, hours, minutes, - * seconds and milliseconds/microseconds of the timecode. Use - * clocktime() for the aggregate seconds and the msec/usec for - * the fraction, when present. Note that this code relies on the - * filesystem time for the years and does not use the years of - * the timecode. - */ - if (!clocktime(pp->day, pp->hour, pp->minute, pp->second, GMT, - pp->lastrec.l_ui, &pp->yearstart, &offset.l_ui)) - return (0); - offset.l_uf = 0; - DTOLFP(pp->nsec / 1e9, <emp); - L_ADD(&offset, <emp); - refclock_process_offset(pp, offset, pp->lastrec, - pp->fudgetime1); - return (1); -} - -/* - * refclock_sample - process a pile of samples from the clock - * - * This routine implements a recursive median filter to suppress spikes - * in the data, as well as determine a performance statistic. It - * calculates the mean offset and jitter (squares). A time adjustment - * fudgetime1 can be added to the final offset to compensate for various - * systematic errors. The routine returns the number of samples - * processed, which could be zero. - */ -static int -refclock_sample( - struct refclockproc *pp /* refclock structure pointer */ - ) -{ - int i, j, k, m, n; - double offset; - double off[MAXSTAGE]; - - /* - * Copy the raw offsets and sort into ascending order. Don't do - * anything if the buffer is empty. - */ - n = 0; - while (pp->codeproc != pp->coderecv) { - pp->codeproc = (pp->codeproc + 1) % MAXSTAGE; - off[n] = pp->filter[pp->codeproc]; - n++; - } - if (n == 0) - return (0); - if (n > 1) - qsort((char *)off, (size_t)n, sizeof(double), refclock_cmpl_fp); - - /* - * Reject the furthest from the median of the samples until - * approximately 60 percent of the samples remain. - */ - i = 0; j = n; - m = n - (n * 2) / NSTAGE; - while ((j - i) > m) { - offset = off[(j + i) / 2]; - if (off[j - 1] - offset < offset - off[i]) - i++; /* reject low end */ - else - j--; /* reject high end */ - } - - /* - * Determine the offset and jitter. - */ - offset = 0; - for (k = i; k < j; k++) - offset += off[k]; - pp->offset = offset / m; - if (m > 1) - pp->jitter = SQUARE(off[i] - off[j - 1]); - else - pp->jitter = 0; -#ifdef DEBUG - if (debug) - printf( - "refclock_sample: n %d offset %.6f disp %.6f jitter %.6f\n", - n, pp->offset, pp->disp, SQRT(pp->jitter)); -#endif - return (n); -} - - -/* - * refclock_receive - simulate the receive and packet procedures - * - * This routine simulates the NTP receive and packet procedures for a - * reference clock. This provides a mechanism in which the ordinary NTP - * filter, selection and combining algorithms can be used to suppress - * misbehaving radios and to mitigate between them when more than one is - * available for backup. - */ -void -refclock_receive( - struct peer *peer /* peer structure pointer */ - ) -{ - struct refclockproc *pp; - -#ifdef DEBUG - if (debug) - printf("refclock_receive: at %lu %s\n", - current_time, stoa(&peer->srcadr)); -#endif - - /* - * Do a little sanity dance and update the peer structure. Groom - * the median filter samples and give the data to the clock - * filter. - */ - peer->received++; - pp = peer->procptr; - peer->processed++; - peer->timereceived = current_time; - peer->leap = pp->leap; - if (peer->leap == LEAP_NOTINSYNC) { - refclock_report(peer, CEVNT_FAULT); - return; - } - if (!peer->reach) - report_event(EVNT_REACH, peer); - peer->reach |= 1; - peer->reftime = pp->lastref; - peer->org = pp->lastrec; - peer->rootdispersion = pp->disp; - get_systime(&peer->rec); - if (!refclock_sample(pp)) - return; - clock_filter(peer, pp->offset, 0., pp->jitter); - clock_select(); - record_peer_stats(&peer->srcadr, ctlpeerstatus(peer), - peer->offset, peer->delay, clock_phi * (current_time - - peer->epoch), SQRT(peer->jitter)); - if (cal_enable && last_offset < MINDISPERSE) { -#ifdef KERNEL_PLL - if (peer != sys_peer || pll_status & STA_PPSTIME) -#else - if (peer != sys_peer) -#endif /* KERNEL_PLL */ - pp->fudgetime1 -= pp->offset * FUDGEFAC; - else - pp->fudgetime1 -= pp->fudgetime1 * FUDGEFAC; - } -} - -/* - * refclock_gtlin - groom next input line and extract timestamp - * - * This routine processes the timecode received from the clock and - * removes the parity bit and control characters. If a timestamp is - * present in the timecode, as produced by the tty_clk STREAMS module, - * it returns that as the timestamp; otherwise, it returns the buffer - * timestamp. The routine return code is the number of characters in - * the line. - */ -int -refclock_gtlin( - struct recvbuf *rbufp, /* receive buffer pointer */ - char *lineptr, /* current line pointer */ - int bmax, /* remaining characters in line */ - l_fp *tsptr /* pointer to timestamp returned */ - ) -{ - char *dpt, *dpend, *dp; - int i; - l_fp trtmp, tstmp; - char c; - - /* - * Check for the presence of a timestamp left by the tty_clock - * module and, if present, use that instead of the buffer - * timestamp captured by the I/O routines. We recognize a - * timestamp by noting its value is earlier than the buffer - * timestamp, but not more than one second earlier. - */ - dpt = (char *)rbufp->recv_buffer; - dpend = dpt + rbufp->recv_length; - trtmp = rbufp->recv_time; - - if (dpend >= dpt + 8) { - if (buftvtots(dpend - 8, &tstmp)) { - L_SUB(&trtmp, &tstmp); - if (trtmp.l_ui == 0) { -#ifdef DEBUG - if (debug > 1) { - printf( - "refclock_gtlin: fd %d ldisc %s", - rbufp->fd, lfptoa(&trtmp, 6)); - get_systime(&trtmp); - L_SUB(&trtmp, &tstmp); - printf(" sigio %s\n", lfptoa(&trtmp, 6)); - } -#endif - dpend -= 8; - trtmp = tstmp; - } else - trtmp = rbufp->recv_time; - } - } - - /* - * Edit timecode to remove control chars. Don't monkey with the - * line buffer if the input buffer contains no ASCII printing - * characters. - */ - if (dpend - dpt > bmax - 1) - dpend = dpt + bmax - 1; - for (dp = lineptr; dpt < dpend; dpt++) { - c = (char) (*dpt & 0x7f); - if (c >= ' ') - *dp++ = c; - } - i = dp - lineptr; - if (i > 0) - *dp = '\0'; -#ifdef DEBUG - if (debug > 1) { - if (i > 0) - printf("refclock_gtlin: fd %d time %s timecode %d %s\n", - rbufp->fd, ulfptoa(&trtmp, 6), i, lineptr); - else - printf("refclock_gtlin: fd %d time %s\n", - rbufp->fd, ulfptoa(&trtmp, 6)); - } -#endif - *tsptr = trtmp; - return (i); -} - -/* - * The following code does not apply to WINNT & VMS ... - */ -#if !defined SYS_VXWORKS && !defined SYS_WINNT -#if defined(HAVE_TERMIOS) || defined(HAVE_SYSV_TTYS) || defined(HAVE_BSD_TTYS) - -/* - * refclock_open - open serial port for reference clock - * - * This routine opens a serial port for I/O and sets default options. It - * returns the file descriptor if success and zero if failure. - */ -int -refclock_open( - char *dev, /* device name pointer */ - int speed, /* serial port speed (code) */ - int lflags /* line discipline flags */ - ) -{ - int fd, i; - int flags; - TTY ttyb, *ttyp; -#ifdef TIOCMGET - u_long ltemp; -#endif /* TIOCMGET */ - int omode; - - /* - * Open serial port and set default options - */ - flags = lflags; - - omode = O_RDWR; -#ifdef O_NONBLOCK - omode |= O_NONBLOCK; -#endif -#ifdef O_NOCTTY - omode |= O_NOCTTY; -#endif - - fd = open(dev, omode, 0777); - - if (fd < 0) { - msyslog(LOG_ERR, "refclock_open: %s: %m", dev); - return (0); - } - - /* - * This little jewel lights up the PPS file descriptor if the - * device name matches the name in the pps line in the - * configuration file. This is so the atom driver can glom onto - * the right device. Very silly. - */ - if (strcmp(dev, pps_device) == 0) - fdpps = fd; - - /* - * The following sections initialize the serial line port in - * canonical (line-oriented) mode and set the specified line - * speed, 8 bits and no parity. The modem control, break, erase - * and kill functions are normally disabled. There is a - * different section for each terminal interface, as selected at - * compile time. - */ - ttyp = &ttyb; - -#ifdef HAVE_TERMIOS - /* - * POSIX serial line parameters (termios interface) - */ - if (tcgetattr(fd, ttyp) < 0) { - msyslog(LOG_ERR, - "refclock_open: fd %d tcgetattr: %m", fd); - return (0); - } - - /* - * Set canonical mode and local connection; set specified speed, - * 8 bits and no parity; map CR to NL; ignore break. - */ - ttyp->c_iflag = IGNBRK | IGNPAR | ICRNL; - ttyp->c_oflag = 0; - ttyp->c_cflag = CS8 | CLOCAL | CREAD; - (void)cfsetispeed(&ttyb, (u_int)speed); - (void)cfsetospeed(&ttyb, (u_int)speed); - ttyp->c_lflag = ICANON; - for (i = 0; i < NCCS; ++i) - { - ttyp->c_cc[i] = '\0'; - } - - /* - * Some special cases - */ - if (flags & LDISC_RAW) { - ttyp->c_iflag = 0; - ttyp->c_lflag = 0; - ttyp->c_cc[VMIN] = 1; - } -#if defined(TIOCMGET) && !defined(SCO5_CLOCK) - /* - * If we have modem control, check to see if modem leads are - * active; if so, set remote connection. This is necessary for - * the kernel pps mods to work. - */ - ltemp = 0; - if (ioctl(fd, TIOCMGET, (char *)<emp) < 0) - msyslog(LOG_ERR, - "refclock_open: fd %d TIOCMGET failed: %m", fd); -#ifdef DEBUG - if (debug) - printf("refclock_open: fd %d modem status 0x%lx\n", - fd, ltemp); -#endif - if (ltemp & TIOCM_DSR) - ttyp->c_cflag &= ~CLOCAL; -#endif /* TIOCMGET */ - if (tcsetattr(fd, TCSANOW, ttyp) < 0) { - msyslog(LOG_ERR, - "refclock_open: fd %d TCSANOW failed: %m", fd); - return (0); - } - if (tcflush(fd, TCIOFLUSH) < 0) { - msyslog(LOG_ERR, - "refclock_open: fd %d TCIOFLUSH failed: %m", fd); - return (0); - } -#endif /* HAVE_TERMIOS */ - -#ifdef HAVE_SYSV_TTYS - - /* - * System V serial line parameters (termio interface) - * - */ - if (ioctl(fd, TCGETA, ttyp) < 0) { - msyslog(LOG_ERR, - "refclock_open: fd %d TCGETA failed: %m", fd); - return (0); - } - - /* - * Set canonical mode and local connection; set specified speed, - * 8 bits and no parity; map CR to NL; ignore break. - */ - ttyp->c_iflag = IGNBRK | IGNPAR | ICRNL; - ttyp->c_oflag = 0; - ttyp->c_cflag = speed | CS8 | CLOCAL | CREAD; - ttyp->c_lflag = ICANON; - ttyp->c_cc[VERASE] = ttyp->c_cc[VKILL] = '\0'; - - /* - * Some special cases - */ - if (flags & LDISC_RAW) { - ttyp->c_iflag = 0; - ttyp->c_lflag = 0; - } -#ifdef TIOCMGET - /* - * If we have modem control, check to see if modem leads are - * active; if so, set remote connection. This is necessary for - * the kernel pps mods to work. - */ - ltemp = 0; - if (ioctl(fd, TIOCMGET, (char *)<emp) < 0) - msyslog(LOG_ERR, - "refclock_open: fd %d TIOCMGET failed: %m", fd); -#ifdef DEBUG - if (debug) - printf("refclock_open: fd %d modem status %lx\n", - fd, ltemp); -#endif - if (ltemp & TIOCM_DSR) - ttyp->c_cflag &= ~CLOCAL; -#endif /* TIOCMGET */ - if (ioctl(fd, TCSETA, ttyp) < 0) { - msyslog(LOG_ERR, - "refclock_open: fd %d TCSETA failed: %m", fd); - return (0); - } -#endif /* HAVE_SYSV_TTYS */ - -#ifdef HAVE_BSD_TTYS - - /* - * 4.3bsd serial line parameters (sgttyb interface) - */ - if (ioctl(fd, TIOCGETP, (char *)ttyp) < 0) { - msyslog(LOG_ERR, - "refclock_open: fd %d TIOCGETP %m", fd); - return (0); - } - ttyp->sg_ispeed = ttyp->sg_ospeed = speed; - ttyp->sg_flags = EVENP | ODDP | CRMOD; - if (ioctl(fd, TIOCSETP, (char *)ttyp) < 0) { - msyslog(LOG_ERR, - "refclock_open: TIOCSETP failed: %m"); - return (0); - } -#endif /* HAVE_BSD_TTYS */ - if (!refclock_ioctl(fd, flags)) { - (void)close(fd); - msyslog(LOG_ERR, - "refclock_open: fd %d ioctl failed: %m", fd); - return (0); - } - return (fd); -} -#endif /* HAVE_TERMIOS || HAVE_SYSV_TTYS || HAVE_BSD_TTYS */ -#endif /* SYS_VXWORKS SYS_WINNT */ - -/* - * refclock_ioctl - set serial port control functions - * - * This routine attempts to hide the internal, system-specific details - * of serial ports. It can handle POSIX (termios), SYSV (termio) and BSD - * (sgtty) interfaces with varying degrees of success. The routine sets - * up optional features such as tty_clk. The routine returns 1 if - * success and 0 if failure. - */ -int -refclock_ioctl( - int fd, /* file descriptor */ - int flags /* line discipline flags */ - ) -{ - /* simply return 1 if no UNIX line discipline is supported */ -#if !defined SYS_VXWORKS && !defined SYS_WINNT -#if defined(HAVE_TERMIOS) || defined(HAVE_SYSV_TTYS) || defined(HAVE_BSD_TTYS) - -#ifdef TTYCLK - TTY ttyb, *ttyp; -#endif /* TTYCLK */ - -#ifdef DEBUG - if (debug) - printf("refclock_ioctl: fd %d flags 0x%x\n", fd, flags); -#endif - if (flags == 0) - return (1); -#if !(defined(HAVE_TERMIOS) || defined(HAVE_BSD_TTYS)) - if (flags & (LDISC_CLK | LDISC_PPS | LDISC_ACTS)) { - msyslog(LOG_ERR, - "refclock_ioctl: unsupported terminal interface"); - return (0); - } -#endif /* HAVE_TERMIOS HAVE_BSD_TTYS */ -#ifdef TTYCLK - ttyp = &ttyb; -#endif /* TTYCLK */ - - /* - * The following features may or may not require System V - * STREAMS support, depending on the particular implementation. - */ -#if defined(TTYCLK) - /* - * The TTYCLK option provides timestamping at the driver level. - * It requires the tty_clk streams module and System V STREAMS - * support. If not available, don't complain. - */ - if (flags & (LDISC_CLK | LDISC_CLKPPS | LDISC_ACTS)) { - int rval = 0; - - if (ioctl(fd, I_PUSH, "clk") < 0) { - msyslog(LOG_NOTICE, - "refclock_ioctl: I_PUSH clk failed: %m"); - } else { - char *str; - - if (flags & LDISC_CLKPPS) - str = "\377"; - else if (flags & LDISC_ACTS) - str = "*"; - else - str = "\n"; -#ifdef CLK_SETSTR - if ((rval = ioctl(fd, CLK_SETSTR, str)) < 0) - msyslog(LOG_ERR, - "refclock_ioctl: CLK_SETSTR failed: %m"); - if (debug) - printf("refclock_ioctl: fd %d CLK_SETSTR %d str %s\n", - fd, rval, str); -#endif - } - } -#endif /* TTYCLK */ -#endif /* HAVE_TERMIOS || HAVE_SYSV_TTYS || HAVE_BSD_TTYS */ -#endif /* SYS_VXWORKS SYS_WINNT */ - return (1); -} - -/* - * refclock_control - set and/or return clock values - * - * This routine is used mainly for debugging. It returns designated - * values from the interface structure that can be displayed using - * ntpdc and the clockstat command. It can also be used to initialize - * configuration variables, such as fudgetimes, fudgevalues, reference - * ID and stratum. - */ -void -refclock_control( - struct sockaddr_storage *srcadr, - struct refclockstat *in, - struct refclockstat *out - ) -{ - struct peer *peer; - struct refclockproc *pp; - u_char clktype; - int unit; - - /* - * Check for valid address and running peer - */ - if (srcadr->ss_family != AF_INET) - return; - if (!ISREFCLOCKADR(srcadr)) - return; - clktype = (u_char)REFCLOCKTYPE(srcadr); - unit = REFCLOCKUNIT(srcadr); - if (clktype >= num_refclock_conf || unit >= MAXUNIT) - return; - peer = typeunit[clktype][unit]; - if (peer == NULL) - return; - if (peer->procptr == NULL) - return; - pp = peer->procptr; - - /* - * Initialize requested data - */ - if (in != 0) { - if (in->haveflags & CLK_HAVETIME1) - pp->fudgetime1 = in->fudgetime1; - if (in->haveflags & CLK_HAVETIME2) - pp->fudgetime2 = in->fudgetime2; - if (in->haveflags & CLK_HAVEVAL1) - pp->stratum = (u_char) in->fudgeval1; - if (in->haveflags & CLK_HAVEVAL2) - pp->refid = in->fudgeval2; - peer->stratum = pp->stratum; - if (peer->stratum == STRATUM_REFCLOCK || peer->stratum == - STRATUM_UNSPEC) - peer->refid = pp->refid; - else - peer->refid = ((struct - sockaddr_in*)&peer->srcadr)->sin_addr.s_addr; - if (in->haveflags & CLK_HAVEFLAG1) { - pp->sloppyclockflag &= ~CLK_FLAG1; - pp->sloppyclockflag |= in->flags & CLK_FLAG1; - } - if (in->haveflags & CLK_HAVEFLAG2) { - pp->sloppyclockflag &= ~CLK_FLAG2; - pp->sloppyclockflag |= in->flags & CLK_FLAG2; - } - if (in->haveflags & CLK_HAVEFLAG3) { - pp->sloppyclockflag &= ~CLK_FLAG3; - pp->sloppyclockflag |= in->flags & CLK_FLAG3; - } - if (in->haveflags & CLK_HAVEFLAG4) { - pp->sloppyclockflag &= ~CLK_FLAG4; - pp->sloppyclockflag |= in->flags & CLK_FLAG4; - } - } - - /* - * Readback requested data - */ - if (out != 0) { - out->haveflags = CLK_HAVETIME1 | CLK_HAVEVAL1 | - CLK_HAVEVAL2 | CLK_HAVEFLAG4; - out->fudgetime1 = pp->fudgetime1; - out->fudgetime2 = pp->fudgetime2; - out->fudgeval1 = pp->stratum; - out->fudgeval2 = pp->refid; - out->flags = (u_char) pp->sloppyclockflag; - - out->timereset = current_time - pp->timestarted; - out->polls = pp->polls; - out->noresponse = pp->noreply; - out->badformat = pp->badformat; - out->baddata = pp->baddata; - - out->lastevent = pp->lastevent; - out->currentstatus = pp->currentstatus; - out->type = pp->type; - out->clockdesc = pp->clockdesc; - out->lencode = pp->lencode; - out->p_lastcode = pp->a_lastcode; - } - - /* - * Give the stuff to the clock - */ - if (refclock_conf[clktype]->clock_control != noentry) - (refclock_conf[clktype]->clock_control)(unit, in, out, peer); -} - - -/* - * refclock_buginfo - return debugging info - * - * This routine is used mainly for debugging. It returns designated - * values from the interface structure that can be displayed using - * ntpdc and the clkbug command. - */ -void -refclock_buginfo( - struct sockaddr_storage *srcadr, /* clock address */ - struct refclockbug *bug /* output structure */ - ) -{ - struct peer *peer; - struct refclockproc *pp; - u_char clktype; - int unit; - int i; - - /* - * Check for valid address and peer structure - */ - if (srcadr->ss_family != AF_INET) - return; - if (!ISREFCLOCKADR(srcadr)) - return; - clktype = (u_char) REFCLOCKTYPE(srcadr); - unit = REFCLOCKUNIT(srcadr); - if (clktype >= num_refclock_conf || unit >= MAXUNIT) - return; - peer = typeunit[clktype][unit]; - if (peer == NULL) - return; - pp = peer->procptr; - - /* - * Copy structure values - */ - bug->nvalues = 8; - bug->svalues = 0x0000003f; - bug->values[0] = pp->year; - bug->values[1] = pp->day; - bug->values[2] = pp->hour; - bug->values[3] = pp->minute; - bug->values[4] = pp->second; - bug->values[5] = pp->nsec; - bug->values[6] = pp->yearstart; - bug->values[7] = pp->coderecv; - bug->stimes = 0xfffffffc; - bug->times[0] = pp->lastref; - bug->times[1] = pp->lastrec; - for (i = 2; i < (int)bug->ntimes; i++) - DTOLFP(pp->filter[i - 2], &bug->times[i]); - - /* - * Give the stuff to the clock - */ - if (refclock_conf[clktype]->clock_buginfo != noentry) - (refclock_conf[clktype]->clock_buginfo)(unit, bug, peer); -} - -#endif /* REFCLOCK */ |