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

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

CVSweb <webmaster@jp.NetBSD.org>