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

1.1       root        1: /*     dh.c    4.3     11/13/80        */
                      2: 
                      3: #include "../conf/dh.h"
                      4: #if NDH11 > 0
                      5: /*
                      6:  * DH-11 driver
                      7:  *
                      8:  * Loaded with dhdm if there are DM-11's otherwise with dhfdm.
                      9:  *
                     10:  * NB: WE HAVEN'T TESTED dhdm CODE ON VAX.
                     11:  */
                     12: 
                     13: #include "../h/param.h"
                     14: #include "../h/conf.h"
                     15: #include "../h/dir.h"
                     16: #include "../h/user.h"
                     17: #include "../h/tty.h"
                     18: #include "../h/map.h"
                     19: #include "../h/pte.h"
                     20: #include "../h/uba.h"
                     21: #include "../h/bk.h"
                     22: #include "../h/clist.h"
                     23: #include "../h/mx.h"
                     24: 
                     25: /*
                     26:  * When running dz's using only SAE (silo alarm) on input
                     27:  * it is necessary to call dzrint() at clock interrupt time.
                     28:  * This is unsafe unless spl5()s in tty code are changed to
                     29:  * spl6()s to block clock interrupts.  Note that the dh driver
                     30:  * currently in use works the same way as the dz, even though
                     31:  * we could try to more intelligently manage its silo.
                     32:  * Thus don't take this out if you have no dz's unless you
                     33:  * change clock.c and dhtimer().
                     34:  */
                     35: #define        spl5    spl6
                     36: 
                     37: #define        UBACVT(x) (cbase + (short)((x)-(char *)cfree))
                     38: 
                     39: struct tty dh11[NDH11];
                     40: int    dhact;
                     41: int    dhisilo;
                     42: int    ndh11   = NDH11;
                     43: int    dhstart();
                     44: int    ttrstrt();
                     45: int    dh_ubinfo;
                     46: int    cbase;
                     47: int    getcbase;
                     48: 
                     49: /*
                     50:  * Hardware control bits
                     51:  */
                     52: #define        BITS6   01
                     53: #define        BITS7   02
                     54: #define        BITS8   03
                     55: #define        TWOSB   04
                     56: #define        PENABLE 020
                     57: /* DEC manuals incorrectly say this bit causes generation of even parity. */
                     58: #define        OPAR    040
                     59: #define        HDUPLX  040000
                     60: 
                     61: #define        IENAB   030100
                     62: #define        NXM     02000
                     63: #define        CLRNXM  0400
                     64: #define        PERROR  010000
                     65: #define        FRERROR 020000
                     66: #define        OVERRUN 040000
                     67: #define        XINT    0100000
                     68: #define        SSPEED  7       /* standard speed: 300 baud */
                     69: 
                     70: /*
                     71:  * DM control bits
                     72:  */
                     73: #define        TURNON  03      /* CD lead + line enable */
                     74: #define        TURNOFF 01      /* line enable */
                     75: #define        DTR     02      /* data terminal ready */
                     76: #define        RQS     04      /* request to send */
                     77: 
                     78: /*
                     79:  * Software copy of last dhbar
                     80:  */
                     81: short  dhsar[(NDH11+15)/16];
                     82: 
                     83: struct device
                     84: {
                     85:        union {
                     86:                short   dhcsr;
                     87:                char    dhcsrl;
                     88:        } un;
                     89:        short   dhnxch;
                     90:        short   dhlpr;
                     91:        unsigned short  dhcar;
                     92:        short   dhbcr;
                     93:        unsigned short  dhbar;
                     94:        short   dhbreak;
                     95:        short   dhsilo;
                     96: };
                     97: 
                     98: /*
                     99:  * Open a DH11 line.
                    100:  */
                    101: /*ARGSUSED*/
                    102: dhopen(dev, flag)
                    103: {
                    104:        register struct tty *tp;
                    105:        register d;
                    106:        register struct device *addr;
                    107:        int s;
                    108: 
                    109:        d = minor(dev) & 0177;
                    110:        if (d >= NDH11) {
                    111:                u.u_error = ENXIO;
                    112:                return;
                    113:        }
                    114:        tp = &dh11[d];
                    115:        addr = DHADDR;
                    116:        addr += d>>4;
                    117:        tp->t_addr = (caddr_t)addr;
                    118:        tp->t_oproc = dhstart;
                    119:        tp->t_iproc = NULL;
                    120:        tp->t_state |= WOPEN;
                    121:        s = spl6();
                    122:        if (!getcbase) {
                    123:                getcbase++;
                    124:                /* 512+ is a kludge to try to get around a hardware problem */
                    125:                dh_ubinfo = uballoc((caddr_t)cfree, 512+NCLIST*sizeof(struct cblock), 0);
                    126:                cbase = (short)dh_ubinfo;
                    127:        }
                    128:        splx(s);
                    129:        addr->un.dhcsr |= IENAB;
                    130:        dhact |= (1<<(d>>4));
                    131:        if ((tp->t_state&ISOPEN) == 0) {
                    132:                ttychars(tp);
                    133:                if (tp->t_ispeed == 0) {
                    134:                        tp->t_ispeed = SSPEED;
                    135:                        tp->t_ospeed = SSPEED;
                    136:                        tp->t_flags = ODDP|EVENP|ECHO;
                    137:                }
                    138:                dhparam(d);
                    139:        }
                    140:        if (tp->t_state&XCLUDE && u.u_uid!=0) {
                    141:                u.u_error = EBUSY;
                    142:                return;
                    143:        }
                    144:        dmopen(dev);
                    145:        (*linesw[tp->t_line].l_open)(dev,tp);
                    146: }
                    147: 
                    148: /*
                    149:  * Close a DH11 line.
                    150:  */
                    151: /*ARGSUSED*/
                    152: dhclose(dev, flag)
                    153: dev_t dev;
                    154: int  flag;
                    155: {
                    156:        register struct tty *tp;
                    157:        register d;
                    158: 
                    159:        d = minor(dev) & 0177;
                    160:        tp = &dh11[d];
                    161:        (*linesw[tp->t_line].l_close)(tp);
                    162:        if (tp->t_state&HUPCLS || (tp->t_state&ISOPEN)==0)
                    163:                dmctl(d, TURNOFF, DMSET);
                    164:        ttyclose(tp);
                    165: }
                    166: 
                    167: /*
                    168:  * Read from a DH11 line.
                    169:  */
                    170: dhread(dev)
                    171: {
                    172: register struct tty *tp;
                    173: 
                    174:        tp = &dh11[minor(dev) & 0177];
                    175:        (*linesw[tp->t_line].l_read)(tp);
                    176: }
                    177: 
                    178: /*
                    179:  * write on a DH11 line
                    180:  */
                    181: dhwrite(dev)
                    182: {
                    183: register struct tty *tp;
                    184: 
                    185:        tp = &dh11[minor(dev) & 0177];
                    186:        (*linesw[tp->t_line].l_write)(tp);
                    187: }
                    188: 
                    189: /*
                    190:  * DH11 receiver interrupt.
                    191:  */
                    192: dhrint(dev)
                    193: {
                    194:        register struct tty *tp;
                    195:        register short c;
                    196:        register struct device *addr;
                    197:        register struct tty *tp0;
                    198:        int s;
                    199: 
                    200:        s = spl6();     /* see comment in clock.c */
                    201:        addr = DHADDR;
                    202:        addr += minor(dev) & 0177;
                    203:        tp0 = &dh11[((minor(dev)&0177)<<4)];
                    204:        while ((c = addr->dhnxch) < 0) {        /* char. present */
                    205:                tp = tp0 + ((c>>8)&017);
                    206:                if (tp >= &dh11[NDH11])
                    207:                        continue;
                    208:                if((tp->t_state&ISOPEN)==0) {
                    209:                        wakeup((caddr_t)tp);
                    210:                        continue;
                    211:                }
                    212:                if (c&PERROR)
                    213:                        if ((tp->t_flags&(EVENP|ODDP))==EVENP
                    214:                         || (tp->t_flags&(EVENP|ODDP))==ODDP )
                    215:                                continue;
                    216:                if (c&OVERRUN)
                    217:                        printf("O");
                    218:                if (c&FRERROR)          /* break */
                    219:                        if (tp->t_flags&RAW)
                    220:                                c = 0;  /* null (for getty) */
                    221:                        else
                    222: #ifdef IIASA
                    223:                                continue;
                    224: #else
                    225:                                c = tun.t_intrc;
                    226: #endif
                    227:                if (tp->t_line == NETLDISC) {
                    228:                        c &= 0177;
                    229:                        BKINPUT(c, tp);
                    230:                } else
                    231:                        (*linesw[tp->t_line].l_rint)(c,tp);
                    232:        }
                    233:        splx(s);
                    234: }
                    235: 
                    236: /*
                    237:  * stty/gtty for DH11
                    238:  */
                    239: /*ARGSUSED*/
                    240: dhioctl(dev, cmd, addr, flag)
                    241: caddr_t addr;
                    242: {
                    243:        register struct tty *tp;
                    244: 
                    245:        tp = &dh11[minor(dev) & 0177];
                    246:        cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
                    247:        if (cmd==0)
                    248:                return;
                    249:        if (ttioctl(cmd, tp, addr, dev, flag)) {
                    250:                if (cmd==TIOCSETP||cmd==TIOCSETN)
                    251:                        dhparam(dev);
                    252:        } else switch(cmd) {
                    253:        case TIOCSBRK:
                    254:                ((struct device *)(tp->t_addr))->dhbreak |= 1<<(minor(dev)&017);
                    255:                break;
                    256:        case TIOCCBRK:
                    257:                ((struct device *)(tp->t_addr))->dhbreak &= ~(1<<(minor(dev)&017));
                    258:                break;
                    259:        case TIOCSDTR:
                    260:                dmctl(minor(dev), DTR|RQS, DMBIS);
                    261:                break;
                    262:        case TIOCCDTR:
                    263:                dmctl(minor(dev), DTR|RQS, DMBIC);
                    264:                break;
                    265:        default:
                    266:                u.u_error = ENOTTY;
                    267:        }
                    268: }
                    269: 
                    270: /*
                    271:  * Set parameters from open or stty into the DH hardware
                    272:  * registers.
                    273:  */
                    274: dhparam(dev)
                    275: {
                    276:        register struct tty *tp;
                    277:        register struct device *addr;
                    278:        register d;
                    279:        int s;
                    280: 
                    281:        d = minor(dev) & 0177;
                    282:        tp = &dh11[d];
                    283:        addr = (struct device *)tp->t_addr;
                    284:        s = spl5();
                    285:        addr->un.dhcsrl = (d&017) | IENAB;
                    286:        /*
                    287:         * Hang up line?
                    288:         */
                    289:        if ((tp->t_ispeed)==0) {
                    290:                tp->t_state |= HUPCLS;
                    291:                dmctl(d, TURNOFF, DMSET);
                    292:                return;
                    293:        }
                    294:        d = ((tp->t_ospeed)<<10) | ((tp->t_ispeed)<<6);
                    295:        if ((tp->t_ispeed) == 4)                /* 134.5 baud */
                    296:                d |= BITS6|PENABLE|HDUPLX;
                    297:        else if (tp->t_flags&RAW)
                    298:                d |= BITS8;
                    299:        else
                    300:                d |= BITS7|PENABLE;
                    301:        if ((tp->t_flags&EVENP) == 0)
                    302:                d |= OPAR;
                    303:        if ((tp->t_ospeed) == 3)        /* 110 baud */
                    304:                d |= TWOSB;
                    305:        addr->dhlpr = d;
                    306:        splx(s);
                    307: }
                    308: 
                    309: /*
                    310:  * DH11 transmitter interrupt.
                    311:  * Restart each line which used to be active but has
                    312:  * terminated transmission since the last interrupt.
                    313:  */
                    314: dhxint(dev)
                    315: {
                    316:        register struct tty *tp;
                    317:        register struct device *addr;
                    318:        register d;
                    319:        short ttybit, bar, *sbar;
                    320:        int s;
                    321: 
                    322:        s = spl6();     /* block the clock */
                    323:        d = minor(dev) & 0177;
                    324:        addr = DHADDR + d;
                    325:        addr->un.dhcsr &= (short)~XINT;
                    326:        if (addr->un.dhcsr & NXM) {
                    327:                addr->un.dhcsr |= CLRNXM;
                    328:                printf("dh clr NXM\n");
                    329:        }
                    330:        sbar = &dhsar[d];
                    331:        bar = *sbar & ~addr->dhbar;
                    332:        d <<= 4; ttybit = 1;
                    333: 
                    334:        for(; bar; d++, ttybit <<= 1) {
                    335:                if(bar&ttybit) {
                    336:                        *sbar &= ~ttybit;
                    337:                        bar &= ~ttybit;
                    338:                        tp = &dh11[d];
                    339:                        tp->t_state &= ~BUSY;
                    340:                        if (tp->t_state&FLUSH)
                    341:                                tp->t_state &= ~FLUSH;
                    342:                        else {
                    343:                                addr->un.dhcsrl = (d&017)|IENAB;
                    344:                                ndflush(&tp->t_outq,
                    345:                                    (int)(short)addr->dhcar-UBACVT(tp->t_outq.c_cf));
                    346:                        }
                    347:                        if (tp->t_line)
                    348:                                (*linesw[tp->t_line].l_start)(tp);
                    349:                        else
                    350:                                dhstart(tp);
                    351:                }
                    352:        }
                    353:        splx(s);
                    354: }
                    355: 
                    356: /*
                    357:  * Start (restart) transmission on the given DH11 line.
                    358:  */
                    359: dhstart(tp)
                    360: register struct tty *tp;
                    361: {
                    362:        register struct device *addr;
                    363:        register short nch;
                    364:        int s, d;
                    365: 
                    366:        /*
                    367:         * If it's currently active, or delaying,
                    368:         * no need to do anything.
                    369:         */
                    370:        s = spl5();
                    371:        d = tp-dh11;
                    372:        addr = (struct device *)tp->t_addr;
                    373:        if (tp->t_state&(TIMEOUT|BUSY|TTSTOP))
                    374:                goto out;
                    375: 
                    376:        /*
                    377:         * If the writer was sleeping on output overflow,
                    378:         * wake him when low tide is reached.
                    379:         */
                    380:        if (tp->t_state&ASLEEP && tp->t_outq.c_cc<=TTLOWAT(tp)) {
                    381:                tp->t_state &= ~ASLEEP;
                    382:                if (tp->t_chan)
                    383:                        mcstart(tp->t_chan, (caddr_t)&tp->t_outq);
                    384:                else
                    385:                        wakeup((caddr_t)&tp->t_outq);
                    386:        }
                    387: 
                    388:        if (tp->t_outq.c_cc == 0)
                    389:                goto out;
                    390: 
                    391:        /*
                    392:         * Find number of characters to transfer.
                    393:         */
                    394:        if (tp->t_flags & RAW) {
                    395:                nch = ndqb(&tp->t_outq, 0);
                    396:        } else {
                    397:                nch = ndqb(&tp->t_outq, 0200);
                    398:                if (nch == 0) {
                    399:                        nch = getc(&tp->t_outq);
                    400:                        timeout(ttrstrt, (caddr_t)tp, (nch&0177)+6);
                    401:                        tp->t_state |= TIMEOUT;
                    402:                        goto out;
                    403:                }
                    404:        }
                    405:        /*
                    406:         * If any characters were set up, start transmission;
                    407:         */
                    408:        if (nch) {
                    409:                addr->un.dhcsrl = (d&017)|IENAB;
                    410:                addr->dhcar = UBACVT(tp->t_outq.c_cf);
                    411:                addr->dhbcr = -nch;
                    412:                nch = 1<<(d&017);
                    413:                addr->dhbar |= nch;
                    414:                dhsar[d>>4] |= nch;
                    415:                tp->t_state |= BUSY;
                    416:        }
                    417:     out:
                    418:        splx(s);
                    419: }
                    420: 
                    421: /*
                    422:  * Stop output on a line.
                    423:  * Assume call is made at spl6.
                    424:  */
                    425: /*ARGSUSED*/
                    426: dhstop(tp, flag)
                    427: register struct tty *tp;
                    428: {
                    429:        register struct device *addr;
                    430:        register d, s;
                    431: 
                    432:        addr = (struct device *)tp->t_addr;
                    433:        s = spl6();
                    434:        if (tp->t_state & BUSY) {
                    435:                d = minor(tp->t_dev);
                    436:                addr->un.dhcsrl = (d&017) | IENAB;
                    437:                if ((tp->t_state&TTSTOP)==0)
                    438:                        tp->t_state |= FLUSH;
                    439:                addr->dhbcr = -1;
                    440:        }
                    441:        splx(s);
                    442: }
                    443: 
                    444: int    dhsilo = 16;
                    445: /*
                    446:  * Silo control is fixed strategy
                    447:  * here, paralleling only option available
                    448:  * on DZ-11.
                    449:  */
                    450: /*ARGSUSED*/
                    451: dhtimer()
                    452: {
                    453:        register d;
                    454:        register struct device *addr;
                    455: 
                    456:        addr = DHADDR; d = 0;
                    457:        do {
                    458:                if (dhact & (1<<d)) {
                    459:                        if ((dhisilo & (1<<d)) == 0) {
                    460:                                addr->dhsilo = dhsilo;
                    461:                                dhisilo |= 1<<d;
                    462:                        }
                    463:                        dhrint(d);
                    464:                }
                    465:                d++;
                    466:                addr++;
                    467:        } while (d < (NDH11+15)/16);
                    468: }
                    469: 
                    470: /*
                    471:  * Reset state of driver if UBA reset was necessary.
                    472:  * Reset the csrl and lpr registers on open lines, and
                    473:  * restart transmitters.
                    474:  */
                    475: dhreset()
                    476: {
                    477:        int d;
                    478:        register struct tty *tp;
                    479:        register struct device *addr;
                    480: 
                    481:        if (getcbase == 0)
                    482:                return;
                    483:        printf(" dh");
                    484:        dhisilo = 0;
                    485:        ubafree(dh_ubinfo);
                    486:        dh_ubinfo = uballoc((caddr_t)cfree, NCLIST*sizeof (struct cblock), 0);
                    487:        cbase = (short)dh_ubinfo;
                    488:        d = 0;
                    489:        do {
                    490:                addr = DHADDR + d;
                    491:                if (dhact & (1<<d))
                    492:                        addr->un.dhcsr |= IENAB;
                    493:                d++;
                    494:        } while (d < (NDH11+15)/16);
                    495:        for (d = 0; d < NDH11; d++) {
                    496:                tp = &dh11[d];
                    497:                if (tp->t_state & (ISOPEN|WOPEN)) {
                    498:                        dhparam(d);
                    499:                        dmctl(d, TURNON, DMSET);
                    500:                        tp->t_state &= ~BUSY;
                    501:                        dhstart(tp);
                    502:                }
                    503:        }
                    504:        dhtimer();
                    505: }
                    506: #endif

unix.superglobalmegacorp.com

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