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)