Subject: kern/16788: pms mouse driver needs to try harder to reset
To: None <gnats-bugs@gnats.netbsd.org>
From: None <apb@cequrux.com>
List: netbsd-bugs
Date: 05/13/2002 15:54:08
>Number:         16788
>Category:       kern
>Synopsis:       pms mouse driver needs to try harder to reset
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon May 13 09:33:00 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator:     Alan Barrett
>Release:        NetBSD 1.5ZC
>Organization:
not much
>Environment:
Architecture: i386
Machine: i386
src/sys/dev/pckbc/psm.c revision 1.20
>Description:
I have an old NEC VERSA 4080H laptop with a trackpad mouse.

The pms mouse driver attaches like this:

    pms0 at pckbc0 (aux slot)
    wsmouse0 at pms0 mux 0
    pms_protocol: standard PS/2 protocol (no scroll wheel)
    pms_enable: using no scroll wheel (3 buttons) protocol

It works fine for a while, but after a suspend/resume cycle the
mouse no longer works.  A kernel built with options PMSDEBUG
reports errors like this:

    pmsinput: 0x8 not set in first byte [0x00], resetting
    pms: resetting mouse interface

I suspect that the trackpad's native protocol is not PS/2 compatible,
that something done by pmsprobe() puts it into PS/2 mode, and that
a suspend/resume cycle puts it back into its native mode.

The appended patch seems to work for me, but is probably not the right
thing.  (I am running with sources from before the psm.c to pms.c
rename.)

>How-To-Repeat:
>Fix:

--- psm.c.orig	Mon May 13 11:27:56 2002
+++ psm.c	Mon May 13 15:30:01 2002
@@ -97,6 +97,7 @@
 static int	pms_protocol __P((pckbc_tag_t, pckbc_slot_t));
 static void	do_enable __P((struct pms_softc *));
 static void	do_disable __P((struct pms_softc *));
+static void	do_really_reset __P((struct pms_softc *));
 static void	pms_reset_thread __P((void*));
 static void	pms_spawn_reset_thread __P((void*));
 int	pms_enable __P((void *));
@@ -314,6 +315,33 @@
 	pckbc_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 0);
 }
 
+static void
+do_really_reset(sc)
+	struct pms_softc *sc;
+{
+	/* 
+	 * XXX: this flush/reset code was adapted from pmsprobe(),
+	 * XXX: and is probably not the right thing.
+	 */
+	u_char cmd[1], resp[2];
+	int res;
+
+	/* Flush any garbage. */
+	pckbc_flush(sc->sc_kbctag, sc->sc_kbcslot);
+
+	/* reset the device */
+	cmd[0] = PMS_RESET;
+	res = pckbc_poll_cmd(sc->sc_kbctag, sc->sc_kbcslot, cmd, 1, 2, resp, 1);
+	if (res) {
+#ifdef DEBUG
+		printf("pms do_really_reset: reset error %d\n", res);
+#endif
+	}
+	if (resp[0] != PMS_RSTDONE) {
+		printf("pms do_really_reset: reset response 0x%x\n", resp[0]);
+	}
+}
+
 int
 pms_enable(v)
 	void *v;
@@ -425,6 +453,7 @@
 		tsleep(&sc->sc_reset_flag, PWAIT, "pmsreset", 0);
 		printf("pms: resetting mouse interface\n");
 		pms_disable(sc);
+		do_really_reset(sc);
 		pms_enable(sc);
 	}
 }
>Release-Note:
>Audit-Trail:
>Unformatted: