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/pc98/pc98/mse.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 1992 by the University of Guelph
    3  *
    4  * Permission to use, copy and modify this
    5  * software and its documentation for any purpose and without
    6  * fee is hereby granted, provided that the above copyright
    7  * notice appear in all copies and that both that copyright
    8  * notice and this permission notice appear in supporting
    9  * documentation.
   10  * University of Guelph makes no representations about the suitability of
   11  * this software for any purpose.  It is provided "as is"
   12  * without express or implied warranty.
   13  *
   14  * $FreeBSD: releng/5.0/sys/pc98/pc98/mse.c 93134 2002-03-25 12:44:03Z nyan $
   15  */
   16 /*
   17  * Driver for the Logitech and ATI Inport Bus mice for use with 386bsd and
   18  * the X386 port, courtesy of
   19  * Rick Macklem, rick@snowhite.cis.uoguelph.ca
   20  * Caveats: The driver currently uses spltty(), but doesn't use any
   21  * generic tty code. It could use splmse() (that only masks off the
   22  * bus mouse interrupt, but that would require hacking in i386/isa/icu.s.
   23  * (This may be worth the effort, since the Logitech generates 30/60
   24  * interrupts/sec continuously while it is open.)
   25  * NB: The ATI has NOT been tested yet!
   26  */
   27 
   28 /*
   29  * Modification history:
   30  * Sep 6, 1994 -- Lars Fredriksen(fredriks@mcs.com)
   31  *   improved probe based on input from Logitech.
   32  *
   33  * Oct 19, 1992 -- E. Stark (stark@cs.sunysb.edu)
   34  *   fixes to make it work with Microsoft InPort busmouse
   35  *
   36  * Jan, 1993 -- E. Stark (stark@cs.sunysb.edu)
   37  *   added patches for new "select" interface
   38  *
   39  * May 4, 1993 -- E. Stark (stark@cs.sunysb.edu)
   40  *   changed position of some spl()'s in mseread
   41  *
   42  * October 8, 1993 -- E. Stark (stark@cs.sunysb.edu)
   43  *   limit maximum negative x/y value to -127 to work around XFree problem
   44  *   that causes spurious button pushes.
   45  */
   46 
   47 #include <sys/param.h>
   48 #include <sys/systm.h>
   49 #include <sys/conf.h>
   50 #include <sys/kernel.h>
   51 #include <sys/bus.h>
   52 #include <sys/poll.h>
   53 #include <sys/selinfo.h>
   54 #include <sys/uio.h>
   55 #include <sys/mouse.h>
   56 
   57 #include <machine/bus.h>
   58 #include <machine/clock.h>
   59 #include <machine/resource.h>
   60 #include <sys/rman.h>
   61 
   62 #include <isa/isavar.h>
   63 
   64 /* driver configuration flags (config) */
   65 #define MSE_CONFIG_ACCEL        0x00f0  /* acceleration factor */
   66 #define MSE_CONFIG_FLAGS        (MSE_CONFIG_ACCEL)
   67 
   68 /*
   69  * Software control structure for mouse. The sc_enablemouse(),
   70  * sc_disablemouse() and sc_getmouse() routines must be called spl'd().
   71  */
   72 typedef struct mse_softc {
   73         int             sc_flags;
   74         int             sc_mousetype;
   75         struct selinfo  sc_selp;
   76         struct resource *sc_port;
   77         struct resource *sc_intr;
   78         bus_space_tag_t sc_iot;
   79         bus_space_handle_t sc_ioh;
   80         void            *sc_ih;
   81         void            (*sc_enablemouse)(bus_space_tag_t t,
   82                             bus_space_handle_t h);
   83         void            (*sc_disablemouse)(bus_space_tag_t t,
   84                             bus_space_handle_t h);
   85         void            (*sc_getmouse)(bus_space_tag_t t, bus_space_handle_t h,
   86                             int *dx, int *dy, int *but);
   87         int             sc_deltax;
   88         int             sc_deltay;
   89         int             sc_obuttons;
   90         int             sc_buttons;
   91         int             sc_bytesread;
   92         u_char          sc_bytes[MOUSE_SYS_PACKETSIZE];
   93         struct          callout_handle sc_callout;
   94         int             sc_watchdog;
   95         dev_t           sc_dev;
   96         dev_t           sc_ndev;
   97         mousehw_t       hw;
   98         mousemode_t     mode;
   99         mousestatus_t   status;
  100 } mse_softc_t;
  101 
  102 static  devclass_t      mse_devclass;
  103 
  104 static  int             mse_probe(device_t dev);
  105 static  int             mse_attach(device_t dev);
  106 static  int             mse_detach(device_t dev);
  107 
  108 static  device_method_t mse_methods[] = {
  109         DEVMETHOD(device_probe,         mse_probe),
  110         DEVMETHOD(device_attach,        mse_attach),
  111         DEVMETHOD(device_detach,        mse_detach),
  112         { 0, 0 }
  113 };
  114 
  115 static  driver_t        mse_driver = {
  116         "mse",
  117         mse_methods,
  118         sizeof(mse_softc_t),
  119 };
  120 
  121 DRIVER_MODULE(mse, isa, mse_driver, mse_devclass, 0, 0);
  122 
  123 static struct isa_pnp_id mse_ids[] = {
  124         { 0x000fd041, "Bus mouse" },                    /* PNP0F00 */
  125         { 0x020fd041, "InPort mouse" },                 /* PNP0F02 */
  126         { 0x0d0fd041, "InPort mouse compatible" },      /* PNP0F0D */
  127         { 0x110fd041, "Bus mouse compatible" },         /* PNP0F11 */
  128         { 0x150fd041, "Logitech bus mouse" },           /* PNP0F15 */
  129         { 0x180fd041, "Logitech bus mouse compatible" },/* PNP0F18 */
  130         { 0 }
  131 };
  132 
  133 static  d_open_t        mseopen;
  134 static  d_close_t       mseclose;
  135 static  d_read_t        mseread;
  136 static  d_ioctl_t       mseioctl;
  137 static  d_poll_t        msepoll;
  138 
  139 #define CDEV_MAJOR 27
  140 static struct cdevsw mse_cdevsw = {
  141         /* open */      mseopen,
  142         /* close */     mseclose,
  143         /* read */      mseread,
  144         /* write */     nowrite,
  145         /* ioctl */     mseioctl,
  146         /* poll */      msepoll,
  147         /* mmap */      nommap,
  148         /* strategy */  nostrategy,
  149         /* name */      "mse",
  150         /* maj */       CDEV_MAJOR,
  151         /* dump */      nodump,
  152         /* psize */     nopsize,
  153         /* flags */     0,
  154 };
  155 
  156 static  void            mseintr(void *);
  157 static  timeout_t       msetimeout;
  158 
  159 /* Flags */
  160 #define MSESC_OPEN      0x1
  161 #define MSESC_WANT      0x2
  162 
  163 /* and Mouse Types */
  164 #define MSE_NONE        0       /* don't move this! */
  165 #ifdef PC98
  166 #define MSE_98BUSMOUSE  0x1
  167 #else
  168 #define MSE_LOGITECH    0x1
  169 #define MSE_ATIINPORT   0x2
  170 #define MSE_LOGI_SIG    0xA5
  171 #endif
  172 
  173 #define MSE_PORTA       0
  174 #define MSE_PORTB       1
  175 #define MSE_PORTC       2
  176 #define MSE_PORTD       3
  177 #define MSE_IOSIZE      4
  178 
  179 #define MSE_UNIT(dev)           (minor(dev) >> 1)
  180 #define MSE_NBLOCKIO(dev)       (minor(dev) & 0x1)
  181 
  182 #ifdef PC98
  183 /*
  184  * PC-9801 Bus mouse definitions
  185  */
  186 
  187 #define MODE    MSE_PORTD
  188 #define HC      MSE_PORTD
  189 #define INT     MSE_PORTD
  190 
  191 #define XL      0x00
  192 #define XH      0x20
  193 #define YL      0x40
  194 #define YH      0x60
  195 
  196 #define INT_ENABLE      0x8
  197 #define INT_DISABLE     0x9
  198 #define HC_NO_CLEAR     0xe
  199 #define HC_CLEAR        0xf
  200 
  201 static  bus_addr_t      mse_port[] = {0, 2, 4, 6};
  202 
  203 static  int             mse_probe98m(device_t dev, mse_softc_t *sc);
  204 static  void            mse_disable98m(bus_space_tag_t t, bus_space_handle_t h);
  205 static  void            mse_get98m(bus_space_tag_t t, bus_space_handle_t h,
  206                             int *dx, int *dy, int *but);
  207 static  void            mse_enable98m(bus_space_tag_t t, bus_space_handle_t h);
  208 #else
  209 /*
  210  * Logitech bus mouse definitions
  211  */
  212 #define MSE_SETUP       0x91    /* What does this mean? */
  213                                 /* The definition for the control port */
  214                                 /* is as follows: */
  215 
  216                                 /* D7    =  Mode set flag (1 = active)  */
  217                                 /* D6,D5 =  Mode selection (port A)     */
  218                                 /*          00 = Mode 0 = Basic I/O     */
  219                                 /*          01 = Mode 1 = Strobed I/O   */
  220                                 /*          10 = Mode 2 = Bi-dir bus    */
  221                                 /* D4    =  Port A direction (1 = input)*/
  222                                 /* D3    =  Port C (upper 4 bits)       */
  223                                 /*          direction. (1 = input)      */
  224                                 /* D2    =  Mode selection (port B & C) */
  225                                 /*          0 = Mode 0 = Basic I/O      */
  226                                 /*          1 = Mode 1 = Strobed I/O    */
  227                                 /* D1    =  Port B direction (1 = input)*/
  228                                 /* D0    =  Port C (lower 4 bits)       */
  229                                 /*          direction. (1 = input)      */
  230 
  231                                 /* So 91 means Basic I/O on all 3 ports,*/
  232                                 /* Port A is an input port, B is an     */
  233                                 /* output port, C is split with upper   */
  234                                 /* 4 bits being an output port and lower*/
  235                                 /* 4 bits an input port, and enable the */
  236                                 /* sucker.                              */
  237                                 /* Courtesy Intel 8255 databook. Lars   */
  238 #define MSE_HOLD        0x80
  239 #define MSE_RXLOW       0x00
  240 #define MSE_RXHIGH      0x20
  241 #define MSE_RYLOW       0x40
  242 #define MSE_RYHIGH      0x60
  243 #define MSE_DISINTR     0x10
  244 #define MSE_INTREN      0x00
  245 
  246 static  int             mse_probelogi(device_t dev, mse_softc_t *sc);
  247 static  void            mse_disablelogi(bus_space_tag_t t,
  248                             bus_space_handle_t h);
  249 static  void            mse_getlogi(bus_space_tag_t t, bus_space_handle_t h,
  250                             int *dx, int *dy, int *but);
  251 static  void            mse_enablelogi(bus_space_tag_t t,
  252                             bus_space_handle_t h);
  253 
  254 /*
  255  * ATI Inport mouse definitions
  256  */
  257 #define MSE_INPORT_RESET        0x80
  258 #define MSE_INPORT_STATUS       0x00
  259 #define MSE_INPORT_DX           0x01
  260 #define MSE_INPORT_DY           0x02
  261 #define MSE_INPORT_MODE         0x07
  262 #define MSE_INPORT_HOLD         0x20
  263 #define MSE_INPORT_INTREN       0x09
  264 
  265 static  int             mse_probeati(device_t dev, mse_softc_t *sc);
  266 static  void            mse_enableati(bus_space_tag_t t, bus_space_handle_t h);
  267 static  void            mse_disableati(bus_space_tag_t t, bus_space_handle_t h);
  268 static  void            mse_getati(bus_space_tag_t t, bus_space_handle_t h,
  269                             int *dx, int *dy, int *but);
  270 #endif
  271 
  272 #define MSEPRI  (PZERO + 3)
  273 
  274 /*
  275  * Table of mouse types.
  276  * Keep the Logitech last, since I haven't figured out how to probe it
  277  * properly yet. (Someday I'll have the documentation.)
  278  */
  279 static struct mse_types {
  280         int     m_type;         /* Type of bus mouse */
  281         int     (*m_probe)(device_t dev, mse_softc_t *sc);
  282                                 /* Probe routine to test for it */
  283         void    (*m_enable)(bus_space_tag_t t, bus_space_handle_t h);
  284                                 /* Start routine */
  285         void    (*m_disable)(bus_space_tag_t t, bus_space_handle_t h);
  286                                 /* Disable interrupts routine */
  287         void    (*m_get)(bus_space_tag_t t, bus_space_handle_t h, int *dx,
  288                     int *dy, int *but);
  289                                 /* and get mouse status */
  290         mousehw_t   m_hw;       /* buttons iftype type model hwid */
  291         mousemode_t m_mode;     /* proto rate res accel level size mask */
  292 } mse_types[] = {
  293 #ifdef PC98
  294         { MSE_98BUSMOUSE,
  295           mse_probe98m, mse_enable98m, mse_disable98m, mse_get98m,
  296           { 2, MOUSE_IF_BUS, MOUSE_MOUSE, MOUSE_MODEL_GENERIC, 0, },
  297           { MOUSE_PROTO_BUS, -1, -1, 0, 0, MOUSE_MSC_PACKETSIZE, 
  298             { MOUSE_MSC_SYNCMASK, MOUSE_MSC_SYNC, }, }, },
  299 #else
  300         { MSE_ATIINPORT, 
  301           mse_probeati, mse_enableati, mse_disableati, mse_getati,
  302           { 2, MOUSE_IF_INPORT, MOUSE_MOUSE, MOUSE_MODEL_GENERIC, 0, },
  303           { MOUSE_PROTO_INPORT, -1, -1, 0, 0, MOUSE_MSC_PACKETSIZE, 
  304             { MOUSE_MSC_SYNCMASK, MOUSE_MSC_SYNC, }, }, },
  305         { MSE_LOGITECH, 
  306           mse_probelogi, mse_enablelogi, mse_disablelogi, mse_getlogi,
  307           { 2, MOUSE_IF_BUS, MOUSE_MOUSE, MOUSE_MODEL_GENERIC, 0, },
  308           { MOUSE_PROTO_BUS, -1, -1, 0, 0, MOUSE_MSC_PACKETSIZE, 
  309             { MOUSE_MSC_SYNCMASK, MOUSE_MSC_SYNC, }, }, },
  310 #endif
  311         { 0, },
  312 };
  313 
  314 static  int
  315 mse_probe(dev)
  316         device_t dev;
  317 {
  318         mse_softc_t *sc;
  319         int error;
  320         int rid;
  321         int i;
  322 
  323         /* check PnP IDs */
  324         error = ISA_PNP_PROBE(device_get_parent(dev), dev, mse_ids);
  325         if (error == ENXIO)
  326                 return error;
  327 
  328         sc = device_get_softc(dev);
  329         rid = 0;
  330 #ifdef PC98
  331         sc->sc_port = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, mse_port,
  332                                           MSE_IOSIZE, RF_ACTIVE);
  333 #else
  334         sc->sc_port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0,
  335                                          MSE_IOSIZE, RF_ACTIVE);
  336 #endif
  337         if (sc->sc_port == NULL)
  338                 return ENXIO;
  339 #ifdef PC98
  340         if (isa_load_resourcev(sc->sc_port, mse_port, MSE_IOSIZE)) {
  341                 bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->sc_port);
  342                 return ENXIO;
  343         }
  344 #endif
  345         sc->sc_iot = rman_get_bustag(sc->sc_port);
  346         sc->sc_ioh = rman_get_bushandle(sc->sc_port);
  347 
  348         /*
  349          * Check for each mouse type in the table.
  350          */
  351         i = 0;
  352         while (mse_types[i].m_type) {
  353                 if ((*mse_types[i].m_probe)(dev, sc)) {
  354                         sc->sc_mousetype = mse_types[i].m_type;
  355                         sc->sc_enablemouse = mse_types[i].m_enable;
  356                         sc->sc_disablemouse = mse_types[i].m_disable;
  357                         sc->sc_getmouse = mse_types[i].m_get;
  358                         sc->hw = mse_types[i].m_hw;
  359                         sc->mode = mse_types[i].m_mode;
  360                         bus_release_resource(dev, SYS_RES_IOPORT, rid,
  361                                              sc->sc_port);
  362                         device_set_desc(dev, "Bus/InPort Mouse");
  363                         return 0;
  364                 }
  365                 i++;
  366         }
  367         bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->sc_port);
  368         return ENXIO;
  369 }
  370 
  371 static  int
  372 mse_attach(dev)
  373         device_t dev;
  374 {
  375         mse_softc_t *sc;
  376         int flags;
  377         int unit;
  378         int rid;
  379 
  380         sc = device_get_softc(dev);
  381         unit = device_get_unit(dev);
  382 
  383         rid = 0;
  384 #ifdef PC98
  385         sc->sc_port = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid, mse_port,
  386                                           MSE_IOSIZE, RF_ACTIVE);
  387 #else
  388         sc->sc_port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0,
  389                                          MSE_IOSIZE, RF_ACTIVE);
  390 #endif
  391         if (sc->sc_port == NULL)
  392                 return ENXIO;
  393 #ifdef PC98
  394         if (isa_load_resourcev(sc->sc_port, mse_port, MSE_IOSIZE)) {
  395                 bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->sc_port);
  396                 return ENXIO;
  397         }
  398 #endif
  399         sc->sc_intr = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
  400                                          RF_ACTIVE);
  401         if (sc->sc_intr == NULL) {
  402                 bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->sc_port);
  403                 return ENXIO;
  404         }
  405         sc->sc_iot = rman_get_bustag(sc->sc_port);
  406         sc->sc_ioh = rman_get_bushandle(sc->sc_port);
  407 
  408         if (BUS_SETUP_INTR(device_get_parent(dev), dev, sc->sc_intr,
  409                            INTR_TYPE_TTY, mseintr, sc, &sc->sc_ih)) {
  410                 bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->sc_port);
  411                 bus_release_resource(dev, SYS_RES_IRQ, rid, sc->sc_intr);
  412                 return ENXIO;
  413         }
  414 
  415         flags = device_get_flags(dev);
  416         sc->mode.accelfactor = (flags & MSE_CONFIG_ACCEL) >> 4;
  417         callout_handle_init(&sc->sc_callout);
  418 
  419         sc->sc_dev = make_dev(&mse_cdevsw, unit << 1, 0, 0, 0600,
  420                               "mse%d", unit);
  421         sc->sc_ndev = make_dev(&mse_cdevsw, (unit<<1)+1, 0, 0, 0600,
  422                                "nmse%d", unit);
  423 
  424         return 0;
  425 }
  426 
  427 static  int
  428 mse_detach(dev)
  429         device_t dev;
  430 {
  431         mse_softc_t *sc;
  432         int rid;
  433 
  434         sc = device_get_softc(dev);
  435         if (sc->sc_flags & MSESC_OPEN)
  436                 return EBUSY;
  437 
  438         rid = 0;
  439         BUS_TEARDOWN_INTR(device_get_parent(dev), dev, sc->sc_intr, sc->sc_ih);
  440         bus_release_resource(dev, SYS_RES_IRQ, rid, sc->sc_intr);
  441         bus_release_resource(dev, SYS_RES_IOPORT, rid, sc->sc_port);
  442 
  443         destroy_dev(sc->sc_dev);
  444         destroy_dev(sc->sc_ndev);
  445 
  446         return 0;
  447 }
  448 
  449 /*
  450  * Exclusive open the mouse, initialize it and enable interrupts.
  451  */
  452 static  int
  453 mseopen(dev, flags, fmt, td)
  454         dev_t dev;
  455         int flags;
  456         int fmt;
  457         struct thread *td;
  458 {
  459         mse_softc_t *sc;
  460         int s;
  461 
  462         sc = devclass_get_softc(mse_devclass, MSE_UNIT(dev));
  463         if (sc == NULL)
  464                 return (ENXIO);
  465         if (sc->sc_mousetype == MSE_NONE)
  466                 return (ENXIO);
  467         if (sc->sc_flags & MSESC_OPEN)
  468                 return (EBUSY);
  469         sc->sc_flags |= MSESC_OPEN;
  470         sc->sc_obuttons = sc->sc_buttons = MOUSE_MSC_BUTTONS;
  471         sc->sc_deltax = sc->sc_deltay = 0;
  472         sc->sc_bytesread = sc->mode.packetsize = MOUSE_MSC_PACKETSIZE;
  473         sc->sc_watchdog = FALSE;
  474         sc->sc_callout = timeout(msetimeout, dev, hz*2);
  475         sc->mode.level = 0;
  476         sc->status.flags = 0;
  477         sc->status.button = sc->status.obutton = 0;
  478         sc->status.dx = sc->status.dy = sc->status.dz = 0;
  479 
  480         /*
  481          * Initialize mouse interface and enable interrupts.
  482          */
  483         s = spltty();
  484         (*sc->sc_enablemouse)(sc->sc_iot, sc->sc_ioh);
  485         splx(s);
  486         return (0);
  487 }
  488 
  489 /*
  490  * mseclose: just turn off mouse innterrupts.
  491  */
  492 static  int
  493 mseclose(dev, flags, fmt, td)
  494         dev_t dev;
  495         int flags;
  496         int fmt;
  497         struct thread *td;
  498 {
  499         mse_softc_t *sc = devclass_get_softc(mse_devclass, MSE_UNIT(dev));
  500         int s;
  501 
  502         untimeout(msetimeout, dev, sc->sc_callout);
  503         callout_handle_init(&sc->sc_callout);
  504         s = spltty();
  505         (*sc->sc_disablemouse)(sc->sc_iot, sc->sc_ioh);
  506         sc->sc_flags &= ~MSESC_OPEN;
  507         splx(s);
  508         return(0);
  509 }
  510 
  511 /*
  512  * mseread: return mouse info using the MSC serial protocol, but without
  513  * using bytes 4 and 5.
  514  * (Yes this is cheesy, but it makes the X386 server happy, so...)
  515  */
  516 static  int
  517 mseread(dev, uio, ioflag)
  518         dev_t dev;
  519         struct uio *uio;
  520         int ioflag;
  521 {
  522         mse_softc_t *sc = devclass_get_softc(mse_devclass, MSE_UNIT(dev));
  523         int xfer, s, error;
  524 
  525         /*
  526          * If there are no protocol bytes to be read, set up a new protocol
  527          * packet.
  528          */
  529         s = spltty(); /* XXX Should be its own spl, but where is imlXX() */
  530         if (sc->sc_bytesread >= sc->mode.packetsize) {
  531                 while (sc->sc_deltax == 0 && sc->sc_deltay == 0 &&
  532                        (sc->sc_obuttons ^ sc->sc_buttons) == 0) {
  533                         if (MSE_NBLOCKIO(dev)) {
  534                                 splx(s);
  535                                 return (0);
  536                         }
  537                         sc->sc_flags |= MSESC_WANT;
  538                         error = tsleep((caddr_t)sc, MSEPRI | PCATCH,
  539                                 "mseread", 0);
  540                         if (error) {
  541                                 splx(s);
  542                                 return (error);
  543                         }
  544                 }
  545 
  546                 /*
  547                  * Generate protocol bytes.
  548                  * For some reason X386 expects 5 bytes but never uses
  549                  * the fourth or fifth?
  550                  */
  551                 sc->sc_bytes[0] = sc->mode.syncmask[1] 
  552                     | (sc->sc_buttons & ~sc->mode.syncmask[0]);
  553                 if (sc->sc_deltax > 127)
  554                         sc->sc_deltax = 127;
  555                 if (sc->sc_deltax < -127)
  556                         sc->sc_deltax = -127;
  557                 sc->sc_deltay = -sc->sc_deltay; /* Otherwise mousey goes wrong way */
  558                 if (sc->sc_deltay > 127)
  559                         sc->sc_deltay = 127;
  560                 if (sc->sc_deltay < -127)
  561                         sc->sc_deltay = -127;
  562                 sc->sc_bytes[1] = sc->sc_deltax;
  563                 sc->sc_bytes[2] = sc->sc_deltay;
  564                 sc->sc_bytes[3] = sc->sc_bytes[4] = 0;
  565                 sc->sc_bytes[5] = sc->sc_bytes[6] = 0;
  566                 sc->sc_bytes[7] = MOUSE_SYS_EXTBUTTONS;
  567                 sc->sc_obuttons = sc->sc_buttons;
  568                 sc->sc_deltax = sc->sc_deltay = 0;
  569                 sc->sc_bytesread = 0;
  570         }
  571         splx(s);
  572         xfer = min(uio->uio_resid, sc->mode.packetsize - sc->sc_bytesread);
  573         error = uiomove(&sc->sc_bytes[sc->sc_bytesread], xfer, uio);
  574         if (error)
  575                 return (error);
  576         sc->sc_bytesread += xfer;
  577         return(0);
  578 }
  579 
  580 /*
  581  * mseioctl: process ioctl commands.
  582  */
  583 static int
  584 mseioctl(dev, cmd, addr, flag, td)
  585         dev_t dev;
  586         u_long cmd;
  587         caddr_t addr;
  588         int flag;
  589         struct thread *td;
  590 {
  591         mse_softc_t *sc = devclass_get_softc(mse_devclass, MSE_UNIT(dev));
  592         mousestatus_t status;
  593         int err = 0;
  594         int s;
  595 
  596         switch (cmd) {
  597 
  598         case MOUSE_GETHWINFO:
  599                 s = spltty();
  600                 *(mousehw_t *)addr = sc->hw;
  601                 if (sc->mode.level == 0)
  602                         ((mousehw_t *)addr)->model = MOUSE_MODEL_GENERIC;
  603                 splx(s);
  604                 break;
  605 
  606         case MOUSE_GETMODE:
  607                 s = spltty();
  608                 *(mousemode_t *)addr = sc->mode;
  609                 switch (sc->mode.level) {
  610                 case 0:
  611                         break;
  612                 case 1:
  613                         ((mousemode_t *)addr)->protocol = MOUSE_PROTO_SYSMOUSE;
  614                         ((mousemode_t *)addr)->syncmask[0] = MOUSE_SYS_SYNCMASK;
  615                         ((mousemode_t *)addr)->syncmask[1] = MOUSE_SYS_SYNC;
  616                         break;
  617                 }
  618                 splx(s);
  619                 break;
  620 
  621         case MOUSE_SETMODE:
  622                 switch (((mousemode_t *)addr)->level) {
  623                 case 0:
  624                 case 1:
  625                         break;
  626                 default:
  627                         return (EINVAL);
  628                 }
  629                 if (((mousemode_t *)addr)->accelfactor < -1)
  630                         return (EINVAL);
  631                 else if (((mousemode_t *)addr)->accelfactor >= 0)
  632                         sc->mode.accelfactor = 
  633                             ((mousemode_t *)addr)->accelfactor;
  634                 sc->mode.level = ((mousemode_t *)addr)->level;
  635                 switch (sc->mode.level) {
  636                 case 0:
  637                         sc->sc_bytesread = sc->mode.packetsize 
  638                             = MOUSE_MSC_PACKETSIZE;
  639                         break;
  640                 case 1:
  641                         sc->sc_bytesread = sc->mode.packetsize 
  642                             = MOUSE_SYS_PACKETSIZE;
  643                         break;
  644                 }
  645                 break;
  646 
  647         case MOUSE_GETLEVEL:
  648                 *(int *)addr = sc->mode.level;
  649                 break;
  650 
  651         case MOUSE_SETLEVEL:
  652                 switch (*(int *)addr) {
  653                 case 0:
  654                         sc->mode.level = *(int *)addr;
  655                         sc->sc_bytesread = sc->mode.packetsize 
  656                             = MOUSE_MSC_PACKETSIZE;
  657                         break;
  658                 case 1:
  659                         sc->mode.level = *(int *)addr;
  660                         sc->sc_bytesread = sc->mode.packetsize 
  661                             = MOUSE_SYS_PACKETSIZE;
  662                         break;
  663                 default:
  664                         return (EINVAL);
  665                 }
  666                 break;
  667 
  668         case MOUSE_GETSTATUS:
  669                 s = spltty();
  670                 status = sc->status;
  671                 sc->status.flags = 0;
  672                 sc->status.obutton = sc->status.button;
  673                 sc->status.button = 0;
  674                 sc->status.dx = 0;
  675                 sc->status.dy = 0;
  676                 sc->status.dz = 0;
  677                 splx(s);
  678                 *(mousestatus_t *)addr = status;
  679                 break;
  680 
  681         case MOUSE_READSTATE:
  682         case MOUSE_READDATA:
  683                 return (ENODEV);
  684 
  685 #if (defined(MOUSE_GETVARS))
  686         case MOUSE_GETVARS:
  687         case MOUSE_SETVARS:
  688                 return (ENODEV);
  689 #endif
  690 
  691         default:
  692                 return (ENOTTY);
  693         }
  694         return (err);
  695 }
  696 
  697 /*
  698  * msepoll: check for mouse input to be processed.
  699  */
  700 static  int
  701 msepoll(dev, events, td)
  702         dev_t dev;
  703         int events;
  704         struct thread *td;
  705 {
  706         mse_softc_t *sc = devclass_get_softc(mse_devclass, MSE_UNIT(dev));
  707         int s;
  708         int revents = 0;
  709 
  710         s = spltty();
  711         if (events & (POLLIN | POLLRDNORM)) {
  712                 if (sc->sc_bytesread != sc->mode.packetsize ||
  713                     sc->sc_deltax != 0 || sc->sc_deltay != 0 ||
  714                     (sc->sc_obuttons ^ sc->sc_buttons) != 0)
  715                         revents |= events & (POLLIN | POLLRDNORM);
  716                 else {
  717                         /*
  718                          * Since this is an exclusive open device, any previous
  719                          * proc pointer is trash now, so we can just assign it.
  720                          */
  721                         selrecord(td, &sc->sc_selp);
  722                 }
  723         }
  724         splx(s);
  725         return (revents);
  726 }
  727 
  728 /*
  729  * msetimeout: watchdog timer routine.
  730  */
  731 static void
  732 msetimeout(arg)
  733         void *arg;
  734 {
  735         dev_t dev;
  736         mse_softc_t *sc;
  737 
  738         dev = (dev_t)arg;
  739         sc = devclass_get_softc(mse_devclass, MSE_UNIT(dev));
  740         if (sc->sc_watchdog) {
  741                 if (bootverbose)
  742                         printf("mse%d: lost interrupt?\n", MSE_UNIT(dev));
  743                 mseintr(sc);
  744         }
  745         sc->sc_watchdog = TRUE;
  746         sc->sc_callout = timeout(msetimeout, dev, hz);
  747 }
  748 
  749 /*
  750  * mseintr: update mouse status. sc_deltax and sc_deltay are accumulative.
  751  */
  752 static void
  753 mseintr(arg)
  754         void *arg;
  755 {
  756         /*
  757          * the table to turn MouseSystem button bits (MOUSE_MSC_BUTTON?UP)
  758          * into `mousestatus' button bits (MOUSE_BUTTON?DOWN).
  759          */
  760         static int butmap[8] = {
  761                 0, 
  762                 MOUSE_BUTTON3DOWN, 
  763                 MOUSE_BUTTON2DOWN, 
  764                 MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN, 
  765                 MOUSE_BUTTON1DOWN, 
  766                 MOUSE_BUTTON1DOWN | MOUSE_BUTTON3DOWN, 
  767                 MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN,
  768                 MOUSE_BUTTON1DOWN | MOUSE_BUTTON2DOWN | MOUSE_BUTTON3DOWN
  769         };
  770         mse_softc_t *sc = arg;
  771         int dx, dy, but;
  772         int sign;
  773 
  774 #ifdef DEBUG
  775         static int mse_intrcnt = 0;
  776         if((mse_intrcnt++ % 10000) == 0)
  777                 printf("mseintr\n");
  778 #endif /* DEBUG */
  779         if ((sc->sc_flags & MSESC_OPEN) == 0)
  780                 return;
  781 
  782         (*sc->sc_getmouse)(sc->sc_iot, sc->sc_ioh, &dx, &dy, &but);
  783         if (sc->mode.accelfactor > 0) {
  784                 sign = (dx < 0);
  785                 dx = dx * dx / sc->mode.accelfactor;
  786                 if (dx == 0)
  787                         dx = 1;
  788                 if (sign)
  789                         dx = -dx;
  790                 sign = (dy < 0);
  791                 dy = dy * dy / sc->mode.accelfactor;
  792                 if (dy == 0)
  793                         dy = 1;
  794                 if (sign)
  795                         dy = -dy;
  796         }
  797         sc->sc_deltax += dx;
  798         sc->sc_deltay += dy;
  799         sc->sc_buttons = but;
  800 
  801         but = butmap[~but & MOUSE_MSC_BUTTONS];
  802         sc->status.dx += dx;
  803         sc->status.dy += dy;
  804         sc->status.flags |= ((dx || dy) ? MOUSE_POSCHANGED : 0)
  805             | (sc->status.button ^ but);
  806         sc->status.button = but;
  807 
  808         sc->sc_watchdog = FALSE;
  809 
  810         /*
  811          * If mouse state has changed, wake up anyone wanting to know.
  812          */
  813         if (sc->sc_deltax != 0 || sc->sc_deltay != 0 ||
  814             (sc->sc_obuttons ^ sc->sc_buttons) != 0) {
  815                 if (sc->sc_flags & MSESC_WANT) {
  816                         sc->sc_flags &= ~MSESC_WANT;
  817                         wakeup((caddr_t)sc);
  818                 }
  819                 selwakeup(&sc->sc_selp);
  820         }
  821 }
  822 
  823 #ifndef PC98
  824 /*
  825  * Routines for the Logitech mouse.
  826  */
  827 /*
  828  * Test for a Logitech bus mouse and return 1 if it is.
  829  * (until I know how to use the signature port properly, just disable
  830  *  interrupts and return 1)
  831  */
  832 static int
  833 mse_probelogi(dev, sc)
  834         device_t dev;
  835         mse_softc_t *sc;
  836 {
  837 
  838         int sig;
  839 
  840         bus_space_write_1(sc->sc_iot, sc->sc_ioh, MSE_PORTD, MSE_SETUP);
  841                 /* set the signature port */
  842         bus_space_write_1(sc->sc_iot, sc->sc_ioh, MSE_PORTB, MSE_LOGI_SIG);
  843 
  844         DELAY(30000); /* 30 ms delay */
  845         sig = bus_space_read_1(sc->sc_iot, sc->sc_ioh, MSE_PORTB) & 0xFF;
  846         if (sig == MSE_LOGI_SIG) {
  847                 bus_space_write_1(sc->sc_iot, sc->sc_ioh, MSE_PORTC,
  848                                   MSE_DISINTR);
  849                 return(1);
  850         } else {
  851                 if (bootverbose)
  852                         device_printf(dev, "wrong signature %x\n", sig);
  853                 return(0);
  854         }
  855 }
  856 
  857 /*
  858  * Initialize Logitech mouse and enable interrupts.
  859  */
  860 static void
  861 mse_enablelogi(tag, handle)
  862         bus_space_tag_t tag;
  863         bus_space_handle_t handle;
  864 {
  865         int dx, dy, but;
  866 
  867         bus_space_write_1(tag, handle, MSE_PORTD, MSE_SETUP);
  868         mse_getlogi(tag, handle, &dx, &dy, &but);
  869 }
  870 
  871 /*
  872  * Disable interrupts for Logitech mouse.
  873  */
  874 static void
  875 mse_disablelogi(tag, handle)
  876         bus_space_tag_t tag;
  877         bus_space_handle_t handle;
  878 {
  879 
  880         bus_space_write_1(tag, handle, MSE_PORTC, MSE_DISINTR);
  881 }
  882 
  883 /*
  884  * Get the current dx, dy and button up/down state.
  885  */
  886 static void
  887 mse_getlogi(tag, handle, dx, dy, but)
  888         bus_space_tag_t tag;
  889         bus_space_handle_t handle;
  890         int *dx;
  891         int *dy;
  892         int *but;
  893 {
  894         register char x, y;
  895 
  896         bus_space_write_1(tag, handle, MSE_PORTC, MSE_HOLD | MSE_RXLOW);
  897         x = bus_space_read_1(tag, handle, MSE_PORTA);
  898         *but = (x >> 5) & MOUSE_MSC_BUTTONS;
  899         x &= 0xf;
  900         bus_space_write_1(tag, handle, MSE_PORTC, MSE_HOLD | MSE_RXHIGH);
  901         x |= (bus_space_read_1(tag, handle, MSE_PORTA) << 4);
  902         bus_space_write_1(tag, handle, MSE_PORTC, MSE_HOLD | MSE_RYLOW);
  903         y = (bus_space_read_1(tag, handle, MSE_PORTA) & 0xf);
  904         bus_space_write_1(tag, handle, MSE_PORTC, MSE_HOLD | MSE_RYHIGH);
  905         y |= (bus_space_read_1(tag, handle, MSE_PORTA) << 4);
  906         *dx = x;
  907         *dy = y;
  908         bus_space_write_1(tag, handle, MSE_PORTC, MSE_INTREN);
  909 }
  910 
  911 /*
  912  * Routines for the ATI Inport bus mouse.
  913  */
  914 /*
  915  * Test for a ATI Inport bus mouse and return 1 if it is.
  916  * (do not enable interrupts)
  917  */
  918 static int
  919 mse_probeati(dev, sc)
  920         device_t dev;
  921         mse_softc_t *sc;
  922 {
  923         int i;
  924 
  925         for (i = 0; i < 2; i++)
  926                 if (bus_space_read_1(sc->sc_iot, sc->sc_ioh, MSE_PORTC) == 0xde)
  927                         return (1);
  928         return (0);
  929 }
  930 
  931 /*
  932  * Initialize ATI Inport mouse and enable interrupts.
  933  */
  934 static void
  935 mse_enableati(tag, handle)
  936         bus_space_tag_t tag;
  937         bus_space_handle_t handle;
  938 {
  939 
  940         bus_space_write_1(tag, handle, MSE_PORTA, MSE_INPORT_RESET);
  941         bus_space_write_1(tag, handle, MSE_PORTA, MSE_INPORT_MODE);
  942         bus_space_write_1(tag, handle, MSE_PORTB, MSE_INPORT_INTREN);
  943 }
  944 
  945 /*
  946  * Disable interrupts for ATI Inport mouse.
  947  */
  948 static void
  949 mse_disableati(tag, handle)
  950         bus_space_tag_t tag;
  951         bus_space_handle_t handle;
  952 {
  953 
  954         bus_space_write_1(tag, handle, MSE_PORTA, MSE_INPORT_MODE);
  955         bus_space_write_1(tag, handle, MSE_PORTB, 0);
  956 }
  957 
  958 /*
  959  * Get current dx, dy and up/down button state.
  960  */
  961 static void
  962 mse_getati(tag, handle, dx, dy, but)
  963         bus_space_tag_t tag;
  964         bus_space_handle_t handle;
  965         int *dx;
  966         int *dy;
  967         int *but;
  968 {
  969         register char byte;
  970 
  971         bus_space_write_1(tag, handle, MSE_PORTA, MSE_INPORT_MODE);
  972         bus_space_write_1(tag, handle, MSE_PORTB, MSE_INPORT_HOLD);
  973         bus_space_write_1(tag, handle, MSE_PORTA, MSE_INPORT_STATUS);
  974         *but = ~bus_space_read_1(tag, handle, MSE_PORTB) & MOUSE_MSC_BUTTONS;
  975         bus_space_write_1(tag, handle, MSE_PORTA, MSE_INPORT_DX);
  976         byte = bus_space_read_1(tag, handle, MSE_PORTB);
  977         *dx = byte;
  978         bus_space_write_1(tag, handle, MSE_PORTA, MSE_INPORT_DY);
  979         byte = bus_space_read_1(tag, handle, MSE_PORTB);
  980         *dy = byte;
  981         bus_space_write_1(tag, handle, MSE_PORTA, MSE_INPORT_MODE);
  982         bus_space_write_1(tag, handle, MSE_PORTB, MSE_INPORT_INTREN);
  983 }
  984 #endif
  985 
  986 #ifdef PC98
  987 /*
  988  * Routines for the PC98 bus mouse.
  989  */
  990 
  991 /*
  992  * Test for a PC98 bus mouse and return 1 if it is.
  993  * (do not enable interrupts)
  994  */
  995 static int
  996 mse_probe98m(dev, sc)
  997         device_t dev;
  998         mse_softc_t *sc;
  999 {
 1000         /* mode set */
 1001         bus_space_write_1(sc->sc_iot, sc->sc_ioh, MODE, 0x93);
 1002 
 1003         /* initialize */
 1004         /* INT disable */
 1005         bus_space_write_1(sc->sc_iot, sc->sc_ioh, INT, INT_DISABLE);
 1006         /* HC = 0 */
 1007         bus_space_write_1(sc->sc_iot, sc->sc_ioh, HC, HC_NO_CLEAR);
 1008         /* HC = 1 */
 1009         bus_space_write_1(sc->sc_iot, sc->sc_ioh, HC, HC_CLEAR);
 1010 
 1011         return (1);
 1012 }
 1013 
 1014 /*
 1015  * Initialize PC98 bus mouse and enable interrupts.
 1016  */
 1017 static void
 1018 mse_enable98m(tag, handle)
 1019         bus_space_tag_t tag;
 1020         bus_space_handle_t handle;
 1021 {
 1022         bus_space_write_1(tag, handle, INT, INT_ENABLE);    /* INT enable */
 1023         bus_space_write_1(tag, handle, HC, HC_NO_CLEAR);    /* HC = 0 */
 1024         bus_space_write_1(tag, handle, HC, HC_CLEAR);       /* HC = 1 */
 1025 }
 1026  
 1027 /*
 1028  * Disable interrupts for PC98 Bus mouse.
 1029  */
 1030 static void
 1031 mse_disable98m(tag, handle)
 1032         bus_space_tag_t tag;
 1033         bus_space_handle_t handle;
 1034 {
 1035         bus_space_write_1(tag, handle, INT, INT_DISABLE);   /* INT disable */
 1036         bus_space_write_1(tag, handle, HC, HC_NO_CLEAR);    /* HC = 0 */
 1037         bus_space_write_1(tag, handle, HC, HC_CLEAR);       /* HC = 1 */
 1038 }
 1039 
 1040 /*
 1041  * Get current dx, dy and up/down button state.
 1042  */
 1043 static void
 1044 mse_get98m(tag, handle, dx, dy, but)
 1045         bus_space_tag_t tag;
 1046         bus_space_handle_t handle;
 1047         int *dx;
 1048         int *dy;
 1049         int *but;
 1050 {
 1051         register char x, y;
 1052 
 1053         bus_space_write_1(tag, handle, INT, INT_DISABLE);   /* INT disable */
 1054 
 1055         bus_space_write_1(tag, handle, HC, HC_CLEAR);       /* HC = 1 */
 1056 
 1057         /* X low */
 1058         bus_space_write_1(tag, handle, MSE_PORTC, 0x90 | XL);
 1059         x = bus_space_read_1(tag, handle, MSE_PORTA) & 0x0f;
 1060         /* X high */
 1061         bus_space_write_1(tag, handle, MSE_PORTC, 0x90 | XH);
 1062         x |= ((bus_space_read_1(tag, handle, MSE_PORTA)  & 0x0f) << 4);
 1063 
 1064         /* Y low */
 1065         bus_space_write_1(tag, handle, MSE_PORTC, 0x90 | YL);
 1066         y = (bus_space_read_1(tag, handle, MSE_PORTA) & 0x0f);
 1067         /* Y high */
 1068         bus_space_write_1(tag, handle, MSE_PORTC, 0x90 | YH);
 1069         y |= ((bus_space_read_1(tag, handle, MSE_PORTA) & 0x0f) << 4);
 1070 
 1071         *but = (bus_space_read_1(tag, handle, MSE_PORTA) >> 5) & 7;
 1072 
 1073         *dx = x;
 1074         *dy = y;
 1075 
 1076         bus_space_write_1(tag, handle, HC, HC_NO_CLEAR);    /* HC = 0 */
 1077 
 1078         bus_space_write_1(tag, handle, INT, INT_ENABLE);    /* INT enable */
 1079 }
 1080 #endif

Cache object: eb437c7afbf3909a505bb04c31a3eb6e


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