summaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/Makefile.am5
-rw-r--r--kernel/Makefile.in445
-rw-r--r--kernel/README200
-rw-r--r--kernel/chuinit.c76
-rw-r--r--kernel/clkinit.c76
-rw-r--r--kernel/sys/Makefile.am8
-rw-r--r--kernel/sys/Makefile.in355
-rw-r--r--kernel/sys/README11
-rw-r--r--kernel/sys/bsd_audioirig.h101
-rw-r--r--kernel/sys/chudefs.h22
-rw-r--r--kernel/sys/clkdefs.h38
-rw-r--r--kernel/sys/i8253.h48
-rw-r--r--kernel/sys/parsestreams.h109
-rw-r--r--kernel/sys/pcl720.h95
-rw-r--r--kernel/sys/ppsclock.h64
-rw-r--r--kernel/sys/timex.h309
-rw-r--r--kernel/sys/tpro.h34
-rw-r--r--kernel/sys/tt560_api.h489
-rw-r--r--kernel/tty_chu.c276
-rw-r--r--kernel/tty_chu_STREAMS.c603
-rw-r--r--kernel/tty_clk.c317
-rw-r--r--kernel/tty_clk_STREAMS.c266
22 files changed, 3947 insertions, 0 deletions
diff --git a/kernel/Makefile.am b/kernel/Makefile.am
new file mode 100644
index 0000000..b3cfc9d
--- /dev/null
+++ b/kernel/Makefile.am
@@ -0,0 +1,5 @@
+#AUTOMAKE_OPTIONS = ../util/ansi2knr no-dependencies
+AUTOMAKE_OPTIONS = ../util/ansi2knr
+SUBDIRS = sys
+ETAGS_ARGS = Makefile.am
+EXTRA_DIST = chuinit.c clkinit.c tty_chu.c tty_chu_STREAMS.c tty_clk.c tty_clk_STREAMS.c
diff --git a/kernel/Makefile.in b/kernel/Makefile.in
new file mode 100644
index 0000000..07eb378
--- /dev/null
+++ b/kernel/Makefile.in
@@ -0,0 +1,445 @@
+# Makefile.in generated by automake 1.7.7 from Makefile.am.
+# @configure_input@
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+# 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.
+
+@SET_MAKE@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+ARLIB_DIR = @ARLIB_DIR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CHUTEST = @CHUTEST@
+CLKTEST = @CLKTEST@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DCFD = @DCFD@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EF_LIBS = @EF_LIBS@
+EF_PROGS = @EF_PROGS@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LCRYPTO = @LCRYPTO@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBPARSE = @LIBPARSE@
+LIBS = @LIBS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MAKE_ADJTIMED = @MAKE_ADJTIMED@
+MAKE_CHECK_Y2K = @MAKE_CHECK_Y2K@
+MAKE_LIBNTPSIM = @MAKE_LIBNTPSIM@
+MAKE_LIBPARSE = @MAKE_LIBPARSE@
+MAKE_LIBPARSE_KERNEL = @MAKE_LIBPARSE_KERNEL@
+MAKE_NTPDSIM = @MAKE_NTPDSIM@
+MAKE_NTPTIME = @MAKE_NTPTIME@
+MAKE_NTP_KEYGEN = @MAKE_NTP_KEYGEN@
+MAKE_PARSEKMODULE = @MAKE_PARSEKMODULE@
+MAKE_SNTP = @MAKE_SNTP@
+MAKE_TICKADJ = @MAKE_TICKADJ@
+MAKE_TIMETRIM = @MAKE_TIMETRIM@
+OBJEXT = @OBJEXT@
+OPENSSL = @OPENSSL@
+OPENSSL_INC = @OPENSSL_INC@
+OPENSSL_LIB = @OPENSSL_LIB@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_PERL = @PATH_PERL@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PATH_SH = @PATH_SH@
+PROPDELAY = @PROPDELAY@
+RANLIB = @RANLIB@
+READLINE_LIBS = @READLINE_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TESTDCF = @TESTDCF@
+U = @U@
+VERSION = @VERSION@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+subdirs = @subdirs@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+
+#AUTOMAKE_OPTIONS = ../util/ansi2knr no-dependencies
+AUTOMAKE_OPTIONS = ../util/ansi2knr
+SUBDIRS = sys
+ETAGS_ARGS = Makefile.am
+EXTRA_DIST = chuinit.c clkinit.c tty_chu.c tty_chu_STREAMS.c tty_clk.c tty_clk_STREAMS.c
+subdir = kernel
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+DIST_SOURCES =
+
+RECURSIVE_TARGETS = info-recursive dvi-recursive pdf-recursive \
+ ps-recursive install-info-recursive uninstall-info-recursive \
+ all-recursive install-data-recursive install-exec-recursive \
+ installdirs-recursive install-recursive uninstall-recursive \
+ check-recursive installcheck-recursive
+DIST_COMMON = README $(srcdir)/Makefile.in Makefile.am
+DIST_SUBDIRS = $(SUBDIRS)
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu kernel/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
+uninstall-info-am:
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @set fnord $$MAKEFLAGS; amf=$$2; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+ @set fnord $$MAKEFLAGS; amf=$$2; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ETAGS = etags
+ETAGSFLAGS =
+
+CTAGS = ctags
+CTAGSFLAGS =
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ if (etags --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ else \
+ include_option=--include; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -f $$subdir/TAGS && \
+ tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$tags$$unique" \
+ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique
+
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = ..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkinstalldirs) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d $(distdir)/$$subdir \
+ || mkdir $(distdir)/$$subdir \
+ || exit 1; \
+ (cd $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$(top_distdir)" \
+ distdir=../$(distdir)/$$subdir \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-recursive
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+uninstall-info: uninstall-info-recursive
+
+.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am clean \
+ clean-generic clean-recursive ctags ctags-recursive distclean \
+ distclean-generic distclean-recursive distclean-tags distdir \
+ dvi dvi-am dvi-recursive info info-am info-recursive install \
+ install-am install-data install-data-am install-data-recursive \
+ install-exec install-exec-am install-exec-recursive \
+ install-info install-info-am install-info-recursive install-man \
+ install-recursive install-strip installcheck installcheck-am \
+ installdirs installdirs-am installdirs-recursive \
+ maintainer-clean maintainer-clean-generic \
+ maintainer-clean-recursive mostlyclean mostlyclean-generic \
+ mostlyclean-recursive pdf pdf-am pdf-recursive ps ps-am \
+ ps-recursive tags tags-recursive uninstall uninstall-am \
+ uninstall-info-am uninstall-info-recursive uninstall-recursive
+
+# 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/kernel/README b/kernel/README
new file mode 100644
index 0000000..253d04e
--- /dev/null
+++ b/kernel/README
@@ -0,0 +1,200 @@
+Installing Line Disciplines and Streams Modules
+
+Description
+
+Most radio and modem clocks used for a primary (stratum-1) NTP server
+utilize serial ports operating at speeds of 9600 baud or greater. The
+timing jitter contributed by the serial port hardware and software
+discipline can accumulate to several milliseconds on a typical Unix
+workstation. In order to reduce these errors, a set of special line
+disciplines can be configured in the operating system process. These
+disciplines intercept special characters or signals provided by the
+radio or modem clock and save a local timestamp for later processing.
+
+The disciplines can be compiled in the kernel in older BSD-derived
+systems, or installed as System V streams modules and either compiled in
+the kernel or dynamically loaded when required. In either case, they
+require reconfiguration of the Unix kernel and provisions in the NTP
+daemon xntpd. The streams modules can be pushed and popped from the
+streams stack using conventional System V streams program primitives.
+Note that not all Unix kernels support line disciplines and of those
+that do, not all support System V streams. The disciplines here are
+known to work correctly with SunOS 4.x kernels, but have not been tested
+for other kernels.
+
+There are two line disciplines included in the distribution. Support for
+each is enabled by adding flags to the DEFS_LOCAL line of the build
+configuration file ./Config.local. This can be done automatically by the
+autoconfiguration build procedures, or can be inserted/deleted after the
+process has completed.
+
+tty_clk (CLK)
+
+ This discipline intercepts characters received from the serial port
+ and passes unchanged all except a set of designated characters to
+ the generic serial port discipline. For each of the exception
+ characters, the character is inserted in the receiver buffer
+ followed by a timestamp in Unix timeval format. Both select() and
+ SIGIO are supported by the discipline. The -DCLK flag is used to
+ compile support for this disipline in the NTP daemon. This flag is
+ included if the clkdefs.h file is found in the /sys/sys directory,
+ or it can be added (or deleted) manually.
+
+tty_chu (CHU)
+
+ This discipline is a special purpose line discipline for receiving
+ a special timecode broadcast by Canadian time and frequency
+ standard station CHU. The radio signal is first demodulated by the
+ 300-baud modem included in the gadget box, then processed by the
+ discipline and finally processed by the Scratchbuilt CHU Receiver
+ discipline (type 7). This discipline should be used in raw mode.
+ The -DCHU flag is used to compile support for this disipline in the
+ NTP daemon. This flag is included if the chudefs.h file is found in
+ the /sys/sys directory, or it can be added (or deleted) manually.
+
+There are two sets of line disciplines. The tty_clk.c and chu_clk.c are
+designed for use with older BSD systems and are compiled in the kernel.
+The tty_clk_STREAMS.c and chu_clk_STREAMS.c are designed for use with
+System V streams, in which case they can be either compiled in the
+kernel or dynamically loaded. Since these disciplines are small,
+unobtrusive, and to nothing unless specifically enabled by an
+application program, it probably doesn't matter which method is choosen.
+
+Compiling with the Kernel
+
+The following procedures are for the tty_clk line discipline; for the
+chu_clk, change "tty" to "chu".
+1. Copy tty_clk.c into /sys/os and clkdefs.h into /sys/sys.
+
+2. For SunOS 4.x systems, edit /sys/os/tty_conf.c using some facsimile
+ of the following lines:
+
+ #include "clk.h"
+ ...
+ #if NCLK > 0
+ int clkopen(), clkclose(), clkwrite(), clkinput(), clkioctl();
+ #endif
+ ...
+ #if NCLK > 0
+ { clkopen, clkclose, ttread, clkwrite, clkioctl,
+ clkinput, nodev, nulldev, ttstart, nullmodem, /* 10 CLK */
+ ttselect },
+ #else
+ { nodev, nodev, nodev, nodev, nodev,
+ nodev, nodev, nodev, nodev, nodev,
+ nodev },
+ #endif
+
+ For Ultrix 4.x systems, edit /sys/data/tty_conf_data.c using some
+ facsimile of the following lines:
+
+ #include "clk.h"
+ ...
+ #if NCLK > 0
+ int clkopen(), clkclose(), clkwrite(), clkinput(), clkioctl();
+ #endif
+ ...
+ #if NCLK > 0
+ clkopen, clkclose, ttread, clkwrite, clkioctl, /* 10 CLK */
+ clkinput, nodev, nulldev, ttstart, nulldev,
+ #else
+ nodev, nodev, nodev, nodev, nodev,
+ nodev, nodev, nodev, nodev, nodev,
+ #endif
+
+ If the kernel doesn't include the ??select() entry in the structure
+ (i.e., there are only ten entry points in the structure) just leave
+ it out. Also note that the number you give the line discipline (10
+ in most kernels) will be specific to that kernel and will depend on
+ what is in there already. The entries sould be in order with no
+ missing space; that is, if there are only seven disciplines already
+ defined and you want to use 10 for good reason, you should define a
+ dummy 9th entry like this:
+
+ nodev, nodev, nodev, nodev, nodev, /* 9 CLK */
+ nodev, nodev, nodev, nodev, nodev,
+
+3. Edit /sys/h/ioctl.h and include a line somewhere near where other
+ line disciplines are defined like:
+
+ #define CLKLDISC 10 /* clock line discipline */
+
+ The "10" should match what you used as the number in the preceding
+ step.
+
+4. Edit /sys/conf/files and add a line which looks like:
+
+ sys/tty_clk.c optional clk
+
+5. Edit the kernel configuration file to include the following:
+
+ pseudo-device tty 4 # TTY clock support
+6. Run config, then make clean, then make depend, then make vmunix,
+ then reboot the new kernel.
+
+Installing as a streams module
+
+The following procedures are for the tty_clk_STREAMS line discipline;
+for the tty_chu_STREAMS, change "clk" to "chu".
+
+1. Copy your choice to /sys/os, removing the "_STREAMS" in the
+ filename.
+
+2. Copy the clkdefs.h file to /usr/include/sys, then construct a soft
+ link to /sys/sys.
+
+3. Append to /sys/conf.common/files.cmn:
+
+ os/tty_tty.c optional tty
+
+4. Edit /sys/sun/str_conf.c. You'll want to add lines in three places.
+ It'll be sort of clear where when you see the file.
+
+ #include "tty.h"
+ ...
+ #if NTTY > 0
+ extern struct streamtab ttyinfo;
+ #endif
+ ...
+ #if NTTY > 0
+ { "tty", &ttyinfo },
+ #endif
+
+5. Edit /sys/[arch]/conf/[k-name] (substituting the architecture and
+ kernel name) to stick in:
+
+ pseudo-device tty 4 # TTY clock support
+
+ You can change "4" to anything you like. It will limit the number
+ of instantiations of the tty discipline you can use at the same
+ time.
+
+6. Run config, then make clean, then make depend, then make vmunix,
+ then reboot the new kernel.
+
+Both disciplines can be dynamically loaded using streams procedures
+specific to the kernel. Before using the chu_clk discipline, all other
+streams modules that may already be on the stack should be popped, then
+the discipline should be pushed on the stack.
+
+How to Use the tty_clk Line Discipline
+
+The tty_clk line discipline defines a new ioctl(), CLK_SETSTR, which
+takes a pointer to a string of no more than CLK_MAXSTRSIZE characters.
+Until the first CLK_SETSTR is performed, the discipline will simply pass
+through characters. Once it is passed a string by CLK_SETSTR, any
+character in that string will be immediately followed by a timestamp in
+Unix timeval format. You can change the string whenever you want by
+doing another CLK_SETSTR. The character must be an exact, 8 bit match.
+The character '\000' cannot, unfortunately, be used, as it is the string
+terminator. Passing an empty string to CLK_SETSTR turns off stamping.
+Passing NULL will produce undefined results.
+
+How to Use the tty_chu Line Discipline
+The tty_chu line discipline translates data received from the CHU modem
+and returns chucode structures, as defined in chudefs.h, and expected by
+the Scratchbuilt CHU Receiver reference clock driver. Depending on the
+settings of PEDANTIC and ANAL_RETENTIVE used when compiling the kernel,
+some checking of the data may or may not be necessary.
+
+David L. Mills (mills@udel.edu)
diff --git a/kernel/chuinit.c b/kernel/chuinit.c
new file mode 100644
index 0000000..5d73e52
--- /dev/null
+++ b/kernel/chuinit.c
@@ -0,0 +1,76 @@
+/*
+** dynamically loadable chu driver
+**
+** /src/NTP/REPOSITORY/v3/kernel/chuinit.c,v 1.1.1.1 1994/07/11 07:56:25 kardel Exp
+**
+** william robertson <rob@agate.berkeley.edu>
+*/
+
+#include <sys/types.h>
+#include <sys/conf.h>
+#include <sys/errno.h>
+#include <sys/stream.h>
+#include <sys/syslog.h>
+
+#include <sun/openprom.h>
+#include <sun/vddrv.h>
+
+extern int findmod(); /* os/str_io.c */
+
+extern struct streamtab chuinfo;
+
+struct vdldrv vd = {
+ VDMAGIC_USER,
+ "chu"
+ };
+
+
+int
+xxxinit(function_code, vdp, vdi, vds)
+unsigned int function_code;
+struct vddrv *vdp;
+addr_t vdi;
+struct vdstat *vds;
+{
+ register int i = 0;
+ register int j;
+
+ switch (function_code) {
+ case VDLOAD:
+
+ if (findmod("chu") >= 0) {
+ log(LOG_ERR, "chu stream module already loaded\n");
+ return (EADDRINUSE);
+ }
+
+ i = findmod("\0");
+
+ if (i == -1 || fmodsw[i].f_name[0] != '\0')
+ return(-1);
+
+ for (j = 0; vd.Drv_name[j] != '\0'; j++) /* XXX check bounds */
+ fmodsw[i].f_name[j] = vd.Drv_name[j];
+
+ fmodsw[i].f_name[j] = '\0';
+ fmodsw[i].f_str = &chuinfo;
+
+ vdp->vdd_vdtab = (struct vdlinkage *) &vd;
+
+ return(0);
+
+ case VDUNLOAD:
+ if ((i = findmod(vd.Drv_name)) == -1)
+ return(-1);
+
+ fmodsw[i].f_name[0] = '\0';
+ fmodsw[i].f_str = 0;
+
+ return(0);
+
+ case VDSTAT:
+ return(0);
+
+ default:
+ return(EIO);
+ }
+}
diff --git a/kernel/clkinit.c b/kernel/clkinit.c
new file mode 100644
index 0000000..1af57fd
--- /dev/null
+++ b/kernel/clkinit.c
@@ -0,0 +1,76 @@
+/*
+** dynamically loadable clk driver
+**
+** /src/NTP/REPOSITORY/v3/kernel/clkinit.c,v 1.1.1.1 1994/07/11 07:56:25 kardel Exp
+**
+** william robertson <rob@agate.berkeley.edu>
+*/
+
+#include <sys/types.h>
+#include <sys/conf.h>
+#include <sys/errno.h>
+#include <sys/stream.h>
+#include <sys/syslog.h>
+
+#include <sun/openprom.h>
+#include <sun/vddrv.h>
+
+extern int findmod(); /* os/str_io.c */
+
+extern struct streamtab clkinfo;
+
+struct vdldrv vd = {
+ VDMAGIC_USER,
+ "clk"
+ };
+
+
+int
+xxxinit(function_code, vdp, vdi, vds)
+unsigned int function_code;
+struct vddrv *vdp;
+addr_t vdi;
+struct vdstat *vds;
+{
+ register int i = 0;
+ register int j;
+
+ switch (function_code) {
+ case VDLOAD:
+
+ if (findmod("clk") >= 0) {
+ log(LOG_ERR, "clk stream module already loaded\n");
+ return (EADDRINUSE);
+ }
+
+ i = findmod("\0");
+
+ if (i == -1 || fmodsw[i].f_name[0] != '\0')
+ return(-1);
+
+ for (j = 0; vd.Drv_name[j] != '\0'; j++) /* XXX check bounds */
+ fmodsw[i].f_name[j] = vd.Drv_name[j];
+
+ fmodsw[i].f_name[j] = '\0';
+ fmodsw[i].f_str = &clkinfo;
+
+ vdp->vdd_vdtab = (struct vdlinkage *) &vd;
+
+ return(0);
+
+ case VDUNLOAD:
+ if ((i = findmod(vd.Drv_name)) == -1)
+ return(-1);
+
+ fmodsw[i].f_name[0] = '\0';
+ fmodsw[i].f_str = 0;
+
+ return(0);
+
+ case VDSTAT:
+ return(0);
+
+ default:
+ return(EIO);
+ }
+}
diff --git a/kernel/sys/Makefile.am b/kernel/sys/Makefile.am
new file mode 100644
index 0000000..e8465d9
--- /dev/null
+++ b/kernel/sys/Makefile.am
@@ -0,0 +1,8 @@
+#AUTOMAKE_OPTIONS = ../../util/ansi2knr no-dependencies
+AUTOMAKE_OPTIONS = ../../util/ansi2knr
+noinst_HEADERS = bsd_audioirig.h chudefs.h clkdefs.h i8253.h parsestreams.h \
+ pcl720.h ppsclock.h timex.h tpro.h tt560_api.h
+#EXTRA_DIST= TAGS
+# HMS: Avoid bug in automake
+#ETAGS_ARGS = ""
+ETAGS_ARGS = Makefile.am
diff --git a/kernel/sys/Makefile.in b/kernel/sys/Makefile.in
new file mode 100644
index 0000000..e8635a3
--- /dev/null
+++ b/kernel/sys/Makefile.in
@@ -0,0 +1,355 @@
+# Makefile.in generated by automake 1.7.7 from Makefile.am.
+# @configure_input@
+
+# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+# 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.
+
+@SET_MAKE@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ../..
+
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+target_triplet = @target@
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+ARLIB_DIR = @ARLIB_DIR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CHUTEST = @CHUTEST@
+CLKTEST = @CLKTEST@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DCFD = @DCFD@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EF_LIBS = @EF_LIBS@
+EF_PROGS = @EF_PROGS@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LCRYPTO = @LCRYPTO@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBPARSE = @LIBPARSE@
+LIBS = @LIBS@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MAKE_ADJTIMED = @MAKE_ADJTIMED@
+MAKE_CHECK_Y2K = @MAKE_CHECK_Y2K@
+MAKE_LIBNTPSIM = @MAKE_LIBNTPSIM@
+MAKE_LIBPARSE = @MAKE_LIBPARSE@
+MAKE_LIBPARSE_KERNEL = @MAKE_LIBPARSE_KERNEL@
+MAKE_NTPDSIM = @MAKE_NTPDSIM@
+MAKE_NTPTIME = @MAKE_NTPTIME@
+MAKE_NTP_KEYGEN = @MAKE_NTP_KEYGEN@
+MAKE_PARSEKMODULE = @MAKE_PARSEKMODULE@
+MAKE_SNTP = @MAKE_SNTP@
+MAKE_TICKADJ = @MAKE_TICKADJ@
+MAKE_TIMETRIM = @MAKE_TIMETRIM@
+OBJEXT = @OBJEXT@
+OPENSSL = @OPENSSL@
+OPENSSL_INC = @OPENSSL_INC@
+OPENSSL_LIB = @OPENSSL_LIB@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_PERL = @PATH_PERL@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PATH_SH = @PATH_SH@
+PROPDELAY = @PROPDELAY@
+RANLIB = @RANLIB@
+READLINE_LIBS = @READLINE_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+TESTDCF = @TESTDCF@
+U = @U@
+VERSION = @VERSION@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+subdirs = @subdirs@
+sysconfdir = @sysconfdir@
+target = @target@
+target_alias = @target_alias@
+target_cpu = @target_cpu@
+target_os = @target_os@
+target_vendor = @target_vendor@
+
+#AUTOMAKE_OPTIONS = ../../util/ansi2knr no-dependencies
+AUTOMAKE_OPTIONS = ../../util/ansi2knr
+noinst_HEADERS = bsd_audioirig.h chudefs.h clkdefs.h i8253.h parsestreams.h \
+ pcl720.h ppsclock.h timex.h tpro.h tt560_api.h
+
+#EXTRA_DIST= TAGS
+# HMS: Avoid bug in automake
+#ETAGS_ARGS = ""
+ETAGS_ARGS = Makefile.am
+subdir = kernel/sys
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+DIST_SOURCES =
+HEADERS = $(noinst_HEADERS)
+
+DIST_COMMON = README $(noinst_HEADERS) $(srcdir)/Makefile.in \
+ Makefile.am
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4)
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu kernel/sys/Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
+uninstall-info-am:
+
+ETAGS = etags
+ETAGSFLAGS =
+
+CTAGS = ctags
+CTAGSFLAGS =
+
+tags: TAGS
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(ETAGS_ARGS)$$tags$$unique" \
+ || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique
+
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+
+top_distdir = ../..
+distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkinstalldirs) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(HEADERS)
+
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am:
+
+install-info: install-info-am
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-info-am
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic ctags \
+ distclean distclean-generic distclean-tags distdir dvi dvi-am \
+ info info-am install install-am install-data install-data-am \
+ install-exec install-exec-am install-info install-info-am \
+ install-man install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-generic pdf pdf-am ps ps-am tags \
+ uninstall uninstall-am uninstall-info-am
+
+# 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/kernel/sys/README b/kernel/sys/README
new file mode 100644
index 0000000..b9d95d9
--- /dev/null
+++ b/kernel/sys/README
@@ -0,0 +1,11 @@
+README file for directory ./kernel/sys of the NTP Version 3 distribution
+
+This directory contains system header files used by the clock discipline
+and STREAMS modules in the .. (./kernel) directory.
+
+If the precision-time kernel (KERNEL_PLL define) is configured, the
+installation process requires the header file /usr/include/sys/timex.h
+for the particular architecture to be in place. The file timex.h included
+in this distribution is for Suns; the files for other systems can be
+found in the kernel distributions available from the manufacturer's
+representatives.
diff --git a/kernel/sys/bsd_audioirig.h b/kernel/sys/bsd_audioirig.h
new file mode 100644
index 0000000..9b7c690
--- /dev/null
+++ b/kernel/sys/bsd_audioirig.h
@@ -0,0 +1,101 @@
+/*
+ * $Header: bsd_audioirig.h,v 1.0 93/08/02 12:42:00
+ */
+
+#ifndef _BSD_AUDIOIRIG_H_
+#define _BSD_AUDIOIRIG_H_
+
+#include <sys/time.h>
+
+/********************************************************************/
+/* user interface */
+
+/*
+ * irig ioctls
+ */
+#if defined(__STDC__) || (!defined(sun) && !defined(ibm032) && !defined(__GNUC))
+#define AUDIO_IRIG_OPEN _IO('A', 50)
+#define AUDIO_IRIG_CLOSE _IO('A', 51)
+#define AUDIO_IRIG_SETFORMAT _IOWR('A', 52, int)
+#else
+#define AUDIO_IRIG_OPEN _IO(A, 50)
+#define AUDIO_IRIG_CLOSE _IO(A, 51)
+#define AUDIO_IRIG_SETFORMAT _IOWR(A, 52, int)
+#endif
+
+/*
+ * irig error codes
+ */
+#define AUDIO_IRIG_BADSIGNAL 0x01
+#define AUDIO_IRIG_BADDATA 0x02
+#define AUDIO_IRIG_BADSYNC 0x04
+#define AUDIO_IRIG_BADCLOCK 0x08
+#define AUDIO_IRIG_OLDDATA 0x10
+
+/********************************************************************/
+
+/*
+ * auib definitions
+ */
+#define AUIB_SIZE (0x0040)
+#define AUIB_INC (0x0008)
+#define AUIB_MOD(k) ((k) & 0x0038)
+#define AUIB_INIT(ib) ((ib)->ib_head = (ib)->ib_tail = (ib)->ib_lock = \
+ (ib)->phase = (ib)->shi = (ib)->slo = (ib)->high = \
+ (ib)->level0 = (ib)->level1 = \
+ (ib)->shift[0] = (ib)->shift[1] = (ib)->shift[2] = \
+ (ib)->shift[3] = (ib)->sdata[0] = (ib)->sdata[1] = \
+ (ib)->sdata[2] = (ib)->sdata[3] = (ib)->err = 0)
+#define AUIB_EMPTY(ib) ((ib)->ib_head == (ib)->ib_tail)
+#define AUIB_LEN(ib) (AUIB_MOD((ib)->ib_tail - (ib)->ib_head))
+#define AUIB_LEFT(ib) (AUIB_MOD((ib)->ib_head - (ib)->ib_tail - 1))
+#define IRIGDELAY 3
+#define IRIGLEVEL 1355
+
+#ifndef LOCORE
+/*
+ * irig_time holds IRIG data for one second
+ */
+struct irig_time {
+ struct timeval stamp; /* timestamp */
+ u_char bits[13]; /* 100 irig data bits */
+ u_char status; /* status byte */
+ char time[14]; /* time string */
+};
+
+/*
+ * auib's are used for IRIG data communication between the trap
+ * handler and the software interrupt.
+ */
+struct auib {
+ /* driver variables */
+ u_short active; /* 0=inactive, else=active */
+ u_short format; /* time output format */
+ struct irig_time timestr; /* time structure */
+ char buffer[14]; /* output formation buffer */
+
+ /* hardware interrupt variables */
+ struct timeval tv1,tv2,tv3; /* time stamps (median filter) */
+ int level0,level1; /* lo/hi input levels */
+ int level; /* decision level */
+ int high; /* recent largest sample */
+ int sl0,sl1; /* recent sample levels */
+ int lasts; /* last sample value */
+ u_short scount; /* sample count */
+ u_long eacc; /* 10-bit element accumulator */
+ u_long ebit; /* current bit in element */
+ u_char r_level,mmr1; /* recording level 0-255 */
+ int shi,slo,phase; /* AGC variables */
+ u_long err; /* error status bits */
+ int ecount; /* count of elements this second */
+ long shift[4]; /* shift register of pos ident */
+ long sdata[4]; /* shift register of symbols */
+
+ int ib_head; /* queue head */
+ int ib_tail; /* queue tail */
+ u_short ib_lock; /* queue head lock */
+ u_long ib_data[AUIB_SIZE]; /* data buffer */
+};
+#endif
+
+#endif /* _BSD_AUDIOIRIG_H_ */
diff --git a/kernel/sys/chudefs.h b/kernel/sys/chudefs.h
new file mode 100644
index 0000000..f5549f5
--- /dev/null
+++ b/kernel/sys/chudefs.h
@@ -0,0 +1,22 @@
+/*
+ * Definitions for the CHU line discipline v2.0
+ */
+
+/*
+ * The CHU time code consists of 10 BCD digits and is repeated
+ * twice for a total of 10 characters. A time is taken after
+ * the arrival of each character. The following structure is
+ * used to return this stuff.
+ */
+#define NCHUCHARS (10)
+
+struct chucode {
+ u_char codechars[NCHUCHARS]; /* code characters */
+ u_char ncodechars; /* number of code characters */
+ u_char chutype; /* packet type */
+ struct timeval codetimes[NCHUCHARS]; /* arrival times */
+};
+
+#define CHU_TIME 0 /* second half is equal to first half */
+#define CHU_YEAR 1 /* second half is one's complement */
+
diff --git a/kernel/sys/clkdefs.h b/kernel/sys/clkdefs.h
new file mode 100644
index 0000000..afbc77a
--- /dev/null
+++ b/kernel/sys/clkdefs.h
@@ -0,0 +1,38 @@
+/*
+ * Defines for the "clk" timestamping STREAMS module
+ */
+
+#if defined(sun)
+#include <sys/ioccom.h>
+#else
+#include <sys/ioctl.h>
+#endif
+
+/*
+ * First, we need to define the maximum size of the set of
+ * characters to timestamp. 32 is MORE than enough.
+ */
+
+#define CLK_MAXSTRSIZE 32
+struct clk_tstamp_charset { /* XXX to use _IOW not _IOWN */
+ char val[CLK_MAXSTRSIZE];
+};
+
+/*
+ * ioctl(fd, CLK_SETSTR, (char*)c );
+ *
+ * will tell the driver that any char in the null-terminated
+ * string c should be timestamped. It is possible, though
+ * unlikely that this ioctl number could collide with an
+ * existing one on your system. If so, change the 'K'
+ * to some other letter. However, once you've compiled
+ * the kernel with this include file, you should NOT
+ * change this file.
+ */
+
+#if defined(__STDC__) /* XXX avoid __STDC__=0 on SOLARIS */
+#define CLK_SETSTR _IOW('K', 01, struct clk_tstamp_charset)
+#else
+#define CLK_SETSTR _IOW(K, 01, struct clk_tstamp_charset)
+#endif
+
diff --git a/kernel/sys/i8253.h b/kernel/sys/i8253.h
new file mode 100644
index 0000000..7096593
--- /dev/null
+++ b/kernel/sys/i8253.h
@@ -0,0 +1,48 @@
+/* Copyright (c) 1995 Vixie Enterprises
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Vixie Enterprises not be used in advertising or publicity
+ * pertaining to distribution of the document or software without specific,
+ * written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND VIXIE ENTERPRISES DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VIXIE ENTERPRISES
+ * BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#ifndef _I8253_DEFINED
+#define _I8253_DEFINED
+
+typedef union {
+ unsigned char i;
+ struct {
+ unsigned int bcd : 1;
+#define i8253_binary 0
+#define i8253_bcd 1
+ unsigned int mode : 3;
+#define i8253_termcnt 0
+#define i8253_oneshot 1
+#define i8253_rategen 2
+#define i8253_sqrwave 3
+#define i8253_softstb 4
+#define i8253_hardstb 5
+ unsigned int rl : 2;
+#define i8253_latch 0
+#define i8253_lsb 1
+#define i8253_msb 2
+#define i8253_lmb 3
+ unsigned int cntr : 2;
+#define i8253_cntr_0 0
+#define i8253_cntr_1 1
+#define i8253_cntr_2 2
+ } s;
+} i8253_ctrl;
+
+#endif /*_I8253_DEFINED*/
diff --git a/kernel/sys/parsestreams.h b/kernel/sys/parsestreams.h
new file mode 100644
index 0000000..47649b3
--- /dev/null
+++ b/kernel/sys/parsestreams.h
@@ -0,0 +1,109 @@
+/*
+ * /src/NTP/ntp-4/kernel/sys/parsestreams.h,v 4.4 1998/06/14 21:09:32 kardel RELEASE_19990228_A
+ *
+ * parsestreams.h,v 4.4 1998/06/14 21:09:32 kardel RELEASE_19990228_A
+ *
+ * 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.
+ *
+ */
+
+#if !(defined(lint) || defined(__GNUC__))
+ static char sysparsehrcsid[] = "parsestreams.h,v 4.4 1998/06/14 21:09:32 kardel RELEASE_19990228_A";
+#endif
+
+#undef PARSEKERNEL
+#if defined(KERNEL) || defined(_KERNEL)
+#ifndef PARSESTREAM
+#define PARSESTREAM
+#endif
+#endif
+#if defined(PARSESTREAM) && defined(HAVE_SYS_STREAM_H)
+#define PARSEKERNEL
+
+#ifdef HAVE_SYS_TERMIOS_H
+#include <sys/termios.h>
+#endif
+
+#include <sys/ppsclock.h>
+
+#ifndef NTP_NEED_BOPS
+#define NTP_NEED_BOPS
+#endif
+
+#if defined(PARSESTREAM) && (defined(_sun) || defined(__sun)) && defined(HAVE_SYS_STREAM_H)
+/*
+ * Sorry, but in SunOS 4.x AND Solaris 2.x kernels there are no
+ * mem* operations. I don't want them - bcopy, bzero
+ * are fine in the kernel
+ */
+#undef HAVE_STRING_H /* don't include that at kernel level - prototype mismatch in Solaris 2.6 */
+#include "ntp_string.h"
+#else
+#include <stdio.h>
+#endif
+
+struct parsestream /* parse module local data */
+{
+ queue_t *parse_queue; /* read stream for this channel */
+ queue_t *parse_dqueue; /* driver queue entry (PPS support) */
+ unsigned long parse_status; /* operation flags */
+ void *parse_data; /* local data space (PPS support) */
+ parse_t parse_io; /* io structure */
+ struct ppsclockev parse_ppsclockev; /* copy of last pps event */
+};
+
+typedef struct parsestream parsestream_t;
+
+#define PARSE_ENABLE 0x0001
+
+/*--------------- debugging support ---------------------------------*/
+
+#define DD_OPEN 0x00000001
+#define DD_CLOSE 0x00000002
+#define DD_RPUT 0x00000004
+#define DD_WPUT 0x00000008
+#define DD_RSVC 0x00000010
+#define DD_PARSE 0x00000020
+#define DD_INSTALL 0x00000040
+#define DD_ISR 0x00000080
+#define DD_RAWDCF 0x00000100
+
+extern int parsedebug;
+
+#ifdef DEBUG_PARSE
+
+#define parseprintf(X, Y) if ((X) & parsedebug) printf Y
+
+#else
+
+#define parseprintf(X, Y)
+
+#endif
+#endif
+
+/*
+ * parsestreams.h,v
+ * Revision 4.4 1998/06/14 21:09:32 kardel
+ * Sun acc cleanup
+ *
+ * Revision 4.3 1998/06/13 18:14:32 kardel
+ * make mem*() to b*() mapping magic work on Solaris too
+ *
+ * Revision 4.2 1998/06/13 15:16:22 kardel
+ * fix mem*() to b*() function macro emulation
+ *
+ * Revision 4.1 1998/06/13 11:50:37 kardel
+ * STREAM macro gone in favor of HAVE_SYS_STREAM_H
+ *
+ * Revision 4.0 1998/04/10 19:51:30 kardel
+ * Start 4.0 release version numbering
+ *
+ * Revision 1.2 1998/04/10 19:27:42 kardel
+ * initial NTP VERSION 4 integration of PARSE with GPS166 binary support
+ *
+ */
diff --git a/kernel/sys/pcl720.h b/kernel/sys/pcl720.h
new file mode 100644
index 0000000..cf4eccd
--- /dev/null
+++ b/kernel/sys/pcl720.h
@@ -0,0 +1,95 @@
+/* Copyright (c) 1995 Vixie Enterprises
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Vixie Enterprises not be used in advertising or publicity
+ * pertaining to distribution of the document or software without specific,
+ * written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND VIXIE ENTERPRISES DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VIXIE ENTERPRISES
+ * BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#ifndef _PCL720_DEFINED
+#define _PCL720_DEFINED
+
+#define pcl720_data(base,bit) (base+(bit>>3))
+#define pcl720_data_0_7(base) (base+0)
+#define pcl720_data_8_15(base) (base+1)
+#define pcl720_data_16_23(base) (base+2)
+#define pcl720_data_24_31(base) (base+3)
+#define pcl720_cntr(base,cntr) (base+4+cntr) /* cntr: 0..2 */
+#define pcl720_cntr_0(base) (base+4)
+#define pcl720_cntr_1(base) (base+5)
+#define pcl720_cntr_2(base) (base+6)
+#define pcl720_ctrl(base) (base+7)
+
+#ifndef DEBUG_PCL720
+#define pcl720_inb(x) inb(x)
+#define pcl720_outb(x,y) outb(x,y)
+#else
+static unsigned char pcl720_inb(int addr) {
+ unsigned char x = inb(addr);
+ fprintf(DEBUG_PCL720, "inb(0x%x) -> 0x%x\n", addr, x);
+ return (x);
+}
+static void pcl720_outb(int addr, unsigned char x) {
+ outb(addr, x);
+ fprintf(DEBUG_PCL720, "outb(0x%x, 0x%x)\n", addr, x);
+}
+#endif
+
+#define pcl720_load(Base,Cntr,Mode,Val) \
+ ({ register unsigned int b = Base, c = Cntr, v = Val; \
+ i8253_ctrl ctrl; \
+ \
+ ctrl.s.bcd = i8253_binary; \
+ ctrl.s.mode = Mode; \
+ ctrl.s.rl = i8253_lmb; \
+ ctrl.s.cntr = c; \
+ pcl720_outb(pcl720_ctrl(b), ctrl.i); \
+ pcl720_outb(pcl720_cntr(b,c), v); \
+ pcl720_outb(pcl720_cntr(b,c), v >> 8); \
+ v; \
+ })
+
+#define pcl720_read(Base,Cntr) \
+ ({ register unsigned int b = Base, v; \
+ i8253_ctrl ctrl; \
+ \
+ ctrl.s.rl = i8253_latch; \
+ ctrl.s.cntr = i8253_cntr_0; \
+ pcl720_outb(pcl720_ctrl(b), ctrl.i); \
+ v = pcl720_inb(pcl720_cntr_0(b)); \
+ v |= (pcl720_inb(pcl720_cntr_0(b)) << 8); \
+ v; \
+ })
+
+#define pcl720_input(Base) \
+ ({ register unsigned int b = Base, v; \
+ \
+ v = pcl720_inb(pcl720_data_0_7(b)); \
+ v |= (pcl720_inb(pcl720_data_8_15(b)) << 8); \
+ v |= (pcl720_inb(pcl720_data_16_23(b)) << 16); \
+ v |= (pcl720_inb(pcl720_data_24_31(b)) << 24); \
+ v; \
+ })
+
+#define pcl720_output(Base,Value) \
+ ({ register unsigned int b = Base, v = Value; \
+ \
+ pcl720_outb(pcl720_data_0_7(b), v); \
+ pcl720_outb(pcl720_data_8_15(b), v << 8); \
+ pcl720_outb(pcl720_data_16_23(b), v << 16); \
+ pcl720_outb(pcl720_data_24_31(b), v << 24); \
+ v; \
+ })
+
+#endif /*_PCL720_DEFINED*/
diff --git a/kernel/sys/ppsclock.h b/kernel/sys/ppsclock.h
new file mode 100644
index 0000000..b0fe407
--- /dev/null
+++ b/kernel/sys/ppsclock.h
@@ -0,0 +1,64 @@
+/*
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66.
+ *
+ * Copyright (c) 1992 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ * 4. The name of the University may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef TIOCGPPSEV
+#define PPSCLOCKSTR "ppsclock"
+
+#ifndef HAVE_STRUCT_PPSCLOCKEV
+struct ppsclockev {
+ struct timeval tv;
+ u_int serial;
+};
+#endif
+
+#if defined(__STDC__) || defined(SYS_HPUX)
+#ifdef _IOR
+#define CIOGETEV _IOR('C', 0, struct ppsclockev) /* get last pps event */
+#else /* XXX SOLARIS is different */
+#define CIO ('C'<<8)
+#define CIOGETEV (CIO|0) /* get last pps event */
+#endif /* _IOR */
+#else /* __STDC__ */
+#ifdef _IOR
+#define CIOGETEV _IOR(C, 0, struct ppsclockev) /* get last pps event */
+#else /* XXX SOLARIS is different */
+#define CIO ('C'<<8)
+#define CIOGETEV (CIO|0) /* get last pps event */
+#endif /* _IOR */
+#endif /* __STDC__ */
+#else
+#define CIOGETEV TIOCGPPSEV
+#endif
diff --git a/kernel/sys/timex.h b/kernel/sys/timex.h
new file mode 100644
index 0000000..d42ec08
--- /dev/null
+++ b/kernel/sys/timex.h
@@ -0,0 +1,309 @@
+/******************************************************************************
+ * *
+ * Copyright (c) David L. Mills 1993, 1994 *
+ * *
+ * Permission to use, copy, modify, and distribute this software and its *
+ * documentation for any purpose and without fee is hereby granted, provided *
+ * that the above copyright notice appears in all copies and that both the *
+ * copyright notice and this permission notice appear in supporting *
+ * documentation, and that the name University of Delaware not be used in *
+ * advertising or publicity pertaining to distribution of the software *
+ * without specific, written prior permission. The University of Delaware *
+ * makes no representations about the suitability this software for any *
+ * purpose. It is provided "as is" without express or implied warranty. *
+ * *
+ ******************************************************************************/
+
+/*
+ * Modification history timex.h
+ *
+ * 26 Sep 94 David L. Mills
+ * Added defines for hybrid phase/frequency-lock loop.
+ *
+ * 19 Mar 94 David L. Mills
+ * Moved defines from kernel routines to header file and added new
+ * defines for PPS phase-lock loop.
+ *
+ * 20 Feb 94 David L. Mills
+ * Revised status codes and structures for external clock and PPS
+ * signal discipline.
+ *
+ * 28 Nov 93 David L. Mills
+ * Adjusted parameters to improve stability and increase poll
+ * interval.
+ *
+ * 17 Sep 93 David L. Mills
+ * Created file
+ */
+/*
+ * This header file defines the Network Time Protocol (NTP) interfaces
+ * for user and daemon application programs. These are implemented using
+ * private syscalls and data structures and require specific kernel
+ * support.
+ *
+ * NAME
+ * ntp_gettime - NTP user application interface
+ *
+ * SYNOPSIS
+ * #include <sys/timex.h>
+ *
+ * int syscall(SYS_ntp_gettime, tptr)
+ *
+ * int SYS_ntp_gettime defined in syscall.h header file
+ * struct ntptimeval *tptr pointer to ntptimeval structure
+ *
+ * NAME
+ * ntp_adjtime - NTP daemon application interface
+ *
+ * SYNOPSIS
+ * #include <sys/timex.h>
+ *
+ * int syscall(SYS_ntp_adjtime, mode, tptr)
+ *
+ * int SYS_ntp_adjtime defined in syscall.h header file
+ * struct timex *tptr pointer to timex structure
+ *
+ */
+#ifndef _SYS_TIMEX_H_
+#define _SYS_TIMEX_H_ 1
+
+#ifndef MSDOS /* Microsoft specific */
+#include <sys/syscall.h>
+#endif /* MSDOS */
+
+/*
+ * The following defines establish the engineering parameters of the
+ * phase-lock loop (PLL) model used in the kernel implementation. These
+ * parameters have been carefully chosen by analysis for good stability
+ * and wide dynamic range.
+ *
+ * The hz variable is defined in the kernel build environment. It
+ * establishes the timer interrupt frequency, 100 Hz for the SunOS
+ * kernel, 256 Hz for the Ultrix kernel and 1024 Hz for the OSF/1
+ * kernel. SHIFT_HZ expresses the same value as the nearest power of two
+ * in order to avoid hardware multiply operations.
+ *
+ * SHIFT_KG and SHIFT_KF establish the damping of the PLL and are chosen
+ * for a slightly underdamped convergence characteristic. SHIFT_KH
+ * establishes the damping of the FLL and is chosen by wisdom and black
+ * art.
+ *
+ * MAXTC establishes the maximum time constant of the PLL. With the
+ * SHIFT_KG and SHIFT_KF values given and a time constant range from
+ * zero to MAXTC, the PLL will converge in 15 minutes to 16 hours,
+ * respectively.
+ */
+#define SHIFT_HZ 7 /* log2(hz) */
+#define SHIFT_KG 6 /* phase factor (shift) */
+#define SHIFT_KF 16 /* PLL frequency factor (shift) */
+#define SHIFT_KH 2 /* FLL frequency factor (shift) */
+#define MAXTC 6 /* maximum time constant (shift) */
+
+/*
+ * The following defines establish the scaling of the various variables
+ * used by the PLL. They are chosen to allow the greatest precision
+ * possible without overflow of a 32-bit word.
+ *
+ * SHIFT_SCALE defines the scaling (shift) of the time_phase variable,
+ * which serves as a an extension to the low-order bits of the system
+ * clock variable time.tv_usec.
+ *
+ * SHIFT_UPDATE defines the scaling (shift) of the time_offset variable,
+ * which represents the current time offset with respect to standard
+ * time.
+ *
+ * SHIFT_USEC defines the scaling (shift) of the time_freq and
+ * time_tolerance variables, which represent the current frequency
+ * offset and maximum frequency tolerance.
+ *
+ * FINEUSEC is 1 us in SHIFT_UPDATE units of the time_phase variable.
+ */
+#define SHIFT_SCALE 22 /* phase scale (shift) */
+#define SHIFT_UPDATE (SHIFT_KG + MAXTC) /* time offset scale (shift) */
+#define SHIFT_USEC 16 /* frequency offset scale (shift) */
+#define FINEUSEC (1L << SHIFT_SCALE) /* 1 us in phase units */
+
+/*
+ * The following defines establish the performance envelope of the PLL.
+ * They insure it operates within predefined limits, in order to satisfy
+ * correctness assertions. An excursion which exceeds these bounds is
+ * clamped to the bound and operation proceeds accordingly. In practice,
+ * this can occur only if something has failed or is operating out of
+ * tolerance, but otherwise the PLL continues to operate in a stable
+ * mode.
+ *
+ * MAXPHASE must be set greater than or equal to CLOCK.MAX (128 ms), as
+ * defined in the NTP specification. CLOCK.MAX establishes the maximum
+ * time offset allowed before the system time is reset, rather than
+ * incrementally adjusted. Here, the maximum offset is clamped to
+ * MAXPHASE only in order to prevent overflow errors due to defective
+ * protocol implementations.
+ *
+ * MAXFREQ is the maximum frequency tolerance of the CPU clock
+ * oscillator plus the maximum slew rate allowed by the protocol. It
+ * should be set to at least the frequency tolerance of the oscillator
+ * plus 100 ppm for vernier frequency adjustments. If the kernel
+ * PPS discipline code is configured (PPS_SYNC), the oscillator time and
+ * frequency are disciplined to an external source, presumably with
+ * negligible time and frequency error relative to UTC, and MAXFREQ can
+ * be reduced.
+ *
+ * MAXTIME is the maximum jitter tolerance of the PPS signal if the
+ * kernel PPS discipline code is configured (PPS_SYNC).
+ *
+ * MINSEC and MAXSEC define the lower and upper bounds on the interval
+ * between protocol updates.
+ */
+#define MAXPHASE 512000L /* max phase error (us) */
+#ifdef PPS_SYNC
+#define MAXFREQ (512L << SHIFT_USEC) /* max freq error (100 ppm) */
+#define MAXTIME (200L << PPS_AVG) /* max PPS error (jitter) (200 us) */
+#else
+#define MAXFREQ (512L << SHIFT_USEC) /* max freq error (200 ppm) */
+#endif /* PPS_SYNC */
+#define MINSEC 16L /* min interval between updates (s) */
+#define MAXSEC 1200L /* max interval between updates (s) */
+
+#ifdef PPS_SYNC
+/*
+ * The following defines are used only if a pulse-per-second (PPS)
+ * signal is available and connected via a modem control lead, such as
+ * produced by the optional ppsclock feature incorporated in the Sun
+ * asynch driver. They establish the design parameters of the frequency-
+ * lock loop used to discipline the CPU clock oscillator to the PPS
+ * signal.
+ *
+ * PPS_AVG is the averaging factor for the frequency loop, as well as
+ * the time and frequency dispersion.
+ *
+ * PPS_SHIFT and PPS_SHIFTMAX specify the minimum and maximum
+ * calibration intervals, respectively, in seconds as a power of two.
+ *
+ * PPS_VALID is the maximum interval before the PPS signal is considered
+ * invalid and protocol updates used directly instead.
+ *
+ * MAXGLITCH is the maximum interval before a time offset of more than
+ * MAXTIME is believed.
+ */
+#define PPS_AVG 2 /* pps averaging constant (shift) */
+#define PPS_SHIFT 2 /* min interval duration (s) (shift) */
+#define PPS_SHIFTMAX 8 /* max interval duration (s) (shift) */
+#define PPS_VALID 120 /* pps signal watchdog max (s) */
+#define MAXGLITCH 30 /* pps signal glitch max (s) */
+#endif /* PPS_SYNC */
+
+/*
+ * The following defines and structures define the user interface for
+ * the ntp_gettime() and ntp_adjtime() system calls.
+ *
+ * Control mode codes (timex.modes)
+ */
+#define MOD_OFFSET 0x0001 /* set time offset */
+#define MOD_FREQUENCY 0x0002 /* set frequency offset */
+#define MOD_MAXERROR 0x0004 /* set maximum time error */
+#define MOD_ESTERROR 0x0008 /* set estimated time error */
+#define MOD_STATUS 0x0010 /* set clock status bits */
+#define MOD_TIMECONST 0x0020 /* set pll time constant */
+#define MOD_CANSCALE 0x0040 /* kernel can scale offset field */
+#define MOD_DOSCALE 0x0080 /* userland wants to scale offset field */
+
+/*
+ * Status codes (timex.status)
+ */
+#define STA_PLL 0x0001 /* enable PLL updates (rw) */
+#define STA_PPSFREQ 0x0002 /* enable PPS freq discipline (rw) */
+#define STA_PPSTIME 0x0004 /* enable PPS time discipline (rw) */
+#define STA_FLL 0x0008 /* select frequency-lock mode (rw) */
+
+#define STA_INS 0x0010 /* insert leap (rw) */
+#define STA_DEL 0x0020 /* delete leap (rw) */
+#define STA_UNSYNC 0x0040 /* clock unsynchronized (rw) */
+#define STA_FREQHOLD 0x0080 /* hold frequency (rw) */
+
+#define STA_PPSSIGNAL 0x0100 /* PPS signal present (ro) */
+#define STA_PPSJITTER 0x0200 /* PPS signal jitter exceeded (ro) */
+#define STA_PPSWANDER 0x0400 /* PPS signal wander exceeded (ro) */
+#define STA_PPSERROR 0x0800 /* PPS signal calibration error (ro) */
+
+#define STA_CLOCKERR 0x1000 /* clock hardware fault (ro) */
+
+#define STA_RONLY (STA_PPSSIGNAL | STA_PPSJITTER | STA_PPSWANDER | \
+ STA_PPSERROR | STA_CLOCKERR) /* read-only bits */
+
+/*
+ * Clock states (time_state)
+ */
+#define TIME_OK 0 /* no leap second warning */
+#define TIME_INS 1 /* insert leap second warning */
+#define TIME_DEL 2 /* delete leap second warning */
+#define TIME_OOP 3 /* leap second in progress */
+#define TIME_WAIT 4 /* leap second has occurred */
+#define TIME_ERROR 5 /* clock not synchronized */
+
+/*
+ * NTP user interface (ntp_gettime()) - used to read kernel clock values
+ *
+ * Note: maximum error = NTP synch distance = dispersion + delay / 2;
+ * estimated error = NTP dispersion.
+ */
+struct ntptimeval {
+ struct timeval time; /* current time (ro) */
+ long maxerror; /* maximum error (us) (ro) */
+ long esterror; /* estimated error (us) (ro) */
+};
+
+/*
+ * NTP daemon interface - (ntp_adjtime()) used to discipline CPU clock
+ * oscillator
+ */
+struct timex {
+ unsigned int modes; /* clock mode bits (wo) */
+ long offset; /* time offset (us) (rw) */
+ long freq; /* frequency offset (scaled ppm) (rw) */
+ long maxerror; /* maximum error (us) (rw) */
+ long esterror; /* estimated error (us) (rw) */
+ int status; /* clock status bits (rw) */
+ long constant; /* pll time constant (rw) */
+ long precision; /* clock precision (us) (ro) */
+ long tolerance; /* clock frequency tolerance (scaled
+ * ppm) (ro) */
+ /*
+ * The following read-only structure members are implemented
+ * only if the PPS signal discipline is configured in the
+ * kernel.
+ */
+ long ppsfreq; /* pps frequency (scaled ppm) (ro) */
+ long jitter; /* pps jitter (us) (ro) */
+ int shift; /* interval duration (s) (shift) (ro) */
+ long stabil; /* pps stability (scaled ppm) (ro) */
+ long jitcnt; /* jitter limit exceeded (ro) */
+ long calcnt; /* calibration intervals (ro) */
+ long errcnt; /* calibration errors (ro) */
+ long stbcnt; /* stability limit exceeded (ro) */
+
+};
+#ifdef __FreeBSD__
+
+/*
+ * sysctl identifiers underneath kern.ntp_pll
+ */
+#define NTP_PLL_GETTIME 1 /* used by ntp_gettime() */
+#define NTP_PLL_MAXID 2 /* number of valid ids */
+
+#define NTP_PLL_NAMES { \
+ { 0, 0 }, \
+ { "gettime", CTLTYPE_STRUCT }, \
+ }
+
+#ifndef KERNEL
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+extern int ntp_gettime __P((struct ntptimeval *));
+extern int ntp_adjtime __P((struct timex *));
+__END_DECLS
+
+#endif /* not KERNEL */
+
+#endif /* __FreeBSD__ */
+#endif /* _SYS_TIMEX_H_ */
diff --git a/kernel/sys/tpro.h b/kernel/sys/tpro.h
new file mode 100644
index 0000000..f276f81
--- /dev/null
+++ b/kernel/sys/tpro.h
@@ -0,0 +1,34 @@
+/*
+ * Structure for the KSI/Odetics TPRO-S data returned in reponse to a
+ * read() call. Note that these are driver-specific and not dependent on
+ * 32/64-bit architecture.
+ */
+struct tproval {
+ u_short day100; /* days * 100 */
+ u_short day10; /* days * 10 */
+ u_short day1; /* days * 1 */
+ u_short hour10; /* hours * 10 */
+ u_short hour1; /* hours * 1 */
+ u_short min10; /* minutes * 10 */
+ u_short min1; /* minutes * 1 */
+ u_short sec10; /* seconds * 10 */
+ u_short sec1; /* seconds * 1*/
+ u_short ms100; /* milliseconds * 100 */
+ u_short ms10; /* milliseconds * 10 */
+ u_short ms1; /* milliseconds * 1 */
+ u_short usec100; /* microseconds * 100 */
+ u_short usec10; /* microseconds * 10 */
+ u_short usec1; /* microseconds * 1 */
+ long tv_sec; /* seconds */
+ long tv_usec; /* microseconds */
+ u_short status; /* status register */
+};
+
+/*
+ * Status register bits
+ */
+#define TIMEAVAIL 0x0001 /* time available */
+#define NOSIGNAL 0x0002 /* insufficient IRIG-B signal */
+#define NOSYNC 0x0004 /* local oscillator not synchronized */
+
+/* end of tpro.h */
diff --git a/kernel/sys/tt560_api.h b/kernel/sys/tt560_api.h
new file mode 100644
index 0000000..c87a7b1
--- /dev/null
+++ b/kernel/sys/tt560_api.h
@@ -0,0 +1,489 @@
+/***********************************************************************
+ *
+ * Module: ttime_api.h
+ *
+ * Author: SIS 1998
+ * LM NE&SS 2001
+ *
+ * Description
+ *
+ * This header file contains data necessary for the API to the
+ * True Time board. This contains all of the structure definitions
+ * for the individual registers.
+ *
+ ***********************************************************************/
+#ifndef TTIME_API_H
+#define TTIME_API_H
+
+#ifdef CPP
+extern "C" {
+#endif
+
+#include <time.h>
+
+typedef struct
+{
+ unsigned int micro_sec;
+ unsigned int milli_sec;
+ struct tm gps_tm;
+} gps_time_t;
+
+typedef struct
+{
+ unsigned char reserved_1;
+ unsigned unit_ms : 4;
+ unsigned filler_0 : 4;
+ unsigned hun_ms : 4;
+ unsigned tens_ms : 4;
+ unsigned tens_sec : 4;
+ unsigned unit_sec : 4;
+
+ unsigned tens_min : 4;
+ unsigned unit_min : 4;
+ unsigned tens_hour : 4;
+ unsigned unit_hour : 4;
+ unsigned tens_day : 4;
+ unsigned unit_day : 4;
+ unsigned filler_1 : 4;
+ unsigned hun_day : 4;
+
+ unsigned tens_year : 4;
+ unsigned unit_year : 4;
+ unsigned thou_year : 4;
+ unsigned hun_year : 4;
+ unsigned char reserved_2[2];
+} preset_time_reg_t;
+
+typedef struct
+{
+ unsigned n_d0 : 2;
+ unsigned antenna_short_stat : 1; /* 0 = fault */
+ unsigned antenna_open_stat : 1; /* 0 = fault */
+ unsigned n_d1 : 1;
+ unsigned rate_gen_pulse_stat : 1;
+ unsigned time_cmp_pulse_stat : 1;
+ unsigned ext_event_stat : 1;
+
+} hw_stat_reg_t;
+
+typedef struct
+{
+ unsigned tens_us : 4;
+ unsigned unit_us : 4;
+ unsigned unit_ms : 4;
+ unsigned hun_us : 4;
+ unsigned char hw_stat; /* hw_stat_reg_t hw_stat; */
+ unsigned char reserved_3;
+
+ unsigned hun_ms : 4;
+ unsigned tens_ms : 4;
+ unsigned tens_sec : 4;
+ unsigned unit_sec : 4;
+ unsigned tens_min : 4;
+ unsigned unit_min : 4;
+ unsigned tens_hour : 4;
+ unsigned unit_hour : 4;
+
+ unsigned tens_day : 4;
+ unsigned unit_day : 4;
+ unsigned status : 4;
+ unsigned hun_day : 4;
+ unsigned tens_year : 4;
+ unsigned unit_year : 4;
+ unsigned thou_year : 4;
+ unsigned hun_year : 4;
+} time_freeze_reg_t;
+
+typedef struct
+{
+ unsigned char off_low;
+ unsigned char off_high;
+ unsigned char reserved_4[2];
+} sync_gen_off_reg_t;
+
+typedef struct
+{
+ unsigned tens_min : 4;
+ unsigned unit_min : 4;
+ unsigned tens_hour : 4;
+ unsigned unit_hour : 4;
+ unsigned char sign_ascii; /* '+' or '-' */
+ unsigned char reserved_5;
+} local_off_t;
+
+/*
+ * This structure can be used for both the position freeze
+ * and position preset registers.
+ */
+typedef struct
+{
+ unsigned lat_tens_degee : 4;
+ unsigned lat_unit_degee : 4;
+ unsigned filler_0 : 4;
+ unsigned lat_hun_degree : 4;
+ unsigned lat_tens_min : 4;
+ unsigned lat_unit_min : 4;
+ unsigned char lat_north_south; /* 'N' or 'S' */
+
+ unsigned filler_1 : 4;
+ unsigned lat_tenth_sec : 4;
+ unsigned lat_tens_sec : 4;
+ unsigned lat_unit_sec : 4;
+ unsigned long_tens_degree : 4;
+ unsigned long_unit_degree : 4;
+ unsigned filler_2 : 4;
+ unsigned long_hun_degree : 4;
+
+ unsigned long_tens_min : 4;
+ unsigned long_unit_min : 4;
+ unsigned char long_east_west; /* 'E' or 'W' */
+ unsigned filler_3 : 4;
+ unsigned long_tenth_sec : 4;
+ unsigned long_tens_sec : 4;
+ unsigned long_unit_sec : 4;
+
+ unsigned elv_tens_km : 4;
+ unsigned elv_unit_km : 4;
+ unsigned char elv_sign; /* '+' or '-' */
+ unsigned elv_unit_m : 4;
+ unsigned elv_tenth_m : 4;
+ unsigned elv_hun_m : 4;
+ unsigned elv_tens_m : 4;
+} pos_reg_t;
+
+typedef struct
+{
+ unsigned char prn1_tens_units;
+ unsigned char prn1_reserved;
+ unsigned char lvl1_tenths_hundredths;
+ unsigned char lvl1_tens_units;
+
+ unsigned char prn2_tens_units;
+ unsigned char prn2_reserved;
+ unsigned char lvl2_tenths_hundredths;
+ unsigned char lvl2_tens_units;
+
+ unsigned char prn3_tens_units;
+ unsigned char prn3_reserved;
+ unsigned char lvl3_tenths_hundredths;
+ unsigned char lvl3_tens_units;
+
+ unsigned char prn4_tens_units;
+ unsigned char prn4_reserved;
+ unsigned char lvl4_tenths_hundredths;
+ unsigned char lvl4_tens_units;
+
+ unsigned char prn5_tens_units;
+ unsigned char prn5_reserved;
+ unsigned char lvl5_tenths_hundredths;
+ unsigned char lvl5_tens_units;
+
+ unsigned char prn6_tens_units;
+ unsigned char prn6_reserved;
+ unsigned char lvl6_tenths_hundredths;
+ unsigned char lvl6_tens_units;
+
+ unsigned char flag;
+ unsigned char reserved[3];
+} sig_levels_t;
+
+typedef struct
+{
+ unsigned tens_us : 4;
+ unsigned unit_us : 4;
+ unsigned unit_ms : 4;
+ unsigned hun_us : 4;
+ unsigned hun_ms : 4;
+ unsigned tens_ms : 4;
+ unsigned tens_sec : 4;
+ unsigned unit_sec : 4;
+
+ unsigned tens_min : 4;
+ unsigned unit_min : 4;
+ unsigned tens_hour : 4;
+ unsigned unit_hour : 4;
+ unsigned tens_day : 4;
+ unsigned unit_day : 4;
+ unsigned stat : 4;
+ unsigned hun_day : 4;
+
+ unsigned tens_year : 4;
+ unsigned unit_year : 4;
+ unsigned thou_year : 4;
+ unsigned hun_year : 4;
+ unsigned char reserved_5[2];
+} ext_time_event_reg_t;
+
+typedef struct
+{
+ unsigned tens_us : 4;
+ unsigned unit_us : 4;
+ unsigned unit_ms : 4;
+ unsigned hun_us : 4;
+ unsigned hun_ms : 4;
+ unsigned tens_ms : 4;
+ unsigned tens_sec : 4;
+ unsigned unit_sec : 4;
+
+ unsigned tens_min : 4;
+ unsigned unit_min : 4;
+ unsigned tens_hour : 4;
+ unsigned unit_hour : 4;
+ unsigned tens_day : 4;
+ unsigned unit_day : 4;
+ unsigned mask : 4;
+ unsigned hun_day : 4;
+} time_cmp_reg_t;
+
+typedef struct
+{
+ unsigned char err_stat;
+ unsigned char no_def;
+ unsigned char oscillator_stat[2];
+} diag_reg_t;
+
+typedef struct
+{
+ unsigned res :2;
+ unsigned rate_int_mask :1;
+ unsigned cmp_int_mask :1;
+ unsigned ext_int_mask :1;
+ unsigned rate_stat_clr :1;
+ unsigned cmp_stat_clr :1;
+ unsigned ext_stat_clr :1;
+ unsigned char reserved[3];
+} hw_ctl_reg_t;
+
+typedef struct
+{
+ unsigned preset_pos_rdy :1;
+ unsigned sel_pps_ref :1;
+ unsigned sel_gps_ref :1;
+ unsigned sel_time_code :1;
+ unsigned gen_stp_run :1;
+ unsigned preset_time_rdy :1;
+ unsigned dst :1;
+ unsigned mode_sel :1;
+
+ unsigned ctl_am_dc :1;
+ unsigned reserved :3;
+ unsigned input_code :4;
+
+ unsigned char rate_reserved;
+
+ unsigned rate_flag :4;
+ unsigned rate_reserved1 :4;
+} conf_reg_t;
+
+typedef struct
+{
+ unsigned char mem_reserved[0xf8];
+
+ hw_ctl_reg_t hw_ctl_reg;
+
+ time_freeze_reg_t time_freeze_reg;
+
+ pos_reg_t pos_freeze_reg;
+
+ conf_reg_t conf_reg;
+
+ diag_reg_t diag_reg;
+
+ local_off_t local_offset;
+
+ sync_gen_off_reg_t sync_gen_offset;
+
+ unsigned char reserved[4];
+
+ unsigned char config_reg2_ctl;
+
+ unsigned char reserved2[11];
+
+ time_cmp_reg_t time_compare_reg;
+
+ unsigned char reserved3[24];
+
+ preset_time_reg_t preset_time_reg;
+
+ pos_reg_t preset_pos_reg;
+
+ ext_time_event_reg_t extern_time_event_reg;
+
+ unsigned char reserved4[24];
+
+ sig_levels_t signal_levels_reg;
+
+ unsigned char reserved5[12];
+} tt_mem_space_t;
+
+#define TTIME_MEMORY_SIZE 0x200
+
+/*
+ * Defines for register offsets
+ */
+#define HW_CTL_REG 0x0f8
+#define TIME_FREEZE_REG 0x0fc
+#define HW_STAT_REG 0x0fe
+#define POS_FREEZE_REG 0x108
+#define CONFIG_REG_1 0x118
+#define DIAG_REG 0x11c
+#define LOCAL_OFF_REG 0x120
+#define SYNC_GEN_OFF_REG 0x124
+#define CONFIG_REG_2 0x12c
+#define TIME_CMP_REG 0x138
+#define PRESET_TIME_REG 0x158
+#define PRESET_POS_REG 0x164
+#define EXT_EVENT_REG 0x174
+#define SIG_LVL_PRN1 0x198
+#define SIG_LVL_PRN2 0x19c
+#define SIG_LVL_PRN3 0x1a0
+#define SIG_LVL_PRN4 0x1a4
+#define SIG_LVL_PRN5 0x1a8
+#define SIG_LVL_PRN6 0x1ac
+#define SIG_LVL_FLAG 0x1b0
+
+/*
+ * Defines for accessing the hardware status register.
+ */
+#define HW_STAT_ANTENNA_SHORT 0 /* access the antenna short bit */
+#define HW_STAT_ANTENNA_OPEN 1 /* access the antenna open bit */
+#define HW_STAT_RATE_GEN_PULSE_STAT 2 /* access the rate gen pulse bit */
+#define HW_STAT_TIME_CMP_PULSE_STAT 3 /* access the time cmp bit */
+#define HW_STAT_EXT_EVENT_STAT 4 /* access the external event bit */
+
+/*
+ * Defines for accessing the hardware control register
+ */
+
+#define HW_CTL_RATE_INT_MASK 0 /* access rate generator int mask */
+#define HW_CTL_CMP_INT_MASK 1 /* access compare interrupt mask */
+#define HW_CTL_EXT_INT_MASK 2 /* access external event interrupt mask */
+#define HW_CTL_RATE_GEN_INT_CLEAR 3 /* access rate gen. interrupt clear field */
+#define HW_CTL_TIME_CMP_INT_CLEAR 4 /* access time cmp interrupt clear field */
+#define HW_CTL_EXT_EVENT_INT_CLEAR 5 /* access external event int clear field */
+
+/*
+ * Defines for configuration register bit fields.
+ */
+#define PRESET_POS_RDY_BIT 0 /* access the preset pos. rdy. bit */
+#define SEL_1_PPS_REF_BIT 1 /* access the select 1 pps reference bit */
+#define SEL_GPS_REF_BIT 2 /* access the select gps reference bit */
+#define SEL_TIME_CODE_REF_BIT 3 /* access the select time code reference bit */
+#define GEN_STOP_BIT 4 /* access the generator start/stop bit */
+#define PRESET_TIME_RDY_BIT 5 /* access the preset time ready bit */
+#define DST_BIT 6 /* access the DST bit */
+#define MODE_SEL_BIT 7 /* access the mode select bit */
+#define AM_DC_BIT 8 /* access the code bits AM/DC bit */
+#define IN_CODE_SEL_BIT 9 /* access the input code select bit */
+#define FLAG_BIT 10 /* access the flag bit */
+
+/*
+ * The following defines are used to set modes in the
+ * configuration register.
+ */
+
+#define CONF_SET_AM 0 /* Set code to AM */
+#define CONF_SET_DC 1 /* Set code to DC */
+#define CONF_SET_IRIG_B 0 /* Set code IRIG B */
+#define CONF_SET_IRIG_A 1 /* Set code IRIG A */
+
+#define CONF_FLAG_DISABLE 0 /* Disable pulse */
+#define CONF_FLAG_10K_PPS 1 /* Set rate to 10k PPS */
+#define CONF_FLAG_1K_PPS 2 /* Set rate to 1k PPS */
+#define CONF_FLAG_100_PPS 3 /* Set rate to 100 PPS */
+#define CONF_FLAG_10_PPS 4 /* Set rate to 10 PPS */
+#define CONF_FLAG_1_PPS 5 /* Set rate to 1 PPS */
+
+/*
+ * Defines for read commands
+ */
+
+#define TT_RD_FREEZE_REG 0x01
+#define TT_RD_HW_CTL_REG 0x02
+#define TT_RD_CNFG_REG 0x03
+#define TT_RD_DIAG_REG 0x04
+#define TT_RD_LCL_OFFSET 0x05
+#define TT_RD_SYNC_GEN_OFF 0x06
+#define TT_RD_CNFG_REG_2 0x07
+#define TT_RD_TIME_CMP_REG 0x08
+#define TT_RD_PRESET_REG 0x09
+#define TT_RD_EXT_EVNT_REG 0x0a
+#define TT_RD_SIG_LVL_REG 0x0b
+
+/*
+ * Defines for write commands
+ */
+#define TT_WRT_FREEZE_REG 0x0c
+#define TT_WRT_HW_CTL_REG 0x0d
+#define TT_WRT_CNFG_REG 0x0e
+#define TT_WRT_DIAG_REG 0x0f
+#define TT_WRT_LCL_OFFSET 0x10
+#define TT_WRT_SYNC_GEN_OFF 0x11
+#define TT_WRT_CNFG_REG_2 0x12
+#define TT_WRT_TIME_CMP_REG 0x13
+#define TT_WRT_PRESET_REG 0x14
+#define TT_WRT_EXT_EVNT_REG 0x15
+#define TT_WRT_SIG_LVL_REG 0x16
+
+/*
+ * Define the length of the buffers to move (in 32 bit words).
+ */
+
+#define HW_CTL_REG_LEN 1
+#define CNFG_REG_1_LEN 1
+#define DIAG_REG_LEN 1
+#define LCL_OFFSET_LEN 1
+#define SYNC_GEN_OFF_LEN 1
+#define CNFG_REG_2_LEN 1
+
+#define TIME_CMP_REG_LEN 2
+#define PRESET_TIME_REG_LEN 3
+#define PRESET_POS_REG_LEN 4
+#define PRESET_REG_LEN (PRESET_TIME_REG_LEN+PRESET_POS_REG_LEN)
+#define TIME_FREEZE_REG_LEN 3
+#define POSN_FREEZE_REG_LEN 4
+#define FREEZE_REG_LEN (TIME_FREEZE_REG_LEN+POSN_FREEZE_REG_LEN)
+#define EXT_EVNT_REG_LEN 3
+#define SIG_LVL_REG_LEN 7
+#define GPS_TIME_LEN 7
+
+/*
+ * Define BCD - INT - BCD macros.
+ */
+
+#define BCDTOI(a) ( ( ( ( (a) & 0xf0 ) >> 4 ) * 10 ) + ( (a) & 0x0f ) )
+#define ITOBCD(a) ( ( ( ( (a) ) / 10) << 4 ) + ( ( (a) ) % 10) )
+#define LTOBCD(a) ( ( ( ( (uint64_t)(a) ) / 10) << 4 ) + ( ( (uint64_t)(a) ) % 10) )
+
+extern int init_560 ( );
+extern void close_560 ( );
+extern int write_hw_ctl_reg (hw_ctl_reg_t *);
+extern int write_hw_ctl_reg_bitfield (int, int );
+extern int read_conf_reg (conf_reg_t *);
+extern int read_conf_reg_bitfield (int );
+extern int write_conf_reg (conf_reg_t *);
+extern int write_conf_reg_bitfield (int, unsigned char );
+extern int read_hw_stat_reg_bitfield (int );
+extern int read_local_offset_reg (local_off_t *);
+extern int write_local_offset_reg (local_off_t *);
+extern int read_sync_offset_reg (sync_gen_off_reg_t *);
+extern int write_sync_offset_reg (sync_gen_off_reg_t *);
+extern int read_time_cmp_reg (time_cmp_reg_t *);
+extern int write_time_cmp_reg (time_cmp_reg_t *);
+extern int read_preset_time_reg (preset_time_reg_t *);
+extern int write_preset_time_reg (preset_time_reg_t *);
+extern int reset_time ( );
+extern int set_new_time (preset_time_reg_t *);
+extern int read_preset_position_reg (pos_reg_t *);
+extern int write_preset_position_reg (pos_reg_t *);
+extern int read_external_event_reg (ext_time_event_reg_t *);
+extern int read_signal_level_reg (sig_levels_t *);
+extern int freeze_time ( );
+extern int snapshot_time (time_freeze_reg_t *);
+extern int read_position_freeze_reg (pos_reg_t *);
+extern int read_diag_reg (diag_reg_t *);
+
+#ifdef CPP
+}
+#endif
+#endif
diff --git a/kernel/tty_chu.c b/kernel/tty_chu.c
new file mode 100644
index 0000000..4615875
--- /dev/null
+++ b/kernel/tty_chu.c
@@ -0,0 +1,276 @@
+/* tty_chu.c,v 3.1 1993/07/06 01:07:30 jbj Exp
+ * tty_chu.c - CHU line driver
+ */
+
+#include "chu.h"
+#if NCHU > 0
+
+#include "../h/param.h"
+#include "../h/types.h"
+#include "../h/systm.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/ioctl.h"
+#include "../h/tty.h"
+#include "../h/proc.h"
+#include "../h/file.h"
+#include "../h/conf.h"
+#include "../h/buf.h"
+#include "../h/uio.h"
+
+#include "../h/chudefs.h"
+
+/*
+ * Line discipline for receiving CHU time codes.
+ * Does elementary noise elimination, takes time stamps after
+ * the arrival of each character, returns a buffer full of the
+ * received 10 character code and the associated time stamps.
+ */
+#define NUMCHUBUFS 3
+
+struct chudata {
+ u_char used; /* Set to 1 when structure in use */
+ u_char lastindex; /* least recently used buffer */
+ u_char curindex; /* buffer to use */
+ u_char sleeping; /* set to 1 when we're sleeping on a buffer */
+ struct chucode chubuf[NUMCHUBUFS];
+} chu_data[NCHU];
+
+/*
+ * Number of microseconds we allow between
+ * character arrivals. The speed is 300 baud
+ * so this should be somewhat more than 30 msec
+ */
+#define CHUMAXUSEC (50*1000) /* 50 msec */
+
+int chu_debug = 0;
+
+/*
+ * Open as CHU time discipline. Called when discipline changed
+ * with ioctl, and changes the interpretation of the information
+ * in the tty structure.
+ */
+/*ARGSUSED*/
+chuopen(dev, tp)
+ dev_t dev;
+ register struct tty *tp;
+{
+ register struct chudata *chu;
+
+ /*
+ * Don't allow multiple opens. This will also protect us
+ * from someone opening /dev/tty
+ */
+ if (tp->t_line == CHULDISC)
+ return (EBUSY);
+ ttywflush(tp);
+ for (chu = chu_data; chu < &chu_data[NCHU]; chu++)
+ if (!chu->used)
+ break;
+ if (chu >= &chu[NCHU])
+ return (EBUSY);
+ chu->used++;
+ chu->lastindex = chu->curindex = 0;
+ chu->sleeping = 0;
+ chu->chubuf[0].ncodechars = 0;
+ tp->T_LINEP = (caddr_t) chu;
+ return (0);
+}
+
+/*
+ * Break down... called when discipline changed or from device
+ * close routine.
+ */
+chuclose(tp)
+ register struct tty *tp;
+{
+ register int s = spl5();
+
+ ((struct chudata *) tp->T_LINEP)->used = 0;
+ tp->t_cp = 0;
+ tp->t_inbuf = 0;
+ tp->t_rawq.c_cc = 0; /* clear queues -- paranoid */
+ tp->t_canq.c_cc = 0;
+ tp->t_line = 0; /* paranoid: avoid races */
+ splx(s);
+}
+
+/*
+ * Read a CHU buffer. Sleep on the current buffer
+ */
+churead(tp, uio)
+ register struct tty *tp;
+ struct uio *uio;
+{
+ register struct chudata *chu;
+ register struct chucode *chucode;
+ register int s;
+
+ if ((tp->t_state&TS_CARR_ON)==0)
+ return (EIO);
+
+ chu = (struct chudata *) (tp->T_LINEP);
+
+ s = spl5();
+ chucode = &(chu->chubuf[chu->lastindex]);
+ while (chu->curindex == chu->lastindex) {
+ chu->sleeping = 1;
+ sleep((caddr_t)chucode, TTIPRI);
+ }
+ chu->sleeping = 0;
+ if (++(chu->lastindex) >= NUMCHUBUFS)
+ chu->lastindex = 0;
+ splx(s);
+
+ return (uiomove((caddr_t)chucode, sizeof(*chucode), UIO_READ, uio));
+}
+
+/*
+ * Low level character input routine.
+ * If the character looks okay, grab a time stamp. If the stuff in
+ * the buffer is too old, dump it and start fresh. If the character is
+ * non-BCDish, everything in the buffer too.
+ */
+chuinput(c, tp)
+ register int c;
+ register struct tty *tp;
+{
+ register struct chudata *chu = (struct chudata *) tp->T_LINEP;
+ register struct chucode *chuc;
+ register int i;
+ long sec, usec;
+ struct timeval tv;
+
+ /*
+ * Do a check on the BSDness of the character. This delays
+ * the time stamp a bit but saves a fair amount of overhead
+ * when the static is bad.
+ */
+ if (((c) & 0xf) > 9 || (((c)>>4) & 0xf) > 9) {
+ chuc = &(chu->chubuf[chu->curindex]);
+ chuc->ncodechars = 0; /* blow all previous away */
+ return;
+ }
+
+ /*
+ * Call microtime() to get the current time of day
+ */
+ microtime(&tv);
+
+ /*
+ * Compute the difference in this character's time stamp
+ * and the last. If it exceeds the margin, blow away all
+ * the characters currently in the buffer.
+ */
+ chuc = &(chu->chubuf[chu->curindex]);
+ i = (int)chuc->ncodechars;
+ if (i > 0) {
+ sec = tv.tv_sec - chuc->codetimes[i-1].tv_sec;
+ usec = tv.tv_usec - chuc->codetimes[i-1].tv_usec;
+ if (usec < 0) {
+ sec -= 1;
+ usec += 1000000;
+ }
+ if (sec != 0 || usec > CHUMAXUSEC) {
+ i = 0;
+ chuc->ncodechars = 0;
+ }
+ }
+
+ /*
+ * Store the character. If we're done, have to tell someone
+ */
+ chuc->codechars[i] = (u_char)c;
+ chuc->codetimes[i] = tv;
+
+ if (++i < NCHUCHARS) {
+ /*
+ * Not much to do here. Save the count and wait
+ * for another character.
+ */
+ chuc->ncodechars = (u_char)i;
+ } else {
+ /*
+ * Mark this buffer full and point at next. If the
+ * next buffer is full we overwrite it by bumping the
+ * next pointer.
+ */
+ chuc->ncodechars = NCHUCHARS;
+ if (++(chu->curindex) >= NUMCHUBUFS)
+ chu->curindex = 0;
+ if (chu->curindex == chu->lastindex)
+ if (++(chu->lastindex) >= NUMCHUBUFS)
+ chu->lastindex = 0;
+ chu->chubuf[chu->curindex].ncodechars = 0;
+
+ /*
+ * Wake up anyone sleeping on this. Also wake up
+ * selectors and/or deliver a SIGIO as required.
+ */
+ if (tp->t_rsel) {
+ selwakeup(tp->t_rsel, tp->t_state&TS_RCOLL);
+ tp->t_state &= ~TS_RCOLL;
+ tp->t_rsel = 0;
+ }
+ if (tp->t_state & TS_ASYNC)
+ gsignal(tp->t_pgrp, SIGIO);
+ if (chu->sleeping)
+ (void) wakeup((caddr_t)chuc);
+ }
+}
+
+/*
+ * Handle ioctls. We reject all tty-style except those that
+ * change the line discipline.
+ */
+chuioctl(tp, cmd, data, flag)
+ struct tty *tp;
+ int cmd;
+ caddr_t data;
+ int flag;
+{
+
+ if ((cmd>>8) != 't')
+ return (-1);
+ switch (cmd) {
+ case TIOCSETD:
+ case TIOCGETD:
+ case TIOCGETP:
+ case TIOCGETC:
+ return (-1);
+ }
+ return (ENOTTY); /* not quite appropriate */
+}
+
+
+chuselect(dev, rw)
+ dev_t dev;
+ int rw;
+{
+ register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)];
+ struct chudata *chu;
+ int s = spl5();
+
+ chu = (struct chudata *) (tp->T_LINEP);
+
+ switch (rw) {
+
+ case FREAD:
+ if (chu->curindex != chu->lastindex)
+ goto win;
+ if (tp->t_rsel && tp->t_rsel->p_wchan == (caddr_t)&selwait)
+ tp->t_state |= TS_RCOLL;
+ else
+ tp->t_rsel = u.u_procp;
+ break;
+
+ case FWRITE:
+ goto win;
+ }
+ splx(s);
+ return (0);
+win:
+ splx(s);
+ return (1);
+}
+#endif NCHU
diff --git a/kernel/tty_chu_STREAMS.c b/kernel/tty_chu_STREAMS.c
new file mode 100644
index 0000000..f46e25d
--- /dev/null
+++ b/kernel/tty_chu_STREAMS.c
@@ -0,0 +1,603 @@
+/*
+ * CHU STREAMS module for SunOS
+ *
+ * Version 2.6
+ *
+ * Copyright 1991-1994, Nick Sayer
+ *
+ * Special thanks to Greg Onufer for his debug assists.
+ * Special thanks to Matthias Urlichs for the 4.1.x loadable driver support
+ * code.
+ * Special wet-noodle whippings to Sun for not properly documenting
+ * ANYTHING that makes this stuff at all possible.
+ *
+ * Should be PUSHed directly on top of a serial I/O channel.
+ * Provides complete chucode structures to user space.
+ *
+ * COMPILATION:
+ *
+ *
+ * To make a SunOS 4.1.x compatable loadable module (from the ntp kernel
+ * directory):
+ *
+ * % cc -c -I../include -DLOADABLE tty_chu_STREAMS.c
+ *
+ * The resulting .o file is the loadable module. Modload it
+ * thusly:
+ *
+ * % modload tty_chu_STREAMS.o -entry _chuinit
+ *
+ * When none of the instances are pushed in a STREAM, you can
+ * modunload the driver in the usual manner if you wish.
+ *
+ * As an alternative to loading it dynamically you can compile it
+ * directly into the kernel by hacking str_conf.c. See the README
+ * file for more details on doing it the old fashioned way.
+ *
+ *
+ * To make a Solaris 2.x compatable module (from the ntp kernel
+ * directory):
+ *
+ * % {gcc,cc} -c -I../include -DSOLARIS2 tty_chu_STREAMS.c
+ * % ld -r -o /usr/kernel/strmod/chu tty_chu_STREAMS.o
+ * % chmod 755 /usr/kernel/strmod/chu
+ *
+ * The OS will load it for you automagically when it is first pushed.
+ *
+ * If you get syntax errors from <sys/timer.h> (really references
+ * to types that weren't typedef'd in gcc's version of types.h),
+ * add -D_SYS_TIMER_H to blot out the miscreants.
+ *
+ * Under Solaris 2.2 and previous, do not attempt to modunload the
+ * module unless you're SURE it's not in use. I haven't tried it, but
+ * I've been told it won't do the right thing. Under Solaris 2.3 (and
+ * presumably future revs) an attempt to unload the module when it's in
+ * use will properly refuse with a "busy" message.
+ *
+ *
+ * HISTORY:
+ *
+ * v2.6 - Mutexed the per-instance chucode just to be safe.
+ * v2.5 - Fixed show-stopper bug in Solaris 2.x - qprocson().
+ * v2.4 - Added dynamic allocation support for Solaris 2.x.
+ * v2.3 - Added support for Solaris 2.x.
+ * v2.2 - Added SERVICE IMMEDIATE hack.
+ * v2.1 - Added 'sixth byte' heuristics.
+ * v2.0 - first version with an actual version number.
+ * Added support for new CHU 'second 31' data format.
+ * Deleted PEDANTIC and ANAL_RETENTIVE.
+ *
+ */
+
+#ifdef SOLARIS2
+# ifndef NCHU
+# define NCHU 1
+# endif
+# define _KERNEL
+#elif defined(LOADABLE)
+# ifndef NCHU
+# define NCHU 3
+# define KERNEL
+# endif
+#else
+# include "chu.h"
+#endif
+
+#if NCHU > 0
+
+/*
+ * Number of microseconds we allow between
+ * character arrivals. The speed is 300 baud
+ * so this should be somewhat more than 30 msec
+ */
+#define CHUMAXUSEC (60*1000) /* 60 msec */
+
+#include <sys/types.h>
+#include <sys/stream.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/errno.h>
+#include <sys/user.h>
+#include <syslog.h>
+#include <sys/tty.h>
+
+#include <sys/chudefs.h>
+
+#ifdef SOLARIS2
+
+#include <sys/ksynch.h>
+#include <sys/kmem.h>
+#include <sys/cmn_err.h>
+#include <sys/conf.h>
+#include <sys/strtty.h>
+#include <sys/modctl.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+
+#endif
+
+#ifdef LOADABLE
+
+#include <sys/kernel.h>
+#include <sys/conf.h>
+#include <sys/buf.h>
+#include <sundev/mbvar.h>
+#include <sun/autoconf.h>
+#include <sun/vddrv.h>
+
+#endif
+
+
+static struct module_info rminfo = { 0, "chu", 0, INFPSZ, 0, 0 };
+static struct module_info wminfo = { 0, "chu", 0, INFPSZ, 0, 0 };
+static int chuopen(), churput(), chuwput(), chuclose();
+
+static struct qinit rinit = { churput, NULL, chuopen, chuclose, NULL,
+ &rminfo, NULL };
+
+static struct qinit winit = { chuwput, NULL, NULL, NULL, NULL,
+ &wminfo, NULL };
+
+struct streamtab chuinfo = { &rinit, &winit, NULL, NULL };
+
+/*
+ * Here's our private data type and structs
+ */
+struct priv_data
+{
+#ifdef SOLARIS2
+ kmutex_t chucode_mutex;
+#else
+ char in_use;
+#endif
+ struct chucode chu_struct;
+};
+
+#ifndef SOLARIS2
+struct priv_data our_priv_data[NCHU];
+#endif
+
+#ifdef SOLARIS2
+
+static struct fmodsw fsw =
+{
+ "chu",
+ &chuinfo,
+ D_NEW | D_MP
+};
+
+extern struct mod_ops mod_strmodops;
+
+static struct modlstrmod modlstrmod =
+{
+ &mod_strmodops,
+ "CHU timecode decoder v2.6",
+ &fsw
+};
+
+static struct modlinkage modlinkage =
+{
+ MODREV_1,
+ (void*) &modlstrmod,
+ NULL
+};
+
+int _init()
+{
+ return mod_install(&modlinkage);
+}
+
+int _info(foo)
+struct modinfo *foo;
+{
+ return mod_info(&modlinkage,foo);
+}
+
+int _fini()
+{
+ return mod_remove(&modlinkage);
+}
+
+#endif /* SOLARIS2 */
+
+#ifdef LOADABLE
+
+# ifdef sun
+
+static struct vdldrv vd =
+{
+ VDMAGIC_PSEUDO,
+ "chu",
+ NULL, NULL, NULL, 0, 0, NULL, NULL, 0, 0,
+};
+
+static struct fmodsw *chu_fmod;
+
+/*ARGSUSED*/
+chuinit (fc, vdp, vdi, vds)
+ unsigned int fc;
+ struct vddrv *vdp;
+ addr_t vdi;
+ struct vdstat *vds;
+{
+ switch (fc) {
+ case VDLOAD:
+ {
+ int dev, i;
+
+ /* Find free entry in fmodsw */
+ for (dev = 0; dev < fmodcnt; dev++) {
+ if (fmodsw[dev].f_str == NULL)
+ break;
+ }
+ if (dev == fmodcnt)
+ return (ENODEV);
+ chu_fmod = &fmodsw[dev];
+
+ /* If you think a kernel would have strcpy() you're mistaken. */
+ for (i = 0; i <= FMNAMESZ; i++)
+ chu_fmod->f_name[i] = wminfo.mi_idname[i];
+
+ chu_fmod->f_str = &chuinfo;
+ }
+ vdp->vdd_vdtab = (struct vdlinkage *) & vd;
+
+ {
+ int i;
+
+ for (i=0; i<NCHU; i++)
+ our_priv_data[i].in_use=0;
+ }
+
+ return 0;
+ case VDUNLOAD:
+ {
+ int dev;
+
+ for (dev = 0; dev < NCHU; dev++)
+ if (our_priv_data[dev].in_use) {
+ /* One of the modules is still open */
+ return (EBUSY);
+ }
+ }
+ chu_fmod->f_name[0] = '\0';
+ chu_fmod->f_str = NULL;
+ return 0;
+ case VDSTAT:
+ return 0;
+ default:
+ return EIO;
+ }
+}
+
+# endif /* sun */
+
+#endif /* LOADABLE */
+
+#if !defined(LOADABLE) && !defined(SOLARIS2)
+
+char chu_first_open=1;
+
+#endif
+
+/*ARGSUSED*/
+static int chuopen(q, dev, flag, sflag)
+queue_t *q;
+dev_t dev;
+int flag;
+int sflag;
+{
+ int i;
+
+#if !defined(LOADABLE) && !defined(SOLARIS2)
+ if (chu_first_open)
+ {
+ chu_first_open=0;
+
+ for(i=0;i<NCHU;i++)
+ our_priv_data[i].in_use=0;
+ }
+#endif
+
+#ifdef SOLARIS2
+ /* According to the docs, calling with KM_SLEEP can never
+ fail */
+
+ q->q_ptr = kmem_alloc( sizeof(struct priv_data), KM_SLEEP );
+ ((struct priv_data *) q->q_ptr)->chu_struct.ncodechars = 0;
+
+ mutex_init(&((struct priv_data *) q->q_ptr)->chucode_mutex,"Chucode Mutex",MUTEX_DRIVER,NULL);
+ qprocson(q);
+
+ if (!putnextctl1(WR(q), M_CTL, MC_SERVICEIMM))
+ {
+ qprocsoff(q);
+ mutex_destroy(&((struct priv_data *)q->q_ptr)->chucode_mutex);
+ kmem_free(q->q_ptr, sizeof(struct chucode) );
+ return (EFAULT);
+ }
+
+ return 0;
+
+#else
+ for(i=0;i<NCHU;i++)
+ if (!our_priv_data[i].in_use)
+ {
+ ((struct priv_data *) (q->q_ptr))=&(our_priv_data[i]);
+ our_priv_data[i].in_use++;
+ our_priv_data[i].chu_struct.ncodechars = 0;
+ if (!putctl1(WR(q)->q_next, M_CTL, MC_SERVICEIMM))
+ {
+ our_priv_data[i].in_use=0;
+ u.u_error = EFAULT;
+ return (OPENFAIL);
+ }
+ return 0;
+ }
+
+ u.u_error = EBUSY;
+ return (OPENFAIL);
+#endif
+
+}
+
+/*ARGSUSED*/
+static int chuclose(q, flag)
+queue_t *q;
+int flag;
+{
+#ifdef SOLARIS2
+ qprocsoff(q);
+ mutex_destroy(&((struct priv_data *)q->q_ptr)->chucode_mutex);
+ kmem_free(q->q_ptr, sizeof(struct chucode) );
+#else
+ ((struct priv_data *) (q->q_ptr))->in_use=0;
+#endif
+ return (0);
+}
+
+/*
+ * Now the crux of the biscuit.
+ *
+ * We will be passed data from the man downstairs. If it's not a data
+ * packet, it must be important, so pass it along unmunged. If, however,
+ * it is a data packet, we're gonna do special stuff to it. We're going
+ * to pass each character we get to the old line discipline code we
+ * include below for just such an occasion. When the old ldisc code
+ * gets a full chucode struct, we'll hand it back upstairs.
+ *
+ * chuinput takes a single character and q (as quickly as possible).
+ * passback takes a pointer to a chucode struct and q and sends it upstream.
+ */
+
+void chuinput();
+void passback();
+
+static int churput(q, mp)
+queue_t *q;
+mblk_t *mp;
+{
+ mblk_t *bp;
+
+ switch(mp->b_datap->db_type)
+ {
+ case M_DATA:
+ for(bp=mp; bp!=NULL; bp=bp->b_cont)
+ {
+ while(bp->b_rptr < bp->b_wptr)
+ chuinput( ((u_char)*(bp->b_rptr++)) , q );
+ }
+ freemsg(mp);
+ break;
+ default:
+ putnext(q,mp);
+ break;
+ }
+
+}
+
+/*
+ * Writing to a chu device doesn't make sense, but we'll pass them
+ * through in case they're important.
+ */
+
+static int chuwput(q, mp)
+queue_t *q;
+mblk_t *mp;
+{
+ putnext(q,mp);
+}
+
+/*
+ * Take a pointer to a filled chucode struct and a queue and
+ * send the chucode stuff upstream
+ */
+
+void passback(outdata,q)
+struct chucode *outdata;
+queue_t *q;
+{
+ mblk_t *mp;
+ int j;
+
+ mp=(mblk_t*) allocb(sizeof(struct chucode),BPRI_LO);
+
+ if (mp==NULL)
+ {
+#ifdef SOLARIS2
+ cmn_err(CE_WARN,"chu module couldn't allocate message block");
+#else
+ log(LOG_ERR,"chu: cannot allocate message");
+#endif
+ return;
+ }
+
+ for(j=0;j<sizeof(struct chucode); j++)
+ *mp->b_wptr++ = *( ((char*)outdata) + j );
+
+ putnext(q,mp);
+}
+
+/*
+ * This routine was copied nearly verbatim from the old line discipline.
+ */
+void chuinput(c,q)
+register u_char c;
+queue_t *q;
+{
+ register struct chucode *chuc;
+ register int i;
+ long sec, usec;
+ struct timeval tv;
+
+ /*
+ * Quick, Batman, get a timestamp! We need to do this
+ * right away. The time between the end of the stop bit
+ * and this point is critical, and should be as nearly
+ * constant and as short as possible. (Un)fortunately,
+ * the Sun's clock granularity is so big this isn't a
+ * major problem.
+ *
+ * uniqtime() is totally undocumented, but there you are.
+ */
+ uniqtime(&tv);
+
+#ifdef SOLARIS2
+ mutex_enter(&((struct priv_data *)q->q_ptr)->chucode_mutex);
+#endif
+
+ /*
+ * Now, locate the chu struct once so we don't have to do it
+ * over and over.
+ */
+ chuc=&(((struct priv_data *) (q->q_ptr))->chu_struct);
+
+ /*
+ * Compute the difference in this character's time stamp
+ * and the last. If it exceeds the margin, blow away all
+ * the characters currently in the buffer.
+ */
+ i = (int)chuc->ncodechars;
+ if (i > 0)
+ {
+ sec = tv.tv_sec - chuc->codetimes[i-1].tv_sec;
+ usec = tv.tv_usec - chuc->codetimes[i-1].tv_usec;
+ if (usec < 0)
+ {
+ sec -= 1;
+ usec += 1000000;
+ }
+ if (sec != 0 || usec > CHUMAXUSEC)
+ {
+ i = 0;
+ chuc->ncodechars = 0;
+ }
+ }
+
+ /*
+ * Store the character.
+ */
+ chuc->codechars[i] = (u_char)c;
+ chuc->codetimes[i] = tv;
+
+ /*
+ * Now we perform the 'sixth byte' heuristics.
+ *
+ * This is a long story.
+ *
+ * We used to be able to count on the first byte of the code
+ * having a '6' in the LSD. This prevented most code framing
+ * errors (garbage before the first byte wouldn't typically
+ * have a 6 in the LSD). That's no longer the case.
+ *
+ * We can get around this, however, by noting that the 6th byte
+ * must be either equal to or one's complement of the first.
+ * If we get a sixth byte that ISN'T like that, then it may
+ * well be that the first byte is garbage. The right thing
+ * to do is to left-shift the whole buffer one count and
+ * continue to wait for the sixth byte.
+ */
+ if (i == NCHUCHARS/2)
+ {
+ register u_char temp_byte;
+
+ temp_byte=chuc->codechars[i] ^ chuc->codechars[0];
+
+ if ( (temp_byte) && (temp_byte!=0xff) )
+ {
+ register int t;
+ /*
+ * No match. Left-shift the buffer and try again
+ */
+ for(t=0;t<=NCHUCHARS/2;t++)
+ {
+ chuc->codechars[t]=chuc->codechars[t+1];
+ chuc->codetimes[t]=chuc->codetimes[t+1];
+ }
+
+ i--; /* This is because of the ++i immediately following */
+ }
+ }
+
+ /*
+ * We done yet?
+ */
+ if (++i < NCHUCHARS)
+ {
+ /*
+ * We're not done. Not much to do here. Save the count and wait
+ * for another character.
+ */
+ chuc->ncodechars = (u_char)i;
+ }
+ else
+ {
+ /*
+ * We are done. Mark this buffer full and pass it along.
+ */
+ chuc->ncodechars = NCHUCHARS;
+
+ /*
+ * Now we have a choice. Either the front half and back half
+ * have to match, or be one's complement of each other.
+ *
+ * So let's try the first byte and see
+ */
+
+ if(chuc->codechars[0] == chuc->codechars[NCHUCHARS/2])
+ {
+ chuc->chutype = CHU_TIME;
+ for( i=0; i<(NCHUCHARS/2); i++)
+ if (chuc->codechars[i] != chuc->codechars[i+(NCHUCHARS/2)])
+ {
+ chuc->ncodechars = 0;
+#ifdef SOLARIS2
+ mutex_exit(&((struct priv_data *)q->q_ptr)->chucode_mutex);
+#endif
+ return;
+ }
+ }
+ else
+ {
+ chuc->chutype = CHU_YEAR;
+ for( i=0; i<(NCHUCHARS/2); i++)
+ if (((chuc->codechars[i] ^ chuc->codechars[i+(NCHUCHARS/2)]) & 0xff)
+ != 0xff )
+ {
+ chuc->ncodechars = 0;
+#ifdef SOLARIS2
+ mutex_exit(&((struct priv_data *)q->q_ptr)->chucode_mutex);
+#endif
+ return;
+ }
+ }
+
+ passback(chuc,q); /* We're done! */
+ chuc->ncodechars = 0; /* Start all over again! */
+ }
+#ifdef SOLARIS2
+ mutex_exit(&((struct priv_data *)q->q_ptr)->chucode_mutex);
+#endif
+}
+
+#endif /* NCHU > 0 */
diff --git a/kernel/tty_clk.c b/kernel/tty_clk.c
new file mode 100644
index 0000000..0720610
--- /dev/null
+++ b/kernel/tty_clk.c
@@ -0,0 +1,317 @@
+/* tty_clk.c,v 3.1 1993/07/06 01:07:33 jbj Exp
+ * tty_clk.c - Generic line driver for receiving radio clock timecodes
+ */
+
+#include "clk.h"
+#if NCLK > 0
+
+#include "../h/param.h"
+#include "../h/types.h"
+#include "../h/systm.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/ioctl.h"
+#include "../h/tty.h"
+#include "../h/proc.h"
+#include "../h/file.h"
+#include "../h/conf.h"
+#include "../h/buf.h"
+#include "../h/uio.h"
+#include "../h/clist.h"
+
+/*
+ * This line discipline is intended to provide well performing
+ * generic support for the reception and time stamping of radio clock
+ * timecodes. Most radio clock devices return a string where a
+ * particular character in the code (usually a \r) is on-time
+ * synchronized with the clock. The idea here is to collect characters
+ * until (one of) the synchronization character(s) (we allow two) is seen.
+ * When the magic character arrives we take a timestamp by calling
+ * microtime() and insert the eight bytes of struct timeval into the
+ * buffer after the magic character. We then wake up anyone waiting
+ * for the buffer and return the whole mess on the next read.
+ *
+ * To use this the calling program is expected to first open the
+ * port, and then to set the port into raw mode with the speed
+ * set appropriately with a TIOCSETP ioctl(), with the erase and kill
+ * characters set to those to be considered magic (yes, I know this
+ * is gross, but they were so convenient). If only one character is
+ * magic you can set then both the same, or perhaps to the alternate
+ * parity versions of said character. After getting all this set,
+ * change the line discipline to CLKLDISC and you are on your way.
+ *
+ * The only other bit of magic we do in here is to flush the receive
+ * buffers on writes if the CRMOD flag is set (hack, hack).
+ */
+
+/*
+ * We run this very much like a raw mode terminal, with the exception
+ * that we store up characters locally until we hit one of the
+ * magic ones and then dump it into the rawq all at once. We keep
+ * the buffered data in clists since we can then often move it to
+ * the rawq without copying. For sanity we limit the number of
+ * characters between specials, and the total number of characters
+ * before we flush the rawq, as follows.
+ */
+#define CLKLINESIZE (256)
+#define NCLKCHARS (CLKLINESIZE*4)
+
+struct clkdata {
+ int inuse;
+ struct clist clkbuf;
+};
+#define clk_cc clkbuf.c_cc
+#define clk_cf clkbuf.c_cf
+#define clk_cl clkbuf.c_cl
+
+struct clkdata clk_data[NCLK];
+
+/*
+ * Routine for flushing the internal clist
+ */
+#define clk_bflush(clk) (ndflush(&((clk)->clkbuf), (clk)->clk_cc))
+
+int clk_debug = 0;
+
+/*ARGSUSED*/
+clkopen(dev, tp)
+ dev_t dev;
+ register struct tty *tp;
+{
+ register struct clkdata *clk;
+
+ /*
+ * Don't allow multiple opens. This will also protect us
+ * from someone opening /dev/tty
+ */
+ if (tp->t_line == CLKLDISC)
+ return (EBUSY);
+ ttywflush(tp);
+ for (clk = clk_data; clk < &clk_data[NCLK]; clk++)
+ if (!clk->inuse)
+ break;
+ if (clk >= &clk_data[NCLK])
+ return (EBUSY);
+ clk->inuse++;
+ clk->clk_cc = 0;
+ clk->clk_cf = clk->clk_cl = NULL;
+ tp->T_LINEP = (caddr_t) clk;
+ return (0);
+}
+
+
+/*
+ * Break down... called when discipline changed or from device
+ * close routine.
+ */
+clkclose(tp)
+ register struct tty *tp;
+{
+ register struct clkdata *clk;
+ register int s = spltty();
+
+ clk = (struct clkdata *)tp->T_LINEP;
+ if (clk->clk_cc > 0)
+ clk_bflush(clk);
+ clk->inuse = 0;
+ tp->t_line = 0; /* paranoid: avoid races */
+ splx(s);
+}
+
+
+/*
+ * Receive a write request. We pass these requests on to the terminal
+ * driver, except that if the CRMOD bit is set in the flags we
+ * first flush the input queues.
+ */
+clkwrite(tp, uio)
+ register struct tty *tp;
+ struct uio *uio;
+{
+ if (tp->t_flags & CRMOD) {
+ register struct clkdata *clk;
+ int s;
+
+ s = spltty();
+ if (tp->t_rawq.c_cc > 0)
+ ndflush(&tp->t_rawq, tp->t_rawq.c_cc);
+ clk = (struct clkdata *) tp->T_LINEP;
+ if (clk->clk_cc > 0)
+ clk_bflush(clk);
+ (void)splx(s);
+ }
+ ttwrite(tp, uio);
+}
+
+
+/*
+ * Low level character input routine.
+ * If the character looks okay, grab a time stamp. If the stuff in
+ * the buffer is too old, dump it and start fresh. If the character is
+ * non-BCDish, everything in the buffer too.
+ */
+clkinput(c, tp)
+ register int c;
+ register struct tty *tp;
+{
+ register struct clkdata *clk;
+ register int i;
+ register long s;
+ struct timeval tv;
+
+ /*
+ * Check to see whether this isn't the magic character. If not,
+ * save the character and return.
+ */
+#ifdef ultrix
+ if (c != tp->t_cc[VERASE] && c != tp->t_cc[VKILL]) {
+#else
+ if (c != tp->t_erase && c != tp->t_kill) {
+#endif
+ clk = (struct clkdata *) tp->T_LINEP;
+ if (clk->clk_cc >= CLKLINESIZE)
+ clk_bflush(clk);
+ if (putc(c, &clk->clkbuf) == -1) {
+ /*
+ * Hopeless, no clists. Flush what we have
+ * and hope things improve.
+ */
+ clk_bflush(clk);
+ }
+ return;
+ }
+
+ /*
+ * Here we have a magic character. Get a timestamp and store
+ * everything.
+ */
+ microtime(&tv);
+ clk = (struct clkdata *) tp->T_LINEP;
+
+ if (putc(c, &clk->clkbuf) == -1)
+ goto flushout;
+
+#ifdef CLKLDISC
+ /*
+ * STREAMS people started writing timestamps this way.
+ * It's not my fault, I am just going along with the flow...
+ */
+ for (i = 0; i < sizeof(struct timeval); i++)
+ if (putc(*( ((char*)&tv) + i ), &clk->clkbuf) == -1)
+ goto flushout;
+#else
+ /*
+ * This is a machine independant way of puting longs into
+ * the datastream. It has fallen into disuse...
+ */
+ s = tv.tv_sec;
+ for (i = 0; i < sizeof(long); i++) {
+ if (putc((s >> 24) & 0xff, &clk->clkbuf) == -1)
+ goto flushout;
+ s <<= 8;
+ }
+
+ s = tv.tv_usec;
+ for (i = 0; i < sizeof(long); i++) {
+ if (putc((s >> 24) & 0xff, &clk->clkbuf) == -1)
+ goto flushout;
+ s <<= 8;
+ }
+#endif
+
+ /*
+ * If the length of the rawq exceeds our sanity limit, dump
+ * all the old crap in there before copying this in.
+ */
+ if (tp->t_rawq.c_cc > NCLKCHARS)
+ ndflush(&tp->t_rawq, tp->t_rawq.c_cc);
+
+ /*
+ * Now copy the buffer in. There is a special case optimization
+ * here. If there is nothing on the rawq at present we can
+ * just copy the clists we own over. Otherwise we must concatenate
+ * the present data on the end.
+ */
+ s = (long)spltty();
+ if (tp->t_rawq.c_cc <= 0) {
+ tp->t_rawq = clk->clkbuf;
+ clk->clk_cc = 0;
+ clk->clk_cl = clk->clk_cf = NULL;
+ (void) splx((int)s);
+ } else {
+ (void) splx((int)s);
+ catq(&clk->clkbuf, &tp->t_rawq);
+ clk_bflush(clk);
+ }
+
+ /*
+ * Tell the world
+ */
+ ttwakeup(tp);
+ return;
+
+flushout:
+ /*
+ * It would be nice if this never happened. Flush the
+ * internal clists and hope someone else frees some of them
+ */
+ clk_bflush(clk);
+ return;
+}
+
+
+/*
+ * Handle ioctls. We reject most tty-style except those that
+ * change the line discipline and a couple of others..
+ */
+clkioctl(tp, cmd, data, flag)
+ struct tty *tp;
+ int cmd;
+ caddr_t data;
+ int flag;
+{
+ int flags;
+ struct sgttyb *sg;
+
+ if ((cmd>>8) != 't')
+ return (-1);
+ switch (cmd) {
+ case TIOCSETD:
+ case TIOCGETD:
+ case TIOCGETP:
+ case TIOCGETC:
+ case TIOCOUTQ:
+ return (-1);
+
+ case TIOCSETP:
+ /*
+ * He likely wants to set new magic characters in.
+ * Do this part.
+ */
+ sg = (struct sgttyb *)data;
+#ifdef ultrix
+ tp->t_cc[VERASE] = sg->sg_erase;
+ tp->t_cc[VKILL] = sg->sg_kill;
+#else
+ tp->t_erase = sg->sg_erase;
+ tp->t_kill = sg->sg_kill;
+#endif
+ return (0);
+
+ case TIOCFLUSH:
+ flags = *(int *)data;
+ if (flags == 0 || (flags & FREAD)) {
+ register struct clkdata *clk;
+
+ clk = (struct clkdata *) tp->T_LINEP;
+ if (clk->clk_cc > 0)
+ clk_bflush(clk);
+ }
+ return (-1);
+
+ default:
+ break;
+ }
+ return (ENOTTY); /* not quite appropriate */
+}
+#endif NCLK
diff --git a/kernel/tty_clk_STREAMS.c b/kernel/tty_clk_STREAMS.c
new file mode 100644
index 0000000..13b0a25
--- /dev/null
+++ b/kernel/tty_clk_STREAMS.c
@@ -0,0 +1,266 @@
+/* tty_clk_STREAMS.c,v 3.1 1993/07/06 01:07:34 jbj Exp
+ * Timestamp STREAMS module for SunOS 4.1
+ *
+ * Copyright 1991, Nick Sayer
+ *
+ * Special thanks to Greg Onufer for his debug assists.
+ *
+ * Should be PUSHed directly on top of a serial I/O channel.
+ * For any character in a user-designated set, adds a kernel
+ * timestamp to that character.
+ *
+ * BUGS:
+ *
+ * Only so many characters can be timestamped. This number, however,
+ * is adjustable.
+ *
+ * The null character ($00) cannot be timestamped.
+ *
+ * The M_DATA messages passed upstream will not be the same
+ * size as when they arrive from downstream, even if no
+ * timestamp character is in the message. This, however,
+ * should not affect anything.
+ *
+ */
+
+#include "clk.h"
+#if NCLK > 0
+/*
+ * How big should the messages we pass upstream be?
+ */
+#define MESSAGE_SIZE 128
+
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stream.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/kernel.h>
+#include <sys/user.h>
+#include <sys/errno.h>
+#include <sys/syslog.h>
+
+#include <sys/clkdefs.h>
+
+static struct module_info rminfo = { 0, "clk", 0, INFPSZ, 0, 0 };
+static struct module_info wminfo = { 0, "clk", 0, INFPSZ, 0, 0 };
+static int clkopen(), clkrput(), clkwput(), clkclose();
+
+static struct qinit rinit = { clkrput, NULL, clkopen, clkclose, NULL,
+ &rminfo, NULL };
+
+static struct qinit winit = { clkwput, NULL, NULL, NULL, NULL,
+ &wminfo, NULL };
+
+struct streamtab clkinfo = { &rinit, &winit, NULL, NULL };
+
+struct priv_data_type
+{
+ char in_use;
+ char string[CLK_MAXSTRSIZE];
+} priv_data[NCLK];
+
+char first_open=1;
+
+/*
+ * God only knows why, but linking with strchr() fails
+ * on my system, so here's a renamed copy.
+ */
+
+u_char *str_chr(s,c)
+u_char *s;
+int c;
+{
+ while (*s)
+ if(*s++ == c)
+ return (s-1);
+ return NULL;
+}
+
+/*ARGSUSED*/
+static int clkopen(q, dev, flag, sflag)
+queue_t *q;
+dev_t dev;
+int flag;
+int sflag;
+{
+ int i;
+
+/* Damn it! We can't even have the global data struct properly
+ initialized! So we have a mark to tell us to init the global
+ data on the first open */
+
+ if (first_open)
+ {
+ first_open=0;
+
+ for(i=0;i<NCLK;i++)
+ priv_data[i].in_use=0;
+ }
+
+ for(i=0;i<NCLK;i++)
+ if(!priv_data[i].in_use)
+ {
+ priv_data[i].in_use++;
+ ((struct priv_data_type *) (q->q_ptr))=priv_data+i;
+ priv_data[i].string[0]=0;
+ return (0);
+ }
+ u.u_error = EBUSY;
+ return (OPENFAIL);
+}
+
+/*ARGSUSED*/
+static int clkclose(q, flag)
+queue_t *q;
+int flag;
+{
+ ((struct priv_data_type *) (q->q_ptr))->in_use=0;
+
+ return (0);
+}
+
+/*
+ * Now the crux of the biscuit.
+ *
+ * If it's an M_DATA package, we take each character and pass
+ * it to clkchar.
+ */
+
+void clkchar();
+
+static int clkrput(q, mp)
+queue_t *q;
+mblk_t *mp;
+{
+ mblk_t *bp;
+
+ switch(mp->b_datap->db_type)
+ {
+ case M_DATA:
+ clkchar(0,q,2);
+ for(bp=mp; bp!=NULL; bp=bp->b_cont)
+ {
+ while(bp->b_rptr < bp->b_wptr)
+ clkchar( ((u_char)*(bp->b_rptr++)) , q , 0 );
+ }
+ clkchar(0,q,1);
+ freemsg(mp);
+ break;
+ default:
+ putnext(q,mp);
+ break;
+ }
+
+}
+
+/*
+ * If it's a matching M_IOCTL, handle it.
+ */
+
+static int clkwput(q, mp)
+queue_t *q;
+mblk_t *mp;
+{
+ struct iocblk *iocp;
+
+ switch(mp->b_datap->db_type)
+ {
+ case M_IOCTL:
+ iocp=(struct iocblk*) mp->b_rptr;
+ if (iocp->ioc_cmd==CLK_SETSTR)
+ {
+ strncpy( ((struct priv_data_type *) (RD(q)->q_ptr))->string,
+ (char *) mp->b_cont->b_rptr,CLK_MAXSTRSIZE);
+ /* make sure it's null terminated */
+ ((struct priv_data_type *) (RD(q)->q_ptr))->string[CLK_MAXSTRSIZE-1]=0;
+ mp->b_datap->db_type = M_IOCACK;
+ qreply(q,mp);
+ }
+ else
+ putnext(q,mp);
+ break;
+ default:
+ putnext(q,mp);
+ break;
+ }
+}
+
+/*
+ * Now clkchar. It takes a character, a queue pointer and an action
+ * flag and depending on the flag either:
+ *
+ * 0 - adds the character to the current message. If there's a
+ * timestamp to be done, do that too. If the message is less than
+ * 8 chars from being full, link in a new one, and set it up for
+ * the next call.
+ *
+ * 1 - sends the whole mess to Valhala.
+ *
+ * 2 - set things up.
+ *
+ * Yeah, it's an ugly hack. Complaints may be filed with /dev/null.
+ */
+
+
+void clkchar(c,q,f)
+ register u_char c;
+ queue_t *q;
+ char f;
+{
+ static char error;
+ static mblk_t *message,*mp;
+ struct timeval tv;
+
+/* Get a timestamp ASAP! */
+ uniqtime(&tv);
+
+ switch(f)
+ {
+ case 1:
+ if (!error)
+ putnext(q,message);
+ break;
+ case 2:
+ mp=message= (mblk_t*) allocb(MESSAGE_SIZE,BPRI_LO);
+ error=(message==NULL);
+ if (error)
+ log(LOG_ERR,"clk: cannot allocate message - data lost");
+ break;
+ case 0:
+ if (error) /* If we had an error, forget it. */
+ return;
+
+ *mp->b_wptr++=c; /* Put the char away first.
+
+ /* If it's in the special string, append a struct timeval */
+
+ if (str_chr( ((struct priv_data_type *) (q->q_ptr))->string ,
+ c )!=NULL)
+ {
+ int i;
+
+ for (i=0;i<sizeof(struct timeval);i++)
+ *mp->b_wptr++= *( ((char*)&tv) + i );
+ }
+
+ /* If we don't have space for a complete struct timeval, and a
+ char, it's time for a new mp block */
+
+ if (((mp->b_wptr-mp->b_rptr)+sizeof(struct timeval)+2)>MESSAGE_SIZE)
+ {
+ mp->b_cont= (mblk_t*) allocb(MESSAGE_SIZE,BPRI_LO);
+ error=(mp->b_cont==NULL);
+ if (error)
+ {
+ log(LOG_ERR,"clk: cannot allocate message - data lost");
+ freemsg(message);
+ }
+ mp=mp->b_cont;
+ }
+
+ break;
+ }
+}
+
+#endif
OpenPOWER on IntegriCloud