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