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


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

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

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

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

Cache object: 1a95ecf5e41cd983d597ce02c921faae


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