Annotation of 40BSD/cmd/berknet/dz1.c, revision 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.