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