[BACK]Return to pccom.c CVS log [TXT][DIR] Up to [local] / sys / arch / i386 / isa

Annotation of sys/arch/i386/isa/pccom.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: pccom.c,v 1.61 2007/05/09 14:32:17 deraadt Exp $      */
        !             2: /*     $NetBSD: com.c,v 1.82.4.1 1996/06/02 09:08:00 mrg Exp $ */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1997 - 1999, Jason Downs.  All rights reserved.
        !             6:  *
        !             7:  * Redistribution and use in source and binary forms, with or without
        !             8:  * modification, are permitted provided that the following conditions
        !             9:  * are met:
        !            10:  * 1. Redistributions of source code must retain the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer.
        !            12:  * 2. Redistributions in binary form must reproduce the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer in the
        !            14:  *    documentation and/or other materials provided with the distribution.
        !            15:  * 3. Neither the name(s) of the author(s) nor the name OpenBSD
        !            16:  *    may be used to endorse or promote products derived from this software
        !            17:  *    without specific prior written permission.
        !            18:  *
        !            19:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS
        !            20:  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
        !            21:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
        !            22:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT,
        !            23:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
        !            24:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
        !            25:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
        !            26:  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            27:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            28:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            29:  * SUCH DAMAGE.
        !            30:  */
        !            31: /*-
        !            32:  * Copyright (c) 1993, 1994, 1995, 1996
        !            33:  *     Charles M. Hannum.  All rights reserved.
        !            34:  * Copyright (c) 1991 The Regents of the University of California.
        !            35:  * All rights reserved.
        !            36:  *
        !            37:  * Redistribution and use in source and binary forms, with or without
        !            38:  * modification, are permitted provided that the following conditions
        !            39:  * are met:
        !            40:  * 1. Redistributions of source code must retain the above copyright
        !            41:  *    notice, this list of conditions and the following disclaimer.
        !            42:  * 2. Redistributions in binary form must reproduce the above copyright
        !            43:  *    notice, this list of conditions and the following disclaimer in the
        !            44:  *    documentation and/or other materials provided with the distribution.
        !            45:  * 3. Neither the name of the University nor the names of its contributors
        !            46:  *    may be used to endorse or promote products derived from this software
        !            47:  *    without specific prior written permission.
        !            48:  *
        !            49:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            50:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            51:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            52:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            53:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            54:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            55:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            56:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            57:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            58:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            59:  * SUCH DAMAGE.
        !            60:  *
        !            61:  *     @(#)com.c       7.5 (Berkeley) 5/16/91
        !            62:  */
        !            63:
        !            64: /*
        !            65:  * PCCOM driver, uses National Semiconductor NS16450/NS16550AF UART
        !            66:  */
        !            67: #include <sys/param.h>
        !            68: #include <sys/systm.h>
        !            69: #include <sys/ioctl.h>
        !            70: #include <sys/selinfo.h>
        !            71: #include <sys/tty.h>
        !            72: #include <sys/proc.h>
        !            73: #include <sys/user.h>
        !            74: #include <sys/conf.h>
        !            75: #include <sys/file.h>
        !            76: #include <sys/uio.h>
        !            77: #include <sys/kernel.h>
        !            78: #include <sys/syslog.h>
        !            79: #include <sys/types.h>
        !            80: #include <sys/device.h>
        !            81: #include <sys/vnode.h>
        !            82: #include <sys/timeout.h>
        !            83:
        !            84: #include <machine/bus.h>
        !            85: #include <machine/intr.h>
        !            86:
        !            87: #include <dev/cons.h>
        !            88: #include <dev/isa/isavar.h>
        !            89: #include <dev/ic/comreg.h>
        !            90: #include <dev/ic/ns16550reg.h>
        !            91: #define        com_lcr com_cfcr
        !            92: #ifdef DDB
        !            93: #include <ddb/db_var.h>
        !            94: #endif
        !            95:
        !            96: #include "pccomvar.h"
        !            97: #include "pccom.h"
        !            98:
        !            99: /* XXX: These belong elsewhere */
        !           100: cdev_decl(com);
        !           101:
        !           102: static u_char tiocm_xxx2mcr(int);
        !           103:
        !           104: void pccom_xr16850_fifo_init(bus_space_tag_t, bus_space_handle_t);
        !           105:
        !           106: /*
        !           107:  * XXX the following two cfattach structs should be different, and possibly
        !           108:  * XXX elsewhere.
        !           109:  */
        !           110: int    comprobe(struct device *, void *, void *);
        !           111: void   comattach(struct device *, struct device *, void *);
        !           112: void   compwroff(struct com_softc *);
        !           113:
        !           114: #if NPCCOM_ISA
        !           115: struct cfattach pccom_isa_ca = {
        !           116:        sizeof(struct com_softc), comprobe, comattach
        !           117: };
        !           118: #endif
        !           119:
        !           120: #if NPCCOM_ISAPNP
        !           121: struct cfattach pccom_isapnp_ca = {
        !           122:        sizeof(struct com_softc), comprobe, comattach
        !           123: };
        !           124: #endif
        !           125:
        !           126: #if NPCCOM_COMMULTI
        !           127: struct cfattach pccom_commulti_ca = {
        !           128:        sizeof(struct com_softc), comprobe, comattach
        !           129: };
        !           130: #endif
        !           131:
        !           132: struct cfdriver pccom_cd = {
        !           133:        NULL, "pccom", DV_TTY
        !           134: };
        !           135:
        !           136: void cominit(bus_space_tag_t, bus_space_handle_t, int);
        !           137:
        !           138: #ifndef CONSPEED
        !           139: #define        CONSPEED B9600
        !           140: #endif
        !           141:
        !           142: #if defined(COMCONSOLE) || defined(PCCOMCONSOLE)
        !           143: int    comdefaultrate = CONSPEED;              /* XXX why set default? */
        !           144: #else
        !           145: int    comdefaultrate = TTYDEF_SPEED;
        !           146: #endif
        !           147: bus_addr_t comconsaddr;
        !           148: int    comconsinit;
        !           149: int    comconsattached;
        !           150: bus_space_tag_t comconsiot;
        !           151: bus_space_handle_t comconsioh;
        !           152: tcflag_t comconscflag = TTYDEF_CFLAG;
        !           153:
        !           154: int    commajor;
        !           155: int    comsopen = 0;
        !           156:
        !           157: #ifdef KGDB
        !           158: #include <sys/kgdb.h>
        !           159:
        !           160: bus_addr_t com_kgdb_addr;
        !           161: bus_space_tag_t com_kgdb_iot;
        !           162: bus_space_handle_t com_kgdb_ioh;
        !           163:
        !           164: int    com_kgdb_getc(void *);
        !           165: void   com_kgdb_putc(void *, int);
        !           166: #endif /* KGDB */
        !           167:
        !           168: #define        DEVUNIT(x)      (minor(x) & 0x7f)
        !           169: #define        DEVCUA(x)       (minor(x) & 0x80)
        !           170:
        !           171: /* Macros for determining bus type. */
        !           172: #if NPCCOM_ISA || NPCCOM_PCMCIA
        !           173: #define IS_ISA(parent) \
        !           174:        (!strcmp((parent)->dv_cfdata->cf_driver->cd_name, "isa") || \
        !           175:         !strcmp((parent)->dv_cfdata->cf_driver->cd_name, "pcmcia"))
        !           176: #elif NPCCOM_ISA
        !           177: #define IS_ISA(parent) \
        !           178:        !strcmp((parent)->dv_cfdata->cf_driver->cd_name, "isa")
        !           179: #elif NPCCOM_ISAPNP
        !           180: #define IS_ISA(parent) 0
        !           181: #endif
        !           182:
        !           183: #if NPCCOM_ISAPNP
        !           184: #define IS_ISAPNP(parent) \
        !           185:         !strcmp((parent)->dv_cfdata->cf_driver->cd_name, "isapnp")
        !           186: #else
        !           187: #define IS_ISAPNP(parent)      0
        !           188: #endif
        !           189:
        !           190: int
        !           191: comspeed(long freq, long speed)
        !           192: {
        !           193: #define        divrnd(n, q)    (((n)*2/(q)+1)/2)       /* divide and round off */
        !           194:
        !           195:        int x, err;
        !           196:
        !           197:        if (speed == 0)
        !           198:                return 0;
        !           199:        if (speed < 0)
        !           200:                return -1;
        !           201:        x = divrnd((freq / 16), speed);
        !           202:        if (x <= 0)
        !           203:                return -1;
        !           204:        err = divrnd((quad_t)freq * 1000 / 16, speed * x) - 1000;
        !           205:        if (err < 0)
        !           206:                err = -err;
        !           207:        if (err > COM_TOLERANCE)
        !           208:                return -1;
        !           209:        return x;
        !           210:
        !           211: #undef divrnd
        !           212: }
        !           213:
        !           214: int
        !           215: comprobe1(bus_space_tag_t iot, bus_space_handle_t ioh)
        !           216: {
        !           217:        int i, k;
        !           218:
        !           219:        /* force access to id reg */
        !           220:        bus_space_write_1(iot, ioh, com_lcr, 0);
        !           221:        bus_space_write_1(iot, ioh, com_iir, 0);
        !           222:        for (i = 0; i < 32; i++) {
        !           223:                k = bus_space_read_1(iot, ioh, com_iir);
        !           224:                if (k & 0x38) {
        !           225:                        bus_space_read_1(iot, ioh, com_data); /* cleanup */
        !           226:                } else
        !           227:                        break;
        !           228:        }
        !           229:        if (i >= 32)
        !           230:            return 0;
        !           231:
        !           232:        return 1;
        !           233: }
        !           234:
        !           235: int
        !           236: comprobe(struct device *parent, void *match, void *aux)
        !           237: {
        !           238:        bus_space_tag_t iot;
        !           239:        bus_space_handle_t ioh;
        !           240:        int iobase, needioh;
        !           241:        int rv = 1;
        !           242:
        !           243:        /*
        !           244:         * XXX should be broken out into functions for isa probe and
        !           245:         * XXX for commulti probe, with a helper function that contains
        !           246:         * XXX most of the interesting stuff.
        !           247:         */
        !           248: /* #if NPCCOM_ISA || NPCCOM_PCMCIA || NPCCOM_ISAPNP */
        !           249: #if NPCCOM_ISA || NPCCOM_ISAPNP
        !           250:        if (IS_ISA(parent) || IS_ISAPNP(parent)) {
        !           251:                struct isa_attach_args *ia = aux;
        !           252:
        !           253:                iot = ia->ia_iot;
        !           254:                iobase = ia->ia_iobase;
        !           255:                if (IS_ISAPNP(parent)) {
        !           256:                        ioh = ia->ia_ioh;
        !           257:                        needioh = 0;
        !           258:                } else
        !           259:                        needioh = 1;
        !           260:        } else
        !           261: #endif
        !           262: #if NPCCOM_COMMULTI
        !           263:        if (1) {
        !           264:                struct cfdata *cf = match;
        !           265:                struct commulti_attach_args *ca = aux;
        !           266:
        !           267:                if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != ca->ca_slave)
        !           268:                        return (0);
        !           269:
        !           270:                iot = ca->ca_iot;
        !           271:                iobase = ca->ca_iobase;
        !           272:                ioh = ca->ca_ioh;
        !           273:                needioh = 0;
        !           274:        } else
        !           275: #endif
        !           276:                return(0);                      /* This cannot happen */
        !           277:
        !           278: #ifdef KGDB
        !           279:        if (iobase == com_kgdb_addr)
        !           280:                goto out;
        !           281: #endif /* KGDB */
        !           282:
        !           283:        /* if it's in use as console, it's there. */
        !           284:        if (iobase == comconsaddr && !comconsattached)
        !           285:                goto out;
        !           286:
        !           287:        if (needioh && bus_space_map(iot, iobase, COM_NPORTS, 0, &ioh)) {
        !           288:                rv = 0;
        !           289:                goto out;
        !           290:        }
        !           291:        rv = comprobe1(iot, ioh);
        !           292:        if (needioh)
        !           293:                bus_space_unmap(iot, ioh, COM_NPORTS);
        !           294:
        !           295: out:
        !           296: /* #if NPCCOM_ISA || NPCCOM_PCMCIA */
        !           297: #if NPCCOM_ISA
        !           298:        if (rv) {
        !           299:                struct isa_attach_args *ia = aux;
        !           300:
        !           301:                ia->ia_iosize = COM_NPORTS;
        !           302:                ia->ia_msize = 0;
        !           303:        }
        !           304: #endif
        !           305:        return (rv);
        !           306: }
        !           307:
        !           308: void
        !           309: comattach(struct device *parent, struct device *self, void *aux)
        !           310: {
        !           311:        struct com_softc *sc = (void *)self;
        !           312:        bus_addr_t iobase;
        !           313:        bus_space_tag_t iot;
        !           314:        bus_space_handle_t ioh;
        !           315:        int irq;
        !           316:
        !           317:        /*
        !           318:         * XXX should be broken out into functions for isa attach and
        !           319:         * XXX for commulti attach, with a helper function that contains
        !           320:         * XXX most of the interesting stuff.
        !           321:         */
        !           322: /* #if NPCCOM_ISA || NPCCOM_PCMCIA || NPCCOM_ISAPNP */
        !           323: #if NPCCOM_ISA || NPCCOM_ISAPNP
        !           324:        if (IS_ISA(parent) || IS_ISAPNP(parent)) {
        !           325:                struct isa_attach_args *ia = aux;
        !           326:
        !           327:                /*
        !           328:                 * We're living on an isa.
        !           329:                 */
        !           330:                iobase = ia->ia_iobase;
        !           331:                iot = ia->ia_iot;
        !           332:                if (IS_ISAPNP(parent)) {
        !           333:                        /* No console support! */
        !           334:                        ioh = ia->ia_ioh;
        !           335:                } else {
        !           336: #ifdef KGDB
        !           337:                        if ((iobase != comconsaddr) &&
        !           338:                            (iobase != com_kgdb_addr)) {
        !           339: #else
        !           340:                        if (iobase != comconsaddr) {
        !           341: #endif /* KGDB */
        !           342:                                if (bus_space_map(iot, iobase, COM_NPORTS, 0, &ioh))
        !           343:                                        panic("comattach: io mapping failed");
        !           344:                        } else
        !           345: #ifdef KGDB
        !           346:                                if (iobase == comconsaddr) {
        !           347:                                        ioh = comconsioh;
        !           348:                                } else {
        !           349:                                        ioh = com_kgdb_ioh;
        !           350:                                }
        !           351: #else
        !           352:                                ioh = comconsioh;
        !           353: #endif /* KGDB */
        !           354:                }
        !           355:                irq = ia->ia_irq;
        !           356:        } else
        !           357: #endif
        !           358: #if NPCCOM_COMMULTI
        !           359:        if (1) {
        !           360:                struct commulti_attach_args *ca = aux;
        !           361:
        !           362:                /*
        !           363:                 * We're living on a commulti.
        !           364:                 */
        !           365:                iobase = ca->ca_iobase;
        !           366:                iot = ca->ca_iot;
        !           367:                ioh = ca->ca_ioh;
        !           368:                irq = IRQUNK;
        !           369:
        !           370:                if (ca->ca_noien)
        !           371:                        SET(sc->sc_hwflags, COM_HW_NOIEN);
        !           372:        } else
        !           373: #endif
        !           374:                panic("comattach: impossible");
        !           375:
        !           376:        sc->sc_iot = iot;
        !           377:        sc->sc_ioh = ioh;
        !           378:        sc->sc_iobase = iobase;
        !           379:        sc->sc_frequency = COM_FREQ;
        !           380:
        !           381:        sc->sc_hwflags = 0;
        !           382:        sc->sc_swflags = 0;
        !           383:
        !           384:        if (irq != IRQUNK) {
        !           385:                /* disable interrupts */
        !           386:                bus_space_write_1(iot, ioh, com_ier, 0);
        !           387:
        !           388: /* #if NPCCOM_ISA || NPCCOM_PCMCIA || NPCCOM_ISAPNP */
        !           389: #if NPCCOM_ISA || NPCCOM_ISAPNP
        !           390:                if (IS_ISA(parent) || IS_ISAPNP(parent)) {
        !           391:                        struct isa_attach_args *ia = aux;
        !           392:
        !           393: #ifdef KGDB
        !           394:                        if (iobase == com_kgdb_addr) {
        !           395:                                sc->sc_ih = isa_intr_establish(ia->ia_ic, irq,
        !           396:                                    IST_EDGE, IPL_HIGH, kgdbintr, sc,
        !           397:                                    sc->sc_dev.dv_xname);
        !           398:                        } else {
        !           399:                                sc->sc_ih = isa_intr_establish(ia->ia_ic, irq,
        !           400:                                    IST_EDGE, IPL_HIGH, comintr, sc,
        !           401:                                    sc->sc_dev.dv_xname);
        !           402:                        }
        !           403: #else
        !           404:                        sc->sc_ih = isa_intr_establish(ia->ia_ic, irq,
        !           405:                            IST_EDGE, IPL_HIGH, comintr, sc,
        !           406:                            sc->sc_dev.dv_xname);
        !           407: #endif /* KGDB */
        !           408:                } else
        !           409: #endif
        !           410:                        panic("comattach: IRQ but can't have one");
        !           411:        }
        !           412:
        !           413:        com_attach_subr(sc);
        !           414: }
        !           415:
        !           416: int
        !           417: com_detach(struct device *self, int flags)
        !           418: {
        !           419:        struct com_softc *sc = (struct com_softc *)self;
        !           420:        int maj, mn;
        !           421:
        !           422:        /* locate the major number */
        !           423:        for (maj = 0; maj < nchrdev; maj++)
        !           424:                if (cdevsw[maj].d_open == comopen)
        !           425:                        break;
        !           426:
        !           427:        /* Nuke the vnodes for any open instances. */
        !           428:        mn = self->dv_unit;
        !           429:        vdevgone(maj, mn, mn, VCHR);
        !           430:
        !           431:        /* XXX a symbolic constant for the cua bit would be nicer. */
        !           432:        mn |= 0x80;
        !           433:        vdevgone(maj, mn, mn, VCHR);
        !           434:
        !           435:        /* Detach and free the tty. */
        !           436:        if (sc->sc_tty) {
        !           437:                ttyfree(sc->sc_tty);
        !           438:        }
        !           439:
        !           440:        timeout_del(&sc->sc_dtr_tmo);
        !           441:        timeout_del(&sc->sc_diag_tmo);
        !           442:
        !           443:        return (0);
        !           444: }
        !           445:
        !           446: int
        !           447: com_activate(struct device *self, enum devact act)
        !           448: {
        !           449:        struct com_softc *sc = (struct com_softc *)self;
        !           450:        int s, rv = 0;
        !           451:
        !           452:        /* XXX splserial, when we get that.  */
        !           453:        s = spltty();
        !           454:        switch (act) {
        !           455:        case DVACT_ACTIVATE:
        !           456:                break;
        !           457:
        !           458:        case DVACT_DEACTIVATE:
        !           459: #ifdef KGDB
        !           460:                if (sc->sc_hwflags & (COM_HW_CONSOLE|COM_HW_KGDB)) {
        !           461: #else
        !           462:                if (sc->sc_hwflags & COM_HW_CONSOLE) {
        !           463: #endif /* KGDB */
        !           464:                        rv = EBUSY;
        !           465:                        break;
        !           466:                }
        !           467:
        !           468:                if (sc->disable != NULL && sc->enabled != 0) {
        !           469:                        (*sc->disable)(sc);
        !           470:                        sc->enabled = 0;
        !           471:                }
        !           472:                break;
        !           473:        }
        !           474:        splx(s);
        !           475:        return (rv);
        !           476: }
        !           477:
        !           478: int
        !           479: comopen(dev_t dev, int flag, int mode, struct proc *p)
        !           480: {
        !           481:        int unit = DEVUNIT(dev);
        !           482:        struct com_softc *sc;
        !           483:        bus_space_tag_t iot;
        !           484:        bus_space_handle_t ioh;
        !           485:        struct tty *tp;
        !           486:        int s;
        !           487:        int error = 0;
        !           488:
        !           489:        if (unit >= pccom_cd.cd_ndevs)
        !           490:                return ENXIO;
        !           491:        sc = pccom_cd.cd_devs[unit];
        !           492:        if (!sc)
        !           493:                return ENXIO;
        !           494:
        !           495: #ifdef KGDB
        !           496:        /*
        !           497:         * If this is the kgdb port, no other use is permitted.
        !           498:         */
        !           499:        if (ISSET(sc->sc_hwflags, COM_HW_KGDB))
        !           500:                return (EBUSY);
        !           501: #endif /* KGDB */
        !           502:
        !           503:        s = spltty();
        !           504:        if (!sc->sc_tty) {
        !           505:                tp = sc->sc_tty = ttymalloc();
        !           506:        } else
        !           507:                tp = sc->sc_tty;
        !           508:        splx(s);
        !           509:
        !           510:        tp->t_oproc = comstart;
        !           511:        tp->t_param = comparam;
        !           512:        tp->t_hwiflow = comhwiflow;
        !           513:        tp->t_dev = dev;
        !           514:        if (!ISSET(tp->t_state, TS_ISOPEN)) {
        !           515:                SET(tp->t_state, TS_WOPEN);
        !           516:                ttychars(tp);
        !           517:                tp->t_iflag = TTYDEF_IFLAG;
        !           518:                tp->t_oflag = TTYDEF_OFLAG;
        !           519:                if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
        !           520:                        tp->t_cflag = comconscflag;
        !           521:                else
        !           522:                        tp->t_cflag = TTYDEF_CFLAG;
        !           523:                if (ISSET(sc->sc_swflags, COM_SW_CLOCAL))
        !           524:                        SET(tp->t_cflag, CLOCAL);
        !           525:                if (ISSET(sc->sc_swflags, COM_SW_CRTSCTS))
        !           526:                        SET(tp->t_cflag, CRTSCTS);
        !           527:                if (ISSET(sc->sc_swflags, COM_SW_MDMBUF))
        !           528:                        SET(tp->t_cflag, MDMBUF);
        !           529:                tp->t_lflag = TTYDEF_LFLAG;
        !           530:                tp->t_ispeed = tp->t_ospeed = comdefaultrate;
        !           531:
        !           532:                s = spltty();
        !           533:
        !           534:                iot = sc->sc_iot;
        !           535:                ioh = sc->sc_ioh;
        !           536:
        !           537:                /*
        !           538:                 * Wake up the sleepy heads.
        !           539:                 */
        !           540:                switch (sc->sc_uarttype) {
        !           541:                case COM_UART_ST16650:
        !           542:                case COM_UART_ST16650V2:
        !           543:                case COM_UART_ST16C654:
        !           544:                case COM_UART_XR16850:
        !           545:                case COM_UART_OX16C950:
        !           546:                        bus_space_write_1(iot, ioh, com_lcr, LCR_EFR);
        !           547:                        bus_space_write_1(iot, ioh, com_efr, EFR_ECB);
        !           548:                        bus_space_write_1(iot, ioh, com_ier, 0);
        !           549:                        bus_space_write_1(iot, ioh, com_efr, 0);
        !           550:                        bus_space_write_1(iot, ioh, com_lcr, 0);
        !           551:                        break;
        !           552:                case COM_UART_TI16750:
        !           553:                        bus_space_write_1(iot, ioh, com_ier, 0);
        !           554:                        break;
        !           555:                }
        !           556:
        !           557:                sc->sc_initialize = 1;
        !           558:                comparam(tp, &tp->t_termios);
        !           559:                ttsetwater(tp);
        !           560:
        !           561:                sc->sc_rxput = sc->sc_rxget = sc->sc_tbc = 0;
        !           562:
        !           563:                if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
        !           564:                        u_int8_t fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST;
        !           565:                        u_int8_t lcr;
        !           566:
        !           567:                        switch (sc->sc_uarttype) {
        !           568:                        case COM_UART_ST16650V2:
        !           569:                                if (tp->t_ispeed <= 1200)
        !           570:                                        fifo |= FIFO_RCV_TRIGGER_8|FIFO_XMT_TRIGGER_8; /* XXX */
        !           571:                                else
        !           572:                                        fifo |= FIFO_RCV_TRIGGER_28|FIFO_XMT_TRIGGER_30;
        !           573:                                break;
        !           574:                        case COM_UART_ST16C654:
        !           575:                                if (tp->t_ispeed <= 1200)
        !           576:                                        fifo |= FIFO_RCV3_TRIGGER_8|FIFO_XMT3_TRIGGER_8; /* XXX */
        !           577:                                else
        !           578:                                        fifo |= FIFO_RCV3_TRIGGER_60|FIFO_XMT3_TRIGGER_56;
        !           579:                                break;
        !           580:                        case COM_UART_XR16850:
        !           581:                        case COM_UART_OX16C950:
        !           582:                                pccom_xr16850_fifo_init(iot, ioh);
        !           583:                                if (tp->t_ispeed <= 1200)
        !           584:                                        fifo |= FIFO_RCV3_TRIGGER_8|FIFO_XMT3_TRIGGER_8; /* XXX */
        !           585:                                else
        !           586:                                        fifo |= FIFO_RCV3_TRIGGER_60|FIFO_XMT3_TRIGGER_56;
        !           587:                                break;
        !           588:                        case COM_UART_TI16750:
        !           589:                                fifo |= FIFO_ENABLE_64BYTE;
        !           590:                                lcr = bus_space_read_1(iot, ioh, com_lcr);
        !           591:                                bus_space_write_1(iot, ioh, com_lcr,
        !           592:                                    lcr | LCR_DLAB);
        !           593:                        default:
        !           594:                                if (tp->t_ispeed <= 1200)
        !           595:                                        fifo |= FIFO_TRIGGER_1;
        !           596:                                else
        !           597:                                        fifo |= FIFO_TRIGGER_8;
        !           598:                        }
        !           599:
        !           600:                        /*
        !           601:                         * (Re)enable and drain FIFOs.
        !           602:                         *
        !           603:                         * Certain SMC chips cause problems if the FIFOs are
        !           604:                         * enabled while input is ready. Turn off the FIFO
        !           605:                         * if necessary to clear the input. Test the input
        !           606:                         * ready bit after enabling the FIFOs to handle races
        !           607:                         * between enabling and fresh input.
        !           608:                         *
        !           609:                         * Set the FIFO threshold based on the receive speed.
        !           610:                         */
        !           611:                        for (;;) {
        !           612:                                bus_space_write_1(iot, ioh, com_fifo, 0);
        !           613:                                delay(100);
        !           614:                                (void) bus_space_read_1(iot, ioh, com_data);
        !           615:                                bus_space_write_1(iot, ioh, com_fifo, fifo |
        !           616:                                    FIFO_RCV_RST | FIFO_XMT_RST);
        !           617:                                delay(100);
        !           618:                                if(!ISSET(bus_space_read_1(iot, ioh,
        !           619:                                    com_lsr), LSR_RXRDY))
        !           620:                                        break;
        !           621:                        }
        !           622:                        if (sc->sc_uarttype == COM_UART_TI16750)
        !           623:                                bus_space_write_1(iot, ioh, com_lcr, lcr);
        !           624:                }
        !           625:
        !           626:                /* flush any pending I/O */
        !           627:                while (ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY))
        !           628:                        (void) bus_space_read_1(iot, ioh, com_data);
        !           629:                /* you turn me on, baby */
        !           630:                sc->sc_mcr = MCR_DTR | MCR_RTS;
        !           631:                if (!ISSET(sc->sc_hwflags, COM_HW_NOIEN))
        !           632:                        SET(sc->sc_mcr, MCR_IENABLE);
        !           633:                bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
        !           634:                sc->sc_ier = IER_ERXRDY | IER_ERLS | IER_EMSC;
        !           635:                bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
        !           636:
        !           637:                sc->sc_msr = bus_space_read_1(iot, ioh, com_msr);
        !           638:                if (ISSET(sc->sc_swflags, COM_SW_SOFTCAR) || DEVCUA(dev) ||
        !           639:                    ISSET(sc->sc_msr, MSR_DCD) || ISSET(tp->t_cflag, MDMBUF))
        !           640:                        SET(tp->t_state, TS_CARR_ON);
        !           641:                else
        !           642:                        CLR(tp->t_state, TS_CARR_ON);
        !           643:        } else if (ISSET(tp->t_state, TS_XCLUDE) && p->p_ucred->cr_uid != 0)
        !           644:                return EBUSY;
        !           645:        else
        !           646:                s = spltty();
        !           647:
        !           648:        if (DEVCUA(dev)) {
        !           649:                if (ISSET(tp->t_state, TS_ISOPEN)) {
        !           650:                        /* Ah, but someone already is dialed in... */
        !           651:                        splx(s);
        !           652:                        return EBUSY;
        !           653:                }
        !           654:                sc->sc_cua = 1;         /* We go into CUA mode */
        !           655:        } else {
        !           656:                /* tty (not cua) device; wait for carrier if necessary */
        !           657:                if (ISSET(flag, O_NONBLOCK)) {
        !           658:                        if (sc->sc_cua) {
        !           659:                                /* Opening TTY non-blocking... but the CUA is busy */
        !           660:                                splx(s);
        !           661:                                return EBUSY;
        !           662:                        }
        !           663:                } else {
        !           664:                        while (sc->sc_cua ||
        !           665:                               (!ISSET(tp->t_cflag, CLOCAL) &&
        !           666:                                !ISSET(tp->t_state, TS_CARR_ON))) {
        !           667:                                SET(tp->t_state, TS_WOPEN);
        !           668:                                error = ttysleep(tp, &tp->t_rawq, TTIPRI | PCATCH, ttopen, 0);
        !           669:                                /*
        !           670:                                 * If TS_WOPEN has been reset, that means the cua device
        !           671:                                 * has been closed.  We don't want to fail in that case,
        !           672:                                 * so just go around again.
        !           673:                                 */
        !           674:                                if (error && ISSET(tp->t_state, TS_WOPEN)) {
        !           675:                                        CLR(tp->t_state, TS_WOPEN);
        !           676:                                        if (!sc->sc_cua && !ISSET(tp->t_state, TS_ISOPEN))
        !           677:                                                compwroff(sc);
        !           678:                                        splx(s);
        !           679:                                        return error;
        !           680:                                }
        !           681:                        }
        !           682:                }
        !           683:        }
        !           684:        splx(s);
        !           685:        return (*linesw[tp->t_line].l_open)(dev, tp);
        !           686: }
        !           687:
        !           688: int
        !           689: comclose(dev_t dev, int flag, int mode, struct proc *p)
        !           690: {
        !           691:        int unit = DEVUNIT(dev);
        !           692:        struct com_softc *sc = pccom_cd.cd_devs[unit];
        !           693:        bus_space_tag_t iot = sc->sc_iot;
        !           694:        bus_space_handle_t ioh = sc->sc_ioh;
        !           695:        struct tty *tp = sc->sc_tty;
        !           696:        int s;
        !           697:
        !           698:        /* XXX This is for cons.c. */
        !           699:        if (!ISSET(tp->t_state, TS_ISOPEN))
        !           700:                return 0;
        !           701:
        !           702:        (*linesw[tp->t_line].l_close)(tp, flag);
        !           703:        s = spltty();
        !           704:        if (ISSET(tp->t_state, TS_WOPEN)) {
        !           705:                /* tty device is waiting for carrier; drop dtr then re-raise */
        !           706:                CLR(sc->sc_mcr, MCR_DTR | MCR_RTS);
        !           707:                bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
        !           708:                timeout_add(&sc->sc_dtr_tmo, hz * 2);
        !           709:        } else {
        !           710:                /* no one else waiting; turn off the uart */
        !           711:                compwroff(sc);
        !           712:        }
        !           713:        CLR(tp->t_state, TS_BUSY | TS_FLUSH);
        !           714:        sc->sc_cua = 0;
        !           715:        splx(s);
        !           716:        ttyclose(tp);
        !           717:
        !           718: #ifdef notyet /* XXXX */
        !           719:        if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
        !           720:                ttyfree(tp);
        !           721:                sc->sc_tty = 0;
        !           722:        }
        !           723: #endif
        !           724:        return 0;
        !           725: }
        !           726:
        !           727: void
        !           728: compwroff(struct com_softc *sc)
        !           729: {
        !           730:        bus_space_tag_t iot = sc->sc_iot;
        !           731:        bus_space_handle_t ioh = sc->sc_ioh;
        !           732:        struct tty *tp = sc->sc_tty;
        !           733:
        !           734:        CLR(sc->sc_lcr, LCR_SBREAK);
        !           735:        bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr);
        !           736:        bus_space_write_1(iot, ioh, com_ier, 0);
        !           737:        if (ISSET(tp->t_cflag, HUPCL) &&
        !           738:            !ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) {
        !           739:                /* XXX perhaps only clear DTR */
        !           740:                sc->sc_mcr = 0;
        !           741:                bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
        !           742:        }
        !           743:
        !           744:        /*
        !           745:         * Turn FIFO off; enter sleep mode if possible.
        !           746:         */
        !           747:        bus_space_write_1(iot, ioh, com_fifo, 0);
        !           748:        delay(100);
        !           749:        (void) bus_space_read_1(iot, ioh, com_data);
        !           750:        delay(100);
        !           751:        bus_space_write_1(iot, ioh, com_fifo,
        !           752:                          FIFO_RCV_RST | FIFO_XMT_RST);
        !           753:
        !           754:        switch (sc->sc_uarttype) {
        !           755:        case COM_UART_ST16650:
        !           756:        case COM_UART_ST16650V2:
        !           757:        case COM_UART_ST16C654:
        !           758:        case COM_UART_XR16850:
        !           759:        case COM_UART_OX16C950:
        !           760:                bus_space_write_1(iot, ioh, com_lcr, LCR_EFR);
        !           761:                bus_space_write_1(iot, ioh, com_efr, EFR_ECB);
        !           762:                bus_space_write_1(iot, ioh, com_ier, IER_SLEEP);
        !           763:                bus_space_write_1(iot, ioh, com_lcr, 0);
        !           764:                break;
        !           765:        case COM_UART_TI16750:
        !           766:                bus_space_write_1(iot, ioh, com_ier, IER_SLEEP);
        !           767:                break;
        !           768:        }
        !           769: }
        !           770:
        !           771: void
        !           772: com_raisedtr(void *arg)
        !           773: {
        !           774:        struct com_softc *sc = arg;
        !           775:
        !           776:        SET(sc->sc_mcr, MCR_DTR | MCR_RTS);
        !           777:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_mcr, sc->sc_mcr);
        !           778: }
        !           779:
        !           780: int
        !           781: comread(dev_t dev, struct uio *uio, int flag)
        !           782: {
        !           783:        struct com_softc *sc = pccom_cd.cd_devs[DEVUNIT(dev)];
        !           784:        struct tty *tp = sc->sc_tty;
        !           785:
        !           786:        return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
        !           787: }
        !           788:
        !           789: int
        !           790: comwrite(dev_t dev, struct uio *uio, int flag)
        !           791: {
        !           792:        struct com_softc *sc = pccom_cd.cd_devs[DEVUNIT(dev)];
        !           793:        struct tty *tp = sc->sc_tty;
        !           794:
        !           795:        return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
        !           796: }
        !           797:
        !           798: struct tty *
        !           799: comtty(dev_t dev)
        !           800: {
        !           801:        struct com_softc *sc = pccom_cd.cd_devs[DEVUNIT(dev)];
        !           802:        struct tty *tp = sc->sc_tty;
        !           803:
        !           804:        return (tp);
        !           805: }
        !           806:
        !           807: static u_char
        !           808: tiocm_xxx2mcr(int data)
        !           809: {
        !           810:        u_char m = 0;
        !           811:
        !           812:        if (ISSET(data, TIOCM_DTR))
        !           813:                SET(m, MCR_DTR);
        !           814:        if (ISSET(data, TIOCM_RTS))
        !           815:                SET(m, MCR_RTS);
        !           816:        return m;
        !           817: }
        !           818:
        !           819: int
        !           820: comioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
        !           821: {
        !           822:        int unit = DEVUNIT(dev);
        !           823:        struct com_softc *sc = pccom_cd.cd_devs[unit];
        !           824:        struct tty *tp = sc->sc_tty;
        !           825:        bus_space_tag_t iot = sc->sc_iot;
        !           826:        bus_space_handle_t ioh = sc->sc_ioh;
        !           827:        int error;
        !           828:
        !           829:        error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
        !           830:        if (error >= 0)
        !           831:                return error;
        !           832:        error = ttioctl(tp, cmd, data, flag, p);
        !           833:        if (error >= 0)
        !           834:                return error;
        !           835:
        !           836:        switch (cmd) {
        !           837:        case TIOCSBRK:
        !           838:                SET(sc->sc_lcr, LCR_SBREAK);
        !           839:                bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr);
        !           840:                break;
        !           841:        case TIOCCBRK:
        !           842:                CLR(sc->sc_lcr, LCR_SBREAK);
        !           843:                bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr);
        !           844:                break;
        !           845:        case TIOCSDTR:
        !           846:                SET(sc->sc_mcr, sc->sc_dtr);
        !           847:                bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
        !           848:                break;
        !           849:        case TIOCCDTR:
        !           850:                CLR(sc->sc_mcr, sc->sc_dtr);
        !           851:                bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
        !           852:                break;
        !           853:        case TIOCMSET:
        !           854:                CLR(sc->sc_mcr, MCR_DTR | MCR_RTS);
        !           855:        case TIOCMBIS:
        !           856:                SET(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
        !           857:                bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
        !           858:                break;
        !           859:        case TIOCMBIC:
        !           860:                CLR(sc->sc_mcr, tiocm_xxx2mcr(*(int *)data));
        !           861:                bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
        !           862:                break;
        !           863:        case TIOCMGET: {
        !           864:                u_char m;
        !           865:                int bits = 0;
        !           866:
        !           867:                m = sc->sc_mcr;
        !           868:                if (ISSET(m, MCR_DTR))
        !           869:                        SET(bits, TIOCM_DTR);
        !           870:                if (ISSET(m, MCR_RTS))
        !           871:                        SET(bits, TIOCM_RTS);
        !           872:                m = sc->sc_msr;
        !           873:                if (ISSET(m, MSR_DCD))
        !           874:                        SET(bits, TIOCM_CD);
        !           875:                if (ISSET(m, MSR_CTS))
        !           876:                        SET(bits, TIOCM_CTS);
        !           877:                if (ISSET(m, MSR_DSR))
        !           878:                        SET(bits, TIOCM_DSR);
        !           879:                if (ISSET(m, MSR_RI | MSR_TERI))
        !           880:                        SET(bits, TIOCM_RI);
        !           881:                if (bus_space_read_1(iot, ioh, com_ier))
        !           882:                        SET(bits, TIOCM_LE);
        !           883:                *(int *)data = bits;
        !           884:                break;
        !           885:        }
        !           886:        case TIOCGFLAGS: {
        !           887:                int driverbits, userbits = 0;
        !           888:
        !           889:                driverbits = sc->sc_swflags;
        !           890:                if (ISSET(driverbits, COM_SW_SOFTCAR))
        !           891:                        SET(userbits, TIOCFLAG_SOFTCAR);
        !           892:                if (ISSET(driverbits, COM_SW_CLOCAL))
        !           893:                        SET(userbits, TIOCFLAG_CLOCAL);
        !           894:                if (ISSET(driverbits, COM_SW_CRTSCTS))
        !           895:                        SET(userbits, TIOCFLAG_CRTSCTS);
        !           896:                if (ISSET(driverbits, COM_SW_MDMBUF))
        !           897:                        SET(userbits, TIOCFLAG_MDMBUF);
        !           898:
        !           899:                *(int *)data = userbits;
        !           900:                break;
        !           901:        }
        !           902:        case TIOCSFLAGS: {
        !           903:                int userbits, driverbits = 0;
        !           904:
        !           905:                error = suser(p, 0);
        !           906:                if (error != 0)
        !           907:                        return(EPERM);
        !           908:
        !           909:                userbits = *(int *)data;
        !           910:                if (ISSET(userbits, TIOCFLAG_SOFTCAR) ||
        !           911:                    ISSET(sc->sc_hwflags, COM_HW_CONSOLE))
        !           912:                        SET(driverbits, COM_SW_SOFTCAR);
        !           913:                if (ISSET(userbits, TIOCFLAG_CLOCAL))
        !           914:                        SET(driverbits, COM_SW_CLOCAL);
        !           915:                if (ISSET(userbits, TIOCFLAG_CRTSCTS))
        !           916:                        SET(driverbits, COM_SW_CRTSCTS);
        !           917:                if (ISSET(userbits, TIOCFLAG_MDMBUF))
        !           918:                        SET(driverbits, COM_SW_MDMBUF);
        !           919:
        !           920:                sc->sc_swflags = driverbits;
        !           921:                break;
        !           922:        }
        !           923:        default:
        !           924:                return ENOTTY;
        !           925:        }
        !           926:
        !           927:        return 0;
        !           928: }
        !           929:
        !           930: int
        !           931: comparam(struct tty *tp, struct termios *t)
        !           932: {
        !           933:        struct com_softc *sc = pccom_cd.cd_devs[DEVUNIT(tp->t_dev)];
        !           934:        bus_space_tag_t iot = sc->sc_iot;
        !           935:        bus_space_handle_t ioh = sc->sc_ioh;
        !           936:        int ospeed = comspeed(sc->sc_frequency, t->c_ospeed);
        !           937:        u_int8_t lcr;
        !           938:        tcflag_t oldcflag;
        !           939:        int s;
        !           940:
        !           941:        /* check requested parameters */
        !           942:        if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
        !           943:                return EINVAL;
        !           944:
        !           945:        lcr = ISSET(sc->sc_lcr, LCR_SBREAK);
        !           946:
        !           947:        switch (ISSET(t->c_cflag, CSIZE)) {
        !           948:        case CS5:
        !           949:                SET(lcr, LCR_5BITS);
        !           950:                break;
        !           951:        case CS6:
        !           952:                SET(lcr, LCR_6BITS);
        !           953:                break;
        !           954:        case CS7:
        !           955:                SET(lcr, LCR_7BITS);
        !           956:                break;
        !           957:        case CS8:
        !           958:                SET(lcr, LCR_8BITS);
        !           959:                break;
        !           960:        }
        !           961:        if (ISSET(t->c_cflag, PARENB)) {
        !           962:                SET(lcr, LCR_PENAB);
        !           963:                if (!ISSET(t->c_cflag, PARODD))
        !           964:                        SET(lcr, LCR_PEVEN);
        !           965:        }
        !           966:        if (ISSET(t->c_cflag, CSTOPB))
        !           967:                SET(lcr, LCR_STOPB);
        !           968:
        !           969:        sc->sc_lcr = lcr;
        !           970:
        !           971:        s = spltty();
        !           972:
        !           973:        if (ospeed == 0) {
        !           974:                CLR(sc->sc_mcr, MCR_DTR);
        !           975:                bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
        !           976:        }
        !           977:
        !           978:        /*
        !           979:         * Set the FIFO threshold based on the receive speed, if we are
        !           980:         * changing it.
        !           981:         */
        !           982:        if (sc->sc_initialize || (tp->t_ispeed != t->c_ispeed)) {
        !           983:                sc->sc_initialize = 0;
        !           984:
        !           985:                if (ospeed != 0) {
        !           986:                        /*
        !           987:                         * Make sure the transmit FIFO is empty before
        !           988:                         * proceeding.  If we don't do this, some revisions
        !           989:                         * of the UART will hang.  Interestingly enough,
        !           990:                         * even if we do this while the last character is
        !           991:                         * still being pushed out, they don't hang.  This
        !           992:                         * seems good enough.
        !           993:                         */
        !           994:                        while (ISSET(tp->t_state, TS_BUSY)) {
        !           995:                                int error;
        !           996:
        !           997:                                ++sc->sc_halt;
        !           998:                                error = ttysleep(tp, &tp->t_outq,
        !           999:                                    TTOPRI | PCATCH, "comprm", 0);
        !          1000:                                --sc->sc_halt;
        !          1001:                                if (error) {
        !          1002:                                        splx(s);
        !          1003:                                        comstart(tp);
        !          1004:                                        return (error);
        !          1005:                                }
        !          1006:                        }
        !          1007:
        !          1008:                        bus_space_write_1(iot, ioh, com_lcr, lcr | LCR_DLAB);
        !          1009:                        bus_space_write_1(iot, ioh, com_dlbl, ospeed);
        !          1010:                        bus_space_write_1(iot, ioh, com_dlbh, ospeed >> 8);
        !          1011:                        bus_space_write_1(iot, ioh, com_lcr, lcr);
        !          1012:                        SET(sc->sc_mcr, MCR_DTR);
        !          1013:                        bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
        !          1014:                } else
        !          1015:                        bus_space_write_1(iot, ioh, com_lcr, lcr);
        !          1016:
        !          1017:                if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
        !          1018:                        u_int8_t fifo = FIFO_ENABLE;
        !          1019:                        u_int8_t lcr2;
        !          1020:
        !          1021:                        switch (sc->sc_uarttype) {
        !          1022:                        case COM_UART_ST16650V2:
        !          1023:                                if (t->c_ispeed <= 1200)
        !          1024:                                        fifo |= FIFO_RCV_TRIGGER_8|FIFO_XMT_TRIGGER_8; /* XXX */
        !          1025:                                else
        !          1026:                                        fifo |= FIFO_RCV_TRIGGER_28|FIFO_XMT_TRIGGER_30;
        !          1027:                                break;
        !          1028:                        case COM_UART_ST16C654:
        !          1029:                        case COM_UART_XR16850:
        !          1030:                        case COM_UART_OX16C950:
        !          1031:                                if (t->c_ispeed <= 1200)
        !          1032:                                        fifo |= FIFO_RCV3_TRIGGER_8|FIFO_XMT3_TRIGGER_8; /* XXX */
        !          1033:                                else
        !          1034:                                        fifo |= FIFO_RCV3_TRIGGER_60|FIFO_XMT3_TRIGGER_56;
        !          1035:                                break;
        !          1036:                        case COM_UART_TI16750:
        !          1037:                                fifo |= FIFO_ENABLE_64BYTE;
        !          1038:                                lcr2 = bus_space_read_1(iot, ioh, com_lcr);
        !          1039:                                bus_space_write_1(iot, ioh, com_lcr,
        !          1040:                                    lcr2 | LCR_DLAB);
        !          1041:                        default:
        !          1042:                                if (t->c_ispeed <= 1200)
        !          1043:                                        fifo |= FIFO_TRIGGER_1;
        !          1044:                                else
        !          1045:                                        fifo |= FIFO_TRIGGER_8;
        !          1046:                        }
        !          1047:                        bus_space_write_1(iot, ioh, com_fifo, fifo);
        !          1048:
        !          1049:                        if (sc->sc_uarttype == COM_UART_TI16750)
        !          1050:                                bus_space_write_1(iot, ioh, com_lcr, lcr2);
        !          1051:                }
        !          1052:        } else
        !          1053:                bus_space_write_1(iot, ioh, com_lcr, lcr);
        !          1054:
        !          1055:        /* When not using CRTSCTS, RTS follows DTR. */
        !          1056:        if (!ISSET(t->c_cflag, CRTSCTS)) {
        !          1057:                if (ISSET(sc->sc_mcr, MCR_DTR)) {
        !          1058:                        if (!ISSET(sc->sc_mcr, MCR_RTS)) {
        !          1059:                                SET(sc->sc_mcr, MCR_RTS);
        !          1060:                                bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
        !          1061:                        }
        !          1062:                } else {
        !          1063:                        if (ISSET(sc->sc_mcr, MCR_RTS)) {
        !          1064:                                CLR(sc->sc_mcr, MCR_RTS);
        !          1065:                                bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
        !          1066:                        }
        !          1067:                }
        !          1068:                sc->sc_dtr = MCR_DTR | MCR_RTS;
        !          1069:        } else
        !          1070:                sc->sc_dtr = MCR_DTR;
        !          1071:
        !          1072:        /* and copy to tty */
        !          1073:        tp->t_ispeed = t->c_ispeed;
        !          1074:        tp->t_ospeed = t->c_ospeed;
        !          1075:        oldcflag = tp->t_cflag;
        !          1076:        tp->t_cflag = t->c_cflag;
        !          1077:
        !          1078:        /*
        !          1079:         * If DCD is off and MDMBUF is changed, ask the tty layer if we should
        !          1080:         * stop the device.
        !          1081:         */
        !          1082:        if (!ISSET(sc->sc_msr, MSR_DCD) &&
        !          1083:            !ISSET(sc->sc_swflags, COM_SW_SOFTCAR) &&
        !          1084:            ISSET(oldcflag, MDMBUF) != ISSET(tp->t_cflag, MDMBUF) &&
        !          1085:            (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
        !          1086:                CLR(sc->sc_mcr, sc->sc_dtr);
        !          1087:                bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
        !          1088:        }
        !          1089:
        !          1090:        /* Just to be sure... */
        !          1091:        splx(s);
        !          1092:        comstart(tp);
        !          1093:        return 0;
        !          1094: }
        !          1095:
        !          1096: /*
        !          1097:  * (un)block input via hw flowcontrol
        !          1098:  */
        !          1099: int
        !          1100: comhwiflow(struct tty *tp, int block)
        !          1101: {
        !          1102:        struct com_softc *sc = pccom_cd.cd_devs[DEVUNIT(tp->t_dev)];
        !          1103:        bus_space_tag_t iot = sc->sc_iot;
        !          1104:        bus_space_handle_t ioh = sc->sc_ioh;
        !          1105:        int     s;
        !          1106:
        !          1107: /*
        !          1108:  * XXX
        !          1109:  * Is spltty needed at all ? sc->sc_mcr is only in comsoft() not comintr()
        !          1110:  */
        !          1111:        s = spltty();
        !          1112:        if (block) {
        !          1113:                /* When not using CRTSCTS, RTS follows DTR. */
        !          1114:                if (ISSET(tp->t_cflag, MDMBUF)) {
        !          1115:                        CLR(sc->sc_mcr, (MCR_DTR | MCR_RTS));
        !          1116:                        bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
        !          1117:                }
        !          1118:                else {
        !          1119:                        CLR(sc->sc_mcr, MCR_RTS);
        !          1120:                        bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
        !          1121:                }
        !          1122:        }
        !          1123:        else {
        !          1124:                /* When not using CRTSCTS, RTS follows DTR. */
        !          1125:                if (ISSET(tp->t_cflag, MDMBUF)) {
        !          1126:                        SET(sc->sc_mcr, (MCR_DTR | MCR_RTS));
        !          1127:                        bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
        !          1128:                }
        !          1129:                else {
        !          1130:                        SET(sc->sc_mcr, MCR_RTS);
        !          1131:                        bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
        !          1132:                }
        !          1133:        }
        !          1134:        splx(s);
        !          1135:        return 1;
        !          1136: }
        !          1137:
        !          1138: void
        !          1139: comstart(struct tty *tp)
        !          1140: {
        !          1141:        struct com_softc *sc = pccom_cd.cd_devs[DEVUNIT(tp->t_dev)];
        !          1142:        bus_space_tag_t iot = sc->sc_iot;
        !          1143:        bus_space_handle_t ioh = sc->sc_ioh;
        !          1144:        int s, count;
        !          1145:
        !          1146:        s = spltty();
        !          1147:        if (ISSET(tp->t_state, TS_BUSY))
        !          1148:                goto out;
        !          1149:        if (ISSET(tp->t_state, TS_TIMEOUT | TS_TTSTOP) || sc->sc_halt > 0)
        !          1150:                goto stopped;
        !          1151:        if (ISSET(tp->t_cflag, CRTSCTS) && !ISSET(sc->sc_msr, MSR_CTS))
        !          1152:                goto stopped;
        !          1153:        if (tp->t_outq.c_cc <= tp->t_lowat) {
        !          1154:                if (ISSET(tp->t_state, TS_ASLEEP)) {
        !          1155:                        CLR(tp->t_state, TS_ASLEEP);
        !          1156:                        wakeup((caddr_t)&tp->t_outq);
        !          1157:                }
        !          1158:                selwakeup(&tp->t_wsel);
        !          1159:        }
        !          1160:        count = ndqb(&tp->t_outq, 0);
        !          1161:        splhigh();
        !          1162:        if (count > 0) {
        !          1163:                int n;
        !          1164:
        !          1165:                SET(tp->t_state, TS_BUSY);
        !          1166:                if (!ISSET(sc->sc_ier, IER_ETXRDY)) {
        !          1167:                        SET(sc->sc_ier, IER_ETXRDY);
        !          1168:                        bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
        !          1169:                }
        !          1170:                n = sc->sc_fifolen;
        !          1171:                if (n > count)
        !          1172:                        n = count;
        !          1173:                sc->sc_tba = tp->t_outq.c_cf;
        !          1174:                while (--n >= 0) {
        !          1175:                        bus_space_write_1(iot, ioh, com_data, *sc->sc_tba++);
        !          1176:                        --count;
        !          1177:                }
        !          1178:                sc->sc_tbc = count;
        !          1179:                goto out;
        !          1180:        }
        !          1181: stopped:
        !          1182:        if (ISSET(sc->sc_ier, IER_ETXRDY)) {
        !          1183:                CLR(sc->sc_ier, IER_ETXRDY);
        !          1184:                bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
        !          1185:        }
        !          1186: out:
        !          1187:        splx(s);
        !          1188:        return;
        !          1189: }
        !          1190:
        !          1191: /*
        !          1192:  * Stop output on a line.
        !          1193:  */
        !          1194: int
        !          1195: comstop(struct tty *tp, int flag)
        !          1196: {
        !          1197:        int s;
        !          1198:        struct com_softc *sc = pccom_cd.cd_devs[DEVUNIT(tp->t_dev)];
        !          1199:
        !          1200:        s = splhigh();
        !          1201:        if (ISSET(tp->t_state, TS_BUSY)) {
        !          1202:                sc->sc_tbc = 0;
        !          1203:                if (!ISSET(tp->t_state, TS_TTSTOP))
        !          1204:                        SET(tp->t_state, TS_FLUSH);
        !          1205:        }
        !          1206:        splx(s);
        !          1207:        return 0;
        !          1208: }
        !          1209:
        !          1210: void
        !          1211: comdiag(void *arg)
        !          1212: {
        !          1213:        struct com_softc *sc = arg;
        !          1214:        int overflows;
        !          1215:        int s;
        !          1216:
        !          1217:        s = spltty();
        !          1218:        overflows = sc->sc_overflows;
        !          1219:        sc->sc_overflows = 0;
        !          1220:        splx(s);
        !          1221:
        !          1222:        if (overflows)
        !          1223:                log(LOG_WARNING, "%s: %d silo overflow%s\n",
        !          1224:                    sc->sc_dev.dv_xname, overflows, overflows == 1 ? "" : "s");
        !          1225: }
        !          1226:
        !          1227: #ifdef PCCOM_DEBUG
        !          1228: int    maxcc = 0;
        !          1229: #endif
        !          1230:
        !          1231: void
        !          1232: comsoft(void)
        !          1233: {
        !          1234:        struct com_softc        *sc;
        !          1235:        struct tty *tp;
        !          1236:        struct linesw   *line;
        !          1237:        int     unit, s, c;
        !          1238:        u_int rxget;
        !          1239:        static int lsrmap[8] = {
        !          1240:                0,      TTY_PE,
        !          1241:                TTY_FE, TTY_PE|TTY_FE,
        !          1242:                TTY_FE, TTY_PE|TTY_FE,
        !          1243:                TTY_FE, TTY_PE|TTY_FE
        !          1244:        };
        !          1245:
        !          1246:        for (unit = 0; unit < pccom_cd.cd_ndevs; unit++) {
        !          1247:                sc = pccom_cd.cd_devs[unit];
        !          1248:                if (sc == NULL)
        !          1249:                        continue;
        !          1250:                tp = sc->sc_tty;
        !          1251: /*
        !          1252:  * XXX only use (tp == NULL) ???
        !          1253:  */
        !          1254:                if (tp == NULL || !ISSET(tp->t_state, TS_ISOPEN | TS_WOPEN))
        !          1255:                        continue;
        !          1256:                line = &linesw[tp->t_line];
        !          1257: /*
        !          1258:  * XXX where do we _really_ need spltty(), if at all ???
        !          1259:  */
        !          1260:                s = spltty();
        !          1261:                rxget = sc->sc_rxget;
        !          1262:                while (rxget != sc->sc_rxput) {
        !          1263:                        u_int8_t lsr;
        !          1264:
        !          1265:                        lsr = sc->sc_rxbuf[rxget];
        !          1266:                        rxget = (rxget + 1) & RBUFMASK;
        !          1267:                        if (ISSET(lsr, LSR_RCV_MASK)) {
        !          1268:                                c = sc->sc_rxbuf[rxget];
        !          1269:                                if (ISSET(lsr, LSR_OE)) {
        !          1270:                                        sc->sc_overflows++;
        !          1271:                                        if (sc->sc_errors++ == 0)
        !          1272:                                                timeout_add(&sc->sc_diag_tmo, 60 * hz);
        !          1273:                                }
        !          1274:                                rxget = (rxget + 1) & RBUFMASK;
        !          1275:                                c |= lsrmap[(lsr & (LSR_BI|LSR_FE|LSR_PE)) >> 2];
        !          1276:                                line->l_rint(c, tp);
        !          1277:                        }
        !          1278:                        else if (ISSET(lsr, LSR_TXRDY)) {
        !          1279:                                CLR(tp->t_state, TS_BUSY);
        !          1280:                                if (ISSET(tp->t_state, TS_FLUSH))
        !          1281:                                        CLR(tp->t_state, TS_FLUSH);
        !          1282:                                else
        !          1283:                                        ndflush(&tp->t_outq,
        !          1284:                                        (int)(sc->sc_tba - tp->t_outq.c_cf));
        !          1285:                                if (sc->sc_halt > 0)
        !          1286:                                        wakeup(&tp->t_outq);
        !          1287:                                line->l_start(tp);
        !          1288:                        }
        !          1289:                        else if (lsr == 0) {
        !          1290:                                u_int8_t msr;
        !          1291:
        !          1292:                                msr = sc->sc_rxbuf[rxget];
        !          1293:                                rxget = (rxget + 1) & RBUFMASK;
        !          1294:                                if (ISSET(msr, MSR_DDCD) &&
        !          1295:                                   !ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) {
        !          1296:                                        if (ISSET(msr, MSR_DCD))
        !          1297:                                                line->l_modem(tp, 1);
        !          1298:                                        else if (line->l_modem(tp, 0) == 0) {
        !          1299:                                                CLR(sc->sc_mcr, sc->sc_dtr);
        !          1300:                                                bus_space_write_1(sc->sc_iot,
        !          1301:                                                               sc->sc_ioh,
        !          1302:                                                               com_mcr,
        !          1303:                                                               sc->sc_mcr);
        !          1304:                                        }
        !          1305:                                }
        !          1306:                                if (ISSET(msr, MSR_DCTS) &&
        !          1307:                                    ISSET(msr, MSR_CTS) &&
        !          1308:                                    ISSET(tp->t_cflag, CRTSCTS))
        !          1309:                                        line->l_start(tp);
        !          1310:                        }
        !          1311:                }
        !          1312:                sc->sc_rxget = rxget;
        !          1313: /*
        !          1314:  * XXX this is the place where we could unblock the input
        !          1315:  */
        !          1316:                splx(s);
        !          1317:        }
        !          1318: }
        !          1319:
        !          1320: #ifdef KGDB
        !          1321:
        !          1322: /*
        !          1323:  * If a line break is set, or data matches one of the characters
        !          1324:  * gdb uses to signal a connection, then start up kgdb. Just gobble
        !          1325:  * any other data. Done in a stand alone function because comintr
        !          1326:  * does tty stuff and we don't have one.
        !          1327:  */
        !          1328:
        !          1329: int
        !          1330: kgdbintr(void *arg)
        !          1331: {
        !          1332:        struct com_softc *sc = arg;
        !          1333:        bus_space_tag_t iot = sc->sc_iot;
        !          1334:        bus_space_handle_t ioh = sc->sc_ioh;
        !          1335:        u_char lsr, data, msr, delta;
        !          1336:
        !          1337:        if (!ISSET(sc->sc_hwflags, COM_HW_KGDB))
        !          1338:                return(0);
        !          1339:
        !          1340:        for (;;) {
        !          1341:                lsr = bus_space_read_1(iot, ioh, com_lsr);
        !          1342:                if (ISSET(lsr, LSR_RXRDY)) {
        !          1343:                        do {
        !          1344:                                data = bus_space_read_1(iot, ioh, com_data);
        !          1345:                                if (data == 3 || data == '$' || data == '+' ||
        !          1346:                                    ISSET(lsr, LSR_BI)) {
        !          1347:                                        kgdb_connect(1);
        !          1348:                                        data = 0;
        !          1349:                                }
        !          1350:                                lsr = bus_space_read_1(iot, ioh, com_lsr);
        !          1351:                        } while (ISSET(lsr, LSR_RXRDY));
        !          1352:
        !          1353:                }
        !          1354:                if (ISSET(lsr, LSR_BI|LSR_FE|LSR_PE|LSR_OE))
        !          1355:                        printf("weird lsr %02x\n", lsr);
        !          1356:
        !          1357:                msr = bus_space_read_1(iot, ioh, com_msr);
        !          1358:
        !          1359:                if (msr != sc->sc_msr) {
        !          1360:                        delta = msr ^ sc->sc_msr;
        !          1361:                        sc->sc_msr = msr;
        !          1362:                        if (ISSET(delta, MSR_DCD)) {
        !          1363:                                if (!ISSET(sc->sc_swflags, COM_SW_SOFTCAR)) {
        !          1364:                                        CLR(sc->sc_mcr, sc->sc_dtr);
        !          1365:                                        bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
        !          1366:                                }
        !          1367:                        }
        !          1368:                }
        !          1369:                if (ISSET(bus_space_read_1(iot, ioh, com_iir), IIR_NOPEND))
        !          1370:                        return (1);
        !          1371:        }
        !          1372: }
        !          1373: #endif /* KGDB */
        !          1374:
        !          1375: int
        !          1376: comintr(void *arg)
        !          1377: {
        !          1378:        struct com_softc *sc = arg;
        !          1379:        struct tty *tp = sc->sc_tty;
        !          1380:        bus_space_tag_t iot = sc->sc_iot;
        !          1381:        bus_space_handle_t ioh = sc->sc_ioh;
        !          1382:        u_int8_t lsr, c;
        !          1383:        u_int   rxput;
        !          1384:
        !          1385:        if (!sc->sc_tty)
        !          1386:                return (0);     /* can't do squat. */
        !          1387:
        !          1388:        if (ISSET(bus_space_read_1(iot, ioh, com_iir), IIR_NOPEND))
        !          1389:                return (0);
        !          1390:
        !          1391:        rxput = sc->sc_rxput;
        !          1392:        do {
        !          1393:                u_int8_t msr, delta;
        !          1394:
        !          1395:                for (;;) {
        !          1396:                        lsr = bus_space_read_1(iot, ioh, com_lsr);
        !          1397:                        if (!ISSET(lsr, LSR_RCV_MASK))
        !          1398:                                break;
        !          1399:                        c = bus_space_read_1(iot, ioh, com_data);
        !          1400:                        if (ISSET(lsr, LSR_BI)) {
        !          1401: #ifdef DDB
        !          1402:                                if (ISSET(sc->sc_hwflags, COM_HW_CONSOLE)) {
        !          1403:                                        if (db_console)
        !          1404:                                                Debugger();
        !          1405:                                        continue;
        !          1406:                                }
        !          1407: #endif
        !          1408:                                c = 0;
        !          1409:                        }
        !          1410:
        !          1411:                        sc->sc_rxbuf[rxput] = lsr;
        !          1412:                        rxput = (rxput + 1) & RBUFMASK;
        !          1413:                        sc->sc_rxbuf[rxput] = c;
        !          1414:                        rxput = (rxput + 1) & RBUFMASK;
        !          1415:                }
        !          1416:                msr = bus_space_read_1(iot, ioh, com_msr);
        !          1417:                delta = msr ^ sc->sc_msr;
        !          1418:
        !          1419:                ttytstamp(tp, sc->sc_msr & MSR_CTS, msr & MSR_CTS,
        !          1420:                    sc->sc_msr & MSR_DCD, msr & MSR_DCD);
        !          1421:
        !          1422:                if (!ISSET(delta, MSR_DCD | MSR_CTS | MSR_RI | MSR_DSR))
        !          1423:                        continue;
        !          1424:                sc->sc_msr = msr;
        !          1425: /*
        !          1426:  * stop output straight away if CTS drops and RTS/CTS flowcontrol is used
        !          1427:  * XXX what about DTR/DCD flowcontrol (ISSET(t_cflag, MDMBUF))
        !          1428:  */
        !          1429:                msr = (msr & 0xf0) | (delta >> 4);
        !          1430:                if (ISSET(tp->t_cflag, CRTSCTS) && ISSET(msr, MSR_DCTS)) {
        !          1431:                        if (!ISSET(msr, MSR_CTS))
        !          1432:                                sc->sc_tbc = 0;
        !          1433:                }
        !          1434:                sc->sc_rxbuf[rxput] = 0;
        !          1435:                rxput = (rxput + 1) & RBUFMASK;
        !          1436:                sc->sc_rxbuf[rxput] = msr;
        !          1437:                rxput = (rxput + 1) & RBUFMASK;
        !          1438:        } while (!ISSET(bus_space_read_1(iot, ioh, com_iir), IIR_NOPEND));
        !          1439:        if (ISSET(lsr, LSR_TXRDY)) {
        !          1440:                if (sc->sc_tbc > 0) {
        !          1441:                        int     n;
        !          1442:
        !          1443:                        n = sc->sc_fifolen;
        !          1444:                        if (n > sc->sc_tbc)
        !          1445:                                n = sc->sc_tbc;
        !          1446:                        while (--n >= 0) {
        !          1447:                                bus_space_write_1(iot, ioh, com_data, *sc->sc_tba++);
        !          1448:                                --sc->sc_tbc;
        !          1449:                        }
        !          1450:                }
        !          1451:                else if (ISSET(tp->t_state, TS_BUSY)) {
        !          1452:                        sc->sc_rxbuf[rxput] = lsr;
        !          1453:                        rxput = (rxput + 1) & RBUFMASK;
        !          1454:                }
        !          1455:        }
        !          1456:        if (sc->sc_rxput != rxput) {
        !          1457: /*
        !          1458:  * XXX
        !          1459:  * This is the place to do input flow control by dropping RTS or DTR.
        !          1460:  * However, 115200 bps transfers get maxcc only up to 112 while there's
        !          1461:  * room for 512 so should we bother ?
        !          1462:  */
        !          1463: #ifdef PCCOM_DEBUG
        !          1464:                int     cc;
        !          1465:
        !          1466:                cc = rxput - sc->sc_rxget;
        !          1467:                if (cc < 0)
        !          1468:                        cc += RBUFSIZE;
        !          1469:                if (cc > maxcc)
        !          1470:                        maxcc = cc;
        !          1471: #endif
        !          1472:                sc->sc_rxput = rxput;
        !          1473:                setsofttty();
        !          1474:        }
        !          1475:        return 1;
        !          1476: }
        !          1477:
        !          1478: void
        !          1479: pccom_xr16850_fifo_init(bus_space_tag_t iot, bus_space_handle_t ioh)
        !          1480: {
        !          1481:        u_int8_t lcr, efr, fctl;
        !          1482:
        !          1483:        lcr = bus_space_read_1(iot, ioh, com_lcr);
        !          1484:        bus_space_write_1(iot, ioh, com_lcr, LCR_EFR);
        !          1485:        efr = bus_space_read_1(iot, ioh, com_efr);
        !          1486:        bus_space_write_1(iot, ioh, com_efr, efr | EFR_ECB);
        !          1487:        fctl = bus_space_read_1(iot, ioh, com_fctl);
        !          1488:        bus_space_write_1(iot, ioh, com_fctl, fctl | FCTL_TRIGGER3);
        !          1489:        bus_space_write_1(iot, ioh, com_lcr, lcr);
        !          1490: }
        !          1491:
        !          1492: /*
        !          1493:  * Following are all routines needed for PCCOM to act as console
        !          1494:  */
        !          1495:
        !          1496: void
        !          1497: comcnprobe(struct consdev *cp)
        !          1498: {
        !          1499:        /* XXX NEEDS TO BE FIXED XXX */
        !          1500:        bus_space_tag_t iot = 0;
        !          1501:        bus_space_handle_t ioh;
        !          1502:        int found;
        !          1503:
        !          1504:        if (bus_space_map(iot, CONADDR, COM_NPORTS, 0, &ioh))
        !          1505:                return;
        !          1506:        found = comprobe1(iot, ioh);
        !          1507:        bus_space_unmap(iot, ioh, COM_NPORTS);
        !          1508:        if (!found)
        !          1509:                return;
        !          1510:
        !          1511:        /* locate the major number */
        !          1512:        for (commajor = 0; commajor < nchrdev; commajor++)
        !          1513:                if (cdevsw[commajor].d_open == comopen)
        !          1514:                        break;
        !          1515:
        !          1516:        /* initialize required fields */
        !          1517:        cp->cn_dev = makedev(commajor, CONUNIT);
        !          1518: #if defined(COMCONSOLE) || defined(PCCOMCONSOLE)
        !          1519:        cp->cn_pri = CN_REMOTE;         /* Force a serial port console */
        !          1520: #else
        !          1521:        cp->cn_pri = CN_NORMAL;
        !          1522: #endif
        !          1523: }
        !          1524:
        !          1525: /*
        !          1526:  * The following functions are polled getc and putc routines, shared
        !          1527:  * by the console and kgdb glue.
        !          1528:  */
        !          1529:
        !          1530: int
        !          1531: com_common_getc(bus_space_tag_t iot, bus_space_handle_t ioh)
        !          1532: {
        !          1533:        int s = splhigh();
        !          1534:        u_char stat, c;
        !          1535:
        !          1536:        /* block until a character becomes available */
        !          1537:        while (!ISSET(stat = bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY))
        !          1538:                continue;
        !          1539:
        !          1540:        c = bus_space_read_1(iot, ioh, com_data);
        !          1541:        /* clear any interrupts generated by this transmission */
        !          1542:        stat = bus_space_read_1(iot, ioh, com_iir);
        !          1543:        splx(s);
        !          1544:        return (c);
        !          1545: }
        !          1546:
        !          1547: void
        !          1548: com_common_putc(bus_space_tag_t iot, bus_space_handle_t ioh, int c)
        !          1549: {
        !          1550:        int s = splhigh();
        !          1551:        int timo;
        !          1552:
        !          1553:        /* wait for any pending transmission to finish */
        !          1554:        timo = 150000;
        !          1555:        while (!ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_TXRDY) && --timo)
        !          1556:                continue;
        !          1557:
        !          1558:        bus_space_write_1(iot, ioh, com_data, c);
        !          1559:
        !          1560:        /* wait for this transmission to complete */
        !          1561:        timo = 1500000;
        !          1562:        while (!ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_TXRDY) && --timo)
        !          1563:                continue;
        !          1564:
        !          1565:        splx(s);
        !          1566: }
        !          1567:
        !          1568: /*
        !          1569:  * Following are all routines needed for COM to act as console
        !          1570:  */
        !          1571:
        !          1572: void
        !          1573: comcninit(struct consdev *cp)
        !          1574: {
        !          1575:
        !          1576: #if 0
        !          1577:        XXX NEEDS TO BE FIXED XXX
        !          1578:        comconsiot = ???;
        !          1579: #endif
        !          1580:
        !          1581: #ifdef CONADDR_OVERRIDE
        !          1582:        comconsaddr = CONADDR;
        !          1583: #else
        !          1584:        const int comports[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
        !          1585:        int unit = minor(cp->cn_dev);
        !          1586:
        !          1587:        if (unit >= 0 && unit < 4)
        !          1588:                comconsaddr = comports[unit];
        !          1589:        else
        !          1590:                comconsaddr = CONADDR;
        !          1591: #endif
        !          1592:
        !          1593:        if (bus_space_map(comconsiot, comconsaddr, COM_NPORTS, 0, &comconsioh))
        !          1594:                panic("comcninit: mapping failed");
        !          1595:
        !          1596:        cominit(comconsiot, comconsioh, comdefaultrate);
        !          1597:        comconsinit = 0;
        !          1598: }
        !          1599:
        !          1600: void
        !          1601: cominit(bus_space_tag_t iot, bus_space_handle_t ioh, int rate)
        !          1602: {
        !          1603:        int s = splhigh();
        !          1604:        u_int8_t stat;
        !          1605:
        !          1606:        bus_space_write_1(iot, ioh, com_lcr, LCR_DLAB);
        !          1607:        rate = comspeed(COM_FREQ, rate); /* XXX not comdefaultrate? */
        !          1608:        bus_space_write_1(iot, ioh, com_dlbl, rate);
        !          1609:        bus_space_write_1(iot, ioh, com_dlbh, rate >> 8);
        !          1610:        bus_space_write_1(iot, ioh, com_lcr, LCR_8BITS);
        !          1611:        bus_space_write_1(iot, ioh, com_mcr, MCR_DTR | MCR_RTS);
        !          1612:        bus_space_write_1(iot, ioh, com_ier, IER_ERXRDY | IER_ETXRDY);
        !          1613:        bus_space_write_1(iot, ioh, com_fifo,
        !          1614:            FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_4);
        !          1615:        stat = bus_space_read_1(iot, ioh, com_iir);
        !          1616:        splx(s);
        !          1617: }
        !          1618:
        !          1619: int
        !          1620: comcngetc(dev_t dev)
        !          1621: {
        !          1622:        return (com_common_getc(comconsiot, comconsioh));
        !          1623: }
        !          1624:
        !          1625: /*
        !          1626:  * Console kernel output character routine.
        !          1627:  */
        !          1628: void
        !          1629: comcnputc(dev_t dev, int c)
        !          1630: {
        !          1631: #if 0
        !          1632:        /* XXX not needed? */
        !          1633:        bus_space_tag_t iot = comconsiot;
        !          1634:        bus_space_handle_t ioh = comconsioh;
        !          1635:
        !          1636:        if (comconsinit == 0) {
        !          1637:                cominit(iot, ioh, comdefaultrate);
        !          1638:                comconsinit = 1;
        !          1639:        }
        !          1640: #endif
        !          1641:        com_common_putc(comconsiot, comconsioh, c);
        !          1642: }
        !          1643:
        !          1644: void
        !          1645: comcnpollc(dev_t dev, int on)
        !          1646: {
        !          1647:
        !          1648: }
        !          1649:
        !          1650: #ifdef KGDB
        !          1651: int
        !          1652: com_kgdb_attach(bus_space_tag_t iot, bus_addr_t iobase, int rate, int frequency,
        !          1653:     tcflag_t cflag)
        !          1654: {
        !          1655:        if (iot == comconsiot && iobase == comconsaddr) {
        !          1656:                return (EBUSY); /* cannot share with console */
        !          1657:        }
        !          1658:
        !          1659:        com_kgdb_iot = iot;
        !          1660:        com_kgdb_addr = iobase;
        !          1661:
        !          1662:        if (bus_space_map(com_kgdb_iot, com_kgdb_addr, COM_NPORTS, 0,
        !          1663:            &com_kgdb_ioh))
        !          1664:                panic("com_kgdb_attach: mapping failed");
        !          1665:
        !          1666:        /* XXX We currently don't respect KGDBMODE? */
        !          1667:        cominit(com_kgdb_iot, com_kgdb_ioh, rate);
        !          1668:
        !          1669:        kgdb_attach(com_kgdb_getc, com_kgdb_putc, NULL);
        !          1670:        kgdb_dev = 123; /* unneeded, only to satisfy some tests */
        !          1671:
        !          1672:        return (0);
        !          1673: }
        !          1674:
        !          1675: /* ARGSUSED */
        !          1676: int
        !          1677: com_kgdb_getc(void *arg)
        !          1678: {
        !          1679:
        !          1680:        return (com_common_getc(com_kgdb_iot, com_kgdb_ioh));
        !          1681: }
        !          1682:
        !          1683: /* ARGSUSED */
        !          1684: void
        !          1685: com_kgdb_putc(void *arg, int c)
        !          1686: {
        !          1687:
        !          1688:        return (com_common_putc(com_kgdb_iot, com_kgdb_ioh, c));
        !          1689: }
        !          1690: #endif /* KGDB */

CVSweb