Annotation of lucent/sys/src/9/port/devlance.c, revision 1.1

1.1     ! root        1: #include       "u.h"
        !             2: #include       "../port/lib.h"
        !             3: #include       "mem.h"
        !             4: #include       "dat.h"
        !             5: #include       "fns.h"
        !             6: #include       "io.h"
        !             7: #include       "../port/error.h"
        !             8: #include       "devtab.h"
        !             9: 
        !            10: enum {
        !            11:        Ntypes=         9,              /* max number of ethernet packet types */
        !            12:        Maxrb=          128,            /* max buffers in a ring */
        !            13: };
        !            14: #define RSUCC(x) (((x)+1)%l.nrrb)
        !            15: #define TSUCC(x) (((x)+1)%l.ntrb)
        !            16: 
        !            17: /*
        !            18:  *  Communication with the lance is via a transmit and receive ring of
        !            19:  *  message descriptors.  The Initblock contains pointers to and sizes of
        !            20:  *  these rings.  The rings must be in RAM addressible by the lance
        !            21:  */
        !            22: typedef struct {
        !            23:        ushort  laddr;          /* low order piece of address */
        !            24:        ushort  flags;          /* flags and high order piece of address */
        !            25:        short   size;           /* size of buffer */
        !            26:        ushort  cntflags;       /* (rcv)count of bytes in buffer; (xmt) more flags */
        !            27: } Msg;
        !            28: 
        !            29: /*
        !            30:  *  lance memory map
        !            31:  */
        !            32: struct Lancemem
        !            33: {
        !            34:        /*
        !            35:         *  initialization block
        !            36:         */
        !            37:        ushort  mode;           /* chip control (see below) */
        !            38:        ushort  etheraddr[3];   /* the ethernet physical address */
        !            39:        ushort  multi[4];       /* multicast addresses, 1 bit for each of 64 */
        !            40:        ushort  rdralow;        /* receive buffer ring */
        !            41:        ushort  rdrahigh;       /* (top three bits define size of ring) */
        !            42:        ushort  tdralow;        /* transmit buffer ring */
        !            43:        ushort  tdrahigh;       /* (top three bits define size of ring) */
        !            44:        
        !            45:        /*
        !            46:         *  ring buffers
        !            47:         *  first receive, then transmit
        !            48:         */
        !            49:        Msg     rmr[Maxrb];             /* recieve message ring */
        !            50:        Msg     tmr[Maxrb];             /* transmit message ring */
        !            51: };
        !            52: 
        !            53: /*
        !            54:  *  Some macros for dealing with lance memory addresses.  The lance splits
        !            55:  *  its 24 bit addresses across two 16 bit registers.
        !            56:  */
        !            57: #define HADDR(a) ((((ulong)(a))>>16)&0xFF)
        !            58: #define LADDR(a) (((ulong)a)&0xFFFF)
        !            59: 
        !            60: /*
        !            61:  *  The following functions exist to sidestep a quirk in the SGI IO3 lance
        !            62:  *  interface.  In all other processors, the lance's initialization block and
        !            63:  *  descriptor rings look like normal memory.  In the SGI IO3, the CPU sees a
        !            64:  *  6 byte pad twixt all lance memory shorts.  Therefore, we use the following
        !            65:  *  macros to compute the address whenever accessing the lance memory to make
        !            66:  *  the code portable.  Sic transit gloria.
        !            67:  */
        !            68: #define LANCEMEM ((Lancemem*)0)
        !            69: #define MPs(a) (*(short *)(l.lanceram + l.sep*((ushort*)&a - (ushort*)0)))
        !            70: #define MPus(a) (*(ushort *)(l.lanceram + l.sep*((ushort*)&a - (ushort*)0)))
        !            71: 
        !            72: /*
        !            73:  *  one per ethernet packet type
        !            74:  */
        !            75: typedef struct Ethertype       Ethertype;
        !            76: struct Ethertype
        !            77: {
        !            78:        QLock;
        !            79:        Netprot;                        /* stat info */
        !            80:        int             type;           /* ethernet type */
        !            81:        int             prom;           /* promiscuous mode */
        !            82:        Queue           *q;
        !            83:        int             inuse;
        !            84:        Rendez          rc;             /* rendzvous for close */
        !            85:        Ethertype       *closeline;     /* close list */
        !            86: };
        !            87: 
        !            88: 
        !            89: /*
        !            90:  *  lance state
        !            91:  */
        !            92: typedef struct {
        !            93:        QLock;
        !            94: 
        !            95:        Lance;                  /* host dependent lance params */
        !            96:        int     prom;           /* number of promiscuous channels */
        !            97:        int     all;            /* number of channels listening to all packets */
        !            98:        int     wedged;         /* the lance is wedged */
        !            99:        Network net;
        !           100: 
        !           101:        int     inited;
        !           102:        uchar   *lmp;           /* location of parity test */
        !           103: 
        !           104:        Rendez  rr;             /* rendezvous for an input buffer */
        !           105:        QLock   rlock;          /* semaphore on tc */
        !           106:        ushort  rl;             /* first rcv Message belonging to Lance */      
        !           107: 
        !           108:        Rendez  tr;             /* rendezvous for an output buffer */
        !           109:        QLock   tlock;          /* semaphore on tc */
        !           110:        ushort  tc;             /* next xmt Message CPU will try for */ 
        !           111: 
        !           112:        Ethertype *closeline;   /* channels waiting to close */
        !           113:        Lock    closepin;       /* lock for closeline */
        !           114:        Ethertype e[Ntypes];
        !           115:        int     debug;
        !           116:        int     kstarted;
        !           117:        uchar   bcast[6];
        !           118: 
        !           119:        Queue   self;   /* packets turned around at the interface */
        !           120: 
        !           121:        /* sadistics */
        !           122: 
        !           123:        int     misses;
        !           124:        int     inpackets;
        !           125:        int     outpackets;
        !           126:        int     crcs;           /* input crc errors */
        !           127:        int     oerrs;          /* output erros */
        !           128:        int     frames;         /* framing errors */
        !           129:        int     overflows;      /* packet overflows */
        !           130:        int     buffs;          /* buffering errors */
        !           131: } SoftLance;
        !           132: static SoftLance l;
        !           133: 
        !           134: /*
        !           135:  *  mode bits in the lance initialization block
        !           136:  */
        !           137: #define PROM   0x8000
        !           138: #define INTL   0x40
        !           139: #define DRTY   0x20
        !           140: #define COLL   0x10
        !           141: #define DTCR   0x8
        !           142: #define LOOP   0x4
        !           143: #define DTX    0x2
        !           144: #define DRX    0x1
        !           145: 
        !           146: /*
        !           147:  *  LANCE CSR0, this is the register we play with most often.  We leave
        !           148:  *  this register pointed to by l.rap in normal operation.
        !           149:  */
        !           150: #define ERR0   0x8000
        !           151: #define BABL   0x4000
        !           152: #define CERR   0x2000
        !           153: #define MISS   0x1000
        !           154: #define MERR   0x800
        !           155: #define RINT   0x400
        !           156: #define TINT   0x200
        !           157: #define IDON   0x100
        !           158: #define INTR   0x80
        !           159: #define INEA   0x40
        !           160: #define RXON   0x20
        !           161: #define TXON   0x10
        !           162: #define TDMD   0x8
        !           163: #define STOP   0x4
        !           164: #define STRT   0x2
        !           165: #define INIT   0x1
        !           166: 
        !           167: /*
        !           168:  *  flag bits from a buffer descriptor in the rcv/xmt rings
        !           169:  */
        !           170: #define LANCEOWNER     0x8000  /* 1 means that the buffer can be used by the chip */
        !           171: #define ERR    0x4000  /* error summary, the OR of all error bits */
        !           172: #define FRAM   0x2000  /* CRC error and incoming packet not a multiple of 8 bits */
        !           173: #define OFLO   0x1000  /* (receive) lost some of the packet */
        !           174: #define MORE   0x1000  /* (transmit) more than 1 retry to send the packet */
        !           175: #define CRC    0x800   /* (receive) crc error reading packet */
        !           176: #define ONE    0x800   /* (transmit) one retry to transmit the packet */
        !           177: #define BUF    0x400   /* (receive) out of buffers while reading a packet */
        !           178: #define DEF    0x400   /* (transmit) deffered while transmitting packet */
        !           179: #define STP    0x200   /* start of packet */
        !           180: #define ENP    0x100   /* end of packet */
        !           181: 
        !           182: /*
        !           183:  *  cntflags bits from a buffer descriptor in the rcv/xmt rings
        !           184:  */
        !           185: #define BUFF   0x8000  /* buffer error (host screwed up?) */
        !           186: #define UFLO   0x4000  /* underflow from memory */
        !           187: #define LCOL   0x1000  /* late collision (ether too long?) */
        !           188: #define LCAR   0x800   /* loss of carrier (ether broken?) */
        !           189: #define RTRY   0x400   /* couldn't transmit (bad station on ether?) */
        !           190: #define TTDR   0x3FF   /* time domain reflectometer */
        !           191: 
        !           192: /*
        !           193:  *  predeclared
        !           194:  */
        !           195: static void    lancekproc(void *);
        !           196: static void    lancestart(int);
        !           197: static void    lanceup(Etherpkt*, int);
        !           198: static int     lanceclonecon(Chan*);
        !           199: static void    lancestatsfill(Chan*, char*, int);
        !           200: static void    lancetypefill(Chan*, char*, int);
        !           201: 
        !           202: /*
        !           203:  *  lance stream module definition
        !           204:  */
        !           205: static void lanceoput(Queue*, Block*);
        !           206: static void lancestopen(Queue*, Stream*);
        !           207: static void lancestclose(Queue*);
        !           208: static void stagerbuf(void);
        !           209: Qinfo lanceinfo = { nullput, lanceoput, lancestopen, lancestclose, "lance" };
        !           210: 
        !           211: /*
        !           212:  *  open a lance line discipline
        !           213:  */
        !           214: void
        !           215: lancestopen(Queue *q, Stream *s)
        !           216: {
        !           217:        Ethertype *et;
        !           218: 
        !           219:        et = &l.e[s->id];
        !           220:        RD(q)->ptr = WR(q)->ptr = et;
        !           221:        et->type = 0;
        !           222:        et->q = RD(q);
        !           223:        et->inuse = 1;
        !           224: }
        !           225: 
        !           226: /*
        !           227:  *  close lance line discipline
        !           228:  *
        !           229:  *  the lock is to synchronize changing the ethertype with
        !           230:  *  sending packets up the stream on interrupts.
        !           231:  */
        !           232: static int
        !           233: isclosed(void *x)
        !           234: {
        !           235:        return ((Ethertype *)x)->q == 0;
        !           236: }
        !           237: 
        !           238: static void
        !           239: lancestclose(Queue *q)
        !           240: {
        !           241:        Ethertype *et;
        !           242: 
        !           243:        et = (Ethertype *)(q->ptr);
        !           244:        if(et->prom){
        !           245:                qlock(&l);
        !           246:                l.prom--;
        !           247:                if(l.prom == 0)
        !           248:                        lancestart(0);
        !           249:                qunlock(&l);
        !           250:        }
        !           251:        if(et->type == -1){
        !           252:                qlock(&l);
        !           253:                l.all--;
        !           254:                qunlock(&l);
        !           255:        }
        !           256: 
        !           257:        /*
        !           258:         *  mark as closing and wait for kproc to close us
        !           259:         */
        !           260:        lock(&l.closepin);
        !           261:        et->closeline = l.closeline;
        !           262:        l.closeline = et;
        !           263:        unlock(&l.closepin);
        !           264:        wakeup(&l.rr);
        !           265:        sleep(&et->rc, isclosed, et);
        !           266:        
        !           267:        et->type = 0;
        !           268:        et->q = 0;
        !           269:        et->prom = 0;
        !           270:        et->inuse = 0;
        !           271:        netdisown(et);
        !           272: }
        !           273: 
        !           274: /*
        !           275:  *  the ``connect'' control message specifyies the type
        !           276:  */
        !           277: Proc *lanceout;
        !           278: static int
        !           279: isobuf(void *x)
        !           280: {
        !           281:        Msg *m;
        !           282: 
        !           283:        m = x;
        !           284:        return l.wedged || (MPus(m->flags)&LANCEOWNER) == 0;
        !           285: }
        !           286: 
        !           287: static void
        !           288: lanceoput(Queue *q, Block *bp)
        !           289: {
        !           290:        int n, len;
        !           291:        Etherpkt *p;
        !           292:        Ethertype *e;
        !           293:        Msg *m;
        !           294:        Block *nbp;
        !           295: 
        !           296:        if(bp->type == M_CTL){
        !           297:                e = q->ptr;
        !           298:                qlock(&l);
        !           299:                if(streamparse("connect", bp)){
        !           300:                        if(e->type == -1)
        !           301:                                l.all--;
        !           302:                        e->type = strtol((char *)bp->rptr, 0, 0);
        !           303:                        if(e->type == -1)
        !           304:                                l.all++;
        !           305:                } else if(streamparse("promiscuous", bp)) {
        !           306:                        e->prom = 1;
        !           307:                        l.prom++;
        !           308:                        if(l.prom == 1)
        !           309:                                lancestart(PROM);/**/
        !           310:                }
        !           311:                qunlock(&l);
        !           312:                freeb(bp);
        !           313:                return;
        !           314:        }
        !           315: 
        !           316:        /*
        !           317:         *  give packet a local address, return upstream if destined for
        !           318:         *  this machine.
        !           319:         */
        !           320:        if(BLEN(bp) < ETHERHDRSIZE){
        !           321:                bp = pullup(bp, ETHERHDRSIZE);
        !           322:                if(bp == 0)
        !           323:                        return;
        !           324:        }
        !           325:        p = (Etherpkt *)bp->rptr;
        !           326:        memmove(p->s, l.ea, sizeof(l.ea));
        !           327:        if(*p->d == 0xff || l.prom || l.all){
        !           328:                len = blen(bp);
        !           329:                nbp = copyb(bp, len);
        !           330:                nbp = expandb(nbp, len >= ETHERMINTU ? len : ETHERMINTU);
        !           331:                if(nbp){
        !           332:                        nbp->wptr = nbp->rptr+len;
        !           333:                        putq(&l.self, nbp);
        !           334:                        wakeup(&l.rr);
        !           335:                }
        !           336:        } else if(*p->d == *l.ea && memcmp(l.ea, p->d, sizeof(l.ea)) == 0){
        !           337:                len = blen(bp);
        !           338:                bp = expandb(bp, len >= ETHERMINTU ? len : ETHERMINTU);
        !           339:                if(bp){
        !           340:                        putq(&l.self, bp);
        !           341:                        wakeup(&l.rr);
        !           342:                }
        !           343:                return;
        !           344:        }
        !           345: 
        !           346:        if(l.wedged) {
        !           347:                freeb(bp);
        !           348:                return;
        !           349:        }
        !           350: 
        !           351:        /*
        !           352:         *  only one transmitter at a time
        !           353:         */
        !           354:        qlock(&l.tlock);
        !           355: 
        !           356:        if(l.wedged) {
        !           357:                qunlock(&l.tlock);
        !           358:                freeb(bp);
        !           359:                return;
        !           360:        }
        !           361: 
        !           362:        if(waserror()){
        !           363:                qunlock(&l.tlock);
        !           364:                freeb(bp);
        !           365:                nexterror();
        !           366:        }
        !           367: 
        !           368:        /*
        !           369:         *  Wait till we get an output buffer, complain if input
        !           370:         *  or output seems wedged.
        !           371:         */
        !           372:        m = &(LANCEMEM->tmr[l.tc]);
        !           373:        p = &l.tp[l.tc];
        !           374:        while((MPus(m->flags)&LANCEOWNER) != 0) {
        !           375:                tsleep(&l.tr, isobuf, m, 128);
        !           376:                if(l.wedged || isobuf(m) == 0){
        !           377:                        qunlock(&l.tlock);
        !           378:                        freeb(bp);
        !           379:                        poperror();
        !           380:                        print("lance wedged, dumping block & restarting\n");
        !           381:                        lancestart(0);
        !           382:                        l.wedged = 0;
        !           383:                        return;
        !           384:                }
        !           385:        }
        !           386: 
        !           387:        /*
        !           388:         *  copy message into lance RAM
        !           389:         */
        !           390:        len = 0;
        !           391:        for(nbp = bp; nbp; nbp = nbp->next){
        !           392:                if(sizeof(Etherpkt) - len >= (n = BLEN(nbp))){
        !           393:                        memmove(((uchar *)p)+len, nbp->rptr, n);
        !           394:                        len += n;
        !           395:                } else
        !           396:                        print("no room damn it\n");
        !           397:                if(bp->flags & S_DELIM)
        !           398:                        break;
        !           399:        }
        !           400: 
        !           401:        /*
        !           402:         *  pad the packet (zero the pad)
        !           403:         */
        !           404:        if(len < ETHERMINTU){
        !           405:                memset(((char*)p)+len, 0, ETHERMINTU-len);
        !           406:                len = ETHERMINTU;
        !           407:        }
        !           408: 
        !           409:        /*
        !           410:         *  set up the ring descriptor and hand to lance
        !           411:         */
        !           412:        l.outpackets++;
        !           413:        MPs(m->size) = -len;
        !           414:        MPus(m->cntflags) = 0;
        !           415:        MPus(m->laddr) = LADDR(&l.ltp[l.tc]);
        !           416:        MPus(m->flags) = LANCEOWNER|STP|ENP|HADDR(&l.ltp[l.tc]);
        !           417:        l.tc = TSUCC(l.tc);
        !           418:        *l.rdp = INEA|TDMD; /**/
        !           419:        wbflush();
        !           420:        qunlock(&l.tlock);
        !           421:        freeb(bp);
        !           422:        poperror();
        !           423: }
        !           424: 
        !           425: /*
        !           426:  *  stop the lance and allocate buffers
        !           427:  */
        !           428: void
        !           429: lancereset(void)
        !           430: {
        !           431:        static int already;
        !           432:        int i;
        !           433: 
        !           434:        if(already == 0){
        !           435:                already = 1;
        !           436:                lancesetup(&l);
        !           437: 
        !           438:                l.net.name = "ether";
        !           439:                l.net.nconv = Ntypes;
        !           440:                l.net.devp = &lanceinfo;
        !           441:                l.net.protop = 0;
        !           442:                l.net.listen = 0;
        !           443:                l.net.clone = lanceclonecon;
        !           444:                l.net.ninfo = 2;
        !           445:                l.net.info[0].name = "stats";
        !           446:                l.net.info[0].fill = lancestatsfill;
        !           447:                l.net.info[1].name = "type";
        !           448:                l.net.info[1].fill = lancetypefill;
        !           449:                for(i = 0; i < Ntypes; i++)
        !           450:                        netadd(&l.net, &l.e[i], i);
        !           451: 
        !           452:                memset(l.bcast, 0xff, sizeof l.bcast);
        !           453:        }
        !           454: 
        !           455:        /*
        !           456:         *  stop the lance
        !           457:         */
        !           458:        *l.rap = 0;
        !           459:        *l.rdp = STOP;
        !           460:        l.wedged = 1;
        !           461: }
        !           462: 
        !           463: /*
        !           464:  *  Initialize and start the lance.  This routine can be called only from a process.
        !           465:  *  It may be used to restart a dead lance.
        !           466:  */
        !           467: static void
        !           468: lancestart(int mode)
        !           469: {
        !           470:        int i;
        !           471:        Lancemem *lm = LANCEMEM;
        !           472:        Msg *m;
        !           473: 
        !           474:        /*
        !           475:         *   wait till both receiver and transmitter are
        !           476:         *   quiescent
        !           477:         */
        !           478:        qlock(&l.tlock);
        !           479:        qlock(&l.rlock);
        !           480: 
        !           481:        lancereset();
        !           482:        l.rl = 0;
        !           483:        l.tc = 0;
        !           484: 
        !           485:        /*
        !           486:         *  create the initialization block
        !           487:         */
        !           488:        MPus(lm->mode) = mode;
        !           489: 
        !           490:        /*
        !           491:         *  set ether addr from the value in the id prom.
        !           492:         *  the id prom has them in reverse order, the init
        !           493:         *  structure wants them in byte swapped order
        !           494:         */
        !           495:        MPus(lm->etheraddr[0]) = (l.ea[1]<<8) | l.ea[0];
        !           496:        MPus(lm->etheraddr[1]) = (l.ea[3]<<8) | l.ea[2];
        !           497:        MPus(lm->etheraddr[2]) = (l.ea[5]<<8) | l.ea[4];
        !           498: 
        !           499:        /*
        !           500:         *  ignore multicast addresses
        !           501:         */
        !           502:        MPus(lm->multi[0]) = 0;
        !           503:        MPus(lm->multi[1]) = 0;
        !           504:        MPus(lm->multi[2]) = 0;
        !           505:        MPus(lm->multi[3]) = 0;
        !           506: 
        !           507:        /*
        !           508:         *  set up rcv message ring
        !           509:         */
        !           510:        m = lm->rmr;
        !           511:        for(i = 0; i < l.nrrb; i++, m++){
        !           512:                MPs(m->size) = -sizeof(Etherpkt);
        !           513:                MPus(m->cntflags) = 0;
        !           514:                MPus(m->laddr) = LADDR(&l.lrp[i]);
        !           515:                MPus(m->flags) = HADDR(&l.lrp[i]);
        !           516:        }
        !           517:        MPus(lm->rdralow) = LADDR(l.lm->rmr);
        !           518:        MPus(lm->rdrahigh) = (l.lognrrb<<13)|HADDR(l.lm->rmr);
        !           519: 
        !           520: 
        !           521:        /*
        !           522:         *  give the lance all the rcv buffers except one (as a sentinel)
        !           523:         */
        !           524:        m = lm->rmr;
        !           525:        for(i = 0; i < l.nrrb; i++, m++)
        !           526:                MPus(m->flags) |= LANCEOWNER;
        !           527: 
        !           528:        /*
        !           529:         *  set up xmit message ring
        !           530:         */
        !           531:        m = lm->tmr;
        !           532:        for(i = 0; i < l.ntrb; i++, m++){
        !           533:                MPs(m->size) = 0;
        !           534:                MPus(m->cntflags) = 0;
        !           535:                MPus(m->laddr) = LADDR(&l.ltp[i]);
        !           536:                MPus(m->flags) = HADDR(&l.ltp[i]);
        !           537:        }
        !           538:        MPus(lm->tdralow) = LADDR(l.lm->tmr);
        !           539:        MPus(lm->tdrahigh) = (l.logntrb<<13)|HADDR(l.lm->tmr);
        !           540: 
        !           541:        /*
        !           542:         *  point lance to the initialization block
        !           543:         */
        !           544:        *l.rap = 1;
        !           545:        *l.rdp = LADDR(l.lm);
        !           546:        wbflush();
        !           547:        *l.rap = 2;
        !           548:        *l.rdp = HADDR(l.lm);
        !           549: 
        !           550:        /*
        !           551:         *  The lance byte swaps the ethernet packet unless we tell it not to
        !           552:         */
        !           553:        wbflush();
        !           554:        *l.rap = 3;
        !           555:        *l.rdp = l.busctl;
        !           556: 
        !           557:        /*
        !           558:         *  initialize lance, turn on interrupts, turn on transmit and rcv.
        !           559:         */
        !           560:        wbflush();
        !           561:        *l.rap = 0;
        !           562:        *l.rdp = INEA|INIT|STRT; /**/
        !           563: 
        !           564:        /*
        !           565:         *  spin for up to a second waiting for the IDON interrupt
        !           566:         */
        !           567:        for(i = 0; i < 1000; i++){
        !           568:                if(l.wedged == 0)
        !           569:                        break;
        !           570:                delay(1);
        !           571:        }
        !           572: 
        !           573:        /*
        !           574:         *  let in everything else
        !           575:         */
        !           576:        qunlock(&l.rlock);
        !           577:        qunlock(&l.tlock);
        !           578: }
        !           579: 
        !           580: void
        !           581: lanceinit(void)
        !           582: {
        !           583: }
        !           584: 
        !           585: Chan*
        !           586: lanceattach(char *spec)
        !           587: {
        !           588:        if(l.kstarted == 0){
        !           589:                kproc("lancekproc", lancekproc, 0);
        !           590:                l.kstarted = 1;
        !           591:                lancestart(0);
        !           592:                print("lance ether: %.2x%.2x%.2x%.2x%.2x%.2x\n",
        !           593:                        l.ea[0], l.ea[1], l.ea[2], l.ea[3], l.ea[4], l.ea[5]);
        !           594:        }
        !           595:        return devattach('l', spec);
        !           596: }
        !           597: 
        !           598: Chan*
        !           599: lanceclone(Chan *c, Chan *nc)
        !           600: {
        !           601:        return devclone(c, nc);
        !           602: }
        !           603: 
        !           604: int     
        !           605: lancewalk(Chan *c, char *name)
        !           606: {
        !           607:        return netwalk(c, name, &l.net);
        !           608: }
        !           609: 
        !           610: void    
        !           611: lancestat(Chan *c, char *dp)
        !           612: {
        !           613:        netstat(c, dp, &l.net);
        !           614: }
        !           615: 
        !           616: /*
        !           617:  *  Pass open's of anything except the directory to streamopen
        !           618:  */
        !           619: Chan*
        !           620: lanceopen(Chan *c, int omode)
        !           621: {
        !           622:        return netopen(c, omode, &l.net);
        !           623: }
        !           624: 
        !           625: void    
        !           626: lancecreate(Chan *c, char *name, int omode, ulong perm)
        !           627: {
        !           628:        USED(c, name, omode, perm);
        !           629:        error(Eperm);
        !           630: }
        !           631: 
        !           632: void    
        !           633: lanceclose(Chan *c)
        !           634: {
        !           635:        if(c->stream)
        !           636:                streamclose(c);
        !           637: }
        !           638: 
        !           639: long    
        !           640: lanceread(Chan *c, void *a, long n, ulong offset)
        !           641: {
        !           642:        return netread(c, a, n, offset,  &l.net);
        !           643: }
        !           644: 
        !           645: long    
        !           646: lancewrite(Chan *c, void *a, long n, ulong offset)
        !           647: {
        !           648:        USED(offset);
        !           649:        return streamwrite(c, a, n, 0);
        !           650: }
        !           651: 
        !           652: void    
        !           653: lanceremove(Chan *c)
        !           654: {
        !           655:        USED(c);
        !           656:        error(Eperm);
        !           657: }
        !           658: 
        !           659: void    
        !           660: lancewstat(Chan *c, char *dp)
        !           661: {
        !           662:        netwstat(c, dp, &l.net);
        !           663: }
        !           664: 
        !           665: /*
        !           666:  *  user level network interface routines
        !           667:  */
        !           668: static void
        !           669: lancestatsfill(Chan *c, char* p, int n)
        !           670: {
        !           671:        char buf[512];
        !           672: 
        !           673:        USED(c);
        !           674:        sprint(buf, "in: %d\nout: %d\ncrc errs: %d\noverflows: %d\nframe errs: %d\nbuff errs: %d\noerrs: %d\naddr: %.02x:%.02x:%.02x:%.02x:%.02x:%.02x\n",
        !           675:                l.inpackets, l.outpackets, l.crcs,
        !           676:                l.overflows, l.frames, l.buffs, l.oerrs,
        !           677:                l.ea[0], l.ea[1], l.ea[2], l.ea[3], l.ea[4], l.ea[5]);
        !           678:        strncpy(p, buf, n);
        !           679: }
        !           680: 
        !           681: static void
        !           682: lancetypefill(Chan *c, char* p, int n)
        !           683: {
        !           684:        char buf[16];
        !           685:        Ethertype *e;
        !           686: 
        !           687:        e = &l.e[STREAMID(c->qid.path)];
        !           688:        sprint(buf, "%d", e->type);
        !           689:        strncpy(p, buf, n);
        !           690: }
        !           691: 
        !           692: static int
        !           693: lanceclonecon(Chan *c)
        !           694: {
        !           695:        Ethertype *e;
        !           696: 
        !           697:        USED(c);
        !           698:        for(e = l.e; e < &l.e[Ntypes]; e++){
        !           699:                qlock(e);
        !           700:                if(e->inuse || e->q){
        !           701:                        qunlock(e);
        !           702:                        continue;
        !           703:                }
        !           704:                e->inuse = 1;
        !           705:                netown(e, u->p->user, 0);
        !           706:                qunlock(e);
        !           707:                return e - l.e;
        !           708:        }
        !           709:        error(Enodev);
        !           710:        return -1;              /* never reached */
        !           711: }
        !           712: 
        !           713: /*
        !           714:  *  We will:
        !           715:  *     (1) Clear interrupt cause in the lance
        !           716:  *     (2) service all current events
        !           717:  */
        !           718: void
        !           719: lanceintr(void)
        !           720: {
        !           721:        ushort csr;
        !           722: 
        !           723:        csr = *l.rdp;
        !           724: 
        !           725:        /*
        !           726:         *  turn off the interrupt and any error indicators
        !           727:         */
        !           728:        *l.rdp = IDON|INEA|TINT|RINT|BABL|CERR|MISS|MERR;
        !           729: 
        !           730:        /*
        !           731:         *  see if an error occurred
        !           732:         */
        !           733:        if(csr & (BABL|MISS|MERR)){
        !           734:                if(l.misses++ < 4) {
        !           735:                        print("lance err #%ux\n", csr);
        !           736:                } else {
        !           737:                        print("lance stopped\n");
        !           738:                        l.wedged = 1;
        !           739:                        l.misses = 0;
        !           740:                        lancereset();
        !           741:                        wakeup(&l.rr);
        !           742:                        wakeup(&l.tr);
        !           743:                        return;
        !           744:                }
        !           745:        }
        !           746: 
        !           747:        /*
        !           748:         *  initialization done
        !           749:         */
        !           750:        if(csr & IDON)
        !           751:                l.wedged = 0;
        !           752: 
        !           753:        /*
        !           754:         *  the lance turns off if it gets strange output errors
        !           755:         */
        !           756:        if((csr & (TXON|RXON)) != (TXON|RXON))
        !           757:                l.wedged = 1;
        !           758: 
        !           759:        /*
        !           760:         *  wakeup the input process
        !           761:         */
        !           762:        if(csr & RINT)
        !           763:                wakeup(&l.rr);
        !           764: 
        !           765:        /*
        !           766:         *  wake any process waiting for a transmit buffer
        !           767:         */
        !           768:        if(csr & TINT)
        !           769:                wakeup(&l.tr);
        !           770: }
        !           771: 
        !           772: /*
        !           773:  *  send a packet upstream
        !           774:  */
        !           775: static void
        !           776: lanceup(Etherpkt *p, int len)
        !           777: {
        !           778:        int t;
        !           779:        Block *bp;
        !           780:        Ethertype *e;
        !           781: 
        !           782:        if(len <= 0)
        !           783:                return;
        !           784: 
        !           785:        t = (p->type[0]<<8) | p->type[1];
        !           786:        for(e = &l.e[0]; e < &l.e[Ntypes]; e++){
        !           787:                /*
        !           788:                 *  check for open, the right type, and flow control
        !           789:                 */
        !           790:                if(e->q==0 || (t!=e->type && e->type!=-1) || e->q->next->len>Streamhi)
        !           791:                        continue;
        !           792: 
        !           793:                /*
        !           794:                 *  only a trace channel gets packets destined for other machines
        !           795:                 */
        !           796:                if(e->type!=-1 && p->d[0]!=0xff
        !           797:                && (*p->d != *l.ea || memcmp(p->d, l.ea, sizeof(p->d))!=0))
        !           798:                        continue;
        !           799: 
        !           800:                if(!waserror()){
        !           801:                        bp = allocb(len);
        !           802:                        memmove(bp->rptr, (uchar *)p, len);
        !           803:                        bp->wptr += len;
        !           804:                        bp->flags |= S_DELIM;
        !           805:                        PUTNEXT(e->q, bp);
        !           806:                        poperror();
        !           807:                }
        !           808:        }
        !           809: }
        !           810: 
        !           811: /*
        !           812:  *  input process, awakened on each interrupt with rcv buffers filled
        !           813:  */
        !           814: static int
        !           815: isinput(void *arg)
        !           816: {
        !           817:        Msg *m = arg;
        !           818: 
        !           819:        return ((MPus(m->flags) & LANCEOWNER)==0) || l.wedged || l.self.first
        !           820:                || l.closeline;
        !           821: }
        !           822: 
        !           823: static void
        !           824: lancekproc(void *arg)
        !           825: {
        !           826:        Etherpkt *p;
        !           827:        Ethertype *e;
        !           828:        int len;
        !           829:        int t;
        !           830:        Lancemem *lm = LANCEMEM;
        !           831:        Msg *m;
        !           832:        Block *bp;
        !           833: 
        !           834:        USED(arg);
        !           835: 
        !           836:        while(waserror())
        !           837:                print("lancekproc err %s\n", u->error);
        !           838: 
        !           839:        for(;;){
        !           840:                qlock(&l.rlock);
        !           841:                while(bp = getq(&l.self)){
        !           842:                        lanceup((Etherpkt*)bp->rptr, BLEN(bp));
        !           843:                        freeb(bp);
        !           844:                }
        !           845:                m = &(lm->rmr[l.rl]);
        !           846:                while((MPus(m->flags) & LANCEOWNER)==0){
        !           847:                        l.inpackets++;
        !           848:                        t = MPus(m->flags);
        !           849:                        if(t & ERR){
        !           850:                                if(t & FRAM)
        !           851:                                        l.frames++;
        !           852:                                if(t & OFLO)
        !           853:                                        l.overflows++;
        !           854:                                if(t & CRC)
        !           855:                                        l.crcs++;
        !           856:                                if(t & BUFF)
        !           857:                                        l.buffs++;
        !           858:                        } else {
        !           859:                                /*
        !           860:                                 *  stuff packet up each queue that wants it
        !           861:                                 */
        !           862:                                p = &l.rp[l.rl];
        !           863:                                len = MPus(m->cntflags) - 4;
        !           864:                                lanceup(p, len);
        !           865:                        }
        !           866: 
        !           867:                        /*
        !           868:                         *  stage the next input buffer
        !           869:                         */
        !           870:                        MPs(m->size) = -sizeof(Etherpkt);
        !           871:                        MPus(m->cntflags) = 0;
        !           872:                        MPus(m->laddr) = LADDR(&l.lrp[l.rl]);
        !           873:                        MPus(m->flags) = LANCEOWNER|HADDR(&l.lrp[l.rl]);
        !           874:                        wbflush();
        !           875:                        l.rl = RSUCC(l.rl);
        !           876:                        m = &(lm->rmr[l.rl]);
        !           877:                }
        !           878:                qunlock(&l.rlock);
        !           879:                sleep(&l.rr, isinput, m);
        !           880: 
        !           881:                /*
        !           882:                 *  if the lance is wedged, restart it
        !           883:                 */
        !           884:                if(l.wedged){
        !           885:                        print("lance wedged, restarting\n");
        !           886:                        lancestart(0);
        !           887:                }
        !           888: 
        !           889:                /*
        !           890:                 *  close ethertypes requesting it
        !           891:                 */
        !           892:                if(l.closeline){
        !           893:                        lock(&l.closepin);
        !           894:                        for(e = l.closeline; e; e = e->closeline){
        !           895:                                e->q = 0;
        !           896:                                wakeup(&e->rc);
        !           897:                        }
        !           898:                        l.closeline = 0;
        !           899:                        unlock(&l.closepin);
        !           900:                }
        !           901:        }
        !           902: }

unix.superglobalmegacorp.com

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