mse.c revision 12521
1285612Sdelphij/*
2258945Sroberto * Copyright 1992 by the University of Guelph
3258945Sroberto *
4285612Sdelphij * Permission to use, copy and modify this
5285612Sdelphij * software and its documentation for any purpose and without
6258945Sroberto * fee is hereby granted, provided that the above copyright
7258945Sroberto * notice appear in all copies and that both that copyright
8258945Sroberto * notice and this permission notice appear in supporting
9258945Sroberto * documentation.
10258945Sroberto * University of Guelph makes no representations about the suitability of
11258945Sroberto * this software for any purpose.  It is provided "as is"
12258945Sroberto * without express or implied warranty.
13258945Sroberto *
14258945Sroberto * $Id: mse.c,v 1.17 1995/11/29 10:47:46 julian Exp $
15258945Sroberto */
16258945Sroberto/*
17258945Sroberto * Driver for the Logitech and ATI Inport Bus mice for use with 386bsd and
18258945Sroberto * the X386 port, courtesy of
19258945Sroberto * Rick Macklem, rick@snowhite.cis.uoguelph.ca
20258945Sroberto * Caveats: The driver currently uses spltty(), but doesn't use any
21258945Sroberto * generic tty code. It could use splmse() (that only masks off the
22258945Sroberto * bus mouse interrupt, but that would require hacking in i386/isa/icu.s.
23285612Sdelphij * (This may be worth the effort, since the Logitech generates 30/60
24285612Sdelphij * interrupts/sec continuously while it is open.)
25285612Sdelphij * NB: The ATI has NOT been tested yet!
26285612Sdelphij */
27285612Sdelphij
28285612Sdelphij/*
29285612Sdelphij * Modification history:
30285612Sdelphij * Sep 6, 1994 -- Lars Fredriksen(fredriks@mcs.com)
31285612Sdelphij *   improved probe based on input from Logitech.
32285612Sdelphij *
33285612Sdelphij * Oct 19, 1992 -- E. Stark (stark@cs.sunysb.edu)
34285612Sdelphij *   fixes to make it work with Microsoft InPort busmouse
35285612Sdelphij *
36285612Sdelphij * Jan, 1993 -- E. Stark (stark@cs.sunysb.edu)
37285612Sdelphij *   added patches for new "select" interface
38285612Sdelphij *
39285612Sdelphij * May 4, 1993 -- E. Stark (stark@cs.sunysb.edu)
40285612Sdelphij *   changed position of some spl()'s in mseread
41285612Sdelphij *
42285612Sdelphij * October 8, 1993 -- E. Stark (stark@cs.sunysb.edu)
43285612Sdelphij *   limit maximum negative x/y value to -127 to work around XFree problem
44285612Sdelphij *   that causes spurious button pushes.
45285612Sdelphij */
46285612Sdelphij
47285612Sdelphij#include "mse.h"
48285612Sdelphij#if NMSE > 0
49285612Sdelphij#include <sys/param.h>
50285612Sdelphij#include <sys/systm.h>
51285612Sdelphij#include <sys/proc.h>
52285612Sdelphij#include <sys/user.h>
53285612Sdelphij#include <sys/buf.h>
54285612Sdelphij#include <sys/kernel.h>
55285612Sdelphij#include <sys/ioctl.h>
56285612Sdelphij#include <sys/uio.h>
57285612Sdelphij#include <sys/devconf.h>
58285612Sdelphij
59285612Sdelphij#include <machine/clock.h>
60285612Sdelphij
61285612Sdelphij#include <i386/isa/isa_device.h>
62285612Sdelphij#include <i386/isa/icu.h>
63285612Sdelphij
64285612Sdelphij#ifdef JREMOD
65285612Sdelphij#include <sys/conf.h>
66285612Sdelphij#include <sys/kernel.h>
67285612Sdelphij#ifdef DEVFS
68285612Sdelphij#include <sys/devfsext.h>
69285612Sdelphij#endif /*DEVFS*/
70285612Sdelphij#define CDEV_MAJOR 27
71285612Sdelphij#endif /*JREMOD*/
72285612Sdelphij
73285612Sdelphijstatic int mseprobe(struct isa_device *);
74285612Sdelphijstatic int mseattach(struct isa_device *);
75285612Sdelphij
76285612Sdelphijstruct	isa_driver msedriver = {
77285612Sdelphij	mseprobe, mseattach, "mse"
78258945Sroberto};
79258945Sroberto
80258945Sroberto/*
81258945Sroberto * Software control structure for mouse. The sc_enablemouse(),
82258945Sroberto * sc_disablemouse() and sc_getmouse() routines must be called spl'd().
83258945Sroberto */
84258945Sroberto#define	PROTOBYTES	5
85258945Srobertostruct mse_softc {
86258945Sroberto	int	sc_flags;
87258945Sroberto	int	sc_mousetype;
88258945Sroberto	struct	selinfo sc_selp;
89258945Sroberto	u_int	sc_port;
90258945Sroberto	void	(*sc_enablemouse)();
91258945Sroberto	void	(*sc_disablemouse)();
92258945Sroberto	void	(*sc_getmouse)();
93258945Sroberto	int	sc_deltax;
94258945Sroberto	int	sc_deltay;
95258945Sroberto	int	sc_obuttons;
96258945Sroberto	int	sc_buttons;
97258945Sroberto	int	sc_bytesread;
98258945Sroberto	u_char	sc_bytes[PROTOBYTES];
99258945Sroberto} mse_sc[NMSE];
100280849Scy
101285612Sdelphij/* Flags */
102280849Scy#define	MSESC_OPEN	0x1
103280849Scy#define	MSESC_WANT	0x2
104280849Scy
105280849Scy/* and Mouse Types */
106280849Scy#define	MSE_LOGITECH	0x1
107280849Scy#define	MSE_ATIINPORT	0x2
108280849Scy#define	MSE_LOGI_SIG	0xA5
109280849Scy
110280849Scy#define	MSE_PORTA	0
111280849Scy#define	MSE_PORTB	1
112280849Scy#define	MSE_PORTC	2
113280849Scy#define	MSE_PORTD	3
114280849Scy
115280849Scy#define	MSE_UNIT(dev)		(minor(dev) >> 1)
116280849Scy#define	MSE_NBLOCKIO(dev)	(minor(dev) & 0x1)
117316722Sdelphij
118280849Scy/*
119280849Scy * Logitech bus mouse definitions
120280849Scy */
121280849Scy#define	MSE_SETUP	0x91	/* What does this mean? */
122280849Scy				/* The definition for the control port */
123280849Scy				/* is as follows: */
124280849Scy
125280849Scy				/* D7 	 =  Mode set flag (1 = active) 	*/
126289997Sglebius				/* D6,D5 =  Mode selection (port A) 	*/
127280849Scy				/* 	    00 = Mode 0 = Basic I/O 	*/
128280849Scy				/* 	    01 = Mode 1 = Strobed I/O 	*/
129280849Scy				/* 	    10 = Mode 2 = Bi-dir bus 	*/
130285612Sdelphij				/* D4	 =  Port A direction (1 = input)*/
131280849Scy				/* D3	 =  Port C (upper 4 bits) 	*/
132280849Scy				/*	    direction. (1 = input)	*/
133285612Sdelphij				/* D2	 =  Mode selection (port B & C) */
134285612Sdelphij				/*	    0 = Mode 0 = Basic I/O	*/
135280849Scy				/*	    1 = Mode 1 = Strobed I/O	*/
136280849Scy				/* D1	 =  Port B direction (1 = input)*/
137280849Scy				/* D0	 =  Port C (lower 4 bits)	*/
138258945Sroberto				/*	    direction. (1 = input)	*/
139258945Sroberto
140285612Sdelphij				/* So 91 means Basic I/O on all 3 ports,*/
141258945Sroberto				/* Port A is an input port, B is an 	*/
142258945Sroberto				/* output port, C is split with upper	*/
143258945Sroberto				/* 4 bits being an output port and lower*/
144258945Sroberto				/* 4 bits an input port, and enable the */
145280849Scy				/* sucker.				*/
146280849Scy				/* Courtesy Intel 8255 databook. Lars   */
147280849Scy#define	MSE_HOLD	0x80
148280849Scy#define	MSE_RXLOW	0x00
149258945Sroberto#define	MSE_RXHIGH	0x20
150258945Sroberto#define	MSE_RYLOW	0x40
151258945Sroberto#define	MSE_RYHIGH	0x60
152258945Sroberto#define	MSE_DISINTR	0x10
153258945Sroberto#define MSE_INTREN	0x00
154258945Sroberto
155280849Scystatic int mse_probelogi();
156280849Scystatic void mse_enablelogi(), mse_disablelogi(), mse_getlogi();
157280849Scy
158285612Sdelphij/*
159285612Sdelphij * ATI Inport mouse definitions
160280849Scy */
161285612Sdelphij#define	MSE_INPORT_RESET	0x80
162285612Sdelphij#define	MSE_INPORT_STATUS	0x00
163285612Sdelphij#define	MSE_INPORT_DX		0x01
164285612Sdelphij#define	MSE_INPORT_DY		0x02
165285612Sdelphij#define	MSE_INPORT_MODE		0x07
166285612Sdelphij#define	MSE_INPORT_HOLD		0x20
167285612Sdelphij#define	MSE_INPORT_INTREN	0x09
168285612Sdelphij
169285612Sdelphijstatic int mse_probeati();
170285612Sdelphijstatic void mse_enableati(), mse_disableati(), mse_getati();
171285612Sdelphij
172285612Sdelphij#define	MSEPRI	(PZERO + 3)
173285612Sdelphij
174258945Sroberto/*
175280849Scy * Table of mouse types.
176258945Sroberto * Keep the Logitech last, since I haven't figured out how to probe it
177258945Sroberto * properly yet. (Someday I'll have the documentation.)
178258945Sroberto */
179258945Srobertostruct mse_types {
180280849Scy	int	m_type;		/* Type of bus mouse */
181280849Scy	int	(*m_probe)();	/* Probe routine to test for it */
182280849Scy	void	(*m_enable)();	/* Start routine */
183280849Scy	void	(*m_disable)();	/* Disable interrupts routine */
184285612Sdelphij	void	(*m_get)();	/* and get mouse status */
185285612Sdelphij} mse_types[] = {
186285612Sdelphij	{ MSE_ATIINPORT, mse_probeati, mse_enableati, mse_disableati, mse_getati },
187285612Sdelphij	{ MSE_LOGITECH, mse_probelogi, mse_enablelogi, mse_disablelogi, mse_getlogi },
188258945Sroberto	{ 0, },
189280849Scy};
190280849Scy
191280849Scystatic struct kern_devconf kdc_mse[NMSE] = { {
192285612Sdelphij	0, 0, 0,		/* filled in by dev_attach */
193285612Sdelphij	"mse", 0, { MDDT_ISA, 0, "tty" },
194285612Sdelphij	isa_generic_externalize, 0, 0, ISA_EXTERNALLEN,
195285612Sdelphij	&kdc_isa0,		/* parent */
196258945Sroberto	0,			/* parentdata */
197258945Sroberto	DC_UNCONFIGURED,	/* state */
198285612Sdelphij	"ATI or Logitech bus mouse adapter",
199285612Sdelphij	DC_CLS_MISC		/* class */
200285612Sdelphij} };
201285612Sdelphij
202285612Sdelphijstatic inline void
203258945Srobertomse_registerdev(struct isa_device *id)
204258945Sroberto{
205258945Sroberto	if(id->id_unit)
206258945Sroberto		kdc_mse[id->id_unit] = kdc_mse[0];
207258945Sroberto	kdc_mse[id->id_unit].kdc_unit = id->id_unit;
208258945Sroberto	kdc_mse[id->id_unit].kdc_isa = id;
209258945Sroberto	dev_attach(&kdc_mse[id->id_unit]);
210258945Sroberto}
211258945Sroberto
212258945Srobertoint
213258945Srobertomseprobe(idp)
214258945Sroberto	register struct isa_device *idp;
215258945Sroberto{
216258945Sroberto	register struct mse_softc *sc = &mse_sc[idp->id_unit];
217258945Sroberto	register int i;
218258945Sroberto
219258945Sroberto	mse_registerdev(idp);
220258945Sroberto	/*
221258945Sroberto	 * Check for each mouse type in the table.
222258945Sroberto	 */
223258945Sroberto	i = 0;
224285612Sdelphij	while (mse_types[i].m_type) {
225285612Sdelphij		if ((*mse_types[i].m_probe)(idp)) {
226285612Sdelphij			sc->sc_mousetype = mse_types[i].m_type;
227285612Sdelphij			sc->sc_enablemouse = mse_types[i].m_enable;
228285612Sdelphij			sc->sc_disablemouse = mse_types[i].m_disable;
229285612Sdelphij			sc->sc_getmouse = mse_types[i].m_get;
230258945Sroberto			return (1);
231280849Scy		}
232258945Sroberto		i++;
233280849Scy	}
234280849Scy	return (0);
235285612Sdelphij}
236285612Sdelphij
237285612Sdelphijint
238285612Sdelphijmseattach(idp)
239285612Sdelphij	struct isa_device *idp;
240285612Sdelphij{
241285612Sdelphij	struct mse_softc *sc = &mse_sc[idp->id_unit];
242285612Sdelphij
243285612Sdelphij	sc->sc_port = idp->id_iobase;
244285612Sdelphij	kdc_mse[idp->id_unit].kdc_state = DC_IDLE;
245285612Sdelphij	return (1);
246285612Sdelphij}
247285612Sdelphij
248285612Sdelphij/*
249285612Sdelphij * Exclusive open the mouse, initialize it and enable interrupts.
250285612Sdelphij */
251285612Sdelphijint
252258945Srobertomseopen(dev, flags, fmt, p)
253258945Sroberto	dev_t dev;
254285612Sdelphij	int flags;
255285612Sdelphij	int fmt;
256285612Sdelphij	struct proc *p;
257285612Sdelphij{
258258945Sroberto	register struct mse_softc *sc;
259258945Sroberto	int s;
260280849Scy
261258945Sroberto	if (MSE_UNIT(dev) >= NMSE)
262280849Scy		return (ENXIO);
263258945Sroberto	sc = &mse_sc[MSE_UNIT(dev)];
264258945Sroberto	if (sc->sc_flags & MSESC_OPEN)
265258945Sroberto		return (EBUSY);
266258945Sroberto	sc->sc_flags |= MSESC_OPEN;
267258945Sroberto	kdc_mse[MSE_UNIT(dev)].kdc_state = DC_BUSY;
268289997Sglebius	sc->sc_obuttons = sc->sc_buttons = 0x7;
269280849Scy	sc->sc_deltax = sc->sc_deltay = 0;
270280849Scy	sc->sc_bytesread = PROTOBYTES;
271280849Scy
272280849Scy	/*
273280849Scy	 * Initialize mouse interface and enable interrupts.
274258945Sroberto	 */
275258945Sroberto	s = spltty();
276258945Sroberto	(*sc->sc_enablemouse)(sc->sc_port);
277289997Sglebius	splx(s);
278280849Scy	return (0);
279258945Sroberto}
280280849Scy
281258945Sroberto/*
282258945Sroberto * mseclose: just turn off mouse innterrupts.
283280849Scy */
284280849Scyint
285258945Srobertomseclose(dev, flags, fmt, p)
286258945Sroberto	dev_t dev;
287258945Sroberto	int flags;
288258945Sroberto	int fmt;
289258945Sroberto	struct proc *p;
290258945Sroberto{
291258945Sroberto	struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
292258945Sroberto	int s;
293258945Sroberto
294258945Sroberto	s = spltty();
295258945Sroberto	(*sc->sc_disablemouse)(sc->sc_port);
296258945Sroberto	sc->sc_flags &= ~MSESC_OPEN;
297258945Sroberto	kdc_mse[MSE_UNIT(dev)].kdc_state = DC_IDLE;
298258945Sroberto	splx(s);
299258945Sroberto	return(0);
300280849Scy}
301280849Scy
302280849Scy/*
303280849Scy * mseread: return mouse info using the MSC serial protocol, but without
304280849Scy * using bytes 4 and 5.
305258945Sroberto * (Yes this is cheesy, but it makes the X386 server happy, so...)
306285612Sdelphij */
307280849Scyint
308280849Scymseread(dev, uio, ioflag)
309258945Sroberto	dev_t dev;
310258945Sroberto	struct uio *uio;
311258945Sroberto	int ioflag;
312258945Sroberto{
313258945Sroberto	register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
314258945Sroberto	int xfer, s, error;
315280849Scy
316280849Scy	/*
317280849Scy	 * If there are no protocol bytes to be read, set up a new protocol
318280849Scy	 * packet.
319280849Scy	 */
320258945Sroberto	s = spltty(); /* XXX Should be its own spl, but where is imlXX() */
321280849Scy	if (sc->sc_bytesread >= PROTOBYTES) {
322280849Scy		while (sc->sc_deltax == 0 && sc->sc_deltay == 0 &&
323280849Scy		       (sc->sc_obuttons ^ sc->sc_buttons) == 0) {
324258945Sroberto			if (MSE_NBLOCKIO(dev)) {
325258945Sroberto				splx(s);
326258945Sroberto				return (0);
327258945Sroberto			}
328258945Sroberto			sc->sc_flags |= MSESC_WANT;
329258945Sroberto			if (error = tsleep((caddr_t)sc, MSEPRI | PCATCH,
330258945Sroberto				"mseread", 0)) {
331280849Scy				splx(s);
332258945Sroberto				return (error);
333258945Sroberto			}
334258945Sroberto		}
335289997Sglebius
336258945Sroberto		/*
337316722Sdelphij		 * Generate protocol bytes.
338258945Sroberto		 * For some reason X386 expects 5 bytes but never uses
339258945Sroberto		 * the fourth or fifth?
340258945Sroberto		 */
341258945Sroberto		sc->sc_bytes[0] = 0x80 | (sc->sc_buttons & ~0xf8);
342258945Sroberto		if (sc->sc_deltax > 127)
343258945Sroberto			sc->sc_deltax = 127;
344258945Sroberto		if (sc->sc_deltax < -127)
345258945Sroberto			sc->sc_deltax = -127;
346258945Sroberto		sc->sc_deltay = -sc->sc_deltay;	/* Otherwise mousey goes wrong way */
347258945Sroberto		if (sc->sc_deltay > 127)
348258945Sroberto			sc->sc_deltay = 127;
349258945Sroberto		if (sc->sc_deltay < -127)
350258945Sroberto			sc->sc_deltay = -127;
351258945Sroberto		sc->sc_bytes[1] = sc->sc_deltax;
352280849Scy		sc->sc_bytes[2] = sc->sc_deltay;
353258945Sroberto		sc->sc_bytes[3] = sc->sc_bytes[4] = 0;
354258945Sroberto		sc->sc_obuttons = sc->sc_buttons;
355258945Sroberto		sc->sc_deltax = sc->sc_deltay = 0;
356280849Scy		sc->sc_bytesread = 0;
357280849Scy	}
358280849Scy	splx(s);
359280849Scy	xfer = min(uio->uio_resid, PROTOBYTES - sc->sc_bytesread);
360280849Scy	if (error = uiomove(&sc->sc_bytes[sc->sc_bytesread], xfer, uio))
361280849Scy		return (error);
362280849Scy	sc->sc_bytesread += xfer;
363280849Scy	return(0);
364280849Scy}
365280849Scy
366280849Scy/*
367280849Scy * mseselect: check for mouse input to be processed.
368280849Scy */
369280849Scyint
370280849Scymseselect(dev, rw, p)
371280849Scy	dev_t dev;
372280849Scy	int rw;
373280849Scy	struct proc *p;
374280849Scy{
375280849Scy	register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
376280849Scy	int s;
377280849Scy
378280849Scy	s = spltty();
379280849Scy	if (sc->sc_bytesread != PROTOBYTES || sc->sc_deltax != 0 ||
380280849Scy	    sc->sc_deltay != 0 || (sc->sc_obuttons ^ sc->sc_buttons) != 0) {
381280849Scy		splx(s);
382280849Scy		return (1);
383280849Scy	}
384280849Scy
385280849Scy	/*
386280849Scy	 * Since this is an exclusive open device, any previous proc.
387280849Scy	 * pointer is trash now, so we can just assign it.
388280849Scy	 */
389280849Scy	selrecord(p, &sc->sc_selp);
390280849Scy	splx(s);
391280849Scy	return (0);
392280849Scy}
393280849Scy
394280849Scy/*
395280849Scy * mseintr: update mouse status. sc_deltax and sc_deltay are accumulative.
396280849Scy */
397280849Scyvoid
398280849Scymseintr(unit)
399280849Scy	int unit;
400280849Scy{
401316722Sdelphij	register struct mse_softc *sc = &mse_sc[unit];
402316722Sdelphij	pid_t p;
403316722Sdelphij
404280849Scy#ifdef DEBUG
405280849Scy	static int mse_intrcnt = 0;
406280849Scy	if((mse_intrcnt++ % 10000) == 0)
407280849Scy		printf("mseintr\n");
408280849Scy#endif /* DEBUG */
409280849Scy	if ((sc->sc_flags & MSESC_OPEN) == 0)
410280849Scy		return;
411280849Scy
412280849Scy	(*sc->sc_getmouse)(sc->sc_port, &sc->sc_deltax, &sc->sc_deltay, &sc->sc_buttons);
413280849Scy
414280849Scy	/*
415258945Sroberto	 * If mouse state has changed, wake up anyone wanting to know.
416258945Sroberto	 */
417258945Sroberto	if (sc->sc_deltax != 0 || sc->sc_deltay != 0 ||
418258945Sroberto	    (sc->sc_obuttons ^ sc->sc_buttons) != 0) {
419258945Sroberto		if (sc->sc_flags & MSESC_WANT) {
420258945Sroberto			sc->sc_flags &= ~MSESC_WANT;
421258945Sroberto			wakeup((caddr_t)sc);
422258945Sroberto		}
423258945Sroberto		selwakeup(&sc->sc_selp);
424258945Sroberto	}
425258945Sroberto}
426258945Sroberto
427258945Sroberto/*
428285612Sdelphij * Routines for the Logitech mouse.
429258945Sroberto */
430258945Sroberto/*
431280849Scy * Test for a Logitech bus mouse and return 1 if it is.
432280849Scy * (until I know how to use the signature port properly, just disable
433258945Sroberto *  interrupts and return 1)
434258945Sroberto */
435280849Scystatic int
436258945Srobertomse_probelogi(idp)
437258945Sroberto	register struct isa_device *idp;
438258945Sroberto{
439258945Sroberto
440258945Sroberto	int sig;
441258945Sroberto
442258945Sroberto	outb(idp->id_iobase + MSE_PORTD, MSE_SETUP);
443280849Scy		/* set the signature port */
444280849Scy	outb(idp->id_iobase + MSE_PORTB, MSE_LOGI_SIG);
445280849Scy
446280849Scy	DELAY(30000); /* 30 ms delay */
447280849Scy	sig = inb(idp->id_iobase + MSE_PORTB) & 0xFF;
448280849Scy	if (sig == MSE_LOGI_SIG) {
449280849Scy		outb(idp->id_iobase + MSE_PORTC, MSE_DISINTR);
450258945Sroberto		return(1);
451258945Sroberto	} else {
452280849Scy		printf("mse%d: wrong signature %x\n",idp->id_unit,sig);
453280849Scy		return(0);
454280849Scy	}
455280849Scy}
456280849Scy
457280849Scy/*
458280849Scy * Initialize Logitech mouse and enable interrupts.
459280849Scy */
460280849Scystatic void
461280849Scymse_enablelogi(port)
462285612Sdelphij	register u_int port;
463285612Sdelphij{
464285612Sdelphij	int dx, dy, but;
465285612Sdelphij
466285612Sdelphij	outb(port + MSE_PORTD, MSE_SETUP);
467258945Sroberto	mse_getlogi(port, &dx, &dy, &but);
468280849Scy}
469258945Sroberto
470258945Sroberto/*
471258945Sroberto * Disable interrupts for Logitech mouse.
472258945Sroberto */
473258945Srobertostatic void
474258945Srobertomse_disablelogi(port)
475258945Sroberto	register u_int port;
476258945Sroberto{
477258945Sroberto
478258945Sroberto	outb(port + MSE_PORTC, MSE_DISINTR);
479258945Sroberto}
480258945Sroberto
481258945Sroberto/*
482258945Sroberto * Get the current dx, dy and button up/down state.
483258945Sroberto */
484258945Srobertostatic void
485258945Srobertomse_getlogi(port, dx, dy, but)
486258945Sroberto	register u_int port;
487258945Sroberto	int *dx;
488258945Sroberto	int *dy;
489258945Sroberto	int *but;
490258945Sroberto{
491258945Sroberto	register char x, y;
492258945Sroberto
493258945Sroberto	outb(port + MSE_PORTC, MSE_HOLD | MSE_RXLOW);
494258945Sroberto	x = inb(port + MSE_PORTA);
495258945Sroberto	*but = (x >> 5) & 0x7;
496258945Sroberto	x &= 0xf;
497258945Sroberto	outb(port + MSE_PORTC, MSE_HOLD | MSE_RXHIGH);
498258945Sroberto	x |= (inb(port + MSE_PORTA) << 4);
499258945Sroberto	outb(port + MSE_PORTC, MSE_HOLD | MSE_RYLOW);
500258945Sroberto	y = (inb(port + MSE_PORTA) & 0xf);
501258945Sroberto	outb(port + MSE_PORTC, MSE_HOLD | MSE_RYHIGH);
502258945Sroberto	y |= (inb(port + MSE_PORTA) << 4);
503258945Sroberto	*dx += x;
504258945Sroberto	*dy += y;
505258945Sroberto	outb(port + MSE_PORTC, MSE_INTREN);
506258945Sroberto}
507258945Sroberto
508258945Sroberto/*
509258945Sroberto * Routines for the ATI Inport bus mouse.
510258945Sroberto */
511258945Sroberto/*
512258945Sroberto * Test for a ATI Inport bus mouse and return 1 if it is.
513258945Sroberto * (do not enable interrupts)
514258945Sroberto */
515258945Srobertostatic int
516258945Srobertomse_probeati(idp)
517258945Sroberto	register struct isa_device *idp;
518258945Sroberto{
519258945Sroberto	int i;
520258945Sroberto
521258945Sroberto	for (i = 0; i < 2; i++)
522258945Sroberto		if (inb(idp->id_iobase + MSE_PORTC) == 0xde)
523258945Sroberto			return (1);
524258945Sroberto	return (0);
525280849Scy}
526280849Scy
527280849Scy/*
528258945Sroberto * Initialize ATI Inport mouse and enable interrupts.
529258945Sroberto */
530258945Srobertostatic void
531258945Srobertomse_enableati(port)
532258945Sroberto	register u_int port;
533280849Scy{
534280849Scy
535280849Scy	outb(port + MSE_PORTA, MSE_INPORT_RESET);
536316722Sdelphij	outb(port + MSE_PORTA, MSE_INPORT_MODE);
537280849Scy	outb(port + MSE_PORTB, MSE_INPORT_INTREN);
538316722Sdelphij}
539316722Sdelphij
540280849Scy/*
541280849Scy * Disable interrupts for ATI Inport mouse.
542280849Scy */
543280849Scystatic void
544280849Scymse_disableati(port)
545280849Scy	register u_int port;
546280849Scy{
547280849Scy
548280849Scy	outb(port + MSE_PORTA, MSE_INPORT_MODE);
549280849Scy	outb(port + MSE_PORTB, 0);
550280849Scy}
551280849Scy
552258945Sroberto/*
553280849Scy * Get current dx, dy and up/down button state.
554280849Scy */
555280849Scystatic void
556280849Scymse_getati(port, dx, dy, but)
557280849Scy	register u_int port;
558280849Scy	int *dx;
559280849Scy	int *dy;
560258945Sroberto	int *but;
561280849Scy{
562280849Scy	register char byte;
563280849Scy
564280849Scy	outb(port + MSE_PORTA, MSE_INPORT_MODE);
565280849Scy	outb(port + MSE_PORTB, MSE_INPORT_HOLD);
566280849Scy	outb(port + MSE_PORTA, MSE_INPORT_STATUS);
567258945Sroberto	*but = ~(inb(port + MSE_PORTB) & 0x7);
568280849Scy	outb(port + MSE_PORTA, MSE_INPORT_DX);
569280849Scy	byte = inb(port + MSE_PORTB);
570280849Scy	*dx += byte;
571280849Scy	outb(port + MSE_PORTA, MSE_INPORT_DY);
572280849Scy	byte = inb(port + MSE_PORTB);
573258945Sroberto	*dy += byte;
574280849Scy	outb(port + MSE_PORTA, MSE_INPORT_MODE);
575280849Scy	outb(port + MSE_PORTB, MSE_INPORT_INTREN);
576280849Scy}
577280849Scy
578280849Scy#ifdef JREMOD
579280849Scystruct cdevsw mse_cdevsw =
580280849Scy	{ mseopen,	mseclose,	mseread,	nowrite,	/*27*/
581280849Scy	  noioc,	nostop,		nullreset,	nodevtotty,/* mse */
582258945Sroberto	  mseselect,	nommap,		NULL };
583280849Scy
584280849Scystatic mse_devsw_installed = 0;
585280849Scy
586258945Srobertostatic void 	mse_drvinit(void *unused)
587258945Sroberto{
588258945Sroberto	dev_t dev;
589258945Sroberto
590258945Sroberto	if( ! mse_devsw_installed ) {
591280849Scy		dev = makedev(CDEV_MAJOR,0);
592258945Sroberto		cdevsw_add(&dev,&mse_cdevsw,NULL);
593258945Sroberto		mse_devsw_installed = 1;
594258945Sroberto#ifdef DEVFS
595258945Sroberto		{
596258945Sroberto			int x;
597258945Sroberto/* default for a simple device with no probe routine (usually delete this) */
598258945Sroberto			x=devfs_add_devsw(
599258945Sroberto/*	path	name	devsw		minor	type   uid gid perm*/
600258945Sroberto	"/",	"mse",	major(dev),	0,	DV_CHR,	0,  0, 0600);
601258945Sroberto		}
602258945Sroberto#endif
603258945Sroberto    	}
604258945Sroberto}
605258945Sroberto
606258945SrobertoSYSINIT(msedev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,mse_drvinit,NULL)
607258945Sroberto
608258945Sroberto#endif /* JREMOD */
609258945Sroberto
610258945Sroberto#endif /* NMSE */
611285612Sdelphij