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