mse.c revision 32726
1637Snate/*
2637Snate * Copyright 1992 by the University of Guelph
3637Snate *
4637Snate * Permission to use, copy and modify this
5637Snate * software and its documentation for any purpose and without
6637Snate * fee is hereby granted, provided that the above copyright
7637Snate * notice appear in all copies and that both that copyright
8637Snate * notice and this permission notice appear in supporting
9637Snate * documentation.
10637Snate * University of Guelph makes no representations about the suitability of
11637Snate * this software for any purpose.  It is provided "as is"
12637Snate * without express or implied warranty.
131817Sdg *
1432726Seivind * $Id: mse.c,v 1.36 1997/12/07 08:09:16 yokota Exp $
15637Snate */
16637Snate/*
17637Snate * Driver for the Logitech and ATI Inport Bus mice for use with 386bsd and
18637Snate * the X386 port, courtesy of
19637Snate * Rick Macklem, rick@snowhite.cis.uoguelph.ca
20637Snate * Caveats: The driver currently uses spltty(), but doesn't use any
21637Snate * generic tty code. It could use splmse() (that only masks off the
22637Snate * bus mouse interrupt, but that would require hacking in i386/isa/icu.s.
23637Snate * (This may be worth the effort, since the Logitech generates 30/60
24637Snate * interrupts/sec continuously while it is open.)
25637Snate * NB: The ATI has NOT been tested yet!
26637Snate */
27637Snate
28637Snate/*
29637Snate * Modification history:
304259Sjkh * Sep 6, 1994 -- Lars Fredriksen(fredriks@mcs.com)
314259Sjkh *   improved probe based on input from Logitech.
32637Snate *
33637Snate * Oct 19, 1992 -- E. Stark (stark@cs.sunysb.edu)
34637Snate *   fixes to make it work with Microsoft InPort busmouse
35637Snate *
36637Snate * Jan, 1993 -- E. Stark (stark@cs.sunysb.edu)
37637Snate *   added patches for new "select" interface
38637Snate *
39637Snate * May 4, 1993 -- E. Stark (stark@cs.sunysb.edu)
40637Snate *   changed position of some spl()'s in mseread
41637Snate *
42637Snate * October 8, 1993 -- E. Stark (stark@cs.sunysb.edu)
43637Snate *   limit maximum negative x/y value to -127 to work around XFree problem
44637Snate *   that causes spurious button pushes.
45637Snate */
46637Snate
47637Snate#include "mse.h"
48637Snate#if NMSE > 0
4932726Seivind#include "opt_devfs.h"
5032726Seivind
512056Swollman#include <sys/param.h>
523745Swollman#include <sys/systm.h>
5312658Sbde#include <sys/conf.h>
542056Swollman#include <sys/kernel.h>
5529368Speter#include <sys/poll.h>
5631254Sbde#include <sys/select.h>
572056Swollman#include <sys/uio.h>
5812675Sjulian#ifdef DEVFS
5912675Sjulian#include <sys/devfsext.h>
6012675Sjulian#endif /*DEVFS*/
61637Snate
627430Sbde#include <machine/clock.h>
6331603Syokota#include <machine/mouse.h>
647430Sbde
652056Swollman#include <i386/isa/isa_device.h>
66637Snate
6731603Syokota/* driver configuration flags (config) */
6831603Syokota#define MSE_CONFIG_ACCEL	0x00f0  /* acceleration factor */
6931603Syokota#define MSE_CONFIG_FLAGS	(MSE_CONFIG_ACCEL)
7031603Syokota
71798Swollmanstatic int mseprobe(struct isa_device *);
72798Swollmanstatic int mseattach(struct isa_device *);
73637Snate
74637Snatestruct	isa_driver msedriver = {
75637Snate	mseprobe, mseattach, "mse"
76637Snate};
77637Snate
7812675Sjulianstatic	d_open_t	mseopen;
7912675Sjulianstatic	d_close_t	mseclose;
8012675Sjulianstatic	d_read_t	mseread;
8131603Syokotastatic  d_ioctl_t	mseioctl;
8229368Speterstatic	d_poll_t	msepoll;
8312675Sjulian
8412675Sjulian#define CDEV_MAJOR 27
8512678Sphkstatic struct cdevsw mse_cdevsw =
8612675Sjulian	{ mseopen,	mseclose,	mseread,	nowrite,	/*27*/
8731603Syokota	  mseioctl,	nostop,		nullreset,	nodevtotty,/* mse */
8829368Speter	  msepoll,	nommap,		NULL,	"mse",	NULL,	-1 };
8912675Sjulian
9012675Sjulian
91637Snate/*
92637Snate * Software control structure for mouse. The sc_enablemouse(),
93637Snate * sc_disablemouse() and sc_getmouse() routines must be called spl'd().
94637Snate */
9512724Sphkstatic struct mse_softc {
96637Snate	int	sc_flags;
97637Snate	int	sc_mousetype;
981549Srgrimes	struct	selinfo sc_selp;
99637Snate	u_int	sc_port;
10012854Sbde	void	(*sc_enablemouse) __P((u_int port));
10112854Sbde	void	(*sc_disablemouse) __P((u_int port));
10212854Sbde	void	(*sc_getmouse) __P((u_int port, int *dx, int *dy, int *but));
103637Snate	int	sc_deltax;
104637Snate	int	sc_deltay;
105637Snate	int	sc_obuttons;
106637Snate	int	sc_buttons;
107637Snate	int	sc_bytesread;
10831603Syokota	u_char	sc_bytes[MOUSE_SYS_PACKETSIZE];
10931603Syokota	mousehw_t	hw;
11031603Syokota	mousemode_t	mode;
11131603Syokota	mousestatus_t	status;
11212675Sjulian#ifdef DEVFS
11312675Sjulian	void 	*devfs_token;
11412675Sjulian	void	*n_devfs_token;
11512675Sjulian#endif
116637Snate} mse_sc[NMSE];
117637Snate
118637Snate/* Flags */
119637Snate#define	MSESC_OPEN	0x1
120637Snate#define	MSESC_WANT	0x2
121637Snate
122637Snate/* and Mouse Types */
12320688Sjoerg#define	MSE_NONE	0	/* don't move this! */
124637Snate#define	MSE_LOGITECH	0x1
125637Snate#define	MSE_ATIINPORT	0x2
1264259Sjkh#define	MSE_LOGI_SIG	0xA5
127637Snate
128637Snate#define	MSE_PORTA	0
129637Snate#define	MSE_PORTB	1
130637Snate#define	MSE_PORTC	2
131637Snate#define	MSE_PORTD	3
132637Snate
133637Snate#define	MSE_UNIT(dev)		(minor(dev) >> 1)
134637Snate#define	MSE_NBLOCKIO(dev)	(minor(dev) & 0x1)
135637Snate
136637Snate/*
137637Snate * Logitech bus mouse definitions
138637Snate */
139637Snate#define	MSE_SETUP	0x91	/* What does this mean? */
1404259Sjkh				/* The definition for the control port */
1414259Sjkh				/* is as follows: */
1428876Srgrimes
1434259Sjkh				/* D7 	 =  Mode set flag (1 = active) 	*/
1448876Srgrimes				/* D6,D5 =  Mode selection (port A) 	*/
1454259Sjkh				/* 	    00 = Mode 0 = Basic I/O 	*/
1464259Sjkh				/* 	    01 = Mode 1 = Strobed I/O 	*/
1474259Sjkh				/* 	    10 = Mode 2 = Bi-dir bus 	*/
1484259Sjkh				/* D4	 =  Port A direction (1 = input)*/
1494259Sjkh				/* D3	 =  Port C (upper 4 bits) 	*/
1504259Sjkh				/*	    direction. (1 = input)	*/
1514259Sjkh				/* D2	 =  Mode selection (port B & C) */
1524259Sjkh				/*	    0 = Mode 0 = Basic I/O	*/
1534259Sjkh				/*	    1 = Mode 1 = Strobed I/O	*/
1544259Sjkh				/* D1	 =  Port B direction (1 = input)*/
1554259Sjkh				/* D0	 =  Port C (lower 4 bits)	*/
1564259Sjkh				/*	    direction. (1 = input)	*/
1578876Srgrimes
1584259Sjkh				/* So 91 means Basic I/O on all 3 ports,*/
1594259Sjkh				/* Port A is an input port, B is an 	*/
1604259Sjkh				/* output port, C is split with upper	*/
1614259Sjkh				/* 4 bits being an output port and lower*/
1624259Sjkh				/* 4 bits an input port, and enable the */
1634259Sjkh				/* sucker.				*/
1644259Sjkh				/* Courtesy Intel 8255 databook. Lars   */
165637Snate#define	MSE_HOLD	0x80
166637Snate#define	MSE_RXLOW	0x00
167637Snate#define	MSE_RXHIGH	0x20
168637Snate#define	MSE_RYLOW	0x40
169637Snate#define	MSE_RYHIGH	0x60
170637Snate#define	MSE_DISINTR	0x10
171637Snate#define MSE_INTREN	0x00
172637Snate
17312854Sbdestatic int mse_probelogi __P((struct isa_device *idp));
17412854Sbdestatic void mse_disablelogi __P((u_int port));
17512854Sbdestatic void mse_getlogi __P((u_int port, int *dx, int *dy, int *but));
17612854Sbdestatic void mse_enablelogi __P((u_int port));
177637Snate
178637Snate/*
179637Snate * ATI Inport mouse definitions
180637Snate */
181637Snate#define	MSE_INPORT_RESET	0x80
182637Snate#define	MSE_INPORT_STATUS	0x00
183637Snate#define	MSE_INPORT_DX		0x01
184637Snate#define	MSE_INPORT_DY		0x02
185637Snate#define	MSE_INPORT_MODE		0x07
186637Snate#define	MSE_INPORT_HOLD		0x20
187637Snate#define	MSE_INPORT_INTREN	0x09
188637Snate
18912854Sbdestatic int mse_probeati __P((struct isa_device *idp));
19012854Sbdestatic void mse_enableati __P((u_int port));
19112854Sbdestatic void mse_disableati __P((u_int port));
19212854Sbdestatic void mse_getati __P((u_int port, int *dx, int *dy, int *but));
193637Snate
194637Snate#define	MSEPRI	(PZERO + 3)
195637Snate
196637Snate/*
197637Snate * Table of mouse types.
198637Snate * Keep the Logitech last, since I haven't figured out how to probe it
199637Snate * properly yet. (Someday I'll have the documentation.)
200637Snate */
20112724Sphkstatic struct mse_types {
202637Snate	int	m_type;		/* Type of bus mouse */
20312854Sbde	int	(*m_probe) __P((struct isa_device *idp));
20412854Sbde				/* Probe routine to test for it */
20512854Sbde	void	(*m_enable) __P((u_int port));
20612854Sbde				/* Start routine */
20712854Sbde	void	(*m_disable) __P((u_int port));
20812854Sbde				/* Disable interrupts routine */
20912854Sbde	void	(*m_get) __P((u_int port, int *dx, int *dy, int *but));
21012854Sbde				/* and get mouse status */
21131603Syokota	mousehw_t   m_hw;	/* buttons iftype type model hwid */
21231603Syokota	mousemode_t m_mode;	/* proto rate res accel level size mask */
213637Snate} mse_types[] = {
21431603Syokota	{ MSE_ATIINPORT,
21531603Syokota	  mse_probeati, mse_enableati, mse_disableati, mse_getati,
21631603Syokota	  { 2, MOUSE_IF_INPORT, MOUSE_MOUSE, MOUSE_MODEL_GENERIC, 0, },
21731603Syokota	  { MOUSE_PROTO_INPORT, -1, -1, 0, 0, MOUSE_MSC_PACKETSIZE,
21831603Syokota	    { MOUSE_MSC_SYNCMASK, MOUSE_MSC_SYNC, }, }, },
21931603Syokota	{ MSE_LOGITECH,
22031603Syokota	  mse_probelogi, mse_enablelogi, mse_disablelogi, mse_getlogi,
22131603Syokota	  { 2, MOUSE_IF_BUS, MOUSE_MOUSE, MOUSE_MODEL_GENERIC, 0, },
22231603Syokota	  { MOUSE_PROTO_BUS, -1, -1, 0, 0, MOUSE_MSC_PACKETSIZE,
22331603Syokota	    { MOUSE_MSC_SYNCMASK, MOUSE_MSC_SYNC, }, }, },
224637Snate	{ 0, },
225637Snate};
226637Snate
227798Swollmanint
228637Snatemseprobe(idp)
229637Snate	register struct isa_device *idp;
230637Snate{
231637Snate	register struct mse_softc *sc = &mse_sc[idp->id_unit];
232637Snate	register int i;
233637Snate
234637Snate	/*
235637Snate	 * Check for each mouse type in the table.
236637Snate	 */
237637Snate	i = 0;
238637Snate	while (mse_types[i].m_type) {
239637Snate		if ((*mse_types[i].m_probe)(idp)) {
240637Snate			sc->sc_mousetype = mse_types[i].m_type;
241637Snate			sc->sc_enablemouse = mse_types[i].m_enable;
242637Snate			sc->sc_disablemouse = mse_types[i].m_disable;
243637Snate			sc->sc_getmouse = mse_types[i].m_get;
24431603Syokota			sc->hw = mse_types[i].m_hw;
24531603Syokota			sc->mode = mse_types[i].m_mode;
246637Snate			return (1);
247637Snate		}
248637Snate		i++;
249637Snate	}
250637Snate	return (0);
251637Snate}
252637Snate
253798Swollmanint
254637Snatemseattach(idp)
255637Snate	struct isa_device *idp;
256637Snate{
25712675Sjulian	int unit = idp->id_unit;
25812675Sjulian	struct mse_softc *sc = &mse_sc[unit];
259637Snate
260637Snate	sc->sc_port = idp->id_iobase;
26131603Syokota	sc->mode.accelfactor = (idp->id_flags & MSE_CONFIG_ACCEL) >> 4;
26212675Sjulian#ifdef	DEVFS
26314873Sscrappy	sc->devfs_token =
26414873Sscrappy		devfs_add_devswf(&mse_cdevsw, unit << 1, DV_CHR, 0, 0,
26514873Sscrappy				 0600, "mse%d", unit);
26614873Sscrappy	sc->n_devfs_token =
26714873Sscrappy		devfs_add_devswf(&mse_cdevsw, (unit<<1)+1, DV_CHR,0, 0,
26814873Sscrappy				 0600, "nmse%d", unit);
26912675Sjulian#endif
270637Snate	return (1);
271637Snate}
272637Snate
273637Snate/*
274637Snate * Exclusive open the mouse, initialize it and enable interrupts.
275637Snate */
27612675Sjulianstatic	int
27710624Sbdemseopen(dev, flags, fmt, p)
278637Snate	dev_t dev;
27910624Sbde	int flags;
28010624Sbde	int fmt;
28110624Sbde	struct proc *p;
282637Snate{
283637Snate	register struct mse_softc *sc;
284637Snate	int s;
285637Snate
286637Snate	if (MSE_UNIT(dev) >= NMSE)
287637Snate		return (ENXIO);
288637Snate	sc = &mse_sc[MSE_UNIT(dev)];
28920688Sjoerg	if (sc->sc_mousetype == MSE_NONE)
29020688Sjoerg		return (ENXIO);
291637Snate	if (sc->sc_flags & MSESC_OPEN)
292637Snate		return (EBUSY);
293637Snate	sc->sc_flags |= MSESC_OPEN;
29431603Syokota	sc->sc_obuttons = sc->sc_buttons = MOUSE_MSC_BUTTONS;
295637Snate	sc->sc_deltax = sc->sc_deltay = 0;
29631603Syokota	sc->sc_bytesread = sc->mode.packetsize = MOUSE_MSC_PACKETSIZE;
29731603Syokota	sc->mode.level = 0;
29831603Syokota	sc->status.flags = 0;
29931603Syokota	sc->status.button = sc->status.obutton = 0;
30031603Syokota	sc->status.dx = sc->status.dy = sc->status.dz = 0;
301637Snate
302637Snate	/*
303637Snate	 * Initialize mouse interface and enable interrupts.
304637Snate	 */
305637Snate	s = spltty();
306637Snate	(*sc->sc_enablemouse)(sc->sc_port);
307637Snate	splx(s);
308637Snate	return (0);
309637Snate}
310637Snate
311637Snate/*
312637Snate * mseclose: just turn off mouse innterrupts.
313637Snate */
31412675Sjulianstatic	int
31510624Sbdemseclose(dev, flags, fmt, p)
316798Swollman	dev_t dev;
31710624Sbde	int flags;
31810624Sbde	int fmt;
31910624Sbde	struct proc *p;
320637Snate{
321637Snate	struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
322637Snate	int s;
323637Snate
324637Snate	s = spltty();
325637Snate	(*sc->sc_disablemouse)(sc->sc_port);
326637Snate	sc->sc_flags &= ~MSESC_OPEN;
327637Snate	splx(s);
328637Snate	return(0);
329637Snate}
330637Snate
3318876Srgrimes/*
332637Snate * mseread: return mouse info using the MSC serial protocol, but without
333637Snate * using bytes 4 and 5.
334637Snate * (Yes this is cheesy, but it makes the X386 server happy, so...)
335637Snate */
33612675Sjulianstatic	int
33710624Sbdemseread(dev, uio, ioflag)
338637Snate	dev_t dev;
339637Snate	struct uio *uio;
34010624Sbde	int ioflag;
341637Snate{
342637Snate	register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
343637Snate	int xfer, s, error;
344637Snate
345637Snate	/*
346637Snate	 * If there are no protocol bytes to be read, set up a new protocol
347637Snate	 * packet.
348637Snate	 */
349637Snate	s = spltty(); /* XXX Should be its own spl, but where is imlXX() */
35031603Syokota	if (sc->sc_bytesread >= sc->mode.packetsize) {
351637Snate		while (sc->sc_deltax == 0 && sc->sc_deltay == 0 &&
352637Snate		       (sc->sc_obuttons ^ sc->sc_buttons) == 0) {
353637Snate			if (MSE_NBLOCKIO(dev)) {
354637Snate				splx(s);
355637Snate				return (0);
356637Snate			}
357637Snate			sc->sc_flags |= MSESC_WANT;
358637Snate			if (error = tsleep((caddr_t)sc, MSEPRI | PCATCH,
359637Snate				"mseread", 0)) {
360637Snate				splx(s);
361637Snate				return (error);
362637Snate			}
363637Snate		}
364637Snate
365637Snate		/*
366637Snate		 * Generate protocol bytes.
367637Snate		 * For some reason X386 expects 5 bytes but never uses
368637Snate		 * the fourth or fifth?
369637Snate		 */
37031603Syokota		sc->sc_bytes[0] = sc->mode.syncmask[1]
37131603Syokota		    | (sc->sc_buttons & ~sc->mode.syncmask[0]);
372637Snate		if (sc->sc_deltax > 127)
373637Snate			sc->sc_deltax = 127;
374637Snate		if (sc->sc_deltax < -127)
375637Snate			sc->sc_deltax = -127;
376637Snate		sc->sc_deltay = -sc->sc_deltay;	/* Otherwise mousey goes wrong way */
377637Snate		if (sc->sc_deltay > 127)
378637Snate			sc->sc_deltay = 127;
379637Snate		if (sc->sc_deltay < -127)
380637Snate			sc->sc_deltay = -127;
381637Snate		sc->sc_bytes[1] = sc->sc_deltax;
382637Snate		sc->sc_bytes[2] = sc->sc_deltay;
383637Snate		sc->sc_bytes[3] = sc->sc_bytes[4] = 0;
38431603Syokota		sc->sc_bytes[5] = sc->sc_bytes[6] = 0;
38531603Syokota		sc->sc_bytes[7] = MOUSE_SYS_EXTBUTTONS;
386637Snate		sc->sc_obuttons = sc->sc_buttons;
387637Snate		sc->sc_deltax = sc->sc_deltay = 0;
388637Snate		sc->sc_bytesread = 0;
389637Snate	}
390637Snate	splx(s);
39131603Syokota	xfer = min(uio->uio_resid, sc->mode.packetsize - sc->sc_bytesread);
392637Snate	if (error = uiomove(&sc->sc_bytes[sc->sc_bytesread], xfer, uio))
393637Snate		return (error);
394637Snate	sc->sc_bytesread += xfer;
395637Snate	return(0);
396637Snate}
397637Snate
398637Snate/*
39931603Syokota * mseioctl: process ioctl commands.
40031603Syokota */
40131603Syokotastatic int
40231603Syokotamseioctl(dev, cmd, addr, flag, p)
40331603Syokota	dev_t dev;
40431603Syokota	int cmd;
40531603Syokota	caddr_t addr;
40631603Syokota	int flag;
40731603Syokota	struct proc *p;
40831603Syokota{
40931603Syokota	register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
41031603Syokota	mousestatus_t status;
41131603Syokota	int err = 0;
41231603Syokota	int s;
41331603Syokota
41431603Syokota	switch (cmd) {
41531603Syokota
41631603Syokota	case MOUSE_GETHWINFO:
41731603Syokota		s = spltty();
41831603Syokota		*(mousehw_t *)addr = sc->hw;
41931603Syokota		if (sc->mode.level == 0)
42031603Syokota			((mousehw_t *)addr)->model = MOUSE_MODEL_GENERIC;
42131603Syokota		splx(s);
42231603Syokota		break;
42331603Syokota
42431603Syokota	case MOUSE_GETMODE:
42531603Syokota		s = spltty();
42631603Syokota		*(mousemode_t *)addr = sc->mode;
42731603Syokota		switch (sc->mode.level) {
42831603Syokota		case 0:
42931603Syokota			break;
43031603Syokota		case 1:
43131603Syokota			((mousemode_t *)addr)->protocol = MOUSE_PROTO_SYSMOUSE;
43231603Syokota	    		((mousemode_t *)addr)->syncmask[0] = MOUSE_SYS_SYNCMASK;
43331603Syokota	    		((mousemode_t *)addr)->syncmask[1] = MOUSE_SYS_SYNC;
43431603Syokota			break;
43531603Syokota		}
43631603Syokota		splx(s);
43731603Syokota		break;
43831603Syokota
43931603Syokota	case MOUSE_SETMODE:
44031603Syokota		switch (((mousemode_t *)addr)->level) {
44131603Syokota		case 0:
44231603Syokota		case 1:
44331603Syokota			break;
44431603Syokota		default:
44531603Syokota			return (EINVAL);
44631603Syokota		}
44731603Syokota		if (((mousemode_t *)addr)->accelfactor < -1)
44831603Syokota			return (EINVAL);
44931603Syokota		else if (((mousemode_t *)addr)->accelfactor >= 0)
45031603Syokota			sc->mode.accelfactor =
45131603Syokota			    ((mousemode_t *)addr)->accelfactor;
45231603Syokota		sc->mode.level = ((mousemode_t *)addr)->level;
45331603Syokota		switch (sc->mode.level) {
45431603Syokota		case 0:
45531603Syokota			sc->sc_bytesread = sc->mode.packetsize
45631603Syokota			    = MOUSE_MSC_PACKETSIZE;
45731603Syokota			break;
45831603Syokota		case 1:
45931603Syokota			sc->sc_bytesread = sc->mode.packetsize
46031603Syokota			    = MOUSE_SYS_PACKETSIZE;
46131603Syokota			break;
46231603Syokota		}
46331603Syokota		break;
46431603Syokota
46531603Syokota	case MOUSE_GETLEVEL:
46631603Syokota		*(int *)addr = sc->mode.level;
46731603Syokota		break;
46831603Syokota
46931603Syokota	case MOUSE_SETLEVEL:
47031603Syokota		switch (*(int *)addr) {
47131603Syokota		case 0:
47231603Syokota			sc->mode.level = *(int *)addr;
47331603Syokota			sc->sc_bytesread = sc->mode.packetsize
47431603Syokota			    = MOUSE_MSC_PACKETSIZE;
47531603Syokota			break;
47631603Syokota		case 1:
47731603Syokota			sc->mode.level = *(int *)addr;
47831603Syokota			sc->sc_bytesread = sc->mode.packetsize
47931603Syokota			    = MOUSE_SYS_PACKETSIZE;
48031603Syokota			break;
48131603Syokota		default:
48231603Syokota			return (EINVAL);
48331603Syokota		}
48431603Syokota		break;
48531603Syokota
48631603Syokota	case MOUSE_GETSTATUS:
48731603Syokota		s = spltty();
48831603Syokota		status = sc->status;
48931603Syokota		sc->status.flags = 0;
49031603Syokota		sc->status.obutton = sc->status.button;
49131603Syokota		sc->status.button = 0;
49231603Syokota		sc->status.dx = 0;
49331603Syokota		sc->status.dy = 0;
49431603Syokota		sc->status.dz = 0;
49531603Syokota		splx(s);
49631603Syokota		*(mousestatus_t *)addr = status;
49731603Syokota		break;
49831603Syokota
49931603Syokota	case MOUSE_READSTATE:
50031603Syokota	case MOUSE_READDATA:
50131603Syokota		return (ENODEV);
50231603Syokota
50331603Syokota#if (defined(MOUSE_GETVARS))
50431603Syokota	case MOUSE_GETVARS:
50531603Syokota	case MOUSE_SETVARS:
50631603Syokota		return (ENODEV);
50731603Syokota#endif
50831603Syokota
50931603Syokota	default:
51031603Syokota		return (ENOTTY);
51131603Syokota	}
51231603Syokota	return (err);
51331603Syokota}
51431603Syokota
51531603Syokota/*
51629368Speter * msepoll: check for mouse input to be processed.
517637Snate */
51812675Sjulianstatic	int
51929368Spetermsepoll(dev, events, p)
520637Snate	dev_t dev;
52129368Speter	int events;
522637Snate	struct proc *p;
523637Snate{
524637Snate	register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
525637Snate	int s;
52629368Speter	int revents = 0;
527637Snate
528637Snate	s = spltty();
52929368Speter	if (events & (POLLIN | POLLRDNORM))
53031603Syokota		if (sc->sc_bytesread != sc->mode.packetsize ||
53131603Syokota		    sc->sc_deltax != 0 || sc->sc_deltay != 0 ||
53229368Speter		    (sc->sc_obuttons ^ sc->sc_buttons) != 0)
53329368Speter			revents |= events & (POLLIN | POLLRDNORM);
53429368Speter		else {
53529368Speter			/*
53629368Speter			 * Since this is an exclusive open device, any previous
53729368Speter			 * proc pointer is trash now, so we can just assign it.
53829368Speter			 */
53929368Speter			selrecord(p, &sc->sc_selp);
54029368Speter		}
541637Snate
542637Snate	splx(s);
54329368Speter	return (revents);
544637Snate}
545637Snate
546637Snate/*
547637Snate * mseintr: update mouse status. sc_deltax and sc_deltay are accumulative.
548637Snate */
549798Swollmanvoid
550637Snatemseintr(unit)
551637Snate	int unit;
552637Snate{
55331603Syokota	/*
55431603Syokota	 * the table to turn MouseSystem button bits (MOUSE_MSC_BUTTON?UP)
55531603Syokota	 * into `mousestatus' button bits (MOUSE_BUTTON?DOWN).
55631603Syokota	 */
55731603Syokota	static int butmap[8] = {
55831603Syokota		0,
55931603Syokota		MOUSE_BUTTON3DOWN,
56031603Syokota		MOUSE_BUTTON2DOWN,
56131603Syokota		MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN,
56231603Syokota		MOUSE_BUTTON1DOWN,
56331603Syokota		MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN,
56431603Syokota		MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN,
56531603Syokota        	MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN
56631603Syokota	};
567637Snate	register struct mse_softc *sc = &mse_sc[unit];
56831603Syokota	int dx, dy, but;
56931603Syokota	int sign;
570637Snate
571637Snate#ifdef DEBUG
572637Snate	static int mse_intrcnt = 0;
573637Snate	if((mse_intrcnt++ % 10000) == 0)
574637Snate		printf("mseintr\n");
575637Snate#endif /* DEBUG */
576637Snate	if ((sc->sc_flags & MSESC_OPEN) == 0)
577637Snate		return;
578637Snate
57931603Syokota	(*sc->sc_getmouse)(sc->sc_port, &dx, &dy, &but);
58031603Syokota	if (sc->mode.accelfactor > 0) {
58131603Syokota		sign = (dx < 0);
58231603Syokota		dx = dx * dx / sc->mode.accelfactor;
58331603Syokota		if (dx == 0)
58431603Syokota			dx = 1;
58531603Syokota		if (sign)
58631603Syokota			dx = -dx;
58731603Syokota		sign = (dy < 0);
58831603Syokota		dy = dy * dy / sc->mode.accelfactor;
58931603Syokota		if (dy == 0)
59031603Syokota			dy = 1;
59131603Syokota		if (sign)
59231603Syokota			dy = -dy;
59331603Syokota	}
59431603Syokota	sc->sc_deltax += dx;
59531603Syokota	sc->sc_deltay += dy;
59631603Syokota	sc->sc_buttons = but;
597637Snate
59831603Syokota	but = butmap[~but & MOUSE_MSC_BUTTONS];
59931603Syokota	sc->status.dx += dx;
60031603Syokota	sc->status.dy += dy;
60131603Syokota	sc->status.flags |= ((dx || dy) ? MOUSE_POSCHANGED : 0)
60231603Syokota	    | (sc->status.button ^ but);
60331603Syokota	sc->status.button = but;
60431603Syokota
605637Snate	/*
606637Snate	 * If mouse state has changed, wake up anyone wanting to know.
607637Snate	 */
608637Snate	if (sc->sc_deltax != 0 || sc->sc_deltay != 0 ||
609637Snate	    (sc->sc_obuttons ^ sc->sc_buttons) != 0) {
6108876Srgrimes		if (sc->sc_flags & MSESC_WANT) {
6118876Srgrimes			sc->sc_flags &= ~MSESC_WANT;
6128876Srgrimes			wakeup((caddr_t)sc);
6138876Srgrimes		}
6141549Srgrimes		selwakeup(&sc->sc_selp);
615637Snate	}
616637Snate}
617637Snate
618637Snate/*
619637Snate * Routines for the Logitech mouse.
620637Snate */
621637Snate/*
622637Snate * Test for a Logitech bus mouse and return 1 if it is.
623637Snate * (until I know how to use the signature port properly, just disable
624637Snate *  interrupts and return 1)
625637Snate */
626637Snatestatic int
627637Snatemse_probelogi(idp)
628637Snate	register struct isa_device *idp;
629637Snate{
630637Snate
6314259Sjkh	int sig;
6324259Sjkh
6334259Sjkh	outb(idp->id_iobase + MSE_PORTD, MSE_SETUP);
6344259Sjkh		/* set the signature port */
6354259Sjkh	outb(idp->id_iobase + MSE_PORTB, MSE_LOGI_SIG);
6364259Sjkh
6374259Sjkh	DELAY(30000); /* 30 ms delay */
6384259Sjkh	sig = inb(idp->id_iobase + MSE_PORTB) & 0xFF;
6394259Sjkh	if (sig == MSE_LOGI_SIG) {
6404259Sjkh		outb(idp->id_iobase + MSE_PORTC, MSE_DISINTR);
6414259Sjkh		return(1);
6424259Sjkh	} else {
64316074Sjoerg		if (bootverbose)
64416074Sjoerg			printf("mse%d: wrong signature %x\n",idp->id_unit,sig);
6454259Sjkh		return(0);
646637Snate	}
647637Snate}
648637Snate
649637Snate/*
650637Snate * Initialize Logitech mouse and enable interrupts.
651637Snate */
652637Snatestatic void
653637Snatemse_enablelogi(port)
654637Snate	register u_int port;
655637Snate{
656637Snate	int dx, dy, but;
657637Snate
658637Snate	outb(port + MSE_PORTD, MSE_SETUP);
659637Snate	mse_getlogi(port, &dx, &dy, &but);
660637Snate}
661637Snate
662637Snate/*
663637Snate * Disable interrupts for Logitech mouse.
664637Snate */
665637Snatestatic void
666637Snatemse_disablelogi(port)
667637Snate	register u_int port;
668637Snate{
669637Snate
670637Snate	outb(port + MSE_PORTC, MSE_DISINTR);
671637Snate}
672637Snate
673637Snate/*
674637Snate * Get the current dx, dy and button up/down state.
675637Snate */
676637Snatestatic void
677637Snatemse_getlogi(port, dx, dy, but)
678637Snate	register u_int port;
679637Snate	int *dx;
680637Snate	int *dy;
681637Snate	int *but;
682637Snate{
683637Snate	register char x, y;
684637Snate
685637Snate	outb(port + MSE_PORTC, MSE_HOLD | MSE_RXLOW);
686637Snate	x = inb(port + MSE_PORTA);
68731603Syokota	*but = (x >> 5) & MOUSE_MSC_BUTTONS;
688637Snate	x &= 0xf;
689637Snate	outb(port + MSE_PORTC, MSE_HOLD | MSE_RXHIGH);
690637Snate	x |= (inb(port + MSE_PORTA) << 4);
691637Snate	outb(port + MSE_PORTC, MSE_HOLD | MSE_RYLOW);
692637Snate	y = (inb(port + MSE_PORTA) & 0xf);
693637Snate	outb(port + MSE_PORTC, MSE_HOLD | MSE_RYHIGH);
694637Snate	y |= (inb(port + MSE_PORTA) << 4);
69531603Syokota	*dx = x;
69631603Syokota	*dy = y;
697637Snate	outb(port + MSE_PORTC, MSE_INTREN);
698637Snate}
699637Snate
700637Snate/*
701637Snate * Routines for the ATI Inport bus mouse.
702637Snate */
703637Snate/*
704637Snate * Test for a ATI Inport bus mouse and return 1 if it is.
705637Snate * (do not enable interrupts)
706637Snate */
707637Snatestatic int
708637Snatemse_probeati(idp)
709637Snate	register struct isa_device *idp;
710637Snate{
711637Snate	int i;
712637Snate
713637Snate	for (i = 0; i < 2; i++)
714637Snate		if (inb(idp->id_iobase + MSE_PORTC) == 0xde)
715637Snate			return (1);
716637Snate	return (0);
717637Snate}
718637Snate
719637Snate/*
720637Snate * Initialize ATI Inport mouse and enable interrupts.
721637Snate */
722637Snatestatic void
723637Snatemse_enableati(port)
724637Snate	register u_int port;
725637Snate{
726637Snate
727637Snate	outb(port + MSE_PORTA, MSE_INPORT_RESET);
728637Snate	outb(port + MSE_PORTA, MSE_INPORT_MODE);
729637Snate	outb(port + MSE_PORTB, MSE_INPORT_INTREN);
730637Snate}
731637Snate
732637Snate/*
733637Snate * Disable interrupts for ATI Inport mouse.
734637Snate */
735637Snatestatic void
736637Snatemse_disableati(port)
737637Snate	register u_int port;
738637Snate{
739637Snate
740637Snate	outb(port + MSE_PORTA, MSE_INPORT_MODE);
741637Snate	outb(port + MSE_PORTB, 0);
742637Snate}
743637Snate
744637Snate/*
745637Snate * Get current dx, dy and up/down button state.
746637Snate */
747637Snatestatic void
748637Snatemse_getati(port, dx, dy, but)
749637Snate	register u_int port;
750637Snate	int *dx;
751637Snate	int *dy;
752637Snate	int *but;
753637Snate{
754637Snate	register char byte;
755637Snate
756637Snate	outb(port + MSE_PORTA, MSE_INPORT_MODE);
757637Snate	outb(port + MSE_PORTB, MSE_INPORT_HOLD);
758637Snate	outb(port + MSE_PORTA, MSE_INPORT_STATUS);
75931603Syokota	*but = ~inb(port + MSE_PORTB) & MOUSE_MSC_BUTTONS;
760637Snate	outb(port + MSE_PORTA, MSE_INPORT_DX);
761637Snate	byte = inb(port + MSE_PORTB);
76231603Syokota	*dx = byte;
763637Snate	outb(port + MSE_PORTA, MSE_INPORT_DY);
764637Snate	byte = inb(port + MSE_PORTB);
76531603Syokota	*dy = byte;
766637Snate	outb(port + MSE_PORTA, MSE_INPORT_MODE);
767637Snate	outb(port + MSE_PORTB, MSE_INPORT_INTREN);
768637Snate}
76912502Sjulian
77012502Sjulianstatic mse_devsw_installed = 0;
77112502Sjulian
77212517Sjulianstatic void 	mse_drvinit(void *unused)
77312502Sjulian{
77412517Sjulian	dev_t dev;
77512517Sjulian
77612502Sjulian	if( ! mse_devsw_installed ) {
77712675Sjulian		dev = makedev(CDEV_MAJOR, 0);
77812675Sjulian		cdevsw_add(&dev,&mse_cdevsw, NULL);
77912502Sjulian		mse_devsw_installed = 1;
78012517Sjulian    	}
78112502Sjulian}
78212517Sjulian
78312517SjulianSYSINIT(msedev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,mse_drvinit,NULL)
78412517Sjulian
78512517Sjulian
786637Snate#endif /* NMSE */
787