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

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

unix.superglobalmegacorp.com

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