mse.c revision 27555
138032Speter/*
2112810Sgshapiro * Copyright 1992 by the University of Guelph
338032Speter *
438032Speter * Permission to use, copy and modify this
538032Speter * software and its documentation for any purpose and without
638032Speter * fee is hereby granted, provided that the above copyright
738032Speter * notice appear in all copies and that both that copyright
838032Speter * notice and this permission notice appear in supporting
9112810Sgshapiro * documentation.
10112810Sgshapiro * University of Guelph makes no representations about the suitability of
11112810Sgshapiro * this software for any purpose.  It is provided "as is"
12112810Sgshapiro * without express or implied warranty.
13112810Sgshapiro *
14112810Sgshapiro * $Id: mse.c,v 1.32 1997/03/24 11:23:56 bde Exp $
15112810Sgshapiro */
16112810Sgshapiro/*
17112810Sgshapiro * Driver for the Logitech and ATI Inport Bus mice for use with 386bsd and
18112810Sgshapiro * the X386 port, courtesy of
19112810Sgshapiro * Rick Macklem, rick@snowhite.cis.uoguelph.ca
20112810Sgshapiro * Caveats: The driver currently uses spltty(), but doesn't use any
21112810Sgshapiro * generic tty code. It could use splmse() (that only masks off the
22112810Sgshapiro * bus mouse interrupt, but that would require hacking in i386/isa/icu.s.
23112810Sgshapiro * (This may be worth the effort, since the Logitech generates 30/60
24112810Sgshapiro * interrupts/sec continuously while it is open.)
25112810Sgshapiro * NB: The ATI has NOT been tested yet!
26112810Sgshapiro */
27112810Sgshapiro
28112810Sgshapiro/*
29112810Sgshapiro * Modification history:
30112810Sgshapiro * Sep 6, 1994 -- Lars Fredriksen(fredriks@mcs.com)
31112810Sgshapiro *   improved probe based on input from Logitech.
32112810Sgshapiro *
33112810Sgshapiro * Oct 19, 1992 -- E. Stark (stark@cs.sunysb.edu)
34112810Sgshapiro *   fixes to make it work with Microsoft InPort busmouse
35112810Sgshapiro *
36112810Sgshapiro * Jan, 1993 -- E. Stark (stark@cs.sunysb.edu)
37112810Sgshapiro *   added patches for new "select" interface
38112810Sgshapiro *
39112810Sgshapiro * May 4, 1993 -- E. Stark (stark@cs.sunysb.edu)
40112810Sgshapiro *   changed position of some spl()'s in mseread
41112810Sgshapiro *
42112810Sgshapiro * October 8, 1993 -- E. Stark (stark@cs.sunysb.edu)
43112810Sgshapiro *   limit maximum negative x/y value to -127 to work around XFree problem
44112810Sgshapiro *   that causes spurious button pushes.
45112810Sgshapiro */
46111823Sgshapiro
47111823Sgshapiro#include "mse.h"
48111823Sgshapiro#if NMSE > 0
49111823Sgshapiro#include <sys/param.h>
50111823Sgshapiro#include <sys/systm.h>
51111823Sgshapiro#include <sys/conf.h>
52111823Sgshapiro#include <sys/proc.h>
53111823Sgshapiro#include <sys/kernel.h>
54111823Sgshapiro#include <sys/uio.h>
55111823Sgshapiro#ifdef DEVFS
56111823Sgshapiro#include <sys/devfsext.h>
57111823Sgshapiro#endif /*DEVFS*/
58111823Sgshapiro
59111823Sgshapiro#include <machine/clock.h>
60111823Sgshapiro
61111823Sgshapiro#include <i386/isa/isa_device.h>
62111823Sgshapiro
63111823Sgshapirostatic int mseprobe(struct isa_device *);
64111823Sgshapirostatic int mseattach(struct isa_device *);
65111823Sgshapiro
66110560Sgshapirostruct	isa_driver msedriver = {
67110560Sgshapiro	mseprobe, mseattach, "mse"
68110560Sgshapiro};
69110560Sgshapiro
70110560Sgshapirostatic	d_open_t	mseopen;
71110560Sgshapirostatic	d_close_t	mseclose;
72110560Sgshapirostatic	d_read_t	mseread;
73110560Sgshapirostatic	d_select_t	mseselect;
74110560Sgshapiro
75110560Sgshapiro#define CDEV_MAJOR 27
76110560Sgshapirostatic struct cdevsw mse_cdevsw =
77110560Sgshapiro	{ mseopen,	mseclose,	mseread,	nowrite,	/*27*/
78110560Sgshapiro	  noioc,	nostop,		nullreset,	nodevtotty,/* mse */
79110560Sgshapiro	  mseselect,	nommap,		NULL,	"mse",	NULL,	-1 };
80110560Sgshapiro
81110560Sgshapiro
82110560Sgshapiro/*
83110560Sgshapiro * Software control structure for mouse. The sc_enablemouse(),
84110560Sgshapiro * sc_disablemouse() and sc_getmouse() routines must be called spl'd().
85110560Sgshapiro */
86110560Sgshapiro#define	PROTOBYTES	5
87110560Sgshapirostatic struct mse_softc {
88110560Sgshapiro	int	sc_flags;
89110560Sgshapiro	int	sc_mousetype;
90110560Sgshapiro	struct	selinfo sc_selp;
91110560Sgshapiro	u_int	sc_port;
92110560Sgshapiro	void	(*sc_enablemouse) __P((u_int port));
93110560Sgshapiro	void	(*sc_disablemouse) __P((u_int port));
94110560Sgshapiro	void	(*sc_getmouse) __P((u_int port, int *dx, int *dy, int *but));
95110560Sgshapiro	int	sc_deltax;
96110560Sgshapiro	int	sc_deltay;
97110560Sgshapiro	int	sc_obuttons;
98110560Sgshapiro	int	sc_buttons;
99110560Sgshapiro	int	sc_bytesread;
100110560Sgshapiro	u_char	sc_bytes[PROTOBYTES];
101110560Sgshapiro#ifdef DEVFS
102110560Sgshapiro	void 	*devfs_token;
103110560Sgshapiro	void	*n_devfs_token;
104110560Sgshapiro#endif
105110560Sgshapiro} mse_sc[NMSE];
106110560Sgshapiro
107110560Sgshapiro/* Flags */
108110560Sgshapiro#define	MSESC_OPEN	0x1
109110560Sgshapiro#define	MSESC_WANT	0x2
110110560Sgshapiro
111110560Sgshapiro/* and Mouse Types */
112110560Sgshapiro#define	MSE_NONE	0	/* don't move this! */
113110560Sgshapiro#define	MSE_LOGITECH	0x1
114110560Sgshapiro#define	MSE_ATIINPORT	0x2
115110560Sgshapiro#define	MSE_LOGI_SIG	0xA5
116110560Sgshapiro
117110560Sgshapiro#define	MSE_PORTA	0
118110560Sgshapiro#define	MSE_PORTB	1
119110560Sgshapiro#define	MSE_PORTC	2
120111823Sgshapiro#define	MSE_PORTD	3
121110560Sgshapiro
122110560Sgshapiro#define	MSE_UNIT(dev)		(minor(dev) >> 1)
123110560Sgshapiro#define	MSE_NBLOCKIO(dev)	(minor(dev) & 0x1)
124110560Sgshapiro
125110560Sgshapiro/*
126110560Sgshapiro * Logitech bus mouse definitions
127110560Sgshapiro */
128110560Sgshapiro#define	MSE_SETUP	0x91	/* What does this mean? */
129110560Sgshapiro				/* The definition for the control port */
130110560Sgshapiro				/* is as follows: */
131110560Sgshapiro
132110560Sgshapiro				/* D7 	 =  Mode set flag (1 = active) 	*/
133110560Sgshapiro				/* D6,D5 =  Mode selection (port A) 	*/
134110560Sgshapiro				/* 	    00 = Mode 0 = Basic I/O 	*/
135110560Sgshapiro				/* 	    01 = Mode 1 = Strobed I/O 	*/
136110560Sgshapiro				/* 	    10 = Mode 2 = Bi-dir bus 	*/
137110560Sgshapiro				/* D4	 =  Port A direction (1 = input)*/
138110560Sgshapiro				/* D3	 =  Port C (upper 4 bits) 	*/
139110560Sgshapiro				/*	    direction. (1 = input)	*/
140110560Sgshapiro				/* D2	 =  Mode selection (port B & C) */
141110560Sgshapiro				/*	    0 = Mode 0 = Basic I/O	*/
142110560Sgshapiro				/*	    1 = Mode 1 = Strobed I/O	*/
143110560Sgshapiro				/* D1	 =  Port B direction (1 = input)*/
144110560Sgshapiro				/* D0	 =  Port C (lower 4 bits)	*/
145110560Sgshapiro				/*	    direction. (1 = input)	*/
146110560Sgshapiro
147110560Sgshapiro				/* So 91 means Basic I/O on all 3 ports,*/
148110560Sgshapiro				/* Port A is an input port, B is an 	*/
149110560Sgshapiro				/* output port, C is split with upper	*/
150110560Sgshapiro				/* 4 bits being an output port and lower*/
151110560Sgshapiro				/* 4 bits an input port, and enable the */
152110560Sgshapiro				/* sucker.				*/
153110560Sgshapiro				/* Courtesy Intel 8255 databook. Lars   */
154110560Sgshapiro#define	MSE_HOLD	0x80
155110560Sgshapiro#define	MSE_RXLOW	0x00
156110560Sgshapiro#define	MSE_RXHIGH	0x20
157110560Sgshapiro#define	MSE_RYLOW	0x40
158110560Sgshapiro#define	MSE_RYHIGH	0x60
159110560Sgshapiro#define	MSE_DISINTR	0x10
160110560Sgshapiro#define MSE_INTREN	0x00
161110560Sgshapiro
162110560Sgshapirostatic int mse_probelogi __P((struct isa_device *idp));
163110560Sgshapirostatic void mse_disablelogi __P((u_int port));
164110560Sgshapirostatic void mse_getlogi __P((u_int port, int *dx, int *dy, int *but));
165110560Sgshapirostatic void mse_enablelogi __P((u_int port));
166110560Sgshapiro
167110560Sgshapiro/*
168110560Sgshapiro * ATI Inport mouse definitions
169110560Sgshapiro */
170110560Sgshapiro#define	MSE_INPORT_RESET	0x80
171110560Sgshapiro#define	MSE_INPORT_STATUS	0x00
172110560Sgshapiro#define	MSE_INPORT_DX		0x01
173110560Sgshapiro#define	MSE_INPORT_DY		0x02
174110560Sgshapiro#define	MSE_INPORT_MODE		0x07
175110560Sgshapiro#define	MSE_INPORT_HOLD		0x20
176110560Sgshapiro#define	MSE_INPORT_INTREN	0x09
177110560Sgshapiro
178102528Sgshapirostatic int mse_probeati __P((struct isa_device *idp));
179102528Sgshapirostatic void mse_enableati __P((u_int port));
180102528Sgshapirostatic void mse_disableati __P((u_int port));
181102528Sgshapirostatic void mse_getati __P((u_int port, int *dx, int *dy, int *but));
182102528Sgshapiro
183102528Sgshapiro#define	MSEPRI	(PZERO + 3)
184102528Sgshapiro
185102528Sgshapiro/*
186102528Sgshapiro * Table of mouse types.
187102528Sgshapiro * Keep the Logitech last, since I haven't figured out how to probe it
188102528Sgshapiro * properly yet. (Someday I'll have the documentation.)
189102528Sgshapiro */
190102528Sgshapirostatic struct mse_types {
191102528Sgshapiro	int	m_type;		/* Type of bus mouse */
192102528Sgshapiro	int	(*m_probe) __P((struct isa_device *idp));
193102528Sgshapiro				/* Probe routine to test for it */
194102528Sgshapiro	void	(*m_enable) __P((u_int port));
195102528Sgshapiro				/* Start routine */
196102528Sgshapiro	void	(*m_disable) __P((u_int port));
197102528Sgshapiro				/* Disable interrupts routine */
198102528Sgshapiro	void	(*m_get) __P((u_int port, int *dx, int *dy, int *but));
199102528Sgshapiro				/* and get mouse status */
200102528Sgshapiro} mse_types[] = {
201102528Sgshapiro	{ MSE_ATIINPORT, mse_probeati, mse_enableati, mse_disableati, mse_getati },
202102528Sgshapiro	{ MSE_LOGITECH, mse_probelogi, mse_enablelogi, mse_disablelogi, mse_getlogi },
203102528Sgshapiro	{ 0, },
204102528Sgshapiro};
205102528Sgshapiro
206102528Sgshapiroint
207102528Sgshapiromseprobe(idp)
208102528Sgshapiro	register struct isa_device *idp;
209102528Sgshapiro{
210102528Sgshapiro	register struct mse_softc *sc = &mse_sc[idp->id_unit];
211102528Sgshapiro	register int i;
212102528Sgshapiro
213102528Sgshapiro	/*
214102528Sgshapiro	 * Check for each mouse type in the table.
215102528Sgshapiro	 */
216102528Sgshapiro	i = 0;
217102528Sgshapiro	while (mse_types[i].m_type) {
218102528Sgshapiro		if ((*mse_types[i].m_probe)(idp)) {
219102528Sgshapiro			sc->sc_mousetype = mse_types[i].m_type;
220102528Sgshapiro			sc->sc_enablemouse = mse_types[i].m_enable;
221102528Sgshapiro			sc->sc_disablemouse = mse_types[i].m_disable;
222102528Sgshapiro			sc->sc_getmouse = mse_types[i].m_get;
223102528Sgshapiro			return (1);
224102528Sgshapiro		}
225102528Sgshapiro		i++;
226102528Sgshapiro	}
227102528Sgshapiro	return (0);
228102528Sgshapiro}
229102528Sgshapiro
230102528Sgshapiroint
231102528Sgshapiromseattach(idp)
232102528Sgshapiro	struct isa_device *idp;
233102528Sgshapiro{
234102528Sgshapiro	int unit = idp->id_unit;
235102528Sgshapiro	struct mse_softc *sc = &mse_sc[unit];
236102528Sgshapiro
237102528Sgshapiro	sc->sc_port = idp->id_iobase;
238102528Sgshapiro#ifdef	DEVFS
239102528Sgshapiro	sc->devfs_token =
240102528Sgshapiro		devfs_add_devswf(&mse_cdevsw, unit << 1, DV_CHR, 0, 0,
241102528Sgshapiro				 0600, "mse%d", unit);
242102528Sgshapiro	sc->n_devfs_token =
243102528Sgshapiro		devfs_add_devswf(&mse_cdevsw, (unit<<1)+1, DV_CHR,0, 0,
244102528Sgshapiro				 0600, "nmse%d", unit);
245102528Sgshapiro#endif
246102528Sgshapiro	return (1);
247102528Sgshapiro}
248102528Sgshapiro
249102528Sgshapiro/*
250102528Sgshapiro * Exclusive open the mouse, initialize it and enable interrupts.
251102528Sgshapiro */
252102528Sgshapirostatic	int
253102528Sgshapiromseopen(dev, flags, fmt, p)
254102528Sgshapiro	dev_t dev;
255102528Sgshapiro	int flags;
256102528Sgshapiro	int fmt;
257102528Sgshapiro	struct proc *p;
25898841Sgshapiro{
25998841Sgshapiro	register struct mse_softc *sc;
26098841Sgshapiro	int s;
26198841Sgshapiro
26298841Sgshapiro	if (MSE_UNIT(dev) >= NMSE)
26398841Sgshapiro		return (ENXIO);
26498841Sgshapiro	sc = &mse_sc[MSE_UNIT(dev)];
26598841Sgshapiro	if (sc->sc_mousetype == MSE_NONE)
26698841Sgshapiro		return (ENXIO);
26798841Sgshapiro	if (sc->sc_flags & MSESC_OPEN)
26898841Sgshapiro		return (EBUSY);
26998841Sgshapiro	sc->sc_flags |= MSESC_OPEN;
27098841Sgshapiro	sc->sc_obuttons = sc->sc_buttons = 0x7;
27198841Sgshapiro	sc->sc_deltax = sc->sc_deltay = 0;
27298841Sgshapiro	sc->sc_bytesread = PROTOBYTES;
27398841Sgshapiro
27498841Sgshapiro	/*
27598841Sgshapiro	 * Initialize mouse interface and enable interrupts.
27698841Sgshapiro	 */
27798841Sgshapiro	s = spltty();
27898841Sgshapiro	(*sc->sc_enablemouse)(sc->sc_port);
27998841Sgshapiro	splx(s);
28098841Sgshapiro	return (0);
28198841Sgshapiro}
28298841Sgshapiro
28398841Sgshapiro/*
28498841Sgshapiro * mseclose: just turn off mouse innterrupts.
28598841Sgshapiro */
28698841Sgshapirostatic	int
28798841Sgshapiromseclose(dev, flags, fmt, p)
28898841Sgshapiro	dev_t dev;
28998841Sgshapiro	int flags;
29098841Sgshapiro	int fmt;
29198841Sgshapiro	struct proc *p;
29298121Sgshapiro{
29398121Sgshapiro	struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
29498121Sgshapiro	int s;
29598121Sgshapiro
29698121Sgshapiro	s = spltty();
29798121Sgshapiro	(*sc->sc_disablemouse)(sc->sc_port);
29898121Sgshapiro	sc->sc_flags &= ~MSESC_OPEN;
29998121Sgshapiro	splx(s);
30098121Sgshapiro	return(0);
30198121Sgshapiro}
30298121Sgshapiro
30398121Sgshapiro/*
30498121Sgshapiro * mseread: return mouse info using the MSC serial protocol, but without
30598121Sgshapiro * using bytes 4 and 5.
30698121Sgshapiro * (Yes this is cheesy, but it makes the X386 server happy, so...)
30798121Sgshapiro */
30898121Sgshapirostatic	int
30998121Sgshapiromseread(dev, uio, ioflag)
31098121Sgshapiro	dev_t dev;
31198121Sgshapiro	struct uio *uio;
31298121Sgshapiro	int ioflag;
31398121Sgshapiro{
31498121Sgshapiro	register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
31598121Sgshapiro	int xfer, s, error;
31698121Sgshapiro
31798121Sgshapiro	/*
31898121Sgshapiro	 * If there are no protocol bytes to be read, set up a new protocol
31998121Sgshapiro	 * packet.
32098121Sgshapiro	 */
32198121Sgshapiro	s = spltty(); /* XXX Should be its own spl, but where is imlXX() */
32298121Sgshapiro	if (sc->sc_bytesread >= PROTOBYTES) {
32398121Sgshapiro		while (sc->sc_deltax == 0 && sc->sc_deltay == 0 &&
32498121Sgshapiro		       (sc->sc_obuttons ^ sc->sc_buttons) == 0) {
32598121Sgshapiro			if (MSE_NBLOCKIO(dev)) {
32698121Sgshapiro				splx(s);
32798121Sgshapiro				return (0);
32898121Sgshapiro			}
32998121Sgshapiro			sc->sc_flags |= MSESC_WANT;
33098121Sgshapiro			if (error = tsleep((caddr_t)sc, MSEPRI | PCATCH,
33198121Sgshapiro				"mseread", 0)) {
33298121Sgshapiro				splx(s);
33398121Sgshapiro				return (error);
33498121Sgshapiro			}
33598121Sgshapiro		}
33698121Sgshapiro
33798121Sgshapiro		/*
33898121Sgshapiro		 * Generate protocol bytes.
33998121Sgshapiro		 * For some reason X386 expects 5 bytes but never uses
34098121Sgshapiro		 * the fourth or fifth?
34198121Sgshapiro		 */
34298121Sgshapiro		sc->sc_bytes[0] = 0x80 | (sc->sc_buttons & ~0xf8);
34398121Sgshapiro		if (sc->sc_deltax > 127)
34498121Sgshapiro			sc->sc_deltax = 127;
34598121Sgshapiro		if (sc->sc_deltax < -127)
34698121Sgshapiro			sc->sc_deltax = -127;
34798121Sgshapiro		sc->sc_deltay = -sc->sc_deltay;	/* Otherwise mousey goes wrong way */
34898121Sgshapiro		if (sc->sc_deltay > 127)
34998121Sgshapiro			sc->sc_deltay = 127;
35098121Sgshapiro		if (sc->sc_deltay < -127)
35198121Sgshapiro			sc->sc_deltay = -127;
35298121Sgshapiro		sc->sc_bytes[1] = sc->sc_deltax;
35398121Sgshapiro		sc->sc_bytes[2] = sc->sc_deltay;
35498121Sgshapiro		sc->sc_bytes[3] = sc->sc_bytes[4] = 0;
35598121Sgshapiro		sc->sc_obuttons = sc->sc_buttons;
35698121Sgshapiro		sc->sc_deltax = sc->sc_deltay = 0;
35798121Sgshapiro		sc->sc_bytesread = 0;
35898121Sgshapiro	}
35998121Sgshapiro	splx(s);
36098121Sgshapiro	xfer = min(uio->uio_resid, PROTOBYTES - sc->sc_bytesread);
36198121Sgshapiro	if (error = uiomove(&sc->sc_bytes[sc->sc_bytesread], xfer, uio))
36298121Sgshapiro		return (error);
36398121Sgshapiro	sc->sc_bytesread += xfer;
36498121Sgshapiro	return(0);
36598121Sgshapiro}
36698121Sgshapiro
36798121Sgshapiro/*
36898121Sgshapiro * mseselect: check for mouse input to be processed.
36998121Sgshapiro */
37098121Sgshapirostatic	int
37198121Sgshapiromseselect(dev, rw, p)
37298121Sgshapiro	dev_t dev;
37398121Sgshapiro	int rw;
37498121Sgshapiro	struct proc *p;
37598121Sgshapiro{
37698121Sgshapiro	register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
37798121Sgshapiro	int s;
37898121Sgshapiro
37998121Sgshapiro	s = spltty();
38098121Sgshapiro	if (sc->sc_bytesread != PROTOBYTES || sc->sc_deltax != 0 ||
38198121Sgshapiro	    sc->sc_deltay != 0 || (sc->sc_obuttons ^ sc->sc_buttons) != 0) {
38298121Sgshapiro		splx(s);
38398121Sgshapiro		return (1);
38498121Sgshapiro	}
38594334Sgshapiro
38694334Sgshapiro	/*
38794334Sgshapiro	 * Since this is an exclusive open device, any previous proc.
38894334Sgshapiro	 * pointer is trash now, so we can just assign it.
38994334Sgshapiro	 */
39094334Sgshapiro	selrecord(p, &sc->sc_selp);
39194334Sgshapiro	splx(s);
39294334Sgshapiro	return (0);
39394334Sgshapiro}
39494334Sgshapiro
39594334Sgshapiro/*
39694334Sgshapiro * mseintr: update mouse status. sc_deltax and sc_deltay are accumulative.
39794334Sgshapiro */
39894334Sgshapirovoid
39994334Sgshapiromseintr(unit)
40094334Sgshapiro	int unit;
40194334Sgshapiro{
40294334Sgshapiro	register struct mse_softc *sc = &mse_sc[unit];
40394334Sgshapiro
40494334Sgshapiro#ifdef DEBUG
40594334Sgshapiro	static int mse_intrcnt = 0;
40694334Sgshapiro	if((mse_intrcnt++ % 10000) == 0)
40794334Sgshapiro		printf("mseintr\n");
40894334Sgshapiro#endif /* DEBUG */
40994334Sgshapiro	if ((sc->sc_flags & MSESC_OPEN) == 0)
41094334Sgshapiro		return;
41194334Sgshapiro
41294334Sgshapiro	(*sc->sc_getmouse)(sc->sc_port, &sc->sc_deltax, &sc->sc_deltay, &sc->sc_buttons);
41394334Sgshapiro
41494334Sgshapiro	/*
41594334Sgshapiro	 * If mouse state has changed, wake up anyone wanting to know.
41694334Sgshapiro	 */
41794334Sgshapiro	if (sc->sc_deltax != 0 || sc->sc_deltay != 0 ||
41894334Sgshapiro	    (sc->sc_obuttons ^ sc->sc_buttons) != 0) {
41994334Sgshapiro		if (sc->sc_flags & MSESC_WANT) {
42094334Sgshapiro			sc->sc_flags &= ~MSESC_WANT;
42194334Sgshapiro			wakeup((caddr_t)sc);
42294334Sgshapiro		}
42394334Sgshapiro		selwakeup(&sc->sc_selp);
42494334Sgshapiro	}
42594334Sgshapiro}
42694334Sgshapiro
42794334Sgshapiro/*
42894334Sgshapiro * Routines for the Logitech mouse.
42994334Sgshapiro */
43094334Sgshapiro/*
43194334Sgshapiro * Test for a Logitech bus mouse and return 1 if it is.
43294334Sgshapiro * (until I know how to use the signature port properly, just disable
43394334Sgshapiro *  interrupts and return 1)
43494334Sgshapiro */
43594334Sgshapirostatic int
43694334Sgshapiromse_probelogi(idp)
43794334Sgshapiro	register struct isa_device *idp;
43894334Sgshapiro{
43994334Sgshapiro
44094334Sgshapiro	int sig;
44194334Sgshapiro
44294334Sgshapiro	outb(idp->id_iobase + MSE_PORTD, MSE_SETUP);
44394334Sgshapiro		/* set the signature port */
44494334Sgshapiro	outb(idp->id_iobase + MSE_PORTB, MSE_LOGI_SIG);
44594334Sgshapiro
44694334Sgshapiro	DELAY(30000); /* 30 ms delay */
44794334Sgshapiro	sig = inb(idp->id_iobase + MSE_PORTB) & 0xFF;
44894334Sgshapiro	if (sig == MSE_LOGI_SIG) {
44994334Sgshapiro		outb(idp->id_iobase + MSE_PORTC, MSE_DISINTR);
45094334Sgshapiro		return(1);
45194334Sgshapiro	} else {
45294334Sgshapiro		if (bootverbose)
45394334Sgshapiro			printf("mse%d: wrong signature %x\n",idp->id_unit,sig);
45494334Sgshapiro		return(0);
45594334Sgshapiro	}
45694334Sgshapiro}
45794334Sgshapiro
45894334Sgshapiro/*
45994334Sgshapiro * Initialize Logitech mouse and enable interrupts.
46094334Sgshapiro */
46194334Sgshapirostatic void
46294334Sgshapiromse_enablelogi(port)
46394334Sgshapiro	register u_int port;
46494334Sgshapiro{
46594334Sgshapiro	int dx, dy, but;
46694334Sgshapiro
46794334Sgshapiro	outb(port + MSE_PORTD, MSE_SETUP);
46894334Sgshapiro	mse_getlogi(port, &dx, &dy, &but);
46994334Sgshapiro}
47094334Sgshapiro
47194334Sgshapiro/*
47294334Sgshapiro * Disable interrupts for Logitech mouse.
47394334Sgshapiro */
47494334Sgshapirostatic void
47594334Sgshapiromse_disablelogi(port)
47694334Sgshapiro	register u_int port;
47794334Sgshapiro{
47894334Sgshapiro
47994334Sgshapiro	outb(port + MSE_PORTC, MSE_DISINTR);
48094334Sgshapiro}
48194334Sgshapiro
48294334Sgshapiro/*
48394334Sgshapiro * Get the current dx, dy and button up/down state.
48494334Sgshapiro */
48594334Sgshapirostatic void
48694334Sgshapiromse_getlogi(port, dx, dy, but)
48794334Sgshapiro	register u_int port;
48894334Sgshapiro	int *dx;
48998121Sgshapiro	int *dy;
49094334Sgshapiro	int *but;
49194334Sgshapiro{
49294334Sgshapiro	register char x, y;
49394334Sgshapiro
49494334Sgshapiro	outb(port + MSE_PORTC, MSE_HOLD | MSE_RXLOW);
49594334Sgshapiro	x = inb(port + MSE_PORTA);
49694334Sgshapiro	*but = (x >> 5) & 0x7;
49794334Sgshapiro	x &= 0xf;
49894334Sgshapiro	outb(port + MSE_PORTC, MSE_HOLD | MSE_RXHIGH);
49994334Sgshapiro	x |= (inb(port + MSE_PORTA) << 4);
50094334Sgshapiro	outb(port + MSE_PORTC, MSE_HOLD | MSE_RYLOW);
50194334Sgshapiro	y = (inb(port + MSE_PORTA) & 0xf);
50294334Sgshapiro	outb(port + MSE_PORTC, MSE_HOLD | MSE_RYHIGH);
50394334Sgshapiro	y |= (inb(port + MSE_PORTA) << 4);
50494334Sgshapiro	*dx += x;
50594334Sgshapiro	*dy += y;
50694334Sgshapiro	outb(port + MSE_PORTC, MSE_INTREN);
50794334Sgshapiro}
50894334Sgshapiro
50994334Sgshapiro/*
51094334Sgshapiro * Routines for the ATI Inport bus mouse.
51194334Sgshapiro */
51294334Sgshapiro/*
51394334Sgshapiro * Test for a ATI Inport bus mouse and return 1 if it is.
51494334Sgshapiro * (do not enable interrupts)
51594334Sgshapiro */
51694334Sgshapirostatic int
51794334Sgshapiromse_probeati(idp)
51894334Sgshapiro	register struct isa_device *idp;
51994334Sgshapiro{
52094334Sgshapiro	int i;
52194334Sgshapiro
52294334Sgshapiro	for (i = 0; i < 2; i++)
52394334Sgshapiro		if (inb(idp->id_iobase + MSE_PORTC) == 0xde)
52494334Sgshapiro			return (1);
52594334Sgshapiro	return (0);
52694334Sgshapiro}
52794334Sgshapiro
52894334Sgshapiro/*
52994334Sgshapiro * Initialize ATI Inport mouse and enable interrupts.
53094334Sgshapiro */
53194334Sgshapirostatic void
53294334Sgshapiromse_enableati(port)
53394334Sgshapiro	register u_int port;
53494334Sgshapiro{
53594334Sgshapiro
53694334Sgshapiro	outb(port + MSE_PORTA, MSE_INPORT_RESET);
53794334Sgshapiro	outb(port + MSE_PORTA, MSE_INPORT_MODE);
53898121Sgshapiro	outb(port + MSE_PORTB, MSE_INPORT_INTREN);
53998121Sgshapiro}
54094334Sgshapiro
54194334Sgshapiro/*
54294334Sgshapiro * Disable interrupts for ATI Inport mouse.
54394334Sgshapiro */
54494334Sgshapirostatic void
54594334Sgshapiromse_disableati(port)
54694334Sgshapiro	register u_int port;
54794334Sgshapiro{
54894334Sgshapiro
54994334Sgshapiro	outb(port + MSE_PORTA, MSE_INPORT_MODE);
55094334Sgshapiro	outb(port + MSE_PORTB, 0);
55194334Sgshapiro}
55294334Sgshapiro
55394334Sgshapiro/*
55494334Sgshapiro * Get current dx, dy and up/down button state.
55594334Sgshapiro */
55694334Sgshapirostatic void
55794334Sgshapiromse_getati(port, dx, dy, but)
55894334Sgshapiro	register u_int port;
55994334Sgshapiro	int *dx;
56094334Sgshapiro	int *dy;
56194334Sgshapiro	int *but;
56294334Sgshapiro{
56394334Sgshapiro	register char byte;
56490792Sgshapiro
56590792Sgshapiro	outb(port + MSE_PORTA, MSE_INPORT_MODE);
56690792Sgshapiro	outb(port + MSE_PORTB, MSE_INPORT_HOLD);
56790792Sgshapiro	outb(port + MSE_PORTA, MSE_INPORT_STATUS);
56890792Sgshapiro	*but = ~(inb(port + MSE_PORTB) & 0x7);
56990792Sgshapiro	outb(port + MSE_PORTA, MSE_INPORT_DX);
57090792Sgshapiro	byte = inb(port + MSE_PORTB);
57190792Sgshapiro	*dx += byte;
57290792Sgshapiro	outb(port + MSE_PORTA, MSE_INPORT_DY);
57390792Sgshapiro	byte = inb(port + MSE_PORTB);
57490792Sgshapiro	*dy += byte;
57590792Sgshapiro	outb(port + MSE_PORTA, MSE_INPORT_MODE);
57690792Sgshapiro	outb(port + MSE_PORTB, MSE_INPORT_INTREN);
57790792Sgshapiro}
57890792Sgshapiro
57990792Sgshapirostatic mse_devsw_installed = 0;
58090792Sgshapiro
58190792Sgshapirostatic void 	mse_drvinit(void *unused)
58290792Sgshapiro{
58390792Sgshapiro	dev_t dev;
58490792Sgshapiro
58590792Sgshapiro	if( ! mse_devsw_installed ) {
58690792Sgshapiro		dev = makedev(CDEV_MAJOR, 0);
58790792Sgshapiro		cdevsw_add(&dev,&mse_cdevsw, NULL);
58890792Sgshapiro		mse_devsw_installed = 1;
58990792Sgshapiro    	}
59090792Sgshapiro}
59190792Sgshapiro
59290792SgshapiroSYSINIT(msedev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,mse_drvinit,NULL)
59390792Sgshapiro
59490792Sgshapiro
59590792Sgshapiro#endif /* NMSE */
59690792Sgshapiro