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