1139749Simp/*-
2138755Simp * Copyright (c) 2004 M. Warner Losh
3138755Simp * All rights reserved.
4138755Simp *
5138755Simp * Redistribution and use in source and binary forms, with or without
6138755Simp * modification, are permitted provided that the following conditions
7138755Simp * are met:
8138755Simp * 1. Redistributions of source code must retain the above copyright
9140040Simp *    notice, this list of conditions and the following disclaimer.
10138755Simp * 2. Redistributions in binary form must reproduce the above copyright
11140040Simp *    notice, this list of conditions and the following disclaimer in the
12140040Simp *    documentation and/or other materials provided with the distribution.
13138755Simp *
14138755Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15138755Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16138755Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17140040Simp * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18140040Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19138755Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20138755Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21138755Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22138755Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23138755Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24138755Simp * SUCH DAMAGE.
25138755Simp *
26138755Simp * $FreeBSD$
27138755Simp */
28138755Simp
29138755Simp/*
30637Snate * Copyright 1992 by the University of Guelph
31637Snate *
32637Snate * Permission to use, copy and modify this
33637Snate * software and its documentation for any purpose and without
34637Snate * fee is hereby granted, provided that the above copyright
35637Snate * notice appear in all copies and that both that copyright
36637Snate * notice and this permission notice appear in supporting
37637Snate * documentation.
38637Snate * University of Guelph makes no representations about the suitability of
39637Snate * this software for any purpose.  It is provided "as is"
40637Snate * without express or implied warranty.
41637Snate */
42637Snate/*
43637Snate * Driver for the Logitech and ATI Inport Bus mice for use with 386bsd and
44637Snate * the X386 port, courtesy of
45637Snate * Rick Macklem, rick@snowhite.cis.uoguelph.ca
46637Snate * Caveats: The driver currently uses spltty(), but doesn't use any
47637Snate * generic tty code. It could use splmse() (that only masks off the
48637Snate * bus mouse interrupt, but that would require hacking in i386/isa/icu.s.
49637Snate * (This may be worth the effort, since the Logitech generates 30/60
50637Snate * interrupts/sec continuously while it is open.)
51637Snate * NB: The ATI has NOT been tested yet!
52637Snate */
53637Snate
54637Snate/*
55637Snate * Modification history:
564259Sjkh * Sep 6, 1994 -- Lars Fredriksen(fredriks@mcs.com)
574259Sjkh *   improved probe based on input from Logitech.
58637Snate *
59637Snate * Oct 19, 1992 -- E. Stark (stark@cs.sunysb.edu)
60637Snate *   fixes to make it work with Microsoft InPort busmouse
61637Snate *
62637Snate * Jan, 1993 -- E. Stark (stark@cs.sunysb.edu)
63637Snate *   added patches for new "select" interface
64637Snate *
65637Snate * May 4, 1993 -- E. Stark (stark@cs.sunysb.edu)
66637Snate *   changed position of some spl()'s in mseread
67637Snate *
68637Snate * October 8, 1993 -- E. Stark (stark@cs.sunysb.edu)
69637Snate *   limit maximum negative x/y value to -127 to work around XFree problem
70637Snate *   that causes spurious button pushes.
71637Snate */
72637Snate
732056Swollman#include <sys/param.h>
743745Swollman#include <sys/systm.h>
7512658Sbde#include <sys/conf.h>
762056Swollman#include <sys/kernel.h>
77129882Sphk#include <sys/module.h>
7858229Syokota#include <sys/bus.h>
7929368Speter#include <sys/poll.h>
8071286Swollman#include <sys/selinfo.h>
812056Swollman#include <sys/uio.h>
8266860Sphk#include <sys/mouse.h>
83637Snate
8458229Syokota#include <machine/bus.h>
8558229Syokota#include <machine/resource.h>
8658229Syokota#include <sys/rman.h>
877430Sbde
8858229Syokota#include <isa/isavar.h>
89637Snate
90138755Simp#include <dev/mse/msevar.h>
9131603Syokota
92138755Simpdevclass_t	mse_devclass;
93637Snate
9412675Sjulianstatic	d_open_t	mseopen;
9512675Sjulianstatic	d_close_t	mseclose;
9612675Sjulianstatic	d_read_t	mseread;
9731603Syokotastatic  d_ioctl_t	mseioctl;
9829368Speterstatic	d_poll_t	msepoll;
9912675Sjulian
10047625Sphkstatic struct cdevsw mse_cdevsw = {
101126080Sphk	.d_version =	D_VERSION,
102111815Sphk	.d_open =	mseopen,
103111815Sphk	.d_close =	mseclose,
104111815Sphk	.d_read =	mseread,
105111815Sphk	.d_ioctl =	mseioctl,
106111815Sphk	.d_poll =	msepoll,
107111815Sphk	.d_name =	"mse",
10847625Sphk};
10912675Sjulian
11092765Salfredstatic	void		mseintr(void *);
111272956Sjhbstatic	void		mseintr_locked(mse_softc_t *sc);
112272956Sjhbstatic	void		msetimeout(void *);
11312675Sjulian
114272956Sjhb#define	MSE_NBLOCKIO(dev)	(dev2unit(dev) != 0)
115637Snate
116637Snate#define	MSEPRI	(PZERO + 3)
117637Snate
118138755Simpint
119138755Simpmse_common_attach(device_t dev)
120637Snate{
12158229Syokota	mse_softc_t *sc;
122138755Simp	int unit, flags, rid;
123637Snate
12458229Syokota	sc = device_get_softc(dev);
12558229Syokota	unit = device_get_unit(dev);
126272956Sjhb	mtx_init(&sc->sc_lock, "mse", NULL, MTX_DEF);
127272956Sjhb	callout_init_mtx(&sc->sc_callout, &sc->sc_lock, 0);
12858229Syokota
12958229Syokota	rid = 0;
130138755Simp	sc->sc_intr = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
131138755Simp					     RF_ACTIVE);
13258229Syokota	if (sc->sc_intr == NULL) {
13358229Syokota		bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->sc_port);
134272956Sjhb		mtx_destroy(&sc->sc_lock);
13558229Syokota		return ENXIO;
13658229Syokota	}
13758229Syokota
138272956Sjhb	if (bus_setup_intr(dev, sc->sc_intr, INTR_TYPE_TTY | INTR_MPSAFE,
139272956Sjhb	    NULL, mseintr, sc, &sc->sc_ih)) {
14058229Syokota		bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->sc_port);
14158229Syokota		bus_release_resource(dev, SYS_RES_IRQ, rid, sc->sc_intr);
142272956Sjhb		mtx_destroy(&sc->sc_lock);
14358229Syokota		return ENXIO;
14458229Syokota	}
14558229Syokota	flags = device_get_flags(dev);
14658229Syokota	sc->mode.accelfactor = (flags & MSE_CONFIG_ACCEL) >> 4;
14758229Syokota
148272956Sjhb	sc->sc_dev = make_dev(&mse_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
149272956Sjhb	    "mse%d", unit);
150191320Sed	sc->sc_dev->si_drv1 = sc;
151272956Sjhb	sc->sc_ndev = make_dev(&mse_cdevsw, 1, UID_ROOT, GID_WHEEL, 0600,
152272956Sjhb	    "nmse%d", unit);
153191320Sed	sc->sc_ndev->si_drv1 = sc;
15458229Syokota	return 0;
155637Snate}
156637Snate
157272956Sjhbint
158272956Sjhbmse_detach(device_t dev)
159272956Sjhb{
160272956Sjhb	mse_softc_t *sc;
161272956Sjhb	int rid;
162272956Sjhb
163272956Sjhb	sc = device_get_softc(dev);
164272956Sjhb	MSE_LOCK(sc);
165272956Sjhb	if (sc->sc_flags & MSESC_OPEN) {
166272956Sjhb		MSE_UNLOCK(sc);
167272956Sjhb		return EBUSY;
168272956Sjhb	}
169272956Sjhb
170272956Sjhb	/* Sabotage subsequent opens. */
171272956Sjhb	sc->sc_mousetype = MSE_NONE;
172272956Sjhb	MSE_UNLOCK(sc);
173272956Sjhb
174272956Sjhb	destroy_dev(sc->sc_dev);
175272956Sjhb	destroy_dev(sc->sc_ndev);
176272956Sjhb
177272956Sjhb	rid = 0;
178272956Sjhb	bus_teardown_intr(dev, sc->sc_intr, sc->sc_ih);
179272956Sjhb	bus_release_resource(dev, SYS_RES_IRQ, rid, sc->sc_intr);
180272956Sjhb	bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->sc_port);
181272956Sjhb
182272956Sjhb	callout_drain(&sc->sc_callout);
183272956Sjhb	mtx_destroy(&sc->sc_lock);
184272956Sjhb
185272956Sjhb	return 0;
186272956Sjhb}
187272956Sjhb
188637Snate/*
189637Snate * Exclusive open the mouse, initialize it and enable interrupts.
190637Snate */
19112675Sjulianstatic	int
192144783Simpmseopen(struct cdev *dev, int flags, int fmt, struct thread *td)
193637Snate{
194191320Sed	mse_softc_t *sc = dev->si_drv1;
195637Snate
196272956Sjhb	MSE_LOCK(sc);
197272956Sjhb	if (sc->sc_mousetype == MSE_NONE) {
198272956Sjhb		MSE_UNLOCK(sc);
19920688Sjoerg		return (ENXIO);
200272956Sjhb	}
201272956Sjhb	if (sc->sc_flags & MSESC_OPEN) {
202272956Sjhb		MSE_UNLOCK(sc);
203637Snate		return (EBUSY);
204272956Sjhb	}
205637Snate	sc->sc_flags |= MSESC_OPEN;
20631603Syokota	sc->sc_obuttons = sc->sc_buttons = MOUSE_MSC_BUTTONS;
207637Snate	sc->sc_deltax = sc->sc_deltay = 0;
20831603Syokota	sc->sc_bytesread = sc->mode.packetsize = MOUSE_MSC_PACKETSIZE;
20958229Syokota	sc->sc_watchdog = FALSE;
210272956Sjhb	callout_reset(&sc->sc_callout, hz * 2, msetimeout, dev);
21131603Syokota	sc->mode.level = 0;
21231603Syokota	sc->status.flags = 0;
21331603Syokota	sc->status.button = sc->status.obutton = 0;
21431603Syokota	sc->status.dx = sc->status.dy = sc->status.dz = 0;
215637Snate
216637Snate	/*
217637Snate	 * Initialize mouse interface and enable interrupts.
218637Snate	 */
219272956Sjhb	(*sc->sc_enablemouse)(sc->sc_port);
220272956Sjhb	MSE_UNLOCK(sc);
221637Snate	return (0);
222637Snate}
223637Snate
224637Snate/*
225637Snate * mseclose: just turn off mouse innterrupts.
226637Snate */
22712675Sjulianstatic	int
228144783Simpmseclose(struct cdev *dev, int flags, int fmt, struct thread *td)
229637Snate{
230191320Sed	mse_softc_t *sc = dev->si_drv1;
231637Snate
232272956Sjhb	MSE_LOCK(sc);
233272956Sjhb	callout_stop(&sc->sc_callout);
234272956Sjhb	(*sc->sc_disablemouse)(sc->sc_port);
235637Snate	sc->sc_flags &= ~MSESC_OPEN;
236272956Sjhb	MSE_UNLOCK(sc);
237637Snate	return(0);
238637Snate}
239637Snate
2408876Srgrimes/*
241637Snate * mseread: return mouse info using the MSC serial protocol, but without
242637Snate * using bytes 4 and 5.
243637Snate * (Yes this is cheesy, but it makes the X386 server happy, so...)
244637Snate */
24512675Sjulianstatic	int
246144783Simpmseread(struct cdev *dev, struct uio *uio, int ioflag)
247637Snate{
248191320Sed	mse_softc_t *sc = dev->si_drv1;
249272956Sjhb	int xfer, error;
250637Snate
251637Snate	/*
252637Snate	 * If there are no protocol bytes to be read, set up a new protocol
253637Snate	 * packet.
254637Snate	 */
255272956Sjhb	MSE_LOCK(sc);
256272956Sjhb	while (sc->sc_flags & MSESC_READING) {
257272956Sjhb		if (MSE_NBLOCKIO(dev)) {
258272956Sjhb			MSE_UNLOCK(sc);
259272956Sjhb			return (0);
260272956Sjhb		}
261272956Sjhb		sc->sc_flags |= MSESC_WANT;
262272956Sjhb		error = mtx_sleep(sc, &sc->sc_lock, MSEPRI | PCATCH, "mseread",
263272956Sjhb		    0);
264272956Sjhb		if (error) {
265272956Sjhb			MSE_UNLOCK(sc);
266272956Sjhb			return (error);
267272956Sjhb		}
268272956Sjhb	}
269272956Sjhb	sc->sc_flags |= MSESC_READING;
270272956Sjhb	xfer = 0;
27131603Syokota	if (sc->sc_bytesread >= sc->mode.packetsize) {
272637Snate		while (sc->sc_deltax == 0 && sc->sc_deltay == 0 &&
273637Snate		       (sc->sc_obuttons ^ sc->sc_buttons) == 0) {
274272956Sjhb			if (MSE_NBLOCKIO(dev))
275272956Sjhb				goto out;
276637Snate			sc->sc_flags |= MSESC_WANT;
277272956Sjhb			error = mtx_sleep(sc, &sc->sc_lock, MSEPRI | PCATCH,
27846571Speter				"mseread", 0);
279272956Sjhb			if (error)
280272956Sjhb				goto out;
281637Snate		}
282637Snate
283637Snate		/*
284637Snate		 * Generate protocol bytes.
285637Snate		 * For some reason X386 expects 5 bytes but never uses
286637Snate		 * the fourth or fifth?
287637Snate		 */
28831603Syokota		sc->sc_bytes[0] = sc->mode.syncmask[1]
28931603Syokota		    | (sc->sc_buttons & ~sc->mode.syncmask[0]);
290637Snate		if (sc->sc_deltax > 127)
291637Snate			sc->sc_deltax = 127;
292637Snate		if (sc->sc_deltax < -127)
293637Snate			sc->sc_deltax = -127;
294637Snate		sc->sc_deltay = -sc->sc_deltay;	/* Otherwise mousey goes wrong way */
295637Snate		if (sc->sc_deltay > 127)
296637Snate			sc->sc_deltay = 127;
297637Snate		if (sc->sc_deltay < -127)
298637Snate			sc->sc_deltay = -127;
299637Snate		sc->sc_bytes[1] = sc->sc_deltax;
300637Snate		sc->sc_bytes[2] = sc->sc_deltay;
301637Snate		sc->sc_bytes[3] = sc->sc_bytes[4] = 0;
30231603Syokota		sc->sc_bytes[5] = sc->sc_bytes[6] = 0;
30331603Syokota		sc->sc_bytes[7] = MOUSE_SYS_EXTBUTTONS;
304637Snate		sc->sc_obuttons = sc->sc_buttons;
305637Snate		sc->sc_deltax = sc->sc_deltay = 0;
306637Snate		sc->sc_bytesread = 0;
307637Snate	}
30831603Syokota	xfer = min(uio->uio_resid, sc->mode.packetsize - sc->sc_bytesread);
309272956Sjhb	MSE_UNLOCK(sc);
31046571Speter	error = uiomove(&sc->sc_bytes[sc->sc_bytesread], xfer, uio);
311272956Sjhb	MSE_LOCK(sc);
312272956Sjhbout:
313272956Sjhb	sc->sc_flags &= ~MSESC_READING;
314272956Sjhb	if (error == 0)
315272956Sjhb		sc->sc_bytesread += xfer;
316272956Sjhb	if (sc->sc_flags & MSESC_WANT) {
317272956Sjhb		sc->sc_flags &= ~MSESC_WANT;
318272956Sjhb		MSE_UNLOCK(sc);
319272956Sjhb		wakeup(sc);
320272956Sjhb	} else
321272956Sjhb		MSE_UNLOCK(sc);
322272956Sjhb	return (error);
323637Snate}
324637Snate
325637Snate/*
32631603Syokota * mseioctl: process ioctl commands.
32731603Syokota */
32831603Syokotastatic int
329144783Simpmseioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
33031603Syokota{
331191320Sed	mse_softc_t *sc = dev->si_drv1;
33231603Syokota	mousestatus_t status;
33331603Syokota	int err = 0;
33431603Syokota
33531603Syokota	switch (cmd) {
33631603Syokota
33731603Syokota	case MOUSE_GETHWINFO:
338272956Sjhb		MSE_LOCK(sc);
33931603Syokota		*(mousehw_t *)addr = sc->hw;
34031603Syokota		if (sc->mode.level == 0)
34131603Syokota			((mousehw_t *)addr)->model = MOUSE_MODEL_GENERIC;
342272956Sjhb		MSE_UNLOCK(sc);
34331603Syokota		break;
34431603Syokota
34531603Syokota	case MOUSE_GETMODE:
346272956Sjhb		MSE_LOCK(sc);
34731603Syokota		*(mousemode_t *)addr = sc->mode;
34831603Syokota		switch (sc->mode.level) {
34931603Syokota		case 0:
35031603Syokota			break;
35131603Syokota		case 1:
35231603Syokota			((mousemode_t *)addr)->protocol = MOUSE_PROTO_SYSMOUSE;
35331603Syokota	    		((mousemode_t *)addr)->syncmask[0] = MOUSE_SYS_SYNCMASK;
35431603Syokota	    		((mousemode_t *)addr)->syncmask[1] = MOUSE_SYS_SYNC;
35531603Syokota			break;
35631603Syokota		}
357272956Sjhb		MSE_UNLOCK(sc);
35831603Syokota		break;
35931603Syokota
36031603Syokota	case MOUSE_SETMODE:
36131603Syokota		switch (((mousemode_t *)addr)->level) {
36231603Syokota		case 0:
36331603Syokota		case 1:
36431603Syokota			break;
36531603Syokota		default:
36631603Syokota			return (EINVAL);
36731603Syokota		}
368272956Sjhb		MSE_LOCK(sc);
369272956Sjhb		if (((mousemode_t *)addr)->accelfactor < -1) {
370272956Sjhb			MSE_UNLOCK(sc);
37131603Syokota			return (EINVAL);
372272956Sjhb		} else if (((mousemode_t *)addr)->accelfactor >= 0)
37331603Syokota			sc->mode.accelfactor =
37431603Syokota			    ((mousemode_t *)addr)->accelfactor;
37531603Syokota		sc->mode.level = ((mousemode_t *)addr)->level;
37631603Syokota		switch (sc->mode.level) {
37731603Syokota		case 0:
37831603Syokota			sc->sc_bytesread = sc->mode.packetsize
37931603Syokota			    = MOUSE_MSC_PACKETSIZE;
38031603Syokota			break;
38131603Syokota		case 1:
38231603Syokota			sc->sc_bytesread = sc->mode.packetsize
38331603Syokota			    = MOUSE_SYS_PACKETSIZE;
38431603Syokota			break;
38531603Syokota		}
386272956Sjhb		MSE_UNLOCK(sc);
38731603Syokota		break;
38831603Syokota
38931603Syokota	case MOUSE_GETLEVEL:
390272956Sjhb		MSE_LOCK(sc);
39131603Syokota		*(int *)addr = sc->mode.level;
392272956Sjhb		MSE_UNLOCK(sc);
39331603Syokota		break;
39431603Syokota
39531603Syokota	case MOUSE_SETLEVEL:
39631603Syokota		switch (*(int *)addr) {
39731603Syokota		case 0:
398272956Sjhb			MSE_LOCK(sc);
39931603Syokota			sc->mode.level = *(int *)addr;
40031603Syokota			sc->sc_bytesread = sc->mode.packetsize
40131603Syokota			    = MOUSE_MSC_PACKETSIZE;
402272956Sjhb			MSE_UNLOCK(sc);
40331603Syokota			break;
40431603Syokota		case 1:
405272956Sjhb			MSE_LOCK(sc);
40631603Syokota			sc->mode.level = *(int *)addr;
40731603Syokota			sc->sc_bytesread = sc->mode.packetsize
40831603Syokota			    = MOUSE_SYS_PACKETSIZE;
409272956Sjhb			MSE_UNLOCK(sc);
41031603Syokota			break;
41131603Syokota		default:
41231603Syokota			return (EINVAL);
41331603Syokota		}
41431603Syokota		break;
41531603Syokota
41631603Syokota	case MOUSE_GETSTATUS:
417272956Sjhb		MSE_LOCK(sc);
41831603Syokota		status = sc->status;
41931603Syokota		sc->status.flags = 0;
42031603Syokota		sc->status.obutton = sc->status.button;
42131603Syokota		sc->status.button = 0;
42231603Syokota		sc->status.dx = 0;
42331603Syokota		sc->status.dy = 0;
42431603Syokota		sc->status.dz = 0;
425272956Sjhb		MSE_UNLOCK(sc);
42631603Syokota		*(mousestatus_t *)addr = status;
42731603Syokota		break;
42831603Syokota
42931603Syokota	case MOUSE_READSTATE:
43031603Syokota	case MOUSE_READDATA:
43131603Syokota		return (ENODEV);
43231603Syokota
43331603Syokota#if (defined(MOUSE_GETVARS))
43431603Syokota	case MOUSE_GETVARS:
43531603Syokota	case MOUSE_SETVARS:
43631603Syokota		return (ENODEV);
43731603Syokota#endif
43831603Syokota
43931603Syokota	default:
44031603Syokota		return (ENOTTY);
44131603Syokota	}
44231603Syokota	return (err);
44331603Syokota}
44431603Syokota
44531603Syokota/*
44629368Speter * msepoll: check for mouse input to be processed.
447637Snate */
44812675Sjulianstatic	int
449144783Simpmsepoll(struct cdev *dev, int events, struct thread *td)
450637Snate{
451191320Sed	mse_softc_t *sc = dev->si_drv1;
45229368Speter	int revents = 0;
453637Snate
454272956Sjhb	MSE_LOCK(sc);
45546568Speter	if (events & (POLLIN | POLLRDNORM)) {
45631603Syokota		if (sc->sc_bytesread != sc->mode.packetsize ||
45731603Syokota		    sc->sc_deltax != 0 || sc->sc_deltay != 0 ||
45829368Speter		    (sc->sc_obuttons ^ sc->sc_buttons) != 0)
45929368Speter			revents |= events & (POLLIN | POLLRDNORM);
460272956Sjhb		else
46183366Sjulian			selrecord(td, &sc->sc_selp);
46246568Speter	}
463272956Sjhb	MSE_UNLOCK(sc);
46429368Speter	return (revents);
465637Snate}
466637Snate
467637Snate/*
46858229Syokota * msetimeout: watchdog timer routine.
46958229Syokota */
47058229Syokotastatic void
471144783Simpmsetimeout(void *arg)
47258229Syokota{
473130585Sphk	struct cdev *dev;
47458229Syokota	mse_softc_t *sc;
47558229Syokota
476130585Sphk	dev = (struct cdev *)arg;
477191320Sed	sc = dev->si_drv1;
478272956Sjhb	MSE_ASSERT_LOCKED(sc);
47958229Syokota	if (sc->sc_watchdog) {
48058229Syokota		if (bootverbose)
481191320Sed			printf("%s: lost interrupt?\n", devtoname(dev));
482272956Sjhb		mseintr_locked(sc);
48358229Syokota	}
48458229Syokota	sc->sc_watchdog = TRUE;
485272956Sjhb	callout_schedule(&sc->sc_callout, hz);
48658229Syokota}
48758229Syokota
48858229Syokota/*
489637Snate * mseintr: update mouse status. sc_deltax and sc_deltay are accumulative.
490637Snate */
49140565Sbdestatic void
492144783Simpmseintr(void *arg)
493637Snate{
494272956Sjhb	mse_softc_t *sc = arg;
495272956Sjhb
496272956Sjhb	MSE_LOCK(sc);
497272956Sjhb	mseintr_locked(sc);
498272956Sjhb	MSE_UNLOCK(sc);
499272956Sjhb}
500272956Sjhb
501272956Sjhbstatic void
502272956Sjhbmseintr_locked(mse_softc_t *sc)
503272956Sjhb{
50431603Syokota	/*
50531603Syokota	 * the table to turn MouseSystem button bits (MOUSE_MSC_BUTTON?UP)
50631603Syokota	 * into `mousestatus' button bits (MOUSE_BUTTON?DOWN).
50731603Syokota	 */
50831603Syokota	static int butmap[8] = {
50931603Syokota		0,
51031603Syokota		MOUSE_BUTTON3DOWN,
51131603Syokota		MOUSE_BUTTON2DOWN,
51231603Syokota		MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN,
51331603Syokota		MOUSE_BUTTON1DOWN,
51431603Syokota		MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN,
51531603Syokota		MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN,
51631603Syokota        	MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN
51731603Syokota	};
51831603Syokota	int dx, dy, but;
51931603Syokota	int sign;
520637Snate
521637Snate#ifdef DEBUG
522637Snate	static int mse_intrcnt = 0;
523637Snate	if((mse_intrcnt++ % 10000) == 0)
524637Snate		printf("mseintr\n");
525637Snate#endif /* DEBUG */
526637Snate	if ((sc->sc_flags & MSESC_OPEN) == 0)
527637Snate		return;
528637Snate
529272956Sjhb	(*sc->sc_getmouse)(sc->sc_port, &dx, &dy, &but);
53031603Syokota	if (sc->mode.accelfactor > 0) {
53131603Syokota		sign = (dx < 0);
53231603Syokota		dx = dx * dx / sc->mode.accelfactor;
53331603Syokota		if (dx == 0)
53431603Syokota			dx = 1;
53531603Syokota		if (sign)
53631603Syokota			dx = -dx;
53731603Syokota		sign = (dy < 0);
53831603Syokota		dy = dy * dy / sc->mode.accelfactor;
53931603Syokota		if (dy == 0)
54031603Syokota			dy = 1;
54131603Syokota		if (sign)
54231603Syokota			dy = -dy;
54331603Syokota	}
54431603Syokota	sc->sc_deltax += dx;
54531603Syokota	sc->sc_deltay += dy;
54631603Syokota	sc->sc_buttons = but;
547637Snate
54831603Syokota	but = butmap[~but & MOUSE_MSC_BUTTONS];
54931603Syokota	sc->status.dx += dx;
55031603Syokota	sc->status.dy += dy;
55131603Syokota	sc->status.flags |= ((dx || dy) ? MOUSE_POSCHANGED : 0)
55231603Syokota	    | (sc->status.button ^ but);
55331603Syokota	sc->status.button = but;
55431603Syokota
55558229Syokota	sc->sc_watchdog = FALSE;
55658229Syokota
557637Snate	/*
558637Snate	 * If mouse state has changed, wake up anyone wanting to know.
559637Snate	 */
560637Snate	if (sc->sc_deltax != 0 || sc->sc_deltay != 0 ||
561637Snate	    (sc->sc_obuttons ^ sc->sc_buttons) != 0) {
5628876Srgrimes		if (sc->sc_flags & MSESC_WANT) {
5638876Srgrimes			sc->sc_flags &= ~MSESC_WANT;
564111748Sdes			wakeup(sc);
5658876Srgrimes		}
566122352Stanimura		selwakeuppri(&sc->sc_selp, MSEPRI);
567637Snate	}
568637Snate}
569