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

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

1.1     ! nbrk        1: /*     $OpenBSD: dcm.c,v 1.28 2006/01/01 11:59:37 miod Exp $   */
        !             2: /*     $NetBSD: dcm.c,v 1.41 1997/05/05 20:59:16 thorpej Exp $ */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1995, 1996, 1997 Jason R. Thorpe.  All rights reserved.
        !             6:  * Copyright (c) 1988 University of Utah.
        !             7:  * Copyright (c) 1982, 1986, 1990, 1993
        !             8:  *     The Regents of the University of California.  All rights reserved.
        !             9:  *
        !            10:  * This code is derived from software contributed to Berkeley by
        !            11:  * the Systems Programming Group of the University of Utah Computer
        !            12:  * Science Department.
        !            13:  *
        !            14:  * Redistribution and use in source and binary forms, with or without
        !            15:  * modification, are permitted provided that the following conditions
        !            16:  * are met:
        !            17:  * 1. Redistributions of source code must retain the above copyright
        !            18:  *    notice, this list of conditions and the following disclaimer.
        !            19:  * 2. Redistributions in binary form must reproduce the above copyright
        !            20:  *    notice, this list of conditions and the following disclaimer in the
        !            21:  *    documentation and/or other materials provided with the distribution.
        !            22:  * 3. Neither the name of the University nor the names of its contributors
        !            23:  *    may be used to endorse or promote products derived from this software
        !            24:  *    without specific prior written permission.
        !            25:  *
        !            26:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            27:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            28:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            29:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            30:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            31:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            32:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            33:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            34:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            35:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            36:  * SUCH DAMAGE.
        !            37:  *
        !            38:  * from Utah: $Hdr: dcm.c 1.29 92/01/21$
        !            39:  *
        !            40:  *     @(#)dcm.c       8.4 (Berkeley) 1/12/94
        !            41:  */
        !            42:
        !            43: /*
        !            44:  * TODO:
        !            45:  *     Timeouts
        !            46:  *     Test console support.
        !            47:  */
        !            48:
        !            49: /*
        !            50:  *  98642/MUX
        !            51:  */
        !            52: #include <sys/param.h>
        !            53: #include <sys/systm.h>
        !            54: #include <sys/ioctl.h>
        !            55: #include <sys/proc.h>
        !            56: #include <sys/tty.h>
        !            57: #include <sys/conf.h>
        !            58: #include <sys/file.h>
        !            59: #include <sys/uio.h>
        !            60: #include <sys/kernel.h>
        !            61: #include <sys/syslog.h>
        !            62: #include <sys/time.h>
        !            63: #include <sys/device.h>
        !            64:
        !            65: #include <machine/autoconf.h>
        !            66: #include <machine/bus.h>
        !            67: #include <machine/cpu.h>
        !            68: #include <machine/intr.h>
        !            69:
        !            70: #include <dev/cons.h>
        !            71:
        !            72: #include <hp300/dev/dioreg.h>
        !            73: #include <hp300/dev/diovar.h>
        !            74: #include <hp300/dev/diodevs.h>
        !            75: #include <hp300/dev/dcmreg.h>
        !            76:
        !            77: #ifndef DEFAULT_BAUD_RATE
        !            78: #define DEFAULT_BAUD_RATE 9600
        !            79: #endif
        !            80:
        !            81: const struct speedtab dcmspeedtab[] = {
        !            82:        {       0,      BR_0            },
        !            83:        {       50,     BR_50           },
        !            84:        {       75,     BR_75           },
        !            85:        {       110,    BR_110          },
        !            86:        {       134,    BR_134          },
        !            87:        {       150,    BR_150          },
        !            88:        {       300,    BR_300          },
        !            89:        {       600,    BR_600          },
        !            90:        {       1200,   BR_1200         },
        !            91:        {       1800,   BR_1800         },
        !            92:        {       2400,   BR_2400         },
        !            93:        {       4800,   BR_4800         },
        !            94:        {       9600,   BR_9600         },
        !            95:        {       19200,  BR_19200        },
        !            96:        {       38400,  BR_38400        },
        !            97:        {       -1,     -1              },
        !            98: };
        !            99:
        !           100: /* u-sec per character based on baudrate (assumes 1 start/8 data/1 stop bit) */
        !           101: #define        DCM_USPERCH(s)  (10000000 / (s))
        !           102:
        !           103: /*
        !           104:  * Per board interrupt scheme.  16.7ms is the polling interrupt rate
        !           105:  * (16.7ms is about 550 baud, 38.4k is 72 chars in 16.7ms).
        !           106:  */
        !           107: #define DIS_TIMER      0
        !           108: #define DIS_PERCHAR    1
        !           109: #define DIS_RESET      2
        !           110:
        !           111: int    dcmistype = -1;         /* -1 == dynamic, 0 == timer, 1 == perchar */
        !           112: int     dcminterval = 5;       /* interval (secs) between checks */
        !           113: struct dcmischeme {
        !           114:        int     dis_perchar;    /* non-zero if interrupting per char */
        !           115:        long    dis_time;       /* last time examined */
        !           116:        int     dis_intr;       /* recv interrupts during last interval */
        !           117:        int     dis_char;       /* characters read during last interval */
        !           118: };
        !           119:
        !           120: /*
        !           121:  * Stuff for DCM console support.  This could probably be done a little
        !           122:  * better.
        !           123:  */
        !           124: static struct dcmdevice *dcm_cn = NULL;        /* pointer to hardware */
        !           125: static int dcmconsinit;                        /* has been initialized */
        !           126:
        !           127: int    dcmdefaultrate = DEFAULT_BAUD_RATE;
        !           128: int    dcmconbrdbusy = 0;
        !           129: int    dcmmajor;
        !           130:
        !           131: #ifdef KGDB
        !           132: /*
        !           133:  * Kernel GDB support
        !           134:  */
        !           135: #include <machine/remote-sl.h>
        !           136:
        !           137: extern dev_t kgdb_dev;
        !           138: extern int kgdb_rate;
        !           139: extern int kgdb_debug_init;
        !           140: #endif
        !           141:
        !           142: /* #define DCMSTATS */
        !           143:
        !           144: #ifdef DEBUG
        !           145: int    dcmdebug = 0x0;
        !           146: #define DDB_SIOERR     0x01
        !           147: #define DDB_PARAM      0x02
        !           148: #define DDB_INPUT      0x04
        !           149: #define DDB_OUTPUT     0x08
        !           150: #define DDB_INTR       0x10
        !           151: #define DDB_IOCTL      0x20
        !           152: #define DDB_INTSCHM    0x40
        !           153: #define DDB_MODEM      0x80
        !           154: #define DDB_OPENCLOSE  0x100
        !           155: #endif
        !           156:
        !           157: #ifdef DCMSTATS
        !           158: #define        DCMRBSIZE       94
        !           159: #define DCMXBSIZE      24
        !           160:
        !           161: struct dcmstats {
        !           162:        long    xints;              /* # of xmit ints */
        !           163:        long    xchars;             /* # of xmit chars */
        !           164:        long    xempty;             /* times outq is empty in dcmstart */
        !           165:        long    xrestarts;          /* times completed while xmitting */
        !           166:        long    rints;              /* # of recv ints */
        !           167:        long    rchars;             /* # of recv chars */
        !           168:        long    xsilo[DCMXBSIZE+2]; /* times this many chars xmit on one int */
        !           169:        long    rsilo[DCMRBSIZE+2]; /* times this many chars read on one int */
        !           170: };
        !           171: #endif
        !           172:
        !           173: #define DCMUNIT(x)             (minor(x) & 0x7f)
        !           174: #define DCMCUA(x)              (minor(x) & 0x80)
        !           175: #define        DCMBOARD(x)             (((x) >> 2) & 0x3f)
        !           176: #define DCMPORT(x)             ((x) & 3)
        !           177:
        !           178: /*
        !           179:  * Conversion from "HP DCE" to almost-normal DCE: on the 638 8-port mux,
        !           180:  * the distribution panel uses "HP DCE" conventions.  If requested via
        !           181:  * the device flags, we swap the inputs to something closer to normal DCE,
        !           182:  * allowing a straight-through cable to a DTE or a reversed cable
        !           183:  * to a DCE (reversing 2-3, 4-5, 8-20 and leaving 6 unconnected;
        !           184:  * this gets "DCD" on pin 20 and "CTS" on 4, but doesn't connect
        !           185:  * DSR or make RTS work, though).  The following gives the full
        !           186:  * details of a cable from this mux panel to a modem:
        !           187:  *
        !           188:  *                  HP             modem
        !           189:  *             name    pin     pin     name
        !           190:  * HP inputs:
        !           191:  *             "Rx"     2       3      Tx
        !           192:  *             CTS      4       5      CTS     (only needed for CCTS_OFLOW)
        !           193:  *             DCD     20       8      DCD
        !           194:  *             "DSR"    9       6      DSR     (unneeded)
        !           195:  *             RI      22      22      RI      (unneeded)
        !           196:  *
        !           197:  * HP outputs:
        !           198:  *             "Tx"     3       2      Rx
        !           199:  *             "DTR"    6      not connected
        !           200:  *             "RTS"    8      20      DTR
        !           201:  *             "SR"    23       4      RTS     (often not needed)
        !           202:  */
        !           203: #define hp2dce_in(ibits)       (iconv[(ibits) & 0xf])
        !           204: static char iconv[16] = {
        !           205:        0,              MI_DM,          MI_CTS,         MI_CTS|MI_DM,
        !           206:        MI_CD,          MI_CD|MI_DM,    MI_CD|MI_CTS,   MI_CD|MI_CTS|MI_DM,
        !           207:        MI_RI,          MI_RI|MI_DM,    MI_RI|MI_CTS,   MI_RI|MI_CTS|MI_DM,
        !           208:        MI_RI|MI_CD,    MI_RI|MI_CD|MI_DM, MI_RI|MI_CD|MI_CTS,
        !           209:        MI_RI|MI_CD|MI_CTS|MI_DM
        !           210: };
        !           211:
        !           212: /*
        !           213:  * Note that 8-port boards appear as 2 4-port boards at consecutive
        !           214:  * select codes.
        !           215:  */
        !           216: #define        NDCMPORT        4
        !           217:
        !           218: struct dcm_softc {
        !           219:        struct  device sc_dev;          /* generic device glue */
        !           220:        struct  isr sc_isr;
        !           221:        struct  dcmdevice *sc_dcm;      /* pointer to hardware */
        !           222:        struct  tty *sc_tty[NDCMPORT];  /* our tty instances */
        !           223:        struct  modemreg *sc_modem[NDCMPORT]; /* modem control */
        !           224:        char    sc_mcndlast[NDCMPORT];  /* XXX last modem status for port */
        !           225:        short   sc_softCAR;             /* mask of ports with soft-carrier */
        !           226:        struct  dcmischeme sc_scheme;   /* interrupt scheme for board */
        !           227:        u_char  sc_cua;                 /* callout mode */
        !           228:
        !           229:        /*
        !           230:         * Mask of soft-carrier bits in config flags.
        !           231:         */
        !           232: #define        DCM_SOFTCAR     0x0000000f
        !           233:
        !           234:        int     sc_flags;               /* misc. configuration info */
        !           235:
        !           236:        /*
        !           237:         * Bits for sc_flags
        !           238:         */
        !           239: #define        DCM_ACTIVE      0x00000001      /* indicates board is alive */
        !           240: #define        DCM_ISCONSOLE   0x00000002      /* indicates board is console */
        !           241: #define        DCM_STDDCE      0x00000010      /* re-map DCE to standard */
        !           242: #define        DCM_FLAGMASK    (DCM_STDDCE)    /* mask of valid bits in config flags */
        !           243:
        !           244: #ifdef DCMSTATS
        !           245:        struct  dcmstats sc_stats;      /* metrics gathering */
        !           246: #endif
        !           247: };
        !           248:
        !           249: cdev_decl(dcm);
        !           250:
        !           251: int    dcmintr(void *);
        !           252: void   dcmpint(struct dcm_softc *, int, int);
        !           253: void   dcmrint(struct dcm_softc *);
        !           254: void   dcmreadbuf(struct dcm_softc *, int);
        !           255: void   dcmxint(struct dcm_softc *, int);
        !           256: void   dcmmint(struct dcm_softc *, int, int);
        !           257:
        !           258: int    dcmparam(struct tty *, struct termios *);
        !           259: void   dcmstart(struct tty *);
        !           260: int    dcmstop(struct tty *, int);
        !           261: int    dcmmctl(dev_t, int, int);
        !           262: void   dcmsetischeme(int, int);
        !           263: void   dcminit(struct dcmdevice *, int, int);
        !           264:
        !           265: int    dcmselftest(struct dcm_softc *);
        !           266:
        !           267: int    dcm_console_scan(int, caddr_t, void *);
        !           268: cons_decl(dcm);
        !           269:
        !           270: int    dcmmatch(struct device *, void *, void *);
        !           271: void   dcmattach(struct device *, struct device *, void *);
        !           272:
        !           273: struct cfattach dcm_ca = {
        !           274:        sizeof(struct dcm_softc), dcmmatch, dcmattach
        !           275: };
        !           276:
        !           277: struct cfdriver dcm_cd = {
        !           278:        NULL, "dcm", DV_TTY
        !           279: };
        !           280:
        !           281: int
        !           282: dcmmatch(parent, match, aux)
        !           283:        struct device *parent;
        !           284:        void *match, *aux;
        !           285: {
        !           286:        struct dio_attach_args *da = aux;
        !           287:
        !           288:        switch (da->da_id) {
        !           289:        case DIO_DEVICE_ID_DCM:
        !           290:        case DIO_DEVICE_ID_DCMREM:
        !           291:                return (1);
        !           292:        }
        !           293:
        !           294:        return (0);
        !           295: }
        !           296:
        !           297: void
        !           298: dcmattach(parent, self, aux)
        !           299:        struct device *parent, *self;
        !           300:        void *aux;
        !           301: {
        !           302:        struct dcm_softc *sc = (struct dcm_softc *)self;
        !           303:        struct dio_attach_args *da = aux;
        !           304:        struct dcmdevice *dcm;
        !           305:        int brd = self->dv_unit;
        !           306:        int scode = da->da_scode;
        !           307:        int i, mbits, code, ipl;
        !           308:
        !           309:        sc->sc_flags = 0;
        !           310:
        !           311:        if (scode == conscode) {
        !           312:                dcm = (struct dcmdevice *)conaddr;
        !           313:                sc->sc_flags |= DCM_ISCONSOLE;
        !           314:
        !           315:                /*
        !           316:                 * We didn't know which unit this would be during
        !           317:                 * the console probe, so we have to fixup cn_dev here.
        !           318:                 * Note that we always assume port 1 on the board.
        !           319:                 */
        !           320:                cn_tab->cn_dev = makedev(dcmmajor, (brd << 2) | DCMCONSPORT);
        !           321:        } else {
        !           322:                dcm = (struct dcmdevice *)iomap(dio_scodetopa(da->da_scode),
        !           323:                    da->da_size);
        !           324:                if (dcm == NULL) {
        !           325:                        printf("\n%s: can't map registers\n",
        !           326:                            sc->sc_dev.dv_xname);
        !           327:                        return;
        !           328:                }
        !           329:        }
        !           330:
        !           331:        sc->sc_dcm = dcm;
        !           332:
        !           333:        ipl = DIO_IPL(dcm);
        !           334:        printf(" ipl %d", ipl);
        !           335:
        !           336:        /*
        !           337:         * XXX someone _should_ fix this; the self test screws
        !           338:         * autoconfig messages.
        !           339:         */
        !           340:        if ((sc->sc_flags & DCM_ISCONSOLE) && dcmselftest(sc)) {
        !           341:                printf("\n%s: self-test failed\n", sc->sc_dev.dv_xname);
        !           342:                return;
        !           343:        }
        !           344:
        !           345:        /* Extract configuration info from flags. */
        !           346:        sc->sc_softCAR = self->dv_cfdata->cf_flags & DCM_SOFTCAR;
        !           347:        sc->sc_flags |= self->dv_cfdata->cf_flags & DCM_FLAGMASK;
        !           348:
        !           349:        /* Mark our unit as configured. */
        !           350:        sc->sc_flags |= DCM_ACTIVE;
        !           351:
        !           352:        /* Establish the interrupt handler. */
        !           353:        sc->sc_isr.isr_func = dcmintr;
        !           354:        sc->sc_isr.isr_arg = sc;
        !           355:        sc->sc_isr.isr_ipl = ipl;
        !           356:        sc->sc_isr.isr_priority = IPL_TTY;
        !           357:        dio_intr_establish(&sc->sc_isr, self->dv_xname);
        !           358:
        !           359:        if (dcmistype == DIS_TIMER)
        !           360:                dcmsetischeme(brd, DIS_RESET|DIS_TIMER);
        !           361:        else
        !           362:                dcmsetischeme(brd, DIS_RESET|DIS_PERCHAR);
        !           363:
        !           364:        /* load pointers to modem control */
        !           365:        sc->sc_modem[0] = &dcm->dcm_modem0;
        !           366:        sc->sc_modem[1] = &dcm->dcm_modem1;
        !           367:        sc->sc_modem[2] = &dcm->dcm_modem2;
        !           368:        sc->sc_modem[3] = &dcm->dcm_modem3;
        !           369:
        !           370:        /* set DCD (modem) and CTS (flow control) on all ports */
        !           371:        if (sc->sc_flags & DCM_STDDCE)
        !           372:                mbits = hp2dce_in(MI_CD|MI_CTS);
        !           373:        else
        !           374:                mbits = MI_CD|MI_CTS;
        !           375:
        !           376:        for (i = 0; i < NDCMPORT; i++)
        !           377:                sc->sc_modem[i]->mdmmsk = mbits;
        !           378:
        !           379:        /*
        !           380:         * Get current state of mdmin register on all ports, so that
        !           381:         * deltas will work properly.
        !           382:         */
        !           383:        for (i = 0; i < NDCMPORT; i++) {
        !           384:                code = sc->sc_modem[i]->mdmin;
        !           385:                if (sc->sc_flags & DCM_STDDCE)
        !           386:                        code = hp2dce_in(code);
        !           387:                sc->sc_mcndlast[i] = code;
        !           388:        }
        !           389:
        !           390:        dcm->dcm_ic = IC_IE;            /* turn all interrupts on */
        !           391:
        !           392:        /*
        !           393:         * Need to reset baud rate, etc. of next print so reset dcmconsinit.
        !           394:         * Also make sure console is always "hardwired"
        !           395:         */
        !           396:        if (sc->sc_flags & DCM_ISCONSOLE) {
        !           397:                dcmconsinit = 0;
        !           398:                sc->sc_softCAR |= (1 << DCMCONSPORT);
        !           399:                printf(": console on port %d\n", DCMCONSPORT);
        !           400:        } else
        !           401:                printf("\n");
        !           402:
        !           403: #ifdef KGDB
        !           404:        if (major(kgdb_dev) == dcmmajor &&
        !           405:            DCMBOARD(DCMUNIT(kgdb_dev)) == brd) {
        !           406:                if (dcmconsole == DCMUNIT(kgdb_dev))    /* XXX fixme */
        !           407:                        kgdb_dev = NODEV; /* can't debug over console port */
        !           408: #ifndef KGDB_CHEAT
        !           409:                /*
        !           410:                 * The following could potentially be replaced
        !           411:                 * by the corresponding code in dcmcnprobe.
        !           412:                 */
        !           413:                else {
        !           414:                        dcminit(dcm, DCMPORT(DCMUNIT(kgdb_dev)),
        !           415:                            kgdb_rate);
        !           416:                        if (kgdb_debug_init) {
        !           417:                                printf("%s port %d: ", sc->sc_dev.dv_xname,
        !           418:                                    DCMPORT(DCMUNIT(kgdb_dev)));
        !           419:                                kgdb_connect(1);
        !           420:                        } else
        !           421:                                printf("%s port %d: kgdb enabled\n",
        !           422:                                    sc->sc_dev.dv_xname,
        !           423:                                    DCMPORT(DCMUNIT(kgdb_dev)));
        !           424:                }
        !           425:                /* end could be replaced */
        !           426: #endif /* KGDB_CHEAT */
        !           427:        }
        !           428: #endif /* KGDB */
        !           429: }
        !           430:
        !           431: /* ARGSUSED */
        !           432: int
        !           433: dcmopen(dev, flag, mode, p)
        !           434:        dev_t dev;
        !           435:        int flag, mode;
        !           436:        struct proc *p;
        !           437: {
        !           438:        struct dcm_softc *sc;
        !           439:        struct tty *tp;
        !           440:        int unit, brd, port;
        !           441:        int error = 0, mbits, s;
        !           442:
        !           443:        unit = DCMUNIT(dev);
        !           444:        brd = DCMBOARD(unit);
        !           445:        port = DCMPORT(unit);
        !           446:
        !           447:        if (brd >= dcm_cd.cd_ndevs || port >= NDCMPORT ||
        !           448:            (sc = dcm_cd.cd_devs[brd]) == NULL)
        !           449:                return (ENXIO);
        !           450:
        !           451:        if ((sc->sc_flags & DCM_ACTIVE) == 0)
        !           452:                return (ENXIO);
        !           453:
        !           454:        s = spltty();
        !           455:        if (sc->sc_tty[port] == NULL) {
        !           456:                tp = sc->sc_tty[port] = ttymalloc();
        !           457:        } else
        !           458:                tp = sc->sc_tty[port];
        !           459:        splx(s);
        !           460:
        !           461:        tp->t_oproc = dcmstart;
        !           462:        tp->t_param = dcmparam;
        !           463:        tp->t_dev = dev;
        !           464:
        !           465:        if ((tp->t_state & TS_ISOPEN) == 0) {
        !           466:                /*
        !           467:                 * Sanity clause: reset the card on first open.
        !           468:                 * The card might be left in an inconsistent state
        !           469:                 * if the card memory is read inadvertently.
        !           470:                 */
        !           471:                dcminit(sc->sc_dcm, port, dcmdefaultrate);
        !           472:
        !           473:                tp->t_state |= TS_WOPEN;
        !           474:                ttychars(tp);
        !           475:                tp->t_iflag = TTYDEF_IFLAG;
        !           476:                tp->t_oflag = TTYDEF_OFLAG;
        !           477:                tp->t_cflag = TTYDEF_CFLAG;
        !           478:                tp->t_lflag = TTYDEF_LFLAG;
        !           479:                tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
        !           480:
        !           481:                s = spltty();
        !           482:
        !           483:                (void) dcmparam(tp, &tp->t_termios);
        !           484:                ttsetwater(tp);
        !           485:        } else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0)
        !           486:                return (EBUSY);
        !           487:        else
        !           488:                s = spltty();
        !           489:
        !           490:        /* Set modem control state. */
        !           491:        mbits = MO_ON;
        !           492:        if (sc->sc_flags & DCM_STDDCE)
        !           493:                mbits |= MO_SR;         /* pin 23, could be used as RTS */
        !           494:
        !           495:        (void) dcmmctl(dev, mbits, DMSET);      /* enable port */
        !           496:
        !           497:        /* Set soft-carrier if so configured. */
        !           498:        if ((sc->sc_softCAR & (1 << port)) || DCMCUA(dev) ||
        !           499:            (dcmmctl(dev, MO_OFF, DMGET) & MI_CD))
        !           500:                tp->t_state |= TS_CARR_ON;
        !           501:
        !           502:        if (DCMCUA(dev)) {
        !           503:                if (tp->t_state & TS_ISOPEN) {
        !           504:                        /* Ah, but someone already is dialed in... */
        !           505:                        splx(s);
        !           506:                        return (EBUSY);
        !           507:                }
        !           508:                sc->sc_cua = 1;         /* We go into CUA mode */
        !           509:        }
        !           510:
        !           511: #ifdef DEBUG
        !           512:        if (dcmdebug & DDB_MODEM)
        !           513:                printf("%s: dcmopen port %d softcarr %c\n",
        !           514:                       sc->sc_dev.dv_xname, port,
        !           515:                       (tp->t_state & TS_CARR_ON) ? '1' : '0');
        !           516: #endif
        !           517:
        !           518:        /* Wait for carrier if necessary. */
        !           519:        if (flag & O_NONBLOCK) {
        !           520:                if (!DCMCUA(dev) && sc->sc_cua) {
        !           521:                        /* Opening TTY non-blocking... but the CUA is busy */
        !           522:                        splx(s);
        !           523:                        return (EBUSY);
        !           524:                }
        !           525:        } else {
        !           526:                while (sc->sc_cua ||
        !           527:                    ((tp->t_cflag & CLOCAL) == 0 &&
        !           528:                    (tp->t_state & TS_CARR_ON) == 0)) {
        !           529:                        tp->t_state |= TS_WOPEN;
        !           530:                        error = ttysleep(tp, (caddr_t)&tp->t_rawq,
        !           531:                            TTIPRI | PCATCH, ttopen, 0);
        !           532:                        if (!DCMCUA(dev) && sc->sc_cua && error == EINTR)
        !           533:                                continue;
        !           534:                        if (error) {
        !           535:                                if (DCMCUA(dev))
        !           536:                                        sc->sc_cua = 0;
        !           537:                                splx(s);
        !           538:                                return (error);
        !           539:                        }
        !           540:                        if (!DCMCUA(dev) && sc->sc_cua)
        !           541:                                continue;
        !           542:                }
        !           543:        }
        !           544:        splx(s);
        !           545:
        !           546: #ifdef DEBUG
        !           547:        if (dcmdebug & DDB_OPENCLOSE)
        !           548:                printf("%s port %d: dcmopen: st %x fl %x\n",
        !           549:                        sc->sc_dev.dv_xname, port, tp->t_state, tp->t_flags);
        !           550: #endif
        !           551:        if (error == 0)
        !           552:                error = (*linesw[tp->t_line].l_open)(dev, tp);
        !           553:
        !           554:        return (error);
        !           555: }
        !           556:
        !           557: /*ARGSUSED*/
        !           558: int
        !           559: dcmclose(dev, flag, mode, p)
        !           560:        dev_t dev;
        !           561:        int flag, mode;
        !           562:        struct proc *p;
        !           563: {
        !           564:        int s, unit, board, port;
        !           565:        struct dcm_softc *sc;
        !           566:        struct tty *tp;
        !           567:
        !           568:        unit = DCMUNIT(dev);
        !           569:        board = DCMBOARD(unit);
        !           570:        port = DCMPORT(unit);
        !           571:
        !           572:        sc = dcm_cd.cd_devs[board];
        !           573:        tp = sc->sc_tty[port];
        !           574:
        !           575:        (*linesw[tp->t_line].l_close)(tp, flag);
        !           576:
        !           577:        s = spltty();
        !           578:
        !           579:        if (tp->t_cflag & HUPCL || tp->t_state & TS_WOPEN ||
        !           580:            (tp->t_state & TS_ISOPEN) == 0)
        !           581:                (void) dcmmctl(dev, MO_OFF, DMSET);
        !           582: #ifdef DEBUG
        !           583:        if (dcmdebug & DDB_OPENCLOSE)
        !           584:                printf("%s port %d: dcmclose: st %x fl %x\n",
        !           585:                        sc->sc_dev.dv_xname, port, tp->t_state, tp->t_flags);
        !           586: #endif
        !           587:        sc->sc_cua = 0;
        !           588:        splx(s);
        !           589:        ttyclose(tp);
        !           590: #if 0
        !           591:        ttyfree(tp);
        !           592:        sc->sc_tty[port] == NULL;
        !           593: #endif
        !           594:        return (0);
        !           595: }
        !           596:
        !           597: int
        !           598: dcmread(dev, uio, flag)
        !           599:        dev_t dev;
        !           600:        struct uio *uio;
        !           601:        int flag;
        !           602: {
        !           603:        int unit, board, port;
        !           604:        struct dcm_softc *sc;
        !           605:        struct tty *tp;
        !           606:
        !           607:        unit = DCMUNIT(dev);
        !           608:        board = DCMBOARD(unit);
        !           609:        port = DCMPORT(unit);
        !           610:
        !           611:        sc = dcm_cd.cd_devs[board];
        !           612:        tp = sc->sc_tty[port];
        !           613:
        !           614:        return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
        !           615: }
        !           616:
        !           617: int
        !           618: dcmwrite(dev, uio, flag)
        !           619:        dev_t dev;
        !           620:        struct uio *uio;
        !           621:        int flag;
        !           622: {
        !           623:        int unit, board, port;
        !           624:        struct dcm_softc *sc;
        !           625:        struct tty *tp;
        !           626:
        !           627:        unit = DCMUNIT(dev);
        !           628:        board = DCMBOARD(unit);
        !           629:        port = DCMPORT(unit);
        !           630:
        !           631:        sc = dcm_cd.cd_devs[board];
        !           632:        tp = sc->sc_tty[port];
        !           633:
        !           634:        return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
        !           635: }
        !           636:
        !           637: struct tty *
        !           638: dcmtty(dev)
        !           639:        dev_t dev;
        !           640: {
        !           641:        int unit, board, port;
        !           642:        struct dcm_softc *sc;
        !           643:
        !           644:        unit = DCMUNIT(dev);
        !           645:        board = DCMBOARD(unit);
        !           646:        port = DCMPORT(unit);
        !           647:
        !           648:        sc = dcm_cd.cd_devs[board];
        !           649:
        !           650:        return (sc->sc_tty[port]);
        !           651: }
        !           652:
        !           653: int
        !           654: dcmintr(arg)
        !           655:        void *arg;
        !           656: {
        !           657:        struct dcm_softc *sc = arg;
        !           658:        struct dcmdevice *dcm = sc->sc_dcm;
        !           659:        struct dcmischeme *dis = &sc->sc_scheme;
        !           660:        int brd = sc->sc_dev.dv_unit;
        !           661:        int code, i;
        !           662:        int pcnd[4], mcode, mcnd[4];
        !           663:
        !           664:        /*
        !           665:         * Do all guarded accesses right off to minimize
        !           666:         * block out of hardware.
        !           667:         */
        !           668:        SEM_LOCK(dcm);
        !           669:        if ((dcm->dcm_ic & IC_IR) == 0) {
        !           670:                SEM_UNLOCK(dcm);
        !           671:                return (0);
        !           672:        }
        !           673:
        !           674:        for (i = 0; i < 4; i++) {
        !           675:                pcnd[i] = dcm->dcm_icrtab[i].dcm_data;
        !           676:                dcm->dcm_icrtab[i].dcm_data = 0;
        !           677:                code = sc->sc_modem[i]->mdmin;
        !           678:                if (sc->sc_flags & DCM_STDDCE)
        !           679:                        code = hp2dce_in(code);
        !           680:                mcnd[i] = code;
        !           681:        }
        !           682:        code = dcm->dcm_iir & IIR_MASK;
        !           683:        dcm->dcm_iir = 0;       /* XXX doc claims read clears interrupt?! */
        !           684:        mcode = dcm->dcm_modemintr;
        !           685:        dcm->dcm_modemintr = 0;
        !           686:        SEM_UNLOCK(dcm);
        !           687:
        !           688: #ifdef DEBUG
        !           689:        if (dcmdebug & DDB_INTR) {
        !           690:                printf("%s: dcmintr: iir %x pc %x/%x/%x/%x ",
        !           691:                       sc->sc_dev.dv_xname, code, pcnd[0], pcnd[1],
        !           692:                       pcnd[2], pcnd[3]);
        !           693:                printf("miir %x mc %x/%x/%x/%x\n",
        !           694:                       mcode, mcnd[0], mcnd[1], mcnd[2], mcnd[3]);
        !           695:        }
        !           696: #endif
        !           697:        if (code & IIR_TIMEO)
        !           698:                dcmrint(sc);
        !           699:        if (code & IIR_PORT0)
        !           700:                dcmpint(sc, 0, pcnd[0]);
        !           701:        if (code & IIR_PORT1)
        !           702:                dcmpint(sc, 1, pcnd[1]);
        !           703:        if (code & IIR_PORT2)
        !           704:                dcmpint(sc, 2, pcnd[2]);
        !           705:        if (code & IIR_PORT3)
        !           706:                dcmpint(sc, 3, pcnd[3]);
        !           707:        if (code & IIR_MODM) {
        !           708:                if (mcode == 0 || mcode & 0x1)  /* mcode==0 -> 98642 board */
        !           709:                        dcmmint(sc, 0, mcnd[0]);
        !           710:                if (mcode & 0x2)
        !           711:                        dcmmint(sc, 1, mcnd[1]);
        !           712:                if (mcode & 0x4)
        !           713:                        dcmmint(sc, 2, mcnd[2]);
        !           714:                if (mcode & 0x8)
        !           715:                        dcmmint(sc, 3, mcnd[3]);
        !           716:        }
        !           717:
        !           718:        /*
        !           719:         * Chalk up a receiver interrupt if the timer running or one of
        !           720:         * the ports reports a special character interrupt.
        !           721:         */
        !           722:        if ((code & IIR_TIMEO) ||
        !           723:            ((pcnd[0]|pcnd[1]|pcnd[2]|pcnd[3]) & IT_SPEC))
        !           724:                dis->dis_intr++;
        !           725:        /*
        !           726:         * See if it is time to check/change the interrupt rate.
        !           727:         */
        !           728:        if (dcmistype < 0 &&
        !           729:            (i = time.tv_sec - dis->dis_time) >= dcminterval) {
        !           730:                /*
        !           731:                 * If currently per-character and averaged over 70 interrupts
        !           732:                 * per-second (66 is threshold of 600 baud) in last interval,
        !           733:                 * switch to timer mode.
        !           734:                 *
        !           735:                 * XXX decay counts ala load average to avoid spikes?
        !           736:                 */
        !           737:                if (dis->dis_perchar && dis->dis_intr > 70 * i)
        !           738:                        dcmsetischeme(brd, DIS_TIMER);
        !           739:                /*
        !           740:                 * If currently using timer and had more interrupts than
        !           741:                 * received characters in the last interval, switch back
        !           742:                 * to per-character.  Note that after changing to per-char
        !           743:                 * we must process any characters already in the queue
        !           744:                 * since they may have arrived before the bitmap was setup.
        !           745:                 *
        !           746:                 * XXX decay counts?
        !           747:                 */
        !           748:                else if (!dis->dis_perchar && dis->dis_intr > dis->dis_char) {
        !           749:                        dcmsetischeme(brd, DIS_PERCHAR);
        !           750:                        dcmrint(sc);
        !           751:                }
        !           752:                dis->dis_intr = dis->dis_char = 0;
        !           753:                dis->dis_time = time.tv_sec;
        !           754:        }
        !           755:        return (1);
        !           756: }
        !           757:
        !           758: /*
        !           759:  *  Port interrupt.  Can be two things:
        !           760:  *     First, it might be a special character (exception interrupt);
        !           761:  *     Second, it may be a buffer empty (transmit interrupt);
        !           762:  */
        !           763: void
        !           764: dcmpint(sc, port, code)
        !           765:        struct dcm_softc *sc;
        !           766:        int port, code;
        !           767: {
        !           768:
        !           769:        if (code & IT_SPEC)
        !           770:                dcmreadbuf(sc, port);
        !           771:        if (code & IT_TX)
        !           772:                dcmxint(sc, port);
        !           773: }
        !           774:
        !           775: void
        !           776: dcmrint(sc)
        !           777:        struct dcm_softc *sc;
        !           778: {
        !           779:        int port;
        !           780:
        !           781:        for (port = 0; port < NDCMPORT; port++)
        !           782:                dcmreadbuf(sc, port);
        !           783: }
        !           784:
        !           785: void
        !           786: dcmreadbuf(sc, port)
        !           787:        struct dcm_softc *sc;
        !           788:        int port;
        !           789: {
        !           790:        struct dcmdevice *dcm = sc->sc_dcm;
        !           791:        struct dcmpreg *pp = dcm_preg(dcm, port);
        !           792:        struct dcmrfifo *fifo;
        !           793:        struct tty *tp;
        !           794:        int c, stat;
        !           795:        u_int head;
        !           796:        int nch = 0;
        !           797: #ifdef DCMSTATS
        !           798:        struct dcmstats *dsp = &sc->sc_stats;
        !           799:
        !           800:        dsp->rints++;
        !           801: #endif
        !           802:        tp = sc->sc_tty[port];
        !           803:        if (tp == NULL)
        !           804:                return;
        !           805:
        !           806:        if ((tp->t_state & TS_ISOPEN) == 0) {
        !           807: #ifdef KGDB
        !           808:                if ((makedev(dcmmajor, minor(tp->t_dev)) == kgdb_dev) &&
        !           809:                    (head = pp->r_head & RX_MASK) != (pp->r_tail & RX_MASK) &&
        !           810:                    dcm->dcm_rfifos[3-port][head>>1].data_char == FRAME_START) {
        !           811:                        pp->r_head = (head + 2) & RX_MASK;
        !           812:                        kgdb_connect(0);        /* trap into kgdb */
        !           813:                        return;
        !           814:                }
        !           815: #endif /* KGDB */
        !           816:                pp->r_head = pp->r_tail & RX_MASK;
        !           817:                return;
        !           818:        }
        !           819:
        !           820:        head = pp->r_head & RX_MASK;
        !           821:        fifo = &dcm->dcm_rfifos[3-port][head>>1];
        !           822:        /*
        !           823:         * XXX upper bound on how many chars we will take in one swallow?
        !           824:         */
        !           825:        while (head != (pp->r_tail & RX_MASK)) {
        !           826:                /*
        !           827:                 * Get character/status and update head pointer as fast
        !           828:                 * as possible to make room for more characters.
        !           829:                 */
        !           830:                c = fifo->data_char;
        !           831:                stat = fifo->data_stat;
        !           832:                head = (head + 2) & RX_MASK;
        !           833:                pp->r_head = head;
        !           834:                fifo = head ? fifo+1 : &dcm->dcm_rfifos[3-port][0];
        !           835:                nch++;
        !           836:
        !           837: #ifdef DEBUG
        !           838:                if (dcmdebug & DDB_INPUT)
        !           839:                        printf("%s port %d: dcmreadbuf: c%x('%c') s%x f%x h%x t%x\n",
        !           840:                               sc->sc_dev.dv_xname, port,
        !           841:                               c&0xFF, c, stat&0xFF,
        !           842:                               tp->t_flags, head, pp->r_tail);
        !           843: #endif
        !           844:                /*
        !           845:                 * Check for and handle errors
        !           846:                 */
        !           847:                if (stat & RD_MASK) {
        !           848: #ifdef DEBUG
        !           849:                        if (dcmdebug & (DDB_INPUT|DDB_SIOERR))
        !           850:                                printf("%s port %d: dcmreadbuf: err: c%x('%c') s%x\n",
        !           851:                                       sc->sc_dev.dv_xname, port,
        !           852:                                       stat, c&0xFF, c);
        !           853: #endif
        !           854:                        if (stat & (RD_BD | RD_FE))
        !           855:                                c |= TTY_FE;
        !           856:                        else if (stat & RD_PE)
        !           857:                                c |= TTY_PE;
        !           858:                        else if (stat & RD_OVF)
        !           859:                                log(LOG_WARNING,
        !           860:                                    "%s port %d: silo overflow\n",
        !           861:                                    sc->sc_dev.dv_xname, port);
        !           862:                        else if (stat & RD_OE)
        !           863:                                log(LOG_WARNING,
        !           864:                                    "%s port %d: uart overflow\n",
        !           865:                                    sc->sc_dev.dv_xname, port);
        !           866:                }
        !           867:                (*linesw[tp->t_line].l_rint)(c, tp);
        !           868:        }
        !           869:        sc->sc_scheme.dis_char += nch;
        !           870:
        !           871: #ifdef DCMSTATS
        !           872:        dsp->rchars += nch;
        !           873:        if (nch <= DCMRBSIZE)
        !           874:                dsp->rsilo[nch]++;
        !           875:        else
        !           876:                dsp->rsilo[DCMRBSIZE+1]++;
        !           877: #endif
        !           878: }
        !           879:
        !           880: void
        !           881: dcmxint(sc, port)
        !           882:        struct dcm_softc *sc;
        !           883:        int port;
        !           884: {
        !           885:        struct tty *tp;
        !           886:
        !           887:        tp = sc->sc_tty[port];
        !           888:        if (tp == NULL || (tp->t_state & TS_ISOPEN) == 0)
        !           889:                return;
        !           890:
        !           891:        tp->t_state &= ~TS_BUSY;
        !           892:        if (tp->t_state & TS_FLUSH)
        !           893:                tp->t_state &= ~TS_FLUSH;
        !           894:        (*linesw[tp->t_line].l_start)(tp);
        !           895: }
        !           896:
        !           897: void
        !           898: dcmmint(sc, port, mcnd)
        !           899:        struct dcm_softc *sc;
        !           900:        int port, mcnd;
        !           901: {
        !           902:        int delta;
        !           903:        struct tty *tp;
        !           904:        struct dcmdevice *dcm = sc->sc_dcm;
        !           905:
        !           906:        tp = sc->sc_tty[port];
        !           907:        if (tp == NULL || (tp->t_state & TS_ISOPEN) == 0)
        !           908:                return;
        !           909:
        !           910: #ifdef DEBUG
        !           911:        if (dcmdebug & DDB_MODEM)
        !           912:                printf("%s port %d: dcmmint: mcnd %x mcndlast %x\n",
        !           913:                       sc->sc_dev.dv_xname, port, mcnd, sc->sc_mcndlast[port]);
        !           914: #endif
        !           915:        delta = mcnd ^ sc->sc_mcndlast[port];
        !           916:        sc->sc_mcndlast[port] = mcnd;
        !           917:        if ((delta & MI_CTS) && (tp->t_state & TS_ISOPEN) &&
        !           918:            (tp->t_flags & CCTS_OFLOW)) {
        !           919:                if (mcnd & MI_CTS) {
        !           920:                        tp->t_state &= ~TS_TTSTOP;
        !           921:                        ttstart(tp);
        !           922:                } else
        !           923:                        tp->t_state |= TS_TTSTOP;       /* inline dcmstop */
        !           924:        }
        !           925:        if (delta & MI_CD) {
        !           926:                if (mcnd & MI_CD)
        !           927:                        (void)(*linesw[tp->t_line].l_modem)(tp, 1);
        !           928:                else if ((sc->sc_softCAR & (1 << port)) == 0 &&
        !           929:                    (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
        !           930:                        sc->sc_modem[port]->mdmout = MO_OFF;
        !           931:                        SEM_LOCK(dcm);
        !           932:                        dcm->dcm_modemchng |= (1 << port);
        !           933:                        dcm->dcm_cr |= CR_MODM;
        !           934:                        SEM_UNLOCK(dcm);
        !           935:                        DELAY(10); /* time to change lines */
        !           936:                }
        !           937:        }
        !           938: }
        !           939:
        !           940: int
        !           941: dcmioctl(dev, cmd, data, flag, p)
        !           942:        dev_t dev;
        !           943:        u_long cmd;
        !           944:        caddr_t data;
        !           945:        int flag;
        !           946:        struct proc *p;
        !           947: {
        !           948:        struct dcm_softc *sc;
        !           949:        struct tty *tp;
        !           950:        struct dcmdevice *dcm;
        !           951:        int board, port, unit = DCMUNIT(dev);
        !           952:        int error, s;
        !           953:
        !           954:        port = DCMPORT(unit);
        !           955:        board = DCMBOARD(unit);
        !           956:
        !           957:        sc = dcm_cd.cd_devs[board];
        !           958:        dcm = sc->sc_dcm;
        !           959:        tp = sc->sc_tty[port];
        !           960:
        !           961: #ifdef DEBUG
        !           962:        if (dcmdebug & DDB_IOCTL)
        !           963:                printf("%s port %d: dcmioctl: cmd %lx data %x flag %x\n",
        !           964:                       sc->sc_dev.dv_xname, port, cmd, *data, flag);
        !           965: #endif
        !           966:        error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
        !           967:        if (error >= 0)
        !           968:                return (error);
        !           969:        error = ttioctl(tp, cmd, data, flag, p);
        !           970:        if (error >= 0)
        !           971:                return (error);
        !           972:
        !           973:        switch (cmd) {
        !           974:        case TIOCSBRK:
        !           975:                /*
        !           976:                 * Wait for transmitter buffer to empty
        !           977:                 */
        !           978:                s = spltty();
        !           979:                while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr)
        !           980:                        DELAY(DCM_USPERCH(tp->t_ospeed));
        !           981:                SEM_LOCK(dcm);
        !           982:                dcm->dcm_cmdtab[port].dcm_data |= CT_BRK;
        !           983:                dcm->dcm_cr |= (1 << port);     /* start break */
        !           984:                SEM_UNLOCK(dcm);
        !           985:                splx(s);
        !           986:                break;
        !           987:
        !           988:        case TIOCCBRK:
        !           989:                SEM_LOCK(dcm);
        !           990:                dcm->dcm_cmdtab[port].dcm_data |= CT_BRK;
        !           991:                dcm->dcm_cr |= (1 << port);     /* end break */
        !           992:                SEM_UNLOCK(dcm);
        !           993:                break;
        !           994:
        !           995:        case TIOCSDTR:
        !           996:                (void) dcmmctl(dev, MO_ON, DMBIS);
        !           997:                break;
        !           998:
        !           999:        case TIOCCDTR:
        !          1000:                (void) dcmmctl(dev, MO_ON, DMBIC);
        !          1001:                break;
        !          1002:
        !          1003:        case TIOCMSET:
        !          1004:                (void) dcmmctl(dev, *(int *)data, DMSET);
        !          1005:                break;
        !          1006:
        !          1007:        case TIOCMBIS:
        !          1008:                (void) dcmmctl(dev, *(int *)data, DMBIS);
        !          1009:                break;
        !          1010:
        !          1011:        case TIOCMBIC:
        !          1012:                (void) dcmmctl(dev, *(int *)data, DMBIC);
        !          1013:                break;
        !          1014:
        !          1015:        case TIOCMGET:
        !          1016:                *(int *)data = dcmmctl(dev, 0, DMGET);
        !          1017:                break;
        !          1018:
        !          1019:        case TIOCGFLAGS: {
        !          1020:                int bits = 0;
        !          1021:
        !          1022:                if ((sc->sc_softCAR & (1 << port)))
        !          1023:                        bits |= TIOCFLAG_SOFTCAR;
        !          1024:
        !          1025:                if (tp->t_cflag & CLOCAL)
        !          1026:                        bits |= TIOCFLAG_CLOCAL;
        !          1027:
        !          1028:                *(int *)data = bits;
        !          1029:                break;
        !          1030:        }
        !          1031:
        !          1032:        case TIOCSFLAGS: {
        !          1033:                int userbits;
        !          1034:
        !          1035:                error = suser(p, 0);
        !          1036:                if (error)
        !          1037:                        return (EPERM);
        !          1038:
        !          1039:                userbits = *(int *)data;
        !          1040:
        !          1041:                if ((userbits & TIOCFLAG_SOFTCAR) ||
        !          1042:                    ((sc->sc_flags & DCM_ISCONSOLE) &&
        !          1043:                    (port == DCMCONSPORT)))
        !          1044:                        sc->sc_softCAR |= (1 << port);
        !          1045:
        !          1046:                if (userbits & TIOCFLAG_CLOCAL)
        !          1047:                        tp->t_cflag |= CLOCAL;
        !          1048:
        !          1049:                break;
        !          1050:        }
        !          1051:
        !          1052:        default:
        !          1053:                return (ENOTTY);
        !          1054:        }
        !          1055:        return (0);
        !          1056: }
        !          1057:
        !          1058: int
        !          1059: dcmparam(tp, t)
        !          1060:        struct tty *tp;
        !          1061:        struct termios *t;
        !          1062: {
        !          1063:        struct dcm_softc *sc;
        !          1064:        struct dcmdevice *dcm;
        !          1065:        int unit, board, port, mode, cflag = t->c_cflag;
        !          1066:        int ospeed = ttspeedtab(t->c_ospeed, dcmspeedtab);
        !          1067:
        !          1068:        unit = DCMUNIT(tp->t_dev);
        !          1069:        board = DCMBOARD(unit);
        !          1070:        port = DCMPORT(unit);
        !          1071:
        !          1072:        sc = dcm_cd.cd_devs[board];
        !          1073:        dcm = sc->sc_dcm;
        !          1074:
        !          1075:        /* check requested parameters */
        !          1076:         if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
        !          1077:                 return (EINVAL);
        !          1078:         /* and copy to tty */
        !          1079:         tp->t_ispeed = t->c_ispeed;
        !          1080:         tp->t_ospeed = t->c_ospeed;
        !          1081:         tp->t_cflag = cflag;
        !          1082:        if (ospeed == 0) {
        !          1083:                (void) dcmmctl(DCMUNIT(tp->t_dev), MO_OFF, DMSET);
        !          1084:                return (0);
        !          1085:        }
        !          1086:
        !          1087:        mode = 0;
        !          1088:        switch (cflag&CSIZE) {
        !          1089:        case CS5:
        !          1090:                mode = LC_5BITS; break;
        !          1091:        case CS6:
        !          1092:                mode = LC_6BITS; break;
        !          1093:        case CS7:
        !          1094:                mode = LC_7BITS; break;
        !          1095:        case CS8:
        !          1096:                mode = LC_8BITS; break;
        !          1097:        }
        !          1098:        if (cflag&PARENB) {
        !          1099:                if (cflag&PARODD)
        !          1100:                        mode |= LC_PODD;
        !          1101:                else
        !          1102:                        mode |= LC_PEVEN;
        !          1103:        }
        !          1104:        if (cflag&CSTOPB)
        !          1105:                mode |= LC_2STOP;
        !          1106:        else
        !          1107:                mode |= LC_1STOP;
        !          1108: #ifdef DEBUG
        !          1109:        if (dcmdebug & DDB_PARAM)
        !          1110:                printf("%s port %d: dcmparam: cflag %x mode %x speed %d uperch %d\n",
        !          1111:                       sc->sc_dev.dv_xname, port, cflag, mode, tp->t_ospeed,
        !          1112:                       DCM_USPERCH(tp->t_ospeed));
        !          1113: #endif
        !          1114:
        !          1115:        /*
        !          1116:         * Wait for transmitter buffer to empty.
        !          1117:         */
        !          1118:        while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr)
        !          1119:                DELAY(DCM_USPERCH(tp->t_ospeed));
        !          1120:        /*
        !          1121:         * Make changes known to hardware.
        !          1122:         */
        !          1123:        dcm->dcm_data[port].dcm_baud = ospeed;
        !          1124:        dcm->dcm_data[port].dcm_conf = mode;
        !          1125:        SEM_LOCK(dcm);
        !          1126:        dcm->dcm_cmdtab[port].dcm_data |= CT_CON;
        !          1127:        dcm->dcm_cr |= (1 << port);
        !          1128:        SEM_UNLOCK(dcm);
        !          1129:        /*
        !          1130:         * Delay for config change to take place. Weighted by baud.
        !          1131:         * XXX why do we do this?
        !          1132:         */
        !          1133:        DELAY(16 * DCM_USPERCH(tp->t_ospeed));
        !          1134:        return (0);
        !          1135: }
        !          1136:
        !          1137: void
        !          1138: dcmstart(tp)
        !          1139:        struct tty *tp;
        !          1140: {
        !          1141:        struct dcm_softc *sc;
        !          1142:        struct dcmdevice *dcm;
        !          1143:        struct dcmpreg *pp;
        !          1144:        struct dcmtfifo *fifo;
        !          1145:        char *bp;
        !          1146:        u_int head, tail, next;
        !          1147:        int unit, board, port, nch;
        !          1148:        char buf[16];
        !          1149:        int s;
        !          1150: #ifdef DCMSTATS
        !          1151:        struct dcmstats *dsp = &sc->sc_stats;
        !          1152:        int tch = 0;
        !          1153: #endif
        !          1154:
        !          1155:        unit = DCMUNIT(tp->t_dev);
        !          1156:        board = DCMBOARD(unit);
        !          1157:        port = DCMPORT(unit);
        !          1158:
        !          1159:        sc = dcm_cd.cd_devs[board];
        !          1160:        dcm = sc->sc_dcm;
        !          1161:
        !          1162:        s = spltty();
        !          1163: #ifdef DCMSTATS
        !          1164:        dsp->xints++;
        !          1165: #endif
        !          1166: #ifdef DEBUG
        !          1167:        if (dcmdebug & DDB_OUTPUT)
        !          1168:                printf("%s port %d: dcmstart: state %x flags %x outcc %d\n",
        !          1169:                       sc->sc_dev.dv_xname, port, tp->t_state, tp->t_flags,
        !          1170:                       tp->t_outq.c_cc);
        !          1171: #endif
        !          1172:        if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
        !          1173:                goto out;
        !          1174:        if (tp->t_outq.c_cc <= tp->t_lowat) {
        !          1175:                if (tp->t_state&TS_ASLEEP) {
        !          1176:                        tp->t_state &= ~TS_ASLEEP;
        !          1177:                        wakeup((caddr_t)&tp->t_outq);
        !          1178:                }
        !          1179:                selwakeup(&tp->t_wsel);
        !          1180:        }
        !          1181:        if (tp->t_outq.c_cc == 0) {
        !          1182: #ifdef DCMSTATS
        !          1183:                dsp->xempty++;
        !          1184: #endif
        !          1185:                goto out;
        !          1186:        }
        !          1187:
        !          1188:        pp = dcm_preg(dcm, port);
        !          1189:        tail = pp->t_tail & TX_MASK;
        !          1190:        next = (tail + 1) & TX_MASK;
        !          1191:        head = pp->t_head & TX_MASK;
        !          1192:        if (head == next)
        !          1193:                goto out;
        !          1194:        fifo = &dcm->dcm_tfifos[3-port][tail];
        !          1195: again:
        !          1196:        nch = q_to_b(&tp->t_outq, buf, (head - next) & TX_MASK);
        !          1197: #ifdef DCMSTATS
        !          1198:        tch += nch;
        !          1199: #endif
        !          1200: #ifdef DEBUG
        !          1201:        if (dcmdebug & DDB_OUTPUT)
        !          1202:                printf("\thead %x tail %x nch %d\n", head, tail, nch);
        !          1203: #endif
        !          1204:        /*
        !          1205:         * Loop transmitting all the characters we can.
        !          1206:         */
        !          1207:        for (bp = buf; --nch >= 0; bp++) {
        !          1208:                fifo->data_char = *bp;
        !          1209:                pp->t_tail = next;
        !          1210:                /*
        !          1211:                 * If this is the first character,
        !          1212:                 * get the hardware moving right now.
        !          1213:                 */
        !          1214:                if (bp == buf) {
        !          1215:                        tp->t_state |= TS_BUSY;
        !          1216:                        SEM_LOCK(dcm);
        !          1217:                        dcm->dcm_cmdtab[port].dcm_data |= CT_TX;
        !          1218:                        dcm->dcm_cr |= (1 << port);
        !          1219:                        SEM_UNLOCK(dcm);
        !          1220:                }
        !          1221:                tail = next;
        !          1222:                fifo = tail ? fifo+1 : &dcm->dcm_tfifos[3-port][0];
        !          1223:                next = (next + 1) & TX_MASK;
        !          1224:        }
        !          1225:        /*
        !          1226:         * Head changed while we were loading the buffer,
        !          1227:         * go back and load some more if we can.
        !          1228:         */
        !          1229:        if (tp->t_outq.c_cc && head != (pp->t_head & TX_MASK)) {
        !          1230: #ifdef DCMSTATS
        !          1231:                dsp->xrestarts++;
        !          1232: #endif
        !          1233:                head = pp->t_head & TX_MASK;
        !          1234:                goto again;
        !          1235:        }
        !          1236:
        !          1237:        /*
        !          1238:         * Kick it one last time in case it finished while we were
        !          1239:         * loading the last bunch.
        !          1240:         */
        !          1241:        if (bp > &buf[1]) {
        !          1242:                tp->t_state |= TS_BUSY;
        !          1243:                SEM_LOCK(dcm);
        !          1244:                dcm->dcm_cmdtab[port].dcm_data |= CT_TX;
        !          1245:                dcm->dcm_cr |= (1 << port);
        !          1246:                SEM_UNLOCK(dcm);
        !          1247:        }
        !          1248: #ifdef DEBUG
        !          1249:        if (dcmdebug & DDB_INTR)
        !          1250:                printf("%s port %d: dcmstart: head %x tail %x outqcc %d\n",
        !          1251:                    sc->sc_dev.dv_xname, port, head, tail, tp->t_outq.c_cc);
        !          1252: #endif
        !          1253: out:
        !          1254: #ifdef DCMSTATS
        !          1255:        dsp->xchars += tch;
        !          1256:        if (tch <= DCMXBSIZE)
        !          1257:                dsp->xsilo[tch]++;
        !          1258:        else
        !          1259:                dsp->xsilo[DCMXBSIZE+1]++;
        !          1260: #endif
        !          1261:        splx(s);
        !          1262: }
        !          1263:
        !          1264: /*
        !          1265:  * Stop output on a line.
        !          1266:  */
        !          1267: int
        !          1268: dcmstop(tp, flag)
        !          1269:        struct tty *tp;
        !          1270:        int flag;
        !          1271: {
        !          1272:        int s;
        !          1273:
        !          1274:        s = spltty();
        !          1275:        if (tp->t_state & TS_BUSY) {
        !          1276:                /* XXX is there some way to safely stop transmission? */
        !          1277:                if ((tp->t_state&TS_TTSTOP) == 0)
        !          1278:                        tp->t_state |= TS_FLUSH;
        !          1279:        }
        !          1280:        splx(s);
        !          1281:        return (0);
        !          1282: }
        !          1283:
        !          1284: /*
        !          1285:  * Modem control
        !          1286:  */
        !          1287: int
        !          1288: dcmmctl(dev, bits, how)
        !          1289:        dev_t dev;
        !          1290:        int bits, how;
        !          1291: {
        !          1292:        struct dcm_softc *sc;
        !          1293:        struct dcmdevice *dcm;
        !          1294:        int s, unit, brd, port, hit = 0;
        !          1295:
        !          1296:        unit = DCMUNIT(dev);
        !          1297:        brd = DCMBOARD(unit);
        !          1298:        port = DCMPORT(unit);
        !          1299:
        !          1300:        sc = dcm_cd.cd_devs[brd];
        !          1301:        dcm = sc->sc_dcm;
        !          1302:
        !          1303: #ifdef DEBUG
        !          1304:        if (dcmdebug & DDB_MODEM)
        !          1305:                printf("%s port %d: dcmmctl: bits 0x%x how %x\n",
        !          1306:                       sc->sc_dev.dv_xname, port, bits, how);
        !          1307: #endif
        !          1308:
        !          1309:        s = spltty();
        !          1310:
        !          1311:        switch (how) {
        !          1312:        case DMSET:
        !          1313:                sc->sc_modem[port]->mdmout = bits;
        !          1314:                hit++;
        !          1315:                break;
        !          1316:
        !          1317:        case DMBIS:
        !          1318:                sc->sc_modem[port]->mdmout |= bits;
        !          1319:                hit++;
        !          1320:                break;
        !          1321:
        !          1322:        case DMBIC:
        !          1323:                sc->sc_modem[port]->mdmout &= ~bits;
        !          1324:                hit++;
        !          1325:                break;
        !          1326:
        !          1327:        case DMGET:
        !          1328:                bits = sc->sc_modem[port]->mdmin;
        !          1329:                if (sc->sc_flags & DCM_STDDCE)
        !          1330:                        bits = hp2dce_in(bits);
        !          1331:                break;
        !          1332:        }
        !          1333:        if (hit) {
        !          1334:                SEM_LOCK(dcm);
        !          1335:                dcm->dcm_modemchng |= 1<<(unit & 3);
        !          1336:                dcm->dcm_cr |= CR_MODM;
        !          1337:                SEM_UNLOCK(dcm);
        !          1338:                DELAY(10); /* delay until done */
        !          1339:                splx(s);
        !          1340:        }
        !          1341:        return (bits);
        !          1342: }
        !          1343:
        !          1344: /*
        !          1345:  * Set board to either interrupt per-character or at a fixed interval.
        !          1346:  */
        !          1347: void
        !          1348: dcmsetischeme(brd, flags)
        !          1349:        int brd, flags;
        !          1350: {
        !          1351:        struct dcm_softc *sc = dcm_cd.cd_devs[brd];
        !          1352:        struct dcmdevice *dcm = sc->sc_dcm;
        !          1353:        struct dcmischeme *dis = &sc->sc_scheme;
        !          1354:        int i;
        !          1355:        u_char mask;
        !          1356:        int perchar = flags & DIS_PERCHAR;
        !          1357:
        !          1358: #ifdef DEBUG
        !          1359:        if (dcmdebug & DDB_INTSCHM)
        !          1360:                printf("%s: dcmsetischeme(%d): cur %d, ints %d, chars %d\n",
        !          1361:                       sc->sc_dev.dv_xname, perchar, dis->dis_perchar,
        !          1362:                       dis->dis_intr, dis->dis_char);
        !          1363:        if ((flags & DIS_RESET) == 0 && perchar == dis->dis_perchar) {
        !          1364:                printf("%s: dcmsetischeme: redundant request %d\n",
        !          1365:                       sc->sc_dev.dv_xname, perchar);
        !          1366:                return;
        !          1367:        }
        !          1368: #endif
        !          1369:        /*
        !          1370:         * If perchar is non-zero, we enable interrupts on all characters
        !          1371:         * otherwise we disable perchar interrupts and use periodic
        !          1372:         * polling interrupts.
        !          1373:         */
        !          1374:        dis->dis_perchar = perchar;
        !          1375:        mask = perchar ? 0xf : 0x0;
        !          1376:        for (i = 0; i < 256; i++)
        !          1377:                dcm->dcm_bmap[i].data_data = mask;
        !          1378:        /*
        !          1379:         * Don't slow down tandem mode, interrupt on flow control
        !          1380:         * chars for any port on the board.
        !          1381:         */
        !          1382:        if (!perchar) {
        !          1383:                struct tty *tp;
        !          1384:                int c;
        !          1385:
        !          1386:                for (i = 0; i < NDCMPORT; i++) {
        !          1387:                        tp = sc->sc_tty[i];
        !          1388:
        !          1389:                        if ((c = tp->t_cc[VSTART]) != _POSIX_VDISABLE)
        !          1390:                                dcm->dcm_bmap[c].data_data |= (1 << i);
        !          1391:                        if ((c = tp->t_cc[VSTOP]) != _POSIX_VDISABLE)
        !          1392:                                dcm->dcm_bmap[c].data_data |= (1 << i);
        !          1393:                }
        !          1394:        }
        !          1395:        /*
        !          1396:         * Board starts with timer disabled so if first call is to
        !          1397:         * set perchar mode then we don't want to toggle the timer.
        !          1398:         */
        !          1399:        if (flags == (DIS_RESET|DIS_PERCHAR))
        !          1400:                return;
        !          1401:        /*
        !          1402:         * Toggle card 16.7ms interrupts (we first make sure that card
        !          1403:         * has cleared the bit so it will see the toggle).
        !          1404:         */
        !          1405:        while (dcm->dcm_cr & CR_TIMER)
        !          1406:                ;
        !          1407:        SEM_LOCK(dcm);
        !          1408:        dcm->dcm_cr |= CR_TIMER;
        !          1409:        SEM_UNLOCK(dcm);
        !          1410: }
        !          1411:
        !          1412: void
        !          1413: dcminit(dcm, port, rate)
        !          1414:        struct dcmdevice *dcm;
        !          1415:        int port, rate;
        !          1416: {
        !          1417:        int s, mode;
        !          1418:
        !          1419:        mode = LC_8BITS | LC_1STOP;
        !          1420:
        !          1421:        s = splhigh();
        !          1422:
        !          1423:        /*
        !          1424:         * Wait for transmitter buffer to empty.
        !          1425:         */
        !          1426:        while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr)
        !          1427:                DELAY(DCM_USPERCH(rate));
        !          1428:
        !          1429:        /*
        !          1430:         * Make changes known to hardware.
        !          1431:         */
        !          1432:        dcm->dcm_data[port].dcm_baud = ttspeedtab(rate, dcmspeedtab);
        !          1433:        dcm->dcm_data[port].dcm_conf = mode;
        !          1434:        SEM_LOCK(dcm);
        !          1435:        dcm->dcm_cmdtab[port].dcm_data |= CT_CON;
        !          1436:        dcm->dcm_cr |= (1 << port);
        !          1437:        SEM_UNLOCK(dcm);
        !          1438:
        !          1439:        /*
        !          1440:         * Delay for config change to take place. Weighted by baud.
        !          1441:         * XXX why do we do this?
        !          1442:         */
        !          1443:        DELAY(16 * DCM_USPERCH(rate));
        !          1444:        splx(s);
        !          1445: }
        !          1446:
        !          1447: /*
        !          1448:  * Empirically derived self-test magic
        !          1449:  */
        !          1450: int
        !          1451: dcmselftest(sc)
        !          1452:        struct dcm_softc *sc;
        !          1453: {
        !          1454:        struct dcmdevice *dcm = sc->sc_dcm;
        !          1455:        int timo = 0;
        !          1456:        int s, rv;
        !          1457:
        !          1458:        rv = 1;
        !          1459:
        !          1460:        s = splhigh();
        !          1461:        dcm->dcm_rsid = DCMRS;
        !          1462:        DELAY(50000);   /* 5000 is not long enough */
        !          1463:        dcm->dcm_rsid = 0;
        !          1464:        dcm->dcm_ic = IC_IE;
        !          1465:        dcm->dcm_cr = CR_SELFT;
        !          1466:        while ((dcm->dcm_ic & IC_IR) == 0) {
        !          1467:                if (++timo == 20000)
        !          1468:                        goto out;
        !          1469:                DELAY(1);
        !          1470:        }
        !          1471:        DELAY(50000);   /* XXX why is this needed ???? */
        !          1472:        while ((dcm->dcm_iir & IIR_SELFT) == 0) {
        !          1473:                if (++timo == 400000)
        !          1474:                        goto out;
        !          1475:                DELAY(1);
        !          1476:        }
        !          1477:        DELAY(50000);   /* XXX why is this needed ???? */
        !          1478:        if (dcm->dcm_stcon != ST_OK) {
        !          1479: #if 0
        !          1480:                if (hd->hp_args->hw_sc != conscode)
        !          1481:                        printf("dcm%d: self test failed: %x\n",
        !          1482:                               brd, dcm->dcm_stcon);
        !          1483: #endif
        !          1484:                goto out;
        !          1485:        }
        !          1486:        dcm->dcm_ic = IC_ID;
        !          1487:        rv = 0;
        !          1488:
        !          1489:  out:
        !          1490:        splx(s);
        !          1491:        return (rv);
        !          1492: }
        !          1493:
        !          1494: /*
        !          1495:  * Following are all routines needed for DCM to act as console
        !          1496:  */
        !          1497:
        !          1498: int
        !          1499: dcm_console_scan(scode, va, arg)
        !          1500:        int scode;
        !          1501:        caddr_t va;
        !          1502:        void *arg;
        !          1503: {
        !          1504:        struct dcmdevice *dcm = (struct dcmdevice *)va;
        !          1505:        struct consdev *cp = arg;
        !          1506:        u_int pri;
        !          1507:
        !          1508:        switch (dcm->dcm_rsid) {
        !          1509:        case DCMID:
        !          1510:                pri = CN_NORMAL;
        !          1511:                break;
        !          1512:
        !          1513:        case DCMID|DCMCON:
        !          1514:                pri = CN_REMOTE;
        !          1515:                break;
        !          1516:
        !          1517:        default:
        !          1518:                return (0);
        !          1519:        }
        !          1520:
        !          1521: #ifdef CONSCODE
        !          1522:        /*
        !          1523:         * Raise our priority, if appropriate.
        !          1524:         */
        !          1525:        if (scode == CONSCODE)
        !          1526:                pri = CN_FORCED;
        !          1527: #endif
        !          1528:
        !          1529:        /* Only raise priority. */
        !          1530:        if (pri > cp->cn_pri)
        !          1531:                cp->cn_pri = pri;
        !          1532:
        !          1533:        /*
        !          1534:         * If our priority is higher than the currently-remembered
        !          1535:         * console, stash our priority, for the benefit of dcmcninit().
        !          1536:         */
        !          1537:        if (cn_tab == NULL || cp->cn_pri > cn_tab->cn_pri) {
        !          1538:                cn_tab = cp;
        !          1539:                conscode = scode;
        !          1540:                return (DIO_SIZE(scode, va));
        !          1541:        }
        !          1542:        return (0);
        !          1543: }
        !          1544:
        !          1545: void
        !          1546: dcmcnprobe(cp)
        !          1547:        struct consdev *cp;
        !          1548: {
        !          1549:
        !          1550:        /* locate the major number */
        !          1551:        for (dcmmajor = 0; dcmmajor < nchrdev; dcmmajor++)
        !          1552:                if (cdevsw[dcmmajor].d_open == dcmopen)
        !          1553:                        break;
        !          1554:
        !          1555:        /* initialize required fields */
        !          1556:        cp->cn_dev = makedev(dcmmajor, 0);      /* XXX */
        !          1557:
        !          1558:        console_scan(dcm_console_scan, cp);
        !          1559:
        !          1560: #ifdef KGDB_CHEAT
        !          1561:        /* XXX this needs to be fixed. */
        !          1562:        /*
        !          1563:         * This doesn't currently work, at least not with ite consoles;
        !          1564:         * the console hasn't been initialized yet.
        !          1565:         */
        !          1566:        if (major(kgdb_dev) == dcmmajor &&
        !          1567:            DCMBOARD(DCMUNIT(kgdb_dev)) == DCMBOARD(unit)) {
        !          1568:                dcminit(dcm_cn, DCMPORT(DCMUNIT(kgdb_dev)), kgdb_rate);
        !          1569:                if (kgdb_debug_init) {
        !          1570:                        /*
        !          1571:                         * We assume that console is ready for us...
        !          1572:                         * this assumes that a dca or ite console
        !          1573:                         * has been selected already and will init
        !          1574:                         * on the first putc.
        !          1575:                         */
        !          1576:                        printf("dcm%d: ", DCMUNIT(kgdb_dev));
        !          1577:                        kgdb_connect(1);
        !          1578:                }
        !          1579:        }
        !          1580: #endif
        !          1581: }
        !          1582:
        !          1583: /* ARGSUSED */
        !          1584: void
        !          1585: dcmcninit(cp)
        !          1586:        struct consdev *cp;
        !          1587: {
        !          1588:
        !          1589:        /*
        !          1590:         * We are not interested by the second console pass.
        !          1591:         */
        !          1592:        if (consolepass != 0)
        !          1593:                return;
        !          1594:
        !          1595:        dcm_cn = (struct dcmdevice *)conaddr;
        !          1596:        dcminit(dcm_cn, DCMCONSPORT, dcmdefaultrate);
        !          1597:        dcmconsinit = 1;
        !          1598: }
        !          1599:
        !          1600: /* ARGSUSED */
        !          1601: int
        !          1602: dcmcngetc(dev)
        !          1603:        dev_t dev;
        !          1604: {
        !          1605:        struct dcmrfifo *fifo;
        !          1606:        struct dcmpreg *pp;
        !          1607:        u_int head;
        !          1608:        int s, c, stat;
        !          1609:
        !          1610:        pp = dcm_preg(dcm_cn, DCMCONSPORT);
        !          1611:
        !          1612:        s = splhigh();
        !          1613:        head = pp->r_head & RX_MASK;
        !          1614:        fifo = &dcm_cn->dcm_rfifos[3-DCMCONSPORT][head>>1];
        !          1615:        while (head == (pp->r_tail & RX_MASK))
        !          1616:                ;
        !          1617:        /*
        !          1618:         * If board interrupts are enabled, just let our received char
        !          1619:         * interrupt through in case some other port on the board was
        !          1620:         * busy.  Otherwise we must clear the interrupt.
        !          1621:         */
        !          1622:        SEM_LOCK(dcm_cn);
        !          1623:        if ((dcm_cn->dcm_ic & IC_IE) == 0)
        !          1624:                stat = dcm_cn->dcm_iir;
        !          1625:        SEM_UNLOCK(dcm_cn);
        !          1626:        c = fifo->data_char;
        !          1627:        stat = fifo->data_stat;
        !          1628:        pp->r_head = (head + 2) & RX_MASK;
        !          1629:        splx(s);
        !          1630:        return (c);
        !          1631: }
        !          1632:
        !          1633: /*
        !          1634:  * Console kernel output character routine.
        !          1635:  */
        !          1636: /* ARGSUSED */
        !          1637: void
        !          1638: dcmcnputc(dev, c)
        !          1639:        dev_t dev;
        !          1640:        int c;
        !          1641: {
        !          1642:        struct dcmpreg *pp;
        !          1643:        unsigned tail;
        !          1644:        int s, stat;
        !          1645:
        !          1646:        pp = dcm_preg(dcm_cn, DCMCONSPORT);
        !          1647:
        !          1648:        s = splhigh();
        !          1649: #ifdef KGDB
        !          1650:        if (dev != kgdb_dev)
        !          1651: #endif
        !          1652:        if (dcmconsinit == 0) {
        !          1653:                dcminit(dcm_cn, DCMCONSPORT, dcmdefaultrate);
        !          1654:                dcmconsinit = 1;
        !          1655:        }
        !          1656:        tail = pp->t_tail & TX_MASK;
        !          1657:        while (tail != (pp->t_head & TX_MASK))
        !          1658:                ;
        !          1659:        dcm_cn->dcm_tfifos[3-DCMCONSPORT][tail].data_char = c;
        !          1660:        pp->t_tail = tail = (tail + 1) & TX_MASK;
        !          1661:        SEM_LOCK(dcm_cn);
        !          1662:        dcm_cn->dcm_cmdtab[DCMCONSPORT].dcm_data |= CT_TX;
        !          1663:        dcm_cn->dcm_cr |= (1 << DCMCONSPORT);
        !          1664:        SEM_UNLOCK(dcm_cn);
        !          1665:        while (tail != (pp->t_head & TX_MASK))
        !          1666:                ;
        !          1667:        /*
        !          1668:         * If board interrupts are enabled, just let our completion
        !          1669:         * interrupt through in case some other port on the board
        !          1670:         * was busy.  Otherwise we must clear the interrupt.
        !          1671:         */
        !          1672:        if ((dcm_cn->dcm_ic & IC_IE) == 0) {
        !          1673:                SEM_LOCK(dcm_cn);
        !          1674:                stat = dcm_cn->dcm_iir;
        !          1675:                SEM_UNLOCK(dcm_cn);
        !          1676:        }
        !          1677:        splx(s);
        !          1678: }

CVSweb