[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

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