mse.c revision 46571
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 *
1446571Speter * $Id: mse.c,v 1.41 1999/05/06 18:12:28 peter 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
9040565Sbdestatic ointhand2_t mseintr;
9112675Sjulian
92637Snate/*
93637Snate * Software control structure for mouse. The sc_enablemouse(),
94637Snate * sc_disablemouse() and sc_getmouse() routines must be called spl'd().
95637Snate */
9612724Sphkstatic struct mse_softc {
97637Snate	int	sc_flags;
98637Snate	int	sc_mousetype;
991549Srgrimes	struct	selinfo sc_selp;
100637Snate	u_int	sc_port;
10112854Sbde	void	(*sc_enablemouse) __P((u_int port));
10212854Sbde	void	(*sc_disablemouse) __P((u_int port));
10312854Sbde	void	(*sc_getmouse) __P((u_int port, int *dx, int *dy, int *but));
104637Snate	int	sc_deltax;
105637Snate	int	sc_deltay;
106637Snate	int	sc_obuttons;
107637Snate	int	sc_buttons;
108637Snate	int	sc_bytesread;
10931603Syokota	u_char	sc_bytes[MOUSE_SYS_PACKETSIZE];
11031603Syokota	mousehw_t	hw;
11131603Syokota	mousemode_t	mode;
11231603Syokota	mousestatus_t	status;
11312675Sjulian#ifdef DEVFS
11412675Sjulian	void 	*devfs_token;
11512675Sjulian	void	*n_devfs_token;
11612675Sjulian#endif
117637Snate} mse_sc[NMSE];
118637Snate
119637Snate/* Flags */
120637Snate#define	MSESC_OPEN	0x1
121637Snate#define	MSESC_WANT	0x2
122637Snate
123637Snate/* and Mouse Types */
12420688Sjoerg#define	MSE_NONE	0	/* don't move this! */
125637Snate#define	MSE_LOGITECH	0x1
126637Snate#define	MSE_ATIINPORT	0x2
1274259Sjkh#define	MSE_LOGI_SIG	0xA5
128637Snate
129637Snate#define	MSE_PORTA	0
130637Snate#define	MSE_PORTB	1
131637Snate#define	MSE_PORTC	2
132637Snate#define	MSE_PORTD	3
133637Snate
134637Snate#define	MSE_UNIT(dev)		(minor(dev) >> 1)
135637Snate#define	MSE_NBLOCKIO(dev)	(minor(dev) & 0x1)
136637Snate
137637Snate/*
138637Snate * Logitech bus mouse definitions
139637Snate */
140637Snate#define	MSE_SETUP	0x91	/* What does this mean? */
1414259Sjkh				/* The definition for the control port */
1424259Sjkh				/* is as follows: */
1438876Srgrimes
1444259Sjkh				/* D7 	 =  Mode set flag (1 = active) 	*/
1458876Srgrimes				/* D6,D5 =  Mode selection (port A) 	*/
1464259Sjkh				/* 	    00 = Mode 0 = Basic I/O 	*/
1474259Sjkh				/* 	    01 = Mode 1 = Strobed I/O 	*/
1484259Sjkh				/* 	    10 = Mode 2 = Bi-dir bus 	*/
1494259Sjkh				/* D4	 =  Port A direction (1 = input)*/
1504259Sjkh				/* D3	 =  Port C (upper 4 bits) 	*/
1514259Sjkh				/*	    direction. (1 = input)	*/
1524259Sjkh				/* D2	 =  Mode selection (port B & C) */
1534259Sjkh				/*	    0 = Mode 0 = Basic I/O	*/
1544259Sjkh				/*	    1 = Mode 1 = Strobed I/O	*/
1554259Sjkh				/* D1	 =  Port B direction (1 = input)*/
1564259Sjkh				/* D0	 =  Port C (lower 4 bits)	*/
1574259Sjkh				/*	    direction. (1 = input)	*/
1588876Srgrimes
1594259Sjkh				/* So 91 means Basic I/O on all 3 ports,*/
1604259Sjkh				/* Port A is an input port, B is an 	*/
1614259Sjkh				/* output port, C is split with upper	*/
1624259Sjkh				/* 4 bits being an output port and lower*/
1634259Sjkh				/* 4 bits an input port, and enable the */
1644259Sjkh				/* sucker.				*/
1654259Sjkh				/* Courtesy Intel 8255 databook. Lars   */
166637Snate#define	MSE_HOLD	0x80
167637Snate#define	MSE_RXLOW	0x00
168637Snate#define	MSE_RXHIGH	0x20
169637Snate#define	MSE_RYLOW	0x40
170637Snate#define	MSE_RYHIGH	0x60
171637Snate#define	MSE_DISINTR	0x10
172637Snate#define MSE_INTREN	0x00
173637Snate
17412854Sbdestatic int mse_probelogi __P((struct isa_device *idp));
17512854Sbdestatic void mse_disablelogi __P((u_int port));
17612854Sbdestatic void mse_getlogi __P((u_int port, int *dx, int *dy, int *but));
17712854Sbdestatic void mse_enablelogi __P((u_int port));
178637Snate
179637Snate/*
180637Snate * ATI Inport mouse definitions
181637Snate */
182637Snate#define	MSE_INPORT_RESET	0x80
183637Snate#define	MSE_INPORT_STATUS	0x00
184637Snate#define	MSE_INPORT_DX		0x01
185637Snate#define	MSE_INPORT_DY		0x02
186637Snate#define	MSE_INPORT_MODE		0x07
187637Snate#define	MSE_INPORT_HOLD		0x20
188637Snate#define	MSE_INPORT_INTREN	0x09
189637Snate
19012854Sbdestatic int mse_probeati __P((struct isa_device *idp));
19112854Sbdestatic void mse_enableati __P((u_int port));
19212854Sbdestatic void mse_disableati __P((u_int port));
19312854Sbdestatic void mse_getati __P((u_int port, int *dx, int *dy, int *but));
194637Snate
195637Snate#define	MSEPRI	(PZERO + 3)
196637Snate
197637Snate/*
198637Snate * Table of mouse types.
199637Snate * Keep the Logitech last, since I haven't figured out how to probe it
200637Snate * properly yet. (Someday I'll have the documentation.)
201637Snate */
20212724Sphkstatic struct mse_types {
203637Snate	int	m_type;		/* Type of bus mouse */
20412854Sbde	int	(*m_probe) __P((struct isa_device *idp));
20512854Sbde				/* Probe routine to test for it */
20612854Sbde	void	(*m_enable) __P((u_int port));
20712854Sbde				/* Start routine */
20812854Sbde	void	(*m_disable) __P((u_int port));
20912854Sbde				/* Disable interrupts routine */
21012854Sbde	void	(*m_get) __P((u_int port, int *dx, int *dy, int *but));
21112854Sbde				/* and get mouse status */
21231603Syokota	mousehw_t   m_hw;	/* buttons iftype type model hwid */
21331603Syokota	mousemode_t m_mode;	/* proto rate res accel level size mask */
214637Snate} mse_types[] = {
21531603Syokota	{ MSE_ATIINPORT,
21631603Syokota	  mse_probeati, mse_enableati, mse_disableati, mse_getati,
21731603Syokota	  { 2, MOUSE_IF_INPORT, MOUSE_MOUSE, MOUSE_MODEL_GENERIC, 0, },
21831603Syokota	  { MOUSE_PROTO_INPORT, -1, -1, 0, 0, MOUSE_MSC_PACKETSIZE,
21931603Syokota	    { MOUSE_MSC_SYNCMASK, MOUSE_MSC_SYNC, }, }, },
22031603Syokota	{ MSE_LOGITECH,
22131603Syokota	  mse_probelogi, mse_enablelogi, mse_disablelogi, mse_getlogi,
22231603Syokota	  { 2, MOUSE_IF_BUS, MOUSE_MOUSE, MOUSE_MODEL_GENERIC, 0, },
22331603Syokota	  { MOUSE_PROTO_BUS, -1, -1, 0, 0, MOUSE_MSC_PACKETSIZE,
22431603Syokota	    { MOUSE_MSC_SYNCMASK, MOUSE_MSC_SYNC, }, }, },
225637Snate	{ 0, },
226637Snate};
227637Snate
228798Swollmanint
229637Snatemseprobe(idp)
230637Snate	register struct isa_device *idp;
231637Snate{
232637Snate	register struct mse_softc *sc = &mse_sc[idp->id_unit];
233637Snate	register int i;
234637Snate
235637Snate	/*
236637Snate	 * Check for each mouse type in the table.
237637Snate	 */
238637Snate	i = 0;
239637Snate	while (mse_types[i].m_type) {
240637Snate		if ((*mse_types[i].m_probe)(idp)) {
241637Snate			sc->sc_mousetype = mse_types[i].m_type;
242637Snate			sc->sc_enablemouse = mse_types[i].m_enable;
243637Snate			sc->sc_disablemouse = mse_types[i].m_disable;
244637Snate			sc->sc_getmouse = mse_types[i].m_get;
24531603Syokota			sc->hw = mse_types[i].m_hw;
24631603Syokota			sc->mode = mse_types[i].m_mode;
247637Snate			return (1);
248637Snate		}
249637Snate		i++;
250637Snate	}
251637Snate	return (0);
252637Snate}
253637Snate
254798Swollmanint
255637Snatemseattach(idp)
256637Snate	struct isa_device *idp;
257637Snate{
25812675Sjulian	int unit = idp->id_unit;
25912675Sjulian	struct mse_softc *sc = &mse_sc[unit];
260637Snate
26140565Sbde	idp->id_ointr = mseintr;
262637Snate	sc->sc_port = idp->id_iobase;
26331603Syokota	sc->mode.accelfactor = (idp->id_flags & MSE_CONFIG_ACCEL) >> 4;
26412675Sjulian#ifdef	DEVFS
26514873Sscrappy	sc->devfs_token =
26614873Sscrappy		devfs_add_devswf(&mse_cdevsw, unit << 1, DV_CHR, 0, 0,
26714873Sscrappy				 0600, "mse%d", unit);
26814873Sscrappy	sc->n_devfs_token =
26914873Sscrappy		devfs_add_devswf(&mse_cdevsw, (unit<<1)+1, DV_CHR,0, 0,
27014873Sscrappy				 0600, "nmse%d", unit);
27112675Sjulian#endif
272637Snate	return (1);
273637Snate}
274637Snate
275637Snate/*
276637Snate * Exclusive open the mouse, initialize it and enable interrupts.
277637Snate */
27812675Sjulianstatic	int
27910624Sbdemseopen(dev, flags, fmt, p)
280637Snate	dev_t dev;
28110624Sbde	int flags;
28210624Sbde	int fmt;
28310624Sbde	struct proc *p;
284637Snate{
285637Snate	register struct mse_softc *sc;
286637Snate	int s;
287637Snate
288637Snate	if (MSE_UNIT(dev) >= NMSE)
289637Snate		return (ENXIO);
290637Snate	sc = &mse_sc[MSE_UNIT(dev)];
29120688Sjoerg	if (sc->sc_mousetype == MSE_NONE)
29220688Sjoerg		return (ENXIO);
293637Snate	if (sc->sc_flags & MSESC_OPEN)
294637Snate		return (EBUSY);
295637Snate	sc->sc_flags |= MSESC_OPEN;
29631603Syokota	sc->sc_obuttons = sc->sc_buttons = MOUSE_MSC_BUTTONS;
297637Snate	sc->sc_deltax = sc->sc_deltay = 0;
29831603Syokota	sc->sc_bytesread = sc->mode.packetsize = MOUSE_MSC_PACKETSIZE;
29931603Syokota	sc->mode.level = 0;
30031603Syokota	sc->status.flags = 0;
30131603Syokota	sc->status.button = sc->status.obutton = 0;
30231603Syokota	sc->status.dx = sc->status.dy = sc->status.dz = 0;
303637Snate
304637Snate	/*
305637Snate	 * Initialize mouse interface and enable interrupts.
306637Snate	 */
307637Snate	s = spltty();
308637Snate	(*sc->sc_enablemouse)(sc->sc_port);
309637Snate	splx(s);
310637Snate	return (0);
311637Snate}
312637Snate
313637Snate/*
314637Snate * mseclose: just turn off mouse innterrupts.
315637Snate */
31612675Sjulianstatic	int
31710624Sbdemseclose(dev, flags, fmt, p)
318798Swollman	dev_t dev;
31910624Sbde	int flags;
32010624Sbde	int fmt;
32110624Sbde	struct proc *p;
322637Snate{
323637Snate	struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
324637Snate	int s;
325637Snate
326637Snate	s = spltty();
327637Snate	(*sc->sc_disablemouse)(sc->sc_port);
328637Snate	sc->sc_flags &= ~MSESC_OPEN;
329637Snate	splx(s);
330637Snate	return(0);
331637Snate}
332637Snate
3338876Srgrimes/*
334637Snate * mseread: return mouse info using the MSC serial protocol, but without
335637Snate * using bytes 4 and 5.
336637Snate * (Yes this is cheesy, but it makes the X386 server happy, so...)
337637Snate */
33812675Sjulianstatic	int
33910624Sbdemseread(dev, uio, ioflag)
340637Snate	dev_t dev;
341637Snate	struct uio *uio;
34210624Sbde	int ioflag;
343637Snate{
344637Snate	register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
345637Snate	int xfer, s, error;
346637Snate
347637Snate	/*
348637Snate	 * If there are no protocol bytes to be read, set up a new protocol
349637Snate	 * packet.
350637Snate	 */
351637Snate	s = spltty(); /* XXX Should be its own spl, but where is imlXX() */
35231603Syokota	if (sc->sc_bytesread >= sc->mode.packetsize) {
353637Snate		while (sc->sc_deltax == 0 && sc->sc_deltay == 0 &&
354637Snate		       (sc->sc_obuttons ^ sc->sc_buttons) == 0) {
355637Snate			if (MSE_NBLOCKIO(dev)) {
356637Snate				splx(s);
357637Snate				return (0);
358637Snate			}
359637Snate			sc->sc_flags |= MSESC_WANT;
36046571Speter			error = tsleep((caddr_t)sc, MSEPRI | PCATCH,
36146571Speter				"mseread", 0);
36246571Speter			if (error) {
363637Snate				splx(s);
364637Snate				return (error);
365637Snate			}
366637Snate		}
367637Snate
368637Snate		/*
369637Snate		 * Generate protocol bytes.
370637Snate		 * For some reason X386 expects 5 bytes but never uses
371637Snate		 * the fourth or fifth?
372637Snate		 */
37331603Syokota		sc->sc_bytes[0] = sc->mode.syncmask[1]
37431603Syokota		    | (sc->sc_buttons & ~sc->mode.syncmask[0]);
375637Snate		if (sc->sc_deltax > 127)
376637Snate			sc->sc_deltax = 127;
377637Snate		if (sc->sc_deltax < -127)
378637Snate			sc->sc_deltax = -127;
379637Snate		sc->sc_deltay = -sc->sc_deltay;	/* Otherwise mousey goes wrong way */
380637Snate		if (sc->sc_deltay > 127)
381637Snate			sc->sc_deltay = 127;
382637Snate		if (sc->sc_deltay < -127)
383637Snate			sc->sc_deltay = -127;
384637Snate		sc->sc_bytes[1] = sc->sc_deltax;
385637Snate		sc->sc_bytes[2] = sc->sc_deltay;
386637Snate		sc->sc_bytes[3] = sc->sc_bytes[4] = 0;
38731603Syokota		sc->sc_bytes[5] = sc->sc_bytes[6] = 0;
38831603Syokota		sc->sc_bytes[7] = MOUSE_SYS_EXTBUTTONS;
389637Snate		sc->sc_obuttons = sc->sc_buttons;
390637Snate		sc->sc_deltax = sc->sc_deltay = 0;
391637Snate		sc->sc_bytesread = 0;
392637Snate	}
393637Snate	splx(s);
39431603Syokota	xfer = min(uio->uio_resid, sc->mode.packetsize - sc->sc_bytesread);
39546571Speter	error = uiomove(&sc->sc_bytes[sc->sc_bytesread], xfer, uio);
39646571Speter	if (error)
397637Snate		return (error);
398637Snate	sc->sc_bytesread += xfer;
399637Snate	return(0);
400637Snate}
401637Snate
402637Snate/*
40331603Syokota * mseioctl: process ioctl commands.
40431603Syokota */
40531603Syokotastatic int
40631603Syokotamseioctl(dev, cmd, addr, flag, p)
40731603Syokota	dev_t dev;
40836735Sdfr	u_long cmd;
40931603Syokota	caddr_t addr;
41031603Syokota	int flag;
41131603Syokota	struct proc *p;
41231603Syokota{
41331603Syokota	register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
41431603Syokota	mousestatus_t status;
41531603Syokota	int err = 0;
41631603Syokota	int s;
41731603Syokota
41831603Syokota	switch (cmd) {
41931603Syokota
42031603Syokota	case MOUSE_GETHWINFO:
42131603Syokota		s = spltty();
42231603Syokota		*(mousehw_t *)addr = sc->hw;
42331603Syokota		if (sc->mode.level == 0)
42431603Syokota			((mousehw_t *)addr)->model = MOUSE_MODEL_GENERIC;
42531603Syokota		splx(s);
42631603Syokota		break;
42731603Syokota
42831603Syokota	case MOUSE_GETMODE:
42931603Syokota		s = spltty();
43031603Syokota		*(mousemode_t *)addr = sc->mode;
43131603Syokota		switch (sc->mode.level) {
43231603Syokota		case 0:
43331603Syokota			break;
43431603Syokota		case 1:
43531603Syokota			((mousemode_t *)addr)->protocol = MOUSE_PROTO_SYSMOUSE;
43631603Syokota	    		((mousemode_t *)addr)->syncmask[0] = MOUSE_SYS_SYNCMASK;
43731603Syokota	    		((mousemode_t *)addr)->syncmask[1] = MOUSE_SYS_SYNC;
43831603Syokota			break;
43931603Syokota		}
44031603Syokota		splx(s);
44131603Syokota		break;
44231603Syokota
44331603Syokota	case MOUSE_SETMODE:
44431603Syokota		switch (((mousemode_t *)addr)->level) {
44531603Syokota		case 0:
44631603Syokota		case 1:
44731603Syokota			break;
44831603Syokota		default:
44931603Syokota			return (EINVAL);
45031603Syokota		}
45131603Syokota		if (((mousemode_t *)addr)->accelfactor < -1)
45231603Syokota			return (EINVAL);
45331603Syokota		else if (((mousemode_t *)addr)->accelfactor >= 0)
45431603Syokota			sc->mode.accelfactor =
45531603Syokota			    ((mousemode_t *)addr)->accelfactor;
45631603Syokota		sc->mode.level = ((mousemode_t *)addr)->level;
45731603Syokota		switch (sc->mode.level) {
45831603Syokota		case 0:
45931603Syokota			sc->sc_bytesread = sc->mode.packetsize
46031603Syokota			    = MOUSE_MSC_PACKETSIZE;
46131603Syokota			break;
46231603Syokota		case 1:
46331603Syokota			sc->sc_bytesread = sc->mode.packetsize
46431603Syokota			    = MOUSE_SYS_PACKETSIZE;
46531603Syokota			break;
46631603Syokota		}
46731603Syokota		break;
46831603Syokota
46931603Syokota	case MOUSE_GETLEVEL:
47031603Syokota		*(int *)addr = sc->mode.level;
47131603Syokota		break;
47231603Syokota
47331603Syokota	case MOUSE_SETLEVEL:
47431603Syokota		switch (*(int *)addr) {
47531603Syokota		case 0:
47631603Syokota			sc->mode.level = *(int *)addr;
47731603Syokota			sc->sc_bytesread = sc->mode.packetsize
47831603Syokota			    = MOUSE_MSC_PACKETSIZE;
47931603Syokota			break;
48031603Syokota		case 1:
48131603Syokota			sc->mode.level = *(int *)addr;
48231603Syokota			sc->sc_bytesread = sc->mode.packetsize
48331603Syokota			    = MOUSE_SYS_PACKETSIZE;
48431603Syokota			break;
48531603Syokota		default:
48631603Syokota			return (EINVAL);
48731603Syokota		}
48831603Syokota		break;
48931603Syokota
49031603Syokota	case MOUSE_GETSTATUS:
49131603Syokota		s = spltty();
49231603Syokota		status = sc->status;
49331603Syokota		sc->status.flags = 0;
49431603Syokota		sc->status.obutton = sc->status.button;
49531603Syokota		sc->status.button = 0;
49631603Syokota		sc->status.dx = 0;
49731603Syokota		sc->status.dy = 0;
49831603Syokota		sc->status.dz = 0;
49931603Syokota		splx(s);
50031603Syokota		*(mousestatus_t *)addr = status;
50131603Syokota		break;
50231603Syokota
50331603Syokota	case MOUSE_READSTATE:
50431603Syokota	case MOUSE_READDATA:
50531603Syokota		return (ENODEV);
50631603Syokota
50731603Syokota#if (defined(MOUSE_GETVARS))
50831603Syokota	case MOUSE_GETVARS:
50931603Syokota	case MOUSE_SETVARS:
51031603Syokota		return (ENODEV);
51131603Syokota#endif
51231603Syokota
51331603Syokota	default:
51431603Syokota		return (ENOTTY);
51531603Syokota	}
51631603Syokota	return (err);
51731603Syokota}
51831603Syokota
51931603Syokota/*
52029368Speter * msepoll: check for mouse input to be processed.
521637Snate */
52212675Sjulianstatic	int
52329368Spetermsepoll(dev, events, p)
524637Snate	dev_t dev;
52529368Speter	int events;
526637Snate	struct proc *p;
527637Snate{
528637Snate	register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
529637Snate	int s;
53029368Speter	int revents = 0;
531637Snate
532637Snate	s = spltty();
53346568Speter	if (events & (POLLIN | POLLRDNORM)) {
53431603Syokota		if (sc->sc_bytesread != sc->mode.packetsize ||
53531603Syokota		    sc->sc_deltax != 0 || sc->sc_deltay != 0 ||
53629368Speter		    (sc->sc_obuttons ^ sc->sc_buttons) != 0)
53729368Speter			revents |= events & (POLLIN | POLLRDNORM);
53829368Speter		else {
53929368Speter			/*
54029368Speter			 * Since this is an exclusive open device, any previous
54129368Speter			 * proc pointer is trash now, so we can just assign it.
54229368Speter			 */
54329368Speter			selrecord(p, &sc->sc_selp);
54429368Speter		}
54546568Speter	}
546637Snate	splx(s);
54729368Speter	return (revents);
548637Snate}
549637Snate
550637Snate/*
551637Snate * mseintr: update mouse status. sc_deltax and sc_deltay are accumulative.
552637Snate */
55340565Sbdestatic void
554637Snatemseintr(unit)
555637Snate	int unit;
556637Snate{
55731603Syokota	/*
55831603Syokota	 * the table to turn MouseSystem button bits (MOUSE_MSC_BUTTON?UP)
55931603Syokota	 * into `mousestatus' button bits (MOUSE_BUTTON?DOWN).
56031603Syokota	 */
56131603Syokota	static int butmap[8] = {
56231603Syokota		0,
56331603Syokota		MOUSE_BUTTON3DOWN,
56431603Syokota		MOUSE_BUTTON2DOWN,
56531603Syokota		MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN,
56631603Syokota		MOUSE_BUTTON1DOWN,
56731603Syokota		MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN,
56831603Syokota		MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN,
56931603Syokota        	MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN
57031603Syokota	};
571637Snate	register struct mse_softc *sc = &mse_sc[unit];
57231603Syokota	int dx, dy, but;
57331603Syokota	int sign;
574637Snate
575637Snate#ifdef DEBUG
576637Snate	static int mse_intrcnt = 0;
577637Snate	if((mse_intrcnt++ % 10000) == 0)
578637Snate		printf("mseintr\n");
579637Snate#endif /* DEBUG */
580637Snate	if ((sc->sc_flags & MSESC_OPEN) == 0)
581637Snate		return;
582637Snate
58331603Syokota	(*sc->sc_getmouse)(sc->sc_port, &dx, &dy, &but);
58431603Syokota	if (sc->mode.accelfactor > 0) {
58531603Syokota		sign = (dx < 0);
58631603Syokota		dx = dx * dx / sc->mode.accelfactor;
58731603Syokota		if (dx == 0)
58831603Syokota			dx = 1;
58931603Syokota		if (sign)
59031603Syokota			dx = -dx;
59131603Syokota		sign = (dy < 0);
59231603Syokota		dy = dy * dy / sc->mode.accelfactor;
59331603Syokota		if (dy == 0)
59431603Syokota			dy = 1;
59531603Syokota		if (sign)
59631603Syokota			dy = -dy;
59731603Syokota	}
59831603Syokota	sc->sc_deltax += dx;
59931603Syokota	sc->sc_deltay += dy;
60031603Syokota	sc->sc_buttons = but;
601637Snate
60231603Syokota	but = butmap[~but & MOUSE_MSC_BUTTONS];
60331603Syokota	sc->status.dx += dx;
60431603Syokota	sc->status.dy += dy;
60531603Syokota	sc->status.flags |= ((dx || dy) ? MOUSE_POSCHANGED : 0)
60631603Syokota	    | (sc->status.button ^ but);
60731603Syokota	sc->status.button = but;
60831603Syokota
609637Snate	/*
610637Snate	 * If mouse state has changed, wake up anyone wanting to know.
611637Snate	 */
612637Snate	if (sc->sc_deltax != 0 || sc->sc_deltay != 0 ||
613637Snate	    (sc->sc_obuttons ^ sc->sc_buttons) != 0) {
6148876Srgrimes		if (sc->sc_flags & MSESC_WANT) {
6158876Srgrimes			sc->sc_flags &= ~MSESC_WANT;
6168876Srgrimes			wakeup((caddr_t)sc);
6178876Srgrimes		}
6181549Srgrimes		selwakeup(&sc->sc_selp);
619637Snate	}
620637Snate}
621637Snate
622637Snate/*
623637Snate * Routines for the Logitech mouse.
624637Snate */
625637Snate/*
626637Snate * Test for a Logitech bus mouse and return 1 if it is.
627637Snate * (until I know how to use the signature port properly, just disable
628637Snate *  interrupts and return 1)
629637Snate */
630637Snatestatic int
631637Snatemse_probelogi(idp)
632637Snate	register struct isa_device *idp;
633637Snate{
634637Snate
6354259Sjkh	int sig;
6364259Sjkh
6374259Sjkh	outb(idp->id_iobase + MSE_PORTD, MSE_SETUP);
6384259Sjkh		/* set the signature port */
6394259Sjkh	outb(idp->id_iobase + MSE_PORTB, MSE_LOGI_SIG);
6404259Sjkh
6414259Sjkh	DELAY(30000); /* 30 ms delay */
6424259Sjkh	sig = inb(idp->id_iobase + MSE_PORTB) & 0xFF;
6434259Sjkh	if (sig == MSE_LOGI_SIG) {
6444259Sjkh		outb(idp->id_iobase + MSE_PORTC, MSE_DISINTR);
6454259Sjkh		return(1);
6464259Sjkh	} else {
64716074Sjoerg		if (bootverbose)
64816074Sjoerg			printf("mse%d: wrong signature %x\n",idp->id_unit,sig);
6494259Sjkh		return(0);
650637Snate	}
651637Snate}
652637Snate
653637Snate/*
654637Snate * Initialize Logitech mouse and enable interrupts.
655637Snate */
656637Snatestatic void
657637Snatemse_enablelogi(port)
658637Snate	register u_int port;
659637Snate{
660637Snate	int dx, dy, but;
661637Snate
662637Snate	outb(port + MSE_PORTD, MSE_SETUP);
663637Snate	mse_getlogi(port, &dx, &dy, &but);
664637Snate}
665637Snate
666637Snate/*
667637Snate * Disable interrupts for Logitech mouse.
668637Snate */
669637Snatestatic void
670637Snatemse_disablelogi(port)
671637Snate	register u_int port;
672637Snate{
673637Snate
674637Snate	outb(port + MSE_PORTC, MSE_DISINTR);
675637Snate}
676637Snate
677637Snate/*
678637Snate * Get the current dx, dy and button up/down state.
679637Snate */
680637Snatestatic void
681637Snatemse_getlogi(port, dx, dy, but)
682637Snate	register u_int port;
683637Snate	int *dx;
684637Snate	int *dy;
685637Snate	int *but;
686637Snate{
687637Snate	register char x, y;
688637Snate
689637Snate	outb(port + MSE_PORTC, MSE_HOLD | MSE_RXLOW);
690637Snate	x = inb(port + MSE_PORTA);
69131603Syokota	*but = (x >> 5) & MOUSE_MSC_BUTTONS;
692637Snate	x &= 0xf;
693637Snate	outb(port + MSE_PORTC, MSE_HOLD | MSE_RXHIGH);
694637Snate	x |= (inb(port + MSE_PORTA) << 4);
695637Snate	outb(port + MSE_PORTC, MSE_HOLD | MSE_RYLOW);
696637Snate	y = (inb(port + MSE_PORTA) & 0xf);
697637Snate	outb(port + MSE_PORTC, MSE_HOLD | MSE_RYHIGH);
698637Snate	y |= (inb(port + MSE_PORTA) << 4);
69931603Syokota	*dx = x;
70031603Syokota	*dy = y;
701637Snate	outb(port + MSE_PORTC, MSE_INTREN);
702637Snate}
703637Snate
704637Snate/*
705637Snate * Routines for the ATI Inport bus mouse.
706637Snate */
707637Snate/*
708637Snate * Test for a ATI Inport bus mouse and return 1 if it is.
709637Snate * (do not enable interrupts)
710637Snate */
711637Snatestatic int
712637Snatemse_probeati(idp)
713637Snate	register struct isa_device *idp;
714637Snate{
715637Snate	int i;
716637Snate
717637Snate	for (i = 0; i < 2; i++)
718637Snate		if (inb(idp->id_iobase + MSE_PORTC) == 0xde)
719637Snate			return (1);
720637Snate	return (0);
721637Snate}
722637Snate
723637Snate/*
724637Snate * Initialize ATI Inport mouse and enable interrupts.
725637Snate */
726637Snatestatic void
727637Snatemse_enableati(port)
728637Snate	register u_int port;
729637Snate{
730637Snate
731637Snate	outb(port + MSE_PORTA, MSE_INPORT_RESET);
732637Snate	outb(port + MSE_PORTA, MSE_INPORT_MODE);
733637Snate	outb(port + MSE_PORTB, MSE_INPORT_INTREN);
734637Snate}
735637Snate
736637Snate/*
737637Snate * Disable interrupts for ATI Inport mouse.
738637Snate */
739637Snatestatic void
740637Snatemse_disableati(port)
741637Snate	register u_int port;
742637Snate{
743637Snate
744637Snate	outb(port + MSE_PORTA, MSE_INPORT_MODE);
745637Snate	outb(port + MSE_PORTB, 0);
746637Snate}
747637Snate
748637Snate/*
749637Snate * Get current dx, dy and up/down button state.
750637Snate */
751637Snatestatic void
752637Snatemse_getati(port, dx, dy, but)
753637Snate	register u_int port;
754637Snate	int *dx;
755637Snate	int *dy;
756637Snate	int *but;
757637Snate{
758637Snate	register char byte;
759637Snate
760637Snate	outb(port + MSE_PORTA, MSE_INPORT_MODE);
761637Snate	outb(port + MSE_PORTB, MSE_INPORT_HOLD);
762637Snate	outb(port + MSE_PORTA, MSE_INPORT_STATUS);
76331603Syokota	*but = ~inb(port + MSE_PORTB) & MOUSE_MSC_BUTTONS;
764637Snate	outb(port + MSE_PORTA, MSE_INPORT_DX);
765637Snate	byte = inb(port + MSE_PORTB);
76631603Syokota	*dx = byte;
767637Snate	outb(port + MSE_PORTA, MSE_INPORT_DY);
768637Snate	byte = inb(port + MSE_PORTB);
76931603Syokota	*dy = byte;
770637Snate	outb(port + MSE_PORTA, MSE_INPORT_MODE);
771637Snate	outb(port + MSE_PORTB, MSE_INPORT_INTREN);
772637Snate}
77312502Sjulian
77446153Sdtstatic int mse_devsw_installed;
77512502Sjulian
77612517Sjulianstatic void 	mse_drvinit(void *unused)
77712502Sjulian{
77812517Sjulian	dev_t dev;
77912517Sjulian
78012502Sjulian	if( ! mse_devsw_installed ) {
78112675Sjulian		dev = makedev(CDEV_MAJOR, 0);
78212675Sjulian		cdevsw_add(&dev,&mse_cdevsw, NULL);
78312502Sjulian		mse_devsw_installed = 1;
78412517Sjulian    	}
78512502Sjulian}
78612517Sjulian
78712517SjulianSYSINIT(msedev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,mse_drvinit,NULL)
78812517Sjulian
78912517Sjulian
790637Snate#endif /* NMSE */
791