Annotation of Net2/arch/hp300/dev/dcm.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1988 University of Utah.
        !             3:  * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
        !             4:  * All rights reserved.
        !             5:  *
        !             6:  * This code is derived from software contributed to Berkeley by
        !             7:  * the Systems Programming Group of the University of Utah Computer
        !             8:  * Science Department.
        !             9:  *
        !            10:  * Redistribution and use in source and binary forms, with or without
        !            11:  * modification, are permitted provided that the following conditions
        !            12:  * are met:
        !            13:  * 1. Redistributions of source code must retain the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer.
        !            15:  * 2. Redistributions in binary form must reproduce the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer in the
        !            17:  *    documentation and/or other materials provided with the distribution.
        !            18:  * 3. All advertising materials mentioning features or use of this software
        !            19:  *    must display the following acknowledgement:
        !            20:  *     This product includes software developed by the University of
        !            21:  *     California, Berkeley and its contributors.
        !            22:  * 4. 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: $Hdr: dcm.c 1.26 91/01/21$
        !            39:  *
        !            40:  *     @(#)dcm.c       7.14 (Berkeley) 6/27/91
        !            41:  */
        !            42: 
        !            43: /*
        !            44:  * TODO:
        !            45:  *     Timeouts
        !            46:  *     Test console support.
        !            47:  */
        !            48: 
        !            49: #include "dcm.h"
        !            50: #if NDCM > 0
        !            51: /*
        !            52:  *  98642/MUX
        !            53:  */
        !            54: #include "sys/param.h"
        !            55: #include "sys/systm.h"
        !            56: #include "sys/ioctl.h"
        !            57: #include "sys/tty.h"
        !            58: #include "sys/proc.h"
        !            59: #include "sys/conf.h"
        !            60: #include "sys/file.h"
        !            61: #include "sys/uio.h"
        !            62: #include "sys/kernel.h"
        !            63: #include "sys/syslog.h"
        !            64: #include "sys/time.h"
        !            65: 
        !            66: #include "device.h"
        !            67: #include "dcmreg.h"
        !            68: #include "machine/cpu.h"
        !            69: #include "../hp300/isr.h"
        !            70: 
        !            71: #ifndef DEFAULT_BAUD_RATE
        !            72: #define DEFAULT_BAUD_RATE 9600
        !            73: #endif
        !            74: 
        !            75: int    ttrstrt();
        !            76: int    dcmprobe(), dcmstart(), dcmintr(), dcmparam();
        !            77: 
        !            78: struct driver dcmdriver = {
        !            79:        dcmprobe, "dcm",
        !            80: };
        !            81: 
        !            82: #define NDCMLINE (NDCM*4)
        !            83: 
        !            84: struct tty dcm_tty[NDCMLINE];
        !            85: struct modemreg *dcm_modem[NDCMLINE];
        !            86: char   mcndlast[NDCMLINE];     /* XXX last modem status for line */
        !            87: int    ndcm = NDCMLINE;
        !            88: 
        !            89: int    dcm_active;
        !            90: int    dcmsoftCAR[NDCM];
        !            91: struct dcmdevice *dcm_addr[NDCM];
        !            92: struct isr dcmisr[NDCM];
        !            93: 
        !            94: struct speedtab dcmspeedtab[] = {
        !            95:        0,      BR_0,
        !            96:        50,     BR_50,
        !            97:        75,     BR_75,
        !            98:        110,    BR_110,
        !            99:        134,    BR_134,
        !           100:        150,    BR_150,
        !           101:        300,    BR_300,
        !           102:        600,    BR_600,
        !           103:        1200,   BR_1200,
        !           104:        1800,   BR_1800,
        !           105:        2400,   BR_2400,
        !           106:        4800,   BR_4800,
        !           107:        9600,   BR_9600,
        !           108:        19200,  BR_19200,
        !           109:        38400,  BR_38400,
        !           110:        -1,     -1
        !           111: };
        !           112: 
        !           113: /* u-sec per character based on baudrate (assumes 1 start/8 data/1 stop bit) */
        !           114: #define        DCM_USPERCH(s)  (10000000 / (s))
        !           115: 
        !           116: /*
        !           117:  * Per board interrupt scheme.  16.7ms is the polling interrupt rate
        !           118:  * (16.7ms is about 550 baud, 38.4k is 72 chars in 16.7ms).
        !           119:  */
        !           120: #define DIS_TIMER      0
        !           121: #define DIS_PERCHAR    1
        !           122: #define DIS_RESET      2
        !           123: 
        !           124: int    dcmistype = -1;         /* -1 == dynamic, 0 == timer, 1 == perchar */
        !           125: int     dcminterval = 5;       /* interval (secs) between checks */
        !           126: struct dcmischeme {
        !           127:        int     dis_perchar;    /* non-zero if interrupting per char */
        !           128:        long    dis_time;       /* last time examined */
        !           129:        int     dis_intr;       /* recv interrupts during last interval */
        !           130:        int     dis_char;       /* characters read during last interval */
        !           131: } dcmischeme[NDCM];
        !           132: 
        !           133: /*
        !           134:  * Console support
        !           135:  */
        !           136: #ifdef DCMCONSOLE
        !           137: int    dcmconsole = DCMCONSOLE;
        !           138: #else
        !           139: int    dcmconsole = -1;
        !           140: #endif
        !           141: int    dcmconsinit;
        !           142: int    dcmdefaultrate = DEFAULT_BAUD_RATE;
        !           143: int    dcmconbrdbusy = 0;
        !           144: int    dcmmajor;
        !           145: extern struct tty *constty;
        !           146: 
        !           147: #ifdef KGDB
        !           148: /*
        !           149:  * Kernel GDB support
        !           150:  */
        !           151: #include "machine/remote-sl.h"
        !           152: 
        !           153: extern dev_t kgdb_dev;
        !           154: extern int kgdb_rate;
        !           155: extern int kgdb_debug_init;
        !           156: #endif
        !           157: 
        !           158: /* #define IOSTATS */
        !           159: 
        !           160: #ifdef DEBUG
        !           161: int    dcmdebug = 0x0;
        !           162: #define DDB_SIOERR     0x01
        !           163: #define DDB_PARAM      0x02
        !           164: #define DDB_INPUT      0x04
        !           165: #define DDB_OUTPUT     0x08
        !           166: #define DDB_INTR       0x10
        !           167: #define DDB_IOCTL      0x20
        !           168: #define DDB_INTSCHM    0x40
        !           169: #define DDB_MODEM      0x80
        !           170: #define DDB_OPENCLOSE  0x100
        !           171: #endif
        !           172: 
        !           173: #ifdef IOSTATS
        !           174: #define        DCMRBSIZE       94
        !           175: #define DCMXBSIZE      24
        !           176: 
        !           177: struct dcmstats {
        !           178:        long    xints;              /* # of xmit ints */
        !           179:        long    xchars;             /* # of xmit chars */
        !           180:        long    xempty;             /* times outq is empty in dcmstart */
        !           181:        long    xrestarts;          /* times completed while xmitting */
        !           182:        long    rints;              /* # of recv ints */
        !           183:        long    rchars;             /* # of recv chars */
        !           184:        long    xsilo[DCMXBSIZE+2]; /* times this many chars xmit on one int */
        !           185:        long    rsilo[DCMRBSIZE+2]; /* times this many chars read on one int */
        !           186: } dcmstats[NDCM];
        !           187: #endif
        !           188: 
        !           189: #define UNIT(x)                minor(x)
        !           190: #define        BOARD(x)        (((x) >> 2) & 0x3f)
        !           191: #define PORT(x)                ((x) & 3)
        !           192: #define MKUNIT(b,p)    (((b) << 2) | (p))
        !           193: 
        !           194: /*
        !           195:  * Conversion from "HP DCE" to almost-normal DCE: on the 638 8-port mux,
        !           196:  * the distribution panel uses "HP DCE" conventions.  If requested via
        !           197:  * the device flags, we swap the inputs to something closer to normal DCE,
        !           198:  * allowing a straight-through cable to a DTE or a reversed cable
        !           199:  * to a DCE (reversing 2-3, 4-5, 8-20 and leaving 6 unconnected;
        !           200:  * this gets "DCD" on pin 20 and "CTS" on 4, but doesn't connect
        !           201:  * DSR or make RTS work, though).  The following gives the full
        !           202:  * details of a cable from this mux panel to a modem:
        !           203:  *
        !           204:  *                  HP             modem
        !           205:  *             name    pin     pin     name
        !           206:  * HP inputs:
        !           207:  *             "Rx"     2       3      Tx
        !           208:  *             CTS      4       5      CTS     (only needed for CCTS_OFLOW)
        !           209:  *             DCD     20       8      DCD
        !           210:  *             "DSR"    9       6      DSR     (unneeded)
        !           211:  *             RI      22      22      RI      (unneeded)
        !           212:  *
        !           213:  * HP outputs:
        !           214:  *             "Tx"     3       2      Rx
        !           215:  *             "DTR"    6      not connected
        !           216:  *             "RTS"    8      20      DTR
        !           217:  *             "SR"    23       4      RTS     (often not needed)
        !           218:  */
        !           219: #define        FLAG_STDDCE     0x10    /* map inputs if this bit is set in flags */
        !           220: #define hp2dce_in(ibits)       (iconv[(ibits) & 0xf])
        !           221: static char iconv[16] = {
        !           222:        0,              MI_DM,          MI_CTS,         MI_CTS|MI_DM,
        !           223:        MI_CD,          MI_CD|MI_DM,    MI_CD|MI_CTS,   MI_CD|MI_CTS|MI_DM,
        !           224:        MI_RI,          MI_RI|MI_DM,    MI_RI|MI_CTS,   MI_RI|MI_CTS|MI_DM,
        !           225:        MI_RI|MI_CD,    MI_RI|MI_CD|MI_DM, MI_RI|MI_CD|MI_CTS,
        !           226:        MI_RI|MI_CD|MI_CTS|MI_DM
        !           227: };
        !           228: 
        !           229: dcmprobe(hd)
        !           230:        register struct hp_device *hd;
        !           231: {
        !           232:        register struct dcmdevice *dcm;
        !           233:        register int i;
        !           234:        register int timo = 0;
        !           235:        int s, brd, isconsole, mbits;
        !           236: 
        !           237:        dcm = (struct dcmdevice *)hd->hp_addr;
        !           238:        if ((dcm->dcm_rsid & 0x1f) != DCMID)
        !           239:                return (0);
        !           240:        brd = hd->hp_unit;
        !           241:        isconsole = (brd == BOARD(dcmconsole));
        !           242:        /*
        !           243:         * XXX selected console device (CONSUNIT) as determined by
        !           244:         * dcmcnprobe does not agree with logical numbering imposed
        !           245:         * by the config file (i.e. lowest address DCM is not unit
        !           246:         * CONSUNIT).  Don't recognize this card.
        !           247:         */
        !           248:        if (isconsole && dcm != dcm_addr[BOARD(dcmconsole)])
        !           249:                return (0);
        !           250: 
        !           251:        /*
        !           252:         * Empirically derived self-test magic
        !           253:         */
        !           254:        s = spltty();
        !           255:        dcm->dcm_rsid = DCMRS;
        !           256:        DELAY(50000);   /* 5000 is not long enough */
        !           257:        dcm->dcm_rsid = 0; 
        !           258:        dcm->dcm_ic = IC_IE;
        !           259:        dcm->dcm_cr = CR_SELFT;
        !           260:        while ((dcm->dcm_ic & IC_IR) == 0)
        !           261:                if (++timo == 20000)
        !           262:                        return (0);
        !           263:        DELAY(50000)    /* XXX why is this needed ???? */
        !           264:        while ((dcm->dcm_iir & IIR_SELFT) == 0)
        !           265:                if (++timo == 400000)
        !           266:                        return (0);
        !           267:        DELAY(50000)    /* XXX why is this needed ???? */
        !           268:        if (dcm->dcm_stcon != ST_OK) {
        !           269:                if (!isconsole)
        !           270:                        printf("dcm%d: self test failed: %x\n",
        !           271:                               brd, dcm->dcm_stcon);
        !           272:                return (0);
        !           273:        }
        !           274:        dcm->dcm_ic = IC_ID;
        !           275:        splx(s);
        !           276: 
        !           277:        hd->hp_ipl = DCMIPL(dcm->dcm_ic);
        !           278:        dcm_addr[brd] = dcm;
        !           279:        dcm_active |= 1 << brd;
        !           280:        dcmsoftCAR[brd] = hd->hp_flags;
        !           281:        dcmisr[brd].isr_ipl = hd->hp_ipl;
        !           282:        dcmisr[brd].isr_arg = brd;
        !           283:        dcmisr[brd].isr_intr = dcmintr;
        !           284:        isrlink(&dcmisr[brd]);
        !           285: #ifdef KGDB
        !           286:        if (major(kgdb_dev) == dcmmajor && BOARD(kgdb_dev) == brd) {
        !           287:                if (dcmconsole == UNIT(kgdb_dev))
        !           288:                        kgdb_dev = NODEV; /* can't debug over console port */
        !           289: #ifndef KGDB_CHEAT
        !           290:                /*
        !           291:                 * The following could potentially be replaced
        !           292:                 * by the corresponding code in dcmcnprobe.
        !           293:                 */
        !           294:                else {
        !           295:                        (void) dcminit(kgdb_dev, kgdb_rate);
        !           296:                        if (kgdb_debug_init) {
        !           297:                                printf("dcm%d: ", UNIT(kgdb_dev));
        !           298:                                kgdb_connect(1);
        !           299:                        } else
        !           300:                                printf("dcm%d: kgdb enabled\n", UNIT(kgdb_dev));
        !           301:                }
        !           302:                /* end could be replaced */
        !           303: #endif
        !           304:        }
        !           305: #endif
        !           306:        if (dcmistype == DIS_TIMER)
        !           307:                dcmsetischeme(brd, DIS_RESET|DIS_TIMER);
        !           308:        else
        !           309:                dcmsetischeme(brd, DIS_RESET|DIS_PERCHAR);
        !           310: 
        !           311:        /* load pointers to modem control */
        !           312:        dcm_modem[MKUNIT(brd, 0)] = &dcm->dcm_modem0;
        !           313:        dcm_modem[MKUNIT(brd, 1)] = &dcm->dcm_modem1;
        !           314:        dcm_modem[MKUNIT(brd, 2)] = &dcm->dcm_modem2;
        !           315:        dcm_modem[MKUNIT(brd, 3)] = &dcm->dcm_modem3;
        !           316:        /* set DCD (modem) and CTS (flow control) on all ports */
        !           317:        if (dcmsoftCAR[brd] & FLAG_STDDCE)
        !           318:                mbits = hp2dce_in(MI_CD|MI_CTS);
        !           319:        else
        !           320:                mbits = MI_CD|MI_CTS;
        !           321:        for (i = 0; i < 4; i++)
        !           322:                dcm_modem[MKUNIT(brd, i)]->mdmmsk = mbits;
        !           323: 
        !           324:        dcm->dcm_ic = IC_IE;            /* turn all interrupts on */
        !           325:        /*
        !           326:         * Need to reset baud rate, etc. of next print so reset dcmconsole.
        !           327:         * Also make sure console is always "hardwired"
        !           328:         */
        !           329:        if (isconsole) {
        !           330:                dcmconsinit = 0;
        !           331:                dcmsoftCAR[brd] |= (1 << PORT(dcmconsole));
        !           332:        }
        !           333:        return (1);
        !           334: }
        !           335: 
        !           336: /* ARGSUSED */
        !           337: #ifdef __STDC__
        !           338: dcmopen(dev_t dev, int flag, int mode, struct proc *p)
        !           339: #else
        !           340: dcmopen(dev, flag, mode, p)
        !           341:        dev_t dev;
        !           342:        int flag, mode;
        !           343:        struct proc *p;
        !           344: #endif
        !           345: {
        !           346:        register struct tty *tp;
        !           347:        register int unit, brd;
        !           348:        int error = 0, mbits;
        !           349: 
        !           350:        unit = UNIT(dev);
        !           351:        brd = BOARD(unit);
        !           352:        if (unit >= NDCMLINE || (dcm_active & (1 << brd)) == 0)
        !           353:                return (ENXIO);
        !           354:        tp = &dcm_tty[unit];
        !           355:        tp->t_oproc = dcmstart;
        !           356:        tp->t_param = dcmparam;
        !           357:        tp->t_dev = dev;
        !           358:        if ((tp->t_state & TS_ISOPEN) == 0) {
        !           359:                tp->t_state |= TS_WOPEN;
        !           360:                ttychars(tp);
        !           361:                if (tp->t_ispeed == 0) {
        !           362:                        tp->t_iflag = TTYDEF_IFLAG;
        !           363:                        tp->t_oflag = TTYDEF_OFLAG;
        !           364:                        tp->t_cflag = TTYDEF_CFLAG;
        !           365:                        tp->t_lflag = TTYDEF_LFLAG;
        !           366:                        tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
        !           367:                }
        !           368:                (void) dcmparam(tp, &tp->t_termios);
        !           369:                ttsetwater(tp);
        !           370:        } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
        !           371:                return (EBUSY);
        !           372:        mbits = MO_ON;
        !           373:        if (dcmsoftCAR[brd] & FLAG_STDDCE)
        !           374:                mbits |= MO_SR;         /* pin 23, could be used as RTS */
        !           375:        (void) dcmmctl(dev, mbits, DMSET);      /* enable port */
        !           376:        if ((dcmsoftCAR[brd] & (1 << PORT(unit))) ||
        !           377:            (dcmmctl(dev, MO_OFF, DMGET) & MI_CD))
        !           378:                tp->t_state |= TS_CARR_ON;
        !           379: #ifdef DEBUG
        !           380:        if (dcmdebug & DDB_MODEM)
        !           381:                printf("dcm%d: dcmopen port %d softcarr %c\n",
        !           382:                       brd, unit, (tp->t_state & TS_CARR_ON) ? '1' : '0');
        !           383: #endif
        !           384:        (void) spltty();
        !           385:        while ((flag&O_NONBLOCK) == 0 && (tp->t_cflag&CLOCAL) == 0 &&
        !           386:            (tp->t_state & TS_CARR_ON) == 0) {
        !           387:                tp->t_state |= TS_WOPEN;
        !           388:                if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
        !           389:                    ttopen, 0))
        !           390:                        break;
        !           391:        }
        !           392:        (void) spl0();
        !           393: 
        !           394: #ifdef DEBUG
        !           395:        if (dcmdebug & DDB_OPENCLOSE)
        !           396:                printf("dcmopen: u %x st %x fl %x\n",
        !           397:                        unit, tp->t_state, tp->t_flags);
        !           398: #endif
        !           399:        if (error == 0)
        !           400:                error = (*linesw[tp->t_line].l_open)(dev, tp);
        !           401:        return (error);
        !           402: }
        !           403:  
        !           404: /*ARGSUSED*/
        !           405: dcmclose(dev, flag, mode, p)
        !           406:        dev_t dev;
        !           407:        int flag, mode;
        !           408:        struct proc *p;
        !           409: {
        !           410:        register struct tty *tp;
        !           411:        int unit;
        !           412:  
        !           413:        unit = UNIT(dev);
        !           414:        tp = &dcm_tty[unit];
        !           415:        (*linesw[tp->t_line].l_close)(tp, flag);
        !           416:        if (tp->t_cflag&HUPCL || tp->t_state&TS_WOPEN ||
        !           417:            (tp->t_state&TS_ISOPEN) == 0)
        !           418:                (void) dcmmctl(dev, MO_OFF, DMSET);
        !           419: #ifdef DEBUG
        !           420:        if (dcmdebug & DDB_OPENCLOSE)
        !           421:                printf("dcmclose: u %x st %x fl %x\n",
        !           422:                        unit, tp->t_state, tp->t_flags);
        !           423: #endif
        !           424:        ttyclose(tp);
        !           425:        return (0);
        !           426: }
        !           427:  
        !           428: dcmread(dev, uio, flag)
        !           429:        dev_t dev;
        !           430:        struct uio *uio;
        !           431: {
        !           432:        register struct tty *tp;
        !           433:  
        !           434:        tp = &dcm_tty[UNIT(dev)];
        !           435:        return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
        !           436: }
        !           437:  
        !           438: dcmwrite(dev, uio, flag)
        !           439:        dev_t dev;
        !           440:        struct uio *uio;
        !           441: {
        !           442:        int unit = UNIT(dev);
        !           443:        register struct tty *tp;
        !           444:  
        !           445:        tp = &dcm_tty[unit];
        !           446:        /*
        !           447:         * XXX we disallow virtual consoles if the physical console is
        !           448:         * a serial port.  This is in case there is a display attached that
        !           449:         * is not the console.  In that situation we don't need/want the X
        !           450:         * server taking over the console.
        !           451:         */
        !           452:        if (constty && unit == dcmconsole)
        !           453:                constty = NULL;
        !           454:        return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
        !           455: }
        !           456:  
        !           457: dcmintr(brd)
        !           458:        register int brd;
        !           459: {
        !           460:        register struct dcmdevice *dcm = dcm_addr[brd];
        !           461:        register struct dcmischeme *dis;
        !           462:        register int unit = MKUNIT(brd, 0);
        !           463:        register int code, i;
        !           464:        int pcnd[4], mcode, mcnd[4];
        !           465: 
        !           466:        /*
        !           467:         * Do all guarded register accesses right off to minimize
        !           468:         * block out of hardware.
        !           469:         */
        !           470:        SEM_LOCK(dcm);
        !           471:        if ((dcm->dcm_ic & IC_IR) == 0) {
        !           472:                SEM_UNLOCK(dcm);
        !           473:                return (0);
        !           474:        }
        !           475:        for (i = 0; i < 4; i++) {
        !           476:                pcnd[i] = dcm->dcm_icrtab[i].dcm_data;
        !           477:                dcm->dcm_icrtab[i].dcm_data = 0;
        !           478:                code = dcm_modem[unit+i]->mdmin;
        !           479:                if (dcmsoftCAR[brd] & FLAG_STDDCE)
        !           480:                        code = hp2dce_in(code);
        !           481:                mcnd[i] = code;
        !           482:        }
        !           483:        code = dcm->dcm_iir & IIR_MASK;
        !           484:        dcm->dcm_iir = 0;       /* XXX doc claims read clears interrupt?! */
        !           485:        mcode = dcm->dcm_modemintr;
        !           486:        dcm->dcm_modemintr = 0;
        !           487:        SEM_UNLOCK(dcm);
        !           488: 
        !           489: #ifdef DEBUG
        !           490:        if (dcmdebug & DDB_INTR) {
        !           491:                printf("dcmintr(%d): iir %x pc %x/%x/%x/%x ",
        !           492:                       brd, code, pcnd[0], pcnd[1], pcnd[2], pcnd[3]); 
        !           493:                printf("miir %x mc %x/%x/%x/%x\n",
        !           494:                       mcode, mcnd[0], mcnd[1], mcnd[2], mcnd[3]);
        !           495:        }
        !           496: #endif
        !           497:        if (code & IIR_TIMEO)
        !           498:                dcmrint(brd, dcm);
        !           499:        if (code & IIR_PORT0)
        !           500:                dcmpint(unit+0, pcnd[0], dcm);
        !           501:        if (code & IIR_PORT1)
        !           502:                dcmpint(unit+1, pcnd[1], dcm);
        !           503:        if (code & IIR_PORT2)
        !           504:                dcmpint(unit+2, pcnd[2], dcm);
        !           505:        if (code & IIR_PORT3)
        !           506:                dcmpint(unit+3, pcnd[3], dcm);
        !           507:        if (code & IIR_MODM) {
        !           508:                if (mcode == 0 || mcode & 0x1)  /* mcode==0 -> 98642 board */
        !           509:                        dcmmint(unit+0, mcnd[0], dcm);
        !           510:                if (mcode & 0x2)
        !           511:                        dcmmint(unit+1, mcnd[1], dcm);
        !           512:                if (mcode & 0x4)
        !           513:                        dcmmint(unit+2, mcnd[2], dcm);
        !           514:                if (mcode & 0x8)
        !           515:                        dcmmint(unit+3, mcnd[3], dcm);
        !           516:        }
        !           517: 
        !           518:        dis = &dcmischeme[brd];
        !           519:        /*
        !           520:         * Chalk up a receiver interrupt if the timer running or one of
        !           521:         * the ports reports a special character interrupt.
        !           522:         */
        !           523:        if ((code & IIR_TIMEO) ||
        !           524:            ((pcnd[0]|pcnd[1]|pcnd[2]|pcnd[3]) & IT_SPEC))
        !           525:                dis->dis_intr++;
        !           526:        /*
        !           527:         * See if it is time to check/change the interrupt rate.
        !           528:         */
        !           529:        if (dcmistype < 0 &&
        !           530:            (i = time.tv_sec - dis->dis_time) >= dcminterval) {
        !           531:                /*
        !           532:                 * If currently per-character and averaged over 70 interrupts
        !           533:                 * per-second (66 is threshold of 600 baud) in last interval,
        !           534:                 * switch to timer mode.
        !           535:                 *
        !           536:                 * XXX decay counts ala load average to avoid spikes?
        !           537:                 */
        !           538:                if (dis->dis_perchar && dis->dis_intr > 70 * i)
        !           539:                        dcmsetischeme(brd, DIS_TIMER);
        !           540:                /*
        !           541:                 * If currently using timer and had more interrupts than
        !           542:                 * received characters in the last interval, switch back
        !           543:                 * to per-character.  Note that after changing to per-char
        !           544:                 * we must process any characters already in the queue
        !           545:                 * since they may have arrived before the bitmap was setup.
        !           546:                 *
        !           547:                 * XXX decay counts?
        !           548:                 */
        !           549:                else if (!dis->dis_perchar && dis->dis_intr > dis->dis_char) {
        !           550:                        dcmsetischeme(brd, DIS_PERCHAR);
        !           551:                        dcmrint(brd, dcm);
        !           552:                }
        !           553:                dis->dis_intr = dis->dis_char = 0;
        !           554:                dis->dis_time = time.tv_sec;
        !           555:        }
        !           556:        return (1);
        !           557: }
        !           558: 
        !           559: /*
        !           560:  *  Port interrupt.  Can be two things:
        !           561:  *     First, it might be a special character (exception interrupt);
        !           562:  *     Second, it may be a buffer empty (transmit interrupt);
        !           563:  */
        !           564: dcmpint(unit, code, dcm)
        !           565:        int unit, code;
        !           566:        struct dcmdevice *dcm;
        !           567: {
        !           568:        struct tty *tp = &dcm_tty[unit];
        !           569: 
        !           570:        if (code & IT_SPEC)
        !           571:                dcmreadbuf(unit, dcm, tp);
        !           572:        if (code & IT_TX)
        !           573:                dcmxint(unit, dcm, tp);
        !           574: }
        !           575: 
        !           576: dcmrint(brd, dcm)
        !           577:        int brd;
        !           578:        register struct dcmdevice *dcm;
        !           579: {
        !           580:        register int i, unit;
        !           581:        register struct tty *tp;
        !           582: 
        !           583:        unit = MKUNIT(brd, 0);
        !           584:        tp = &dcm_tty[unit];
        !           585:        for (i = 0; i < 4; i++, tp++, unit++)
        !           586:                dcmreadbuf(unit, dcm, tp);
        !           587: }
        !           588: 
        !           589: dcmreadbuf(unit, dcm, tp)
        !           590:        int unit;
        !           591:        register struct dcmdevice *dcm;
        !           592:        register struct tty *tp;
        !           593: {
        !           594:        int port = PORT(unit);
        !           595:        register struct dcmpreg *pp = dcm_preg(dcm, port);
        !           596:        register struct dcmrfifo *fifo;
        !           597:        register int c, stat;
        !           598:        register unsigned head;
        !           599:        int nch = 0;
        !           600: #ifdef IOSTATS
        !           601:        struct dcmstats *dsp = &dcmstats[BOARD(unit)];
        !           602: 
        !           603:        dsp->rints++;
        !           604: #endif
        !           605:        if ((tp->t_state & TS_ISOPEN) == 0) {
        !           606: #ifdef KGDB
        !           607:                if ((makedev(dcmmajor, unit) == kgdb_dev) &&
        !           608:                    (head = pp->r_head & RX_MASK) != (pp->r_tail & RX_MASK) &&
        !           609:                    dcm->dcm_rfifos[3-port][head>>1].data_char == FRAME_END) {
        !           610:                        pp->r_head = (head + 2) & RX_MASK;
        !           611:                        kgdb_connect(0);        /* trap into kgdb */
        !           612:                        return;
        !           613:                }
        !           614: #endif /* KGDB */
        !           615:                pp->r_head = pp->r_tail & RX_MASK;
        !           616:                return;
        !           617:        }
        !           618: 
        !           619:        head = pp->r_head & RX_MASK;
        !           620:        fifo = &dcm->dcm_rfifos[3-port][head>>1];
        !           621:        /*
        !           622:         * XXX upper bound on how many chars we will take in one swallow?
        !           623:         */
        !           624:        while (head != (pp->r_tail & RX_MASK)) {
        !           625:                /*
        !           626:                 * Get character/status and update head pointer as fast
        !           627:                 * as possible to make room for more characters.
        !           628:                 */
        !           629:                c = fifo->data_char;
        !           630:                stat = fifo->data_stat;
        !           631:                head = (head + 2) & RX_MASK;
        !           632:                pp->r_head = head;
        !           633:                fifo = head ? fifo+1 : &dcm->dcm_rfifos[3-port][0];
        !           634:                nch++;
        !           635: 
        !           636: #ifdef DEBUG
        !           637:                if (dcmdebug & DDB_INPUT)
        !           638:                        printf("dcmreadbuf(%d): c%x('%c') s%x f%x h%x t%x\n",
        !           639:                               unit, c&0xFF, c, stat&0xFF,
        !           640:                               tp->t_flags, head, pp->r_tail);
        !           641: #endif
        !           642:                /*
        !           643:                 * Check for and handle errors
        !           644:                 */
        !           645:                if (stat & RD_MASK) {
        !           646: #ifdef DEBUG
        !           647:                        if (dcmdebug & (DDB_INPUT|DDB_SIOERR))
        !           648:                                printf("dcmreadbuf(%d): err: c%x('%c') s%x\n",
        !           649:                                       unit, stat, c&0xFF, c);
        !           650: #endif
        !           651:                        if (stat & (RD_BD | RD_FE))
        !           652:                                c |= TTY_FE;
        !           653:                        else if (stat & RD_PE)
        !           654:                                c |= TTY_PE;
        !           655:                        else if (stat & RD_OVF)
        !           656:                                log(LOG_WARNING,
        !           657:                                    "dcm%d: silo overflow\n", unit);
        !           658:                        else if (stat & RD_OE)
        !           659:                                log(LOG_WARNING,
        !           660:                                    "dcm%d: uart overflow\n", unit);
        !           661:                }
        !           662:                (*linesw[tp->t_line].l_rint)(c, tp);
        !           663:        }
        !           664:        dcmischeme[BOARD(unit)].dis_char += nch;
        !           665: #ifdef IOSTATS
        !           666:        dsp->rchars += nch;
        !           667:        if (nch <= DCMRBSIZE)
        !           668:                dsp->rsilo[nch]++;
        !           669:        else
        !           670:                dsp->rsilo[DCMRBSIZE+1]++;
        !           671: #endif
        !           672: }
        !           673: 
        !           674: dcmxint(unit, dcm, tp)
        !           675:        int unit;
        !           676:        struct dcmdevice *dcm;
        !           677:        register struct tty *tp;
        !           678: {
        !           679:        tp->t_state &= ~TS_BUSY;
        !           680:        if (tp->t_state & TS_FLUSH)
        !           681:                tp->t_state &= ~TS_FLUSH;
        !           682:        (*linesw[tp->t_line].l_start)(tp);
        !           683: }
        !           684: 
        !           685: dcmmint(unit, mcnd, dcm)
        !           686:        register int unit;
        !           687:        register struct dcmdevice *dcm;
        !           688:         int mcnd;
        !           689: {
        !           690:        register struct tty *tp;
        !           691:        int delta;
        !           692: 
        !           693: #ifdef DEBUG
        !           694:        if (dcmdebug & DDB_MODEM)
        !           695:                printf("dcmmint: port %d mcnd %x mcndlast %x\n",
        !           696:                       unit, mcnd, mcndlast[unit]);
        !           697: #endif
        !           698:        tp = &dcm_tty[unit];
        !           699:        delta = mcnd ^ mcndlast[unit];
        !           700:        mcndlast[unit] = mcnd;
        !           701:        if ((delta & MI_CTS) && (tp->t_state & TS_ISOPEN) &&
        !           702:            (tp->t_flags & CCTS_OFLOW)) {
        !           703:                if (mcnd & MI_CTS) {
        !           704:                        tp->t_state &= ~TS_TTSTOP;
        !           705:                        ttstart(tp);
        !           706:                } else
        !           707:                        tp->t_state |= TS_TTSTOP;       /* inline dcmstop */
        !           708:        }
        !           709:        if (delta & MI_CD) {
        !           710:                if (mcnd & MI_CD)
        !           711:                        (void)(*linesw[tp->t_line].l_modem)(tp, 1);
        !           712:                else if ((dcmsoftCAR[BOARD(unit)] & (1 << PORT(unit))) == 0 &&
        !           713:                    (*linesw[tp->t_line].l_modem)(tp, 0) == 0) {
        !           714:                        dcm_modem[unit]->mdmout = MO_OFF;
        !           715:                        SEM_LOCK(dcm);
        !           716:                        dcm->dcm_modemchng |= 1<<(unit & 3);
        !           717:                        dcm->dcm_cr |= CR_MODM;
        !           718:                        SEM_UNLOCK(dcm);
        !           719:                        DELAY(10); /* time to change lines */
        !           720:                }
        !           721:        }
        !           722: }
        !           723: 
        !           724: dcmioctl(dev, cmd, data, flag)
        !           725:        dev_t dev;
        !           726:        caddr_t data;
        !           727: {
        !           728:        register struct tty *tp;
        !           729:        register int unit = UNIT(dev);
        !           730:        register struct dcmdevice *dcm;
        !           731:        register int port;
        !           732:        int error, s;
        !           733:  
        !           734: #ifdef DEBUG
        !           735:        if (dcmdebug & DDB_IOCTL)
        !           736:                printf("dcmioctl: unit %d cmd %x data %x flag %x\n",
        !           737:                       unit, cmd, *data, flag);
        !           738: #endif
        !           739:        tp = &dcm_tty[unit];
        !           740:        error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
        !           741:        if (error >= 0)
        !           742:                return (error);
        !           743:        error = ttioctl(tp, cmd, data, flag);
        !           744:        if (error >= 0)
        !           745:                return (error);
        !           746: 
        !           747:        port = PORT(unit);
        !           748:        dcm = dcm_addr[BOARD(unit)];
        !           749:        switch (cmd) {
        !           750:        case TIOCSBRK:
        !           751:                /*
        !           752:                 * Wait for transmitter buffer to empty
        !           753:                 */
        !           754:                s = spltty();
        !           755:                while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr)
        !           756:                        DELAY(DCM_USPERCH(tp->t_ospeed));
        !           757:                SEM_LOCK(dcm);
        !           758:                dcm->dcm_cmdtab[port].dcm_data |= CT_BRK;
        !           759:                dcm->dcm_cr |= (1 << port);     /* start break */
        !           760:                SEM_UNLOCK(dcm);
        !           761:                splx(s);
        !           762:                break;
        !           763: 
        !           764:        case TIOCCBRK:
        !           765:                SEM_LOCK(dcm);
        !           766:                dcm->dcm_cmdtab[port].dcm_data |= CT_BRK;
        !           767:                dcm->dcm_cr |= (1 << port);     /* end break */
        !           768:                SEM_UNLOCK(dcm);
        !           769:                break;
        !           770: 
        !           771:        case TIOCSDTR:
        !           772:                (void) dcmmctl(dev, MO_ON, DMBIS);
        !           773:                break;
        !           774: 
        !           775:        case TIOCCDTR:
        !           776:                (void) dcmmctl(dev, MO_ON, DMBIC);
        !           777:                break;
        !           778: 
        !           779:        case TIOCMSET:
        !           780:                (void) dcmmctl(dev, *(int *)data, DMSET);
        !           781:                break;
        !           782: 
        !           783:        case TIOCMBIS:
        !           784:                (void) dcmmctl(dev, *(int *)data, DMBIS);
        !           785:                break;
        !           786: 
        !           787:        case TIOCMBIC:
        !           788:                (void) dcmmctl(dev, *(int *)data, DMBIC);
        !           789:                break;
        !           790: 
        !           791:        case TIOCMGET:
        !           792:                *(int *)data = dcmmctl(dev, 0, DMGET);
        !           793:                break;
        !           794: 
        !           795:        default:
        !           796:                return (ENOTTY);
        !           797:        }
        !           798:        return (0);
        !           799: }
        !           800: 
        !           801: dcmparam(tp, t)
        !           802:        register struct tty *tp;
        !           803:        register struct termios *t;
        !           804: {
        !           805:        register struct dcmdevice *dcm;
        !           806:        register int port, mode, cflag = t->c_cflag;
        !           807:        int ospeed = ttspeedtab(t->c_ospeed, dcmspeedtab);
        !           808: 
        !           809:        /* check requested parameters */
        !           810:         if (ospeed < 0 || (t->c_ispeed && t->c_ispeed != t->c_ospeed))
        !           811:                 return (EINVAL);
        !           812:         /* and copy to tty */
        !           813:         tp->t_ispeed = t->c_ispeed;
        !           814:         tp->t_ospeed = t->c_ospeed;
        !           815:         tp->t_cflag = cflag;
        !           816:        if (ospeed == 0) {
        !           817:                (void) dcmmctl(UNIT(tp->t_dev), MO_OFF, DMSET);
        !           818:                return (0);
        !           819:        }
        !           820: 
        !           821:        mode = 0;
        !           822:        switch (cflag&CSIZE) {
        !           823:        case CS5:
        !           824:                mode = LC_5BITS; break;
        !           825:        case CS6:
        !           826:                mode = LC_6BITS; break;
        !           827:        case CS7:
        !           828:                mode = LC_7BITS; break;
        !           829:        case CS8:
        !           830:                mode = LC_8BITS; break;
        !           831:        }
        !           832:        if (cflag&PARENB) {
        !           833:                if (cflag&PARODD)
        !           834:                        mode |= LC_PODD;
        !           835:                else
        !           836:                        mode |= LC_PEVEN;
        !           837:        }
        !           838:        if (cflag&CSTOPB)
        !           839:                mode |= LC_2STOP;
        !           840:        else
        !           841:                mode |= LC_1STOP;
        !           842: #ifdef DEBUG
        !           843:        if (dcmdebug & DDB_PARAM)
        !           844:                printf("dcmparam(%d): cflag %x mode %x speed %d uperch %d\n",
        !           845:                       UNIT(tp->t_dev), cflag, mode, tp->t_ospeed,
        !           846:                       DCM_USPERCH(tp->t_ospeed));
        !           847: #endif
        !           848: 
        !           849:        port = PORT(tp->t_dev);
        !           850:        dcm = dcm_addr[BOARD(tp->t_dev)];
        !           851:        /*
        !           852:         * Wait for transmitter buffer to empty.
        !           853:         */
        !           854:        while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr)
        !           855:                DELAY(DCM_USPERCH(tp->t_ospeed));
        !           856:        /*
        !           857:         * Make changes known to hardware.
        !           858:         */
        !           859:        dcm->dcm_data[port].dcm_baud = ospeed;
        !           860:        dcm->dcm_data[port].dcm_conf = mode;
        !           861:        SEM_LOCK(dcm);
        !           862:        dcm->dcm_cmdtab[port].dcm_data |= CT_CON;
        !           863:        dcm->dcm_cr |= (1 << port);
        !           864:        SEM_UNLOCK(dcm);
        !           865:        /*
        !           866:         * Delay for config change to take place. Weighted by baud.
        !           867:         * XXX why do we do this?
        !           868:         */
        !           869:        DELAY(16 * DCM_USPERCH(tp->t_ospeed));
        !           870:        return (0);
        !           871: }
        !           872:  
        !           873: dcmstart(tp)
        !           874:        register struct tty *tp;
        !           875: {
        !           876:        register struct dcmdevice *dcm;
        !           877:        register struct dcmpreg *pp;
        !           878:        register struct dcmtfifo *fifo;
        !           879:        register char *bp;
        !           880:        register unsigned tail, next;
        !           881:        register int port, nch;
        !           882:        unsigned head;
        !           883:        char buf[16];
        !           884:        int s;
        !           885: #ifdef IOSTATS
        !           886:        struct dcmstats *dsp = &dcmstats[BOARD(tp->t_dev)];
        !           887:        int tch = 0;
        !           888: #endif
        !           889: 
        !           890:        s = spltty();
        !           891: #ifdef IOSTATS
        !           892:        dsp->xints++;
        !           893: #endif
        !           894: #ifdef DEBUG
        !           895:        if (dcmdebug & DDB_OUTPUT)
        !           896:                printf("dcmstart(%d): state %x flags %x outcc %d\n",
        !           897:                       UNIT(tp->t_dev), tp->t_state, tp->t_flags,
        !           898:                       tp->t_outq.c_cc);
        !           899: #endif
        !           900:        if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
        !           901:                goto out;
        !           902:        if (tp->t_outq.c_cc <= tp->t_lowat) {
        !           903:                if (tp->t_state&TS_ASLEEP) {
        !           904:                        tp->t_state &= ~TS_ASLEEP;
        !           905:                        wakeup((caddr_t)&tp->t_outq);
        !           906:                }
        !           907:                if (tp->t_wsel) {
        !           908:                        selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
        !           909:                        tp->t_wsel = 0;
        !           910:                        tp->t_state &= ~TS_WCOLL;
        !           911:                }
        !           912:        }
        !           913:        if (tp->t_outq.c_cc == 0) {
        !           914: #ifdef IOSTATS
        !           915:                dsp->xempty++;
        !           916: #endif
        !           917:                goto out;
        !           918:        }
        !           919: 
        !           920:        dcm = dcm_addr[BOARD(tp->t_dev)];
        !           921:        port = PORT(tp->t_dev);
        !           922:        pp = dcm_preg(dcm, port);
        !           923:        tail = pp->t_tail & TX_MASK;
        !           924:        next = (tail + 1) & TX_MASK;
        !           925:        head = pp->t_head & TX_MASK;
        !           926:        if (head == next)
        !           927:                goto out;
        !           928:        fifo = &dcm->dcm_tfifos[3-port][tail];
        !           929: again:
        !           930:        nch = q_to_b(&tp->t_outq, buf, (head - next) & TX_MASK);
        !           931: #ifdef IOSTATS
        !           932:        tch += nch;
        !           933: #endif
        !           934: #ifdef DEBUG
        !           935:        if (dcmdebug & DDB_OUTPUT)
        !           936:                printf("\thead %x tail %x nch %d\n", head, tail, nch);
        !           937: #endif
        !           938:        /*
        !           939:         * Loop transmitting all the characters we can.
        !           940:         */
        !           941:        for (bp = buf; --nch >= 0; bp++) {
        !           942:                fifo->data_char = *bp;
        !           943:                pp->t_tail = next;
        !           944:                /*
        !           945:                 * If this is the first character,
        !           946:                 * get the hardware moving right now.
        !           947:                 */
        !           948:                if (bp == buf) {
        !           949:                        tp->t_state |= TS_BUSY;
        !           950:                        SEM_LOCK(dcm);
        !           951:                        dcm->dcm_cmdtab[port].dcm_data |= CT_TX;
        !           952:                        dcm->dcm_cr |= (1 << port);
        !           953:                        SEM_UNLOCK(dcm);
        !           954:                }
        !           955:                tail = next;
        !           956:                fifo = tail ? fifo+1 : &dcm->dcm_tfifos[3-port][0];
        !           957:                next = (next + 1) & TX_MASK;
        !           958:        }
        !           959:        /*
        !           960:         * Head changed while we were loading the buffer,
        !           961:         * go back and load some more if we can.
        !           962:         */
        !           963:        if (tp->t_outq.c_cc && head != (pp->t_head & TX_MASK)) {
        !           964: #ifdef IOSTATS
        !           965:                dsp->xrestarts++;
        !           966: #endif
        !           967:                head = pp->t_head & TX_MASK;
        !           968:                goto again;
        !           969:        }
        !           970: 
        !           971:        /*
        !           972:         * Kick it one last time in case it finished while we were
        !           973:         * loading the last bunch.
        !           974:         */
        !           975:        if (bp > &buf[1]) {
        !           976:                tp->t_state |= TS_BUSY;
        !           977:                SEM_LOCK(dcm);
        !           978:                dcm->dcm_cmdtab[port].dcm_data |= CT_TX;
        !           979:                dcm->dcm_cr |= (1 << port);
        !           980:                SEM_UNLOCK(dcm);
        !           981:        }
        !           982: #ifdef DEBUG
        !           983:        if (dcmdebug & DDB_INTR)
        !           984:                printf("dcmstart(%d): head %x tail %x outqcc %d\n",
        !           985:                       UNIT(tp->t_dev), head, tail, tp->t_outq.c_cc);
        !           986: #endif
        !           987: out:
        !           988: #ifdef IOSTATS
        !           989:        dsp->xchars += tch;
        !           990:        if (tch <= DCMXBSIZE)
        !           991:                dsp->xsilo[tch]++;
        !           992:        else
        !           993:                dsp->xsilo[DCMXBSIZE+1]++;
        !           994: #endif
        !           995:        splx(s);
        !           996: }
        !           997:  
        !           998: /*
        !           999:  * Stop output on a line.
        !          1000:  */
        !          1001: dcmstop(tp, flag)
        !          1002:        register struct tty *tp;
        !          1003: {
        !          1004:        int s;
        !          1005: 
        !          1006:        s = spltty();
        !          1007:        if (tp->t_state & TS_BUSY) {
        !          1008:                /* XXX is there some way to safely stop transmission? */
        !          1009:                if ((tp->t_state&TS_TTSTOP) == 0)
        !          1010:                        tp->t_state |= TS_FLUSH;
        !          1011:        }
        !          1012:        splx(s);
        !          1013: }
        !          1014:  
        !          1015: /*
        !          1016:  * Modem control
        !          1017:  */
        !          1018: dcmmctl(dev, bits, how)
        !          1019:        dev_t dev;
        !          1020:        int bits, how;
        !          1021: {
        !          1022:        register struct dcmdevice *dcm;
        !          1023:        int s, unit, brd, hit = 0;
        !          1024: 
        !          1025:        unit = UNIT(dev);
        !          1026: #ifdef DEBUG
        !          1027:        if (dcmdebug & DDB_MODEM)
        !          1028:                printf("dcmmctl(%d) unit %d  bits 0x%x how %x\n",
        !          1029:                       BOARD(unit), unit, bits, how);
        !          1030: #endif
        !          1031: 
        !          1032:        brd = BOARD(unit);
        !          1033:        dcm = dcm_addr[brd];
        !          1034:        s = spltty();
        !          1035:        switch (how) {
        !          1036: 
        !          1037:        case DMSET:
        !          1038:                dcm_modem[unit]->mdmout = bits;
        !          1039:                hit++;
        !          1040:                break;
        !          1041: 
        !          1042:        case DMBIS:
        !          1043:                dcm_modem[unit]->mdmout |= bits;
        !          1044:                hit++;
        !          1045:                break;
        !          1046: 
        !          1047:        case DMBIC:
        !          1048:                dcm_modem[unit]->mdmout &= ~bits;
        !          1049:                hit++;
        !          1050:                break;
        !          1051: 
        !          1052:        case DMGET:
        !          1053:                bits = dcm_modem[unit]->mdmin;
        !          1054:                if (dcmsoftCAR[brd] & FLAG_STDDCE)
        !          1055:                        bits = hp2dce_in(bits);
        !          1056:                break;
        !          1057:        }
        !          1058:        if (hit) {
        !          1059:                SEM_LOCK(dcm);
        !          1060:                dcm->dcm_modemchng |= 1<<(unit & 3);
        !          1061:                dcm->dcm_cr |= CR_MODM;
        !          1062:                SEM_UNLOCK(dcm);
        !          1063:                DELAY(10); /* delay until done */
        !          1064:                (void) splx(s);
        !          1065:        }
        !          1066:        return (bits);
        !          1067: }
        !          1068: 
        !          1069: /*
        !          1070:  * Set board to either interrupt per-character or at a fixed interval.
        !          1071:  */
        !          1072: dcmsetischeme(brd, flags)
        !          1073:        int brd, flags;
        !          1074: {
        !          1075:        register struct dcmdevice *dcm = dcm_addr[brd];
        !          1076:        register struct dcmischeme *dis = &dcmischeme[brd];
        !          1077:        register int i;
        !          1078:        u_char mask;
        !          1079:        int perchar = flags & DIS_PERCHAR;
        !          1080: 
        !          1081: #ifdef DEBUG
        !          1082:        if (dcmdebug & DDB_INTSCHM)
        !          1083:                printf("dcmsetischeme(%d, %d): cur %d, ints %d, chars %d\n",
        !          1084:                       brd, perchar, dis->dis_perchar,
        !          1085:                       dis->dis_intr, dis->dis_char);
        !          1086:        if ((flags & DIS_RESET) == 0 && perchar == dis->dis_perchar) {
        !          1087:                printf("dcmsetischeme(%d):  redundent request %d\n",
        !          1088:                       brd, perchar);
        !          1089:                return;
        !          1090:        }
        !          1091: #endif
        !          1092:        /*
        !          1093:         * If perchar is non-zero, we enable interrupts on all characters
        !          1094:         * otherwise we disable perchar interrupts and use periodic
        !          1095:         * polling interrupts.
        !          1096:         */
        !          1097:        dis->dis_perchar = perchar;
        !          1098:        mask = perchar ? 0xf : 0x0;
        !          1099:        for (i = 0; i < 256; i++)
        !          1100:                dcm->dcm_bmap[i].data_data = mask;
        !          1101:        /*
        !          1102:         * Don't slow down tandem mode, interrupt on flow control
        !          1103:         * chars for any port on the board.
        !          1104:         */
        !          1105:        if (!perchar) {
        !          1106:                register struct tty *tp = &dcm_tty[MKUNIT(brd, 0)];
        !          1107:                int c;
        !          1108: 
        !          1109:                for (i = 0; i < 4; i++, tp++) {
        !          1110:                        if ((c = tp->t_cc[VSTART]) != _POSIX_VDISABLE)
        !          1111:                                dcm->dcm_bmap[c].data_data |= (1 << i);
        !          1112:                        if ((c = tp->t_cc[VSTOP]) != _POSIX_VDISABLE)
        !          1113:                                dcm->dcm_bmap[c].data_data |= (1 << i);
        !          1114:                }
        !          1115:        }
        !          1116:        /*
        !          1117:         * Board starts with timer disabled so if first call is to
        !          1118:         * set perchar mode then we don't want to toggle the timer.
        !          1119:         */
        !          1120:        if (flags == (DIS_RESET|DIS_PERCHAR))
        !          1121:                return;
        !          1122:        /*
        !          1123:         * Toggle card 16.7ms interrupts (we first make sure that card
        !          1124:         * has cleared the bit so it will see the toggle).
        !          1125:         */
        !          1126:        while (dcm->dcm_cr & CR_TIMER)
        !          1127:                ;
        !          1128:        SEM_LOCK(dcm);
        !          1129:        dcm->dcm_cr |= CR_TIMER;
        !          1130:        SEM_UNLOCK(dcm);
        !          1131: }
        !          1132: 
        !          1133: /*
        !          1134:  * Following are all routines needed for DCM to act as console
        !          1135:  */
        !          1136: #include "../hp300/cons.h"
        !          1137: 
        !          1138: dcmcnprobe(cp)
        !          1139:        struct consdev *cp;
        !          1140: {
        !          1141:        register struct hp_hw *hw;
        !          1142:        int unit;
        !          1143: 
        !          1144:        /* locate the major number */
        !          1145:        for (dcmmajor = 0; dcmmajor < nchrdev; dcmmajor++)
        !          1146:                if (cdevsw[dcmmajor].d_open == dcmopen)
        !          1147:                        break;
        !          1148: 
        !          1149:        /*
        !          1150:         * Implicitly assigns the lowest select code DCM card found to be
        !          1151:         * logical unit 0 (actually CONUNIT).  If your config file does
        !          1152:         * anything different, you're screwed.
        !          1153:         */
        !          1154:        for (hw = sc_table; hw->hw_type; hw++)
        !          1155:                if (HW_ISDEV(hw, D_COMMDCM) && !badaddr((short *)hw->hw_kva))
        !          1156:                        break;
        !          1157:        if (!HW_ISDEV(hw, D_COMMDCM)) {
        !          1158:                cp->cn_pri = CN_DEAD;
        !          1159:                return;
        !          1160:        }
        !          1161:        unit = CONUNIT;
        !          1162:        dcm_addr[BOARD(CONUNIT)] = (struct dcmdevice *)hw->hw_kva;
        !          1163: 
        !          1164:        /* initialize required fields */
        !          1165:        cp->cn_dev = makedev(dcmmajor, unit);
        !          1166:        cp->cn_tp = &dcm_tty[unit];
        !          1167:        switch (dcm_addr[BOARD(unit)]->dcm_rsid) {
        !          1168:        case DCMID:
        !          1169:                cp->cn_pri = CN_NORMAL;
        !          1170:                break;
        !          1171:        case DCMID|DCMCON:
        !          1172:                cp->cn_pri = CN_REMOTE;
        !          1173:                break;
        !          1174:        default:
        !          1175:                cp->cn_pri = CN_DEAD;
        !          1176:                return;
        !          1177:        }
        !          1178:        /*
        !          1179:         * If dcmconsole is initialized, raise our priority.
        !          1180:         */
        !          1181:        if (dcmconsole == UNIT(unit))
        !          1182:                cp->cn_pri = CN_REMOTE;
        !          1183: #ifdef KGDB_CHEAT
        !          1184:        /*
        !          1185:         * This doesn't currently work, at least not with ite consoles;
        !          1186:         * the console hasn't been initialized yet.
        !          1187:         */
        !          1188:        if (major(kgdb_dev) == dcmmajor && BOARD(kgdb_dev) == BOARD(unit)) {
        !          1189:                (void) dcminit(kgdb_dev, kgdb_rate);
        !          1190:                if (kgdb_debug_init) {
        !          1191:                        /*
        !          1192:                         * We assume that console is ready for us...
        !          1193:                         * this assumes that a dca or ite console
        !          1194:                         * has been selected already and will init
        !          1195:                         * on the first putc.
        !          1196:                         */
        !          1197:                        printf("dcm%d: ", UNIT(kgdb_dev));
        !          1198:                        kgdb_connect(1);
        !          1199:                }
        !          1200:        }
        !          1201: #endif
        !          1202: }
        !          1203: 
        !          1204: dcmcninit(cp)
        !          1205:        struct consdev *cp;
        !          1206: {
        !          1207:        dcminit(cp->cn_dev, dcmdefaultrate);
        !          1208:        dcmconsinit = 1;
        !          1209:        dcmconsole = UNIT(cp->cn_dev);
        !          1210: }
        !          1211: 
        !          1212: dcminit(dev, rate)
        !          1213:        dev_t dev;
        !          1214:        int rate;
        !          1215: {
        !          1216:        register struct dcmdevice *dcm = dcm_addr[BOARD(dev)];
        !          1217:        int s, mode, port;
        !          1218: 
        !          1219:        port = PORT(dev);
        !          1220:        mode = LC_8BITS | LC_1STOP;
        !          1221:        s = splhigh();
        !          1222:        /*
        !          1223:         * Wait for transmitter buffer to empty.
        !          1224:         */
        !          1225:        while (dcm->dcm_thead[port].ptr != dcm->dcm_ttail[port].ptr)
        !          1226:                DELAY(DCM_USPERCH(rate));
        !          1227:        /*
        !          1228:         * Make changes known to hardware.
        !          1229:         */
        !          1230:        dcm->dcm_data[port].dcm_baud = ttspeedtab(rate, dcmspeedtab);
        !          1231:        dcm->dcm_data[port].dcm_conf = mode;
        !          1232:        SEM_LOCK(dcm);
        !          1233:        dcm->dcm_cmdtab[port].dcm_data |= CT_CON;
        !          1234:        dcm->dcm_cr |= (1 << port);
        !          1235:        SEM_UNLOCK(dcm);
        !          1236:        /*
        !          1237:         * Delay for config change to take place. Weighted by baud.
        !          1238:         * XXX why do we do this?
        !          1239:         */
        !          1240:        DELAY(16 * DCM_USPERCH(rate));
        !          1241:        splx(s);
        !          1242: }
        !          1243: 
        !          1244: dcmcngetc(dev)
        !          1245:        dev_t dev;
        !          1246: {
        !          1247:        register struct dcmdevice *dcm = dcm_addr[BOARD(dev)];
        !          1248:        register struct dcmrfifo *fifo;
        !          1249:        register struct dcmpreg *pp;
        !          1250:        register unsigned head;
        !          1251:        int s, c, stat, port;
        !          1252: 
        !          1253:        port = PORT(dev);
        !          1254:        pp = dcm_preg(dcm, port);
        !          1255:        s = splhigh();
        !          1256:        head = pp->r_head & RX_MASK;
        !          1257:        fifo = &dcm->dcm_rfifos[3-port][head>>1];
        !          1258:        while (head == (pp->r_tail & RX_MASK))
        !          1259:                ;
        !          1260:        /*
        !          1261:         * If board interrupts are enabled, just let our received char
        !          1262:         * interrupt through in case some other port on the board was
        !          1263:         * busy.  Otherwise we must clear the interrupt.
        !          1264:         */
        !          1265:        SEM_LOCK(dcm);
        !          1266:        if ((dcm->dcm_ic & IC_IE) == 0)
        !          1267:                stat = dcm->dcm_iir;
        !          1268:        SEM_UNLOCK(dcm);
        !          1269:        c = fifo->data_char;
        !          1270:        stat = fifo->data_stat;
        !          1271:        pp->r_head = (head + 2) & RX_MASK;
        !          1272:        splx(s);
        !          1273:        return (c);
        !          1274: }
        !          1275: 
        !          1276: /*
        !          1277:  * Console kernel output character routine.
        !          1278:  */
        !          1279: dcmcnputc(dev, c)
        !          1280:        dev_t dev;
        !          1281:        int c;
        !          1282: {
        !          1283:        register struct dcmdevice *dcm = dcm_addr[BOARD(dev)];
        !          1284:        register struct dcmpreg *pp;
        !          1285:        unsigned tail;
        !          1286:        int s, port, stat;
        !          1287: 
        !          1288:        port = PORT(dev);
        !          1289:        pp = dcm_preg(dcm, port);
        !          1290:        s = splhigh();
        !          1291: #ifdef KGDB
        !          1292:        if (dev != kgdb_dev)
        !          1293: #endif
        !          1294:        if (dcmconsinit == 0) {
        !          1295:                (void) dcminit(dev, dcmdefaultrate);
        !          1296:                dcmconsinit = 1;
        !          1297:        }
        !          1298:        tail = pp->t_tail & TX_MASK;
        !          1299:        while (tail != (pp->t_head & TX_MASK))
        !          1300:                ;
        !          1301:        dcm->dcm_tfifos[3-port][tail].data_char = c;
        !          1302:        pp->t_tail = tail = (tail + 1) & TX_MASK;
        !          1303:        SEM_LOCK(dcm);
        !          1304:        dcm->dcm_cmdtab[port].dcm_data |= CT_TX;
        !          1305:        dcm->dcm_cr |= (1 << port);
        !          1306:        SEM_UNLOCK(dcm);
        !          1307:        while (tail != (pp->t_head & TX_MASK))
        !          1308:                ;
        !          1309:        /*
        !          1310:         * If board interrupts are enabled, just let our completion
        !          1311:         * interrupt through in case some other port on the board
        !          1312:         * was busy.  Otherwise we must clear the interrupt.
        !          1313:         */
        !          1314:        if ((dcm->dcm_ic & IC_IE) == 0) {
        !          1315:                SEM_LOCK(dcm);
        !          1316:                stat = dcm->dcm_iir;
        !          1317:                SEM_UNLOCK(dcm);
        !          1318:        }
        !          1319:        splx(s);
        !          1320: }
        !          1321: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.