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