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/qbus/dhu.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: dhu.c,v 1.46 2006/10/01 19:28:44 elad Exp $    */
    2 /*
    3  * Copyright (c) 2003, Hugh Graham.
    4  * Copyright (c) 1992, 1993
    5  *      The Regents of the University of California.  All rights reserved.
    6  *
    7  * This code is derived from software contributed to Berkeley by
    8  * Ralph Campbell and Rick Macklem.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. Neither the name of the University nor the names of its contributors
   19  *    may be used to endorse or promote products derived from this software
   20  *    without specific prior written permission.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  */
   34 
   35 /*
   36  * Copyright (c) 1996  Ken C. Wellsch.  All rights reserved.
   37  *
   38  * This code is derived from software contributed to Berkeley by
   39  * Ralph Campbell and Rick Macklem.
   40  *
   41  * Redistribution and use in source and binary forms, with or without
   42  * modification, are permitted provided that the following conditions
   43  * are met:
   44  * 1. Redistributions of source code must retain the above copyright
   45  *    notice, this list of conditions and the following disclaimer.
   46  * 2. Redistributions in binary form must reproduce the above copyright
   47  *    notice, this list of conditions and the following disclaimer in the
   48  *    documentation and/or other materials provided with the distribution.
   49  * 3. All advertising materials mentioning features or use of this software
   50  *    must display the following acknowledgement:
   51  *      This product includes software developed by the University of
   52  *      California, Berkeley and its contributors.
   53  * 4. Neither the name of the University nor the names of its contributors
   54  *    may be used to endorse or promote products derived from this software
   55  *    without specific prior written permission.
   56  *
   57  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   58  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   59  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   60  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   61  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   62  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   63  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   64  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   65  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   66  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   67  * SUCH DAMAGE.
   68  */
   69 
   70 #include <sys/cdefs.h>
   71 __KERNEL_RCSID(0, "$NetBSD: dhu.c,v 1.46 2006/10/01 19:28:44 elad Exp $");
   72 
   73 #include <sys/param.h>
   74 #include <sys/systm.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 #include <machine/scb.h>
   89 
   90 #include <dev/qbus/ubavar.h>
   91 
   92 #include <dev/qbus/dhureg.h>
   93 
   94 #include "ioconf.h"
   95 
   96 /* A DHU-11 has 16 ports while a DHV-11 has only 8. We use 16 by default */
   97 
   98 #define NDHULINE        16
   99 
  100 #define DHU_M2U(c)      ((c)>>4)        /* convert minor(dev) to unit # */
  101 #define DHU_LINE(u)     ((u)&0xF)       /* extract line # from minor(dev) */
  102 
  103 struct  dhu_softc {
  104         struct  device  sc_dev;         /* Device struct used by config */
  105         struct  evcnt   sc_rintrcnt;    /* Interrupt statistics */
  106         struct  evcnt   sc_tintrcnt;    /* Interrupt statistics */
  107         int             sc_type;        /* controller type, DHU or DHV */
  108         int             sc_lines;       /* number of lines */
  109         bus_space_tag_t sc_iot;
  110         bus_space_handle_t sc_ioh;
  111         bus_dma_tag_t   sc_dmat;
  112         struct {
  113                 struct  tty *dhu_tty;   /* what we work on */
  114                 bus_dmamap_t dhu_dmah;
  115                 int     dhu_state;      /* to manage TX output status */
  116                 short   dhu_cc;         /* character count on TX */
  117                 short   dhu_modem;      /* modem bits state */
  118         } sc_dhu[NDHULINE];
  119 };
  120 
  121 #define IS_DHU                  16      /* Unibus DHU-11 board linecount */
  122 #define IS_DHV                   8      /* Q-bus DHV-11 or DHQ-11 */
  123 
  124 #define STATE_IDLE              000     /* no current output in progress */
  125 #define STATE_DMA_RUNNING       001     /* DMA TX in progress */
  126 #define STATE_DMA_STOPPED       002     /* DMA TX was aborted */
  127 #define STATE_TX_ONE_CHAR       004     /* did a single char directly */
  128 
  129 /* Flags used to monitor modem bits, make them understood outside driver */
  130 
  131 #define DML_DTR         TIOCM_DTR
  132 #define DML_RTS         TIOCM_RTS
  133 #define DML_CTS         TIOCM_CTS
  134 #define DML_DCD         TIOCM_CD
  135 #define DML_RI          TIOCM_RI
  136 #define DML_DSR         TIOCM_DSR
  137 #define DML_BRK         0100000         /* no equivalent, we will mask */
  138 
  139 #define DHU_READ_WORD(reg) \
  140         bus_space_read_2(sc->sc_iot, sc->sc_ioh, reg)
  141 #define DHU_WRITE_WORD(reg, val) \
  142         bus_space_write_2(sc->sc_iot, sc->sc_ioh, reg, val)
  143 #define DHU_READ_BYTE(reg) \
  144         bus_space_read_1(sc->sc_iot, sc->sc_ioh, reg)
  145 #define DHU_WRITE_BYTE(reg, val) \
  146         bus_space_write_1(sc->sc_iot, sc->sc_ioh, reg, val)
  147 
  148 
  149 /*  On a stock DHV, channel pairs (0/1, 2/3, etc.) must use */
  150 /* a baud rate from the same group.  So limiting to B is likely */
  151 /* best, although clone boards like the ABLE QHV allow all settings. */
  152 
  153 static const struct speedtab dhuspeedtab[] = {
  154   {       0,    0               },      /* Groups  */
  155   {      50,    DHU_LPR_B50     },      /* A       */
  156   {      75,    DHU_LPR_B75     },      /*       B */
  157   {     110,    DHU_LPR_B110    },      /* A and B */
  158   {     134,    DHU_LPR_B134    },      /* A and B */
  159   {     150,    DHU_LPR_B150    },      /*       B */
  160   {     300,    DHU_LPR_B300    },      /* A and B */
  161   {     600,    DHU_LPR_B600    },      /* A and B */
  162   {    1200,    DHU_LPR_B1200   },      /* A and B */
  163   {    1800,    DHU_LPR_B1800   },      /*       B */
  164   {    2000,    DHU_LPR_B2000   },      /*       B */
  165   {    2400,    DHU_LPR_B2400   },      /* A and B */
  166   {    4800,    DHU_LPR_B4800   },      /* A and B */
  167   {    7200,    DHU_LPR_B7200   },      /* A       */
  168   {    9600,    DHU_LPR_B9600   },      /* A and B */
  169   {   19200,    DHU_LPR_B19200  },      /*       B */
  170   {   38400,    DHU_LPR_B38400  },      /* A       */
  171   {      -1,    -1              }
  172 };
  173 
  174 static int      dhu_match(struct device *, struct cfdata *, void *);
  175 static void     dhu_attach(struct device *, struct device *, void *);
  176 static  void    dhurint(void *);
  177 static  void    dhuxint(void *);
  178 static  void    dhustart(struct tty *);
  179 static  int     dhuparam(struct tty *, struct termios *);
  180 static  int     dhuiflow(struct tty *, int);
  181 static unsigned dhumctl(struct dhu_softc *,int, int, int);
  182 
  183 CFATTACH_DECL(dhu, sizeof(struct dhu_softc),
  184     dhu_match, dhu_attach, NULL, NULL);
  185 
  186 dev_type_open(dhuopen);
  187 dev_type_close(dhuclose);
  188 dev_type_read(dhuread);
  189 dev_type_write(dhuwrite);
  190 dev_type_ioctl(dhuioctl);
  191 dev_type_stop(dhustop);
  192 dev_type_tty(dhutty);
  193 dev_type_poll(dhupoll);
  194 
  195 const struct cdevsw dhu_cdevsw = {
  196         dhuopen, dhuclose, dhuread, dhuwrite, dhuioctl,
  197         dhustop, dhutty, dhupoll, nommap, ttykqfilter, D_TTY
  198 };
  199 
  200 /* Autoconfig handles: setup the controller to interrupt, */
  201 /* then complete the housecleaning for full operation */
  202 
  203 static int
  204 dhu_match(parent, cf, aux)
  205         struct device *parent;
  206         struct cfdata *cf;
  207         void *aux;
  208 {
  209         struct uba_attach_args *ua = aux;
  210         int n;
  211 
  212         /* Reset controller to initialize, enable TX/RX interrupts */
  213         /* to catch floating vector info elsewhere when completed */
  214 
  215         bus_space_write_2(ua->ua_iot, ua->ua_ioh, DHU_UBA_CSR,
  216             DHU_CSR_MASTER_RESET | DHU_CSR_RXIE | DHU_CSR_TXIE);
  217 
  218         /* Now wait up to 3 seconds for self-test to complete. */
  219 
  220         for (n = 0; n < 300; n++) {
  221                 DELAY(10000);
  222                 if ((bus_space_read_2(ua->ua_iot, ua->ua_ioh, DHU_UBA_CSR) &
  223                     DHU_CSR_MASTER_RESET) == 0)
  224                         break;
  225         }
  226 
  227         /* If the RESET did not clear after 3 seconds, */
  228         /* the controller must be broken. */
  229 
  230         if (n >= 300)
  231                 return 0;
  232 
  233         /* Check whether diagnostic run has signalled a failure. */
  234 
  235         if ((bus_space_read_2(ua->ua_iot, ua->ua_ioh, DHU_UBA_CSR) &
  236             DHU_CSR_DIAG_FAIL) != 0)
  237                 return 0;
  238 
  239         return 1;
  240 }
  241 
  242 static void
  243 dhu_attach(parent, self, aux)
  244         struct device *parent, *self;
  245         void *aux;
  246 {
  247         struct dhu_softc *sc = device_private(self);
  248         struct uba_attach_args *ua = aux;
  249         unsigned c;
  250         int n, i;
  251 
  252         sc->sc_iot = ua->ua_iot;
  253         sc->sc_ioh = ua->ua_ioh;
  254         sc->sc_dmat = ua->ua_dmat;
  255         /* Process the 8 bytes of diagnostic info put into */
  256         /* the FIFO following the master reset operation. */
  257 
  258         printf("\n%s:", self->dv_xname);
  259         for (n = 0; n < 8; n++) {
  260                 c = DHU_READ_WORD(DHU_UBA_RBUF);
  261 
  262                 if ((c&DHU_DIAG_CODE) == DHU_DIAG_CODE) {
  263                         if ((c&0200) == 0000)
  264                                 printf(" rom(%d) version %d",
  265                                         ((c>>1)&01), ((c>>2)&037));
  266                         else if (((c>>2)&07) != 0)
  267                                 printf(" diag-error(proc%d)=%x",
  268                                         ((c>>1)&01), ((c>>2)&07));
  269                 }
  270         }
  271 
  272         c = DHU_READ_WORD(DHU_UBA_STAT);
  273 
  274         sc->sc_type = (c & DHU_STAT_DHU)? IS_DHU: IS_DHV;
  275 
  276         sc->sc_lines = 8;       /* default */
  277         if (sc->sc_type == IS_DHU && (c & DHU_STAT_MDL))
  278                 sc->sc_lines = 16;
  279 
  280         printf("\n%s: DH%s-11\n", self->dv_xname,
  281             sc->sc_type == IS_DHU ? "U" : "V");
  282 
  283         for (i = 0; i < sc->sc_lines; i++) {
  284                 struct tty *tp;
  285                 tp = sc->sc_dhu[i].dhu_tty = ttymalloc();
  286                 sc->sc_dhu[i].dhu_state = STATE_IDLE;
  287                 bus_dmamap_create(sc->sc_dmat, tp->t_outq.c_cn, 1,
  288                     tp->t_outq.c_cn, 0, BUS_DMA_ALLOCNOW|BUS_DMA_NOWAIT,
  289                     &sc->sc_dhu[i].dhu_dmah);
  290                 bus_dmamap_load(sc->sc_dmat, sc->sc_dhu[i].dhu_dmah,
  291                     tp->t_outq.c_cs, tp->t_outq.c_cn, 0, BUS_DMA_NOWAIT);
  292 
  293         }
  294 
  295         /* Now establish RX & TX interrupt handlers */
  296 
  297         uba_intr_establish(ua->ua_icookie, ua->ua_cvec,
  298                 dhurint, sc, &sc->sc_rintrcnt);
  299         uba_intr_establish(ua->ua_icookie, ua->ua_cvec + 4,
  300                 dhuxint, sc, &sc->sc_tintrcnt);
  301         evcnt_attach_dynamic(&sc->sc_rintrcnt, EVCNT_TYPE_INTR, ua->ua_evcnt,
  302                 sc->sc_dev.dv_xname, "rintr");
  303         evcnt_attach_dynamic(&sc->sc_tintrcnt, EVCNT_TYPE_INTR, ua->ua_evcnt,
  304                 sc->sc_dev.dv_xname, "tintr");
  305 }
  306 
  307 /* Receiver Interrupt */
  308 
  309 static void
  310 dhurint(arg)
  311         void *arg;
  312 {
  313         struct  dhu_softc *sc = arg;
  314         struct tty *tp;
  315         int cc, line;
  316         unsigned c, delta;
  317         int overrun = 0;
  318 
  319         while ((c = DHU_READ_WORD(DHU_UBA_RBUF)) & DHU_RBUF_DATA_VALID) {
  320 
  321                 /* Ignore diagnostic FIFO entries. */
  322 
  323                 if ((c & DHU_DIAG_CODE) == DHU_DIAG_CODE)
  324                         continue;
  325 
  326                 cc = c & 0xFF;
  327                 line = DHU_LINE(c>>8);
  328                 tp = sc->sc_dhu[line].dhu_tty;
  329 
  330                 /* LINK.TYPE is set so we get modem control FIFO entries */
  331 
  332                 if ((c & DHU_DIAG_CODE) == DHU_MODEM_CODE) {
  333                         c = (c << 8);
  334                         /* Do MDMBUF flow control, wakeup sleeping opens */
  335                         if (c & DHU_STAT_DCD) {
  336                                 if (!(tp->t_state & TS_CARR_ON))
  337                                     (void)(*tp->t_linesw->l_modem)(tp, 1);
  338                         }
  339                         else if ((tp->t_state & TS_CARR_ON) &&
  340                                 (*tp->t_linesw->l_modem)(tp, 0) == 0)
  341                                         (void) dhumctl(sc, line, 0, DMSET);
  342 
  343                         /* Do CRTSCTS flow control */
  344                         delta = c ^ sc->sc_dhu[line].dhu_modem;
  345                         sc->sc_dhu[line].dhu_modem = c;
  346                         if ((delta & DHU_STAT_CTS) &&
  347                             (tp->t_state & TS_ISOPEN) &&
  348                             (tp->t_cflag & CRTSCTS)) {
  349                                 if (c & DHU_STAT_CTS) {
  350                                         tp->t_state &= ~TS_TTSTOP;
  351                                         ttstart(tp);
  352                                 } else {
  353                                         tp->t_state |= TS_TTSTOP;
  354                                         dhustop(tp, 0);
  355                                 }
  356                         }
  357                         continue;
  358                 }
  359 
  360                 if (!(tp->t_state & TS_ISOPEN)) {
  361                         wakeup((caddr_t)&tp->t_rawq);
  362                         continue;
  363                 }
  364 
  365                 if ((c & DHU_RBUF_OVERRUN_ERR) && overrun == 0) {
  366                         log(LOG_WARNING, "%s: silo overflow, line %d\n",
  367                                 sc->sc_dev.dv_xname, line);
  368                         overrun = 1;
  369                 }
  370                 /* A BREAK key will appear as a NULL with a framing error */
  371                 if (c & DHU_RBUF_FRAMING_ERR)
  372                         cc |= TTY_FE;
  373                 if (c & DHU_RBUF_PARITY_ERR)
  374                         cc |= TTY_PE;
  375 
  376                 (*tp->t_linesw->l_rint)(cc, tp);
  377         }
  378 }
  379 
  380 /* Transmitter Interrupt */
  381 
  382 static void
  383 dhuxint(arg)
  384         void *arg;
  385 {
  386         struct  dhu_softc *sc = arg;
  387         struct tty *tp;
  388         int line, i;
  389 
  390         while ((i = DHU_READ_BYTE(DHU_UBA_CSR_HI)) & (DHU_CSR_TX_ACTION >> 8)) {
  391 
  392                 line = DHU_LINE(i);
  393                 tp = sc->sc_dhu[line].dhu_tty;
  394 
  395                 if (i & (DHU_CSR_TX_DMA_ERROR >> 8))
  396                         printf("%s: DMA ERROR on line: %d\n",
  397                             sc->sc_dev.dv_xname, line);
  398                 if (i & (DHU_CSR_DIAG_FAIL >> 8))
  399                         printf("%s: DIAG FAIL on line: %d\n",
  400                             sc->sc_dev.dv_xname, line);
  401 
  402                 tp->t_state &= ~TS_BUSY;
  403                 if (tp->t_state & TS_FLUSH)
  404                         tp->t_state &= ~TS_FLUSH;
  405                 else {
  406                         if (sc->sc_dhu[line].dhu_state == STATE_DMA_STOPPED)
  407                                 sc->sc_dhu[line].dhu_cc -=
  408                                     DHU_READ_WORD(DHU_UBA_TBUFCNT);
  409                         ndflush(&tp->t_outq, sc->sc_dhu[line].dhu_cc);
  410                         sc->sc_dhu[line].dhu_cc = 0;
  411                 }
  412 
  413                 sc->sc_dhu[line].dhu_state = STATE_IDLE;
  414 
  415                 (*tp->t_linesw->l_start)(tp);
  416         }
  417 }
  418 
  419 int
  420 dhuopen(dev, flag, mode, l)
  421         dev_t dev;
  422         int flag, mode;
  423         struct lwp *l;
  424 {
  425         struct tty *tp;
  426         int unit, line;
  427         struct dhu_softc *sc;
  428         int s, error = 0;
  429 
  430         unit = DHU_M2U(minor(dev));
  431         line = DHU_LINE(minor(dev));
  432 
  433         if (unit >= dhu_cd.cd_ndevs || dhu_cd.cd_devs[unit] == NULL)
  434                 return (ENXIO);
  435 
  436         sc = dhu_cd.cd_devs[unit];
  437 
  438         if (line >= sc->sc_lines)
  439                 return ENXIO;
  440 
  441         if (sc->sc_type == IS_DHU) {
  442                 s = spltty();   /* CSR 3:0 must be 0 */
  443                 DHU_WRITE_BYTE(DHU_UBA_CSR, DHU_CSR_RXIE);
  444                 DHU_WRITE_BYTE(DHU_UBA_RXTIME, 10);
  445                 splx(s);        /* RX int delay 10ms */
  446         }
  447 
  448         s = spltty();
  449         DHU_WRITE_BYTE(DHU_UBA_CSR, DHU_CSR_RXIE | line);
  450         sc->sc_dhu[line].dhu_modem = DHU_READ_WORD(DHU_UBA_STAT);
  451         (void) splx(s);
  452 
  453         tp = sc->sc_dhu[line].dhu_tty;
  454 
  455         tp->t_oproc   = dhustart;
  456         tp->t_param   = dhuparam;
  457         tp->t_hwiflow = dhuiflow;
  458         tp->t_dev = dev;
  459 
  460         if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp))
  461                 return (EBUSY);
  462 
  463         if ((tp->t_state & TS_ISOPEN) == 0) {
  464                 ttychars(tp);
  465                 if (tp->t_ispeed == 0) {
  466                         tp->t_iflag = TTYDEF_IFLAG;
  467                         tp->t_oflag = TTYDEF_OFLAG;
  468                         tp->t_cflag = TTYDEF_CFLAG;
  469                         tp->t_lflag = TTYDEF_LFLAG;
  470                         tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
  471                 }
  472                 (void) dhuparam(tp, &tp->t_termios);
  473                 ttsetwater(tp);
  474         }
  475         /* Use DMBIS and *not* DMSET or else we clobber incoming bits */
  476         if (dhumctl(sc, line, DML_DTR|DML_RTS, DMBIS) & DML_DCD)
  477                 tp->t_state |= TS_CARR_ON;
  478         s = spltty();
  479         while (!(flag & O_NONBLOCK) && !(tp->t_cflag & CLOCAL) &&
  480             !(tp->t_state & TS_CARR_ON)) {
  481                 tp->t_wopen++;
  482                 error = ttysleep(tp, (caddr_t)&tp->t_rawq,
  483                                 TTIPRI | PCATCH, ttopen, 0);
  484                 tp->t_wopen--;
  485                 if (error)
  486                         break;
  487         }
  488         (void) splx(s);
  489         if (error)
  490                 return (error);
  491         return ((*tp->t_linesw->l_open)(dev, tp));
  492 }
  493 
  494 /*ARGSUSED*/
  495 int
  496 dhuclose(dev, flag, mode, l)
  497         dev_t dev;
  498         int flag, mode;
  499         struct lwp *l;
  500 {
  501         struct tty *tp;
  502         int unit, line;
  503         struct dhu_softc *sc;
  504 
  505         unit = DHU_M2U(minor(dev));
  506         line = DHU_LINE(minor(dev));
  507 
  508         sc = dhu_cd.cd_devs[unit];
  509 
  510         tp = sc->sc_dhu[line].dhu_tty;
  511 
  512         (*tp->t_linesw->l_close)(tp, flag);
  513 
  514         /* Make sure a BREAK state is not left enabled. */
  515 
  516         (void) dhumctl(sc, line, DML_BRK, DMBIC);
  517 
  518         /* Do a hangup if so required. */
  519 
  520         if ((tp->t_cflag & HUPCL) || tp->t_wopen ||
  521             !(tp->t_state & TS_ISOPEN))
  522                 (void) dhumctl(sc, line, 0, DMSET);
  523 
  524         return (ttyclose(tp));
  525 }
  526 
  527 int
  528 dhuread(dev, uio, flag)
  529         dev_t dev;
  530         struct uio *uio;
  531         int flag;
  532 {
  533         struct dhu_softc *sc;
  534         struct tty *tp;
  535 
  536         sc = dhu_cd.cd_devs[DHU_M2U(minor(dev))];
  537 
  538         tp = sc->sc_dhu[DHU_LINE(minor(dev))].dhu_tty;
  539         return ((*tp->t_linesw->l_read)(tp, uio, flag));
  540 }
  541 
  542 int
  543 dhuwrite(dev, uio, flag)
  544         dev_t dev;
  545         struct uio *uio;
  546         int flag;
  547 {
  548         struct dhu_softc *sc;
  549         struct tty *tp;
  550 
  551         sc = dhu_cd.cd_devs[DHU_M2U(minor(dev))];
  552 
  553         tp = sc->sc_dhu[DHU_LINE(minor(dev))].dhu_tty;
  554         return ((*tp->t_linesw->l_write)(tp, uio, flag));
  555 }
  556 
  557 int
  558 dhupoll(dev, events, l)
  559         dev_t dev;
  560         int events;
  561         struct lwp *l;
  562 {
  563         struct dhu_softc *sc;
  564         struct tty *tp;
  565 
  566         sc = dhu_cd.cd_devs[DHU_M2U(minor(dev))];
  567 
  568         tp = sc->sc_dhu[DHU_LINE(minor(dev))].dhu_tty;
  569         return ((*tp->t_linesw->l_poll)(tp, events, l));
  570 }
  571 
  572 /*ARGSUSED*/
  573 int
  574 dhuioctl(dev, cmd, data, flag, l)
  575         dev_t dev;
  576         u_long cmd;
  577         caddr_t data;
  578         int flag;
  579         struct lwp *l;
  580 {
  581         struct dhu_softc *sc;
  582         struct tty *tp;
  583         int unit, line;
  584         int error;
  585 
  586         unit = DHU_M2U(minor(dev));
  587         line = DHU_LINE(minor(dev));
  588         sc = dhu_cd.cd_devs[unit];
  589         tp = sc->sc_dhu[line].dhu_tty;
  590 
  591         error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l);
  592         if (error != EPASSTHROUGH)
  593                 return (error);
  594 
  595         error = ttioctl(tp, cmd, data, flag, l);
  596         if (error != EPASSTHROUGH)
  597                 return (error);
  598 
  599         switch (cmd) {
  600 
  601         case TIOCSBRK:
  602                 (void) dhumctl(sc, line, DML_BRK, DMBIS);
  603                 break;
  604 
  605         case TIOCCBRK:
  606                 (void) dhumctl(sc, line, DML_BRK, DMBIC);
  607                 break;
  608 
  609         case TIOCSDTR:
  610                 (void) dhumctl(sc, line, DML_DTR|DML_RTS, DMBIS);
  611                 break;
  612 
  613         case TIOCCDTR:
  614                 (void) dhumctl(sc, line, DML_DTR|DML_RTS, DMBIC);
  615                 break;
  616 
  617         case TIOCMSET:
  618                 (void) dhumctl(sc, line, *(int *)data, DMSET);
  619                 break;
  620 
  621         case TIOCMBIS:
  622                 (void) dhumctl(sc, line, *(int *)data, DMBIS);
  623                 break;
  624 
  625         case TIOCMBIC:
  626                 (void) dhumctl(sc, line, *(int *)data, DMBIC);
  627                 break;
  628 
  629         case TIOCMGET:
  630                 *(int *)data = (dhumctl(sc, line, 0, DMGET) & ~DML_BRK);
  631                 break;
  632 
  633         default:
  634                 return (EPASSTHROUGH);
  635         }
  636         return (0);
  637 }
  638 
  639 struct tty *
  640 dhutty(dev)
  641         dev_t dev;
  642 {
  643         struct dhu_softc *sc = dhu_cd.cd_devs[DHU_M2U(minor(dev))];
  644         struct tty *tp = sc->sc_dhu[DHU_LINE(minor(dev))].dhu_tty;
  645         return (tp);
  646 }
  647 
  648 /*ARGSUSED*/
  649 void
  650 dhustop(tp, flag)
  651         struct tty *tp;
  652         int flag;
  653 {
  654         struct dhu_softc *sc;
  655         int line;
  656         int s;
  657 
  658         s = spltty();
  659 
  660         if (tp->t_state & TS_BUSY) {
  661 
  662                 sc = dhu_cd.cd_devs[DHU_M2U(minor(tp->t_dev))];
  663                 line = DHU_LINE(minor(tp->t_dev));
  664 
  665                 if (sc->sc_dhu[line].dhu_state == STATE_DMA_RUNNING) {
  666 
  667                         sc->sc_dhu[line].dhu_state = STATE_DMA_STOPPED;
  668 
  669                         DHU_WRITE_BYTE(DHU_UBA_CSR, DHU_CSR_RXIE | line);
  670                         DHU_WRITE_WORD(DHU_UBA_LNCTRL,
  671                             DHU_READ_WORD(DHU_UBA_LNCTRL) |
  672                             DHU_LNCTRL_DMA_ABORT);
  673                 }
  674 
  675                 if (!(tp->t_state & TS_TTSTOP))
  676                         tp->t_state |= TS_FLUSH;
  677         }
  678         (void) splx(s);
  679 }
  680 
  681 static void
  682 dhustart(tp)
  683         struct tty *tp;
  684 {
  685         struct dhu_softc *sc;
  686         int line, cc;
  687         int addr;
  688         int s;
  689 
  690         s = spltty();
  691         if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
  692                 goto out;
  693         if (tp->t_outq.c_cc <= tp->t_lowat) {
  694                 if (tp->t_state & TS_ASLEEP) {
  695                         tp->t_state &= ~TS_ASLEEP;
  696                         wakeup((caddr_t)&tp->t_outq);
  697                 }
  698                 selwakeup(&tp->t_wsel);
  699         }
  700         if (tp->t_outq.c_cc == 0)
  701                 goto out;
  702         cc = ndqb(&tp->t_outq, 0);
  703         if (cc == 0)
  704                 goto out;
  705 
  706         tp->t_state |= TS_BUSY;
  707 
  708         sc = dhu_cd.cd_devs[DHU_M2U(minor(tp->t_dev))];
  709 
  710         line = DHU_LINE(minor(tp->t_dev));
  711 
  712         DHU_WRITE_BYTE(DHU_UBA_CSR, DHU_CSR_RXIE | line);
  713 
  714         sc->sc_dhu[line].dhu_cc = cc;
  715 
  716         if (cc == 1 && sc->sc_type == IS_DHV) {
  717 
  718                 sc->sc_dhu[line].dhu_state = STATE_TX_ONE_CHAR;
  719 
  720                 DHU_WRITE_WORD(DHU_UBA_TXCHAR,
  721                     DHU_TXCHAR_DATA_VALID | *tp->t_outq.c_cf);
  722 
  723         } else {
  724 
  725                 sc->sc_dhu[line].dhu_state = STATE_DMA_RUNNING;
  726 
  727                 addr = sc->sc_dhu[line].dhu_dmah->dm_segs[0].ds_addr +
  728                         (tp->t_outq.c_cf - tp->t_outq.c_cs);
  729 
  730                 DHU_WRITE_WORD(DHU_UBA_TBUFCNT, cc);
  731                 DHU_WRITE_WORD(DHU_UBA_TBUFAD1, addr & 0xFFFF);
  732                 DHU_WRITE_WORD(DHU_UBA_TBUFAD2, ((addr>>16) & 0x3F) |
  733                     DHU_TBUFAD2_TX_ENABLE);
  734                 DHU_WRITE_WORD(DHU_UBA_LNCTRL,
  735                     DHU_READ_WORD(DHU_UBA_LNCTRL) & ~DHU_LNCTRL_DMA_ABORT);
  736                 DHU_WRITE_WORD(DHU_UBA_TBUFAD2,
  737                     DHU_READ_WORD(DHU_UBA_TBUFAD2) | DHU_TBUFAD2_DMA_START);
  738         }
  739 out:
  740         (void) splx(s);
  741         return;
  742 }
  743 
  744 static int
  745 dhuparam(tp, t)
  746         struct tty *tp;
  747         struct termios *t;
  748 {
  749         struct dhu_softc *sc;
  750         int cflag = t->c_cflag;
  751         int ispeed = ttspeedtab(t->c_ispeed, dhuspeedtab);
  752         int ospeed = ttspeedtab(t->c_ospeed, dhuspeedtab);
  753         unsigned lpr, lnctrl;
  754         int unit, line;
  755         int s;
  756 
  757         unit = DHU_M2U(minor(tp->t_dev));
  758         line = DHU_LINE(minor(tp->t_dev));
  759 
  760         sc = dhu_cd.cd_devs[unit];
  761 
  762         /* check requested parameters */
  763         if (ospeed < 0 || ispeed < 0)
  764                 return (EINVAL);
  765 
  766         tp->t_ispeed = t->c_ispeed;
  767         tp->t_ospeed = t->c_ospeed;
  768         tp->t_cflag = cflag;
  769 
  770         if (ospeed == 0) {
  771                 (void) dhumctl(sc, line, 0, DMSET);     /* hang up line */
  772                 return (0);
  773         }
  774 
  775         s = spltty();
  776         DHU_WRITE_BYTE(DHU_UBA_CSR, DHU_CSR_RXIE | line);
  777 
  778         lpr = ((ispeed&017)<<8) | ((ospeed&017)<<12) ;
  779 
  780         switch (cflag & CSIZE) {
  781 
  782         case CS5:
  783                 lpr |= DHU_LPR_5_BIT_CHAR;
  784                 break;
  785 
  786         case CS6:
  787                 lpr |= DHU_LPR_6_BIT_CHAR;
  788                 break;
  789 
  790         case CS7:
  791                 lpr |= DHU_LPR_7_BIT_CHAR;
  792                 break;
  793 
  794         default:
  795                 lpr |= DHU_LPR_8_BIT_CHAR;
  796                 break;
  797         }
  798 
  799         if (cflag & PARENB)
  800                 lpr |= DHU_LPR_PARENB;
  801         if (!(cflag & PARODD))
  802                 lpr |= DHU_LPR_EPAR;
  803         if (cflag & CSTOPB)
  804                 lpr |= DHU_LPR_2_STOP;
  805 
  806         DHU_WRITE_WORD(DHU_UBA_LPR, lpr);
  807 
  808         DHU_WRITE_WORD(DHU_UBA_TBUFAD2,
  809             DHU_READ_WORD(DHU_UBA_TBUFAD2) | DHU_TBUFAD2_TX_ENABLE);
  810 
  811         lnctrl = DHU_READ_WORD(DHU_UBA_LNCTRL);
  812 
  813         /* Setting LINK.TYPE enables modem signal change interrupts. */
  814 
  815         lnctrl |= (DHU_LNCTRL_RX_ENABLE | DHU_LNCTRL_LINK_TYPE);
  816 
  817         /* Enable the auto XON/XOFF feature on the controller */
  818 
  819         if (t->c_iflag & IXON)
  820                 lnctrl |= DHU_LNCTRL_OAUTO;
  821         else
  822                 lnctrl &= ~DHU_LNCTRL_OAUTO;
  823 
  824         if (t->c_iflag & IXOFF)
  825                 lnctrl |= DHU_LNCTRL_IAUTO;
  826         else
  827                 lnctrl &= ~DHU_LNCTRL_IAUTO;
  828 
  829         DHU_WRITE_WORD(DHU_UBA_LNCTRL, lnctrl);
  830 
  831         (void) splx(s);
  832         return (0);
  833 }
  834 
  835 static int
  836 dhuiflow(tp, flag)
  837         struct tty *tp;
  838         int flag;
  839 {
  840         struct dhu_softc *sc;
  841         int line = DHU_LINE(minor(tp->t_dev));
  842 
  843         if (tp->t_cflag & CRTSCTS) {
  844                 sc = dhu_cd.cd_devs[DHU_M2U(minor(tp->t_dev))];
  845                 (void) dhumctl(sc, line, DML_RTS, ((flag)? DMBIC: DMBIS));
  846                 return (1);
  847         }
  848         return (0);
  849 }
  850 
  851 static unsigned
  852 dhumctl(sc, line, bits, how)
  853         struct dhu_softc *sc;
  854         int line, bits, how;
  855 {
  856         unsigned status;
  857         unsigned lnctrl;
  858         unsigned mbits;
  859         int s;
  860 
  861         s = spltty();
  862 
  863         DHU_WRITE_BYTE(DHU_UBA_CSR, DHU_CSR_RXIE | line);
  864 
  865         mbits = 0;
  866 
  867         /* external signals as seen from the port */
  868 
  869         status = DHU_READ_WORD(DHU_UBA_STAT);
  870 
  871         if (status & DHU_STAT_CTS)
  872                 mbits |= DML_CTS;
  873 
  874         if (status & DHU_STAT_DCD)
  875                 mbits |= DML_DCD;
  876 
  877         if (status & DHU_STAT_DSR)
  878                 mbits |= DML_DSR;
  879 
  880         if (status & DHU_STAT_RI)
  881                 mbits |= DML_RI;
  882 
  883         /* internal signals/state delivered to port */
  884 
  885         lnctrl = DHU_READ_WORD(DHU_UBA_LNCTRL);
  886 
  887         if (lnctrl & DHU_LNCTRL_RTS)
  888                 mbits |= DML_RTS;
  889 
  890         if (lnctrl & DHU_LNCTRL_DTR)
  891                 mbits |= DML_DTR;
  892 
  893         if (lnctrl & DHU_LNCTRL_BREAK)
  894                 mbits |= DML_BRK;
  895 
  896         switch (how) {
  897 
  898         case DMSET:
  899                 mbits = bits;
  900                 break;
  901 
  902         case DMBIS:
  903                 mbits |= bits;
  904                 break;
  905 
  906         case DMBIC:
  907                 mbits &= ~bits;
  908                 break;
  909 
  910         case DMGET:
  911                 (void) splx(s);
  912                 return (mbits);
  913         }
  914 
  915         if (mbits & DML_RTS)
  916                 lnctrl |= DHU_LNCTRL_RTS;
  917         else
  918                 lnctrl &= ~DHU_LNCTRL_RTS;
  919 
  920         if (mbits & DML_DTR)
  921                 lnctrl |= DHU_LNCTRL_DTR;
  922         else
  923                 lnctrl &= ~DHU_LNCTRL_DTR;
  924 
  925         if (mbits & DML_BRK)
  926                 lnctrl |= DHU_LNCTRL_BREAK;
  927         else
  928                 lnctrl &= ~DHU_LNCTRL_BREAK;
  929 
  930         DHU_WRITE_WORD(DHU_UBA_LNCTRL, lnctrl);
  931 
  932         (void) splx(s);
  933         return (mbits);
  934 }

Cache object: 9e4beb9b58550863744d9ef36c4ce0d5


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