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


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

FreeBSD/Linux Kernel Cross Reference
sys/dev/ic/spic.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 /*      $NetBSD: spic.c,v 1.1 2002/04/22 12:42:11 augustss Exp $        */
    2 
    3 /*
    4  * Copyright (c) 2002 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Lennart Augustsson (lennart@augustsson.net) at
    9  * Carlstedt Research & Technology.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. All advertising materials mentioning features or use of this software
   20  *    must display the following acknowledgement:
   21  *        This product includes software developed by the NetBSD
   22  *        Foundation, Inc. and its contributors.
   23  * 4. Neither the name of The NetBSD Foundation nor the names of its
   24  *    contributors may be used to endorse or promote products derived
   25  *    from this software without specific prior written permission.
   26  *
   27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   37  * POSSIBILITY OF SUCH DAMAGE.
   38  */
   39 
   40 /*
   41  * The SPIC is used on some Sony Vaios to handle the jog dial and other
   42  * peripherals.
   43  * The protocol used by the SPIC seems to vary wildly among the different
   44  * models, and I've found no documentation.
   45  * This file handles the jog dial on the SRX77 model, and perhaps nothing
   46  * else.
   47  *
   48  * The general way of talking to the SPIC was gleaned from the Linux and
   49  * FreeBSD drivers.  The hex numbers were taken from these drivers (they
   50  * come from reverese engineering.)
   51  *
   52  * TODO:
   53  *   Make it handle more models.
   54  *   Figure out why the interrupt mode doesn't work.
   55  */
   56 
   57 
   58 #include <sys/cdefs.h>
   59 __KERNEL_RCSID(0, "$NetBSD: spic.c,v 1.1 2002/04/22 12:42:11 augustss Exp $");
   60 
   61 #include <sys/param.h>
   62 #include <sys/systm.h>
   63 #include <sys/device.h>
   64 #include <sys/proc.h>
   65 #include <sys/kernel.h>
   66 #include <sys/callout.h>
   67 
   68 #include <machine/bus.h>
   69 
   70 #include <dev/ic/spicvar.h>
   71 
   72 #include <dev/wscons/wsconsio.h>
   73 #include <dev/wscons/wsmousevar.h>
   74 
   75 #define POLLRATE (hz/30)
   76 
   77 /* Some hardware constants */
   78 #define SPIC_PORT1 0
   79 #define SPIC_PORT2 4
   80 
   81 #ifdef SPIC_DEBUG
   82 int spicdebug = 0;
   83 #endif
   84 
   85 static int      spic_enable(void *);
   86 static void     spic_disable(void *);
   87 static int      spic_ioctl(void *, u_long, caddr_t, int, struct proc *);
   88 
   89 static const struct wsmouse_accessops spic_accessops = {
   90         spic_enable,
   91         spic_ioctl,
   92         spic_disable,
   93 };
   94 
   95 #define SPIC_COMMAND(quiet, command) do { \
   96         unsigned int n = 10000; \
   97         while (--n && (command)) \
   98                 delay(1); \
   99         if (n == 0 && !(quiet)) \
  100                 printf("spic: command failed at line %d\n", __LINE__); \
  101 } while (0)
  102 
  103 #if 0
  104 #define INB(sc, p) (delay(100), printf("inb(%x)=%x\n", (uint)sc->sc_ioh+p, bus_space_read_1(sc->sc_iot, sc->sc_ioh, p)), delay(100), bus_space_read_1(sc->sc_iot, sc->sc_ioh, (p)))
  105 #define OUTB(sc, v, p) do { delay(100); bus_space_write_1(sc->sc_iot, sc->sc_ioh, (p), (v)); printf("outb(%x, %x)\n", (uint)sc->sc_ioh+p, v); } while(0)
  106 #else
  107 #define INB(sc, p) (delay(100), bus_space_read_1(sc->sc_iot, sc->sc_ioh, (p)))
  108 #define OUTB(sc, v, p) do { delay(100); bus_space_write_1(sc->sc_iot, sc->sc_ioh, (p), (v)); } while(0)
  109 #endif
  110 
  111 static u_int8_t
  112 spic_call1(struct spic_softc *sc, u_int8_t dev)
  113 {
  114         u_int8_t v1, v2;
  115 
  116         SPIC_COMMAND(0, INB(sc, SPIC_PORT2) & 2);
  117         OUTB(sc, dev, SPIC_PORT2);
  118         v1 = INB(sc, SPIC_PORT2);
  119         v2 = INB(sc, SPIC_PORT1);
  120         return v2;
  121 }
  122 
  123 static u_int8_t
  124 spic_call2(struct spic_softc *sc, u_int8_t dev, u_int8_t fn)
  125 {
  126         u_int8_t v1;
  127 
  128         SPIC_COMMAND(0, INB(sc, SPIC_PORT2) & 2);
  129         OUTB(sc, dev, SPIC_PORT2);
  130         SPIC_COMMAND(0, INB(sc, SPIC_PORT2) & 2);
  131         OUTB(sc, fn, SPIC_PORT1);
  132         v1 = INB(sc, SPIC_PORT1);
  133         return v1;
  134 }
  135 
  136 /* Interrupt handler: some event is available */
  137 int
  138 spic_intr(void *v) {
  139         struct spic_softc *sc = v;
  140         u_int8_t v1, v2;
  141         int dz, buttons;
  142 
  143         v1 = INB(sc, SPIC_PORT1);
  144         v2 = INB(sc, SPIC_PORT2);
  145 
  146         buttons = 0;
  147         if (v1 & 0x40)
  148                 buttons |= 1 << 1;
  149         if (v1 & 0x20)
  150                 buttons |= 1 << 5;
  151         dz = v1 & 0x1f;
  152         switch (dz) {
  153         case 0:
  154         case 1:
  155         case 2:
  156         case 3:
  157                 break;
  158         case 0x1f:
  159         case 0x1e:
  160         case 0x1d:
  161                 dz -= 0x20;
  162                 break;
  163         default:
  164                 printf("spic: v1=0x%02x v2=0x%02x\n", v1, v2);
  165                 goto skip;
  166         }
  167 
  168         if (!sc->sc_enabled) {
  169                 /*printf("spic: not enabled\n");*/
  170                 goto skip;
  171         }
  172 
  173         if (dz != 0 || buttons != sc->sc_buttons) {
  174 #ifdef SPIC_DEBUG
  175                 if (spicdebug)
  176                         printf("spic: but=0x%x dz=%d v1=0x%02x v2=0x%02x\n",
  177                                buttons, dz, v1, v2);
  178 #endif
  179                 sc->sc_buttons = buttons;
  180                 if (sc->sc_wsmousedev != NULL) {
  181                         wsmouse_input(sc->sc_wsmousedev, buttons, 0, 0, dz,
  182                                       WSMOUSE_INPUT_DELTA);
  183                 }
  184         }
  185 
  186 skip:
  187         spic_call2(sc, 0x81, 0xff); /* Clear event */
  188         return (1);
  189 }
  190 
  191 static void
  192 spictimeout(void *v)
  193 {
  194         struct spic_softc *sc = v;
  195         int s = spltty();
  196         spic_intr(v);
  197         splx(s);
  198         callout_reset(&sc->sc_poll, POLLRATE, spictimeout, sc);
  199 }
  200 
  201 void
  202 spic_attach(struct spic_softc *sc)
  203 {
  204         struct wsmousedev_attach_args a;
  205 
  206 #ifdef SPIC_DEBUG
  207         if (spicdebug)
  208                 printf("spic_attach %x %x\n", sc->sc_iot, (uint)sc->sc_ioh);
  209 #endif
  210 
  211         callout_init(&sc->sc_poll);
  212 
  213         spic_call1(sc, 0x82);
  214         spic_call2(sc, 0x81, 0xff);
  215         spic_call1(sc, 0x92);   /* or 0x82 */
  216 
  217         a.accessops = &spic_accessops;
  218         a.accesscookie = sc;
  219         sc->sc_wsmousedev = config_found(&sc->sc_dev, &a, wsmousedevprint);
  220 }
  221 
  222 
  223 static int
  224 spic_enable(void *v)
  225 {
  226         struct spic_softc *sc = v;
  227 
  228         if (sc->sc_enabled)
  229                 return (EBUSY);
  230 
  231         sc->sc_enabled = 1;
  232         sc->sc_buttons = 0;
  233 
  234 #ifdef SPIC_DEBUG
  235         if (spicdebug)
  236                 printf("spic_enable\n");
  237 #endif
  238 
  239         callout_reset(&sc->sc_poll, POLLRATE, spictimeout, sc);
  240 
  241         return (0);
  242 }
  243 
  244 static void
  245 spic_disable(void *v)
  246 {
  247         struct spic_softc *sc = v;
  248 
  249 #ifdef DIAGNOSTIC
  250         if (!sc->sc_enabled) {
  251                 printf("spic_disable: not enabled\n");
  252                 return;
  253         }
  254 #endif
  255 
  256         callout_stop(&sc->sc_poll);
  257 
  258         sc->sc_enabled = 0;
  259 
  260 #ifdef SPIC_DEBUG
  261         if (spicdebug)
  262                 printf("spic_disable\n");
  263 #endif
  264 }
  265 
  266 static int
  267 spic_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct proc *p)
  268 {
  269         switch (cmd) {
  270         case WSMOUSEIO_GTYPE:
  271                 /* XXX this is not really correct */
  272                 *(u_int *)data = WSMOUSE_TYPE_PS2;
  273                 return (0);
  274         }
  275 
  276         return (-1);
  277 }

Cache object: 30ddc5cd343f0ff15eee48bf83cf1687


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