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/ic/cy.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 /*      $OpenBSD: cy.c,v 1.41 2021/09/01 16:10:39 jan Exp $     */
    2 /*
    3  * Copyright (c) 1996 Timo Rossi.
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  * 3. Neither the name of the author nor the names of contributors
   15  *    may be used to endorse or promote products derived from this software
   16  *    without specific prior written permission.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   28  * SUCH DAMAGE.
   29  */
   30 
   31 /*
   32  * cy.c
   33  *
   34  * Driver for Cyclades Cyclom-8/16/32 multiport serial cards
   35  * (currently not tested with Cyclom-32 cards)
   36  *
   37  * Timo Rossi, 1996
   38  *
   39  * Supports both ISA and PCI Cyclom cards
   40  *
   41  * Uses CD1400 automatic CTS flow control, and
   42  * if CY_HW_RTS is defined, uses CD1400 automatic input flow control.
   43  * This requires a special cable that exchanges the RTS and DTR lines.
   44  *
   45  * Lots of debug output can be enabled by defining CY_DEBUG
   46  * Some debugging counters (number of receive/transmit interrupts etc.)
   47  * can be enabled by defining CY_DEBUG1
   48  *
   49  * This version uses the bus_space/io_??() stuff
   50  *
   51  */
   52 
   53 #include <sys/param.h>
   54 #include <sys/ioctl.h>
   55 #include <sys/syslog.h>
   56 #include <sys/fcntl.h>
   57 #include <sys/tty.h>
   58 #include <sys/conf.h>
   59 #include <sys/selinfo.h>
   60 #include <sys/device.h>
   61 #include <sys/malloc.h>
   62 #include <sys/systm.h>
   63 
   64 #include <machine/bus.h>
   65 #include <machine/intr.h>
   66 
   67 #include <dev/ic/cd1400reg.h>
   68 #include <dev/ic/cyreg.h>
   69 
   70 
   71 int     cy_intr(void *);
   72 int     cyparam(struct tty *, struct termios *);
   73 void    cystart(struct tty *);
   74 void    cy_poll(void *);
   75 int     cy_modem_control(struct cy_port *, int, int);
   76 void    cy_enable_transmitter(struct cy_port *);
   77 void    cd1400_channel_cmd(struct cy_port *, int);
   78 int     cy_speed(speed_t, int *, int *, int);
   79 
   80 struct cfdriver cy_cd = {
   81         NULL, "cy", DV_TTY
   82 };
   83 
   84 /*
   85  * Common probe routine
   86  *
   87  * returns the number of chips found.
   88  */
   89 int
   90 cy_probe_common(bus_space_tag_t memt, bus_space_handle_t memh, int bustype)
   91 {
   92         int cy_chip, chip_offs;
   93         u_char firmware_ver;
   94         int nchips;
   95 
   96         /* Cyclom card hardware reset */
   97         bus_space_write_1(memt, memh, CY16_RESET<<bustype, 0);
   98         DELAY(500); /* wait for reset to complete */
   99         bus_space_write_1(memt, memh, CY_CLEAR_INTR<<bustype, 0);
  100 
  101 #ifdef CY_DEBUG
  102         printf("cy: card reset done\n");
  103 #endif
  104 
  105         nchips = 0;
  106 
  107         for (cy_chip = 0, chip_offs = 0;
  108             cy_chip < CY_MAX_CD1400s;
  109             cy_chip++, chip_offs += (CY_CD1400_MEMSPACING << bustype)) {
  110                 int i;
  111 
  112                 /* the last 4 cd1400s are 'interleaved'
  113                    with the first 4 on 32-port boards */
  114                 if (cy_chip == 4)
  115                         chip_offs -= (CY32_ADDR_FIX << bustype);
  116 
  117 #ifdef CY_DEBUG
  118                 printf("cy: probe chip %d offset 0x%x ... ",
  119                     cy_chip, chip_offs);
  120 #endif
  121 
  122                 /* wait until the chip is ready for command */
  123                 DELAY(1000);
  124                 if (bus_space_read_1(memt, memh, chip_offs +
  125                     ((CD1400_CCR << 1) << bustype)) != 0) {
  126 #ifdef CY_DEBUG
  127                         printf("not ready for command\n");
  128 #endif
  129                         break;
  130                 }
  131 
  132                 /* clear the firmware version reg. */
  133                 bus_space_write_1(memt, memh, chip_offs +
  134                     ((CD1400_GFRCR << 1) << bustype), 0);
  135 
  136                 /*
  137                  * On Cyclom-16 references to non-existent chip 4
  138                  * actually access chip 0 (address line 9 not decoded).
  139                  * Here we check if the clearing of chip 4 GFRCR actually
  140                  * cleared chip 0 GFRCR. In that case we have a 16 port card.
  141                  */
  142                 if (cy_chip == 4 &&
  143                     bus_space_read_1(memt, memh, chip_offs +
  144                         ((CD1400_GFRCR << 1) << bustype)) == 0)
  145                         break;
  146 
  147                 /* reset the chip */
  148                 bus_space_write_1(memt, memh, chip_offs +
  149                     ((CD1400_CCR << 1) << bustype),
  150                     CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET);
  151 
  152                 /* wait for the chip to initialize itself */
  153                 for (i = 0; i < 200; i++) {
  154                         DELAY(50);
  155                         firmware_ver = bus_space_read_1(memt, memh, chip_offs +
  156                             ((CD1400_GFRCR << 1) << bustype));
  157                         if ((firmware_ver & 0xf0) == 0x40) /* found a CD1400 */
  158                                 break;
  159                 }
  160 #ifdef CY_DEBUG
  161                 printf("firmware version 0x%x\n", firmware_ver);
  162 #endif      
  163 
  164                 if ((firmware_ver & 0xf0) != 0x40)
  165                         break;
  166 
  167                 /* firmware version OK, CD1400 found */
  168                 nchips++;
  169         }
  170 
  171         if (nchips == 0) {
  172 #ifdef CY_DEBUG
  173                 printf("no CD1400s found\n");
  174 #endif
  175                 return (0);
  176         }
  177 
  178 #ifdef CY_DEBUG
  179         printf("found %d CD1400s\n", nchips);
  180 #endif
  181 
  182         return (nchips);
  183 }
  184 
  185 void
  186 cy_attach(struct device *parent, struct device *self)
  187 {
  188         int card, port, cy_chip, num_chips, cdu, chip_offs, cy_clock;
  189         struct cy_softc *sc = (void *)self;
  190 
  191         card = sc->sc_dev.dv_unit;
  192         num_chips = sc->sc_nr_cd1400s;
  193         if (num_chips == 0)
  194                 return;
  195 
  196         timeout_set(&sc->sc_poll_to, cy_poll, sc);
  197         bzero(sc->sc_ports, sizeof(sc->sc_ports));
  198         sc->sc_nports = num_chips * CD1400_NO_OF_CHANNELS;
  199 
  200         port = 0;
  201         for (cy_chip = 0, chip_offs = 0;
  202             cy_chip < num_chips;
  203             cy_chip++, chip_offs += (CY_CD1400_MEMSPACING<<sc->sc_bustype)) {
  204                 if (cy_chip == 4)
  205                         chip_offs -= (CY32_ADDR_FIX<<sc->sc_bustype);
  206 
  207 #ifdef CY_DEBUG
  208                 printf("attach CD1400 #%d offset 0x%x\n", cy_chip, chip_offs);
  209 #endif
  210                 sc->sc_cd1400_offs[cy_chip] = chip_offs;
  211 
  212                 /* configure port 0 as serial port
  213                    (should already be after reset) */
  214                 cd_write_reg_sc(sc, cy_chip, CD1400_GCR, 0);
  215 
  216                 /* Set cy_clock depending on firmware version */
  217                 if (cd_read_reg_sc(sc, cy_chip, CD1400_GFRCR) <= 0x46)
  218                         cy_clock = CY_CLOCK;
  219                 else 
  220                         cy_clock = CY_CLOCK_60;
  221 
  222                 /* set up a receive timeout period (1ms) */
  223                 cd_write_reg_sc(sc, cy_chip, CD1400_PPR,
  224                     (cy_clock / CD1400_PPR_PRESCALER / 1000) + 1);
  225 
  226                 for (cdu = 0; cdu < CD1400_NO_OF_CHANNELS; cdu++) {
  227                         sc->sc_ports[port].cy_port_num = port;
  228                         sc->sc_ports[port].cy_memt = sc->sc_memt;
  229                         sc->sc_ports[port].cy_memh = sc->sc_memh;
  230                         sc->sc_ports[port].cy_chip_offs = chip_offs;
  231                         sc->sc_ports[port].cy_bustype = sc->sc_bustype;
  232                         sc->sc_ports[port].cy_clock = cy_clock;
  233 
  234                         /* should we initialize anything else here? */
  235                         port++;
  236                 } /* for(each port on one CD1400...) */
  237 
  238         } /* for(each CD1400 on a card... ) */
  239 
  240         printf(": %d ports\n", port);
  241 
  242         /* ensure an edge for the next interrupt */
  243         bus_space_write_1(sc->sc_memt, sc->sc_memh,
  244             CY_CLEAR_INTR<<sc->sc_bustype, 0);
  245 }
  246 
  247 /*
  248  * open routine. returns zero if successful, else error code
  249  */
  250 int cyopen(dev_t, int, int, struct proc *);
  251 int cyclose(dev_t, int, int, struct proc *);
  252 int cyread(dev_t, struct uio *, int);
  253 int cywrite(dev_t, struct uio *, int);
  254 struct tty *cytty(dev_t);
  255 int cyioctl(dev_t, u_long, caddr_t, int, struct proc *);
  256 int cystop(struct tty *, int flag);
  257 
  258 int
  259 cyopen(dev_t dev, int flag, int mode, struct proc *p)
  260 {
  261         int card = CY_CARD(dev);
  262         int port = CY_PORT(dev);
  263         struct cy_softc *sc;
  264         struct cy_port *cy;
  265         struct tty *tp;
  266         int s, error;
  267 
  268         if (card >= cy_cd.cd_ndevs ||
  269             (sc = cy_cd.cd_devs[card]) == NULL) {
  270                 return (ENXIO);
  271         }
  272 
  273 #ifdef CY_DEBUG
  274         printf("%s open port %d flag 0x%x mode 0x%x\n", sc->sc_dev.dv_xname,
  275             port, flag, mode);
  276 #endif
  277 
  278         cy = &sc->sc_ports[port];
  279 
  280         s = spltty();
  281         if (cy->cy_tty == NULL) {
  282                 cy->cy_tty = ttymalloc(0);
  283         }
  284         splx(s);
  285 
  286         tp = cy->cy_tty;
  287         tp->t_oproc = cystart;
  288         tp->t_param = cyparam;
  289         tp->t_dev = dev;
  290 
  291         if (!ISSET(tp->t_state, TS_ISOPEN)) {
  292                 SET(tp->t_state, TS_WOPEN);
  293                 ttychars(tp);
  294                 tp->t_iflag = TTYDEF_IFLAG;
  295                 tp->t_oflag = TTYDEF_OFLAG;
  296                 tp->t_cflag = TTYDEF_CFLAG;
  297                 if (ISSET(cy->cy_openflags, TIOCFLAG_CLOCAL))
  298                         SET(tp->t_cflag, CLOCAL);
  299                 if (ISSET(cy->cy_openflags, TIOCFLAG_CRTSCTS))
  300                         SET(tp->t_cflag, CRTSCTS);
  301                 if (ISSET(cy->cy_openflags, TIOCFLAG_MDMBUF))
  302                         SET(tp->t_cflag, MDMBUF);
  303                 tp->t_lflag = TTYDEF_LFLAG;
  304                 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
  305 
  306                 s = spltty();
  307 
  308                 /*
  309                  * Allocate input ring buffer if we don't already have one
  310                  */
  311                 if (cy->cy_ibuf == NULL) {
  312                         cy->cy_ibuf = malloc(IBUF_SIZE, M_DEVBUF, M_NOWAIT);
  313                         if (cy->cy_ibuf == NULL) {
  314                                 printf("%s: (port %d) can't allocate input buffer\n",
  315                                        sc->sc_dev.dv_xname, port);
  316                                 splx(s);
  317                                 return (ENOMEM);
  318                         }
  319                         cy->cy_ibuf_end = cy->cy_ibuf + IBUF_SIZE;
  320                 }
  321 
  322                 /* mark the ring buffer as empty */
  323                 cy->cy_ibuf_rd_ptr = cy->cy_ibuf_wr_ptr = cy->cy_ibuf;
  324 
  325                 /* select CD1400 channel */
  326                 cd_write_reg(cy, CD1400_CAR, port & CD1400_CAR_CHAN);
  327                 /* reset the channel */
  328                 cd1400_channel_cmd(cy, CD1400_CCR_CMDRESET);
  329                 /* encode unit (port) number in LIVR */
  330                 /* there is just enough space for 5 bits (32 ports) */
  331                 cd_write_reg(cy, CD1400_LIVR, port << 3);
  332 
  333                 cy->cy_channel_control = 0;
  334 
  335                 if (!timeout_pending(&sc->sc_poll_to))
  336                         timeout_add(&sc->sc_poll_to, 1);
  337 
  338                 /* this sets parameters and raises DTR */
  339                 cyparam(tp, &tp->t_termios);
  340 
  341                 ttsetwater(tp);
  342 
  343                 /* raise RTS too */
  344                 cy_modem_control(cy, TIOCM_RTS, DMBIS);
  345 
  346                 cy->cy_carrier_stat = cd_read_reg(cy, CD1400_MSVR2);
  347 
  348                 /* enable receiver and modem change interrupts */
  349                 cd_write_reg(cy, CD1400_SRER,
  350                     CD1400_SRER_MDMCH | CD1400_SRER_RXDATA);
  351 
  352                 if (CY_DIALOUT(dev) ||
  353                     ISSET(cy->cy_openflags, TIOCFLAG_SOFTCAR) ||
  354                     ISSET(tp->t_cflag, MDMBUF) ||
  355                     ISSET(cy->cy_carrier_stat, CD1400_MSVR2_CD))
  356                         SET(tp->t_state, TS_CARR_ON);
  357                 else
  358                         CLR(tp->t_state, TS_CARR_ON);
  359         } else if (ISSET(tp->t_state, TS_XCLUDE) && suser(p) != 0) {
  360                 return (EBUSY);
  361         } else {
  362                 s = spltty();
  363         }
  364 
  365         /* wait for carrier if necessary */
  366         if (!ISSET(flag, O_NONBLOCK)) {
  367                 while (!ISSET(tp->t_cflag, CLOCAL) &&
  368                     !ISSET(tp->t_state, TS_CARR_ON)) {
  369                         SET(tp->t_state, TS_WOPEN);
  370                         error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH,
  371                             ttopen);
  372                         if (error != 0) {
  373                                 splx(s);
  374                                 CLR(tp->t_state, TS_WOPEN);
  375                                 return (error);
  376                         }
  377                 }
  378         }
  379 
  380         splx(s);
  381 
  382         return (*linesw[tp->t_line].l_open)(dev, tp, p);
  383 }
  384 
  385 /*
  386  * close routine. returns zero if successful, else error code
  387  */
  388 int
  389 cyclose(dev_t dev, int flag, int mode, struct proc *p)
  390 {
  391         int card = CY_CARD(dev);
  392         int port = CY_PORT(dev);
  393         struct cy_softc *sc = cy_cd.cd_devs[card];
  394         struct cy_port *cy = &sc->sc_ports[port];
  395         struct tty *tp = cy->cy_tty;
  396         int s;
  397 
  398 #ifdef CY_DEBUG
  399         printf("%s close port %d, flag 0x%x, mode 0x%x\n", sc->sc_dev.dv_xname,
  400             port, flag, mode);
  401 #endif
  402 
  403         (*linesw[tp->t_line].l_close)(tp, flag, p);
  404         s = spltty();
  405 
  406         if (ISSET(tp->t_cflag, HUPCL) &&
  407             !ISSET(cy->cy_openflags, TIOCFLAG_SOFTCAR)) {
  408                 /* drop DTR and RTS
  409                    (should we wait for output buffer to become empty first?) */
  410                 cy_modem_control(cy, 0, DMSET);
  411         }
  412 
  413         /*
  414          * XXX should we disable modem change and
  415          * receive interrupts here or somewhere ?
  416          */
  417         CLR(tp->t_state, TS_BUSY | TS_FLUSH);
  418 
  419         splx(s);
  420         ttyclose(tp);
  421 
  422         return (0);
  423 }
  424 
  425 /*
  426  * Read routine
  427  */
  428 int
  429 cyread(dev_t dev, struct uio *uio, int flag)
  430 {
  431         int card = CY_CARD(dev);
  432         int port = CY_PORT(dev);
  433         struct cy_softc *sc = cy_cd.cd_devs[card];
  434         struct cy_port *cy = &sc->sc_ports[port];
  435         struct tty *tp = cy->cy_tty;
  436 
  437 #ifdef CY_DEBUG
  438         printf("%s read port %d uio %p flag 0x%x\n", sc->sc_dev.dv_xname,
  439             port, uio, flag);
  440 #endif
  441 
  442         return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
  443 }
  444 
  445 /*
  446  * Write routine
  447  */
  448 int
  449 cywrite(dev_t dev, struct uio *uio, int flag)
  450 {
  451         int card = CY_CARD(dev);
  452         int port = CY_PORT(dev);
  453         struct cy_softc *sc = cy_cd.cd_devs[card];
  454         struct cy_port *cy = &sc->sc_ports[port];
  455         struct tty *tp = cy->cy_tty;
  456 
  457 #ifdef CY_DEBUG
  458         printf("%s write port %d uio %p flag 0x%x\n", sc->sc_dev.dv_xname,
  459             port, uio, flag);
  460 #endif
  461 
  462         return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
  463 }
  464 
  465 /*
  466  * return tty pointer
  467  */
  468 struct tty *
  469 cytty(dev_t dev)
  470 {
  471         int card = CY_CARD(dev);
  472         int port = CY_PORT(dev);
  473         struct cy_softc *sc = cy_cd.cd_devs[card];
  474         struct cy_port *cy = &sc->sc_ports[port];
  475         struct tty *tp = cy->cy_tty;
  476 
  477         return (tp);
  478 }
  479 
  480 /*
  481  * ioctl routine
  482  */
  483 int
  484 cyioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
  485 {
  486         int card = CY_CARD(dev);
  487         int port = CY_PORT(dev);
  488         struct cy_softc *sc = cy_cd.cd_devs[card];
  489         struct cy_port *cy = &sc->sc_ports[port];
  490         struct tty *tp = cy->cy_tty;
  491         int error;
  492 
  493 #ifdef CY_DEBUG
  494         printf("%s port %d ioctl cmd 0x%lx data %p flag 0x%x\n",
  495             sc->sc_dev.dv_xname, port, cmd, data, flag);
  496 #endif
  497 
  498         error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
  499         if (error >= 0)
  500                 return (error);
  501 
  502         error = ttioctl(tp, cmd, data, flag, p);
  503         if (error >= 0)
  504                 return (error);
  505 
  506         /* XXX should not allow dropping DTR when dialin? */
  507 
  508         switch (cmd) {
  509         case TIOCSBRK:          /* start break */
  510                 SET(cy->cy_flags, CYF_START_BREAK);
  511                 cy_enable_transmitter(cy);
  512                 break;
  513 
  514         case TIOCCBRK:          /* stop break */
  515                 SET(cy->cy_flags, CYF_END_BREAK);
  516                 cy_enable_transmitter(cy);
  517                 break;
  518 
  519         case TIOCSDTR:          /* DTR on */
  520                 cy_modem_control(cy, TIOCM_DTR, DMBIS);
  521                 break;
  522 
  523         case TIOCCDTR:          /* DTR off */
  524                 cy_modem_control(cy, TIOCM_DTR, DMBIC);
  525                 break;
  526 
  527         case TIOCMSET:          /* set new modem control line values */
  528                 cy_modem_control(cy, *((int *)data), DMSET);
  529                 break;
  530 
  531         case TIOCMBIS:          /* turn modem control bits on */
  532                 cy_modem_control(cy, *((int *)data), DMBIS);
  533                 break;
  534 
  535         case TIOCMBIC:          /* turn modem control bits off */
  536                 cy_modem_control(cy, *((int *)data), DMBIC);
  537                 break;
  538 
  539         case TIOCMGET:          /* get modem control/status line state */
  540                 *((int *)data) = cy_modem_control(cy, 0, DMGET);
  541                 break;
  542 
  543         case TIOCGFLAGS:
  544                 *((int *)data) = cy->cy_openflags |
  545                     (CY_DIALOUT(dev) ? TIOCFLAG_SOFTCAR : 0);
  546                 break;
  547 
  548         case TIOCSFLAGS:
  549                 error = suser(p);
  550                 if (error != 0)
  551                         return (EPERM);
  552 
  553                 cy->cy_openflags = *((int *)data) &
  554                     (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL |
  555                      TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF);
  556                 break;
  557 
  558         default:
  559                 return (ENOTTY);
  560         }
  561 
  562         return (0);
  563 }
  564 
  565 /*
  566  * start output
  567  */
  568 void
  569 cystart(struct tty *tp)
  570 {
  571         int card = CY_CARD(tp->t_dev);
  572         int port = CY_PORT(tp->t_dev);
  573         struct cy_softc *sc = cy_cd.cd_devs[card];
  574         struct cy_port *cy = &sc->sc_ports[port];
  575         int s;
  576 
  577 #ifdef CY_DEBUG
  578         printf("%s port %d start, tty %p\n", sc->sc_dev.dv_xname, port, tp);
  579 #endif
  580 
  581         s = spltty();
  582 
  583 #ifdef CY_DEBUG1
  584         cy->cy_start_count++;
  585 #endif
  586 
  587         if (!ISSET(tp->t_state, TS_TTSTOP | TS_TIMEOUT | TS_BUSY)) {
  588                 ttwakeupwr(tp);
  589                 if (tp->t_outq.c_cc == 0)
  590                         goto out;
  591 
  592                 SET(tp->t_state, TS_BUSY);
  593                 cy_enable_transmitter(cy);
  594         }
  595 out:
  596 
  597         splx(s);
  598 }
  599 
  600 /*
  601  * stop output
  602  */
  603 int
  604 cystop(struct tty *tp, int flag)
  605 {
  606         int card = CY_CARD(tp->t_dev);
  607         int port = CY_PORT(tp->t_dev);
  608         struct cy_softc *sc = cy_cd.cd_devs[card];
  609         struct cy_port *cy = &sc->sc_ports[port];
  610         int s;
  611 
  612 #ifdef CY_DEBUG
  613         printf("%s port %d stop tty %p flag 0x%x\n", sc->sc_dev.dv_xname,
  614             port, tp, flag);
  615 #endif
  616 
  617         s = spltty();
  618 
  619         if (ISSET(tp->t_state, TS_BUSY)) {
  620                 if (!ISSET(tp->t_state, TS_TTSTOP))
  621                         SET(tp->t_state, TS_FLUSH);
  622 
  623                 /*
  624                  * the transmit interrupt routine will disable transmit when it
  625                  * notices that CYF_STOP has been set.
  626                  */
  627                 SET(cy->cy_flags, CYF_STOP);
  628         }
  629         splx(s);
  630         return (0);
  631 }
  632 
  633 /*
  634  * parameter setting routine.
  635  * returns 0 if successful, else returns error code
  636  */
  637 int
  638 cyparam(struct tty *tp, struct termios *t)
  639 {
  640         int card = CY_CARD(tp->t_dev);
  641         int port = CY_PORT(tp->t_dev);
  642         struct cy_softc *sc = cy_cd.cd_devs[card];
  643         struct cy_port *cy = &sc->sc_ports[port];
  644         int ibpr, obpr, i_clk_opt, o_clk_opt;
  645         int s, opt;
  646 
  647 #ifdef CY_DEBUG
  648         printf("%s port %d param tty %p termios %p\n", sc->sc_dev.dv_xname,
  649             port, tp, t);
  650         printf("ispeed %d ospeed %d\n", t->c_ispeed, t->c_ospeed);
  651 #endif
  652 
  653         if (t->c_ospeed != 0 &&
  654             cy_speed(t->c_ospeed, &o_clk_opt, &obpr, cy->cy_clock) < 0)
  655                 return (EINVAL);
  656 
  657         if (t->c_ispeed != 0 &&
  658             cy_speed(t->c_ispeed, &i_clk_opt, &ibpr, cy->cy_clock) < 0)
  659                 return (EINVAL);
  660 
  661         s = spltty();
  662 
  663         /* hang up the line is ospeed is zero, else turn DTR on */
  664         cy_modem_control(cy, TIOCM_DTR, (t->c_ospeed == 0 ? DMBIC : DMBIS));
  665 
  666         /* channel was selected by the above call to cy_modem_control() */
  667         /* cd_write_reg(cy, CD1400_CAR, port & CD1400_CAR_CHAN); */
  668 
  669         /* set transmit speed */
  670         if (t->c_ospeed != 0) {
  671                 cd_write_reg(cy, CD1400_TCOR, o_clk_opt);
  672                 cd_write_reg(cy, CD1400_TBPR, obpr);
  673         }
  674         /* set receive speed */
  675         if (t->c_ispeed != 0) {
  676                 cd_write_reg(cy, CD1400_RCOR, i_clk_opt);
  677                 cd_write_reg(cy, CD1400_RBPR, ibpr);
  678         }
  679 
  680         opt = CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN
  681             | (ISSET(t->c_cflag, CREAD) ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS);
  682 
  683         if (opt != cy->cy_channel_control) {
  684                 cy->cy_channel_control = opt;
  685                 cd1400_channel_cmd(cy, opt);
  686         }
  687 
  688         /* compute COR1 contents */
  689         opt = 0;
  690         if (ISSET(t->c_cflag, PARENB)) {
  691                 if (ISSET(t->c_cflag, PARODD))
  692                         opt |= CD1400_COR1_PARODD;
  693                 opt |= CD1400_COR1_PARNORMAL;
  694         }
  695 
  696         if (!ISSET(t->c_iflag, INPCK))
  697                 opt |= CD1400_COR1_NOINPCK;     /* no parity checking */
  698 
  699         if (ISSET(t->c_cflag, CSTOPB))
  700                 opt |= CD1400_COR1_STOP2;
  701 
  702         switch (t->c_cflag & CSIZE) {
  703         case CS5:
  704                 opt |= CD1400_COR1_CS5;
  705                 break;
  706 
  707         case CS6:
  708                 opt |= CD1400_COR1_CS6;
  709                 break;
  710 
  711         case CS7:
  712                 opt |= CD1400_COR1_CS7;
  713                 break;
  714 
  715         default:
  716                 opt |= CD1400_COR1_CS8;
  717                 break;
  718         }
  719 
  720         cd_write_reg(cy, CD1400_COR1, opt);
  721 
  722 #ifdef CY_DEBUG
  723         printf("cor1 = 0x%x...", opt);
  724 #endif
  725 
  726         /*
  727          * use the CD1400 automatic CTS flow control if CRTSCTS is set
  728          *
  729          * CD1400_COR2_ETC is used because breaks are generated with
  730          * embedded transmit commands
  731          */
  732         cd_write_reg(cy, CD1400_COR2,
  733             CD1400_COR2_ETC |
  734             (ISSET(t->c_cflag, CRTSCTS) ? CD1400_COR2_CCTS_OFLOW : 0));
  735 
  736         cd_write_reg(cy, CD1400_COR3, RX_FIFO_THRESHOLD);
  737 
  738         cd1400_channel_cmd(cy,
  739             CD1400_CCR_CMDCORCHG |
  740             CD1400_CCR_COR1 | CD1400_CCR_COR2 | CD1400_CCR_COR3);
  741 
  742         cd_write_reg(cy, CD1400_COR4, CD1400_COR4_PFO_EXCEPTION);
  743         cd_write_reg(cy, CD1400_COR5, 0);
  744 
  745         /*
  746          * set modem change option registers to generate interrupts
  747          * on carrier detect changes.
  748          *
  749          * if hardware RTS handshaking is used (CY_HW_RTS, DTR and RTS lines
  750          * exchanged), also set the handshaking threshold.
  751          */
  752 #ifdef CY_HW_RTS
  753         cd_write_reg(cy, CD1400_MCOR1, CD1400_MCOR1_CDzd |
  754             (ISSET(t->c_cflag, CRTSCTS) ? RX_DTR_THRESHOLD : 0));
  755 #else
  756         cd_write_reg(cy, CD1400_MCOR1, CD1400_MCOR1_CDzd);
  757 #endif /* CY_HW_RTS */
  758 
  759         cd_write_reg(cy, CD1400_MCOR2, CD1400_MCOR2_CDod);
  760 
  761         /*
  762          * set receive timeout to approx. 2ms
  763          * could use more complex logic here...
  764          * (but is it actually needed or even useful?)
  765          */
  766         cd_write_reg(cy, CD1400_RTPR, 2);
  767 
  768         /*
  769          * should do anything else here?
  770          * XXX check MDMBUF handshaking like in com.c?
  771          */
  772 
  773         splx(s);
  774         return (0);
  775 }
  776 
  777 /*
  778  * set/get modem line status
  779  *
  780  * bits can be: TIOCM_DTR, TIOCM_RTS, TIOCM_CTS, TIOCM_CD, TIOCM_RI, TIOCM_DSR
  781  *
  782  * RTS and DTR are exchanged if CY_HW_RTS is set
  783  *
  784  */
  785 int
  786 cy_modem_control(struct cy_port *cy, int bits, int howto)
  787 {
  788         int s, msvr;
  789 
  790         s = spltty();
  791 
  792         /* select channel */
  793         cd_write_reg(cy, CD1400_CAR, cy->cy_port_num & CD1400_CAR_CHAN);
  794 
  795 /* does not manipulate RTS if it is used for flow control */
  796         switch (howto) {
  797         case DMGET:
  798                 bits = 0;
  799                 if (cy->cy_channel_control & CD1400_CCR_RCVEN)
  800                         bits |= TIOCM_LE;
  801                 msvr = cd_read_reg(cy, CD1400_MSVR2);
  802 #ifdef CY_HW_RTS
  803                 if (cd_read_reg(cy, CD1400_MSVR1) & CD1400_MSVR1_RTS)
  804                         bits |= TIOCM_DTR;
  805                 if (msvr & CD1400_MSVR2_DTR)
  806                         bits |= TIOCM_RTS;
  807 #else
  808                 if (cd_read_reg(cy, CD1400_MSVR1) & CD1400_MSVR1_RTS)
  809                         bits |= TIOCM_RTS;
  810                 if (msvr & CD1400_MSVR2_DTR)
  811                         bits |= TIOCM_DTR;
  812 #endif /* CY_HW_RTS */
  813                 if (msvr & CD1400_MSVR2_CTS)
  814                         bits |= TIOCM_CTS;
  815                 if (msvr & CD1400_MSVR2_CD)
  816                         bits |= TIOCM_CD;
  817                 if (msvr & CD1400_MSVR2_DSR)    /* not connected on some
  818                                                    Cyclom cards? */
  819                         bits |= TIOCM_DSR;
  820                 if (msvr & CD1400_MSVR2_RI)     /* not connected on
  821                                                    Cyclom-8Y cards? */
  822                         bits |= TIOCM_RI;
  823                 splx(s);
  824                 return (bits);
  825 
  826         case DMSET: /* replace old values with new ones */
  827 #ifdef CY_HW_RTS
  828                 if (!ISSET(cy->cy_tty->t_cflag, CRTSCTS))
  829                         cd_write_reg(cy, CD1400_MSVR2,
  830                             ((bits & TIOCM_RTS) ? CD1400_MSVR2_DTR : 0));
  831                 cd_write_reg(cy, CD1400_MSVR1,
  832                     ((bits & TIOCM_DTR) ? CD1400_MSVR1_RTS : 0));
  833 #else
  834                 if (!ISSET(cy->cy_tty->t_cflag, CRTSCTS))
  835                         cd_write_reg(cy, CD1400_MSVR1,
  836                             ((bits & TIOCM_RTS) ? CD1400_MSVR1_RTS : 0));
  837                 cd_write_reg(cy, CD1400_MSVR2,
  838                     ((bits & TIOCM_DTR) ? CD1400_MSVR2_DTR : 0));
  839 #endif /* CY_HW_RTS */
  840                 break;
  841 
  842         case DMBIS: /* set bits */
  843 #ifdef CY_HW_RTS
  844                 if (!ISSET(cy->cy_tty->t_cflag, CRTSCTS) &&
  845                     (bits & TIOCM_RTS) != 0)
  846                         cd_write_reg(cy, CD1400_MSVR2, CD1400_MSVR2_DTR);
  847                 if (bits & TIOCM_DTR)
  848                         cd_write_reg(cy, CD1400_MSVR1, CD1400_MSVR1_RTS);
  849 #else
  850                 if (!ISSET(cy->cy_tty->t_cflag, CRTSCTS) &&
  851                     (bits & TIOCM_RTS) != 0)
  852                         cd_write_reg(cy, CD1400_MSVR1, CD1400_MSVR1_RTS);
  853                 if (bits & TIOCM_DTR)
  854                         cd_write_reg(cy, CD1400_MSVR2, CD1400_MSVR2_DTR);
  855 #endif /* CY_HW_RTS */
  856                 break;
  857 
  858         case DMBIC: /* clear bits */
  859 #ifdef CY_HW_RTS
  860                 if (!ISSET(cy->cy_tty->t_cflag, CRTSCTS) &&
  861                     (bits & TIOCM_RTS))
  862                         cd_write_reg(cy, CD1400_MSVR2, 0);
  863                 if (bits & TIOCM_DTR)
  864                         cd_write_reg(cy, CD1400_MSVR1, 0);
  865 #else
  866                 if (!ISSET(cy->cy_tty->t_cflag, CRTSCTS) &&
  867                     (bits & TIOCM_RTS))
  868                         cd_write_reg(cy, CD1400_MSVR1, 0);
  869                 if (bits & TIOCM_DTR)
  870                         cd_write_reg(cy, CD1400_MSVR2, 0);
  871 #endif /* CY_HW_RTS */
  872                 break;
  873         }
  874         splx(s);
  875         return (0);
  876 }
  877 
  878 /*
  879  * Upper-level handler loop (called from timer interrupt?)
  880  * This routine is common for multiple cards
  881  */
  882 void
  883 cy_poll(void *arg)
  884 {
  885         int port;
  886         struct cy_softc *sc = arg;
  887         struct cy_port *cy;
  888         struct tty *tp;
  889         static int counter = 0;
  890 #ifdef CY_DEBUG1
  891         int did_something;
  892 #endif
  893 
  894         int s;
  895 
  896         s = spltty();
  897 
  898         if (sc->sc_events == 0 && ++counter < 200) {
  899                 splx(s);
  900                 goto out;
  901         }
  902 
  903         sc->sc_events = 0;
  904         splx(s);
  905 
  906 #ifdef CY_DEBUG1
  907         sc->sc_poll_count1++;
  908         did_something = 0;
  909 #endif
  910 
  911         for (port = 0; port < sc->sc_nports; port++) {
  912                 cy = &sc->sc_ports[port];
  913                 if ((tp = cy->cy_tty) == NULL || cy->cy_ibuf == NULL ||
  914                     !ISSET(tp->t_state, TS_ISOPEN | TS_WOPEN))
  915                         continue;
  916 
  917                 /*
  918                  * handle received data
  919                  */
  920                 while (cy->cy_ibuf_rd_ptr != cy->cy_ibuf_wr_ptr) {
  921                         u_char line_stat;
  922                         int chr;
  923 
  924                         line_stat = cy->cy_ibuf_rd_ptr[0];
  925                         chr = cy->cy_ibuf_rd_ptr[1];
  926 
  927                         if (line_stat &
  928                             (CD1400_RDSR_BREAK|CD1400_RDSR_FE))
  929                                 chr |= TTY_FE;
  930                         if (line_stat & CD1400_RDSR_PE)
  931                                 chr |= TTY_PE;
  932 
  933                         /*
  934                          * on an overrun error the data is treated as
  935                          * good just as it should be.
  936                          */
  937 
  938 #ifdef CY_DEBUG
  939                         printf("%s port %d ttyinput 0x%x\n",
  940                             sc->sc_dev.dv_xname, port, chr);
  941 #endif
  942 
  943                         (*linesw[tp->t_line].l_rint)(chr, tp);
  944 
  945                         s = spltty(); /* really necessary? */
  946                         if ((cy->cy_ibuf_rd_ptr += 2) ==
  947                             cy->cy_ibuf_end)
  948                                 cy->cy_ibuf_rd_ptr = cy->cy_ibuf;
  949                         splx(s);
  950 
  951 #ifdef CY_DEBUG1
  952                         did_something = 1;
  953 #endif
  954                 }
  955 
  956 #ifndef CY_HW_RTS
  957                 /*
  958                  * If we don't have any received data in ibuf and
  959                  * CRTSCTS is on and RTS is turned off, it is time
  960                  * to turn RTS back on
  961                  */
  962                 if (ISSET(tp->t_cflag, CRTSCTS)) {
  963                         /* we can't use cy_modem_control() here as it
  964                             doesn't change RTS if RTSCTS is on */
  965                         cd_write_reg(cy, CD1400_CAR,
  966                             port & CD1400_CAR_CHAN);
  967               
  968                         if ((cd_read_reg(cy,
  969                             CD1400_MSVR1) & CD1400_MSVR1_RTS) == 0) {
  970                                 cd_write_reg(cy, CD1400_MSVR1,
  971                                     CD1400_MSVR1_RTS);
  972 #ifdef CY_DEBUG1
  973                                 did_something = 1;
  974 #endif
  975                         }
  976                 }
  977 #endif /* CY_HW_RTS */
  978 
  979                 /*
  980                  * handle carrier changes
  981                  */
  982                 s = spltty();
  983                 if (ISSET(cy->cy_flags, CYF_CARRIER_CHANGED)) {
  984                         int carrier;
  985 
  986                         CLR(cy->cy_flags, CYF_CARRIER_CHANGED);
  987                         splx(s);
  988 
  989                         carrier = ((cy->cy_carrier_stat &
  990                             CD1400_MSVR2_CD) != 0);
  991 
  992 #ifdef CY_DEBUG
  993                         printf("%s: cy_poll: carrier change "
  994                             "(port %d, carrier %d)\n",
  995                             sc->sc_dev.dv_xname, port, carrier);
  996 #endif
  997                         if (CY_DIALIN(tp->t_dev) &&
  998                             !(*linesw[tp->t_line].l_modem)(tp, carrier))
  999                                 cy_modem_control(cy, TIOCM_DTR, DMBIC);
 1000 
 1001 #ifdef CY_DEBUG1
 1002                         did_something = 1;
 1003 #endif
 1004                 } else {
 1005                         splx(s);
 1006                 }
 1007 
 1008                 s = spltty();
 1009                 if (ISSET(cy->cy_flags, CYF_START)) {
 1010                         CLR(cy->cy_flags, CYF_START);
 1011                         splx(s);
 1012 
 1013                         (*linesw[tp->t_line].l_start)(tp);
 1014 
 1015 #ifdef CY_DEBUG1
 1016                         did_something = 1;
 1017 #endif
 1018                 } else {
 1019                         splx(s);
 1020                 }
 1021 
 1022                 /* could move this to even upper level... */
 1023                 if (cy->cy_fifo_overruns) {
 1024                         cy->cy_fifo_overruns = 0;
 1025                         /* doesn't report overrun count,
 1026                            but shouldn't really matter */
 1027                         log(LOG_WARNING, "%s: port %d fifo overrun\n",
 1028                             sc->sc_dev.dv_xname, port);
 1029                 }
 1030                 if (cy->cy_ibuf_overruns) {
 1031                         cy->cy_ibuf_overruns = 0;
 1032                         log(LOG_WARNING, "%s: port %d ibuf overrun\n",
 1033                             sc->sc_dev.dv_xname, port);
 1034                 }
 1035         } /* for(port...) */
 1036 #ifdef CY_DEBUG1
 1037         if (did_something && counter >= 200)
 1038                 sc->sc_poll_count2++;
 1039 #endif
 1040 
 1041         counter = 0;
 1042 
 1043 out:
 1044         timeout_add(&sc->sc_poll_to, 1);
 1045 }
 1046 
 1047 /*
 1048  * hardware interrupt routine
 1049  */
 1050 int
 1051 cy_intr(void *arg)
 1052 {
 1053         struct cy_softc *sc = arg;
 1054         struct cy_port *cy;
 1055         int cy_chip, stat;
 1056         int int_serviced = -1;
 1057 
 1058         /*
 1059          * Check interrupt status of each CD1400 chip on this card
 1060          * (multiple cards cannot share the same interrupt)
 1061          */
 1062         for (cy_chip = 0; cy_chip < sc->sc_nr_cd1400s; cy_chip++) {
 1063 
 1064                 stat = cd_read_reg_sc(sc, cy_chip, CD1400_SVRR);
 1065                 if (stat == 0)
 1066                         continue;
 1067 
 1068                 if (ISSET(stat, CD1400_SVRR_RXRDY)) {
 1069                         u_char save_car, save_rir, serv_type;
 1070                         u_char line_stat, recv_data, n_chars;
 1071                         u_char *buf_p;
 1072 
 1073                         save_rir = cd_read_reg_sc(sc, cy_chip, CD1400_RIR);
 1074                         save_car = cd_read_reg_sc(sc, cy_chip, CD1400_CAR);
 1075                         /* enter rx service */
 1076                         cd_write_reg_sc(sc, cy_chip, CD1400_CAR, save_rir);
 1077 
 1078                         serv_type = cd_read_reg_sc(sc, cy_chip, CD1400_RIVR);
 1079                         cy = &sc->sc_ports[serv_type >> 3];
 1080 
 1081 #ifdef CY_DEBUG1
 1082                         cy->cy_rx_int_count++;
 1083 #endif
 1084 
 1085                         buf_p = cy->cy_ibuf_wr_ptr;
 1086 
 1087                         if (ISSET(serv_type, CD1400_RIVR_EXCEPTION)) {
 1088                                 line_stat = cd_read_reg(cy, CD1400_RDSR);
 1089                                 recv_data = cd_read_reg(cy, CD1400_RDSR);
 1090 
 1091                                 if (cy->cy_tty == NULL ||
 1092                                     !ISSET(cy->cy_tty->t_state, TS_ISOPEN))
 1093                                         goto end_rx_serv;
 1094 
 1095 #ifdef CY_DEBUG
 1096                                 printf("%s port %d recv exception, "
 1097                                     "line_stat 0x%x, char 0x%x\n",
 1098                                     sc->sc_dev.dv_xname, cy->cy_port_num,
 1099                                     line_stat, recv_data);
 1100 #endif
 1101                                 if (ISSET(line_stat, CD1400_RDSR_OE))
 1102                                         cy->cy_fifo_overruns++;
 1103 
 1104                                 *buf_p++ = line_stat;
 1105                                 *buf_p++ = recv_data;
 1106                                 if (buf_p == cy->cy_ibuf_end)
 1107                                         buf_p = cy->cy_ibuf;
 1108 
 1109                                 if (buf_p == cy->cy_ibuf_rd_ptr) {
 1110                                         if (buf_p == cy->cy_ibuf)
 1111                                                 buf_p = cy->cy_ibuf_end;
 1112                                         buf_p -= 2;
 1113                                         cy->cy_ibuf_overruns++;
 1114                                 }
 1115                                 sc->sc_events = 1;
 1116                         } else { /* no exception, received data OK */
 1117                                 n_chars = cd_read_reg(cy, CD1400_RDCR);
 1118 
 1119                                 /* If no tty or not open, discard data */
 1120                                 if (cy->cy_tty == NULL ||
 1121                                     !ISSET(cy->cy_tty->t_state, TS_ISOPEN)) {
 1122                                         while (n_chars--)
 1123                                                 cd_read_reg(cy, CD1400_RDSR);
 1124                                         goto end_rx_serv;
 1125                                 }
 1126 
 1127 #ifdef CY_DEBUG
 1128                                 printf("%s port %d receive ok %d chars\n",
 1129                                     sc->sc_dev.dv_xname, cy->cy_port_num,
 1130                                     n_chars);
 1131 #endif
 1132                                 while (n_chars--) {
 1133                                         *buf_p++ = 0; /* status: OK */
 1134                                         *buf_p++ = cd_read_reg(cy,
 1135                                             CD1400_RDSR); /* data byte */
 1136                                         if (buf_p == cy->cy_ibuf_end)
 1137                                                 buf_p = cy->cy_ibuf;
 1138                                         if (buf_p == cy->cy_ibuf_rd_ptr) {
 1139                                                 if (buf_p == cy->cy_ibuf)
 1140                                                         buf_p = cy->cy_ibuf_end;
 1141                                                 buf_p -= 2;
 1142                                                 cy->cy_ibuf_overruns++;
 1143                                                 break;
 1144                                         }
 1145                                 }
 1146                                 sc->sc_events = 1;
 1147                         }
 1148 
 1149                         cy->cy_ibuf_wr_ptr = buf_p;
 1150 
 1151 #ifndef CY_HW_RTS
 1152                         /* RTS handshaking for incoming data */
 1153                         if (ISSET(cy->cy_tty->t_cflag, CRTSCTS)) {
 1154                                 int bf;
 1155 
 1156                                 bf = buf_p - cy->cy_ibuf_rd_ptr;
 1157                                 if (bf < 0)
 1158                                         bf += IBUF_SIZE;
 1159 
 1160                                 if (bf > (IBUF_SIZE/2)) /* turn RTS off */
 1161                                         cd_write_reg(cy, CD1400_MSVR1, 0);
 1162                         }
 1163 #endif /* CY_HW_RTS */
 1164 
 1165                 end_rx_serv:
 1166                         /* terminate service context */
 1167                         cd_write_reg(cy, CD1400_RIR, save_rir & 0x3f);
 1168                         cd_write_reg(cy, CD1400_CAR, save_car);
 1169                         int_serviced = 1;
 1170                 } /* if(rx_service...) */
 1171 
 1172                 if (ISSET(stat, CD1400_SVRR_MDMCH)) {
 1173                         u_char save_car, save_mir, serv_type, modem_stat;
 1174 
 1175                         save_mir = cd_read_reg_sc(sc, cy_chip, CD1400_MIR);
 1176                         save_car = cd_read_reg_sc(sc, cy_chip, CD1400_CAR);
 1177                         /* enter modem service */
 1178                         cd_write_reg_sc(sc, cy_chip, CD1400_CAR, save_mir);
 1179 
 1180                         serv_type = cd_read_reg_sc(sc, cy_chip, CD1400_MIVR);
 1181                         cy = &sc->sc_ports[serv_type >> 3];
 1182 
 1183 #ifdef CY_DEBUG1
 1184                         cy->cy_modem_int_count++;
 1185 #endif
 1186 
 1187                         modem_stat = cd_read_reg(cy, CD1400_MSVR2);
 1188 
 1189 #ifdef CY_DEBUG
 1190                         printf("%s port %d modem line change, new stat 0x%x\n",
 1191                             sc->sc_dev.dv_xname, cy->cy_port_num, modem_stat);
 1192 #endif
 1193                         if (ISSET((cy->cy_carrier_stat ^ modem_stat),
 1194                             CD1400_MSVR2_CD)) {
 1195                                 SET(cy->cy_flags, CYF_CARRIER_CHANGED);
 1196                                 sc->sc_events = 1;
 1197                         }
 1198 
 1199                         cy->cy_carrier_stat = modem_stat;
 1200 
 1201                         /* terminate service context */
 1202                         cd_write_reg(cy, CD1400_MIR, save_mir & 0x3f);
 1203                         cd_write_reg(cy, CD1400_CAR, save_car);
 1204                         int_serviced = 1;
 1205                 } /* if(modem_service...) */
 1206 
 1207                 if (ISSET(stat, CD1400_SVRR_TXRDY)) {
 1208                         u_char save_car, save_tir, serv_type, count, ch;
 1209                         struct tty *tp;
 1210 
 1211                         save_tir = cd_read_reg_sc(sc, cy_chip, CD1400_TIR);
 1212                         save_car = cd_read_reg_sc(sc, cy_chip, CD1400_CAR);
 1213                         /* enter tx service */
 1214                         cd_write_reg_sc(sc, cy_chip, CD1400_CAR, save_tir);
 1215 
 1216                         serv_type = cd_read_reg_sc(sc, cy_chip, CD1400_TIVR);
 1217                         cy = &sc->sc_ports[serv_type >> 3];
 1218 
 1219 #ifdef CY_DEBUG1
 1220                         cy->cy_tx_int_count++;
 1221 #endif
 1222 #ifdef CY_DEBUG
 1223                         printf("%s port %d tx service\n", sc->sc_dev.dv_xname,
 1224                             cy->cy_port_num);
 1225 #endif
 1226 
 1227                         /* stop transmitting if no tty or CYF_STOP set */
 1228                         tp = cy->cy_tty;
 1229                         if (tp == NULL || ISSET(cy->cy_flags, CYF_STOP))
 1230                                 goto txdone;
 1231 
 1232                         count = 0;
 1233                         if (ISSET(cy->cy_flags, CYF_SEND_NUL)) {
 1234                                 cd_write_reg(cy, CD1400_TDR, 0);
 1235                                 cd_write_reg(cy, CD1400_TDR, 0);
 1236                                 count += 2;
 1237                                 CLR(cy->cy_flags, CYF_SEND_NUL);
 1238                         }
 1239 
 1240                         if (tp->t_outq.c_cc > 0) {
 1241                                 SET(tp->t_state, TS_BUSY);
 1242                                 while (tp->t_outq.c_cc > 0 &&
 1243                                     count < CD1400_TX_FIFO_SIZE) {
 1244                                         ch = getc(&tp->t_outq);
 1245                                         /* remember to double NUL characters
 1246                                            because embedded transmit commands
 1247                                            are enabled */
 1248                                         if (ch == 0) {
 1249                                                 if (count >=
 1250                                                     CD1400_TX_FIFO_SIZE-2) {
 1251                                                         SET(cy->cy_flags,
 1252                                                             CYF_SEND_NUL);
 1253                                                         break;
 1254                                                 }
 1255 
 1256                                                 cd_write_reg(cy, CD1400_TDR, ch);
 1257                                                 count++;
 1258                                         }
 1259 
 1260                                         cd_write_reg(cy, CD1400_TDR, ch);
 1261                                         count++;
 1262                                 }
 1263                         } else {
 1264                                 /* no data to send -- check if we should
 1265                                    start/stop a break */
 1266                                 /* XXX does this cause too much delay before
 1267                                    breaks? */
 1268                                 if (ISSET(cy->cy_flags, CYF_START_BREAK)) {
 1269                                         cd_write_reg(cy, CD1400_TDR, 0);
 1270                                         cd_write_reg(cy, CD1400_TDR, 0x81);
 1271                                         CLR(cy->cy_flags, CYF_START_BREAK);
 1272                                 }
 1273                                 if (ISSET(cy->cy_flags, CYF_END_BREAK)) {
 1274                                         cd_write_reg(cy, CD1400_TDR, 0);
 1275                                         cd_write_reg(cy, CD1400_TDR, 0x83);
 1276                                         CLR(cy->cy_flags, CYF_END_BREAK);
 1277                                 }
 1278                         }
 1279 
 1280                         if (tp->t_outq.c_cc == 0) {
 1281 txdone:
 1282                                 /*
 1283                                  * No data to send or requested to stop.
 1284                                  * Disable transmit interrupt
 1285                                  */
 1286                                 cd_write_reg(cy, CD1400_SRER,
 1287                                     cd_read_reg(cy, CD1400_SRER)
 1288                                     & ~CD1400_SRER_TXRDY);
 1289                                 CLR(cy->cy_flags, CYF_STOP);
 1290                                 CLR(tp->t_state, TS_BUSY);
 1291                         }
 1292 
 1293                         if (tp->t_outq.c_cc <= tp->t_lowat) {
 1294                                 SET(cy->cy_flags, CYF_START);
 1295                                 sc->sc_events = 1;
 1296                         }
 1297 
 1298                         /* terminate service context */
 1299                         cd_write_reg(cy, CD1400_TIR, save_tir & 0x3f);
 1300                         cd_write_reg(cy, CD1400_CAR, save_car);
 1301                         int_serviced = 1;
 1302                 } /* if(tx_service...) */
 1303         } /* for(...all CD1400s on a card) */
 1304 
 1305         /* ensure an edge for next interrupt */
 1306         bus_space_write_1(sc->sc_memt, sc->sc_memh,
 1307             CY_CLEAR_INTR<<sc->sc_bustype, 0);
 1308         return (int_serviced);
 1309 }
 1310 
 1311 /*
 1312  * subroutine to enable CD1400 transmitter
 1313  */
 1314 void
 1315 cy_enable_transmitter(struct cy_port *cy)
 1316 {
 1317         int s;
 1318         s = spltty();
 1319         cd_write_reg(cy, CD1400_CAR, cy->cy_port_num & CD1400_CAR_CHAN);
 1320         cd_write_reg(cy, CD1400_SRER, cd_read_reg(cy, CD1400_SRER)
 1321             | CD1400_SRER_TXRDY);
 1322         splx(s);
 1323 }
 1324 
 1325 /*
 1326  * Execute a CD1400 channel command
 1327  */
 1328 void
 1329 cd1400_channel_cmd(struct cy_port *cy, int cmd)
 1330 {
 1331         u_int waitcnt = 5 * 8 * 1024; /* approx 5 ms */
 1332 
 1333 #ifdef CY_DEBUG
 1334         printf("c1400_channel_cmd cy %p command 0x%x\n", cy, cmd);
 1335 #endif
 1336 
 1337         /* wait until cd1400 is ready to process a new command */
 1338         while (cd_read_reg(cy, CD1400_CCR) != 0 && waitcnt-- > 0)
 1339                 ;
 1340 
 1341         if (waitcnt == 0)
 1342                 log(LOG_ERR, "cy: channel command timeout\n");
 1343 
 1344         cd_write_reg(cy, CD1400_CCR, cmd);
 1345 }
 1346 
 1347 /*
 1348  * Compute clock option register and baud rate register values
 1349  * for a given speed. Return 0 on success, -1 on failure.
 1350  *
 1351  * The error between requested and actual speed seems
 1352  * to be well within allowed limits (less than 3%)
 1353  * with every speed value between 50 and 150000 bps.
 1354  */
 1355 int
 1356 cy_speed(speed_t speed, int *cor, int *bpr, int cy_clock)
 1357 {
 1358         int c, co, br;
 1359 
 1360         if (speed < 50 || speed > 150000)
 1361                 return (-1);
 1362 
 1363         for (c = 0, co = 8; co <= 2048; co <<= 2, c++) {
 1364                 br = (cy_clock + (co * speed) / 2) / (co * speed);
 1365                 if (br < 0x100) {
 1366                         *bpr = br;
 1367                         *cor = c;
 1368                         return (0);
 1369                 }
 1370         }
 1371 
 1372         return (-1);
 1373 }

Cache object: e671f3ccc774dee8d526cc34fcada89e


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