Deleted Added
full compact
1/*
2 * Copyright 1992 by the University of Guelph
3 *
4 * Permission to use, copy and modify this
5 * software and its documentation for any purpose and without
6 * fee is hereby granted, provided that the above copyright
7 * notice appear in all copies and that both that copyright
8 * notice and this permission notice appear in supporting
9 * documentation.
10 * University of Guelph makes no representations about the suitability of
11 * this software for any purpose. It is provided "as is"
12 * without express or implied warranty.
13 *
14 * $Id: mse.c,v 1.39 1998/10/22 05:58:39 bde Exp $
14 * $Id: mse.c,v 1.40 1999/04/28 10:52:43 dt Exp $
15 */
16/*
17 * Driver for the Logitech and ATI Inport Bus mice for use with 386bsd and
18 * the X386 port, courtesy of
19 * Rick Macklem, rick@snowhite.cis.uoguelph.ca
20 * Caveats: The driver currently uses spltty(), but doesn't use any
21 * generic tty code. It could use splmse() (that only masks off the
22 * bus mouse interrupt, but that would require hacking in i386/isa/icu.s.
23 * (This may be worth the effort, since the Logitech generates 30/60
24 * interrupts/sec continuously while it is open.)
25 * NB: The ATI has NOT been tested yet!
26 */
27
28/*
29 * Modification history:
30 * Sep 6, 1994 -- Lars Fredriksen(fredriks@mcs.com)
31 * improved probe based on input from Logitech.
32 *
33 * Oct 19, 1992 -- E. Stark (stark@cs.sunysb.edu)
34 * fixes to make it work with Microsoft InPort busmouse
35 *
36 * Jan, 1993 -- E. Stark (stark@cs.sunysb.edu)
37 * added patches for new "select" interface
38 *
39 * May 4, 1993 -- E. Stark (stark@cs.sunysb.edu)
40 * changed position of some spl()'s in mseread
41 *
42 * October 8, 1993 -- E. Stark (stark@cs.sunysb.edu)
43 * limit maximum negative x/y value to -127 to work around XFree problem
44 * that causes spurious button pushes.
45 */
46
47#include "mse.h"
48#if NMSE > 0
49#include "opt_devfs.h"
50
51#include <sys/param.h>
52#include <sys/systm.h>
53#include <sys/conf.h>
54#include <sys/kernel.h>
55#include <sys/poll.h>
56#include <sys/select.h>
57#include <sys/uio.h>
58#ifdef DEVFS
59#include <sys/devfsext.h>
60#endif /*DEVFS*/
61
62#include <machine/clock.h>
63#include <machine/mouse.h>
64
65#include <i386/isa/isa_device.h>
66
67/* driver configuration flags (config) */
68#define MSE_CONFIG_ACCEL 0x00f0 /* acceleration factor */
69#define MSE_CONFIG_FLAGS (MSE_CONFIG_ACCEL)
70
71static int mseprobe(struct isa_device *);
72static int mseattach(struct isa_device *);
73
74struct isa_driver msedriver = {
75 mseprobe, mseattach, "mse"
76};
77
78static d_open_t mseopen;
79static d_close_t mseclose;
80static d_read_t mseread;
81static d_ioctl_t mseioctl;
82static d_poll_t msepoll;
83
84#define CDEV_MAJOR 27
85static struct cdevsw mse_cdevsw =
86 { mseopen, mseclose, mseread, nowrite, /*27*/
87 mseioctl, nostop, nullreset, nodevtotty,/* mse */
88 msepoll, nommap, NULL, "mse", NULL, -1 };
89
90static ointhand2_t mseintr;
91
92/*
93 * Software control structure for mouse. The sc_enablemouse(),
94 * sc_disablemouse() and sc_getmouse() routines must be called spl'd().
95 */
96static struct mse_softc {
97 int sc_flags;
98 int sc_mousetype;
99 struct selinfo sc_selp;
100 u_int sc_port;
101 void (*sc_enablemouse) __P((u_int port));
102 void (*sc_disablemouse) __P((u_int port));
103 void (*sc_getmouse) __P((u_int port, int *dx, int *dy, int *but));
104 int sc_deltax;
105 int sc_deltay;
106 int sc_obuttons;
107 int sc_buttons;
108 int sc_bytesread;
109 u_char sc_bytes[MOUSE_SYS_PACKETSIZE];
110 mousehw_t hw;
111 mousemode_t mode;
112 mousestatus_t status;
113#ifdef DEVFS
114 void *devfs_token;
115 void *n_devfs_token;
116#endif
117} mse_sc[NMSE];
118
119/* Flags */
120#define MSESC_OPEN 0x1
121#define MSESC_WANT 0x2
122
123/* and Mouse Types */
124#define MSE_NONE 0 /* don't move this! */
125#define MSE_LOGITECH 0x1
126#define MSE_ATIINPORT 0x2
127#define MSE_LOGI_SIG 0xA5
128
129#define MSE_PORTA 0
130#define MSE_PORTB 1
131#define MSE_PORTC 2
132#define MSE_PORTD 3
133
134#define MSE_UNIT(dev) (minor(dev) >> 1)
135#define MSE_NBLOCKIO(dev) (minor(dev) & 0x1)
136
137/*
138 * Logitech bus mouse definitions
139 */
140#define MSE_SETUP 0x91 /* What does this mean? */
141 /* The definition for the control port */
142 /* is as follows: */
143
144 /* D7 = Mode set flag (1 = active) */
145 /* D6,D5 = Mode selection (port A) */
146 /* 00 = Mode 0 = Basic I/O */
147 /* 01 = Mode 1 = Strobed I/O */
148 /* 10 = Mode 2 = Bi-dir bus */
149 /* D4 = Port A direction (1 = input)*/
150 /* D3 = Port C (upper 4 bits) */
151 /* direction. (1 = input) */
152 /* D2 = Mode selection (port B & C) */
153 /* 0 = Mode 0 = Basic I/O */
154 /* 1 = Mode 1 = Strobed I/O */
155 /* D1 = Port B direction (1 = input)*/
156 /* D0 = Port C (lower 4 bits) */
157 /* direction. (1 = input) */
158
159 /* So 91 means Basic I/O on all 3 ports,*/
160 /* Port A is an input port, B is an */
161 /* output port, C is split with upper */
162 /* 4 bits being an output port and lower*/
163 /* 4 bits an input port, and enable the */
164 /* sucker. */
165 /* Courtesy Intel 8255 databook. Lars */
166#define MSE_HOLD 0x80
167#define MSE_RXLOW 0x00
168#define MSE_RXHIGH 0x20
169#define MSE_RYLOW 0x40
170#define MSE_RYHIGH 0x60
171#define MSE_DISINTR 0x10
172#define MSE_INTREN 0x00
173
174static int mse_probelogi __P((struct isa_device *idp));
175static void mse_disablelogi __P((u_int port));
176static void mse_getlogi __P((u_int port, int *dx, int *dy, int *but));
177static void mse_enablelogi __P((u_int port));
178
179/*
180 * ATI Inport mouse definitions
181 */
182#define MSE_INPORT_RESET 0x80
183#define MSE_INPORT_STATUS 0x00
184#define MSE_INPORT_DX 0x01
185#define MSE_INPORT_DY 0x02
186#define MSE_INPORT_MODE 0x07
187#define MSE_INPORT_HOLD 0x20
188#define MSE_INPORT_INTREN 0x09
189
190static int mse_probeati __P((struct isa_device *idp));
191static void mse_enableati __P((u_int port));
192static void mse_disableati __P((u_int port));
193static void mse_getati __P((u_int port, int *dx, int *dy, int *but));
194
195#define MSEPRI (PZERO + 3)
196
197/*
198 * Table of mouse types.
199 * Keep the Logitech last, since I haven't figured out how to probe it
200 * properly yet. (Someday I'll have the documentation.)
201 */
202static struct mse_types {
203 int m_type; /* Type of bus mouse */
204 int (*m_probe) __P((struct isa_device *idp));
205 /* Probe routine to test for it */
206 void (*m_enable) __P((u_int port));
207 /* Start routine */
208 void (*m_disable) __P((u_int port));
209 /* Disable interrupts routine */
210 void (*m_get) __P((u_int port, int *dx, int *dy, int *but));
211 /* and get mouse status */
212 mousehw_t m_hw; /* buttons iftype type model hwid */
213 mousemode_t m_mode; /* proto rate res accel level size mask */
214} mse_types[] = {
215 { MSE_ATIINPORT,
216 mse_probeati, mse_enableati, mse_disableati, mse_getati,
217 { 2, MOUSE_IF_INPORT, MOUSE_MOUSE, MOUSE_MODEL_GENERIC, 0, },
218 { MOUSE_PROTO_INPORT, -1, -1, 0, 0, MOUSE_MSC_PACKETSIZE,
219 { MOUSE_MSC_SYNCMASK, MOUSE_MSC_SYNC, }, }, },
220 { MSE_LOGITECH,
221 mse_probelogi, mse_enablelogi, mse_disablelogi, mse_getlogi,
222 { 2, MOUSE_IF_BUS, MOUSE_MOUSE, MOUSE_MODEL_GENERIC, 0, },
223 { MOUSE_PROTO_BUS, -1, -1, 0, 0, MOUSE_MSC_PACKETSIZE,
224 { MOUSE_MSC_SYNCMASK, MOUSE_MSC_SYNC, }, }, },
225 { 0, },
226};
227
228int
229mseprobe(idp)
230 register struct isa_device *idp;
231{
232 register struct mse_softc *sc = &mse_sc[idp->id_unit];
233 register int i;
234
235 /*
236 * Check for each mouse type in the table.
237 */
238 i = 0;
239 while (mse_types[i].m_type) {
240 if ((*mse_types[i].m_probe)(idp)) {
241 sc->sc_mousetype = mse_types[i].m_type;
242 sc->sc_enablemouse = mse_types[i].m_enable;
243 sc->sc_disablemouse = mse_types[i].m_disable;
244 sc->sc_getmouse = mse_types[i].m_get;
245 sc->hw = mse_types[i].m_hw;
246 sc->mode = mse_types[i].m_mode;
247 return (1);
248 }
249 i++;
250 }
251 return (0);
252}
253
254int
255mseattach(idp)
256 struct isa_device *idp;
257{
258 int unit = idp->id_unit;
259 struct mse_softc *sc = &mse_sc[unit];
260
261 idp->id_ointr = mseintr;
262 sc->sc_port = idp->id_iobase;
263 sc->mode.accelfactor = (idp->id_flags & MSE_CONFIG_ACCEL) >> 4;
264#ifdef DEVFS
265 sc->devfs_token =
266 devfs_add_devswf(&mse_cdevsw, unit << 1, DV_CHR, 0, 0,
267 0600, "mse%d", unit);
268 sc->n_devfs_token =
269 devfs_add_devswf(&mse_cdevsw, (unit<<1)+1, DV_CHR,0, 0,
270 0600, "nmse%d", unit);
271#endif
272 return (1);
273}
274
275/*
276 * Exclusive open the mouse, initialize it and enable interrupts.
277 */
278static int
279mseopen(dev, flags, fmt, p)
280 dev_t dev;
281 int flags;
282 int fmt;
283 struct proc *p;
284{
285 register struct mse_softc *sc;
286 int s;
287
288 if (MSE_UNIT(dev) >= NMSE)
289 return (ENXIO);
290 sc = &mse_sc[MSE_UNIT(dev)];
291 if (sc->sc_mousetype == MSE_NONE)
292 return (ENXIO);
293 if (sc->sc_flags & MSESC_OPEN)
294 return (EBUSY);
295 sc->sc_flags |= MSESC_OPEN;
296 sc->sc_obuttons = sc->sc_buttons = MOUSE_MSC_BUTTONS;
297 sc->sc_deltax = sc->sc_deltay = 0;
298 sc->sc_bytesread = sc->mode.packetsize = MOUSE_MSC_PACKETSIZE;
299 sc->mode.level = 0;
300 sc->status.flags = 0;
301 sc->status.button = sc->status.obutton = 0;
302 sc->status.dx = sc->status.dy = sc->status.dz = 0;
303
304 /*
305 * Initialize mouse interface and enable interrupts.
306 */
307 s = spltty();
308 (*sc->sc_enablemouse)(sc->sc_port);
309 splx(s);
310 return (0);
311}
312
313/*
314 * mseclose: just turn off mouse innterrupts.
315 */
316static int
317mseclose(dev, flags, fmt, p)
318 dev_t dev;
319 int flags;
320 int fmt;
321 struct proc *p;
322{
323 struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
324 int s;
325
326 s = spltty();
327 (*sc->sc_disablemouse)(sc->sc_port);
328 sc->sc_flags &= ~MSESC_OPEN;
329 splx(s);
330 return(0);
331}
332
333/*
334 * mseread: return mouse info using the MSC serial protocol, but without
335 * using bytes 4 and 5.
336 * (Yes this is cheesy, but it makes the X386 server happy, so...)
337 */
338static int
339mseread(dev, uio, ioflag)
340 dev_t dev;
341 struct uio *uio;
342 int ioflag;
343{
344 register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
345 int xfer, s, error;
346
347 /*
348 * If there are no protocol bytes to be read, set up a new protocol
349 * packet.
350 */
351 s = spltty(); /* XXX Should be its own spl, but where is imlXX() */
352 if (sc->sc_bytesread >= sc->mode.packetsize) {
353 while (sc->sc_deltax == 0 && sc->sc_deltay == 0 &&
354 (sc->sc_obuttons ^ sc->sc_buttons) == 0) {
355 if (MSE_NBLOCKIO(dev)) {
356 splx(s);
357 return (0);
358 }
359 sc->sc_flags |= MSESC_WANT;
360 if (error = tsleep((caddr_t)sc, MSEPRI | PCATCH,
361 "mseread", 0)) {
362 splx(s);
363 return (error);
364 }
365 }
366
367 /*
368 * Generate protocol bytes.
369 * For some reason X386 expects 5 bytes but never uses
370 * the fourth or fifth?
371 */
372 sc->sc_bytes[0] = sc->mode.syncmask[1]
373 | (sc->sc_buttons & ~sc->mode.syncmask[0]);
374 if (sc->sc_deltax > 127)
375 sc->sc_deltax = 127;
376 if (sc->sc_deltax < -127)
377 sc->sc_deltax = -127;
378 sc->sc_deltay = -sc->sc_deltay; /* Otherwise mousey goes wrong way */
379 if (sc->sc_deltay > 127)
380 sc->sc_deltay = 127;
381 if (sc->sc_deltay < -127)
382 sc->sc_deltay = -127;
383 sc->sc_bytes[1] = sc->sc_deltax;
384 sc->sc_bytes[2] = sc->sc_deltay;
385 sc->sc_bytes[3] = sc->sc_bytes[4] = 0;
386 sc->sc_bytes[5] = sc->sc_bytes[6] = 0;
387 sc->sc_bytes[7] = MOUSE_SYS_EXTBUTTONS;
388 sc->sc_obuttons = sc->sc_buttons;
389 sc->sc_deltax = sc->sc_deltay = 0;
390 sc->sc_bytesread = 0;
391 }
392 splx(s);
393 xfer = min(uio->uio_resid, sc->mode.packetsize - sc->sc_bytesread);
394 if (error = uiomove(&sc->sc_bytes[sc->sc_bytesread], xfer, uio))
395 return (error);
396 sc->sc_bytesread += xfer;
397 return(0);
398}
399
400/*
401 * mseioctl: process ioctl commands.
402 */
403static int
404mseioctl(dev, cmd, addr, flag, p)
405 dev_t dev;
406 u_long cmd;
407 caddr_t addr;
408 int flag;
409 struct proc *p;
410{
411 register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
412 mousestatus_t status;
413 int err = 0;
414 int s;
415
416 switch (cmd) {
417
418 case MOUSE_GETHWINFO:
419 s = spltty();
420 *(mousehw_t *)addr = sc->hw;
421 if (sc->mode.level == 0)
422 ((mousehw_t *)addr)->model = MOUSE_MODEL_GENERIC;
423 splx(s);
424 break;
425
426 case MOUSE_GETMODE:
427 s = spltty();
428 *(mousemode_t *)addr = sc->mode;
429 switch (sc->mode.level) {
430 case 0:
431 break;
432 case 1:
433 ((mousemode_t *)addr)->protocol = MOUSE_PROTO_SYSMOUSE;
434 ((mousemode_t *)addr)->syncmask[0] = MOUSE_SYS_SYNCMASK;
435 ((mousemode_t *)addr)->syncmask[1] = MOUSE_SYS_SYNC;
436 break;
437 }
438 splx(s);
439 break;
440
441 case MOUSE_SETMODE:
442 switch (((mousemode_t *)addr)->level) {
443 case 0:
444 case 1:
445 break;
446 default:
447 return (EINVAL);
448 }
449 if (((mousemode_t *)addr)->accelfactor < -1)
450 return (EINVAL);
451 else if (((mousemode_t *)addr)->accelfactor >= 0)
452 sc->mode.accelfactor =
453 ((mousemode_t *)addr)->accelfactor;
454 sc->mode.level = ((mousemode_t *)addr)->level;
455 switch (sc->mode.level) {
456 case 0:
457 sc->sc_bytesread = sc->mode.packetsize
458 = MOUSE_MSC_PACKETSIZE;
459 break;
460 case 1:
461 sc->sc_bytesread = sc->mode.packetsize
462 = MOUSE_SYS_PACKETSIZE;
463 break;
464 }
465 break;
466
467 case MOUSE_GETLEVEL:
468 *(int *)addr = sc->mode.level;
469 break;
470
471 case MOUSE_SETLEVEL:
472 switch (*(int *)addr) {
473 case 0:
474 sc->mode.level = *(int *)addr;
475 sc->sc_bytesread = sc->mode.packetsize
476 = MOUSE_MSC_PACKETSIZE;
477 break;
478 case 1:
479 sc->mode.level = *(int *)addr;
480 sc->sc_bytesread = sc->mode.packetsize
481 = MOUSE_SYS_PACKETSIZE;
482 break;
483 default:
484 return (EINVAL);
485 }
486 break;
487
488 case MOUSE_GETSTATUS:
489 s = spltty();
490 status = sc->status;
491 sc->status.flags = 0;
492 sc->status.obutton = sc->status.button;
493 sc->status.button = 0;
494 sc->status.dx = 0;
495 sc->status.dy = 0;
496 sc->status.dz = 0;
497 splx(s);
498 *(mousestatus_t *)addr = status;
499 break;
500
501 case MOUSE_READSTATE:
502 case MOUSE_READDATA:
503 return (ENODEV);
504
505#if (defined(MOUSE_GETVARS))
506 case MOUSE_GETVARS:
507 case MOUSE_SETVARS:
508 return (ENODEV);
509#endif
510
511 default:
512 return (ENOTTY);
513 }
514 return (err);
515}
516
517/*
518 * msepoll: check for mouse input to be processed.
519 */
520static int
521msepoll(dev, events, p)
522 dev_t dev;
523 int events;
524 struct proc *p;
525{
526 register struct mse_softc *sc = &mse_sc[MSE_UNIT(dev)];
527 int s;
528 int revents = 0;
529
530 s = spltty();
531 if (events & (POLLIN | POLLRDNORM))
531 if (events & (POLLIN | POLLRDNORM)) {
532 if (sc->sc_bytesread != sc->mode.packetsize ||
533 sc->sc_deltax != 0 || sc->sc_deltay != 0 ||
534 (sc->sc_obuttons ^ sc->sc_buttons) != 0)
535 revents |= events & (POLLIN | POLLRDNORM);
536 else {
537 /*
538 * Since this is an exclusive open device, any previous
539 * proc pointer is trash now, so we can just assign it.
540 */
541 selrecord(p, &sc->sc_selp);
542 }
543
543 }
544 splx(s);
545 return (revents);
546}
547
548/*
549 * mseintr: update mouse status. sc_deltax and sc_deltay are accumulative.
550 */
551static void
552mseintr(unit)
553 int unit;
554{
555 /*
556 * the table to turn MouseSystem button bits (MOUSE_MSC_BUTTON?UP)
557 * into `mousestatus' button bits (MOUSE_BUTTON?DOWN).
558 */
559 static int butmap[8] = {
560 0,
561 MOUSE_BUTTON3DOWN,
562 MOUSE_BUTTON2DOWN,
563 MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN,
564 MOUSE_BUTTON1DOWN,
565 MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN,
566 MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN,
567 MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN
568 };
569 register struct mse_softc *sc = &mse_sc[unit];
570 int dx, dy, but;
571 int sign;
572
573#ifdef DEBUG
574 static int mse_intrcnt = 0;
575 if((mse_intrcnt++ % 10000) == 0)
576 printf("mseintr\n");
577#endif /* DEBUG */
578 if ((sc->sc_flags & MSESC_OPEN) == 0)
579 return;
580
581 (*sc->sc_getmouse)(sc->sc_port, &dx, &dy, &but);
582 if (sc->mode.accelfactor > 0) {
583 sign = (dx < 0);
584 dx = dx * dx / sc->mode.accelfactor;
585 if (dx == 0)
586 dx = 1;
587 if (sign)
588 dx = -dx;
589 sign = (dy < 0);
590 dy = dy * dy / sc->mode.accelfactor;
591 if (dy == 0)
592 dy = 1;
593 if (sign)
594 dy = -dy;
595 }
596 sc->sc_deltax += dx;
597 sc->sc_deltay += dy;
598 sc->sc_buttons = but;
599
600 but = butmap[~but & MOUSE_MSC_BUTTONS];
601 sc->status.dx += dx;
602 sc->status.dy += dy;
603 sc->status.flags |= ((dx || dy) ? MOUSE_POSCHANGED : 0)
604 | (sc->status.button ^ but);
605 sc->status.button = but;
606
607 /*
608 * If mouse state has changed, wake up anyone wanting to know.
609 */
610 if (sc->sc_deltax != 0 || sc->sc_deltay != 0 ||
611 (sc->sc_obuttons ^ sc->sc_buttons) != 0) {
612 if (sc->sc_flags & MSESC_WANT) {
613 sc->sc_flags &= ~MSESC_WANT;
614 wakeup((caddr_t)sc);
615 }
616 selwakeup(&sc->sc_selp);
617 }
618}
619
620/*
621 * Routines for the Logitech mouse.
622 */
623/*
624 * Test for a Logitech bus mouse and return 1 if it is.
625 * (until I know how to use the signature port properly, just disable
626 * interrupts and return 1)
627 */
628static int
629mse_probelogi(idp)
630 register struct isa_device *idp;
631{
632
633 int sig;
634
635 outb(idp->id_iobase + MSE_PORTD, MSE_SETUP);
636 /* set the signature port */
637 outb(idp->id_iobase + MSE_PORTB, MSE_LOGI_SIG);
638
639 DELAY(30000); /* 30 ms delay */
640 sig = inb(idp->id_iobase + MSE_PORTB) & 0xFF;
641 if (sig == MSE_LOGI_SIG) {
642 outb(idp->id_iobase + MSE_PORTC, MSE_DISINTR);
643 return(1);
644 } else {
645 if (bootverbose)
646 printf("mse%d: wrong signature %x\n",idp->id_unit,sig);
647 return(0);
648 }
649}
650
651/*
652 * Initialize Logitech mouse and enable interrupts.
653 */
654static void
655mse_enablelogi(port)
656 register u_int port;
657{
658 int dx, dy, but;
659
660 outb(port + MSE_PORTD, MSE_SETUP);
661 mse_getlogi(port, &dx, &dy, &but);
662}
663
664/*
665 * Disable interrupts for Logitech mouse.
666 */
667static void
668mse_disablelogi(port)
669 register u_int port;
670{
671
672 outb(port + MSE_PORTC, MSE_DISINTR);
673}
674
675/*
676 * Get the current dx, dy and button up/down state.
677 */
678static void
679mse_getlogi(port, dx, dy, but)
680 register u_int port;
681 int *dx;
682 int *dy;
683 int *but;
684{
685 register char x, y;
686
687 outb(port + MSE_PORTC, MSE_HOLD | MSE_RXLOW);
688 x = inb(port + MSE_PORTA);
689 *but = (x >> 5) & MOUSE_MSC_BUTTONS;
690 x &= 0xf;
691 outb(port + MSE_PORTC, MSE_HOLD | MSE_RXHIGH);
692 x |= (inb(port + MSE_PORTA) << 4);
693 outb(port + MSE_PORTC, MSE_HOLD | MSE_RYLOW);
694 y = (inb(port + MSE_PORTA) & 0xf);
695 outb(port + MSE_PORTC, MSE_HOLD | MSE_RYHIGH);
696 y |= (inb(port + MSE_PORTA) << 4);
697 *dx = x;
698 *dy = y;
699 outb(port + MSE_PORTC, MSE_INTREN);
700}
701
702/*
703 * Routines for the ATI Inport bus mouse.
704 */
705/*
706 * Test for a ATI Inport bus mouse and return 1 if it is.
707 * (do not enable interrupts)
708 */
709static int
710mse_probeati(idp)
711 register struct isa_device *idp;
712{
713 int i;
714
715 for (i = 0; i < 2; i++)
716 if (inb(idp->id_iobase + MSE_PORTC) == 0xde)
717 return (1);
718 return (0);
719}
720
721/*
722 * Initialize ATI Inport mouse and enable interrupts.
723 */
724static void
725mse_enableati(port)
726 register u_int port;
727{
728
729 outb(port + MSE_PORTA, MSE_INPORT_RESET);
730 outb(port + MSE_PORTA, MSE_INPORT_MODE);
731 outb(port + MSE_PORTB, MSE_INPORT_INTREN);
732}
733
734/*
735 * Disable interrupts for ATI Inport mouse.
736 */
737static void
738mse_disableati(port)
739 register u_int port;
740{
741
742 outb(port + MSE_PORTA, MSE_INPORT_MODE);
743 outb(port + MSE_PORTB, 0);
744}
745
746/*
747 * Get current dx, dy and up/down button state.
748 */
749static void
750mse_getati(port, dx, dy, but)
751 register u_int port;
752 int *dx;
753 int *dy;
754 int *but;
755{
756 register char byte;
757
758 outb(port + MSE_PORTA, MSE_INPORT_MODE);
759 outb(port + MSE_PORTB, MSE_INPORT_HOLD);
760 outb(port + MSE_PORTA, MSE_INPORT_STATUS);
761 *but = ~inb(port + MSE_PORTB) & MOUSE_MSC_BUTTONS;
762 outb(port + MSE_PORTA, MSE_INPORT_DX);
763 byte = inb(port + MSE_PORTB);
764 *dx = byte;
765 outb(port + MSE_PORTA, MSE_INPORT_DY);
766 byte = inb(port + MSE_PORTB);
767 *dy = byte;
768 outb(port + MSE_PORTA, MSE_INPORT_MODE);
769 outb(port + MSE_PORTB, MSE_INPORT_INTREN);
770}
771
772static int mse_devsw_installed;
773
774static void mse_drvinit(void *unused)
775{
776 dev_t dev;
777
778 if( ! mse_devsw_installed ) {
779 dev = makedev(CDEV_MAJOR, 0);
780 cdevsw_add(&dev,&mse_cdevsw, NULL);
781 mse_devsw_installed = 1;
782 }
783}
784
785SYSINIT(msedev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,mse_drvinit,NULL)
786
787
788#endif /* NMSE */