[BACK]Return to dca.c CVS log [TXT][DIR] Up to [local] / sys / arch / hp300 / dev

Annotation of sys/arch/hp300/dev/dca.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: dca.c,v 1.31 2006/01/01 11:59:37 miod Exp $   */
        !             2: /*     $NetBSD: dca.c,v 1.35 1997/05/05 20:58:18 thorpej Exp $ */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1995, 1996, 1997 Jason R. Thorpe.  All rights reserved.
        !             6:  * Copyright (c) 1982, 1986, 1990, 1993
        !             7:  *     The Regents of the University of California.  All rights reserved.
        !             8:  *
        !             9:  * Redistribution and use in source and binary forms, with or without
        !            10:  * modification, are permitted provided that the following conditions
        !            11:  * are met:
        !            12:  * 1. Redistributions of source code must retain the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer.
        !            14:  * 2. Redistributions in binary form must reproduce the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer in the
        !            16:  *    documentation and/or other materials provided with the distribution.
        !            17:  * 3. Neither the name of the University nor the names of its contributors
        !            18:  *    may be used to endorse or promote products derived from this software
        !            19:  *    without specific prior written permission.
        !            20:  *
        !            21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            31:  * SUCH DAMAGE.
        !            32:  *
        !            33:  *     @(#)dca.c       8.2 (Berkeley) 1/12/94
        !            34:  */
        !            35:
        !            36: /*
        !            37:  *  Driver for the 98626/98644/internal serial interface on hp300/hp400,
        !            38:  *  based on the National Semiconductor INS8250/NS16550AF/WD16C552 UARTs.
        !            39:  *
        !            40:  *  N.B. On the hp700 and some hp300s, there is a "secret bit" with
        !            41:  *  undocumented behavior.  The third bit of the Modem Control Register
        !            42:  *  (MCR_IEN == 0x08) must be set to enable interrupts.  Failure to do
        !            43:  *  so can result in deadlock on those machines, whereas the don't seem to
        !            44:  *  be any harmful side-effects from setting this bit on non-affected
        !            45:  *  machines.
        !            46:  */
        !            47:
        !            48: #include <sys/param.h>
        !            49: #include <sys/systm.h>
        !            50: #include <sys/ioctl.h>
        !            51: #include <sys/proc.h>
        !            52: #include <sys/tty.h>
        !            53: #include <sys/conf.h>
        !            54: #include <sys/file.h>
        !            55: #include <sys/uio.h>
        !            56: #include <sys/kernel.h>
        !            57: #include <sys/syslog.h>
        !            58: #include <sys/device.h>
        !            59:
        !            60: #include <machine/autoconf.h>
        !            61: #include <machine/bus.h>
        !            62: #include <machine/cpu.h>
        !            63: #include <machine/intr.h>
        !            64:
        !            65: #include <dev/cons.h>
        !            66:
        !            67: #include <hp300/dev/dioreg.h>
        !            68: #include <hp300/dev/diovar.h>
        !            69: #include <hp300/dev/diodevs.h>
        !            70: #include <hp300/dev/dcareg.h>
        !            71:
        !            72: #ifdef DDB
        !            73: #include <ddb/db_var.h>
        !            74: #endif
        !            75:
        !            76: struct dca_softc {
        !            77:        struct device           sc_dev;         /* generic device glue */
        !            78:        struct isr              sc_isr;
        !            79:        struct dcadevice        *sc_dca;        /* pointer to hardware */
        !            80:        struct tty              *sc_tty;        /* our tty instance */
        !            81:        int                     sc_oflows;      /* overflow counter */
        !            82:        short                   sc_flags;       /* state flags */
        !            83:        u_char                  sc_cua;         /* callout mode */
        !            84:
        !            85:        /*
        !            86:         * Bits for sc_flags.
        !            87:         */
        !            88: #define        DCA_ACTIVE      0x0001  /* indicates live unit */
        !            89: #define        DCA_SOFTCAR     0x0002  /* indicates soft-carrier */
        !            90: #define        DCA_HASFIFO     0x0004  /* indicates unit has FIFO */
        !            91: #define DCA_ISCONSOLE  0x0008  /* indicates unit is console */
        !            92:
        !            93: };
        !            94:
        !            95: int    dcamatch(struct device *, void *, void *);
        !            96: void   dcaattach(struct device *, struct device *, void *);
        !            97:
        !            98: struct cfattach dca_ca = {
        !            99:        sizeof(struct dca_softc), dcamatch, dcaattach
        !           100: };
        !           101:
        !           102: struct cfdriver dca_cd = {
        !           103:        NULL, "dca", DV_TTY
        !           104: };
        !           105:
        !           106: int    dcadefaultrate = TTYDEF_SPEED;
        !           107: int    dcamajor;
        !           108:
        !           109: cdev_decl(dca);
        !           110:
        !           111: int    dcaintr(void *);
        !           112: void   dcaeint(struct dca_softc *, int);
        !           113: void   dcamint(struct dca_softc *);
        !           114:
        !           115: int    dcaparam(struct tty *, struct termios *);
        !           116: void   dcastart(struct tty *);
        !           117: int    dcastop(struct tty *, int);
        !           118: int    dcamctl(struct dca_softc *, int, int);
        !           119: void   dcainit(struct dcadevice *, int);
        !           120:
        !           121: int    dca_console_scan(int, caddr_t, void *);
        !           122: cons_decl(dca);
        !           123:
        !           124: /*
        !           125:  * Stuff for DCA console support.
        !           126:  */
        !           127: static struct dcadevice *dca_cn = NULL;        /* pointer to hardware */
        !           128: static int dcaconsinit;                        /* has been initialized */
        !           129:
        !           130: const struct speedtab dcaspeedtab[] = {
        !           131:        {       0,      0               },
        !           132:        {       50,     DCABRD(50)      },
        !           133:        {       75,     DCABRD(75)      },
        !           134:        {       110,    DCABRD(110)     },
        !           135:        {       134,    DCABRD(134)     },
        !           136:        {       150,    DCABRD(150)     },
        !           137:        {       200,    DCABRD(200)     },
        !           138:        {       300,    DCABRD(300)     },
        !           139:        {       600,    DCABRD(600)     },
        !           140:        {       1200,   DCABRD(1200)    },
        !           141:        {       1800,   DCABRD(1800)    },
        !           142:        {       2400,   DCABRD(2400)    },
        !           143:        {       4800,   DCABRD(4800)    },
        !           144:        {       9600,   DCABRD(9600)    },
        !           145:        {       19200,  DCABRD(19200)   },
        !           146:        {       38400,  DCABRD(38400)   },
        !           147:        {       -1,     -1              },
        !           148: };
        !           149:
        !           150: #ifdef KGDB
        !           151: #include <machine/remote-sl.h>
        !           152:
        !           153: extern dev_t kgdb_dev;
        !           154: extern int kgdb_rate;
        !           155: extern int kgdb_debug_init;
        !           156: #endif
        !           157:
        !           158: #define        DCAUNIT(x)              (minor(x) & 0x7f)
        !           159: #define DCACUA(x)              (minor(x) & 0x80)
        !           160:
        !           161: #ifdef DEBUG
        !           162: long   fifoin[17];
        !           163: long   fifoout[17];
        !           164: long   dcaintrcount[16];
        !           165: long   dcamintcount[16];
        !           166: #endif
        !           167:
        !           168: void   dcainit(struct dcadevice *, int);
        !           169:
        !           170: int
        !           171: dcamatch(parent, match, aux)
        !           172:        struct device *parent;
        !           173:        void *match, *aux;
        !           174: {
        !           175:        struct dio_attach_args *da = aux;
        !           176:
        !           177:        switch (da->da_id) {
        !           178:        case DIO_DEVICE_ID_DCA0:
        !           179:        case DIO_DEVICE_ID_DCA0REM:
        !           180:        case DIO_DEVICE_ID_DCA1:
        !           181:        case DIO_DEVICE_ID_DCA1REM:
        !           182:                return (1);
        !           183:        }
        !           184:
        !           185:        return (0);
        !           186: }
        !           187:
        !           188: void
        !           189: dcaattach(parent, self, aux)
        !           190:        struct device *parent, *self;
        !           191:        void *aux;
        !           192: {
        !           193:        struct dca_softc *sc = (struct dca_softc *)self;
        !           194:        struct dio_attach_args *da = aux;
        !           195:        struct dcadevice *dca;
        !           196:        int unit = self->dv_unit;
        !           197:        int scode = da->da_scode;
        !           198:        int ipl;
        !           199:
        !           200:        if (scode == conscode) {
        !           201:                dca = (struct dcadevice *)conaddr;
        !           202:                sc->sc_flags |= DCA_ISCONSOLE;
        !           203:                DELAY(100000);
        !           204:
        !           205:                /*
        !           206:                 * We didn't know which unit this would be during
        !           207:                 * the console probe, so we have to fixup cn_dev here.
        !           208:                 */
        !           209:                cn_tab->cn_dev = makedev(dcamajor, unit);
        !           210:        } else {
        !           211:                dca = (struct dcadevice *)iomap(dio_scodetopa(da->da_scode),
        !           212:                    da->da_size);
        !           213:                if (dca == NULL) {
        !           214:                        printf("\n%s: can't map registers\n",
        !           215:                            sc->sc_dev.dv_xname);
        !           216:                        return;
        !           217:                }
        !           218:        }
        !           219:
        !           220:        sc->sc_dca = dca;
        !           221:
        !           222:        ipl = DIO_IPL(dca);
        !           223:        printf(" ipl %d", ipl);
        !           224:
        !           225:        dca->dca_reset = 0xFF;
        !           226:        DELAY(100);
        !           227:
        !           228:        /* look for a NS 16550AF UART with FIFOs */
        !           229:        dca->dca_fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST|FIFO_TRIGGER_14;
        !           230:        DELAY(100);
        !           231:        if ((dca->dca_iir & IIR_FIFO_MASK) == IIR_FIFO_MASK)
        !           232:                sc->sc_flags |= DCA_HASFIFO;
        !           233:
        !           234:        /* Establish interrupt handler. */
        !           235:        sc->sc_isr.isr_func = dcaintr;
        !           236:        sc->sc_isr.isr_arg = sc;
        !           237:        sc->sc_isr.isr_ipl = ipl;
        !           238:        sc->sc_isr.isr_priority =
        !           239:            (sc->sc_flags & DCA_HASFIFO) ? IPL_TTY : IPL_TTYNOBUF;
        !           240:        dio_intr_establish(&sc->sc_isr, self->dv_xname);
        !           241:
        !           242:        sc->sc_flags |= DCA_ACTIVE;
        !           243:        if (self->dv_cfdata->cf_flags)
        !           244:                sc->sc_flags |= DCA_SOFTCAR;
        !           245:
        !           246:        /* Enable interrupts. */
        !           247:        dca->dca_ic = IC_IE;
        !           248:
        !           249:        /*
        !           250:         * Need to reset baud rate, etc. of next print so reset dcaconsinit.
        !           251:         * Also make sure console is always "hardwired."
        !           252:         */
        !           253:        if (sc->sc_flags & DCA_ISCONSOLE) {
        !           254:                dcaconsinit = 0;
        !           255:                sc->sc_flags |= DCA_SOFTCAR;
        !           256:                printf(": console, ");
        !           257:        } else
        !           258:                printf(": ");
        !           259:
        !           260:        if (sc->sc_flags & DCA_HASFIFO)
        !           261:                printf("working fifo\n");
        !           262:        else
        !           263:                printf("no fifo\n");
        !           264:
        !           265: #ifdef KGDB
        !           266:        if (kgdb_dev == makedev(dcamajor, unit)) {
        !           267:                if (sc->sc_flags & DCA_ISCONSOLE)
        !           268:                        kgdb_dev = NODEV; /* can't debug over console port */
        !           269:                else {
        !           270:                        dcainit(dca, kgdb_rate);
        !           271:                        dcaconsinit = 1;        /* don't re-init in dcaputc */
        !           272:                        if (kgdb_debug_init) {
        !           273:                                /*
        !           274:                                 * Print prefix of device name,
        !           275:                                 * let kgdb_connect print the rest.
        !           276:                                 */
        !           277:                                printf("%s: ", sc->sc_dev.dv_xname);
        !           278:                                kgdb_connect(1);
        !           279:                        } else
        !           280:                                printf("%s: kgdb enabled\n",
        !           281:                                    sc->sc_dev.dv_xname);
        !           282:                }
        !           283:        }
        !           284: #endif
        !           285: }
        !           286:
        !           287: /* ARGSUSED */
        !           288: int
        !           289: dcaopen(dev, flag, mode, p)
        !           290:        dev_t dev;
        !           291:        int flag, mode;
        !           292:        struct proc *p;
        !           293: {
        !           294:        int unit = DCAUNIT(dev);
        !           295:        struct dca_softc *sc;
        !           296:        struct tty *tp;
        !           297:        struct dcadevice *dca;
        !           298:        u_char code;
        !           299:        int s, error = 0;
        !           300:
        !           301:        if (unit >= dca_cd.cd_ndevs ||
        !           302:            (sc = dca_cd.cd_devs[unit]) == NULL)
        !           303:                return (ENXIO);
        !           304:
        !           305:        if ((sc->sc_flags & DCA_ACTIVE) == 0)
        !           306:                return (ENXIO);
        !           307:
        !           308:        dca = sc->sc_dca;
        !           309:
        !           310:        s = spltty();
        !           311:        if (sc->sc_tty == NULL) {
        !           312:                tp = sc->sc_tty = ttymalloc();
        !           313:        } else
        !           314:                tp = sc->sc_tty;
        !           315:        splx(s);
        !           316:
        !           317:        tp->t_oproc = dcastart;
        !           318:        tp->t_param = dcaparam;
        !           319:        tp->t_dev = dev;
        !           320:
        !           321:        if ((tp->t_state & TS_ISOPEN) == 0) {
        !           322:                /*
        !           323:                 * Sanity clause: reset the card on first open.
        !           324:                 * The card might be left in an inconsistent state
        !           325:                 * if card memory is read inadvertently.
        !           326:                 */
        !           327:                dcainit(dca, dcadefaultrate);
        !           328:
        !           329:                tp->t_state |= TS_WOPEN;
        !           330:                ttychars(tp);
        !           331:                tp->t_iflag = TTYDEF_IFLAG;
        !           332:                tp->t_oflag = TTYDEF_OFLAG;
        !           333:                tp->t_cflag = TTYDEF_CFLAG;
        !           334:                tp->t_lflag = TTYDEF_LFLAG;
        !           335:                tp->t_ispeed = tp->t_ospeed = dcadefaultrate;
        !           336:
        !           337:                s = spltty();
        !           338:
        !           339:                dcaparam(tp, &tp->t_termios);
        !           340:                ttsetwater(tp);
        !           341:
        !           342:                /* Set the FIFO threshold based on the receive speed. */
        !           343:                if (sc->sc_flags & DCA_HASFIFO)
        !           344:                         dca->dca_fifo = FIFO_ENABLE | FIFO_RCV_RST |
        !           345:                             FIFO_XMT_RST |
        !           346:                            (tp->t_ispeed <= 1200 ? FIFO_TRIGGER_1 :
        !           347:                            FIFO_TRIGGER_14);
        !           348:
        !           349:                /* Flush any pending I/O */
        !           350:                while ((dca->dca_iir & IIR_IMASK) == IIR_RXRDY)
        !           351:                        code = dca->dca_data;
        !           352:
        !           353:        } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
        !           354:                return (EBUSY);
        !           355:        else
        !           356:                s = spltty();
        !           357:
        !           358:        /* Set modem control state. */
        !           359:        (void) dcamctl(sc, MCR_DTR | MCR_RTS, DMSET);
        !           360:
        !           361:        /* Set soft-carrier if so configured. */
        !           362:        if ((sc->sc_flags & DCA_SOFTCAR) || DCACUA(dev) ||
        !           363:            (dcamctl(sc, 0, DMGET) & MSR_DCD))
        !           364:                tp->t_state |= TS_CARR_ON;
        !           365:
        !           366:        if (DCACUA(dev)) {
        !           367:                if (tp->t_state & TS_ISOPEN) {
        !           368:                        /* Ah, but someone already is dialed in... */
        !           369:                        splx(s);
        !           370:                        return (EBUSY);
        !           371:                }
        !           372:                sc->sc_cua = 1;         /* We go into CUA mode */
        !           373:        }
        !           374:
        !           375:        /* Wait for carrier if necessary. */
        !           376:        if (flag & O_NONBLOCK) {
        !           377:                if (!DCACUA(dev) && sc->sc_cua) {
        !           378:                        /* Opening TTY non-blocking... but the CUA is busy */
        !           379:                        splx(s);
        !           380:                        return (EBUSY);
        !           381:                }
        !           382:        } else {
        !           383:                while (sc->sc_cua ||
        !           384:                    ((tp->t_cflag & CLOCAL) == 0 &&
        !           385:                    (tp->t_state & TS_CARR_ON) == 0)) {
        !           386:                        tp->t_state |= TS_WOPEN;
        !           387:                        error = ttysleep(tp, (caddr_t)&tp->t_rawq,
        !           388:                            TTIPRI | PCATCH, ttopen, 0);
        !           389:                        if (!DCACUA(dev) && sc->sc_cua && error == EINTR)
        !           390:                                continue;
        !           391:                        if (error) {
        !           392:                                if (DCACUA(dev))
        !           393:                                        sc->sc_cua = 0;
        !           394:                                splx(s);
        !           395:                                return (error);
        !           396:                        }
        !           397:                        if (!DCACUA(dev) && sc->sc_cua)
        !           398:                                continue;
        !           399:                }
        !           400:        }
        !           401:        splx(s);
        !           402:
        !           403:        if (error == 0)
        !           404:                error = (*linesw[tp->t_line].l_open)(dev, tp);
        !           405:
        !           406:        return (error);
        !           407: }
        !           408:
        !           409: /*ARGSUSED*/
        !           410: int
        !           411: dcaclose(dev, flag, mode, p)
        !           412:        dev_t dev;
        !           413:        int flag, mode;
        !           414:        struct proc *p;
        !           415: {
        !           416:        struct dca_softc *sc;
        !           417:        struct tty *tp;
        !           418:        struct dcadevice *dca;
        !           419:        int unit;
        !           420:        int s;
        !           421:
        !           422:        unit = DCAUNIT(dev);
        !           423:
        !           424:        sc = dca_cd.cd_devs[unit];
        !           425:
        !           426:        dca = sc->sc_dca;
        !           427:        tp = sc->sc_tty;
        !           428:        (*linesw[tp->t_line].l_close)(tp, flag);
        !           429:
        !           430:        s = spltty();
        !           431:
        !           432:        dca->dca_cfcr &= ~CFCR_SBREAK;
        !           433: #ifdef KGDB
        !           434:        /* do not disable interrupts if debugging */
        !           435:        if (dev != kgdb_dev)
        !           436: #endif
        !           437:        dca->dca_ier = 0;
        !           438:        if (tp->t_cflag & HUPCL && (sc->sc_flags & DCA_SOFTCAR) == 0) {
        !           439:                /* XXX perhaps only clear DTR */
        !           440:                (void) dcamctl(sc, 0, DMSET);
        !           441:        }
        !           442:        tp->t_state &= ~(TS_BUSY | TS_FLUSH);
        !           443:        sc->sc_cua = 0;
        !           444:        splx(s);
        !           445:        ttyclose(tp);
        !           446: #if 0
        !           447:        ttyfree(tp);
        !           448:        sc->sc_tty = NULL;
        !           449: #endif
        !           450:        return (0);
        !           451: }
        !           452:
        !           453: int
        !           454: dcaread(dev, uio, flag)
        !           455:        dev_t dev;
        !           456:        struct uio *uio;
        !           457:        int flag;
        !           458: {
        !           459:        int unit = DCAUNIT(dev);
        !           460:        struct dca_softc *sc;
        !           461:        struct tty *tp;
        !           462:        int error, of;
        !           463:
        !           464:        sc = dca_cd.cd_devs[unit];
        !           465:
        !           466:        tp = sc->sc_tty;
        !           467:        of = sc->sc_oflows;
        !           468:        error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
        !           469:        /*
        !           470:         * XXX hardly a reasonable thing to do, but reporting overflows
        !           471:         * at interrupt time just exacerbates the problem.
        !           472:         */
        !           473:        if (sc->sc_oflows != of)
        !           474:                log(LOG_WARNING, "%s: silo overflow\n", sc->sc_dev.dv_xname);
        !           475:        return (error);
        !           476: }
        !           477:
        !           478: int
        !           479: dcawrite(dev, uio, flag)
        !           480:        dev_t dev;
        !           481:        struct uio *uio;
        !           482:        int flag;
        !           483: {
        !           484:        struct dca_softc *sc = dca_cd.cd_devs[DCAUNIT(dev)];
        !           485:        struct tty *tp = sc->sc_tty;
        !           486:
        !           487:        return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
        !           488: }
        !           489:
        !           490: struct tty *
        !           491: dcatty(dev)
        !           492:        dev_t dev;
        !           493: {
        !           494:        struct dca_softc *sc = dca_cd.cd_devs[DCAUNIT(dev)];
        !           495:
        !           496:        return (sc->sc_tty);
        !           497: }
        !           498:
        !           499: int
        !           500: dcaintr(arg)
        !           501:        void *arg;
        !           502: {
        !           503:        struct dca_softc *sc = arg;
        !           504: #ifdef KGDB
        !           505:        int unit = sc->sc_dev.dv_unit;
        !           506: #endif
        !           507:        struct dcadevice *dca = sc->sc_dca;
        !           508:        struct tty *tp = sc->sc_tty;
        !           509:        u_char code;
        !           510:        int iflowdone = 0;
        !           511:
        !           512:        /*
        !           513:         * If interrupts aren't enabled, then the interrupt can't
        !           514:         * be for us.
        !           515:         */
        !           516:        if ((dca->dca_ic & (IC_IR|IC_IE)) != (IC_IR|IC_IE))
        !           517:                return (0);
        !           518:
        !           519:        for (;;) {
        !           520:                code = dca->dca_iir;
        !           521: #ifdef DEBUG
        !           522:                dcaintrcount[code & IIR_IMASK]++;
        !           523: #endif
        !           524:
        !           525:                switch (code & IIR_IMASK) {
        !           526:                case IIR_NOPEND:
        !           527:                        return (1);
        !           528:                case IIR_RXTOUT:
        !           529:                case IIR_RXRDY:
        !           530:                        /* do time-critical read in-line */
        !           531: /*
        !           532:  * Process a received byte.  Inline for speed...
        !           533:  */
        !           534: #ifdef KGDB
        !           535: #define        RCVBYTE() \
        !           536:                        code = dca->dca_data; \
        !           537:                        if (tp != NULL) { \
        !           538:                                if ((tp->t_state & TS_ISOPEN) == 0) { \
        !           539:                                        if (code == FRAME_END && \
        !           540:                                            kgdb_dev == makedev(dcamajor, unit)) \
        !           541:                                                kgdb_connect(0); /* trap into kgdb */ \
        !           542:                                } else \
        !           543:                                        (*linesw[tp->t_line].l_rint)(code, tp) \
        !           544:                        }
        !           545: #else
        !           546: #define        RCVBYTE() \
        !           547:                        code = dca->dca_data; \
        !           548:                        if (tp != NULL && (tp->t_state & TS_ISOPEN) != 0) \
        !           549:                                (*linesw[tp->t_line].l_rint)(code, tp)
        !           550: #endif
        !           551:                        RCVBYTE();
        !           552:                        if (sc->sc_flags & DCA_HASFIFO) {
        !           553: #ifdef DEBUG
        !           554:                                int fifocnt = 1;
        !           555: #endif
        !           556:                                while ((code = dca->dca_lsr) & LSR_RCV_MASK) {
        !           557:                                        if (code == LSR_RXRDY) {
        !           558:                                                RCVBYTE();
        !           559:                                        } else
        !           560:                                                dcaeint(sc, code);
        !           561: #ifdef DEBUG
        !           562:                                        fifocnt++;
        !           563: #endif
        !           564:                                }
        !           565: #ifdef DEBUG
        !           566:                                if (fifocnt > 16)
        !           567:                                        fifoin[0]++;
        !           568:                                else
        !           569:                                        fifoin[fifocnt]++;
        !           570: #endif
        !           571:                        }
        !           572:                        if (!iflowdone && (tp->t_cflag&CRTS_IFLOW) &&
        !           573:                            tp->t_rawq.c_cc > TTYHOG/2) {
        !           574:                                dca->dca_mcr &= ~MCR_RTS;
        !           575:                                iflowdone = 1;
        !           576:                        }
        !           577:                        break;
        !           578:                case IIR_TXRDY:
        !           579:                        if (tp != NULL) {
        !           580:                                tp->t_state &=~ (TS_BUSY|TS_FLUSH);
        !           581:                                if (tp->t_line)
        !           582:                                        (*linesw[tp->t_line].l_start)(tp);
        !           583:                                else
        !           584:                                        dcastart(tp);
        !           585:                        }
        !           586:                        break;
        !           587:                case IIR_RLS:
        !           588:                        dcaeint(sc, dca->dca_lsr);
        !           589:                        break;
        !           590:                default:
        !           591:                        if (code & IIR_NOPEND)
        !           592:                                return (1);
        !           593:                        log(LOG_WARNING, "%s: weird interrupt: 0x%x\n",
        !           594:                            sc->sc_dev.dv_xname, code);
        !           595:                        /* FALLTHROUGH */
        !           596:                case IIR_MLSC:
        !           597:                        dcamint(sc);
        !           598:                        break;
        !           599:                }
        !           600:        }
        !           601: }
        !           602:
        !           603: void
        !           604: dcaeint(sc, stat)
        !           605:        struct dca_softc *sc;
        !           606:        int stat;
        !           607: {
        !           608:        struct tty *tp = sc->sc_tty;
        !           609:        struct dcadevice *dca = sc->sc_dca;
        !           610:        int c;
        !           611:
        !           612:        c = dca->dca_data;
        !           613:
        !           614: #if defined(DDB) && !defined(KGDB)
        !           615:        if ((sc->sc_flags & DCA_ISCONSOLE) && db_console && (stat & LSR_BI)) {
        !           616:                Debugger();
        !           617:                return;
        !           618:        }
        !           619: #endif
        !           620:
        !           621:        if (tp == NULL)
        !           622:                return;
        !           623:
        !           624:        if ((tp->t_state & TS_ISOPEN) == 0) {
        !           625: #ifdef KGDB
        !           626:                /* we don't care about parity errors */
        !           627:                if (((stat & (LSR_BI|LSR_FE|LSR_PE)) == LSR_PE) &&
        !           628:                    kgdb_dev == makedev(dcamajor, sc->sc_hd->hp_unit) &&
        !           629:                    c == FRAME_END)
        !           630:                        kgdb_connect(0); /* trap into kgdb */
        !           631: #endif
        !           632:                return;
        !           633:        }
        !           634:
        !           635:        if (stat & (LSR_BI | LSR_FE))
        !           636:                c |= TTY_FE;
        !           637:        else if (stat & LSR_PE)
        !           638:                c |= TTY_PE;
        !           639:        else if (stat & LSR_OE)
        !           640:                sc->sc_oflows++;
        !           641:        (*linesw[tp->t_line].l_rint)(c, tp);
        !           642: }
        !           643:
        !           644: void
        !           645: dcamint(sc)
        !           646:        struct dca_softc *sc;
        !           647: {
        !           648:        struct tty *tp = sc->sc_tty;
        !           649:        struct dcadevice *dca = sc->sc_dca;
        !           650:        u_char stat;
        !           651:
        !           652:        stat = dca->dca_msr;
        !           653: #ifdef DEBUG
        !           654:        dcamintcount[stat & 0xf]++;
        !           655: #endif
        !           656:
        !           657:        if (tp == NULL)
        !           658:                return;
        !           659:
        !           660:        if ((stat & MSR_DDCD) &&
        !           661:            (sc->sc_flags & DCA_SOFTCAR) == 0) {
        !           662:                if (stat & MSR_DCD)
        !           663:                        (void)(*linesw[tp->t_line].l_modem)(tp, 1);
        !           664:                else if ((*linesw[tp->t_line].l_modem)(tp, 0) == 0)
        !           665:                        dca->dca_mcr &= ~(MCR_DTR | MCR_RTS);
        !           666:        }
        !           667:        /*
        !           668:         * CTS change.
        !           669:         * If doing HW output flow control start/stop output as appropriate.
        !           670:         */
        !           671:        if ((stat & MSR_DCTS) &&
        !           672:            (tp->t_state & TS_ISOPEN) && (tp->t_cflag & CCTS_OFLOW)) {
        !           673:                if (stat & MSR_CTS) {
        !           674:                        tp->t_state &=~ TS_TTSTOP;
        !           675:                        dcastart(tp);
        !           676:                } else {
        !           677:                        tp->t_state |= TS_TTSTOP;
        !           678:                }
        !           679:        }
        !           680: }
        !           681:
        !           682: int
        !           683: dcaioctl(dev, cmd, data, flag, p)
        !           684:        dev_t dev;
        !           685:        u_long cmd;
        !           686:        caddr_t data;
        !           687:        int flag;
        !           688:        struct proc *p;
        !           689: {
        !           690:        int unit = DCAUNIT(dev);
        !           691:        struct dca_softc *sc = dca_cd.cd_devs[unit];
        !           692:        struct tty *tp = sc->sc_tty;
        !           693:        struct dcadevice *dca = sc->sc_dca;
        !           694:        int error;
        !           695:
        !           696:        error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
        !           697:        if (error >= 0)
        !           698:                return (error);
        !           699:        error = ttioctl(tp, cmd, data, flag, p);
        !           700:        if (error >= 0)
        !           701:                return (error);
        !           702:
        !           703:        switch (cmd) {
        !           704:        case TIOCSBRK:
        !           705:                dca->dca_cfcr |= CFCR_SBREAK;
        !           706:                break;
        !           707:
        !           708:        case TIOCCBRK:
        !           709:                dca->dca_cfcr &= ~CFCR_SBREAK;
        !           710:                break;
        !           711:
        !           712:        case TIOCSDTR:
        !           713:                (void) dcamctl(sc, MCR_DTR | MCR_RTS, DMBIS);
        !           714:                break;
        !           715:
        !           716:        case TIOCCDTR:
        !           717:                (void) dcamctl(sc, MCR_DTR | MCR_RTS, DMBIC);
        !           718:                break;
        !           719:
        !           720:        case TIOCMSET:
        !           721:                (void) dcamctl(sc, *(int *)data, DMSET);
        !           722:                break;
        !           723:
        !           724:        case TIOCMBIS:
        !           725:                (void) dcamctl(sc, *(int *)data, DMBIS);
        !           726:                break;
        !           727:
        !           728:        case TIOCMBIC:
        !           729:                (void) dcamctl(sc, *(int *)data, DMBIC);
        !           730:                break;
        !           731:
        !           732:        case TIOCMGET:
        !           733:                *(int *)data = dcamctl(sc, 0, DMGET);
        !           734:                break;
        !           735:
        !           736:        case TIOCGFLAGS: {
        !           737:                int bits = 0;
        !           738:
        !           739:                if (sc->sc_flags & DCA_SOFTCAR)
        !           740:                        bits |= TIOCFLAG_SOFTCAR;
        !           741:
        !           742:                if (tp->t_cflag & CLOCAL)
        !           743:                        bits |= TIOCFLAG_CLOCAL;
        !           744:
        !           745:                *(int *)data = bits;
        !           746:                break;
        !           747:        }
        !           748:
        !           749:        case TIOCSFLAGS: {
        !           750:                int userbits;
        !           751:
        !           752:                error = suser(p, 0);
        !           753:                if (error)
        !           754:                        return (EPERM);
        !           755:
        !           756:                userbits = *(int *)data;
        !           757:
        !           758:                if ((userbits & TIOCFLAG_SOFTCAR) ||
        !           759:                    (sc->sc_flags & DCA_ISCONSOLE))
        !           760:                        sc->sc_flags |= DCA_SOFTCAR;
        !           761:
        !           762:                if (userbits & TIOCFLAG_CLOCAL)
        !           763:                        tp->t_cflag |= CLOCAL;
        !           764:
        !           765:                break;
        !           766:        }
        !           767:
        !           768:        default:
        !           769:                return (ENOTTY);
        !           770:        }
        !           771:        return (0);
        !           772: }
        !           773:
        !           774: int
        !           775: dcaparam(tp, t)
        !           776:        struct tty *tp;
        !           777:        struct termios *t;
        !           778: {
        !           779:        int unit = DCAUNIT(tp->t_dev);
        !           780:        struct dca_softc *sc = dca_cd.cd_devs[unit];
        !           781:        struct dcadevice *dca = sc->sc_dca;
        !           782:        int cfcr, cflag = t->c_cflag;
        !           783:        int ospeed = ttspeedtab(t->c_ospeed, dcaspeedtab);
        !           784:        int s;
        !           785:
        !           786:        /* check requested parameters */
        !           787:         if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
        !           788:                 return (EINVAL);
        !           789:
        !           790:        switch (cflag & CSIZE) {
        !           791:        case CS5:
        !           792:                cfcr = CFCR_5BITS;
        !           793:                break;
        !           794:
        !           795:        case CS6:
        !           796:                cfcr = CFCR_6BITS;
        !           797:                break;
        !           798:
        !           799:        case CS7:
        !           800:                cfcr = CFCR_7BITS;
        !           801:                break;
        !           802:
        !           803:        case CS8:
        !           804:        default:        /* XXX gcc whines about cfcr being unitialized... */
        !           805:                cfcr = CFCR_8BITS;
        !           806:                break;
        !           807:        }
        !           808:        if (cflag & PARENB) {
        !           809:                cfcr |= CFCR_PENAB;
        !           810:                if ((cflag & PARODD) == 0)
        !           811:                        cfcr |= CFCR_PEVEN;
        !           812:        }
        !           813:        if (cflag & CSTOPB)
        !           814:                cfcr |= CFCR_STOPB;
        !           815:
        !           816:        s = spltty();
        !           817:
        !           818:        if (ospeed == 0)
        !           819:                (void) dcamctl(sc, 0, DMSET);   /* hang up line */
        !           820:
        !           821:        /*
        !           822:         * Set the FIFO threshold based on the receive speed, if we
        !           823:         * are changing it.
        !           824:         */
        !           825:        if (tp->t_ispeed != t->c_ispeed) {
        !           826:                if (sc->sc_flags & DCA_HASFIFO)
        !           827:                        dca->dca_fifo = FIFO_ENABLE |
        !           828:                            (t->c_ispeed <= 1200 ? FIFO_TRIGGER_1 :
        !           829:                            FIFO_TRIGGER_14);
        !           830:        }
        !           831:
        !           832:        if (ospeed != 0) {
        !           833:                dca->dca_cfcr |= CFCR_DLAB;
        !           834:                dca->dca_data = ospeed & 0xFF;
        !           835:                dca->dca_ier = ospeed >> 8;
        !           836:                dca->dca_cfcr = cfcr;
        !           837:        } else
        !           838:                dca->dca_cfcr = cfcr;
        !           839:
        !           840:        /* and copy to tty */
        !           841:        tp->t_ispeed = t->c_ispeed;
        !           842:        tp->t_ospeed = t->c_ospeed;
        !           843:        tp->t_cflag = cflag;
        !           844:
        !           845:        dca->dca_ier = IER_ERXRDY | IER_ETXRDY | IER_ERLS | IER_EMSC;
        !           846:        dca->dca_mcr |= MCR_IEN;
        !           847:
        !           848:        splx(s);
        !           849:        return (0);
        !           850: }
        !           851:
        !           852: void
        !           853: dcastart(tp)
        !           854:        struct tty *tp;
        !           855: {
        !           856:        int s, c, unit = DCAUNIT(tp->t_dev);
        !           857:        struct dca_softc *sc = dca_cd.cd_devs[unit];
        !           858:        struct dcadevice *dca = sc->sc_dca;
        !           859:
        !           860:        s = spltty();
        !           861:
        !           862:        if (tp->t_state & (TS_TIMEOUT|TS_TTSTOP))
        !           863:                goto out;
        !           864:        if (tp->t_outq.c_cc <= tp->t_lowat) {
        !           865:                if (tp->t_state & TS_ASLEEP) {
        !           866:                        tp->t_state &= ~TS_ASLEEP;
        !           867:                        wakeup((caddr_t)&tp->t_outq);
        !           868:                }
        !           869:                if (tp->t_outq.c_cc == 0)
        !           870:                        goto out;
        !           871:                selwakeup(&tp->t_wsel);
        !           872:        }
        !           873:        if (dca->dca_lsr & LSR_TXRDY) {
        !           874:                tp->t_state |= TS_BUSY;
        !           875:                if (sc->sc_flags & DCA_HASFIFO) {
        !           876:                        for (c = 0; c < 16 && tp->t_outq.c_cc; ++c)
        !           877:                                dca->dca_data = getc(&tp->t_outq);
        !           878: #ifdef DEBUG
        !           879:                        if (c > 16)
        !           880:                                fifoout[0]++;
        !           881:                        else
        !           882:                                fifoout[c]++;
        !           883: #endif
        !           884:                } else
        !           885:                        dca->dca_data = getc(&tp->t_outq);
        !           886:        }
        !           887:
        !           888: out:
        !           889:        splx(s);
        !           890: }
        !           891:
        !           892: /*
        !           893:  * Stop output on a line.
        !           894:  */
        !           895: /*ARGSUSED*/
        !           896: int
        !           897: dcastop(tp, flag)
        !           898:        struct tty *tp;
        !           899:        int flag;
        !           900: {
        !           901:        int s;
        !           902:
        !           903:        s = spltty();
        !           904:        if (tp->t_state & TS_BUSY)
        !           905:                if ((tp->t_state & TS_TTSTOP) == 0)
        !           906:                        tp->t_state |= TS_FLUSH;
        !           907:        splx(s);
        !           908:        return (0);
        !           909: }
        !           910:
        !           911: int
        !           912: dcamctl(sc, bits, how)
        !           913:        struct dca_softc *sc;
        !           914:        int bits, how;
        !           915: {
        !           916:        struct dcadevice *dca = sc->sc_dca;
        !           917:        int s;
        !           918:
        !           919:        /*
        !           920:         * Always make sure MCR_IEN is set (unless setting to 0)
        !           921:         */
        !           922: #ifdef KGDB
        !           923:        if (how == DMSET && kgdb_dev == makedev(dcamajor, sc->sc_hd->hp_unit))
        !           924:                bits |= MCR_IEN;
        !           925:        else
        !           926: #endif
        !           927:        if (how == DMBIS || (how == DMSET && bits))
        !           928:                bits |= MCR_IEN;
        !           929:        else if (how == DMBIC)
        !           930:                bits &= ~MCR_IEN;
        !           931:        s = spltty();
        !           932:
        !           933:        switch (how) {
        !           934:        case DMSET:
        !           935:                dca->dca_mcr = bits;
        !           936:                break;
        !           937:
        !           938:        case DMBIS:
        !           939:                dca->dca_mcr |= bits;
        !           940:                break;
        !           941:
        !           942:        case DMBIC:
        !           943:                dca->dca_mcr &= ~bits;
        !           944:                break;
        !           945:
        !           946:        case DMGET:
        !           947:                bits = dca->dca_msr;
        !           948:                break;
        !           949:        }
        !           950:        splx(s);
        !           951:        return (bits);
        !           952: }
        !           953:
        !           954: void
        !           955: dcainit(dca, rate)
        !           956:        struct dcadevice *dca;
        !           957:        int rate;
        !           958: {
        !           959:        int s;
        !           960:        short stat;
        !           961:
        !           962:        s = splhigh();
        !           963:
        !           964:        dca->dca_reset = 0xFF;
        !           965:        DELAY(100);
        !           966:        dca->dca_ic = IC_IE;
        !           967:
        !           968:        dca->dca_cfcr = CFCR_DLAB;
        !           969:        rate = ttspeedtab(rate, dcaspeedtab);
        !           970:        dca->dca_data = rate & 0xFF;
        !           971:        dca->dca_ier = rate >> 8;
        !           972:        dca->dca_cfcr = CFCR_8BITS;
        !           973:        dca->dca_ier = IER_ERXRDY | IER_ETXRDY;
        !           974:        dca->dca_fifo =
        !           975:            FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_1;
        !           976:        dca->dca_mcr = MCR_DTR | MCR_RTS;
        !           977:        DELAY(100);
        !           978:        stat = dca->dca_iir;
        !           979:        splx(s);
        !           980: }
        !           981:
        !           982: /*
        !           983:  * Following are all routines needed for DCA to act as console
        !           984:  */
        !           985:
        !           986: int
        !           987: dca_console_scan(scode, va, arg)
        !           988:        int scode;
        !           989:        caddr_t va;
        !           990:        void *arg;
        !           991: {
        !           992:        struct dcadevice *dca = (struct dcadevice *)va;
        !           993:        struct consdev *cp = arg;
        !           994:        u_int pri;
        !           995:
        !           996:        switch (dca->dca_id) {
        !           997:        case DCAID0:
        !           998:        case DCAID1:
        !           999:                pri = CN_NORMAL;
        !          1000:                break;
        !          1001:
        !          1002:        case DCAID0 | DCACON:
        !          1003:        case DCAID1 | DCACON:
        !          1004:                pri = CN_REMOTE;
        !          1005:                break;
        !          1006:
        !          1007:        default:
        !          1008:                return (0);
        !          1009:        }
        !          1010:
        !          1011: #ifdef CONSCODE
        !          1012:        /*
        !          1013:         * Raise our priority, if appropriate.
        !          1014:         */
        !          1015:        if (scode == CONSCODE)
        !          1016:                pri = CN_FORCED;
        !          1017: #endif
        !          1018:
        !          1019:        /* Only raise priority. */
        !          1020:        if (pri > cp->cn_pri)
        !          1021:                cp->cn_pri = pri;
        !          1022:
        !          1023:        /*
        !          1024:         * If our priority is higher than the currently-remembered
        !          1025:         * console, stash our priority, for the benefit of dcacninit().
        !          1026:         */
        !          1027:        if (cn_tab == NULL || cp->cn_pri > cn_tab->cn_pri) {
        !          1028:                cn_tab = cp;
        !          1029:                conscode = scode;
        !          1030:                return (DIO_SIZE(scode, va));
        !          1031:        }
        !          1032:        return (0);
        !          1033: }
        !          1034:
        !          1035: void
        !          1036: dcacnprobe(cp)
        !          1037:        struct consdev *cp;
        !          1038: {
        !          1039:
        !          1040:        /* locate the major number */
        !          1041:        for (dcamajor = 0; dcamajor < nchrdev; dcamajor++)
        !          1042:                if (cdevsw[dcamajor].d_open == dcaopen)
        !          1043:                        break;
        !          1044:
        !          1045:        /* initialize required fields */
        !          1046:        cp->cn_dev = makedev(dcamajor, 0);      /* XXX */
        !          1047:
        !          1048:        console_scan(dca_console_scan, cp);
        !          1049:
        !          1050: #ifdef KGDB
        !          1051:        /* XXX this needs to be fixed. */
        !          1052:        if (major(kgdb_dev) == 1)                       /* XXX */
        !          1053:                kgdb_dev = makedev(dcamajor, minor(kgdb_dev));
        !          1054: #endif
        !          1055: }
        !          1056:
        !          1057: /* ARGSUSED */
        !          1058: void
        !          1059: dcacninit(cp)
        !          1060:        struct consdev *cp;
        !          1061: {
        !          1062:
        !          1063:        /*
        !          1064:         * We are not interested by the second console pass.
        !          1065:         */
        !          1066:        if (consolepass != 0)
        !          1067:                return;
        !          1068:
        !          1069:        dca_cn = (struct dcadevice *)conaddr;
        !          1070:        dcainit(dca_cn, dcadefaultrate);
        !          1071:        dcaconsinit = 1;
        !          1072: }
        !          1073:
        !          1074: /* ARGSUSED */
        !          1075: int
        !          1076: dcacngetc(dev)
        !          1077:        dev_t dev;
        !          1078: {
        !          1079:        u_char stat;
        !          1080:        int c, s;
        !          1081:
        !          1082: #ifdef lint
        !          1083:        stat = dev; if (stat) return (0);
        !          1084: #endif
        !          1085:
        !          1086:        s = splhigh();
        !          1087:        while (((stat = dca_cn->dca_lsr) & LSR_RXRDY) == 0)
        !          1088:                ;
        !          1089:        c = dca_cn->dca_data;
        !          1090:        stat = dca_cn->dca_iir;
        !          1091:        splx(s);
        !          1092:        return (c);
        !          1093: }
        !          1094:
        !          1095: /*
        !          1096:  * Console kernel output character routine.
        !          1097:  */
        !          1098: /* ARGSUSED */
        !          1099: void
        !          1100: dcacnputc(dev, c)
        !          1101:        dev_t dev;
        !          1102:        int c;
        !          1103: {
        !          1104:        int timo;
        !          1105:        u_char stat;
        !          1106:        int s = splhigh();
        !          1107:
        !          1108: #ifdef lint
        !          1109:        stat = dev; if (stat) return;
        !          1110: #endif
        !          1111:
        !          1112:        if (dcaconsinit == 0) {
        !          1113:                dcainit(dca_cn, dcadefaultrate);
        !          1114:                dcaconsinit = 1;
        !          1115:        }
        !          1116:        /* wait for any pending transmission to finish */
        !          1117:        timo = 50000;
        !          1118:        while (((stat = dca_cn->dca_lsr) & LSR_TXRDY) == 0 && --timo)
        !          1119:                ;
        !          1120:        dca_cn->dca_data = c;
        !          1121:        /* wait for this transmission to complete */
        !          1122:        timo = 1500000;
        !          1123:        while (((stat = dca_cn->dca_lsr) & LSR_TXRDY) == 0 && --timo)
        !          1124:                ;
        !          1125:        /* clear any interrupts generated by this transmission */
        !          1126:        stat = dca_cn->dca_iir;
        !          1127:        splx(s);
        !          1128: }

CVSweb