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/com.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 /*      $OpenBSD: com.c,v 1.175 2022/01/11 11:51:14 uaa Exp $   */
    2 /*      $NetBSD: com.c,v 1.82.4.1 1996/06/02 09:08:00 mrg Exp $ */
    3 
    4 /*
    5  * Copyright (c) 1997 - 1999, Jason Downs.  All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
   17  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   19  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
   20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   22  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
   23  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 /*-
   29  * Copyright (c) 1993, 1994, 1995, 1996
   30  *      Charles M. Hannum.  All rights reserved.
   31  * Copyright (c) 1991 The Regents of the University of California.
   32  * All rights reserved.
   33  *
   34  * Redistribution and use in source and binary forms, with or without
   35  * modification, are permitted provided that the following conditions
   36  * are met:
   37  * 1. Redistributions of source code must retain the above copyright
   38  *    notice, this list of conditions and the following disclaimer.
   39  * 2. Redistributions in binary form must reproduce the above copyright
   40  *    notice, this list of conditions and the following disclaimer in the
   41  *    documentation and/or other materials provided with the distribution.
   42  * 3. Neither the name of the University nor the names of its contributors
   43  *    may be used to endorse or promote products derived from this software
   44  *    without specific prior written permission.
   45  *
   46  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   47  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   48  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   49  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   50  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   51  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   52  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   53  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   54  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   55  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   56  * SUCH DAMAGE.
   57  *
   58  *      @(#)com.c       7.5 (Berkeley) 5/16/91
   59  */
   60 
   61 /*
   62  * COM driver, based on HP dca driver
   63  * uses National Semiconductor NS16450/NS16550AF UART
   64  */
   65 #include <sys/param.h>
   66 #include <sys/systm.h>
   67 #include <sys/ioctl.h>
   68 #include <sys/selinfo.h>
   69 #include <sys/tty.h>
   70 #include <sys/conf.h>
   71 #include <sys/fcntl.h>
   72 #include <sys/uio.h>
   73 #include <sys/kernel.h>
   74 #include <sys/syslog.h>
   75 #include <sys/device.h>
   76 #include <sys/vnode.h>
   77 #ifdef DDB
   78 #include <ddb/db_var.h>
   79 #endif
   80 
   81 #include <machine/bus.h>
   82 #include <machine/intr.h>
   83 
   84 #define COM_CONSOLE
   85 #include <dev/cons.h>
   86 
   87 #include <dev/ic/comreg.h>
   88 #include <dev/ic/comvar.h>
   89 #include <dev/ic/ns16550reg.h>
   90 #define com_lcr com_cfcr
   91 
   92 cdev_decl(com);
   93 
   94 static u_char tiocm_xxx2mcr(int);
   95 
   96 void    compwroff(struct com_softc *);
   97 void    cominit(bus_space_tag_t, bus_space_handle_t, int, int);
   98 int     com_is_console(bus_space_tag_t, bus_addr_t);
   99 
  100 struct cfdriver com_cd = {
  101         NULL, "com", DV_TTY
  102 };
  103 
  104 int     comdefaultrate = TTYDEF_SPEED;
  105 #ifdef COM_CONSOLE
  106 int     comconsfreq;
  107 int     comconsrate = TTYDEF_SPEED;
  108 bus_addr_t comconsaddr = 0;
  109 int     comconsattached;
  110 bus_space_tag_t comconsiot;
  111 bus_space_handle_t comconsioh;
  112 int     comconsunit;
  113 tcflag_t comconscflag = TTYDEF_CFLAG;
  114 #endif
  115 
  116 int     commajor;
  117 
  118 #define DEVUNIT(x)      (minor(x) & 0x7f)
  119 #define DEVCUA(x)       (minor(x) & 0x80)
  120 
  121 int
  122 comspeed(long freq, long speed)
  123 {
  124 #define divrnd(n, q)    (((n)*2/(q)+1)/2)       /* divide and round off */
  125 
  126         int x, err;
  127 
  128         if (speed == 0)
  129                 return 0;
  130         if (speed < 0)
  131                 return -1;
  132         x = divrnd((freq / 16), speed);
  133         if (x <= 0)
  134                 return -1;
  135         err = divrnd((quad_t)freq * 1000 / 16, speed * x) - 1000;
  136         if (err < 0)
  137                 err = -err;
  138         if (err > COM_TOLERANCE)
  139                 return -1;
  140         return x;
  141 
  142 #undef  divrnd
  143 }
  144 
  145 #ifdef COM_CONSOLE
  146 int
  147 comprobe1(bus_space_tag_t iot, bus_space_handle_t ioh)
  148 {
  149         int i, k;
  150 
  151         /* force access to id reg */
  152         bus_space_write_1(iot, ioh, com_lcr, 0);
  153         bus_space_write_1(iot, ioh, com_iir, 0);
  154         for (i = 0; i < 32; i++) {
  155                 k = bus_space_read_1(iot, ioh, com_iir);
  156                 if (k & 0x38) {
  157                         bus_space_read_1(iot, ioh, com_data); /* cleanup */
  158                 } else
  159                         break;
  160         }
  161         if (i >= 32)
  162                 return 0;
  163 
  164         return 1;
  165 }
  166 #endif
  167 
  168 int
  169 com_detach(struct device *self, int flags)
  170 {
  171         struct com_softc *sc = (struct com_softc *)self;
  172         int maj, mn;
  173 
  174         sc->sc_swflags |= COM_SW_DEAD;
  175 
  176         /* Locate the major number. */
  177         for (maj = 0; maj < nchrdev; maj++)
  178                 if (cdevsw[maj].d_open == comopen)
  179                         break;
  180 
  181         /* Nuke the vnodes for any open instances. */
  182         mn = self->dv_unit;
  183         vdevgone(maj, mn, mn, VCHR);
  184 
  185         /* XXX a symbolic constant for the cua bit would be nicer. */
  186         mn |= 0x80;
  187         vdevgone(maj, mn, mn, VCHR);
  188 
  189         timeout_del(&sc->sc_dtr_tmo);
  190         timeout_del(&sc->sc_diag_tmo);
  191         softintr_disestablish(sc->sc_si);
  192 
  193         /* Detach and free the tty. */
  194         if (sc->sc_tty) {
  195                 ttyfree(sc->sc_tty);
  196         }
  197 
  198         return (0);
  199 }
  200 
  201 int
  202 com_activate(struct device *self, int act)
  203 {
  204         struct com_softc *sc = (struct com_softc *)self;
  205         int s, rv = 0;
  206 
  207         switch (act) {
  208         case DVACT_SUSPEND:
  209                 if (timeout_del(&sc->sc_dtr_tmo)) {
  210                         /* Make sure DTR gets raised upon resume. */
  211                         SET(sc->sc_mcr, MCR_DTR | MCR_RTS);
  212                 }
  213                 timeout_del(&sc->sc_diag_tmo);
  214                 break;
  215         case DVACT_RESUME:
  216                 com_resume(sc);
  217                 break;
  218         case DVACT_DEACTIVATE:
  219                 if (sc->sc_hwflags & COM_HW_CONSOLE) {
  220                         rv = EBUSY;
  221                         break;
  222                 }
  223 
  224                 s = spltty();
  225                 if (sc->disable != NULL && sc->enabled != 0) {
  226                         (*sc->disable)(sc);
  227                         sc->enabled = 0;
  228                 }
  229                 splx(s);
  230                 break;
  231         }
  232         return (rv);
  233 }
  234 
  235 int
  236 comopen(dev_t dev, int flag, int mode, struct proc *p)
  237 {
  238         int unit = DEVUNIT(dev);
  239         struct com_softc *sc;
  240         struct tty *tp;
  241         int s;
  242         int error = 0;
  243 
  244         if (unit >= com_cd.cd_ndevs)
  245                 return ENXIO;
  246         sc = com_cd.cd_devs[unit];
  247         if (!sc)
  248                 return ENXIO;
  249 
  250         s = spltty();
  251         if (!sc->sc_tty) {
  252                 tp = sc->sc_tty = ttymalloc(1000000);
  253         } else
  254                 tp = sc->sc_tty;
  255         splx(s);
  256 
  257         tp->t_oproc = comstart;
  258         tp->t_param = comparam;
  259         tp->t_dev = dev;
  260         if (!ISSET(tp->t_state, TS_ISOPEN)) {
  261                 SET(tp->t_state, TS_WOPEN);
  262                 ttychars(tp);
  263                 tp->t_iflag = TTYDEF_IFLAG;
  264                 tp->t_oflag = TTYDEF_OFLAG;
  265 #ifdef COM_CONSOLE
  266                 if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
  267                         tp->t_cflag = comconscflag;
  268                         tp->t_ispeed = tp->t_ospeed = comconsrate;
  269                 } else
  270 #endif
  271                 {
  272                         tp->t_cflag = TTYDEF_CFLAG;
  273                         tp->t_ispeed = tp->t_ospeed = comdefaultrate;
  274                 }
  275                 if (ISSET(sc->sc_swflags, COM_SW_CLOCAL))
  276                         SET(tp->t_cflag, CLOCAL);
  277                 if (ISSET(sc->sc_swflags, COM_SW_CRTSCTS))
  278                         SET(tp->t_cflag, CRTSCTS);
  279                 if (ISSET(sc->sc_swflags, COM_SW_MDMBUF))
  280                         SET(tp->t_cflag, MDMBUF);
  281                 tp->t_lflag = TTYDEF_LFLAG;
  282 
  283                 s = spltty();
  284 
  285                 sc->sc_initialize = 1;
  286                 comparam(tp, &tp->t_termios);
  287                 ttsetwater(tp);
  288 
  289                 sc->sc_ibufp = sc->sc_ibuf = sc->sc_ibufs[0];
  290                 sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER;
  291                 sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE;
  292 
  293                 /*
  294                  * Wake up the sleepy heads.
  295                  */
  296                 if (!ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
  297                         switch (sc->sc_uarttype) {
  298                         case COM_UART_ST16650:
  299                         case COM_UART_ST16650V2:
  300                                 com_write_reg(sc, com_lcr, LCR_EFR);
  301                                 com_write_reg(sc, com_efr, EFR_ECB);
  302                                 com_write_reg(sc, com_ier, 0);
  303                                 com_write_reg(sc, com_efr, 0);
  304                                 com_write_reg(sc, com_lcr, 0);
  305                                 break;
  306                         case COM_UART_TI16750:
  307                                 com_write_reg(sc, com_ier, 0);
  308                                 break;
  309                         case COM_UART_XR17V35X:
  310                                 com_write_reg(sc, UART_EXAR_SLEEP, 0);
  311                                 break;
  312                         }
  313                 }
  314 
  315                 if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
  316                         u_int8_t fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST;
  317                         u_int8_t lcr;
  318 
  319                         if (tp->t_ispeed <= 1200)
  320                                 fifo |= FIFO_TRIGGER_1;
  321                         else if (tp->t_ispeed <= 38400)
  322                                 fifo |= FIFO_TRIGGER_4;
  323                         else
  324                                 fifo |= FIFO_TRIGGER_8;
  325                         if (sc->sc_uarttype == COM_UART_TI16750) {
  326                                 fifo |= FIFO_ENABLE_64BYTE;
  327                                 lcr = com_read_reg(sc, com_lcr);
  328                                 com_write_reg(sc, com_lcr,
  329                                     lcr | LCR_DLAB);
  330                         }
  331 
  332                         /*
  333                          * (Re)enable and drain FIFOs.
  334                          *
  335                          * Certain SMC chips cause problems if the FIFOs are
  336                          * enabled while input is ready. Turn off the FIFO
  337                          * if necessary to clear the input. Test the input
  338                          * ready bit after enabling the FIFOs to handle races
  339                          * between enabling and fresh input.
  340                          *
  341                          * Set the FIFO threshold based on the receive speed.
  342                          */
  343                         for (;;) {
  344                                 com_write_reg(sc, com_fifo, 0);
  345                                 delay(100);
  346                                 (void) com_read_reg(sc, com_data);
  347                                 com_write_reg(sc, com_fifo, fifo |
  348                                     FIFO_RCV_RST | FIFO_XMT_RST);
  349                                 delay(100);
  350                                 if(!ISSET(com_read_reg(sc,
  351                                     com_lsr), LSR_RXRDY))
  352                                         break;
  353                         }
  354                         if (sc->sc_uarttype == COM_UART_TI16750)
  355                                 com_write_reg(sc, com_lcr, lcr);
  356                 }
  357 
  358                 /* Flush any pending I/O. */
  359                 while (ISSET(com_read_reg(sc, com_lsr), LSR_RXRDY))
  360                         (void) com_read_reg(sc, com_data);
  361 
  362                 /* You turn me on, baby! */
  363                 sc->sc_mcr = MCR_DTR | MCR_RTS;
  364                 if (!ISSET(sc->sc_hwflags, COM_HW_NOIEN))
  365                         SET(sc->sc_mcr, MCR_IENABLE);
  366                 com_write_reg(sc, com_mcr, sc->sc_mcr);
  367                 sc->sc_ier = IER_ERXRDY | IER_ERLS | IER_EMSC;
  368                 com_write_reg(sc, com_ier, sc->sc_ier);
  369 
  370                 sc->sc_msr = com_read_reg(sc, com_msr);
  371                 if (ISSET(sc->sc_swflags, COM_SW_SOFTCAR) || DEVCUA(dev) ||
  372                     ISSET(sc->sc_msr, MSR_DCD) || ISSET(tp->t_cflag, MDMBUF))
  373                         SET(tp->t_state, TS_CARR_ON);
  374                 else
  375                         CLR(tp->t_state, TS_CARR_ON);
  376         } else if (ISSET(tp->t_state, TS_XCLUDE) && suser(p) != 0)
  377                 return EBUSY;
  378         else
  379                 s = spltty();
  380 
  381         if (DEVCUA(dev)) {
  382                 if (ISSET(tp->t_state, TS_ISOPEN)) {
  383                         /* Ah, but someone already is dialed in... */
  384                         splx(s);
  385                         return EBUSY;
  386                 }
  387                 sc->sc_cua = 1;         /* We go into CUA mode. */
  388         } else {
  389                 /* tty (not cua) device; wait for carrier if necessary. */
  390                 if (ISSET(flag, O_NONBLOCK)) {
  391                         if (sc->sc_cua) {
  392                                 /* Opening TTY non-blocking... but the CUA is busy. */
  393                                 splx(s);
  394                                 return EBUSY;
  395                         }
  396                 } else {
  397                         while (sc->sc_cua ||
  398                             (!ISSET(tp->t_cflag, CLOCAL) &&
  399                                 !ISSET(tp->t_state, TS_CARR_ON))) {
  400                                 SET(tp->t_state, TS_WOPEN);
  401                                 error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, ttopen);
  402                                 /*
  403                                  * If TS_WOPEN has been reset, that means the cua device
  404                                  * has been closed.  We don't want to fail in that case,
  405                                  * so just go around again.
  406                                  */
  407                                 if (error && ISSET(tp->t_state, TS_WOPEN)) {
  408                                         CLR(tp->t_state, TS_WOPEN);
  409                                         if (!sc->sc_cua && !ISSET(tp->t_state, TS_ISOPEN))
  410                                                 compwroff(sc);
  411                                         splx(s);
  412                                         return error;
  413                                 }
  414                         }
  415                 }
  416         }
  417         splx(s);
  418 
  419         return (*linesw[tp->t_line].l_open)(dev, tp, p);
  420 }
  421 
  422 int
  423 comclose(dev_t dev, int flag, int mode, struct proc *p)
  424 {
  425         int unit = DEVUNIT(dev);
  426         struct com_softc *sc = com_cd.cd_devs[unit];
  427         struct tty *tp = sc->sc_tty;
  428         int s;
  429 
  430 #ifdef COM_CONSOLE
  431         /* XXX This is for cons.c. */
  432         if (!ISSET(tp->t_state, TS_ISOPEN))
  433                 return 0;
  434 #endif
  435 
  436         if(sc->sc_swflags & COM_SW_DEAD)
  437                 return 0;
  438 
  439         (*linesw[tp->t_line].l_close)(tp, flag, p);
  440         s = spltty();
  441         if (ISSET(tp->t_state, TS_WOPEN)) {
  442                 /* tty device is waiting for carrier; drop dtr then re-raise */
  443                 CLR(sc->sc_mcr, MCR_DTR | MCR_RTS);
  444                 com_write_reg(sc, com_mcr, sc->sc_mcr);
  445                 timeout_add_sec(&sc->sc_dtr_tmo, 2);
  446         } else {
  447                 /* no one else waiting; turn off the uart */
  448                 compwroff(sc);
  449         }
  450         CLR(tp->t_state, TS_BUSY | TS_FLUSH);
  451         sc->sc_cua = 0;
  452         splx(s);
  453         ttyclose(tp);
  454 
  455 #ifdef COM_CONSOLE
  456 #ifdef notyet /* XXXX */
  457         if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
  458                 ttyfree(tp);
  459                 sc->sc_tty = 0;
  460         }
  461 #endif
  462 #endif
  463         return 0;
  464 }
  465 
  466 void
  467 compwroff(struct com_softc *sc)
  468 {
  469         struct tty *tp = sc->sc_tty;
  470 
  471         CLR(sc->sc_lcr, LCR_SBREAK);
  472         com_write_reg(sc, com_lcr, sc->sc_lcr);
  473         com_write_reg(sc, com_ier, 0);
  474         if (ISSET(tp->t_cflag, HUPCL) &&
  475             !ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) {
  476                 /* XXX perhaps only clear DTR */
  477                 sc->sc_mcr = 0;
  478                 com_write_reg(sc, com_mcr, sc->sc_mcr);
  479         }
  480 
  481         /*
  482          * Turn FIFO off; enter sleep mode if possible.
  483          */
  484         com_write_reg(sc, com_fifo, 0);
  485         delay(100);
  486         if (ISSET(com_read_reg(sc, com_lsr), LSR_RXRDY))
  487                 (void) com_read_reg(sc, com_data);
  488         delay(100);
  489         com_write_reg(sc, com_fifo,
  490                           FIFO_RCV_RST | FIFO_XMT_RST);
  491 
  492         if (!ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
  493                 switch (sc->sc_uarttype) {
  494                 case COM_UART_ST16650:
  495                 case COM_UART_ST16650V2:
  496                         com_write_reg(sc, com_lcr, LCR_EFR);
  497                         com_write_reg(sc, com_efr, EFR_ECB);
  498                         com_write_reg(sc, com_ier, IER_SLEEP);
  499                         com_write_reg(sc, com_lcr, 0);
  500                         break;
  501                 case COM_UART_TI16750:
  502                         com_write_reg(sc, com_ier, IER_SLEEP);
  503                         break;
  504                 case COM_UART_XR17V35X:
  505                         com_write_reg(sc, UART_EXAR_SLEEP, 0xff);
  506                         break;
  507                 }
  508         }
  509 }
  510 
  511 void
  512 com_resume(struct com_softc *sc)
  513 {
  514         struct tty *tp = sc->sc_tty;
  515         int ospeed;
  516 
  517         if (!tp || !ISSET(tp->t_state, TS_ISOPEN)) {
  518 #ifdef COM_CONSOLE
  519                 if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
  520                         cominit(comconsiot, comconsioh, comconsrate,
  521                             comconsfreq);
  522 #endif
  523                 return;
  524         }
  525 
  526         /*
  527          * Wake up the sleepy heads.
  528          */
  529         if (!ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
  530                 switch (sc->sc_uarttype) {
  531                 case COM_UART_ST16650:
  532                 case COM_UART_ST16650V2:
  533                         com_write_reg(sc, com_lcr, LCR_EFR);
  534                         com_write_reg(sc, com_efr, EFR_ECB);
  535                         com_write_reg(sc, com_ier, 0);
  536                         com_write_reg(sc, com_efr, 0);
  537                         com_write_reg(sc, com_lcr, 0);
  538                         break;
  539                 case COM_UART_TI16750:
  540                         com_write_reg(sc, com_ier, 0);
  541                         break;
  542                 case COM_UART_XR17V35X:
  543                         com_write_reg(sc, UART_EXAR_SLEEP, 0);
  544                         break;
  545                 }
  546         }
  547 
  548         ospeed = comspeed(sc->sc_frequency, tp->t_ospeed);
  549 
  550         if (ospeed != 0) {
  551                 com_write_reg(sc, com_lcr, sc->sc_lcr | LCR_DLAB);
  552                 com_write_reg(sc, com_dlbl, ospeed);
  553                 com_write_reg(sc, com_dlbh, ospeed >> 8);
  554                 com_write_reg(sc, com_lcr, sc->sc_lcr);
  555         } else {
  556                 com_write_reg(sc, com_lcr, sc->sc_lcr);
  557         }
  558 
  559         if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
  560                 u_int8_t fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST;
  561                 u_int8_t lcr;
  562 
  563                 if (tp->t_ispeed <= 1200)
  564                         fifo |= FIFO_TRIGGER_1;
  565                 else if (tp->t_ispeed <= 38400)
  566                         fifo |= FIFO_TRIGGER_4;
  567                 else
  568                         fifo |= FIFO_TRIGGER_8;
  569                 if (sc->sc_uarttype == COM_UART_TI16750) {
  570                         fifo |= FIFO_ENABLE_64BYTE;
  571                         lcr = com_read_reg(sc, com_lcr);
  572                         com_write_reg(sc, com_lcr,
  573                             lcr | LCR_DLAB);
  574                 }
  575 
  576                 /*
  577                  * (Re)enable and drain FIFOs.
  578                  *
  579                  * Certain SMC chips cause problems if the FIFOs are
  580                  * enabled while input is ready. Turn off the FIFO
  581                  * if necessary to clear the input. Test the input
  582                  * ready bit after enabling the FIFOs to handle races
  583                  * between enabling and fresh input.
  584                  *
  585                  * Set the FIFO threshold based on the receive speed.
  586                  */
  587                 for (;;) {
  588                         com_write_reg(sc, com_fifo, 0);
  589                         delay(100);
  590                         (void) com_read_reg(sc, com_data);
  591                         com_write_reg(sc, com_fifo, fifo |
  592                             FIFO_RCV_RST | FIFO_XMT_RST);
  593                         delay(100);
  594                         if(!ISSET(com_read_reg(sc,
  595                             com_lsr), LSR_RXRDY))
  596                                 break;
  597                 }
  598                 if (sc->sc_uarttype == COM_UART_TI16750)
  599                         com_write_reg(sc, com_lcr, lcr);
  600         }
  601 
  602         /* You turn me on, baby! */
  603         com_write_reg(sc, com_mcr, sc->sc_mcr);
  604         com_write_reg(sc, com_ier, sc->sc_ier);
  605 }
  606 
  607 void
  608 com_raisedtr(void *arg)
  609 {
  610         struct com_softc *sc = arg;
  611 
  612         SET(sc->sc_mcr, MCR_DTR | MCR_RTS);
  613         com_write_reg(sc, com_mcr, sc->sc_mcr);
  614 }
  615 
  616 int
  617 comread(dev_t dev, struct uio *uio, int flag)
  618 {
  619         struct com_softc *sc = com_cd.cd_devs[DEVUNIT(dev)];
  620         struct tty *tp = sc->sc_tty;
  621 
  622         return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
  623 }
  624 
  625 int
  626 comwrite(dev_t dev, struct uio *uio, int flag)
  627 {
  628         struct com_softc *sc = com_cd.cd_devs[DEVUNIT(dev)];
  629         struct tty *tp = sc->sc_tty;
  630 
  631         return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
  632 }
  633 
  634 struct tty *
  635 comtty(dev_t dev)
  636 {
  637         struct com_softc *sc = com_cd.cd_devs[DEVUNIT(dev)];
  638         struct tty *tp = sc->sc_tty;
  639 
  640         return (tp);
  641 }
  642 
  643 static u_char
  644 tiocm_xxx2mcr(int data)
  645 {
  646         u_char m = 0;
  647 
  648         if (ISSET(data, TIOCM_DTR))
  649                 SET(m, MCR_DTR);
  650         if (ISSET(data, TIOCM_RTS))
  651                 SET(m, MCR_RTS);
  652         return m;
  653 }
  654 
  655 int
  656 comioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
  657 {
  658         int unit = DEVUNIT(dev);
  659         struct com_softc *sc = com_cd.cd_devs[unit];
  660         struct tty *tp = sc->sc_tty;
  661         int error;
  662 
  663         error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
  664         if (error >= 0)
  665                 return error;
  666         error = ttioctl(tp, cmd, data, flag, p);
  667         if (error >= 0)
  668                 return error;
  669 
  670         switch (cmd) {
  671         case TIOCSBRK:
  672                 SET(sc->sc_lcr, LCR_SBREAK);
  673                 com_write_reg(sc, com_lcr, sc->sc_lcr);
  674                 break;
  675         case TIOCCBRK:
  676                 CLR(sc->sc_lcr, LCR_SBREAK);
  677                 com_write_reg(sc, com_lcr, sc->sc_lcr);
  678                 break;
  679         case TIOCSDTR:
  680                 SET(sc->sc_mcr, sc->sc_dtr);
  681                 com_write_reg(sc, com_mcr, sc->sc_mcr);
  682                 break;
  683         case TIOCCDTR:
  684                 CLR(sc->sc_mcr, sc->sc_dtr);
  685                 com_write_reg(sc, com_mcr, sc->sc_mcr);
  686                 break;
  687         case TIOCMSET:
  688                 CLR(sc->sc_mcr, MCR_DTR | MCR_RTS);
  689         case TIOCMBIS:
  690                 SET(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
  691                 com_write_reg(sc, com_mcr, sc->sc_mcr);
  692                 break;
  693         case TIOCMBIC:
  694                 CLR(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
  695                 com_write_reg(sc, com_mcr, sc->sc_mcr);
  696                 break;
  697         case TIOCMGET: {
  698                 u_char m;
  699                 int bits = 0;
  700 
  701                 m = sc->sc_mcr;
  702                 if (ISSET(m, MCR_DTR))
  703                         SET(bits, TIOCM_DTR);
  704                 if (ISSET(m, MCR_RTS))
  705                         SET(bits, TIOCM_RTS);
  706                 m = sc->sc_msr;
  707                 if (ISSET(m, MSR_DCD))
  708                         SET(bits, TIOCM_CD);
  709                 if (ISSET(m, MSR_CTS))
  710                         SET(bits, TIOCM_CTS);
  711                 if (ISSET(m, MSR_DSR))
  712                         SET(bits, TIOCM_DSR);
  713                 if (ISSET(m, MSR_RI | MSR_TERI))
  714                         SET(bits, TIOCM_RI);
  715                 if (com_read_reg(sc, com_ier))
  716                         SET(bits, TIOCM_LE);
  717                 *(int *)data = bits;
  718                 break;
  719         }
  720         case TIOCGFLAGS: {
  721                 int driverbits, userbits = 0;
  722 
  723                 driverbits = sc->sc_swflags;
  724                 if (ISSET(driverbits, COM_SW_SOFTCAR))
  725                         SET(userbits, TIOCFLAG_SOFTCAR);
  726                 if (ISSET(driverbits, COM_SW_CLOCAL))
  727                         SET(userbits, TIOCFLAG_CLOCAL);
  728                 if (ISSET(driverbits, COM_SW_CRTSCTS))
  729                         SET(userbits, TIOCFLAG_CRTSCTS);
  730                 if (ISSET(driverbits, COM_SW_MDMBUF))
  731                         SET(userbits, TIOCFLAG_MDMBUF);
  732                 if (ISSET(driverbits, COM_SW_PPS))
  733                         SET(userbits, TIOCFLAG_PPS);
  734 
  735                 *(int *)data = userbits;
  736                 break;
  737         }
  738         case TIOCSFLAGS: {
  739                 int userbits, driverbits = 0;
  740 
  741                 error = suser(p);
  742                 if (error != 0)
  743                         return(EPERM);
  744 
  745                 userbits = *(int *)data;
  746                 if (ISSET(userbits, TIOCFLAG_SOFTCAR) ||
  747                     ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
  748                         SET(driverbits, COM_SW_SOFTCAR);
  749                 if (ISSET(userbits, TIOCFLAG_CLOCAL))
  750                         SET(driverbits, COM_SW_CLOCAL);
  751                 if (ISSET(userbits, TIOCFLAG_CRTSCTS))
  752                         SET(driverbits, COM_SW_CRTSCTS);
  753                 if (ISSET(userbits, TIOCFLAG_MDMBUF))
  754                         SET(driverbits, COM_SW_MDMBUF);
  755                 if (ISSET(userbits, TIOCFLAG_PPS))
  756                         SET(driverbits, COM_SW_PPS);
  757 
  758                 sc->sc_swflags = driverbits;
  759                 break;
  760         }
  761         default:
  762                 return ENOTTY;
  763         }
  764 
  765         return 0;
  766 }
  767 
  768 /* already called at spltty */
  769 int
  770 comparam(struct tty *tp, struct termios *t)
  771 {
  772         struct com_softc *sc = com_cd.cd_devs[DEVUNIT(tp->t_dev)];
  773         int ospeed = comspeed(sc->sc_frequency, t->c_ospeed);
  774         u_char lcr;
  775         tcflag_t oldcflag;
  776 
  777         /* Check requested parameters. */
  778         if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
  779                 return EINVAL;
  780 
  781         lcr = ISSET(sc->sc_lcr, LCR_SBREAK);
  782 
  783         switch (ISSET(t->c_cflag, CSIZE)) {
  784         case CS5:
  785                 SET(lcr, LCR_5BITS);
  786                 break;
  787         case CS6:
  788                 SET(lcr, LCR_6BITS);
  789                 break;
  790         case CS7:
  791                 SET(lcr, LCR_7BITS);
  792                 break;
  793         case CS8:
  794                 SET(lcr, LCR_8BITS);
  795                 break;
  796         }
  797         if (ISSET(t->c_cflag, PARENB)) {
  798                 SET(lcr, LCR_PENAB);
  799                 if (!ISSET(t->c_cflag, PARODD))
  800                         SET(lcr, LCR_PEVEN);
  801         }
  802         if (ISSET(t->c_cflag, CSTOPB))
  803                 SET(lcr, LCR_STOPB);
  804 
  805         sc->sc_lcr = lcr;
  806 
  807         if (ospeed == 0) {
  808                 CLR(sc->sc_mcr, MCR_DTR);
  809                 com_write_reg(sc, com_mcr, sc->sc_mcr);
  810         }
  811 
  812         /*
  813          * Set the FIFO threshold based on the receive speed, if we are
  814          * changing it.
  815          */
  816         if (sc->sc_initialize || (tp->t_ispeed != t->c_ispeed)) {
  817                 sc->sc_initialize = 0;
  818 
  819                 if (ospeed != 0) {
  820                         /*
  821                          * Make sure the transmit FIFO is empty before
  822                          * proceeding.  If we don't do this, some revisions
  823                          * of the UART will hang.  Interestingly enough,
  824                          * even if we do this while the last character is
  825                          * still being pushed out, they don't hang.  This
  826                          * seems good enough.
  827                          */
  828                         while (ISSET(tp->t_state, TS_BUSY)) {
  829                                 int error;
  830 
  831                                 ++sc->sc_halt;
  832                                 error = ttysleep(tp, &tp->t_outq,
  833                                     TTOPRI | PCATCH, "comprm");
  834                                 --sc->sc_halt;
  835                                 if (error) {
  836                                         comstart(tp);
  837                                         return (error);
  838                                 }
  839                         }
  840 
  841                         com_write_reg(sc, com_lcr, lcr | LCR_DLAB);
  842                         com_write_reg(sc, com_dlbl, ospeed);
  843                         com_write_reg(sc, com_dlbh, ospeed >> 8);
  844                         com_write_reg(sc, com_lcr, lcr);
  845                         SET(sc->sc_mcr, MCR_DTR);
  846                         com_write_reg(sc, com_mcr, sc->sc_mcr);
  847                 } else
  848                         com_write_reg(sc, com_lcr, lcr);
  849 
  850                 if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
  851                         if (sc->sc_uarttype == COM_UART_TI16750) {
  852                                 com_write_reg(sc, com_lcr,
  853                                     lcr | LCR_DLAB);
  854                                 com_write_reg(sc, com_fifo,
  855                                     FIFO_ENABLE | FIFO_ENABLE_64BYTE |
  856                                     (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
  857                                 com_write_reg(sc, com_lcr, lcr);
  858                         } else
  859                                 com_write_reg(sc, com_fifo,
  860                                     FIFO_ENABLE |
  861                                     (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8));
  862                 }
  863         } else
  864                 com_write_reg(sc, com_lcr, lcr);
  865 
  866         /* When not using CRTSCTS, RTS follows DTR. */
  867         if (!ISSET(t->c_cflag, CRTSCTS)) {
  868                 if (ISSET(sc->sc_mcr, MCR_DTR)) {
  869                         if (!ISSET(sc->sc_mcr, MCR_RTS)) {
  870                                 SET(sc->sc_mcr, MCR_RTS);
  871                                 com_write_reg(sc, com_mcr, sc->sc_mcr);
  872                         }
  873                 } else {
  874                         if (ISSET(sc->sc_mcr, MCR_RTS)) {
  875                                 CLR(sc->sc_mcr, MCR_RTS);
  876                                 com_write_reg(sc, com_mcr, sc->sc_mcr);
  877                         }
  878                 }
  879                 sc->sc_dtr = MCR_DTR | MCR_RTS;
  880         } else
  881                 sc->sc_dtr = MCR_DTR;
  882 
  883         /* and copy to tty */
  884         tp->t_ispeed = t->c_ispeed;
  885         tp->t_ospeed = t->c_ospeed;
  886         oldcflag = tp->t_cflag;
  887         tp->t_cflag = t->c_cflag;
  888 
  889         /*
  890          * If DCD is off and MDMBUF is changed, ask the tty layer if we should
  891          * stop the device.
  892          */
  893         if (!ISSET(sc->sc_msr, MSR_DCD) &&
  894             !ISSET(sc->sc_swflags, COM_SW_SOFTCAR) &&
  895             ISSET(oldcflag, MDMBUF) != ISSET(tp->t_cflag, MDMBUF) &&
  896             (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
  897                 CLR(sc->sc_mcr, sc->sc_dtr);
  898                 com_write_reg(sc, com_mcr, sc->sc_mcr);
  899         }
  900 
  901         /* Just to be sure... */
  902         comstart(tp);
  903         return 0;
  904 }
  905 
  906 void
  907 comstart(struct tty *tp)
  908 {
  909         struct com_softc *sc = com_cd.cd_devs[DEVUNIT(tp->t_dev)];
  910         int s;
  911 
  912         s = spltty();
  913         if (ISSET(tp->t_state, TS_BUSY))
  914                 goto out;
  915         if (ISSET(tp->t_state, TS_TIMEOUT | TS_TTSTOP) || sc->sc_halt > 0)
  916                 goto stopped;
  917         if (ISSET(tp->t_cflag, CRTSCTS) && !ISSET(sc->sc_msr, MSR_CTS))
  918                 goto stopped;
  919         ttwakeupwr(tp);
  920         if (tp->t_outq.c_cc == 0)
  921                 goto stopped;
  922         SET(tp->t_state, TS_BUSY);
  923 
  924         /* Enable transmit completion interrupts. */
  925         if (!ISSET(sc->sc_ier, IER_ETXRDY)) {
  926                 SET(sc->sc_ier, IER_ETXRDY);
  927                 com_write_reg(sc, com_ier, sc->sc_ier);
  928         }
  929 
  930         if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
  931                 u_char buffer[256];     /* largest fifo */
  932                 int i, n;
  933 
  934                 n = q_to_b(&tp->t_outq, buffer,
  935                     min(sc->sc_fifolen, sizeof buffer));
  936                 for (i = 0; i < n; i++) {
  937                         com_write_reg(sc, com_data, buffer[i]);
  938                 }
  939                 bzero(buffer, n);
  940         } else if (tp->t_outq.c_cc != 0)
  941                 com_write_reg(sc, com_data, getc(&tp->t_outq));
  942 out:
  943         splx(s);
  944         return;
  945 stopped:
  946         if (ISSET(sc->sc_ier, IER_ETXRDY)) {
  947                 CLR(sc->sc_ier, IER_ETXRDY);
  948                 com_write_reg(sc, com_ier, sc->sc_ier);
  949         }
  950         splx(s);
  951 }
  952 
  953 /*
  954  * Stop output on a line.
  955  */
  956 int
  957 comstop(struct tty *tp, int flag)
  958 {
  959         int s;
  960 
  961         s = spltty();
  962         if (ISSET(tp->t_state, TS_BUSY))
  963                 if (!ISSET(tp->t_state, TS_TTSTOP))
  964                         SET(tp->t_state, TS_FLUSH);
  965         splx(s);
  966         return 0;
  967 }
  968 
  969 void
  970 comdiag(void *arg)
  971 {
  972         struct com_softc *sc = arg;
  973         int overflows, floods;
  974         int s;
  975 
  976         s = spltty();
  977         sc->sc_errors = 0;
  978         overflows = sc->sc_overflows;
  979         sc->sc_overflows = 0;
  980         floods = sc->sc_floods;
  981         sc->sc_floods = 0;
  982         splx(s);
  983         log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf overflow%s\n",
  984             sc->sc_dev.dv_xname,
  985             overflows, overflows == 1 ? "" : "s",
  986             floods, floods == 1 ? "" : "s");
  987 }
  988 
  989 void
  990 comsoft(void *arg)
  991 {
  992         struct com_softc *sc = (struct com_softc *)arg;
  993         struct tty *tp;
  994         u_char *ibufp;
  995         u_char *ibufend;
  996         int c;
  997         int s;
  998         static int lsrmap[8] = {
  999                 0,      TTY_PE,
 1000                 TTY_FE, TTY_PE|TTY_FE,
 1001                 TTY_FE, TTY_PE|TTY_FE,
 1002                 TTY_FE, TTY_PE|TTY_FE
 1003         };
 1004 
 1005         if (sc == NULL || sc->sc_ibufp == sc->sc_ibuf)
 1006                 return;
 1007 
 1008         tp = sc->sc_tty;
 1009 
 1010         s = spltty();
 1011 
 1012         ibufp = sc->sc_ibuf;
 1013         ibufend = sc->sc_ibufp;
 1014 
 1015         if (ibufp == ibufend) {
 1016                 splx(s);
 1017                 return;
 1018         }
 1019 
 1020         sc->sc_ibufp = sc->sc_ibuf = (ibufp == sc->sc_ibufs[0]) ?
 1021                                      sc->sc_ibufs[1] : sc->sc_ibufs[0];
 1022         sc->sc_ibufhigh = sc->sc_ibuf + COM_IHIGHWATER;
 1023         sc->sc_ibufend = sc->sc_ibuf + COM_IBUFSIZE;
 1024 
 1025         if (tp == NULL || !ISSET(tp->t_state, TS_ISOPEN)) {
 1026                 splx(s);
 1027                 return;
 1028         }
 1029 
 1030         if (ISSET(tp->t_cflag, CRTSCTS) &&
 1031             !ISSET(sc->sc_mcr, MCR_RTS)) {
 1032                 /* XXX */
 1033                 SET(sc->sc_mcr, MCR_RTS);
 1034                 com_write_reg(sc, com_mcr, sc->sc_mcr);
 1035         }
 1036 
 1037         splx(s);
 1038 
 1039         while (ibufp < ibufend) {
 1040                 c = *ibufp++;
 1041                 if (ISSET(*ibufp, LSR_OE)) {
 1042                         sc->sc_overflows++;
 1043                         if (sc->sc_errors++ == 0)
 1044                                 timeout_add_sec(&sc->sc_diag_tmo, 60);
 1045                 }
 1046                 /* This is ugly, but fast. */
 1047                 c |= lsrmap[(*ibufp++ & (LSR_BI|LSR_FE|LSR_PE)) >> 2];
 1048                 (*linesw[tp->t_line].l_rint)(c, tp);
 1049         }
 1050 }
 1051 
 1052 int
 1053 comintr(void *arg)
 1054 {
 1055         struct com_softc *sc = arg;
 1056         struct tty *tp;
 1057         u_char lsr, data, msr, delta;
 1058 
 1059         if (!sc->sc_tty)
 1060                 return (0);             /* Can't do squat. */
 1061 
 1062         if (ISSET(com_read_reg(sc, com_iir), IIR_NOPEND))
 1063                 return (0);
 1064 
 1065         tp = sc->sc_tty;
 1066 
 1067         for (;;) {
 1068                 lsr = com_read_reg(sc, com_lsr);
 1069 
 1070                 if (ISSET(lsr, LSR_RXRDY)) {
 1071                         u_char *p = sc->sc_ibufp;
 1072 
 1073                         softintr_schedule(sc->sc_si);
 1074                         do {
 1075                                 data = com_read_reg(sc, com_data);
 1076                                 if (ISSET(lsr, LSR_BI)) {
 1077 #if defined(COM_CONSOLE) && defined(DDB)
 1078                                         if (ISSET(sc->sc_hwflags,
 1079                                             COM_HW_CONSOLE)) {
 1080                                                 if (db_console)
 1081                                                         db_enter();
 1082                                                 goto next;
 1083                                         }
 1084 #endif
 1085                                         data = 0;
 1086                                 }
 1087                                 if (p >= sc->sc_ibufend) {
 1088                                         sc->sc_floods++;
 1089                                         if (sc->sc_errors++ == 0)
 1090                                                 timeout_add_sec(&sc->sc_diag_tmo, 60);
 1091                                 } else {
 1092                                         *p++ = data;
 1093                                         *p++ = lsr;
 1094                                         if (p == sc->sc_ibufhigh &&
 1095                                             ISSET(tp->t_cflag, CRTSCTS)) {
 1096                                                 /* XXX */
 1097                                                 CLR(sc->sc_mcr, MCR_RTS);
 1098                                                 com_write_reg(sc, com_mcr,
 1099                                                     sc->sc_mcr);
 1100                                         }
 1101                                 }
 1102 #if defined(COM_CONSOLE) && defined(DDB)
 1103                         next:
 1104 #endif
 1105                                 lsr = com_read_reg(sc, com_lsr);
 1106                         } while (ISSET(lsr, LSR_RXRDY));
 1107 
 1108                         sc->sc_ibufp = p;
 1109                 }
 1110                 msr = com_read_reg(sc, com_msr);
 1111 
 1112                 if (msr != sc->sc_msr) {
 1113                         delta = msr ^ sc->sc_msr;
 1114 
 1115                         ttytstamp(tp, sc->sc_msr & MSR_CTS, msr & MSR_CTS,
 1116                             sc->sc_msr & MSR_DCD, msr & MSR_DCD);
 1117 
 1118                         sc->sc_msr = msr;
 1119                         if (ISSET(delta, MSR_DCD)) {
 1120                                 if (!ISSET(sc->sc_swflags, COM_SW_SOFTCAR) &&
 1121                                     (*linesw[tp->t_line].l_modem)(tp, ISSET(msr, MSR_DCD)) == 0) {
 1122                                         CLR(sc->sc_mcr, sc->sc_dtr);
 1123                                         com_write_reg(sc, com_mcr, sc->sc_mcr);
 1124                                 }
 1125                         }
 1126                         if (ISSET(delta & msr, MSR_CTS) &&
 1127                             ISSET(tp->t_cflag, CRTSCTS)) {
 1128                                 /* the line is up and we want to do rts/cts flow control */
 1129                                 (*linesw[tp->t_line].l_start)(tp);
 1130                         }
 1131                 }
 1132 
 1133                 if (ISSET(lsr, LSR_TXRDY) && ISSET(tp->t_state, TS_BUSY)) {
 1134                         CLR(tp->t_state, TS_BUSY | TS_FLUSH);
 1135                         if (sc->sc_halt > 0)
 1136                                 wakeup(&tp->t_outq);
 1137                         (*linesw[tp->t_line].l_start)(tp);
 1138                 }
 1139 
 1140                 if (ISSET(com_read_reg(sc, com_iir), IIR_NOPEND))
 1141                         return (1);
 1142         }
 1143 }
 1144 
 1145 void
 1146 cominit(bus_space_tag_t iot, bus_space_handle_t ioh, int rate, int frequency)
 1147 {
 1148         int s = splhigh();
 1149         u_char stat;
 1150 
 1151         bus_space_write_1(iot, ioh, com_lcr, LCR_DLAB);
 1152         rate = comspeed(frequency, rate); /* XXX not comdefaultrate? */
 1153         bus_space_write_1(iot, ioh, com_dlbl, rate);
 1154         bus_space_write_1(iot, ioh, com_dlbh, rate >> 8);
 1155         bus_space_write_1(iot, ioh, com_lcr, LCR_8BITS);
 1156         bus_space_write_1(iot, ioh, com_mcr, MCR_DTR | MCR_RTS);
 1157         bus_space_write_1(iot, ioh, com_ier, 0);  /* Make sure they are off */
 1158         bus_space_write_1(iot, ioh, com_fifo,
 1159             FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_1);
 1160         stat = bus_space_read_1(iot, ioh, com_iir);
 1161         splx(s);
 1162 }
 1163 
 1164 #ifdef COM_CONSOLE
 1165 void  
 1166 comcnprobe(struct consdev *cp)
 1167 {
 1168         bus_space_handle_t ioh;
 1169         int found;
 1170 
 1171         if (comconsaddr == 0)
 1172                 return;
 1173 
 1174         if (bus_space_map(comconsiot, comconsaddr, COM_NPORTS, 0, &ioh))
 1175                 return;
 1176         found = comprobe1(comconsiot, ioh);
 1177         bus_space_unmap(comconsiot, ioh, COM_NPORTS);
 1178         if (!found)
 1179                 return;
 1180 
 1181         /* Locate the major number. */
 1182         for (commajor = 0; commajor < nchrdev; commajor++)
 1183                 if (cdevsw[commajor].d_open == comopen)
 1184                         break;
 1185 
 1186         /* Initialize required fields. */
 1187         cp->cn_dev = makedev(commajor, comconsunit);
 1188         cp->cn_pri = CN_HIGHPRI;
 1189 }
 1190 
 1191 void
 1192 comcninit(struct consdev *cp)
 1193 {
 1194         if (bus_space_map(comconsiot, comconsaddr, COM_NPORTS, 0, &comconsioh))
 1195                 panic("comcninit: mapping failed");
 1196 
 1197         if (comconsfreq == 0)
 1198                 comconsfreq = COM_FREQ;
 1199 
 1200         cominit(comconsiot, comconsioh, comconsrate, comconsfreq);
 1201 }
 1202 
 1203 int
 1204 comcnattach(bus_space_tag_t iot, bus_addr_t iobase, int rate,
 1205     int frequency, tcflag_t cflag)
 1206 {
 1207         static struct consdev comcons = {
 1208                 NULL, NULL, comcngetc, comcnputc, comcnpollc, NULL,
 1209                 NODEV, CN_LOWPRI
 1210         };
 1211 
 1212 #ifndef __sparc64__
 1213         if (bus_space_map(iot, iobase, COM_NPORTS, 0, &comconsioh))
 1214                 return ENOMEM;
 1215 #endif
 1216 
 1217         cominit(iot, comconsioh, rate, frequency);
 1218 
 1219         cn_tab = &comcons;
 1220 
 1221         comconsiot = iot;
 1222         comconsaddr = iobase;
 1223         comconscflag = cflag;
 1224         comconsfreq = frequency;
 1225         comconsrate = rate;
 1226 
 1227         return (0);
 1228 }
 1229 
 1230 int
 1231 comcngetc(dev_t dev)
 1232 {
 1233         int s = splhigh();
 1234         u_char stat, c;
 1235 
 1236         /* Block until a character becomes available. */
 1237         while (!ISSET(stat = comcn_read_reg(com_lsr), LSR_RXRDY))
 1238                 continue;
 1239 
 1240         c = comcn_read_reg(com_data);
 1241 
 1242         /* Clear any interrupts generated by this transmission. */
 1243         stat = comcn_read_reg(com_iir);
 1244         splx(s);
 1245         return (c);
 1246 }
 1247 
 1248 /*
 1249  * Console kernel output character routine.
 1250  */
 1251 void
 1252 comcnputc(dev_t dev, int c)
 1253 {
 1254         int s = spltty();
 1255         int timo;
 1256 
 1257         /* Wait for any pending transmission to finish. */
 1258         timo = 2000;
 1259         while (!ISSET(comcn_read_reg(com_lsr), LSR_TXRDY) && --timo)
 1260                 delay(1);
 1261 
 1262         comcn_write_reg(com_data, (u_int8_t)(c & 0xff));
 1263         bus_space_barrier(comconsiot, comconsioh, 0,
 1264             COM_NPORTS << comcons_reg_shift,
 1265             (BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE));
 1266 
 1267         /* Wait for this transmission to complete. */
 1268         timo = 2000;
 1269         while (!ISSET(comcn_read_reg(com_lsr), LSR_TXRDY) && --timo)
 1270                 delay(1);
 1271 
 1272         splx(s);
 1273 }
 1274 
 1275 void
 1276 comcnpollc(dev_t dev, int on)
 1277 {
 1278 }
 1279 #endif  /* COM_CONSOLE */
 1280 
 1281 void    com_enable_debugport(struct com_softc *);
 1282 void    com_fifo_probe(struct com_softc *);
 1283 
 1284 #ifdef COM_CONSOLE
 1285 void
 1286 com_enable_debugport(struct com_softc *sc)
 1287 {
 1288         int s;
 1289 
 1290         /* Turn on line break interrupt, set carrier. */
 1291         s = splhigh();
 1292         SET(sc->sc_mcr, MCR_DTR | MCR_RTS | MCR_IENABLE);
 1293         com_write_reg(sc, com_mcr, sc->sc_mcr);
 1294 
 1295         splx(s);
 1296 }
 1297 #endif  /* COM_CONSOLE */
 1298 
 1299 void
 1300 com_attach_subr(struct com_softc *sc)
 1301 {
 1302         int probe = 0;
 1303         u_int8_t lcr, fifo;
 1304         u_int32_t cpr;
 1305 
 1306         sc->sc_ier = 0;
 1307         /* disable interrupts */
 1308         com_write_reg(sc, com_ier, sc->sc_ier);
 1309 
 1310 #ifdef COM_CONSOLE
 1311         if (sc->sc_iot == comconsiot && sc->sc_iobase == comconsaddr) {
 1312                 comconsattached = 1;
 1313                 delay(10000);                   /* wait for output to finish */
 1314                 SET(sc->sc_hwflags, COM_HW_CONSOLE);
 1315                 SET(sc->sc_swflags, COM_SW_SOFTCAR);
 1316         }
 1317 #endif
 1318 
 1319         /*
 1320          * Probe for all known forms of UART.
 1321          */
 1322         lcr = com_read_reg(sc, com_lcr);
 1323         com_write_reg(sc, com_lcr, LCR_EFR);
 1324         com_write_reg(sc, com_efr, 0);
 1325         com_write_reg(sc, com_lcr, 0);
 1326 
 1327         com_write_reg(sc, com_fifo, FIFO_ENABLE);
 1328         delay(100);
 1329 
 1330         /*
 1331          * Skip specific probes if attachment code knows it already.
 1332          */
 1333         if (sc->sc_uarttype == COM_UART_UNKNOWN) {
 1334                 switch (com_read_reg(sc, com_iir) >> 6) {
 1335                 case 0:
 1336                         sc->sc_uarttype = COM_UART_16450;
 1337                         break;
 1338                 case 2:
 1339                         sc->sc_uarttype = COM_UART_16550;
 1340                         break;
 1341                 case 3:
 1342                         sc->sc_uarttype = COM_UART_16550A;
 1343                         break;
 1344                 default:
 1345                         sc->sc_uarttype = COM_UART_UNKNOWN;
 1346                         break;
 1347                 }
 1348                 probe = 1;
 1349         }
 1350 
 1351         /* Probe for ST16650s */
 1352         if (probe && sc->sc_uarttype == COM_UART_16550A) {
 1353                 com_write_reg(sc, com_lcr, lcr | LCR_DLAB);
 1354                 if (com_read_reg(sc, com_efr) == 0) {
 1355                         com_write_reg(sc, com_efr, EFR_CTS);
 1356                         if (com_read_reg(sc, com_efr) != 0)
 1357                                 sc->sc_uarttype = COM_UART_ST16650;
 1358                         com_write_reg(sc, com_efr, 0);
 1359                 } else {
 1360                         com_write_reg(sc, com_lcr, LCR_EFR);
 1361                         if (com_read_reg(sc, com_efr) == 0)
 1362                                 sc->sc_uarttype = COM_UART_ST16650V2;
 1363                 }
 1364         }
 1365 
 1366 #if 0   /* until com works with large FIFOs */
 1367         /* Probe for XR16850s */
 1368         if (probe && sc->sc_uarttype == COM_UART_ST16650V2) {
 1369                 u_int8_t dlbl, dlbh;
 1370 
 1371                 /* Enable latch access and get the current values. */
 1372                 com_write_reg(sc, com_lcr, lcr | LCR_DLAB);
 1373                 dlbl = com_read_reg(sc, com_dlbl);
 1374                 dlbh = com_read_reg(sc, com_dlbh);
 1375 
 1376                 /* Zero out the latch divisors */
 1377                 com_write_reg(sc, com_dlbl, 0);
 1378                 com_write_reg(sc, com_dlbh, 0);
 1379 
 1380                 if (com_read_reg(sc, com_dlbh) == 0x10) {
 1381                         sc->sc_uarttype = COM_UART_XR16850;
 1382                         sc->sc_uartrev = com_read_reg(sc, com_dlbl);
 1383                 }
 1384 
 1385                 /* Reset to original. */
 1386                 com_write_reg(sc, com_dlbl, dlbl);
 1387                 com_write_reg(sc, com_dlbh, dlbh);
 1388         }
 1389 #endif
 1390 
 1391         /* Probe for TI16750s */
 1392         if (probe && sc->sc_uarttype == COM_UART_16550A) {
 1393                 com_write_reg(sc, com_lcr, lcr | LCR_DLAB);
 1394                 com_write_reg(sc, com_fifo,
 1395                     FIFO_ENABLE | FIFO_ENABLE_64BYTE);
 1396                 if ((com_read_reg(sc, com_iir) >> 5) == 7) {
 1397 #if 0
 1398                         com_write_reg(sc, com_lcr, 0);
 1399                         if ((com_read_reg(sc, com_iir) >> 5) == 6)
 1400 #endif
 1401                                 sc->sc_uarttype = COM_UART_TI16750;
 1402                 }
 1403                 com_write_reg(sc, com_fifo, FIFO_ENABLE);
 1404         }
 1405 
 1406         /* Reset the LCR (latch access is probably enabled). */
 1407         com_write_reg(sc, com_lcr, lcr);
 1408 
 1409         /* Probe for 8250 */
 1410         if (probe && sc->sc_uarttype == COM_UART_16450) {
 1411                 u_int8_t scr0, scr1, scr2;
 1412 
 1413                 scr0 = com_read_reg(sc, com_scratch);
 1414                 com_write_reg(sc, com_scratch, 0xa5);
 1415                 scr1 = com_read_reg(sc, com_scratch);
 1416                 com_write_reg(sc, com_scratch, 0x5a);
 1417                 scr2 = com_read_reg(sc, com_scratch);
 1418                 com_write_reg(sc, com_scratch, scr0);
 1419 
 1420                 if ((scr1 != 0xa5) || (scr2 != 0x5a))
 1421                         sc->sc_uarttype = COM_UART_8250;
 1422         }
 1423 
 1424         /*
 1425          * Print UART type and initialize ourself.
 1426          */
 1427         switch (sc->sc_uarttype) {
 1428         case COM_UART_UNKNOWN:
 1429                 printf(": unknown uart\n");
 1430                 break;
 1431         case COM_UART_8250:
 1432                 printf(": ns8250, no fifo\n");
 1433                 break;
 1434         case COM_UART_16450:
 1435                 printf(": ns16450, no fifo\n");
 1436                 break;
 1437         case COM_UART_16550:
 1438                 printf(": ns16550, no working fifo\n");
 1439                 break;
 1440         case COM_UART_16550A:
 1441                 if (sc->sc_fifolen == 0)
 1442                         sc->sc_fifolen = 16;
 1443                 printf(": ns16550a, %d byte fifo\n", sc->sc_fifolen);
 1444                 SET(sc->sc_hwflags, COM_HW_FIFO);
 1445                 break;
 1446         case COM_UART_ST16650:
 1447                 printf(": st16650, no working fifo\n");
 1448                 break;
 1449         case COM_UART_ST16650V2:
 1450                 if (sc->sc_fifolen == 0)
 1451                         sc->sc_fifolen = 32;
 1452                 printf(": st16650, %d byte fifo\n", sc->sc_fifolen);
 1453                 SET(sc->sc_hwflags, COM_HW_FIFO);
 1454                 break;
 1455         case COM_UART_ST16C654:
 1456                 printf(": st16c654, 64 byte fifo\n");
 1457                 SET(sc->sc_hwflags, COM_HW_FIFO);
 1458                 sc->sc_fifolen = 64;
 1459                 break;
 1460         case COM_UART_TI16750:
 1461                 printf(": ti16750, 64 byte fifo\n");
 1462                 SET(sc->sc_hwflags, COM_HW_FIFO);
 1463                 sc->sc_fifolen = 64;
 1464                 break;
 1465 #if 0
 1466         case COM_UART_XR16850:
 1467                 printf(": xr16850 (rev %d), 128 byte fifo\n", sc->sc_uartrev);
 1468                 SET(sc->sc_hwflags, COM_HW_FIFO);
 1469                 sc->sc_fifolen = 128;
 1470                 break;
 1471 #ifdef COM_UART_OX16C950
 1472         case COM_UART_OX16C950:
 1473                 printf(": ox16c950 (rev %d), 128 byte fifo\n", sc->sc_uartrev);
 1474                 SET(sc->sc_hwflags, COM_HW_FIFO);
 1475                 sc->sc_fifolen = 128;
 1476                 break;
 1477 #endif
 1478 #endif
 1479         case COM_UART_XR17V35X:
 1480                 printf(": xr17v35x, 256 byte fifo\n");
 1481                 SET(sc->sc_hwflags, COM_HW_FIFO);
 1482                 sc->sc_fifolen = 256;
 1483                 break;
 1484         case COM_UART_DW_APB:
 1485                 printf(": dw16550");
 1486                 SET(sc->sc_hwflags, COM_HW_FIFO);
 1487                 cpr = bus_space_read_4(sc->sc_iot, sc->sc_ioh, com_cpr << 2);
 1488                 sc->sc_fifolen = CPR_FIFO_MODE(cpr) * 16;
 1489                 if (sc->sc_fifolen) {
 1490                         printf(", %d byte fifo\n", sc->sc_fifolen);
 1491                 } else {
 1492                         printf("\n");
 1493                         /*
 1494                          * The DW-APB configuration on the Allwinner H6 SoC
 1495                          * does not provide the CPR register and will be
 1496                          * detected as having no FIFO.  But it does have a
 1497                          * 256-byte FIFO and with the FIFO disabled the
 1498                          * LSR_RXRDY bit remains set even if the input
 1499                          * buffer is empty.  As a workaround, treat as a
 1500                          * 1-byte FIFO.
 1501                          */
 1502                         sc->sc_fifolen = 1;
 1503                 }
 1504                 break;
 1505         default:
 1506                 panic("comattach: bad fifo type");
 1507         }
 1508 
 1509 #ifdef COM_CONSOLE
 1510         if (!ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
 1511 #endif
 1512                 if (sc->sc_fifolen < 256)
 1513                         com_fifo_probe(sc);
 1514 
 1515         if (sc->sc_fifolen == 0) {
 1516                 CLR(sc->sc_hwflags, COM_HW_FIFO);
 1517                 sc->sc_fifolen = 1;
 1518         }
 1519 
 1520         /* clear and disable fifo */
 1521         /* DW-APB UART cannot turn off FIFO here (ddb will not work) */
 1522         fifo = (sc->sc_uarttype == COM_UART_DW_APB) ?
 1523                 (FIFO_ENABLE | FIFO_TRIGGER_1) : 0;
 1524         com_write_reg(sc, com_fifo, fifo | FIFO_RCV_RST | FIFO_XMT_RST);
 1525         if (ISSET(com_read_reg(sc, com_lsr), LSR_RXRDY))
 1526                 (void)com_read_reg(sc, com_data);
 1527         com_write_reg(sc, com_fifo, fifo);
 1528 
 1529         sc->sc_mcr = 0;
 1530         com_write_reg(sc, com_mcr, sc->sc_mcr);
 1531 
 1532 #ifdef COM_CONSOLE
 1533         if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
 1534                 int maj;
 1535 
 1536                 /* locate the major number */
 1537                 for (maj = 0; maj < nchrdev; maj++)
 1538                         if (cdevsw[maj].d_open == comopen)
 1539                                 break;
 1540 
 1541                 KASSERT(maj < nchrdev);
 1542                 cn_tab->cn_dev = makedev(maj, sc->sc_dev.dv_unit);
 1543 
 1544                 printf("%s: console\n", sc->sc_dev.dv_xname);
 1545         }
 1546 #endif
 1547 
 1548         timeout_set(&sc->sc_diag_tmo, comdiag, sc);
 1549         timeout_set(&sc->sc_dtr_tmo, com_raisedtr, sc);
 1550         sc->sc_si = softintr_establish(IPL_TTY, comsoft, sc);
 1551         if (sc->sc_si == NULL)
 1552                 panic("%s: can't establish soft interrupt",
 1553                     sc->sc_dev.dv_xname);
 1554 
 1555         /*
 1556          * If there are no enable/disable functions, assume the device
 1557          * is always enabled.
 1558          */
 1559         if (!sc->enable)
 1560                 sc->enabled = 1;
 1561 
 1562 #ifdef COM_CONSOLE
 1563         if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
 1564                 com_enable_debugport(sc);
 1565 #endif
 1566 }
 1567 
 1568 void
 1569 com_fifo_probe(struct com_softc *sc)
 1570 {
 1571         u_int8_t fifo, ier;
 1572         int timo, len;
 1573 
 1574         if (!ISSET(sc->sc_hwflags, COM_HW_FIFO))
 1575                 return;
 1576 
 1577         ier = 0;
 1578         com_write_reg(sc, com_ier, ier);
 1579         com_write_reg(sc, com_lcr, LCR_DLAB);
 1580         com_write_reg(sc, com_dlbl, 3);
 1581         com_write_reg(sc, com_dlbh, 0);
 1582         com_write_reg(sc, com_lcr, LCR_PNONE | LCR_8BITS);
 1583         com_write_reg(sc, com_mcr, MCR_LOOPBACK);
 1584 
 1585         fifo = FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST;
 1586         if (sc->sc_uarttype == COM_UART_TI16750)
 1587                 fifo |= FIFO_ENABLE_64BYTE;
 1588 
 1589         com_write_reg(sc, com_fifo, fifo);
 1590 
 1591         for (len = 0; len < 256; len++) {
 1592                 com_write_reg(sc, com_data, (len + 1));
 1593                 timo = 2000;
 1594                 while (!ISSET(com_read_reg(sc, com_lsr),
 1595                     LSR_TXRDY) && --timo)
 1596                         delay(1);
 1597                 if (!timo)
 1598                         break;
 1599         }
 1600 
 1601         delay(100);
 1602 
 1603         for (len = 0; len < 256; len++) {
 1604                 timo = 2000;
 1605                 while (!ISSET(com_read_reg(sc, com_lsr),
 1606                     LSR_RXRDY) && --timo)
 1607                         delay(1);
 1608                 if (!timo || com_read_reg(sc, com_data) != (len + 1))
 1609                         break;
 1610         }
 1611 
 1612         /* For safety, always use the smaller value. */
 1613         if (sc->sc_fifolen > len) {
 1614                 printf("%s: probed fifo depth: %d bytes\n",
 1615                     sc->sc_dev.dv_xname, len);
 1616                 sc->sc_fifolen = len;
 1617         }
 1618 }
 1619 
 1620 uint8_t
 1621 com_read_reg(struct com_softc *sc, bus_size_t reg)
 1622 {
 1623         reg <<= sc->sc_reg_shift;
 1624 
 1625         if (sc->sc_reg_width == 4)
 1626                 return bus_space_read_4(sc->sc_iot, sc->sc_ioh, reg);
 1627         else
 1628                 return bus_space_read_1(sc->sc_iot, sc->sc_ioh, reg);
 1629 }
 1630 
 1631 void
 1632 com_write_reg(struct com_softc *sc, bus_size_t reg, uint8_t value)
 1633 {
 1634         reg <<= sc->sc_reg_shift;
 1635 
 1636         if (sc->sc_reg_width == 4)
 1637                 bus_space_write_4(sc->sc_iot, sc->sc_ioh, reg, value);
 1638         else
 1639                 bus_space_write_1(sc->sc_iot, sc->sc_ioh, reg, value);
 1640 }
 1641 
 1642 #ifdef COM_CONSOLE
 1643 
 1644 u_char comcons_reg_width;
 1645 u_char comcons_reg_shift;
 1646 
 1647 uint8_t
 1648 comcn_read_reg(bus_size_t reg)
 1649 {
 1650         reg <<= comcons_reg_shift;
 1651 
 1652         if (comcons_reg_width == 4)
 1653                 return bus_space_read_4(comconsiot, comconsioh, reg);
 1654         else
 1655                 return bus_space_read_1(comconsiot, comconsioh, reg);
 1656 }
 1657 
 1658 void
 1659 comcn_write_reg(bus_size_t reg, uint8_t value)
 1660 {
 1661         reg <<= comcons_reg_shift;
 1662 
 1663         if (comcons_reg_width == 4)
 1664                 bus_space_write_4(comconsiot, comconsioh, reg, value);
 1665         else
 1666                 bus_space_write_1(comconsiot, comconsioh, reg, value);
 1667 }
 1668 
 1669 #endif

Cache object: 7fd4da5e281eb273912964ef3986a7ae


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