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