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

Cache object: ffcbd3eba036779b1cfb924c06492f38


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