[BACK]Return to spic.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / ic

Annotation of src/sys/dev/ic/spic.c, Revision 1.1.8.2

1.1.8.2 ! jdolecek    1: /*     $NetBSD: spic.c,v 1.1.8.1 2002/06/23 17:46:51 jdolecek 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.8.1 2002/06/23 17:46:51 jdolecek 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: }

CVSweb <webmaster@jp.NetBSD.org>