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

1.105   ! drochner    1: /*     $NetBSD: com.c,v 1.104 1997/08/14 16:15:15 drochner Exp $       */
1.38      cgd         2:
1.1       cgd         3: /*-
1.99      mycroft     4:  * Copyright (c) 1993, 1994, 1995, 1996, 1997
1.71      mycroft     5:  *     Charles M. Hannum.  All rights reserved.
1.99      mycroft     6:  *
                      7:  * Interrupt processing and hardware flow control partly based on code from
                      8:  * Onno van der Linden and Gordon Ross.
                      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:
                     20:  *     This product includes software developed by Charles M. Hannum.
                     21:  * 4. The name of the author may not be used to endorse or promote products
                     22:  *    derived from this software without specific prior written permission.
                     23:  *
                     24:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     25:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     26:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     27:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     28:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     29:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     30:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     31:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     32:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     33:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     34:  */
                     35:
                     36: /*
1.1       cgd        37:  * Copyright (c) 1991 The Regents of the University of California.
                     38:  * All rights reserved.
                     39:  *
                     40:  * Redistribution and use in source and binary forms, with or without
                     41:  * modification, are permitted provided that the following conditions
                     42:  * are met:
                     43:  * 1. Redistributions of source code must retain the above copyright
                     44:  *    notice, this list of conditions and the following disclaimer.
                     45:  * 2. Redistributions in binary form must reproduce the above copyright
                     46:  *    notice, this list of conditions and the following disclaimer in the
                     47:  *    documentation and/or other materials provided with the distribution.
                     48:  * 3. All advertising materials mentioning features or use of this software
                     49:  *    must display the following acknowledgement:
                     50:  *     This product includes software developed by the University of
                     51:  *     California, Berkeley and its contributors.
                     52:  * 4. Neither the name of the University nor the names of its contributors
                     53:  *    may be used to endorse or promote products derived from this software
                     54:  *    without specific prior written permission.
                     55:  *
                     56:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     57:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     58:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     59:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     60:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     61:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     62:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     63:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     64:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     65:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     66:  * SUCH DAMAGE.
                     67:  *
1.38      cgd        68:  *     @(#)com.c       7.5 (Berkeley) 5/16/91
1.1       cgd        69:  */
                     70:
                     71: /*
1.99      mycroft    72:  * COM driver, uses National Semiconductor NS16450/NS16550AF UART
1.1       cgd        73:  */
1.14      mycroft    74: #include <sys/param.h>
                     75: #include <sys/systm.h>
                     76: #include <sys/ioctl.h>
                     77: #include <sys/select.h>
                     78: #include <sys/tty.h>
                     79: #include <sys/proc.h>
                     80: #include <sys/user.h>
                     81: #include <sys/conf.h>
                     82: #include <sys/file.h>
                     83: #include <sys/uio.h>
                     84: #include <sys/kernel.h>
                     85: #include <sys/syslog.h>
                     86: #include <sys/types.h>
1.21      mycroft    87: #include <sys/device.h>
1.14      mycroft    88:
1.99      mycroft    89: #include <machine/intr.h>
1.82      mycroft    90: #include <machine/bus.h>
1.14      mycroft    91:
1.47      cgd        92: #include <dev/isa/comreg.h>
1.74      cgd        93: #include <dev/isa/comvar.h>
1.60      cgd        94: #include <dev/ic/ns16550reg.h>
1.65      christos   95: #ifdef COM_HAYESP
                     96: #include <dev/ic/hayespreg.h>
                     97: #endif
1.62      mycroft    98: #define        com_lcr com_cfcr
1.14      mycroft    99:
1.77      cgd       100: #include "com.h"
                    101:
1.65      christos  102: #ifdef COM_HAYESP
1.99      mycroft   103: int comprobeHAYESP __P((bus_space_handle_t hayespioh, struct com_softc *sc));
1.65      christos  104: #endif
1.102     thorpej   105:
1.104     drochner  106: #if defined(DDB) || defined(KGDB)
                    107: static void com_enable_debugport __P((struct com_softc *));
                    108: #endif
1.99      mycroft   109: void   com_attach_subr __P((struct com_softc *sc));
1.80      christos  110: void   comdiag         __P((void *));
                    111: int    comspeed        __P((long));
                    112: int    comparam        __P((struct tty *, struct termios *));
                    113: void   comstart        __P((struct tty *));
1.99      mycroft   114: void   comstop         __P((struct tty *, int));
                    115: #ifdef __GENERIC_SOFT_INTERRUPTS
                    116: void   comsoft         __P((void *));
                    117: #else
                    118: #ifndef alpha
                    119: void   comsoft         __P((void));
                    120: #else
                    121: void   comsoft         __P((void *));
                    122: #endif
                    123: #endif
                    124: int    comhwiflow      __P((struct tty *, int));
                    125:
                    126: void   com_loadchannelregs __P((struct com_softc *));
1.101     mycroft   127: void   com_hwiflow     __P((struct com_softc *));
1.99      mycroft   128: void   com_break       __P((struct com_softc *, int));
                    129: void   com_modem       __P((struct com_softc *, int));
                    130: void   com_iflush      __P((struct com_softc *));
1.80      christos  131:
1.102     thorpej   132: int    com_common_getc __P((bus_space_tag_t, bus_space_handle_t));
                    133: void   com_common_putc __P((bus_space_tag_t, bus_space_handle_t, int));
                    134:
1.80      christos  135: /* XXX: These belong elsewhere */
                    136: cdev_decl(com);
                    137: bdev_decl(com);
                    138:
                    139: struct consdev;
                    140: void   comcnprobe      __P((struct consdev *));
                    141: void   comcninit       __P((struct consdev *));
                    142: int    comcngetc       __P((dev_t));
                    143: void   comcnputc       __P((dev_t, int));
                    144: void   comcnpollc      __P((dev_t, int));
                    145:
1.99      mycroft   146: #define        integrate       static inline
                    147: integrate void comrxint                __P((struct com_softc *, struct tty *));
                    148: integrate void comtxint                __P((struct com_softc *, struct tty *));
                    149: integrate void commsrint       __P((struct com_softc *, struct tty *));
1.101     mycroft   150: integrate void com_schedrx     __P((struct com_softc *));
1.75      cgd       151:
1.76      thorpej   152: struct cfdriver com_cd = {
                    153:        NULL, "com", DV_TTY
1.1       cgd       154: };
1.76      thorpej   155:
1.99      mycroft   156: void cominitcons       __P((bus_space_tag_t, bus_space_handle_t, int));
                    157:
                    158: #ifdef CONSPEED
                    159: int    comconsrate = CONSPEED;
1.1       cgd       160: #else
1.98      mycroft   161: int    comconsrate = TTYDEF_SPEED;
1.1       cgd       162: #endif
1.75      cgd       163: int    comconsaddr;
1.91      thorpej   164: bus_space_tag_t comconstag;
1.98      mycroft   165: bus_space_handle_t comconsioh;
1.79      cgd       166: tcflag_t comconscflag = TTYDEF_CFLAG;
1.105   ! drochner  167: int    comconsattached;
1.75      cgd       168:
1.1       cgd       169: int    commajor;
1.99      mycroft   170:
                    171: #ifndef __GENERIC_SOFT_INTERRUPTS
                    172: #ifdef alpha
                    173: volatile int   com_softintr_scheduled;
                    174: #endif
                    175: #endif
1.1       cgd       176:
                    177: #ifdef KGDB
1.102     thorpej   178: #include <sys/kgdb.h>
1.1       cgd       179: extern int kgdb_dev;
                    180: extern int kgdb_rate;
                    181: extern int kgdb_debug_init;
1.102     thorpej   182:
1.103     drochner  183: int com_kgdb_addr;
1.102     thorpej   184: bus_space_tag_t com_kgdb_iot;
                    185: bus_space_handle_t com_kgdb_ioh;
                    186:
                    187: int    com_kgdb_getc __P((void *));
                    188: void   com_kgdb_putc __P((void *, int));
                    189: #endif /* KGDB */
1.1       cgd       190:
1.21      mycroft   191: #define        COMUNIT(x)      (minor(x))
1.1       cgd       192:
1.21      mycroft   193: int
                    194: comspeed(speed)
                    195:        long speed;
1.1       cgd       196: {
1.21      mycroft   197: #define        divrnd(n, q)    (((n)*2/(q)+1)/2)       /* divide and round off */
                    198:
                    199:        int x, err;
                    200:
1.99      mycroft   201: #if 0
1.21      mycroft   202:        if (speed == 0)
1.99      mycroft   203:                return (0);
                    204: #endif
                    205:        if (speed <= 0)
                    206:                return (-1);
1.21      mycroft   207:        x = divrnd((COM_FREQ / 16), speed);
                    208:        if (x <= 0)
1.99      mycroft   209:                return (-1);
1.21      mycroft   210:        err = divrnd((COM_FREQ / 16) * 1000, speed * x) - 1000;
                    211:        if (err < 0)
                    212:                err = -err;
                    213:        if (err > COM_TOLERANCE)
1.99      mycroft   214:                return (-1);
                    215:        return (x);
1.21      mycroft   216:
                    217: #undef divrnd(n, q)
                    218: }
                    219:
1.99      mycroft   220: #ifdef COM_DEBUG
1.101     mycroft   221: int    com_debug = 0;
                    222:
1.99      mycroft   223: void comstatus __P((struct com_softc *, char *));
                    224: void
                    225: comstatus(sc, str)
                    226:        struct com_softc *sc;
                    227:        char *str;
                    228: {
                    229:        struct tty *tp = sc->sc_tty;
                    230:
                    231:        printf("%s: %s %sclocal  %sdcd %sts_carr_on %sdtr %stx_stopped\n",
                    232:            sc->sc_dev.dv_xname, str,
                    233:            ISSET(tp->t_cflag, CLOCAL) ? "+" : "-",
                    234:            ISSET(sc->sc_msr, MSR_DCD) ? "+" : "-",
                    235:            ISSET(tp->t_state, TS_CARR_ON) ? "+" : "-",
                    236:            ISSET(sc->sc_mcr, MCR_DTR) ? "+" : "-",
                    237:            sc->sc_tx_stopped ? "+" : "-");
                    238:
1.101     mycroft   239:        printf("%s: %s %scrtscts %scts %sts_ttstop  %srts %xrx_flags\n",
1.99      mycroft   240:            sc->sc_dev.dv_xname, str,
                    241:            ISSET(tp->t_cflag, CRTSCTS) ? "+" : "-",
                    242:            ISSET(sc->sc_msr, MSR_CTS) ? "+" : "-",
                    243:            ISSET(tp->t_state, TS_TTSTOP) ? "+" : "-",
                    244:            ISSET(sc->sc_mcr, MCR_RTS) ? "+" : "-",
1.101     mycroft   245:            sc->sc_rx_flags);
1.99      mycroft   246: }
                    247: #endif
                    248:
1.21      mycroft   249: int
1.91      thorpej   250: comprobe1(iot, ioh, iobase)
                    251:        bus_space_tag_t iot;
                    252:        bus_space_handle_t ioh;
1.41      mycroft   253:        int iobase;
1.21      mycroft   254: {
                    255:
1.1       cgd       256:        /* force access to id reg */
1.91      thorpej   257:        bus_space_write_1(iot, ioh, com_lcr, 0);
                    258:        bus_space_write_1(iot, ioh, com_iir, 0);
                    259:        if (bus_space_read_1(iot, ioh, com_iir) & 0x38)
1.99      mycroft   260:                return (0);
1.21      mycroft   261:
1.99      mycroft   262:        return (1);
1.1       cgd       263: }
                    264:
1.65      christos  265: #ifdef COM_HAYESP
                    266: int
1.75      cgd       267: comprobeHAYESP(hayespioh, sc)
1.91      thorpej   268:        bus_space_handle_t hayespioh;
1.64      christos  269:        struct com_softc *sc;
                    270: {
1.65      christos  271:        char    val, dips;
1.64      christos  272:        int     combaselist[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
1.91      thorpej   273:        bus_space_tag_t iot = sc->sc_iot;
1.64      christos  274:
                    275:        /*
                    276:         * Hayes ESP cards have two iobases.  One is for compatibility with
                    277:         * 16550 serial chips, and at the same ISA PC base addresses.  The
                    278:         * other is for ESP-specific enhanced features, and lies at a
1.65      christos  279:         * different addressing range entirely (0x140, 0x180, 0x280, or 0x300).
1.64      christos  280:         */
                    281:
                    282:        /* Test for ESP signature */
1.91      thorpej   283:        if ((bus_space_read_1(iot, hayespioh, 0) & 0xf3) == 0)
1.99      mycroft   284:                return (0);
1.64      christos  285:
                    286:        /*
                    287:         * ESP is present at ESP enhanced base address; unknown com port
                    288:         */
                    289:
                    290:        /* Get the dip-switch configurations */
1.91      thorpej   291:        bus_space_write_1(iot, hayespioh, HAYESP_CMD1, HAYESP_GETDIPS);
                    292:        dips = bus_space_read_1(iot, hayespioh, HAYESP_STATUS1);
1.64      christos  293:
                    294:        /* Determine which com port this ESP card services: bits 0,1 of  */
                    295:        /*  dips is the port # (0-3); combaselist[val] is the com_iobase */
1.65      christos  296:        if (sc->sc_iobase != combaselist[dips & 0x03])
1.99      mycroft   297:                return (0);
1.65      christos  298:
1.90      christos  299:        printf(": ESP");
1.64      christos  300:
1.65      christos  301:        /* Check ESP Self Test bits. */
1.64      christos  302:        /* Check for ESP version 2.0: bits 4,5,6 == 010 */
1.91      thorpej   303:        bus_space_write_1(iot, hayespioh, HAYESP_CMD1, HAYESP_GETTEST);
1.99      mycroft   304:        val = bus_space_read_1(iot, hayespioh, HAYESP_STATUS1); /* Clear reg1 */
1.91      thorpej   305:        val = bus_space_read_1(iot, hayespioh, HAYESP_STATUS2);
1.64      christos  306:        if ((val & 0x70) < 0x20) {
1.90      christos  307:                printf("-old (%o)", val & 0x70);
1.64      christos  308:                /* we do not support the necessary features */
1.99      mycroft   309:                return (0);
1.64      christos  310:        }
                    311:
                    312:        /* Check for ability to emulate 16550: bit 8 == 1 */
                    313:        if ((dips & 0x80) == 0) {
1.90      christos  314:                printf(" slave");
1.64      christos  315:                /* XXX Does slave really mean no 16550 support?? */
1.99      mycroft   316:                return (0);
1.64      christos  317:        }
                    318:
                    319:        /*
                    320:         * If we made it this far, we are a full-featured ESP v2.0 (or
                    321:         * better), at the correct com port address.
                    322:         */
                    323:
1.65      christos  324:        SET(sc->sc_hwflags, COM_HW_HAYESP);
1.90      christos  325:        printf(", 1024 byte fifo\n");
1.99      mycroft   326:        return (1);
1.64      christos  327: }
1.65      christos  328: #endif
1.64      christos  329:
1.99      mycroft   330: #ifdef KGDB
1.102     thorpej   331: /* ARGSUSED */
                    332: int
                    333: com_kgdb_getc(arg)
                    334:        void *arg;
                    335: {
                    336:
                    337:        return (com_common_getc(com_kgdb_iot, com_kgdb_ioh));
                    338: }
                    339:
                    340: /* ARGSUSED */
                    341: void
                    342: com_kgdb_putc(arg, c)
                    343:        void *arg;
                    344:        int c;
                    345: {
                    346:
                    347:        return (com_common_putc(com_kgdb_iot, com_kgdb_ioh, c));
1.99      mycroft   348: }
1.102     thorpej   349: #endif /* KGDB */
1.75      cgd       350:
1.104     drochner  351: #if defined(DDB) || defined(KGDB)
                    352: static void
                    353: com_enable_debugport(sc)
                    354:        struct com_softc *sc;
                    355: {
                    356:        int s;
                    357:
                    358:        /* Turn on line break interrupt, set carrier. */
                    359:        s = splserial();
                    360:        sc->sc_ier = IER_ERXRDY;
                    361:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_ier, sc->sc_ier);
                    362:        SET(sc->sc_mcr, MCR_DTR | MCR_RTS);
                    363:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_mcr, sc->sc_mcr);
                    364:        splx(s);
                    365: }
                    366: #endif
1.1       cgd       367:
1.29      mycroft   368: void
1.99      mycroft   369: com_attach_subr(sc)
                    370:        struct com_softc *sc;
1.29      mycroft   371: {
1.99      mycroft   372:        int iobase = sc->sc_iobase;
                    373:        bus_space_tag_t iot = sc->sc_iot;
                    374:        bus_space_handle_t ioh = sc->sc_ioh;
1.65      christos  375: #ifdef COM_HAYESP
                    376:        int     hayesp_ports[] = { 0x140, 0x180, 0x280, 0x300, 0 };
                    377:        int     *hayespp;
                    378: #endif
1.1       cgd       379:
1.75      cgd       380:        if (iobase == comconsaddr) {
1.105   ! drochner  381:                comconsattached = 1;
        !           382:
1.96      mycroft   383:                /* Make sure the console is always "hardwired". */
1.75      cgd       384:                delay(1000);                    /* wait for output to finish */
                    385:                SET(sc->sc_hwflags, COM_HW_CONSOLE);
1.99      mycroft   386:                SET(sc->sc_swflags, TIOCFLAG_SOFTCAR);
1.75      cgd       387:        }
1.26      cgd       388:
1.65      christos  389: #ifdef COM_HAYESP
                    390:        /* Look for a Hayes ESP board. */
1.75      cgd       391:        for (hayespp = hayesp_ports; *hayespp != 0; hayespp++) {
1.91      thorpej   392:                bus_space_handle_t hayespioh;
1.75      cgd       393:
                    394: #define        HAYESP_NPORTS   8                       /* XXX XXX XXX ??? ??? ??? */
1.92      cgd       395:                if (bus_space_map(iot, *hayespp, HAYESP_NPORTS, 0, &hayespioh))
1.75      cgd       396:                        continue;
                    397:                if (comprobeHAYESP(hayespioh, sc)) {
                    398:                        sc->sc_hayespioh = hayespioh;
1.99      mycroft   399:                        sc->sc_fifolen = 1024;
                    400:
                    401:                        /* Set 16550 compatibility mode */
                    402:                        bus_space_write_1(iot, hayespioh, HAYESP_CMD1, HAYESP_SETMODE);
                    403:                        bus_space_write_1(iot, hayespioh, HAYESP_CMD2,
                    404:                             HAYESP_MODE_FIFO|HAYESP_MODE_RTS|
                    405:                             HAYESP_MODE_SCALE);
                    406:
                    407:                        /* Set RTS/CTS flow control */
                    408:                        bus_space_write_1(iot, hayespioh, HAYESP_CMD1, HAYESP_SETFLOWTYPE);
                    409:                        bus_space_write_1(iot, hayespioh, HAYESP_CMD2, HAYESP_FLOW_RTS);
                    410:                        bus_space_write_1(iot, hayespioh, HAYESP_CMD2, HAYESP_FLOW_CTS);
                    411:
                    412:                        /* Set flow control levels */
                    413:                        bus_space_write_1(iot, hayespioh, HAYESP_CMD1, HAYESP_SETRXFLOW);
                    414:                        bus_space_write_1(iot, hayespioh, HAYESP_CMD2,
                    415:                             HAYESP_HIBYTE(HAYESP_RXHIWMARK));
                    416:                        bus_space_write_1(iot, hayespioh, HAYESP_CMD2,
                    417:                             HAYESP_LOBYTE(HAYESP_RXHIWMARK));
                    418:                        bus_space_write_1(iot, hayespioh, HAYESP_CMD2,
                    419:                             HAYESP_HIBYTE(HAYESP_RXLOWMARK));
                    420:                        bus_space_write_1(iot, hayespioh, HAYESP_CMD2,
                    421:                             HAYESP_LOBYTE(HAYESP_RXLOWMARK));
                    422:
1.65      christos  423:                        break;
                    424:                }
1.91      thorpej   425:                bus_space_unmap(iot, hayespioh, HAYESP_NPORTS);
1.75      cgd       426:        }
1.65      christos  427:        /* No ESP; look for other things. */
                    428:        if (*hayespp == 0) {
                    429: #endif
1.64      christos  430:
1.99      mycroft   431:        sc->sc_fifolen = 1;
1.1       cgd       432:        /* look for a NS 16550AF UART with FIFOs */
1.91      thorpej   433:        bus_space_write_1(iot, ioh, com_fifo,
1.21      mycroft   434:            FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_14);
1.20      mycroft   435:        delay(100);
1.99      mycroft   436:        if (ISSET(bus_space_read_1(iot, ioh, com_iir), IIR_FIFO_MASK)
                    437:            == IIR_FIFO_MASK)
                    438:                if (ISSET(bus_space_read_1(iot, ioh, com_fifo), FIFO_TRIGGER_14)
                    439:                    == FIFO_TRIGGER_14) {
1.62      mycroft   440:                        SET(sc->sc_hwflags, COM_HW_FIFO);
1.90      christos  441:                        printf(": ns16550a, working fifo\n");
1.99      mycroft   442:                        sc->sc_fifolen = 16;
1.21      mycroft   443:                } else
1.90      christos  444:                        printf(": ns16550, broken fifo\n");
1.21      mycroft   445:        else
1.90      christos  446:                printf(": ns8250 or ns16450, no fifo\n");
1.91      thorpej   447:        bus_space_write_1(iot, ioh, com_fifo, 0);
1.65      christos  448: #ifdef COM_HAYESP
                    449:        }
                    450: #endif
1.21      mycroft   451:
1.99      mycroft   452:        if (!ISSET(sc->sc_hwflags, COM_HW_NOIEN))
                    453:                SET(sc->sc_mcr, MCR_IENABLE);
1.30      mycroft   454:
1.96      mycroft   455:        if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
1.104     drochner  456: #ifdef DDB
                    457:                com_enable_debugport(sc);
                    458: #endif
1.96      mycroft   459:                printf("%s: console\n", sc->sc_dev.dv_xname);
                    460:        }
                    461:
1.1       cgd       462: #ifdef KGDB
1.102     thorpej   463:        /*
                    464:         * Allow kgdb to "take over" this port.  If this is
                    465:         * the kgdb device, it has exclusive use.
                    466:         */
1.104     drochner  467:        if (iobase == com_kgdb_addr) {
                    468:                SET(sc->sc_hwflags, COM_HW_KGDB);
                    469:                com_enable_debugport(sc);
1.103     drochner  470:                printf("%s: kgdb\n", sc->sc_dev.dv_xname);
                    471:        }
1.99      mycroft   472: #endif
                    473:
                    474: #ifdef __GENERIC_SOFT_INTERRUPTS
                    475:        sc->sc_si = softintr_establish(IPL_SOFTSERIAL, comsoft, sc);
1.1       cgd       476: #endif
                    477: }
                    478:
1.21      mycroft   479: int
                    480: comopen(dev, flag, mode, p)
                    481:        dev_t dev;
                    482:        int flag, mode;
                    483:        struct proc *p;
1.1       cgd       484: {
1.21      mycroft   485:        int unit = COMUNIT(dev);
                    486:        struct com_softc *sc;
                    487:        struct tty *tp;
1.99      mycroft   488:        int s, s2;
1.1       cgd       489:        int error = 0;
                    490:
1.76      thorpej   491:        if (unit >= com_cd.cd_ndevs)
1.99      mycroft   492:                return (ENXIO);
1.76      thorpej   493:        sc = com_cd.cd_devs[unit];
1.29      mycroft   494:        if (!sc)
1.99      mycroft   495:                return (ENXIO);
1.21      mycroft   496:
1.102     thorpej   497: #ifdef KGDB
                    498:        /*
                    499:         * If this is the kgdb port, no other use is permitted.
                    500:         */
                    501:        if (ISSET(sc->sc_hwflags, COM_HW_KGDB))
                    502:                return (EBUSY);
                    503: #endif
                    504:
1.83      cgd       505:        if (!sc->sc_tty) {
1.50      mycroft   506:                tp = sc->sc_tty = ttymalloc();
1.83      cgd       507:                tty_attach(tp);
                    508:        } else
1.50      mycroft   509:                tp = sc->sc_tty;
1.21      mycroft   510:
1.99      mycroft   511:        if (ISSET(tp->t_state, TS_ISOPEN) &&
                    512:            ISSET(tp->t_state, TS_XCLUDE) &&
                    513:            p->p_ucred->cr_uid != 0)
                    514:                return (EBUSY);
                    515:
                    516:        s = spltty();
                    517:
                    518:        /* We need to set this early for the benefit of comsoft(). */
                    519:        SET(tp->t_state, TS_WOPEN);
                    520:
                    521:        /*
                    522:         * Do the following iff this is a first open.
                    523:         */
1.62      mycroft   524:        if (!ISSET(tp->t_state, TS_ISOPEN)) {
1.99      mycroft   525:                struct termios t;
                    526:
                    527:                /* Turn on interrupts. */
                    528:                sc->sc_ier = IER_ERXRDY | IER_ERLS | IER_EMSC;
                    529:                bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_ier, sc->sc_ier);
                    530:
                    531:                /* Fetch the current modem control status, needed later. */
                    532:                sc->sc_msr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, com_msr);
                    533:
                    534:                /* Add some entry points needed by the tty layer. */
                    535:                tp->t_oproc = comstart;
                    536:                tp->t_param = comparam;
                    537:                tp->t_hwiflow = comhwiflow;
                    538:                tp->t_dev = dev;
                    539:
                    540:                /*
                    541:                 * Initialize the termios status to the defaults.  Add in the
                    542:                 * sticky bits from TIOCSFLAGS.
                    543:                 */
                    544:                t.c_ispeed = 0;
1.98      mycroft   545:                if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
1.99      mycroft   546:                        t.c_ospeed = comconsrate;
                    547:                        t.c_cflag = comconscflag;
1.98      mycroft   548:                } else {
1.99      mycroft   549:                        t.c_ospeed = TTYDEF_SPEED;
                    550:                        t.c_cflag = TTYDEF_CFLAG;
1.98      mycroft   551:                }
1.99      mycroft   552:                if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL))
                    553:                        SET(t.c_cflag, CLOCAL);
                    554:                if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS))
                    555:                        SET(t.c_cflag, CRTSCTS);
                    556:                if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF))
                    557:                        SET(t.c_cflag, MDMBUF);
                    558:                tp->t_iflag = TTYDEF_IFLAG;
                    559:                tp->t_oflag = TTYDEF_OFLAG;
1.16      ws        560:                tp->t_lflag = TTYDEF_LFLAG;
1.99      mycroft   561:                ttychars(tp);
                    562:                (void) comparam(tp, &t);
1.1       cgd       563:                ttsetwater(tp);
1.21      mycroft   564:
1.99      mycroft   565:                s2 = splserial();
1.57      mycroft   566:
1.99      mycroft   567:                /*
                    568:                 * Turn on DTR.  We must always do this, even if carrier is not
                    569:                 * present, because otherwise we'd have to use TIOCSDTR
                    570:                 * immediately after setting CLOCAL.  We will drop DTR only on
                    571:                 * the next high-low transition of DCD, or by explicit request.
                    572:                 */
                    573:                com_modem(sc, 1);
1.65      christos  574:
1.99      mycroft   575:                /* Clear the input ring, and unblock. */
                    576:                sc->sc_rbput = sc->sc_rbget = 0;
                    577:                sc->sc_rbavail = RXBUFSIZE;
                    578:                com_iflush(sc);
1.101     mycroft   579:                CLR(sc->sc_rx_flags, RX_ANY_BLOCK);
                    580:                com_hwiflow(sc);
1.65      christos  581:
1.99      mycroft   582: #ifdef COM_DEBUG
1.101     mycroft   583:                if (com_debug)
                    584:                        comstatus(sc, "comopen  ");
1.65      christos  585: #endif
1.21      mycroft   586:
1.99      mycroft   587:                splx(s2);
                    588:        }
                    589:        error = 0;
1.21      mycroft   590:
1.99      mycroft   591:        /* If we're doing a blocking open... */
1.62      mycroft   592:        if (!ISSET(flag, O_NONBLOCK))
1.99      mycroft   593:                /* ...then wait for carrier. */
                    594:                while (!ISSET(tp->t_state, TS_CARR_ON) &&
                    595:                    !ISSET(tp->t_cflag, CLOCAL | MDMBUF)) {
1.62      mycroft   596:                        error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH,
                    597:                            ttopen, 0);
1.21      mycroft   598:                        if (error) {
1.99      mycroft   599:                                /*
                    600:                                 * If the open was interrupted and nobody
                    601:                                 * else has the device open, then hang up.
                    602:                                 */
                    603:                                if (!ISSET(tp->t_state, TS_ISOPEN)) {
                    604:                                        com_modem(sc, 0);
                    605:                                        CLR(tp->t_state, TS_WOPEN);
                    606:                                        ttwakeup(tp);
                    607:                                }
                    608:                                break;
1.21      mycroft   609:                        }
1.99      mycroft   610:                        SET(tp->t_state, TS_WOPEN);
1.21      mycroft   611:                }
1.99      mycroft   612:
1.21      mycroft   613:        splx(s);
1.99      mycroft   614:        if (error == 0)
                    615:                error = (*linesw[tp->t_line].l_open)(dev, tp);
                    616:        return (error);
1.1       cgd       617: }
                    618:
1.21      mycroft   619: int
1.1       cgd       620: comclose(dev, flag, mode, p)
                    621:        dev_t dev;
                    622:        int flag, mode;
                    623:        struct proc *p;
                    624: {
1.21      mycroft   625:        int unit = COMUNIT(dev);
1.76      thorpej   626:        struct com_softc *sc = com_cd.cd_devs[unit];
1.50      mycroft   627:        struct tty *tp = sc->sc_tty;
1.57      mycroft   628:        int s;
                    629:
                    630:        /* XXX This is for cons.c. */
1.62      mycroft   631:        if (!ISSET(tp->t_state, TS_ISOPEN))
1.99      mycroft   632:                return (0);
1.21      mycroft   633:
1.1       cgd       634:        (*linesw[tp->t_line].l_close)(tp, flag);
                    635:        ttyclose(tp);
1.99      mycroft   636:
                    637:        /* If we were asserting flow control, then deassert it. */
1.101     mycroft   638:        SET(sc->sc_rx_flags, RX_IBUF_BLOCKED);
                    639:        com_hwiflow(sc);
1.99      mycroft   640:        /* Clear any break condition set with TIOCSBRK. */
                    641:        com_break(sc, 0);
                    642:        /*
                    643:         * Hang up if necessary.  Wait a bit, so the other side has time to
                    644:         * notice even if we immediately open the port again.
                    645:         */
                    646:        if (ISSET(tp->t_cflag, HUPCL)) {
                    647:                com_modem(sc, 0);
                    648:                (void) tsleep(sc, TTIPRI, ttclos, hz);
1.21      mycroft   649:        }
1.99      mycroft   650:
                    651:        s = splserial();
                    652:        /* Turn off interrupts. */
1.104     drochner  653: #ifdef DDB
                    654:        if(ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
                    655:                sc->sc_ier = IER_ERXRDY; /* interrupt on break */
                    656:        else
                    657: #else
                    658:                sc->sc_ier = 0;
                    659: #endif
1.99      mycroft   660:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_ier, sc->sc_ier);
                    661:        splx(s);
                    662:
                    663:        return (0);
1.1       cgd       664: }
                    665:
1.21      mycroft   666: int
1.1       cgd       667: comread(dev, uio, flag)
                    668:        dev_t dev;
                    669:        struct uio *uio;
1.21      mycroft   670:        int flag;
1.1       cgd       671: {
1.76      thorpej   672:        struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
1.52      mycroft   673:        struct tty *tp = sc->sc_tty;
1.1       cgd       674:
                    675:        return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
                    676: }
                    677:
1.21      mycroft   678: int
1.1       cgd       679: comwrite(dev, uio, flag)
                    680:        dev_t dev;
                    681:        struct uio *uio;
1.21      mycroft   682:        int flag;
1.1       cgd       683: {
1.76      thorpej   684:        struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
1.52      mycroft   685:        struct tty *tp = sc->sc_tty;
1.1       cgd       686:
                    687:        return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
                    688: }
1.50      mycroft   689:
                    690: struct tty *
                    691: comtty(dev)
                    692:        dev_t dev;
                    693: {
1.76      thorpej   694:        struct com_softc *sc = com_cd.cd_devs[COMUNIT(dev)];
1.52      mycroft   695:        struct tty *tp = sc->sc_tty;
1.50      mycroft   696:
1.52      mycroft   697:        return (tp);
1.50      mycroft   698: }
1.1       cgd       699:
1.21      mycroft   700: int
1.19      mycroft   701: comioctl(dev, cmd, data, flag, p)
1.1       cgd       702:        dev_t dev;
1.39      cgd       703:        u_long cmd;
1.1       cgd       704:        caddr_t data;
1.19      mycroft   705:        int flag;
                    706:        struct proc *p;
1.1       cgd       707: {
1.21      mycroft   708:        int unit = COMUNIT(dev);
1.76      thorpej   709:        struct com_softc *sc = com_cd.cd_devs[unit];
1.50      mycroft   710:        struct tty *tp = sc->sc_tty;
1.21      mycroft   711:        int error;
                    712:
1.19      mycroft   713:        error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
1.1       cgd       714:        if (error >= 0)
1.99      mycroft   715:                return (error);
                    716:
1.19      mycroft   717:        error = ttioctl(tp, cmd, data, flag, p);
1.1       cgd       718:        if (error >= 0)
1.99      mycroft   719:                return (error);
1.1       cgd       720:
                    721:        switch (cmd) {
                    722:        case TIOCSBRK:
1.99      mycroft   723:                com_break(sc, 1);
1.1       cgd       724:                break;
1.99      mycroft   725:
1.1       cgd       726:        case TIOCCBRK:
1.99      mycroft   727:                com_break(sc, 0);
1.1       cgd       728:                break;
1.99      mycroft   729:
1.1       cgd       730:        case TIOCSDTR:
1.99      mycroft   731:                com_modem(sc, 1);
1.1       cgd       732:                break;
1.99      mycroft   733:
1.1       cgd       734:        case TIOCCDTR:
1.99      mycroft   735:                com_modem(sc, 0);
1.1       cgd       736:                break;
1.99      mycroft   737:
                    738:        case TIOCGFLAGS:
                    739:                *(int *)data = sc->sc_swflags;
                    740:                break;
                    741:
                    742:        case TIOCSFLAGS:
                    743:                error = suser(p->p_ucred, &p->p_acflag);
                    744:                if (error)
                    745:                        return (error);
                    746:                sc->sc_swflags = *(int *)data;
                    747:                break;
                    748:
1.1       cgd       749:        case TIOCMSET:
                    750:        case TIOCMBIS:
                    751:        case TIOCMBIC:
1.99      mycroft   752:        case TIOCMGET:
                    753:        default:
                    754:                return (ENOTTY);
1.21      mycroft   755:        }
1.22      cgd       756:
1.99      mycroft   757: #ifdef COM_DEBUG
1.101     mycroft   758:        if (com_debug)
1.99      mycroft   759:                comstatus(sc, "comioctl ");
                    760: #endif
                    761:
                    762:        return (0);
                    763: }
                    764:
1.101     mycroft   765: integrate void
                    766: com_schedrx(sc)
                    767:        struct com_softc *sc;
                    768: {
                    769:
                    770:        sc->sc_rx_ready = 1;
                    771:
                    772:        /* Wake up the poller. */
                    773: #ifdef __GENERIC_SOFT_INTERRUPTS
                    774:        softintr_schedule(sc->sc_si);
                    775: #else
                    776: #ifndef alpha
                    777:        setsoftserial();
                    778: #else
                    779:        if (!com_softintr_scheduled) {
                    780:                com_softintr_scheduled = 1;
                    781:                timeout(comsoft, NULL, 1);
                    782:        }
                    783: #endif
                    784: #endif
                    785: }
                    786:
1.99      mycroft   787: void
                    788: com_break(sc, onoff)
                    789:        struct com_softc *sc;
                    790:        int onoff;
                    791: {
                    792:        int s;
                    793:
                    794:        s = splserial();
                    795:        if (onoff)
                    796:                SET(sc->sc_lcr, LCR_SBREAK);
                    797:        else
                    798:                CLR(sc->sc_lcr, LCR_SBREAK);
1.22      cgd       799:
1.99      mycroft   800:        if (!sc->sc_heldchange) {
                    801:                if (sc->sc_tx_busy) {
                    802:                        sc->sc_heldtbc = sc->sc_tbc;
                    803:                        sc->sc_tbc = 0;
                    804:                        sc->sc_heldchange = 1;
                    805:                } else
                    806:                        com_loadchannelregs(sc);
1.22      cgd       807:        }
1.99      mycroft   808:        splx(s);
                    809: }
1.22      cgd       810:
1.99      mycroft   811: void
                    812: com_modem(sc, onoff)
                    813:        struct com_softc *sc;
                    814:        int onoff;
                    815: {
                    816:        int s;
1.22      cgd       817:
1.99      mycroft   818:        s = splserial();
                    819:        if (onoff)
                    820:                SET(sc->sc_mcr, sc->sc_mcr_dtr);
                    821:        else
                    822:                CLR(sc->sc_mcr, sc->sc_mcr_dtr);
1.22      cgd       823:
1.99      mycroft   824:        if (!sc->sc_heldchange) {
                    825:                if (sc->sc_tx_busy) {
                    826:                        sc->sc_heldtbc = sc->sc_tbc;
                    827:                        sc->sc_tbc = 0;
                    828:                        sc->sc_heldchange = 1;
                    829:                } else
                    830:                        com_loadchannelregs(sc);
1.22      cgd       831:        }
1.99      mycroft   832:        splx(s);
1.1       cgd       833: }
                    834:
1.21      mycroft   835: int
1.1       cgd       836: comparam(tp, t)
1.21      mycroft   837:        struct tty *tp;
                    838:        struct termios *t;
1.1       cgd       839: {
1.76      thorpej   840:        struct com_softc *sc = com_cd.cd_devs[COMUNIT(tp->t_dev)];
1.21      mycroft   841:        int ospeed = comspeed(t->c_ospeed);
1.62      mycroft   842:        u_char lcr;
1.21      mycroft   843:        int s;
                    844:
1.1       cgd       845:        /* check requested parameters */
1.99      mycroft   846:        if (ospeed < 0)
                    847:                return (EINVAL);
                    848:        if (t->c_ispeed && t->c_ispeed != t->c_ospeed)
                    849:                return (EINVAL);
1.21      mycroft   850:
1.66      mycroft   851:        lcr = ISSET(sc->sc_lcr, LCR_SBREAK);
1.62      mycroft   852:
                    853:        switch (ISSET(t->c_cflag, CSIZE)) {
1.1       cgd       854:        case CS5:
1.62      mycroft   855:                SET(lcr, LCR_5BITS);
1.21      mycroft   856:                break;
1.1       cgd       857:        case CS6:
1.62      mycroft   858:                SET(lcr, LCR_6BITS);
1.21      mycroft   859:                break;
1.1       cgd       860:        case CS7:
1.62      mycroft   861:                SET(lcr, LCR_7BITS);
1.21      mycroft   862:                break;
1.1       cgd       863:        case CS8:
1.62      mycroft   864:                SET(lcr, LCR_8BITS);
1.21      mycroft   865:                break;
1.1       cgd       866:        }
1.62      mycroft   867:        if (ISSET(t->c_cflag, PARENB)) {
                    868:                SET(lcr, LCR_PENAB);
                    869:                if (!ISSET(t->c_cflag, PARODD))
                    870:                        SET(lcr, LCR_PEVEN);
1.1       cgd       871:        }
1.62      mycroft   872:        if (ISSET(t->c_cflag, CSTOPB))
                    873:                SET(lcr, LCR_STOPB);
                    874:
1.99      mycroft   875:        s = splserial();
                    876:
1.62      mycroft   877:        sc->sc_lcr = lcr;
1.1       cgd       878:
1.99      mycroft   879:        /*
                    880:         * For the console, always force CLOCAL and !HUPCL, so that the port
                    881:         * is always active.
                    882:         */
                    883:        if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) ||
                    884:            ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
                    885:                SET(t->c_cflag, CLOCAL);
                    886:                CLR(t->c_cflag, HUPCL);
1.62      mycroft   887:        }
1.36      mycroft   888:
                    889:        /*
1.99      mycroft   890:         * If we're not in a mode that assumes a connection is present, then
                    891:         * ignore carrier changes.
1.36      mycroft   892:         */
1.99      mycroft   893:        if (ISSET(t->c_cflag, CLOCAL | MDMBUF))
                    894:                sc->sc_msr_dcd = 0;
                    895:        else
                    896:                sc->sc_msr_dcd = MSR_DCD;
                    897:        /*
                    898:         * Set the flow control pins depending on the current flow control
                    899:         * mode.
                    900:         */
                    901:        if (ISSET(t->c_cflag, CRTSCTS)) {
                    902:                sc->sc_mcr_dtr = MCR_DTR;
                    903:                sc->sc_mcr_rts = MCR_RTS;
                    904:                sc->sc_msr_cts = MSR_CTS;
                    905:                sc->sc_r_hiwat = RXHIWAT;
1.101     mycroft   906:                sc->sc_r_lowat = RXLOWAT;
1.99      mycroft   907:        } else if (ISSET(t->c_cflag, MDMBUF)) {
                    908:                /*
                    909:                 * For DTR/DCD flow control, make sure we don't toggle DTR for
                    910:                 * carrier detection.
                    911:                 */
                    912:                sc->sc_mcr_dtr = 0;
                    913:                sc->sc_mcr_rts = MCR_DTR;
                    914:                sc->sc_msr_cts = MSR_DCD;
                    915:                sc->sc_r_hiwat = RXHIWAT;
1.101     mycroft   916:                sc->sc_r_lowat = RXLOWAT;
1.99      mycroft   917:        } else {
                    918:                /*
                    919:                 * If no flow control, then always set RTS.  This will make
                    920:                 * the other side happy if it mistakenly thinks we're doing
                    921:                 * RTS/CTS flow control.
                    922:                 */
                    923:                sc->sc_mcr_dtr = MCR_DTR | MCR_RTS;
                    924:                sc->sc_mcr_rts = 0;
                    925:                sc->sc_msr_cts = 0;
                    926:                sc->sc_r_hiwat = 0;
1.101     mycroft   927:                sc->sc_r_lowat = 0;
1.99      mycroft   928:                if (ISSET(sc->sc_mcr, MCR_DTR))
                    929:                        SET(sc->sc_mcr, MCR_RTS);
                    930:                else
                    931:                        CLR(sc->sc_mcr, MCR_RTS);
                    932:        }
                    933:        sc->sc_msr_mask = sc->sc_msr_cts | sc->sc_msr_dcd;
                    934:
1.95      mycroft   935: #if 0
1.99      mycroft   936:        if (ospeed == 0)
                    937:                CLR(sc->sc_mcr, sc->sc_mcr_dtr);
                    938:        else
                    939:                SET(sc->sc_mcr, sc->sc_mcr_dtr);
1.66      mycroft   940: #endif
                    941:
1.99      mycroft   942:        sc->sc_dlbl = ospeed;
                    943:        sc->sc_dlbh = ospeed >> 8;
1.66      mycroft   944:
1.99      mycroft   945:        /*
                    946:         * Set the FIFO threshold based on the receive speed.
                    947:         *
                    948:         *  * If it's a low speed, it's probably a mouse or some other
                    949:         *    interactive device, so set the threshold low.
                    950:         *  * If it's a high speed, trim the trigger level down to prevent
                    951:         *    overflows.
                    952:         *  * Otherwise set it a bit higher.
                    953:         */
                    954:        if (ISSET(sc->sc_hwflags, COM_HW_HAYESP))
                    955:                sc->sc_fifo = FIFO_DMA_MODE | FIFO_ENABLE | FIFO_TRIGGER_8;
                    956:        else if (ISSET(sc->sc_hwflags, COM_HW_FIFO))
                    957:                sc->sc_fifo = FIFO_ENABLE |
                    958:                    (t->c_ospeed <= 1200 ? FIFO_TRIGGER_1 :
                    959:                     t->c_ospeed <= 38400 ? FIFO_TRIGGER_8 : FIFO_TRIGGER_4);
                    960:        else
                    961:                sc->sc_fifo = 0;
1.21      mycroft   962:
1.57      mycroft   963:        /* and copy to tty */
1.99      mycroft   964:        tp->t_ispeed = 0;
1.57      mycroft   965:        tp->t_ospeed = t->c_ospeed;
                    966:        tp->t_cflag = t->c_cflag;
1.25      cgd       967:
1.99      mycroft   968:        if (!sc->sc_heldchange) {
                    969:                if (sc->sc_tx_busy) {
                    970:                        sc->sc_heldtbc = sc->sc_tbc;
                    971:                        sc->sc_tbc = 0;
                    972:                        sc->sc_heldchange = 1;
                    973:                } else
                    974:                        com_loadchannelregs(sc);
                    975:        }
                    976:
                    977:        splx(s);
                    978:
1.25      cgd       979:        /*
1.99      mycroft   980:         * Update the tty layer's idea of the carrier bit, in case we changed
                    981:         * CLOCAL or MDMBUF.  We don't hang up here; we only do that if we
                    982:         * lose carrier while carrier detection is on.
1.25      cgd       983:         */
1.99      mycroft   984:        (void) (*linesw[tp->t_line].l_modem)(tp, ISSET(sc->sc_msr, MSR_DCD));
                    985:
                    986: #ifdef COM_DEBUG
1.101     mycroft   987:        if (com_debug)
                    988:                comstatus(sc, "comparam ");
1.99      mycroft   989: #endif
                    990:
                    991:        /* Block or unblock as needed. */
                    992:        if (!ISSET(t->c_cflag, CHWFLOW)) {
1.101     mycroft   993:                if (ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) {
                    994:                        CLR(sc->sc_rx_flags, RX_TTY_OVERFLOWED);
                    995:                        com_schedrx(sc);
                    996:                }
                    997:                if (ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED)) {
                    998:                        CLR(sc->sc_rx_flags, RX_TTY_BLOCKED|RX_IBUF_BLOCKED);
                    999:                        com_hwiflow(sc);
1.99      mycroft  1000:                }
                   1001:                if (sc->sc_tx_stopped) {
                   1002:                        sc->sc_tx_stopped = 0;
                   1003:                        comstart(tp);
                   1004:                }
                   1005:        } else {
1.101     mycroft  1006:                /* XXXXX FIX ME */
1.99      mycroft  1007: #if 0
                   1008:                commsrint(sc, tp);
                   1009: #endif
1.21      mycroft  1010:        }
1.1       cgd      1011:
1.99      mycroft  1012:        return (0);
                   1013: }
                   1014:
                   1015: void
                   1016: com_iflush(sc)
                   1017:        struct com_softc *sc;
                   1018: {
                   1019:        bus_space_tag_t iot = sc->sc_iot;
                   1020:        bus_space_handle_t ioh = sc->sc_ioh;
                   1021:
                   1022:        /* flush any pending I/O */
                   1023:        while (ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY))
                   1024:                (void) bus_space_read_1(iot, ioh, com_data);
                   1025: }
                   1026:
                   1027: void
                   1028: com_loadchannelregs(sc)
                   1029:        struct com_softc *sc;
                   1030: {
                   1031:        bus_space_tag_t iot = sc->sc_iot;
                   1032:        bus_space_handle_t ioh = sc->sc_ioh;
                   1033:
                   1034:        /* XXXXX necessary? */
                   1035:        com_iflush(sc);
                   1036:
                   1037:        bus_space_write_1(iot, ioh, com_ier, 0);
                   1038:
                   1039:        bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr | LCR_DLAB);
                   1040:        bus_space_write_1(iot, ioh, com_dlbl, sc->sc_dlbl);
                   1041:        bus_space_write_1(iot, ioh, com_dlbh, sc->sc_dlbh);
                   1042:        bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr);
                   1043:        bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr_active = sc->sc_mcr);
                   1044:        bus_space_write_1(iot, ioh, com_fifo, sc->sc_fifo);
                   1045:
                   1046:        bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
                   1047: }
                   1048:
                   1049: int
                   1050: comhwiflow(tp, block)
                   1051:        struct tty *tp;
                   1052:        int block;
                   1053: {
                   1054:        struct com_softc *sc = com_cd.cd_devs[COMUNIT(tp->t_dev)];
                   1055:        int s;
                   1056:
                   1057:        if (sc->sc_mcr_rts == 0)
                   1058:                return (0);
                   1059:
                   1060:        s = splserial();
                   1061:        if (block) {
1.101     mycroft  1062:                if (!ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) {
                   1063:                        SET(sc->sc_rx_flags, RX_TTY_BLOCKED);
                   1064:                        com_hwiflow(sc);
                   1065:                }
1.99      mycroft  1066:        } else {
1.101     mycroft  1067:                if (ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) {
                   1068:                        CLR(sc->sc_rx_flags, RX_TTY_OVERFLOWED);
                   1069:                        com_schedrx(sc);
                   1070:                }
                   1071:                if (ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) {
                   1072:                        CLR(sc->sc_rx_flags, RX_TTY_BLOCKED);
                   1073:                        com_hwiflow(sc);
                   1074:                }
1.99      mycroft  1075:        }
1.21      mycroft  1076:        splx(s);
1.99      mycroft  1077:        return (1);
                   1078: }
                   1079:
                   1080: /*
                   1081:  * (un)block input via hw flowcontrol
                   1082:  */
                   1083: void
1.101     mycroft  1084: com_hwiflow(sc)
1.99      mycroft  1085:        struct com_softc *sc;
                   1086: {
                   1087:        bus_space_tag_t iot = sc->sc_iot;
                   1088:        bus_space_handle_t ioh = sc->sc_ioh;
                   1089:
                   1090:        if (sc->sc_mcr_rts == 0)
                   1091:                return;
                   1092:
1.101     mycroft  1093:        if (ISSET(sc->sc_rx_flags, RX_ANY_BLOCK)) {
1.99      mycroft  1094:                CLR(sc->sc_mcr, sc->sc_mcr_rts);
                   1095:                CLR(sc->sc_mcr_active, sc->sc_mcr_rts);
                   1096:        } else {
                   1097:                SET(sc->sc_mcr, sc->sc_mcr_rts);
                   1098:                SET(sc->sc_mcr_active, sc->sc_mcr_rts);
                   1099:        }
                   1100:        bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr_active);
1.1       cgd      1101: }
1.21      mycroft  1102:
1.99      mycroft  1103:
1.12      deraadt  1104: void
1.1       cgd      1105: comstart(tp)
1.21      mycroft  1106:        struct tty *tp;
1.1       cgd      1107: {
1.76      thorpej  1108:        struct com_softc *sc = com_cd.cd_devs[COMUNIT(tp->t_dev)];
1.91      thorpej  1109:        bus_space_tag_t iot = sc->sc_iot;
                   1110:        bus_space_handle_t ioh = sc->sc_ioh;
1.21      mycroft  1111:        int s;
                   1112:
1.1       cgd      1113:        s = spltty();
1.69      mycroft  1114:        if (ISSET(tp->t_state, TS_BUSY))
1.70      mycroft  1115:                goto out;
1.99      mycroft  1116:        if (ISSET(tp->t_state, TS_TIMEOUT | TS_TTSTOP))
1.69      mycroft  1117:                goto stopped;
1.99      mycroft  1118:
                   1119:        if (sc->sc_tx_stopped)
1.69      mycroft  1120:                goto stopped;
1.99      mycroft  1121:
1.61      mycroft  1122:        if (tp->t_outq.c_cc <= tp->t_lowat) {
1.62      mycroft  1123:                if (ISSET(tp->t_state, TS_ASLEEP)) {
                   1124:                        CLR(tp->t_state, TS_ASLEEP);
                   1125:                        wakeup(&tp->t_outq);
1.61      mycroft  1126:                }
1.99      mycroft  1127:                selwakeup(&tp->t_wsel);
1.61      mycroft  1128:                if (tp->t_outq.c_cc == 0)
1.69      mycroft  1129:                        goto stopped;
1.61      mycroft  1130:        }
1.99      mycroft  1131:
                   1132:        /* Grab the first contiguous region of buffer space. */
                   1133:        {
                   1134:                u_char *tba;
                   1135:                int tbc;
                   1136:
                   1137:                tba = tp->t_outq.c_cf;
                   1138:                tbc = ndqb(&tp->t_outq, 0);
                   1139:
                   1140:                (void)splserial();
                   1141:
                   1142:                sc->sc_tba = tba;
                   1143:                sc->sc_tbc = tbc;
                   1144:        }
                   1145:
1.62      mycroft  1146:        SET(tp->t_state, TS_BUSY);
1.99      mycroft  1147:        sc->sc_tx_busy = 1;
1.64      christos 1148:
1.99      mycroft  1149:        /* Enable transmit completion interrupts if necessary. */
1.70      mycroft  1150:        if (!ISSET(sc->sc_ier, IER_ETXRDY)) {
                   1151:                SET(sc->sc_ier, IER_ETXRDY);
1.91      thorpej  1152:                bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
1.70      mycroft  1153:        }
1.99      mycroft  1154:
                   1155:        /* Output the first chunk of the contiguous buffer. */
                   1156:        {
                   1157:                int n;
                   1158:
                   1159:                n = sc->sc_fifolen;
                   1160:                if (n > sc->sc_tbc)
                   1161:                        n = sc->sc_tbc;
                   1162:                bus_space_write_multi_1(iot, ioh, com_data, sc->sc_tba, n);
                   1163:                sc->sc_tbc -= n;
                   1164:                sc->sc_tba += n;
1.64      christos 1165:        }
1.69      mycroft  1166:        splx(s);
                   1167:        return;
1.99      mycroft  1168:
1.69      mycroft  1169: stopped:
1.99      mycroft  1170:        /* Disable transmit completion interrupts if necessary. */
1.69      mycroft  1171:        if (ISSET(sc->sc_ier, IER_ETXRDY)) {
                   1172:                CLR(sc->sc_ier, IER_ETXRDY);
1.91      thorpej  1173:                bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
1.69      mycroft  1174:        }
1.99      mycroft  1175: out:
1.1       cgd      1176:        splx(s);
1.99      mycroft  1177:        return;
1.1       cgd      1178: }
1.21      mycroft  1179:
1.1       cgd      1180: /*
                   1181:  * Stop output on a line.
                   1182:  */
1.85      mycroft  1183: void
1.1       cgd      1184: comstop(tp, flag)
1.21      mycroft  1185:        struct tty *tp;
1.80      christos 1186:        int flag;
1.1       cgd      1187: {
1.99      mycroft  1188:        struct com_softc *sc = com_cd.cd_devs[COMUNIT(tp->t_dev)];
1.21      mycroft  1189:        int s;
1.1       cgd      1190:
1.99      mycroft  1191:        s = splserial();
                   1192:        if (ISSET(tp->t_state, TS_BUSY)) {
                   1193:                /* Stop transmitting at the next chunk. */
                   1194:                sc->sc_tbc = 0;
                   1195:                sc->sc_heldtbc = 0;
1.62      mycroft  1196:                if (!ISSET(tp->t_state, TS_TTSTOP))
                   1197:                        SET(tp->t_state, TS_FLUSH);
1.99      mycroft  1198:        }
1.1       cgd      1199:        splx(s);
                   1200: }
                   1201:
1.33      mycroft  1202: void
                   1203: comdiag(arg)
                   1204:        void *arg;
                   1205: {
                   1206:        struct com_softc *sc = arg;
1.99      mycroft  1207:        int overflows, floods;
1.33      mycroft  1208:        int s;
                   1209:
1.99      mycroft  1210:        s = splserial();
1.33      mycroft  1211:        overflows = sc->sc_overflows;
                   1212:        sc->sc_overflows = 0;
1.57      mycroft  1213:        floods = sc->sc_floods;
                   1214:        sc->sc_floods = 0;
1.99      mycroft  1215:        sc->sc_errors = 0;
1.57      mycroft  1216:        splx(s);
                   1217:
1.99      mycroft  1218:        log(LOG_WARNING,
                   1219:            "%s: %d silo overflow%s, %d ibuf flood%s\n",
1.57      mycroft  1220:            sc->sc_dev.dv_xname,
                   1221:            overflows, overflows == 1 ? "" : "s",
1.99      mycroft  1222:            floods, floods == 1 ? "" : "s");
1.57      mycroft  1223: }
                   1224:
1.99      mycroft  1225: integrate void
                   1226: comrxint(sc, tp)
                   1227:        struct com_softc        *sc;
                   1228:        struct tty      *tp;
                   1229: {
                   1230:        u_int   get, cc, scc;
                   1231:        int     code;
                   1232:        u_char  lsr;
                   1233:        int     s;
1.57      mycroft  1234:        static int lsrmap[8] = {
                   1235:                0,      TTY_PE,
                   1236:                TTY_FE, TTY_PE|TTY_FE,
                   1237:                TTY_FE, TTY_PE|TTY_FE,
                   1238:                TTY_FE, TTY_PE|TTY_FE
                   1239:        };
                   1240:
1.99      mycroft  1241:        get = sc->sc_rbget;
                   1242:        scc = cc = RXBUFSIZE - sc->sc_rbavail;
                   1243:
                   1244:        if (cc == RXBUFSIZE) {
                   1245:                sc->sc_floods++;
                   1246:                if (sc->sc_errors++ == 0)
                   1247:                        timeout(comdiag, sc, 60 * hz);
                   1248:        }
                   1249:
1.101     mycroft  1250:        while (cc) {
1.99      mycroft  1251:                lsr = sc->sc_lbuf[get];
1.103     drochner 1252:                if (ISSET(lsr, LSR_OE)) {
1.99      mycroft  1253:                        sc->sc_overflows++;
                   1254:                        if (sc->sc_errors++ == 0)
                   1255:                                timeout(comdiag, sc, 60 * hz);
                   1256:                }
                   1257:                code = sc->sc_rbuf[get] |
                   1258:                    lsrmap[(lsr & (LSR_BI|LSR_FE|LSR_PE)) >> 2];
1.101     mycroft  1259:                if ((*linesw[tp->t_line].l_rint)(code, tp) == -1) {
                   1260:                        /*
                   1261:                         * The line discipline's buffer is out of space.
                   1262:                         */
                   1263:                        if (!ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) {
                   1264:                                /*
                   1265:                                 * We're either not using flow control, or the
                   1266:                                 * line discipline didn't tell us to block for
                   1267:                                 * some reason.  Either way, we have no way to
                   1268:                                 * know when there's more space available, so
                   1269:                                 * just drop the rest of the data.
                   1270:                                 */
                   1271:                                get = (get + cc) & RXBUFMASK;
                   1272:                                cc = 0;
                   1273:                        } else {
                   1274:                                /*
                   1275:                                 * Don't schedule any more receive processing
                   1276:                                 * until the line discipline tells us there's
                   1277:                                 * space available (through comhwiflow()).
                   1278:                                 * Leave the rest of the data in the input
                   1279:                                 * buffer.
                   1280:                                 */
                   1281:                                SET(sc->sc_rx_flags, RX_TTY_OVERFLOWED);
                   1282:                        }
                   1283:                        break;
                   1284:                }
1.99      mycroft  1285:                get = (get + 1) & RXBUFMASK;
1.101     mycroft  1286:                cc--;
1.99      mycroft  1287:        }
                   1288:
1.101     mycroft  1289:        if (cc != scc) {
                   1290:                sc->sc_rbget = get;
                   1291:                s = splserial();
                   1292:                cc = sc->sc_rbavail += scc - cc;
                   1293:                /* Buffers should be ok again, release possible block. */
                   1294:                if (cc >= sc->sc_r_lowat) {
                   1295:                        if (ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) {
                   1296:                                CLR(sc->sc_rx_flags, RX_IBUF_OVERFLOWED);
                   1297:                                SET(sc->sc_ier, IER_ERXRDY);
                   1298:                                bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_ier, sc->sc_ier);
                   1299:                        }
                   1300:                        if (ISSET(sc->sc_rx_flags, RX_IBUF_BLOCKED)) {
                   1301:                                CLR(sc->sc_rx_flags, RX_IBUF_BLOCKED);
                   1302:                                com_hwiflow(sc);
                   1303:                        }
                   1304:                }
                   1305:                splx(s);
1.57      mycroft  1306:        }
1.99      mycroft  1307: }
                   1308:
                   1309: integrate void
                   1310: comtxint(sc, tp)
                   1311:        struct com_softc        *sc;
                   1312:        struct tty      *tp;
                   1313: {
1.33      mycroft  1314:
1.99      mycroft  1315:        CLR(tp->t_state, TS_BUSY);
                   1316:        if (ISSET(tp->t_state, TS_FLUSH))
                   1317:                CLR(tp->t_state, TS_FLUSH);
                   1318:        else
                   1319:                ndflush(&tp->t_outq, (int)(sc->sc_tba - tp->t_outq.c_cf));
                   1320:        (*linesw[tp->t_line].l_start)(tp);
                   1321: }
1.57      mycroft  1322:
1.99      mycroft  1323: integrate void
                   1324: commsrint(sc, tp)
                   1325:        struct com_softc        *sc;
                   1326:        struct tty      *tp;
                   1327: {
                   1328:        u_char msr, delta;
                   1329:        int s;
1.57      mycroft  1330:
1.99      mycroft  1331:        s = splserial();
                   1332:        msr = sc->sc_msr;
                   1333:        delta = sc->sc_msr_delta;
                   1334:        sc->sc_msr_delta = 0;
                   1335:        splx(s);
1.57      mycroft  1336:
1.99      mycroft  1337:        if (ISSET(delta, sc->sc_msr_dcd)) {
                   1338:                /*
                   1339:                 * Inform the tty layer that carrier detect changed.
                   1340:                 */
                   1341:                (void) (*linesw[tp->t_line].l_modem)(tp, ISSET(msr, MSR_DCD));
                   1342:        }
1.61      mycroft  1343:
1.99      mycroft  1344:        if (ISSET(delta, sc->sc_msr_cts)) {
                   1345:                /* Block or unblock output according to flow control. */
                   1346:                if (ISSET(msr, sc->sc_msr_cts)) {
                   1347:                        sc->sc_tx_stopped = 0;
                   1348:                        (*linesw[tp->t_line].l_start)(tp);
                   1349:                } else {
                   1350:                        sc->sc_tx_stopped = 1;
1.61      mycroft  1351:                }
1.99      mycroft  1352:        }
                   1353:
                   1354: #ifdef COM_DEBUG
1.101     mycroft  1355:        if (com_debug)
                   1356:                comstatus(sc, "commsrint");
1.99      mycroft  1357: #endif
                   1358: }
                   1359:
                   1360: #ifdef __GENERIC_SOFT_INTERRUPTS
                   1361: void
                   1362: comsoft(arg)
                   1363:        void *arg;
                   1364: {
                   1365:        struct com_softc *sc = arg;
                   1366:        struct tty *tp;
                   1367:
                   1368:        {
                   1369: #else
                   1370: void
                   1371: #ifndef alpha
                   1372: comsoft()
                   1373: #else
                   1374: comsoft(arg)
                   1375:        void *arg;
                   1376: #endif
                   1377: {
                   1378:        struct com_softc        *sc;
                   1379:        struct tty      *tp;
                   1380:        int     unit;
                   1381: #ifdef alpha
                   1382:        int s;
                   1383:
                   1384:        s = splsoftserial();
                   1385:        com_softintr_scheduled = 0;
                   1386: #endif
1.57      mycroft  1387:
1.99      mycroft  1388:        for (unit = 0; unit < com_cd.cd_ndevs; unit++) {
                   1389:                sc = com_cd.cd_devs[unit];
                   1390:                if (sc == NULL)
                   1391:                        continue;
                   1392: #endif
1.57      mycroft  1393:
1.99      mycroft  1394:                tp = sc->sc_tty;
                   1395:                if (tp == NULL || !ISSET(tp->t_state, TS_ISOPEN | TS_WOPEN))
1.57      mycroft  1396:                        continue;
1.99      mycroft  1397:
                   1398:                if (sc->sc_rx_ready) {
                   1399:                        sc->sc_rx_ready = 0;
                   1400:                        comrxint(sc, tp);
1.57      mycroft  1401:                }
                   1402:
1.99      mycroft  1403:                if (sc->sc_st_check) {
                   1404:                        sc->sc_st_check = 0;
                   1405:                        commsrint(sc, tp);
1.62      mycroft  1406:                }
1.57      mycroft  1407:
1.99      mycroft  1408:                if (sc->sc_tx_done) {
                   1409:                        sc->sc_tx_done = 0;
                   1410:                        comtxint(sc, tp);
1.57      mycroft  1411:                }
                   1412:        }
                   1413:
1.99      mycroft  1414: #ifndef __GENERIC_SOFT_INTERRUPTS
                   1415: #ifdef alpha
                   1416:        splx(s);
                   1417: #endif
                   1418: #endif
1.21      mycroft  1419: }
1.1       cgd      1420:
1.21      mycroft  1421: int
1.49      cgd      1422: comintr(arg)
1.99      mycroft  1423:        void    *arg;
1.21      mycroft  1424: {
1.49      cgd      1425:        struct com_softc *sc = arg;
1.91      thorpej  1426:        bus_space_tag_t iot = sc->sc_iot;
                   1427:        bus_space_handle_t ioh = sc->sc_ioh;
1.99      mycroft  1428:        u_char  lsr, iir;
                   1429:        u_int   put, cc;
1.55      mycroft  1430:
1.91      thorpej  1431:        iir = bus_space_read_1(iot, ioh, com_iir);
1.88      mycroft  1432:        if (ISSET(iir, IIR_NOPEND))
1.55      mycroft  1433:                return (0);
1.21      mycroft  1434:
1.99      mycroft  1435:        put = sc->sc_rbput;
                   1436:        cc = sc->sc_rbavail;
                   1437:
                   1438:        do {
                   1439:                u_char  msr, delta;
1.21      mycroft  1440:
1.91      thorpej  1441:                lsr = bus_space_read_1(iot, ioh, com_lsr);
1.103     drochner 1442: #if defined(DDB) || defined(KGDB)
                   1443:                if (ISSET(lsr, LSR_BI)) {
                   1444: #ifdef DDB
                   1445:                        if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
                   1446:                                Debugger();
                   1447:                                continue;
                   1448:                        }
                   1449: #endif
                   1450: #ifdef KGDB
                   1451:                        if (ISSET(sc->sc_hwflags, COM_HW_KGDB)) {
                   1452:                                kgdb_connect(1);
                   1453:                                continue;
                   1454:                        }
                   1455: #endif
1.102     thorpej  1456:                }
1.103     drochner 1457: #endif /* DDB || KGDB */
1.102     thorpej  1458:
1.101     mycroft  1459:                if (ISSET(lsr, LSR_RCV_MASK) &&
                   1460:                    !ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) {
1.99      mycroft  1461:                        for (; ISSET(lsr, LSR_RCV_MASK) && cc > 0; cc--) {
                   1462:                                sc->sc_rbuf[put] =
                   1463:                                    bus_space_read_1(iot, ioh, com_data);
                   1464:                                sc->sc_lbuf[put] = lsr;
                   1465:                                put = (put + 1) & RXBUFMASK;
                   1466:                                lsr = bus_space_read_1(iot, ioh, com_lsr);
                   1467:                        }
                   1468:                        /*
                   1469:                         * Current string of incoming characters ended because
                   1470:                         * no more data was available. Schedule a receive event
                   1471:                         * if any data was received. Drop any characters that
                   1472:                         * we couldn't handle.
                   1473:                         */
                   1474:                        sc->sc_rbput = put;
                   1475:                        sc->sc_rbavail = cc;
1.101     mycroft  1476:                        if (!ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED))
                   1477:                                sc->sc_rx_ready = 1;
1.99      mycroft  1478:                        /*
                   1479:                         * See if we are in danger of overflowing a buffer. If
                   1480:                         * so, use hardware flow control to ease the pressure.
                   1481:                         */
1.101     mycroft  1482:                        if (!ISSET(sc->sc_rx_flags, RX_IBUF_BLOCKED) &&
1.99      mycroft  1483:                            cc < sc->sc_r_hiwat) {
1.101     mycroft  1484:                                SET(sc->sc_rx_flags, RX_IBUF_BLOCKED);
                   1485:                                com_hwiflow(sc);
1.99      mycroft  1486:                        }
                   1487:                        /*
1.101     mycroft  1488:                         * If we're out of space, disable receive interrupts
                   1489:                         * until the queue has drained a bit.
1.99      mycroft  1490:                         */
                   1491:                        if (!cc) {
1.101     mycroft  1492:                                SET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED);
                   1493:                                CLR(sc->sc_ier, IER_ERXRDY);
                   1494:                                bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
1.99      mycroft  1495:                        }
1.88      mycroft  1496:                } else {
                   1497:                        if ((iir & IIR_IMASK) == IIR_RXRDY) {
1.91      thorpej  1498:                                bus_space_write_1(iot, ioh, com_ier, 0);
1.88      mycroft  1499:                                delay(10);
1.99      mycroft  1500:                                bus_space_write_1(iot, ioh, com_ier,sc->sc_ier);
1.88      mycroft  1501:                                iir = IIR_NOPEND;
                   1502:                                continue;
                   1503:                        }
                   1504:                }
1.55      mycroft  1505:
1.99      mycroft  1506:                msr = bus_space_read_1(iot, ioh, com_msr);
                   1507:                delta = msr ^ sc->sc_msr;
                   1508:                sc->sc_msr = msr;
                   1509:                if (ISSET(delta, sc->sc_msr_mask)) {
                   1510:                        sc->sc_msr_delta |= delta;
                   1511:
                   1512:                        /*
                   1513:                         * Stop output immediately if we lose the output
                   1514:                         * flow control signal or carrier detect.
                   1515:                         */
                   1516:                        if (ISSET(~msr, sc->sc_msr_mask)) {
                   1517:                                sc->sc_tbc = 0;
                   1518:                                sc->sc_heldtbc = 0;
1.69      mycroft  1519: #ifdef COM_DEBUG
1.101     mycroft  1520:                                if (com_debug)
                   1521:                                        comstatus(sc, "comintr  ");
1.69      mycroft  1522: #endif
1.99      mycroft  1523:                        }
1.55      mycroft  1524:
1.99      mycroft  1525:                        sc->sc_st_check = 1;
1.55      mycroft  1526:                }
1.99      mycroft  1527:        } while (!ISSET((iir = bus_space_read_1(iot, ioh, com_iir)), IIR_NOPEND));
1.55      mycroft  1528:
1.99      mycroft  1529:        /*
                   1530:         * Done handling any receive interrupts. See if data can be
                   1531:         * transmitted as well. Schedule tx done event if no data left
                   1532:         * and tty was marked busy.
                   1533:         */
                   1534:        if (ISSET(lsr, LSR_TXRDY)) {
                   1535:                /*
                   1536:                 * If we've delayed a parameter change, do it now, and restart
                   1537:                 * output.
                   1538:                 */
                   1539:                if (sc->sc_heldchange) {
                   1540:                        com_loadchannelregs(sc);
                   1541:                        sc->sc_heldchange = 0;
                   1542:                        sc->sc_tbc = sc->sc_heldtbc;
                   1543:                        sc->sc_heldtbc = 0;
                   1544:                }
                   1545:                /* Output the next chunk of the contiguous buffer, if any. */
                   1546:                if (sc->sc_tbc > 0) {
                   1547:                        int n;
                   1548:
                   1549:                        n = sc->sc_fifolen;
                   1550:                        if (n > sc->sc_tbc)
                   1551:                                n = sc->sc_tbc;
                   1552:                        bus_space_write_multi_1(iot, ioh, com_data, sc->sc_tba, n);
                   1553:                        sc->sc_tbc -= n;
                   1554:                        sc->sc_tba += n;
                   1555:                } else if (sc->sc_tx_busy) {
                   1556:                        sc->sc_tx_busy = 0;
                   1557:                        sc->sc_tx_done = 1;
1.62      mycroft  1558:                }
1.99      mycroft  1559:        }
1.62      mycroft  1560:
1.99      mycroft  1561:        /* Wake up the poller. */
                   1562: #ifdef __GENERIC_SOFT_INTERRUPTS
                   1563:        softintr_schedule(sc->sc_si);
                   1564: #else
                   1565: #ifndef alpha
                   1566:        setsoftserial();
                   1567: #else
                   1568:        if (!com_softintr_scheduled) {
                   1569:                com_softintr_scheduled = 1;
                   1570:                timeout(comsoft, NULL, 1);
1.1       cgd      1571:        }
1.99      mycroft  1572: #endif
                   1573: #endif
1.88      mycroft  1574:        return (1);
1.1       cgd      1575: }
                   1576:
                   1577: /*
1.102     thorpej  1578:  * The following functions are polled getc and putc routines, shared
                   1579:  * by the console and kgdb glue.
                   1580:  */
                   1581:
                   1582: int
                   1583: com_common_getc(iot, ioh)
                   1584:        bus_space_tag_t iot;
                   1585:        bus_space_handle_t ioh;
                   1586: {
                   1587:        int s = splserial();
                   1588:        u_char stat, c;
                   1589:
                   1590:        while (!ISSET(stat = bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY))
                   1591:                ;
                   1592:        c = bus_space_read_1(iot, ioh, com_data);
                   1593:        stat = bus_space_read_1(iot, ioh, com_iir);
                   1594:        splx(s);
                   1595:        return (c);
                   1596: }
                   1597:
                   1598: void
                   1599: com_common_putc(iot, ioh, c)
                   1600:        bus_space_tag_t iot;
                   1601:        bus_space_handle_t ioh;
                   1602:        int c;
                   1603: {
                   1604:        int s = splserial();
                   1605:        u_char stat;
                   1606:        register int timo;
                   1607:
                   1608:        /* wait for any pending transmission to finish */
                   1609:        timo = 50000;
                   1610:        while (!ISSET(stat = bus_space_read_1(iot, ioh, com_lsr), LSR_TXRDY)
                   1611:            && --timo)
                   1612:                ;
                   1613:        bus_space_write_1(iot, ioh, com_data, c);
                   1614:        /* wait for this transmission to complete */
                   1615:        timo = 1500000;
                   1616:        while (!ISSET(stat = bus_space_read_1(iot, ioh, com_lsr), LSR_TXRDY)
                   1617:            && --timo)
                   1618:                ;
                   1619:        /* clear any interrupts generated by this transmission */
                   1620:        stat = bus_space_read_1(iot, ioh, com_iir);
                   1621:        splx(s);
                   1622: }
                   1623:
                   1624: /*
1.1       cgd      1625:  * Following are all routines needed for COM to act as console
                   1626:  */
1.17      cgd      1627: #include <dev/cons.h>
1.1       cgd      1628:
1.48      mycroft  1629: void
1.1       cgd      1630: comcnprobe(cp)
                   1631:        struct consdev *cp;
                   1632: {
1.80      christos 1633:        /* XXX NEEDS TO BE FIXED XXX */
1.91      thorpej  1634:        bus_space_tag_t iot = 0;
                   1635:        bus_space_handle_t ioh;
1.75      cgd      1636:        int found;
                   1637:
1.91      thorpej  1638:        if (bus_space_map(iot, CONADDR, COM_NPORTS, 0, &ioh)) {
1.75      cgd      1639:                cp->cn_pri = CN_DEAD;
                   1640:                return;
                   1641:        }
1.91      thorpej  1642:        found = comprobe1(iot, ioh, CONADDR);
                   1643:        bus_space_unmap(iot, ioh, COM_NPORTS);
1.75      cgd      1644:        if (!found) {
1.21      mycroft  1645:                cp->cn_pri = CN_DEAD;
                   1646:                return;
                   1647:        }
1.1       cgd      1648:
                   1649:        /* locate the major number */
                   1650:        for (commajor = 0; commajor < nchrdev; commajor++)
                   1651:                if (cdevsw[commajor].d_open == comopen)
                   1652:                        break;
                   1653:
                   1654:        /* initialize required fields */
1.29      mycroft  1655:        cp->cn_dev = makedev(commajor, CONUNIT);
1.1       cgd      1656: #ifdef COMCONSOLE
                   1657:        cp->cn_pri = CN_REMOTE;         /* Force a serial port console */
                   1658: #else
                   1659:        cp->cn_pri = CN_NORMAL;
                   1660: #endif
                   1661: }
                   1662:
1.48      mycroft  1663: void
1.1       cgd      1664: comcninit(cp)
                   1665:        struct consdev *cp;
                   1666: {
                   1667:
1.75      cgd      1668: #if 0
                   1669:        XXX NEEDS TO BE FIXED XXX
1.91      thorpej  1670:        comconstag = ???;
1.75      cgd      1671: #endif
1.98      mycroft  1672:        if (bus_space_map(comconstag, CONADDR, COM_NPORTS, 0, &comconsioh))
1.75      cgd      1673:                panic("comcninit: mapping failed");
                   1674:
1.99      mycroft  1675:        cominitcons(comconstag, comconsioh, comconsrate);
1.75      cgd      1676:        comconsaddr = CONADDR;
1.1       cgd      1677: }
                   1678:
1.99      mycroft  1679: /*
                   1680:  * Initialize UART to known state.
                   1681:  */
1.80      christos 1682: void
1.91      thorpej  1683: cominit(iot, ioh, rate)
                   1684:        bus_space_tag_t iot;
                   1685:        bus_space_handle_t ioh;
1.75      cgd      1686:        int rate;
1.1       cgd      1687: {
                   1688:
1.91      thorpej  1689:        bus_space_write_1(iot, ioh, com_lcr, LCR_DLAB);
1.99      mycroft  1690:        rate = comspeed(rate);
1.91      thorpej  1691:        bus_space_write_1(iot, ioh, com_dlbl, rate);
                   1692:        bus_space_write_1(iot, ioh, com_dlbh, rate >> 8);
                   1693:        bus_space_write_1(iot, ioh, com_lcr, LCR_8BITS);
1.99      mycroft  1694:        bus_space_write_1(iot, ioh, com_mcr, 0);
1.91      thorpej  1695:        bus_space_write_1(iot, ioh, com_fifo,
1.87      mycroft  1696:            FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_1);
1.99      mycroft  1697:        bus_space_write_1(iot, ioh, com_ier, 0);
                   1698: }
                   1699:
                   1700: /*
                   1701:  * Set UART for console use. Do normal init, then enable interrupts.
                   1702:  */
                   1703: void
                   1704: cominitcons(iot, ioh, rate)
                   1705:        bus_space_tag_t iot;
                   1706:        bus_space_handle_t ioh;
                   1707:        int rate;
                   1708: {
                   1709:        int s = splserial();
                   1710:        u_char stat;
                   1711:
                   1712:        cominit(iot, ioh, rate);
                   1713:        bus_space_write_1(iot, ioh, com_ier, IER_ERXRDY | IER_ETXRDY);
1.91      thorpej  1714:        bus_space_write_1(iot, ioh, com_mcr, MCR_DTR | MCR_RTS);
1.87      mycroft  1715:        DELAY(100);
1.91      thorpej  1716:        stat = bus_space_read_1(iot, ioh, com_iir);
1.1       cgd      1717:        splx(s);
                   1718: }
                   1719:
1.80      christos 1720: int
1.1       cgd      1721: comcngetc(dev)
1.21      mycroft  1722:        dev_t dev;
1.1       cgd      1723: {
                   1724:
1.102     thorpej  1725:        return (com_common_getc(comconstag, comconsioh));
1.1       cgd      1726: }
                   1727:
                   1728: /*
                   1729:  * Console kernel output character routine.
                   1730:  */
1.48      mycroft  1731: void
1.1       cgd      1732: comcnputc(dev, c)
                   1733:        dev_t dev;
1.21      mycroft  1734:        int c;
1.1       cgd      1735: {
                   1736:
1.102     thorpej  1737:        com_common_putc(comconstag, comconsioh, c);
1.37      mycroft  1738: }
                   1739:
                   1740: void
                   1741: comcnpollc(dev, on)
                   1742:        dev_t dev;
                   1743:        int on;
                   1744: {
                   1745:
1.2       cgd      1746: }

CVSweb <webmaster@jp.NetBSD.org>