Initial import from FreeBSD RELENG_4:
[dragonfly.git] / contrib / ntp / ntpd / refclock_palisade.c
1 /*
2  * This software was developed by the Software and Component Technologies
3  * group of Trimble Navigation, Ltd.
4  *
5  * Copyright (c) 1997, 1998, 1999, 2000  Trimble Navigation Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *    This product includes software developed by Trimble Navigation, Ltd.
19  * 4. The name of Trimble Navigation Ltd. may not be used to endorse or
20  *    promote products derived from this software without specific prior
21  *    written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY TRIMBLE NAVIGATION LTD. ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL TRIMBLE NAVIGATION LTD. BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35
36 /*
37  * refclock_palisade - clock driver for the Trimble Palisade GPS
38  * timing receiver
39  *
40  * For detailed information on this program, please refer to the html 
41  * Refclock 29 page accompanying the NTP distribution.
42  *
43  * for questions / bugs / comments, contact:
44  * sven_dietrich@trimble.com
45  *
46  * Sven-Thorsten Dietrich
47  * 645 North Mary Avenue
48  * Post Office Box 3642
49  * Sunnyvale, CA 94088-3642
50  *
51  * Version 2.45; July 14, 1999
52  *
53  */
54
55 #ifdef HAVE_CONFIG_H
56 #include "config.h"
57 #endif
58
59 #if defined(REFCLOCK) && (defined(PALISADE) || defined(CLOCK_PALISADE))
60
61 #include "refclock_palisade.h"
62 /* Table to get from month to day of the year */
63 const int days_of_year [12] = {
64         0,  31,  59,  90, 120, 151, 181, 212, 243, 273, 304, 334
65 };
66
67 #ifdef DEBUG
68 const char * Tracking_Status[15][15] = { 
69                 { "Doing Fixes\0" }, { "Good 1SV\0" }, { "Approx. 1SV\0" },
70                 {"Need Time\0" }, { "Need INIT\0" }, { "PDOP too High\0" },
71                 { "Bad 1SV\0" }, { "0SV Usable\0" }, { "1SV Usable\0" },
72                 { "2SV Usable\0" }, { "3SV Usable\0" }, { "No Integrity\0" },
73                 { "Diff Corr\0" }, { "Overdet Clock\0" }, { "Invalid\0" } };
74 #endif
75
76 /*
77  * Transfer vector
78  */
79 struct refclock refclock_palisade = {
80         palisade_start,         /* start up driver */
81         palisade_shutdown,      /* shut down driver */
82         palisade_poll,          /* transmit poll message */
83         noentry,                /* not used  */
84         noentry,                /* initialize driver (not used) */
85         noentry,                /* not used */
86         NOFLAGS                 /* not used */
87 };
88
89 int day_of_year P((char *dt));
90
91 /*
92  * palisade_start - open the devices and initialize data for processing
93  */
94 static int
95 palisade_start (
96 #ifdef PALISADE
97         unit, peer
98         )
99         int unit;
100         struct peer *peer;
101 #else /* ANSI */
102         int unit,
103         struct peer *peer
104         )
105 #endif
106 {
107         struct palisade_unit *up;
108         struct refclockproc *pp;
109         int fd;
110         char gpsdev[20];
111
112         struct termios tio;
113 #ifdef SYS_WINNT
114         (void) sprintf(gpsdev, "COM%d:", unit);
115 #else   
116         (void) sprintf(gpsdev, DEVICE, unit);
117 #endif
118         /*
119          * Open serial port. 
120          */
121 #if defined PALISADE
122          fd = open(gpsdev, O_RDWR
123 #ifdef O_NONBLOCK
124                   | O_NONBLOCK
125 #endif
126                   );
127 #else /* NTP 4.x */
128         fd = refclock_open(gpsdev, SPEED232, LDISC_RAW);
129 #endif
130         if (fd <= 0) {
131 #ifdef DEBUG
132                 printf("Palisade(%d) start: open %s failed\n", unit, gpsdev);
133 #endif
134                 return 0;
135         }
136
137         msyslog(LOG_NOTICE, "Palisade(%d) fd: %d dev: %s", unit, fd,
138                 gpsdev);
139
140 #if defined PALISADE 
141         tio.c_cflag = (CS8|CLOCAL|CREAD|PARENB|PARODD);
142         tio.c_iflag = (IGNBRK);
143         tio.c_oflag = (0);
144         tio.c_lflag = (0);
145
146         if (cfsetispeed(&tio, SPEED232) == -1) {
147                 msyslog(LOG_ERR,"Palisade(%d) cfsetispeed(fd, &tio): %m",unit);
148 #ifdef DEBUG
149                 printf("Palisade(%d) cfsetispeed(fd, &tio)\n",unit);
150 #endif
151                 return 0;
152         }
153         if (cfsetospeed(&tio, SPEED232) == -1) {
154 #ifdef DEBUG
155                 printf("Palisade(%d) cfsetospeed(fd, &tio)\n",unit);
156 #endif
157                 msyslog(LOG_ERR,"Palisade(%d) cfsetospeed(fd, &tio): %m",unit);
158                 return 0;
159         }
160 #else /* NTP 4.x */
161         if (tcgetattr(fd, &tio) < 0) {
162                 msyslog(LOG_ERR, 
163                         "Palisade(%d) tcgetattr(fd, &tio): %m",unit);
164 #ifdef DEBUG
165                 printf("Palisade(%d) tcgetattr(fd, &tio)\n",unit);
166 #endif
167                 return (0);
168         }
169
170         tio.c_cflag |= (PARENB|PARODD);
171         tio.c_iflag &= ~ICRNL;
172 #endif /*  NTP 4.x */
173
174         if (tcsetattr(fd, TCSANOW, &tio) == -1) {
175                 msyslog(LOG_ERR, "Palisade(%d) tcsetattr(fd, &tio): %m",unit);
176 #ifdef DEBUG
177                 printf("Palisade(%d) tcsetattr(fd, &tio)\n",unit);
178 #endif
179                 return 0;
180         }
181
182         /*
183          * Allocate and initialize unit structure
184          */
185         up = (struct palisade_unit *) emalloc(sizeof(struct palisade_unit));
186               
187         if (!(up)) {
188                 msyslog(LOG_ERR, "Palisade(%d) emalloc: %m",unit);
189 #ifdef DEBUG
190                 printf("Palisade(%d) emalloc\n",unit);
191 #endif
192                 (void) close(fd);
193                 return (0);
194         }
195
196         memset((char *)up, 0, sizeof(struct palisade_unit));
197
198         pp = peer->procptr;
199         pp->io.clock_recv = palisade_io;
200         pp->io.srcclock = (caddr_t)peer;
201         pp->io.datalen = 0;
202         pp->io.fd = fd;
203         if (!io_addclock(&pp->io)) {
204 #ifdef DEBUG
205                 printf("Palisade(%d) io_addclock\n",unit);
206 #endif
207                 (void) close(fd);
208                 free(up);
209                 return (0);
210         }
211
212         /*
213          * Initialize miscellaneous variables
214          */
215         pp->unitptr = (caddr_t)up;
216         pp->clockdesc = DESCRIPTION;
217
218         peer->precision = PRECISION;
219         peer->sstclktype = CTL_SST_TS_UHF;
220         peer->minpoll = TRMB_MINPOLL;
221         peer->maxpoll = TRMB_MAXPOLL;
222         memcpy((char *)&pp->refid, REFID, 4);
223         
224         up->leap_status = 0;
225         up->unit = (short) unit;
226         up->rpt_status = TSIP_PARSED_EMPTY;
227         up->rpt_cnt = 0;
228
229         return 1;
230 }
231
232
233 /*
234  * palisade_shutdown - shut down the clock
235  */
236 static void
237 palisade_shutdown (
238 #ifdef PALISADE
239         unit, peer
240         )
241         int unit;
242         struct peer *peer;
243 #else /* ANSI */
244         int unit,
245         struct peer *peer
246         )
247 #endif
248 {
249         struct palisade_unit *up;
250         struct refclockproc *pp;
251         pp = peer->procptr;
252         up = (struct palisade_unit *)pp->unitptr;
253         io_closeclock(&pp->io);
254         free(up);
255 }
256
257
258
259 /* 
260  * unpack_date - get day and year from date
261  */
262 int
263 day_of_year (
264 #ifdef PALISADE
265         dt
266         )
267         char * dt;
268 #else
269         char * dt
270         )
271 #endif
272 {
273         int day, mon, year;
274
275         mon = dt[1];
276        /* Check month is inside array bounds */
277        if ((mon < 1) || (mon > 12)) 
278                 return -1;
279
280         day = dt[0] + days_of_year[mon - 1];
281         year = getint((u_char *) (dt + 2)); 
282
283         if ( !(year % 4) && ((year % 100) || 
284                 (!(year % 100) && !(year%400)))
285                         &&(mon > 2))
286                         day ++; /* leap year and March or later */
287
288         return day;
289 }
290
291
292 /* 
293  * TSIP_decode - decode the TSIP data packets 
294  */
295 int
296 TSIP_decode (
297 #ifdef PALISADE
298         peer
299         )
300         struct peer *peer;
301 #else
302         struct peer *peer
303         )
304 #endif
305 {
306         int st;
307         long   secint;
308         double secs;
309         double secfrac;
310         unsigned short event = 0;
311
312         struct palisade_unit *up;
313         struct refclockproc *pp;
314
315         pp = peer->procptr;
316         up = (struct palisade_unit *)pp->unitptr;
317
318         /*
319          * Check the time packet, decode its contents. 
320          * If the timecode has invalid length or is not in
321          * proper format, declare bad format and exit.
322          */
323
324         if ((up->rpt_buf[0] == (char) 0x41) ||
325                 (up->rpt_buf[0] == (char) 0x46) ||
326                 (up->rpt_buf[0] == (char) 0x54) ||
327                 (up->rpt_buf[0] == (char) 0x4B) ||
328                 (up->rpt_buf[0] == (char) 0x6D)) {
329
330         /* standard time packet - GPS time and GPS week number */
331 #ifdef DEBUG
332                         printf("Palisade Port B packets detected. Connect to Port A\n");
333 #endif
334
335                 return 0;       
336         }
337
338         if (up->rpt_buf[0] == (char) 0x8f) {
339         /* 
340          * Superpackets
341          */
342            event = (unsigned short) (getint((u_char *) &mb(1)) & 0xffff);
343            if (!((pp->sloppyclockflag & CLK_FLAG2) || event)) 
344                 /* Ignore Packet */
345                         return 0;          
346         
347            switch (mb(0) & 0xff) {
348              int GPS_UTC_Offset;
349              case PACKET_8F0B: 
350
351                 if (up->polled <= 0)
352                         return 0;
353
354                 if (up->rpt_cnt != LENCODE_8F0B)  /* check length */
355                         break;
356                 
357 #ifdef DEBUG
358 if (debug > 1) {
359                 int ts;
360                 double lat, lon, alt;
361                 lat = getdbl((u_char *) &mb(42)) * R2D;
362                 lon = getdbl((u_char *) &mb(50)) * R2D;
363                 alt = getdbl((u_char *) &mb(58));
364
365                 printf("TSIP_decode: unit %d: Latitude: %03.4f Longitude: %03.4f Alt: %05.2f m\n",
366                                 up->unit, lat,lon,alt);
367                 printf("TSIP_decode: unit %d: Sats:", up->unit);
368                 for (st = 66, ts = 0; st <= 73; st++) if (mb(st)) {
369                         if (mb(st) > 0) ts++;
370                         printf(" %02d", mb(st));
371                 }
372                 printf(" : Tracking %d\n", ts); 
373         }
374 #endif
375
376                 GPS_UTC_Offset = getint((u_char *) &mb(16));  
377                 if (GPS_UTC_Offset == 0) { /* Check UTC offset */ 
378 #ifdef DEBUG
379                          printf("TSIP_decode: UTC Offset Unknown\n");
380 #endif
381                         break;
382                 }
383
384                 secs = getdbl((u_char *) &mb(3));
385                 secint = (long) secs;
386                 secfrac = secs - secint; /* 0.0 <= secfrac < 1.0 */
387
388                 pp->usec = (long) (secfrac * 1000000); 
389
390                 secint %= 86400;    /* Only care about today */
391                 pp->hour = secint / 3600;
392                 secint %= 3600;
393                 pp->minute = secint / 60;
394                 secint %= 60;
395                 pp->second = secint % 60;
396                 
397                 if ((pp->day = day_of_year(&mb(11))) < 0) break;
398
399                 pp->year = getint((u_char *) &mb(13)); 
400
401 #ifdef DEBUG
402         if (debug > 1)
403                 printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%06ld %02d/%02d/%04d UTC %02d\n",
404                         up->unit, mb(0) & 0xff, event, pp->hour, pp->minute, 
405                         pp->second, pp->usec, mb(12), mb(11), pp->year, GPS_UTC_Offset);
406 #endif
407                 /* Only use this packet when no
408                  * 8F-AD's are being received
409                  */
410
411                 if (up->leap_status) {
412                         up->leap_status = 0;
413                         return 0;
414                 }
415
416                 return 2;
417                 break;
418
419           case PACKET_NTP:
420                 /* Palisade-NTP Packet */
421
422                 if (up->rpt_cnt != LENCODE_NTP) /* check length */
423                         break;
424         
425                 up->leap_status = mb(19);
426
427                 if (up->polled  <= 0) 
428                         return 0;
429                                 
430                 /* Check Tracking Status */
431                 st = mb(18);
432                 if (st < 0 || st > 14) st = 14;
433                 if ((st >= 2 && st <= 7) || st == 11 || st == 12) {
434 #ifdef DEBUG
435                  printf("TSIP_decode: Not Tracking Sats : %s\n",
436                                 *Tracking_Status[st]);
437 #endif
438                         refclock_report(peer, CEVNT_BADTIME);
439                         up->polled = -1;
440                         return 0;
441                         break;
442                 }
443
444                 if (up->leap_status & PALISADE_LEAP_PENDING) {
445                         if (up->leap_status & PALISADE_UTC_TIME)  
446                                 pp->leap = LEAP_ADDSECOND;
447                         else
448                                 pp->leap = LEAP_DELSECOND;
449                 }
450                 else if (up->leap_status)
451                         pp->leap = LEAP_NOWARNING;
452                 
453                 else {  /* UTC flag is not set:
454                          * Receiver may have been reset, and lost
455                          * its UTC almanac data */
456                         pp->leap = LEAP_NOTINSYNC;
457 #ifdef DEBUG
458                          printf("TSIP_decode: UTC Almanac unavailable: %d\n",
459                                 mb(19));        
460 #endif
461                         refclock_report(peer, CEVNT_BADTIME);
462                         up->polled = -1;
463                         return 0;
464                 }
465
466                 pp->usec = (long) (getdbl((u_char *) &mb(3)) * 1000000);
467
468                 if ((pp->day = day_of_year(&mb(14))) < 0) 
469                         break;
470                 pp->year = getint((u_char *) &mb(16)); 
471                 pp->hour = mb(11);
472                 pp->minute = mb(12);
473                 pp->second = mb(13);
474
475 #ifdef DEBUG
476         if (debug > 1)
477 printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%06ld %02d/%02d/%04d UTC %02x %s\n",
478                         up->unit, mb(0) & 0xff, event, pp->hour, pp->minute, 
479                         pp->second, pp->usec, mb(15), mb(14), pp->year,
480                         mb(19), *Tracking_Status[st]);
481 #endif
482                 return 1;
483                 break;
484
485           default:      
486                 /* Ignore Packet */
487                 return 0;
488           } /* switch */
489         }/* if 8F packets */    
490
491         refclock_report(peer, CEVNT_BADREPLY);
492         up->polled = -1;
493 #ifdef DEBUG
494         printf("TSIP_decode: unit %d: bad packet %02x-%02x event %d len %d\n", 
495                    up->unit, up->rpt_buf[0] & 0xff, mb(0) & 0xff, 
496                         event, up->rpt_cnt);
497 #endif
498         return 0;
499 }
500
501 /*
502  * palisade__receive - receive data from the serial interface
503  */
504
505 static void
506 palisade_receive (
507 #ifdef PALISADE
508         peer
509         )
510         struct peer * peer;
511 #else /* ANSI */
512         struct peer * peer
513         )
514 #endif
515 {
516         struct palisade_unit *up;
517         struct refclockproc *pp;
518
519         /*
520          * Initialize pointers and read the timecode and timestamp.
521          */
522         pp = peer->procptr;
523         up = (struct palisade_unit *)pp->unitptr;
524                 
525         if (! TSIP_decode(peer)) return;
526         
527         if (up->polled <= 0) 
528             return;   /* no poll pending, already received or timeout */
529
530         up->polled = 0;  /* Poll reply received */
531         pp->lencode = 0; /* clear time code */
532 #ifdef DEBUG
533         if (debug) 
534                 printf(
535         "palisade_receive: unit %d: %4d %03d %02d:%02d:%02d.%06ld\n",
536                         up->unit, pp->year, pp->day, pp->hour, pp->minute, 
537                         pp->second, pp->usec);
538 #endif
539
540         /*
541          * Process the sample
542          * Generate timecode: YYYY DoY HH:MM:SS.microsec 
543          * report and process 
544          */
545
546         (void) sprintf(pp->a_lastcode,"%4d %03d %02d:%02d:%02d.%06ld",
547                    pp->year,pp->day,pp->hour,pp->minute, pp->second,pp->usec); 
548         pp->lencode = 24;
549
550 #ifdef PALISADE
551         pp->lasttime = current_time;
552 #endif
553         if (!refclock_process(pp
554 #ifdef PALISADE
555                 , PALISADE_SAMPLES, PALISADE_SAMPLES * 3 / 5
556 #endif
557                 )) {
558                 refclock_report(peer, CEVNT_BADTIME);
559
560 #ifdef DEBUG
561                 printf("palisade_receive: unit %d: refclock_process failed!\n",
562                         up->unit);
563 #endif
564                 return;
565         }
566
567         record_clock_stats(&peer->srcadr, pp->a_lastcode); 
568
569 #ifdef DEBUG
570         if (debug)
571             printf("palisade_receive: unit %d: %s\n",
572                    up->unit, prettydate(&pp->lastrec));
573 #endif
574
575         refclock_receive(peer
576 #ifdef PALISADE
577                 , &pp->offset, 0, pp->dispersion,
578               &pp->lastrec, &pp->lastrec, pp->leap              
579 #endif          
580                 );
581 }
582
583
584 /*
585  * palisade_poll - called by the transmit procedure
586  *
587  */
588 static void
589 palisade_poll (
590 #ifdef PALISADE
591         unit, peer
592         )
593         int unit;
594         struct peer *peer;
595 #else
596         int unit,
597         struct peer *peer
598         )
599 #endif
600 {
601         struct palisade_unit *up;
602         struct refclockproc *pp;
603         
604         pp = peer->procptr;
605         up = (struct palisade_unit *)pp->unitptr;
606
607         pp->polls++;
608         if (up->polled > 0) /* last reply never arrived or error */ 
609             refclock_report(peer, CEVNT_TIMEOUT);
610
611         up->polled = 2; /* synchronous packet + 1 event */
612         
613 #ifdef DEBUG
614         if (debug)
615             printf("palisade_poll: unit %d: polling %s\n", unit,
616                    (pp->sloppyclockflag & CLK_FLAG2) ? 
617                         "synchronous packet" : "event");
618 #endif 
619
620         if (pp->sloppyclockflag & CLK_FLAG2) 
621             return;  /* using synchronous packet input */
622
623         if (HW_poll(pp) < 0) 
624             refclock_report(peer, CEVNT_FAULT); 
625 }
626
627
628 static void
629 palisade_io (
630 #ifdef PALISADE
631         rbufp
632         )
633         struct recvbuf *rbufp;
634 #else /* ANSI */
635         struct recvbuf *rbufp
636         )
637 #endif
638 {
639         /*
640          * Initialize pointers and read the timecode and timestamp.
641          */
642         struct palisade_unit *up;
643         struct refclockproc *pp;
644         struct peer *peer;
645
646         char * c, * d;
647
648         peer = (struct peer *)rbufp->recv_srcclock;
649         pp = peer->procptr;
650         up = (struct palisade_unit *)pp->unitptr;
651
652         c = (char *) &rbufp->recv_space;
653         d = c + rbufp->recv_length;
654                 
655         while (c != d) {
656
657                 /* Build time packet */
658                 switch (up->rpt_status) {
659
660                     case TSIP_PARSED_DLE_1:
661                         switch (*c)
662                         {
663                             case 0:
664                             case DLE:
665                             case ETX:
666                                 up->rpt_status = TSIP_PARSED_EMPTY;
667                                 break;
668
669                             default:
670                                 up->rpt_status = TSIP_PARSED_DATA;
671                                 /* save packet ID */
672                                 up->rpt_buf[0] = *c;
673                                 break;
674                         }
675                         break;
676
677                     case TSIP_PARSED_DATA:
678                         if (*c == DLE)
679                             up->rpt_status = TSIP_PARSED_DLE_2;
680                         else 
681                             mb(up->rpt_cnt++) = *c;
682                         break;
683
684                     case TSIP_PARSED_DLE_2:
685                         if (*c == DLE) {
686                                 up->rpt_status = TSIP_PARSED_DATA;
687                                 mb(up->rpt_cnt++) = 
688                                                 *c;
689                         }       
690                         else if (*c == ETX) 
691                                     up->rpt_status = TSIP_PARSED_FULL;
692                         else    {
693                                 /* error: start new report packet */
694                                 up->rpt_status = TSIP_PARSED_DLE_1;
695                                 up->rpt_buf[0] = *c;
696                         }
697                         break;
698
699                     case TSIP_PARSED_FULL:
700                     case TSIP_PARSED_EMPTY:
701                     default:
702                         if ( *c != DLE)
703                           up->rpt_status = TSIP_PARSED_EMPTY;
704                 else 
705                           up->rpt_status = TSIP_PARSED_DLE_1;
706                         break;
707                 }
708                 
709                 c++;
710
711                 if (up->rpt_status == TSIP_PARSED_DLE_1) {
712                     up->rpt_cnt = 0;
713                         if (pp->sloppyclockflag & CLK_FLAG2) 
714                                 /* stamp it */
715                         get_systime(&pp->lastrec);
716                 }
717                 else if (up->rpt_status == TSIP_PARSED_EMPTY)
718                         up->rpt_cnt = 0;
719
720                 else if (up->rpt_cnt > BMAX) 
721                         up->rpt_status =TSIP_PARSED_EMPTY;
722
723                 if (up->rpt_status == TSIP_PARSED_FULL) 
724                         palisade_receive(peer);
725
726         } /* while chars in buffer */
727 }
728
729
730 /*
731  * Trigger the Palisade's event input, which is driven off the RTS
732  *
733  * Take a system time stamp to match the GPS time stamp.
734  *
735  */
736 long
737 HW_poll (
738 #ifdef PALISADE
739         pp      /* pointer to unit structure */
740         )
741         struct refclockproc * pp;       /* pointer to unit structure */
742 #else
743         struct refclockproc * pp        /* pointer to unit structure */
744         )
745 #endif
746 {       
747         int x;  /* state before & after RTS set */
748         struct palisade_unit *up;
749
750         up = (struct palisade_unit *) pp->unitptr;
751
752         /* read the current status, so we put things back right */
753         if (ioctl(pp->io.fd, TIOCMGET, &x) < 0) {
754 #ifdef DEBUG
755         if (debug)
756             printf("Palisade HW_poll: unit %d: GET %s\n", up->unit, strerror(errno));
757 #endif
758                 msyslog(LOG_ERR, "Palisade(%d) HW_poll: ioctl(fd,GET): %m", 
759                         up->unit);
760                 return -1;
761         }
762   
763         x |= TIOCM_RTS;        /* turn on RTS  */
764
765         /* Edge trigger */
766         if (ioctl(pp->io.fd, TIOCMSET, &x) < 0) { 
767 #ifdef DEBUG
768         if (debug)
769             printf("Palisade HW_poll: unit %d: SET \n", up->unit);
770 #endif
771                 msyslog(LOG_ERR,
772                         "Palisade(%d) HW_poll: ioctl(fd, SET, RTS_on): %m", 
773                         up->unit);
774                 return -1;
775         }
776
777         x &= ~TIOCM_RTS;        /* turn off RTS  */
778         
779         /* poll timestamp */
780         get_systime(&pp->lastrec);
781
782         if (ioctl(pp->io.fd, TIOCMSET, &x) == -1) {
783 #ifdef DEBUG
784         if (debug)
785             printf("Palisade HW_poll: unit %d: UNSET \n", up->unit);
786 #endif
787                 msyslog(LOG_ERR,
788                         "Palisade(%d) HW_poll: ioctl(fd, UNSET, RTS_off): %m", 
789                         up->unit);
790                 return -1;
791         }
792
793         return 0;
794 }
795
796 #if 0 /* unused */
797 /*
798  * this 'casts' a character array into a float
799  */
800 float
801 getfloat (
802 #ifdef PALISADE
803         bp
804         )
805         u_char *bp;
806 #else
807         u_char *bp
808         )
809 #endif
810 {
811         float sval;
812 #ifdef WORDS_BIGENDIAN 
813         ((char *) &sval)[0] = *bp++;
814         ((char *) &sval)[1] = *bp++;
815         ((char *) &sval)[2] = *bp++;
816         ((char *) &sval)[3] = *bp++;
817 #else
818         ((char *) &sval)[3] = *bp++;
819         ((char *) &sval)[2] = *bp++;
820         ((char *) &sval)[1] = *bp++;
821         ((char *) &sval)[0] = *bp;
822 #endif  /* ! XNTP_BIG_ENDIAN */ 
823         return sval;
824 }
825 #endif
826
827 /*
828  * this 'casts' a character array into a double
829  */
830 double
831 getdbl (
832 #ifdef PALISADE
833         bp
834         )
835         u_char *bp;
836 #else
837         u_char *bp
838         )
839 #endif
840 {
841         double dval;
842 #ifdef WORDS_BIGENDIAN 
843         ((char *) &dval)[0] = *bp++;
844         ((char *) &dval)[1] = *bp++;
845         ((char *) &dval)[2] = *bp++;
846         ((char *) &dval)[3] = *bp++;
847         ((char *) &dval)[4] = *bp++;
848         ((char *) &dval)[5] = *bp++;
849         ((char *) &dval)[6] = *bp++;
850         ((char *) &dval)[7] = *bp;
851 #else
852         ((char *) &dval)[7] = *bp++;
853         ((char *) &dval)[6] = *bp++;
854         ((char *) &dval)[5] = *bp++;
855         ((char *) &dval)[4] = *bp++;
856         ((char *) &dval)[3] = *bp++;
857         ((char *) &dval)[2] = *bp++;
858         ((char *) &dval)[1] = *bp++;
859         ((char *) &dval)[0] = *bp;
860 #endif  /* ! XNTP_BIG_ENDIAN */ 
861         return dval;
862 }
863
864 /*
865  * cast a 16 bit character array into a short (16 bit) int
866  */
867 short
868 getint (
869 #ifdef PALISADE
870         bp
871         )
872         u_char *bp;
873 #else
874         u_char *bp
875         )
876 #endif
877 {
878 return (short) (bp[1] + (bp[0] << 8));
879 }
880
881 #endif /* REFCLOCK */