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/sun/kbd_zs.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: kbd_zs.c,v 1.16 2003/08/07 16:31:25 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  *      @(#)kbd.c       8.2 (Berkeley) 10/30/93
   41  */
   42 
   43 /*
   44  * /dev/kbd lower layer for sun keyboard off a zs channel.
   45  * This driver uses kbdsun middle layer to hook up to /dev/kbd.
   46  */
   47 
   48 /*
   49  * Zilog Z8530 Dual UART driver (keyboard interface)
   50  *
   51  * This is the 8530 portion of the driver that will be attached to
   52  * the "zsc" driver for a Sun keyboard.
   53  */
   54 
   55 #include <sys/cdefs.h>
   56 __KERNEL_RCSID(0, "$NetBSD: kbd_zs.c,v 1.16 2003/08/07 16:31:25 agc Exp $");
   57 
   58 #include <sys/param.h>
   59 #include <sys/systm.h>
   60 #include <sys/conf.h>
   61 #include <sys/device.h>
   62 #include <sys/kernel.h>
   63 #include <sys/malloc.h>
   64 #include <sys/proc.h>
   65 #include <sys/signal.h>
   66 #include <sys/signalvar.h>
   67 #include <sys/time.h>
   68 #include <sys/select.h>
   69 #include <sys/syslog.h>
   70 
   71 #include <dev/ic/z8530reg.h>
   72 #include <machine/z8530var.h>
   73 #include <dev/sun/vuid_event.h>
   74 #include <dev/sun/event_var.h>
   75 #include <dev/sun/kbd_reg.h>
   76 #include <dev/sun/kbd_xlate.h>
   77 #include <dev/sun/kbdvar.h>
   78 #include <dev/sun/kbdsunvar.h>
   79 
   80 
   81 /****************************************************************
   82  * Interface to the lower layer (zscc)
   83  ****************************************************************/
   84 
   85 static void kbd_zs_rxint __P((struct zs_chanstate *));
   86 static void kbd_zs_stint __P((struct zs_chanstate *, int));
   87 static void kbd_zs_txint __P((struct zs_chanstate *));
   88 static void kbd_zs_softint __P((struct zs_chanstate *));
   89 
   90 struct zsops zsops_kbd = {
   91         kbd_zs_rxint,   /* receive char available */
   92         kbd_zs_stint,   /* external/status */
   93         kbd_zs_txint,   /* xmit buffer empty */
   94         kbd_zs_softint, /* process software interrupt */
   95 };
   96 
   97 static int      kbd_zs_match(struct device *, struct cfdata *, void *);
   98 static void     kbd_zs_attach(struct device *, struct device *, void *);
   99 static void     kbd_zs_write_data __P((struct kbd_sun_softc *, int));
  100 
  101 CFATTACH_DECL(kbd_zs, sizeof(struct kbd_sun_softc),
  102     kbd_zs_match, kbd_zs_attach, NULL, NULL);
  103 
  104 /* Fall-back baud rate */
  105 int     kbd_zs_bps = KBD_DEFAULT_BPS;
  106 
  107 /*
  108  * kbd_zs_match: how is this zs channel configured?
  109  */
  110 int 
  111 kbd_zs_match(parent, cf, aux)
  112         struct device *parent;
  113         struct cfdata *cf;
  114         void   *aux;
  115 {
  116         struct zsc_attach_args *args = aux;
  117 
  118         /* Exact match required for keyboard. */
  119         if (cf->cf_loc[ZSCCF_CHANNEL] == args->channel)
  120                 return 2;
  121 
  122         return 0;
  123 }
  124 
  125 void 
  126 kbd_zs_attach(parent, self, aux)
  127         struct device *parent, *self;
  128         void   *aux;
  129 
  130 {
  131         struct zsc_softc *zsc = (void *) parent;
  132         struct kbd_sun_softc *k = (void *) self;
  133         struct zsc_attach_args *args = aux;
  134         struct zs_chanstate *cs;
  135         int channel;
  136         int reset, s;
  137         int bps;
  138 
  139         /* provide upper layer with a link to the middle layer */
  140         k->k_kbd.k_ops = &kbd_ops_sun;
  141 
  142         /* provide middle layer with a link to the lower layer (i.e. us) */
  143         channel = args->channel;
  144         cs = zsc->zsc_cs[channel];
  145         cs->cs_private = k;
  146         cs->cs_ops = &zsops_kbd;
  147         k->k_cs = cs;
  148         k->k_write_data = kbd_zs_write_data;
  149 
  150         if ((bps = cs->cs_defspeed) == 0)
  151                 bps = kbd_zs_bps;
  152 
  153         printf(": baud rate %d", bps);
  154 
  155         if ((args->hwflags & ZS_HWFLAG_CONSOLE_INPUT) != 0) {
  156                 /*
  157                  * Hookup ourselves as the console input channel
  158                  */
  159                 struct cons_channel *cc = kbd_cc_alloc(&k->k_kbd);
  160 
  161                 if (cc == NULL)
  162                         return;
  163 
  164                 cons_attach_input(cc, args->consdev);
  165                 k->k_kbd.k_isconsole = 1;
  166                 printf(" (console input)");
  167         }
  168         printf("\n");
  169 
  170         /* Initialize the speed, etc. */
  171         s = splzs();
  172         if (k->k_kbd.k_isconsole == 0) {
  173                 /* Not the console; may need reset. */
  174                 reset = (channel == 0) ?
  175                         ZSWR9_A_RESET : ZSWR9_B_RESET;
  176                 zs_write_reg(cs, 9, reset);
  177         }
  178         /* These are OK as set by zscc: WR3, WR4, WR5 */
  179         /* We don't care about status interrupts. */
  180         cs->cs_preg[1] = ZSWR1_RIE | ZSWR1_TIE;
  181         (void) zs_set_speed(cs, bps);
  182         zs_loadchannelregs(cs);
  183         splx(s);
  184 
  185         /* Do this before any calls to kbd_rint(). */
  186         kbd_xlate_init(&k->k_kbd.k_state);
  187 
  188         /* Magic sequence. */
  189         k->k_magic1 = KBD_L1;
  190         k->k_magic2 = KBD_A;
  191 }
  192 
  193 /*
  194  * used by kbd_sun_start_tx();
  195  */
  196 void
  197 kbd_zs_write_data(k, c)
  198         struct kbd_sun_softc *k;
  199         int c;
  200 {
  201         int     s;
  202 
  203         /* Need splzs to avoid interruption of the delay. */
  204         s = splzs();
  205         zs_write_data(k->k_cs, c);
  206         splx(s);
  207 }
  208 
  209 static void
  210 kbd_zs_rxint(cs)
  211         struct zs_chanstate *cs;
  212 {
  213         struct kbd_sun_softc *k;
  214         int put, put_next;
  215         u_char c, rr1;
  216 
  217         k = cs->cs_private;
  218         put = k->k_rbput;
  219 
  220         /*
  221          * First read the status, because reading the received char
  222          * destroys the status of this char.
  223          */
  224         rr1 = zs_read_reg(cs, 1);
  225         c = zs_read_data(cs);
  226 
  227         if (rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) {
  228                 /* Clear the receive error. */
  229                 zs_write_csr(cs, ZSWR0_RESET_ERRORS);
  230         }
  231 
  232         /*
  233          * Check NOW for a console abort sequence, so that we can
  234          * abort even when interrupts are locking up the machine.
  235          */
  236         if (k->k_magic1_down) {
  237                 /* The last keycode was "MAGIC1" down. */
  238                 k->k_magic1_down = 0;
  239                 if (c == k->k_magic2) {
  240                         /* Magic "L1-A" sequence; enter debugger. */
  241                         if (k->k_kbd.k_isconsole) {
  242                                 zs_abort(cs);
  243                                 /* Debugger done.  Fake L1-up to finish it. */
  244                                 c = k->k_magic1 | KBD_UP;
  245                         } else {
  246                                 printf("kbd: magic sequence, but not console\n");
  247                         }
  248                 }
  249         }
  250         if (c == k->k_magic1) {
  251                 k->k_magic1_down = 1;
  252         }
  253 
  254         k->k_rbuf[put] = (c << 8) | rr1;
  255         put_next = (put + 1) & KBD_RX_RING_MASK;
  256 
  257         /* Would overrun if increment makes (put==get). */
  258         if (put_next == k->k_rbget) {
  259                 k->k_intr_flags |= INTR_RX_OVERRUN;
  260         } else {
  261                 /* OK, really increment. */
  262                 put = put_next;
  263         }
  264 
  265         /* Done reading. */
  266         k->k_rbput = put;
  267 
  268         /* Ask for softint() call. */
  269         cs->cs_softreq = 1;
  270 }
  271 
  272 
  273 static void
  274 kbd_zs_txint(cs)
  275         struct zs_chanstate *cs;
  276 {
  277         struct kbd_sun_softc *k;
  278 
  279         k = cs->cs_private;
  280         zs_write_csr(cs, ZSWR0_RESET_TXINT);
  281         k->k_intr_flags |= INTR_TX_EMPTY;
  282         /* Ask for softint() call. */
  283         cs->cs_softreq = 1;
  284 }
  285 
  286 
  287 static void
  288 kbd_zs_stint(cs, force)
  289         struct zs_chanstate *cs;
  290         int force;
  291 {
  292         struct kbd_sun_softc *k;
  293         int rr0;
  294 
  295         k = cs->cs_private;
  296 
  297         rr0 = zs_read_csr(cs);
  298         zs_write_csr(cs, ZSWR0_RESET_STATUS);
  299 
  300 #if 0
  301         if (rr0 & ZSRR0_BREAK) {
  302                 /* Keyboard unplugged? */
  303                 zs_abort(cs);
  304                 return (0);
  305         }
  306 #endif
  307 
  308         /*
  309          * We have to accumulate status line changes here.
  310          * Otherwise, if we get multiple status interrupts
  311          * before the softint runs, we could fail to notice
  312          * some status line changes in the softint routine.
  313          * Fix from Bill Studenmund, October 1996.
  314          */
  315         cs->cs_rr0_delta |= (cs->cs_rr0 ^ rr0);
  316         cs->cs_rr0 = rr0;
  317         k->k_intr_flags |= INTR_ST_CHECK;
  318 
  319         /* Ask for softint() call. */
  320         cs->cs_softreq = 1;
  321 }
  322 
  323 /*
  324  * Get input from the receive ring and pass it on.
  325  * Note: this is called at splsoftclock()
  326  */
  327 static void
  328 kbd_zs_softint(cs)
  329         struct zs_chanstate *cs;
  330 {
  331         struct kbd_sun_softc *k;
  332         int get, c, s;
  333         int intr_flags;
  334         u_short ring_data;
  335 
  336         k = cs->cs_private;
  337 
  338         /* Atomically get and clear flags. */
  339         s = splzs();
  340         intr_flags = k->k_intr_flags;
  341         k->k_intr_flags = 0;
  342 
  343         /* Now lower to spltty for the rest. */
  344         (void) spltty();
  345 
  346         /*
  347          * Copy data from the receive ring to the event layer.
  348          */
  349         get = k->k_rbget;
  350         while (get != k->k_rbput) {
  351                 ring_data = k->k_rbuf[get];
  352                 get = (get + 1) & KBD_RX_RING_MASK;
  353 
  354                 /* low byte of ring_data is rr1 */
  355                 c = (ring_data >> 8) & 0xff;
  356 
  357                 if (ring_data & ZSRR1_DO)
  358                         intr_flags |= INTR_RX_OVERRUN;
  359                 if (ring_data & (ZSRR1_FE | ZSRR1_PE)) {
  360                         /*
  361                          * After garbage, flush pending input, and
  362                          * send a reset to resync key translation.
  363                          */
  364                         log(LOG_ERR, "%s: input error (0x%x)\n",
  365                                 k->k_kbd.k_dev.dv_xname, ring_data);
  366                         get = k->k_rbput; /* flush */
  367                         goto send_reset;
  368                 }
  369 
  370                 /* Pass this up to the "middle" layer. */
  371                 kbd_sun_input(k, c);
  372         }
  373         if (intr_flags & INTR_RX_OVERRUN) {
  374                 log(LOG_ERR, "%s: input overrun\n",
  375                     k->k_kbd.k_dev.dv_xname);
  376         send_reset:
  377                 /* Send a reset to resync translation. */
  378                 kbd_sun_output(k, KBD_CMD_RESET);
  379                 kbd_sun_start_tx(k);
  380         }
  381         k->k_rbget = get;
  382 
  383         if (intr_flags & INTR_TX_EMPTY) {
  384                 /*
  385                  * Transmit done.  Try to send more, or
  386                  * clear busy and wakeup drain waiters.
  387                  */
  388                 k->k_txflags &= ~K_TXBUSY;
  389                 kbd_sun_start_tx(k);
  390         }
  391 
  392         if (intr_flags & INTR_ST_CHECK) {
  393                 /*
  394                  * Status line change.  (Not expected.)
  395                  */
  396                 log(LOG_ERR, "%s: status interrupt?\n",
  397                     k->k_kbd.k_dev.dv_xname);
  398                 cs->cs_rr0_delta = 0;
  399         }
  400 
  401         splx(s);
  402 }

Cache object: dffe561ac2f06f399ad5c770051a94fe


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