mse.c revision 12502
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 *
1412502Sjulian * $Id: mse.c,v 1.15 1995/11/04 17:07:37 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>
512056Swollman#include <sys/proc.h>
522056Swollman#include <sys/user.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>
58637Snate
597430Sbde#include <machine/clock.h>
607430Sbde
612056Swollman#include <i386/isa/isa_device.h>
622056Swollman#include <i386/isa/icu.h>
63637Snate
6412502Sjulian#ifdef JREMOD
6512502Sjulian#include <sys/conf.h>
6612502Sjulian#define CDEV_MAJOR 27
6712502Sjulianstatic void 	mse_devsw_install();
6812502Sjulian#endif /*JREMOD*/
6912502Sjulian
70798Swollmanstatic int mseprobe(struct isa_device *);
71798Swollmanstatic int mseattach(struct isa_device *);
72637Snate
73637Snatestruct	isa_driver msedriver = {
74637Snate	mseprobe, mseattach, "mse"
75637Snate};
76637Snate
77637Snate/*
78637Snate * Software control structure for mouse. The sc_enablemouse(),
79637Snate * sc_disablemouse() and sc_getmouse() routines must be called spl'd().
80637Snate */
81637Snate#define	PROTOBYTES	5
82637Snatestruct mse_softc {
83637Snate	int	sc_flags;
84637Snate	int	sc_mousetype;
851549Srgrimes	struct	selinfo sc_selp;
86637Snate	u_int	sc_port;
87637Snate	void	(*sc_enablemouse)();
88637Snate	void	(*sc_disablemouse)();
89637Snate	void	(*sc_getmouse)();
90637Snate	int	sc_deltax;
91637Snate	int	sc_deltay;
92637Snate	int	sc_obuttons;
93637Snate	int	sc_buttons;
94637Snate	int	sc_bytesread;
95637Snate	u_char	sc_bytes[PROTOBYTES];
96637Snate} mse_sc[NMSE];
97637Snate
98637Snate/* Flags */
99637Snate#define	MSESC_OPEN	0x1
100637Snate#define	MSESC_WANT	0x2
101637Snate
102637Snate/* and Mouse Types */
103637Snate#define	MSE_LOGITECH	0x1
104637Snate#define	MSE_ATIINPORT	0x2
1054259Sjkh#define	MSE_LOGI_SIG	0xA5
106637Snate
107637Snate#define	MSE_PORTA	0
108637Snate#define	MSE_PORTB	1
109637Snate#define	MSE_PORTC	2
110637Snate#define	MSE_PORTD	3
111637Snate
112637Snate#define	MSE_UNIT(dev)		(minor(dev) >> 1)
113637Snate#define	MSE_NBLOCKIO(dev)	(minor(dev) & 0x1)
114637Snate
115637Snate/*
116637Snate * Logitech bus mouse definitions
117637Snate */
118637Snate#define	MSE_SETUP	0x91	/* What does this mean? */
1194259Sjkh				/* The definition for the control port */
1204259Sjkh				/* is as follows: */
1218876Srgrimes
1224259Sjkh				/* D7 	 =  Mode set flag (1 = active) 	*/
1238876Srgrimes				/* D6,D5 =  Mode selection (port A) 	*/
1244259Sjkh				/* 	    00 = Mode 0 = Basic I/O 	*/
1254259Sjkh				/* 	    01 = Mode 1 = Strobed I/O 	*/
1264259Sjkh				/* 	    10 = Mode 2 = Bi-dir bus 	*/
1274259Sjkh				/* D4	 =  Port A direction (1 = input)*/
1284259Sjkh				/* D3	 =  Port C (upper 4 bits) 	*/
1294259Sjkh				/*	    direction. (1 = input)	*/
1304259Sjkh				/* D2	 =  Mode selection (port B & C) */
1314259Sjkh				/*	    0 = Mode 0 = Basic I/O	*/
1324259Sjkh				/*	    1 = Mode 1 = Strobed I/O	*/
1334259Sjkh				/* D1	 =  Port B direction (1 = input)*/
1344259Sjkh				/* D0	 =  Port C (lower 4 bits)	*/
1354259Sjkh				/*	    direction. (1 = input)	*/
1368876Srgrimes
1374259Sjkh				/* So 91 means Basic I/O on all 3 ports,*/
1384259Sjkh				/* Port A is an input port, B is an 	*/
1394259Sjkh				/* output port, C is split with upper	*/
1404259Sjkh				/* 4 bits being an output port and lower*/
1414259Sjkh				/* 4 bits an input port, and enable the */
1424259Sjkh				/* sucker.				*/
1434259Sjkh				/* Courtesy Intel 8255 databook. Lars   */
144637Snate#define	MSE_HOLD	0x80
145637Snate#define	MSE_RXLOW	0x00
146637Snate#define	MSE_RXHIGH	0x20
147637Snate#define	MSE_RYLOW	0x40
148637Snate#define	MSE_RYHIGH	0x60
149637Snate#define	MSE_DISINTR	0x10
150637Snate#define MSE_INTREN	0x00
151637Snate
152637Snatestatic int mse_probelogi();
153637Snatestatic void mse_enablelogi(), mse_disablelogi(), mse_getlogi();
154637Snate
155637Snate/*
156637Snate * ATI Inport mouse definitions
157637Snate */
158637Snate#define	MSE_INPORT_RESET	0x80
159637Snate#define	MSE_INPORT_STATUS	0x00
160637Snate#define	MSE_INPORT_DX		0x01
161637Snate#define	MSE_INPORT_DY		0x02
162637Snate#define	MSE_INPORT_MODE		0x07
163637Snate#define	MSE_INPORT_HOLD		0x20
164637Snate#define	MSE_INPORT_INTREN	0x09
165637Snate
166637Snatestatic int mse_probeati();
167637Snatestatic void mse_enableati(), mse_disableati(), mse_getati();
168637Snate
169637Snate#define	MSEPRI	(PZERO + 3)
170637Snate
171637Snate/*
172637Snate * Table of mouse types.
173637Snate * Keep the Logitech last, since I haven't figured out how to probe it
174637Snate * properly yet. (Someday I'll have the documentation.)
175637Snate */
176637Snatestruct mse_types {
177637Snate	int	m_type;		/* Type of bus mouse */
178637Snate	int	(*m_probe)();	/* Probe routine to test for it */
179637Snate	void	(*m_enable)();	/* Start routine */
180637Snate	void	(*m_disable)();	/* Disable interrupts routine */
181637Snate	void	(*m_get)();	/* and get mouse status */
182637Snate} mse_types[] = {
183637Snate	{ MSE_ATIINPORT, mse_probeati, mse_enableati, mse_disableati, mse_getati },
184637Snate	{ MSE_LOGITECH, mse_probelogi, mse_enablelogi, mse_disablelogi, mse_getlogi },
185637Snate	{ 0, },
186637Snate};
187637Snate
1887780Swollmanstatic struct kern_devconf kdc_mse[NMSE] = { {
1897780Swollman	0, 0, 0,		/* filled in by dev_attach */
1907780Swollman	"mse", 0, { MDDT_ISA, 0, "tty" },
1917780Swollman	isa_generic_externalize, 0, 0, ISA_EXTERNALLEN,
1927780Swollman	&kdc_isa0,		/* parent */
1937780Swollman	0,			/* parentdata */
1947780Swollman	DC_UNCONFIGURED,	/* state */
1957780Swollman	"ATI or Logitech bus mouse adapter",
1967780Swollman	DC_CLS_MISC		/* class */
1977780Swollman} };
1987780Swollman
1997780Swollmanstatic inline void
2007780Swollmanmse_registerdev(struct isa_device *id)
2017780Swollman{
2027780Swollman	if(id->id_unit)
2037780Swollman		kdc_mse[id->id_unit] = kdc_mse[0];
2047780Swollman	kdc_mse[id->id_unit].kdc_unit = id->id_unit;
2057780Swollman	kdc_mse[id->id_unit].kdc_isa = id;
2067780Swollman	dev_attach(&kdc_mse[id->id_unit]);
2077780Swollman}
2087780Swollman
209798Swollmanint
210637Snatemseprobe(idp)
211637Snate	register struct isa_device *idp;
212637Snate{
213637Snate	register struct mse_softc *sc = &mse_sc[idp->id_unit];
214637Snate	register int i;
215637Snate
2167780Swollman	mse_registerdev(idp);
217637Snate	/*
218637Snate	 * Check for each mouse type in the table.
219637Snate	 */
220637Snate	i = 0;
221637Snate	while (mse_types[i].m_type) {
222637Snate		if ((*mse_types[i].m_probe)(idp)) {
223637Snate			sc->sc_mousetype = mse_types[i].m_type;
224637Snate			sc->sc_enablemouse = mse_types[i].m_enable;
225637Snate			sc->sc_disablemouse = mse_types[i].m_disable;
226637Snate			sc->sc_getmouse = mse_types[i].m_get;
227637Snate			return (1);
228637Snate		}
229637Snate		i++;
230637Snate	}
231637Snate	return (0);
232637Snate}
233637Snate
234798Swollmanint
235637Snatemseattach(idp)
236637Snate	struct isa_device *idp;
237637Snate{
238637Snate	struct mse_softc *sc = &mse_sc[idp->id_unit];
239637Snate
240637Snate	sc->sc_port = idp->id_iobase;
2417780Swollman	kdc_mse[idp->id_unit].kdc_state = DC_IDLE;
24212502Sjulian#ifdef JREMOD
24312502Sjulian	mse_devsw_install();
24412502Sjulian#endif /*JREMOD*/
245637Snate	return (1);
246637Snate}
247637Snate
248637Snate/*
249637Snate * Exclusive open the mouse, initialize it and enable interrupts.
250637Snate */
251798Swollmanint
25210624Sbdemseopen(dev, flags, fmt, p)
253637Snate	dev_t dev;
25410624Sbde	int flags;
25510624Sbde	int fmt;
25610624Sbde	struct proc *p;
257637Snate{
258637Snate	register struct mse_softc *sc;
259637Snate	int s;
260637Snate
261637Snate	if (MSE_UNIT(dev) >= NMSE)
262637Snate		return (ENXIO);
263637Snate	sc = &mse_sc[MSE_UNIT(dev)];
264637Snate	if (sc->sc_flags & MSESC_OPEN)
265637Snate		return (EBUSY);
266637Snate	sc->sc_flags |= MSESC_OPEN;
2677780Swollman	kdc_mse[MSE_UNIT(dev)].kdc_state = DC_BUSY;
268637Snate	sc->sc_obuttons = sc->sc_buttons = 0x7;
269637Snate	sc->sc_deltax = sc->sc_deltay = 0;
270637Snate	sc->sc_bytesread = PROTOBYTES;
271637Snate
272637Snate	/*
273637Snate	 * Initialize mouse interface and enable interrupts.
274637Snate	 */
275637Snate	s = spltty();
276637Snate	(*sc->sc_enablemouse)(sc->sc_port);
277637Snate	splx(s);
278637Snate	return (0);
279637Snate}
280637Snate
281637Snate/*
282637Snate * mseclose: just turn off mouse innterrupts.
283637Snate */
284798Swollmanint
28510624Sbdemseclose(dev, flags, fmt, p)
286798Swollman	dev_t dev;
28710624Sbde	int flags;
28810624Sbde	int fmt;
28910624Sbde	struct proc *p;
290637Snate{
291637Snate	struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
292637Snate	int s;
293637Snate
294637Snate	s = spltty();
295637Snate	(*sc->sc_disablemouse)(sc->sc_port);
296637Snate	sc->sc_flags &= ~MSESC_OPEN;
2977780Swollman	kdc_mse[MSE_UNIT(dev)].kdc_state = DC_IDLE;
298637Snate	splx(s);
299637Snate	return(0);
300637Snate}
301637Snate
3028876Srgrimes/*
303637Snate * mseread: return mouse info using the MSC serial protocol, but without
304637Snate * using bytes 4 and 5.
305637Snate * (Yes this is cheesy, but it makes the X386 server happy, so...)
306637Snate */
307798Swollmanint
30810624Sbdemseread(dev, uio, ioflag)
309637Snate	dev_t dev;
310637Snate	struct uio *uio;
31110624Sbde	int ioflag;
312637Snate{
313637Snate	register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
314637Snate	int xfer, s, error;
315637Snate
316637Snate	/*
317637Snate	 * If there are no protocol bytes to be read, set up a new protocol
318637Snate	 * packet.
319637Snate	 */
320637Snate	s = spltty(); /* XXX Should be its own spl, but where is imlXX() */
321637Snate	if (sc->sc_bytesread >= PROTOBYTES) {
322637Snate		while (sc->sc_deltax == 0 && sc->sc_deltay == 0 &&
323637Snate		       (sc->sc_obuttons ^ sc->sc_buttons) == 0) {
324637Snate			if (MSE_NBLOCKIO(dev)) {
325637Snate				splx(s);
326637Snate				return (0);
327637Snate			}
328637Snate			sc->sc_flags |= MSESC_WANT;
329637Snate			if (error = tsleep((caddr_t)sc, MSEPRI | PCATCH,
330637Snate				"mseread", 0)) {
331637Snate				splx(s);
332637Snate				return (error);
333637Snate			}
334637Snate		}
335637Snate
336637Snate		/*
337637Snate		 * Generate protocol bytes.
338637Snate		 * For some reason X386 expects 5 bytes but never uses
339637Snate		 * the fourth or fifth?
340637Snate		 */
341637Snate		sc->sc_bytes[0] = 0x80 | (sc->sc_buttons & ~0xf8);
342637Snate		if (sc->sc_deltax > 127)
343637Snate			sc->sc_deltax = 127;
344637Snate		if (sc->sc_deltax < -127)
345637Snate			sc->sc_deltax = -127;
346637Snate		sc->sc_deltay = -sc->sc_deltay;	/* Otherwise mousey goes wrong way */
347637Snate		if (sc->sc_deltay > 127)
348637Snate			sc->sc_deltay = 127;
349637Snate		if (sc->sc_deltay < -127)
350637Snate			sc->sc_deltay = -127;
351637Snate		sc->sc_bytes[1] = sc->sc_deltax;
352637Snate		sc->sc_bytes[2] = sc->sc_deltay;
353637Snate		sc->sc_bytes[3] = sc->sc_bytes[4] = 0;
354637Snate		sc->sc_obuttons = sc->sc_buttons;
355637Snate		sc->sc_deltax = sc->sc_deltay = 0;
356637Snate		sc->sc_bytesread = 0;
357637Snate	}
358637Snate	splx(s);
3591567Srgrimes	xfer = min(uio->uio_resid, PROTOBYTES - sc->sc_bytesread);
360637Snate	if (error = uiomove(&sc->sc_bytes[sc->sc_bytesread], xfer, uio))
361637Snate		return (error);
362637Snate	sc->sc_bytesread += xfer;
363637Snate	return(0);
364637Snate}
365637Snate
366637Snate/*
367637Snate * mseselect: check for mouse input to be processed.
368637Snate */
369798Swollmanint
370637Snatemseselect(dev, rw, p)
371637Snate	dev_t dev;
372637Snate	int rw;
373637Snate	struct proc *p;
374637Snate{
375637Snate	register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
376637Snate	int s;
377637Snate
378637Snate	s = spltty();
379637Snate	if (sc->sc_bytesread != PROTOBYTES || sc->sc_deltax != 0 ||
380637Snate	    sc->sc_deltay != 0 || (sc->sc_obuttons ^ sc->sc_buttons) != 0) {
381637Snate		splx(s);
382637Snate		return (1);
383637Snate	}
384637Snate
385637Snate	/*
386637Snate	 * Since this is an exclusive open device, any previous proc.
387637Snate	 * pointer is trash now, so we can just assign it.
388637Snate	 */
3891549Srgrimes	selrecord(p, &sc->sc_selp);
390637Snate	splx(s);
391637Snate	return (0);
392637Snate}
393637Snate
394637Snate/*
395637Snate * mseintr: update mouse status. sc_deltax and sc_deltay are accumulative.
396637Snate */
397798Swollmanvoid
398637Snatemseintr(unit)
399637Snate	int unit;
400637Snate{
401637Snate	register struct mse_softc *sc = &mse_sc[unit];
402637Snate	pid_t p;
403637Snate
404637Snate#ifdef DEBUG
405637Snate	static int mse_intrcnt = 0;
406637Snate	if((mse_intrcnt++ % 10000) == 0)
407637Snate		printf("mseintr\n");
408637Snate#endif /* DEBUG */
409637Snate	if ((sc->sc_flags & MSESC_OPEN) == 0)
410637Snate		return;
411637Snate
412637Snate	(*sc->sc_getmouse)(sc->sc_port, &sc->sc_deltax, &sc->sc_deltay, &sc->sc_buttons);
413637Snate
414637Snate	/*
415637Snate	 * If mouse state has changed, wake up anyone wanting to know.
416637Snate	 */
417637Snate	if (sc->sc_deltax != 0 || sc->sc_deltay != 0 ||
418637Snate	    (sc->sc_obuttons ^ sc->sc_buttons) != 0) {
4198876Srgrimes		if (sc->sc_flags & MSESC_WANT) {
4208876Srgrimes			sc->sc_flags &= ~MSESC_WANT;
4218876Srgrimes			wakeup((caddr_t)sc);
4228876Srgrimes		}
4231549Srgrimes		selwakeup(&sc->sc_selp);
424637Snate	}
425637Snate}
426637Snate
427637Snate/*
428637Snate * Routines for the Logitech mouse.
429637Snate */
430637Snate/*
431637Snate * Test for a Logitech bus mouse and return 1 if it is.
432637Snate * (until I know how to use the signature port properly, just disable
433637Snate *  interrupts and return 1)
434637Snate */
435637Snatestatic int
436637Snatemse_probelogi(idp)
437637Snate	register struct isa_device *idp;
438637Snate{
439637Snate
4404259Sjkh	int sig;
4414259Sjkh
4424259Sjkh	outb(idp->id_iobase + MSE_PORTD, MSE_SETUP);
4434259Sjkh		/* set the signature port */
4444259Sjkh	outb(idp->id_iobase + MSE_PORTB, MSE_LOGI_SIG);
4454259Sjkh
4464259Sjkh	DELAY(30000); /* 30 ms delay */
4474259Sjkh	sig = inb(idp->id_iobase + MSE_PORTB) & 0xFF;
4484259Sjkh	if (sig == MSE_LOGI_SIG) {
4494259Sjkh		outb(idp->id_iobase + MSE_PORTC, MSE_DISINTR);
4504259Sjkh		return(1);
4514259Sjkh	} else {
4528876Srgrimes		printf("mse%d: wrong signature %x\n",idp->id_unit,sig);
4534259Sjkh		return(0);
454637Snate	}
455637Snate}
456637Snate
457637Snate/*
458637Snate * Initialize Logitech mouse and enable interrupts.
459637Snate */
460637Snatestatic void
461637Snatemse_enablelogi(port)
462637Snate	register u_int port;
463637Snate{
464637Snate	int dx, dy, but;
465637Snate
466637Snate	outb(port + MSE_PORTD, MSE_SETUP);
467637Snate	mse_getlogi(port, &dx, &dy, &but);
468637Snate}
469637Snate
470637Snate/*
471637Snate * Disable interrupts for Logitech mouse.
472637Snate */
473637Snatestatic void
474637Snatemse_disablelogi(port)
475637Snate	register u_int port;
476637Snate{
477637Snate
478637Snate	outb(port + MSE_PORTC, MSE_DISINTR);
479637Snate}
480637Snate
481637Snate/*
482637Snate * Get the current dx, dy and button up/down state.
483637Snate */
484637Snatestatic void
485637Snatemse_getlogi(port, dx, dy, but)
486637Snate	register u_int port;
487637Snate	int *dx;
488637Snate	int *dy;
489637Snate	int *but;
490637Snate{
491637Snate	register char x, y;
492637Snate
493637Snate	outb(port + MSE_PORTC, MSE_HOLD | MSE_RXLOW);
494637Snate	x = inb(port + MSE_PORTA);
495637Snate	*but = (x >> 5) & 0x7;
496637Snate	x &= 0xf;
497637Snate	outb(port + MSE_PORTC, MSE_HOLD | MSE_RXHIGH);
498637Snate	x |= (inb(port + MSE_PORTA) << 4);
499637Snate	outb(port + MSE_PORTC, MSE_HOLD | MSE_RYLOW);
500637Snate	y = (inb(port + MSE_PORTA) & 0xf);
501637Snate	outb(port + MSE_PORTC, MSE_HOLD | MSE_RYHIGH);
502637Snate	y |= (inb(port + MSE_PORTA) << 4);
503637Snate	*dx += x;
504637Snate	*dy += y;
505637Snate	outb(port + MSE_PORTC, MSE_INTREN);
506637Snate}
507637Snate
508637Snate/*
509637Snate * Routines for the ATI Inport bus mouse.
510637Snate */
511637Snate/*
512637Snate * Test for a ATI Inport bus mouse and return 1 if it is.
513637Snate * (do not enable interrupts)
514637Snate */
515637Snatestatic int
516637Snatemse_probeati(idp)
517637Snate	register struct isa_device *idp;
518637Snate{
519637Snate	int i;
520637Snate
521637Snate	for (i = 0; i < 2; i++)
522637Snate		if (inb(idp->id_iobase + MSE_PORTC) == 0xde)
523637Snate			return (1);
524637Snate	return (0);
525637Snate}
526637Snate
527637Snate/*
528637Snate * Initialize ATI Inport mouse and enable interrupts.
529637Snate */
530637Snatestatic void
531637Snatemse_enableati(port)
532637Snate	register u_int port;
533637Snate{
534637Snate
535637Snate	outb(port + MSE_PORTA, MSE_INPORT_RESET);
536637Snate	outb(port + MSE_PORTA, MSE_INPORT_MODE);
537637Snate	outb(port + MSE_PORTB, MSE_INPORT_INTREN);
538637Snate}
539637Snate
540637Snate/*
541637Snate * Disable interrupts for ATI Inport mouse.
542637Snate */
543637Snatestatic void
544637Snatemse_disableati(port)
545637Snate	register u_int port;
546637Snate{
547637Snate
548637Snate	outb(port + MSE_PORTA, MSE_INPORT_MODE);
549637Snate	outb(port + MSE_PORTB, 0);
550637Snate}
551637Snate
552637Snate/*
553637Snate * Get current dx, dy and up/down button state.
554637Snate */
555637Snatestatic void
556637Snatemse_getati(port, dx, dy, but)
557637Snate	register u_int port;
558637Snate	int *dx;
559637Snate	int *dy;
560637Snate	int *but;
561637Snate{
562637Snate	register char byte;
563637Snate
564637Snate	outb(port + MSE_PORTA, MSE_INPORT_MODE);
565637Snate	outb(port + MSE_PORTB, MSE_INPORT_HOLD);
566637Snate	outb(port + MSE_PORTA, MSE_INPORT_STATUS);
567637Snate	*but = ~(inb(port + MSE_PORTB) & 0x7);
568637Snate	outb(port + MSE_PORTA, MSE_INPORT_DX);
569637Snate	byte = inb(port + MSE_PORTB);
570637Snate	*dx += byte;
571637Snate	outb(port + MSE_PORTA, MSE_INPORT_DY);
572637Snate	byte = inb(port + MSE_PORTB);
573637Snate	*dy += byte;
574637Snate	outb(port + MSE_PORTA, MSE_INPORT_MODE);
575637Snate	outb(port + MSE_PORTB, MSE_INPORT_INTREN);
576637Snate}
57712502Sjulian
57812502Sjulian#ifdef JREMOD
57912502Sjulianstruct cdevsw mse_cdevsw =
58012502Sjulian	{ mseopen,	mseclose,	mseread,	nowrite,	/*27*/
58112502Sjulian	  noioc,	nostop,		nullreset,	nodevtotty,/* mse */
58212502Sjulian	  mseselect,	nommap,		NULL };
58312502Sjulian
58412502Sjulianstatic mse_devsw_installed = 0;
58512502Sjulian
58612502Sjulianstatic void 	mse_devsw_install()
58712502Sjulian{
58812502Sjulian	dev_t descript;
58912502Sjulian	if( ! mse_devsw_installed ) {
59012502Sjulian		descript = makedev(CDEV_MAJOR,0);
59112502Sjulian		cdevsw_add(&descript,&mse_cdevsw,NULL);
59212502Sjulian#if defined(BDEV_MAJOR)
59312502Sjulian		descript = makedev(BDEV_MAJOR,0);
59412502Sjulian		bdevsw_add(&descript,&mse_bdevsw,NULL);
59512502Sjulian#endif /*BDEV_MAJOR*/
59612502Sjulian		mse_devsw_installed = 1;
59712502Sjulian	}
59812502Sjulian}
59912502Sjulian#endif /* JREMOD */
600637Snate#endif /* NMSE */
601