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

1.1       root        1: /*     dh.c    2.2     2/18/80 */
                      2: 
                      3: /*
                      4:  *     DH-11 driver
                      5:  *     This driver calls on the DHDM driver.
                      6:  *     If the DH has no DM11-BB, then the latter will
                      7:  *     be fake. To insure loading of the correct DM code,
                      8:  *     lib2 should have dhdm.o, dh.o and dhfdm.o in that order.
                      9:  */
                     10: 
                     11: #include "../h/param.h"
                     12: #include "../h/conf.h"
                     13: #include "../h/dir.h"
                     14: #include "../h/user.h"
                     15: #include "../h/tty.h"
                     16: #include "../h/map.h"
                     17: #include "../h/pte.h"
                     18: #include "../h/uba.h"
                     19: 
                     20: #define        q3      tp->t_outq
                     21: #define        DHADDR  ((struct device *)(UBA0_DEV + 0160020))
                     22: #define        NDH11   16      /* number of lines */
                     23: #define UBACVT(x) (cbase + (short)((x)-(char *)cfree))
                     24: 
                     25: struct cblock {
                     26:        struct cblock *c_next;
                     27:        char    c_info[CBSIZE];
                     28: };
                     29: 
                     30: struct tty dh11[NDH11];
                     31: short  dhcc[NDH11];
                     32: int    dhchars[(NDH11+15)/16];
                     33: int    ndh11   = NDH11;
                     34: int    dhstart();
                     35: int    ttrstrt();
                     36: int cbase;
                     37: extern struct cblock cfree[];
                     38: 
                     39: /*
                     40:  * Hardware control bits
                     41:  */
                     42: #define        BITS6   01
                     43: #define        BITS7   02
                     44: #define        BITS8   03
                     45: #define        TWOSB   04
                     46: #define        PENABLE 020
                     47: /* DEC manuals incorrectly say this bit causes generation of even parity. */
                     48: #define        OPAR    040
                     49: #define        HDUPLX  040000
                     50: 
                     51: #define        IENAB   030100
                     52: #define        PERROR  010000
                     53: #define        FRERROR 020000
                     54: #define        OVERRUN 040000
                     55: #define        XINT    0100000
                     56: #define        SSPEED  7       /* standard speed: 300 baud */
                     57: #define        NSILO   16
                     58: #define        DHTIME  6
                     59: extern int dhtimer();
                     60: 
                     61: /*
                     62:  * DM control bits
                     63:  */
                     64: #define        TURNON  03      /* CD lead + line enable */
                     65: #define        TURNOFF 01      /* line enable */
                     66: #define        RQS     04      /* request to send */
                     67: 
                     68: /*
                     69:  * Software copy of last dhbar
                     70:  */
                     71: short  dhsar[(NDH11+15)/16];
                     72: 
                     73: struct device
                     74: {
                     75:        union {
                     76:                short   dhcsr;
                     77:                char    dhcsrl;
                     78:        } un;
                     79:        short   dhnxch;
                     80:        short   dhlpr;
                     81:        unsigned short  dhcar;
                     82:        short   dhbcr;
                     83:        unsigned short  dhbar;
                     84:        short   dhbreak;
                     85:        short   dhsilo;
                     86: };
                     87: 
                     88: /*
                     89:  * Open a DH11 line.
                     90:  */
                     91: dhopen(dev, flag)
                     92: {
                     93:        register struct tty *tp;
                     94:        register d;
                     95:        register struct device *addr;
                     96:        static  timer_on;
                     97:        int s;
                     98: 
                     99:        d = minor(dev) & 0177;
                    100:        if (d >= NDH11) {
                    101:                u.u_error = ENXIO;
                    102:                return;
                    103:        }
                    104:        tp = &dh11[d];
                    105:        addr = DHADDR;
                    106:        addr += d>>4;
                    107:        tp->t_addr = (caddr_t)addr;
                    108:        tp->t_oproc = dhstart;
                    109:        tp->t_iproc = NULL;
                    110:        tp->t_state |= WOPEN;
                    111:        s = spl6();
                    112:        if (!timer_on) {
                    113:                timer_on++;
                    114:                timeout(dhtimer, (caddr_t)0, DHTIME);
                    115:                cbase = (short)uballoc(cfree, NCLIST*sizeof(struct cblock), 0);
                    116:        }
                    117:        splx(s);
                    118:        addr->un.dhcsr |= IENAB;
                    119:        if ((tp->t_state&ISOPEN) == 0) {
                    120:                ttychars(tp);
                    121:                tp->t_ispeed = SSPEED;
                    122:                tp->t_ospeed = SSPEED;
                    123:                tp->t_flags = ODDP|EVENP|ECHO;
                    124:                dhparam(d);
                    125:        }
                    126:        if (tp->t_state&XCLUDE && u.u_uid!=0) {
                    127:                u.u_error = EBUSY;
                    128:                return;
                    129:        }
                    130:        dmopen(dev);
                    131:        (*linesw[tp->t_line].l_open)(dev,tp);
                    132: }
                    133: 
                    134: /*
                    135:  * Close a DH11 line.
                    136:  */
                    137: dhclose(dev, flag)
                    138: dev_t dev;
                    139: int  flag;
                    140: {
                    141:        register struct tty *tp;
                    142:        register d;
                    143: 
                    144:        d = minor(dev) & 0177;
                    145:        tp = &dh11[d];
                    146:        (*linesw[tp->t_line].l_close)(tp);
                    147:        if (tp->t_state&HUPCLS || (tp->t_state&ISOPEN)==0)
                    148:                dmctl(d, TURNOFF);
                    149:        ttyclose(tp);
                    150: }
                    151: 
                    152: /*
                    153:  * Read from a DH11 line.
                    154:  */
                    155: dhread(dev)
                    156: {
                    157: register struct tty *tp;
                    158: 
                    159:        tp = &dh11[minor(dev) & 0177];
                    160:        (*linesw[tp->t_line].l_read)(tp);
                    161: }
                    162: 
                    163: /*
                    164:  * write on a DH11 line
                    165:  */
                    166: dhwrite(dev)
                    167: {
                    168: register struct tty *tp;
                    169: 
                    170:        tp = &dh11[minor(dev) & 0177];
                    171:        (*linesw[tp->t_line].l_write)(tp);
                    172: }
                    173: 
                    174: /*
                    175:  * DH11 receiver interrupt.
                    176:  */
                    177: dhrint(dev)
                    178: {
                    179:        register struct tty *tp;
                    180:        register short c;
                    181:        register struct device *addr;
                    182: 
                    183:        addr = DHADDR;
                    184:        addr += minor(dev) & 0177;
                    185:        while ((c = addr->dhnxch) < 0) {        /* char. present */
                    186:                tp = &dh11[((minor(dev)&0177)<<4) + ((c>>8)&017)];
                    187:                dhchars[minor(dev)&0177]++;
                    188:                if (tp >= &dh11[NDH11])
                    189:                        continue;
                    190:                if((tp->t_state&ISOPEN)==0) {
                    191:                        wakeup((caddr_t)tp);
                    192:                        continue;
                    193:                }
                    194:                if (c&PERROR)
                    195:                        if ((tp->t_flags&(EVENP|ODDP))==EVENP
                    196:                         || (tp->t_flags&(EVENP|ODDP))==ODDP )
                    197:                                continue;
                    198:                if (c&OVERRUN)
                    199:                        printf("O");
                    200:                if (c&FRERROR)          /* break */
                    201:                        if (tp->t_flags&RAW)
                    202:                                c = 0;  /* null (for getty) */
                    203:                        else
                    204:                                c = 0177;       /* DEL (intr) */
                    205:                (*linesw[tp->t_line].l_rint)(c,tp);
                    206:        }
                    207: }
                    208: 
                    209: /*
                    210:  * stty/gtty for DH11
                    211:  */
                    212: dhioctl(dev, cmd, addr, flag)
                    213: caddr_t addr;
                    214: {
                    215:        register struct tty *tp;
                    216: 
                    217:        tp = &dh11[minor(dev) & 0177];
                    218:        if (ttioccomm(cmd, tp, addr, dev)) {
                    219:                if (cmd==TIOCSETP||cmd==TIOCSETN)
                    220:                        dhparam(dev);
                    221:        } else if (cmd==TIOCSBRK) {
                    222:                /* send a break */
                    223:                register int linebit = 1 << (dev&017);
                    224:                extern dhunbrk();
                    225: 
                    226:                wflushtty(tp);
                    227:                spl5();
                    228:                ((struct device *)tp->t_addr)->dhbreak |= linebit;
                    229:                tp->t_state |= TIMEOUT;
                    230:                timeout(dhunbrk, (caddr_t)tp, 25);      /* 300-500 ms */
                    231:                while (((struct device *)tp->t_addr)->dhbreak & linebit)
                    232:                        sleep((caddr_t)&tp->t_rawq, TTIPRI);
                    233:                tp->t_state &= ~TIMEOUT;
                    234:                spl0();
                    235:                flushtty(tp);
                    236:                return;
                    237:        } else
                    238:                u.u_error = ENOTTY;
                    239: }
                    240: 
                    241: dhunbrk(tp)
                    242: register struct tty *tp;
                    243: {
                    244: 
                    245:        ((struct device *)tp->t_addr)->dhbreak &= ~ (1 << (minor(tp->t_dev)&017));
                    246:        wakeup((caddr_t)&tp->t_rawq);
                    247: }
                    248: 
                    249: /*
                    250:  * Set parameters from open or stty into the DH hardware
                    251:  * registers.
                    252:  */
                    253: dhparam(dev)
                    254: {
                    255:        register struct tty *tp;
                    256:        register struct device *addr;
                    257:        register d;
                    258: 
                    259:        d = minor(dev) & 0177;
                    260:        tp = &dh11[d];
                    261:        addr = (struct device *)tp->t_addr;
                    262:        spl5();
                    263:        addr->un.dhcsrl = (d&017) | IENAB;
                    264:        /*
                    265:         * Hang up line?
                    266:         */
                    267:        if ((tp->t_ispeed)==0) {
                    268:                tp->t_state |= HUPCLS;
                    269:                dmctl(d, TURNOFF);
                    270:                return;
                    271:        }
                    272:        d = ((tp->t_ospeed)<<10) | ((tp->t_ispeed)<<6);
                    273:        if ((tp->t_ispeed) == 4)                /* 134.5 baud */
                    274:                d |= BITS6|PENABLE|HDUPLX;
                    275:        else if (tp->t_flags&RAW)
                    276:                d |= BITS8;
                    277:        else
                    278:                d |= BITS7|PENABLE;
                    279:        if ((tp->t_flags&EVENP) == 0)
                    280:                d |= OPAR;
                    281:        if ((tp->t_ospeed) == 3)        /* 110 baud */
                    282:                d |= TWOSB;
                    283:        addr->dhlpr = d;
                    284:        spl0();
                    285: }
                    286: 
                    287: /*
                    288:  * DH11 transmitter interrupt.
                    289:  * Restart each line which used to be active but has
                    290:  * terminated transmission since the last interrupt.
                    291:  */
                    292: dhxint(dev)
                    293: {
                    294:        register struct tty *tp;
                    295:        register struct device *addr;
                    296:        register d;
                    297:        short ttybit, bar, *sbar;
                    298: 
                    299:        d = minor(dev) & 0177;
                    300:        addr = DHADDR + d;
                    301:        addr->un.dhcsr &= (short)~XINT;
                    302:        sbar = &dhsar[d];
                    303:        bar = *sbar & ~addr->dhbar;
                    304:        d <<= 4; ttybit = 1;
                    305: 
                    306:        for(; bar; d++, ttybit <<= 1) {
                    307:                if(bar&ttybit) {
                    308:                        *sbar &= ~ttybit;
                    309:                        bar &= ~ttybit;
                    310:                        tp = &dh11[d];
                    311:                        if (tp->t_line) {
                    312:                                (*linesw[tp->t_line].l_start)(tp);
                    313:                        } else {
                    314:                                addr->un.dhcsrl = (d&017)|IENAB;
                    315:                                if (tp->t_state&FLUSH)
                    316:                                        tp->t_state &= ~FLUSH;
                    317:                                else {
                    318:                                        ndflush(&q3, dhcc[d]);
                    319:                                }
                    320:                                tp->t_state &= ~BUSY;
                    321:                                dhstart(tp);
                    322:                        }
                    323:                }
                    324:        }
                    325: }
                    326: 
                    327: /*
                    328:  * Start (restart) transmission on the given DH11 line.
                    329:  */
                    330: dhstart(tp)
                    331: register struct tty *tp;
                    332: {
                    333:        register struct device *addr;
                    334:        register short nch;
                    335:        int s, d;
                    336: 
                    337:        /*
                    338:         * If it's currently active, or delaying,
                    339:         * no need to do anything.
                    340:         */
                    341:        s = spl5();
                    342:        d = tp-dh11;
                    343:        addr = (struct device *)tp->t_addr;
                    344:        if (tp->t_state&(TIMEOUT|BUSY|TTSTOP))
                    345:                goto out;
                    346: 
                    347: 
                    348:        /*
                    349:         * If the writer was sleeping on output overflow,
                    350:         * wake him when low tide is reached.
                    351:         */
                    352:        if (tp->t_state&ASLEEP && tp->t_outq.c_cc<=TTLOWAT) {
                    353:                tp->t_state &= ~ASLEEP;
                    354:                if (tp->t_chan)
                    355:                        mcstart(tp->t_chan, (caddr_t)&tp->t_outq); else
                    356:                        wakeup((caddr_t)&tp->t_outq);
                    357:        }
                    358: 
                    359:        if (tp->t_outq.c_cc == 0)
                    360:                goto out;
                    361: 
                    362: 
                    363: 
                    364:        /*
                    365:         * Find number of characters to transfer.
                    366:         */
                    367:        if (tp->t_flags & RAW) {
                    368:                nch = ndqb(&tp->t_outq, 0);
                    369:        } else {
                    370:                nch = ndqb(&tp->t_outq, 0200);
                    371:                if (nch == 0) {
                    372:                        nch = getc(&tp->t_outq);
                    373:                        timeout(ttrstrt, (caddr_t)tp, (nch&0177)+6);
                    374:                        tp->t_state |= TIMEOUT;
                    375:                        goto out;
                    376:                }
                    377:        }
                    378:        /*
                    379:         * If any characters were set up, start transmission;
                    380:         */
                    381:        if (nch) {
                    382:                addr->un.dhcsrl = (d&017)|IENAB;
                    383:                addr->dhcar = UBACVT(tp->t_outq.c_cf);
                    384:                addr->dhbcr = -nch;
                    385:                dhcc[d] = nch;
                    386:                nch = 1<<(d&017);
                    387:                addr->dhbar |= nch;
                    388:                dhsar[d>>4] |= nch;
                    389:                tp->t_state |= BUSY;
                    390:        }
                    391:     out:
                    392:        splx(s);
                    393: }
                    394: 
                    395: 
                    396: /*
                    397:  * Stop output on a line.
                    398:  * Assume call is made at spl6.
                    399:  */
                    400: dhstop(tp, flag)
                    401: register struct tty *tp;
                    402: {
                    403:        register struct device *addr;
                    404:        register d, s;
                    405: 
                    406:        addr = (struct device *)tp->t_addr;
                    407:        s = spl6();
                    408:        if (tp->t_state & BUSY) {
                    409: /*
                    410:                d = minor(tp->t_dev);
                    411:                addr->un.dhcsrl = (d&017) | IENAB;
                    412: */
                    413:                if ((tp->t_state&TTSTOP)==0) {
                    414:                        tp->t_state |= FLUSH;
                    415:                }
                    416: /*
                    417:                addr->dhbcr = -1;
                    418: */
                    419:        }
                    420:        splx(s);
                    421: }
                    422: 
                    423: dhtimer(dev)
                    424: {
                    425: register d,cc;
                    426: register struct device *addr;
                    427: 
                    428:        addr = DHADDR; d = 0;
                    429:        do {
                    430:                cc = dhchars[d];
                    431:                dhchars[d] = 0;
                    432:                if (cc > 50)
                    433:                        cc = 32; else
                    434:                        if (cc > 16)
                    435:                                cc = 16; else
                    436:                                cc = 0;
                    437:                addr->dhsilo = cc;
                    438:                addr += 1;
                    439:                dhrint(d++);
                    440:        } while (d < (NDH11+15)/16);
                    441:        timeout(dhtimer, (caddr_t)0, DHTIME);
                    442: }

unix.superglobalmegacorp.com

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