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

Cache object: f4ca8163f76931ecafa828ed2710bf71


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