Subject: com.c pps fixed in -current
To: None <tech-kern@netbsd.org>
From: Jonathan Stone <jonathan@Cuisinart.DSG.Stanford.EDU>
List: tech-kern
Date: 02/06/2000 15:20:00
I just committed a fix for the PPS code in com.c.

The problem was simple. NTP clock disciplines run with the tty line in
local mode, so they can still catch ASCII timestamps (giving date and
time to the nearest second) without getting hangups every time the
clock deasserts DCD to signal a second boundary.

So, the PPS timestamp code needs to notice DCD events even if the
line  discipline is ignoring them (via CLOCAL or MDMBUF).

The fix is to change comintr() to compute whether the msr flags PPS is
interested in changed, irrespective of what the line discipline wants,
and if so process a PPS event. (i.e, hoist the PPS code outside the
`normal' carrier processing).

Here's the patch (from -current). I tested it using a Ricochet modem
to generate DCD, and verified that the PPS-API gets events both when a
network discipline is active, and when using tip to talk to the port
in CLOCAL mode. But I dont have 1.4.2 branch sources at home; could
someone (Erik, maybe?)  confirm these work with -release, so we can
get it into the 1.4.2 release?

thanks
--Jonathan


--- com.c	Sun Jan 23 13:06:01 2000
+++ com.c.PPS	Sun Feb  6 14:59:02 2000
@@ -1936,7 +1936,7 @@
 	cc = sc->sc_rbavail;
 
 	do {
-		u_char	msr, delta;
+		u_char	msr, delta, ppsdelta;
 
 		lsr = bus_space_read_1(iot, ioh, com_lsr);
 #if defined(DDB) || defined(KGDB)
@@ -2014,55 +2014,55 @@
 		msr = bus_space_read_1(iot, ioh, com_msr);
 		delta = msr ^ sc->sc_msr;
 		sc->sc_msr = msr;
-		if (ISSET(delta, sc->sc_msr_mask)) {
-			SET(sc->sc_msr_delta, delta);
-
-			/*
-			 * Pulse-per-second clock signal on edge of DCD?
-			 */
-			if (ISSET(delta, sc->sc_ppsmask)) {
-				struct timeval tv;
-			    	if (ISSET(msr, sc->sc_ppsmask) ==
-				    sc->sc_ppsassert) {
-					/* XXX nanotime() */
-					microtime(&tv);
-					TIMEVAL_TO_TIMESPEC(&tv, 
-					    &sc->ppsinfo.assert_timestamp);
-					if (sc->ppsparam.mode & PPS_OFFSETASSERT) {
-						timespecadd(&sc->ppsinfo.assert_timestamp,
-						    &sc->ppsparam.assert_offset,
+		/*
+		 * Pulse-per-second (PSS) signals on edge of DCD?
+		 * Process these even if line discipline is ignoring DCD.
+		 */
+		ppsdelta = delta & sc->sc_ppsmask;
+		if (ppsdelta) {
+			struct timeval tv;
+		    	if (ppsdelta == sc->sc_ppsassert) {
+				/* XXX nanotime() */
+				microtime(&tv);
+				TIMEVAL_TO_TIMESPEC(&tv, 
+				    &sc->ppsinfo.assert_timestamp);
+				if (sc->ppsparam.mode & PPS_OFFSETASSERT) {
+					timespecadd(&sc->ppsinfo.assert_timestamp,
+					    &sc->ppsparam.assert_offset,
 						    &sc->ppsinfo.assert_timestamp);
-	}
+				}
 
 #ifdef PPS_SYNC
-					if (sc->ppsparam.mode & PPS_HARDPPSONASSERT)
-						hardpps(&tv, tv.tv_usec);
+				if (sc->ppsparam.mode & PPS_HARDPPSONASSERT)
+					hardpps(&tv, tv.tv_usec);
 #endif
-					sc->ppsinfo.assert_sequence++;
-					sc->ppsinfo.current_mode = 
-					    sc->ppsparam.mode;
-
-				} else if (ISSET(msr, sc->sc_ppsmask) == 
-				    sc->sc_ppsclear) {
-					/* XXX nanotime() */
-					microtime(&tv);
-					TIMEVAL_TO_TIMESPEC(&tv, 
+				sc->ppsinfo.assert_sequence++;
+				sc->ppsinfo.current_mode = sc->ppsparam.mode;
+
+			} else if (ppsdelta == sc->sc_ppsclear) {
+				/* XXX nanotime() */
+				microtime(&tv);
+				TIMEVAL_TO_TIMESPEC(&tv, 
+				    &sc->ppsinfo.clear_timestamp);
+				if (sc->ppsparam.mode & PPS_OFFSETCLEAR) {
+					timespecadd(&sc->ppsinfo.clear_timestamp,
+					    &sc->ppsparam.clear_offset,
 					    &sc->ppsinfo.clear_timestamp);
-					if (sc->ppsparam.mode & PPS_OFFSETCLEAR) {
-						timespecadd(&sc->ppsinfo.clear_timestamp,
-						    &sc->ppsparam.clear_offset,
-						    &sc->ppsinfo.clear_timestamp);
-	}
+				}
 
 #ifdef PPS_SYNC
-					if (sc->ppsparam.mode & PPS_HARDPPSONCLEAR)
-						hardpps(&tv, tv.tv_usec);
+				if (sc->ppsparam.mode & PPS_HARDPPSONCLEAR)
+					hardpps(&tv, tv.tv_usec);
 #endif
-					sc->ppsinfo.clear_sequence++;
-					sc->ppsinfo.current_mode = 
-					    sc->ppsparam.mode;
-				}
+				sc->ppsinfo.clear_sequence++;
+				sc->ppsinfo.current_mode = sc->ppsparam.mode;
 			}
+		}
+		/*
+		 * Process normal status changes
+		 */
+		if (ISSET(delta, sc->sc_msr_mask)) {
+			SET(sc->sc_msr_delta, delta);
 
 			/*
 			 * Stop output immediately if we lose the output