xref: /freebsd/contrib/ntp/ntpd/refclock_oncore.c (revision 4e99f45480598189d49d45a825533a6c9e12f02c)
1 /*
2  * ----------------------------------------------------------------------------
3  * "THE BEER-WARE LICENSE" (Revision 42):
4  * <phk@FreeBSD.ORG> wrote this file.  As long as you retain this notice you
5  * can do whatever you want with this stuff. If we meet some day, and you think
6  * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
7  * ----------------------------------------------------------------------------
8  *
9  * refclock_oncore.c
10  *
11  * Driver for some of the various the Motorola Oncore GPS receivers.
12  *   should work with Basic, PVT6, VP, UT, UT+, GT, GT+, SL, M12, M12+T
13  *	The receivers with TRAIM (VP, UT, UT+, M12+T), will be more accurate
14  *	   than the others.
15  *	The receivers without position hold (GT, GT+) will be less accurate.
16  *
17  * Tested with:
18  *
19  *		(UT)				   (VP)
20  *   COPYRIGHT 1991-1997 MOTOROLA INC.	COPYRIGHT 1991-1996 MOTOROLA INC.
21  *   SFTW P/N #     98-P36848P		SFTW P/N # 98-P36830P
22  *   SOFTWARE VER # 2			SOFTWARE VER # 8
23  *   SOFTWARE REV # 2			SOFTWARE REV # 8
24  *   SOFTWARE DATE  APR 24 1998 	SOFTWARE DATE  06 Aug 1996
25  *   MODEL #	R1121N1114		MODEL #    B4121P1155
26  *   HWDR P/N # 1			HDWR P/N # _
27  *   SERIAL #	R0010A			SERIAL #   SSG0226478
28  *   MANUFACTUR DATE 6H07		MANUFACTUR DATE 7E02
29  *					OPTIONS LIST	IB
30  *
31  *	      (Basic)				   (M12)
32  *   COPYRIGHT 1991-1994 MOTOROLA INC.	COPYRIGHT 1991-2000 MOTOROLA INC.
33  *   SFTW P/N # 98-P39949M		SFTW P/N # 61-G10002A
34  *   SOFTWARE VER # 5			SOFTWARE VER # 1
35  *   SOFTWARE REV # 0			SOFTWARE REV # 3
36  *   SOFTWARE DATE  20 JAN 1994 	SOFTWARE DATE  Mar 13 2000
37  *   MODEL #	A11121P116		MODEL #    P143T12NR1
38  *   HDWR P/N # _			HWDR P/N # 1
39  *   SERIAL #	SSG0049809		SERIAL #   P003UD
40  *   MANUFACTUR DATE 417AMA199		MANUFACTUR DATE 0C27
41  *   OPTIONS LIST    AB
42  *
43  *	      (M12+T)				  (M12+T later version)
44  *   COPYRIGHT 1991-2002 MOTOROLA INC.	COPYRIGHT 1991-2003 MOTOROLA INC.
45  *   SFTW P/N #     61-G10268A		SFTW P/N #     61-G10268A
46  *   SOFTWARE VER # 2			SOFTWARE VER # 2
47  *   SOFTWARE REV # 0			SOFTWARE REV # 1
48  *   SOFTWARE DATE  AUG 14 2002 	SOFTWARE DATE  APR 16 2003
49  *   MODEL #	P283T12T11		MODEL #    P273T12T12
50  *   HWDR P/N # 2			HWDR P/N # 2
51  *   SERIAL #	P04DC2			SERIAL #   P05Z7Z
52  *   MANUFACTUR DATE 2J17		MANUFACTUR DATE 3G15
53  *
54  * --------------------------------------------------------------------------
55  * Reg Clemens (June 2009)
56  * BUG[1220] OK, big patch, but mostly done mechanically.  Change direct calls to write
57  * to clockstats to a call to oncore_log, which now calls the old routine plus msyslog.
58  * Have to set the LOG_LEVELS of the calls for msyslog, and this was done by hand. New
59  * routine oncore_log.
60  * --------------------------------------------------------------------------
61  * Reg Clemens (June 2009)
62  * BUG[1218] The comment on where the oncore driver gets its input file does not
63  * agree with the code.  Change the comment.
64  * --------------------------------------------------------------------------
65  * Reg Clemens (June 2009)
66  * change exit statements to return(0) in main program.  I had assumed that if the
67  * PPS driver did not start for some reason, we shuould stop NTPD itelf.  Others
68  * disagree.  We now give an ERR log message and stop this driver.
69  * --------------------------------------------------------------------------
70  * Reg Clemens (June 2009)
71  * A bytes available message for the input subsystem (Debug message).
72  * --------------------------------------------------------------------------
73  * Reg Clemens (Nov 2008)
74  * This code adds a message for TRAIM messages.  Users often worry about the
75  * driver not starting up, and it is often because of signal strength being low.
76  * Low signal strength will give TRAIM messages.
77  * --------------------------------------------------------------------------
78  * Reg Clemens (Nov 2008)
79  * Add waiting on Almanac Message.
80  * --------------------------------------------------------------------------
81  * Reg Clemens (Nov 2008)
82  * Add back in @@Bl code to do the @@Bj/@@Gj that is in later ONCOREs
83  * LEAP SECONDS: All of the ONCORE receivers, VP -> M12T have the @@Bj command
84  * that says 'Leap Pending'.  As documented it only becomes true in the month
85  * before the leap second is to be applied, but in practice at least some of
86  * the receivers turn this indicator on as soon as the message is posted, which
87  * can be 6months early.  As such, we use the Bj command to turn on the
88  * instance->pp->leap indicator but only run this test in December and June for
89  * updates on 1Jan and 1July.
90  *
91  * The @@Gj command exists in later ONCOREs, and it gives the exact date
92  * and size of the Leap Update.  It can be emulated in the VP using the @@Bl
93  * command which reads the raw Satellite Broadcast Messages.
94  * We use these two commands to print informative messages in the clockstats
95  * file once per day as soon as the message appears on the satellites.
96  * --------------------------------------------------------------------------
97  * Reg Clemens (Feb 2006)
98  * Fix some gcc4 compiler complaints
99  * Fix possible segfault in oncore_init_shmem
100  * change all (possible) fprintf(stderr, to record_clock_stats
101  * Apply patch from Russell J. Yount <rjy@cmu.edu> Fixed (new) MT12+T UTC not correct
102  *   immediately after new Almanac Read.
103  * Apply patch for new PPS implementation by Rodolfo Giometti <giometti@linux.it>
104  *   now code can use old Ulrich Windl <Ulrich.Windl@rz.uni-regensburg.de> or
105  *   the new one.  Compiles depending on timepps.h seen.
106  * --------------------------------------------------------------------------
107  * Luis Batanero Guerrero <luisba@rao.es> (Dec 2005) Patch for leap seconds
108  * (the oncore driver was setting the wrong ntpd variable)
109  * --------------------------------------------------------------------------
110  * Reg.Clemens (Mar 2004)
111  * Support for interfaces other than PPSAPI removed, for Solaris, SunOS,
112  * SCO, you now need to use one of the timepps.h files in the root dir.
113  * this driver will 'grab' it for you if you dont have one in /usr/include
114  * --------------------------------------------------------------------------
115  * This code uses the two devices
116  *	/dev/oncore.serial.n
117  *	/dev/oncore.pps.n
118  * which may be linked to the same device.
119  * and can read initialization data from the file
120  *	/etc/ntp.oncoreN, /etc/ntp.oncore.N, or /etc/ntp.oncore, where
121  *	n or N are the unit number, viz 127.127.30.N.
122  * --------------------------------------------------------------------------
123  * Reg.Clemens <reg@dwf.com> Sep98.
124  *  Original code written for FreeBSD.
125  *  With these mods it works on FreeBSD, SunOS, Solaris and Linux
126  *    (SunOS 4.1.3 + ppsclock)
127  *    (Solaris7 + MU4)
128  *    (RedHat 5.1 2.0.35 + PPSKit, 2.1.126 + or later).
129  *
130  *  Lat,Long,Ht, cable-delay, offset, and the ReceiverID (along with the
131  *  state machine state) are printed to CLOCKSTATS if that file is enabled
132  *  in /etc/ntp.conf.
133  *
134  * --------------------------------------------------------------------------
135  *
136  * According to the ONCORE manual (TRM0003, Rev 3.2, June 1998, page 3.13)
137  * doing an average of 10000 valid 2D and 3D fixes is what the automatic
138  * site survey mode does.  Looking at the output from the receiver
139  * it seems like it is only using 3D fixes.
140  * When we do it ourselves, take 10000 3D fixes.
141  */
142 
143 #define POS_HOLD_AVERAGE	10000	/* nb, 10000s ~= 2h45m */
144 
145 /*
146  * ONCORE_SHMEM_STATUS will create a mmap(2)'ed file named according to a
147  * "STATUS" line in the oncore config file, which contains the most recent
148  * copy of all types of messages we recognize.	This file can be mmap(2)'ed
149  * by monitoring and statistics programs.
150  *
151  * See separate HTML documentation for this option.
152  */
153 
154 #ifdef HAVE_CONFIG_H
155 #include <config.h>
156 #endif
157 
158 #if defined(REFCLOCK) && defined(CLOCK_ONCORE)
159 
160 #include "ntpd.h"
161 #include "ntp_io.h"
162 #include "ntp_unixtime.h"
163 #include "ntp_refclock.h"
164 #include "ntp_calendar.h"
165 #include "ntp_calgps.h"
166 #include "ntp_stdlib.h"
167 
168 #include <stdio.h>
169 #include <stdarg.h>
170 #include <ctype.h>
171 #include <sys/stat.h>
172 #ifdef ONCORE_SHMEM_STATUS
173 # ifdef HAVE_SYS_MMAN_H
174 #  include <sys/mman.h>
175 #  ifndef MAP_FAILED
176 #   define MAP_FAILED ((u_char *) -1)
177 #  endif  /* MAP_FAILED */
178 # endif /* HAVE_SYS_MMAN_H */
179 #endif /* ONCORE_SHMEM_STATUS */
180 
181 #ifdef HAVE_PPSAPI
182 # include "ppsapi_timepps.h"
183 #endif
184 
185 struct Bl {
186 	int	dt_ls;
187 	int	dt_lsf;
188 	int	WN;
189 	int	DN;
190 	int	WN_lsf;
191 	int	DN_lsf;
192 	int	wn_flg;
193 	int	lsf_flg;
194 	int	Bl_day;
195 } Bl;
196 
197 enum receive_state {
198 	ONCORE_NO_IDEA,
199 	ONCORE_CHECK_ID,
200 	ONCORE_CHECK_CHAN,
201 	ONCORE_HAVE_CHAN,
202 	ONCORE_RESET_SENT,
203 	ONCORE_TEST_SENT,
204 	ONCORE_INIT,
205 	ONCORE_ALMANAC,
206 	ONCORE_RUN
207 };
208 
209 enum site_survey_state {
210 	ONCORE_SS_UNKNOWN,
211 	ONCORE_SS_TESTING,
212 	ONCORE_SS_HW,
213 	ONCORE_SS_SW,
214 	ONCORE_SS_DONE
215 };
216 
217 enum antenna_state {
218       ONCORE_ANTENNA_UNKNOWN = -1,
219       ONCORE_ANTENNA_OK      =	0,
220       ONCORE_ANTENNA_OC      =	1,
221       ONCORE_ANTENNA_UC      =	2,
222       ONCORE_ANTENNA_NV      =	3
223 };
224 
225 /* Model Name, derived from the @@Cj message.
226  * Used to initialize some variables.
227  */
228 
229 enum oncore_model {
230 	ONCORE_BASIC,
231 	ONCORE_PVT6,
232 	ONCORE_VP,
233 	ONCORE_UT,
234 	ONCORE_UTPLUS,
235 	ONCORE_GT,
236 	ONCORE_GTPLUS,
237 	ONCORE_SL,
238 	ONCORE_M12,
239 	ONCORE_UNKNOWN
240 };
241 
242 /* the bits that describe these properties are in the same place
243  * on the VP/UT, but have moved on the M12.  As such we extract
244  * them, and use them from this struct.
245  *
246  */
247 
248 struct RSM {
249 	u_char	posn0D;
250 	u_char	posn2D;
251 	u_char	posn3D;
252 	u_char	bad_almanac;
253 	u_char	bad_fix;
254 };
255 
256 /* It is possible to test the VP/UT each cycle (@@Ea or equivalent) to
257  * see what mode it is in.  The bits on the M12 are multiplexed with
258  * other messages, so we have to 'keep' the last known mode here.
259  */
260 
261 enum posn_mode {
262 	MODE_UNKNOWN,
263 	MODE_0D,
264 	MODE_2D,
265 	MODE_3D
266 };
267 
268 struct instance {
269 	int	unit;		/* 127.127.30.unit */
270 	struct	refclockproc *pp;
271 	struct	peer *peer;
272 
273 	int	ttyfd;		/* TTY file descriptor */
274 	int	ppsfd;		/* PPS file descriptor */
275 	int	shmemfd;	/* Status shm descriptor */
276 	pps_handle_t pps_h;
277 	pps_params_t pps_p;
278 	enum receive_state o_state;		/* Receive state */
279 	enum posn_mode mode;			/* 0D, 2D, 3D */
280 	enum site_survey_state site_survey;	/* Site Survey state */
281 	enum antenna_state ant_state;		/* antenna state */
282 
283 	int	Bj_day;
284 
285 	u_long	delay;		/* ns */
286 	long	offset; 	/* ns */
287 
288 	u_char	*shmem;
289 	char	*shmem_fname;
290 	u_int	shmem_Cb;
291 	u_int	shmem_Ba;
292 	u_int	shmem_Ea;
293 	u_int	shmem_Ha;
294 	u_char	shmem_reset;
295 	u_char	shmem_Posn;
296 	u_char	shmem_bad_Ea;
297 	u_char	almanac_from_shmem;
298 
299 	double	ss_lat;
300 	double	ss_long;
301 	double	ss_ht;
302 	double	dH;
303 	int	ss_count;
304 	u_char	posn_set;
305 
306 	enum oncore_model model;
307 	u_int	version;
308 	u_int	revision;
309 
310 	u_char	chan;		/* 6 for PVT6 or BASIC, 8 for UT/VP, 12 for m12, 0 if unknown */
311 	s_char	traim;		/* do we have traim? yes UT/VP, M12+T, no BASIC, GT, M12, -1 unknown, 0 no, +1 yes */
312 				/* the following 7 are all timing counters */
313 	u_char	traim_delay;	/* seconds counter, waiting for reply */
314 	u_char	count;		/* cycles thru Ea before starting */
315 	u_char	count1; 	/* cycles thru Ea after SS_TESTING, waiting for SS_HW */
316 	u_char	count2; 	/* cycles thru Ea after count, to check for @@Ea */
317 	u_char	count3; 	/* cycles thru Ea checking for # channels */
318 	u_char	count4; 	/* cycles thru leap after Gj to issue Bj */
319 	u_char	count5; 	/* cycles thru get_timestamp waiting for valid UTC correction */
320 	u_char	count5_set;	/* only set count5 once */
321 	u_char	counta; 	/* count for waiting on almanac message */
322 	u_char	pollcnt;
323 	u_char	timeout;	/* count to retry Cj after Fa self-test */
324 	u_char	max_len;	/* max length message seen by oncore_log, for debugging */
325 	u_char	max_count;	/* count for message statistics */
326 
327 	struct	RSM rsm;	/* bits extracted from Receiver Status Msg in @@Ea */
328 	struct	Bl Bl;		/* Satellite Broadcast Data Message */
329 	u_char	printed;
330 	u_char	polled;
331 	u_long	ev_serial;
332 	unsigned	Rcvptr;
333 	u_char	Rcvbuf[500];
334 	u_char	BEHa[160];	/* Ba, Ea or Ha */
335 	u_char	BEHn[80];	/* Bn , En , or Hn */
336 	u_char	Cj[300];
337 	u_char	Ag;		/* Satellite mask angle */
338 	u_char	saw_At;
339 	u_char	saw_Ay;
340 	u_char	saw_Az;
341 	s_char	saw_Bj;
342 	s_char	saw_Gj;
343 	u_char	have_dH;
344 	u_char	init_type;
345 	s_char	saw_tooth;
346 	s_char	chan_in;	/* chan number from INPUT, will always use it */
347 	u_char	chan_id;	/* chan number determined from part number */
348 	u_char	chan_ck;	/* chan number determined by sending commands to hardware */
349 	s_char	traim_in;	/* TRAIM from INPUT, will always use ON/OFF specified */
350 	s_char	traim_id;	/* TRAIM determined from part number */
351 	u_char	traim_ck;	/* TRAIM determined by sending commands to hardware */
352 	u_char	once;		/* one pass code at top of BaEaHa */
353 	s_char	assert;
354 	u_char	hardpps;
355 	s_char	pps_control;	/* PPS control, M12 only */
356 	s_char	pps_control_msg_seen;
357 };
358 
359 #define rcvbuf	instance->Rcvbuf
360 #define rcvptr	instance->Rcvptr
361 
362 static	int	oncore_start	      (int, struct peer *);
363 static	void	oncore_poll	      (int, struct peer *);
364 static	void	oncore_shutdown       (int, struct peer *);
365 static	void	oncore_consume	      (struct instance *);
366 static	void	oncore_read_config    (struct instance *);
367 static	void	oncore_receive	      (struct recvbuf *);
368 static	int	oncore_ppsapi	      (struct instance *);
369 static	void	oncore_get_timestamp  (struct instance *, long, long);
370 static	void	oncore_init_shmem     (struct instance *);
371 
372 static	void	oncore_antenna_report (struct instance *, enum antenna_state);
373 static	void	oncore_chan_test      (struct instance *);
374 static	void	oncore_check_almanac  (struct instance *);
375 static	void	oncore_check_antenna  (struct instance *);
376 static	void	oncore_check_leap_sec (struct instance *);
377 static	int	oncore_checksum_ok    (u_char *, int);
378 static	void	oncore_compute_dH     (struct instance *);
379 static	void	oncore_load_almanac   (struct instance *);
380 static	void	oncore_log	      (struct instance *, int, const char *);
381 static	int	oncore_log_f	      (struct instance *, int, const char *, ...)
382 		NTP_PRINTF(3, 4);
383 static	void	oncore_print_Cb       (struct instance *, u_char *);
384 /* static  void    oncore_print_array	 (u_char *, int);	*/
385 static	void	oncore_print_posn     (struct instance *);
386 static	void	oncore_sendmsg	      (struct instance *, u_char *, size_t);
387 static	void	oncore_set_posn       (struct instance *);
388 static	void	oncore_set_traim      (struct instance *);
389 static	void	oncore_shmem_get_3D   (struct instance *);
390 static	void	oncore_ss	      (struct instance *);
391 static	int	oncore_wait_almanac   (struct instance *);
392 static	void	oncore_feed_clockproc (struct instance *);
393 
394 static	void	oncore_msg_any	   (struct instance *, u_char *, size_t, int);
395 static	void	oncore_msg_Adef    (struct instance *, u_char *, size_t);
396 static	void	oncore_msg_Ag	   (struct instance *, u_char *, size_t);
397 static	void	oncore_msg_As	   (struct instance *, u_char *, size_t);
398 static	void	oncore_msg_At	   (struct instance *, u_char *, size_t);
399 static	void	oncore_msg_Ay	   (struct instance *, u_char *, size_t);
400 static	void	oncore_msg_Az	   (struct instance *, u_char *, size_t);
401 static	void	oncore_msg_BaEaHa  (struct instance *, u_char *, size_t);
402 static	void	oncore_msg_Bd	   (struct instance *, u_char *, size_t);
403 static	void	oncore_msg_Bj	   (struct instance *, u_char *, size_t);
404 static	void	oncore_msg_Bl	   (struct instance *, u_char *, size_t);
405 static	void	oncore_msg_BnEnHn  (struct instance *, u_char *, size_t);
406 static	void	oncore_msg_CaFaIa  (struct instance *, u_char *, size_t);
407 static	void	oncore_msg_Cb	   (struct instance *, u_char *, size_t);
408 static	void	oncore_msg_Cf	   (struct instance *, u_char *, size_t);
409 static	void	oncore_msg_Cj	   (struct instance *, u_char *, size_t);
410 static	void	oncore_msg_Cj_id   (struct instance *, u_char *, size_t);
411 static	void	oncore_msg_Cj_init (struct instance *, u_char *, size_t);
412 static	void	oncore_msg_Ga	   (struct instance *, u_char *, size_t);
413 static	void	oncore_msg_Gb	   (struct instance *, u_char *, size_t);
414 static	void	oncore_msg_Gc	   (struct instance *, u_char *, size_t);
415 static	void	oncore_msg_Gj	   (struct instance *, u_char *, size_t);
416 static	void	oncore_msg_Sz	   (struct instance *, u_char *, size_t);
417 
418 struct	refclock refclock_oncore = {
419 	oncore_start,		/* start up driver */
420 	oncore_shutdown,	/* shut down driver */
421 	oncore_poll,		/* transmit poll message */
422 	noentry,		/* not used */
423 	noentry,		/* not used */
424 	noentry,		/* not used */
425 	NOFLAGS 		/* not used */
426 };
427 
428 /*
429  * Understanding the next bit here is not easy unless you have a manual
430  * for the the various Oncore Models.
431  */
432 
433 static struct msg_desc {
434 	const char	flag[3];
435 	const int	len;
436 	void		(*handler) (struct instance *, u_char *, size_t);
437 	const char	*fmt;
438 	int		shmem;
439 } oncore_messages[] = {
440 			/* Ea and En first since they're most common */
441 	{ "Ea",  76,    oncore_msg_BaEaHa, "mdyyhmsffffaaaaoooohhhhmmmmvvhhddtntimsdimsdimsdimsdimsdimsdimsdimsdsC", 0 },
442 	{ "Ba",  68,    oncore_msg_BaEaHa, "mdyyhmsffffaaaaoooohhhhmmmmvvhhddtntimsdimsdimsdimsdimsdimsdsC", 0 },
443 	{ "Ha", 154,    oncore_msg_BaEaHa, "mdyyhmsffffaaaaoooohhhhmmmmaaaaoooohhhhmmmmVVvvhhddntimsiddimsiddimsiddimsiddimsiddimsiddimsiddimsiddimsiddimsiddimsiddimsiddssrrccooooTTushmvvvvvvC", 0 },
444 	{ "Bn",  59,    oncore_msg_BnEnHn, "otaapxxxxxxxxxxpysreensffffsffffsffffsffffsffffsffffC", 0 },
445 	{ "En",  69,    oncore_msg_BnEnHn, "otaapxxxxxxxxxxpysreensffffsffffsffffsffffsffffsffffsffffsffffC", 0 },
446 	{ "Hn",  78,    oncore_msg_BnEnHn, "", 0 },
447 	{ "Ab",  10,    0,                 "", 0 },
448 	{ "Ac",  11,    0,                 "", 0 },
449 	{ "Ad",  11,    oncore_msg_Adef,   "", 0 },
450 	{ "Ae",  11,    oncore_msg_Adef,   "", 0 },
451 	{ "Af",  15,    oncore_msg_Adef,   "", 0 },
452 	{ "Ag",   8,    oncore_msg_Ag,     "", 0 }, /* Satellite mask angle */
453 	{ "As",  20,    oncore_msg_As,     "", 0 },
454 	{ "At",   8,    oncore_msg_At,     "", 0 },
455 	{ "Au",  12,    0,                 "", 0 },
456 	{ "Av",   8,    0,                 "", 0 },
457 	{ "Aw",   8,    0,                 "", 0 },
458 	{ "Ay",  11,    oncore_msg_Ay,     "", 0 },
459 	{ "Az",  11,    oncore_msg_Az,     "", 0 },
460 	{ "AB",   8,    0,                 "", 0 },
461 	{ "Bb",  92,    0,                 "", 0 },
462 	{ "Bd",  23,    oncore_msg_Bd,     "", 0 },
463 	{ "Bj",   8,    oncore_msg_Bj,     "", 0 },
464 	{ "Bl",  41,    oncore_msg_Bl,     "", 0 },
465 	{ "Ca",   9,    oncore_msg_CaFaIa, "", 0 },
466 	{ "Cb",  33,    oncore_msg_Cb,     "", 0 },
467 	{ "Cf",   7,    oncore_msg_Cf,     "", 0 },
468 	{ "Cg",   8,    0,                 "", 0 },
469 	{ "Ch",   9,    0,                 "", 0 },
470 	{ "Cj", 294,    oncore_msg_Cj,     "", 0 },
471 	{ "Ek",  71,    0,                 "", 0 },
472 	{ "Fa",   9,    oncore_msg_CaFaIa, "", 0 },
473 	{ "Ga",  20,    oncore_msg_Ga,     "", 0 },
474 	{ "Gb",  17,    oncore_msg_Gb,     "", 0 },
475 	{ "Gc",   8,    oncore_msg_Gc,     "", 0 },
476 	{ "Gd",   8,    0,                 "", 0 },
477 	{ "Ge",   8,    0,                 "", 0 },
478 	{ "Gj",  21,    oncore_msg_Gj,     "", 0 },
479 	{ "Ia",  10,    oncore_msg_CaFaIa, "", 0 },
480 	{ "Sz",   8,    oncore_msg_Sz,     "", 0 },
481 	{ {0},	  7,	0,		   "", 0 }
482 };
483 
484 
485 static u_char oncore_cmd_Aa[]  = { 'A', 'a', 0, 0, 0 }; 			    /* 6/8	Time of Day				*/
486 static u_char oncore_cmd_Ab[]  = { 'A', 'b', 0, 0, 0 }; 			    /* 6/8	GMT Correction				*/
487 static u_char oncore_cmd_AB[]  = { 'A', 'B', 4 };				    /* VP	Application Type: Static		*/
488 static u_char oncore_cmd_Ac[]  = { 'A', 'c', 0, 0, 0, 0 };			    /* 6/8	Date					*/
489 static u_char oncore_cmd_Ad[]  = { 'A', 'd', 0,0,0,0 }; 			    /* 6/8	Latitude				*/
490 static u_char oncore_cmd_Ae[]  = { 'A', 'e', 0,0,0,0 }; 			    /* 6/8	Longitude				*/
491 static u_char oncore_cmd_Af[]  = { 'A', 'f', 0,0,0,0, 0 };			    /* 6/8	Height					*/
492 static u_char oncore_cmd_Ag[]  = { 'A', 'g', 0 };				    /* 6/8/12	Satellite Mask Angle			*/
493 static u_char oncore_cmd_Agx[] = { 'A', 'g', 0xff };				    /* 6/8/12	Satellite Mask Angle: read		*/
494 static u_char oncore_cmd_As[]  = { 'A', 's', 0,0,0,0, 0,0,0,0, 0,0,0,0, 0 };	    /* 6/8/12	Posn Hold Parameters			*/
495 static u_char oncore_cmd_Asx[] = { 'A', 's', 0x7f,0xff,0xff,0xff,		    /* 6/8/12	Posn Hold Readback			*/
496 					     0x7f,0xff,0xff,0xff,		    /*		 on UT+ this doesnt work with 0xff	*/
497 					     0x7f,0xff,0xff,0xff, 0xff };	    /*		 but does work with 0x7f (sigh).	*/
498 static u_char oncore_cmd_At0[] = { 'A', 't', 0 };				    /* 6/8	Posn Hold: off				*/
499 static u_char oncore_cmd_At1[] = { 'A', 't', 1 };				    /* 6/8	Posn Hold: on				*/
500 static u_char oncore_cmd_At2[] = { 'A', 't', 2 };				    /* 6/8	Posn Hold: Start Site Survey		*/
501 static u_char oncore_cmd_Atx[] = { 'A', 't', 0xff };				    /* 6/8	Posn Hold: Read Back			*/
502 static u_char oncore_cmd_Au[]  = { 'A', 'u', 0,0,0,0, 0 };			    /* GT/M12	Altitude Hold Ht.			*/
503 static u_char oncore_cmd_Av0[] = { 'A', 'v', 0 };				    /* VP/GT	Altitude Hold: off			*/
504 static u_char oncore_cmd_Av1[] = { 'A', 'v', 1 };				    /* VP/GT	Altitude Hold: on			*/
505 static u_char oncore_cmd_Aw[]  = { 'A', 'w', 1 };				    /* 6/8/12	UTC/GPS time selection			*/
506 static u_char oncore_cmd_Ay[]  = { 'A', 'y', 0, 0, 0, 0 };			    /* Timing	1PPS time offset: set			*/
507 static u_char oncore_cmd_Ayx[] = { 'A', 'y', 0xff, 0xff, 0xff, 0xff };		    /* Timing	1PPS time offset: Read			*/
508 static u_char oncore_cmd_Az[]  = { 'A', 'z', 0, 0, 0, 0 };			    /* 6/8UT/12 1PPS Cable Delay: set			*/
509 static u_char oncore_cmd_Azx[] = { 'A', 'z', 0xff, 0xff, 0xff, 0xff };		    /* 6/8UT/12 1PPS Cable Delay: Read			*/
510 static u_char oncore_cmd_Ba0[] = { 'B', 'a', 0 };				    /* 6	Position/Data/Status: off		*/
511 static u_char oncore_cmd_Ba[]  = { 'B', 'a', 1 };				    /* 6	Position/Data/Status: on		*/
512 static u_char oncore_cmd_Bb[]  = { 'B', 'b', 1 };				    /* 6/8/12	Visible Satellites			*/
513 static u_char oncore_cmd_Bd[]  = { 'B', 'd', 1 };				    /* 6/8/12?	Almanac Status Msg.			*/
514 static u_char oncore_cmd_Be[]  = { 'B', 'e', 1 };				    /* 6/8/12	Request Almanac Data			*/
515 static u_char oncore_cmd_Bj[]  = { 'B', 'j', 0 };				    /* 6/8	Leap Second Pending			*/
516 static u_char oncore_cmd_Bl[]  = { 'B', 'l', 1 };				    /* VP	Satellite Broadcast Data Msg		*/
517 static u_char oncore_cmd_Bn0[] = { 'B', 'n', 0, 1, 0,10, 2, 0,0,0, 0,0,0,0,0,0,0 }; /* 6	TRAIM setup/status: msg off, traim on	*/
518 static u_char oncore_cmd_Bn[]  = { 'B', 'n', 1, 1, 0,10, 2, 0,0,0, 0,0,0,0,0,0,0 }; /* 6	TRAIM setup/status: msg on,  traim on	*/
519 static u_char oncore_cmd_Bnx[] = { 'B', 'n', 0, 0, 0,10, 2, 0,0,0, 0,0,0,0,0,0,0 }; /* 6	TRAIM setup/status: msg off, traim off	*/
520 static u_char oncore_cmd_Ca[]  = { 'C', 'a' };					    /* 6	Self Test				*/
521 static u_char oncore_cmd_Cf[]  = { 'C', 'f' };					    /* 6/8/12	Set to Defaults 			*/
522 static u_char oncore_cmd_Cg[]  = { 'C', 'g', 1 };				    /* VP	Posn Fix/Idle Mode			*/
523 static u_char oncore_cmd_Cj[]  = { 'C', 'j' };					    /* 6/8/12	Receiver ID				*/
524 static u_char oncore_cmd_Ea0[] = { 'E', 'a', 0 };				    /* 8	Position/Data/Status: off		*/
525 static u_char oncore_cmd_Ea[]  = { 'E', 'a', 1 };				    /* 8	Position/Data/Status: on		*/
526 static u_char oncore_cmd_Ek[]  = { 'E', 'k', 0 }; /* just turn off */		    /* 8	Posn/Status/Data - extension		*/
527 static u_char oncore_cmd_En0[] = { 'E', 'n', 0, 1, 0,10, 2, 0,0,0, 0,0,0,0,0,0,0 }; /* 8/GT	TRAIM setup/status: msg off, traim on	*/
528 static u_char oncore_cmd_En[]  = { 'E', 'n', 1, 1, 0,10, 2, 0,0,0, 0,0,0,0,0,0,0 }; /* 8/GT	TRAIM setup/status: msg on,  traim on	*/
529 static u_char oncore_cmd_Enx[] = { 'E', 'n', 0, 0, 0,10, 2, 0,0,0, 0,0,0,0,0,0,0 }; /* 8/GT	TRAIM setup/status: msg off, traim off	*/
530 static u_char oncore_cmd_Fa[]  = { 'F', 'a' };					    /* 8	Self Test				*/
531 static u_char oncore_cmd_Ga[]  = { 'G', 'a', 0,0,0,0, 0,0,0,0, 0,0,0,0, 0 };	    /* 12	Position Set				*/
532 static u_char oncore_cmd_Gax[] = { 'G', 'a', 0xff, 0xff, 0xff, 0xff,		    /* 12	Position Set: Read			*/
533 					     0xff, 0xff, 0xff, 0xff,		    /*							*/
534 					     0xff, 0xff, 0xff, 0xff, 0xff };	    /*							*/
535 static u_char oncore_cmd_Gb[]  = { 'G', 'b', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };	    /* 12	set Date/Time				*/
536 static u_char oncore_cmd_Gc[]  = { 'G', 'c', 0 };				    /* 12	PPS Control: Off, On, 1+satellite,TRAIM */
537 static u_char oncore_cmd_Gd0[] = { 'G', 'd', 0 };				    /* 12	Position Control: 3D (no hold)		*/
538 static u_char oncore_cmd_Gd1[] = { 'G', 'd', 1 };				    /* 12	Position Control: 0D (3D hold)		*/
539 static u_char oncore_cmd_Gd2[] = { 'G', 'd', 2 };				    /* 12	Position Control: 2D (Alt Hold) 	*/
540 static u_char oncore_cmd_Gd3[] = { 'G', 'd', 3 };				    /* 12	Position Coltrol: Start Site Survey	*/
541 static u_char oncore_cmd_Ge0[] = { 'G', 'e', 0 };				    /* M12+T	TRAIM: off				*/
542 static u_char oncore_cmd_Ge[]  = { 'G', 'e', 1 };				    /* M12+T	TRAIM: on				*/
543 static u_char oncore_cmd_Gj[]  = { 'G', 'j' };					    /* 8?/12	Leap Second Pending			*/
544 static u_char oncore_cmd_Ha0[] = { 'H', 'a', 0 };				    /* 12	Position/Data/Status: off		*/
545 static u_char oncore_cmd_Ha[]  = { 'H', 'a', 1 };				    /* 12	Position/Data/Status: on		*/
546 static u_char oncore_cmd_Hn0[] = { 'H', 'n', 0 };				    /* 12	TRAIM Status: off			*/
547 static u_char oncore_cmd_Hn[]  = { 'H', 'n', 1 };				    /* 12	TRAIM Status: on			*/
548 static u_char oncore_cmd_Ia[]  = { 'I', 'a' };					    /* 12	Self Test				*/
549 
550 /* it appears that as of 1997/1998, the UT had As,At, but not Au,Av
551  *				    the GT had Au,Av, but not As,At
552  * This was as of v2.0 of both firmware sets. possibly 1.3 for UT.
553  * Bj in UT at v1.3
554  * dont see Bd in UT/GT thru 1999
555  * Gj in UT as of 3.0, 1999 , Bj as of 1.3
556  */
557 
558 #define DEVICE1 	"/dev/oncore.serial.%d" /* name of serial device */
559 #define DEVICE2 	"/dev/oncore.pps.%d"    /* name of pps device */
560 
561 #define SPEED		B9600		/* Oncore Binary speed (9600 bps) */
562 
563 /*
564  * Assemble and disassemble 32bit signed quantities from a buffer.
565  *
566  */
567 
568 	/* to buffer, int w, u_char *buf */
569 #define w32_buf(buf,w)	{ u_int i_tmp;			   \
570 			  i_tmp = (w<0) ? (~(-w)+1) : (w); \
571 			  (buf)[0] = (i_tmp >> 24) & 0xff; \
572 			  (buf)[1] = (i_tmp >> 16) & 0xff; \
573 			  (buf)[2] = (i_tmp >>	8) & 0xff; \
574 			  (buf)[3] = (i_tmp	 ) & 0xff; \
575 			}
576 
577 #define w32(buf)      (((buf)[0]&0xff) << 24 | \
578 		       ((buf)[1]&0xff) << 16 | \
579 		       ((buf)[2]&0xff) <<  8 | \
580 		       ((buf)[3]&0xff) )
581 
582 	/* from buffer, char *buf, result to an int */
583 #define buf_w32(buf) (((buf)[0]&0200) ? (-(~w32(buf)+1)) : w32(buf))
584 
585 
586 /*
587  * oncore_start - initialize data for processing
588  */
589 
590 static int
591 oncore_start(
592 	int unit,
593 	struct peer *peer
594 	)
595 {
596 #define STRING_LEN	32
597 	register struct instance *instance;
598 	struct refclockproc *pp;
599 	int fd1, fd2;
600 	char device1[STRING_LEN], device2[STRING_LEN];
601 #ifndef SYS_WINNT
602 	struct stat stat1, stat2;
603 #endif
604 
605 	/* create instance structure for this unit */
606 
607 	instance = emalloc(sizeof(*instance));
608 	memset(instance, 0, sizeof(*instance));
609 
610 	/* initialize miscellaneous variables */
611 
612 	pp = peer->procptr;
613 	instance->pp   = pp;
614 	instance->unit = unit;
615 	instance->peer = peer;
616 	instance->assert = 1;
617 	instance->once = 1;
618 
619 	instance->Bj_day = -1;
620 	instance->traim = -1;
621 	instance->traim_in = -1;
622 	instance->chan_in = -1;
623 	instance->pps_control = -1;	/* PPS control, M12 only */
624 	instance->pps_control_msg_seen = -1;	/* Have seen response to Gc msg */
625 	instance->model = ONCORE_UNKNOWN;
626 	instance->mode = MODE_UNKNOWN;
627 	instance->site_survey = ONCORE_SS_UNKNOWN;
628 	instance->Ag = 0xff;		/* Satellite mask angle, unset by user */
629 	instance->ant_state = ONCORE_ANTENNA_UNKNOWN;
630 
631 	peer->flags &= ~FLAG_PPS;	/* PPS not active yet */
632 	peer->precision = -26;
633 	peer->minpoll = 4;
634 	peer->maxpoll = 4;
635 	pp->clockdesc = "Motorola Oncore GPS Receiver";
636 	memcpy((char *)&pp->refid, "GPS\0", (size_t) 4);
637 
638 	oncore_log(instance, LOG_NOTICE, "ONCORE DRIVER -- CONFIGURING");
639 	instance->o_state = ONCORE_NO_IDEA;
640 	oncore_log(instance, LOG_NOTICE, "state = ONCORE_NO_IDEA");
641 
642 	/* Now open files.
643 	 * This is a bit complicated, a we dont want to open the same file twice
644 	 * (its a problem on some OS), and device2 may not exist for the new PPS
645 	 */
646 
647 	(void)snprintf(device1, sizeof(device1), DEVICE1, unit);
648 	(void)snprintf(device2, sizeof(device2), DEVICE2, unit);
649 
650 	/* OPEN DEVICES */
651 	/* opening different devices for fd1 and fd2 presents no problems */
652 	/* opening the SAME device twice, seems to be OS dependent.
653 		(a) on Linux (no streams) no problem
654 		(b) on SunOS (and possibly Solaris, untested), (streams)
655 			never see the line discipline.
656 	   Since things ALWAYS work if we only open the device once, we check
657 	     to see if the two devices are in fact the same, then proceed to
658 	     do one open or two.
659 
660 	   For use with linuxPPS we assume that the N_TTY file has been opened
661 	     and that the line discipline has been changed to N_PPS by another
662 	     program (say ppsldisc) so that the two files expected by the oncore
663 	     driver can be opened.
664 
665 	   Note that the linuxPPS N_PPS file is just like a N_TTY, so we can do
666 	     the stat below without error even though the file has already had its
667 	     line discipline changed by another process.
668 
669 	   The Windows port of ntpd arranges to return duplicate handles for
670 	     multiple opens of the same serial device, and doesn't have inodes
671 	     for serial handles, so we just open both on Windows.
672 	*/
673 #ifndef SYS_WINNT
674 	if (stat(device1, &stat1)) {
675 		oncore_log_f(instance, LOG_ERR, "Can't stat fd1 (%s)",
676 			     device1);
677 		return(0);			/* exit, no file, can't start driver */
678 	}
679 
680 	if (stat(device2, &stat2)) {
681 		stat2.st_dev = stat2.st_ino = -2;
682 		oncore_log_f(instance, LOG_ERR, "Can't stat fd2 (%s) %d %m",
683 			     device2, errno);
684 	}
685 #endif	/* !SYS_WINNT */
686 
687 	fd1 = refclock_open(device1, SPEED, LDISC_RAW);
688 	if (fd1 <= 0) {
689 		oncore_log_f(instance, LOG_ERR, "Can't open fd1 (%s)",
690 			     device1);
691 		return(0);			/* exit, can't open file, can't start driver */
692 	}
693 
694 	/* for LINUX the PPS device is the result of a line discipline.
695 	   It seems simplest to let an external program create the appropriate
696 	   /dev/pps<n> file, and only check (carefully) for its existance here
697 	 */
698 
699 #ifndef SYS_WINNT
700 	if ((stat1.st_dev == stat2.st_dev) && (stat1.st_ino == stat2.st_ino))	/* same device here */
701 		fd2 = fd1;
702 	else
703 #endif	/* !SYS_WINNT */
704 	{	/* different devices here */
705 		if ((fd2=tty_open(device2, O_RDWR, 0777)) < 0) {
706 			oncore_log_f(instance, LOG_ERR,
707 				     "Can't open fd2 (%s)", device2);
708 			return(0);		/* exit, can't open PPS file, can't start driver */
709 		}
710 	}
711 
712 	/* open ppsapi source */
713 
714 	if (time_pps_create(fd2, &instance->pps_h) < 0) {
715 		oncore_log(instance, LOG_ERR, "exit, PPSAPI not found in kernel");
716 		return(0);			/* exit, don't find PPSAPI in kernel */
717 	}
718 
719 	/* continue initialization */
720 
721 	instance->ttyfd = fd1;
722 	instance->ppsfd = fd2;
723 
724 	/* go read any input data in /etc/ntp.oncoreX or /etc/ntp/oncore.X */
725 
726 	oncore_read_config(instance);
727 
728 	if (!oncore_ppsapi(instance))
729 		return(0);
730 
731 	pp->io.clock_recv = oncore_receive;
732 	pp->io.srcclock = peer;
733 	pp->io.datalen = 0;
734 	pp->io.fd = fd1;
735 	if (!io_addclock(&pp->io)) {
736 		oncore_log(instance, LOG_ERR, "can't do io_addclock");
737 		close(fd1);
738 		pp->io.fd = -1;
739 		free(instance);
740 		return (0);
741 	}
742 	pp->unitptr = instance;
743 
744 #ifdef ONCORE_SHMEM_STATUS
745 	/*
746 	 * Before starting ONCORE, lets setup SHMEM
747 	 * This will include merging an old SHMEM into the new one if
748 	 * an old one is found.
749 	 */
750 
751 	oncore_init_shmem(instance);
752 #endif
753 
754 	/*
755 	 * This will return the Model of the Oncore receiver.
756 	 * and start the Initialization loop in oncore_msg_Cj.
757 	 */
758 
759 	instance->o_state = ONCORE_CHECK_ID;
760 	oncore_log(instance, LOG_NOTICE, "state = ONCORE_CHECK_ID");
761 
762 	instance->timeout = 4;
763 	oncore_sendmsg(instance, oncore_cmd_Cg, sizeof(oncore_cmd_Cg)); /* Set Posn Fix mode (not Idle (VP)) */
764 	oncore_sendmsg(instance, oncore_cmd_Cj, sizeof(oncore_cmd_Cj));
765 
766 	instance->pollcnt = 2;
767 	return (1);
768 }
769 
770 
771 /*
772  * oncore_shutdown - shut down the clock
773  */
774 
775 static void
776 oncore_shutdown(
777 	int unit,
778 	struct peer *peer
779 	)
780 {
781 	register struct instance *instance;
782 	struct refclockproc *pp;
783 
784 	pp = peer->procptr;
785 	instance = pp->unitptr;
786 
787 	if (pp->io.fd != -1)
788 		io_closeclock(&pp->io);
789 
790 	if (instance != NULL) {
791 		time_pps_destroy (instance->pps_h);
792 
793 		close(instance->ttyfd);
794 
795 		if ((instance->ppsfd != -1) && (instance->ppsfd != instance->ttyfd))
796 			close(instance->ppsfd);
797 
798 		if (instance->shmemfd)
799 			close(instance->shmemfd);
800 
801 		free(instance);
802 	}
803 }
804 
805 
806 
807 /*
808  * oncore_poll - called by the transmit procedure
809  */
810 
811 static void
812 oncore_poll(
813 	int unit,
814 	struct peer *peer
815 	)
816 {
817 	struct instance *instance;
818 
819 	instance = peer->procptr->unitptr;
820 	if (instance->timeout) {
821 		instance->timeout--;
822 		if (instance->timeout == 0) {
823 			oncore_log(instance, LOG_ERR,
824 			    "Oncore: No response from @@Cj, shutting down driver");
825 			oncore_shutdown(unit, peer);
826 		} else {
827 			oncore_sendmsg(instance, oncore_cmd_Cj, sizeof(oncore_cmd_Cj));
828 			oncore_log(instance, LOG_WARNING, "Oncore: Resend @@Cj");
829 		}
830 		return;
831 	}
832 
833 	if (!instance->pollcnt)
834 		refclock_report(peer, CEVNT_TIMEOUT);
835 	else
836 		instance->pollcnt--;
837 	peer->procptr->polls++;
838 	instance->polled = 1;
839 }
840 
841 
842 
843 /*
844  * Initialize PPSAPI
845  */
846 
847 static int
848 oncore_ppsapi(
849 	struct instance *instance
850 	)
851 {
852 	int cap, mode, mode1;
853 	const char *cp;
854 
855 	if (time_pps_getcap(instance->pps_h, &cap) < 0) {
856 		oncore_log_f(instance, LOG_ERR, "time_pps_getcap failed: %m");
857 		return (0);
858 	}
859 
860 	if (time_pps_getparams(instance->pps_h, &instance->pps_p) < 0) {
861 		oncore_log_f(instance, LOG_ERR, "time_pps_getparams failed: %m");
862 		return (0);
863 	}
864 
865 	/* nb. only turn things on, if someone else has turned something
866 	 *	on before we get here, leave it alone!
867 	 */
868 
869 	if (instance->assert) {
870 		cp = "Assert";
871 		mode = PPS_CAPTUREASSERT;
872 		mode1 = PPS_OFFSETASSERT;
873 	} else {
874 		cp = "Clear";
875 		mode = PPS_CAPTURECLEAR;
876 		mode1 = PPS_OFFSETCLEAR;
877 	}
878 	oncore_log_f(instance, LOG_INFO, "Initializing timing to %s.",
879 		     cp);
880 
881 	if (!(mode & cap)) {
882 		oncore_log_f(instance, LOG_ERR,
883 			     "Can't set timing to %s, exiting...", cp);
884 		return(0);
885 	}
886 
887 	if (!(mode1 & cap)) {
888 		oncore_log_f(instance, LOG_NOTICE,
889 			     "Can't set %s, this will increase jitter.",
890 			     cp);
891 		mode1 = 0;
892 	}
893 
894 	/* only set what is legal */
895 
896 	instance->pps_p.mode = (mode | mode1 | PPS_TSFMT_TSPEC) & cap;
897 
898 	if (time_pps_setparams(instance->pps_h, &instance->pps_p) < 0) {
899 		oncore_log_f(instance, LOG_ERR, "ONCORE: time_pps_setparams fails %m");
900 		return(0);		/* exit, can't do time_pps_setparans on PPS file */
901 	}
902 
903 	/* If HARDPPS is on, we tell kernel */
904 
905 	if (instance->hardpps) {
906 		int	i;
907 
908 		oncore_log(instance, LOG_INFO, "HARDPPS Set.");
909 
910 		if (instance->assert)
911 			i = PPS_CAPTUREASSERT;
912 		else
913 			i = PPS_CAPTURECLEAR;
914 
915 		/* we know that 'i' is legal from above */
916 
917 		if (time_pps_kcbind(instance->pps_h, PPS_KC_HARDPPS, i,
918 		    PPS_TSFMT_TSPEC) < 0) {
919 			oncore_log_f(instance, LOG_ERR, "time_pps_kcbind failed: %m");
920 			oncore_log(instance, LOG_ERR, "HARDPPS failed, abort...");
921 			return (0);
922 		}
923 
924 		hardpps_enable = 1;
925 	}
926 	return(1);
927 }
928 
929 
930 
931 #ifdef ONCORE_SHMEM_STATUS
932 static void
933 oncore_init_shmem(
934 	struct instance *instance
935 	)
936 {
937 	int l, fd;
938 	u_char *cp, *cp1, *buf, *shmem_old;
939 	struct msg_desc *mp;
940 	struct stat sbuf;
941 	size_t i, n, n1, shmem_length, shmem_old_size;
942 
943 	/*
944 	* The first thing we do is see if there is an instance->shmem_fname file (still)
945 	* out there from a previous run.  If so, we copy it in and use it to initialize
946 	* shmem (so we won't lose our almanac if we need it).
947 	*/
948 
949 	shmem_old = 0;
950 	shmem_old_size = 0;
951 	if ((fd = open(instance->shmem_fname, O_RDONLY)) < 0)
952 		oncore_log(instance, LOG_WARNING, "ONCORE: Can't open SHMEM file");
953 	else {
954 		fstat(fd, &sbuf);
955 		shmem_old_size = sbuf.st_size;
956 		if (shmem_old_size != 0) {
957 			shmem_old = emalloc((unsigned) sbuf.st_size);
958 			read(fd, shmem_old, shmem_old_size);
959 		}
960 		close(fd);
961 	}
962 
963 	/* OK, we now create the NEW SHMEM. */
964 
965 	if ((instance->shmemfd = open(instance->shmem_fname, O_RDWR|O_CREAT|O_TRUNC, 0644)) < 0) {
966 		oncore_log(instance, LOG_WARNING, "ONCORE: Can't open shmem");
967 		if (shmem_old)
968 			free(shmem_old);
969 
970 		return;
971 	}
972 
973 	/* see how big it needs to be */
974 
975 	n = 1;
976 	for (mp=oncore_messages; mp->flag[0]; mp++) {
977 		mp->shmem = n;
978 		/* Allocate space for multiplexed almanac, and 0D/2D/3D @@Ea records */
979 		if (!strcmp(mp->flag, "Cb")) {
980 			instance->shmem_Cb = n;
981 			n += (mp->len + 3) * 34;
982 		}
983 		if (!strcmp(mp->flag, "Ba")) {
984 			instance->shmem_Ba = n;
985 			n += (mp->len + 3) * 3;
986 		}
987 		if (!strcmp(mp->flag, "Ea")) {
988 			instance->shmem_Ea = n;
989 			n += (mp->len + 3) * 3;
990 		}
991 		if (!strcmp(mp->flag, "Ha")) {
992 			instance->shmem_Ha = n;
993 			n += (mp->len + 3) * 3;
994 		}
995 		n += (mp->len + 3);
996 	}
997 	shmem_length = n + 2;
998 
999 	buf = emalloc(shmem_length);
1000 	memset(buf, 0, shmem_length);
1001 
1002 	/* next build the new SHMEM buffer in memory */
1003 
1004 	for (mp=oncore_messages; mp->flag[0]; mp++) {
1005 		l = mp->shmem;
1006 		buf[l + 0] = mp->len >> 8;
1007 		buf[l + 1] = mp->len & 0xff;
1008 		buf[l + 2] = 0;
1009 		buf[l + 3] = '@';
1010 		buf[l + 4] = '@';
1011 		buf[l + 5] = mp->flag[0];
1012 		buf[l + 6] = mp->flag[1];
1013 		if (!strcmp(mp->flag, "Cb") || !strcmp(mp->flag, "Ba") || !strcmp(mp->flag, "Ea") || !strcmp(mp->flag, "Ha")) {
1014 			if (!strcmp(mp->flag, "Cb"))
1015 				n = 35;
1016 			else
1017 				n = 4;
1018 			for (i=1; i<n; i++) {
1019 				buf[l + i * (mp->len+3) + 0] = mp->len >> 8;
1020 				buf[l + i * (mp->len+3) + 1] = mp->len & 0xff;
1021 				buf[l + i * (mp->len+3) + 2] = 0;
1022 				buf[l + i * (mp->len+3) + 3] = '@';
1023 				buf[l + i * (mp->len+3) + 4] = '@';
1024 				buf[l + i * (mp->len+3) + 5] = mp->flag[0];
1025 				buf[l + i * (mp->len+3) + 6] = mp->flag[1];
1026 			}
1027 		}
1028 	}
1029 
1030 	/* we now walk thru the two buffers (shmem_old and buf, soon to become shmem)
1031 	 * copying the data in shmem_old to buf.
1032 	 * When we are done we write it out and free both buffers.
1033 	 * If the structure sizes dont agree, I will not copy.
1034 	 * This could be due to an addition/deletion or a problem with the disk file.
1035 	 */
1036 
1037 	if (shmem_old) {
1038 		if (shmem_old_size == shmem_length) {
1039 			for (cp=buf+4, cp1=shmem_old+4; (n = 256*(*(cp-3)) + *(cp-2));	cp+=(n+3), cp1+=(n+3)) {
1040 				n1 = 256*(*(cp1-3)) + *(cp1-2);
1041 				if (n == 0 || n1 != n || strncmp((char *) cp, (char *) cp1, 4))
1042 					break;
1043 
1044 				memcpy(cp, cp1, (size_t) n);
1045 			}
1046 		}
1047 		free(shmem_old);
1048 	}
1049 
1050 	i = write(instance->shmemfd, buf, shmem_length);
1051 	free(buf);
1052 
1053 	if (i != shmem_length) {
1054 		oncore_log(instance, LOG_ERR, "ONCORE: error writing shmem");
1055 		close(instance->shmemfd);
1056 		return;
1057 	}
1058 
1059 	instance->shmem = (u_char *) mmap(0, shmem_length,
1060 		PROT_READ | PROT_WRITE,
1061 #ifdef MAP_HASSEMAPHORE
1062 		MAP_HASSEMAPHORE |
1063 #endif
1064 		MAP_SHARED, instance->shmemfd, (off_t)0);
1065 
1066 	if (instance->shmem == (u_char *)MAP_FAILED) {
1067 		instance->shmem = 0;
1068 		close(instance->shmemfd);
1069 		return;
1070 	}
1071 
1072 	oncore_log_f(instance, LOG_NOTICE,
1073 		     "SHMEM (size = %ld) is CONFIGURED and available as %s",
1074 		     (u_long) shmem_length, instance->shmem_fname);
1075 }
1076 #endif /* ONCORE_SHMEM_STATUS */
1077 
1078 
1079 
1080 /*
1081  * Read Input file if it exists.
1082  */
1083 
1084 static void
1085 oncore_read_config(
1086 	struct instance *instance
1087 	)
1088 {
1089 /*
1090  * First we try to open the configuration file
1091  *    /etc/ntp.oncore.N
1092  * where N is the unit number viz 127.127.30.N.
1093  * If we don't find it we try
1094  *    /etc/ntp.oncoreN
1095  * and then
1096  *    /etc/ntp.oncore
1097  *
1098  * If we don't find any then we don't have the cable delay or PPS offset
1099  * and we choose MODE (4) below.
1100  *
1101  * Five Choices for MODE
1102  *    (0) ONCORE is preinitialized, don't do anything to change it.
1103  *	    nb, DON'T set 0D mode, DON'T set Delay, position...
1104  *    (1) NO RESET, Read Position, delays from data file, lock it in, go to 0D mode.
1105  *    (2) NO RESET, Read Delays from data file, do SITE SURVEY to get position,
1106  *		    lock this in, go to 0D mode.
1107  *    (3) HARD RESET, Read Position, delays from data file, lock it in, go to 0D mode.
1108  *    (4) HARD RESET, Read Delays from data file, do SITE SURVEY to get position,
1109  *		    lock this in, go to 0D mode.
1110  *     NB. If a POSITION is specified in the config file with mode=(2,4) [SITE SURVEY]
1111  *	   then this position is set as the INITIAL position of the ONCORE.
1112  *	   This can reduce the time to first fix.
1113  * -------------------------------------------------------------------------------
1114  * Note that an Oncore UT without a battery backup retains NO information if it is
1115  *   power cycled, with a Battery Backup it remembers the almanac, etc.
1116  * For an Oncore VP, there is an eeprom that will contain this data, along with the
1117  *   option of Battery Backup.
1118  * So a UT without Battery Backup is equivalent to doing a HARD RESET on each
1119  *   power cycle, since there is nowhere to store the data.
1120  * -------------------------------------------------------------------------------
1121  *
1122  * If we open one or the other of the files, we read it looking for
1123  *   MODE, LAT, LON, (HT, HTGPS, HTMSL), DELAY, OFFSET, ASSERT, CLEAR, HARDPPS,
1124  *   STATUS, POSN3D, POSN2D, CHAN, TRAIM
1125  * then initialize using method MODE.  For Mode = (1,3) all of (LAT, LON, HT) must
1126  *   be present or mode reverts to (2,4).
1127  *
1128  * Read input file.
1129  *
1130  *	# is comment to end of line
1131  *	= allowed between 1st and 2nd fields.
1132  *
1133  *	Expect to see one line with 'MODE' as first field, followed by an integer
1134  *	   in the range 0-4 (default = 4).
1135  *
1136  *	Expect to see two lines with 'LONG', 'LAT' followed by 1-3 fields.
1137  *	All numbers are floating point.
1138  *		DDD.ddd
1139  *		DDD  MMM.mmm
1140  *		DDD  MMM  SSS.sss
1141  *
1142  *	Expect to see one line with 'HT' as first field,
1143  *	   followed by 1-2 fields.  First is a number, the second is 'FT' or 'M'
1144  *	   for feet or meters.	HT is the height above the GPS ellipsoid.
1145  *	   If the receiver reports height in both GPS and MSL, then we will report
1146  *	   the difference GPS-MSL on the clockstats file.
1147  *
1148  *	There is an optional line, starting with DELAY, followed
1149  *	   by 1 or two fields.	The first is a number (a time) the second is
1150  *	   'MS', 'US' or 'NS' for miliseconds, microseconds or nanoseconds.
1151  *	    DELAY  is cable delay, typically a few tens of ns.
1152  *
1153  *	There is an optional line, starting with OFFSET, followed
1154  *	   by 1 or two fields.	The first is a number (a time) the second is
1155  *	   'MS', 'US' or 'NS' for miliseconds, microseconds or nanoseconds.
1156  *	   OFFSET is the offset of the PPS pulse from 0. (only fully implemented
1157  *		with the PPSAPI, we need to be able to tell the Kernel about this
1158  *		offset if the Kernel PLL is in use, but can only do this presently
1159  *		when using the PPSAPI interface.  If not using the Kernel PLL,
1160  *		then there is no problem.
1161  *
1162  *	There is an optional line, with either ASSERT or CLEAR on it, which
1163  *	   determine which transition of the PPS signal is used for timing by the
1164  *	   PPSAPI.  If neither is present, then ASSERT is assumed.
1165  *	   ASSERT/CLEAR can also be set with FLAG2 of the ntp.conf input.
1166  *	   For Flag2, ASSERT=0, and hence is default.
1167  *
1168  *	There is an optional line, with HARDPPS on it.	Including this line causes
1169  *	     the PPS signal to control the kernel PLL.
1170  *	   HARDPPS can also be set with FLAG3 of the ntp.conf input.
1171  *	   For Flag3, 0 is disabled, and the default.
1172  *
1173  *	There are three options that have to do with using the shared memory option.
1174  *	   First, to enable the option there must be a SHMEM line with a file name.
1175  *	   The file name is the file associated with the shared memory.
1176  *
1177  *	In shared memory, there is one 'record' for each returned variable.
1178  *	For the @@Ea data there are three 'records' containing position data.
1179  *	   There will always be data in the record corresponding to the '0D' @@Ea record,
1180  *	   and the user has a choice of filling the '3D' record by specifying POSN3D,
1181  *	   or the '2D' record by specifying POSN2D.  In either case the '2D' or '3D'
1182  *	   record is filled once every 15s.
1183  *
1184  *	Two additional variables that can be set are CHAN and TRAIM.  These should be
1185  *	   set correctly by the code examining the @@Cj record, but we bring them out here
1186  *	   to allow the user to override either the # of channels, or the existence of TRAIM.
1187  *	   CHAN expects to be followed by in integer: 6, 8, or 12. TRAIM expects to be
1188  *	   followed by YES or NO.
1189  *
1190  *	There is an optional line with MASK on it followed by one integer field in the
1191  *	   range 0 to 89. This sets the satellite mask angle and will determine the minimum
1192  *	   elevation angle for satellites to be tracked by the receiver. The default value
1193  *	   is 10 deg for the VP and 0 deg for all other receivers.
1194  *
1195  *	There is an optional line with PPSCONTROL on it (only valid for M12 or M12+T
1196  *	   receivers, the option is read, but ignored for all others)
1197  *	   and it is followed by:
1198  *		ON	   Turn PPS on.  This is the default and the default for other
1199  *			       oncore receivers.  The PPS is on even if not tracking
1200  *			       any satellites.
1201  *		SATELLITE  Turns PPS on if tracking at least 1 satellite, else off.
1202  *		TRAIM	   Turns PPS on or off controlled by TRAIM.
1203  *	  The OFF option is NOT implemented, since the Oncore driver will not work
1204  *	     without the PPS signal.
1205  *
1206  * So acceptable input would be
1207  *	# these are my coordinates (RWC)
1208  *	LON  -106 34.610
1209  *	LAT    35 08.999
1210  *	HT	1589	# could equally well say HT 5215 FT
1211  *	DELAY  60 ns
1212  */
1213 
1214 	FILE	*fd;
1215 	char	*cc, *ca, line[100], units[2], device[64];
1216 	const char	*dirs[] = { "/etc/ntp", "/etc", 0 };
1217 	const char *cp, **cpp;
1218 	int	i, sign, lat_flg, long_flg, ht_flg, mode, mask;
1219 	double	f1, f2, f3;
1220 
1221 	fd = NULL;	/* just to shutup gcc complaint */
1222 	for (cpp=dirs; *cpp; cpp++) {
1223 		cp = *cpp;
1224 		snprintf(device, sizeof(device), "%s/ntp.oncore.%d",
1225 			 cp, instance->unit);  /* try "ntp.oncore.0 */
1226 		if ((fd=fopen(device, "r")))
1227 			break;
1228 		snprintf(device, sizeof(device), "%s/ntp.oncore%d",
1229 			 cp, instance->unit);  /* try "ntp.oncore0" */
1230 		if ((fd=fopen(device, "r")))
1231 			break;
1232 		snprintf(device, sizeof(device), "%s/ntp.oncore", cp);
1233 		if ((fd=fopen(device, "r")))   /* last try "ntp.oncore" */
1234 			break;
1235 	}
1236 
1237 	if (!fd) {	/* no inputfile, default to the works ... */
1238 		instance->init_type = 4;
1239 		return;
1240 	}
1241 
1242 	mode = mask = 0;
1243 	lat_flg = long_flg = ht_flg = 0;
1244 	while (fgets(line, 100, fd)) {
1245 		char *cpw;
1246 
1247 		/* Remove comments */
1248 		if ((cpw = strchr(line, '#')))
1249 			*cpw = '\0';
1250 
1251 		/* Remove trailing space */
1252 		for (i = strlen(line);
1253 		     i > 0 && isascii((unsigned char)line[i - 1]) && isspace((unsigned char)line[i - 1]);
1254 			)
1255 			line[--i] = '\0';
1256 
1257 		/* Remove leading space */
1258 		for (cc = line; *cc && isascii((unsigned char)*cc) && isspace((unsigned char)*cc); cc++)
1259 			continue;
1260 
1261 		/* Stop if nothing left */
1262 		if (!*cc)
1263 			continue;
1264 
1265 		/* Uppercase the command and find the arg */
1266 		for (ca = cc; *ca; ca++) {
1267 			if (isascii((unsigned char)*ca)) {
1268 				if (islower((unsigned char)*ca)) {
1269 					*ca = toupper((unsigned char)*ca);
1270 				} else if (isspace((unsigned char)*ca) || (*ca == '='))
1271 					break;
1272 			}
1273 		}
1274 
1275 		/* Remove space (and possible =) leading the arg */
1276 		for (; *ca && isascii((unsigned char)*ca) && (isspace((unsigned char)*ca) || (*ca == '=')); ca++)
1277 			continue;
1278 
1279 		if (!strncmp(cc, "STATUS", (size_t) 6) || !strncmp(cc, "SHMEM", (size_t) 5)) {
1280 			instance->shmem_fname = estrdup(ca);
1281 			continue;
1282 		}
1283 
1284 		/* Uppercase argument as well */
1285 		for (cpw = ca; *cpw; cpw++)
1286 			if (isascii((unsigned char)*cpw) && islower((unsigned char)*cpw))
1287 				*cpw = toupper((unsigned char)*cpw);
1288 
1289 		if (!strncmp(cc, "LAT", (size_t) 3)) {
1290 			f1 = f2 = f3 = 0;
1291 			sscanf(ca, "%lf %lf %lf", &f1, &f2, &f3);
1292 			sign = 1;
1293 			if (f1 < 0) {
1294 				f1 = -f1;
1295 				sign = -1;
1296 			}
1297 			instance->ss_lat = sign*1000*(fabs(f3) + 60*(fabs(f2) + 60*f1)); /*miliseconds*/
1298 			lat_flg++;
1299 		} else if (!strncmp(cc, "LON", (size_t) 3)) {
1300 			f1 = f2 = f3 = 0;
1301 			sscanf(ca, "%lf %lf %lf", &f1, &f2, &f3);
1302 			sign = 1;
1303 			if (f1 < 0) {
1304 				f1 = -f1;
1305 				sign = -1;
1306 			}
1307 			instance->ss_long = sign*1000*(fabs(f3) + 60*(fabs(f2) + 60*f1)); /*miliseconds*/
1308 			long_flg++;
1309 		} else if (!strncmp(cc, "HT", (size_t) 2)) {
1310 			f1 = 0;
1311 			units[0] = '\0';
1312 			sscanf(ca, "%lf %1s", &f1, units);
1313 			if (units[0] == 'F')
1314 				f1 = 0.3048 * f1;
1315 			instance->ss_ht = 100 * f1;    /* cm */
1316 			ht_flg++;
1317 		} else if (!strncmp(cc, "DELAY", (size_t) 5)) {
1318 			f1 = 0;
1319 			units[0] = '\0';
1320 			sscanf(ca, "%lf %1s", &f1, units);
1321 			if (units[0] == 'N')
1322 				;
1323 			else if (units[0] == 'U')
1324 				f1 = 1000 * f1;
1325 			else if (units[0] == 'M')
1326 				f1 = 1000000 * f1;
1327 			else
1328 				f1 = 1000000000 * f1;
1329 			if (f1 < 0 || f1 > 1.e9)
1330 				f1 = 0;
1331 			if (f1 < 0 || f1 > 999999)
1332 				oncore_log_f(instance, LOG_WARNING,
1333 					     "PPS Cable delay of %fns out of Range, ignored",
1334 					     f1);
1335 			else
1336 				instance->delay = f1;		/* delay in ns */
1337 		} else if (!strncmp(cc, "OFFSET", (size_t) 6)) {
1338 			f1 = 0;
1339 			units[0] = '\0';
1340 			sscanf(ca, "%lf %1s", &f1, units);
1341 			if (units[0] == 'N')
1342 				;
1343 			else if (units[0] == 'U')
1344 				f1 = 1000 * f1;
1345 			else if (units[0] == 'M')
1346 				f1 = 1000000 * f1;
1347 			else
1348 				f1 = 1000000000 * f1;
1349 			if (f1 < 0 || f1 > 1.e9)
1350 				f1 = 0;
1351 			if (f1 < 0 || f1 > 999999999.)
1352 				oncore_log_f(instance, LOG_WARNING,
1353 					     "PPS Offset of %fns out of Range, ignored",
1354 					     f1);
1355 			else
1356 				instance->offset = f1;		/* offset in ns */
1357 		} else if (!strncmp(cc, "MODE", (size_t) 4)) {
1358 			sscanf(ca, "%d", &mode);
1359 			if (mode < 0 || mode > 4)
1360 				mode = 4;
1361 		} else if (!strncmp(cc, "ASSERT", (size_t) 6)) {
1362 			instance->assert = 1;
1363 		} else if (!strncmp(cc, "CLEAR", (size_t) 5)) {
1364 			instance->assert = 0;
1365 		} else if (!strncmp(cc, "HARDPPS", (size_t) 7)) {
1366 			instance->hardpps = 1;
1367 		} else if (!strncmp(cc, "POSN2D", (size_t) 6)) {
1368 			instance->shmem_Posn = 2;
1369 		} else if (!strncmp(cc, "POSN3D", (size_t) 6)) {
1370 			instance->shmem_Posn = 3;
1371 		} else if (!strncmp(cc, "CHAN", (size_t) 4)) {
1372 			sscanf(ca, "%d", &i);
1373 			if ((i == 6) || (i == 8) || (i == 12))
1374 				instance->chan_in = i;
1375 		} else if (!strncmp(cc, "TRAIM", (size_t) 5)) {
1376 			instance->traim_in = 1; 	/* so TRAIM alone is YES */
1377 			if (!strcmp(ca, "NO") || !strcmp(ca, "OFF"))    /* Yes/No, On/Off */
1378 				instance->traim_in = 0;
1379 		} else if (!strncmp(cc, "MASK", (size_t) 4)) {
1380 			sscanf(ca, "%d", &mask);
1381 			if (mask > -1 && mask < 90)
1382 				instance->Ag = mask;			/* Satellite mask angle */
1383 		} else if (!strncmp(cc,"PPSCONTROL",10)) {              /* pps control M12 only */
1384 			if (!strcmp(ca,"ON") || !strcmp(ca, "CONTINUOUS")) {
1385 				instance->pps_control = 1;		/* PPS always on */
1386 			} else if (!strcmp(ca,"SATELLITE")) {
1387 				instance->pps_control = 2;		/* PPS on when satellite is available */
1388 			} else if (!strcmp(ca,"TRAIM")) {
1389 				instance->pps_control = 3;		/* PPS on when TRAIM status is OK */
1390 			} else {
1391 				oncore_log_f(instance, LOG_WARNING,
1392 				             "Unknown value \"%s\" for PPSCONTROL, ignored",
1393 					     cc);
1394 			}
1395 		}
1396 	}
1397 	fclose(fd);
1398 
1399 	/*
1400 	 *    OK, have read all of data file, and extracted the good stuff.
1401 	 *    If lat/long/ht specified they ALL must be specified for mode = (1,3).
1402 	 */
1403 
1404 	instance->posn_set = 1;
1405 	if (!( lat_flg && long_flg && ht_flg )) {
1406 		oncore_log_f(instance, LOG_WARNING,
1407 			     "ONCORE: incomplete data on %s", device);
1408 		instance->posn_set = 0;
1409 		if (mode == 1 || mode == 3) {
1410 			oncore_log_f(instance, LOG_WARNING,
1411 				     "Input Mode = %d, but no/incomplete position, mode set to %d",
1412 				     mode, mode+1);
1413 			mode++;
1414 		}
1415 	}
1416 	instance->init_type = mode;
1417 
1418 	oncore_log_f(instance, LOG_INFO, "Input mode = %d", mode);
1419 }
1420 
1421 
1422 
1423 /*
1424  * move data from NTP to buffer (toss the extra in the unlikely case it won't fit)
1425  */
1426 
1427 static void
1428 oncore_receive(
1429 	struct recvbuf *rbufp
1430 	)
1431 {
1432 	size_t i;
1433 	u_char *p;
1434 	struct peer *peer;
1435 	struct instance *instance;
1436 
1437 	peer = rbufp->recv_peer;
1438 	instance = peer->procptr->unitptr;
1439 	p = (u_char *) &rbufp->recv_space;
1440 
1441 #ifdef ONCORE_VERBOSE_RECEIVE
1442 	if (debug > 4) {
1443 		int i;
1444 		char	Msg[120], Msg2[10];
1445 
1446 		oncore_log_f(instance, LOG_DEBUG,
1447 			     ">>> %d bytes available",
1448 			     rbufp->recv_length);
1449 		strlcpy(Msg, ">>>", sizeof(Msg));
1450 		for (i = 0; i < rbufp->recv_length; i++) {
1451 			snprintf(Msg2, sizeof(Msg2), "%02x ", p[i]);
1452 			strlcat(Msg, Msg2, sizeof(Msg));
1453 		}
1454 		oncore_log(instance, LOG_DEBUG, Msg);
1455 
1456 		strlcpy(Msg, ">>>", sizeof(Msg));
1457 		for (i = 0; i < rbufp->recv_length; i++) {
1458 			snprintf(Msg2, sizeof(Msg2), "%03o ", p[i]);
1459 			strlcat(Msg, Msg2, sizeof(Msg));
1460 		}
1461 		oncore_log(instance, LOG_DEBUG, Msg);
1462 	}
1463 #endif
1464 
1465 	i = rbufp->recv_length;
1466 	if ((size_t)rcvptr + i >= sizeof(rcvbuf))
1467 		i = sizeof(rcvbuf) - rcvptr;	/* and some char will be lost */
1468 	memcpy(rcvbuf+rcvptr, p, i);
1469 	rcvptr += i;
1470 	oncore_consume(instance);
1471 }
1472 
1473 
1474 
1475 /*
1476  * Deal with any complete messages
1477  */
1478 
1479 static void
1480 oncore_consume(
1481 	struct instance *instance
1482 	)
1483 {
1484 	unsigned i, m, l;
1485 
1486 	while (rcvptr >= 7) {
1487 		if (rcvbuf[0] != '@' || rcvbuf[1] != '@') {
1488 			/* We're not in sync, lets try to get there */
1489 			for (i=1; i < rcvptr-1; i++)
1490 				if (rcvbuf[i] == '@' && rcvbuf[i+1] == '@')
1491 					break;
1492 #ifdef ONCORE_VERBOSE_CONSUME
1493 			if (debug > 4)
1494 				oncore_log_f(instance, LOG_DEBUG,
1495 					     ">>> skipping %d chars",
1496 					     i);
1497 #endif
1498 			if (i != rcvptr)
1499 				memcpy(rcvbuf, rcvbuf+i, (size_t)(rcvptr-i));
1500 			rcvptr -= i;
1501 			continue;
1502 		}
1503 
1504 		/* Ok, we have a header now */
1505 		l = sizeof(oncore_messages)/sizeof(oncore_messages[0]) -1;
1506 		for(m=0; m<l; m++)
1507 			if (!strncmp(oncore_messages[m].flag, (char *)(rcvbuf+2), (size_t) 2))
1508 				break;
1509 		if (m == l) {
1510 #ifdef ONCORE_VERBOSE_CONSUME
1511 			if (debug > 4)
1512 				oncore_log_f(instance, LOG_DEBUG,
1513 					     ">>> Unknown MSG, skipping 4 (%c%c)",
1514 					     rcvbuf[2], rcvbuf[3]);
1515 #endif
1516 			memcpy(rcvbuf, rcvbuf+4, (size_t) 4);
1517 			rcvptr -= 4;
1518 			continue;
1519 		}
1520 
1521 		l = oncore_messages[m].len;
1522 #ifdef ONCORE_VERBOSE_CONSUME
1523 		if (debug > 3)
1524 			oncore_log_f(instance, LOG_DEBUG,
1525 				     "GOT: %c%c  %d of %d entry %d",
1526 				     instance->unit, rcvbuf[2],
1527 				     rcvbuf[3], rcvptr, l, m);
1528 #endif
1529 		/* Got the entire message ? */
1530 
1531 		if (rcvptr < l)
1532 			return;
1533 
1534 		/* are we at the end of message? should be <Cksum><CR><LF> */
1535 
1536 		if (rcvbuf[l-2] != '\r' || rcvbuf[l-1] != '\n') {
1537 #ifdef ONCORE_VERBOSE_CONSUME
1538 			if (debug)
1539 				oncore_log(instance, LOG_DEBUG, "NO <CR><LF> at end of message");
1540 #endif
1541 		} else {	/* check the CheckSum */
1542 			if (oncore_checksum_ok(rcvbuf, l)) {
1543 				if (instance->shmem != NULL) {
1544 					instance->shmem[oncore_messages[m].shmem + 2]++;
1545 					memcpy(instance->shmem + oncore_messages[m].shmem + 3,
1546 					    rcvbuf, (size_t) l);
1547 				}
1548 				oncore_msg_any(instance, rcvbuf, (size_t) (l-3), m);
1549 				if (oncore_messages[m].handler)
1550 					oncore_messages[m].handler(instance, rcvbuf, (size_t) (l-3));
1551 			}
1552 #ifdef ONCORE_VERBOSE_CONSUME
1553 			else if (debug) {
1554 				char	Msg[120], Msg2[10];
1555 
1556 				oncore_log(instance, LOG_ERR, "Checksum mismatch!");
1557 				snprintf(Msg, sizeof(Msg), "@@%c%c ", rcvbuf[2], rcvbuf[3]);
1558 				for (i = 4; i < l; i++) {
1559 					snprintf(Msg2, sizeof(Msg2),
1560 						 "%03o ", rcvbuf[i]);
1561 					strlcat(Msg, Msg2, sizeof(Msg));
1562 				}
1563 				oncore_log(instance, LOG_DEBUG, Msg);
1564 			}
1565 #endif
1566 		}
1567 
1568 		if (l != rcvptr)
1569 			memcpy(rcvbuf, rcvbuf+l, (size_t) (rcvptr-l));
1570 		rcvptr -= l;
1571 	}
1572 }
1573 
1574 
1575 
1576 static void
1577 oncore_get_timestamp(
1578 	struct instance *instance,
1579 	long dt1,	/* tick offset THIS time step */
1580 	long dt2	/* tick offset NEXT time step */
1581 	)
1582 {
1583 	int	Rsm;
1584 	u_long	j;
1585 	l_fp ts, ts_tmp;
1586 	double dmy;
1587 #ifdef HAVE_STRUCT_TIMESPEC
1588 	struct timespec *tsp = 0;
1589 #else
1590 	struct timeval	*tsp = 0;
1591 #endif
1592 	int	current_mode;
1593 	pps_params_t current_params;
1594 	struct timespec timeout;
1595 	struct peer *peer;
1596 	pps_info_t pps_i;
1597 	char Msg[160];
1598 
1599 	peer = instance->peer;
1600 
1601 #if 1
1602 	/* If we are in SiteSurvey mode, then we are in 3D mode, and we fall thru.
1603 	 * If we have Finished the SiteSurvey, then we fall thru for the 14/15
1604 	 *  times we get here in 0D mode (the 1/15 is in 3D for SHMEM).
1605 	 * This gives good time, which gets better when the SS is done.
1606 	 */
1607 
1608 	if ((instance->site_survey == ONCORE_SS_DONE) && (instance->mode != MODE_0D)) {
1609 #else
1610 	/* old check, only fall thru for SS_DONE and 0D mode, 2h45m wait for ticks */
1611 
1612 	if ((instance->site_survey != ONCORE_SS_DONE) || (instance->mode != MODE_0D)) {
1613 #endif
1614 		peer->flags &= ~FLAG_PPS;	/* problem - clear PPS FLAG */
1615 		return;
1616 	}
1617 
1618 	/* Don't do anything without an almanac to define the GPS->UTC delta */
1619 
1620 	if (instance->rsm.bad_almanac) {
1621 		peer->flags &= ~FLAG_PPS;	/* problem - clear PPS FLAG */
1622 		return;
1623 	}
1624 
1625 	/* Once the Almanac is valid, the M12+T does not produce valid UTC
1626 	 * immediately.
1627 	 * Wait for UTC offset decode valid, then wait one message more
1628 	 * so we are not off by 13 seconds after  reset.
1629 	 */
1630 
1631 	if (instance->count5) {
1632 		instance->count5--;
1633 		peer->flags &= ~FLAG_PPS;	/* problem - clear PPS FLAG */
1634 		return;
1635 	}
1636 
1637 	j = instance->ev_serial;
1638 	timeout.tv_sec = 0;
1639 	timeout.tv_nsec = 0;
1640 	if (time_pps_fetch(instance->pps_h, PPS_TSFMT_TSPEC, &pps_i,
1641 	    &timeout) < 0) {
1642 		oncore_log_f(instance, LOG_ERR,
1643 			     "time_pps_fetch failed %m");
1644 		peer->flags &= ~FLAG_PPS;	/* problem - clear PPS FLAG */
1645 		return;
1646 	}
1647 
1648 	if (instance->assert) {
1649 		tsp = &pps_i.assert_timestamp;
1650 
1651 #ifdef ONCORE_VERBOSE_GET_TIMESTAMP
1652 		if (debug > 2) {
1653 			u_long i;
1654 
1655 			i = (u_long) pps_i.assert_sequence;
1656 # ifdef HAVE_STRUCT_TIMESPEC
1657 			oncore_log_f(instance, LOG_DEBUG,
1658 				     "serial/j (%lu, %lu) %ld.%09ld", i,
1659 				     j, (long)tsp->tv_sec,
1660 				     (long)tsp->tv_nsec);
1661 # else
1662 			oncore_log_f(instance, LOG_DEBUG,
1663 				     "serial/j (%lu, %lu) %ld.%06ld", i,
1664 				     j, (long)tsp->tv_sec,
1665 				     (long)tsp->tv_usec);
1666 # endif
1667 		}
1668 #endif
1669 
1670 		if (pps_i.assert_sequence == j) {
1671 			oncore_log(instance, LOG_NOTICE, "ONCORE: oncore_get_timestamp, error serial pps");
1672 			peer->flags &= ~FLAG_PPS;	/* problem - clear PPS FLAG */
1673 			return;
1674 		}
1675 
1676 		instance->ev_serial = pps_i.assert_sequence;
1677 	} else {
1678 		tsp = &pps_i.clear_timestamp;
1679 
1680 #if 0
1681 		if (debug > 2) {
1682 			u_long i;
1683 
1684 			i = (u_long) pps_i.clear_sequence;
1685 # ifdef HAVE_STRUCT_TIMESPEC
1686 			oncore_log_f(instance, LOG_DEBUG,
1687 				     "serial/j (%lu, %lu) %ld.%09ld", i,
1688 				     j, (long)tsp->tv_sec,
1689 				     (long)tsp->tv_nsec);
1690 # else
1691 			oncore_log_f(instance, LOG_DEBUG,
1692 				     "serial/j (%lu, %lu) %ld.%06ld", i,
1693 				     j, (long)tsp->tv_sec,
1694 				     (long)tsp->tv_usec);
1695 # endif
1696 		}
1697 #endif
1698 
1699 		if (pps_i.clear_sequence == j) {
1700 			oncore_log(instance, LOG_ERR, "oncore_get_timestamp, error serial pps");
1701 			peer->flags &= ~FLAG_PPS;	/* problem - clear PPS FLAG */
1702 			return;
1703 		}
1704 		instance->ev_serial = pps_i.clear_sequence;
1705 	}
1706 
1707 	/* convert timespec -> ntp l_fp */
1708 
1709 	dmy = tsp->tv_nsec;
1710 	dmy /= 1e9;
1711 	ts.l_uf = dmy * 4294967296.0;
1712 	ts.l_ui = tsp->tv_sec;
1713 
1714 #if 0
1715      alternate code for previous 4 lines is
1716 	dmy = 1.0e-9*tsp->tv_nsec;	/* fractional part */
1717 	DTOLFP(dmy, &ts);
1718 	dmy = tsp->tv_sec;		/* integer part */
1719 	DTOLFP(dmy, &ts_tmp);
1720 	L_ADD(&ts, &ts_tmp);
1721      or more simply
1722 	dmy = 1.0e-9*tsp->tv_nsec;	/* fractional part */
1723 	DTOLFP(dmy, &ts);
1724 	ts.l_ui = tsp->tv_sec;
1725 #endif	/* 0 */
1726 
1727 	/* now have timestamp in ts */
1728 	/* add in saw_tooth and offset, these will be ZERO if no TRAIM */
1729 	/* they will be IGNORED if the PPSAPI cant do PPS_OFFSET/ASSERT/CLEAR */
1730 	/* we just try to add them in and dont test for that here */
1731 
1732 	/* saw_tooth not really necessary if using TIMEVAL */
1733 	/* since its only precise to us, but do it anyway. */
1734 
1735 	/* offset in ns, and is positive (late), we subtract */
1736 	/* to put the PPS time transition back where it belongs */
1737 
1738 	/* must hand the offset for the NEXT sec off to the Kernel to do */
1739 	/* the addition, so that the Kernel PLL sees the offset too */
1740 
1741 	if (instance->assert)
1742 		instance->pps_p.assert_offset.tv_nsec = -dt2;
1743 	else
1744 		instance->pps_p.clear_offset.tv_nsec  = -dt2;
1745 
1746 	/* The following code is necessary, and not just a time_pps_setparams,
1747 	 * using the saved instance->pps_p, since some other process on the
1748 	 * machine may have diddled with the mode bits (say adding something
1749 	 * that it needs).  We take what is there and ADD what we need.
1750 	 * [[ The results from the time_pps_getcap is unlikely to change so
1751 	 *    we could probably just save it, but I choose to do the call ]]
1752 	 * Unfortunately, there is only ONE set of mode bits in the kernel per
1753 	 * interface, and not one set for each open handle.
1754 	 *
1755 	 * There is still a race condition here where we might mess up someone
1756 	 * elses mode, but if he is being careful too, he should survive.
1757 	 */
1758 
1759 	if (time_pps_getcap(instance->pps_h, &current_mode) < 0) {
1760 		oncore_log_f(instance, LOG_ERR,
1761 			     "time_pps_getcap failed: %m");
1762 		peer->flags &= ~FLAG_PPS;	/* problem - clear PPS FLAG */
1763 		return;
1764 	}
1765 
1766 	if (time_pps_getparams(instance->pps_h, &current_params) < 0) {
1767 		oncore_log_f(instance, LOG_ERR,
1768 			     "time_pps_getparams failed: %m");
1769 		peer->flags &= ~FLAG_PPS;	/* problem - clear PPS FLAG */
1770 		return;
1771 	}
1772 
1773 		/* or current and mine */
1774 	current_params.mode |= instance->pps_p.mode;
1775 		/* but only set whats legal */
1776 	current_params.mode &= current_mode;
1777 
1778 	current_params.assert_offset.tv_sec = 0;
1779 	current_params.assert_offset.tv_nsec = -dt2;
1780 	current_params.clear_offset.tv_sec = 0;
1781 	current_params.clear_offset.tv_nsec = -dt2;
1782 
1783 	if (time_pps_setparams(instance->pps_h, &current_params))
1784 		oncore_log(instance, LOG_ERR, "ONCORE: Error doing time_pps_setparams");
1785 
1786 	/* have time from UNIX origin, convert to NTP origin. */
1787 
1788 	ts.l_ui += JAN_1970;
1789 	instance->pp->lastrec = ts;
1790 
1791 	/* print out information about this timestamp (long line) */
1792 
1793 	ts_tmp = ts;
1794 	ts_tmp.l_ui = 0;	/* zero integer part */
1795 	LFPTOD(&ts_tmp, dmy);	/* convert fractional part to a double */
1796 	j = 1.0e9*dmy;		/* then to integer ns */
1797 
1798 	Rsm = 0;
1799 	if (instance->chan == 6)
1800 		Rsm = instance->BEHa[64];
1801 	else if (instance->chan == 8)
1802 		Rsm = instance->BEHa[72];
1803 	else if (instance->chan == 12)
1804 		Rsm = ((instance->BEHa[129]<<8) | instance->BEHa[130]);
1805 
1806 	if (instance->chan == 6 || instance->chan == 8) {
1807 		char	f1[5], f2[5], f3[5], f4[5];
1808 		if (instance->traim) {
1809 			snprintf(f1, sizeof(f1), "%d",
1810 				 instance->BEHn[21]);
1811 			snprintf(f2, sizeof(f2), "%d",
1812 				 instance->BEHn[22]);
1813 			snprintf(f3, sizeof(f3), "%2d",
1814 				 instance->BEHn[23] * 256 +
1815 				     instance->BEHn[24]);
1816 			snprintf(f4, sizeof(f4), "%3d",
1817 				 (s_char)instance->BEHn[25]);
1818 		} else {
1819 			strlcpy(f1, "x", sizeof(f1));
1820 			strlcpy(f2, "x", sizeof(f2));
1821 			strlcpy(f3, "xx", sizeof(f3));
1822 			strlcpy(f4, "xxx", sizeof(f4));
1823 		}
1824 		snprintf(Msg, sizeof(Msg),	/* MAX length 128, currently at 127 */
1825  "%u.%09lu %d %d %2d %2d %2d %2ld rstat   %02x dop %4.1f nsat %2d,%d traim %d,%s,%s sigma %s neg-sawtooth %s sat %d%d%d%d%d%d%d%d",
1826 		    ts.l_ui, j,
1827 		    instance->pp->year, instance->pp->day,
1828 		    instance->pp->hour, instance->pp->minute, instance->pp->second,
1829 		    (long) tsp->tv_sec % 60,
1830 		    Rsm, 0.1*(256*instance->BEHa[35]+instance->BEHa[36]),
1831 		    /*rsat	dop */
1832 		    instance->BEHa[38], instance->BEHa[39], instance->traim, f1, f2,
1833 		    /*	nsat visible,	  nsat tracked,     traim,traim,traim */
1834 		    f3, f4,
1835 		    /* sigma neg-sawtooth */
1836 	  /*sat*/   instance->BEHa[41], instance->BEHa[45], instance->BEHa[49], instance->BEHa[53],
1837 		    instance->BEHa[57], instance->BEHa[61], instance->BEHa[65], instance->BEHa[69]
1838 		    );					/* will be 0 for 6 chan */
1839 	} else if (instance->chan == 12) {
1840 		char	f1[5], f2[5], f3[5], f4[5];
1841 		if (instance->traim) {
1842 			snprintf(f1, sizeof(f1), "%d",
1843 				 instance->BEHn[6]);
1844 			snprintf(f2, sizeof(f2), "%d",
1845 				 instance->BEHn[7]);
1846 			snprintf(f3, sizeof(f3), "%d",
1847 				 instance->BEHn[12] * 256 +
1848 				     instance->BEHn[13]);
1849 			snprintf(f4, sizeof(f4), "%3d",
1850 				 (s_char)instance->BEHn[14]);
1851 		} else {
1852 			strlcpy(f1, "x", sizeof(f1));
1853 			strlcpy(f2, "x", sizeof(f2));
1854 			strlcpy(f3, "xx", sizeof(f3));
1855 			strlcpy(f4, "xxx", sizeof(f4));
1856 		}
1857 		snprintf(Msg, sizeof(Msg),
1858  "%u.%09lu %d %d %2d %2d %2d %2ld rstat %02x dop %4.1f nsat %2d,%d traim %d,%s,%s sigma %s neg-sawtooth %s sat %d%d%d%d%d%d%d%d%d%d%d%d",
1859 		    ts.l_ui, j,
1860 		    instance->pp->year, instance->pp->day,
1861 		    instance->pp->hour, instance->pp->minute, instance->pp->second,
1862 		    (long) tsp->tv_sec % 60,
1863 		    Rsm, 0.1*(256*instance->BEHa[53]+instance->BEHa[54]),
1864 		    /*rsat	dop */
1865 		    instance->BEHa[55], instance->BEHa[56], instance->traim, f1, f2,
1866 		    /*	nsat visible,	  nsat tracked	 traim,traim,traim */
1867 		    f3, f4,
1868 		    /* sigma neg-sawtooth */
1869 	  /*sat*/   instance->BEHa[58], instance->BEHa[64], instance->BEHa[70], instance->BEHa[76],
1870 		    instance->BEHa[82], instance->BEHa[88], instance->BEHa[94], instance->BEHa[100],
1871 		    instance->BEHa[106], instance->BEHa[112], instance->BEHa[118], instance->BEHa[124]
1872 		    );
1873 	}
1874 
1875 	/* and some things I dont understand (magic ntp things) */
1876 
1877 #if 1
1878 	oncore_feed_clockproc(instance);
1879 #else
1880 	if (!refclock_process(instance->pp)) {
1881 		refclock_report(peer, CEVNT_BADTIME);
1882 		peer->flags &= ~FLAG_PPS;	/* problem - clear PPS FLAG */
1883 		return;
1884 	}
1885 #endif
1886 
1887 	oncore_log(instance, LOG_INFO, Msg);	 /* this is long message above */
1888 	instance->pollcnt = 2;
1889 
1890 	if (instance->polled) {
1891 		instance->polled = 0;
1892 	     /* instance->pp->dispersion = instance->pp->skew = 0;	*/
1893 		instance->pp->lastref = instance->pp->lastrec;
1894 		refclock_receive(instance->peer);
1895 	}
1896 	peer->flags |= FLAG_PPS;
1897 }
1898 
1899 
1900 /*************** oncore_msg_XX routines start here *******************/
1901 
1902 
1903 /*
1904  * print Oncore response message.
1905  */
1906 
1907 static void
1908 oncore_msg_any(
1909 	struct instance *instance,
1910 	u_char *buf,
1911 	size_t len,
1912 	int idx
1913 	)
1914 {
1915 #ifdef ONCORE_VERBOSE_MSG_ANY
1916 	int i;
1917 	const char *fmt = oncore_messages[idx].fmt;
1918 	const char *p;
1919 	char *q;
1920 	char *qlim;
1921 #ifdef HAVE_GETCLOCK
1922 	struct timespec ts;
1923 #endif
1924 	struct timeval tv;
1925 	char	Msg[120], Msg2[10];
1926 
1927 	if (debug > 3) {
1928 # ifdef HAVE_GETCLOCK
1929 		(void) getclock(TIMEOFDAY, &ts);
1930 		tv.tv_sec = ts.tv_sec;
1931 		tv.tv_usec = ts.tv_nsec / 1000;
1932 # else
1933 		GETTIMEOFDAY(&tv, 0);
1934 # endif
1935 		oncore_log(instance, LOG_DEBUG, "%ld.%06ld",
1936 			   (long)tv.tv_sec, (long)tv.tv_usec);
1937 
1938 		if (!*fmt) {
1939 			snprintf(Msg, sizeof(Msg), ">>@@%c%c ", buf[2],
1940 				 buf[3]);
1941 			for(i = 2; i < len && i < 2400 ; i++) {
1942 				snprintf(Msg2, sizeof(Msg2), "%02x",
1943 					 buf[i]);
1944 				strlcat(Msg, Msg2, sizeof(Msg));
1945 			}
1946 			oncore_log(instance, LOG_DEBUG, Msg);
1947 			return;
1948 		} else {
1949 			strlcpy(Msg, "##", sizeof(Msg));
1950 			qlim = Msg + sizeof(Msg) - 3;
1951 			for (p = fmt, q = Msg + 2; q < qlim && *p; ) {
1952 				*q++ = *p++;
1953 				*q++ = '_';
1954 			}
1955 			*q = '\0';
1956 			oncore_log(instance, LOG_DEBUG, Msg);
1957 			snprintf(Msg, sizeof(Msg), "%c%c", buf[2],
1958 				 buf[3]);
1959 			i = 4;
1960 			for (p = fmt; *p; p++) {
1961 				snprintf(Msg2, "%02x", buf[i++]);
1962 				strlcat(Msg, Msg2, sizeof(Msg));
1963 			}
1964 			oncore_log(instance, LOG_DEBUG, Msg);
1965 		}
1966 	}
1967 #endif
1968 }
1969 
1970 
1971 
1972 /* Latitude, Longitude, Height */
1973 
1974 static void
1975 oncore_msg_Adef(
1976 	struct instance *instance,
1977 	u_char *buf,
1978 	size_t len
1979 	)
1980 {
1981 }
1982 
1983 
1984 
1985 /* Mask Angle */
1986 
1987 static void
1988 oncore_msg_Ag(
1989 	struct instance *instance,
1990 	u_char *buf,
1991 	size_t len
1992 	)
1993 {
1994 	const char *cp;
1995 
1996 	cp = "set to";
1997 	if (instance->o_state == ONCORE_RUN)
1998 		cp = "is";
1999 
2000 	instance->Ag = buf[4];
2001 	oncore_log_f(instance, LOG_INFO,
2002 		     "Satellite mask angle %s %d degrees", cp,
2003 		     (int)instance->Ag);
2004 }
2005 
2006 
2007 
2008 /*
2009  * get Position hold position
2010  */
2011 
2012 static void
2013 oncore_msg_As(
2014 	struct instance *instance,
2015 	u_char *buf,
2016 	size_t len
2017 	)
2018 {
2019 	instance->ss_lat  = buf_w32(&buf[4]);
2020 	instance->ss_long = buf_w32(&buf[8]);
2021 	instance->ss_ht   = buf_w32(&buf[12]);
2022 
2023 	/* Print out Position */
2024 	oncore_print_posn(instance);
2025 }
2026 
2027 
2028 
2029 /*
2030  * Try to use Oncore UT+ Auto Survey Feature
2031  *	If its not there (VP), set flag to do it ourselves.
2032  */
2033 
2034 static void
2035 oncore_msg_At(
2036 	struct instance *instance,
2037 	u_char *buf,
2038 	size_t len
2039 	)
2040 {
2041 	instance->saw_At = 1;
2042 	if (instance->site_survey == ONCORE_SS_TESTING) {
2043 		if (buf[4] == 2) {
2044 			oncore_log(instance, LOG_NOTICE,
2045 					"Initiating hardware 3D site survey");
2046 
2047 			oncore_log(instance, LOG_NOTICE, "SSstate = ONCORE_SS_HW");
2048 			instance->site_survey = ONCORE_SS_HW;
2049 		}
2050 	}
2051 }
2052 
2053 
2054 
2055 /*
2056  * get PPS Offset
2057  * Nb. @@Ay is not supported for early UT (no plus) model
2058  */
2059 
2060 static void
2061 oncore_msg_Ay(
2062 	struct instance *instance,
2063 	u_char *buf,
2064 	size_t len
2065 	)
2066 {
2067 	if (instance->saw_Ay)
2068 		return;
2069 
2070 	instance->saw_Ay = 1;
2071 
2072 	instance->offset = buf_w32(&buf[4]);
2073 
2074 	oncore_log_f(instance, LOG_INFO, "PPS Offset is set to %ld ns",
2075 		     instance->offset);
2076 }
2077 
2078 
2079 
2080 /*
2081  * get Cable Delay
2082  */
2083 
2084 static void
2085 oncore_msg_Az(
2086 	struct instance *instance,
2087 	u_char *buf,
2088 	size_t len
2089 	)
2090 {
2091 	if (instance->saw_Az)
2092 		return;
2093 
2094 	instance->saw_Az = 1;
2095 
2096 	instance->delay = buf_w32(&buf[4]);
2097 
2098 	oncore_log_f(instance, LOG_INFO, "Cable delay is set to %ld ns",
2099 		     instance->delay);
2100 }
2101 
2102 
2103 
2104 /* Ba, Ea and Ha come here, these contain Position */
2105 
2106 static void
2107 oncore_msg_BaEaHa(
2108 	struct instance *instance,
2109 	u_char *buf,
2110 	size_t len
2111 	)
2112 {
2113 	const char	*cp;
2114 	int		mode;
2115 
2116 	/* OK, we are close to the RUN state now.
2117 	 * But we have a few more items to initialize first.
2118 	 *
2119 	 * At the beginning of this routine there are several 'timers'.
2120 	 * We enter this routine 1/sec, and since the upper levels of NTP have usurped
2121 	 * the use of timers, we use the 1/sec entry to do things that
2122 	 * we would normally do with timers...
2123 	 */
2124 
2125 	if (instance->o_state == ONCORE_CHECK_CHAN) {	/* here while checking for the # chan */
2126 		if (buf[2] == 'B') {		/* 6chan */
2127 			if (instance->chan_ck < 6) instance->chan_ck = 6;
2128 		} else if (buf[2] == 'E') {	/* 8chan */
2129 			if (instance->chan_ck < 8) instance->chan_ck = 8;
2130 		} else if (buf[2] == 'H') {	/* 12chan */
2131 			if (instance->chan_ck < 12) instance->chan_ck = 12;
2132 		}
2133 
2134 		if (instance->count3++ < 5)
2135 			return;
2136 
2137 		instance->count3 = 0;
2138 
2139 		if (instance->chan_in != -1)	/* set in Input */
2140 			instance->chan = instance->chan_in;
2141 		else				/* set from test */
2142 			instance->chan = instance->chan_ck;
2143 
2144 		oncore_log_f(instance, LOG_INFO, "Input   says chan = %d",
2145 			    instance->chan_in);
2146 		oncore_log_f(instance, LOG_INFO, "Model # says chan = %d",
2147 			     instance->chan_id);
2148 		oncore_log_f(instance, LOG_INFO, "Testing says chan = %d",
2149 			     instance->chan_ck);
2150 		oncore_log_f(instance, LOG_INFO, "Using        chan = %d",
2151 			     instance->chan);
2152 
2153 		instance->o_state = ONCORE_HAVE_CHAN;
2154 		oncore_log(instance, LOG_NOTICE, "state = ONCORE_HAVE_CHAN");
2155 
2156 		instance->timeout = 4;
2157 		oncore_sendmsg(instance, oncore_cmd_Cj, sizeof(oncore_cmd_Cj));
2158 		return;
2159 	}
2160 
2161 	if (instance->o_state != ONCORE_ALMANAC && instance->o_state != ONCORE_RUN)
2162 		return;
2163 
2164 	/* PAUSE 5sec - make sure results are stable, before using position */
2165 
2166 	if (instance->count) {
2167 		if (instance->count++ < 5)
2168 			return;
2169 		instance->count = 0;
2170 	}
2171 
2172 	memcpy(instance->BEHa, buf, (size_t) (len+3));	/* Ba, Ea or Ha */
2173 
2174 	/* check if we saw a response to Gc (M12 or M12+T */
2175 
2176 	if (instance->pps_control_msg_seen != -2) {
2177 		if ((instance->pps_control_msg_seen == -1) && (instance->pps_control != -1)) {
2178 			oncore_log(instance, LOG_INFO, "PPSCONTROL set, but not implemented (not M12)");
2179 		}
2180 		instance->pps_control_msg_seen = -2;
2181 	}
2182 
2183 	/* check the antenna (did it get unplugged) and almanac (is it ready) for changes. */
2184 
2185 	oncore_check_almanac(instance);
2186 	oncore_check_antenna(instance);
2187 
2188 	/* If we are in Almanac mode, waiting for Almanac, we can't do anything till we have it */
2189 	/* When we have an almanac, we will start the Bn/En/@@Hn messages */
2190 
2191 	if (instance->o_state == ONCORE_ALMANAC)
2192 		if (oncore_wait_almanac(instance))
2193 			return;
2194 
2195 	/* do some things once when we get this far in BaEaHa */
2196 
2197 	if (instance->once) {
2198 		instance->once = 0;
2199 		instance->count2 = 1;
2200 
2201 		/* Have we seen an @@At (position hold) command response */
2202 		/* if not, message out */
2203 
2204 		if (instance->chan != 12 && !instance->saw_At) {
2205 			oncore_log(instance, LOG_NOTICE,
2206 				"Not Good, no @@At command (no Position Hold), must be a GT/GT+");
2207 			oncore_sendmsg(instance, oncore_cmd_Av1, sizeof(oncore_cmd_Av1));
2208 		}
2209 
2210 		/* have an Almanac, can start the SiteSurvey
2211 		 * (actually only need to get past the almanac_load where we diddle with At
2212 		 *  command,- we can't change it after we start the HW_SS below
2213 		 */
2214 
2215 		mode = instance->init_type;
2216 		switch (mode) {
2217 		case 0: /* NO initialization, don't change anything */
2218 		case 1: /* Use given Position */
2219 		case 3:
2220 			instance->site_survey = ONCORE_SS_DONE;
2221 			oncore_log(instance, LOG_NOTICE, "SSstate = ONCORE_SS_DONE");
2222 			break;
2223 
2224 		case 2:
2225 		case 4: /* Site Survey */
2226 			oncore_log(instance, LOG_NOTICE, "SSstate = ONCORE_SS_TESTING");
2227 			instance->site_survey = ONCORE_SS_TESTING;
2228 			instance->count1 = 1;
2229 			if (instance->chan == 12)
2230 				oncore_sendmsg(instance, oncore_cmd_Gd3,  sizeof(oncore_cmd_Gd3));  /* M12+T */
2231 			else
2232 				oncore_sendmsg(instance, oncore_cmd_At2,  sizeof(oncore_cmd_At2));  /* not GT, arg not VP */
2233 			break;
2234 		}
2235 
2236 		/* Read back PPS Offset for Output */
2237 		/* Nb. This will fail silently for early UT (no plus) and M12 models */
2238 
2239 		oncore_sendmsg(instance, oncore_cmd_Ayx,  sizeof(oncore_cmd_Ayx));
2240 
2241 		/* Read back Cable Delay for Output */
2242 
2243 		oncore_sendmsg(instance, oncore_cmd_Azx,  sizeof(oncore_cmd_Azx));
2244 
2245 		/* Read back Satellite Mask Angle for Output */
2246 
2247 		oncore_sendmsg(instance, oncore_cmd_Agx,  sizeof(oncore_cmd_Agx));
2248 	}
2249 
2250 
2251 	/* Unfortunately, the Gd3 command returns '3' for the M12 v1.3 firmware where it is
2252 	 * out-of-range and it should return 0-2. (v1.3 can't do a HW Site Survey)
2253 	 * We must do the Gd3, and then wait a cycle or two for things to settle,
2254 	 * then check Ha[130]&0x10 to see if a SS is in progress.
2255 	 * We will set SW if HW has not been set after an appropriate delay.
2256 	 */
2257 
2258 	if (instance->site_survey == ONCORE_SS_TESTING) {
2259 		if (instance->chan == 12) {
2260 			if (instance->count1) {
2261 				if (instance->count1++ > 5 || instance->BEHa[130]&0x10) {
2262 					instance->count1 = 0;
2263 					if (instance->BEHa[130]&0x10) {
2264 						oncore_log(instance, LOG_NOTICE,
2265 								"Initiating hardware 3D site survey");
2266 
2267 						oncore_log(instance, LOG_NOTICE, "SSstate = ONCORE_SS_HW");
2268 						instance->site_survey = ONCORE_SS_HW;
2269 					} else {
2270 						oncore_log(instance, LOG_NOTICE, "SSstate = ONCORE_SS_SW");
2271 						instance->site_survey = ONCORE_SS_SW;
2272 					}
2273 				}
2274 			}
2275 		} else {
2276 			if (instance->count1) {
2277 				if (instance->count1++ > 5) {
2278 					instance->count1 = 0;
2279 					/*
2280 					 * For instance->site_survey to still be ONCORE_SS_TESTING, then after a 5sec
2281 					 * wait after the @@At2/@@Gd3 command we have not changed the state to
2282 					 * ONCORE_SS_HW.  If the Hardware is capable of doing a Site Survey, then
2283 					 * the variable would have been changed by now.
2284 					 * There are three possibilities:
2285 					 * 6/8chan
2286 					 *   (a) We did not get a response to the @@At0 or @@At2 commands,
2287 					 *	   and it must be a GT/GT+/SL with no position hold mode.
2288 					 *	   We will have to do it ourselves.
2289 					 *   (b) We saw the @@At0, @@At2 commands, but @@At2 failed,
2290 					 *	   must be a VP or older UT which doesn't have Site Survey mode.
2291 					 *	   We will have to do it ourselves.
2292 					 * 12chan
2293 					 *   (c) We saw the @@Gd command, and saw H[13]*0x10
2294 					 *	   We will have to do it ourselves (done above)
2295 					 */
2296 
2297 					oncore_log_f(instance, LOG_INFO,
2298 						     "Initiating software 3D site survey (%d samples)",
2299 						     POS_HOLD_AVERAGE);
2300 
2301 					oncore_log(instance, LOG_NOTICE, "SSstate = ONCORE_SS_SW");
2302 					instance->site_survey = ONCORE_SS_SW;
2303 
2304 					instance->ss_lat = instance->ss_long = instance->ss_ht = 0;
2305 					if (instance->chan == 12)
2306 						oncore_sendmsg(instance, oncore_cmd_Gd0, sizeof(oncore_cmd_Gd0)); /* disable */
2307 					else {
2308 						oncore_sendmsg(instance, oncore_cmd_At0, sizeof(oncore_cmd_At0)); /* disable */
2309 						oncore_sendmsg(instance, oncore_cmd_Av0, sizeof(oncore_cmd_Av0)); /* disable */
2310 					}
2311 				}
2312 			}
2313 		}
2314 	}
2315 
2316 	/* check the mode we are in 0/2/3D */
2317 
2318 	if (instance->chan == 6) {
2319 		if (instance->BEHa[64]&0x8)
2320 			instance->mode = MODE_0D;
2321 		else if (instance->BEHa[64]&0x10)
2322 			instance->mode = MODE_2D;
2323 		else if (instance->BEHa[64]&0x20)
2324 			instance->mode = MODE_3D;
2325 	} else if (instance->chan == 8) {
2326 		if (instance->BEHa[72]&0x8)
2327 			instance->mode = MODE_0D;
2328 		else if (instance->BEHa[72]&0x10)
2329 			instance->mode = MODE_2D;
2330 		else if (instance->BEHa[72]&0x20)
2331 			instance->mode = MODE_3D;
2332 	} else if (instance->chan == 12) {
2333 		int bits;
2334 
2335 		bits = (instance->BEHa[129]>>5) & 0x7;	/* actually Ha */
2336 		if (bits == 0x4)
2337 			instance->mode = MODE_0D;
2338 		else if (bits == 0x6)
2339 			instance->mode = MODE_2D;
2340 		else if (bits == 0x7)
2341 			instance->mode = MODE_3D;
2342 	}
2343 
2344 	/* copy the record to the (extra) location in SHMEM */
2345 
2346 	if (instance->shmem) {
2347 		int	i;
2348 		u_char	*smp;	 /* pointer to start of shared mem for Ba/Ea/Ha */
2349 
2350 		switch(instance->chan) {
2351 		case 6:   smp = &instance->shmem[instance->shmem_Ba]; break;
2352 		case 8:   smp = &instance->shmem[instance->shmem_Ea]; break;
2353 		case 12:  smp = &instance->shmem[instance->shmem_Ha]; break;
2354 		default:  smp = (u_char *) NULL;		      break;
2355 		}
2356 
2357 		switch (instance->mode) {
2358 		case MODE_0D:	i = 1; break;	/* 0D, Position Hold */
2359 		case MODE_2D:	i = 2; break;	/* 2D, Altitude Hold */
2360 		case MODE_3D:	i = 3; break;	/* 3D fix */
2361 		default:	i = 0; break;
2362 		}
2363 
2364 		if (i && smp != NULL) {
2365 			i *= (len+6);
2366 			smp[i + 2]++;
2367 			memcpy(&smp[i+3], buf, (size_t) (len+3));
2368 		}
2369 	}
2370 
2371 	/*
2372 	 * check if traim timer active
2373 	 * if it hasn't been cleared, then @@Bn/@@En/@@Hn did not respond
2374 	 */
2375 
2376 	if (instance->traim_delay) {
2377 		if (instance->traim_delay++ > 5) {
2378 			instance->traim = 0;
2379 			instance->traim_delay = 0;
2380 			cp = "ONCORE: Did not detect TRAIM response, TRAIM = OFF";
2381 			oncore_log(instance, LOG_INFO, cp);
2382 
2383 			oncore_set_traim(instance);
2384 		} else
2385 			return;
2386 
2387 	}
2388 
2389 	/* by now should have a @@Ba/@@Ea/@@Ha with good data in it */
2390 
2391 	if (!instance->have_dH && !instance->traim_delay)
2392 		oncore_compute_dH(instance);
2393 
2394 	/*
2395 	 * must be ONCORE_RUN if we are here.
2396 	 * Have # chan and TRAIM by now.
2397 	 */
2398 
2399 	instance->pp->year   = buf[6]*256+buf[7];
2400 	instance->pp->day    = ymd2yd(buf[6]*256+buf[7], buf[4], buf[5]);
2401 	instance->pp->hour   = buf[8];
2402 	instance->pp->minute = buf[9];
2403 	instance->pp->second = buf[10];
2404 
2405 	/*
2406 	 * Are we doing a Hardware or Software Site Survey?
2407 	 */
2408 
2409 	if (instance->site_survey == ONCORE_SS_HW || instance->site_survey == ONCORE_SS_SW)
2410 		oncore_ss(instance);
2411 
2412 	/* see if we ever saw a response from the @@Ayx above */
2413 
2414 	if (instance->count2) {
2415 		if (instance->count2++ > 5) {	/* this delay to check on @@Ay command */
2416 			instance->count2 = 0;
2417 
2418 			/* Have we seen an Ay (1PPS time offset) command response */
2419 			/* if not, and non-zero offset, zero the offset, and send message */
2420 
2421 			if (!instance->saw_Ay && instance->offset) {
2422 				oncore_log(instance, LOG_INFO, "No @@Ay command, PPS OFFSET ignored");
2423 				instance->offset = 0;
2424 			}
2425 		}
2426 	}
2427 
2428 	/*
2429 	 * Check the leap second status once per day.
2430 	 */
2431 
2432 	oncore_check_leap_sec(instance);
2433 
2434 	/*
2435 	 * if SHMEM active, every 15s, steal one 'tick' to get 2D or 3D posn.
2436 	 */
2437 
2438 	if (instance->shmem && !instance->shmem_bad_Ea && instance->shmem_Posn && (instance->site_survey == ONCORE_SS_DONE))
2439 		oncore_shmem_get_3D(instance);
2440 
2441 	if (!instance->traim)	/* NO traim, no BnEnHn, go get tick */
2442 		oncore_get_timestamp(instance, instance->offset, instance->offset);
2443 }
2444 
2445 
2446 
2447 /* Almanac Status */
2448 
2449 static void
2450 oncore_msg_Bd(
2451 	struct instance *instance,
2452 	u_char *buf,
2453 	size_t len
2454 	)
2455 {
2456 	oncore_log_f(instance, LOG_NOTICE,
2457 		     "Bd: Almanac %s, week = %d, t = %d, %d SVs: %x",
2458 		     ((buf[4]) ? "LOADED" : "(NONE)"), buf[5], buf[6],
2459 		     buf[7], w32(&buf[8]));
2460 }
2461 
2462 
2463 
2464 /* get leap-second warning message */
2465 
2466 /*
2467  * @@Bj does NOT behave as documented in current Oncore firmware.
2468  * It turns on the LEAP indicator when the data is set, and does not,
2469  * as documented, wait until the beginning of the month when the
2470  * leap second will occur.
2471  * Since this firmware bug will never be fixed in all the outstanding Oncore receivers
2472  * @@Bj is only called in June/December.
2473  */
2474 
2475 static void
2476 oncore_msg_Bj(
2477 	struct instance *instance,
2478 	u_char *buf,
2479 	size_t len
2480 	)
2481 {
2482 	const char	*cp;
2483 
2484 	instance->saw_Bj = 1;
2485 
2486 	switch(buf[4]) {
2487 	case 1:
2488 		instance->pp->leap = LEAP_ADDSECOND;
2489 		cp = "Set pp.leap to LEAP_ADDSECOND";
2490 		break;
2491 	case 2:
2492 		instance->pp->leap = LEAP_DELSECOND;
2493 		cp = "Set pp.leap to LEAP_DELSECOND";
2494 		break;
2495 	case 0:
2496 	default:
2497 		instance->pp->leap = LEAP_NOWARNING;
2498 		cp = "Set pp.leap to LEAP_NOWARNING";
2499 		break;
2500 	}
2501 	oncore_log(instance, LOG_NOTICE, cp);
2502 }
2503 
2504 
2505 
2506 static void
2507 oncore_msg_Bl(
2508 	struct instance *instance,
2509 	u_char *buf,
2510 	size_t	len
2511 	)
2512 {
2513 	int	subframe, valid, page, i, j, tow;
2514 	int	day_now, day_lsf;
2515 	const char	*cp;
2516 	enum {
2517 		WARN_NOT_YET,
2518 		WARN_0,
2519 		WARN_PLUS,
2520 		WARN_MINUS
2521 	} warn;
2522 
2523 
2524 	subframe = buf[6] & 017;
2525 	valid = (buf[6] >> 4) & 017;
2526 	page = buf[7];
2527 
2528 	if ((!instance->Bl.lsf_flg && !instance->Bl.wn_flg) && (subframe == 4 && page == 18 && valid == 10)) {
2529 		instance->Bl.dt_ls  = buf[32];
2530 		instance->Bl.WN_lsf = buf[33];
2531 		instance->Bl.DN_lsf = buf[34];
2532 		instance->Bl.dt_lsf = buf[35];
2533 		instance->Bl.lsf_flg++;
2534 	}
2535 	if ((instance->Bl.lsf_flg && !instance->Bl.wn_flg) && (subframe == 1 && valid == 10)) {
2536 		i = (buf[7+7]<<8) + buf[7+8];
2537 		instance->Bl.WN = i >> 6;
2538 		tow = (buf[7+4]<<16) + (buf[7+5]<<8) + buf[7+6];
2539 		tow >>= 7;
2540 		tow = tow & 0377777;
2541 		tow <<= 2;
2542 		instance->Bl.DN = tow/57600L + 1;
2543 		instance->Bl.wn_flg++;
2544 	}
2545 	if (instance->Bl.wn_flg && instance->Bl.lsf_flg)  {
2546 		instance->Bl.wn_flg = instance->Bl.lsf_flg = 0;
2547 		oncore_cmd_Bl[2] = 0;
2548 		oncore_sendmsg(instance, oncore_cmd_Bl, sizeof oncore_cmd_Bl);
2549 		oncore_cmd_Bl[2] = 1;
2550 
2551 		i = instance->Bl.WN&01400;
2552 		instance->Bl.WN_lsf |= i;
2553 
2554 		/* have everything I need, doit */
2555 
2556 		i = (instance->Bl.WN_lsf - instance->Bl.WN);
2557 		if (i < 0)
2558 			i += 1024;
2559 		day_now = instance->Bl.DN;
2560 		day_lsf = 7*i + instance->Bl.DN_lsf;
2561 
2562 		/* ignore if in past or more than a month in future */
2563 
2564 		warn = WARN_NOT_YET;
2565 		if (day_lsf >= day_now && day_lsf - day_now < 32) {
2566 			/* if < 28d, doit, if 28-31, ck day-of-month < 20 (not at end of prev month) */
2567 			if (day_lsf - day_now < 28 ||  instance->BEHa[5] < 20) {
2568 				i = instance->Bl.dt_lsf - instance->Bl.dt_ls;
2569 				switch (i) {
2570 				case -1:
2571 					warn = WARN_MINUS;
2572 					break;
2573 				case  0:
2574 					warn = WARN_0;
2575 					break;
2576 				case  1:
2577 					warn = WARN_PLUS;
2578 					break;
2579 				}
2580 			}
2581 		}
2582 
2583 		switch (warn) {
2584 		case WARN_0:
2585 		case WARN_NOT_YET:
2586 			instance->peer->leap = LEAP_NOWARNING;
2587 			cp = "Set peer.leap to LEAP_NOWARNING";
2588 			break;
2589 		case WARN_MINUS:
2590 			instance->peer->leap = LEAP_DELSECOND;
2591 			cp = "Set peer.leap to LEAP_DELSECOND";
2592 			break;
2593 		case WARN_PLUS:
2594 			instance->peer->leap = LEAP_ADDSECOND;
2595 			cp = "Set peer.leap to LEAP_ADDSECOND";
2596 			break;
2597 		default:
2598 			cp = NULL;
2599 			break;
2600 		}
2601 		oncore_log(instance, LOG_NOTICE, cp);
2602 
2603 		i = instance->Bl.dt_lsf-instance->Bl.dt_ls;
2604 		if (i) {
2605 			j = (i >= 0) ? i : -i;		/* abs(i) */
2606 			oncore_log_f(instance, LOG_NOTICE,
2607 				     "see Leap_Second (%c%d) in %d days",
2608 				     ((i >= 0) ? '+' : '-'), j,
2609 				     day_lsf-day_now);
2610 		}
2611 	}
2612 
2613 /*
2614  * Reg only wants the following output for "deeper" driver debugging.
2615  * See Bug 2142 and Bug 1866
2616  */
2617 #if 0
2618 	oncore_log_f(instance, LOG_DEBUG,
2619 		     "dt_ls = %d  dt_lsf = %d  WN = %d  DN = %d  WN_lsf = %d  DNlsf = %d  wn_flg = %d  lsf_flg = %d  Bl_day = %d",
2620 		     instance->Bl.dt_ls, instance->Bl.dt_lsf,
2621 		     instance->Bl.WN, instance->Bl.DN,
2622 		     instance->Bl.WN_lsf, instance->Bl.DN_lsf,
2623 		     instance->Bl.wn_flg, instance->Bl.lsf_flg,
2624 		     instance->Bl.Bl_day);
2625 #endif
2626 }
2627 
2628 
2629 static void
2630 oncore_msg_BnEnHn(
2631 	struct instance *instance,
2632 	u_char *buf,
2633 	size_t	len
2634 	)
2635 {
2636 	long	dt1, dt2;
2637 
2638 	if (instance->o_state != ONCORE_RUN)
2639 		return;
2640 
2641 	if (instance->traim_delay) {	 /* flag that @@Bn/@@En/Hn returned */
2642 			instance->traim_ck = 1;
2643 			instance->traim_delay = 0;
2644 			oncore_log(instance, LOG_NOTICE, "ONCORE: Detected TRAIM, TRAIM = ON");
2645 
2646 			oncore_set_traim(instance);
2647 	}
2648 
2649 	memcpy(instance->BEHn, buf, (size_t) len);	/* Bn or En or Hn */
2650 
2651 	if (!instance->traim)	/* BnEnHn will be turned off in any case */
2652 		return;
2653 
2654 	/* If Time RAIM doesn't like it, don't trust it */
2655 
2656 	if (buf[2] == 'H') {
2657 		if (instance->BEHn[6]) {    /* bad TRAIM */
2658 			oncore_log(instance, LOG_WARNING, "BAD TRAIM");
2659 			return;
2660 		}
2661 
2662 		dt1 = instance->saw_tooth + instance->offset;	 /* dt this time step */
2663 		instance->saw_tooth = (s_char) instance->BEHn[14]; /* update for next time Hn[14] */
2664 		dt2 = instance->saw_tooth + instance->offset;	 /* dt next time step */
2665 	} else {
2666 		if (instance->BEHn[21]) /* bad TRAIM */
2667 			return;
2668 
2669 		dt1 = instance->saw_tooth + instance->offset;	 /* dt this time step */
2670 		instance->saw_tooth = (s_char) instance->BEHn[25]; /* update for next time Bn[25], En[25] */
2671 		dt2 = instance->saw_tooth + instance->offset;	 /* dt next time step */
2672 	}
2673 
2674 	oncore_get_timestamp(instance, dt1, dt2);
2675 }
2676 
2677 
2678 
2679 /* Here for @@Ca, @@Fa and @@Ia messages */
2680 
2681 /* These are Self test Commands for 6, 8, and 12 chan receivers.
2682  * There are good reasons NOT to do a @@Ca, @@Fa or @@Ia command with the ONCORE.
2683  * It was found that under some circumstances the following
2684  * command would fail if issued immediately after the return from the
2685  * @@Fa, but a 2sec delay seemed to fix things.  Since simply calling
2686  * sleep(2) is wasteful, and may cause trouble for some OS's, repeating
2687  * itimer, we set a flag, and test it at the next POLL.  If it hasn't
2688  * been cleared, we reissue the @@Cj that is issued below.
2689  * Note that we do a @@Cj at the beginning, and again here.
2690  * The first is to get the info, the 2nd is just used as a safe command
2691  * after the @@Fa for all Oncores (and it was in this posn in the
2692  * original code).
2693  */
2694 
2695 static void
2696 oncore_msg_CaFaIa(
2697 	struct instance *instance,
2698 	u_char *buf,
2699 	size_t len
2700 	)
2701 {
2702 	int	i;
2703 
2704 	if (instance->o_state == ONCORE_TEST_SENT) {
2705 		enum antenna_state antenna;
2706 
2707 		instance->timeout = 0;
2708 
2709 #if ONCORE_VERBOSE_SELF_TEST
2710 		if (debug > 2) {
2711 			if (buf[2] == 'I')
2712 				oncore_log_f(instance, LOG_DEBUG,
2713 					     ">>@@%ca %x %x %x", buf[2],
2714 					     buf[4], buf[5], buf[6]);
2715 			else
2716 				oncore_log_f(instance, LOG_DEBUG,
2717 					     ">>@@%ca %x %x", buf[2],
2718 					     buf[4], buf[5]);
2719 		}
2720 #endif
2721 
2722 		antenna = (buf[4] & 0xc0) >> 6;
2723 		buf[4] &= ~0xc0;
2724 
2725 		i = buf[4] || buf[5];
2726 		if (buf[2] == 'I') i = i || buf[6];
2727 		if (i) {
2728 			if (buf[2] == 'I')
2729 				oncore_log_f(instance, LOG_ERR,
2730 					     "self test failed: result %02x %02x %02x",
2731 					     buf[4], buf[5], buf[6]);
2732 			else
2733 				oncore_log_f(instance, LOG_ERR,
2734 					     "self test failed: result %02x %02x",
2735 					     buf[4], buf[5]);
2736 
2737 			oncore_log(instance, LOG_ERR,
2738 				   "ONCORE: self test failed, shutting down driver");
2739 
2740 			refclock_report(instance->peer, CEVNT_FAULT);
2741 			oncore_shutdown(instance->unit, instance->peer);
2742 			return;
2743 		}
2744 
2745 		/* report the current antenna state */
2746 
2747 		oncore_antenna_report(instance, antenna);
2748 
2749 		instance->o_state = ONCORE_INIT;
2750 		oncore_log(instance, LOG_NOTICE, "state = ONCORE_INIT");
2751 
2752 		instance->timeout = 4;
2753 		oncore_sendmsg(instance, oncore_cmd_Cj, sizeof(oncore_cmd_Cj));
2754 	}
2755 }
2756 
2757 
2758 
2759 /*
2760  * Demultiplex the almanac into shmem
2761  */
2762 
2763 static void
2764 oncore_msg_Cb(
2765 	struct instance *instance,
2766 	u_char *buf,
2767 	size_t len
2768 	)
2769 {
2770 	int i;
2771 
2772 	if (instance->shmem == NULL)
2773 		return;
2774 
2775 	if (buf[4] == 5 && buf[5] > 0 && buf[5] < 26)
2776 		i = buf[5];
2777 	else if (buf[4] == 4 && buf[5] <= 5)
2778 		i = buf[5] + 24;
2779 	else if (buf[4] == 4 && buf[5] <= 10)
2780 		i = buf[5] + 23;
2781 	else if (buf[4] == 4 && buf[5] == 25)
2782 		i = 34;
2783 	else {
2784 		oncore_log(instance, LOG_NOTICE, "Cb: Response is NO ALMANAC");
2785 		return;
2786 	}
2787 
2788 	i *= 36;
2789 	instance->shmem[instance->shmem_Cb + i + 2]++;
2790 	memcpy(instance->shmem + instance->shmem_Cb + i + 3, buf, (size_t) (len + 3));
2791 
2792 #ifdef ONCORE_VERBOSE_MSG_CB
2793 	oncore_log_f(instance, LOG_DEBUG, "See Cb [%d,%d]", buf[4],
2794 		     buf[5]);
2795 #endif
2796 }
2797 
2798 
2799 
2800 /*
2801  * Set to Factory Defaults (Reasonable for UT w/ no Battery Backup
2802  *	not so for VP (eeprom) or any unit with a battery
2803  */
2804 
2805 static void
2806 oncore_msg_Cf(
2807 	struct instance *instance,
2808 	u_char *buf,
2809 	size_t len
2810 	)
2811 {
2812 	if (instance->o_state == ONCORE_RESET_SENT) {
2813 		oncore_sendmsg(instance, oncore_cmd_Cg, sizeof(oncore_cmd_Cg)); /* Return to  Posn Fix mode */
2814 										       /* Reset set VP to IDLE */
2815 		instance->o_state = ONCORE_TEST_SENT;
2816 		oncore_log(instance, LOG_NOTICE, "state = ONCORE_TEST_SENT");
2817 
2818 		oncore_sendmsg(instance, oncore_cmd_Cj, sizeof(oncore_cmd_Cj));
2819 	}
2820 }
2821 
2822 
2823 
2824 /*
2825  * This is the Grand Central Station for the Preliminary Initialization.
2826  * Once done here we move on to oncore_msg_BaEaHa for final Initialization and Running.
2827  *
2828  * We do an @@Cj whenever we need a safe command for all Oncores.
2829  * The @@Cj gets us back here where we can switch to the next phase of setup.
2830  *
2831  * o Once at the very beginning (in start) to get the Model number.
2832  *   This info is printed, but no longer used.
2833  * o Again after we have determined the number of Channels in the receiver.
2834  * o And once later after we have done a reset and test, (which may hang),
2835  *   as we are about to initialize the Oncore and start it running.
2836  * o We have one routine below for each case.
2837  */
2838 
2839 static void
2840 oncore_msg_Cj(
2841 	struct instance *instance,
2842 	u_char *buf,
2843 	size_t len
2844 	)
2845 {
2846 	int	mode;
2847 
2848 	memcpy(instance->Cj, buf, len);
2849 
2850 	instance->timeout = 0;
2851 	if (instance->o_state == ONCORE_CHECK_ID) {
2852 		oncore_msg_Cj_id(instance, buf, len);
2853 		oncore_chan_test(instance);
2854 	} else if (instance->o_state == ONCORE_HAVE_CHAN) {
2855 		mode = instance->init_type;
2856 		if (mode == 3 || mode == 4) {	/* Cf will return here to check for TEST */
2857 			instance->o_state = ONCORE_RESET_SENT;
2858 			oncore_log(instance, LOG_NOTICE, "state = ONCORE_RESET_SENT");
2859 			oncore_sendmsg(instance, oncore_cmd_Cf, sizeof(oncore_cmd_Cf));
2860 		} else {
2861 			instance->o_state = ONCORE_TEST_SENT;
2862 			oncore_log(instance, LOG_NOTICE, "state = ONCORE_TEST_SENT");
2863 		}
2864 	}
2865 
2866 	if (instance->o_state == ONCORE_TEST_SENT) {
2867 		if (instance->chan == 6)
2868 			oncore_sendmsg(instance, oncore_cmd_Ca, sizeof(oncore_cmd_Ca));
2869 		else if (instance->chan == 8)
2870 			oncore_sendmsg(instance, oncore_cmd_Fa, sizeof(oncore_cmd_Fa));
2871 		else if (instance->chan == 12)
2872 			oncore_sendmsg(instance, oncore_cmd_Ia, sizeof(oncore_cmd_Ia));
2873 	} else if (instance->o_state == ONCORE_INIT)
2874 		oncore_msg_Cj_init(instance, buf, len);
2875 }
2876 
2877 
2878 
2879 /* The information on determining a Oncore 'Model', viz VP, UT, etc, from
2880  *	the Model Number comes from "Richard M. Hambly" <rick@cnssys.com>
2881  *	and from Motorola.  Until recently Rick was the only source of
2882  *	this information as Motorola didn't give the information out.
2883  *
2884  * Determine the Type from the Model #, this determines #chan and if TRAIM is
2885  *   available.
2886  *
2887  * The Information from this routine is NO LONGER USED.
2888  * The RESULTS are PRINTED, BUT NOT USED, and the routine COULD BE DELETED
2889  */
2890 
2891 static void
2892 oncore_msg_Cj_id(
2893 	struct instance *instance,
2894 	u_char *buf,
2895 	size_t len
2896 	)
2897 {
2898 	char *cp2, Model[21];
2899 	const char *cp, *cp1;
2900 
2901 	/* Write Receiver ID message to clockstats file */
2902 
2903 	instance->Cj[294] = '\0';
2904 	for (cp= (char *)instance->Cj; cp< (char *) &instance->Cj[294]; ) {
2905 		char *cpw = strchr(cp, '\r');
2906 		if (!cpw)
2907 			cpw = (char *)&instance->Cj[294];
2908 		*cpw = '\0';
2909 		oncore_log(instance, LOG_NOTICE, cp);
2910 		*cpw = '\r';
2911 		cp = cpw+2;
2912 	}
2913 
2914 	/* next, the Firmware Version and Revision numbers */
2915 
2916 	instance->version  = atoi((char *) &instance->Cj[83]);
2917 	instance->revision = atoi((char *) &instance->Cj[111]);
2918 
2919 	/* from model number decide which Oncore this is,
2920 		and then the number of channels */
2921 
2922 	for (cp= (char *) &instance->Cj[160]; *cp == ' '; cp++)   /* start right after 'Model #' */
2923 		;
2924 	cp1 = cp;
2925 	cp2 = Model;
2926 	for (; !isspace((unsigned char)*cp) && cp-cp1 < 20; cp++, cp2++)
2927 		*cp2 = *cp;
2928 	*cp2 = '\0';
2929 
2930 	cp = 0;
2931 	if (!strncmp(Model, "PVT6", (size_t) 4)) {
2932 		cp = "PVT6";
2933 		instance->model = ONCORE_PVT6;
2934 	} else if (Model[0] == 'A') {
2935 		cp = "Basic";
2936 		instance->model = ONCORE_BASIC;
2937 	} else if (Model[0] == 'B' || !strncmp(Model, "T8", (size_t) 2)) {
2938 		cp = "VP";
2939 		instance->model = ONCORE_VP;
2940 	} else if (Model[0] == 'P') {
2941 		cp = "M12";
2942 		instance->model = ONCORE_M12;
2943 	} else if (Model[0] == 'R' || Model[0] == 'D' || Model[0] == 'S') {
2944 		if (Model[5] == 'N') {
2945 			cp = "GT";
2946 			instance->model = ONCORE_GT;
2947 		} else if ((Model[1] == '3' || Model[1] == '4') && Model[5] == 'G') {
2948 			cp = "GT+";
2949 			instance->model = ONCORE_GTPLUS;
2950 		} else if ((Model[1] == '5' && Model[5] == 'U') || (Model[1] == '1' && Model[5] == 'A')) {
2951 				cp = "UT";
2952 				instance->model = ONCORE_UT;
2953 		} else if (Model[1] == '5' && Model[5] == 'G') {
2954 			cp = "UT+";
2955 			instance->model = ONCORE_UTPLUS;
2956 		} else if (Model[1] == '6' && Model[5] == 'G') {
2957 			cp = "SL";
2958 			instance->model = ONCORE_SL;
2959 		} else {
2960 			cp = "Unknown";
2961 			instance->model = ONCORE_UNKNOWN;
2962 		}
2963 	} else	{
2964 		cp = "Unknown";
2965 		instance->model = ONCORE_UNKNOWN;
2966 	}
2967 
2968 	/* use MODEL to set CHAN and TRAIM and possibly zero SHMEM */
2969 
2970 	oncore_log_f(instance, LOG_INFO,
2971 		     "This looks like an Oncore %s with version %d.%d firmware.",
2972 		     cp, instance->version, instance->revision);
2973 
2974 	instance->chan_id = 8;	   /* default */
2975 	if (instance->model == ONCORE_BASIC || instance->model == ONCORE_PVT6)
2976 		instance->chan_id = 6;
2977 	else if (instance->model == ONCORE_VP || instance->model == ONCORE_UT || instance->model == ONCORE_UTPLUS)
2978 		instance->chan_id = 8;
2979 	else if (instance->model == ONCORE_M12)
2980 		instance->chan_id = 12;
2981 
2982 	instance->traim_id = 0;    /* default */
2983 	if (instance->model == ONCORE_BASIC || instance->model == ONCORE_PVT6)
2984 		instance->traim_id = 0;
2985 	else if (instance->model == ONCORE_VP || instance->model == ONCORE_UT || instance->model == ONCORE_UTPLUS)
2986 		instance->traim_id = 1;
2987 	else if (instance->model == ONCORE_M12)
2988 		instance->traim_id = -1;
2989 
2990 	oncore_log_f(instance, LOG_INFO, "Channels = %d, TRAIM = %s",
2991 		     instance->chan_id,
2992 		     ((instance->traim_id < 0)
2993 			  ? "UNKNOWN"
2994 			  : (instance->traim_id > 0)
2995 				? "ON"
2996 				: "OFF"));
2997 }
2998 
2999 
3000 
3001 /* OK, know type of Oncore, have possibly reset it, and have tested it.
3002  * We know the number of channels.
3003  * We will determine whether we have TRAIM before we actually start.
3004  * Now initialize.
3005  */
3006 
3007 static void
3008 oncore_msg_Cj_init(
3009 	struct instance *instance,
3010 	u_char *buf,
3011 	size_t len
3012 	)
3013 {
3014 	u_char	Cmd[20];
3015 	int	mode;
3016 
3017 
3018 	/* The M12 with 1.3 or 2.0 Firmware, loses track of all Satellites and has to
3019 	 * start again if we go from 0D -> 3D, then loses them again when we
3020 	 * go from 3D -> 0D.  We do this to get a @@Ea message for SHMEM.
3021 	 * For NOW we will turn this aspect of filling SHMEM off for the M12
3022 	 */
3023 
3024 	if (instance->chan == 12) {
3025 		instance->shmem_bad_Ea = 1;
3026 		oncore_log_f(instance, LOG_NOTICE,
3027 			     "*** SHMEM partially enabled for ONCORE M12 s/w v%d.%d ***",
3028 			     instance->version, instance->revision);
3029 	}
3030 
3031 	oncore_sendmsg(instance, oncore_cmd_Cg, sizeof(oncore_cmd_Cg)); /* Return to  Posn Fix mode */
3032 	oncore_sendmsg(instance, oncore_cmd_Bb, sizeof(oncore_cmd_Bb)); /* turn on for shmem (6/8/12) */
3033 	oncore_sendmsg(instance, oncore_cmd_Ek, sizeof(oncore_cmd_Ek)); /* turn off (VP) */
3034 	oncore_sendmsg(instance, oncore_cmd_Aw, sizeof(oncore_cmd_Aw)); /* UTC time (6/8/12) */
3035 	oncore_sendmsg(instance, oncore_cmd_AB, sizeof(oncore_cmd_AB)); /* Appl type static (VP) */
3036 	oncore_sendmsg(instance, oncore_cmd_Be, sizeof(oncore_cmd_Be)); /* Tell us the Almanac for shmem (6/8/12) */
3037 	oncore_sendmsg(instance, oncore_cmd_Bd, sizeof(oncore_cmd_Bd)); /* Tell us when Almanac changes */
3038 
3039 	mode = instance->init_type;
3040 
3041 	/* If there is Position input in the Config file
3042 	 * and mode = (1,3) set it as posn hold posn, goto 0D mode.
3043 	 *  or mode = (2,4) set it as INITIAL position, and do Site Survey.
3044 	 */
3045 
3046 	if (instance->posn_set) {
3047 		oncore_log(instance, LOG_INFO, "Setting Posn from input data");
3048 		oncore_set_posn(instance);	/* this should print posn indirectly thru the As cmd */
3049 	} else	/* must issue an @@At here to check on 6/8 Position Hold, set_posn would have */
3050 		if (instance->chan != 12)
3051 			oncore_sendmsg(instance, oncore_cmd_Atx, sizeof(oncore_cmd_Atx));
3052 
3053 	if (mode != 0) {
3054 			/* cable delay in ns */
3055 		memcpy(Cmd, oncore_cmd_Az, (size_t) sizeof(oncore_cmd_Az));
3056 		w32_buf(&Cmd[-2+4], (int)instance->delay);
3057 		oncore_sendmsg(instance, Cmd,  sizeof(oncore_cmd_Az));	/* 6,8,12 */
3058 
3059 			/* PPS offset in ns */
3060 		memcpy(Cmd, oncore_cmd_Ay, (size_t) sizeof(oncore_cmd_Ay));	/* some have it, some don't */
3061 		w32_buf(&Cmd[-2+4], instance->offset);			/* will check for hw response */
3062 		oncore_sendmsg(instance, Cmd,  sizeof(oncore_cmd_Ay));
3063 
3064 		/* Satellite mask angle */
3065 
3066 		if (instance->Ag != 0xff) {	/* will have 0xff in it if not set by user */
3067 			memcpy(Cmd, oncore_cmd_Ag, (size_t) sizeof(oncore_cmd_Ag));
3068 			Cmd[-2+4] = instance->Ag;
3069 			oncore_sendmsg(instance, Cmd,  sizeof(oncore_cmd_Ag));
3070 		}
3071 	}
3072 
3073 	/* 6, 8 12 chan - Position/Status/Data Output Message, 1/s
3074 	 * now we're really running
3075 	 * these were ALL started in the chan test,
3076 	 * However, if we had mode=3,4 then commands got turned off, so we turn
3077 	 * them on again here just in case
3078 	 */
3079 
3080 	if (instance->chan == 6) { /* start 6chan, kill 8,12chan commands, possibly testing VP in 6chan mode */
3081 		oncore_sendmsg(instance, oncore_cmd_Ea0, sizeof(oncore_cmd_Ea0));
3082 		oncore_sendmsg(instance, oncore_cmd_En0, sizeof(oncore_cmd_En0));
3083 		oncore_sendmsg(instance, oncore_cmd_Ha0, sizeof(oncore_cmd_Ha0));
3084 		oncore_sendmsg(instance, oncore_cmd_Hn0, sizeof(oncore_cmd_Hn0));
3085 		oncore_sendmsg(instance, oncore_cmd_Ba, sizeof(oncore_cmd_Ba ));
3086 	} else if (instance->chan == 8) {  /* start 8chan, kill 6,12chan commands */
3087 		oncore_sendmsg(instance, oncore_cmd_Ba0, sizeof(oncore_cmd_Ba0));
3088 		oncore_sendmsg(instance, oncore_cmd_Bn0, sizeof(oncore_cmd_Bn0));
3089 		oncore_sendmsg(instance, oncore_cmd_Ha0, sizeof(oncore_cmd_Ha0));
3090 		oncore_sendmsg(instance, oncore_cmd_Hn0, sizeof(oncore_cmd_Hn0));
3091 		oncore_sendmsg(instance, oncore_cmd_Ea, sizeof(oncore_cmd_Ea ));
3092 	} else if (instance->chan == 12){  /* start 12chan, kill 6,12chan commands */
3093 		oncore_sendmsg(instance, oncore_cmd_Ba0, sizeof(oncore_cmd_Ba0));
3094 		oncore_sendmsg(instance, oncore_cmd_Bn0, sizeof(oncore_cmd_Bn0));
3095 		oncore_sendmsg(instance, oncore_cmd_Ea0, sizeof(oncore_cmd_Ea0));
3096 		oncore_sendmsg(instance, oncore_cmd_En0, sizeof(oncore_cmd_En0));
3097 		oncore_sendmsg(instance, oncore_cmd_Ha, sizeof(oncore_cmd_Ha ));
3098 		oncore_cmd_Gc[2] = (instance->pps_control < 0) ? 1 : instance->pps_control;
3099 		oncore_sendmsg(instance, oncore_cmd_Gc, sizeof(oncore_cmd_Gc)); /* PPS off/continuous/Tracking 1+sat/TRAIM */
3100 	}
3101 
3102 	instance->count = 1;
3103 	instance->o_state = ONCORE_ALMANAC;
3104 	oncore_log(instance, LOG_NOTICE, "state = ONCORE_ALMANAC");
3105 }
3106 
3107 
3108 
3109 /* 12chan position */
3110 
3111 static void
3112 oncore_msg_Ga(
3113 	struct instance *instance,
3114 	u_char *buf,
3115 	size_t len
3116 	)
3117 {
3118 	long lat, lon, ht;
3119 	double Lat, Lon, Ht;
3120 
3121 
3122 	lat = buf_w32(&buf[4]);
3123 	lon = buf_w32(&buf[8]);
3124 	ht  = buf_w32(&buf[12]);  /* GPS ellipsoid */
3125 
3126 	Lat = lat;
3127 	Lon = lon;
3128 	Ht  = ht;
3129 
3130 	Lat /= 3600000;
3131 	Lon /= 3600000;
3132 	Ht  /= 100;
3133 
3134 	oncore_log_f(instance, LOG_NOTICE,
3135 		     "Ga Posn Lat = %.7f, Lon = %.7f, Ht  = %.2f", Lat,
3136 		     Lon, Ht);
3137 
3138 	instance->ss_lat  = lat;
3139 	instance->ss_long = lon;
3140 	instance->ss_ht   = ht;
3141 
3142 	oncore_print_posn(instance);
3143 }
3144 
3145 
3146 
3147 /* 12 chan time/date */
3148 
3149 static void
3150 oncore_msg_Gb(
3151 	struct instance *instance,
3152 	u_char *buf,
3153 	size_t len
3154 	)
3155 {
3156 	const char *	gmts;
3157 	int	mo, d, y, h, m, s, gmth, gmtm;
3158 
3159 	mo = buf[4];
3160 	d  = buf[5];
3161 	y  = 256*buf[6]+buf[7];
3162 
3163 	h  = buf[8];
3164 	m  = buf[9];
3165 	s  = buf[10];
3166 
3167 	gmts = ((buf[11] == 0) ? "+" : "-");
3168 	gmth = buf[12];
3169 	gmtm = buf[13];
3170 
3171 	oncore_log_f(instance, LOG_NOTICE,
3172 		     "Date/Time set to: %d%s%d %2d:%02d:%02d GMT (GMT offset is %s%02d:%02d)",
3173 		     d, months[mo-1], y, h, m, s, gmts, gmth, gmtm);
3174 }
3175 
3176 
3177 
3178 /* Response to PPS Control message (M12 and M12+T only ) */
3179 
3180 static void
3181 oncore_msg_Gc(
3182 	struct instance *instance,
3183 	u_char *buf,
3184 	size_t len
3185 	)
3186 {
3187 	const char *tbl[] = {"OFF", "ON", "SATELLITE", "TRAIM" };
3188 
3189 	instance->pps_control_msg_seen = 1;
3190 	oncore_log_f(instance, LOG_INFO, "PPS Control set to %s",
3191 		     tbl[buf[4]]);
3192 }
3193 
3194 
3195 
3196 /* Leap Second for M12, gives all info from satellite message */
3197 /* also in UT v3.0 */
3198 
3199 static void
3200 oncore_msg_Gj(
3201 	struct instance *instance,
3202 	u_char *buf,
3203 	size_t len
3204 	)
3205 {
3206 	static const char * insrem[2] = {
3207 		"removed",
3208 		"inserted"
3209 	};
3210 
3211 	int dt;
3212 	const char *cp;
3213 
3214 	instance->saw_Gj = 1; /* flag, saw_Gj, dont need to try Bj in check_leap */
3215 
3216 	/* print the message to verify whats there */
3217 
3218 	dt = buf[5] - buf[4];
3219 
3220 	oncore_log_f(instance, LOG_INFO,
3221 		     "Leap Sec Msg: %d %d %d %d %d %d %d %d %d %d",
3222 		     buf[4], buf[5], 256 * buf[6] + buf[7], buf[8],
3223 		     buf[9], buf[10],
3224 		     (buf[14] + 256 *
3225 		         (buf[13] + 256 * (buf[12] + 256 * buf[11]))),
3226 		     buf[15], buf[16], buf[17]);
3227 
3228 	/* There seems to be eternal confusion about when a leap second
3229 	 * takes place. It's the second *before* the new TAI offset
3230 	 * becomes effective. But since the ONCORE receiver tells us
3231 	 * just that, we would have to do some time/date calculations to
3232 	 * get the actual leap second -- that is, the one that is
3233 	 * deleted or inserted.
3234 	 *
3235 	 * Going through all this for a simple log is probably overkill,
3236 	 * so for fixing bug#1050 the message output is changed to
3237 	 * reflect the fact that it tells the second after the leap
3238 	 * second.
3239 	 */
3240 	if (dt)
3241 		oncore_log_f(instance, LOG_NOTICE,
3242 			     "Leap second %s (%d) before %04u-%02u-%02u/%02u:%02u:%02u",
3243 			     insrem[(dt > 0)], dt,
3244 			     256u * buf[6] + buf[7], buf[8], buf[9],
3245 			     buf[15], buf[16], buf[17]);
3246 
3247 	/* Only raise warning within a month of the leap second */
3248 
3249 	instance->pp->leap = LEAP_NOWARNING;
3250 	cp = "Set pp.leap to LEAP_NOWARNING";
3251 
3252 	if (buf[6] == instance->BEHa[6] && buf[7] == instance->BEHa[7] && /* year */
3253 	    buf[8] == instance->BEHa[4]) {	/* month */
3254 		if (dt) {
3255 			if (dt < 0) {
3256 				instance->pp->leap = LEAP_DELSECOND;
3257 				cp = "Set pp.leap to LEAP_DELSECOND";
3258 			} else {
3259 				instance->pp->leap = LEAP_ADDSECOND;
3260 				cp = "Set pp.leap to LEAP_ADDSECOND";
3261 			}
3262 		}
3263 	}
3264 	oncore_log(instance, LOG_INFO, cp);
3265 }
3266 
3267 
3268 
3269 /* Power on failure */
3270 
3271 static void
3272 oncore_msg_Sz(
3273 	struct instance *instance,
3274 	u_char *buf,
3275 	size_t len
3276 	)
3277 {
3278 	if (instance && instance->peer) {
3279 		oncore_log(instance, LOG_ERR, "Oncore: System Failure at Power On");
3280 		oncore_shutdown(instance->unit, instance->peer);
3281 	}
3282 }
3283 
3284 /************** Small Subroutines ***************/
3285 
3286 
3287 static void
3288 oncore_antenna_report(
3289 	struct instance *instance,
3290 	enum antenna_state new_state)
3291 {
3292 	const char *cp;
3293 
3294 	if (instance->ant_state == new_state)
3295 		return;
3296 
3297 	switch (new_state) {
3298 	case ONCORE_ANTENNA_OK: cp = "GPS antenna: OK";                   break;
3299 	case ONCORE_ANTENNA_OC: cp = "GPS antenna: short (overcurrent)";  break;
3300 	case ONCORE_ANTENNA_UC: cp = "GPS antenna: open (not connected)"; break;
3301 	case ONCORE_ANTENNA_NV: cp = "GPS antenna: short (no voltage)";   break;
3302 	default:		cp = "GPS antenna: ?";                    break;
3303 	}
3304 
3305 	instance->ant_state = new_state;
3306 	oncore_log(instance, LOG_NOTICE, cp);
3307 }
3308 
3309 
3310 
3311 static void
3312 oncore_chan_test(
3313 	struct instance *instance
3314 	)
3315 {
3316 	/* subroutine oncore_Cj_id has determined the number of channels from the
3317 	 * model number of the attached oncore.  This is not always correct since
3318 	 * the oncore could have non-standard firmware.  Here we check (independently) by
3319 	 * trying a 6, 8, and 12 chan command, and see which responds.
3320 	 * Caution: more than one CAN respond.
3321 	 *
3322 	 * This #chan is used by the code rather than that calculated from the model number.
3323 	 */
3324 
3325 	instance->o_state = ONCORE_CHECK_CHAN;
3326 	oncore_log(instance, LOG_NOTICE, "state = ONCORE_CHECK_CHAN");
3327 
3328 	instance->count3 = 1;
3329 	oncore_sendmsg(instance, oncore_cmd_Ba, sizeof(oncore_cmd_Ba));
3330 	oncore_sendmsg(instance, oncore_cmd_Ea, sizeof(oncore_cmd_Ea));
3331 	oncore_sendmsg(instance, oncore_cmd_Ha, sizeof(oncore_cmd_Ha));
3332 }
3333 
3334 
3335 
3336 /* check for a GOOD Almanac, have we got one yet? */
3337 
3338 static void
3339 oncore_check_almanac(
3340 	struct instance *instance
3341 	)
3342 {
3343 	if (instance->chan == 6) {
3344 		instance->rsm.bad_almanac = instance->BEHa[64]&0x1;
3345 		instance->rsm.bad_fix	  = instance->BEHa[64]&0x52;
3346 	} else if (instance->chan == 8) {
3347 		instance->rsm.bad_almanac = instance->BEHa[72]&0x1;
3348 		instance->rsm.bad_fix	  = instance->BEHa[72]&0x52;
3349 	} else if (instance->chan == 12) {
3350 		int bits1, bits2, bits3;
3351 
3352 		bits1 = (instance->BEHa[129]>>5) & 0x7; 	/* actually Ha */
3353 		bits2 = instance->BEHa[130];
3354 		instance->rsm.bad_almanac = (bits2 & 0x80);
3355 		instance->rsm.bad_fix	  = (bits2 & 0x8) || (bits1 == 0x2);
3356 					  /* too few sat     Bad Geom	  */
3357 
3358 		bits3 = instance->BEHa[141];	/* UTC parameters */
3359 		if (!instance->count5_set && (bits3 & 0xC0)) {
3360 			instance->count5 = 4;	/* was 2 [Bug 1766] */
3361 			instance->count5_set = 1;
3362 		}
3363 #ifdef ONCORE_VERBOSE_CHECK_ALMANAC
3364 		oncore_log_f(instance, LOG_DEBUG,
3365 			     "DEBUG BITS: (%x %x), (%x %x %x),  %x %x %x %x %x",
3366 			     instance->BEHa[129], instance->BEHa[130],
3367 			     bits1, bits2, bits3,
3368 			     instance->mode == MODE_0D,
3369 			     instance->mode == MODE_2D,
3370 			     instance->mode == MODE_3D,
3371 			     instance->rsm.bad_almanac,
3372 			     instance->rsm.bad_fix);
3373 		}
3374 #endif
3375 	}
3376 }
3377 
3378 
3379 
3380 /* check the antenna for changes (did it get unplugged?) */
3381 
3382 static void
3383 oncore_check_antenna(
3384 	struct instance *instance
3385 	)
3386 {
3387 	enum antenna_state antenna;		/* antenna state */
3388 
3389 	if (instance->chan == 12)
3390 		antenna = (instance->BEHa[130] & 0x6 ) >> 1;
3391 	else
3392 		antenna = (instance->BEHa[37] & 0xc0) >> 6;  /* prob unset 6, set GT, UT unset VP */
3393 
3394 	oncore_antenna_report (instance, antenna);
3395 }
3396 
3397 
3398 
3399 /*
3400  * Check the leap second status once per day.
3401  *
3402  * Note that the ONCORE firmware for the Bj command is wrong at
3403  * least in the VP.
3404  * It starts advertising a LEAP SECOND as soon as the GPS satellite
3405  * data message (page 18, subframe 4) is updated to a date in the
3406  * future, and does not wait for the month that it will occur.
3407  * The event will usually be advertised several months in advance.
3408  * Since there is a one bit flag, there is no way to tell if it is
3409  * this month, or when...
3410  *
3411  * As such, we have the workaround below, of only checking for leap
3412  * seconds with the Bj command in June/December.
3413  *
3414  * The Gj command gives more information, and we can tell in which
3415  * month to apply the correction.
3416  *
3417  * Note that with the VP we COULD read the raw data message, and
3418  * interpret it ourselves, but since this is specific to this receiver
3419  * only, and the above workaround is adequate, we don't bother.
3420  */
3421 
3422 static void
3423 oncore_check_leap_sec(
3424 	struct instance *instance
3425 	)
3426 {
3427 	oncore_cmd_Bl[2] = 1;				/* just to be sure */
3428 	if (instance->Bj_day != instance->BEHa[5]) {	/* do this 1/day */
3429 		instance->Bj_day = instance->BEHa[5];
3430 
3431 		if (instance->saw_Gj < 0) {	/* -1 DONT have Gj use Bj */
3432 			if ((instance->BEHa[4] == 6) || (instance->BEHa[4] == 12))
3433 				oncore_sendmsg(instance, oncore_cmd_Bj, sizeof(oncore_cmd_Bj));
3434 				oncore_sendmsg(instance, oncore_cmd_Bl, sizeof(oncore_cmd_Bl));
3435 			return;
3436 		}
3437 
3438 		if (instance->saw_Gj == 0)	/* 0 is dont know if we have Gj */
3439 			instance->count4 = 1;
3440 
3441 		oncore_sendmsg(instance, oncore_cmd_Gj, sizeof(oncore_cmd_Gj));
3442 		return;
3443 	}
3444 
3445 	/* Gj works for some 6/8 chan UT and the M12	  */
3446 	/* if no response from Gj in 5 sec, we try Bj	  */
3447 	/* which isnt implemented in all the GT/UT either */
3448 
3449 	if (instance->count4) { 	/* delay, waiting for Gj response */
3450 		if (instance->saw_Gj == 1)
3451 			instance->count4 = 0;
3452 		else if (instance->count4++ > 5) {	/* delay, waiting for Gj response */
3453 			instance->saw_Gj = -1;		/* didnt see it, will use Bj */
3454 			instance->count4 = 0;
3455 			if ((instance->BEHa[4] == 6) || (instance->BEHa[4] == 12)) {
3456 				oncore_sendmsg(instance, oncore_cmd_Bj, sizeof(oncore_cmd_Bj));
3457 				oncore_sendmsg(instance, oncore_cmd_Bl, sizeof(oncore_cmd_Bl));
3458 			}
3459 		}
3460 	}
3461 }
3462 
3463 
3464 
3465 /* check the message checksum,
3466  *  buf points to START of message ( @@ )
3467  *  len is length WITH CR/LF.
3468  */
3469 
3470 static int
3471 oncore_checksum_ok(
3472 	u_char *buf,
3473 	int	len
3474 	)
3475 {
3476 	int	i, j;
3477 
3478 	j = 0;
3479 	for (i = 2; i < len-3; i++)
3480 		j ^= buf[i];
3481 
3482 	return(j == buf[len-3]);
3483 }
3484 
3485 
3486 
3487 static void
3488 oncore_compute_dH(
3489 	struct instance *instance
3490 	)
3491 {
3492 	int GPS, MSL;
3493 
3494 	/* Here calculate dH = GPS - MSL for output message */
3495 	/* also set Altitude Hold mode if GT */
3496 
3497 	instance->have_dH = 1;
3498 	if (instance->chan == 12) {
3499 		GPS = buf_w32(&instance->BEHa[39]);
3500 		MSL = buf_w32(&instance->BEHa[43]);
3501 	} else {
3502 		GPS = buf_w32(&instance->BEHa[23]);
3503 		MSL = buf_w32(&instance->BEHa[27]);
3504 	}
3505 	instance->dH = GPS - MSL;
3506 	instance->dH /= 100.;
3507 
3508 	/* if MSL is not set, the calculation is meaningless */
3509 
3510 	if (MSL)	/* not set ! */
3511 		oncore_log_f(instance, LOG_INFO,
3512 		             "dH = (GPS - MSL) = %.2fm", instance->dH);
3513 }
3514 
3515 
3516 
3517 /*
3518  * try loading Almanac from shmem (where it was copied from shmem_old
3519  */
3520 
3521 static void
3522 oncore_load_almanac(
3523 	struct instance *instance
3524 	)
3525 {
3526 	u_char	*cp, Cmd[20];
3527 	int	n;
3528 	struct timeval tv;
3529 	struct tm *tm;
3530 
3531 	if (!instance->shmem)
3532 		return;
3533 
3534 #ifndef ONCORE_VERBOSE_LOAD_ALMANAC
3535 	for (cp = instance->shmem + 4; (n = 256 * (*(cp-3)) + *(cp-2));
3536 	     cp += (n + 3)) {
3537 		if (!strncmp((char *) cp, "@@Cb", 4) &&
3538 		    oncore_checksum_ok(cp, 33) &&
3539 		    (*(cp+4) == 4 || *(cp+4) == 5)) {
3540 			write(instance->ttyfd, cp, n);
3541 			oncore_print_Cb(instance, cp);
3542 		}
3543 	}
3544 #else	/* ONCORE_VERBOSE_LOAD_ALMANAC follows */
3545 	for (cp = instance->shmem + 4; (n = 256 * (*(cp-3)) + *(cp-2));
3546 	     cp += (n+3)) {
3547 		oncore_log_f(instance, LOG_DEBUG, "See %c%c%c%c %d",
3548 			   *(cp), *(cp+1), *(cp+2), *(cp+3), *(cp+4));
3549 
3550 		if (!strncmp(cp, "@@Cb", 4)) {
3551 			oncore_print_Cb(instance, cp);
3552 			if (oncore_checksum_ok(cp, 33)) {
3553 				if (*(cp+4) == 4 || *(cp+4) == 5) {
3554 					oncore_log(instance, LOG_DEBUG, "GOOD SF");
3555 					write(instance->ttyfd, cp, n);
3556 				} else
3557 					oncore_log(instance, LOG_DEBUG, "BAD SF");
3558 			} else
3559 				oncore_log(instance, LOG_DEBUG, "BAD CHECKSUM");
3560 		}
3561 	}
3562 #endif
3563 
3564 	/* Must load position and time or the Almanac doesn't do us any good */
3565 
3566 	if (!instance->posn_set) {	/* if we input a posn use it, else from SHMEM */
3567 		oncore_log(instance, LOG_NOTICE, "Loading Posn from SHMEM");
3568 		for (cp=instance->shmem+4; (n = 256*(*(cp-3)) + *(cp-2));  cp+=(n+3)) {
3569 			if ((instance->chan == 6  && (!strncmp((char *) cp, "@@Ba", 4) && oncore_checksum_ok(cp,  68))) ||
3570 			    (instance->chan == 8  && (!strncmp((char *) cp, "@@Ea", 4) && oncore_checksum_ok(cp,  76))) ||
3571 			    (instance->chan == 12 && (!strncmp((char *) cp, "@@Ha", 4) && oncore_checksum_ok(cp, 154)))) {
3572 				int ii, jj, kk;
3573 
3574 				instance->posn_set = 1;
3575 				ii = buf_w32(cp + 15);
3576 				jj = buf_w32(cp + 19);
3577 				kk = buf_w32(cp + 23);
3578 #ifdef ONCORE_VERBOSE_LOAD_ALMANAC
3579 				oncore_log_f(instance, LOG_DEBUG,
3580 					     "SHMEM posn = %ld (%d, %d, %d)",
3581 					     (long)(cp-instance->shmem),
3582 					     ii, jj, kk);
3583 #endif
3584 				if (ii != 0 || jj != 0 || kk != 0) { /* phk asked for this test */
3585 					instance->ss_lat  = ii;
3586 					instance->ss_long = jj;
3587 					instance->ss_ht   = kk;
3588 				}
3589 			}
3590 		}
3591 	}
3592 	oncore_set_posn(instance);
3593 
3594 	/* and set time to time from Computer clock */
3595 
3596 	GETTIMEOFDAY(&tv, 0);
3597 	tm = gmtime((const time_t *) &tv.tv_sec);
3598 
3599 #ifdef ONCORE_VERBOSE_LOAD_ALMANAC
3600 	oncore_log_f(instance, LOG_DEBUG, "DATE %d %d %d, %d %d %d",
3601 		     1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
3602 		     tm->tm_hour, tm->tm_min, tm->tm_sec);
3603 #endif
3604 	if (instance->chan == 12) {
3605 		memcpy(Cmd, oncore_cmd_Gb, (size_t) sizeof(oncore_cmd_Gb));
3606 		Cmd[-2+4]  = tm->tm_mon + 1;
3607 		Cmd[-2+5]  = tm->tm_mday;
3608 		Cmd[-2+6]  = (1900+tm->tm_year)/256;
3609 		Cmd[-2+7]  = (1900+tm->tm_year)%256;
3610 		Cmd[-2+8]  = tm->tm_hour;
3611 		Cmd[-2+9]  = tm->tm_min;
3612 		Cmd[-2+10] = tm->tm_sec;
3613 		Cmd[-2+11] = 0;
3614 		Cmd[-2+12] = 0;
3615 		Cmd[-2+13] = 0;
3616 		oncore_sendmsg(instance, Cmd,  sizeof(oncore_cmd_Gb));
3617 	} else {
3618 		/* First set GMT offset to zero */
3619 
3620 		oncore_sendmsg(instance, oncore_cmd_Ab, sizeof(oncore_cmd_Ab));
3621 
3622 		memcpy(Cmd, oncore_cmd_Ac, (size_t) sizeof(oncore_cmd_Ac));
3623 		Cmd[-2+4] = tm->tm_mon + 1;
3624 		Cmd[-2+5] = tm->tm_mday;
3625 		Cmd[-2+6] = (1900+tm->tm_year)/256;
3626 		Cmd[-2+7] = (1900+tm->tm_year)%256;
3627 		oncore_sendmsg(instance, Cmd,  sizeof(oncore_cmd_Ac));
3628 
3629 		memcpy(Cmd, oncore_cmd_Aa, (size_t) sizeof(oncore_cmd_Aa));
3630 		Cmd[-2+4] = tm->tm_hour;
3631 		Cmd[-2+5] = tm->tm_min;
3632 		Cmd[-2+6] = tm->tm_sec;
3633 		oncore_sendmsg(instance, Cmd,  sizeof(oncore_cmd_Aa));
3634 	}
3635 
3636 	oncore_log(instance, LOG_INFO, "Setting Posn and Time after Loading Almanac");
3637 }
3638 
3639 
3640 
3641 /* Almanac data input */
3642 
3643 static void
3644 oncore_print_Cb(
3645 	struct instance *instance,
3646 	u_char *cp
3647 	)
3648 {
3649 #ifdef ONCORE_VERBOSE_CB
3650 	int	ii;
3651 	char	Msg[160], Msg2[10];
3652 
3653 	oncore_log_f(instance, LOG_DEBUG, "DEBUG: See: %c%c%c%c", *(cp),
3654 		     *(cp+1), *(cp+2), *(cp+3));
3655 
3656 	snprintf(Msg, sizeof(Msg), "DEBUG: Cb: [%d,%d]", *(cp+4),
3657 		*(cp+5));
3658 	for (ii = 0; ii < 33; ii++) {
3659 		snprintf(Msg2, sizeof(Msg2), " %d", *(cp+ii));
3660 		strlcat(Msg, Msg2, sizeof(Msg));
3661 	}
3662 	oncore_log(instance, LOG_DEBUG, Msg);
3663 
3664 	oncore_log_f(instance, LOG_DEBUG, "Debug: Cb: [%d,%d]", *(cp+4),
3665 		     *(cp+5));
3666 #endif
3667 }
3668 
3669 
3670 #if 0
3671 static void
3672 oncore_print_array(
3673 	u_char *cp,
3674 	int	n
3675 	)
3676 {
3677 	int	jj, i, j, nn;
3678 
3679 	nn = 0;
3680 	printf("\nTOP\n");
3681 	jj = n/16;
3682 	for (j=0; j<jj; j++) {
3683 		printf("%4d: ", nn);
3684 		nn += 16;
3685 		for (i=0; i<16; i++)
3686 			printf(" %o", *cp++);
3687 		printf("\n");
3688 	}
3689 }
3690 #endif
3691 
3692 
3693 static void
3694 oncore_print_posn(
3695 	struct instance *instance
3696 	)
3697 {
3698 	char ew, ns;
3699 	double xd, xm, xs, yd, ym, ys, hm, hft;
3700 	int idx, idy, is, imx, imy;
3701 	long lat, lon;
3702 
3703 	oncore_log(instance, LOG_INFO, "Posn:");
3704 	ew = 'E';
3705 	lon = instance->ss_long;
3706 	if (lon < 0) {
3707 		ew = 'W';
3708 		lon = -lon;
3709 	}
3710 
3711 	ns = 'N';
3712 	lat = instance->ss_lat;
3713 	if (lat < 0) {
3714 		ns = 'S';
3715 		lat = -lat;
3716 	}
3717 
3718 	hm = instance->ss_ht/100.;
3719 	hft= hm/0.3048;
3720 
3721 	xd = lat/3600000.;	/* lat, lon in int msec arc, ht in cm. */
3722 	yd = lon/3600000.;
3723 	oncore_log_f(instance, LOG_INFO,
3724 		     "Lat = %c %11.7fdeg,    Long = %c %11.7fdeg,    Alt = %5.2fm (%5.2fft) GPS",
3725 		     ns, xd, ew, yd, hm, hft);
3726 
3727 	idx = xd;
3728 	idy = yd;
3729 	imx = lat%3600000;
3730 	imy = lon%3600000;
3731 	xm = imx/60000.;
3732 	ym = imy/60000.;
3733 	oncore_log_f(instance, LOG_INFO,
3734 		     "Lat = %c %3ddeg %7.4fm,   Long = %c %3ddeg %8.5fm,  Alt = %7.2fm (%7.2fft) GPS",
3735 		     ns, idx, xm, ew, idy, ym, hm, hft);
3736 
3737 	imx = xm;
3738 	imy = ym;
3739 	is  = lat%60000;
3740 	xs  = is/1000.;
3741 	is  = lon%60000;
3742 	ys  = is/1000.;
3743 	oncore_log_f(instance, LOG_INFO,
3744 		     "Lat = %c %3ddeg %2dm %5.2fs, Long = %c %3ddeg %2dm %5.2fs, Alt = %7.2fm (%7.2fft) GPS",
3745 		     ns, idx, imx, xs, ew, idy, imy, ys, hm, hft);
3746 }
3747 
3748 
3749 
3750 /*
3751  * write message to Oncore.
3752  */
3753 
3754 static void
3755 oncore_sendmsg(
3756 	struct	instance *instance,
3757 	u_char *ptr,
3758 	size_t len
3759 	)
3760 {
3761 	int	fd;
3762 	u_char cs = 0;
3763 
3764 	fd = instance->ttyfd;
3765 #ifdef ONCORE_VERBOSE_SENDMSG
3766 	if (debug > 4) {
3767 		oncore_log_f(instance, LOG_DEBUG, "ONCORE: Send @@%c%c %d",
3768 			     ptr[0], ptr[1], (int)len);
3769 	}
3770 #endif
3771 	write(fd, "@@", (size_t) 2);
3772 	write(fd, ptr, len);
3773 	while (len--)
3774 		cs ^= *ptr++;
3775 	write(fd, &cs, (size_t) 1);
3776 	write(fd, "\r\n", (size_t) 2);
3777 }
3778 
3779 
3780 
3781 static void
3782 oncore_set_posn(
3783 	struct instance *instance
3784 	)
3785 {
3786 	int	mode;
3787 	u_char	  Cmd[20];
3788 
3789 	/* Turn OFF position hold, it needs to be off to set position (for some units),
3790 	   will get set ON in @@Ea later */
3791 
3792 	if (instance->chan == 12)
3793 		oncore_sendmsg(instance, oncore_cmd_Gd0, sizeof(oncore_cmd_Gd0)); /* (12) */
3794 	else {
3795 		oncore_sendmsg(instance, oncore_cmd_At0, sizeof(oncore_cmd_At0)); /* (6/8) */
3796 		oncore_sendmsg(instance, oncore_cmd_Av0, sizeof(oncore_cmd_Av0)); /* (6/8) */
3797 	}
3798 
3799 	mode = instance->init_type;
3800 
3801 	if (mode != 0) {	/* first set posn hold position */
3802 		memcpy(Cmd, oncore_cmd_As, (size_t) sizeof(oncore_cmd_As));	/* don't modify static variables */
3803 		w32_buf(&Cmd[-2+4],  (int) instance->ss_lat);
3804 		w32_buf(&Cmd[-2+8],  (int) instance->ss_long);
3805 		w32_buf(&Cmd[-2+12], (int) instance->ss_ht);
3806 		Cmd[-2+16] = 0;
3807 		oncore_sendmsg(instance, Cmd,  sizeof(oncore_cmd_As));	/* posn hold 3D posn (6/8/12) */
3808 
3809 		memcpy(Cmd, oncore_cmd_Au, (size_t) sizeof(oncore_cmd_Au));
3810 		w32_buf(&Cmd[-2+4], (int) instance->ss_ht);
3811 		Cmd[-2+8] = 0;
3812 		oncore_sendmsg(instance, Cmd,  sizeof(oncore_cmd_Au));	/* altitude hold (6/8/12 not UT, M12T) */
3813 
3814 		/* next set current position */
3815 
3816 		if (instance->chan == 12) {
3817 			memcpy(Cmd, oncore_cmd_Ga, (size_t) sizeof(oncore_cmd_Ga));
3818 			w32_buf(&Cmd[-2+4], (int) instance->ss_lat);
3819 			w32_buf(&Cmd[-2+8], (int) instance->ss_long);
3820 			w32_buf(&Cmd[-2+12],(int) instance->ss_ht);
3821 			Cmd[-2+16] = 0;
3822 			oncore_sendmsg(instance, Cmd,  sizeof(oncore_cmd_Ga));		  /* 3d posn (12) */
3823 		} else {
3824 			memcpy(Cmd, oncore_cmd_Ad, (size_t) sizeof(oncore_cmd_Ad));
3825 			w32_buf(&Cmd[-2+4], (int) instance->ss_lat);
3826 			oncore_sendmsg(instance, Cmd,  sizeof(oncore_cmd_Ad));	/* lat (6/8) */
3827 
3828 			memcpy(Cmd, oncore_cmd_Ae, (size_t) sizeof(oncore_cmd_Ae));
3829 			w32_buf(&Cmd[-2+4], (int) instance->ss_long);
3830 			oncore_sendmsg(instance, Cmd,  sizeof(oncore_cmd_Ae));	/* long (6/8) */
3831 
3832 			memcpy(Cmd, oncore_cmd_Af, (size_t) sizeof(oncore_cmd_Af));
3833 			w32_buf(&Cmd[-2+4], (int) instance->ss_ht);
3834 			Cmd[-2+8] = 0;
3835 			oncore_sendmsg(instance, Cmd,  sizeof(oncore_cmd_Af));	/* ht (6/8) */
3836 		}
3837 
3838 		/* Finally, turn on position hold */
3839 
3840 		if (instance->chan == 12)
3841 			oncore_sendmsg(instance, oncore_cmd_Gd1,  sizeof(oncore_cmd_Gd1));
3842 		else
3843 			oncore_sendmsg(instance, oncore_cmd_At1,  sizeof(oncore_cmd_At1));
3844 	}
3845 }
3846 
3847 
3848 
3849 static void
3850 oncore_set_traim(
3851 	struct instance *instance
3852 	)
3853 {
3854 	if (instance->traim_in != -1)	/* set in Input */
3855 		instance->traim = instance->traim_in;
3856 	else
3857 		instance->traim = instance->traim_ck;
3858 
3859 	oncore_log_f(instance, LOG_INFO, "Input   says TRAIM = %d",
3860 		     instance->traim_in);
3861 	oncore_log_f(instance, LOG_INFO, "Model # says TRAIM = %d",
3862 		     instance->traim_id);
3863 	oncore_log_f(instance, LOG_INFO, "Testing says TRAIM = %d",
3864 		     instance->traim_ck);
3865 	oncore_log_f(instance, LOG_INFO, "Using        TRAIM = %d",
3866 		     instance->traim);
3867 
3868 	if (instance->traim_ck == 1 && instance->traim == 0) {
3869 		/* if it should be off, and I turned it on during testing,
3870 		   then turn it off again */
3871 		if (instance->chan == 6)
3872 			oncore_sendmsg(instance, oncore_cmd_Bnx, sizeof(oncore_cmd_Bnx));
3873 		else if (instance->chan == 8)
3874 			oncore_sendmsg(instance, oncore_cmd_Enx, sizeof(oncore_cmd_Enx));
3875 		else	/* chan == 12 */
3876 			oncore_sendmsg(instance, oncore_cmd_Ge0, sizeof(oncore_cmd_Ge0));
3877 			oncore_sendmsg(instance, oncore_cmd_Hn0, sizeof(oncore_cmd_Hn0));
3878 	}
3879 }
3880 
3881 
3882 
3883 /*
3884  * if SHMEM active, every 15s, steal one 'tick' to get 2D or 3D posn.
3885  */
3886 
3887 static void
3888 oncore_shmem_get_3D(
3889 	struct instance *instance
3890 	)
3891 {
3892 	if (instance->pp->second%15 == 3) {	/* start the sequence */			/* by changing mode */
3893 		instance->shmem_reset = 1;
3894 		if (instance->chan == 12) {
3895 			if (instance->shmem_Posn == 2)
3896 				oncore_sendmsg(instance, oncore_cmd_Gd2,  sizeof(oncore_cmd_Gd2));  /* 2D */
3897 			else
3898 				oncore_sendmsg(instance, oncore_cmd_Gd0,  sizeof(oncore_cmd_Gd0));  /* 3D */
3899 		} else {
3900 			if (instance->saw_At) { 		/* out of 0D -> 3D mode */
3901 				oncore_sendmsg(instance, oncore_cmd_At0, sizeof(oncore_cmd_At0));
3902 				if (instance->shmem_Posn == 2)	/* 3D -> 2D mode */
3903 					oncore_sendmsg(instance, oncore_cmd_Av1, sizeof(oncore_cmd_Av1));
3904 			} else
3905 				oncore_sendmsg(instance, oncore_cmd_Av0, sizeof(oncore_cmd_Av0));
3906 		}
3907 	} else if (instance->shmem_reset || (instance->mode != MODE_0D)) {
3908 		instance->shmem_reset = 0;
3909 		if (instance->chan == 12)
3910 			oncore_sendmsg(instance, oncore_cmd_Gd1,  sizeof(oncore_cmd_Gd1));	/* 0D */
3911 		else {
3912 			if (instance->saw_At) {
3913 				if (instance->mode == MODE_2D)	/* 2D -> 3D or 0D mode */
3914 					oncore_sendmsg(instance, oncore_cmd_Av0, sizeof(oncore_cmd_Av0));
3915 				oncore_sendmsg(instance, oncore_cmd_At1,  sizeof(oncore_cmd_At1)); /* to 0D mode */
3916 			} else
3917 				oncore_sendmsg(instance, oncore_cmd_Av1,  sizeof(oncore_cmd_Av1));
3918 		}
3919 	}
3920 }
3921 
3922 
3923 
3924 /*
3925  * Here we do the Software SiteSurvey.
3926  * We have to average our own position for the Position Hold Mode
3927  *   We use Heights from the GPS ellipsoid.
3928  * We check for the END of either HW or SW SiteSurvey.
3929  */
3930 
3931 static void
3932 oncore_ss(
3933 	struct instance *instance
3934 	)
3935 {
3936 	double	lat, lon, ht;
3937 
3938 
3939 	if (instance->site_survey == ONCORE_SS_HW) {
3940 		/*
3941 		 * Check to see if Hardware SiteSurvey has Finished.
3942 		 */
3943 
3944 		if ((instance->chan == 8  && !(instance->BEHa[37]  & 0x20)) ||
3945 		    (instance->chan == 12 && !(instance->BEHa[130] & 0x10))) {
3946 			oncore_log(instance, LOG_INFO, "Now in 0D mode");
3947 
3948 			if (instance->chan == 12)
3949 				oncore_sendmsg(instance, oncore_cmd_Gax, sizeof(oncore_cmd_Gax));
3950 			else
3951 				oncore_sendmsg(instance, oncore_cmd_Asx, sizeof(oncore_cmd_Asx));
3952 
3953 			oncore_log(instance, LOG_NOTICE, "SSstate = ONCORE_SS_DONE");
3954 			instance->site_survey = ONCORE_SS_DONE;
3955 		}
3956 	} else {
3957 		/*
3958 		 * Must be a Software Site Survey.
3959 		 */
3960 
3961 		if (instance->rsm.bad_fix)	/* Not if poor geometry or less than 3 sats */
3962 			return;
3963 
3964 		if (instance->mode != MODE_3D)	/* Use only 3D Fixes */
3965 			return;
3966 
3967 		instance->ss_lat  += buf_w32(&instance->BEHa[15]);
3968 		instance->ss_long += buf_w32(&instance->BEHa[19]);
3969 		instance->ss_ht   += buf_w32(&instance->BEHa[23]);  /* GPS ellipsoid */
3970 		instance->ss_count++;
3971 
3972 		if (instance->ss_count != POS_HOLD_AVERAGE)
3973 			return;
3974 
3975 		instance->ss_lat  /= POS_HOLD_AVERAGE;
3976 		instance->ss_long /= POS_HOLD_AVERAGE;
3977 		instance->ss_ht   /= POS_HOLD_AVERAGE;
3978 
3979 		oncore_log_f(instance, LOG_NOTICE,
3980 			     "Surveyed posn: lat %.3f (mas) long %.3f (mas) ht %.3f (cm)",
3981 			     instance->ss_lat, instance->ss_long,
3982 			     instance->ss_ht);
3983 		lat = instance->ss_lat/3600000.;
3984 		lon = instance->ss_long/3600000.;
3985 		ht  = instance->ss_ht/100;
3986 		oncore_log_f(instance, LOG_NOTICE,
3987 			     "Surveyed posn: lat %.7f (deg) long %.7f (deg) ht %.2f (m)",
3988 			     lat, lon, ht);
3989 
3990 		oncore_set_posn(instance);
3991 
3992 		oncore_log(instance, LOG_INFO, "Now in 0D mode");
3993 
3994 		oncore_log(instance, LOG_NOTICE, "SSstate = ONCORE_SS_DONE");
3995 		instance->site_survey = ONCORE_SS_DONE;
3996 	}
3997 }
3998 
3999 
4000 
4001 static int
4002 oncore_wait_almanac(
4003 	struct instance *instance
4004 	)
4005 {
4006 	if (instance->rsm.bad_almanac) {
4007 		instance->counta++;
4008 		if (instance->counta%5 == 0)
4009 			oncore_log(instance, LOG_INFO, "Waiting for Almanac");
4010 
4011 		/*
4012 		 * If we get here (first time) then we don't have an almanac in memory.
4013 		 * Check if we have a SHMEM, and if so try to load whatever is there.
4014 		 */
4015 
4016 		if (!instance->almanac_from_shmem) {
4017 			instance->almanac_from_shmem = 1;
4018 			oncore_load_almanac(instance);
4019 		}
4020 		return(1);
4021 	} else {  /* Here we have the Almanac, we will be starting the @@Bn/@@En/@@Hn
4022 		     commands, and can finally check for TRAIM.  Again, we set a delay
4023 		     (5sec) and wait for things to settle down */
4024 
4025 		if (instance->chan == 6)
4026 			oncore_sendmsg(instance, oncore_cmd_Bn, sizeof(oncore_cmd_Bn));
4027 		else if (instance->chan == 8)
4028 			oncore_sendmsg(instance, oncore_cmd_En, sizeof(oncore_cmd_En));
4029 		else if (instance->chan == 12) {
4030 			oncore_sendmsg(instance, oncore_cmd_Gc, sizeof(oncore_cmd_Gc)); /* 1PPS on, continuous */
4031 			oncore_sendmsg(instance, oncore_cmd_Ge, sizeof(oncore_cmd_Ge)); /* TRAIM on */
4032 			oncore_sendmsg(instance, oncore_cmd_Hn, sizeof(oncore_cmd_Hn)); /* TRAIM status 1/s */
4033 		}
4034 		instance->traim_delay = 1;
4035 
4036 		oncore_log(instance, LOG_NOTICE, "Have now loaded an ALMANAC");
4037 
4038 		instance->o_state = ONCORE_RUN;
4039 		oncore_log(instance, LOG_NOTICE, "state = ONCORE_RUN");
4040 	}
4041 	return(0);
4042 }
4043 
4044 
4045 static	void
4046 oncore_feed_clockproc(
4047 	struct instance * instance
4048 	)
4049 {
4050 	struct peer         * const peer = instance->peer;
4051 	struct refclockproc * const pp   = instance->pp;
4052 
4053 	TCivilDate cd;	/* calendar date + time */
4054 	TGpsDatum  gd;	/* GPS datum, remapped into NTP epoch */
4055 	l_fp       fp;	/* the reference time in NTP format */
4056 
4057 	if (pp->year >= 1980) {
4058 		/* There are oncore receivers that run in a fixed
4059 		 * (possibly shifted) GPS era and fold back into that
4060 		 * era on every GPS week rollover.
4061 		 *
4062 		 * We do not trust the date we get and remap to a GPS
4063 		 * era defined by the GPS base date (derived from the
4064 		 * build time stamp or a 'tos basedate' config option.
4065 		 */
4066 		ZERO(fp);	/* has a zero to begin with */
4067 		ZERO(cd);	/* month == monthday == 0 -> use year+yearday */
4068 		cd.year    = pp->year;
4069 		cd.yearday = pp->day;
4070 		cd.hour    = pp->hour;
4071 		cd.minute  = pp->minute;
4072 		cd.second  = pp->second;
4073 
4074 		/* the magic happens in the next line: */
4075 		gd = gpscal_from_calendar(&cd, fp); /* fp should be zero here */
4076 
4077 		/* To avoid the trouble the day-of-year calculations in
4078 		 * 'refclock_process()' can cause we feed the time
4079 		 * stamps we have now directly. This also saves us two
4080 		 * full calendar calendar conversion cycles.
4081 		 */
4082 		fp = ntpfp_from_gpsdatum(&gd);
4083 		refclock_process_offset(pp, fp, pp->lastrec, pp->fudgetime1);
4084 	} else {
4085 		/* This is obviously a bad date/time... */
4086 		refclock_report(peer, CEVNT_BADDATE);
4087 		peer->flags &= ~FLAG_PPS;	/* problem - clear PPS FLAG */
4088 		return;
4089 	}
4090 }
4091 
4092 static void
4093 oncore_log (
4094 	struct instance *instance,
4095 	int log_level,
4096 	const char *msg
4097 	)
4098 {
4099 	msyslog(log_level, "ONCORE[%d]: %s", instance->unit, msg);
4100 	mprintf_clock_stats(&instance->peer->srcadr, "ONCORE[%d]: %s",
4101 			    instance->unit, msg);
4102 }
4103 
4104 
4105 static int
4106 oncore_log_f(
4107 	struct instance *	instance,
4108 	int			log_level,
4109 	const char *		fmt,
4110 	...
4111 	)
4112 {
4113 	va_list	ap;
4114 	int	rc;
4115 	char	msg[512];
4116 
4117 	va_start(ap, fmt);
4118 	rc = mvsnprintf(msg, sizeof(msg), fmt, ap);
4119 	va_end(ap);
4120 	oncore_log(instance, log_level, msg);
4121 
4122 #ifdef ONCORE_VERBOSE_ONCORE_LOG
4123 	instance->max_len = max(strlen(msg), instance->max_len);
4124 	instance->max_count++;
4125 	if (instance->max_count % 100 == 0)
4126 		oncore_log_f(instance, LOG_INFO,
4127 			    "Max Message Length so far is %d",
4128 			    instance->max_len);
4129 #endif
4130 	return rc;
4131 }
4132 
4133 #else
4134 int refclock_oncore_bs;
4135 #endif	/* REFCLOCK && CLOCK_ONCORE */
4136