Index: Documentation/Configure.help
===================================================================
RCS file: /root/21REP/linux21/Documentation/Configure.help,v
retrieving revision 1.1.1.4
retrieving revision 1.1.1.4.4.2
diff -u -r1.1.1.4 -r1.1.1.4.4.2
--- Configure.help	1999/01/22 18:45:11	1.1.1.4
+++ Configure.help	1999/01/31 23:15:13	1.1.1.4.4.2
@@ -1611,6 +1611,28 @@
 
   If you don't know what to do, choose "386".
 
+NTP kernel support
+CONFIG_NTP
+  Say N here if you are sure you do not use the NTP kernel code and you
+  want to minimize the kernel size or system overhead.  Otherwise say Y.
+
+NTP PPS support
+CONFIG_NTP_PPS
+  Saying Y enables extra code that can calibrate your system clock relative
+  to some external precision pulse-per-second (PPS).  This simply provides
+  an additional kernel routine that still needs to be used by some driver
+  (e.g. the serial driver can take time stamps for pulses on carrier detect).
+  Normally you would say N here.
+
+NTP PPS support on serial port
+CONFIG_NTP_PPS_SERIAL
+  Saying Y here will include code for the serial driver to capture precision
+  time stamps that can be used to calibrate the software clock.  If you want
+  to use this, you'll have to connect a "pulse-per-second" source of high
+  accuracy to the carrier detect pin of a serial port.  This feature is
+  optional, and it keeps the port available for normal operation.  Usually
+  you don't need this.
+
 VGA text console
 CONFIG_VGA_CONSOLE
   Saying Y here will allow you to use Linux in text mode through a
Index: arch/alpha/config.in
===================================================================
RCS file: /root/21REP/linux21/arch/alpha/config.in,v
retrieving revision 1.1.1.4
retrieving revision 1.1.1.4.4.1
diff -u -r1.1.1.4 -r1.1.1.4.4.1
--- config.in	1999/01/22 18:45:27	1.1.1.4
+++ config.in	1999/01/31 23:15:36	1.1.1.4.4.1
@@ -146,6 +146,10 @@
 	# EV45 and older do not support all rounding modes in hw:
 	define_bool CONFIG_ALPHA_NEED_ROUNDING_EMULATION y
 fi
+bool 'NTP kernel support' CONFIG_NTP
+if [ "$CONFIG_NTP" != "n" ]; then
+  bool '   NTP PPS support' CONFIG_NTP_PPS
+fi
 
 if [ "$CONFIG_ALPHA_CABRIOLET" = "y" -o "$CONFIG_ALPHA_AVANTI" = "y" \
 	-o "$CONFIG_ALPHA_EB64P" = "y" -o "$CONFIG_ALPHA_JENSEN" = "y" \
Index: arch/alpha/defconfig
===================================================================
RCS file: /root/21REP/linux21/arch/alpha/defconfig,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.4.1
diff -u -r1.1.1.2 -r1.1.1.2.4.1
--- defconfig	1999/01/18 19:10:09	1.1.1.2
+++ defconfig	1999/01/31 23:15:37	1.1.1.2.4.1
@@ -55,6 +55,9 @@
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
 CONFIG_BINFMT_EM86=y
+CONFIG_NTP=y
+# CONFIG_NTP_PPS is not set
+# CONFIG_NTP_PPS_SERIAL is not set
 # CONFIG_PARPORT is not set
 
 #
Index: arch/alpha/kernel/time.c
===================================================================
RCS file: /root/21REP/linux21/arch/alpha/kernel/time.c,v
retrieving revision 1.1.1.3
retrieving revision 1.1.1.3.4.1
diff -u -r1.1.1.3 -r1.1.1.3.4.1
--- time.c	1999/01/22 18:45:37	1.1.1.3
+++ time.c	1999/01/31 23:15:44	1.1.1.3.4.1
@@ -109,6 +109,7 @@
 		nticks--;
 	}
 
+#ifdef CONFIG_NTP
 	/*
 	 * If we have an externally synchronized Linux clock, then update
 	 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
@@ -121,6 +122,7 @@
 		int tmp = set_rtc_mmss(xtime.tv_sec);
 		state.last_rtc_update = xtime.tv_sec - (tmp ? 600 : 0);
 	}
+#endif
 }
 
 /*
@@ -356,10 +358,12 @@
 	cli();
 	xtime = *tv;
 	time_adjust = 0;		/* stop active adjtime() */
+#ifdef CONFIG_NTP
 	time_status |= STA_UNSYNC;
 	time_state = TIME_ERROR;	/* p. 24, (a) */
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
+#endif
 	sti();
 }
 
@@ -393,6 +397,7 @@
 	if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD)
 		BCD_TO_BIN(cmos_minutes);
 
+#ifdef CONFIG_NTP
 	/*
 	 * since we're only adjusting minutes and seconds,
 	 * don't interfere with hour overflow. This avoids
Index: arch/arm/config.in
===================================================================
RCS file: /root/21REP/linux21/arch/arm/config.in,v
retrieving revision 1.1.1.3
retrieving revision 1.1.1.3.4.1
diff -u -r1.1.1.3 -r1.1.1.3.4.1
--- config.in	1999/01/22 18:45:40	1.1.1.3
+++ config.in	1999/01/31 23:15:48	1.1.1.3.4.1
@@ -68,6 +68,10 @@
   define_bool CONFIG_CPU_32 y
   define_bool CONFIG_CPU_26 n
 fi
+bool 'NTP kernel support' CONFIG_NTP
+if [ "$CONFIG_NTP" != "n" ]; then
+  bool '   NTP PPS support' CONFIG_NTP_PPS
+fi
 
 # Now allow the user to choose a more precise CPU.  This is only used to set
 # the flags we pass to GCC, not in any code.
Index: arch/arm/defconfig
===================================================================
RCS file: /root/21REP/linux21/arch/arm/defconfig,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.4.1
diff -u -r1.1.1.1 -r1.1.1.1.4.1
--- defconfig	1998/08/05 06:42:22	1.1.1.1
+++ defconfig	1999/01/31 23:15:50	1.1.1.1.4.1
@@ -38,6 +38,9 @@
 CONFIG_BINFMT_AOUT=y
 CONFIG_BINFMT_ELF=m
 # CONFIG_BINFMT_JAVA is not set
+CONFIG_NTP=y
+# CONFIG_NTP_PPS is not set
+# CONFIG_NTP_PPS_SERIAL is not set
 CONFIG_PARPORT=y
 CONFIG_PARPORT_PC=y
 
Index: arch/arm/kernel/time.c
===================================================================
RCS file: /root/21REP/linux21/arch/arm/kernel/time.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.4.1
diff -u -r1.1.1.2 -r1.1.1.2.4.1
--- time.c	1999/01/22 18:45:42	1.1.1.2
+++ time.c	1999/01/31 23:15:56	1.1.1.2.4.1
@@ -93,6 +93,7 @@
 	*tv = xtime;
 	tv->tv_usec += do_gettimeoffset();
 
+#ifdef CONFIG_NTP
 	/*
 	 * xtime is atomically updated in timer_bh. lost_ticks is
 	 * nonzero if the tiemr bottom half hasnt executed yet.
@@ -126,10 +127,12 @@
 
 	xtime = *tv;
 	time_adjust = 0;		/* stop active adjtime() */
+#ifdef CONFIG_NTP
 	time_status |= STA_UNSYNC;
 	time_state = TIME_ERROR;	/* p. 24, (a) */
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
+#endif
 	sti ();
 }
 
Index: arch/i386/config.in
===================================================================
RCS file: /root/21REP/linux21/arch/i386/config.in,v
retrieving revision 1.1.1.4
retrieving revision 1.1.1.4.4.1
diff -u -r1.1.1.4 -r1.1.1.4.4.1
--- config.in	1999/01/22 18:45:44	1.1.1.4
+++ config.in	1999/01/31 23:16:03	1.1.1.4.4.1
@@ -90,6 +90,10 @@
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
   tristate 'Kernel support for JAVA binaries (obsolete)' CONFIG_BINFMT_JAVA
 fi
+bool 'NTP kernel support' CONFIG_NTP
+if [ "$CONFIG_NTP" != "n" ]; then
+  bool '   NTP PPS support' CONFIG_NTP_PPS
+fi
 
 tristate 'Parallel port support' CONFIG_PARPORT
 if [ "$CONFIG_PARPORT" != "n" ]; then
Index: arch/i386/defconfig
===================================================================
RCS file: /root/21REP/linux21/arch/i386/defconfig,v
retrieving revision 1.1.1.4
retrieving revision 1.1.1.4.4.1
diff -u -r1.1.1.4 -r1.1.1.4.4.1
--- defconfig	1999/01/22 18:45:45	1.1.1.4
+++ defconfig	1999/01/31 23:16:04	1.1.1.4.4.1
@@ -54,6 +54,9 @@
 CONFIG_BINFMT_AOUT=y
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=y
+CONFIG_NTP=y
+# CONFIG_NTP_PPS is not set
+# CONFIG_NTP_PPS_SERIAL is not set
 # CONFIG_PARPORT is not set
 # CONFIG_APM is not set
 
Index: arch/i386/kernel/time.c
===================================================================
RCS file: /root/21REP/linux21/arch/i386/kernel/time.c,v
retrieving revision 1.1.1.4
retrieving revision 1.1.1.4.4.1
diff -u -r1.1.1.4 -r1.1.1.4.4.1
--- time.c	1999/01/22 18:45:59	1.1.1.4
+++ time.c	1999/01/31 23:16:11	1.1.1.4.4.1
@@ -291,10 +291,12 @@
 
 	xtime = *tv;
 	time_adjust = 0;		/* stop active adjtime() */
+#ifdef CONFIG_NTP
 	time_status |= STA_UNSYNC;
 	time_state = TIME_ERROR;	/* p. 24, (a) */
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
+#endif
 	write_unlock_irq(&xtime_lock);
 }
 
@@ -390,6 +392,7 @@
 		smp_local_timer_interrupt(regs);
 #endif
 
+#ifdef CONFIG_NTP
 	/*
 	 * If we have an externally synchronized Linux clock, then update
 	 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
@@ -404,6 +407,7 @@
 		else
 			last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
 	}
+#endif
 	    
 #ifdef CONFIG_MCA
 	if( MCA_bus ) {
Index: arch/m68k/config.in
===================================================================
RCS file: /root/21REP/linux21/arch/m68k/config.in,v
retrieving revision 1.1.1.4
retrieving revision 1.1.1.4.4.1
diff -u -r1.1.1.4 -r1.1.1.4.4.1
--- config.in	1999/01/22 18:46:05	1.1.1.4
+++ config.in	1999/01/31 23:16:21	1.1.1.4.4.1
@@ -101,6 +101,10 @@
 if [ "$CONFIG_NET" = "y" ]; then
   source net/Config.in
 fi
+bool 'NTP kernel support' CONFIG_NTP
+if [ "$CONFIG_NTP" != "n" ]; then
+  bool '   NTP PPS support' CONFIG_NTP_PPS
+fi
 
 mainmenu_option next_comment
 comment 'SCSI support'
Index: arch/m68k/defconfig
===================================================================
RCS file: /root/21REP/linux21/arch/m68k/defconfig,v
retrieving revision 1.1.1.3
retrieving revision 1.1.1.3.4.1
diff -u -r1.1.1.3 -r1.1.1.3.4.1
--- defconfig	1999/01/22 18:46:06	1.1.1.3
+++ defconfig	1999/01/31 23:16:22	1.1.1.3.4.1
@@ -40,6 +40,9 @@
 CONFIG_SYSCTL=y
 CONFIG_BINFMT_AOUT=y
 CONFIG_BINFMT_ELF=y
+CONFIG_NTP=y
+# CONFIG_NTP_PPS is not set
+# CONFIG_NTP_PPS_SERIAL is not set
 CONFIG_ZORRO=y
 # CONFIG_AMIGA_GSP is not set
 # CONFIG_GSP_RESOLVER is not set
Index: arch/m68k/kernel/time.c
===================================================================
RCS file: /root/21REP/linux21/arch/m68k/kernel/time.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.4.1
diff -u -r1.1.1.2 -r1.1.1.2.4.1
--- time.c	1999/01/22 18:46:28	1.1.1.2
+++ time.c	1999/01/31 23:16:32	1.1.1.2.4.1
@@ -63,6 +63,7 @@
 	if (!user_mode(regs))
 		do_profile(regs->pc);
 
+#ifdef CONFIG_NTP
 	/*
 	 * If we have an externally synchronized Linux clock, then update
 	 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
@@ -77,6 +78,7 @@
 	  else
 	    last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
 	}
+#endif
 #ifdef CONFIG_HEARTBEAT
 	/* use power LED as a heartbeat instead -- much more useful
 	   for debugging -- based on the version for PReP by Cort */
@@ -197,9 +199,11 @@
 
 	xtime = *tv;
 	time_adjust = 0;		/* stop active adjtime() */
+#ifdef CONFIG_NTP
 	time_status |= STA_UNSYNC;
 	time_state = TIME_ERROR;	/* p. 24, (a) */
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
+#endif
 	sti();
 }
Index: arch/mips/config.in
===================================================================
RCS file: /root/21REP/linux21/arch/mips/config.in,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.4.1
diff -u -r1.1.1.2 -r1.1.1.2.4.1
--- config.in	1999/01/22 18:46:37	1.1.1.2
+++ config.in	1999/01/31 23:16:37	1.1.1.2.4.1
@@ -98,6 +98,10 @@
   bool 'Set version information on all symbols for modules' CONFIG_MODVERSIONS
   bool 'Kernel module loader' CONFIG_KMOD
 fi
+bool 'NTP kernel support' CONFIG_NTP
+if [ "$CONFIG_NTP" != "n" ]; then
+  bool '   NTP PPS support' CONFIG_NTP_PPS
+fi
 
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
   bool 'Support for frame buffer devices (EXPERIMENTAL)' CONFIG_FB
Index: arch/mips/defconfig
===================================================================
RCS file: /root/21REP/linux21/arch/mips/defconfig,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.4.1
diff -u -r1.1.1.1 -r1.1.1.1.4.1
--- defconfig	1998/10/20 20:52:54	1.1.1.1
+++ defconfig	1999/01/31 23:16:38	1.1.1.1.4.1
@@ -39,6 +39,9 @@
 # CONFIG_BINFMT_AOUT is not set
 CONFIG_BINFMT_ELF=y
 # CONFIG_BINFMT_MISC is not set
+CONFIG_NTP=y
+# CONFIG_NTP_PPS is not set
+# CONFIG_NTP_PPS_SERIAL is not set
 CONFIG_NET=y
 CONFIG_SYSVIPC=y
 # CONFIG_BSD_PROCESS_ACCT is not set
Index: arch/mips/kernel/time.c
===================================================================
RCS file: /root/21REP/linux21/arch/mips/kernel/time.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.4.1
diff -u -r1.1.1.2 -r1.1.1.2.4.1
--- time.c	1999/01/22 18:46:40	1.1.1.2
+++ time.c	1999/01/31 23:16:49	1.1.1.2.4.1
@@ -259,10 +259,12 @@
 
 	xtime = *tv;
 	time_adjust = 0;		/* stop active adjtime() */
+#ifdef CONFIG_NTP
 	time_status |= STA_UNSYNC;
 	time_state = TIME_ERROR;	/* p. 24, (a) */
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
+#endif
 	sti();
 }
 
@@ -343,6 +345,7 @@
 {
 	do_timer(regs);
 
+#ifdef CONFIG_NTP
 	/*
 	 * If we have an externally synchronized Linux clock, then update
 	 * CMOS clock accordingly every ~11 minutes. Set_rtc_mmss() has to be
@@ -356,6 +359,7 @@
 	    last_rtc_update = xtime.tv_sec;
 	  else
 	    last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
+#endif
 	/* As we return to user mode fire off the other CPU schedulers.. this is 
 	   basically because we don't yet share IRQ's around. This message is
 	   rigged to be safe on the 386 - basically it's a hack, so don't look
@@ -367,6 +371,7 @@
 {
 	unsigned int count;
 
+#ifdef CONFIG_NTP
 	/*
 	 * The cycle counter is only 32 bit which is good for about
 	 * a minute at current count rates of upto 150MHz or so.
Index: arch/ppc/config.in
===================================================================
RCS file: /root/21REP/linux21/arch/ppc/config.in,v
retrieving revision 1.1.1.3
retrieving revision 1.1.1.3.4.1
diff -u -r1.1.1.3 -r1.1.1.3.4.1
--- config.in	1999/01/22 18:46:43	1.1.1.3
+++ config.in	1999/01/31 23:16:57	1.1.1.3.4.1
@@ -77,6 +77,10 @@
 if [ "$CONFIG_FB" = "y" ]; then
   bool 'Backward compatibility mode for Xpmac' CONFIG_FB_COMPAT_XPMAC
 fi
+bool 'NTP kernel support' CONFIG_NTP
+if [ "$CONFIG_NTP" != "n" ]; then
+  bool '   NTP PPS support' CONFIG_NTP_PPS
+fi
 
 bool 'Power management support for PowerBook 3400/2400' CONFIG_PMAC_PBOOK
 bool 'Support for PowerMac keyboard' CONFIG_MAC_KEYBOARD
Index: arch/ppc/defconfig
===================================================================
RCS file: /root/21REP/linux21/arch/ppc/defconfig,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.4.1
diff -u -r1.1.1.2 -r1.1.1.2.4.1
--- defconfig	1999/01/18 19:11:36	1.1.1.2
+++ defconfig	1999/01/31 23:16:58	1.1.1.2.4.1
@@ -35,6 +35,9 @@
 CONFIG_KERNEL_ELF=y
 CONFIG_BINFMT_MISC=m
 # CONFIG_BINFMT_JAVA is not set
+CONFIG_NTP=y
+# CONFIG_NTP_PPS is not set
+# CONFIG_NTP_PPS_SERIAL is not set
 # CONFIG_PARPORT is not set
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_FB=y
Index: arch/ppc/kernel/time.c
===================================================================
RCS file: /root/21REP/linux21/arch/ppc/kernel/time.c,v
retrieving revision 1.1.1.4
retrieving revision 1.1.1.4.4.1
diff -u -r1.1.1.4 -r1.1.1.4.4.1
--- time.c	1999/01/22 18:46:48	1.1.1.4
+++ time.c	1999/01/31 23:17:03	1.1.1.4.4.1
@@ -199,10 +199,12 @@
 	xtime.tv_usec = tv->tv_usec - frac_tick;
 	set_dec(frac_tick * count_period_den / count_period_num);
 	time_adjust = 0;		/* stop active adjtime() */
+#ifdef CONFIG_NTP
 	time_status |= STA_UNSYNC;
 	time_state = TIME_ERROR;	/* p. 24, (a) */
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
+#endif
 	restore_flags(flags);
 }
 
Index: arch/sparc/config.in
===================================================================
RCS file: /root/21REP/linux21/arch/sparc/config.in,v
retrieving revision 1.1.1.3
retrieving revision 1.1.1.3.4.1
diff -u -r1.1.1.3 -r1.1.1.3.4.1
--- config.in	1999/01/22 18:46:51	1.1.1.3
+++ config.in	1999/01/31 23:17:08	1.1.1.3.4.1
@@ -89,6 +89,10 @@
   tristate '   RAID-1 (mirroring) mode' CONFIG_MD_MIRRORING
   tristate '   RAID-4/RAID-5 mode' CONFIG_MD_RAID5
 fi
+bool 'NTP kernel support' CONFIG_NTP
+if [ "$CONFIG_NTP" != "n" ]; then
+  bool '   NTP PPS support' CONFIG_NTP_PPS
+fi
 
 tristate 'RAM disk support' CONFIG_BLK_DEV_RAM
 if [ "$CONFIG_BLK_DEV_RAM" = "y" ]; then
Index: arch/sparc/defconfig
===================================================================
RCS file: /root/21REP/linux21/arch/sparc/defconfig,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.4.1
diff -u -r1.1.1.2 -r1.1.1.2.4.1
--- defconfig	1999/01/08 19:05:45	1.1.1.2
+++ defconfig	1999/01/31 23:17:09	1.1.1.2.4.1
@@ -80,6 +80,9 @@
 CONFIG_BINFMT_ELF=y
 CONFIG_BINFMT_MISC=m
 CONFIG_BINFMT_JAVA=m
+CONFIG_NTP=y
+# CONFIG_NTP_PPS is not set
+# CONFIG_NTP_PPS_SERIAL is not set
 
 #
 # Floppy, IDE, and other block devices
Index: arch/sparc/kernel/time.c
===================================================================
RCS file: /root/21REP/linux21/arch/sparc/kernel/time.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.4.1
diff -u -r1.1.1.2 -r1.1.1.2.4.1
--- time.c	1999/01/22 18:46:53	1.1.1.2
+++ time.c	1999/01/31 23:17:15	1.1.1.2.4.1
@@ -91,6 +91,7 @@
 
 	do_timer(regs);
 
+#ifdef CONFIG_NTP
 	/* Determine when to update the Mostek clock. */
 	if ((time_status & STA_UNSYNC) == 0 &&
 	    xtime.tv_sec > last_rtc_update + 660 &&
@@ -101,6 +102,7 @@
 	  else
 	    last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */
 	}
+#endif
 }
 
 /* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
@@ -500,10 +502,12 @@
 #endif
 	xtime = *tv;
 	time_adjust = 0;		/* stop active adjtime() */
+#ifdef CONFIG_NTP
 	time_status |= STA_UNSYNC;
 	time_state = TIME_ERROR;	/* p. 24, (a) */
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
+#endif
 	sti();
 }
 
Index: arch/sparc64/config.in
===================================================================
RCS file: /root/21REP/linux21/arch/sparc64/config.in,v
retrieving revision 1.1.1.3
retrieving revision 1.1.1.3.4.1
diff -u -r1.1.1.3 -r1.1.1.3.4.1
--- config.in	1999/01/22 18:46:59	1.1.1.3
+++ config.in	1999/01/31 23:17:21	1.1.1.3.4.1
@@ -78,6 +78,10 @@
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
   tristate 'Solaris binary emulation' CONFIG_SOLARIS_EMUL
 fi
+bool 'NTP kernel support' CONFIG_NTP
+if [ "$CONFIG_NTP" != "n" ]; then
+  bool '   NTP PPS support' CONFIG_NTP_PPS
+fi
 
 if [ "$CONFIG_PCI" = "y" ]; then
   tristate 'Parallel port support' CONFIG_PARPORT
Index: arch/sparc64/defconfig
===================================================================
RCS file: /root/21REP/linux21/arch/sparc64/defconfig,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.4.1
diff -u -r1.1.1.2 -r1.1.1.2.4.1
--- defconfig	1999/01/08 19:05:45	1.1.1.2
+++ defconfig	1999/01/31 23:17:22	1.1.1.2.4.1
@@ -89,6 +89,9 @@
 CONFIG_BINFMT_MISC=m
 CONFIG_BINFMT_JAVA=m
 CONFIG_SOLARIS_EMUL=m
+CONFIG_NTP=y
+# CONFIG_NTP_PPS is not set
+# CONFIG_NTP_PPS_SERIAL is not set
 CONFIG_PARPORT=m
 CONFIG_PARPORT_AX=m
 CONFIG_PARPORT_LOWLEVEL_MODULE=y
Index: arch/sparc64/kernel/time.c
===================================================================
RCS file: /root/21REP/linux21/arch/sparc64/kernel/time.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.4.1
diff -u -r1.1.1.2 -r1.1.1.2.4.1
--- time.c	1999/01/22 18:47:02	1.1.1.2
+++ time.c	1999/01/31 23:17:27	1.1.1.2.4.1
@@ -53,6 +53,7 @@
 	static long last_rtc_update=0;
 
 	/* Determine when to update the Mostek clock. */
+#ifdef CONFIG_NTP
 	if ((time_status & STA_UNSYNC) == 0 &&
 	    xtime.tv_sec > last_rtc_update + 660 &&
 	    xtime.tv_usec >= 500000 - ((unsigned) tick) / 2 &&
@@ -63,6 +64,7 @@
 			last_rtc_update = xtime.tv_sec - 600;
 			/* do it again in 60 s */
 	}
+#endif
 }
 
 static void timer_interrupt(int irq, void *dev_id, struct pt_regs * regs)
@@ -460,10 +462,12 @@
 
 	xtime = *tv;
 	time_adjust = 0;		/* stop active adjtime() */
+#ifdef CONFIG_NTP
 	time_status |= STA_UNSYNC;
 	time_state = TIME_ERROR;	/* p. 24, (a) */
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
+#endif
 	sti();
 }
 
@@ -500,6 +504,5 @@
 		regs->creg &= ~MSTK_CREG_WRITE;
 	} else
 		return -1;
-
 	return 0;
 }
Index: drivers/char/Config.in
===================================================================
RCS file: /root/21REP/linux21/drivers/char/Config.in,v
retrieving revision 1.1.1.3
retrieving revision 1.1.1.3.4.2
diff -u -r1.1.1.3 -r1.1.1.3.4.2
--- Config.in	1999/01/18 19:13:00	1.1.1.3
+++ Config.in	1999/01/31 23:17:48	1.1.1.3.4.2
@@ -12,6 +12,13 @@
 if [ "$CONFIG_SERIAL" = "y" ]; then
    bool '   Support for console on serial port' CONFIG_SERIAL_CONSOLE
 fi
+if [ "$CONFIG_SERIAL" != "n" ]; then
+   if [ "$CONFIG_NTP" = "y" -a "$CONFIG_NTP_PPS" = "y" ]; then
+      if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+	 bool '   NTP PPS support on serial port' CONFIG_NTP_PPS_SERIAL
+      fi
+   fi
+fi
 bool 'Extended dumb serial driver options' CONFIG_SERIAL_EXTENDED
 if [ "$CONFIG_SERIAL_EXTENDED" = "y" ]; then
    bool '   Support more than 4 serial ports' CONFIG_SERIAL_MANY_PORTS
Index: drivers/char/n_tty.c
===================================================================
RCS file: /root/21REP/linux21/drivers/char/n_tty.c,v
retrieving revision 1.1.1.3
retrieving revision 1.1.1.3.4.2
diff -u -r1.1.1.3 -r1.1.1.3.4.2
--- n_tty.c	1999/01/22 18:47:44	1.1.1.3
+++ n_tty.c	1999/01/31 23:17:49	1.1.1.3.4.2
@@ -1161,3 +1161,27 @@
 	0			/* write_wakeup */
 };
 
+#ifdef	CONFIG_NTP_PPS
+	/* OK, I found this too late: That hack is most likely wrong, but
+	 * it should be better than the previous versions. XXX FIXME!
+	 * (Any help appreciated -- U. Windl)
+	 */
+struct tty_ldisc tty_ldisc_N_PPSCLOCK = {
+	TTY_LDISC_MAGIC,	/* magic */
+	"n_PPSclock",		/* name */
+	0,			/* num */
+	0,			/* flags */
+	n_tty_open,		/* open */
+	n_tty_close,		/* close */
+	n_tty_flush_buffer,	/* flush_buffer */
+	n_tty_chars_in_buffer,	/* chars_in_buffer */
+	read_chan,		/* read */
+	write_chan,		/* write */
+	n_tty_ioctl,		/* ioctl */
+	n_tty_set_termios,	/* set_termios */
+	normal_poll,		/* poll */
+	n_tty_receive_buf,	/* receive_buf */
+	n_tty_receive_room,	/* receive_room */
+	0			/* write_wakeup */
+};
+#endif
Index: drivers/char/serial.c
===================================================================
RCS file: /root/21REP/linux21/drivers/char/serial.c,v
retrieving revision 1.1.1.4
retrieving revision 1.1.1.4.4.3
diff -u -r1.1.1.4 -r1.1.1.4.4.3
--- serial.c	1999/01/22 18:47:45	1.1.1.4
+++ serial.c	1999/02/02 21:34:32	1.1.1.4.4.3
@@ -32,6 +32,9 @@
  *  4/98: Added changes to support the ARM architecture proposed by
  * 	  Russell King
  *
+ *  1/99: Additions for NTP PPS pulse on CD by Ulrich Windl (with
+ *	  contributions by H. P. Anvin)
+ *
  * This module exports the following rs232 io functions:
  *
  *	int rs_init(void);
@@ -149,12 +152,19 @@
 #include <asm/bitops.h>
 #include <asm/serial.h>
 
+#ifdef	CONFIG_NTP_PPS_SERIAL
+#include <linux/time.h> 	/* struct timeval, do_gettimeofday(),
+				   hardware_pps() */
+#include <linux/ppsclock.h>	/* CIOGETEV, struct ppsclockev, etc. */
+#include <linux/malloc.h>	/* kmalloc(), kfree() */
+#endif
+
 #ifdef SERIAL_INLINE
 #define _INLINE_ inline
 #endif
 	
 static char *serial_name = "Serial driver";
-static char *serial_version = "4.27";
+static char *serial_version = "4.27+";
 
 static DECLARE_TASK_QUEUE(tq_serial);
 
@@ -498,6 +508,30 @@
 	}
 }
 
+#ifdef	CONFIG_NTP_PPS_SERIAL
+/* store the time of the event and increment the counter to indicate
+ * a new event
+ */
+static inline void get_pps_event(struct async_struct *info,
+				 struct timeval const *tvp)
+{
+	struct tty_struct const	*const itp	= info->tty;
+	struct pps	*pp;
+
+	if (itp->termios->c_line == N_PPSCLOCK
+	    && (pp = (struct pps *) itp->disc_data) != NULL
+	    && pp->magic == PPSCLOCK_MAGIC)
+	{
+		pp->ev.tv = *tvp;
+		pp->ev.serial++;
+#ifdef DEBUG_NTP_PPS_SERIAL
+		printk(KERN_DEBUG "pps at %p has event #%u at %u.%06d\n",
+		       pp, pp->ev.serial, pp->ev.tv.tv_sec, pp->ev.tv.tv_usec);
+#endif /* DEBUG_NTP_PPS_SERIAL */
+	}
+}
+#endif
+
 static _INLINE_ void check_modem_status(struct async_struct *info)
 {
 	int	status;
@@ -514,11 +548,24 @@
 			icount->dsr++;
 		if (status & UART_MSR_DDCD) {
 			icount->dcd++;
-#ifdef CONFIG_HARD_PPS
-			if ((info->flags & ASYNC_HARDPPS_CD) &&
-			    (status & UART_MSR_DCD))
-				hardpps();
-#endif
+#ifdef CONFIG_NTP_PPS_SERIAL
+			if ((info->flags & (ASYNC_PPS_CD_POS|ASYNC_PPS_CD_NEG))
+			    && (!(status & UART_MSR_DCD) ==
+				!(info->flags & ASYNC_PPS_CD_POS))) {
+				struct timeval	now;
+
+				do_gettimeofday(&now);
+				/* processing time between level change and
+				 * execution of do_gettimeoffset() in
+				 * microseconds
+				 * [I assume "interrupts disabled"; right?]
+				 */
+#define	DELAY_COMPENSATION	0	/* [us] I don't know yet */
+				now.tv_usec -= DELAY_COMPENSATION;
+				hardware_pps(&now);
+				get_pps_event(info, &now);
+			}
+#endif /* CONFIG_NTP_PPS_SERIAL */
 		}
 		if (status & UART_MSR_DCTS)
 			icount->cts++;
@@ -1322,8 +1369,10 @@
 	
 	/* CTS flow control flag and modem status interrupts */
 	info->IER &= ~UART_IER_MSI;
-	if (info->flags & ASYNC_HARDPPS_CD)
+#ifdef CONFIG_NTP_PPS_SERIAL
+	if (info->flags & (ASYNC_PPS_CD_POS|ASYNC_PPS_CD_NEG))
 		info->IER |= UART_IER_MSI;
+#endif /* CONFIG_NTP_PPS_SERIAL */
 	if (cflag & CRTSCTS) {
 		info->flags |= ASYNC_CTS_FLOW;
 		info->IER |= UART_IER_MSI;
@@ -2026,6 +2075,32 @@
 }
 #endif
 
+#ifdef	CONFIG_NTP_PPS_SERIAL
+static int get_ppsclockev(struct tty_struct *tty, struct ppsclockev *to_pps, 
+			  struct ppsclockev *from_pps, int size)
+{
+	struct pps *pps;
+
+	if (tty->disc_data == NULL) { 
+		pps = tty->disc_data = (char *) kmalloc(sizeof(struct pps),
+							GFP_KERNEL);
+		if (tty->disc_data == NULL) {
+			printk(KERN_ERR "get_ppsclockev: kmalloc failed\n");
+			return -EINVAL;
+		} else {
+			pps->magic = PPSCLOCK_MAGIC;
+			tty->termios->c_line = N_PPSCLOCK;
+			from_pps = &pps->ev;
+			do_gettimeofday(&from_pps->tv);
+			from_pps->serial = 0;
+		}
+	} /* ldisc not initialized */
+	if (to_pps == NULL)
+		return -EINVAL;
+	return copy_to_user(to_pps, from_pps, size);
+}
+#endif /* CONFIG_NTP_PPS_SERIAL */
+
 static int rs_ioctl(struct tty_struct *tty, struct file * file,
 		    unsigned int cmd, unsigned long arg)
 {
@@ -2151,6 +2226,19 @@
 			/* "setserial -W" is called in Debian boot */
 			printk ("TIOCSER?WILD ioctl obsolete, ignored.\n");
 			return 0;
+#ifdef	CONFIG_NTP_PPS_SERIAL
+		case CIOGETEV:
+		{
+			struct ppsclockev *ev = NULL;
+			int	i;
+
+			if ( tty->disc_data != NULL )
+				ev = &(((struct pps *) (tty->disc_data))->ev);
+			i = get_ppsclockev(tty, (struct ppsclockev *) arg, 
+					   ev, sizeof(struct ppsclockev));
+			return i;
+		}
+#endif /* CONFIG_NTP_PPS_SERIAL */
 
 		default:
 			return -ENOIOCTLCMD;
@@ -2407,6 +2495,17 @@
 	info->event = 0;
 	state->count = 0;
 	info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CALLOUT_ACTIVE);
+#ifdef CONFIG_NTP_PPS_SERIAL
+	if (info->tty->disc_data != NULL
+	    && ((struct pps *)(info->tty->disc_data))->magic == PPSCLOCK_MAGIC)
+	{
+		void *tmp = info->tty->disc_data;
+		((struct pps *) tmp)->magic = 0;
+		info->tty->disc_data = NULL;
+		info->tty->termios->c_line = N_TTY;
+		kfree(tmp);
+	}
+#endif /* CONFIG_NTP_PPS_SERIAL */
 	info->tty = 0;
 	wake_up_interruptible(&info->open_wait);
 }
@@ -2811,32 +2910,34 @@
  */
 static _INLINE_ void show_serial_version(void)
 {
- 	printk(KERN_INFO "%s version %s with", serial_name, serial_version);
+ 	printk(KERN_INFO "%s version %s with%s",
+	       serial_name, serial_version,
+
 #ifdef CONFIG_HUB6
-	printk(" HUB-6");
+	       " HUB-6"
 #define SERIAL_OPT
 #endif
-#ifdef CONFIG_SERIAL_MANY_PORTS
-	printk(" MANY_PORTS");
-#define SERIAL_OPT
-#endif
 #ifdef CONFIG_SERIAL_MULTIPORT
-	printk(" MULTIPORT");
+	       " MULTIPORT"
 #define SERIAL_OPT
 #endif
 #ifdef CONFIG_SERIAL_SHARE_IRQ
-	printk(" SHARE_IRQ");
+	       " SHARE_IRQ"
 #define SERIAL_OPT
 #endif
 #ifdef CONFIG_SERIAL_DETECT_IRQ
-	printk(" DETECT_IRQ");
+	       " DETECT_IRQ"
 #define SERIAL_OPT
 #endif
-#ifdef SERIAL_OPT
-	printk(" enabled\n");
-#else
-	printk(" no serial options enabled\n");
+#ifdef CONFIG_NTP_PPS_SERIAL
+	       " PPS"
+#define SERIAL_OPT
+#endif
+
+#ifndef SERIAL_OPT
+	       " no options"
 #endif
+	       " enabled\n");
 #undef SERIAL_OPT
 }
 
@@ -3235,7 +3336,8 @@
 	state = &rs_table[i];
 	if (rs_table[i].count) {
 		restore_flags(flags);
-		printk("Couldn't configure serial #%d (port=%d,irq=%d): "
+		printk(KERN_ERR
+		       "Couldn't configure serial #%d (port=%d,irq=%d): "
 		       "device already open\n", i, req->port, req->irq);
 		return -1;
 	}
@@ -3246,7 +3348,7 @@
 	autoconfig(state);
 	if (state->type == PORT_UNKNOWN) {
 		restore_flags(flags);
-		printk("register_serial(): autoconfig failed\n");
+		printk(KERN_ERR "register_serial(): autoconfig failed\n");
 		return -1;
 	}
 	restore_flags(flags);
@@ -3294,10 +3396,12 @@
 	timer_table[RS_TIMER].expires = 0;
         remove_bh(SERIAL_BH);
 	if ((e1 = tty_unregister_driver(&serial_driver)))
-		printk("SERIAL: failed to unregister serial driver (%d)\n",
+		printk(KERN_WARNING
+		       "SERIAL: failed to unregister serial driver (%d)\n",
 		       e1);
 	if ((e2 = tty_unregister_driver(&callout_driver)))
-		printk("SERIAL: failed to unregister callout driver (%d)\n", 
+		printk(KERN_WARNING
+		       "SERIAL: failed to unregister callout driver (%d)\n", 
 		       e2);
 	restore_flags(flags);
 
Index: drivers/char/tty_io.c
===================================================================
RCS file: /root/21REP/linux21/drivers/char/tty_io.c,v
retrieving revision 1.1.1.3
retrieving revision 1.1.1.3.4.2
diff -u -r1.1.1.3 -r1.1.1.3.4.2
--- tty_io.c	1999/01/22 18:47:52	1.1.1.3
+++ tty_io.c	1999/01/31 23:17:52	1.1.1.3.4.2
@@ -2014,7 +2014,6 @@
 	return 0;
 }
 
-
 /*
  * Initialize the console device. This is called *early*, so
  * we can't necessarily depend on lots of kernel help here.
@@ -2026,6 +2025,9 @@
 	/* Setup the default TTY line discipline. */
 	memset(ldiscs, 0, sizeof(ldiscs));
 	(void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);
+#ifdef	CONFIG_NTP_PPS
+	(void) tty_register_ldisc(N_PPSCLOCK, &tty_ldisc_N_PPSCLOCK);
+#endif
 
 	/*
 	 * Set up the standard termios.  Individual tty drivers may 
Index: include/asm-alpha/ioctls.h
===================================================================
RCS file: /root/21REP/linux21/include/asm-alpha/ioctls.h,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.4.1
diff -u -r1.1.1.1 -r1.1.1.1.4.1
--- ioctls.h	1998/02/13 00:25:04	1.1.1.1
+++ ioctls.h	1999/01/31 14:22:40	1.1.1.1.4.1
@@ -103,5 +103,6 @@
 
 #define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
 #define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
+#define CIOGETEV	0x5460  /* for N_PPSCLOCK line discipline */
 
 #endif /* _ASM_ALPHA_IOCTLS_H */
Index: include/asm-alpha/termios.h
===================================================================
RCS file: /root/21REP/linux21/include/asm-alpha/termios.h,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.4.1
diff -u -r1.1.1.2 -r1.1.1.2.4.1
--- termios.h	1999/01/08 19:06:05	1.1.1.2
+++ termios.h	1999/01/31 14:22:41	1.1.1.2.4.1
@@ -71,6 +71,7 @@
 #define N_SLIP		1
 #define N_MOUSE		2
 #define N_PPP		3
+/* N_STRIP on i386 */
 #define N_AX25		5
 #define N_X25		6	/* X.25 async */
 #define N_6PACK		7
@@ -79,6 +80,7 @@
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
 #define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
+#define	N_PPSCLOCK	13	/* pulse-per-second detection */
 
 #ifdef __KERNEL__
 /*	eof=^D		eol=\0		eol2=\0		erase=del
Index: include/asm-arm/ioctls.h
===================================================================
RCS file: /root/21REP/linux21/include/asm-arm/ioctls.h,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.4.1
diff -u -r1.1.1.1 -r1.1.1.1.4.1
--- ioctls.h	1998/02/13 00:25:04	1.1.1.1
+++ ioctls.h	1999/01/31 14:22:46	1.1.1.1.4.1
@@ -65,6 +65,7 @@
 
 #define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
 #define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
+#define CIOGETEV	0x5460  /* for N_PPSCLOCK line discipline */
 
 /* Used for packet mode */
 #define TIOCPKT_DATA		 0
Index: include/asm-arm/termios.h
===================================================================
RCS file: /root/21REP/linux21/include/asm-arm/termios.h,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.4.1
diff -u -r1.1.1.2 -r1.1.1.2.4.1
--- termios.h	1999/01/08 19:06:06	1.1.1.2
+++ termios.h	1999/01/31 14:22:47	1.1.1.2.4.1
@@ -60,6 +60,7 @@
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
 #define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
+#define	N_PPSCLOCK	13	/* pulse-per-second detection */
 
 #ifdef __KERNEL__
 
Index: include/asm-i386/ioctls.h
===================================================================
RCS file: /root/21REP/linux21/include/asm-i386/ioctls.h,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.4.1
diff -u -r1.1.1.1 -r1.1.1.1.4.1
--- ioctls.h	1998/07/24 18:10:16	1.1.1.1
+++ ioctls.h	1999/01/31 14:22:52	1.1.1.1.4.1
@@ -67,6 +67,7 @@
 #define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
 #define TIOCGHAYESESP   0x545E  /* Get Hayes ESP configuration */
 #define TIOCSHAYESESP   0x545F  /* Set Hayes ESP configuration */
+#define CIOGETEV	0x5460  /* for N_PPSCLOCK line discipline */
 
 /* Used for packet mode */
 #define TIOCPKT_DATA		 0
Index: include/asm-i386/termios.h
===================================================================
RCS file: /root/21REP/linux21/include/asm-i386/termios.h,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.4.1
diff -u -r1.1.1.2 -r1.1.1.2.4.1
--- termios.h	1999/01/08 19:06:06	1.1.1.2
+++ termios.h	1999/01/31 14:22:54	1.1.1.2.4.1
@@ -52,6 +52,7 @@
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
 #define N_IRDA		11	/* Linux IR - http://www.cs.uit.no/~dagb/irda/irda.html */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
+#define	N_PPSCLOCK	13	/* pulse-per-second detection */
 
 #ifdef __KERNEL__
 
Index: include/asm-m68k/ioctls.h
===================================================================
RCS file: /root/21REP/linux21/include/asm-m68k/ioctls.h,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.4.1
diff -u -r1.1.1.1 -r1.1.1.1.4.1
--- ioctls.h	1998/02/13 00:25:04	1.1.1.1
+++ ioctls.h	1999/01/31 14:22:59	1.1.1.1.4.1
@@ -65,6 +65,7 @@
 
 #define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
 #define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
+#define CIOGETEV	0x5460  /* for N_PPSCLOCK line discipline */
 
 /* Used for packet mode */
 #define TIOCPKT_DATA		 0
Index: include/asm-m68k/termios.h
===================================================================
RCS file: /root/21REP/linux21/include/asm-m68k/termios.h,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.4.1
diff -u -r1.1.1.2 -r1.1.1.2.4.1
--- termios.h	1999/01/08 19:06:06	1.1.1.2
+++ termios.h	1999/01/31 14:23:00	1.1.1.2.4.1
@@ -60,6 +60,7 @@
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
 #define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
+#define	N_PPSCLOCK	13	/* pulse-per-second detection */
 
 #ifdef __KERNEL__
 
Index: include/asm-mips/ioctls.h
===================================================================
RCS file: /root/21REP/linux21/include/asm-mips/ioctls.h,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.4.1
diff -u -r1.1.1.1 -r1.1.1.1.4.1
--- ioctls.h	1998/10/20 20:52:53	1.1.1.1
+++ ioctls.h	1999/01/31 14:23:13	1.1.1.1.4.1
@@ -28,6 +28,7 @@
 #define TCSETS		0x540e
 #define TCSETSW		0x540f
 #define TCSETSF		0x5410
+#define CIOGETEV	0x5460		/* for N_PPSCLOCK line discipline */
 
 #define TIOCEXCL	0x740d		/* set exclusive use of tty */
 #define TIOCNXCL	0x740e		/* reset exclusive use of tty */
Index: include/asm-mips/termios.h
===================================================================
RCS file: /root/21REP/linux21/include/asm-mips/termios.h,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.4.1
diff -u -r1.1.1.2 -r1.1.1.2.4.1
--- termios.h	1999/01/08 19:06:06	1.1.1.2
+++ termios.h	1999/01/31 14:23:14	1.1.1.2.4.1
@@ -98,6 +98,7 @@
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
 #define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
+#define	N_PPSCLOCK	13	/* pulse-per-second detection */
 
 #ifdef __KERNEL__
 
Index: include/asm-ppc/ioctls.h
===================================================================
RCS file: /root/21REP/linux21/include/asm-ppc/ioctls.h,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.4.1
diff -u -r1.1.1.1 -r1.1.1.1.4.1
--- ioctls.h	1998/02/13 00:25:04	1.1.1.1
+++ ioctls.h	1999/01/31 14:23:22	1.1.1.1.4.1
@@ -103,5 +103,6 @@
 
 #define TIOCMIWAIT	0x545C	/* wait for a change on serial input line(s) */
 #define TIOCGICOUNT	0x545D	/* read serial port inline interrupt counts */
+#define CIOGETEV	0x5460  /* for N_PPSCLOCK line discipline */
 
 #endif /* _ASM_PPC_IOCTLS_H */
Index: include/asm-ppc/termios.h
===================================================================
RCS file: /root/21REP/linux21/include/asm-ppc/termios.h,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.4.1
diff -u -r1.1.1.2 -r1.1.1.2.4.1
--- termios.h	1999/01/18 19:21:36	1.1.1.2
+++ termios.h	1999/01/31 14:23:23	1.1.1.2.4.1
@@ -184,6 +184,7 @@
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
 #define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
+#define	N_PPSCLOCK	13	/* pulse-per-second detection */
 
 #ifdef __KERNEL__
 
Index: include/asm-sparc/termios.h
===================================================================
RCS file: /root/21REP/linux21/include/asm-sparc/termios.h,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.4.1
diff -u -r1.1.1.2 -r1.1.1.2.4.1
--- termios.h	1999/01/08 19:06:06	1.1.1.2
+++ termios.h	1999/01/31 14:23:32	1.1.1.2.4.1
@@ -68,6 +68,7 @@
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
 #define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
+#define	N_PPSCLOCK	13	/* pulse-per-second detection */
 
 #ifdef __KERNEL__
 
Index: include/asm-sparc64/ioctls.h
===================================================================
RCS file: /root/21REP/linux21/include/asm-sparc64/ioctls.h,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.4.1
diff -u -r1.1.1.1 -r1.1.1.1.4.1
--- ioctls.h	1998/04/15 00:44:24	1.1.1.1
+++ ioctls.h	1999/01/31 14:23:39	1.1.1.1.4.1
@@ -111,6 +111,7 @@
 #define TIOCSERSETMULTI 0x545B /* Set multiport config */
 #define TIOCMIWAIT	0x545C /* Wait for change on serial input line(s) */
 #define TIOCGICOUNT	0x545D /* Read serial port inline interrupt counts */
+#define CIOGETEV	0x5460  /* for N_PPSCLOCK line discipline */
 
 /* Kernel definitions */
 #ifdef __KERNEL__
Index: include/asm-sparc64/termios.h
===================================================================
RCS file: /root/21REP/linux21/include/asm-sparc64/termios.h,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.4.1
diff -u -r1.1.1.2 -r1.1.1.2.4.1
--- termios.h	1999/01/08 19:06:06	1.1.1.2
+++ termios.h	1999/01/31 14:23:40	1.1.1.2.4.1
@@ -68,6 +68,7 @@
 #define N_PROFIBUS_FDL	10	/* Reserved for Profibus <Dave@mvhi.com> */
 #define N_IRDA		11	/* Linux IrDa - http://www.cs.uit.no/~dagb/irda/irda.html */
 #define N_SMSBLOCK	12	/* SMS block mode - for talking to GSM data cards about SMS messages */
+#define	N_PPSCLOCK	13	/* pulse-per-second detection */
 
 #ifdef __KERNEL__
 
Index: include/linux/sched.h
===================================================================
RCS file: /root/21REP/linux21/include/linux/sched.h,v
retrieving revision 1.1.1.3
retrieving revision 1.1.1.3.4.1
diff -u -r1.1.1.3 -r1.1.1.3.4.1
--- sched.h	1999/01/22 18:52:53	1.1.1.3
+++ sched.h	1999/02/02 21:34:44	1.1.1.3.4.1
@@ -1,6 +1,10 @@
 #ifndef _LINUX_SCHED_H
 #define _LINUX_SCHED_H
 
+/* 1999-02-02	Ulrich Windl
+ *	Moved time related stuff to <linux/time.h>
+ */
+
 #include <asm/param.h>	/* for HZ */
 
 extern unsigned long event;
@@ -10,8 +14,8 @@
 #include <linux/tasks.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
+#include <linux/time.h>
 #include <linux/times.h>
-#include <linux/timex.h>
 
 #include <asm/system.h>
 #include <asm/semaphore.h>
@@ -454,14 +458,11 @@
 extern unsigned long volatile jiffies;
 extern unsigned long itimer_ticks;
 extern unsigned long itimer_next;
-extern struct timeval xtime;
 extern void do_timer(struct pt_regs *);
 
 extern unsigned int * prof_buffer;
 extern unsigned long prof_len;
 extern unsigned long prof_shift;
-
-#define CURRENT_TIME (xtime.tv_sec)
 
 extern void FASTCALL(__wake_up(struct wait_queue ** p, unsigned int mode));
 extern void FASTCALL(sleep_on(struct wait_queue ** p));
Index: include/linux/serial.h
===================================================================
RCS file: /root/21REP/linux21/include/linux/serial.h,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.4.1
diff -u -r1.1.1.1 -r1.1.1.1.4.1
--- serial.h	1998/11/04 06:05:25	1.1.1.1
+++ serial.h	1999/01/31 14:23:49	1.1.1.1.4.1
@@ -80,14 +80,15 @@
 #define ASYNC_PGRP_LOCKOUT    0x0200 /* Lock out cua opens based on pgrp */
 #define ASYNC_CALLOUT_NOHUP   0x0400 /* Don't do hangups for cua device */
 
-#define ASYNC_HARDPPS_CD	0x0800	/* Call hardpps when CD goes high  */
+#define ASYNC_PPS_CD_POS	0x0800	/* Call hardpps when CD goes high  */
 
 #define ASYNC_SPD_SHI	0x1000	/* Use 230400 instead of 38400 bps */
 #define ASYNC_SPD_WARP	0x1010	/* Use 460800 instead of 38400 bps */
 
 #define ASYNC_LOW_LATENCY 0x2000 /* Request low latency behaviour */
 
-#define ASYNC_FLAGS	0x3FFF	/* Possible legal async flags */
+#define ASYNC_FLAGS	0x7FFF	/* Possible legal async flags */
+#define ASYNC_PPS_CD_NEG	0x4000	/* Call hardpps when CD goes low  */
 #define ASYNC_USR_MASK	0x3430	/* Legal flags that non-privileged
 				 * users can set or reset */
 
Index: include/linux/time.h
===================================================================
RCS file: /root/21REP/linux21/include/linux/time.h,v
retrieving revision 1.1.1.1
retrieving revision 1.1.1.1.4.3
diff -u -r1.1.1.1 -r1.1.1.1.4.3
--- time.h	1998/11/20 00:56:39	1.1.1.1
+++ time.h	1999/02/02 21:34:45	1.1.1.1.4.3
@@ -1,9 +1,23 @@
 #ifndef _LINUX_TIME_H
 #define _LINUX_TIME_H
 
+/* 1999-02-02	Ulrich Windl
+ *	Added time related stuff from <linux/sched.h>
+ */
 #include <asm/param.h>
+#include <asm/spinlock.h>
 #include <linux/types.h>
 
+struct timeval {
+	time_t		tv_sec;		/* seconds */
+	suseconds_t	tv_usec;	/* microseconds */
+};
+
+struct timezone {
+	int	tz_minuteswest;	/* minutes west of Greenwich */
+	int	tz_dsttime;	/* type of dst correction */
+};
+
 #ifndef _STRUCT_TIMESPEC
 #define _STRUCT_TIMESPEC
 struct timespec {
@@ -11,6 +25,7 @@
 	long	tv_nsec;	/* nanoseconds */
 };
 #endif /* _STRUCT_TIMESPEC */
+#include <linux/timex.h>
 
 /*
  * Change timeval to jiffies, trying to avoid the
@@ -46,23 +61,25 @@
 	value->tv_sec = jiffies / HZ;
 }
  
-struct timeval {
-	time_t		tv_sec;		/* seconds */
-	suseconds_t	tv_usec;	/* microseconds */
-};
-
-struct timezone {
-	int	tz_minuteswest;	/* minutes west of Greenwich */
-	int	tz_dsttime;	/* type of dst correction */
-};
-
 #define NFDBITS			__NFDBITS
 
 #ifdef __KERNEL__
+extern volatile struct timeval xtime;
+#define CURRENT_TIME (xtime.tv_sec)
+
+/*
+ * This spinlock protect us from races in SMP while playing with xtime. -arca
+ */
+extern rwlock_t xtime_lock;
+
+extern void update_wall_time(unsigned long ticks);
 extern void do_gettimeofday(struct timeval *tv);
 extern void do_settimeofday(struct timeval *tv);
 extern void get_fast_time(struct timeval *tv);
 extern void (*do_get_fast_time)(struct timeval *);
+#ifdef CONFIG_NTP_PPS	/* handle PPS pulse */
+extern void hardware_pps(const struct timeval *p_tv);
+#endif
 #endif
 
 #define FD_SETSIZE		__FD_SETSIZE
Index: include/linux/timex.h
===================================================================
RCS file: /root/21REP/linux21/include/linux/timex.h,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.4.1
diff -u -r1.1.1.2 -r1.1.1.2.4.1
--- timex.h	1999/01/22 18:52:56	1.1.1.2
+++ timex.h	1999/01/31 14:23:51	1.1.1.2.4.1
@@ -47,6 +47,8 @@
  *      kernel PLL updated to 1994-12-13 specs (rfc-1589)
  * 1997-08-30    Ulrich Windl
  *      Added new constant NTP_PHASE_LIMIT
+ * 1999-01-24    Ulrich Windl
+ *	Activated new field ``tickadj''
  */
 #ifndef _LINUX_TIMEX_H
 #define _LINUX_TIMEX_H
@@ -169,8 +171,9 @@
 	long stbcnt;            /* stability limit exceeded (ro) */
 
 	int  :32; int  :32; int  :32; int  :32;
+	int tickadj;		/* tickadj (rw) -- extension by UW */
+	int  :32; int  :32; int  :32;
 	int  :32; int  :32; int  :32; int  :32;
-	int  :32; int  :32; int  :32; int  :32;
 };
 
 /*
@@ -182,6 +185,7 @@
 #define ADJ_ESTERROR		0x0008	/* estimated time error */
 #define ADJ_STATUS		0x0010	/* clock status */
 #define ADJ_TIMECONST		0x0020	/* pll time constant */
+#define ADJ_TICKADJ		0x2000	/* tickadj value */
 #define ADJ_TICK		0x4000	/* tick value */
 #define ADJ_OFFSET_SINGLESHOT	0x8001	/* old-fashioned adjtime */
 
Index: include/linux/tty.h
===================================================================
RCS file: /root/21REP/linux21/include/linux/tty.h,v
retrieving revision 1.1.1.2
diff -u -r1.1.1.2 tty.h
--- tty.h	1999/01/18 19:22:25	1.1.1.2
+++ tty.h	1999/02/02 21:07:54
@@ -383,6 +383,9 @@
 
 /* n_tty.c */
 extern struct tty_ldisc tty_ldisc_N_TTY;
+#ifdef CONFIG_NTP_PPS
+extern struct tty_ldisc tty_ldisc_N_PPSCLOCK;
+#endif
 
 /* tty_ioctl.c */
 extern int n_tty_ioctl(struct tty_struct * tty, struct file * file,
Index: kernel/ksyms.c
===================================================================
RCS file: /root/21REP/linux21/kernel/ksyms.c,v
retrieving revision 1.1.1.4
retrieving revision 1.1.1.4.4.2
diff -u -r1.1.1.4 -r1.1.1.4.4.2
--- ksyms.c	1999/01/22 18:53:20	1.1.1.4
+++ ksyms.c	1999/01/31 23:18:23	1.1.1.4.4.2
@@ -310,6 +310,9 @@
 EXPORT_SYMBOL(jiffies);
 EXPORT_SYMBOL(xtime);
 EXPORT_SYMBOL(do_gettimeofday);
+#ifdef	CONFIG_NTP_PPS
+EXPORT_SYMBOL(hardware_pps);
+#endif
 EXPORT_SYMBOL(loops_per_sec);
 EXPORT_SYMBOL(kstat);
 
Index: kernel/sched.c
===================================================================
RCS file: /root/21REP/linux21/kernel/sched.c,v
retrieving revision 1.1.1.3
retrieving revision 1.1.1.3.4.2
diff -u -r1.1.1.3 -r1.1.1.3.4.2
--- sched.c	1999/01/22 18:53:21	1.1.1.3
+++ sched.c	1999/02/02 21:34:54	1.1.1.3.4.2
@@ -3,12 +3,9 @@
  *
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *
- *  1996-04-21	Modified by Ulrich Windl to make NTP work
  *  1996-12-23  Modified by Dave Grothe to fix bugs in semaphores and
  *              make semaphores SMP safe
  *  1997-01-28  Modified by Finn Arne Gangstad to make timers scale better.
- *  1997-09-10	Updated NTP code according to technical memorandum Jan '96
- *		"A Kernel Model for Precision Timekeeping" by Dave Mills
  *  1998-11-19	Implemented schedule_timeout() and related stuff
  *		by Andrea Arcangeli
  *  1998-12-24	Fixed a xtime SMP race (we need the xtime_lock rw spinlock to
@@ -45,38 +42,10 @@
 
 unsigned securebits = SECUREBITS_DEFAULT; /* systemwide security settings */
 
-long tick = (1000000 + HZ/2) / HZ;	/* timer interrupt period */
-
-/* The current time */
-volatile struct timeval xtime __attribute__ ((aligned (16)));
-
-/* Don't completely fail for HZ > 500.  */
-int tickadj = 500/HZ ? : 1;		/* microsecs */
-
 DECLARE_TASK_QUEUE(tq_timer);
 DECLARE_TASK_QUEUE(tq_immediate);
 DECLARE_TASK_QUEUE(tq_scheduler);
 
-/*
- * phase-lock loop variables
- */
-/* TIME_ERROR prevents overwriting the CMOS clock */
-int time_state = TIME_ERROR;	/* clock synchronization status */
-int time_status = STA_UNSYNC;	/* clock status bits */
-long time_offset = 0;		/* time adjustment (us) */
-long time_constant = 2;		/* pll time constant */
-long time_tolerance = MAXFREQ;	/* frequency tolerance (ppm) */
-long time_precision = 1;	/* clock precision (us) */
-long time_maxerror = NTP_PHASE_LIMIT;	/* maximum error (us) */
-long time_esterror = NTP_PHASE_LIMIT;	/* estimated error (us) */
-long time_phase = 0;		/* phase offset (scaled us) */
-long time_freq = ((1000000 + HZ/2) % HZ - HZ/2) << SHIFT_USEC;	/* frequency offset (scaled ppm) */
-long time_adj = 0;		/* tick adjust (scaled 1 / HZ) */
-long time_reftime = 0;		/* time at last adjustment (s) */
-
-long time_adjust = 0;
-long time_adjust_step = 0;
-
 unsigned long event = 0;
 
 extern int do_setitimer(int, struct itimerval *, struct itimerval *);
@@ -1103,190 +1072,6 @@
 	}
 }
 
-/*
- * this routine handles the overflow of the microsecond field
- *
- * The tricky bits of code to handle the accurate clock support
- * were provided by Dave Mills (Mills@UDEL.EDU) of NTP fame.
- * They were originally developed for SUN and DEC kernels.
- * All the kudos should go to Dave for this stuff.
- *
- */
-static void second_overflow(void)
-{
-    long ltemp;
-
-    /* Bump the maxerror field */
-    time_maxerror += time_tolerance >> SHIFT_USEC;
-    if ( time_maxerror > NTP_PHASE_LIMIT ) {
-        time_maxerror = NTP_PHASE_LIMIT;
-	time_state = TIME_ERROR;	/* p. 17, sect. 4.3, (b) */
-	time_status |= STA_UNSYNC;
-    }
-
-    /*
-     * Leap second processing. If in leap-insert state at
-     * the end of the day, the system clock is set back one
-     * second; if in leap-delete state, the system clock is
-     * set ahead one second. The microtime() routine or
-     * external clock driver will insure that reported time
-     * is always monotonic. The ugly divides should be
-     * replaced.
-     */
-    switch (time_state) {
-
-    case TIME_OK:
-	if (time_status & STA_INS)
-	    time_state = TIME_INS;
-	else if (time_status & STA_DEL)
-	    time_state = TIME_DEL;
-	break;
-
-    case TIME_INS:
-	if (xtime.tv_sec % 86400 == 0) {
-	    xtime.tv_sec--;
-	    time_state = TIME_OOP;
-	    printk(KERN_NOTICE "Clock: inserting leap second 23:59:60 UTC\n");
-	}
-	break;
-
-    case TIME_DEL:
-	if ((xtime.tv_sec + 1) % 86400 == 0) {
-	    xtime.tv_sec++;
-	    time_state = TIME_WAIT;
-	    printk(KERN_NOTICE "Clock: deleting leap second 23:59:59 UTC\n");
-	}
-	break;
-
-    case TIME_OOP:
-	time_state = TIME_WAIT;
-	break;
-
-    case TIME_WAIT:
-	if (!(time_status & (STA_INS | STA_DEL)))
-	    time_state = TIME_OK;
-    }
-
-    /*
-     * Compute the phase adjustment for the next second. In
-     * PLL mode, the offset is reduced by a fixed factor
-     * times the time constant. In FLL mode the offset is
-     * used directly. In either mode, the maximum phase
-     * adjustment for each second is clamped so as to spread
-     * the adjustment over not more than the number of
-     * seconds between updates.
-     */
-    if (time_offset < 0) {
-	ltemp = -time_offset;
-	if (!(time_status & STA_FLL))
-	    ltemp >>= SHIFT_KG + time_constant;
-	if (ltemp > (MAXPHASE / MINSEC) << SHIFT_UPDATE)
-	    ltemp = (MAXPHASE / MINSEC) << SHIFT_UPDATE;
-	time_offset += ltemp;
-	time_adj = -ltemp << (SHIFT_SCALE - SHIFT_HZ - SHIFT_UPDATE);
-    } else {
-	ltemp = time_offset;
-	if (!(time_status & STA_FLL))
-	    ltemp >>= SHIFT_KG + time_constant;
-	if (ltemp > (MAXPHASE / MINSEC) << SHIFT_UPDATE)
-	    ltemp = (MAXPHASE / MINSEC) << SHIFT_UPDATE;
-	time_offset -= ltemp;
-	time_adj = ltemp << (SHIFT_SCALE - SHIFT_HZ - SHIFT_UPDATE);
-    }
-
-    /*
-     * Compute the frequency estimate and additional phase
-     * adjustment due to frequency error for the next
-     * second. When the PPS signal is engaged, gnaw on the
-     * watchdog counter and update the frequency computed by
-     * the pll and the PPS signal.
-     */
-    pps_valid++;
-    if (pps_valid == PPS_VALID) {	/* PPS signal lost */
-	pps_jitter = MAXTIME;
-	pps_stabil = MAXFREQ;
-	time_status &= ~(STA_PPSSIGNAL | STA_PPSJITTER |
-			 STA_PPSWANDER | STA_PPSERROR);
-    }
-    ltemp = time_freq + pps_freq;
-    if (ltemp < 0)
-	time_adj -= -ltemp >>
-	    (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE);
-    else
-	time_adj += ltemp >>
-	    (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE);
-
-#if HZ == 100
-    /* Compensate for (HZ==100) != (1 << SHIFT_HZ).
-     * Add 25% and 3.125% to get 128.125; => only 0.125% error (p. 14)
-     */
-    if (time_adj < 0)
-	time_adj -= (-time_adj >> 2) + (-time_adj >> 5);
-    else
-	time_adj += (time_adj >> 2) + (time_adj >> 5);
-#endif
-}
-
-/* in the NTP reference this is called "hardclock()" */
-static void update_wall_time_one_tick(void)
-{
-	if ( (time_adjust_step = time_adjust) != 0 ) {
-	    /* We are doing an adjtime thing. 
-	     *
-	     * Prepare time_adjust_step to be within bounds.
-	     * Note that a positive time_adjust means we want the clock
-	     * to run faster.
-	     *
-	     * Limit the amount of the step to be in the range
-	     * -tickadj .. +tickadj
-	     */
-	     if (time_adjust > tickadj)
-		time_adjust_step = tickadj;
-	     else if (time_adjust < -tickadj)
-		time_adjust_step = -tickadj;
-	     
-	    /* Reduce by this step the amount of time left  */
-	    time_adjust -= time_adjust_step;
-	}
-	xtime.tv_usec += tick + time_adjust_step;
-	/*
-	 * Advance the phase, once it gets to one microsecond, then
-	 * advance the tick more.
-	 */
-	time_phase += time_adj;
-	if (time_phase <= -FINEUSEC) {
-		long ltemp = -time_phase >> SHIFT_SCALE;
-		time_phase += ltemp << SHIFT_SCALE;
-		xtime.tv_usec -= ltemp;
-	}
-	else if (time_phase >= FINEUSEC) {
-		long ltemp = time_phase >> SHIFT_SCALE;
-		time_phase -= ltemp << SHIFT_SCALE;
-		xtime.tv_usec += ltemp;
-	}
-}
-
-/*
- * Using a loop looks inefficient, but "ticks" is
- * usually just one (we shouldn't be losing ticks,
- * we're doing this this way mainly for interrupt
- * latency reasons, not because we think we'll
- * have lots of lost timer ticks
- */
-static void update_wall_time(unsigned long ticks)
-{
-	do {
-		ticks--;
-		update_wall_time_one_tick();
-	} while (ticks);
-
-	if (xtime.tv_usec >= 1000000) {
-	    xtime.tv_usec -= 1000000;
-	    xtime.tv_sec++;
-	    second_overflow();
-	}
-}
-
 static inline void do_process_times(struct task_struct *p,
 	unsigned long user, unsigned long system)
 {
@@ -1366,11 +1151,6 @@
 
 volatile unsigned long lost_ticks = 0;
 static unsigned long lost_ticks_system = 0;
-
-/*
- * This spinlock protect us from races in SMP while playing with xtime. -arca
- */
-rwlock_t xtime_lock = RW_LOCK_UNLOCKED;
 
 static inline void update_times(void)
 {
Index: kernel/time.c
===================================================================
RCS file: /root/21REP/linux21/kernel/time.c,v
retrieving revision 1.1.1.2
retrieving revision 1.1.1.2.4.3
diff -u -r1.1.1.2 -r1.1.1.2.4.3
--- time.c	1999/01/22 18:53:22	1.1.1.2
+++ time.c	1999/02/02 21:34:55	1.1.1.2.4.3
@@ -16,12 +16,25 @@
  *      adjtime interface update and CMOS clock write code
  * 1995-08-13    Torsten Duwe
  *      kernel PLL updated to 1994-12-13 specs (rfc-1589)
+ * 1996-04-21	Modified by Ulrich Windl to make NTP work
+ * 1997-09-10	Updated NTP code according to technical memorandum Jan '96
+ *		"A Kernel Model for Precision Timekeeping" by Dave Mills
+ *  1998-12-24	Fixed a xtime SMP race (we need the xtime_lock rw spinlock to
+ *		serialize accesses to xtime/lost_ticks).
+ *				Copyright (C) 1998  Andrea Arcangeli
  * 1999-01-16    Ulrich Windl
  *	Introduced error checking for many cases in adjtimex().
  *	Updated NTP code according to technical memorandum Jan '96
  *	"A Kernel Model for Precision Timekeeping" by Dave Mills
  *	Allow time_constant larger than MAXTC(6) for NTP v4 (MAXTC == 10)
  *	(Even though the technical memorandum forbids it)
+ * 1999-01-24    Ulrich Windl
+ *	Added code to support ADJ_TICKADJ in adjtimex(). Added support for
+ *	PPS signal.
+ * 1999-01-31	Ulrich Windl
+ *	Split NTP PPS support into different levels: NTP, NTP with PPS,
+ *	NTP with PPS and serial carrier detect.  Moved time stuff from
+ *	sched.c to the place where it really belongs.
  */
 
 #include <linux/mm.h>
@@ -30,12 +43,239 @@
 
 #include <asm/uaccess.h>
 
+/* kernel time variables */
+long tick = (1000000 + HZ/2) / HZ;	/* timer interrupt period */
+long time_adjust = 0;			/* remaining time adjustment */
+long time_adjust_step = 0;		/* current time adjustment */
+
+/* The current time */
+volatile struct timeval xtime __attribute__ ((aligned (16)));
+
+/*
+ * This spinlock protect us from races in SMP while playing with xtime. -arca
+ */
+rwlock_t xtime_lock = RW_LOCK_UNLOCKED;
+
 /* 
  * The timezone where the local system is located.  Used as a default by some
  * programs who obtain this value by using gettimeofday.
  */
 struct timezone sys_tz = { 0, 0};
 
+/* Don't completely fail for HZ > 500.  */
+int tickadj = 500/HZ ? : 1;		/* microsecs */
+
+#ifdef CONFIG_NTP
+/*
+ * phase-lock loop variables
+ */
+int time_state = TIME_ERROR;	/* clock synchronization status */
+/* bit STA_UNSYNC prevents overwriting the CMOS clock */
+int time_status = STA_UNSYNC;	/* clock status bits */
+long time_offset = 0;		/* time adjustment (us) */
+long time_constant = 2;		/* pll time constant */
+long time_tolerance = MAXFREQ;	/* frequency tolerance (ppm) */
+long time_precision = 1;	/* clock precision (us) */
+long time_maxerror = NTP_PHASE_LIMIT;	/* maximum error (us) */
+long time_esterror = NTP_PHASE_LIMIT;	/* estimated error (us) */
+long time_phase = 0;		/* phase offset (scaled us) */
+long time_freq = ((1000000 + HZ/2) % HZ - HZ/2) << SHIFT_USEC;	/* frequency offset (scaled ppm) */
+long time_adj = 0;		/* tick adjust (scaled 1 / HZ) */
+long time_reftime = 0;		/* time at last adjustment (s) */
+#endif
+
+/*
+ * this routine handles the overflow of the microsecond field
+ *
+ * The tricky bits of code to handle the accurate clock support
+ * were provided by Dave Mills (Mills@UDEL.EDU) of NTP fame.
+ * They were originally developed for SUN and DEC kernels.
+ * All the kudos should go to Dave for this stuff.
+ *
+ */
+static void second_overflow(void)
+{
+#ifdef CONFIG_NTP
+    long ltemp;
+
+    /* Bump the maxerror field */
+    time_maxerror += time_tolerance >> SHIFT_USEC;
+    if ( time_maxerror > NTP_PHASE_LIMIT ) {
+        time_maxerror = NTP_PHASE_LIMIT;
+	time_state = TIME_ERROR;	/* p. 17, sect. 4.3, (b) */
+	time_status |= STA_UNSYNC;
+    }
+
+    /*
+     * Leap second processing. If in leap-insert state at
+     * the end of the day, the system clock is set back one
+     * second; if in leap-delete state, the system clock is
+     * set ahead one second. The microtime() routine or
+     * external clock driver will insure that reported time
+     * is always monotonic. The ugly divides should be
+     * replaced.
+     */
+    switch (time_state) {
+
+    case TIME_OK:
+	if (time_status & STA_INS)
+	    time_state = TIME_INS;
+	else if (time_status & STA_DEL)
+	    time_state = TIME_DEL;
+	break;
+
+    case TIME_INS:
+	if (xtime.tv_sec % 86400 == 0) {
+	    xtime.tv_sec--;
+	    time_state = TIME_OOP;
+	    printk(KERN_NOTICE "Clock: inserting leap second 23:59:60 UTC\n");
+	}
+	break;
+
+    case TIME_DEL:
+	if ((xtime.tv_sec + 1) % 86400 == 0) {
+	    xtime.tv_sec++;
+	    time_state = TIME_WAIT;
+	    printk(KERN_NOTICE "Clock: deleting leap second 23:59:59 UTC\n");
+	}
+	break;
+
+    case TIME_OOP:
+	time_state = TIME_WAIT;
+	break;
+
+    case TIME_WAIT:
+	if (!(time_status & (STA_INS | STA_DEL)))
+	    time_state = TIME_OK;
+    }
+
+    /*
+     * Compute the phase adjustment for the next second. In
+     * PLL mode, the offset is reduced by a fixed factor
+     * times the time constant. In FLL mode the offset is
+     * used directly. In either mode, the maximum phase
+     * adjustment for each second is clamped so as to spread
+     * the adjustment over not more than the number of
+     * seconds between updates.
+     */
+    if (time_offset < 0) {
+	ltemp = -time_offset;
+	if (!(time_status & STA_FLL))
+	    ltemp >>= SHIFT_KG + time_constant;
+	if (ltemp > (MAXPHASE / MINSEC) << SHIFT_UPDATE)
+	    ltemp = (MAXPHASE / MINSEC) << SHIFT_UPDATE;
+	time_offset += ltemp;
+	time_adj = -ltemp << (SHIFT_SCALE - SHIFT_HZ - SHIFT_UPDATE);
+    } else {
+	ltemp = time_offset;
+	if (!(time_status & STA_FLL))
+	    ltemp >>= SHIFT_KG + time_constant;
+	if (ltemp > (MAXPHASE / MINSEC) << SHIFT_UPDATE)
+	    ltemp = (MAXPHASE / MINSEC) << SHIFT_UPDATE;
+	time_offset -= ltemp;
+	time_adj = ltemp << (SHIFT_SCALE - SHIFT_HZ - SHIFT_UPDATE);
+    }
+
+#ifdef CONFIG_NTP_PPS
+    /*
+     * Compute the frequency estimate and additional phase
+     * adjustment due to frequency error for the next
+     * second. When the PPS signal is engaged, gnaw on the
+     * watchdog counter and update the frequency computed by
+     * the pll and the PPS signal.
+     */
+    pps_valid++;
+    if (pps_valid == PPS_VALID) {	/* PPS signal lost */
+	pps_jitter = MAXTIME;
+	pps_stabil = MAXFREQ;
+	time_status &= ~(STA_PPSSIGNAL | STA_PPSJITTER |
+			 STA_PPSWANDER | STA_PPSERROR);
+    }
+    ltemp = time_freq + pps_freq;
+#else
+    ltemp = time_freq;
+#endif /* CONFIG_NTP_PPS */
+    if (ltemp < 0)
+	time_adj -= -ltemp >>
+	    (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE);
+    else
+	time_adj += ltemp >>
+	    (SHIFT_USEC + SHIFT_HZ - SHIFT_SCALE);
+
+#if HZ == 100
+    /* Compensate for (HZ==100) != (1 << SHIFT_HZ).
+     * Add 25% and 3.125% to get 128.125; => only 0.125% error (p. 14)
+     */
+    if (time_adj < 0)
+	time_adj -= (-time_adj >> 2) + (-time_adj >> 5);
+    else
+	time_adj += (time_adj >> 2) + (time_adj >> 5);
+#endif
+#endif /* CONFIG_NTP */
+}
+
+/* in the NTP reference this is called "hardclock()" */
+inline static void update_wall_time_one_tick(void)
+{
+	if ( (time_adjust_step = time_adjust) != 0 ) {
+	    /* We are doing an adjtime thing. 
+	     *
+	     * Prepare time_adjust_step to be within bounds.
+	     * Note that a positive time_adjust means we want the clock
+	     * to run faster.
+	     *
+	     * Limit the amount of the step to be in the range
+	     * -tickadj .. +tickadj
+	     */
+	     if (time_adjust > tickadj)
+		time_adjust_step = tickadj;
+	     else if (time_adjust < -tickadj)
+		time_adjust_step = -tickadj;
+	     
+	    /* Reduce by this step the amount of time left  */
+	    time_adjust -= time_adjust_step;
+	}
+	xtime.tv_usec += tick + time_adjust_step;
+#ifdef CONFIG_NTP
+	/*
+	 * Advance the phase, once it gets to one microsecond, then
+	 * advance the tick more.
+	 */
+	time_phase += time_adj;
+	if (time_phase <= -FINEUSEC) {
+		long ltemp = -time_phase >> SHIFT_SCALE;
+		time_phase += ltemp << SHIFT_SCALE;
+		xtime.tv_usec -= ltemp;
+	}
+	else if (time_phase >= FINEUSEC) {
+		long ltemp = time_phase >> SHIFT_SCALE;
+		time_phase -= ltemp << SHIFT_SCALE;
+		xtime.tv_usec += ltemp;
+	}
+#endif
+}
+
+/*
+ * Using a loop looks inefficient, but "ticks" is
+ * usually just one (we shouldn't be losing ticks,
+ * we're doing this this way mainly for interrupt
+ * latency reasons, not because we think we'll
+ * have lots of lost timer ticks
+ */
+void update_wall_time(unsigned long ticks)
+{
+	do {
+		ticks--;
+		update_wall_time_one_tick();
+	} while (ticks);
+
+	if (xtime.tv_usec >= 1000000) {
+	    xtime.tv_usec -= 1000000;
+	    xtime.tv_sec++;
+	    second_overflow();
+	}
+}
+
 static void do_normal_gettime(struct timeval * tm)
 {
         *tm=xtime;
@@ -95,10 +335,12 @@
 	xtime.tv_sec = value;
 	xtime.tv_usec = 0;
 	time_adjust = 0;	/* stop active adjtime() */
+#ifdef CONFIG_NTP
 	time_status |= STA_UNSYNC;
 	time_state = TIME_ERROR;	/* p. 24, (a) */
 	time_maxerror = NTP_PHASE_LIMIT;
 	time_esterror = NTP_PHASE_LIMIT;
+#endif
 	sti();
 	return 0;
 }
@@ -197,6 +439,7 @@
 	return do_sys_settimeofday(tv ? &new_tv : NULL, tz ? &new_tz : NULL);
 }
 
+#ifdef CONFIG_NTP
 long pps_offset = 0;		/* pps time offset (us) */
 long pps_jitter = MAXTIME;	/* time dispersion (jitter) (us) */
 
@@ -211,10 +454,306 @@
 long pps_calcnt = 0;		/* calibration intervals */
 long pps_errcnt = 0;		/* calibration errors */
 long pps_stbcnt = 0;		/* stability limit exceeded */
+#endif /* CONFIG_NTP */
 
-/* hook for a loadable hardpps kernel module */
-void (*hardpps_ptr)(struct timeval *) = (void (*)(struct timeval *))0;
+#ifdef	CONFIG_NTP_PPS
+#define DEBUG_NTP_PPS	0	/* set to 1 if debugging the PPS timings */
 
+/* Hardware PPS routine as defined for NTP V3. Called from interrupt with
+ * interrupts disabled. Parts taken from Dave Millsī specifications.
+ */
+
+/*
+ * hardware_pps() - discipline CPU clock oscillator to external PPS signal
+ *
+ * This routine is called at each PPS interrupt in order to discipline
+ * the CPU clock oscillator to the PPS signal. It measures the PPS phase
+ * and leaves it in a handy spot for the second_overflow() routine. It
+ * integrates successive PPS phase differences and calculates the
+ * frequency offset. This is used in second_overflow() to discipline the CPU
+ * clock oscillator so that intrinsic frequency error is cancelled out.
+ * The code requires the caller to capture the kernel time and hardware counter
+ * value (offset to kernel time) at the on-time PPS signal transition.
+ *
+ * Note that, on some Unix systems, this routine runs at an interrupt
+ * priority level higher than the timer interrupt routine second_overflow().
+ * Therefore, the variables used are distinct from the second_overflow()
+ * variables, except for certain exceptions: The PPS frequency pps_freq
+ * and phase pps_offset variables are determined by this routine and
+ * updated atomically. The time_tolerance variable can be considered a
+ * constant, since it is infrequently changed, and then only when the
+ * PPS signal is disabled. The watchdog counter pps_valid is updated
+ * once per second by second_overflow() and is atomically cleared in this
+ * routine.
+ */
+void hardware_pps(const struct timeval *p_tv)
+{
+	static long pps_tf[3] = {0, 0, 0};
+				/* pps time offset median filter (us) */
+	static long pps_ff[3] = {0, 0, 0};
+				/* pps frequency offset median filter */
+	static struct timeval pps_time;	/* kernel time at last interval */
+	static int pps_count = 0;	/* calibration interval counter (s) */
+	static int glitch = 0;		/* PPS signal glitch counter */
+	static int int_count = 0;	/* intervals at current duration */
+	static long pps_usec = 0;	/* us in calibration interval */
+	long u_usec, v_usec, bigtick;
+	long cal_sec, cal_usec;
+#if DEBUG_NTP_PPS
+#ifdef CONFIG_X86_TSC
+	struct {
+		unsigned long low;
+		unsigned long high;
+	} start_cc, end_cc;
+	static long cc_min = 10000000L;
+	static long cc_max = 0L;
+	unsigned long cc;
+
+	/* read Pentium cycle counter */
+	__asm__("rdtsc"
+		:"=a" (start_cc.low),
+		 "=d" (start_cc.high));
+#endif
+#endif
+	/*
+	 * An occasional glitch can be produced when the PPS interrupt
+	 * occurs in second_overflow() before the time variable is
+	 * updated. Here the offset is discarded when the difference
+	 * between it and the last one is greater than tick/2, but not
+	 * if the interval since the first discard exceeds 30 s.
+	 */
+	time_status |= STA_PPSSIGNAL;
+	time_status &= ~(STA_PPSJITTER | STA_PPSWANDER | STA_PPSERROR);
+	pps_valid = 0;
+	u_usec = -p_tv->tv_usec;	/* relative position around second */
+	if (u_usec < -500000)
+		u_usec += 1000000;
+	v_usec = pps_offset - u_usec;	/* relative offset to last position */
+	if (v_usec < 0)
+		v_usec = -v_usec;
+	if (v_usec > (tick >> 1)) {	/* jitter above threshold */
+		if (glitch > MAXGLITCH) {
+			glitch = 0;
+			pps_tf[0] = u_usec;
+			pps_tf[1] = u_usec;
+#if DEBUG_NTP_PPS
+			printk(KERN_NOTICE "hardpps: MAXGLITCH reached\n");
+#endif
+		} else {
+			glitch++;
+			u_usec = pps_offset;
+		}
+	} else {
+#if DEBUG_NTP_PPS
+		if ( glitch > 0 )
+			printk(KERN_DEBUG "hardpps: glitch was %d\n", glitch);
+#endif
+		glitch = 0;
+	}
+
+	/*
+	 * A three-stage median filter is used to help deglitch the pps
+	 * time. The median sample becomes the time offset estimate; the
+	 * difference between the other two samples becomes the time
+	 * dispersion (jitter) estimate.
+	 */
+	pps_tf[2] = pps_tf[1];
+	pps_tf[1] = pps_tf[0];
+	pps_tf[0] = u_usec;
+	if (pps_tf[0] > pps_tf[1]) {
+		if (pps_tf[1] > pps_tf[2]) {
+			pps_offset = pps_tf[1];		/* 0 1 2 */
+			v_usec = pps_tf[0] - pps_tf[2];
+		} else if (pps_tf[2] > pps_tf[0]) {
+			pps_offset = pps_tf[0];		/* 2 0 1 */
+			v_usec = pps_tf[2] - pps_tf[1];
+		} else {
+			pps_offset = pps_tf[2];		/* 0 2 1 */
+			v_usec = pps_tf[0] - pps_tf[1];
+		}
+	} else {
+		if (pps_tf[1] < pps_tf[2]) {
+			pps_offset = pps_tf[1];		/* 2 1 0 */
+			v_usec = pps_tf[2] - pps_tf[0];
+		} else  if (pps_tf[2] < pps_tf[0]) {
+			pps_offset = pps_tf[0];		/* 1 0 2 */
+			v_usec = pps_tf[1] - pps_tf[2];
+		} else {
+			pps_offset = pps_tf[2];		/* 1 2 0 */
+			v_usec = pps_tf[1] - pps_tf[0];
+		}
+	}
+	if (v_usec > MAXTIME)
+		pps_jitcnt++;		/* jitter too large */
+	v_usec = (v_usec << PPS_AVG) - pps_jitter;
+	if (v_usec < 0)
+		pps_jitter -= -v_usec >> PPS_AVG;
+	else
+		pps_jitter += v_usec >> PPS_AVG;
+	if (pps_jitter > (MAXTIME >> 1))
+		time_status |= STA_PPSJITTER;
+
+	/*
+	 * During the calibration interval adjust the starting time when
+	 * the tick overflows. At the end of the interval compute the
+	 * duration of the interval and the difference of the hardware
+	 * counters at the beginning and end of the interval. This code
+	 * is deliciously complicated by the fact valid differences may
+	 * exceed the value of tick when using long calibration
+	 * intervals and small ticks. Note that the counter can be
+	 * greater than tick if caught at just the wrong instant, but
+	 * the values returned and used here are correct.
+	 */
+	bigtick = (long)tick << SHIFT_USEC;
+	pps_usec -= pps_freq;
+	if (pps_usec >= bigtick)
+		pps_usec -= bigtick;
+	if (pps_usec < 0)
+		pps_usec += bigtick;
+	pps_time.tv_sec++;
+	if (++pps_count < (1 << pps_shift))
+		goto done;		/* continue calibration interval */
+	pps_count = 0;
+	pps_calcnt++;			/* finished calibration interval */
+	u_usec = p_tv->tv_usec << SHIFT_USEC;
+	v_usec = pps_usec - u_usec;
+	if (v_usec >= bigtick >> 1)
+		v_usec -= bigtick;
+	if (v_usec < -(bigtick >> 1))
+		v_usec += bigtick;
+	if (v_usec < 0)
+		v_usec = -(-v_usec >> pps_shift);
+	else
+		v_usec = v_usec >> pps_shift;
+	pps_usec = u_usec;
+	cal_sec = p_tv->tv_sec - pps_time.tv_sec;
+	cal_usec = p_tv->tv_usec - pps_time.tv_usec;
+	if (cal_usec < 0) {
+		cal_usec += 1000000;
+		cal_sec--;
+	}
+	pps_time = *p_tv;
+
+	/*
+	 * Check for lost interrupts, noise, excessive jitter and
+	 * excessive frequency error. The number of timer ticks during
+	 * the interval may vary +-1 tick. Add to this a margin of one
+	 * tick for the PPS signal jitter and maximum frequency
+	 * deviation. If the limits are exceeded, the calibration
+	 * interval is reset to the minimum and we start over.
+	 */
+	u_usec = (long)tick << 1;
+	if (!((cal_sec == -1 && cal_usec > (1000000 - u_usec))
+	      || (cal_sec == 0 && cal_usec < u_usec))
+	    || v_usec > time_tolerance || v_usec < -time_tolerance) {
+		pps_errcnt++;
+		pps_shift = PPS_SHIFT;
+		int_count = 0;
+		time_status |= STA_PPSERROR;
+		goto done;
+	}
+
+	/*
+	 * A three-stage median filter is used to help deglitch the pps
+	 * frequency. The median sample becomes the frequency offset
+	 * estimate; the difference between the other two samples
+	 * becomes the frequency dispersion (stability) estimate.
+	 */
+	pps_ff[2] = pps_ff[1];
+	pps_ff[1] = pps_ff[0];
+	pps_ff[0] = v_usec;
+	if (pps_ff[0] > pps_ff[1]) {
+		if (pps_ff[1] > pps_ff[2]) {
+			u_usec = pps_ff[1];		/* 0 1 2 */
+			v_usec = pps_ff[0] - pps_ff[2];
+		} else if (pps_ff[2] > pps_ff[0]) {
+			u_usec = pps_ff[0];		/* 2 0 1 */
+			v_usec = pps_ff[2] - pps_ff[1];
+		} else {
+			u_usec = pps_ff[2];		/* 0 2 1 */
+			v_usec = pps_ff[0] - pps_ff[1];
+		}
+	} else {
+		if (pps_ff[1] < pps_ff[2]) {
+			u_usec = pps_ff[1];		/* 2 1 0 */
+			v_usec = pps_ff[2] - pps_ff[0];
+		} else  if (pps_ff[2] < pps_ff[0]) {
+			u_usec = pps_ff[0];		/* 1 0 2 */
+			v_usec = pps_ff[1] - pps_ff[2];
+		} else {
+			u_usec = pps_ff[2];		/* 1 2 0 */
+			v_usec = pps_ff[1] - pps_ff[0];
+		}
+	}
+
+	/*
+	 * Here the frequency dispersion (stability) is updated. If it
+	 * is less than one-fourth the maximum (MAXFREQ), the frequency
+	 * offset is updated as well, but clamped to the tolerance. It
+	 * will be processed later by the hardclock() routine.
+	 */
+	v_usec = (v_usec >> 1) - pps_stabil;
+	if (v_usec < 0)
+		pps_stabil -= -v_usec >> PPS_AVG;
+	else
+		pps_stabil += v_usec >> PPS_AVG;
+	if (pps_stabil > MAXFREQ >> 2) {
+		pps_shift = PPS_SHIFT;
+		int_count = 0;
+		pps_stbcnt++;
+		time_status |= STA_PPSWANDER;
+		goto done;
+	}
+	if (time_status & STA_PPSFREQ) {
+		if (u_usec < 0) {
+			pps_freq -= -u_usec >> PPS_AVG;
+			if (pps_freq < -time_tolerance)
+				pps_freq = -time_tolerance;
+			u_usec = -u_usec;
+		} else {
+			pps_freq += u_usec >> PPS_AVG;
+			if (pps_freq > time_tolerance)
+				pps_freq = time_tolerance;
+		}
+	}
+
+	/*
+	 * Here the calibration interval is adjusted. If the maximum
+	 * time difference is greater than tick / 4, reduce the interval
+	 * by half. If this is not the case for four consecutive
+	 * intervals, double the interval.
+	 */
+	int_count++;
+	if (u_usec << pps_shift > bigtick >> 2) {
+		int_count = 0;
+		if (pps_shift > PPS_SHIFT)
+			pps_shift--;
+	} else if (int_count >= 4) {
+		int_count = 0;
+		if (pps_shift < PPS_SHIFTMAX)
+			pps_shift++;
+	}
+done:
+#if DEBUG_NTP_PPS
+#ifdef CONFIG_X86_TSC
+	/* read Pentium cycle counter */
+	__asm__("rdtsc"
+		:"=a" (end_cc.low),
+		 "=d" (end_cc.high));
+	cc = end_cc.low - start_cc.low;
+	if ( cc > cc_max ) {
+		cc_max = cc;
+		printk(KERN_DEBUG "hardpps: new max CC = %lu\n", cc_max);
+	}
+	if ( cc < cc_min ) {
+		cc_min = cc;
+		printk(KERN_DEBUG "hardpps: new min CC = %lu\n", cc_min);
+	}
+#endif
+#endif
+}
+#endif	/* CONFIG_NTP_PPS */
+
 /* adjtimex mainly allows reading (and writing, if superuser) of
  * kernel time-keeping variables. used by xntpd.
  */
@@ -230,7 +769,7 @@
 	/* Now we validate the data before disabling interrupts */
 
 	if (txc->modes != ADJ_OFFSET_SINGLESHOT && (txc->modes & ADJ_OFFSET))
-	  /* adjustment Offset limited to +- .512 seconds */
+	  /* adjustment Offset limited to +- 0.2 seconds */
 		if (txc->offset <= - MAXPHASE || txc->offset >= MAXPHASE )
 			return -EINVAL;	
 
@@ -244,12 +783,13 @@
 	/* Save for later - semantics of adjtime is to return old value */
 	save_adjust = time_adjust;
 
-#if 0	/* STA_CLOCKERR is never set yet */
+#if defined(CONFIG_NTP) && 0	/* STA_CLOCKERR is never set yet */
 	time_status &= ~STA_CLOCKERR;		/* reset STA_CLOCKERR */
 #endif
 	/* If there are input parameters, then process them */
 	if (txc->modes)
 	{
+#ifdef CONFIG_NTP
 	    if (time_state == TIME_ERROR)
 		time_state = TIME_OK;		/* reset error -- why? */
 
@@ -288,12 +828,14 @@
 		}
 		time_constant = txc->constant;
 	    }
+#endif /* CONFIG_NTP */
 
 	    if (txc->modes & ADJ_OFFSET) {	/* values checked earlier */
 		if (txc->modes == ADJ_OFFSET_SINGLESHOT) {
 		    /* adjtime() is independent from ntp_adjtime() */
 		    time_adjust = txc->offset;
 		}
+#ifdef CONFIG_NTP
 		else if ( time_status & (STA_PLL | STA_PPSTIME) ) {
 		    ltemp = (time_status & (STA_PPSTIME | STA_PPSSIGNAL)) ==
 		            (STA_PPSTIME | STA_PPSSIGNAL) ?
@@ -349,6 +891,7 @@
 		    else if (time_freq < -time_tolerance)
 		        time_freq = -time_tolerance;
 		} /* STA_PLL || STA_PPSTIME */
+#endif /* CONFIG_NTP */
 	    } /* txc->modes & ADJ_OFFSET */
 	    if (txc->modes & ADJ_TICK) {
 		/* if the quartz is off by more than 10% something is
@@ -359,8 +902,21 @@
 		}
 		tick = txc->tick;
 	    }
+	    if (txc->modes & ADJ_TICKADJ) {
+		/* Tradidional UN*Xes seem to allow about ``tick/10'',
+		   but we will allow up to ``tick/4''. Larger values
+		   might cause trouble!
+		 */
+		if (txc->tickadj <= 0 || txc->tickadj > tick/4) {
+		    error = -EINVAL;
+		    goto leave;
+		}
+		tickadj = txc->tickadj;
+	    }
 	} /* txc->modes */
-leave:	if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0
+leave:
+#ifdef CONFIG_NTP
+	if ((time_status & (STA_UNSYNC|STA_CLOCKERR)) != 0
 	    || ((time_status & (STA_PPSFREQ|STA_PPSTIME)) != 0
 		&& (time_status & STA_PPSSIGNAL) == 0)
 	    /* p. 24, (b) */
@@ -371,9 +927,11 @@
 		&& (time_status & (STA_PPSWANDER|STA_PPSERROR)) != 0))
 	    /* p. 24, (d) */
 		time_state = TIME_ERROR;
+#endif
 	
 	if ((txc->modes & ADJ_OFFSET_SINGLESHOT) == ADJ_OFFSET_SINGLESHOT)
 	    txc->offset	   = save_adjust;
+#ifdef CONFIG_NTP
 	else {
 	    if (time_offset < 0)
 		txc->offset = -(-time_offset >> SHIFT_UPDATE);
@@ -388,7 +946,9 @@
 	txc->precision	   = time_precision;
 	txc->tolerance	   = time_tolerance;
 	do_gettimeofday(&txc->time);
+#endif
 	txc->tick	   = tick;
+#ifdef CONFIG_NTP_PPS
 	txc->ppsfreq	   = pps_freq;
 	txc->jitter	   = pps_jitter >> PPS_AVG;
 	txc->shift	   = pps_shift;
@@ -397,6 +957,8 @@
 	txc->calcnt	   = pps_calcnt;
 	txc->errcnt	   = pps_errcnt;
 	txc->stbcnt	   = pps_stbcnt;
+#endif
+	txc->tickadj	   = tickadj;	/* extension by UW */
 
 	sti();
 	return(error < 0 ? error : time_state);
