xref: /freebsd/sys/dev/atkbdc/psm.c (revision 10534a60e8a62e6e70320bfa2e7fbe5ffe5ee4ba)
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 "psm.h"
65 #ifdef __i386__
66 #include "apm.h"
67 #endif
68 #include "opt_psm.h"
69 
70 #if NPSM > 0
71 
72 #include <sys/param.h>
73 #include <sys/systm.h>
74 #include <sys/kernel.h>
75 #include <sys/module.h>
76 #include <sys/bus.h>
77 #include <sys/conf.h>
78 #include <sys/poll.h>
79 #include <sys/syslog.h>
80 #include <sys/malloc.h>
81 #include <machine/bus.h>
82 #include <sys/rman.h>
83 #include <sys/select.h>
84 #include <sys/uio.h>
85 
86 #ifdef __i386__
87 #include <machine/apm_bios.h>
88 #endif
89 #include <machine/clock.h>
90 #include <machine/limits.h>
91 #include <machine/mouse.h>
92 #include <machine/resource.h>
93 
94 #include <isa/isareg.h>
95 #include <isa/isavar.h>
96 #include <dev/kbd/atkbdcreg.h>
97 
98 /*
99  * Driver specific options: the following options may be set by
100  * `options' statements in the kernel configuration file.
101  */
102 
103 /* debugging */
104 #ifndef PSM_DEBUG
105 #define PSM_DEBUG	0	/* logging: 0: none, 1: brief, 2: verbose */
106 #endif
107 
108 /* features */
109 
110 /* #define PSM_HOOKAPM	   	   hook the APM resume event */
111 /* #define PSM_RESETAFTERSUSPEND   reset the device at the resume event */
112 
113 #if NAPM <= 0
114 #undef PSM_HOOKAPM
115 #endif /* NAPM */
116 
117 #ifndef PSM_HOOKAPM
118 #undef PSM_RESETAFTERSUSPEND
119 #endif /* PSM_HOOKAPM */
120 
121 /* end of driver specific options */
122 
123 /* input queue */
124 #define PSM_BUFSIZE		960
125 #define PSM_SMALLBUFSIZE	240
126 
127 /* operation levels */
128 #define PSM_LEVEL_BASE		0
129 #define PSM_LEVEL_STANDARD	1
130 #define PSM_LEVEL_NATIVE	2
131 #define PSM_LEVEL_MIN		PSM_LEVEL_BASE
132 #define PSM_LEVEL_MAX		PSM_LEVEL_NATIVE
133 
134 /* Logitech PS2++ protocol */
135 #define MOUSE_PS2PLUS_CHECKBITS(b)	\
136 				((((b[2] & 0x03) << 2) | 0x02) == (b[1] & 0x0f))
137 #define MOUSE_PS2PLUS_PACKET_TYPE(b)	\
138 				(((b[0] & 0x30) >> 2) | ((b[1] & 0x30) >> 4))
139 
140 /* some macros */
141 #define PSM_UNIT(dev)		(minor(dev) >> 1)
142 #define PSM_NBLOCKIO(dev)	(minor(dev) & 1)
143 #define PSM_MKMINOR(unit,block)	(((unit) << 1) | ((block) ? 0:1))
144 
145 #ifndef max
146 #define max(x,y)		((x) > (y) ? (x) : (y))
147 #endif
148 #ifndef min
149 #define min(x,y)		((x) < (y) ? (x) : (y))
150 #endif
151 
152 #define abs(x)			(((x) < 0) ? -(x) : (x))
153 
154 /* ring buffer */
155 typedef struct ringbuf {
156     int           count;	/* # of valid elements in the buffer */
157     int           head;		/* head pointer */
158     int           tail;		/* tail poiner */
159     unsigned char buf[PSM_BUFSIZE];
160 } ringbuf_t;
161 
162 /* driver control block */
163 struct psm_softc {		/* Driver status information */
164     struct selinfo rsel;	/* Process selecting for Input */
165     unsigned char state;	/* Mouse driver state */
166     int           config;	/* driver configuration flags */
167     int           flags;	/* other flags */
168     KBDC          kbdc;		/* handle to access the keyboard controller */
169     int           addr;		/* I/O port address */
170     mousehw_t     hw;		/* hardware information */
171     mousemode_t   mode;		/* operation mode */
172     mousemode_t   dflt_mode;	/* default operation mode */
173     mousestatus_t status;	/* accumulated mouse movement */
174     ringbuf_t     queue;	/* mouse status queue */
175     unsigned char ipacket[16];	/* interim input buffer */
176     int           inputbytes;	/* # of bytes in the input buffer */
177     int           button;	/* the latest button state */
178     int		  xold;	/* previous absolute X position */
179     int		  yold;	/* previous absolute Y position */
180 #ifdef PSM_HOOKAPM
181     struct apmhook resumehook;
182 #endif
183 };
184 devclass_t psm_devclass;
185 #define PSM_SOFTC(unit)	((struct psm_softc*)devclass_get_softc(psm_devclass, unit))
186 
187 /* driver state flags (state) */
188 #define PSM_VALID		0x80
189 #define PSM_OPEN		1	/* Device is open */
190 #define PSM_ASLP		2	/* Waiting for mouse data */
191 
192 /* driver configuration flags (config) */
193 #define PSM_CONFIG_RESOLUTION	0x000f	/* resolution */
194 #define PSM_CONFIG_ACCEL	0x00f0  /* acceleration factor */
195 #define PSM_CONFIG_NOCHECKSYNC	0x0100  /* disable sync. test */
196 #define PSM_CONFIG_NOIDPROBE	0x0200  /* disable mouse model probe */
197 #define PSM_CONFIG_NORESET	0x0400  /* don't reset the mouse */
198 #define PSM_CONFIG_FORCETAP	0x0800  /* assume `tap' action exists */
199 #define PSM_CONFIG_IGNPORTERROR	0x1000  /* ignore error in aux port test */
200 
201 #define PSM_CONFIG_FLAGS	(PSM_CONFIG_RESOLUTION 		\
202 				    | PSM_CONFIG_ACCEL		\
203 				    | PSM_CONFIG_NOCHECKSYNC	\
204 				    | PSM_CONFIG_NOIDPROBE	\
205 				    | PSM_CONFIG_NORESET	\
206 				    | PSM_CONFIG_FORCETAP	\
207 				    | PSM_CONFIG_IGNPORTERROR)
208 
209 /* other flags (flags) */
210 #define PSM_FLAGS_FINGERDOWN	0x0001 /* VersaPad finger down */
211 
212 /* for backward compatibility */
213 #define OLD_MOUSE_GETHWINFO	_IOR('M', 1, old_mousehw_t)
214 #define OLD_MOUSE_GETMODE	_IOR('M', 2, old_mousemode_t)
215 #define OLD_MOUSE_SETMODE	_IOW('M', 3, old_mousemode_t)
216 
217 typedef struct old_mousehw {
218     int buttons;
219     int iftype;
220     int type;
221     int hwid;
222 } old_mousehw_t;
223 
224 typedef struct old_mousemode {
225     int protocol;
226     int rate;
227     int resolution;
228     int accelfactor;
229 } old_mousemode_t;
230 
231 /* packet formatting function */
232 typedef int packetfunc_t __P((struct psm_softc *, unsigned char *,
233 			      int *, int, mousestatus_t *));
234 
235 /* function prototypes */
236 static int psmprobe __P((device_t));
237 static int psmattach __P((device_t));
238 #ifdef PSM_HOOKAPM
239 static int psmresume __P((void *));
240 #endif
241 
242 static d_open_t psmopen;
243 static d_close_t psmclose;
244 static d_read_t psmread;
245 static d_ioctl_t psmioctl;
246 static d_poll_t psmpoll;
247 
248 static int enable_aux_dev __P((KBDC));
249 static int disable_aux_dev __P((KBDC));
250 static int get_mouse_status __P((KBDC, int *, int, int));
251 static int get_aux_id __P((KBDC));
252 static int set_mouse_sampling_rate __P((KBDC, int));
253 static int set_mouse_scaling __P((KBDC, int));
254 static int set_mouse_resolution __P((KBDC, int));
255 #ifdef PSM_RESETAFTERSUSPEND
256 static int set_mouse_mode __P((KBDC));
257 #endif /* PSM_RESETAFTERSUSPEND */
258 static int get_mouse_buttons __P((KBDC));
259 static int is_a_mouse __P((int));
260 static void recover_from_error __P((KBDC));
261 static int restore_controller __P((KBDC, int));
262 #ifdef PSM_RESETAFTERSUSPEND
263 static int reinitialize __P((int, mousemode_t *));
264 #endif
265 static int doopen __P((int, int));
266 static char *model_name(int);
267 static void psmintr(void*);
268 
269 /* vendor specific features */
270 typedef int probefunc_t __P((struct psm_softc *));
271 
272 static int mouse_id_proc1 __P((KBDC, int, int, int *));
273 static probefunc_t enable_groller;
274 static probefunc_t enable_gmouse;
275 static probefunc_t enable_aglide;
276 static probefunc_t enable_kmouse;
277 static probefunc_t enable_msintelli;
278 static probefunc_t enable_mmanplus;
279 static probefunc_t enable_versapad;
280 static int tame_mouse __P((struct psm_softc *, mousestatus_t *, unsigned char *));
281 
282 static struct {
283     int                 model;
284     unsigned char	syncmask;
285     int 		packetsize;
286     probefunc_t 	*probefunc;
287 } vendortype[] = {
288     { MOUSE_MODEL_NET,			/* Genius NetMouse */
289       0xc8, MOUSE_INTELLI_PACKETSIZE, enable_gmouse, },
290     { MOUSE_MODEL_NETSCROLL,		/* Genius NetScroll */
291       0xc8, 6, enable_groller, },
292     { MOUSE_MODEL_GLIDEPOINT,		/* ALPS GlidePoint */
293       0xc0, MOUSE_PS2_PACKETSIZE, enable_aglide, },
294     { MOUSE_MODEL_MOUSEMANPLUS,		/* Logitech MouseMan+ */
295       0x08, MOUSE_PS2_PACKETSIZE, enable_mmanplus, },
296     { MOUSE_MODEL_THINK,		/* Kensignton ThinkingMouse */
297       0x80, MOUSE_PS2_PACKETSIZE, enable_kmouse, },
298     { MOUSE_MODEL_INTELLI,		/* Microsoft IntelliMouse */
299       0xc8, MOUSE_INTELLI_PACKETSIZE, enable_msintelli, },
300     { MOUSE_MODEL_VERSAPAD,		/* Interlink electronics VersaPad */
301       0xe8, MOUSE_PS2VERSA_PACKETSIZE, enable_versapad, },
302     { MOUSE_MODEL_GENERIC,
303       0xc0, MOUSE_PS2_PACKETSIZE, NULL, },
304 };
305 #define GENERIC_MOUSE_ENTRY	7
306 
307 /* device driver declarateion */
308 static device_method_t psm_methods[] = {
309 	/* Device interface */
310 	DEVMETHOD(device_probe,		psmprobe),
311 	DEVMETHOD(device_attach,	psmattach),
312 
313 	{ 0, 0 }
314 };
315 
316 static driver_t psm_driver = {
317     "psm",
318     psm_methods,
319     sizeof(struct psm_softc),
320 };
321 
322 #define CDEV_MAJOR        21
323 
324 static struct cdevsw psm_cdevsw = {
325 	/* open */	psmopen,
326 	/* close */	psmclose,
327 	/* read */	psmread,
328 	/* write */	nowrite,
329 	/* ioctl */	psmioctl,
330 	/* poll */	psmpoll,
331 	/* mmap */	nommap,
332 	/* strategy */	nostrategy,
333 	/* name */	"psm",
334 	/* maj */	CDEV_MAJOR,
335 	/* dump */	nodump,
336 	/* psize */	nopsize,
337 	/* flags */	0,
338 	/* bmaj */	-1
339 };
340 
341 /* debug message level */
342 static int verbose = PSM_DEBUG;
343 
344 /* device I/O routines */
345 static int
346 enable_aux_dev(KBDC kbdc)
347 {
348     int res;
349 
350     res = send_aux_command(kbdc, PSMC_ENABLE_DEV);
351     if (verbose >= 2)
352         log(LOG_DEBUG, "psm: ENABLE_DEV return code:%04x\n", res);
353 
354     return (res == PSM_ACK);
355 }
356 
357 static int
358 disable_aux_dev(KBDC kbdc)
359 {
360     int res;
361 
362     res = send_aux_command(kbdc, PSMC_DISABLE_DEV);
363     if (verbose >= 2)
364         log(LOG_DEBUG, "psm: DISABLE_DEV return code:%04x\n", res);
365 
366     return (res == PSM_ACK);
367 }
368 
369 static int
370 get_mouse_status(KBDC kbdc, int *status, int flag, int len)
371 {
372     int cmd;
373     int res;
374     int i;
375 
376     switch (flag) {
377     case 0:
378     default:
379 	cmd = PSMC_SEND_DEV_STATUS;
380 	break;
381     case 1:
382 	cmd = PSMC_SEND_DEV_DATA;
383 	break;
384     }
385     empty_aux_buffer(kbdc, 5);
386     res = send_aux_command(kbdc, cmd);
387     if (verbose >= 2)
388         log(LOG_DEBUG, "psm: SEND_AUX_DEV_%s return code:%04x\n",
389 	    (flag == 1) ? "DATA" : "STATUS", res);
390     if (res != PSM_ACK)
391         return 0;
392 
393     for (i = 0; i < len; ++i) {
394         status[i] = read_aux_data(kbdc);
395 	if (status[i] < 0)
396 	    break;
397     }
398 
399     if (verbose) {
400         log(LOG_DEBUG, "psm: %s %02x %02x %02x\n",
401             (flag == 1) ? "data" : "status", status[0], status[1], status[2]);
402     }
403 
404     return i;
405 }
406 
407 static int
408 get_aux_id(KBDC kbdc)
409 {
410     int res;
411     int id;
412 
413     empty_aux_buffer(kbdc, 5);
414     res = send_aux_command(kbdc, PSMC_SEND_DEV_ID);
415     if (verbose >= 2)
416         log(LOG_DEBUG, "psm: SEND_DEV_ID return code:%04x\n", res);
417     if (res != PSM_ACK)
418 	return (-1);
419 
420     /* 10ms delay */
421     DELAY(10000);
422 
423     id = read_aux_data(kbdc);
424     if (verbose >= 2)
425         log(LOG_DEBUG, "psm: device ID: %04x\n", id);
426 
427     return id;
428 }
429 
430 static int
431 set_mouse_sampling_rate(KBDC kbdc, int rate)
432 {
433     int res;
434 
435     res = send_aux_command_and_data(kbdc, PSMC_SET_SAMPLING_RATE, rate);
436     if (verbose >= 2)
437         log(LOG_DEBUG, "psm: SET_SAMPLING_RATE (%d) %04x\n", rate, res);
438 
439     return ((res == PSM_ACK) ? rate : -1);
440 }
441 
442 static int
443 set_mouse_scaling(KBDC kbdc, int scale)
444 {
445     int res;
446 
447     switch (scale) {
448     case 1:
449     default:
450 	scale = PSMC_SET_SCALING11;
451 	break;
452     case 2:
453 	scale = PSMC_SET_SCALING21;
454 	break;
455     }
456     res = send_aux_command(kbdc, scale);
457     if (verbose >= 2)
458         log(LOG_DEBUG, "psm: SET_SCALING%s return code:%04x\n",
459 	    (scale == PSMC_SET_SCALING21) ? "21" : "11", res);
460 
461     return (res == PSM_ACK);
462 }
463 
464 /* `val' must be 0 through PSMD_MAX_RESOLUTION */
465 static int
466 set_mouse_resolution(KBDC kbdc, int val)
467 {
468     int res;
469 
470     res = send_aux_command_and_data(kbdc, PSMC_SET_RESOLUTION, val);
471     if (verbose >= 2)
472         log(LOG_DEBUG, "psm: SET_RESOLUTION (%d) %04x\n", val, res);
473 
474     return ((res == PSM_ACK) ? val : -1);
475 }
476 
477 #ifdef PSM_RESETAFTERSUSPEND
478 /*
479  * NOTE: once `set_mouse_mode()' is called, the mouse device must be
480  * re-enabled by calling `enable_aux_dev()'
481  */
482 static int
483 set_mouse_mode(KBDC kbdc)
484 {
485     int res;
486 
487     res = send_aux_command(kbdc, PSMC_SET_STREAM_MODE);
488     if (verbose >= 2)
489         log(LOG_DEBUG, "psm: SET_STREAM_MODE return code:%04x\n", res);
490 
491     return (res == PSM_ACK);
492 }
493 #endif /* PSM_RESETAFTERSUSPEND */
494 
495 
496 static int
497 get_mouse_buttons(KBDC kbdc)
498 {
499     int c = 2;		/* assume two buttons by default */
500     int status[3];
501 
502     /*
503      * NOTE: a special sequence to obtain Logitech Mouse specific
504      * information: set resolution to 25 ppi, set scaling to 1:1, set
505      * scaling to 1:1, set scaling to 1:1. Then the second byte of the
506      * mouse status bytes is the number of available buttons.
507      * Some manufactures also support this sequence.
508      */
509     if (set_mouse_resolution(kbdc, PSMD_RES_LOW) != PSMD_RES_LOW)
510         return c;
511     if (set_mouse_scaling(kbdc, 1) && set_mouse_scaling(kbdc, 1)
512         && set_mouse_scaling(kbdc, 1)
513 	&& (get_mouse_status(kbdc, status, 0, 3) >= 3)) {
514         if (status[1] != 0)
515             return status[1];
516     }
517     return c;
518 }
519 
520 /* misc subroutines */
521 /*
522  * Someday, I will get the complete list of valid pointing devices and
523  * their IDs... XXX
524  */
525 static int
526 is_a_mouse(int id)
527 {
528 #if 0
529     static int valid_ids[] = {
530         PSM_MOUSE_ID,		/* mouse */
531         PSM_BALLPOINT_ID,	/* ballpoint device */
532         PSM_INTELLI_ID,		/* Intellimouse */
533         -1			/* end of table */
534     };
535     int i;
536 
537     for (i = 0; valid_ids[i] >= 0; ++i)
538         if (valid_ids[i] == id)
539             return TRUE;
540     return FALSE;
541 #else
542     return TRUE;
543 #endif
544 }
545 
546 static char *
547 model_name(int model)
548 {
549     static struct {
550 	int model_code;
551 	char *model_name;
552     } models[] = {
553         { MOUSE_MODEL_NETSCROLL,	"NetScroll Mouse" },
554         { MOUSE_MODEL_NET,		"NetMouse" },
555         { MOUSE_MODEL_GLIDEPOINT,	"GlidePoint" },
556         { MOUSE_MODEL_THINK,		"ThinkingMouse" },
557         { MOUSE_MODEL_INTELLI,		"IntelliMouse" },
558         { MOUSE_MODEL_MOUSEMANPLUS,	"MouseMan+" },
559         { MOUSE_MODEL_VERSAPAD,		"VersaPad" },
560         { MOUSE_MODEL_GENERIC,		"Generic PS/2 mouse" },
561         { MOUSE_MODEL_UNKNOWN,		NULL },
562     };
563     int i;
564 
565     for (i = 0; models[i].model_code != MOUSE_MODEL_UNKNOWN; ++i) {
566 	if (models[i].model_code == model)
567 	    return models[i].model_name;
568     }
569     return "Unknown";
570 }
571 
572 static void
573 recover_from_error(KBDC kbdc)
574 {
575     /* discard anything left in the output buffer */
576     empty_both_buffers(kbdc, 10);
577 
578 #if 0
579     /*
580      * NOTE: KBDC_RESET_KBD may not restore the communication between the
581      * keyboard and the controller.
582      */
583     reset_kbd(kbdc);
584 #else
585     /*
586      * NOTE: somehow diagnostic and keyboard port test commands bring the
587      * keyboard back.
588      */
589     if (!test_controller(kbdc))
590         log(LOG_ERR, "psm: keyboard controller failed.\n");
591     /* if there isn't a keyboard in the system, the following error is OK */
592     if (test_kbd_port(kbdc) != 0) {
593 	if (verbose)
594 	    log(LOG_ERR, "psm: keyboard port failed.\n");
595     }
596 #endif
597 }
598 
599 static int
600 restore_controller(KBDC kbdc, int command_byte)
601 {
602     empty_both_buffers(kbdc, 10);
603 
604     if (!set_controller_command_byte(kbdc, 0xff, command_byte)) {
605 	log(LOG_ERR, "psm: failed to restore the keyboard controller "
606 		     "command byte.\n");
607 	return FALSE;
608     } else {
609 	return TRUE;
610     }
611 }
612 
613 #ifdef PSM_RESETAFTERSUSPEND
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 #endif /* PSM_RESETAFTERSUSPEND */
721 
722 static int
723 doopen(int unit, int command_byte)
724 {
725     struct psm_softc *sc = PSM_SOFTC(unit);
726     int stat[3];
727 
728     /* enable the mouse device */
729     if (!enable_aux_dev(sc->kbdc)) {
730 	/* MOUSE ERROR: failed to enable the mouse because:
731 	 * 1) the mouse is faulty,
732 	 * 2) the mouse has been removed(!?)
733 	 * In the latter case, the keyboard may have hung, and need
734 	 * recovery procedure...
735 	 */
736 	recover_from_error(sc->kbdc);
737 #if 0
738 	/* FIXME: we could reset the mouse here and try to enable
739 	 * it again. But it will take long time and it's not a good
740 	 * idea to disable the keyboard that long...
741 	 */
742 	if (!reinitialize(unit, &sc->mode) || !enable_aux_dev(sc->kbdc)) {
743 	    recover_from_error(sc->kbdc);
744 #else
745         {
746 #endif
747             restore_controller(sc->kbdc, command_byte);
748 	    /* mark this device is no longer available */
749 	    sc->state &= ~PSM_VALID;
750 	    log(LOG_ERR, "psm%d: failed to enable the device (doopen).\n",
751 		unit);
752 	    return (EIO);
753 	}
754     }
755 
756     if (get_mouse_status(sc->kbdc, stat, 0, 3) < 3)
757         log(LOG_DEBUG, "psm%d: failed to get status (doopen).\n", unit);
758 
759     /* enable the aux port and interrupt */
760     if (!set_controller_command_byte(sc->kbdc,
761 	    kbdc_get_device_mask(sc->kbdc),
762 	    (command_byte & KBD_KBD_CONTROL_BITS)
763 		| KBD_ENABLE_AUX_PORT | KBD_ENABLE_AUX_INT)) {
764 	/* CONTROLLER ERROR */
765 	disable_aux_dev(sc->kbdc);
766         restore_controller(sc->kbdc, command_byte);
767 	log(LOG_ERR, "psm%d: failed to enable the aux interrupt (doopen).\n",
768 	    unit);
769 	return (EIO);
770     }
771 
772     return (0);
773 }
774 
775 /* psm driver entry points */
776 
777 #define endprobe(v)	{   if (bootverbose) 				\
778 				--verbose;   				\
779                             kbdc_set_device_mask(sc->kbdc, mask);	\
780 			    kbdc_lock(sc->kbdc, FALSE);			\
781  	                    free(sc, M_DEVBUF);                         \
782 			    return (v);	     				\
783 			}
784 
785 static int
786 psmprobe(device_t dev)
787 {
788     int unit = device_get_unit(dev);
789     struct psm_softc *sc = device_get_softc(dev);
790     uintptr_t port;
791     uintptr_t flags;
792     int stat[3];
793     int command_byte;
794     int mask;
795     int i;
796 
797 #if 0
798     kbdc_debug(TRUE);
799 #endif
800     BUS_READ_IVAR(device_get_parent(dev), dev, KBDC_IVAR_PORT, &port);
801     BUS_READ_IVAR(device_get_parent(dev), dev, KBDC_IVAR_FLAGS, &flags);
802 
803     sc->addr = port;
804     sc->kbdc = kbdc_open(sc->addr);
805     sc->config = flags & PSM_CONFIG_FLAGS;
806     sc->flags = 0;
807     if (bootverbose)
808         ++verbose;
809 
810     device_set_desc(dev, "PS/2 Mouse");
811 
812     if (!kbdc_lock(sc->kbdc, TRUE)) {
813         printf("psm%d: unable to lock the controller.\n", unit);
814         if (bootverbose)
815             --verbose;
816 	return (ENXIO);
817     }
818 
819     /*
820      * NOTE: two bits in the command byte controls the operation of the
821      * aux port (mouse port): the aux port disable bit (bit 5) and the aux
822      * port interrupt (IRQ 12) enable bit (bit 2).
823      */
824 
825     /* discard anything left after the keyboard initialization */
826     empty_both_buffers(sc->kbdc, 10);
827 
828     /* save the current command byte; it will be used later */
829     mask = kbdc_get_device_mask(sc->kbdc) & ~KBD_AUX_CONTROL_BITS;
830     command_byte = get_controller_command_byte(sc->kbdc);
831     if (verbose)
832         printf("psm%d: current command byte:%04x\n", unit, command_byte);
833     if (command_byte == -1) {
834         /* CONTROLLER ERROR */
835         printf("psm%d: unable to get the current command byte value.\n",
836             unit);
837         endprobe(ENXIO);
838     }
839 
840     /*
841      * disable the keyboard port while probing the aux port, which must be
842      * enabled during this routine
843      */
844     if (!set_controller_command_byte(sc->kbdc,
845 	    KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS,
846   	    KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT
847                 | KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
848         /*
849 	 * this is CONTROLLER ERROR; I don't know how to recover
850          * from this error...
851 	 */
852         restore_controller(sc->kbdc, command_byte);
853         printf("psm%d: unable to set the command byte.\n", unit);
854         endprobe(ENXIO);
855     }
856     write_controller_command(sc->kbdc, KBDC_ENABLE_AUX_PORT);
857 
858     /*
859      * NOTE: `test_aux_port()' is designed to return with zero if the aux
860      * port exists and is functioning. However, some controllers appears
861      * to respond with zero even when the aux port doesn't exist. (It may
862      * be that this is only the case when the controller DOES have the aux
863      * port but the port is not wired on the motherboard.) The keyboard
864      * controllers without the port, such as the original AT, are
865      * supporsed to return with an error code or simply time out. In any
866      * case, we have to continue probing the port even when the controller
867      * passes this test.
868      *
869      * XXX: some controllers erroneously return the error code 1 when
870      * it has the perfectly functional aux port. We have to ignore this
871      * error code. Even if the controller HAS error with the aux port,
872      * it will be detected later...
873      * XXX: another incompatible controller returns PSM_ACK (0xfa)...
874      */
875     switch ((i = test_aux_port(sc->kbdc))) {
876     case 1:	   /* ignore this error */
877     case PSM_ACK:
878         if (verbose)
879 	    printf("psm%d: strange result for test aux port (%d).\n",
880 	        unit, i);
881 	/* fall though */
882     case 0:        /* no error */
883         break;
884     case -1:        /* time out */
885     default:        /* error */
886         recover_from_error(sc->kbdc);
887 	if (sc->config & PSM_CONFIG_IGNPORTERROR)
888 	    break;
889         restore_controller(sc->kbdc, command_byte);
890         if (verbose)
891             printf("psm%d: the aux port is not functioning (%d).\n",
892                 unit, i);
893         endprobe(ENXIO);
894     }
895 
896     if (sc->config & PSM_CONFIG_NORESET) {
897 	/*
898 	 * Don't try to reset the pointing device.  It may possibly be
899 	 * left in the unknown state, though...
900 	 */
901     } else {
902 	/*
903 	 * NOTE: some controllers appears to hang the `keyboard' when the aux
904 	 * port doesn't exist and `PSMC_RESET_DEV' is issued.
905 	 */
906 	if (!reset_aux_dev(sc->kbdc)) {
907             recover_from_error(sc->kbdc);
908             restore_controller(sc->kbdc, command_byte);
909             if (verbose)
910         	printf("psm%d: failed to reset the aux device.\n", unit);
911             endprobe(ENXIO);
912 	}
913     }
914 
915     /*
916      * both the aux port and the aux device is functioning, see if the
917      * device can be enabled. NOTE: when enabled, the device will start
918      * sending data; we shall immediately disable the device once we know
919      * the device can be enabled.
920      */
921     if (!enable_aux_dev(sc->kbdc) || !disable_aux_dev(sc->kbdc)) {
922         /* MOUSE ERROR */
923 	recover_from_error(sc->kbdc);
924 	restore_controller(sc->kbdc, command_byte);
925 	if (verbose)
926 	    printf("psm%d: failed to enable the aux device.\n", unit);
927         endprobe(ENXIO);
928     }
929 
930     /* save the default values after reset */
931     if (get_mouse_status(sc->kbdc, stat, 0, 3) >= 3) {
932 	sc->dflt_mode.rate = sc->mode.rate = stat[2];
933 	sc->dflt_mode.resolution = sc->mode.resolution = stat[1];
934     } else {
935 	sc->dflt_mode.rate = sc->mode.rate = -1;
936 	sc->dflt_mode.resolution = sc->mode.resolution = -1;
937     }
938 
939     /* hardware information */
940     sc->hw.iftype = MOUSE_IF_PS2;
941 
942     /* verify the device is a mouse */
943     sc->hw.hwid = get_aux_id(sc->kbdc);
944     if (!is_a_mouse(sc->hw.hwid)) {
945         restore_controller(sc->kbdc, command_byte);
946         if (verbose)
947             printf("psm%d: unknown device type (%d).\n", unit, sc->hw.hwid);
948         endprobe(ENXIO);
949     }
950     switch (sc->hw.hwid) {
951     case PSM_BALLPOINT_ID:
952         sc->hw.type = MOUSE_TRACKBALL;
953         break;
954     case PSM_MOUSE_ID:
955     case PSM_INTELLI_ID:
956         sc->hw.type = MOUSE_MOUSE;
957         break;
958     default:
959         sc->hw.type = MOUSE_UNKNOWN;
960         break;
961     }
962 
963     if (sc->config & PSM_CONFIG_NOIDPROBE) {
964 	sc->hw.buttons = 2;
965 	i = GENERIC_MOUSE_ENTRY;
966     } else {
967 	/* # of buttons */
968 	sc->hw.buttons = get_mouse_buttons(sc->kbdc);
969 
970 	/* other parameters */
971 	for (i = 0; vendortype[i].probefunc != NULL; ++i) {
972 	    if ((*vendortype[i].probefunc)(sc)) {
973 		if (verbose >= 2)
974 		    printf("psm%d: found %s\n",
975 			   unit, model_name(vendortype[i].model));
976 		break;
977 	    }
978 	}
979     }
980 
981     sc->hw.model = vendortype[i].model;
982 
983     sc->dflt_mode.level = PSM_LEVEL_BASE;
984     sc->dflt_mode.packetsize = MOUSE_PS2_PACKETSIZE;
985     sc->dflt_mode.accelfactor = (sc->config & PSM_CONFIG_ACCEL) >> 4;
986     if (sc->config & PSM_CONFIG_NOCHECKSYNC)
987         sc->dflt_mode.syncmask[0] = 0;
988     else
989         sc->dflt_mode.syncmask[0] = vendortype[i].syncmask;
990     if (sc->config & PSM_CONFIG_FORCETAP)
991         sc->mode.syncmask[0] &= ~MOUSE_PS2_TAP;
992     sc->dflt_mode.syncmask[1] = 0;	/* syncbits */
993     sc->mode = sc->dflt_mode;
994     sc->mode.packetsize = vendortype[i].packetsize;
995 
996     /* set mouse parameters */
997 #if 0
998     /*
999      * A version of Logitech FirstMouse+ won't report wheel movement,
1000      * if SET_DEFAULTS is sent...  Don't use this command.
1001      * This fix was found by Takashi Nishida.
1002      */
1003     i = send_aux_command(sc->kbdc, PSMC_SET_DEFAULTS);
1004     if (verbose >= 2)
1005 	printf("psm%d: SET_DEFAULTS return code:%04x\n", unit, i);
1006 #endif
1007     if (sc->config & PSM_CONFIG_RESOLUTION) {
1008         sc->mode.resolution
1009 	    = set_mouse_resolution(sc->kbdc,
1010 				   (sc->config & PSM_CONFIG_RESOLUTION) - 1);
1011     } else if (sc->mode.resolution >= 0) {
1012 	sc->mode.resolution
1013 	    = set_mouse_resolution(sc->kbdc, sc->dflt_mode.resolution);
1014     }
1015     if (sc->mode.rate > 0) {
1016 	sc->mode.rate = set_mouse_sampling_rate(sc->kbdc, sc->dflt_mode.rate);
1017     }
1018     set_mouse_scaling(sc->kbdc, 1);
1019 
1020     /* request a data packet and extract sync. bits */
1021     if (get_mouse_status(sc->kbdc, stat, 1, 3) < 3) {
1022         printf("psm%d: failed to get data.\n", unit);
1023         sc->mode.syncmask[0] = 0;
1024     } else {
1025         sc->mode.syncmask[1] = stat[0] & sc->mode.syncmask[0];	/* syncbits */
1026 	/* the NetScroll Mouse will send three more bytes... Ignore them */
1027 	empty_aux_buffer(sc->kbdc, 5);
1028     }
1029 
1030     /* just check the status of the mouse */
1031     /*
1032      * NOTE: XXX there are some arcane controller/mouse combinations out
1033      * there, which hung the controller unless there is data transmission
1034      * after ACK from the mouse.
1035      */
1036     if (get_mouse_status(sc->kbdc, stat, 0, 3) < 3) {
1037         printf("psm%d: failed to get status.\n", unit);
1038     } else {
1039 	/*
1040 	 * When in its native mode, some mice operate with different
1041 	 * default parameters than in the PS/2 compatible mode.
1042 	 */
1043         sc->dflt_mode.rate = sc->mode.rate = stat[2];
1044         sc->dflt_mode.resolution = sc->mode.resolution = stat[1];
1045      }
1046 
1047     /* disable the aux port for now... */
1048     if (!set_controller_command_byte(sc->kbdc,
1049 	    KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS,
1050             (command_byte & KBD_KBD_CONTROL_BITS)
1051                 | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
1052         /*
1053 	 * this is CONTROLLER ERROR; I don't know the proper way to
1054          * recover from this error...
1055 	 */
1056         restore_controller(sc->kbdc, command_byte);
1057         printf("psm%d: unable to set the command byte.\n", unit);
1058         endprobe(ENXIO);
1059     }
1060 
1061     /* done */
1062     kbdc_set_device_mask(sc->kbdc, mask | KBD_AUX_CONTROL_BITS);
1063     kbdc_lock(sc->kbdc, FALSE);
1064     return (0);
1065 }
1066 
1067 static int
1068 psmattach(device_t dev)
1069 {
1070     int unit = device_get_unit(dev);
1071     struct psm_softc *sc = device_get_softc(dev);
1072     void *ih;
1073     struct resource *res;
1074     uintptr_t irq;
1075     int zero = 0;
1076 
1077     if (sc == NULL)    /* shouldn't happen */
1078 	return (ENXIO);
1079 
1080     /* Setup initial state */
1081     sc->state = PSM_VALID;
1082 
1083     /* Done */
1084     make_dev(&psm_cdevsw, PSM_MKMINOR(unit, FALSE), 0, 0, 0666, "psm%d", unit);
1085     make_dev(&psm_cdevsw, PSM_MKMINOR(unit, TRUE), 0, 0, 0666, "bpsm%d", unit);
1086 
1087 #ifdef PSM_HOOKAPM
1088     sc->resumehook.ah_name = "PS/2 mouse";
1089     sc->resumehook.ah_fun = psmresume;
1090     sc->resumehook.ah_arg = (void *)unit;
1091     sc->resumehook.ah_order = APM_MID_ORDER;
1092     apm_hook_establish(APM_HOOK_RESUME , &sc->resumehook);
1093     if (verbose)
1094         printf("psm%d: APM hooks installed.\n", unit);
1095 #endif /* PSM_HOOKAPM */
1096 
1097     if (!verbose) {
1098         printf("psm%d: model %s, device ID %d\n",
1099 	    unit, model_name(sc->hw.model), sc->hw.hwid & 0x00ff);
1100     } else {
1101         printf("psm%d: model %s, device ID %d-%02x, %d buttons\n",
1102 	    unit, model_name(sc->hw.model),
1103 	    sc->hw.hwid & 0x00ff, sc->hw.hwid >> 8, sc->hw.buttons);
1104 	printf("psm%d: config:%08x, flags:%08x, packet size:%d\n",
1105 	    unit, sc->config, sc->flags, sc->mode.packetsize);
1106 	printf("psm%d: syncmask:%02x, syncbits:%02x\n",
1107 	    unit, sc->mode.syncmask[0], sc->mode.syncmask[1]);
1108     }
1109 
1110     if (bootverbose)
1111         --verbose;
1112 
1113     BUS_READ_IVAR(device_get_parent(dev), dev, KBDC_IVAR_IRQ, &irq);
1114     res = bus_alloc_resource(dev, SYS_RES_IRQ, &zero, irq, irq, 1,
1115 			     RF_SHAREABLE | RF_ACTIVE);
1116     BUS_SETUP_INTR(device_get_parent(dev), dev, res, INTR_TYPE_TTY,
1117 		   psmintr, sc, &ih);
1118 
1119     return (0);
1120 }
1121 
1122 static int
1123 psmopen(dev_t dev, int flag, int fmt, struct proc *p)
1124 {
1125     int unit = PSM_UNIT(dev);
1126     struct psm_softc *sc;
1127     int command_byte;
1128     int err;
1129     int s;
1130 
1131     /* Validate unit number */
1132     if (unit >= NPSM)
1133         return (ENXIO);
1134 
1135     /* Get device data */
1136     sc = PSM_SOFTC(unit);
1137     if ((sc == NULL) || (sc->state & PSM_VALID) == 0)
1138 	/* the device is no longer valid/functioning */
1139         return (ENXIO);
1140 
1141     /* Disallow multiple opens */
1142     if (sc->state & PSM_OPEN)
1143         return (EBUSY);
1144 
1145     device_busy(devclass_get_device(psm_devclass, unit));
1146 
1147     /* Initialize state */
1148     sc->rsel.si_flags = 0;
1149     sc->rsel.si_pid = 0;
1150     sc->mode.level = sc->dflt_mode.level;
1151     sc->mode.protocol = sc->dflt_mode.protocol;
1152 
1153     /* flush the event queue */
1154     sc->queue.count = 0;
1155     sc->queue.head = 0;
1156     sc->queue.tail = 0;
1157     sc->status.flags = 0;
1158     sc->status.button = 0;
1159     sc->status.obutton = 0;
1160     sc->status.dx = 0;
1161     sc->status.dy = 0;
1162     sc->status.dz = 0;
1163     sc->button = 0;
1164 
1165     /* empty input buffer */
1166     bzero(sc->ipacket, sizeof(sc->ipacket));
1167     sc->inputbytes = 0;
1168 
1169     /* don't let timeout routines in the keyboard driver to poll the kbdc */
1170     if (!kbdc_lock(sc->kbdc, TRUE))
1171 	return (EIO);
1172 
1173     /* save the current controller command byte */
1174     s = spltty();
1175     command_byte = get_controller_command_byte(sc->kbdc);
1176 
1177     /* enable the aux port and temporalily disable the keyboard */
1178     if ((command_byte == -1)
1179         || !set_controller_command_byte(sc->kbdc,
1180 	    kbdc_get_device_mask(sc->kbdc),
1181   	    KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT
1182 	        | KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
1183         /* CONTROLLER ERROR; do you know how to get out of this? */
1184         kbdc_lock(sc->kbdc, FALSE);
1185 	splx(s);
1186 	log(LOG_ERR, "psm%d: unable to set the command byte (psmopen).\n",
1187 	    unit);
1188 	return (EIO);
1189     }
1190     /*
1191      * Now that the keyboard controller is told not to generate
1192      * the keyboard and mouse interrupts, call `splx()' to allow
1193      * the other tty interrupts. The clock interrupt may also occur,
1194      * but timeout routines will be blocked by the poll flag set
1195      * via `kbdc_lock()'
1196      */
1197     splx(s);
1198 
1199     /* enable the mouse device */
1200     err = doopen(unit, command_byte);
1201 
1202     /* done */
1203     if (err == 0)
1204         sc->state |= PSM_OPEN;
1205     kbdc_lock(sc->kbdc, FALSE);
1206     return (err);
1207 }
1208 
1209 static int
1210 psmclose(dev_t dev, int flag, int fmt, struct proc *p)
1211 {
1212     int unit = PSM_UNIT(dev);
1213     struct psm_softc *sc = PSM_SOFTC(unit);
1214     int stat[3];
1215     int command_byte;
1216     int s;
1217 
1218     /* don't let timeout routines in the keyboard driver to poll the kbdc */
1219     if (!kbdc_lock(sc->kbdc, TRUE))
1220 	return (EIO);
1221 
1222     /* save the current controller command byte */
1223     s = spltty();
1224     command_byte = get_controller_command_byte(sc->kbdc);
1225     if (command_byte == -1) {
1226         kbdc_lock(sc->kbdc, FALSE);
1227 	splx(s);
1228 	return (EIO);
1229     }
1230 
1231     /* disable the aux interrupt and temporalily disable the keyboard */
1232     if (!set_controller_command_byte(sc->kbdc,
1233 	    kbdc_get_device_mask(sc->kbdc),
1234   	    KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT
1235 	        | KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
1236 	log(LOG_ERR, "psm%d: failed to disable the aux int (psmclose).\n",
1237 	    PSM_UNIT(dev));
1238 	/* CONTROLLER ERROR;
1239 	 * NOTE: we shall force our way through. Because the only
1240 	 * ill effect we shall see is that we may not be able
1241 	 * to read ACK from the mouse, and it doesn't matter much
1242 	 * so long as the mouse will accept the DISABLE command.
1243 	 */
1244     }
1245     splx(s);
1246 
1247     /* remove anything left in the output buffer */
1248     empty_aux_buffer(sc->kbdc, 10);
1249 
1250     /* disable the aux device, port and interrupt */
1251     if (sc->state & PSM_VALID) {
1252         if (!disable_aux_dev(sc->kbdc)) {
1253 	    /* MOUSE ERROR;
1254 	     * NOTE: we don't return error and continue, pretending
1255 	     * we have successfully disabled the device. It's OK because
1256 	     * the interrupt routine will discard any data from the mouse
1257 	     * hereafter.
1258 	     */
1259 	    log(LOG_ERR, "psm%d: failed to disable the device (psmclose).\n",
1260 	        PSM_UNIT(dev));
1261         }
1262 
1263         if (get_mouse_status(sc->kbdc, stat, 0, 3) < 3)
1264             log(LOG_DEBUG, "psm%d: failed to get status (psmclose).\n",
1265 	        PSM_UNIT(dev));
1266     }
1267 
1268     if (!set_controller_command_byte(sc->kbdc,
1269 	    kbdc_get_device_mask(sc->kbdc),
1270 	    (command_byte & KBD_KBD_CONTROL_BITS)
1271 	        | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
1272 	/* CONTROLLER ERROR;
1273 	 * we shall ignore this error; see the above comment.
1274 	 */
1275 	log(LOG_ERR, "psm%d: failed to disable the aux port (psmclose).\n",
1276 	    PSM_UNIT(dev));
1277     }
1278 
1279     /* remove anything left in the output buffer */
1280     empty_aux_buffer(sc->kbdc, 10);
1281 
1282     /* close is almost always successful */
1283     sc->state &= ~PSM_OPEN;
1284     kbdc_lock(sc->kbdc, FALSE);
1285     device_unbusy(devclass_get_device(psm_devclass, unit));
1286     return (0);
1287 }
1288 
1289 static int
1290 tame_mouse(struct psm_softc *sc, mousestatus_t *status, unsigned char *buf)
1291 {
1292     static unsigned char butmapps2[8] = {
1293         0,
1294         MOUSE_PS2_BUTTON1DOWN,
1295         MOUSE_PS2_BUTTON2DOWN,
1296         MOUSE_PS2_BUTTON1DOWN | MOUSE_PS2_BUTTON2DOWN,
1297         MOUSE_PS2_BUTTON3DOWN,
1298         MOUSE_PS2_BUTTON1DOWN | MOUSE_PS2_BUTTON3DOWN,
1299         MOUSE_PS2_BUTTON2DOWN | MOUSE_PS2_BUTTON3DOWN,
1300         MOUSE_PS2_BUTTON1DOWN | MOUSE_PS2_BUTTON2DOWN | MOUSE_PS2_BUTTON3DOWN,
1301     };
1302     static unsigned char butmapmsc[8] = {
1303         MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP,
1304         MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP,
1305         MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP,
1306         MOUSE_MSC_BUTTON3UP,
1307         MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP,
1308         MOUSE_MSC_BUTTON2UP,
1309         MOUSE_MSC_BUTTON1UP,
1310         0,
1311     };
1312     int mapped;
1313     int i;
1314 
1315     if (sc->mode.level == PSM_LEVEL_BASE) {
1316         mapped = status->button & ~MOUSE_BUTTON4DOWN;
1317         if (status->button & MOUSE_BUTTON4DOWN)
1318 	    mapped |= MOUSE_BUTTON1DOWN;
1319         status->button = mapped;
1320         buf[0] = MOUSE_PS2_SYNC | butmapps2[mapped & MOUSE_STDBUTTONS];
1321         i = max(min(status->dx, 255), -256);
1322 	if (i < 0)
1323 	    buf[0] |= MOUSE_PS2_XNEG;
1324         buf[1] = i;
1325         i = max(min(status->dy, 255), -256);
1326 	if (i < 0)
1327 	    buf[0] |= MOUSE_PS2_YNEG;
1328         buf[2] = i;
1329 	return MOUSE_PS2_PACKETSIZE;
1330     } else if (sc->mode.level == PSM_LEVEL_STANDARD) {
1331         buf[0] = MOUSE_MSC_SYNC | butmapmsc[status->button & MOUSE_STDBUTTONS];
1332         i = max(min(status->dx, 255), -256);
1333         buf[1] = i >> 1;
1334         buf[3] = i - buf[1];
1335         i = max(min(status->dy, 255), -256);
1336         buf[2] = i >> 1;
1337         buf[4] = i - buf[2];
1338         i = max(min(status->dz, 127), -128);
1339         buf[5] = (i >> 1) & 0x7f;
1340         buf[6] = (i - (i >> 1)) & 0x7f;
1341         buf[7] = (~status->button >> 3) & 0x7f;
1342 	return MOUSE_SYS_PACKETSIZE;
1343     }
1344     return sc->inputbytes;;
1345 }
1346 
1347 static int
1348 psmread(dev_t dev, struct uio *uio, int flag)
1349 {
1350     register struct psm_softc *sc = PSM_SOFTC(PSM_UNIT(dev));
1351     unsigned char buf[PSM_SMALLBUFSIZE];
1352     int error = 0;
1353     int s;
1354     int l;
1355 
1356     if ((sc->state & PSM_VALID) == 0)
1357 	return EIO;
1358 
1359     /* block until mouse activity occured */
1360     s = spltty();
1361     while (sc->queue.count <= 0) {
1362         if (PSM_NBLOCKIO(dev)) {
1363             splx(s);
1364             return EWOULDBLOCK;
1365         }
1366         sc->state |= PSM_ASLP;
1367         error = tsleep((caddr_t) sc, PZERO | PCATCH, "psmrea", 0);
1368         sc->state &= ~PSM_ASLP;
1369         if (error) {
1370             splx(s);
1371             return error;
1372         } else if ((sc->state & PSM_VALID) == 0) {
1373             /* the device disappeared! */
1374             splx(s);
1375             return EIO;
1376 	}
1377     }
1378     splx(s);
1379 
1380     /* copy data to the user land */
1381     while ((sc->queue.count > 0) && (uio->uio_resid > 0)) {
1382         s = spltty();
1383 	l = min(sc->queue.count, uio->uio_resid);
1384 	if (l > sizeof(buf))
1385 	    l = sizeof(buf);
1386 	if (l > sizeof(sc->queue.buf) - sc->queue.head) {
1387 	    bcopy(&sc->queue.buf[sc->queue.head], &buf[0],
1388 		sizeof(sc->queue.buf) - sc->queue.head);
1389 	    bcopy(&sc->queue.buf[0],
1390 		&buf[sizeof(sc->queue.buf) - sc->queue.head],
1391 		l - (sizeof(sc->queue.buf) - sc->queue.head));
1392 	} else {
1393 	    bcopy(&sc->queue.buf[sc->queue.head], &buf[0], l);
1394 	}
1395 	sc->queue.count -= l;
1396 	sc->queue.head = (sc->queue.head + l) % sizeof(sc->queue.buf);
1397         splx(s);
1398         error = uiomove(buf, l, uio);
1399         if (error)
1400 	    break;
1401     }
1402 
1403     return error;
1404 }
1405 
1406 static int
1407 block_mouse_data(struct psm_softc *sc, int *c)
1408 {
1409     int s;
1410 
1411     if (!kbdc_lock(sc->kbdc, TRUE))
1412 	return EIO;
1413 
1414     s = spltty();
1415     *c = get_controller_command_byte(sc->kbdc);
1416     if ((*c == -1)
1417 	|| !set_controller_command_byte(sc->kbdc,
1418 	    kbdc_get_device_mask(sc->kbdc),
1419             KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT
1420                 | KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
1421         /* this is CONTROLLER ERROR */
1422 	splx(s);
1423         kbdc_lock(sc->kbdc, FALSE);
1424 	return EIO;
1425     }
1426 
1427     /*
1428      * The device may be in the middle of status data transmission.
1429      * The transmission will be interrupted, thus, incomplete status
1430      * data must be discarded. Although the aux interrupt is disabled
1431      * at the keyboard controller level, at most one aux interrupt
1432      * may have already been pending and a data byte is in the
1433      * output buffer; throw it away. Note that the second argument
1434      * to `empty_aux_buffer()' is zero, so that the call will just
1435      * flush the internal queue.
1436      * `psmintr()' will be invoked after `splx()' if an interrupt is
1437      * pending; it will see no data and returns immediately.
1438      */
1439     empty_aux_buffer(sc->kbdc, 0);	/* flush the queue */
1440     read_aux_data_no_wait(sc->kbdc);	/* throw away data if any */
1441     sc->inputbytes = 0;
1442     splx(s);
1443 
1444     return 0;
1445 }
1446 
1447 static int
1448 unblock_mouse_data(struct psm_softc *sc, int c)
1449 {
1450     int error = 0;
1451 
1452     /*
1453      * We may have seen a part of status data during `set_mouse_XXX()'.
1454      * they have been queued; flush it.
1455      */
1456     empty_aux_buffer(sc->kbdc, 0);
1457 
1458     /* restore ports and interrupt */
1459     if (!set_controller_command_byte(sc->kbdc,
1460             kbdc_get_device_mask(sc->kbdc),
1461 	    c & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS))) {
1462         /* CONTROLLER ERROR; this is serious, we may have
1463          * been left with the inaccessible keyboard and
1464          * the disabled mouse interrupt.
1465          */
1466         error = EIO;
1467     }
1468 
1469     kbdc_lock(sc->kbdc, FALSE);
1470     return error;
1471 }
1472 
1473 static int
1474 psmioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
1475 {
1476     struct psm_softc *sc = PSM_SOFTC(PSM_UNIT(dev));
1477     mousemode_t mode;
1478     mousestatus_t status;
1479 #if (defined(MOUSE_GETVARS))
1480     mousevar_t *var;
1481 #endif
1482     mousedata_t *data;
1483     int stat[3];
1484     int command_byte;
1485     int error = 0;
1486     int s;
1487 
1488     /* Perform IOCTL command */
1489     switch (cmd) {
1490 
1491     case OLD_MOUSE_GETHWINFO:
1492 	s = spltty();
1493         ((old_mousehw_t *)addr)->buttons = sc->hw.buttons;
1494         ((old_mousehw_t *)addr)->iftype = sc->hw.iftype;
1495         ((old_mousehw_t *)addr)->type = sc->hw.type;
1496         ((old_mousehw_t *)addr)->hwid = sc->hw.hwid & 0x00ff;
1497 	splx(s);
1498         break;
1499 
1500     case MOUSE_GETHWINFO:
1501 	s = spltty();
1502         *(mousehw_t *)addr = sc->hw;
1503 	if (sc->mode.level == PSM_LEVEL_BASE)
1504 	    ((mousehw_t *)addr)->model = MOUSE_MODEL_GENERIC;
1505 	splx(s);
1506         break;
1507 
1508     case OLD_MOUSE_GETMODE:
1509 	s = spltty();
1510 	switch (sc->mode.level) {
1511 	case PSM_LEVEL_BASE:
1512 	    ((old_mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2;
1513 	    break;
1514 	case PSM_LEVEL_STANDARD:
1515 	    ((old_mousemode_t *)addr)->protocol = MOUSE_PROTO_SYSMOUSE;
1516 	    break;
1517 	case PSM_LEVEL_NATIVE:
1518 	    ((old_mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2;
1519 	    break;
1520 	}
1521         ((old_mousemode_t *)addr)->rate = sc->mode.rate;
1522         ((old_mousemode_t *)addr)->resolution = sc->mode.resolution;
1523         ((old_mousemode_t *)addr)->accelfactor = sc->mode.accelfactor;
1524 	splx(s);
1525         break;
1526 
1527     case MOUSE_GETMODE:
1528 	s = spltty();
1529         *(mousemode_t *)addr = sc->mode;
1530         ((mousemode_t *)addr)->resolution =
1531 	    MOUSE_RES_LOW - sc->mode.resolution;
1532 	switch (sc->mode.level) {
1533 	case PSM_LEVEL_BASE:
1534 	    ((mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2;
1535 	    ((mousemode_t *)addr)->packetsize = MOUSE_PS2_PACKETSIZE;
1536 	    break;
1537 	case PSM_LEVEL_STANDARD:
1538 	    ((mousemode_t *)addr)->protocol = MOUSE_PROTO_SYSMOUSE;
1539 	    ((mousemode_t *)addr)->packetsize = MOUSE_SYS_PACKETSIZE;
1540 	    ((mousemode_t *)addr)->syncmask[0] = MOUSE_SYS_SYNCMASK;
1541 	    ((mousemode_t *)addr)->syncmask[1] = MOUSE_SYS_SYNC;
1542 	    break;
1543 	case PSM_LEVEL_NATIVE:
1544 	    /* FIXME: this isn't quite correct... XXX */
1545 	    ((mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2;
1546 	    break;
1547 	}
1548 	splx(s);
1549         break;
1550 
1551     case OLD_MOUSE_SETMODE:
1552     case MOUSE_SETMODE:
1553 	if (cmd == OLD_MOUSE_SETMODE) {
1554 	    mode.rate = ((old_mousemode_t *)addr)->rate;
1555 	    /*
1556 	     * resolution  old I/F   new I/F
1557 	     * default        0         0
1558 	     * low            1        -2
1559 	     * medium low     2        -3
1560 	     * medium high    3        -4
1561 	     * high           4        -5
1562 	     */
1563 	    if (((old_mousemode_t *)addr)->resolution > 0)
1564 	        mode.resolution = -((old_mousemode_t *)addr)->resolution - 1;
1565 	    mode.accelfactor = ((old_mousemode_t *)addr)->accelfactor;
1566 	    mode.level = -1;
1567 	} else {
1568 	    mode = *(mousemode_t *)addr;
1569 	}
1570 
1571 	/* adjust and validate parameters. */
1572 	if (mode.rate > UCHAR_MAX)
1573 	    return EINVAL;
1574         if (mode.rate == 0)
1575             mode.rate = sc->dflt_mode.rate;
1576 	else if (mode.rate == -1)
1577 	    /* don't change the current setting */
1578 	    ;
1579 	else if (mode.rate < 0)
1580 	    return EINVAL;
1581 	if (mode.resolution >= UCHAR_MAX)
1582 	    return EINVAL;
1583 	if (mode.resolution >= 200)
1584 	    mode.resolution = MOUSE_RES_HIGH;
1585 	else if (mode.resolution >= 100)
1586 	    mode.resolution = MOUSE_RES_MEDIUMHIGH;
1587 	else if (mode.resolution >= 50)
1588 	    mode.resolution = MOUSE_RES_MEDIUMLOW;
1589 	else if (mode.resolution > 0)
1590 	    mode.resolution = MOUSE_RES_LOW;
1591         if (mode.resolution == MOUSE_RES_DEFAULT)
1592             mode.resolution = sc->dflt_mode.resolution;
1593         else if (mode.resolution == -1)
1594 	    /* don't change the current setting */
1595 	    ;
1596         else if (mode.resolution < 0) /* MOUSE_RES_LOW/MEDIUM/HIGH */
1597             mode.resolution = MOUSE_RES_LOW - mode.resolution;
1598 	if (mode.level == -1)
1599 	    /* don't change the current setting */
1600 	    mode.level = sc->mode.level;
1601 	else if ((mode.level < PSM_LEVEL_MIN) || (mode.level > PSM_LEVEL_MAX))
1602 	    return EINVAL;
1603         if (mode.accelfactor == -1)
1604 	    /* don't change the current setting */
1605 	    mode.accelfactor = sc->mode.accelfactor;
1606         else if (mode.accelfactor < 0)
1607 	    return EINVAL;
1608 
1609 	/* don't allow anybody to poll the keyboard controller */
1610 	error = block_mouse_data(sc, &command_byte);
1611 	if (error)
1612             return error;
1613 
1614         /* set mouse parameters */
1615 	if (mode.rate > 0)
1616 	    mode.rate = set_mouse_sampling_rate(sc->kbdc, mode.rate);
1617 	if (mode.resolution >= 0)
1618 	    mode.resolution = set_mouse_resolution(sc->kbdc, mode.resolution);
1619 	set_mouse_scaling(sc->kbdc, 1);
1620 	get_mouse_status(sc->kbdc, stat, 0, 3);
1621 
1622         s = spltty();
1623     	sc->mode.rate = mode.rate;
1624     	sc->mode.resolution = mode.resolution;
1625     	sc->mode.accelfactor = mode.accelfactor;
1626     	sc->mode.level = mode.level;
1627         splx(s);
1628 
1629 	unblock_mouse_data(sc, command_byte);
1630         break;
1631 
1632     case MOUSE_GETLEVEL:
1633 	*(int *)addr = sc->mode.level;
1634         break;
1635 
1636     case MOUSE_SETLEVEL:
1637 	if ((*(int *)addr < PSM_LEVEL_MIN) || (*(int *)addr > PSM_LEVEL_MAX))
1638 	    return EINVAL;
1639 	sc->mode.level = *(int *)addr;
1640         break;
1641 
1642     case MOUSE_GETSTATUS:
1643         s = spltty();
1644 	status = sc->status;
1645 	sc->status.flags = 0;
1646 	sc->status.obutton = sc->status.button;
1647 	sc->status.button = 0;
1648 	sc->status.dx = 0;
1649 	sc->status.dy = 0;
1650 	sc->status.dz = 0;
1651         splx(s);
1652         *(mousestatus_t *)addr = status;
1653         break;
1654 
1655 #if (defined(MOUSE_GETVARS))
1656     case MOUSE_GETVARS:
1657 	var = (mousevar_t *)addr;
1658 	bzero(var, sizeof(*var));
1659 	s = spltty();
1660         var->var[0] = MOUSE_VARS_PS2_SIG;
1661         var->var[1] = sc->config;
1662         var->var[2] = sc->flags;
1663 	splx(s);
1664         break;
1665 
1666     case MOUSE_SETVARS:
1667 	return ENODEV;
1668 #endif /* MOUSE_GETVARS */
1669 
1670     case MOUSE_READSTATE:
1671     case MOUSE_READDATA:
1672 	data = (mousedata_t *)addr;
1673 	if (data->len > sizeof(data->buf)/sizeof(data->buf[0]))
1674 	    return EINVAL;
1675 
1676 	error = block_mouse_data(sc, &command_byte);
1677 	if (error)
1678             return error;
1679         if ((data->len = get_mouse_status(sc->kbdc, data->buf,
1680 		(cmd == MOUSE_READDATA) ? 1 : 0, data->len)) <= 0)
1681             error = EIO;
1682 	unblock_mouse_data(sc, command_byte);
1683 	break;
1684 
1685 #if (defined(MOUSE_SETRESOLUTION))
1686     case MOUSE_SETRESOLUTION:
1687 	mode.resolution = *(int *)addr;
1688 	if (mode.resolution >= UCHAR_MAX)
1689 	    return EINVAL;
1690 	else if (mode.resolution >= 200)
1691 	    mode.resolution = MOUSE_RES_HIGH;
1692 	else if (mode.resolution >= 100)
1693 	    mode.resolution = MOUSE_RES_MEDIUMHIGH;
1694 	else if (mode.resolution >= 50)
1695 	    mode.resolution = MOUSE_RES_MEDIUMLOW;
1696 	else if (mode.resolution > 0)
1697 	    mode.resolution = MOUSE_RES_LOW;
1698         if (mode.resolution == MOUSE_RES_DEFAULT)
1699             mode.resolution = sc->dflt_mode.resolution;
1700         else if (mode.resolution == -1)
1701 	    mode.resolution = sc->mode.resolution;
1702         else if (mode.resolution < 0) /* MOUSE_RES_LOW/MEDIUM/HIGH */
1703             mode.resolution = MOUSE_RES_LOW - mode.resolution;
1704 
1705 	error = block_mouse_data(sc, &command_byte);
1706 	if (error)
1707             return error;
1708         sc->mode.resolution = set_mouse_resolution(sc->kbdc, mode.resolution);
1709 	if (sc->mode.resolution != mode.resolution)
1710 	    error = EIO;
1711 	unblock_mouse_data(sc, command_byte);
1712         break;
1713 #endif /* MOUSE_SETRESOLUTION */
1714 
1715 #if (defined(MOUSE_SETRATE))
1716     case MOUSE_SETRATE:
1717 	mode.rate = *(int *)addr;
1718 	if (mode.rate > UCHAR_MAX)
1719 	    return EINVAL;
1720         if (mode.rate == 0)
1721             mode.rate = sc->dflt_mode.rate;
1722 	else if (mode.rate < 0)
1723 	    mode.rate = sc->mode.rate;
1724 
1725 	error = block_mouse_data(sc, &command_byte);
1726 	if (error)
1727             return error;
1728         sc->mode.rate = set_mouse_sampling_rate(sc->kbdc, mode.rate);
1729 	if (sc->mode.rate != mode.rate)
1730 	    error = EIO;
1731 	unblock_mouse_data(sc, command_byte);
1732         break;
1733 #endif /* MOUSE_SETRATE */
1734 
1735 #if (defined(MOUSE_SETSCALING))
1736     case MOUSE_SETSCALING:
1737 	if ((*(int *)addr <= 0) || (*(int *)addr > 2))
1738 	    return EINVAL;
1739 
1740 	error = block_mouse_data(sc, &command_byte);
1741 	if (error)
1742             return error;
1743         if (!set_mouse_scaling(sc->kbdc, *(int *)addr))
1744 	    error = EIO;
1745 	unblock_mouse_data(sc, command_byte);
1746         break;
1747 #endif /* MOUSE_SETSCALING */
1748 
1749 #if (defined(MOUSE_GETHWID))
1750     case MOUSE_GETHWID:
1751 	error = block_mouse_data(sc, &command_byte);
1752 	if (error)
1753             return error;
1754         sc->hw.hwid &= ~0x00ff;
1755         sc->hw.hwid |= get_aux_id(sc->kbdc);
1756 	*(int *)addr = sc->hw.hwid & 0x00ff;
1757 	unblock_mouse_data(sc, command_byte);
1758         break;
1759 #endif /* MOUSE_GETHWID */
1760 
1761     default:
1762 	return ENOTTY;
1763     }
1764 
1765     return error;
1766 }
1767 
1768 static void
1769 psmintr(void *arg)
1770 {
1771     /*
1772      * the table to turn PS/2 mouse button bits (MOUSE_PS2_BUTTON?DOWN)
1773      * into `mousestatus' button bits (MOUSE_BUTTON?DOWN).
1774      */
1775     static int butmap[8] = {
1776         0,
1777 	MOUSE_BUTTON1DOWN,
1778 	MOUSE_BUTTON3DOWN,
1779 	MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN,
1780 	MOUSE_BUTTON2DOWN,
1781 	MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN,
1782 	MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN,
1783         MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN
1784     };
1785     static int butmap_versapad[8] = {
1786 	0,
1787 	MOUSE_BUTTON3DOWN,
1788 	0,
1789 	MOUSE_BUTTON3DOWN,
1790 	MOUSE_BUTTON1DOWN,
1791 	MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN,
1792 	MOUSE_BUTTON1DOWN,
1793 	MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN
1794     };
1795     register struct psm_softc *sc = arg;
1796     mousestatus_t ms;
1797     int x, y, z;
1798     int c;
1799     int l;
1800     int x0, y0;
1801 
1802     /* read until there is nothing to read */
1803     while((c = read_aux_data_no_wait(sc->kbdc)) != -1) {
1804 
1805         /* discard the byte if the device is not open */
1806         if ((sc->state & PSM_OPEN) == 0)
1807             continue;
1808 
1809         /*
1810 	 * Check sync bits. We check for overflow bits and the bit 3
1811 	 * for most mice. True, the code doesn't work if overflow
1812 	 * condition occurs. But we expect it rarely happens...
1813 	 */
1814 	if ((sc->inputbytes == 0)
1815 		&& ((c & sc->mode.syncmask[0]) != sc->mode.syncmask[1])) {
1816             log(LOG_DEBUG, "psmintr: out of sync (%04x != %04x).\n",
1817 		c & sc->mode.syncmask[0], sc->mode.syncmask[1]);
1818             continue;
1819 	}
1820 
1821         sc->ipacket[sc->inputbytes++] = c;
1822         if (sc->inputbytes < sc->mode.packetsize)
1823 	    continue;
1824 
1825 #if 0
1826         log(LOG_DEBUG, "psmintr: %02x %02x %02x %02x %02x %02x\n",
1827 	    sc->ipacket[0], sc->ipacket[1], sc->ipacket[2],
1828 	    sc->ipacket[3], sc->ipacket[4], sc->ipacket[5]);
1829 #endif
1830 
1831 	c = sc->ipacket[0];
1832 
1833 	/*
1834 	 * A kludge for Kensington device!
1835 	 * The MSB of the horizontal count appears to be stored in
1836 	 * a strange place. This kludge doesn't affect other mice
1837 	 * because the bit is the overflow bit which is, in most cases,
1838 	 * expected to be zero when we reach here. XXX
1839 	 */
1840 	if (sc->hw.model != MOUSE_MODEL_VERSAPAD)
1841 	    sc->ipacket[1] |= (c & MOUSE_PS2_XOVERFLOW) ? 0x80 : 0;
1842 
1843         /* ignore the overflow bits... */
1844         x = (c & MOUSE_PS2_XNEG) ?  sc->ipacket[1] - 256 : sc->ipacket[1];
1845         y = (c & MOUSE_PS2_YNEG) ?  sc->ipacket[2] - 256 : sc->ipacket[2];
1846 	z = 0;
1847         ms.obutton = sc->button;		  /* previous button state */
1848         ms.button = butmap[c & MOUSE_PS2_BUTTONS];
1849 	/* `tapping' action */
1850 	if (sc->config & PSM_CONFIG_FORCETAP)
1851 	    ms.button |= ((c & MOUSE_PS2_TAP)) ? 0 : MOUSE_BUTTON4DOWN;
1852 
1853 	switch (sc->hw.model) {
1854 
1855 	case MOUSE_MODEL_INTELLI:
1856 	case MOUSE_MODEL_NET:
1857 	    /* wheel data is in the fourth byte */
1858 	    z = (char)sc->ipacket[3];
1859 	    break;
1860 
1861 	case MOUSE_MODEL_MOUSEMANPLUS:
1862 	    /*
1863 	     * PS2++ protocl packet
1864 	     *
1865 	     *          b7 b6 b5 b4 b3 b2 b1 b0
1866 	     * byte 1:  *  1  p3 p2 1  *  *  *
1867 	     * byte 2:  c1 c2 p1 p0 d1 d0 1  0
1868 	     *
1869 	     * p3-p0: packet type
1870 	     * c1, c2: c1 & c2 == 1, if p2 == 0
1871 	     *         c1 & c2 == 0, if p2 == 1
1872 	     *
1873 	     * packet type: 0 (device type)
1874 	     * See comments in enable_mmanplus() below.
1875 	     *
1876 	     * packet type: 1 (wheel data)
1877 	     *
1878 	     *          b7 b6 b5 b4 b3 b2 b1 b0
1879 	     * byte 3:  h  *  B5 B4 s  d2 d1 d0
1880 	     *
1881 	     * h: 1, if horizontal roller data
1882 	     *    0, if vertical roller data
1883 	     * B4, B5: button 4 and 5
1884 	     * s: sign bit
1885 	     * d2-d0: roller data
1886 	     *
1887 	     * packet type: 2 (reserved)
1888 	     */
1889 	    if (((c & MOUSE_PS2PLUS_SYNCMASK) == MOUSE_PS2PLUS_SYNC)
1890 		    && (abs(x) > 191)
1891 		    && MOUSE_PS2PLUS_CHECKBITS(sc->ipacket)) {
1892 		/* the extended data packet encodes button and wheel events */
1893 		switch (MOUSE_PS2PLUS_PACKET_TYPE(sc->ipacket)) {
1894 		case 1:
1895 		    /* wheel data packet */
1896 		    x = y = 0;
1897 		    if (sc->ipacket[2] & 0x80) {
1898 			/* horizontal roller count - ignore it XXX*/
1899 		    } else {
1900 			/* vertical roller count */
1901 			z = (sc->ipacket[2] & MOUSE_PS2PLUS_ZNEG)
1902 			    ? (sc->ipacket[2] & 0x0f) - 16
1903 			    : (sc->ipacket[2] & 0x0f);
1904 		    }
1905 		    ms.button |= (sc->ipacket[2] & MOUSE_PS2PLUS_BUTTON4DOWN)
1906 			? MOUSE_BUTTON4DOWN : 0;
1907 		    ms.button |= (sc->ipacket[2] & MOUSE_PS2PLUS_BUTTON5DOWN)
1908 			? MOUSE_BUTTON5DOWN : 0;
1909 		    break;
1910 		case 2:
1911 		    /* this packet type is reserved, and currently ignored */
1912 		    /* FALL THROUGH */
1913 		case 0:
1914 		    /* device type packet - shouldn't happen */
1915 		    /* FALL THROUGH */
1916 		default:
1917 		    x = y = 0;
1918 		    ms.button = ms.obutton;
1919             	    log(LOG_DEBUG, "psmintr: unknown PS2++ packet type %d: "
1920 				   "0x%02x 0x%02x 0x%02x\n",
1921 			MOUSE_PS2PLUS_PACKET_TYPE(sc->ipacket),
1922 			sc->ipacket[0], sc->ipacket[1], sc->ipacket[2]);
1923 		    break;
1924 		}
1925 	    } else {
1926 		/* preserve button states */
1927 		ms.button |= ms.obutton & MOUSE_EXTBUTTONS;
1928 	    }
1929 	    break;
1930 
1931 	case MOUSE_MODEL_GLIDEPOINT:
1932 	    /* `tapping' action */
1933 	    ms.button |= ((c & MOUSE_PS2_TAP)) ? 0 : MOUSE_BUTTON4DOWN;
1934 	    break;
1935 
1936 	case MOUSE_MODEL_NETSCROLL:
1937 	    /* three addtional bytes encode button and wheel events */
1938 	    ms.button |= (sc->ipacket[3] & MOUSE_PS2_BUTTON3DOWN)
1939 		? MOUSE_BUTTON4DOWN : 0;
1940 	    z = (sc->ipacket[3] & MOUSE_PS2_XNEG)
1941 		? sc->ipacket[4] - 256 : sc->ipacket[4];
1942 	    break;
1943 
1944 	case MOUSE_MODEL_THINK:
1945 	    /* the fourth button state in the first byte */
1946 	    ms.button |= (c & MOUSE_PS2_TAP) ? MOUSE_BUTTON4DOWN : 0;
1947 	    break;
1948 
1949 	case MOUSE_MODEL_VERSAPAD:
1950 	    /* VersaPad PS/2 absolute mode message format
1951 	     *
1952 	     * [packet1]     7   6   5   4   3   2   1   0(LSB)
1953 	     *  ipacket[0]:  1   1   0   A   1   L   T   R
1954 	     *  ipacket[1]: H7  H6  H5  H4  H3  H2  H1  H0
1955 	     *  ipacket[2]: V7  V6  V5  V4  V3  V2  V1  V0
1956 	     *  ipacket[3]:  1   1   1   A   1   L   T   R
1957 	     *  ipacket[4]:V11 V10  V9  V8 H11 H10  H9  H8
1958 	     *  ipacket[5]:  0  P6  P5  P4  P3  P2  P1  P0
1959 	     *
1960 	     * [note]
1961 	     *  R: right physical mouse button (1=on)
1962 	     *  T: touch pad virtual button (1=tapping)
1963 	     *  L: left physical mouse button (1=on)
1964 	     *  A: position data is valid (1=valid)
1965 	     *  H: horizontal data (12bit signed integer. H11 is sign bit.)
1966 	     *  V: vertical data (12bit signed integer. V11 is sign bit.)
1967 	     *  P: pressure data
1968 	     *
1969 	     * Tapping is mapped to MOUSE_BUTTON4.
1970 	     */
1971 	    ms.button = butmap_versapad[c & MOUSE_PS2VERSA_BUTTONS];
1972 	    ms.button |= (c & MOUSE_PS2VERSA_TAP) ? MOUSE_BUTTON4DOWN : 0;
1973 	    x = y = 0;
1974 	    if (c & MOUSE_PS2VERSA_IN_USE) {
1975 		x0 = sc->ipacket[1] | (((sc->ipacket[4]) & 0x0f) << 8);
1976 		y0 = sc->ipacket[2] | (((sc->ipacket[4]) & 0xf0) << 4);
1977 		if (x0 & 0x800)
1978 		    x0 -= 0x1000;
1979 		if (y0 & 0x800)
1980 		    y0 -= 0x1000;
1981 		if (sc->flags & PSM_FLAGS_FINGERDOWN) {
1982 		    x = sc->xold - x0;
1983 		    y = y0 - sc->yold;
1984 		    if (x < 0)	/* XXX */
1985 			x++;
1986 		    else if (x)
1987 			x--;
1988 		    if (y < 0)
1989 			y++;
1990 		    else if (y)
1991 			y--;
1992 		} else {
1993 		    sc->flags |= PSM_FLAGS_FINGERDOWN;
1994 		}
1995 		sc->xold = x0;
1996 		sc->yold = y0;
1997 	    } else {
1998 		sc->flags &= ~PSM_FLAGS_FINGERDOWN;
1999 	    }
2000 	    c = ((x < 0) ? MOUSE_PS2_XNEG : 0)
2001 		| ((y < 0) ? MOUSE_PS2_YNEG : 0);
2002 	    break;
2003 
2004 	case MOUSE_MODEL_GENERIC:
2005 	default:
2006 	    break;
2007 	}
2008 
2009         /* scale values */
2010         if (sc->mode.accelfactor >= 1) {
2011             if (x != 0) {
2012                 x = x * x / sc->mode.accelfactor;
2013                 if (x == 0)
2014                     x = 1;
2015                 if (c & MOUSE_PS2_XNEG)
2016                     x = -x;
2017             }
2018             if (y != 0) {
2019                 y = y * y / sc->mode.accelfactor;
2020                 if (y == 0)
2021                     y = 1;
2022                 if (c & MOUSE_PS2_YNEG)
2023                     y = -y;
2024             }
2025         }
2026 
2027         ms.dx = x;
2028         ms.dy = y;
2029         ms.dz = z;
2030         ms.flags = ((x || y || z) ? MOUSE_POSCHANGED : 0)
2031 	    | (ms.obutton ^ ms.button);
2032 
2033 	if (sc->mode.level < PSM_LEVEL_NATIVE)
2034 	    sc->inputbytes = tame_mouse(sc, &ms, sc->ipacket);
2035 
2036         sc->status.flags |= ms.flags;
2037         sc->status.dx += ms.dx;
2038         sc->status.dy += ms.dy;
2039         sc->status.dz += ms.dz;
2040         sc->status.button = ms.button;
2041         sc->button = ms.button;
2042 
2043         /* queue data */
2044         if (sc->queue.count + sc->inputbytes < sizeof(sc->queue.buf)) {
2045 	    l = min(sc->inputbytes, sizeof(sc->queue.buf) - sc->queue.tail);
2046 	    bcopy(&sc->ipacket[0], &sc->queue.buf[sc->queue.tail], l);
2047 	    if (sc->inputbytes > l)
2048 	        bcopy(&sc->ipacket[l], &sc->queue.buf[0], sc->inputbytes - l);
2049             sc->queue.tail =
2050 		(sc->queue.tail + sc->inputbytes) % sizeof(sc->queue.buf);
2051             sc->queue.count += sc->inputbytes;
2052 	}
2053         sc->inputbytes = 0;
2054 
2055         if (sc->state & PSM_ASLP) {
2056             sc->state &= ~PSM_ASLP;
2057             wakeup((caddr_t) sc);
2058     	}
2059         selwakeup(&sc->rsel);
2060     }
2061 }
2062 
2063 static int
2064 psmpoll(dev_t dev, int events, struct proc *p)
2065 {
2066     struct psm_softc *sc = PSM_SOFTC(PSM_UNIT(dev));
2067     int s;
2068     int revents = 0;
2069 
2070     /* Return true if a mouse event available */
2071     s = spltty();
2072     if (events & (POLLIN | POLLRDNORM)) {
2073 	if (sc->queue.count > 0)
2074 	    revents |= events & (POLLIN | POLLRDNORM);
2075 	else
2076 	    selrecord(p, &sc->rsel);
2077     }
2078     splx(s);
2079 
2080     return (revents);
2081 }
2082 
2083 /* vendor/model specific routines */
2084 
2085 static int mouse_id_proc1(KBDC kbdc, int res, int scale, int *status)
2086 {
2087     if (set_mouse_resolution(kbdc, res) != res)
2088         return FALSE;
2089     if (set_mouse_scaling(kbdc, scale)
2090 	&& set_mouse_scaling(kbdc, scale)
2091 	&& set_mouse_scaling(kbdc, scale)
2092 	&& (get_mouse_status(kbdc, status, 0, 3) >= 3))
2093 	return TRUE;
2094     return FALSE;
2095 }
2096 
2097 #if notyet
2098 /* Logitech MouseMan Cordless II */
2099 static int
2100 enable_lcordless(struct psm_softc *sc)
2101 {
2102     int status[3];
2103     int ch;
2104 
2105     if (!mouse_id_proc1(sc->kbdc, PSMD_RES_HIGH, 2, status))
2106         return FALSE;
2107     if (status[1] == PSMD_RES_HIGH)
2108 	return FALSE;
2109     ch = (status[0] & 0x07) - 1;	/* channel # */
2110     if ((ch <= 0) || (ch > 4))
2111 	return FALSE;
2112     /*
2113      * status[1]: always one?
2114      * status[2]: battery status? (0-100)
2115      */
2116     return TRUE;
2117 }
2118 #endif /* notyet */
2119 
2120 /* Genius NetScroll Mouse */
2121 static int
2122 enable_groller(struct psm_softc *sc)
2123 {
2124     int status[3];
2125 
2126     /*
2127      * The special sequence to enable the fourth button and the
2128      * roller. Immediately after this sequence check status bytes.
2129      * if the mouse is NetScroll, the second and the third bytes are
2130      * '3' and 'D'.
2131      */
2132 
2133     /*
2134      * If the mouse is an ordinary PS/2 mouse, the status bytes should
2135      * look like the following.
2136      *
2137      * byte 1 bit 7 always 0
2138      *        bit 6 stream mode (0)
2139      *        bit 5 disabled (0)
2140      *        bit 4 1:1 scaling (0)
2141      *        bit 3 always 0
2142      *        bit 0-2 button status
2143      * byte 2 resolution (PSMD_RES_HIGH)
2144      * byte 3 report rate (?)
2145      */
2146 
2147     if (!mouse_id_proc1(sc->kbdc, PSMD_RES_HIGH, 1, status))
2148         return FALSE;
2149     if ((status[1] != '3') || (status[2] != 'D'))
2150         return FALSE;
2151     /* FIXME!! */
2152     sc->hw.buttons = get_mouse_buttons(sc->kbdc);
2153     sc->hw.buttons = 4;
2154     return TRUE;
2155 }
2156 
2157 /* Genius NetMouse/NetMouse Pro */
2158 static int
2159 enable_gmouse(struct psm_softc *sc)
2160 {
2161     int status[3];
2162 
2163     /*
2164      * The special sequence to enable the middle, "rubber" button.
2165      * Immediately after this sequence check status bytes.
2166      * if the mouse is NetMouse, NetMouse Pro, or ASCII MIE Mouse,
2167      * the second and the third bytes are '3' and 'U'.
2168      * NOTE: NetMouse reports that it has three buttons although it has
2169      * two buttons and a rubber button. NetMouse Pro and MIE Mouse
2170      * say they have three buttons too and they do have a button on the
2171      * side...
2172      */
2173     if (!mouse_id_proc1(sc->kbdc, PSMD_RES_HIGH, 1, status))
2174         return FALSE;
2175     if ((status[1] != '3') || (status[2] != 'U'))
2176         return FALSE;
2177     return TRUE;
2178 }
2179 
2180 /* ALPS GlidePoint */
2181 static int
2182 enable_aglide(struct psm_softc *sc)
2183 {
2184     int status[3];
2185 
2186     /*
2187      * The special sequence to obtain ALPS GlidePoint specific
2188      * information. Immediately after this sequence, status bytes will
2189      * contain something interesting.
2190      * NOTE: ALPS produces several models of GlidePoint. Some of those
2191      * do not respond to this sequence, thus, cannot be detected this way.
2192      */
2193     if (set_mouse_sampling_rate(sc->kbdc, 100) != 100)
2194 	return FALSE;
2195     if (!mouse_id_proc1(sc->kbdc, PSMD_RES_LOW, 2, status))
2196         return FALSE;
2197     if ((status[1] == PSMD_RES_LOW) || (status[2] == 100))
2198         return FALSE;
2199     return TRUE;
2200 }
2201 
2202 /* Kensington ThinkingMouse/Trackball */
2203 static int
2204 enable_kmouse(struct psm_softc *sc)
2205 {
2206     static unsigned char rate[] = { 20, 60, 40, 20, 20, 60, 40, 20, 20 };
2207     KBDC kbdc = sc->kbdc;
2208     int status[3];
2209     int id1;
2210     int id2;
2211     int i;
2212 
2213     id1 = get_aux_id(kbdc);
2214     if (set_mouse_sampling_rate(kbdc, 10) != 10)
2215 	return FALSE;
2216     /*
2217      * The device is now in the native mode? It returns a different
2218      * ID value...
2219      */
2220     id2 = get_aux_id(kbdc);
2221     if ((id1 == id2) || (id2 != 2))
2222 	return FALSE;
2223 
2224     if (set_mouse_resolution(kbdc, PSMD_RES_LOW) != PSMD_RES_LOW)
2225         return FALSE;
2226 #if PSM_DEBUG >= 2
2227     /* at this point, resolution is LOW, sampling rate is 10/sec */
2228     if (get_mouse_status(kbdc, status, 0, 3) < 3)
2229         return FALSE;
2230 #endif
2231 
2232     /*
2233      * The special sequence to enable the third and fourth buttons.
2234      * Otherwise they behave like the first and second buttons.
2235      */
2236     for (i = 0; i < sizeof(rate)/sizeof(rate[0]); ++i) {
2237         if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i])
2238 	    return FALSE;
2239     }
2240 
2241     /*
2242      * At this point, the device is using default resolution and
2243      * sampling rate for the native mode.
2244      */
2245     if (get_mouse_status(kbdc, status, 0, 3) < 3)
2246         return FALSE;
2247     if ((status[1] == PSMD_RES_LOW) || (status[2] == rate[i - 1]))
2248         return FALSE;
2249 
2250     /* the device appears be enabled by this sequence, diable it for now */
2251     disable_aux_dev(kbdc);
2252     empty_aux_buffer(kbdc, 5);
2253 
2254     return TRUE;
2255 }
2256 
2257 /* Logitech MouseMan+/FirstMouse+ */
2258 static int
2259 enable_mmanplus(struct psm_softc *sc)
2260 {
2261     static char res[] = {
2262 	-1, PSMD_RES_LOW, PSMD_RES_HIGH, PSMD_RES_MEDIUM_HIGH,
2263 	PSMD_RES_MEDIUM_LOW, -1, PSMD_RES_HIGH, PSMD_RES_MEDIUM_LOW,
2264 	PSMD_RES_MEDIUM_HIGH, PSMD_RES_HIGH,
2265     };
2266     KBDC kbdc = sc->kbdc;
2267     int data[3];
2268     int i;
2269 
2270     /* the special sequence to enable the fourth button and the roller. */
2271     for (i = 0; i < sizeof(res)/sizeof(res[0]); ++i) {
2272 	if (res[i] < 0) {
2273 	    if (!set_mouse_scaling(kbdc, 1))
2274 		return FALSE;
2275 	} else {
2276 	    if (set_mouse_resolution(kbdc, res[i]) != res[i])
2277 		return FALSE;
2278 	}
2279     }
2280 
2281     if (get_mouse_status(kbdc, data, 1, 3) < 3)
2282         return FALSE;
2283 
2284     /*
2285      * PS2++ protocl, packet type 0
2286      *
2287      *          b7 b6 b5 b4 b3 b2 b1 b0
2288      * byte 1:  *  1  p3 p2 1  *  *  *
2289      * byte 2:  1  1  p1 p0 m1 m0 1  0
2290      * byte 3:  m7 m6 m5 m4 m3 m2 m1 m0
2291      *
2292      * p3-p0: packet type: 0
2293      * m7-m0: model ID: MouseMan+:0x50, FirstMouse+:0x51,...
2294      */
2295     /* check constant bits */
2296     if ((data[0] & MOUSE_PS2PLUS_SYNCMASK) != MOUSE_PS2PLUS_SYNC)
2297         return FALSE;
2298     if ((data[1] & 0xc3) != 0xc2)
2299         return FALSE;
2300     /* check d3-d0 in byte 2 */
2301     if (!MOUSE_PS2PLUS_CHECKBITS(data))
2302         return FALSE;
2303     /* check p3-p0 */
2304     if (MOUSE_PS2PLUS_PACKET_TYPE(data) != 0)
2305         return FALSE;
2306 
2307     sc->hw.hwid &= 0x00ff;
2308     sc->hw.hwid |= data[2] << 8;	/* save model ID */
2309 
2310     /*
2311      * MouseMan+ (or FirstMouse+) is now in its native mode, in which
2312      * the wheel and the fourth button events are encoded in the
2313      * special data packet. The mouse may be put in the IntelliMouse mode
2314      * if it is initialized by the IntelliMouse's method.
2315      */
2316     return TRUE;
2317 }
2318 
2319 /* MS IntelliMouse */
2320 static int
2321 enable_msintelli(struct psm_softc *sc)
2322 {
2323     /*
2324      * Logitech MouseMan+ and FirstMouse+ will also respond to this
2325      * probe routine and act like IntelliMouse.
2326      */
2327 
2328     static unsigned char rate[] = { 200, 100, 80, };
2329     KBDC kbdc = sc->kbdc;
2330     int id;
2331     int i;
2332 
2333     /* the special sequence to enable the third button and the roller. */
2334     for (i = 0; i < sizeof(rate)/sizeof(rate[0]); ++i) {
2335         if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i])
2336 	    return FALSE;
2337     }
2338     /* the device will give the genuine ID only after the above sequence */
2339     id = get_aux_id(kbdc);
2340     if (id != PSM_INTELLI_ID)
2341 	return FALSE;
2342 
2343     sc->hw.hwid = id;
2344     sc->hw.buttons = 3;
2345 
2346     return TRUE;
2347 }
2348 
2349 /* Interlink electronics VersaPad */
2350 static int
2351 enable_versapad(struct psm_softc *sc)
2352 {
2353     KBDC kbdc = sc->kbdc;
2354     int data[3];
2355 
2356     set_mouse_resolution(kbdc, PSMD_RES_MEDIUM_HIGH); /* set res. 2 */
2357     set_mouse_sampling_rate(kbdc, 100);		/* set rate 100 */
2358     set_mouse_scaling(kbdc, 1);			/* set scale 1:1 */
2359     set_mouse_scaling(kbdc, 1);			/* set scale 1:1 */
2360     set_mouse_scaling(kbdc, 1);			/* set scale 1:1 */
2361     set_mouse_scaling(kbdc, 1);			/* set scale 1:1 */
2362     if (get_mouse_status(kbdc, data, 0, 3) < 3)	/* get status */
2363 	return FALSE;
2364     if (data[2] != 0xa || data[1] != 0 )	/* rate == 0xa && res. == 0 */
2365 	return FALSE;
2366     set_mouse_scaling(kbdc, 1);			/* set scale 1:1 */
2367 
2368     return TRUE;				/* PS/2 absolute mode */
2369 }
2370 
2371 #ifdef PSM_HOOKAPM
2372 static int
2373 psmresume(void *dummy)
2374 {
2375     struct psm_softc *sc = PSM_SOFTC((int)dummy);
2376     int unit = (int)dummy;
2377     int err = 0;
2378     int s;
2379     int c;
2380 
2381     if (verbose >= 2)
2382         log(LOG_NOTICE, "psm%d: APM resume hook called.\n", unit);
2383 
2384     /* don't let anybody mess with the aux device */
2385     if (!kbdc_lock(sc->kbdc, TRUE))
2386 	return (EIO);
2387     s = spltty();
2388 
2389     /* save the current controller command byte */
2390     empty_both_buffers(sc->kbdc, 10);
2391     c = get_controller_command_byte(sc->kbdc);
2392     if (verbose >= 2)
2393         log(LOG_DEBUG, "psm%d: current command byte: %04x (psmresume).\n",
2394 	    unit, c);
2395 
2396     /* enable the aux port but disable the aux interrupt and the keyboard */
2397     if ((c == -1) || !set_controller_command_byte(sc->kbdc,
2398 	    kbdc_get_device_mask(sc->kbdc),
2399   	    KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT
2400 	        | KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
2401         /* CONTROLLER ERROR */
2402 	splx(s);
2403         kbdc_lock(sc->kbdc, FALSE);
2404 	log(LOG_ERR, "psm%d: unable to set the command byte (psmresume).\n",
2405 	    unit);
2406 	return (EIO);
2407     }
2408 
2409     /* flush any data */
2410     if (sc->state & PSM_VALID) {
2411 	disable_aux_dev(sc->kbdc);	/* this may fail; but never mind... */
2412 	empty_aux_buffer(sc->kbdc, 10);
2413     }
2414     sc->inputbytes = 0;
2415 
2416 #ifdef PSM_RESETAFTERSUSPEND
2417     /* try to detect the aux device; are you still there? */
2418     if (reinitialize(unit, &sc->mode)) {
2419 	/* yes */
2420 	sc->state |= PSM_VALID;
2421     } else {
2422 	/* the device has gone! */
2423         restore_controller(sc->kbdc, c);
2424 	sc->state &= ~PSM_VALID;
2425 	log(LOG_ERR, "psm%d: the aux device has gone! (psmresume).\n",
2426 	    unit);
2427 	err = ENXIO;
2428     }
2429 #endif /* PSM_RESETAFTERSUSPEND */
2430     splx(s);
2431 
2432     /* restore the driver state */
2433     if ((sc->state & PSM_OPEN) && (err == 0)) {
2434         /* enable the aux device and the port again */
2435 	err = doopen(unit, c);
2436 	if (err != 0)
2437 	    log(LOG_ERR, "psm%d: failed to enable the device (psmresume).\n",
2438 		unit);
2439     } else {
2440         /* restore the keyboard port and disable the aux port */
2441         if (!set_controller_command_byte(sc->kbdc,
2442                 kbdc_get_device_mask(sc->kbdc),
2443                 (c & KBD_KBD_CONTROL_BITS)
2444                     | KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
2445             /* CONTROLLER ERROR */
2446             log(LOG_ERR, "psm%d: failed to disable the aux port (psmresume).\n",
2447                 unit);
2448             err = EIO;
2449 	}
2450     }
2451 
2452     /* done */
2453     kbdc_lock(sc->kbdc, FALSE);
2454     if ((sc->state & PSM_ASLP) && !(sc->state & PSM_VALID)) {
2455 	/*
2456 	 * Release the blocked process; it must be notified that the device
2457 	 * cannot be accessed anymore.
2458 	 */
2459         sc->state &= ~PSM_ASLP;
2460         wakeup((caddr_t)sc);
2461     }
2462 
2463     if (verbose >= 2)
2464         log(LOG_DEBUG, "psm%d: APM resume hook exiting.\n", unit);
2465 
2466     return (err);
2467 }
2468 #endif /* PSM_HOOKAPM */
2469 
2470 DRIVER_MODULE(psm, atkbdc, psm_driver, psm_devclass, 0, 0);
2471 
2472 #endif /* NPSM > 0 */
2473