[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

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