Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 15 Oct 2003 02:59:28 -0700
From:      Alfred Perlstein <bright@mu.org>
To:        hackers@freebsd.org
Cc:        yokota@freebsd.org
Subject:   [patch] psm hacks for kvm problems.
Message-ID:  <20031015095928.GC99943@elvis.mu.org>

next in thread | raw e-mail | index | archive | help
I was getting fustrated with the effect my KVM was having on my PS/2
mouse, basically after switching to the FreeBSD box I was getting
random mouse movement for a second or two including button clicks
as the kvm "settled".

Windows doesn't have this problem.

I have some hacks here that get me close to a solution but not all
the way there. 

This change signifigantly reduces the "jitter" by detecting when
we get out of sync and just dropping data for two seconds (tunable
via sysctl).

I also tried to get the mouse status if there has been no activity
for more than two seconds however this doesn't seem to work.  I
still get an initial jitter.

Does anyone have any suggestions how I could ask the mouse "are you
ok" from within the context of the interrupt routine?  If I could
do that reliably (check to make sure mouse is sane) then I could
get rid of the jitter entirely.

thank you.


Index: psm.c
===================================================================
RCS file: /home/ncvs/src/sys/isa/psm.c,v
retrieving revision 1.61
diff -u -r1.61 psm.c
--- psm.c	12 Jul 2003 18:36:04 -0000	1.61
+++ psm.c	15 Oct 2003 09:43:58 -0000
@@ -74,6 +74,7 @@
 #include <machine/bus.h>
 #include <sys/rman.h>
 #include <sys/selinfo.h>
+#include <sys/sysctl.h>
 #include <sys/time.h>
 #include <sys/uio.h>
 
@@ -99,7 +100,7 @@
 #endif
 
 #ifndef PSM_INPUT_TIMEOUT
-#define PSM_INPUT_TIMEOUT	2000000	/* 2 sec */
+#define PSM_INPUT_TIMEOUT	500000	/* .5 sec */
 #endif
 
 /* end of driver specific options */
@@ -158,7 +159,9 @@
     int		  xold;	/* previous absolute X position */
     int		  yold;	/* previous absolute Y position */
     int		  syncerrors;
-    struct timeval inputtimeout;
+    struct timeval inputtimeout; /* max delay between bytes per packet */
+    struct timeval syncholdtime; /* how long to backoff when sync error */
+    struct timeval lastvalid;	/* last valid packet time */
     int		  watchdog;	/* watchdog timer flag */
     struct callout_handle callout;	/* watchdog timer call out */
     dev_t	  dev;
@@ -1951,6 +1954,15 @@
     sc->callout = timeout(psmtimeout, (void *)(uintptr_t)sc, hz);
 }
 
+static int syncholdtime = 2;
+static int lastvalidthresh = 2;
+
+SYSCTL_NODE(_hw, OID_AUTO, psm, CTLFLAG_RD, 0, "ps/2 mouse");
+SYSCTL_INT(_hw_psm, OID_AUTO, syncholdtime, CTLFLAG_RW, &syncholdtime, 0,
+    "block mouse input when out of sync for this long.");
+SYSCTL_INT(_hw_psm, OID_AUTO, lastvalidthresh, CTLFLAG_RW, &lastvalidthresh, 0,
+    "time between packets to check for status.");
+
 static void
 psmintr(void *arg)
 {
@@ -1980,11 +1992,12 @@
     };
     register struct psm_softc *sc = arg;
     mousestatus_t ms;
-    struct timeval tv;
+    struct timeval tv, tv2;
     int x, y, z;
     int c;
     int l;
     int x0, y0;
+    int stat[3];
 
     /* read until there is nothing to read */
     while((c = read_aux_data_no_wait(sc->kbdc)) != -1) {
@@ -2018,6 +2031,14 @@
 	if ((c & sc->mode.syncmask[0]) != sc->mode.syncmask[1]) {
             log(LOG_DEBUG, "psmintr: out of sync (%04x != %04x).\n", 
 		c & sc->mode.syncmask[0], sc->mode.syncmask[1]);
+	    /*
+	     * When we get out of sync record when it happened so that
+	     * we can temporarily turn off data until we're back in sync
+	     * for 'syncholdtime' seconds.
+	     */
+	    sc->syncholdtime.tv_sec = syncholdtime;
+	    sc->syncholdtime.tv_usec = 0;
+	    timevaladd(&sc->syncholdtime, &tv);
 	    ++sc->syncerrors;
 	    if (sc->syncerrors < sc->mode.packetsize) {
 		log(LOG_DEBUG, "psmintr: discard a byte (%d).\n", sc->syncerrors);
@@ -2038,6 +2059,28 @@
 	    }
 	    continue;
 	}
+
+	/*
+	 * Are we still possibly resyncing?
+	 */
+	if (timevalcmp(&tv, &sc->syncholdtime, <)) {
+		sc->inputbytes = 0;
+		continue;
+	}
+	/* If more than 2 seconds have gone by since the last packet
+	 * then make sure our mouse is alright.
+	 */
+	tv2.tv_sec = lastvalidthresh;
+	tv2.tv_usec = 0;
+	timevaladd(&tv2, &sc->lastvalid);
+	if (timevalcmp(&tv2, &tv, <) &&
+	    get_mouse_status(sc->kbdc, stat, 0, 3) < 3) {
+		log(LOG_DEBUG, "psm%d: failed to get status (psmintr).\n",
+		    sc->unit);
+		sc->inputbytes = 0;
+		continue;
+	}
+	sc->lastvalid = tv;
 
 	/* 
 	 * A kludge for Kensington device! 


-- 
- Alfred Perlstein
- Research Engineering Development Inc.
- email: bright@mu.org cell: 408-480-4684



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20031015095928.GC99943>