| plan 9 kernel history: overview | file list | diff list |
1992/0410/pc/devether.c (diff list | history)
| 1992/0409/sys/src/9/pc/devether.c:18,39 – 1992/0410/sys/src/9/pc/devether.c:18,44 (short | long | prev | next) | ||
| 1992/0403 | #include "io.h" #include "devtab.h" | |
| 1992/0410 | static int debug; | |
| 1992/0403 | typedef struct Ctlr Ctlr; | |
| 1992/0410 | typedef struct Type Type; | |
| 1992/0404 | typedef struct Ring Ring; | |
| 1992/0403 | enum { IObase = 0x360, | |
| 1992/0404 |
| |
| 1992/0410 | RAMbase = 0xD0000, | |
| 1992/0404 | RAMsize = 8*1024, BUFsize = 256, | |
| 1992/0403 | ||
| 1992/0410 | RINGbase = 6, /* gak */ RINGsize = 32, /* gak */ | |
| 1992/0404 | Nctlr = 1, | |
| 1992/0410 | NType = 9, /* types/interface */ | |
| 1992/0404 | }; | |
| 1992/0408 |
| |
| 1992/0410 | #define NEXT(x, l) ((((x)+1)%(l)) == 0 ? RINGbase: (((x)+1)%(l))) #define PREV(x, l) (((x)-1) < RINGbase ? (l-1): ((x)-1)) | |
| 1992/0408 | ||
| 1992/0404 | /* * register offsets from IObase | |
| 1992/0409/sys/src/9/pc/devether.c:77,83 – 1992/0410/sys/src/9/pc/devether.c:82,87 | ||
| 1992/0404 | Rxe = 0x04, /* receive error */ Txe = 0x08, /* transmit error */ Ovw = 0x10, /* overwrite warning */ | |
| 1992/0403 | ||
| 1992/0404 | struct Ring { | |
| 1992/0409/sys/src/9/pc/devether.c:91,97 – 1992/0410/sys/src/9/pc/devether.c:95,101 | ||
| 1992/0403 | /* * one per ethernet packet type */ | |
| 1992/0410 | struct Type { | |
| 1992/0403 | QLock; int type; /* ethernet type */ int prom; /* promiscuous mode */ | |
| 1992/0409/sys/src/9/pc/devether.c:119,125 – 1992/0410/sys/src/9/pc/devether.c:123,129 | ||
| 1992/0403 | int iobase; /* I/O base address */ | |
| 1992/0410 | Type type[NType]; | |
| 1992/0403 | uchar ea[6]; uchar ba[6]; | |
| 1992/0409/sys/src/9/pc/devether.c:127,133 – 1992/0410/sys/src/9/pc/devether.c:131,137 | ||
| 1992/0403 | uchar kproc; /* true if kproc started */ char name[NAMELEN]; /* name of kproc */ Network net; | |
| 1992/0410 | Netprot prot[NType]; | |
| 1992/0403 | int inpackets; int outpackets; | |
| 1992/0409/sys/src/9/pc/devether.c:152,168 – 1992/0410/sys/src/9/pc/devether.c:156,172 | ||
| 1992/0403 | { | |
| 1992/0406 | Ctlr *cp; | |
| 1992/0403 | int len, n; | |
| 1992/0406 |
| |
| 1992/0410 | Type *tp; | |
| 1992/0403 | Etherpkt *p; Block *nbp; | |
| 1992/0406 |
| |
| 1992/0410 | cp = ((Type *)q->ptr)->ctlr; | |
| 1992/0403 | if(bp->type == M_CTL){ | |
| 1992/0406 |
| |
| 1992/0410 | tp = q->ptr; | |
| 1992/0403 | if(streamparse("connect", bp)) | |
| 1992/0406 |
| |
| 1992/0410 | tp->type = strtol((char *)bp->rptr, 0, 0); | |
| 1992/0403 | else if(streamparse("promiscuous", bp)) { | |
| 1992/0406 |
| |
| 1992/0410 | tp->prom = 1; | |
| 1992/0406 | qlock(cp); cp->prom++; if(cp->prom == 1) | |
| 1992/0409/sys/src/9/pc/devether.c:264,279 – 1992/0410/sys/src/9/pc/devether.c:268,283 | ||
| 1992/0403 | etherstopen(Queue *q, Stream *s) { | |
| 1992/0404 | Ctlr *cp = &ctlr[0]; | |
| 1992/0410 | Type *tp; | |
| 1992/0403 | ||
| 1992/0404 |
| |
| 1992/0410 | tp = &cp->type[s->id]; qlock(tp); RD(q)->ptr = WR(q)->ptr = tp; tp->type = 0; tp->q = RD(q); tp->inuse = 1; tp->ctlr = cp; qunlock(tp); | |
| 1992/0403 | } /* | |
| 1992/0409/sys/src/9/pc/devether.c:285,307 – 1992/0410/sys/src/9/pc/devether.c:289,311 | ||
| 1992/0403 | static void etherstclose(Queue *q) { | |
| 1992/0404 |
| |
| 1992/0410 | Type *tp; | |
| 1992/0403 | ||
| 1992/0404 |
| |
| 1992/0405 |
| |
| 1992/0404 |
| |
| 1992/0410 | tp = (Type *)(q->ptr); if(tp->prom){ qlock(tp->ctlr); tp->ctlr->prom--; if(tp->ctlr->prom == 0) outb(tp->ctlr->iobase+Rcr, 0x04);/* AB */ qunlock(tp->ctlr); | |
| 1992/0403 | } | |
| 1992/0404 |
| |
| 1992/0410 | qlock(tp); tp->type = 0; tp->q = 0; tp->prom = 0; tp->inuse = 0; netdisown(&tp->ctlr->net, tp - tp->ctlr->type); qunlock(tp); | |
| 1992/0403 | } static Qinfo info = { | |
| 1992/0409/sys/src/9/pc/devether.c:316,333 – 1992/0410/sys/src/9/pc/devether.c:320,337 | ||
| 1992/0404 | clonecon(Chan *c) | |
| 1992/0403 | { | |
| 1992/0404 | Ctlr *cp = &ctlr[0]; | |
| 1992/0410 | Type *tp; | |
| 1992/0403 | ||
| 1992/0404 |
| |
| 1992/0410 | for(tp = cp->type; tp < &cp->type[NType]; tp++){ qlock(tp); if(tp->inuse || tp->q){ qunlock(tp); | |
| 1992/0403 | continue; } | |
| 1992/0404 |
| |
| 1992/0410 | tp->inuse = 1; netown(&cp->net, tp - cp->type, u->p->user, 0); qunlock(tp); return tp - cp->type; | |
| 1992/0403 | } exhausted("ether channels"); } | |
| 1992/0409/sys/src/9/pc/devether.c:349,358 – 1992/0410/sys/src/9/pc/devether.c:353,362 | ||
| 1992/0403 | typefill(Chan *c, char *p, int n) { char buf[16]; | |
| 1992/0404 |
| |
| 1992/0410 | Type *tp; | |
| 1992/0403 | ||
| 1992/0404 |
| |
| 1992/0410 | tp = &ctlr[0].type[STREAMID(c->qid.path)]; sprint(buf, "%d", tp->type); | |
| 1992/0403 | strncpy(p, buf, n); } | |
| 1992/0409/sys/src/9/pc/devether.c:360,366 – 1992/0410/sys/src/9/pc/devether.c:364,370 | ||
| 1992/0403 | intr(Ureg *ur) { | |
| 1992/0404 | Ctlr *cp = &ctlr[0]; | |
| 1992/0410 | uchar isr, bnry, curr; | |
| 1992/0404 | while(isr = inb(cp->iobase+Isr)){ outb(cp->iobase+Isr, isr); | |
| 1992/0409/sys/src/9/pc/devether.c:369,375 – 1992/0410/sys/src/9/pc/devether.c:373,379 | ||
| 1992/0404 | if(isr & Rxe){ cp->frames += inb(cp->iobase+Cntr0); cp->crcs += inb(cp->iobase+Cntr1); | |
| 1992/0410 | cp->overflows += inb(cp->iobase+Cntr2); | |
| 1992/0404 | } if(isr & Ptx) cp->outpackets++; | |
| 1992/0409/sys/src/9/pc/devether.c:377,384 – 1992/0410/sys/src/9/pc/devether.c:381,391 | ||
| 1992/0407 | cp->xbusy = 0; wakeup(&cp->xr); | |
| 1992/0404 | } | |
| 1992/0409 |
| |
| 1992/0408 |
| |
| 1992/0410 | if(isr & Ovw){ bnry = inb(cp->iobase+Bnry); outb(cp->iobase+bnry, bnry); cp->buffs++; } | |
| 1992/0404 | /* * we have received packets. * this is the only place, other than the init code, | |
| 1992/0409/sys/src/9/pc/devether.c:386,397 – 1992/0410/sys/src/9/pc/devether.c:393,404 | ||
| 1992/0405 | * we must be sure to reset it back to Page0 in case | |
| 1992/0404 | * we interrupted some other part of this driver. */ | |
| 1992/0410 | if(isr & (Rxe|Prx)){ | |
| 1992/0404 | outb(cp->iobase+Cr, 0x62); /* Page1, RD2|STA */ cp->curr = inb(cp->iobase+Curr); | |
| 1992/0409 |
| |
| 1992/0404 | outb(cp->iobase+Cr, 0x22); /* Page0, RD2|STA */ | |
| 1992/0410 | if(debug) print("I%d/%d/%d|", isr, cp->curr, cp->bnry); | |
| 1992/0404 | wakeup(&cp->rr); } } | |
| 1992/0409/sys/src/9/pc/devether.c:414,424 – 1992/0410/sys/src/9/pc/devether.c:421,431 | ||
| 1992/0404 | outb(cp->iobase+Rbcr1, 0); outb(cp->iobase+Rcr, 0x04); /* AB */ outb(cp->iobase+Tcr, 0x20); /* LB0 */ | |
| 1992/0410 | cp->bnry = RINGbase; | |
| 1992/0408 | outb(cp->iobase+Bnry, cp->bnry); | |
| 1992/0407 | cp->ring = (Ring*)(KZERO|RAMbase); | |
| 1992/0404 |
| |
| 1992/0410 | outb(cp->iobase+Pstart, RINGbase); outb(cp->iobase+Pstop, RINGsize); | |
| 1992/0404 | outb(cp->iobase+Isr, 0xFF); outb(cp->iobase+Imr, 0x1F); /* OVWE|TXEE|RXEE|PTXE|PRXE */ | |
| 1992/0403 | ||
| 1992/0409/sys/src/9/pc/devether.c:443,451 – 1992/0410/sys/src/9/pc/devether.c:450,462 | ||
| 1992/0404 | cp->iobase = IObase; | |
| 1992/0409 | msr = 0x40|inb(cp->iobase); outb(cp->iobase, msr); | |
| 1992/0410 | msr=0x40|inb(cp->iobase+0x05); outb(cp->iobase+0x05, msr); | |
| 1992/0409 | for(i = 0; i < 0x10; i++) print("#%2.2ux ", inb(cp->iobase+i)); print("\n"); | |
| 1992/0410 | msr=0x40|inb(cp->iobase+0x05); outb(cp->iobase+0x05, msr); | |
| 1992/0404 | for(i = 0; i < sizeof(cp->ea); i++) cp->ea[i] = inb(cp->iobase+EA+i); | |
| 1992/0408 | init(cp); | |
| 1992/0409/sys/src/9/pc/devether.c:453,459 – 1992/0410/sys/src/9/pc/devether.c:464,470 | ||
| 1992/0404 | memset(cp->ba, 0xFF, sizeof(cp->ba)); | |
| 1992/0403 | ||
| 1992/0404 | cp->net.name = "ether"; | |
| 1992/0410 | cp->net.nconv = NType; | |
| 1992/0404 | cp->net.devp = &info; cp->net.protop = 0; cp->net.listen = 0; | |
| 1992/0409/sys/src/9/pc/devether.c:467,490 – 1992/0410/sys/src/9/pc/devether.c:478,503 | ||
| 1992/0403 | } | |
| 1992/0404 | static void | |
| 1992/0410 | etherup(Ctlr *cp, uchar *d0, int len0, uchar *d1, int len1) | |
| 1992/0404 | { | |
| 1992/0410 | Etherpkt *p; | |
| 1992/0404 | Block *bp; | |
| 1992/0410 | Type *tp; | |
| 1992/0404 | int t; | |
| 1992/0410 | p = (Etherpkt*)d0; t = (p->type[0]<<8)|p->type[1]; for(tp = &cp->type[0]; tp < &cp->type[NType]; tp++){ | |
| 1992/0404 | /* * check before locking just to save a lock */ | |
| 1992/0410 | if(tp->q == 0 || (t != tp->type && tp->type != -1)) | |
| 1992/0404 | continue; /* * only a trace channel gets packets destined for other machines */ | |
| 1992/0410 | if(tp->type != -1 && p->d[0] != 0xFF && memcmp(p->d, cp->ea, sizeof(p->d))) | |
| 1992/0404 | continue; /* | |
| 1992/0409/sys/src/9/pc/devether.c:491,511 – 1992/0410/sys/src/9/pc/devether.c:504,526 | ||
| 1992/0404 | * check after locking to make sure things didn't * change under foot */ | |
| 1992/0410 | if(canqlock(tp) == 0) | |
| 1992/0404 | continue; | |
| 1992/0410 | if(tp->q == 0 || tp->q->next->len > Streamhi || (t != tp->type && tp->type != -1)){ qunlock(tp); | |
| 1992/0404 | continue; } if(waserror() == 0){ | |
| 1992/0410 | bp = allocb(len0+len1); memmove(bp->rptr, d0, len0); if(len1) memmove(bp->rptr+len0, d1, len1); bp->wptr += len0+len1; | |
| 1992/0404 | bp->flags |= S_DELIM; | |
| 1992/0410 | PUTNEXT(tp->q, bp); | |
| 1992/0404 | } poperror(); | |
| 1992/0410 | qunlock(tp); | |
| 1992/0404 | } } | |
| 1992/0409/sys/src/9/pc/devether.c:526,532 – 1992/0410/sys/src/9/pc/devether.c:541,547 | ||
| 1992/0403 | { | |
| 1992/0404 | Ctlr *cp = arg; | |
| 1992/0403 | ||
| 1992/0408 |
| |
| 1992/0410 | return NEXT(cp->bnry, RINGsize) != cp->curr; | |
| 1992/0403 | } static void | |
| 1992/0409/sys/src/9/pc/devether.c:536,541 – 1992/0410/sys/src/9/pc/devether.c:551,557 | ||
| 1992/0404 | Block *bp; uchar bnry, curr; Ring *rp; | |
| 1992/0410 | int len0, len1; | |
| 1992/0403 | if(waserror()){ | |
| 1992/0404 | print("%s noted\n", cp->name); | |
| 1992/0409/sys/src/9/pc/devether.c:551,557 – 1992/0410/sys/src/9/pc/devether.c:567,573 | ||
| 1992/0406 | */ | |
| 1992/0404 | while(bp = getq(&cp->rq)){ cp->inpackets++; | |
| 1992/0410 | etherup(cp, bp->rptr, BLEN(bp), 0, 0); | |
| 1992/0404 | freeb(bp); } | |
| 1992/0408 | ||
| 1992/0409/sys/src/9/pc/devether.c:558,570 – 1992/0410/sys/src/9/pc/devether.c:574,599 | ||
| 1992/0406 | /* * process any received packets */ | |
| 1992/0408 |
| |
| 1992/0410 | bnry = NEXT(cp->bnry, RINGsize); | |
| 1992/0408 | while(bnry != cp->curr){ rp = &cp->ring[bnry]; | |
| 1992/0406 | cp->inpackets++; | |
| 1992/0407 |
| |
| 1992/0410 | len0 = ((rp->len1<<8)+rp->len0)-4; len1 = 0; if(rp->data+len0 >= (uchar*)&cp->ring[RINGsize]){ len1 = rp->data+len0 - (uchar*)&cp->ring[RINGsize]; len0 = (uchar*)&cp->ring[RINGsize] - rp->data; } etherup(cp, rp->data, len0, (uchar*)&cp->ring[RINGbase], len1); if(debug) print("K%d/%d/%d|", bnry, rp->next, PREV(rp->next, RINGsize)); | |
| 1992/0408 | bnry = rp->next; | |
| 1992/0410 | cp->bnry = PREV(bnry, RINGsize); | |
| 1992/0407 | outb(cp->iobase+Bnry, cp->bnry); | |
| 1992/0406 | } | |
| 1992/0403 | } | |
| 1992/0409/sys/src/9/pc/devether.c:661,666 – 1992/0410/sys/src/9/pc/devether.c:690,696 | ||
| 1992/0409 | int s; s = splhi(); | |
| 1992/0410 | debug++; | |
| 1992/0409 | bnry = inb(cp->iobase+Bnry); outb(cp->iobase+Cr, 0x62); /* Page1, RD2|STA */ curr = inb(cp->iobase+Curr); | |
| 1992/0409/sys/src/9/pc/devether.c:668,674 – 1992/0410/sys/src/9/pc/devether.c:698,704 | ||
| 1992/0409 | isr = inb(cp->iobase+Isr); print("b%d c%d x%d B%d C%d I%ux", cp->bnry, cp->curr, cp->xbusy, bnry, curr, isr); | |
| 1992/0410 | print("\t%d %d %d %d %d %d %d\n", cp->inpackets, cp->outpackets, | |
| 1992/0409 | cp->crcs, cp->oerrs, cp->frames, cp->overflows, cp->buffs); splx(s); | |
| 1992/0403 | } | |