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