Annotation of 41BSD/cmd/berknet/dz1.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *     DZ-11 driver
                      3:  *     ------------
                      4:  *
                      5:  *     OPTIMIZED dz driver to handle multiple dzs as efficiently
                      6:  *     as possible.  The efficiency is gained by disabling all
                      7:  *     dz transmitter interrupts and using a KW11-P to generate
                      8:  *     suitable interrupts.  Carrier is supported but not Ring.
                      9:  *
                     10:  *                             Ian Johnstone   UNSW
                     11:  *                             May 1979
                     12:  */ 
                     13: 
                     14: #include       "../defines.h"
                     15: #include       "../param.h"
                     16: #include       "../conf.h"
                     17: #include       "../user.h"
                     18: #include       "../tty.h"
                     19: #include       "../proc.h"
                     20: 
                     21: #define        NDZ              7              /* no. of dz-11s */
                     22: 
                     23: #define NDZLIN          8              /* no. of lines per dz DO NOT ALTER */
                     24: #define NLINES (NDZLIN*NDZ)            /* total no. of lines available */
                     25: 
                     26: #define SSPEED         11              /* standard speed 2400 bd */
                     27: 
                     28: #define CLOCK           0172540        /* kw11-p lives here */
                     29: 
                     30: struct
                     31: {
                     32:        int csr;                        /* control and status */
                     33: #define GO     0101                    /* down, single, 100K, run */
                     34:        unsigned counter;               /* counter */
                     35: };
                     36: 
                     37: struct tty dz11[NLINES];               /* tty structures for this dz */
                     38: 
                     39: struct dz                              /* one for each dz-11 */ 
                     40: {
                     41:        int *dzaddr;                    /* control registers for this dz */ 
                     42:        char nocarr;                    /* set for lines WITHOUT carrier */ 
                     43:        char sopen;                     /* set for lines with exclusive use */ 
                     44:        struct tty *ttys[NDZLIN];       /* address of tty structs this dz */
                     45:                                        /* that is only ONE `open' allowed */ 
                     46:        char openl;                     /* flags for open lines */ 
                     47:        char closl;                     /* flags to indicate closing lines */
                     48:        char xmit;                      /* set for lines to transmit on */
                     49:        unsigned pyerrors;              /* number of parity errors on input */ 
                     50:        unsigned overrors;              /* number of overrun errors on input */ 
                     51:        int closet[NDZLIN];             /* handle closing via this field */
                     52: }
                     53: dz[NDZ]
                     54: {
                     55:        {
                     56:          0160100, 0377, 0000,
                     57:          &dz11[000],&dz11[001],&dz11[002],&dz11[003],
                     58:          &dz11[004],&dz11[005],&dz11[006],&dz11[007]
                     59:        },
                     60:        {
                     61:          0160110, 0007, 0000,
                     62:          &dz11[010],&dz11[011],&dz11[012],&dz11[013],
                     63:          &dz11[014],&dz11[015],&dz11[016],&dz11[017]
                     64:        },
                     65:        {
                     66:          0160120, 0320, 0020,
                     67:          &dz11[020],&dz11[021],&dz11[022],&dz11[023],
                     68:          &dz11[024],&dz11[025],&dz11[026],&dz11[027]
                     69:        },
                     70:        {
                     71:          0160130, 0000, 0000,
                     72:          &dz11[030],&dz11[031],&dz11[032],&dz11[033],
                     73:          &dz11[034],&dz11[035],&dz11[036],&dz11[037]
                     74:        },
                     75:        {
                     76:          0160140, 0000, 0000,
                     77:          &dz11[040],&dz11[041],&dz11[042],&dz11[043],
                     78:          &dz11[044],&dz11[045],&dz11[046],&dz11[047]
                     79:        },
                     80:        {
                     81:          0160150, 0360, 0100,
                     82:          &dz11[050],&dz11[051],&dz11[052],&dz11[053],
                     83:          &dz11[054],&dz11[055],&dz11[056],&dz11[057]
                     84:        },
                     85:        {
                     86:          0160160, 0110, 0013,
                     87:          &dz11[060],&dz11[061],&dz11[062],&dz11[063],
                     88:          &dz11[064],&dz11[065],&dz11[066],&dz11[067]
                     89:        },
                     90: /*
                     91:        {
                     92:          0160170, 0377, 0000,
                     93:          &dz11[070],&dz11[071],&dz11[072],&dz11[073],
                     94:          &dz11[074],&dz11[075],&dz11[076],&dz11[077]
                     95:        }
                     96: */
                     97: };
                     98: 
                     99: int dzopenc;                   /* equal to total number of 'open' lines */
                    100: 
                    101: int dzrcvscan;                 /* when <= 0 scan receiver silos */
                    102: 
                    103: char dzbitab[NDZLIN]           /* convert line numbers to bit pattern */
                    104: {
                    105:        0001, 0002, 0004, 0010, 0020, 0040, 0100, 0200
                    106: };
                    107: 
                    108: #define        SPLDZ   spl5            /* dz interrupts at this priority */
                    109: 
                    110: /*
                    111:  *     DZ11 register layout
                    112:  */ 
                    113: struct dzr_read
                    114: {
                    115:        int dzcsr;      /* r/w */ 
                    116:        int dzrbuf;     /* no bit, byte, or tst ops */ 
                    117:        char dztcr;     /* r/w */ 
                    118:        char dzdtr;     /* r/w */ 
                    119:        char dzring;
                    120:        char dzcarr;
                    121: };
                    122: struct dzr_write
                    123: {
                    124:        int dzcsr;
                    125:        int dzlpr;      /* no bit or byte ops */ 
                    126:        char dztcr;
                    127:        char dzdtr;
                    128:        char dztbuf;    /* no bit ops */ 
                    129:        char dzbrk;     /* no bit ops */ 
                    130: };
                    131: /*
                    132:  *     register control bits
                    133:  */ 
                    134: #define SAE            010000          /* dzcsr */
                    135: #define RIE            0100
                    136: #define MSE            040
                    137: #define RCVR_ON        010000          /* dzlpr */
                    138: #define ODD_PAR        0300
                    139: #define EVN_PAR        0100
                    140: #define TWOSBIT                040
                    141: #define C8BIT          030
                    142: #define C7BIT          020
                    143: #define        RERROR          070000          /* dzrbuf */
                    144: #define OVR_RUN        040000  
                    145: #define FRAME          020000
                    146: #define PARITY         010000
                    147: 
                    148: /*
                    149:  *     Table to map UNIX standard speeds to DZ11 speeds.
                    150:  *     Illegal speeds are ignored, and are indicated by 0200 bit.
                    151:  */ 
                    152: char dzspeedmap[16]
                    153: {
                    154:          0200  /* 0 - zero */ 
                    155:        , 0220  /* 1 - 50 */ 
                    156:        , 0221  /* 2 - 75 */ 
                    157:        , 0222  /* 3 - 110 */ 
                    158:        , 0223  /* 4 - 134.5 */ 
                    159:        , 0224  /* 5 - 150 */ 
                    160:        , 0200  /* 6 - ILLEGAL */ 
                    161: #define        LOWSPEED 7      /* lowest speed allowed on dz */
                    162:        ,  025  /* 7 - 300 */ 
                    163:        ,  026  /* 8 - 600 */ 
                    164:        ,  027  /* 9 - 1200 */ 
                    165:        , 0230  /* 10 - 1800 */ 
                    166:        ,  032  /* 11 - 2400 */ 
                    167:        ,  034  /* 12 - 4800 */ 
                    168:        ,  036  /* 13 - 9600 */ 
                    169:        , 0231  /* 14 - ext A - maps to 2000 */ 
                    170:        , 0237  /* 15 - ext B - maps to 19200 */ 
                    171: };
                    172: 
                    173: /*
                    174:  *     Table to map UNIX standard speeds to time between interrupts for
                    175:  *     a line running at that speed.  The value in the table is multiplied
                    176:  *     by 10 to get a value in microseconds.  A nominal 20 microseconds
                    177:  *     is subtracted to make up for interrupt overhead.
                    178:  */ 
                    179: 
                    180: unsigned dzmicmap[16]
                    181: {
                    182:               0                /* 0 - zero */ 
                    183:        ,  19998                /* 1 - 50 */ 
                    184:        ,  13331                /* 2 - 75 */ 
                    185:        ,   9088                /* 3 - 110 */ 
                    186:        ,   7433                /* 4 - 134.5 */ 
                    187:        ,   6665                /* 5 - 150 */ 
                    188:        ,      0                /* 6 - ILLEGAL */ 
                    189:        ,   3331                /* 7 - 300 */ 
                    190:        ,   1665                /* 8 - 600 */ 
                    191:        ,    831                /* 9 - 1200 */ 
                    192:        ,    554                /* 10 - 1800 */ 
                    193:        ,    415                /* 11 - 2400 */ 
                    194:        ,    206                /* 12 - 4800 */ 
                    195:        ,    102                /* 13 - 9600 */ 
                    196:        ,    498                /* 14 - ext A - maps to 2000 */ 
                    197:        ,     50                /* 15 - ext B - maps to 19200 */ 
                    198: };
                    199: 
                    200: /*
                    201:  *     open a DZ11 line
                    202:  */ 
                    203: dzopen(dev, flag)
                    204: {
                    205:        extern dzstart();
                    206:        register struct tty *tp;
                    207:        register struct dz *dzp;
                    208:        register lino;
                    209: 
                    210:        lino =  dev.d_minor;
                    211:        if(lino >= NLINES)
                    212:        {
                    213:                u.u_error = ENXIO;
                    214:                return;
                    215:        }
                    216:        dzp   =  &dz[lino>>3];
                    217:        if(!fkword(dzp->dzaddr))                /* fix036 */
                    218:        {
                    219:                u.u_error = ENXIO;
                    220:                return;
                    221:        }                                       /* fix036 */
                    222:        tp    =  &dz11[lino];
                    223:        lino =& 07;
                    224: 
                    225:        if( (dzp->sopen&dzbitab[lino]) && (dzp->openl&dzbitab[lino]) )
                    226:        {
                    227:                u.u_error = EOPENFAIL;
                    228:                return;
                    229:        }
                    230: 
                    231:        if(u.u_procp->p_ttyp == 0)
                    232:                u.u_procp->p_ttyp = tp;
                    233: 
                    234:        SPLDZ();
                    235: 
                    236:        if( (dzp->openl&dzbitab[lino]) == 0 )
                    237:        {
                    238:                tp->t_dev    = dev;
                    239:                tp->t_state  = (ISOPEN|CARR_ON|SSTART);
                    240:                tp->t_addr   = &dzstart;
                    241:                tp->t_speeds = SSPEED|(SSPEED<<8);
                    242:                tp->t_flags  = ODDP|EVENP|XTABS|RAW;
                    243:                tp->t_erase  = CERASE;
                    244:                tp->t_kill   = CKILL;
                    245: 
                    246:                dzparam(tp);
                    247: 
                    248:                if(dzp->openl == 0)
                    249:                        dzp->dzaddr->dzcsr =| (RIE|SAE|MSE); /* init */
                    250: 
                    251:                dzp->openl =| dzbitab[lino];
                    252: 
                    253:                if(dzopenc++ == 0)
                    254:                        dzxint();       /* start transmitting */
                    255: 
                    256:        }
                    257:        else
                    258:                dzp->closl =& ~dzbitab[lino];
                    259:        spl0();
                    260: }
                    261: 
                    262: /*
                    263:  *     close a DZ11 line
                    264:  */ 
                    265: dzclose(dev)
                    266: {
                    267:        register struct tty *tp;
                    268:        register struct dz *dzp;
                    269:        register lino;
                    270: 
                    271:        lino  =  dev.d_minor;
                    272:        dzp   =  &dz[lino>>3];
                    273:        tp    =  &dz11[lino];
                    274:        lino  =& 07;
                    275: 
                    276:        dzp->closet[lino] =  tp->t_outq.c_cc << 1;      /* time for close */
                    277:        dzp->closl  =| dzbitab[lino];
                    278:        dzp->xmit   =| dzbitab[lino];                   /* start transmitting */
                    279:        dzp->dzaddr->dztcr =| dzbitab[lino];            /* start transmitting */
                    280: }
                    281: 
                    282: /*
                    283:  *     read from a DZ11 line
                    284:  */ 
                    285: dzread(dev)
                    286: {
                    287:        ttread( &dz11[dev.d_minor] );
                    288: }
                    289: 
                    290: /*
                    291:  *     write on a DZ11 line
                    292:  */ 
                    293: dzwrite(dev)
                    294: {
                    295:        ttwrite( &dz11[dev.d_minor] );
                    296: }
                    297: 
                    298: /*
                    299:  *     stty/gtty for DZ11
                    300:  */ 
                    301: dzsgtty(dev, av)
                    302: {
                    303:        register struct tty *tp;
                    304: 
                    305:        if((av == 0) && (dzspeedmap[u.u_arg[0]&017] < 0))
                    306:        {
                    307:                u.u_error = ENXIO;      /* illegal speed */ 
                    308:                return;
                    309:        }
                    310:        tp = &dz11[dev.d_minor];
                    311:        if(ttystty(tp, av))
                    312:                return;
                    313:        dzparam(tp);
                    314: }
                    315: 
                    316: /*
                    317:  *     set parameters from open or stty into DZ hardware registers
                    318:  */ 
                    319: dzparam(tp)
                    320: register struct tty *tp;
                    321: {
                    322:        register lpr, x;
                    323:        extern wakeup();
                    324: 
                    325:        lpr = dzspeedmap[tp->t_speeds&017]<<8;
                    326: 
                    327:        if((x = tp->t_flags)&EVENP)
                    328:                if((x&ODDP) == 0)
                    329:                        lpr =| (EVN_PAR|C7BIT);
                    330:                else
                    331:                        lpr =| C8BIT;
                    332:        else if(x&ODDP)
                    333:                lpr =| (ODD_PAR|C7BIT);
                    334:        else
                    335:                lpr =| C8BIT;
                    336: 
                    337:        /* set new speed, char currently in uart may be screwed */ 
                    338: 
                    339:        dz[tp->t_dev.d_minor>>3].dzaddr->dzlpr = lpr|(tp->t_dev.d_minor&07);
                    340: }
                    341: /*
                    342:  *     dz start routine
                    343:  */
                    344: dzstart(tp)    /* at SPLDZ */
                    345: struct tty *tp;
                    346: {
                    347:        register lino = tp->t_dev.d_minor;
                    348:        register struct dz *dzp;
                    349: 
                    350:        dzp  =  &dz[lino>>3];
                    351:        lino =& 07;
                    352:        dzp->xmit =| dzbitab[lino];             /* start transmitting */
                    353:        dzp->dzaddr->dztcr =| dzbitab[lino];    /* start transmitting */
                    354: }
                    355: 
                    356: /*
                    357:  *     DZ11 transmitter interrupt.
                    358:  *
                    359:  *     Scan every line on each dz.  Internal dz limitations
                    360:  *     force this scan to take an unusual form.  One line
                    361:  *     from each dz is serviced each scan until no dz requires
                    362:  *     service.  This is less efficient than servicing
                    363:  *     entirely a dz prior to scanning the next dz but it
                    364:  *     it is necessary.
                    365:  *
                    366:  *     dzxint is not actually invoked by a dz interrupt
                    367:  *     rather it is invoked by a clock interrupt.
                    368:  *     to drive multiple dz's efficiently utilizing dz
                    369:  *     transmitter interrupts is just NOT possible.
                    370:  */ 
                    371: int dzxc;
                    372: dzxint()        /* at SPLDZ */ 
                    373: {
                    374:        extern ttrstrt();
                    375:        register struct dz *dzp;
                    376:        int hspeed = LOWSPEED;  /* to determine clock speed */
                    377:        int flag;               /* control dz scanning */
                    378: 
                    379: dzxc++;        /* count */
                    380:        if( dzopenc == 0 ) return;      /* stop if inactive */
                    381: 
                    382:        /*      scan every dz for characters to transmit        */
                    383: 
                    384:    do
                    385:    {
                    386:        for(dzp = &dz[0], flag=0; dzp < &dz[NDZ]; dzp++ )
                    387:        {
                    388:                register struct tty *tp;
                    389:                register struct dzr_read *dza = dzp->dzaddr;
                    390:                int lino, t_bit;
                    391: 
                    392:                if((lino = dza->dzcsr.hibyte)  < 0) /* xmit ?? */ 
                    393:                {
                    394:                        lino =& 07;             /* isolate line number */ 
                    395:                        tp = dzp->ttys[lino];
                    396:                        t_bit = dzbitab[lino];  /* bit mask, not line number */
                    397:                        flag++;                 /* note service */
                    398:                        if( (dzp->closl & t_bit)
                    399:                        && ((--(dzp->closet[lino]) <= 0) || (tp->t_outq.c_cc == 0)) )
                    400:                        {
                    401:                                /* line closed, no time or chars left */
                    402:                                flushtty(tp);
                    403:                                tp->t_state = SSTART;
                    404:                                dzp->closl =& ~t_bit;
                    405:                                dzp->openl =& ~t_bit;
                    406:                                dzp->xmit  =& ~t_bit;
                    407:                                dza->dztcr =& ~t_bit;
                    408:                                dza->dzdtr =& ~t_bit;
                    409:                                if( (dzp->closl==0) && (dzp->openl==0) )
                    410:                                        dza->dzcsr = 0;
                    411:                                if( --dzopenc == 0 )
                    412:                                        return;
                    413:                        }
                    414:                        else if(tp->t_outq.c_cc == 0)
                    415:                        {
                    416:                                dzp->xmit =& ~t_bit;
                    417:                                dza->dztcr =& ~t_bit;
                    418:                        }
                    419:                        else if((dzp->nocarr&t_bit)||(dza->dzcarr&t_bit))
                    420:                        {
                    421:                                int c = getc(&tp->t_outq);
                    422:                                if( c <= 0177 || tp->t_flags == RAW )
                    423:                                {
                    424:                                        /* transmit the char for this line */ 
                    425:                                        dza->dztbuf = c;
                    426:                                        if( tp->t_speeds.lobyte > hspeed )
                    427:                                                hspeed = tp->t_speeds.lobyte;
                    428:                                }
                    429:                                else
                    430:                                {
                    431:                                        dzp->xmit =& ~t_bit;
                    432:                                        dza->dztcr =& ~t_bit;
                    433:                                        timeout( &ttrstrt, tp, c&0177 );
                    434:                                        tp->t_state =| TIMEOUT;
                    435:                                }
                    436:                                /* if low water mark then want more */ 
                    437:                                if( tp->t_state&ASLEEP
                    438:                                &&  tp->t_outq.c_cc <= TTLOWAT )
                    439:                                {
                    440:                                        tp->t_state =& ~ASLEEP;
                    441:                                        wakeup(&tp->t_outq);
                    442:                                }
                    443:                        }
                    444:                        else
                    445:                        {
                    446:                                dza->dztcr =& ~t_bit;
                    447:                        }
                    448:                }
                    449:        }
                    450:   } while( flag );
                    451: 
                    452:        /* finalize state of DZs prior to exitting */
                    453: 
                    454:        for(dzp = &dz[0]; dzp < &dz[NDZ]; dzp++ )
                    455:        {
                    456:                register struct dzr_read *dza = dzp->dzaddr;
                    457: 
                    458:                /* dtr to reflect state of carrier, for carrier lines */ 
                    459: 
                    460:                dza->dzdtr = (dza->dzcarr | dzp->nocarr) & dzp->openl;
                    461: 
                    462:                /* Enable all lines still with characters to send */
                    463: 
                    464:                dza->dztcr = dzp->xmit;
                    465:        }
                    466: 
                    467:        /*      setup for next interrupt        */
                    468: 
                    469:        CLOCK->counter = dzmicmap[hspeed];      /* count in 10microseconds */
                    470:        CLOCK->csr = GO;
                    471: 
                    472:        /*      call dzrint if needed   */
                    473: 
                    474:        if( dzrcvscan <= 0 )
                    475:                dzrint(0);
                    476:        dzrcvscan =- dzmicmap[hspeed];
                    477: }
                    478: 
                    479: /*
                    480:  *     DZ11 receiver interrupt
                    481:  *
                    482:  *     Scan each dz commencing with the particular device that caused this call
                    483:  *     Scan at least every dzmicmap[LOWSPEED] microseconds.
                    484:  */ 
                    485: dzrint(dev)
                    486: {
                    487:        register struct tty *tp;
                    488:        register struct dz *dzp;
                    489:        register int lino;
                    490:        int i, c;
                    491: 
                    492:        for(dzp = &dz[dev], i = 0; i < NDZ; i++)
                    493:        {
                    494:                while((c = dzp->dzaddr->dzrbuf) < 0)    /* char present in silo */ 
                    495:                {
                    496:                        lino =  c.hibyte; lino =& 07;
                    497:                        if( ((dzp->nocarr&dzbitab[lino]) == 0 )
                    498:                        &&  ((dzp->dzaddr->dzcarr&dzbitab[lino]) == 0 )) continue;
                    499:                        if( (dzp->openl&dzbitab[lino]) == 0 ) continue;
                    500:                        tp = dzp->ttys[lino];
                    501:                        if(c&RERROR)
                    502:                        {
                    503:                                if( (c & FRAME) && (tp->t_flags & RAW ) )
                    504:                                        ttyinput(0, tp); /* break for getty */
                    505:                                else if(c & OVR_RUN)
                    506:                                        dzp->overrors++;
                    507:                                else if(c & PARITY)
                    508:                                        dzp->pyerrors++;
                    509:                        }
                    510:                        else
                    511:                        {
                    512:                                ttyinput(c, tp);
                    513:                        }
                    514:                }
                    515:                if( ++dzp >= &dz[NDZ] ) dzp = &dz[0];
                    516:        }
                    517:        dzrcvscan = dzmicmap[LOWSPEED];
                    518: }

unix.superglobalmegacorp.com

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