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

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

CVSweb <webmaster@jp.NetBSD.org>