LCOV - code coverage report
Current view: top level - dev/ic - com.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 846 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 34 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13