Annotation of lucent/sys/src/9/pc/devether.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 "../port/error.h"
                      7: #include "io.h"
                      8: #include "devtab.h"
                      9: 
                     10: #include "ether.h"
                     11: 
                     12: /*
                     13:  * Half-arsed attempt at a general top-level
                     14:  * ethernet driver. Needs work:
                     15:  *     handle multiple controllers
                     16:  *     much tidying
                     17:  *     set ethernet address
                     18:  *     need a ctl file passed down to card drivers
                     19:  *       so we can set options.
                     20:  */
                     21: 
                     22: struct Ctlr *softctlr;
                     23: 
                     24: Chan*
                     25: etherclone(Chan *c, Chan *nc)
                     26: {
                     27:        return devclone(c, nc);
                     28: }
                     29: 
                     30: int
                     31: etherwalk(Chan *c, char *name)
                     32: {
                     33:        return netwalk(c, name, &softctlr->net);
                     34: }
                     35: 
                     36: void
                     37: etherstat(Chan *c, char *dp)
                     38: {
                     39:        netstat(c, dp, &softctlr->net);
                     40: }
                     41: 
                     42: Chan*
                     43: etheropen(Chan *c, int omode)
                     44: {
                     45:        return netopen(c, omode, &softctlr->net);
                     46: }
                     47: 
                     48: void
                     49: ethercreate(Chan *c, char *name, int omode, ulong perm)
                     50: {
                     51:        USED(c, name, omode, perm);
                     52:        error(Eperm);
                     53: }
                     54: 
                     55: void
                     56: etherclose(Chan *c)
                     57: {
                     58:        if(c->stream)
                     59:                streamclose(c);
                     60: }
                     61: 
                     62: long
                     63: etherread(Chan *c, void *a, long n, ulong offset)
                     64: {
                     65:        return netread(c, a, n, offset, &softctlr->net);
                     66: }
                     67: 
                     68: long
                     69: etherwrite(Chan *c, char *a, long n, ulong offset)
                     70: {
                     71:        USED(offset);
                     72:        return streamwrite(c, a, n, 0);
                     73: }
                     74: 
                     75: void
                     76: etherremove(Chan *c)
                     77: {
                     78:        USED(c);
                     79:        error(Eperm);
                     80: }
                     81: 
                     82: void
                     83: etherwstat(Chan *c, char *dp)
                     84: {
                     85:        netwstat(c, dp, &softctlr->net);
                     86: }
                     87: 
                     88: static int
                     89: isobuf(void *arg)
                     90: {
                     91:        Ctlr *ctlr = arg;
                     92: 
                     93:        return ctlr->tb[ctlr->th].owner == Host;
                     94: }
                     95: 
                     96: static void
                     97: etheroput(Queue *q, Block *bp)
                     98: {
                     99:        Ctlr *ctlr;
                    100:        Type *type;
                    101:        Etherpkt *pkt;
                    102:        RingBuf *ring;
                    103:        int len, n, s;
                    104:        Block *nbp;
                    105:        uchar ea[6];
                    106:        char *err;
                    107: 
                    108:        type = q->ptr;
                    109:        ctlr = type->ctlr;
                    110:        if(bp->type == M_CTL){
                    111:                err = 0;
                    112:                qlock(ctlr);
                    113:                if(streamparse("connect", bp)){
                    114:                        if(type->type == -1)
                    115:                                ctlr->all--;
                    116:                        type->type = strtol((char*)bp->rptr, 0, 0);
                    117:                        if(type->type == -1)
                    118:                                ctlr->all++;
                    119:                }
                    120:                else if(streamparse("promiscuous", bp)) {
                    121:                        if(type->prom)
                    122:                                goto ctlout;
                    123:                        if(type->filter){
                    124:                                err = "address already set";
                    125:                                goto ctlout;
                    126:                        }
                    127:                        type->prom = 1;
                    128:                        ctlr->prom++;
                    129:                        if(ctlr->prom+ctlr->filter == 1)
                    130:                                (*ctlr->card.mode)(ctlr, 1);
                    131:                }
                    132:                else if(streamparse("address", bp)) {
                    133:                        if(type->prom){
                    134:                                err = "already promiscuous";
                    135:                                goto ctlout;
                    136:                        }
                    137:                        if(parseether(ea, bp->rptr) < 0){
                    138:                                err = "bad ether address";
                    139:                                goto ctlout;
                    140:                        }
                    141:                        memmove(type->ea, ea, sizeof(ea));
                    142:                        if(!type->filter){
                    143:                                type->filter = 1;
                    144:                                ctlr->filter++;
                    145:                                if(ctlr->filter == 1)
                    146:                                        (*ctlr->card.mode)(ctlr, 3);
                    147:                        }
                    148:                }
                    149:        ctlout:
                    150:                qunlock(ctlr);
                    151:                freeb(bp);
                    152:                if(err)
                    153:                        error(err);
                    154:                return;
                    155:        }
                    156: 
                    157:        /*
                    158:         * Give packet a local address, return upstream if destined for
                    159:         * this machine.
                    160:         */
                    161:        if(BLEN(bp) < ETHERHDRSIZE && (bp = pullup(bp, ETHERHDRSIZE)) == 0)
                    162:                return;
                    163:        pkt = (Etherpkt*)bp->rptr;
                    164:        memmove(pkt->s, type->ea, sizeof(type->ea));
                    165:        if(memcmp(ctlr->ea, pkt->d, sizeof(ctlr->ea)) == 0){
                    166:                len = blen(bp);
                    167:                if(bp = expandb(bp, len >= ETHERMINTU ? len: ETHERMINTU)){
                    168:                        putq(&ctlr->lbq, bp);
                    169:                        wakeup(&ctlr->rr);
                    170:                }
                    171:                return;
                    172:        }
                    173:        if(memcmp(ctlr->ba, pkt->d, sizeof(ctlr->ba)) == 0 || ctlr->prom || ctlr->all){
                    174:                len = blen(bp);
                    175:                nbp = copyb(bp, len);
                    176:                if(nbp = expandb(nbp, len >= ETHERMINTU ? len: ETHERMINTU)){
                    177:                        nbp->wptr = nbp->rptr+len;
                    178:                        putq(&ctlr->lbq, nbp);
                    179:                        wakeup(&ctlr->rr);
                    180:                }
                    181:        }
                    182: 
                    183:        /*
                    184:         * Only one transmitter at a time.
                    185:         */
                    186:        qlock(&ctlr->tlock);
                    187:        if(waserror()){
                    188:                qunlock(&ctlr->tlock);
                    189:                freeb(bp);
                    190:                nexterror();
                    191:        }
                    192: 
                    193:        /*
                    194:         * Wait till we get an output buffer.
                    195:         * should try to restart.
                    196:         */
                    197:        if(isobuf(ctlr) == 0){
                    198:                tsleep(&ctlr->tr, isobuf, ctlr, 3*1000);
                    199:                if(isobuf(ctlr) == 0){
                    200:                        qunlock(&ctlr->tlock);
                    201:                        freeb(bp);
                    202:                        poperror();
                    203:                        return;
                    204:                }
                    205:        }
                    206: 
                    207:        ring = &ctlr->tb[ctlr->th];
                    208: 
                    209:        /*
                    210:         * Copy message into buffer.
                    211:         */
                    212:        len = 0;
                    213:        for(nbp = bp; nbp; nbp = nbp->next){
                    214:                if(sizeof(Etherpkt) - len >= (n = BLEN(nbp))){
                    215:                        memmove(ring->pkt+len, nbp->rptr, n);
                    216:                        len += n;
                    217:                }
                    218:                if(bp->flags & S_DELIM)
                    219:                        break;
                    220:        }
                    221: 
                    222:        /*
                    223:         * Pad the packet (zero the pad).
                    224:         */
                    225:        if(len < ETHERMINTU){
                    226:                memset(ring->pkt+len, 0, ETHERMINTU-len);
                    227:                len = ETHERMINTU;
                    228:        }
                    229: 
                    230:        /*
                    231:         * Set up the transmit buffer and 
                    232:         * start the transmission.
                    233:         */
                    234:        s = splhi();
                    235:        ring->len = len;
                    236:        ring->owner = Interface;
                    237:        ctlr->th = NEXT(ctlr->th, ctlr->ntb);
                    238:        (*ctlr->card.transmit)(ctlr);
                    239:        ctlr->outpackets++;
                    240:        splx(s);
                    241: 
                    242:        qunlock(&ctlr->tlock);
                    243:        freeb(bp);
                    244:        poperror();
                    245: }
                    246: 
                    247: /*
                    248:  * Open an ether line discipline.
                    249:  */
                    250: static void
                    251: etherstopen(Queue *q, Stream *s)
                    252: {
                    253:        Ctlr *ctlr = softctlr;
                    254:        Type *type;
                    255: 
                    256:        type = &ctlr->type[s->id];
                    257:        RD(q)->ptr = WR(q)->ptr = type;
                    258:        type->type = 0;
                    259:        type->q = RD(q);
                    260:        type->inuse = 1;
                    261:        memmove(type->ea, ctlr->ea, sizeof(type->ea));
                    262:        type->ctlr = ctlr;
                    263: }
                    264: 
                    265: /*
                    266:  * Close ether line discipline.
                    267:  *
                    268:  * The locking is to synchronize changing the ethertype with
                    269:  * sending packets up the stream on interrupts.
                    270:  */
                    271: static int
                    272: isclosed(void *arg)
                    273: {
                    274:        return ((Type*)arg)->q == 0;
                    275: }
                    276: 
                    277: static void
                    278: etherstclose(Queue *q)
                    279: {
                    280:        Type *type = (Type*)(q->ptr);
                    281:        Ctlr *ctlr = type->ctlr;
                    282: 
                    283:        if(type->prom){
                    284:                qlock(ctlr);
                    285:                ctlr->prom--;
                    286:                if(ctlr->prom+ctlr->filter == 0)
                    287:                        (*ctlr->card.mode)(ctlr, 0);
                    288:                qunlock(ctlr);
                    289:        }
                    290:        if(type->filter){
                    291:                qlock(ctlr);
                    292:                ctlr->filter--;
                    293:                if(ctlr->filter == 0)
                    294:                        (*ctlr->card.mode)(ctlr, ctlr->prom ? 1 : 0);
                    295:                qunlock(ctlr);
                    296:        }
                    297:        if(type->type == -1){
                    298:                qlock(ctlr);
                    299:                ctlr->all--;
                    300:                qunlock(ctlr);
                    301:        }
                    302: 
                    303:        /*
                    304:         * Mark as closing and wait for kproc
                    305:         * to close us.
                    306:         */
                    307:        lock(&ctlr->clock);
                    308:        type->clist = ctlr->clist;
                    309:        ctlr->clist = type;
                    310:        unlock(&ctlr->clock);
                    311:        wakeup(&ctlr->rr);
                    312:        sleep(&type->cr, isclosed, type);
                    313: 
                    314:        type->type = 0;
                    315:        type->prom = 0;
                    316:        type->filter = 0;
                    317:        type->inuse = 0;
                    318:        netdisown(type);
                    319:        type->ctlr = 0;
                    320: }
                    321: 
                    322: static Qinfo info = {
                    323:        nullput,
                    324:        etheroput,
                    325:        etherstopen,
                    326:        etherstclose,
                    327:        "ether"
                    328: };
                    329: 
                    330: static int
                    331: clonecon(Chan *c)
                    332: {
                    333:        Ctlr *ctlr = softctlr;
                    334:        Type *type;
                    335: 
                    336:        USED(c);
                    337:        for(type = ctlr->type; type < &ctlr->type[NType]; type++){
                    338:                qlock(type);
                    339:                if(type->inuse || type->q){
                    340:                        qunlock(type);
                    341:                        continue;
                    342:                }
                    343:                type->inuse = 1;
                    344:                memmove(type->ea, ctlr->ea, sizeof(type->ea));
                    345:                netown(type, u->p->user, 0);
                    346:                qunlock(type);
                    347:                return type - ctlr->type;
                    348:        }
                    349:        exhausted("ether channels");
                    350:        return 0;
                    351: }
                    352: 
                    353: static void
                    354: statsfill(Chan *c, char *p, int n)
                    355: {
                    356:        Ctlr *ctlr = softctlr;
                    357:        char buf[256];
                    358: 
                    359:        USED(c);
                    360:        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",
                    361:                ctlr->inpackets, ctlr->outpackets, ctlr->crcs,
                    362:                ctlr->overflows, ctlr->frames, ctlr->buffs, ctlr->oerrs,
                    363:                ctlr->ea[0], ctlr->ea[1], ctlr->ea[2],
                    364:                ctlr->ea[3], ctlr->ea[4], ctlr->ea[5]);
                    365:        strncpy(p, buf, n);
                    366: }
                    367: 
                    368: static void
                    369: typefill(Chan *c, char *p, int n)
                    370: {
                    371:        char buf[16];
                    372:        Type *type;
                    373: 
                    374:        type = &softctlr->type[STREAMID(c->qid.path)];
                    375:        sprint(buf, "%d", type->type);
                    376:        strncpy(p, buf, n);
                    377: }
                    378: 
                    379: int
                    380: eaddrmatch(Ctlr *ctlr, uchar *ea)
                    381: {
                    382:        Type *type;
                    383: 
                    384:        for(type = &ctlr->type[0]; type < &ctlr->type[NType]; type++){
                    385:                if(type->q == 0 || ea[0] != type->ea[0])
                    386:                        continue;
                    387:                if(memcmp(ea, type->ea, sizeof(type->ea)) == 0)
                    388:                        return 1;
                    389:        }
                    390:        return 0;
                    391: }
                    392: 
                    393: static void
                    394: etherup(Ctlr *ctlr, Etherpkt *pkt, int len)
                    395: {
                    396:        int t;
                    397:        Type *type;
                    398:        Block *bp;
                    399: 
                    400:        t = (pkt->type[0]<<8)|pkt->type[1];
                    401:        for(type = &ctlr->type[0]; type < &ctlr->type[NType]; type++){
                    402: 
                    403:                /*
                    404:                 * Check for open, the right type, and flow control.
                    405:                 */
                    406:                if(type->q == 0)
                    407:                        continue;
                    408:                if(t != type->type && type->type >= 0)
                    409:                        continue;
                    410:                if(type->q->next->len > Streamhi)
                    411:                        continue;
                    412: 
                    413:                /*
                    414:                 * Only a trace channel gets packets destined for other machines.
                    415:                 */
                    416:                if(type->type != -1 && pkt->d[0] != 0xFF
                    417:                  && (*pkt->d != *type->ea || memcmp(pkt->d, type->ea, sizeof(pkt->d))))
                    418:                        continue;
                    419: 
                    420:                if(waserror() == 0){
                    421:                        bp = allocb(len);
                    422:                        memmove(bp->rptr, pkt, len);
                    423:                        bp->wptr += len;
                    424:                        bp->flags |= S_DELIM;
                    425:                        PUTNEXT(type->q, bp);
                    426:                        poperror();
                    427:                }
                    428:        }
                    429: }
                    430: 
                    431: static int
                    432: isinput(void *arg)
                    433: {
                    434:        Ctlr *ctlr = arg;
                    435: 
                    436:        return ctlr->lbq.first || ctlr->rb[ctlr->rh].owner == Host || ctlr->clist;
                    437: }
                    438: 
                    439: static void
                    440: etherkproc(void *arg)
                    441: {
                    442:        Ctlr *ctlr = arg;
                    443:        RingBuf *ring;
                    444:        Block *bp;
                    445:        Type *type;
                    446: 
                    447:        if(waserror()){
                    448:                print("%s noted\n", ctlr->name);
                    449:                /* fix
                    450:                if(ctlr->card.reset)
                    451:                        (*ctlr->card.reset)(ctlr);
                    452:                 */
                    453:                ctlr->kproc = 0;
                    454:                nexterror();
                    455:        }
                    456: 
                    457:        for(;;){
                    458:                tsleep(&ctlr->rr, isinput, ctlr, 500);
                    459:                if(ctlr->card.watch)
                    460:                        (*ctlr->card.watch)(ctlr);
                    461: 
                    462:                /*
                    463:                 * Process any internal loopback packets.
                    464:                 */
                    465:                while(bp = getq(&ctlr->lbq)){
                    466:                        ctlr->inpackets++;
                    467:                        etherup(ctlr, (Etherpkt*)bp->rptr, BLEN(bp));
                    468:                        freeb(bp);
                    469:                }
                    470: 
                    471:                /*
                    472:                 * Process any received packets.
                    473:                 */
                    474:                while(ctlr->rb[ctlr->rh].owner == Host){
                    475:                        ctlr->inpackets++;
                    476:                        ring = &ctlr->rb[ctlr->rh];
                    477:                        etherup(ctlr, (Etherpkt*)ring->pkt, ring->len);
                    478:                        ring->owner = Interface;
                    479:                        ctlr->rh = NEXT(ctlr->rh, ctlr->nrb);
                    480:                }
                    481: 
                    482:                /*
                    483:                 * Close Types requesting it.
                    484:                 */
                    485:                if(ctlr->clist){
                    486:                        lock(&ctlr->clock);
                    487:                        for(type = ctlr->clist; type; type = type->clist){
                    488:                                type->q = 0;
                    489:                                wakeup(&type->cr);
                    490:                        }
                    491:                        ctlr->clist = 0;
                    492:                        unlock(&ctlr->clock);
                    493:                }
                    494:        }
                    495: }
                    496: 
                    497: static void
                    498: etherintr(Ureg *ur, void *a)
                    499: {
                    500:        Ctlr *ctlr = softctlr;
                    501: 
                    502:        USED(ur, a);
                    503:        (*ctlr->card.intr)(ctlr);
                    504: }
                    505: 
                    506: static void
                    507: reset(Ctlr *ctlr)
                    508: {
                    509:        int i;
                    510: 
                    511:        if(ctlr->nrb == 0)
                    512:                ctlr->nrb = Nrb;
                    513:        ctlr->rb = xalloc(sizeof(RingBuf)*ctlr->nrb);
                    514:        if(ctlr->ntb == 0)
                    515:                ctlr->ntb = Ntb;
                    516:        ctlr->tb = xalloc(sizeof(RingBuf)*ctlr->ntb);
                    517: 
                    518:        memset(ctlr->ba, 0xFF, sizeof(ctlr->ba));
                    519: 
                    520:        ctlr->net.name = "ether";
                    521:        ctlr->net.nconv = NType;
                    522:        ctlr->net.devp = &info;
                    523:        ctlr->net.protop = 0;
                    524:        ctlr->net.listen = 0;
                    525:        ctlr->net.clone = clonecon;
                    526:        ctlr->net.ninfo = 2;
                    527:        ctlr->net.info[0].name = "stats";
                    528:        ctlr->net.info[0].fill = statsfill;
                    529:        ctlr->net.info[1].name = "type";
                    530:        ctlr->net.info[1].fill = typefill;
                    531:        for(i = 0; i < NType; i++)
                    532:                netadd(&ctlr->net, &ctlr->type[i], i);
                    533: }
                    534: 
                    535: extern int wd8003reset(Ctlr*);
                    536: extern int ne2000reset(Ctlr*);
                    537: extern int ccc509reset(Ctlr*);
                    538: extern int nsciareset(Ctlr*);
                    539: extern int ne2000PCMreset(Ctlr*);
                    540: 
                    541: #define NCARD 32
                    542: struct {
                    543:        char    *type;
                    544:        int     (*reset)(Ctlr*);
                    545: } cards[NCARD+1];
                    546: 
                    547: void
                    548: addethercard(char *t, int (*r)(Ctlr*))
                    549: {
                    550:        static int ncard;
                    551: 
                    552:        if(ncard == NCARD)
                    553:                panic("too many ether cards");
                    554:        cards[ncard].type = t;
                    555:        cards[ncard].reset = r;
                    556:        ncard++;
                    557: }
                    558: 
                    559: void
                    560: etherreset(void)
                    561: {
                    562:        Ctlr *ctlr;
                    563:        int i, n, ctlrno;
                    564: 
                    565:        if(softctlr == 0)
                    566:                softctlr = xalloc(sizeof(Ctlr));
                    567:        else
                    568:                memset(softctlr, 0, sizeof(Ctlr));
                    569:        ctlr = softctlr;
                    570: 
                    571:        for(ctlrno = i = 0; isaconfig("ether", i, &ctlr->card); i++){
                    572:                for(n = 0; cards[n].type; n++){
                    573:                        if(strcmp(cards[n].type, ctlr->card.type))
                    574:                                continue;
                    575:                        ctlr->ctlrno = ctlrno;
                    576:                        memmove(ctlr->ea, ctlr->card.ea, sizeof(ctlr->ea));
                    577:                        if((*cards[n].reset)(ctlr))
                    578:                                break;
                    579: 
                    580:                        /*ctlrno++;*/
                    581:                        ctlr->present = 1;
                    582:                        /*
                    583:                         * IRQ2 doesn't really exist, it's used to gang the interrupt
                    584:                         * controllers together. A device set to IRQ2 will appear on
                    585:                         * the second interrupt controller as IRQ9.
                    586:                         */
                    587:                        if(ctlr->card.irq == 2)
                    588:                                ctlr->card.irq = 9;
                    589:                        setvec(Int0vec + ctlr->card.irq, etherintr, 0);
                    590: 
                    591:                        print("ether%d:%s: port %lux irq %d addr %lux size %d width %d:",
                    592:                                ctlr->ctlrno, ctlr->card.type, ctlr->card.port, ctlr->card.irq,
                    593:                                ctlr->card.mem, ctlr->card.size, ctlr->card.bit16 ? 16: 8);
                    594:                        for(i = 0; i < sizeof(ctlr->ea); i++)
                    595:                                print("%2.2ux", ctlr->ea[i]);
                    596:                        print("\n");
                    597: 
                    598:                        reset(ctlr);
                    599:                        return;
                    600:                }
                    601:                memset(softctlr, 0, sizeof(Ctlr));
                    602:        }
                    603: }
                    604: 
                    605: void
                    606: etherinit(void)
                    607: {
                    608:        Ctlr *ctlr = softctlr;
                    609:        int i;
                    610: 
                    611:        if(ctlr->present == 0)
                    612:                return;
                    613: 
                    614:        ctlr->rh = 0;
                    615:        ctlr->ri = 0;
                    616:        for(i = 0; i < ctlr->nrb; i++)
                    617:                ctlr->rb[i].owner = Interface;
                    618: 
                    619:        ctlr->th = 0;
                    620:        ctlr->ti = 0;
                    621:        for(i = 0; i < ctlr->ntb; i++)
                    622:                ctlr->tb[i].owner = Host;
                    623: }
                    624: 
                    625: Chan*
                    626: etherattach(char *spec)
                    627: {
                    628:        Ctlr *ctlr = softctlr;
                    629: 
                    630:        if(ctlr->present == 0)
                    631:                error(Enodev);
                    632: 
                    633:        /*
                    634:         * Enable the interface
                    635:         * and start the kproc.
                    636:         */     
                    637:        (*ctlr->card.attach)(ctlr);
                    638:        if(ctlr->kproc == 0){
                    639:                sprint(ctlr->name, "ether%dkproc", 0);
                    640:                ctlr->kproc = 1;
                    641:                kproc(ctlr->name, etherkproc, ctlr);
                    642:        }
                    643:        return devattach('l', spec);
                    644: }

unix.superglobalmegacorp.com

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