mse.c revision 46153
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 *
1446153Sdt * $Id: mse.c,v 1.39 1998/10/22 05:58:39 bde 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;
360637Snate			if (error = tsleep((caddr_t)sc, MSEPRI | PCATCH,
361637Snate				"mseread", 0)) {
362637Snate				splx(s);
363637Snate				return (error);
364637Snate			}
365637Snate		}
366637Snate
367637Snate		/*
368637Snate		 * Generate protocol bytes.
369637Snate		 * For some reason X386 expects 5 bytes but never uses
370637Snate		 * the fourth or fifth?
371637Snate		 */
37231603Syokota		sc->sc_bytes[0] = sc->mode.syncmask[1]
37331603Syokota		    | (sc->sc_buttons & ~sc->mode.syncmask[0]);
374637Snate		if (sc->sc_deltax > 127)
375637Snate			sc->sc_deltax = 127;
376637Snate		if (sc->sc_deltax < -127)
377637Snate			sc->sc_deltax = -127;
378637Snate		sc->sc_deltay = -sc->sc_deltay;	/* Otherwise mousey goes wrong way */
379637Snate		if (sc->sc_deltay > 127)
380637Snate			sc->sc_deltay = 127;
381637Snate		if (sc->sc_deltay < -127)
382637Snate			sc->sc_deltay = -127;
383637Snate		sc->sc_bytes[1] = sc->sc_deltax;
384637Snate		sc->sc_bytes[2] = sc->sc_deltay;
385637Snate		sc->sc_bytes[3] = sc->sc_bytes[4] = 0;
38631603Syokota		sc->sc_bytes[5] = sc->sc_bytes[6] = 0;
38731603Syokota		sc->sc_bytes[7] = MOUSE_SYS_EXTBUTTONS;
388637Snate		sc->sc_obuttons = sc->sc_buttons;
389637Snate		sc->sc_deltax = sc->sc_deltay = 0;
390637Snate		sc->sc_bytesread = 0;
391637Snate	}
392637Snate	splx(s);
39331603Syokota	xfer = min(uio->uio_resid, sc->mode.packetsize - sc->sc_bytesread);
394637Snate	if (error = uiomove(&sc->sc_bytes[sc->sc_bytesread], xfer, uio))
395637Snate		return (error);
396637Snate	sc->sc_bytesread += xfer;
397637Snate	return(0);
398637Snate}
399637Snate
400637Snate/*
40131603Syokota * mseioctl: process ioctl commands.
40231603Syokota */
40331603Syokotastatic int
40431603Syokotamseioctl(dev, cmd, addr, flag, p)
40531603Syokota	dev_t dev;
40636735Sdfr	u_long cmd;
40731603Syokota	caddr_t addr;
40831603Syokota	int flag;
40931603Syokota	struct proc *p;
41031603Syokota{
41131603Syokota	register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
41231603Syokota	mousestatus_t status;
41331603Syokota	int err = 0;
41431603Syokota	int s;
41531603Syokota
41631603Syokota	switch (cmd) {
41731603Syokota
41831603Syokota	case MOUSE_GETHWINFO:
41931603Syokota		s = spltty();
42031603Syokota		*(mousehw_t *)addr = sc->hw;
42131603Syokota		if (sc->mode.level == 0)
42231603Syokota			((mousehw_t *)addr)->model = MOUSE_MODEL_GENERIC;
42331603Syokota		splx(s);
42431603Syokota		break;
42531603Syokota
42631603Syokota	case MOUSE_GETMODE:
42731603Syokota		s = spltty();
42831603Syokota		*(mousemode_t *)addr = sc->mode;
42931603Syokota		switch (sc->mode.level) {
43031603Syokota		case 0:
43131603Syokota			break;
43231603Syokota		case 1:
43331603Syokota			((mousemode_t *)addr)->protocol = MOUSE_PROTO_SYSMOUSE;
43431603Syokota	    		((mousemode_t *)addr)->syncmask[0] = MOUSE_SYS_SYNCMASK;
43531603Syokota	    		((mousemode_t *)addr)->syncmask[1] = MOUSE_SYS_SYNC;
43631603Syokota			break;
43731603Syokota		}
43831603Syokota		splx(s);
43931603Syokota		break;
44031603Syokota
44131603Syokota	case MOUSE_SETMODE:
44231603Syokota		switch (((mousemode_t *)addr)->level) {
44331603Syokota		case 0:
44431603Syokota		case 1:
44531603Syokota			break;
44631603Syokota		default:
44731603Syokota			return (EINVAL);
44831603Syokota		}
44931603Syokota		if (((mousemode_t *)addr)->accelfactor < -1)
45031603Syokota			return (EINVAL);
45131603Syokota		else if (((mousemode_t *)addr)->accelfactor >= 0)
45231603Syokota			sc->mode.accelfactor =
45331603Syokota			    ((mousemode_t *)addr)->accelfactor;
45431603Syokota		sc->mode.level = ((mousemode_t *)addr)->level;
45531603Syokota		switch (sc->mode.level) {
45631603Syokota		case 0:
45731603Syokota			sc->sc_bytesread = sc->mode.packetsize
45831603Syokota			    = MOUSE_MSC_PACKETSIZE;
45931603Syokota			break;
46031603Syokota		case 1:
46131603Syokota			sc->sc_bytesread = sc->mode.packetsize
46231603Syokota			    = MOUSE_SYS_PACKETSIZE;
46331603Syokota			break;
46431603Syokota		}
46531603Syokota		break;
46631603Syokota
46731603Syokota	case MOUSE_GETLEVEL:
46831603Syokota		*(int *)addr = sc->mode.level;
46931603Syokota		break;
47031603Syokota
47131603Syokota	case MOUSE_SETLEVEL:
47231603Syokota		switch (*(int *)addr) {
47331603Syokota		case 0:
47431603Syokota			sc->mode.level = *(int *)addr;
47531603Syokota			sc->sc_bytesread = sc->mode.packetsize
47631603Syokota			    = MOUSE_MSC_PACKETSIZE;
47731603Syokota			break;
47831603Syokota		case 1:
47931603Syokota			sc->mode.level = *(int *)addr;
48031603Syokota			sc->sc_bytesread = sc->mode.packetsize
48131603Syokota			    = MOUSE_SYS_PACKETSIZE;
48231603Syokota			break;
48331603Syokota		default:
48431603Syokota			return (EINVAL);
48531603Syokota		}
48631603Syokota		break;
48731603Syokota
48831603Syokota	case MOUSE_GETSTATUS:
48931603Syokota		s = spltty();
49031603Syokota		status = sc->status;
49131603Syokota		sc->status.flags = 0;
49231603Syokota		sc->status.obutton = sc->status.button;
49331603Syokota		sc->status.button = 0;
49431603Syokota		sc->status.dx = 0;
49531603Syokota		sc->status.dy = 0;
49631603Syokota		sc->status.dz = 0;
49731603Syokota		splx(s);
49831603Syokota		*(mousestatus_t *)addr = status;
49931603Syokota		break;
50031603Syokota
50131603Syokota	case MOUSE_READSTATE:
50231603Syokota	case MOUSE_READDATA:
50331603Syokota		return (ENODEV);
50431603Syokota
50531603Syokota#if (defined(MOUSE_GETVARS))
50631603Syokota	case MOUSE_GETVARS:
50731603Syokota	case MOUSE_SETVARS:
50831603Syokota		return (ENODEV);
50931603Syokota#endif
51031603Syokota
51131603Syokota	default:
51231603Syokota		return (ENOTTY);
51331603Syokota	}
51431603Syokota	return (err);
51531603Syokota}
51631603Syokota
51731603Syokota/*
51829368Speter * msepoll: check for mouse input to be processed.
519637Snate */
52012675Sjulianstatic	int
52129368Spetermsepoll(dev, events, p)
522637Snate	dev_t dev;
52329368Speter	int events;
524637Snate	struct proc *p;
525637Snate{
526637Snate	register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
527637Snate	int s;
52829368Speter	int revents = 0;
529637Snate
530637Snate	s = spltty();
53129368Speter	if (events & (POLLIN | POLLRDNORM))
53231603Syokota		if (sc->sc_bytesread != sc->mode.packetsize ||
53331603Syokota		    sc->sc_deltax != 0 || sc->sc_deltay != 0 ||
53429368Speter		    (sc->sc_obuttons ^ sc->sc_buttons) != 0)
53529368Speter			revents |= events & (POLLIN | POLLRDNORM);
53629368Speter		else {
53729368Speter			/*
53829368Speter			 * Since this is an exclusive open device, any previous
53929368Speter			 * proc pointer is trash now, so we can just assign it.
54029368Speter			 */
54129368Speter			selrecord(p, &sc->sc_selp);
54229368Speter		}
543637Snate
544637Snate	splx(s);
54529368Speter	return (revents);
546637Snate}
547637Snate
548637Snate/*
549637Snate * mseintr: update mouse status. sc_deltax and sc_deltay are accumulative.
550637Snate */
55140565Sbdestatic void
552637Snatemseintr(unit)
553637Snate	int unit;
554637Snate{
55531603Syokota	/*
55631603Syokota	 * the table to turn MouseSystem button bits (MOUSE_MSC_BUTTON?UP)
55731603Syokota	 * into `mousestatus' button bits (MOUSE_BUTTON?DOWN).
55831603Syokota	 */
55931603Syokota	static int butmap[8] = {
56031603Syokota		0,
56131603Syokota		MOUSE_BUTTON3DOWN,
56231603Syokota		MOUSE_BUTTON2DOWN,
56331603Syokota		MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN,
56431603Syokota		MOUSE_BUTTON1DOWN,
56531603Syokota		MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN,
56631603Syokota		MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN,
56731603Syokota        	MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN
56831603Syokota	};
569637Snate	register struct mse_softc *sc = &mse_sc[unit];
57031603Syokota	int dx, dy, but;
57131603Syokota	int sign;
572637Snate
573637Snate#ifdef DEBUG
574637Snate	static int mse_intrcnt = 0;
575637Snate	if((mse_intrcnt++ % 10000) == 0)
576637Snate		printf("mseintr\n");
577637Snate#endif /* DEBUG */
578637Snate	if ((sc->sc_flags & MSESC_OPEN) == 0)
579637Snate		return;
580637Snate
58131603Syokota	(*sc->sc_getmouse)(sc->sc_port, &dx, &dy, &but);
58231603Syokota	if (sc->mode.accelfactor > 0) {
58331603Syokota		sign = (dx < 0);
58431603Syokota		dx = dx * dx / sc->mode.accelfactor;
58531603Syokota		if (dx == 0)
58631603Syokota			dx = 1;
58731603Syokota		if (sign)
58831603Syokota			dx = -dx;
58931603Syokota		sign = (dy < 0);
59031603Syokota		dy = dy * dy / sc->mode.accelfactor;
59131603Syokota		if (dy == 0)
59231603Syokota			dy = 1;
59331603Syokota		if (sign)
59431603Syokota			dy = -dy;
59531603Syokota	}
59631603Syokota	sc->sc_deltax += dx;
59731603Syokota	sc->sc_deltay += dy;
59831603Syokota	sc->sc_buttons = but;
599637Snate
60031603Syokota	but = butmap[~but & MOUSE_MSC_BUTTONS];
60131603Syokota	sc->status.dx += dx;
60231603Syokota	sc->status.dy += dy;
60331603Syokota	sc->status.flags |= ((dx || dy) ? MOUSE_POSCHANGED : 0)
60431603Syokota	    | (sc->status.button ^ but);
60531603Syokota	sc->status.button = but;
60631603Syokota
607637Snate	/*
608637Snate	 * If mouse state has changed, wake up anyone wanting to know.
609637Snate	 */
610637Snate	if (sc->sc_deltax != 0 || sc->sc_deltay != 0 ||
611637Snate	    (sc->sc_obuttons ^ sc->sc_buttons) != 0) {
6128876Srgrimes		if (sc->sc_flags & MSESC_WANT) {
6138876Srgrimes			sc->sc_flags &= ~MSESC_WANT;
6148876Srgrimes			wakeup((caddr_t)sc);
6158876Srgrimes		}
6161549Srgrimes		selwakeup(&sc->sc_selp);
617637Snate	}
618637Snate}
619637Snate
620637Snate/*
621637Snate * Routines for the Logitech mouse.
622637Snate */
623637Snate/*
624637Snate * Test for a Logitech bus mouse and return 1 if it is.
625637Snate * (until I know how to use the signature port properly, just disable
626637Snate *  interrupts and return 1)
627637Snate */
628637Snatestatic int
629637Snatemse_probelogi(idp)
630637Snate	register struct isa_device *idp;
631637Snate{
632637Snate
6334259Sjkh	int sig;
6344259Sjkh
6354259Sjkh	outb(idp->id_iobase + MSE_PORTD, MSE_SETUP);
6364259Sjkh		/* set the signature port */
6374259Sjkh	outb(idp->id_iobase + MSE_PORTB, MSE_LOGI_SIG);
6384259Sjkh
6394259Sjkh	DELAY(30000); /* 30 ms delay */
6404259Sjkh	sig = inb(idp->id_iobase + MSE_PORTB) & 0xFF;
6414259Sjkh	if (sig == MSE_LOGI_SIG) {
6424259Sjkh		outb(idp->id_iobase + MSE_PORTC, MSE_DISINTR);
6434259Sjkh		return(1);
6444259Sjkh	} else {
64516074Sjoerg		if (bootverbose)
64616074Sjoerg			printf("mse%d: wrong signature %x\n",idp->id_unit,sig);
6474259Sjkh		return(0);
648637Snate	}
649637Snate}
650637Snate
651637Snate/*
652637Snate * Initialize Logitech mouse and enable interrupts.
653637Snate */
654637Snatestatic void
655637Snatemse_enablelogi(port)
656637Snate	register u_int port;
657637Snate{
658637Snate	int dx, dy, but;
659637Snate
660637Snate	outb(port + MSE_PORTD, MSE_SETUP);
661637Snate	mse_getlogi(port, &dx, &dy, &but);
662637Snate}
663637Snate
664637Snate/*
665637Snate * Disable interrupts for Logitech mouse.
666637Snate */
667637Snatestatic void
668637Snatemse_disablelogi(port)
669637Snate	register u_int port;
670637Snate{
671637Snate
672637Snate	outb(port + MSE_PORTC, MSE_DISINTR);
673637Snate}
674637Snate
675637Snate/*
676637Snate * Get the current dx, dy and button up/down state.
677637Snate */
678637Snatestatic void
679637Snatemse_getlogi(port, dx, dy, but)
680637Snate	register u_int port;
681637Snate	int *dx;
682637Snate	int *dy;
683637Snate	int *but;
684637Snate{
685637Snate	register char x, y;
686637Snate
687637Snate	outb(port + MSE_PORTC, MSE_HOLD | MSE_RXLOW);
688637Snate	x = inb(port + MSE_PORTA);
68931603Syokota	*but = (x >> 5) & MOUSE_MSC_BUTTONS;
690637Snate	x &= 0xf;
691637Snate	outb(port + MSE_PORTC, MSE_HOLD | MSE_RXHIGH);
692637Snate	x |= (inb(port + MSE_PORTA) << 4);
693637Snate	outb(port + MSE_PORTC, MSE_HOLD | MSE_RYLOW);
694637Snate	y = (inb(port + MSE_PORTA) & 0xf);
695637Snate	outb(port + MSE_PORTC, MSE_HOLD | MSE_RYHIGH);
696637Snate	y |= (inb(port + MSE_PORTA) << 4);
69731603Syokota	*dx = x;
69831603Syokota	*dy = y;
699637Snate	outb(port + MSE_PORTC, MSE_INTREN);
700637Snate}
701637Snate
702637Snate/*
703637Snate * Routines for the ATI Inport bus mouse.
704637Snate */
705637Snate/*
706637Snate * Test for a ATI Inport bus mouse and return 1 if it is.
707637Snate * (do not enable interrupts)
708637Snate */
709637Snatestatic int
710637Snatemse_probeati(idp)
711637Snate	register struct isa_device *idp;
712637Snate{
713637Snate	int i;
714637Snate
715637Snate	for (i = 0; i < 2; i++)
716637Snate		if (inb(idp->id_iobase + MSE_PORTC) == 0xde)
717637Snate			return (1);
718637Snate	return (0);
719637Snate}
720637Snate
721637Snate/*
722637Snate * Initialize ATI Inport mouse and enable interrupts.
723637Snate */
724637Snatestatic void
725637Snatemse_enableati(port)
726637Snate	register u_int port;
727637Snate{
728637Snate
729637Snate	outb(port + MSE_PORTA, MSE_INPORT_RESET);
730637Snate	outb(port + MSE_PORTA, MSE_INPORT_MODE);
731637Snate	outb(port + MSE_PORTB, MSE_INPORT_INTREN);
732637Snate}
733637Snate
734637Snate/*
735637Snate * Disable interrupts for ATI Inport mouse.
736637Snate */
737637Snatestatic void
738637Snatemse_disableati(port)
739637Snate	register u_int port;
740637Snate{
741637Snate
742637Snate	outb(port + MSE_PORTA, MSE_INPORT_MODE);
743637Snate	outb(port + MSE_PORTB, 0);
744637Snate}
745637Snate
746637Snate/*
747637Snate * Get current dx, dy and up/down button state.
748637Snate */
749637Snatestatic void
750637Snatemse_getati(port, dx, dy, but)
751637Snate	register u_int port;
752637Snate	int *dx;
753637Snate	int *dy;
754637Snate	int *but;
755637Snate{
756637Snate	register char byte;
757637Snate
758637Snate	outb(port + MSE_PORTA, MSE_INPORT_MODE);
759637Snate	outb(port + MSE_PORTB, MSE_INPORT_HOLD);
760637Snate	outb(port + MSE_PORTA, MSE_INPORT_STATUS);
76131603Syokota	*but = ~inb(port + MSE_PORTB) & MOUSE_MSC_BUTTONS;
762637Snate	outb(port + MSE_PORTA, MSE_INPORT_DX);
763637Snate	byte = inb(port + MSE_PORTB);
76431603Syokota	*dx = byte;
765637Snate	outb(port + MSE_PORTA, MSE_INPORT_DY);
766637Snate	byte = inb(port + MSE_PORTB);
76731603Syokota	*dy = byte;
768637Snate	outb(port + MSE_PORTA, MSE_INPORT_MODE);
769637Snate	outb(port + MSE_PORTB, MSE_INPORT_INTREN);
770637Snate}
77112502Sjulian
77246153Sdtstatic int mse_devsw_installed;
77312502Sjulian
77412517Sjulianstatic void 	mse_drvinit(void *unused)
77512502Sjulian{
77612517Sjulian	dev_t dev;
77712517Sjulian
77812502Sjulian	if( ! mse_devsw_installed ) {
77912675Sjulian		dev = makedev(CDEV_MAJOR, 0);
78012675Sjulian		cdevsw_add(&dev,&mse_cdevsw, NULL);
78112502Sjulian		mse_devsw_installed = 1;
78212517Sjulian    	}
78312502Sjulian}
78412517Sjulian
78512517SjulianSYSINIT(msedev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,mse_drvinit,NULL)
78612517Sjulian
78712517Sjulian
788637Snate#endif /* NMSE */
789