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/sx/sx.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 /*-
    2  * Device tsfsdriver for Specialix I/O8+ multiport serial card.
    3  *
    4  * Copyright 2003 Frank Mayhar <frank@exit.com>
    5  *
    6  * Derived from the "si" driver by Peter Wemm <peter@netplex.com.au>, using
    7  * lots of information from the Linux "specialix" driver by Roger Wolff
    8  * <R.E.Wolff@BitWizard.nl> and from the Intel CD1865 "Intelligent Eight-
    9  * Channel Communications Controller" datasheet.  Roger was also nice
   10  * enough to answer numerous questions about stuff specific to the I/O8+
   11  * not covered by the CD1865 datasheet.
   12  *
   13  * Redistribution and use in source and binary forms, with or without
   14  * modification, are permitted provided that the following conditions
   15  * are met:
   16  * 1. Redistributions of source code must retain the above copyright
   17  *    notices, this list of conditions and the following disclaimer.
   18  * 2. Redistributions in binary form must reproduce the above copyright
   19  *    notices, this list of conditions and the foljxowing disclaimer in the
   20  *    documentation and/or other materials provided with the distribution.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY EXPRESS OR IMPLIED
   23  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
   24  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
   25  * NO EVENT SHALL THE AUTHORS BE LIABLE.
   26  *
   27  * $FreeBSD$
   28  */
   29 
   30 
   31 /* Main tty driver routines for the Specialix I/O8+ device driver. */
   32 
   33 #include "opt_compat.h"
   34 #include "opt_debug_sx.h"
   35 
   36 #include <sys/param.h>
   37 #include <sys/systm.h>
   38 #ifndef BURN_BRIDGES
   39 #if defined(COMPAT_43)
   40 #include <sys/ioctl_compat.h>
   41 #endif
   42 #endif
   43 #include <sys/tty.h>
   44 #include <sys/proc.h>
   45 #include <sys/conf.h>
   46 #include <sys/fcntl.h>
   47 #include <sys/dkstat.h>
   48 #include <sys/kernel.h>
   49 #include <sys/malloc.h>
   50 #include <sys/sysctl.h>
   51 #include <sys/bus.h>
   52 #include <machine/bus.h>
   53 #include <sys/rman.h>
   54 #include <machine/resource.h>
   55 
   56 #include <machine/clock.h>
   57 
   58 #include <vm/vm.h>
   59 #include <vm/pmap.h>
   60 
   61 #include <machine/stdarg.h>
   62 
   63 #include <dev/sx/cd1865.h>
   64 #include <dev/sx/sxvar.h>
   65 #include <dev/sx/sx.h>
   66 #include <dev/sx/sx_util.h>
   67 
   68 #define SX_BROKEN_CTS
   69 
   70 enum sx_mctl { GET, SET, BIS, BIC };
   71 
   72 static int sx_modem(struct sx_softc *, struct sx_port *, enum sx_mctl, int);
   73 static void sx_write_enable(struct sx_port *, int);
   74 static void sx_start(struct tty *);
   75 static void sx_stop(struct tty *, int);
   76 static void sxhardclose(struct sx_port *pp);
   77 static void sxdtrwakeup(void *chan);
   78 static void sx_shutdown_chan(struct sx_port *);
   79 
   80 #ifdef SX_DEBUG
   81 static char     *sx_mctl2str(enum sx_mctl cmd);
   82 #endif
   83 
   84 static int      sxparam(struct tty *, struct termios *);
   85 
   86 static void sx_modem_state(struct sx_softc *sc, struct sx_port *pp, int card);
   87 
   88 static  d_open_t        sxopen;
   89 static  d_close_t       sxclose;
   90 static  d_write_t       sxwrite;
   91 static  d_ioctl_t       sxioctl;
   92 
   93 #define CDEV_MAJOR      185
   94 static struct cdevsw sx_cdevsw = {
   95         .d_version =    D_VERSION,
   96         .d_open =       sxopen,
   97         .d_close =      sxclose,
   98         .d_write =      sxwrite,
   99         .d_ioctl =      sxioctl,
  100         .d_name =       "sx",
  101         .d_flags =      D_TTY | D_NEEDGIANT,
  102 };
  103 
  104 static int sx_debug = 0; /* DBG_ALL|DBG_PRINTF|DBG_MODEM|DBG_IOCTL|DBG_PARAM;e */
  105 SYSCTL_INT(_machdep, OID_AUTO, sx_debug, CTLFLAG_RW, &sx_debug, 0, "");
  106 
  107 static struct tty *sx__tty;
  108 
  109 static int sx_numunits;
  110 
  111 devclass_t sx_devclass;
  112 
  113 /*
  114  * See sx.h for these values.
  115  */
  116 static struct speedtab bdrates[] = {
  117         { B75,          CLK75, },
  118         { B110,         CLK110, },
  119         { B150,         CLK150, },
  120         { B300,         CLK300, },
  121         { B600,         CLK600, },
  122         { B1200,        CLK1200, },
  123         { B2400,        CLK2400, },
  124         { B4800,        CLK4800, },
  125         { B9600,        CLK9600, },
  126         { B19200,       CLK19200, },
  127         { B38400,       CLK38400, },
  128         { B57600,       CLK57600, },
  129         { B115200,      CLK115200, },
  130         { -1,           -1 },
  131 };
  132 
  133 
  134 /*
  135  * Approximate (rounded) character per second rates.  Translated at card
  136  * initialization time to characters per clock tick.
  137  */
  138 static int done_chartimes = 0;
  139 static struct speedtab chartimes[] = {
  140         { B75,          8, },
  141         { B110,         11, },
  142         { B150,         15, },
  143         { B300,         30, },
  144         { B600,         60, },
  145         { B1200,        120, },
  146         { B2400,        240, },
  147         { B4800,        480, },
  148         { B9600,        960, },
  149         { B19200,       1920, },
  150         { B38400,       3840, },
  151         { B57600,       5760, },
  152         { B115200,      11520, },
  153         { -1,           -1 },
  154 };
  155 static volatile int in_interrupt = 0;   /* Inside interrupt handler?          */
  156 
  157 static int sx_flags;                    /* The flags we were configured with. */
  158 SYSCTL_INT(_machdep, OID_AUTO, sx_flags, CTLFLAG_RW, &sx_flags, 0, "");
  159 
  160 #ifdef POLL
  161 static int sx_pollrate;                 /* in addition to irq */
  162 static int sx_realpoll = 0;             /* poll HW on timer */
  163 
  164 SYSCTL_INT(_machdep, OID_AUTO, sx_pollrate, CTLFLAG_RW, &sx_pollrate, 0, "");
  165 SYSCTL_INT(_machdep, OID_AUTO, sx_realpoll, CTLFLAG_RW, &sx_realpoll, 0, "");
  166 
  167 static int init_finished = 0;
  168 static void sx_poll(void *);
  169 #endif
  170 
  171 /*
  172  * sxattach()
  173  *      Initialize and attach the card, initialize the driver.
  174  *
  175  * Description:
  176  *      This is the standard attach routine.  It initializes the I/O8+
  177  *      card, identifies the chip on that card, then allocates and
  178  *      initializes the various data structures used by the driver
  179  *      itself.
  180  */
  181 int
  182 sxattach(
  183         device_t dev)
  184 {
  185         int unit;
  186         struct sx_softc *sc;
  187         struct tty *tp;
  188         struct speedtab *spt;
  189         int chip, x, y;
  190         char rev;
  191         int error;
  192 
  193         sc = device_get_softc(dev);
  194         unit = device_get_unit(dev);
  195         sx_flags = device_get_flags(dev);
  196 
  197         if (sx_numunits < unit + 1)
  198                 sx_numunits = unit + 1;
  199 
  200         DPRINT((0, DBG_AUTOBOOT, "sx%d: sxattach\n", unit));
  201 
  202         /* Reset the CD1865.  */
  203         if ((error = sx_init_cd1865(sc, unit)) != 0) {
  204                 return(error);
  205         }
  206 
  207         /*
  208          * ID the chip:
  209          *
  210          * Chip           revcode   pkgtype
  211          *                GFRCR     SRCR bit 7
  212          * CD180 rev B    0x81      0
  213          * CD180 rev C    0x82      0
  214          * CD1864 rev A   0x82      1
  215          * CD1865 rev A   0x83      1  -- Do not use!!! Does not work. 
  216          * CD1865 rev B   0x84      1
  217          *       -- Thanks to Gwen Wang, Cirrus Logic (via Roger Wollf).
  218          */
  219         switch (sx_cd1865_in(sc, CD1865_GFRCR)) {
  220                 case 0x82:
  221                         chip = 1864;
  222                         rev = 'A';
  223                         break;
  224                 case 0x83:
  225                         chip = 1865;
  226                         rev = 'A';
  227                         break;
  228                 case 0x84:
  229                         chip = 1865;
  230                         rev = 'B';
  231                         break;
  232                 case 0x85:
  233                         chip = 1865;
  234                         rev = 'C';
  235                         break;
  236                 default:
  237                         chip = -1;
  238                         rev = '\0';
  239                         break;
  240         }
  241 
  242         if (bootverbose && chip != -1)
  243                 printf("sx%d: Specialix I/O8+ CD%d processor rev %c\n",
  244                                                         unit, chip, rev);
  245         DPRINT((0, DBG_AUTOBOOT, "sx%d: GFRCR 0x%02x\n",
  246                                         unit, sx_cd1865_in(sc, CD1865_GFRCR)));
  247 #ifdef POLL
  248         if (sx_pollrate == 0) {
  249                 sx_pollrate = POLLHZ;           /* in addition to irq */
  250 #ifdef REALPOLL
  251                 sx_realpoll = 1;                /* scan always */
  252 #endif
  253         }
  254 #endif
  255         sc->sc_ports = (struct sx_port *)malloc(
  256                                            sizeof(struct sx_port) * SX_NUMCHANS,
  257                                            M_DEVBUF,
  258                                            M_NOWAIT);
  259         if (sc->sc_ports == NULL) {
  260                 printf("sx%d:  No memory for sx_port structs!\n", unit);
  261                 return(EINVAL);
  262         }
  263         bzero(sc->sc_ports, sizeof(struct sx_port) * SX_NUMCHANS);
  264         /*
  265          * Allocate tty structures for the channels.
  266          */
  267         tp = (struct tty *)malloc(sizeof(struct tty) * SX_NUMCHANS,
  268                                   M_DEVBUF,
  269                                   M_NOWAIT);
  270         if (tp == NULL) {
  271                 free(sc->sc_ports, M_DEVBUF);
  272                 printf("sx%d:  No memory for tty structs!\n", unit);
  273                 return(EINVAL);
  274         }
  275         bzero(tp, sizeof(struct tty) * SX_NUMCHANS);
  276         sx__tty = tp;
  277         /*
  278          * Initialize the channels.
  279          */
  280         for (x = 0; x < SX_NUMCHANS; x++) {
  281                 sc->sc_ports[x].sp_chan = x;
  282                 sc->sc_ports[x].sp_tty = tp++;
  283                 sc->sc_ports[x].sp_state = 0;   /* internal flag */
  284                 sc->sc_ports[x].sp_iin.c_iflag = TTYDEF_IFLAG;
  285                 sc->sc_ports[x].sp_iin.c_oflag = TTYDEF_OFLAG;
  286                 sc->sc_ports[x].sp_iin.c_cflag = TTYDEF_CFLAG;
  287                 sc->sc_ports[x].sp_iin.c_lflag = TTYDEF_LFLAG;
  288                 termioschars(&sc->sc_ports[x].sp_iin);
  289                 sc->sc_ports[x].sp_iin.c_ispeed = TTYDEF_SPEED;;
  290                 sc->sc_ports[x].sp_iin.c_ospeed = TTYDEF_SPEED;;
  291                 sc->sc_ports[x].sp_iout = sc->sc_ports[x].sp_iin;
  292         }
  293         if (done_chartimes == 0) {
  294                 for (spt = chartimes ; spt->sp_speed != -1; spt++) {
  295                         if ((spt->sp_code /= hz) == 0)
  296                                 spt->sp_code = 1;
  297                 }
  298                 done_chartimes = 1;
  299         }
  300         /*
  301          * Set up the known devices.
  302          */
  303         y = unit * (1 << SX_CARDSHIFT);
  304         for (x = 0; x < SX_NUMCHANS; x++) {
  305                 register int num;
  306 
  307                                         /* DTR/RTS -> RTS devices.            */
  308                 num = x + y;
  309                 make_dev(&sx_cdevsw, x, 0, 0, 0600, "ttyG%02d", x+y);
  310                 make_dev(&sx_cdevsw, x + 0x00080, 0, 0, 0600, "cuaG%02d", num);
  311                 make_dev(&sx_cdevsw, x + 0x10000, 0, 0, 0600, "ttyiG%02d", num);
  312                 make_dev(&sx_cdevsw, x + 0x10080, 0, 0, 0600, "cuaiG%02d", num);
  313                 make_dev(&sx_cdevsw, x + 0x20000, 0, 0, 0600, "ttylG%02d", num);
  314                 make_dev(&sx_cdevsw, x + 0x20080, 0, 0, 0600, "cualG%02d", num);
  315                                         /* DTR/RTS -> DTR devices.            */
  316                 num += SX_NUMCHANS;
  317                 make_dev(&sx_cdevsw, x + 0x00008, 0, 0, 0600, "ttyG%02d", num);
  318                 make_dev(&sx_cdevsw, x + 0x00088, 0, 0, 0600, "cuaG%02d", num);
  319                 make_dev(&sx_cdevsw, x + 0x10008, 0, 0, 0600, "ttyiG%02d", num);
  320                 make_dev(&sx_cdevsw, x + 0x10088, 0, 0, 0600, "cuaiG%02d", num);
  321                 make_dev(&sx_cdevsw, x + 0x20008, 0, 0, 0600, "ttylG%02d", num);
  322                 make_dev(&sx_cdevsw, x + 0x20088, 0, 0, 0600, "cualG%02d", num);
  323         }
  324         return (0);
  325 }
  326 
  327 /*
  328  * sxopen()
  329  *      Open a port on behalf of a user.
  330  *
  331  * Description:
  332  *      This is the standard open routine.
  333  */
  334 static int
  335 sxopen(
  336         struct cdev *dev,
  337         int flag,
  338         int mode,
  339         d_thread_t *p)
  340 {
  341         int oldspl, error;
  342         int card, chan;
  343         struct sx_softc *sc;
  344         struct tty *tp;
  345         struct sx_port *pp;
  346         int mynor = minor(dev);
  347 
  348         card = SX_MINOR2CARD(mynor);
  349         if ((sc = devclass_get_softc(sx_devclass, card)) == NULL)
  350                 return (ENXIO);
  351         chan = SX_MINOR2CHAN(mynor);
  352         if (chan >= SX_NUMCHANS) {
  353                 DPRINT((0, DBG_OPEN|DBG_FAIL, "sx%d: nchans %d\n",
  354                         card, SX_NUMCHANS));
  355                 return(ENXIO);
  356         }
  357 #ifdef  POLL
  358         /*
  359          * We've now got a device, so start the poller.
  360          */
  361         if (init_finished == 0) {
  362                 timeout(sx_poll, (caddr_t)0L, sx_pollrate);
  363                 init_finished = 1;
  364         }
  365 #endif
  366         /* initial/lock device */
  367         if (DEV_IS_STATE(mynor)) {
  368                 return(0);
  369         }
  370         pp = &(sc->sc_ports[chan]);
  371         tp = pp->sp_tty;                /* the "real" tty */
  372         dev->si_tty = tp;
  373         DPRINT((pp, DBG_ENTRY|DBG_OPEN, "sxopen(%s,%x,%x,%x)\n",
  374                 devtoname(dev), flag, mode, p));
  375 
  376         oldspl = spltty();              /* Keep others out */
  377         error = 0;
  378         /*
  379          * The minor also indicates whether the DTR pin on this port is wired
  380          * as DTR or as RTS.  Default is zero, wired as RTS.
  381          */
  382         if (DEV_DTRPIN(mynor))
  383                 pp->sp_state |= SX_SS_DTRPIN;
  384         else
  385                 pp->sp_state &= ~SX_SS_DTRPIN;
  386         pp->sp_state &= SX_SS_XMIT;     /* Turn off "transmitting" flag.      */
  387 open_top:
  388         /*
  389          * If DTR is off and we actually do have a DTR pin, sleep waiting for
  390          * it to assert.
  391          */
  392         while (pp->sp_state & SX_SS_DTR_OFF && SX_DTRPIN(pp)) {
  393                 error = tsleep(&tp->t_dtr_wait, TTIPRI|PCATCH, "sxdtr", 0);
  394                 if (error != 0)
  395                         goto out;
  396         }
  397 
  398         if (tp->t_state & TS_ISOPEN) {
  399                 /*
  400                  * The device is open, so everything has been initialized.
  401                  * Handle conflicts.
  402                  */
  403                 if (DEV_IS_CALLOUT(mynor)) {
  404                         if (!pp->sp_active_out) {
  405                                 error = EBUSY;
  406                                 goto out;
  407                         }
  408                 }
  409                 else {
  410                         if (pp->sp_active_out) {
  411                                 if (flag & O_NONBLOCK) {
  412                                         error = EBUSY;
  413                                         goto out;
  414                                 }
  415                                 error = tsleep(&pp->sp_active_out,
  416                                                TTIPRI|PCATCH,
  417                                                "sxbi", 0);
  418                                 if (error != 0)
  419                                         goto out;
  420                                 goto open_top;
  421                         }
  422                 }
  423                 if (tp->t_state & TS_XCLUDE && suser(p)) {
  424                         DPRINT((pp, DBG_OPEN|DBG_FAIL,
  425                                 "already open and EXCLUSIVE set\n"));
  426                         error = EBUSY;
  427                         goto out;
  428                 }
  429         } else {
  430                 /*
  431                  * The device isn't open, so there are no conflicts.
  432                  * Initialize it. Avoid sleep... :-)
  433                  */
  434                 DPRINT((pp, DBG_OPEN, "first open\n"));
  435                 tp->t_oproc = sx_start;
  436                 tp->t_stop = sx_stop;
  437                 tp->t_param = sxparam;
  438                 tp->t_dev = dev;
  439                 tp->t_termios = mynor & SX_CALLOUT_MASK
  440                                 ? pp->sp_iout : pp->sp_iin;
  441 
  442                 (void)sx_modem(sc, pp, SET, TIOCM_DTR|TIOCM_RTS);
  443 
  444                 ++pp->sp_wopeners;      /* in case of sleep in sxparam */
  445 
  446                 error = sxparam(tp, &tp->t_termios);
  447 
  448                 --pp->sp_wopeners;
  449                 if (error != 0)
  450                         goto out;
  451                 /* XXX: we should goto_top if sxparam slept */
  452 
  453                 /* set initial DCD state */
  454                 if (DEV_IS_CALLOUT(mynor) ||
  455                                         (sx_modem(sc, pp, GET, 0) & TIOCM_CD)) {
  456                         ttyld_modem(tp, 1);
  457                 }
  458         }
  459         /* whoops! we beat the close! */
  460         if (pp->sp_state & SX_SS_CLOSING) {
  461                 /* try and stop it from proceeding to bash the hardware */
  462                 pp->sp_state &= ~SX_SS_CLOSING;
  463         }
  464         /*
  465          * Wait for DCD if necessary
  466          */
  467         if (!(tp->t_state & TS_CARR_ON) && !DEV_IS_CALLOUT(mynor) &&
  468             !(tp->t_cflag & CLOCAL) && !(flag & O_NONBLOCK)) {
  469                 ++pp->sp_wopeners;
  470                 DPRINT((pp, DBG_OPEN, "sleeping for carrier\n"));
  471                 error = tsleep(TSA_CARR_ON(tp), TTIPRI|PCATCH, "sxdcd", 0);
  472                 --pp->sp_wopeners;
  473                 if (error != 0)
  474                         goto out;
  475                 goto open_top;
  476         }
  477 
  478         error = ttyld_open(tp, dev);
  479         ttyldoptim(tp);
  480         if (tp->t_state & TS_ISOPEN && DEV_IS_CALLOUT(mynor))
  481                 pp->sp_active_out = TRUE;
  482 
  483         pp->sp_state |= SX_SS_OPEN;     /* made it! */
  484 
  485 out:
  486         splx(oldspl);
  487 
  488         DPRINT((pp, DBG_OPEN, "leaving sxopen\n"));
  489 
  490         if (!(tp->t_state & TS_ISOPEN) && pp->sp_wopeners == 0)
  491                 sxhardclose(pp);
  492 
  493         return(error);
  494 }
  495 
  496 /*
  497  * sxclose()
  498  *      Close a port for a user.
  499  *
  500  * Description:
  501  *      This is the standard close routine.
  502  */
  503 static int
  504 sxclose(
  505         struct cdev *dev,
  506         int flag,
  507         int mode,
  508         d_thread_t *p)
  509 {
  510         struct sx_port *pp;
  511         struct tty *tp;
  512         int oldspl;
  513         int error = 0;
  514         int mynor = minor(dev);
  515 
  516         if (DEV_IS_SPECIAL(mynor))
  517                 return(0);
  518 
  519         oldspl = spltty();
  520 
  521         pp = MINOR2PP(mynor);
  522         tp = pp->sp_tty;
  523 
  524         DPRINT((pp, DBG_ENTRY|DBG_CLOSE, "sxclose(%s,%x,%x,%x) sp_state:%x\n",
  525                 devtoname(dev), flag, mode, p, pp->sp_state));
  526 
  527         /* did we sleep and lose a race? */
  528         if (pp->sp_state & SX_SS_CLOSING) {
  529                 /* error = ESOMETING? */
  530                 goto out;
  531         }
  532 
  533         /* begin race detection.. */
  534         pp->sp_state |= SX_SS_CLOSING;
  535 
  536         sx_write_enable(pp, 0);         /* block writes for ttywait() */
  537 
  538         /* THIS MAY SLEEP IN TTYWAIT!!! */
  539         ttyld_close(tp, flag);
  540 
  541         sx_write_enable(pp, 1);
  542 
  543         /* did we sleep and somebody started another open? */
  544         if (!(pp->sp_state & SX_SS_CLOSING)) {
  545                 /* error = ESOMETING? */
  546                 goto out;
  547         }
  548         /* ok. we are now still on the right track.. nuke the hardware */
  549 
  550         sxhardclose(pp);
  551         tty_close(tp);
  552         pp->sp_state &= ~SX_SS_OPEN;
  553 
  554 out:
  555         DPRINT((pp, DBG_CLOSE|DBG_EXIT, "sxclose out\n"));
  556         splx(oldspl);
  557         return(error);
  558 }
  559 
  560 /*
  561  * sxhardclose()
  562  *      Do hard-close processing.
  563  *
  564  * Description:
  565  *      Called on last close.  Handle DTR and RTS, do cleanup.  If we have
  566  *      pending output in the FIFO, wait for it to clear before we shut down
  567  *      the hardware.
  568  */
  569 static void
  570 sxhardclose(
  571         struct sx_port *pp)
  572 {
  573         struct sx_softc *sc;
  574         struct tty *tp;
  575         int oldspl, dcd;
  576 
  577         oldspl = spltty();
  578 
  579         DPRINT((pp, DBG_CLOSE, "sxhardclose sp_state:%x\n", pp->sp_state));
  580         tp = pp->sp_tty;
  581         sc = PP2SC(pp);
  582         dcd = sx_modem(sc, pp, GET, 0) & TIOCM_CD;
  583         if (tp->t_cflag & HUPCL ||
  584             (!pp->sp_active_out && !dcd && !(pp->sp_iin.c_cflag && CLOCAL)) ||
  585             !(tp->t_state & TS_ISOPEN)) {
  586                 disable_intr();
  587                 sx_cd1865_out(sc, CD1865_CAR, pp->sp_chan);
  588                 if (sx_cd1865_in(sc, CD1865_IER|SX_EI) & CD1865_IER_TXRDY) {
  589                         sx_cd1865_bic(sc, CD1865_IER, CD1865_IER_TXRDY);
  590                         sx_cd1865_bis(sc, CD1865_IER, CD1865_IER_TXEMPTY);
  591                         enable_intr();
  592                         splx(oldspl);
  593                         ttysleep(tp, (caddr_t)pp,
  594                                  TTOPRI|PCATCH, "sxclose", tp->t_timeout);
  595                         oldspl = spltty();
  596                 }
  597                 else {
  598                         enable_intr();
  599                 }
  600                 (void)sx_modem(sc, pp, BIC, TIOCM_DTR|TIOCM_RTS);
  601                 /*
  602                  * If we should hold DTR off for a bit and we actually have a
  603                  * DTR pin to hold down, schedule sxdtrwakeup().
  604                  */
  605                 if (tp->t_dtr_wait != 0 && SX_DTRPIN(pp)) {
  606                         timeout(sxdtrwakeup, pp, tp->t_dtr_wait);
  607                         pp->sp_state |= SX_SS_DTR_OFF;
  608                 }
  609 
  610         }
  611         (void)sx_shutdown_chan(pp);     /* Turn off the hardware.             */
  612         pp->sp_active_out = FALSE;
  613         wakeup((caddr_t)&pp->sp_active_out);
  614         wakeup(TSA_CARR_ON(tp));
  615 
  616         splx(oldspl);
  617 }
  618 
  619 
  620 /*
  621  * called at splsoftclock()...
  622  */
  623 static void
  624 sxdtrwakeup(void *chan)
  625 {
  626         struct sx_port *pp;
  627         int oldspl;
  628 
  629         oldspl = spltty();
  630         pp = (struct sx_port *)chan;
  631         pp->sp_state &= ~SX_SS_DTR_OFF;
  632         wakeup(&pp->sp_tty->t_dtr_wait);
  633         splx(oldspl);
  634 }
  635 
  636 /*
  637  * sxwrite()
  638  *      Handle a write to a port on the I/O8+.
  639  *
  640  * Description:
  641  *      This just hands processing off to the line discipline.
  642  */
  643 static int
  644 sxwrite(
  645         struct cdev *dev,
  646         struct uio *uio,
  647         int flag)
  648 {
  649         struct sx_softc *sc;
  650         struct sx_port *pp;
  651         struct tty *tp;
  652         int error = 0;
  653         int mynor = minor(dev);
  654         int oldspl;
  655 
  656         pp = MINOR2PP(mynor);
  657         sc = PP2SC(pp);
  658         tp = pp->sp_tty;
  659         DPRINT((pp, DBG_WRITE, "sxwrite %s %x %x\n", devtoname(dev), uio, flag));
  660 
  661         oldspl = spltty();
  662         /*
  663          * If writes are currently blocked, wait on the "real" tty
  664          */
  665         while (pp->sp_state & SX_SS_BLOCKWRITE) {
  666                 pp->sp_state |= SX_SS_WAITWRITE;
  667                 DPRINT((pp, DBG_WRITE, "sxwrite sleep on SX_SS_BLOCKWRITE\n"));
  668                 if ((error = ttysleep(tp,
  669                                       (caddr_t)pp,
  670                                       TTOPRI|PCATCH,
  671                                       "sxwrite",
  672                                       tp->t_timeout))) {
  673                         if (error == EWOULDBLOCK)
  674                                 error = EIO;
  675                         goto out;
  676                 }
  677         }
  678         error = ttyld_write(tp, uio, flag);
  679 out:    splx(oldspl);
  680         DPRINT((pp, DBG_WRITE, "sxwrite out\n"));
  681         return (error);
  682 }
  683 
  684 /*
  685  * sxioctl()
  686  *      Handle ioctl() processing.
  687  *
  688  * Description:
  689  *      This is the standard serial ioctl() routine.  It was cribbed almost
  690  *      entirely from the si(4) driver.  Thanks, Peter.
  691  */
  692 static int
  693 sxioctl(
  694         struct cdev *dev,
  695         u_long cmd,
  696         caddr_t data,
  697         int flag,
  698         d_thread_t *p)
  699 {
  700         struct sx_softc *sc;
  701         struct sx_port *pp;
  702         struct tty *tp;
  703         int error;
  704         int mynor = minor(dev);
  705         int oldspl;
  706         int blocked = 0;
  707 #ifndef BURN_BRIDGES
  708 #if defined(COMPAT_43)
  709         u_long oldcmd;        
  710         
  711         struct termios term;
  712 #endif
  713 #endif
  714 
  715         pp = MINOR2PP(mynor);
  716         tp = pp->sp_tty;
  717 
  718         DPRINT((pp, DBG_ENTRY|DBG_IOCTL, "sxioctl %s %lx %x %x\n",
  719                 devtoname(dev), cmd, data, flag));
  720         if (DEV_IS_STATE(mynor)) {
  721                 struct termios *ct;
  722 
  723                 switch (mynor & SX_STATE_MASK) {
  724                         case SX_INIT_STATE_MASK:
  725                                 ct = DEV_IS_CALLOUT(mynor) ? &pp->sp_iout :
  726                                                              &pp->sp_iin;
  727                                 break;
  728                         case SX_LOCK_STATE_MASK:
  729                                 ct = DEV_IS_CALLOUT(mynor) ? &pp->sp_lout :
  730                                                              &pp->sp_lin;
  731                                 break;
  732                         default:
  733                                 return(ENODEV);
  734                 }
  735                 switch (cmd) {
  736                         case TIOCSETA:
  737                                 error = suser(p);
  738                                 if (error != 0)
  739                                         return(error);
  740                                 *ct = *(struct termios *)data;
  741                                 return(0);
  742                         case TIOCGETA:
  743                                 *(struct termios *)data = *ct;
  744                                 return(0);
  745                         case TIOCGETD:
  746                                 *(int *)data = TTYDISC;
  747                                 return(0);
  748                         case TIOCGWINSZ:
  749                                 bzero(data, sizeof(struct winsize));
  750                                 return(0);
  751                         default:
  752                                 return(ENOTTY);
  753                 }
  754         }
  755         /*
  756          * Do the old-style ioctl compat routines...
  757          */
  758 #ifndef BURN_BRIDGES
  759 #if defined(COMPAT_43)
  760         term = tp->t_termios;
  761         oldcmd = cmd;
  762         error = ttsetcompat(tp, &cmd, data, &term);
  763         if (error != 0)
  764                 return(error);
  765         if (cmd != oldcmd)
  766                 data = (caddr_t)&term;
  767 #endif
  768 #endif
  769         /*
  770          * Do the initial / lock state business
  771          */
  772         if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) {
  773                 int     cc;
  774                 struct termios *dt = (struct termios *)data;
  775                 struct termios *lt = mynor & SX_CALLOUT_MASK
  776                                      ? &pp->sp_lout : &pp->sp_lin;
  777 
  778                 dt->c_iflag = (tp->t_iflag & lt->c_iflag) |
  779                         (dt->c_iflag & ~lt->c_iflag);
  780                 dt->c_oflag = (tp->t_oflag & lt->c_oflag) |
  781                         (dt->c_oflag & ~lt->c_oflag);
  782                 dt->c_cflag = (tp->t_cflag & lt->c_cflag) |
  783                         (dt->c_cflag & ~lt->c_cflag);
  784                 dt->c_lflag = (tp->t_lflag & lt->c_lflag) |
  785                         (dt->c_lflag & ~lt->c_lflag);
  786                 for (cc = 0; cc < NCCS; ++cc)
  787                         if (lt->c_cc[cc] != 0)
  788                                 dt->c_cc[cc] = tp->t_cc[cc];
  789                 if (lt->c_ispeed != 0)
  790                         dt->c_ispeed = tp->t_ispeed;
  791                 if (lt->c_ospeed != 0)
  792                         dt->c_ospeed = tp->t_ospeed;
  793         }
  794 
  795         /*
  796          * Block user-level writes to give the ttywait()
  797          * a chance to completely drain for commands
  798          * that require the port to be in a quiescent state.
  799          */
  800         switch (cmd) {
  801         case TIOCSETAW:
  802         case TIOCSETAF:
  803         case TIOCDRAIN:
  804 #ifndef BURN_BRIDGES
  805 #ifdef COMPAT_43
  806         case TIOCSETP:
  807 #endif
  808 #endif
  809                 blocked++;      /* block writes for ttywait() and sxparam() */
  810                 sx_write_enable(pp, 0);
  811         }
  812 
  813         error = ttyioctl(dev, cmd, data, flag, p);
  814         ttyldoptim(tp);
  815         if (error != ENOTTY)
  816                 goto out;
  817 
  818         oldspl = spltty();
  819 
  820         sc = PP2SC(pp);                 /* Need this to do I/O to the card.   */
  821         error = 0;
  822         switch (cmd) {
  823                 case TIOCSBRK:          /* Send BREAK.                        */
  824                         DPRINT((pp, DBG_IOCTL, "sxioctl %s BRK S\n",
  825                                 devtoname(dev)));
  826                         /*
  827                          * If there's already a break state change pending or
  828                          * we're already sending a break, just ignore this.
  829                          * Otherwise, just set our flag and start the
  830                          * transmitter.
  831                          */
  832                         if (!SX_DOBRK(pp) && !SX_BREAK(pp)) {
  833                                 pp->sp_state |= SX_SS_DOBRK;
  834                                 sx_start(tp);
  835                         }
  836                         break;
  837                 case TIOCCBRK:          /* Stop sending BREAK.                */
  838                         DPRINT((pp, DBG_IOCTL, "sxioctl %s BRK E\n",
  839                                 devtoname(dev)));
  840                         /*
  841                          * If a break is going, set our flag so we turn it off
  842                          * when we can, then kick the transmitter.  If a break
  843                          * isn't going and the flag is set, turn it off.
  844                          */
  845                         if (SX_BREAK(pp)) {
  846                                 pp->sp_state |= SX_SS_DOBRK;
  847                                 sx_start(tp);
  848                         }
  849                         else {
  850                                 if (SX_DOBRK(pp))
  851                                         pp->sp_state &= SX_SS_DOBRK;
  852                         }
  853                         break;
  854                 case TIOCSDTR:          /* Assert DTR.                        */
  855                         DPRINT((pp, DBG_IOCTL, "sxioctl %s +DTR\n",
  856                                 devtoname(dev)));
  857                         if (SX_DTRPIN(pp)) /* Using DTR?                      */
  858                                 (void)sx_modem(sc, pp, SET, TIOCM_DTR);
  859                         break;
  860                 case TIOCCDTR:          /* Clear DTR.                         */
  861                         DPRINT((pp, DBG_IOCTL, "sxioctl(%s) -DTR\n",
  862                                 devtoname(dev)));
  863                         if (SX_DTRPIN(pp)) /* Using DTR?                      */
  864                                 (void)sx_modem(sc, pp, SET, 0);
  865                         break;
  866                 case TIOCMSET:          /* Force all modem signals.           */
  867                         DPRINT((pp, DBG_IOCTL, "sxioctl %s =%x\n",
  868                                 devtoname(dev), *(int *)data));
  869                         (void)sx_modem(sc, pp, SET, *(int *)data);
  870                         break;
  871                 case TIOCMBIS:          /* Set (some) modem signals.          */
  872                         DPRINT((pp, DBG_IOCTL, "sxioctl %s +%x\n",
  873                                 devtoname(dev), *(int *)data));
  874                         (void)sx_modem(sc, pp, BIS, *(int *)data);
  875                         break;
  876                 case TIOCMBIC:          /* Clear (some) modem signals.        */
  877                         DPRINT((pp, DBG_IOCTL, "sxioctl %s -%x\n",
  878                                 devtoname(dev), *(int *)data));
  879                         (void)sx_modem(sc, pp, BIC, *(int *)data);
  880                         break;
  881                 case TIOCMGET:          /* Get state of modem signals.        */
  882                         *(int *)data = sx_modem(sc, pp, GET, 0);
  883                         DPRINT((pp, DBG_IOCTL, "sxioctl(%s) got signals 0x%x\n",
  884                                 devtoname(dev), *(int *)data));
  885                         break;
  886                 default:
  887                         error = ENOTTY;
  888         }
  889         splx(oldspl);
  890 
  891 out:    DPRINT((pp, DBG_IOCTL|DBG_EXIT, "sxioctl out %d\n", error));
  892         if (blocked)
  893                 sx_write_enable(pp, 1);
  894         return(error);
  895 }
  896 
  897 /*
  898  * sxparam()
  899  *      Configure line parameters.
  900  *
  901  * Description:
  902  *      Configure the bitrate, wordsize, flow control and various other serial
  903  *      port parameters for this line.
  904  *
  905  * Environment:
  906  *      Called at spltty(); this may sleep, does not flush nor wait for drain,
  907  *      nor block writes.  Caller must arrange this if it's important..
  908  */
  909 static int
  910 sxparam(
  911         struct tty *tp,
  912         struct termios *t)
  913 {
  914         struct sx_softc *sc;
  915         struct sx_port *pp = TP2PP(tp);
  916         int oldspl, cflag, iflag, oflag, lflag;
  917         int error = 0;
  918         int ispd = 0;
  919         int ospd = 0;
  920         unsigned char val, cor1, cor2, cor3, ier;
  921 
  922         sc = PP2SC(pp);
  923         DPRINT((pp, DBG_ENTRY|DBG_PARAM, "sxparam %x/%x\n", tp, t));
  924         cflag = t->c_cflag;
  925         iflag = t->c_iflag;
  926         oflag = t->c_oflag;
  927         lflag = t->c_lflag;
  928         DPRINT((pp, DBG_PARAM, "OF 0x%x CF 0x%x IF 0x%x LF 0x%x\n",
  929                 oflag, cflag, iflag, lflag));
  930 
  931         /* If the port isn't hung up... */
  932         if (t->c_ospeed != 0) {
  933                 /* Convert bit rate to hardware divisor values. */
  934                 ospd = ttspeedtab(t->c_ospeed, bdrates);
  935                 ispd = t->c_ispeed ? ttspeedtab(t->c_ispeed, bdrates) : ospd;
  936                 /* We only allow standard bit rates. */
  937                 if (ospd < 0 || ispd < 0)
  938                         return(EINVAL);
  939         }
  940         oldspl = spltty();              /* Block other activity.              */
  941         cor1 = 0;
  942         cor2 = 0;
  943         cor3 = 0;
  944         ier = CD1865_IER_RXD | CD1865_IER_CD;
  945 #ifdef notyet
  946         /* We don't yet handle this stuff. */
  947         val = 0;
  948         if (iflag & IGNBRK)             /* Breaks */
  949                 val |= BR_IGN;
  950         if (iflag & BRKINT)             /* Interrupt on break? */
  951                 val |= BR_INT;
  952         if (iflag & PARMRK)             /* Parity mark? */
  953                 val |= BR_PARMRK;
  954 #endif /* notyet */
  955         /*
  956          * If the device isn't hung up, set the serial port bitrates.
  957          */
  958         if (t->c_ospeed != 0) {
  959                 disable_intr();
  960                 sx_cd1865_out(sc, CD1865_CAR|SX_EI, pp->sp_chan);
  961                 sx_cd1865_out(sc, CD1865_RBPRH|SX_EI, (ispd >> 8) & 0xff);
  962                 sx_cd1865_out(sc, CD1865_RBPRL|SX_EI, ispd & 0xff);
  963                 sx_cd1865_out(sc, CD1865_TBPRH|SX_EI, (ospd >> 8) & 0xff);
  964                 sx_cd1865_out(sc, CD1865_TBPRL|SX_EI, ospd & 0xff);
  965                 enable_intr();
  966         }
  967         if (cflag & CSTOPB)             /* Two stop bits?                     */
  968                 cor1 |= CD1865_COR1_2SB; /* Yep.                              */
  969         /*
  970          * Parity settings.
  971          */
  972         val = 0;
  973         if (cflag & PARENB) {           /* Parity enabled?                    */
  974                 val = CD1865_COR1_NORMPAR; /* Turn on normal parity handling. */
  975                 if (cflag & PARODD)     /* Odd Parity?                        */
  976                         val |= CD1865_COR1_ODDP; /* Turn it on.               */
  977         }
  978         else
  979                 val = CD1865_COR1_NOPAR; /* Turn off parity detection.        */
  980         cor1 |= val;
  981         if (iflag & IGNPAR)             /* Ignore chars with parity errors?   */
  982                 cor1 |= CD1865_COR1_IGNORE;
  983         /*
  984          * Set word length.
  985          */
  986         if ((cflag & CS8) == CS8)
  987                 val = CD1865_COR1_8BITS;
  988         else if ((cflag & CS7) == CS7)
  989                 val = CD1865_COR1_7BITS;
  990         else if ((cflag & CS6) == CS6)
  991                 val = CD1865_COR1_6BITS;
  992         else
  993                 val = CD1865_COR1_5BITS;
  994         cor1 |= val;
  995         /*
  996          * Enable hardware RTS/CTS flow control.  We can handle output flow
  997          * control at any time, since we have a dedicated CTS pin.
  998          * Unfortunately, though, the RTS pin is really the DTR pin.  This
  999          * means that we can't ever use the automatic input flow control of
 1000          * the CD1865 and that we can only use the pin for input flow
 1001          * control when it's wired as RTS.
 1002          */
 1003         if (cflag & CCTS_OFLOW) {       /* Output flow control...             */
 1004                 pp->sp_state |= SX_SS_OFLOW;
 1005 #ifdef SX_BROKEN_CTS
 1006                 disable_intr();
 1007                 sx_cd1865_out(sc, CD1865_CAR|SX_EI, pp->sp_chan);
 1008                 if (sx_cd1865_in(sc, CD1865_MSVR|SX_EI) & CD1865_MSVR_CTS) {
 1009                         enable_intr();
 1010                         pp->sp_state |= SX_SS_OSTOP;
 1011                         sx_write_enable(pp, 0); /* Block writes.              */
 1012                 }
 1013                 else {
 1014                         enable_intr();
 1015                 }
 1016                 ier |= CD1865_IER_CTS;
 1017 #else /* SX_BROKEN_CTS */
 1018                 cor2 |= CD1865_COR2_CTSAE; /* Set CTS automatic enable.       */
 1019 #endif /* SX_BROKEN_CTS */
 1020         }
 1021         else {
 1022                 pp->sp_state &= ~SX_SS_OFLOW;
 1023         }
 1024         if (cflag & CRTS_IFLOW && !SX_DTRPIN(pp)) /* Input flow control.      */
 1025                 pp->sp_state |= SX_SS_IFLOW;
 1026         else
 1027                 pp->sp_state &= ~SX_SS_IFLOW;
 1028         if (iflag & IXANY)
 1029                 cor2 |= CD1865_COR2_IXM;        /* Any character is XON.      */
 1030         if (iflag & IXOFF) {
 1031                 cor2 |= CD1865_COR2_TXIBE;      /* Enable inband flow control.*/
 1032                 cor3 |= CD1865_COR3_FCT | CD1865_COR3_SCDE; /* Hide from host */
 1033                 disable_intr();
 1034                 sx_cd1865_out(sc, CD1865_CAR|SX_EI, pp->sp_chan); /* Sel chan.*/
 1035                 sx_cd1865_out(sc, CD1865_SCHR1|SX_EI, t->c_cc[VSTART]);
 1036                 sx_cd1865_out(sc, CD1865_SCHR2|SX_EI, t->c_cc[VSTOP]);
 1037                 sx_cd1865_out(sc, CD1865_SCHR3|SX_EI, t->c_cc[VSTART]);
 1038                 sx_cd1865_out(sc, CD1865_SCHR4|SX_EI, t->c_cc[VSTOP]);
 1039                 enable_intr();
 1040         }
 1041         /*
 1042          * All set, now program the hardware.
 1043          */
 1044         disable_intr();
 1045         sx_cd1865_out(sc, CD1865_CAR|SX_EI, pp->sp_chan); /* Select channel.  */
 1046         sx_cd1865_out(sc, CD1865_COR1|SX_EI, cor1);
 1047         sx_cd1865_out(sc, CD1865_COR2|SX_EI, cor2);
 1048         sx_cd1865_out(sc, CD1865_COR3|SX_EI, cor3);
 1049         sx_cd1865_wait_CCR(sc, SX_EI);
 1050         sx_cd1865_out(sc, CD1865_CCR|SX_EI,
 1051                       CD1865_CCR_CORCHG1|CD1865_CCR_CORCHG2|CD1865_CCR_CORCHG3);
 1052         sx_cd1865_wait_CCR(sc, SX_EI);
 1053         enable_intr();
 1054         if (SX_DTRPIN(pp))
 1055                 val = TIOCM_DTR;
 1056         else
 1057                 val = TIOCM_RTS;
 1058         if (t->c_ospeed == 0)           /* Clear DTR/RTS if we're hung up.    */
 1059                 (void)sx_modem(sc, pp, BIC, val);
 1060         else                            /* If we were hung up, we may have to */
 1061                 (void)sx_modem(sc, pp, BIS, val); /* re-enable the signal.    */
 1062         /*
 1063          * Last, enable the receiver and transmitter and turn on the
 1064          * interrupts we need (receive, carrier-detect and possibly CTS
 1065          * (iff we're built with SX_BROKEN_CTS and CCTS_OFLOW is on).
 1066          */
 1067         disable_intr();
 1068         sx_cd1865_out(sc, CD1865_CAR|SX_EI, pp->sp_chan); /* Select channel.  */
 1069         sx_cd1865_wait_CCR(sc, SX_EI);
 1070         sx_cd1865_out(sc, CD1865_CCR|SX_EI, CD1865_CCR_RXEN|CD1865_CCR_TXEN);
 1071         sx_cd1865_wait_CCR(sc, SX_EI);
 1072         sx_cd1865_out(sc, CD1865_IER|SX_EI, ier);
 1073         enable_intr();
 1074         DPRINT((pp, DBG_PARAM, "sxparam out\n"));
 1075         splx(oldspl);
 1076         return(error);
 1077 }
 1078 
 1079 /*
 1080  * sx_write_enable()
 1081  *      Enable/disable writes to a card channel.
 1082  *
 1083  * Description:
 1084  *      Set or clear the SX_SS_BLOCKWRITE flag in sp_state to block or allow
 1085  *      writes to a serial port on the card.  When we enable writes, we
 1086  *      wake up anyone sleeping on SX_SS_WAITWRITE for this channel.
 1087  *
 1088  * Parameters:
 1089  *      flag    0 - disable writes.
 1090  *              1 - enable writes.
 1091  */
 1092 static void
 1093 sx_write_enable(
 1094         struct sx_port *pp,
 1095         int flag)
 1096 {
 1097         int oldspl;
 1098 
 1099         oldspl = spltty();              /* Keep interrupts out.               */
 1100         if (flag) {                     /* Enable writes to the channel?      */
 1101                 pp->sp_state &= ~SX_SS_BLOCKWRITE; /* Clear our flag.         */
 1102                 if (pp->sp_state & SX_SS_WAITWRITE) { /* Sleepers?            */
 1103                         pp->sp_state &= ~SX_SS_WAITWRITE; /* Clear their flag */
 1104                         wakeup((caddr_t)pp); /* & wake them up.               */
 1105                 }
 1106         }
 1107         else                            /* Disabling writes.                  */
 1108                 pp->sp_state |= SX_SS_BLOCKWRITE; /* Set our flag.            */
 1109         splx(oldspl);
 1110 }
 1111 
 1112 /*
 1113  * sx_shutdown_chan()
 1114  *      Shut down a channel on the I/O8+.
 1115  *
 1116  * Description:
 1117  *      This does all hardware shutdown processing for a channel on the I/O8+.
 1118  *      It is called from sxhardclose().  We reset the channel and turn off
 1119  *      interrupts.
 1120  */
 1121 static void
 1122 sx_shutdown_chan(
 1123         struct sx_port *pp)
 1124 {
 1125         int s;
 1126         struct sx_softc *sc;
 1127 
 1128         DPRINT((pp, DBG_ENTRY, "sx_shutdown_chan %x %x\n", pp, pp->sp_state));
 1129         sc = PP2SC(pp);
 1130         s = spltty();
 1131         disable_intr();
 1132         sx_cd1865_out(sc, CD1865_CAR, pp->sp_chan); /* Select channel.        */
 1133         sx_cd1865_wait_CCR(sc, 0);      /* Wait for any commands to complete. */
 1134         sx_cd1865_out(sc, CD1865_CCR, CD1865_CCR_SOFTRESET); /* Reset chan.   */
 1135         sx_cd1865_wait_CCR(sc, 0);
 1136         sx_cd1865_out(sc, CD1865_IER, 0); /* Disable all interrupts.          */
 1137         enable_intr();
 1138         splx(s);
 1139 }
 1140 
 1141 /*
 1142  * sx_modem()
 1143  *      Set/Get state of modem control lines.
 1144  *
 1145  * Description:
 1146  *      Get and set the state of the modem control lines that we have available
 1147  *      on the I/O8+.  The only lines we are guaranteed to have are CD and CTS.
 1148  *      We have DTR if the "DTR/RTS pin is DTR" flag is set, otherwise we have
 1149  *      RTS through the DTR pin.
 1150  */
 1151 static int
 1152 sx_modem(
 1153         struct sx_softc *sc,
 1154         struct sx_port *pp,
 1155         enum sx_mctl cmd,
 1156         int bits)
 1157 {
 1158         int s, x;
 1159 
 1160         DPRINT((pp, DBG_ENTRY|DBG_MODEM, "sx_modem %x/%s/%x\n",
 1161                 pp, sx_mctl2str(cmd), bits));
 1162         s = spltty();                   /* Block interrupts.                  */
 1163         disable_intr();
 1164         sx_cd1865_out(sc, CD1865_CAR|SX_EI, pp->sp_chan); /* Select our port. */
 1165         x = sx_cd1865_in(sc, CD1865_MSVR|SX_EI); /* Get the current signals.  */
 1166 #ifdef SX_DEBUG
 1167         DPRINT((pp, DBG_MODEM, "sx_modem MSVR 0x%x, CCSR %x GIVR %x SRSR %x\n",
 1168                 x, sx_cd1865_in(sc, CD1865_CCSR|SX_EI),
 1169                 sx_cd1865_in(sc, CD1865_GIVR|SX_EI),
 1170                 sx_cd1865_in(sc, CD1865_SRSR|SX_EI)));
 1171 #endif
 1172         enable_intr();                  /* Allow other interrupts.            */
 1173         switch (cmd) {
 1174                 case GET:
 1175                         bits = TIOCM_LE;
 1176                         if ((x & CD1865_MSVR_CD) == 0)
 1177                                 bits |= TIOCM_CD;
 1178                         if ((x & CD1865_MSVR_CTS) == 0)
 1179                                 bits |= TIOCM_CTS;
 1180                         if ((x & CD1865_MSVR_DTR) == 0) {
 1181                                 if (SX_DTRPIN(pp)) /* Odd pin is DTR?         */
 1182                                         bits |= TIOCM_DTR; /* Report DTR.     */
 1183                                 else               /* Odd pin is RTS.         */
 1184                                         bits |= TIOCM_RTS; /* Report RTS.     */
 1185                         }
 1186                         splx(s);
 1187                         return(bits);
 1188                 case SET:
 1189                         x = CD1865_MSVR_OFF;
 1190                         if ((bits & TIOCM_RTS && !SX_DTRPIN(pp)) ||
 1191                             (bits & TIOCM_DTR && SX_DTRPIN(pp)))
 1192                                 x &= ~CD1865_MSVR_DTR;
 1193                         break;
 1194                 case BIS:
 1195                         if ((bits & TIOCM_RTS && !SX_DTRPIN(pp)) ||
 1196                             (bits & TIOCM_DTR && SX_DTRPIN(pp)))
 1197                                 x &= ~CD1865_MSVR_DTR;
 1198                         break;
 1199                 case BIC:
 1200                         if ((bits & TIOCM_RTS && !SX_DTRPIN(pp)) ||
 1201                             (bits & TIOCM_DTR && SX_DTRPIN(pp)))
 1202                                 x |= CD1865_MSVR_DTR;
 1203                         break;
 1204         }
 1205         DPRINT((pp, DBG_MODEM, "sx_modem MSVR=0x%x\n", x));
 1206         disable_intr();
 1207         /*
 1208          * Set the new modem signals.
 1209          */
 1210         sx_cd1865_out(sc, CD1865_CAR|SX_EI, pp->sp_chan);
 1211         sx_cd1865_out(sc, CD1865_MSVR|SX_EI, x);
 1212         enable_intr();
 1213         splx(s);
 1214         return 0;
 1215 }
 1216 
 1217 #ifdef POLL
 1218 
 1219 /*
 1220  * sx_poll()
 1221  *      Poller to catch missed interrupts.
 1222  *
 1223  * Description:
 1224  *      Only used if we're complied with POLL.  This routine is called every
 1225  *      sx_pollrate ticks to check for missed interrupts.  We check each card
 1226  *      in the system; if we missed an interrupt, we complain about each one
 1227  *      and later call sx_intr() to handle them.
 1228  */
 1229 static void
 1230 sx_poll(
 1231         void *dummy)
 1232 {
 1233         struct sx_softc *sc;
 1234         struct sx_port *pp;
 1235         int card, lost, oldspl, chan;
 1236 
 1237         DPRINT((0, DBG_POLL, "sx_poll\n"));
 1238         oldspl = spltty();
 1239         if (in_interrupt)
 1240                 goto out;
 1241         lost = 0;
 1242         for (card = 0; card < sx_numunits; card++) {
 1243                 sc = devclass_get_softc(sx_devclass, card);
 1244                 if (sc == NULL)
 1245                         continue;
 1246                 if (sx_cd1865_in(sc, CD1865_SRSR|SX_EI) & CD1865_SRSR_REQint) {
 1247                         printf("sx%d: lost interrupt\n", card);
 1248                         lost++;
 1249                 }
 1250                 /*
 1251                  * Gripe about no input flow control.
 1252                  */
 1253                 for (chan = 0; chan < SX_NUMCHANS; pp++, chan++) {
 1254                         pp = &(sc->sc_ports[chan]);
 1255                         if (pp->sp_delta_overflows > 0) {
 1256                                 printf("sx%d: %d tty level buffer overflows\n",
 1257                                        card, pp->sp_delta_overflows);
 1258                                 pp->sp_delta_overflows = 0;
 1259                         }
 1260                 }
 1261         }
 1262         if (lost || sx_realpoll)
 1263                 sx_intr(NULL);  /* call intr with fake vector */
 1264 out:    splx(oldspl);
 1265         timeout(sx_poll, (caddr_t)0L, sx_pollrate);
 1266 }
 1267 
 1268 #endif  /* POLL */
 1269 
 1270 
 1271 /*
 1272  * sx_transmit()
 1273  *      Handle transmit request interrupt.
 1274  *
 1275  * Description:
 1276  *      This routine handles the transmit request interrupt from the CD1865
 1277  *      chip on the I/O8+ card.  The CD1865 interrupts us for a transmit
 1278  *      request under two circumstances:  When the last character in the
 1279  *      transmit FIFO is sent and the channel is ready for more characters
 1280  *      ("transmit ready"), or when the last bit of the last character in the
 1281  *      FIFO is actually transmitted ("transmit empty").  In the former case,
 1282  *      we just pass processing off to sx_start() (via the line discipline)
 1283  *      to queue more characters.  In the latter case, we were waiting for
 1284  *      the line to flush in sxhardclose() so we need to wake the sleeper.
 1285  */
 1286 static void
 1287 sx_transmit(
 1288         struct sx_softc *sc,
 1289         struct sx_port *pp,
 1290         int card)
 1291 {
 1292         struct tty *tp;
 1293         unsigned char flags;
 1294 
 1295         tp = pp->sp_tty;
 1296         /*
 1297          * Let others know what we're doing.
 1298          */
 1299         pp->sp_state |= SX_SS_IXMIT;
 1300         /*
 1301          * Get the service request enable register to see what we're waiting
 1302          * for.
 1303          */
 1304         flags = sx_cd1865_in(sc, CD1865_SRER|SX_EI);
 1305 
 1306         DPRINT((pp, DBG_TRANSMIT, "sx_xmit %x SRER %x\n", tp, flags));
 1307         /*
 1308          * "Transmit ready."  The transmit FIFO is empty (but there are still
 1309          * two characters being transmitted), so we need to tell the line
 1310          * discipline to send more.
 1311          */
 1312         if (flags & CD1865_IER_TXRDY) {
 1313                 ttyld_start(tp);
 1314                 pp->sp_state &= ~SX_SS_IXMIT;
 1315                 DPRINT((pp, DBG_TRANSMIT, "sx_xmit TXRDY out\n"));
 1316                 return;
 1317         }
 1318         /*
 1319          * "Transmit empty."  The transmitter is completely empty; turn off the
 1320          * service request and wake up the guy in sxhardclose() who is waiting
 1321          * for this.
 1322          */
 1323         if (flags & CD1865_IER_TXEMPTY) {
 1324                 flags &= ~CD1865_IER_TXEMPTY;
 1325                 sx_cd1865_out(sc, CD1865_CAR|SX_EI, pp->sp_chan);
 1326                 sx_cd1865_out(sc, CD1865_SRER|SX_EI, flags);
 1327                 wakeup((caddr_t)pp);
 1328         }
 1329         pp->sp_state &= ~SX_SS_IXMIT;
 1330         DPRINT((pp, DBG_TRANSMIT, "sx_xmit out\n"));
 1331 }
 1332 
 1333 /*
 1334  * sx_modem_state()
 1335  *      Handle modem state-change request interrupt.
 1336  *
 1337  * Description:
 1338  *      Handles changed modem signals CD and CTS.  We pass the CD change
 1339  *      off to the line discipline.  We can't handle DSR since there isn't a
 1340  *      pin for it.
 1341  */
 1342 static void
 1343 sx_modem_state(
 1344         struct sx_softc *sc,
 1345         struct sx_port *pp,
 1346         int card)
 1347 {
 1348         struct tty *tp;
 1349         unsigned char mcr;
 1350 
 1351         /*
 1352          * Let others know what we're doing.
 1353          */
 1354         pp->sp_state |= SX_SS_IMODEM;
 1355         tp = pp->sp_tty;
 1356         /* Grab the Modem Change Register. */
 1357         mcr = sx_cd1865_in(sc, CD1865_MCR|SX_EI);
 1358         DPRINT((pp, DBG_MODEM_STATE,
 1359                 "sx_mdmst %x st %x sp %x mcr %x\n",
 1360                 tp, tp->t_state, pp->sp_state, mcr));
 1361         if (mcr & CD1865_MCR_CDCHG) {   /* CD changed?                        */
 1362                 if ((sx_cd1865_in(sc, CD1865_MSVR) & CD1865_MSVR_CD) == 0) {
 1363                         DPRINT((pp, DBG_INTR, "modem carr on t_line %d\n",
 1364                                 tp->t_line));
 1365                         (void)ttyld_modem(tp, 1);
 1366                 }
 1367                 else {                  /* CD went down.                      */
 1368                         DPRINT((pp, DBG_INTR, "modem carr off\n"));
 1369                         if (ttyld_modem(tp, 0))
 1370                                 (void)sx_modem(sc, pp, SET, 0);
 1371                 }
 1372         }
 1373 #ifdef SX_BROKEN_CTS
 1374         if (mcr & CD1865_MCR_CTSCHG) {  /* CTS changed?                       */
 1375                 if (sx_cd1865_in(sc, CD1865_MSVR|SX_EI) & CD1865_MSVR_CTS) {
 1376                         pp->sp_state |= SX_SS_OSTOP;
 1377                         sx_cd1865_bic(sc, CD1865_IER|SX_EI, CD1865_IER_TXRDY);
 1378                         sx_write_enable(pp, 0); /* Block writes.              */
 1379                 }
 1380                 else {
 1381                         pp->sp_state &= ~SX_SS_OSTOP;
 1382                         sx_cd1865_bis(sc, CD1865_IER|SX_EI, CD1865_IER_TXRDY);
 1383                         sx_write_enable(pp, 1); /* Unblock writes.            */
 1384                 }
 1385         }
 1386 #endif /* SX_BROKEN_CTS */
 1387         /* Clear state-change indicator bits. */
 1388         sx_cd1865_out(sc, CD1865_MCR|SX_EI, 0);
 1389         pp->sp_state &= ~SX_SS_IMODEM;
 1390 }
 1391 
 1392 /*
 1393  * sx_receive()
 1394  *      Handle receive request interrupt.
 1395  *
 1396  * Description:
 1397  *      Handle a receive request interrupt from the CD1865.  This is just a
 1398  *      standard "we have characters to process" request, we don't have to
 1399  *      worry about exceptions like BREAK and such.  Exceptions are handled
 1400  *      by sx_receive_exception().
 1401  */
 1402 static void
 1403 sx_receive(
 1404         struct sx_softc *sc,
 1405         struct sx_port *pp,
 1406         int card)
 1407 {
 1408         struct tty *tp;
 1409         unsigned char count;
 1410         int i, x;
 1411         static unsigned char sx_rxbuf[SX_BUFFERSIZE];   /* input staging area */
 1412 
 1413         tp = pp->sp_tty;
 1414         DPRINT((pp, DBG_RECEIVE,
 1415                 "sx_rcv %x st %x sp %x\n",
 1416                 tp, tp->t_state, pp->sp_state));
 1417         /*
 1418          * Let others know what we're doing.
 1419          */
 1420         pp->sp_state |= SX_SS_IRCV;
 1421         /*
 1422          * How many characters are waiting for us?
 1423          */
 1424         count = sx_cd1865_in(sc, CD1865_RDCR|SX_EI);
 1425         if (count == 0)                 /* None?  Bail.                       */
 1426                 return;
 1427         DPRINT((pp, DBG_RECEIVE, "sx_receive count %d\n", count));
 1428         /*
 1429          * Pull the characters off the card into our local buffer, then
 1430          * process that.
 1431          */
 1432         for (i = 0; i < count; i++)
 1433                 sx_rxbuf[i] = sx_cd1865_in(sc, CD1865_RDR|SX_EI);
 1434         /*
 1435          * If we're not open and connected, bail.
 1436          */
 1437         if (!(tp->t_state & TS_CONNECTED && tp->t_state & TS_ISOPEN)) {
 1438                 pp->sp_state &= ~SX_SS_IRCV;
 1439                 DPRINT((pp, DBG_RECEIVE, "sx_rcv not open\n"));
 1440                 return;
 1441         }
 1442         /*
 1443          * If the tty input buffers are blocked and we have an RTS pin,
 1444          * drop RTS and bail.
 1445          */
 1446         if (tp->t_state & TS_TBLOCK) {
 1447                 if (!SX_DTRPIN(pp) && SX_IFLOW(pp)) {
 1448                         (void)sx_modem(sc, pp, BIC, TIOCM_RTS);
 1449                         pp->sp_state |= SX_SS_ISTOP;
 1450                 }
 1451                 pp->sp_state &= ~SX_SS_IRCV;
 1452                 return;
 1453         }
 1454         if (tp->t_state & TS_CAN_BYPASS_L_RINT) {
 1455                 DPRINT((pp, DBG_RECEIVE, "sx_rcv BYPASS\n"));
 1456                 /*
 1457                  * Avoid the grotesquely inefficient lineswitch routine
 1458                  * (ttyinput) in "raw" mode. It usually takes about 450
 1459                  * instructions (that's without canonical processing or
 1460                  * echo!).  slinput is reasonably fast (usually 40
 1461                  * instructions plus call overhead).
 1462                  */
 1463                 if (tp->t_rawq.c_cc + count >= SX_I_HIGH_WATER &&
 1464                     (tp->t_cflag & CRTS_IFLOW || tp->t_iflag & IXOFF) &&
 1465                     !(tp->t_state & TS_TBLOCK)) {
 1466                         ttyblock(tp);
 1467                         DPRINT((pp, DBG_RECEIVE, "sx_rcv block\n"));
 1468                     }
 1469                 tk_nin += count;
 1470                 tk_rawcc += count;
 1471                 tp->t_rawcc += count;
 1472 
 1473                 pp->sp_delta_overflows +=
 1474                                 b_to_q((char *)sx_rxbuf, count, &tp->t_rawq);
 1475                 ttwakeup(tp);
 1476                 /*
 1477                  * If we were stopped and need to start again because of this
 1478                  * receive, kick the output routine to get things going again.
 1479                  */
 1480                 if (tp->t_state & TS_TTSTOP && (tp->t_iflag & IXANY ||
 1481                                         tp->t_cc[VSTART] == tp->t_cc[VSTOP])) {
 1482                         tp->t_state &= ~TS_TTSTOP;
 1483                         tp->t_lflag &= ~FLUSHO;
 1484                         sx_start(tp);
 1485                 }
 1486         } 
 1487         else {
 1488                 DPRINT((pp, DBG_RECEIVE, "sx_rcv l_rint\n"));
 1489                 /*
 1490                  * It'd be nice to not have to go through the function call
 1491                  * overhead for each char here.  It'd be nice to block input
 1492                  * it, saving a loop here and the call/return overhead.
 1493                  */
 1494                 for (x = 0; x < count; x++) {
 1495                         i = sx_rxbuf[x];
 1496                         if (ttyld_rint(tp, i) == -1)
 1497                                 pp->sp_delta_overflows++;
 1498                 }
 1499         }
 1500         pp->sp_state &= ~SX_SS_IRCV;
 1501         DPRINT((pp, DBG_RECEIVE, "sx_rcv out\n"));
 1502 }
 1503 
 1504 
 1505 
 1506 /*
 1507  * sx_receive_exception()
 1508  *      Handle receive exception request interrupt processing.
 1509  *
 1510  * Description:
 1511  *      Handle a receive exception request interrupt from the CD1865.
 1512  *      Possible exceptions include BREAK, overrun, receiver timeout
 1513  *      and parity and frame errors.  We don't handle receiver timeout,
 1514  *      we just complain.  The rest are passed to ttyinput().
 1515  */
 1516 static void
 1517 sx_receive_exception(
 1518         struct sx_softc *sc,
 1519         struct sx_port *pp,
 1520         int card)
 1521 {
 1522         struct tty *tp;
 1523         unsigned char st;
 1524         int ch, isopen;
 1525         
 1526         tp = pp->sp_tty;
 1527         /*
 1528          * Let others know what we're doing.
 1529          */
 1530         pp->sp_state |= SX_SS_IRCVEXC;
 1531         /*
 1532          * Check to see whether we should receive characters.
 1533          */
 1534         if (tp->t_state & TS_CONNECTED &&
 1535             tp->t_state & TS_ISOPEN)
 1536                 isopen = 1;
 1537         else
 1538                 isopen = 0;
 1539 
 1540         st = sx_cd1865_in(sc, CD1865_RCSR|SX_EI); /* Get the character status.*/
 1541         ch = (int)sx_cd1865_in(sc, CD1865_RDR|SX_EI); /* Get the character.   */
 1542         DPRINT((pp, DBG_RECEIVE_EXC,
 1543                 "sx_rexc %x st %x sp %x st 0x%x ch 0x%x ('%c')\n",
 1544                 tp, tp->t_state, pp->sp_state, st, ch, ch));
 1545         /* If there's no status or the tty isn't open, bail. */
 1546         if (!st || !isopen) {
 1547                 pp->sp_state &= ~SX_SS_IRCVEXC;
 1548                 DPRINT((pp, DBG_RECEIVE_EXC, "sx_rexc not open\n"));
 1549                 return;
 1550         }
 1551         if (st & CD1865_RCSR_TOUT)      /* Receiver timeout; just complain.   */
 1552                 printf("sx%d: port %d: Receiver timeout.\n", card, pp->sp_chan);
 1553         else if (st & CD1865_RCSR_BREAK)
 1554                 ch |= TTY_BI;
 1555         else if (st & CD1865_RCSR_PE) 
 1556                 ch |= TTY_PE;
 1557         else if (st & CD1865_RCSR_FE) 
 1558                 ch |= TTY_FE;
 1559         else if (st & CD1865_RCSR_OE)
 1560                 ch |= TTY_OE;
 1561         ttyld_rint(tp, ch);
 1562         pp->sp_state &= ~SX_SS_IRCVEXC;
 1563 }
 1564 
 1565 /*
 1566  * sx_intr()
 1567  *      Field interrupts from the I/O8+.
 1568  *
 1569  * Description:
 1570  * The interrupt handler polls ALL ports on ALL adapters each time
 1571  * it is called.
 1572  */
 1573 void
 1574 sx_intr(
 1575         void *arg)
 1576 {
 1577         struct sx_softc *sc;
 1578         struct sx_port *pp = NULL;
 1579         int card;
 1580         unsigned char ack;
 1581 
 1582         sc = arg;
 1583 
 1584         DPRINT((0, arg == NULL ? DBG_POLL:DBG_INTR, "sx_intr\n"));
 1585         if (in_interrupt)
 1586                 return;
 1587         in_interrupt = 1;
 1588 
 1589         /*
 1590          * When we get an int we poll all the channels and do ALL pending
 1591          * work, not just the first one we find. This allows all cards to
 1592          * share the same vector.
 1593          *
 1594          * On the other hand, if we're sharing the vector with something
 1595          * that's not an I/O8+, we may be making extra work for ourselves.
 1596          */
 1597         for (card = 0; card < sx_numunits; card++) {
 1598                 unsigned char st;
 1599 
 1600                 sc = devclass_get_softc(sx_devclass, card);
 1601                 if (sc == NULL)
 1602                         continue;
 1603                 /*
 1604                  * Check the Service Request Status Register to see who
 1605                  * interrupted us and why.  May be a receive, transmit or
 1606                  * modem-signal-change interrupt.  Reading the appropriate
 1607                  * Request Acknowledge Register acknowledges the request and
 1608                  * gives us the contents of the Global Service Vector Register,
 1609                  * which in a daisy-chained configuration (not ours) uniquely
 1610                  * identifies the particular CD1865 and gives us the request
 1611                  * type.  We mask off the ID part and use the rest.
 1612                  *
 1613                  * From the CD1865 specs, it appears that only one request can
 1614                  * happen at a time, but in testing it's pretty obvious that
 1615                  * the specs lie.  Or perhaps we're just slow enough that the
 1616                  * requests pile up.  Regardless, if we try to process more
 1617                  * than one at a time without clearing the previous request
 1618                  * (writing zero to EOIR) first, we hang the card.  Thus the
 1619                  * "else if" logic here.
 1620                  */
 1621                 while ((st = (sx_cd1865_in(sc, CD1865_SRSR|SX_EI)) &
 1622                                                           CD1865_SRSR_REQint)) {
 1623                         /*
 1624                          * Transmit request interrupt.
 1625                          */
 1626                         if (st & CD1865_SRSR_TREQint) {
 1627                                 ack = sx_cd1865_in(sc, CD1865_TRAR|SX_EI) &
 1628                                                              CD1865_GIVR_ITMASK;
 1629                                 pp = sx_int_port(sc, card);
 1630                                 if (pp == NULL) /* Bad channel.               */
 1631                                         goto skip;
 1632                                 pp->sp_state |= SX_SS_INTR; /* In interrupt.  */
 1633                                 if (ack == CD1865_GIVR_IT_TX)
 1634                                         sx_transmit(sc, pp, card);
 1635                                 else
 1636                                         printf("sx%d: Bad transmit ack 0x%02x.\n",
 1637                                                card, ack);
 1638                         }
 1639                         /*
 1640                          * Modem signal change request interrupt.
 1641                          */
 1642                         else if (st & CD1865_SRSR_MREQint) {
 1643                                 ack = sx_cd1865_in(sc, CD1865_MRAR|SX_EI) &
 1644                                                              CD1865_GIVR_ITMASK;
 1645                                 pp = sx_int_port(sc, card);
 1646                                 if (pp == NULL) /* Bad channel.               */
 1647                                         goto skip;
 1648                                 pp->sp_state |= SX_SS_INTR; /* In interrupt.  */
 1649                                 if (ack == CD1865_GIVR_IT_MODEM)
 1650                                         sx_modem_state(sc, pp, card);
 1651                                 else
 1652                                         printf("sx%d: Bad modem ack 0x%02x.\n",
 1653                                                card, ack);
 1654                         }
 1655                         /*
 1656                          * Receive request interrupt.
 1657                          */
 1658                         else if (st & CD1865_SRSR_RREQint) {
 1659                                 ack = sx_cd1865_in(sc, CD1865_RRAR|SX_EI) &
 1660                                                              CD1865_GIVR_ITMASK;
 1661                                 pp = sx_int_port(sc, card);
 1662                                 if (pp == NULL) /* Bad channel.               */
 1663                                         goto skip;
 1664                                 pp->sp_state |= SX_SS_INTR; /* In interrupt.  */
 1665                                 if (ack == CD1865_GIVR_IT_RCV)
 1666                                         sx_receive(sc, pp, card);
 1667                                 else if (ack == CD1865_GIVR_IT_REXC)
 1668                                         sx_receive_exception(sc, pp, card);
 1669                                 else
 1670                                         printf("sx%d: Bad receive ack 0x%02x.\n",
 1671                                                card, ack);
 1672                         }
 1673                         /*
 1674                          * None of the above; this is a "can't happen," but
 1675                          * you never know...
 1676                          */
 1677                         else {
 1678                                 printf("sx%d: Bad service request 0x%02x.\n",
 1679                                        card, st);
 1680                         }
 1681                         pp->sp_state &= ~SX_SS_INTR;
 1682 skip:                   sx_cd1865_out(sc, CD1865_EOIR|SX_EI, 0); /* EOI.      */
 1683                 }               /* while (st & CD1865_SRSR_REQint)            */
 1684         }                       /* for (card = 0; card < sx_numunits; card++) */
 1685         in_interrupt = 0;
 1686         DPRINT((0, arg == NULL ? DBG_POLL:DBG_INTR, "sx_intr out\n"));
 1687 }
 1688 
 1689 /*
 1690  * sx_start()
 1691  *      Handle transmit and state-change stuff.
 1692  *
 1693  * Description:
 1694  *      This is part of the line discipline processing; at various points in
 1695  *      the line discipline he calls ttstart() which calls the oproc routine,
 1696  *      which is this function.  We're called by the line discipline to start
 1697  *      data transmission and to change signal states (for RTS flow control).
 1698  *      We're also called by this driver to perform line-breaks and to actually
 1699  *      do the data transmission.
 1700 
 1701  *      We can only fill the FIFO from interrupt since the card only makes it
 1702  *      available to us during a service request such as TXRDY; this only
 1703  *      happens at interrupt.
 1704  *
 1705  *      All paths through this code call ttwwakeup().
 1706  */
 1707 static void
 1708 sx_start(
 1709         struct tty *tp)
 1710 {
 1711         struct sx_softc *sc;
 1712         struct sx_port *pp;
 1713         struct clist *qp;
 1714         int s;
 1715         int count = CD1865_TFIFOSZ;
 1716 
 1717         s = spltty();
 1718         pp = TP2PP(tp);
 1719         qp = &tp->t_outq;
 1720         DPRINT((pp, DBG_ENTRY|DBG_START,
 1721                 "sx_start %x st %x sp %x cc %d\n",
 1722                 tp, tp->t_state, pp->sp_state, qp->c_cc));
 1723 
 1724         /*
 1725          * If we're stopped, just wake up sleepers and get out.
 1726          */
 1727         if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP)) {
 1728                 ttwwakeup(tp);
 1729                 splx(s);
 1730                 DPRINT((pp, DBG_EXIT|DBG_START, "sx_start out\n", tp->t_state));
 1731                 return;
 1732         }
 1733         sc = TP2SC(tp);
 1734         /*
 1735          * If we're not transmitting, we may have been called to crank up the
 1736          * transmitter and start things rolling or we may have been called to
 1737          * get a bit of tty state.  If the latter, handle it.  Either way, if
 1738          * we have data to transmit, turn on the transmit-ready interrupt,
 1739          * set the XMIT flag and we're done.  As soon as we allow interrupts
 1740          * the card will interrupt for the first chunk of data.  Note that
 1741          * we don't mark the tty as busy until we are actually sending data
 1742          * and then only if we have more than will fill the FIFO.  If there's
 1743          * no data to transmit, just handle the tty state.
 1744          */
 1745         if (!SX_XMITTING(pp)) {
 1746                 /*
 1747                  * If we were flow-controlled and input is no longer blocked,
 1748                  * raise RTS if we can.
 1749                  */
 1750                 if (SX_ISTOP(pp) && !(tp->t_state & TS_TBLOCK)) {
 1751                         if (!SX_DTRPIN(pp) && SX_IFLOW(pp))
 1752                                 (void)sx_modem(sc, pp, BIS, TIOCM_RTS);
 1753                         pp->sp_state &= ~SX_SS_ISTOP;
 1754                 }
 1755                 /*
 1756                  * If input is blocked, drop RTS if we can and set our flag.
 1757                  */
 1758                 if (tp->t_state & TS_TBLOCK) {
 1759                         if (!SX_DTRPIN(pp) && SX_IFLOW(pp))
 1760                                 (void)sx_modem(sc, pp, BIC, TIOCM_RTS);
 1761                         pp->sp_state |= SX_SS_ISTOP;
 1762                 }
 1763                 if ((qp->c_cc > 0 && !SX_OSTOP(pp)) || SX_DOBRK(pp)) {
 1764                         disable_intr();
 1765                         sx_cd1865_out(sc, CD1865_CAR|SX_EI, pp->sp_chan);
 1766                         sx_cd1865_bis(sc, CD1865_IER|SX_EI, CD1865_IER_TXRDY);
 1767                         enable_intr();
 1768                         pp->sp_state |= SX_SS_XMIT;
 1769                 }
 1770                 ttwwakeup(tp);
 1771                 splx(s);
 1772                 DPRINT((pp, DBG_EXIT|DBG_START,
 1773                         "sx_start out B st %x sp %x cc %d\n",
 1774                         tp->t_state, pp->sp_state, qp->c_cc));
 1775                 return;
 1776         }
 1777         /*
 1778          * If we weren't called from an interrupt or it wasn't a transmit
 1779          * interrupt, we've done all we need to do.  Everything else is done
 1780          * in the transmit interrupt.
 1781          */
 1782         if (!SX_INTR(pp) || !SX_IXMIT(pp)) {
 1783                 ttwwakeup(tp);
 1784                 splx(s);
 1785                 DPRINT((pp, DBG_EXIT|DBG_START, "sx_start out X\n"));
 1786                 return;
 1787         }
 1788         /*
 1789          * We're transmitting.  If the clist is empty and we don't have a break
 1790          * to send, turn off transmit-ready interrupts, and clear the XMIT
 1791          * flag.  Mark the tty as no longer busy, in case we haven't done
 1792          * that yet. A future call to sxwrite() with more characters will
 1793          * start up the process once more.
 1794          */
 1795         if (qp->c_cc == 0 && !SX_DOBRK(pp)) {
 1796                 disable_intr();
 1797 /*              sx_cd1865_out(sc, CD1865_CAR|SX_EI, pp->sp_chan);*/
 1798                 sx_cd1865_bic(sc, CD1865_IER|SX_EI, CD1865_IER_TXRDY);
 1799                 enable_intr();
 1800                 pp->sp_state &= ~SX_SS_XMIT;
 1801                 tp->t_state &= ~TS_BUSY;
 1802                 ttwwakeup(tp);
 1803                 splx(s);
 1804                 DPRINT((pp, DBG_EXIT|DBG_START,
 1805                         "sx_start out E st %x sp %x\n",
 1806                         tp->t_state, pp->sp_state));
 1807                 return;
 1808         }
 1809         disable_intr();
 1810         /*
 1811          * If we have a BREAK state-change pending, handle it.  If we aren't
 1812          * sending a break, start one.  If we are, turn it off.
 1813          */
 1814         if (SX_DOBRK(pp)) {
 1815                 count -= 2;             /* Account for escape chars in FIFO.  */
 1816                 if (SX_BREAK(pp)) {     /* Doing break, stop it.              */
 1817                         sx_cd1865_out(sc, CD1865_TDR, CD1865_C_ESC);
 1818                         sx_cd1865_out(sc, CD1865_TDR, CD1865_C_EBRK);
 1819                         sx_cd1865_etcmode(sc, SX_EI, pp->sp_chan, 0);
 1820                         pp->sp_state &= ~SX_SS_BREAK;
 1821                 }
 1822                 else {                  /* Start doing break.                 */
 1823                         sx_cd1865_etcmode(sc, SX_EI, pp->sp_chan, 1);
 1824                         sx_cd1865_out(sc, CD1865_TDR, CD1865_C_ESC);
 1825                         sx_cd1865_out(sc, CD1865_TDR, CD1865_C_SBRK);
 1826                         pp->sp_state |= SX_SS_BREAK;
 1827                 }
 1828                 pp->sp_state &= ~SX_SS_DOBRK;
 1829         }
 1830         /*
 1831          * We've still got data in the clist, fill the channel's FIFO.  The
 1832          * CD1865 only gives us access to the FIFO during a transmit ready
 1833          * request [interrupt] for this channel.
 1834          */
 1835         while (qp->c_cc > 0 && count-- >= 0) {
 1836                 register unsigned char ch, *cp;
 1837                 int nch;
 1838 
 1839                 ch = (char)getc(qp);
 1840                 /*
 1841                  * If we're doing a break we're in ETC mode, so we need to
 1842                  * double any NULs in the stream.
 1843                  */
 1844                 if (SX_BREAK(pp)) {     /* Doing break, in ETC mode.          */
 1845                         if (ch == '\0') { /* NUL?  Double it.                 */
 1846                                 sx_cd1865_out(sc, CD1865_TDR, ch);
 1847                                 count--;
 1848                         }
 1849                         /*
 1850                          * Peek the next character; if it's a NUL, we need
 1851                          * to escape it, but we can't if we're out of FIFO.
 1852                          * We'll do it on the next pass and leave the FIFO
 1853                          * incompletely filled.
 1854                          */
 1855                         if (qp->c_cc > 0) {
 1856                                 cp = qp->c_cf;
 1857                                 cp = nextc(qp, cp, &nch);
 1858                                 if (nch == '\0' && count < 1)
 1859                                         count = -1;
 1860                         }
 1861                 }
 1862                 sx_cd1865_out(sc, CD1865_TDR, ch);
 1863         }
 1864         enable_intr();
 1865         /*
 1866          * If we still have data to transmit, mark the tty busy for the
 1867          * line discipline.
 1868          */
 1869         if (qp->c_cc > 0)
 1870                 tp->t_state |= TS_BUSY;
 1871         else
 1872                 tp->t_state &= ~TS_BUSY;
 1873         /* Wake up sleepers if necessary. */
 1874         ttwwakeup(tp);
 1875         splx(s);
 1876         DPRINT((pp, DBG_EXIT|DBG_START,
 1877                 "sx_start out R %d/%d\n",
 1878                 count, qp->c_cc));
 1879 }
 1880 
 1881 /*
 1882  * Stop output on a line. called at spltty();
 1883  */
 1884 void
 1885 sx_stop(
 1886         struct tty *tp,
 1887         int rw)
 1888 {
 1889         struct sx_softc *sc;
 1890         struct sx_port *pp;
 1891         int s;
 1892 
 1893         sc = TP2SC(tp);
 1894         pp = TP2PP(tp);
 1895         DPRINT((TP2PP(tp), DBG_ENTRY|DBG_STOP, "sx_stop(%x,%x)\n", tp, rw));
 1896 
 1897         s = spltty();
 1898         /* XXX: must check (rw & FWRITE | FREAD) etc flushing... */
 1899         if (rw & FWRITE) {
 1900                 disable_intr();
 1901                 sx_cd1865_out(sc, CD1865_CAR|SX_EI, pp->sp_chan);
 1902                 sx_cd1865_bic(sc, CD1865_IER|SX_EI, CD1865_IER_TXRDY);
 1903                 sx_cd1865_wait_CCR(sc, SX_EI);  /* Wait for CCR to go idle.   */
 1904                 sx_cd1865_out(sc, CD1865_CCR|SX_EI, CD1865_CCR_TXDIS);
 1905                 sx_cd1865_wait_CCR(sc, SX_EI);
 1906                 enable_intr();
 1907         /* what level are we meant to be flushing anyway? */
 1908                 if (tp->t_state & TS_BUSY) {
 1909                         if ((tp->t_state & TS_TTSTOP) == 0)
 1910                                 tp->t_state |= TS_FLUSH;
 1911                         tp->t_state &= ~TS_BUSY;
 1912                         ttwwakeup(tp);
 1913                 }
 1914         }
 1915         /*
 1916          * Nothing to do for FREAD.
 1917          */
 1918         splx(s);
 1919 }
 1920 
 1921 #ifdef  SX_DEBUG
 1922 
 1923 void
 1924 sx_dprintf(
 1925         struct sx_port *pp,
 1926         int flags,
 1927         const char *fmt, ...)
 1928 {
 1929         static char *logbuf = NULL;
 1930         static char *linebuf = NULL;
 1931         static char *logptr;
 1932         char *lbuf;
 1933         int n, m;
 1934         va_list ap;
 1935 
 1936         if (logbuf == NULL) {
 1937                 logbuf = (char *)malloc(1024*1024, M_DEVBUF, M_WAITOK);
 1938                 linebuf = (char *)malloc(256, M_DEVBUF, M_WAITOK);
 1939                 logptr = logbuf;
 1940         }
 1941         lbuf = linebuf;
 1942         n = 0;
 1943         if ((pp == NULL && (sx_debug&flags)) ||
 1944             (pp != NULL && ((pp->sp_debug&flags) || (sx_debug&flags)))) {
 1945                 if (pp != NULL &&
 1946                     pp->sp_tty != NULL &&
 1947                     pp->sp_tty->t_dev != NULL) {
 1948                         n = snprintf(linebuf, 256, "%cx%d(%d): ", 's',
 1949                                 (int)SX_MINOR2CARD(minor(pp->sp_tty->t_dev)),
 1950                                 (int)SX_MINOR2CHAN(minor(pp->sp_tty->t_dev)));
 1951                         if (n > 256)
 1952                                 n = 256;
 1953                         lbuf += n;
 1954                 }
 1955                 m = n;
 1956                 va_start(ap, fmt);
 1957                 n = vsnprintf(lbuf, 256 - m, fmt, ap);
 1958                 va_end(ap);
 1959                 if (n > 256 - m)
 1960                         n = 256 - m;
 1961                 n += m;
 1962                 if (logptr + n + 1 > logbuf + (1024 * 1024)) {
 1963                         bzero(logptr, logbuf + (1024 * 1024) - logptr);
 1964                         logptr = logbuf;
 1965                 }
 1966                 bcopy(linebuf, logptr, n);
 1967                 logptr += n;
 1968                 *logptr = '\0';
 1969                 if (sx_debug & DBG_PRINTF)
 1970                         printf("%s", linebuf);
 1971         }
 1972 }
 1973 
 1974 static char *
 1975 sx_mctl2str(enum sx_mctl cmd)
 1976 {
 1977         switch (cmd) {
 1978         case GET:
 1979                 return("GET");
 1980         case SET:
 1981                 return("SET");
 1982         case BIS:
 1983                 return("BIS");
 1984         case BIC:
 1985                 return("BIC");
 1986         }
 1987         return("BAD");
 1988 }
 1989 
 1990 #endif  /* DEBUG */

Cache object: 3702cb40df12c3c9e82b83e2f5c31d5d


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