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