(Mostly) backout previous, with some slight modifications.

Restore the reset thread, to make resetting the interface possible while
not blocking interrupts.
Make sure to throw away garbage input while the reset thread is at work
(by setting sc_enabled a bit later).
Issue a PMS_RESET command when resetting to address PR 16788.
This commit is contained in:
martin 2002-05-17 22:49:48 +00:00
parent c37fca45ce
commit bdd46f7081
1 changed files with 52 additions and 51 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: pms.c,v 1.3 2002/05/13 21:18:51 jdolecek Exp $ */ /* $NetBSD: pms.c,v 1.4 2002/05/17 22:49:48 martin Exp $ */
/*- /*-
* Copyright (c) 1994 Charles M. Hannum. * Copyright (c) 1994 Charles M. Hannum.
@ -24,13 +24,13 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: pms.c,v 1.3 2002/05/13 21:18:51 jdolecek Exp $"); __KERNEL_RCSID(0, "$NetBSD: pms.c,v 1.4 2002/05/17 22:49:48 martin Exp $");
#include <sys/param.h> #include <sys/param.h>
#include <sys/systm.h> #include <sys/systm.h>
#include <sys/device.h> #include <sys/device.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/callout.h> #include <sys/kthread.h>
#include <machine/bus.h> #include <machine/bus.h>
@ -82,7 +82,7 @@ struct pms_softc { /* driver status information */
struct timeval last, current; struct timeval last, current;
struct device *sc_wsmousedev; struct device *sc_wsmousedev;
struct callout sc_rst; struct proc *sc_event_thread;
}; };
int pmsprobe __P((struct device *, struct cfdata *, void *)); int pmsprobe __P((struct device *, struct cfdata *, void *));
@ -94,9 +94,10 @@ struct cfattach pms_ca = {
}; };
static int pms_protocol __P((pckbc_tag_t, pckbc_slot_t)); static int pms_protocol __P((pckbc_tag_t, pckbc_slot_t));
static void do_enable __P((struct pms_softc *, int)); static void do_enable __P((struct pms_softc *));
static void do_disable __P((struct pms_softc *, int)); static void do_disable __P((struct pms_softc *));
static void pms_reset __P((void*)); static void pms_reset_thread __P((void*));
static void pms_spawn_reset_thread __P((void*));
int pms_enable __P((void *)); int pms_enable __P((void *));
int pms_ioctl __P((void *, u_long, caddr_t, int, struct proc *)); int pms_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
void pms_disable __P((void *)); void pms_disable __P((void *));
@ -231,9 +232,6 @@ pmsattach(parent, self, aux)
*/ */
sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint); sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
/* Reset callout */
callout_init(&sc->sc_rst);
/* no interrupts until enabled */ /* no interrupts until enabled */
cmd[0] = PMS_DEV_DISABLE; cmd[0] = PMS_DEV_DISABLE;
res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 0, 0, 0); res = pckbc_poll_cmd(pa->pa_tag, pa->pa_slot, cmd, 1, 0, 0, 0);
@ -241,15 +239,16 @@ pmsattach(parent, self, aux)
printf("pmsattach: disable error\n"); printf("pmsattach: disable error\n");
pckbc_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 0); pckbc_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 0);
kthread_create(pms_spawn_reset_thread, sc);
#ifndef PMS_DISABLE_POWERHOOK #ifndef PMS_DISABLE_POWERHOOK
sc->sc_powerhook = powerhook_establish(pms_power, sc); sc->sc_powerhook = powerhook_establish(pms_power, sc);
#endif /* !PMS_DISABLE_POWERHOOK */ #endif /* !PMS_DISABLE_POWERHOOK */
} }
static void static void
do_enable(sc, poll) do_enable(sc)
struct pms_softc *sc; struct pms_softc *sc;
int poll;
{ {
u_char cmd[1]; u_char cmd[1];
int res; int res;
@ -263,13 +262,7 @@ do_enable(sc, poll)
pckbc_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 1); pckbc_slot_enable(sc->sc_kbctag, sc->sc_kbcslot, 1);
cmd[0] = PMS_DEV_ENABLE; cmd[0] = PMS_DEV_ENABLE;
if (poll) { res = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, cmd, 1, 0, 1, 0);
res = pckbc_poll_cmd(sc->sc_kbctag, sc->sc_kbcslot,
cmd, 1, 0, 0, 1);
} else {
res = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot,
cmd, 1, 0, 1, 0);
}
if (res) if (res)
printf("pms_enable: command error %d\n", res); printf("pms_enable: command error %d\n", res);
@ -304,21 +297,14 @@ do_enable(sc, poll)
} }
static void static void
do_disable(sc, poll) do_disable(sc)
struct pms_softc *sc; struct pms_softc *sc;
int poll;
{ {
u_char cmd[1]; u_char cmd[1];
int res; int res;
cmd[0] = PMS_DEV_DISABLE; cmd[0] = PMS_DEV_DISABLE;
if (poll) { res = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, cmd, 1, 0, 1, 0);
res = pckbc_poll_cmd(sc->sc_kbctag, sc->sc_kbcslot, cmd,
1, 0, 0, 1);
} else {
res = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, cmd,
1, 0, 1, 0);
}
if (res) if (res)
printf("pms_disable: command error\n"); printf("pms_disable: command error\n");
@ -330,13 +316,16 @@ pms_enable(v)
void *v; void *v;
{ {
struct pms_softc *sc = v; struct pms_softc *sc = v;
int s;
if (sc->sc_enabled) if (sc->sc_enabled)
return EBUSY; return EBUSY;
sc->sc_enabled = 1; do_enable(sc);
do_enable(sc, 0); s = spltty();
sc->sc_enabled = 1;
splx(s);
return 0; return 0;
} }
@ -347,7 +336,7 @@ pms_disable(v)
{ {
struct pms_softc *sc = v; struct pms_softc *sc = v;
do_disable(sc, 0); do_disable(sc);
sc->sc_enabled = 0; sc->sc_enabled = 0;
} }
@ -364,11 +353,11 @@ pms_power(why, v)
case PWR_SUSPEND: case PWR_SUSPEND:
case PWR_STANDBY: case PWR_STANDBY:
if (sc->sc_enabled) if (sc->sc_enabled)
do_disable(sc, 0); do_disable(sc);
break; break;
case PWR_RESUME: case PWR_RESUME:
if (sc->sc_enabled) if (sc->sc_enabled)
do_enable(sc, 0); do_enable(sc);
case PWR_SOFTSUSPEND: case PWR_SOFTSUSPEND:
case PWR_SOFTSTANDBY: case PWR_SOFTSTANDBY:
case PWR_SOFTRESUME: case PWR_SOFTRESUME:
@ -419,26 +408,41 @@ pms_ioctl(v, cmd, data, flag, p)
} }
static void static void
pms_reset(arg) pms_spawn_reset_thread(arg)
void *arg; void *arg;
{ {
struct pms_softc *sc = arg; struct pms_softc *sc = arg;
int s;
kthread_create1(pms_reset_thread, sc, &sc->sc_event_thread,
sc->sc_dev.dv_xname);
}
static void
pms_reset_thread(arg)
void *arg;
{
struct pms_softc *sc = arg;
u_char cmd[1], resp[2];
int res;
for (;;) {
tsleep(&sc->sc_enabled, PWAIT, "pmsreset", 0);
#ifdef PMSDEBUG #ifdef PMSDEBUG
if (pmsdebug) if (pmsdebug)
#endif #endif
#if defined(PMSDEBUG) || defined(DIAGNOSTIC) #if defined(PMSDEBUG) || defined(DIAGNOSTIC)
printf("%s: resetting mouse interface\n", printf("%s: resetting mouse interface\n",
sc->sc_dev.dv_xname); sc->sc_dev.dv_xname);
#endif #endif
pms_disable(sc);
s = spltty(); cmd[0] = PMS_RESET;
sc->sc_enabled = 0; res = pckbc_enqueue_cmd(sc->sc_kbctag, sc->sc_kbcslot, cmd, 1,
do_disable(sc, 1); 2, 1, resp);
do_enable(sc, 1); if (res)
sc->sc_enabled = 1; DPRINTF(("%s: reset error %d\n", sc->sc_dev.dv_xname,
splx(s); res));
pms_enable(sc);
}
} }
/* Masks for the first byte of a packet */ /* Masks for the first byte of a packet */
@ -486,8 +490,7 @@ pmsinput(vsc, data)
(long)diff.tv_sec, (long)diff.tv_usec)); (long)diff.tv_sec, (long)diff.tv_usec));
sc->inputstate = 0; sc->inputstate = 0;
sc->sc_enabled = 0; sc->sc_enabled = 0;
/* Schedule reset */ wakeup(&sc->sc_enabled);
callout_reset(&sc->sc_rst, 0, pms_reset, sc);
return; return;
} }
} }
@ -504,8 +507,7 @@ pmsinput(vsc, data)
"[0x%02x], resetting\n", sc->packet[0])); "[0x%02x], resetting\n", sc->packet[0]));
sc->inputstate = 0; sc->inputstate = 0;
sc->sc_enabled = 0; sc->sc_enabled = 0;
/* Schedule reset */ wakeup(&sc->sc_enabled);
callout_reset(&sc->sc_rst, 0, pms_reset, sc);
return; return;
} }
break; break;
@ -589,8 +591,7 @@ pmsinput(vsc, data)
printf("pmsinput: very confused. resetting.\n"); printf("pmsinput: very confused. resetting.\n");
sc->inputstate = 0; sc->inputstate = 0;
sc->sc_enabled = 0; sc->sc_enabled = 0;
/* Schedule reset */ wakeup(&sc->sc_enabled);
callout_reset(&sc->sc_rst, 0, pms_reset, sc);
return; return;
} }
} }