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

unix.superglobalmegacorp.com

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