📄 ntp_refclock.c
字号:
#endif /* HAVE_TERMIOS || HAVE_SYSV_TTYS || HAVE_BSD_TTYS *//* * 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 the tty_clk, chu_clk and ppsclock streams module/line discipline, * if compiled in the daemon and requested in the call. The routine * returns one if success and zero if failure. */intrefclock_ioctl(fd, flags) int fd; /* file descriptor */ int flags; /* line discipline flags */{ /* simply return 1 if no UNIX line discipline is supported */#if defined(HAVE_TERMIOS) || defined(HAVE_SYSV_TTYS) || defined(HAVE_BSD_TTYS)#ifdef HAVE_TERMIOS struct termios ttyb, *ttyp;#endif /* HAVE_TERMIOS */#ifdef HAVE_SYSV_TTYS struct termio ttyb, *ttyp;#endif /* HAVE_SYSV_TTYS */#ifdef HAVE_BSD_TTYS struct sgttyb ttyb, *ttyp;#endif /* HAVE_BSD_TTYS */#ifdef DEBUG if (debug) printf("refclock_ioctl: fd %d flags %x\n", fd, flags);#endif /* * The following sections select optional features, such as * modem control, line discipline and so forth. Some require * specific operating system support in the form of streams * modules, which can be loaded and unloaded at run time without * rebooting the kernel, or line discipline modules, which must * be compiled in the kernel. The streams modules require System * V STREAMS support, while the line discipline modules require * 4.3bsd or later. The checking frenzy is attenuated here, * since the device is already open. * * Note that both the clk and ppsclock modules are optional; the * dang thing still works, but the accuracy improvement using * them will not be available. The ppsclock module is associated * with a specific, declared line and should be used only once. * If requested, the chu module is mandatory, since the driver * will not work without it. * * Use the LDISC_PPS option ONLY with Sun baseboard ttya or * ttyb. Using it with the SPIF multipexor crashes the kernel. */ if (flags == 0) return (1);#if !(defined(HAVE_TERMIOS) || defined(HAVE_BSD_TTYS)) if (flags & (LDISC_CLK | LDISC_CHU | LDISC_PPS | LDISC_ACTS)) msyslog(LOG_ERR, "refclock_ioctl: unsupported terminal interface"); return (0);#endif /* HAVE_TERMIOS HAVE_BSD_TTYS */ ttyp = &ttyb;#ifdef STREAM#ifdef TTYCLK /* * The TTYCLK option provides timestamping at the driver level. * It requires the tty_clk streams module and System V STREAMS * support. */ if (flags & (LDISC_CLK | LDISC_CLKPPS | LDISC_ACTS)) { if (ioctl(fd, I_PUSH, "clk") < 0) { msyslog(LOG_NOTICE, "refclock_ioctl: optional clk streams module unavailable: %m"); } else { char *str; if (flags & LDISC_PPS) str = "\377"; else if (flags & LDISC_ACTS) str = "*"; else str = "\n"; if (ioctl(fd, CLK_SETSTR, str) < 0) msyslog(LOG_ERR, "refclock_ioctl: CLK_SETSTR failed: %m"); } } /* * The ACTS line discipline requires additional line-ending * character '*'. */ if (flags & LDISC_ACTS) { (void)tcgetattr(fd, ttyp); ttyp->c_cc[VEOL] = '*'; (void)tcsetattr(fd, TCSANOW, ttyp); }#else if (flags & LDISC_CLK) msyslog(LOG_NOTICE, "refclock_ioctl: optional clk streams module unsupported");#endif /* TTYCLK */#ifdef CHUCLK /* * The CHUCLK option provides timestamping and decoding for the CHU * timecode. It requires the tty_chu streams module and System V * STREAMS support. */ if (flags & LDISC_CHU) { (void)tcgetattr(fd, ttyp); ttyp->c_lflag = 0; ttyp->c_cc[VERASE] = ttyp->c_cc[VKILL] = '\0'; ttyp->c_cc[VMIN] = 1; ttyp->c_cc[VTIME] = 0; (void)tcsetattr(fd, TCSANOW, ttyp); (void)tcflush(fd, TCIOFLUSH); while (ioctl(fd, I_POP, 0) >= 0); if (ioctl(fd, I_PUSH, "chu") < 0) { msyslog(LOG_ERR, "refclock_ioctl: required chu streams module unavailable"); return (0); } }#else if (flags & LDISC_CHU) { msyslog(LOG_ERR, "refclock_ioctl: required chu streams module unsupported"); return (0); }#endif /* CHUCLK */#ifdef PPS /* * The PPS option provides timestamping at the driver level. * It uses a 1-pps signal and level converter (gadget box) and * requires the ppsclock streams module and System V STREAMS * support. */ if (flags & LDISC_PPS) { if (fdpps != -1) { msyslog(LOG_ERR, "refclock_ioctl: ppsclock already configured"); return (0); } if (#ifdef SYS_SOLARIS (ioctl(fd, TIOCSPPS, (char *)&pps_enable) < 0)#else (ioctl(fd, I_PUSH, "ppsclock") < 0)#endif /* SYS_SOLARIS */ ) { msyslog(LOG_NOTICE, "refclock_ioctl: optional ppsclock streams module unavailable"); } else { fdpps = fd; } }#else if (flags & LDISC_PPS) msyslog(LOG_NOTICE, "refclock_ioctl: optional ppsclock streams module unsupported");#endif /* PPS */#else /* not STREAM */#ifdef HAVE_TERMIOS#ifdef TTYCLK /* * The TTYCLK option provides timestamping at the driver level. It * requires the tty_clk line discipline and 4.3bsd or later. */ if (flags & (LDISC_CLK | LDISC_CLKPPS | LDISC_ACTS)) { (void)tcgetattr(fd, ttyp); ttyp->c_lflag = 0; if (flags & LDISC_CLKPPS) ttyp->c_cc[VERASE] = ttyp->c_cc[VKILL] = '\377'; else if (flags & LDISC_ACTS) { ttyp->c_cc[VERASE] = '*'; ttyp->c_cc[VKILL] = '#'; } else ttyp->c_cc[VERASE] = ttyp->c_cc[VKILL] = '\n'; ttyp->c_cc[VMIN] = 1; ttyp->c_cc[VTIME] = 0; ttyp->c_line = CLKLDISC; (void)tcsetattr(fd, TCSANOW, ttyp); (void)tcflush(fd, TCIOFLUSH); }#else if (flags & LDISC_CLK) msyslog(LOG_NOTICE, "refclock_ioctl: optional clk line discipline unsupported");#endif /* TTYCLK */#ifdef CHUCLK /* * The CHUCLK option provides timestamping and decoding for the CHU * timecode. It requires the tty_chu line disciplne and 4.3bsd * or later. */ if (flags & LDISC_CHU) { (void)tcgetattr(fd, ttyp); ttyp->c_lflag = 0; ttyp->c_cc[VERASE] = ttyp->c_cc[VKILL] = '\r'; ttyp->c_cc[VMIN] = 1; ttyp->c_cc[VTIME] = 0; ttyp->c_line = CHULDISC; (void)tcsetattr(fd, TCSANOW, ttyp) < 0); (void)tcflush(fd, TCIOFLUSH); }#else if (flags & LDISC_CHU) { msyslog(LOG_ERR, "refclock_ioctl: required chu line discipline unsupported"); return (0); }#endif /* CHUCLK */#endif /* HAVE_TERMIOS */#ifdef HAVE_BSD_TTYS#ifdef TTYCLK /* * The TTYCLK option provides timestamping at the driver level. It * requires the tty_clk line discipline and 4.3bsd or later. */ if (flags & (LDISC_CLK | LDISC_CLKPPS | LDISC_ACTS)) { int ldisc = CLKLDISC; (void)ioctl(fd, TIOCGETP, (char *)ttyp); if (flags & LDISC_CLKPPS) ttyp->sg_erase = ttyp->sg_kill = '\377'; else if (flags & LDISC_ACTS) { ttyp->sg_erase = '*'; ttyp->sg_kill = '#'; } else ttyp->sg_erase = ttyp->sg_kill = '\r'; ttyp->sg_flags = RAW; (void)ioctl(fd, TIOCSETP, ttyp); if (ioctl(fd, TIOCSETD, (char *)&ldisc) < 0) msyslog(LOG_NOTICE, "refclock_ioctl: optional clk line discipline unavailable"); }#else if (flags & LDISC_CLK) msyslog(LOG_NOTICE, "refclock_ioctl: optional clk line discipline unsupported");#endif /* TTYCLK */#ifdef CHUCLK /* * The CHUCLK option provides timestamping and decoding for the CHU * timecode. It requires the tty_chu line disciplne and 4.3bsd * or later. */ if (flags & LDISC_CHU) { int ldisc = CHULDISC; (void)ioctl(fd, TIOCGETP, (char *)ttyp); ttyp->sg_erase = ttyp->sg_kill = '\r'; ttyp->sg_flags = RAW; (void)ioctl(fd, TIOCSETP, (char *)ttyp); if (ioctl(fd, TIOCSETD, (char *)&ldisc) < 0) { msyslog(LOG_ERR, "refclock_ioctl: required chu line discipline unavailable"); return (0); } }#else if (flags & LDISC_CHU) { msyslog(LOG_ERR, "refclock_ioctl: required chu line discipline unsupported"); return (0); }#endif /* CHUCLK */#endif /* HAVE_BSD_TTYS */#endif /* STREAM */#endif /* HAVE_TERMIOS || HAVE_SYSV_TTYS || HAVE_BSD_TTYS */ 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 * xntpdc and the clockstat command. It can also be used to initialize * configuration variables, such as fudgetimes, fudgevalues, reference * ID and stratum. */voidrefclock_control(srcadr, in, out) struct sockaddr_in *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 (!ISREFCLOCKADR(srcadr)) return; clktype = (u_char)REFCLOCKTYPE(srcadr); unit = REFCLOCKUNIT(srcadr); if (clktype >= num_refclock_conf || unit > MAXUNIT) return; if (!(peer = typeunit[clktype][unit])) 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) peer->stratum = (u_char) in->fudgeval1; if (in->haveflags & CLK_HAVEVAL2) pp->refid = in->fudgeval2; if (peer->stratum <= 1) peer->refid = pp->refid; else peer->refid = 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; } if (in->flags & CLK_FLAG3) (void)refclock_ioctl(pp->io.fd, LDISC_PPS); } /* * 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 = peer->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->lastcode = pp->lastcode; } /* * Give the stuff to the clock */ if (refclock_conf[clktype]->clock_control != noentry) (refclock_conf[clktype]->clock_control)(unit, in, out);}/* * 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 * xntpdc and the clkbug command. */voidrefclock_buginfo(srcadr, bug) struct sockaddr_in *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 (!ISREFCLOCKADR(srcadr)) return; clktype = (u_char) REFCLOCKTYPE(srcadr); unit = REFCLOCKUNIT(srcadr); if (clktype >= num_refclock_conf || unit > MAXUNIT) return; if (!(peer = typeunit[clktype][unit])) return; pp = peer->procptr; /* * Copy structure values */ bug->nvalues = 8; 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->msec; bug->values[6] = pp->yearstart; bug->values[7] = pp->coderecv; bug->ntimes = pp->nstages + 3; if (bug->ntimes > NCLKBUGTIMES) bug->ntimes = NCLKBUGTIMES; bug->stimes = 0xfffffffc; bug->times[0] = pp->lastref; bug->times[1] = pp->lastrec; UFPTOLFP(pp->dispersion, &bug->times[2]); for (i = 0; i < (int)bug->ntimes; i++) bug->times[i + 3] = pp->filter[i]; /* * Give the stuff to the clock */ if (refclock_conf[clktype]->clock_buginfo != noentry) (refclock_conf[clktype]->clock_buginfo)(unit, bug);}#endif /* REFCLOCK */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -