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

Cache object: 622ad00c13d974d8a7407079c296c76e


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