[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

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