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