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

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

unix.superglobalmegacorp.com

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