mse.c revision 12658
1168404Spjd/*
2168404Spjd * Copyright 1992 by the University of Guelph
3168404Spjd *
4168404Spjd * Permission to use, copy and modify this
5168404Spjd * software and its documentation for any purpose and without
6168404Spjd * fee is hereby granted, provided that the above copyright
7168404Spjd * notice appear in all copies and that both that copyright
8168404Spjd * notice and this permission notice appear in supporting
9168404Spjd * documentation.
10168404Spjd * University of Guelph makes no representations about the suitability of
11168404Spjd * this software for any purpose.  It is provided "as is"
12168404Spjd * without express or implied warranty.
13168404Spjd *
14168404Spjd * $Id: mse.c,v 1.18 1995/11/29 14:39:47 julian Exp $
15168404Spjd */
16168404Spjd/*
17168404Spjd * Driver for the Logitech and ATI Inport Bus mice for use with 386bsd and
18168404Spjd * the X386 port, courtesy of
19168404Spjd * Rick Macklem, rick@snowhite.cis.uoguelph.ca
20168404Spjd * Caveats: The driver currently uses spltty(), but doesn't use any
21168404Spjd * generic tty code. It could use splmse() (that only masks off the
22168404Spjd * bus mouse interrupt, but that would require hacking in i386/isa/icu.s.
23168404Spjd * (This may be worth the effort, since the Logitech generates 30/60
24236155Smm * interrupts/sec continuously while it is open.)
25236155Smm * NB: The ATI has NOT been tested yet!
26168404Spjd */
27168404Spjd
28168404Spjd/*
29168404Spjd * Modification history:
30168404Spjd * Sep 6, 1994 -- Lars Fredriksen(fredriks@mcs.com)
31168404Spjd *   improved probe based on input from Logitech.
32169303Spjd *
33168404Spjd * Oct 19, 1992 -- E. Stark (stark@cs.sunysb.edu)
34205346Spjd *   fixes to make it work with Microsoft InPort busmouse
35168404Spjd *
36168404Spjd * Jan, 1993 -- E. Stark (stark@cs.sunysb.edu)
37168404Spjd *   added patches for new "select" interface
38168404Spjd *
39169303Spjd * May 4, 1993 -- E. Stark (stark@cs.sunysb.edu)
40168404Spjd *   changed position of some spl()'s in mseread
41168404Spjd *
42168404Spjd * October 8, 1993 -- E. Stark (stark@cs.sunysb.edu)
43168404Spjd *   limit maximum negative x/y value to -127 to work around XFree problem
44168404Spjd *   that causes spurious button pushes.
45256956Ssmh */
46168404Spjd
47168404Spjd#include "mse.h"
48168404Spjd#if NMSE > 0
49256956Ssmh#include <sys/param.h>
50168404Spjd#include <sys/systm.h>
51168404Spjd#include <sys/conf.h>
52168404Spjd#include <sys/proc.h>
53168404Spjd#include <sys/buf.h>
54240868Spjd#include <sys/kernel.h>
55240868Spjd#include <sys/ioctl.h>
56267992Shselasky#include <sys/uio.h>
57267992Shselasky#include <sys/devconf.h>
58219089Spjd
59240868Spjd#include <machine/clock.h>
60267992Shselasky
61267992Shselasky#include <i386/isa/isa_device.h>
62240868Spjd#include <i386/isa/icu.h>
63219089Spjd
64168404Spjd#ifdef JREMOD
65256956Ssmh#include <sys/conf.h>
66256956Ssmh#include <sys/kernel.h>
67256956Ssmh#ifdef DEVFS
68256956Ssmh#include <sys/devfsext.h>
69256956Ssmh#endif /*DEVFS*/
70256956Ssmh#define CDEV_MAJOR 27
71256956Ssmh#endif /*JREMOD*/
72256956Ssmh
73256956Ssmhstatic int mseprobe(struct isa_device *);
74256956Ssmhstatic int mseattach(struct isa_device *);
75256956Ssmh
76256956Ssmhstruct	isa_driver msedriver = {
77256956Ssmh	mseprobe, mseattach, "mse"
78256956Ssmh};
79256956Ssmh
80256956Ssmh/*
81256956Ssmh * Software control structure for mouse. The sc_enablemouse(),
82256956Ssmh * sc_disablemouse() and sc_getmouse() routines must be called spl'd().
83256956Ssmh */
84256956Ssmh#define	PROTOBYTES	5
85256956Ssmhstruct mse_softc {
86256956Ssmh	int	sc_flags;
87256956Ssmh	int	sc_mousetype;
88256956Ssmh	struct	selinfo sc_selp;
89256956Ssmh	u_int	sc_port;
90256956Ssmh	void	(*sc_enablemouse)();
91256956Ssmh	void	(*sc_disablemouse)();
92256956Ssmh	void	(*sc_getmouse)();
93168404Spjd	int	sc_deltax;
94168404Spjd	int	sc_deltay;
95168404Spjd	int	sc_obuttons;
96168404Spjd	int	sc_buttons;
97168404Spjd	int	sc_bytesread;
98168404Spjd	u_char	sc_bytes[PROTOBYTES];
99168404Spjd} mse_sc[NMSE];
100253754Smav
101253754Smav/* Flags */
102168404Spjd#define	MSESC_OPEN	0x1
103219089Spjd#define	MSESC_WANT	0x2
104219089Spjd
105219089Spjd/* and Mouse Types */
106219089Spjd#define	MSE_LOGITECH	0x1
107219089Spjd#define	MSE_ATIINPORT	0x2
108219089Spjd#define	MSE_LOGI_SIG	0xA5
109219089Spjd
110219089Spjd#define	MSE_PORTA	0
111219089Spjd#define	MSE_PORTB	1
112219089Spjd#define	MSE_PORTC	2
113219089Spjd#define	MSE_PORTD	3
114219089Spjd
115219089Spjd#define	MSE_UNIT(dev)		(minor(dev) >> 1)
116219089Spjd#define	MSE_NBLOCKIO(dev)	(minor(dev) & 0x1)
117219089Spjd
118185029Spjd/*
119185029Spjd * Logitech bus mouse definitions
120168404Spjd */
121168404Spjd#define	MSE_SETUP	0x91	/* What does this mean? */
122168404Spjd				/* The definition for the control port */
123203504Spjd				/* is as follows: */
124168404Spjd
125168404Spjd				/* D7 	 =  Mode set flag (1 = active) 	*/
126168404Spjd				/* D6,D5 =  Mode selection (port A) 	*/
127168404Spjd				/* 	    00 = Mode 0 = Basic I/O 	*/
128168404Spjd				/* 	    01 = Mode 1 = Strobed I/O 	*/
129168404Spjd				/* 	    10 = Mode 2 = Bi-dir bus 	*/
130168404Spjd				/* D4	 =  Port A direction (1 = input)*/
131168404Spjd				/* D3	 =  Port C (upper 4 bits) 	*/
132168404Spjd				/*	    direction. (1 = input)	*/
133169303Spjd				/* D2	 =  Mode selection (port B & C) */
134169303Spjd				/*	    0 = Mode 0 = Basic I/O	*/
135169303Spjd				/*	    1 = Mode 1 = Strobed I/O	*/
136169303Spjd				/* D1	 =  Port B direction (1 = input)*/
137169303Spjd				/* D0	 =  Port C (lower 4 bits)	*/
138168404Spjd				/*	    direction. (1 = input)	*/
139168404Spjd
140168404Spjd				/* So 91 means Basic I/O on all 3 ports,*/
141168404Spjd				/* Port A is an input port, B is an 	*/
142168404Spjd				/* output port, C is split with upper	*/
143168404Spjd				/* 4 bits being an output port and lower*/
144168404Spjd				/* 4 bits an input port, and enable the */
145168404Spjd				/* sucker.				*/
146168404Spjd				/* Courtesy Intel 8255 databook. Lars   */
147203504Spjd#define	MSE_HOLD	0x80
148168404Spjd#define	MSE_RXLOW	0x00
149168404Spjd#define	MSE_RXHIGH	0x20
150168404Spjd#define	MSE_RYLOW	0x40
151168404Spjd#define	MSE_RYHIGH	0x60
152168404Spjd#define	MSE_DISINTR	0x10
153168404Spjd#define MSE_INTREN	0x00
154168404Spjd
155168404Spjdstatic int mse_probelogi();
156168404Spjdstatic void mse_enablelogi(), mse_disablelogi(), mse_getlogi();
157168404Spjd
158168404Spjd/*
159168404Spjd * ATI Inport mouse definitions
160168404Spjd */
161168404Spjd#define	MSE_INPORT_RESET	0x80
162168404Spjd#define	MSE_INPORT_STATUS	0x00
163168404Spjd#define	MSE_INPORT_DX		0x01
164168404Spjd#define	MSE_INPORT_DY		0x02
165168404Spjd#define	MSE_INPORT_MODE		0x07
166203504Spjd#define	MSE_INPORT_HOLD		0x20
167168404Spjd#define	MSE_INPORT_INTREN	0x09
168168404Spjd
169168404Spjdstatic int mse_probeati();
170168404Spjdstatic void mse_enableati(), mse_disableati(), mse_getati();
171168404Spjd
172168404Spjd#define	MSEPRI	(PZERO + 3)
173203504Spjd
174168404Spjd/*
175168404Spjd * Table of mouse types.
176168404Spjd * Keep the Logitech last, since I haven't figured out how to probe it
177168404Spjd * properly yet. (Someday I'll have the documentation.)
178256880Smav */
179168404Spjdstruct mse_types {
180168404Spjd	int	m_type;		/* Type of bus mouse */
181168404Spjd	int	(*m_probe)();	/* Probe routine to test for it */
182168404Spjd	void	(*m_enable)();	/* Start routine */
183168404Spjd	void	(*m_disable)();	/* Disable interrupts routine */
184168404Spjd	void	(*m_get)();	/* and get mouse status */
185168404Spjd} mse_types[] = {
186168404Spjd	{ MSE_ATIINPORT, mse_probeati, mse_enableati, mse_disableati, mse_getati },
187168404Spjd	{ MSE_LOGITECH, mse_probelogi, mse_enablelogi, mse_disablelogi, mse_getlogi },
188168404Spjd	{ 0, },
189168404Spjd};
190168404Spjd
191168404Spjdstatic struct kern_devconf kdc_mse[NMSE] = { {
192168404Spjd	0, 0, 0,		/* filled in by dev_attach */
193168404Spjd	"mse", 0, { MDDT_ISA, 0, "tty" },
194168404Spjd	isa_generic_externalize, 0, 0, ISA_EXTERNALLEN,
195168404Spjd	&kdc_isa0,		/* parent */
196168404Spjd	0,			/* parentdata */
197168404Spjd	DC_UNCONFIGURED,	/* state */
198168404Spjd	"ATI or Logitech bus mouse adapter",
199168404Spjd	DC_CLS_MISC		/* class */
200168404Spjd} };
201168404Spjd
202168404Spjdstatic inline void
203168404Spjdmse_registerdev(struct isa_device *id)
204168404Spjd{
205168404Spjd	if(id->id_unit)
206168404Spjd		kdc_mse[id->id_unit] = kdc_mse[0];
207168404Spjd	kdc_mse[id->id_unit].kdc_unit = id->id_unit;
208168404Spjd	kdc_mse[id->id_unit].kdc_isa = id;
209185029Spjd	dev_attach(&kdc_mse[id->id_unit]);
210185029Spjd}
211185029Spjd
212185029Spjdint
213185029Spjdmseprobe(idp)
214241286Savg	register struct isa_device *idp;
215241286Savg{
216241286Savg	register struct mse_softc *sc = &mse_sc[idp->id_unit];
217185029Spjd	register int i;
218185029Spjd
219185029Spjd	mse_registerdev(idp);
220185029Spjd	/*
221185029Spjd	 * Check for each mouse type in the table.
222185029Spjd	 */
223185029Spjd	i = 0;
224208682Spjd	while (mse_types[i].m_type) {
225185029Spjd		if ((*mse_types[i].m_probe)(idp)) {
226185029Spjd			sc->sc_mousetype = mse_types[i].m_type;
227185029Spjd			sc->sc_enablemouse = mse_types[i].m_enable;
228185029Spjd			sc->sc_disablemouse = mse_types[i].m_disable;
229185029Spjd			sc->sc_getmouse = mse_types[i].m_get;
230185029Spjd			return (1);
231185029Spjd		}
232185029Spjd		i++;
233185029Spjd	}
234208682Spjd	return (0);
235185029Spjd}
236185029Spjd
237208682Spjdint
238185029Spjdmseattach(idp)
239185029Spjd	struct isa_device *idp;
240185029Spjd{
241185029Spjd	struct mse_softc *sc = &mse_sc[idp->id_unit];
242208682Spjd
243185029Spjd	sc->sc_port = idp->id_iobase;
244185029Spjd	kdc_mse[idp->id_unit].kdc_state = DC_IDLE;
245185029Spjd	return (1);
246185029Spjd}
247185029Spjd
248185029Spjd/*
249185029Spjd * Exclusive open the mouse, initialize it and enable interrupts.
250185029Spjd */
251185029Spjdint
252185029Spjdmseopen(dev, flags, fmt, p)
253185029Spjd	dev_t dev;
254241286Savg	int flags;
255241286Savg	int fmt;
256185029Spjd	struct proc *p;
257241286Savg{
258241286Savg	register struct mse_softc *sc;
259241286Savg	int s;
260241286Savg
261241286Savg	if (MSE_UNIT(dev) >= NMSE)
262241286Savg		return (ENXIO);
263241286Savg	sc = &mse_sc[MSE_UNIT(dev)];
264241286Savg	if (sc->sc_flags & MSESC_OPEN)
265185029Spjd		return (EBUSY);
266185029Spjd	sc->sc_flags |= MSESC_OPEN;
267185029Spjd	kdc_mse[MSE_UNIT(dev)].kdc_state = DC_BUSY;
268185029Spjd	sc->sc_obuttons = sc->sc_buttons = 0x7;
269185029Spjd	sc->sc_deltax = sc->sc_deltay = 0;
270185029Spjd	sc->sc_bytesread = PROTOBYTES;
271241286Savg
272219089Spjd	/*
273185029Spjd	 * Initialize mouse interface and enable interrupts.
274185029Spjd	 */
275185029Spjd	s = spltty();
276185029Spjd	(*sc->sc_enablemouse)(sc->sc_port);
277241286Savg	splx(s);
278185029Spjd	return (0);
279185029Spjd}
280185029Spjd
281185029Spjd/*
282185029Spjd * mseclose: just turn off mouse innterrupts.
283185029Spjd */
284185029Spjdint
285185174Spjdmseclose(dev, flags, fmt, p)
286185029Spjd	dev_t dev;
287185029Spjd	int flags;
288185029Spjd	int fmt;
289241286Savg	struct proc *p;
290185174Spjd{
291185029Spjd	struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
292185029Spjd	int s;
293185029Spjd
294185029Spjd	s = spltty();
295185029Spjd	(*sc->sc_disablemouse)(sc->sc_port);
296200124Spjd	sc->sc_flags &= ~MSESC_OPEN;
297185029Spjd	kdc_mse[MSE_UNIT(dev)].kdc_state = DC_IDLE;
298185029Spjd	splx(s);
299185029Spjd	return(0);
300241286Savg}
301185029Spjd
302185029Spjd/*
303241286Savg * mseread: return mouse info using the MSC serial protocol, but without
304252056Ssmh * using bytes 4 and 5.
305241286Savg * (Yes this is cheesy, but it makes the X386 server happy, so...)
306241286Savg */
307241286Savgint
308241286Savgmseread(dev, uio, ioflag)
309241286Savg	dev_t dev;
310242135Savg	struct uio *uio;
311242135Savg	int ioflag;
312242135Savg{
313241286Savg	register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
314241286Savg	int xfer, s, error;
315241286Savg
316241286Savg	/*
317241286Savg	 * If there are no protocol bytes to be read, set up a new protocol
318241286Savg	 * packet.
319185029Spjd	 */
320185029Spjd	s = spltty(); /* XXX Should be its own spl, but where is imlXX() */
321185029Spjd	if (sc->sc_bytesread >= PROTOBYTES) {
322241286Savg		while (sc->sc_deltax == 0 && sc->sc_deltay == 0 &&
323185029Spjd		       (sc->sc_obuttons ^ sc->sc_buttons) == 0) {
324185029Spjd			if (MSE_NBLOCKIO(dev)) {
325243502Savg				splx(s);
326243502Savg				return (0);
327241286Savg			}
328243502Savg			sc->sc_flags |= MSESC_WANT;
329243502Savg			if (error = tsleep((caddr_t)sc, MSEPRI | PCATCH,
330243502Savg				"mseread", 0)) {
331243502Savg				splx(s);
332243502Savg				return (error);
333244635Savg			}
334244635Savg		}
335243502Savg
336243502Savg		/*
337243502Savg		 * Generate protocol bytes.
338243502Savg		 * For some reason X386 expects 5 bytes but never uses
339243502Savg		 * the fourth or fifth?
340243502Savg		 */
341243502Savg		sc->sc_bytes[0] = 0x80 | (sc->sc_buttons & ~0xf8);
342243502Savg		if (sc->sc_deltax > 127)
343243502Savg			sc->sc_deltax = 127;
344243502Savg		if (sc->sc_deltax < -127)
345243502Savg			sc->sc_deltax = -127;
346243502Savg		sc->sc_deltay = -sc->sc_deltay;	/* Otherwise mousey goes wrong way */
347243502Savg		if (sc->sc_deltay > 127)
348243502Savg			sc->sc_deltay = 127;
349243502Savg		if (sc->sc_deltay < -127)
350243502Savg			sc->sc_deltay = -127;
351241286Savg		sc->sc_bytes[1] = sc->sc_deltax;
352243502Savg		sc->sc_bytes[2] = sc->sc_deltay;
353241286Savg		sc->sc_bytes[3] = sc->sc_bytes[4] = 0;
354243502Savg		sc->sc_obuttons = sc->sc_buttons;
355241286Savg		sc->sc_deltax = sc->sc_deltay = 0;
356243502Savg		sc->sc_bytesread = 0;
357241286Savg	}
358243502Savg	splx(s);
359243502Savg	xfer = min(uio->uio_resid, PROTOBYTES - sc->sc_bytesread);
360241286Savg	if (error = uiomove(&sc->sc_bytes[sc->sc_bytesread], xfer, uio))
361243502Savg		return (error);
362243502Savg	sc->sc_bytesread += xfer;
363241286Savg	return(0);
364243502Savg}
365243502Savg
366243502Savg/*
367243502Savg * mseselect: check for mouse input to be processed.
368243502Savg */
369243502Savgint
370243502Savgmseselect(dev, rw, p)
371243502Savg	dev_t dev;
372243502Savg	int rw;
373243502Savg	struct proc *p;
374243502Savg{
375243502Savg	register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
376243502Savg	int s;
377243502Savg
378243502Savg	s = spltty();
379243502Savg	if (sc->sc_bytesread != PROTOBYTES || sc->sc_deltax != 0 ||
380243502Savg	    sc->sc_deltay != 0 || (sc->sc_obuttons ^ sc->sc_buttons) != 0) {
381243502Savg		splx(s);
382243502Savg		return (1);
383243502Savg	}
384243502Savg
385243502Savg	/*
386243502Savg	 * Since this is an exclusive open device, any previous proc.
387243502Savg	 * pointer is trash now, so we can just assign it.
388243502Savg	 */
389243502Savg	selrecord(p, &sc->sc_selp);
390243502Savg	splx(s);
391243502Savg	return (0);
392243502Savg}
393241286Savg
394241286Savg/*
395241286Savg * mseintr: update mouse status. sc_deltax and sc_deltay are accumulative.
396241286Savg */
397241286Savgvoid
398241286Savgmseintr(unit)
399241286Savg	int unit;
400241286Savg{
401241286Savg	register struct mse_softc *sc = &mse_sc[unit];
402241286Savg	pid_t p;
403241286Savg
404259168Smav#ifdef DEBUG
405259168Smav	static int mse_intrcnt = 0;
406259168Smav	if((mse_intrcnt++ % 10000) == 0)
407259168Smav		printf("mseintr\n");
408259168Smav#endif /* DEBUG */
409259168Smav	if ((sc->sc_flags & MSESC_OPEN) == 0)
410259168Smav		return;
411259168Smav
412241286Savg	(*sc->sc_getmouse)(sc->sc_port, &sc->sc_deltax, &sc->sc_deltay, &sc->sc_buttons);
413241286Savg
414241286Savg	/*
415241286Savg	 * If mouse state has changed, wake up anyone wanting to know.
416241286Savg	 */
417169303Spjd	if (sc->sc_deltax != 0 || sc->sc_deltay != 0 ||
418242332Sdelphij	    (sc->sc_obuttons ^ sc->sc_buttons) != 0) {
419169303Spjd		if (sc->sc_flags & MSESC_WANT) {
420241286Savg			sc->sc_flags &= ~MSESC_WANT;
421241286Savg			wakeup((caddr_t)sc);
422241286Savg		}
423169303Spjd		selwakeup(&sc->sc_selp);
424241286Savg	}
425243502Savg}
426243502Savg
427241286Savg/*
428241286Savg * Routines for the Logitech mouse.
429241286Savg */
430241286Savg/*
431241286Savg * Test for a Logitech bus mouse and return 1 if it is.
432241286Savg * (until I know how to use the signature port properly, just disable
433243502Savg *  interrupts and return 1)
434241286Savg */
435241286Savgstatic int
436241286Savgmse_probelogi(idp)
437241286Savg	register struct isa_device *idp;
438241286Savg{
439241286Savg
440241286Savg	int sig;
441241286Savg
442241286Savg	outb(idp->id_iobase + MSE_PORTD, MSE_SETUP);
443241286Savg		/* set the signature port */
444243502Savg	outb(idp->id_iobase + MSE_PORTB, MSE_LOGI_SIG);
445243502Savg
446243502Savg	DELAY(30000); /* 30 ms delay */
447241286Savg	sig = inb(idp->id_iobase + MSE_PORTB) & 0xFF;
448241286Savg	if (sig == MSE_LOGI_SIG) {
449241286Savg		outb(idp->id_iobase + MSE_PORTC, MSE_DISINTR);
450241286Savg		return(1);
451241286Savg	} else {
452241286Savg		printf("mse%d: wrong signature %x\n",idp->id_unit,sig);
453241286Savg		return(0);
454241286Savg	}
455241286Savg}
456241286Savg
457241286Savg/*
458241286Savg * Initialize Logitech mouse and enable interrupts.
459241286Savg */
460241286Savgstatic void
461242332Sdelphijmse_enablelogi(port)
462241286Savg	register u_int port;
463241286Savg{
464241286Savg	int dx, dy, but;
465241286Savg
466243502Savg	outb(port + MSE_PORTD, MSE_SETUP);
467243502Savg	mse_getlogi(port, &dx, &dy, &but);
468241286Savg}
469241286Savg
470241286Savg/*
471241286Savg * Disable interrupts for Logitech mouse.
472241286Savg */
473241286Savgstatic void
474241286Savgmse_disablelogi(port)
475241286Savg	register u_int port;
476243502Savg{
477243502Savg
478169303Spjd	outb(port + MSE_PORTC, MSE_DISINTR);
479169303Spjd}
480241286Savg
481241286Savg/*
482241286Savg * Get the current dx, dy and button up/down state.
483241286Savg */
484241286Savgstatic void
485241286Savgmse_getlogi(port, dx, dy, but)
486241286Savg	register u_int port;
487241286Savg	int *dx;
488241286Savg	int *dy;
489241286Savg	int *but;
490241286Savg{
491241286Savg	register char x, y;
492241286Savg
493241286Savg	outb(port + MSE_PORTC, MSE_HOLD | MSE_RXLOW);
494241286Savg	x = inb(port + MSE_PORTA);
495241286Savg	*but = (x >> 5) & 0x7;
496219089Spjd	x &= 0xf;
497219089Spjd	outb(port + MSE_PORTC, MSE_HOLD | MSE_RXHIGH);
498169303Spjd	x |= (inb(port + MSE_PORTA) << 4);
499169303Spjd	outb(port + MSE_PORTC, MSE_HOLD | MSE_RYLOW);
500169303Spjd	y = (inb(port + MSE_PORTA) & 0xf);
501169303Spjd	outb(port + MSE_PORTC, MSE_HOLD | MSE_RYHIGH);
502219089Spjd	y |= (inb(port + MSE_PORTA) << 4);
503219089Spjd	*dx += x;
504169303Spjd	*dy += y;
505169303Spjd	outb(port + MSE_PORTC, MSE_INTREN);
506169303Spjd}
507169303Spjd
508169303Spjd/*
509169303Spjd * Routines for the ATI Inport bus mouse.
510169303Spjd */
511169303Spjd/*
512219089Spjd * Test for a ATI Inport bus mouse and return 1 if it is.
513169303Spjd * (do not enable interrupts)
514169303Spjd */
515169303Spjdstatic int
516169303Spjdmse_probeati(idp)
517169303Spjd	register struct isa_device *idp;
518169303Spjd{
519169303Spjd	int i;
520241286Savg
521169303Spjd	for (i = 0; i < 2; i++)
522169303Spjd		if (inb(idp->id_iobase + MSE_PORTC) == 0xde)
523219089Spjd			return (1);
524169303Spjd	return (0);
525242332Sdelphij}
526219089Spjd
527169303Spjd/*
528219089Spjd * Initialize ATI Inport mouse and enable interrupts.
529219089Spjd */
530207934Spjdstatic void
531203504Spjdmse_enableati(port)
532169303Spjd	register u_int port;
533169303Spjd{
534219089Spjd
535169303Spjd	outb(port + MSE_PORTA, MSE_INPORT_RESET);
536219089Spjd	outb(port + MSE_PORTA, MSE_INPORT_MODE);
537219089Spjd	outb(port + MSE_PORTB, MSE_INPORT_INTREN);
538169303Spjd}
539219089Spjd
540219089Spjd/*
541169303Spjd * Disable interrupts for ATI Inport mouse.
542169303Spjd */
543169303Spjdstatic void
544169303Spjdmse_disableati(port)
545169303Spjd	register u_int port;
546169303Spjd{
547169303Spjd
548185029Spjd	outb(port + MSE_PORTA, MSE_INPORT_MODE);
549185174Spjd	outb(port + MSE_PORTB, 0);
550168404Spjd}
551185174Spjd
552185174Spjd/*
553185174Spjd * Get current dx, dy and up/down button state.
554185174Spjd */
555219089Spjdstatic void
556219089Spjdmse_getati(port, dx, dy, but)
557185174Spjd	register u_int port;
558203504Spjd	int *dx;
559185174Spjd	int *dy;
560185174Spjd	int *but;
561185174Spjd{
562197842Spjd	register char byte;
563185174Spjd
564185174Spjd	outb(port + MSE_PORTA, MSE_INPORT_MODE);
565185174Spjd	outb(port + MSE_PORTB, MSE_INPORT_HOLD);
566185174Spjd	outb(port + MSE_PORTA, MSE_INPORT_STATUS);
567185174Spjd	*but = ~(inb(port + MSE_PORTB) & 0x7);
568185174Spjd	outb(port + MSE_PORTA, MSE_INPORT_DX);
569185174Spjd	byte = inb(port + MSE_PORTB);
570185174Spjd	*dx += byte;
571185174Spjd	outb(port + MSE_PORTA, MSE_INPORT_DY);
572185174Spjd	byte = inb(port + MSE_PORTB);
573185174Spjd	*dy += byte;
574185174Spjd	outb(port + MSE_PORTA, MSE_INPORT_MODE);
575185174Spjd	outb(port + MSE_PORTB, MSE_INPORT_INTREN);
576185174Spjd}
577185174Spjd
578200158Spjd#ifdef JREMOD
579185174Spjdstruct cdevsw mse_cdevsw =
580168404Spjd	{ mseopen,	mseclose,	mseread,	nowrite,	/*27*/
581168404Spjd	  noioc,	nostop,		nullreset,	nodevtotty,/* mse */
582185174Spjd	  mseselect,	nommap,		NULL };
583168404Spjd
584219089Spjdstatic mse_devsw_installed = 0;
585219089Spjd
586169303Spjdstatic void 	mse_drvinit(void *unused)
587168404Spjd{
588169303Spjd	dev_t dev;
589169303Spjd
590203504Spjd	if( ! mse_devsw_installed ) {
591218278Sae		dev = makedev(CDEV_MAJOR,0);
592218278Sae		cdevsw_add(&dev,&mse_cdevsw,NULL);
593169303Spjd		mse_devsw_installed = 1;
594185174Spjd#ifdef DEVFS
595169303Spjd		{
596185174Spjd			int x;
597169303Spjd/* default for a simple device with no probe routine (usually delete this) */
598169303Spjd			x=devfs_add_devsw(
599185174Spjd/*	path	name	devsw		minor	type   uid gid perm*/
600185174Spjd	"/",	"mse",	major(dev),	0,	DV_CHR,	0,  0, 0600);
601185174Spjd		}
602185174Spjd#endif
603185174Spjd    	}
604185029Spjd}
605185174Spjd
606169303SpjdSYSINIT(msedev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,mse_drvinit,NULL)
607168404Spjd
608169303Spjd#endif /* JREMOD */
609185029Spjd
610185029Spjd#endif /* NMSE */
611169303Spjd