diff options
Diffstat (limited to 'contrib/ntp/libparse')
36 files changed, 8676 insertions, 0 deletions
diff --git a/contrib/ntp/libparse/Makefile.am b/contrib/ntp/libparse/Makefile.am new file mode 100644 index 000000000000..c0f838b798a3 --- /dev/null +++ b/contrib/ntp/libparse/Makefile.am @@ -0,0 +1,93 @@ +#AUTOMAKE_OPTIONS = ../util/ansi2knr no-dependencies +# +# this is sick - i want the source to be compile with +# two time with different flags resulting different +# objects - still need to find a way to communicate +# that to automake/autoconf +# +# Frank Kardel +# +AUTOMAKE_OPTIONS = ../util/ansi2knr +noinst_LIBRARIES = @MAKE_LIBPARSE@ @MAKE_LIBPARSE_KERNEL@ +EXTRA_LIBRARIES = libparse.a libparse_kernel.a +EXTRA_PROGRAMS = parsestreams parsesolaris +noinst_PROGRAMS = @MAKE_PARSEKMODULE@ +CLEANFILES = libparse.a libparse_kernel.a + +libparse_a_SOURCES = parse.c \ + parse_conf.c \ + clk_meinberg.c \ + clk_schmid.c \ + clk_rawdcf.c \ + clk_trimtsip.c \ + clk_dcf7000.c \ + clk_trimtaip.c \ + clk_rcc8000.c \ + clk_hopf6021.c \ + clk_computime.c \ + clk_wharton.c \ + clk_varitext.c \ + data_mbg.c \ + info_trimble.c \ + trim_info.c + +libparse_kernel_a_SOURCES = kparse.c \ + kparse_conf.c \ + kclk_meinberg.c \ + kclk_schmid.c \ + kclk_rawdcf.c \ + kclk_trimtsip.c \ + kclk_dcf7000.c \ + kclk_trimtaip.c \ + kclk_rcc8000.c \ + kclk_hopf6021.c \ + kclk_computime.c \ + kclk_wharton.c \ + kclk_varitext.c + +INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/kernel +ETAGS_ARGS = Makefile.am + +EXTRA_DIST = parsesolaris.c parsestreams.c mkinfo_scmd.sed mkinfo_rcmd.sed info_trimble.c + +# +# create info_trimble.c +# +info_trimble.c: $(top_srcdir)/include/trimble.h mkinfo_rcmd.sed mkinfo_scmd.sed + @rm -f info_trimble.c + sed -n -f mkinfo_scmd.sed $(top_srcdir)/include/trimble.h > info_trimble.c || rm -f info_trimble.c + sed -n -f mkinfo_rcmd.sed $(top_srcdir)/include/trimble.h >> info_trimble.c || rm -f info_trimble.c + +# +# HACK following below... +# +kparse_conf.o: parse_conf.c +kparse.o: parse.c +kclk_rawdcf.o: clk_rawdcf.c +kclk_trimtsip.o: clk_trimtsip.c +kclk_meinberg.o: clk_meinberg.c +kclk_schmid.o: clk_schmid.c +kclk_rawdcf.o: clk_rawdcf.c +kclk_trimtsip.o: clk_trimtsip.c +kclk_dcf7000.o: clk_dcf7000.c +kclk_trimtaip.o: clk_trimtaip.c +kclk_rcc8000.o: clk_rcc8000.c +kclk_hopf6021.o: clk_hopf6021.c +kclk_computime.o: clk_computime.c +kclk_wharton.o: clk_wharton.c +kclk_varitext.o: clk_varitext.c + +parsestreams.loadable_module.o: $(parsestreams_OBJECTS) libparse_kernel.a ../libntp/libntp.a + $(LD) -r -o $@ $(parsestreams_OBJECTS) libparse_kernel.a ../libntp/libntp.a + +parse: $(parsesolaris_OBJECTS) libparse_kernel.a ../libntp/libntp.a + $(LD) -r -o $@ $(parsesolaris_OBJECTS) libparse_kernel.a ../libntp/libntp.a + +../libntp/libntp.a: + cd ../libntp && $(MAKE) + +parsesolaris.o: sys/systm.h + +sys/systm.h: + mkdir sys && \ + sed -e 's/ffs(long)/ffs(int)/' < /usr/include/sys/systm.h > sys/systm.h diff --git a/contrib/ntp/libparse/Makefile.in b/contrib/ntp/libparse/Makefile.in new file mode 100644 index 000000000000..44f3174fb255 --- /dev/null +++ b/contrib/ntp/libparse/Makefile.in @@ -0,0 +1,598 @@ +# Makefile.in generated automatically by automake 1.4a from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_FLAG = +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_alias = @build_alias@ +build_triplet = @build@ +host_alias = @host_alias@ +host_triplet = @host@ +target_alias = @target_alias@ +target_triplet = @target@ +AMTAR = @AMTAR@ +AMTARFLAGS = @AMTARFLAGS@ +AWK = @AWK@ +CC = @CC@ +CFLAGS = @CFLAGS@ +CHUTEST = @CHUTEST@ +CLKTEST = @CLKTEST@ +CPP = @CPP@ +DCFD = @DCFD@ +LDFLAGS = @LDFLAGS@ +LIBPARSE = @LIBPARSE@ +LIBRSAREF = @LIBRSAREF@ +LN_S = @LN_S@ +MAKEINFO = @MAKEINFO@ +MAKE_ADJTIMED = @MAKE_ADJTIMED@ +MAKE_CHECK_Y2K = @MAKE_CHECK_Y2K@ +MAKE_LIBPARSE = @MAKE_LIBPARSE@ +MAKE_LIBPARSE_KERNEL = @MAKE_LIBPARSE_KERNEL@ +MAKE_LIBRSAREF = @MAKE_LIBRSAREF@ +MAKE_NTPTIME = @MAKE_NTPTIME@ +MAKE_PARSEKMODULE = @MAKE_PARSEKMODULE@ +MAKE_TICKADJ = @MAKE_TICKADJ@ +PACKAGE = @PACKAGE@ +PATH_SH = @PATH_SH@ +PROPDELAY = @PROPDELAY@ +RANLIB = @RANLIB@ +RSAREF = @RSAREF@ +TESTDCF = @TESTDCF@ +U = @U@ +VERSION = @VERSION@ + +#AUTOMAKE_OPTIONS = ../util/ansi2knr no-dependencies +# +# this is sick - i want the source to be compile with +# two time with different flags resulting different +# objects - still need to find a way to communicate +# that to automake/autoconf +# +# Frank Kardel +# + + +AUTOMAKE_OPTIONS = ../util/ansi2knr +noinst_LIBRARIES = @MAKE_LIBPARSE@ @MAKE_LIBPARSE_KERNEL@ +EXTRA_LIBRARIES = libparse.a libparse_kernel.a +EXTRA_PROGRAMS = parsestreams parsesolaris +noinst_PROGRAMS = @MAKE_PARSEKMODULE@ +CLEANFILES = libparse.a libparse_kernel.a + +libparse_a_SOURCES = parse.c \ + parse_conf.c \ + clk_meinberg.c \ + clk_schmid.c \ + clk_rawdcf.c \ + clk_trimtsip.c \ + clk_dcf7000.c \ + clk_trimtaip.c \ + clk_rcc8000.c \ + clk_hopf6021.c \ + clk_computime.c \ + clk_wharton.c \ + clk_varitext.c \ + data_mbg.c \ + info_trimble.c \ + trim_info.c + + +libparse_kernel_a_SOURCES = kparse.c \ + kparse_conf.c \ + kclk_meinberg.c \ + kclk_schmid.c \ + kclk_rawdcf.c \ + kclk_trimtsip.c \ + kclk_dcf7000.c \ + kclk_trimtaip.c \ + kclk_rcc8000.c \ + kclk_hopf6021.c \ + kclk_computime.c \ + kclk_wharton.c \ + kclk_varitext.c + + +INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/kernel +ETAGS_ARGS = Makefile.am + +EXTRA_DIST = parsesolaris.c parsestreams.c mkinfo_scmd.sed mkinfo_rcmd.sed info_trimble.c +subdir = libparse +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../config.h +CONFIG_CLEAN_FILES = +LIBRARIES = $(noinst_LIBRARIES) + + +DEFS = @DEFS@ -I. -I$(srcdir) -I.. +CPPFLAGS = @CPPFLAGS@ +LIBS = @LIBS@ +ANSI2KNR = ../util/ansi2knr +libparse_a_LIBADD = +am_libparse_a_OBJECTS = parse$U.o parse_conf$U.o clk_meinberg$U.o \ +clk_schmid$U.o clk_rawdcf$U.o clk_trimtsip$U.o clk_dcf7000$U.o \ +clk_trimtaip$U.o clk_rcc8000$U.o clk_hopf6021$U.o clk_computime$U.o \ +clk_wharton$U.o clk_varitext$U.o data_mbg$U.o info_trimble$U.o \ +trim_info$U.o +libparse_a_OBJECTS = $(am_libparse_a_OBJECTS) +libparse_kernel_a_LIBADD = +am_libparse_kernel_a_OBJECTS = kparse$U.o kparse_conf$U.o \ +kclk_meinberg$U.o kclk_schmid$U.o kclk_rawdcf$U.o kclk_trimtsip$U.o \ +kclk_dcf7000$U.o kclk_trimtaip$U.o kclk_rcc8000$U.o kclk_hopf6021$U.o \ +kclk_computime$U.o kclk_wharton$U.o kclk_varitext$U.o +libparse_kernel_a_OBJECTS = $(am_libparse_kernel_a_OBJECTS) +AR = ar +PROGRAMS = $(noinst_PROGRAMS) + +parsesolaris_SOURCES = parsesolaris.c +parsesolaris_OBJECTS = parsesolaris$U.o +parsesolaris_LDADD = $(LDADD) +parsesolaris_DEPENDENCIES = +parsesolaris_LDFLAGS = +parsestreams_SOURCES = parsestreams.c +parsestreams_OBJECTS = parsestreams$U.o +parsestreams_LDADD = $(LDADD) +parsestreams_DEPENDENCIES = +parsestreams_LDFLAGS = +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ +DIST_SOURCES = $(libparse_a_SOURCES) $(libparse_kernel_a_SOURCES) \ +parsesolaris.c parsestreams.c +DIST_COMMON = README Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +GZIP_ENV = --best +SOURCES = $(libparse_a_SOURCES) $(libparse_kernel_a_SOURCES) parsesolaris.c parsestreams.c +OBJECTS = $(am_libparse_a_OBJECTS) $(am_libparse_kernel_a_OBJECTS) parsesolaris$U.o parsestreams$U.o + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .c .o +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps libparse/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +mostlyclean-noinstLIBRARIES: + +clean-noinstLIBRARIES: + -test -z "$(noinst_LIBRARIES)" || rm -f $(noinst_LIBRARIES) + +distclean-noinstLIBRARIES: + +maintainer-clean-noinstLIBRARIES: + +.c.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: +../util/ansi2knr: ../util/ansi2knr.o + cd ../util && $(MAKE) $(AM_MAKEFLAGS) ansi2knr + +../util/ansi2knr.o: + cd ../util && $(MAKE) $(AM_MAKEFLAGS) ansi2knr.o + + +mostlyclean-kr: + -rm -f *_.c + +clean-kr: + +distclean-kr: + +maintainer-clean-kr: +parse$U.o: +parse_conf$U.o: +clk_meinberg$U.o: +clk_schmid$U.o: +clk_rawdcf$U.o: +clk_trimtsip$U.o: +clk_dcf7000$U.o: +clk_trimtaip$U.o: +clk_rcc8000$U.o: +clk_hopf6021$U.o: +clk_computime$U.o: +clk_wharton$U.o: +clk_varitext$U.o: +data_mbg$U.o: +info_trimble$U.o: +trim_info$U.o: + +libparse.a: $(libparse_a_OBJECTS) $(libparse_a_DEPENDENCIES) + -rm -f libparse.a + $(AR) cru libparse.a $(libparse_a_OBJECTS) $(libparse_a_LIBADD) + $(RANLIB) libparse.a +kparse$U.o: +kparse_conf$U.o: +kclk_meinberg$U.o: +kclk_schmid$U.o: +kclk_rawdcf$U.o: +kclk_trimtsip$U.o: +kclk_dcf7000$U.o: +kclk_trimtaip$U.o: +kclk_rcc8000$U.o: +kclk_hopf6021$U.o: +kclk_computime$U.o: +kclk_wharton$U.o: +kclk_varitext$U.o: + +libparse_kernel.a: $(libparse_kernel_a_OBJECTS) $(libparse_kernel_a_DEPENDENCIES) + -rm -f libparse_kernel.a + $(AR) cru libparse_kernel.a $(libparse_kernel_a_OBJECTS) $(libparse_kernel_a_LIBADD) + $(RANLIB) libparse_kernel.a + +mostlyclean-noinstPROGRAMS: + +clean-noinstPROGRAMS: + -test -z "$(noinst_PROGRAMS)" || rm -f $(noinst_PROGRAMS) + +distclean-noinstPROGRAMS: + +maintainer-clean-noinstPROGRAMS: +parsesolaris$U.o: + +parsesolaris: $(parsesolaris_OBJECTS) $(parsesolaris_DEPENDENCIES) + @rm -f parsesolaris + $(LINK) $(parsesolaris_LDFLAGS) $(parsesolaris_OBJECTS) $(parsesolaris_LDADD) $(LIBS) +parsestreams$U.o: + +parsestreams: $(parsestreams_OBJECTS) $(parsestreams_DEPENDENCIES) + @rm -f parsestreams + $(LINK) $(parsestreams_LDFLAGS) $(parsestreams_OBJECTS) $(parsestreams_LDADD) $(LIBS) +clk_computime_.c: clk_computime.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/clk_computime.c; then echo $(srcdir)/clk_computime.c; else echo clk_computime.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > clk_computime_.c +clk_dcf7000_.c: clk_dcf7000.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/clk_dcf7000.c; then echo $(srcdir)/clk_dcf7000.c; else echo clk_dcf7000.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > clk_dcf7000_.c +clk_hopf6021_.c: clk_hopf6021.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/clk_hopf6021.c; then echo $(srcdir)/clk_hopf6021.c; else echo clk_hopf6021.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > clk_hopf6021_.c +clk_meinberg_.c: clk_meinberg.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/clk_meinberg.c; then echo $(srcdir)/clk_meinberg.c; else echo clk_meinberg.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > clk_meinberg_.c +clk_rawdcf_.c: clk_rawdcf.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/clk_rawdcf.c; then echo $(srcdir)/clk_rawdcf.c; else echo clk_rawdcf.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > clk_rawdcf_.c +clk_rcc8000_.c: clk_rcc8000.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/clk_rcc8000.c; then echo $(srcdir)/clk_rcc8000.c; else echo clk_rcc8000.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > clk_rcc8000_.c +clk_schmid_.c: clk_schmid.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/clk_schmid.c; then echo $(srcdir)/clk_schmid.c; else echo clk_schmid.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > clk_schmid_.c +clk_trimtaip_.c: clk_trimtaip.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/clk_trimtaip.c; then echo $(srcdir)/clk_trimtaip.c; else echo clk_trimtaip.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > clk_trimtaip_.c +clk_trimtsip_.c: clk_trimtsip.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/clk_trimtsip.c; then echo $(srcdir)/clk_trimtsip.c; else echo clk_trimtsip.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > clk_trimtsip_.c +clk_varitext_.c: clk_varitext.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/clk_varitext.c; then echo $(srcdir)/clk_varitext.c; else echo clk_varitext.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > clk_varitext_.c +clk_wharton_.c: clk_wharton.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/clk_wharton.c; then echo $(srcdir)/clk_wharton.c; else echo clk_wharton.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > clk_wharton_.c +data_mbg_.c: data_mbg.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/data_mbg.c; then echo $(srcdir)/data_mbg.c; else echo data_mbg.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > data_mbg_.c +info_trimble_.c: info_trimble.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/info_trimble.c; then echo $(srcdir)/info_trimble.c; else echo info_trimble.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > info_trimble_.c +kclk_computime_.c: kclk_computime.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/kclk_computime.c; then echo $(srcdir)/kclk_computime.c; else echo kclk_computime.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > kclk_computime_.c +kclk_dcf7000_.c: kclk_dcf7000.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/kclk_dcf7000.c; then echo $(srcdir)/kclk_dcf7000.c; else echo kclk_dcf7000.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > kclk_dcf7000_.c +kclk_hopf6021_.c: kclk_hopf6021.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/kclk_hopf6021.c; then echo $(srcdir)/kclk_hopf6021.c; else echo kclk_hopf6021.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > kclk_hopf6021_.c +kclk_meinberg_.c: kclk_meinberg.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/kclk_meinberg.c; then echo $(srcdir)/kclk_meinberg.c; else echo kclk_meinberg.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > kclk_meinberg_.c +kclk_rawdcf_.c: kclk_rawdcf.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/kclk_rawdcf.c; then echo $(srcdir)/kclk_rawdcf.c; else echo kclk_rawdcf.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > kclk_rawdcf_.c +kclk_rcc8000_.c: kclk_rcc8000.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/kclk_rcc8000.c; then echo $(srcdir)/kclk_rcc8000.c; else echo kclk_rcc8000.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > kclk_rcc8000_.c +kclk_schmid_.c: kclk_schmid.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/kclk_schmid.c; then echo $(srcdir)/kclk_schmid.c; else echo kclk_schmid.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > kclk_schmid_.c +kclk_trimtaip_.c: kclk_trimtaip.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/kclk_trimtaip.c; then echo $(srcdir)/kclk_trimtaip.c; else echo kclk_trimtaip.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > kclk_trimtaip_.c +kclk_trimtsip_.c: kclk_trimtsip.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/kclk_trimtsip.c; then echo $(srcdir)/kclk_trimtsip.c; else echo kclk_trimtsip.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > kclk_trimtsip_.c +kclk_varitext_.c: kclk_varitext.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/kclk_varitext.c; then echo $(srcdir)/kclk_varitext.c; else echo kclk_varitext.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > kclk_varitext_.c +kclk_wharton_.c: kclk_wharton.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/kclk_wharton.c; then echo $(srcdir)/kclk_wharton.c; else echo kclk_wharton.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > kclk_wharton_.c +kparse_.c: kparse.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/kparse.c; then echo $(srcdir)/kparse.c; else echo kparse.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > kparse_.c +kparse_conf_.c: kparse_conf.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/kparse_conf.c; then echo $(srcdir)/kparse_conf.c; else echo kparse_conf.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > kparse_conf_.c +parse_.c: parse.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/parse.c; then echo $(srcdir)/parse.c; else echo parse.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > parse_.c +parse_conf_.c: parse_conf.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/parse_conf.c; then echo $(srcdir)/parse_conf.c; else echo parse_conf.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > parse_conf_.c +parsesolaris_.c: parsesolaris.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/parsesolaris.c; then echo $(srcdir)/parsesolaris.c; else echo parsesolaris.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > parsesolaris_.c +parsestreams_.c: parsestreams.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/parsestreams.c; then echo $(srcdir)/parsestreams.c; else echo parsestreams.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > parsestreams_.c +trim_info_.c: trim_info.c $(ANSI2KNR) + $(CPP) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) `if test -f $(srcdir)/trim_info.c; then echo $(srcdir)/trim_info.c; else echo trim_info.c; fi` | sed 's/^# \([0-9]\)/#line \1/' | $(ANSI2KNR) > trim_info_.c +clk_computime_.o clk_dcf7000_.o clk_hopf6021_.o clk_meinberg_.o \ +clk_rawdcf_.o clk_rcc8000_.o clk_schmid_.o clk_trimtaip_.o \ +clk_trimtsip_.o clk_varitext_.o clk_wharton_.o data_mbg_.o \ +info_trimble_.o kclk_computime_.o kclk_dcf7000_.o kclk_hopf6021_.o \ +kclk_meinberg_.o kclk_rawdcf_.o kclk_rcc8000_.o kclk_schmid_.o \ +kclk_trimtaip_.o kclk_trimtsip_.o kclk_varitext_.o kclk_wharton_.o \ +kparse_.o kparse_conf_.o parse_.o parse_conf_.o parsesolaris_.o \ +parsestreams_.o trim_info_.o : $(ANSI2KNR) + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + ${AWK:-awk} ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + ${AWK:-awk} ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done +clk_computime.o clk_computime.lo: clk_computime.c ../config.h +clk_dcf7000.o clk_dcf7000.lo: clk_dcf7000.c ../config.h +clk_hopf6021.o clk_hopf6021.lo: clk_hopf6021.c ../config.h +clk_meinberg.o clk_meinberg.lo: clk_meinberg.c ../config.h +clk_rawdcf.o clk_rawdcf.lo: clk_rawdcf.c ../config.h +clk_rcc8000.o clk_rcc8000.lo: clk_rcc8000.c ../config.h +clk_schmid.o clk_schmid.lo: clk_schmid.c ../config.h +clk_trimtaip.o clk_trimtaip.lo: clk_trimtaip.c ../config.h +clk_trimtsip.o clk_trimtsip.lo: clk_trimtsip.c ../config.h +clk_varitext.o clk_varitext.lo: clk_varitext.c ../config.h +clk_wharton.o clk_wharton.lo: clk_wharton.c ../config.h +data_mbg.o data_mbg.lo: data_mbg.c ../include/ntp_types.h \ + ../include/ntp_machine.h ../config.h ../include/ntp_proto.h \ + ../include/ntp_stdlib.h ../include/ntp_string.h \ + ../include/l_stdlib.h ../include/ntp_fp.h \ + ../include/mbg_gps166.h ../include/binio.h \ + ../include/ieee754io.h +info_trimble.o info_trimble.lo: info_trimble.c ../include/ntp_types.h \ + ../include/ntp_machine.h ../config.h ../include/ntp_proto.h \ + ../include/ntpd.h ../include/ntp_syslog.h ../include/ntp_fp.h \ + ../include/ntp.h ../include/ntp_malloc.h \ + ../include/ntp_refclock.h ../include/recvbuff.h \ + ../include/trimble.h +kclk_computime.o kclk_computime.lo: kclk_computime.c clk_computime.c \ + ../config.h +kclk_dcf7000.o kclk_dcf7000.lo: kclk_dcf7000.c clk_dcf7000.c ../config.h +kclk_hopf6021.o kclk_hopf6021.lo: kclk_hopf6021.c clk_hopf6021.c \ + ../config.h +kclk_meinberg.o kclk_meinberg.lo: kclk_meinberg.c clk_meinberg.c \ + ../config.h +kclk_rawdcf.o kclk_rawdcf.lo: kclk_rawdcf.c clk_rawdcf.c ../config.h +kclk_rcc8000.o kclk_rcc8000.lo: kclk_rcc8000.c clk_rcc8000.c ../config.h +kclk_schmid.o kclk_schmid.lo: kclk_schmid.c clk_schmid.c ../config.h +kclk_trimtaip.o kclk_trimtaip.lo: kclk_trimtaip.c clk_trimtaip.c \ + ../config.h +kclk_trimtsip.o kclk_trimtsip.lo: kclk_trimtsip.c clk_trimtsip.c \ + ../config.h +kclk_varitext.o kclk_varitext.lo: kclk_varitext.c clk_varitext.c \ + ../config.h +kclk_wharton.o kclk_wharton.lo: kclk_wharton.c clk_wharton.c ../config.h +kparse.o kparse.lo: kparse.c parse.c ../config.h +kparse_conf.o kparse_conf.lo: kparse_conf.c parse_conf.c ../config.h +parse.o parse.lo: parse.c ../config.h +parse_conf.o parse_conf.lo: parse_conf.c ../config.h +parsesolaris.o parsesolaris.lo: parsesolaris.c sys/systm.h \ + ../include/ntp_fp.h ../include/ntp_types.h \ + ../include/ntp_machine.h ../config.h ../include/ntp_proto.h \ + ../include/parse.h ../include/parse_conf.h \ + ../kernel/sys/parsestreams.h ../kernel/sys/ppsclock.h \ + ../include/ntp_string.h + +trim_info.o trim_info.lo: trim_info.c ../include/ntp_types.h \ + ../include/ntp_machine.h ../config.h ../include/ntp_proto.h \ + ../include/trimble.h + +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: +install-exec: install-exec-am + +install-data-am: +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: +uninstall: uninstall-am +all-am: Makefile $(LIBRARIES) $(PROGRAMS) +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install +installdirs: + + +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-noinstLIBRARIES mostlyclean-compile \ + mostlyclean-kr mostlyclean-noinstPROGRAMS \ + mostlyclean-tags mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-noinstLIBRARIES clean-compile clean-kr \ + clean-noinstPROGRAMS clean-tags clean-generic \ + mostlyclean-am + +clean: clean-am + +distclean-am: distclean-noinstLIBRARIES distclean-compile distclean-kr \ + distclean-noinstPROGRAMS distclean-tags \ + distclean-generic clean-am + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-noinstLIBRARIES \ + maintainer-clean-compile maintainer-clean-kr \ + maintainer-clean-noinstPROGRAMS maintainer-clean-tags \ + maintainer-clean-generic distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: mostlyclean-noinstLIBRARIES distclean-noinstLIBRARIES \ +clean-noinstLIBRARIES maintainer-clean-noinstLIBRARIES \ +mostlyclean-compile distclean-compile clean-compile \ +maintainer-clean-compile mostlyclean-kr distclean-kr clean-kr \ +maintainer-clean-kr mostlyclean-noinstPROGRAMS distclean-noinstPROGRAMS \ +clean-noinstPROGRAMS maintainer-clean-noinstPROGRAMS tags \ +mostlyclean-tags distclean-tags clean-tags maintainer-clean-tags \ +distdir info-am info dvi-am dvi check check-am installcheck-am \ +installcheck install-exec-am install-exec install-data-am install-data \ +install-am install uninstall-am uninstall all-redirect all-am all \ +install-strip installdirs mostlyclean-generic distclean-generic \ +clean-generic maintainer-clean-generic clean mostlyclean distclean \ +maintainer-clean + + +# +# create info_trimble.c +# +info_trimble.c: $(top_srcdir)/include/trimble.h mkinfo_rcmd.sed mkinfo_scmd.sed + @rm -f info_trimble.c + sed -n -f mkinfo_scmd.sed $(top_srcdir)/include/trimble.h > info_trimble.c || rm -f info_trimble.c + sed -n -f mkinfo_rcmd.sed $(top_srcdir)/include/trimble.h >> info_trimble.c || rm -f info_trimble.c + +# +# HACK following below... +# +kparse_conf.o: parse_conf.c +kparse.o: parse.c +kclk_rawdcf.o: clk_rawdcf.c +kclk_trimtsip.o: clk_trimtsip.c +kclk_meinberg.o: clk_meinberg.c +kclk_schmid.o: clk_schmid.c +kclk_rawdcf.o: clk_rawdcf.c +kclk_trimtsip.o: clk_trimtsip.c +kclk_dcf7000.o: clk_dcf7000.c +kclk_trimtaip.o: clk_trimtaip.c +kclk_rcc8000.o: clk_rcc8000.c +kclk_hopf6021.o: clk_hopf6021.c +kclk_computime.o: clk_computime.c +kclk_wharton.o: clk_wharton.c +kclk_varitext.o: clk_varitext.c + +parsestreams.loadable_module.o: $(parsestreams_OBJECTS) libparse_kernel.a ../libntp/libntp.a + $(LD) -r -o $@ $(parsestreams_OBJECTS) libparse_kernel.a ../libntp/libntp.a + +parse: $(parsesolaris_OBJECTS) libparse_kernel.a ../libntp/libntp.a + $(LD) -r -o $@ $(parsesolaris_OBJECTS) libparse_kernel.a ../libntp/libntp.a + +../libntp/libntp.a: + cd ../libntp && $(MAKE) + +parsesolaris.o: sys/systm.h + +sys/systm.h: + mkdir sys && \ + sed -e 's/ffs(long)/ffs(int)/' < /usr/include/sys/systm.h > sys/systm.h + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/contrib/ntp/libparse/README b/contrib/ntp/libparse/README new file mode 100644 index 000000000000..3484f9a935b3 --- /dev/null +++ b/contrib/ntp/libparse/README @@ -0,0 +1,96 @@ +PARSE reference clock driver: + +This directory contains the files making up the parser for +the parse refclock driver. For reasonably sane clocks this refclock +drivers allows a refclock implementation by just providing a +conversion routine and the appropriate NTP parameters. Refclock +support can run as low a 3k code with the parse refclock driver. + +The modules in here are designed to live in two worlds. In userlevel +as part of the xntp daemon and in kernel land as part of a STREAMS module +or, if someone gets to it, as part of a line discipline. Currently only +SunOS4.x/SunOS5.x STREAMS are supported (volunteers for other vendors like HP?). +This structure means, that refclock_parse can work with or without kernel +support. Kernelsupport increases accuracy tremendingly. The current restriction +of the parse driver is that it only supports SYSV type ttys and that kernel +support is only available for Suns right now. + +Three kernel modules are part of this directory. These work only on +SunOS (SunOS4 and SunOS5). + + SunOS4 (aka Solaris 1.x): + parsestreams.loadable_module.o - standard parse module for SunOS 4 + + Both modules can be loaded via modload <modulename>. + + SunOS5 (aka Solaris 2.x): + parse - auto loadable streams module + + To install just drop "parse" into /kernel/strmod and + start the daemon (SunOS5 will do the rest). + +The structure of the parse reference clock driver is as follows: + + xntpd - contains NTP implementation and calls a reference clock + 127.127.8.x which is implemented by + refclock_parse.c + - which contains several refclock decriptions. These are + selected by the x part of the refclock address. + The lower two bits specify the device to use. Thus the + value (x % 4) determines the device to open + (/dev/refclock-0 - /dev/refclock-3). + + The kind of clock is selected by the mode parameter. This parameter + selects the clock type which deterimines how I/O is done, + the tty parameters and the NTP parameters. + + refclock_parse operates on an abstract reference clock + that delivers time stamps and stati. Offsets and sychron- + isation information is derived from this data and passed + on to refclock_receive of xntp which uses that data for + syncronisation. + + The abstract reference clock is generated by the parse* + routines. They parse the incoming data stream from the + clock and convert it to the appropriate time stamps. + The data is also mapped int the abstract clock states + POWERUP - clock has no valid phase and time code + information + + NOSYNC - Time code is not confirmed, phase is probably + ok. + SYNC - Time code and phase are correct. + + A clock is trusted for a certain time (type parameter) when + it leaves the SYNC state. This is derived from the + observation that quite a few clocks can still generate good + time code information when losing contact to their + synchronisation source. When the clock does not reagain + synchronisation in that trust period it will be deemed + unsynchronised until it regains synchronisation. The same + will happen if xntp sees the clock unsynchronised at + startup. + + The upper bit of x specifies that all samples delivered + from the clock should be used to discipline the NTP + loopfilter. For clock with accurate once a second time + information this means big improvements for time keeping. + A prerequisite for passing on the time stamps to + the loopfilter is, that the clock is in synchronised state. + + parse.c These are the general routines to parse the incoming data + stream. Usually these routines should not require + modification. + + clk_*.c These files hole the conversion code for the time stamps + and the description how the time code can be parsed and + where the time stamps are to be taken. + If you want to add a new clock type this is the file + you need to write in addition to mention it in + parse_conf.c and setting up the NTP and TTY parameters + in refclock_parse.c. + +Further information can be found in parse/README.parse and the various source +files. + +Frank Kardel diff --git a/contrib/ntp/libparse/clk_computime.c b/contrib/ntp/libparse/clk_computime.c new file mode 100644 index 000000000000..8e050c00fcad --- /dev/null +++ b/contrib/ntp/libparse/clk_computime.c @@ -0,0 +1,194 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_COMPUTIME) +/* + * /src/NTP/ntp-4/libparse/clk_computime.c,v 4.5 1998/06/14 21:09:34 kardel RELEASE_19990228_A + * + * clk_computime.c,v 4.5 1998/06/14 21:09:34 kardel RELEASE_19990228_A + * + * Supports Diem's Computime Radio Clock + * + * Used the Meinberg clock as a template for Diem's Computime Radio Clock + * + * adapted by Alois Camenzind <alois.camenzind@ubs.ch> + * + * Copyright (C) 1992-1998 by Frank Kardel + * Friedrich-Alexander Universität Erlangen-Nürnberg, Germany + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + */ + + +#include <sys/types.h> +#include <sys/time.h> + +#include "ntp_fp.h" +#include "ntp_unixtime.h" +#include "ntp_calendar.h" +#include "ntp_stdlib.h" + +#include "parse.h" + +#ifndef PARSESTREAM +#include <stdio.h> +#else +#include "sys/parsestreams.h" +extern void printf P((const char *, ...)); +#endif + +/* + * The Computime receiver sends a datagram in the following format every minute + * + * Timestamp T:YY:MM:MD:WD:HH:MM:SSCRLF + * Pos 0123456789012345678901 2 3 + * 0000000000111111111122 2 2 + * Parse T: : : : : : : rn + * + * T Startcharacter "T" specifies start of the timestamp + * YY Year MM Month 1-12 + * MD Day of the month + * WD Day of week + * HH Hour + * MM Minute + * SS Second + * CR Carriage return + * LF Linefeed + * + */ + +static struct format computime_fmt = +{ + { + {8, 2}, {5, 2}, {2, 2}, /* day, month, year */ + {14, 2}, {17, 2}, {20, 2}, /* hour, minute, second */ + {11, 2}, /* dayofweek, */ + }, + (const unsigned char *)"T: : : : : : : \r\n", + 0 +}; + +static u_long cvt_computime P((unsigned char *, int, struct format *, clocktime_t *, void *)); +static unsigned long inp_computime P((parse_t *, unsigned int, timestamp_t *)); + +clockformat_t clock_computime = +{ + inp_computime, /* Computime input handling */ + cvt_computime, /* Computime conversion */ + 0, /* no PPS monitoring */ + (void *)&computime_fmt, /* conversion configuration */ + "Diem's Computime Radio Clock", /* Computime Radio Clock */ + 24, /* string buffer */ + 0 /* no private data (complete pakets) */ +}; + +/* + * cvt_computime + * + * convert simple type format + */ +static u_long +cvt_computime( + unsigned char *buffer, + int size, + struct format *format, + clocktime_t *clock_time, + void *local + ) +{ + + if (!Strok(buffer, format->fixed_string)) { + return CVT_NONE; + } else { + if (Stoi(&buffer[format->field_offsets[O_DAY].offset], &clock_time->day, + format->field_offsets[O_DAY].length) || + Stoi(&buffer[format->field_offsets[O_MONTH].offset], &clock_time->month, + format->field_offsets[O_MONTH].length) || + Stoi(&buffer[format->field_offsets[O_YEAR].offset], &clock_time->year, + format->field_offsets[O_YEAR].length) || + Stoi(&buffer[format->field_offsets[O_HOUR].offset], &clock_time->hour, + format->field_offsets[O_HOUR].length) || + Stoi(&buffer[format->field_offsets[O_MIN].offset], &clock_time->minute, + format->field_offsets[O_MIN].length) || + Stoi(&buffer[format->field_offsets[O_SEC].offset], &clock_time->second, + format->field_offsets[O_SEC].length)) { + return CVT_FAIL | CVT_BADFMT; + } else { + + clock_time->flags = 0; + clock_time->utcoffset = 0; /* We have UTC time */ + + return CVT_OK; + } + } +} + +/* + * inp_computime + * + * grep data from input stream + */ +static u_long +inp_computime( + parse_t *parseio, + unsigned int ch, + timestamp_t *tstamp + ) +{ + unsigned int rtc; + + parseprintf(DD_PARSE, ("inp_computime(0x%x, 0x%x, ...)\n", (int)parseio, (int)ch)); + + switch (ch) + { + case 'T': + parseprintf(DD_PARSE, ("inp_computime: START seen\n")); + + parseio->parse_index = 1; + parseio->parse_data[0] = ch; + parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */ + return PARSE_INP_SKIP; + + case '\n': + parseprintf(DD_PARSE, ("inp_computime: END seen\n")); + if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP) + return parse_end(parseio); + else + return rtc; + + default: + return parse_addchar(parseio, ch); + } +} + +#else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_COMPUTIME) */ +int clk_computime_bs; +#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_COMPUTIME) */ + +/* + * clk_computime.c,v + * Revision 4.5 1998/06/14 21:09:34 kardel + * Sun acc cleanup + * + * Revision 4.4 1998/06/13 12:00:38 kardel + * fix SYSV clock name clash + * + * Revision 4.3 1998/06/12 15:22:26 kardel + * fix prototypes + * + * Revision 4.2 1998/06/12 09:13:24 kardel + * conditional compile macros fixed + * printf prototype + * + * Revision 4.1 1998/05/24 09:39:51 kardel + * implementation of the new IO handling model + * + * Revision 4.0 1998/04/10 19:45:27 kardel + * Start 4.0 release version numbering + * + * from V3 1.8 log info deleted 1998/04/11 kardel + */ diff --git a/contrib/ntp/libparse/clk_dcf7000.c b/contrib/ntp/libparse/clk_dcf7000.c new file mode 100644 index 000000000000..845b46716d08 --- /dev/null +++ b/contrib/ntp/libparse/clk_dcf7000.c @@ -0,0 +1,188 @@ +/* + * /src/NTP/ntp-4/libparse/clk_dcf7000.c,v 4.5 1998/06/14 21:09:34 kardel RELEASE_19990228_A + * + * clk_dcf7000.c,v 4.5 1998/06/14 21:09:34 kardel RELEASE_19990228_A + * + * ELV DCF7000 module + * + * Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998 by Frank Kardel + * Friedrich-Alexander Universität Erlangen-Nürnberg, Germany + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_DCF7000) + +#include <sys/types.h> +#include <sys/time.h> + +#include "ntp_fp.h" +#include "ntp_unixtime.h" +#include "ntp_calendar.h" + +#include "parse.h" + +#ifndef PARSESTREAM +#include "ntp_stdlib.h" +#include <stdio.h> +#else +#include "sys/parsestreams.h" +extern void printf P((const char *, ...)); +#endif + +static struct format dcf7000_fmt = +{ /* ELV DCF7000 */ + { + { 6, 2}, { 3, 2}, { 0, 2}, + { 12, 2}, { 15, 2}, { 18, 2}, + { 9, 2}, { 21, 2}, + }, + (const unsigned char *)" - - - - - - - \r", + 0 +}; +static u_long cvt_dcf7000 P((unsigned char *, int, struct format *, clocktime_t *, void *)); +static unsigned long inp_dcf7000 P((parse_t *, unsigned int, timestamp_t *)); + +clockformat_t clock_dcf7000 = +{ + inp_dcf7000, /* DCF7000 input handling */ + cvt_dcf7000, /* ELV DCF77 conversion */ + 0, /* no direct PPS monitoring */ + (void *)&dcf7000_fmt, /* conversion configuration */ + "ELV DCF7000", /* ELV clock */ + 24, /* string buffer */ + 0 /* no private data (complete pakets) */ +}; + +/* + * cvt_dcf7000 + * + * convert dcf7000 type format + */ +static u_long +cvt_dcf7000( + unsigned char *buffer, + int size, + struct format *format, + clocktime_t *clock_time, + void *local + ) +{ + if (!Strok(buffer, format->fixed_string)) + { + return CVT_NONE; + } + else + { + if (Stoi(&buffer[format->field_offsets[O_DAY].offset], &clock_time->day, + format->field_offsets[O_DAY].length) || + Stoi(&buffer[format->field_offsets[O_MONTH].offset], &clock_time->month, + format->field_offsets[O_MONTH].length) || + Stoi(&buffer[format->field_offsets[O_YEAR].offset], &clock_time->year, + format->field_offsets[O_YEAR].length) || + Stoi(&buffer[format->field_offsets[O_HOUR].offset], &clock_time->hour, + format->field_offsets[O_HOUR].length) || + Stoi(&buffer[format->field_offsets[O_MIN].offset], &clock_time->minute, + format->field_offsets[O_MIN].length) || + Stoi(&buffer[format->field_offsets[O_SEC].offset], &clock_time->second, + format->field_offsets[O_SEC].length)) + { + return CVT_FAIL|CVT_BADFMT; + } + else + { + unsigned char *f = &buffer[format->field_offsets[O_FLAGS].offset]; + long flags; + + clock_time->flags = 0; + clock_time->usecond = 0; + + if (Stoi(f, &flags, format->field_offsets[O_FLAGS].length)) + { + return CVT_FAIL|CVT_BADFMT; + } + else + { + if (flags & 0x1) + clock_time->utcoffset = -2*60*60; + else + clock_time->utcoffset = -1*60*60; + + if (flags & 0x2) + clock_time->flags |= PARSEB_ANNOUNCE; + + if (flags & 0x4) + clock_time->flags |= PARSEB_NOSYNC; + } + return CVT_OK; + } + } +} + +/* + * inp_dcf700 + * + * grep data from input stream + */ +static u_long +inp_dcf7000( + parse_t *parseio, + unsigned int ch, + timestamp_t *tstamp + ) +{ + unsigned int rtc; + + parseprintf(DD_PARSE, ("inp_dcf7000(0x%x, 0x%x, ...)\n", (int)parseio, (int)ch)); + + switch (ch) + { + case '\r': + parseprintf(DD_PARSE, ("inp_dcf7000: EOL seen\n")); + parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */ + if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP) + return parse_end(parseio); + else + return rtc; + + default: + return parse_addchar(parseio, ch); + } +} + +#else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_DCF7000) */ +int clk_dcf7000_bs; +#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_DCF7000) */ + +/* + * History: + * + * clk_dcf7000.c,v + * Revision 4.5 1998/06/14 21:09:34 kardel + * Sun acc cleanup + * + * Revision 4.4 1998/06/13 12:01:59 kardel + * fix SYSV clock name clash + * + * Revision 4.3 1998/06/12 15:22:27 kardel + * fix prototypes + * + * Revision 4.2 1998/06/12 09:13:24 kardel + * conditional compile macros fixed + * printf prototype + * + * Revision 4.1 1998/05/24 09:39:51 kardel + * implementation of the new IO handling model + * + * Revision 4.0 1998/04/10 19:45:28 kardel + * Start 4.0 release version numbering + * + * from V3 3.18 log info deleted 1998/04/11 kardel + */ diff --git a/contrib/ntp/libparse/clk_hopf6021.c b/contrib/ntp/libparse/clk_hopf6021.c new file mode 100644 index 000000000000..06efc6ff6dc2 --- /dev/null +++ b/contrib/ntp/libparse/clk_hopf6021.c @@ -0,0 +1,280 @@ +/* + * /src/NTP/ntp-4/libparse/clk_hopf6021.c,v 4.6 1998/11/15 20:27:57 kardel RELEASE_19990228_A + * + * clk_hopf6021.c,v 4.6 1998/11/15 20:27:57 kardel RELEASE_19990228_A + * + * Radiocode Clocks HOPF Funkuhr 6021 mit serieller Schnittstelle + * base code version from 24th Nov 1995 - history at end + * + * Created by F.Schnekenbuehl <frank@comsys.dofn.de> from clk_rcc8000.c + * Nortel DASA Network Systems GmbH, Department: ND250 + * A Joint venture of Daimler-Benz Aerospace and Nortel + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_HOPF6021) + +#include <sys/types.h> +#include <sys/time.h> + +#include "ntp_fp.h" +#include "ntp_unixtime.h" +#include "ntp_calendar.h" +#include "ascii.h" + +#include "parse.h" + +#ifndef PARSESTREAM +#include "ntp_stdlib.h" +#include <stdio.h> +#else +#include "sys/parsestreams.h" +extern void printf P((const char *, ...)); +#endif + +/* + * hopf Funkuhr 6021 + * used with 9600,8N1, + * UTC ueber serielle Schnittstelle + * Sekundenvorlauf ON + * ETX zum Sekundenvorlauf ON + * Datenstring 6021 + * Ausgabe Uhrzeit und Datum + * Senden mit Steuerzeichen + * Senden sekuendlich + */ + +/* + * Type 6021 Serial Output format + * + * 000000000011111111 / char + * 012345678901234567 \ position + * sABHHMMSSDDMMYYnre Actual + * C4110046231195 Parse + * s enr Check + * + * s = STX (0x02), e = ETX (0x03) + * n = NL (0x0A), r = CR (0x0D) + * + * A B - Status and weekday + * + * A - Status + * + * 8 4 2 1 + * x x x 0 - no announcement + * x x x 1 - Summertime - wintertime - summertime announcement + * x x 0 x - Wintertime + * x x 1 x - Summertime + * 0 0 x x - Time/Date invalid + * 0 1 x x - Internal clock used + * 1 0 x x - Radio clock + * 1 1 x x - Radio clock highprecision + * + * B - 8 4 2 1 + * 0 x x x - MESZ/MEZ + * 1 x x x - UTC + * x 0 0 1 - Monday + * x 0 1 0 - Tuesday + * x 0 1 1 - Wednesday + * x 1 0 0 - Thursday + * x 1 0 1 - Friday + * x 1 1 0 - Saturday + * x 1 1 1 - Sunday + */ + +#define HOPF_DSTWARN 0x01 /* DST switch warning */ +#define HOPF_DST 0x02 /* DST in effect */ + +#define HOPF_MODE 0x0C /* operation mode mask */ +#define HOPF_INVALID 0x00 /* no time code available */ +#define HOPF_INTERNAL 0x04 /* internal clock */ +#define HOPF_RADIO 0x08 /* radio clock */ +#define HOPF_RADIOHP 0x0C /* high precision radio clock */ + +#define HOPF_UTC 0x08 /* time code in UTC */ +#define HOPF_WMASK 0x07 /* mask for weekday code */ + +static struct format hopf6021_fmt = +{ + { + { 9, 2 }, {11, 2}, { 13, 2}, /* Day, Month, Year */ + { 3, 2 }, { 5, 2}, { 7, 2}, /* Hour, Minute, Second */ + { 2, 1 }, { 1, 1}, { 0, 0}, /* Weekday, Flags, Zone */ + /* ... */ + }, + (const unsigned char *)"\002 \n\r\003", + 0 +}; + +#define OFFS(x) format->field_offsets[(x)].offset +#define STOI(x, y) Stoi(&buffer[OFFS(x)], y, format->field_offsets[(x)].length) +#define hexval(x) (('0' <= (x) && (x) <= '9') ? (x) - '0' : \ + ('a' <= (x) && (x) <= 'f') ? (x) - 'a' + 10 : \ + ('A' <= (x) && (x) <= 'F') ? (x) - 'A' + 10 : \ + -1) + +static unsigned long cvt_hopf6021 P((unsigned char *, int, struct format *, clocktime_t *, void *)); +static unsigned long inp_hopf6021 P((parse_t *, unsigned int, timestamp_t *)); + +clockformat_t clock_hopf6021 = +{ + inp_hopf6021, /* HOPF 6021 input handling */ + cvt_hopf6021, /* Radiocode clock conversion */ + 0, /* no direct PPS monitoring */ + (void *)&hopf6021_fmt, /* conversion configuration */ + "hopf Funkuhr 6021", /* clock format name */ + 19, /* string buffer */ + 0 /* private data length, no private data */ +}; + +static unsigned long +cvt_hopf6021( + unsigned char *buffer, + int size, + struct format *format, + clocktime_t *clock_time, + void *local + ) +{ + unsigned char status,weekday; + + if (!Strok(buffer, format->fixed_string)) + { + return CVT_NONE; + } + + if ( STOI(O_DAY, &clock_time->day) || + STOI(O_MONTH, &clock_time->month) || + STOI(O_YEAR, &clock_time->year) || + STOI(O_HOUR, &clock_time->hour) || + STOI(O_MIN, &clock_time->minute) || + STOI(O_SEC, &clock_time->second) + ) + { + return CVT_FAIL|CVT_BADFMT; + } + + clock_time->usecond = 0; + clock_time->utcoffset = 0; + + status = hexval(buffer[OFFS(O_FLAGS)]); + weekday= hexval(buffer[OFFS(O_WDAY)]); + + if ((status == 0xFF) || (weekday == 0xFF)) + { + return CVT_FAIL|CVT_BADFMT; + } + + clock_time->flags = 0; + + if (weekday & HOPF_UTC) + { + clock_time->flags |= PARSEB_UTC; + } + else + { + if (status & HOPF_DST) + { + clock_time->flags |= PARSEB_DST; + clock_time->utcoffset = -2*60*60; /* MET DST */ + } + else + { + clock_time->utcoffset = -1*60*60; /* MET */ + } + } + + clock_time->flags |= (status & HOPF_DSTWARN) ? PARSEB_ANNOUNCE : 0; + + switch (status & HOPF_MODE) + { + case HOPF_INVALID: /* Time/Date invalid */ + clock_time->flags |= PARSEB_POWERUP; + break; + + case HOPF_INTERNAL: /* internal clock */ + clock_time->flags |= PARSEB_NOSYNC; + break; + + case HOPF_RADIO: /* Radio clock */ + case HOPF_RADIOHP: /* Radio clock high precision */ + break; + + default: + return CVT_FAIL|CVT_BADFMT; + } + + return CVT_OK; +} + +/* + * inp_hopf6021 + * + * grep data from input stream + */ +static u_long +inp_hopf6021( + parse_t *parseio, + unsigned int ch, + timestamp_t *tstamp + ) +{ + unsigned int rtc; + + parseprintf(DD_PARSE, ("inp_hopf6021(0x%x, 0x%x, ...)\n", (int)parseio, (int)ch)); + + switch (ch) + { + case ETX: + parseprintf(DD_PARSE, ("inp_hopf6021: EOL seen\n")); + parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */ + if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP) + return parse_end(parseio); + else + return rtc; + + default: + return parse_addchar(parseio, ch); + } +} + +#else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_HOPF6021) */ +int clk_hopf6021_bs; +#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_HOPF6021) */ + +/* + * History: + * + * clk_hopf6021.c,v + * Revision 4.6 1998/11/15 20:27:57 kardel + * Release 4.0.73e13 reconcilation + * + * Revision 4.5 1998/06/14 21:09:35 kardel + * Sun acc cleanup + * + * Revision 4.4 1998/06/13 12:02:38 kardel + * fix SYSV clock name clash + * + * Revision 4.3 1998/06/12 15:22:27 kardel + * fix prototypes + * + * Revision 4.2 1998/06/12 09:13:25 kardel + * conditional compile macros fixed + * printf prototype + * + * Revision 4.1 1998/05/24 09:39:52 kardel + * implementation of the new IO handling model + * + * Revision 4.0 1998/04/10 19:45:29 kardel + * Start 4.0 release version numbering + * + * from V3 3.6 log info deleted 1998/04/11 kardel + */ diff --git a/contrib/ntp/libparse/clk_meinberg.c b/contrib/ntp/libparse/clk_meinberg.c new file mode 100644 index 000000000000..fdffa1bf33c6 --- /dev/null +++ b/contrib/ntp/libparse/clk_meinberg.c @@ -0,0 +1,747 @@ +/* + * /src/NTP/ntp-4/libparse/clk_meinberg.c,v 4.7 1999/02/21 11:09:14 kardel RELEASE_19990228_A + * + * clk_meinberg.c,v 4.7 1999/02/21 11:09:14 kardel RELEASE_19990228_A + * + * Meinberg clock support + * + * Copyright (C) 1995-1999 by Frank Kardel <kardel@acm.org> + * Copyright (C) 1992-1994 by Frank Kardel, Friedrich-Alexander Universität Erlangen-Nürnberg, Germany + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_MEINBERG) + +#include <sys/types.h> +#include <sys/time.h> + +#include "ntp_fp.h" +#include "ntp_unixtime.h" +#include "ntp_calendar.h" + +#include "ntp_machine.h" + +#include "parse.h" + +#ifndef PARSESTREAM +#include <stdio.h> +#else +#include "sys/parsestreams.h" +#endif + +#include "ntp_stdlib.h" + +#include "ntp_stdlib.h" + +#include "mbg_gps166.h" +#include "binio.h" +#include "ascii.h" + +/* + * The Meinberg receiver every second sends a datagram of the following form + * (Standard Format) + * + * <STX>D:<dd>.<mm>.<yy>;T:<w>;U:<hh>:<mm>:<ss>;<S><F><D><A><ETX> + * pos: 0 00 00 0 00 0 11 111 1 111 12 2 22 2 22 2 2 2 3 3 3 + * 1 23 45 6 78 9 01 234 5 678 90 1 23 4 56 7 8 9 0 1 2 + * <STX> = '\002' ASCII start of text + * <ETX> = '\003' ASCII end of text + * <dd>,<mm>,<yy> = day, month, year(2 digits!!) + * <w> = day of week (sunday= 0) + * <hh>,<mm>,<ss> = hour, minute, second + * <S> = '#' if never synced since powerup for DCF C51 + * = '#' if not PZF sychronisation available for PZF 535/509 + * = ' ' if ok + * <F> = '*' if time comes from internal quartz + * = ' ' if completely synched + * <D> = 'S' if daylight saving time is active + * = 'U' if time is represented in UTC + * = ' ' if no special condition exists + * <A> = '!' during the hour preceeding an daylight saving time + * start/end change + * = 'A' leap second insert warning + * = ' ' if no special condition exists + * + * Extended data format (PZFUERL for PZF type clocks) + * + * <STX><dd>.<mm>.<yy>; <w>; <hh>:<mm>:<ss>; <U><S><F><D><A><L><R><ETX> + * pos: 0 00 0 00 0 00 11 1 11 11 1 11 2 22 22 2 2 2 2 2 3 3 3 + * 1 23 4 56 7 89 01 2 34 56 7 89 0 12 34 5 6 7 8 9 0 1 2 + * <STX> = '\002' ASCII start of text + * <ETX> = '\003' ASCII end of text + * <dd>,<mm>,<yy> = day, month, year(2 digits!!) + * <w> = day of week (sunday= 0) + * <hh>,<mm>,<ss> = hour, minute, second + * <U> = 'U' UTC time display + * <S> = '#' if never synced since powerup else ' ' for DCF C51 + * '#' if not PZF sychronisation available else ' ' for PZF 535/509 + * <F> = '*' if time comes from internal quartz else ' ' + * <D> = 'S' if daylight saving time is active else ' ' + * <A> = '!' during the hour preceeding an daylight saving time + * start/end change + * <L> = 'A' LEAP second announcement + * <R> = 'R' alternate antenna + * + * Meinberg GPS166 receiver + * + * You must get the Uni-Erlangen firmware for the GPS receiver support + * to work to full satisfaction ! + * + * <STX><dd>.<mm>.<yy>; <w>; <hh>:<mm>:<ss>; <+/-><00:00>; <U><S><F><D><A><L><R><L>; <position...><ETX> + * + * 000000000111111111122222222223333333333444444444455555555556666666 + * 123456789012345678901234567890123456789012345678901234567890123456 + * \x0209.07.93; 5; 08:48:26; +00:00; #*S!A L; 49.5736N 11.0280E 373m\x03 + * + * + * <STX> = '\002' ASCII start of text + * <ETX> = '\003' ASCII end of text + * <dd>,<mm>,<yy> = day, month, year(2 digits!!) + * <w> = day of week (sunday= 0) + * <hh>,<mm>,<ss> = hour, minute, second + * <+/->,<00:00> = offset to UTC + * <S> = '#' if never synced since powerup else ' ' + * <F> = '*' if position is not confirmed else ' ' + * <D> = 'S' if daylight saving time is active else ' ' + * <A> = '!' during the hour preceeding an daylight saving time + * start/end change + * <L> = 'A' LEAP second announcement + * <R> = 'R' alternate antenna (reminiscent of PZF535) usually ' ' + * <L> = 'L' on 23:59:60 + * + * Binary messages have a lead in for a fixed header of SOH + */ + +/*--------------------------------------------------------------*/ +/* Name: csum() */ +/* */ +/* Purpose: Compute a checksum about a number of bytes */ +/* */ +/* Input: uchar *p address of the first byte */ +/* short n the number of bytes */ +/* */ +/* Output: -- */ +/* */ +/* Ret val: the checksum */ +/*+-------------------------------------------------------------*/ + +unsigned long +mbg_csum( + unsigned char *p, + unsigned int n + ) +{ + unsigned long sum = 0; + short i; + + for ( i = 0; i < n; i++ ) + sum += *p++; + + return( sum ); +} /* csum */ + +void +get_mbg_header( + unsigned char **bufpp, + GPS_MSG_HDR *headerp + ) +{ + headerp->gps_cmd = get_lsb_short(bufpp); + headerp->gps_len = get_lsb_short(bufpp); + headerp->gps_data_csum = get_lsb_short(bufpp); + headerp->gps_hdr_csum = get_lsb_short(bufpp); +} + +static struct format meinberg_fmt[] = +{ + { + { + { 3, 2}, { 6, 2}, { 9, 2}, + { 18, 2}, { 21, 2}, { 24, 2}, + { 14, 1}, { 27, 4}, { 29, 1}, + }, + (const unsigned char *)"\2D: . . ;T: ;U: . . ; \3", + 0 + }, + { /* special extended FAU Erlangen extended format */ + { + { 1, 2}, { 4, 2}, { 7, 2}, + { 14, 2}, { 17, 2}, { 20, 2}, + { 11, 1}, { 25, 4}, { 27, 1}, + }, + (const unsigned char *)"\2 . . ; ; : : ; \3", + MBG_EXTENDED + }, + { /* special extended FAU Erlangen GPS format */ + { + { 1, 2}, { 4, 2}, { 7, 2}, + { 14, 2}, { 17, 2}, { 20, 2}, + { 11, 1}, { 32, 7}, { 35, 1}, + { 25, 2}, { 28, 2}, { 24, 1} + }, + (const unsigned char *)"\2 . . ; ; : : ; : ; ; . . ", + 0 + } +}; + +static u_long cvt_meinberg P((unsigned char *, int, struct format *, clocktime_t *, void *)); +static u_long cvt_mgps P((unsigned char *, int, struct format *, clocktime_t *, void *)); +static u_long mbg_input P((parse_t *, unsigned int, timestamp_t *)); +static u_long gps_input P((parse_t *, unsigned int, timestamp_t *)); + +struct msg_buf +{ + unsigned short len; /* len to fill */ + unsigned short phase; /* current input phase */ +}; + +#define MBG_NONE 0 /* no data input */ +#define MBG_HEADER 1 /* receiving header */ +#define MBG_DATA 2 /* receiving data */ +#define MBG_STRING 3 /* receiving standard data message */ + +clockformat_t clock_meinberg[] = +{ + { + mbg_input, /* normal input handling */ + cvt_meinberg, /* Meinberg conversion */ + pps_one, /* easy PPS monitoring */ + 0, /* conversion configuration */ + "Meinberg Standard", /* Meinberg simple format - beware */ + 32, /* string buffer */ + 0 /* no private data (complete pakets) */ + }, + { + mbg_input, /* normal input handling */ + cvt_meinberg, /* Meinberg conversion */ + pps_one, /* easy PPS monitoring */ + 0, /* conversion configuration */ + "Meinberg Extended", /* Meinberg enhanced format */ + 32, /* string buffer */ + 0 /* no private data (complete pakets) */ + }, + { + gps_input, /* no input handling */ + cvt_mgps, /* Meinberg GPS166 conversion */ + pps_one, /* easy PPS monitoring */ + (void *)&meinberg_fmt[2], /* conversion configuration */ + "Meinberg GPS Extended", /* Meinberg FAU GPS format */ + 512, /* string buffer */ + sizeof(struct msg_buf) /* no private data (complete pakets) */ + } +}; + +/* + * cvt_meinberg + * + * convert simple type format + */ +static u_long +cvt_meinberg( + unsigned char *buffer, + int size, + struct format *unused, + clocktime_t *clock_time, + void *local + ) +{ + struct format *format; + + /* + * select automagically correct data format + */ + if (Strok(buffer, meinberg_fmt[0].fixed_string)) + { + format = &meinberg_fmt[0]; + } + else + { + if (Strok(buffer, meinberg_fmt[1].fixed_string)) + { + format = &meinberg_fmt[1]; + } + else + { + return CVT_FAIL|CVT_BADFMT; + } + } + + /* + * collect data + */ + if (Stoi(&buffer[format->field_offsets[O_DAY].offset], &clock_time->day, + format->field_offsets[O_DAY].length) || + Stoi(&buffer[format->field_offsets[O_MONTH].offset], &clock_time->month, + format->field_offsets[O_MONTH].length) || + Stoi(&buffer[format->field_offsets[O_YEAR].offset], &clock_time->year, + format->field_offsets[O_YEAR].length) || + Stoi(&buffer[format->field_offsets[O_HOUR].offset], &clock_time->hour, + format->field_offsets[O_HOUR].length) || + Stoi(&buffer[format->field_offsets[O_MIN].offset], &clock_time->minute, + format->field_offsets[O_MIN].length) || + Stoi(&buffer[format->field_offsets[O_SEC].offset], &clock_time->second, + format->field_offsets[O_SEC].length)) + { + return CVT_FAIL|CVT_BADFMT; + } + else + { + unsigned char *f = &buffer[format->field_offsets[O_FLAGS].offset]; + + clock_time->usecond = 0; + clock_time->flags = PARSEB_S_LEAP; + + if (clock_time->second == 60) + clock_time->flags |= PARSEB_LEAPSECOND; + + /* + * in the extended timecode format we have also the + * indication that the timecode is in UTC + * for compatibilty reasons we start at the USUAL + * offset (POWERUP flag) and know that the UTC indication + * is the character before the powerup flag + */ + if ((format->flags & MBG_EXTENDED) && (f[-1] == 'U')) + { + /* + * timecode is in UTC + */ + clock_time->utcoffset = 0; /* UTC */ + clock_time->flags |= PARSEB_UTC; + } + else + { + /* + * only calculate UTC offset if MET/MED is in time code + * or we have the old time code format, where we do not + * know whether it is UTC time or MET/MED + * pray that nobody switches to UTC in the *old* standard time code + * ROMS !!!! The new ROMS have 'U' at the ZONE field - good. + */ + switch (buffer[format->field_offsets[O_ZONE].offset]) + { + case ' ': + clock_time->utcoffset = -1*60*60; /* MET */ + break; + + case 'S': + clock_time->utcoffset = -2*60*60; /* MED */ + break; + + case 'U': + /* + * timecode is in UTC + */ + clock_time->utcoffset = 0; /* UTC */ + clock_time->flags |= PARSEB_UTC; + break; + + default: + return CVT_FAIL|CVT_BADFMT; + } + } + + /* + * gather status flags + */ + if (buffer[format->field_offsets[O_ZONE].offset] == 'S') + clock_time->flags |= PARSEB_DST; + + if (f[0] == '#') + clock_time->flags |= PARSEB_POWERUP; + + if (f[1] == '*') + clock_time->flags |= PARSEB_NOSYNC; + + if (f[3] == '!') + clock_time->flags |= PARSEB_ANNOUNCE; + + /* + * oncoming leap second + * 'a' code not confirmed - earth is not + * expected to speed up + */ + if (f[3] == 'A') + clock_time->flags |= PARSEB_LEAPADD; + + if (f[3] == 'a') + clock_time->flags |= PARSEB_LEAPDEL; + + + if (format->flags & MBG_EXTENDED) + { + clock_time->flags |= PARSEB_S_ANTENNA; + + /* + * DCF77 does not encode the direction - + * so we take the current default - + * earth slowing down + */ + clock_time->flags &= ~PARSEB_LEAPDEL; + + if (f[4] == 'A') + clock_time->flags |= PARSEB_LEAPADD; + + if (f[5] == 'R') + clock_time->flags |= PARSEB_ALTERNATE; + } + return CVT_OK; + } +} + + +/* + * mbg_input + * + * grep data from input stream + */ +static u_long +mbg_input( + parse_t *parseio, + unsigned int ch, + timestamp_t *tstamp + ) +{ + unsigned int rtc; + + parseprintf(DD_PARSE, ("mbg_input(0x%x, 0x%x, ...)\n", (int)parseio, (int)ch)); + + switch (ch) + { + case STX: + parseprintf(DD_PARSE, ("mbg_input: STX seen\n")); + + parseio->parse_index = 1; + parseio->parse_data[0] = ch; + parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */ + return PARSE_INP_SKIP; + + case ETX: + parseprintf(DD_PARSE, ("mbg_input: ETX seen\n")); + if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP) + return parse_end(parseio); + else + return rtc; + + default: + return parse_addchar(parseio, ch); + } +} + + +/* + * cvt_mgps + * + * convert Meinberg GPS format + */ +static u_long +cvt_mgps( + unsigned char *buffer, + int size, + struct format *format, + clocktime_t *clock_time, + void *local + ) +{ + if (!Strok(buffer, format->fixed_string)) + { + return cvt_meinberg(buffer, size, format, clock_time, local); + } + else + { + if (Stoi(&buffer[format->field_offsets[O_DAY].offset], &clock_time->day, + format->field_offsets[O_DAY].length) || + Stoi(&buffer[format->field_offsets[O_MONTH].offset], &clock_time->month, + format->field_offsets[O_MONTH].length) || + Stoi(&buffer[format->field_offsets[O_YEAR].offset], &clock_time->year, + format->field_offsets[O_YEAR].length) || + Stoi(&buffer[format->field_offsets[O_HOUR].offset], &clock_time->hour, + format->field_offsets[O_HOUR].length) || + Stoi(&buffer[format->field_offsets[O_MIN].offset], &clock_time->minute, + format->field_offsets[O_MIN].length) || + Stoi(&buffer[format->field_offsets[O_SEC].offset], &clock_time->second, + format->field_offsets[O_SEC].length)) + { + return CVT_FAIL|CVT_BADFMT; + } + else + { + long h; + unsigned char *f = &buffer[format->field_offsets[O_FLAGS].offset]; + + clock_time->flags = PARSEB_S_LEAP|PARSEB_S_POSITION; + + clock_time->usecond = 0; + + /* + * calculate UTC offset + */ + if (Stoi(&buffer[format->field_offsets[O_UTCHOFFSET].offset], &h, + format->field_offsets[O_UTCHOFFSET].length)) + { + return CVT_FAIL|CVT_BADFMT; + } + else + { + if (Stoi(&buffer[format->field_offsets[O_UTCMOFFSET].offset], &clock_time->utcoffset, + format->field_offsets[O_UTCMOFFSET].length)) + { + return CVT_FAIL|CVT_BADFMT; + } + + clock_time->utcoffset += TIMES60(h); + clock_time->utcoffset = TIMES60(clock_time->utcoffset); + + if (buffer[format->field_offsets[O_UTCSOFFSET].offset] != '-') + { + clock_time->utcoffset = -clock_time->utcoffset; + } + } + + /* + * gather status flags + */ + if (buffer[format->field_offsets[O_ZONE].offset] == 'S') + clock_time->flags |= PARSEB_DST; + + if (clock_time->utcoffset == 0) + clock_time->flags |= PARSEB_UTC; + + /* + * no sv's seen - no time & position + */ + if (f[0] == '#') + clock_time->flags |= PARSEB_POWERUP; + + /* + * at least one sv seen - time (for last position) + */ + if (f[1] == '*') + clock_time->flags |= PARSEB_NOSYNC; + else + if (!(clock_time->flags & PARSEB_POWERUP)) + clock_time->flags |= PARSEB_POSITION; + + /* + * oncoming zone switch + */ + if (f[3] == '!') + clock_time->flags |= PARSEB_ANNOUNCE; + + /* + * oncoming leap second + * 'a' code not confirmed - earth is not + * expected to speed up + */ + if (f[4] == 'A') + clock_time->flags |= PARSEB_LEAPADD; + + if (f[4] == 'a') + clock_time->flags |= PARSEB_LEAPDEL; + + /* + * f[5] == ' ' + */ + + /* + * this is the leap second + */ + if ((f[6] == 'L') || (clock_time->second == 60)) + clock_time->flags |= PARSEB_LEAPSECOND; + + return CVT_OK; + } + } +} + +/* + * gps_input + * + * grep binary data from input stream + */ +static u_long +gps_input( + parse_t *parseio, + unsigned int ch, + timestamp_t *tstamp + ) +{ + CSUM calc_csum; /* used to compare the incoming csums */ + GPS_MSG_HDR header; + struct msg_buf *msg_buf; + + msg_buf = (struct msg_buf *)parseio->parse_pdata; + + parseprintf(DD_PARSE, ("gps_input(0x%x, 0x%x, ...)\n", (int)parseio, (int)ch)); + + if (!msg_buf) + return PARSE_INP_SKIP; + + if ( msg_buf->phase == MBG_NONE ) + { /* not receiving yet */ + switch (ch) + { + case SOH: + parseprintf(DD_PARSE, ("gps_input: SOH seen\n")); + + msg_buf->len = sizeof( header ); /* prepare to receive msg header */ + msg_buf->phase = MBG_HEADER; /* receiving header */ + break; + + case STX: + parseprintf(DD_PARSE, ("gps_input: STX seen\n")); + + msg_buf->len = 0; + msg_buf->phase = MBG_STRING; /* prepare to receive ASCII ETX delimited message */ + parseio->parse_index = 1; + parseio->parse_data[0] = ch; + break; + + default: + return PARSE_INP_SKIP; /* keep searching */ + } + + parseio->parse_dtime.parse_msglen = 1; /* reset buffer pointer */ + parseio->parse_dtime.parse_msg[0] = ch; /* fill in first character */ + parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */ + return PARSE_INP_SKIP; + } + + /* SOH/STX has already been received */ + + /* save incoming character in both buffers if needbe */ + if ((msg_buf->phase == MBG_STRING) && + (parseio->parse_index < parseio->parse_dsize)) + parseio->parse_data[parseio->parse_index++] = ch; + + parseio->parse_dtime.parse_msg[parseio->parse_dtime.parse_msglen++] = ch; + + if (parseio->parse_dtime.parse_msglen > sizeof(parseio->parse_dtime.parse_msg)) + { + msg_buf->phase = MBG_NONE; /* buffer overflow - discard */ + parseio->parse_data[parseio->parse_index] = '\0'; + memcpy(parseio->parse_ldata, parseio->parse_data, (unsigned)(parseio->parse_index+1)); + parseio->parse_ldsize = parseio->parse_index+1; + return PARSE_INP_DATA; + } + + switch (msg_buf->phase) + { + case MBG_HEADER: + case MBG_DATA: + msg_buf->len--; + + if ( msg_buf->len ) /* transfer not complete */ + return PARSE_INP_SKIP; + + parseprintf(DD_PARSE, ("gps_input: %s complete\n", (msg_buf->phase == MBG_DATA) ? "data" : "header")); + + break; + + case MBG_STRING: + if ((ch == ETX) || (parseio->parse_index >= parseio->parse_dsize)) + { + msg_buf->phase = MBG_NONE; + parseprintf(DD_PARSE, ("gps_input: string complete\n")); + parseio->parse_data[parseio->parse_index] = '\0'; + memcpy(parseio->parse_ldata, parseio->parse_data, (unsigned)(parseio->parse_index+1)); + parseio->parse_ldsize = parseio->parse_index+1; + parseio->parse_index = 0; + return PARSE_INP_TIME; + } + else + { + return PARSE_INP_SKIP; + } + } + + /* cnt == 0, so the header or the whole message is complete */ + + if ( msg_buf->phase == MBG_HEADER ) + { /* header complete now */ + unsigned char *datap = parseio->parse_dtime.parse_msg + 1; + + get_mbg_header(&datap, &header); + + parseprintf(DD_PARSE, ("gps_input: header: cmd 0x%x, len %d, dcsum 0x%x, hcsum 0x%x\n", + (int)header.gps_cmd, (int)header.gps_len, (int)header.gps_data_csum, + (int)header.gps_hdr_csum)); + + + calc_csum = mbg_csum( (unsigned char *) parseio->parse_dtime.parse_msg + 1, (unsigned short)6 ); + + if ( calc_csum != header.gps_hdr_csum ) + { + parseprintf(DD_PARSE, ("gps_input: header checksum mismatch expected 0x%x, got 0x%x\n", + (int)calc_csum, (int)mbg_csum( (unsigned char *) parseio->parse_dtime.parse_msg, (unsigned short)6 ))); + + msg_buf->phase = MBG_NONE; /* back to hunting mode */ + return PARSE_INP_DATA; /* invalid header checksum received - pass up for detection */ + } + + if ((header.gps_len == 0) || /* no data to wait for */ + (header.gps_len >= (sizeof (parseio->parse_dtime.parse_msg) - sizeof(header) - 1))) /* blows anything we have space for */ + { + msg_buf->phase = MBG_NONE; /* back to hunting mode */ + return (header.gps_len == 0) ? PARSE_INP_DATA : PARSE_INP_SKIP; /* message complete/throwaway */ + } + + parseprintf(DD_PARSE, ("gps_input: expecting %d bytes of data message\n", (int)header.gps_len)); + + msg_buf->len = header.gps_len;/* save number of bytes to wait for */ + msg_buf->phase = MBG_DATA; /* flag header already complete */ + return PARSE_INP_SKIP; + } + + parseprintf(DD_PARSE, ("gps_input: message data complete\n")); + + /* Header and data have been received. The header checksum has been */ + /* checked */ + + msg_buf->phase = MBG_NONE; /* back to hunting mode */ + return PARSE_INP_DATA; /* message complete, must be evaluated */ +} + +#else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_MEINBERG) */ +int clk_meinberg_bs; +#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_MEINBERG) */ + +/* + * History: + * + * clk_meinberg.c,v + * Revision 4.7 1999/02/21 11:09:14 kardel + * cleanup + * + * Revision 4.6 1998/06/14 21:09:36 kardel + * Sun acc cleanup + * + * Revision 4.5 1998/06/13 15:18:54 kardel + * fix mem*() to b*() function macro emulation + * + * Revision 4.4 1998/06/13 12:03:23 kardel + * fix SYSV clock name clash + * + * Revision 4.3 1998/06/12 15:22:28 kardel + * fix prototypes + * + * Revision 4.2 1998/05/24 16:14:42 kardel + * support current Meinberg standard data formats + * + * Revision 4.1 1998/05/24 09:39:52 kardel + * implementation of the new IO handling model + * + * Revision 4.0 1998/04/10 19:45:29 kardel + * Start 4.0 release version numbering + * + * from V3 3.23 - log info deleted 1998/04/11 kardel + * + */ diff --git a/contrib/ntp/libparse/clk_rawdcf.c b/contrib/ntp/libparse/clk_rawdcf.c new file mode 100644 index 000000000000..ac854c57b223 --- /dev/null +++ b/contrib/ntp/libparse/clk_rawdcf.c @@ -0,0 +1,581 @@ +/* + * /src/NTP/ntp-4/libparse/clk_rawdcf.c,v 4.6 1998/06/14 21:09:37 kardel RELEASE_19990228_A + * + * clk_rawdcf.c,v 4.6 1998/06/14 21:09:37 kardel RELEASE_19990228_A + * + * Raw DCF77 pulse clock support + * + * Copyright (C) 1992-1998 by Frank Kardel + * Friedrich-Alexander Universität Erlangen-Nürnberg, Germany + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_RAWDCF) + +#include <sys/types.h> +#include <sys/time.h> + +#include "ntp_fp.h" +#include "ntp_unixtime.h" +#include "ntp_calendar.h" + +#include "parse.h" +#ifdef PARSESTREAM +# include <sys/parsestreams.h> +#endif + +#ifndef PARSEKERNEL +# include "ntp_stdlib.h" +#endif + +/* + * DCF77 raw time code + * + * From "Zur Zeit", Physikalisch-Technische Bundesanstalt (PTB), Braunschweig + * und Berlin, Maerz 1989 + * + * Timecode transmission: + * AM: + * time marks are send every second except for the second before the + * next minute mark + * time marks consist of a reduction of transmitter power to 25% + * of the nominal level + * the falling edge is the time indication (on time) + * time marks of a 100ms duration constitute a logical 0 + * time marks of a 200ms duration constitute a logical 1 + * FM: + * see the spec. (basically a (non-)inverted psuedo random phase shift) + * + * Encoding: + * Second Contents + * 0 - 10 AM: free, FM: 0 + * 11 - 14 free + * 15 R - alternate antenna + * 16 A1 - expect zone change (1 hour before) + * 17 - 18 Z1,Z2 - time zone + * 0 0 illegal + * 0 1 MEZ (MET) + * 1 0 MESZ (MED, MET DST) + * 1 1 illegal + * 19 A2 - expect leap insertion/deletion (1 hour before) + * 20 S - start of time code (1) + * 21 - 24 M1 - BCD (lsb first) Minutes + * 25 - 27 M10 - BCD (lsb first) 10 Minutes + * 28 P1 - Minute Parity (even) + * 29 - 32 H1 - BCD (lsb first) Hours + * 33 - 34 H10 - BCD (lsb first) 10 Hours + * 35 P2 - Hour Parity (even) + * 36 - 39 D1 - BCD (lsb first) Days + * 40 - 41 D10 - BCD (lsb first) 10 Days + * 42 - 44 DW - BCD (lsb first) day of week (1: Monday -> 7: Sunday) + * 45 - 49 MO - BCD (lsb first) Month + * 50 MO0 - 10 Months + * 51 - 53 Y1 - BCD (lsb first) Years + * 54 - 57 Y10 - BCD (lsb first) 10 Years + * 58 P3 - Date Parity (even) + * 59 - usually missing (minute indication), except for leap insertion + */ + +static u_long pps_rawdcf P((parse_t *, int, timestamp_t *)); +static u_long cvt_rawdcf P((unsigned char *, int, struct format *, clocktime_t *, void *)); +static u_long inp_rawdcf P((parse_t *, unsigned int, timestamp_t *)); + +clockformat_t clock_rawdcf = +{ + inp_rawdcf, /* DCF77 input handling */ + cvt_rawdcf, /* raw dcf input conversion */ + pps_rawdcf, /* examining PPS information */ + 0, /* no private configuration data */ + "RAW DCF77 Timecode", /* direct decoding / time synthesis */ + + 61, /* bit buffer */ + 0 /* no private data (currently in input buffer) */ +}; + +static struct dcfparam +{ + unsigned char onebits[60]; + unsigned char zerobits[60]; +} dcfparameter = +{ + "###############RADMLS1248124P124812P1248121241248112481248P", /* 'ONE' representation */ + "--------------------s-------p------p----------------------p" /* 'ZERO' representation */ +}; + +static struct rawdcfcode +{ + char offset; /* start bit */ +} rawdcfcode[] = +{ + { 0 }, { 15 }, { 16 }, { 17 }, { 19 }, { 20 }, { 21 }, { 25 }, { 28 }, { 29 }, + { 33 }, { 35 }, { 36 }, { 40 }, { 42 }, { 45 }, { 49 }, { 50 }, { 54 }, { 58 }, { 59 } +}; + +#define DCF_M 0 +#define DCF_R 1 +#define DCF_A1 2 +#define DCF_Z 3 +#define DCF_A2 4 +#define DCF_S 5 +#define DCF_M1 6 +#define DCF_M10 7 +#define DCF_P1 8 +#define DCF_H1 9 +#define DCF_H10 10 +#define DCF_P2 11 +#define DCF_D1 12 +#define DCF_D10 13 +#define DCF_DW 14 +#define DCF_MO 15 +#define DCF_MO0 16 +#define DCF_Y1 17 +#define DCF_Y10 18 +#define DCF_P3 19 + +static struct partab +{ + char offset; /* start bit of parity field */ +} partab[] = +{ + { 21 }, { 29 }, { 36 }, { 59 } +}; + +#define DCF_P_P1 0 +#define DCF_P_P2 1 +#define DCF_P_P3 2 + +#define DCF_Z_MET 0x2 +#define DCF_Z_MED 0x1 + +static u_long +ext_bf( + register unsigned char *buf, + register int idx, + register unsigned char *zero + ) +{ + register u_long sum = 0; + register int i, first; + + first = rawdcfcode[idx].offset; + + for (i = rawdcfcode[idx+1].offset - 1; i >= first; i--) + { + sum <<= 1; + sum |= (buf[i] != zero[i]); + } + return sum; +} + +static unsigned +pcheck( + unsigned char *buf, + int idx, + unsigned char *zero + ) +{ + int i,last; + unsigned psum = 1; + + last = partab[idx+1].offset; + + for (i = partab[idx].offset; i < last; i++) + psum ^= (buf[i] != zero[i]); + + return psum; +} + +static u_long +convert_rawdcf( + unsigned char *buffer, + int size, + struct dcfparam *dcfprm, + clocktime_t *clock_time + ) +{ + register unsigned char *s = buffer; + register unsigned char *b = dcfprm->onebits; + register unsigned char *c = dcfprm->zerobits; + register int i; + + parseprintf(DD_RAWDCF,("parse: convert_rawdcf: \"%s\"\n", buffer)); + + if (size < 57) + { +#ifndef PARSEKERNEL + msyslog(LOG_ERR, "parse: convert_rawdcf: INCOMPLETE DATA - time code only has %d bits\n", size); +#endif + return CVT_NONE; + } + + for (i = 0; i < 58; i++) + { + if ((*s != *b) && (*s != *c)) + { + /* + * we only have two types of bytes (ones and zeros) + */ +#ifndef PARSEKERNEL + msyslog(LOG_ERR, "parse: convert_rawdcf: BAD DATA - no conversion for \"%s\"\n", buffer); +#endif + return CVT_NONE; + } + b++; + c++; + s++; + } + + /* + * check Start and Parity bits + */ + if ((ext_bf(buffer, DCF_S, dcfprm->zerobits) == 1) && + pcheck(buffer, DCF_P_P1, dcfprm->zerobits) && + pcheck(buffer, DCF_P_P2, dcfprm->zerobits) && + pcheck(buffer, DCF_P_P3, dcfprm->zerobits)) + { + /* + * buffer OK + */ + parseprintf(DD_RAWDCF,("parse: convert_rawdcf: parity check passed\n")); + + clock_time->flags = PARSEB_S_ANTENNA|PARSEB_S_LEAP; + clock_time->utctime= 0; + clock_time->usecond= 0; + clock_time->second = 0; + clock_time->minute = ext_bf(buffer, DCF_M10, dcfprm->zerobits); + clock_time->minute = TIMES10(clock_time->minute) + ext_bf(buffer, DCF_M1, dcfprm->zerobits); + clock_time->hour = ext_bf(buffer, DCF_H10, dcfprm->zerobits); + clock_time->hour = TIMES10(clock_time->hour) + ext_bf(buffer, DCF_H1, dcfprm->zerobits); + clock_time->day = ext_bf(buffer, DCF_D10, dcfprm->zerobits); + clock_time->day = TIMES10(clock_time->day) + ext_bf(buffer, DCF_D1, dcfprm->zerobits); + clock_time->month = ext_bf(buffer, DCF_MO0, dcfprm->zerobits); + clock_time->month = TIMES10(clock_time->month) + ext_bf(buffer, DCF_MO, dcfprm->zerobits); + clock_time->year = ext_bf(buffer, DCF_Y10, dcfprm->zerobits); + clock_time->year = TIMES10(clock_time->year) + ext_bf(buffer, DCF_Y1, dcfprm->zerobits); + + switch (ext_bf(buffer, DCF_Z, dcfprm->zerobits)) + { + case DCF_Z_MET: + clock_time->utcoffset = -1*60*60; + break; + + case DCF_Z_MED: + clock_time->flags |= PARSEB_DST; + clock_time->utcoffset = -2*60*60; + break; + + default: + parseprintf(DD_RAWDCF,("parse: convert_rawdcf: BAD TIME ZONE\n")); + return CVT_FAIL|CVT_BADFMT; + } + + if (ext_bf(buffer, DCF_A1, dcfprm->zerobits)) + clock_time->flags |= PARSEB_ANNOUNCE; + + if (ext_bf(buffer, DCF_A2, dcfprm->zerobits)) + clock_time->flags |= PARSEB_LEAPADD; /* default: DCF77 data format deficiency */ + + if (ext_bf(buffer, DCF_R, dcfprm->zerobits)) + clock_time->flags |= PARSEB_ALTERNATE; + + parseprintf(DD_RAWDCF,("parse: convert_rawdcf: TIME CODE OK: %d:%d, %d.%d.%d, flags 0x%lx\n", + (int)clock_time->hour, (int)clock_time->minute, (int)clock_time->day, (int)clock_time->month,(int) clock_time->year, + (u_long)clock_time->flags)); + return CVT_OK; + } + else + { + /* + * bad format - not for us + */ +#ifndef PARSEKERNEL + msyslog(LOG_ERR, "parse: convert_rawdcf: parity check FAILED for \"%s\"\n", buffer); +#endif + return CVT_FAIL|CVT_BADFMT; + } +} + +/* + * raw dcf input routine - needs to fix up 50 baud + * characters for 1/0 decision + */ +static u_long +cvt_rawdcf( + unsigned char *buffer, + int size, + struct format *param, + clocktime_t *clock_time, + void *local + ) +{ + register unsigned char *s = (unsigned char *)buffer; + register unsigned char *e = s + size; + register unsigned char *b = dcfparameter.onebits; + register unsigned char *c = dcfparameter.zerobits; + register unsigned rtc = CVT_NONE; + register unsigned int i, lowmax, highmax, cutoff, span; +#define BITS 9 + unsigned char histbuf[BITS]; + /* + * the input buffer contains characters with runs of consecutive + * bits set. These set bits are an indication of the DCF77 pulse + * length. We assume that we receive the pulse at 50 Baud. Thus + * a 100ms pulse would generate a 4 bit train (20ms per bit and + * start bit) + * a 200ms pulse would create all zeroes (and probably a frame error) + */ + + for (i = 0; i < BITS; i++) + { + histbuf[i] = 0; + } + + cutoff = 0; + lowmax = 0; + + while (s < e) + { + register unsigned int ch = *s ^ 0xFF; + /* + * these lines are left as an excercise to the reader 8-) + */ + if (!((ch+1) & ch) || !*s) + { + + for (i = 0; ch; i++) + { + ch >>= 1; + } + + *s = i; + histbuf[i]++; + cutoff += i; + lowmax++; + } + else + { + parseprintf(DD_RAWDCF,("parse: cvt_rawdcf: character check for 0x%x@%d FAILED\n", *s, (int)(s - (unsigned char *)buffer))); + *s = (unsigned char)~0; + rtc = CVT_FAIL|CVT_BADFMT; + } + s++; + } + + if (lowmax) + { + cutoff /= lowmax; + } + else + { + cutoff = 4; /* doesn't really matter - it'll fail anyway, but gives error output */ + } + + parseprintf(DD_RAWDCF,("parse: cvt_rawdcf: average bit count: %d\n", cutoff)); + + lowmax = 0; + highmax = 0; + + parseprintf(DD_RAWDCF,("parse: cvt_rawdcf: histogram:")); + for (i = 0; i <= cutoff; i++) + { + lowmax+=histbuf[i] * i; + highmax += histbuf[i]; + parseprintf(DD_RAWDCF,(" %d", histbuf[i])); + } + parseprintf(DD_RAWDCF, (" <M>")); + + lowmax += highmax / 2; + + if (highmax) + { + lowmax /= highmax; + } + else + { + lowmax = 0; + } + + highmax = 0; + cutoff = 0; + + for (; i < BITS; i++) + { + highmax+=histbuf[i] * i; + cutoff +=histbuf[i]; + parseprintf(DD_RAWDCF,(" %d", histbuf[i])); + } + parseprintf(DD_RAWDCF,("\n")); + + if (cutoff) + { + highmax /= cutoff; + } + else + { + highmax = BITS-1; + } + + span = cutoff = lowmax; + for (i = lowmax; i <= highmax; i++) + { + if (histbuf[cutoff] > histbuf[i]) + { + cutoff = i; + span = i; + } + else + if (histbuf[cutoff] == histbuf[i]) + { + span = i; + } + } + + cutoff = (cutoff + span) / 2; + + parseprintf(DD_RAWDCF,("parse: cvt_rawdcf: lower maximum %d, higher maximum %d, cutoff %d\n", lowmax, highmax, cutoff)); + + s = (unsigned char *)buffer; + while ((s < e) && *c && *b) + { + if (*s == (unsigned char)~0) + { + *s = '?'; + } + else + { + *s = (*s >= cutoff) ? *b : *c; + } + s++; + b++; + c++; + } + + return (rtc == CVT_NONE) ? convert_rawdcf(buffer, size, &dcfparameter, clock_time) : rtc; +} + +/* + * pps_rawdcf + * + * currently a very stupid version - should be extended to decode + * also ones and zeros (which is easy) + */ +/*ARGSUSED*/ +static u_long +pps_rawdcf( + register parse_t *parseio, + register int status, + register timestamp_t *ptime + ) +{ + if (!status) /* negative edge for simpler wiring (Rx->DCD) */ + { + parseio->parse_dtime.parse_ptime = *ptime; + parseio->parse_dtime.parse_state |= PARSEB_PPS|PARSEB_S_PPS; + } + + return CVT_NONE; +} + +static u_long +snt_rawdcf( + register parse_t *parseio, + register timestamp_t *ptime + ) +{ + if ((parseio->parse_dtime.parse_status & CVT_MASK) == CVT_OK) + { + parseio->parse_dtime.parse_stime = *ptime; + +#ifdef PARSEKERNEL + parseio->parse_dtime.parse_time.tv.tv_sec++; +#else + parseio->parse_dtime.parse_time.fp.l_ui++; +#endif + + parseprintf(DD_RAWDCF,("parse: snt_rawdcf: time stamp synthesized offset %d seconds\n", parseio->parse_index - 1)); + + return updatetimeinfo(parseio, parseio->parse_lstate); + } + return CVT_NONE; +} + +/* + * inp_rawdcf + * + * grep DCF77 data from input stream + */ +static u_long +inp_rawdcf( + parse_t *parseio, + unsigned int ch, + timestamp_t *tstamp + ) +{ + static struct timeval timeout = { 1, 500000 }; /* 1.5 secongs denote second #60 */ + + parseprintf(DD_PARSE, ("inp_rawdcf(0x%x, 0x%x, ...)\n", (int)parseio, (int)ch)); + + parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */ + + if (parse_timedout(parseio, tstamp, &timeout)) + { + parseprintf(DD_PARSE, ("inp_rawdcf: time out seen\n")); + + (void) parse_end(parseio); + (void) parse_addchar(parseio, ch); + return PARSE_INP_TIME; + } + else + { + unsigned int rtc; + + rtc = parse_addchar(parseio, ch); + if (rtc == PARSE_INP_SKIP) + { + if (snt_rawdcf(parseio, tstamp) == CVT_OK) + return PARSE_INP_SYNTH; + } + return rtc; + } +} + +#else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_RAWDCF) */ +int clk_rawdcf_bs; +#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_RAWDCF) */ + +/* + * History: + * + * clk_rawdcf.c,v + * Revision 4.6 1998/06/14 21:09:37 kardel + * Sun acc cleanup + * + * Revision 4.5 1998/06/13 12:04:16 kardel + * fix SYSV clock name clash + * + * Revision 4.4 1998/06/12 15:22:28 kardel + * fix prototypes + * + * Revision 4.3 1998/06/06 18:33:36 kardel + * simplified condidional compile expression + * + * Revision 4.2 1998/05/24 11:04:18 kardel + * triggering PPS on negative edge for simpler wiring (Rx->DCD) + * + * Revision 4.1 1998/05/24 09:39:53 kardel + * implementation of the new IO handling model + * + * Revision 4.0 1998/04/10 19:45:30 kardel + * Start 4.0 release version numbering + * + * from V3 3.24 log info deleted 1998/04/11 kardel + * + */ diff --git a/contrib/ntp/libparse/clk_rcc8000.c b/contrib/ntp/libparse/clk_rcc8000.c new file mode 100644 index 000000000000..09405c73d20e --- /dev/null +++ b/contrib/ntp/libparse/clk_rcc8000.c @@ -0,0 +1,195 @@ +/* + * /src/NTP/ntp-4/libparse/clk_rcc8000.c,v 4.5 1998/06/14 21:09:38 kardel RELEASE_19990228_A + * + * clk_rcc8000.c,v 4.5 1998/06/14 21:09:38 kardel RELEASE_19990228_A + * + * Radiocode Clocks Ltd RCC 8000 Intelligent Off-Air Master Clock support + * + * Created by R.E.Broughton from clk_trimtaip.c + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#if HAVE_CONFIG_H +# include <config.h> +#endif + +#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_RCC8000) + +#include <sys/types.h> +#include <sys/time.h> + +#include "ntp_fp.h" +#include "ntp_unixtime.h" +#include "ntp_calendar.h" + +#include "parse.h" + +#ifndef PARSESTREAM +#include "ntp_stdlib.h" +#include <stdio.h> +#else +#include "sys/parsestreams.h" +extern void printf P((const char *, ...)); +#endif + +/* Type II Serial Output format + * + * 0000000000111111111122222222223 / char + * 0123456789012345678901234567890 \ posn + * HH:MM:SS.XYZ DD/MM/YY DDD W Prn Actual + * 33 44 55 666 00 11 22 7 Parse + * : : . / / rn Check + * "15:50:36.534 30/09/94 273 5 A\x0d\x0a" + * + * DDD - Day of year number + * W - Day of week number (Sunday is 0) + * P is the Status. See comment below for details. + */ + +#define O_USEC O_WDAY +static struct format rcc8000_fmt = +{ { { 13, 2 }, {16, 2}, { 19, 2}, /* Day, Month, Year */ + { 0, 2 }, { 3, 2}, { 6, 2}, /* Hour, Minute, Second */ + { 9, 3 }, {28, 1}, { 0, 0}, /* uSec, Status (Valid,Reject,BST,Leapyear) */ }, + (const unsigned char *)" : : . / / \r\n", + /*"15:50:36.534 30/09/94 273 5 A\x0d\x0a" */ + 0 +}; + +static unsigned long cvt_rcc8000 P((unsigned char *, int, struct format *, clocktime_t *, void *)); +static unsigned long inp_rcc8000 P((parse_t *, unsigned int, timestamp_t *)); + +clockformat_t clock_rcc8000 = +{ + inp_rcc8000, /* no input handling */ + cvt_rcc8000, /* Radiocode clock conversion */ + 0, /* no direct PPS monitoring */ + (void *)&rcc8000_fmt, /* conversion configuration */ + "Radiocode RCC8000", + 31, /* string buffer */ + 0 /* no private data */ +}; + +static unsigned long +cvt_rcc8000( + unsigned char *buffer, + int size, + struct format *format, + clocktime_t *clock_time, + void *local + ) +{ + if (!Strok(buffer, format->fixed_string)) return CVT_NONE; +#define OFFS(x) format->field_offsets[(x)].offset +#define STOI(x, y) Stoi(&buffer[OFFS(x)], y, format->field_offsets[(x)].length) + if ( STOI(O_DAY, &clock_time->day) || + STOI(O_MONTH, &clock_time->month) || + STOI(O_YEAR, &clock_time->year) || + STOI(O_HOUR, &clock_time->hour) || + STOI(O_MIN, &clock_time->minute) || + STOI(O_SEC, &clock_time->second) || + STOI(O_USEC, &clock_time->usecond) + ) return CVT_FAIL|CVT_BADFMT; + clock_time->usecond *= 1000; + + clock_time->utcoffset = 0; + +#define RCCP buffer[28] + /* + * buffer[28] is the ASCII representation of a hex character ( 0 through F ) + * The four bits correspond to: + * 8 - Valid Time + * 4 - Reject Code + * 2 - British Summer Time (receiver set to emit GMT all year.) + * 1 - Leap year + */ +#define RCC8000_VALID 0x8 +#define RCC8000_REJECT 0x4 +#define RCC8000_BST 0x2 +#define RCC8000_LEAPY 0x1 + + clock_time->flags = 0; + + if ( (RCCP >= '0' && RCCP <= '9') || (RCCP >= 'A' && RCCP <= 'F') ) + { + register int flag; + + flag = (RCCP >= '0' && RCCP <= '9' ) ? RCCP - '0' : RCCP - 'A' + 10; + + if (!(flag & RCC8000_VALID)) + clock_time->flags |= PARSEB_POWERUP; + + clock_time->flags |= PARSEB_UTC; /* British special - guess why 8-) */ + + /* other flags not used */ + } + return CVT_OK; +} +/* + * inp_rcc8000 + * + * grep data from input stream + */ +static u_long +inp_rcc8000( + parse_t *parseio, + unsigned int ch, + timestamp_t *tstamp + ) +{ + unsigned int rtc; + + parseprintf(DD_PARSE, ("inp_rcc8000(0x%x, 0x%x, ...)\n", (int)parseio, (int)ch)); + + switch (ch) + { + case '\n': + parseprintf(DD_PARSE, ("inp_rcc8000: EOL seen\n")); + if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP) + return parse_end(parseio); + else + return rtc; + + + default: + if (parseio->parse_index == 0) /* take sample at start of message */ + { + parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */ + } + return parse_addchar(parseio, ch); + } +} + +#else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_RCC8000) */ +int clk_rcc8000_bs; +#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_RCC8000) */ + +/* + * History: + * + * clk_rcc8000.c,v + * Revision 4.5 1998/06/14 21:09:38 kardel + * Sun acc cleanup + * + * Revision 4.4 1998/06/13 12:05:02 kardel + * fix SYSV clock name clash + * + * Revision 4.3 1998/06/12 15:22:29 kardel + * fix prototypes + * + * Revision 4.2 1998/06/12 09:13:25 kardel + * conditional compile macros fixed + * printf prototype + * + * Revision 4.1 1998/05/24 09:39:53 kardel + * implementation of the new IO handling model + * + * Revision 4.0 1998/04/10 19:45:30 kardel + * Start 4.0 release version numbering + * + * from V3 3.5 log info deleted 1998/04/11 kardel + */ diff --git a/contrib/ntp/libparse/clk_schmid.c b/contrib/ntp/libparse/clk_schmid.c new file mode 100644 index 000000000000..049b4e49c02d --- /dev/null +++ b/contrib/ntp/libparse/clk_schmid.c @@ -0,0 +1,231 @@ +/* + * /src/NTP/ntp-4/libparse/clk_schmid.c,v 4.4 1998/06/13 12:06:03 kardel RELEASE_19990228_A + * + * clk_schmid.c,v 4.4 1998/06/13 12:06:03 kardel RELEASE_19990228_A + * + * Schmid clock support + * + * Copyright (C) 1992-1998 by Frank Kardel + * Friedrich-Alexander Universität Erlangen-Nürnberg, Germany + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#if HAVE_CONFIG_H +# include <config.h> +#endif + +#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_SCHMID) + +#include <sys/types.h> +#include <sys/time.h> + +#include "ntp_fp.h" +#include "ntp_unixtime.h" +#include "ntp_calendar.h" + +#include "parse.h" + +#ifndef PARSESTREAM +#include "ntp_stdlib.h" +#include <stdio.h> +#else +#include "sys/parsestreams.h" +extern void printf P((const char *, ...)); +#endif + +/* + * Description courtesy of Adam W. Feigin et. al (Swisstime iis.ethz.ch) + * + * The command to Schmid's DCF77 clock is a single byte; each bit + * allows the user to select some part of the time string, as follows (the + * output for the lsb is sent first). + * + * Bit 0: time in MEZ, 4 bytes *binary, not BCD*; hh.mm.ss.tenths + * Bit 1: date 3 bytes *binary, not BCD: dd.mm.yy + * Bit 2: week day, 1 byte (unused here) + * Bit 3: time zone, 1 byte, 0=MET, 1=MEST. (unused here) + * Bit 4: clock status, 1 byte, 0=time invalid, + * 1=time from crystal backup, + * 3=time from DCF77 + * Bit 5: transmitter status, 1 byte, + * bit 0: backup antenna + * bit 1: time zone change within 1h + * bit 3,2: TZ 01=MEST, 10=MET + * bit 4: leap second will be + * added within one hour + * bits 5-7: Zero + * Bit 6: time in backup mode, units of 5 minutes (unused here) + * + */ +#define WS_TIME 0x01 +#define WS_SIGNAL 0x02 + +#define WS_ALTERNATE 0x01 +#define WS_ANNOUNCE 0x02 +#define WS_TZ 0x0c +#define WS_MET 0x08 +#define WS_MEST 0x04 +#define WS_LEAP 0x10 + +static u_long cvt_schmid P((unsigned char *, int, struct format *, clocktime_t *, void *)); +static unsigned long inp_schmid P((parse_t *, unsigned int, timestamp_t *)); + +clockformat_t clock_schmid = +{ + inp_schmid, /* no input handling */ + cvt_schmid, /* Schmid conversion */ + 0, /* not direct PPS monitoring */ + 0, /* conversion configuration */ + "Schmid", /* Schmid receiver */ + 12, /* binary data buffer */ + 0, /* no private data (complete messages) */ +}; + + +static u_long +cvt_schmid( + unsigned char *buffer, + int size, + struct format *format, + clocktime_t *clock_time, + void *local + ) +{ + if ((size != 11) || (buffer[10] != (unsigned char)'\375')) + { + return CVT_NONE; + } + else + { + if (buffer[0] > 23 || buffer[1] > 59 || buffer[2] > 59 || buffer[3] > 9) /* Time */ + { + return CVT_FAIL|CVT_BADTIME; + } + else + if (buffer[4] < 1 || buffer[4] > 31 || buffer[5] < 1 || buffer[5] > 12 + || buffer[6] > 99) + { + return CVT_FAIL|CVT_BADDATE; + } + else + { + clock_time->hour = buffer[0]; + clock_time->minute = buffer[1]; + clock_time->second = buffer[2]; + clock_time->usecond = buffer[3] * 100000; + clock_time->day = buffer[4]; + clock_time->month = buffer[5]; + clock_time->year = buffer[6]; + + clock_time->flags = 0; + + switch (buffer[8] & WS_TZ) + { + case WS_MET: + clock_time->utcoffset = -1*60*60; + break; + + case WS_MEST: + clock_time->utcoffset = -2*60*60; + clock_time->flags |= PARSEB_DST; + break; + + default: + return CVT_FAIL|CVT_BADFMT; + } + + if (!(buffer[7] & WS_TIME)) + { + clock_time->flags |= PARSEB_POWERUP; + } + + if (!(buffer[7] & WS_SIGNAL)) + { + clock_time->flags |= PARSEB_NOSYNC; + } + + if (buffer[7] & WS_SIGNAL) + { + if (buffer[8] & WS_ALTERNATE) + { + clock_time->flags |= PARSEB_ALTERNATE; + } + + if (buffer[8] & WS_ANNOUNCE) + { + clock_time->flags |= PARSEB_ANNOUNCE; + } + + if (buffer[8] & WS_LEAP) + { + clock_time->flags |= PARSEB_LEAPADD; /* default: DCF77 data format deficiency */ + } + } + + clock_time->flags |= PARSEB_S_LEAP|PARSEB_S_ANTENNA; + + return CVT_OK; + } + } +} + +/* + * inp_schmid + * + * grep data from input stream + */ +static u_long +inp_schmid( + parse_t *parseio, + unsigned int ch, + timestamp_t *tstamp + ) +{ + unsigned int rtc; + + parseprintf(DD_PARSE, ("inp_schmid(0x%x, 0x%x, ...)\n", (int)parseio, (int)ch)); + + switch (ch) + { + case 0xFD: /* */ + parseprintf(DD_PARSE, ("mbg_input: ETX seen\n")); + if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP) + return parse_end(parseio); + else + return rtc; + + default: + return parse_addchar(parseio, ch); + } +} + +#else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_SCHMID) */ +int clk_schmid_bs; +#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_SCHMID) */ + +/* + * History: + * + * clk_schmid.c,v + * Revision 4.4 1998/06/13 12:06:03 kardel + * fix SYSV clock name clash + * + * Revision 4.3 1998/06/12 15:22:29 kardel + * fix prototypes + * + * Revision 4.2 1998/06/12 09:13:26 kardel + * conditional compile macros fixed + * printf prototype + * + * Revision 4.1 1998/05/24 09:39:53 kardel + * implementation of the new IO handling model + * + * Revision 4.0 1998/04/10 19:45:31 kardel + * Start 4.0 release version numbering + * + * from V3 3.22 log info deleted 1998/04/11 kardel + */ diff --git a/contrib/ntp/libparse/clk_trimtaip.c b/contrib/ntp/libparse/clk_trimtaip.c new file mode 100644 index 000000000000..2fd1eab74694 --- /dev/null +++ b/contrib/ntp/libparse/clk_trimtaip.c @@ -0,0 +1,188 @@ +/* + * /src/NTP/ntp-4/libparse/clk_trimtaip.c,v 4.6 1998/08/16 18:46:27 kardel RELEASE_19990228_A + * + * clk_trimtaip.c,v 4.6 1998/08/16 18:46:27 kardel RELEASE_19990228_A + * + * Trimble SV6 clock support - several collected codepieces + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_TRIMTAIP) +#include <sys/types.h> +#include <sys/time.h> + +#include "ntp_fp.h" +#include "ntp_unixtime.h" +#include "ntp_calendar.h" + +#include "parse.h" + +#ifndef PARSESTREAM +#include "ntp_stdlib.h" +#include <stdio.h> +#else +#include "sys/parsestreams.h" +extern void printf P((const char *, ...)); +#endif + +/* 0000000000111111111122222222223333333 / char + * 0123456789012345678901234567890123456 \ posn + * >RTMhhmmssdddDDMMYYYYoodnnvrrrrr;*xx< Actual + * ----33445566600112222BB7__-_____--99- Parse + * >RTM 1 ;* <", Check + */ + +#define hexval(x) (('0' <= (x) && (x) <= '9') ? (x) - '0' : \ + ('a' <= (x) && (x) <= 'f') ? (x) - 'a' + 10 : \ + ('A' <= (x) && (x) <= 'F') ? (x) - 'A' + 10 : \ + -1) +#define O_USEC O_WDAY +#define O_GPSFIX O_FLAGS +#define O_CHKSUM O_UTCHOFFSET + static struct format trimsv6_fmt = +{ { { 13, 2 }, {15, 2}, { 17, 4}, /* Day, Month, Year */ + { 4, 2 }, { 6, 2}, { 8, 2}, /* Hour, Minute, Second */ + { 10, 3 }, {23, 1}, { 0, 0}, /* uSec, FIXes (WeekDAY, FLAGS, ZONE) */ + { 34, 2 }, { 0, 0}, { 21, 2}, /* cksum, -, utcS (UTC[HMS]OFFSET) */ +}, + (const unsigned char *)">RTM 1 ;* <", + 0 +}; + +static unsigned long cvt_trimtaip P((unsigned char *, int, struct format *, clocktime_t *, void *)); +static unsigned long inp_trimtaip P((parse_t *, unsigned int, timestamp_t *)); + +clockformat_t clock_trimtaip = +{ + inp_trimtaip, /* no input handling */ + cvt_trimtaip, /* Trimble conversion */ + pps_one, /* easy PPS monitoring */ + (void *)&trimsv6_fmt, /* conversion configuration */ + "Trimble TAIP", + 37, /* string buffer */ + 0 /* no private data */ +}; + +static unsigned long +cvt_trimtaip( + unsigned char *buffer, + int size, + struct format *format, + clocktime_t *clock_time, + void *local + ) +{ + long gpsfix; + u_char calc_csum = 0; + long recv_csum; + int i; + + if (!Strok(buffer, format->fixed_string)) return CVT_NONE; +#define OFFS(x) format->field_offsets[(x)].offset +#define STOI(x, y) \ + Stoi(&buffer[OFFS(x)], y, \ + format->field_offsets[(x)].length) + if ( STOI(O_DAY, &clock_time->day) || + STOI(O_MONTH, &clock_time->month) || + STOI(O_YEAR, &clock_time->year) || + STOI(O_HOUR, &clock_time->hour) || + STOI(O_MIN, &clock_time->minute) || + STOI(O_SEC, &clock_time->second) || + STOI(O_USEC, &clock_time->usecond)|| + STOI(O_GPSFIX, &gpsfix) + ) return CVT_FAIL|CVT_BADFMT; + + clock_time->usecond *= 1000; + /* Check that the checksum is right */ + for (i=OFFS(O_CHKSUM)-1; i >= 0; i--) calc_csum ^= buffer[i]; + recv_csum = (hexval(buffer[OFFS(O_CHKSUM)]) << 4) | + hexval(buffer[OFFS(O_CHKSUM)+1]); + if (recv_csum < 0) return CVT_FAIL|CVT_BADTIME; + if (((u_char) recv_csum) != calc_csum) return CVT_FAIL|CVT_BADTIME; + + clock_time->utcoffset = 0; + + /* What should flags be set to ? */ + clock_time->flags = PARSEB_UTC; + + /* if the current GPS fix is 9 (unknown), reject */ + if (0 > gpsfix || gpsfix > 9) clock_time->flags |= PARSEB_POWERUP; + + return CVT_OK; +} + +/* + * inp_trimtaip + * + * grep data from input stream + */ +static u_long +inp_trimtaip( + parse_t *parseio, + unsigned int ch, + timestamp_t *tstamp + ) +{ + unsigned int rtc; + + parseprintf(DD_PARSE, ("inp_trimtaip(0x%x, 0x%x, ...)\n", (int)parseio, (int)ch)); + + switch (ch) + { + case '>': + parseprintf(DD_PARSE, ("inp_trimptaip: START seen\n")); + + parseio->parse_index = 1; + parseio->parse_data[0] = ch; + parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */ + return PARSE_INP_SKIP; + + case '<': + parseprintf(DD_PARSE, ("inp_trimtaip: END seen\n")); + if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP) + return parse_end(parseio); + else + return rtc; + + + default: + return parse_addchar(parseio, ch); + } +} + +#else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_TRIMTAIP) */ +int clk_trimtaip_bs; +#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_TRIMTAIP) */ + +/* + * History: + * + * clk_trimtaip.c,v + * Revision 4.6 1998/08/16 18:46:27 kardel + * (clock_trimtaip =): changed format name + * + * Revision 4.5 1998/06/14 21:09:38 kardel + * Sun acc cleanup + * + * Revision 4.4 1998/06/13 12:06:57 kardel + * fix SYSV clock name clash + * + * Revision 4.3 1998/06/12 15:22:29 kardel + * fix prototypes + * + * Revision 4.2 1998/06/12 09:13:26 kardel + * conditional compile macros fixed + * printf prototype + * + * Revision 4.1 1998/05/24 09:39:54 kardel + * implementation of the new IO handling model + * + * Revision 4.0 1998/04/10 19:45:31 kardel + * Start 4.0 release version numbering + * + * from V3 1.4 log info deleted 1998/04/11 kardel + */ + diff --git a/contrib/ntp/libparse/clk_trimtsip.c b/contrib/ntp/libparse/clk_trimtsip.c new file mode 100644 index 000000000000..52a753649ea6 --- /dev/null +++ b/contrib/ntp/libparse/clk_trimtsip.c @@ -0,0 +1,421 @@ +/* + * /src/NTP/ntp-4/libparse/clk_trimtsip.c,v 4.12 1999/02/28 13:00:08 kardel RELEASE_19990228_A + * + * clk_trimtsip.c,v 4.12 1999/02/28 13:00:08 kardel RELEASE_19990228_A + * + * Trimble TSIP support - CURRENTLY VERY MUCH UNDER CONSTRUCTION + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_TRIMTSIP) + +#include <sys/types.h> +#include <sys/time.h> + +#include "ntp_syslog.h" +#include "ntp_types.h" +#include "ntp_fp.h" +#include "ntp_unixtime.h" +#include "ntp_calendar.h" +#include "ntp_machine.h" +#include "ntp_stdlib.h" + +#include "parse.h" + +#ifndef PARSESTREAM +#include <stdio.h> +#else +#include "sys/parsestreams.h" +# endif + +#include "ascii.h" +#include "binio.h" +#include "ieee754io.h" +#include "trimble.h" + +/* + * Trimble low level TSIP parser / time converter + * + * The receiver uses a serial message protocol called Trimble Standard + * Interface Protocol (it can support others but this driver only supports + * TSIP). Messages in this protocol have the following form: + * + * <DLE><id> ... <data> ... <DLE><ETX> + * + * Any bytes within the <data> portion of value 10 hex (<DLE>) are doubled + * on transmission and compressed back to one on reception. Otherwise + * the values of data bytes can be anything. The serial interface is RS-422 + * asynchronous using 9600 baud, 8 data bits with odd party (**note** 9 bits + * in total!), and 1 stop bit. The protocol supports byte, integer, single, + * and double datatypes. Integers are two bytes, sent most significant first. + * Singles are IEEE754 single precision floating point numbers (4 byte) sent + * sign & exponent first. Doubles are IEEE754 double precision floating point + * numbers (8 byte) sent sign & exponent first. + * The receiver supports a large set of messages, only a very small subset of + * which is used here. + * + * From this module the following are recognised: + * + * ID Description + * + * 41 GPS Time + * 46 Receiver health + * 4F UTC correction data (used to get leap second warnings) + * + * All others are accepted but ignored for time conversion - they are passed up to higher layers. + * + */ + +static offsets_t trim_offsets = { 0, 1, 2, 3, 4, 5, 6, 7 }; + +struct trimble +{ + u_char t_in_pkt; /* first DLE received */ + u_char t_dle; /* subsequent DLE received */ + u_short t_week; /* GPS week */ + u_short t_weekleap; /* GPS week of next/last week */ + u_short t_dayleap; /* day in week */ + u_short t_gpsutc; /* GPS - UTC offset */ + u_short t_gpsutcleap; /* offset at next/last leap */ + u_char t_operable; /* receiver feels OK */ + u_char t_mode; /* actual operating mode */ + u_char t_leap; /* possible leap warning */ + u_char t_utcknown; /* utc offset known */ +}; + +#define STATUS_BAD 0 /* BAD or UNINITIALIZED receiver status */ +#define STATUS_UNSAFE 1 /* not enough receivers for full precision */ +#define STATUS_SYNC 2 /* enough information for good operation */ + +static unsigned long inp_tsip P((parse_t *, unsigned int, timestamp_t *)); +static unsigned long cvt_trimtsip P((unsigned char *, int, struct format *, clocktime_t *, void *)); + +struct clockformat clock_trimtsip = +{ + inp_tsip, /* Trimble TSIP input handler */ + cvt_trimtsip, /* Trimble TSIP conversion */ + pps_one, /* easy PPS monitoring */ + 0, /* no configuration data */ + "Trimble TSIP", + 400, /* input buffer */ + sizeof(struct trimble) /* private data */ +}; + +#define ADDSECOND 0x01 +#define DELSECOND 0x02 + +static unsigned long +inp_tsip( + parse_t *parseio, + unsigned int ch, + timestamp_t *tstamp + ) +{ + struct trimble *t = (struct trimble *)parseio->parse_pdata; + + if (!t) + return PARSE_INP_SKIP; /* local data not allocated - sigh! */ + + if (!t->t_in_pkt && ch != DLE) { + /* wait for start of packet */ + return PARSE_INP_SKIP; + } + + if ((parseio->parse_index >= (parseio->parse_dsize - 2)) || + (parseio->parse_dtime.parse_msglen >= (sizeof(parseio->parse_dtime.parse_msg) - 2))) + { /* OVERFLOW - DROP! */ + t->t_in_pkt = t->t_dle = 0; + parseio->parse_index = 0; + parseio->parse_dtime.parse_msglen = 0; + return PARSE_INP_SKIP; + } + + switch (ch) { + case DLE: + if (!t->t_in_pkt) { + t->t_dle = 0; + t->t_in_pkt = 1; + parseio->parse_index = 0; + parseio->parse_data[parseio->parse_index++] = ch; + parseio->parse_dtime.parse_msglen = 0; + parseio->parse_dtime.parse_msg[parseio->parse_dtime.parse_msglen++] = ch; + parseio->parse_dtime.parse_stime = *tstamp; /* pick up time stamp at packet start */ + } else if (t->t_dle) { + /* Double DLE -> insert a DLE */ + t->t_dle = 0; + parseio->parse_data[parseio->parse_index++] = DLE; + parseio->parse_dtime.parse_msg[parseio->parse_dtime.parse_msglen++] = DLE; + } else + t->t_dle = 1; + break; + + case ETX: + if (t->t_dle) { + /* DLE,ETX -> end of packet */ + parseio->parse_data[parseio->parse_index++] = DLE; + parseio->parse_data[parseio->parse_index] = ch; + parseio->parse_ldsize = parseio->parse_index+1; + memcpy(parseio->parse_ldata, parseio->parse_data, parseio->parse_ldsize); + parseio->parse_dtime.parse_msg[parseio->parse_dtime.parse_msglen++] = DLE; + parseio->parse_dtime.parse_msg[parseio->parse_dtime.parse_msglen++] = ch; + t->t_in_pkt = t->t_dle = 0; + return PARSE_INP_TIME|PARSE_INP_DATA; + } + + default: /* collect data */ + t->t_dle = 0; + parseio->parse_data[parseio->parse_index++] = ch; + parseio->parse_dtime.parse_msg[parseio->parse_dtime.parse_msglen++] = ch; + } + + return PARSE_INP_SKIP; +} + +static int +getshort( + unsigned char *p + ) +{ + return get_msb_short(&p); +} + +/* + * cvt_trimtsip + * + * convert TSIP type format + */ +static unsigned long +cvt_trimtsip( + unsigned char *buffer, + int size, + struct format *format, + clocktime_t *clock_time, + void *local + ) +{ + register struct trimble *t = (struct trimble *)local; /* get local data space */ +#define mb(_X_) (buffer[2+(_X_)]) /* shortcut for buffer access */ + register u_char cmd; + + clock_time->flags = 0; + + if (!t) { + return CVT_NONE; /* local data not allocated - sigh! */ + } + + if ((size < 4) || + (buffer[0] != DLE) || + (buffer[size-1] != ETX) || + (buffer[size-2] != DLE)) + { + printf("TRIMBLE BAD packet, size %d:\n", size); + return CVT_NONE; + } + else + { + unsigned char *bp; + cmd = buffer[1]; + + switch(cmd) + { + case CMD_RCURTIME: + { /* GPS time */ + l_fp secs; + int week = getshort((unsigned char *)&mb(4)); + l_fp utcoffset; + l_fp gpstime; + + bp = &mb(0); + if (fetch_ieee754(&bp, IEEE_SINGLE, &secs, trim_offsets) != IEEE_OK) + return CVT_FAIL|CVT_BADFMT; + + if ((secs.l_i <= 0) || + (t->t_utcknown == 0)) + { + clock_time->flags = PARSEB_POWERUP; + return CVT_OK; + } + if (week < 990) { + week += 1024; + } + + /* time OK */ + + /* fetch UTC offset */ + bp = &mb(6); + if (fetch_ieee754(&bp, IEEE_SINGLE, &utcoffset, trim_offsets) != IEEE_OK) + return CVT_FAIL|CVT_BADFMT; + + L_SUB(&secs, &utcoffset); /* adjust GPS time to UTC time */ + + gpstolfp((unsigned short)week, (unsigned short)0, + secs.l_ui, &gpstime); + + gpstime.l_uf = secs.l_uf; + + clock_time->utctime = gpstime.l_ui - JAN_1970; + + TSFTOTVU(gpstime.l_uf, clock_time->usecond); + + if (t->t_leap == ADDSECOND) + clock_time->flags |= PARSEB_LEAPADD; + + if (t->t_leap == DELSECOND) + clock_time->flags |= PARSEB_LEAPDEL; + + switch (t->t_operable) + { + case STATUS_SYNC: + clock_time->flags &= ~(PARSEB_POWERUP|PARSEB_NOSYNC); + break; + + case STATUS_UNSAFE: + clock_time->flags |= PARSEB_NOSYNC; + break; + + case STATUS_BAD: + clock_time->flags |= PARSEB_NOSYNC|PARSEB_POWERUP; + break; + } + + if (t->t_mode == 0) + clock_time->flags |= PARSEB_POSITION; + + clock_time->flags |= PARSEB_S_LEAP|PARSEB_S_POSITION; + + return CVT_OK; + + } /* case 0x41 */ + + case CMD_RRECVHEALTH: + { + /* TRIMBLE health */ + u_char status = mb(0); + + switch (status) + { + case 0x00: /* position fixes */ + t->t_operable = STATUS_SYNC; + break; + + case 0x09: /* 1 satellite */ + case 0x0A: /* 2 satellites */ + case 0x0B: /* 3 satellites */ + t->t_operable = STATUS_UNSAFE; + break; + + default: + t->t_operable = STATUS_BAD; + break; + } + t->t_mode = status; + } + break; + + case CMD_RUTCPARAM: + { + l_fp t0t; + unsigned char *lbp; + + /* UTC correction data - derive a leap warning */ + int tls = t->t_gpsutc = getshort((unsigned char *)&mb(12)); /* current leap correction (GPS-UTC) */ + int tlsf = t->t_gpsutcleap = getshort((unsigned char *)&mb(24)); /* new leap correction */ + + t->t_weekleap = getshort((unsigned char *)&mb(20)); /* week no of leap correction */ + if (t->t_weekleap < 990) + t->t_weekleap += 1024; + + t->t_dayleap = getshort((unsigned char *)&mb(22)); /* day in week of leap correction */ + t->t_week = getshort((unsigned char *)&mb(18)); /* current week no */ + if (t->t_week < 990) + t->t_week += 1024; + + lbp = (unsigned char *)&mb(14); /* last update time */ + if (fetch_ieee754(&lbp, IEEE_SINGLE, &t0t, trim_offsets) != IEEE_OK) + return CVT_FAIL|CVT_BADFMT; + + t->t_utcknown = t0t.l_ui != 0; + + if ((t->t_utcknown) && /* got UTC information */ + (tlsf != tls) && /* something will change */ + ((t->t_weekleap - t->t_week) < 5)) /* and close in the future */ + { + /* generate a leap warning */ + if (tlsf > tls) + t->t_leap = ADDSECOND; + else + t->t_leap = DELSECOND; + } + else + { + t->t_leap = 0; + } + } + break; + + default: + /* it's validly formed, but we don't care about it! */ + break; + } + } + return CVT_SKIP; +} + +#else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_TRIMTSIP && !PARSESTREAM) */ +int clk_trimtsip_bs; +#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_TRIMTSIP && !PARSESTREAM) */ + +/* + * History: + * + * clk_trimtsip.c,v + * Revision 4.12 1999/02/28 13:00:08 kardel + * *** empty log message *** + * + * Revision 4.11 1999/02/28 11:47:54 kardel + * (struct trimble): new member t_utcknown + * (cvt_trimtsip): fixed status monitoring, bad receiver states are + * now recognized + * + * Revision 4.10 1999/02/27 15:57:15 kardel + * use mmemcpy instead of bcopy + * + * Revision 4.9 1999/02/21 12:17:42 kardel + * 4.91f reconcilation + * + * Revision 4.8 1998/11/15 20:27:58 kardel + * Release 4.0.73e13 reconcilation + * + * Revision 4.7 1998/08/16 18:49:20 kardel + * (cvt_trimtsip): initial kernel capable version (no more floats) + * (clock_trimtsip =): new format name + * + * Revision 4.6 1998/08/09 22:26:05 kardel + * Trimble TSIP support + * + * Revision 4.5 1998/08/02 10:37:05 kardel + * working TSIP parser + * + * Revision 4.4 1998/06/28 16:50:40 kardel + * (getflt): fixed ENDIAN issue + * (getdbl): fixed ENDIAN issue + * (getint): use get_msb_short() + * (cvt_trimtsip): use gpstolfp() for conversion + * + * Revision 4.3 1998/06/13 12:07:31 kardel + * fix SYSV clock name clash + * + * Revision 4.2 1998/06/12 15:22:30 kardel + * fix prototypes + * + * Revision 4.1 1998/05/24 09:39:54 kardel + * implementation of the new IO handling model + * + * Revision 4.0 1998/04/10 19:45:32 kardel + * Start 4.0 release version numbering + * + * from V3 1.8 loginfo deleted 1998/04/11 kardel + */ diff --git a/contrib/ntp/libparse/clk_varitext.c b/contrib/ntp/libparse/clk_varitext.c new file mode 100644 index 000000000000..9236bb4b8c9a --- /dev/null +++ b/contrib/ntp/libparse/clk_varitext.c @@ -0,0 +1,239 @@ +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_VARITEXT) +/* + * clk_varitext.c,v 1.0 1997/01/19 A.McConnell + * + * Supports Varitext's Radio Clock + * + * Used the Meinberg/Computime clock as a template for Varitext Radio Clock + * + * Copyright (C) 1992-1996 by Frank Kardel + * Friedrich-Alexander Universitt Erlangen-Nrnberg, Germany + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#include <sys/types.h> +#include <sys/time.h> + +#include "ntp_fp.h" +#include "ntp_unixtime.h" +#include "ntp_calendar.h" + +#include "parse.h" + +#ifndef PARSESTREAM +#include "ntp_stdlib.h" +#include <stdio.h> +#else +#include "sys/parsestreams.h" +extern void printf P((const char *, ...)); +#endif + +static const u_char VT_INITIALISED = 0x01; +static const u_char VT_SYNCHRONISED = 0x02; +static const u_char VT_ALARM_STATE = 0x04; +static const u_char VT_BST = 0x08; +static const u_char VT_SEASON_CHANGE = 0x10; +static const u_char VT_LAST_TELEGRAM_OK = 0x20; + +/* + * The Varitext receiver sends a datagram in the following format every minute + * + * Timestamp T:YY:MM:MD:WD:HH:MM:SSCRLFSTXXX + * Pos 0123456789012345678901 2 3 4567 + * 0000000000111111111122 2 2 2222 + * Parse T: : : : : : : \r\n + * + * T Startcharacter "T" specifies start of the timestamp + * YY Year MM Month 1-12 + * MD Day of the month + * WD Day of week + * HH Hour + * MM Minute + * SS Second + * CR Carriage return + * LF Linefeed + * ST Status character + * Bit 0 - Set= Initialised; Reset=Time Invalid (DO NOT USE) + * Bit 1 - Set= Synchronised; Reset= Unsynchronised + * Bit 2 - Set= Alarm state; Reset= No alarm + * Bit 3 - Set= BST; Reset= GMT + * Bit 4 - Set= Seasonal change in approx hour; Reset= No seasonal change expected + * Bit 5 - Set= Last MSF telegram was OK; Reset= Last telegram was in error; + * Bit 6 - Always set + * Bit 7 - Unused + * XXX Checksum calculated using Fletcher's method (ignored for now). + */ + +static struct format varitext_fmt = +{ + { + {8, 2}, {5, 2}, {2, 2}, /* day, month, year */ + {14, 2}, {17, 2}, {20, 2}, /* hour, minute, second */ + {11, 2}, {24, 1} /* dayofweek, status */ + }, + (const unsigned char*)"T: : : : : : : \r\n ", + 0 +}; + +static u_long cvt_varitext P((unsigned char *, int, struct format *, clocktime_t *, void *)); +static u_long inp_varitext P((parse_t *, unsigned int, timestamp_t *)); + +struct varitext { + unsigned char start_found; + unsigned char end_found; + unsigned char end_count; + unsigned char previous_ch; + timestamp_t tstamp; +}; + +clockformat_t clock_varitext = +{ + inp_varitext, /* Because of the strange format we need to parse it ourselves */ + cvt_varitext, /* Varitext conversion */ + 0, /* no PPS monitoring */ + (void *)&varitext_fmt, /* conversion configuration */ + "Varitext Radio Clock", /* Varitext Radio Clock */ + 30, /* string buffer */ + sizeof(struct varitext), /* Private data size required to hold current parse state */ +}; + +/* + * cvt_varitext + * + * convert simple type format + */ +static u_long +cvt_varitext( + unsigned char *buffer, + int size, + struct format *format, + clocktime_t *clock_time, + void *local + ) +{ + + if (!Strok(buffer, format->fixed_string)) { + return CVT_NONE; + } else { + if (Stoi(&buffer[format->field_offsets[O_DAY].offset], &clock_time->day, + format->field_offsets[O_DAY].length) || + Stoi(&buffer[format->field_offsets[O_MONTH].offset], &clock_time->month, + format->field_offsets[O_MONTH].length) || + Stoi(&buffer[format->field_offsets[O_YEAR].offset], &clock_time->year, + format->field_offsets[O_YEAR].length) || + Stoi(&buffer[format->field_offsets[O_HOUR].offset], &clock_time->hour, + format->field_offsets[O_HOUR].length) || + Stoi(&buffer[format->field_offsets[O_MIN].offset], &clock_time->minute, + format->field_offsets[O_MIN].length) || + Stoi(&buffer[format->field_offsets[O_SEC].offset], &clock_time->second, + format->field_offsets[O_SEC].length)) { + return CVT_FAIL | CVT_BADFMT; + } else { + u_char *f = (u_char*) &buffer[format->field_offsets[O_FLAGS].offset]; + + clock_time->flags = 0; + clock_time->utcoffset = 0; + + if (((*f) & VT_BST)) /* BST flag is set so set to indicate daylight saving time is active and utc offset */ + { + clock_time->utcoffset = -1*60*60; + clock_time->flags |= PARSEB_DST; + } + /* + if (!((*f) & VT_INITIALISED)) Clock not initialised + clock_time->flags |= PARSEB_POWERUP; + + if (!((*f) & VT_SYNCHRONISED)) Clock not synchronised + clock_time->flags |= PARSEB_NOSYNC; + + if (((*f) & VT_SEASON_CHANGE)) Seasonal change expected in the next hour + clock_time->flags |= PARSEB_ANNOUNCE; + */ + return CVT_OK; + } + } +} + +static u_long +inp_varitext( + parse_t *parseio, + unsigned int ch, + timestamp_t *tstamp + ) +{ + struct varitext *t = (struct varitext *)parseio->parse_pdata; + int rtc; + + parseprintf(DD_PARSE, ("inp_varitext(0x%x, 0x%x, ...)\n", (int)parseio, (int)ch)); + + if (!t) + return PARSE_INP_SKIP; /* local data not allocated - sigh! */ + + if (ch == 'T') + t->tstamp = *tstamp; + + if ((t->previous_ch == 'T') && (ch == ':')) + { + parseprintf(DD_PARSE, ("inp_varitext: START seen\n")); + + parseio->parse_data[0] = 'T'; + parseio->parse_index=1; + parseio->parse_dtime.parse_stime = t->tstamp; /* Time stamp at packet start */ + t->start_found = 1; + t->end_found = 0; + t->end_count = 0; + } + + if (t->start_found) + { + if ((rtc = parse_addchar(parseio, ch)) != PARSE_INP_SKIP) + { + parseprintf(DD_PARSE, ("inp_varitext: ABORTED due to too many characters\n")); + + memset(t, 0, sizeof(struct varitext)); + return rtc; + } + + if (t->end_found) + { + if (++(t->end_count) == 4) /* Finally found the end of the message */ + { + parseprintf(DD_PARSE, ("inp_varitext: END seen\n")); + + memset(t, 0, sizeof(struct varitext)); + if ((rtc = parse_addchar(parseio, 0)) == PARSE_INP_SKIP) + return parse_end(parseio); + else + return rtc; + } + } + + if ((t->previous_ch == '\r') && (ch == '\n')) + { + t->end_found = 1; + } + + } + + t->previous_ch = ch; + + return PARSE_INP_SKIP; +} + +#else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_VARITEXT) */ +int clk_varitext_bs; +#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_VARITEXT) */ + +/* + * Revision 1.0 1997/06/02 13:16:30 McConnell + * File created + * + */ diff --git a/contrib/ntp/libparse/clk_wharton.c b/contrib/ntp/libparse/clk_wharton.c new file mode 100644 index 000000000000..2a243a5c114b --- /dev/null +++ b/contrib/ntp/libparse/clk_wharton.c @@ -0,0 +1,180 @@ +/* + * /src/NTP/ntp-4/libparse/clk_wharton.c,v 4.1 1999/02/28 15:27:24 kardel RELEASE_19990228_A + * + * clk_wharton.c,v 4.1 1999/02/28 15:27:24 kardel RELEASE_19990228_A + * + * From Philippe De Muyter <phdm@macqel.be>, 1999 + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#if defined(REFCLOCK) && defined(CLOCK_PARSE) && defined(CLOCK_WHARTON_400A) +/* + * Support for WHARTON 400A Series clock + 404.2 serial interface. + * + * Copyright (C) 1999 by Philippe De Muyter <phdm@macqel.be> + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#include "ntp_fp.h" +#include "ascii.h" +#include "parse.h" + +#ifndef PARSESTREAM +#include "ntp_stdlib.h" +#include <stdio.h> +#else +#include "sys/parsestreams.h" +extern void printf P((const char *, ...)); +#endif + +/* + * In private e-mail alastair@wharton.co.uk said : + * "If you are going to use the 400A and 404.2 system [for ntp] I recommend + * that you set the 400A to output the message every second. The start of + * transmission of the first byte of the message is synchronised to the + * second edge." + * The WHARTON 400A Series is able to send date/time serial messages + * in 7 output formats. We use format 1 here because it is the shortest. + * For use with this driver, the WHARTON 400A Series clock must be set-up + * as follows : + * Programmable Selected + * Option No Option + * BST or CET display 3 9 or 11 + * No external controller 7 0 + * Serial Output Format 1 9 1 + * Baud rate 9600 bps 10 96 + * Bit length 8 bits 11 8 + * Parity even 12 E + * + * WHARTON 400A Series output format 1 is as follows : + * + * Timestamp STXssmmhhDDMMYYSETX + * Pos 0 12345678901234 + * 0 00000000011111 + * + * STX start transmission (ASCII 0x02) + * ETX end transmission (ASCII 0x03) + * ss Second expressed in reversed decimal (units then tens) + * mm Minute expressed in reversed decimal + * hh Hour expressed in reversed decimal + * DD Day of month expressed in reversed decimal + * MM Month expressed in reversed decimal (January is 1) + * YY Year (without century) expressed in reversed decimal + * S Status byte : 0x30 + + * bit 0 0 = MSF source 1 = DCF source + * bit 1 0 = Winter time 1 = Summer time + * bit 2 0 = not synchronised 1 = synchronised + * bit 3 0 = no early warning 1 = early warning + * + */ + +/* + * cvt_wharton_400a + * + * convert simple type format + */ +static u_long +cvt_wharton_400a( + unsigned char *buffer, + int size, + struct format *format, + clocktime_t *clock_time, + void *local + ) +{ + int i; + + /* The given `size' includes a terminating null-character. */ + if (size != 16 || buffer[0] != STX || buffer[14] != ETX) + return CVT_NONE; + for (i = 1; i < 14; i += 1) + if (buffer[i] < '0' || buffer[i] > '9') + return CVT_NONE; + clock_time->second = (buffer[2] - '0') * 10 + buffer[1] - '0'; + clock_time->minute = (buffer[4] - '0') * 10 + buffer[3] - '0'; + clock_time->hour = (buffer[6] - '0') * 10 + buffer[5] - '0'; + clock_time->day = (buffer[8] - '0') * 10 + buffer[7] - '0'; + clock_time->month = (buffer[10] - '0') * 10 + buffer[9] - '0'; + clock_time->year = (buffer[12] - '0') * 10 + buffer[11] - '0'; + clock_time->usecond = 0; + if (buffer[13] & 0x1) /* We have CET time */ + clock_time->utcoffset = -1*60*60; + else /* We have BST time */ + clock_time->utcoffset = 0; + if (buffer[13] & 0x2) { + clock_time->flags |= PARSEB_DST; + clock_time->utcoffset += -1*60*60; + } + if (!(buffer[13] & 0x4)) + clock_time->flags |= PARSEB_NOSYNC; + if (buffer[13] & 0x8) + clock_time->flags |= PARSEB_ANNOUNCE; + + return CVT_OK; +} + +/* + * inp_wharton_400a + * + * grep data from input stream + */ +static u_long +inp_wharton_400a( + parse_t *parseio, + unsigned int ch, + timestamp_t *tstamp + ) +{ + unsigned int rtc; + + parseprintf(DD_PARSE, ("inp_wharton_400a(0x%x, 0x%x, ...)\n", (int)parseio, (int)ch)); + + switch (ch) + { + case STX: + parseprintf(DD_PARSE, ("inp_wharton_400a: STX seen\n")); + + parseio->parse_index = 1; + parseio->parse_data[0] = ch; + parseio->parse_dtime.parse_stime = *tstamp; /* collect timestamp */ + return PARSE_INP_SKIP; + + case ETX: + parseprintf(DD_PARSE, ("inp_wharton_400a: ETX seen\n")); + if ((rtc = parse_addchar(parseio, ch)) == PARSE_INP_SKIP) + return parse_end(parseio); + else + return rtc; + + default: + return parse_addchar(parseio, ch); + } +} + +clockformat_t clock_wharton_400a = +{ + inp_wharton_400a, /* input handling function */ + cvt_wharton_400a, /* conversion function */ + 0, /* no PPS monitoring */ + 0, /* conversion configuration */ + "WHARTON 400A Series clock Output Format 1", /* String format name */ + 15, /* string buffer */ + 0 /* no private data (complete pakets) */ +}; + +#else /* not (REFCLOCK && CLOCK_PARSE && CLOCK_WHARTON_400A) */ +int clk_wharton_400a_bs; +#endif /* not (REFCLOCK && CLOCK_PARSE && CLOCK_WHARTON_400A) */ + +/* + * clk_wharton.c,v + * Revision 4.1 1999/02/28 15:27:24 kardel + * wharton clock integration + * + */ diff --git a/contrib/ntp/libparse/data_mbg.c b/contrib/ntp/libparse/data_mbg.c new file mode 100644 index 000000000000..af7987d0714a --- /dev/null +++ b/contrib/ntp/libparse/data_mbg.c @@ -0,0 +1,490 @@ +/* + * /src/NTP/ntp-4/libparse/data_mbg.c,v 4.3 1999/02/21 12:17:42 kardel RELEASE_19990228_A + * + * $Created: Sun Jul 20 12:08:14 1997 $ + * + * Copyright (C) 1997, 1998 by Frank Kardel + */ + +#ifdef PARSESTREAM +#define NEED_BOPS +#include "ntp_string.h" +#else +#include <stdio.h> +#endif +#include "ntp_types.h" +#include "ntp_stdlib.h" +#include "ntp_fp.h" +#include "mbg_gps166.h" +#include "binio.h" +#include "ieee754io.h" + +static void get_mbg_tzname P((unsigned char **, char *)); +static void mbg_time_status_str P((unsigned char **, unsigned int)); + +#if 0 /* no actual floats on Meinberg binary interface */ +static offsets_t mbg_float = { 1, 0, 3, 2, 0, 0, 0, 0 }; /* byte order for meinberg floats */ +#endif +static offsets_t mbg_double = { 1, 0, 3, 2, 5, 4, 7, 6 }; /* byte order for meinberg doubles */ +static int32 rad2deg_i = 57; +static u_int32 rad2deg_f = 0x4BB834C7; /* 57.2957795131 == 180/PI */ + +void +put_mbg_header( + unsigned char **bufpp, + GPS_MSG_HDR *headerp + ) +{ + put_lsb_short(bufpp, headerp->gps_cmd); + put_lsb_short(bufpp, headerp->gps_len); + put_lsb_short(bufpp, headerp->gps_data_csum); + put_lsb_short(bufpp, headerp->gps_hdr_csum); +} + +void +get_mbg_sw_rev( + unsigned char **bufpp, + SW_REV *sw_revp + ) +{ + sw_revp->code = get_lsb_short(bufpp); + memcpy(sw_revp->name, *bufpp, sizeof(sw_revp->name)); + *bufpp += sizeof(sw_revp->name); +} + +void +get_mbg_ascii_msg( + unsigned char **bufpp, + ASCII_MSG *ascii_msgp + ) +{ + ascii_msgp->csum = get_lsb_short(bufpp); + ascii_msgp->valid = get_lsb_short(bufpp); + memcpy(ascii_msgp->s, *bufpp, sizeof(ascii_msgp->s)); + *bufpp += sizeof(ascii_msgp->s); +} + +void +get_mbg_svno( + unsigned char **bufpp, + SVNO *svnop + ) +{ + *svnop = get_lsb_short(bufpp); +} + +void +get_mbg_health( + unsigned char **bufpp, + HEALTH *healthp + ) +{ + *healthp = get_lsb_short(bufpp); +} + +void +get_mbg_cfg( + unsigned char **bufpp, + CFG *cfgp + ) +{ + *cfgp = get_lsb_short(bufpp); +} + +void +get_mbg_tgps( + unsigned char **bufpp, + T_GPS *tgpsp + ) +{ + tgpsp->wn = get_lsb_short(bufpp); + tgpsp->sec = get_lsb_long(bufpp); + tgpsp->tick = get_lsb_long(bufpp); +} + +void +get_mbg_tm( + unsigned char **buffpp, + TM *tmp + ) +{ + tmp->year = get_lsb_short(buffpp); + tmp->month = *(*buffpp)++; + tmp->mday = *(*buffpp)++; + tmp->yday = get_lsb_short(buffpp); + tmp->wday = *(*buffpp)++; + tmp->hour = *(*buffpp)++; + tmp->minute = *(*buffpp)++; + tmp->second = *(*buffpp)++; + tmp->frac = get_lsb_long(buffpp); + tmp->offs_from_utc = get_lsb_long(buffpp); + tmp->status= get_lsb_short(buffpp); +} + +void +get_mbg_ttm( + unsigned char **buffpp, + TTM *ttmp + ) +{ + ttmp->channel = get_lsb_short(buffpp); + get_mbg_tgps(buffpp, &ttmp->t); + get_mbg_tm(buffpp, &ttmp->tm); +} + +void +get_mbg_synth( + unsigned char **buffpp, + SYNTH *synthp + ) +{ + synthp->freq = get_lsb_short(buffpp); + synthp->range = get_lsb_short(buffpp); + synthp->phase = get_lsb_short(buffpp); +} + +static void +get_mbg_tzname( + unsigned char **buffpp, + char *tznamep + ) +{ + strncpy(tznamep, (char *)*buffpp, sizeof(TZ_NAME)); + *buffpp += sizeof(TZ_NAME); +} + +void +get_mbg_tzdl( + unsigned char **buffpp, + TZDL *tzdlp + ) +{ + tzdlp->offs = get_lsb_long(buffpp); + tzdlp->offs_dl = get_lsb_long(buffpp); + get_mbg_tm(buffpp, &tzdlp->tm_on); + get_mbg_tm(buffpp, &tzdlp->tm_off); + get_mbg_tzname(buffpp, (char *)tzdlp->name[0]); + get_mbg_tzname(buffpp, (char *)tzdlp->name[1]); +} + +void +get_mbg_antinfo( + unsigned char **buffpp, + ANT_INFO *antinfop + ) +{ + antinfop->status = get_lsb_short(buffpp); + get_mbg_tm(buffpp, &antinfop->tm_disconn); + get_mbg_tm(buffpp, &antinfop->tm_reconn); + antinfop->delta_t = get_lsb_long(buffpp); +} + +static void +mbg_time_status_str( + unsigned char **buffpp, + unsigned int status + ) +{ + static struct state + { + int flag; /* bit flag */ + const char *string; /* bit name */ + } states[] = + { + { TM_UTC, "UTC CORR" }, + { TM_LOCAL, "LOCAL TIME" }, + { TM_DL_ANN, "DST WARN" }, + { TM_DL_ENB, "DST" }, + { TM_LS_ANN, "LEAP WARN" }, + { TM_LS_ENB, "LEAP SEC" }, + { 0, "" } + }; + + if (status) + { + unsigned char *p; + struct state *s; + + p = *buffpp; + + for (s = states; s->flag; s++) + { + if (s->flag & status) + { + if (p != *buffpp) + { + *p++ = ','; + *p++ = ' '; + } + strcpy((char *)p, s->string); + p += strlen((char *)p); + } + } + *buffpp = p; + } +} + +void +mbg_tm_str( + unsigned char **buffpp, + TM *tmp + ) +{ + sprintf((char *)*buffpp, "%04d-%02d-%02d %02d:%02d:%02d.%07ld (%c%02d%02d) ", + tmp->year, tmp->month, tmp->mday, + tmp->hour, tmp->minute, tmp->second, tmp->frac, + (tmp->offs_from_utc < 0) ? '-' : '+', + abs(tmp->offs_from_utc) / 3600, + (abs(tmp->offs_from_utc) / 60) % 60); + *buffpp += strlen((char *)*buffpp); + mbg_time_status_str(buffpp, tmp->status); +} + +void +mbg_tgps_str( + unsigned char **buffpp, + T_GPS *tgpsp + ) +{ + sprintf((char *)*buffpp, "week %d + %ld days + %ld.%07ld sec", + tgpsp->wn, tgpsp->sec / 86400, + tgpsp->sec % 86400, tgpsp->tick); + *buffpp += strlen((char *)*buffpp); +} + +void +get_mbg_cfgh( + unsigned char **buffpp, + CFGH *cfghp + ) +{ + int i; + + cfghp->csum = get_lsb_short(buffpp); + cfghp->valid = get_lsb_short(buffpp); + get_mbg_tgps(buffpp, &cfghp->tot_51); + get_mbg_tgps(buffpp, &cfghp->tot_63); + get_mbg_tgps(buffpp, &cfghp->t0a); + + for (i = MIN_SVNO; i <= MAX_SVNO; i++) + { + get_mbg_cfg(buffpp, &cfghp->cfg[i]); + } + + for (i = MIN_SVNO; i <= MAX_SVNO; i++) + { + get_mbg_health(buffpp, &cfghp->health[i]); + } +} + +void +get_mbg_utc( + unsigned char **buffpp, + UTC *utcp + ) +{ + utcp->csum = get_lsb_short(buffpp); + utcp->valid = get_lsb_short(buffpp); + + get_mbg_tgps(buffpp, &utcp->t0t); + + if (fetch_ieee754(buffpp, IEEE_DOUBLE, &utcp->A0, mbg_double) != IEEE_OK) + { + L_CLR(&utcp->A0); + } + + if (fetch_ieee754(buffpp, IEEE_DOUBLE, &utcp->A1, mbg_double) != IEEE_OK) + { + L_CLR(&utcp->A1); + } + + utcp->WNlsf = get_lsb_short(buffpp); + utcp->DNt = get_lsb_short(buffpp); + utcp->delta_tls = *(*buffpp)++; + utcp->delta_tlsf = *(*buffpp)++; +} + +void +get_mbg_lla( + unsigned char **buffpp, + LLA lla + ) +{ + int i; + + for (i = LAT; i <= ALT; i++) + { + if (fetch_ieee754(buffpp, IEEE_DOUBLE, &lla[i], mbg_double) != IEEE_OK) + { + L_CLR(&lla[i]); + } + else + if (i != ALT) + { /* convert to degrees (* 180/PI) */ + mfp_mul(&lla[i].l_i, &lla[i].l_uf, lla[i].l_i, lla[i].l_uf, rad2deg_i, rad2deg_f); + } + } +} + +void +get_mbg_xyz( + unsigned char **buffpp, + XYZ xyz + ) +{ + int i; + + for (i = XP; i <= ZP; i++) + { + if (fetch_ieee754(buffpp, IEEE_DOUBLE, &xyz[i], mbg_double) != IEEE_OK) + { + L_CLR(&xyz[i]); + } + } +} + +static void +get_mbg_comparam( + unsigned char **buffpp, + COM_PARM *comparamp + ) +{ + int i; + + comparamp->baud_rate = get_lsb_long(buffpp); + for (i = 0; i < sizeof(comparamp->framing); i++) + { + comparamp->framing[i] = *(*buffpp)++; + } + comparamp->handshake = get_lsb_short(buffpp); +} + +void +get_mbg_portparam( + unsigned char **buffpp, + PORT_PARM *portparamp + ) +{ + int i; + + for (i = 0; i < N_COM; i++) + { + get_mbg_comparam(buffpp, &portparamp->com[i]); + } + for (i = 0; i < N_COM; i++) + { + portparamp->mode[i] = *(*buffpp)++; + } +} + +#define FETCH_DOUBLE(src, addr) \ + if (fetch_ieee754(src, IEEE_DOUBLE, addr, mbg_double) != IEEE_OK) \ + { \ + L_CLR(addr); \ + } + +void +get_mbg_eph( + unsigned char ** buffpp, + EPH *ephp + ) +{ + ephp->csum = get_lsb_short(buffpp); + ephp->valid = get_lsb_short(buffpp); + + ephp->health = get_lsb_short(buffpp); + ephp->IODC = get_lsb_short(buffpp); + ephp->IODE2 = get_lsb_short(buffpp); + ephp->IODE3 = get_lsb_short(buffpp); + + get_mbg_tgps(buffpp, &ephp->tt); + get_mbg_tgps(buffpp, &ephp->t0c); + get_mbg_tgps(buffpp, &ephp->t0e); + + FETCH_DOUBLE(buffpp, &ephp->sqrt_A); + FETCH_DOUBLE(buffpp, &ephp->e); + FETCH_DOUBLE(buffpp, &ephp->M0); + FETCH_DOUBLE(buffpp, &ephp->omega); + FETCH_DOUBLE(buffpp, &ephp->OMEGA0); + FETCH_DOUBLE(buffpp, &ephp->OMEGADOT); + FETCH_DOUBLE(buffpp, &ephp->deltan); + FETCH_DOUBLE(buffpp, &ephp->i0); + FETCH_DOUBLE(buffpp, &ephp->idot); + FETCH_DOUBLE(buffpp, &ephp->crc); + FETCH_DOUBLE(buffpp, &ephp->crs); + FETCH_DOUBLE(buffpp, &ephp->cuc); + FETCH_DOUBLE(buffpp, &ephp->cus); + FETCH_DOUBLE(buffpp, &ephp->cic); + FETCH_DOUBLE(buffpp, &ephp->cis); + + FETCH_DOUBLE(buffpp, &ephp->af0); + FETCH_DOUBLE(buffpp, &ephp->af1); + FETCH_DOUBLE(buffpp, &ephp->af2); + FETCH_DOUBLE(buffpp, &ephp->tgd); + + ephp->URA = get_lsb_short(buffpp); + + ephp->L2code = *(*buffpp)++; + ephp->L2flag = *(*buffpp)++; +} + +void +get_mbg_alm( + unsigned char **buffpp, + ALM *almp + ) +{ + almp->csum = get_lsb_short(buffpp); + almp->valid = get_lsb_short(buffpp); + + almp->health = get_lsb_short(buffpp); + get_mbg_tgps(buffpp, &almp->t0a); + + + FETCH_DOUBLE(buffpp, &almp->sqrt_A); + FETCH_DOUBLE(buffpp, &almp->e); + + FETCH_DOUBLE(buffpp, &almp->M0); + FETCH_DOUBLE(buffpp, &almp->omega); + FETCH_DOUBLE(buffpp, &almp->OMEGA0); + FETCH_DOUBLE(buffpp, &almp->OMEGADOT); + FETCH_DOUBLE(buffpp, &almp->deltai); + FETCH_DOUBLE(buffpp, &almp->af0); + FETCH_DOUBLE(buffpp, &almp->af1); +} + +void +get_mbg_iono( + unsigned char **buffpp, + IONO *ionop + ) +{ + ionop->csum = get_lsb_short(buffpp); + ionop->valid = get_lsb_short(buffpp); + + FETCH_DOUBLE(buffpp, &ionop->alpha_0); + FETCH_DOUBLE(buffpp, &ionop->alpha_1); + FETCH_DOUBLE(buffpp, &ionop->alpha_2); + FETCH_DOUBLE(buffpp, &ionop->alpha_3); + + FETCH_DOUBLE(buffpp, &ionop->beta_0); + FETCH_DOUBLE(buffpp, &ionop->beta_1); + FETCH_DOUBLE(buffpp, &ionop->beta_2); + FETCH_DOUBLE(buffpp, &ionop->beta_3); +} + +/* + * data_mbg.c,v + * Revision 4.3 1999/02/21 12:17:42 kardel + * 4.91f reconcilation + * + * Revision 4.2 1998/06/14 21:09:39 kardel + * Sun acc cleanup + * + * Revision 4.1 1998/05/24 08:02:06 kardel + * trimmed version log + * + * Revision 4.0 1998/04/10 19:45:33 kardel + * Start 4.0 release version numbering + */ + diff --git a/contrib/ntp/libparse/info_trimble.c b/contrib/ntp/libparse/info_trimble.c new file mode 100644 index 000000000000..af508582aa95 --- /dev/null +++ b/contrib/ntp/libparse/info_trimble.c @@ -0,0 +1,94 @@ +/* +* Automatically generated - do not modify +*/ + +#include "ntp_types.h" +#include "ntpd.h" +#include "trimble.h" + +cmd_info_t trimble_scmds[] = { + { CMD_CCLROSC, "CMD_CCLROSC", "clear oscillator offset (0x1D)", "", 0 }, + { CMD_CCLRRST, "CMD_CCLRRST", "clear battery backup and RESET (0x1E)", "", 0 }, + { CMD_CVERSION, "CMD_CVERSION", "return software version (0x1F)", "", 0 }, + { CMD_CALMANAC, "CMD_CALMANAC", "almanac (0x20)", "", 0 }, + { CMD_CCURTIME, "CMD_CCURTIME", "current time (0x21)", "", 0 }, + { CMD_CMODESEL, "CMD_CMODESEL", "mode select (2-d, 3-D, auto) (0x22)", "", 0 }, + { CMD_CINITPOS, "CMD_CINITPOS", "initial position (0x23)", "", 0 }, + { CMD_CRECVPOS, "CMD_CRECVPOS", "receiver position fix mode (0x24)", "", 0 }, + { CMD_CRESET, "CMD_CRESET", "soft reset & selftest (0x25)", "", 0 }, + { CMD_CRECVHEALTH, "CMD_CRECVHEALTH", "receiver health (0x26)", "", 0 }, + { CMD_CSIGNALLV, "CMD_CSIGNALLV", "signal levels (0x27)", "", 0 }, + { CMD_CMESSAGE, "CMD_CMESSAGE", "GPS system message (0x28)", "", 0 }, + { CMD_CALMAHEALTH, "CMD_CALMAHEALTH", "almanac healt page (0x29)", "", 0 }, + { CMD_C2DALTITUDE, "CMD_C2DALTITUDE", "altitude for 2-D mode (0x2A)", "", 0 }, + { CMD_CINITPOSLLA, "CMD_CINITPOSLLA", "initial position LLA (0x2B)", "", 0 }, + { CMD_COPERPARAM, "CMD_COPERPARAM", "operating parameters (0x2C)", "", 0 }, + { CMD_COSCOFFSET, "CMD_COSCOFFSET", "oscillator offset (0x2D)", "", 0 }, + { CMD_CSETGPSTIME, "CMD_CSETGPSTIME", "set GPS time (0x2E)", "", 0 }, + { CMD_CUTCPARAM, "CMD_CUTCPARAM", "UTC parameters (0x2F)", "", 0 }, + { CMD_CACCPOSXYZ, "CMD_CACCPOSXYZ", "accurate initial position (XYZ/ECEF) (0x31)", "", 0 }, + { CMD_CACCPOS, "CMD_CACCPOS", "accurate initial position (0x32)", "", 0 }, + { CMD_CANALOGDIG, "CMD_CANALOGDIG", "analog to digital (0x33)", "", 0 }, + { CMD_CSAT1SAT, "CMD_CSAT1SAT", "satellite for 1-Sat mode (0x34)", "", 0 }, + { CMD_CIOOPTIONS, "CMD_CIOOPTIONS", "I/O options (0x35)", "", 0 }, + { CMD_CVELOCAID, "CMD_CVELOCAID", "velocity aiding of acquisition (0x36)", "", 0 }, + { CMD_CSTATLSTPOS, "CMD_CSTATLSTPOS", "status and values of last pos. and vel. (0x37)", "", 0 }, + { CMD_CLOADSSATDT, "CMD_CLOADSSATDT", "load satellite system data (0x38)", "", 0 }, + { CMD_CSATDISABLE, "CMD_CSATDISABLE", "satellite disable (0x39)", "", 0 }, + { CMD_CLASTRAW, "CMD_CLASTRAW", "last raw measurement (0x3A)", "", 0 }, + { CMD_CSTATSATEPH, "CMD_CSTATSATEPH", "satellite ephemeris status (0x3B)", "", 0 }, + { CMD_CSTATTRACK, "CMD_CSTATTRACK", "tracking status (0x3C)", "", 0 }, + { CMD_CCHANADGPS, "CMD_CCHANADGPS", "configure channel A for differential GPS (0x3D)", "", 0 }, + { CMD_CADDITFIX, "CMD_CADDITFIX", "additional fix data (0x3E)", "", 0 }, + { CMD_CDGPSFIXMD, "CMD_CDGPSFIXMD", "set/request differential GPS position fix mode (0x62)", "", 0 }, + { CMD_CDGPSCORR, "CMD_CDGPSCORR", "differential correction status (0x65)", "", 0 }, + { CMD_CPOSFILT, "CMD_CPOSFILT", "position filter parameters (0x71)", "", 0 }, + { CMD_CHEIGHTFILT, "CMD_CHEIGHTFILT", "height filter control (0x73)", "", 0 }, + { CMD_CHIGH8CNT, "CMD_CHIGH8CNT", "high-8 (best 4) / high-6 (overdetermined) control (0x75)", "", 0 }, + { CMD_CMAXDGPSCOR, "CMD_CMAXDGPSCOR", "maximum rate of DGPS corrections (0x77)", "", 0 }, + { CMD_CSUPER, "CMD_CSUPER", "super paket (0x8E)", "", 0 }, +{ 0xFF, "", "" } +}; + + +cmd_info_t trimble_rcmds[] = { + { CMD_RDATAA, "CMD_RDATAA", "data channel A configuration (0x3D)", "trimble_channelA", RO }, + { CMD_RALMANAC, "CMD_RALMANAC", "almanac data for sat (0x40)", "gps_almanac", RO }, + { CMD_RCURTIME, "CMD_RCURTIME", "GPS time (0x41)", "gps_time", RO }, + { CMD_RSPOSXYZ, "CMD_RSPOSXYZ", "single precision XYZ position (0x42)", "gps_position(XYZ)", RO|DEF }, + { CMD_RVELOXYZ, "CMD_RVELOXYZ", "velocity fix (XYZ ECEF) (0x43)", "gps_velocity(XYZ)", RO|DEF }, + { CMD_RBEST4, "CMD_RBEST4", "best 4 satellite selection (0x44)", "trimble_best4", RO|DEF }, + { CMD_RVERSION, "CMD_RVERSION", "software version (0x45)", "trimble_version", RO|DEF }, + { CMD_RRECVHEALTH, "CMD_RRECVHEALTH", "receiver health (0x46)", "trimble_receiver_health", RO|DEF }, + { CMD_RSIGNALLV, "CMD_RSIGNALLV", "signal levels of all satellites (0x47)", "trimble_signal_levels", RO }, + { CMD_RMESSAGE, "CMD_RMESSAGE", "GPS system message (0x48)", "gps-message", RO|DEF }, + { CMD_RALMAHEALTH, "CMD_RALMAHEALTH", "almanac health page for all satellites (0x49)", "gps_almanac_health", RO }, + { CMD_RSLLAPOS, "CMD_RSLLAPOS", "single LLA position (0x4A)", "gps_position(LLA)", RO|DEF }, + { CMD_RMACHSTAT, "CMD_RMACHSTAT", "machine code / status (0x4B)", "trimble_status", RO|DEF }, + { CMD_ROPERPARAM, "CMD_ROPERPARAM", "operating parameters (0x4C)", "trimble_opparam", RO }, + { CMD_ROSCOFFSET, "CMD_ROSCOFFSET", "oscillator offset (0x4D)", "trimble_oscoffset", RO }, + { CMD_RSETGPSTIME, "CMD_RSETGPSTIME", "response to set GPS time (0x4E)", "trimble_setgpstime", RO }, + { CMD_RUTCPARAM, "CMD_RUTCPARAM", "UTC parameters (0x4F)", "gps_utc_correction", RO|DEF }, + { CMD_RANALOGDIG, "CMD_RANALOGDIG", "analog to digital (0x53)", "trimble_analogdigital", RO }, + { CMD_RSAT1BIAS, "CMD_RSAT1BIAS", "one-satellite bias & bias rate (0x54)", "trimble_sat1bias", RO }, + { CMD_RIOOPTIONS, "CMD_RIOOPTIONS", "I/O options (0x55)", "trimble_iooptions", RO }, + { CMD_RSTATLSTFIX, "CMD_RSTATLSTFIX", "status and values of last pos. and vel. (0x57)", "trimble_status_lastpos", RO }, + { CMD_RLOADSSATDT, "CMD_RLOADSSATDT", "response to load satellite system data (0x58)", "trimble_loaddata", RO }, + { CMD_RSATDISABLE, "CMD_RSATDISABLE", "satellite disable (0x59)", "trimble_satdisble", RO }, + { CMD_RLASTRAW, "CMD_RLASTRAW", "last raw measurement (0x5A)", "trimble_lastraw", RO }, + { CMD_RSTATSATEPH, "CMD_RSTATSATEPH", "satellite ephemeris status (0x5B)", "trimble_ephstatus", RO }, + { CMD_RSTATTRACK, "CMD_RSTATTRACK", "tracking status (0x5C)", "trimble_tracking_status", RO|DEF }, + { CMD_RADDITFIX, "CMD_RADDITFIX", "additional fix data (0x5E)", "trimble_addfix", RO }, + { CMD_RALLINVIEW, "CMD_RALLINVIEW", "all in view satellite selection (0x6D)", "trimble_satview", RO|DEF }, + { CMD_RPOSFILT, "CMD_RPOSFILT", "position filter parameters (0x72)", "trimble_posfilt", RO }, + { CMD_RHEIGHTFILT, "CMD_RHEIGHTFILT", "height filter control (0x74)", "trimble_heightfilt", RO }, + { CMD_RHIGH8CNT, "CMD_RHIGH8CNT", "high-8 (best 4) / high-6 (overdetermined) control (0x76)", "trimble_high8control", RO }, + { CMD_RMAXAGE, "CMD_RMAXAGE", "DC MaxAge (0x78)", "trimble_dgpsmaxage", RO }, + { CMD_RDGPSFIX, "CMD_RDGPSFIX", "differential position fix mode (0x82)", "trimble_dgpsfixmode", RO }, + { CMD_RDOUBLEXYZ, "CMD_RDOUBLEXYZ", "double precision XYZ (0x83)", "gps_position_ext(XYZ)", RO|DEF }, + { CMD_RDOUBLELLA, "CMD_RDOUBLELLA", "double precision LLA (0x84)", "gps_position_ext(LLA)", RO|DEF }, + { CMD_RDGPSSTAT, "CMD_RDGPSSTAT", "differential correction status (0x85)", "trimble_dgpsstatus", RO }, + { CMD_RSUPER, "CMD_RSUPER", "super paket (0x8F)", "", 0 }, +{ 0xFF, "", "" } +}; + diff --git a/contrib/ntp/libparse/kclk_computime.c b/contrib/ntp/libparse/kclk_computime.c new file mode 100644 index 000000000000..14707b98801f --- /dev/null +++ b/contrib/ntp/libparse/kclk_computime.c @@ -0,0 +1,17 @@ +/* + * /src/NTP/ntp-4/libparse/kclk_computime.c,v 4.2 1998/07/11 10:05:27 kardel RELEASE_19990228_A + * + * $Created: Sat Jun 13 09:58:27 1998 $ + * + * Copyright (C) 1998 by Frank Kardel + */ +#define PARSESTREAM +#include "clk_computime.c" +/* + * kclk_computime.c,v + * Revision 4.2 1998/07/11 10:05:27 kardel + * Release 4.0.73d reconcilation + * + * Revision 4.1 1998/06/13 12:09:27 kardel + * hack to compile the source for kernel/user-land + */ diff --git a/contrib/ntp/libparse/kclk_dcf7000.c b/contrib/ntp/libparse/kclk_dcf7000.c new file mode 100644 index 000000000000..e5d9436c565b --- /dev/null +++ b/contrib/ntp/libparse/kclk_dcf7000.c @@ -0,0 +1,17 @@ +/* + * /src/NTP/ntp-4/libparse/kclk_dcf7000.c,v 4.2 1998/07/11 10:05:27 kardel RELEASE_19990228_A + * + * $Created: Sat Jun 13 09:59:11 1998 $ + * + * Copyright (C) 1998 by Frank Kardel + */ +#define PARSESTREAM +#include "clk_dcf7000.c" +/* + * kclk_dcf7000.c,v + * Revision 4.2 1998/07/11 10:05:27 kardel + * Release 4.0.73d reconcilation + * + * Revision 4.1 1998/06/13 12:09:28 kardel + * hack to compile the source for kernel/user-land + */ diff --git a/contrib/ntp/libparse/kclk_hopf6021.c b/contrib/ntp/libparse/kclk_hopf6021.c new file mode 100644 index 000000000000..2d51788b625e --- /dev/null +++ b/contrib/ntp/libparse/kclk_hopf6021.c @@ -0,0 +1,17 @@ +/* + * /src/NTP/ntp-4/libparse/kclk_hopf6021.c,v 4.2 1998/07/11 10:05:28 kardel RELEASE_19990228_A + * + * $Created: Sat Jun 13 09:59:57 1998 $ + * + * Copyright (C) 1998 by Frank Kardel + */ +#define PARSESTREAM +#include "clk_hopf6021.c" +/* + * kclk_hopf6021.c,v + * Revision 4.2 1998/07/11 10:05:28 kardel + * Release 4.0.73d reconcilation + * + * Revision 4.1 1998/06/13 12:09:29 kardel + * hack to compile the source for kernel/user-land + */ diff --git a/contrib/ntp/libparse/kclk_meinberg.c b/contrib/ntp/libparse/kclk_meinberg.c new file mode 100644 index 000000000000..7cdb3e17093a --- /dev/null +++ b/contrib/ntp/libparse/kclk_meinberg.c @@ -0,0 +1,17 @@ +/* + * /src/NTP/ntp-4/libparse/kclk_meinberg.c,v 4.2 1998/07/11 10:05:28 kardel RELEASE_19990228_A + * + * $Created: Sat Jun 13 10:00:28 1998 $ + * + * Copyright (C) 1998 by Frank Kardel + */ +#define PARSESTREAM +#include "clk_meinberg.c" +/* + * kclk_meinberg.c,v + * Revision 4.2 1998/07/11 10:05:28 kardel + * Release 4.0.73d reconcilation + * + * Revision 4.1 1998/06/13 12:09:29 kardel + * hack to compile the source for kernel/user-land + */ diff --git a/contrib/ntp/libparse/kclk_rawdcf.c b/contrib/ntp/libparse/kclk_rawdcf.c new file mode 100644 index 000000000000..45ba743764f2 --- /dev/null +++ b/contrib/ntp/libparse/kclk_rawdcf.c @@ -0,0 +1,15 @@ +/* + * /src/NTP/ntp-4/libparse/kclk_rawdcf.c,v 4.1 1998/06/13 12:07:55 kardel RELEASE_19990228_A + * + * $Created: Sat Jun 13 10:03:35 1998 $ + * + * Copyright (C) 1998 by Frank Kardel + */ +#define PARSESTREAM +#include "clk_rawdcf.c" +/* + * kclk_rawdcf.c,v + * Revision 4.1 1998/06/13 12:07:55 kardel + * standard format + * + */ diff --git a/contrib/ntp/libparse/kclk_rcc8000.c b/contrib/ntp/libparse/kclk_rcc8000.c new file mode 100644 index 000000000000..67e6550b96c1 --- /dev/null +++ b/contrib/ntp/libparse/kclk_rcc8000.c @@ -0,0 +1,17 @@ +/* + * /src/NTP/ntp-4/libparse/kclk_rcc8000.c,v 4.2 1998/07/11 10:05:28 kardel RELEASE_19990228_A + * + * $Created: Sat Jun 13 10:01:11 1998 $ + * + * Copyright (C) 1998 by Frank Kardel + */ +#define PARSESTREAM +#include "clk_rcc8000.c" +/* + * kclk_rcc8000.c,v + * Revision 4.2 1998/07/11 10:05:28 kardel + * Release 4.0.73d reconcilation + * + * Revision 4.1 1998/06/13 12:09:29 kardel + * hack to compile the source for kernel/user-land + */ diff --git a/contrib/ntp/libparse/kclk_schmid.c b/contrib/ntp/libparse/kclk_schmid.c new file mode 100644 index 000000000000..ee87b7eed059 --- /dev/null +++ b/contrib/ntp/libparse/kclk_schmid.c @@ -0,0 +1,17 @@ +/* + * /src/NTP/ntp-4/libparse/kclk_schmid.c,v 4.2 1998/07/11 10:05:28 kardel RELEASE_19990228_A + * + * $Created: Sat Jun 13 10:01:42 1998 $ + * + * Copyright (C) 1998 by Frank Kardel + */ +#define PARSESTREAM +#include "clk_schmid.c" +/* + * kclk_schmid.c,v + * Revision 4.2 1998/07/11 10:05:28 kardel + * Release 4.0.73d reconcilation + * + * Revision 4.1 1998/06/13 12:09:30 kardel + * hack to compile the source for kernel/user-land + */ diff --git a/contrib/ntp/libparse/kclk_trimtaip.c b/contrib/ntp/libparse/kclk_trimtaip.c new file mode 100644 index 000000000000..20193f4e7b27 --- /dev/null +++ b/contrib/ntp/libparse/kclk_trimtaip.c @@ -0,0 +1,17 @@ +/* + * /src/NTP/ntp-4/libparse/kclk_trimtaip.c,v 4.2 1998/07/11 10:05:29 kardel RELEASE_19990228_A + * + * $Created: Sat Jun 13 10:02:35 1998 $ + * + * Copyright (C) 1998 by Frank Kardel + */ +#define PARSESTREAM +#include "clk_trimtaip.c" +/* + * kclk_trimtaip.c,v + * Revision 4.2 1998/07/11 10:05:29 kardel + * Release 4.0.73d reconcilation + * + * Revision 4.1 1998/06/13 12:09:30 kardel + * hack to compile the source for kernel/user-land + */ diff --git a/contrib/ntp/libparse/kclk_trimtsip.c b/contrib/ntp/libparse/kclk_trimtsip.c new file mode 100644 index 000000000000..1dcfec8029f8 --- /dev/null +++ b/contrib/ntp/libparse/kclk_trimtsip.c @@ -0,0 +1,17 @@ +/* + * /src/NTP/ntp-4/libparse/kclk_trimtsip.c,v 4.2 1998/07/11 10:05:29 kardel RELEASE_19990228_A + * + * $Created: Sat Jun 13 10:04:12 1998 $ + * + * Copyright (C) 1998 by Frank Kardel + */ +#define PARSESTREAM +#include "clk_trimtsip.c" +/* + * kclk_trimtsip.c,v + * Revision 4.2 1998/07/11 10:05:29 kardel + * Release 4.0.73d reconcilation + * + * Revision 4.1 1998/06/13 12:08:02 kardel + * standard format + */ diff --git a/contrib/ntp/libparse/kclk_varitext.c b/contrib/ntp/libparse/kclk_varitext.c new file mode 100644 index 000000000000..3ecc69dc228d --- /dev/null +++ b/contrib/ntp/libparse/kclk_varitext.c @@ -0,0 +1,28 @@ +/* + * $Header: /cvs/ntp/libparse/kclk_varitext.c,v 1.1 1999/07/25 09:21:16 stenn Exp $ + * + * $Created: Sat Jun 13 09:58:27 1998 $ + * + * Copyright (C) 1998 by Frank Kardel + */ +#define PARSESTREAM +#include "clk_varitext.c" +/* + * $Log: kclk_varitext.c,v $ + * Revision 1.1 1999/07/25 09:21:16 stenn + * * configure.in: 4.0.94b + * + * * acconfig.h: + * * configure.in: + * * libparse/Makefile.am: + * * libparse/parse_conf.c: + * * libparse/clk_varitext.c: + * * libparse/kclk_varitext.c: + * * ntpd/refclock_parse.c: VARITEXT parse clock + * * ntpdate/ntpdate.c: bugfix + * From: Tony McConnell <tonym@datel-technology.co.uk> + * + * Revision 4.1 1998/06/13 12:09:27 kardel + * hack to compile the source for kernel/user-land + * + */ diff --git a/contrib/ntp/libparse/kclk_wharton.c b/contrib/ntp/libparse/kclk_wharton.c new file mode 100644 index 000000000000..0496f773d6d2 --- /dev/null +++ b/contrib/ntp/libparse/kclk_wharton.c @@ -0,0 +1,15 @@ +/* + * /src/NTP/ntp-4/libparse/kclk_wharton.c,v 4.1 1999/02/28 15:50:08 kardel RELEASE_19990228_A + * + * $Created: Sun Feb 28 16:46:14 MET 1999 $ + * + * Copyright (C) 1999 by Frank Kardel + */ +#define PARSESTREAM +#include "clk_wharton.c" +/* + * kclk_wharton.c,v + * Revision 4.1 1999/02/28 15:50:08 kardel + * new clock input machine + * + */ diff --git a/contrib/ntp/libparse/kparse.c b/contrib/ntp/libparse/kparse.c new file mode 100644 index 000000000000..a79943d76d81 --- /dev/null +++ b/contrib/ntp/libparse/kparse.c @@ -0,0 +1,17 @@ +/* + * /src/NTP/ntp-4/libparse/kparse.c,v 4.2 1998/07/11 10:05:29 kardel RELEASE_19990228_A + * + * $Created: Sat Jun 13 10:04:47 1998 $ + * + * Copyright (C) 1998 by Frank Kardel + */ +#define PARSESTREAM +#include "parse.c" +/* + * kparse.c,v + * Revision 4.2 1998/07/11 10:05:29 kardel + * Release 4.0.73d reconcilation + * + * Revision 4.1 1998/06/13 12:08:12 kardel + * standard format + */ diff --git a/contrib/ntp/libparse/kparse_conf.c b/contrib/ntp/libparse/kparse_conf.c new file mode 100644 index 000000000000..be8628e3e179 --- /dev/null +++ b/contrib/ntp/libparse/kparse_conf.c @@ -0,0 +1,17 @@ +/* + * /src/NTP/ntp-4/libparse/kparse_conf.c,v 4.2 1998/07/11 10:05:30 kardel RELEASE_19990228_A + * + * $Created: Sat Jun 13 10:05:32 1998 $ + * + * Copyright (C) 1998 by Frank Kardel + */ +#define PARSESTREAM +#include "parse_conf.c" +/* + * kparse_conf.c,v + * Revision 4.2 1998/07/11 10:05:30 kardel + * Release 4.0.73d reconcilation + * + * Revision 4.1 1998/06/13 12:08:12 kardel + * standard format + */ diff --git a/contrib/ntp/libparse/mkinfo_rcmd.sed b/contrib/ntp/libparse/mkinfo_rcmd.sed new file mode 100644 index 000000000000..570c7a0b81e2 --- /dev/null +++ b/contrib/ntp/libparse/mkinfo_rcmd.sed @@ -0,0 +1,8 @@ +1i\ +\ +cmd_info_t trimble_rcmds[] = { +s!^#define[ ][ ]*\(CMD_R[^ ]*\)[ ][ ]*\([^ ]*\)[ ][ ]*/\*[ ][ ]*\(.*\)[ ]*:\([^:]*\):\([^:]*\)[ ][ ]*\*/! { \1, "\1", "\3 (\2)", "\4", \5 },!p +$a\ + { 0xFF, "", "" }\ +};\ + diff --git a/contrib/ntp/libparse/mkinfo_scmd.sed b/contrib/ntp/libparse/mkinfo_scmd.sed new file mode 100644 index 000000000000..cabe0654588d --- /dev/null +++ b/contrib/ntp/libparse/mkinfo_scmd.sed @@ -0,0 +1,16 @@ +1i\ +/*\ + * Automatically generated - do not modify\ + */\ +\ +#include "ntp_types.h"\ +#include "ntpd.h"\ +#include "trimble.h"\ +\ +cmd_info_t trimble_scmds[] = { +s!^#define[ ][ ]*\(CMD_C[^ ]*\)[ ][ ]*\([^ ]*\)[ ][ ]*/\*[ ][ ]*\(.*\)[ ][ ]*\*/! { \1, "\1", "\3 (\2)", "", 0 },!p +$a\ + { 0xFF, "", "" }\ +};\ + + diff --git a/contrib/ntp/libparse/parse.c b/contrib/ntp/libparse/parse.c new file mode 100644 index 000000000000..3d8485e14254 --- /dev/null +++ b/contrib/ntp/libparse/parse.c @@ -0,0 +1,917 @@ +/* + * /src/NTP/ntp-4/libparse/parse.c,v 4.13 1999/02/28 11:50:20 kardel RELEASE_19990228_A + * + * parse.c,v 4.13 1999/02/28 11:50:20 kardel RELEASE_19990228_A + * + * Parser module for reference clock + * + * PARSEKERNEL define switches between two personalities of the module + * if PARSEKERNEL is defined this module can be used + * as kernel module. In this case the time stamps will be + * a struct timeval. + * when PARSEKERNEL is not defined NTP time stamps will be used. + * + * Copyright (c) 1992-1998 by Frank Kardel + * Friedrich-Alexander Universität Erlangen-Nürnberg, Germany + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#if defined(REFCLOCK) && defined(CLOCK_PARSE) + +#if !(defined(lint) || defined(__GNUC__)) +static char rcsid[] = "parse.c,v 4.13 1999/02/28 11:50:20 kardel RELEASE_19990228_A"; +#endif + +#include <sys/types.h> +#include <sys/time.h> + +#include "ntp_fp.h" +#include "ntp_unixtime.h" +#include "ntp_calendar.h" +#include "ntp_stdlib.h" +#include "ntp_machine.h" +#include "ntp.h" /* (get Y2KFixes definitions) Y2KFixes */ + +#include "parse.h" + +#ifndef PARSESTREAM +#include <stdio.h> +#else +#include "sys/parsestreams.h" +#endif + +extern clockformat_t *clockformats[]; +extern unsigned short nformats; + +static u_long timepacket P((parse_t *)); + +/* + * strings support usually not in kernel - duplicated, but what the heck + */ +static int +Strlen( + register const char *s + ) +{ + register int c; + + c = 0; + if (s) + { + while (*s++) + { + c++; + } + } + return c; +} + +static int +Strcmp( + register const char *s, + register const char *t + ) +{ + register int c = 0; + + if (!s || !t || (s == t)) + { + return 0; + } + + while (!(c = *s++ - *t++) && *s && *t) + /* empty loop */; + + return c; +} + +int +parse_timedout( + parse_t *parseio, + timestamp_t *tstamp, + struct timeval *del + ) +{ + struct timeval delta; + +#ifdef PARSEKERNEL + delta.tv_sec = tstamp->tv.tv_sec - parseio->parse_lastchar.tv.tv_sec; + delta.tv_usec = tstamp->tv.tv_usec - parseio->parse_lastchar.tv.tv_usec; + if (delta.tv_usec < 0) + { + delta.tv_sec -= 1; + delta.tv_usec += 1000000; + } +#else + extern long tstouslo[]; + extern long tstousmid[]; + extern long tstoushi[]; + + l_fp delt; + + delt = tstamp->fp; + L_SUB(&delt, &parseio->parse_lastchar.fp); + TSTOTV(&delt, &delta); +#endif + + if (timercmp(&delta, del, >)) + { + parseprintf(DD_PARSE, ("parse: timedout: TRUE\n")); + return 1; + } + else + { + parseprintf(DD_PARSE, ("parse: timedout: FALSE\n")); + return 0; + } +} + +/*ARGSUSED*/ +int +parse_ioinit( + register parse_t *parseio + ) +{ + parseprintf(DD_PARSE, ("parse_iostart\n")); + + parseio->parse_plen = 0; + parseio->parse_pdata = (void *)0; + + parseio->parse_data = 0; + parseio->parse_ldata = 0; + parseio->parse_dsize = 0; + + parseio->parse_badformat = 0; + parseio->parse_ioflags = PARSE_IO_CS7; /* usual unix default */ + parseio->parse_index = 0; + parseio->parse_ldsize = 0; + + return 1; +} + +/*ARGSUSED*/ +void +parse_ioend( + register parse_t *parseio + ) +{ + parseprintf(DD_PARSE, ("parse_ioend\n")); + + if (parseio->parse_pdata) + FREE(parseio->parse_pdata, parseio->parse_plen); + + if (parseio->parse_data) + FREE(parseio->parse_data, (unsigned)(parseio->parse_dsize * 2 + 2)); +} + +unsigned int +parse_restart( + parse_t *parseio, + unsigned int ch + ) +{ + unsigned int updated = PARSE_INP_SKIP; + + /* + * re-start packet - timeout - overflow - start symbol + */ + + if (parseio->parse_index) + { + /* + * filled buffer - thus not end character found + * do processing now + */ + parseio->parse_data[parseio->parse_index] = '\0'; + memcpy(parseio->parse_ldata, parseio->parse_data, (unsigned)(parseio->parse_index+1)); + parseio->parse_ldsize = parseio->parse_index+1; + updated = PARSE_INP_TIME; + } + + parseio->parse_index = 1; + parseio->parse_data[0] = ch; + parseprintf(DD_PARSE, ("parse: parse_restart: buffer start (updated = %x)\n", updated)); + return updated; +} + +unsigned int +parse_addchar( + parse_t *parseio, + unsigned int ch + ) +{ + /* + * add to buffer + */ + if (parseio->parse_index < parseio->parse_dsize) + { + /* + * collect into buffer + */ + parseprintf(DD_PARSE, ("parse: parse_addchar: buffer[%d] = 0x%x\n", parseio->parse_index, ch)); + parseio->parse_data[parseio->parse_index++] = ch; + return PARSE_INP_SKIP; + } + else + /* + * buffer overflow - attempt to make the best of it + */ + return parse_restart(parseio, ch); +} + +unsigned int +parse_end( + parse_t *parseio + ) +{ + /* + * message complete processing + */ + parseio->parse_data[parseio->parse_index] = '\0'; + memcpy(parseio->parse_ldata, parseio->parse_data, (unsigned)(parseio->parse_index+1)); + parseio->parse_ldsize = parseio->parse_index+1; + parseio->parse_index = 0; + parseprintf(DD_PARSE, ("parse: parse_end: buffer end\n")); + return PARSE_INP_TIME; +} + +/*ARGSUSED*/ +int +parse_ioread( + register parse_t *parseio, + register unsigned int ch, + register timestamp_t *tstamp + ) +{ + register unsigned updated = CVT_NONE; + /* + * within STREAMS CSx (x < 8) chars still have the upper bits set + * so we normalize the characters by masking unecessary bits off. + */ + switch (parseio->parse_ioflags & PARSE_IO_CSIZE) + { + case PARSE_IO_CS5: + ch &= 0x1F; + break; + + case PARSE_IO_CS6: + ch &= 0x3F; + break; + + case PARSE_IO_CS7: + ch &= 0x7F; + break; + + case PARSE_IO_CS8: + ch &= 0xFF; + break; + } + + parseprintf(DD_PARSE, ("parse_ioread(0x%lx, char=0x%x, ..., ...)\n", (unsigned long)parseio, ch & 0xFF)); + + if (!clockformats[parseio->parse_lformat]->convert) + { + parseprintf(DD_PARSE, ("parse_ioread: input dropped.\n")); + return CVT_NONE; + } + + if (clockformats[parseio->parse_lformat]->input) + { + unsigned long input_status; + + input_status = clockformats[parseio->parse_lformat]->input(parseio, ch, tstamp); + + if (input_status & PARSE_INP_SYNTH) + { + updated = CVT_OK; + } + + if (input_status & PARSE_INP_TIME) /* time sample is available */ + { + updated = timepacket(parseio); + } + + if (input_status & PARSE_INP_DATA) /* got additional data */ + { + updated |= CVT_ADDITIONAL; + } + } + + + /* + * remember last character time + */ + parseio->parse_lastchar = *tstamp; + +#ifdef DEBUG + if ((updated & CVT_MASK) != CVT_NONE) + { + parseprintf(DD_PARSE, ("parse_ioread: time sample accumulated (status=0x%x)\n", updated)); + } +#endif + + parseio->parse_dtime.parse_status = updated; + + return (((updated & CVT_MASK) != CVT_NONE) || + ((updated & CVT_ADDITIONAL) != 0)); +} + +/* + * parse_iopps + * + * take status line indication and derive synchronisation information + * from it. + * It can also be used to decode a serial serial data format (such as the + * ONE, ZERO, MINUTE sync data stream from DCF77) + */ +/*ARGSUSED*/ +int +parse_iopps( + register parse_t *parseio, + register int status, + register timestamp_t *ptime + ) +{ + register unsigned updated = CVT_NONE; + + /* + * PPS pulse information will only be delivered to ONE clock format + * this is either the last successful conversion module with a ppssync + * routine, or a fixed format with a ppssync routine + */ + parseprintf(DD_PARSE, ("parse_iopps: STATUS %s\n", (status == SYNC_ONE) ? "ONE" : "ZERO")); + + if (clockformats[parseio->parse_lformat]->syncpps) + { + updated = clockformats[parseio->parse_lformat]->syncpps(parseio, status == SYNC_ONE, ptime); + parseprintf(DD_PARSE, ("parse_iopps: updated = 0x%x\n", updated)); + } + + return (updated & CVT_MASK) != CVT_NONE; +} + +/* + * parse_iodone + * + * clean up internal status for new round + */ +/*ARGSUSED*/ +void +parse_iodone( + register parse_t *parseio + ) +{ + /* + * we need to clean up certain flags for the next round + */ + parseprintf(DD_PARSE, ("parse_iodone: DONE\n")); + parseio->parse_dtime.parse_state = 0; /* no problems with ISRs */ +} + +/*---------- conversion implementation --------------------*/ + +/* + * convert a struct clock to UTC since Jan, 1st 1970 0:00 (the UNIX EPOCH) + */ +#define days_per_year(x) ((x) % 4 ? 365 : ((x % 400) ? ((x % 100) ? 366 : 365) : 366)) + +time_t +parse_to_unixtime( + register clocktime_t *clock_time, + register u_long *cvtrtc + ) +{ +#define SETRTC(_X_) { if (cvtrtc) *cvtrtc = (_X_); } + static int days_of_month[] = + { + 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 + }; + register int i; + time_t t; + + if (clock_time->utctime) + return clock_time->utctime; /* if the conversion routine gets it right away - why not */ + + if ( clock_time->year < YEAR_PIVOT ) /* Y2KFixes [ */ + clock_time->year += 100; /* convert 20xx%100 to 20xx-1900 */ + if ( clock_time->year < YEAR_BREAK ) /* expand to full four-digits */ + clock_time->year += 1900; + + if (clock_time->year < 1970 ) /* Y2KFixes ] */ + { + SETRTC(CVT_FAIL|CVT_BADDATE); + return -1; + } + + /* + * sorry, slow section here - but it's not time critical anyway + */ + t = julian0(clock_time->year) - julian0(1970); /* Y2kFixes */ + /* month */ + if (clock_time->month <= 0 || clock_time->month > 12) + { + SETRTC(CVT_FAIL|CVT_BADDATE); + return -1; /* bad month */ + } + +#if 0 /* Y2KFixes */ + /* adjust leap year */ + if (clock_time->month < 3 && days_per_year(clock_time->year) == 366) + t--; +#else /* Y2KFixes [ */ + if ( clock_time->month >= 3 && isleap_4(clock_time->year) ) + t++; /* add one more if within leap year */ +#endif /* Y2KFixes ] */ + + for (i = 1; i < clock_time->month; i++) + { + t += days_of_month[i]; + } + /* day */ + if (clock_time->day < 1 || ((clock_time->month == 2 && days_per_year(clock_time->year) == 366) ? + clock_time->day > 29 : clock_time->day > days_of_month[clock_time->month])) + { + SETRTC(CVT_FAIL|CVT_BADDATE); + return -1; /* bad day */ + } + + t += clock_time->day - 1; + /* hour */ + if (clock_time->hour < 0 || clock_time->hour >= 24) + { + SETRTC(CVT_FAIL|CVT_BADTIME); + return -1; /* bad hour */ + } + + t = TIMES24(t) + clock_time->hour; + + /* min */ + if (clock_time->minute < 0 || clock_time->minute > 59) + { + SETRTC(CVT_FAIL|CVT_BADTIME); + return -1; /* bad min */ + } + + t = TIMES60(t) + clock_time->minute; + /* sec */ + + if (clock_time->second < 0 || clock_time->second > 60) /* allow for LEAPs */ + { + SETRTC(CVT_FAIL|CVT_BADTIME); + return -1; /* bad sec */ + } + + t = TIMES60(t) + clock_time->second; + + t += clock_time->utcoffset; /* warp to UTC */ + + /* done */ + + clock_time->utctime = t; /* documentray only */ + + return t; +} + +/*--------------- format conversion -----------------------------------*/ + +int +Stoi( + const unsigned char *s, + long *zp, + int cnt + ) +{ + char unsigned const *b = s; + int f,z,v; + char unsigned c; + + f=z=v=0; + + while(*s == ' ') + s++; + + if (*s == '-') + { + s++; + v = 1; + } + else + if (*s == '+') + s++; + + for(;;) + { + c = *s++; + if (c == '\0' || c < '0' || c > '9' || (cnt && ((s-b) > cnt))) + { + if (f == 0) + { + return(-1); + } + if (v) + z = -z; + *zp = z; + return(0); + } + z = (z << 3) + (z << 1) + ( c - '0' ); + f=1; + } +} + +int +Strok( + const unsigned char *s, + const unsigned char *m + ) +{ + if (!s || !m) + return 0; + + while(*s && *m) + { + if ((*m == ' ') ? 1 : (*s == *m)) + { + s++; + m++; + } + else + { + return 0; + } + } + return !*m; +} + +u_long +updatetimeinfo( + register parse_t *parseio, + register u_long flags + ) +{ +#ifdef PARSEKERNEL + { + int s = splhigh(); +#endif + + parseio->parse_lstate = parseio->parse_dtime.parse_state | flags | PARSEB_TIMECODE; + + parseio->parse_dtime.parse_state = parseio->parse_lstate; + +#ifdef PARSEKERNEL + (void)splx((unsigned int)s); + } +#endif + + +#ifdef PARSEKERNEL + parseprintf(DD_PARSE, ("updatetimeinfo status=0x%x, time=%x\n", parseio->parse_dtime.parse_state, + parseio->parse_dtime.parse_time.tv.tv_sec)); +#else + parseprintf(DD_PARSE, ("updatetimeinfo status=0x%lx, time=%x\n", (long)parseio->parse_dtime.parse_state, + parseio->parse_dtime.parse_time.fp.l_ui)); +#endif + + return CVT_OK; /* everything fine and dandy... */ +} + + +/* + * syn_simple + * + * handle a sync time stamp + */ +/*ARGSUSED*/ +void +syn_simple( + register parse_t *parseio, + register timestamp_t *ts, + register struct format *format, + register u_long why + ) +{ + parseio->parse_dtime.parse_stime = *ts; +} + +/* + * pps_simple + * + * handle a pps time stamp + */ +/*ARGSUSED*/ +u_long +pps_simple( + register parse_t *parseio, + register int status, + register timestamp_t *ptime + ) +{ + parseio->parse_dtime.parse_ptime = *ptime; + parseio->parse_dtime.parse_state |= PARSEB_PPS|PARSEB_S_PPS; + + return CVT_NONE; +} + +/* + * pps_one + * + * handle a pps time stamp in ONE edge + */ +/*ARGSUSED*/ +u_long +pps_one( + register parse_t *parseio, + register int status, + register timestamp_t *ptime + ) +{ + if (status) + return pps_simple(parseio, status, ptime); + + return CVT_NONE; +} + +/* + * pps_zero + * + * handle a pps time stamp in ZERO edge + */ +/*ARGSUSED*/ +u_long +pps_zero( + register parse_t *parseio, + register int status, + register timestamp_t *ptime + ) +{ + if (!status) + return pps_simple(parseio, status, ptime); + + return CVT_NONE; +} + +/* + * timepacket + * + * process a data packet + */ +static u_long +timepacket( + register parse_t *parseio + ) +{ + register unsigned short format; + register time_t t; + u_long cvtrtc; /* current conversion result */ + clocktime_t clock_time; + + memset((char *)&clock_time, 0, sizeof clock_time); + format = parseio->parse_lformat; + + if (format == (unsigned short)~0) + return CVT_NONE; + + switch ((cvtrtc = clockformats[format]->convert ? + clockformats[format]->convert((unsigned char *)parseio->parse_ldata, parseio->parse_ldsize, (struct format *)(clockformats[format]->data), &clock_time, parseio->parse_pdata) : + CVT_NONE) & CVT_MASK) + { + case CVT_FAIL: + parseio->parse_badformat++; + break; + + case CVT_NONE: + /* + * too bad - pretend bad format + */ + parseio->parse_badformat++; + break; + + case CVT_OK: + break; + + case CVT_SKIP: + return CVT_NONE; + + default: + /* shouldn't happen */ +#ifndef PARSEKERNEL + msyslog(LOG_WARNING, "parse: INTERNAL error: bad return code of convert routine \"%s\"\n", clockformats[format]->name); +#endif + return CVT_FAIL|cvtrtc; + } + + if ((t = parse_to_unixtime(&clock_time, &cvtrtc)) == -1) + { + return CVT_FAIL|cvtrtc; + } + + /* + * time stamp + */ +#ifdef PARSEKERNEL + parseio->parse_dtime.parse_time.tv.tv_sec = t; + parseio->parse_dtime.parse_time.tv.tv_usec = clock_time.usecond; +#else + parseio->parse_dtime.parse_time.fp.l_ui = t + JAN_1970; + TVUTOTSF(clock_time.usecond, parseio->parse_dtime.parse_time.fp.l_uf); +#endif + + parseio->parse_dtime.parse_format = format; + + return updatetimeinfo(parseio, clock_time.flags); +} + +/*ARGSUSED*/ +int +parse_timecode( + parsectl_t *dct, + parse_t *parse + ) +{ + dct->parsegettc.parse_state = parse->parse_lstate; + dct->parsegettc.parse_format = parse->parse_lformat; + /* + * move out current bad packet count + * user program is expected to sum these up + * this is not a problem, as "parse" module are + * exclusive open only + */ + dct->parsegettc.parse_badformat = parse->parse_badformat; + parse->parse_badformat = 0; + + if (parse->parse_ldsize <= PARSE_TCMAX) + { + dct->parsegettc.parse_count = parse->parse_ldsize; + memcpy(dct->parsegettc.parse_buffer, parse->parse_ldata, dct->parsegettc.parse_count); + return 1; + } + else + { + return 0; + } +} + + +/*ARGSUSED*/ +int +parse_setfmt( + parsectl_t *dct, + parse_t *parse + ) +{ + if (dct->parseformat.parse_count <= PARSE_TCMAX) + { + if (dct->parseformat.parse_count) + { + register unsigned short i; + + for (i = 0; i < nformats; i++) + { + if (!Strcmp(dct->parseformat.parse_buffer, clockformats[i]->name)) + { + if (parse->parse_pdata) + FREE(parse->parse_pdata, parse->parse_plen); + parse->parse_pdata = 0; + + parse->parse_plen = clockformats[i]->plen; + + if (parse->parse_plen) + { + parse->parse_pdata = MALLOC(parse->parse_plen); + if (!parse->parse_pdata) + { + parseprintf(DD_PARSE, ("set format failed: malloc for private data area failed\n")); + return 0; + } + memset((char *)parse->parse_pdata, 0, parse->parse_plen); + } + + if (parse->parse_data) + FREE(parse->parse_data, (unsigned)(parse->parse_dsize * 2 + 2)); + parse->parse_ldata = parse->parse_data = 0; + + parse->parse_dsize = clockformats[i]->length; + + if (parse->parse_dsize) + { + parse->parse_data = (char*)MALLOC((unsigned)(parse->parse_dsize * 2 + 2)); + if (!parse->parse_data) + { + if (parse->parse_pdata) + FREE(parse->parse_pdata, parse->parse_plen); + parse->parse_pdata = 0; + + parseprintf(DD_PARSE, ("init failed: malloc for data area failed\n")); + return 0; + } + } + + + /* + * leave room for '\0' + */ + parse->parse_ldata = parse->parse_data + parse->parse_dsize + 1; + + parse->parse_lformat = i; + + return 1; + } + } + } + } + return 0; +} + +/*ARGSUSED*/ +int +parse_getfmt( + parsectl_t *dct, + parse_t *parse + ) +{ + if (dct->parseformat.parse_format < nformats && + Strlen(clockformats[dct->parseformat.parse_format]->name) <= PARSE_TCMAX) + { + dct->parseformat.parse_count = Strlen(clockformats[dct->parseformat.parse_format]->name)+1; + memcpy(dct->parseformat.parse_buffer, clockformats[dct->parseformat.parse_format]->name, dct->parseformat.parse_count); + return 1; + } + else + { + return 0; + } +} + +/*ARGSUSED*/ +int +parse_setcs( + parsectl_t *dct, + parse_t *parse + ) +{ + parse->parse_ioflags &= ~PARSE_IO_CSIZE; + parse->parse_ioflags |= dct->parsesetcs.parse_cs & PARSE_IO_CSIZE; + return 1; +} + +#else /* not (REFCLOCK && CLOCK_PARSE) */ +int parse_bs; +#endif /* not (REFCLOCK && CLOCK_PARSE) */ + +/* + * History: + * + * parse.c,v + * Revision 4.13 1999/02/28 11:50:20 kardel + * (timepacket): removed unecessary code + * + * Revision 4.12 1999/02/21 12:17:44 kardel + * 4.91f reconcilation + * + * Revision 4.11 1999/02/21 11:09:47 kardel + * unified debug output + * + * Revision 4.10 1998/12/20 23:45:30 kardel + * fix types and warnings + * + * Revision 4.9 1998/08/09 22:26:06 kardel + * Trimble TSIP support + * + * Revision 4.8 1998/06/14 21:09:39 kardel + * Sun acc cleanup + * + * Revision 4.7 1998/06/13 15:19:13 kardel + * fix mem*() to b*() function macro emulation + * + * Revision 4.6 1998/06/13 13:24:13 kardel + * printf fmt + * + * Revision 4.5 1998/06/13 13:01:10 kardel + * printf fmt + * + * Revision 4.4 1998/06/13 12:12:10 kardel + * bcopy/memcpy cleanup + * fix SVSV name clash + * + * Revision 4.3 1998/06/12 15:22:30 kardel + * fix prototypes + * + * Revision 4.2 1998/06/12 09:13:27 kardel + * conditional compile macros fixed + * printf prototype + * + * Revision 4.1 1998/05/24 09:39:55 kardel + * implementation of the new IO handling model + * + * Revision 4.0 1998/04/10 19:45:36 kardel + * Start 4.0 release version numbering + * + * from V3 3.46 log info deleted 1998/04/11 kardel + */ diff --git a/contrib/ntp/libparse/parse_conf.c b/contrib/ntp/libparse/parse_conf.c new file mode 100644 index 000000000000..3333cd97d6e1 --- /dev/null +++ b/contrib/ntp/libparse/parse_conf.c @@ -0,0 +1,149 @@ +/* + * /src/NTP/ntp-4/libparse/parse_conf.c,v 4.4 1999/02/28 15:27:25 kardel RELEASE_19990228_A + * + * parse_conf.c,v 4.4 1999/02/28 15:27:25 kardel RELEASE_19990228_A + * + * Parser configuration module for reference clocks + * + * STREAM define switches between two personalities of the module + * if STREAM is defined this module can be used with dcf77sync.c as + * a STREAMS kernel module. In this case the time stamps will be + * a struct timeval. + * when STREAM is not defined NTP time stamps will be used. + * + * Copyright (C) 1995-1998 by Frank Kardel + * Copyright (C) 1992-1994 by Frank Kardel, Friedrich-Alexander Universität Erlangen-Nürnberg, Germany + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#if defined(REFCLOCK) && defined(CLOCK_PARSE) + +#include <sys/types.h> +#include <sys/time.h> + +#include "ntp_fp.h" +#include "ntp_unixtime.h" +#include "ntp_calendar.h" + +#include "parse.h" + +#ifdef CLOCK_SCHMID +extern clockformat_t clock_schmid; +#endif + +#ifdef CLOCK_DCF7000 +extern clockformat_t clock_dcf7000; +#endif + +#ifdef CLOCK_MEINBERG +extern clockformat_t clock_meinberg[]; +#endif + +#ifdef CLOCK_RAWDCF +extern clockformat_t clock_rawdcf; +#endif + +#ifdef CLOCK_TRIMTAIP +extern clockformat_t clock_trimtaip; +#endif + +#ifdef CLOCK_TRIMTSIP +extern clockformat_t clock_trimtsip; +#endif + +#ifdef CLOCK_RCC8000 +extern clockformat_t clock_rcc8000; +#endif + +#ifdef CLOCK_HOPF6021 +extern clockformat_t clock_hopf6021; +#endif + +#ifdef CLOCK_COMPUTIME +extern clockformat_t clock_computime; +#endif + +#ifdef CLOCK_WHARTON_400A +extern clockformat_t clock_wharton_400a; +#endif + +#ifdef CLOCK_VARITEXT +extern clockformat_t clock_varitext; +#endif + +/* + * format definitions + */ +clockformat_t *clockformats[] = +{ +#ifdef CLOCK_MEINBERG + &clock_meinberg[0], + &clock_meinberg[1], + &clock_meinberg[2], +#endif +#ifdef CLOCK_DCF7000 + &clock_dcf7000, +#endif +#ifdef CLOCK_SCHMID + &clock_schmid, +#endif +#ifdef CLOCK_RAWDCF + &clock_rawdcf, +#endif +#ifdef CLOCK_TRIMTAIP + &clock_trimtaip, +#endif +#ifdef CLOCK_TRIMTSIP + &clock_trimtsip, +#endif +#ifdef CLOCK_RCC8000 + &clock_rcc8000, +#endif +#ifdef CLOCK_HOPF6021 + &clock_hopf6021, +#endif +#ifdef CLOCK_COMPUTIME + &clock_computime, +#endif +#ifdef CLOCK_WHARTON_400A + &clock_wharton_400a, +#endif +#ifdef CLOCK_VARITEXT + &clock_varitext, +#endif + 0}; + +unsigned short nformats = sizeof(clockformats) / sizeof(clockformats[0]) - 1; + +#else /* not (REFCLOCK && CLOCK_PARSE) */ +int parse_conf_bs; +#endif /* not (REFCLOCK && CLOCK_PARSE) */ + +/* + * History: + * + * parse_conf.c,v + * Revision 4.4 1999/02/28 15:27:25 kardel + * wharton clock integration + * + * Revision 4.3 1998/08/16 18:52:15 kardel + * (clockformats): Trimble TSIP driver now also + * available for kernel operation + * + * Revision 4.2 1998/06/12 09:13:48 kardel + * conditional compile macros fixed + * + * Revision 4.1 1998/05/24 09:40:49 kardel + * adjustments of log messages + * + * + * from V3 3.24 log info deleted 1998/04/11 kardel + */ diff --git a/contrib/ntp/libparse/parsesolaris.c b/contrib/ntp/libparse/parsesolaris.c new file mode 100644 index 000000000000..e0e7c23bd382 --- /dev/null +++ b/contrib/ntp/libparse/parsesolaris.c @@ -0,0 +1,1173 @@ +/* + * /src/NTP/ntp-4/libparse/parsesolaris.c,v 4.6 1998/11/15 21:56:08 kardel RELEASE_19990228_A + * + * parsesolaris.c,v 4.6 1998/11/15 21:56:08 kardel RELEASE_19990228_A + * + * STREAMS module for reference clocks + * + * Copyright (C) 1993-1998 by Frank Kardel + * derived work from parsestreams.c ((c) 1991-1993, Frank Kardel) and + * dcf77sync.c((c) Frank Kardel) + * Friedrich-Alexander Universität Erlangen-Nürnberg, Germany + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#define _KERNEL /* it is a _KERNEL module */ + +#ifndef lint +static char rcsid[] = "parsesolaris.c,v 4.6 1998/11/15 21:56:08 kardel RELEASE_19990228_A"; +#endif + +#include <sys/types.h> +#include <sys/conf.h> +#include <sys/errno.h> +#include <sys/time.h> +#include <sys/termios.h> +#include <sys/stream.h> +#include <sys/strtty.h> +#include <sys/stropts.h> +#include <sys/modctl.h> +#include <sys/ddi.h> +#include <sys/sunddi.h> +#ifdef __GNUC__ /* makes it compile on Solaris 2.6 - acc doesn't like it -- GREAT! */ +#include <stdarg.h> +#endif + +#include "ntp_fp.h" +#include "parse.h" +#include <sys/parsestreams.h> + +/*--------------- loadable driver section -----------------------------*/ + +static struct streamtab parseinfo; + +static struct fmodsw fmod_templ = +{ + "parse", /* module name */ + &parseinfo, /* module information */ + D_NEW|D_MP|D_MTQPAIR, /* exclusive for q pair */ + /* lock ptr */ +}; + +extern struct mod_ops mod_strmodops; + +static struct modlstrmod modlstrmod = +{ + &mod_strmodops, /* a STREAMS module */ + "PARSE - NTP reference", /* name this baby - keep room for revision number */ + &fmod_templ +}; + +static struct modlinkage modlinkage = +{ + MODREV_1, + { + &modlstrmod, + NULL + } +}; + +/* + * module management routines + */ +/*ARGSUSED*/ +int +_init( + void + ) +{ + static char revision[] = "4.6"; + char *s, *S; + char *t; + +#ifndef lint + t = rcsid; +#endif + + /* + * copy RCS revision into Drv_name + * + * are we forcing RCS here to do things it was not built for ? + */ + s = revision; + if (*s == '$') + { + /* + * skip "$Revision: " + * if present. - not necessary on a -kv co (cvs export) + */ + while (*s && (*s != ' ')) + { + s++; + } + if (*s == ' ') s++; + } + + t = modlstrmod.strmod_linkinfo; + while (*t && (*t != ' ')) + { + t++; + } + if (*t == ' ') t++; + + S = s; + while (*S && (((*S >= '0') && (*S <= '9')) || (*S == '.'))) + { + S++; + } + + if (*s && *t && (S > s)) + { + if (strlen(t) >= (S - s)) + { + (void) strncpy(t, s, (unsigned)(S - s)); + } + } + return (mod_install(&modlinkage)); +} + +/*ARGSUSED*/ +int +_info( + struct modinfo *modinfop + ) +{ + return (mod_info(&modlinkage, modinfop)); +} + +/*ARGSUSED*/ +int +_fini( + void + ) +{ + if (mod_remove(&modlinkage) != DDI_SUCCESS) + { + return EBUSY; + } + else + return DDI_SUCCESS; +} + +/*--------------- stream module definition ----------------------------*/ + +static int parseopen P((queue_t *, dev_t *, int, int, cred_t *)); +static int parseclose P((queue_t *, int)); +static int parsewput P((queue_t *, mblk_t *)); +static int parserput P((queue_t *, mblk_t *)); +static int parsersvc P((queue_t *)); + +static struct module_info driverinfo = +{ + 0, /* module ID number */ + fmod_templ.f_name, /* module name - why repeated here ? compat ?*/ + 0, /* minimum accepted packet size */ + INFPSZ, /* maximum accepted packet size */ + 1, /* high water mark - flow control */ + 0 /* low water mark - flow control */ +}; + +static struct qinit rinit = /* read queue definition */ +{ + parserput, /* put procedure */ + parsersvc, /* service procedure */ + parseopen, /* open procedure */ + parseclose, /* close procedure */ + NULL, /* admin procedure - NOT USED FOR NOW */ + &driverinfo, /* information structure */ + NULL /* statistics */ +}; + +static struct qinit winit = /* write queue definition */ +{ + parsewput, /* put procedure */ + NULL, /* service procedure */ + NULL, /* open procedure */ + NULL, /* close procedure */ + NULL, /* admin procedure - NOT USED FOR NOW */ + &driverinfo, /* information structure */ + NULL /* statistics */ +}; + +static struct streamtab parseinfo = /* stream info element for parse driver */ +{ + &rinit, /* read queue */ + &winit, /* write queue */ + NULL, /* read mux */ + NULL /* write mux */ +}; + +/*--------------- driver data structures ----------------------------*/ + +/* + * we usually have an inverted signal - but you + * can change this to suit your needs + */ +int cd_invert = 1; /* invert status of CD line - PPS support via CD input */ + +#ifdef PARSEDEBUG +int parsedebug = ~0; +#else +int parsedebug = 0; +#endif + +/*--------------- module implementation -----------------------------*/ + +#define TIMEVAL_USADD(_X_, _US_) do {\ + (_X_)->tv_usec += (_US_);\ + if ((_X_)->tv_usec >= 1000000)\ + {\ + (_X_)->tv_sec++;\ + (_X_)->tv_usec -= 1000000;\ + }\ + } while (0) + +static int init_linemon P((queue_t *)); +static void close_linemon P((queue_t *, queue_t *)); + +#define M_PARSE 0x0001 +#define M_NOPARSE 0x0002 + +void +ntp_memset( + char *a, + int x, + int c + ) +{ + while (c-- > 0) + *a++ = x; +} + +static void +pprintf( + int lev, + const char *form, + ... + ) +{ + va_list ap; + + va_start(ap, form); + + if (lev & parsedebug) + vcmn_err(CE_CONT, (char *)form, ap); + + va_end(ap); +} + +static int +setup_stream( + queue_t *q, + int mode + ) +{ + register mblk_t *mp; + + pprintf(DD_OPEN,"parse: SETUP_STREAM - setting up stream for q=%x\n", q); + + mp = allocb(sizeof(struct stroptions), BPRI_MED); + if (mp) + { + struct stroptions *str = (struct stroptions *)mp->b_wptr; + + str->so_flags = SO_READOPT|SO_HIWAT|SO_LOWAT|SO_ISNTTY; + str->so_readopt = (mode == M_PARSE) ? RMSGD : RNORM; + str->so_hiwat = (mode == M_PARSE) ? sizeof(parsetime_t) : 256; + str->so_lowat = 0; + mp->b_datap->db_type = M_SETOPTS; + mp->b_wptr += sizeof(struct stroptions); + if (!q) + panic("NULL q - strange"); + putnext(q, mp); + return putctl1(WR(q)->q_next, M_CTL, (mode == M_PARSE) ? MC_SERVICEIMM : + MC_SERVICEDEF); + } + else + { + pprintf(DD_OPEN, "parse: setup_stream - FAILED - no MEMORY for allocb\n"); + return 0; + } +} + +/*ARGSUSED*/ +static int +parseopen( + queue_t *q, + dev_t *dev, + int flag, + int sflag, + cred_t *credp + ) +{ + register parsestream_t *parse; + static int notice = 0; + + pprintf(DD_OPEN, "parse: OPEN - q=%x\n", q); + + if (sflag != MODOPEN) + { /* open only for modules */ + pprintf(DD_OPEN, "parse: OPEN - FAILED - not MODOPEN\n"); + return EIO; + } + + if (q->q_ptr != (caddr_t)NULL) + { + pprintf(DD_OPEN, "parse: OPEN - FAILED - EXCLUSIVE ONLY\n"); + return EBUSY; + } + + q->q_ptr = (caddr_t)kmem_alloc(sizeof(parsestream_t), KM_SLEEP); + if (q->q_ptr == (caddr_t)0) + { + return ENOMEM; + } + + pprintf(DD_OPEN, "parse: OPEN - parse area q=%x, q->q_ptr=%x\n", q, q->q_ptr); + WR(q)->q_ptr = q->q_ptr; + pprintf(DD_OPEN, "parse: OPEN - WQ parse area q=%x, q->q_ptr=%x\n", WR(q), WR(q)->q_ptr); + + parse = (parsestream_t *) q->q_ptr; + bzero((caddr_t)parse, sizeof(*parse)); + parse->parse_queue = q; + parse->parse_status = PARSE_ENABLE; + parse->parse_ppsclockev.tv.tv_sec = 0; + parse->parse_ppsclockev.tv.tv_usec = 0; + parse->parse_ppsclockev.serial = 0; + + qprocson(q); + + pprintf(DD_OPEN, "parse: OPEN - initializing io subsystem q=%x\n", q); + + if (!parse_ioinit(&parse->parse_io)) + { + /* + * ok guys - beat it + */ + qprocsoff(q); + + kmem_free((caddr_t)parse, sizeof(parsestream_t)); + + return EIO; + } + + pprintf(DD_OPEN, "parse: OPEN - initializing stream q=%x\n", q); + + if (setup_stream(q, M_PARSE)) + { + (void) init_linemon(q); /* hook up PPS ISR routines if possible */ + pprintf(DD_OPEN, "parse: OPEN - SUCCEEDED\n"); + + /* + * I know that you know the delete key, but you didn't write this + * code, did you ? - So, keep the message in here. + */ + if (!notice) + { + cmn_err(CE_CONT, "?%s: Copyright (c) 1993-1998, Frank Kardel\n", modlstrmod.strmod_linkinfo); + notice = 1; + } + + return 0; + } + else + { + qprocsoff(q); + + kmem_free((caddr_t)parse, sizeof(parsestream_t)); + + return EIO; + } +} + +/*ARGSUSED*/ +static int +parseclose( + queue_t *q, + int flags + ) +{ + register parsestream_t *parse = (parsestream_t *)q->q_ptr; + register unsigned long s; + + pprintf(DD_CLOSE, "parse: CLOSE\n"); + + qprocsoff(q); + + s = splhigh(); + + if (parse->parse_dqueue) + close_linemon(parse->parse_dqueue, q); + parse->parse_dqueue = (queue_t *)0; + + (void) splx(s); + + parse_ioend(&parse->parse_io); + + kmem_free((caddr_t)parse, sizeof(parsestream_t)); + + q->q_ptr = (caddr_t)NULL; + WR(q)->q_ptr = (caddr_t)NULL; + + return 0; +} + +/* + * move unrecognized stuff upward + */ +static int +parsersvc( + queue_t *q + ) +{ + mblk_t *mp; + + while ((mp = getq(q))) + { + if (canputnext(q) || (mp->b_datap->db_type > QPCTL)) + { + putnext(q, mp); + pprintf(DD_RSVC, "parse: RSVC - putnext\n"); + } + else + { + putbq(q, mp); + pprintf(DD_RSVC, "parse: RSVC - flow control wait\n"); + break; + } + } + return 0; +} + +/* + * do ioctls and + * send stuff down - dont care about + * flow control + */ +static int +parsewput( + queue_t *q, + mblk_t *mp + ) +{ + register int ok = 1; + register mblk_t *datap; + register struct iocblk *iocp; + parsestream_t *parse = (parsestream_t *)q->q_ptr; + + pprintf(DD_WPUT, "parse: parsewput\n"); + + switch (mp->b_datap->db_type) + { + default: + putnext(q, mp); + break; + + case M_IOCTL: + iocp = (struct iocblk *)mp->b_rptr; + switch (iocp->ioc_cmd) + { + default: + pprintf(DD_WPUT, "parse: parsewput - forward M_IOCTL\n"); + putnext(q, mp); + break; + + case CIOGETEV: + /* + * taken from Craig Leres ppsclock module (and modified) + */ + datap = allocb(sizeof(struct ppsclockev), BPRI_MED); + if (datap == NULL || mp->b_cont) + { + mp->b_datap->db_type = M_IOCNAK; + iocp->ioc_error = (datap == NULL) ? ENOMEM : EINVAL; + if (datap != NULL) + freeb(datap); + qreply(q, mp); + break; + } + + mp->b_cont = datap; + *(struct ppsclockev *)datap->b_wptr = parse->parse_ppsclockev; + datap->b_wptr += + sizeof(struct ppsclockev) / sizeof(*datap->b_wptr); + mp->b_datap->db_type = M_IOCACK; + iocp->ioc_count = sizeof(struct ppsclockev); + qreply(q, mp); + break; + + case PARSEIOC_ENABLE: + case PARSEIOC_DISABLE: + { + parse->parse_status = (parse->parse_status & (unsigned)~PARSE_ENABLE) | + (iocp->ioc_cmd == PARSEIOC_ENABLE) ? + PARSE_ENABLE : 0; + if (!setup_stream(RD(q), (parse->parse_status & PARSE_ENABLE) ? + M_PARSE : M_NOPARSE)) + { + mp->b_datap->db_type = M_IOCNAK; + } + else + { + mp->b_datap->db_type = M_IOCACK; + } + qreply(q, mp); + break; + } + + case PARSEIOC_TIMECODE: + case PARSEIOC_SETFMT: + case PARSEIOC_GETFMT: + case PARSEIOC_SETCS: + if (iocp->ioc_count == sizeof(parsectl_t)) + { + parsectl_t *dct = (parsectl_t *)mp->b_cont->b_rptr; + + switch (iocp->ioc_cmd) + { + case PARSEIOC_TIMECODE: + pprintf(DD_WPUT, "parse: parsewput - PARSEIOC_TIMECODE\n"); + ok = parse_timecode(dct, &parse->parse_io); + break; + + case PARSEIOC_SETFMT: + pprintf(DD_WPUT, "parse: parsewput - PARSEIOC_SETFMT\n"); + ok = parse_setfmt(dct, &parse->parse_io); + break; + + case PARSEIOC_GETFMT: + pprintf(DD_WPUT, "parse: parsewput - PARSEIOC_GETFMT\n"); + ok = parse_getfmt(dct, &parse->parse_io); + break; + + case PARSEIOC_SETCS: + pprintf(DD_WPUT, "parse: parsewput - PARSEIOC_SETCS\n"); + ok = parse_setcs(dct, &parse->parse_io); + break; + } + mp->b_datap->db_type = ok ? M_IOCACK : M_IOCNAK; + } + else + { + mp->b_datap->db_type = M_IOCNAK; + } + pprintf(DD_WPUT, "parse: parsewput qreply - %s\n", (mp->b_datap->db_type == M_IOCNAK) ? "M_IOCNAK" : "M_IOCACK"); + qreply(q, mp); + break; + } + } + return 0; +} + +/* + * read characters from streams buffers + */ +static unsigned long +rdchar( + mblk_t **mp + ) +{ + while (*mp != (mblk_t *)NULL) + { + if ((*mp)->b_wptr - (*mp)->b_rptr) + { + return (unsigned long)(*(unsigned char *)((*mp)->b_rptr++)); + } + else + { + register mblk_t *mmp = *mp; + + *mp = (*mp)->b_cont; + freeb(mmp); + } + } + return (unsigned)~0; +} + +/* + * convert incoming data + */ +static int +parserput( + queue_t *q, + mblk_t *imp + ) +{ + register unsigned char type; + mblk_t *mp = imp; + + switch (type = mp->b_datap->db_type) + { + default: + /* + * anything we don't know will be put on queue + * the service routine will move it to the next one + */ + pprintf(DD_RPUT, "parse: parserput - forward type 0x%x\n", type); + + if (canputnext(q) || (mp->b_datap->db_type > QPCTL)) + { + putnext(q, mp); + } + else + putq(q, mp); + break; + + case M_BREAK: + case M_DATA: + { + register parsestream_t * parse = (parsestream_t *)q->q_ptr; + register mblk_t *nmp; + register unsigned long ch; + timestamp_t ctime; + timespec_t hres_time; + + /* + * get time on packet delivery + */ + gethrestime(&hres_time); + ctime.tv.tv_sec = hres_time.tv_sec; + ctime.tv.tv_usec = hres_time.tv_nsec / 1000; + + if (!(parse->parse_status & PARSE_ENABLE)) + { + pprintf(DD_RPUT, "parse: parserput - parser disabled - forward type 0x%x\n", type); + if (canputnext(q) || (mp->b_datap->db_type > QPCTL)) + { + putnext(q, mp); + } + else + putq(q, mp); + } + else + { + pprintf(DD_RPUT, "parse: parserput - M_%s\n", (type == M_DATA) ? "DATA" : "BREAK"); + if (type == M_DATA) + { + /* + * parse packet looking for start an end characters + */ + while (mp != (mblk_t *)NULL) + { + ch = rdchar(&mp); + if (ch != ~0 && parse_ioread(&parse->parse_io, (unsigned int)ch, &ctime)) + { + /* + * up up and away (hopefully ...) + * don't press it if resources are tight or nobody wants it + */ + nmp = (mblk_t *)NULL; + if (canputnext(parse->parse_queue) && (nmp = allocb(sizeof(parsetime_t), BPRI_MED))) + { + bcopy((caddr_t)&parse->parse_io.parse_dtime, (caddr_t)nmp->b_rptr, sizeof(parsetime_t)); + nmp->b_wptr += sizeof(parsetime_t); + putnext(parse->parse_queue, nmp); + } + else + if (nmp) freemsg(nmp); + parse_iodone(&parse->parse_io); + } + } + } + else + { + if (parse_ioread(&parse->parse_io, (unsigned int)0, &ctime)) + { + /* + * up up and away (hopefully ...) + * don't press it if resources are tight or nobody wants it + */ + nmp = (mblk_t *)NULL; + if (canputnext(parse->parse_queue) && (nmp = allocb(sizeof(parsetime_t), BPRI_MED))) + { + bcopy((caddr_t)&parse->parse_io.parse_dtime, (caddr_t)nmp->b_rptr, sizeof(parsetime_t)); + nmp->b_wptr += sizeof(parsetime_t); + putnext(parse->parse_queue, nmp); + } + else + if (nmp) freemsg(nmp); + parse_iodone(&parse->parse_io); + } + freemsg(mp); + } + break; + } + } + + /* + * CD PPS support for non direct ISR hack + */ + case M_HANGUP: + case M_UNHANGUP: + { + register parsestream_t * parse = (parsestream_t *)q->q_ptr; + timestamp_t ctime; + timespec_t hres_time; + register mblk_t *nmp; + register int status = cd_invert ^ (type == M_UNHANGUP); + + gethrestime(&hres_time); + ctime.tv.tv_sec = hres_time.tv_sec; + ctime.tv.tv_usec = hres_time.tv_nsec / 1000; + + pprintf(DD_RPUT, "parse: parserput - M_%sHANGUP\n", (type == M_HANGUP) ? "" : "UN"); + + if ((parse->parse_status & PARSE_ENABLE) && + parse_iopps(&parse->parse_io, status ? SYNC_ONE : SYNC_ZERO, &ctime)) + { + nmp = (mblk_t *)NULL; + if (canputnext(parse->parse_queue) && (nmp = allocb(sizeof(parsetime_t), BPRI_MED))) + { + bcopy((caddr_t)&parse->parse_io.parse_dtime, (caddr_t)nmp->b_rptr, sizeof(parsetime_t)); + nmp->b_wptr += sizeof(parsetime_t); + putnext(parse->parse_queue, nmp); + } + else + if (nmp) freemsg(nmp); + parse_iodone(&parse->parse_io); + freemsg(mp); + } + else + if (canputnext(q) || (mp->b_datap->db_type > QPCTL)) + { + putnext(q, mp); + } + else + putq(q, mp); + + if (status) + { + parse->parse_ppsclockev.tv = ctime.tv; + ++(parse->parse_ppsclockev.serial); + } + } + } + return 0; +} + +static int init_zs_linemon P((queue_t *, queue_t *)); /* handle line monitor for "zs" driver */ +static void close_zs_linemon P((queue_t *, queue_t *)); + +/*-------------------- CD isr status monitor ---------------*/ + +static int +init_linemon( + queue_t *q + ) +{ + register queue_t *dq; + + dq = WR(q); + /* + * we ARE doing very bad things down here (basically stealing ISR + * hooks) + * + * so we chase down the STREAMS stack searching for the driver + * and if this is a known driver we insert our ISR routine for + * status changes in to the ExternalStatus handling hook + */ + while (dq->q_next) + { + dq = dq->q_next; /* skip down to driver */ + } + + /* + * find appropriate driver dependent routine + */ + if (dq->q_qinfo && dq->q_qinfo->qi_minfo) + { + register char *dname = dq->q_qinfo->qi_minfo->mi_idname; + + pprintf(DD_INSTALL, "init_linemon: driver is \"%s\"\n", dname); + +#ifdef sun + if (dname && !strcmp(dname, "zs")) + { + return init_zs_linemon(dq, q); + } + else +#endif + { + pprintf(DD_INSTALL, "init_linemon: driver \"%s\" not suitable for CD monitoring\n", dname); + return 0; + } + } + pprintf(DD_INSTALL, "init_linemon: cannot find driver\n"); + return 0; +} + +static void +close_linemon( + queue_t *q, + queue_t *my_q + ) +{ + /* + * find appropriate driver dependent routine + */ + if (q->q_qinfo && q->q_qinfo->qi_minfo) + { + register char *dname = q->q_qinfo->qi_minfo->mi_idname; + +#ifdef sun + if (dname && !strcmp(dname, "zs")) + { + close_zs_linemon(q, my_q); + return; + } + pprintf(DD_INSTALL, "close_linemon: cannot find driver close routine for \"%s\"\n", dname); +#endif + } + pprintf(DD_INSTALL, "close_linemon: cannot find driver name\n"); +} + +#ifdef sun +#include <sys/tty.h> +#include <sys/zsdev.h> +#include <sys/ser_async.h> +#include <sys/ser_zscc.h> + +static void zs_xsisr P((struct zscom *)); /* zs external status interupt handler */ + +/* + * there should be some docs telling how to get to + * sz:zs_usec_delay and zs:initzsops() + */ +#define zs_usec_delay 5 + +struct savedzsops +{ + struct zsops zsops; + struct zsops *oldzsops; +}; + +static struct zsops *emergencyzs; + +static int +init_zs_linemon( + queue_t *q, + queue_t *my_q + ) +{ + register struct zscom *zs; + register struct savedzsops *szs; + register parsestream_t *parsestream = (parsestream_t *)my_q->q_ptr; + /* + * we expect the zsaline pointer in the q_data pointer + * from there on we insert our on EXTERNAL/STATUS ISR routine + * into the interrupt path, before the standard handler + */ + zs = ((struct asyncline *)q->q_ptr)->za_common; + if (!zs) + { + /* + * well - not found on startup - just say no (shouldn't happen though) + */ + return 0; + } + else + { + /* + * we do a direct replacement, in case others fiddle also + * if somebody else grabs our hook and we disconnect + * we are in DEEP trouble - panic is likely to be next, sorry + */ + szs = (struct savedzsops *) kmem_alloc(sizeof(struct savedzsops), KM_SLEEP); + + if (szs == (struct savedzsops *)0) + { + pprintf(DD_INSTALL, "init_zs_linemon: CD monitor NOT installed - no memory\n"); + + return 0; + } + else + { + parsestream->parse_data = (void *)szs; + + mutex_enter(zs->zs_excl); + + parsestream->parse_dqueue = q; /* remember driver */ + + szs->zsops = *zs->zs_ops; + szs->zsops.zsop_xsint = (void (*) P((struct zscom *)))zs_xsisr; /* place our bastard */ + szs->oldzsops = zs->zs_ops; + emergencyzs = zs->zs_ops; + + zs->zs_ops = &szs->zsops; /* hook it up */ + /* + * XXX: this is usually done via zsopinit() + * - have yet to find a way to call that routine + */ + zs->zs_xsint = (void (*) P((struct zscom *)))zs_xsisr; + + mutex_exit(zs->zs_excl); + + pprintf(DD_INSTALL, "init_zs_linemon: CD monitor installed\n"); + + return 1; + } + } +} + +/* + * unregister our ISR routine - must call under splhigh() (or + * whatever block ZS status interrupts) + */ +static void +close_zs_linemon( + queue_t *q, + queue_t *my_q + ) +{ + register struct zscom *zs; + register parsestream_t *parsestream = (parsestream_t *)my_q->q_ptr; + + zs = ((struct asyncline *)q->q_ptr)->za_common; + if (!zs) + { + /* + * well - not found on startup - just say no (shouldn't happen though) + */ + return; + } + else + { + register struct savedzsops *szs = (struct savedzsops *)parsestream->parse_data; + + mutex_enter(zs->zs_excl); + + zs->zs_ops = szs->oldzsops; /* reset to previous handler functions */ + /* + * XXX: revert xsint (usually done via zsopinit() - have still to find + * a way to call that bugger + */ + zs->zs_xsint = zs->zs_ops->zsop_xsint; + + mutex_exit(zs->zs_excl); + + kmem_free((caddr_t)szs, sizeof (struct savedzsops)); + + pprintf(DD_INSTALL, "close_zs_linemon: CD monitor deleted\n"); + return; + } +} + +#define ZSRR0_IGNORE (ZSRR0_CD|ZSRR0_SYNC|ZSRR0_CTS) + +#define MAXDEPTH 50 /* maximum allowed stream crawl */ + +/* + * take external status interrupt (only CD interests us) + */ +static void +zs_xsisr( + struct zscom *zs + ) +{ + register struct asyncline *za = (struct asyncline *)zs->zs_priv; + register queue_t *q; + register unsigned char zsstatus; + register int loopcheck; + register unsigned char cdstate; + register const char *dname = "-UNKNOWN-"; + timespec_t hres_time; + + /* + * pick up current state + */ + zsstatus = SCC_READ0(); + + if (za->za_rr0 ^ (cdstate = zsstatus & ZSRR0_CD)) + { + timestamp_t cdevent; + register int status; + + /* + * time stamp + */ + gethrestime(&hres_time); + cdevent.tv.tv_sec = hres_time.tv_sec; + cdevent.tv.tv_usec = hres_time.tv_nsec / 1000; + + q = za->za_ttycommon.t_readq; + + /* + * logical state + */ + status = cd_invert ? cdstate == 0 : cdstate != 0; + + /* + * ok - now the hard part - find ourself + */ + loopcheck = MAXDEPTH; + + while (q) + { + if (q->q_qinfo && q->q_qinfo->qi_minfo) + { + dname = q->q_qinfo->qi_minfo->mi_idname; + + if (!strcmp(dname, parseinfo.st_rdinit->qi_minfo->mi_idname)) + { + /* + * back home - phew (hopping along stream queues might + * prove dangerous to your health) + */ + + if ((((parsestream_t *)q->q_ptr)->parse_status & PARSE_ENABLE) && + parse_iopps(&((parsestream_t *)q->q_ptr)->parse_io, status ? SYNC_ONE : SYNC_ZERO, &cdevent)) + { + /* + * XXX - currently we do not pass up the message, as + * we should. + * for a correct behaviour wee need to block out + * processing until parse_iodone has been posted via + * a softcall-ed routine which does the message pass-up + * right now PPS information relies on input being + * received + */ + parse_iodone(&((parsestream_t *)q->q_ptr)->parse_io); + } + + if (status) + { + ((parsestream_t *)q->q_ptr)->parse_ppsclockev.tv = cdevent.tv; + ++(((parsestream_t *)q->q_ptr)->parse_ppsclockev.serial); + } + + pprintf(DD_ISR, "zs_xsisr: CD event %s has been posted for \"%s\"\n", status ? "ONE" : "ZERO", dname); + break; + } + } + + q = q->q_next; + + if (!loopcheck--) + { + panic("zs_xsisr: STREAMS Queue corrupted - CD event"); + } + } + + if (cdstate) /* fake CARRIER status - XXX currently not coordinated */ + za->za_flags |= ZAS_CARR_ON; + else + za->za_flags &= ~ZAS_CARR_ON; + + /* + * only pretend that CD and ignored transistion (SYNC,CTS) + * have been handled + */ + za->za_rr0 = (za->za_rr0 & ~ZSRR0_IGNORE) | (zsstatus & ZSRR0_IGNORE); + + if (((za->za_rr0 ^ zsstatus) & ~ZSRR0_IGNORE) == 0) + { + /* + * all done - kill status indication and return + */ + SCC_WRITE0(ZSWR0_RESET_STATUS); /* might kill other conditions here */ + return; + } + } + + pprintf(DD_ISR, "zs_xsisr: non CD event 0x%x for \"%s\"\n", + (za->za_rr0 ^ zsstatus) & ~ZSRR0_CD,dname); + /* + * we are now gathered here to process some unusual external status + * interrupts. + * any CD events have also been handled and shouldn't be processed + * by the original routine (unless we have a VERY busy port pin) + * some initializations are done here, which could have been done before for + * both code paths but have been avioded for minimum path length to + * the uniq_time routine + */ + dname = (char *) 0; + q = za->za_ttycommon.t_readq; + + loopcheck = MAXDEPTH; + + /* + * the real thing for everything else ... + */ + while (q) + { + if (q->q_qinfo && q->q_qinfo->qi_minfo) + { + dname = q->q_qinfo->qi_minfo->mi_idname; + if (!strcmp(dname, parseinfo.st_rdinit->qi_minfo->mi_idname)) + { + register void (*zsisr) P((struct zscom *)); + + /* + * back home - phew (hopping along stream queues might + * prove dangerous to your health) + */ + if ((zsisr = ((struct savedzsops *)((parsestream_t *)q->q_ptr)->parse_data)->oldzsops->zsop_xsint)) + zsisr(zs); + else + panic("zs_xsisr: unable to locate original ISR"); + + pprintf(DD_ISR, "zs_xsisr: non CD event was processed for \"%s\"\n", dname); + /* + * now back to our program ... + */ + return; + } + } + + q = q->q_next; + + if (!loopcheck--) + { + panic("zs_xsisr: STREAMS Queue corrupted - non CD event"); + } + } + + /* + * last resort - shouldn't even come here as it indicates + * corrupted TTY structures + */ + printf("zs_zsisr: looking for \"%s\" - found \"%s\" - taking EMERGENCY path\n", parseinfo.st_rdinit->qi_minfo->mi_idname, dname ? dname : "-NIL-"); + + if (emergencyzs && emergencyzs->zsop_xsint) + emergencyzs->zsop_xsint(zs); + else + panic("zs_xsisr: no emergency ISR handler"); +} +#endif /* sun */ + +/* + * History: + * + * parsesolaris.c,v + * Revision 4.6 1998/11/15 21:56:08 kardel + * ntp_memset not necessary + * + * Revision 4.5 1998/11/15 21:23:37 kardel + * ntp_memset() replicated in Sun kernel files + * + * Revision 4.4 1998/06/14 21:09:40 kardel + * Sun acc cleanup + * + * Revision 4.3 1998/06/13 12:14:59 kardel + * more prototypes + * fix name clashes + * allow for ansi2knr + * + * Revision 4.2 1998/06/12 15:23:08 kardel + * fix prototypes + * adjust for ansi2knr + * + * Revision 4.1 1998/05/24 09:38:46 kardel + * streams initiated iopps calls (M_xHANGUP) are now consistent with the + * respective calls from zs_xsisr() + * simulation of CARRIER status to avoid unecessary M_xHANGUP messages + * + * Revision 4.0 1998/04/10 19:45:38 kardel + * Start 4.0 release version numbering + * + * from V3 3.28 log info deleted 1998/04/11 kardel + */ diff --git a/contrib/ntp/libparse/parsestreams.c b/contrib/ntp/libparse/parsestreams.c new file mode 100644 index 000000000000..1578229e19a8 --- /dev/null +++ b/contrib/ntp/libparse/parsestreams.c @@ -0,0 +1,1335 @@ +/* + * /src/NTP/ntp-4/libparse/parsestreams.c,v 4.6 1998/12/20 23:45:31 kardel RELEASE_19990228_A + * + * parsestreams.c,v 4.6 1998/12/20 23:45:31 kardel RELEASE_19990228_A + * + * STREAMS module for reference clocks + * (SunOS4.x) + * + * Copyright (c) 1989-1998 by Frank Kardel + * Friedrich-Alexander Universität Erlangen-Nürnberg, Germany + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + */ + +#define KERNEL /* MUST */ +#define VDDRV /* SHOULD */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifndef lint +static char rcsid[] = "parsestreams.c,v 4.6 1998/12/20 23:45:31 kardel RELEASE_19990228_A"; +#endif + +#ifndef KERNEL +#include "Bletch: MUST COMPILE WITH KERNEL DEFINE" +#endif + +#include <sys/types.h> +#include <sys/conf.h> +#include <sys/buf.h> +#include <sys/param.h> +#include <sys/sysmacros.h> +#include <sys/time.h> +#include <sundev/mbvar.h> +#include <sun/autoconf.h> +#include <sys/stream.h> +#include <sys/stropts.h> +#include <sys/dir.h> +#include <sys/signal.h> +#include <sys/termios.h> +#include <sys/termio.h> +#include <sys/ttold.h> +#include <sys/user.h> +#include <sys/tty.h> + +#ifdef VDDRV +#include <sun/vddrv.h> +#endif + +#include "ntp_stdlib.h" +#include "ntp_fp.h" +/* + * just make checking compilers more silent + */ +extern int printf P((const char *, ...)); +extern int putctl1 P((queue_t *, int, int)); +extern int canput P((queue_t *)); +extern void putbq P((queue_t *, mblk_t *)); +extern void freeb P((mblk_t *)); +extern void qreply P((queue_t *, mblk_t *)); +extern void freemsg P((mblk_t *)); +extern void panic P((const char *, ...)); +extern void usec_delay P((int)); + +#include "parse.h" +#include "sys/parsestreams.h" + +/* + * use microtime instead of uniqtime if advised to + */ +#ifdef MICROTIME +#define uniqtime microtime +#endif + +#ifdef VDDRV +static unsigned int parsebusy = 0; + +/*--------------- loadable driver section -----------------------------*/ + +extern struct streamtab parseinfo; + + +#ifdef PPS_SYNC +static char mnam[] = "PARSEPPS "; /* name this baby - keep room for revision number */ +#else +static char mnam[] = "PARSE "; /* name this baby - keep room for revision number */ +#endif +struct vdldrv parsesync_vd = +{ + VDMAGIC_PSEUDO, /* nothing like a real driver - a STREAMS module */ + mnam, +}; + +/* + * strings support usually not in kernel + */ +static int +Strlen( + register const char *s + ) +{ + register int c; + + c = 0; + if (s) + { + while (*s++) + { + c++; + } + } + return c; +} + +static void +Strncpy( + register char *t, + register char *s, + register int c + ) +{ + if (s && t) + { + while ((c-- > 0) && (*t++ = *s++)) + ; + } +} + +static int +Strcmp( + register const char *s, + register const char *t + ) +{ + register int c = 0; + + if (!s || !t || (s == t)) + { + return 0; + } + + while (!(c = *s++ - *t++) && *s && *t) + /* empty loop */; + + return c; +} + +static int +Strncmp( + register char *s, + register char *t, + register int n + ) +{ + register int c = 0; + + if (!s || !t || (s == t)) + { + return 0; + } + + while (n-- && !(c = *s++ - *t++) && *s && *t) + /* empty loop */; + + return c; +} + +void +ntp_memset( + char *a, + int x, + int c + ) +{ + while (c-- > 0) + *a++ = x; +} + +/* + * driver init routine + * since no mechanism gets us into and out of the fmodsw, we have to + * do it ourselves + */ +/*ARGSUSED*/ +int +xxxinit( + unsigned int fc, + struct vddrv *vdp, + addr_t vdin, + struct vdstat *vds + ) +{ + extern struct fmodsw fmodsw[]; + extern int fmodcnt; + + struct fmodsw *fm = fmodsw; + struct fmodsw *fmend = &fmodsw[fmodcnt]; + struct fmodsw *ifm = (struct fmodsw *)0; + char *mname = parseinfo.st_rdinit->qi_minfo->mi_idname; + + switch (fc) + { + case VDLOAD: + vdp->vdd_vdtab = (struct vdlinkage *)&parsesync_vd; + /* + * now, jog along fmodsw scanning for an empty slot + * and deposit our name there + */ + while (fm <= fmend) + { + if (!Strncmp(fm->f_name, mname, FMNAMESZ)) + { + printf("vddrinit[%s]: STREAMS module already loaded.\n", mname); + return(EBUSY); + } + else + if ((ifm == (struct fmodsw *)0) && + (fm->f_name[0] == '\0') && + (fm->f_str == (struct streamtab *)0)) + { + /* + * got one - so move in + */ + ifm = fm; + break; + } + fm++; + } + + if (ifm == (struct fmodsw *)0) + { + printf("vddrinit[%s]: no slot free for STREAMS module\n", mname); + return (ENOSPC); + } + else + { + static char revision[] = "4.6"; + char *s, *S, *t; + + s = rcsid; /* NOOP - keep compilers happy */ + + Strncpy(ifm->f_name, mname, FMNAMESZ); + ifm->f_name[FMNAMESZ] = '\0'; + ifm->f_str = &parseinfo; + /* + * copy RCS revision into Drv_name + * + * are we forcing RCS here to do things it was not built for ? + */ + s = revision; + if (*s == '$') + { + /* + * skip "$Revision: " + * if present. - not necessary on a -kv co (cvs export) + */ + while (*s && (*s != ' ')) + { + s++; + } + if (*s == ' ') s++; + } + + t = parsesync_vd.Drv_name; + while (*t && (*t != ' ')) + { + t++; + } + if (*t == ' ') t++; + + S = s; + while (*S && (((*S >= '0') && (*S <= '9')) || (*S == '.'))) + { + S++; + } + + if (*s && *t && (S > s)) + { + if (Strlen(t) >= (S - s)) + { + (void) Strncpy(t, s, S - s); + } + } + return (0); + } + break; + + case VDUNLOAD: + if (parsebusy > 0) + { + printf("vddrinit[%s]: STREAMS module has still %d instances active.\n", mname, parsebusy); + return (EBUSY); + } + else + { + while (fm <= fmend) + { + if (!Strncmp(fm->f_name, mname, FMNAMESZ)) + { + /* + * got it - kill entry + */ + fm->f_name[0] = '\0'; + fm->f_str = (struct streamtab *)0; + fm++; + + break; + } + fm++; + } + if (fm > fmend) + { + printf("vddrinit[%s]: cannot find entry for STREAMS module\n", mname); + return (ENXIO); + } + else + return (0); + } + + + case VDSTAT: + return (0); + + default: + return (EIO); + + } + return EIO; +} + +#endif + +/*--------------- stream module definition ----------------------------*/ + +static int parseopen P((queue_t *, dev_t, int, int)); +static int parseclose P((queue_t *, int)); +static int parsewput P((queue_t *, mblk_t *)); +static int parserput P((queue_t *, mblk_t *)); +static int parsersvc P((queue_t *)); + +static char mn[] = "parse"; + +static struct module_info driverinfo = +{ + 0, /* module ID number */ + mn, /* module name */ + 0, /* minimum accepted packet size */ + INFPSZ, /* maximum accepted packet size */ + 1, /* high water mark - flow control */ + 0 /* low water mark - flow control */ +}; + +static struct qinit rinit = /* read queue definition */ +{ + parserput, /* put procedure */ + parsersvc, /* service procedure */ + parseopen, /* open procedure */ + parseclose, /* close procedure */ + NULL, /* admin procedure - NOT USED FOR NOW */ + &driverinfo, /* information structure */ + NULL /* statistics */ +}; + +static struct qinit winit = /* write queue definition */ +{ + parsewput, /* put procedure */ + NULL, /* service procedure */ + NULL, /* open procedure */ + NULL, /* close procedure */ + NULL, /* admin procedure - NOT USED FOR NOW */ + &driverinfo, /* information structure */ + NULL /* statistics */ +}; + +struct streamtab parseinfo = /* stream info element for dpr driver */ +{ + &rinit, /* read queue */ + &winit, /* write queue */ + NULL, /* read mux */ + NULL, /* write mux */ + NULL /* module auto push */ +}; + +/*--------------- driver data structures ----------------------------*/ + +/* + * we usually have an inverted signal - but you + * can change this to suit your needs + */ +int cd_invert = 1; /* invert status of CD line - PPS support via CD input */ + +int parsedebug = ~0; + +extern void uniqtime P((struct timeval *)); + +/*--------------- module implementation -----------------------------*/ + +#define TIMEVAL_USADD(_X_, _US_) {\ + (_X_)->tv_usec += (_US_);\ + if ((_X_)->tv_usec >= 1000000)\ + {\ + (_X_)->tv_sec++;\ + (_X_)->tv_usec -= 1000000;\ + }\ + } while (0) + +static int init_linemon P((queue_t *)); +static void close_linemon P((queue_t *, queue_t *)); + +#define M_PARSE 0x0001 +#define M_NOPARSE 0x0002 + +static int +setup_stream( + queue_t *q, + int mode + ) +{ + mblk_t *mp; + + mp = allocb(sizeof(struct stroptions), BPRI_MED); + if (mp) + { + struct stroptions *str = (struct stroptions *)(void *)mp->b_rptr; + + str->so_flags = SO_READOPT|SO_HIWAT|SO_LOWAT; + str->so_readopt = (mode == M_PARSE) ? RMSGD : RNORM; + str->so_hiwat = (mode == M_PARSE) ? sizeof(parsetime_t) : 256; + str->so_lowat = 0; + mp->b_datap->db_type = M_SETOPTS; + mp->b_wptr += sizeof(struct stroptions); + putnext(q, mp); + return putctl1(WR(q)->q_next, M_CTL, (mode == M_PARSE) ? MC_SERVICEIMM : + MC_SERVICEDEF); + } + else + { + parseprintf(DD_OPEN,("parse: setup_stream - FAILED - no MEMORY for allocb\n")); + return 0; + } +} + +/*ARGSUSED*/ +static int +parseopen( + queue_t *q, + dev_t dev, + int flag, + int sflag + ) +{ + register parsestream_t *parse; + static int notice = 0; + + parseprintf(DD_OPEN,("parse: OPEN\n")); + + if (sflag != MODOPEN) + { /* open only for modules */ + parseprintf(DD_OPEN,("parse: OPEN - FAILED - not MODOPEN\n")); + return OPENFAIL; + } + + if (q->q_ptr != (caddr_t)NULL) + { + u.u_error = EBUSY; + parseprintf(DD_OPEN,("parse: OPEN - FAILED - EXCLUSIVE ONLY\n")); + return OPENFAIL; + } + +#ifdef VDDRV + parsebusy++; +#endif + + q->q_ptr = (caddr_t)kmem_alloc(sizeof(parsestream_t)); + if (q->q_ptr == (caddr_t)0) + { + parseprintf(DD_OPEN,("parse: OPEN - FAILED - no memory\n")); +#ifdef VDDRV + parsebusy--; +#endif + return OPENFAIL; + } + WR(q)->q_ptr = q->q_ptr; + + parse = (parsestream_t *)(void *)q->q_ptr; + bzero((caddr_t)parse, sizeof(*parse)); + parse->parse_queue = q; + parse->parse_status = PARSE_ENABLE; + parse->parse_ppsclockev.tv.tv_sec = 0; + parse->parse_ppsclockev.tv.tv_usec = 0; + parse->parse_ppsclockev.serial = 0; + + if (!parse_ioinit(&parse->parse_io)) + { + /* + * ok guys - beat it + */ + kmem_free((caddr_t)parse, sizeof(parsestream_t)); +#ifdef VDDRV + parsebusy--; +#endif + return OPENFAIL; + } + + if (setup_stream(q, M_PARSE)) + { + (void) init_linemon(q); /* hook up PPS ISR routines if possible */ + + parseprintf(DD_OPEN,("parse: OPEN - SUCCEEDED\n")); + + /* + * I know that you know the delete key, but you didn't write this + * code, did you ? - So, keep the message in here. + */ + if (!notice) + { +#ifdef VDDRV + printf("%s: Copyright (C) 1991-1998, Frank Kardel\n", parsesync_vd.Drv_name); +#else + printf("%s: Copyright (C) 1991-1998, Frank Kardel\n", "parsestreams.c,v 4.6 1998/12/20 23:45:31 kardel RELEASE_19990228_A"); +#endif + notice = 1; + } + + return MODOPEN; + } + else + { + kmem_free((caddr_t)parse, sizeof(parsestream_t)); + +#ifdef VDDRV + parsebusy--; +#endif + return OPENFAIL; + } +} + +/*ARGSUSED*/ +static int +parseclose( + queue_t *q, + int flags + ) +{ + register parsestream_t *parse = (parsestream_t *)(void *)q->q_ptr; + register unsigned long s; + + parseprintf(DD_CLOSE,("parse: CLOSE\n")); + + s = splhigh(); + + if (parse->parse_dqueue) + close_linemon(parse->parse_dqueue, q); + parse->parse_dqueue = (queue_t *)0; + + (void) splx(s); + + parse_ioend(&parse->parse_io); + + kmem_free((caddr_t)parse, sizeof(parsestream_t)); + + q->q_ptr = (caddr_t)NULL; + WR(q)->q_ptr = (caddr_t)NULL; + +#ifdef VDDRV + parsebusy--; +#endif + return 0; +} + +/* + * move unrecognized stuff upward + */ +static int +parsersvc( + queue_t *q + ) +{ + mblk_t *mp; + + while ((mp = getq(q))) + { + if (canput(q->q_next) || (mp->b_datap->db_type > QPCTL)) + { + putnext(q, mp); + parseprintf(DD_RSVC,("parse: RSVC - putnext\n")); + } + else + { + putbq(q, mp); + parseprintf(DD_RSVC,("parse: RSVC - flow control wait\n")); + break; + } + } + return 0; +} + +/* + * do ioctls and + * send stuff down - dont care about + * flow control + */ +static int +parsewput( + queue_t *q, + register mblk_t *mp + ) +{ + register int ok = 1; + register mblk_t *datap; + register struct iocblk *iocp; + parsestream_t *parse = (parsestream_t *)(void *)q->q_ptr; + + parseprintf(DD_WPUT,("parse: parsewput\n")); + + switch (mp->b_datap->db_type) + { + default: + putnext(q, mp); + break; + + case M_IOCTL: + iocp = (struct iocblk *)(void *)mp->b_rptr; + switch (iocp->ioc_cmd) + { + default: + parseprintf(DD_WPUT,("parse: parsewput - forward M_IOCTL\n")); + putnext(q, mp); + break; + + case CIOGETEV: + /* + * taken from Craig Leres ppsclock module (and modified) + */ + datap = allocb(sizeof(struct ppsclockev), BPRI_MED); + if (datap == NULL || mp->b_cont) + { + mp->b_datap->db_type = M_IOCNAK; + iocp->ioc_error = (datap == NULL) ? ENOMEM : EINVAL; + if (datap != NULL) + freeb(datap); + qreply(q, mp); + break; + } + + mp->b_cont = datap; + *(struct ppsclockev *)(void *)datap->b_wptr = parse->parse_ppsclockev; + datap->b_wptr += + sizeof(struct ppsclockev) / sizeof(*datap->b_wptr); + mp->b_datap->db_type = M_IOCACK; + iocp->ioc_count = sizeof(struct ppsclockev); + qreply(q, mp); + break; + + case PARSEIOC_ENABLE: + case PARSEIOC_DISABLE: + { + parse->parse_status = (parse->parse_status & (unsigned)~PARSE_ENABLE) | + (iocp->ioc_cmd == PARSEIOC_ENABLE) ? + PARSE_ENABLE : 0; + if (!setup_stream(RD(q), (parse->parse_status & PARSE_ENABLE) ? + M_PARSE : M_NOPARSE)) + { + mp->b_datap->db_type = M_IOCNAK; + } + else + { + mp->b_datap->db_type = M_IOCACK; + } + qreply(q, mp); + break; + } + + case PARSEIOC_TIMECODE: + case PARSEIOC_SETFMT: + case PARSEIOC_GETFMT: + case PARSEIOC_SETCS: + if (iocp->ioc_count == sizeof(parsectl_t)) + { + parsectl_t *dct = (parsectl_t *)(void *)mp->b_cont->b_rptr; + + switch (iocp->ioc_cmd) + { + case PARSEIOC_TIMECODE: + parseprintf(DD_WPUT,("parse: parsewput - PARSEIOC_TIMECODE\n")); + ok = parse_timecode(dct, &parse->parse_io); + break; + + case PARSEIOC_SETFMT: + parseprintf(DD_WPUT,("parse: parsewput - PARSEIOC_SETFMT\n")); + ok = parse_setfmt(dct, &parse->parse_io); + break; + + case PARSEIOC_GETFMT: + parseprintf(DD_WPUT,("parse: parsewput - PARSEIOC_GETFMT\n")); + ok = parse_getfmt(dct, &parse->parse_io); + break; + + case PARSEIOC_SETCS: + parseprintf(DD_WPUT,("parse: parsewput - PARSEIOC_SETCS\n")); + ok = parse_setcs(dct, &parse->parse_io); + break; + } + mp->b_datap->db_type = ok ? M_IOCACK : M_IOCNAK; + } + else + { + mp->b_datap->db_type = M_IOCNAK; + } + parseprintf(DD_WPUT,("parse: parsewput qreply - %s\n", (mp->b_datap->db_type == M_IOCNAK) ? "M_IOCNAK" : "M_IOCACK")); + qreply(q, mp); + break; + } + } + return 0; +} + +/* + * read characters from streams buffers + */ +static unsigned long +rdchar( + register mblk_t **mp + ) +{ + while (*mp != (mblk_t *)NULL) + { + if ((*mp)->b_wptr - (*mp)->b_rptr) + { + return (unsigned long)(*(unsigned char *)((*mp)->b_rptr++)); + } + else + { + register mblk_t *mmp = *mp; + + *mp = (*mp)->b_cont; + freeb(mmp); + } + } + return (unsigned)~0; +} + +/* + * convert incoming data + */ +static int +parserput( + queue_t *q, + mblk_t *mp + ) +{ + unsigned char type; + + switch (type = mp->b_datap->db_type) + { + default: + /* + * anything we don't know will be put on queue + * the service routine will move it to the next one + */ + parseprintf(DD_RPUT,("parse: parserput - forward type 0x%x\n", type)); + if (canput(q->q_next) || (mp->b_datap->db_type > QPCTL)) + { + putnext(q, mp); + } + else + putq(q, mp); + break; + + case M_BREAK: + case M_DATA: + { + register parsestream_t * parse = (parsestream_t *)(void *)q->q_ptr; + register mblk_t *nmp; + register unsigned long ch; + timestamp_t ctime; + + /* + * get time on packet delivery + */ + uniqtime(&ctime.tv); + + if (!(parse->parse_status & PARSE_ENABLE)) + { + parseprintf(DD_RPUT,("parse: parserput - parser disabled - forward type 0x%x\n", type)); + if (canput(q->q_next) || (mp->b_datap->db_type > QPCTL)) + { + putnext(q, mp); + } + else + putq(q, mp); + } + else + { + parseprintf(DD_RPUT,("parse: parserput - M_%s\n", (type == M_DATA) ? "DATA" : "BREAK")); + + if (type == M_DATA) + { + /* + * parse packet looking for start an end characters + */ + while (mp != (mblk_t *)NULL) + { + ch = rdchar(&mp); + if (ch != ~0 && parse_ioread(&parse->parse_io, (unsigned int)ch, &ctime)) + { + /* + * up up and away (hopefully ...) + * don't press it if resources are tight or nobody wants it + */ + nmp = (mblk_t *)NULL; + if (canput(parse->parse_queue->q_next) && (nmp = allocb(sizeof(parsetime_t), BPRI_MED))) + { + bcopy((caddr_t)&parse->parse_io.parse_dtime, (caddr_t)nmp->b_rptr, sizeof(parsetime_t)); + nmp->b_wptr += sizeof(parsetime_t); + putnext(parse->parse_queue, nmp); + } + else + if (nmp) freemsg(nmp); + parse_iodone(&parse->parse_io); + } + } + } + else + { + if (parse_ioread(&parse->parse_io, (unsigned int)0, &ctime)) + { + /* + * up up and away (hopefully ...) + * don't press it if resources are tight or nobody wants it + */ + nmp = (mblk_t *)NULL; + if (canput(parse->parse_queue->q_next) && (nmp = allocb(sizeof(parsetime_t), BPRI_MED))) + { + bcopy((caddr_t)&parse->parse_io.parse_dtime, (caddr_t)nmp->b_rptr, sizeof(parsetime_t)); + nmp->b_wptr += sizeof(parsetime_t); + putnext(parse->parse_queue, nmp); + } + else + if (nmp) freemsg(nmp); + parse_iodone(&parse->parse_io); + } + freemsg(mp); + } + break; + } + } + + /* + * CD PPS support for non direct ISR hack + */ + case M_HANGUP: + case M_UNHANGUP: + { + register parsestream_t * parse = (parsestream_t *)(void *)q->q_ptr; + timestamp_t ctime; + register mblk_t *nmp; + register int status = cd_invert ^ (type == M_UNHANGUP); + + uniqtime(&ctime.tv); + + parseprintf(DD_RPUT,("parse: parserput - M_%sHANGUP\n", (type == M_HANGUP) ? "" : "UN")); + + if ((parse->parse_status & PARSE_ENABLE) && + parse_iopps(&parse->parse_io, (int)(status ? SYNC_ONE : SYNC_ZERO), &ctime)) + { + nmp = (mblk_t *)NULL; + if (canput(parse->parse_queue->q_next) && (nmp = allocb(sizeof(parsetime_t), BPRI_MED))) + { + bcopy((caddr_t)&parse->parse_io.parse_dtime, (caddr_t)nmp->b_rptr, sizeof(parsetime_t)); + nmp->b_wptr += sizeof(parsetime_t); + putnext(parse->parse_queue, nmp); + } + else + if (nmp) freemsg(nmp); + parse_iodone(&parse->parse_io); + freemsg(mp); + } + else + if (canput(q->q_next) || (mp->b_datap->db_type > QPCTL)) + { + putnext(q, mp); + } + else + putq(q, mp); + + if (status) + { + parse->parse_ppsclockev.tv = ctime.tv; + ++(parse->parse_ppsclockev.serial); + } + } + } + return 0; +} + +static int init_zs_linemon P((queue_t *, queue_t *)); /* handle line monitor for "zs" driver */ +static void close_zs_linemon P((queue_t *, queue_t *)); + +/*-------------------- CD isr status monitor ---------------*/ + +static int +init_linemon( + register queue_t *q + ) +{ + register queue_t *dq; + + dq = WR(q); + /* + * we ARE doing very bad things down here (basically stealing ISR + * hooks) + * + * so we chase down the STREAMS stack searching for the driver + * and if this is a known driver we insert our ISR routine for + * status changes in to the ExternalStatus handling hook + */ + while (dq->q_next) + { + dq = dq->q_next; /* skip down to driver */ + } + + /* + * find appropriate driver dependent routine + */ + if (dq->q_qinfo && dq->q_qinfo->qi_minfo) + { + register char *dname = dq->q_qinfo->qi_minfo->mi_idname; + + parseprintf(DD_INSTALL, ("init_linemon: driver is \"%s\"\n", dname)); + +#ifdef sun + if (dname && !Strcmp(dname, "zs")) + { + return init_zs_linemon(dq, q); + } + else +#endif + { + parseprintf(DD_INSTALL, ("init_linemon: driver \"%s\" not suitable for CD monitoring\n", dname)); + return 0; + } + } + parseprintf(DD_INSTALL, ("init_linemon: cannot find driver\n")); + return 0; +} + +static void +close_linemon( + register queue_t *q, + register queue_t *my_q + ) +{ + /* + * find appropriate driver dependent routine + */ + if (q->q_qinfo && q->q_qinfo->qi_minfo) + { + register char *dname = q->q_qinfo->qi_minfo->mi_idname; + +#ifdef sun + if (dname && !Strcmp(dname, "zs")) + { + close_zs_linemon(q, my_q); + return; + } + parseprintf(DD_INSTALL, ("close_linemon: cannot find driver close routine for \"%s\"\n", dname)); +#endif + } + parseprintf(DD_INSTALL, ("close_linemon: cannot find driver name\n")); +} + +#ifdef sun + +#include <sundev/zsreg.h> +#include <sundev/zscom.h> +#include <sundev/zsvar.h> + +static unsigned long cdmask = ZSRR0_CD; + +struct savedzsops +{ + struct zsops zsops; + struct zsops *oldzsops; +}; + +struct zsops *emergencyzs; +extern void zsopinit P((struct zscom *, struct zsops *)); +static int zs_xsisr P((struct zscom *)); /* zs external status interupt handler */ + +static int +init_zs_linemon( + register queue_t *q, + register queue_t *my_q + ) +{ + register struct zscom *zs; + register struct savedzsops *szs; + register parsestream_t *parsestream = (parsestream_t *)(void *)my_q->q_ptr; + /* + * we expect the zsaline pointer in the q_data pointer + * from there on we insert our on EXTERNAL/STATUS ISR routine + * into the interrupt path, before the standard handler + */ + zs = ((struct zsaline *)(void *)q->q_ptr)->za_common; + if (!zs) + { + /* + * well - not found on startup - just say no (shouldn't happen though) + */ + return 0; + } + else + { + unsigned long s; + + /* + * we do a direct replacement, in case others fiddle also + * if somebody else grabs our hook and we disconnect + * we are in DEEP trouble - panic is likely to be next, sorry + */ + szs = (struct savedzsops *)(void *)kmem_alloc(sizeof(struct savedzsops)); + + if (szs == (struct savedzsops *)0) + { + parseprintf(DD_INSTALL, ("init_zs_linemon: CD monitor NOT installed - no memory\n")); + + return 0; + } + else + { + parsestream->parse_data = (void *)szs; + + s = splhigh(); + + parsestream->parse_dqueue = q; /* remember driver */ + + szs->zsops = *zs->zs_ops; + szs->zsops.zsop_xsint = zs_xsisr; /* place our bastard */ + szs->oldzsops = zs->zs_ops; + emergencyzs = zs->zs_ops; + + zsopinit(zs, &szs->zsops); /* hook it up */ + + (void) splx(s); + + parseprintf(DD_INSTALL, ("init_zs_linemon: CD monitor installed\n")); + + return 1; + } + } +} + +/* + * unregister our ISR routine - must call under splhigh() + */ +static void +close_zs_linemon( + register queue_t *q, + register queue_t *my_q + ) +{ + register struct zscom *zs; + register parsestream_t *parsestream = (parsestream_t *)(void *)my_q->q_ptr; + + zs = ((struct zsaline *)(void *)q->q_ptr)->za_common; + if (!zs) + { + /* + * well - not found on startup - just say no (shouldn't happen though) + */ + return; + } + else + { + register struct savedzsops *szs = (struct savedzsops *)parsestream->parse_data; + + zsopinit(zs, szs->oldzsops); /* reset to previous handler functions */ + + kmem_free((caddr_t)szs, sizeof (struct savedzsops)); + + parseprintf(DD_INSTALL, ("close_zs_linemon: CD monitor deleted\n")); + return; + } +} + +#define MAXDEPTH 50 /* maximum allowed stream crawl */ + +#ifdef PPS_SYNC +extern void hardpps P((struct timeval *, long)); +#ifdef PPS_NEW +extern struct timeval timestamp; +#else +extern struct timeval pps_time; +#endif +#endif + +/* + * take external status interrupt (only CD interests us) + */ +static int +zs_xsisr( + struct zscom *zs + ) +{ + register struct zsaline *za = (struct zsaline *)(void *)zs->zs_priv; + register struct zscc_device *zsaddr = zs->zs_addr; + register queue_t *q; + register unsigned char zsstatus; + register int loopcheck; + register char *dname; +#ifdef PPS_SYNC + register unsigned int s; + register long usec; +#endif + + /* + * pick up current state + */ + zsstatus = zsaddr->zscc_control; + + if ((za->za_rr0 ^ zsstatus) & (cdmask)) + { + timestamp_t cdevent; + register int status; + + za->za_rr0 = (za->za_rr0 & ~(cdmask)) | (zsstatus & (cdmask)); + +#ifdef PPS_SYNC + s = splclock(); +#ifdef PPS_NEW + usec = timestamp.tv_usec; +#else + usec = pps_time.tv_usec; +#endif +#endif + /* + * time stamp + */ + uniqtime(&cdevent.tv); + +#ifdef PPS_SYNC + (void)splx(s); +#endif + + /* + * logical state + */ + status = cd_invert ? (zsstatus & cdmask) == 0 : (zsstatus & cdmask) != 0; + +#ifdef PPS_SYNC + if (status) + { + usec = cdevent.tv.tv_usec - usec; + if (usec < 0) + usec += 1000000; + + hardpps(&cdevent.tv, usec); + } +#endif + + q = za->za_ttycommon.t_readq; + + /* + * ok - now the hard part - find ourself + */ + loopcheck = MAXDEPTH; + + while (q) + { + if (q->q_qinfo && q->q_qinfo->qi_minfo) + { + dname = q->q_qinfo->qi_minfo->mi_idname; + + if (!Strcmp(dname, parseinfo.st_rdinit->qi_minfo->mi_idname)) + { + /* + * back home - phew (hopping along stream queues might + * prove dangerous to your health) + */ + + if ((((parsestream_t *)(void *)q->q_ptr)->parse_status & PARSE_ENABLE) && + parse_iopps(&((parsestream_t *)(void *)q->q_ptr)->parse_io, (int)(status ? SYNC_ONE : SYNC_ZERO), &cdevent)) + { + /* + * XXX - currently we do not pass up the message, as + * we should. + * for a correct behaviour wee need to block out + * processing until parse_iodone has been posted via + * a softcall-ed routine which does the message pass-up + * right now PPS information relies on input being + * received + */ + parse_iodone(&((parsestream_t *)(void *)q->q_ptr)->parse_io); + } + + if (status) + { + ((parsestream_t *)(void *)q->q_ptr)->parse_ppsclockev.tv = cdevent.tv; + ++(((parsestream_t *)(void *)q->q_ptr)->parse_ppsclockev.serial); + } + + parseprintf(DD_ISR, ("zs_xsisr: CD event %s has been posted for \"%s\"\n", status ? "ONE" : "ZERO", dname)); + break; + } + } + + q = q->q_next; + + if (!loopcheck--) + { + panic("zs_xsisr: STREAMS Queue corrupted - CD event"); + } + } + + /* + * only pretend that CD has been handled + */ + ZSDELAY(2); + + if (!((za->za_rr0 ^ zsstatus) & ~(cdmask))) + { + /* + * all done - kill status indication and return + */ + zsaddr->zscc_control = ZSWR0_RESET_STATUS; /* might kill other conditions here */ + return 0; + } + } + + if (zsstatus & cdmask) /* fake CARRIER status */ + za->za_flags |= ZAS_CARR_ON; + else + za->za_flags &= ~ZAS_CARR_ON; + + /* + * we are now gathered here to process some unusual external status + * interrupts. + * any CD events have also been handled and shouldn't be processed + * by the original routine (unless we have a VERY busy port pin) + * some initializations are done here, which could have been done before for + * both code paths but have been avoided for minimum path length to + * the uniq_time routine + */ + dname = (char *) 0; + q = za->za_ttycommon.t_readq; + + loopcheck = MAXDEPTH; + + /* + * the real thing for everything else ... + */ + while (q) + { + if (q->q_qinfo && q->q_qinfo->qi_minfo) + { + dname = q->q_qinfo->qi_minfo->mi_idname; + if (!Strcmp(dname, parseinfo.st_rdinit->qi_minfo->mi_idname)) + { + register int (*zsisr) P((struct zscom *)); + + /* + * back home - phew (hopping along stream queues might + * prove dangerous to your health) + */ + if ((zsisr = ((struct savedzsops *)((parsestream_t *)(void *)q->q_ptr)->parse_data)->oldzsops->zsop_xsint)) + return zsisr(zs); + else + panic("zs_xsisr: unable to locate original ISR"); + + parseprintf(DD_ISR, ("zs_xsisr: non CD event was processed for \"%s\"\n", dname)); + /* + * now back to our program ... + */ + return 0; + } + } + + q = q->q_next; + + if (!loopcheck--) + { + panic("zs_xsisr: STREAMS Queue corrupted - non CD event"); + } + } + + /* + * last resort - shouldn't even come here as it indicates + * corrupted TTY structures + */ + printf("zs_zsisr: looking for \"%s\" - found \"%s\" - taking EMERGENCY path\n", parseinfo.st_rdinit->qi_minfo->mi_idname, dname ? dname : "-NIL-"); + + if (emergencyzs && emergencyzs->zsop_xsint) + emergencyzs->zsop_xsint(zs); + else + panic("zs_xsisr: no emergency ISR handler"); + return 0; +} +#endif /* sun */ + +/* + * History: + * + * parsestreams.c,v + * Revision 4.6 1998/12/20 23:45:31 kardel + * fix types and warnings + * + * Revision 4.5 1998/11/15 21:23:38 kardel + * ntp_memset() replicated in Sun kernel files + * + * Revision 4.4 1998/06/13 12:15:59 kardel + * superfluous variable removed + * + * Revision 4.3 1998/06/12 15:23:08 kardel + * fix prototypes + * adjust for ansi2knr + * + * Revision 4.2 1998/05/24 18:16:22 kardel + * moved copy of shadow status to the beginning + * + * Revision 4.1 1998/05/24 09:38:47 kardel + * streams initiated iopps calls (M_xHANGUP) are now consistent with the + * respective calls from zs_xsisr() + * simulation of CARRIER status to avoid unecessary M_xHANGUP messages + * + * Revision 4.0 1998/04/10 19:45:38 kardel + * Start 4.0 release version numbering + * + * from V3 3.37 log info deleted 1998/04/11 kardel + */ diff --git a/contrib/ntp/libparse/trim_info.c b/contrib/ntp/libparse/trim_info.c new file mode 100644 index 000000000000..ab2e1fe1ca55 --- /dev/null +++ b/contrib/ntp/libparse/trim_info.c @@ -0,0 +1,35 @@ +/* + * /src/NTP/ntp-4/libparse/trim_info.c,v 4.2 1998/12/20 23:45:31 kardel RELEASE_19990228_A + * + * $Created: Sun Aug 2 20:20:34 1998 $ + * + * Copyright (C) 1998 by Frank Kardel + */ +#include "ntp_types.h" +#include "trimble.h" + +cmd_info_t * +trimble_convert( + unsigned int cmd, + cmd_info_t *tbl + ) +{ + int i; + + for (i = 0; tbl[i].cmd != 0xFF; i++) + { + if (tbl[i].cmd == cmd) + return &tbl[i]; + } + return 0; +} + +/* + * trim_info.c,v + * Revision 4.2 1998/12/20 23:45:31 kardel + * fix types and warnings + * + * Revision 4.1 1998/08/09 22:27:48 kardel + * Trimble TSIP support + * + */ |