Annotation of 43BSD/sys/vaxuba/dh.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1982, 1986 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  *
                      6:  *     @(#)dh.c        7.1 (Berkeley) 6/5/86
                      7:  */
                      8: 
                      9: #include "dh.h"
                     10: #if NDH > 0
                     11: /*
                     12:  * DH-11/DM-11 driver
                     13:  */
                     14: #include "../machine/pte.h"
                     15: 
                     16: #include "bk.h"
                     17: #include "uba.h"
                     18: #include "param.h"
                     19: #include "conf.h"
                     20: #include "dir.h"
                     21: #include "user.h"
                     22: #include "proc.h"
                     23: #include "ioctl.h"
                     24: #include "tty.h"
                     25: #include "map.h"
                     26: #include "buf.h"
                     27: #include "vm.h"
                     28: #include "kernel.h"
                     29: #include "syslog.h"
                     30: 
                     31: #include "ubareg.h"
                     32: #include "ubavar.h"
                     33: #include "dhreg.h"
                     34: #include "dmreg.h"
                     35: 
                     36: #include "bkmac.h"
                     37: #include "clist.h"
                     38: #include "file.h"
                     39: #include "uio.h"
                     40: 
                     41: /*
                     42:  * Definition of the driver for the auto-configuration program.
                     43:  * There is one definition for the dh and one for the dm.
                     44:  */
                     45: int    dhprobe(), dhattach(), dhrint(), dhxint(), dhtimer();
                     46: struct uba_device *dhinfo[NDH];
                     47: u_short        dhstd[] = { 0 };
                     48: struct uba_driver dhdriver =
                     49:        { dhprobe, 0, dhattach, 0, dhstd, "dh", dhinfo };
                     50: 
                     51: int    dmprobe(), dmattach(), dmintr();
                     52: struct uba_device *dminfo[NDH];
                     53: u_short        dmstd[] = { 0 };
                     54: struct uba_driver dmdriver =
                     55:        { dmprobe, 0, dmattach, 0, dmstd, "dm", dminfo };
                     56: 
                     57: #ifndef        PORTSELECTOR
                     58: #define        ISPEED  B9600
                     59: #define        IFLAGS  (EVENP|ODDP|ECHO)
                     60: #else
                     61: #define        ISPEED  B4800
                     62: #define        IFLAGS  (EVENP|ODDP)
                     63: #endif
                     64: 
                     65: #define        FASTTIMER       (hz/30)         /* scan rate with silos on */
                     66: 
                     67: /*
                     68:  * Local variables for the driver
                     69:  */
                     70: short  dhsar[NDH];                     /* software copy of last bar */
                     71: short  dhsoftCAR[NDH];
                     72: 
                     73: struct tty dh11[NDH*16];
                     74: int    ndh11   = NDH*16;
                     75: int    dhact;                          /* mask of active dh's */
                     76: int    dhsilos;                        /* mask of dh's with silo in use */
                     77: int    dhchars[NDH];                   /* recent input count */
                     78: int    dhrate[NDH];                    /* smoothed input count */
                     79: int    dhhighrate = 100;               /* silo on if dhchars > dhhighrate */
                     80: int    dhlowrate = 75;                 /* silo off if dhrate < dhlowrate */
                     81: static short timerstarted;
                     82: int    dhstart(), ttrstrt();
                     83: 
                     84: /*
                     85:  * The clist space is mapped by the driver onto each UNIBUS.
                     86:  * The UBACVT macro converts a clist space address for unibus uban
                     87:  * into an i/o space address for the DMA routine.
                     88:  */
                     89: int    dh_ubinfo[NUBA];                /* info about allocated unibus map */
                     90: int    cbase[NUBA];                    /* base address in unibus map */
                     91: #define        UBACVT(x, uban)         (cbase[uban] + ((x)-(char *)cfree))
                     92: 
                     93: /*
                     94:  * Routine for configuration to force a dh to interrupt.
                     95:  * Set to transmit at 9600 baud, and cause a transmitter interrupt.
                     96:  */
                     97: /*ARGSUSED*/
                     98: dhprobe(reg)
                     99:        caddr_t reg;
                    100: {
                    101:        register int br, cvec;          /* these are ``value-result'' */
                    102:        register struct dhdevice *dhaddr = (struct dhdevice *)reg;
                    103: 
                    104: #ifdef lint
                    105:        br = 0; cvec = br; br = cvec;
                    106:        if (ndh11 == 0) ndh11 = 1;
                    107:        dhrint(0); dhxint(0);
                    108: #endif
                    109: #ifndef notdef
                    110:        dhaddr->un.dhcsr = DH_RIE|DH_MM|DH_RI;
                    111:        DELAY(1000);
                    112:        dhaddr->un.dhcsr &= ~DH_RI;
                    113:        dhaddr->un.dhcsr = 0;
                    114: #else
                    115:        dhaddr->un.dhcsr = DH_TIE;
                    116:        DELAY(5);
                    117:        dhaddr->dhlpr = (B9600 << 10) | (B9600 << 6) | BITS7|PENABLE;
                    118:        dhaddr->dhbcr = -1;
                    119:        dhaddr->dhcar = 0;
                    120:        dhaddr->dhbar = 1;
                    121:        DELAY(100000);          /* wait 1/10'th of a sec for interrupt */
                    122:        dhaddr->un.dhcsr = 0;
                    123:        if (cvec && cvec != 0x200)
                    124:                cvec -= 4;              /* transmit -> receive */
                    125: #endif
                    126:        return (sizeof (struct dhdevice));
                    127: }
                    128: 
                    129: /*
                    130:  * Routine called to attach a dh.
                    131:  */
                    132: dhattach(ui)
                    133:        struct uba_device *ui;
                    134: {
                    135: 
                    136:        dhsoftCAR[ui->ui_unit] = ui->ui_flags;
                    137:        cbase[ui->ui_ubanum] = -1;
                    138: }
                    139: 
                    140: /*
                    141:  * Configuration routine to cause a dm to interrupt.
                    142:  */
                    143: dmprobe(reg)
                    144:        caddr_t reg;
                    145: {
                    146:        register int br, vec;                   /* value-result */
                    147:        register struct dmdevice *dmaddr = (struct dmdevice *)reg;
                    148: 
                    149: #ifdef lint
                    150:        br = 0; vec = br; br = vec;
                    151:        dmintr(0);
                    152: #endif
                    153:        dmaddr->dmcsr = DM_DONE|DM_IE;
                    154:        DELAY(20);
                    155:        dmaddr->dmcsr = 0;
                    156:        return (1);
                    157: }
                    158: 
                    159: /*ARGSUSED*/
                    160: dmattach(ui)
                    161:        struct uba_device *ui;
                    162: {
                    163: 
                    164:        /* no local state to set up */
                    165: }
                    166: 
                    167: /*
                    168:  * Open a DH11 line, mapping the clist onto the uba if this
                    169:  * is the first dh on this uba.  Turn on this dh if this is
                    170:  * the first use of it.  Also do a dmopen to wait for carrier.
                    171:  */
                    172: /*ARGSUSED*/
                    173: dhopen(dev, flag)
                    174:        dev_t dev;
                    175: {
                    176:        register struct tty *tp;
                    177:        register int unit, dh;
                    178:        register struct dhdevice *addr;
                    179:        register struct uba_device *ui;
                    180:        int s;
                    181: 
                    182:        unit = minor(dev);
                    183:        dh = unit >> 4;
                    184:        if (unit >= NDH*16 || (ui = dhinfo[dh])== 0 || ui->ui_alive == 0)
                    185:                return (ENXIO);
                    186:        tp = &dh11[unit];
                    187:        if (tp->t_state&TS_XCLUDE && u.u_uid!=0)
                    188:                return (EBUSY);
                    189:        addr = (struct dhdevice *)ui->ui_addr;
                    190:        tp->t_addr = (caddr_t)addr;
                    191:        tp->t_oproc = dhstart;
                    192:        tp->t_state |= TS_WOPEN;
                    193:        /*
                    194:         * While setting up state for this uba and this dh,
                    195:         * block uba resets which can clear the state.
                    196:         */
                    197:        s = spl5();
                    198:        if (cbase[ui->ui_ubanum] == -1) {
                    199:                dh_ubinfo[ui->ui_ubanum] =
                    200:                    uballoc(ui->ui_ubanum, (caddr_t)cfree,
                    201:                        nclist*sizeof(struct cblock), 0);
                    202:                cbase[ui->ui_ubanum] = UBAI_ADDR(dh_ubinfo[ui->ui_ubanum]);
                    203:        }
                    204:        if (timerstarted == 0) {
                    205:                timerstarted++;
                    206:                timeout(dhtimer, (caddr_t) 0, hz);
                    207:        }
                    208:        if ((dhact&(1<<dh)) == 0) {
                    209:                addr->un.dhcsr |= DH_IE;
                    210:                dhact |= (1<<dh);
                    211:                addr->dhsilo = 0;
                    212:        }
                    213:        splx(s);
                    214:        /*
                    215:         * If this is first open, initialize tty state to default.
                    216:         */
                    217:        if ((tp->t_state&TS_ISOPEN) == 0) {
                    218:                ttychars(tp);
                    219: #ifndef PORTSELECTOR
                    220:                if (tp->t_ispeed == 0) {
                    221: #else
                    222:                        tp->t_state |= TS_HUPCLS;
                    223: #endif PORTSELECTOR
                    224:                        tp->t_ispeed = ISPEED;
                    225:                        tp->t_ospeed = ISPEED;
                    226:                        tp->t_flags = IFLAGS;
                    227: #ifndef PORTSELECTOR
                    228:                }
                    229: #endif PORTSELECTOR
                    230:                dhparam(unit);
                    231:        }
                    232:        /*
                    233:         * Wait for carrier, then process line discipline specific open.
                    234:         */
                    235:        dmopen(dev);
                    236:        return ((*linesw[tp->t_line].l_open)(dev, tp));
                    237: }
                    238: 
                    239: /*
                    240:  * Close a DH11 line, turning off the DM11.
                    241:  */
                    242: /*ARGSUSED*/
                    243: dhclose(dev, flag)
                    244:        dev_t dev;
                    245:        int flag;
                    246: {
                    247:        register struct tty *tp;
                    248:        register unit;
                    249: 
                    250:        unit = minor(dev);
                    251:        tp = &dh11[unit];
                    252:        (*linesw[tp->t_line].l_close)(tp);
                    253:        ((struct dhdevice *)(tp->t_addr))->dhbreak &= ~(1<<(unit&017));
                    254:        if (tp->t_state&TS_HUPCLS || (tp->t_state&TS_ISOPEN)==0)
                    255:                dmctl(unit, DML_OFF, DMSET);
                    256:        ttyclose(tp);
                    257: }
                    258: 
                    259: dhread(dev, uio)
                    260:        dev_t dev;
                    261:        struct uio *uio;
                    262: {
                    263:        register struct tty *tp = &dh11[minor(dev)];
                    264: 
                    265:        return ((*linesw[tp->t_line].l_read)(tp, uio));
                    266: }
                    267: 
                    268: dhwrite(dev, uio)
                    269:        dev_t dev;
                    270:        struct uio *uio;
                    271: {
                    272:        register struct tty *tp = &dh11[minor(dev)];
                    273: 
                    274:        return ((*linesw[tp->t_line].l_write)(tp, uio));
                    275: }
                    276: 
                    277: /*
                    278:  * DH11 receiver interrupt.
                    279:  */
                    280: dhrint(dh)
                    281:        int dh;
                    282: {
                    283:        register struct tty *tp;
                    284:        register c;
                    285:        register struct dhdevice *addr;
                    286:        register struct tty *tp0;
                    287:        register struct uba_device *ui;
                    288:        int overrun = 0;
                    289: 
                    290:        ui = dhinfo[dh];
                    291:        if (ui == 0 || ui->ui_alive == 0)
                    292:                return;
                    293:        addr = (struct dhdevice *)ui->ui_addr;
                    294:        tp0 = &dh11[dh<<4];
                    295:        /*
                    296:         * Loop fetching characters from the silo for this
                    297:         * dh until there are no more in the silo.
                    298:         */
                    299:        while ((c = addr->dhrcr) < 0) {
                    300:                tp = tp0 + ((c>>8)&0xf);
                    301:                dhchars[dh]++;
                    302:                if ((tp->t_state&TS_ISOPEN)==0) {
                    303:                        wakeup((caddr_t)&tp->t_rawq);
                    304: #ifdef PORTSELECTOR
                    305:                        if ((tp->t_state&TS_WOPEN) == 0)
                    306: #endif
                    307:                                continue;
                    308:                }
                    309:                if (c & DH_PE)
                    310:                        if ((tp->t_flags&(EVENP|ODDP))==EVENP
                    311:                         || (tp->t_flags&(EVENP|ODDP))==ODDP )
                    312:                                continue;
                    313:                if ((c & DH_DO) && overrun == 0) {
                    314:                        log(LOG_WARNING, "dh%d: silo overflow\n", dh);
                    315:                        overrun = 1;
                    316:                }
                    317:                if (c & DH_FE)
                    318:                        /*
                    319:                         * At framing error (break) generate
                    320:                         * a null (in raw mode, for getty), or a
                    321:                         * interrupt (in cooked/cbreak mode).
                    322:                         */
                    323:                        if (tp->t_flags&RAW)
                    324:                                c = 0;
                    325:                        else
                    326:                                c = tp->t_intrc;
                    327: #if NBK > 0
                    328:                if (tp->t_line == NETLDISC) {
                    329:                        c &= 0177;
                    330:                        BKINPUT(c, tp);
                    331:                } else
                    332: #endif
                    333:                        (*linesw[tp->t_line].l_rint)(c, tp);
                    334:        }
                    335: }
                    336: 
                    337: /*
                    338:  * Ioctl for DH11.
                    339:  */
                    340: /*ARGSUSED*/
                    341: dhioctl(dev, cmd, data, flag)
                    342:        caddr_t data;
                    343: {
                    344:        register struct tty *tp;
                    345:        register int unit = minor(dev);
                    346:        int error;
                    347: 
                    348:        tp = &dh11[unit];
                    349:        error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
                    350:        if (error >= 0)
                    351:                return (error);
                    352:        error = ttioctl(tp, cmd, data, flag);
                    353:        if (error >= 0) {
                    354:                if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLBIS ||
                    355:                    cmd == TIOCLBIC || cmd == TIOCLSET)
                    356:                        dhparam(unit);
                    357:                return (error);
                    358:        }
                    359:        switch (cmd) {
                    360: 
                    361:        case TIOCSBRK:
                    362:                ((struct dhdevice *)(tp->t_addr))->dhbreak |= 1<<(unit&017);
                    363:                break;
                    364: 
                    365:        case TIOCCBRK:
                    366:                ((struct dhdevice *)(tp->t_addr))->dhbreak &= ~(1<<(unit&017));
                    367:                break;
                    368: 
                    369:        case TIOCSDTR:
                    370:                dmctl(unit, DML_DTR|DML_RTS, DMBIS);
                    371:                break;
                    372: 
                    373:        case TIOCCDTR:
                    374:                dmctl(unit, DML_DTR|DML_RTS, DMBIC);
                    375:                break;
                    376: 
                    377:        default:
                    378:                return (ENOTTY);
                    379:        }
                    380:        return (0);
                    381: }
                    382: 
                    383: /*
                    384:  * Set parameters from open or stty into the DH hardware
                    385:  * registers.
                    386:  */
                    387: dhparam(unit)
                    388:        register int unit;
                    389: {
                    390:        register struct tty *tp;
                    391:        register struct dhdevice *addr;
                    392:        register int lpar;
                    393:        int s;
                    394: 
                    395:        tp = &dh11[unit];
                    396:        addr = (struct dhdevice *)tp->t_addr;
                    397:        /*
                    398:         * Block interrupts so parameters will be set
                    399:         * before the line interrupts.
                    400:         */
                    401:        s = spl5();
                    402:        addr->un.dhcsrl = (unit&0xf) | DH_IE;
                    403:        if ((tp->t_ispeed)==0) {
                    404:                tp->t_state |= TS_HUPCLS;
                    405:                dmctl(unit, DML_OFF, DMSET);
                    406:                splx(s);
                    407:                return;
                    408:        }
                    409:        lpar = ((tp->t_ospeed)<<10) | ((tp->t_ispeed)<<6);
                    410:        if ((tp->t_ispeed) == B134)
                    411:                lpar |= BITS6|PENABLE|HDUPLX;
                    412:        else if (tp->t_flags & (RAW|LITOUT|PASS8))
                    413:                lpar |= BITS8;
                    414:        else
                    415:                lpar |= BITS7|PENABLE;
                    416:        if ((tp->t_flags&EVENP) == 0)
                    417:                lpar |= OPAR;
                    418:        if ((tp->t_ospeed) == B110)
                    419:                lpar |= TWOSB;
                    420:        addr->dhlpr = lpar;
                    421:        splx(s);
                    422: }
                    423: 
                    424: /*
                    425:  * DH11 transmitter interrupt.
                    426:  * Restart each line which used to be active but has
                    427:  * terminated transmission since the last interrupt.
                    428:  */
                    429: dhxint(dh)
                    430:        int dh;
                    431: {
                    432:        register struct tty *tp;
                    433:        register struct dhdevice *addr;
                    434:        short ttybit, bar, *sbar;
                    435:        register struct uba_device *ui;
                    436:        register int unit;
                    437:        u_short cntr;
                    438: 
                    439:        ui = dhinfo[dh];
                    440:        addr = (struct dhdevice *)ui->ui_addr;
                    441:        if (addr->un.dhcsr & DH_NXM) {
                    442:                addr->un.dhcsr |= DH_CNI;
                    443:                printf("dh%d: NXM\n", dh);
                    444:        }
                    445:        sbar = &dhsar[dh];
                    446:        bar = *sbar & ~addr->dhbar;
                    447:        unit = dh * 16; ttybit = 1;
                    448:        addr->un.dhcsr &= (short)~DH_TI;
                    449:        for (; bar; unit++, ttybit <<= 1) {
                    450:                if (bar & ttybit) {
                    451:                        *sbar &= ~ttybit;
                    452:                        bar &= ~ttybit;
                    453:                        tp = &dh11[unit];
                    454:                        tp->t_state &= ~TS_BUSY;
                    455:                        if (tp->t_state&TS_FLUSH)
                    456:                                tp->t_state &= ~TS_FLUSH;
                    457:                        else {
                    458:                                addr->un.dhcsrl = (unit&017)|DH_IE;
                    459:                                /*
                    460:                                 * Do arithmetic in a short to make up
                    461:                                 * for lost 16&17 bits.
                    462:                                 */
                    463:                                cntr = addr->dhcar -
                    464:                                    UBACVT(tp->t_outq.c_cf, ui->ui_ubanum);
                    465:                                ndflush(&tp->t_outq, (int)cntr);
                    466:                        }
                    467:                        if (tp->t_line)
                    468:                                (*linesw[tp->t_line].l_start)(tp);
                    469:                        else
                    470:                                dhstart(tp);
                    471:                }
                    472:        }
                    473: }
                    474: 
                    475: /*
                    476:  * Start (restart) transmission on the given DH11 line.
                    477:  */
                    478: dhstart(tp)
                    479:        register struct tty *tp;
                    480: {
                    481:        register struct dhdevice *addr;
                    482:        register int car, dh, unit, nch;
                    483:        int s;
                    484: 
                    485:        unit = minor(tp->t_dev);
                    486:        dh = unit >> 4;
                    487:        unit &= 0xf;
                    488:        addr = (struct dhdevice *)tp->t_addr;
                    489: 
                    490:        /*
                    491:         * Must hold interrupts in following code to prevent
                    492:         * state of the tp from changing.
                    493:         */
                    494:        s = spl5();
                    495:        /*
                    496:         * If it's currently active, or delaying, no need to do anything.
                    497:         */
                    498:        if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
                    499:                goto out;
                    500:        /*
                    501:         * If there are sleepers, and output has drained below low
                    502:         * water mark, wake up the sleepers.
                    503:         */
                    504:        if (tp->t_outq.c_cc<=TTLOWAT(tp)) {
                    505:                if (tp->t_state&TS_ASLEEP) {
                    506:                        tp->t_state &= ~TS_ASLEEP;
                    507:                        wakeup((caddr_t)&tp->t_outq);
                    508:                }
                    509:                if (tp->t_wsel) {
                    510:                        selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
                    511:                        tp->t_wsel = 0;
                    512:                        tp->t_state &= ~TS_WCOLL;
                    513:                }
                    514:        }
                    515:        /*
                    516:         * Now restart transmission unless the output queue is
                    517:         * empty.
                    518:         */
                    519:        if (tp->t_outq.c_cc == 0)
                    520:                goto out;
                    521:        if (tp->t_flags & (RAW|LITOUT))
                    522:                nch = ndqb(&tp->t_outq, 0);
                    523:        else {
                    524:                nch = ndqb(&tp->t_outq, 0200);
                    525:                /*
                    526:                 * If first thing on queue is a delay process it.
                    527:                 */
                    528:                if (nch == 0) {
                    529:                        nch = getc(&tp->t_outq);
                    530:                        timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6);
                    531:                        tp->t_state |= TS_TIMEOUT;
                    532:                        goto out;
                    533:                }
                    534:        }
                    535:        /*
                    536:         * If characters to transmit, restart transmission.
                    537:         */
                    538:        if (nch) {
                    539:                car = UBACVT(tp->t_outq.c_cf, dhinfo[dh]->ui_ubanum);
                    540:                addr->un.dhcsrl = unit|((car>>12)&0x30)|DH_IE;
                    541:                /*
                    542:                 * The following nonsense with short word
                    543:                 * is to make sure the dhbar |= word below
                    544:                 * is done with an interlocking bisw2 instruction.
                    545:                 */
                    546:                { short word = 1 << unit;
                    547:                dhsar[dh] |= word;
                    548:                addr->dhcar = car;
                    549:                addr->dhbcr = -nch;
                    550:                addr->dhbar |= word;
                    551:                }
                    552:                tp->t_state |= TS_BUSY;
                    553:        }
                    554: out:
                    555:        splx(s);
                    556: }
                    557: 
                    558: /*
                    559:  * Stop output on a line, e.g. for ^S/^Q or output flush.
                    560:  */
                    561: /*ARGSUSED*/
                    562: dhstop(tp, flag)
                    563:        register struct tty *tp;
                    564: {
                    565:        register struct dhdevice *addr;
                    566:        register int unit, s;
                    567: 
                    568:        addr = (struct dhdevice *)tp->t_addr;
                    569:        /*
                    570:         * Block input/output interrupts while messing with state.
                    571:         */
                    572:        s = spl5();
                    573:        if (tp->t_state & TS_BUSY) {
                    574:                /*
                    575:                 * Device is transmitting; stop output
                    576:                 * by selecting the line and setting the byte
                    577:                 * count to -1.  We will clean up later
                    578:                 * by examining the address where the dh stopped.
                    579:                 */
                    580:                unit = minor(tp->t_dev);
                    581:                addr->un.dhcsrl = (unit&017) | DH_IE;
                    582:                if ((tp->t_state&TS_TTSTOP)==0)
                    583:                        tp->t_state |= TS_FLUSH;
                    584:                addr->dhbcr = -1;
                    585:        }
                    586:        splx(s);
                    587: }
                    588: 
                    589: /*
                    590:  * Reset state of driver if UBA reset was necessary.
                    591:  * Reset the csrl and lpr registers on open lines, and
                    592:  * restart transmitters.
                    593:  */
                    594: dhreset(uban)
                    595:        int uban;
                    596: {
                    597:        register int dh, unit;
                    598:        register struct tty *tp;
                    599:        register struct uba_device *ui;
                    600:        int i;
                    601: 
                    602:        dh = 0;
                    603:        for (dh = 0; dh < NDH; dh++) {
                    604:                ui = dhinfo[dh];
                    605:                if (ui == 0 || ui->ui_alive == 0 || ui->ui_ubanum != uban)
                    606:                        continue;
                    607:                printf(" dh%d", dh);
                    608:                if (dh_ubinfo[uban]) {
                    609:                        dh_ubinfo[uban] = uballoc(uban, (caddr_t)cfree,
                    610:                            nclist*sizeof (struct cblock), 0);
                    611:                        cbase[uban] = UBAI_ADDR(dh_ubinfo[uban]);
                    612:                }
                    613:                ((struct dhdevice *)ui->ui_addr)->un.dhcsr |= DH_IE;
                    614:                ((struct dhdevice *)ui->ui_addr)->dhsilo = 0;
                    615:                unit = dh * 16;
                    616:                for (i = 0; i < 16; i++) {
                    617:                        tp = &dh11[unit];
                    618:                        if (tp->t_state & (TS_ISOPEN|TS_WOPEN)) {
                    619:                                dhparam(unit);
                    620:                                dmctl(unit, DML_ON, DMSET);
                    621:                                tp->t_state &= ~TS_BUSY;
                    622:                                dhstart(tp);
                    623:                        }
                    624:                        unit++;
                    625:                }
                    626:        }
                    627:        dhsilos = 0;
                    628: }
                    629: 
                    630: int dhtransitions, dhslowtimers, dhfasttimers;         /*DEBUG*/
                    631: /*
                    632:  * At software clock interrupt time, check status.
                    633:  * Empty all the dh silos that are in use, and decide whether
                    634:  * to turn any silos off or on.
                    635:  */
                    636: dhtimer()
                    637: {
                    638:        register int dh, s;
                    639:        static int timercalls;
                    640: 
                    641:        if (dhsilos) {
                    642:                dhfasttimers++;         /*DEBUG*/
                    643:                timercalls++;
                    644:                s = spl5();
                    645:                for (dh = 0; dh < NDH; dh++)
                    646:                        if (dhsilos & (1 << dh))
                    647:                                dhrint(dh);
                    648:                splx(s);
                    649:        }
                    650:        if ((dhsilos == 0) || ((timercalls += FASTTIMER) >= hz)) {
                    651:                dhslowtimers++;         /*DEBUG*/
                    652:                timercalls = 0;
                    653:                for (dh = 0; dh < NDH; dh++) {
                    654:                    ave(dhrate[dh], dhchars[dh], 8);
                    655:                    if ((dhchars[dh] > dhhighrate) &&
                    656:                      ((dhsilos & (1 << dh)) == 0)) {
                    657:                        ((struct dhdevice *)(dhinfo[dh]->ui_addr))->dhsilo =
                    658:                            (dhchars[dh] > 500? 32 : 16);
                    659:                        dhsilos |= (1 << dh);
                    660:                        dhtransitions++;                /*DEBUG*/
                    661:                    } else if ((dhsilos & (1 << dh)) &&
                    662:                      (dhrate[dh] < dhlowrate)) {
                    663:                        ((struct dhdevice *)(dhinfo[dh]->ui_addr))->dhsilo = 0;
                    664:                        dhsilos &= ~(1 << dh);
                    665:                    }
                    666:                    dhchars[dh] = 0;
                    667:                }
                    668:        }
                    669:        timeout(dhtimer, (caddr_t) 0, dhsilos? FASTTIMER: hz);
                    670: }
                    671: 
                    672: /*
                    673:  * Turn on the line associated with dh dev.
                    674:  */
                    675: dmopen(dev)
                    676:        dev_t dev;
                    677: {
                    678:        register struct tty *tp;
                    679:        register struct dmdevice *addr;
                    680:        register struct uba_device *ui;
                    681:        register int unit;
                    682:        register int dm;
                    683:        int s;
                    684: 
                    685:        unit = minor(dev);
                    686:        dm = unit >> 4;
                    687:        tp = &dh11[unit];
                    688:        unit &= 0xf;
                    689:        if (dm >= NDH || (ui = dminfo[dm]) == 0 || ui->ui_alive == 0) {
                    690:                tp->t_state |= TS_CARR_ON;
                    691:                return;
                    692:        }
                    693:        addr = (struct dmdevice *)ui->ui_addr;
                    694:        s = spl5();
                    695:        addr->dmcsr &= ~DM_SE;
                    696:        while (addr->dmcsr & DM_BUSY)
                    697:                ;
                    698:        addr->dmcsr = unit;
                    699:        addr->dmlstat = DML_ON;
                    700:        if ((addr->dmlstat&DML_CAR) || (dhsoftCAR[dm]&(1<<unit)))
                    701:                tp->t_state |= TS_CARR_ON;
                    702:        addr->dmcsr = DM_IE|DM_SE;
                    703:        while ((tp->t_state&TS_CARR_ON)==0)
                    704:                sleep((caddr_t)&tp->t_rawq, TTIPRI);
                    705:        splx(s);
                    706: }
                    707: 
                    708: /*
                    709:  * Dump control bits into the DM registers.
                    710:  */
                    711: dmctl(dev, bits, how)
                    712:        dev_t dev;
                    713:        int bits, how;
                    714: {
                    715:        register struct uba_device *ui;
                    716:        register struct dmdevice *addr;
                    717:        register int unit, s;
                    718:        int dm;
                    719: 
                    720:        unit = minor(dev);
                    721:        dm = unit >> 4;
                    722:        if ((ui = dminfo[dm]) == 0 || ui->ui_alive == 0)
                    723:                return;
                    724:        addr = (struct dmdevice *)ui->ui_addr;
                    725:        s = spl5();
                    726:        addr->dmcsr &= ~DM_SE;
                    727:        while (addr->dmcsr & DM_BUSY)
                    728:                ;
                    729:        addr->dmcsr = unit & 0xf;
                    730:        switch(how) {
                    731:        case DMSET:
                    732:                addr->dmlstat = bits;
                    733:                break;
                    734:        case DMBIS:
                    735:                addr->dmlstat |= bits;
                    736:                break;
                    737:        case DMBIC:
                    738:                addr->dmlstat &= ~bits;
                    739:                break;
                    740:        }
                    741:        addr->dmcsr = DM_IE|DM_SE;
                    742:        splx(s);
                    743: }
                    744: 
                    745: /*
                    746:  * DM11 interrupt; deal with carrier transitions.
                    747:  */
                    748: dmintr(dm)
                    749:        register int dm;
                    750: {
                    751:        register struct uba_device *ui;
                    752:        register struct tty *tp;
                    753:        register struct dmdevice *addr;
                    754:        int unit;
                    755: 
                    756:        ui = dminfo[dm];
                    757:        if (ui == 0)
                    758:                return;
                    759:        addr = (struct dmdevice *)ui->ui_addr;
                    760:        if (addr->dmcsr&DM_DONE) {
                    761:                if (addr->dmcsr&DM_CF) {
                    762:                        unit = addr->dmcsr & 0xf;
                    763:                        tp = &dh11[(dm << 4) + unit];
                    764:                        if (addr->dmlstat & DML_CAR)
                    765:                                (void)(*linesw[tp->t_line].l_modem)(tp, 1);
                    766:                        else if ((dhsoftCAR[dm] & (1<<unit)) == 0 &&
                    767:                            (*linesw[tp->t_line].l_modem)(tp, 0) == 0)
                    768:                                addr->dmlstat = 0;
                    769:                }
                    770:                addr->dmcsr = DM_IE|DM_SE;
                    771:        }
                    772: }
                    773: #endif

unix.superglobalmegacorp.com

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