diff options
author | Ollivier Robert <roberto@FreeBSD.org> | 1999-12-09 13:01:21 +0000 |
---|---|---|
committer | Ollivier Robert <roberto@FreeBSD.org> | 1999-12-09 13:01:21 +0000 |
commit | c0b746e5e8d9479f05b3749cbf1f73b8928719bd (patch) | |
tree | fc0cfa1aab0ff6b228f511b410733ef4f35d1ead /contrib/ntp/kernel | |
download | src-c0b746e5e8d9479f05b3749cbf1f73b8928719bd.tar.gz src-c0b746e5e8d9479f05b3749cbf1f73b8928719bd.zip |
Virgin import of ntpd 4.0.98fvendor/ntp/4.0.98f
Notes
Notes:
svn path=/vendor/ntp/dist/; revision=54359
svn path=/vendor/ntp/4.0.98f/; revision=54361; tag=vendor/ntp/4.0.98f
Diffstat (limited to 'contrib/ntp/kernel')
-rw-r--r-- | contrib/ntp/kernel/Makefile.am | 5 | ||||
-rw-r--r-- | contrib/ntp/kernel/Makefile.in | 309 | ||||
-rw-r--r-- | contrib/ntp/kernel/README | 200 | ||||
-rw-r--r-- | contrib/ntp/kernel/chuinit.c | 76 | ||||
-rw-r--r-- | contrib/ntp/kernel/clkinit.c | 76 | ||||
-rw-r--r-- | contrib/ntp/kernel/sys/Makefile.am | 8 | ||||
-rw-r--r-- | contrib/ntp/kernel/sys/Makefile.in | 238 | ||||
-rw-r--r-- | contrib/ntp/kernel/sys/README | 11 | ||||
-rw-r--r-- | contrib/ntp/kernel/sys/bsd_audioirig.h | 101 | ||||
-rw-r--r-- | contrib/ntp/kernel/sys/chudefs.h | 22 | ||||
-rw-r--r-- | contrib/ntp/kernel/sys/clkdefs.h | 38 | ||||
-rw-r--r-- | contrib/ntp/kernel/sys/i8253.h | 48 | ||||
-rw-r--r-- | contrib/ntp/kernel/sys/parsestreams.h | 107 | ||||
-rw-r--r-- | contrib/ntp/kernel/sys/pcl720.h | 95 | ||||
-rw-r--r-- | contrib/ntp/kernel/sys/ppsclock.h | 64 | ||||
-rw-r--r-- | contrib/ntp/kernel/sys/timex.h | 309 | ||||
-rw-r--r-- | contrib/ntp/kernel/sys/tpro.h | 34 | ||||
-rw-r--r-- | contrib/ntp/kernel/tty_chu.c | 276 | ||||
-rw-r--r-- | contrib/ntp/kernel/tty_chu_STREAMS.c | 603 | ||||
-rw-r--r-- | contrib/ntp/kernel/tty_clk.c | 317 | ||||
-rw-r--r-- | contrib/ntp/kernel/tty_clk_STREAMS.c | 266 |
21 files changed, 3203 insertions, 0 deletions
diff --git a/contrib/ntp/kernel/Makefile.am b/contrib/ntp/kernel/Makefile.am new file mode 100644 index 000000000000..b3cfc9d6d815 --- /dev/null +++ b/contrib/ntp/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/contrib/ntp/kernel/Makefile.in b/contrib/ntp/kernel/Makefile.in new file mode 100644 index 000000000000..1a4d1ed96071 --- /dev/null +++ b/contrib/ntp/kernel/Makefile.in @@ -0,0 +1,309 @@ +# Makefile.in generated automatically by automake 1.4a from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_FLAG = +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_alias = @build_alias@ +build_triplet = @build@ +host_alias = @host_alias@ +host_triplet = @host@ +target_alias = @target_alias@ +target_triplet = @target@ +AMTAR = @AMTAR@ +AMTARFLAGS = @AMTARFLAGS@ +AWK = @AWK@ +CC = @CC@ +CFLAGS = @CFLAGS@ +CHUTEST = @CHUTEST@ +CLKTEST = @CLKTEST@ +CPP = @CPP@ +DCFD = @DCFD@ +LDFLAGS = @LDFLAGS@ +LIBPARSE = @LIBPARSE@ +LIBRSAREF = @LIBRSAREF@ +LN_S = @LN_S@ +MAKEINFO = @MAKEINFO@ +MAKE_ADJTIMED = @MAKE_ADJTIMED@ +MAKE_CHECK_Y2K = @MAKE_CHECK_Y2K@ +MAKE_LIBPARSE = @MAKE_LIBPARSE@ +MAKE_LIBPARSE_KERNEL = @MAKE_LIBPARSE_KERNEL@ +MAKE_LIBRSAREF = @MAKE_LIBRSAREF@ +MAKE_NTPTIME = @MAKE_NTPTIME@ +MAKE_PARSEKMODULE = @MAKE_PARSEKMODULE@ +MAKE_TICKADJ = @MAKE_TICKADJ@ +PACKAGE = @PACKAGE@ +PATH_SH = @PATH_SH@ +PROPDELAY = @PROPDELAY@ +RANLIB = @RANLIB@ +RSAREF = @RSAREF@ +TESTDCF = @TESTDCF@ +U = @U@ +VERSION = @VERSION@ + +#AUTOMAKE_OPTIONS = ../util/ansi2knr no-dependencies + + +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 +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../config.h +CONFIG_CLEAN_FILES = +DIST_SOURCES = +DIST_COMMON = README Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +GZIP_ENV = --best +all: all-redirect +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps kernel/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +# 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. + +@SET_MAKE@ + +all-recursive install-data-recursive install-exec-recursive \ +installdirs-recursive install-recursive uninstall-recursive \ +check-recursive installcheck-recursive info-recursive dvi-recursive: + @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; \ + rev=''; list='$(SUBDIRS)'; for subdir in $$list; do \ + rev="$$subdir $$rev"; \ + if test "$$subdir" = "."; then dot_seen=yes; else :; fi; \ + done; \ + test "$$dot_seen" = "no" && 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 + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + ${AWK:-awk} ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + ${AWK:-awk} ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done + for subdir in $(SUBDIRS); do \ + if test "$$subdir" = .; then :; else \ + test -d $(distdir)/$$subdir \ + || mkdir $(distdir)/$$subdir \ + || exit 1; \ + chmod 777 $(distdir)/$$subdir; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir=../$(top_distdir) distdir=../$(distdir)/$$subdir distdir) \ + || exit 1; \ + fi; \ + done +info-am: +info: info-recursive +dvi-am: +dvi: dvi-recursive +check-am: all-am +check: check-recursive +installcheck-am: +installcheck: installcheck-recursive +install-exec-am: +install-exec: install-exec-recursive + +install-data-am: +install-data: install-data-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-recursive +uninstall-am: +uninstall: uninstall-recursive +all-am: Makefile +all-redirect: all-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install +installdirs: installdirs-recursive +installdirs-am: + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-tags mostlyclean-generic + +mostlyclean: mostlyclean-recursive + +clean-am: clean-tags clean-generic mostlyclean-am + +clean: clean-recursive + +distclean-am: distclean-tags distclean-generic clean-am + +distclean: distclean-recursive + +maintainer-clean-am: maintainer-clean-tags maintainer-clean-generic \ + distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-recursive + +.PHONY: install-recursive uninstall-recursive install-data-recursive \ +uninstall-data-recursive install-exec-recursive \ +uninstall-exec-recursive installdirs-recursive uninstalldirs-recursive \ +all-recursive check-recursive installcheck-recursive info-recursive \ +dvi-recursive mostlyclean-recursive distclean-recursive clean-recursive \ +maintainer-clean-recursive tags tags-recursive mostlyclean-tags \ +distclean-tags clean-tags maintainer-clean-tags distdir info-am info \ +dvi-am dvi check check-am installcheck-am installcheck install-exec-am \ +install-exec install-data-am install-data install-am install \ +uninstall-am uninstall all-redirect all-am all install-strip \ +installdirs-am installdirs mostlyclean-generic distclean-generic \ +clean-generic maintainer-clean-generic clean mostlyclean distclean \ +maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/contrib/ntp/kernel/README b/contrib/ntp/kernel/README new file mode 100644 index 000000000000..253d04e4e8d5 --- /dev/null +++ b/contrib/ntp/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/contrib/ntp/kernel/chuinit.c b/contrib/ntp/kernel/chuinit.c new file mode 100644 index 000000000000..5d73e52e21f3 --- /dev/null +++ b/contrib/ntp/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/contrib/ntp/kernel/clkinit.c b/contrib/ntp/kernel/clkinit.c new file mode 100644 index 000000000000..1af57fd4460e --- /dev/null +++ b/contrib/ntp/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/contrib/ntp/kernel/sys/Makefile.am b/contrib/ntp/kernel/sys/Makefile.am new file mode 100644 index 000000000000..ba405cdf49c0 --- /dev/null +++ b/contrib/ntp/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 +#EXTRA_DIST= TAGS +# HMS: Avoid bug in automake +#ETAGS_ARGS = "" +ETAGS_ARGS = Makefile.am diff --git a/contrib/ntp/kernel/sys/Makefile.in b/contrib/ntp/kernel/sys/Makefile.in new file mode 100644 index 000000000000..530f3861f876 --- /dev/null +++ b/contrib/ntp/kernel/sys/Makefile.in @@ -0,0 +1,238 @@ +# Makefile.in generated automatically by automake 1.4a from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = ../.. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_FLAG = +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_alias = @build_alias@ +build_triplet = @build@ +host_alias = @host_alias@ +host_triplet = @host@ +target_alias = @target_alias@ +target_triplet = @target@ +AMTAR = @AMTAR@ +AMTARFLAGS = @AMTARFLAGS@ +AWK = @AWK@ +CC = @CC@ +CFLAGS = @CFLAGS@ +CHUTEST = @CHUTEST@ +CLKTEST = @CLKTEST@ +CPP = @CPP@ +DCFD = @DCFD@ +LDFLAGS = @LDFLAGS@ +LIBPARSE = @LIBPARSE@ +LIBRSAREF = @LIBRSAREF@ +LN_S = @LN_S@ +MAKEINFO = @MAKEINFO@ +MAKE_ADJTIMED = @MAKE_ADJTIMED@ +MAKE_CHECK_Y2K = @MAKE_CHECK_Y2K@ +MAKE_LIBPARSE = @MAKE_LIBPARSE@ +MAKE_LIBPARSE_KERNEL = @MAKE_LIBPARSE_KERNEL@ +MAKE_LIBRSAREF = @MAKE_LIBRSAREF@ +MAKE_NTPTIME = @MAKE_NTPTIME@ +MAKE_PARSEKMODULE = @MAKE_PARSEKMODULE@ +MAKE_TICKADJ = @MAKE_TICKADJ@ +PACKAGE = @PACKAGE@ +PATH_SH = @PATH_SH@ +PROPDELAY = @PROPDELAY@ +RANLIB = @RANLIB@ +RSAREF = @RSAREF@ +TESTDCF = @TESTDCF@ +U = @U@ +VERSION = @VERSION@ + +#AUTOMAKE_OPTIONS = ../../util/ansi2knr no-dependencies + + +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 + +#EXTRA_DIST= TAGS +# HMS: Avoid bug in automake +#ETAGS_ARGS = "" +ETAGS_ARGS = Makefile.am +subdir = kernel/sys +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../../config.h +CONFIG_CLEAN_FILES = +DIST_SOURCES = +HEADERS = $(noinst_HEADERS) + +DIST_COMMON = README $(noinst_HEADERS) Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +GZIP_ENV = --best +all: all-redirect +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps kernel/sys/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + ${AWK:-awk} ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + ${AWK:-awk} ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: +install-exec: install-exec-am + +install-data-am: +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: +uninstall: uninstall-am +all-am: Makefile $(HEADERS) +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_STRIP_FLAG=-s install +installdirs: + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-tags mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-tags clean-generic mostlyclean-am + +clean: clean-am + +distclean-am: distclean-tags distclean-generic clean-am + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-tags maintainer-clean-generic \ + distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: tags mostlyclean-tags distclean-tags clean-tags \ +maintainer-clean-tags distdir info-am info dvi-am dvi check check-am \ +installcheck-am installcheck install-exec-am install-exec \ +install-data-am install-data install-am install uninstall-am uninstall \ +all-redirect all-am all install-strip installdirs mostlyclean-generic \ +distclean-generic clean-generic maintainer-clean-generic clean \ +mostlyclean distclean maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/contrib/ntp/kernel/sys/README b/contrib/ntp/kernel/sys/README new file mode 100644 index 000000000000..b9d95d926407 --- /dev/null +++ b/contrib/ntp/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/contrib/ntp/kernel/sys/bsd_audioirig.h b/contrib/ntp/kernel/sys/bsd_audioirig.h new file mode 100644 index 000000000000..9b7c69009fb8 --- /dev/null +++ b/contrib/ntp/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/contrib/ntp/kernel/sys/chudefs.h b/contrib/ntp/kernel/sys/chudefs.h new file mode 100644 index 000000000000..f5549f58b828 --- /dev/null +++ b/contrib/ntp/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/contrib/ntp/kernel/sys/clkdefs.h b/contrib/ntp/kernel/sys/clkdefs.h new file mode 100644 index 000000000000..afbc77a8f1ac --- /dev/null +++ b/contrib/ntp/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/contrib/ntp/kernel/sys/i8253.h b/contrib/ntp/kernel/sys/i8253.h new file mode 100644 index 000000000000..70965931691f --- /dev/null +++ b/contrib/ntp/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/contrib/ntp/kernel/sys/parsestreams.h b/contrib/ntp/kernel/sys/parsestreams.h new file mode 100644 index 000000000000..b12e92c338e2 --- /dev/null +++ b/contrib/ntp/kernel/sys/parsestreams.h @@ -0,0 +1,107 @@ +/* + * /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> + +#define NTP_NEED_BOPS + +#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/contrib/ntp/kernel/sys/pcl720.h b/contrib/ntp/kernel/sys/pcl720.h new file mode 100644 index 000000000000..e8638ae33534 --- /dev/null +++ b/contrib/ntp/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, c = Cntr, 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/contrib/ntp/kernel/sys/ppsclock.h b/contrib/ntp/kernel/sys/ppsclock.h new file mode 100644 index 000000000000..b0fe407339b3 --- /dev/null +++ b/contrib/ntp/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/contrib/ntp/kernel/sys/timex.h b/contrib/ntp/kernel/sys/timex.h new file mode 100644 index 000000000000..d42ec08d0f8a --- /dev/null +++ b/contrib/ntp/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/contrib/ntp/kernel/sys/tpro.h b/contrib/ntp/kernel/sys/tpro.h new file mode 100644 index 000000000000..f276f81bead0 --- /dev/null +++ b/contrib/ntp/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/contrib/ntp/kernel/tty_chu.c b/contrib/ntp/kernel/tty_chu.c new file mode 100644 index 000000000000..4615875e77e0 --- /dev/null +++ b/contrib/ntp/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/contrib/ntp/kernel/tty_chu_STREAMS.c b/contrib/ntp/kernel/tty_chu_STREAMS.c new file mode 100644 index 000000000000..f46e25d2ab51 --- /dev/null +++ b/contrib/ntp/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/contrib/ntp/kernel/tty_clk.c b/contrib/ntp/kernel/tty_clk.c new file mode 100644 index 000000000000..072061039bf3 --- /dev/null +++ b/contrib/ntp/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/contrib/ntp/kernel/tty_clk_STREAMS.c b/contrib/ntp/kernel/tty_clk_STREAMS.c new file mode 100644 index 000000000000..13b0a25f1d89 --- /dev/null +++ b/contrib/ntp/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 |