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