kernel - Fix kqfilter error return codes
[dragonfly.git] / sys / dev / misc / psm / psm.c
1 /*-
2  * Copyright (c) 1992, 1993 Erik Forsberg.
3  * Copyright (c) 1996, 1997 Kazutaka YOKOTA.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
13  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
14  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
15  * NO EVENT SHALL I BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
16  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
17  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
18  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
19  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
20  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22  *
23  * $FreeBSD: src/sys/isa/psm.c,v 1.23.2.7 2003/11/12 04:26:26 mikeh Exp $
24  * $DragonFly: src/sys/dev/misc/psm/psm.c,v 1.25 2007/06/13 17:15:25 dillon Exp $
25  */
26
27 /*
28  *  Ported to 386bsd Oct 17, 1992
29  *  Sandi Donno, Computer Science, University of Cape Town, South Africa
30  *  Please send bug reports to sandi@cs.uct.ac.za
31  *
32  *  Thanks are also due to Rick Macklem, rick@snowhite.cis.uoguelph.ca -
33  *  although I was only partially successful in getting the alpha release
34  *  of his "driver for the Logitech and ATI Inport Bus mice for use with
35  *  386bsd and the X386 port" to work with my Microsoft mouse, I nevertheless
36  *  found his code to be an invaluable reference when porting this driver
37  *  to 386bsd.
38  *
39  *  Further modifications for latest 386BSD+patchkit and port to NetBSD,
40  *  Andrew Herbert <andrew@werple.apana.org.au> - 8 June 1993
41  *
42  *  Cloned from the Microsoft Bus Mouse driver, also by Erik Forsberg, by
43  *  Andrew Herbert - 12 June 1993
44  *
45  *  Modified for PS/2 mouse by Charles Hannum <mycroft@ai.mit.edu>
46  *  - 13 June 1993
47  *
48  *  Modified for PS/2 AUX mouse by Shoji Yuen <yuen@nuie.nagoya-u.ac.jp>
49  *  - 24 October 1993
50  *
51  *  Hardware access routines and probe logic rewritten by
52  *  Kazutaka Yokota <yokota@zodiac.mech.utsunomiya-u.ac.jp>
53  *  - 3, 14, 22 October 1996.
54  *  - 12 November 1996. IOCTLs and rearranging `psmread', `psmioctl'...
55  *  - 14, 30 November 1996. Uses `kbdio.c'.
56  *  - 13 December 1996. Uses queuing version of `kbdio.c'.
57  *  - January/February 1997. Tweaked probe logic for 
58  *    HiNote UltraII/Latitude/Armada laptops.
59  *  - 30 July 1997. Added APM support.
60  *  - 5 March 1997. Defined driver configuration flags (PSM_CONFIG_XXX). 
61  *    Improved sync check logic.
62  *    Vendor specific support routines.
63  */
64
65 #include "opt_psm.h"
66
67 #include <sys/param.h>
68 #include <sys/systm.h>
69 #include <sys/kernel.h>
70 #include <sys/module.h>
71 #include <sys/bus.h>
72 #include <sys/conf.h>
73 #include <sys/device.h>
74 #include <sys/poll.h>
75 #include <sys/event.h>
76 #include <sys/syslog.h>
77 #include <sys/malloc.h>
78 #include <sys/rman.h>
79 #include <sys/selinfo.h>
80 #include <sys/thread2.h>
81 #include <sys/time.h>
82 #include <sys/uio.h>
83
84 #include <machine/clock.h>
85 #include <machine/limits.h>
86 #include <machine/mouse.h>
87
88 #include <bus/isa/isavar.h>
89 #include <dev/misc/kbd/atkbdcreg.h>
90
91 /*
92  * Driver specific options: the following options may be set by
93  * `options' statements in the kernel configuration file.
94  */
95
96 /* debugging */
97 #ifndef PSM_DEBUG
98 #define PSM_DEBUG       0       /* logging: 0: none, 1: brief, 2: verbose */
99 #endif
100
101 #ifndef PSM_SYNCERR_THRESHOLD1
102 #define PSM_SYNCERR_THRESHOLD1  20
103 #endif
104
105 #ifndef PSM_INPUT_TIMEOUT
106 #define PSM_INPUT_TIMEOUT       2000000 /* 2 sec */
107 #endif
108
109 /* end of driver specific options */
110
111 #define PSM_DRIVER_NAME         "psm"
112 #define PSMCPNP_DRIVER_NAME     "psmcpnp"
113
114 /* input queue */
115 #define PSM_BUFSIZE             960
116 #define PSM_SMALLBUFSIZE        240
117
118 /* operation levels */
119 #define PSM_LEVEL_BASE          0
120 #define PSM_LEVEL_STANDARD      1
121 #define PSM_LEVEL_NATIVE        2
122 #define PSM_LEVEL_MIN           PSM_LEVEL_BASE
123 #define PSM_LEVEL_MAX           PSM_LEVEL_NATIVE
124
125 /* Logitech PS2++ protocol */
126 #define MOUSE_PS2PLUS_CHECKBITS(b)      \
127                                 ((((b[2] & 0x03) << 2) | 0x02) == (b[1] & 0x0f))
128 #define MOUSE_PS2PLUS_PACKET_TYPE(b)    \
129                                 (((b[0] & 0x30) >> 2) | ((b[1] & 0x30) >> 4))
130
131 /* some macros */
132 #define PSM_UNIT(dev)           (minor(dev) >> 1)
133 #define PSM_NBLOCKIO(dev)       (minor(dev) & 1)
134 #define PSM_MKMINOR(unit,block) ((((unit) & 0xff) << 1) | ((block) ? 0:1))
135
136 #ifndef max
137 #define max(x,y)                ((x) > (y) ? (x) : (y))
138 #endif
139 #ifndef min
140 #define min(x,y)                ((x) < (y) ? (x) : (y))
141 #endif
142
143 #define abs(x)                  (((x) < 0) ? -(x) : (x))
144
145 /* ring buffer */
146 typedef struct ringbuf {
147     int           count;        /* # of valid elements in the buffer */
148     int           head;         /* head pointer */
149     int           tail;         /* tail poiner */
150     unsigned char buf[PSM_BUFSIZE];
151 } ringbuf_t;
152
153 /* driver control block */
154 struct psm_softc {              /* Driver status information */
155     int           unit;
156     struct selinfo rsel;        /* Process selecting for Input */
157     unsigned char state;        /* Mouse driver state */
158     int           config;       /* driver configuration flags */
159     int           flags;        /* other flags */
160     KBDC          kbdc;         /* handle to access the keyboard controller */
161     struct resource *intr;      /* IRQ resource */
162     void          *ih;          /* interrupt handle */
163     mousehw_t     hw;           /* hardware information */
164     mousemode_t   mode;         /* operation mode */
165     mousemode_t   dflt_mode;    /* default operation mode */
166     mousestatus_t status;       /* accumulated mouse movement */
167     ringbuf_t     queue;        /* mouse status queue */
168     unsigned char ipacket[16];  /* interim input buffer */
169     int           inputbytes;   /* # of bytes in the input buffer */
170     int           button;       /* the latest button state */
171     int           xold; /* previous absolute X position */
172     int           yold; /* previous absolute Y position */
173     int           syncerrors;
174     struct timeval inputtimeout;
175     int           watchdog;     /* watchdog timer flag */
176     struct callout callout;     /* watchdog timer call out */
177 };
178 devclass_t psm_devclass;
179 #define PSM_SOFTC(unit) ((struct psm_softc*)devclass_get_softc(psm_devclass, unit))
180
181 /* driver state flags (state) */
182 #define PSM_VALID               0x80
183 #define PSM_OPEN                1       /* Device is open */
184 #define PSM_ASLP                2       /* Waiting for mouse data */
185
186 /* driver configuration flags (config) */
187 #define PSM_CONFIG_RESOLUTION   0x000f  /* resolution */
188 #define PSM_CONFIG_ACCEL        0x00f0  /* acceleration factor */
189 #define PSM_CONFIG_NOCHECKSYNC  0x0100  /* disable sync. test */
190 #define PSM_CONFIG_NOIDPROBE    0x0200  /* disable mouse model probe */
191 #define PSM_CONFIG_NORESET      0x0400  /* don't reset the mouse */
192 #define PSM_CONFIG_FORCETAP     0x0800  /* assume `tap' action exists */
193 #define PSM_CONFIG_IGNPORTERROR 0x1000  /* ignore error in aux port test */
194 #define PSM_CONFIG_HOOKRESUME   0x2000  /* hook the system resume event */
195 #define PSM_CONFIG_INITAFTERSUSPEND 0x4000 /* init the device at the resume event */
196 #define PSM_CONFIG_SYNCHACK     0x8000 /* enable `out-of-sync' hack */
197
198 #define PSM_CONFIG_FLAGS        (PSM_CONFIG_RESOLUTION          \
199                                     | PSM_CONFIG_ACCEL          \
200                                     | PSM_CONFIG_NOCHECKSYNC    \
201                                     | PSM_CONFIG_SYNCHACK       \
202                                     | PSM_CONFIG_NOIDPROBE      \
203                                     | PSM_CONFIG_NORESET        \
204                                     | PSM_CONFIG_FORCETAP       \
205                                     | PSM_CONFIG_IGNPORTERROR   \
206                                     | PSM_CONFIG_HOOKRESUME     \
207                                     | PSM_CONFIG_INITAFTERSUSPEND)
208
209 /* other flags (flags) */
210 #define PSM_FLAGS_FINGERDOWN    0x0001 /* VersaPad finger down */
211
212 /* for backward compatibility */
213 #define OLD_MOUSE_GETHWINFO     _IOR('M', 1, old_mousehw_t)
214 #define OLD_MOUSE_GETMODE       _IOR('M', 2, old_mousemode_t)
215 #define OLD_MOUSE_SETMODE       _IOW('M', 3, old_mousemode_t)
216
217 typedef struct old_mousehw {
218     int buttons;
219     int iftype;
220     int type;
221     int hwid;
222 } old_mousehw_t;
223
224 typedef struct old_mousemode {
225     int protocol;
226     int rate;
227     int resolution;
228     int accelfactor;
229 } old_mousemode_t;
230
231 /* packet formatting function */
232 typedef int packetfunc_t (struct psm_softc *, unsigned char *,
233                               int *, int, mousestatus_t *);
234
235 /* function prototypes */
236 static int psmprobe (device_t);
237 static int psmattach (device_t);
238 static int psmdetach (device_t);
239 static int psmresume (device_t);
240
241 static d_open_t psmopen;
242 static d_close_t psmclose;
243 static d_read_t psmread;
244 static d_ioctl_t psmioctl;
245 static d_poll_t psmpoll;
246 static d_kqfilter_t psmkqfilter;
247
248 static int enable_aux_dev (KBDC);
249 static int disable_aux_dev (KBDC);
250 static int get_mouse_status (KBDC, int *, int, int);
251 static int get_aux_id (KBDC);
252 static int set_mouse_sampling_rate (KBDC, int);
253 static int set_mouse_scaling (KBDC, int);
254 static int set_mouse_resolution (KBDC, int);
255 static int set_mouse_mode (KBDC);
256 static int get_mouse_buttons (KBDC);
257 static int is_a_mouse (int);
258 static void recover_from_error (KBDC);
259 static int restore_controller (KBDC, int);
260 static int doinitialize (struct psm_softc *, mousemode_t *);
261 static int doopen (struct psm_softc *, int);
262 static int reinitialize (struct psm_softc *, int);
263 static char *model_name (int);
264 static void psmintr (void *);
265 static void psmtimeout (void *);
266 static void psmfilter_detach(struct knote *);
267 static int psmfilter(struct knote *, long);
268
269 /* vendor specific features */
270 typedef int probefunc_t (struct psm_softc *);
271
272 static int mouse_id_proc1 (KBDC, int, int, int *);
273 static int mouse_ext_command (KBDC, int);
274 static probefunc_t enable_groller;
275 static probefunc_t enable_gmouse;
276 static probefunc_t enable_aglide; 
277 static probefunc_t enable_kmouse;
278 static probefunc_t enable_msexplorer;
279 static probefunc_t enable_msintelli;
280 static probefunc_t enable_4dmouse;
281 static probefunc_t enable_4dplus;
282 static probefunc_t enable_mmanplus;
283 static probefunc_t enable_versapad;
284 static int tame_mouse (struct psm_softc *, mousestatus_t *, unsigned char *);
285
286 static struct {
287     int                 model;
288     unsigned char       syncmask;
289     int                 packetsize;
290     probefunc_t         *probefunc;
291 } vendortype[] = {
292     /*
293      * WARNING: the order of probe is very important.  Don't mess it
294      * unless you know what you are doing.
295      */
296     { MOUSE_MODEL_NET,                  /* Genius NetMouse */
297       0x08, MOUSE_PS2INTELLI_PACKETSIZE, enable_gmouse, },
298     { MOUSE_MODEL_NETSCROLL,            /* Genius NetScroll */
299       0xc8, 6, enable_groller, },
300     { MOUSE_MODEL_MOUSEMANPLUS,         /* Logitech MouseMan+ */
301       0x08, MOUSE_PS2_PACKETSIZE, enable_mmanplus, },
302     { MOUSE_MODEL_EXPLORER,             /* Microsoft IntelliMouse Explorer */
303       0x08, MOUSE_PS2INTELLI_PACKETSIZE, enable_msexplorer, },
304     { MOUSE_MODEL_4D,                   /* A4 Tech 4D Mouse */
305       0x08, MOUSE_4D_PACKETSIZE, enable_4dmouse, },
306     { MOUSE_MODEL_4DPLUS,               /* A4 Tech 4D+ Mouse */
307       0xc8, MOUSE_4DPLUS_PACKETSIZE, enable_4dplus, },
308     { MOUSE_MODEL_INTELLI,              /* Microsoft IntelliMouse */
309       0x08, MOUSE_PS2INTELLI_PACKETSIZE, enable_msintelli, },
310     { MOUSE_MODEL_GLIDEPOINT,           /* ALPS GlidePoint */
311       0xc0, MOUSE_PS2_PACKETSIZE, enable_aglide, },
312     { MOUSE_MODEL_THINK,                /* Kensignton ThinkingMouse */
313       0x80, MOUSE_PS2_PACKETSIZE, enable_kmouse, },
314     { MOUSE_MODEL_VERSAPAD,             /* Interlink electronics VersaPad */
315       0xe8, MOUSE_PS2VERSA_PACKETSIZE, enable_versapad, },
316     { MOUSE_MODEL_GENERIC,
317       0xc0, MOUSE_PS2_PACKETSIZE, NULL, },
318 };
319 #define GENERIC_MOUSE_ENTRY     ((sizeof(vendortype) / sizeof(*vendortype)) - 1)
320
321 /* device driver declarateion */
322 static device_method_t psm_methods[] = {
323         /* Device interface */
324         DEVMETHOD(device_probe,         psmprobe),
325         DEVMETHOD(device_attach,        psmattach),
326         DEVMETHOD(device_detach,        psmdetach),
327         DEVMETHOD(device_resume,        psmresume),
328
329         { 0, 0 }
330 };
331
332 static driver_t psm_driver = {
333     PSM_DRIVER_NAME,
334     psm_methods,
335     sizeof(struct psm_softc),
336 };
337
338 #if notyet
339 static struct isa_pnp_id psm_ids[] = {
340     { 0x130fd041, "PS/2 mouse port" },                  /* PNP0F13 */
341     { 0x1303d041, "PS/2 port" },                        /* PNP0313, XXX */
342     { 0 }
343 };
344 #endif
345
346 #define CDEV_MAJOR        21
347
348 static struct dev_ops psm_ops = {
349         { PSM_DRIVER_NAME, CDEV_MAJOR, D_KQFILTER },
350         .d_open =       psmopen,
351         .d_close =      psmclose,
352         .d_read =       psmread,
353         .d_ioctl =      psmioctl,
354         .d_poll =       psmpoll,
355         .d_kqfilter =   psmkqfilter
356 };
357
358 /* debug message level */
359 static int verbose = PSM_DEBUG;
360
361 /* device I/O routines */
362 static int
363 enable_aux_dev(KBDC kbdc)
364 {
365     int res;
366
367     res = send_aux_command(kbdc, PSMC_ENABLE_DEV);
368     if (verbose >= 2)
369         log(LOG_DEBUG, "psm: ENABLE_DEV return code:%04x\n", res);
370
371     return (res == PSM_ACK);
372 }
373
374 static int
375 disable_aux_dev(KBDC kbdc)
376 {
377     int res;
378
379     res = send_aux_command(kbdc, PSMC_DISABLE_DEV);
380     if (verbose >= 2)
381         log(LOG_DEBUG, "psm: DISABLE_DEV return code:%04x\n", res);
382
383     return (res == PSM_ACK);
384 }
385
386 static int
387 get_mouse_status(KBDC kbdc, int *status, int flag, int len)
388 {
389     int cmd;
390     int res;
391     int i;
392
393     switch (flag) {
394     case 0:
395     default:
396         cmd = PSMC_SEND_DEV_STATUS;
397         break;
398     case 1:
399         cmd = PSMC_SEND_DEV_DATA;
400         break;
401     }
402     empty_aux_buffer(kbdc, 5);
403     res = send_aux_command(kbdc, cmd);
404     if (verbose >= 2)
405         log(LOG_DEBUG, "psm: SEND_AUX_DEV_%s return code:%04x\n", 
406             (flag == 1) ? "DATA" : "STATUS", res);
407     if (res != PSM_ACK)
408         return 0;
409
410     for (i = 0; i < len; ++i) {
411         status[i] = read_aux_data(kbdc);
412         if (status[i] < 0)
413             break;
414     }
415
416     if (verbose) {
417         log(LOG_DEBUG, "psm: %s %02x %02x %02x\n",
418             (flag == 1) ? "data" : "status", status[0], status[1], status[2]);
419     }
420
421     return i;
422 }
423
424 static int
425 get_aux_id(KBDC kbdc)
426 {
427     int res;
428     int id;
429
430     empty_aux_buffer(kbdc, 5);
431     res = send_aux_command(kbdc, PSMC_SEND_DEV_ID);
432     if (verbose >= 2)
433         log(LOG_DEBUG, "psm: SEND_DEV_ID return code:%04x\n", res);
434     if (res != PSM_ACK)
435         return (-1);
436
437     /* 10ms delay */
438     DRIVERSLEEP(10000);
439
440     id = read_aux_data(kbdc);
441     if (verbose >= 2)
442         log(LOG_DEBUG, "psm: device ID: %04x\n", id);
443
444     return id;
445 }
446
447 static int
448 set_mouse_sampling_rate(KBDC kbdc, int rate)
449 {
450     int res;
451
452     res = send_aux_command_and_data(kbdc, PSMC_SET_SAMPLING_RATE, rate);
453     if (verbose >= 2)
454         log(LOG_DEBUG, "psm: SET_SAMPLING_RATE (%d) %04x\n", rate, res);
455
456     return ((res == PSM_ACK) ? rate : -1);
457 }
458
459 static int
460 set_mouse_scaling(KBDC kbdc, int scale)
461 {
462     int res;
463
464     switch (scale) {
465     case 1:
466     default:
467         scale = PSMC_SET_SCALING11;
468         break;
469     case 2:
470         scale = PSMC_SET_SCALING21;
471         break;
472     }
473     res = send_aux_command(kbdc, scale);
474     if (verbose >= 2)
475         log(LOG_DEBUG, "psm: SET_SCALING%s return code:%04x\n", 
476             (scale == PSMC_SET_SCALING21) ? "21" : "11", res);
477
478     return (res == PSM_ACK);
479 }
480
481 /* `val' must be 0 through PSMD_MAX_RESOLUTION */
482 static int
483 set_mouse_resolution(KBDC kbdc, int val)
484 {
485     int res;
486
487     res = send_aux_command_and_data(kbdc, PSMC_SET_RESOLUTION, val);
488     if (verbose >= 2)
489         log(LOG_DEBUG, "psm: SET_RESOLUTION (%d) %04x\n", val, res);
490
491     return ((res == PSM_ACK) ? val : -1);
492 }
493
494 /*
495  * NOTE: once `set_mouse_mode()' is called, the mouse device must be
496  * re-enabled by calling `enable_aux_dev()'
497  */
498 static int
499 set_mouse_mode(KBDC kbdc)
500 {
501     int res;
502
503     res = send_aux_command(kbdc, PSMC_SET_STREAM_MODE);
504     if (verbose >= 2)
505         log(LOG_DEBUG, "psm: SET_STREAM_MODE return code:%04x\n", res);
506
507     return (res == PSM_ACK);
508 }
509
510 static int
511 get_mouse_buttons(KBDC kbdc)
512 {
513     int c = 2;          /* assume two buttons by default */
514     int status[3];
515
516     /*
517      * NOTE: a special sequence to obtain Logitech Mouse specific
518      * information: set resolution to 25 ppi, set scaling to 1:1, set
519      * scaling to 1:1, set scaling to 1:1. Then the second byte of the
520      * mouse status bytes is the number of available buttons.
521      * Some manufactures also support this sequence.
522      */
523     if (set_mouse_resolution(kbdc, PSMD_RES_LOW) != PSMD_RES_LOW)
524         return c;
525     if (set_mouse_scaling(kbdc, 1) && set_mouse_scaling(kbdc, 1)
526         && set_mouse_scaling(kbdc, 1) 
527         && (get_mouse_status(kbdc, status, 0, 3) >= 3)) {
528         if (status[1] != 0)
529             return status[1];
530     }
531     return c;
532 }
533
534 /* misc subroutines */
535 /*
536  * Someday, I will get the complete list of valid pointing devices and
537  * their IDs... XXX
538  */
539 static int
540 is_a_mouse(int id)
541 {
542 #if 0
543     static int valid_ids[] = {
544         PSM_MOUSE_ID,           /* mouse */
545         PSM_BALLPOINT_ID,       /* ballpoint device */
546         PSM_INTELLI_ID,         /* Intellimouse */
547         PSM_EXPLORER_ID,        /* Intellimouse Explorer */
548         -1                      /* end of table */
549     };
550     int i;
551
552     for (i = 0; valid_ids[i] >= 0; ++i)
553         if (valid_ids[i] == id)
554             return TRUE;
555     return FALSE;
556 #else
557     return TRUE;
558 #endif
559 }
560
561 static char *
562 model_name(int model)
563 {
564     static struct {
565         int model_code;
566         char *model_name;
567     } models[] = {
568         { MOUSE_MODEL_NETSCROLL,        "NetScroll" },
569         { MOUSE_MODEL_NET,              "NetMouse/NetScroll Optical" },
570         { MOUSE_MODEL_GLIDEPOINT,       "GlidePoint" },
571         { MOUSE_MODEL_THINK,            "ThinkingMouse" },
572         { MOUSE_MODEL_INTELLI,          "IntelliMouse" },
573         { MOUSE_MODEL_MOUSEMANPLUS,     "MouseMan+" },
574         { MOUSE_MODEL_VERSAPAD,         "VersaPad" },
575         { MOUSE_MODEL_EXPLORER,         "IntelliMouse Explorer" },
576         { MOUSE_MODEL_4D,               "4D Mouse" },
577         { MOUSE_MODEL_4DPLUS,           "4D+ Mouse" },
578         { MOUSE_MODEL_GENERIC,          "Generic PS/2 mouse" },
579         { MOUSE_MODEL_UNKNOWN,          NULL },
580     };
581     int i;
582
583     for (i = 0; models[i].model_code != MOUSE_MODEL_UNKNOWN; ++i) {
584         if (models[i].model_code == model)
585             return models[i].model_name;
586     }
587     return "Unknown";
588 }
589
590 static void
591 recover_from_error(KBDC kbdc)
592 {
593     /* discard anything left in the output buffer */
594     empty_both_buffers(kbdc, 10);
595
596 #if 0
597     /*
598      * NOTE: KBDC_RESET_KBD may not restore the communication between the
599      * keyboard and the controller.
600      */
601     reset_kbd(kbdc);
602 #else
603     /*
604      * NOTE: somehow diagnostic and keyboard port test commands bring the
605      * keyboard back.
606      */
607     if (!test_controller(kbdc)) 
608         log(LOG_ERR, "psm: keyboard controller failed.\n");
609     /* if there isn't a keyboard in the system, the following error is OK */
610     if (test_kbd_port(kbdc) != 0) {
611         if (verbose)
612             log(LOG_ERR, "psm: keyboard port failed.\n");
613     }
614 #endif
615 }
616
617 static int
618 restore_controller(KBDC kbdc, int command_byte)
619 {
620     empty_both_buffers(kbdc, 10);
621
622     if (!set_controller_command_byte(kbdc, 0xff, command_byte)) {
623         log(LOG_ERR, "psm: failed to restore the keyboard controller "
624                      "command byte.\n");
625         empty_both_buffers(kbdc, 10);
626         return FALSE;
627     } else {
628         empty_both_buffers(kbdc, 10);
629         return TRUE;
630     }
631 }
632
633 /* 
634  * Re-initialize the aux port and device. The aux port must be enabled
635  * and its interrupt must be disabled before calling this routine. 
636  * The aux device will be disabled before returning.
637  * The keyboard controller must be locked via `kbdc_lock()' before
638  * calling this routine.
639  */
640 static int
641 doinitialize(struct psm_softc *sc, mousemode_t *mode)
642 {
643     KBDC kbdc = sc->kbdc;
644     int stat[3];
645     int i;
646
647     switch((i = test_aux_port(kbdc))) {
648     case 1:     /* ignore this error */
649     case 2:     /* Ignore 2 and 3 for use with some acer and compal laptops */
650     case 3:
651     case PSM_ACK:
652         if (verbose)
653             log(LOG_DEBUG, "psm%d: strange result for test aux port (%d).\n",
654                 sc->unit, i);
655         /* fall though */
656     case 0:     /* no error */
657         break;
658     case -1:    /* time out */
659     default:    /* error */
660         recover_from_error(kbdc);
661         if (sc->config & PSM_CONFIG_IGNPORTERROR)
662             break;
663         log(LOG_ERR, "psm%d: the aux port is not functioning (%d).\n",
664             sc->unit, i);
665         return FALSE;
666     }
667
668     if (sc->config & PSM_CONFIG_NORESET) {
669         /* 
670          * Don't try to reset the pointing device.  It may possibly be
671          * left in the unknown state, though...
672          */
673     } else {
674         /* 
675          * NOTE: some controllers appears to hang the `keyboard' when
676          * the aux port doesn't exist and `PSMC_RESET_DEV' is issued. 
677          */
678         if (!reset_aux_dev(kbdc)) {
679             recover_from_error(kbdc);
680             log(LOG_ERR, "psm%d: failed to reset the aux device.\n", sc->unit);
681             return FALSE;
682         }
683     }
684
685     /* 
686      * both the aux port and the aux device is functioning, see
687      * if the device can be enabled. 
688      */
689     if (!enable_aux_dev(kbdc) || !disable_aux_dev(kbdc)) {
690         log(LOG_ERR, "psm%d: failed to enable the aux device.\n", sc->unit);
691         return FALSE;
692     }
693     empty_both_buffers(kbdc, 10);       /* remove stray data if any */
694
695     if (sc->config & PSM_CONFIG_NOIDPROBE) {
696         i = GENERIC_MOUSE_ENTRY;
697     } else {
698         /* FIXME: hardware ID, mouse buttons? */
699
700         /* other parameters */
701         for (i = 0; vendortype[i].probefunc != NULL; ++i) {
702             if ((*vendortype[i].probefunc)(sc)) {
703                 if (verbose >= 2)
704                     log(LOG_ERR, "psm%d: found %s\n", 
705                         sc->unit, model_name(vendortype[i].model));
706                 break;
707             }
708         }
709     }
710
711     sc->hw.model = vendortype[i].model;
712     sc->mode.packetsize = vendortype[i].packetsize;
713
714     /* set mouse parameters */
715     if (mode != NULL) {
716         if (mode->rate > 0)
717             mode->rate = set_mouse_sampling_rate(kbdc, mode->rate);
718         if (mode->resolution >= 0)
719             mode->resolution = set_mouse_resolution(kbdc, mode->resolution);
720         set_mouse_scaling(kbdc, 1);
721         set_mouse_mode(kbdc);   
722     }
723
724     /* request a data packet and extract sync. bits */
725     if (get_mouse_status(kbdc, stat, 1, 3) < 3) {
726         log(LOG_DEBUG, "psm%d: failed to get data (doinitialize).\n",
727             sc->unit);
728         sc->mode.syncmask[0] = 0;
729     } else {
730         sc->mode.syncmask[1] = stat[0] & sc->mode.syncmask[0];  /* syncbits */
731         /* the NetScroll Mouse will send three more bytes... Ignore them */
732         empty_aux_buffer(kbdc, 5);
733     }
734
735     /* just check the status of the mouse */
736     if (get_mouse_status(kbdc, stat, 0, 3) < 3)
737         log(LOG_DEBUG, "psm%d: failed to get status (doinitialize).\n",
738             sc->unit);
739
740     return TRUE;
741 }
742
743 static int
744 doopen(struct psm_softc *sc, int command_byte)
745 {
746     int stat[3];
747
748     /* enable the mouse device */
749     if (!enable_aux_dev(sc->kbdc)) {
750         /* MOUSE ERROR: failed to enable the mouse because:
751          * 1) the mouse is faulty,
752          * 2) the mouse has been removed(!?)
753          * In the latter case, the keyboard may have hung, and need 
754          * recovery procedure...
755          */
756         recover_from_error(sc->kbdc);
757 #if 0
758         /* FIXME: we could reset the mouse here and try to enable
759          * it again. But it will take long time and it's not a good
760          * idea to disable the keyboard that long...
761          */
762         if (!doinitialize(sc, &sc->mode) || !enable_aux_dev(sc->kbdc)) {
763             recover_from_error(sc->kbdc);
764 #else
765         {
766 #endif
767             restore_controller(sc->kbdc, command_byte);
768             /* mark this device is no longer available */
769             sc->state &= ~PSM_VALID;    
770             log(LOG_ERR, "psm%d: failed to enable the device (doopen).\n",
771                 sc->unit);
772             return (EIO);
773         }
774     }
775
776     if (get_mouse_status(sc->kbdc, stat, 0, 3) < 3) 
777         log(LOG_DEBUG, "psm%d: failed to get status (doopen).\n", sc->unit);
778
779     /* enable the aux port and interrupt */
780     if (!set_controller_command_byte(sc->kbdc, 
781             kbdc_get_device_mask(sc->kbdc),
782             (command_byte & KBD_KBD_CONTROL_BITS)
783                 | KBD_ENABLE_AUX_PORT | KBD_ENABLE_AUX_INT)) {
784         /* CONTROLLER ERROR */
785         disable_aux_dev(sc->kbdc);
786         restore_controller(sc->kbdc, command_byte);
787         log(LOG_ERR, "psm%d: failed to enable the aux interrupt (doopen).\n",
788             sc->unit);
789         return (EIO);
790     }
791
792     /* start the watchdog timer */
793     sc->watchdog = FALSE;
794     callout_reset(&sc->callout, hz * 2, psmtimeout, (void *)(uintptr_t)sc);
795
796     return (0);
797 }
798
799 static int
800 reinitialize(struct psm_softc *sc, int doinit)
801 {
802     int err;
803     int c;
804
805     /* don't let anybody mess with the aux device */
806     if (!kbdc_lock(sc->kbdc, TRUE))
807         return (EIO);
808     crit_enter();
809
810     /* block our watchdog timer */
811     sc->watchdog = FALSE;
812     callout_stop(&sc->callout);
813
814     /* save the current controller command byte */
815     empty_both_buffers(sc->kbdc, 10);
816     c = get_controller_command_byte(sc->kbdc);
817     if (verbose >= 2)
818         log(LOG_DEBUG, "psm%d: current command byte: %04x (reinitialize).\n", 
819             sc->unit, c);
820
821     /* enable the aux port but disable the aux interrupt and the keyboard */
822     if ((c == -1) || !set_controller_command_byte(sc->kbdc,
823             kbdc_get_device_mask(sc->kbdc),
824             KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT
825                 | KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
826         /* CONTROLLER ERROR */
827         crit_exit();
828         kbdc_lock(sc->kbdc, FALSE);
829         log(LOG_ERR, "psm%d: unable to set the command byte (reinitialize).\n",
830             sc->unit);
831         return (EIO);
832     }
833
834     /* flush any data */
835     if (sc->state & PSM_VALID) {
836         disable_aux_dev(sc->kbdc);      /* this may fail; but never mind... */
837         empty_aux_buffer(sc->kbdc, 10);
838     }
839     sc->inputbytes = 0;
840     sc->syncerrors = 0;
841
842     /* try to detect the aux device; are you still there? */
843     err = 0;
844     if (doinit) {
845         if (doinitialize(sc, &sc->mode)) {
846             /* yes */
847             sc->state |= PSM_VALID;
848         } else {
849             /* the device has gone! */
850             restore_controller(sc->kbdc, c);
851             sc->state &= ~PSM_VALID;
852             log(LOG_ERR, "psm%d: the aux device has gone! (reinitialize).\n",
853                 sc->unit);
854             err = ENXIO;
855         }
856     }
857     crit_exit();
858
859     /* restore the driver state */
860     if ((sc->state & PSM_OPEN) && (err == 0)) {
861         /* enable the aux device and the port again */
862         err = doopen(sc, c);
863         if (err != 0) 
864             log(LOG_ERR, "psm%d: failed to enable the device (reinitialize).\n",
865                 sc->unit);
866     } else {
867         /* restore the keyboard port and disable the aux port */
868         if (!set_controller_command_byte(sc->kbdc, 
869                 kbdc_get_device_mask(sc->kbdc),
870                 (c & KBD_KBD_CONTROL_BITS)
871                     | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
872             /* CONTROLLER ERROR */
873             log(LOG_ERR, "psm%d: failed to disable the aux port (reinitialize).\n",
874                 sc->unit);
875             err = EIO;
876         }
877     }
878
879     kbdc_lock(sc->kbdc, FALSE);
880     return (err);
881 }
882
883 /* psm driver entry points */
884
885 #define endprobe(v)     {   if (bootverbose)                            \
886                                 --verbose;                              \
887                             kbdc_set_device_mask(sc->kbdc, mask);       \
888                             kbdc_lock(sc->kbdc, FALSE);                 \
889                             return (v);                                 \
890                         }
891
892 static int
893 psmprobe(device_t dev)
894 {
895     int unit = device_get_unit(dev);
896     struct psm_softc *sc = device_get_softc(dev);
897     uintptr_t irq;
898     uintptr_t flags;
899     int stat[3];
900     int command_byte;
901     int mask;
902     int rid;
903     int i;
904
905 #if 0
906     kbdc_debug(TRUE);
907 #endif
908
909 #if notyet
910     /* check PnP IDs */
911     if (XXX_PNP_PROBE(device_get_parent(dev), dev, psm_ids) == ENXIO)
912         return ENXIO;
913 #endif
914
915     BUS_READ_IVAR(device_get_parent(dev), dev, KBDC_IVAR_IRQ, &irq);
916     BUS_READ_IVAR(device_get_parent(dev), dev, KBDC_IVAR_FLAGS, &flags);
917
918     sc->unit = unit;
919     sc->kbdc = atkbdc_open(device_get_unit(device_get_parent(dev)));
920     sc->config = flags & PSM_CONFIG_FLAGS;
921     /* XXX: for backward compatibility */
922 #if defined(PSM_HOOKRESUME) || defined(PSM_HOOKAPM)
923     sc->config |= 
924 #ifdef PSM_RESETAFTERSUSPEND
925         PSM_CONFIG_HOOKRESUME | PSM_CONFIG_INITAFTERSUSPEND;
926 #else
927         PSM_CONFIG_HOOKRESUME;
928 #endif
929 #endif /* PSM_HOOKRESUME | PSM_HOOKAPM */
930     sc->flags = 0;
931     if (bootverbose)
932         ++verbose;
933
934     device_set_desc(dev, "PS/2 Mouse");
935
936     if (!kbdc_lock(sc->kbdc, TRUE)) {
937         kprintf("psm%d: unable to lock the controller.\n", unit);
938         if (bootverbose)
939             --verbose;
940         return (ENXIO);
941     }
942
943     /*
944      * NOTE: two bits in the command byte controls the operation of the
945      * aux port (mouse port): the aux port disable bit (bit 5) and the aux
946      * port interrupt (IRQ 12) enable bit (bit 2).
947      */
948
949     /* discard anything left after the keyboard initialization */
950     empty_both_buffers(sc->kbdc, 10);
951
952     /* save the current command byte; it will be used later */
953     mask = kbdc_get_device_mask(sc->kbdc) & ~KBD_AUX_CONTROL_BITS;
954     command_byte = get_controller_command_byte(sc->kbdc);
955     if (verbose) 
956         kprintf("psm%d: current command byte:%04x\n", unit, command_byte);
957     if (command_byte == -1) {
958         /* CONTROLLER ERROR */
959         kprintf("psm%d: unable to get the current command byte value.\n",
960             unit);
961         endprobe(ENXIO);
962     }
963
964     /*
965      * disable the keyboard port while probing the aux port, which must be
966      * enabled during this routine
967      */
968     if (!set_controller_command_byte(sc->kbdc,
969             KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS,
970             KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT
971                 | KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
972         /* 
973          * this is CONTROLLER ERROR; I don't know how to recover 
974          * from this error... 
975          */
976         restore_controller(sc->kbdc, command_byte);
977         kprintf("psm%d: unable to set the command byte.\n", unit);
978         endprobe(ENXIO);
979     }
980     write_controller_command(sc->kbdc, KBDC_ENABLE_AUX_PORT);
981
982     /*
983      * NOTE: `test_aux_port()' is designed to return with zero if the aux
984      * port exists and is functioning. However, some controllers appears
985      * to respond with zero even when the aux port doesn't exist. (It may
986      * be that this is only the case when the controller DOES have the aux
987      * port but the port is not wired on the motherboard.) The keyboard
988      * controllers without the port, such as the original AT, are
989      * supporsed to return with an error code or simply time out. In any
990      * case, we have to continue probing the port even when the controller
991      * passes this test.
992      *
993      * XXX: some controllers erroneously return the error code 1 when
994      * it has the perfectly functional aux port. We have to ignore this
995      * error code. Even if the controller HAS error with the aux port,
996      * it will be detected later...
997      * XXX: another incompatible controller returns PSM_ACK (0xfa)...
998      */
999     switch ((i = test_aux_port(sc->kbdc))) {
1000     case 1:        /* ignore this error */
1001     case 2:     /* Ignore 2 and 3 for use with some acer and compal laptops */
1002     case 3:
1003     case PSM_ACK:
1004         if (verbose)
1005             kprintf("psm%d: strange result for test aux port (%d).\n",
1006                 unit, i);
1007         /* fall though */
1008     case 0:        /* no error */
1009         break;
1010     case -1:        /* time out */
1011     default:        /* error */
1012         recover_from_error(sc->kbdc);
1013         if (sc->config & PSM_CONFIG_IGNPORTERROR)
1014             break;
1015         restore_controller(sc->kbdc, command_byte);
1016         if (verbose)
1017             kprintf("psm%d: the aux port is not functioning (%d).\n",
1018                 unit, i);
1019         endprobe(ENXIO);
1020     }
1021
1022     if (sc->config & PSM_CONFIG_NORESET) {
1023         /* 
1024          * Don't try to reset the pointing device.  It may possibly be
1025          * left in the unknown state, though...
1026          */
1027     } else {
1028         /*
1029          * NOTE: some controllers appears to hang the `keyboard' when the aux
1030          * port doesn't exist and `PSMC_RESET_DEV' is issued.
1031          *
1032          * Attempt to reset the controller twice -- this helps
1033          * pierce through some KVM switches. The second reset
1034          * is non-fatal.
1035          */
1036         if (!reset_aux_dev(sc->kbdc)) {
1037             recover_from_error(sc->kbdc);
1038             restore_controller(sc->kbdc, command_byte);
1039             if (verbose)
1040                 kprintf("psm%d: failed to reset the aux device.\n", unit);
1041             endprobe(ENXIO);
1042         } else if (!reset_aux_dev(sc->kbdc)) {
1043             recover_from_error(sc->kbdc);
1044             if (verbose >= 2)
1045                 kprintf("psm%d: failed to reset the aux device (2).\n",
1046                     unit);
1047         }
1048     }
1049
1050     /*
1051      * both the aux port and the aux device is functioning, see if the
1052      * device can be enabled. NOTE: when enabled, the device will start
1053      * sending data; we shall immediately disable the device once we know
1054      * the device can be enabled.
1055      */
1056     if (!enable_aux_dev(sc->kbdc) || !disable_aux_dev(sc->kbdc)) {
1057         /* MOUSE ERROR */
1058         recover_from_error(sc->kbdc);
1059         restore_controller(sc->kbdc, command_byte);
1060         if (verbose)
1061             kprintf("psm%d: failed to enable the aux device.\n", unit);
1062         endprobe(ENXIO);
1063     }
1064
1065     /* save the default values after reset */
1066     if (get_mouse_status(sc->kbdc, stat, 0, 3) >= 3) {
1067         sc->dflt_mode.rate = sc->mode.rate = stat[2];
1068         sc->dflt_mode.resolution = sc->mode.resolution = stat[1];
1069     } else {
1070         sc->dflt_mode.rate = sc->mode.rate = -1;
1071         sc->dflt_mode.resolution = sc->mode.resolution = -1;
1072     }
1073
1074     /* hardware information */
1075     sc->hw.iftype = MOUSE_IF_PS2;
1076
1077     /* verify the device is a mouse */
1078     sc->hw.hwid = get_aux_id(sc->kbdc);
1079     if (!is_a_mouse(sc->hw.hwid)) {
1080         restore_controller(sc->kbdc, command_byte);
1081         if (verbose)
1082             kprintf("psm%d: unknown device type (%d).\n", unit, sc->hw.hwid);
1083         endprobe(ENXIO);
1084     }
1085     switch (sc->hw.hwid) {
1086     case PSM_BALLPOINT_ID:
1087         sc->hw.type = MOUSE_TRACKBALL;
1088         break;
1089     case PSM_MOUSE_ID:
1090     case PSM_INTELLI_ID:
1091     case PSM_EXPLORER_ID:
1092     case PSM_4DMOUSE_ID:
1093     case PSM_4DPLUS_ID:
1094         sc->hw.type = MOUSE_MOUSE;
1095         break;
1096     default:
1097         sc->hw.type = MOUSE_UNKNOWN;
1098         break;
1099     }
1100
1101     if (sc->config & PSM_CONFIG_NOIDPROBE) {
1102         sc->hw.buttons = 2;
1103         i = GENERIC_MOUSE_ENTRY;
1104     } else {
1105         /* # of buttons */
1106         sc->hw.buttons = get_mouse_buttons(sc->kbdc);
1107
1108         /* other parameters */
1109         for (i = 0; vendortype[i].probefunc != NULL; ++i) {
1110             if ((*vendortype[i].probefunc)(sc)) {
1111                 if (verbose >= 2)
1112                     kprintf("psm%d: found %s\n",
1113                            unit, model_name(vendortype[i].model));
1114                 break;
1115             }
1116         }
1117     }
1118
1119     sc->hw.model = vendortype[i].model;
1120
1121     sc->dflt_mode.level = PSM_LEVEL_BASE;
1122     sc->dflt_mode.packetsize = MOUSE_PS2_PACKETSIZE;
1123     sc->dflt_mode.accelfactor = (sc->config & PSM_CONFIG_ACCEL) >> 4;
1124     if (sc->config & PSM_CONFIG_NOCHECKSYNC)
1125         sc->dflt_mode.syncmask[0] = 0;
1126     else
1127         sc->dflt_mode.syncmask[0] = vendortype[i].syncmask;
1128     if (sc->config & PSM_CONFIG_FORCETAP)
1129         sc->mode.syncmask[0] &= ~MOUSE_PS2_TAP;
1130     sc->dflt_mode.syncmask[1] = 0;      /* syncbits */
1131     sc->mode = sc->dflt_mode;
1132     sc->mode.packetsize = vendortype[i].packetsize;
1133
1134     /* set mouse parameters */
1135 #if 0
1136     /* 
1137      * A version of Logitech FirstMouse+ won't report wheel movement,
1138      * if SET_DEFAULTS is sent...  Don't use this command.
1139      * This fix was found by Takashi Nishida.
1140      */
1141     i = send_aux_command(sc->kbdc, PSMC_SET_DEFAULTS);
1142     if (verbose >= 2)
1143         kprintf("psm%d: SET_DEFAULTS return code:%04x\n", unit, i);
1144 #endif
1145     if (sc->config & PSM_CONFIG_RESOLUTION) {
1146         sc->mode.resolution
1147             = set_mouse_resolution(sc->kbdc, 
1148                                    (sc->config & PSM_CONFIG_RESOLUTION) - 1);
1149     } else if (sc->mode.resolution >= 0) {
1150         sc->mode.resolution
1151             = set_mouse_resolution(sc->kbdc, sc->dflt_mode.resolution);
1152     }
1153     if (sc->mode.rate > 0) {
1154         sc->mode.rate = set_mouse_sampling_rate(sc->kbdc, sc->dflt_mode.rate);
1155     }
1156     set_mouse_scaling(sc->kbdc, 1);
1157
1158     /* request a data packet and extract sync. bits */
1159     if (get_mouse_status(sc->kbdc, stat, 1, 3) < 3) {
1160         kprintf("psm%d: failed to get data.\n", unit);
1161         sc->mode.syncmask[0] = 0;
1162     } else {
1163         sc->mode.syncmask[1] = stat[0] & sc->mode.syncmask[0];  /* syncbits */
1164         /* the NetScroll Mouse will send three more bytes... Ignore them */
1165         empty_aux_buffer(sc->kbdc, 5);
1166     }
1167
1168     /* just check the status of the mouse */
1169     /* 
1170      * NOTE: XXX there are some arcane controller/mouse combinations out 
1171      * there, which hung the controller unless there is data transmission 
1172      * after ACK from the mouse.
1173      */
1174     if (get_mouse_status(sc->kbdc, stat, 0, 3) < 3) {
1175         kprintf("psm%d: failed to get status.\n", unit);
1176     } else {
1177         /* 
1178          * When in its native mode, some mice operate with different 
1179          * default parameters than in the PS/2 compatible mode.
1180          */
1181         sc->dflt_mode.rate = sc->mode.rate = stat[2];
1182         sc->dflt_mode.resolution = sc->mode.resolution = stat[1];
1183      }
1184
1185     /* disable the aux port for now... */
1186     if (!set_controller_command_byte(sc->kbdc, 
1187             KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS,
1188             (command_byte & KBD_KBD_CONTROL_BITS)
1189                 | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
1190         /* 
1191          * this is CONTROLLER ERROR; I don't know the proper way to 
1192          * recover from this error... 
1193          */
1194         restore_controller(sc->kbdc, command_byte);
1195         kprintf("psm%d: unable to set the command byte.\n", unit);
1196         endprobe(ENXIO);
1197     }
1198
1199     /* see if IRQ is available */
1200     rid = 0;
1201     sc->intr = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, irq, irq, 1,
1202                                   RF_ACTIVE);
1203     if (sc->intr == NULL) {
1204         kprintf("psm%d: unable to allocate the IRQ resource (%d).\n",
1205                unit, (int)irq);
1206         endprobe(ENXIO);
1207     } else {
1208         bus_release_resource(dev, SYS_RES_IRQ, rid, sc->intr);
1209     }
1210
1211     /* done */
1212     kbdc_set_device_mask(sc->kbdc, mask | KBD_AUX_CONTROL_BITS);
1213     kbdc_lock(sc->kbdc, FALSE);
1214     return (0);
1215 }
1216
1217 static int
1218 psmattach(device_t dev)
1219 {
1220     int unit = device_get_unit(dev);
1221     struct psm_softc *sc = device_get_softc(dev);
1222     uintptr_t irq;
1223     int error;
1224     int rid;
1225
1226     if (sc == NULL)    /* shouldn't happen */
1227         return (ENXIO);
1228
1229     /* Setup initial state */
1230     sc->state = PSM_VALID;
1231     callout_init(&sc->callout);
1232
1233     /* Setup our interrupt handler */
1234     rid = 0;
1235     BUS_READ_IVAR(device_get_parent(dev), dev, KBDC_IVAR_IRQ, &irq);
1236     sc->intr = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, irq, irq, 1,
1237                                   RF_ACTIVE);
1238     if (sc->intr == NULL)
1239         return (ENXIO);
1240     error = BUS_SETUP_INTR(device_get_parent(dev), dev, sc->intr,
1241                            INTR_NOPOLL, psmintr, sc, &sc->ih, NULL);
1242     if (error) {
1243         bus_release_resource(dev, SYS_RES_IRQ, rid, sc->intr);
1244         return (error);
1245     }
1246
1247     /* Done */
1248     make_dev(&psm_ops, PSM_MKMINOR(unit, FALSE), 0, 0, 0666, "psm%d", unit);
1249     make_dev(&psm_ops, PSM_MKMINOR(unit, TRUE), 0, 0, 0666, "bpsm%d", unit);
1250
1251     if (!verbose) {
1252         kprintf("psm%d: model %s, device ID %d\n", 
1253             unit, model_name(sc->hw.model), sc->hw.hwid & 0x00ff);
1254     } else {
1255         kprintf("psm%d: model %s, device ID %d-%02x, %d buttons\n",
1256             unit, model_name(sc->hw.model),
1257             sc->hw.hwid & 0x00ff, sc->hw.hwid >> 8, sc->hw.buttons);
1258         kprintf("psm%d: config:%08x, flags:%08x, packet size:%d\n",
1259             unit, sc->config, sc->flags, sc->mode.packetsize);
1260         kprintf("psm%d: syncmask:%02x, syncbits:%02x\n",
1261             unit, sc->mode.syncmask[0], sc->mode.syncmask[1]);
1262     }
1263
1264     if (bootverbose)
1265         --verbose;
1266
1267     return (0);
1268 }
1269
1270 static int
1271 psmdetach(device_t dev)
1272 {
1273     struct psm_softc *sc;
1274     int rid;
1275     int unit;
1276
1277     sc = device_get_softc(dev);
1278     if (sc->state & PSM_OPEN)
1279         return EBUSY;
1280
1281     unit = device_get_unit(dev);
1282
1283     rid = 0;
1284     BUS_TEARDOWN_INTR(device_get_parent(dev), dev, sc->intr, sc->ih);
1285     bus_release_resource(dev, SYS_RES_IRQ, rid, sc->intr);
1286     kprintf("devfs: Please make sure that only the right psm device was removed!!!!\n");
1287     dev_ops_remove_minor(&psm_ops, /*PSM_MKMINOR(-1, 0), */PSM_MKMINOR(unit, 0));
1288
1289     return 0;
1290 }
1291
1292 static int
1293 psmopen(struct dev_open_args *ap)
1294 {
1295     cdev_t dev = ap->a_head.a_dev;
1296     int unit = PSM_UNIT(dev);
1297     struct psm_softc *sc;
1298     int command_byte;
1299     int err;
1300
1301     /* Get device data */
1302     sc = PSM_SOFTC(unit);
1303     if ((sc == NULL) || (sc->state & PSM_VALID) == 0)
1304         /* the device is no longer valid/functioning */
1305         return (ENXIO);
1306
1307     /* Disallow multiple opens */
1308     if (sc->state & PSM_OPEN)
1309         return (EBUSY);
1310
1311 #if 0
1312     device_busy(devclass_get_device(psm_devclass, unit));
1313 #endif
1314
1315     /* Initialize state */
1316     sc->rsel.si_flags = 0;
1317     sc->rsel.si_pid = 0;
1318     sc->mode.level = sc->dflt_mode.level;
1319     sc->mode.protocol = sc->dflt_mode.protocol;
1320     sc->watchdog = FALSE;
1321
1322     /* flush the event queue */
1323     sc->queue.count = 0;
1324     sc->queue.head = 0;
1325     sc->queue.tail = 0;
1326     sc->status.flags = 0;
1327     sc->status.button = 0;
1328     sc->status.obutton = 0;
1329     sc->status.dx = 0;
1330     sc->status.dy = 0;
1331     sc->status.dz = 0;
1332     sc->button = 0;
1333
1334     /* empty input buffer */
1335     bzero(sc->ipacket, sizeof(sc->ipacket));
1336     sc->inputbytes = 0;
1337     sc->syncerrors = 0;
1338
1339     /* don't let timeout routines in the keyboard driver to poll the kbdc */
1340     if (!kbdc_lock(sc->kbdc, TRUE))
1341         return (EIO);
1342
1343     /* save the current controller command byte */
1344     crit_enter();
1345     command_byte = get_controller_command_byte(sc->kbdc);
1346
1347     /* enable the aux port and temporalily disable the keyboard */
1348     if ((command_byte == -1) 
1349         || !set_controller_command_byte(sc->kbdc,
1350             kbdc_get_device_mask(sc->kbdc),
1351             KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT
1352                 | KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
1353         /* CONTROLLER ERROR; do you know how to get out of this? */
1354         kbdc_lock(sc->kbdc, FALSE);
1355         crit_exit();
1356         log(LOG_ERR, "psm%d: unable to set the command byte (psmopen).\n",
1357             unit);
1358         return (EIO);
1359     }
1360     /* 
1361      * Now that the keyboard controller is told not to generate 
1362      * the keyboard and mouse interrupts, call `splx()' to allow 
1363      * the other tty interrupts. The clock interrupt may also occur, 
1364      * but timeout routines will be blocked by the poll flag set 
1365      * via `kbdc_lock()'
1366      */
1367     crit_exit();
1368   
1369     /* enable the mouse device */
1370     err = doopen(sc, command_byte);
1371
1372     /* done */
1373     if (err == 0) 
1374         sc->state |= PSM_OPEN;
1375     kbdc_lock(sc->kbdc, FALSE);
1376     return (err);
1377 }
1378
1379 static int
1380 psmclose(struct dev_close_args *ap)
1381 {
1382     cdev_t dev = ap->a_head.a_dev;
1383     int unit = PSM_UNIT(dev);
1384     struct psm_softc *sc = PSM_SOFTC(unit);
1385     int stat[3];
1386     int command_byte;
1387
1388     /* don't let timeout routines in the keyboard driver to poll the kbdc */
1389     if (!kbdc_lock(sc->kbdc, TRUE))
1390         return (EIO);
1391
1392     /* save the current controller command byte */
1393     crit_enter();
1394     command_byte = get_controller_command_byte(sc->kbdc);
1395     if (command_byte == -1) {
1396         kbdc_lock(sc->kbdc, FALSE);
1397         crit_exit();
1398         return (EIO);
1399     }
1400
1401     /* disable the aux interrupt and temporalily disable the keyboard */
1402     if (!set_controller_command_byte(sc->kbdc, 
1403             kbdc_get_device_mask(sc->kbdc),
1404             KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT
1405                 | KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
1406         log(LOG_ERR, "psm%d: failed to disable the aux int (psmclose).\n",
1407             unit);
1408         /* CONTROLLER ERROR;
1409          * NOTE: we shall force our way through. Because the only
1410          * ill effect we shall see is that we may not be able
1411          * to read ACK from the mouse, and it doesn't matter much 
1412          * so long as the mouse will accept the DISABLE command.
1413          */
1414     }
1415     crit_exit();
1416
1417     /* stop the watchdog timer */
1418     callout_stop(&sc->callout);
1419
1420     /* remove anything left in the output buffer */
1421     empty_aux_buffer(sc->kbdc, 10);
1422
1423     /* disable the aux device, port and interrupt */
1424     if (sc->state & PSM_VALID) {
1425         if (!disable_aux_dev(sc->kbdc)) {
1426             /* MOUSE ERROR; 
1427              * NOTE: we don't return error and continue, pretending 
1428              * we have successfully disabled the device. It's OK because 
1429              * the interrupt routine will discard any data from the mouse
1430              * hereafter. 
1431              */
1432             log(LOG_ERR, "psm%d: failed to disable the device (psmclose).\n",
1433                 unit);
1434         }
1435
1436         if (get_mouse_status(sc->kbdc, stat, 0, 3) < 3)
1437             log(LOG_DEBUG, "psm%d: failed to get status (psmclose).\n", 
1438                 unit);
1439     }
1440
1441     if (!set_controller_command_byte(sc->kbdc, 
1442             kbdc_get_device_mask(sc->kbdc),
1443             (command_byte & KBD_KBD_CONTROL_BITS)
1444                 | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
1445         /* CONTROLLER ERROR; 
1446          * we shall ignore this error; see the above comment.
1447          */
1448         log(LOG_ERR, "psm%d: failed to disable the aux port (psmclose).\n",
1449             unit);
1450     }
1451
1452     /* remove anything left in the output buffer */
1453     empty_aux_buffer(sc->kbdc, 10);
1454
1455     /* close is almost always successful */
1456     sc->state &= ~PSM_OPEN;
1457     kbdc_lock(sc->kbdc, FALSE);
1458 #if 0
1459     device_unbusy(devclass_get_device(psm_devclass, unit));
1460 #endif
1461     return (0);
1462 }
1463
1464 static int
1465 tame_mouse(struct psm_softc *sc, mousestatus_t *status, unsigned char *buf)
1466 {
1467     static unsigned char butmapps2[8] = {
1468         0,
1469         MOUSE_PS2_BUTTON1DOWN, 
1470         MOUSE_PS2_BUTTON2DOWN,
1471         MOUSE_PS2_BUTTON1DOWN | MOUSE_PS2_BUTTON2DOWN,
1472         MOUSE_PS2_BUTTON3DOWN,
1473         MOUSE_PS2_BUTTON1DOWN | MOUSE_PS2_BUTTON3DOWN,
1474         MOUSE_PS2_BUTTON2DOWN | MOUSE_PS2_BUTTON3DOWN,
1475         MOUSE_PS2_BUTTON1DOWN | MOUSE_PS2_BUTTON2DOWN | MOUSE_PS2_BUTTON3DOWN,
1476     };
1477     static unsigned char butmapmsc[8] = {
1478         MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP,
1479         MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP,
1480         MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP,
1481         MOUSE_MSC_BUTTON3UP,
1482         MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP,
1483         MOUSE_MSC_BUTTON2UP,
1484         MOUSE_MSC_BUTTON1UP, 
1485         0,
1486     };
1487     int mapped;
1488     int i;
1489
1490     if (sc->mode.level == PSM_LEVEL_BASE) {
1491         mapped = status->button & ~MOUSE_BUTTON4DOWN;
1492         if (status->button & MOUSE_BUTTON4DOWN) 
1493             mapped |= MOUSE_BUTTON1DOWN;
1494         status->button = mapped;
1495         buf[0] = MOUSE_PS2_SYNC | butmapps2[mapped & MOUSE_STDBUTTONS];
1496         i = max(min(status->dx, 255), -256);
1497         if (i < 0)
1498             buf[0] |= MOUSE_PS2_XNEG;
1499         buf[1] = i;
1500         i = max(min(status->dy, 255), -256);
1501         if (i < 0)
1502             buf[0] |= MOUSE_PS2_YNEG;
1503         buf[2] = i;
1504         return MOUSE_PS2_PACKETSIZE;
1505     } else if (sc->mode.level == PSM_LEVEL_STANDARD) {
1506         buf[0] = MOUSE_MSC_SYNC | butmapmsc[status->button & MOUSE_STDBUTTONS];
1507         i = max(min(status->dx, 255), -256);
1508         buf[1] = i >> 1;
1509         buf[3] = i - buf[1];
1510         i = max(min(status->dy, 255), -256);
1511         buf[2] = i >> 1;
1512         buf[4] = i - buf[2];
1513         i = max(min(status->dz, 127), -128);
1514         buf[5] = (i >> 1) & 0x7f;
1515         buf[6] = (i - (i >> 1)) & 0x7f;
1516         buf[7] = (~status->button >> 3) & 0x7f;
1517         return MOUSE_SYS_PACKETSIZE;
1518     }
1519     return sc->inputbytes;
1520 }
1521
1522 static int
1523 psmread(struct dev_read_args *ap)
1524 {
1525     cdev_t dev = ap->a_head.a_dev;
1526     struct uio *uio = ap->a_uio;
1527     struct psm_softc *sc = PSM_SOFTC(PSM_UNIT(dev));
1528     unsigned char buf[PSM_SMALLBUFSIZE];
1529     int error = 0;
1530     int l;
1531
1532     if ((sc->state & PSM_VALID) == 0)
1533         return EIO;
1534
1535     /* block until mouse activity occured */
1536     crit_enter();
1537     while (sc->queue.count <= 0) {
1538         if (PSM_NBLOCKIO(dev)) {
1539             crit_exit();
1540             return EWOULDBLOCK;
1541         }
1542         sc->state |= PSM_ASLP;
1543         error = tsleep((caddr_t) sc, PCATCH, "psmrea", 0);
1544         sc->state &= ~PSM_ASLP;
1545         if (error) {
1546             crit_exit();
1547             return error;
1548         } else if ((sc->state & PSM_VALID) == 0) {
1549             /* the device disappeared! */
1550             crit_exit();
1551             return EIO;
1552         }
1553     }
1554     crit_exit();
1555
1556     /* copy data to the user land */
1557     while ((sc->queue.count > 0) && (uio->uio_resid > 0)) {
1558         crit_enter();
1559         l = (int)szmin(sc->queue.count, uio->uio_resid);
1560         if (l > sizeof(buf))
1561             l = sizeof(buf);
1562         if (l > sizeof(sc->queue.buf) - sc->queue.head) {
1563             bcopy(&sc->queue.buf[sc->queue.head], &buf[0], 
1564                 sizeof(sc->queue.buf) - sc->queue.head);
1565             bcopy(&sc->queue.buf[0], 
1566                 &buf[sizeof(sc->queue.buf) - sc->queue.head],
1567                 l - (sizeof(sc->queue.buf) - sc->queue.head));
1568         } else {
1569             bcopy(&sc->queue.buf[sc->queue.head], &buf[0], l);
1570         }
1571         sc->queue.count -= l;
1572         sc->queue.head = (sc->queue.head + l) % sizeof(sc->queue.buf);
1573         crit_exit();
1574         error = uiomove(buf, (size_t)l, uio);
1575         if (error)
1576             break;
1577     }
1578
1579     return error;
1580 }
1581
1582 static int
1583 block_mouse_data(struct psm_softc *sc, int *c)
1584 {
1585     if (!kbdc_lock(sc->kbdc, TRUE)) 
1586         return EIO;
1587
1588     crit_enter();
1589     *c = get_controller_command_byte(sc->kbdc);
1590     if ((*c == -1) 
1591         || !set_controller_command_byte(sc->kbdc, 
1592             kbdc_get_device_mask(sc->kbdc),
1593             KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT
1594                 | KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
1595         /* this is CONTROLLER ERROR */
1596         crit_exit();
1597         kbdc_lock(sc->kbdc, FALSE);
1598         return EIO;
1599     }
1600
1601     /* 
1602      * The device may be in the middle of status data transmission.
1603      * The transmission will be interrupted, thus, incomplete status 
1604      * data must be discarded. Although the aux interrupt is disabled 
1605      * at the keyboard controller level, at most one aux interrupt 
1606      * may have already been pending and a data byte is in the 
1607      * output buffer; throw it away. Note that the second argument 
1608      * to `empty_aux_buffer()' is zero, so that the call will just 
1609      * flush the internal queue.
1610      * `psmintr()' will be invoked after `splx()' if an interrupt is
1611      * pending; it will see no data and returns immediately.
1612      */
1613     empty_aux_buffer(sc->kbdc, 0);      /* flush the queue */
1614     read_aux_data_no_wait(sc->kbdc);    /* throw away data if any */
1615     sc->inputbytes = 0;
1616     crit_exit();
1617
1618     return 0;
1619 }
1620
1621 static int
1622 unblock_mouse_data(struct psm_softc *sc, int c)
1623 {
1624     int error = 0;
1625
1626     /* 
1627      * We may have seen a part of status data during `set_mouse_XXX()'.
1628      * they have been queued; flush it.
1629      */
1630     empty_aux_buffer(sc->kbdc, 0);
1631
1632     /* restore ports and interrupt */
1633     if (!set_controller_command_byte(sc->kbdc, 
1634             kbdc_get_device_mask(sc->kbdc),
1635             c & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS))) {
1636         /* CONTROLLER ERROR; this is serious, we may have
1637          * been left with the inaccessible keyboard and
1638          * the disabled mouse interrupt. 
1639          */
1640         error = EIO;
1641     }
1642
1643     kbdc_lock(sc->kbdc, FALSE);
1644     return error;
1645 }
1646
1647 static int
1648 psmioctl(struct dev_ioctl_args *ap)
1649 {
1650     cdev_t dev = ap->a_head.a_dev;
1651     caddr_t addr=  ap->a_data;
1652     struct psm_softc *sc = PSM_SOFTC(PSM_UNIT(dev));
1653     mousemode_t mode;
1654     mousestatus_t status;
1655 #if (defined(MOUSE_GETVARS))
1656     mousevar_t *var;
1657 #endif
1658     mousedata_t *data;
1659     int stat[3];
1660     int command_byte;
1661     int error = 0;
1662
1663     mode.resolution = -1;
1664
1665     /* Perform IOCTL command */
1666
1667     switch (ap->a_cmd) {
1668     case OLD_MOUSE_GETHWINFO:
1669         crit_enter();
1670         ((old_mousehw_t *)addr)->buttons = sc->hw.buttons;
1671         ((old_mousehw_t *)addr)->iftype = sc->hw.iftype;
1672         ((old_mousehw_t *)addr)->type = sc->hw.type;
1673         ((old_mousehw_t *)addr)->hwid = sc->hw.hwid & 0x00ff;
1674         crit_exit();
1675         break;
1676
1677     case MOUSE_GETHWINFO:
1678         crit_enter();
1679         *(mousehw_t *)addr = sc->hw;
1680         if (sc->mode.level == PSM_LEVEL_BASE)
1681             ((mousehw_t *)addr)->model = MOUSE_MODEL_GENERIC;
1682         crit_exit();
1683         break;
1684
1685     case OLD_MOUSE_GETMODE:
1686         crit_enter();
1687         switch (sc->mode.level) {
1688         case PSM_LEVEL_BASE:
1689             ((old_mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2;
1690             break;
1691         case PSM_LEVEL_STANDARD:
1692             ((old_mousemode_t *)addr)->protocol = MOUSE_PROTO_SYSMOUSE;
1693             break;
1694         case PSM_LEVEL_NATIVE:
1695             ((old_mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2;
1696             break;
1697         }
1698         ((old_mousemode_t *)addr)->rate = sc->mode.rate;
1699         ((old_mousemode_t *)addr)->resolution = sc->mode.resolution;
1700         ((old_mousemode_t *)addr)->accelfactor = sc->mode.accelfactor;
1701         crit_exit();
1702         break;
1703
1704     case MOUSE_GETMODE:
1705         crit_enter();
1706         *(mousemode_t *)addr = sc->mode;
1707         ((mousemode_t *)addr)->resolution = 
1708             MOUSE_RES_LOW - sc->mode.resolution;
1709         switch (sc->mode.level) {
1710         case PSM_LEVEL_BASE:
1711             ((mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2;
1712             ((mousemode_t *)addr)->packetsize = MOUSE_PS2_PACKETSIZE;
1713             break;
1714         case PSM_LEVEL_STANDARD:
1715             ((mousemode_t *)addr)->protocol = MOUSE_PROTO_SYSMOUSE;
1716             ((mousemode_t *)addr)->packetsize = MOUSE_SYS_PACKETSIZE;
1717             ((mousemode_t *)addr)->syncmask[0] = MOUSE_SYS_SYNCMASK;
1718             ((mousemode_t *)addr)->syncmask[1] = MOUSE_SYS_SYNC;
1719             break;
1720         case PSM_LEVEL_NATIVE:
1721             /* FIXME: this isn't quite correct... XXX */
1722             ((mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2;
1723             break;
1724         }
1725         crit_exit();
1726         break;
1727
1728     case OLD_MOUSE_SETMODE:
1729     case MOUSE_SETMODE:
1730         if (ap->a_cmd == OLD_MOUSE_SETMODE) {
1731             mode.rate = ((old_mousemode_t *)addr)->rate;
1732             /*
1733              * resolution  old I/F   new I/F
1734              * default        0         0
1735              * low            1        -2
1736              * medium low     2        -3
1737              * medium high    3        -4
1738              * high           4        -5
1739              */
1740             if (((old_mousemode_t *)addr)->resolution > 0)
1741                 mode.resolution = -((old_mousemode_t *)addr)->resolution - 1;
1742             mode.accelfactor = ((old_mousemode_t *)addr)->accelfactor;
1743             mode.level = -1;
1744         } else {
1745             mode = *(mousemode_t *)addr;
1746         }
1747
1748         /* adjust and validate parameters. */
1749         if (mode.rate > UCHAR_MAX)
1750             return EINVAL;
1751         if (mode.rate == 0)
1752             mode.rate = sc->dflt_mode.rate;
1753         else if (mode.rate == -1)
1754             /* don't change the current setting */
1755             ;
1756         else if (mode.rate < 0)
1757             return EINVAL;
1758         if (mode.resolution >= UCHAR_MAX)
1759             return EINVAL;
1760         if (mode.resolution >= 200)
1761             mode.resolution = MOUSE_RES_HIGH;
1762         else if (mode.resolution >= 100)
1763             mode.resolution = MOUSE_RES_MEDIUMHIGH;
1764         else if (mode.resolution >= 50)
1765             mode.resolution = MOUSE_RES_MEDIUMLOW;
1766         else if (mode.resolution > 0)
1767             mode.resolution = MOUSE_RES_LOW;
1768         if (mode.resolution == MOUSE_RES_DEFAULT)
1769             mode.resolution = sc->dflt_mode.resolution;
1770         else if (mode.resolution == -1)
1771             /* don't change the current setting */
1772             ;
1773         else if (mode.resolution < 0) /* MOUSE_RES_LOW/MEDIUM/HIGH */
1774             mode.resolution = MOUSE_RES_LOW - mode.resolution;
1775         if (mode.level == -1)
1776             /* don't change the current setting */
1777             mode.level = sc->mode.level;
1778         else if ((mode.level < PSM_LEVEL_MIN) || (mode.level > PSM_LEVEL_MAX))
1779             return EINVAL;
1780         if (mode.accelfactor == -1)
1781             /* don't change the current setting */
1782             mode.accelfactor = sc->mode.accelfactor;
1783         else if (mode.accelfactor < 0)
1784             return EINVAL;
1785
1786         /* don't allow anybody to poll the keyboard controller */
1787         error = block_mouse_data(sc, &command_byte);
1788         if (error)
1789             return error;
1790
1791         /* set mouse parameters */
1792         if (mode.rate > 0)
1793             mode.rate = set_mouse_sampling_rate(sc->kbdc, mode.rate);
1794         if (mode.resolution >= 0)
1795             mode.resolution = set_mouse_resolution(sc->kbdc, mode.resolution);
1796         set_mouse_scaling(sc->kbdc, 1);
1797         get_mouse_status(sc->kbdc, stat, 0, 3);
1798
1799         crit_enter();
1800         sc->mode.rate = mode.rate;
1801         sc->mode.resolution = mode.resolution;
1802         sc->mode.accelfactor = mode.accelfactor;
1803         sc->mode.level = mode.level;
1804         crit_exit();
1805
1806         unblock_mouse_data(sc, command_byte);
1807         break;
1808
1809     case MOUSE_GETLEVEL:
1810         *(int *)addr = sc->mode.level;
1811         break;
1812
1813     case MOUSE_SETLEVEL:
1814         if ((*(int *)addr < PSM_LEVEL_MIN) || (*(int *)addr > PSM_LEVEL_MAX))
1815             return EINVAL;
1816         sc->mode.level = *(int *)addr;
1817         break;
1818
1819     case MOUSE_GETSTATUS:
1820         crit_enter();
1821         status = sc->status;
1822         sc->status.flags = 0;
1823         sc->status.obutton = sc->status.button;
1824         sc->status.button = 0;
1825         sc->status.dx = 0;
1826         sc->status.dy = 0;
1827         sc->status.dz = 0;
1828         crit_exit();
1829         *(mousestatus_t *)addr = status;
1830         break;
1831
1832 #if (defined(MOUSE_GETVARS))
1833     case MOUSE_GETVARS:
1834         var = (mousevar_t *)addr;
1835         bzero(var, sizeof(*var));
1836         crit_enter();
1837         var->var[0] = MOUSE_VARS_PS2_SIG;
1838         var->var[1] = sc->config;
1839         var->var[2] = sc->flags;
1840         crit_exit();
1841         break;
1842
1843     case MOUSE_SETVARS:
1844         return ENODEV;
1845 #endif /* MOUSE_GETVARS */
1846
1847     case MOUSE_READSTATE:
1848     case MOUSE_READDATA:
1849         data = (mousedata_t *)addr;
1850         if (data->len > sizeof(data->buf)/sizeof(data->buf[0]))
1851             return EINVAL;
1852
1853         error = block_mouse_data(sc, &command_byte);
1854         if (error)
1855             return error;
1856         if ((data->len = get_mouse_status(sc->kbdc, data->buf, 
1857                 (ap->a_cmd == MOUSE_READDATA) ? 1 : 0, data->len)) <= 0)
1858             error = EIO;
1859         unblock_mouse_data(sc, command_byte);
1860         break;
1861
1862 #if (defined(MOUSE_SETRESOLUTION))
1863     case MOUSE_SETRESOLUTION:
1864         mode.resolution = *(int *)addr;
1865         if (mode.resolution >= UCHAR_MAX)
1866             return EINVAL;
1867         else if (mode.resolution >= 200)
1868             mode.resolution = MOUSE_RES_HIGH;
1869         else if (mode.resolution >= 100)
1870             mode.resolution = MOUSE_RES_MEDIUMHIGH;
1871         else if (mode.resolution >= 50)
1872             mode.resolution = MOUSE_RES_MEDIUMLOW;
1873         else if (mode.resolution > 0)
1874             mode.resolution = MOUSE_RES_LOW;
1875         if (mode.resolution == MOUSE_RES_DEFAULT)
1876             mode.resolution = sc->dflt_mode.resolution;
1877         else if (mode.resolution == -1)
1878             mode.resolution = sc->mode.resolution;
1879         else if (mode.resolution < 0) /* MOUSE_RES_LOW/MEDIUM/HIGH */
1880             mode.resolution = MOUSE_RES_LOW - mode.resolution;
1881
1882         error = block_mouse_data(sc, &command_byte);
1883         if (error)
1884             return error;
1885         sc->mode.resolution = set_mouse_resolution(sc->kbdc, mode.resolution);
1886         if (sc->mode.resolution != mode.resolution)
1887             error = EIO;
1888         unblock_mouse_data(sc, command_byte);
1889         break;
1890 #endif /* MOUSE_SETRESOLUTION */
1891
1892 #if (defined(MOUSE_SETRATE))
1893     case MOUSE_SETRATE:
1894         mode.rate = *(int *)addr;
1895         if (mode.rate > UCHAR_MAX)
1896             return EINVAL;
1897         if (mode.rate == 0)
1898             mode.rate = sc->dflt_mode.rate;
1899         else if (mode.rate < 0)
1900             mode.rate = sc->mode.rate;
1901
1902         error = block_mouse_data(sc, &command_byte);
1903         if (error)
1904             return error;
1905         sc->mode.rate = set_mouse_sampling_rate(sc->kbdc, mode.rate);
1906         if (sc->mode.rate != mode.rate)
1907             error = EIO;
1908         unblock_mouse_data(sc, command_byte);
1909         break;
1910 #endif /* MOUSE_SETRATE */
1911
1912 #if (defined(MOUSE_SETSCALING))
1913     case MOUSE_SETSCALING:
1914         if ((*(int *)addr <= 0) || (*(int *)addr > 2))
1915             return EINVAL;
1916
1917         error = block_mouse_data(sc, &command_byte);
1918         if (error)
1919             return error;
1920         if (!set_mouse_scaling(sc->kbdc, *(int *)addr))
1921             error = EIO;
1922         unblock_mouse_data(sc, command_byte);
1923         break;
1924 #endif /* MOUSE_SETSCALING */
1925
1926 #if (defined(MOUSE_GETHWID))
1927     case MOUSE_GETHWID:
1928         error = block_mouse_data(sc, &command_byte);
1929         if (error)
1930             return error;
1931         sc->hw.hwid &= ~0x00ff;
1932         sc->hw.hwid |= get_aux_id(sc->kbdc);
1933         *(int *)addr = sc->hw.hwid & 0x00ff;
1934         unblock_mouse_data(sc, command_byte);
1935         break;
1936 #endif /* MOUSE_GETHWID */
1937
1938     default:
1939         return ENOTTY;
1940     }
1941
1942     return error;
1943 }
1944
1945 static void
1946 psmtimeout(void *arg)
1947 {
1948     struct psm_softc *sc;
1949
1950     sc = (struct psm_softc *)arg;
1951     crit_enter();
1952     if (sc->watchdog && kbdc_lock(sc->kbdc, TRUE)) {
1953         if (verbose >= 4)
1954             log(LOG_DEBUG, "psm%d: lost interrupt?\n", sc->unit);
1955         psmintr(sc);
1956         kbdc_lock(sc->kbdc, FALSE);
1957     }
1958     sc->watchdog = TRUE;
1959     callout_reset(&sc->callout, hz, psmtimeout, (void *)(uintptr_t)sc);
1960     crit_exit();
1961 }
1962
1963 static void
1964 psmintr(void *arg)
1965 {
1966     /*
1967      * the table to turn PS/2 mouse button bits (MOUSE_PS2_BUTTON?DOWN)
1968      * into `mousestatus' button bits (MOUSE_BUTTON?DOWN).
1969      */
1970     static int butmap[8] = {
1971         0, 
1972         MOUSE_BUTTON1DOWN, 
1973         MOUSE_BUTTON3DOWN, 
1974         MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN, 
1975         MOUSE_BUTTON2DOWN, 
1976         MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN, 
1977         MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN,
1978         MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN
1979     };
1980     static int butmap_versapad[8] = {
1981         0, 
1982         MOUSE_BUTTON3DOWN, 
1983         0, 
1984         MOUSE_BUTTON3DOWN, 
1985         MOUSE_BUTTON1DOWN, 
1986         MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN, 
1987         MOUSE_BUTTON1DOWN,
1988         MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN
1989     };
1990     struct psm_softc *sc = arg;
1991     mousestatus_t ms;
1992     struct timeval tv;
1993     int x, y, z;
1994     int c;
1995     int l;
1996     int x0, y0;
1997
1998     /* read until there is nothing to read */
1999     while((c = read_aux_data_no_wait(sc->kbdc)) != -1) {
2000     
2001         /* discard the byte if the device is not open */
2002         if ((sc->state & PSM_OPEN) == 0)
2003             continue;
2004     
2005         getmicrouptime(&tv);
2006         if ((sc->inputbytes > 0) && timevalcmp(&tv, &sc->inputtimeout, >)) {
2007             log(LOG_DEBUG, "psmintr: delay too long; resetting byte count\n");
2008             sc->inputbytes = 0;
2009             sc->syncerrors = 0;
2010         }
2011         sc->inputtimeout.tv_sec = PSM_INPUT_TIMEOUT/1000000;
2012         sc->inputtimeout.tv_usec = PSM_INPUT_TIMEOUT%1000000;
2013         timevaladd(&sc->inputtimeout, &tv);
2014
2015         sc->ipacket[sc->inputbytes++] = c;
2016         if (sc->inputbytes < sc->mode.packetsize) 
2017             continue;
2018
2019 #if 0
2020         log(LOG_DEBUG, "psmintr: %02x %02x %02x %02x %02x %02x\n",
2021             sc->ipacket[0], sc->ipacket[1], sc->ipacket[2],
2022             sc->ipacket[3], sc->ipacket[4], sc->ipacket[5]);
2023 #endif
2024
2025         c = sc->ipacket[0];
2026
2027         if ((c & sc->mode.syncmask[0]) != sc->mode.syncmask[1]) {
2028             log(LOG_DEBUG, "psmintr: out of sync (%04x != %04x).\n", 
2029                 c & sc->mode.syncmask[0], sc->mode.syncmask[1]);
2030             ++sc->syncerrors;
2031             if (sc->syncerrors < sc->mode.packetsize) {
2032                 log(LOG_DEBUG, "psmintr: discard a byte (%d).\n", sc->syncerrors);
2033                 --sc->inputbytes;
2034                 bcopy(&sc->ipacket[1], &sc->ipacket[0], sc->inputbytes);
2035             } else if (sc->syncerrors == sc->mode.packetsize) {
2036                 log(LOG_DEBUG, "psmintr: re-enable the mouse.\n");
2037                 sc->inputbytes = 0;
2038                 disable_aux_dev(sc->kbdc);
2039                 enable_aux_dev(sc->kbdc);
2040             } else if (sc->syncerrors < PSM_SYNCERR_THRESHOLD1) {
2041                 log(LOG_DEBUG, "psmintr: discard a byte (%d).\n", sc->syncerrors);
2042                 --sc->inputbytes;
2043                 bcopy(&sc->ipacket[1], &sc->ipacket[0], sc->inputbytes);
2044             } else if (sc->syncerrors >= PSM_SYNCERR_THRESHOLD1) {
2045                 log(LOG_DEBUG, "psmintr: reset the mouse.\n");
2046                 reinitialize(sc, TRUE);
2047             }
2048             continue;
2049         }
2050
2051         /* 
2052          * A kludge for Kensington device! 
2053          * The MSB of the horizontal count appears to be stored in 
2054          * a strange place.
2055          */
2056         if (sc->hw.model == MOUSE_MODEL_THINK)
2057             sc->ipacket[1] |= (c & MOUSE_PS2_XOVERFLOW) ? 0x80 : 0;
2058
2059         /* ignore the overflow bits... */
2060         x = (c & MOUSE_PS2_XNEG) ?  sc->ipacket[1] - 256 : sc->ipacket[1];
2061         y = (c & MOUSE_PS2_YNEG) ?  sc->ipacket[2] - 256 : sc->ipacket[2];
2062         z = 0;
2063         ms.obutton = sc->button;                  /* previous button state */
2064         ms.button = butmap[c & MOUSE_PS2_BUTTONS];
2065         /* `tapping' action */
2066         if (sc->config & PSM_CONFIG_FORCETAP)
2067             ms.button |= ((c & MOUSE_PS2_TAP)) ? 0 : MOUSE_BUTTON4DOWN;
2068
2069         switch (sc->hw.model) {
2070
2071         case MOUSE_MODEL_EXPLORER:
2072             /*
2073              *          b7 b6 b5 b4 b3 b2 b1 b0
2074              * byte 1:  oy ox sy sx 1  M  R  L
2075              * byte 2:  x  x  x  x  x  x  x  x
2076              * byte 3:  y  y  y  y  y  y  y  y
2077              * byte 4:  *  *  S2 S1 s  d2 d1 d0
2078              *
2079              * L, M, R, S1, S2: left, middle, right and side buttons
2080              * s: wheel data sign bit
2081              * d2-d0: wheel data
2082              */
2083             z = (sc->ipacket[3] & MOUSE_EXPLORER_ZNEG)
2084                 ? (sc->ipacket[3] & 0x0f) - 16 : (sc->ipacket[3] & 0x0f);
2085             ms.button |= (sc->ipacket[3] & MOUSE_EXPLORER_BUTTON4DOWN)
2086                 ? MOUSE_BUTTON4DOWN : 0;
2087             ms.button |= (sc->ipacket[3] & MOUSE_EXPLORER_BUTTON5DOWN)
2088                 ? MOUSE_BUTTON5DOWN : 0;
2089             break;
2090
2091         case MOUSE_MODEL_INTELLI:
2092         case MOUSE_MODEL_NET:
2093             /* wheel data is in the fourth byte */
2094             z = (char)sc->ipacket[3];
2095             /* some mice may send 7 when there is no Z movement?! XXX */
2096             if ((z >= 7) || (z <= -7))
2097                 z = 0;
2098             /* some compatible mice have additional buttons */
2099             ms.button |= (c & MOUSE_PS2INTELLI_BUTTON4DOWN)
2100                 ? MOUSE_BUTTON4DOWN : 0;
2101             ms.button |= (c & MOUSE_PS2INTELLI_BUTTON5DOWN)
2102                 ? MOUSE_BUTTON5DOWN : 0;
2103             break;
2104
2105         case MOUSE_MODEL_MOUSEMANPLUS:
2106             /*
2107              * PS2++ protocl packet
2108              *
2109              *          b7 b6 b5 b4 b3 b2 b1 b0
2110              * byte 1:  *  1  p3 p2 1  *  *  *
2111              * byte 2:  c1 c2 p1 p0 d1 d0 1  0
2112              *
2113              * p3-p0: packet type
2114              * c1, c2: c1 & c2 == 1, if p2 == 0
2115              *         c1 & c2 == 0, if p2 == 1
2116              *
2117              * packet type: 0 (device type)
2118              * See comments in enable_mmanplus() below.
2119              * 
2120              * packet type: 1 (wheel data)
2121              *
2122              *          b7 b6 b5 b4 b3 b2 b1 b0
2123              * byte 3:  h  *  B5 B4 s  d2 d1 d0
2124              *
2125              * h: 1, if horizontal roller data
2126              *    0, if vertical roller data
2127              * B4, B5: button 4 and 5
2128              * s: sign bit
2129              * d2-d0: roller data
2130              *
2131              * packet type: 2 (reserved)
2132              */
2133             if (((c & MOUSE_PS2PLUS_SYNCMASK) == MOUSE_PS2PLUS_SYNC)
2134                     && (abs(x) > 191)
2135                     && MOUSE_PS2PLUS_CHECKBITS(sc->ipacket)) {
2136                 /* the extended data packet encodes button and wheel events */
2137                 switch (MOUSE_PS2PLUS_PACKET_TYPE(sc->ipacket)) {
2138                 case 1:
2139                     /* wheel data packet */
2140                     x = y = 0;
2141                     if (sc->ipacket[2] & 0x80) {
2142                         /* horizontal roller count - ignore it XXX*/
2143                     } else {
2144                         /* vertical roller count */
2145                         z = (sc->ipacket[2] & MOUSE_PS2PLUS_ZNEG)
2146                             ? (sc->ipacket[2] & 0x0f) - 16
2147                             : (sc->ipacket[2] & 0x0f);
2148                     }
2149                     ms.button |= (sc->ipacket[2] & MOUSE_PS2PLUS_BUTTON4DOWN)
2150                         ? MOUSE_BUTTON4DOWN : 0;
2151                     ms.button |= (sc->ipacket[2] & MOUSE_PS2PLUS_BUTTON5DOWN)
2152                         ? MOUSE_BUTTON5DOWN : 0;
2153                     break;
2154                 case 2:
2155                     /* this packet type is reserved by Logitech... */
2156                     /*
2157                      * IBM ScrollPoint Mouse uses this packet type to
2158                      * encode both vertical and horizontal scroll movement.
2159                      */
2160                     x = y = 0;
2161                     /* horizontal count */
2162                     if (sc->ipacket[2] & 0x0f)
2163                         z = (sc->ipacket[2] & MOUSE_SPOINT_WNEG) ? -2 : 2;
2164                     /* vertical count */
2165                     if (sc->ipacket[2] & 0xf0)
2166                         z = (sc->ipacket[2] & MOUSE_SPOINT_ZNEG) ? -1 : 1;
2167 #if 0
2168                     /* vertical count */
2169                     z = (sc->ipacket[2] & MOUSE_SPOINT_ZNEG)
2170                         ? ((sc->ipacket[2] >> 4) & 0x0f) - 16
2171                         : ((sc->ipacket[2] >> 4) & 0x0f);
2172                     /* horizontal count */
2173                     w = (sc->ipacket[2] & MOUSE_SPOINT_WNEG)
2174                         ? (sc->ipacket[2] & 0x0f) - 16
2175                         : (sc->ipacket[2] & 0x0f);
2176 #endif
2177                     break;
2178                 case 0:
2179                     /* device type packet - shouldn't happen */
2180                     /* FALL THROUGH */
2181                 default:
2182                     x = y = 0;
2183                     ms.button = ms.obutton;
2184                     if (bootverbose)
2185                         log(LOG_DEBUG, "psmintr: unknown PS2++ packet type %d: "
2186                                        "0x%02x 0x%02x 0x%02x\n",
2187                             MOUSE_PS2PLUS_PACKET_TYPE(sc->ipacket),
2188                             sc->ipacket[0], sc->ipacket[1], sc->ipacket[2]);
2189                     break;
2190                 }
2191             } else {
2192                 /* preserve button states */
2193                 ms.button |= ms.obutton & MOUSE_EXTBUTTONS;
2194             }
2195             break;
2196
2197         case MOUSE_MODEL_GLIDEPOINT:
2198             /* `tapping' action */
2199             ms.button |= ((c & MOUSE_PS2_TAP)) ? 0 : MOUSE_BUTTON4DOWN;
2200             break;
2201
2202         case MOUSE_MODEL_NETSCROLL:
2203             /* three addtional bytes encode buttons and wheel events */
2204             ms.button |= (sc->ipacket[3] & MOUSE_PS2_BUTTON3DOWN)
2205                 ? MOUSE_BUTTON4DOWN : 0;
2206             ms.button |= (sc->ipacket[3] & MOUSE_PS2_BUTTON1DOWN)
2207                 ? MOUSE_BUTTON5DOWN : 0;
2208             z = (sc->ipacket[3] & MOUSE_PS2_XNEG) 
2209                 ? sc->ipacket[4] - 256 : sc->ipacket[4];
2210             break;
2211
2212         case MOUSE_MODEL_THINK:
2213             /* the fourth button state in the first byte */
2214             ms.button |= (c & MOUSE_PS2_TAP) ? MOUSE_BUTTON4DOWN : 0;
2215             break;
2216
2217         case MOUSE_MODEL_VERSAPAD:
2218             /* VersaPad PS/2 absolute mode message format
2219              *
2220              * [packet1]     7   6   5   4   3   2   1   0(LSB)
2221              *  ipacket[0]:  1   1   0   A   1   L   T   R
2222              *  ipacket[1]: H7  H6  H5  H4  H3  H2  H1  H0
2223              *  ipacket[2]: V7  V6  V5  V4  V3  V2  V1  V0
2224              *  ipacket[3]:  1   1   1   A   1   L   T   R
2225              *  ipacket[4]:V11 V10  V9  V8 H11 H10  H9  H8
2226              *  ipacket[5]:  0  P6  P5  P4  P3  P2  P1  P0
2227              *
2228              * [note]
2229              *  R: right physical mouse button (1=on)
2230              *  T: touch pad virtual button (1=tapping)
2231              *  L: left physical mouse button (1=on)
2232              *  A: position data is valid (1=valid)
2233              *  H: horizontal data (12bit signed integer. H11 is sign bit.)
2234              *  V: vertical data (12bit signed integer. V11 is sign bit.)
2235              *  P: pressure data
2236              *
2237              * Tapping is mapped to MOUSE_BUTTON4.
2238              */
2239             ms.button = butmap_versapad[c & MOUSE_PS2VERSA_BUTTONS];
2240             ms.button |= (c & MOUSE_PS2VERSA_TAP) ? MOUSE_BUTTON4DOWN : 0;
2241             x = y = 0;
2242             if (c & MOUSE_PS2VERSA_IN_USE) {
2243                 x0 = sc->ipacket[1] | (((sc->ipacket[4]) & 0x0f) << 8);
2244                 y0 = sc->ipacket[2] | (((sc->ipacket[4]) & 0xf0) << 4);
2245                 if (x0 & 0x800)
2246                     x0 -= 0x1000;
2247                 if (y0 & 0x800)
2248                     y0 -= 0x1000;
2249                 if (sc->flags & PSM_FLAGS_FINGERDOWN) {
2250                     x = sc->xold - x0;
2251                     y = y0 - sc->yold;
2252                     if (x < 0)  /* XXX */
2253                         x++;
2254                     else if (x)
2255                         x--;
2256                     if (y < 0)
2257                         y++;
2258                     else if (y)
2259                         y--;
2260                 } else {
2261                     sc->flags |= PSM_FLAGS_FINGERDOWN;
2262                 }
2263                 sc->xold = x0;
2264                 sc->yold = y0;
2265             } else {
2266                 sc->flags &= ~PSM_FLAGS_FINGERDOWN;
2267             }
2268             c = ((x < 0) ? MOUSE_PS2_XNEG : 0)
2269                 | ((y < 0) ? MOUSE_PS2_YNEG : 0);
2270             break;
2271
2272         case MOUSE_MODEL_4D:
2273             /*
2274              *          b7 b6 b5 b4 b3 b2 b1 b0
2275              * byte 1:  s2 d2 s1 d1 1  M  R  L
2276              * byte 2:  sx x  x  x  x  x  x  x
2277              * byte 3:  sy y  y  y  y  y  y  y
2278              *
2279              * s1: wheel 1 direction
2280              * d1: wheel 1 data
2281              * s2: wheel 2 direction
2282              * d2: wheel 2 data
2283              */
2284             x = (sc->ipacket[1] & 0x80) ? sc->ipacket[1] - 256 : sc->ipacket[1];
2285             y = (sc->ipacket[2] & 0x80) ? sc->ipacket[2] - 256 : sc->ipacket[2];
2286             switch (c & MOUSE_4D_WHEELBITS) {
2287             case 0x10:
2288                 z = 1;
2289                 break;
2290             case 0x30:
2291                 z = -1;
2292                 break;
2293             case 0x40:  /* 2nd wheel turning right XXX */
2294                 z = 2;
2295                 break;
2296             case 0xc0:  /* 2nd wheel turning left XXX */
2297                 z = -2;
2298                 break;
2299             }
2300             break;
2301
2302         case MOUSE_MODEL_4DPLUS:
2303             if ((x < 16 - 256) && (y < 16 - 256)) {
2304                 /*
2305                  *          b7 b6 b5 b4 b3 b2 b1 b0
2306                  * byte 1:  0  0  1  1  1  M  R  L
2307                  * byte 2:  0  0  0  0  1  0  0  0
2308                  * byte 3:  0  0  0  0  S  s  d1 d0
2309                  *
2310                  * L, M, R, S: left, middle, right and side buttons
2311                  * s: wheel data sign bit
2312                  * d1-d0: wheel data
2313                  */
2314                 x = y = 0;
2315                 if (sc->ipacket[2] & MOUSE_4DPLUS_BUTTON4DOWN)
2316                     ms.button |= MOUSE_BUTTON4DOWN;
2317                 z = (sc->ipacket[2] & MOUSE_4DPLUS_ZNEG)
2318                         ? ((sc->ipacket[2] & 0x07) - 8)
2319                         : (sc->ipacket[2] & 0x07) ;
2320             } else {
2321                 /* preserve previous button states */
2322                 ms.button |= ms.obutton & MOUSE_EXTBUTTONS;
2323             }
2324             break;
2325
2326         case MOUSE_MODEL_GENERIC:
2327         default:
2328             break;
2329         }
2330
2331         /* scale values */
2332         if (sc->mode.accelfactor >= 1) {
2333             if (x != 0) {
2334                 x = x * x / sc->mode.accelfactor;
2335                 if (x == 0)
2336                     x = 1;
2337                 if (c & MOUSE_PS2_XNEG)
2338                     x = -x;
2339             }
2340             if (y != 0) {
2341                 y = y * y / sc->mode.accelfactor;
2342                 if (y == 0)
2343                     y = 1;
2344                 if (c & MOUSE_PS2_YNEG)
2345                     y = -y;
2346             }
2347         }
2348
2349         ms.dx = x;
2350         ms.dy = y;
2351         ms.dz = z;
2352         ms.flags = ((x || y || z) ? MOUSE_POSCHANGED : 0) 
2353             | (ms.obutton ^ ms.button);
2354
2355         if (sc->mode.level < PSM_LEVEL_NATIVE)
2356             sc->inputbytes = tame_mouse(sc, &ms, sc->ipacket);
2357
2358         sc->status.flags |= ms.flags;
2359         sc->status.dx += ms.dx;
2360         sc->status.dy += ms.dy;
2361         sc->status.dz += ms.dz;
2362         sc->status.button = ms.button;
2363         sc->button = ms.button;
2364
2365         sc->watchdog = FALSE;
2366
2367         /* queue data */
2368         if (sc->queue.count + sc->inputbytes < sizeof(sc->queue.buf)) {
2369             l = min(sc->inputbytes, sizeof(sc->queue.buf) - sc->queue.tail);
2370             bcopy(&sc->ipacket[0], &sc->queue.buf[sc->queue.tail], l);
2371             if (sc->inputbytes > l)
2372                 bcopy(&sc->ipacket[l], &sc->queue.buf[0], sc->inputbytes - l);
2373             sc->queue.tail = 
2374                 (sc->queue.tail + sc->inputbytes) % sizeof(sc->queue.buf);
2375             sc->queue.count += sc->inputbytes;
2376         }
2377         sc->inputbytes = 0;
2378
2379         if (sc->state & PSM_ASLP) {
2380             sc->state &= ~PSM_ASLP;
2381             wakeup((caddr_t) sc);
2382         }
2383         selwakeup(&sc->rsel);
2384     }
2385 }
2386
2387 static int
2388 psmpoll(struct dev_poll_args *ap)
2389 {
2390     cdev_t dev = ap->a_head.a_dev;
2391     struct psm_softc *sc = PSM_SOFTC(PSM_UNIT(dev));
2392     int revents = 0;
2393
2394     /* Return true if a mouse event available */
2395     crit_enter();
2396     if (ap->a_events & (POLLIN | POLLRDNORM)) {
2397         if (sc->queue.count > 0)
2398             revents |= ap->a_events & (POLLIN | POLLRDNORM);
2399         else
2400             selrecord(curthread, &sc->rsel);
2401     }
2402     crit_exit();
2403     ap->a_events = revents;
2404     return (0);
2405 }
2406
2407 static struct filterops psmfiltops =
2408         { 1, NULL, psmfilter_detach, psmfilter };
2409
2410 static int
2411 psmkqfilter(struct dev_kqfilter_args *ap)
2412 {
2413         cdev_t dev = ap->a_head.a_dev;
2414         struct psm_softc *sc = PSM_SOFTC(PSM_UNIT(dev));
2415         struct knote *kn = ap->a_kn;
2416         struct klist *klist;
2417
2418         ap->a_result = 0;
2419
2420         switch (kn->kn_filter) {
2421         case EVFILT_READ:
2422                 kn->kn_fop = &psmfiltops;
2423                 kn->kn_hook = (caddr_t)sc;
2424                 break;
2425         default:
2426                 ap->a_result = EOPNOTSUPP;
2427                 return (0);
2428         }
2429
2430         crit_enter();
2431         klist = &sc->rsel.si_note;
2432         SLIST_INSERT_HEAD(klist, kn, kn_selnext);
2433         crit_exit();
2434
2435         return (0);
2436 }
2437
2438 static void
2439 psmfilter_detach(struct knote *kn)
2440 {
2441         struct psm_softc *sc = (struct psm_softc *)kn->kn_hook;
2442         struct klist *klist;
2443
2444         crit_enter();
2445         klist = &sc->rsel.si_note;
2446         SLIST_REMOVE(klist, kn, knote, kn_selnext);
2447         crit_exit();
2448 }
2449
2450 static int
2451 psmfilter(struct knote *kn, long hint)
2452 {
2453         struct psm_softc *sc = (struct psm_softc *)kn->kn_hook;
2454         int ready = 0;
2455
2456         crit_enter();
2457         if (sc->queue.count > 0)
2458                 ready = 1;
2459         crit_exit();
2460
2461         return (ready);
2462 }
2463
2464 /* vendor/model specific routines */
2465
2466 static int mouse_id_proc1(KBDC kbdc, int res, int scale, int *status)
2467 {
2468     if (set_mouse_resolution(kbdc, res) != res)
2469         return FALSE;
2470     if (set_mouse_scaling(kbdc, scale)
2471         && set_mouse_scaling(kbdc, scale)
2472         && set_mouse_scaling(kbdc, scale) 
2473         && (get_mouse_status(kbdc, status, 0, 3) >= 3)) 
2474         return TRUE;
2475     return FALSE;
2476 }
2477
2478 static int 
2479 mouse_ext_command(KBDC kbdc, int command)
2480 {
2481     int c;
2482
2483     c = (command >> 6) & 0x03;
2484     if (set_mouse_resolution(kbdc, c) != c)
2485         return FALSE;
2486     c = (command >> 4) & 0x03;
2487     if (set_mouse_resolution(kbdc, c) != c)
2488         return FALSE;
2489     c = (command >> 2) & 0x03;
2490     if (set_mouse_resolution(kbdc, c) != c)
2491         return FALSE;
2492     c = (command >> 0) & 0x03;
2493     if (set_mouse_resolution(kbdc, c) != c)
2494         return FALSE;
2495     return TRUE;
2496 }
2497
2498 #if notyet
2499 /* Logitech MouseMan Cordless II */
2500 static int
2501 enable_lcordless(struct psm_softc *sc)
2502 {
2503     int status[3];
2504     int ch;
2505
2506     if (!mouse_id_proc1(sc->kbdc, PSMD_RES_HIGH, 2, status))
2507         return FALSE;
2508     if (status[1] == PSMD_RES_HIGH)
2509         return FALSE;
2510     ch = (status[0] & 0x07) - 1;        /* channel # */
2511     if ((ch <= 0) || (ch > 4))
2512         return FALSE;
2513     /* 
2514      * status[1]: always one?
2515      * status[2]: battery status? (0-100)
2516      */
2517     return TRUE;
2518 }
2519 #endif /* notyet */
2520
2521 /* Genius NetScroll Mouse, MouseSystems SmartScroll Mouse */
2522 static int
2523 enable_groller(struct psm_softc *sc)
2524 {
2525     int status[3];
2526
2527     /*
2528      * The special sequence to enable the fourth button and the
2529      * roller. Immediately after this sequence check status bytes.
2530      * if the mouse is NetScroll, the second and the third bytes are 
2531      * '3' and 'D'.
2532      */
2533
2534     /*
2535      * If the mouse is an ordinary PS/2 mouse, the status bytes should
2536      * look like the following.
2537      * 
2538      * byte 1 bit 7 always 0
2539      *        bit 6 stream mode (0)
2540      *        bit 5 disabled (0)
2541      *        bit 4 1:1 scaling (0)
2542      *        bit 3 always 0
2543      *        bit 0-2 button status
2544      * byte 2 resolution (PSMD_RES_HIGH)
2545      * byte 3 report rate (?)
2546      */
2547
2548     if (!mouse_id_proc1(sc->kbdc, PSMD_RES_HIGH, 1, status))
2549         return FALSE;
2550     if ((status[1] != '3') || (status[2] != 'D'))
2551         return FALSE;
2552     /* FIXME: SmartScroll Mouse has 5 buttons! XXX */
2553     sc->hw.buttons = 4;
2554     return TRUE;
2555 }
2556
2557 /* Genius NetMouse/NetMouse Pro, ASCII Mie Mouse, NetScroll Optical */
2558 static int
2559 enable_gmouse(struct psm_softc *sc)
2560 {
2561     int status[3];
2562
2563     /*
2564      * The special sequence to enable the middle, "rubber" button. 
2565      * Immediately after this sequence check status bytes.
2566      * if the mouse is NetMouse, NetMouse Pro, or ASCII MIE Mouse, 
2567      * the second and the third bytes are '3' and 'U'.
2568      * NOTE: NetMouse reports that it has three buttons although it has
2569      * two buttons and a rubber button. NetMouse Pro and MIE Mouse
2570      * say they have three buttons too and they do have a button on the
2571      * side...
2572      */
2573     if (!mouse_id_proc1(sc->kbdc, PSMD_RES_HIGH, 1, status))
2574         return FALSE;
2575     if ((status[1] != '3') || (status[2] != 'U'))
2576         return FALSE;
2577     return TRUE;
2578 }
2579
2580 /* ALPS GlidePoint */
2581 static int
2582 enable_aglide(struct psm_softc *sc)
2583 {
2584     int status[3];
2585
2586     /*
2587      * The special sequence to obtain ALPS GlidePoint specific
2588      * information. Immediately after this sequence, status bytes will 
2589      * contain something interesting.
2590      * NOTE: ALPS produces several models of GlidePoint. Some of those
2591      * do not respond to this sequence, thus, cannot be detected this way.
2592      */
2593     if (set_mouse_sampling_rate(sc->kbdc, 100) != 100)
2594         return FALSE;
2595     if (!mouse_id_proc1(sc->kbdc, PSMD_RES_LOW, 2, status))
2596         return FALSE;
2597     if ((status[1] == PSMD_RES_LOW) || (status[2] == 100))
2598         return FALSE;
2599     return TRUE;
2600 }
2601
2602 /* Kensington ThinkingMouse/Trackball */
2603 static int
2604 enable_kmouse(struct psm_softc *sc)
2605 {
2606     static unsigned char rate[] = { 20, 60, 40, 20, 20, 60, 40, 20, 20 };
2607     KBDC kbdc = sc->kbdc;
2608     int status[3];
2609     int id1;
2610     int id2;
2611     int i;
2612
2613     id1 = get_aux_id(kbdc);
2614     if (set_mouse_sampling_rate(kbdc, 10) != 10)
2615         return FALSE;
2616     /* 
2617      * The device is now in the native mode? It returns a different
2618      * ID value...
2619      */
2620     id2 = get_aux_id(kbdc);
2621     if ((id1 == id2) || (id2 != 2))
2622         return FALSE;
2623
2624     if (set_mouse_resolution(kbdc, PSMD_RES_LOW) != PSMD_RES_LOW)
2625         return FALSE;
2626 #if PSM_DEBUG >= 2
2627     /* at this point, resolution is LOW, sampling rate is 10/sec */
2628     if (get_mouse_status(kbdc, status, 0, 3) < 3)
2629         return FALSE;
2630 #endif
2631
2632     /*
2633      * The special sequence to enable the third and fourth buttons.
2634      * Otherwise they behave like the first and second buttons.
2635      */
2636     for (i = 0; i < sizeof(rate)/sizeof(rate[0]); ++i) {
2637         if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i])
2638             return FALSE;
2639     }
2640
2641     /* 
2642      * At this point, the device is using default resolution and
2643      * sampling rate for the native mode. 
2644      */
2645     if (get_mouse_status(kbdc, status, 0, 3) < 3)
2646         return FALSE;
2647     if ((status[1] == PSMD_RES_LOW) || (status[2] == rate[i - 1]))
2648         return FALSE;
2649
2650     /* the device appears be enabled by this sequence, diable it for now */
2651     disable_aux_dev(kbdc);
2652     empty_aux_buffer(kbdc, 5);
2653
2654     return TRUE;
2655 }
2656
2657 /* Logitech MouseMan+/FirstMouse+, IBM ScrollPoint Mouse */
2658 static int
2659 enable_mmanplus(struct psm_softc *sc)
2660 {
2661     KBDC kbdc = sc->kbdc;
2662     int data[3];
2663
2664     /* the special sequence to enable the fourth button and the roller. */
2665     /*
2666      * NOTE: for ScrollPoint to respond correctly, the SET_RESOLUTION
2667      * must be called exactly three times since the last RESET command
2668      * before this sequence. XXX
2669      */
2670     if (!set_mouse_scaling(kbdc, 1))
2671         return FALSE;
2672     if (!mouse_ext_command(kbdc, 0x39) || !mouse_ext_command(kbdc, 0xdb))
2673         return FALSE;
2674     if (get_mouse_status(kbdc, data, 1, 3) < 3)
2675         return FALSE;
2676
2677     /*
2678      * PS2++ protocl, packet type 0
2679      *
2680      *          b7 b6 b5 b4 b3 b2 b1 b0
2681      * byte 1:  *  1  p3 p2 1  *  *  *
2682      * byte 2:  1  1  p1 p0 m1 m0 1  0
2683      * byte 3:  m7 m6 m5 m4 m3 m2 m1 m0
2684      *
2685      * p3-p0: packet type: 0
2686      * m7-m0: model ID: MouseMan+:0x50, FirstMouse+:0x51, ScrollPoint:0x58...
2687      */
2688     /* check constant bits */
2689     if ((data[0] & MOUSE_PS2PLUS_SYNCMASK) != MOUSE_PS2PLUS_SYNC)
2690         return FALSE;
2691     if ((data[1] & 0xc3) != 0xc2)
2692         return FALSE;
2693     /* check d3-d0 in byte 2 */
2694     if (!MOUSE_PS2PLUS_CHECKBITS(data))
2695         return FALSE;
2696     /* check p3-p0 */
2697     if (MOUSE_PS2PLUS_PACKET_TYPE(data) != 0)
2698         return FALSE;
2699
2700     sc->hw.hwid &= 0x00ff;
2701     sc->hw.hwid |= data[2] << 8;        /* save model ID */
2702
2703     /*
2704      * MouseMan+ (or FirstMouse+) is now in its native mode, in which
2705      * the wheel and the fourth button events are encoded in the
2706      * special data packet. The mouse may be put in the IntelliMouse mode
2707      * if it is initialized by the IntelliMouse's method.
2708      */
2709     return TRUE;
2710 }
2711
2712 /* MS IntelliMouse Explorer */
2713 static int
2714 enable_msexplorer(struct psm_softc *sc)
2715 {
2716     static unsigned char rate0[] = { 200, 100, 80, };
2717     static unsigned char rate1[] = { 200, 200, 80, };
2718     KBDC kbdc = sc->kbdc;
2719     int id;
2720     int i;
2721
2722     /* the special sequence to enable the extra buttons and the roller. */
2723     for (i = 0; i < sizeof(rate1)/sizeof(rate1[0]); ++i) {
2724         if (set_mouse_sampling_rate(kbdc, rate1[i]) != rate1[i])
2725             return FALSE;
2726     }
2727     /* the device will give the genuine ID only after the above sequence */
2728     id = get_aux_id(kbdc);
2729     if (id != PSM_EXPLORER_ID)
2730         return FALSE;
2731
2732     sc->hw.hwid = id;
2733     sc->hw.buttons = 5;         /* IntelliMouse Explorer XXX */
2734
2735     /*
2736      * XXX: this is a kludge to fool some KVM switch products
2737      * which think they are clever enough to know the 4-byte IntelliMouse
2738      * protocol, and assume any other protocols use 3-byte packets.
2739      * They don't convey 4-byte data packets from the IntelliMouse Explorer 
2740      * correctly to the host computer because of this!
2741      * The following sequence is actually IntelliMouse's "wake up"
2742      * sequence; it will make the KVM think the mouse is IntelliMouse
2743      * when it is in fact IntelliMouse Explorer.
2744      */
2745     for (i = 0; i < sizeof(rate0)/sizeof(rate0[0]); ++i) {
2746         if (set_mouse_sampling_rate(kbdc, rate0[i]) != rate0[i])
2747             break;
2748     }
2749     id = get_aux_id(kbdc);
2750
2751     return TRUE;
2752 }
2753
2754 /* MS IntelliMouse */
2755 static int
2756 enable_msintelli(struct psm_softc *sc)
2757 {
2758     /*
2759      * Logitech MouseMan+ and FirstMouse+ will also respond to this
2760      * probe routine and act like IntelliMouse.
2761      */
2762
2763     static unsigned char rate[] = { 200, 100, 80, };
2764     KBDC kbdc = sc->kbdc;
2765     int id;
2766     int i;
2767
2768     /* the special sequence to enable the third button and the roller. */
2769     for (i = 0; i < sizeof(rate)/sizeof(rate[0]); ++i) {
2770         if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i])
2771             return FALSE;
2772     }
2773     /* the device will give the genuine ID only after the above sequence */
2774     id = get_aux_id(kbdc);
2775     if (id != PSM_INTELLI_ID)
2776         return FALSE;
2777
2778     sc->hw.hwid = id;
2779     sc->hw.buttons = 3;
2780
2781     return TRUE;
2782 }
2783
2784 /* A4 Tech 4D Mouse */
2785 static int
2786 enable_4dmouse(struct psm_softc *sc)
2787 {
2788     /*
2789      * Newer wheel mice from A4 Tech may use the 4D+ protocol.
2790      */
2791
2792     static unsigned char rate[] = { 200, 100, 80, 60, 40, 20 };
2793     KBDC kbdc = sc->kbdc;
2794     int id;
2795     int i;
2796
2797     for (i = 0; i < sizeof(rate)/sizeof(rate[0]); ++i) {
2798         if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i])
2799             return FALSE;
2800     }
2801     id = get_aux_id(kbdc);
2802     /*
2803      * WinEasy 4D, 4 Way Scroll 4D: 6
2804      * Cable-Free 4D: 8 (4DPLUS)
2805      * WinBest 4D+, 4 Way Scroll 4D+: 8 (4DPLUS)
2806      */
2807     if (id != PSM_4DMOUSE_ID)
2808         return FALSE;
2809
2810     sc->hw.hwid = id;
2811     sc->hw.buttons = 3;         /* XXX some 4D mice have 4? */
2812
2813     return TRUE;
2814 }
2815
2816 /* A4 Tech 4D+ Mouse */
2817 static int
2818 enable_4dplus(struct psm_softc *sc)
2819 {
2820     /*
2821      * Newer wheel mice from A4 Tech seem to use this protocol.
2822      * Older models are recognized as either 4D Mouse or IntelliMouse.
2823      */
2824     KBDC kbdc = sc->kbdc;
2825     int id;
2826
2827     /*
2828      * enable_4dmouse() already issued the following ID sequence...
2829     static unsigned char rate[] = { 200, 100, 80, 60, 40, 20 };
2830     int i;
2831
2832     for (i = 0; i < sizeof(rate)/sizeof(rate[0]); ++i) {
2833         if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i])
2834             return FALSE;
2835     }
2836     */
2837
2838     id = get_aux_id(kbdc);
2839     if (id != PSM_4DPLUS_ID)
2840         return FALSE;
2841
2842     sc->hw.hwid = id;
2843     sc->hw.buttons = 4;         /* XXX */
2844
2845     return TRUE;
2846 }
2847
2848 /* Interlink electronics VersaPad */
2849 static int
2850 enable_versapad(struct psm_softc *sc)
2851 {
2852     KBDC kbdc = sc->kbdc;
2853     int data[3];
2854
2855     set_mouse_resolution(kbdc, PSMD_RES_MEDIUM_HIGH); /* set res. 2 */
2856     set_mouse_sampling_rate(kbdc, 100);         /* set rate 100 */
2857     set_mouse_scaling(kbdc, 1);                 /* set scale 1:1 */
2858     set_mouse_scaling(kbdc, 1);                 /* set scale 1:1 */
2859     set_mouse_scaling(kbdc, 1);                 /* set scale 1:1 */
2860     set_mouse_scaling(kbdc, 1);                 /* set scale 1:1 */
2861     if (get_mouse_status(kbdc, data, 0, 3) < 3) /* get status */
2862         return FALSE;
2863     if (data[2] != 0xa || data[1] != 0 )        /* rate == 0xa && res. == 0 */
2864         return FALSE;
2865     set_mouse_scaling(kbdc, 1);                 /* set scale 1:1 */
2866
2867     sc->config |= PSM_CONFIG_HOOKRESUME | PSM_CONFIG_INITAFTERSUSPEND;
2868
2869     return TRUE;                                /* PS/2 absolute mode */
2870 }
2871
2872 static int
2873 psmresume(device_t dev)
2874 {
2875     struct psm_softc *sc = device_get_softc(dev);
2876     int unit = device_get_unit(dev);
2877     int err;
2878
2879     if (verbose >= 2)
2880         log(LOG_NOTICE, "psm%d: system resume hook called.\n", unit);
2881
2882     if (!(sc->config & PSM_CONFIG_HOOKRESUME))
2883         return (0);
2884
2885     err = reinitialize(sc, sc->config & PSM_CONFIG_INITAFTERSUSPEND);
2886
2887     if ((sc->state & PSM_ASLP) && !(sc->state & PSM_VALID)) {
2888         /* 
2889          * Release the blocked process; it must be notified that the device
2890          * cannot be accessed anymore.
2891          */
2892         sc->state &= ~PSM_ASLP;
2893         wakeup((caddr_t)sc);
2894     }
2895
2896     if (verbose >= 2)
2897         log(LOG_DEBUG, "psm%d: system resume hook exiting.\n", unit);
2898
2899     return (err);
2900 }
2901
2902 DRIVER_MODULE(psm, atkbdc, psm_driver, psm_devclass, 0, 0);