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