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/z8530sc.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: z8530sc.c,v 1.28.14.1 2011/01/16 12:54:43 bouyer 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  *      @(#)zs.c        8.1 (Berkeley) 7/19/93
   41  */
   42 
   43 /*
   44  * Copyright (c) 1994 Gordon W. Ross
   45  *
   46  * This software was developed by the Computer Systems Engineering group
   47  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
   48  * contributed to Berkeley.
   49  *
   50  * All advertising materials mentioning features or use of this software
   51  * must display the following acknowledgement:
   52  *      This product includes software developed by the University of
   53  *      California, Lawrence Berkeley Laboratory.
   54  *
   55  * Redistribution and use in source and binary forms, with or without
   56  * modification, are permitted provided that the following conditions
   57  * are met:
   58  * 1. Redistributions of source code must retain the above copyright
   59  *    notice, this list of conditions and the following disclaimer.
   60  * 2. Redistributions in binary form must reproduce the above copyright
   61  *    notice, this list of conditions and the following disclaimer in the
   62  *    documentation and/or other materials provided with the distribution.
   63  * 3. All advertising materials mentioning features or use of this software
   64  *    must display the following acknowledgement:
   65  *      This product includes software developed by the University of
   66  *      California, Berkeley and its contributors.
   67  * 4. Neither the name of the University nor the names of its contributors
   68  *    may be used to endorse or promote products derived from this software
   69  *    without specific prior written permission.
   70  *
   71  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   72  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   73  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   74  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   75  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   76  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   77  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   78  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   79  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   80  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   81  * SUCH DAMAGE.
   82  *
   83  *      @(#)zs.c        8.1 (Berkeley) 7/19/93
   84  */
   85 
   86 /*
   87  * Zilog Z8530 Dual UART driver (common part)
   88  *
   89  * This file contains the machine-independent parts of the
   90  * driver common to tty and keyboard/mouse sub-drivers.
   91  */
   92 
   93 #include <sys/cdefs.h>
   94 __KERNEL_RCSID(0, "$NetBSD: z8530sc.c,v 1.28.14.1 2011/01/16 12:54:43 bouyer Exp $");
   95 
   96 #include <sys/param.h>
   97 #include <sys/systm.h>
   98 #include <sys/proc.h>
   99 #include <sys/device.h>
  100 #include <sys/conf.h>
  101 #include <sys/file.h>
  102 #include <sys/ioctl.h>
  103 #include <sys/tty.h>
  104 #include <sys/time.h>
  105 #include <sys/kernel.h>
  106 #include <sys/syslog.h>
  107 
  108 #include <dev/ic/z8530reg.h>
  109 #include <machine/z8530var.h>
  110 
  111 void
  112 zs_break(struct zs_chanstate *cs, int set)
  113 {
  114 
  115         if (set) {
  116                 cs->cs_preg[5] |= ZSWR5_BREAK;
  117                 cs->cs_creg[5] |= ZSWR5_BREAK;
  118         } else {
  119                 cs->cs_preg[5] &= ~ZSWR5_BREAK;
  120                 cs->cs_creg[5] &= ~ZSWR5_BREAK;
  121         }
  122         zs_write_reg(cs, 5, cs->cs_creg[5]);
  123 }
  124 
  125 
  126 /*
  127  * drain on-chip fifo
  128  */
  129 void
  130 zs_iflush(struct zs_chanstate *cs)
  131 {
  132         uint8_t c, rr0, rr1;
  133         int i;
  134 
  135         /*
  136          * Count how many times we loop. Some systems, such as some
  137          * Apple PowerBooks, claim to have SCC's which they really don't.
  138          */
  139         for (i = 0; i < 32; i++) {
  140                 /* Is there input available? */
  141                 rr0 = zs_read_csr(cs);
  142                 if ((rr0 & ZSRR0_RX_READY) == 0)
  143                         break;
  144 
  145                 /*
  146                  * First read the status, because reading the data
  147                  * destroys the status of this char.
  148                  */
  149                 rr1 = zs_read_reg(cs, 1);
  150                 c = zs_read_data(cs);
  151 
  152                 if (rr1 & (ZSRR1_FE | ZSRR1_DO | ZSRR1_PE)) {
  153                         /* Clear the receive error. */
  154                         zs_write_csr(cs, ZSWR0_RESET_ERRORS);
  155                 }
  156         }
  157 }
  158 
  159 
  160 /*
  161  * Write the given register set to the given zs channel in the proper order.
  162  * The channel must not be transmitting at the time.  The receiver will
  163  * be disabled for the time it takes to write all the registers.
  164  * Call this with interrupts disabled.
  165  */
  166 void
  167 zs_loadchannelregs(struct zs_chanstate *cs)
  168 {
  169         uint8_t *reg, v;
  170 
  171         zs_write_csr(cs, ZSM_RESET_ERR); /* XXX: reset error condition */
  172 
  173 #if 1
  174         /*
  175          * XXX: Is this really a good idea?
  176          * XXX: Should go elsewhere! -gwr
  177          */
  178         zs_iflush(cs);  /* XXX */
  179 #endif
  180 
  181         if (cs->cs_ctl_chan != NULL)
  182                 v = ((cs->cs_ctl_chan->cs_creg[5] & (ZSWR5_RTS | ZSWR5_DTR)) !=
  183                     (cs->cs_ctl_chan->cs_preg[5] & (ZSWR5_RTS | ZSWR5_DTR)));
  184         else
  185                 v = 0;
  186 
  187         if (memcmp((void *)cs->cs_preg, (void *)cs->cs_creg, 16) == 0 && !v)
  188                 return; /* only change if values are different */
  189 
  190         /* Copy "pending" regs to "current" */
  191         memcpy((void *)cs->cs_creg, (void *)cs->cs_preg, 16);
  192         reg = cs->cs_creg;      /* current regs */
  193 
  194         /* disable interrupts */
  195         zs_write_reg(cs, 1, reg[1] & ~ZSWR1_IMASK);
  196 
  197         /* baud clock divisor, stop bits, parity */
  198         zs_write_reg(cs, 4, reg[4]);
  199 
  200         /* misc. TX/RX control bits */
  201         zs_write_reg(cs, 10, reg[10]);
  202 
  203         /* char size, enable (RX/TX) */
  204         zs_write_reg(cs, 3, reg[3] & ~ZSWR3_RX_ENABLE);
  205         zs_write_reg(cs, 5, reg[5] & ~ZSWR5_TX_ENABLE);
  206 
  207         /* synchronous mode stuff */
  208         zs_write_reg(cs, 6, reg[6]);
  209         zs_write_reg(cs, 7, reg[7]);
  210 
  211 #if 0
  212         /*
  213          * Registers 2 and 9 are special because they are
  214          * actually common to both channels, but must be
  215          * programmed through channel A.  The "zsc" attach
  216          * function takes care of setting these registers
  217          * and they should not be touched thereafter.
  218          */
  219         /* interrupt vector */
  220         zs_write_reg(cs, 2, reg[2]);
  221         /* master interrupt control */
  222         zs_write_reg(cs, 9, reg[9]);
  223 #endif
  224 
  225         /* Shut down the BRG */
  226         zs_write_reg(cs, 14, reg[14] & ~ZSWR14_BAUD_ENA);
  227 
  228 #ifdef  ZS_MD_SETCLK
  229         /* Let the MD code setup any external clock. */
  230         ZS_MD_SETCLK(cs);
  231 #endif  /* ZS_MD_SETCLK */
  232 
  233         /* clock mode control */
  234         zs_write_reg(cs, 11, reg[11]);
  235 
  236         /* baud rate (lo/hi) */
  237         zs_write_reg(cs, 12, reg[12]);
  238         zs_write_reg(cs, 13, reg[13]);
  239 
  240         /* Misc. control bits */
  241         zs_write_reg(cs, 14, reg[14]);
  242 
  243         /* which lines cause status interrupts */
  244         zs_write_reg(cs, 15, reg[15]);
  245 
  246         /*
  247          * Zilog docs recommend resetting external status twice at this
  248          * point. Mainly as the status bits are latched, and the first
  249          * interrupt clear might unlatch them to new values, generating
  250          * a second interrupt request.
  251          */
  252         zs_write_csr(cs, ZSM_RESET_STINT);
  253         zs_write_csr(cs, ZSM_RESET_STINT);
  254 
  255         /* char size, enable (RX/TX)*/
  256         zs_write_reg(cs, 3, reg[3]);
  257         zs_write_reg(cs, 5, reg[5]);
  258 
  259         /* Write the status bits on the alternate channel also. */
  260         if (cs->cs_ctl_chan != NULL) {
  261                 v = cs->cs_ctl_chan->cs_preg[5];
  262                 cs->cs_ctl_chan->cs_creg[5] = v;
  263                 zs_write_reg(cs->cs_ctl_chan, 5, v);
  264         }
  265 
  266         /* interrupt enables: RX, TX, STATUS */
  267         zs_write_reg(cs, 1, reg[1]);
  268 }
  269 
  270 void
  271 zs_lock_init(struct zs_chanstate *cs)
  272 {
  273 
  274         mutex_init(&cs->cs_lock, MUTEX_NODEBUG, IPL_ZS);
  275 }
  276 
  277 void
  278 zs_lock_chan(struct zs_chanstate *cs)
  279 {
  280 
  281         mutex_spin_enter(&cs->cs_lock);
  282 }
  283 
  284 void
  285 zs_unlock_chan(struct zs_chanstate *cs)
  286 {
  287 
  288         mutex_spin_exit(&cs->cs_lock);
  289 }
  290 
  291 /*
  292  * ZS hardware interrupt.  Scan all ZS channels.  NB: we know here that
  293  * channels are kept in (A,B) pairs.
  294  *
  295  * Do just a little, then get out; set a software interrupt if more
  296  * work is needed.
  297  *
  298  * We deliberately ignore the vectoring Zilog gives us, and match up
  299  * only the number of `reset interrupt under service' operations, not
  300  * the order.
  301  */
  302 int
  303 zsc_intr_hard(void *arg)
  304 {
  305         struct zsc_softc *zsc = arg;
  306         struct zs_chanstate *cs;
  307         uint8_t rr3;
  308 
  309         /* First look at channel A. */
  310         cs = zsc->zsc_cs[0];
  311 
  312         /* Lock both channels */
  313         mutex_spin_enter(&cs->cs_lock);
  314         mutex_spin_enter(&zsc->zsc_cs[1]->cs_lock);
  315         /* Note: only channel A has an RR3 */
  316         rr3 = zs_read_reg(cs, 3);
  317 
  318         /*
  319          * Clear interrupt first to avoid a race condition.
  320          * If a new interrupt condition happens while we are
  321          * servicing this one, we will get another interrupt
  322          * shortly.  We can NOT just sit here in a loop, or
  323          * we will cause horrible latency for other devices
  324          * on this interrupt level (i.e. sun3x floppy disk).
  325          */
  326         if (rr3 & (ZSRR3_IP_A_RX | ZSRR3_IP_A_TX | ZSRR3_IP_A_STAT)) {
  327                 zs_write_csr(cs, ZSWR0_CLR_INTR);
  328                 if (rr3 & ZSRR3_IP_A_RX)
  329                         (*cs->cs_ops->zsop_rxint)(cs);
  330                 if (rr3 & ZSRR3_IP_A_STAT)
  331                         (*cs->cs_ops->zsop_stint)(cs, 0);
  332                 if (rr3 & ZSRR3_IP_A_TX)
  333                         (*cs->cs_ops->zsop_txint)(cs);
  334         }
  335 
  336         /* Done with channel A */
  337         mutex_spin_exit(&cs->cs_lock);
  338 
  339         /* Now look at channel B. */
  340         cs = zsc->zsc_cs[1];
  341         if (rr3 & (ZSRR3_IP_B_RX | ZSRR3_IP_B_TX | ZSRR3_IP_B_STAT)) {
  342                 zs_write_csr(cs, ZSWR0_CLR_INTR);
  343                 if (rr3 & ZSRR3_IP_B_RX)
  344                         (*cs->cs_ops->zsop_rxint)(cs);
  345                 if (rr3 & ZSRR3_IP_B_STAT)
  346                         (*cs->cs_ops->zsop_stint)(cs, 0);
  347                 if (rr3 & ZSRR3_IP_B_TX)
  348                         (*cs->cs_ops->zsop_txint)(cs);
  349         }
  350 
  351         mutex_spin_exit(&cs->cs_lock);
  352 
  353         /* Note: caller will check cs_x->cs_softreq and DTRT. */
  354         return (rr3);
  355 }
  356 
  357 
  358 /*
  359  * ZS software interrupt.  Scan all channels for deferred interrupts.
  360  */
  361 int
  362 zsc_intr_soft(void *arg)
  363 {
  364         struct zsc_softc *zsc = arg;
  365         struct zs_chanstate *cs;
  366         int rval, chan;
  367 
  368         rval = 0;
  369         for (chan = 0; chan < 2; chan++) {
  370                 cs = zsc->zsc_cs[chan];
  371 
  372                 /*
  373                  * The softint flag can be safely cleared once
  374                  * we have decided to call the softint routine.
  375                  * (No need to do splzs() first.)
  376                  */
  377                 if (cs->cs_softreq) {
  378                         cs->cs_softreq = 0;
  379                         (*cs->cs_ops->zsop_softint)(cs);
  380                         rval++;
  381                 }
  382         }
  383         return (rval);
  384 }
  385 
  386 /*
  387  * Provide a null zs "ops" vector.
  388  */
  389 
  390 static void zsnull_rxint  (struct zs_chanstate *);
  391 static void zsnull_stint  (struct zs_chanstate *, int);
  392 static void zsnull_txint  (struct zs_chanstate *);
  393 static void zsnull_softint(struct zs_chanstate *);
  394 
  395 static void
  396 zsnull_rxint(struct zs_chanstate *cs)
  397 {
  398 
  399         /* Ask for softint() call. */
  400         cs->cs_softreq = 1;
  401 }
  402 
  403 static void
  404 zsnull_stint(struct zs_chanstate *cs, int force)
  405 {
  406 
  407         /* Ask for softint() call. */
  408         cs->cs_softreq = 1;
  409 }
  410 
  411 static void
  412 zsnull_txint(struct zs_chanstate *cs)
  413 {
  414 
  415         /* Ask for softint() call. */
  416         cs->cs_softreq = 1;
  417 }
  418 
  419 static void
  420 zsnull_softint(struct zs_chanstate *cs)
  421 {
  422 
  423         zs_write_reg(cs,  1, 0);
  424         zs_write_reg(cs, 15, 0);
  425 }
  426 
  427 struct zsops zsops_null = {
  428         zsnull_rxint,   /* receive char available */
  429         zsnull_stint,   /* external/status */
  430         zsnull_txint,   /* xmit buffer empty */
  431         zsnull_softint, /* process software interrupt */
  432 };

Cache object: e8f26b0bf86108892057eae43ceb0756


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