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

unix.superglobalmegacorp.com

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