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