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.24 2006/10/03 12:50:12 he 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.24 2006/10/03 12:50:12 he 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 <machine/bus.h>
   88 
   89 #include <dev/dec/dzreg.h>
   90 #include <dev/dec/dzvar.h>
   91 
   92 #include <dev/cons.h>
   93 
   94 #define DZ_READ_BYTE(adr) \
   95         bus_space_read_1(sc->sc_iot, sc->sc_ioh, sc->sc_dr.adr)
   96 #define DZ_READ_WORD(adr) \
   97         bus_space_read_2(sc->sc_iot, sc->sc_ioh, sc->sc_dr.adr)
   98 #define DZ_WRITE_BYTE(adr, val) \
   99         bus_space_write_1(sc->sc_iot, sc->sc_ioh, sc->sc_dr.adr, val)
  100 #define DZ_WRITE_WORD(adr, val) \
  101         bus_space_write_2(sc->sc_iot, sc->sc_ioh, sc->sc_dr.adr, val)
  102 #define DZ_BARRIER() \
  103         bus_space_barrier(sc->sc_iot, sc->sc_ioh, sc->sc_dr.dr_firstreg, \
  104             sc->sc_dr.dr_winsize, \
  105             BUS_SPACE_BARRIER_WRITE | BUS_SPACE_BARRIER_READ)
  106 
  107 #include "ioconf.h"
  108 
  109 /* Flags used to monitor modem bits, make them understood outside driver */
  110 
  111 #define DML_DTR         TIOCM_DTR
  112 #define DML_DCD         TIOCM_CD
  113 #define DML_RI          TIOCM_RI
  114 #define DML_BRK         0100000         /* no equivalent, we will mask */
  115 
  116 static const struct speedtab dzspeedtab[] =
  117 {
  118   {       0,    0               },
  119   {      50,    DZ_LPR_B50      },
  120   {      75,    DZ_LPR_B75      },
  121   {     110,    DZ_LPR_B110     },
  122   {     134,    DZ_LPR_B134     },
  123   {     150,    DZ_LPR_B150     },
  124   {     300,    DZ_LPR_B300     },
  125   {     600,    DZ_LPR_B600     },
  126   {    1200,    DZ_LPR_B1200    },
  127   {    1800,    DZ_LPR_B1800    },
  128   {    2000,    DZ_LPR_B2000    },
  129   {    2400,    DZ_LPR_B2400    },
  130   {    3600,    DZ_LPR_B3600    },
  131   {    4800,    DZ_LPR_B4800    },
  132   {    7200,    DZ_LPR_B7200    },
  133   {    9600,    DZ_LPR_B9600    },
  134   {   19200,    DZ_LPR_B19200   },
  135   {      -1,    -1              }
  136 };
  137 
  138 static void     dzstart(struct tty *);
  139 static int      dzparam(struct tty *, struct termios *);
  140 static unsigned dzmctl(struct dz_softc *, int, int, int);
  141 static void     dzscan(void *);
  142 
  143 dev_type_open(dzopen);
  144 dev_type_close(dzclose);
  145 dev_type_read(dzread);
  146 dev_type_write(dzwrite);
  147 dev_type_ioctl(dzioctl);
  148 dev_type_stop(dzstop);
  149 dev_type_tty(dztty);
  150 dev_type_poll(dzpoll);
  151 
  152 const struct cdevsw dz_cdevsw = {
  153         dzopen, dzclose, dzread, dzwrite, dzioctl,
  154         dzstop, dztty, dzpoll, nommap, ttykqfilter, D_TTY
  155 };
  156 
  157 /*
  158  * The DZ series doesn't interrupt on carrier transitions,
  159  * so we have to use a timer to watch it.
  160  */
  161 int     dz_timer;       /* true if timer started */
  162 struct callout dzscan_ch;
  163 static struct cnm_state dz_cnm_state;
  164 
  165 void
  166 dzattach(struct dz_softc *sc, struct evcnt *parent_evcnt, int consline)
  167 {
  168         int n;
  169 
  170         sc->sc_rxint = sc->sc_brk = 0;
  171         sc->sc_consline = consline;
  172 
  173         sc->sc_dr.dr_tcrw = sc->sc_dr.dr_tcr;
  174         DZ_WRITE_WORD(dr_csr, DZ_CSR_MSE | DZ_CSR_RXIE | DZ_CSR_TXIE);
  175         DZ_WRITE_BYTE(dr_dtr, 0);
  176         DZ_WRITE_BYTE(dr_break, 0);
  177         DZ_BARRIER();
  178 
  179         /* Initialize our softc structure. Should be done in open? */
  180 
  181         for (n = 0; n < sc->sc_type; n++) {
  182                 sc->sc_dz[n].dz_sc = sc;
  183                 sc->sc_dz[n].dz_line = n;
  184                 sc->sc_dz[n].dz_tty = ttymalloc();
  185         }
  186 
  187         evcnt_attach_dynamic(&sc->sc_rintrcnt, EVCNT_TYPE_INTR, parent_evcnt,
  188                 sc->sc_dev.dv_xname, "rintr");
  189         evcnt_attach_dynamic(&sc->sc_tintrcnt, EVCNT_TYPE_INTR, parent_evcnt,
  190                 sc->sc_dev.dv_xname, "tintr");
  191 
  192         /* Console magic keys */
  193         cn_init_magic(&dz_cnm_state);
  194         cn_set_magic("\047\001"); /* default magic is BREAK */
  195                                   /* VAX will change it in MD code */
  196 
  197         /* Alas no interrupt on modem bit changes, so we manually scan */
  198 
  199         if (dz_timer == 0) {
  200                 dz_timer = 1;
  201                 callout_init(&dzscan_ch);
  202                 callout_reset(&dzscan_ch, hz, dzscan, NULL);
  203         }
  204         printf("\n");
  205 }
  206 
  207 /* Receiver Interrupt */
  208 
  209 void
  210 dzrint(void *arg)
  211 {
  212         struct dz_softc *sc = arg;
  213         struct tty *tp;
  214         int cc, mcc, line;
  215         unsigned c;
  216         int overrun = 0;
  217 
  218         sc->sc_rxint++;
  219 
  220         while ((c = DZ_READ_WORD(dr_rbuf)) & DZ_RBUF_DATA_VALID) {
  221                 cc = c & 0xFF;
  222                 line = DZ_PORT(c>>8);
  223                 tp = sc->sc_dz[line].dz_tty;
  224 
  225                 /* Must be caught early */
  226                 if (sc->sc_dz[line].dz_catch &&
  227                     (*sc->sc_dz[line].dz_catch)(sc->sc_dz[line].dz_private, cc))
  228                         continue;
  229 
  230                 if ((c & (DZ_RBUF_FRAMING_ERR | 0xff)) == DZ_RBUF_FRAMING_ERR)
  231                         mcc = CNC_BREAK;
  232                 else
  233                         mcc = cc;
  234 
  235                 cn_check_magic(tp->t_dev, mcc, dz_cnm_state);
  236 
  237                 if (!(tp->t_state & TS_ISOPEN)) {
  238                         wakeup((caddr_t)&tp->t_rawq);
  239                         continue;
  240                 }
  241 
  242                 if ((c & DZ_RBUF_OVERRUN_ERR) && overrun == 0) {
  243                         log(LOG_WARNING, "%s: silo overflow, line %d\n",
  244                             sc->sc_dev.dv_xname, line);
  245                         overrun = 1;
  246                 }
  247 
  248                 if (c & DZ_RBUF_FRAMING_ERR)
  249                         cc |= TTY_FE;
  250                 if (c & DZ_RBUF_PARITY_ERR)
  251                         cc |= TTY_PE;
  252 
  253                 (*tp->t_linesw->l_rint)(cc, tp);
  254         }
  255 }
  256 
  257 /* Transmitter Interrupt */
  258 
  259 void
  260 dzxint(void *arg)
  261 {
  262         struct dz_softc *sc = arg;
  263         struct tty *tp;
  264         struct clist *cl;
  265         int line, ch, csr;
  266         u_char tcr;
  267 
  268         /*
  269          * Switch to POLLED mode.
  270          *   Some simple measurements indicated that even on
  271          *  one port, by freeing the scanner in the controller
  272          *  by either providing a character or turning off
  273          *  the port when output is complete, the transmitter
  274          *  was ready to accept more output when polled again.
  275          *   With just two ports running the game "worms,"
  276          *  almost every interrupt serviced both transmitters!
  277          *   Each UART is double buffered, so if the scanner
  278          *  is quick enough and timing works out, we can even
  279          *  feed the same port twice.
  280          *
  281          * Ragge 980517:
  282          * Do not need to turn off interrupts, already at interrupt level.
  283          * Remove the pdma stuff; no great need of it right now.
  284          */
  285 
  286         while (((csr = DZ_READ_WORD(dr_csr)) & DZ_CSR_TX_READY) != 0) {
  287 
  288                 line = DZ_PORT(csr>>8);
  289 
  290                 tp = sc->sc_dz[line].dz_tty;
  291                 cl = &tp->t_outq;
  292                 tp->t_state &= ~TS_BUSY;
  293 
  294                 /* Just send out a char if we have one */
  295                 /* As long as we can fill the chip buffer, we just loop here */
  296                 if (cl->c_cc) {
  297                         tp->t_state |= TS_BUSY;
  298                         ch = getc(cl);
  299                         DZ_WRITE_BYTE(dr_tbuf, ch);
  300                         DZ_BARRIER();
  301                         continue;
  302                 }
  303                 /* Nothing to send; clear the scan bit */
  304                 /* Clear xmit scanner bit; dzstart may set it again */
  305                 tcr = DZ_READ_WORD(dr_tcrw);
  306                 tcr &= 255;
  307                 tcr &= ~(1 << line);
  308                 DZ_WRITE_BYTE(dr_tcr, tcr);
  309                 DZ_BARRIER();
  310                 if (sc->sc_dz[line].dz_catch)
  311                         continue;
  312 
  313                 if (tp->t_state & TS_FLUSH)
  314                         tp->t_state &= ~TS_FLUSH;
  315                 else
  316                         ndflush (&tp->t_outq, cl->c_cc);
  317 
  318                 (*tp->t_linesw->l_start)(tp);
  319         }
  320 }
  321 
  322 int
  323 dzopen(dev_t dev, int flag, int mode, struct lwp *l)
  324 {
  325         struct tty *tp;
  326         int unit, line;
  327         struct  dz_softc *sc;
  328         int s, error = 0;
  329 
  330         unit = DZ_I2C(minor(dev));
  331         line = DZ_PORT(minor(dev));
  332         if (unit >= dz_cd.cd_ndevs ||  dz_cd.cd_devs[unit] == NULL)
  333                 return (ENXIO);
  334 
  335         sc = dz_cd.cd_devs[unit];
  336 
  337         if (line >= sc->sc_type)
  338                 return ENXIO;
  339 
  340         /* if some other device is using the line, it's busy */
  341         if (sc->sc_dz[line].dz_catch)
  342                 return EBUSY;
  343 
  344         tp = sc->sc_dz[line].dz_tty;
  345         if (tp == NULL)
  346                 return (ENODEV);
  347         tp->t_oproc   = dzstart;
  348         tp->t_param   = dzparam;
  349         tp->t_dev = dev;
  350 
  351         if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp))
  352                 return (EBUSY);
  353 
  354         if ((tp->t_state & TS_ISOPEN) == 0) {
  355                 ttychars(tp);
  356                 if (tp->t_ispeed == 0) {
  357                         tp->t_iflag = TTYDEF_IFLAG;
  358                         tp->t_oflag = TTYDEF_OFLAG;
  359                         tp->t_cflag = TTYDEF_CFLAG;
  360                         tp->t_lflag = TTYDEF_LFLAG;
  361                         tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
  362                 }
  363                 (void) dzparam(tp, &tp->t_termios);
  364                 ttsetwater(tp);
  365         }
  366         /* Use DMBIS and *not* DMSET or else we clobber incoming bits */
  367         if (dzmctl(sc, line, DML_DTR, DMBIS) & DML_DCD)
  368                 tp->t_state |= TS_CARR_ON;
  369         s = spltty();
  370         while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) &&
  371                !(tp->t_state & TS_CARR_ON)) {
  372                 tp->t_wopen++;
  373                 error = ttysleep(tp, (caddr_t)&tp->t_rawq,
  374                                 TTIPRI | PCATCH, ttopen, 0);
  375                 tp->t_wopen--;
  376                 if (error)
  377                         break;
  378         }
  379         (void) splx(s);
  380         if (error)
  381                 return (error);
  382         return ((*tp->t_linesw->l_open)(dev, tp));
  383 }
  384 
  385 /*ARGSUSED*/
  386 int
  387 dzclose(dev_t dev, int flag, int mode, struct lwp *l)
  388 {
  389         struct  dz_softc *sc;
  390         struct tty *tp;
  391         int unit, line;
  392 
  393 
  394         unit = DZ_I2C(minor(dev));
  395         line = DZ_PORT(minor(dev));
  396         sc = dz_cd.cd_devs[unit];
  397 
  398         tp = sc->sc_dz[line].dz_tty;
  399 
  400         (*tp->t_linesw->l_close)(tp, flag);
  401 
  402         /* Make sure a BREAK state is not left enabled. */
  403         (void) dzmctl(sc, line, DML_BRK, DMBIC);
  404 
  405         /* Do a hangup if so required. */
  406         if ((tp->t_cflag & HUPCL) || tp->t_wopen || !(tp->t_state & TS_ISOPEN))
  407                 (void) dzmctl(sc, line, 0, DMSET);
  408 
  409         return (ttyclose(tp));
  410 }
  411 
  412 int
  413 dzread(dev_t dev, struct uio *uio, int flag)
  414 {
  415         struct tty *tp;
  416         struct  dz_softc *sc;
  417 
  418         sc = dz_cd.cd_devs[DZ_I2C(minor(dev))];
  419 
  420         tp = sc->sc_dz[DZ_PORT(minor(dev))].dz_tty;
  421         return ((*tp->t_linesw->l_read)(tp, uio, flag));
  422 }
  423 
  424 int
  425 dzwrite(dev_t dev, struct uio *uio, int flag)
  426 {
  427         struct tty *tp;
  428         struct  dz_softc *sc;
  429 
  430         sc = dz_cd.cd_devs[DZ_I2C(minor(dev))];
  431 
  432         tp = sc->sc_dz[DZ_PORT(minor(dev))].dz_tty;
  433         return ((*tp->t_linesw->l_write)(tp, uio, flag));
  434 }
  435 
  436 int
  437 dzpoll(dev, events, l)
  438         dev_t dev;
  439         int events;
  440         struct lwp *l;
  441 {
  442         struct tty *tp;
  443         struct  dz_softc *sc;
  444 
  445         sc = dz_cd.cd_devs[DZ_I2C(minor(dev))];
  446 
  447         tp = sc->sc_dz[DZ_PORT(minor(dev))].dz_tty;
  448         return ((*tp->t_linesw->l_poll)(tp, events, l));
  449 }
  450 
  451 /*ARGSUSED*/
  452 int
  453 dzioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct lwp *l)
  454 {
  455         struct  dz_softc *sc;
  456         struct tty *tp;
  457         int unit, line;
  458         int error;
  459 
  460         unit = DZ_I2C(minor(dev));
  461         line = DZ_PORT(minor(dev));
  462         sc = dz_cd.cd_devs[unit];
  463         tp = sc->sc_dz[line].dz_tty;
  464 
  465         error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l);
  466         if (error >= 0)
  467                 return (error);
  468 
  469         error = ttioctl(tp, cmd, data, flag, l);
  470         if (error >= 0)
  471                 return (error);
  472 
  473         switch (cmd) {
  474 
  475         case TIOCSBRK:
  476                 (void) dzmctl(sc, line, DML_BRK, DMBIS);
  477                 break;
  478 
  479         case TIOCCBRK:
  480                 (void) dzmctl(sc, line, DML_BRK, DMBIC);
  481                 break;
  482 
  483         case TIOCSDTR:
  484                 (void) dzmctl(sc, line, DML_DTR, DMBIS);
  485                 break;
  486 
  487         case TIOCCDTR:
  488                 (void) dzmctl(sc, line, DML_DTR, DMBIC);
  489                 break;
  490 
  491         case TIOCMSET:
  492                 (void) dzmctl(sc, line, *(int *)data, DMSET);
  493                 break;
  494 
  495         case TIOCMBIS:
  496                 (void) dzmctl(sc, line, *(int *)data, DMBIS);
  497                 break;
  498 
  499         case TIOCMBIC:
  500                 (void) dzmctl(sc, line, *(int *)data, DMBIC);
  501                 break;
  502 
  503         case TIOCMGET:
  504                 *(int *)data = (dzmctl(sc, line, 0, DMGET) & ~DML_BRK);
  505                 break;
  506 
  507         default:
  508                 return (EPASSTHROUGH);
  509         }
  510         return (0);
  511 }
  512 
  513 struct tty *
  514 dztty(dev_t dev)
  515 {
  516         struct  dz_softc *sc = dz_cd.cd_devs[DZ_I2C(minor(dev))];
  517         struct tty *tp = sc->sc_dz[DZ_PORT(minor(dev))].dz_tty;
  518 
  519         return (tp);
  520 }
  521 
  522 /*ARGSUSED*/
  523 void
  524 dzstop(struct tty *tp, int flag)
  525 {
  526         if (tp->t_state & TS_BUSY)
  527                 if (!(tp->t_state & TS_TTSTOP))
  528                         tp->t_state |= TS_FLUSH;
  529 }
  530 
  531 void
  532 dzstart(struct tty *tp)
  533 {
  534         struct dz_softc *sc;
  535         struct clist *cl;
  536         int unit, line, s;
  537         char state;
  538 
  539         unit = DZ_I2C(minor(tp->t_dev));
  540         line = DZ_PORT(minor(tp->t_dev));
  541         sc = dz_cd.cd_devs[unit];
  542 
  543         s = spltty();
  544         if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP)) {
  545                 splx(s);
  546                 return;
  547         }
  548         cl = &tp->t_outq;
  549         if (cl->c_cc <= tp->t_lowat) {
  550                 if (tp->t_state & TS_ASLEEP) {
  551                         tp->t_state &= ~TS_ASLEEP;
  552                         wakeup((caddr_t)cl);
  553                 }
  554                 selwakeup(&tp->t_wsel);
  555         }
  556         if (cl->c_cc == 0) {
  557                 splx(s);
  558                 return;
  559         }
  560 
  561         tp->t_state |= TS_BUSY;
  562 
  563         state = DZ_READ_WORD(dr_tcrw) & 255;
  564         if ((state & (1 << line)) == 0) {
  565                 DZ_WRITE_BYTE(dr_tcr, state | (1 << line));
  566                 DZ_BARRIER();
  567         }
  568         dzxint(sc);
  569         splx(s);
  570 }
  571 
  572 static int
  573 dzparam(struct tty *tp, struct termios *t)
  574 {
  575         struct  dz_softc *sc;
  576         int cflag = t->c_cflag;
  577         int unit, line;
  578         int ispeed = ttspeedtab(t->c_ispeed, dzspeedtab);
  579         int ospeed = ttspeedtab(t->c_ospeed, dzspeedtab);
  580         unsigned lpr;
  581         int s;
  582 
  583         unit = DZ_I2C(minor(tp->t_dev));
  584         line = DZ_PORT(minor(tp->t_dev));
  585         sc = dz_cd.cd_devs[unit];
  586 
  587         /* check requested parameters */
  588         if (ospeed < 0 || ispeed < 0 || ispeed != ospeed)
  589                 return (EINVAL);
  590 
  591         tp->t_ispeed = t->c_ispeed;
  592         tp->t_ospeed = t->c_ospeed;
  593         tp->t_cflag = cflag;
  594 
  595         if (ospeed == 0) {
  596                 (void) dzmctl(sc, line, 0, DMSET);      /* hang up line */
  597                 return (0);
  598         }
  599 
  600         s = spltty();
  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_WRITE_WORD(dr_lpr, lpr);
  627         DZ_BARRIER();
  628 
  629         (void) splx(s);
  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 
  643         mbits = 0;
  644 
  645         bit = (1 << line);
  646 
  647         /* external signals as seen from the port */
  648 
  649         status = DZ_READ_BYTE(dr_dcd) | sc->sc_dsr;
  650 
  651         if (status & bit)
  652                 mbits |= DML_DCD;
  653 
  654         status = DZ_READ_BYTE(dr_ring);
  655 
  656         if (status & bit)
  657                 mbits |= DML_RI;
  658 
  659         /* internal signals/state delivered to port */
  660 
  661         status = DZ_READ_BYTE(dr_dtr);
  662 
  663         if (status & bit)
  664                 mbits |= DML_DTR;
  665 
  666         if (sc->sc_brk & bit)
  667                 mbits |= DML_BRK;
  668 
  669         switch (how)
  670         {
  671           case DMSET:
  672                 mbits = bits;
  673                 break;
  674 
  675           case DMBIS:
  676                 mbits |= bits;
  677                 break;
  678 
  679           case DMBIC:
  680                 mbits &= ~bits;
  681                 break;
  682 
  683           case DMGET:
  684                 (void) splx(s);
  685                 return (mbits);
  686         }
  687 
  688         if (mbits & DML_DTR) {
  689                 DZ_WRITE_BYTE(dr_dtr, DZ_READ_BYTE(dr_dtr) | bit);
  690         } else {
  691                 DZ_WRITE_BYTE(dr_dtr, DZ_READ_BYTE(dr_dtr) & ~bit);
  692         }
  693 
  694         if (mbits & DML_BRK) {
  695                 sc->sc_brk |= bit;
  696                 DZ_WRITE_BYTE(dr_break, sc->sc_brk);
  697         } else {
  698                 sc->sc_brk &= ~bit;
  699                 DZ_WRITE_BYTE(dr_break, sc->sc_brk);
  700         }
  701 
  702         DZ_BARRIER();
  703         (void) splx(s);
  704         return (mbits);
  705 }
  706 
  707 /*
  708  * This is called by timeout() periodically.
  709  * Check to see if modem status bits have changed.
  710  */
  711 static void
  712 dzscan(void *arg)
  713 {
  714         struct dz_softc *sc;
  715         struct tty *tp;
  716         int n, bit, port;
  717         unsigned csr;
  718         int s;
  719 
  720         s = spltty();
  721 
  722         for (n = 0; n < dz_cd.cd_ndevs; n++) {
  723 
  724                 if (dz_cd.cd_devs[n] == NULL)
  725                         continue;
  726 
  727                 sc = dz_cd.cd_devs[n];
  728 
  729                 for (port = 0; port < sc->sc_type; port++) {
  730 
  731                         tp = sc->sc_dz[port].dz_tty;
  732                         bit = (1 << port);
  733 
  734                         if ((DZ_READ_BYTE(dr_dcd) | sc->sc_dsr) & bit) {
  735                                 if (!(tp->t_state & TS_CARR_ON))
  736                                         (*tp->t_linesw->l_modem) (tp, 1);
  737                         } else if ((tp->t_state & TS_CARR_ON) &&
  738                             (*tp->t_linesw->l_modem)(tp, 0) == 0) {
  739                                 DZ_WRITE_BYTE(dr_tcr,
  740                                     (DZ_READ_WORD(dr_tcrw) & 255) & ~bit);
  741                                 DZ_BARRIER();
  742                         }
  743                 }
  744 
  745                 /*
  746                  *  If the RX interrupt rate is this high, switch
  747                  *  the controller to Silo Alarm - which means don't
  748                  *  interrupt until the RX silo has 16 characters in
  749                  *  it (the silo is 64 characters in all).
  750                  *  Avoid oscillating SA on and off by not turning
  751                  *  if off unless the rate is appropriately low.
  752                  */
  753 
  754                 csr = DZ_READ_WORD(dr_csr);
  755 
  756                 if (sc->sc_rxint > (16*10)) {
  757                         if ((csr & DZ_CSR_SAE) == 0)
  758                                 DZ_WRITE_WORD(dr_csr, csr | DZ_CSR_SAE);
  759                 } else if ((csr & DZ_CSR_SAE) != 0)
  760                         if (sc->sc_rxint < 10)
  761                                 DZ_WRITE_WORD(dr_csr, csr & ~(DZ_CSR_SAE));
  762 
  763                 DZ_BARRIER();
  764                 sc->sc_rxint = 0;
  765         }
  766         (void) splx(s);
  767         callout_reset(&dzscan_ch, hz, dzscan, NULL);
  768 }
  769 
  770 /*
  771  * Called after an ubareset. The DZ card is reset, but the only thing
  772  * that must be done is to start the receiver and transmitter again.
  773  * No DMA setup to care about.
  774  */
  775 void
  776 dzreset(struct device *dev)
  777 {
  778         struct dz_softc *sc = (void *)dev;
  779         struct tty *tp;
  780         int i;
  781 
  782         for (i = 0; i < sc->sc_type; i++) {
  783                 tp = sc->sc_dz[i].dz_tty;
  784 
  785                 if (((tp->t_state & TS_ISOPEN) == 0) || (tp->t_wopen == 0))
  786                         continue;
  787 
  788                 dzparam(tp, &tp->t_termios);
  789                 dzmctl(sc, i, DML_DTR, DMSET);
  790                 tp->t_state &= ~TS_BUSY;
  791                 dzstart(tp);    /* Kick off transmitter again */
  792         }
  793 }

Cache object: 6af4485193b9274a2efcfceae2278bdf


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