mse.c revision 29368
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 *
1429368Speter * $Id: mse.c,v 1.33 1997/07/20 14:10:06 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
492056Swollman#include <sys/param.h>
503745Swollman#include <sys/systm.h>
5112658Sbde#include <sys/conf.h>
522056Swollman#include <sys/proc.h>
532056Swollman#include <sys/kernel.h>
5429368Speter#include <sys/poll.h>
552056Swollman#include <sys/uio.h>
5612675Sjulian#ifdef DEVFS
5712675Sjulian#include <sys/devfsext.h>
5812675Sjulian#endif /*DEVFS*/
59637Snate
607430Sbde#include <machine/clock.h>
617430Sbde
622056Swollman#include <i386/isa/isa_device.h>
63637Snate
64798Swollmanstatic int mseprobe(struct isa_device *);
65798Swollmanstatic int mseattach(struct isa_device *);
66637Snate
67637Snatestruct	isa_driver msedriver = {
68637Snate	mseprobe, mseattach, "mse"
69637Snate};
70637Snate
7112675Sjulianstatic	d_open_t	mseopen;
7212675Sjulianstatic	d_close_t	mseclose;
7312675Sjulianstatic	d_read_t	mseread;
7429368Speterstatic	d_poll_t	msepoll;
7512675Sjulian
7612675Sjulian#define CDEV_MAJOR 27
7712678Sphkstatic struct cdevsw mse_cdevsw =
7812675Sjulian	{ mseopen,	mseclose,	mseread,	nowrite,	/*27*/
7912675Sjulian	  noioc,	nostop,		nullreset,	nodevtotty,/* mse */
8029368Speter	  msepoll,	nommap,		NULL,	"mse",	NULL,	-1 };
8112675Sjulian
8212675Sjulian
83637Snate/*
84637Snate * Software control structure for mouse. The sc_enablemouse(),
85637Snate * sc_disablemouse() and sc_getmouse() routines must be called spl'd().
86637Snate */
87637Snate#define	PROTOBYTES	5
8812724Sphkstatic struct mse_softc {
89637Snate	int	sc_flags;
90637Snate	int	sc_mousetype;
911549Srgrimes	struct	selinfo sc_selp;
92637Snate	u_int	sc_port;
9312854Sbde	void	(*sc_enablemouse) __P((u_int port));
9412854Sbde	void	(*sc_disablemouse) __P((u_int port));
9512854Sbde	void	(*sc_getmouse) __P((u_int port, int *dx, int *dy, int *but));
96637Snate	int	sc_deltax;
97637Snate	int	sc_deltay;
98637Snate	int	sc_obuttons;
99637Snate	int	sc_buttons;
100637Snate	int	sc_bytesread;
101637Snate	u_char	sc_bytes[PROTOBYTES];
10212675Sjulian#ifdef DEVFS
10312675Sjulian	void 	*devfs_token;
10412675Sjulian	void	*n_devfs_token;
10512675Sjulian#endif
106637Snate} mse_sc[NMSE];
107637Snate
108637Snate/* Flags */
109637Snate#define	MSESC_OPEN	0x1
110637Snate#define	MSESC_WANT	0x2
111637Snate
112637Snate/* and Mouse Types */
11320688Sjoerg#define	MSE_NONE	0	/* don't move this! */
114637Snate#define	MSE_LOGITECH	0x1
115637Snate#define	MSE_ATIINPORT	0x2
1164259Sjkh#define	MSE_LOGI_SIG	0xA5
117637Snate
118637Snate#define	MSE_PORTA	0
119637Snate#define	MSE_PORTB	1
120637Snate#define	MSE_PORTC	2
121637Snate#define	MSE_PORTD	3
122637Snate
123637Snate#define	MSE_UNIT(dev)		(minor(dev) >> 1)
124637Snate#define	MSE_NBLOCKIO(dev)	(minor(dev) & 0x1)
125637Snate
126637Snate/*
127637Snate * Logitech bus mouse definitions
128637Snate */
129637Snate#define	MSE_SETUP	0x91	/* What does this mean? */
1304259Sjkh				/* The definition for the control port */
1314259Sjkh				/* is as follows: */
1328876Srgrimes
1334259Sjkh				/* D7 	 =  Mode set flag (1 = active) 	*/
1348876Srgrimes				/* D6,D5 =  Mode selection (port A) 	*/
1354259Sjkh				/* 	    00 = Mode 0 = Basic I/O 	*/
1364259Sjkh				/* 	    01 = Mode 1 = Strobed I/O 	*/
1374259Sjkh				/* 	    10 = Mode 2 = Bi-dir bus 	*/
1384259Sjkh				/* D4	 =  Port A direction (1 = input)*/
1394259Sjkh				/* D3	 =  Port C (upper 4 bits) 	*/
1404259Sjkh				/*	    direction. (1 = input)	*/
1414259Sjkh				/* D2	 =  Mode selection (port B & C) */
1424259Sjkh				/*	    0 = Mode 0 = Basic I/O	*/
1434259Sjkh				/*	    1 = Mode 1 = Strobed I/O	*/
1444259Sjkh				/* D1	 =  Port B direction (1 = input)*/
1454259Sjkh				/* D0	 =  Port C (lower 4 bits)	*/
1464259Sjkh				/*	    direction. (1 = input)	*/
1478876Srgrimes
1484259Sjkh				/* So 91 means Basic I/O on all 3 ports,*/
1494259Sjkh				/* Port A is an input port, B is an 	*/
1504259Sjkh				/* output port, C is split with upper	*/
1514259Sjkh				/* 4 bits being an output port and lower*/
1524259Sjkh				/* 4 bits an input port, and enable the */
1534259Sjkh				/* sucker.				*/
1544259Sjkh				/* Courtesy Intel 8255 databook. Lars   */
155637Snate#define	MSE_HOLD	0x80
156637Snate#define	MSE_RXLOW	0x00
157637Snate#define	MSE_RXHIGH	0x20
158637Snate#define	MSE_RYLOW	0x40
159637Snate#define	MSE_RYHIGH	0x60
160637Snate#define	MSE_DISINTR	0x10
161637Snate#define MSE_INTREN	0x00
162637Snate
16312854Sbdestatic int mse_probelogi __P((struct isa_device *idp));
16412854Sbdestatic void mse_disablelogi __P((u_int port));
16512854Sbdestatic void mse_getlogi __P((u_int port, int *dx, int *dy, int *but));
16612854Sbdestatic void mse_enablelogi __P((u_int port));
167637Snate
168637Snate/*
169637Snate * ATI Inport mouse definitions
170637Snate */
171637Snate#define	MSE_INPORT_RESET	0x80
172637Snate#define	MSE_INPORT_STATUS	0x00
173637Snate#define	MSE_INPORT_DX		0x01
174637Snate#define	MSE_INPORT_DY		0x02
175637Snate#define	MSE_INPORT_MODE		0x07
176637Snate#define	MSE_INPORT_HOLD		0x20
177637Snate#define	MSE_INPORT_INTREN	0x09
178637Snate
17912854Sbdestatic int mse_probeati __P((struct isa_device *idp));
18012854Sbdestatic void mse_enableati __P((u_int port));
18112854Sbdestatic void mse_disableati __P((u_int port));
18212854Sbdestatic void mse_getati __P((u_int port, int *dx, int *dy, int *but));
183637Snate
184637Snate#define	MSEPRI	(PZERO + 3)
185637Snate
186637Snate/*
187637Snate * Table of mouse types.
188637Snate * Keep the Logitech last, since I haven't figured out how to probe it
189637Snate * properly yet. (Someday I'll have the documentation.)
190637Snate */
19112724Sphkstatic struct mse_types {
192637Snate	int	m_type;		/* Type of bus mouse */
19312854Sbde	int	(*m_probe) __P((struct isa_device *idp));
19412854Sbde				/* Probe routine to test for it */
19512854Sbde	void	(*m_enable) __P((u_int port));
19612854Sbde				/* Start routine */
19712854Sbde	void	(*m_disable) __P((u_int port));
19812854Sbde				/* Disable interrupts routine */
19912854Sbde	void	(*m_get) __P((u_int port, int *dx, int *dy, int *but));
20012854Sbde				/* and get mouse status */
201637Snate} mse_types[] = {
202637Snate	{ MSE_ATIINPORT, mse_probeati, mse_enableati, mse_disableati, mse_getati },
203637Snate	{ MSE_LOGITECH, mse_probelogi, mse_enablelogi, mse_disablelogi, mse_getlogi },
204637Snate	{ 0, },
205637Snate};
206637Snate
207798Swollmanint
208637Snatemseprobe(idp)
209637Snate	register struct isa_device *idp;
210637Snate{
211637Snate	register struct mse_softc *sc = &mse_sc[idp->id_unit];
212637Snate	register int i;
213637Snate
214637Snate	/*
215637Snate	 * Check for each mouse type in the table.
216637Snate	 */
217637Snate	i = 0;
218637Snate	while (mse_types[i].m_type) {
219637Snate		if ((*mse_types[i].m_probe)(idp)) {
220637Snate			sc->sc_mousetype = mse_types[i].m_type;
221637Snate			sc->sc_enablemouse = mse_types[i].m_enable;
222637Snate			sc->sc_disablemouse = mse_types[i].m_disable;
223637Snate			sc->sc_getmouse = mse_types[i].m_get;
224637Snate			return (1);
225637Snate		}
226637Snate		i++;
227637Snate	}
228637Snate	return (0);
229637Snate}
230637Snate
231798Swollmanint
232637Snatemseattach(idp)
233637Snate	struct isa_device *idp;
234637Snate{
23512675Sjulian	int unit = idp->id_unit;
23612675Sjulian	struct mse_softc *sc = &mse_sc[unit];
237637Snate
238637Snate	sc->sc_port = idp->id_iobase;
23912675Sjulian#ifdef	DEVFS
24014873Sscrappy	sc->devfs_token =
24114873Sscrappy		devfs_add_devswf(&mse_cdevsw, unit << 1, DV_CHR, 0, 0,
24214873Sscrappy				 0600, "mse%d", unit);
24314873Sscrappy	sc->n_devfs_token =
24414873Sscrappy		devfs_add_devswf(&mse_cdevsw, (unit<<1)+1, DV_CHR,0, 0,
24514873Sscrappy				 0600, "nmse%d", unit);
24612675Sjulian#endif
247637Snate	return (1);
248637Snate}
249637Snate
250637Snate/*
251637Snate * Exclusive open the mouse, initialize it and enable interrupts.
252637Snate */
25312675Sjulianstatic	int
25410624Sbdemseopen(dev, flags, fmt, p)
255637Snate	dev_t dev;
25610624Sbde	int flags;
25710624Sbde	int fmt;
25810624Sbde	struct proc *p;
259637Snate{
260637Snate	register struct mse_softc *sc;
261637Snate	int s;
262637Snate
263637Snate	if (MSE_UNIT(dev) >= NMSE)
264637Snate		return (ENXIO);
265637Snate	sc = &mse_sc[MSE_UNIT(dev)];
26620688Sjoerg	if (sc->sc_mousetype == MSE_NONE)
26720688Sjoerg		return (ENXIO);
268637Snate	if (sc->sc_flags & MSESC_OPEN)
269637Snate		return (EBUSY);
270637Snate	sc->sc_flags |= MSESC_OPEN;
271637Snate	sc->sc_obuttons = sc->sc_buttons = 0x7;
272637Snate	sc->sc_deltax = sc->sc_deltay = 0;
273637Snate	sc->sc_bytesread = PROTOBYTES;
274637Snate
275637Snate	/*
276637Snate	 * Initialize mouse interface and enable interrupts.
277637Snate	 */
278637Snate	s = spltty();
279637Snate	(*sc->sc_enablemouse)(sc->sc_port);
280637Snate	splx(s);
281637Snate	return (0);
282637Snate}
283637Snate
284637Snate/*
285637Snate * mseclose: just turn off mouse innterrupts.
286637Snate */
28712675Sjulianstatic	int
28810624Sbdemseclose(dev, flags, fmt, p)
289798Swollman	dev_t dev;
29010624Sbde	int flags;
29110624Sbde	int fmt;
29210624Sbde	struct proc *p;
293637Snate{
294637Snate	struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
295637Snate	int s;
296637Snate
297637Snate	s = spltty();
298637Snate	(*sc->sc_disablemouse)(sc->sc_port);
299637Snate	sc->sc_flags &= ~MSESC_OPEN;
300637Snate	splx(s);
301637Snate	return(0);
302637Snate}
303637Snate
3048876Srgrimes/*
305637Snate * mseread: return mouse info using the MSC serial protocol, but without
306637Snate * using bytes 4 and 5.
307637Snate * (Yes this is cheesy, but it makes the X386 server happy, so...)
308637Snate */
30912675Sjulianstatic	int
31010624Sbdemseread(dev, uio, ioflag)
311637Snate	dev_t dev;
312637Snate	struct uio *uio;
31310624Sbde	int ioflag;
314637Snate{
315637Snate	register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
316637Snate	int xfer, s, error;
317637Snate
318637Snate	/*
319637Snate	 * If there are no protocol bytes to be read, set up a new protocol
320637Snate	 * packet.
321637Snate	 */
322637Snate	s = spltty(); /* XXX Should be its own spl, but where is imlXX() */
323637Snate	if (sc->sc_bytesread >= PROTOBYTES) {
324637Snate		while (sc->sc_deltax == 0 && sc->sc_deltay == 0 &&
325637Snate		       (sc->sc_obuttons ^ sc->sc_buttons) == 0) {
326637Snate			if (MSE_NBLOCKIO(dev)) {
327637Snate				splx(s);
328637Snate				return (0);
329637Snate			}
330637Snate			sc->sc_flags |= MSESC_WANT;
331637Snate			if (error = tsleep((caddr_t)sc, MSEPRI | PCATCH,
332637Snate				"mseread", 0)) {
333637Snate				splx(s);
334637Snate				return (error);
335637Snate			}
336637Snate		}
337637Snate
338637Snate		/*
339637Snate		 * Generate protocol bytes.
340637Snate		 * For some reason X386 expects 5 bytes but never uses
341637Snate		 * the fourth or fifth?
342637Snate		 */
343637Snate		sc->sc_bytes[0] = 0x80 | (sc->sc_buttons & ~0xf8);
344637Snate		if (sc->sc_deltax > 127)
345637Snate			sc->sc_deltax = 127;
346637Snate		if (sc->sc_deltax < -127)
347637Snate			sc->sc_deltax = -127;
348637Snate		sc->sc_deltay = -sc->sc_deltay;	/* Otherwise mousey goes wrong way */
349637Snate		if (sc->sc_deltay > 127)
350637Snate			sc->sc_deltay = 127;
351637Snate		if (sc->sc_deltay < -127)
352637Snate			sc->sc_deltay = -127;
353637Snate		sc->sc_bytes[1] = sc->sc_deltax;
354637Snate		sc->sc_bytes[2] = sc->sc_deltay;
355637Snate		sc->sc_bytes[3] = sc->sc_bytes[4] = 0;
356637Snate		sc->sc_obuttons = sc->sc_buttons;
357637Snate		sc->sc_deltax = sc->sc_deltay = 0;
358637Snate		sc->sc_bytesread = 0;
359637Snate	}
360637Snate	splx(s);
3611567Srgrimes	xfer = min(uio->uio_resid, PROTOBYTES - sc->sc_bytesread);
362637Snate	if (error = uiomove(&sc->sc_bytes[sc->sc_bytesread], xfer, uio))
363637Snate		return (error);
364637Snate	sc->sc_bytesread += xfer;
365637Snate	return(0);
366637Snate}
367637Snate
368637Snate/*
36929368Speter * msepoll: check for mouse input to be processed.
370637Snate */
37112675Sjulianstatic	int
37229368Spetermsepoll(dev, events, p)
373637Snate	dev_t dev;
37429368Speter	int events;
375637Snate	struct proc *p;
376637Snate{
377637Snate	register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
378637Snate	int s;
37929368Speter	int revents = 0;
380637Snate
381637Snate	s = spltty();
38229368Speter	if (events & (POLLIN | POLLRDNORM))
38329368Speter		if (sc->sc_bytesread != PROTOBYTES || sc->sc_deltax != 0 ||
38429368Speter		    sc->sc_deltay != 0 ||
38529368Speter		    (sc->sc_obuttons ^ sc->sc_buttons) != 0)
38629368Speter			revents |= events & (POLLIN | POLLRDNORM);
38729368Speter		else {
38829368Speter			/*
38929368Speter			 * Since this is an exclusive open device, any previous
39029368Speter			 * proc pointer is trash now, so we can just assign it.
39129368Speter			 */
39229368Speter			selrecord(p, &sc->sc_selp);
39329368Speter		}
394637Snate
395637Snate	splx(s);
39629368Speter	return (revents);
397637Snate}
398637Snate
399637Snate/*
400637Snate * mseintr: update mouse status. sc_deltax and sc_deltay are accumulative.
401637Snate */
402798Swollmanvoid
403637Snatemseintr(unit)
404637Snate	int unit;
405637Snate{
406637Snate	register struct mse_softc *sc = &mse_sc[unit];
407637Snate
408637Snate#ifdef DEBUG
409637Snate	static int mse_intrcnt = 0;
410637Snate	if((mse_intrcnt++ % 10000) == 0)
411637Snate		printf("mseintr\n");
412637Snate#endif /* DEBUG */
413637Snate	if ((sc->sc_flags & MSESC_OPEN) == 0)
414637Snate		return;
415637Snate
416637Snate	(*sc->sc_getmouse)(sc->sc_port, &sc->sc_deltax, &sc->sc_deltay, &sc->sc_buttons);
417637Snate
418637Snate	/*
419637Snate	 * If mouse state has changed, wake up anyone wanting to know.
420637Snate	 */
421637Snate	if (sc->sc_deltax != 0 || sc->sc_deltay != 0 ||
422637Snate	    (sc->sc_obuttons ^ sc->sc_buttons) != 0) {
4238876Srgrimes		if (sc->sc_flags & MSESC_WANT) {
4248876Srgrimes			sc->sc_flags &= ~MSESC_WANT;
4258876Srgrimes			wakeup((caddr_t)sc);
4268876Srgrimes		}
4271549Srgrimes		selwakeup(&sc->sc_selp);
428637Snate	}
429637Snate}
430637Snate
431637Snate/*
432637Snate * Routines for the Logitech mouse.
433637Snate */
434637Snate/*
435637Snate * Test for a Logitech bus mouse and return 1 if it is.
436637Snate * (until I know how to use the signature port properly, just disable
437637Snate *  interrupts and return 1)
438637Snate */
439637Snatestatic int
440637Snatemse_probelogi(idp)
441637Snate	register struct isa_device *idp;
442637Snate{
443637Snate
4444259Sjkh	int sig;
4454259Sjkh
4464259Sjkh	outb(idp->id_iobase + MSE_PORTD, MSE_SETUP);
4474259Sjkh		/* set the signature port */
4484259Sjkh	outb(idp->id_iobase + MSE_PORTB, MSE_LOGI_SIG);
4494259Sjkh
4504259Sjkh	DELAY(30000); /* 30 ms delay */
4514259Sjkh	sig = inb(idp->id_iobase + MSE_PORTB) & 0xFF;
4524259Sjkh	if (sig == MSE_LOGI_SIG) {
4534259Sjkh		outb(idp->id_iobase + MSE_PORTC, MSE_DISINTR);
4544259Sjkh		return(1);
4554259Sjkh	} else {
45616074Sjoerg		if (bootverbose)
45716074Sjoerg			printf("mse%d: wrong signature %x\n",idp->id_unit,sig);
4584259Sjkh		return(0);
459637Snate	}
460637Snate}
461637Snate
462637Snate/*
463637Snate * Initialize Logitech mouse and enable interrupts.
464637Snate */
465637Snatestatic void
466637Snatemse_enablelogi(port)
467637Snate	register u_int port;
468637Snate{
469637Snate	int dx, dy, but;
470637Snate
471637Snate	outb(port + MSE_PORTD, MSE_SETUP);
472637Snate	mse_getlogi(port, &dx, &dy, &but);
473637Snate}
474637Snate
475637Snate/*
476637Snate * Disable interrupts for Logitech mouse.
477637Snate */
478637Snatestatic void
479637Snatemse_disablelogi(port)
480637Snate	register u_int port;
481637Snate{
482637Snate
483637Snate	outb(port + MSE_PORTC, MSE_DISINTR);
484637Snate}
485637Snate
486637Snate/*
487637Snate * Get the current dx, dy and button up/down state.
488637Snate */
489637Snatestatic void
490637Snatemse_getlogi(port, dx, dy, but)
491637Snate	register u_int port;
492637Snate	int *dx;
493637Snate	int *dy;
494637Snate	int *but;
495637Snate{
496637Snate	register char x, y;
497637Snate
498637Snate	outb(port + MSE_PORTC, MSE_HOLD | MSE_RXLOW);
499637Snate	x = inb(port + MSE_PORTA);
500637Snate	*but = (x >> 5) & 0x7;
501637Snate	x &= 0xf;
502637Snate	outb(port + MSE_PORTC, MSE_HOLD | MSE_RXHIGH);
503637Snate	x |= (inb(port + MSE_PORTA) << 4);
504637Snate	outb(port + MSE_PORTC, MSE_HOLD | MSE_RYLOW);
505637Snate	y = (inb(port + MSE_PORTA) & 0xf);
506637Snate	outb(port + MSE_PORTC, MSE_HOLD | MSE_RYHIGH);
507637Snate	y |= (inb(port + MSE_PORTA) << 4);
508637Snate	*dx += x;
509637Snate	*dy += y;
510637Snate	outb(port + MSE_PORTC, MSE_INTREN);
511637Snate}
512637Snate
513637Snate/*
514637Snate * Routines for the ATI Inport bus mouse.
515637Snate */
516637Snate/*
517637Snate * Test for a ATI Inport bus mouse and return 1 if it is.
518637Snate * (do not enable interrupts)
519637Snate */
520637Snatestatic int
521637Snatemse_probeati(idp)
522637Snate	register struct isa_device *idp;
523637Snate{
524637Snate	int i;
525637Snate
526637Snate	for (i = 0; i < 2; i++)
527637Snate		if (inb(idp->id_iobase + MSE_PORTC) == 0xde)
528637Snate			return (1);
529637Snate	return (0);
530637Snate}
531637Snate
532637Snate/*
533637Snate * Initialize ATI Inport mouse and enable interrupts.
534637Snate */
535637Snatestatic void
536637Snatemse_enableati(port)
537637Snate	register u_int port;
538637Snate{
539637Snate
540637Snate	outb(port + MSE_PORTA, MSE_INPORT_RESET);
541637Snate	outb(port + MSE_PORTA, MSE_INPORT_MODE);
542637Snate	outb(port + MSE_PORTB, MSE_INPORT_INTREN);
543637Snate}
544637Snate
545637Snate/*
546637Snate * Disable interrupts for ATI Inport mouse.
547637Snate */
548637Snatestatic void
549637Snatemse_disableati(port)
550637Snate	register u_int port;
551637Snate{
552637Snate
553637Snate	outb(port + MSE_PORTA, MSE_INPORT_MODE);
554637Snate	outb(port + MSE_PORTB, 0);
555637Snate}
556637Snate
557637Snate/*
558637Snate * Get current dx, dy and up/down button state.
559637Snate */
560637Snatestatic void
561637Snatemse_getati(port, dx, dy, but)
562637Snate	register u_int port;
563637Snate	int *dx;
564637Snate	int *dy;
565637Snate	int *but;
566637Snate{
567637Snate	register char byte;
568637Snate
569637Snate	outb(port + MSE_PORTA, MSE_INPORT_MODE);
570637Snate	outb(port + MSE_PORTB, MSE_INPORT_HOLD);
571637Snate	outb(port + MSE_PORTA, MSE_INPORT_STATUS);
572637Snate	*but = ~(inb(port + MSE_PORTB) & 0x7);
573637Snate	outb(port + MSE_PORTA, MSE_INPORT_DX);
574637Snate	byte = inb(port + MSE_PORTB);
575637Snate	*dx += byte;
576637Snate	outb(port + MSE_PORTA, MSE_INPORT_DY);
577637Snate	byte = inb(port + MSE_PORTB);
578637Snate	*dy += byte;
579637Snate	outb(port + MSE_PORTA, MSE_INPORT_MODE);
580637Snate	outb(port + MSE_PORTB, MSE_INPORT_INTREN);
581637Snate}
58212502Sjulian
58312502Sjulianstatic mse_devsw_installed = 0;
58412502Sjulian
58512517Sjulianstatic void 	mse_drvinit(void *unused)
58612502Sjulian{
58712517Sjulian	dev_t dev;
58812517Sjulian
58912502Sjulian	if( ! mse_devsw_installed ) {
59012675Sjulian		dev = makedev(CDEV_MAJOR, 0);
59112675Sjulian		cdevsw_add(&dev,&mse_cdevsw, NULL);
59212502Sjulian		mse_devsw_installed = 1;
59312517Sjulian    	}
59412502Sjulian}
59512517Sjulian
59612517SjulianSYSINIT(msedev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,mse_drvinit,NULL)
59712517Sjulian
59812517Sjulian
599637Snate#endif /* NMSE */
600