⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tty_clk.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
字号:
/* tty_clk.c,v 3.1 1993/07/06 01:07:33 jbj Exp * tty_clk.c - Generic line driver for receiving radio clock timecodes */#include "clk.h"#if NCLK > 0#include "../h/param.h"#include "../h/types.h"#include "../h/systm.h"#include "../h/dir.h"#include "../h/user.h"#include "../h/ioctl.h"#include "../h/tty.h"#include "../h/proc.h"#include "../h/file.h"#include "../h/conf.h"#include "../h/buf.h"#include "../h/uio.h"#include "../h/clist.h"/* * This line discipline is intended to provide well performing * generic support for the reception and time stamping of radio clock * timecodes.  Most radio clock devices return a string where a * particular character in the code (usually a \r) is on-time * synchronized with the clock.  The idea here is to collect characters * until (one of) the synchronization character(s) (we allow two) is seen. * When the magic character arrives we take a timestamp by calling * microtime() and insert the eight bytes of struct timeval into the * buffer after the magic character.  We then wake up anyone waiting * for the buffer and return the whole mess on the next read. * * To use this the calling program is expected to first open the * port, and then to set the port into raw mode with the speed * set appropriately with a TIOCSETP ioctl(), with the erase and kill * characters set to those to be considered magic (yes, I know this * is gross, but they were so convenient).  If only one character is * magic you can set then both the same, or perhaps to the alternate * parity versions of said character.  After getting all this set, * change the line discipline to CLKLDISC and you are on your way. * * The only other bit of magic we do in here is to flush the receive * buffers on writes if the CRMOD flag is set (hack, hack). *//* * We run this very much like a raw mode terminal, with the exception * that we store up characters locally until we hit one of the * magic ones and then dump it into the rawq all at once.  We keep * the buffered data in clists since we can then often move it to * the rawq without copying.  For sanity we limit the number of * characters between specials, and the total number of characters * before we flush the rawq, as follows. */#define	CLKLINESIZE	(256)#define	NCLKCHARS	(CLKLINESIZE*4)struct clkdata {	int inuse;	struct clist clkbuf;};#define	clk_cc	clkbuf.c_cc#define	clk_cf	clkbuf.c_cf#define	clk_cl	clkbuf.c_clstruct clkdata clk_data[NCLK];/* * Routine for flushing the internal clist */#define	clk_bflush(clk)		(ndflush(&((clk)->clkbuf), (clk)->clk_cc))int clk_debug = 0;/*ARGSUSED*/clkopen(dev, tp)	dev_t dev;	register struct tty *tp;{	register struct clkdata *clk;	/*	 * Don't allow multiple opens.  This will also protect us	 * from someone opening /dev/tty	 */	if (tp->t_line == CLKLDISC)		return (EBUSY);	ttywflush(tp);	for (clk = clk_data; clk < &clk_data[NCLK]; clk++)		if (!clk->inuse)			break;	if (clk >= &clk_data[NCLK])		return (EBUSY);	clk->inuse++;	clk->clk_cc = 0;	clk->clk_cf = clk->clk_cl = NULL;	tp->T_LINEP = (caddr_t) clk;	return (0);}/* * Break down... called when discipline changed or from device * close routine. */clkclose(tp)	register struct tty *tp;{	register struct clkdata *clk;	register int s = spltty();	clk = (struct clkdata *)tp->T_LINEP;	if (clk->clk_cc > 0)		clk_bflush(clk);	clk->inuse = 0;	tp->t_line = 0;			/* paranoid: avoid races */	splx(s);}/* * Receive a write request.  We pass these requests on to the terminal * driver, except that if the CRMOD bit is set in the flags we * first flush the input queues. */clkwrite(tp, uio)	register struct tty *tp;	struct uio *uio;{	if (tp->t_flags & CRMOD) {		register struct clkdata *clk;		int s;		s = spltty();		if (tp->t_rawq.c_cc > 0)			ndflush(&tp->t_rawq, tp->t_rawq.c_cc);		clk = (struct clkdata *) tp->T_LINEP;		if (clk->clk_cc > 0)			clk_bflush(clk);		(void)splx(s);	}	ttwrite(tp, uio);}/* * Low level character input routine. * If the character looks okay, grab a time stamp.  If the stuff in * the buffer is too old, dump it and start fresh.  If the character is * non-BCDish, everything in the buffer too. */clkinput(c, tp)	register int c;	register struct tty *tp;{	register struct clkdata *clk;	register int i;	register long s;	struct timeval tv;	/*	 * Check to see whether this isn't the magic character.  If not,	 * save the character and return.	 */#ifdef ultrix	if (c != tp->t_cc[VERASE] && c != tp->t_cc[VKILL]) {#else	if (c != tp->t_erase && c != tp->t_kill) {#endif		clk = (struct clkdata *) tp->T_LINEP;		if (clk->clk_cc >= CLKLINESIZE)			clk_bflush(clk);		if (putc(c, &clk->clkbuf) == -1) {			/*			 * Hopeless, no clists.  Flush what we have			 * and hope things improve.			 */			clk_bflush(clk);		}		return;	}	/*	 * Here we have a magic character.  Get a timestamp and store	 * everything.	 */	microtime(&tv);	clk = (struct clkdata *) tp->T_LINEP;	if (putc(c, &clk->clkbuf) == -1)		goto flushout;	#ifdef CLKLDISC	/*	 * STREAMS people started writing timestamps this way.	 * It's not my fault, I am just going along with the flow...	 */	for (i = 0; i < sizeof(struct timeval); i++)		if (putc(*( ((char*)&tv) + i ), &clk->clkbuf) == -1)			goto flushout;#else	/*	 * This is a machine independant way of puting longs into	 * the datastream.  It has fallen into disuse...	 */	s = tv.tv_sec;	for (i = 0; i < sizeof(long); i++) {		if (putc((s >> 24) & 0xff, &clk->clkbuf) == -1)			goto flushout;		s <<= 8;	}	s = tv.tv_usec;	for (i = 0; i < sizeof(long); i++) {		if (putc((s >> 24) & 0xff, &clk->clkbuf) == -1)			goto flushout;		s <<= 8;	}#endif	/*	 * If the length of the rawq exceeds our sanity limit, dump	 * all the old crap in there before copying this in.	 */	if (tp->t_rawq.c_cc > NCLKCHARS)		ndflush(&tp->t_rawq, tp->t_rawq.c_cc);		/*	 * Now copy the buffer in.  There is a special case optimization	 * here.  If there is nothing on the rawq at present we can	 * just copy the clists we own over.  Otherwise we must concatenate	 * the present data on the end.	 */	s = (long)spltty();	if (tp->t_rawq.c_cc <= 0) {		tp->t_rawq = clk->clkbuf;		clk->clk_cc = 0;		clk->clk_cl = clk->clk_cf = NULL;		(void) splx((int)s);	} else {		(void) splx((int)s);		catq(&clk->clkbuf, &tp->t_rawq);		clk_bflush(clk);	}	/*	 * Tell the world	 */	ttwakeup(tp);	return;flushout:	/*	 * It would be nice if this never happened.  Flush the	 * internal clists and hope someone else frees some of them	 */	clk_bflush(clk);	return;}/* * Handle ioctls.  We reject most tty-style except those that * change the line discipline and a couple of others.. */clkioctl(tp, cmd, data, flag)	struct tty *tp;	int cmd;	caddr_t data;	int flag;{	int flags;	struct sgttyb *sg;	if ((cmd>>8) != 't')		return (-1);	switch (cmd) {	case TIOCSETD:	case TIOCGETD:	case TIOCGETP:	case TIOCGETC:	case TIOCOUTQ:		return (-1);	case TIOCSETP:		/*		 * He likely wants to set new magic characters in.		 * Do this part.		 */		sg = (struct sgttyb *)data;#ifdef ultrix		tp->t_cc[VERASE] = sg->sg_erase;		tp->t_cc[VKILL] = sg->sg_kill;#else		tp->t_erase = sg->sg_erase;		tp->t_kill = sg->sg_kill;#endif		return (0);	case TIOCFLUSH:		flags = *(int *)data;		if (flags == 0 || (flags & FREAD)) {			register struct clkdata *clk;			clk = (struct clkdata *) tp->T_LINEP;			if (clk->clk_cc > 0)				clk_bflush(clk);		}		return (-1);		default:		break;	}	return (ENOTTY);	/* not quite appropriate */}#endif NCLK

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -