kernel - Remove kevent subsystem from under mplock
[dragonfly.git] / sys / dev / misc / mse / 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.49.2.1 2000/03/20 13:58:47 yokota Exp $
15  * $DragonFly: src/sys/dev/misc/mse/mse.c,v 1.20 2006/12/22 23:26:17 swildner Exp $
16  */
17 /*
18  * Driver for the Logitech and ATI Inport Bus mice for use with 386bsd and
19  * the X386 port, courtesy of
20  * Rick Macklem, rick@snowhite.cis.uoguelph.ca
21  * Caveats: The driver currently uses spltty(), but doesn't use any
22  * generic tty code. It could use splmse() (that only masks off the
23  * bus mouse interrupt, but that would require hacking in i386/isa/icu.s.
24  * (This may be worth the effort, since the Logitech generates 30/60
25  * interrupts/sec continuously while it is open.)
26  * NB: The ATI has NOT been tested yet!
27  */
28
29 /*
30  * Modification history:
31  * Sep 6, 1994 -- Lars Fredriksen(fredriks@mcs.com)
32  *   improved probe based on input from Logitech.
33  *
34  * Oct 19, 1992 -- E. Stark (stark@cs.sunysb.edu)
35  *   fixes to make it work with Microsoft InPort busmouse
36  *
37  * Jan, 1993 -- E. Stark (stark@cs.sunysb.edu)
38  *   added patches for new "select" interface
39  *
40  * May 4, 1993 -- E. Stark (stark@cs.sunysb.edu)
41  *   changed position of some spl()'s in mseread
42  *
43  * October 8, 1993 -- E. Stark (stark@cs.sunysb.edu)
44  *   limit maximum negative x/y value to -127 to work around XFree problem
45  *   that causes spurious button pushes.
46  */
47
48 #include <sys/param.h>
49 #include <sys/systm.h>
50 #include <sys/conf.h>
51 #include <sys/device.h>
52 #include <sys/kernel.h>
53 #include <sys/bus.h>
54 #include <sys/event.h>
55 #include <sys/uio.h>
56 #include <sys/rman.h>
57 #include <sys/thread2.h>
58
59 #include <machine/clock.h>
60 #include <machine/mouse.h>
61
62 #include <bus/isa/isavar.h>
63
64 /* driver configuration flags (config) */
65 #define MSE_CONFIG_ACCEL        0x00f0  /* acceleration factor */
66 #define MSE_CONFIG_FLAGS        (MSE_CONFIG_ACCEL)
67
68 /*
69  * Software control structure for mouse. The sc_enablemouse(),
70  * sc_disablemouse() and sc_getmouse() routines must be called spl'd().
71  */
72 typedef struct mse_softc {
73         int             sc_flags;
74         int             sc_mousetype;
75         struct kqinfo   sc_kqp;
76         struct resource *sc_port;
77         struct resource *sc_intr;
78         bus_space_tag_t sc_iot;
79         bus_space_handle_t sc_ioh;
80         void            *sc_ih;
81         void            (*sc_enablemouse) (bus_space_tag_t t,
82                                                bus_space_handle_t h);
83         void            (*sc_disablemouse) (bus_space_tag_t t,
84                                                 bus_space_handle_t h);
85         void            (*sc_getmouse) (bus_space_tag_t t,
86                                             bus_space_handle_t h,
87                                             int *dx, int *dy, int *but);
88         int             sc_deltax;
89         int             sc_deltay;
90         int             sc_obuttons;
91         int             sc_buttons;
92         int             sc_bytesread;
93         u_char          sc_bytes[MOUSE_SYS_PACKETSIZE];
94         struct          callout sc_callout;
95         int             sc_watchdog;
96         mousehw_t       hw;
97         mousemode_t     mode;
98         mousestatus_t   status;
99 } mse_softc_t;
100
101 static  devclass_t      mse_devclass;
102
103 static  int             mse_probe (device_t dev);
104 static  int             mse_attach (device_t dev);
105 static  int             mse_detach (device_t dev);
106
107 static  device_method_t mse_methods[] = {
108         DEVMETHOD(device_probe,         mse_probe),
109         DEVMETHOD(device_attach,        mse_attach),
110         DEVMETHOD(device_detach,        mse_detach),
111         { 0, 0 }
112 };
113
114 static  driver_t        mse_driver = {
115         "mse",
116         mse_methods,
117         sizeof(mse_softc_t),
118 };
119
120 DRIVER_MODULE(mse, isa, mse_driver, mse_devclass, 0, 0);
121
122 static struct isa_pnp_id mse_ids[] = {
123         { 0x000fd041, "Bus mouse" },                    /* PNP0F00 */
124         { 0x020fd041, "InPort mouse" },                 /* PNP0F02 */
125         { 0x0d0fd041, "InPort mouse compatible" },      /* PNP0F0D */
126         { 0x110fd041, "Bus mouse compatible" },         /* PNP0F11 */
127         { 0x150fd041, "Logitech bus mouse" },           /* PNP0F15 */
128         { 0x180fd041, "Logitech bus mouse compatible" },/* PNP0F18 */
129         { 0 }
130 };
131
132 static  d_open_t        mseopen;
133 static  d_close_t       mseclose;
134 static  d_read_t        mseread;
135 static  d_ioctl_t       mseioctl;
136 static  d_kqfilter_t    msekqfilter;
137
138 static void msefilter_detach(struct knote *);
139 static int msefilter(struct knote *, long);
140
141 #define CDEV_MAJOR 27
142 static struct dev_ops mse_ops = {
143         { "mse", CDEV_MAJOR, 0 },
144         .d_open =       mseopen,
145         .d_close =      mseclose,
146         .d_read =       mseread,
147         .d_ioctl =      mseioctl,
148         .d_kqfilter =   msekqfilter
149 };
150
151 static  void            mseintr (void *);
152 static  timeout_t       msetimeout;
153
154 /* Flags */
155 #define MSESC_OPEN      0x1
156 #define MSESC_WANT      0x2
157
158 /* and Mouse Types */
159 #define MSE_NONE        0       /* don't move this! */
160 #define MSE_LOGITECH    0x1
161 #define MSE_ATIINPORT   0x2
162 #define MSE_LOGI_SIG    0xA5
163
164 #define MSE_PORTA       0
165 #define MSE_PORTB       1
166 #define MSE_PORTC       2
167 #define MSE_PORTD       3
168 #define MSE_IOSIZE      4
169
170 #define MSE_UNIT(dev)           (minor(dev) >> 1)
171 #define MSE_NBLOCKIO(dev)       (minor(dev) & 0x1)
172
173 /*
174  * Logitech bus mouse definitions
175  */
176 #define MSE_SETUP       0x91    /* What does this mean? */
177                                 /* The definition for the control port */
178                                 /* is as follows: */
179
180                                 /* D7    =  Mode set flag (1 = active)  */
181                                 /* D6,D5 =  Mode selection (port A)     */
182                                 /*          00 = Mode 0 = Basic I/O     */
183                                 /*          01 = Mode 1 = Strobed I/O   */
184                                 /*          10 = Mode 2 = Bi-dir bus    */
185                                 /* D4    =  Port A direction (1 = input)*/
186                                 /* D3    =  Port C (upper 4 bits)       */
187                                 /*          direction. (1 = input)      */
188                                 /* D2    =  Mode selection (port B & C) */
189                                 /*          0 = Mode 0 = Basic I/O      */
190                                 /*          1 = Mode 1 = Strobed I/O    */
191                                 /* D1    =  Port B direction (1 = input)*/
192                                 /* D0    =  Port C (lower 4 bits)       */
193                                 /*          direction. (1 = input)      */
194
195                                 /* So 91 means Basic I/O on all 3 ports,*/
196                                 /* Port A is an input port, B is an     */
197                                 /* output port, C is split with upper   */
198                                 /* 4 bits being an output port and lower*/
199                                 /* 4 bits an input port, and enable the */
200                                 /* sucker.                              */
201                                 /* Courtesy Intel 8255 databook. Lars   */
202 #define MSE_HOLD        0x80
203 #define MSE_RXLOW       0x00
204 #define MSE_RXHIGH      0x20
205 #define MSE_RYLOW       0x40
206 #define MSE_RYHIGH      0x60
207 #define MSE_DISINTR     0x10
208 #define MSE_INTREN      0x00
209
210 static  int             mse_probelogi (device_t dev, mse_softc_t *sc);
211 static  void            mse_disablelogi (bus_space_tag_t t,
212                                              bus_space_handle_t h);
213 static  void            mse_getlogi (bus_space_tag_t t,
214                                          bus_space_handle_t h,
215                                          int *dx, int *dy, int *but);
216 static  void            mse_enablelogi (bus_space_tag_t t,
217                                             bus_space_handle_t h);
218
219 /*
220  * ATI Inport mouse definitions
221  */
222 #define MSE_INPORT_RESET        0x80
223 #define MSE_INPORT_STATUS       0x00
224 #define MSE_INPORT_DX           0x01
225 #define MSE_INPORT_DY           0x02
226 #define MSE_INPORT_MODE         0x07
227 #define MSE_INPORT_HOLD         0x20
228 #define MSE_INPORT_INTREN       0x09
229
230 static  int             mse_probeati (device_t dev, mse_softc_t *sc);
231 static  void            mse_enableati (bus_space_tag_t t,
232                                            bus_space_handle_t h);
233 static  void            mse_disableati (bus_space_tag_t t,
234                                             bus_space_handle_t h);
235 static  void            mse_getati (bus_space_tag_t t,
236                                         bus_space_handle_t h,
237                                         int *dx, int *dy, int *but);
238
239 /*
240  * Table of mouse types.
241  * Keep the Logitech last, since I haven't figured out how to probe it
242  * properly yet. (Someday I'll have the documentation.)
243  */
244 static struct mse_types {
245         int     m_type;         /* Type of bus mouse */
246         int     (*m_probe) (device_t dev, mse_softc_t *sc);
247                                 /* Probe routine to test for it */
248         void    (*m_enable) (bus_space_tag_t t, bus_space_handle_t h);
249                                 /* Start routine */
250         void    (*m_disable) (bus_space_tag_t t, bus_space_handle_t h);
251                                 /* Disable interrupts routine */
252         void    (*m_get) (bus_space_tag_t t, bus_space_handle_t h,
253                               int *dx, int *dy, int *but);
254                                 /* and get mouse status */
255         mousehw_t   m_hw;       /* buttons iftype type model hwid */
256         mousemode_t m_mode;     /* proto rate res accel level size mask */
257 } mse_types[] = {
258         { MSE_ATIINPORT, 
259           mse_probeati, mse_enableati, mse_disableati, mse_getati,
260           { 2, MOUSE_IF_INPORT, MOUSE_MOUSE, MOUSE_MODEL_GENERIC, 0, },
261           { MOUSE_PROTO_INPORT, -1, -1, 0, 0, MOUSE_MSC_PACKETSIZE, 
262             { MOUSE_MSC_SYNCMASK, MOUSE_MSC_SYNC, }, }, },
263         { MSE_LOGITECH, 
264           mse_probelogi, mse_enablelogi, mse_disablelogi, mse_getlogi,
265           { 2, MOUSE_IF_BUS, MOUSE_MOUSE, MOUSE_MODEL_GENERIC, 0, },
266           { MOUSE_PROTO_BUS, -1, -1, 0, 0, MOUSE_MSC_PACKETSIZE, 
267             { MOUSE_MSC_SYNCMASK, MOUSE_MSC_SYNC, }, }, },
268         { 0, },
269 };
270
271 static  int
272 mse_probe(device_t dev)
273 {
274         mse_softc_t *sc;
275         int error;
276         int rid;
277         int i;
278
279         /* check PnP IDs */
280         error = ISA_PNP_PROBE(device_get_parent(dev), dev, mse_ids);
281         if (error == ENXIO)
282                 return ENXIO;
283
284         sc = device_get_softc(dev);
285         rid = 0;
286         sc->sc_port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0,
287                                          MSE_IOSIZE, RF_ACTIVE);
288         if (sc->sc_port == NULL)
289                 return ENXIO;
290         sc->sc_iot = rman_get_bustag(sc->sc_port);
291         sc->sc_ioh = rman_get_bushandle(sc->sc_port);
292
293         /*
294          * Check for each mouse type in the table.
295          */
296         i = 0;
297         while (mse_types[i].m_type) {
298                 if ((*mse_types[i].m_probe)(dev, sc)) {
299                         sc->sc_mousetype = mse_types[i].m_type;
300                         sc->sc_enablemouse = mse_types[i].m_enable;
301                         sc->sc_disablemouse = mse_types[i].m_disable;
302                         sc->sc_getmouse = mse_types[i].m_get;
303                         sc->hw = mse_types[i].m_hw;
304                         sc->mode = mse_types[i].m_mode;
305                         bus_release_resource(dev, SYS_RES_IOPORT, rid,
306                                              sc->sc_port);
307                         device_set_desc(dev, "Bus/InPort Mouse");
308                         return 0;
309                 }
310                 i++;
311         }
312         bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->sc_port);
313         return ENXIO;
314 }
315
316 static  int
317 mse_attach(device_t dev)
318 {
319         mse_softc_t *sc;
320         int flags;
321         int unit;
322         int rid;
323
324         sc = device_get_softc(dev);
325         unit = device_get_unit(dev);
326
327         rid = 0;
328         sc->sc_port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0,
329                                          MSE_IOSIZE, RF_ACTIVE);
330         if (sc->sc_port == NULL)
331                 return ENXIO;
332         sc->sc_intr = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
333                                          RF_ACTIVE);
334         if (sc->sc_intr == NULL) {
335                 bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->sc_port);
336                 return ENXIO;
337         }
338         sc->sc_iot = rman_get_bustag(sc->sc_port);
339         sc->sc_ioh = rman_get_bushandle(sc->sc_port);
340
341         if (BUS_SETUP_INTR(device_get_parent(dev), dev, sc->sc_intr,
342                            0, mseintr, sc, &sc->sc_ih, NULL)) {
343                 bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->sc_port);
344                 bus_release_resource(dev, SYS_RES_IRQ, rid, sc->sc_intr);
345                 return ENXIO;
346         }
347
348         flags = device_get_flags(dev);
349         sc->mode.accelfactor = (flags & MSE_CONFIG_ACCEL) >> 4;
350         callout_init(&sc->sc_callout);
351
352         make_dev(&mse_ops, unit << 1, 0, 0, 0600, "mse%d", unit);
353         make_dev(&mse_ops, (unit<<1)+1, 0, 0, 0600, "nmse%d", unit);
354
355         return 0;
356 }
357
358 static  int
359 mse_detach(device_t dev)
360 {
361         mse_softc_t *sc;
362         int rid;
363
364         sc = device_get_softc(dev);
365         if (sc->sc_flags & MSESC_OPEN)
366                 return EBUSY;
367
368         rid = 0;
369         BUS_TEARDOWN_INTR(device_get_parent(dev), dev, sc->sc_intr, sc->sc_ih);
370         bus_release_resource(dev, SYS_RES_IRQ, rid, sc->sc_intr);
371         bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->sc_port);
372         dev_ops_remove_minor(&mse_ops, device_get_unit(dev) << 1);
373
374         return 0;
375 }
376
377 /*
378  * Exclusive open the mouse, initialize it and enable interrupts.
379  */
380 static  int
381 mseopen(struct dev_open_args *ap)
382 {
383         cdev_t dev = ap->a_head.a_dev;
384         mse_softc_t *sc;
385
386         sc = devclass_get_softc(mse_devclass, MSE_UNIT(dev));
387         if (sc == NULL)
388                 return (ENXIO);
389         if (sc->sc_mousetype == MSE_NONE)
390                 return (ENXIO);
391         if (sc->sc_flags & MSESC_OPEN)
392                 return (EBUSY);
393         sc->sc_flags |= MSESC_OPEN;
394         sc->sc_obuttons = sc->sc_buttons = MOUSE_MSC_BUTTONS;
395         sc->sc_deltax = sc->sc_deltay = 0;
396         sc->sc_bytesread = sc->mode.packetsize = MOUSE_MSC_PACKETSIZE;
397         sc->sc_watchdog = FALSE;
398         callout_reset(&sc->sc_callout, hz * 2, msetimeout, dev);
399         sc->mode.level = 0;
400         sc->status.flags = 0;
401         sc->status.button = sc->status.obutton = 0;
402         sc->status.dx = sc->status.dy = sc->status.dz = 0;
403
404         /*
405          * Initialize mouse interface and enable interrupts.
406          */
407         crit_enter();
408         (*sc->sc_enablemouse)(sc->sc_iot, sc->sc_ioh);
409         crit_exit();
410         return (0);
411 }
412
413 /*
414  * mseclose: just turn off mouse innterrupts.
415  */
416 static  int
417 mseclose(struct dev_close_args *ap)
418 {
419         cdev_t dev = ap->a_head.a_dev;
420         mse_softc_t *sc = devclass_get_softc(mse_devclass, MSE_UNIT(dev));
421
422         crit_enter();
423         callout_stop(&sc->sc_callout);
424         (*sc->sc_disablemouse)(sc->sc_iot, sc->sc_ioh);
425         sc->sc_flags &= ~MSESC_OPEN;
426         crit_exit();
427         return(0);
428 }
429
430 /*
431  * mseread: return mouse info using the MSC serial protocol, but without
432  * using bytes 4 and 5.
433  * (Yes this is cheesy, but it makes the X386 server happy, so...)
434  */
435 static  int
436 mseread(struct dev_read_args *ap)
437 {
438         cdev_t dev = ap->a_head.a_dev;
439         struct uio *uio = ap->a_uio;
440         mse_softc_t *sc = devclass_get_softc(mse_devclass, MSE_UNIT(dev));
441         int xfer, error;
442
443         /*
444          * If there are no protocol bytes to be read, set up a new protocol
445          * packet.
446          */
447         crit_enter(); /* XXX Should be its own spl, but where is imlXX() */
448         if (sc->sc_bytesread >= sc->mode.packetsize) {
449                 while (sc->sc_deltax == 0 && sc->sc_deltay == 0 &&
450                        (sc->sc_obuttons ^ sc->sc_buttons) == 0) {
451                         if (MSE_NBLOCKIO(dev)) {
452                                 crit_exit();
453                                 return (0);
454                         }
455                         sc->sc_flags |= MSESC_WANT;
456                         error = tsleep((caddr_t)sc, PCATCH, "mseread", 0);
457                         if (error) {
458                                 crit_exit();
459                                 return (error);
460                         }
461                 }
462
463                 /*
464                  * Generate protocol bytes.
465                  * For some reason X386 expects 5 bytes but never uses
466                  * the fourth or fifth?
467                  */
468                 sc->sc_bytes[0] = sc->mode.syncmask[1] 
469                     | (sc->sc_buttons & ~sc->mode.syncmask[0]);
470                 if (sc->sc_deltax > 127)
471                         sc->sc_deltax = 127;
472                 if (sc->sc_deltax < -127)
473                         sc->sc_deltax = -127;
474                 sc->sc_deltay = -sc->sc_deltay; /* Otherwise mousey goes wrong way */
475                 if (sc->sc_deltay > 127)
476                         sc->sc_deltay = 127;
477                 if (sc->sc_deltay < -127)
478                         sc->sc_deltay = -127;
479                 sc->sc_bytes[1] = sc->sc_deltax;
480                 sc->sc_bytes[2] = sc->sc_deltay;
481                 sc->sc_bytes[3] = sc->sc_bytes[4] = 0;
482                 sc->sc_bytes[5] = sc->sc_bytes[6] = 0;
483                 sc->sc_bytes[7] = MOUSE_SYS_EXTBUTTONS;
484                 sc->sc_obuttons = sc->sc_buttons;
485                 sc->sc_deltax = sc->sc_deltay = 0;
486                 sc->sc_bytesread = 0;
487         }
488         crit_exit();
489         xfer = (int)szmin(uio->uio_resid,
490                           sc->mode.packetsize - sc->sc_bytesread);
491         error = uiomove(&sc->sc_bytes[sc->sc_bytesread], (size_t)xfer, uio);
492         if (error)
493                 return (error);
494         sc->sc_bytesread += xfer;
495         return(0);
496 }
497
498 /*
499  * mseioctl: process ioctl commands.
500  */
501 static int
502 mseioctl(struct dev_ioctl_args *ap)
503 {
504         cdev_t dev = ap->a_head.a_dev;
505         caddr_t addr = ap->a_data;
506         mse_softc_t *sc = devclass_get_softc(mse_devclass, MSE_UNIT(dev));
507         mousestatus_t status;
508         int err = 0;
509
510         switch (ap->a_cmd) {
511         case MOUSE_GETHWINFO:
512                 crit_enter();
513                 *(mousehw_t *)addr = sc->hw;
514                 if (sc->mode.level == 0)
515                         ((mousehw_t *)addr)->model = MOUSE_MODEL_GENERIC;
516                 crit_exit();
517                 break;
518
519         case MOUSE_GETMODE:
520                 crit_enter();
521                 *(mousemode_t *)addr = sc->mode;
522                 switch (sc->mode.level) {
523                 case 0:
524                         break;
525                 case 1:
526                         ((mousemode_t *)addr)->protocol = MOUSE_PROTO_SYSMOUSE;
527                         ((mousemode_t *)addr)->syncmask[0] = MOUSE_SYS_SYNCMASK;
528                         ((mousemode_t *)addr)->syncmask[1] = MOUSE_SYS_SYNC;
529                         break;
530                 }
531                 crit_exit();
532                 break;
533
534         case MOUSE_SETMODE:
535                 switch (((mousemode_t *)addr)->level) {
536                 case 0:
537                 case 1:
538                         break;
539                 default:
540                         return (EINVAL);
541                 }
542                 if (((mousemode_t *)addr)->accelfactor < -1)
543                         return (EINVAL);
544                 else if (((mousemode_t *)addr)->accelfactor >= 0)
545                         sc->mode.accelfactor = 
546                             ((mousemode_t *)addr)->accelfactor;
547                 sc->mode.level = ((mousemode_t *)addr)->level;
548                 switch (sc->mode.level) {
549                 case 0:
550                         sc->sc_bytesread = sc->mode.packetsize 
551                             = MOUSE_MSC_PACKETSIZE;
552                         break;
553                 case 1:
554                         sc->sc_bytesread = sc->mode.packetsize 
555                             = MOUSE_SYS_PACKETSIZE;
556                         break;
557                 }
558                 break;
559
560         case MOUSE_GETLEVEL:
561                 *(int *)addr = sc->mode.level;
562                 break;
563
564         case MOUSE_SETLEVEL:
565                 switch (*(int *)addr) {
566                 case 0:
567                         sc->mode.level = *(int *)addr;
568                         sc->sc_bytesread = sc->mode.packetsize 
569                             = MOUSE_MSC_PACKETSIZE;
570                         break;
571                 case 1:
572                         sc->mode.level = *(int *)addr;
573                         sc->sc_bytesread = sc->mode.packetsize 
574                             = MOUSE_SYS_PACKETSIZE;
575                         break;
576                 default:
577                         return (EINVAL);
578                 }
579                 break;
580
581         case MOUSE_GETSTATUS:
582                 crit_enter();
583                 status = sc->status;
584                 sc->status.flags = 0;
585                 sc->status.obutton = sc->status.button;
586                 sc->status.button = 0;
587                 sc->status.dx = 0;
588                 sc->status.dy = 0;
589                 sc->status.dz = 0;
590                 crit_exit();
591                 *(mousestatus_t *)addr = status;
592                 break;
593
594         case MOUSE_READSTATE:
595         case MOUSE_READDATA:
596                 return (ENODEV);
597
598 #if (defined(MOUSE_GETVARS))
599         case MOUSE_GETVARS:
600         case MOUSE_SETVARS:
601                 return (ENODEV);
602 #endif
603
604         default:
605                 return (ENOTTY);
606         }
607         return (err);
608 }
609
610 static struct filterops msefiltops =
611         { 1, NULL, msefilter_detach, msefilter };
612
613 static int
614 msekqfilter(struct dev_kqfilter_args *ap)
615 {
616         cdev_t dev = ap->a_head.a_dev;
617         mse_softc_t *sc = devclass_get_softc(mse_devclass, MSE_UNIT(dev));
618         struct knote *kn = ap->a_kn;
619         struct klist *klist;
620
621         ap->a_result = 0;
622
623         switch (kn->kn_filter) {
624         case EVFILT_READ:
625                 kn->kn_fop = &msefiltops;
626                 kn->kn_hook = (caddr_t)sc;
627                 break;
628         default:
629                 ap->a_result = EOPNOTSUPP;
630                 return (0);
631         }
632
633         klist = &sc->sc_kqp.ki_note;
634         knote_insert(klist, kn);
635
636         return (0);
637 }
638
639 static void
640 msefilter_detach(struct knote *kn)
641 {
642         mse_softc_t *sc = (mse_softc_t *)kn->kn_hook;
643         struct klist *klist;
644
645         klist = &sc->sc_kqp.ki_note;
646         knote_remove(klist, kn);
647 }
648
649 static int
650 msefilter(struct knote *kn, long hint)
651 {
652         mse_softc_t *sc = (mse_softc_t *)kn->kn_hook;
653         int ready = 0;
654
655         crit_enter();
656         if (sc->sc_bytesread != sc->mode.packetsize ||
657             sc->sc_deltax != 0 || sc->sc_deltay != 0 ||
658             (sc->sc_obuttons ^ sc->sc_buttons) != 0)
659                 ready = 1;
660
661         crit_exit();
662
663         return (ready);
664 }
665
666 /*
667  * msetimeout: watchdog timer routine.
668  */
669 static void
670 msetimeout(void *arg)
671 {
672         cdev_t dev;
673         mse_softc_t *sc;
674
675         dev = (cdev_t)arg;
676         sc = devclass_get_softc(mse_devclass, MSE_UNIT(dev));
677         if (sc->sc_watchdog) {
678                 if (bootverbose)
679                         kprintf("mse%d: lost interrupt?\n", MSE_UNIT(dev));
680                 mseintr(sc);
681         }
682         sc->sc_watchdog = TRUE;
683         callout_reset(&sc->sc_callout, hz, msetimeout, dev);
684 }
685
686 /*
687  * mseintr: update mouse status. sc_deltax and sc_deltay are accumulative.
688  */
689 static void
690 mseintr(void *arg)
691 {
692         /*
693          * the table to turn MouseSystem button bits (MOUSE_MSC_BUTTON?UP)
694          * into `mousestatus' button bits (MOUSE_BUTTON?DOWN).
695          */
696         static int butmap[8] = {
697                 0, 
698                 MOUSE_BUTTON3DOWN, 
699                 MOUSE_BUTTON2DOWN, 
700                 MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN, 
701                 MOUSE_BUTTON1DOWN, 
702                 MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN, 
703                 MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN,
704                 MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN
705         };
706         mse_softc_t *sc = arg;
707         int dx, dy, but;
708         int sign;
709
710 #ifdef DEBUG
711         static int mse_intrcnt = 0;
712         if((mse_intrcnt++ % 10000) == 0)
713                 kprintf("mseintr\n");
714 #endif /* DEBUG */
715         if ((sc->sc_flags & MSESC_OPEN) == 0)
716                 return;
717
718         (*sc->sc_getmouse)(sc->sc_iot, sc->sc_ioh, &dx, &dy, &but);
719         if (sc->mode.accelfactor > 0) {
720                 sign = (dx < 0);
721                 dx = dx * dx / sc->mode.accelfactor;
722                 if (dx == 0)
723                         dx = 1;
724                 if (sign)
725                         dx = -dx;
726                 sign = (dy < 0);
727                 dy = dy * dy / sc->mode.accelfactor;
728                 if (dy == 0)
729                         dy = 1;
730                 if (sign)
731                         dy = -dy;
732         }
733         sc->sc_deltax += dx;
734         sc->sc_deltay += dy;
735         sc->sc_buttons = but;
736
737         but = butmap[~but & MOUSE_MSC_BUTTONS];
738         sc->status.dx += dx;
739         sc->status.dy += dy;
740         sc->status.flags |= ((dx || dy) ? MOUSE_POSCHANGED : 0)
741             | (sc->status.button ^ but);
742         sc->status.button = but;
743
744         sc->sc_watchdog = FALSE;
745
746         /*
747          * If mouse state has changed, wake up anyone wanting to know.
748          */
749         if (sc->sc_deltax != 0 || sc->sc_deltay != 0 ||
750             (sc->sc_obuttons ^ sc->sc_buttons) != 0) {
751                 if (sc->sc_flags & MSESC_WANT) {
752                         sc->sc_flags &= ~MSESC_WANT;
753                         wakeup((caddr_t)sc);
754                 }
755                 KNOTE(&sc->sc_kqp.ki_note, 0);
756         }
757 }
758
759 /*
760  * Routines for the Logitech mouse.
761  */
762 /*
763  * Test for a Logitech bus mouse and return 1 if it is.
764  * (until I know how to use the signature port properly, just disable
765  *  interrupts and return 1)
766  */
767 static int
768 mse_probelogi(device_t dev, mse_softc_t *sc)
769 {
770
771         int sig;
772
773         bus_space_write_1(sc->sc_iot, sc->sc_ioh, MSE_PORTD, MSE_SETUP);
774                 /* set the signature port */
775         bus_space_write_1(sc->sc_iot, sc->sc_ioh, MSE_PORTB, MSE_LOGI_SIG);
776
777         DELAY(30000); /* 30 ms delay */
778         sig = bus_space_read_1(sc->sc_iot, sc->sc_ioh, MSE_PORTB) & 0xFF;
779         if (sig == MSE_LOGI_SIG) {
780                 bus_space_write_1(sc->sc_iot, sc->sc_ioh, MSE_PORTC,
781                                   MSE_DISINTR);
782                 return(1);
783         } else {
784                 if (bootverbose)
785                         device_printf(dev, "wrong signature %x\n", sig);
786                 return(0);
787         }
788 }
789
790 /*
791  * Initialize Logitech mouse and enable interrupts.
792  */
793 static void
794 mse_enablelogi(bus_space_tag_t tag, bus_space_handle_t handle)
795 {
796         int dx, dy, but;
797
798         bus_space_write_1(tag, handle, MSE_PORTD, MSE_SETUP);
799         mse_getlogi(tag, handle, &dx, &dy, &but);
800 }
801
802 /*
803  * Disable interrupts for Logitech mouse.
804  */
805 static void
806 mse_disablelogi(bus_space_tag_t tag, bus_space_handle_t handle)
807 {
808
809         bus_space_write_1(tag, handle, MSE_PORTC, MSE_DISINTR);
810 }
811
812 /*
813  * Get the current dx, dy and button up/down state.
814  */
815 static void
816 mse_getlogi(bus_space_tag_t tag, bus_space_handle_t handle, int *dx, int *dy,
817             int *but)
818 {
819         char x, y;
820
821         bus_space_write_1(tag, handle, MSE_PORTC, MSE_HOLD | MSE_RXLOW);
822         x = bus_space_read_1(tag, handle, MSE_PORTA);
823         *but = (x >> 5) & MOUSE_MSC_BUTTONS;
824         x &= 0xf;
825         bus_space_write_1(tag, handle, MSE_PORTC, MSE_HOLD | MSE_RXHIGH);
826         x |= (bus_space_read_1(tag, handle, MSE_PORTA) << 4);
827         bus_space_write_1(tag, handle, MSE_PORTC, MSE_HOLD | MSE_RYLOW);
828         y = (bus_space_read_1(tag, handle, MSE_PORTA) & 0xf);
829         bus_space_write_1(tag, handle, MSE_PORTC, MSE_HOLD | MSE_RYHIGH);
830         y |= (bus_space_read_1(tag, handle, MSE_PORTA) << 4);
831         *dx = x;
832         *dy = y;
833         bus_space_write_1(tag, handle, MSE_PORTC, MSE_INTREN);
834 }
835
836 /*
837  * Routines for the ATI Inport bus mouse.
838  */
839 /*
840  * Test for a ATI Inport bus mouse and return 1 if it is.
841  * (do not enable interrupts)
842  */
843 static int
844 mse_probeati(device_t dev, mse_softc_t *sc)
845 {
846         int i;
847
848         for (i = 0; i < 2; i++)
849                 if (bus_space_read_1(sc->sc_iot, sc->sc_ioh, MSE_PORTC) == 0xde)
850                         return (1);
851         return (0);
852 }
853
854 /*
855  * Initialize ATI Inport mouse and enable interrupts.
856  */
857 static void
858 mse_enableati(bus_space_tag_t tag, bus_space_handle_t handle)
859 {
860
861         bus_space_write_1(tag, handle, MSE_PORTA, MSE_INPORT_RESET);
862         bus_space_write_1(tag, handle, MSE_PORTA, MSE_INPORT_MODE);
863         bus_space_write_1(tag, handle, MSE_PORTB, MSE_INPORT_INTREN);
864 }
865
866 /*
867  * Disable interrupts for ATI Inport mouse.
868  */
869 static void
870 mse_disableati(bus_space_tag_t tag, bus_space_handle_t handle)
871 {
872
873         bus_space_write_1(tag, handle, MSE_PORTA, MSE_INPORT_MODE);
874         bus_space_write_1(tag, handle, MSE_PORTB, 0);
875 }
876
877 /*
878  * Get current dx, dy and up/down button state.
879  */
880 static void
881 mse_getati(bus_space_tag_t tag, bus_space_handle_t handle, int *dx, int *dy,
882            int *but)
883 {
884         char byte;
885
886         bus_space_write_1(tag, handle, MSE_PORTA, MSE_INPORT_MODE);
887         bus_space_write_1(tag, handle, MSE_PORTB, MSE_INPORT_HOLD);
888         bus_space_write_1(tag, handle, MSE_PORTA, MSE_INPORT_STATUS);
889         *but = ~bus_space_read_1(tag, handle, MSE_PORTB) & MOUSE_MSC_BUTTONS;
890         bus_space_write_1(tag, handle, MSE_PORTA, MSE_INPORT_DX);
891         byte = bus_space_read_1(tag, handle, MSE_PORTB);
892         *dx = byte;
893         bus_space_write_1(tag, handle, MSE_PORTA, MSE_INPORT_DY);
894         byte = bus_space_read_1(tag, handle, MSE_PORTB);
895         *dy = byte;
896         bus_space_write_1(tag, handle, MSE_PORTA, MSE_INPORT_MODE);
897         bus_space_write_1(tag, handle, MSE_PORTB, MSE_INPORT_INTREN);
898 }