diff options
Diffstat (limited to 'contrib/ntp/ntpd/refclock_palisade.c')
-rw-r--r-- | contrib/ntp/ntpd/refclock_palisade.c | 880 |
1 files changed, 880 insertions, 0 deletions
diff --git a/contrib/ntp/ntpd/refclock_palisade.c b/contrib/ntp/ntpd/refclock_palisade.c new file mode 100644 index 0000000..b9a0e2a --- /dev/null +++ b/contrib/ntp/ntpd/refclock_palisade.c @@ -0,0 +1,880 @@ +/* + * This software was developed by the Software and Component Technologies + * group of Trimble Navigation, Ltd. + * + * Copyright (c) 1997, 1998, 1999 Trimble Navigation Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Trimble Navigation, Ltd. + * 4. The name of Trimble Navigation Ltd. may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY TRIMBLE NAVIGATION LTD. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL TRIMBLE NAVIGATION LTD. BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * refclock_palisade - clock driver for the Trimble Palisade GPS + * timing receiver + * + * For detailed information on this program, please refer to the html + * Refclock 29 page accompanying the NTP distribution. + * + * for questions / bugs / comments, contact: + * sven_dietrich@trimble.com + * + * Sven-Thorsten Dietrich + * 645 North Mary Avenue + * Post Office Box 3642 + * Sunnyvale, CA 94088-3642 + * + * Version 2.45; July 14, 1999 + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#if defined(REFCLOCK) && (defined(PALISADE) || defined(CLOCK_PALISADE)) + +#include "refclock_palisade.h" +/* Table to get from month to day of the year */ +const int days_of_year [12] = { + 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 +}; + +#ifdef DEBUG +const char * Tracking_Status[15][15] = { + { "Doing Fixes\0" }, { "Good 1SV\0" }, { "Approx. 1SV\0" }, + {"Need Time\0" }, { "Need INIT\0" }, { "PDOP too High\0" }, + { "Bad 1SV\0" }, { "0SV Usable\0" }, { "1SV Usable\0" }, + { "2SV Usable\0" }, { "3SV Usable\0" }, { "No Integrity\0" }, + { "Diff Corr\0" }, { "Overdet Clock\0" }, { "Invalid\0" } }; +#endif + +/* + * Transfer vector + */ +struct refclock refclock_palisade = { + palisade_start, /* start up driver */ + palisade_shutdown, /* shut down driver */ + palisade_poll, /* transmit poll message */ + noentry, /* not used */ + noentry, /* initialize driver (not used) */ + noentry, /* not used */ + NOFLAGS /* not used */ +}; + + +/* + * palisade_start - open the devices and initialize data for processing + */ +static int +palisade_start ( +#ifdef PALISADE + unit, peer + ) + int unit; + struct peer *peer; +#else /* ANSI */ + int unit, + struct peer *peer + ) +#endif +{ + struct palisade_unit *up; + struct refclockproc *pp; + int fd; + char gpsdev[20]; + + struct termios tio; +#ifdef SYS_WINNT + (void) sprintf(gpsdev, "COM%d:", unit); +#else + (void) sprintf(gpsdev, DEVICE, unit); +#endif + /* + * Open serial port. + */ +#if defined PALISADE + fd = open(gpsdev, O_RDWR +#ifdef O_NONBLOCK + | O_NONBLOCK +#endif + ); +#else /* NTP 4.x */ + fd = refclock_open(gpsdev, SPEED232, LDISC_RAW); +#endif + if (fd <= 0) { +#ifdef DEBUG + printf("Palisade(%d) start: open %s failed\n", unit, gpsdev); +#endif + return 0; + } + + msyslog(LOG_NOTICE, "Palisade(%d) fd: %d dev: %s", unit, fd, + gpsdev); + +#if defined PALISADE + tio.c_cflag = (CS8|CLOCAL|CREAD|PARENB|PARODD); + tio.c_iflag = (IGNBRK); + tio.c_oflag = (0); + tio.c_lflag = (0); + + if (cfsetispeed(&tio, SPEED232) == -1) { + msyslog(LOG_ERR,"Palisade(%d) cfsetispeed(fd, &tio): %m",unit); +#ifdef DEBUG + printf("Palisade(%d) cfsetispeed(fd, &tio)\n",unit); +#endif + return 0; + } + if (cfsetospeed(&tio, SPEED232) == -1) { +#ifdef DEBUG + printf("Palisade(%d) cfsetospeed(fd, &tio)\n",unit); +#endif + msyslog(LOG_ERR,"Palisade(%d) cfsetospeed(fd, &tio): %m",unit); + return 0; + } +#else /* NTP 4.x */ + if (tcgetattr(fd, &tio) < 0) { + msyslog(LOG_ERR, + "Palisade(%d) tcgetattr(fd, &tio): %m",unit); +#ifdef DEBUG + printf("Palisade(%d) tcgetattr(fd, &tio)\n",unit); +#endif + return (0); + } + + tio.c_cflag |= (PARENB|PARODD); + tio.c_iflag &= ~ICRNL; +#endif /* NTP 4.x */ + + if (tcsetattr(fd, TCSANOW, &tio) == -1) { + msyslog(LOG_ERR, "Palisade(%d) tcsetattr(fd, &tio): %m",unit); +#ifdef DEBUG + printf("Palisade(%d) tcsetattr(fd, &tio)\n",unit); +#endif + return 0; + } + + /* + * Allocate and initialize unit structure + */ + up = (struct palisade_unit *) emalloc(sizeof(struct palisade_unit)); + + if (!(up)) { + msyslog(LOG_ERR, "Palisade(%d) emalloc: %m",unit); +#ifdef DEBUG + printf("Palisade(%d) emalloc\n",unit); +#endif + (void) close(fd); + return (0); + } + + memset((char *)up, 0, sizeof(struct palisade_unit)); + + pp = peer->procptr; + pp->io.clock_recv = palisade_io; + pp->io.srcclock = (caddr_t)peer; + pp->io.datalen = 0; + pp->io.fd = fd; + if (!io_addclock(&pp->io)) { +#ifdef DEBUG + printf("Palisade(%d) io_addclock\n",unit); +#endif + (void) close(fd); + free(up); + return (0); + } + + /* + * Initialize miscellaneous variables + */ + pp->unitptr = (caddr_t)up; + pp->clockdesc = DESCRIPTION; + + peer->precision = PRECISION; + peer->sstclktype = CTL_SST_TS_UHF; + peer->minpoll = TRMB_MINPOLL; + peer->maxpoll = TRMB_MAXPOLL; + memcpy((char *)&pp->refid, REFID, 4); + + up->leap_status = 0; + up->unit = (short) unit; + up->rpt_status = TSIP_PARSED_EMPTY; + up->rpt_cnt = 0; + + return 1; +} + + +/* + * palisade_shutdown - shut down the clock + */ +static void +palisade_shutdown ( +#ifdef PALISADE + unit, peer + ) + int unit; + struct peer *peer; +#else /* ANSI */ + int unit, + struct peer *peer + ) +#endif +{ + struct palisade_unit *up; + struct refclockproc *pp; + pp = peer->procptr; + up = (struct palisade_unit *)pp->unitptr; + io_closeclock(&pp->io); + free(up); +} + + + +/* + * unpack_date - get day and year from date + */ +int +day_of_year ( +#ifdef PALISADE + dt + ) + char * dt; +#else + char * dt + ) +#endif +{ + int day, mon, year; + + mon = dt[1]; + /* Check month is inside array bounds */ + if ((mon < 1) || (mon > 12)) + return -1; + + day = dt[0] + days_of_year[mon - 1]; + year = getint((u_char *) (dt + 2)); + + if ( !(year % 4) && ((year % 100) || + (!(year % 100) && !(year%400))) + &&(mon > 2)) + day ++; /* leap year and March or later */ + + return day; +} + + +/* + * TSIP_decode - decode the TSIP data packets + */ +int +TSIP_decode ( +#ifdef PALISADE + peer + ) + struct peer *peer; +#else + struct peer *peer + ) +#endif +{ + int st; + long secint; + double secs; + double secfrac; + unsigned short event = 0; + + struct palisade_unit *up; + struct refclockproc *pp; + + pp = peer->procptr; + up = (struct palisade_unit *)pp->unitptr; + + /* + * Check the time packet, decode its contents. + * If the timecode has invalid length or is not in + * proper format, declare bad format and exit. + */ + + if ((up->rpt_buf[0] == (char) 0x41) || + (up->rpt_buf[0] == (char) 0x46) || + (up->rpt_buf[0] == (char) 0x54) || + (up->rpt_buf[0] == (char) 0x4B) || + (up->rpt_buf[0] == (char) 0x6D)) { + + /* standard time packet - GPS time and GPS week number */ +#ifdef DEBUG + printf("Palisade Port B packets detected. Connect to Port A\n"); +#endif + + return 0; + } + + if (up->rpt_buf[0] == (char) 0x8f) { + /* + * Superpackets + */ + event = (unsigned short) (getint((u_char *) &mb(1)) & 0xffff); + if (!((pp->sloppyclockflag & CLK_FLAG2) || event)) + /* Ignore Packet */ + return 0; + + switch (mb(0) & 0xff) { + int GPS_UTC_Offset; + case PACKET_8F0B: + + if (up->polled <= 0) + return 0; + + if (up->rpt_cnt != LENCODE_8F0B) /* check length */ + break; + +#ifdef DEBUG +if (debug > 1) { + int ts; + double lat, lon, alt; + lat = getdbl((u_char *) &mb(42)) * R2D; + lon = getdbl((u_char *) &mb(50)) * R2D; + alt = getdbl((u_char *) &mb(58)); + + printf("TSIP_decode: unit %d: Latitude: %03.4f Longitude: %03.4f Alt: %05.2f m\n", + up->unit, lat,lon,alt); + printf("TSIP_decode: unit %d: Sats:", up->unit); + for (st = 66, ts = 0; st <= 73; st++) if (mb(st)) { + if (mb(st) > 0) ts++; + printf(" %02d", mb(st)); + } + printf(" : Tracking %d\n", ts); + } +#endif + + GPS_UTC_Offset = getint((u_char *) &mb(16)); + if (GPS_UTC_Offset == 0) { /* Check UTC offset */ +#ifdef DEBUG + printf("TSIP_decode: UTC Offset Unknown\n"); +#endif + break; + } + + secs = getdbl((u_char *) &mb(3)); + secint = (long) secs; + secfrac = secs - secint; /* 0.0 <= secfrac < 1.0 */ + + pp->usec = (long) (secfrac * 1000000); + + secint %= 86400; /* Only care about today */ + pp->hour = secint / 3600; + secint %= 3600; + pp->minute = secint / 60; + secint %= 60; + pp->second = secint % 60; + + if ((pp->day = day_of_year(&mb(11))) < 0) break; + + pp->year = getint((u_char *) &mb(13)); + +#ifdef DEBUG + if (debug > 1) + printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%06ld %02d/%02d/%04d UTC %02d\n", + up->unit, mb(0) & 0xff, event, pp->hour, pp->minute, + pp->second, pp->usec, mb(12), mb(11), pp->year, GPS_UTC_Offset); +#endif + /* Only use this packet when no + * 8F-AD's are being received + */ + + if (up->leap_status) { + up->leap_status = 0; + return 0; + } + + return 2; + break; + + case PACKET_NTP: + /* Palisade-NTP Packet */ + + if (up->rpt_cnt != LENCODE_NTP) /* check length */ + break; + + up->leap_status = mb(19); + + if (up->polled <= 0) + return 0; + + /* Check Tracking Status */ + st = mb(18); + if (st < 0 || st > 14) st = 14; + if ((st >= 2 && st <= 7) || st == 11 || st == 12) { +#ifdef DEBUG + printf("TSIP_decode: Not Tracking Sats : %s\n", + *Tracking_Status[st]); +#endif + refclock_report(peer, CEVNT_BADTIME); + up->polled = -1; + return 0; + break; + } + + if (up->leap_status & PALISADE_LEAP_PENDING) { + if (up->leap_status & PALISADE_UTC_TIME) + pp->leap = LEAP_ADDSECOND; + else + pp->leap = LEAP_DELSECOND; + } + else if (up->leap_status) + pp->leap = LEAP_NOWARNING; + + else { /* UTC flag is not set: + * Receiver may have been reset, and lost + * its UTC almanac data */ + pp->leap = LEAP_NOTINSYNC; +#ifdef DEBUG + printf("TSIP_decode: UTC Almanac unavailable: %d\n", + mb(19)); +#endif + refclock_report(peer, CEVNT_BADTIME); + up->polled = -1; + return 0; + } + + pp->usec = (long) (getdbl((u_char *) &mb(3)) * 1000000); + + if ((pp->day = day_of_year(&mb(14))) < 0) + break; + pp->year = getint((u_char *) &mb(16)); + pp->hour = mb(11); + pp->minute = mb(12); + pp->second = mb(13); + +#ifdef DEBUG + if (debug > 1) +printf("TSIP_decode: unit %d: %02X #%d %02d:%02d:%02d.%06ld %02d/%02d/%04d UTC %02x %s\n", + up->unit, mb(0) & 0xff, event, pp->hour, pp->minute, + pp->second, pp->usec, mb(15), mb(14), pp->year, + mb(19), *Tracking_Status[st]); +#endif + return 1; + break; + + default: + /* Ignore Packet */ + return 0; + } /* switch */ + }/* if 8F packets */ + + refclock_report(peer, CEVNT_BADREPLY); + up->polled = -1; +#ifdef DEBUG + printf("TSIP_decode: unit %d: bad packet %02x-%02x event %d len %d\n", + up->unit, up->rpt_buf[0] & 0xff, mb(0) & 0xff, + event, up->rpt_cnt); +#endif + return 0; +} + +/* + * palisade__receive - receive data from the serial interface + */ + +static void +palisade_receive ( +#ifdef PALISADE + peer + ) + struct peer * peer; +#else /* ANSI */ + struct peer * peer + ) +#endif +{ + struct palisade_unit *up; + struct refclockproc *pp; + + /* + * Initialize pointers and read the timecode and timestamp. + */ + pp = peer->procptr; + up = (struct palisade_unit *)pp->unitptr; + + if (! TSIP_decode(peer)) return; + + if (up->polled <= 0) + return; /* no poll pending, already received or timeout */ + + up->polled = 0; /* Poll reply received */ + pp->lencode = 0; /* clear time code */ +#ifdef DEBUG + if (debug) + printf( + "palisade_receive: unit %d: %4d %03d %02d:%02d:%02d.%06ld\n", + up->unit, pp->year, pp->day, pp->hour, pp->minute, + pp->second, pp->usec); +#endif + + /* + * Process the sample + * Generate timecode: YYYY DoY HH:MM:SS.microsec + * report and process + */ + + (void) sprintf(pp->a_lastcode,"%4d %03d %02d:%02d:%02d.%06ld", + pp->year,pp->day,pp->hour,pp->minute, pp->second,pp->usec); + pp->lencode = 24; + +#ifdef PALISADE + pp->lasttime = current_time; +#endif + if (!refclock_process(pp +#ifdef PALISADE + , PALISADE_SAMPLES, PALISADE_SAMPLES * 3 / 5 +#endif + )) { + refclock_report(peer, CEVNT_BADTIME); + +#ifdef DEBUG + printf("palisade_receive: unit %d: refclock_process failed!\n", + up->unit); +#endif + return; + } + + record_clock_stats(&peer->srcadr, pp->a_lastcode); + +#ifdef DEBUG + if (debug) + printf("palisade_receive: unit %d: %s\n", + up->unit, prettydate(&pp->lastrec)); +#endif + + refclock_receive(peer +#ifdef PALISADE + , &pp->offset, 0, pp->dispersion, + &pp->lastrec, &pp->lastrec, pp->leap +#endif + ); +} + + +/* + * palisade_poll - called by the transmit procedure + * + */ +static void +palisade_poll ( +#ifdef PALISADE + unit, peer + ) + int unit; + struct peer *peer; +#else + int unit, + struct peer *peer + ) +#endif +{ + struct palisade_unit *up; + struct refclockproc *pp; + + pp = peer->procptr; + up = (struct palisade_unit *)pp->unitptr; + + pp->polls++; + if (up->polled > 0) /* last reply never arrived or error */ + refclock_report(peer, CEVNT_TIMEOUT); + + up->polled = 2; /* synchronous packet + 1 event */ + +#ifdef DEBUG + if (debug) + printf("palisade_poll: unit %d: polling %s\n", unit, + (pp->sloppyclockflag & CLK_FLAG2) ? + "synchronous packet" : "event"); +#endif + + if (pp->sloppyclockflag & CLK_FLAG2) + return; /* using synchronous packet input */ + + if (HW_poll(pp) < 0) + refclock_report(peer, CEVNT_FAULT); +} + + +static void +palisade_io ( +#ifdef PALISADE + rbufp + ) + struct recvbuf *rbufp; +#else /* ANSI */ + struct recvbuf *rbufp + ) +#endif +{ + /* + * Initialize pointers and read the timecode and timestamp. + */ + struct palisade_unit *up; + struct refclockproc *pp; + struct peer *peer; + + char * c, * d; + + peer = (struct peer *)rbufp->recv_srcclock; + pp = peer->procptr; + up = (struct palisade_unit *)pp->unitptr; + + c = (char *) &rbufp->recv_space; + d = c + rbufp->recv_length; + + while (c != d) { + + /* Build time packet */ + switch (up->rpt_status) { + + case TSIP_PARSED_DLE_1: + switch (*c) + { + case 0: + case DLE: + case ETX: + up->rpt_status = TSIP_PARSED_EMPTY; + break; + + default: + up->rpt_status = TSIP_PARSED_DATA; + /* save packet ID */ + up->rpt_buf[0] = *c; + break; + } + break; + + case TSIP_PARSED_DATA: + if (*c == DLE) + up->rpt_status = TSIP_PARSED_DLE_2; + else + mb(up->rpt_cnt++) = *c; + break; + + case TSIP_PARSED_DLE_2: + if (*c == DLE) { + up->rpt_status = TSIP_PARSED_DATA; + mb(up->rpt_cnt++) = + *c; + } + else if (*c == ETX) + up->rpt_status = TSIP_PARSED_FULL; + else { + /* error: start new report packet */ + up->rpt_status = TSIP_PARSED_DLE_1; + up->rpt_buf[0] = *c; + } + break; + + case TSIP_PARSED_FULL: + case TSIP_PARSED_EMPTY: + default: + if ( *c != DLE) + up->rpt_status = TSIP_PARSED_EMPTY; + else + up->rpt_status = TSIP_PARSED_DLE_1; + break; + } + + c++; + + if (up->rpt_status == TSIP_PARSED_DLE_1) { + up->rpt_cnt = 0; + if (pp->sloppyclockflag & CLK_FLAG2) + /* stamp it */ + get_systime(&pp->lastrec); + } + else if (up->rpt_status == TSIP_PARSED_EMPTY) + up->rpt_cnt = 0; + + else if (up->rpt_cnt > BMAX) + up->rpt_status =TSIP_PARSED_EMPTY; + + if (up->rpt_status == TSIP_PARSED_FULL) + palisade_receive(peer); + + } /* while chars in buffer */ +} + + +/* + * Trigger the Palisade's event input, which is driven off the RTS + * + * Take a system time stamp to match the GPS time stamp. + * + */ +long +HW_poll ( +#ifdef PALISADE + pp /* pointer to unit structure */ + ) + struct refclockproc * pp; /* pointer to unit structure */ +#else + struct refclockproc * pp /* pointer to unit structure */ + ) +#endif +{ + int x; /* state before & after RTS set */ + struct palisade_unit *up; + + up = (struct palisade_unit *) pp->unitptr; + + /* read the current status, so we put things back right */ + if (ioctl(pp->io.fd, TIOCMGET, &x) < 0) { +#ifdef DEBUG + if (debug) + printf("Palisade HW_poll: unit %d: GET %s\n", up->unit, strerror(errno)); +#endif + msyslog(LOG_ERR, "Palisade(%d) HW_poll: ioctl(fd,GET): %m", + up->unit); + return -1; + } + + x |= TIOCM_RTS; /* turn on RTS */ + + /* Edge trigger */ + if (ioctl(pp->io.fd, TIOCMSET, &x) < 0) { +#ifdef DEBUG + if (debug) + printf("Palisade HW_poll: unit %d: SET \n", up->unit); +#endif + msyslog(LOG_ERR, + "Palisade(%d) HW_poll: ioctl(fd, SET, RTS_on): %m", + up->unit); + return -1; + } + + x &= ~TIOCM_RTS; /* turn off RTS */ + + /* poll timestamp */ + get_systime(&pp->lastrec); + + if (ioctl(pp->io.fd, TIOCMSET, &x) == -1) { +#ifdef DEBUG + if (debug) + printf("Palisade HW_poll: unit %d: UNSET \n", up->unit); +#endif + msyslog(LOG_ERR, + "Palisade(%d) HW_poll: ioctl(fd, UNSET, RTS_off): %m", + up->unit); + return -1; + } + + return 0; +} + +#if 0 /* unused */ +/* + * this 'casts' a character array into a float + */ +float +getfloat ( +#ifdef PALISADE + bp + ) + u_char *bp; +#else + u_char *bp + ) +#endif +{ + float sval; +#ifdef WORDS_BIGENDIAN + ((char *) &sval)[0] = *bp++; + ((char *) &sval)[1] = *bp++; + ((char *) &sval)[2] = *bp++; + ((char *) &sval)[3] = *bp++; +#else + ((char *) &sval)[3] = *bp++; + ((char *) &sval)[2] = *bp++; + ((char *) &sval)[1] = *bp++; + ((char *) &sval)[0] = *bp; +#endif /* ! XNTP_BIG_ENDIAN */ + return sval; +} +#endif + +/* + * this 'casts' a character array into a double + */ +double +getdbl ( +#ifdef PALISADE + bp + ) + u_char *bp; +#else + u_char *bp + ) +#endif +{ + double dval; +#ifdef WORDS_BIGENDIAN + ((char *) &dval)[0] = *bp++; + ((char *) &dval)[1] = *bp++; + ((char *) &dval)[2] = *bp++; + ((char *) &dval)[3] = *bp++; + ((char *) &dval)[4] = *bp++; + ((char *) &dval)[5] = *bp++; + ((char *) &dval)[6] = *bp++; + ((char *) &dval)[7] = *bp; +#else + ((char *) &dval)[7] = *bp++; + ((char *) &dval)[6] = *bp++; + ((char *) &dval)[5] = *bp++; + ((char *) &dval)[4] = *bp++; + ((char *) &dval)[3] = *bp++; + ((char *) &dval)[2] = *bp++; + ((char *) &dval)[1] = *bp++; + ((char *) &dval)[0] = *bp; +#endif /* ! XNTP_BIG_ENDIAN */ + return dval; +} + +/* + * cast a 16 bit character array into a short (16 bit) int + */ +short +getint ( +#ifdef PALISADE + bp + ) + u_char *bp; +#else + u_char *bp + ) +#endif +{ +return (short) (bp[1] + (bp[0] << 8)); +} + +#endif /* REFCLOCK */ |