mse.c revision 12724
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 *
1412724Sphk * $Id: mse.c,v 1.21 1995/12/08 23:20:35 phk 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/buf.h>
542056Swollman#include <sys/kernel.h>
552056Swollman#include <sys/ioctl.h>
562056Swollman#include <sys/uio.h>
573816Swollman#include <sys/devconf.h>
5812675Sjulian#include <sys/conf.h>
5912675Sjulian#ifdef DEVFS
6012675Sjulian#include <sys/devfsext.h>
6112675Sjulian#endif /*DEVFS*/
62637Snate
637430Sbde#include <machine/clock.h>
647430Sbde
652056Swollman#include <i386/isa/isa_device.h>
662056Swollman#include <i386/isa/icu.h>
67637Snate
6812502Sjulian
69798Swollmanstatic int mseprobe(struct isa_device *);
70798Swollmanstatic int mseattach(struct isa_device *);
71637Snate
72637Snatestruct	isa_driver msedriver = {
73637Snate	mseprobe, mseattach, "mse"
74637Snate};
75637Snate
7612675Sjulianstatic	d_open_t	mseopen;
7712675Sjulianstatic	d_close_t	mseclose;
7812675Sjulianstatic	d_read_t	mseread;
7912675Sjulianstatic	d_select_t	mseselect;
8012675Sjulian
8112675Sjulian#define CDEV_MAJOR 27
8212678Sphkstatic struct cdevsw mse_cdevsw =
8312675Sjulian	{ mseopen,	mseclose,	mseread,	nowrite,	/*27*/
8412675Sjulian	  noioc,	nostop,		nullreset,	nodevtotty,/* mse */
8512675Sjulian	  mseselect,	nommap,		NULL,	"mse",	NULL,	-1 };
8612675Sjulian
8712675Sjulian
88637Snate/*
89637Snate * Software control structure for mouse. The sc_enablemouse(),
90637Snate * sc_disablemouse() and sc_getmouse() routines must be called spl'd().
91637Snate */
92637Snate#define	PROTOBYTES	5
9312724Sphkstatic struct mse_softc {
94637Snate	int	sc_flags;
95637Snate	int	sc_mousetype;
961549Srgrimes	struct	selinfo sc_selp;
97637Snate	u_int	sc_port;
98637Snate	void	(*sc_enablemouse)();
99637Snate	void	(*sc_disablemouse)();
100637Snate	void	(*sc_getmouse)();
101637Snate	int	sc_deltax;
102637Snate	int	sc_deltay;
103637Snate	int	sc_obuttons;
104637Snate	int	sc_buttons;
105637Snate	int	sc_bytesread;
106637Snate	u_char	sc_bytes[PROTOBYTES];
10712675Sjulian#ifdef DEVFS
10812675Sjulian	void 	*devfs_token;
10912675Sjulian	void	*n_devfs_token;
11012675Sjulian#endif
111637Snate} mse_sc[NMSE];
112637Snate
113637Snate/* Flags */
114637Snate#define	MSESC_OPEN	0x1
115637Snate#define	MSESC_WANT	0x2
116637Snate
117637Snate/* and Mouse Types */
118637Snate#define	MSE_LOGITECH	0x1
119637Snate#define	MSE_ATIINPORT	0x2
1204259Sjkh#define	MSE_LOGI_SIG	0xA5
121637Snate
122637Snate#define	MSE_PORTA	0
123637Snate#define	MSE_PORTB	1
124637Snate#define	MSE_PORTC	2
125637Snate#define	MSE_PORTD	3
126637Snate
127637Snate#define	MSE_UNIT(dev)		(minor(dev) >> 1)
128637Snate#define	MSE_NBLOCKIO(dev)	(minor(dev) & 0x1)
129637Snate
130637Snate/*
131637Snate * Logitech bus mouse definitions
132637Snate */
133637Snate#define	MSE_SETUP	0x91	/* What does this mean? */
1344259Sjkh				/* The definition for the control port */
1354259Sjkh				/* is as follows: */
1368876Srgrimes
1374259Sjkh				/* D7 	 =  Mode set flag (1 = active) 	*/
1388876Srgrimes				/* D6,D5 =  Mode selection (port A) 	*/
1394259Sjkh				/* 	    00 = Mode 0 = Basic I/O 	*/
1404259Sjkh				/* 	    01 = Mode 1 = Strobed I/O 	*/
1414259Sjkh				/* 	    10 = Mode 2 = Bi-dir bus 	*/
1424259Sjkh				/* D4	 =  Port A direction (1 = input)*/
1434259Sjkh				/* D3	 =  Port C (upper 4 bits) 	*/
1444259Sjkh				/*	    direction. (1 = input)	*/
1454259Sjkh				/* D2	 =  Mode selection (port B & C) */
1464259Sjkh				/*	    0 = Mode 0 = Basic I/O	*/
1474259Sjkh				/*	    1 = Mode 1 = Strobed I/O	*/
1484259Sjkh				/* D1	 =  Port B direction (1 = input)*/
1494259Sjkh				/* D0	 =  Port C (lower 4 bits)	*/
1504259Sjkh				/*	    direction. (1 = input)	*/
1518876Srgrimes
1524259Sjkh				/* So 91 means Basic I/O on all 3 ports,*/
1534259Sjkh				/* Port A is an input port, B is an 	*/
1544259Sjkh				/* output port, C is split with upper	*/
1554259Sjkh				/* 4 bits being an output port and lower*/
1564259Sjkh				/* 4 bits an input port, and enable the */
1574259Sjkh				/* sucker.				*/
1584259Sjkh				/* Courtesy Intel 8255 databook. Lars   */
159637Snate#define	MSE_HOLD	0x80
160637Snate#define	MSE_RXLOW	0x00
161637Snate#define	MSE_RXHIGH	0x20
162637Snate#define	MSE_RYLOW	0x40
163637Snate#define	MSE_RYHIGH	0x60
164637Snate#define	MSE_DISINTR	0x10
165637Snate#define MSE_INTREN	0x00
166637Snate
167637Snatestatic int mse_probelogi();
168637Snatestatic void mse_enablelogi(), mse_disablelogi(), mse_getlogi();
169637Snate
170637Snate/*
171637Snate * ATI Inport mouse definitions
172637Snate */
173637Snate#define	MSE_INPORT_RESET	0x80
174637Snate#define	MSE_INPORT_STATUS	0x00
175637Snate#define	MSE_INPORT_DX		0x01
176637Snate#define	MSE_INPORT_DY		0x02
177637Snate#define	MSE_INPORT_MODE		0x07
178637Snate#define	MSE_INPORT_HOLD		0x20
179637Snate#define	MSE_INPORT_INTREN	0x09
180637Snate
181637Snatestatic int mse_probeati();
182637Snatestatic void mse_enableati(), mse_disableati(), mse_getati();
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 */
193637Snate	int	(*m_probe)();	/* Probe routine to test for it */
194637Snate	void	(*m_enable)();	/* Start routine */
195637Snate	void	(*m_disable)();	/* Disable interrupts routine */
196637Snate	void	(*m_get)();	/* and get mouse status */
197637Snate} mse_types[] = {
198637Snate	{ MSE_ATIINPORT, mse_probeati, mse_enableati, mse_disableati, mse_getati },
199637Snate	{ MSE_LOGITECH, mse_probelogi, mse_enablelogi, mse_disablelogi, mse_getlogi },
200637Snate	{ 0, },
201637Snate};
202637Snate
2037780Swollmanstatic struct kern_devconf kdc_mse[NMSE] = { {
2047780Swollman	0, 0, 0,		/* filled in by dev_attach */
2057780Swollman	"mse", 0, { MDDT_ISA, 0, "tty" },
2067780Swollman	isa_generic_externalize, 0, 0, ISA_EXTERNALLEN,
2077780Swollman	&kdc_isa0,		/* parent */
2087780Swollman	0,			/* parentdata */
2097780Swollman	DC_UNCONFIGURED,	/* state */
2107780Swollman	"ATI or Logitech bus mouse adapter",
2117780Swollman	DC_CLS_MISC		/* class */
2127780Swollman} };
2137780Swollman
2147780Swollmanstatic inline void
2157780Swollmanmse_registerdev(struct isa_device *id)
2167780Swollman{
2177780Swollman	if(id->id_unit)
2187780Swollman		kdc_mse[id->id_unit] = kdc_mse[0];
2197780Swollman	kdc_mse[id->id_unit].kdc_unit = id->id_unit;
2207780Swollman	kdc_mse[id->id_unit].kdc_isa = id;
2217780Swollman	dev_attach(&kdc_mse[id->id_unit]);
2227780Swollman}
2237780Swollman
224798Swollmanint
225637Snatemseprobe(idp)
226637Snate	register struct isa_device *idp;
227637Snate{
228637Snate	register struct mse_softc *sc = &mse_sc[idp->id_unit];
229637Snate	register int i;
230637Snate
2317780Swollman	mse_registerdev(idp);
232637Snate	/*
233637Snate	 * Check for each mouse type in the table.
234637Snate	 */
235637Snate	i = 0;
236637Snate	while (mse_types[i].m_type) {
237637Snate		if ((*mse_types[i].m_probe)(idp)) {
238637Snate			sc->sc_mousetype = mse_types[i].m_type;
239637Snate			sc->sc_enablemouse = mse_types[i].m_enable;
240637Snate			sc->sc_disablemouse = mse_types[i].m_disable;
241637Snate			sc->sc_getmouse = mse_types[i].m_get;
242637Snate			return (1);
243637Snate		}
244637Snate		i++;
245637Snate	}
246637Snate	return (0);
247637Snate}
248637Snate
249798Swollmanint
250637Snatemseattach(idp)
251637Snate	struct isa_device *idp;
252637Snate{
25312675Sjulian	char name[32];
25412675Sjulian	int unit = idp->id_unit;
25512675Sjulian	struct mse_softc *sc = &mse_sc[unit];
256637Snate
257637Snate	sc->sc_port = idp->id_iobase;
25812675Sjulian	kdc_mse[unit].kdc_state = DC_IDLE;
25912675Sjulian#ifdef	DEVFS
26012675Sjulian	sprintf(name,"mse%d", unit);
26112675Sjulian                                /*        path  name   devsw    minor */
26212675Sjulian	sc->devfs_token = devfs_add_devsw( "/",	name, &mse_cdevsw, unit << 1,
26312675Sjulian                                              /*type   uid gid perm*/
26412675Sjulian						DV_CHR,	0, 0, 0600);
26512675Sjulian	sprintf(name,"nmse%d", unit);
26612675Sjulian                                /*        path  name   devsw    minor */
26712675Sjulian	sc->n_devfs_token = devfs_add_devsw("/", name, &mse_cdevsw, (unit<<1)+1,
26812675Sjulian                                              /*type   uid gid perm*/
26912675Sjulian						DV_CHR,	0, 0, 0600);
27012675Sjulian#endif
271637Snate	return (1);
272637Snate}
273637Snate
274637Snate/*
275637Snate * Exclusive open the mouse, initialize it and enable interrupts.
276637Snate */
27712675Sjulianstatic	int
27810624Sbdemseopen(dev, flags, fmt, p)
279637Snate	dev_t dev;
28010624Sbde	int flags;
28110624Sbde	int fmt;
28210624Sbde	struct proc *p;
283637Snate{
284637Snate	register struct mse_softc *sc;
285637Snate	int s;
286637Snate
287637Snate	if (MSE_UNIT(dev) >= NMSE)
288637Snate		return (ENXIO);
289637Snate	sc = &mse_sc[MSE_UNIT(dev)];
290637Snate	if (sc->sc_flags & MSESC_OPEN)
291637Snate		return (EBUSY);
292637Snate	sc->sc_flags |= MSESC_OPEN;
2937780Swollman	kdc_mse[MSE_UNIT(dev)].kdc_state = DC_BUSY;
294637Snate	sc->sc_obuttons = sc->sc_buttons = 0x7;
295637Snate	sc->sc_deltax = sc->sc_deltay = 0;
296637Snate	sc->sc_bytesread = PROTOBYTES;
297637Snate
298637Snate	/*
299637Snate	 * Initialize mouse interface and enable interrupts.
300637Snate	 */
301637Snate	s = spltty();
302637Snate	(*sc->sc_enablemouse)(sc->sc_port);
303637Snate	splx(s);
304637Snate	return (0);
305637Snate}
306637Snate
307637Snate/*
308637Snate * mseclose: just turn off mouse innterrupts.
309637Snate */
31012675Sjulianstatic	int
31110624Sbdemseclose(dev, flags, fmt, p)
312798Swollman	dev_t dev;
31310624Sbde	int flags;
31410624Sbde	int fmt;
31510624Sbde	struct proc *p;
316637Snate{
317637Snate	struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
318637Snate	int s;
319637Snate
320637Snate	s = spltty();
321637Snate	(*sc->sc_disablemouse)(sc->sc_port);
322637Snate	sc->sc_flags &= ~MSESC_OPEN;
3237780Swollman	kdc_mse[MSE_UNIT(dev)].kdc_state = DC_IDLE;
324637Snate	splx(s);
325637Snate	return(0);
326637Snate}
327637Snate
3288876Srgrimes/*
329637Snate * mseread: return mouse info using the MSC serial protocol, but without
330637Snate * using bytes 4 and 5.
331637Snate * (Yes this is cheesy, but it makes the X386 server happy, so...)
332637Snate */
33312675Sjulianstatic	int
33410624Sbdemseread(dev, uio, ioflag)
335637Snate	dev_t dev;
336637Snate	struct uio *uio;
33710624Sbde	int ioflag;
338637Snate{
339637Snate	register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
340637Snate	int xfer, s, error;
341637Snate
342637Snate	/*
343637Snate	 * If there are no protocol bytes to be read, set up a new protocol
344637Snate	 * packet.
345637Snate	 */
346637Snate	s = spltty(); /* XXX Should be its own spl, but where is imlXX() */
347637Snate	if (sc->sc_bytesread >= PROTOBYTES) {
348637Snate		while (sc->sc_deltax == 0 && sc->sc_deltay == 0 &&
349637Snate		       (sc->sc_obuttons ^ sc->sc_buttons) == 0) {
350637Snate			if (MSE_NBLOCKIO(dev)) {
351637Snate				splx(s);
352637Snate				return (0);
353637Snate			}
354637Snate			sc->sc_flags |= MSESC_WANT;
355637Snate			if (error = tsleep((caddr_t)sc, MSEPRI | PCATCH,
356637Snate				"mseread", 0)) {
357637Snate				splx(s);
358637Snate				return (error);
359637Snate			}
360637Snate		}
361637Snate
362637Snate		/*
363637Snate		 * Generate protocol bytes.
364637Snate		 * For some reason X386 expects 5 bytes but never uses
365637Snate		 * the fourth or fifth?
366637Snate		 */
367637Snate		sc->sc_bytes[0] = 0x80 | (sc->sc_buttons & ~0xf8);
368637Snate		if (sc->sc_deltax > 127)
369637Snate			sc->sc_deltax = 127;
370637Snate		if (sc->sc_deltax < -127)
371637Snate			sc->sc_deltax = -127;
372637Snate		sc->sc_deltay = -sc->sc_deltay;	/* Otherwise mousey goes wrong way */
373637Snate		if (sc->sc_deltay > 127)
374637Snate			sc->sc_deltay = 127;
375637Snate		if (sc->sc_deltay < -127)
376637Snate			sc->sc_deltay = -127;
377637Snate		sc->sc_bytes[1] = sc->sc_deltax;
378637Snate		sc->sc_bytes[2] = sc->sc_deltay;
379637Snate		sc->sc_bytes[3] = sc->sc_bytes[4] = 0;
380637Snate		sc->sc_obuttons = sc->sc_buttons;
381637Snate		sc->sc_deltax = sc->sc_deltay = 0;
382637Snate		sc->sc_bytesread = 0;
383637Snate	}
384637Snate	splx(s);
3851567Srgrimes	xfer = min(uio->uio_resid, PROTOBYTES - sc->sc_bytesread);
386637Snate	if (error = uiomove(&sc->sc_bytes[sc->sc_bytesread], xfer, uio))
387637Snate		return (error);
388637Snate	sc->sc_bytesread += xfer;
389637Snate	return(0);
390637Snate}
391637Snate
392637Snate/*
393637Snate * mseselect: check for mouse input to be processed.
394637Snate */
39512675Sjulianstatic	int
396637Snatemseselect(dev, rw, p)
397637Snate	dev_t dev;
398637Snate	int rw;
399637Snate	struct proc *p;
400637Snate{
401637Snate	register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
402637Snate	int s;
403637Snate
404637Snate	s = spltty();
405637Snate	if (sc->sc_bytesread != PROTOBYTES || sc->sc_deltax != 0 ||
406637Snate	    sc->sc_deltay != 0 || (sc->sc_obuttons ^ sc->sc_buttons) != 0) {
407637Snate		splx(s);
408637Snate		return (1);
409637Snate	}
410637Snate
411637Snate	/*
412637Snate	 * Since this is an exclusive open device, any previous proc.
413637Snate	 * pointer is trash now, so we can just assign it.
414637Snate	 */
4151549Srgrimes	selrecord(p, &sc->sc_selp);
416637Snate	splx(s);
417637Snate	return (0);
418637Snate}
419637Snate
420637Snate/*
421637Snate * mseintr: update mouse status. sc_deltax and sc_deltay are accumulative.
422637Snate */
423798Swollmanvoid
424637Snatemseintr(unit)
425637Snate	int unit;
426637Snate{
427637Snate	register struct mse_softc *sc = &mse_sc[unit];
428637Snate
429637Snate#ifdef DEBUG
430637Snate	static int mse_intrcnt = 0;
431637Snate	if((mse_intrcnt++ % 10000) == 0)
432637Snate		printf("mseintr\n");
433637Snate#endif /* DEBUG */
434637Snate	if ((sc->sc_flags & MSESC_OPEN) == 0)
435637Snate		return;
436637Snate
437637Snate	(*sc->sc_getmouse)(sc->sc_port, &sc->sc_deltax, &sc->sc_deltay, &sc->sc_buttons);
438637Snate
439637Snate	/*
440637Snate	 * If mouse state has changed, wake up anyone wanting to know.
441637Snate	 */
442637Snate	if (sc->sc_deltax != 0 || sc->sc_deltay != 0 ||
443637Snate	    (sc->sc_obuttons ^ sc->sc_buttons) != 0) {
4448876Srgrimes		if (sc->sc_flags & MSESC_WANT) {
4458876Srgrimes			sc->sc_flags &= ~MSESC_WANT;
4468876Srgrimes			wakeup((caddr_t)sc);
4478876Srgrimes		}
4481549Srgrimes		selwakeup(&sc->sc_selp);
449637Snate	}
450637Snate}
451637Snate
452637Snate/*
453637Snate * Routines for the Logitech mouse.
454637Snate */
455637Snate/*
456637Snate * Test for a Logitech bus mouse and return 1 if it is.
457637Snate * (until I know how to use the signature port properly, just disable
458637Snate *  interrupts and return 1)
459637Snate */
460637Snatestatic int
461637Snatemse_probelogi(idp)
462637Snate	register struct isa_device *idp;
463637Snate{
464637Snate
4654259Sjkh	int sig;
4664259Sjkh
4674259Sjkh	outb(idp->id_iobase + MSE_PORTD, MSE_SETUP);
4684259Sjkh		/* set the signature port */
4694259Sjkh	outb(idp->id_iobase + MSE_PORTB, MSE_LOGI_SIG);
4704259Sjkh
4714259Sjkh	DELAY(30000); /* 30 ms delay */
4724259Sjkh	sig = inb(idp->id_iobase + MSE_PORTB) & 0xFF;
4734259Sjkh	if (sig == MSE_LOGI_SIG) {
4744259Sjkh		outb(idp->id_iobase + MSE_PORTC, MSE_DISINTR);
4754259Sjkh		return(1);
4764259Sjkh	} else {
4778876Srgrimes		printf("mse%d: wrong signature %x\n",idp->id_unit,sig);
4784259Sjkh		return(0);
479637Snate	}
480637Snate}
481637Snate
482637Snate/*
483637Snate * Initialize Logitech mouse and enable interrupts.
484637Snate */
485637Snatestatic void
486637Snatemse_enablelogi(port)
487637Snate	register u_int port;
488637Snate{
489637Snate	int dx, dy, but;
490637Snate
491637Snate	outb(port + MSE_PORTD, MSE_SETUP);
492637Snate	mse_getlogi(port, &dx, &dy, &but);
493637Snate}
494637Snate
495637Snate/*
496637Snate * Disable interrupts for Logitech mouse.
497637Snate */
498637Snatestatic void
499637Snatemse_disablelogi(port)
500637Snate	register u_int port;
501637Snate{
502637Snate
503637Snate	outb(port + MSE_PORTC, MSE_DISINTR);
504637Snate}
505637Snate
506637Snate/*
507637Snate * Get the current dx, dy and button up/down state.
508637Snate */
509637Snatestatic void
510637Snatemse_getlogi(port, dx, dy, but)
511637Snate	register u_int port;
512637Snate	int *dx;
513637Snate	int *dy;
514637Snate	int *but;
515637Snate{
516637Snate	register char x, y;
517637Snate
518637Snate	outb(port + MSE_PORTC, MSE_HOLD | MSE_RXLOW);
519637Snate	x = inb(port + MSE_PORTA);
520637Snate	*but = (x >> 5) & 0x7;
521637Snate	x &= 0xf;
522637Snate	outb(port + MSE_PORTC, MSE_HOLD | MSE_RXHIGH);
523637Snate	x |= (inb(port + MSE_PORTA) << 4);
524637Snate	outb(port + MSE_PORTC, MSE_HOLD | MSE_RYLOW);
525637Snate	y = (inb(port + MSE_PORTA) & 0xf);
526637Snate	outb(port + MSE_PORTC, MSE_HOLD | MSE_RYHIGH);
527637Snate	y |= (inb(port + MSE_PORTA) << 4);
528637Snate	*dx += x;
529637Snate	*dy += y;
530637Snate	outb(port + MSE_PORTC, MSE_INTREN);
531637Snate}
532637Snate
533637Snate/*
534637Snate * Routines for the ATI Inport bus mouse.
535637Snate */
536637Snate/*
537637Snate * Test for a ATI Inport bus mouse and return 1 if it is.
538637Snate * (do not enable interrupts)
539637Snate */
540637Snatestatic int
541637Snatemse_probeati(idp)
542637Snate	register struct isa_device *idp;
543637Snate{
544637Snate	int i;
545637Snate
546637Snate	for (i = 0; i < 2; i++)
547637Snate		if (inb(idp->id_iobase + MSE_PORTC) == 0xde)
548637Snate			return (1);
549637Snate	return (0);
550637Snate}
551637Snate
552637Snate/*
553637Snate * Initialize ATI Inport mouse and enable interrupts.
554637Snate */
555637Snatestatic void
556637Snatemse_enableati(port)
557637Snate	register u_int port;
558637Snate{
559637Snate
560637Snate	outb(port + MSE_PORTA, MSE_INPORT_RESET);
561637Snate	outb(port + MSE_PORTA, MSE_INPORT_MODE);
562637Snate	outb(port + MSE_PORTB, MSE_INPORT_INTREN);
563637Snate}
564637Snate
565637Snate/*
566637Snate * Disable interrupts for ATI Inport mouse.
567637Snate */
568637Snatestatic void
569637Snatemse_disableati(port)
570637Snate	register u_int port;
571637Snate{
572637Snate
573637Snate	outb(port + MSE_PORTA, MSE_INPORT_MODE);
574637Snate	outb(port + MSE_PORTB, 0);
575637Snate}
576637Snate
577637Snate/*
578637Snate * Get current dx, dy and up/down button state.
579637Snate */
580637Snatestatic void
581637Snatemse_getati(port, dx, dy, but)
582637Snate	register u_int port;
583637Snate	int *dx;
584637Snate	int *dy;
585637Snate	int *but;
586637Snate{
587637Snate	register char byte;
588637Snate
589637Snate	outb(port + MSE_PORTA, MSE_INPORT_MODE);
590637Snate	outb(port + MSE_PORTB, MSE_INPORT_HOLD);
591637Snate	outb(port + MSE_PORTA, MSE_INPORT_STATUS);
592637Snate	*but = ~(inb(port + MSE_PORTB) & 0x7);
593637Snate	outb(port + MSE_PORTA, MSE_INPORT_DX);
594637Snate	byte = inb(port + MSE_PORTB);
595637Snate	*dx += byte;
596637Snate	outb(port + MSE_PORTA, MSE_INPORT_DY);
597637Snate	byte = inb(port + MSE_PORTB);
598637Snate	*dy += byte;
599637Snate	outb(port + MSE_PORTA, MSE_INPORT_MODE);
600637Snate	outb(port + MSE_PORTB, MSE_INPORT_INTREN);
601637Snate}
60212502Sjulian
60312502Sjulianstatic mse_devsw_installed = 0;
60412502Sjulian
60512517Sjulianstatic void 	mse_drvinit(void *unused)
60612502Sjulian{
60712517Sjulian	dev_t dev;
60812517Sjulian
60912502Sjulian	if( ! mse_devsw_installed ) {
61012675Sjulian		dev = makedev(CDEV_MAJOR, 0);
61112675Sjulian		cdevsw_add(&dev,&mse_cdevsw, NULL);
61212502Sjulian		mse_devsw_installed = 1;
61312517Sjulian    	}
61412502Sjulian}
61512517Sjulian
61612517SjulianSYSINIT(msedev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,mse_drvinit,NULL)
61712517Sjulian
61812517Sjulian
619637Snate#endif /* NMSE */
620