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