xref: /freebsd/contrib/ntp/ntpd/refclock_true.c (revision e0c4386e)
1 /*
2  * refclock_true - clock driver for the Kinemetrics/TrueTime receivers
3  *	Receiver Version 3.0C - tested plain, with CLKLDISC
4  *	Development work being done:
5  *      - Support TL-3 WWV TOD receiver
6  */
7 
8 #ifdef HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11 
12 #if defined(REFCLOCK) && defined(CLOCK_TRUETIME)
13 
14 #include <stdio.h>
15 #include <ctype.h>
16 
17 #include "ntpd.h"
18 #include "ntp_io.h"
19 #include "ntp_refclock.h"
20 #include "ntp_unixtime.h"
21 #include "ntp_stdlib.h"
22 
23 /* This should be an atom clock but those are very hard to build.
24  *
25  * The PCL720 from P C Labs has an Intel 8253 lookalike, as well as a bunch
26  * of TTL input and output pins, all brought out to the back panel.  If you
27  * wire a PPS signal (such as the TTL PPS coming out of a GOES or other
28  * Kinemetrics/Truetime clock) to the 8253's GATE0, and then also wire the
29  * 8253's OUT0 to the PCL720's INPUT3.BIT0, then we can read CTR0 to get the
30  * number of uSecs since the last PPS upward swing, mediated by reading OUT0
31  * to find out if the counter has wrapped around (this happens if more than
32  * 65535us (65ms) elapses between the PPS event and our being called.)
33  */
34 #ifdef CLOCK_PPS720
35 # undef min	/* XXX */
36 # undef max	/* XXX */
37 # include <machine/inline.h>
38 # include <sys/pcl720.h>
39 # include <sys/i8253.h>
40 # define PCL720_IOB 0x2a0	/* XXX */
41 # define PCL720_CTR 0		/* XXX */
42 #endif
43 
44 /*
45  * Support for Kinemetrics Truetime Receivers
46  *	GOES:           (468-DC, usable with GPS->GOES converting antenna)
47  *	GPS/TM-TMD:
48  *	XL-DC:		(a 151-602-210, reported by the driver as a GPS/TM-TMD)
49  *	GPS-800 TCU:	(an 805-957 with the RS232 Talker/Listener module)
50  *      TL-3:           3 channel WWV/H receiver w/ IRIG and RS-232 outputs
51  *	OM-DC:		getting stale ("OMEGA")
52  *
53  * Most of this code is originally from refclock_wwvb.c with thanks.
54  * It has been so mangled that wwvb is not a recognizable ancestor.
55  *
56  * Timcode format: ADDD:HH:MM:SSQCL
57  *	A - control A		(this is stripped before we see it)
58  *	Q - Quality indication	(see below)
59  *	C - Carriage return
60  *	L - Line feed
61  *
62  * Quality codes indicate possible error of
63  *   468-DC GOES Receiver:
64  *   GPS-TM/TMD Receiver: (default quality codes for XL-DC)
65  *       ?     +/- 1  milliseconds	#     +/- 100 microseconds
66  *       *     +/- 10 microseconds	.     +/- 1   microsecond
67  *     space   less than 1 microsecond
68  *   TL-3 Receiver: (default quality codes for TL-3)
69  *       ?     unknown quality (receiver is unlocked)
70  *     space   +/- 5 milliseconds
71  *   OM-DC OMEGA Receiver: (default quality codes for OMEGA)
72  *   WARNING OMEGA navigation system is no longer existent
73  *       >     >+- 5 seconds
74  *       ?     >+/- 500 milliseconds    #     >+/- 50 milliseconds
75  *       *     >+/- 5 milliseconds      .     >+/- 1 millisecond
76  *      A-H    less than 1 millisecond.  Character indicates which station
77  *	       is being received as follows:
78  *	       A = Norway, B = Liberia, C = Hawaii, D = North Dakota,
79  *	       E = La Reunion, F = Argentina, G = Australia, H = Japan.
80  *
81  * The carriage return start bit begins on 0 seconds and extends to 1 bit time.
82  *
83  * Notes on 468-DC and OMEGA receiver:
84  *
85  * Send the clock a 'R' or 'C' and once per second a timestamp will
86  * appear.  Send a 'P' to get the satellite position once (GOES only.)
87  *
88  * Notes on the 468-DC receiver:
89  *
90  * Since the old east/west satellite locations are only historical, you can't
91  * set your clock propagation delay settings correctly and still use
92  * automatic mode. The manual says to use a compromise when setting the
93  * switches. This results in significant errors. The solution; use fudge
94  * time1 and time2 to incorporate corrections. If your clock is set for
95  * 50 and it should be 58 for using the west and 46 for using the east,
96  * use the line
97  *
98  * fudge 127.127.5.0 time1 +0.008 time2 -0.004
99  *
100  * This corrects the 4 milliseconds advance and 8 milliseconds retard
101  * needed. The software will ask the clock which satellite it sees.
102  *
103  * Notes on the TrueTime TimeLink TL-3 WWV TOD receiver:
104  *
105  * This clock may be polled, or send one timecode per second.
106  * That mode may be toggled via the front panel ("C" mode), or controlled
107  * from the RS-232 port.  Send the receiver "ST1" to turn it on, and
108  * "ST0" to turn it off.  Send "QV" to get the firmware revision (useful
109  * for identifying this model.)
110  *
111  * Note that it can take several polling cycles, especially if the receiver
112  * was in the continuous timecode mode.  (It can be slow to leave that mode.)
113  *
114  * ntp.conf parameters:
115  * time1   - offset applied to samples when reading WEST satellite (default = 0)
116  * time2   - offset applied to samples when reading EAST satellite (default = 0)
117  * stratum - stratum to assign to this clock (default = 0)
118  * refid   - refid assigned to this clock (default = "TRUE", see below)
119  * flag1   - will silence the clock side of ntpd, just reading the clock
120  *	     without trying to write to it.  (default = 0)
121  * flag2   - generate a debug file /tmp/true%d.
122  * flag3   - enable ppsclock streams module
123  * flag4   - use the PCL-720 (BSD/OS only)
124  */
125 
126 
127 /*
128  * Definitions
129  */
130 #define	DEVICE		"/dev/true%d"
131 #define	SPEED232	B9600	/* 9600 baud */
132 
133 /*
134  * Radio interface parameters
135  */
136 #define	PRECISION	(-10)	/* precision assumed (about 1 ms) */
137 #define	REFID		"TRUE"	/* reference id */
138 #define	DESCRIPTION	"Kinemetrics/TrueTime Receiver"
139 
140 /*
141  * Tags which station (satellite) we see
142  */
143 #define GOES_WEST	0	/* Default to WEST satellite and apply time1 */
144 #define GOES_EAST	1	/* until you discover otherwise */
145 
146 /*
147  * used by the state machine
148  */
149 enum true_event	{e_Init, e_Huh, e_F18, e_F50, e_F51, e_Satellite,
150 		 e_TL3, e_Poll, e_Location, e_TS, e_Max};
151 const char *events[] = {"Init", "Huh", "F18", "F50", "F51", "Satellite",
152 			"TL3", "Poll", "Location", "TS"};
153 #define eventStr(x) (((int)x<(int)e_Max) ? events[(int)x] : "?")
154 
155 enum true_state	{s_Base, s_InqTM, s_InqTCU, s_InqOmega, s_InqGOES,
156 		 s_InqTL3, s_Init, s_F18, s_F50, s_Start, s_Auto, s_Max};
157 const char *states[] = {"Base", "InqTM", "InqTCU", "InqOmega", "InqGOES",
158 			"InqTL3", "Init", "F18", "F50", "Start", "Auto"};
159 #define stateStr(x) (((int)x<(int)s_Max) ? states[(int)x] : "?")
160 
161 enum true_type	{t_unknown, t_goes, t_tm, t_tcu, t_omega, t_tl3, t_Max};
162 const char *types[] = {"unknown", "goes", "tm", "tcu", "omega", "tl3"};
163 #define typeStr(x) (((int)x<(int)t_Max) ? types[(int)x] : "?")
164 
165 /*
166  * unit control structure
167  */
168 struct true_unit {
169 	unsigned int	pollcnt;	/* poll message counter */
170 	unsigned int	station;	/* which station we are on */
171 	unsigned int	polled;		/* Hand in a time sample? */
172 	enum true_state	state;		/* state machine */
173 	enum true_type	type;		/* what kind of clock is it? */
174 	int		unit;		/* save an extra copy of this */
175 	FILE		*debug;		/* debug logging file */
176 #ifdef CLOCK_PPS720
177 	int		pcl720init;	/* init flag for PCL 720 */
178 #endif
179 };
180 
181 /*
182  * Function prototypes
183  */
184 static	int	true_start	(int, struct peer *);
185 static	void	true_shutdown	(int, struct peer *);
186 static	void	true_receive	(struct recvbuf *);
187 static	void	true_poll	(int, struct peer *);
188 static	void	true_send	(struct peer *, const char *);
189 static	void	true_doevent	(struct peer *, enum true_event);
190 
191 #ifdef CLOCK_PPS720
192 static	u_long	true_sample720	(void);
193 #endif
194 
195 /*
196  * Transfer vector
197  */
198 struct	refclock refclock_true = {
199 	true_start,		/* start up driver */
200 	true_shutdown,		/* shut down driver */
201 	true_poll,		/* transmit poll message */
202 	noentry,		/* not used (old true_control) */
203 	noentry,		/* initialize driver (not used) */
204 	noentry,		/* not used (old true_buginfo) */
205 	NOFLAGS			/* not used */
206 };
207 
208 
209 #if !defined(__STDC__)
210 # define true_debug (void)
211 #else
212 NTP_PRINTF(2, 3)
213 static void
214 true_debug(struct peer *peer, const char *fmt, ...)
215 {
216 	va_list ap;
217 	int want_debugging, now_debugging;
218 	struct refclockproc *pp;
219 	struct true_unit *up;
220 
221 	va_start(ap, fmt);
222 	pp = peer->procptr;
223 	up = pp->unitptr;
224 
225 	want_debugging = (pp->sloppyclockflag & CLK_FLAG2) != 0;
226 	now_debugging = (up->debug != NULL);
227 	if (want_debugging != now_debugging)
228 	{
229 		if (want_debugging) {
230 			char filename[40];
231 			int fd;
232 
233 			snprintf(filename, sizeof(filename),
234 				 "/tmp/true%d.debug", up->unit);
235 			fd = open(filename, O_CREAT | O_WRONLY | O_EXCL,
236 				  0600);
237 			if (fd >= 0 && (up->debug = fdopen(fd, "w"))) {
238 #ifdef HAVE_SETVBUF
239 				static char buf[BUFSIZ];
240 
241 				setvbuf(up->debug, buf, _IOLBF, BUFSIZ);
242 #else
243 				setlinebuf(up->debug);
244 #endif
245 			}
246 		} else {
247 			fclose(up->debug);
248 			up->debug = NULL;
249 		}
250 	}
251 
252 	if (up->debug) {
253 		fprintf(up->debug, "true%d: ", up->unit);
254 		vfprintf(up->debug, fmt, ap);
255 	}
256 	va_end(ap);
257 }
258 #endif /*STDC*/
259 
260 /*
261  * true_start - open the devices and initialize data for processing
262  */
263 static int
264 true_start(
265 	int unit,
266 	struct peer *peer
267 	)
268 {
269 	register struct true_unit *up;
270 	struct refclockproc *pp;
271 	char device[40];
272 	int fd;
273 
274 	/*
275 	 * Open serial port
276 	 */
277 	snprintf(device, sizeof(device), DEVICE, unit);
278 	fd = refclock_open(&peer->srcadr, device, SPEED232, LDISC_CLK);
279 	if (fd <= 0)
280 		return 0;
281 
282 	/*
283 	 * Allocate and initialize unit structure
284 	 */
285 	up = emalloc_zero(sizeof(*up));
286 	pp = peer->procptr;
287 	pp->io.clock_recv = true_receive;
288 	pp->io.srcclock = peer;
289 	pp->io.datalen = 0;
290 	pp->io.fd = fd;
291 	if (!io_addclock(&pp->io)) {
292 		close(fd);
293 		pp->io.fd = -1;
294 		free(up);
295 		return (0);
296 	}
297 	pp->unitptr = up;
298 
299 	/*
300 	 * Initialize miscellaneous variables
301 	 */
302 	peer->precision = PRECISION;
303 	pp->clockdesc = DESCRIPTION;
304 	memcpy(&pp->refid, REFID, 4);
305 	up->pollcnt = 2;
306 	up->type = t_unknown;
307 	up->state = s_Base;
308 
309 	/*
310 	 * Send a CTRL-C character at the start,
311 	 * just in case the clock is already
312 	 * sending timecodes
313 	 */
314 	true_send(peer, "\03\r");
315 
316 	true_doevent(peer, e_Init);
317 
318 	return (1);
319 }
320 
321 
322 /*
323  * true_shutdown - shut down the clock
324  */
325 static void
326 true_shutdown(
327 	int unit,
328 	struct peer *peer
329 	)
330 {
331 	register struct true_unit *up;
332 	struct refclockproc *pp;
333 
334 	pp = peer->procptr;
335 	up = pp->unitptr;
336 	if (pp->io.fd != -1)
337 		io_closeclock(&pp->io);
338 	if (up != NULL)
339 		free(up);
340 }
341 
342 
343 /*
344  * true_receive - receive data from the serial interface on a clock
345  */
346 static void
347 true_receive(
348 	struct recvbuf *rbufp
349 	)
350 {
351 	register struct true_unit *up;
352 	struct refclockproc *pp;
353 	struct peer *peer;
354 	u_short new_station;
355 	char synced;
356 	int i;
357 	int lat, lon, off;	/* GOES Satellite position */
358 	/* These variables hold data until we decide to keep it */
359 	char	rd_lastcode[BMAX];
360 	l_fp	rd_tmp;
361 	u_short	rd_lencode;
362 
363 	/*
364 	 * Get the clock this applies to and pointers to the data.
365 	 */
366 	peer = rbufp->recv_peer;
367 	pp = peer->procptr;
368 	up = pp->unitptr;
369 
370 	/*
371 	 * Read clock output.  Automatically handles STREAMS, CLKLDISC.
372 	 */
373 	rd_lencode = refclock_gtlin(rbufp, rd_lastcode, BMAX, &rd_tmp);
374 	rd_lastcode[rd_lencode] = '\0';
375 
376 	/*
377 	 * There is a case where <cr><lf> generates 2 timestamps.
378 	 */
379 	if (rd_lencode == 0)
380 		return;
381 	pp->lencode = rd_lencode;
382 	strlcpy(pp->a_lastcode, rd_lastcode, sizeof(pp->a_lastcode));
383 	pp->lastrec = rd_tmp;
384 	true_debug(peer, "receive(%s) [%d]\n", pp->a_lastcode,
385 		   pp->lencode);
386 
387 	up->pollcnt = 2;
388 	record_clock_stats(&peer->srcadr, pp->a_lastcode);
389 
390 	/*
391 	 * We get down to business, check the timecode format and decode
392 	 * its contents. This code decodes a multitude of different
393 	 * clock messages. Timecodes are processed if needed. All replies
394 	 * will be run through the state machine to tweak driver options
395 	 * and program the clock.
396 	 */
397 
398 	/*
399 	 * Clock misunderstood our last command?
400 	 */
401 	if (pp->a_lastcode[0] == '?' ||
402 	    strcmp(pp->a_lastcode, "ERROR 05 NO SUCH FUNCTION") == 0) {
403 		true_doevent(peer, e_Huh);
404 		return;
405 	}
406 
407 	/*
408 	 * Timecode: "nnnnn+nnn-nnn"
409 	 * (from GOES clock when asked about satellite position)
410 	 */
411 	if ((pp->a_lastcode[5] == '+' || pp->a_lastcode[5] == '-') &&
412 	    (pp->a_lastcode[9] == '+' || pp->a_lastcode[9] == '-') &&
413 	    sscanf(pp->a_lastcode, "%5d%*c%3d%*c%3d", &lon, &lat, &off) == 3
414 	    ) {
415 		const char *label = "Botch!";
416 
417 		/*
418 		 * This is less than perfect.  Call the (satellite)
419 		 * either EAST or WEST and adjust slop accodingly
420 		 * Perfectionists would recalculate the exact delay
421 		 * and adjust accordingly...
422 		 */
423 		if (lon > 7000 && lon < 14000) {
424 			if (lon < 10000) {
425 				new_station = GOES_EAST;
426 				label = "EAST";
427 			} else {
428 				new_station = GOES_WEST;
429 				label = "WEST";
430 			}
431 
432 			if (new_station != up->station) {
433 				double dtemp;
434 
435 				dtemp = pp->fudgetime1;
436 				pp->fudgetime1 = pp->fudgetime2;
437 				pp->fudgetime2 = dtemp;
438 				up->station = new_station;
439 			}
440 		}
441 		else {
442 			/*refclock_report(peer, CEVNT_BADREPLY);*/
443 			label = "UNKNOWN";
444 		}
445 		true_debug(peer, "GOES: station %s\n", label);
446 		true_doevent(peer, e_Satellite);
447 		return;
448 	}
449 
450 	/*
451 	 * Timecode: "Fnn"
452 	 * (from TM/TMD clock when it wants to tell us what it's up to.)
453 	 */
454 	if (sscanf(pp->a_lastcode, "F%2d", &i) == 1 && i > 0 && i < 80) {
455 		switch (i) {
456 		case 50:
457 			true_doevent(peer, e_F50);
458 			break;
459 		case 51:
460 			true_doevent(peer, e_F51);
461 			break;
462 		default:
463 			true_debug(peer, "got F%02d - ignoring\n", i);
464 			break;
465 		}
466 		return;
467 	}
468 
469         /*
470          * Timecode: "VER xx.xx"
471          * (from a TL3 when sent "QV", so id's it during initialization.)
472          */
473         if (pp->a_lastcode[0] == 'V' && pp->a_lastcode[1] == 'E' &&
474             pp->a_lastcode[2] == 'R' && pp->a_lastcode[6] == '.') {
475                 true_doevent(peer, e_TL3);
476                 NLOG(NLOG_CLOCKSTATUS) {
477                         msyslog(LOG_INFO, "TL3: %s", pp->a_lastcode);
478                 }
479                 return;
480         }
481 
482 	/*
483 	 * Timecode: " TRUETIME Mk III" or " TRUETIME XL"
484 	 * (from a TM/TMD/XL clock during initialization.)
485 	 */
486 	if (strncmp(pp->a_lastcode, " TRUETIME Mk III ", 17) == 0 ||
487 	    strncmp(pp->a_lastcode, " TRUETIME XL", 12) == 0) {
488 		true_doevent(peer, e_F18);
489 		NLOG(NLOG_CLOCKSTATUS) {
490 			msyslog(LOG_INFO, "TM/TMD/XL: %s", pp->a_lastcode);
491 		}
492 		return;
493 	}
494 
495 	/*
496 	 * Timecode: "N03726428W12209421+000033"
497 	 *			1	   2
498 	 * index      0123456789012345678901234
499 	 * (from a TCU during initialization)
500 	 */
501 	if ((pp->a_lastcode[0] == 'N' || pp->a_lastcode[0] == 'S') &&
502 	    (pp->a_lastcode[9] == 'W' || pp->a_lastcode[9] == 'E') &&
503 	    pp->a_lastcode[18] == '+') {
504 		true_doevent(peer, e_Location);
505 		NLOG(NLOG_CLOCKSTATUS) {
506 			msyslog(LOG_INFO, "TCU-800: %s", pp->a_lastcode);
507 		}
508 		return;
509 	}
510 	/*
511 	 * Timecode: "ddd:hh:mm:ssQ"
512 	 *			1	   2
513 	 * index      0123456789012345678901234
514 	 * (from all clocks supported by this driver.)
515 	 */
516 	if (pp->a_lastcode[3] == ':' &&
517 	    pp->a_lastcode[6] == ':' &&
518 	    pp->a_lastcode[9] == ':' &&
519 	    sscanf(pp->a_lastcode, "%3d:%2d:%2d:%2d%c",
520 		   &pp->day, &pp->hour, &pp->minute,
521 		   &pp->second, &synced) == 5) {
522 
523 		/*
524 		 * Adjust the synchronize indicator according to timecode
525 		 * say were OK, and then say not if we really are not OK
526 		 */
527 		if (synced == '>' || synced == '#' || synced == '?'
528 		    || synced == 'X')
529 			pp->leap = LEAP_NOTINSYNC;
530 		else
531 			pp->leap = LEAP_NOWARNING;
532 
533 		true_doevent(peer, e_TS);
534 
535 #ifdef CLOCK_PPS720
536 		/* If it's taken more than 65ms to get here, we'll lose. */
537 		if ((pp->sloppyclockflag & CLK_FLAG4) && up->pcl720init) {
538 			l_fp   off;
539 
540 #ifdef CLOCK_ATOM
541 			/*
542 			 * find out what time it really is. Include
543 			 * the count from the PCL720
544 			 */
545 			if (!clocktime(pp->day, pp->hour, pp->minute,
546 				       pp->second, GMT, pp->lastrec.l_ui,
547 				       &pp->yearstart, &off.l_ui)) {
548 				refclock_report(peer, CEVNT_BADTIME);
549 				return;
550 			}
551 			off.l_uf = 0;
552 #endif
553 
554 			pp->usec = true_sample720();
555 #ifdef CLOCK_ATOM
556 			TVUTOTSF(pp->usec, off.l_uf);
557 #endif
558 
559 			/*
560 			 * Stomp all over the timestamp that was pulled out
561 			 * of the input stream. It's irrelevant since we've
562 			 * adjusted the input time to reflect now (via pp->usec)
563 			 * rather than when the data was collected.
564 			 */
565 			get_systime(&pp->lastrec);
566 #ifdef CLOCK_ATOM
567 			/*
568 			 * Create a true offset for feeding to pps_sample()
569 			 */
570 			L_SUB(&off, &pp->lastrec);
571 
572 			pps_sample(peer, &off);
573 #endif
574 			true_debug(peer, "true_sample720: %luus\n", pp->usec);
575 		}
576 #endif
577 
578 		/*
579 		 * The clock will blurt a timecode every second but we only
580 		 * want one when polled.  If we havn't been polled, bail out.
581 		 */
582 		if (!up->polled)
583 			return;
584 
585                 /* We only call doevent if additional things need be done
586                  * at poll interval.  Currently, its only for GOES.  We also
587                  * call it for clock unknown so that it gets logged.
588                  */
589                 if (up->type == t_goes || up->type == t_unknown)
590                     true_doevent(peer, e_Poll);
591 
592 		if (!refclock_process(pp)) {
593 			refclock_report(peer, CEVNT_BADTIME);
594 			return;
595 		}
596 		/*
597 		 * If clock is good we send a NOMINAL message so that
598 		 * any previous BAD messages are nullified
599 		 */
600 		pp->lastref = pp->lastrec;
601 		refclock_receive(peer);
602 		refclock_report(peer, CEVNT_NOMINAL);
603 
604 		/*
605 		 * We have succedded in answering the poll.
606 		 * Turn off the flag and return
607 		 */
608 		up->polled = 0;
609 
610 		return;
611 	}
612 
613 	/*
614 	 * No match to known timecodes, report failure and return
615 	 */
616 	refclock_report(peer, CEVNT_BADREPLY);
617 	return;
618 }
619 
620 
621 /*
622  * true_send - time to send the clock a signal to cough up a time sample
623  */
624 static void
625 true_send(
626 	struct peer *peer,
627 	const char *cmd
628 	)
629 {
630 	struct refclockproc *pp;
631 
632 	pp = peer->procptr;
633 	if (!(pp->sloppyclockflag & CLK_FLAG1)) {
634 		size_t len = strlen(cmd);
635 
636 		true_debug(peer, "Send '%s'\n", cmd);
637 		if (refclock_write(peer, cmd, len, NULL) != (ssize_t)len)
638 			refclock_report(peer, CEVNT_FAULT);
639 		else
640 			pp->polls++;
641 	}
642 }
643 
644 
645 /*
646  * state machine for initializing and controlling a clock
647  */
648 static void
649 true_doevent(
650 	struct peer *peer,
651 	enum true_event event
652 	)
653 {
654 	struct true_unit *up;
655 	struct refclockproc *pp;
656 
657 	pp = peer->procptr;
658 	up = pp->unitptr;
659 	if (event != e_TS) {
660 		NLOG(NLOG_CLOCKSTATUS) {
661 			msyslog(LOG_INFO, "TRUE: clock %s, state %s, event %s",
662 				typeStr(up->type),
663 				stateStr(up->state),
664 				eventStr(event));
665 		}
666 	}
667 	true_debug(peer, "clock %s, state %s, event %s\n",
668 		   typeStr(up->type), stateStr(up->state), eventStr(event));
669 	switch (up->type) {
670 	case t_goes:
671 		switch (event) {
672 		case e_Init:	/* FALLTHROUGH */
673 		case e_Satellite:
674 			/*
675 			 * Switch back to on-second time codes and return.
676 			 */
677 			true_send(peer, "C");
678 			up->state = s_Start;
679 			break;
680 		case e_Poll:
681 			/*
682 			 * After each poll, check the station (satellite).
683 			 */
684 			true_send(peer, "P");
685 			/* No state change needed. */
686 			break;
687 		default:
688 			break;
689 		}
690 		/* FALLTHROUGH */
691 	case t_omega:
692 		switch (event) {
693 		case e_Init:
694 			true_send(peer, "C");
695 			up->state = s_Start;
696 			break;
697 		case e_TS:
698 			if (up->state != s_Start && up->state != s_Auto) {
699 				true_send(peer, "\03\r");
700 				break;
701 			}
702 			up->state = s_Auto;
703 			break;
704 		default:
705 			break;
706 		}
707 		break;
708 	case t_tm:
709 		switch (event) {
710 		case e_Init:
711 			true_send(peer, "F18\r");
712 			up->state = s_Init;
713 			break;
714 		case e_F18:
715 			true_send(peer, "F50\r");
716                         /*
717                          * Timecode: " TRUETIME Mk III" or " TRUETIME XL"
718                          * (from a TM/TMD/XL clock during initialization.)
719                          */
720                         if ( strcmp(pp->a_lastcode, " TRUETIME Mk III") == 0 ||
721                             strncmp(pp->a_lastcode, " TRUETIME XL", 12) == 0) {
722                                 true_doevent(peer, e_F18);
723                                 NLOG(NLOG_CLOCKSTATUS) {
724                                     msyslog(LOG_INFO, "TM/TMD/XL: %s",
725                                             pp->a_lastcode);
726                                 }
727                                 return;
728                         }
729 			up->state = s_F18;
730 			break;
731 		case e_F50:
732 			true_send(peer, "F51\r");
733 			up->state = s_F50;
734 			break;
735 		case e_F51:
736 			true_send(peer, "F08\r");
737 			up->state = s_Start;
738 			break;
739 		case e_TS:
740 			if (up->state != s_Start && up->state != s_Auto) {
741 				true_send(peer, "\03\r");
742 				break;
743 			}
744 			up->state = s_Auto;
745 			break;
746 		default:
747 			break;
748 		}
749 		break;
750 	case t_tcu:
751 		switch (event) {
752 		case e_Init:
753 			true_send(peer, "MD3\r");	/* GPS Synch'd Gen. */
754 			true_send(peer, "TSU\r");	/* UTC, not GPS. */
755 			true_send(peer, "AU\r");	/* Auto Timestamps. */
756 			up->state = s_Start;
757 			break;
758 		case e_TS:
759 			if (up->state != s_Start && up->state != s_Auto) {
760 				true_send(peer, "\03\r");
761 				break;
762 			}
763 			up->state = s_Auto;
764 			break;
765 		default:
766 			break;
767 		}
768 		break;
769 	case t_tl3:
770                 switch (event) {
771                     case e_Init:
772                         true_send(peer, "ST1"); /* Turn on continuous stream */
773                         break;
774                     case e_TS:
775                         up->state = s_Auto;
776                         break;
777                     default:
778                         break;
779                 }
780                 break;
781 	case t_unknown:
782                if (event == e_Poll)
783                    break;
784 		switch (up->state) {
785 		case s_Base:
786 			if (event != e_Init)
787 			    abort();
788 			true_send(peer, "P\r");
789 			up->state = s_InqGOES;
790 			break;
791 		case s_InqGOES:
792 			switch (event) {
793 			case e_Satellite:
794 				up->type = t_goes;
795 				true_doevent(peer, e_Init);
796 				break;
797 			case e_Init:	/*FALLTHROUGH*/
798 			case e_Huh:
799 			case e_TS:
800                                 true_send(peer, "ST0"); /* turn off TL3 auto */
801                                 sleep(1);               /* wait for it */
802                                 up->state = s_InqTL3;
803                                 true_send(peer, "QV");  /* see if its a TL3 */
804                                 break;
805                             default:
806                                 abort();
807                         }
808                         break;
809                     case s_InqTL3:
810                         switch (event) {
811                             case e_TL3:
812                                 up->type = t_tl3;
813                                 up->state = s_Auto;     /* Inq side-effect. */
814                                 true_send(peer, "ST1"); /* Turn on 1/sec data */
815                                 break;
816                             case e_Init:        /*FALLTHROUGH*/
817                             case e_Huh:
818 				up->state = s_InqOmega;
819 				true_send(peer, "C\r");
820 				break;
821                             case e_TS:
822                                  up->type = t_tl3;    /* Already sending data */
823                                  up->state = s_Auto;
824                                  break;
825 			    default:
826                                 msyslog(LOG_INFO,
827                                         "TRUE: TL3 init fellthrough! (%d)", event);
828                                 break;
829 			}
830 			break;
831 		case s_InqOmega:
832 			switch (event) {
833 			case e_TS:
834 				up->type = t_omega;
835 				up->state = s_Auto;	/* Inq side-effect. */
836 				break;
837 			case e_Init:	/*FALLTHROUGH*/
838 			case e_Huh:
839 				up->state = s_InqTM;
840 				true_send(peer, "F18\r");
841 				break;
842 			default:
843 				abort();
844 			}
845 			break;
846 		case s_InqTM:
847 			switch (event) {
848 			case e_F18:
849 				up->type = t_tm;
850 				true_doevent(peer, e_Init);
851 				break;
852 			case e_Init:	/*FALLTHROUGH*/
853 			case e_Huh:
854 				true_send(peer, "PO\r");
855 				up->state = s_InqTCU;
856 				break;
857 			default:
858                                 msyslog(LOG_INFO,
859                                         "TRUE: TM/TMD init fellthrough!");
860 			        break;
861 			}
862 			break;
863 		case s_InqTCU:
864 			switch (event) {
865 			case e_Location:
866 				up->type = t_tcu;
867 				true_doevent(peer, e_Init);
868 				break;
869 			case e_Init:	/*FALLTHROUGH*/
870 			case e_Huh:
871 				up->state = s_Base;
872 				sleep(1);	/* XXX */
873 				break;
874 			default:
875                                 msyslog(LOG_INFO,
876                                         "TRUE: TCU init fellthrough!");
877                                 break;
878 			}
879 			break;
880 			/*
881 			 * An expedient hack to prevent lint complaints,
882 			 * these don't actually need to be used here...
883 			 */
884 		case s_Init:
885 		case s_F18:
886 		case s_F50:
887 		case s_Start:
888 		case s_Auto:
889 		case s_Max:
890 			msyslog(LOG_INFO, "TRUE: state %s is unexpected!",
891 				stateStr(up->state));
892 		}
893 		break;
894 	default:
895                 msyslog(LOG_INFO, "TRUE: cannot identify refclock!");
896 		abort();
897 		/* NOTREACHED */
898 	}
899 
900 #ifdef CLOCK_PPS720
901 	if ((pp->sloppyclockflag & CLK_FLAG4) && !up->pcl720init) {
902 		/* Make counter trigger on gate0, count down from 65535. */
903 		pcl720_load(PCL720_IOB, PCL720_CTR, i8253_oneshot, 65535);
904 		/*
905 		 * (These constants are OK since
906 		 * they represent hardware maximums.)
907 		 */
908 		NLOG(NLOG_CLOCKINFO) {
909 			msyslog(LOG_NOTICE, "PCL-720 initialized");
910 		}
911 		up->pcl720init++;
912 	}
913 #endif
914 
915 
916 }
917 
918 /*
919  * true_poll - called by the transmit procedure
920  */
921 static void
922 true_poll(
923 	int unit,
924 	struct peer *peer
925 	)
926 {
927 	struct true_unit *up;
928 	struct refclockproc *pp;
929 
930 	/*
931 	 * You don't need to poll this clock.  It puts out timecodes
932 	 * once per second.  If asked for a timestamp, take note.
933 	 * The next time a timecode comes in, it will be fed back.
934 	 */
935 	pp = peer->procptr;
936 	up = pp->unitptr;
937 	if (up->pollcnt > 0) {
938 		up->pollcnt--;
939 	} else {
940 		true_doevent(peer, e_Init);
941 		refclock_report(peer, CEVNT_TIMEOUT);
942 	}
943 
944 	/*
945 	 * polled every 64 seconds. Ask true_receive to hand in a
946 	 * timestamp.
947 	 */
948 	up->polled = 1;
949 	pp->polls++;
950 }
951 
952 #ifdef CLOCK_PPS720
953 /*
954  * true_sample720 - sample the PCL-720
955  */
956 static u_long
957 true_sample720(void)
958 {
959 	unsigned long f;
960 
961 	/* We wire the PCL-720's 8253.OUT0 to bit 0 of connector 3.
962 	 * If it is not being held low now, we did not get called
963 	 * within 65535us.
964 	 */
965 	if (inb(pcl720_data_16_23(PCL720_IOB)) & 0x01) {
966 		NLOG(NLOG_CLOCKINFO) {
967 			msyslog(LOG_NOTICE, "PCL-720 out of synch");
968 		}
969 		return (0);
970 	}
971 	f = (65536 - pcl720_read(PCL720_IOB, PCL720_CTR));
972 #ifdef PPS720_DEBUG
973 	msyslog(LOG_DEBUG, "PCL-720: %luus", f);
974 #endif
975 	return (f);
976 }
977 #endif
978 
979 #else
980 int refclock_true_bs;
981 #endif /* REFCLOCK */
982