root/arch/i386/isa/mms.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. mmsprobe
  2. mmsattach
  3. mms_enable
  4. mms_disable
  5. mms_ioctl
  6. mmsintr

    1 /* $OpenBSD: mms.c,v 1.19 2007/04/10 22:37:17 miod Exp $ */
    2 /*      $NetBSD: mms.c,v 1.35 2000/01/08 02:57:25 takemura Exp $        */
    3 
    4 /*-
    5  * Copyright (c) 1993, 1994 Charles M. Hannum.
    6  * Copyright (c) 1992, 1993 Erik Forsberg.
    7  * All rights reserved.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
   16  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
   17  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
   18  * NO EVENT SHALL I BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   22  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   23  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   24  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/param.h>
   28 #include <sys/systm.h>
   29 #include <sys/ioctl.h>
   30 #include <sys/device.h>
   31 
   32 #include <machine/intr.h>
   33 #include <machine/bus.h>
   34 
   35 #include <dev/isa/isavar.h>
   36 
   37 #include <dev/wscons/wsconsio.h>
   38 #include <dev/wscons/wsmousevar.h>
   39 
   40 #define MMS_ADDR        0       /* offset for register select */
   41 #define MMS_DATA        1       /* offset for InPort data */
   42 #define MMS_IDENT       2       /* offset for identification register */
   43 #define MMS_NPORTS      4
   44 
   45 struct mms_softc {              /* driver status information */
   46         struct device sc_dev;
   47         void *sc_ih;
   48 
   49         bus_space_tag_t sc_iot;
   50         bus_space_handle_t sc_ioh;
   51 
   52         int sc_enabled; /* device is open */
   53 
   54         struct device *sc_wsmousedev;
   55 };
   56 
   57 int mmsprobe(struct device *, void *, void *);
   58 void mmsattach(struct device *, struct device *, void *);
   59 int mmsintr(void *);
   60 
   61 struct cfattach mms_ca = {
   62         sizeof(struct mms_softc), mmsprobe, mmsattach
   63 };
   64 
   65 int     mms_enable(void *);
   66 int     mms_ioctl(void *, u_long, caddr_t, int, struct proc *);
   67 void    mms_disable(void *);
   68 
   69 const struct wsmouse_accessops mms_accessops = {
   70         mms_enable,
   71         mms_ioctl,
   72         mms_disable,
   73 };
   74 
   75 int
   76 mmsprobe(struct device *parent, void *match, void *aux)
   77 {
   78         struct isa_attach_args *ia = aux;
   79         bus_space_tag_t iot = ia->ia_iot;
   80         bus_space_handle_t ioh;
   81         int rv;
   82 
   83         /* Disallow wildcarded i/o address. */
   84         if (ia->ia_iobase == IOBASEUNK)
   85                 return 0;
   86 
   87         /* Map the i/o space. */
   88         if (bus_space_map(iot, ia->ia_iobase, MMS_NPORTS, 0, &ioh))
   89                 return 0;
   90 
   91         rv = 0;
   92 
   93         /* Read identification register to see if present */
   94         if (bus_space_read_1(iot, ioh, MMS_IDENT) != 0xde)
   95                 goto out;
   96 
   97         /* Seems it was there; reset. */
   98         bus_space_write_1(iot, ioh, MMS_ADDR, 0x87);
   99 
  100         rv = 1;
  101         ia->ia_iosize = MMS_NPORTS;
  102         ia->ia_msize = 0;
  103 
  104 out:
  105         bus_space_unmap(iot, ioh, MMS_NPORTS);
  106         return rv;
  107 }
  108 
  109 void
  110 mmsattach(struct device *parent, struct device *self, void *aux)
  111 {
  112         struct mms_softc *sc = (void *)self;
  113         struct isa_attach_args *ia = aux;
  114         bus_space_tag_t iot = ia->ia_iot;
  115         bus_space_handle_t ioh;
  116         struct wsmousedev_attach_args a;
  117 
  118         printf("\n");
  119 
  120         if (bus_space_map(iot, ia->ia_iobase, MMS_NPORTS, 0, &ioh)) {
  121                 printf("%s: can't map i/o space\n", sc->sc_dev.dv_xname);
  122                 return;
  123         }
  124 
  125         /* Other initialization was done by mmsprobe. */
  126         sc->sc_iot = iot;
  127         sc->sc_ioh = ioh;
  128         sc->sc_enabled = 0;
  129 
  130         sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_PULSE,
  131             IPL_TTY, mmsintr, sc, sc->sc_dev.dv_xname);
  132 
  133         a.accessops = &mms_accessops;
  134         a.accesscookie = sc;
  135 
  136         /*
  137          * Attach the wsmouse, saving a handle to it.
  138          * Note that we don't need to check this pointer against NULL
  139          * here or in psmintr, because if this fails lms_enable() will
  140          * never be called, so lmsintr() will never be called.
  141          */
  142         sc->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
  143 }
  144 
  145 int
  146 mms_enable(void *v)
  147 {
  148         struct mms_softc *sc = v;
  149 
  150         if (sc->sc_enabled)
  151                 return EBUSY;
  152 
  153         sc->sc_enabled = 1;
  154 
  155         /* Enable interrupts. */
  156         bus_space_write_1(sc->sc_iot, sc->sc_ioh, MMS_ADDR, 0x07);
  157         bus_space_write_1(sc->sc_iot, sc->sc_ioh, MMS_DATA, 0x09);
  158 
  159         return 0;
  160 }
  161 
  162 void
  163 mms_disable(void *v)
  164 {
  165         struct mms_softc *sc = v;
  166 
  167         /* Disable interrupts. */
  168         bus_space_write_1(sc->sc_iot, sc->sc_ioh, MMS_ADDR, 0x87);
  169 
  170         sc->sc_enabled = 0;
  171 }
  172 
  173 int
  174 mms_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
  175 {
  176 #if 0
  177         struct mms_softc *sc = v;
  178 #endif
  179 
  180         switch (cmd) {
  181         case WSMOUSEIO_GTYPE:
  182                 *(u_int *)data = WSMOUSE_TYPE_MMS;
  183                 return (0);
  184         }
  185         return (-1);
  186 }
  187 
  188 int
  189 mmsintr(void *arg)
  190 {
  191         struct mms_softc *sc = arg;
  192         bus_space_tag_t iot = sc->sc_iot;
  193         bus_space_handle_t ioh = sc->sc_ioh;
  194         u_char status;
  195         signed char dx, dy;
  196         u_int buttons;
  197         int changed;
  198 
  199         if (!sc->sc_enabled)
  200                 /* Interrupts are not expected. */
  201                 return 0;
  202 
  203         /* Freeze InPort registers (disabling interrupts). */
  204         bus_space_write_1(iot, ioh, MMS_ADDR, 0x07);
  205         bus_space_write_1(iot, ioh, MMS_DATA, 0x29);
  206 
  207         bus_space_write_1(iot, ioh, MMS_ADDR, 0x00);
  208         status = bus_space_read_1(iot, ioh, MMS_DATA);
  209 
  210         if (status & 0x40) {
  211                 bus_space_write_1(iot, ioh, MMS_ADDR, 1);
  212                 dx = bus_space_read_1(iot, ioh, MMS_DATA);
  213                 /* Bounding at -127 avoids a bug in XFree86. */
  214                 dx = (dx == -128) ? -127 : dx;
  215 
  216                 bus_space_write_1(iot, ioh, MMS_ADDR, 2);
  217                 dy = bus_space_read_1(iot, ioh, MMS_DATA);
  218                 dy = (dy == -128) ? 127 : -dy;
  219         } else
  220                 dx = dy = 0;
  221 
  222         /* Unfreeze InPort registers (reenabling interrupts). */
  223         bus_space_write_1(iot, ioh, MMS_ADDR, 0x07);
  224         bus_space_write_1(iot, ioh, MMS_DATA, 0x09);
  225 
  226         buttons = ((status & 0x04) ? 0x1 : 0) |
  227                 ((status & 0x02) ? 0x2 : 0) |
  228                 ((status & 0x01) ? 0x4 : 0);
  229         changed = status & 0x38;
  230 
  231         if (dx || dy || changed)
  232                 wsmouse_input(sc->sc_wsmousedev,
  233                               buttons, dx, dy, 0, 0, WSMOUSE_INPUT_DELTA);
  234 
  235         return -1;
  236 }
  237 
  238 struct cfdriver mms_cd = {
  239         NULL, "mms", DV_DULL
  240 };

/* [<][>][^][v][top][bottom][index][help] */