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