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