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

📄 refclock_arc.c

📁 网络时间协议NTP 源码 版本v4.2.0b 该源码用于linux平台下
💻 C
📖 第 1 页 / 共 4 页
字号:
#define LENARC          16              /* Format `o' timecode length. */#define BITSPERCHAR     11              /* Bits per character. */#define BITTIME         0x0DA740E       /* Time for 1 bit at 300bps. */#define CHARTIME10      0x8888888       /* Time for 10-bit char at 300bps. */#define CHARTIME11      0x962FC96       /* Time for 11-bit char at 300bps. */#define CHARTIME                        /* Time for char at 300bps. */ \( (BITSPERCHAR == 11) ? CHARTIME11 : ( (BITSPERCHAR == 10) ? CHARTIME10 : \				       (BITSPERCHAR * BITTIME) ) )     /* Allow for UART to accept char half-way through final stop bit. */#define INITIALOFFSET (u_int32)(-BITTIME/2)     /*    charoffsets[x] is the time after the start of the second that byte    x (with the first byte being byte 1) is received by the UART,    assuming that the initial edge of the start bit of the first byte    is on-time.  The values are represented as the fractional part of    an l_fp.    We store enough values to have the offset of each byte including    the trailing \r, on the assumption that the bytes follow one    another without gaps.    */     static const u_int32 charoffsets[LENARC+1] = {#if BITSPERCHAR == 11 /* Usual case. */	     /* Offsets computed as accurately as possible... */	     0,	     INITIALOFFSET + 0x0962fc96, /*  1 chars,  11 bits */	     INITIALOFFSET + 0x12c5f92c, /*  2 chars,  22 bits */	     INITIALOFFSET + 0x1c28f5c3, /*  3 chars,  33 bits */	     INITIALOFFSET + 0x258bf259, /*  4 chars,  44 bits */	     INITIALOFFSET + 0x2eeeeeef, /*  5 chars,  55 bits */	     INITIALOFFSET + 0x3851eb85, /*  6 chars,  66 bits */	     INITIALOFFSET + 0x41b4e81b, /*  7 chars,  77 bits */	     INITIALOFFSET + 0x4b17e4b1, /*  8 chars,  88 bits */	     INITIALOFFSET + 0x547ae148, /*  9 chars,  99 bits */	     INITIALOFFSET + 0x5dddddde, /* 10 chars, 110 bits */	     INITIALOFFSET + 0x6740da74, /* 11 chars, 121 bits */	     INITIALOFFSET + 0x70a3d70a, /* 12 chars, 132 bits */	     INITIALOFFSET + 0x7a06d3a0, /* 13 chars, 143 bits */	     INITIALOFFSET + 0x8369d037, /* 14 chars, 154 bits */	     INITIALOFFSET + 0x8ccccccd, /* 15 chars, 165 bits */	     INITIALOFFSET + 0x962fc963  /* 16 chars, 176 bits */#else	     /* Offsets computed with a small rounding error... */	     0,	     INITIALOFFSET +  1 * CHARTIME,	     INITIALOFFSET +  2 * CHARTIME,	     INITIALOFFSET +  3 * CHARTIME,	     INITIALOFFSET +  4 * CHARTIME,	     INITIALOFFSET +  5 * CHARTIME,	     INITIALOFFSET +  6 * CHARTIME,	     INITIALOFFSET +  7 * CHARTIME,	     INITIALOFFSET +  8 * CHARTIME,	     INITIALOFFSET +  9 * CHARTIME,	     INITIALOFFSET + 10 * CHARTIME,	     INITIALOFFSET + 11 * CHARTIME,	     INITIALOFFSET + 12 * CHARTIME,	     INITIALOFFSET + 13 * CHARTIME,	     INITIALOFFSET + 14 * CHARTIME,	     INITIALOFFSET + 15 * CHARTIME,	     INITIALOFFSET + 16 * CHARTIME#endif     };#define DEFAULT_RESYNC_TIME  (57*60)    /* Gap between resync attempts (s). */#define RETRY_RESYNC_TIME    (27*60)    /* Gap to emergency resync attempt. */#ifdef ARCRON_KEEN#define INITIAL_RESYNC_DELAY 500        /* Delay before first resync. */#else#define INITIAL_RESYNC_DELAY 50         /* Delay before first resync. */#endif     static const int moff[12] ={ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };/* Flags for a raw open() of the clock serial device. */#ifdef O_NOCTTY /* Good, we can avoid tty becoming controlling tty. */#define OPEN_FLAGS (O_RDWR | O_NOCTTY)#else           /* Oh well, it may not matter... */#define OPEN_FLAGS (O_RDWR)#endif/* Length of queue of command bytes to be sent. */#define CMDQUEUELEN 4                   /* Enough for two cmds + each \r. *//* Queue tick time; interval in seconds between chars taken off queue. *//* Must be >= 2 to allow o\r response to come back uninterrupted. */#define QUEUETICK   2                   /* Allow o\r reply to finish. *//* * ARC unit control structure */struct arcunit {	l_fp lastrec;       /* Time tag for the receive time (system). */	int status;         /* Clock status. */	int quality;        /* Quality of reception 0--5 for unit. */	/* We may also use the values -1 or 6 internally. */	u_long quality_stamp; /* Next time to reset quality average. */	u_long next_resync; /* Next resync time (s) compared to current_time. */	int resyncing;      /* Resync in progress if true. */	/* In the outgoing queue, cmdqueue[0] is next to be sent. */	char cmdqueue[CMDQUEUELEN+1]; /* Queue of outgoing commands + \0. */	u_long saved_flags; /* Saved fudge flags. */};#ifdef ARCRON_LEAPSECOND_KEEN/* The flag `possible_leap' is set non-zero when any MSF unit       thinks a leap-second may have happened.       Set whenever we receive a valid time sample in the first hour of       the first day of the first/seventh months.       Outside the special hour this value is unconditionally set       to zero by the receive routine.       On finding itself in this timeslot, as long as the value is       non-negative, the receive routine sets it to a positive value to       indicate a resync to MSF should be performed.       In the poll routine, if this value is positive and we are not       already resyncing (eg from a sync that started just before       midnight), start resyncing and set this value negative to       indicate that a leap-triggered resync has been started.  Having       set this negative prevents the receive routine setting it       positive and thus prevents multiple resyncs during the witching       hour.     */static int possible_leap = 0;       /* No resync required by default. */#endif#if 0static void dummy_event_handler P((struct peer *));static void   arc_event_handler P((struct peer *));#endif /* 0 */#define QUALITY_UNKNOWN     -1 /* Indicates unknown clock quality. */#define MIN_CLOCK_QUALITY    0 /* Min quality clock will return. */#define MIN_CLOCK_QUALITY_OK 3 /* Min quality for OK reception. */#define MAX_CLOCK_QUALITY    5 /* Max quality clock will return. *//* * Function prototypes */static  int     arc_start       P((int, struct peer *));static  void    arc_shutdown    P((int, struct peer *));static  void    arc_receive     P((struct recvbuf *));static  void    arc_poll        P((int, struct peer *));/* * Transfer vector */struct  refclock refclock_arc = {	arc_start,              /* start up driver */	arc_shutdown,           /* shut down driver */	arc_poll,               /* transmit poll message */	noentry,                /* not used (old arc_control) */	noentry,                /* initialize driver (not used) */	noentry,                /* not used (old arc_buginfo) */	NOFLAGS                 /* not used */};/* Queue us up for the next tick. */#define ENQUEUE(up) \	do { \	     peer->nextaction = current_time + QUEUETICK; \	} while(0)/* Placeholder event handler---does nothing safely---soaks up loose tick. */static voiddummy_event_handler(	struct peer *peer	){#ifdef DEBUG	if(debug) { printf("arc: dummy_event_handler() called.\n"); }#endif}/*Normal event handler.Take first character off queue and send to clock if not a null.Shift characters down and put a null on the end.We assume that there is no parallelism so no race condition, but evenif there is nothing bad will happen except that we might send some baddata to the clock once in a while.*/static voidarc_event_handler(	struct peer *peer	){	struct refclockproc *pp = peer->procptr;	register struct arcunit *up = (struct arcunit *)pp->unitptr;	int i;	char c;#ifdef DEBUG	if(debug > 2) { printf("arc: arc_event_handler() called.\n"); }#endif	c = up->cmdqueue[0];       /* Next char to be sent. */	/* Shift down characters, shifting trailing \0 in at end. */	for(i = 0; i < CMDQUEUELEN; ++i)	{ up->cmdqueue[i] = up->cmdqueue[i+1]; }	/* Don't send '\0' characters. */	if(c != '\0') {		if(write(pp->io.fd, &c, 1) != 1) {			msyslog(LOG_NOTICE, "ARCRON: write to fd %d failed", pp->io.fd);		}#ifdef DEBUG		else if(debug) { printf("arc: sent `%2.2x', fd %d.\n", c, pp->io.fd); }#endif	}	ENQUEUE(up);}/* * arc_start - open the devices and initialize data for processing */static intarc_start(	int unit,	struct peer *peer	){	register struct arcunit *up;	struct refclockproc *pp;	int fd;	char device[20];#ifdef HAVE_TERMIOS	struct termios arg;#endif	msyslog(LOG_NOTICE, "ARCRON: %s: opening unit %d", arc_version, unit);#ifdef DEBUG	if(debug) {		printf("arc: %s: attempt to open unit %d.\n", arc_version, unit);	}#endif	/* Prevent a ridiculous device number causing overflow of device[]. */	if((unit < 0) || (unit > 255)) { return(0); }	/*	 * Open serial port. Use CLK line discipline, if available.	 */	(void)sprintf(device, DEVICE, unit);	if (!(fd = refclock_open(device, SPEED, LDISC_CLK)))		return(0);#ifdef DEBUG	if(debug) { printf("arc: unit %d using open().\n", unit); }#endif	fd = open(device, OPEN_FLAGS);	if(fd < 0) {#ifdef DEBUG		if(debug) { printf("arc: failed [open()] to open %s.\n", device); }#endif		return(0);	}	fcntl(fd, F_SETFL, 0); /* clear the descriptor flags */#ifdef DEBUG	if(debug)	{ printf("arc: opened RS232 port with file descriptor %d.\n", fd); }#endif#ifdef HAVE_TERMIOS	tcgetattr(fd, &arg);	arg.c_iflag = IGNBRK | ISTRIP;	arg.c_oflag = 0;	arg.c_cflag = B300 | CS8 | CREAD | CLOCAL | CSTOPB;	arg.c_lflag = 0;	arg.c_cc[VMIN] = 1;	arg.c_cc[VTIME] = 0;	tcsetattr(fd, TCSANOW, &arg);#else	msyslog(LOG_ERR, "ARCRON: termios not supported in this driver");	(void)close(fd);	return 0;#endif	up = (struct arcunit *) emalloc(sizeof(struct arcunit));	if(!up) { (void) close(fd); return(0); }	/* Set structure to all zeros... */	memset((char *)up, 0, sizeof(struct arcunit));	pp = peer->procptr;	pp->io.clock_recv = arc_receive;	pp->io.srcclock = (caddr_t)peer;	pp->io.datalen = 0;	pp->io.fd = fd;	if(!io_addclock(&pp->io)) { (void) close(fd); free(up); return(0); }	pp->unitptr = (caddr_t)up;	/*	 * Initialize miscellaneous variables	 */	peer->precision = PRECISION;	peer->stratum = 2;              /* Default to stratum 2 not 0. */	pp->clockdesc = DESCRIPTION;	if (peer->MODE > 3) {		msyslog(LOG_NOTICE, "ARCRON: Invalid mode %d", peer->MODE);		return 0;	}#ifdef DEBUG	if(debug) { printf("arc: mode = %d.\n", peer->MODE); }#endif	switch (peer->MODE) {	    case 1:		memcpy((char *)&pp->refid, REFID_MSF, 4);		break;	    case 2:		memcpy((char *)&pp->refid, REFID_DCF77, 4);		break;	    case 3:		memcpy((char *)&pp->refid, REFID_WWVB, 4);		break;	    default:		memcpy((char *)&pp->refid, REFID, 4);		break;	}	/* Spread out resyncs so that they should remain separated. */	up->next_resync = current_time + INITIAL_RESYNC_DELAY + (67*unit)%1009;#if 0 /* Not needed because of zeroing of arcunit structure... */	up->resyncing = 0;              /* Not resyncing yet. */	up->saved_flags = 0;            /* Default is all flags off. */	/* Clear send buffer out... */	{		int i;		for(i = CMDQUEUELEN; i >= 0; --i) { up->cmdqueue[i] = '\0'; }	}#endif#ifdef ARCRON_KEEN	up->quality = QUALITY_UNKNOWN;  /* Trust the clock immediately. */#else	up->quality = MIN_CLOCK_QUALITY;/* Don't trust the clock yet. */#endif	peer->action = arc_event_handler;	ENQUEUE(up);	return(1);}/* * arc_shutdown - shut down the clock */static voidarc_shutdown(	int unit,	struct peer *peer	){	register struct arcunit *up;	struct refclockproc *pp;	peer->action = dummy_event_handler;	pp = peer->procptr;	up = (struct arcunit *)pp->unitptr;	io_closeclock(&pp->io);	free(up);}/*Compute space left in output buffer.*/static intspace_left(	register struct arcunit *up	){	int spaceleft;

⌨️ 快捷键说明

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