[BACK]Return to com.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / ic

Annotation of src/sys/dev/ic/com.c, Revision 1.216.2.3

1.216.2.3! skrll       1: /*     $NetBSD: com.c,v 1.216.2.2 2004/08/03 10:46:12 skrll Exp $      */
1.38      cgd         2:
1.1       cgd         3: /*-
1.216.2.2  skrll       4:  * Copyright (c) 1998, 1999, 2004 The NetBSD Foundation, Inc.
1.146     mycroft     5:  * All rights reserved.
1.99      mycroft     6:  *
1.146     mycroft     7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by Charles M. Hannum.
1.99      mycroft     9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  * 3. All advertising materials mentioning features or use of this software
                     19:  *    must display the following acknowledgement:
1.146     mycroft    20:  *        This product includes software developed by the NetBSD
                     21:  *        Foundation, Inc. and its contributors.
                     22:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     23:  *    contributors may be used to endorse or promote products derived
                     24:  *    from this software without specific prior written permission.
1.99      mycroft    25:  *
1.146     mycroft    26:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     27:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     28:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     29:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     30:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     31:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     32:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     33:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     34:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     35:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     36:  * POSSIBILITY OF SUCH DAMAGE.
1.99      mycroft    37:  */
                     38:
                     39: /*
1.1       cgd        40:  * Copyright (c) 1991 The Regents of the University of California.
                     41:  * All rights reserved.
                     42:  *
                     43:  * Redistribution and use in source and binary forms, with or without
                     44:  * modification, are permitted provided that the following conditions
                     45:  * are met:
                     46:  * 1. Redistributions of source code must retain the above copyright
                     47:  *    notice, this list of conditions and the following disclaimer.
                     48:  * 2. Redistributions in binary form must reproduce the above copyright
                     49:  *    notice, this list of conditions and the following disclaimer in the
                     50:  *    documentation and/or other materials provided with the distribution.
1.216.2.2  skrll      51:  * 3. Neither the name of the University nor the names of its contributors
1.1       cgd        52:  *    may be used to endorse or promote products derived from this software
                     53:  *    without specific prior written permission.
                     54:  *
                     55:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     56:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     57:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     58:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     59:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     60:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     61:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     62:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     63:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     64:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     65:  * SUCH DAMAGE.
                     66:  *
1.38      cgd        67:  *     @(#)com.c       7.5 (Berkeley) 5/16/91
1.1       cgd        68:  */
                     69:
                     70: /*
1.99      mycroft    71:  * COM driver, uses National Semiconductor NS16450/NS16550AF UART
1.116     fvdl       72:  * Supports automatic hardware flow control on StarTech ST16C650A UART
1.1       cgd        73:  */
1.191     lukem      74:
                     75: #include <sys/cdefs.h>
1.216.2.3! skrll      76: __KERNEL_RCSID(0, "$NetBSD: com.c,v 1.216.2.2 2004/08/03 10:46:12 skrll Exp $");
1.145     jonathan   77:
1.185     lukem      78: #include "opt_com.h"
1.145     jonathan   79: #include "opt_ddb.h"
1.185     lukem      80: #include "opt_kgdb.h"
1.213     martin     81: #include "opt_lockdebug.h"
                     82: #include "opt_multiprocessor.h"
1.216.2.2  skrll      83: #include "opt_ntp.h"
1.115     explorer   84:
                     85: #include "rnd.h"
                     86: #if NRND > 0 && defined(RND_COM)
                     87: #include <sys/rnd.h>
                     88: #endif
                     89:
1.216.2.2  skrll      90: /* The COM16650 option was renamed to COM_16650. */
                     91: #ifdef COM16650
                     92: #error Obsolete COM16650 option; use COM_16650 instead.
                     93: #endif
                     94:
1.186     uwe        95: /*
                     96:  * Override cnmagic(9) macro before including <sys/systm.h>.
                     97:  * We need to know if cn_check_magic triggered debugger, so set a flag.
                     98:  * Callers of cn_check_magic must declare int cn_trapped = 0;
                     99:  * XXX: this is *ugly*!
                    100:  */
                    101: #define cn_trap()                              \
                    102:        do {                                    \
                    103:                console_debugger();             \
                    104:                cn_trapped = 1;                 \
                    105:        } while (/* CONSTCOND */ 0)
                    106:
1.14      mycroft   107: #include <sys/param.h>
                    108: #include <sys/systm.h>
                    109: #include <sys/ioctl.h>
                    110: #include <sys/select.h>
                    111: #include <sys/tty.h>
                    112: #include <sys/proc.h>
                    113: #include <sys/user.h>
                    114: #include <sys/conf.h>
                    115: #include <sys/file.h>
                    116: #include <sys/uio.h>
                    117: #include <sys/kernel.h>
                    118: #include <sys/syslog.h>
1.21      mycroft   119: #include <sys/device.h>
1.127     mycroft   120: #include <sys/malloc.h>
1.144     jonathan  121: #include <sys/timepps.h>
1.149     thorpej   122: #include <sys/vnode.h>
1.14      mycroft   123:
1.99      mycroft   124: #include <machine/intr.h>
1.82      mycroft   125: #include <machine/bus.h>
1.14      mycroft   126:
1.113     thorpej   127: #include <dev/ic/comreg.h>
                    128: #include <dev/ic/comvar.h>
1.60      cgd       129: #include <dev/ic/ns16550reg.h>
1.116     fvdl      130: #include <dev/ic/st16650reg.h>
1.65      christos  131: #ifdef COM_HAYESP
                    132: #include <dev/ic/hayespreg.h>
                    133: #endif
1.62      mycroft   134: #define        com_lcr com_cfcr
1.106     drochner  135: #include <dev/cons.h>
1.14      mycroft   136:
1.65      christos  137: #ifdef COM_HAYESP
1.197     simonb    138: int comprobeHAYESP(bus_space_handle_t hayespioh, struct com_softc *sc);
1.65      christos  139: #endif
1.102     thorpej   140:
1.197     simonb    141: static void com_enable_debugport(struct com_softc *);
1.186     uwe       142:
1.197     simonb    143: void   com_config(struct com_softc *);
                    144: void   com_shutdown(struct com_softc *);
1.210     thorpej   145: int    comspeed(long, long, int);
1.197     simonb    146: static u_char  cflag2lcr(tcflag_t);
                    147: int    comparam(struct tty *, struct termios *);
                    148: void   comstart(struct tty *);
                    149: int    comhwiflow(struct tty *, int);
                    150:
                    151: void   com_loadchannelregs(struct com_softc *);
                    152: void   com_hwiflow(struct com_softc *);
                    153: void   com_break(struct com_softc *, int);
                    154: void   com_modem(struct com_softc *, int);
                    155: void   tiocm_to_com(struct com_softc *, u_long, int);
                    156: int    com_to_tiocm(struct com_softc *);
                    157: void   com_iflush(struct com_softc *);
1.80      christos  158:
1.197     simonb    159: int    com_common_getc(dev_t, bus_space_tag_t, bus_space_handle_t);
                    160: void   com_common_putc(dev_t, bus_space_tag_t, bus_space_handle_t, int);
1.102     thorpej   161:
1.210     thorpej   162: int    cominit(bus_space_tag_t, bus_addr_t, int, int, int, tcflag_t,
1.204     simonb    163:            bus_space_handle_t *);
1.187     simonb    164:
1.197     simonb    165: int    comcngetc(dev_t);
                    166: void   comcnputc(dev_t, int);
                    167: void   comcnpollc(dev_t, int);
1.80      christos  168:
1.99      mycroft   169: #define        integrate       static inline
1.183     thorpej   170: #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
1.197     simonb    171: void   comsoft(void *);
1.127     mycroft   172: #else
1.133     cgd       173: #ifndef __NO_SOFT_SERIAL_INTERRUPT
1.197     simonb    174: void   comsoft(void);
1.127     mycroft   175: #else
1.197     simonb    176: void   comsoft(void *);
1.216.2.2  skrll     177: static struct callout comsoft_callout = CALLOUT_INITIALIZER;
1.127     mycroft   178: #endif
                    179: #endif
1.197     simonb    180: integrate void com_rxsoft(struct com_softc *, struct tty *);
                    181: integrate void com_txsoft(struct com_softc *, struct tty *);
                    182: integrate void com_stsoft(struct com_softc *, struct tty *);
                    183: integrate void com_schedrx(struct com_softc *);
                    184: void   comdiag(void *);
1.127     mycroft   185:
1.130     thorpej   186: extern struct cfdriver com_cd;
1.76      thorpej   187:
1.199     gehenna   188: dev_type_open(comopen);
                    189: dev_type_close(comclose);
                    190: dev_type_read(comread);
                    191: dev_type_write(comwrite);
                    192: dev_type_ioctl(comioctl);
                    193: dev_type_stop(comstop);
                    194: dev_type_tty(comtty);
                    195: dev_type_poll(compoll);
                    196:
                    197: const struct cdevsw com_cdevsw = {
                    198:        comopen, comclose, comread, comwrite, comioctl,
1.200     jdolecek  199:        comstop, comtty, compoll, nommap, ttykqfilter, D_TTY
1.199     gehenna   200: };
                    201:
1.127     mycroft   202: /*
                    203:  * Make this an option variable one can patch.
                    204:  * But be warned:  this must be a power of 2!
                    205:  */
                    206: u_int com_rbuf_size = COM_RING_SIZE;
                    207:
                    208: /* Stop input when 3/4 of the ring is full; restart when only 1/4 is full. */
                    209: u_int com_rbuf_hiwat = (COM_RING_SIZE * 1) / 4;
                    210: u_int com_rbuf_lowat = (COM_RING_SIZE * 3) / 4;
                    211:
1.178     eeh       212: static bus_addr_t      comconsaddr;
1.106     drochner  213: static bus_space_tag_t comconstag;
                    214: static bus_space_handle_t comconsioh;
                    215: static int     comconsattached;
                    216: static int comconsrate;
                    217: static tcflag_t comconscflag;
1.186     uwe       218: static struct cnm_state com_cnm_state;
1.99      mycroft   219:
1.144     jonathan  220: static int ppscap =
                    221:        PPS_TSFMT_TSPEC |
                    222:        PPS_CAPTUREASSERT |
                    223:        PPS_CAPTURECLEAR |
                    224:        PPS_OFFSETASSERT | PPS_OFFSETCLEAR;
                    225:
1.183     thorpej   226: #ifndef __HAVE_GENERIC_SOFT_INTERRUPTS
1.133     cgd       227: #ifdef __NO_SOFT_SERIAL_INTERRUPT
1.99      mycroft   228: volatile int   com_softintr_scheduled;
                    229: #endif
                    230: #endif
1.1       cgd       231:
                    232: #ifdef KGDB
1.102     thorpej   233: #include <sys/kgdb.h>
1.106     drochner  234:
1.178     eeh       235: static bus_addr_t com_kgdb_addr;
1.106     drochner  236: static bus_space_tag_t com_kgdb_iot;
                    237: static bus_space_handle_t com_kgdb_ioh;
                    238: static int com_kgdb_attached;
1.102     thorpej   239:
1.197     simonb    240: int    com_kgdb_getc(void *);
                    241: void   com_kgdb_putc(void *, int);
1.102     thorpej   242: #endif /* KGDB */
1.1       cgd       243:
1.149     thorpej   244: #define        COMUNIT_MASK    0x7ffff
                    245: #define        COMDIALOUT_MASK 0x80000
                    246:
                    247: #define        COMUNIT(x)      (minor(x) & COMUNIT_MASK)
                    248: #define        COMDIALOUT(x)   (minor(x) & COMDIALOUT_MASK)
                    249:
                    250: #define        COM_ISALIVE(sc) ((sc)->enabled != 0 && \
                    251:                         ISSET((sc)->sc_dev.dv_flags, DVF_ACTIVE))
1.1       cgd       252:
1.160     thorpej   253: #define        BR      BUS_SPACE_BARRIER_READ
                    254: #define        BW      BUS_SPACE_BARRIER_WRITE
                    255: #define COM_BARRIER(t, h, f) bus_space_barrier((t), (h), 0, COM_NPORTS, (f))
                    256:
1.179     sommerfe  257: #if (defined(MULTIPROCESSOR) || defined(LOCKDEBUG)) && defined(COM_MPLOCK)
                    258:
                    259: #define COM_LOCK(sc) simple_lock(&(sc)->sc_lock)
                    260: #define COM_UNLOCK(sc) simple_unlock(&(sc)->sc_lock)
                    261:
                    262: #else
                    263:
                    264: #define COM_LOCK(sc)
                    265: #define COM_UNLOCK(sc)
                    266:
                    267: #endif
                    268:
1.210     thorpej   269: /*ARGSUSED*/
1.21      mycroft   270: int
1.210     thorpej   271: comspeed(long speed, long frequency, int type)
1.1       cgd       272: {
1.21      mycroft   273: #define        divrnd(n, q)    (((n)*2/(q)+1)/2)       /* divide and round off */
                    274:
                    275:        int x, err;
                    276:
1.99      mycroft   277: #if 0
1.21      mycroft   278:        if (speed == 0)
1.99      mycroft   279:                return (0);
                    280: #endif
                    281:        if (speed <= 0)
                    282:                return (-1);
1.109     is        283:        x = divrnd(frequency / 16, speed);
1.21      mycroft   284:        if (x <= 0)
1.99      mycroft   285:                return (-1);
1.114     is        286:        err = divrnd(((quad_t)frequency) * 1000 / 16, speed * x) - 1000;
1.21      mycroft   287:        if (err < 0)
                    288:                err = -err;
                    289:        if (err > COM_TOLERANCE)
1.99      mycroft   290:                return (-1);
                    291:        return (x);
1.21      mycroft   292:
1.172     thorpej   293: #undef divrnd
1.21      mycroft   294: }
                    295:
1.99      mycroft   296: #ifdef COM_DEBUG
1.101     mycroft   297: int    com_debug = 0;
                    298:
1.197     simonb    299: void comstatus(struct com_softc *, char *);
1.99      mycroft   300: void
1.197     simonb    301: comstatus(struct com_softc *sc, char *str)
1.99      mycroft   302: {
                    303:        struct tty *tp = sc->sc_tty;
                    304:
1.216.2.2  skrll     305:        printf("%s: %s %cclocal  %cdcd %cts_carr_on %cdtr %ctx_stopped\n",
1.99      mycroft   306:            sc->sc_dev.dv_xname, str,
1.216.2.2  skrll     307:            ISSET(tp->t_cflag, CLOCAL) ? '+' : '-',
                    308:            ISSET(sc->sc_msr, MSR_DCD) ? '+' : '-',
                    309:            ISSET(tp->t_state, TS_CARR_ON) ? '+' : '-',
                    310:            ISSET(sc->sc_mcr, MCR_DTR) ? '+' : '-',
                    311:            sc->sc_tx_stopped ? '+' : '-');
1.99      mycroft   312:
1.216.2.2  skrll     313:        printf("%s: %s %ccrtscts %ccts %cts_ttstop  %crts rx_flags=0x%x\n",
1.99      mycroft   314:            sc->sc_dev.dv_xname, str,
1.216.2.2  skrll     315:            ISSET(tp->t_cflag, CRTSCTS) ? '+' : '-',
                    316:            ISSET(sc->sc_msr, MSR_CTS) ? '+' : '-',
                    317:            ISSET(tp->t_state, TS_TTSTOP) ? '+' : '-',
                    318:            ISSET(sc->sc_mcr, MCR_RTS) ? '+' : '-',
1.101     mycroft   319:            sc->sc_rx_flags);
1.99      mycroft   320: }
                    321: #endif
                    322:
1.21      mycroft   323: int
1.197     simonb    324: comprobe1(bus_space_tag_t iot, bus_space_handle_t ioh)
1.21      mycroft   325: {
                    326:
1.1       cgd       327:        /* force access to id reg */
1.154     drochner  328:        bus_space_write_1(iot, ioh, com_lcr, LCR_8BITS);
1.91      thorpej   329:        bus_space_write_1(iot, ioh, com_iir, 0);
1.154     drochner  330:        if ((bus_space_read_1(iot, ioh, com_lcr) != LCR_8BITS) ||
                    331:            (bus_space_read_1(iot, ioh, com_iir) & 0x38))
1.99      mycroft   332:                return (0);
1.21      mycroft   333:
1.99      mycroft   334:        return (1);
1.1       cgd       335: }
                    336:
1.65      christos  337: #ifdef COM_HAYESP
                    338: int
1.197     simonb    339: comprobeHAYESP(bus_space_handle_t hayespioh, struct com_softc *sc)
1.64      christos  340: {
1.65      christos  341:        char    val, dips;
1.64      christos  342:        int     combaselist[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
1.91      thorpej   343:        bus_space_tag_t iot = sc->sc_iot;
1.64      christos  344:
                    345:        /*
                    346:         * Hayes ESP cards have two iobases.  One is for compatibility with
                    347:         * 16550 serial chips, and at the same ISA PC base addresses.  The
                    348:         * other is for ESP-specific enhanced features, and lies at a
1.65      christos  349:         * different addressing range entirely (0x140, 0x180, 0x280, or 0x300).
1.64      christos  350:         */
                    351:
                    352:        /* Test for ESP signature */
1.91      thorpej   353:        if ((bus_space_read_1(iot, hayespioh, 0) & 0xf3) == 0)
1.99      mycroft   354:                return (0);
1.64      christos  355:
                    356:        /*
                    357:         * ESP is present at ESP enhanced base address; unknown com port
                    358:         */
                    359:
                    360:        /* Get the dip-switch configurations */
1.91      thorpej   361:        bus_space_write_1(iot, hayespioh, HAYESP_CMD1, HAYESP_GETDIPS);
                    362:        dips = bus_space_read_1(iot, hayespioh, HAYESP_STATUS1);
1.64      christos  363:
                    364:        /* Determine which com port this ESP card services: bits 0,1 of  */
                    365:        /*  dips is the port # (0-3); combaselist[val] is the com_iobase */
1.65      christos  366:        if (sc->sc_iobase != combaselist[dips & 0x03])
1.99      mycroft   367:                return (0);
1.65      christos  368:
1.90      christos  369:        printf(": ESP");
1.64      christos  370:
1.65      christos  371:        /* Check ESP Self Test bits. */
1.64      christos  372:        /* Check for ESP version 2.0: bits 4,5,6 == 010 */
1.91      thorpej   373:        bus_space_write_1(iot, hayespioh, HAYESP_CMD1, HAYESP_GETTEST);
1.99      mycroft   374:        val = bus_space_read_1(iot, hayespioh, HAYESP_STATUS1); /* Clear reg1 */
1.91      thorpej   375:        val = bus_space_read_1(iot, hayespioh, HAYESP_STATUS2);
1.64      christos  376:        if ((val & 0x70) < 0x20) {
1.90      christos  377:                printf("-old (%o)", val & 0x70);
1.64      christos  378:                /* we do not support the necessary features */
1.99      mycroft   379:                return (0);
1.64      christos  380:        }
                    381:
                    382:        /* Check for ability to emulate 16550: bit 8 == 1 */
                    383:        if ((dips & 0x80) == 0) {
1.90      christos  384:                printf(" slave");
1.64      christos  385:                /* XXX Does slave really mean no 16550 support?? */
1.99      mycroft   386:                return (0);
1.64      christos  387:        }
                    388:
                    389:        /*
                    390:         * If we made it this far, we are a full-featured ESP v2.0 (or
                    391:         * better), at the correct com port address.
                    392:         */
                    393:
1.209     thorpej   394:        sc->sc_type = COM_TYPE_HAYESP;
1.90      christos  395:        printf(", 1024 byte fifo\n");
1.99      mycroft   396:        return (1);
1.64      christos  397: }
1.65      christos  398: #endif
1.64      christos  399:
1.104     drochner  400: static void
1.197     simonb    401: com_enable_debugport(struct com_softc *sc)
1.104     drochner  402: {
                    403:        int s;
                    404:
                    405:        /* Turn on line break interrupt, set carrier. */
                    406:        s = splserial();
1.179     sommerfe  407:        COM_LOCK(sc);
1.104     drochner  408:        sc->sc_ier = IER_ERXRDY;
1.208     scw       409: #ifdef COM_PXA2X0
1.209     thorpej   410:        if (sc->sc_type == COM_TYPE_PXA2x0)
1.208     scw       411:                sc->sc_ier |= IER_EUART | IER_ERXTOUT;
                    412: #endif
1.104     drochner  413:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_ier, sc->sc_ier);
                    414:        SET(sc->sc_mcr, MCR_DTR | MCR_RTS);
                    415:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_mcr, sc->sc_mcr);
1.179     sommerfe  416:        COM_UNLOCK(sc);
1.104     drochner  417:        splx(s);
                    418: }
1.1       cgd       419:
1.29      mycroft   420: void
1.197     simonb    421: com_attach_subr(struct com_softc *sc)
1.29      mycroft   422: {
1.178     eeh       423:        bus_addr_t iobase = sc->sc_iobase;
1.99      mycroft   424:        bus_space_tag_t iot = sc->sc_iot;
                    425:        bus_space_handle_t ioh = sc->sc_ioh;
1.127     mycroft   426:        struct tty *tp;
1.216.2.2  skrll     427: #ifdef COM_16650
1.116     fvdl      428:        u_int8_t lcr;
1.118     fvdl      429: #endif
1.65      christos  430: #ifdef COM_HAYESP
                    431:        int     hayesp_ports[] = { 0x140, 0x180, 0x280, 0x300, 0 };
                    432:        int     *hayespp;
                    433: #endif
1.208     scw       434:        const char *fifo_msg = NULL;
1.117     mycroft   435:
1.170     thorpej   436:        callout_init(&sc->sc_diag_callout);
1.180     sommerfe  437: #if (defined(MULTIPROCESSOR) || defined(LOCKDEBUG)) && defined(COM_MPLOCK)
1.179     sommerfe  438:        simple_lock_init(&sc->sc_lock);
                    439: #endif
1.170     thorpej   440:
1.117     mycroft   441:        /* Disable interrupts before configuring the device. */
1.208     scw       442: #ifdef COM_PXA2X0
1.209     thorpej   443:        if (sc->sc_type == COM_TYPE_PXA2x0)
1.208     scw       444:                sc->sc_ier = IER_EUART;
                    445:        else
                    446: #endif
                    447:                sc->sc_ier = 0;
1.131     marc      448:        bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
1.1       cgd       449:
1.106     drochner  450:        if (iot == comconstag && iobase == comconsaddr) {
1.105     drochner  451:                comconsattached = 1;
                    452:
1.96      mycroft   453:                /* Make sure the console is always "hardwired". */
1.216.2.2  skrll     454:                delay(10000);                   /* wait for output to finish */
1.75      cgd       455:                SET(sc->sc_hwflags, COM_HW_CONSOLE);
1.99      mycroft   456:                SET(sc->sc_swflags, TIOCFLAG_SOFTCAR);
1.75      cgd       457:        }
1.26      cgd       458:
1.65      christos  459: #ifdef COM_HAYESP
1.188     enami     460:        sc->sc_prescaler = 0;                   /* set prescaler to x1. */
                    461:
1.65      christos  462:        /* Look for a Hayes ESP board. */
1.75      cgd       463:        for (hayespp = hayesp_ports; *hayespp != 0; hayespp++) {
1.91      thorpej   464:                bus_space_handle_t hayespioh;
1.75      cgd       465:
                    466: #define        HAYESP_NPORTS   8                       /* XXX XXX XXX ??? ??? ??? */
1.92      cgd       467:                if (bus_space_map(iot, *hayespp, HAYESP_NPORTS, 0, &hayespioh))
1.75      cgd       468:                        continue;
                    469:                if (comprobeHAYESP(hayespioh, sc)) {
                    470:                        sc->sc_hayespioh = hayespioh;
1.99      mycroft   471:                        sc->sc_fifolen = 1024;
                    472:
1.65      christos  473:                        break;
                    474:                }
1.91      thorpej   475:                bus_space_unmap(iot, hayespioh, HAYESP_NPORTS);
1.75      cgd       476:        }
1.65      christos  477:        /* No ESP; look for other things. */
1.209     thorpej   478:        if (sc->sc_type != COM_TYPE_HAYESP) {
1.65      christos  479: #endif
1.99      mycroft   480:        sc->sc_fifolen = 1;
1.1       cgd       481:        /* look for a NS 16550AF UART with FIFOs */
1.91      thorpej   482:        bus_space_write_1(iot, ioh, com_fifo,
1.21      mycroft   483:            FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_14);
1.20      mycroft   484:        delay(100);
1.99      mycroft   485:        if (ISSET(bus_space_read_1(iot, ioh, com_iir), IIR_FIFO_MASK)
                    486:            == IIR_FIFO_MASK)
                    487:                if (ISSET(bus_space_read_1(iot, ioh, com_fifo), FIFO_TRIGGER_14)
                    488:                    == FIFO_TRIGGER_14) {
1.62      mycroft   489:                        SET(sc->sc_hwflags, COM_HW_FIFO);
1.116     fvdl      490:
1.216.2.2  skrll     491: #ifdef COM_16650
1.116     fvdl      492:                        /*
                    493:                         * IIR changes into the EFR if LCR is set to LCR_EERS
                    494:                         * on 16650s. We also know IIR != 0 at this point.
                    495:                         * Write 0 into the EFR, and read it. If the result
                    496:                         * is 0, we have a 16650.
                    497:                         *
                    498:                         * Older 16650s were broken; the test to detect them
                    499:                         * is taken from the Linux driver. Apparently
                    500:                         * setting DLAB enable gives access to the EFR on
                    501:                         * these chips.
                    502:                         */
                    503:                        lcr = bus_space_read_1(iot, ioh, com_lcr);
                    504:                        bus_space_write_1(iot, ioh, com_lcr, LCR_EERS);
                    505:                        bus_space_write_1(iot, ioh, com_efr, 0);
                    506:                        if (bus_space_read_1(iot, ioh, com_efr) == 0) {
                    507:                                bus_space_write_1(iot, ioh, com_lcr,
                    508:                                    lcr | LCR_DLAB);
                    509:                                if (bus_space_read_1(iot, ioh, com_efr) == 0) {
                    510:                                        CLR(sc->sc_hwflags, COM_HW_FIFO);
                    511:                                        sc->sc_fifolen = 0;
                    512:                                } else {
                    513:                                        SET(sc->sc_hwflags, COM_HW_FLOW);
                    514:                                        sc->sc_fifolen = 32;
                    515:                                }
1.118     fvdl      516:                        } else
                    517: #endif
1.116     fvdl      518:                                sc->sc_fifolen = 16;
                    519:
1.216.2.2  skrll     520: #ifdef COM_16650
1.119     drochner  521:                        bus_space_write_1(iot, ioh, com_lcr, lcr);
                    522:                        if (sc->sc_fifolen == 0)
1.208     scw       523:                                fifo_msg = "st16650, broken fifo";
1.119     drochner  524:                        else if (sc->sc_fifolen == 32)
1.208     scw       525:                                fifo_msg = "st16650a, working fifo";
1.119     drochner  526:                        else
1.118     fvdl      527: #endif
1.208     scw       528:                                fifo_msg = "ns16550a, working fifo";
1.21      mycroft   529:                } else
1.208     scw       530:                        fifo_msg = "ns16550, broken fifo";
1.21      mycroft   531:        else
1.208     scw       532:                fifo_msg = "ns8250 or ns16450, no fifo";
1.91      thorpej   533:        bus_space_write_1(iot, ioh, com_fifo, 0);
1.208     scw       534:        /*
                    535:         * Some chips will clear down both Tx and Rx FIFOs when zero is
                    536:         * written to com_fifo. If this chip is the console, writing zero
                    537:         * results in some of the chip/FIFO description being lost, so delay
                    538:         * printing it until now.
                    539:         */
                    540:        delay(10);
                    541:        aprint_normal(": %s\n", fifo_msg);
1.166     soda      542:        if (ISSET(sc->sc_hwflags, COM_HW_TXFIFO_DISABLE)) {
                    543:                sc->sc_fifolen = 1;
1.202     thorpej   544:                aprint_normal("%s: txfifo disabled\n", sc->sc_dev.dv_xname);
1.166     soda      545:        }
1.65      christos  546: #ifdef COM_HAYESP
                    547:        }
                    548: #endif
1.21      mycroft   549:
1.127     mycroft   550:        tp = ttymalloc();
                    551:        tp->t_oproc = comstart;
                    552:        tp->t_param = comparam;
                    553:        tp->t_hwiflow = comhwiflow;
                    554:
                    555:        sc->sc_tty = tp;
1.147     thorpej   556:        sc->sc_rbuf = malloc(com_rbuf_size << 1, M_DEVBUF, M_NOWAIT);
1.182     sommerfe  557:        sc->sc_rbput = sc->sc_rbget = sc->sc_rbuf;
                    558:        sc->sc_rbavail = com_rbuf_size;
1.147     thorpej   559:        if (sc->sc_rbuf == NULL) {
1.202     thorpej   560:                aprint_error("%s: unable to allocate ring buffer\n",
1.147     thorpej   561:                    sc->sc_dev.dv_xname);
                    562:                return;
                    563:        }
1.127     mycroft   564:        sc->sc_ebuf = sc->sc_rbuf + (com_rbuf_size << 1);
1.147     thorpej   565:
                    566:        tty_attach(tp);
                    567:
1.99      mycroft   568:        if (!ISSET(sc->sc_hwflags, COM_HW_NOIEN))
                    569:                SET(sc->sc_mcr, MCR_IENABLE);
1.30      mycroft   570:
1.96      mycroft   571:        if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
1.106     drochner  572:                int maj;
                    573:
                    574:                /* locate the major number */
1.199     gehenna   575:                maj = cdevsw_lookup_major(&com_cdevsw);
1.106     drochner  576:
1.207     fvdl      577:                tp->t_dev = cn_tab->cn_dev = makedev(maj, sc->sc_dev.dv_unit);
1.131     marc      578:
1.202     thorpej   579:                aprint_normal("%s: console\n", sc->sc_dev.dv_xname);
1.96      mycroft   580:        }
                    581:
1.1       cgd       582: #ifdef KGDB
1.102     thorpej   583:        /*
                    584:         * Allow kgdb to "take over" this port.  If this is
1.206     briggs    585:         * not the console and is the kgdb device, it has
                    586:         * exclusive use.  If it's the console _and_ the
                    587:         * kgdb device, it doesn't.
1.102     thorpej   588:         */
1.106     drochner  589:        if (iot == com_kgdb_iot && iobase == com_kgdb_addr) {
1.206     briggs    590:                if (!ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
                    591:                        com_kgdb_attached = 1;
1.106     drochner  592:
1.206     briggs    593:                        SET(sc->sc_hwflags, COM_HW_KGDB);
                    594:                }
1.202     thorpej   595:                aprint_normal("%s: kgdb\n", sc->sc_dev.dv_xname);
1.103     drochner  596:        }
1.99      mycroft   597: #endif
                    598:
1.183     thorpej   599: #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
1.99      mycroft   600:        sc->sc_si = softintr_establish(IPL_SOFTSERIAL, comsoft, sc);
1.1       cgd       601: #endif
1.115     explorer  602:
                    603: #if NRND > 0 && defined(RND_COM)
                    604:        rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname,
1.155     explorer  605:                          RND_TYPE_TTY, 0);
1.115     explorer  606: #endif
1.131     marc      607:
                    608:        /* if there are no enable/disable functions, assume the device
                    609:           is always enabled */
                    610:        if (!sc->enable)
                    611:                sc->enabled = 1;
                    612:
                    613:        com_config(sc);
1.132     cgd       614:
                    615:        SET(sc->sc_hwflags, COM_HW_DEV_OK);
1.131     marc      616: }
                    617:
                    618: void
1.197     simonb    619: com_config(struct com_softc *sc)
1.131     marc      620: {
                    621:        bus_space_tag_t iot = sc->sc_iot;
                    622:        bus_space_handle_t ioh = sc->sc_ioh;
                    623:
                    624:        /* Disable interrupts before configuring the device. */
1.208     scw       625: #ifdef COM_PXA2X0
1.209     thorpej   626:        if (sc->sc_type == COM_TYPE_PXA2x0)
1.208     scw       627:                sc->sc_ier = IER_EUART;
                    628:        else
                    629: #endif
                    630:                sc->sc_ier = 0;
1.131     marc      631:        bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
1.216.2.3! skrll     632:        (void) bus_space_read_1(iot, ioh, com_iir);
1.131     marc      633:
                    634: #ifdef COM_HAYESP
                    635:        /* Look for a Hayes ESP board. */
1.209     thorpej   636:        if (sc->sc_type == COM_TYPE_HAYESP) {
1.131     marc      637:                sc->sc_fifolen = 1024;
                    638:
                    639:                /* Set 16550 compatibility mode */
                    640:                bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD1,
                    641:                                  HAYESP_SETMODE);
                    642:                bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD2,
                    643:                                  HAYESP_MODE_FIFO|HAYESP_MODE_RTS|
                    644:                                  HAYESP_MODE_SCALE);
                    645:
                    646:                /* Set RTS/CTS flow control */
                    647:                bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD1,
                    648:                                  HAYESP_SETFLOWTYPE);
                    649:                bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD2,
                    650:                                  HAYESP_FLOW_RTS);
                    651:                bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD2,
                    652:                                  HAYESP_FLOW_CTS);
                    653:
                    654:                /* Set flow control levels */
                    655:                bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD1,
                    656:                                  HAYESP_SETRXFLOW);
                    657:                bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD2,
                    658:                                  HAYESP_HIBYTE(HAYESP_RXHIWMARK));
                    659:                bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD2,
                    660:                                  HAYESP_LOBYTE(HAYESP_RXHIWMARK));
                    661:                bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD2,
                    662:                                  HAYESP_HIBYTE(HAYESP_RXLOWMARK));
                    663:                bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD2,
                    664:                                  HAYESP_LOBYTE(HAYESP_RXLOWMARK));
                    665:        }
                    666: #endif
                    667:
1.186     uwe       668:        if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE|COM_HW_KGDB))
1.131     marc      669:                com_enable_debugport(sc);
1.1       cgd       670: }
                    671:
1.149     thorpej   672: int
1.197     simonb    673: com_detach(struct device *self, int flags)
1.149     thorpej   674: {
                    675:        struct com_softc *sc = (struct com_softc *)self;
                    676:        int maj, mn;
                    677:
                    678:        /* locate the major number */
1.199     gehenna   679:        maj = cdevsw_lookup_major(&com_cdevsw);
1.149     thorpej   680:
                    681:        /* Nuke the vnodes for any open instances. */
                    682:        mn = self->dv_unit;
                    683:        vdevgone(maj, mn, mn, VCHR);
                    684:
                    685:        mn |= COMDIALOUT_MASK;
                    686:        vdevgone(maj, mn, mn, VCHR);
                    687:
1.196     christos  688:        if (sc->sc_rbuf == NULL) {
                    689:                /*
                    690:                 * Ring buffer allocation failed in the com_attach_subr,
                    691:                 * only the tty is allocated, and nothing else.
                    692:                 */
                    693:                ttyfree(sc->sc_tty);
                    694:                return 0;
                    695:        }
                    696:
1.149     thorpej   697:        /* Free the receive buffer. */
                    698:        free(sc->sc_rbuf, M_DEVBUF);
                    699:
                    700:        /* Detach and free the tty. */
                    701:        tty_detach(sc->sc_tty);
                    702:        ttyfree(sc->sc_tty);
                    703:
1.183     thorpej   704: #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
1.149     thorpej   705:        /* Unhook the soft interrupt handler. */
                    706:        softintr_disestablish(sc->sc_si);
                    707: #endif
                    708:
                    709: #if NRND > 0 && defined(RND_COM)
                    710:        /* Unhook the entropy source. */
                    711:        rnd_detach_source(&sc->rnd_source);
                    712: #endif
                    713:
                    714:        return (0);
                    715: }
                    716:
                    717: int
1.197     simonb    718: com_activate(struct device *self, enum devact act)
1.149     thorpej   719: {
                    720:        struct com_softc *sc = (struct com_softc *)self;
                    721:        int s, rv = 0;
                    722:
                    723:        s = splserial();
1.179     sommerfe  724:        COM_LOCK(sc);
1.149     thorpej   725:        switch (act) {
                    726:        case DVACT_ACTIVATE:
                    727:                rv = EOPNOTSUPP;
                    728:                break;
                    729:
                    730:        case DVACT_DEACTIVATE:
                    731:                if (sc->sc_hwflags & (COM_HW_CONSOLE|COM_HW_KGDB)) {
                    732:                        rv = EBUSY;
                    733:                        break;
                    734:                }
                    735:
                    736:                if (sc->disable != NULL && sc->enabled != 0) {
                    737:                        (*sc->disable)(sc);
                    738:                        sc->enabled = 0;
                    739:                }
                    740:                break;
                    741:        }
1.179     sommerfe  742:
                    743:        COM_UNLOCK(sc);
1.149     thorpej   744:        splx(s);
                    745:        return (rv);
                    746: }
                    747:
1.141     mycroft   748: void
1.197     simonb    749: com_shutdown(struct com_softc *sc)
1.141     mycroft   750: {
                    751:        struct tty *tp = sc->sc_tty;
                    752:        int s;
                    753:
                    754:        s = splserial();
1.179     sommerfe  755:        COM_LOCK(sc);
1.141     mycroft   756:
                    757:        /* If we were asserting flow control, then deassert it. */
                    758:        SET(sc->sc_rx_flags, RX_IBUF_BLOCKED);
                    759:        com_hwiflow(sc);
                    760:
                    761:        /* Clear any break condition set with TIOCSBRK. */
                    762:        com_break(sc, 0);
                    763:
1.144     jonathan  764:        /* Turn off PPS capture on last close. */
1.151     mycroft   765:        sc->sc_ppsmask = 0;
1.144     jonathan  766:        sc->ppsparam.mode = 0;
                    767:
1.141     mycroft   768:        /*
                    769:         * Hang up if necessary.  Wait a bit, so the other side has time to
                    770:         * notice even if we immediately open the port again.
1.175     sommerfe  771:         * Avoid tsleeping above splhigh().
1.141     mycroft   772:         */
                    773:        if (ISSET(tp->t_cflag, HUPCL)) {
                    774:                com_modem(sc, 0);
1.179     sommerfe  775:                COM_UNLOCK(sc);
1.175     sommerfe  776:                splx(s);
                    777:                /* XXX tsleep will only timeout */
1.141     mycroft   778:                (void) tsleep(sc, TTIPRI, ttclos, hz);
1.175     sommerfe  779:                s = splserial();
1.179     sommerfe  780:                COM_LOCK(sc);
1.141     mycroft   781:        }
                    782:
                    783:        /* Turn off interrupts. */
1.208     scw       784:        if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
1.141     mycroft   785:                sc->sc_ier = IER_ERXRDY; /* interrupt on break */
1.208     scw       786: #ifdef COM_PXA2X0
1.209     thorpej   787:                if (sc->sc_type == COM_TYPE_PXA2x0)
1.208     scw       788:                        sc->sc_ier |= IER_ERXTOUT;
                    789: #endif
                    790:        } else
1.141     mycroft   791:                sc->sc_ier = 0;
1.208     scw       792:
                    793: #ifdef COM_PXA2X0
1.209     thorpej   794:        if (sc->sc_type == COM_TYPE_PXA2x0)
1.208     scw       795:                sc->sc_ier |= IER_EUART;
                    796: #endif
                    797:
1.141     mycroft   798:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_ier, sc->sc_ier);
                    799:
                    800:        if (sc->disable) {
                    801: #ifdef DIAGNOSTIC
                    802:                if (!sc->enabled)
                    803:                        panic("com_shutdown: not enabled?");
                    804: #endif
                    805:                (*sc->disable)(sc);
                    806:                sc->enabled = 0;
                    807:        }
1.179     sommerfe  808:        COM_UNLOCK(sc);
1.141     mycroft   809:        splx(s);
                    810: }
                    811:
1.21      mycroft   812: int
1.216.2.1  darrenr   813: comopen(dev_t dev, int flag, int mode, struct lwp *l)
1.1       cgd       814: {
1.21      mycroft   815:        struct com_softc *sc;
                    816:        struct tty *tp;
1.99      mycroft   817:        int s, s2;
1.142     mycroft   818:        int error;
1.173     thorpej   819:
                    820:        sc = device_lookup(&com_cd, COMUNIT(dev));
                    821:        if (sc == NULL || !ISSET(sc->sc_hwflags, COM_HW_DEV_OK) ||
1.177     eeh       822:                sc->sc_rbuf == NULL)
1.99      mycroft   823:                return (ENXIO);
1.21      mycroft   824:
1.149     thorpej   825:        if (ISSET(sc->sc_dev.dv_flags, DVF_ACTIVE) == 0)
                    826:                return (ENXIO);
                    827:
1.102     thorpej   828: #ifdef KGDB
                    829:        /*
                    830:         * If this is the kgdb port, no other use is permitted.
                    831:         */
                    832:        if (ISSET(sc->sc_hwflags, COM_HW_KGDB))
                    833:                return (EBUSY);
                    834: #endif
                    835:
1.120     mycroft   836:        tp = sc->sc_tty;
1.21      mycroft   837:
1.99      mycroft   838:        if (ISSET(tp->t_state, TS_ISOPEN) &&
                    839:            ISSET(tp->t_state, TS_XCLUDE) &&
1.216.2.1  darrenr   840:                l->l_proc->p_ucred->cr_uid != 0)
1.99      mycroft   841:                return (EBUSY);
                    842:
                    843:        s = spltty();
                    844:
                    845:        /*
                    846:         * Do the following iff this is a first open.
                    847:         */
1.141     mycroft   848:        if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
1.99      mycroft   849:                struct termios t;
                    850:
1.127     mycroft   851:                tp->t_dev = dev;
                    852:
1.120     mycroft   853:                s2 = splserial();
1.179     sommerfe  854:                COM_LOCK(sc);
1.120     mycroft   855:
1.131     marc      856:                if (sc->enable) {
                    857:                        if ((*sc->enable)(sc)) {
1.179     sommerfe  858:                                COM_UNLOCK(sc);
1.141     mycroft   859:                                splx(s2);
1.134     enami     860:                                splx(s);
1.131     marc      861:                                printf("%s: device enable failed\n",
                    862:                                       sc->sc_dev.dv_xname);
                    863:                                return (EIO);
                    864:                        }
                    865:                        sc->enabled = 1;
                    866:                        com_config(sc);
                    867:                }
                    868:
1.99      mycroft   869:                /* Turn on interrupts. */
                    870:                sc->sc_ier = IER_ERXRDY | IER_ERLS | IER_EMSC;
1.208     scw       871: #ifdef COM_PXA2X0
1.209     thorpej   872:                if (sc->sc_type == COM_TYPE_PXA2x0)
1.208     scw       873:                        sc->sc_ier |= IER_EUART | IER_ERXTOUT;
                    874: #endif
1.99      mycroft   875:                bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_ier, sc->sc_ier);
                    876:
                    877:                /* Fetch the current modem control status, needed later. */
                    878:                sc->sc_msr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, com_msr);
                    879:
1.144     jonathan  880:                /* Clear PPS capture state on first open. */
1.151     mycroft   881:                sc->sc_ppsmask = 0;
1.152     mycroft   882:                sc->ppsparam.mode = 0;
1.144     jonathan  883:
1.179     sommerfe  884:                COM_UNLOCK(sc);
1.120     mycroft   885:                splx(s2);
1.99      mycroft   886:
                    887:                /*
                    888:                 * Initialize the termios status to the defaults.  Add in the
                    889:                 * sticky bits from TIOCSFLAGS.
                    890:                 */
                    891:                t.c_ispeed = 0;
1.98      mycroft   892:                if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
1.99      mycroft   893:                        t.c_ospeed = comconsrate;
                    894:                        t.c_cflag = comconscflag;
1.98      mycroft   895:                } else {
1.99      mycroft   896:                        t.c_ospeed = TTYDEF_SPEED;
                    897:                        t.c_cflag = TTYDEF_CFLAG;
1.98      mycroft   898:                }
1.99      mycroft   899:                if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL))
                    900:                        SET(t.c_cflag, CLOCAL);
                    901:                if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS))
                    902:                        SET(t.c_cflag, CRTSCTS);
                    903:                if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF))
                    904:                        SET(t.c_cflag, MDMBUF);
1.129     mycroft   905:                /* Make sure comparam() will do something. */
                    906:                tp->t_ospeed = 0;
1.120     mycroft   907:                (void) comparam(tp, &t);
1.99      mycroft   908:                tp->t_iflag = TTYDEF_IFLAG;
                    909:                tp->t_oflag = TTYDEF_OFLAG;
1.16      ws        910:                tp->t_lflag = TTYDEF_LFLAG;
1.99      mycroft   911:                ttychars(tp);
1.1       cgd       912:                ttsetwater(tp);
1.21      mycroft   913:
1.136     mycroft   914:                s2 = splserial();
1.179     sommerfe  915:                COM_LOCK(sc);
1.136     mycroft   916:
1.99      mycroft   917:                /*
                    918:                 * Turn on DTR.  We must always do this, even if carrier is not
                    919:                 * present, because otherwise we'd have to use TIOCSDTR
1.121     mycroft   920:                 * immediately after setting CLOCAL, which applications do not
                    921:                 * expect.  We always assert DTR while the device is open
                    922:                 * unless explicitly requested to deassert it.
1.99      mycroft   923:                 */
                    924:                com_modem(sc, 1);
1.65      christos  925:
1.99      mycroft   926:                /* Clear the input ring, and unblock. */
1.127     mycroft   927:                sc->sc_rbput = sc->sc_rbget = sc->sc_rbuf;
                    928:                sc->sc_rbavail = com_rbuf_size;
1.99      mycroft   929:                com_iflush(sc);
1.101     mycroft   930:                CLR(sc->sc_rx_flags, RX_ANY_BLOCK);
                    931:                com_hwiflow(sc);
1.65      christos  932:
1.99      mycroft   933: #ifdef COM_DEBUG
1.101     mycroft   934:                if (com_debug)
                    935:                        comstatus(sc, "comopen  ");
1.65      christos  936: #endif
1.21      mycroft   937:
1.179     sommerfe  938:                COM_UNLOCK(sc);
1.99      mycroft   939:                splx(s2);
                    940:        }
1.143     mycroft   941:
                    942:        splx(s);
1.21      mycroft   943:
1.143     mycroft   944:        error = ttyopen(tp, COMDIALOUT(dev), ISSET(flag, O_NONBLOCK));
                    945:        if (error)
                    946:                goto bad;
1.141     mycroft   947:
1.181     eeh       948:        error = (*tp->t_linesw->l_open)(dev, tp);
1.139     enami     949:        if (error)
1.141     mycroft   950:                goto bad;
1.139     enami     951:
1.141     mycroft   952:        return (0);
1.139     enami     953:
1.141     mycroft   954: bad:
                    955:        if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
                    956:                /*
                    957:                 * We failed to open the device, and nobody else had it opened.
                    958:                 * Clean up the state as appropriate.
                    959:                 */
                    960:                com_shutdown(sc);
                    961:        }
1.139     enami     962:
1.99      mycroft   963:        return (error);
1.1       cgd       964: }
                    965:
1.21      mycroft   966: int
1.216.2.1  darrenr   967: comclose(dev_t dev, int flag, int mode, struct lwp *l)
1.1       cgd       968: {
1.173     thorpej   969:        struct com_softc *sc = device_lookup(&com_cd, COMUNIT(dev));
1.50      mycroft   970:        struct tty *tp = sc->sc_tty;
1.57      mycroft   971:
                    972:        /* XXX This is for cons.c. */
1.62      mycroft   973:        if (!ISSET(tp->t_state, TS_ISOPEN))
1.99      mycroft   974:                return (0);
1.21      mycroft   975:
1.181     eeh       976:        (*tp->t_linesw->l_close)(tp, flag);
1.1       cgd       977:        ttyclose(tp);
1.99      mycroft   978:
1.149     thorpej   979:        if (COM_ISALIVE(sc) == 0)
                    980:                return (0);
                    981:
1.143     mycroft   982:        if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
                    983:                /*
                    984:                 * Although we got a last close, the device may still be in
                    985:                 * use; e.g. if this was the dialout node, and there are still
                    986:                 * processes waiting for carrier on the non-dialout node.
                    987:                 */
                    988:                com_shutdown(sc);
                    989:        }
1.120     mycroft   990:
1.99      mycroft   991:        return (0);
1.1       cgd       992: }
                    993:
1.21      mycroft   994: int
1.197     simonb    995: comread(dev_t dev, struct uio *uio, int flag)
1.1       cgd       996: {
1.173     thorpej   997:        struct com_softc *sc = device_lookup(&com_cd, COMUNIT(dev));
1.52      mycroft   998:        struct tty *tp = sc->sc_tty;
1.149     thorpej   999:
                   1000:        if (COM_ISALIVE(sc) == 0)
                   1001:                return (EIO);
1.1       cgd      1002:
1.181     eeh      1003:        return ((*tp->t_linesw->l_read)(tp, uio, flag));
1.1       cgd      1004: }
                   1005:
1.21      mycroft  1006: int
1.197     simonb   1007: comwrite(dev_t dev, struct uio *uio, int flag)
1.1       cgd      1008: {
1.173     thorpej  1009:        struct com_softc *sc = device_lookup(&com_cd, COMUNIT(dev));
1.52      mycroft  1010:        struct tty *tp = sc->sc_tty;
1.149     thorpej  1011:
                   1012:        if (COM_ISALIVE(sc) == 0)
                   1013:                return (EIO);
1.1       cgd      1014:
1.181     eeh      1015:        return ((*tp->t_linesw->l_write)(tp, uio, flag));
1.184     scw      1016: }
                   1017:
                   1018: int
1.216.2.1  darrenr  1019: compoll(dev_t dev, int events, struct lwp *l)
1.184     scw      1020: {
                   1021:        struct com_softc *sc = device_lookup(&com_cd, COMUNIT(dev));
                   1022:        struct tty *tp = sc->sc_tty;
                   1023:
                   1024:        if (COM_ISALIVE(sc) == 0)
                   1025:                return (EIO);
                   1026:
1.216.2.1  darrenr  1027:        return (*tp->t_linesw->l_poll)(tp, events, l);
1.1       cgd      1028: }
1.50      mycroft  1029:
                   1030: struct tty *
1.197     simonb   1031: comtty(dev_t dev)
1.50      mycroft  1032: {
1.173     thorpej  1033:        struct com_softc *sc = device_lookup(&com_cd, COMUNIT(dev));
1.52      mycroft  1034:        struct tty *tp = sc->sc_tty;
1.50      mycroft  1035:
1.52      mycroft  1036:        return (tp);
1.50      mycroft  1037: }
1.111     christos 1038:
1.21      mycroft  1039: int
1.216.2.1  darrenr  1040: comioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct lwp *l)
1.1       cgd      1041: {
1.173     thorpej  1042:        struct com_softc *sc = device_lookup(&com_cd, COMUNIT(dev));
1.50      mycroft  1043:        struct tty *tp = sc->sc_tty;
1.216.2.1  darrenr  1044:        struct proc *p = l->l_proc;
1.21      mycroft  1045:        int error;
1.136     mycroft  1046:        int s;
1.21      mycroft  1047:
1.149     thorpej  1048:        if (COM_ISALIVE(sc) == 0)
                   1049:                return (EIO);
                   1050:
1.216.2.1  darrenr  1051:        error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l);
1.194     atatat   1052:        if (error != EPASSTHROUGH)
1.99      mycroft  1053:                return (error);
                   1054:
1.216.2.1  darrenr  1055:        error = ttioctl(tp, cmd, data, flag, l);
1.194     atatat   1056:        if (error != EPASSTHROUGH)
1.99      mycroft  1057:                return (error);
1.138     mycroft  1058:
                   1059:        error = 0;
1.1       cgd      1060:
1.136     mycroft  1061:        s = splserial();
1.179     sommerfe 1062:        COM_LOCK(sc);
1.136     mycroft  1063:
1.1       cgd      1064:        switch (cmd) {
                   1065:        case TIOCSBRK:
1.99      mycroft  1066:                com_break(sc, 1);
1.1       cgd      1067:                break;
1.99      mycroft  1068:
1.1       cgd      1069:        case TIOCCBRK:
1.99      mycroft  1070:                com_break(sc, 0);
1.1       cgd      1071:                break;
1.99      mycroft  1072:
1.1       cgd      1073:        case TIOCSDTR:
1.99      mycroft  1074:                com_modem(sc, 1);
1.1       cgd      1075:                break;
1.99      mycroft  1076:
1.1       cgd      1077:        case TIOCCDTR:
1.99      mycroft  1078:                com_modem(sc, 0);
1.1       cgd      1079:                break;
1.99      mycroft  1080:
                   1081:        case TIOCGFLAGS:
                   1082:                *(int *)data = sc->sc_swflags;
                   1083:                break;
                   1084:
                   1085:        case TIOCSFLAGS:
                   1086:                error = suser(p->p_ucred, &p->p_acflag);
                   1087:                if (error)
1.136     mycroft  1088:                        break;
1.99      mycroft  1089:                sc->sc_swflags = *(int *)data;
                   1090:                break;
                   1091:
1.1       cgd      1092:        case TIOCMSET:
                   1093:        case TIOCMBIS:
                   1094:        case TIOCMBIC:
1.153     mycroft  1095:                tiocm_to_com(sc, cmd, *(int *)data);
1.111     christos 1096:                break;
                   1097:
1.153     mycroft  1098:        case TIOCMGET:
                   1099:                *(int *)data = com_to_tiocm(sc);
1.111     christos 1100:                break;
1.144     jonathan 1101:
1.163     jonathan 1102:        case PPS_IOC_CREATE:
1.144     jonathan 1103:                break;
                   1104:
1.163     jonathan 1105:        case PPS_IOC_DESTROY:
1.144     jonathan 1106:                break;
                   1107:
1.163     jonathan 1108:        case PPS_IOC_GETPARAMS: {
1.144     jonathan 1109:                pps_params_t *pp;
                   1110:                pp = (pps_params_t *)data;
                   1111:                *pp = sc->ppsparam;
                   1112:                break;
                   1113:        }
                   1114:
1.163     jonathan 1115:        case PPS_IOC_SETPARAMS: {
1.144     jonathan 1116:                pps_params_t *pp;
                   1117:                int mode;
                   1118:                pp = (pps_params_t *)data;
                   1119:                if (pp->mode & ~ppscap) {
                   1120:                        error = EINVAL;
                   1121:                        break;
                   1122:                }
                   1123:                sc->ppsparam = *pp;
                   1124:                /*
                   1125:                 * Compute msr masks from user-specified timestamp state.
                   1126:                 */
                   1127:                mode = sc->ppsparam.mode;
                   1128:                switch (mode & PPS_CAPTUREBOTH) {
                   1129:                case 0:
1.151     mycroft  1130:                        sc->sc_ppsmask = 0;
1.144     jonathan 1131:                        break;
                   1132:
                   1133:                case PPS_CAPTUREASSERT:
1.151     mycroft  1134:                        sc->sc_ppsmask = MSR_DCD;
1.144     jonathan 1135:                        sc->sc_ppsassert = MSR_DCD;
1.151     mycroft  1136:                        sc->sc_ppsclear = -1;
1.144     jonathan 1137:                        break;
                   1138:
                   1139:                case PPS_CAPTURECLEAR:
1.151     mycroft  1140:                        sc->sc_ppsmask = MSR_DCD;
                   1141:                        sc->sc_ppsassert = -1;
1.144     jonathan 1142:                        sc->sc_ppsclear = 0;
                   1143:                        break;
                   1144:
                   1145:                case PPS_CAPTUREBOTH:
1.151     mycroft  1146:                        sc->sc_ppsmask = MSR_DCD;
1.144     jonathan 1147:                        sc->sc_ppsassert = MSR_DCD;
                   1148:                        sc->sc_ppsclear = 0;
                   1149:                        break;
                   1150:
                   1151:                default:
                   1152:                        error = EINVAL;
                   1153:                        break;
                   1154:                }
                   1155:                break;
                   1156:        }
                   1157:
1.163     jonathan 1158:        case PPS_IOC_GETCAP:
1.144     jonathan 1159:                *(int*)data = ppscap;
                   1160:                break;
                   1161:
1.163     jonathan 1162:        case PPS_IOC_FETCH: {
1.144     jonathan 1163:                pps_info_t *pi;
                   1164:                pi = (pps_info_t *)data;
                   1165:                *pi = sc->ppsinfo;
                   1166:                break;
                   1167:        }
                   1168:
1.216.2.2  skrll    1169: #ifdef PPS_SYNC
                   1170:        case PPS_IOC_KCBIND: {
                   1171:                int edge = (*(int *)data) & PPS_CAPTUREBOTH;
                   1172:
                   1173:                if (edge == 0) {
                   1174:                        /*
                   1175:                         * remove binding for this source; ignore
                   1176:                         * the request if this is not the current
                   1177:                         * hardpps source
                   1178:                         */
                   1179:                        if (pps_kc_hardpps_source == sc) {
                   1180:                                pps_kc_hardpps_source = NULL;
                   1181:                                pps_kc_hardpps_mode = 0;
                   1182:                        }
                   1183:                } else {
                   1184:                        /*
                   1185:                         * bind hardpps to this source, replacing any
                   1186:                         * previously specified source or edges
                   1187:                         */
                   1188:                        pps_kc_hardpps_source = sc;
                   1189:                        pps_kc_hardpps_mode = edge;
                   1190:                }
                   1191:                break;
                   1192:        }
                   1193: #endif /* PPS_SYNC */
                   1194:
1.144     jonathan 1195:        case TIOCDCDTIMESTAMP:  /* XXX old, overloaded  API used by xntpd v3 */
                   1196:                /*
                   1197:                 * Some GPS clocks models use the falling rather than
                   1198:                 * rising edge as the on-the-second signal.
                   1199:                 * The old API has no way to specify PPS polarity.
                   1200:                 */
1.151     mycroft  1201:                sc->sc_ppsmask = MSR_DCD;
1.144     jonathan 1202: #ifndef PPS_TRAILING_EDGE
                   1203:                sc->sc_ppsassert = MSR_DCD;
1.151     mycroft  1204:                sc->sc_ppsclear = -1;
                   1205:                TIMESPEC_TO_TIMEVAL((struct timeval *)data,
1.144     jonathan 1206:                    &sc->ppsinfo.assert_timestamp);
                   1207: #else
1.216.2.2  skrll    1208:                sc->sc_ppsassert = -1;
1.144     jonathan 1209:                sc->sc_ppsclear = 0;
1.151     mycroft  1210:                TIMESPEC_TO_TIMEVAL((struct timeval *)data,
1.144     jonathan 1211:                    &sc->ppsinfo.clear_timestamp);
                   1212: #endif
                   1213:                break;
                   1214:
1.99      mycroft  1215:        default:
1.194     atatat   1216:                error = EPASSTHROUGH;
1.136     mycroft  1217:                break;
1.21      mycroft  1218:        }
1.22      cgd      1219:
1.179     sommerfe 1220:        COM_UNLOCK(sc);
1.136     mycroft  1221:        splx(s);
                   1222:
1.99      mycroft  1223: #ifdef COM_DEBUG
1.101     mycroft  1224:        if (com_debug)
1.99      mycroft  1225:                comstatus(sc, "comioctl ");
                   1226: #endif
                   1227:
1.136     mycroft  1228:        return (error);
1.99      mycroft  1229: }
                   1230:
1.101     mycroft  1231: integrate void
1.197     simonb   1232: com_schedrx(struct com_softc *sc)
1.101     mycroft  1233: {
                   1234:
                   1235:        sc->sc_rx_ready = 1;
                   1236:
                   1237:        /* Wake up the poller. */
1.183     thorpej  1238: #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
1.101     mycroft  1239:        softintr_schedule(sc->sc_si);
                   1240: #else
1.133     cgd      1241: #ifndef __NO_SOFT_SERIAL_INTERRUPT
1.101     mycroft  1242:        setsoftserial();
                   1243: #else
                   1244:        if (!com_softintr_scheduled) {
                   1245:                com_softintr_scheduled = 1;
1.170     thorpej  1246:                callout_reset(&comsoft_callout, 1, comsoft, NULL);
1.101     mycroft  1247:        }
                   1248: #endif
                   1249: #endif
                   1250: }
                   1251:
1.99      mycroft  1252: void
1.197     simonb   1253: com_break(struct com_softc *sc, int onoff)
1.99      mycroft  1254: {
                   1255:
                   1256:        if (onoff)
                   1257:                SET(sc->sc_lcr, LCR_SBREAK);
                   1258:        else
                   1259:                CLR(sc->sc_lcr, LCR_SBREAK);
1.22      cgd      1260:
1.99      mycroft  1261:        if (!sc->sc_heldchange) {
                   1262:                if (sc->sc_tx_busy) {
                   1263:                        sc->sc_heldtbc = sc->sc_tbc;
                   1264:                        sc->sc_tbc = 0;
                   1265:                        sc->sc_heldchange = 1;
                   1266:                } else
                   1267:                        com_loadchannelregs(sc);
1.22      cgd      1268:        }
1.99      mycroft  1269: }
1.22      cgd      1270:
1.99      mycroft  1271: void
1.197     simonb   1272: com_modem(struct com_softc *sc, int onoff)
1.99      mycroft  1273: {
1.22      cgd      1274:
1.153     mycroft  1275:        if (sc->sc_mcr_dtr == 0)
                   1276:                return;
                   1277:
1.99      mycroft  1278:        if (onoff)
                   1279:                SET(sc->sc_mcr, sc->sc_mcr_dtr);
                   1280:        else
                   1281:                CLR(sc->sc_mcr, sc->sc_mcr_dtr);
1.22      cgd      1282:
1.99      mycroft  1283:        if (!sc->sc_heldchange) {
                   1284:                if (sc->sc_tx_busy) {
                   1285:                        sc->sc_heldtbc = sc->sc_tbc;
                   1286:                        sc->sc_tbc = 0;
                   1287:                        sc->sc_heldchange = 1;
                   1288:                } else
                   1289:                        com_loadchannelregs(sc);
1.22      cgd      1290:        }
1.153     mycroft  1291: }
                   1292:
                   1293: void
1.197     simonb   1294: tiocm_to_com(struct com_softc *sc, u_long how, int ttybits)
1.153     mycroft  1295: {
                   1296:        u_char combits;
                   1297:
                   1298:        combits = 0;
                   1299:        if (ISSET(ttybits, TIOCM_DTR))
                   1300:                SET(combits, MCR_DTR);
                   1301:        if (ISSET(ttybits, TIOCM_RTS))
                   1302:                SET(combits, MCR_RTS);
                   1303:
                   1304:        switch (how) {
                   1305:        case TIOCMBIC:
                   1306:                CLR(sc->sc_mcr, combits);
                   1307:                break;
                   1308:
                   1309:        case TIOCMBIS:
                   1310:                SET(sc->sc_mcr, combits);
                   1311:                break;
                   1312:
                   1313:        case TIOCMSET:
                   1314:                CLR(sc->sc_mcr, MCR_DTR | MCR_RTS);
                   1315:                SET(sc->sc_mcr, combits);
                   1316:                break;
                   1317:        }
                   1318:
                   1319:        if (!sc->sc_heldchange) {
                   1320:                if (sc->sc_tx_busy) {
                   1321:                        sc->sc_heldtbc = sc->sc_tbc;
                   1322:                        sc->sc_tbc = 0;
                   1323:                        sc->sc_heldchange = 1;
                   1324:                } else
                   1325:                        com_loadchannelregs(sc);
                   1326:        }
                   1327: }
                   1328:
                   1329: int
1.197     simonb   1330: com_to_tiocm(struct com_softc *sc)
1.153     mycroft  1331: {
                   1332:        u_char combits;
                   1333:        int ttybits = 0;
                   1334:
                   1335:        combits = sc->sc_mcr;
                   1336:        if (ISSET(combits, MCR_DTR))
                   1337:                SET(ttybits, TIOCM_DTR);
                   1338:        if (ISSET(combits, MCR_RTS))
                   1339:                SET(ttybits, TIOCM_RTS);
                   1340:
                   1341:        combits = sc->sc_msr;
                   1342:        if (ISSET(combits, MSR_DCD))
                   1343:                SET(ttybits, TIOCM_CD);
                   1344:        if (ISSET(combits, MSR_CTS))
                   1345:                SET(ttybits, TIOCM_CTS);
                   1346:        if (ISSET(combits, MSR_DSR))
                   1347:                SET(ttybits, TIOCM_DSR);
                   1348:        if (ISSET(combits, MSR_RI | MSR_TERI))
                   1349:                SET(ttybits, TIOCM_RI);
                   1350:
1.216.2.2  skrll    1351:        if (ISSET(sc->sc_ier, IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC))
1.153     mycroft  1352:                SET(ttybits, TIOCM_LE);
                   1353:
                   1354:        return (ttybits);
1.1       cgd      1355: }
                   1356:
1.106     drochner 1357: static u_char
1.197     simonb   1358: cflag2lcr(tcflag_t cflag)
1.106     drochner 1359: {
                   1360:        u_char lcr = 0;
                   1361:
                   1362:        switch (ISSET(cflag, CSIZE)) {
1.127     mycroft  1363:        case CS5:
1.106     drochner 1364:                SET(lcr, LCR_5BITS);
                   1365:                break;
1.127     mycroft  1366:        case CS6:
1.106     drochner 1367:                SET(lcr, LCR_6BITS);
                   1368:                break;
1.127     mycroft  1369:        case CS7:
1.106     drochner 1370:                SET(lcr, LCR_7BITS);
                   1371:                break;
1.127     mycroft  1372:        case CS8:
1.106     drochner 1373:                SET(lcr, LCR_8BITS);
                   1374:                break;
                   1375:        }
                   1376:        if (ISSET(cflag, PARENB)) {
                   1377:                SET(lcr, LCR_PENAB);
                   1378:                if (!ISSET(cflag, PARODD))
                   1379:                        SET(lcr, LCR_PEVEN);
                   1380:        }
                   1381:        if (ISSET(cflag, CSTOPB))
                   1382:                SET(lcr, LCR_STOPB);
                   1383:
1.110     enami    1384:        return (lcr);
1.106     drochner 1385: }
                   1386:
1.21      mycroft  1387: int
1.197     simonb   1388: comparam(struct tty *tp, struct termios *t)
1.1       cgd      1389: {
1.173     thorpej  1390:        struct com_softc *sc = device_lookup(&com_cd, COMUNIT(tp->t_dev));
1.188     enami    1391:        int ospeed;
1.62      mycroft  1392:        u_char lcr;
1.21      mycroft  1393:        int s;
                   1394:
1.149     thorpej  1395:        if (COM_ISALIVE(sc) == 0)
                   1396:                return (EIO);
                   1397:
1.188     enami    1398: #ifdef COM_HAYESP
1.209     thorpej  1399:        if (sc->sc_type == COM_TYPE_HAYESP) {
1.188     enami    1400:                int prescaler, speed;
                   1401:
                   1402:                /*
                   1403:                 * Calculate UART clock prescaler.  It should be in
                   1404:                 * range of 0 .. 3.
                   1405:                 */
                   1406:                for (prescaler = 0, speed = t->c_ospeed; prescaler < 4;
                   1407:                    prescaler++, speed /= 2)
1.210     thorpej  1408:                        if ((ospeed = comspeed(speed, sc->sc_frequency,
                   1409:                                               sc->sc_type)) > 0)
1.188     enami    1410:                                break;
                   1411:
                   1412:                if (prescaler == 4)
                   1413:                        return (EINVAL);
                   1414:                sc->sc_prescaler = prescaler;
                   1415:        } else
                   1416: #endif
1.210     thorpej  1417:        ospeed = comspeed(t->c_ospeed, sc->sc_frequency, sc->sc_type);
1.188     enami    1418:
1.127     mycroft  1419:        /* Check requested parameters. */
1.99      mycroft  1420:        if (ospeed < 0)
                   1421:                return (EINVAL);
                   1422:        if (t->c_ispeed && t->c_ispeed != t->c_ospeed)
                   1423:                return (EINVAL);
1.21      mycroft  1424:
1.99      mycroft  1425:        /*
                   1426:         * For the console, always force CLOCAL and !HUPCL, so that the port
                   1427:         * is always active.
                   1428:         */
                   1429:        if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) ||
                   1430:            ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
                   1431:                SET(t->c_cflag, CLOCAL);
                   1432:                CLR(t->c_cflag, HUPCL);
1.62      mycroft  1433:        }
1.129     mycroft  1434:
                   1435:        /*
                   1436:         * If there were no changes, don't do anything.  This avoids dropping
                   1437:         * input and improves performance when all we did was frob things like
                   1438:         * VMIN and VTIME.
                   1439:         */
                   1440:        if (tp->t_ospeed == t->c_ospeed &&
                   1441:            tp->t_cflag == t->c_cflag)
                   1442:                return (0);
1.126     mycroft  1443:
                   1444:        lcr = ISSET(sc->sc_lcr, LCR_SBREAK) | cflag2lcr(t->c_cflag);
                   1445:
                   1446:        s = splserial();
1.179     sommerfe 1447:        COM_LOCK(sc);
1.126     mycroft  1448:
                   1449:        sc->sc_lcr = lcr;
1.36      mycroft  1450:
                   1451:        /*
1.99      mycroft  1452:         * If we're not in a mode that assumes a connection is present, then
                   1453:         * ignore carrier changes.
1.36      mycroft  1454:         */
1.99      mycroft  1455:        if (ISSET(t->c_cflag, CLOCAL | MDMBUF))
                   1456:                sc->sc_msr_dcd = 0;
                   1457:        else
                   1458:                sc->sc_msr_dcd = MSR_DCD;
                   1459:        /*
                   1460:         * Set the flow control pins depending on the current flow control
                   1461:         * mode.
                   1462:         */
                   1463:        if (ISSET(t->c_cflag, CRTSCTS)) {
                   1464:                sc->sc_mcr_dtr = MCR_DTR;
                   1465:                sc->sc_mcr_rts = MCR_RTS;
                   1466:                sc->sc_msr_cts = MSR_CTS;
1.116     fvdl     1467:                sc->sc_efr = EFR_AUTORTS | EFR_AUTOCTS;
1.99      mycroft  1468:        } else if (ISSET(t->c_cflag, MDMBUF)) {
                   1469:                /*
                   1470:                 * For DTR/DCD flow control, make sure we don't toggle DTR for
                   1471:                 * carrier detection.
                   1472:                 */
                   1473:                sc->sc_mcr_dtr = 0;
                   1474:                sc->sc_mcr_rts = MCR_DTR;
                   1475:                sc->sc_msr_cts = MSR_DCD;
1.116     fvdl     1476:                sc->sc_efr = 0;
1.99      mycroft  1477:        } else {
                   1478:                /*
                   1479:                 * If no flow control, then always set RTS.  This will make
                   1480:                 * the other side happy if it mistakenly thinks we're doing
                   1481:                 * RTS/CTS flow control.
                   1482:                 */
                   1483:                sc->sc_mcr_dtr = MCR_DTR | MCR_RTS;
                   1484:                sc->sc_mcr_rts = 0;
                   1485:                sc->sc_msr_cts = 0;
1.116     fvdl     1486:                sc->sc_efr = 0;
1.99      mycroft  1487:                if (ISSET(sc->sc_mcr, MCR_DTR))
                   1488:                        SET(sc->sc_mcr, MCR_RTS);
                   1489:                else
                   1490:                        CLR(sc->sc_mcr, MCR_RTS);
                   1491:        }
                   1492:        sc->sc_msr_mask = sc->sc_msr_cts | sc->sc_msr_dcd;
                   1493:
1.95      mycroft  1494: #if 0
1.99      mycroft  1495:        if (ospeed == 0)
                   1496:                CLR(sc->sc_mcr, sc->sc_mcr_dtr);
                   1497:        else
                   1498:                SET(sc->sc_mcr, sc->sc_mcr_dtr);
1.66      mycroft  1499: #endif
                   1500:
1.99      mycroft  1501:        sc->sc_dlbl = ospeed;
                   1502:        sc->sc_dlbh = ospeed >> 8;
1.66      mycroft  1503:
1.99      mycroft  1504:        /*
                   1505:         * Set the FIFO threshold based on the receive speed.
                   1506:         *
                   1507:         *  * If it's a low speed, it's probably a mouse or some other
                   1508:         *    interactive device, so set the threshold low.
                   1509:         *  * If it's a high speed, trim the trigger level down to prevent
                   1510:         *    overflows.
                   1511:         *  * Otherwise set it a bit higher.
                   1512:         */
1.209     thorpej  1513:        if (sc->sc_type == COM_TYPE_HAYESP)
1.99      mycroft  1514:                sc->sc_fifo = FIFO_DMA_MODE | FIFO_ENABLE | FIFO_TRIGGER_8;
                   1515:        else if (ISSET(sc->sc_hwflags, COM_HW_FIFO))
                   1516:                sc->sc_fifo = FIFO_ENABLE |
1.216.2.2  skrll    1517:                    (t->c_ospeed <= 1200 ? FIFO_TRIGGER_1 : FIFO_TRIGGER_8);
1.99      mycroft  1518:        else
                   1519:                sc->sc_fifo = 0;
1.21      mycroft  1520:
1.127     mycroft  1521:        /* And copy to tty. */
1.99      mycroft  1522:        tp->t_ispeed = 0;
1.57      mycroft  1523:        tp->t_ospeed = t->c_ospeed;
                   1524:        tp->t_cflag = t->c_cflag;
1.25      cgd      1525:
1.99      mycroft  1526:        if (!sc->sc_heldchange) {
                   1527:                if (sc->sc_tx_busy) {
                   1528:                        sc->sc_heldtbc = sc->sc_tbc;
                   1529:                        sc->sc_tbc = 0;
                   1530:                        sc->sc_heldchange = 1;
                   1531:                } else
                   1532:                        com_loadchannelregs(sc);
                   1533:        }
                   1534:
1.124     mycroft  1535:        if (!ISSET(t->c_cflag, CHWFLOW)) {
1.125     mycroft  1536:                /* Disable the high water mark. */
                   1537:                sc->sc_r_hiwat = 0;
                   1538:                sc->sc_r_lowat = 0;
1.124     mycroft  1539:                if (ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) {
                   1540:                        CLR(sc->sc_rx_flags, RX_TTY_OVERFLOWED);
                   1541:                        com_schedrx(sc);
                   1542:                }
                   1543:                if (ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED)) {
                   1544:                        CLR(sc->sc_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED);
                   1545:                        com_hwiflow(sc);
                   1546:                }
1.125     mycroft  1547:        } else {
1.127     mycroft  1548:                sc->sc_r_hiwat = com_rbuf_hiwat;
                   1549:                sc->sc_r_lowat = com_rbuf_lowat;
1.124     mycroft  1550:        }
                   1551:
1.179     sommerfe 1552:        COM_UNLOCK(sc);
1.99      mycroft  1553:        splx(s);
                   1554:
1.25      cgd      1555:        /*
1.99      mycroft  1556:         * Update the tty layer's idea of the carrier bit, in case we changed
1.124     mycroft  1557:         * CLOCAL or MDMBUF.  We don't hang up here; we only do that by
                   1558:         * explicit request.
1.25      cgd      1559:         */
1.181     eeh      1560:        (void) (*tp->t_linesw->l_modem)(tp, ISSET(sc->sc_msr, MSR_DCD));
1.99      mycroft  1561:
                   1562: #ifdef COM_DEBUG
1.101     mycroft  1563:        if (com_debug)
                   1564:                comstatus(sc, "comparam ");
1.99      mycroft  1565: #endif
                   1566:
                   1567:        if (!ISSET(t->c_cflag, CHWFLOW)) {
                   1568:                if (sc->sc_tx_stopped) {
                   1569:                        sc->sc_tx_stopped = 0;
                   1570:                        comstart(tp);
                   1571:                }
1.21      mycroft  1572:        }
1.1       cgd      1573:
1.99      mycroft  1574:        return (0);
                   1575: }
                   1576:
                   1577: void
1.197     simonb   1578: com_iflush(struct com_softc *sc)
1.99      mycroft  1579: {
                   1580:        bus_space_tag_t iot = sc->sc_iot;
                   1581:        bus_space_handle_t ioh = sc->sc_ioh;
1.131     marc     1582: #ifdef DIAGNOSTIC
                   1583:        int reg;
                   1584: #endif
                   1585:        int timo;
1.99      mycroft  1586:
1.131     marc     1587: #ifdef DIAGNOSTIC
                   1588:        reg = 0xffff;
                   1589: #endif
                   1590:        timo = 50000;
1.99      mycroft  1591:        /* flush any pending I/O */
1.131     marc     1592:        while (ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY)
                   1593:            && --timo)
                   1594: #ifdef DIAGNOSTIC
                   1595:                reg =
                   1596: #else
                   1597:                    (void)
                   1598: #endif
                   1599:                    bus_space_read_1(iot, ioh, com_data);
                   1600: #ifdef DIAGNOSTIC
                   1601:        if (!timo)
                   1602:                printf("%s: com_iflush timeout %02x\n", sc->sc_dev.dv_xname,
                   1603:                       reg);
                   1604: #endif
1.99      mycroft  1605: }
                   1606:
                   1607: void
1.197     simonb   1608: com_loadchannelregs(struct com_softc *sc)
1.99      mycroft  1609: {
                   1610:        bus_space_tag_t iot = sc->sc_iot;
                   1611:        bus_space_handle_t ioh = sc->sc_ioh;
                   1612:
                   1613:        /* XXXXX necessary? */
                   1614:        com_iflush(sc);
                   1615:
1.208     scw      1616: #ifdef COM_PXA2X0
1.209     thorpej  1617:        if (sc->sc_type == COM_TYPE_PXA2x0)
1.208     scw      1618:                bus_space_write_1(iot, ioh, com_ier, IER_EUART);
                   1619:        else
                   1620: #endif
                   1621:                bus_space_write_1(iot, ioh, com_ier, 0);
1.99      mycroft  1622:
1.116     fvdl     1623:        if (ISSET(sc->sc_hwflags, COM_HW_FLOW)) {
                   1624:                bus_space_write_1(iot, ioh, com_lcr, LCR_EERS);
                   1625:                bus_space_write_1(iot, ioh, com_efr, sc->sc_efr);
                   1626:        }
1.99      mycroft  1627:        bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr | LCR_DLAB);
                   1628:        bus_space_write_1(iot, ioh, com_dlbl, sc->sc_dlbl);
                   1629:        bus_space_write_1(iot, ioh, com_dlbh, sc->sc_dlbh);
                   1630:        bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr);
                   1631:        bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr_active = sc->sc_mcr);
                   1632:        bus_space_write_1(iot, ioh, com_fifo, sc->sc_fifo);
1.188     enami    1633: #ifdef COM_HAYESP
1.209     thorpej  1634:        if (sc->sc_type == COM_TYPE_HAYESP) {
1.188     enami    1635:                bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD1,
                   1636:                    HAYESP_SETPRESCALER);
                   1637:                bus_space_write_1(iot, sc->sc_hayespioh, HAYESP_CMD2,
                   1638:                    sc->sc_prescaler);
                   1639:        }
                   1640: #endif
1.99      mycroft  1641:
                   1642:        bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
                   1643: }
                   1644:
                   1645: int
1.197     simonb   1646: comhwiflow(struct tty *tp, int block)
1.99      mycroft  1647: {
1.173     thorpej  1648:        struct com_softc *sc = device_lookup(&com_cd, COMUNIT(tp->t_dev));
1.99      mycroft  1649:        int s;
                   1650:
1.149     thorpej  1651:        if (COM_ISALIVE(sc) == 0)
                   1652:                return (0);
                   1653:
1.99      mycroft  1654:        if (sc->sc_mcr_rts == 0)
                   1655:                return (0);
                   1656:
                   1657:        s = splserial();
1.179     sommerfe 1658:        COM_LOCK(sc);
                   1659:
1.99      mycroft  1660:        if (block) {
1.101     mycroft  1661:                if (!ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) {
                   1662:                        SET(sc->sc_rx_flags, RX_TTY_BLOCKED);
                   1663:                        com_hwiflow(sc);
                   1664:                }
1.99      mycroft  1665:        } else {
1.101     mycroft  1666:                if (ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) {
                   1667:                        CLR(sc->sc_rx_flags, RX_TTY_OVERFLOWED);
                   1668:                        com_schedrx(sc);
                   1669:                }
                   1670:                if (ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) {
                   1671:                        CLR(sc->sc_rx_flags, RX_TTY_BLOCKED);
                   1672:                        com_hwiflow(sc);
                   1673:                }
1.99      mycroft  1674:        }
1.179     sommerfe 1675:
                   1676:        COM_UNLOCK(sc);
1.21      mycroft  1677:        splx(s);
1.99      mycroft  1678:        return (1);
                   1679: }
                   1680:
                   1681: /*
                   1682:  * (un)block input via hw flowcontrol
                   1683:  */
                   1684: void
1.197     simonb   1685: com_hwiflow(struct com_softc *sc)
1.99      mycroft  1686: {
                   1687:        bus_space_tag_t iot = sc->sc_iot;
                   1688:        bus_space_handle_t ioh = sc->sc_ioh;
                   1689:
                   1690:        if (sc->sc_mcr_rts == 0)
                   1691:                return;
                   1692:
1.101     mycroft  1693:        if (ISSET(sc->sc_rx_flags, RX_ANY_BLOCK)) {
1.99      mycroft  1694:                CLR(sc->sc_mcr, sc->sc_mcr_rts);
                   1695:                CLR(sc->sc_mcr_active, sc->sc_mcr_rts);
                   1696:        } else {
                   1697:                SET(sc->sc_mcr, sc->sc_mcr_rts);
                   1698:                SET(sc->sc_mcr_active, sc->sc_mcr_rts);
                   1699:        }
                   1700:        bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr_active);
1.1       cgd      1701: }
1.21      mycroft  1702:
1.99      mycroft  1703:
1.12      deraadt  1704: void
1.197     simonb   1705: comstart(struct tty *tp)
1.1       cgd      1706: {
1.173     thorpej  1707:        struct com_softc *sc = device_lookup(&com_cd, COMUNIT(tp->t_dev));
1.91      thorpej  1708:        bus_space_tag_t iot = sc->sc_iot;
                   1709:        bus_space_handle_t ioh = sc->sc_ioh;
1.21      mycroft  1710:        int s;
                   1711:
1.149     thorpej  1712:        if (COM_ISALIVE(sc) == 0)
                   1713:                return;
                   1714:
1.1       cgd      1715:        s = spltty();
1.178     eeh      1716:        if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP))
1.70      mycroft  1717:                goto out;
1.178     eeh      1718:        if (sc->sc_tx_stopped)
1.127     mycroft  1719:                goto out;
1.178     eeh      1720:
1.61      mycroft  1721:        if (tp->t_outq.c_cc <= tp->t_lowat) {
1.62      mycroft  1722:                if (ISSET(tp->t_state, TS_ASLEEP)) {
                   1723:                        CLR(tp->t_state, TS_ASLEEP);
                   1724:                        wakeup(&tp->t_outq);
1.61      mycroft  1725:                }
1.99      mycroft  1726:                selwakeup(&tp->t_wsel);
1.178     eeh      1727:                if (tp->t_outq.c_cc == 0)
1.127     mycroft  1728:                        goto out;
1.61      mycroft  1729:        }
1.99      mycroft  1730:
                   1731:        /* Grab the first contiguous region of buffer space. */
                   1732:        {
                   1733:                u_char *tba;
                   1734:                int tbc;
                   1735:
                   1736:                tba = tp->t_outq.c_cf;
                   1737:                tbc = ndqb(&tp->t_outq, 0);
                   1738:
                   1739:                (void)splserial();
1.179     sommerfe 1740:                COM_LOCK(sc);
1.99      mycroft  1741:
                   1742:                sc->sc_tba = tba;
                   1743:                sc->sc_tbc = tbc;
                   1744:        }
                   1745:
1.62      mycroft  1746:        SET(tp->t_state, TS_BUSY);
1.99      mycroft  1747:        sc->sc_tx_busy = 1;
1.64      christos 1748:
1.99      mycroft  1749:        /* Enable transmit completion interrupts if necessary. */
1.70      mycroft  1750:        if (!ISSET(sc->sc_ier, IER_ETXRDY)) {
                   1751:                SET(sc->sc_ier, IER_ETXRDY);
1.91      thorpej  1752:                bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
1.70      mycroft  1753:        }
1.99      mycroft  1754:
1.216.2.2  skrll    1755: #if 0
1.99      mycroft  1756:        /* Output the first chunk of the contiguous buffer. */
1.195     thorpej  1757:        if (!ISSET(sc->sc_hwflags, COM_HW_NO_TXPRELOAD)) {
1.201     thorpej  1758:                u_int n;
1.99      mycroft  1759:
1.127     mycroft  1760:                n = sc->sc_tbc;
                   1761:                if (n > sc->sc_fifolen)
                   1762:                        n = sc->sc_fifolen;
1.99      mycroft  1763:                bus_space_write_multi_1(iot, ioh, com_data, sc->sc_tba, n);
                   1764:                sc->sc_tbc -= n;
                   1765:                sc->sc_tba += n;
1.64      christos 1766:        }
1.216.2.2  skrll    1767: #endif
1.179     sommerfe 1768:        COM_UNLOCK(sc);
1.99      mycroft  1769: out:
1.1       cgd      1770:        splx(s);
1.99      mycroft  1771:        return;
1.1       cgd      1772: }
1.21      mycroft  1773:
1.1       cgd      1774: /*
                   1775:  * Stop output on a line.
                   1776:  */
1.85      mycroft  1777: void
1.197     simonb   1778: comstop(struct tty *tp, int flag)
1.1       cgd      1779: {
1.173     thorpej  1780:        struct com_softc *sc = device_lookup(&com_cd, COMUNIT(tp->t_dev));
1.21      mycroft  1781:        int s;
1.1       cgd      1782:
1.99      mycroft  1783:        s = splserial();
1.179     sommerfe 1784:        COM_LOCK(sc);
1.99      mycroft  1785:        if (ISSET(tp->t_state, TS_BUSY)) {
                   1786:                /* Stop transmitting at the next chunk. */
                   1787:                sc->sc_tbc = 0;
                   1788:                sc->sc_heldtbc = 0;
1.62      mycroft  1789:                if (!ISSET(tp->t_state, TS_TTSTOP))
                   1790:                        SET(tp->t_state, TS_FLUSH);
1.99      mycroft  1791:        }
1.179     sommerfe 1792:        COM_UNLOCK(sc);
1.1       cgd      1793:        splx(s);
                   1794: }
                   1795:
1.33      mycroft  1796: void
1.197     simonb   1797: comdiag(void *arg)
1.33      mycroft  1798: {
                   1799:        struct com_softc *sc = arg;
1.99      mycroft  1800:        int overflows, floods;
1.33      mycroft  1801:        int s;
                   1802:
1.99      mycroft  1803:        s = splserial();
1.179     sommerfe 1804:        COM_LOCK(sc);
1.33      mycroft  1805:        overflows = sc->sc_overflows;
                   1806:        sc->sc_overflows = 0;
1.57      mycroft  1807:        floods = sc->sc_floods;
                   1808:        sc->sc_floods = 0;
1.99      mycroft  1809:        sc->sc_errors = 0;
1.179     sommerfe 1810:        COM_UNLOCK(sc);
1.57      mycroft  1811:        splx(s);
                   1812:
1.127     mycroft  1813:        log(LOG_WARNING, "%s: %d silo overflow%s, %d ibuf flood%s\n",
1.57      mycroft  1814:            sc->sc_dev.dv_xname,
                   1815:            overflows, overflows == 1 ? "" : "s",
1.99      mycroft  1816:            floods, floods == 1 ? "" : "s");
1.57      mycroft  1817: }
                   1818:
1.99      mycroft  1819: integrate void
1.197     simonb   1820: com_rxsoft(struct com_softc *sc, struct tty *tp)
1.99      mycroft  1821: {
1.198     simonb   1822:        int (*rint)(int, struct tty *) = tp->t_linesw->l_rint;
1.127     mycroft  1823:        u_char *get, *end;
                   1824:        u_int cc, scc;
                   1825:        u_char lsr;
                   1826:        int code;
                   1827:        int s;
1.57      mycroft  1828:
1.127     mycroft  1829:        end = sc->sc_ebuf;
1.99      mycroft  1830:        get = sc->sc_rbget;
1.127     mycroft  1831:        scc = cc = com_rbuf_size - sc->sc_rbavail;
1.99      mycroft  1832:
1.127     mycroft  1833:        if (cc == com_rbuf_size) {
1.99      mycroft  1834:                sc->sc_floods++;
                   1835:                if (sc->sc_errors++ == 0)
1.170     thorpej  1836:                        callout_reset(&sc->sc_diag_callout, 60 * hz,
                   1837:                            comdiag, sc);
1.99      mycroft  1838:        }
                   1839:
1.205     gson     1840:        /* If not yet open, drop the entire buffer content here */
                   1841:        if (!ISSET(tp->t_state, TS_ISOPEN)) {
                   1842:                get += cc << 1;
                   1843:                if (get >= end)
                   1844:                        get -= com_rbuf_size << 1;
                   1845:                cc = 0;
                   1846:        }
1.101     mycroft  1847:        while (cc) {
1.128     mycroft  1848:                code = get[0];
1.127     mycroft  1849:                lsr = get[1];
1.128     mycroft  1850:                if (ISSET(lsr, LSR_OE | LSR_BI | LSR_FE | LSR_PE)) {
                   1851:                        if (ISSET(lsr, LSR_OE)) {
                   1852:                                sc->sc_overflows++;
                   1853:                                if (sc->sc_errors++ == 0)
1.170     thorpej  1854:                                        callout_reset(&sc->sc_diag_callout,
                   1855:                                            60 * hz, comdiag, sc);
1.128     mycroft  1856:                        }
1.127     mycroft  1857:                        if (ISSET(lsr, LSR_BI | LSR_FE))
                   1858:                                SET(code, TTY_FE);
                   1859:                        if (ISSET(lsr, LSR_PE))
                   1860:                                SET(code, TTY_PE);
                   1861:                }
                   1862:                if ((*rint)(code, tp) == -1) {
1.101     mycroft  1863:                        /*
                   1864:                         * The line discipline's buffer is out of space.
                   1865:                         */
                   1866:                        if (!ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) {
                   1867:                                /*
                   1868:                                 * We're either not using flow control, or the
                   1869:                                 * line discipline didn't tell us to block for
                   1870:                                 * some reason.  Either way, we have no way to
                   1871:                                 * know when there's more space available, so
                   1872:                                 * just drop the rest of the data.
                   1873:                                 */
1.127     mycroft  1874:                                get += cc << 1;
                   1875:                                if (get >= end)
                   1876:                                        get -= com_rbuf_size << 1;
1.101     mycroft  1877:                                cc = 0;
                   1878:                        } else {
                   1879:                                /*
                   1880:                                 * Don't schedule any more receive processing
                   1881:                                 * until the line discipline tells us there's
                   1882:                                 * space available (through comhwiflow()).
                   1883:                                 * Leave the rest of the data in the input
                   1884:                                 * buffer.
                   1885:                                 */
                   1886:                                SET(sc->sc_rx_flags, RX_TTY_OVERFLOWED);
                   1887:                        }
                   1888:                        break;
                   1889:                }
1.127     mycroft  1890:                get += 2;
                   1891:                if (get >= end)
                   1892:                        get = sc->sc_rbuf;
1.101     mycroft  1893:                cc--;
1.99      mycroft  1894:        }
                   1895:
1.101     mycroft  1896:        if (cc != scc) {
                   1897:                sc->sc_rbget = get;
                   1898:                s = splserial();
1.179     sommerfe 1899:                COM_LOCK(sc);
                   1900:
1.101     mycroft  1901:                cc = sc->sc_rbavail += scc - cc;
                   1902:                /* Buffers should be ok again, release possible block. */
                   1903:                if (cc >= sc->sc_r_lowat) {
                   1904:                        if (ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) {
                   1905:                                CLR(sc->sc_rx_flags, RX_IBUF_OVERFLOWED);
                   1906:                                SET(sc->sc_ier, IER_ERXRDY);
1.208     scw      1907: #ifdef COM_PXA2X0
1.209     thorpej  1908:                                if (sc->sc_type == COM_TYPE_PXA2x0)
1.208     scw      1909:                                        SET(sc->sc_ier, IER_ERXTOUT);
                   1910: #endif
1.211     simonb   1911:                                bus_space_write_1(sc->sc_iot, sc->sc_ioh,
                   1912:                                    com_ier, sc->sc_ier);
1.101     mycroft  1913:                        }
                   1914:                        if (ISSET(sc->sc_rx_flags, RX_IBUF_BLOCKED)) {
                   1915:                                CLR(sc->sc_rx_flags, RX_IBUF_BLOCKED);
                   1916:                                com_hwiflow(sc);
                   1917:                        }
                   1918:                }
1.179     sommerfe 1919:                COM_UNLOCK(sc);
1.101     mycroft  1920:                splx(s);
1.57      mycroft  1921:        }
1.99      mycroft  1922: }
                   1923:
                   1924: integrate void
1.197     simonb   1925: com_txsoft(struct com_softc *sc, struct tty *tp)
1.99      mycroft  1926: {
1.33      mycroft  1927:
1.99      mycroft  1928:        CLR(tp->t_state, TS_BUSY);
                   1929:        if (ISSET(tp->t_state, TS_FLUSH))
                   1930:                CLR(tp->t_state, TS_FLUSH);
                   1931:        else
                   1932:                ndflush(&tp->t_outq, (int)(sc->sc_tba - tp->t_outq.c_cf));
1.181     eeh      1933:        (*tp->t_linesw->l_start)(tp);
1.99      mycroft  1934: }
1.57      mycroft  1935:
1.99      mycroft  1936: integrate void
1.197     simonb   1937: com_stsoft(struct com_softc *sc, struct tty *tp)
1.99      mycroft  1938: {
                   1939:        u_char msr, delta;
                   1940:        int s;
1.57      mycroft  1941:
1.99      mycroft  1942:        s = splserial();
1.179     sommerfe 1943:        COM_LOCK(sc);
1.99      mycroft  1944:        msr = sc->sc_msr;
                   1945:        delta = sc->sc_msr_delta;
                   1946:        sc->sc_msr_delta = 0;
1.179     sommerfe 1947:        COM_UNLOCK(sc);
1.99      mycroft  1948:        splx(s);
1.57      mycroft  1949:
1.99      mycroft  1950:        if (ISSET(delta, sc->sc_msr_dcd)) {
                   1951:                /*
                   1952:                 * Inform the tty layer that carrier detect changed.
                   1953:                 */
1.181     eeh      1954:                (void) (*tp->t_linesw->l_modem)(tp, ISSET(msr, MSR_DCD));
1.99      mycroft  1955:        }
1.61      mycroft  1956:
1.99      mycroft  1957:        if (ISSET(delta, sc->sc_msr_cts)) {
                   1958:                /* Block or unblock output according to flow control. */
                   1959:                if (ISSET(msr, sc->sc_msr_cts)) {
                   1960:                        sc->sc_tx_stopped = 0;
1.181     eeh      1961:                        (*tp->t_linesw->l_start)(tp);
1.99      mycroft  1962:                } else {
                   1963:                        sc->sc_tx_stopped = 1;
1.61      mycroft  1964:                }
1.99      mycroft  1965:        }
                   1966:
                   1967: #ifdef COM_DEBUG
1.101     mycroft  1968:        if (com_debug)
1.127     mycroft  1969:                comstatus(sc, "com_stsoft");
1.99      mycroft  1970: #endif
                   1971: }
                   1972:
1.183     thorpej  1973: #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
1.99      mycroft  1974: void
1.197     simonb   1975: comsoft(void *arg)
1.99      mycroft  1976: {
                   1977:        struct com_softc *sc = arg;
                   1978:        struct tty *tp;
                   1979:
1.149     thorpej  1980:        if (COM_ISALIVE(sc) == 0)
1.131     marc     1981:                return;
                   1982:
1.99      mycroft  1983:        {
                   1984: #else
                   1985: void
1.133     cgd      1986: #ifndef __NO_SOFT_SERIAL_INTERRUPT
1.197     simonb   1987: comsoft(void)
1.99      mycroft  1988: #else
1.197     simonb   1989: comsoft(void *arg)
1.99      mycroft  1990: #endif
                   1991: {
                   1992:        struct com_softc        *sc;
                   1993:        struct tty      *tp;
                   1994:        int     unit;
1.133     cgd      1995: #ifdef __NO_SOFT_SERIAL_INTERRUPT
1.99      mycroft  1996:        int s;
                   1997:
                   1998:        s = splsoftserial();
                   1999:        com_softintr_scheduled = 0;
                   2000: #endif
1.57      mycroft  2001:
1.99      mycroft  2002:        for (unit = 0; unit < com_cd.cd_ndevs; unit++) {
1.173     thorpej  2003:                sc = device_lookup(&com_cd, unit);
1.132     cgd      2004:                if (sc == NULL || !ISSET(sc->sc_hwflags, COM_HW_DEV_OK))
1.99      mycroft  2005:                        continue;
1.57      mycroft  2006:
1.149     thorpej  2007:                if (COM_ISALIVE(sc) == 0)
1.131     marc     2008:                        continue;
                   2009:
1.99      mycroft  2010:                tp = sc->sc_tty;
1.141     mycroft  2011:                if (tp == NULL)
                   2012:                        continue;
                   2013:                if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0)
1.57      mycroft  2014:                        continue;
1.108     is       2015: #endif
                   2016:                tp = sc->sc_tty;
1.99      mycroft  2017:
                   2018:                if (sc->sc_rx_ready) {
                   2019:                        sc->sc_rx_ready = 0;
1.127     mycroft  2020:                        com_rxsoft(sc, tp);
1.57      mycroft  2021:                }
                   2022:
1.99      mycroft  2023:                if (sc->sc_st_check) {
                   2024:                        sc->sc_st_check = 0;
1.127     mycroft  2025:                        com_stsoft(sc, tp);
1.62      mycroft  2026:                }
1.57      mycroft  2027:
1.99      mycroft  2028:                if (sc->sc_tx_done) {
                   2029:                        sc->sc_tx_done = 0;
1.127     mycroft  2030:                        com_txsoft(sc, tp);
1.57      mycroft  2031:                }
                   2032:        }
                   2033:
1.183     thorpej  2034: #ifndef __HAVE_GENERIC_SOFT_INTERRUPTS
1.133     cgd      2035: #ifdef __NO_SOFT_SERIAL_INTERRUPT
1.99      mycroft  2036:        splx(s);
                   2037: #endif
                   2038: #endif
1.21      mycroft  2039: }
1.140     ross     2040:
                   2041: #ifdef __ALIGN_BRACKET_LEVEL_FOR_CTAGS
                   2042:        /* there has got to be a better way to do comsoft() */
                   2043: }}
                   2044: #endif
1.1       cgd      2045:
1.21      mycroft  2046: int
1.197     simonb   2047: comintr(void *arg)
1.21      mycroft  2048: {
1.49      cgd      2049:        struct com_softc *sc = arg;
1.91      thorpej  2050:        bus_space_tag_t iot = sc->sc_iot;
                   2051:        bus_space_handle_t ioh = sc->sc_ioh;
1.127     mycroft  2052:        u_char *put, *end;
                   2053:        u_int cc;
                   2054:        u_char lsr, iir;
1.55      mycroft  2055:
1.149     thorpej  2056:        if (COM_ISALIVE(sc) == 0)
1.131     marc     2057:                return (0);
                   2058:
1.179     sommerfe 2059:        COM_LOCK(sc);
1.91      thorpej  2060:        iir = bus_space_read_1(iot, ioh, com_iir);
1.179     sommerfe 2061:        if (ISSET(iir, IIR_NOPEND)) {
                   2062:                COM_UNLOCK(sc);
1.55      mycroft  2063:                return (0);
1.179     sommerfe 2064:        }
1.21      mycroft  2065:
1.127     mycroft  2066:        end = sc->sc_ebuf;
1.99      mycroft  2067:        put = sc->sc_rbput;
                   2068:        cc = sc->sc_rbavail;
                   2069:
1.189     briggs   2070: again: do {
1.168     jonathan 2071:                u_char  msr, delta;
1.21      mycroft  2072:
1.91      thorpej  2073:                lsr = bus_space_read_1(iot, ioh, com_lsr);
1.103     drochner 2074:                if (ISSET(lsr, LSR_BI)) {
1.186     uwe      2075:                        int cn_trapped = 0;
1.207     fvdl     2076:
1.186     uwe      2077:                        cn_check_magic(sc->sc_tty->t_dev,
                   2078:                                       CNC_BREAK, com_cnm_state);
                   2079:                        if (cn_trapped)
1.103     drochner 2080:                                continue;
1.206     briggs   2081: #if defined(KGDB) && !defined(DDB)
1.103     drochner 2082:                        if (ISSET(sc->sc_hwflags, COM_HW_KGDB)) {
                   2083:                                kgdb_connect(1);
                   2084:                                continue;
                   2085:                        }
                   2086: #endif
1.102     thorpej  2087:                }
                   2088:
1.101     mycroft  2089:                if (ISSET(lsr, LSR_RCV_MASK) &&
                   2090:                    !ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) {
1.127     mycroft  2091:                        while (cc > 0) {
1.186     uwe      2092:                                int cn_trapped = 0;
1.127     mycroft  2093:                                put[0] = bus_space_read_1(iot, ioh, com_data);
                   2094:                                put[1] = lsr;
1.186     uwe      2095:                                cn_check_magic(sc->sc_tty->t_dev,
                   2096:                                               put[0], com_cnm_state);
1.216.2.2  skrll    2097:                                if (cn_trapped)
                   2098:                                        goto next;
1.127     mycroft  2099:                                put += 2;
                   2100:                                if (put >= end)
                   2101:                                        put = sc->sc_rbuf;
                   2102:                                cc--;
1.216.2.2  skrll    2103:                        next:
1.99      mycroft  2104:                                lsr = bus_space_read_1(iot, ioh, com_lsr);
1.127     mycroft  2105:                                if (!ISSET(lsr, LSR_RCV_MASK))
                   2106:                                        break;
1.99      mycroft  2107:                        }
1.127     mycroft  2108:
1.99      mycroft  2109:                        /*
                   2110:                         * Current string of incoming characters ended because
1.127     mycroft  2111:                         * no more data was available or we ran out of space.
                   2112:                         * Schedule a receive event if any data was received.
                   2113:                         * If we're out of space, turn off receive interrupts.
1.99      mycroft  2114:                         */
                   2115:                        sc->sc_rbput = put;
                   2116:                        sc->sc_rbavail = cc;
1.101     mycroft  2117:                        if (!ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED))
                   2118:                                sc->sc_rx_ready = 1;
1.127     mycroft  2119:
1.99      mycroft  2120:                        /*
                   2121:                         * See if we are in danger of overflowing a buffer. If
                   2122:                         * so, use hardware flow control to ease the pressure.
                   2123:                         */
1.101     mycroft  2124:                        if (!ISSET(sc->sc_rx_flags, RX_IBUF_BLOCKED) &&
1.99      mycroft  2125:                            cc < sc->sc_r_hiwat) {
1.101     mycroft  2126:                                SET(sc->sc_rx_flags, RX_IBUF_BLOCKED);
                   2127:                                com_hwiflow(sc);
1.99      mycroft  2128:                        }
1.127     mycroft  2129:
1.99      mycroft  2130:                        /*
1.101     mycroft  2131:                         * If we're out of space, disable receive interrupts
                   2132:                         * until the queue has drained a bit.
1.99      mycroft  2133:                         */
                   2134:                        if (!cc) {
1.101     mycroft  2135:                                SET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED);
1.208     scw      2136: #ifdef COM_PXA2X0
1.209     thorpej  2137:                                if (sc->sc_type == COM_TYPE_PXA2x0)
1.216.2.2  skrll    2138:                                        CLR(sc->sc_ier, IER_ERXRDY|IER_ERXTOUT);
                   2139:                                else
1.208     scw      2140: #endif
1.216.2.2  skrll    2141:                                        CLR(sc->sc_ier, IER_ERXRDY);
1.211     simonb   2142:                                bus_space_write_1(iot, ioh, com_ier,
                   2143:                                    sc->sc_ier);
1.99      mycroft  2144:                        }
1.88      mycroft  2145:                } else {
1.216.2.2  skrll    2146:                        if ((iir & (IIR_RXRDY|IIR_TXRDY)) == IIR_RXRDY) {
                   2147:                                (void) bus_space_read_1(iot, ioh, com_data);
1.88      mycroft  2148:                                continue;
                   2149:                        }
                   2150:                }
1.55      mycroft  2151:
1.99      mycroft  2152:                msr = bus_space_read_1(iot, ioh, com_msr);
                   2153:                delta = msr ^ sc->sc_msr;
                   2154:                sc->sc_msr = msr;
1.167     jonathan 2155:                /*
                   2156:                 * Pulse-per-second (PSS) signals on edge of DCD?
                   2157:                 * Process these even if line discipline is ignoring DCD.
                   2158:                 */
1.168     jonathan 2159:                if (delta & sc->sc_ppsmask) {
1.167     jonathan 2160:                        struct timeval tv;
1.168     jonathan 2161:                        if ((msr & sc->sc_ppsmask) == sc->sc_ppsassert) {
1.167     jonathan 2162:                                /* XXX nanotime() */
                   2163:                                microtime(&tv);
                   2164:                                TIMEVAL_TO_TIMESPEC(&tv,
                   2165:                                    &sc->ppsinfo.assert_timestamp);
                   2166:                                if (sc->ppsparam.mode & PPS_OFFSETASSERT) {
                   2167:                                        timespecadd(&sc->ppsinfo.assert_timestamp,
                   2168:                                            &sc->ppsparam.assert_offset,
1.144     jonathan 2169:                                                    &sc->ppsinfo.assert_timestamp);
1.167     jonathan 2170:                                }
1.144     jonathan 2171:
                   2172: #ifdef PPS_SYNC
1.216.2.2  skrll    2173:                                if (pps_kc_hardpps_source == sc &&
                   2174:                                    pps_kc_hardpps_mode & PPS_CAPTUREASSERT) {
1.167     jonathan 2175:                                        hardpps(&tv, tv.tv_usec);
1.216.2.2  skrll    2176:                                }
1.144     jonathan 2177: #endif
1.167     jonathan 2178:                                sc->ppsinfo.assert_sequence++;
                   2179:                                sc->ppsinfo.current_mode = sc->ppsparam.mode;
                   2180:
1.168     jonathan 2181:                        } else if ((msr & sc->sc_ppsmask) == sc->sc_ppsclear) {
1.167     jonathan 2182:                                /* XXX nanotime() */
                   2183:                                microtime(&tv);
                   2184:                                TIMEVAL_TO_TIMESPEC(&tv,
                   2185:                                    &sc->ppsinfo.clear_timestamp);
                   2186:                                if (sc->ppsparam.mode & PPS_OFFSETCLEAR) {
                   2187:                                        timespecadd(&sc->ppsinfo.clear_timestamp,
                   2188:                                            &sc->ppsparam.clear_offset,
1.144     jonathan 2189:                                            &sc->ppsinfo.clear_timestamp);
1.167     jonathan 2190:                                }
1.144     jonathan 2191:
                   2192: #ifdef PPS_SYNC
1.216.2.2  skrll    2193:                                if (pps_kc_hardpps_source == sc &&
                   2194:                                    pps_kc_hardpps_mode & PPS_CAPTURECLEAR) {
1.167     jonathan 2195:                                        hardpps(&tv, tv.tv_usec);
1.216.2.2  skrll    2196:                                }
1.144     jonathan 2197: #endif
1.167     jonathan 2198:                                sc->ppsinfo.clear_sequence++;
                   2199:                                sc->ppsinfo.current_mode = sc->ppsparam.mode;
1.144     jonathan 2200:                        }
1.167     jonathan 2201:                }
1.168     jonathan 2202:
1.167     jonathan 2203:                /*
                   2204:                 * Process normal status changes
                   2205:                 */
                   2206:                if (ISSET(delta, sc->sc_msr_mask)) {
                   2207:                        SET(sc->sc_msr_delta, delta);
1.99      mycroft  2208:
                   2209:                        /*
                   2210:                         * Stop output immediately if we lose the output
                   2211:                         * flow control signal or carrier detect.
                   2212:                         */
                   2213:                        if (ISSET(~msr, sc->sc_msr_mask)) {
                   2214:                                sc->sc_tbc = 0;
                   2215:                                sc->sc_heldtbc = 0;
1.69      mycroft  2216: #ifdef COM_DEBUG
1.101     mycroft  2217:                                if (com_debug)
                   2218:                                        comstatus(sc, "comintr  ");
1.69      mycroft  2219: #endif
1.99      mycroft  2220:                        }
1.55      mycroft  2221:
1.99      mycroft  2222:                        sc->sc_st_check = 1;
1.55      mycroft  2223:                }
1.216.2.2  skrll    2224:        } while (!ISSET((iir =
                   2225:            bus_space_read_1(iot, ioh, com_iir)), IIR_NOPEND) &&
                   2226:            /*
                   2227:             * Since some device (e.g., ST16C1550) doesn't clear IIR_TXRDY
                   2228:             * by IIR read, so we can't do this way: `process all interrupts,
                   2229:             * then do TX if possble'.
                   2230:             */
                   2231:            (iir & IIR_IMASK) != IIR_TXRDY);
1.55      mycroft  2232:
1.99      mycroft  2233:        /*
1.216.2.2  skrll    2234:         * Read LSR again, since there may be an interrupt between
                   2235:         * the last LSR read and IIR read above.
                   2236:         */
                   2237:        lsr = bus_space_read_1(iot, ioh, com_lsr);
                   2238:
                   2239:        /*
                   2240:         * See if data can be transmitted as well.
                   2241:         * Schedule tx done event if no data left
1.99      mycroft  2242:         * and tty was marked busy.
                   2243:         */
                   2244:        if (ISSET(lsr, LSR_TXRDY)) {
                   2245:                /*
                   2246:                 * If we've delayed a parameter change, do it now, and restart
                   2247:                 * output.
                   2248:                 */
                   2249:                if (sc->sc_heldchange) {
                   2250:                        com_loadchannelregs(sc);
                   2251:                        sc->sc_heldchange = 0;
                   2252:                        sc->sc_tbc = sc->sc_heldtbc;
                   2253:                        sc->sc_heldtbc = 0;
                   2254:                }
1.127     mycroft  2255:
1.99      mycroft  2256:                /* Output the next chunk of the contiguous buffer, if any. */
                   2257:                if (sc->sc_tbc > 0) {
1.201     thorpej  2258:                        u_int n;
1.99      mycroft  2259:
1.127     mycroft  2260:                        n = sc->sc_tbc;
                   2261:                        if (n > sc->sc_fifolen)
                   2262:                                n = sc->sc_fifolen;
1.99      mycroft  2263:                        bus_space_write_multi_1(iot, ioh, com_data, sc->sc_tba, n);
                   2264:                        sc->sc_tbc -= n;
                   2265:                        sc->sc_tba += n;
1.127     mycroft  2266:                } else {
                   2267:                        /* Disable transmit completion interrupts if necessary. */
                   2268:                        if (ISSET(sc->sc_ier, IER_ETXRDY)) {
                   2269:                                CLR(sc->sc_ier, IER_ETXRDY);
                   2270:                                bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
                   2271:                        }
                   2272:                        if (sc->sc_tx_busy) {
                   2273:                                sc->sc_tx_busy = 0;
                   2274:                                sc->sc_tx_done = 1;
                   2275:                        }
1.62      mycroft  2276:                }
1.99      mycroft  2277:        }
1.189     briggs   2278:
                   2279:        if (!ISSET((iir = bus_space_read_1(iot, ioh, com_iir)), IIR_NOPEND))
                   2280:                goto again;
                   2281:
1.179     sommerfe 2282:        COM_UNLOCK(sc);
1.62      mycroft  2283:
1.99      mycroft  2284:        /* Wake up the poller. */
1.183     thorpej  2285: #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
1.99      mycroft  2286:        softintr_schedule(sc->sc_si);
                   2287: #else
1.133     cgd      2288: #ifndef __NO_SOFT_SERIAL_INTERRUPT
1.99      mycroft  2289:        setsoftserial();
                   2290: #else
                   2291:        if (!com_softintr_scheduled) {
                   2292:                com_softintr_scheduled = 1;
1.170     thorpej  2293:                callout_reset(&comsoft_callout, 1, comsoft, NULL);
1.1       cgd      2294:        }
1.99      mycroft  2295: #endif
                   2296: #endif
1.115     explorer 2297:
                   2298: #if NRND > 0 && defined(RND_COM)
                   2299:        rnd_add_uint32(&sc->rnd_source, iir | lsr);
                   2300: #endif
                   2301:
1.88      mycroft  2302:        return (1);
1.1       cgd      2303: }
                   2304:
                   2305: /*
1.102     thorpej  2306:  * The following functions are polled getc and putc routines, shared
                   2307:  * by the console and kgdb glue.
1.186     uwe      2308:  *
                   2309:  * The read-ahead code is so that you can detect pending in-band
                   2310:  * cn_magic in polled mode while doing output rather than having to
                   2311:  * wait until the kernel decides it needs input.
1.102     thorpej  2312:  */
                   2313:
1.186     uwe      2314: #define MAX_READAHEAD  20
                   2315: static int com_readahead[MAX_READAHEAD];
                   2316: static int com_readaheadcount = 0;
1.174     jeffs    2317:
1.102     thorpej  2318: int
1.197     simonb   2319: com_common_getc(dev_t dev, bus_space_tag_t iot, bus_space_handle_t ioh)
1.102     thorpej  2320: {
                   2321:        int s = splserial();
                   2322:        u_char stat, c;
                   2323:
1.174     jeffs    2324:        /* got a character from reading things earlier */
1.186     uwe      2325:        if (com_readaheadcount > 0) {
1.174     jeffs    2326:                int i;
                   2327:
1.186     uwe      2328:                c = com_readahead[0];
                   2329:                for (i = 1; i < com_readaheadcount; i++) {
                   2330:                        com_readahead[i-1] = com_readahead[i];
1.174     jeffs    2331:                }
1.186     uwe      2332:                com_readaheadcount--;
1.174     jeffs    2333:                splx(s);
                   2334:                return (c);
                   2335:        }
                   2336:
1.135     thorpej  2337:        /* block until a character becomes available */
                   2338:        while (!ISSET(stat = bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY))
1.102     thorpej  2339:                ;
1.135     thorpej  2340:
1.102     thorpej  2341:        c = bus_space_read_1(iot, ioh, com_data);
                   2342:        stat = bus_space_read_1(iot, ioh, com_iir);
1.186     uwe      2343:        {
                   2344:                int cn_trapped = 0; /* unused */
                   2345: #ifdef DDB
1.174     jeffs    2346:                extern int db_active;
1.186     uwe      2347:                if (!db_active)
                   2348: #endif
                   2349:                        cn_check_magic(dev, c, com_cnm_state);
1.174     jeffs    2350:        }
1.102     thorpej  2351:        splx(s);
                   2352:        return (c);
                   2353: }
                   2354:
                   2355: void
1.197     simonb   2356: com_common_putc(dev_t dev, bus_space_tag_t iot, bus_space_handle_t ioh, int c)
1.102     thorpej  2357: {
                   2358:        int s = splserial();
1.204     simonb   2359:        int cin, stat, timo;
1.174     jeffs    2360:
1.186     uwe      2361:        if (com_readaheadcount < MAX_READAHEAD
1.174     jeffs    2362:             && ISSET(stat = bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY)) {
1.186     uwe      2363:                int cn_trapped = 0;
1.174     jeffs    2364:                cin = bus_space_read_1(iot, ioh, com_data);
                   2365:                stat = bus_space_read_1(iot, ioh, com_iir);
1.186     uwe      2366:                cn_check_magic(dev, cin, com_cnm_state);
                   2367:                com_readahead[com_readaheadcount++] = cin;
1.174     jeffs    2368:        }
1.102     thorpej  2369:
                   2370:        /* wait for any pending transmission to finish */
1.161     ross     2371:        timo = 150000;
1.160     thorpej  2372:        while (!ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_TXRDY) && --timo)
1.161     ross     2373:                continue;
1.135     thorpej  2374:
1.102     thorpej  2375:        bus_space_write_1(iot, ioh, com_data, c);
1.160     thorpej  2376:        COM_BARRIER(iot, ioh, BR | BW);
                   2377:
1.157     mycroft  2378:        splx(s);
1.102     thorpej  2379: }
                   2380:
                   2381: /*
1.165     drochner 2382:  * Initialize UART for use as console or KGDB line.
1.99      mycroft  2383:  */
1.106     drochner 2384: int
1.197     simonb   2385: cominit(bus_space_tag_t iot, bus_addr_t iobase, int rate, int frequency,
1.210     thorpej  2386:     int type, tcflag_t cflag, bus_space_handle_t *iohp)
1.1       cgd      2387: {
1.106     drochner 2388:        bus_space_handle_t ioh;
                   2389:
                   2390:        if (bus_space_map(iot, iobase, COM_NPORTS, 0, &ioh))
1.110     enami    2391:                return (ENOMEM); /* ??? */
1.1       cgd      2392:
1.116     fvdl     2393:        bus_space_write_1(iot, ioh, com_lcr, LCR_EERS);
                   2394:        bus_space_write_1(iot, ioh, com_efr, 0);
1.91      thorpej  2395:        bus_space_write_1(iot, ioh, com_lcr, LCR_DLAB);
1.210     thorpej  2396:        rate = comspeed(rate, frequency, type);
1.91      thorpej  2397:        bus_space_write_1(iot, ioh, com_dlbl, rate);
                   2398:        bus_space_write_1(iot, ioh, com_dlbh, rate >> 8);
1.106     drochner 2399:        bus_space_write_1(iot, ioh, com_lcr, cflag2lcr(cflag));
1.165     drochner 2400:        bus_space_write_1(iot, ioh, com_mcr, MCR_DTR | MCR_RTS);
1.91      thorpej  2401:        bus_space_write_1(iot, ioh, com_fifo,
1.87      mycroft  2402:            FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_1);
1.212     bsh      2403: #ifdef COM_PXA2X0
1.216.2.2  skrll    2404:        if (type == COM_TYPE_PXA2x0)
                   2405:                bus_space_write_1(iot, ioh, com_ier, IER_EUART);
                   2406:        else
1.212     bsh      2407: #endif
1.216.2.2  skrll    2408:                bus_space_write_1(iot, ioh, com_ier, 0);
1.106     drochner 2409:
                   2410:        *iohp = ioh;
1.110     enami    2411:        return (0);
1.99      mycroft  2412: }
                   2413:
                   2414: /*
1.106     drochner 2415:  * Following are all routines needed for COM to act as console
1.99      mycroft  2416:  */
1.177     eeh      2417: struct consdev comcons = {
1.203     matt     2418:        NULL, NULL, comcngetc, comcnputc, comcnpollc, NULL, NULL, NULL,
1.177     eeh      2419:        NODEV, CN_NORMAL
                   2420: };
                   2421:
1.106     drochner 2422:
                   2423: int
1.197     simonb   2424: comcnattach(bus_space_tag_t iot, bus_addr_t iobase, int rate, int frequency,
1.210     thorpej  2425:     int type, tcflag_t cflag)
1.99      mycroft  2426: {
1.106     drochner 2427:        int res;
                   2428:
1.210     thorpej  2429:        res = cominit(iot, iobase, rate, frequency, type, cflag, &comconsioh);
1.110     enami    2430:        if (res)
                   2431:                return (res);
1.106     drochner 2432:
                   2433:        cn_tab = &comcons;
1.186     uwe      2434:        cn_init_magic(&com_cnm_state);
                   2435:        cn_set_magic("\047\001"); /* default magic is BREAK */
1.106     drochner 2436:
                   2437:        comconstag = iot;
                   2438:        comconsaddr = iobase;
                   2439:        comconsrate = rate;
                   2440:        comconscflag = cflag;
1.99      mycroft  2441:
1.110     enami    2442:        return (0);
1.1       cgd      2443: }
                   2444:
1.80      christos 2445: int
1.197     simonb   2446: comcngetc(dev_t dev)
1.1       cgd      2447: {
1.197     simonb   2448:
1.186     uwe      2449:        return (com_common_getc(dev, comconstag, comconsioh));
1.1       cgd      2450: }
                   2451:
                   2452: /*
                   2453:  * Console kernel output character routine.
                   2454:  */
1.48      mycroft  2455: void
1.197     simonb   2456: comcnputc(dev_t dev, int c)
1.1       cgd      2457: {
1.197     simonb   2458:
1.186     uwe      2459:        com_common_putc(dev, comconstag, comconsioh, c);
1.37      mycroft  2460: }
                   2461:
                   2462: void
1.197     simonb   2463: comcnpollc(dev_t dev, int on)
1.37      mycroft  2464: {
                   2465:
1.106     drochner 2466: }
                   2467:
                   2468: #ifdef KGDB
                   2469: int
1.197     simonb   2470: com_kgdb_attach(bus_space_tag_t iot, bus_addr_t iobase, int rate,
1.210     thorpej  2471:     int frequency, int type, tcflag_t cflag)
1.106     drochner 2472: {
                   2473:        int res;
1.107     drochner 2474:
1.206     briggs   2475:        if (iot == comconstag && iobase == comconsaddr) {
                   2476: #if !defined(DDB)
1.110     enami    2477:                return (EBUSY); /* cannot share with console */
1.206     briggs   2478: #else
                   2479:                com_kgdb_ioh = comconsioh;
                   2480: #endif
                   2481:        } else {
1.210     thorpej  2482:                res = cominit(iot, iobase, rate, frequency, type, cflag,
1.206     briggs   2483:                              &com_kgdb_ioh);
                   2484:                if (res)
                   2485:                        return (res);
1.190     fvdl     2486:
1.206     briggs   2487:                /*
                   2488:                 * XXXfvdl this shouldn't be needed, but the cn_magic goo
                   2489:                 * expects this to be initialized
                   2490:                 */
                   2491:                cn_init_magic(&com_cnm_state);
                   2492:                cn_set_magic("\047\001");
                   2493:        }
1.106     drochner 2494:
                   2495:        kgdb_attach(com_kgdb_getc, com_kgdb_putc, NULL);
                   2496:        kgdb_dev = 123; /* unneeded, only to satisfy some tests */
                   2497:
                   2498:        com_kgdb_iot = iot;
                   2499:        com_kgdb_addr = iobase;
                   2500:
1.110     enami    2501:        return (0);
1.106     drochner 2502: }
                   2503:
                   2504: /* ARGSUSED */
                   2505: int
1.197     simonb   2506: com_kgdb_getc(void *arg)
1.106     drochner 2507: {
1.197     simonb   2508:
1.186     uwe      2509:        return (com_common_getc(NODEV, com_kgdb_iot, com_kgdb_ioh));
1.106     drochner 2510: }
                   2511:
                   2512: /* ARGSUSED */
                   2513: void
1.197     simonb   2514: com_kgdb_putc(void *arg, int c)
1.106     drochner 2515: {
1.197     simonb   2516:
1.186     uwe      2517:        com_common_putc(NODEV, com_kgdb_iot, com_kgdb_ioh, c);
1.106     drochner 2518: }
                   2519: #endif /* KGDB */
                   2520:
                   2521: /* helper function to identify the com ports used by
                   2522:  console or KGDB (and not yet autoconf attached) */
                   2523: int
1.197     simonb   2524: com_is_console(bus_space_tag_t iot, bus_addr_t iobase, bus_space_handle_t *ioh)
1.106     drochner 2525: {
                   2526:        bus_space_handle_t help;
                   2527:
1.110     enami    2528:        if (!comconsattached &&
                   2529:            iot == comconstag && iobase == comconsaddr)
1.106     drochner 2530:                help = comconsioh;
                   2531: #ifdef KGDB
1.110     enami    2532:        else if (!com_kgdb_attached &&
                   2533:            iot == com_kgdb_iot && iobase == com_kgdb_addr)
1.106     drochner 2534:                help = com_kgdb_ioh;
                   2535: #endif
                   2536:        else
1.110     enami    2537:                return (0);
1.106     drochner 2538:
1.110     enami    2539:        if (ioh)
                   2540:                *ioh = help;
                   2541:        return (1);
1.2       cgd      2542: }

CVSweb <webmaster@jp.NetBSD.org>