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/dev/atkbdc/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 /*
   24  *  Ported to 386bsd Oct 17, 1992
   25  *  Sandi Donno, Computer Science, University of Cape Town, South Africa
   26  *  Please send bug reports to sandi@cs.uct.ac.za
   27  *
   28  *  Thanks are also due to Rick Macklem, rick@snowhite.cis.uoguelph.ca -
   29  *  although I was only partially successful in getting the alpha release
   30  *  of his "driver for the Logitech and ATI Inport Bus mice for use with
   31  *  386bsd and the X386 port" to work with my Microsoft mouse, I nevertheless
   32  *  found his code to be an invaluable reference when porting this driver
   33  *  to 386bsd.
   34  *
   35  *  Further modifications for latest 386BSD+patchkit and port to NetBSD,
   36  *  Andrew Herbert <andrew@werple.apana.org.au> - 8 June 1993
   37  *
   38  *  Cloned from the Microsoft Bus Mouse driver, also by Erik Forsberg, by
   39  *  Andrew Herbert - 12 June 1993
   40  *
   41  *  Modified for PS/2 mouse by Charles Hannum <mycroft@ai.mit.edu>
   42  *  - 13 June 1993
   43  *
   44  *  Modified for PS/2 AUX mouse by Shoji Yuen <yuen@nuie.nagoya-u.ac.jp>
   45  *  - 24 October 1993
   46  *
   47  *  Hardware access routines and probe logic rewritten by
   48  *  Kazutaka Yokota <yokota@zodiac.mech.utsunomiya-u.ac.jp>
   49  *  - 3, 14, 22 October 1996.
   50  *  - 12 November 1996. IOCTLs and rearranging `psmread', `psmioctl'...
   51  *  - 14, 30 November 1996. Uses `kbdio.c'.
   52  *  - 13 December 1996. Uses queuing version of `kbdio.c'.
   53  *  - January/February 1997. Tweaked probe logic for
   54  *    HiNote UltraII/Latitude/Armada laptops.
   55  *  - 30 July 1997. Added APM support.
   56  *  - 5 March 1997. Defined driver configuration flags (PSM_CONFIG_XXX).
   57  *    Improved sync check logic.
   58  *    Vendor specific support routines.
   59  */
   60 
   61 #include <sys/cdefs.h>
   62 __FBSDID("$FreeBSD: releng/7.3/sys/dev/atkbdc/psm.c 190017 2009-03-19 07:40:41Z rnoland $");
   63 
   64 #include "opt_isa.h"
   65 #include "opt_psm.h"
   66 
   67 #include <sys/param.h>
   68 #include <sys/systm.h>
   69 #include <sys/kernel.h>
   70 #include <sys/module.h>
   71 #include <sys/bus.h>
   72 #include <sys/conf.h>
   73 #include <sys/filio.h>
   74 #include <sys/poll.h>
   75 #include <sys/sigio.h>
   76 #include <sys/signalvar.h>
   77 #include <sys/syslog.h>
   78 #include <machine/bus.h>
   79 #include <sys/rman.h>
   80 #include <sys/selinfo.h>
   81 #include <sys/sysctl.h>
   82 #include <sys/time.h>
   83 #include <sys/uio.h>
   84 
   85 #include <sys/limits.h>
   86 #include <sys/mouse.h>
   87 #include <machine/resource.h>
   88 
   89 #ifdef DEV_ISA
   90 #include <isa/isavar.h>
   91 #endif
   92 
   93 #include <dev/atkbdc/atkbdcreg.h>
   94 #include <dev/atkbdc/psm.h>
   95 
   96 /*
   97  * Driver specific options: the following options may be set by
   98  * `options' statements in the kernel configuration file.
   99  */
  100 
  101 /* debugging */
  102 #ifndef PSM_DEBUG
  103 #define PSM_DEBUG       0       /*
  104                                  * logging: 0: none, 1: brief, 2: verbose
  105                                  *          3: sync errors, 4: all packets
  106                                  */
  107 #endif
  108 #define VLOG(level, args)       do {    \
  109         if (verbose >= level)           \
  110                 log args;               \
  111 } while (0)
  112 
  113 #ifndef PSM_INPUT_TIMEOUT
  114 #define PSM_INPUT_TIMEOUT       2000000 /* 2 sec */
  115 #endif
  116 
  117 #ifndef PSM_TAP_TIMEOUT
  118 #define PSM_TAP_TIMEOUT         125000
  119 #endif
  120 
  121 #ifndef PSM_TAP_THRESHOLD
  122 #define PSM_TAP_THRESHOLD       25
  123 #endif
  124 
  125 /* end of driver specific options */
  126 
  127 #define PSMCPNP_DRIVER_NAME     "psmcpnp"
  128 
  129 /* input queue */
  130 #define PSM_BUFSIZE             960
  131 #define PSM_SMALLBUFSIZE        240
  132 
  133 /* operation levels */
  134 #define PSM_LEVEL_BASE          0
  135 #define PSM_LEVEL_STANDARD      1
  136 #define PSM_LEVEL_NATIVE        2
  137 #define PSM_LEVEL_MIN           PSM_LEVEL_BASE
  138 #define PSM_LEVEL_MAX           PSM_LEVEL_NATIVE
  139 
  140 /* Logitech PS2++ protocol */
  141 #define MOUSE_PS2PLUS_CHECKBITS(b)      \
  142     ((((b[2] & 0x03) << 2) | 0x02) == (b[1] & 0x0f))
  143 #define MOUSE_PS2PLUS_PACKET_TYPE(b)    \
  144     (((b[0] & 0x30) >> 2) | ((b[1] & 0x30) >> 4))
  145 
  146 /* some macros */
  147 #define PSM_UNIT(dev)           (minor(dev) >> 1)
  148 #define PSM_NBLOCKIO(dev)       (minor(dev) & 1)
  149 #define PSM_MKMINOR(unit,block) (((unit) << 1) | ((block) ? 0:1))
  150 
  151 /* ring buffer */
  152 typedef struct ringbuf {
  153         int             count;  /* # of valid elements in the buffer */
  154         int             head;   /* head pointer */
  155         int             tail;   /* tail poiner */
  156         u_char buf[PSM_BUFSIZE];
  157 } ringbuf_t;
  158 
  159 /* data buffer */
  160 typedef struct packetbuf {
  161         u_char  ipacket[16];    /* interim input buffer */
  162         int     inputbytes;     /* # of bytes in the input buffer */
  163 } packetbuf_t;
  164 
  165 #ifndef PSM_PACKETQUEUE
  166 #define PSM_PACKETQUEUE 128
  167 #endif
  168 
  169 typedef struct synapticsinfo {
  170         struct sysctl_ctx_list  sysctl_ctx;
  171         struct sysctl_oid       *sysctl_tree;
  172         int                     directional_scrolls;
  173         int                     low_speed_threshold;
  174         int                     min_movement;
  175         int                     squelch_level;
  176 } synapticsinfo_t;
  177 
  178 /* driver control block */
  179 struct psm_softc {              /* Driver status information */
  180         int             unit;
  181         struct selinfo  rsel;           /* Process selecting for Input */
  182         u_char          state;          /* Mouse driver state */
  183         int             config;         /* driver configuration flags */
  184         int             flags;          /* other flags */
  185         KBDC            kbdc;           /* handle to access kbd controller */
  186         struct resource *intr;          /* IRQ resource */
  187         void            *ih;            /* interrupt handle */
  188         mousehw_t       hw;             /* hardware information */
  189         synapticshw_t   synhw;          /* Synaptics hardware information */
  190         synapticsinfo_t syninfo;        /* Synaptics configuration */
  191         mousemode_t     mode;           /* operation mode */
  192         mousemode_t     dflt_mode;      /* default operation mode */
  193         mousestatus_t   status;         /* accumulated mouse movement */
  194         ringbuf_t       queue;          /* mouse status queue */
  195         packetbuf_t     pqueue[PSM_PACKETQUEUE]; /* mouse data queue */
  196         int             pqueue_start;   /* start of data in queue */
  197         int             pqueue_end;     /* end of data in queue */
  198         int             button;         /* the latest button state */
  199         int             xold;           /* previous absolute X position */
  200         int             yold;           /* previous absolute Y position */
  201         int             xaverage;       /* average X position */
  202         int             yaverage;       /* average Y position */
  203         int             squelch; /* level to filter movement at low speed */
  204         int             zmax;   /* maximum pressure value for touchpads */
  205         int             syncerrors; /* # of bytes discarded to synchronize */
  206         int             pkterrors;  /* # of packets failed during quaranteen. */
  207         struct timeval  inputtimeout;
  208         struct timeval  lastsoftintr;   /* time of last soft interrupt */
  209         struct timeval  lastinputerr;   /* time last sync error happened */
  210         struct timeval  taptimeout;     /* tap timeout for touchpads */
  211         int             watchdog;       /* watchdog timer flag */
  212         struct callout_handle callout;  /* watchdog timer call out */
  213         struct callout_handle softcallout; /* buffer timer call out */
  214         struct cdev     *dev;
  215         struct cdev     *bdev;
  216         int             lasterr;
  217         int             cmdcount;
  218         struct sigio    *async;         /* Processes waiting for SIGIO */
  219 };
  220 static devclass_t psm_devclass;
  221 #define PSM_SOFTC(unit) \
  222     ((struct psm_softc*)devclass_get_softc(psm_devclass, unit))
  223 
  224 /* driver state flags (state) */
  225 #define PSM_VALID               0x80
  226 #define PSM_OPEN                1       /* Device is open */
  227 #define PSM_ASLP                2       /* Waiting for mouse data */
  228 #define PSM_SOFTARMED           4       /* Software interrupt armed */
  229 #define PSM_NEED_SYNCBITS       8       /* Set syncbits using next data pkt */
  230 
  231 /* driver configuration flags (config) */
  232 #define PSM_CONFIG_RESOLUTION   0x000f  /* resolution */
  233 #define PSM_CONFIG_ACCEL        0x00f0  /* acceleration factor */
  234 #define PSM_CONFIG_NOCHECKSYNC  0x0100  /* disable sync. test */
  235 #define PSM_CONFIG_NOIDPROBE    0x0200  /* disable mouse model probe */
  236 #define PSM_CONFIG_NORESET      0x0400  /* don't reset the mouse */
  237 #define PSM_CONFIG_FORCETAP     0x0800  /* assume `tap' action exists */
  238 #define PSM_CONFIG_IGNPORTERROR 0x1000  /* ignore error in aux port test */
  239 #define PSM_CONFIG_HOOKRESUME   0x2000  /* hook the system resume event */
  240 #define PSM_CONFIG_INITAFTERSUSPEND 0x4000 /* init the device at the resume event */
  241 #define PSM_CONFIG_SYNCHACK     0x8000  /* enable `out-of-sync' hack */
  242 
  243 #define PSM_CONFIG_FLAGS        \
  244     (PSM_CONFIG_RESOLUTION |    \
  245     PSM_CONFIG_ACCEL |          \
  246     PSM_CONFIG_NOCHECKSYNC |    \
  247     PSM_CONFIG_SYNCHACK |       \
  248     PSM_CONFIG_NOIDPROBE |      \
  249     PSM_CONFIG_NORESET |        \
  250     PSM_CONFIG_FORCETAP |       \
  251     PSM_CONFIG_IGNPORTERROR |   \
  252     PSM_CONFIG_HOOKRESUME |     \
  253     PSM_CONFIG_INITAFTERSUSPEND)
  254 
  255 /* other flags (flags) */
  256 #define PSM_FLAGS_FINGERDOWN    0x0001  /* VersaPad finger down */
  257 
  258 /* Tunables */
  259 static int synaptics_support = 0;
  260 TUNABLE_INT("hw.psm.synaptics_support", &synaptics_support);
  261 
  262 static int verbose = PSM_DEBUG;
  263 TUNABLE_INT("debug.psm.loglevel", &verbose);
  264 
  265 /* for backward compatibility */
  266 #define OLD_MOUSE_GETHWINFO     _IOR('M', 1, old_mousehw_t)
  267 #define OLD_MOUSE_GETMODE       _IOR('M', 2, old_mousemode_t)
  268 #define OLD_MOUSE_SETMODE       _IOW('M', 3, old_mousemode_t)
  269 
  270 typedef struct old_mousehw {
  271         int     buttons;
  272         int     iftype;
  273         int     type;
  274         int     hwid;
  275 } old_mousehw_t;
  276 
  277 typedef struct old_mousemode {
  278         int     protocol;
  279         int     rate;
  280         int     resolution;
  281         int     accelfactor;
  282 } old_mousemode_t;
  283 
  284 /* packet formatting function */
  285 typedef int     packetfunc_t(struct psm_softc *, u_char *, int *, int,
  286     mousestatus_t *);
  287 
  288 /* function prototypes */
  289 static void     psmidentify(driver_t *, device_t);
  290 static int      psmprobe(device_t);
  291 static int      psmattach(device_t);
  292 static int      psmdetach(device_t);
  293 static int      psmresume(device_t);
  294 
  295 static d_open_t         psmopen;
  296 static d_close_t        psmclose;
  297 static d_read_t         psmread;
  298 static d_write_t        psmwrite;
  299 static d_ioctl_t        psmioctl;
  300 static d_poll_t         psmpoll;
  301 
  302 static int      enable_aux_dev(KBDC);
  303 static int      disable_aux_dev(KBDC);
  304 static int      get_mouse_status(KBDC, int *, int, int);
  305 static int      get_aux_id(KBDC);
  306 static int      set_mouse_sampling_rate(KBDC, int);
  307 static int      set_mouse_scaling(KBDC, int);
  308 static int      set_mouse_resolution(KBDC, int);
  309 static int      set_mouse_mode(KBDC);
  310 static int      get_mouse_buttons(KBDC);
  311 static int      is_a_mouse(int);
  312 static void     recover_from_error(KBDC);
  313 static int      restore_controller(KBDC, int);
  314 static int      doinitialize(struct psm_softc *, mousemode_t *);
  315 static int      doopen(struct psm_softc *, int);
  316 static int      reinitialize(struct psm_softc *, int);
  317 static char     *model_name(int);
  318 static void     psmsoftintr(void *);
  319 static void     psmintr(void *);
  320 static void     psmtimeout(void *);
  321 static int      timeelapsed(const struct timeval *, int, int,
  322                     const struct timeval *);
  323 static void     dropqueue(struct psm_softc *);
  324 static void     flushpackets(struct psm_softc *);
  325 static void     proc_mmanplus(struct psm_softc *, packetbuf_t *,
  326                     mousestatus_t *, int *, int *, int *);
  327 static int      proc_synaptics(struct psm_softc *, packetbuf_t *,
  328                     mousestatus_t *, int *, int *, int *);
  329 static void     proc_versapad(struct psm_softc *, packetbuf_t *,
  330                     mousestatus_t *, int *, int *, int *);
  331 static int      tame_mouse(struct psm_softc *, packetbuf_t *, mousestatus_t *,
  332                     u_char *);
  333 
  334 /* vendor specific features */
  335 typedef int     probefunc_t(struct psm_softc *);
  336 
  337 static int      mouse_id_proc1(KBDC, int, int, int *);
  338 static int      mouse_ext_command(KBDC, int);
  339 
  340 static probefunc_t      enable_groller;
  341 static probefunc_t      enable_gmouse;
  342 static probefunc_t      enable_aglide;
  343 static probefunc_t      enable_kmouse;
  344 static probefunc_t      enable_msexplorer;
  345 static probefunc_t      enable_msintelli;
  346 static probefunc_t      enable_4dmouse;
  347 static probefunc_t      enable_4dplus;
  348 static probefunc_t      enable_mmanplus;
  349 static probefunc_t      enable_synaptics;
  350 static probefunc_t      enable_versapad;
  351 
  352 static struct {
  353         int             model;
  354         u_char          syncmask;
  355         int             packetsize;
  356         probefunc_t     *probefunc;
  357 } vendortype[] = {
  358         /*
  359          * WARNING: the order of probe is very important.  Don't mess it
  360          * unless you know what you are doing.
  361          */
  362         { MOUSE_MODEL_NET,              /* Genius NetMouse */
  363           0x08, MOUSE_PS2INTELLI_PACKETSIZE, enable_gmouse },
  364         { MOUSE_MODEL_NETSCROLL,        /* Genius NetScroll */
  365           0xc8, 6, enable_groller },
  366         { MOUSE_MODEL_MOUSEMANPLUS,     /* Logitech MouseMan+ */
  367           0x08, MOUSE_PS2_PACKETSIZE, enable_mmanplus },
  368         { MOUSE_MODEL_EXPLORER,         /* Microsoft IntelliMouse Explorer */
  369           0x08, MOUSE_PS2INTELLI_PACKETSIZE, enable_msexplorer },
  370         { MOUSE_MODEL_4D,               /* A4 Tech 4D Mouse */
  371           0x08, MOUSE_4D_PACKETSIZE, enable_4dmouse },
  372         { MOUSE_MODEL_4DPLUS,           /* A4 Tech 4D+ Mouse */
  373           0xc8, MOUSE_4DPLUS_PACKETSIZE, enable_4dplus },
  374         { MOUSE_MODEL_SYNAPTICS,        /* Synaptics Touchpad */
  375           0xc0, MOUSE_SYNAPTICS_PACKETSIZE, enable_synaptics },
  376         { MOUSE_MODEL_INTELLI,          /* Microsoft IntelliMouse */
  377           0x08, MOUSE_PS2INTELLI_PACKETSIZE, enable_msintelli },
  378         { MOUSE_MODEL_GLIDEPOINT,       /* ALPS GlidePoint */
  379           0xc0, MOUSE_PS2_PACKETSIZE, enable_aglide },
  380         { MOUSE_MODEL_THINK,            /* Kensington ThinkingMouse */
  381           0x80, MOUSE_PS2_PACKETSIZE, enable_kmouse },
  382         { MOUSE_MODEL_VERSAPAD,         /* Interlink electronics VersaPad */
  383           0xe8, MOUSE_PS2VERSA_PACKETSIZE, enable_versapad },
  384         { MOUSE_MODEL_GENERIC,
  385           0xc0, MOUSE_PS2_PACKETSIZE, NULL },
  386 };
  387 #define GENERIC_MOUSE_ENTRY     \
  388     ((sizeof(vendortype) / sizeof(*vendortype)) - 1)
  389 
  390 /* device driver declarateion */
  391 static device_method_t psm_methods[] = {
  392         /* Device interface */
  393         DEVMETHOD(device_identify,      psmidentify),
  394         DEVMETHOD(device_probe,         psmprobe),
  395         DEVMETHOD(device_attach,        psmattach),
  396         DEVMETHOD(device_detach,        psmdetach),
  397         DEVMETHOD(device_resume,        psmresume),
  398 
  399         { 0, 0 }
  400 };
  401 
  402 static driver_t psm_driver = {
  403         PSM_DRIVER_NAME,
  404         psm_methods,
  405         sizeof(struct psm_softc),
  406 };
  407 
  408 static struct cdevsw psm_cdevsw = {
  409         .d_version =    D_VERSION,
  410         .d_flags =      D_NEEDGIANT,
  411         .d_open =       psmopen,
  412         .d_close =      psmclose,
  413         .d_read =       psmread,
  414         .d_write =      psmwrite,
  415         .d_ioctl =      psmioctl,
  416         .d_poll =       psmpoll,
  417         .d_name =       PSM_DRIVER_NAME,
  418 };
  419 
  420 /* device I/O routines */
  421 static int
  422 enable_aux_dev(KBDC kbdc)
  423 {
  424         int res;
  425 
  426         res = send_aux_command(kbdc, PSMC_ENABLE_DEV);
  427         VLOG(2, (LOG_DEBUG, "psm: ENABLE_DEV return code:%04x\n", res));
  428 
  429         return (res == PSM_ACK);
  430 }
  431 
  432 static int
  433 disable_aux_dev(KBDC kbdc)
  434 {
  435         int res;
  436 
  437         res = send_aux_command(kbdc, PSMC_DISABLE_DEV);
  438         VLOG(2, (LOG_DEBUG, "psm: DISABLE_DEV return code:%04x\n", res));
  439 
  440         return (res == PSM_ACK);
  441 }
  442 
  443 static int
  444 get_mouse_status(KBDC kbdc, int *status, int flag, int len)
  445 {
  446         int cmd;
  447         int res;
  448         int i;
  449 
  450         switch (flag) {
  451         case 0:
  452         default:
  453                 cmd = PSMC_SEND_DEV_STATUS;
  454                 break;
  455         case 1:
  456                 cmd = PSMC_SEND_DEV_DATA;
  457                 break;
  458         }
  459         empty_aux_buffer(kbdc, 5);
  460         res = send_aux_command(kbdc, cmd);
  461         VLOG(2, (LOG_DEBUG, "psm: SEND_AUX_DEV_%s return code:%04x\n",
  462             (flag == 1) ? "DATA" : "STATUS", res));
  463         if (res != PSM_ACK)
  464                 return (0);
  465 
  466         for (i = 0; i < len; ++i) {
  467                 status[i] = read_aux_data(kbdc);
  468                 if (status[i] < 0)
  469                         break;
  470         }
  471 
  472         VLOG(1, (LOG_DEBUG, "psm: %s %02x %02x %02x\n",
  473             (flag == 1) ? "data" : "status", status[0], status[1], status[2]));
  474 
  475         return (i);
  476 }
  477 
  478 static int
  479 get_aux_id(KBDC kbdc)
  480 {
  481         int res;
  482         int id;
  483 
  484         empty_aux_buffer(kbdc, 5);
  485         res = send_aux_command(kbdc, PSMC_SEND_DEV_ID);
  486         VLOG(2, (LOG_DEBUG, "psm: SEND_DEV_ID return code:%04x\n", res));
  487         if (res != PSM_ACK)
  488                 return (-1);
  489 
  490         /* 10ms delay */
  491         DELAY(10000);
  492 
  493         id = read_aux_data(kbdc);
  494         VLOG(2, (LOG_DEBUG, "psm: device ID: %04x\n", id));
  495 
  496         return (id);
  497 }
  498 
  499 static int
  500 set_mouse_sampling_rate(KBDC kbdc, int rate)
  501 {
  502         int res;
  503 
  504         res = send_aux_command_and_data(kbdc, PSMC_SET_SAMPLING_RATE, rate);
  505         VLOG(2, (LOG_DEBUG, "psm: SET_SAMPLING_RATE (%d) %04x\n", rate, res));
  506 
  507         return ((res == PSM_ACK) ? rate : -1);
  508 }
  509 
  510 static int
  511 set_mouse_scaling(KBDC kbdc, int scale)
  512 {
  513         int res;
  514 
  515         switch (scale) {
  516         case 1:
  517         default:
  518                 scale = PSMC_SET_SCALING11;
  519                 break;
  520         case 2:
  521                 scale = PSMC_SET_SCALING21;
  522                 break;
  523         }
  524         res = send_aux_command(kbdc, scale);
  525         VLOG(2, (LOG_DEBUG, "psm: SET_SCALING%s return code:%04x\n",
  526             (scale == PSMC_SET_SCALING21) ? "21" : "11", res));
  527 
  528         return (res == PSM_ACK);
  529 }
  530 
  531 /* `val' must be 0 through PSMD_MAX_RESOLUTION */
  532 static int
  533 set_mouse_resolution(KBDC kbdc, int val)
  534 {
  535         int res;
  536 
  537         res = send_aux_command_and_data(kbdc, PSMC_SET_RESOLUTION, val);
  538         VLOG(2, (LOG_DEBUG, "psm: SET_RESOLUTION (%d) %04x\n", val, res));
  539 
  540         return ((res == PSM_ACK) ? val : -1);
  541 }
  542 
  543 /*
  544  * NOTE: once `set_mouse_mode()' is called, the mouse device must be
  545  * re-enabled by calling `enable_aux_dev()'
  546  */
  547 static int
  548 set_mouse_mode(KBDC kbdc)
  549 {
  550         int res;
  551 
  552         res = send_aux_command(kbdc, PSMC_SET_STREAM_MODE);
  553         VLOG(2, (LOG_DEBUG, "psm: SET_STREAM_MODE return code:%04x\n", res));
  554 
  555         return (res == PSM_ACK);
  556 }
  557 
  558 static int
  559 get_mouse_buttons(KBDC kbdc)
  560 {
  561         int c = 2;              /* assume two buttons by default */
  562         int status[3];
  563 
  564         /*
  565          * NOTE: a special sequence to obtain Logitech Mouse specific
  566          * information: set resolution to 25 ppi, set scaling to 1:1, set
  567          * scaling to 1:1, set scaling to 1:1. Then the second byte of the
  568          * mouse status bytes is the number of available buttons.
  569          * Some manufactures also support this sequence.
  570          */
  571         if (set_mouse_resolution(kbdc, PSMD_RES_LOW) != PSMD_RES_LOW)
  572                 return (c);
  573         if (set_mouse_scaling(kbdc, 1) && set_mouse_scaling(kbdc, 1) &&
  574             set_mouse_scaling(kbdc, 1) &&
  575             get_mouse_status(kbdc, status, 0, 3) >= 3 && status[1] != 0)
  576                 return (status[1]);
  577         return (c);
  578 }
  579 
  580 /* misc subroutines */
  581 /*
  582  * Someday, I will get the complete list of valid pointing devices and
  583  * their IDs... XXX
  584  */
  585 static int
  586 is_a_mouse(int id)
  587 {
  588 #if 0
  589         static int valid_ids[] = {
  590                 PSM_MOUSE_ID,           /* mouse */
  591                 PSM_BALLPOINT_ID,       /* ballpoint device */
  592                 PSM_INTELLI_ID,         /* Intellimouse */
  593                 PSM_EXPLORER_ID,        /* Intellimouse Explorer */
  594                 -1                      /* end of table */
  595         };
  596         int i;
  597 
  598         for (i = 0; valid_ids[i] >= 0; ++i)
  599         if (valid_ids[i] == id)
  600                 return (TRUE);
  601         return (FALSE);
  602 #else
  603         return (TRUE);
  604 #endif
  605 }
  606 
  607 static char *
  608 model_name(int model)
  609 {
  610         static struct {
  611                 int     model_code;
  612                 char    *model_name;
  613         } models[] = {
  614                 { MOUSE_MODEL_NETSCROLL,        "NetScroll" },
  615                 { MOUSE_MODEL_NET,              "NetMouse/NetScroll Optical" },
  616                 { MOUSE_MODEL_GLIDEPOINT,       "GlidePoint" },
  617                 { MOUSE_MODEL_THINK,            "ThinkingMouse" },
  618                 { MOUSE_MODEL_INTELLI,          "IntelliMouse" },
  619                 { MOUSE_MODEL_MOUSEMANPLUS,     "MouseMan+" },
  620                 { MOUSE_MODEL_VERSAPAD,         "VersaPad" },
  621                 { MOUSE_MODEL_EXPLORER,         "IntelliMouse Explorer" },
  622                 { MOUSE_MODEL_4D,               "4D Mouse" },
  623                 { MOUSE_MODEL_4DPLUS,           "4D+ Mouse" },
  624                 { MOUSE_MODEL_SYNAPTICS,        "Synaptics Touchpad" },
  625                 { MOUSE_MODEL_GENERIC,          "Generic PS/2 mouse" },
  626                 { MOUSE_MODEL_UNKNOWN,          "Unknown" },
  627         };
  628         int i;
  629 
  630         for (i = 0; models[i].model_code != MOUSE_MODEL_UNKNOWN; ++i)
  631                 if (models[i].model_code == model)
  632                         break;
  633         return (models[i].model_name);
  634 }
  635 
  636 static void
  637 recover_from_error(KBDC kbdc)
  638 {
  639         /* discard anything left in the output buffer */
  640         empty_both_buffers(kbdc, 10);
  641 
  642 #if 0
  643         /*
  644          * NOTE: KBDC_RESET_KBD may not restore the communication between the
  645          * keyboard and the controller.
  646          */
  647         reset_kbd(kbdc);
  648 #else
  649         /*
  650          * NOTE: somehow diagnostic and keyboard port test commands bring the
  651          * keyboard back.
  652          */
  653         if (!test_controller(kbdc))
  654                 log(LOG_ERR, "psm: keyboard controller failed.\n");
  655         /* if there isn't a keyboard in the system, the following error is OK */
  656         if (test_kbd_port(kbdc) != 0)
  657                 VLOG(1, (LOG_ERR, "psm: keyboard port failed.\n"));
  658 #endif
  659 }
  660 
  661 static int
  662 restore_controller(KBDC kbdc, int command_byte)
  663 {
  664         empty_both_buffers(kbdc, 10);
  665 
  666         if (!set_controller_command_byte(kbdc, 0xff, command_byte)) {
  667                 log(LOG_ERR, "psm: failed to restore the keyboard controller "
  668                     "command byte.\n");
  669                 empty_both_buffers(kbdc, 10);
  670                 return (FALSE);
  671         } else {
  672                 empty_both_buffers(kbdc, 10);
  673                 return (TRUE);
  674         }
  675 }
  676 
  677 /*
  678  * Re-initialize the aux port and device. The aux port must be enabled
  679  * and its interrupt must be disabled before calling this routine.
  680  * The aux device will be disabled before returning.
  681  * The keyboard controller must be locked via `kbdc_lock()' before
  682  * calling this routine.
  683  */
  684 static int
  685 doinitialize(struct psm_softc *sc, mousemode_t *mode)
  686 {
  687         KBDC kbdc = sc->kbdc;
  688         int stat[3];
  689         int i;
  690 
  691         switch((i = test_aux_port(kbdc))) {
  692         case 1: /* ignore these errors */
  693         case 2:
  694         case 3:
  695         case PSM_ACK:
  696                 if (verbose)
  697                         log(LOG_DEBUG,
  698                             "psm%d: strange result for test aux port (%d).\n",
  699                             sc->unit, i);
  700                 /* FALLTHROUGH */
  701         case 0:         /* no error */
  702                 break;
  703         case -1:        /* time out */
  704         default:        /* error */
  705                 recover_from_error(kbdc);
  706                 if (sc->config & PSM_CONFIG_IGNPORTERROR)
  707                         break;
  708                 log(LOG_ERR, "psm%d: the aux port is not functioning (%d).\n",
  709                     sc->unit, i);
  710                 return (FALSE);
  711         }
  712 
  713         if (sc->config & PSM_CONFIG_NORESET) {
  714                 /*
  715                  * Don't try to reset the pointing device.  It may possibly
  716                  * be left in the unknown state, though...
  717                  */
  718         } else {
  719                 /*
  720                  * NOTE: some controllers appears to hang the `keyboard' when
  721                  * the aux port doesn't exist and `PSMC_RESET_DEV' is issued.
  722                  */
  723                 if (!reset_aux_dev(kbdc)) {
  724                         recover_from_error(kbdc);
  725                         log(LOG_ERR, "psm%d: failed to reset the aux device.\n",
  726                             sc->unit);
  727                         return (FALSE);
  728                 }
  729         }
  730 
  731         /*
  732          * both the aux port and the aux device is functioning, see
  733          * if the device can be enabled.
  734          */
  735         if (!enable_aux_dev(kbdc) || !disable_aux_dev(kbdc)) {
  736                 log(LOG_ERR, "psm%d: failed to enable the aux device.\n",
  737                     sc->unit);
  738                 return (FALSE);
  739         }
  740         empty_both_buffers(kbdc, 10);   /* remove stray data if any */
  741 
  742         if (sc->config & PSM_CONFIG_NOIDPROBE)
  743                 i = GENERIC_MOUSE_ENTRY;
  744         else {
  745                 /* FIXME: hardware ID, mouse buttons? */
  746 
  747                 /* other parameters */
  748                 for (i = 0; vendortype[i].probefunc != NULL; ++i)
  749                         if ((*vendortype[i].probefunc)(sc)) {
  750                                 if (verbose >= 2)
  751                                         log(LOG_ERR, "psm%d: found %s\n",
  752                                             sc->unit,
  753                                             model_name(vendortype[i].model));
  754                                 break;
  755                         }
  756         }
  757 
  758         sc->hw.model = vendortype[i].model;
  759         sc->mode.packetsize = vendortype[i].packetsize;
  760 
  761         /* set mouse parameters */
  762         if (mode != (mousemode_t *)NULL) {
  763                 if (mode->rate > 0)
  764                         mode->rate = set_mouse_sampling_rate(kbdc, mode->rate);
  765                 if (mode->resolution >= 0)
  766                         mode->resolution =
  767                             set_mouse_resolution(kbdc, mode->resolution);
  768                 set_mouse_scaling(kbdc, 1);
  769                 set_mouse_mode(kbdc);
  770         }
  771 
  772         /* Record sync on the next data packet we see. */
  773         sc->flags |= PSM_NEED_SYNCBITS;
  774 
  775         /* just check the status of the mouse */
  776         if (get_mouse_status(kbdc, stat, 0, 3) < 3)
  777                 log(LOG_DEBUG, "psm%d: failed to get status (doinitialize).\n",
  778                     sc->unit);
  779 
  780         return (TRUE);
  781 }
  782 
  783 static int
  784 doopen(struct psm_softc *sc, int command_byte)
  785 {
  786         int stat[3];
  787 
  788         /* enable the mouse device */
  789         if (!enable_aux_dev(sc->kbdc)) {
  790                 /* MOUSE ERROR: failed to enable the mouse because:
  791                  * 1) the mouse is faulty,
  792                  * 2) the mouse has been removed(!?)
  793                  * In the latter case, the keyboard may have hung, and need
  794                  * recovery procedure...
  795                  */
  796                 recover_from_error(sc->kbdc);
  797 #if 0
  798                 /* FIXME: we could reset the mouse here and try to enable
  799                  * it again. But it will take long time and it's not a good
  800                  * idea to disable the keyboard that long...
  801                  */
  802                 if (!doinitialize(sc, &sc->mode) || !enable_aux_dev(sc->kbdc)) {
  803                         recover_from_error(sc->kbdc);
  804 #else
  805                 {
  806 #endif
  807                         restore_controller(sc->kbdc, command_byte);
  808                         /* mark this device is no longer available */
  809                         sc->state &= ~PSM_VALID;
  810                         log(LOG_ERR,
  811                             "psm%d: failed to enable the device (doopen).\n",
  812                         sc->unit);
  813                         return (EIO);
  814                 }
  815         }
  816 
  817         if (get_mouse_status(sc->kbdc, stat, 0, 3) < 3)
  818                 log(LOG_DEBUG, "psm%d: failed to get status (doopen).\n",
  819                     sc->unit);
  820 
  821         /* enable the aux port and interrupt */
  822         if (!set_controller_command_byte(sc->kbdc,
  823             kbdc_get_device_mask(sc->kbdc),
  824             (command_byte & KBD_KBD_CONTROL_BITS) |
  825             KBD_ENABLE_AUX_PORT | KBD_ENABLE_AUX_INT)) {
  826                 /* CONTROLLER ERROR */
  827                 disable_aux_dev(sc->kbdc);
  828                 restore_controller(sc->kbdc, command_byte);
  829                 log(LOG_ERR,
  830                     "psm%d: failed to enable the aux interrupt (doopen).\n",
  831                     sc->unit);
  832                 return (EIO);
  833         }
  834 
  835         /* start the watchdog timer */
  836         sc->watchdog = FALSE;
  837         sc->callout = timeout(psmtimeout, (void *)(uintptr_t)sc, hz*2);
  838 
  839         return (0);
  840 }
  841 
  842 static int
  843 reinitialize(struct psm_softc *sc, int doinit)
  844 {
  845         int err;
  846         int c;
  847         int s;
  848 
  849         /* don't let anybody mess with the aux device */
  850         if (!kbdc_lock(sc->kbdc, TRUE))
  851                 return (EIO);
  852         s = spltty();
  853 
  854         /* block our watchdog timer */
  855         sc->watchdog = FALSE;
  856         untimeout(psmtimeout, (void *)(uintptr_t)sc, sc->callout);
  857         callout_handle_init(&sc->callout);
  858 
  859         /* save the current controller command byte */
  860         empty_both_buffers(sc->kbdc, 10);
  861         c = get_controller_command_byte(sc->kbdc);
  862         VLOG(2, (LOG_DEBUG,
  863             "psm%d: current command byte: %04x (reinitialize).\n",
  864             sc->unit, c));
  865 
  866         /* enable the aux port but disable the aux interrupt and the keyboard */
  867         if ((c == -1) || !set_controller_command_byte(sc->kbdc,
  868             kbdc_get_device_mask(sc->kbdc),
  869             KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT |
  870             KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
  871                 /* CONTROLLER ERROR */
  872                 splx(s);
  873                 kbdc_lock(sc->kbdc, FALSE);
  874                 log(LOG_ERR,
  875                     "psm%d: unable to set the command byte (reinitialize).\n",
  876                     sc->unit);
  877                 return (EIO);
  878         }
  879 
  880         /* flush any data */
  881         if (sc->state & PSM_VALID) {
  882                 /* this may fail; but never mind... */
  883                 disable_aux_dev(sc->kbdc);
  884                 empty_aux_buffer(sc->kbdc, 10);
  885         }
  886         flushpackets(sc);
  887         sc->syncerrors = 0;
  888         sc->pkterrors = 0;
  889         memset(&sc->lastinputerr, 0, sizeof(sc->lastinputerr));
  890 
  891         /* try to detect the aux device; are you still there? */
  892         err = 0;
  893         if (doinit) {
  894                 if (doinitialize(sc, &sc->mode)) {
  895                         /* yes */
  896                         sc->state |= PSM_VALID;
  897                 } else {
  898                         /* the device has gone! */
  899                         restore_controller(sc->kbdc, c);
  900                         sc->state &= ~PSM_VALID;
  901                         log(LOG_ERR,
  902                             "psm%d: the aux device has gone! (reinitialize).\n",
  903                             sc->unit);
  904                         err = ENXIO;
  905                 }
  906         }
  907         splx(s);
  908 
  909         /* restore the driver state */
  910         if ((sc->state & PSM_OPEN) && (err == 0)) {
  911                 /* enable the aux device and the port again */
  912                 err = doopen(sc, c);
  913                 if (err != 0)
  914                         log(LOG_ERR, "psm%d: failed to enable the device "
  915                             "(reinitialize).\n", sc->unit);
  916         } else {
  917                 /* restore the keyboard port and disable the aux port */
  918                 if (!set_controller_command_byte(sc->kbdc,
  919                     kbdc_get_device_mask(sc->kbdc),
  920                     (c & KBD_KBD_CONTROL_BITS) |
  921                     KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
  922                         /* CONTROLLER ERROR */
  923                         log(LOG_ERR, "psm%d: failed to disable the aux port "
  924                             "(reinitialize).\n", sc->unit);
  925                         err = EIO;
  926                 }
  927         }
  928 
  929         kbdc_lock(sc->kbdc, FALSE);
  930         return (err);
  931 }
  932 
  933 /* psm driver entry points */
  934 
  935 static void
  936 psmidentify(driver_t *driver, device_t parent)
  937 {
  938         device_t psmc;
  939         device_t psm;
  940         u_long irq;
  941         int unit;
  942 
  943         unit = device_get_unit(parent);
  944 
  945         /* always add at least one child */
  946         psm = BUS_ADD_CHILD(parent, KBDC_RID_AUX, driver->name, unit);
  947         if (psm == NULL)
  948                 return;
  949 
  950         irq = bus_get_resource_start(psm, SYS_RES_IRQ, KBDC_RID_AUX);
  951         if (irq > 0)
  952                 return;
  953 
  954         /*
  955          * If the PS/2 mouse device has already been reported by ACPI or
  956          * PnP BIOS, obtain the IRQ resource from it.
  957          * (See psmcpnp_attach() below.)
  958          */
  959         psmc = device_find_child(device_get_parent(parent),
  960             PSMCPNP_DRIVER_NAME, unit);
  961         if (psmc == NULL)
  962                 return;
  963         irq = bus_get_resource_start(psmc, SYS_RES_IRQ, 0);
  964         if (irq <= 0)
  965                 return;
  966         bus_set_resource(psm, SYS_RES_IRQ, KBDC_RID_AUX, irq, 1);
  967 }
  968 
  969 #define endprobe(v)     do {                    \
  970         if (bootverbose)                        \
  971                 --verbose;                      \
  972         kbdc_set_device_mask(sc->kbdc, mask);   \
  973         kbdc_lock(sc->kbdc, FALSE);             \
  974         return (v);                             \
  975 } while (0)
  976 
  977 static int
  978 psmprobe(device_t dev)
  979 {
  980         int unit = device_get_unit(dev);
  981         struct psm_softc *sc = device_get_softc(dev);
  982         int stat[3];
  983         int command_byte;
  984         int mask;
  985         int rid;
  986         int i;
  987 
  988 #if 0
  989         kbdc_debug(TRUE);
  990 #endif
  991 
  992         /* see if IRQ is available */
  993         rid = KBDC_RID_AUX;
  994         sc->intr = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
  995             RF_SHAREABLE | RF_ACTIVE);
  996         if (sc->intr == NULL) {
  997                 if (bootverbose)
  998                         device_printf(dev, "unable to allocate IRQ\n");
  999                 return (ENXIO);
 1000         }
 1001         bus_release_resource(dev, SYS_RES_IRQ, rid, sc->intr);
 1002 
 1003         sc->unit = unit;
 1004         sc->kbdc = atkbdc_open(device_get_unit(device_get_parent(dev)));
 1005         sc->config = device_get_flags(dev) & PSM_CONFIG_FLAGS;
 1006         /* XXX: for backward compatibility */
 1007 #if defined(PSM_HOOKRESUME) || defined(PSM_HOOKAPM)
 1008         sc->config |=
 1009 #ifdef PSM_RESETAFTERSUSPEND
 1010         PSM_CONFIG_HOOKRESUME | PSM_CONFIG_INITAFTERSUSPEND;
 1011 #else
 1012         PSM_CONFIG_HOOKRESUME;
 1013 #endif
 1014 #endif /* PSM_HOOKRESUME | PSM_HOOKAPM */
 1015         sc->flags = 0;
 1016         if (bootverbose)
 1017                 ++verbose;
 1018 
 1019         device_set_desc(dev, "PS/2 Mouse");
 1020 
 1021         if (!kbdc_lock(sc->kbdc, TRUE)) {
 1022                 printf("psm%d: unable to lock the controller.\n", unit);
 1023                 if (bootverbose)
 1024                         --verbose;
 1025                 return (ENXIO);
 1026         }
 1027 
 1028         /*
 1029          * NOTE: two bits in the command byte controls the operation of the
 1030          * aux port (mouse port): the aux port disable bit (bit 5) and the aux
 1031          * port interrupt (IRQ 12) enable bit (bit 2).
 1032          */
 1033 
 1034         /* discard anything left after the keyboard initialization */
 1035         empty_both_buffers(sc->kbdc, 10);
 1036 
 1037         /* save the current command byte; it will be used later */
 1038         mask = kbdc_get_device_mask(sc->kbdc) & ~KBD_AUX_CONTROL_BITS;
 1039         command_byte = get_controller_command_byte(sc->kbdc);
 1040         if (verbose)
 1041                 printf("psm%d: current command byte:%04x\n", unit,
 1042                     command_byte);
 1043         if (command_byte == -1) {
 1044                 /* CONTROLLER ERROR */
 1045                 printf("psm%d: unable to get the current command byte value.\n",
 1046                         unit);
 1047                 endprobe(ENXIO);
 1048         }
 1049 
 1050         /*
 1051          * disable the keyboard port while probing the aux port, which must be
 1052          * enabled during this routine
 1053          */
 1054         if (!set_controller_command_byte(sc->kbdc,
 1055             KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS,
 1056             KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT |
 1057             KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
 1058                 /*
 1059                  * this is CONTROLLER ERROR; I don't know how to recover
 1060                  * from this error...
 1061                  */
 1062                 restore_controller(sc->kbdc, command_byte);
 1063                 printf("psm%d: unable to set the command byte.\n", unit);
 1064                 endprobe(ENXIO);
 1065         }
 1066         write_controller_command(sc->kbdc, KBDC_ENABLE_AUX_PORT);
 1067 
 1068         /*
 1069          * NOTE: `test_aux_port()' is designed to return with zero if the aux
 1070          * port exists and is functioning. However, some controllers appears
 1071          * to respond with zero even when the aux port doesn't exist. (It may
 1072          * be that this is only the case when the controller DOES have the aux
 1073          * port but the port is not wired on the motherboard.) The keyboard
 1074          * controllers without the port, such as the original AT, are
 1075          * supporsed to return with an error code or simply time out. In any
 1076          * case, we have to continue probing the port even when the controller
 1077          * passes this test.
 1078          *
 1079          * XXX: some controllers erroneously return the error code 1, 2 or 3
 1080          * when it has the perfectly functional aux port. We have to ignore
 1081          * this error code. Even if the controller HAS error with the aux
 1082          * port, it will be detected later...
 1083          * XXX: another incompatible controller returns PSM_ACK (0xfa)...
 1084          */
 1085         switch ((i = test_aux_port(sc->kbdc))) {
 1086         case 1:         /* ignore these errors */
 1087         case 2:
 1088         case 3:
 1089         case PSM_ACK:
 1090                 if (verbose)
 1091                         printf("psm%d: strange result for test aux port "
 1092                             "(%d).\n", unit, i);
 1093                 /* FALLTHROUGH */
 1094         case 0:         /* no error */
 1095                 break;
 1096         case -1:        /* time out */
 1097         default:        /* error */
 1098                 recover_from_error(sc->kbdc);
 1099                 if (sc->config & PSM_CONFIG_IGNPORTERROR)
 1100                         break;
 1101                 restore_controller(sc->kbdc, command_byte);
 1102                 if (verbose)
 1103                         printf("psm%d: the aux port is not functioning (%d).\n",
 1104                             unit, i);
 1105                 endprobe(ENXIO);
 1106         }
 1107 
 1108         if (sc->config & PSM_CONFIG_NORESET) {
 1109                 /*
 1110                  * Don't try to reset the pointing device.  It may possibly be
 1111                  * left in the unknown state, though...
 1112                  */
 1113         } else {
 1114                 /*
 1115                  * NOTE: some controllers appears to hang the `keyboard' when
 1116                  * the aux port doesn't exist and `PSMC_RESET_DEV' is issued.
 1117                  *
 1118                  * Attempt to reset the controller twice -- this helps
 1119                  * pierce through some KVM switches. The second reset
 1120                  * is non-fatal.
 1121                  */
 1122                 if (!reset_aux_dev(sc->kbdc)) {
 1123                         recover_from_error(sc->kbdc);
 1124                         restore_controller(sc->kbdc, command_byte);
 1125                         if (verbose)
 1126                                 printf("psm%d: failed to reset the aux "
 1127                                     "device.\n", unit);
 1128                         endprobe(ENXIO);
 1129                 } else if (!reset_aux_dev(sc->kbdc)) {
 1130                         recover_from_error(sc->kbdc);
 1131                         if (verbose >= 2)
 1132                                 printf("psm%d: failed to reset the aux device "
 1133                                     "(2).\n", unit);
 1134                 }
 1135         }
 1136 
 1137         /*
 1138          * both the aux port and the aux device is functioning, see if the
 1139          * device can be enabled. NOTE: when enabled, the device will start
 1140          * sending data; we shall immediately disable the device once we know
 1141          * the device can be enabled.
 1142          */
 1143         if (!enable_aux_dev(sc->kbdc) || !disable_aux_dev(sc->kbdc)) {
 1144                 /* MOUSE ERROR */
 1145                 recover_from_error(sc->kbdc);
 1146                 restore_controller(sc->kbdc, command_byte);
 1147                 if (verbose)
 1148                         printf("psm%d: failed to enable the aux device.\n",
 1149                             unit);
 1150                 endprobe(ENXIO);
 1151         }
 1152 
 1153         /* save the default values after reset */
 1154         if (get_mouse_status(sc->kbdc, stat, 0, 3) >= 3) {
 1155                 sc->dflt_mode.rate = sc->mode.rate = stat[2];
 1156                 sc->dflt_mode.resolution = sc->mode.resolution = stat[1];
 1157         } else {
 1158                 sc->dflt_mode.rate = sc->mode.rate = -1;
 1159                 sc->dflt_mode.resolution = sc->mode.resolution = -1;
 1160         }
 1161 
 1162         /* hardware information */
 1163         sc->hw.iftype = MOUSE_IF_PS2;
 1164 
 1165         /* verify the device is a mouse */
 1166         sc->hw.hwid = get_aux_id(sc->kbdc);
 1167         if (!is_a_mouse(sc->hw.hwid)) {
 1168                 restore_controller(sc->kbdc, command_byte);
 1169                 if (verbose)
 1170                         printf("psm%d: unknown device type (%d).\n", unit,
 1171                             sc->hw.hwid);
 1172                 endprobe(ENXIO);
 1173         }
 1174         switch (sc->hw.hwid) {
 1175         case PSM_BALLPOINT_ID:
 1176                 sc->hw.type = MOUSE_TRACKBALL;
 1177                 break;
 1178         case PSM_MOUSE_ID:
 1179         case PSM_INTELLI_ID:
 1180         case PSM_EXPLORER_ID:
 1181         case PSM_4DMOUSE_ID:
 1182         case PSM_4DPLUS_ID:
 1183                 sc->hw.type = MOUSE_MOUSE;
 1184                 break;
 1185         default:
 1186                 sc->hw.type = MOUSE_UNKNOWN;
 1187                 break;
 1188         }
 1189 
 1190         if (sc->config & PSM_CONFIG_NOIDPROBE) {
 1191                 sc->hw.buttons = 2;
 1192                 i = GENERIC_MOUSE_ENTRY;
 1193         } else {
 1194                 /* # of buttons */
 1195                 sc->hw.buttons = get_mouse_buttons(sc->kbdc);
 1196 
 1197                 /* other parameters */
 1198                 for (i = 0; vendortype[i].probefunc != NULL; ++i)
 1199                         if ((*vendortype[i].probefunc)(sc)) {
 1200                                 if (verbose >= 2)
 1201                                         printf("psm%d: found %s\n", unit,
 1202                                             model_name(vendortype[i].model));
 1203                                 break;
 1204                         }
 1205         }
 1206 
 1207         sc->hw.model = vendortype[i].model;
 1208 
 1209         sc->dflt_mode.level = PSM_LEVEL_BASE;
 1210         sc->dflt_mode.packetsize = MOUSE_PS2_PACKETSIZE;
 1211         sc->dflt_mode.accelfactor = (sc->config & PSM_CONFIG_ACCEL) >> 4;
 1212         if (sc->config & PSM_CONFIG_NOCHECKSYNC)
 1213                 sc->dflt_mode.syncmask[0] = 0;
 1214         else
 1215                 sc->dflt_mode.syncmask[0] = vendortype[i].syncmask;
 1216         if (sc->config & PSM_CONFIG_FORCETAP)
 1217                 sc->dflt_mode.syncmask[0] &= ~MOUSE_PS2_TAP;
 1218         sc->dflt_mode.syncmask[1] = 0;  /* syncbits */
 1219         sc->mode = sc->dflt_mode;
 1220         sc->mode.packetsize = vendortype[i].packetsize;
 1221 
 1222         /* set mouse parameters */
 1223 #if 0
 1224         /*
 1225          * A version of Logitech FirstMouse+ won't report wheel movement,
 1226          * if SET_DEFAULTS is sent...  Don't use this command.
 1227          * This fix was found by Takashi Nishida.
 1228          */
 1229         i = send_aux_command(sc->kbdc, PSMC_SET_DEFAULTS);
 1230         if (verbose >= 2)
 1231                 printf("psm%d: SET_DEFAULTS return code:%04x\n", unit, i);
 1232 #endif
 1233         if (sc->config & PSM_CONFIG_RESOLUTION)
 1234                 sc->mode.resolution =
 1235                     set_mouse_resolution(sc->kbdc,
 1236                     (sc->config & PSM_CONFIG_RESOLUTION) - 1);
 1237         else if (sc->mode.resolution >= 0)
 1238                 sc->mode.resolution =
 1239                     set_mouse_resolution(sc->kbdc, sc->dflt_mode.resolution);
 1240         if (sc->mode.rate > 0)
 1241                 sc->mode.rate =
 1242                     set_mouse_sampling_rate(sc->kbdc, sc->dflt_mode.rate);
 1243         set_mouse_scaling(sc->kbdc, 1);
 1244 
 1245         /* Record sync on the next data packet we see. */
 1246         sc->flags |= PSM_NEED_SYNCBITS;
 1247 
 1248         /* just check the status of the mouse */
 1249         /*
 1250          * NOTE: XXX there are some arcane controller/mouse combinations out
 1251          * there, which hung the controller unless there is data transmission
 1252          * after ACK from the mouse.
 1253          */
 1254         if (get_mouse_status(sc->kbdc, stat, 0, 3) < 3)
 1255                 printf("psm%d: failed to get status.\n", unit);
 1256         else {
 1257                 /*
 1258                  * When in its native mode, some mice operate with different
 1259                  * default parameters than in the PS/2 compatible mode.
 1260                  */
 1261                 sc->dflt_mode.rate = sc->mode.rate = stat[2];
 1262                 sc->dflt_mode.resolution = sc->mode.resolution = stat[1];
 1263         }
 1264 
 1265         /* disable the aux port for now... */
 1266         if (!set_controller_command_byte(sc->kbdc,
 1267             KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS,
 1268             (command_byte & KBD_KBD_CONTROL_BITS) |
 1269             KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
 1270                 /*
 1271                  * this is CONTROLLER ERROR; I don't know the proper way to
 1272                  * recover from this error...
 1273                  */
 1274                 restore_controller(sc->kbdc, command_byte);
 1275                 printf("psm%d: unable to set the command byte.\n", unit);
 1276                 endprobe(ENXIO);
 1277         }
 1278 
 1279         /*
 1280          * Synaptics TouchPad seems to go back to Relative Mode after
 1281          * the previous set_controller_command_byte() call; by issueing
 1282          * a Read Mode Byte command, the touchpad is in Absolute Mode
 1283          * again.
 1284          */
 1285         if (sc->hw.model == MOUSE_MODEL_SYNAPTICS)
 1286                 mouse_ext_command(sc->kbdc, 1);
 1287 
 1288         /* done */
 1289         kbdc_set_device_mask(sc->kbdc, mask | KBD_AUX_CONTROL_BITS);
 1290         kbdc_lock(sc->kbdc, FALSE);
 1291         return (0);
 1292 }
 1293 
 1294 static int
 1295 psmattach(device_t dev)
 1296 {
 1297         int unit = device_get_unit(dev);
 1298         struct psm_softc *sc = device_get_softc(dev);
 1299         int error;
 1300         int rid;
 1301 
 1302         /* Setup initial state */
 1303         sc->state = PSM_VALID;
 1304         callout_handle_init(&sc->callout);
 1305 
 1306         /* Setup our interrupt handler */
 1307         rid = KBDC_RID_AUX;
 1308         sc->intr = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
 1309             RF_SHAREABLE | RF_ACTIVE);
 1310         if (sc->intr == NULL)
 1311                 return (ENXIO);
 1312         error = bus_setup_intr(dev, sc->intr, INTR_TYPE_TTY, NULL, psmintr, sc,
 1313             &sc->ih);
 1314         if (error) {
 1315                 bus_release_resource(dev, SYS_RES_IRQ, rid, sc->intr);
 1316                 return (error);
 1317         }
 1318 
 1319         /* Done */
 1320         sc->dev = make_dev(&psm_cdevsw, PSM_MKMINOR(unit, FALSE), 0, 0, 0666,
 1321             "psm%d", unit);
 1322         sc->bdev = make_dev(&psm_cdevsw, PSM_MKMINOR(unit, TRUE), 0, 0, 0666,
 1323             "bpsm%d", unit);
 1324 
 1325         if (!verbose)
 1326                 printf("psm%d: model %s, device ID %d\n",
 1327                     unit, model_name(sc->hw.model), sc->hw.hwid & 0x00ff);
 1328         else {
 1329                 printf("psm%d: model %s, device ID %d-%02x, %d buttons\n",
 1330                     unit, model_name(sc->hw.model), sc->hw.hwid & 0x00ff,
 1331                     sc->hw.hwid >> 8, sc->hw.buttons);
 1332                 printf("psm%d: config:%08x, flags:%08x, packet size:%d\n",
 1333                     unit, sc->config, sc->flags, sc->mode.packetsize);
 1334                 printf("psm%d: syncmask:%02x, syncbits:%02x\n",
 1335                     unit, sc->mode.syncmask[0], sc->mode.syncmask[1]);
 1336         }
 1337 
 1338         if (bootverbose)
 1339                 --verbose;
 1340 
 1341         return (0);
 1342 }
 1343 
 1344 static int
 1345 psmdetach(device_t dev)
 1346 {
 1347         struct psm_softc *sc;
 1348         int rid;
 1349 
 1350         sc = device_get_softc(dev);
 1351         if (sc->state & PSM_OPEN)
 1352                 return (EBUSY);
 1353 
 1354         rid = KBDC_RID_AUX;
 1355         bus_teardown_intr(dev, sc->intr, sc->ih);
 1356         bus_release_resource(dev, SYS_RES_IRQ, rid, sc->intr);
 1357 
 1358         destroy_dev(sc->dev);
 1359         destroy_dev(sc->bdev);
 1360 
 1361         return (0);
 1362 }
 1363 
 1364 static int
 1365 psmopen(struct cdev *dev, int flag, int fmt, struct thread *td)
 1366 {
 1367         int unit = PSM_UNIT(dev);
 1368         struct psm_softc *sc;
 1369         int command_byte;
 1370         int err;
 1371         int s;
 1372 
 1373         /* Get device data */
 1374         sc = PSM_SOFTC(unit);
 1375         if ((sc == NULL) || (sc->state & PSM_VALID) == 0) {
 1376                 /* the device is no longer valid/functioning */
 1377                 return (ENXIO);
 1378         }
 1379 
 1380         /* Disallow multiple opens */
 1381         if (sc->state & PSM_OPEN)
 1382                 return (EBUSY);
 1383 
 1384         device_busy(devclass_get_device(psm_devclass, unit));
 1385 
 1386         /* Initialize state */
 1387         sc->mode.level = sc->dflt_mode.level;
 1388         sc->mode.protocol = sc->dflt_mode.protocol;
 1389         sc->watchdog = FALSE;
 1390         sc->async = NULL;
 1391 
 1392         /* flush the event queue */
 1393         sc->queue.count = 0;
 1394         sc->queue.head = 0;
 1395         sc->queue.tail = 0;
 1396         sc->status.flags = 0;
 1397         sc->status.button = 0;
 1398         sc->status.obutton = 0;
 1399         sc->status.dx = 0;
 1400         sc->status.dy = 0;
 1401         sc->status.dz = 0;
 1402         sc->button = 0;
 1403         sc->pqueue_start = 0;
 1404         sc->pqueue_end = 0;
 1405 
 1406         /* empty input buffer */
 1407         flushpackets(sc);
 1408         sc->syncerrors = 0;
 1409         sc->pkterrors = 0;
 1410 
 1411         /* don't let timeout routines in the keyboard driver to poll the kbdc */
 1412         if (!kbdc_lock(sc->kbdc, TRUE))
 1413                 return (EIO);
 1414 
 1415         /* save the current controller command byte */
 1416         s = spltty();
 1417         command_byte = get_controller_command_byte(sc->kbdc);
 1418 
 1419         /* enable the aux port and temporalily disable the keyboard */
 1420         if (command_byte == -1 || !set_controller_command_byte(sc->kbdc,
 1421             kbdc_get_device_mask(sc->kbdc),
 1422             KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT |
 1423             KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
 1424                 /* CONTROLLER ERROR; do you know how to get out of this? */
 1425                 kbdc_lock(sc->kbdc, FALSE);
 1426                 splx(s);
 1427                 log(LOG_ERR,
 1428                     "psm%d: unable to set the command byte (psmopen).\n", unit);
 1429                 return (EIO);
 1430         }
 1431         /*
 1432          * Now that the keyboard controller is told not to generate
 1433          * the keyboard and mouse interrupts, call `splx()' to allow
 1434          * the other tty interrupts. The clock interrupt may also occur,
 1435          * but timeout routines will be blocked by the poll flag set
 1436          * via `kbdc_lock()'
 1437          */
 1438         splx(s);
 1439 
 1440         /* enable the mouse device */
 1441         err = doopen(sc, command_byte);
 1442 
 1443         /* done */
 1444         if (err == 0)
 1445                 sc->state |= PSM_OPEN;
 1446         kbdc_lock(sc->kbdc, FALSE);
 1447         return (err);
 1448 }
 1449 
 1450 static int
 1451 psmclose(struct cdev *dev, int flag, int fmt, struct thread *td)
 1452 {
 1453         int unit = PSM_UNIT(dev);
 1454         struct psm_softc *sc = PSM_SOFTC(unit);
 1455         int stat[3];
 1456         int command_byte;
 1457         int s;
 1458 
 1459         /* don't let timeout routines in the keyboard driver to poll the kbdc */
 1460         if (!kbdc_lock(sc->kbdc, TRUE))
 1461                 return (EIO);
 1462 
 1463         /* save the current controller command byte */
 1464         s = spltty();
 1465         command_byte = get_controller_command_byte(sc->kbdc);
 1466         if (command_byte == -1) {
 1467                 kbdc_lock(sc->kbdc, FALSE);
 1468                 splx(s);
 1469                 return (EIO);
 1470         }
 1471 
 1472         /* disable the aux interrupt and temporalily disable the keyboard */
 1473         if (!set_controller_command_byte(sc->kbdc,
 1474             kbdc_get_device_mask(sc->kbdc),
 1475             KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT |
 1476             KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
 1477                 log(LOG_ERR,
 1478                     "psm%d: failed to disable the aux int (psmclose).\n", unit);
 1479                 /* CONTROLLER ERROR;
 1480                  * NOTE: we shall force our way through. Because the only
 1481                  * ill effect we shall see is that we may not be able
 1482                  * to read ACK from the mouse, and it doesn't matter much
 1483                  * so long as the mouse will accept the DISABLE command.
 1484                  */
 1485         }
 1486         splx(s);
 1487 
 1488         /* stop the watchdog timer */
 1489         untimeout(psmtimeout, (void *)(uintptr_t)sc, sc->callout);
 1490         callout_handle_init(&sc->callout);
 1491 
 1492         /* remove anything left in the output buffer */
 1493         empty_aux_buffer(sc->kbdc, 10);
 1494 
 1495         /* disable the aux device, port and interrupt */
 1496         if (sc->state & PSM_VALID) {
 1497                 if (!disable_aux_dev(sc->kbdc)) {
 1498                         /* MOUSE ERROR;
 1499                          * NOTE: we don't return (error) and continue,
 1500                          * pretending we have successfully disabled the device.
 1501                          * It's OK because the interrupt routine will discard
 1502                          * any data from the mouse hereafter.
 1503                          */
 1504                         log(LOG_ERR,
 1505                             "psm%d: failed to disable the device (psmclose).\n",
 1506                             unit);
 1507                 }
 1508 
 1509                 if (get_mouse_status(sc->kbdc, stat, 0, 3) < 3)
 1510                         log(LOG_DEBUG,
 1511                             "psm%d: failed to get status (psmclose).\n", unit);
 1512         }
 1513 
 1514         if (!set_controller_command_byte(sc->kbdc,
 1515             kbdc_get_device_mask(sc->kbdc),
 1516             (command_byte & KBD_KBD_CONTROL_BITS) |
 1517             KBD_DISABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
 1518                 /*
 1519                  * CONTROLLER ERROR;
 1520                  * we shall ignore this error; see the above comment.
 1521                  */
 1522                 log(LOG_ERR,
 1523                     "psm%d: failed to disable the aux port (psmclose).\n",
 1524                     unit);
 1525         }
 1526 
 1527         /* remove anything left in the output buffer */
 1528         empty_aux_buffer(sc->kbdc, 10);
 1529 
 1530         /* clean up and sigio requests */
 1531         if (sc->async != NULL) {
 1532                 funsetown(&sc->async);
 1533                 sc->async = NULL;
 1534         }
 1535 
 1536         /* close is almost always successful */
 1537         sc->state &= ~PSM_OPEN;
 1538         kbdc_lock(sc->kbdc, FALSE);
 1539         device_unbusy(devclass_get_device(psm_devclass, unit));
 1540         return (0);
 1541 }
 1542 
 1543 static int
 1544 tame_mouse(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *status,
 1545     u_char *buf)
 1546 {
 1547         static u_char butmapps2[8] = {
 1548                 0,
 1549                 MOUSE_PS2_BUTTON1DOWN,
 1550                 MOUSE_PS2_BUTTON2DOWN,
 1551                 MOUSE_PS2_BUTTON1DOWN | MOUSE_PS2_BUTTON2DOWN,
 1552                 MOUSE_PS2_BUTTON3DOWN,
 1553                 MOUSE_PS2_BUTTON1DOWN | MOUSE_PS2_BUTTON3DOWN,
 1554                 MOUSE_PS2_BUTTON2DOWN | MOUSE_PS2_BUTTON3DOWN,
 1555                 MOUSE_PS2_BUTTON1DOWN | MOUSE_PS2_BUTTON2DOWN |
 1556                     MOUSE_PS2_BUTTON3DOWN,
 1557         };
 1558         static u_char butmapmsc[8] = {
 1559                 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP |
 1560                     MOUSE_MSC_BUTTON3UP,
 1561                 MOUSE_MSC_BUTTON2UP | MOUSE_MSC_BUTTON3UP,
 1562                 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON3UP,
 1563                 MOUSE_MSC_BUTTON3UP,
 1564                 MOUSE_MSC_BUTTON1UP | MOUSE_MSC_BUTTON2UP,
 1565                 MOUSE_MSC_BUTTON2UP,
 1566                 MOUSE_MSC_BUTTON1UP,
 1567                 0,
 1568         };
 1569         int mapped;
 1570         int i;
 1571 
 1572         if (sc->mode.level == PSM_LEVEL_BASE) {
 1573                 mapped = status->button & ~MOUSE_BUTTON4DOWN;
 1574                 if (status->button & MOUSE_BUTTON4DOWN)
 1575                         mapped |= MOUSE_BUTTON1DOWN;
 1576                 status->button = mapped;
 1577                 buf[0] = MOUSE_PS2_SYNC | butmapps2[mapped & MOUSE_STDBUTTONS];
 1578                 i = imax(imin(status->dx, 255), -256);
 1579                 if (i < 0)
 1580                         buf[0] |= MOUSE_PS2_XNEG;
 1581                 buf[1] = i;
 1582                 i = imax(imin(status->dy, 255), -256);
 1583                 if (i < 0)
 1584                         buf[0] |= MOUSE_PS2_YNEG;
 1585                 buf[2] = i;
 1586                 return (MOUSE_PS2_PACKETSIZE);
 1587         } else if (sc->mode.level == PSM_LEVEL_STANDARD) {
 1588                 buf[0] = MOUSE_MSC_SYNC |
 1589                     butmapmsc[status->button & MOUSE_STDBUTTONS];
 1590                 i = imax(imin(status->dx, 255), -256);
 1591                 buf[1] = i >> 1;
 1592                 buf[3] = i - buf[1];
 1593                 i = imax(imin(status->dy, 255), -256);
 1594                 buf[2] = i >> 1;
 1595                 buf[4] = i - buf[2];
 1596                 i = imax(imin(status->dz, 127), -128);
 1597                 buf[5] = (i >> 1) & 0x7f;
 1598                 buf[6] = (i - (i >> 1)) & 0x7f;
 1599                 buf[7] = (~status->button >> 3) & 0x7f;
 1600                 return (MOUSE_SYS_PACKETSIZE);
 1601         }
 1602         return (pb->inputbytes);
 1603 }
 1604 
 1605 static int
 1606 psmread(struct cdev *dev, struct uio *uio, int flag)
 1607 {
 1608         register struct psm_softc *sc = PSM_SOFTC(PSM_UNIT(dev));
 1609         u_char buf[PSM_SMALLBUFSIZE];
 1610         int error = 0;
 1611         int s;
 1612         int l;
 1613 
 1614         if ((sc->state & PSM_VALID) == 0)
 1615                 return (EIO);
 1616 
 1617         /* block until mouse activity occured */
 1618         s = spltty();
 1619         while (sc->queue.count <= 0) {
 1620                 if (PSM_NBLOCKIO(dev)) {
 1621                         splx(s);
 1622                         return (EWOULDBLOCK);
 1623                 }
 1624                 sc->state |= PSM_ASLP;
 1625                 error = tsleep(sc, PZERO | PCATCH, "psmrea", 0);
 1626                 sc->state &= ~PSM_ASLP;
 1627                 if (error) {
 1628                         splx(s);
 1629                         return (error);
 1630                 } else if ((sc->state & PSM_VALID) == 0) {
 1631                         /* the device disappeared! */
 1632                         splx(s);
 1633                         return (EIO);
 1634                 }
 1635         }
 1636         splx(s);
 1637 
 1638         /* copy data to the user land */
 1639         while ((sc->queue.count > 0) && (uio->uio_resid > 0)) {
 1640                 s = spltty();
 1641                 l = imin(sc->queue.count, uio->uio_resid);
 1642                 if (l > sizeof(buf))
 1643                         l = sizeof(buf);
 1644                 if (l > sizeof(sc->queue.buf) - sc->queue.head) {
 1645                         bcopy(&sc->queue.buf[sc->queue.head], &buf[0],
 1646                             sizeof(sc->queue.buf) - sc->queue.head);
 1647                         bcopy(&sc->queue.buf[0],
 1648                             &buf[sizeof(sc->queue.buf) - sc->queue.head],
 1649                             l - (sizeof(sc->queue.buf) - sc->queue.head));
 1650                 } else
 1651                         bcopy(&sc->queue.buf[sc->queue.head], &buf[0], l);
 1652                 sc->queue.count -= l;
 1653                 sc->queue.head = (sc->queue.head + l) % sizeof(sc->queue.buf);
 1654                 splx(s);
 1655                 error = uiomove(buf, l, uio);
 1656                 if (error)
 1657                         break;
 1658         }
 1659 
 1660         return (error);
 1661 }
 1662 
 1663 static int
 1664 block_mouse_data(struct psm_softc *sc, int *c)
 1665 {
 1666         int s;
 1667 
 1668         if (!kbdc_lock(sc->kbdc, TRUE))
 1669                 return (EIO);
 1670 
 1671         s = spltty();
 1672         *c = get_controller_command_byte(sc->kbdc);
 1673         if ((*c == -1) || !set_controller_command_byte(sc->kbdc,
 1674             kbdc_get_device_mask(sc->kbdc),
 1675             KBD_DISABLE_KBD_PORT | KBD_DISABLE_KBD_INT |
 1676             KBD_ENABLE_AUX_PORT | KBD_DISABLE_AUX_INT)) {
 1677                 /* this is CONTROLLER ERROR */
 1678                 splx(s);
 1679                 kbdc_lock(sc->kbdc, FALSE);
 1680                 return (EIO);
 1681         }
 1682 
 1683         /*
 1684          * The device may be in the middle of status data transmission.
 1685          * The transmission will be interrupted, thus, incomplete status
 1686          * data must be discarded. Although the aux interrupt is disabled
 1687          * at the keyboard controller level, at most one aux interrupt
 1688          * may have already been pending and a data byte is in the
 1689          * output buffer; throw it away. Note that the second argument
 1690          * to `empty_aux_buffer()' is zero, so that the call will just
 1691          * flush the internal queue.
 1692          * `psmintr()' will be invoked after `splx()' if an interrupt is
 1693          * pending; it will see no data and returns immediately.
 1694          */
 1695         empty_aux_buffer(sc->kbdc, 0);          /* flush the queue */
 1696         read_aux_data_no_wait(sc->kbdc);        /* throw away data if any */
 1697         flushpackets(sc);
 1698         splx(s);
 1699 
 1700         return (0);
 1701 }
 1702 
 1703 static void
 1704 dropqueue(struct psm_softc *sc)
 1705 {
 1706 
 1707         sc->queue.count = 0;
 1708         sc->queue.head = 0;
 1709         sc->queue.tail = 0;
 1710         if ((sc->state & PSM_SOFTARMED) != 0) {
 1711                 sc->state &= ~PSM_SOFTARMED;
 1712                 untimeout(psmsoftintr, (void *)(uintptr_t)sc, sc->softcallout);
 1713         }
 1714         sc->pqueue_start = sc->pqueue_end;
 1715 }
 1716 
 1717 static void
 1718 flushpackets(struct psm_softc *sc)
 1719 {
 1720 
 1721         dropqueue(sc);
 1722         bzero(&sc->pqueue, sizeof(sc->pqueue));
 1723 }
 1724 
 1725 static int
 1726 unblock_mouse_data(struct psm_softc *sc, int c)
 1727 {
 1728         int error = 0;
 1729 
 1730         /*
 1731          * We may have seen a part of status data during `set_mouse_XXX()'.
 1732          * they have been queued; flush it.
 1733          */
 1734         empty_aux_buffer(sc->kbdc, 0);
 1735 
 1736         /* restore ports and interrupt */
 1737         if (!set_controller_command_byte(sc->kbdc,
 1738             kbdc_get_device_mask(sc->kbdc),
 1739             c & (KBD_KBD_CONTROL_BITS | KBD_AUX_CONTROL_BITS))) {
 1740                 /*
 1741                  * CONTROLLER ERROR; this is serious, we may have
 1742                  * been left with the inaccessible keyboard and
 1743                  * the disabled mouse interrupt.
 1744                  */
 1745                 error = EIO;
 1746         }
 1747 
 1748         kbdc_lock(sc->kbdc, FALSE);
 1749         return (error);
 1750 }
 1751 
 1752 static int
 1753 psmwrite(struct cdev *dev, struct uio *uio, int flag)
 1754 {
 1755         register struct psm_softc *sc = PSM_SOFTC(PSM_UNIT(dev));
 1756         u_char buf[PSM_SMALLBUFSIZE];
 1757         int error = 0, i, l;
 1758 
 1759         if ((sc->state & PSM_VALID) == 0)
 1760                 return (EIO);
 1761 
 1762         if (sc->mode.level < PSM_LEVEL_NATIVE)
 1763                 return (ENODEV);
 1764 
 1765         /* copy data from the user land */
 1766         while (uio->uio_resid > 0) {
 1767                 l = imin(PSM_SMALLBUFSIZE, uio->uio_resid);
 1768                 error = uiomove(buf, l, uio);
 1769                 if (error)
 1770                         break;
 1771                 for (i = 0; i < l; i++) {
 1772                         VLOG(4, (LOG_DEBUG, "psm: cmd 0x%x\n", buf[i]));
 1773                         if (!write_aux_command(sc->kbdc, buf[i])) {
 1774                                 VLOG(2, (LOG_DEBUG,
 1775                                     "psm: cmd 0x%x failed.\n", buf[i]));
 1776                                 return (reinitialize(sc, FALSE));
 1777                         }
 1778                 }
 1779         }
 1780 
 1781         return (error);
 1782 }
 1783 
 1784 static int
 1785 psmioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
 1786     struct thread *td)
 1787 {
 1788         struct psm_softc *sc = PSM_SOFTC(PSM_UNIT(dev));
 1789         mousemode_t mode;
 1790         mousestatus_t status;
 1791 #if (defined(MOUSE_GETVARS))
 1792         mousevar_t *var;
 1793 #endif
 1794         mousedata_t *data;
 1795         int stat[3];
 1796         int command_byte;
 1797         int error = 0;
 1798         int s;
 1799 
 1800         /* Perform IOCTL command */
 1801         switch (cmd) {
 1802 
 1803         case OLD_MOUSE_GETHWINFO:
 1804                 s = spltty();
 1805                 ((old_mousehw_t *)addr)->buttons = sc->hw.buttons;
 1806                 ((old_mousehw_t *)addr)->iftype = sc->hw.iftype;
 1807                 ((old_mousehw_t *)addr)->type = sc->hw.type;
 1808                 ((old_mousehw_t *)addr)->hwid = sc->hw.hwid & 0x00ff;
 1809                 splx(s);
 1810                 break;
 1811 
 1812         case MOUSE_GETHWINFO:
 1813                 s = spltty();
 1814                 *(mousehw_t *)addr = sc->hw;
 1815                 if (sc->mode.level == PSM_LEVEL_BASE)
 1816                         ((mousehw_t *)addr)->model = MOUSE_MODEL_GENERIC;
 1817                 splx(s);
 1818                 break;
 1819 
 1820         case MOUSE_SYN_GETHWINFO:
 1821                 s = spltty();
 1822                 if (synaptics_support && sc->hw.model == MOUSE_MODEL_SYNAPTICS)
 1823                         *(synapticshw_t *)addr = sc->synhw;
 1824                 else
 1825                         error = EINVAL;
 1826                 splx(s);
 1827                 break;
 1828 
 1829         case OLD_MOUSE_GETMODE:
 1830                 s = spltty();
 1831                 switch (sc->mode.level) {
 1832                 case PSM_LEVEL_BASE:
 1833                         ((old_mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2;
 1834                         break;
 1835                 case PSM_LEVEL_STANDARD:
 1836                         ((old_mousemode_t *)addr)->protocol =
 1837                             MOUSE_PROTO_SYSMOUSE;
 1838                         break;
 1839                 case PSM_LEVEL_NATIVE:
 1840                         ((old_mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2;
 1841                         break;
 1842                 }
 1843                 ((old_mousemode_t *)addr)->rate = sc->mode.rate;
 1844                 ((old_mousemode_t *)addr)->resolution = sc->mode.resolution;
 1845                 ((old_mousemode_t *)addr)->accelfactor = sc->mode.accelfactor;
 1846                 splx(s);
 1847                 break;
 1848 
 1849         case MOUSE_GETMODE:
 1850                 s = spltty();
 1851                 *(mousemode_t *)addr = sc->mode;
 1852                 if ((sc->flags & PSM_NEED_SYNCBITS) != 0) {
 1853                         ((mousemode_t *)addr)->syncmask[0] = 0;
 1854                         ((mousemode_t *)addr)->syncmask[1] = 0;
 1855                 }
 1856                 ((mousemode_t *)addr)->resolution =
 1857                         MOUSE_RES_LOW - sc->mode.resolution;
 1858                 switch (sc->mode.level) {
 1859                 case PSM_LEVEL_BASE:
 1860                         ((mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2;
 1861                         ((mousemode_t *)addr)->packetsize =
 1862                             MOUSE_PS2_PACKETSIZE;
 1863                         break;
 1864                 case PSM_LEVEL_STANDARD:
 1865                         ((mousemode_t *)addr)->protocol = MOUSE_PROTO_SYSMOUSE;
 1866                         ((mousemode_t *)addr)->packetsize =
 1867                             MOUSE_SYS_PACKETSIZE;
 1868                         ((mousemode_t *)addr)->syncmask[0] = MOUSE_SYS_SYNCMASK;
 1869                         ((mousemode_t *)addr)->syncmask[1] = MOUSE_SYS_SYNC;
 1870                         break;
 1871                 case PSM_LEVEL_NATIVE:
 1872                         /* FIXME: this isn't quite correct... XXX */
 1873                         ((mousemode_t *)addr)->protocol = MOUSE_PROTO_PS2;
 1874                         break;
 1875                 }
 1876                 splx(s);
 1877                 break;
 1878 
 1879         case OLD_MOUSE_SETMODE:
 1880         case MOUSE_SETMODE:
 1881                 if (cmd == OLD_MOUSE_SETMODE) {
 1882                         mode.rate = ((old_mousemode_t *)addr)->rate;
 1883                         /*
 1884                          * resolution  old I/F   new I/F
 1885                          * default        0         0
 1886                          * low            1        -2
 1887                          * medium low     2        -3
 1888                          * medium high    3        -4
 1889                          * high           4        -5
 1890                          */
 1891                         if (((old_mousemode_t *)addr)->resolution > 0)
 1892                                 mode.resolution =
 1893                                     -((old_mousemode_t *)addr)->resolution - 1;
 1894                         else
 1895                                 mode.resolution = 0;
 1896                         mode.accelfactor =
 1897                             ((old_mousemode_t *)addr)->accelfactor;
 1898                         mode.level = -1;
 1899                 } else
 1900                         mode = *(mousemode_t *)addr;
 1901 
 1902                 /* adjust and validate parameters. */
 1903                 if (mode.rate > UCHAR_MAX)
 1904                         return (EINVAL);
 1905                 if (mode.rate == 0)
 1906                         mode.rate = sc->dflt_mode.rate;
 1907                 else if (mode.rate == -1)
 1908                         /* don't change the current setting */
 1909                         ;
 1910                 else if (mode.rate < 0)
 1911                         return (EINVAL);
 1912                 if (mode.resolution >= UCHAR_MAX)
 1913                         return (EINVAL);
 1914                 if (mode.resolution >= 200)
 1915                         mode.resolution = MOUSE_RES_HIGH;
 1916                 else if (mode.resolution >= 100)
 1917                         mode.resolution = MOUSE_RES_MEDIUMHIGH;
 1918                 else if (mode.resolution >= 50)
 1919                         mode.resolution = MOUSE_RES_MEDIUMLOW;
 1920                 else if (mode.resolution > 0)
 1921                         mode.resolution = MOUSE_RES_LOW;
 1922                 if (mode.resolution == MOUSE_RES_DEFAULT)
 1923                         mode.resolution = sc->dflt_mode.resolution;
 1924                 else if (mode.resolution == -1)
 1925                         /* don't change the current setting */
 1926                         ;
 1927                 else if (mode.resolution < 0) /* MOUSE_RES_LOW/MEDIUM/HIGH */
 1928                         mode.resolution = MOUSE_RES_LOW - mode.resolution;
 1929                 if (mode.level == -1)
 1930                         /* don't change the current setting */
 1931                         mode.level = sc->mode.level;
 1932                 else if ((mode.level < PSM_LEVEL_MIN) ||
 1933                     (mode.level > PSM_LEVEL_MAX))
 1934                         return (EINVAL);
 1935                 if (mode.accelfactor == -1)
 1936                         /* don't change the current setting */
 1937                         mode.accelfactor = sc->mode.accelfactor;
 1938                 else if (mode.accelfactor < 0)
 1939                         return (EINVAL);
 1940 
 1941                 /* don't allow anybody to poll the keyboard controller */
 1942                 error = block_mouse_data(sc, &command_byte);
 1943                 if (error)
 1944                         return (error);
 1945 
 1946                 /* set mouse parameters */
 1947                 if (mode.rate > 0)
 1948                         mode.rate = set_mouse_sampling_rate(sc->kbdc,
 1949                             mode.rate);
 1950                 if (mode.resolution >= 0)
 1951                         mode.resolution =
 1952                             set_mouse_resolution(sc->kbdc, mode.resolution);
 1953                 set_mouse_scaling(sc->kbdc, 1);
 1954                 get_mouse_status(sc->kbdc, stat, 0, 3);
 1955 
 1956                 s = spltty();
 1957                 sc->mode.rate = mode.rate;
 1958                 sc->mode.resolution = mode.resolution;
 1959                 sc->mode.accelfactor = mode.accelfactor;
 1960                 sc->mode.level = mode.level;
 1961                 splx(s);
 1962 
 1963                 unblock_mouse_data(sc, command_byte);
 1964                 break;
 1965 
 1966         case MOUSE_GETLEVEL:
 1967                 *(int *)addr = sc->mode.level;
 1968                 break;
 1969 
 1970         case MOUSE_SETLEVEL:
 1971                 if ((*(int *)addr < PSM_LEVEL_MIN) ||
 1972                     (*(int *)addr > PSM_LEVEL_MAX))
 1973                         return (EINVAL);
 1974                 sc->mode.level = *(int *)addr;
 1975                 break;
 1976 
 1977         case MOUSE_GETSTATUS:
 1978                 s = spltty();
 1979                 status = sc->status;
 1980                 sc->status.flags = 0;
 1981                 sc->status.obutton = sc->status.button;
 1982                 sc->status.button = 0;
 1983                 sc->status.dx = 0;
 1984                 sc->status.dy = 0;
 1985                 sc->status.dz = 0;
 1986                 splx(s);
 1987                 *(mousestatus_t *)addr = status;
 1988                 break;
 1989 
 1990 #if (defined(MOUSE_GETVARS))
 1991         case MOUSE_GETVARS:
 1992                 var = (mousevar_t *)addr;
 1993                 bzero(var, sizeof(*var));
 1994                 s = spltty();
 1995                 var->var[0] = MOUSE_VARS_PS2_SIG;
 1996                 var->var[1] = sc->config;
 1997                 var->var[2] = sc->flags;
 1998                 splx(s);
 1999                 break;
 2000 
 2001         case MOUSE_SETVARS:
 2002                 return (ENODEV);
 2003 #endif /* MOUSE_GETVARS */
 2004 
 2005         case MOUSE_READSTATE:
 2006         case MOUSE_READDATA:
 2007                 data = (mousedata_t *)addr;
 2008                 if (data->len > sizeof(data->buf)/sizeof(data->buf[0]))
 2009                         return (EINVAL);
 2010 
 2011                 error = block_mouse_data(sc, &command_byte);
 2012                 if (error)
 2013                         return (error);
 2014                 if ((data->len = get_mouse_status(sc->kbdc, data->buf,
 2015                     (cmd == MOUSE_READDATA) ? 1 : 0, data->len)) <= 0)
 2016                         error = EIO;
 2017                 unblock_mouse_data(sc, command_byte);
 2018                 break;
 2019 
 2020 #if (defined(MOUSE_SETRESOLUTION))
 2021         case MOUSE_SETRESOLUTION:
 2022                 mode.resolution = *(int *)addr;
 2023                 if (mode.resolution >= UCHAR_MAX)
 2024                         return (EINVAL);
 2025                 else if (mode.resolution >= 200)
 2026                         mode.resolution = MOUSE_RES_HIGH;
 2027                 else if (mode.resolution >= 100)
 2028                         mode.resolution = MOUSE_RES_MEDIUMHIGH;
 2029                 else if (mode.resolution >= 50)
 2030                         mode.resolution = MOUSE_RES_MEDIUMLOW;
 2031                 else if (mode.resolution > 0)
 2032                         mode.resolution = MOUSE_RES_LOW;
 2033                 if (mode.resolution == MOUSE_RES_DEFAULT)
 2034                         mode.resolution = sc->dflt_mode.resolution;
 2035                 else if (mode.resolution == -1)
 2036                         mode.resolution = sc->mode.resolution;
 2037                 else if (mode.resolution < 0) /* MOUSE_RES_LOW/MEDIUM/HIGH */
 2038                         mode.resolution = MOUSE_RES_LOW - mode.resolution;
 2039 
 2040                 error = block_mouse_data(sc, &command_byte);
 2041                 if (error)
 2042                         return (error);
 2043                 sc->mode.resolution =
 2044                     set_mouse_resolution(sc->kbdc, mode.resolution);
 2045                 if (sc->mode.resolution != mode.resolution)
 2046                         error = EIO;
 2047                 unblock_mouse_data(sc, command_byte);
 2048                 break;
 2049 #endif /* MOUSE_SETRESOLUTION */
 2050 
 2051 #if (defined(MOUSE_SETRATE))
 2052         case MOUSE_SETRATE:
 2053                 mode.rate = *(int *)addr;
 2054                 if (mode.rate > UCHAR_MAX)
 2055                         return (EINVAL);
 2056                 if (mode.rate == 0)
 2057                         mode.rate = sc->dflt_mode.rate;
 2058                 else if (mode.rate < 0)
 2059                         mode.rate = sc->mode.rate;
 2060 
 2061                 error = block_mouse_data(sc, &command_byte);
 2062                 if (error)
 2063                         return (error);
 2064                 sc->mode.rate = set_mouse_sampling_rate(sc->kbdc, mode.rate);
 2065                 if (sc->mode.rate != mode.rate)
 2066                         error = EIO;
 2067                 unblock_mouse_data(sc, command_byte);
 2068                 break;
 2069 #endif /* MOUSE_SETRATE */
 2070 
 2071 #if (defined(MOUSE_SETSCALING))
 2072         case MOUSE_SETSCALING:
 2073                 if ((*(int *)addr <= 0) || (*(int *)addr > 2))
 2074                         return (EINVAL);
 2075 
 2076                 error = block_mouse_data(sc, &command_byte);
 2077                 if (error)
 2078                         return (error);
 2079                 if (!set_mouse_scaling(sc->kbdc, *(int *)addr))
 2080                         error = EIO;
 2081                 unblock_mouse_data(sc, command_byte);
 2082                 break;
 2083 #endif /* MOUSE_SETSCALING */
 2084 
 2085 #if (defined(MOUSE_GETHWID))
 2086         case MOUSE_GETHWID:
 2087                 error = block_mouse_data(sc, &command_byte);
 2088                 if (error)
 2089                         return (error);
 2090                 sc->hw.hwid &= ~0x00ff;
 2091                 sc->hw.hwid |= get_aux_id(sc->kbdc);
 2092                 *(int *)addr = sc->hw.hwid & 0x00ff;
 2093                 unblock_mouse_data(sc, command_byte);
 2094                 break;
 2095 #endif /* MOUSE_GETHWID */
 2096 
 2097         case FIONBIO:
 2098         case FIOASYNC:
 2099                 break;
 2100         case FIOSETOWN:
 2101                 error = fsetown(*(int *)addr, &sc->async);
 2102                 break;
 2103         case FIOGETOWN:
 2104                 *(int *) addr = fgetown(&sc->async);
 2105                 break;
 2106         default:
 2107                 return (ENOTTY);
 2108         }
 2109 
 2110         return (error);
 2111 }
 2112 
 2113 static void
 2114 psmtimeout(void *arg)
 2115 {
 2116         struct psm_softc *sc;
 2117         int s;
 2118 
 2119         sc = (struct psm_softc *)arg;
 2120         s = spltty();
 2121         if (sc->watchdog && kbdc_lock(sc->kbdc, TRUE)) {
 2122                 VLOG(4, (LOG_DEBUG, "psm%d: lost interrupt?\n", sc->unit));
 2123                 psmintr(sc);
 2124                 kbdc_lock(sc->kbdc, FALSE);
 2125         }
 2126         sc->watchdog = TRUE;
 2127         splx(s);
 2128         sc->callout = timeout(psmtimeout, (void *)(uintptr_t)sc, hz);
 2129 }
 2130 
 2131 /* Add all sysctls under the debug.psm and hw.psm nodes */
 2132 SYSCTL_NODE(_debug, OID_AUTO, psm, CTLFLAG_RD, 0, "ps/2 mouse");
 2133 SYSCTL_NODE(_hw, OID_AUTO, psm, CTLFLAG_RD, 0, "ps/2 mouse");
 2134 
 2135 SYSCTL_INT(_debug_psm, OID_AUTO, loglevel, CTLFLAG_RW, &verbose, 0, "");
 2136 
 2137 static int psmhz = 20;
 2138 SYSCTL_INT(_debug_psm, OID_AUTO, hz, CTLFLAG_RW, &psmhz, 0, "");
 2139 static int psmerrsecs = 2;
 2140 SYSCTL_INT(_debug_psm, OID_AUTO, errsecs, CTLFLAG_RW, &psmerrsecs, 0, "");
 2141 static int psmerrusecs = 0;
 2142 SYSCTL_INT(_debug_psm, OID_AUTO, errusecs, CTLFLAG_RW, &psmerrusecs, 0, "");
 2143 static int psmsecs = 0;
 2144 SYSCTL_INT(_debug_psm, OID_AUTO, secs, CTLFLAG_RW, &psmsecs, 0, "");
 2145 static int psmusecs = 500000;
 2146 SYSCTL_INT(_debug_psm, OID_AUTO, usecs, CTLFLAG_RW, &psmusecs, 0, "");
 2147 static int pkterrthresh = 2;
 2148 SYSCTL_INT(_debug_psm, OID_AUTO, pkterrthresh, CTLFLAG_RW, &pkterrthresh,
 2149     0, "");
 2150 
 2151 static int tap_threshold = PSM_TAP_THRESHOLD;
 2152 SYSCTL_INT(_hw_psm, OID_AUTO, tap_threshold, CTLFLAG_RW, &tap_threshold, 0, "");
 2153 static int tap_timeout = PSM_TAP_TIMEOUT;
 2154 SYSCTL_INT(_hw_psm, OID_AUTO, tap_timeout, CTLFLAG_RW, &tap_timeout, 0, "");
 2155 
 2156 static void
 2157 psmintr(void *arg)
 2158 {
 2159         struct psm_softc *sc = arg;
 2160         struct timeval now;
 2161         int c;
 2162         packetbuf_t *pb;
 2163 
 2164 
 2165         /* read until there is nothing to read */
 2166         while((c = read_aux_data_no_wait(sc->kbdc)) != -1) {
 2167                 pb = &sc->pqueue[sc->pqueue_end];
 2168 
 2169                 /* discard the byte if the device is not open */
 2170                 if ((sc->state & PSM_OPEN) == 0)
 2171                         continue;
 2172 
 2173                 getmicrouptime(&now);
 2174                 if ((pb->inputbytes > 0) &&
 2175                     timevalcmp(&now, &sc->inputtimeout, >)) {
 2176                         VLOG(3, (LOG_DEBUG, "psmintr: delay too long; "
 2177                             "resetting byte count\n"));
 2178                         pb->inputbytes = 0;
 2179                         sc->syncerrors = 0;
 2180                         sc->pkterrors = 0;
 2181                 }
 2182                 sc->inputtimeout.tv_sec = PSM_INPUT_TIMEOUT / 1000000;
 2183                 sc->inputtimeout.tv_usec = PSM_INPUT_TIMEOUT % 1000000;
 2184                 timevaladd(&sc->inputtimeout, &now);
 2185 
 2186                 pb->ipacket[pb->inputbytes++] = c;
 2187 
 2188                 if (sc->mode.level == PSM_LEVEL_NATIVE) {
 2189                         VLOG(4, (LOG_DEBUG, "psmintr: %02x\n", pb->ipacket[0]));
 2190                         sc->syncerrors = 0;
 2191                         sc->pkterrors = 0;
 2192                         goto next;
 2193                 } else {
 2194                         if (pb->inputbytes < sc->mode.packetsize)
 2195                                 continue;
 2196 
 2197                         VLOG(4, (LOG_DEBUG,
 2198                             "psmintr: %02x %02x %02x %02x %02x %02x\n",
 2199                             pb->ipacket[0], pb->ipacket[1], pb->ipacket[2],
 2200                             pb->ipacket[3], pb->ipacket[4], pb->ipacket[5]));
 2201                 }
 2202 
 2203                 c = pb->ipacket[0];
 2204 
 2205                 if ((sc->flags & PSM_NEED_SYNCBITS) != 0) {
 2206                         sc->mode.syncmask[1] = (c & sc->mode.syncmask[0]);
 2207                         sc->flags &= ~PSM_NEED_SYNCBITS;
 2208                         VLOG(2, (LOG_DEBUG,
 2209                             "psmintr: Sync bytes now %04x,%04x\n",
 2210                             sc->mode.syncmask[0], sc->mode.syncmask[0]));
 2211                 } else if ((c & sc->mode.syncmask[0]) != sc->mode.syncmask[1]) {
 2212                         VLOG(3, (LOG_DEBUG, "psmintr: out of sync "
 2213                             "(%04x != %04x) %d cmds since last error.\n",
 2214                             c & sc->mode.syncmask[0], sc->mode.syncmask[1],
 2215                             sc->cmdcount - sc->lasterr));
 2216                         sc->lasterr = sc->cmdcount;
 2217                         /*
 2218                          * The sync byte test is a weak measure of packet
 2219                          * validity.  Conservatively discard any input yet
 2220                          * to be seen by userland when we detect a sync
 2221                          * error since there is a good chance some of
 2222                          * the queued packets have undetected errors.
 2223                          */
 2224                         dropqueue(sc);
 2225                         if (sc->syncerrors == 0)
 2226                                 sc->pkterrors++;
 2227                         ++sc->syncerrors;
 2228                         sc->lastinputerr = now;
 2229                         if (sc->syncerrors >= sc->mode.packetsize * 2 ||
 2230                             sc->pkterrors >= pkterrthresh) {
 2231                                 /*
 2232                                  * If we've failed to find a single sync byte
 2233                                  * in 2 packets worth of data, or we've seen
 2234                                  * persistent packet errors during the
 2235                                  * validation period, reinitialize the mouse
 2236                                  * in hopes of returning it to the expected
 2237                                  * mode.
 2238                                  */
 2239                                 VLOG(3, (LOG_DEBUG,
 2240                                     "psmintr: reset the mouse.\n"));
 2241                                 reinitialize(sc, TRUE);
 2242                         } else if (sc->syncerrors == sc->mode.packetsize) {
 2243                                 /*
 2244                                  * Try a soft reset after searching for a sync
 2245                                  * byte through a packet length of bytes.
 2246                                  */
 2247                                 VLOG(3, (LOG_DEBUG,
 2248                                     "psmintr: re-enable the mouse.\n"));
 2249                                 pb->inputbytes = 0;
 2250                                 disable_aux_dev(sc->kbdc);
 2251                                 enable_aux_dev(sc->kbdc);
 2252                         } else {
 2253                                 VLOG(3, (LOG_DEBUG,
 2254                                     "psmintr: discard a byte (%d)\n",
 2255                                     sc->syncerrors));
 2256                                 pb->inputbytes--;
 2257                                 bcopy(&pb->ipacket[1], &pb->ipacket[0],
 2258                                     pb->inputbytes);
 2259                         }
 2260                         continue;
 2261                 }
 2262 
 2263                 /*
 2264                  * We have what appears to be a valid packet.
 2265                  * Reset the error counters.
 2266                  */
 2267                 sc->syncerrors = 0;
 2268 
 2269                 /*
 2270                  * Drop even good packets if they occur within a timeout
 2271                  * period of a sync error.  This allows the detection of
 2272                  * a change in the mouse's packet mode without exposing
 2273                  * erratic mouse behavior to the user.  Some KVMs forget
 2274                  * enhanced mouse modes during switch events.
 2275                  */
 2276                 if (!timeelapsed(&sc->lastinputerr, psmerrsecs, psmerrusecs,
 2277                     &now)) {
 2278                         pb->inputbytes = 0;
 2279                         continue;
 2280                 }
 2281 
 2282                 /*
 2283                  * Now that we're out of the validation period, reset
 2284                  * the packet error count.
 2285                  */
 2286                 sc->pkterrors = 0;
 2287 
 2288                 sc->cmdcount++;
 2289 next:
 2290                 if (++sc->pqueue_end >= PSM_PACKETQUEUE)
 2291                         sc->pqueue_end = 0;
 2292                 /*
 2293                  * If we've filled the queue then call the softintr ourselves,
 2294                  * otherwise schedule the interrupt for later.
 2295                  */
 2296                 if (!timeelapsed(&sc->lastsoftintr, psmsecs, psmusecs, &now) ||
 2297                     (sc->pqueue_end == sc->pqueue_start)) {
 2298                         if ((sc->state & PSM_SOFTARMED) != 0) {
 2299                                 sc->state &= ~PSM_SOFTARMED;
 2300                                 untimeout(psmsoftintr, arg, sc->softcallout);
 2301                         }
 2302                         psmsoftintr(arg);
 2303                 } else if ((sc->state & PSM_SOFTARMED) == 0) {
 2304                         sc->state |= PSM_SOFTARMED;
 2305                         sc->softcallout = timeout(psmsoftintr, arg,
 2306                             psmhz < 1 ? 1 : (hz/psmhz));
 2307                 }
 2308         }
 2309 }
 2310 
 2311 static void
 2312 proc_mmanplus(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms,
 2313     int *x, int *y, int *z)
 2314 {
 2315 
 2316         /*
 2317          * PS2++ protocl packet
 2318          *
 2319          *          b7 b6 b5 b4 b3 b2 b1 b0
 2320          * byte 1:  *  1  p3 p2 1  *  *  *
 2321          * byte 2:  c1 c2 p1 p0 d1 d0 1  0
 2322          *
 2323          * p3-p0: packet type
 2324          * c1, c2: c1 & c2 == 1, if p2 == 0
 2325          *         c1 & c2 == 0, if p2 == 1
 2326          *
 2327          * packet type: 0 (device type)
 2328          * See comments in enable_mmanplus() below.
 2329          *
 2330          * packet type: 1 (wheel data)
 2331          *
 2332          *          b7 b6 b5 b4 b3 b2 b1 b0
 2333          * byte 3:  h  *  B5 B4 s  d2 d1 d0
 2334          *
 2335          * h: 1, if horizontal roller data
 2336          *    0, if vertical roller data
 2337          * B4, B5: button 4 and 5
 2338          * s: sign bit
 2339          * d2-d0: roller data
 2340          *
 2341          * packet type: 2 (reserved)
 2342          */
 2343         if (((pb->ipacket[0] & MOUSE_PS2PLUS_SYNCMASK) == MOUSE_PS2PLUS_SYNC) &&
 2344             (abs(*x) > 191) && MOUSE_PS2PLUS_CHECKBITS(pb->ipacket)) {
 2345                 /*
 2346                  * the extended data packet encodes button
 2347                  * and wheel events
 2348                  */
 2349                 switch (MOUSE_PS2PLUS_PACKET_TYPE(pb->ipacket)) {
 2350                 case 1:
 2351                         /* wheel data packet */
 2352                         *x = *y = 0;
 2353                         if (pb->ipacket[2] & 0x80) {
 2354                                 /* XXX horizontal roller count - ignore it */
 2355                                 ;
 2356                         } else {
 2357                                 /* vertical roller count */
 2358                                 *z = (pb->ipacket[2] & MOUSE_PS2PLUS_ZNEG) ?
 2359                                     (pb->ipacket[2] & 0x0f) - 16 :
 2360                                     (pb->ipacket[2] & 0x0f);
 2361                         }
 2362                         ms->button |= (pb->ipacket[2] &
 2363                             MOUSE_PS2PLUS_BUTTON4DOWN) ?
 2364                             MOUSE_BUTTON4DOWN : 0;
 2365                         ms->button |= (pb->ipacket[2] &
 2366                             MOUSE_PS2PLUS_BUTTON5DOWN) ?
 2367                             MOUSE_BUTTON5DOWN : 0;
 2368                         break;
 2369                 case 2:
 2370                         /*
 2371                          * this packet type is reserved by
 2372                          * Logitech...
 2373                          */
 2374                         /*
 2375                          * IBM ScrollPoint Mouse uses this
 2376                          * packet type to encode both vertical
 2377                          * and horizontal scroll movement.
 2378                          */
 2379                         *x = *y = 0;
 2380                         /* horizontal count */
 2381                         if (pb->ipacket[2] & 0x0f)
 2382                                 *z = (pb->ipacket[2] & MOUSE_SPOINT_WNEG) ?
 2383                                     -2 : 2;
 2384                         /* vertical count */
 2385                         if (pb->ipacket[2] & 0xf0)
 2386                                 *z = (pb->ipacket[2] & MOUSE_SPOINT_ZNEG) ?
 2387                                     -1 : 1;
 2388                         break;
 2389                 case 0:
 2390                         /* device type packet - shouldn't happen */
 2391                         /* FALLTHROUGH */
 2392                 default:
 2393                         *x = *y = 0;
 2394                         ms->button = ms->obutton;
 2395                         VLOG(1, (LOG_DEBUG, "psmintr: unknown PS2++ packet "
 2396                             "type %d: 0x%02x 0x%02x 0x%02x\n",
 2397                             MOUSE_PS2PLUS_PACKET_TYPE(pb->ipacket),
 2398                             pb->ipacket[0], pb->ipacket[1], pb->ipacket[2]));
 2399                         break;
 2400                 }
 2401         } else {
 2402                 /* preserve button states */
 2403                 ms->button |= ms->obutton & MOUSE_EXTBUTTONS;
 2404         }
 2405 }
 2406 
 2407 static int
 2408 proc_synaptics(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms,
 2409     int *x, int *y, int *z)
 2410 {
 2411         static int touchpad_buttons;
 2412         static int guest_buttons;
 2413         int w, x0, y0, xavg, yavg, xsensitivity, ysensitivity, sensitivity = 0;
 2414 
 2415         /* TouchPad PS/2 absolute mode message format
 2416          *
 2417          *  Bits:        7   6   5   4   3   2   1   0 (LSB)
 2418          *  ------------------------------------------------
 2419          *  ipacket[0]:  1   0  W3  W2   0  W1   R   L
 2420          *  ipacket[1]: Yb  Ya  Y9  Y8  Xb  Xa  X9  X8
 2421          *  ipacket[2]: Z7  Z6  Z5  Z4  Z3  Z2  Z1  Z0
 2422          *  ipacket[3]:  1   1  Yc  Xc   0  W0   D   U
 2423          *  ipacket[4]: X7  X6  X5  X4  X3  X2  X1  X0
 2424          *  ipacket[5]: Y7  Y6  Y5  Y4  Y3  Y2  Y1  Y0
 2425          *
 2426          * Legend:
 2427          *  L: left physical mouse button
 2428          *  R: right physical mouse button
 2429          *  D: down button
 2430          *  U: up button
 2431          *  W: "wrist" value
 2432          *  X: x position
 2433          *  Y: x position
 2434          *  Z: pressure
 2435          *
 2436          * Absolute reportable limits:    0 - 6143.
 2437          * Typical bezel limits:       1472 - 5472.
 2438          * Typical edge marings:       1632 - 5312.
 2439          *
 2440          * w = 3 Passthrough Packet
 2441          *
 2442          * Byte 2,5,6 == Byte 1,2,3 of "Guest"
 2443          */
 2444 
 2445         if (!synaptics_support)
 2446                 return (0);
 2447 
 2448         /* Sanity check for out of sync packets. */
 2449         if ((pb->ipacket[0] & 0xc8) != 0x80 ||
 2450             (pb->ipacket[3] & 0xc8) != 0xc0)
 2451                 return (-1);
 2452 
 2453         *x = *y = x0 = y0 = 0;
 2454 
 2455         /* Pressure value. */
 2456         *z = pb->ipacket[2];
 2457 
 2458         /* Finger width value */
 2459         if (sc->synhw.capExtended)
 2460                 w = ((pb->ipacket[0] & 0x30) >> 2) |
 2461                     ((pb->ipacket[0] & 0x04) >> 1) |
 2462                     ((pb->ipacket[3] & 0x04) >> 2);
 2463         else {
 2464                 /* Assume a finger of regular width */
 2465                 w = 4;
 2466         }
 2467 
 2468         /* Handle packets from the guest device */
 2469         if (w == 3 && sc->synhw.capPassthrough) {
 2470                 *x = ((pb->ipacket[1] & 0x10) ?
 2471                     pb->ipacket[4] - 256 : pb->ipacket[4]);
 2472                 *y = ((pb->ipacket[1] & 0x20) ?
 2473                     pb->ipacket[5] - 256 : pb->ipacket[5]);
 2474                 *z = 0;
 2475 
 2476                 guest_buttons = 0;
 2477                 if (pb->ipacket[1] & 0x01)
 2478                         guest_buttons |= MOUSE_BUTTON1DOWN;
 2479                 if (pb->ipacket[1] & 0x04)
 2480                         guest_buttons |= MOUSE_BUTTON2DOWN;
 2481                 if (pb->ipacket[1] & 0x02)
 2482                         guest_buttons |= MOUSE_BUTTON3DOWN;
 2483 
 2484                 ms->button = touchpad_buttons | guest_buttons;
 2485                 return (0);
 2486         }
 2487 
 2488         /* Button presses */
 2489         touchpad_buttons = 0;
 2490         if (pb->ipacket[0] & 0x01)
 2491                 touchpad_buttons |= MOUSE_BUTTON1DOWN;
 2492         if (pb->ipacket[0] & 0x02)
 2493                 touchpad_buttons |= MOUSE_BUTTON3DOWN;
 2494 
 2495         if (sc->synhw.capExtended && sc->synhw.capFourButtons) {
 2496                 if ((pb->ipacket[3] & 0x01) && (pb->ipacket[0] & 0x01) == 0)
 2497                         touchpad_buttons |= MOUSE_BUTTON4DOWN;
 2498                 if ((pb->ipacket[3] & 0x02) && (pb->ipacket[0] & 0x02) == 0)
 2499                         touchpad_buttons |= MOUSE_BUTTON5DOWN;
 2500         }
 2501 
 2502         /*
 2503          * In newer pads - bit 0x02 in the third byte of
 2504          * the packet indicates that we have an extended
 2505          * button press.
 2506          */
 2507         if (pb->ipacket[3] & 0x02) {
 2508                 /*
 2509                  * if directional_scrolls is not 1, we treat any of
 2510                  * the scrolling directions as middle-click.
 2511                  */
 2512                 if (sc->syninfo.directional_scrolls) {
 2513                         if (pb->ipacket[4] & 0x01)
 2514                                 touchpad_buttons |= MOUSE_BUTTON4DOWN;
 2515                         if (pb->ipacket[5] & 0x01)
 2516                                 touchpad_buttons |= MOUSE_BUTTON5DOWN;
 2517                         if (pb->ipacket[4] & 0x02)
 2518                                 touchpad_buttons |= MOUSE_BUTTON6DOWN;
 2519                         if (pb->ipacket[5] & 0x02)
 2520                                 touchpad_buttons |= MOUSE_BUTTON7DOWN;
 2521                 } else {
 2522                         if ((pb->ipacket[4] & 0x0F) || (pb->ipacket[5] & 0x0F))
 2523                                 touchpad_buttons |= MOUSE_BUTTON2DOWN;
 2524                 }
 2525         }
 2526 
 2527         ms->button = touchpad_buttons | guest_buttons;
 2528 
 2529         /* There is a finger on the pad. */
 2530         if ((w >= 4 && w <= 7) && (*z >= 16 && *z < 200)) {
 2531                 x0 = ((pb->ipacket[3] & 0x10) << 8) |
 2532                     ((pb->ipacket[1] & 0x0f) << 8) | pb->ipacket[4];
 2533                 y0 = ((pb->ipacket[3] & 0x20) << 7) |
 2534                     ((pb->ipacket[1] & 0xf0) << 4) | pb->ipacket[5];
 2535 
 2536                 if (sc->flags & PSM_FLAGS_FINGERDOWN) {
 2537                         *x = x0 - sc->xold;
 2538                         *y = y0 - sc->yold;
 2539 
 2540                         /*
 2541                          * we compute averages of x and y
 2542                          * movement
 2543                          */
 2544                         if (sc->xaverage == 0)
 2545                                 sc->xaverage = *x;
 2546 
 2547                         if (sc->yaverage == 0)
 2548                                 sc->yaverage = *y;
 2549 
 2550                         xavg = sc->xaverage;
 2551                         yavg = sc->yaverage;
 2552 
 2553                         sc->xaverage = (xavg + *x) >> 1;
 2554                         sc->yaverage = (yavg + *y) >> 1;
 2555 
 2556                         /*
 2557                          * then use the averages to compute
 2558                          * a sensitivity level in each dimension
 2559                          */
 2560                         xsensitivity = (sc->xaverage - xavg);
 2561                         if (xsensitivity < 0)
 2562                                 xsensitivity = -xsensitivity;
 2563 
 2564                         ysensitivity = (sc->yaverage - yavg);
 2565                         if (ysensitivity < 0)
 2566                                 ysensitivity = -ysensitivity;
 2567 
 2568                         /*
 2569                          * The sensitivity level is higher the faster
 2570                          * the finger is moving.  It also tends to be
 2571                          * higher in the middle of a touchpad motion
 2572                          * than on either end
 2573                          * Note - sensitivity gets to 0 when moving slowly -
 2574                          * so we add 1 to it to give it a meaningful value
 2575                          * in that case.
 2576                          */
 2577                         sensitivity = (xsensitivity & ysensitivity) + 1;
 2578 
 2579                         /*
 2580                          * If either our x or y change is greater than
 2581                          * our hi/low speed threshold - we do the high-speed
 2582                          * absolute to relative calculation otherwise
 2583                          * we do the low-speed calculation.
 2584                          */
 2585                         if ((*x > sc->syninfo.low_speed_threshold ||
 2586                             *x < -sc->syninfo.low_speed_threshold) ||
 2587                             (*y > sc->syninfo.low_speed_threshold ||
 2588                             *y < -sc->syninfo.low_speed_threshold)) {
 2589                                 x0 = (x0 + sc->xold * 3) / 4;
 2590                                 y0 = (y0 + sc->yold * 3) / 4;
 2591                                 *x = (x0 - sc->xold) * 10 / 85;
 2592                                 *y = (y0 - sc->yold) * 10 / 85;
 2593                         } else {
 2594                                 /*
 2595                                  * This is the low speed calculation.
 2596                                  * We simply check to see if our movement is
 2597                                  * more than our minimum movement threshold
 2598                                  * and if it is - set the movement to 1
 2599                                  * in the correct direction.
 2600                                  * NOTE - Normally this would result
 2601                                  * in pointer movement that was WAY too fast.
 2602                                  * This works due to the movement squelch
 2603                                  * we do later.
 2604                                  */
 2605                                 if (*x < -sc->syninfo.min_movement)
 2606                                         *x = -1;
 2607                                 else if (*x > sc->syninfo.min_movement)
 2608                                         *x = 1;
 2609                                 else
 2610                                         *x = 0;
 2611                                 if (*y < -sc->syninfo.min_movement)
 2612                                         *y = -1;
 2613                                 else if (*y > sc->syninfo.min_movement)
 2614                                         *y = 1;
 2615                                 else
 2616                                         *y = 0;
 2617 
 2618                         }
 2619                 } else
 2620                         sc->flags |= PSM_FLAGS_FINGERDOWN;
 2621 
 2622                 /*
 2623                  * The squelch process.  Take our sensitivity value and
 2624                  * add it to the current squelch value - if squelch is
 2625                  * less than our squelch threshold we kill the movement,
 2626                  * otherwise we reset squelch and pass the movement through.
 2627                  * Since squelch is cumulative - when mouse movement is slow
 2628                  * (around sensitivity 1) the net result is that only 1
 2629                  * out of every squelch_level packets is delivered,
 2630                  * effectively slowing down the movement.
 2631                  */
 2632                 sc->squelch += sensitivity;
 2633                 if (sc->squelch < sc->syninfo.squelch_level) {
 2634                         *x = 0;
 2635                         *y = 0;
 2636                 } else
 2637                         sc->squelch = 0;
 2638 
 2639                 sc->xold = x0;
 2640                 sc->yold = y0;
 2641                 sc->zmax = imax(*z, sc->zmax);
 2642         } else {
 2643                 sc->flags &= ~PSM_FLAGS_FINGERDOWN;
 2644 
 2645                 if (sc->zmax > tap_threshold &&
 2646                     timevalcmp(&sc->lastsoftintr, &sc->taptimeout, <=)) {
 2647                         if (w == 0)
 2648                                 ms->button |= MOUSE_BUTTON3DOWN;
 2649                         else if (w == 1)
 2650                                 ms->button |= MOUSE_BUTTON2DOWN;
 2651                         else
 2652                                 ms->button |= MOUSE_BUTTON1DOWN;
 2653                 }
 2654 
 2655                 sc->zmax = 0;
 2656                 sc->taptimeout.tv_sec = tap_timeout / 1000000;
 2657                 sc->taptimeout.tv_usec = tap_timeout % 1000000;
 2658                 timevaladd(&sc->taptimeout, &sc->lastsoftintr);
 2659         }
 2660 
 2661         /* Use the extra buttons as a scrollwheel */
 2662         if (ms->button & MOUSE_BUTTON4DOWN)
 2663                 *z = -1;
 2664         else if (ms->button & MOUSE_BUTTON5DOWN)
 2665                 *z = 1;
 2666         else
 2667                 *z = 0;
 2668 
 2669         return (0);
 2670 }
 2671 
 2672 static void
 2673 proc_versapad(struct psm_softc *sc, packetbuf_t *pb, mousestatus_t *ms,
 2674     int *x, int *y, int *z)
 2675 {
 2676         static int butmap_versapad[8] = {
 2677                 0,
 2678                 MOUSE_BUTTON3DOWN,
 2679                 0,
 2680                 MOUSE_BUTTON3DOWN,
 2681                 MOUSE_BUTTON1DOWN,
 2682                 MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN,
 2683                 MOUSE_BUTTON1DOWN,
 2684                 MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN
 2685         };
 2686         int c, x0, y0;
 2687 
 2688         /* VersaPad PS/2 absolute mode message format
 2689          *
 2690          * [packet1]     7   6   5   4   3   2   1   0(LSB)
 2691          *  ipacket[0]:  1   1   0   A   1   L   T   R
 2692          *  ipacket[1]: H7  H6  H5  H4  H3  H2  H1  H0
 2693          *  ipacket[2]: V7  V6  V5  V4  V3  V2  V1  V0
 2694          *  ipacket[3]:  1   1   1   A   1   L   T   R
 2695          *  ipacket[4]:V11 V10  V9  V8 H11 H10  H9  H8
 2696          *  ipacket[5]:  0  P6  P5  P4  P3  P2  P1  P0
 2697          *
 2698          * [note]
 2699          *  R: right physical mouse button (1=on)
 2700          *  T: touch pad virtual button (1=tapping)
 2701          *  L: left physical mouse button (1=on)
 2702          *  A: position data is valid (1=valid)
 2703          *  H: horizontal data (12bit signed integer. H11 is sign bit.)
 2704          *  V: vertical data (12bit signed integer. V11 is sign bit.)
 2705          *  P: pressure data
 2706          *
 2707          * Tapping is mapped to MOUSE_BUTTON4.
 2708          */
 2709         c = pb->ipacket[0];
 2710         *x = *y = 0;
 2711         ms->button = butmap_versapad[c & MOUSE_PS2VERSA_BUTTONS];
 2712         ms->button |= (c & MOUSE_PS2VERSA_TAP) ? MOUSE_BUTTON4DOWN : 0;
 2713         if (c & MOUSE_PS2VERSA_IN_USE) {
 2714                 x0 = pb->ipacket[1] | (((pb->ipacket[4]) & 0x0f) << 8);
 2715                 y0 = pb->ipacket[2] | (((pb->ipacket[4]) & 0xf0) << 4);
 2716                 if (x0 & 0x800)
 2717                         x0 -= 0x1000;
 2718                 if (y0 & 0x800)
 2719                         y0 -= 0x1000;
 2720                 if (sc->flags & PSM_FLAGS_FINGERDOWN) {
 2721                         *x = sc->xold - x0;
 2722                         *y = y0 - sc->yold;
 2723                         if (*x < 0)     /* XXX */
 2724                                 ++*x;
 2725                         else if (*x)
 2726                                 --*x;
 2727                         if (*y < 0)
 2728                                 ++*y;
 2729                         else if (*y)
 2730                                 --*y;
 2731                 } else
 2732                         sc->flags |= PSM_FLAGS_FINGERDOWN;
 2733                 sc->xold = x0;
 2734                 sc->yold = y0;
 2735         } else
 2736                 sc->flags &= ~PSM_FLAGS_FINGERDOWN;
 2737 }
 2738 
 2739 static void
 2740 psmsoftintr(void *arg)
 2741 {
 2742         /*
 2743          * the table to turn PS/2 mouse button bits (MOUSE_PS2_BUTTON?DOWN)
 2744          * into `mousestatus' button bits (MOUSE_BUTTON?DOWN).
 2745          */
 2746         static int butmap[8] = {
 2747                 0,
 2748                 MOUSE_BUTTON1DOWN,
 2749                 MOUSE_BUTTON3DOWN,
 2750                 MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN,
 2751                 MOUSE_BUTTON2DOWN,
 2752                 MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN,
 2753                 MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN,
 2754                 MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN
 2755         };
 2756         register struct psm_softc *sc = arg;
 2757         mousestatus_t ms;
 2758         packetbuf_t *pb;
 2759         int x, y, z, c, l, s;
 2760 
 2761         getmicrouptime(&sc->lastsoftintr);
 2762 
 2763         s = spltty();
 2764 
 2765         do {
 2766                 pb = &sc->pqueue[sc->pqueue_start];
 2767 
 2768                 if (sc->mode.level == PSM_LEVEL_NATIVE)
 2769                         goto next_native;
 2770 
 2771                 c = pb->ipacket[0];
 2772                 /*
 2773                  * A kludge for Kensington device!
 2774                  * The MSB of the horizontal count appears to be stored in
 2775                  * a strange place.
 2776                  */
 2777                 if (sc->hw.model == MOUSE_MODEL_THINK)
 2778                         pb->ipacket[1] |= (c & MOUSE_PS2_XOVERFLOW) ? 0x80 : 0;
 2779 
 2780                 /* ignore the overflow bits... */
 2781                 x = (c & MOUSE_PS2_XNEG) ?
 2782                     pb->ipacket[1] - 256 : pb->ipacket[1];
 2783                 y = (c & MOUSE_PS2_YNEG) ?
 2784                     pb->ipacket[2] - 256 : pb->ipacket[2];
 2785                 z = 0;
 2786                 ms.obutton = sc->button;          /* previous button state */
 2787                 ms.button = butmap[c & MOUSE_PS2_BUTTONS];
 2788                 /* `tapping' action */
 2789                 if (sc->config & PSM_CONFIG_FORCETAP)
 2790                         ms.button |= ((c & MOUSE_PS2_TAP)) ?
 2791                             0 : MOUSE_BUTTON4DOWN;
 2792 
 2793                 switch (sc->hw.model) {
 2794 
 2795                 case MOUSE_MODEL_EXPLORER:
 2796                         /*
 2797                          *          b7 b6 b5 b4 b3 b2 b1 b0
 2798                          * byte 1:  oy ox sy sx 1  M  R  L
 2799                          * byte 2:  x  x  x  x  x  x  x  x
 2800                          * byte 3:  y  y  y  y  y  y  y  y
 2801                          * byte 4:  *  *  S2 S1 s  d2 d1 d0
 2802                          *
 2803                          * L, M, R, S1, S2: left, middle, right and side buttons
 2804                          * s: wheel data sign bit
 2805                          * d2-d0: wheel data
 2806                          */
 2807                         z = (pb->ipacket[3] & MOUSE_EXPLORER_ZNEG) ?
 2808                             (pb->ipacket[3] & 0x0f) - 16 :
 2809                             (pb->ipacket[3] & 0x0f);
 2810                         ms.button |=
 2811                             (pb->ipacket[3] & MOUSE_EXPLORER_BUTTON4DOWN) ?
 2812                             MOUSE_BUTTON4DOWN : 0;
 2813                         ms.button |=
 2814                             (pb->ipacket[3] & MOUSE_EXPLORER_BUTTON5DOWN) ?
 2815                             MOUSE_BUTTON5DOWN : 0;
 2816                         break;
 2817 
 2818                 case MOUSE_MODEL_INTELLI:
 2819                 case MOUSE_MODEL_NET:
 2820                         /* wheel data is in the fourth byte */
 2821                         z = (char)pb->ipacket[3];
 2822                         /*
 2823                          * XXX some mice may send 7 when there is no Z movement?                         */
 2824                         if ((z >= 7) || (z <= -7))
 2825                                 z = 0;
 2826                         /* some compatible mice have additional buttons */
 2827                         ms.button |= (c & MOUSE_PS2INTELLI_BUTTON4DOWN) ?
 2828                             MOUSE_BUTTON4DOWN : 0;
 2829                         ms.button |= (c & MOUSE_PS2INTELLI_BUTTON5DOWN) ?
 2830                             MOUSE_BUTTON5DOWN : 0;
 2831                         break;
 2832 
 2833                 case MOUSE_MODEL_MOUSEMANPLUS:
 2834                         proc_mmanplus(sc, pb, &ms, &x, &y, &z);
 2835                         break;
 2836 
 2837                 case MOUSE_MODEL_GLIDEPOINT:
 2838                         /* `tapping' action */
 2839                         ms.button |= ((c & MOUSE_PS2_TAP)) ? 0 :
 2840                             MOUSE_BUTTON4DOWN;
 2841                         break;
 2842 
 2843                 case MOUSE_MODEL_NETSCROLL:
 2844                         /*
 2845                          * three addtional bytes encode buttons and
 2846                          * wheel events
 2847                          */
 2848                         ms.button |= (pb->ipacket[3] & MOUSE_PS2_BUTTON3DOWN) ?
 2849                             MOUSE_BUTTON4DOWN : 0;
 2850                         ms.button |= (pb->ipacket[3] & MOUSE_PS2_BUTTON1DOWN) ?
 2851                             MOUSE_BUTTON5DOWN : 0;
 2852                         z = (pb->ipacket[3] & MOUSE_PS2_XNEG) ?
 2853                             pb->ipacket[4] - 256 : pb->ipacket[4];
 2854                         break;
 2855 
 2856                 case MOUSE_MODEL_THINK:
 2857                         /* the fourth button state in the first byte */
 2858                         ms.button |= (c & MOUSE_PS2_TAP) ?
 2859                             MOUSE_BUTTON4DOWN : 0;
 2860                         break;
 2861 
 2862                 case MOUSE_MODEL_VERSAPAD:
 2863                         proc_versapad(sc, pb, &ms, &x, &y, &z);
 2864                         c = ((x < 0) ? MOUSE_PS2_XNEG : 0) |
 2865                             ((y < 0) ? MOUSE_PS2_YNEG : 0);
 2866                         break;
 2867         
 2868                 case MOUSE_MODEL_4D:
 2869                         /*
 2870                          *          b7 b6 b5 b4 b3 b2 b1 b0
 2871                          * byte 1:  s2 d2 s1 d1 1  M  R  L
 2872                          * byte 2:  sx x  x  x  x  x  x  x
 2873                          * byte 3:  sy y  y  y  y  y  y  y
 2874                          *
 2875                          * s1: wheel 1 direction
 2876                          * d1: wheel 1 data
 2877                          * s2: wheel 2 direction
 2878                          * d2: wheel 2 data
 2879                          */
 2880                         x = (pb->ipacket[1] & 0x80) ?
 2881                             pb->ipacket[1] - 256 : pb->ipacket[1];
 2882                         y = (pb->ipacket[2] & 0x80) ?
 2883                             pb->ipacket[2] - 256 : pb->ipacket[2];
 2884                         switch (c & MOUSE_4D_WHEELBITS) {
 2885                         case 0x10:
 2886                                 z = 1;
 2887                                 break;
 2888                         case 0x30:
 2889                                 z = -1;
 2890                                 break;
 2891                         case 0x40:      /* XXX 2nd wheel turning right */
 2892                                 z = 2;
 2893                                 break;
 2894                         case 0xc0:      /* XXX 2nd wheel turning left */
 2895                                 z = -2;
 2896                                 break;
 2897                         }
 2898                         break;
 2899 
 2900                 case MOUSE_MODEL_4DPLUS:
 2901                         if ((x < 16 - 256) && (y < 16 - 256)) {
 2902                                 /*
 2903                                  *          b7 b6 b5 b4 b3 b2 b1 b0
 2904                                  * byte 1:  0  0  1  1  1  M  R  L
 2905                                  * byte 2:  0  0  0  0  1  0  0  0
 2906                                  * byte 3:  0  0  0  0  S  s  d1 d0
 2907                                  *
 2908                                  * L, M, R, S: left, middle, right,
 2909                                  *             and side buttons
 2910                                  * s: wheel data sign bit
 2911                                  * d1-d0: wheel data
 2912                                  */
 2913                                 x = y = 0;
 2914                                 if (pb->ipacket[2] & MOUSE_4DPLUS_BUTTON4DOWN)
 2915                                         ms.button |= MOUSE_BUTTON4DOWN;
 2916                                 z = (pb->ipacket[2] & MOUSE_4DPLUS_ZNEG) ?
 2917                                     ((pb->ipacket[2] & 0x07) - 8) :
 2918                                     (pb->ipacket[2] & 0x07) ;
 2919                         } else {
 2920                                 /* preserve previous button states */
 2921                                 ms.button |= ms.obutton & MOUSE_EXTBUTTONS;
 2922                         }
 2923                         break;
 2924 
 2925                 case MOUSE_MODEL_SYNAPTICS:
 2926                         if (proc_synaptics(sc, pb, &ms, &x, &y, &z) != 0)
 2927                                 goto next;
 2928                         break;
 2929 
 2930                 case MOUSE_MODEL_GENERIC:
 2931                 default:
 2932                         break;
 2933                 }
 2934 
 2935         /* scale values */
 2936         if (sc->mode.accelfactor >= 1) {
 2937                 if (x != 0) {
 2938                         x = x * x / sc->mode.accelfactor;
 2939                         if (x == 0)
 2940                                 x = 1;
 2941                         if (c & MOUSE_PS2_XNEG)
 2942                                 x = -x;
 2943                 }
 2944                 if (y != 0) {
 2945                         y = y * y / sc->mode.accelfactor;
 2946                         if (y == 0)
 2947                                 y = 1;
 2948                         if (c & MOUSE_PS2_YNEG)
 2949                                 y = -y;
 2950                 }
 2951         }
 2952 
 2953         ms.dx = x;
 2954         ms.dy = y;
 2955         ms.dz = z;
 2956         ms.flags = ((x || y || z) ? MOUSE_POSCHANGED : 0) |
 2957             (ms.obutton ^ ms.button);
 2958 
 2959         pb->inputbytes = tame_mouse(sc, pb, &ms, pb->ipacket);
 2960 
 2961         sc->status.flags |= ms.flags;
 2962         sc->status.dx += ms.dx;
 2963         sc->status.dy += ms.dy;
 2964         sc->status.dz += ms.dz;
 2965         sc->status.button = ms.button;
 2966         sc->button = ms.button;
 2967 
 2968 next_native:
 2969         sc->watchdog = FALSE;
 2970 
 2971         /* queue data */
 2972         if (sc->queue.count + pb->inputbytes < sizeof(sc->queue.buf)) {
 2973                 l = imin(pb->inputbytes,
 2974                     sizeof(sc->queue.buf) - sc->queue.tail);
 2975                 bcopy(&pb->ipacket[0], &sc->queue.buf[sc->queue.tail], l);
 2976                 if (pb->inputbytes > l)
 2977                         bcopy(&pb->ipacket[l], &sc->queue.buf[0],
 2978                             pb->inputbytes - l);
 2979                 sc->queue.tail = (sc->queue.tail + pb->inputbytes) %
 2980                     sizeof(sc->queue.buf);
 2981                 sc->queue.count += pb->inputbytes;
 2982         }
 2983         pb->inputbytes = 0;
 2984 
 2985 next:
 2986         if (++sc->pqueue_start >= PSM_PACKETQUEUE)
 2987                 sc->pqueue_start = 0;
 2988         } while (sc->pqueue_start != sc->pqueue_end);
 2989 
 2990         if (sc->state & PSM_ASLP) {
 2991                 sc->state &= ~PSM_ASLP;
 2992                 wakeup(sc);
 2993         }
 2994         selwakeuppri(&sc->rsel, PZERO);
 2995         if (sc->async != NULL) {
 2996                 pgsigio(&sc->async, SIGIO, 0);
 2997         }
 2998         sc->state &= ~PSM_SOFTARMED;
 2999         splx(s);
 3000 }
 3001 
 3002 static int
 3003 psmpoll(struct cdev *dev, int events, struct thread *td)
 3004 {
 3005         struct psm_softc *sc = PSM_SOFTC(PSM_UNIT(dev));
 3006         int s;
 3007         int revents = 0;
 3008 
 3009         /* Return true if a mouse event available */
 3010         s = spltty();
 3011         if (events & (POLLIN | POLLRDNORM)) {
 3012                 if (sc->queue.count > 0)
 3013                         revents |= events & (POLLIN | POLLRDNORM);
 3014                 else
 3015                         selrecord(td, &sc->rsel);
 3016         }
 3017         splx(s);
 3018 
 3019         return (revents);
 3020 }
 3021 
 3022 /* vendor/model specific routines */
 3023 
 3024 static int mouse_id_proc1(KBDC kbdc, int res, int scale, int *status)
 3025 {
 3026         if (set_mouse_resolution(kbdc, res) != res)
 3027                 return (FALSE);
 3028         if (set_mouse_scaling(kbdc, scale) &&
 3029             set_mouse_scaling(kbdc, scale) &&
 3030             set_mouse_scaling(kbdc, scale) &&
 3031             (get_mouse_status(kbdc, status, 0, 3) >= 3))
 3032                 return (TRUE);
 3033         return (FALSE);
 3034 }
 3035 
 3036 static int
 3037 mouse_ext_command(KBDC kbdc, int command)
 3038 {
 3039         int c;
 3040 
 3041         c = (command >> 6) & 0x03;
 3042         if (set_mouse_resolution(kbdc, c) != c)
 3043                 return (FALSE);
 3044         c = (command >> 4) & 0x03;
 3045         if (set_mouse_resolution(kbdc, c) != c)
 3046                 return (FALSE);
 3047         c = (command >> 2) & 0x03;
 3048         if (set_mouse_resolution(kbdc, c) != c)
 3049                 return (FALSE);
 3050         c = (command >> 0) & 0x03;
 3051         if (set_mouse_resolution(kbdc, c) != c)
 3052                 return (FALSE);
 3053         return (TRUE);
 3054 }
 3055 
 3056 #ifdef notyet
 3057 /* Logitech MouseMan Cordless II */
 3058 static int
 3059 enable_lcordless(struct psm_softc *sc)
 3060 {
 3061         int status[3];
 3062         int ch;
 3063 
 3064         if (!mouse_id_proc1(sc->kbdc, PSMD_RES_HIGH, 2, status))
 3065                 return (FALSE);
 3066         if (status[1] == PSMD_RES_HIGH)
 3067                 return (FALSE);
 3068         ch = (status[0] & 0x07) - 1;    /* channel # */
 3069         if ((ch <= 0) || (ch > 4))
 3070                 return (FALSE);
 3071         /*
 3072          * status[1]: always one?
 3073          * status[2]: battery status? (0-100)
 3074          */
 3075         return (TRUE);
 3076 }
 3077 #endif /* notyet */
 3078 
 3079 /* Genius NetScroll Mouse, MouseSystems SmartScroll Mouse */
 3080 static int
 3081 enable_groller(struct psm_softc *sc)
 3082 {
 3083         int status[3];
 3084 
 3085         /*
 3086          * The special sequence to enable the fourth button and the
 3087          * roller. Immediately after this sequence check status bytes.
 3088          * if the mouse is NetScroll, the second and the third bytes are
 3089          * '3' and 'D'.
 3090          */
 3091 
 3092         /*
 3093          * If the mouse is an ordinary PS/2 mouse, the status bytes should
 3094          * look like the following.
 3095          *
 3096          * byte 1 bit 7 always 0
 3097          *        bit 6 stream mode (0)
 3098          *        bit 5 disabled (0)
 3099          *        bit 4 1:1 scaling (0)
 3100          *        bit 3 always 0
 3101          *        bit 0-2 button status
 3102          * byte 2 resolution (PSMD_RES_HIGH)
 3103          * byte 3 report rate (?)
 3104          */
 3105 
 3106         if (!mouse_id_proc1(sc->kbdc, PSMD_RES_HIGH, 1, status))
 3107                 return (FALSE);
 3108         if ((status[1] != '3') || (status[2] != 'D'))
 3109                 return (FALSE);
 3110         /* FIXME: SmartScroll Mouse has 5 buttons! XXX */
 3111         sc->hw.buttons = 4;
 3112         return (TRUE);
 3113 }
 3114 
 3115 /* Genius NetMouse/NetMouse Pro, ASCII Mie Mouse, NetScroll Optical */
 3116 static int
 3117 enable_gmouse(struct psm_softc *sc)
 3118 {
 3119         int status[3];
 3120 
 3121         /*
 3122          * The special sequence to enable the middle, "rubber" button.
 3123          * Immediately after this sequence check status bytes.
 3124          * if the mouse is NetMouse, NetMouse Pro, or ASCII MIE Mouse,
 3125          * the second and the third bytes are '3' and 'U'.
 3126          * NOTE: NetMouse reports that it has three buttons although it has
 3127          * two buttons and a rubber button. NetMouse Pro and MIE Mouse
 3128          * say they have three buttons too and they do have a button on the
 3129          * side...
 3130          */
 3131         if (!mouse_id_proc1(sc->kbdc, PSMD_RES_HIGH, 1, status))
 3132                 return (FALSE);
 3133         if ((status[1] != '3') || (status[2] != 'U'))
 3134                 return (FALSE);
 3135         return (TRUE);
 3136 }
 3137 
 3138 /* ALPS GlidePoint */
 3139 static int
 3140 enable_aglide(struct psm_softc *sc)
 3141 {
 3142         int status[3];
 3143 
 3144         /*
 3145          * The special sequence to obtain ALPS GlidePoint specific
 3146          * information. Immediately after this sequence, status bytes will
 3147          * contain something interesting.
 3148          * NOTE: ALPS produces several models of GlidePoint. Some of those
 3149          * do not respond to this sequence, thus, cannot be detected this way.
 3150          */
 3151         if (set_mouse_sampling_rate(sc->kbdc, 100) != 100)
 3152                 return (FALSE);
 3153         if (!mouse_id_proc1(sc->kbdc, PSMD_RES_LOW, 2, status))
 3154                 return (FALSE);
 3155         if ((status[1] == PSMD_RES_LOW) || (status[2] == 100))
 3156                 return (FALSE);
 3157         return (TRUE);
 3158 }
 3159 
 3160 /* Kensington ThinkingMouse/Trackball */
 3161 static int
 3162 enable_kmouse(struct psm_softc *sc)
 3163 {
 3164         static u_char rate[] = { 20, 60, 40, 20, 20, 60, 40, 20, 20 };
 3165         KBDC kbdc = sc->kbdc;
 3166         int status[3];
 3167         int id1;
 3168         int id2;
 3169         int i;
 3170 
 3171         id1 = get_aux_id(kbdc);
 3172         if (set_mouse_sampling_rate(kbdc, 10) != 10)
 3173                 return (FALSE);
 3174         /*
 3175          * The device is now in the native mode? It returns a different
 3176          * ID value...
 3177          */
 3178         id2 = get_aux_id(kbdc);
 3179         if ((id1 == id2) || (id2 != 2))
 3180                 return (FALSE);
 3181 
 3182         if (set_mouse_resolution(kbdc, PSMD_RES_LOW) != PSMD_RES_LOW)
 3183                 return (FALSE);
 3184 #if PSM_DEBUG >= 2
 3185         /* at this point, resolution is LOW, sampling rate is 10/sec */
 3186         if (get_mouse_status(kbdc, status, 0, 3) < 3)
 3187                 return (FALSE);
 3188 #endif
 3189 
 3190         /*
 3191          * The special sequence to enable the third and fourth buttons.
 3192          * Otherwise they behave like the first and second buttons.
 3193          */
 3194         for (i = 0; i < sizeof(rate)/sizeof(rate[0]); ++i)
 3195                 if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i])
 3196                         return (FALSE);
 3197 
 3198         /*
 3199          * At this point, the device is using default resolution and
 3200          * sampling rate for the native mode.
 3201          */
 3202         if (get_mouse_status(kbdc, status, 0, 3) < 3)
 3203                 return (FALSE);
 3204         if ((status[1] == PSMD_RES_LOW) || (status[2] == rate[i - 1]))
 3205                 return (FALSE);
 3206 
 3207         /* the device appears be enabled by this sequence, diable it for now */
 3208         disable_aux_dev(kbdc);
 3209         empty_aux_buffer(kbdc, 5);
 3210 
 3211         return (TRUE);
 3212 }
 3213 
 3214 /* Logitech MouseMan+/FirstMouse+, IBM ScrollPoint Mouse */
 3215 static int
 3216 enable_mmanplus(struct psm_softc *sc)
 3217 {
 3218         KBDC kbdc = sc->kbdc;
 3219         int data[3];
 3220 
 3221         /* the special sequence to enable the fourth button and the roller. */
 3222         /*
 3223          * NOTE: for ScrollPoint to respond correctly, the SET_RESOLUTION
 3224          * must be called exactly three times since the last RESET command
 3225          * before this sequence. XXX
 3226          */
 3227         if (!set_mouse_scaling(kbdc, 1))
 3228                 return (FALSE);
 3229         if (!mouse_ext_command(kbdc, 0x39) || !mouse_ext_command(kbdc, 0xdb))
 3230                 return (FALSE);
 3231         if (get_mouse_status(kbdc, data, 1, 3) < 3)
 3232                 return (FALSE);
 3233 
 3234         /*
 3235          * PS2++ protocl, packet type 0
 3236          *
 3237          *          b7 b6 b5 b4 b3 b2 b1 b0
 3238          * byte 1:  *  1  p3 p2 1  *  *  *
 3239          * byte 2:  1  1  p1 p0 m1 m0 1  0
 3240          * byte 3:  m7 m6 m5 m4 m3 m2 m1 m0
 3241          *
 3242          * p3-p0: packet type: 0
 3243          * m7-m0: model ID: MouseMan+:0x50,
 3244          *                  FirstMouse+:0x51,
 3245          *                  ScrollPoint:0x58...
 3246          */
 3247         /* check constant bits */
 3248         if ((data[0] & MOUSE_PS2PLUS_SYNCMASK) != MOUSE_PS2PLUS_SYNC)
 3249                 return (FALSE);
 3250         if ((data[1] & 0xc3) != 0xc2)
 3251                 return (FALSE);
 3252         /* check d3-d0 in byte 2 */
 3253         if (!MOUSE_PS2PLUS_CHECKBITS(data))
 3254                 return (FALSE);
 3255         /* check p3-p0 */
 3256         if (MOUSE_PS2PLUS_PACKET_TYPE(data) != 0)
 3257                 return (FALSE);
 3258 
 3259         sc->hw.hwid &= 0x00ff;
 3260         sc->hw.hwid |= data[2] << 8;    /* save model ID */
 3261 
 3262         /*
 3263          * MouseMan+ (or FirstMouse+) is now in its native mode, in which
 3264          * the wheel and the fourth button events are encoded in the
 3265          * special data packet. The mouse may be put in the IntelliMouse mode
 3266          * if it is initialized by the IntelliMouse's method.
 3267          */
 3268         return (TRUE);
 3269 }
 3270 
 3271 /* MS IntelliMouse Explorer */
 3272 static int
 3273 enable_msexplorer(struct psm_softc *sc)
 3274 {
 3275         static u_char rate0[] = { 200, 100, 80, };
 3276         static u_char rate1[] = { 200, 200, 80, };
 3277         KBDC kbdc = sc->kbdc;
 3278         int id;
 3279         int i;
 3280 
 3281         /*
 3282          * This is needed for at least A4Tech X-7xx mice - they do not go
 3283          * straight to Explorer mode, but need to be set to Intelli mode
 3284          * first.
 3285          */
 3286         enable_msintelli(sc);
 3287 
 3288         /* the special sequence to enable the extra buttons and the roller. */
 3289         for (i = 0; i < sizeof(rate1)/sizeof(rate1[0]); ++i)
 3290                 if (set_mouse_sampling_rate(kbdc, rate1[i]) != rate1[i])
 3291                         return (FALSE);
 3292         /* the device will give the genuine ID only after the above sequence */
 3293         id = get_aux_id(kbdc);
 3294         if (id != PSM_EXPLORER_ID)
 3295                 return (FALSE);
 3296 
 3297         sc->hw.hwid = id;
 3298         sc->hw.buttons = 5;             /* IntelliMouse Explorer XXX */
 3299 
 3300         /*
 3301          * XXX: this is a kludge to fool some KVM switch products
 3302          * which think they are clever enough to know the 4-byte IntelliMouse
 3303          * protocol, and assume any other protocols use 3-byte packets.
 3304          * They don't convey 4-byte data packets from the IntelliMouse Explorer
 3305          * correctly to the host computer because of this!
 3306          * The following sequence is actually IntelliMouse's "wake up"
 3307          * sequence; it will make the KVM think the mouse is IntelliMouse
 3308          * when it is in fact IntelliMouse Explorer.
 3309          */
 3310         for (i = 0; i < sizeof(rate0)/sizeof(rate0[0]); ++i)
 3311                 if (set_mouse_sampling_rate(kbdc, rate0[i]) != rate0[i])
 3312                         break;
 3313         id = get_aux_id(kbdc);
 3314 
 3315         return (TRUE);
 3316 }
 3317 
 3318 /* MS IntelliMouse */
 3319 static int
 3320 enable_msintelli(struct psm_softc *sc)
 3321 {
 3322         /*
 3323          * Logitech MouseMan+ and FirstMouse+ will also respond to this
 3324          * probe routine and act like IntelliMouse.
 3325          */
 3326 
 3327         static u_char rate[] = { 200, 100, 80, };
 3328         KBDC kbdc = sc->kbdc;
 3329         int id;
 3330         int i;
 3331 
 3332         /* the special sequence to enable the third button and the roller. */
 3333         for (i = 0; i < sizeof(rate)/sizeof(rate[0]); ++i)
 3334                 if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i])
 3335                         return (FALSE);
 3336         /* the device will give the genuine ID only after the above sequence */
 3337         id = get_aux_id(kbdc);
 3338         if (id != PSM_INTELLI_ID)
 3339                 return (FALSE);
 3340 
 3341         sc->hw.hwid = id;
 3342         sc->hw.buttons = 3;
 3343 
 3344         return (TRUE);
 3345 }
 3346 
 3347 /* A4 Tech 4D Mouse */
 3348 static int
 3349 enable_4dmouse(struct psm_softc *sc)
 3350 {
 3351         /*
 3352          * Newer wheel mice from A4 Tech may use the 4D+ protocol.
 3353          */
 3354 
 3355         static u_char rate[] = { 200, 100, 80, 60, 40, 20 };
 3356         KBDC kbdc = sc->kbdc;
 3357         int id;
 3358         int i;
 3359 
 3360         for (i = 0; i < sizeof(rate)/sizeof(rate[0]); ++i)
 3361                 if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i])
 3362                         return (FALSE);
 3363         id = get_aux_id(kbdc);
 3364         /*
 3365          * WinEasy 4D, 4 Way Scroll 4D: 6
 3366          * Cable-Free 4D: 8 (4DPLUS)
 3367          * WinBest 4D+, 4 Way Scroll 4D+: 8 (4DPLUS)
 3368          */
 3369         if (id != PSM_4DMOUSE_ID)
 3370                 return (FALSE);
 3371 
 3372         sc->hw.hwid = id;
 3373         sc->hw.buttons = 3;             /* XXX some 4D mice have 4? */
 3374 
 3375         return (TRUE);
 3376 }
 3377 
 3378 /* A4 Tech 4D+ Mouse */
 3379 static int
 3380 enable_4dplus(struct psm_softc *sc)
 3381 {
 3382         /*
 3383          * Newer wheel mice from A4 Tech seem to use this protocol.
 3384          * Older models are recognized as either 4D Mouse or IntelliMouse.
 3385          */
 3386         KBDC kbdc = sc->kbdc;
 3387         int id;
 3388 
 3389         /*
 3390          * enable_4dmouse() already issued the following ID sequence...
 3391         static u_char rate[] = { 200, 100, 80, 60, 40, 20 };
 3392         int i;
 3393 
 3394         for (i = 0; i < sizeof(rate)/sizeof(rate[0]); ++i)
 3395                 if (set_mouse_sampling_rate(kbdc, rate[i]) != rate[i])
 3396                         return (FALSE);
 3397         */
 3398 
 3399         id = get_aux_id(kbdc);
 3400         switch (id) {
 3401         case PSM_4DPLUS_ID:
 3402                 sc->hw.buttons = 4;
 3403                 break;
 3404         case PSM_4DPLUS_RFSW35_ID:
 3405                 sc->hw.buttons = 3;
 3406                 break;
 3407         default:
 3408                 return (FALSE);
 3409         }
 3410 
 3411         sc->hw.hwid = id;
 3412 
 3413         return (TRUE);
 3414 }
 3415 
 3416 /* Synaptics Touchpad */
 3417 static int
 3418 enable_synaptics(struct psm_softc *sc)
 3419 {
 3420         int status[3];
 3421         KBDC kbdc;
 3422 
 3423         if (!synaptics_support)
 3424                 return (FALSE);
 3425 
 3426         /* Attach extra synaptics sysctl nodes under hw.psm.synaptics */
 3427         sysctl_ctx_init(&sc->syninfo.sysctl_ctx);
 3428         sc->syninfo.sysctl_tree = SYSCTL_ADD_NODE(&sc->syninfo.sysctl_ctx,
 3429             SYSCTL_STATIC_CHILDREN(_hw_psm), OID_AUTO, "synaptics", CTLFLAG_RD,
 3430             0, "Synaptics TouchPad");
 3431 
 3432         /*
 3433          * synaptics_directional_scrolls - if non-zero, the directional
 3434          * pad scrolls, otherwise it registers as a middle-click.
 3435          */
 3436         sc->syninfo.directional_scrolls = 1;
 3437         SYSCTL_ADD_INT(&sc->syninfo.sysctl_ctx,
 3438             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
 3439             "directional_scrolls", CTLFLAG_RW,
 3440             &sc->syninfo.directional_scrolls, 0,
 3441             "directional pad scrolls (1=yes  0=3rd button)");
 3442 
 3443         /*
 3444          * Synaptics_low_speed_threshold - the number of touchpad units
 3445          * below-which we go into low-speed tracking mode.
 3446          */
 3447         sc->syninfo.low_speed_threshold = 20;
 3448         SYSCTL_ADD_INT(&sc->syninfo.sysctl_ctx,
 3449             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
 3450             "low_speed_threshold", CTLFLAG_RW,
 3451             &sc->syninfo.low_speed_threshold, 0,
 3452             "threshold between low and hi speed positioning");
 3453 
 3454         /*
 3455          * Synaptics_min_movement - the number of touchpad units below
 3456          * which we ignore altogether.
 3457          */
 3458         sc->syninfo.min_movement = 2;
 3459         SYSCTL_ADD_INT(&sc->syninfo.sysctl_ctx,
 3460             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
 3461             "min_movement", CTLFLAG_RW,
 3462             &sc->syninfo.min_movement, 0,
 3463             "ignore touchpad movements less than this");
 3464 
 3465         /*
 3466          * Synaptics_squelch_level - level at which we squelch movement
 3467          * packets.
 3468          *
 3469          * This effectively sends 1 out of every synaptics_squelch_level
 3470          * packets when * running in low-speed mode.
 3471          */
 3472         sc->syninfo.squelch_level=3;
 3473         SYSCTL_ADD_INT(&sc->syninfo.sysctl_ctx,
 3474             SYSCTL_CHILDREN(sc->syninfo.sysctl_tree), OID_AUTO,
 3475             "squelch_level", CTLFLAG_RW,
 3476             &sc->syninfo.squelch_level, 0,
 3477             "squelch level for synaptics touchpads");
 3478 
 3479         kbdc = sc->kbdc;
 3480         disable_aux_dev(kbdc);
 3481         sc->hw.buttons = 3;
 3482         sc->squelch = 0;
 3483 
 3484         /* Just to be on the safe side */
 3485         set_mouse_scaling(kbdc, 1);
 3486 
 3487         /* Identify the Touchpad version */
 3488         if (mouse_ext_command(kbdc, 0) == 0)
 3489                 return (FALSE);
 3490         if (get_mouse_status(kbdc, status, 0, 3) != 3)
 3491                 return (FALSE);
 3492         if (status[1] != 0x47)
 3493                 return (FALSE);
 3494 
 3495         sc->synhw.infoMinor = status[0];
 3496         sc->synhw.infoMajor = status[2] & 0x0f;
 3497 
 3498         if (verbose >= 2)
 3499                 printf("Synaptics Touchpad v%d.%d\n", sc->synhw.infoMajor,
 3500                     sc->synhw.infoMinor);
 3501 
 3502         if (sc->synhw.infoMajor < 4) {
 3503                 printf("  Unsupported (pre-v4) Touchpad detected\n");
 3504                 return (FALSE);
 3505         }
 3506 
 3507         /* Get the Touchpad model information */
 3508         if (mouse_ext_command(kbdc, 3) == 0)
 3509                 return (FALSE);
 3510         if (get_mouse_status(kbdc, status, 0, 3) != 3)
 3511                 return (FALSE);
 3512         if ((status[1] & 0x01) != 0) {
 3513                 printf("  Failed to read model information\n");
 3514                 return (FALSE);
 3515         }
 3516 
 3517         sc->synhw.infoRot180   = (status[0] & 0x80) >> 7;
 3518         sc->synhw.infoPortrait = (status[0] & 0x40) >> 6;
 3519         sc->synhw.infoSensor   =  status[0] & 0x3f;
 3520         sc->synhw.infoHardware = (status[1] & 0xfe) >> 1;
 3521         sc->synhw.infoNewAbs   = (status[2] & 0x80) >> 7;
 3522         sc->synhw.capPen       = (status[2] & 0x40) >> 6;
 3523         sc->synhw.infoSimplC   = (status[2] & 0x20) >> 5;
 3524         sc->synhw.infoGeometry =  status[2] & 0x0f;
 3525 
 3526         if (verbose >= 2) {
 3527                 printf("  Model information:\n");
 3528                 printf("   infoRot180: %d\n", sc->synhw.infoRot180);
 3529                 printf("   infoPortrait: %d\n", sc->synhw.infoPortrait);
 3530                 printf("   infoSensor: %d\n", sc->synhw.infoSensor);
 3531                 printf("   infoHardware: %d\n", sc->synhw.infoHardware);
 3532                 printf("   infoNewAbs: %d\n", sc->synhw.infoNewAbs);
 3533                 printf("   capPen: %d\n", sc->synhw.capPen);
 3534                 printf("   infoSimplC: %d\n", sc->synhw.infoSimplC);
 3535                 printf("   infoGeometry: %d\n", sc->synhw.infoGeometry);
 3536         }
 3537 
 3538         /* Read the extended capability bits */
 3539         if (mouse_ext_command(kbdc, 2) == 0)
 3540                 return (FALSE);
 3541         if (get_mouse_status(kbdc, status, 0, 3) != 3)
 3542                 return (FALSE);
 3543         if (status[1] != 0x47) {
 3544                 printf("  Failed to read extended capability bits\n");
 3545                 return (FALSE);
 3546         }
 3547 
 3548         /* Set the different capabilities when they exist */
 3549         if ((status[0] & 0x80) >> 7) {
 3550                 sc->synhw.capExtended    = (status[0] & 0x80) >> 7;
 3551                 sc->synhw.capPassthrough = (status[2] & 0x80) >> 7;
 3552                 sc->synhw.capSleep       = (status[2] & 0x10) >> 4;
 3553                 sc->synhw.capFourButtons = (status[2] & 0x08) >> 3;
 3554                 sc->synhw.capMultiFinger = (status[2] & 0x02) >> 1;
 3555                 sc->synhw.capPalmDetect  = (status[2] & 0x01);
 3556 
 3557                 if (verbose >= 2) {
 3558                         printf("  Extended capabilities:\n");
 3559                         printf("   capExtended: %d\n", sc->synhw.capExtended);
 3560                         printf("   capPassthrough: %d\n",
 3561                             sc->synhw.capPassthrough);
 3562                         printf("   capSleep: %d\n", sc->synhw.capSleep);
 3563                         printf("   capFourButtons: %d\n",
 3564                             sc->synhw.capFourButtons);
 3565                         printf("   capMultiFinger: %d\n",
 3566                             sc->synhw.capMultiFinger);
 3567                         printf("   capPalmDetect: %d\n",
 3568                             sc->synhw.capPalmDetect);
 3569                 }
 3570 
 3571                 /*
 3572                  * if we have bits set in status[0] & 0x70 - then we can load
 3573                  * more information about buttons using query 0x09
 3574                  */
 3575                 if (status[0] & 0x70) {
 3576                         if (mouse_ext_command(kbdc, 0x09) == 0)
 3577                                 return (FALSE);
 3578                         if (get_mouse_status(kbdc, status, 0, 3) != 3)
 3579                                 return (FALSE);
 3580                         sc->hw.buttons = ((status[1] & 0xf0) >> 4) + 3;
 3581                         if (verbose >= 2)
 3582                                 printf("  Additional Buttons: %d\n",
 3583                                     sc->hw.buttons -3);
 3584                 }
 3585         } else {
 3586                 sc->synhw.capExtended = 0;
 3587 
 3588                 if (verbose >= 2)
 3589                         printf("  No extended capabilities\n");
 3590         }
 3591 
 3592         /*
 3593          * Read the mode byte
 3594          *
 3595          * XXX: Note the Synaptics documentation also defines the first
 3596          * byte of the response to this query to be a constant 0x3b, this
 3597          * does not appear to be true for Touchpads with guest devices.
 3598          */
 3599         if (mouse_ext_command(kbdc, 1) == 0)
 3600                 return (FALSE);
 3601         if (get_mouse_status(kbdc, status, 0, 3) != 3)
 3602                 return (FALSE);
 3603         if (status[1] != 0x47) {
 3604                 printf("  Failed to read mode byte\n");
 3605                 return (FALSE);
 3606         }
 3607 
 3608         /* Set the mode byte -- request wmode where available */
 3609         if (sc->synhw.capExtended)
 3610                 mouse_ext_command(kbdc, 0xc1);
 3611         else
 3612                 mouse_ext_command(kbdc, 0xc0);
 3613 
 3614         /* Reset the sampling rate */
 3615         set_mouse_sampling_rate(kbdc, 20);
 3616 
 3617         /*
 3618          * Report the correct number of buttons
 3619          *
 3620          * XXX: I'm not sure this is used anywhere.
 3621          */
 3622         if (sc->synhw.capExtended && sc->synhw.capFourButtons)
 3623                 sc->hw.buttons = 4;
 3624 
 3625         return (TRUE);
 3626 }
 3627 
 3628 /* Interlink electronics VersaPad */
 3629 static int
 3630 enable_versapad(struct psm_softc *sc)
 3631 {
 3632         KBDC kbdc = sc->kbdc;
 3633         int data[3];
 3634 
 3635         set_mouse_resolution(kbdc, PSMD_RES_MEDIUM_HIGH); /* set res. 2 */
 3636         set_mouse_sampling_rate(kbdc, 100);             /* set rate 100 */
 3637         set_mouse_scaling(kbdc, 1);                     /* set scale 1:1 */
 3638         set_mouse_scaling(kbdc, 1);                     /* set scale 1:1 */
 3639         set_mouse_scaling(kbdc, 1);                     /* set scale 1:1 */
 3640         set_mouse_scaling(kbdc, 1);                     /* set scale 1:1 */
 3641         if (get_mouse_status(kbdc, data, 0, 3) < 3)     /* get status */
 3642                 return (FALSE);
 3643         if (data[2] != 0xa || data[1] != 0 )    /* rate == 0xa && res. == 0 */
 3644                 return (FALSE);
 3645         set_mouse_scaling(kbdc, 1);                     /* set scale 1:1 */
 3646 
 3647         sc->config |= PSM_CONFIG_HOOKRESUME | PSM_CONFIG_INITAFTERSUSPEND;
 3648 
 3649         return (TRUE);                          /* PS/2 absolute mode */
 3650 }
 3651 
 3652 /*
 3653  * Return true if 'now' is earlier than (start + (secs.usecs)).
 3654  * Now may be NULL and the function will fetch the current time from
 3655  * getmicrouptime(), or a cached 'now' can be passed in.
 3656  * All values should be numbers derived from getmicrouptime().
 3657  */
 3658 static int
 3659 timeelapsed(start, secs, usecs, now)
 3660         const struct timeval *start, *now;
 3661         int secs, usecs;
 3662 {
 3663         struct timeval snow, tv;
 3664 
 3665         /* if there is no 'now' passed in, the get it as a convience. */
 3666         if (now == NULL) {
 3667                 getmicrouptime(&snow);
 3668                 now = &snow;
 3669         }
 3670 
 3671         tv.tv_sec = secs;
 3672         tv.tv_usec = usecs;
 3673         timevaladd(&tv, start);
 3674         return (timevalcmp(&tv, now, <));
 3675 }
 3676 
 3677 static int
 3678 psmresume(device_t dev)
 3679 {
 3680         struct psm_softc *sc = device_get_softc(dev);
 3681         int unit = device_get_unit(dev);
 3682         int err;
 3683 
 3684         VLOG(2, (LOG_NOTICE, "psm%d: system resume hook called.\n", unit));
 3685 
 3686         if (!(sc->config & PSM_CONFIG_HOOKRESUME))
 3687                 return (0);
 3688 
 3689         err = reinitialize(sc, sc->config & PSM_CONFIG_INITAFTERSUSPEND);
 3690 
 3691         if ((sc->state & PSM_ASLP) && !(sc->state & PSM_VALID)) {
 3692                 /*
 3693                  * Release the blocked process; it must be notified that
 3694                  * the device cannot be accessed anymore.
 3695                  */
 3696                 sc->state &= ~PSM_ASLP;
 3697                 wakeup(sc);
 3698         }
 3699 
 3700         VLOG(2, (LOG_DEBUG, "psm%d: system resume hook exiting.\n", unit));
 3701 
 3702         return (err);
 3703 }
 3704 
 3705 DRIVER_MODULE(psm, atkbdc, psm_driver, psm_devclass, 0, 0);
 3706 
 3707 #ifdef DEV_ISA
 3708 
 3709 /*
 3710  * This sucks up assignments from PNPBIOS and ACPI.
 3711  */
 3712 
 3713 /*
 3714  * When the PS/2 mouse device is reported by ACPI or PnP BIOS, it may
 3715  * appear BEFORE the AT keyboard controller.  As the PS/2 mouse device
 3716  * can be probed and attached only after the AT keyboard controller is
 3717  * attached, we shall quietly reserve the IRQ resource for later use.
 3718  * If the PS/2 mouse device is reported to us AFTER the keyboard controller,
 3719  * copy the IRQ resource to the PS/2 mouse device instance hanging
 3720  * under the keyboard controller, then probe and attach it.
 3721  */
 3722 
 3723 static  devclass_t                      psmcpnp_devclass;
 3724 
 3725 static  device_probe_t                  psmcpnp_probe;
 3726 static  device_attach_t                 psmcpnp_attach;
 3727 
 3728 static device_method_t psmcpnp_methods[] = {
 3729         DEVMETHOD(device_probe,         psmcpnp_probe),
 3730         DEVMETHOD(device_attach,        psmcpnp_attach),
 3731 
 3732         { 0, 0 }
 3733 };
 3734 
 3735 static driver_t psmcpnp_driver = {
 3736         PSMCPNP_DRIVER_NAME,
 3737         psmcpnp_methods,
 3738         1,                      /* no softc */
 3739 };
 3740 
 3741 static struct isa_pnp_id psmcpnp_ids[] = {
 3742         { 0x030fd041, "PS/2 mouse port" },              /* PNP0F03 */
 3743         { 0x0e0fd041, "PS/2 mouse port" },              /* PNP0F0E */
 3744         { 0x120fd041, "PS/2 mouse port" },              /* PNP0F12 */
 3745         { 0x130fd041, "PS/2 mouse port" },              /* PNP0F13 */
 3746         { 0x1303d041, "PS/2 port" },                    /* PNP0313, XXX */
 3747         { 0x02002e4f, "Dell PS/2 mouse port" },         /* Lat. X200, Dell */
 3748         { 0x0002a906, "ALPS Glide Point" },             /* ALPS Glide Point */
 3749         { 0x80374d24, "IBM PS/2 mouse port" },          /* IBM3780, ThinkPad */
 3750         { 0x81374d24, "IBM PS/2 mouse port" },          /* IBM3781, ThinkPad */
 3751         { 0x0190d94d, "SONY VAIO PS/2 mouse port"},     /* SNY9001, Vaio */
 3752         { 0x0290d94d, "SONY VAIO PS/2 mouse port"},     /* SNY9002, Vaio */
 3753         { 0x0390d94d, "SONY VAIO PS/2 mouse port"},     /* SNY9003, Vaio */
 3754         { 0x0490d94d, "SONY VAIO PS/2 mouse port"},     /* SNY9004, Vaio */
 3755         { 0 }
 3756 };
 3757 
 3758 static int
 3759 create_a_copy(device_t atkbdc, device_t me)
 3760 {
 3761         device_t psm;
 3762         u_long irq;
 3763 
 3764         /* find the PS/2 mouse device instance under the keyboard controller */
 3765         psm = device_find_child(atkbdc, PSM_DRIVER_NAME,
 3766             device_get_unit(atkbdc));
 3767         if (psm == NULL)
 3768                 return (ENXIO);
 3769         if (device_get_state(psm) != DS_NOTPRESENT)
 3770                 return (0);
 3771 
 3772         /* move our resource to the found device */
 3773         irq = bus_get_resource_start(me, SYS_RES_IRQ, 0);
 3774         bus_set_resource(psm, SYS_RES_IRQ, KBDC_RID_AUX, irq, 1);
 3775 
 3776         /* ...then probe and attach it */
 3777         return (device_probe_and_attach(psm));
 3778 }
 3779 
 3780 static int
 3781 psmcpnp_probe(device_t dev)
 3782 {
 3783         struct resource *res;
 3784         u_long irq;
 3785         int rid;
 3786 
 3787         if (ISA_PNP_PROBE(device_get_parent(dev), dev, psmcpnp_ids))
 3788                 return (ENXIO);
 3789 
 3790         /*
 3791          * The PnP BIOS and ACPI are supposed to assign an IRQ (12)
 3792          * to the PS/2 mouse device node. But, some buggy PnP BIOS
 3793          * declares the PS/2 mouse device node without an IRQ resource!
 3794          * If this happens, we shall refer to device hints.
 3795          * If we still don't find it there, use a hardcoded value... XXX
 3796          */
 3797         rid = 0;
 3798         irq = bus_get_resource_start(dev, SYS_RES_IRQ, rid);
 3799         if (irq <= 0) {
 3800                 if (resource_long_value(PSM_DRIVER_NAME,
 3801                     device_get_unit(dev),"irq", &irq) != 0)
 3802                         irq = 12;       /* XXX */
 3803                 device_printf(dev, "irq resource info is missing; "
 3804                     "assuming irq %ld\n", irq);
 3805                 bus_set_resource(dev, SYS_RES_IRQ, rid, irq, 1);
 3806         }
 3807         res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE);
 3808         bus_release_resource(dev, SYS_RES_IRQ, rid, res);
 3809 
 3810         /* keep quiet */
 3811         if (!bootverbose)
 3812                 device_quiet(dev);
 3813 
 3814         return ((res == NULL) ? ENXIO : 0);
 3815 }
 3816 
 3817 static int
 3818 psmcpnp_attach(device_t dev)
 3819 {
 3820         device_t atkbdc;
 3821         int rid;
 3822 
 3823         /* find the keyboard controller, which may be on acpi* or isa* bus */
 3824         atkbdc = devclass_get_device(devclass_find(ATKBDC_DRIVER_NAME),
 3825             device_get_unit(dev));
 3826         if ((atkbdc != NULL) && (device_get_state(atkbdc) == DS_ATTACHED))
 3827                 create_a_copy(atkbdc, dev);
 3828         else {
 3829                 /*
 3830                  * If we don't have the AT keyboard controller yet,
 3831                  * just reserve the IRQ for later use...
 3832                  * (See psmidentify() above.)
 3833                  */
 3834                 rid = 0;
 3835                 bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE);
 3836         }
 3837 
 3838         return (0);
 3839 }
 3840 
 3841 DRIVER_MODULE(psmcpnp, isa, psmcpnp_driver, psmcpnp_devclass, 0, 0);
 3842 DRIVER_MODULE(psmcpnp, acpi, psmcpnp_driver, psmcpnp_devclass, 0, 0);
 3843 
 3844 #endif /* DEV_ISA */

Cache object: 8c19a49053d7dccde3b0f511675d1129


[ 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.