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 */
149enum 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};
151const 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
155enum 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};
157const 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
161enum true_type	{t_unknown, t_goes, t_tm, t_tcu, t_omega, t_tl3, t_Max};
162const 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 */
168struct 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 */
184static	int	true_start	(int, struct peer *);
185static	void	true_shutdown	(int, struct peer *);
186static	void	true_receive	(struct recvbuf *);
187static	void	true_poll	(int, struct peer *);
188static	void	true_send	(struct peer *, const char *);
189static	void	true_doevent	(struct peer *, enum true_event);
190
191#ifdef CLOCK_PPS720
192static	u_long	true_sample720	(void);
193#endif
194
195/*
196 * Transfer vector
197 */
198struct	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
212NTP_PRINTF(2, 3)
213static void
214true_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 */
263static int
264true_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 */
325static void
326true_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 */
346static void
347true_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 */
624static void
625true_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 */
648static void
649true_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 */
921static void
922true_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 */
956static u_long
957true_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
980NONEMPTY_TRANSLATION_UNIT
981#endif /* REFCLOCK */
982