File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / ntpd / refclock_leitch.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:08:38 2012 UTC (12 years, 1 month ago) by misho
Branches: ntp, MAIN
CVS tags: v4_2_6p5p0, v4_2_6p5, HEAD
ntp 4.2.6p5

    1: /*
    2:  * refclock_leitch - clock driver for the Leitch CSD-5300 Master Clock
    3:  */
    4: 
    5: #ifdef HAVE_CONFIG_H
    6: # include <config.h>
    7: #endif
    8: 
    9: #if defined(REFCLOCK) && defined(CLOCK_LEITCH)
   10: 
   11: #include "ntpd.h"
   12: #include "ntp_io.h"
   13: #include "ntp_refclock.h"
   14: #include "ntp_unixtime.h"
   15: 
   16: #include <stdio.h>
   17: #include <ctype.h>
   18: 
   19: #ifdef STREAM
   20: #include <stropts.h>
   21: #if defined(LEITCHCLK)
   22: #include <sys/clkdefs.h>
   23: #endif /* LEITCHCLK */
   24: #endif /* STREAM */
   25: 
   26: #include "ntp_stdlib.h"
   27: 
   28: 
   29: /*
   30:  * Driver for Leitch CSD-5300 Master Clock System
   31:  *
   32:  * COMMANDS:
   33:  *	DATE:	D <CR>
   34:  *	TIME:	T <CR>
   35:  *	STATUS:	S <CR>
   36:  *	LOOP:	L <CR>
   37:  *
   38:  * FORMAT:
   39:  *	DATE: YYMMDD<CR>
   40:  *	TIME: <CR>/HHMMSS <CR>/HHMMSS <CR>/HHMMSS <CR>/
   41:  *		second bondaried on the stop bit of the <CR>
   42:  *		second boundaries at '/' above.
   43:  *	STATUS: G (good), D (diag fail), T (time not provided) or
   44:  *		P (last phone update failed)
   45:  */
   46: #define PRECISION	(-20)	/* 1x10-8 */
   47: #define MAXUNITS 1		/* max number of LEITCH units */
   48: #define LEITCHREFID	"ATOM"	/* reference id */
   49: #define LEITCH_DESCRIPTION "Leitch: CSD 5300 Master Clock System Driver"
   50: #define LEITCH232 "/dev/leitch%d"	/* name of radio device */
   51: #define SPEED232 B300		/* uart speed (300 baud) */ 
   52: #ifdef DEBUG
   53: #define leitch_send(A,M) \
   54: if (debug) fprintf(stderr,"write leitch %s\n",M); \
   55: if ((write(A->leitchio.fd,M,sizeof(M)) < 0)) {\
   56: 	if (debug) \
   57: 	    fprintf(stderr, "leitch_send: unit %d send failed\n", A->unit); \
   58: 	else \
   59: 	    msyslog(LOG_ERR, "leitch_send: unit %d send failed %m",A->unit);}
   60: #else
   61: #define leitch_send(A,M) \
   62: if ((write(A->leitchio.fd,M,sizeof(M)) < 0)) {\
   63: 	msyslog(LOG_ERR, "leitch_send: unit %d send failed %m",A->unit);}
   64: #endif
   65: 
   66: #define STATE_IDLE 0
   67: #define STATE_DATE 1
   68: #define STATE_TIME1 2
   69: #define STATE_TIME2 3
   70: #define STATE_TIME3 4
   71: 
   72: /*
   73:  * LEITCH unit control structure
   74:  */
   75: struct leitchunit {
   76: 	struct peer *peer;
   77: 	struct refclockio leitchio;
   78: 	u_char unit;
   79: 	short year;
   80: 	short yearday;
   81: 	short month;
   82: 	short day;
   83: 	short hour;
   84: 	short second;
   85: 	short minute;
   86: 	short state;
   87: 	u_short fudge1;
   88: 	l_fp reftime1;
   89: 	l_fp reftime2;
   90: 	l_fp reftime3;
   91: 	l_fp codetime1;
   92: 	l_fp codetime2;
   93: 	l_fp codetime3;
   94: 	u_long yearstart;
   95: };
   96: 
   97: /*
   98:  * Function prototypes
   99:  */
  100: static	void	leitch_init	(void);
  101: static	int	leitch_start	(int, struct peer *);
  102: static	void	leitch_shutdown	(int, struct peer *);
  103: static	void	leitch_poll	(int, struct peer *);
  104: static	void	leitch_control	(int, struct refclockstat *, struct refclockstat *, struct peer *);
  105: #define	leitch_buginfo	noentry
  106: static	void	leitch_receive	(struct recvbuf *);
  107: static	void	leitch_process	(struct leitchunit *);
  108: #if 0
  109: static	void	leitch_timeout	(struct peer *);
  110: #endif
  111: static	int	leitch_get_date	(struct recvbuf *, struct leitchunit *);
  112: static	int	leitch_get_time	(struct recvbuf *, struct leitchunit *, int);
  113: static	int	days_per_year		(int);
  114: 
  115: static struct leitchunit leitchunits[MAXUNITS];
  116: static u_char unitinuse[MAXUNITS];
  117: static u_char stratumtouse[MAXUNITS];
  118: static u_int32 refid[MAXUNITS];
  119: 
  120: static	char days_in_month [] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
  121: 
  122: /*
  123:  * Transfer vector
  124:  */
  125: struct	refclock refclock_leitch = {
  126: 	leitch_start, leitch_shutdown, leitch_poll,
  127: 	leitch_control, leitch_init, leitch_buginfo, NOFLAGS
  128: };
  129: 
  130: /*
  131:  * leitch_init - initialize internal leitch driver data
  132:  */
  133: static void
  134: leitch_init(void)
  135: {
  136: 	int i;
  137: 
  138: 	memset((char*)leitchunits, 0, sizeof(leitchunits));
  139: 	memset((char*)unitinuse, 0, sizeof(unitinuse));
  140: 	for (i = 0; i < MAXUNITS; i++)
  141: 	    memcpy((char *)&refid[i], LEITCHREFID, 4);
  142: }
  143: 
  144: /*
  145:  * leitch_shutdown - shut down a LEITCH clock
  146:  */
  147: static void
  148: leitch_shutdown(
  149: 	int unit,
  150: 	struct peer *peer
  151: 	)
  152: {
  153: 	struct leitchunit *leitch;
  154: 
  155: 	if (unit >= MAXUNITS) {
  156: 		return;
  157: 	}
  158: 	leitch = &leitchunits[unit];
  159: 	if (-1 != leitch->leitchio.fd)
  160: 		io_closeclock(&leitch->leitchio);
  161: #ifdef DEBUG
  162: 	if (debug)
  163: 		fprintf(stderr, "leitch_shutdown()\n");
  164: #endif
  165: }
  166: 
  167: /*
  168:  * leitch_poll - called by the transmit procedure
  169:  */
  170: static void
  171: leitch_poll(
  172: 	int unit,
  173: 	struct peer *peer
  174: 	)
  175: {
  176: 	struct leitchunit *leitch;
  177: 
  178: 	/* start the state machine rolling */
  179: 
  180: #ifdef DEBUG
  181: 	if (debug)
  182: 	    fprintf(stderr, "leitch_poll()\n");
  183: #endif
  184: 	if (unit >= MAXUNITS) {
  185: 		/* XXXX syslog it */
  186: 		return;
  187: 	}
  188: 
  189: 	leitch = &leitchunits[unit];
  190: 
  191: 	if (leitch->state != STATE_IDLE) {
  192: 		/* reset and wait for next poll */
  193: 		/* XXXX syslog it */
  194: 		leitch->state = STATE_IDLE;
  195: 	} else {
  196: 		leitch_send(leitch,"D\r");
  197: 		leitch->state = STATE_DATE;
  198: 	}
  199: }
  200: 
  201: static void
  202: leitch_control(
  203: 	int unit,
  204: 	struct refclockstat *in,
  205: 	struct refclockstat *out,
  206: 	struct peer *passed_peer
  207: 	)
  208: {
  209: 	if (unit >= MAXUNITS) {
  210: 		msyslog(LOG_ERR,
  211: 			"leitch_control: unit %d invalid", unit);
  212: 		return;
  213: 	}
  214: 
  215: 	if (in) {
  216: 		if (in->haveflags & CLK_HAVEVAL1)
  217: 		    stratumtouse[unit] = (u_char)(in->fudgeval1);
  218: 		if (in->haveflags & CLK_HAVEVAL2)
  219: 		    refid[unit] = in->fudgeval2;
  220: 		if (unitinuse[unit]) {
  221: 			struct peer *peer;
  222: 
  223: 			peer = (&leitchunits[unit])->peer;
  224: 			peer->stratum = stratumtouse[unit];
  225: 			peer->refid = refid[unit];
  226: 		}
  227: 	}
  228: 
  229: 	if (out) {
  230: 		memset((char *)out, 0, sizeof (struct refclockstat));
  231: 		out->type = REFCLK_ATOM_LEITCH;
  232: 		out->haveflags = CLK_HAVEVAL1 | CLK_HAVEVAL2;
  233: 		out->fudgeval1 = (int32)stratumtouse[unit];
  234: 		out->fudgeval2 = refid[unit];
  235: 		out->p_lastcode = "";
  236: 		out->clockdesc = LEITCH_DESCRIPTION;
  237: 	}
  238: }
  239: 
  240: /*
  241:  * leitch_start - open the LEITCH devices and initialize data for processing
  242:  */
  243: static int
  244: leitch_start(
  245: 	int unit,
  246: 	struct peer *peer
  247: 	)
  248: {
  249: 	struct leitchunit *leitch;
  250: 	int fd232;
  251: 	char leitchdev[20];
  252: 
  253: 	/*
  254: 	 * Check configuration info.
  255: 	 */
  256: 	if (unit >= MAXUNITS) {
  257: 		msyslog(LOG_ERR, "leitch_start: unit %d invalid", unit);
  258: 		return (0);
  259: 	}
  260: 
  261: 	if (unitinuse[unit]) {
  262: 		msyslog(LOG_ERR, "leitch_start: unit %d in use", unit);
  263: 		return (0);
  264: 	}
  265: 
  266: 	/*
  267: 	 * Open serial port.
  268: 	 */
  269: 	snprintf(leitchdev, sizeof(leitchdev), LEITCH232, unit);
  270: 	fd232 = open(leitchdev, O_RDWR, 0777);
  271: 	if (fd232 == -1) {
  272: 		msyslog(LOG_ERR,
  273: 			"leitch_start: open of %s: %m", leitchdev);
  274: 		return (0);
  275: 	}
  276: 
  277: 	leitch = &leitchunits[unit];
  278: 	memset(leitch, 0, sizeof(*leitch));
  279: 
  280: #if defined(HAVE_SYSV_TTYS)
  281: 	/*
  282: 	 * System V serial line parameters (termio interface)
  283: 	 *
  284: 	 */
  285: 	{	struct termio ttyb;
  286: 	if (ioctl(fd232, TCGETA, &ttyb) < 0) {
  287: 		msyslog(LOG_ERR,
  288: 			"leitch_start: ioctl(%s, TCGETA): %m", leitchdev);
  289: 		goto screwed;
  290: 	}
  291: 	ttyb.c_iflag = IGNBRK|IGNPAR|ICRNL;
  292: 	ttyb.c_oflag = 0;
  293: 	ttyb.c_cflag = SPEED232|CS8|CLOCAL|CREAD;
  294: 	ttyb.c_lflag = ICANON;
  295: 	ttyb.c_cc[VERASE] = ttyb.c_cc[VKILL] = '\0';
  296: 	if (ioctl(fd232, TCSETA, &ttyb) < 0) {
  297: 		msyslog(LOG_ERR,
  298: 			"leitch_start: ioctl(%s, TCSETA): %m", leitchdev);
  299: 		goto screwed;
  300: 	}
  301: 	}
  302: #endif /* HAVE_SYSV_TTYS */
  303: #if defined(HAVE_TERMIOS)
  304: 	/*
  305: 	 * POSIX serial line parameters (termios interface)
  306: 	 *
  307: 	 * The LEITCHCLK option provides timestamping at the driver level. 
  308: 	 * It requires the tty_clk streams module.
  309: 	 */
  310: 	{	struct termios ttyb, *ttyp;
  311: 
  312: 	ttyp = &ttyb;
  313: 	if (tcgetattr(fd232, ttyp) < 0) {
  314: 		msyslog(LOG_ERR,
  315: 			"leitch_start: tcgetattr(%s): %m", leitchdev);
  316: 		goto screwed;
  317: 	}
  318: 	ttyp->c_iflag = IGNBRK|IGNPAR|ICRNL;
  319: 	ttyp->c_oflag = 0;
  320: 	ttyp->c_cflag = SPEED232|CS8|CLOCAL|CREAD;
  321: 	ttyp->c_lflag = ICANON;
  322: 	ttyp->c_cc[VERASE] = ttyp->c_cc[VKILL] = '\0';
  323: 	if (tcsetattr(fd232, TCSANOW, ttyp) < 0) {
  324: 		msyslog(LOG_ERR,
  325: 			"leitch_start: tcsetattr(%s): %m", leitchdev);
  326: 		goto screwed;
  327: 	}
  328: 	if (tcflush(fd232, TCIOFLUSH) < 0) {
  329: 		msyslog(LOG_ERR,
  330: 			"leitch_start: tcflush(%s): %m", leitchdev);
  331: 		goto screwed;
  332: 	}
  333: 	}
  334: #endif /* HAVE_TERMIOS */
  335: #ifdef STREAM
  336: #if defined(LEITCHCLK)
  337: 	if (ioctl(fd232, I_PUSH, "clk") < 0)
  338: 	    msyslog(LOG_ERR,
  339: 		    "leitch_start: ioctl(%s, I_PUSH, clk): %m", leitchdev);
  340: 	if (ioctl(fd232, CLK_SETSTR, "\n") < 0)
  341: 	    msyslog(LOG_ERR,
  342: 		    "leitch_start: ioctl(%s, CLK_SETSTR): %m", leitchdev);
  343: #endif /* LEITCHCLK */
  344: #endif /* STREAM */
  345: #if defined(HAVE_BSD_TTYS)
  346: 	/*
  347: 	 * 4.3bsd serial line parameters (sgttyb interface)
  348: 	 *
  349: 	 * The LEITCHCLK option provides timestamping at the driver level. 
  350: 	 * It requires the tty_clk line discipline and 4.3bsd or later.
  351: 	 */
  352: 	{	struct sgttyb ttyb;
  353: #if defined(LEITCHCLK)
  354: 	int ldisc = CLKLDISC;
  355: #endif /* LEITCHCLK */
  356: 
  357: 	if (ioctl(fd232, TIOCGETP, &ttyb) < 0) {
  358: 		msyslog(LOG_ERR,
  359: 			"leitch_start: ioctl(%s, TIOCGETP): %m", leitchdev);
  360: 		goto screwed;
  361: 	}
  362: 	ttyb.sg_ispeed = ttyb.sg_ospeed = SPEED232;
  363: #if defined(LEITCHCLK)
  364: 	ttyb.sg_erase = ttyb.sg_kill = '\r';
  365: 	ttyb.sg_flags = RAW;
  366: #else
  367: 	ttyb.sg_erase = ttyb.sg_kill = '\0';
  368: 	ttyb.sg_flags = EVENP|ODDP|CRMOD;
  369: #endif /* LEITCHCLK */
  370: 	if (ioctl(fd232, TIOCSETP, &ttyb) < 0) {
  371: 		msyslog(LOG_ERR,
  372: 			"leitch_start: ioctl(%s, TIOCSETP): %m", leitchdev);
  373: 		goto screwed;
  374: 	}
  375: #if defined(LEITCHCLK)
  376: 	if (ioctl(fd232, TIOCSETD, &ldisc) < 0) {
  377: 		msyslog(LOG_ERR,
  378: 			"leitch_start: ioctl(%s, TIOCSETD): %m",leitchdev);
  379: 		goto screwed;
  380: 	}
  381: #endif /* LEITCHCLK */
  382: 	}
  383: #endif /* HAVE_BSD_TTYS */
  384: 
  385: 	/*
  386: 	 * Set up the structures
  387: 	 */
  388: 	leitch->peer = peer;
  389: 	leitch->unit = unit;
  390: 	leitch->state = STATE_IDLE;
  391: 	leitch->fudge1 = 15;	/* 15ms */
  392: 
  393: 	leitch->leitchio.clock_recv = leitch_receive;
  394: 	leitch->leitchio.srcclock = (caddr_t) leitch;
  395: 	leitch->leitchio.datalen = 0;
  396: 	leitch->leitchio.fd = fd232;
  397: 	if (!io_addclock(&leitch->leitchio)) {
  398: 		leitch->leitchio.fd = -1;
  399: 		goto screwed;
  400: 	}
  401: 
  402: 	/*
  403: 	 * All done.  Initialize a few random peer variables, then
  404: 	 * return success.
  405: 	 */
  406: 	peer->precision = PRECISION;
  407: 	peer->stratum = stratumtouse[unit];
  408: 	peer->refid = refid[unit];
  409: 	unitinuse[unit] = 1;
  410: 	return(1);
  411: 
  412: 	/*
  413: 	 * Something broke; abandon ship.
  414: 	 */
  415:     screwed:
  416: 	close(fd232);
  417: 	return(0);
  418: }
  419: 
  420: /*
  421:  * leitch_receive - receive data from the serial interface on a leitch
  422:  * clock
  423:  */
  424: static void
  425: leitch_receive(
  426: 	struct recvbuf *rbufp
  427: 	)
  428: {
  429: 	struct leitchunit *leitch = (struct leitchunit *)rbufp->recv_srcclock;
  430: 
  431: #ifdef DEBUG
  432: 	if (debug)
  433: 	    fprintf(stderr, "leitch_recieve(%*.*s)\n", 
  434: 		    rbufp->recv_length, rbufp->recv_length,
  435: 		    rbufp->recv_buffer);
  436: #endif
  437: 	if (rbufp->recv_length != 7)
  438: 	    return; /* The date is return with a trailing newline,
  439: 		       discard it. */
  440: 
  441: 	switch (leitch->state) {
  442: 	    case STATE_IDLE:	/* unexpected, discard and resync */
  443: 		return;
  444: 	    case STATE_DATE:
  445: 		if (!leitch_get_date(rbufp,leitch)) {
  446: 			leitch->state = STATE_IDLE;
  447: 			break;
  448: 		}
  449: 		leitch_send(leitch,"T\r");
  450: #ifdef DEBUG
  451: 		if (debug)
  452: 		    fprintf(stderr, "%u\n",leitch->yearday);
  453: #endif
  454: 		leitch->state = STATE_TIME1;
  455: 		break;
  456: 	    case STATE_TIME1:
  457: 		if (!leitch_get_time(rbufp,leitch,1)) {
  458: 		}
  459: 		if (!clocktime(leitch->yearday,leitch->hour,leitch->minute,
  460: 			       leitch->second, 1, rbufp->recv_time.l_ui,
  461: 			       &leitch->yearstart, &leitch->reftime1.l_ui)) {
  462: 			leitch->state = STATE_IDLE;
  463: 			break;
  464: 		}
  465: 		leitch->reftime1.l_uf = 0;
  466: #ifdef DEBUG
  467: 		if (debug)
  468: 		    fprintf(stderr, "%lu\n", (u_long)leitch->reftime1.l_ui);
  469: #endif
  470: 		MSUTOTSF(leitch->fudge1, leitch->reftime1.l_uf);
  471: 		leitch->codetime1 = rbufp->recv_time;
  472: 		leitch->state = STATE_TIME2;
  473: 		break;
  474: 	    case STATE_TIME2:
  475: 		if (!leitch_get_time(rbufp,leitch,2)) {
  476: 		}
  477: 		if (!clocktime(leitch->yearday,leitch->hour,leitch->minute,
  478: 			       leitch->second, 1, rbufp->recv_time.l_ui,
  479: 			       &leitch->yearstart, &leitch->reftime2.l_ui)) {
  480: 			leitch->state = STATE_IDLE;
  481: 			break;
  482: 		}
  483: #ifdef DEBUG
  484: 		if (debug)
  485: 		    fprintf(stderr, "%lu\n", (u_long)leitch->reftime2.l_ui);
  486: #endif
  487: 		MSUTOTSF(leitch->fudge1, leitch->reftime2.l_uf);
  488: 		leitch->codetime2 = rbufp->recv_time;
  489: 		leitch->state = STATE_TIME3;
  490: 		break;
  491: 	    case STATE_TIME3:
  492: 		if (!leitch_get_time(rbufp,leitch,3)) {
  493: 		}
  494: 		if (!clocktime(leitch->yearday,leitch->hour,leitch->minute,
  495: 			       leitch->second, GMT, rbufp->recv_time.l_ui,
  496: 			       &leitch->yearstart, &leitch->reftime3.l_ui)) {
  497: 			leitch->state = STATE_IDLE;
  498: 			break;
  499: 		}
  500: #ifdef DEBUG
  501: 		if (debug)
  502: 		    fprintf(stderr, "%lu\n", (u_long)leitch->reftime3.l_ui);
  503: #endif
  504: 		MSUTOTSF(leitch->fudge1, leitch->reftime3.l_uf);
  505: 		leitch->codetime3 = rbufp->recv_time;
  506: 		leitch_process(leitch);
  507: 		leitch->state = STATE_IDLE;
  508: 		break;
  509: 	    default:
  510: 		msyslog(LOG_ERR,
  511: 			"leitech_receive: invalid state %d unit %d",
  512: 			leitch->state, leitch->unit);
  513: 	}
  514: }
  515: 
  516: /*
  517:  * leitch_process - process a pile of samples from the clock
  518:  *
  519:  * This routine uses a three-stage median filter to calculate offset and
  520:  * dispersion. reduce jitter. The dispersion is calculated as the span
  521:  * of the filter (max - min), unless the quality character (format 2) is
  522:  * non-blank, in which case the dispersion is calculated on the basis of
  523:  * the inherent tolerance of the internal radio oscillator, which is
  524:  * +-2e-5 according to the radio specifications.
  525:  */
  526: static void
  527: leitch_process(
  528: 	struct leitchunit *leitch
  529: 	)
  530: {
  531: 	l_fp off;
  532: 	l_fp tmp_fp;
  533:       /*double doffset;*/
  534: 
  535: 	off = leitch->reftime1;
  536: 	L_SUB(&off,&leitch->codetime1);
  537: 	tmp_fp = leitch->reftime2;
  538: 	L_SUB(&tmp_fp,&leitch->codetime2);
  539: 	if (L_ISGEQ(&off,&tmp_fp))
  540: 	    off = tmp_fp;
  541: 	tmp_fp = leitch->reftime3;
  542: 	L_SUB(&tmp_fp,&leitch->codetime3);
  543: 
  544: 	if (L_ISGEQ(&off,&tmp_fp))
  545: 	    off = tmp_fp;
  546:       /*LFPTOD(&off, doffset);*/
  547: 	refclock_receive(leitch->peer);
  548: }
  549: 
  550: /*
  551:  * days_per_year
  552:  */
  553: static int
  554: days_per_year(
  555: 	int year
  556: 	)
  557: {
  558: 	if (year%4) {	/* not a potential leap year */
  559: 		return (365);
  560: 	} else {
  561: 		if (year % 100) {	/* is a leap year */
  562: 			return (366);
  563: 		} else {	
  564: 			if (year % 400) {
  565: 				return (365);
  566: 			} else {
  567: 				return (366);
  568: 			}
  569: 		}
  570: 	}
  571: }
  572: 
  573: static int
  574: leitch_get_date(
  575: 	struct recvbuf *rbufp,
  576: 	struct leitchunit *leitch
  577: 	)
  578: {
  579: 	int i;
  580: 
  581: 	if (rbufp->recv_length < 6)
  582: 	    return(0);
  583: #undef  BAD    /* confict: defined as (-1) in AIX sys/param.h */
  584: #define BAD(A) (rbufp->recv_buffer[A] < '0') || (rbufp->recv_buffer[A] > '9')
  585: 	if (BAD(0)||BAD(1)||BAD(2)||BAD(3)||BAD(4)||BAD(5))
  586: 	    return(0);
  587: #define ATOB(A) ((rbufp->recv_buffer[A])-'0')
  588: 	leitch->year = ATOB(0)*10 + ATOB(1);
  589: 	leitch->month = ATOB(2)*10 + ATOB(3);
  590: 	leitch->day = ATOB(4)*10 + ATOB(5);
  591: 
  592: 	/* sanity checks */
  593: 	if (leitch->month > 12)
  594: 	    return(0);
  595: 	if (leitch->day > days_in_month[leitch->month-1])
  596: 	    return(0);
  597: 
  598: 	/* calculate yearday */
  599: 	i = 0;
  600: 	leitch->yearday = leitch->day;
  601: 
  602: 	while ( i < (leitch->month-1) )
  603: 	    leitch->yearday += days_in_month[i++];
  604: 
  605: 	if ((days_per_year((leitch->year>90?1900:2000)+leitch->year)==365) && 
  606: 	    leitch->month > 2)
  607: 	    leitch->yearday--;
  608: 
  609: 	return(1);
  610: }
  611: 
  612: /*
  613:  * leitch_get_time
  614:  */
  615: static int
  616: leitch_get_time(
  617: 	struct recvbuf *rbufp,
  618: 	struct leitchunit *leitch,
  619: 	int which
  620: 	)
  621: {
  622: 	if (BAD(0)||BAD(1)||BAD(2)||BAD(3)||BAD(4)||BAD(5))
  623: 	    return(0);
  624: 	leitch->hour = ATOB(0)*10 +ATOB(1);
  625: 	leitch->minute = ATOB(2)*10 +ATOB(3);
  626: 	leitch->second = ATOB(4)*10 +ATOB(5);
  627: 
  628: 	if ((leitch->hour > 23) || (leitch->minute > 60) ||
  629: 	    (leitch->second > 60))
  630: 	    return(0);
  631: 	return(1);
  632: }
  633: 
  634: #else
  635: int refclock_leitch_bs;
  636: #endif /* REFCLOCK */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>