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 driver can accumulate to several milliseconds on a typical Unix workstation. In order to reduce these errors, a set of special line disciplines and stream modules can be configured in the Unix kernel. These routines intercept special characters or signals provided by the radio or modem clock and save a local timestamp for later processing.

The routines 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 minor changes in some kernel files and in the NTP daemon ntpd. 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 and a special streams module included in the distribution. Support for each in ntpd is enabled by adding flags to the DEFS_LOCAL line of the ntpd 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
This routine 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 local timestamp in Unix timeval format. Both select() and SIGIO are supported by the routine. The -DTTYCLK flag is used to compile support for this discipline in ntpd. This flag is automatically included if the clkdefs.h file is found in the /usr/include/sys directory, or it can be added (or deleted) manually. This module must be configured in the kernel during the kernel build process, as described in the README file in the ./kernel directory.

tty_chu
This routine 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 CHU modem driver (type 7) described in the Reference Clock Drivers page. This discipline should be used in raw mode. The -DCHUCLK flag is used to compile support for this discipline in ntpd. This flag is automatically included if the chudefs.h file is found in the /usr/include/sys directory, or it can be added (or deleted) manually. This module must be configured in the kernel during the kernel build process, as described in the README file in the ./kernel directory.

ppsclock
This routine is a special purpose streams module which monitors the state of the data carrier detect (DCD) modem interface signal. It is normally used in connection with a pulse-per-second (PPS) signal generated by some radio clocks, which requires a hardware level converter/pulse generator, such as described in the Gadget Box PPS Level Converter and CHU Modem page. For each positive-going edge of the DCD signal, the ppsclock module captures a timestamp in Unix timeval format for later retrieval using a special ioctl() system call. The -DPPS flag is used to compile support for this module in ntpd. This flag is automatically included if the ppsclock.h file is found in the /sys/sys directory, or it can be added (or deleted) manually. This module must also be configured in the kernel during the kernel build process, as described in the README file in the ./kernel directory.

There are two versions of both the tty_clk and chu_clk programs. 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 programs are small, unobtrusive, and do nothing unless specifically enabled by an application program, it probably doesn't matter which version is chosen. Instructions on how to configure and build a kernel supporting either or both of these line disciplines is in the README file in the ./kernel directory.

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 32 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, be used, as it is the string terminator. Passing an empty string to CLK_SETSTR turns off timestamping. 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.

How to Use the ppsclock Stream Module

The ppsclock streams module implements an ioctl() CIOGETEV, which takes a pointer to the structure

struct ppsclockev {
     struct timeval tv;
     u_int serial;
};

The ppsclock module is pushed on the streams stack of the serial port connected to the PPS signal. The port must be configured for local operation, rather than remote (modem) operation. At each positive-going edge of the DCD signal, the routine latches the current local timestamp and increments a counter. At each CIOGETEV ioctl() call, the current values of the timestamp and counter are returned in the ppsclockev structure.

TIOCDCDTIMESTAMP timestamping

On FreeBSD 2.2 and later systems the TIOCDCDTIMESTAMP ioctl is used to read the timestamp when the DCD serial go active. To use this the PPS signal must be tied to the serial port DCD signal through the appropriate level converters and pulse stretch circuitry if necessary. This enhances the accuracy of the driver to a few microseconds. Using FreeBSD 2.2 the measured delay between activation of the PPS signal and the time the timestamp is made on a 66MHz 486DX2 is 19us and on a 100MHz Pentium is 6us. The driver does NOT compensate for this.

The TIOCDCDTIMESTAMP timestamping ioctl() is used automatically on FreeBSD systems if available. It is integrated into the refclock_gtlin() function so any driver using it will benefit from the enhanced accuracy.


David L. Mills ([email protected])