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