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