xref: /freebsd/contrib/ntp/ntpd/refclock_jupiter.c (revision 1b6c76a2fe091c74f08427e6c870851025a9cf67)
1 /*
2  * Copyright (c) 1997, 1998
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Lawrence Berkeley Laboratory.
17  * 4. The name of the University may not be used to endorse or promote
18  *    products derived from this software without specific prior
19  *    written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 #ifdef HAVE_CONFIG_H
35 # include <config.h>
36 #endif
37 
38 #if defined(REFCLOCK) && defined(CLOCK_JUPITER) && defined(PPS)
39 
40 #include <stdio.h>
41 #include <ctype.h>
42 #include <sys/time.h>
43 
44 #include "ntpd.h"
45 #include "ntp_io.h"
46 #include "ntp_refclock.h"
47 #include "ntp_unixtime.h"
48 #include "ntp_stdlib.h"
49 #include "ntp_calendar.h"
50 
51 #include "jupiter.h"
52 
53 #include <sys/ppsclock.h>
54 
55 #ifdef XNTP_BIG_ENDIAN
56 #define getshort(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff))
57 #define putshort(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff))
58 #else
59 #define getshort(s) (s)
60 #define putshort(s) (s)
61 #endif
62 
63 /* XXX */
64 #ifdef sun
65 char *strerror(int);
66 #endif
67 
68 /*
69  * This driver supports the Rockwell Jupiter GPS Receiver board
70  * adapted to precision timing applications.  It requires the
71  * ppsclock line discipline or streams module described in the
72  * Line Disciplines and Streams Drivers page. It also requires a
73  * gadget box and 1-PPS level converter, such as described in the
74  * Pulse-per-second (PPS) Signal Interfacing page.
75  *
76  * It may work (with minor modifications) with other Rockwell GPS
77  * receivers such as the CityTracker.
78  */
79 
80 /*
81  * GPS Definitions
82  */
83 #define	DEVICE		"/dev/gps%d"	/* device name and unit */
84 #define	SPEED232	B9600		/* baud */
85 
86 /*
87  * The number of raw samples which we acquire to derive a single estimate.
88  * NSAMPLES ideally should not exceed the default poll interval 64.
89  * NKEEP must be a power of 2 to simplify the averaging process.
90  */
91 #define NSAMPLES	64
92 #define NKEEP		8
93 #define REFCLOCKMAXDISPERSE .25	/* max sample dispersion */
94 
95 /*
96  * Radio interface parameters
97  */
98 #define	PRECISION	(-18)	/* precision assumed (about 4 us) */
99 #define	REFID	"GPS\0"		/* reference id */
100 #define	DESCRIPTION	"Rockwell Jupiter GPS Receiver" /* who we are */
101 #define	DEFFUDGETIME	0	/* default fudge time (ms) */
102 
103 /* Unix timestamp for the GPS epoch: January 6, 1980 */
104 #define GPS_EPOCH 315964800
105 
106 /* Double short to unsigned int */
107 #define DS2UI(p) ((getshort((p)[1]) << 16) | getshort((p)[0]))
108 
109 /* Double short to signed int */
110 #define DS2I(p) ((getshort((p)[1]) << 16) | getshort((p)[0]))
111 
112 /* One week's worth of seconds */
113 #define WEEKSECS (7 * 24 * 60 * 60)
114 
115 /*
116  * Jupiter unit control structure.
117  */
118 struct jupiterunit {
119 	u_int  pollcnt;			/* poll message counter */
120 	u_int  polled;			/* Hand in a time sample? */
121 	u_int  lastserial;		/* last pps serial number */
122 	struct ppsclockev ppsev;	/* PPS control structure */
123 	u_int gweek;			/* current GPS week number */
124 	u_int32 lastsweek;		/* last seconds into GPS week */
125 	u_int32 timecode;		/* current ntp timecode */
126 	u_int32 stime;			/* used to detect firmware bug */
127 	int wantid;			/* don't reconfig on channel id msg */
128 	u_int  moving;			/* mobile platform? */
129 	u_long sloppyclockflag;		/* fudge flags */
130 	u_int  known;			/* position known yet? */
131 	int    coderecv;		/* total received samples */
132 	int    nkeep;			/* number of samples to preserve */
133 	int    rshift;			/* number of rshifts for division */
134 	l_fp   filter[NSAMPLES];	/* offset filter */
135 	l_fp   lastref;			/* last reference timestamp */
136 	u_short sbuf[512];		/* local input buffer */
137 	int ssize;			/* space used in sbuf */
138 };
139 
140 /*
141  * Function prototypes
142  */
143 static	void	jupiter_canmsg	P((struct peer *, u_int));
144 static	u_short	jupiter_cksum	P((u_short *, u_int));
145 #ifdef QSORT_USES_VOID_P
146 	int	jupiter_cmpl_fp	P((const void *, const void *));
147 #else
148 	int	jupiter_cmpl_fp	P((const l_fp *, const l_fp *));
149 #endif /* not QSORT_USES_VOID_P */
150 static	void	jupiter_config	P((struct peer *));
151 static	void	jupiter_debug	P((struct peer *, char *, ...))
152     __attribute__ ((format (printf, 2, 3)));
153 static	char *	jupiter_offset	P((struct peer *));
154 static	char *	jupiter_parse_t	P((struct peer *, u_short *));
155 static	void	jupiter_platform	P((struct peer *, u_int));
156 static	void	jupiter_poll	P((int, struct peer *));
157 static	int	jupiter_pps	P((struct peer *));
158 static	char *	jupiter_process	P((struct peer *));
159 static	int	jupiter_recv	P((struct peer *));
160 static	void	jupiter_receive P((register struct recvbuf *rbufp));
161 static	void	jupiter_reqmsg	P((struct peer *, u_int, u_int));
162 static	void	jupiter_reqonemsg	P((struct peer *, u_int));
163 static	char *	jupiter_send	P((struct peer *, struct jheader *));
164 static	void	jupiter_shutdown	P((int, struct peer *));
165 static	int	jupiter_start	P((int, struct peer *));
166 static	int	jupiter_ttyinit	P((struct peer *, int));
167 
168 /*
169  * Transfer vector
170  */
171 struct	refclock refclock_jupiter = {
172 	jupiter_start,		/* start up driver */
173 	jupiter_shutdown,	/* shut down driver */
174 	jupiter_poll,		/* transmit poll message */
175 	noentry,		/* (clock control) */
176 	noentry,		/* (clock init) */
177 	noentry,		/* (clock buginfo) */
178 	NOFLAGS			/* not used */
179 };
180 
181 /*
182  * jupiter_start - open the devices and initialize data for processing
183  */
184 static int
185 jupiter_start(
186 	register int unit,
187 	register struct peer *peer
188 	)
189 {
190 	struct refclockproc *pp;
191 	register struct jupiterunit *up;
192 	register int fd;
193 	char gpsdev[20];
194 
195 	/*
196 	 * Open serial port
197 	 */
198 	(void)sprintf(gpsdev, DEVICE, unit);
199 	fd = open(gpsdev, O_RDWR
200 #ifdef O_NONBLOCK
201 	    | O_NONBLOCK
202 #endif
203 	    , 0);
204 	if (fd < 0) {
205 		jupiter_debug(peer, "jupiter_start: open %s: %s\n",
206 		    gpsdev, strerror(errno));
207 		return (0);
208 	}
209 	if (!jupiter_ttyinit(peer, fd))
210 		return (0);
211 
212 	/* Allocate unit structure */
213 	if ((up = (struct jupiterunit *)
214 	    emalloc(sizeof(struct jupiterunit))) == NULL) {
215 		(void) close(fd);
216 		return (0);
217 	}
218 	memset((char *)up, 0, sizeof(struct jupiterunit));
219 	pp = peer->procptr;
220 	pp->io.clock_recv = jupiter_receive;
221 	pp->io.srcclock = (caddr_t)peer;
222 	pp->io.datalen = 0;
223 	pp->io.fd = fd;
224 	if (!io_addclock(&pp->io)) {
225 		(void) close(fd);
226 		free(up);
227 		return (0);
228 	}
229 	pp->unitptr = (caddr_t)up;
230 
231 	/*
232 	 * Initialize miscellaneous variables
233 	 */
234 	peer->precision = PRECISION;
235 	pp->clockdesc = DESCRIPTION;
236 	memcpy((char *)&pp->refid, REFID, 4);
237 
238 
239 	/* Ensure the receiver is properly configured */
240 	jupiter_config(peer);
241 
242 	/* Turn on pulse gathering by requesting the first sample */
243 	if (ioctl(fd, CIOGETEV, (caddr_t)&up->ppsev) < 0) {
244 		jupiter_debug(peer, "jupiter_ttyinit: CIOGETEV: %s\n",
245 		    strerror(errno));
246 		(void) close(fd);
247 		free(up);
248 		return (0);
249 	}
250 	up->lastserial = up->ppsev.serial;
251 	memset(&up->ppsev, 0, sizeof(up->ppsev));
252 	return (1);
253 }
254 
255 /*
256  * jupiter_shutdown - shut down the clock
257  */
258 static void
259 jupiter_shutdown(register int unit, register struct peer *peer)
260 {
261 	register struct jupiterunit *up;
262 	struct refclockproc *pp;
263 
264 	pp = peer->procptr;
265 	up = (struct jupiterunit *)pp->unitptr;
266 	io_closeclock(&pp->io);
267 	free(up);
268 }
269 
270 /*
271  * jupiter_config - Configure the receiver
272  */
273 static void
274 jupiter_config(register struct peer *peer)
275 {
276 	register int i;
277 	register struct jupiterunit *up;
278 	register struct refclockproc *pp;
279 
280 	pp = peer->procptr;
281 	up = (struct jupiterunit *)pp->unitptr;
282 
283 	/*
284 	 * Initialize the unit variables
285 	 *
286 	 * STRANGE BEHAVIOUR WARNING: The fudge flags are not available
287 	 * at the time jupiter_start is called.  These are set later,
288 	 * and so the code must be prepared to handle changing flags.
289 	 */
290 	up->sloppyclockflag = pp->sloppyclockflag;
291 	if (pp->sloppyclockflag & CLK_FLAG2) {
292 		up->moving = 1;		/* Receiver on mobile platform */
293 		msyslog(LOG_DEBUG, "jupiter_config: mobile platform");
294 	} else {
295 		up->moving = 0;		/* Static Installation */
296 	}
297 
298 	/* XXX fludge flags don't make the trip from the config to here... */
299 #ifdef notdef
300 	/* Configure for trailing edge triggers */
301 #ifdef CIOSETTET
302 	i = ((pp->sloppyclockflag & CLK_FLAG3) != 0);
303 	jupiter_debug(peer, "jupiter_configure: (sloppyclockflag 0x%lx)\n",
304 	    pp->sloppyclockflag);
305 	if (ioctl(pp->io.fd, CIOSETTET, (char *)&i) < 0)
306 		msyslog(LOG_DEBUG, "jupiter_configure: CIOSETTET %d: %m", i);
307 #else
308 	if (pp->sloppyclockflag & CLK_FLAG3)
309 		msyslog(LOG_DEBUG, "jupiter_configure: \
310 No kernel support for trailing edge trigger");
311 #endif
312 #endif
313 
314 	up->pollcnt     = 2;
315 	up->polled      = 0;
316 	up->known       = 0;
317 	up->gweek = 0;
318 	up->lastsweek = 2 * WEEKSECS;
319 	up->timecode = 0;
320 	up->stime = 0;
321 	up->ssize = 0;
322 	up->coderecv    = 0;
323 	up->nkeep       = NKEEP;
324 	if (up->nkeep > NSAMPLES)
325 		up->nkeep = NSAMPLES;
326 	if (up->nkeep >= 1)
327 		up->rshift = 0;
328 	if (up->nkeep >= 2)
329 		up->rshift = 1;
330 	if (up->nkeep >= 4)
331 		up->rshift = 2;
332 	if (up->nkeep >= 8)
333 		up->rshift = 3;
334 	if (up->nkeep >= 16)
335 		up->rshift = 4;
336 	if (up->nkeep >= 32)
337 		up->rshift = 5;
338 	if (up->nkeep >= 64)
339 		up->rshift = 6;
340 	up->nkeep = 1;
341 	i = up->rshift;
342 	while (i > 0) {
343 		up->nkeep *= 2;
344 		i--;
345 	}
346 
347 	/* Stop outputting all messages */
348 	jupiter_canmsg(peer, JUPITER_ALL);
349 
350 	/* Request the receiver id so we can syslog the firmware version */
351 	jupiter_reqonemsg(peer, JUPITER_O_ID);
352 
353 	/* Flag that this the id was requested (so we don't get called again) */
354 	up->wantid = 1;
355 
356 	/* Request perodic time mark pulse messages */
357 	jupiter_reqmsg(peer, JUPITER_O_PULSE, 1);
358 
359 	/* Set application platform type */
360 	if (up->moving)
361 		jupiter_platform(peer, JUPITER_I_PLAT_MED);
362 	else
363 		jupiter_platform(peer, JUPITER_I_PLAT_LOW);
364 }
365 
366 /*
367  * jupiter_poll - jupiter watchdog routine
368  */
369 static void
370 jupiter_poll(register int unit, register struct peer *peer)
371 {
372 	register struct jupiterunit *up;
373 	register struct refclockproc *pp;
374 
375 	pp = peer->procptr;
376 	up = (struct jupiterunit *)pp->unitptr;
377 
378 	/*
379 	 * You don't need to poll this clock.  It puts out timecodes
380 	 * once per second.  If asked for a timestamp, take note.
381 	 * The next time a timecode comes in, it will be fed back.
382 	 */
383 
384 	/*
385 	 * If we haven't had a response in a while, reset the receiver.
386 	 */
387 	if (up->pollcnt > 0) {
388 		up->pollcnt--;
389 	} else {
390 		refclock_report(peer, CEVNT_TIMEOUT);
391 
392 		/* Request the receiver id to trigger a reconfig */
393 		jupiter_reqonemsg(peer, JUPITER_O_ID);
394 		up->wantid = 0;
395 	}
396 
397 	/*
398 	 * polled every 64 seconds. Ask jupiter_receive to hand in
399 	 * a timestamp.
400 	 */
401 	up->polled = 1;
402 	pp->polls++;
403 }
404 
405 /*
406  * jupiter_receive - receive gps data
407  * Gag me!
408  */
409 static void
410 jupiter_receive(register struct recvbuf *rbufp)
411 {
412 	register int bpcnt, cc, size, ppsret;
413 	register u_int32 last_timecode, laststime;
414 	register char *cp;
415 	register u_char *bp;
416 	register u_short *sp;
417 	register u_long sloppyclockflag;
418 	register struct jupiterunit *up;
419 	register struct jid *ip;
420 	register struct jheader *hp;
421 	register struct refclockproc *pp;
422 	register struct peer *peer;
423 
424 	/* Initialize pointers and read the timecode and timestamp */
425 	peer = (struct peer *)rbufp->recv_srcclock;
426 	pp = peer->procptr;
427 	up = (struct jupiterunit *)pp->unitptr;
428 
429 	/*
430 	 * If operating mode has been changed, then reinitialize the receiver
431 	 * before doing anything else.
432 	 */
433 /* XXX Sloppy clock flags are broken!! */
434 	sloppyclockflag = up->sloppyclockflag;
435 	up->sloppyclockflag = pp->sloppyclockflag;
436 	if ((pp->sloppyclockflag & CLK_FLAG2) !=
437 	    (sloppyclockflag & CLK_FLAG2)) {
438 		jupiter_debug(peer,
439 		    "jupiter_receive: mode switch: reset receiver\n");
440 		jupiter_config(peer);
441 		return;
442 	}
443 
444 	up->pollcnt = 2;
445 
446 	bp = (u_char *)rbufp->recv_buffer;
447 	bpcnt = rbufp->recv_length;
448 
449 	/* This shouldn't happen */
450 	if (bpcnt > sizeof(up->sbuf) - up->ssize)
451 		bpcnt = sizeof(up->sbuf) - up->ssize;
452 
453 	/* Append to input buffer */
454 	memcpy((u_char *)up->sbuf + up->ssize, bp, bpcnt);
455 	up->ssize += bpcnt;
456 
457 	/* While there's at least a header and we parse a intact message */
458 	while (up->ssize > sizeof(*hp) && (cc = jupiter_recv(peer)) > 0) {
459 		hp = (struct jheader *)up->sbuf;
460 		sp = (u_short *)(hp + 1);
461 		size = cc - sizeof(*hp);
462 		switch (getshort(hp->id)) {
463 
464 		case JUPITER_O_PULSE:
465 			if (size != sizeof(struct jpulse)) {
466 				jupiter_debug(peer,
467 				    "jupiter_receive: pulse: len %d != %u\n",
468 				    size, (int)sizeof(struct jpulse));
469 				refclock_report(peer, CEVNT_BADREPLY);
470 				break;
471 			}
472 
473 			/*
474 			 * There appears to be a firmware bug related
475 			 * to the pulse message; in addition to the one
476 			 * per second messages, we get an extra pulse
477 			 * message once an hour (on the anniversary of
478 			 * the cold start). It seems to come 200 ms
479 			 * after the one requested. So if we've seen a
480 			 * pulse message in the last 210 ms, we skip
481 			 * this one.
482 			 */
483 			laststime = up->stime;
484 			up->stime = DS2UI(((struct jpulse *)sp)->stime);
485 			if (laststime != 0 && up->stime - laststime <= 21) {
486 				jupiter_debug(peer, "jupiter_receive: \
487 avoided firmware bug (stime %.2f, laststime %.2f)\n",
488     (double)up->stime * 0.01, (double)laststime * 0.01);
489 				break;
490 			}
491 
492 			/* Retrieve pps timestamp */
493 			ppsret = jupiter_pps(peer);
494 
495 			/* Parse timecode (even when there's no pps) */
496 			last_timecode = up->timecode;
497 			if ((cp = jupiter_parse_t(peer, sp)) != NULL) {
498 				jupiter_debug(peer,
499 				    "jupiter_receive: pulse: %s\n", cp);
500 				break;
501 			}
502 
503 			/* Bail if we didn't get a pps timestamp */
504 			if (ppsret)
505 				break;
506 
507 			/* Bail if we don't have the last timecode yet */
508 			if (last_timecode == 0)
509 				break;
510 
511 			/* Add the new sample to a median filter */
512 			if ((cp = jupiter_offset(peer)) != NULL) {
513 				jupiter_debug(peer,
514 				    "jupiter_receive: offset: %s\n", cp);
515 				refclock_report(peer, CEVNT_BADTIME);
516 				break;
517 			}
518 
519 			/*
520 			 * The clock will blurt a timecode every second
521 			 * but we only want one when polled.  If we
522 			 * havn't been polled, bail out.
523 			 */
524 			if (!up->polled)
525 				break;
526 
527 			/*
528 			 * It's a live one!  Remember this time.
529 			 */
530 			pp->lasttime = current_time;
531 
532 			/*
533 			 * Determine the reference clock offset and
534 			 * dispersion. NKEEP of NSAMPLE offsets are
535 			 * passed through a median filter.
536 			 * Save the (filtered) offset and dispersion in
537 			 * pp->offset and pp->disp.
538 			 */
539 			if ((cp = jupiter_process(peer)) != NULL) {
540 				jupiter_debug(peer,
541 				    "jupiter_receive: process: %s\n", cp);
542 				refclock_report(peer, CEVNT_BADTIME);
543 				break;
544 			}
545 			/*
546 			 * Return offset and dispersion to control
547 			 * module. We use lastrec as both the reference
548 			 * time and receive time in order to avoid
549 			 * being cute, like setting the reference time
550 			 * later than the receive time, which may cause
551 			 * a paranoid protocol module to chuck out the
552 			 * data.
553 			 */
554 			jupiter_debug(peer,
555 			    "jupiter_receive: process time: \
556 %4d-%03d %02d:%02d:%02d at %s, %s\n",
557 			    pp->year, pp->day,
558 			    pp->hour, pp->minute, pp->second,
559 			    prettydate(&pp->lastrec), lfptoa(&pp->offset, 6));
560 
561 			refclock_receive(peer);
562 
563 			/*
564 			 * We have succeeded in answering the poll.
565 			 * Turn off the flag and return
566 			 */
567 			up->polled = 0;
568 			break;
569 
570 		case JUPITER_O_ID:
571 			if (size != sizeof(struct jid)) {
572 				jupiter_debug(peer,
573 				    "jupiter_receive: id: len %d != %u\n",
574 				    size, (int)sizeof(struct jid));
575 				refclock_report(peer, CEVNT_BADREPLY);
576 				break;
577 			}
578 			/*
579 			 * If we got this message because the Jupiter
580 			 * just powered up, it needs to be reconfigured.
581 			 */
582 			ip = (struct jid *)sp;
583 			jupiter_debug(peer,
584 			    "jupiter_receive: >> %s chan ver %s, %s (%s)\n",
585 			    ip->chans, ip->vers, ip->date, ip->opts);
586 			msyslog(LOG_DEBUG,
587 			    "jupiter_receive: %s chan ver %s, %s (%s)\n",
588 			    ip->chans, ip->vers, ip->date, ip->opts);
589 			if (up->wantid)
590 				up->wantid = 0;
591 			else {
592 				jupiter_debug(peer,
593 				    "jupiter_receive: reset receiver\n");
594 				jupiter_config(peer);
595 				/* Rese since jupiter_config() just zeroed it */
596 				up->ssize = cc;
597 			}
598 			break;
599 
600 		default:
601 			jupiter_debug(peer,
602 			    "jupiter_receive: >> unknown message id %d\n",
603 			    getshort(hp->id));
604 			break;
605 		}
606 		up->ssize -= cc;
607 		if (up->ssize < 0) {
608 			fprintf(stderr, "jupiter_recv: negative ssize!\n");
609 			abort();
610 		} else if (up->ssize > 0)
611 			memcpy(up->sbuf, (u_char *)up->sbuf + cc, up->ssize);
612 	}
613 	record_clock_stats(&peer->srcadr, "<timecode is binary>");
614 }
615 
616 /*
617  * jupiter_offset - Calculate the offset, and add to the rolling filter.
618  */
619 static char *
620 jupiter_offset(register struct peer *peer)
621 {
622 	register struct jupiterunit *up;
623 	register struct refclockproc *pp;
624 	register int i;
625 	l_fp offset;
626 
627 	pp = peer->procptr;
628 	up = (struct jupiterunit *)pp->unitptr;
629 
630 	/*
631 	 * Calculate the offset
632 	 */
633 	if (!clocktime(pp->day, pp->hour, pp->minute, pp->second, GMT,
634 		pp->lastrec.l_ui, &pp->yearstart, &offset.l_ui)) {
635 		return ("jupiter_process: clocktime failed");
636 	}
637 	if (pp->usec) {
638 		TVUTOTSF(pp->usec, offset.l_uf);
639 	} else {
640 		MSUTOTSF(pp->msec, offset.l_uf);
641 	}
642 	L_ADD(&offset, &pp->fudgetime1);
643 	up->lastref = offset;   /* save last reference time */
644 	L_SUB(&offset, &pp->lastrec); /* form true offset */
645 
646 	/*
647 	 * A rolling filter.  Initialize first time around.
648 	 */
649 	i = ((up->coderecv)) % NSAMPLES;
650 
651 	up->filter[i] = offset;
652 	if (up->coderecv == 0)
653 		for (i = 1; (u_int) i < NSAMPLES; i++)
654 			up->filter[i] = up->filter[0];
655 	up->coderecv++;
656 
657 	return (NULL);
658 }
659 
660 /*
661  * jupiter_process - process the sample from the clock,
662  * passing it through a median filter and optionally averaging
663  * the samples.  Returns offset and dispersion in "up" structure.
664  */
665 static char *
666 jupiter_process(register struct peer *peer)
667 {
668 	register struct jupiterunit *up;
669 	register struct refclockproc *pp;
670 	register int i, n;
671 	register int j, k;
672 	l_fp offset, median, lftmp;
673 	u_fp disp;
674 	l_fp off[NSAMPLES];
675 
676 	pp = peer->procptr;
677 	up = (struct jupiterunit *)pp->unitptr;
678 
679 	/*
680 	 * Copy the raw offsets and sort into ascending order
681 	 */
682 	for (i = 0; i < NSAMPLES; i++)
683 		off[i] = up->filter[i];
684 	qsort((char *)off, NSAMPLES, sizeof(l_fp), jupiter_cmpl_fp);
685 
686 	/*
687 	 * Reject the furthest from the median of NSAMPLES samples until
688 	 * NKEEP samples remain.
689 	 */
690 	i = 0;
691 	n = NSAMPLES;
692 	while ((n - i) > up->nkeep) {
693 		lftmp = off[n - 1];
694 		median = off[(n + i) / 2];
695 		L_SUB(&lftmp, &median);
696 		L_SUB(&median, &off[i]);
697 		if (L_ISHIS(&median, &lftmp)) {
698 			/* reject low end */
699 			i++;
700 		} else {
701 			/* reject high end */
702 			n--;
703 		}
704 	}
705 
706 	/*
707 	 * Copy key values to the billboard to measure performance.
708 	 */
709 	pp->lastref = up->lastref;
710 	pp->coderecv = up->coderecv;
711 	pp->filter[0] = off[0];			/* smallest offset */
712 	pp->filter[1] = off[NSAMPLES-1];	/* largest offset */
713 	for (j = 2, k = i; k < n; j++, k++)
714 		pp->filter[j] = off[k];		/* offsets actually examined */
715 
716 	/*
717 	 * Compute the dispersion based on the difference between the
718 	 * extremes of the remaining offsets. Add to this the time since
719 	 * the last clock update, which represents the dispersion
720 	 * increase with time. We know that NTP_MAXSKEW is 16. If the
721 	 * sum is greater than the allowed sample dispersion, bail out.
722 	 * If the loop is unlocked, return the most recent offset;
723 	 * otherwise, return the median offset.
724 	 */
725 	lftmp = off[n - 1];
726 	L_SUB(&lftmp, &off[i]);
727 	disp = LFPTOFP(&lftmp);
728 	if (disp > REFCLOCKMAXDISPERSE)
729 		return ("Maximum dispersion exceeded");
730 
731 	/*
732 	 * Now compute the offset estimate.  If fudge flag 1
733 	 * is set, average the remainder, otherwise pick the
734 	 * median.
735 	 */
736 	if (pp->sloppyclockflag & CLK_FLAG1) {
737 		L_CLR(&lftmp);
738 		while (i < n) {
739 			L_ADD(&lftmp, &off[i]);
740 			i++;
741 		}
742 		i = up->rshift;
743 		while (i > 0) {
744 			L_RSHIFT(&lftmp);
745 			i--;
746 		}
747 		offset = lftmp;
748 	} else {
749 		i = (n + i) / 2;
750 		offset = off[i];
751 	}
752 
753 	/*
754 	 * The payload: filtered offset and dispersion.
755 	 */
756 
757 	pp->offset = offset;
758 	pp->disp = disp;
759 
760 	return (NULL);
761 
762 }
763 
764 /* Compare two l_fp's, used with qsort() */
765 #ifdef QSORT_USES_VOID_P
766 int
767 jupiter_cmpl_fp(register const void *p1, register const void *p2)
768 #else
769 int
770 jupiter_cmpl_fp(register const l_fp *fp1, register const l_fp *fp2)
771 #endif
772 {
773 #ifdef QSORT_USES_VOID_P
774 	register const l_fp *fp1 = (const l_fp *)p1;
775 	register const l_fp *fp2 = (const l_fp *)p2;
776 #endif
777 
778 	if (!L_ISGEQ(fp1, fp2))
779 		return (-1);
780 	if (L_ISEQU(fp1, fp2))
781 		return (0);
782 	return (1);
783 }
784 
785 static char *
786 jupiter_parse_t(register struct peer *peer, register u_short *sp)
787 {
788 	register struct refclockproc *pp;
789 	register struct jupiterunit *up;
790 	register struct tm *tm;
791 	register char *cp;
792 	register struct jpulse *jp;
793 	register struct calendar *jt;
794 	register u_int32 sweek;
795 	register u_int32 last_timecode;
796 	register u_short flags;
797 	time_t t;
798 	struct calendar cal;
799 
800 	pp = peer->procptr;
801 	up = (struct jupiterunit *)pp->unitptr;
802 	jp = (struct jpulse *)sp;
803 
804 	/* The timecode is presented as seconds into the current GPS week */
805 	sweek = DS2UI(jp->sweek);
806 
807 	/*
808 	 * If we don't know the current GPS week, calculate it from the
809 	 * current time. (It's too bad they didn't include this
810 	 * important value in the pulse message). We'd like to pick it
811 	 * up from one of the other messages like gpos or chan but they
812 	 * don't appear to be synchronous with time keeping and changes
813 	 * too soon (something like 10 seconds before the new GPS
814 	 * week).
815 	 *
816 	 * If we already know the current GPS week, increment it when
817 	 * we wrap into a new week.
818 	 */
819 	if (up->gweek == 0)
820 		up->gweek = (time(NULL) - GPS_EPOCH) / WEEKSECS;
821 	else if (sweek == 0 && up->lastsweek == WEEKSECS - 1) {
822 		++up->gweek;
823 		jupiter_debug(peer,
824 		    "jupiter_parse_t: NEW gps week %u\n", up->gweek);
825 	}
826 
827 	/*
828 	 * See if the sweek stayed the same (this happens when there is
829 	 * no pps pulse).
830 	 *
831 	 * Otherwise, look for time warps:
832 	 *
833 	 *   - we have stored at least one lastsweek and
834 	 *   - the sweek didn't increase by one and
835 	 *   - we didn't wrap to a new GPS week
836 	 *
837 	 * Then we warped.
838 	 */
839 	if (up->lastsweek == sweek)
840 		jupiter_debug(peer,
841 		    "jupiter_parse_t: gps sweek not incrementing (%d)\n",
842 		    sweek);
843 	else if (up->lastsweek != 2 * WEEKSECS &&
844 	    up->lastsweek + 1 != sweek &&
845 	    !(sweek == 0 && up->lastsweek == WEEKSECS - 1))
846 		jupiter_debug(peer,
847 		    "jupiter_parse_t: gps sweek jumped (was %d, now %d)\n",
848 		    up->lastsweek, sweek);
849 	up->lastsweek = sweek;
850 
851 	/* This timecode describes next pulse */
852 	last_timecode = up->timecode;
853 	up->timecode = (u_int32)JAN_1970 +
854 	    GPS_EPOCH + (up->gweek * WEEKSECS) + sweek;
855 
856 	if (last_timecode == 0)
857 		/* XXX debugging */
858 		jupiter_debug(peer,
859 		    "jupiter_parse_t: UTC <none> (gweek/sweek %u/%u)\n",
860 		    up->gweek, sweek);
861 	else {
862 		/* XXX debugging */
863 		t = last_timecode - (u_int32)JAN_1970;
864 		tm = gmtime(&t);
865 		cp = asctime(tm);
866 
867 		jupiter_debug(peer,
868 		    "jupiter_parse_t: UTC %.24s (gweek/sweek %u/%u)\n",
869 		    cp, up->gweek, sweek);
870 
871 		/* Billboard last_timecode (which is now the current time) */
872 		jt = &cal;
873 		caljulian(last_timecode, jt);
874 		pp = peer->procptr;
875 		pp->year = jt->year;
876 		pp->day = jt->yearday;
877 		pp->hour = jt->hour;
878 		pp->minute = jt->minute;
879 		pp->second = jt->second;
880 		pp->msec = 0;
881 		pp->usec = 0;
882 	}
883 
884 	/* XXX debugging */
885 	tm = gmtime(&up->ppsev.tv.tv_sec);
886 	cp = asctime(tm);
887 	flags = getshort(jp->flags);
888 	jupiter_debug(peer,
889 	    "jupiter_parse_t: PPS %.19s.%06lu %.4s (serial %u)%s\n",
890 	    cp, up->ppsev.tv.tv_usec, cp + 20, up->ppsev.serial,
891 	    (flags & JUPITER_O_PULSE_VALID) == 0 ?
892 	    " NOT VALID" : "");
893 
894 	/* Toss if not designated "valid" by the gps */
895 	if ((flags & JUPITER_O_PULSE_VALID) == 0) {
896 		refclock_report(peer, CEVNT_BADTIME);
897 		return ("time mark not valid");
898 	}
899 
900 	/* We better be sync'ed to UTC... */
901 	if ((flags & JUPITER_O_PULSE_UTC) == 0) {
902 		refclock_report(peer, CEVNT_BADTIME);
903 		return ("time mark not sync'ed to UTC");
904 	}
905 
906 	return (NULL);
907 }
908 
909 /*
910  * Process a PPS signal, returning a timestamp.
911  */
912 static int
913 jupiter_pps(register struct peer *peer)
914 {
915 	register struct refclockproc *pp;
916 	register struct jupiterunit *up;
917 	register int firsttime;
918 	struct timeval ntp_tv;
919 
920 	pp = peer->procptr;
921 	up = (struct jupiterunit *)pp->unitptr;
922 
923 	/*
924 	 * Grab the timestamp of the PPS signal.
925 	 */
926 	firsttime = (up->ppsev.tv.tv_sec == 0);
927 	if (ioctl(pp->io.fd, CIOGETEV, (caddr_t)&up->ppsev) < 0) {
928 		/* XXX Actually, if this fails, we're pretty much screwed */
929 		jupiter_debug(peer, "jupiter_pps: CIOGETEV: %s\n",
930 		    strerror(errno));
931 		refclock_report(peer, CEVNT_FAULT);
932 		return (1);
933 	}
934 
935 	/*
936 	 * Check pps serial number against last one
937 	 */
938 	if (!firsttime && up->lastserial + 1 != up->ppsev.serial) {
939 		if (up->ppsev.serial == up->lastserial)
940 			jupiter_debug(peer, "jupiter_pps: no new pps event\n");
941 		else
942 			jupiter_debug(peer,
943 			    "jupiter_pps: missed %d pps events\n",
944 				up->ppsev.serial - up->lastserial - 1);
945 		up->lastserial = up->ppsev.serial;
946 		refclock_report(peer, CEVNT_FAULT);
947 		return (1);
948 	}
949 	up->lastserial = up->ppsev.serial;
950 
951 	/*
952 	 * Return the timestamp in pp->lastrec
953 	 */
954 	ntp_tv = up->ppsev.tv;
955 	ntp_tv.tv_sec += (u_int32)JAN_1970;
956 	TVTOTS(&ntp_tv, &pp->lastrec);
957 
958 	return (0);
959 }
960 
961 /*
962  * jupiter_debug - print debug messages
963  */
964 #if defined(__STDC__)
965 static void
966 jupiter_debug(struct peer *peer, char *fmt, ...)
967 #else
968 static void
969 jupiter_debug(peer, fmt, va_alist)
970 	struct peer *peer;
971 	char *fmt;
972 #endif /* __STDC__ */
973 {
974 	va_list ap;
975 
976 	if (debug) {
977 
978 #if defined(__STDC__)
979 		va_start(ap, fmt);
980 #else
981 		va_start(ap);
982 #endif /* __STDC__ */
983 		/*
984 		 * Print debug message to stdout
985 		 * In the future, we may want to get get more creative...
986 		 */
987 		vfprintf(stderr, fmt, ap);
988 
989 		va_end(ap);
990 	}
991 }
992 
993 /* Checksum and transmit a message to the Jupiter */
994 static char *
995 jupiter_send(register struct peer *peer, register struct jheader *hp)
996 {
997 	register u_int len, size;
998 	register int cc;
999 	register u_short *sp;
1000 	static char errstr[132];
1001 
1002 	size = sizeof(*hp);
1003 	hp->hsum = putshort(jupiter_cksum((u_short *)hp,
1004 	    (size / sizeof(u_short)) - 1));
1005 	len = getshort(hp->len);
1006 	if (len > 0) {
1007 		sp = (u_short *)(hp + 1);
1008 		sp[len] = putshort(jupiter_cksum(sp, len));
1009 		size += (len + 1) * sizeof(u_short);
1010 	}
1011 
1012 	if ((cc = write(peer->procptr->io.fd, (char *)hp, size)) < 0) {
1013 		(void)sprintf(errstr, "write: %s", strerror(errno));
1014 		return (errstr);
1015 	} else if (cc != size) {
1016 		(void)sprintf(errstr, "short write (%d != %d)", cc, size);
1017 		return (errstr);
1018 	}
1019 	return (NULL);
1020 }
1021 
1022 /* Request periodic message output */
1023 static struct {
1024 	struct jheader jheader;
1025 	struct jrequest jrequest;
1026 } reqmsg = {
1027 	{ putshort(JUPITER_SYNC), 0,
1028 	    putshort((sizeof(struct jrequest) / sizeof(u_short)) - 1),
1029 	    0, putshort(JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK |
1030 	    JUPITER_FLAG_CONN | JUPITER_FLAG_LOG), 0 },
1031 	{ 0, 0, 0, 0 }
1032 };
1033 
1034 /* An interval of zero means to output on trigger */
1035 static void
1036 jupiter_reqmsg(register struct peer *peer, register u_int id,
1037     register u_int interval)
1038 {
1039 	register struct jheader *hp;
1040 	register struct jrequest *rp;
1041 	register char *cp;
1042 
1043 	hp = &reqmsg.jheader;
1044 	hp->id = putshort(id);
1045 	rp = &reqmsg.jrequest;
1046 	rp->trigger = putshort(interval == 0);
1047 	rp->interval = putshort(interval);
1048 	if ((cp = jupiter_send(peer, hp)) != NULL)
1049 		jupiter_debug(peer, "jupiter_reqmsg: %u: %s\n", id, cp);
1050 }
1051 
1052 /* Cancel periodic message output */
1053 static struct jheader canmsg = {
1054 	putshort(JUPITER_SYNC), 0, 0, 0,
1055 	putshort(JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK | JUPITER_FLAG_DISC),
1056 	0
1057 };
1058 
1059 static void
1060 jupiter_canmsg(register struct peer *peer, register u_int id)
1061 {
1062 	register struct jheader *hp;
1063 	register char *cp;
1064 
1065 	hp = &canmsg;
1066 	hp->id = putshort(id);
1067 	if ((cp = jupiter_send(peer, hp)) != NULL)
1068 		jupiter_debug(peer, "jupiter_canmsg: %u: %s\n", id, cp);
1069 }
1070 
1071 /* Request a single message output */
1072 static struct jheader reqonemsg = {
1073 	putshort(JUPITER_SYNC), 0, 0, 0,
1074 	putshort(JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK | JUPITER_FLAG_QUERY),
1075 	0
1076 };
1077 
1078 static void
1079 jupiter_reqonemsg(register struct peer *peer, register u_int id)
1080 {
1081 	register struct jheader *hp;
1082 	register char *cp;
1083 
1084 	hp = &reqonemsg;
1085 	hp->id = putshort(id);
1086 	if ((cp = jupiter_send(peer, hp)) != NULL)
1087 		jupiter_debug(peer, "jupiter_reqonemsg: %u: %s\n", id, cp);
1088 }
1089 
1090 /* Set the platform dynamics */
1091 static struct {
1092 	struct jheader jheader;
1093 	struct jplat jplat;
1094 } platmsg = {
1095 	{ putshort(JUPITER_SYNC), putshort(JUPITER_I_PLAT),
1096 	    putshort((sizeof(struct jplat) / sizeof(u_short)) - 1), 0,
1097 	    putshort(JUPITER_FLAG_REQUEST | JUPITER_FLAG_NAK), 0 },
1098 	{ 0, 0, 0 }
1099 };
1100 
1101 static void
1102 jupiter_platform(register struct peer *peer, register u_int platform)
1103 {
1104 	register struct jheader *hp;
1105 	register struct jplat *pp;
1106 	register char *cp;
1107 
1108 	hp = &platmsg.jheader;
1109 	pp = &platmsg.jplat;
1110 	pp->platform = putshort(platform);
1111 	if ((cp = jupiter_send(peer, hp)) != NULL)
1112 		jupiter_debug(peer, "jupiter_platform: %u: %s\n", platform, cp);
1113 }
1114 
1115 /* Checksum "len" shorts */
1116 static u_short
1117 jupiter_cksum(register u_short *sp, register u_int len)
1118 {
1119 	register u_short sum, x;
1120 
1121 	sum = 0;
1122 	while (len-- > 0) {
1123 		x = *sp++;
1124 		sum += getshort(x);
1125 	}
1126 	return (~sum + 1);
1127 }
1128 
1129 /* Return the size of the next message (or zero if we don't have it all yet) */
1130 static int
1131 jupiter_recv(register struct peer *peer)
1132 {
1133 	register int n, len, size, cc;
1134 	register struct refclockproc *pp;
1135 	register struct jupiterunit *up;
1136 	register struct jheader *hp;
1137 	register u_char *bp;
1138 	register u_short *sp;
1139 
1140 	pp = peer->procptr;
1141 	up = (struct jupiterunit *)pp->unitptr;
1142 
1143 	/* Must have at least a header's worth */
1144 	cc = sizeof(*hp);
1145 	size = up->ssize;
1146 	if (size < cc)
1147 		return (0);
1148 
1149 	/* Search for the sync short if missing */
1150 	sp = up->sbuf;
1151 	hp = (struct jheader *)sp;
1152 	if (getshort(hp->sync) != JUPITER_SYNC) {
1153 		/* Wasn't at the front, sync up */
1154 		jupiter_debug(peer, "syncing");
1155 		bp = (u_char *)sp;
1156 		n = size;
1157 		while (n >= 2) {
1158 			if (bp[0] != (JUPITER_SYNC & 0xff)) {
1159 				jupiter_debug(peer, "{0x%x}", bp[0]);
1160 				++bp;
1161 				--n;
1162 				continue;
1163 			}
1164 			if (bp[1] == ((JUPITER_SYNC >> 8) & 0xff))
1165 				break;
1166 			jupiter_debug(peer, "{0x%x 0x%x}", bp[0], bp[1]);
1167 			bp += 2;
1168 			n -= 2;
1169 		}
1170 		jupiter_debug(peer, "\n");
1171 		/* Shuffle data to front of input buffer */
1172 		if (n > 0)
1173 			memcpy(sp, bp, n);
1174 		size = n;
1175 		up->ssize = size;
1176 		if (size < cc || hp->sync != JUPITER_SYNC)
1177 			return (0);
1178 	}
1179 
1180 	if (jupiter_cksum(sp, (cc / sizeof(u_short) - 1)) !=
1181 	    getshort(hp->hsum)) {
1182 	    jupiter_debug(peer, "jupiter_recv: bad header checksum!\n");
1183 		/* This is drastic but checksum errors should be rare */
1184 		up->ssize = 0;
1185 		return (0);
1186 	}
1187 
1188 	/* Check for a payload */
1189 	len = getshort(hp->len);
1190 	if (len > 0) {
1191 		n = (len + 1) * sizeof(u_short);
1192 		/* Not enough data yet */
1193 		if (size < cc + n)
1194 			return (0);
1195 
1196 		/* Check payload checksum */
1197 		sp = (u_short *)(hp + 1);
1198 		if (jupiter_cksum(sp, len) != getshort(sp[len])) {
1199 			jupiter_debug(peer,
1200 			    "jupiter_recv: bad payload checksum!\n");
1201 			/* This is drastic but checksum errors should be rare */
1202 			up->ssize = 0;
1203 			return (0);
1204 		}
1205 		cc += n;
1206 	}
1207 	return (cc);
1208 }
1209 
1210 static int
1211 jupiter_ttyinit(register struct peer *peer, register int fd)
1212 {
1213 	struct termios termios;
1214 
1215 	memset((char *)&termios, 0, sizeof(termios));
1216 	if (cfsetispeed(&termios, B9600) < 0 ||
1217 	    cfsetospeed(&termios, B9600) < 0) {
1218 		jupiter_debug(peer,
1219 		    "jupiter_ttyinit: cfsetispeed/cfgetospeed: %s\n",
1220 		    strerror(errno));
1221 		return (0);
1222 	}
1223 #ifdef HAVE_CFMAKERAW
1224 	cfmakeraw(&termios);
1225 #else
1226 	termios.c_iflag &= ~(IMAXBEL | IXOFF | INPCK | BRKINT | PARMRK |
1227 	    ISTRIP | INLCR | IGNCR | ICRNL | IXON | IGNPAR);
1228 	termios.c_iflag |= IGNBRK;
1229 	termios.c_oflag &= ~OPOST;
1230 	termios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL | ICANON | ISIG |
1231 	    IEXTEN | NOFLSH | TOSTOP | PENDIN);
1232 	termios.c_cflag &= ~(CSIZE | PARENB);
1233 	termios.c_cflag |= CS8 | CREAD;
1234 	termios.c_cc[VMIN] = 1;
1235 #endif
1236 	termios.c_cflag |= CLOCAL;
1237 	if (tcsetattr(fd, TCSANOW, &termios) < 0) {
1238 		jupiter_debug(peer, "jupiter_ttyinit: tcsetattr: %s\n",
1239 		    strerror(errno));
1240 		return (0);
1241 	}
1242 
1243 #ifdef TIOCSPPS
1244 	if (ioctl(fd, TIOCSPPS, (char *)&fdpps) < 0) {
1245 		jupiter_debug(peer, "jupiter_ttyinit: TIOCSPPS: %s\n",
1246 		    strerror(errno));
1247 		return (0);
1248 	}
1249 #endif
1250 #ifdef I_PUSH
1251 	if (ioctl(fd, I_PUSH, "ppsclock") < 0) {
1252 		jupiter_debug(peer, "jupiter_ttyinit: push ppsclock: %s\n",
1253 		    strerror(errno));
1254 		return (0);
1255 	}
1256 #endif
1257 
1258 	return (1);
1259 }
1260 
1261 #else /* not (REFCLOCK && CLOCK_JUPITER && PPS) */
1262 int refclock_jupiter_bs;
1263 #endif /* not (REFCLOCK && CLOCK_JUPITER && PPS) */
1264