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