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

Cache object: 48b7db8f2ef24b0dc920a79eb1e5e8ca


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