]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/ntp/ntpd/refclock_tt560.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / ntp / ntpd / refclock_tt560.c
1 /*
2  * refclock_tt560 - clock driver for the TrueTime 560 IRIG-B decoder
3  */
4
5 #ifdef HAVE_CONFIG_H
6 #include <config.h>
7 #endif
8
9 #if defined(REFCLOCK) && defined(CLOCK_TT560)
10
11 #include "ntpd.h"
12 #include "ntp_io.h"
13 #include "ntp_refclock.h"
14 #include "ntp_unixtime.h"
15 #include "sys/tt560_api.h"
16 #include "ntp_stdlib.h"
17
18 #include <stdio.h>
19 #include <ctype.h>
20
21 /*
22  * This driver supports the TrueTime 560 IRIG-B decoder for the PCI bus.
23  */ 
24
25 /*
26  * TT560 interface definitions
27  */
28 #define DEVICE           "/dev/tt560%d" /* device name and unit */
29 #define PRECISION       (-20)   /* precision assumed (1 us) */
30 #define REFID           "IRIG"  /* reference ID */
31 #define DESCRIPTION     "TrueTime 560 IRIG-B PCI Decoder"
32
33 /*
34  * Unit control structure
35  */
36 struct tt560unit {
37         tt_mem_space_t   *tt_mem;       /* mapped address of PCI board */
38         time_freeze_reg_t tt560rawt;    /* data returned from PCI board */
39 };
40
41 typedef union byteswap_u
42 {
43     unsigned int long_word;
44     unsigned char byte[4];
45 } byteswap_t;
46
47 /*
48  * Function prototypes
49  */
50 static  int     tt560_start     P((int, struct peer *));
51 static  void    tt560_shutdown  P((int, struct peer *));
52 static  void    tt560_poll      P((int unit, struct peer *));
53
54 /*
55  * Transfer vector
56  */
57 struct  refclock refclock_tt560 = {
58         tt560_start,            /* clock_start    */
59         tt560_shutdown,         /* clock_shutdown */
60         tt560_poll,             /* clock_poll     */
61         noentry,                /* clock_control (not used) */
62         noentry,                /* clock_init    (not used) */
63         noentry,                /* clock_buginfo (not used) */
64         NOFLAGS                 /* clock_flags   (not used) */
65 };
66
67
68 /*
69  * tt560_start - open the TT560 device and initialize data for processing
70  */
71 static int
72 tt560_start(
73         int unit,
74         struct peer *peer
75         )
76 {
77         register struct tt560unit *up;
78         struct refclockproc *pp;
79         char device[20];
80         int     fd;
81         caddr_t membase;
82
83         /*
84          * Open TT560 device
85          */
86         (void)sprintf(device, DEVICE, unit);
87         fd = open(device, O_RDWR);
88         if (fd == -1) {
89                 msyslog(LOG_ERR, "tt560_start: open of %s: %m", device);
90                 return (0);
91         }
92
93         /*
94          * Map the device registers into user space.
95          */
96         membase = mmap ((caddr_t) 0, TTIME_MEMORY_SIZE,
97                         PROT_READ | PROT_WRITE,
98                         MAP_SHARED, fd, (off_t)0);
99
100         if (membase == (caddr_t) -1) {
101                 msyslog(LOG_ERR, "tt560_start: mapping of %s: %m", device);
102                 (void) close(fd);
103                 return (0);
104         }
105
106         /*
107          * Allocate and initialize unit structure
108          */
109         if (!(up = (struct tt560unit *) emalloc(sizeof(struct tt560unit)))) {
110                 (void) close(fd);
111                 return (0);
112         }
113         memset((char *)up, 0, sizeof(struct tt560unit));
114         up->tt_mem = (tt_mem_space_t *)membase;
115         pp = peer->procptr;
116         pp->io.clock_recv = noentry;
117         pp->io.srcclock = (caddr_t)peer;
118         pp->io.datalen = 0;
119         pp->io.fd = fd;
120         pp->unitptr = (caddr_t)up;
121
122         /*
123          * Initialize miscellaneous peer variables
124          */
125         peer->precision = PRECISION;
126         peer->burst = NSTAGE;
127         pp->clockdesc = DESCRIPTION;
128         memcpy((char *)&pp->refid, REFID, 4);
129         return (1);
130 }
131
132
133 /*
134  * tt560_shutdown - shut down the clock
135  */
136 static void
137 tt560_shutdown(
138         int unit,
139         struct peer *peer
140         )
141 {
142         register struct tt560unit *up;
143         struct refclockproc *pp;
144
145         pp = peer->procptr;
146         up = (struct tt560unit *)pp->unitptr;
147         io_closeclock(&pp->io);
148         free(up);
149 }
150
151
152 /*
153  * tt560_poll - called by the transmit procedure
154  */
155 static void
156 tt560_poll(
157         int unit,
158         struct peer *peer
159         )
160 {
161         register struct tt560unit *up;
162         struct refclockproc       *pp;
163         time_freeze_reg_t         *tp;
164         tt_mem_space_t            *mp;
165
166         int i;
167         unsigned int *p_time_t, *tt_mem_t;
168
169         /*
170          * This is the main routine. It snatches the time from the TT560
171          * board and tacks on a local timestamp.
172          */
173         pp = peer->procptr;
174         up = (struct tt560unit *)pp->unitptr;
175         mp = up->tt_mem;
176         tp = &up->tt560rawt;
177
178         p_time_t = (unsigned int *)tp;
179         tt_mem_t = (unsigned int *)&mp->time_freeze_reg;
180
181         *tt_mem_t = 0;          /* update the time freeze register */
182                                 /* and copy time stamp to memory */
183         for (i=0; i < TIME_FREEZE_REG_LEN; i++) {
184             *p_time_t = byte_swap(*tt_mem_t);
185              p_time_t++;
186              tt_mem_t++;
187         }
188
189         get_systime(&pp->lastrec);
190         pp->polls++;
191
192         /*
193          * We get down to business, check the timecode format and decode
194          * its contents. If the timecode has invalid length or is not in
195          * proper format, we declare bad format and exit. Note: we
196          * can't use the sec/usec conversion produced by the driver,
197          * since the year may be suspect. All format error checking is
198          * done by the sprintf() and sscanf() routines.
199          */
200         sprintf(pp->a_lastcode,
201             "%1x%1x%1x %1x%1x:%1x%1x:%1x%1x.%1x%1x%1x%1x%1x%1x %1x",
202             tp->hun_day,  tp->tens_day,  tp->unit_day,
203                           tp->tens_hour, tp->unit_hour,
204                           tp->tens_min,  tp->unit_min,
205                           tp->tens_sec,  tp->unit_sec,
206             tp->hun_ms,   tp->tens_ms,   tp->unit_ms,
207             tp->hun_us,   tp->tens_us,   tp->unit_us,
208             tp->status);
209             pp->lencode = strlen(pp->a_lastcode);
210 #ifdef DEBUG
211         if (debug)
212                 printf("tt560: time %s timecode %d %s\n",
213                    ulfptoa(&pp->lastrec, 6), pp->lencode,
214                    pp->a_lastcode);
215 #endif
216         if (sscanf(pp->a_lastcode, "%3d %2d:%2d:%2d.%6ld", 
217                   &pp->day, &pp->hour, &pp->minute, &pp->second, &pp->usec)
218             != 5) {
219                 refclock_report(peer, CEVNT_BADTIME);
220                 return;
221         }
222         if ((tp->status & 0x6) != 0x6)
223                 pp->leap = LEAP_NOTINSYNC;
224         else
225                 pp->leap = LEAP_NOWARNING;
226         if (!refclock_process(pp)) {
227                 refclock_report(peer, CEVNT_BADTIME);
228                 return;
229         }
230         if (peer->burst > 0)
231                 return;
232         if (pp->coderecv == pp->codeproc) {
233                 refclock_report(peer, CEVNT_TIMEOUT);
234                 return;
235         }
236         record_clock_stats(&peer->srcadr, pp->a_lastcode);
237         refclock_receive(peer);
238         peer->burst = NSTAGE;
239 }
240
241 /******************************************************************
242  *
243  *  byte_swap
244  *
245  *  Inputs: 32 bit integer
246  *
247  *  Output: byte swapped 32 bit integer.
248  *
249  *  This routine is used to compensate for the byte alignment
250  *  differences between big-endian and little-endian integers.
251  *
252  ******************************************************************/
253 static unsigned int
254 byte_swap(unsigned int input_num)
255 {
256     byteswap_t    byte_swap;
257     unsigned char temp;
258
259     byte_swap.long_word = input_num;
260
261     temp              = byte_swap.byte[3];
262     byte_swap.byte[3] = byte_swap.byte[0];
263     byte_swap.byte[0] = temp;
264
265     temp              = byte_swap.byte[2];
266     byte_swap.byte[2] = byte_swap.byte[1];
267     byte_swap.byte[1] = temp;
268
269     return (byte_swap.long_word);
270 }
271
272 #else
273 int refclock_tt560_bs;
274 #endif /* REFCLOCK */