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