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/tc/zsms.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: zsms.c,v 1.10 2003/08/07 16:31:28 agc Exp $    */
    2 
    3 /*
    4  * Copyright (c) 1992, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * This software was developed by the Computer Systems Engineering group
    8  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
    9  * contributed to Berkeley.
   10  *
   11  * All advertising materials mentioning features or use of this software
   12  * must display the following acknowledgement:
   13  *      This product includes software developed by the University of
   14  *      California, Lawrence Berkeley Laboratory.
   15  *
   16  * Redistribution and use in source and binary forms, with or without
   17  * modification, are permitted provided that the following conditions
   18  * are met:
   19  * 1. Redistributions of source code must retain the above copyright
   20  *    notice, this list of conditions and the following disclaimer.
   21  * 2. Redistributions in binary form must reproduce the above copyright
   22  *    notice, this list of conditions and the following disclaimer in the
   23  *    documentation and/or other materials provided with the distribution.
   24  * 3. Neither the name of the University nor the names of its contributors
   25  *    may be used to endorse or promote products derived from this software
   26  *    without specific prior written permission.
   27  *
   28  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   29  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   31  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   32  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   33  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   34  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   35  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   36  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   37  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   38  * SUCH DAMAGE.
   39  *
   40  *      @(#)ms.c        8.1 (Berkeley) 6/11/93
   41  */
   42 
   43 /*
   44  * VSXXX mice attached with channel A of the 1st SCC
   45  */
   46 
   47 #include <sys/cdefs.h>
   48 __KERNEL_RCSID(0, "$NetBSD: zsms.c,v 1.10 2003/08/07 16:31:28 agc Exp $");
   49 
   50 #include <sys/param.h>
   51 #include <sys/systm.h>
   52 #include <sys/device.h>
   53 #include <sys/ioctl.h>
   54 #include <sys/syslog.h>
   55 #include <sys/kernel.h>
   56 #include <sys/proc.h>
   57 #include <sys/tty.h>
   58 
   59 #include <dev/ic/z8530reg.h>
   60 #include <machine/z8530var.h>
   61 
   62 #include <dev/dec/lk201.h>
   63 
   64 #include <dev/wscons/wsconsio.h>
   65 #include <dev/wscons/wsmousevar.h>
   66 
   67 #include "locators.h"
   68 
   69 /*
   70  * How many input characters we can buffer.
   71  * The port-specific var.h may override this.
   72  * Note: must be a power of two!
   73  */
   74 #define ZSMS_RX_RING_SIZE       256
   75 #define ZSMS_RX_RING_MASK (ZSMS_RX_RING_SIZE-1)
   76 /*
   77  * Output buffer.  Only need a few chars.
   78  */
   79 #define ZSMS_TX_RING_SIZE       16
   80 #define ZSMS_TX_RING_MASK (ZSMS_TX_RING_SIZE-1)
   81 
   82 #define ZSMS_BPS 4800
   83 
   84 struct zsms_softc {             /* driver status information */
   85         struct  device zsms_dev;        /* required first: base device */
   86         struct  zs_chanstate *zsms_cs;
   87 
   88         /* Flags to communicate with zsms_softintr() */
   89         volatile int zsms_intr_flags;
   90 #define INTR_RX_OVERRUN 1
   91 #define INTR_TX_EMPTY   2
   92 #define INTR_ST_CHECK   4
   93 
   94         /*
   95          * The receive ring buffer.
   96          */
   97         u_int   zsms_rbget;     /* ring buffer `get' index */
   98         volatile u_int  zsms_rbput;     /* ring buffer `put' index */
   99         u_short zsms_rbuf[ZSMS_RX_RING_SIZE]; /* rr1, data pairs */
  100 
  101         int sc_enabled;         /* input enabled? */
  102         int sc_selftest;        /* self test in progress */
  103 
  104         int inputstate;
  105         u_int buttons;
  106         int dx, dy;
  107 
  108         struct device *sc_wsmousedev;
  109 };
  110 
  111 struct zsops zsops_zsms;
  112 
  113 static int  zsms_match __P((struct device *, struct cfdata *, void *));
  114 static void zsms_attach __P((struct device *, struct device *, void *));
  115 static void zsms_input __P((void *, int));
  116 
  117 CFATTACH_DECL(zsms, sizeof(struct zsms_softc),
  118     zsms_match, zsms_attach, NULL, NULL);
  119 
  120 static int  zsms_enable __P((void *));
  121 static int  zsms_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
  122 static void zsms_disable __P((void *));
  123 
  124 const struct wsmouse_accessops zsms_accessops = {
  125         zsms_enable,
  126         zsms_ioctl,
  127         zsms_disable,
  128 };
  129 
  130 static int
  131 zsms_match(parent, cf, aux)
  132         struct device *parent;
  133         struct cfdata *cf;
  134         void *aux;
  135 {
  136         struct zsc_attach_args *args = aux;
  137 
  138         /* Exact match is better than wildcard. */
  139         if (cf->cf_loc[ZSCCF_CHANNEL] == args->channel)
  140                 return 2;
  141 
  142         /* This driver accepts wildcard. */
  143         if (cf->cf_loc[ZSCCF_CHANNEL] == ZSCCF_CHANNEL_DEFAULT)
  144                 return 1;
  145 
  146         return 0;
  147 }
  148 
  149 static void
  150 zsms_attach(parent, self, aux)
  151         struct device *parent, *self;
  152         void *aux;
  153 {
  154         struct zsc_softc *zsc = (void *)parent;
  155         struct zsms_softc *zsms = (void *)self;
  156         struct zsc_attach_args *args = aux;
  157         struct zs_chanstate *cs;
  158         struct wsmousedev_attach_args a;
  159         int s;
  160 
  161         cs = zsc->zsc_cs[args->channel];
  162         cs->cs_private = zsms;
  163         cs->cs_ops = &zsops_zsms;
  164         zsms->zsms_cs = cs;
  165 
  166         printf("\n");
  167 
  168         /* Initialize the speed, etc. */
  169         s = splzs();
  170         /* May need reset... */
  171         zs_write_reg(cs, 9, ZSWR9_A_RESET);
  172         /* These are OK as set by zscc: WR3, WR5 */
  173         /* We don't care about status or tx interrupts. */
  174         cs->cs_preg[1] = ZSWR1_RIE;
  175         (void) zs_set_speed(cs, ZSMS_BPS);
  176 
  177         /* mouse wants odd parity */
  178         cs->cs_preg[4] |= ZSWR4_PARENB;
  179         /* cs->cs_preg[4] &= ~ZSWR4_EVENP; (no-op) */
  180 
  181         zs_loadchannelregs(cs);
  182         splx(s);
  183 
  184         a.accessops = &zsms_accessops;
  185         a.accesscookie = zsms;
  186 
  187         zsms->sc_enabled = 0;
  188         zsms->sc_selftest = 0;
  189         zsms->sc_wsmousedev = config_found(self, &a, wsmousedevprint);
  190 }
  191 
  192 static int
  193 zsms_enable(v)
  194         void *v;
  195 {
  196         struct zsms_softc *sc = v;
  197 
  198         if (sc->sc_enabled)
  199                 return EBUSY;
  200 
  201         sc->sc_selftest = 4; /* wait for 4 byte reply upto 1/2 sec */
  202         zs_write_data(sc->zsms_cs,  MOUSE_SELF_TEST);
  203         (void)tsleep(zsms_enable, TTIPRI, "zsmsopen", hz / 2);
  204         if (sc->sc_selftest != 0) {
  205                 sc->sc_selftest = 0;
  206                 return ENXIO;
  207         }
  208         /* XXX DELAY before mode set? */
  209         zs_write_data(sc->zsms_cs, MOUSE_INCREMENTAL);
  210         sc->sc_enabled = 1;
  211         sc->inputstate = 0;
  212         return 0;
  213 }
  214 
  215 static void
  216 zsms_disable(v)
  217         void *v;
  218 {
  219         struct zsms_softc *sc = v;
  220 
  221         sc->sc_enabled = 0;
  222 }
  223 
  224 static int
  225 zsms_ioctl(v, cmd, data, flag, p)
  226         void *v;
  227         u_long cmd;
  228         caddr_t data;
  229         int flag;
  230         struct proc *p;
  231 {
  232 
  233         if (cmd == WSMOUSEIO_GTYPE) {
  234                 *(u_int *)data = WSMOUSE_TYPE_VSXXX;
  235                 return 0;
  236         }
  237         return EPASSTHROUGH;
  238 }
  239 
  240 static void
  241 zsms_input(vsc, data)
  242         void *vsc;
  243         int data;
  244 {
  245         struct zsms_softc *sc = vsc;
  246 
  247         if (sc->sc_enabled == 0) {
  248                 if (sc->sc_selftest > 0) {
  249                         sc->sc_selftest -= 1;
  250                         if (sc->sc_selftest == 0)
  251                                 wakeup(zsms_enable);
  252                 }
  253                 return;
  254         }
  255 
  256         if ((data & MOUSE_START_FRAME) != 0)
  257                 sc->inputstate = 1;
  258         else
  259                 sc->inputstate++;
  260 
  261         if (sc->inputstate == 1) {
  262                 /* LMR -> RML: wsevents counts 0 for the left-most */
  263                 sc->buttons = data & 02;
  264                 if (data & 01)
  265                         sc->buttons |= 04;
  266                 if (data & 04)
  267                         sc->buttons |= 01;
  268                 sc->dx = data & MOUSE_X_SIGN;
  269                 sc->dy = data & MOUSE_Y_SIGN;
  270         } else if (sc->inputstate == 2) {
  271                 if (sc->dx == 0)
  272                         sc->dx = -data;
  273                 else
  274                         sc->dx = data;
  275         } else if (sc->inputstate == 3) {
  276                 sc->inputstate = 0;
  277                 if (sc->dy == 0)
  278                         sc->dy = -data;
  279                 else
  280                         sc->dy = data;
  281                 wsmouse_input(sc->sc_wsmousedev, sc->buttons,
  282                     sc->dx, sc->dy, 0, WSMOUSE_INPUT_DELTA);
  283         }
  284 
  285         return;
  286 }
  287 
  288 /****************************************************************
  289  * Interface to the lower layer (zscc)
  290  ****************************************************************/
  291 
  292 static void zsms_rxint __P((struct zs_chanstate *));
  293 static void zsms_stint __P((struct zs_chanstate *, int));
  294 static void zsms_txint __P((struct zs_chanstate *));
  295 static void zsms_softint __P((struct zs_chanstate *));
  296 
  297 static void
  298 zsms_rxint(cs)
  299         struct zs_chanstate *cs;
  300 {
  301         struct zsms_softc *zsms;
  302         int put, put_next;
  303         u_char c, rr1;
  304 
  305         zsms = cs->cs_private;
  306         put = zsms->zsms_rbput;
  307 
  308         /*
  309          * First read the status, because reading the received char
  310          * destroys the status of this char.
  311          */
  312         rr1 = zs_read_reg(cs, 1);
  313         c = zs_read_data(cs);
  314         if (rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) {
  315                 /* Clear the receive error. */
  316                 zs_write_csr(cs, ZSWR0_RESET_ERRORS);
  317         }
  318 
  319         zsms->zsms_rbuf[put] = (c << 8) | rr1;
  320         put_next = (put + 1) & ZSMS_RX_RING_MASK;
  321 
  322         /* Would overrun if increment makes (put==get). */
  323         if (put_next == zsms->zsms_rbget) {
  324                 zsms->zsms_intr_flags |= INTR_RX_OVERRUN;
  325         } else {
  326                 /* OK, really increment. */
  327                 put = put_next;
  328         }
  329 
  330         /* Done reading. */
  331         zsms->zsms_rbput = put;
  332 
  333         /* Ask for softint() call. */
  334         cs->cs_softreq = 1;
  335 }
  336 
  337 
  338 static void
  339 zsms_txint(cs)
  340         struct zs_chanstate *cs;
  341 {
  342         struct zsms_softc *zsms;
  343 
  344         zsms = cs->cs_private;
  345         zs_write_csr(cs, ZSWR0_RESET_TXINT);
  346         zsms->zsms_intr_flags |= INTR_TX_EMPTY;
  347         /* Ask for softint() call. */
  348         cs->cs_softreq = 1;
  349 }
  350 
  351 
  352 static void
  353 zsms_stint(cs, force)
  354         struct zs_chanstate *cs;
  355         int force;
  356 {
  357         struct zsms_softc *zsms;
  358         int rr0;
  359 
  360         zsms = cs->cs_private;
  361 
  362         rr0 = zs_read_csr(cs);
  363         zs_write_csr(cs, ZSWR0_RESET_STATUS);
  364 
  365         /*
  366          * We have to accumulate status line changes here.
  367          * Otherwise, if we get multiple status interrupts
  368          * before the softint runs, we could fail to notice
  369          * some status line changes in the softint routine.
  370          * Fix from Bill Studenmund, October 1996.
  371          */
  372         cs->cs_rr0_delta |= (cs->cs_rr0 ^ rr0);
  373         cs->cs_rr0 = rr0;
  374         zsms->zsms_intr_flags |= INTR_ST_CHECK;
  375 
  376         /* Ask for softint() call. */
  377         cs->cs_softreq = 1;
  378 }
  379 
  380 
  381 static void
  382 zsms_softint(cs)
  383         struct zs_chanstate *cs;
  384 {
  385         struct zsms_softc *zsms;
  386         int get, c, s;
  387         int intr_flags;
  388         u_short ring_data;
  389 
  390         zsms = cs->cs_private;
  391 
  392         /* Atomically get and clear flags. */
  393         s = splzs();
  394         intr_flags = zsms->zsms_intr_flags;
  395         zsms->zsms_intr_flags = 0;
  396 
  397         /* Now lower to spltty for the rest. */
  398         (void) spltty();
  399 
  400         /*
  401          * Copy data from the receive ring to the event layer.
  402          */
  403         get = zsms->zsms_rbget;
  404         while (get != zsms->zsms_rbput) {
  405                 ring_data = zsms->zsms_rbuf[get];
  406                 get = (get + 1) & ZSMS_RX_RING_MASK;
  407 
  408                 /* low byte of ring_data is rr1 */
  409                 c = (ring_data >> 8) & 0xff;
  410 
  411                 if (ring_data & ZSRR1_DO)
  412                         intr_flags |= INTR_RX_OVERRUN;
  413                 if (ring_data & (ZSRR1_FE | ZSRR1_PE)) {
  414                         log(LOG_ERR, "%s: input error (0x%x)\n",
  415                                 zsms->zsms_dev.dv_xname, ring_data);
  416                         c = -1; /* signal input error */
  417                 }
  418 
  419                 /* Pass this up to the "middle" layer. */
  420                 zsms_input(zsms, c);
  421         }
  422         if (intr_flags & INTR_RX_OVERRUN) {
  423                 log(LOG_ERR, "%s: input overrun\n",
  424                     zsms->zsms_dev.dv_xname);
  425         }
  426         zsms->zsms_rbget = get;
  427 
  428         if (intr_flags & INTR_TX_EMPTY) {
  429                 /*
  430                  * Transmit done.  (Not expected.)
  431                  */
  432                 log(LOG_ERR, "%s: transmit interrupt?\n",
  433                     zsms->zsms_dev.dv_xname);
  434         }
  435 
  436         if (intr_flags & INTR_ST_CHECK) {
  437                 /*
  438                  * Status line change.  (Not expected.)
  439                  */
  440                 log(LOG_ERR, "%s: status interrupt?\n",
  441                     zsms->zsms_dev.dv_xname);
  442                 cs->cs_rr0_delta = 0;
  443         }
  444 
  445         splx(s);
  446 }
  447 
  448 struct zsops zsops_zsms = {
  449         zsms_rxint,     /* receive char available */
  450         zsms_stint,     /* external/status */
  451         zsms_txint,     /* xmit buffer empty */
  452         zsms_softint,   /* process software interrupt */
  453 };

Cache object: 94094597947a5b1949fb73e1ff7a5d75


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