Annotation of 41BSD/4.0.upgrade/sys/dev/dh.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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