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/dec/dz.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: dz.c,v 1.38.4.1 2010/11/21 21:27:37 riz Exp $  */
    2 /*
    3  * Copyright (c) 1992, 1993
    4  *      The Regents of the University of California.  All rights reserved.
    5  *
    6  * This code is derived from software contributed to Berkeley by
    7  * Ralph Campbell and Rick Macklem.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  * 3. Neither the name of the University nor the names of its contributors
   18  *    may be used to endorse or promote products derived from this software
   19  *    without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31  * SUCH DAMAGE.
   32  */
   33 
   34 /*
   35  * Copyright (c) 1996  Ken C. Wellsch.  All rights reserved.
   36  *
   37  * This code is derived from software contributed to Berkeley by
   38  * Ralph Campbell and Rick Macklem.
   39  *
   40  * Redistribution and use in source and binary forms, with or without
   41  * modification, are permitted provided that the following conditions
   42  * are met:
   43  * 1. Redistributions of source code must retain the above copyright
   44  *    notice, this list of conditions and the following disclaimer.
   45  * 2. Redistributions in binary form must reproduce the above copyright
   46  *    notice, this list of conditions and the following disclaimer in the
   47  *    documentation and/or other materials provided with the distribution.
   48  * 3. All advertising materials mentioning features or use of this software
   49  *    must display the following acknowledgement:
   50  *      This product includes software developed by the University of
   51  *      California, Berkeley and its contributors.
   52  * 4. Neither the name of the University nor the names of its contributors
   53  *    may be used to endorse or promote products derived from this software
   54  *    without specific prior written permission.
   55  *
   56  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   57  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   58  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   59  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   60  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   61  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   62  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   63  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   64  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   65  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   66  * SUCH DAMAGE.
   67  */
   68 
   69 #include <sys/cdefs.h>
   70 __KERNEL_RCSID(0, "$NetBSD: dz.c,v 1.38.4.1 2010/11/21 21:27:37 riz Exp $");
   71 
   72 #include <sys/param.h>
   73 #include <sys/systm.h>
   74 #include <sys/callout.h>
   75 #include <sys/ioctl.h>
   76 #include <sys/tty.h>
   77 #include <sys/proc.h>
   78 #include <sys/buf.h>
   79 #include <sys/conf.h>
   80 #include <sys/file.h>
   81 #include <sys/uio.h>
   82 #include <sys/kernel.h>
   83 #include <sys/syslog.h>
   84 #include <sys/device.h>
   85 #include <sys/kauth.h>
   86 
   87 #include <sys/bus.h>
   88 
   89 #include <dev/dec/dzreg.h>
   90 #include <dev/dec/dzvar.h>
   91 
   92 #include <dev/cons.h>
   93 
   94 #ifdef __mips__
   95 #define DZ_DELAY(x)     DELAY(x)
   96 #define control         __noinline
   97 #else   /* presumably vax */
   98 #define DZ_DELAY(x)     /* nothing */
   99 #define control         inline
  100 #endif
  101 
  102 static control uint
  103 dz_read1(struct dz_softc *sc, u_int off)
  104 {
  105         u_int rv;
  106 
  107         rv = bus_space_read_1(sc->sc_iot, sc->sc_ioh, off);
  108         DZ_DELAY(1);
  109         return rv;
  110 }
  111 
  112 static control u_int
  113 dz_read2(struct dz_softc *sc, u_int off)
  114 {
  115         u_int rv;
  116 
  117         rv = bus_space_read_2(sc->sc_iot, sc->sc_ioh, off);
  118         DZ_DELAY(1);
  119         return rv;
  120 }
  121 
  122 static control void
  123 dz_write1(struct dz_softc *sc, u_int off, u_int val)
  124 {
  125 
  126         bus_space_write_1(sc->sc_iot, sc->sc_ioh, off, val);
  127         bus_space_barrier(sc->sc_iot, sc->sc_ioh, sc->sc_dr.dr_firstreg,
  128             sc->sc_dr.dr_winsize, BUS_SPACE_BARRIER_WRITE |
  129             BUS_SPACE_BARRIER_READ);
  130         DZ_DELAY(10);
  131 }
  132 
  133 static control void
  134 dz_write2(struct dz_softc *sc, u_int off, u_int val)
  135 {
  136 
  137         bus_space_write_2(sc->sc_iot, sc->sc_ioh, off, val);
  138         bus_space_barrier(sc->sc_iot, sc->sc_ioh, sc->sc_dr.dr_firstreg,
  139             sc->sc_dr.dr_winsize, BUS_SPACE_BARRIER_WRITE |
  140             BUS_SPACE_BARRIER_READ);
  141         DZ_DELAY(10);
  142 }
  143 
  144 #include "ioconf.h"
  145 
  146 /* Flags used to monitor modem bits, make them understood outside driver */
  147 
  148 #define DML_DTR         TIOCM_DTR
  149 #define DML_DCD         TIOCM_CD
  150 #define DML_RI          TIOCM_RI
  151 #define DML_BRK         0100000         /* no equivalent, we will mask */
  152 
  153 static const struct speedtab dzspeedtab[] =
  154 {
  155   {       0,    0               },
  156   {      50,    DZ_LPR_B50      },
  157   {      75,    DZ_LPR_B75      },
  158   {     110,    DZ_LPR_B110     },
  159   {     134,    DZ_LPR_B134     },
  160   {     150,    DZ_LPR_B150     },
  161   {     300,    DZ_LPR_B300     },
  162   {     600,    DZ_LPR_B600     },
  163   {    1200,    DZ_LPR_B1200    },
  164   {    1800,    DZ_LPR_B1800    },
  165   {    2000,    DZ_LPR_B2000    },
  166   {    2400,    DZ_LPR_B2400    },
  167   {    3600,    DZ_LPR_B3600    },
  168   {    4800,    DZ_LPR_B4800    },
  169   {    7200,    DZ_LPR_B7200    },
  170   {    9600,    DZ_LPR_B9600    },
  171   {   19200,    DZ_LPR_B19200   },
  172   {      -1,    -1              }
  173 };
  174 
  175 static void     dzstart(struct tty *);
  176 static int      dzparam(struct tty *, struct termios *);
  177 static unsigned dzmctl(struct dz_softc *, int, int, int);
  178 static void     dzscan(void *);
  179 
  180 static dev_type_open(dzopen);
  181 static dev_type_close(dzclose);
  182 static dev_type_read(dzread);
  183 static dev_type_write(dzwrite);
  184 static dev_type_ioctl(dzioctl);
  185 static dev_type_stop(dzstop);
  186 static dev_type_tty(dztty);
  187 static dev_type_poll(dzpoll);
  188 
  189 const struct cdevsw dz_cdevsw = {
  190         dzopen, dzclose, dzread, dzwrite, dzioctl,
  191         dzstop, dztty, dzpoll, nommap, ttykqfilter, D_TTY
  192 };
  193 
  194 /*
  195  * The DZ series doesn't interrupt on carrier transitions,
  196  * so we have to use a timer to watch it.
  197  */
  198 int     dz_timer;       /* true if timer started */
  199 struct callout dzscan_ch;
  200 static struct cnm_state dz_cnm_state;
  201 
  202 void
  203 dzattach(struct dz_softc *sc, struct evcnt *parent_evcnt, int consline)
  204 {
  205         int n;
  206 
  207         /* Initialize our softc structure. */
  208 
  209         for (n = 0; n < sc->sc_type; n++) {
  210                 sc->sc_dz[n].dz_sc = sc;
  211                 sc->sc_dz[n].dz_line = n;
  212                 sc->sc_dz[n].dz_tty = ttymalloc();
  213         }
  214 
  215         evcnt_attach_dynamic(&sc->sc_rintrcnt, EVCNT_TYPE_INTR, parent_evcnt,
  216             device_xname(sc->sc_dev), "rintr");
  217         evcnt_attach_dynamic(&sc->sc_tintrcnt, EVCNT_TYPE_INTR, parent_evcnt,
  218             device_xname(sc->sc_dev), "tintr");
  219 
  220         /* Console magic keys */
  221         cn_init_magic(&dz_cnm_state);
  222         cn_set_magic("\047\001"); /* default magic is BREAK */
  223                                   /* VAX will change it in MD code */
  224 
  225         sc->sc_rxint = sc->sc_brk = 0;
  226         sc->sc_consline = consline;
  227 
  228         sc->sc_dr.dr_tcrw = sc->sc_dr.dr_tcr;
  229         dz_write2(sc, sc->sc_dr.dr_csr, DZ_CSR_MSE | DZ_CSR_RXIE | DZ_CSR_TXIE);
  230         dz_write1(sc, sc->sc_dr.dr_dtr, 0);
  231         dz_write1(sc, sc->sc_dr.dr_break, 0);
  232         DELAY(10000);
  233 
  234         /* Alas no interrupt on modem bit changes, so we manually scan */
  235         if (dz_timer == 0) {
  236                 dz_timer = 1;
  237                 callout_init(&dzscan_ch, 0);
  238                 callout_reset(&dzscan_ch, hz, dzscan, NULL);
  239         }
  240         printf("\n");
  241 }
  242 
  243 /* Receiver Interrupt */
  244 
  245 void
  246 dzrint(void *arg)
  247 {
  248         struct dz_softc *sc = arg;
  249         struct tty *tp;
  250         int cc, mcc, line;
  251         unsigned c;
  252         int overrun = 0;
  253 
  254         sc->sc_rxint++;
  255 
  256         while ((c = dz_read2(sc, sc->sc_dr.dr_rbuf)) & DZ_RBUF_DATA_VALID) {
  257                 cc = c & 0xFF;
  258                 line = DZ_PORT(c>>8);
  259                 tp = sc->sc_dz[line].dz_tty;
  260 
  261                 /* Must be caught early */
  262                 if (sc->sc_dz[line].dz_catch &&
  263                     (*sc->sc_dz[line].dz_catch)(sc->sc_dz[line].dz_private, cc))
  264                         continue;
  265 
  266                 if ((c & (DZ_RBUF_FRAMING_ERR | 0xff)) == DZ_RBUF_FRAMING_ERR)
  267                         mcc = CNC_BREAK;
  268                 else
  269                         mcc = cc;
  270 
  271                 cn_check_magic(tp->t_dev, mcc, dz_cnm_state);
  272 
  273                 if (!(tp->t_state & TS_ISOPEN)) {
  274                         cv_broadcast(&tp->t_rawcv);
  275                         continue;
  276                 }
  277 
  278                 if ((c & DZ_RBUF_OVERRUN_ERR) && overrun == 0) {
  279                         log(LOG_WARNING, "%s: silo overflow, line %d\n",
  280                             device_xname(sc->sc_dev), line);
  281                         overrun = 1;
  282                 }
  283 
  284                 if (c & DZ_RBUF_FRAMING_ERR)
  285                         cc |= TTY_FE;
  286                 if (c & DZ_RBUF_PARITY_ERR)
  287                         cc |= TTY_PE;
  288 
  289                 (*tp->t_linesw->l_rint)(cc, tp);
  290         }
  291 }
  292 
  293 /* Transmitter Interrupt */
  294 
  295 void
  296 dzxint(void *arg)
  297 {
  298         struct dz_softc *sc = arg;
  299         struct tty *tp;
  300         struct clist *cl;
  301         int line, ch, csr;
  302         u_char tcr;
  303 
  304         /*
  305          * Switch to POLLED mode.
  306          *   Some simple measurements indicated that even on
  307          *  one port, by freeing the scanner in the controller
  308          *  by either providing a character or turning off
  309          *  the port when output is complete, the transmitter
  310          *  was ready to accept more output when polled again.
  311          *   With just two ports running the game "worms,"
  312          *  almost every interrupt serviced both transmitters!
  313          *   Each UART is double buffered, so if the scanner
  314          *  is quick enough and timing works out, we can even
  315          *  feed the same port twice.
  316          *
  317          * Ragge 980517:
  318          * Do not need to turn off interrupts, already at interrupt level.
  319          * Remove the pdma stuff; no great need of it right now.
  320          */
  321 
  322         for (;;) {
  323                 csr = dz_read2(sc, sc->sc_dr.dr_csr);
  324                 if ((csr & DZ_CSR_TX_READY) == 0)
  325                         break;
  326 
  327                 line = DZ_PORT(csr >> 8);
  328                 tp = sc->sc_dz[line].dz_tty;
  329                 cl = &tp->t_outq;
  330                 tp->t_state &= ~TS_BUSY;
  331 
  332                 /* Just send out a char if we have one */
  333                 /* As long as we can fill the chip buffer, we just loop here */
  334                 if (cl->c_cc) {
  335                         tp->t_state |= TS_BUSY;
  336                         ch = getc(cl);
  337                         dz_write1(sc, sc->sc_dr.dr_tbuf, ch);
  338                         continue;
  339                 }
  340 
  341                 /* Nothing to send; clear the scan bit */
  342                 /* Clear xmit scanner bit; dzstart may set it again */
  343                 tcr = dz_read2(sc, sc->sc_dr.dr_tcrw);
  344                 tcr &= 255;
  345                 tcr &= ~(1 << line);
  346                 dz_write1(sc, sc->sc_dr.dr_tcr, tcr);
  347                 if (sc->sc_dz[line].dz_catch)
  348                         continue;
  349 
  350                 if (tp->t_state & TS_FLUSH)
  351                         tp->t_state &= ~TS_FLUSH;
  352                 else
  353                         ndflush (&tp->t_outq, cl->c_cc);
  354 
  355                 (*tp->t_linesw->l_start)(tp);
  356         }
  357 }
  358 
  359 int
  360 dzopen(dev_t dev, int flag, int mode, struct lwp *l)
  361 {
  362         const int line = DZ_PORT(minor(dev));
  363         struct dz_softc *sc = device_lookup_private(&dz_cd, DZ_I2C(minor(dev)));
  364         struct tty *tp;
  365         int error = 0;
  366 
  367         if (sc == NULL || line >= sc->sc_type)
  368                 return ENXIO;
  369 
  370         /* if some other device is using the line, it's busy */
  371         if (sc->sc_dz[line].dz_catch)
  372                 return EBUSY;
  373 
  374         tp = sc->sc_dz[line].dz_tty;
  375         if (tp == NULL)
  376                 return (ENODEV);
  377         tp->t_oproc = dzstart;
  378         tp->t_param = dzparam;
  379         tp->t_dev = dev;
  380 
  381         if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp))
  382                 return (EBUSY);
  383 
  384         if ((tp->t_state & TS_ISOPEN) == 0) {
  385                 ttychars(tp);
  386                 if (tp->t_ispeed == 0) {
  387                         tp->t_iflag = TTYDEF_IFLAG;
  388                         tp->t_oflag = TTYDEF_OFLAG;
  389                         tp->t_cflag = TTYDEF_CFLAG;
  390                         tp->t_lflag = TTYDEF_LFLAG;
  391                         tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
  392                 }
  393                 (void) dzparam(tp, &tp->t_termios);
  394                 ttsetwater(tp);
  395         }
  396 
  397         /* Use DMBIS and *not* DMSET or else we clobber incoming bits */
  398         if (dzmctl(sc, line, DML_DTR, DMBIS) & DML_DCD)
  399                 tp->t_state |= TS_CARR_ON;
  400         mutex_spin_enter(&tty_lock);
  401         while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) &&
  402                !(tp->t_state & TS_CARR_ON)) {
  403                 tp->t_wopen++;
  404                 error = ttysleep(tp, &tp->t_rawcv, true, 0);
  405                 tp->t_wopen--;
  406                 if (error)
  407                         break;
  408         }
  409         mutex_spin_exit(&tty_lock);
  410         if (error)
  411                 return (error);
  412         return ((*tp->t_linesw->l_open)(dev, tp));
  413 }
  414 
  415 /*ARGSUSED*/
  416 int
  417 dzclose(dev_t dev, int flag, int mode, struct lwp *l)
  418 {
  419         const int line = DZ_PORT(minor(dev));
  420         struct dz_softc *sc = device_lookup_private(&dz_cd, DZ_I2C(minor(dev)));
  421         struct tty *tp = sc->sc_dz[line].dz_tty;
  422 
  423         (*tp->t_linesw->l_close)(tp, flag);
  424 
  425         /* Make sure a BREAK state is not left enabled. */
  426         (void) dzmctl(sc, line, DML_BRK, DMBIC);
  427 
  428         /* Do a hangup if so required. */
  429         if ((tp->t_cflag & HUPCL) || tp->t_wopen || !(tp->t_state & TS_ISOPEN))
  430                 (void) dzmctl(sc, line, 0, DMSET);
  431 
  432         return ttyclose(tp);
  433 }
  434 
  435 int
  436 dzread(dev_t dev, struct uio *uio, int flag)
  437 {
  438         struct dz_softc *sc = device_lookup_private(&dz_cd, DZ_I2C(minor(dev)));
  439         struct tty *tp = sc->sc_dz[DZ_PORT(minor(dev))].dz_tty;
  440 
  441         return ((*tp->t_linesw->l_read)(tp, uio, flag));
  442 }
  443 
  444 int
  445 dzwrite(dev_t dev, struct uio *uio, int flag)
  446 {
  447         struct dz_softc *sc = device_lookup_private(&dz_cd, DZ_I2C(minor(dev)));
  448         struct tty *tp = sc->sc_dz[DZ_PORT(minor(dev))].dz_tty;
  449 
  450         return ((*tp->t_linesw->l_write)(tp, uio, flag));
  451 }
  452 
  453 int
  454 dzpoll(dev_t dev, int events, struct lwp *l)
  455 {
  456         struct dz_softc *sc = device_lookup_private(&dz_cd, DZ_I2C(minor(dev)));
  457         struct tty *tp = sc->sc_dz[DZ_PORT(minor(dev))].dz_tty;
  458 
  459         return ((*tp->t_linesw->l_poll)(tp, events, l));
  460 }
  461 
  462 /*ARGSUSED*/
  463 int
  464 dzioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
  465 {
  466         struct dz_softc *sc = device_lookup_private(&dz_cd, DZ_I2C(minor(dev)));
  467         const int line = DZ_PORT(minor(dev));
  468         struct tty *tp = sc->sc_dz[line].dz_tty;
  469         int error;
  470 
  471         error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l);
  472         if (error >= 0)
  473                 return (error);
  474 
  475         error = ttioctl(tp, cmd, data, flag, l);
  476         if (error >= 0)
  477                 return (error);
  478 
  479         switch (cmd) {
  480         case TIOCSBRK:
  481                 (void) dzmctl(sc, line, DML_BRK, DMBIS);
  482                 break;
  483 
  484         case TIOCCBRK:
  485                 (void) dzmctl(sc, line, DML_BRK, DMBIC);
  486                 break;
  487 
  488         case TIOCSDTR:
  489                 (void) dzmctl(sc, line, DML_DTR, DMBIS);
  490                 break;
  491 
  492         case TIOCCDTR:
  493                 (void) dzmctl(sc, line, DML_DTR, DMBIC);
  494                 break;
  495 
  496         case TIOCMSET:
  497                 (void) dzmctl(sc, line, *(int *)data, DMSET);
  498                 break;
  499 
  500         case TIOCMBIS:
  501                 (void) dzmctl(sc, line, *(int *)data, DMBIS);
  502                 break;
  503 
  504         case TIOCMBIC:
  505                 (void) dzmctl(sc, line, *(int *)data, DMBIC);
  506                 break;
  507 
  508         case TIOCMGET:
  509                 *(int *)data = (dzmctl(sc, line, 0, DMGET) & ~DML_BRK);
  510                 break;
  511 
  512         default:
  513                 return (EPASSTHROUGH);
  514         }
  515         return (0);
  516 }
  517 
  518 struct tty *
  519 dztty(dev_t dev)
  520 {
  521         struct dz_softc *sc = device_lookup_private(&dz_cd, DZ_I2C(minor(dev)));
  522 
  523         return sc->sc_dz[DZ_PORT(minor(dev))].dz_tty;
  524 }
  525 
  526 /*ARGSUSED*/
  527 void
  528 dzstop(struct tty *tp, int flag)
  529 {
  530         if ((tp->t_state & (TS_BUSY | TS_TTSTOP)) == TS_BUSY)
  531                 tp->t_state |= TS_FLUSH;
  532 }
  533 
  534 void
  535 dzstart(struct tty *tp)
  536 {
  537         struct dz_softc *sc;
  538         int line;
  539         int s;
  540         char state;
  541 
  542         s = spltty();
  543         if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) {
  544                 splx(s);
  545                 return;
  546         }
  547         if (!ttypull(tp)) {
  548                 splx(s);
  549                 return;
  550         }
  551 
  552         line = DZ_PORT(minor(tp->t_dev));
  553         sc = device_lookup_private(&dz_cd, DZ_I2C(minor(tp->t_dev)));
  554 
  555         tp->t_state |= TS_BUSY;
  556         state = dz_read2(sc, sc->sc_dr.dr_tcrw) & 255;
  557         if ((state & (1 << line)) == 0)
  558                 dz_write1(sc, sc->sc_dr.dr_tcr, state | (1 << line));
  559         dzxint(sc);
  560         splx(s);
  561 }
  562 
  563 static int
  564 dzparam(struct tty *tp, struct termios *t)
  565 {
  566         struct dz_softc *sc = device_lookup_private(&dz_cd, DZ_I2C(minor(tp->t_dev)));
  567         const int line = DZ_PORT(minor(tp->t_dev));
  568         int cflag = t->c_cflag;
  569         int ispeed = ttspeedtab(t->c_ispeed, dzspeedtab);
  570         int ospeed = ttspeedtab(t->c_ospeed, dzspeedtab);
  571         unsigned lpr;
  572         int s;
  573 
  574         /* check requested parameters */
  575         if (ospeed < 0 || ispeed < 0 || ispeed != ospeed)
  576                 return (EINVAL);
  577 
  578         tp->t_ispeed = t->c_ispeed;
  579         tp->t_ospeed = t->c_ospeed;
  580         tp->t_cflag = cflag;
  581 
  582         if (ospeed == 0) {
  583                 (void) dzmctl(sc, line, 0, DMSET);      /* hang up line */
  584                 return (0);
  585         }
  586 
  587         s = spltty();
  588 
  589         /* XXX This is wrong.  Flush output or the chip gets very confused. */
  590         ttywait(tp);
  591 
  592         lpr = DZ_LPR_RX_ENABLE | ((ispeed&0xF)<<8) | line;
  593 
  594         switch (cflag & CSIZE)
  595         {
  596           case CS5:
  597                 lpr |= DZ_LPR_5_BIT_CHAR;
  598                 break;
  599           case CS6:
  600                 lpr |= DZ_LPR_6_BIT_CHAR;
  601                 break;
  602           case CS7:
  603                 lpr |= DZ_LPR_7_BIT_CHAR;
  604                 break;
  605           default:
  606                 lpr |= DZ_LPR_8_BIT_CHAR;
  607                 break;
  608         }
  609         if (cflag & PARENB)
  610                 lpr |= DZ_LPR_PARENB;
  611         if (cflag & PARODD)
  612                 lpr |= DZ_LPR_OPAR;
  613         if (cflag & CSTOPB)
  614                 lpr |= DZ_LPR_2_STOP;
  615 
  616         dz_write2(sc, sc->sc_dr.dr_lpr, lpr);
  617         (void) splx(s);
  618         DELAY(10000);
  619 
  620         return (0);
  621 }
  622 
  623 static unsigned
  624 dzmctl(struct dz_softc *sc, int line, int bits, int how)
  625 {
  626         unsigned status;
  627         unsigned mbits;
  628         unsigned bit;
  629         int s;
  630 
  631         s = spltty();
  632         mbits = 0;
  633         bit = (1 << line);
  634 
  635         /* external signals as seen from the port */
  636         status = dz_read1(sc, sc->sc_dr.dr_dcd) | sc->sc_dsr;
  637         if (status & bit)
  638                 mbits |= DML_DCD;
  639         status = dz_read1(sc, sc->sc_dr.dr_ring);
  640         if (status & bit)
  641                 mbits |= DML_RI;
  642 
  643         /* internal signals/state delivered to port */
  644         status = dz_read1(sc, sc->sc_dr.dr_dtr);
  645         if (status & bit)
  646                 mbits |= DML_DTR;
  647         if (sc->sc_brk & bit)
  648                 mbits |= DML_BRK;
  649 
  650         switch (how)
  651         {
  652           case DMSET:
  653                 mbits = bits;
  654                 break;
  655 
  656           case DMBIS:
  657                 mbits |= bits;
  658                 break;
  659 
  660           case DMBIC:
  661                 mbits &= ~bits;
  662                 break;
  663 
  664           case DMGET:
  665                 (void) splx(s);
  666                 return (mbits);
  667         }
  668 
  669         if (mbits & DML_DTR) {
  670                 dz_write1(sc, sc->sc_dr.dr_dtr, dz_read1(sc, sc->sc_dr.dr_dtr) | bit);
  671         } else {
  672                 dz_write1(sc, sc->sc_dr.dr_dtr, dz_read1(sc, sc->sc_dr.dr_dtr) & ~bit);
  673         }
  674 
  675         if (mbits & DML_BRK) {
  676                 sc->sc_brk |= bit;
  677                 dz_write1(sc, sc->sc_dr.dr_break, sc->sc_brk);
  678         } else {
  679                 sc->sc_brk &= ~bit;
  680                 dz_write1(sc, sc->sc_dr.dr_break, sc->sc_brk);
  681         }
  682 
  683         (void) splx(s);
  684 
  685         return (mbits);
  686 }
  687 
  688 /*
  689  * This is called by timeout() periodically.
  690  * Check to see if modem status bits have changed.
  691  */
  692 static void
  693 dzscan(void *arg)
  694 {
  695         struct dz_softc *sc;
  696         struct tty *tp;
  697         int n, bit, port;
  698         unsigned int csr;
  699         unsigned int tmp;
  700         int s;
  701 
  702         s = spltty();
  703         for (n = 0; n < dz_cd.cd_ndevs; n++) {
  704                 if ((sc = device_lookup_private(&dz_cd, n)) == NULL)
  705                         continue;
  706 
  707                 for (port = 0; port < sc->sc_type; port++) {
  708                         tp = sc->sc_dz[port].dz_tty;
  709                         bit = (1 << port);
  710 
  711                         if ((dz_read1(sc, sc->sc_dr.dr_dcd) | sc->sc_dsr) & bit) {
  712                                 if (!(tp->t_state & TS_CARR_ON))
  713                                         (*tp->t_linesw->l_modem) (tp, 1);
  714                         } else if ((tp->t_state & TS_CARR_ON) &&
  715                             (*tp->t_linesw->l_modem)(tp, 0) == 0) {
  716                                 tmp = dz_read2(sc, sc->sc_dr.dr_tcrw) & 255;
  717                                 dz_write1(sc, sc->sc_dr.dr_tcr, tmp & ~bit);
  718                         }
  719                 }
  720 
  721                 /*
  722                  *  If the RX interrupt rate is this high, switch
  723                  *  the controller to Silo Alarm - which means don't
  724                  *  interrupt until the RX silo has 16 characters in
  725                  *  it (the silo is 64 characters in all).
  726                  *  Avoid oscillating SA on and off by not turning
  727                  *  if off unless the rate is appropriately low.
  728                  */
  729                 csr = dz_read2(sc, sc->sc_dr.dr_csr);
  730                 tmp = csr;
  731                 if (sc->sc_rxint > 16*10)
  732                         csr |= DZ_CSR_SAE;
  733                 else if (sc->sc_rxint < 10)
  734                         csr &= ~DZ_CSR_SAE;
  735                 if (csr != tmp)
  736                         dz_write2(sc, sc->sc_dr.dr_csr, csr);
  737                 sc->sc_rxint = 0;
  738 
  739                 dzxint(sc);
  740                 dzrint(sc);
  741         }
  742         (void) splx(s);
  743         callout_reset(&dzscan_ch, hz, dzscan, NULL);
  744 }
  745 
  746 /*
  747  * Called after an ubareset. The DZ card is reset, but the only thing
  748  * that must be done is to start the receiver and transmitter again.
  749  * No DMA setup to care about.
  750  */
  751 void
  752 dzreset(device_t dev)
  753 {
  754         struct dz_softc *sc = device_private(dev);
  755         struct tty *tp;
  756         int i;
  757 
  758         for (i = 0; i < sc->sc_type; i++) {
  759                 tp = sc->sc_dz[i].dz_tty;
  760 
  761                 if (((tp->t_state & TS_ISOPEN) == 0) || (tp->t_wopen == 0))
  762                         continue;
  763 
  764                 dzparam(tp, &tp->t_termios);
  765                 dzmctl(sc, i, DML_DTR, DMSET);
  766                 tp->t_state &= ~TS_BUSY;
  767                 dzstart(tp);    /* Kick off transmitter again */
  768         }
  769 }

Cache object: 4d1f4d2da88b2a21fe9560c4cd24d968


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