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-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: cy.c,v 1.56 2008/05/25 19:22:21 ad 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.56 2008/05/25 19:22:21 ad 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/select.h>
   30 #include <sys/device.h>
   31 #include <sys/malloc.h>
   32 #include <sys/systm.h>
   33 #include <sys/callout.h>
   34 #include <sys/kauth.h>
   35 
   36 #include <sys/bus.h>
   37 
   38 #include <dev/ic/cd1400reg.h>
   39 #include <dev/ic/cyreg.h>
   40 #include <dev/ic/cyvar.h>
   41 
   42 static int      cyparam(struct tty *, struct termios *);
   43 static void     cystart(struct tty *);
   44 static void     cy_poll(void *);
   45 static int      cy_modem_control(struct cy_softc *, struct cy_port *, int, int);
   46 static void     cy_enable_transmitter(struct cy_softc *, struct cy_port *);
   47 static void     cd1400_channel_cmd(struct cy_softc *, struct cy_port *, int);
   48 static int      cy_speed(speed_t, int *, int *, int);
   49 
   50 extern struct cfdriver cy_cd;
   51 
   52 static dev_type_open(cyopen);
   53 static dev_type_close(cyclose);
   54 static dev_type_read(cyread);
   55 static dev_type_write(cywrite);
   56 static dev_type_ioctl(cyioctl);
   57 static dev_type_stop(cystop);
   58 static dev_type_tty(cytty);
   59 static dev_type_poll(cypoll);
   60 
   61 const struct cdevsw cy_cdevsw = {
   62         .d_open = cyopen,
   63         .d_close = cyclose,
   64         .d_read = cyread,
   65         .d_write = cywrite,
   66         .d_ioctl = cyioctl,
   67         .d_stop = cystop,
   68         .d_tty = cytty,
   69         .d_poll = cypoll,
   70         .d_mmap = nommap,
   71         .d_kqfilter = ttykqfilter,
   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 CYDIALOUT_MASK          0x80000
  250 #define CY_DIALOUT(dev)         (minor(dev) & CYDIALOUT_MASK)
  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 = minor(dev) & ~CYDIALOUT_MASK;
  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 = ttymalloc()) == 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_NOWAIT);
  334                         if (cy->cy_ibuf == NULL) {
  335                                 aprint_error_dev(sc->sc_dev,
  336                                     "port %d: can't allocate input buffer\n",
  337                                     cy->cy_port_num);
  338                                 splx(s);
  339                                 return ENOMEM;
  340                         }
  341                         cy->cy_ibuf_end = cy->cy_ibuf + CY_IBUF_SIZE;
  342                 }
  343                 /* mark the ring buffer as empty */
  344                 cy->cy_ibuf_rd_ptr = cy->cy_ibuf_wr_ptr = cy->cy_ibuf;
  345 
  346                 /* select CD1400 channel */
  347                 cd_write_reg(sc, cy->cy_chip, CD1400_CAR,
  348                     cy->cy_port_num & CD1400_CAR_CHAN);
  349                 /* reset the channel */
  350                 cd1400_channel_cmd(sc, cy, CD1400_CCR_CMDRESET);
  351                 /* encode unit (port) number in LIVR */
  352                 /* there is just enough space for 5 bits (32 ports) */
  353                 cd_write_reg(sc, cy->cy_chip, CD1400_LIVR,
  354                     cy->cy_port_num << 3);
  355 
  356                 cy->cy_channel_control = 0;
  357 
  358                 /* hmm... need spltty() here? */
  359                 if (cy_open == 0) {
  360                         cy_open = 1;
  361                         callout_reset(&cy_poll_callout, 1, cy_poll, NULL);
  362                 }
  363                 /* this sets parameters and raises DTR */
  364                 cyparam(tp, &tp->t_termios);
  365 
  366                 ttsetwater(tp);
  367 
  368                 /* raise RTS too */
  369                 cy_modem_control(sc, cy, TIOCM_RTS, DMBIS);
  370 
  371                 cy->cy_carrier_stat =
  372                         cd_read_reg(sc, cy->cy_chip, CD1400_MSVR2);
  373 
  374                 /* enable receiver and modem change interrupts */
  375                 cd_write_reg(sc, cy->cy_chip, CD1400_SRER,
  376                     CD1400_SRER_MDMCH | CD1400_SRER_RXDATA);
  377 
  378                 if (CY_DIALOUT(dev) ||
  379                     ISSET(cy->cy_openflags, TIOCFLAG_SOFTCAR) ||
  380                     ISSET(tp->t_cflag, MDMBUF) ||
  381                     ISSET(cy->cy_carrier_stat, CD1400_MSVR2_CD))
  382                         SET(tp->t_state, TS_CARR_ON);
  383                 else
  384                         CLR(tp->t_state, TS_CARR_ON);
  385                 splx(s);
  386         }
  387 
  388         /* wait for carrier if necessary */
  389         if (!ISSET(flag, O_NONBLOCK)) {
  390                 mutex_spin_enter(&tty_lock);
  391                 while (!ISSET(tp->t_cflag, CLOCAL) &&
  392                     !ISSET(tp->t_state, TS_CARR_ON)) {
  393                         tp->t_wopen++;
  394                         error = ttysleep(tp, &tp->t_rawcv, true, 0);
  395                         tp->t_wopen--;
  396                         if (error != 0) {
  397                                 mutex_spin_exit(&tty_lock);
  398                                 return error;
  399                         }
  400                 }
  401                 mutex_spin_exit(&tty_lock);
  402         }
  403 
  404         return (*tp->t_linesw->l_open) (dev, tp);
  405 }
  406 
  407 /*
  408  * close routine. returns zero if successful, else error code
  409  */
  410 int
  411 cyclose(dev_t dev, int flag, int mode, struct lwp *l)
  412 {
  413         struct cy_softc *sc;
  414         struct cy_port *cy;
  415         struct tty *tp;
  416         int s;
  417 
  418         cy = CY_PORT(dev);
  419         sc = CY_BOARD(cy);
  420         tp = cy->cy_tty;
  421 
  422         (*tp->t_linesw->l_close) (tp, flag);
  423         s = spltty();
  424 
  425         if (ISSET(tp->t_cflag, HUPCL) &&
  426             !ISSET(cy->cy_openflags, TIOCFLAG_SOFTCAR)) {
  427                 /*
  428                  * drop DTR and RTS (should we wait for output buffer to
  429                  * become empty first?)
  430                  */
  431                 cy_modem_control(sc, cy, 0, DMSET);
  432         }
  433         /*
  434          * XXX should we disable modem change and
  435          * receive interrupts here or somewhere ?
  436          */
  437         CLR(tp->t_state, TS_BUSY | TS_FLUSH);
  438 
  439         splx(s);
  440         ttyclose(tp);
  441 
  442         return 0;
  443 }
  444 
  445 /*
  446  * Read routine
  447  */
  448 int
  449 cyread(dev_t dev, struct uio *uio, int flag)
  450 {
  451         struct cy_port *cy;
  452         struct tty *tp;
  453 
  454         cy = CY_PORT(dev);
  455         tp = cy->cy_tty;
  456 
  457         return ((*tp->t_linesw->l_read)(tp, uio, flag));
  458 }
  459 
  460 /*
  461  * Write routine
  462  */
  463 int
  464 cywrite(dev_t dev, struct uio *uio, int flag)
  465 {
  466         struct cy_port *cy;
  467         struct tty *tp;
  468 
  469         cy = CY_PORT(dev);
  470         tp = cy->cy_tty;
  471 
  472         return ((*tp->t_linesw->l_write)(tp, uio, flag));
  473 }
  474 
  475 /*
  476  * Poll routine
  477  */
  478 int
  479 cypoll(dev_t dev, int events, struct lwp *l)
  480 {
  481         struct cy_port *cy;
  482         struct tty *tp;
  483 
  484         cy = CY_PORT(dev);
  485         tp = cy->cy_tty;
  486 
  487         return ((*tp->t_linesw->l_poll)(tp, events, l));
  488 }
  489 
  490 /*
  491  * return tty pointer
  492  */
  493 struct tty *
  494 cytty(dev_t dev)
  495 {
  496         struct cy_port *cy;
  497 
  498         cy = CY_PORT(dev);
  499 
  500         return (cy->cy_tty);
  501 }
  502 
  503 /*
  504  * ioctl routine
  505  */
  506 int
  507 cyioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
  508 {
  509         struct cy_softc *sc;
  510         struct cy_port *cy;
  511         struct tty *tp;
  512         int error;
  513 
  514         cy = CY_PORT(dev);
  515         sc = CY_BOARD(cy);
  516         tp = cy->cy_tty;
  517 
  518         error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l);
  519         if (error != EPASSTHROUGH)
  520                 return error;
  521 
  522         error = ttioctl(tp, cmd, data, flag, l);
  523         if (error != EPASSTHROUGH)
  524                 return error;
  525 
  526         /* XXX should not allow dropping DTR when dialin? */
  527 
  528         switch (cmd) {
  529         case TIOCSBRK:          /* start break */
  530                 SET(cy->cy_flags, CY_F_START_BREAK);
  531                 cy_enable_transmitter(sc, cy);
  532                 break;
  533 
  534         case TIOCCBRK:          /* stop break */
  535                 SET(cy->cy_flags, CY_F_END_BREAK);
  536                 cy_enable_transmitter(sc, cy);
  537                 break;
  538 
  539         case TIOCSDTR:          /* DTR on */
  540                 cy_modem_control(sc, cy, TIOCM_DTR, DMBIS);
  541                 break;
  542 
  543         case TIOCCDTR:          /* DTR off */
  544                 cy_modem_control(sc, cy, TIOCM_DTR, DMBIC);
  545                 break;
  546 
  547         case TIOCMSET:          /* set new modem control line values */
  548                 cy_modem_control(sc, cy, *((int *) data), DMSET);
  549                 break;
  550 
  551         case TIOCMBIS:          /* turn modem control bits on */
  552                 cy_modem_control(sc, cy, *((int *) data), DMBIS);
  553                 break;
  554 
  555         case TIOCMBIC:          /* turn modem control bits off */
  556                 cy_modem_control(sc, cy, *((int *) data), DMBIC);
  557                 break;
  558 
  559         case TIOCMGET:          /* get modem control/status line state */
  560                 *((int *) data) = cy_modem_control(sc, cy, 0, DMGET);
  561                 break;
  562 
  563         case TIOCGFLAGS:
  564                 *((int *) data) = cy->cy_openflags |
  565                         (CY_DIALOUT(dev) ? TIOCFLAG_SOFTCAR : 0);
  566                 break;
  567 
  568         case TIOCSFLAGS:
  569                 error = kauth_authorize_device_tty(l->l_cred,
  570                     KAUTH_DEVICE_TTY_PRIVSET, tp);
  571                 if (error != 0)
  572                         return EPERM;
  573 
  574                 cy->cy_openflags = *((int *) data) &
  575                     (TIOCFLAG_SOFTCAR | TIOCFLAG_CLOCAL |
  576                      TIOCFLAG_CRTSCTS | TIOCFLAG_MDMBUF);
  577                 break;
  578 
  579         default:
  580                 return EPASSTHROUGH;
  581         }
  582 
  583         return 0;
  584 }
  585 
  586 /*
  587  * start output
  588  */
  589 void
  590 cystart(struct tty *tp)
  591 {
  592         struct cy_softc *sc;
  593         struct cy_port *cy;
  594         int s;
  595 
  596         cy = CY_PORT(tp->t_dev);
  597         sc = cy->cy_softc;
  598 
  599         s = spltty();
  600 
  601 #ifdef CY_DEBUG1
  602         cy->cy_start_count++;
  603 #endif
  604 
  605         if (!ISSET(tp->t_state, TS_TTSTOP | TS_TIMEOUT | TS_BUSY)) {
  606                 if (!ttypull(tp))
  607                         goto out;
  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 = 0, obpr = 0, i_clk_opt = 0, o_clk_opt = 0;   /* XXX: GCC */
  651         int s, opt;
  652 
  653         cy = CY_PORT(tp->t_dev);
  654         sc = CY_BOARD(cy);
  655 
  656         if (t->c_ospeed != 0 && cy_speed(t->c_ospeed, &o_clk_opt, &obpr, cy->cy_clock) < 0)
  657                 return EINVAL;
  658 
  659         if (t->c_ispeed != 0 && cy_speed(t->c_ispeed, &i_clk_opt, &ibpr, cy->cy_clock) < 0)
  660                 return EINVAL;
  661 
  662         s = spltty();
  663 
  664         /* hang up the line is ospeed is zero, else turn DTR on */
  665         cy_modem_control(sc, cy, TIOCM_DTR, (t->c_ospeed == 0 ? DMBIC : DMBIS));
  666 
  667         /* channel was selected by the above call to cy_modem_control() */
  668 #if 0
  669         cd_write_reg(sc, cy->cy_chip, CD1400_CAR, port & CD1400_CAR_CHAN);
  670 #endif
  671 
  672         /* set transmit speed */
  673         if (t->c_ospeed != 0) {
  674                 cd_write_reg(sc, cy->cy_chip, CD1400_TCOR, o_clk_opt);
  675                 cd_write_reg(sc, cy->cy_chip, CD1400_TBPR, obpr);
  676         }
  677         /* set receive speed */
  678         if (t->c_ispeed != 0) {
  679                 cd_write_reg(sc, cy->cy_chip, CD1400_RCOR, i_clk_opt);
  680                 cd_write_reg(sc, cy->cy_chip, CD1400_RBPR, ibpr);
  681         }
  682         opt = CD1400_CCR_CMDCHANCTL | CD1400_CCR_XMTEN
  683                 | (ISSET(t->c_cflag, CREAD) ? CD1400_CCR_RCVEN : CD1400_CCR_RCVDIS);
  684 
  685         if (opt != cy->cy_channel_control) {
  686                 cy->cy_channel_control = opt;
  687                 cd1400_channel_cmd(sc, cy, opt);
  688         }
  689         /* compute COR1 contents */
  690         opt = 0;
  691         if (ISSET(t->c_cflag, PARENB)) {
  692                 if (ISSET(t->c_cflag, PARODD))
  693                         opt |= CD1400_COR1_PARODD;
  694                 opt |= CD1400_COR1_PARNORMAL;
  695         }
  696         if (!ISSET(t->c_iflag, INPCK))
  697                 opt |= CD1400_COR1_NOINPCK;     /* no parity checking */
  698 
  699         if (ISSET(t->c_cflag, CSTOPB))
  700                 opt |= CD1400_COR1_STOP2;
  701 
  702         switch (t->c_cflag & CSIZE) {
  703         case CS5:
  704                 opt |= CD1400_COR1_CS5;
  705                 break;
  706 
  707         case CS6:
  708                 opt |= CD1400_COR1_CS6;
  709                 break;
  710 
  711         case CS7:
  712                 opt |= CD1400_COR1_CS7;
  713                 break;
  714 
  715         default:
  716                 opt |= CD1400_COR1_CS8;
  717                 break;
  718         }
  719 
  720         cd_write_reg(sc, cy->cy_chip, CD1400_COR1, opt);
  721 
  722 #ifdef CY_DEBUG
  723         printf("cor1 = 0x%x...", opt);
  724 #endif
  725 
  726         /*
  727          * use the CD1400 automatic CTS flow control if CRTSCTS is set
  728          *
  729          * CD1400_COR2_ETC is used because breaks are generated with
  730          * embedded transmit commands
  731          */
  732         cd_write_reg(sc, cy->cy_chip, CD1400_COR2,
  733                      CD1400_COR2_ETC |
  734                  (ISSET(t->c_cflag, CRTSCTS) ? CD1400_COR2_CCTS_OFLOW : 0));
  735 
  736         cd_write_reg(sc, cy->cy_chip, CD1400_COR3, CY_RX_FIFO_THRESHOLD);
  737 
  738         cd1400_channel_cmd(sc, cy, CD1400_CCR_CMDCORCHG |
  739             CD1400_CCR_COR1 | CD1400_CCR_COR2 | CD1400_CCR_COR3);
  740 
  741         cd_write_reg(sc, cy->cy_chip, CD1400_COR4, CD1400_COR4_PFO_EXCEPTION);
  742         cd_write_reg(sc, cy->cy_chip, CD1400_COR5, 0);
  743 
  744         /*
  745          * set modem change option registers to generate interrupts
  746          * on carrier detect changes.
  747          *
  748          * if hardware RTS handshaking is used
  749          * also set the handshaking threshold.
  750          */
  751         if (cy->cy_clock == CY_CLOCK_60) {
  752            cd_write_reg(sc, cy->cy_chip, CD1400_MCOR1, CD1400_MCOR1_CDzd |
  753               (ISSET(t->c_cflag, CRTSCTS) ? CY_RX_DTR_THRESHOLD : 0));
  754         } else {
  755            cd_write_reg(sc, cy->cy_chip, CD1400_MCOR1, CD1400_MCOR1_CDzd);
  756         }
  757 
  758         cd_write_reg(sc, cy->cy_chip, CD1400_MCOR2, CD1400_MCOR2_CDod);
  759 
  760         /*
  761          * set receive timeout to approx. 2ms
  762          * could use more complex logic here...
  763          * (but is it actually needed or even useful?)
  764          */
  765         cd_write_reg(sc, cy->cy_chip, CD1400_RTPR, 2);
  766 
  767         /*
  768          * should do anything else here?
  769          * XXX check MDMBUF handshaking like in com.c?
  770          */
  771 
  772         splx(s);
  773         return 0;
  774 }
  775 
  776 /*
  777  * set/get modem line status
  778  *
  779  * bits can be: TIOCM_DTR, TIOCM_RTS, TIOCM_CTS, TIOCM_CD, TIOCM_RI, TIOCM_DSR
  780  */
  781 int
  782 cy_modem_control(struct cy_softc *sc, struct cy_port *cy, int bits, int howto)
  783 {
  784         struct tty *tp = cy->cy_tty;
  785         int s, msvr;
  786 
  787         s = spltty();
  788 
  789         /* select channel */
  790         cd_write_reg(sc, cy->cy_chip, CD1400_CAR,
  791             cy->cy_port_num & CD1400_CAR_CHAN);
  792 
  793         /* Does not manipulate RTS if it is used for flow control. */
  794         switch (howto) {
  795         case DMGET:
  796                 bits = 0;
  797                 if (cy->cy_channel_control & CD1400_CCR_RCVEN)
  798                         bits |= TIOCM_LE;
  799                 msvr = cd_read_reg(sc, cy->cy_chip, CD1400_MSVR2);
  800                 if (cy->cy_clock == CY_CLOCK_60) {
  801                         if (cd_read_reg(sc, cy->cy_chip, CD1400_MSVR1) &
  802                                 CD1400_MSVR1_RTS)
  803                                 bits |= TIOCM_DTR;
  804                         if (msvr & CD1400_MSVR2_DTR)
  805                                 bits |= TIOCM_RTS;
  806                 } else {
  807                         if (cd_read_reg(sc, cy->cy_chip, CD1400_MSVR1) &
  808                             CD1400_MSVR1_RTS)
  809                                 bits |= TIOCM_RTS;
  810                         if (msvr & CD1400_MSVR2_DTR)
  811                                 bits |= TIOCM_DTR;
  812                 }
  813                 if (msvr & CD1400_MSVR2_CTS)
  814                         bits |= TIOCM_CTS;
  815                 if (msvr & CD1400_MSVR2_CD)
  816                         bits |= TIOCM_CD;
  817                 /* Not connected on some Cyclom-Y boards? */
  818                 if (msvr & CD1400_MSVR2_DSR)
  819                         bits |= TIOCM_DSR;
  820                 /* Not connected on some Cyclom-8Y boards? */
  821                 if (msvr & CD1400_MSVR2_RI)
  822                         bits |= TIOCM_RI;
  823                 break;
  824 
  825         case DMSET:             /* replace old values with new ones */
  826                 if (cy->cy_clock == CY_CLOCK_60) {
  827                         if (!ISSET(tp->t_cflag, CRTSCTS))
  828                                 cd_write_reg(sc, cy->cy_chip, CD1400_MSVR2,
  829                                    ((bits & TIOCM_RTS) ? CD1400_MSVR2_DTR : 0));
  830                         cd_write_reg(sc, cy->cy_chip, CD1400_MSVR1,
  831                             ((bits & TIOCM_DTR) ? CD1400_MSVR1_RTS : 0));
  832                 } else {
  833                         if (!ISSET(tp->t_cflag, CRTSCTS))
  834                                 cd_write_reg(sc, cy->cy_chip, CD1400_MSVR1,
  835                                    ((bits & TIOCM_RTS) ? CD1400_MSVR1_RTS : 0));
  836                         cd_write_reg(sc, cy->cy_chip, CD1400_MSVR2,
  837                             ((bits & TIOCM_DTR) ? CD1400_MSVR2_DTR : 0));
  838                 }
  839                 break;
  840 
  841         case DMBIS:             /* set bits */
  842                 if (cy->cy_clock == CY_CLOCK_60) {
  843                         if (!ISSET(tp->t_cflag, CRTSCTS) &&
  844                             (bits & TIOCM_RTS) != 0)
  845                                 cd_write_reg(sc, cy->cy_chip, CD1400_MSVR2,
  846                                     CD1400_MSVR2_DTR);
  847                         if (bits & TIOCM_DTR)
  848                                 cd_write_reg(sc, cy->cy_chip, CD1400_MSVR1,
  849                                     CD1400_MSVR1_RTS);
  850                 } else {
  851                         if (!ISSET(tp->t_cflag, CRTSCTS) &&
  852                             (bits & TIOCM_RTS) != 0)
  853                                 cd_write_reg(sc, cy->cy_chip, CD1400_MSVR1,
  854                                     CD1400_MSVR1_RTS);
  855                         if (bits & TIOCM_DTR)
  856                                 cd_write_reg(sc, cy->cy_chip, CD1400_MSVR2,
  857                                     CD1400_MSVR2_DTR);
  858                 }
  859                 break;
  860 
  861         case DMBIC:             /* clear bits */
  862                 if (cy->cy_clock == CY_CLOCK_60) {
  863                         if (!ISSET(tp->t_cflag, CRTSCTS) && (bits & TIOCM_RTS))
  864                                 cd_write_reg(sc, cy->cy_chip, CD1400_MSVR2, 0);
  865                         if (bits & TIOCM_DTR)
  866                                 cd_write_reg(sc, cy->cy_chip, CD1400_MSVR1, 0);
  867                 } else {
  868                         if (!ISSET(tp->t_cflag, CRTSCTS) && (bits & TIOCM_RTS))
  869                                 cd_write_reg(sc, cy->cy_chip, CD1400_MSVR1, 0);
  870                         if (bits & TIOCM_DTR)
  871                                 cd_write_reg(sc, cy->cy_chip, CD1400_MSVR2, 0);
  872                 }
  873                 break;
  874         }
  875         splx(s);
  876         return ((howto == DMGET) ? bits : 0);
  877 }
  878 
  879 /*
  880  * Upper-level handler loop (called from timer interrupt?)
  881  * This routine is common for multiple cards
  882  */
  883 void
  884 cy_poll(void *arg)
  885 {
  886         int card, port;
  887         struct cy_softc *sc;
  888         struct cy_port *cy;
  889         struct tty *tp;
  890         static int counter = 0;
  891 #ifdef CY_DEBUG1
  892         int did_something;
  893 #endif
  894         int s = spltty();
  895 
  896         if (cy_events == 0 && ++counter < 200) {
  897                 splx(s);
  898                 goto out;
  899         }
  900         cy_events = 0;
  901         splx(s);
  902 
  903         for (card = 0; card < cy_cd.cd_ndevs; card++) {
  904                 sc = device_lookup_private(&cy_cd, card);
  905                 if (sc == NULL)
  906                         continue;
  907 
  908 #ifdef CY_DEBUG1
  909                 sc->sc_poll_count1++;
  910                 did_something = 0;
  911 #endif
  912 
  913                 for (port = 0; port < sc->sc_nchannels; port++) {
  914                         cy = &sc->sc_ports[port];
  915                         if ((tp = cy->cy_tty) == NULL || cy->cy_ibuf == NULL ||
  916                             (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0))
  917                                 continue;
  918 
  919                         /*
  920                          * handle received data
  921                          */
  922                         while (cy->cy_ibuf_rd_ptr != cy->cy_ibuf_wr_ptr) {
  923                                 u_char line_stat;
  924                                 int chr;
  925 
  926                                 line_stat = cy->cy_ibuf_rd_ptr[0];
  927                                 chr = cy->cy_ibuf_rd_ptr[1];
  928 
  929                                 if (line_stat &
  930                                     (CD1400_RDSR_BREAK | CD1400_RDSR_FE))
  931                                         chr |= TTY_FE;
  932                                 if (line_stat & CD1400_RDSR_PE)
  933                                         chr |= TTY_PE;
  934 
  935                                 /*
  936                                  * on an overrun error the data is treated as
  937                                  * good just as it should be.
  938                                  */
  939 
  940 #ifdef CY_DEBUG
  941                                 aprint_debug_dev(sc->sc_dev,
  942                                     "port %d ttyinput 0x%x\n",
  943                                     port, chr);
  944 #endif
  945 
  946                                 (*tp->t_linesw->l_rint) (chr, tp);
  947 
  948                                 s = spltty();   /* really necessary? */
  949                                 if ((cy->cy_ibuf_rd_ptr += 2) ==
  950                                     cy->cy_ibuf_end)
  951                                         cy->cy_ibuf_rd_ptr = cy->cy_ibuf;
  952                                 splx(s);
  953 
  954 #ifdef CY_DEBUG1
  955                                 did_something = 1;
  956 #endif
  957                         }
  958 
  959                         /*
  960                          * If we don't have any received data in ibuf and
  961                          * CRTSCTS is on and RTS is turned off, it is time to
  962                          * turn RTS back on
  963                          */
  964                         if (ISSET(tp->t_cflag, CRTSCTS)) {
  965                                 /*
  966                                  * we can't use cy_modem_control() here as it
  967                                  * doesn't change RTS if RTSCTS is on
  968                                  */
  969                                 cd_write_reg(sc, cy->cy_chip, CD1400_CAR,
  970                                     port & CD1400_CAR_CHAN);
  971 
  972                                 if (cy->cy_clock == CY_CLOCK_60) {
  973                                   if ((cd_read_reg(sc, cy->cy_chip,
  974                                     CD1400_MSVR2) & CD1400_MSVR2_DTR) == 0) {
  975                                         cd_write_reg(sc, cy->cy_chip,
  976                                         CD1400_MSVR2,CD1400_MSVR2_DTR);
  977 #ifdef CY_DEBUG1
  978                                         did_something = 1;
  979 #endif
  980                                   }
  981                                 } else {
  982                                   if ((cd_read_reg(sc, cy->cy_chip,
  983                                     CD1400_MSVR1) & CD1400_MSVR1_RTS) == 0) {
  984                                         cd_write_reg(sc, cy->cy_chip,
  985                                         CD1400_MSVR1,CD1400_MSVR1_RTS);
  986 #ifdef CY_DEBUG1
  987                                         did_something = 1;
  988 #endif
  989                                   }
  990                                 }
  991                         }
  992 
  993                         /*
  994                          * handle carrier changes
  995                          */
  996                         s = spltty();
  997                         if (ISSET(cy->cy_flags, CY_F_CARRIER_CHANGED)) {
  998                                 int             carrier;
  999 
 1000                                 CLR(cy->cy_flags, CY_F_CARRIER_CHANGED);
 1001                                 splx(s);
 1002 
 1003                                 carrier = ((cy->cy_carrier_stat &
 1004                                     CD1400_MSVR2_CD) != 0);
 1005 
 1006 #ifdef CY_DEBUG
 1007                                 printf("cy_poll: carrier change "
 1008                                     "(card %d, port %d, carrier %d)\n",
 1009                                     card, port, carrier);
 1010 #endif
 1011                                 if (CY_DIALOUT(tp->t_dev) == 0 &&
 1012                                     !(*tp->t_linesw->l_modem)(tp, carrier))
 1013                                         cy_modem_control(sc, cy,
 1014                                             TIOCM_DTR, DMBIC);
 1015 
 1016 #ifdef CY_DEBUG1
 1017                                 did_something = 1;
 1018 #endif
 1019                         } else
 1020                                 splx(s);
 1021 
 1022                         s = spltty();
 1023                         if (ISSET(cy->cy_flags, CY_F_START)) {
 1024                                 CLR(cy->cy_flags, CY_F_START);
 1025                                 splx(s);
 1026 
 1027                                 (*tp->t_linesw->l_start) (tp);
 1028 
 1029 #ifdef CY_DEBUG1
 1030                                 did_something = 1;
 1031 #endif
 1032                         } else
 1033                                 splx(s);
 1034 
 1035                         /* could move this to even upper level... */
 1036                         if (cy->cy_fifo_overruns) {
 1037                                 cy->cy_fifo_overruns = 0;
 1038                                 /*
 1039                                  * doesn't report overrun count, but
 1040                                  * shouldn't really matter
 1041                                  */
 1042                                 log(LOG_WARNING, "%s: port %d fifo overrun\n",
 1043                                     device_xname(sc->sc_dev), port);
 1044                         }
 1045                         if (cy->cy_ibuf_overruns) {
 1046                                 cy->cy_ibuf_overruns = 0;
 1047                                 log(LOG_WARNING, "%s: port %d ibuf overrun\n",
 1048                                     device_xname(sc->sc_dev), port);
 1049                         }
 1050                 }               /* for(port...) */
 1051 #ifdef CY_DEBUG1
 1052                 if (did_something && counter >= 200)
 1053                         sc->sc_poll_count2++;
 1054 #endif
 1055         } /* for(card...) */
 1056 
 1057         counter = 0;
 1058 
 1059 out:
 1060         callout_reset(&cy_poll_callout, 1, cy_poll, NULL);
 1061 }
 1062 
 1063 /*
 1064  * hardware interrupt routine
 1065  */
 1066 int
 1067 cy_intr(void *arg)
 1068 {
 1069         struct cy_softc *sc = arg;
 1070         struct cy_port *cy;
 1071         int cy_chip, stat;
 1072         int int_serviced = 0;
 1073 
 1074         /*
 1075          * Check interrupt status of each CD1400 chip on this card
 1076          * (multiple cards cannot share the same interrupt)
 1077          */
 1078         for (cy_chip = 0; cy_chip < sc->sc_nchips; cy_chip++) {
 1079 
 1080                 stat = cd_read_reg(sc, cy_chip, CD1400_SVRR);
 1081                 if (stat == 0)
 1082                         continue;
 1083 
 1084                 if (ISSET(stat, CD1400_SVRR_RXRDY)) {
 1085                         u_char save_car, save_rir, serv_type;
 1086                         u_char line_stat, recv_data, n_chars;
 1087                         u_char *buf_p;
 1088 
 1089                         save_rir = cd_read_reg(sc, cy_chip, CD1400_RIR);
 1090                         save_car = cd_read_reg(sc, cy_chip, CD1400_CAR);
 1091                         /* enter rx service */
 1092                         cd_write_reg(sc, cy_chip, CD1400_CAR, save_rir);
 1093 
 1094                         serv_type = cd_read_reg(sc, cy_chip, CD1400_RIVR);
 1095                         cy = &sc->sc_ports[serv_type >> 3];
 1096 
 1097 #ifdef CY_DEBUG1
 1098                         cy->cy_rx_int_count++;
 1099 #endif
 1100 
 1101                         buf_p = cy->cy_ibuf_wr_ptr;
 1102 
 1103                         if (ISSET(serv_type, CD1400_RIVR_EXCEPTION)) {
 1104                                 line_stat = cd_read_reg(sc, cy->cy_chip,
 1105                                     CD1400_RDSR);
 1106                                 recv_data = cd_read_reg(sc, cy->cy_chip,
 1107                                     CD1400_RDSR);
 1108 
 1109                                 if (cy->cy_tty == NULL ||
 1110                                     !ISSET(cy->cy_tty->t_state, TS_ISOPEN))
 1111                                         goto end_rx_serv;
 1112 
 1113 #ifdef CY_DEBUG
 1114                                 aprint_debug_dev(
 1115                                     sc->sc_dev,
 1116                                     "port %d recv exception, "
 1117                                     "line_stat 0x%x, char 0x%x\n",
 1118                                     cy->cy_port_num, line_stat, recv_data);
 1119 #endif
 1120                                 if (ISSET(line_stat, CD1400_RDSR_OE))
 1121                                         cy->cy_fifo_overruns++;
 1122 
 1123                                 *buf_p++ = line_stat;
 1124                                 *buf_p++ = recv_data;
 1125                                 if (buf_p == cy->cy_ibuf_end)
 1126                                         buf_p = cy->cy_ibuf;
 1127 
 1128                                 if (buf_p == cy->cy_ibuf_rd_ptr) {
 1129                                         if (buf_p == cy->cy_ibuf)
 1130                                                 buf_p = cy->cy_ibuf_end;
 1131                                         buf_p -= 2;
 1132                                         cy->cy_ibuf_overruns++;
 1133                                 }
 1134                                 cy_events = 1;
 1135                         } else {/* no exception, received data OK */
 1136                                 n_chars = cd_read_reg(sc, cy->cy_chip,
 1137                                     CD1400_RDCR);
 1138 
 1139                                 /* If no tty or not open, discard data */
 1140                                 if (cy->cy_tty == NULL ||
 1141                                     !ISSET(cy->cy_tty->t_state, TS_ISOPEN)) {
 1142                                         while (n_chars--)
 1143                                                 (void)cd_read_reg(sc,
 1144                                                     cy->cy_chip, CD1400_RDSR);
 1145                                         goto end_rx_serv;
 1146                                 }
 1147 
 1148 #ifdef CY_DEBUG
 1149                                 aprint_debug_dev(sc->sc_dev,
 1150                                     "port %d receive ok %d chars\n",
 1151                                     cy->cy_port_num, n_chars);
 1152 #endif
 1153                                 while (n_chars--) {
 1154                                         *buf_p++ = 0;   /* status: OK */
 1155                                         /* data byte */
 1156                                         *buf_p++ = cd_read_reg(sc,
 1157                                             cy->cy_chip, CD1400_RDSR);
 1158                                         if (buf_p == cy->cy_ibuf_end)
 1159                                                 buf_p = cy->cy_ibuf;
 1160                                         if (buf_p == cy->cy_ibuf_rd_ptr) {
 1161                                                 if (buf_p == cy->cy_ibuf)
 1162                                                         buf_p = cy->cy_ibuf_end;
 1163                                                 buf_p -= 2;
 1164                                                 cy->cy_ibuf_overruns++;
 1165                                                 break;
 1166                                         }
 1167                                 }
 1168                                 cy_events = 1;
 1169                         }
 1170 
 1171                         cy->cy_ibuf_wr_ptr = buf_p;
 1172 
 1173                         /* RTS handshaking for incoming data */
 1174                         if (ISSET(cy->cy_tty->t_cflag, CRTSCTS)) {
 1175                                 int bf, msvr;
 1176 
 1177                                 bf = buf_p - cy->cy_ibuf_rd_ptr;
 1178                                 if (bf < 0)
 1179                                         bf += CY_IBUF_SIZE;
 1180 
 1181                                 if (bf > (CY_IBUF_SIZE / 2)) {
 1182                                         /* turn RTS off */
 1183                                         if (cy->cy_clock == CY_CLOCK_60)
 1184                                                 msvr = CD1400_MSVR2;
 1185                                         else
 1186                                                 msvr = CD1400_MSVR1;
 1187                                         cd_write_reg(sc, cy->cy_chip, msvr, 0);
 1188                                 }
 1189                         }
 1190 
 1191         end_rx_serv:
 1192                         /* terminate service context */
 1193                         cd_write_reg(sc, cy->cy_chip, CD1400_RIR,
 1194                                      save_rir & 0x3f);
 1195                         cd_write_reg(sc, cy->cy_chip, CD1400_CAR, save_car);
 1196                         int_serviced = 1;
 1197                 } /* if (rx_service...) */
 1198                 if (ISSET(stat, CD1400_SVRR_MDMCH)) {
 1199                         u_char save_car, save_mir, serv_type, modem_stat;
 1200 
 1201                         save_mir = cd_read_reg(sc, cy_chip, CD1400_MIR);
 1202                         save_car = cd_read_reg(sc, cy_chip, CD1400_CAR);
 1203                         /* enter modem service */
 1204                         cd_write_reg(sc, cy_chip, CD1400_CAR, save_mir);
 1205 
 1206                         serv_type = cd_read_reg(sc, cy_chip, CD1400_MIVR);
 1207                         cy = &sc->sc_ports[serv_type >> 3];
 1208 
 1209 #ifdef CY_DEBUG1
 1210                         cy->cy_modem_int_count++;
 1211 #endif
 1212 
 1213                         modem_stat = cd_read_reg(sc, cy->cy_chip, CD1400_MSVR2);
 1214 
 1215 #ifdef CY_DEBUG
 1216                         aprint_debug_dev(sc->sc_dev,
 1217                             "port %d modem line change, new stat 0x%x\n",
 1218                             cy->cy_port_num, modem_stat);
 1219 #endif
 1220                         if (ISSET((cy->cy_carrier_stat ^ modem_stat), CD1400_MSVR2_CD)) {
 1221                                 SET(cy->cy_flags, CY_F_CARRIER_CHANGED);
 1222                                 cy_events = 1;
 1223                         }
 1224                         cy->cy_carrier_stat = modem_stat;
 1225 
 1226                         /* terminate service context */
 1227                         cd_write_reg(sc, cy->cy_chip, CD1400_MIR, save_mir & 0x3f);
 1228                         cd_write_reg(sc, cy->cy_chip, CD1400_CAR, save_car);
 1229                         int_serviced = 1;
 1230                 } /* if (modem_service...) */
 1231                 if (ISSET(stat, CD1400_SVRR_TXRDY)) {
 1232                         u_char          save_car, save_tir, serv_type,
 1233                                         count, ch;
 1234                         struct tty     *tp;
 1235 
 1236                         save_tir = cd_read_reg(sc, cy_chip, CD1400_TIR);
 1237                         save_car = cd_read_reg(sc, cy_chip, CD1400_CAR);
 1238                         /* enter tx service */
 1239                         cd_write_reg(sc, cy_chip, CD1400_CAR, save_tir);
 1240 
 1241                         serv_type = cd_read_reg(sc, cy_chip, CD1400_TIVR);
 1242                         cy = &sc->sc_ports[serv_type >> 3];
 1243 
 1244 #ifdef CY_DEBUG1
 1245                         cy->cy_tx_int_count++;
 1246 #endif
 1247 #ifdef CY_DEBUG
 1248                         aprint_debug_dev(sc->sc_dev, "port %d tx service\n",
 1249                             cy->cy_port_num);
 1250 #endif
 1251 
 1252                         /* stop transmitting if no tty or CY_F_STOP set */
 1253                         tp = cy->cy_tty;
 1254                         if (tp == NULL || ISSET(cy->cy_flags, CY_F_STOP))
 1255                                 goto txdone;
 1256 
 1257                         count = 0;
 1258                         if (ISSET(cy->cy_flags, CY_F_SEND_NUL)) {
 1259                                 cd_write_reg(sc, cy->cy_chip, CD1400_TDR, 0);
 1260                                 cd_write_reg(sc, cy->cy_chip, CD1400_TDR, 0);
 1261                                 count += 2;
 1262                                 CLR(cy->cy_flags, CY_F_SEND_NUL);
 1263                         }
 1264                         if (tp->t_outq.c_cc > 0) {
 1265                                 SET(tp->t_state, TS_BUSY);
 1266                                 while (tp->t_outq.c_cc > 0 &&
 1267                                     count < CD1400_TX_FIFO_SIZE) {
 1268                                         ch = getc(&tp->t_outq);
 1269                                         /*
 1270                                          * remember to double NUL characters
 1271                                          * because embedded transmit commands
 1272                                          * are enabled
 1273                                          */
 1274                                         if (ch == 0) {
 1275                                                 if (count >= CD1400_TX_FIFO_SIZE - 2) {
 1276                                                         SET(cy->cy_flags, CY_F_SEND_NUL);
 1277                                                         break;
 1278                                                 }
 1279                                                 cd_write_reg(sc, cy->cy_chip,
 1280                                                     CD1400_TDR, ch);
 1281                                                 count++;
 1282                                         }
 1283                                         cd_write_reg(sc, cy->cy_chip,
 1284                                             CD1400_TDR, ch);
 1285                                         count++;
 1286                                 }
 1287                         } else {
 1288                                 /*
 1289                                  * no data to send -- check if we should
 1290                                  * start/stop a break
 1291                                  */
 1292                                 /*
 1293                                  * XXX does this cause too much delay before
 1294                                  * breaks?
 1295                                  */
 1296                                 if (ISSET(cy->cy_flags, CY_F_START_BREAK)) {
 1297                                         cd_write_reg(sc, cy->cy_chip,
 1298                                             CD1400_TDR, 0);
 1299                                         cd_write_reg(sc, cy->cy_chip,
 1300                                             CD1400_TDR, 0x81);
 1301                                         CLR(cy->cy_flags, CY_F_START_BREAK);
 1302                                 }
 1303                                 if (ISSET(cy->cy_flags, CY_F_END_BREAK)) {
 1304                                         cd_write_reg(sc, cy->cy_chip,
 1305                                             CD1400_TDR, 0);
 1306                                         cd_write_reg(sc, cy->cy_chip,
 1307                                             CD1400_TDR, 0x83);
 1308                                         CLR(cy->cy_flags, CY_F_END_BREAK);
 1309                                 }
 1310                         }
 1311 
 1312                         if (tp->t_outq.c_cc == 0) {
 1313                 txdone:
 1314                                 /*
 1315                                  * No data to send or requested to stop.
 1316                                  * Disable transmit interrupt
 1317                                  */
 1318                                 cd_write_reg(sc, cy->cy_chip, CD1400_SRER,
 1319                                      cd_read_reg(sc, cy->cy_chip, CD1400_SRER)
 1320                                      & ~CD1400_SRER_TXRDY);
 1321                                 CLR(cy->cy_flags, CY_F_STOP);
 1322                                 CLR(tp->t_state, TS_BUSY);
 1323                         }
 1324                         if (tp->t_outq.c_cc <= tp->t_lowat) {
 1325                                 SET(cy->cy_flags, CY_F_START);
 1326                                 cy_events = 1;
 1327                         }
 1328                         /* terminate service context */
 1329                         cd_write_reg(sc, cy->cy_chip, CD1400_TIR, save_tir & 0x3f);
 1330                         cd_write_reg(sc, cy->cy_chip, CD1400_CAR, save_car);
 1331                         int_serviced = 1;
 1332                 }               /* if (tx_service...) */
 1333         }                       /* for(...all CD1400s on a card) */
 1334 
 1335         /* ensure an edge for next interrupt */
 1336         bus_space_write_1(sc->sc_memt, sc->sc_bsh,
 1337                         CY_CLEAR_INTR << sc->sc_bustype, 0);
 1338         return int_serviced;
 1339 }
 1340 
 1341 /*
 1342  * subroutine to enable CD1400 transmitter
 1343  */
 1344 void
 1345 cy_enable_transmitter(struct cy_softc *sc, struct cy_port *cy)
 1346 {
 1347         int s = spltty();
 1348         cd_write_reg(sc, cy->cy_chip, CD1400_CAR,
 1349             cy->cy_port_num & CD1400_CAR_CHAN);
 1350         cd_write_reg(sc, cy->cy_chip, CD1400_SRER,
 1351             cd_read_reg(sc, cy->cy_chip, CD1400_SRER) | CD1400_SRER_TXRDY);
 1352         splx(s);
 1353 }
 1354 
 1355 /*
 1356  * Execute a CD1400 channel command
 1357  */
 1358 void
 1359 cd1400_channel_cmd(struct cy_softc *sc, struct cy_port *cy, int cmd)
 1360 {
 1361         u_int waitcnt = 5 * 8 * 1024;   /* approx 5 ms */
 1362 
 1363 #ifdef CY_DEBUG
 1364         printf("c1400_channel_cmd cy %p command 0x%x\n", cy, cmd);
 1365 #endif
 1366 
 1367         /* wait until cd1400 is ready to process a new command */
 1368         while (cd_read_reg(sc, cy->cy_chip, CD1400_CCR) != 0 && waitcnt-- > 0);
 1369 
 1370         if (waitcnt == 0)
 1371                 log(LOG_ERR, "%s: channel command timeout\n",
 1372                     device_xname(sc->sc_dev));
 1373 
 1374         cd_write_reg(sc, cy->cy_chip, CD1400_CCR, cmd);
 1375 }
 1376 
 1377 /*
 1378  * Compute clock option register and baud rate register values
 1379  * for a given speed. Return 0 on success, -1 on failure.
 1380  *
 1381  * The error between requested and actual speed seems
 1382  * to be well within allowed limits (less than 3%)
 1383  * with every speed value between 50 and 150000 bps.
 1384  */
 1385 int
 1386 cy_speed(speed_t speed, int *cor, int *bpr, int cy_clock)
 1387 {
 1388         int c, co, br;
 1389 
 1390         if (speed < 50 || speed > 150000)
 1391                 return -1;
 1392 
 1393         for (c = 0, co = 8; co <= 2048; co <<= 2, c++) {
 1394                 br = (cy_clock + (co * speed) / 2) / (co * speed);
 1395                 if (br < 0x100) {
 1396                         *bpr = br;
 1397                         *cor = c;
 1398                         return 0;
 1399                 }
 1400         }
 1401 
 1402         return -1;
 1403 }

Cache object: 57da125f5599a0163a48b9f5399fd977


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