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

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

CVSweb <webmaster@jp.NetBSD.org>