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

unix.superglobalmegacorp.com

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