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)