[BACK]Return to epcom.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / arm / ep93xx

Annotation of src/sys/arch/arm/ep93xx/epcom.c, Revision 1.11

1.11    ! ad          1: /*     $NetBSD: epcom.c,v 1.10 2006/05/14 21:55:09 elad Exp $ */
1.1       joff        2: /*
                      3:  * Copyright (c) 1998, 1999, 2001, 2002, 2004 The NetBSD Foundation, Inc.
                      4:  * All rights reserved.
                      5:  *
                      6:  * This code is derived from software contributed to The NetBSD Foundation
                      7:  * by Jesse Off
                      8:  *
                      9:  * This code is derived from software contributed to The NetBSD Foundation
                     10:  * by Ichiro FUKUHARA and Naoto Shimazaki.
                     11:  *
                     12:  * This code is derived from software contributed to The NetBSD Foundation
                     13:  * by IWAMOTO Toshihiro.
                     14:  *
                     15:  * This code is derived from software contributed to The NetBSD Foundation
                     16:  * by Charles M. Hannum.
                     17:  *
                     18:  * Redistribution and use in source and binary forms, with or without
                     19:  * modification, are permitted provided that the following conditions
                     20:  * are met:
                     21:  * 1. Redistributions of source code must retain the above copyright
                     22:  *    notice, this list of conditions and the following disclaimer.
                     23:  * 2. Redistributions in binary form must reproduce the above copyright
                     24:  *    notice, this list of conditions and the following disclaimer in the
                     25:  *    documentation and/or other materials provided with the distribution.
                     26:  * 3. All advertising materials mentioning features or use of this software
                     27:  *    must display the following acknowledgement:
                     28:  *        This product includes software developed by the NetBSD
                     29:  *        Foundation, Inc. and its contributors.
                     30:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     31:  *    contributors may be used to endorse or promote products derived
                     32:  *    from this software without specific prior written permission.
                     33:  *
                     34:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     35:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     36:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     37:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     38:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     39:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     40:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     41:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     42:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     43:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     44:  * POSSIBILITY OF SUCH DAMAGE.
                     45:  */
                     46:
                     47: /*
                     48:  * Copyright (c) 1991 The Regents of the University of California.
                     49:  * All rights reserved.
                     50:  *
                     51:  * Redistribution and use in source and binary forms, with or without
                     52:  * modification, are permitted provided that the following conditions
                     53:  * are met:
                     54:  * 1. Redistributions of source code must retain the above copyright
                     55:  *    notice, this list of conditions and the following disclaimer.
                     56:  * 2. Redistributions in binary form must reproduce the above copyright
                     57:  *    notice, this list of conditions and the following disclaimer in the
                     58:  *    documentation and/or other materials provided with the distribution.
                     59:  * 3. Neither the name of the University nor the names of its contributors
                     60:  *    may be used to endorse or promote products derived from this software
                     61:  *    without specific prior written permission.
                     62:  *
                     63:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     64:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     65:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     66:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     67:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     68:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     69:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     70:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     71:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     72:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     73:  * SUCH DAMAGE.
                     74:  *
                     75:  *      @(#)com.c       7.5 (Berkeley) 5/16/91
                     76:  */
                     77:
                     78: /*
                     79:  * TODO: hardware flow control
                     80:  */
                     81:
                     82: #include <sys/cdefs.h>
1.11    ! ad         83: __KERNEL_RCSID(0, "$NetBSD: epcom.c,v 1.10 2006/05/14 21:55:09 elad Exp $");
1.1       joff       84:
                     85: #include "opt_ddb.h"
                     86: #include "opt_kgdb.h"
                     87: #include "epcom.h"
                     88:
                     89: #include "rnd.h"
                     90: #if NRND > 0 && defined(RND_COM)
                     91: #include <sys/rnd.h>
                     92: #endif
                     93:
                     94: /*
                     95:  * Override cnmagic(9) macro before including <sys/systm.h>.
                     96:  * We need to know if cn_check_magic triggered debugger, so set a flag.
                     97:  * Callers of cn_check_magic must declare int cn_trapped = 0;
                     98:  * XXX: this is *ugly*!
                     99:  */
                    100: #define cn_trap()                              \
                    101:        do {                                    \
                    102:                console_debugger();             \
                    103:                cn_trapped = 1;                 \
                    104:        } while (/* CONSTCOND */ 0)
                    105:
                    106:
                    107: #include <sys/param.h>
                    108: #include <sys/systm.h>
                    109: #include <sys/types.h>
                    110: #include <sys/conf.h>
                    111: #include <sys/file.h>
                    112: #include <sys/device.h>
                    113: #include <sys/kernel.h>
                    114: #include <sys/malloc.h>
                    115: #include <sys/tty.h>
                    116: #include <sys/uio.h>
                    117: #include <sys/vnode.h>
1.10      elad      118: #include <sys/kauth.h>
1.1       joff      119:
                    120: #include <machine/intr.h>
                    121: #include <machine/bus.h>
                    122:
                    123: #include <arm/ep93xx/epcomreg.h>
                    124: #include <arm/ep93xx/epcomvar.h>
                    125: #include <arm/ep93xx/ep93xxreg.h>
                    126: #include <arm/ep93xx/ep93xxvar.h>
                    127:
                    128: #include <dev/cons.h>
                    129:
                    130: static int     epcomparam(struct tty *, struct termios *);
                    131: static void    epcomstart(struct tty *);
                    132: static int     epcomhwiflow(struct tty *, int);
                    133:
                    134: static u_int   cflag2lcrhi(tcflag_t);
                    135: static void    epcom_iflush(struct epcom_softc *);
                    136: static void    epcom_set(struct epcom_softc *);
                    137:
                    138: int             epcomcngetc(dev_t);
                    139: void            epcomcnputc(dev_t, int);
                    140: void            epcomcnpollc(dev_t, int);
                    141:
                    142: static void    epcomsoft(void* arg);
                    143: inline static void     epcom_txsoft(struct epcom_softc *, struct tty *);
                    144: inline static void     epcom_rxsoft(struct epcom_softc *, struct tty *);
                    145:
                    146: void            epcomcnprobe(struct consdev *);
                    147: void            epcomcninit(struct consdev *);
                    148:
                    149: static struct epcom_cons_softc {
                    150:        bus_space_tag_t         sc_iot;
                    151:        bus_space_handle_t      sc_ioh;
                    152:        bus_addr_t              sc_hwbase;
                    153:        int                     sc_ospeed;
                    154:        tcflag_t                sc_cflag;
                    155:        int                     sc_attached;
                    156: } epcomcn_sc;
                    157:
                    158: static struct cnm_state epcom_cnm_state;
                    159:
                    160: extern struct cfdriver epcom_cd;
                    161:
                    162: dev_type_open(epcomopen);
                    163: dev_type_close(epcomclose);
                    164: dev_type_read(epcomread);
                    165: dev_type_write(epcomwrite);
                    166: dev_type_ioctl(epcomioctl);
                    167: dev_type_stop(epcomstop);
                    168: dev_type_tty(epcomtty);
                    169: dev_type_poll(epcompoll);
                    170:
                    171: const struct cdevsw epcom_cdevsw = {
                    172:        epcomopen, epcomclose, epcomread, epcomwrite, epcomioctl,
                    173:        epcomstop, epcomtty, epcompoll, nommap, ttykqfilter, D_TTY
                    174: };
                    175:
                    176: struct consdev epcomcons = {
                    177:        NULL, NULL, epcomcngetc, epcomcnputc, epcomcnpollc, NULL,
                    178:        NULL, NULL, NODEV, CN_NORMAL
                    179: };
                    180:
                    181: #ifndef DEFAULT_COMSPEED
                    182: #define DEFAULT_COMSPEED 115200
                    183: #endif
                    184:
                    185: #define COMUNIT_MASK    0x7ffff
                    186: #define COMDIALOUT_MASK 0x80000
                    187:
                    188: #define COMUNIT(x)     (minor(x) & COMUNIT_MASK)
                    189: #define COMDIALOUT(x)  (minor(x) & COMDIALOUT_MASK)
                    190:
                    191: #define COM_ISALIVE(sc)        ((sc)->enabled != 0 && \
1.7       thorpej   192:                        device_is_active(&(sc)->sc_dev))
1.1       joff      193:
                    194: void
1.6       christos  195: epcom_attach_subr(struct epcom_softc *sc)
1.1       joff      196: {
                    197:        struct tty *tp;
                    198:
                    199:        if (sc->sc_iot == epcomcn_sc.sc_iot
                    200:            && sc->sc_hwbase == epcomcn_sc.sc_hwbase) {
                    201:                epcomcn_sc.sc_attached = 1;
                    202:                sc->sc_lcrlo = EPCOMSPEED2BRD(epcomcn_sc.sc_ospeed) & 0xff;
                    203:                sc->sc_lcrmid = EPCOMSPEED2BRD(epcomcn_sc.sc_ospeed) >> 8;
                    204:
                    205:                /* Make sure the console is always "hardwired". */
                    206:                delay(10000);   /* wait for output to finish */
                    207:                SET(sc->sc_hwflags, COM_HW_CONSOLE);
                    208:                SET(sc->sc_swflags, TIOCFLAG_SOFTCAR);
                    209:        }
                    210:
                    211:        tp = ttymalloc();
                    212:        tp->t_oproc = epcomstart;
                    213:        tp->t_param = epcomparam;
                    214:        tp->t_hwiflow = epcomhwiflow;
                    215:
                    216:        sc->sc_tty = tp;
                    217:        sc->sc_rbuf = malloc(EPCOM_RING_SIZE << 1, M_DEVBUF, M_NOWAIT);
                    218:        sc->sc_rbput = sc->sc_rbget = sc->sc_rbuf;
                    219:        sc->sc_rbavail = EPCOM_RING_SIZE;
                    220:        if (sc->sc_rbuf == NULL) {
                    221:                printf("%s: unable to allocate ring buffer\n",
                    222:                    sc->sc_dev.dv_xname);
                    223:                return;
                    224:        }
                    225:        sc->sc_ebuf = sc->sc_rbuf + (EPCOM_RING_SIZE << 1);
                    226:        sc->sc_tbc = 0;
                    227:
                    228:        sc->sc_lcrlo = EPCOMSPEED2BRD(DEFAULT_COMSPEED) & 0xff;
                    229:        sc->sc_lcrmid = EPCOMSPEED2BRD(DEFAULT_COMSPEED) >> 8;
                    230:        sc->sc_lcrhi = cflag2lcrhi(CS8); /* 8N1 */
                    231:
                    232:        tty_attach(tp);
                    233:
                    234:        if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
                    235:                int maj;
                    236:
                    237:                /* locate the major number */
                    238:                maj = cdevsw_lookup_major(&epcom_cdevsw);
                    239:
1.9       thorpej   240:                cn_tab->cn_dev = makedev(maj, device_unit(&sc->sc_dev));
1.1       joff      241:
                    242:                aprint_normal("%s: console\n", sc->sc_dev.dv_xname);
                    243:        }
                    244:
                    245:        sc->sc_si = softintr_establish(IPL_SOFTSERIAL, epcomsoft, sc);
                    246:
                    247: #if NRND > 0 && defined(RND_COM)
                    248:        rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname,
                    249:                          RND_TYPE_TTY, 0);
                    250: #endif
                    251:
                    252:        /* if there are no enable/disable functions, assume the device
                    253:           is always enabled */
                    254:        if (!sc->enable)
                    255:                sc->enabled = 1;
                    256:
                    257:        /* XXX configure register */
                    258:        /* xxx_config(sc) */
                    259:
                    260:        SET(sc->sc_hwflags, COM_HW_DEV_OK);
                    261: }
                    262:
                    263: static int
1.6       christos  264: epcomparam(struct tty *tp, struct termios *t)
1.1       joff      265: {
                    266:        struct epcom_softc *sc
                    267:                = device_lookup(&epcom_cd, COMUNIT(tp->t_dev));
                    268:        int s;
                    269:
                    270:        if (COM_ISALIVE(sc) == 0)
                    271:                return (EIO);
                    272:
                    273:        if (t->c_ispeed && t->c_ispeed != t->c_ospeed)
                    274:                return (EINVAL);
                    275:
                    276:        /*
                    277:         * For the console, always force CLOCAL and !HUPCL, so that the port
                    278:         * is always active.
                    279:         */
                    280:        if (ISSET(sc->sc_swflags, TIOCFLAG_SOFTCAR) ||
                    281:            ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
                    282:                SET(t->c_cflag, CLOCAL);
                    283:                CLR(t->c_cflag, HUPCL);
                    284:        }
                    285:
                    286:        /*
                    287:         * If there were no changes, don't do anything.  This avoids dropping
                    288:         * input and improves performance when all we did was frob things like
                    289:         * VMIN and VTIME.
                    290:         */
                    291:        if (tp->t_ospeed == t->c_ospeed &&
                    292:            tp->t_cflag == t->c_cflag)
                    293:                return (0);
                    294:
                    295:        s = splserial();
                    296:
                    297:        sc->sc_lcrhi = cflag2lcrhi(t->c_cflag);
                    298:        sc->sc_lcrlo = EPCOMSPEED2BRD(t->c_ospeed) & 0xff;
                    299:        sc->sc_lcrmid = EPCOMSPEED2BRD(t->c_ospeed) >> 8;
                    300:
                    301:        /* And copy to tty. */
                    302:        tp->t_ispeed = 0;
                    303:        tp->t_ospeed = t->c_ospeed;
                    304:        tp->t_cflag = t->c_cflag;
1.2       joff      305:        epcom_set(sc);
1.1       joff      306:
                    307:        splx(s);
                    308:
                    309:        /*
                    310:         * Update the tty layer's idea of the carrier bit.
                    311:         * We tell tty the carrier is always on.
                    312:         */
                    313:        (void) (*tp->t_linesw->l_modem)(tp, 1);
                    314:
                    315: #ifdef COM_DEBUG
                    316:        if (com_debug)
                    317:                comstatus(sc, "comparam ");
                    318: #endif
                    319:
                    320:        if (!ISSET(t->c_cflag, CHWFLOW)) {
                    321:                if (sc->sc_tx_stopped) {
                    322:                        sc->sc_tx_stopped = 0;
                    323:                        epcomstart(tp);
                    324:                }
                    325:        }
                    326:
                    327:        return (0);
                    328: }
                    329:
                    330: static int
1.6       christos  331: epcomhwiflow(struct tty *tp, int block)
1.1       joff      332: {
                    333:        return (0);
                    334: }
                    335:
                    336: static void
                    337: epcom_filltx(struct epcom_softc *sc)
                    338: {
                    339:        bus_space_tag_t iot = sc->sc_iot;
                    340:        bus_space_handle_t ioh = sc->sc_ioh;
                    341:        int n;
                    342:
                    343:        n = 0;
                    344:         while ((bus_space_read_4(iot, ioh, EPCOM_Flag) & Flag_TXFF) == 0) {
                    345:                if (n >= sc->sc_tbc)
                    346:                        break;
                    347:                bus_space_write_4(iot, ioh, EPCOM_Data,
                    348:                                  0xff & *(sc->sc_tba + n));
                    349:                n++;
                    350:         }
                    351:         sc->sc_tbc -= n;
                    352:         sc->sc_tba += n;
                    353: }
                    354:
                    355: static void
1.6       christos  356: epcomstart(struct tty *tp)
1.1       joff      357: {
                    358:        struct epcom_softc *sc
                    359:                = device_lookup(&epcom_cd, COMUNIT(tp->t_dev));
                    360:        int s;
                    361:
                    362:        if (COM_ISALIVE(sc) == 0)
                    363:                return;
                    364:
                    365:        s = spltty();
                    366:        if (ISSET(tp->t_state, TS_BUSY | TS_TIMEOUT | TS_TTSTOP))
                    367:                goto out;
                    368:        if (sc->sc_tx_stopped)
                    369:                goto out;
                    370:
                    371:        if (tp->t_outq.c_cc <= tp->t_lowat) {
                    372:                if (ISSET(tp->t_state, TS_ASLEEP)) {
                    373:                        CLR(tp->t_state, TS_ASLEEP);
                    374:                        wakeup(&tp->t_outq);
                    375:                }
                    376:                selwakeup(&tp->t_wsel);
                    377:                if (tp->t_outq.c_cc == 0)
                    378:                        goto out;
                    379:        }
                    380:
                    381:        /* Grab the first contiguous region of buffer space. */
                    382:        {
                    383:                u_char *tba;
                    384:                int tbc;
                    385:
                    386:                tba = tp->t_outq.c_cf;
                    387:                tbc = ndqb(&tp->t_outq, 0);
                    388:
                    389:                (void)splserial();
                    390:
                    391:                sc->sc_tba = tba;
                    392:                sc->sc_tbc = tbc;
                    393:        }
                    394:
                    395:        SET(tp->t_state, TS_BUSY);
                    396:        sc->sc_tx_busy = 1;
                    397:
1.2       joff      398:        /* Output the first chunk of the contiguous buffer. */
                    399:        epcom_filltx(sc);
                    400:
1.1       joff      401:        if (!ISSET(sc->sc_ctrl, Ctrl_TIE)) {
                    402:                SET(sc->sc_ctrl, Ctrl_TIE);
                    403:                epcom_set(sc);
                    404:        }
                    405:
                    406: out:
                    407:        splx(s);
                    408:        return;
                    409: }
                    410:
                    411: static void
                    412: epcom_break(struct epcom_softc *sc, int onoff)
                    413: {
                    414:        if (onoff)
                    415:                SET(sc->sc_lcrhi, LinCtrlHigh_BRK);
                    416:        else
                    417:                CLR(sc->sc_lcrhi, LinCtrlHigh_BRK);
1.2       joff      418:        epcom_set(sc);
1.1       joff      419: }
                    420:
                    421: static void
                    422: epcom_shutdown(struct epcom_softc *sc)
                    423: {
                    424:        int s;
                    425:
                    426:        s = splserial();
                    427:
                    428:        /* Turn off interrupts. */
                    429:        CLR(sc->sc_ctrl, (Ctrl_TIE|Ctrl_RTIE|Ctrl_RIE));
                    430:
                    431:        /* Clear any break condition set with TIOCSBRK. */
                    432:        epcom_break(sc, 0);
                    433:        epcom_set(sc);
                    434:
                    435:        if (sc->disable) {
                    436: #ifdef DIAGNOSTIC
                    437:                if (!sc->enabled)
                    438:                        panic("epcom_shutdown: not enabled?");
                    439: #endif
                    440:                (*sc->disable)(sc);
                    441:                sc->enabled = 0;
                    442:        }
                    443:        splx(s);
                    444: }
                    445:
                    446: int
1.6       christos  447: epcomopen(dev_t dev, int flag, int mode, struct lwp *l)
1.1       joff      448: {
                    449:        struct epcom_softc *sc;
                    450:        struct tty *tp;
                    451:        int s, s2;
                    452:        int error;
                    453:
                    454:        sc = device_lookup(&epcom_cd, COMUNIT(dev));
                    455:        if (sc == NULL || !ISSET(sc->sc_hwflags, COM_HW_DEV_OK) ||
                    456:                sc->sc_rbuf == NULL)
                    457:                return (ENXIO);
                    458:
1.7       thorpej   459:        if (!device_is_active(&sc->sc_dev))
1.1       joff      460:                return (ENXIO);
                    461:
                    462: #ifdef KGDB
                    463:        /*
                    464:         * If this is the kgdb port, no other use is permitted.
                    465:         */
                    466:        if (ISSET(sc->sc_hwflags, COM_HW_KGDB))
                    467:                return (EBUSY);
                    468: #endif
                    469:
                    470:        tp = sc->sc_tty;
                    471:
                    472:        if (ISSET(tp->t_state, TS_ISOPEN) &&
                    473:            ISSET(tp->t_state, TS_XCLUDE) &&
1.11    ! ad        474:            kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER,
        !           475:            &l->l_acflag) != 0)
1.1       joff      476:                return (EBUSY);
                    477:
                    478:        s = spltty();
                    479:
                    480:        /*
                    481:         * Do the following iff this is a first open.
                    482:         */
                    483:        if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
                    484:                struct termios t;
                    485:
                    486:                tp->t_dev = dev;
                    487:
                    488:                s2 = splserial();
                    489:
                    490:                if (sc->enable) {
                    491:                        if ((*sc->enable)(sc)) {
                    492:                                splx(s2);
                    493:                                splx(s);
                    494:                                printf("%s: device enable failed\n",
                    495:                                       sc->sc_dev.dv_xname);
                    496:                                return (EIO);
                    497:                        }
                    498:                        sc->enabled = 1;
                    499: #if 0
                    500: /* XXXXXXXXXXXXXXX */
                    501:                        com_config(sc);
                    502: #endif
                    503:                }
                    504:
                    505:                /* Turn on interrupts. */
                    506:                SET(sc->sc_ctrl, (Ctrl_UARTE|Ctrl_RIE|Ctrl_RTIE));
                    507:                epcom_set(sc);
                    508:
                    509: #if 0
                    510:                /* Fetch the current modem control status, needed later. */
                    511:                sc->sc_msr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, com_msr);
                    512:
                    513:                /* Clear PPS capture state on first open. */
                    514:                sc->sc_ppsmask = 0;
                    515:                sc->ppsparam.mode = 0;
                    516: #endif
                    517:
                    518:                splx(s2);
                    519:
                    520:                /*
                    521:                 * Initialize the termios status to the defaults.  Add in the
                    522:                 * sticky bits from TIOCSFLAGS.
                    523:                 */
                    524:                t.c_ispeed = 0;
                    525:                if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
                    526:                        t.c_ospeed = epcomcn_sc.sc_ospeed;
                    527:                        t.c_cflag = epcomcn_sc.sc_cflag;
                    528:                } else {
                    529:                        t.c_ospeed = TTYDEF_SPEED;
                    530:                        t.c_cflag = TTYDEF_CFLAG;
                    531:                }
                    532:                if (ISSET(sc->sc_swflags, TIOCFLAG_CLOCAL))
                    533:                        SET(t.c_cflag, CLOCAL);
                    534:                if (ISSET(sc->sc_swflags, TIOCFLAG_CRTSCTS))
                    535:                        SET(t.c_cflag, CRTSCTS);
                    536:                if (ISSET(sc->sc_swflags, TIOCFLAG_MDMBUF))
                    537:                        SET(t.c_cflag, MDMBUF);
                    538:                /* Make sure epcomparam() will do something. */
                    539:                tp->t_ospeed = 0;
                    540:                (void) epcomparam(tp, &t);
                    541:                tp->t_iflag = TTYDEF_IFLAG;
                    542:                tp->t_oflag = TTYDEF_OFLAG;
                    543:                tp->t_lflag = TTYDEF_LFLAG;
                    544:                ttychars(tp);
                    545:                ttsetwater(tp);
                    546:
                    547:                s2 = splserial();
                    548:
                    549:                /* Clear the input ring, and unblock. */
                    550:                sc->sc_rbput = sc->sc_rbget = sc->sc_rbuf;
                    551:                sc->sc_rbavail = EPCOM_RING_SIZE;
                    552:                epcom_iflush(sc);
                    553:                CLR(sc->sc_rx_flags, RX_ANY_BLOCK);
                    554:
                    555: #ifdef COM_DEBUG
                    556:                if (epcom_debug)
                    557:                        comstatus(sc, "epcomopen  ");
                    558: #endif
                    559:
                    560:                splx(s2);
                    561:        }
                    562:
                    563:        splx(s);
                    564:
                    565:        error = ttyopen(tp, COMDIALOUT(dev), ISSET(flag, O_NONBLOCK));
                    566:        if (error)
                    567:                goto bad;
                    568:
                    569:        error = (*tp->t_linesw->l_open)(dev, tp);
                    570:        if (error)
                    571:                goto bad;
                    572:
                    573:        return (0);
                    574:
                    575: bad:
                    576:        if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
                    577:                /*
                    578:                 * We failed to open the device, and nobody else had it opened.
                    579:                 * Clean up the state as appropriate.
                    580:                 */
                    581:                epcom_shutdown(sc);
                    582:        }
                    583:
                    584:        return (error);
                    585: }
                    586:
                    587: int
1.6       christos  588: epcomclose(dev_t dev, int flag, int mode, struct lwp *l)
1.1       joff      589: {
                    590:        struct epcom_softc *sc = device_lookup(&epcom_cd, COMUNIT(dev));
                    591:        struct tty *tp = sc->sc_tty;
                    592:
                    593:        /* XXX This is for cons.c. */
                    594:        if (!ISSET(tp->t_state, TS_ISOPEN))
                    595:                return (0);
                    596:
                    597:        (*tp->t_linesw->l_close)(tp, flag);
                    598:        ttyclose(tp);
                    599:
                    600:        if (COM_ISALIVE(sc) == 0)
                    601:                return (0);
                    602:
                    603:        if (!ISSET(tp->t_state, TS_ISOPEN) && tp->t_wopen == 0) {
                    604:                /*
                    605:                 * Although we got a last close, the device may still be in
                    606:                 * use; e.g. if this was the dialout node, and there are still
                    607:                 * processes waiting for carrier on the non-dialout node.
                    608:                 */
                    609:                epcom_shutdown(sc);
                    610:        }
                    611:
                    612:        return (0);
                    613: }
                    614:
                    615: int
1.6       christos  616: epcomread(dev_t dev, struct uio *uio, int flag)
1.1       joff      617: {
                    618:        struct epcom_softc *sc = device_lookup(&epcom_cd, COMUNIT(dev));
                    619:        struct tty *tp = sc->sc_tty;
                    620:
                    621:        if (COM_ISALIVE(sc) == 0)
                    622:                return (EIO);
                    623:
                    624:        return ((*tp->t_linesw->l_read)(tp, uio, flag));
                    625: }
                    626:
                    627: int
1.6       christos  628: epcomwrite(dev_t dev, struct uio *uio, int flag)
1.1       joff      629: {
                    630:        struct epcom_softc *sc = device_lookup(&epcom_cd, COMUNIT(dev));
                    631:        struct tty *tp = sc->sc_tty;
                    632:
                    633:        if (COM_ISALIVE(sc) == 0)
                    634:                return (EIO);
                    635:
                    636:        return ((*tp->t_linesw->l_write)(tp, uio, flag));
                    637: }
                    638:
                    639: int
1.6       christos  640: epcompoll(dev_t dev, int events, struct lwp *l)
1.1       joff      641: {
                    642:        struct epcom_softc *sc = device_lookup(&epcom_cd, COMUNIT(dev));
                    643:        struct tty *tp = sc->sc_tty;
                    644:
                    645:        if (COM_ISALIVE(sc) == 0)
                    646:                return (EIO);
                    647:
1.6       christos  648:        return ((*tp->t_linesw->l_poll)(tp, events, l));
1.1       joff      649: }
                    650:
                    651: struct tty *
1.6       christos  652: epcomtty(dev_t dev)
1.1       joff      653: {
                    654:        struct epcom_softc *sc = device_lookup(&epcom_cd, COMUNIT(dev));
                    655:        struct tty *tp = sc->sc_tty;
                    656:
                    657:        return (tp);
                    658: }
                    659:
                    660: int
1.6       christos  661: epcomioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct lwp *l)
1.1       joff      662: {
                    663:        struct epcom_softc *sc = device_lookup(&epcom_cd, COMUNIT(dev));
                    664:        struct tty *tp = sc->sc_tty;
                    665:        int error;
                    666:        int s;
                    667:
                    668:        if (COM_ISALIVE(sc) == 0)
                    669:                return (EIO);
                    670:
1.6       christos  671:        error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l);
1.1       joff      672:        if (error != EPASSTHROUGH)
                    673:                return (error);
                    674:
1.6       christos  675:        error = ttioctl(tp, cmd, data, flag, l);
1.1       joff      676:        if (error != EPASSTHROUGH)
                    677:                return (error);
                    678:
                    679:        error = 0;
                    680:
                    681:        s = splserial();
                    682:
                    683:        switch (cmd) {
                    684:        case TIOCSBRK:
                    685:                epcom_break(sc, 1);
                    686:                break;
                    687:
                    688:        case TIOCCBRK:
                    689:                epcom_break(sc, 0);
                    690:                break;
                    691:
                    692:        case TIOCGFLAGS:
                    693:                *(int *)data = sc->sc_swflags;
                    694:                break;
                    695:
                    696:        case TIOCSFLAGS:
1.11    ! ad        697:                error = kauth_authorize_generic(l->l_cred,
        !           698:                    KAUTH_GENERIC_ISSUSER, &l->l_acflag);
1.1       joff      699:                if (error)
                    700:                        break;
                    701:                sc->sc_swflags = *(int *)data;
                    702:                break;
                    703:
                    704:        default:
                    705:                error = EPASSTHROUGH;
                    706:                break;
                    707:        }
                    708:
                    709:        splx(s);
                    710:
                    711:        return (error);
                    712: }
                    713:
                    714: /*
                    715:  * Stop output on a line.
                    716:  */
                    717: void
1.6       christos  718: epcomstop(struct tty *tp, int flag)
1.1       joff      719: {
                    720:        struct epcom_softc *sc
                    721:                = device_lookup(&epcom_cd, COMUNIT(tp->t_dev));
                    722:        int s;
                    723:
                    724:        s = splserial();
                    725:        if (ISSET(tp->t_state, TS_BUSY)) {
                    726:                /* Stop transmitting at the next chunk. */
                    727:                sc->sc_tbc = 0;
                    728:                if (!ISSET(tp->t_state, TS_TTSTOP))
                    729:                        SET(tp->t_state, TS_FLUSH);
                    730:        }
                    731:        splx(s);
                    732: }
                    733:
                    734: static u_int
1.6       christos  735: cflag2lcrhi(tcflag_t cflag)
1.1       joff      736: {
                    737:        u_int lcrhi;
                    738:
                    739:        switch (cflag & CSIZE) {
                    740:        case CS7:
                    741:                lcrhi = 0x40;
                    742:                break;
                    743:        case CS6:
                    744:                lcrhi = 0x20;
                    745:                break;
                    746:        case CS8:
                    747:        default:
                    748:                lcrhi = 0x60;
                    749:                break;
                    750:        }
                    751:        lcrhi |= (cflag & PARENB) ? LinCtrlHigh_PEN : 0;
                    752:        lcrhi |= (cflag & PARODD) ? 0 : LinCtrlHigh_EPS;
                    753:        lcrhi |= (cflag & CSTOPB) ? LinCtrlHigh_STP2 : 0;
                    754:        lcrhi |= LinCtrlHigh_FEN;  /* FIFO always enabled */
                    755:
                    756:        return (lcrhi);
                    757: }
                    758:
                    759: static void
1.6       christos  760: epcom_iflush(struct epcom_softc *sc)
1.1       joff      761: {
                    762:        bus_space_tag_t iot = sc->sc_iot;
                    763:        bus_space_handle_t ioh = sc->sc_ioh;
                    764: #ifdef DIAGNOSTIC
                    765:        int reg;
                    766: #endif
                    767:        int timo;
                    768:
                    769: #ifdef DIAGNOSTIC
                    770:        reg = 0xffff;
                    771: #endif
                    772:        timo = 50000;
                    773:        /* flush any pending I/O */
                    774:        while ((bus_space_read_4(iot, ioh, EPCOM_Flag) & Flag_RXFE) == 0
                    775:               && --timo)
                    776: #ifdef DIAGNOSTIC
                    777:                reg =
                    778: #else
                    779:                        (void)
                    780: #endif
                    781:                        bus_space_read_4(iot, ioh, EPCOM_Data);
                    782: #ifdef DIAGNOSTIC
                    783:        if (!timo)
                    784:                printf("%s: com_iflush timeout %02x\n", sc->sc_dev.dv_xname,
                    785:                       reg);
                    786: #endif
                    787: }
                    788:
                    789: static void
                    790: epcom_set(struct epcom_softc *sc)
                    791: {
                    792:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, EPCOM_LinCtrlLow,
                    793:                          sc->sc_lcrlo);
                    794:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, EPCOM_LinCtrlMid,
                    795:                          sc->sc_lcrmid);
                    796:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, EPCOM_LinCtrlHigh,
                    797:                          sc->sc_lcrhi);
                    798:        bus_space_write_4(sc->sc_iot, sc->sc_ioh, EPCOM_Ctrl,
                    799:                          sc->sc_ctrl);
                    800: }
                    801:
                    802: int
1.6       christos  803: epcomcnattach(bus_space_tag_t iot, bus_addr_t iobase, bus_space_handle_t ioh,
                    804:     int ospeed, tcflag_t cflag)
1.1       joff      805: {
                    806:        u_int lcrlo, lcrmid, lcrhi, ctrl, pwrcnt;
                    807:        bus_space_handle_t syscon_ioh;
                    808:
                    809:        cn_tab = &epcomcons;
                    810:        cn_init_magic(&epcom_cnm_state);
                    811:        cn_set_magic("\047\001");
                    812:
                    813:        epcomcn_sc.sc_iot = iot;
                    814:        epcomcn_sc.sc_ioh = ioh;
                    815:        epcomcn_sc.sc_hwbase = iobase;
                    816:        epcomcn_sc.sc_ospeed = ospeed;
                    817:        epcomcn_sc.sc_cflag = cflag;
                    818:
                    819:        lcrhi = cflag2lcrhi(cflag);
                    820:        lcrlo = EPCOMSPEED2BRD(ospeed) & 0xff;
                    821:        lcrmid = EPCOMSPEED2BRD(ospeed) >> 8;
                    822:        ctrl = Ctrl_UARTE;
                    823:
                    824:        bus_space_map(iot, EP93XX_APB_HWBASE + EP93XX_APB_SYSCON,
                    825:                EP93XX_APB_SYSCON_SIZE, 0, &syscon_ioh);
                    826:        pwrcnt = bus_space_read_4(iot, syscon_ioh, EP93XX_SYSCON_PwrCnt);
                    827:        pwrcnt &= ~(PwrCnt_UARTBAUD);
                    828:        bus_space_write_4(iot, syscon_ioh, EP93XX_SYSCON_PwrCnt, pwrcnt);
                    829:        bus_space_unmap(iot, syscon_ioh, EP93XX_APB_SYSCON_SIZE);
                    830:
                    831:        bus_space_write_4(iot, ioh, EPCOM_LinCtrlLow, lcrlo);
                    832:        bus_space_write_4(iot, ioh, EPCOM_LinCtrlMid, lcrmid);
                    833:        bus_space_write_4(iot, ioh, EPCOM_LinCtrlHigh, lcrhi);
                    834:        bus_space_write_4(iot, ioh, EPCOM_Ctrl, ctrl);
                    835:
                    836:        return (0);
                    837: }
                    838:
                    839: void
1.6       christos  840: epcomcnprobe(struct consdev *cp)
1.1       joff      841: {
                    842:        cp->cn_pri = CN_REMOTE;
                    843: }
                    844:
                    845: void
1.6       christos  846: epcomcnpollc(dev_t dev, int on)
1.1       joff      847: {
                    848: }
                    849:
                    850: void
1.6       christos  851: epcomcnputc(dev_t dev, int c)
1.1       joff      852: {
                    853:        int                     s;
                    854:        bus_space_tag_t         iot = epcomcn_sc.sc_iot;
                    855:        bus_space_handle_t      ioh = epcomcn_sc.sc_ioh;
                    856:
                    857:        s = splserial();
                    858:
                    859:        while((bus_space_read_4(iot, ioh, EPCOM_Flag) & Flag_TXFF) != 0)
                    860:                ;
                    861:
                    862:        bus_space_write_4(iot, ioh, EPCOM_Data, c);
                    863:
                    864: #ifdef DEBUG
                    865:        if (c == '\r') {
                    866:                while((bus_space_read_4(iot, ioh, EPCOM_Flag) & Flag_TXFE) == 0)
                    867:                        ;
                    868:        }
                    869: #endif
                    870:
                    871:        splx(s);
                    872: }
                    873:
                    874: int
1.6       christos  875: epcomcngetc(dev_t dev)
1.1       joff      876: {
                    877:        int                     c, sts;
                    878:        int                     s;
                    879:        bus_space_tag_t         iot = epcomcn_sc.sc_iot;
                    880:        bus_space_handle_t      ioh = epcomcn_sc.sc_ioh;
                    881:
                    882:         s = splserial();
                    883:
                    884:        while((bus_space_read_4(iot, ioh, EPCOM_Flag) & Flag_RXFE) != 0)
                    885:                ;
                    886:
                    887:        c = bus_space_read_4(iot, ioh, EPCOM_Data);
                    888:        sts = bus_space_read_4(iot, ioh, EPCOM_RXSts);
                    889:        if (ISSET(sts, RXSts_BE)) c = CNC_BREAK;
                    890: #ifdef DDB
                    891:        extern int db_active;
                    892:        if (!db_active)
                    893: #endif
                    894:        {
                    895:                int cn_trapped = 0; /* unused */
                    896:
                    897:                cn_check_magic(dev, c, epcom_cnm_state);
                    898:        }
                    899:        c &= 0xff;
                    900:        splx(s);
                    901:
                    902:        return (c);
                    903: }
                    904:
                    905: inline static void
1.6       christos  906: epcom_txsoft(struct epcom_softc *sc, struct tty *tp)
1.1       joff      907: {
                    908:        CLR(tp->t_state, TS_BUSY);
                    909:        if (ISSET(tp->t_state, TS_FLUSH))
                    910:                CLR(tp->t_state, TS_FLUSH);
                    911:         else
                    912:                ndflush(&tp->t_outq, (int)(sc->sc_tba - tp->t_outq.c_cf));
                    913:        (*tp->t_linesw->l_start)(tp);
                    914: }
                    915:
                    916: inline static void
1.6       christos  917: epcom_rxsoft(struct epcom_softc *sc, struct tty *tp)
1.1       joff      918: {
1.3       he        919:        int (*rint) __P((int, struct tty *)) = tp->t_linesw->l_rint;
1.1       joff      920:        u_char *get, *end;
                    921:        u_int cc, scc;
                    922:        u_char sts;
                    923:        int code;
                    924:        int s;
                    925:
                    926:        end = sc->sc_ebuf;
                    927:        get = sc->sc_rbget;
                    928:        scc = cc = EPCOM_RING_SIZE - sc->sc_rbavail;
                    929: #if 0
                    930:        if (cc == EPCOM_RING_SIZE) {
                    931:                sc->sc_floods++;
                    932:                if (sc->sc_errors++ == 0)
                    933:                        callout_reset(&sc->sc_diag_callout, 60 * hz,
                    934:                            comdiag, sc);
                    935:        }
                    936: #endif
                    937:        while (cc) {
                    938:                code = get[0];
                    939:                sts = get[1];
                    940:                if (ISSET(sts, RXSts_OE | RXSts_FE | RXSts_PE | RXSts_BE)) {
                    941: #if 0
                    942:                        if (ISSET(lsr, DR_ROR)) {
                    943:                                sc->sc_overflows++;
                    944:                                if (sc->sc_errors++ == 0)
                    945:                                        callout_reset(&sc->sc_diag_callout,
                    946:                                            60 * hz, comdiag, sc);
                    947:                        }
                    948: #endif
                    949:                        if (ISSET(sts, (RXSts_FE|RXSts_BE)))
                    950:                                SET(code, TTY_FE);
                    951:                        if (ISSET(sts, RXSts_PE))
                    952:                                SET(code, TTY_PE);
                    953:                }
                    954:                if ((*rint)(code, tp) == -1) {
                    955:                        /*
                    956:                         * The line discipline's buffer is out of space.
                    957:                         */
                    958:                        if (!ISSET(sc->sc_rx_flags, RX_TTY_BLOCKED)) {
                    959:                                /*
                    960:                                 * We're either not using flow control, or the
                    961:                                 * line discipline didn't tell us to block for
                    962:                                 * some reason.  Either way, we have no way to
                    963:                                 * know when there's more space available, so
                    964:                                 * just drop the rest of the data.
                    965:                                 */
                    966:                                get += cc << 1;
                    967:                                if (get >= end)
                    968:                                        get -= EPCOM_RING_SIZE << 1;
                    969:                                cc = 0;
                    970:                        } else {
                    971:                                /*
                    972:                                 * Don't schedule any more receive processing
                    973:                                 * until the line discipline tells us there's
                    974:                                 * space available (through comhwiflow()).
                    975:                                 * Leave the rest of the data in the input
                    976:                                 * buffer.
                    977:                                 */
                    978:                                SET(sc->sc_rx_flags, RX_TTY_OVERFLOWED);
                    979:                        }
                    980:                        break;
                    981:                }
                    982:                get += 2;
                    983:                if (get >= end)
                    984:                        get = sc->sc_rbuf;
                    985:                cc--;
                    986:        }
                    987:
                    988:        if (cc != scc) {
                    989:                sc->sc_rbget = get;
                    990:                s = splserial();
                    991:
                    992:                cc = sc->sc_rbavail += scc - cc;
                    993:                /* Buffers should be ok again, release possible block. */
                    994:                if (cc >= 1) {
                    995:                        if (ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) {
                    996:                                CLR(sc->sc_rx_flags, RX_IBUF_OVERFLOWED);
                    997:                                SET(sc->sc_ctrl, (Ctrl_RIE|Ctrl_RTIE));
                    998:                                epcom_set(sc);
                    999:                        }
                   1000:                        if (ISSET(sc->sc_rx_flags, RX_IBUF_BLOCKED)) {
                   1001:                                CLR(sc->sc_rx_flags, RX_IBUF_BLOCKED);
                   1002: #if 0
                   1003:                                com_hwiflow(sc);
                   1004: #endif
                   1005:                        }
                   1006:                }
                   1007:                splx(s);
                   1008:        }
                   1009: }
                   1010:
                   1011: static void
                   1012: epcomsoft(void* arg)
                   1013: {
                   1014:        struct epcom_softc *sc = arg;
                   1015:
                   1016:        if (COM_ISALIVE(sc) == 0)
                   1017:                return;
                   1018:
                   1019:        if (sc->sc_rx_ready) {
                   1020:                sc->sc_rx_ready = 0;
                   1021:                epcom_rxsoft(sc, sc->sc_tty);
                   1022:        }
                   1023:        if (sc->sc_tx_done) {
                   1024:                sc->sc_tx_done = 0;
                   1025:                epcom_txsoft(sc, sc->sc_tty);
                   1026:        }
                   1027: }
                   1028:
                   1029: int
                   1030: epcomintr(void* arg)
                   1031: {
                   1032:        struct epcom_softc *sc = arg;
                   1033:        bus_space_tag_t iot = sc->sc_iot;
                   1034:        bus_space_handle_t ioh = sc->sc_ioh;
                   1035:        u_char *put, *end;
                   1036:        u_int cc;
                   1037:        u_int flagr;
                   1038:        u_int intr;
                   1039:        u_int32_t c, csts;
                   1040:
                   1041:        intr = bus_space_read_4(iot, ioh, EPCOM_IntIDIntClr);
                   1042:
                   1043:        if (COM_ISALIVE(sc) == 0)
                   1044:                panic("intr on disabled epcom");
                   1045:
                   1046:        flagr = bus_space_read_4(iot, ioh, EPCOM_Flag);
                   1047:
                   1048:        end = sc->sc_ebuf;
                   1049:        put = sc->sc_rbput;
                   1050:        cc = sc->sc_rbavail;
                   1051:
                   1052:        if (!(ISSET(flagr, Flag_RXFE))) {
                   1053:                if (!ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) {
                   1054:                        while (cc > 0) {
                   1055:                                if (ISSET(flagr, Flag_RXFE))
                   1056:                                        break;
                   1057:                                c = bus_space_read_4(iot, ioh, EPCOM_Data);
                   1058:                                csts = bus_space_read_4(iot, ioh, EPCOM_RXSts);
                   1059:                                if (ISSET(csts, RXSts_BE)) {
                   1060:                                        int cn_trapped = 0;
                   1061:
                   1062:                                        cn_check_magic(sc->sc_tty->t_dev,
                   1063:                                          CNC_BREAK, epcom_cnm_state);
                   1064:                                        if (cn_trapped)
                   1065:                                                goto next;
                   1066: #if defined(KGDB) && !defined(DDB)
                   1067:                                        if (ISSET(sc->sc_hwflags, COM_HW_KGDB)){
                   1068:                                                kgdb_connect(1);
                   1069:                                                goto next;
                   1070:                                        }
                   1071: #endif
                   1072:                                } else {
                   1073:                                        int cn_trapped = 0;
                   1074:
                   1075:                                        cn_check_magic(sc->sc_tty->t_dev,
                   1076:                                          (c & 0xff), epcom_cnm_state);
                   1077:                                        if (cn_trapped)
                   1078:                                                goto next;
                   1079:                                }
                   1080:
                   1081:
                   1082:                                put[0] = c & 0xff;
                   1083:                                put[1] = csts & 0xf;
                   1084:                                put += 2;
                   1085:                                if (put >= end)
                   1086:                                        put = sc->sc_rbuf;
                   1087:                                cc--;
                   1088:                        next:
                   1089:                                flagr = bus_space_read_4(iot, ioh, EPCOM_Flag);
                   1090:                        }
                   1091:
                   1092:                        /*
                   1093:                         * Current string of incoming characters ended because
                   1094:                         * no more data was available or we ran out of space.
                   1095:                         * Schedule a receive event if any data was received.
                   1096:                         * If we're out of space, turn off receive interrupts.
                   1097:                         */
                   1098:                        sc->sc_rbput = put;
                   1099:                        sc->sc_rbavail = cc;
                   1100:                        if (!ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED))
                   1101:                                sc->sc_rx_ready = 1;
                   1102:
                   1103:                        /*
                   1104:                         * See if we are in danger of overflowing a buffer. If
                   1105:                         * so, use hardware flow control to ease the pressure.
                   1106:                         */
                   1107:
                   1108:                        /* but epcom cannot. X-( */
                   1109:
                   1110:                        /*
                   1111:                         * If we're out of space, disable receive interrupts
                   1112:                         * until the queue has drained a bit.
                   1113:                         */
                   1114:                        if (!cc) {
                   1115:                                SET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED);
                   1116:                                CLR(sc->sc_ctrl, (Ctrl_RIE|Ctrl_RTIE));
                   1117:                                epcom_set(sc);
                   1118:                        }
                   1119:                } else {
                   1120: #ifdef DIAGNOSTIC
                   1121:                        panic("epcomintr: we shouldn't reach here");
                   1122: #endif
                   1123:                        CLR(sc->sc_ctrl, (Ctrl_RIE|Ctrl_RTIE));
                   1124:                        epcom_set(sc);
                   1125:                }
                   1126:        }
                   1127:
                   1128:        /*
                   1129:         * Done handling any receive interrupts. See if data can be
                   1130:         * transmitted as well. Schedule tx done event if no data left
                   1131:         * and tty was marked busy.
                   1132:         */
1.2       joff     1133:
                   1134:        if (!ISSET(flagr, Flag_TXFF) && sc->sc_tbc > 0) {
                   1135:                /* Output the next chunk of the contiguous buffer, if any. */
                   1136:                epcom_filltx(sc);
                   1137:        } else {
                   1138:                /* Disable transmit completion interrupts if necessary. */
                   1139:                if (ISSET(sc->sc_ctrl, Ctrl_TIE)) {
                   1140:                        CLR(sc->sc_ctrl, Ctrl_TIE);
1.1       joff     1141:                        epcom_set(sc);
                   1142:                }
1.2       joff     1143:                if (sc->sc_tx_busy) {
                   1144:                        sc->sc_tx_busy = 0;
                   1145:                        sc->sc_tx_done = 1;
1.1       joff     1146:                }
                   1147:        }
                   1148:
                   1149:        /* Wake up the poller. */
                   1150:        softintr_schedule(sc->sc_si);
                   1151:
                   1152: #if 0 /* XXX: broken */
                   1153: #if NRND > 0 && defined(RND_COM)
                   1154:        rnd_add_uint32(&sc->rnd_source, intr ^ flagr);
                   1155: #endif
                   1156: #endif
                   1157:        return (1);
                   1158: }

CVSweb <webmaster@jp.NetBSD.org>