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.43 2022/10/26 23:44:36 riastradh 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.43 2022/10/26 23:44:36 riastradh 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         .d_open = dzopen,
  191         .d_close = dzclose,
  192         .d_read = dzread,
  193         .d_write = dzwrite,
  194         .d_ioctl = dzioctl,
  195         .d_stop = dzstop,
  196         .d_tty = dztty,
  197         .d_poll = dzpoll,
  198         .d_mmap = nommap,
  199         .d_kqfilter = ttykqfilter,
  200         .d_discard = nodiscard,
  201         .d_flag = D_TTY
  202 };
  203 
  204 /*
  205  * The DZ series doesn't interrupt on carrier transitions,
  206  * so we have to use a timer to watch it.
  207  */
  208 int     dz_timer;       /* true if timer started */
  209 struct callout dzscan_ch;
  210 static struct cnm_state dz_cnm_state;
  211 
  212 void
  213 dzattach(struct dz_softc *sc, struct evcnt *parent_evcnt, int consline)
  214 {
  215         int n;
  216 
  217         /* Initialize our softc structure. */
  218 
  219         for (n = 0; n < sc->sc_type; n++) {
  220                 sc->sc_dz[n].dz_sc = sc;
  221                 sc->sc_dz[n].dz_line = n;
  222                 sc->sc_dz[n].dz_tty = tty_alloc();
  223         }
  224 
  225         evcnt_attach_dynamic(&sc->sc_rintrcnt, EVCNT_TYPE_INTR, parent_evcnt,
  226             device_xname(sc->sc_dev), "rintr");
  227         evcnt_attach_dynamic(&sc->sc_tintrcnt, EVCNT_TYPE_INTR, parent_evcnt,
  228             device_xname(sc->sc_dev), "tintr");
  229 
  230         /* Console magic keys */
  231         cn_init_magic(&dz_cnm_state);
  232         cn_set_magic("\047\001"); /* default magic is BREAK */
  233                                   /* VAX will change it in MD code */
  234 
  235         sc->sc_rxint = sc->sc_brk = 0;
  236         sc->sc_consline = consline;
  237 
  238         sc->sc_dr.dr_tcrw = sc->sc_dr.dr_tcr;
  239         dz_write2(sc, sc->sc_dr.dr_csr, DZ_CSR_MSE | DZ_CSR_RXIE | DZ_CSR_TXIE);
  240         dz_write1(sc, sc->sc_dr.dr_dtr, 0);
  241         dz_write1(sc, sc->sc_dr.dr_break, 0);
  242         DELAY(10000);
  243 
  244         /* Alas no interrupt on modem bit changes, so we manually scan */
  245         if (dz_timer == 0) {
  246                 dz_timer = 1;
  247                 callout_init(&dzscan_ch, 0);
  248                 callout_reset(&dzscan_ch, hz, dzscan, NULL);
  249         }
  250         printf("\n");
  251 }
  252 
  253 /* Receiver Interrupt */
  254 
  255 void
  256 dzrint(void *arg)
  257 {
  258         struct dz_softc *sc = arg;
  259         struct tty *tp;
  260         int cc, mcc, line;
  261         unsigned c;
  262         int overrun = 0;
  263 
  264         sc->sc_rxint++;
  265 
  266         while ((c = dz_read2(sc, sc->sc_dr.dr_rbuf)) & DZ_RBUF_DATA_VALID) {
  267                 cc = c & 0xFF;
  268                 line = DZ_PORT(c>>8);
  269                 tp = sc->sc_dz[line].dz_tty;
  270 
  271                 /* Must be caught early */
  272                 if (sc->sc_dz[line].dz_catch &&
  273                     (*sc->sc_dz[line].dz_catch)(sc->sc_dz[line].dz_private, cc))
  274                         continue;
  275 
  276                 if ((c & (DZ_RBUF_FRAMING_ERR | 0xff)) == DZ_RBUF_FRAMING_ERR)
  277                         mcc = CNC_BREAK;
  278                 else
  279                         mcc = cc;
  280 
  281                 cn_check_magic(tp->t_dev, mcc, dz_cnm_state);
  282 
  283                 if (!(tp->t_state & TS_ISOPEN)) {
  284                         cv_broadcast(&tp->t_rawcv);
  285                         continue;
  286                 }
  287 
  288                 if ((c & DZ_RBUF_OVERRUN_ERR) && overrun == 0) {
  289                         log(LOG_WARNING, "%s: silo overflow, line %d\n",
  290                             device_xname(sc->sc_dev), line);
  291                         overrun = 1;
  292                 }
  293 
  294                 if (c & DZ_RBUF_FRAMING_ERR)
  295                         cc |= TTY_FE;
  296                 if (c & DZ_RBUF_PARITY_ERR)
  297                         cc |= TTY_PE;
  298 
  299                 (*tp->t_linesw->l_rint)(cc, tp);
  300         }
  301 }
  302 
  303 /* Transmitter Interrupt */
  304 
  305 void
  306 dzxint(void *arg)
  307 {
  308         struct dz_softc *sc = arg;
  309         struct tty *tp;
  310         struct clist *cl;
  311         int line, ch, csr;
  312         u_char tcr;
  313 
  314         /*
  315          * Switch to POLLED mode.
  316          *   Some simple measurements indicated that even on
  317          *  one port, by freeing the scanner in the controller
  318          *  by either providing a character or turning off
  319          *  the port when output is complete, the transmitter
  320          *  was ready to accept more output when polled again.
  321          *   With just two ports running the game "worms,"
  322          *  almost every interrupt serviced both transmitters!
  323          *   Each UART is double buffered, so if the scanner
  324          *  is quick enough and timing works out, we can even
  325          *  feed the same port twice.
  326          *
  327          * Ragge 980517:
  328          * Do not need to turn off interrupts, already at interrupt level.
  329          * Remove the pdma stuff; no great need of it right now.
  330          */
  331 
  332         for (;;) {
  333                 csr = dz_read2(sc, sc->sc_dr.dr_csr);
  334                 if ((csr & DZ_CSR_TX_READY) == 0)
  335                         break;
  336 
  337                 line = DZ_PORT(csr >> 8);
  338                 tp = sc->sc_dz[line].dz_tty;
  339                 cl = &tp->t_outq;
  340                 tp->t_state &= ~TS_BUSY;
  341 
  342                 /* Just send out a char if we have one */
  343                 /* As long as we can fill the chip buffer, we just loop here */
  344                 if (cl->c_cc) {
  345                         tp->t_state |= TS_BUSY;
  346                         ch = getc(cl);
  347                         dz_write1(sc, sc->sc_dr.dr_tbuf, ch);
  348                         continue;
  349                 }
  350 
  351                 /* Nothing to send; clear the scan bit */
  352                 /* Clear xmit scanner bit; dzstart may set it again */
  353                 tcr = dz_read2(sc, sc->sc_dr.dr_tcrw);
  354                 tcr &= 255;
  355                 tcr &= ~(1 << line);
  356                 dz_write1(sc, sc->sc_dr.dr_tcr, tcr);
  357                 if (sc->sc_dz[line].dz_catch)
  358                         continue;
  359 
  360                 if (tp->t_state & TS_FLUSH)
  361                         tp->t_state &= ~TS_FLUSH;
  362                 else
  363                         ndflush (&tp->t_outq, cl->c_cc);
  364 
  365                 (*tp->t_linesw->l_start)(tp);
  366         }
  367 }
  368 
  369 int
  370 dzopen(dev_t dev, int flag, int mode, struct lwp *l)
  371 {
  372         const int line = DZ_PORT(minor(dev));
  373         struct dz_softc *sc = device_lookup_private(&dz_cd, DZ_I2C(minor(dev)));
  374         struct tty *tp;
  375         int error = 0;
  376 
  377         if (sc == NULL || line >= sc->sc_type)
  378                 return ENXIO;
  379 
  380         /* if some other device is using the line, it's busy */
  381         if (sc->sc_dz[line].dz_catch)
  382                 return EBUSY;
  383 
  384         tp = sc->sc_dz[line].dz_tty;
  385         if (tp == NULL)
  386                 return (ENODEV);
  387         tp->t_oproc = dzstart;
  388         tp->t_param = dzparam;
  389         tp->t_dev = dev;
  390 
  391         if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp))
  392                 return (EBUSY);
  393 
  394         if ((tp->t_state & TS_ISOPEN) == 0) {
  395                 ttychars(tp);
  396                 if (tp->t_ispeed == 0) {
  397                         tp->t_iflag = TTYDEF_IFLAG;
  398                         tp->t_oflag = TTYDEF_OFLAG;
  399                         tp->t_cflag = TTYDEF_CFLAG;
  400                         tp->t_lflag = TTYDEF_LFLAG;
  401                         tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
  402                 }
  403                 (void) dzparam(tp, &tp->t_termios);
  404                 ttsetwater(tp);
  405         }
  406 
  407         /* Use DMBIS and *not* DMSET or else we clobber incoming bits */
  408         if (dzmctl(sc, line, DML_DTR, DMBIS) & DML_DCD)
  409                 tp->t_state |= TS_CARR_ON;
  410         ttylock(tp);
  411         while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) &&
  412                !(tp->t_state & TS_CARR_ON)) {
  413                 tp->t_wopen++;
  414                 error = ttysleep(tp, &tp->t_rawcv, true, 0);
  415                 tp->t_wopen--;
  416                 if (error)
  417                         break;
  418         }
  419         ttyunlock(tp);
  420         if (error)
  421                 return (error);
  422         return ((*tp->t_linesw->l_open)(dev, tp));
  423 }
  424 
  425 /*ARGSUSED*/
  426 int
  427 dzclose(dev_t dev, int flag, int mode, struct lwp *l)
  428 {
  429         const int line = DZ_PORT(minor(dev));
  430         struct dz_softc *sc = device_lookup_private(&dz_cd, DZ_I2C(minor(dev)));
  431         struct tty *tp = sc->sc_dz[line].dz_tty;
  432 
  433         (*tp->t_linesw->l_close)(tp, flag);
  434 
  435         /* Make sure a BREAK state is not left enabled. */
  436         (void) dzmctl(sc, line, DML_BRK, DMBIC);
  437 
  438         /* Do a hangup if so required. */
  439         if ((tp->t_cflag & HUPCL) || tp->t_wopen || !(tp->t_state & TS_ISOPEN))
  440                 (void) dzmctl(sc, line, 0, DMSET);
  441 
  442         return ttyclose(tp);
  443 }
  444 
  445 int
  446 dzread(dev_t dev, struct uio *uio, int flag)
  447 {
  448         struct dz_softc *sc = device_lookup_private(&dz_cd, DZ_I2C(minor(dev)));
  449         struct tty *tp = sc->sc_dz[DZ_PORT(minor(dev))].dz_tty;
  450 
  451         return ((*tp->t_linesw->l_read)(tp, uio, flag));
  452 }
  453 
  454 int
  455 dzwrite(dev_t dev, struct uio *uio, int flag)
  456 {
  457         struct dz_softc *sc = device_lookup_private(&dz_cd, DZ_I2C(minor(dev)));
  458         struct tty *tp = sc->sc_dz[DZ_PORT(minor(dev))].dz_tty;
  459 
  460         return ((*tp->t_linesw->l_write)(tp, uio, flag));
  461 }
  462 
  463 int
  464 dzpoll(dev_t dev, int events, struct lwp *l)
  465 {
  466         struct dz_softc *sc = device_lookup_private(&dz_cd, DZ_I2C(minor(dev)));
  467         struct tty *tp = sc->sc_dz[DZ_PORT(minor(dev))].dz_tty;
  468 
  469         return ((*tp->t_linesw->l_poll)(tp, events, l));
  470 }
  471 
  472 /*ARGSUSED*/
  473 int
  474 dzioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
  475 {
  476         struct dz_softc *sc = device_lookup_private(&dz_cd, DZ_I2C(minor(dev)));
  477         const int line = DZ_PORT(minor(dev));
  478         struct tty *tp = sc->sc_dz[line].dz_tty;
  479         int error;
  480 
  481         error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l);
  482         if (error >= 0)
  483                 return (error);
  484 
  485         error = ttioctl(tp, cmd, data, flag, l);
  486         if (error >= 0)
  487                 return (error);
  488 
  489         switch (cmd) {
  490         case TIOCSBRK:
  491                 (void) dzmctl(sc, line, DML_BRK, DMBIS);
  492                 break;
  493 
  494         case TIOCCBRK:
  495                 (void) dzmctl(sc, line, DML_BRK, DMBIC);
  496                 break;
  497 
  498         case TIOCSDTR:
  499                 (void) dzmctl(sc, line, DML_DTR, DMBIS);
  500                 break;
  501 
  502         case TIOCCDTR:
  503                 (void) dzmctl(sc, line, DML_DTR, DMBIC);
  504                 break;
  505 
  506         case TIOCMSET:
  507                 (void) dzmctl(sc, line, *(int *)data, DMSET);
  508                 break;
  509 
  510         case TIOCMBIS:
  511                 (void) dzmctl(sc, line, *(int *)data, DMBIS);
  512                 break;
  513 
  514         case TIOCMBIC:
  515                 (void) dzmctl(sc, line, *(int *)data, DMBIC);
  516                 break;
  517 
  518         case TIOCMGET:
  519                 *(int *)data = (dzmctl(sc, line, 0, DMGET) & ~DML_BRK);
  520                 break;
  521 
  522         default:
  523                 return (EPASSTHROUGH);
  524         }
  525         return (0);
  526 }
  527 
  528 struct tty *
  529 dztty(dev_t dev)
  530 {
  531         struct dz_softc *sc = device_lookup_private(&dz_cd, DZ_I2C(minor(dev)));
  532 
  533         return sc->sc_dz[DZ_PORT(minor(dev))].dz_tty;
  534 }
  535 
  536 /*ARGSUSED*/
  537 void
  538 dzstop(struct tty *tp, int flag)
  539 {
  540         if ((tp->t_state & (TS_BUSY | TS_TTSTOP)) == TS_BUSY)
  541                 tp->t_state |= TS_FLUSH;
  542 }
  543 
  544 void
  545 dzstart(struct tty *tp)
  546 {
  547         struct dz_softc *sc;
  548         int line;
  549         int s;
  550         char state;
  551 
  552         s = spltty();
  553         if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) {
  554                 splx(s);
  555                 return;
  556         }
  557         if (!ttypull(tp)) {
  558                 splx(s);
  559                 return;
  560         }
  561 
  562         line = DZ_PORT(minor(tp->t_dev));
  563         sc = device_lookup_private(&dz_cd, DZ_I2C(minor(tp->t_dev)));
  564 
  565         tp->t_state |= TS_BUSY;
  566         state = dz_read2(sc, sc->sc_dr.dr_tcrw) & 255;
  567         if ((state & (1 << line)) == 0)
  568                 dz_write1(sc, sc->sc_dr.dr_tcr, state | (1 << line));
  569         dzxint(sc);
  570         splx(s);
  571 }
  572 
  573 static int
  574 dzparam(struct tty *tp, struct termios *t)
  575 {
  576         struct dz_softc *sc = device_lookup_private(&dz_cd, DZ_I2C(minor(tp->t_dev)));
  577         const int line = DZ_PORT(minor(tp->t_dev));
  578         int cflag = t->c_cflag;
  579         int ispeed = ttspeedtab(t->c_ispeed, dzspeedtab);
  580         int ospeed = ttspeedtab(t->c_ospeed, dzspeedtab);
  581         unsigned lpr;
  582         int s;
  583 
  584         /* check requested parameters */
  585         if (ospeed < 0 || ispeed < 0 || ispeed != ospeed)
  586                 return (EINVAL);
  587 
  588         tp->t_ispeed = t->c_ispeed;
  589         tp->t_ospeed = t->c_ospeed;
  590         tp->t_cflag = cflag;
  591 
  592         if (ospeed == 0) {
  593                 (void) dzmctl(sc, line, 0, DMSET);      /* hang up line */
  594                 return (0);
  595         }
  596 
  597         s = spltty();
  598 
  599         /* XXX This is wrong.  Flush output or the chip gets very confused. */
  600         ttywait(tp);
  601 
  602         lpr = DZ_LPR_RX_ENABLE | ((ispeed&0xF)<<8) | line;
  603 
  604         switch (cflag & CSIZE)
  605         {
  606           case CS5:
  607                 lpr |= DZ_LPR_5_BIT_CHAR;
  608                 break;
  609           case CS6:
  610                 lpr |= DZ_LPR_6_BIT_CHAR;
  611                 break;
  612           case CS7:
  613                 lpr |= DZ_LPR_7_BIT_CHAR;
  614                 break;
  615           default:
  616                 lpr |= DZ_LPR_8_BIT_CHAR;
  617                 break;
  618         }
  619         if (cflag & PARENB)
  620                 lpr |= DZ_LPR_PARENB;
  621         if (cflag & PARODD)
  622                 lpr |= DZ_LPR_OPAR;
  623         if (cflag & CSTOPB)
  624                 lpr |= DZ_LPR_2_STOP;
  625 
  626         dz_write2(sc, sc->sc_dr.dr_lpr, lpr);
  627         (void) splx(s);
  628         DELAY(10000);
  629 
  630         return (0);
  631 }
  632 
  633 static unsigned
  634 dzmctl(struct dz_softc *sc, int line, int bits, int how)
  635 {
  636         unsigned status;
  637         unsigned mbits;
  638         unsigned bit;
  639         int s;
  640 
  641         s = spltty();
  642         mbits = 0;
  643         bit = (1 << line);
  644 
  645         /* external signals as seen from the port */
  646         status = dz_read1(sc, sc->sc_dr.dr_dcd) | sc->sc_dsr;
  647         if (status & bit)
  648                 mbits |= DML_DCD;
  649         status = dz_read1(sc, sc->sc_dr.dr_ring);
  650         if (status & bit)
  651                 mbits |= DML_RI;
  652 
  653         /* internal signals/state delivered to port */
  654         status = dz_read1(sc, sc->sc_dr.dr_dtr);
  655         if (status & bit)
  656                 mbits |= DML_DTR;
  657         if (sc->sc_brk & bit)
  658                 mbits |= DML_BRK;
  659 
  660         switch (how)
  661         {
  662           case DMSET:
  663                 mbits = bits;
  664                 break;
  665 
  666           case DMBIS:
  667                 mbits |= bits;
  668                 break;
  669 
  670           case DMBIC:
  671                 mbits &= ~bits;
  672                 break;
  673 
  674           case DMGET:
  675                 (void) splx(s);
  676                 return (mbits);
  677         }
  678 
  679         if (mbits & DML_DTR) {
  680                 dz_write1(sc, sc->sc_dr.dr_dtr, dz_read1(sc, sc->sc_dr.dr_dtr) | bit);
  681         } else {
  682                 dz_write1(sc, sc->sc_dr.dr_dtr, dz_read1(sc, sc->sc_dr.dr_dtr) & ~bit);
  683         }
  684 
  685         if (mbits & DML_BRK) {
  686                 sc->sc_brk |= bit;
  687                 dz_write1(sc, sc->sc_dr.dr_break, sc->sc_brk);
  688         } else {
  689                 sc->sc_brk &= ~bit;
  690                 dz_write1(sc, sc->sc_dr.dr_break, sc->sc_brk);
  691         }
  692 
  693         (void) splx(s);
  694 
  695         return (mbits);
  696 }
  697 
  698 /*
  699  * This is called by timeout() periodically.
  700  * Check to see if modem status bits have changed.
  701  */
  702 static void
  703 dzscan(void *arg)
  704 {
  705         struct dz_softc *sc;
  706         struct tty *tp;
  707         int n, bit, port;
  708         unsigned int csr;
  709         unsigned int tmp;
  710         int s;
  711 
  712         s = spltty();
  713         for (n = 0; n < dz_cd.cd_ndevs; n++) {
  714                 if ((sc = device_lookup_private(&dz_cd, n)) == NULL)
  715                         continue;
  716 
  717                 for (port = 0; port < sc->sc_type; port++) {
  718                         tp = sc->sc_dz[port].dz_tty;
  719                         bit = (1 << port);
  720 
  721                         if ((dz_read1(sc, sc->sc_dr.dr_dcd) | sc->sc_dsr) & bit) {
  722                                 if (!(tp->t_state & TS_CARR_ON))
  723                                         (*tp->t_linesw->l_modem) (tp, 1);
  724                         } else if ((tp->t_state & TS_CARR_ON) &&
  725                             (*tp->t_linesw->l_modem)(tp, 0) == 0) {
  726                                 tmp = dz_read2(sc, sc->sc_dr.dr_tcrw) & 255;
  727                                 dz_write1(sc, sc->sc_dr.dr_tcr, tmp & ~bit);
  728                         }
  729                 }
  730 
  731                 /*
  732                  *  If the RX interrupt rate is this high, switch
  733                  *  the controller to Silo Alarm - which means don't
  734                  *  interrupt until the RX silo has 16 characters in
  735                  *  it (the silo is 64 characters in all).
  736                  *  Avoid oscillating SA on and off by not turning
  737                  *  if off unless the rate is appropriately low.
  738                  */
  739                 csr = dz_read2(sc, sc->sc_dr.dr_csr);
  740                 tmp = csr;
  741                 if (sc->sc_rxint > 16*10)
  742                         csr |= DZ_CSR_SAE;
  743                 else if (sc->sc_rxint < 10)
  744                         csr &= ~DZ_CSR_SAE;
  745                 if (csr != tmp)
  746                         dz_write2(sc, sc->sc_dr.dr_csr, csr);
  747                 sc->sc_rxint = 0;
  748 
  749                 dzxint(sc);
  750                 dzrint(sc);
  751         }
  752         (void) splx(s);
  753         callout_reset(&dzscan_ch, hz, dzscan, NULL);
  754 }
  755 
  756 /*
  757  * Called after an ubareset. The DZ card is reset, but the only thing
  758  * that must be done is to start the receiver and transmitter again.
  759  * No DMA setup to care about.
  760  */
  761 void
  762 dzreset(device_t dev)
  763 {
  764         struct dz_softc *sc = device_private(dev);
  765         struct tty *tp;
  766         int i;
  767 
  768         for (i = 0; i < sc->sc_type; i++) {
  769                 tp = sc->sc_dz[i].dz_tty;
  770 
  771                 if (((tp->t_state & TS_ISOPEN) == 0) || (tp->t_wopen == 0))
  772                         continue;
  773 
  774                 dzparam(tp, &tp->t_termios);
  775                 dzmctl(sc, i, DML_DTR, DMSET);
  776                 tp->t_state &= ~TS_BUSY;
  777                 dzstart(tp);    /* Kick off transmitter again */
  778         }
  779 }

Cache object: ccc5cfd8f18d7d4a1f4b25f7903c0164


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