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.63 2022/10/26 23:42:04 riastradh 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.63 2022/10/26 23:42:04 riastradh 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/select.h>
   29 #include <sys/device.h>
   30 #include <sys/malloc.h>
   31 #include <sys/systm.h>
   32 #include <sys/callout.h>
   33 #include <sys/kauth.h>
   34 
   35 #include <sys/bus.h>
   36 
   37 #include <dev/ic/cd1400reg.h>
   38 #include <dev/ic/cyreg.h>
   39 #include <dev/ic/cyvar.h>
   40 
   41 #include "ioconf.h"
   42 
   43 static int      cyparam(struct tty *, struct termios *);
   44 static void     cystart(struct tty *);
   45 static void     cy_poll(void *);
   46 static int      cy_modem_control(struct cy_softc *, struct cy_port *, int, int);
   47 static void     cy_enable_transmitter(struct cy_softc *, struct cy_port *);
   48 static void     cd1400_channel_cmd(struct cy_softc *, struct cy_port *, int);
   49 static int      cy_speed(speed_t, int *, int *, int);
   50 
   51 static dev_type_open(cyopen);
   52 static dev_type_close(cyclose);
   53 static dev_type_read(cyread);
   54 static dev_type_write(cywrite);
   55 static dev_type_ioctl(cyioctl);
   56 static dev_type_stop(cystop);
   57 static dev_type_tty(cytty);
   58 static dev_type_poll(cypoll);
   59 
   60 const struct cdevsw cy_cdevsw = {
   61         .d_open = cyopen,
   62         .d_close = cyclose,
   63         .d_read = cyread,
   64         .d_write = cywrite,
   65         .d_ioctl = cyioctl,
   66         .d_stop = cystop,
   67         .d_tty = cytty,
   68         .d_poll = cypoll,
   69         .d_mmap = nommap,
   70         .d_kqfilter = ttykqfilter,
   71         .d_discard = nodiscard,
   72         .d_flag = D_TTY
   73 };
   74 
   75 static int      cy_open = 0;
   76 static int      cy_events = 0;
   77 
   78 int     cy_attached_ttys;
   79 bool    cy_callout_init;
   80 callout_t cy_poll_callout;
   81 
   82 /*
   83  * Common probe routine
   84  */
   85 int
   86 cy_find(struct cy_softc *sc)
   87 {
   88         int cy_chip, chip;
   89         u_char firmware_ver;
   90         bus_space_tag_t tag = sc->sc_memt;
   91         bus_space_handle_t bsh = sc->sc_bsh;
   92         int bustype = sc->sc_bustype;
   93 
   94         /* Cyclom card hardware reset */
   95         bus_space_write_1(tag, bsh, CY16_RESET << bustype, 0);
   96         DELAY(500);             /* wait for reset to complete */
   97         bus_space_write_1(tag, bsh, CY_CLEAR_INTR << bustype, 0);
   98 
   99 #ifdef CY_DEBUG
  100         printf("cy: card reset done\n");
  101 #endif
  102         sc->sc_nchips = 0;
  103 
  104         for (cy_chip = 0, chip = 0; cy_chip < CY_MAX_CD1400s;
  105             cy_chip++, chip += (CY_CD1400_MEMSPACING << bustype)) {
  106                 int i;
  107 
  108                 /*
  109                  * the last 4 nchips are 'interleaved' with the first 4 on
  110                  * 32-port boards
  111                  */
  112                 if (cy_chip == 4)
  113                         chip -= (CY32_ADDR_FIX << bustype);
  114 
  115 #ifdef CY_DEBUG
  116                 printf("sy: probe chip %d offset 0x%x ... ", cy_chip, chip);
  117 #endif
  118 
  119                 /* wait until the chip is ready for command */
  120                 DELAY(1000);
  121                 if (bus_space_read_1(tag, bsh, chip +
  122                     ((CD1400_CCR << 1) << bustype)) != 0) {
  123 #ifdef CY_DEBUG
  124                         printf("not ready for command\n");
  125 #endif
  126                         break;
  127                 }
  128                 /* clear the firmware version reg. */
  129                 bus_space_write_1(tag, bsh, chip +
  130                     ((CD1400_GFRCR << 1) << bustype), 0);
  131 
  132                 /*
  133                  * On Cyclom-16 references to non-existent chip 4
  134                  * actually access chip 0 (address line 9 not decoded).
  135                  * Here we check if the clearing of chip 4 GFRCR actually
  136                  * cleared chip 0 GFRCR. In that case we have a 16 port card.
  137                  */
  138                 if (cy_chip == 4 &&
  139                     bus_space_read_1(tag, bsh, /* off for chip 0 (0) + */
  140                        ((CD1400_GFRCR << 1) << bustype)) == 0)
  141                         break;
  142 
  143                 /* reset the chip */
  144                 bus_space_write_1(tag, bsh, chip +
  145                     ((CD1400_CCR << 1) << bustype),
  146                     CD1400_CCR_CMDRESET | CD1400_CCR_FULLRESET);
  147 
  148                 /* wait for the chip to initialize itself */
  149                 for (i = 0; i < 200; i++) {
  150                         DELAY(50);
  151                         firmware_ver = bus_space_read_1(tag, bsh, chip +
  152                             ((CD1400_GFRCR << 1) << bustype));
  153                         if ((firmware_ver & 0xf0) == 0x40) /* found a CD1400 */
  154                                 break;
  155                 }
  156 #ifdef CY_DEBUG
  157                 printf("firmware version 0x%x\n", firmware_ver);
  158 #endif
  159 
  160                 if ((firmware_ver & 0xf0) != 0x40)
  161                         break;
  162 
  163                 /* firmware version OK, CD1400 found */
  164                 sc->sc_nchips++;
  165         }
  166 
  167         if (sc->sc_nchips == 0) {
  168 #ifdef CY_DEBUG
  169                 printf("no CD1400s found\n");
  170 #endif
  171                 return 0;
  172         }
  173 #ifdef CY_DEBUG
  174         printf("found %d CD1400s\n", sc->sc_nchips);
  175 #endif
  176 
  177         return 1;
  178 }
  179 
  180 void
  181 cy_attach(struct cy_softc *sc)
  182 {
  183         int port, cy_chip, num_chips, cdu, chip;
  184         int cy_clock;
  185 
  186         if (!cy_callout_init) {
  187                 cy_callout_init = true;
  188                 callout_init(&cy_poll_callout, 0);
  189         }
  190 
  191         num_chips = sc->sc_nchips;
  192         if (num_chips == 0)
  193                 return;
  194 
  195         memset(sc->sc_ports, 0, sizeof(sc->sc_ports));
  196 
  197         port = 0;
  198         for (cy_chip = 0, chip = 0; cy_chip < num_chips; cy_chip++,
  199             chip += (CY_CD1400_MEMSPACING << sc->sc_bustype)) {
  200 
  201                 if (cy_chip == 4)
  202                         chip -= (CY32_ADDR_FIX << sc->sc_bustype);
  203 
  204 #ifdef CY_DEBUG
  205                 aprint_debug("attach CD1400 #%d offset 0x%x\n", cy_chip, chip);
  206 #endif
  207                 sc->sc_cd1400_offs[cy_chip] = chip;
  208 
  209                 /*
  210                  * configure port 0 as serial port (should already be after
  211                  * reset)
  212                  */
  213                 cd_write_reg(sc, cy_chip, CD1400_GCR, 0);
  214 
  215                 if (cd_read_reg(sc, cy_chip, CD1400_GFRCR) <= 0x46)
  216                         cy_clock = CY_CLOCK;
  217                 else
  218                         cy_clock = CY_CLOCK_60;
  219 
  220                 /* set up a receive timeout period (1ms) */
  221                 cd_write_reg(sc, cy_chip, CD1400_PPR,
  222                     (cy_clock / CD1400_PPR_PRESCALER / 1000) + 1);
  223 
  224                 for (cdu = 0; cdu < CD1400_NO_OF_CHANNELS; cdu++) {
  225                         sc->sc_ports[port].cy_softc = sc;
  226                         sc->sc_ports[port].cy_port_num = port;
  227                         sc->sc_ports[port].cy_chip = cy_chip;
  228                         sc->sc_ports[port].cy_clock = cy_clock;
  229 
  230                         /* should we initialize anything else here? */
  231                         port++;
  232                 } /* for(each port on one CD1400...) */
  233 
  234         } /* for(each CD1400 on a card... ) */
  235 
  236         sc->sc_nchannels = port;
  237 
  238         aprint_normal_dev(sc->sc_dev, "%d channels (ttyCY%03d..ttyCY%03d)\n",
  239             sc->sc_nchannels, cy_attached_ttys,
  240             cy_attached_ttys + (sc->sc_nchannels - 1));
  241 
  242         cy_attached_ttys += sc->sc_nchannels;
  243 
  244         /* ensure an edge for the next interrupt */
  245         bus_space_write_1(sc->sc_memt, sc->sc_bsh,
  246             CY_CLEAR_INTR << sc->sc_bustype, 0);
  247 }
  248 
  249 #define CY_UNIT(dev)            TTUNIT(dev)
  250 #define CY_DIALOUT(dev)         TTDIALOUT(dev)
  251 
  252 #define CY_PORT(dev)            cy_getport((dev))
  253 #define CY_BOARD(cy)            ((cy)->cy_softc)
  254 
  255 static struct cy_port *
  256 cy_getport(dev_t dev)
  257 {
  258         int i, j, k, u = CY_UNIT(dev);
  259         struct cy_softc *sc;
  260 
  261         for (i = 0, j = 0; i < cy_cd.cd_ndevs; i++) {
  262                 k = j;
  263                 sc = device_lookup_private(&cy_cd, i);
  264                 if (sc == NULL)
  265                         continue;
  266                 if (sc->sc_nchannels == 0)
  267                         continue;
  268                 j += sc->sc_nchannels;
  269                 if (j > u)
  270                         return (&sc->sc_ports[u - k]);
  271         }
  272 
  273         return (NULL);
  274 }
  275 
  276 /*
  277  * open routine. returns zero if successful, else error code
  278  */
  279 int
  280 cyopen(dev_t dev, int flag, int mode, struct lwp *l)
  281 {
  282         struct cy_softc *sc;
  283         struct cy_port *cy;
  284         struct tty *tp;
  285         int s, error;
  286 
  287         cy = CY_PORT(dev);
  288         if (cy == NULL)
  289                 return (ENXIO);
  290         sc = CY_BOARD(cy);
  291 
  292         s = spltty();
  293         if (cy->cy_tty == NULL) {
  294                 if ((cy->cy_tty = tty_alloc()) == NULL) {
  295                         splx(s);
  296                         aprint_error_dev(sc->sc_dev,
  297                             "port %d: can't allocate tty\n",
  298                             cy->cy_port_num);
  299                         return (ENOMEM);
  300                 }
  301                 tty_attach(cy->cy_tty);
  302         }
  303         splx(s);
  304 
  305         tp = cy->cy_tty;
  306         tp->t_oproc = cystart;
  307         tp->t_param = cyparam;
  308         tp->t_dev = dev;
  309 
  310         if (kauth_authorize_device_tty(l->l_cred, KAUTH_DEVICE_TTY_OPEN, tp))
  311                 return (EBUSY);
  312 
  313         if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
  314                 ttychars(tp);
  315                 tp->t_iflag = TTYDEF_IFLAG;
  316                 tp->t_oflag = TTYDEF_OFLAG;
  317                 tp->t_cflag = TTYDEF_CFLAG;
  318                 if (ISSET(cy->cy_openflags, TIOCFLAG_CLOCAL))
  319                         SET(tp->t_cflag, CLOCAL);
  320                 if (ISSET(cy->cy_openflags, TIOCFLAG_CRTSCTS))
  321                         SET(tp->t_cflag, CRTSCTS);
  322                 if (ISSET(cy->cy_openflags, TIOCFLAG_MDMBUF))
  323                         SET(tp->t_cflag, MDMBUF);
  324                 tp->t_lflag = TTYDEF_LFLAG;
  325                 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
  326 
  327                 s = spltty();
  328 
  329                 /*
  330                  * Allocate input ring buffer if we don't already have one
  331                  */
  332                 if (cy->cy_ibuf == NULL) {
  333                         cy->cy_ibuf = malloc(CY_IBUF_SIZE, M_DEVBUF, M_WAITOK);
  334                         cy->cy_ibuf_end = cy->cy_ibuf + CY_IBUF_SIZE;
  335                 }
  336                 /* mark the ring buffer as empty */
  337                 cy->cy_ibuf_rd_ptr = cy->cy_ibuf_wr_ptr = cy->cy_ibuf;
  338 
  339                 /* select CD1400 channel */
  340                 cd_write_reg(sc, cy->cy_chip, CD1400_CAR,
  341                     cy->cy_port_num & CD1400_CAR_CHAN);
  342                 /* reset the channel */
  343                 cd1400_channel_cmd(sc, cy, CD1400_CCR_CMDRESET);
  344                 /* encode unit (port) number in LIVR */
  345                 /* there is just enough space for 5 bits (32 ports) */
  346                 cd_write_reg(sc, cy->cy_chip, CD1400_LIVR,
  347                     cy->cy_port_num << 3);
  348 
  349                 cy->cy_channel_control = 0;
  350 
  351                 /* hmm... need spltty() here? */
  352                 if (cy_open == 0) {
  353                         cy_open = 1;
  354                         callout_reset(&cy_poll_callout, 1, cy_poll, NULL);
  355                 }
  356                 /* this sets parameters and raises DTR */
  357                 cyparam(tp, &tp->t_termios);
  358 
  359                 ttsetwater(tp);
  360 
  361                 /* raise RTS too */
  362                 cy_modem_control(sc, cy, TIOCM_RTS, DMBIS);
  363 
  364                 cy->cy_carrier_stat =
  365                         cd_read_reg(sc, cy->cy_chip, CD1400_MSVR2);
  366 
  367                 /* enable receiver and modem change interrupts */
  368                 cd_write_reg(sc, cy->cy_chip, CD1400_SRER,
  369                     CD1400_SRER_MDMCH | CD1400_SRER_RXDATA);
  370 
  371                 if (CY_DIALOUT(dev) ||
  372                     ISSET(cy->cy_openflags, TIOCFLAG_SOFTCAR) ||
  373                     ISSET(tp->t_cflag, MDMBUF) ||
  374                     ISSET(cy->cy_carrier_stat, CD1400_MSVR2_CD))
  375                         SET(tp->t_state, TS_CARR_ON);
  376                 else
  377                         CLR(tp->t_state, TS_CARR_ON);
  378                 splx(s);
  379         }
  380 
  381         /* wait for carrier if necessary */
  382         if (!ISSET(flag, O_NONBLOCK)) {
  383                 ttylock(tp);
  384                 while (!ISSET(tp->t_cflag, CLOCAL) &&
  385                     !ISSET(tp->t_state, TS_CARR_ON)) {
  386                         tp->t_wopen++;
  387                         error = ttysleep(tp, &tp->t_rawcv, true, 0);
  388                         tp->t_wopen--;
  389                         if (error != 0) {
  390                                 ttyunlock(tp);
  391                                 return error;
  392                         }
  393                 }
  394                 ttyunlock(tp);
  395         }
  396 
  397         return (*tp->t_linesw->l_open) (dev, tp);
  398 }
  399 
  400 /*
  401  * close routine. returns zero if successful, else error code
  402  */
  403 int
  404 cyclose(dev_t dev, int flag, int mode, struct lwp *l)
  405 {
  406         struct cy_softc *sc;
  407         struct cy_port *cy;
  408         struct tty *tp;
  409         int s;
  410 
  411         cy = CY_PORT(dev);
  412         sc = CY_BOARD(cy);
  413         tp = cy->cy_tty;
  414 
  415         (*tp->t_linesw->l_close) (tp, flag);
  416         s = spltty();
  417 
  418         if (ISSET(tp->t_cflag, HUPCL) &&
  419             !ISSET(cy->cy_openflags, TIOCFLAG_SOFTCAR)) {
  420                 /*
  421                  * drop DTR and RTS (should we wait for output buffer to
  422                  * become empty first?)
  423                  */
  424                 cy_modem_control(sc, cy, 0, DMSET);
  425         }
  426         /*
  427          * XXX should we disable modem change and
  428          * receive interrupts here or somewhere ?
  429          */
  430         CLR(tp->t_state, TS_BUSY | TS_FLUSH);
  431 
  432         splx(s);
  433         ttyclose(tp);
  434 
  435         return 0;
  436 }
  437 
  438 /*
  439  * Read routine
  440  */
  441 int
  442 cyread(dev_t dev, struct uio *uio, int flag)
  443 {
  444         struct cy_port *cy;
  445         struct tty *tp;
  446 
  447         cy = CY_PORT(dev);
  448         tp = cy->cy_tty;
  449 
  450         return ((*tp->t_linesw->l_read)(tp, uio, flag));
  451 }
  452 
  453 /*
  454  * Write routine
  455  */
  456 int
  457 cywrite(dev_t dev, struct uio *uio, int flag)
  458 {
  459         struct cy_port *cy;
  460         struct tty *tp;
  461 
  462         cy = CY_PORT(dev);
  463         tp = cy->cy_tty;
  464 
  465         return ((*tp->t_linesw->l_write)(tp, uio, flag));
  466 }
  467 
  468 /*
  469  * Poll routine
  470  */
  471 int
  472 cypoll(dev_t dev, int events, struct lwp *l)
  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, l));
  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, void *data, int flag, struct lwp *l)
  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, l);
  512         if (error != EPASSTHROUGH)
  513                 return error;
  514 
  515         error = ttioctl(tp, cmd, data, flag, l);
  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 = kauth_authorize_device_tty(l->l_cred,
  563                     KAUTH_DEVICE_TTY_PRIVSET, tp);
  564                 if (error != 0)
  565                         return EPERM;
  566 
  567                 cy->cy_openflags = *((int *) data) &
  568                     (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL |
  569                      TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF);
  570                 break;
  571 
  572         default:
  573                 return EPASSTHROUGH;
  574         }
  575 
  576         return 0;
  577 }
  578 
  579 /*
  580  * start output
  581  */
  582 void
  583 cystart(struct tty *tp)
  584 {
  585         struct cy_softc *sc;
  586         struct cy_port *cy;
  587         int s;
  588 
  589         cy = CY_PORT(tp->t_dev);
  590         sc = cy->cy_softc;
  591 
  592         s = spltty();
  593 
  594 #ifdef CY_DEBUG1
  595         cy->cy_start_count++;
  596 #endif
  597 
  598         if (!ISSET(tp->t_state, TS_TTSTOP | TS_TIMEOUT | TS_BUSY)) {
  599                 if (!ttypull(tp))
  600                         goto out;
  601                 SET(tp->t_state, TS_BUSY);
  602                 cy_enable_transmitter(sc, cy);
  603         }
  604 out:
  605 
  606         splx(s);
  607 }
  608 
  609 /*
  610  * stop output
  611  */
  612 void
  613 cystop(struct tty *tp, int flag)
  614 {
  615         struct cy_port *cy;
  616         int s;
  617 
  618         cy = CY_PORT(tp->t_dev);
  619 
  620         s = spltty();
  621         if (ISSET(tp->t_state, TS_BUSY)) {
  622                 if (!ISSET(tp->t_state, TS_TTSTOP))
  623                         SET(tp->t_state, TS_FLUSH);
  624 
  625                 /*
  626                  * the transmit interrupt routine will disable transmit when it
  627                  * notices that CY_F_STOP has been set.
  628                  */
  629                 SET(cy->cy_flags, CY_F_STOP);
  630         }
  631         splx(s);
  632 }
  633 
  634 /*
  635  * parameter setting routine.
  636  * returns 0 if successful, else returns error code
  637  */
  638 int
  639 cyparam(struct tty *tp, struct termios *t)
  640 {
  641         struct cy_softc *sc;
  642         struct cy_port *cy;
  643         int ibpr = 0, obpr = 0, i_clk_opt = 0, o_clk_opt = 0;   /* XXX: GCC */
  644         int s, opt;
  645 
  646         cy = CY_PORT(tp->t_dev);
  647         sc = CY_BOARD(cy);
  648 
  649         if (t->c_ospeed != 0 && cy_speed(t->c_ospeed, &o_clk_opt, &obpr, cy->cy_clock) < 0)
  650                 return EINVAL;
  651 
  652         if (t->c_ispeed != 0 && cy_speed(t->c_ispeed, &i_clk_opt, &ibpr, cy->cy_clock) < 0)
  653                 return EINVAL;
  654 
  655         s = spltty();
  656 
  657         /* hang up the line is ospeed is zero, else turn DTR on */
  658         cy_modem_control(sc, cy, TIOCM_DTR, (t->c_ospeed == 0 ? DMBIC : DMBIS));
  659 
  660         /* channel was selected by the above call to cy_modem_control() */
  661 #if 0
  662         cd_write_reg(sc, cy->cy_chip, CD1400_CAR, port & CD1400_CAR_CHAN);
  663 #endif
  664 
  665         /* set transmit speed */
  666         if (t->c_ospeed != 0) {
  667                 cd_write_reg(sc, cy->cy_chip, CD1400_TCOR, o_clk_opt);
  668                 cd_write_reg(sc, cy->cy_chip, CD1400_TBPR, obpr);
  669         }
  670         /* set receive speed */
  671         if (t->c_ispeed != 0) {
  672                 cd_write_reg(sc, cy->cy_chip, CD1400_RCOR, i_clk_opt);
  673                 cd_write_reg(sc, cy->cy_chip, CD1400_RBPR, ibpr);
  674         }
  675         opt = CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN
  676                 | (ISSET(t->c_cflag, CREAD) ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS);
  677 
  678         if (opt != cy->cy_channel_control) {
  679                 cy->cy_channel_control = opt;
  680                 cd1400_channel_cmd(sc, cy, opt);
  681         }
  682         /* compute COR1 contents */
  683         opt = 0;
  684         if (ISSET(t->c_cflag, PARENB)) {
  685                 if (ISSET(t->c_cflag, PARODD))
  686                         opt |= CD1400_COR1_PARODD;
  687                 opt |= CD1400_COR1_PARNORMAL;
  688         }
  689         if (!ISSET(t->c_iflag, INPCK))
  690                 opt |= CD1400_COR1_NOINPCK;     /* no parity checking */
  691 
  692         if (ISSET(t->c_cflag, CSTOPB))
  693                 opt |= CD1400_COR1_STOP2;
  694 
  695         switch (t->c_cflag & CSIZE) {
  696         case CS5:
  697                 opt |= CD1400_COR1_CS5;
  698                 break;
  699 
  700         case CS6:
  701                 opt |= CD1400_COR1_CS6;
  702                 break;
  703 
  704         case CS7:
  705                 opt |= CD1400_COR1_CS7;
  706                 break;
  707 
  708         default:
  709                 opt |= CD1400_COR1_CS8;
  710                 break;
  711         }
  712 
  713         cd_write_reg(sc, cy->cy_chip, CD1400_COR1, opt);
  714 
  715 #ifdef CY_DEBUG
  716         printf("cor1 = 0x%x...", opt);
  717 #endif
  718 
  719         /*
  720          * use the CD1400 automatic CTS flow control if CRTSCTS is set
  721          *
  722          * CD1400_COR2_ETC is used because breaks are generated with
  723          * embedded transmit commands
  724          */
  725         cd_write_reg(sc, cy->cy_chip, CD1400_COR2,
  726                      CD1400_COR2_ETC |
  727                  (ISSET(t->c_cflag, CRTSCTS) ? CD1400_COR2_CCTS_OFLOW : 0));
  728 
  729         cd_write_reg(sc, cy->cy_chip, CD1400_COR3, CY_RX_FIFO_THRESHOLD);
  730 
  731         cd1400_channel_cmd(sc, cy, CD1400_CCR_CMDCORCHG |
  732             CD1400_CCR_COR1 | CD1400_CCR_COR2 | CD1400_CCR_COR3);
  733 
  734         cd_write_reg(sc, cy->cy_chip, CD1400_COR4, CD1400_COR4_PFO_EXCEPTION);
  735         cd_write_reg(sc, cy->cy_chip, CD1400_COR5, 0);
  736 
  737         /*
  738          * set modem change option registers to generate interrupts
  739          * on carrier detect changes.
  740          *
  741          * if hardware RTS handshaking is used
  742          * also set the handshaking threshold.
  743          */
  744         if (cy->cy_clock == CY_CLOCK_60) {
  745            cd_write_reg(sc, cy->cy_chip, CD1400_MCOR1, CD1400_MCOR1_CDzd |
  746               (ISSET(t->c_cflag, CRTSCTS) ? CY_RX_DTR_THRESHOLD : 0));
  747         } else {
  748            cd_write_reg(sc, cy->cy_chip, CD1400_MCOR1, CD1400_MCOR1_CDzd);
  749         }
  750 
  751         cd_write_reg(sc, cy->cy_chip, CD1400_MCOR2, CD1400_MCOR2_CDod);
  752 
  753         /*
  754          * set receive timeout to approx. 2ms
  755          * could use more complex logic here...
  756          * (but is it actually needed or even useful?)
  757          */
  758         cd_write_reg(sc, cy->cy_chip, CD1400_RTPR, 2);
  759 
  760         /*
  761          * should do anything else here?
  762          * XXX check MDMBUF handshaking like in com.c?
  763          */
  764 
  765         splx(s);
  766         return 0;
  767 }
  768 
  769 /*
  770  * set/get modem line status
  771  *
  772  * bits can be: TIOCM_DTR, TIOCM_RTS, TIOCM_CTS, TIOCM_CD, TIOCM_RI, TIOCM_DSR
  773  */
  774 int
  775 cy_modem_control(struct cy_softc *sc, struct cy_port *cy, int bits, int howto)
  776 {
  777         struct tty *tp = cy->cy_tty;
  778         int s, msvr;
  779 
  780         s = spltty();
  781 
  782         /* select channel */
  783         cd_write_reg(sc, cy->cy_chip, CD1400_CAR,
  784             cy->cy_port_num & CD1400_CAR_CHAN);
  785 
  786         /* Does not manipulate RTS if it is used for flow control. */
  787         switch (howto) {
  788         case DMGET:
  789                 bits = 0;
  790                 if (cy->cy_channel_control & CD1400_CCR_RCVEN)
  791                         bits |= TIOCM_LE;
  792                 msvr = cd_read_reg(sc, cy->cy_chip, CD1400_MSVR2);
  793                 if (cy->cy_clock == CY_CLOCK_60) {
  794                         if (cd_read_reg(sc, cy->cy_chip, CD1400_MSVR1) &
  795                                 CD1400_MSVR1_RTS)
  796                                 bits |= TIOCM_DTR;
  797                         if (msvr & CD1400_MSVR2_DTR)
  798                                 bits |= TIOCM_RTS;
  799                 } else {
  800                         if (cd_read_reg(sc, cy->cy_chip, CD1400_MSVR1) &
  801                             CD1400_MSVR1_RTS)
  802                                 bits |= TIOCM_RTS;
  803                         if (msvr & CD1400_MSVR2_DTR)
  804                                 bits |= TIOCM_DTR;
  805                 }
  806                 if (msvr & CD1400_MSVR2_CTS)
  807                         bits |= TIOCM_CTS;
  808                 if (msvr & CD1400_MSVR2_CD)
  809                         bits |= TIOCM_CD;
  810                 /* Not connected on some Cyclom-Y boards? */
  811                 if (msvr & CD1400_MSVR2_DSR)
  812                         bits |= TIOCM_DSR;
  813                 /* Not connected on some Cyclom-8Y boards? */
  814                 if (msvr & CD1400_MSVR2_RI)
  815                         bits |= TIOCM_RI;
  816                 break;
  817 
  818         case DMSET:             /* replace old values with new ones */
  819                 if (cy->cy_clock == CY_CLOCK_60) {
  820                         if (!ISSET(tp->t_cflag, CRTSCTS))
  821                                 cd_write_reg(sc, cy->cy_chip, CD1400_MSVR2,
  822                                    ((bits & TIOCM_RTS) ? CD1400_MSVR2_DTR : 0));
  823                         cd_write_reg(sc, cy->cy_chip, CD1400_MSVR1,
  824                             ((bits & TIOCM_DTR) ? CD1400_MSVR1_RTS : 0));
  825                 } else {
  826                         if (!ISSET(tp->t_cflag, CRTSCTS))
  827                                 cd_write_reg(sc, cy->cy_chip, CD1400_MSVR1,
  828                                    ((bits & TIOCM_RTS) ? CD1400_MSVR1_RTS : 0));
  829                         cd_write_reg(sc, cy->cy_chip, CD1400_MSVR2,
  830                             ((bits & TIOCM_DTR) ? CD1400_MSVR2_DTR : 0));
  831                 }
  832                 break;
  833 
  834         case DMBIS:             /* set bits */
  835                 if (cy->cy_clock == CY_CLOCK_60) {
  836                         if (!ISSET(tp->t_cflag, CRTSCTS) &&
  837                             (bits & TIOCM_RTS) != 0)
  838                                 cd_write_reg(sc, cy->cy_chip, CD1400_MSVR2,
  839                                     CD1400_MSVR2_DTR);
  840                         if (bits & TIOCM_DTR)
  841                                 cd_write_reg(sc, cy->cy_chip, CD1400_MSVR1,
  842                                     CD1400_MSVR1_RTS);
  843                 } else {
  844                         if (!ISSET(tp->t_cflag, CRTSCTS) &&
  845                             (bits & TIOCM_RTS) != 0)
  846                                 cd_write_reg(sc, cy->cy_chip, CD1400_MSVR1,
  847                                     CD1400_MSVR1_RTS);
  848                         if (bits & TIOCM_DTR)
  849                                 cd_write_reg(sc, cy->cy_chip, CD1400_MSVR2,
  850                                     CD1400_MSVR2_DTR);
  851                 }
  852                 break;
  853 
  854         case DMBIC:             /* clear bits */
  855                 if (cy->cy_clock == CY_CLOCK_60) {
  856                         if (!ISSET(tp->t_cflag, CRTSCTS) && (bits & TIOCM_RTS))
  857                                 cd_write_reg(sc, cy->cy_chip, CD1400_MSVR2, 0);
  858                         if (bits & TIOCM_DTR)
  859                                 cd_write_reg(sc, cy->cy_chip, CD1400_MSVR1, 0);
  860                 } else {
  861                         if (!ISSET(tp->t_cflag, CRTSCTS) && (bits & TIOCM_RTS))
  862                                 cd_write_reg(sc, cy->cy_chip, CD1400_MSVR1, 0);
  863                         if (bits & TIOCM_DTR)
  864                                 cd_write_reg(sc, cy->cy_chip, CD1400_MSVR2, 0);
  865                 }
  866                 break;
  867         }
  868         splx(s);
  869         return ((howto == DMGET) ? bits : 0);
  870 }
  871 
  872 /*
  873  * Upper-level handler loop (called from timer interrupt?)
  874  * This routine is common for multiple cards
  875  */
  876 void
  877 cy_poll(void *arg)
  878 {
  879         int card, port;
  880         struct cy_softc *sc;
  881         struct cy_port *cy;
  882         struct tty *tp;
  883         static int counter = 0;
  884 #ifdef CY_DEBUG1
  885         int did_something;
  886 #endif
  887         int s = spltty();
  888 
  889         if (cy_events == 0 && ++counter < 200) {
  890                 splx(s);
  891                 goto out;
  892         }
  893         cy_events = 0;
  894         splx(s);
  895 
  896         for (card = 0; card < cy_cd.cd_ndevs; card++) {
  897                 sc = device_lookup_private(&cy_cd, card);
  898                 if (sc == NULL)
  899                         continue;
  900 
  901 #ifdef CY_DEBUG1
  902                 sc->sc_poll_count1++;
  903                 did_something = 0;
  904 #endif
  905 
  906                 for (port = 0; port < sc->sc_nchannels; port++) {
  907                         cy = &sc->sc_ports[port];
  908                         if ((tp = cy->cy_tty) == NULL || cy->cy_ibuf == NULL ||
  909                             (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0))
  910                                 continue;
  911 
  912                         /*
  913                          * handle received data
  914                          */
  915                         while (cy->cy_ibuf_rd_ptr != cy->cy_ibuf_wr_ptr) {
  916                                 u_char line_stat;
  917                                 int chr;
  918 
  919                                 line_stat = cy->cy_ibuf_rd_ptr[0];
  920                                 chr = cy->cy_ibuf_rd_ptr[1];
  921 
  922                                 if (line_stat &
  923                                     (CD1400_RDSR_BREAK | CD1400_RDSR_FE))
  924                                         chr |= TTY_FE;
  925                                 if (line_stat & CD1400_RDSR_PE)
  926                                         chr |= TTY_PE;
  927 
  928                                 /*
  929                                  * on an overrun error the data is treated as
  930                                  * good just as it should be.
  931                                  */
  932 
  933 #ifdef CY_DEBUG
  934                                 aprint_debug_dev(sc->sc_dev,
  935                                     "port %d ttyinput 0x%x\n",
  936                                     port, chr);
  937 #endif
  938 
  939                                 (*tp->t_linesw->l_rint) (chr, tp);
  940 
  941                                 s = spltty();   /* really necessary? */
  942                                 if ((cy->cy_ibuf_rd_ptr += 2) ==
  943                                     cy->cy_ibuf_end)
  944                                         cy->cy_ibuf_rd_ptr = cy->cy_ibuf;
  945                                 splx(s);
  946 
  947 #ifdef CY_DEBUG1
  948                                 did_something = 1;
  949 #endif
  950                         }
  951 
  952                         /*
  953                          * If we don't have any received data in ibuf and
  954                          * CRTSCTS is on and RTS is turned off, it is time to
  955                          * turn RTS back on
  956                          */
  957                         if (ISSET(tp->t_cflag, CRTSCTS)) {
  958                                 /*
  959                                  * we can't use cy_modem_control() here as it
  960                                  * doesn't change RTS if RTSCTS is on
  961                                  */
  962                                 cd_write_reg(sc, cy->cy_chip, CD1400_CAR,
  963                                     port & CD1400_CAR_CHAN);
  964 
  965                                 if (cy->cy_clock == CY_CLOCK_60) {
  966                                   if ((cd_read_reg(sc, cy->cy_chip,
  967                                     CD1400_MSVR2) & CD1400_MSVR2_DTR) == 0) {
  968                                         cd_write_reg(sc, cy->cy_chip,
  969                                         CD1400_MSVR2,CD1400_MSVR2_DTR);
  970 #ifdef CY_DEBUG1
  971                                         did_something = 1;
  972 #endif
  973                                   }
  974                                 } else {
  975                                   if ((cd_read_reg(sc, cy->cy_chip,
  976                                     CD1400_MSVR1) & CD1400_MSVR1_RTS) == 0) {
  977                                         cd_write_reg(sc, cy->cy_chip,
  978                                         CD1400_MSVR1,CD1400_MSVR1_RTS);
  979 #ifdef CY_DEBUG1
  980                                         did_something = 1;
  981 #endif
  982                                   }
  983                                 }
  984                         }
  985 
  986                         /*
  987                          * handle carrier changes
  988                          */
  989                         s = spltty();
  990                         if (ISSET(cy->cy_flags, CY_F_CARRIER_CHANGED)) {
  991                                 int             carrier;
  992 
  993                                 CLR(cy->cy_flags, CY_F_CARRIER_CHANGED);
  994                                 splx(s);
  995 
  996                                 carrier = ((cy->cy_carrier_stat &
  997                                     CD1400_MSVR2_CD) != 0);
  998 
  999 #ifdef CY_DEBUG
 1000                                 printf("cy_poll: carrier change "
 1001                                     "(card %d, port %d, carrier %d)\n",
 1002                                     card, port, carrier);
 1003 #endif
 1004                                 if (CY_DIALOUT(tp->t_dev) == 0 &&
 1005                                     !(*tp->t_linesw->l_modem)(tp, carrier))
 1006                                         cy_modem_control(sc, cy,
 1007                                             TIOCM_DTR, DMBIC);
 1008 
 1009 #ifdef CY_DEBUG1
 1010                                 did_something = 1;
 1011 #endif
 1012                         } else
 1013                                 splx(s);
 1014 
 1015                         s = spltty();
 1016                         if (ISSET(cy->cy_flags, CY_F_START)) {
 1017                                 CLR(cy->cy_flags, CY_F_START);
 1018                                 splx(s);
 1019 
 1020                                 (*tp->t_linesw->l_start) (tp);
 1021 
 1022 #ifdef CY_DEBUG1
 1023                                 did_something = 1;
 1024 #endif
 1025                         } else
 1026                                 splx(s);
 1027 
 1028                         /* could move this to even upper level... */
 1029                         if (cy->cy_fifo_overruns) {
 1030                                 cy->cy_fifo_overruns = 0;
 1031                                 /*
 1032                                  * doesn't report overrun count, but
 1033                                  * shouldn't really matter
 1034                                  */
 1035                                 log(LOG_WARNING, "%s: port %d fifo overrun\n",
 1036                                     device_xname(sc->sc_dev), port);
 1037                         }
 1038                         if (cy->cy_ibuf_overruns) {
 1039                                 cy->cy_ibuf_overruns = 0;
 1040                                 log(LOG_WARNING, "%s: port %d ibuf overrun\n",
 1041                                     device_xname(sc->sc_dev), port);
 1042                         }
 1043                 }               /* for(port...) */
 1044 #ifdef CY_DEBUG1
 1045                 if (did_something && counter >= 200)
 1046                         sc->sc_poll_count2++;
 1047 #endif
 1048         } /* for(card...) */
 1049 
 1050         counter = 0;
 1051 
 1052 out:
 1053         callout_reset(&cy_poll_callout, 1, cy_poll, NULL);
 1054 }
 1055 
 1056 /*
 1057  * hardware interrupt routine
 1058  */
 1059 int
 1060 cy_intr(void *arg)
 1061 {
 1062         struct cy_softc *sc = arg;
 1063         struct cy_port *cy;
 1064         int cy_chip, stat;
 1065         int int_serviced = 0;
 1066 
 1067         /*
 1068          * Check interrupt status of each CD1400 chip on this card
 1069          * (multiple cards cannot share the same interrupt)
 1070          */
 1071         for (cy_chip = 0; cy_chip < sc->sc_nchips; cy_chip++) {
 1072 
 1073                 stat = cd_read_reg(sc, cy_chip, CD1400_SVRR);
 1074                 if (stat == 0)
 1075                         continue;
 1076 
 1077                 if (ISSET(stat, CD1400_SVRR_RXRDY)) {
 1078                         u_char save_car, save_rir, serv_type;
 1079                         u_char line_stat, recv_data, n_chars;
 1080                         u_char *buf_p;
 1081 
 1082                         save_rir = cd_read_reg(sc, cy_chip, CD1400_RIR);
 1083                         save_car = cd_read_reg(sc, cy_chip, CD1400_CAR);
 1084                         /* enter rx service */
 1085                         cd_write_reg(sc, cy_chip, CD1400_CAR, save_rir);
 1086 
 1087                         serv_type = cd_read_reg(sc, cy_chip, CD1400_RIVR);
 1088                         cy = &sc->sc_ports[serv_type >> 3];
 1089 
 1090 #ifdef CY_DEBUG1
 1091                         cy->cy_rx_int_count++;
 1092 #endif
 1093 
 1094                         buf_p = cy->cy_ibuf_wr_ptr;
 1095 
 1096                         if (ISSET(serv_type, CD1400_RIVR_EXCEPTION)) {
 1097                                 line_stat = cd_read_reg(sc, cy->cy_chip,
 1098                                     CD1400_RDSR);
 1099                                 recv_data = cd_read_reg(sc, cy->cy_chip,
 1100                                     CD1400_RDSR);
 1101 
 1102                                 if (cy->cy_tty == NULL ||
 1103                                     !ISSET(cy->cy_tty->t_state, TS_ISOPEN))
 1104                                         goto end_rx_serv;
 1105 
 1106 #ifdef CY_DEBUG
 1107                                 aprint_debug_dev(
 1108                                     sc->sc_dev,
 1109                                     "port %d recv exception, "
 1110                                     "line_stat 0x%x, char 0x%x\n",
 1111                                     cy->cy_port_num, line_stat, recv_data);
 1112 #endif
 1113                                 if (ISSET(line_stat, CD1400_RDSR_OE))
 1114                                         cy->cy_fifo_overruns++;
 1115 
 1116                                 *buf_p++ = line_stat;
 1117                                 *buf_p++ = recv_data;
 1118                                 if (buf_p == cy->cy_ibuf_end)
 1119                                         buf_p = cy->cy_ibuf;
 1120 
 1121                                 if (buf_p == cy->cy_ibuf_rd_ptr) {
 1122                                         if (buf_p == cy->cy_ibuf)
 1123                                                 buf_p = cy->cy_ibuf_end;
 1124                                         buf_p -= 2;
 1125                                         cy->cy_ibuf_overruns++;
 1126                                 }
 1127                                 cy_events = 1;
 1128                         } else {/* no exception, received data OK */
 1129                                 n_chars = cd_read_reg(sc, cy->cy_chip,
 1130                                     CD1400_RDCR);
 1131 
 1132                                 /* If no tty or not open, discard data */
 1133                                 if (cy->cy_tty == NULL ||
 1134                                     !ISSET(cy->cy_tty->t_state, TS_ISOPEN)) {
 1135                                         while (n_chars--)
 1136                                                 (void)cd_read_reg(sc,
 1137                                                     cy->cy_chip, CD1400_RDSR);
 1138                                         goto end_rx_serv;
 1139                                 }
 1140 
 1141 #ifdef CY_DEBUG
 1142                                 aprint_debug_dev(sc->sc_dev,
 1143                                     "port %d receive ok %d chars\n",
 1144                                     cy->cy_port_num, n_chars);
 1145 #endif
 1146                                 while (n_chars--) {
 1147                                         *buf_p++ = 0;   /* status: OK */
 1148                                         /* data byte */
 1149                                         *buf_p++ = cd_read_reg(sc,
 1150                                             cy->cy_chip, CD1400_RDSR);
 1151                                         if (buf_p == cy->cy_ibuf_end)
 1152                                                 buf_p = cy->cy_ibuf;
 1153                                         if (buf_p == cy->cy_ibuf_rd_ptr) {
 1154                                                 if (buf_p == cy->cy_ibuf)
 1155                                                         buf_p = cy->cy_ibuf_end;
 1156                                                 buf_p -= 2;
 1157                                                 cy->cy_ibuf_overruns++;
 1158                                                 break;
 1159                                         }
 1160                                 }
 1161                                 cy_events = 1;
 1162                         }
 1163 
 1164                         cy->cy_ibuf_wr_ptr = buf_p;
 1165 
 1166                         /* RTS handshaking for incoming data */
 1167                         if (ISSET(cy->cy_tty->t_cflag, CRTSCTS)) {
 1168                                 int bf, msvr;
 1169 
 1170                                 bf = buf_p - cy->cy_ibuf_rd_ptr;
 1171                                 if (bf < 0)
 1172                                         bf += CY_IBUF_SIZE;
 1173 
 1174                                 if (bf > (CY_IBUF_SIZE / 2)) {
 1175                                         /* turn RTS off */
 1176                                         if (cy->cy_clock == CY_CLOCK_60)
 1177                                                 msvr = CD1400_MSVR2;
 1178                                         else
 1179                                                 msvr = CD1400_MSVR1;
 1180                                         cd_write_reg(sc, cy->cy_chip, msvr, 0);
 1181                                 }
 1182                         }
 1183 
 1184         end_rx_serv:
 1185                         /* terminate service context */
 1186                         cd_write_reg(sc, cy->cy_chip, CD1400_RIR,
 1187                                      save_rir & 0x3f);
 1188                         cd_write_reg(sc, cy->cy_chip, CD1400_CAR, save_car);
 1189                         int_serviced = 1;
 1190                 } /* if (rx_service...) */
 1191                 if (ISSET(stat, CD1400_SVRR_MDMCH)) {
 1192                         u_char save_car, save_mir, serv_type, modem_stat;
 1193 
 1194                         save_mir = cd_read_reg(sc, cy_chip, CD1400_MIR);
 1195                         save_car = cd_read_reg(sc, cy_chip, CD1400_CAR);
 1196                         /* enter modem service */
 1197                         cd_write_reg(sc, cy_chip, CD1400_CAR, save_mir);
 1198 
 1199                         serv_type = cd_read_reg(sc, cy_chip, CD1400_MIVR);
 1200                         cy = &sc->sc_ports[serv_type >> 3];
 1201 
 1202 #ifdef CY_DEBUG1
 1203                         cy->cy_modem_int_count++;
 1204 #endif
 1205 
 1206                         modem_stat = cd_read_reg(sc, cy->cy_chip, CD1400_MSVR2);
 1207 
 1208 #ifdef CY_DEBUG
 1209                         aprint_debug_dev(sc->sc_dev,
 1210                             "port %d modem line change, new stat 0x%x\n",
 1211                             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                         aprint_debug_dev(sc->sc_dev, "port %d tx service\n",
 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                     device_xname(sc->sc_dev));
 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: 2650c10873185849d8a44df929fcef05


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