Annotation of lucent/sys/src/9/port/devlance.c, revision 1.1.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.