The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/isa/psm.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 91294039e075bb44609c6f125833461b


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.