## diffname pc/devether.c 1992/0403 ## diff -e /dev/null /n/bootesdump/1992/0403/sys/src/9/safari/devether.c 0a /* * Western Digital ethernet adapter * BUGS: * more than one controller * fix for different controller types */ #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "../port/error.h" #include "io.h" #include "devtab.h" typedef struct Ctlr Ctlr; typedef struct Pktype Pktype; enum { IObase = 0x360, EA = 0x08, /* Ethernet Address in ROM */ ID = 0x0E, /* interface type */ NIC = 0x10, /* National DP8390 Chip */ Cr = NIC+0x00, /* Page [01] */ Clda0 = NIC+0x01, /* read */ Pstart = Clda0, /* write */ Clda1 = NIC+0x02, /* read */ Pstop = Clda1, /* write */ Bnry = NIC+0x03, /* Page 0 */ Tsr = NIC+0x04, /* read */ Tpsr = Tsr, /* write */ Ncr = NIC+0x05, Isr = NIC+0x07, Rbcr0 = NIC+0x0A, Rbcr1 = NIC+0x0B, Rsr = NIC+0x0C, /* read */ Rcr = Rsr, /* write */ Cntr0 = NIC+0x0D, /* read */ Tcr = Cntr0, /* write */ Cntr1 = NIC+0x0E, /* read */ Dcr = Cntr1, /* write */ Cntr2 = NIC+0x0F, /* read */ Imr = Cntr2, /* write */ Par0 = NIC+0x01, /* Page 1 */ Curr = NIC+0x07, Mar0 = NIC+0x08, Mar1 = NIC+0x09, Mar2 = NIC+0x0A, Mar3 = NIC+0x0B, Mar4 = NIC+0x0C, Mar5 = NIC+0x0D, Mar6 = NIC+0x0E, Mar7 = NIC+0x0F, RAMbase = 0xC8000, Nctlr = 1, NPktype = 9, /* types/interface */ }; /* * one per ethernet packet type */ struct Pktype { QLock; int type; /* ethernet type */ int prom; /* promiscuous mode */ Queue *q; int inuse; Ctlr *ctlr; }; /* * per ethernet */ struct Ctlr { QLock; Rendez rr; /* rendezvous for an input buffer */ Queue rq; Qlock xl; Rendez xr; int iobase; /* I/O base address */ Pktype pktype[NPktype]; uchar ea[6]; uchar ba[6]; uchar prom; /* true if promiscuous mode */ uchar kproc; /* true if kproc started */ char name[NAMELEN]; /* name of kproc */ Network net; Netprot prot[NPktype]; int inpackets; int outpackets; int crcs; /* input crc errors */ int oerrs; /* output errors */ int frames; /* framing errors */ int overflows; /* packet overflows */ int buffs; /* buffering errors */ }; static Ctlr ctlr[Nctlr]; static void etheroput(Queue *q, Block *bp) { Ctlr *c; int len, n; Pktype *t; Etherpkt *p; Block *nbp; c = ((Pktype *)q->ptr)->ctlr; if(bp->type == M_CTL){ t = q->ptr; if(streamparse("connect", bp)) t->type = strtol((char *)bp->rptr, 0, 0); else if(streamparse("promiscuous", bp)) { t->prom = 1; qlock(c); c->prom++; if(c->prom == 1) outb(c->iobase+Rcr, 0x14); /* PRO|AB */ qunlock(c); } freeb(bp); return; } /* * give packet a local address, return upstream if destined for * this machine. */ if(BLEN(bp) < ETHERHDRSIZE){ bp = pullup(bp, ETHERHDRSIZE); if(bp == 0) return; } p = (Etherpkt *)bp->rptr; memmove(p->s, c->ea, sizeof(c->ea)); if(memcmp(c->ea, p->d, sizeof(c->ea)) == 0){ len = blen(bp); bp = expandb(bp, len >= ETHERMINTU ? len: ETHERMINTU); if(bp){ putq(&c->rq, bp); wakeup(&c->rr); } return; } if(memcmp(c->ba, p->d, sizeof(c->ba)) == 0){ len = blen(bp); nbp = copyb(bp, len); nbp = expandb(nbp, len >= ETHERMINTU ? len: ETHERMINTU); if(nbp){ nbp->wptr = nbp->rptr+len; putq(&c->rq, nbp); wakeup(&c->rr); } } /* * only one transmitter at a time */ qlock(&c->xl); if(waserror()){ qunlock(&c->xl); nexterror(); } /* * Wait till we get an output buffer */ sleep(&c->xr, isobuf, c); p = enet.xn; /* * copy message into buffer */ len = 0; for(nbp = bp; nbp; nbp = nbp->next){ if(sizeof(Etherpkt) - len >= (n = BLEN(nbp))){ memmove(((uchar *)p)+len, nbp->rptr, n); len += n; } else print("no room damn it\n"); if(bp->flags & S_DELIM) break; } /* * pad the packet (zero the pad) */ if(len < ETHERMINTU){ memset(((char*)p)+len, 0, ETHERMINTU-len); len = ETHERMINTU; } enet.xn->len = len; /* * give packet a local address */ memmove(p->s, enet.ea, sizeof(enet.ea)); /* * give to Chip */ splhi(); /* sync with interrupt routine */ enet.xn->owner = Chip; if(enet.xmting == 0) ethersend(enet.xn); spllo(); /* * send */ enet.xn = XSUCC(enet.xn); freeb(bp); qunlock(&enet.xl); poperror(); enet.outpackets++; } /* * open an ether line discipline * * the lock is to synchronize changing the ethertype with * sending packets up the stream on interrupts. */ static void etherstopen(Queue *q, Stream *s) { Ctlr *c = &ctlr[0]; Pktype *t; t = &c->pktype[s->id]; qlock(t); RD(q)->ptr = WR(q)->ptr = t; t->type = 0; t->q = RD(q); t->inuse = 1; t->ctlr = c; qunlock(t); } /* * close ether line discipline * * the lock is to synchronize changing the ethertype with * sending packets up the stream on interrupts. */ static void etherstclose(Queue *q) { Pktype *t; t = (Pktype *)(q->ptr); if(t->prom){ qlock(t->ctlr); t->ctlr->prom--; if(t->ctlr->prom == 0) /* turn off promiscuous mode here */; qunlock(t->ctlr); } qlock(t); t->type = 0; t->q = 0; t->prom = 0; t->inuse = 0; netdisown(&t->ctlr->net, t - t->ctlr->pktype); qunlock(t); } static Qinfo info = { nullput, etheroput, etherstopen, etherstclose, "ether" }; static int clonecon(Chan *chan) { Ctlr *c = &ctlr[0]; Pktype *t; for(t = c->pktype; t < &c->pktype[NPktype]; t++){ qlock(t); if(t->inuse || t->q){ qunlock(t); continue; } t->inuse = 1; netown(&c->net, t - c->pktype, u->p->user, 0); qunlock(t); return t - c->pktype; } exhausted("ether channels"); } static void statsfill(Chan *chan, char *p, int n) { Ctlr *c = &ctlr[0]; char buf[256]; 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", c->inpackets, c->outpackets, c->crcs, c->overflows, c->frames, c->buffs, c->oerrs, c->ea[0], c->ea[1], c->ea[2], c->ea[3], c->ea[4], c->ea[5]); strncpy(p, buf, n); } static void typefill(Chan *c, char *p, int n) { char buf[16]; Pktype *t; t = &ctlr[0].pktype[STREAMID(c->qid.path)]; sprint(buf, "%d", t->type); strncpy(p, buf, n); } static void intr(Ureg *ur) { panic("ether intr\n"); } /* * the following initialisation procedure * is mandatory * after this, the chip is still offline */ static void init(Ctlr *c) { int i; outb(c->iobase+Cr, 0x21); /* Page0, RD2|STP */ outb(c->iobase+Dcr, 0x48); /* FT1|LS */ outb(c->iobase+Rbcr0, 0); outb(c->iobase+Rbcr1, 0); outb(c->iobase+Rcr, 0x04); /* AB */ outb(c->iobase+Tcr, 0); outb(c->iobase+Bnry, 6); outb(c->iobase+Pstart, 6); /* 6*256 */ outb(c->iobase+Pstop, 32); /* 8*1024/256 */ outb(c->iobase+Isr, 0xFF); outb(c->iobase+Imr, 0x0F); /* TXEE|RXEE|PTXE|PRXE */ outb(c->iobase+Cr, 0x61); /* Page1, RD2|STP */ for(i = 0; i < sizeof(c->ea); i++) outb(c->iobase+Par0+i, c->ea[i]); outb(c->iobase+Curr, 6); /* 6*256 */ } void etherreset(void) { Ctlr *c = &ctlr[0]; int i; c->iobase = IObase; init(c); setvec(Ethervec, intr); for(i = 0; i < sizeof(c->ea); i++) c->ea[i] = inb(c->iobase+EA+i); memset(c->ba, 0xFF, sizeof(c->ba)); c->net.name = "ether"; c->net.nconv = NPktype; c->net.devp = &info; c->net.protop = 0; c->net.listen = 0; c->net.clone = clonecon; c->net.ninfo = 2; c->net.prot = c->prot; c->net.info[0].name = "stats"; c->net.info[0].fill = statsfill; c->net.info[1].name = "type"; c->net.info[1].fill = typefill; } static int isinput(void *arg) { Ctlr *c = arg; return 0; } static void etherkproc(void *arg) { Ctlr *c = arg; if(waserror()){ print("someone noted %s\n", c->name); c->kproc = 0; nexterror(); } c->kproc = 1; for(;;){ sleep(&c->rr, isinput, c); } } void etherinit(void) { int ctlrno = 0; /* * put the receiver online * and start the kproc */ outb(c->iobase+Cr, 0x22); /* Page0, RD2|STA */ outb(c->iobase+Tpsr, 0); if(ctlr[ctlrno].kproc == 0){ sprint(ctlr[ctlrno].name, "ether%dkproc", ctlrno); kproc(ctlr[ctlrno].name, etherkproc, &ctlr[ctlrno]); } } Chan * etherattach(char *spec) { return devattach('l', spec); } Chan * etherclone(Chan *c, Chan *nc) { return devclone(c, nc); } int etherwalk(Chan *c, char *name) { return netwalk(c, name, &ctlr[0].net); } void etherstat(Chan *c, char *dp) { netstat(c, dp, &ctlr[0].net); } Chan * etheropen(Chan *c, int omode) { return netopen(c, omode, &ctlr[0].net); } void ethercreate(Chan *c, char *name, int omode, ulong perm) { error(Eperm); } void etherremove(Chan *c) { error(Eperm); } void etherwstat(Chan *c, char *dp) { netwstat(c, dp, &ctlr[0].net); } void etherclose(Chan *c) { if(c->stream) streamclose(c); } long etherread(Chan *c, void *a, long n, ulong offset) { return netread(c, a, n, offset, &ctlr[0].net); } long etherwrite(Chan *c, char *a, long n, ulong offset) { return streamwrite(c, a, n, 0); } . ## diffname pc/devether.c 1992/0404 ## diff -e /n/bootesdump/1992/0403/sys/src/9/safari/devether.c /n/bootesdump/1992/0404/sys/src/9/safari/devether.c 428,429c outb(ctlr[ctlrno].iobase+Tcr, 0); . 415c sleep(&cp->rr, isinput, cp); while(bp = getq(&cp->rq)){ cp->inpackets++; etherup(cp, (Etherpkt*)bp->rptr, BLEN(bp)); freeb(bp); } #ifdef foo bnry = inb(cp->iobase+Bnry); while(bnry != cp->curr){ rp = &((Ring *)RAMbase)[bnry]; } #endif . 413c cp->kproc = 1; . 409,410c print("%s noted\n", cp->name); init(cp); cp->kproc = 0; . 406c Ctlr *cp = arg; Block *bp; uchar bnry, curr; Ring *rp; . 400c return cp->bnry != cp->curr; . 398c Ctlr *cp = arg; . 394a static void etherup(Ctlr *cp, Etherpkt *p, int len) { Block *bp; Pktype *pp; int t; t = (p->type[0]<<8) | p->type[1]; for(pp = &cp->pktype[0]; pp < &cp->pktype[NPktype]; pp++){ /* * check before locking just to save a lock */ if(pp->q == 0 || (t != pp->type && pp->type != -1)) continue; /* * only a trace channel gets packets destined for other machines */ if(pp->type != -1 && p->d[0] != 0xFF && memcmp(p->d, cp->ea, sizeof(p->d))) continue; /* * check after locking to make sure things didn't * change under foot */ if(canqlock(pp) == 0) continue; if(pp->q == 0 || pp->q->next->len > Streamhi || (t != pp->type && pp->type != -1)){ qunlock(pp); continue; } if(waserror() == 0){ bp = allocb(len); memmove(bp->rptr, (uchar *)p, len); bp->wptr += len; bp->flags |= S_DELIM; PUTNEXT(pp->q, bp); } poperror(); qunlock(pp); } } . 381,392c cp->net.name = "ether"; cp->net.nconv = NPktype; cp->net.devp = &info; cp->net.protop = 0; cp->net.listen = 0; cp->net.clone = clonecon; cp->net.ninfo = 2; cp->net.prot = cp->prot; cp->net.info[0].name = "stats"; cp->net.info[0].fill = statsfill; cp->net.info[1].name = "type"; cp->net.info[1].fill = typefill; . 377,379c for(i = 0; i < sizeof(cp->ea); i++) cp->ea[i] = inb(cp->iobase+EA+i); memset(cp->ba, 0xFF, sizeof(cp->ba)); . 373,374c cp->iobase = IObase; init(cp); . 370c Ctlr *cp = &ctlr[0]; . 361,364c outb(cp->iobase+Cr, 0x61); /* Page1, RD2|STP */ for(i = 0; i < sizeof(cp->ea); i++) outb(cp->iobase+Par0+i, cp->ea[i]); outb(cp->iobase+Curr, 6); /* 6*256 */ cp->curr = 6; outb(cp->iobase+Cr, 0x22); /* Page0, RD2|STA */ outb(cp->iobase+Tpsr, 0); . 349,359c outb(cp->iobase+Cr, 0x21); /* Page0, RD2|STP */ outb(cp->iobase+Dcr, 0x48); /* FT1|LS */ outb(cp->iobase+Rbcr0, 0); outb(cp->iobase+Rbcr1, 0); outb(cp->iobase+Rcr, 0x04); /* AB */ outb(cp->iobase+Tcr, 0x20); /* LB0 */ outb(cp->iobase+Bnry, 6); cp->bnry = 6; outb(cp->iobase+Pstart, 6); /* 6*256 */ outb(cp->iobase+Pstop, 32); /* 8*1024/256 */ outb(cp->iobase+Isr, 0xFF); outb(cp->iobase+Imr, 0x1F); /* OVWE|TXEE|RXEE|PTXE|PRXE */ . 345c init(Ctlr *cp) . 342c * we leave the chip idling on internal loopback . 336c Ctlr *cp = &ctlr[0]; uchar isr, curr; outb(cp->iobase+Cr, 0x22); /* Page0, RD2|STA */ while(isr = inb(cp->iobase+Isr)){ outb(cp->iobase+Isr, isr); if(isr & Txe) cp->oerrs++; if(isr & Rxe){ cp->frames += inb(cp->iobase+Cntr0); cp->crcs += inb(cp->iobase+Cntr1); cp->buffs += inb(cp->iobase+Cntr2); } if(isr & Ptx) cp->outpackets++; if(isr & (Txe|Ptx)){ panic("tx intr\n"); } /* * the receive ring is full. * put the NIC into loopback mode to give * kproc a chance to process some packets. */ if(isr & Ovw){ outb(cp->iobase+Cr, 0x21); /* Page0, RD2|STP */ outb(cp->iobase+Rbcr0, 0); outb(cp->iobase+Rbcr1, 0); while((inb(cp->iobase+Isr) & Rst) == 0) delay(1); outb(cp->iobase+Tcr, 0x20); /* LB0 */ outb(cp->iobase+Cr, 0x22); /* Page0, RD2|STA */ cp->ovw = 1; } /* * we have received packets. * this is the only place, other than the init code, * where we set the controller to Page1. * we must be careful to reset it back to Page0 in case * we interrupted some other part of this driver. */ if(isr & (Ovw|Prx)){ outb(cp->iobase+Cr, 0x62); /* Page1, RD2|STA */ cp->curr = inb(cp->iobase+Curr); outb(cp->iobase+Cr, 0x22); /* Page0, RD2|STA */ wakeup(&cp->rr); } } . 328,329c pp = &ctlr[0].pktype[STREAMID(c->qid.path)]; sprint(buf, "%d", pp->type); . 326c Pktype *pp; . 316,318c cp->inpackets, cp->outpackets, cp->crcs, cp->overflows, cp->frames, cp->buffs, cp->oerrs, cp->ea[0], cp->ea[1], cp->ea[2], cp->ea[3], cp->ea[4], cp->ea[5]); . 312c Ctlr *cp = &ctlr[0]; . 310c statsfill(Chan *c, char *p, int n) . 301,304c pp->inuse = 1; netown(&cp->net, pp - cp->pktype, u->p->user, 0); qunlock(pp); return pp - cp->pktype; . 295,298c for(pp = cp->pktype; pp < &cp->pktype[NPktype]; pp++){ qlock(pp); if(pp->inuse || pp->q){ qunlock(pp); . 292,293c Ctlr *cp = &ctlr[0]; Pktype *pp; . 290c clonecon(Chan *c) . 272,278c qlock(pp); pp->type = 0; pp->q = 0; pp->prom = 0; pp->inuse = 0; netdisown(&pp->ctlr->net, pp - pp->ctlr->pktype); qunlock(pp); . 264,270c pp = (Pktype *)(q->ptr); if(pp->prom){ qlock(pp->ctlr); pp->ctlr->prom--; if(pp->ctlr->prom == 0){ outb(pp->ctlr->iobase+Cr, 0x22);/* Page0, RD2|STA */ outb(pp->ctlr->iobase+Rcr, 0x04);/* AB */ } qunlock(pp->ctlr); . 262c Pktype *pp; . 243,250c pp = &cp->pktype[s->id]; qlock(pp); RD(q)->ptr = WR(q)->ptr = pp; pp->type = 0; pp->q = RD(q); pp->inuse = 1; pp->ctlr = cp; qunlock(pp); . 240,241c Ctlr *cp = &ctlr[0]; Pktype *pp; . 228a #endif . 130a } . 129c if(c->prom == 1){ outb(t->ctlr->iobase+Cr, 0x22); /* Page0, RD2|STA */ . 119a panic("etheroput\n"); #ifdef notdef . 86c QLock xl; . 83a uchar bnry; uchar curr; uchar ovw; . 61,62c struct Ring { uchar status; uchar next; ushort len; uchar data[BUFsize-4]; . 59c /* * some register bits */ enum { Prx = 0x01, /* Isr: packet received */ Ptx = 0x02, /* packet transmitted */ Rxe = 0x04, /* receive error */ Txe = 0x08, /* transmit error */ Ovw = 0x10, /* overwrite warning */ Rst = 0x80, /* reset status */ }; . 50,57c }; . 35c Tbcr0 = NIC+0x05, /* write */ Tbcr1 = NIC+0x06, /* write */ . 28,32c Pstart = NIC+0x01, /* write */ Pstop = NIC+0x02, /* write */ Bnry = NIC+0x03, . 21a Nctlr = 1, NPktype = 9, /* types/interface */ }; /* * register offsets from IObase */ enum { . 20a RAMbase = 0xC8000, RAMsize = 8*1024, BUFsize = 256, . 17a typedef struct Ring Ring; . 4c * no more than one controller . ## diffname pc/devether.c 1992/0405 ## diff -e /n/bootesdump/1992/0404/sys/src/9/safari/devether.c /n/bootesdump/1992/0405/sys/src/9/safari/devether.c 415a * and pointing to Page0. . 414c * is mandatory. . 400c * we must be sure to reset it back to Page0 in case . 366d 296d 293,294c if(pp->ctlr->prom == 0) . 154d 151,152c if(c->prom == 1) . ## diffname pc/devether.c 1992/0406 ## diff -e /n/bootesdump/1992/0405/sys/src/9/safari/devether.c /n/bootesdump/1992/0406/sys/src/9/safari/devether.c 542,547c /* * process any received packets */ bnry = inb(cp->iobase+Bnry); while(bnry != cp->curr){ rp = &((Ring*)RAMbase)[bnry]; printpkt(bnry, rp->len, (Etherpkt*)rp->data); cp->inpackets++; etherup(cp, (Etherpkt*)rp->data, rp->len-4); bnry = rp->next; outb(cp->iobase+Bnry, bnry); } /* * if we idled input because of overflow, * restart */ if(cp->ovw){ cp->ovw = 0; outb(cp->iobase+Tcr, 0); } . 536a /* * process any internal loopback packets */ . 511a static void printpkt(uchar bnry, ushort len, Etherpkt *p) { int i; print("%.2ux: %.4d d(%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux)s(%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux)t(%.2ux %.2ux)\n", bnry, len, p->d[0], p->d[1], p->d[2], p->d[3], p->d[4], p->d[5], p->s[0], p->s[1], p->s[2], p->s[3], p->s[4], p->s[5], p->type[0], p->type[1]); } . 189a panic("etheroput\n"); #ifdef notdef . 185,186c putq(&cp->rq, nbp); wakeup(&cp->rr); . 182,183c if(nbp = expandb(nbp, len >= ETHERMINTU ? len: ETHERMINTU)){ . 179c if(memcmp(cp->ba, p->d, sizeof(cp->ba)) == 0){ . 172,175c if (bp = expandb(bp, len >= ETHERMINTU ? len: ETHERMINTU)){ putq(&cp->rq, bp); wakeup(&cp->rr); . 169,170c memmove(p->s, cp->ea, sizeof(cp->ea)); if(memcmp(cp->ea, p->d, sizeof(cp->ea)) == 0){ . 163,167c if(BLEN(bp) < ETHERHDRSIZE && (bp = pullup(bp, ETHERHDRSIZE)) == 0) return; . 148,153c pp->prom = 1; qlock(cp); cp->prom++; if(cp->prom == 1) outb(cp->iobase+Rcr, 0x14); /* PRO|AB */ qunlock(cp); . 146c pp->type = strtol((char *)bp->rptr, 0, 0); . 144c pp = q->ptr; . 140,142c cp = ((Pktype *)q->ptr)->ctlr; . 136c Pktype *pp; . 134c Ctlr *cp; . 5a * output * deal with stalling and restarting output on input overflow * fix magic ring constants . 4a * TODO: . ## diffname pc/devether.c 1992/0407 ## diff -e /n/bootesdump/1992/0406/sys/src/9/safari/devether.c /n/bootesdump/1992/0407/sys/src/9/safari/devether.c 574a wakeup(&cp->xr); . 564,566c etherup(cp, (Etherpkt*)rp->data, ((rp->len1<<8)+rp->len0)-4); cp->bnry = rp->next; outb(cp->iobase+Bnry, cp->bnry); . 559,562c cp->bnry = inb(cp->iobase+Bnry); while(cp->bnry != cp->curr){ rp = &cp->ring[cp->bnry]; . 437a cp->xpkt = (Etherpkt*)(KZERO|RAMbase); . 424a cp->ring = (Ring*)(KZERO|RAMbase); . 373c cp->xbusy = 0; wakeup(&cp->xr); . 248,250d 246c qunlock(&cp->xl); . 241,244d 235,239c outb(cp->iobase+Tbcr0, len & 0xFF); outb(cp->iobase+Tbcr1, (len>>8) & 0xFF); outb(cp->iobase+Cr, 0x26); /* Page0|TXP|STA */ cp->xbusy = 1; . 233c * start the transmission . 230c memmove(p->s, cp->ea, sizeof(cp->ea)); . 228c * give packet a local address . 225d 219c * pad the packet (zero the pad) . 201,202c sleep(&cp->xr, isxfree, cp); p = cp->xpkt; . 199c * Wait till we get an output buffer . 194c qunlock(&cp->xl); . 192c qlock(&cp->xl); . 187,188d 134a static int isxfree(void *arg) { Ctlr *cp = arg; return cp->xbusy == 0 && cp->ovw == 0; } . 111a uchar xbusy; . 109a Etherpkt *xpkt; . 108d 104a Queue rq; . 103a Ring *ring; . 82c uchar len0; uchar len1; . 9a * rewrite per SMC doc . ## diffname pc/devether.c 1992/0408 ## diff -e /n/bootesdump/1992/0407/sys/src/9/safari/devether.c /n/bootesdump/1992/0408/sys/src/9/safari/devether.c 571a . 569c bnry = rp->next; cp->bnry = PREV(bnry, 32); . 564,566c bnry = NEXT(cp->bnry, 32); while(bnry != cp->curr){ rp = &cp->ring[bnry]; . 560a . 533c return NEXT(cp->bnry, 32) != cp->curr; . 456a init(cp); setvec(Ethervec, intr); . 452,454d 437,438c cp->curr = cp->bnry+1; outb(cp->iobase+Curr, cp->curr); . 427a outb(cp->iobase+Bnry, cp->bnry); . 426d 391a cp->overflows++; . 34a #define NEXT(x, l) ((((x)+1)%(l)) == 0 ? 6: (((x)+1)%(l))) #define PREV(x, l) (((x)-1) == 5 ? (l-1): ((x)-1)) . ## diffname pc/devether.c 1992/0409 ## diff -e /n/bootesdump/1992/0408/sys/src/9/safari/devether.c /n/bootesdump/1992/0409/sys/src/9/safari/devether.c 670a } void etherdump(void) { Ctlr *cp = &ctlr[0]; uchar bnry, curr, isr; int s; s = splhi(); bnry = inb(cp->iobase+Bnry); outb(cp->iobase+Cr, 0x62); /* Page1, RD2|STA */ curr = inb(cp->iobase+Curr); outb(cp->iobase+Cr, 0x22); /* Page0, RD2|STA */ 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); print("\t%d %d %d %d %d %d %d\n", cp->inpackets, cp->opackets, cp->crcs, cp->oerrs, cp->frames, cp->overflows, cp->buffs); splx(s); . 577,586d 455a msr = 0x40|inb(cp->iobase); outb(cp->iobase, msr); for(i = 0; i < 0x10; i++) print("#%2.2ux ", inb(cp->iobase+i)); print("\n"); . 453a uchar msr; . 406a if(cp->curr == 0) print("C0: b%d i%ux\n", cp->bnry, isr); . 396d 381,394c if(isr & Ovw) . 148c return cp->xbusy == 0; . 114d ## diffname pc/devether.c 1992/0410 ## diff -e /n/bootesdump/1992/0409/sys/src/9/safari/devether.c /n/bootesdump/1992/0410/sys/src/9/safari/devether.c 671c print("\t%d %d %d %d %d %d %d\n", cp->inpackets, cp->outpackets, . 663a debug++; . 567c cp->bnry = PREV(bnry, RINGsize); . 565c 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)); . 561c bnry = NEXT(cp->bnry, RINGsize); . 554c etherup(cp, bp->rptr, BLEN(bp), 0, 0); . 538a int len0, len1; . 529c return NEXT(cp->bnry, RINGsize) != cp->curr; . 508c qunlock(tp); . 505c PUTNEXT(tp->q, bp); . 501,503c bp = allocb(len0+len1); memmove(bp->rptr, d0, len0); if(len1) memmove(bp->rptr+len0, d1, len1); bp->wptr += len0+len1; . 496,497c if(tp->q == 0 || tp->q->next->len > Streamhi || (t != tp->type && tp->type != -1)){ qunlock(tp); . 494c if(canqlock(tp) == 0) . 487c if(tp->type != -1 && p->d[0] != 0xFF && memcmp(p->d, cp->ea, sizeof(p->d))) . 481c if(tp->q == 0 || (t != tp->type && tp->type != -1)) . 476,477c p = (Etherpkt*)d0; t = (p->type[0]<<8)|p->type[1]; for(tp = &cp->type[0]; tp < &cp->type[NType]; tp++){ . 473c Type *tp; . 471a Etherpkt *p; . 470c etherup(Ctlr *cp, uchar *d0, int len0, uchar *d1, int len1) . 456c cp->net.nconv = NType; . 448a msr=0x40|inb(cp->iobase+0x05); outb(cp->iobase+0x05, msr); . 445a msr=0x40|inb(cp->iobase+0x05); outb(cp->iobase+0x05, msr); . 420,421c outb(cp->iobase+Pstart, RINGbase); outb(cp->iobase+Pstop, RINGsize); . 417c cp->bnry = RINGbase; . 394a if(debug) print("I%d/%d/%d|", isr, cp->curr, cp->bnry); . 392,393d 389c if(isr & (Rxe|Prx)){ . 380,381c if(isr & Ovw){ bnry = inb(cp->iobase+Bnry); outb(cp->iobase+bnry, bnry); cp->buffs++; } . 372c cp->overflows += inb(cp->iobase+Cntr2); . 363c uchar isr, bnry, curr; . 354,355c tp = &ctlr[0].type[STREAMID(c->qid.path)]; sprint(buf, "%d", tp->type); . 352c Type *tp; . 327,330c tp->inuse = 1; netown(&cp->net, tp - cp->type, u->p->user, 0); qunlock(tp); return tp - cp->type; . 321,324c for(tp = cp->type; tp < &cp->type[NType]; tp++){ qlock(tp); if(tp->inuse || tp->q){ qunlock(tp); . 319c Type *tp; . 298,304c qlock(tp); tp->type = 0; tp->q = 0; tp->prom = 0; tp->inuse = 0; netdisown(&tp->ctlr->net, tp - tp->ctlr->type); qunlock(tp); . 290,296c 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); . 288c Type *tp; . 269,276c 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); . 267c Type *tp; . 165c tp->prom = 1; . 163c tp->type = strtol((char *)bp->rptr, 0, 0); . 161c tp = q->ptr; . 159c cp = ((Type *)q->ptr)->ctlr; . 155c Type *tp; . 130c Netprot prot[NType]; . 122c Type type[NType]; . 94c struct Type { . 80d 35,36c #define NEXT(x, l) ((((x)+1)%(l)) == 0 ? RINGbase: (((x)+1)%(l))) #define PREV(x, l) (((x)-1) < RINGbase ? (l-1): ((x)-1)) . 32c NType = 9, /* types/interface */ . 30a RINGbase = 6, /* gak */ RINGsize = 32, /* gak */ . 27c RAMbase = 0xD0000, . 22c typedef struct Type Type; . 20a static int debug; . ## diffname pc/devether.c 1992/0411 ## diff -e /n/bootesdump/1992/0410/sys/src/9/safari/devether.c /n/bootesdump/1992/0411/sys/src/9/safari/devether.c 686c consdebug(void) . 517c xmemmove(bp->rptr+len0, d1, len1); . 515c xmemmove(bp->rptr, d0, len0); . 458,459d 451,454c reg = 0x40|inb(cp->iobase); outb(cp->iobase, reg); reg = 0x40|inb(cp->iobase+0x05); outb(cp->iobase+0x05, reg); . 448c uchar reg; . 246a xmemmove(cp->xpkt, p, len); . 218,219c tsleep(&cp->xr, isxfree, cp, 1000); if(isxfree(cp) == 0) print("Tx wedged\n"); p = &txpkt; . 210a freeb(bp); . 145a static Etherpkt txpkt; static void xmemmove(void *to, void *from, long len) { ushort *t, *f; int s; Ctlr *cp = &ctlr[0]; uchar reg; t = to; f = from; len = (len+1)/2; s = splhi(); reg = inb(cp->iobase+0x05); outb(cp->iobase+Imr, 0); outb(cp->iobase+0x05, 0x80|reg); while(len--) *t++ = *f++; outb(cp->iobase+0x05, reg); outb(cp->iobase+Imr, 0x1F); splx(s); } . 29c RAMbase = 0xC8000, . ## diffname pc/devether.c 1992/0424 ## diff -e /n/bootesdump/1992/0411/sys/src/9/safari/devether.c /n/bootesdump/1992/0424/sys/src/9/safari/devether.c 714,729d 710a static Hw wd8013 = { 0x360, /* I/O base address */ KZERO|0xC8000, /* shared memory address */ 8*1024, /* shared memory size */ wd8013reset, wd8013init, wd8013mode, wd8013online, wd8013receive, wd8013transmit, wd8013intr, }; . 708c Ctlr *cp = &ctlr[0]; Hw *hw = cp->hw; Buffer *tb; uchar isr; while(isr = IN(hw, r.isr)){ OUT(hw, w.isr, isr); if(isr & 0x08) /* Txe - transmit error */ cp->oerrs++; if(isr & 0x04){ /* Rxe - receive error */ cp->frames += IN(hw, r.cntr0); cp->crcs += IN(hw, r.cntr1); cp->buffs += IN(hw, r.cntr2); } if(isr & 0x02) /* Ptx - packet transmitted */ cp->outpackets++; /* * a packet completed transmission, successfully or * not. start transmission on the next buffered packet, * and wake the output routine. */ if(isr & (0x08|0x02)){ tb = &cp->tb[cp->ti]; tb->owner = Host; tb->busy = 0; cp->ti = NEXT(cp->ti, Ntb); (*cp->hw->transmit)(cp); wakeup(&cp->tr); } if(isr & 0x10) /* Ovw - overwrite warning */ cp->overflows++; /* * we have received packets. */ if(isr & (0x04|0x01)){ /* Rxe|Prx - packet received */ (*cp->hw->receive)(cp); wakeup(&cp->rr); } } . 705,706c static void wd8013intr(Ureg *ur) . 702c Hw *hw; Buffer *tb; int s; print("transmit\n"); s = splhi(); tb = &cp->tb[cp->ti]; if(tb->busy == 0 && tb->owner == Interface){ hw = cp->hw; print("transmit memove %lux %lux, %d\n", hw->ram, &tb->pkt, tb->len); memmove(hw->ram, &tb->pkt, tb->len); OUT(hw, w.tbcr0, tb->len & 0xFF); OUT(hw, w.tbcr1, (tb->len>>8) & 0xFF); OUT(hw, w.cr, 0x26); /* Page0|RD2|TXP|STA */ tb->busy = 1; } splx(s); print("transmit done\n"); . 699,700c static void wd8013transmit(Ctlr *cp) . 695,696c Hw *hw = cp->hw; Buffer *rb; uchar bnry, curr, next; typedef struct Ring { uchar status; uchar next; uchar len0; uchar len1; uchar data[256-4]; } Ring; Ring *p; int len; bnry = IN(hw, r.bnry); next = NEXT(bnry, HOWMANY(hw->ramsz, 256)); if(next == 0) next = HOWMANY(sizeof(Etherpkt), 256); for(;;){ OUT(hw, w.cr, 0x62); /* Page1|RD2|STA */ curr = IN(hw, curr); OUT(hw, w.cr, 0x22); /* Page0|RD2|STA */ if(next == curr) break; cp->inpackets++; p = &((Ring*)hw->ram)[next]; len = (p->len1<<8)|p->len0; rb = &cp->rb[cp->ri]; if(rb->owner == Interface){ rb->len = len; /*copy in packet*/ rb->owner = Host; cp->ri = NEXT(cp->ri, Nrb); } next = p->next; bnry = next-1; if(bnry < HOWMANY(sizeof(Etherpkt), 256)) bnry = HOWMANY(hw->ramsz, 256)-1; OUT(hw, w.bnry, bnry); } . 692,693c static void wd8013receive(Ctlr *cp) . 689c OUT(cp->hw, w.tcr, 0); . 686,687c static void wd8013online(Ctlr *cp, int on) . 683c qlock(cp); if(on){ cp->prom++; if(cp->prom == 1) OUT(cp->hw, w.rcr, 0x14);/* PRO|AB */ } else { cp->prom--; if(cp->prom == 0) OUT(cp->hw, w.rcr, 0x04);/* AB */ } qunlock(cp); . 681c wd8013mode(Ctlr *cp, int on) . 677c Hw *hw = cp->hw; int i; uchar bnry; print("init %d %d\n", HOWMANY(sizeof(Etherpkt), 256), HOWMANY(hw->ramsz, 256)); OUT(hw, w.cr, 0x21); /* Page0|RD2|STP */ OUT(hw, w.dcr, 0x48); /* FT1|LS */ OUT(hw, w.rbcr0, 0); OUT(hw, w.rbcr1, 0); OUT(hw, w.rcr, 0x04); /* AB */ OUT(hw, w.tcr, 0x20); /* LB0 */ bnry = HOWMANY(sizeof(Etherpkt), 256); OUT(hw, w.bnry, bnry); OUT(hw, w.pstart, bnry); OUT(hw, w.pstop, HOWMANY(hw->ramsz, 256)); OUT(hw, w.isr, 0xFF); OUT(hw, w.imr, 0x1F); /* OVWE|TXEE|RXEE|PTXE|PRXE */ OUT(hw, w.cr, 0x61); /* Page1|RD2|STP */ for(i = 0; i < sizeof(cp->ea); i++) OUT(hw, par[i], cp->ea[i]); OUT(hw, curr, bnry+1); OUT(hw, w.cr, 0x22); /* Page0|RD2|STA */ OUT(hw, w.tpsr, 0); . 674,675c /* * we leave the chip idling on internal loopback * and pointing to Page0. */ static void wd8013init(Ctlr *cp) . 672a print("\n"); } for(i = 0; i < sizeof(cp->ea); i++) cp->ea[i] = IN(hw, lan[i]); (*hw->init)(cp); setvec(Ethervec, hw->intr); } . 671c int addr = hw->addr; for(i = 0; i < 16; i++){ print("#%2.2ux ", inb(addr)); addr++; . 668,669c print("reset\n"); cp->rb = ialloc(sizeof(Buffer)*Nrb, 0); cp->nrb = Nrb; cp->tb = ialloc(sizeof(Buffer)*Ntb, 0); cp->ntb = Ntb; msr = IN(hw, msr); OUT(hw, msr, 0x40|msr); . 665,666c Hw *hw = cp->hw; int i; uchar msr; . 662,663c #define IN(hw, m) inb((hw)->addr+OFFSETOF(Wd8013, m)) #define OUT(hw, m, x) outb((hw)->addr+OFFSETOF(Wd8013, m), (x)) /* */ static void wd8013reset(Ctlr *cp) . 656,660c union { /* DP8390/83C690 LAN controller */ struct { /* Page0, read */ uchar cr; uchar clda0; uchar clda1; uchar bnry; uchar tsr; uchar ncr; uchar fifo; uchar isr; uchar crda0; uchar crda1; uchar pad0x0A; uchar pad0x0B; uchar rsr; uchar cntr0; uchar cntr1; uchar cntr2; } r; struct { /* Page0, write */ uchar cr; uchar pstart; uchar pstop; uchar bnry; uchar tpsr; uchar tbcr0; uchar tbcr1; uchar isr; uchar rsar0; uchar rsar1; uchar rbcr0; uchar rbcr1; uchar rcr; uchar tcr; uchar dcr; uchar imr; } w; struct { /* Page1, read/write */ uchar cr; uchar par[6]; uchar curr; uchar mar[8]; }; }; } Wd8013; . 650,654c typedef struct { uchar msr; /* 83C584 bus interface */ uchar icr; uchar iar; uchar bio; uchar irr; uchar laar; uchar ijr; uchar gp2; uchar lan[6]; uchar id; uchar cksum; . 642,646d 637,640c (*cp->hw->online)(cp, 1); if(cp->kproc == 0){ sprint(cp->name, "ether%dkproc", ctlrno); kproc(cp->name, etherkproc, cp); . 632a cp->rh = 0; cp->ri = 0; for(i = 0; i < cp->nrb; i++) cp->rb[i].owner = Interface; cp->th = 0; cp->ti = 0; for(i = 0; i < cp->ntb; i++) cp->tb[i].owner = Host; . 631a Ctlr *cp = &ctlr[ctlrno]; int i; . 628,629c Chan* etherattach(char *spec) . 619,625c cp->net.name = "ether"; cp->net.nconv = NType; cp->net.devp = &info; cp->net.protop = 0; cp->net.listen = 0; cp->net.clone = clonecon; cp->net.ninfo = 2; cp->net.prot = cp->prot; cp->net.info[0].name = "stats"; cp->net.info[0].fill = statsfill; cp->net.info[1].name = "type"; cp->net.info[1].fill = typefill; . 617a memset(cp->ba, 0xFF, sizeof(cp->ba)); . 616a cp->hw = &wd8013; (*cp->hw->reset)(cp); . 615c void etherreset(void) { Ctlr *cp = &ctlr[0]; . 610,613c qunlock(&cp->rlock); sleep(&cp->rr, isinput, cp); } } . 607,608c rb = &cp->rb[cp->rh]; etherup(cp, &rb->pkt, rb->len); rb->owner = Interface; cp->rh = NEXT(cp->rh, Nrb); } . 603,605c while(cp->rb[cp->rh].owner == Host){ . 596c etherup(cp, (Etherpkt*)bp->rptr, BLEN(bp)); . 594c while(bp = getq(&cp->lbq)){ . 590c qlock(&cp->rlock); . 584c (*cp->hw->init)(cp); . 578,580d 576a Buffer *rb; . 570c return cp->lbq.first || cp->rb[cp->ri].owner == Host; . 553,564d 540,544c bp = allocb(len); memmove(bp->rptr, p, len); bp->wptr += len; . 514d 394,509d 392c etherup(Ctlr *cp, Etherpkt *p, int len) . 323,329c if(tp->prom) (*tp->ctlr->hw->mode)(tp->ctlr, 0); . 285c qunlock(&cp->tlock); print("oput done\n"); . 279,282c cp->outpackets++; tb->len = len; tb->owner = Interface; cp->th = NEXT(cp->th, cp->ntb); (*cp->hw->transmit)(cp); . 276a * set up the transmit buffer and . 274d 247a tb = &cp->tb[cp->th]; p = &tb->pkt; . 243,246c print("oput sleep\n"); sleep(&cp->tr, isobuf, cp); . 241c * wait till we get an output buffer. * should try to restart. . 236c qunlock(&cp->tlock); . 233c qlock(&cp->tlock); . 225c putq(&cp->lbq, nbp); . 215c putq(&cp->lbq, bp); . 203a cp = ((Type *)q->ptr)->ctlr; . 194,198c (*tp->ctlr->hw->mode)(tp->ctlr, 1); . 187d 184a Buffer *tb; . 175c cp->tb[cp->th].owner == Host; . 171c isobuf(void *arg) . 169a long etherwrite(Chan *c, char *a, long n, ulong offset) { return streamwrite(c, a, n, 0); } void etherremove(Chan *c) { error(Eperm); } void etherwstat(Chan *c, char *dp) { netwstat(c, dp, &ctlr[0].net); } . 156,167c int etherwalk(Chan *c, char *name) { return netwalk(c, name, &ctlr[0].net); } void etherstat(Chan *c, char *dp) { netstat(c, dp, &ctlr[0].net); } Chan* etheropen(Chan *c, int omode) { return netopen(c, omode, &ctlr[0].net); } void ethercreate(Chan *c, char *name, int omode, ulong perm) { error(Eperm); } void etherclose(Chan *c) { if(c->stream) streamclose(c); } long etherread(Chan *c, void *a, long n, ulong offset) { return netread(c, a, n, offset, &ctlr[0].net); . 151,154c return devclone(c, nc); } . 148,149c Chan* etherclone(Chan *c, Chan *nc) . 146c void etherinit(void) { } . 138,142c int crcs; /* input crc errors */ int oerrs; /* output errors */ int frames; /* framing errors */ int overflows; /* packet overflows */ int buffs; /* buffering errors */ . 135a Queue lbq; /* software loopback packet queue */ . 130,132c Rendez tr; /* rendezvous for a transmit buffer */ QLock tlock; /* semaphore on tc */ ushort th; /* first transmit buffer belonging to host */ ushort ti; /* first transmit buffer belonging to interface */ Type type[NType]; uchar prom; /* true if promiscuous mode */ uchar kproc; /* true if kproc started */ char name[NAMELEN]; /* name of kproc */ . 126,128c Rendez rr; /* rendezvous for a receive buffer */ QLock rlock; /* semaphore on rc */ ushort rh; /* first receive buffer belonging to host */ ushort ri; /* first receive buffer belonging to interface */ . 124c uchar ea[6]; /* ethernet address */ uchar ba[6]; /* broadcast address */ . 119,122c ushort nrb; /* number of software receive buffers */ ushort ntb; /* number of software transmit buffers */ Buffer *rb; /* software receive buffers */ Buffer *tb; /* software transmit buffers */ . 113,117c Hw *hw; . 108c * per ethernet . 87,94d 80,84c Host = 0, /* buffer owned by host */ Interface = 1, /* buffer owned by interface */ . 76,78d 72,73c struct Buffer { uchar owner; uchar busy; ushort len; Etherpkt pkt; . 53,70c #define NEXT(x, l) (((x)+1)%(l)) #define OFFSETOF(t, m) ((unsigned)&(((t*)0)->m)) #define HOWMANY(x, y) (((x)+((y)-1))/(y)) #define ROUNDUP(x, y) (HOWMANY((x), (y))*(y)) . 50,51c Nrb = 16, /* software receive buffers */ Ntb = 4, /* software transmit buffers */ }; . 47,48c Nctlr = 1, /* even one of these is too many */ NType = 9, /* types/interface */ . 40,45d 38a static Hw wd8013; . 27,37c struct Hw { int addr; /* interface address */ void *ram; /* interface shared memory address */ int ramsz; /* interface shared memory size */ void (*reset)(Ctlr*); void (*init)(Ctlr*); void (*mode)(Ctlr*, int); void (*online)(Ctlr*, int); void (*receive)(Ctlr*); void (*transmit)(Ctlr*); void (*intr)(Ureg*); . 25c typedef struct Ctlr Ctlr; . 21,23c typedef struct Hw Hw; typedef struct Buffer Buffer; . 1,11d ## diffname pc/devether.c 1992/0425 ## diff -e /n/bootesdump/1992/0424/sys/src/9/safari/devether.c /n/bootesdump/1992/0425/sys/src/9/safari/devether.c 727a if(p->data+len0 >= (uchar*)hw->ram+hw->ramsz){ len1 = p->data+len0 - (uchar*)hw->ram+hw->ramsz; len0 = (uchar*)hw->ram+hw->ramsz - p->data; } memmove((uchar*)&rb->pkt, p->data, len0); if(len1) memmove((uchar*)&rb->pkt+len0, (uchar*)hw->ram+ROUNDUP(sizeof(Etherpkt), 256), len1); . 726c rb->len = len0; . 722c len0 = (p->len1<<8)|p->len0-4; len1 = 0; . 708c int len0, len1; . 613d 539d 512,513c void etherinit(void) . 294d 249d 182c return cp->tb[cp->th].owner == Host; . 113a return devattach('l', spec); . 111,112c Chan* etherattach(char *spec) . ## diffname pc/devether.c 1992/0501 ## diff -e /n/bootesdump/1992/0425/sys/src/9/safari/devether.c /n/bootesdump/1992/0501/sys/src/9/safari/devether.c 829a Ctlr *cp = &ctlr[0]; Hw *hw = cp->hw; Buffer *bp; uchar bnry, curr; print("th%d ti%d rh%d ri%d\n", cp->th, cp->ti, cp->rh, cp->ri); bp = &cp->tb[cp->ti]; print("t: owner %d busy %d len %d\n", bp->owner, bp->busy, bp->len); bnry = IN(hw, r.bnry); OUT(hw, w.cr, 0x62); curr = IN(hw, curr); OUT(hw, w.cr, 0x22); print("bnry %d, curr %d\n", bnry, curr); print("in %d out %d crcs %d oerrs %d frames %d overflows %d buffs %d wraps %d\n", cp->inpackets, cp->outpackets, cp->crcs, cp->oerrs, cp->frames, cp->overflows, cp->buffs, wraps); . 817c 8*1024, 0, HOWMANY(sizeof(Etherpkt), 256), HOWMANY(8*1024, 256), . 767d 759,760c tb->len = tb->len+1 & ~1; memmove(hw->ram, tb->pkt, tb->len); . 754d 741,742c if(bnry < hw->pstart) bnry = hw->pstop-1; . 738a p->status = 0; . 730,734c memmove(rb->pkt, p->data, len); . 726,728c if(p->data+len >= hw->ram+hw->size){ wraps++; len = hw->ram+hw->size - p->data; memmove(rb->pkt+len, &((Ring*)hw->ram)[hw->pstart], p->data+rb->len - hw->ram+hw->size); . 724c rb->len = len; . 719,720c len = (p->len1<<8)|p->len0-4; if(len > sizeof(Etherpkt)) print("!"); . 708,710c next = bnry+1; if(next >= hw->pstop) next = hw->pstart; . 705c int len; . 697,703d 690a static ulong wraps; . 662c OUT(hw, curr, hw->pstart+1); . 652,655c OUT(hw, w.bnry, hw->pstart); OUT(hw, w.pstart, hw->pstart); OUT(hw, w.pstop, hw->pstop); . 644d 642d 628a . 621,626d 618,619d 614a cp->rb = ialloc(sizeof(Buffer)*Nrb, 1); cp->nrb = Nrb; . 611,613c cp->tb = ialloc(sizeof(Buffer)*Ntb, 1); . 601a typedef struct { uchar status; uchar next; uchar len0; uchar len1; uchar data[256-4]; } Ring; . 531,532c */ . 477c etherup(cp, rb->pkt, rb->len); . 467c etherup(cp, bp->rptr, BLEN(bp)); . 400a p = data; . 399a Type *tp; Block *bp; . 397,398c Etherpkt *p; . 395c etherup(Ctlr *cp, void *data, int len) . 278,282d 273c memset(tb->pkt+len, 0, ETHERMINTU-len); . 261c memmove(tb->pkt+len, nbp->rptr, n); . 253d 46c uchar pkt[sizeof(Etherpkt)]; . 17,18c uchar *ram; /* interface shared memory address */ int size; uchar tstart; uchar pstart; uchar pstop; . ## diffname pc/devether.c 1992/0502 ## diff -e /n/bootesdump/1992/0501/sys/src/9/safari/devether.c /n/bootesdump/1992/0502/sys/src/9/safari/devether.c 823,840d 788c cp->ti = NEXT(cp->ti, cp->ntb); . 750d 730c p->status = 0; . 727c cp->ri = NEXT(cp->ri, cp->nrb); . 723c (p->data+rb->len) - (hw->ram+hw->size)); . 717,719c if((p->data+len) >= (hw->ram+hw->size)){ . 711,712d 687,688d 620a cp->tb = ialloc(sizeof(Buffer)*Ntb, 1); cp->ntb = Ntb; . 617,618d 478c cp->rh = NEXT(cp->rh, cp->nrb); . ## diffname pc/devether.c 1992/0503 ## diff -e /n/bootesdump/1992/0502/sys/src/9/safari/devether.c /n/bootesdump/1992/0503/sys/src/9/safari/devether.c 714c len = (hw->ram+hw->size) - p->data; . ## diffname pc/devether.c 1992/0505 ## diff -e /n/bootesdump/1992/0503/sys/src/9/safari/devether.c /n/bootesdump/1992/0505/sys/src/9/safari/devether.c 708c len = ((p->len1<<8)|p->len0)-4; if(p->next < hw->pstart || p->next >= hw->pstop || len < 60){ print("%d: #%2.2ux #%2.2ux #%2.2ux #%2.2ux\n", next, p->status, p->next, p->len0, p->len1); dp8390rinit(cp); return; } . 631a static void dp8390rinit(Ctlr *cp) { Hw *hw = cp->hw; OUT(hw, w.cr, 0x21); /* Page0|RD2|STP */ OUT(hw, w.bnry, hw->pstart); OUT(hw, w.cr, 0x61); /* Page1|RD2|STP */ OUT(hw, curr, hw->pstart+1); OUT(hw, w.cr, 0x22); /* Page0|RD2|STA */ } . 480,482d 459c sleep(&cp->rr, isinput, cp); . 335a tp->ctlr = 0; . 91c QLock tlock; /* semaphore on th */ . 86d ## diffname pc/devether.c 1992/0506 ## diff -e /n/bootesdump/1992/0505/sys/src/9/safari/devether.c /n/bootesdump/1992/0506/sys/src/9/safari/devether.c 720a panic("receive"); . 719c print("%d/%d : #%2.2ux #%2.2ux #%2.2ux #%2.2ux\n", next, len, . ## diffname pc/devether.c 1992/0625 ## diff -e /n/bootesdump/1992/0506/sys/src/9/safari/devether.c /n/bootesdump/1992/0625/sys/src/9/safari/devether.c 616c cp->tb = xspanalloc(sizeof(Buffer)*Ntb, BY2PG, 0); . 614c cp->rb = xspanalloc(sizeof(Buffer)*Nrb, BY2PG, 0); . 504a for(i = 0; i < NType; i++) netadd(&cp->net, &cp->type[i], i); . 500d 487a cp = &ctlr[0]; . 486c int i; Ctlr *cp; . 360c netown(tp, u->p->user, 0); . 334c netdisown(tp); . 99d 61a Netprot; /* stat info */ . ## diffname pc/devether.c 1992/0711 ## diff -e /n/bootesdump/1992/0625/sys/src/9/safari/devether.c /n/bootesdump/1992/0711/sys/src/9/safari/devether.c 779a USED(ur); . 695a USED(on); . 372a USED(c); . 364a return 0; . 352a USED(c); . 170a USED(c); . 164a USED(offset); . 145a USED(c, name, omode, perm); . ## diffname pc/devether.c 1992/0905 ## diff -e /n/bootesdump/1992/0808/sys/src/9/safari/devether.c /n/bootesdump/1992/0905/sys/src/9/pc/devether.c 839,843d 826c KZERO|0xF0000, /* shared memory address */ . 770c bmemmove(hw->ram, tb->pkt, tb->len); . 756a print(">"); . 751a OUT(hw, laar, 0x01); print("?"); . 745c bmemmove(rb->pkt, p->data, len); . 741c bmemmove(rb->pkt+len, . 733c break; . 731c OUT(hw, laar, 0x01); . 726a { int ii; for(ii = 0; ii < 30; ii++) print("%2.2ux ", p->data[ii]); for(;;); } . 725a print("*"); OUT(hw, laar, 0xC1); print("!"); . 706a bmemmove(void *a, void *b, int n) { uchar *to, *from; to = a; from = b; while(n-- > 0) *to++ = *from++; } static void . 633a /* get configuration info from card */ ram = (IN(hw, msr) & 0x3f) << 13; ram |= KZERO|0x80000; hw->ram = (uchar*)ram; print("ether ram is at %lux\n", ram); . 629c OUT(hw, msr, MENB|msr); . 621a ulong ram; . 613a static void wd8013dumpregs(Hw *hw) { print("msr=#%2.2ux\n", IN(hw, msr)); print("icr=#%2.2ux\n", IN(hw, icr)); print("iar=#%2.2ux\n", IN(hw, iar)); print("bio=#%2.2ux\n", IN(hw, bio)); print("irr=#%2.2ux\n", IN(hw, irr)); print("laar=#%2.2ux\n", IN(hw, laar)); print("ijr=#%2.2ux\n", IN(hw, ijr)); print("gp2=#%2.2ux\n", IN(hw, gp2)); print("lan0=#%2.2ux\n", IN(hw, lan[0])); print("lan1=#%2.2ux\n", IN(hw, lan[1])); print("lan2=#%2.2ux\n", IN(hw, lan[2])); print("lan3=#%2.2ux\n", IN(hw, lan[3])); print("lan4=#%2.2ux\n", IN(hw, lan[4])); print("lan5=#%2.2ux\n", IN(hw, lan[5])); print("id=#%2.2ux\n", IN(hw, id)); } . 602a enum { MENB = 0x40, /* memory enable */ L16EN = 0x40, /* enable 16-bit LAN operation */ M16EN = 0x80, /* enable 16-bit memory access */ }; . ## diffname pc/devether.c 1992/0906 ## diff -e /n/bootesdump/1992/0905/sys/src/9/pc/devether.c /n/bootesdump/1992/0906/sys/src/9/pc/devether.c 883c 0, . 881a 0, 0, 0, 0, . 879,880d 822,823c memmove(hw->ram, tb->pkt, tb->len); . 819a hw = cp->hw; . 809d 802,803d 795c memmove(rb->pkt, p->data, len); . 791c memmove(rb->pkt+len, . 781d 776d 772,774d 742,752d 696c if(hw->bt16) OUT(hw, w.dcr, 0x49); /* 16 bit interface, DMA burst size 8 */ else OUT(hw, w.dcr, 0x48); /* FT1|LS */ . 670c setvec(Int0vec + hw->lvl, hw->intr); . 668a /* interrupt level */ hw->lvl = intrmap[((irr>>5) & 0x3) | (icr & 0x4)]; /* ram size */ if(icr&(1<<3)) hw->size = 32*1024; else hw->size = 8*1024; if(hw->bt16) hw->size <<= 1; hw->pstop = HOWMANY(hw->size, 256); print("ether width %d addr %lux size %d lvl %d\n", hw->bt16?16:8, hw->ram, hw->size, hw->lvl); /* enable interface RAM, set interface width */ OUT(hw, msr, MENB|msr); if(hw->bt16) OUT(hw, laar, laar|L16EN|M16EN); . 667d 663,665c /* 16 bit operation? */ hw->bt16 = icr & 0x1; /* address of interface RAM */ ram = KZERO | ((msr & 0x3f) << 13); if(hw->bt16) ram |= (laar & 0x3f)<<19; else ram |= 0x80000; . 659a /* ethernet address */ . 658c icr = IN(hw, icr); irr = IN(hw, irr); laar = IN(hw, laar); . 649a uchar icr; uchar laar; uchar irr; . 642a * get configuration parameters, enable memory . 641a /* mapping from configuration bits to interrupt level */ int intrmap[] = { 9, 3, 5, 7, 10, 11, 15, 4, }; . 17a int bt16; /* true if a 16 bit interface */ int lvl; /* interrupt level */ . ## diffname pc/devether.c 1992/0909 ## diff -e /n/bootesdump/1992/0906/sys/src/9/pc/devether.c /n/bootesdump/1992/0909/sys/src/9/pc/devether.c 916a wd8013tweek, 0x360, /* I/O base address */ . 911c dp8390init, . 901,909c static Hw wd8013 = { . 898a if(hw->bt16){ OUT(hw, laar, laar); OUT(hw, w.imr, 0x1F); } . 863a if(hw->bt16){ laar = IN(hw, laar); OUT(hw, w.imr, 0x0); OUT(hw, laar, laar|M16EN); } . 862c uchar isr, laar; . 851a if(hw->bt16 && (laar&M16EN)==0){ OUT(hw, laar, laar); OUT(hw, w.imr, 0x1F); } . 846a if(hw->bt16){ OUT(hw, w.imr, 0x0); laar = IN(hw, laar); OUT(hw, laar, laar|M16EN); } . 841a uchar laar; . 808c p->status, p->next, p->len0, p->len1);/**/ . 730c dp8390init(Ctlr *cp) . 713a wd8013tweek(Ctlr *cp) { uchar laar, msr; Hw *hw = cp->hw; Buffer *tb; int s; s = splhi(); msr = IN(hw, msr); if(msr & MENB){ splx(s); return; } print("TWEEK\n"); delay(500); /* reset the hardware */ OUT(hw, msr, MENB|msr); laar = IN(hw, laar); if(hw->bt16) OUT(hw, laar, laar|L16EN); (*hw->init)(cp); (*cp->hw->online)(cp, 1); /* retransmit the current packet */ tb = &cp->tb[cp->ti]; if(tb->owner == Interface){ tb->busy = 0; (*cp->hw->transmit)(cp); } splx(s); } static void . 707c OUT(hw, laar, laar|L16EN); . 698a hw->pstart = HOWMANY(sizeof(Etherpkt), 256); . 623d 467c tsleep(&cp->rr, isinput, cp, 1000); (*cp->hw->tweek)(cp); . 24,30d 15a void (*reset)(Ctlr*); void (*init)(Ctlr*); void (*mode)(Ctlr*, int); void (*online)(Ctlr*, int); void (*receive)(Ctlr*); void (*transmit)(Ctlr*); void (*intr)(Ureg*); void (*tweek)(Ctlr*); . ## diffname pc/devether.c 1992/0913 ## diff -e /n/bootesdump/1992/0909/sys/src/9/pc/devether.c /n/bootesdump/1992/0913/sys/src/9/pc/devether.c 965d 716,749d 468,469c sleep(&cp->rr, isinput, cp); . 23d ## diffname pc/devether.c 1992/0915 ## diff -e /n/bootesdump/1992/0913/sys/src/9/pc/devether.c /n/bootesdump/1992/0915/sys/src/9/pc/devether.c 928a wd8013tweek, . 914,917d 874,878d 872c uchar isr; . 858,861d 848,852d 842d 832a break; . 808a delay(100); . 807c /* print("%d/%d : #%2.2ux #%2.2ux #%2.2ux #%2.2ux\n", next, len, . 784a wd8013tweek(Ctlr *cp) { uchar msr; Hw *hw = cp->hw; int s; s = splhi(); msr = IN(hw, msr); if((msr & MENB) == 0){ /* board has reset itself, start again */ delay(100); (*hw->reset)(cp); etherinit(); wakeup(&cp->tr); wakeup(&cp->rr); } splx(s); } static void . 742c if(cp->prom) OUT(hw, w.rcr, 0x14); /* PRO|AB */ else OUT(hw, w.rcr, 0x04); /* AB */ . 737c OUT(hw, w.dcr, 0x61); /* 16 bit interface */ . 707c OUT(hw, laar, laar|L16EN|M16EN); . 701,702c /* print("ether width %d addr %lux size %d lvl %d\n", hw->bt16?16:8, hw->ram, hw->size, hw->lvl);/**/ . 663,666c if(cp->rb == 0){ cp->rb = xspanalloc(sizeof(Buffer)*Nrb, BY2PG, 0); cp->nrb = Nrb; cp->tb = xspanalloc(sizeof(Buffer)*Ntb, BY2PG, 0); cp->ntb = Ntb; } . 467c tsleep(&cp->rr, isinput, cp, 500); (*cp->hw->tweek)(cp); . 22a void (*tweek)(Ctlr*); . ## diffname pc/devether.c 1992/0916 ## diff -e /n/bootesdump/1992/0915/sys/src/9/pc/devether.c /n/bootesdump/1992/0916/sys/src/9/pc/devether.c 741c OUT(hw, w.dcr, 0x01); /* 16 bit interface */ . ## diffname pc/devether.c 1992/0917 ## diff -e /n/bootesdump/1992/0916/sys/src/9/pc/devether.c /n/bootesdump/1992/0917/sys/src/9/pc/devether.c 919,927d 897a /* * we have received packets. */ if(isr & (0x04|0x01)){ /* Rxe|Prx - packet received */ (*cp->hw->receive)(cp); wakeup(&cp->rr); } if(isr & 0x10) /* Ovw - overwrite warning */ cp->overflows++; . 881c OUT(hw, w.cr, Page0|RD2|TXP|STA); . 863d 856d 842d 838d 836c /*print("%d/%d : #%2.2ux #%2.2ux #%2.2ux #%2.2ux\n", next, len, . 831a waitfordma(hw); . 829c OUT(hw, w.cr, Page0|RD2|STA); . 826,827c for(i = 0; ; i++){ OUT(hw, w.cr, Page1|RD2|STA); . 820c int i, len; . 812a /* * hack to keep away from the card's memory while it is receiving * a packet. This is only a problem on the NCR 3170 safari. * * we peek at the DMA registers and, if they are changing, wait. */ void waitfordma(Hw *hw) { uchar a,b,c; for(;;delay(10)){ a = IN(hw, r.clda0); b = IN(hw, r.clda0); if(a != b) continue; c = IN(hw, r.clda0); if(c != b) continue; break; } } . 763c OUT(hw, w.cr, Page0|RD2|STA); . 758c OUT(hw, w.cr, Page1|RD2|STP); . 741c OUT(hw, w.dcr, (1<<0)|(3<<5)); /* 16 bit interface, 12 byte DMA burst */ . 739c OUT(hw, w.cr, Page0|RD2|STP); . 726c OUT(hw, w.cr, Page0|RD2|STA); . 724c OUT(hw, w.cr, Page1|RD2|STP); . 722c OUT(hw, w.cr, Page0|RD2|STP); . 714a return 0; . 711c OUT(hw, laar, laar|L16EN|M16EN|ZeroWS16); . 672,676d 664a msr = IN(hw, msr); icr = IN(hw, icr); irr = IN(hw, irr); laar = IN(hw, laar); if(msr == 0xff || icr == 0xff || irr == 0xff || laar == 0xff) return -1; . 654c static int . 650a . 610,611c /* bit definitions for laar */ ZeroWS16 = (1<<5), /* zero wait states for 16-bit ops */ L16EN = (1<<6), /* enable 16-bit LAN operation */ M16EN = (1<<7), /* enable 16-bit memory access */ /* bit defintitions for DP8390/83C690 cr */ Page0 = (0<<6), Page1 = (1<<6), Page2 = (2<<6), RD2 = (4<<3), TXP = (1<<2), STA = (1<<1), STP = (1<<0), . 603a struct { /* Page2, read */ uchar cr; uchar pstart; uchar pstop; uchar dummy1[1]; uchar tstart; uchar next; uchar block; uchar enh; uchar dummy2[4]; uchar rcon; uchar tcon; uchar dcon; uchar intmask; } r2; struct { /* Page2, write */ uchar cr; uchar trincrl; uchar trincrh; uchar dummy1[2]; uchar next; uchar block; uchar enh; } w2; . 526a if(cp->present == 0) return; . 501c if((*cp->hw->reset)(cp) < 0){ cp->present = 0; return; } cp->present = 1; . 118a if(ctlr[0].present == 0) error(Enodev); . 79a int present; . 16c int (*reset)(Ctlr*); . ## diffname pc/devether.c 1992/0918 ## diff -e /n/bootesdump/1992/0917/sys/src/9/pc/devether.c /n/bootesdump/1992/0918/sys/src/9/pc/devether.c 1012d 905c if(strcmp(machtype, "NCRD.0") == 0) waitfordma(hw); . 754c print("elite at %lux width %d addr %lux size %d lvl %d\n", hw->addr, hw->bt16?16:8, . 726,729d 716c /* ethernet address */ for(i = 0; i < sizeof(cp->ea); i++) cp->ea[i] = IN(hw, lan[i]); /* look for an elite ether address */ if(cp->ea[0] == 0x00 && cp->ea[1] == 0x00 && cp->ea[2] == 0xC0) break; } if(hw->addr >= 0x400) . 711,714c /* find the ineterface */ SET(msr, icr, irr, laar); for(hw->addr = 0x200; hw->addr < 0x400; hw->addr += 0x20){ msr = IN(hw, msr); icr = IN(hw, icr); irr = IN(hw, irr); laar = IN(hw, laar); if((msr&0x80) || (icr&0xf0) || irr == 0xff || laar == 0xff) continue; /* nothing there */ . 705,708c uchar msr, icr, laar, irr; . 696d ## diffname pc/devether.c 1992/0922 ## diff -e /n/bootesdump/1992/0918/sys/src/9/pc/devether.c /n/bootesdump/1992/0922/sys/src/9/pc/devether.c 557,1018d 531c EtherCtlr *cp = &ctlr[ctlrno]; . 508c if(cp->present == 0) return; . 503,506c for(hw = etherhw; *hw; hw++){ cp->hw = *hw; if((*cp->hw->reset)(cp) == 0){ cp->present = 1; setvec(Int0vec + cp->hw->irq, etherintr); break; } . 500d 498a EtherCtlr *cp; EtherHw **hw; . 495a static void etherintr(Ureg *ur) { EtherCtlr *cp = &ctlr[0]; USED(ur); (*cp->hw->intr)(cp); } . 472c if(cp->hw->tweak) (*cp->hw->tweak)(cp); . 465c if(cp->hw->init) (*cp->hw->init)(cp); . 459,460c EtherCtlr *cp = arg; EtherBuf *rb; . 451c EtherCtlr *cp = arg; . 408c EtherType *tp; . 404c etherup(EtherCtlr *cp, void *data, int len) . 396c EtherType *tp; . 381c EtherCtlr *cp = &ctlr[0]; . 359,360c EtherCtlr *cp = &ctlr[0]; EtherType *tp; . 335c tp = (EtherType*)(q->ptr); . 333c EtherType *tp; . 311,312c EtherCtlr *cp = &ctlr[0]; EtherType *tp; . 227c p = (Etherpkt*)bp->rptr; . 219c cp = ((EtherType*)q->ptr)->ctlr; . 210c tp->type = strtol((char*)bp->rptr, 0, 0); . 204c EtherBuf *tb; int len, n; . 200,202c EtherCtlr *cp; EtherType *tp; . 192c EtherCtlr *cp = arg; . 48,116d 42a static struct EtherCtlr ctlr[Nctlr]; . 36,40c Nctlr = 1, . 33d 15,31c static EtherHw *etherhw[] = { ðer509, ðer80x3, 0 . 10,13c /* * Half-arsed attempt at a general top-level * ethernet driver. Needs work: * handle multiple controllers * much tidying * set ethernet address */ extern EtherHw ether509; extern EtherHw ether80x3; . ## diffname pc/devether.c 1992/0925 ## diff -e /n/bootesdump/1992/0922/sys/src/9/pc/devether.c /n/bootesdump/1992/0925/sys/src/9/pc/devether.c 373c return cp->lbq.first || cp->rb[cp->rh].owner == Host; . ## diffname pc/devether.c 1992/1015 ## diff -e /n/bootesdump/1992/0925/sys/src/9/pc/devether.c /n/bootesdump/1992/1015/sys/src/9/pc/devether.c 363d 361a poperror(); . 356c if(!waserror()){ . ## diffname pc/devether.c 1992/1222 ## diff -e /n/bootesdump/1992/1015/sys/src/9/pc/devether.c /n/bootesdump/1992/1222/sys/src/9/pc/devether.c 491a return devattach('l', spec); . 487,490c (*ctlr->board->attach)(ctlr); if(ctlr->kproc == 0){ sprint(ctlr->name, "ether%dkproc", ctlrno); ctlr->kproc = 1; kproc(ctlr->name, etherkproc, ctlr); . 484,485c * Enable the interface * and start the kproc. . 482a Chan* etherattach(char *spec) { int ctlrno = 0; Ctlr *ctlr = softctlr[ctlrno]; if(ctlr->present == 0) error(Enodev); . 478,481c ctlr->th = 0; ctlr->ti = 0; for(i = 0; i < ctlr->ntb; i++) ctlr->tb[i].owner = Host; } . 473,476c ctlr->rh = 0; ctlr->ri = 0; for(i = 0; i < ctlr->nrb; i++) ctlr->rb[i].owner = Interface; . 470c if(ctlr->present == 0) . 467c Ctlr *ctlr = softctlr[ctlrno]; . 460c netadd(&ctlr->net, &ctlr->type[i], i); . 448,458c memset(ctlr->ba, 0xFF, sizeof(ctlr->ba)); ctlr->net.name = "ether"; ctlr->net.nconv = NType; ctlr->net.devp = &info; ctlr->net.protop = 0; ctlr->net.listen = 0; ctlr->net.clone = clonecon; ctlr->net.ninfo = 2; ctlr->net.info[0].name = "stats"; ctlr->net.info[0].fill = statsfill; ctlr->net.info[1].name = "type"; ctlr->net.info[1].fill = typefill; . 446c if(ctlr->nrb == 0) ctlr->nrb = Nrb; ctlr->rb = xalloc(sizeof(RingBuf)*ctlr->nrb); if(ctlr->ntb == 0) ctlr->ntb = Ntb; ctlr->tb = xalloc(sizeof(RingBuf)*ctlr->ntb); . 444a nctlr++; . 443c if(ctlr->present == 0) . 434,439c if(softctlr[nctlr] == 0) softctlr[nctlr] = xalloc(sizeof(Ctlr)); ctlr = softctlr[nctlr]; for(board = boards; *board; board++){ ctlr->board = *board; if((*ctlr->board->reset)(ctlr) == 0){ ctlr->present = 1; /* * IRQ2 doesn't really exist, it's used to gang the interrupt * controllers together. A device set to IRQ2 will appear on * the second interrupt controller as IRQ9. */ if(ctlr->board->irq == 2) ctlr->board->irq = 9; setvec(Int0vec + ctlr->board->irq, etherintr); . 430,431c Ctlr *ctlr; Board **board; . 424c (*ctlr->board->intr)(ctlr); . 421c Ctlr *ctlr = softctlr[0]; . 414a /* * Close Types requesting it. */ if(ctlr->clist){ lock(&ctlr->clock); for(type = ctlr->clist; type; type = type->clist){ type->q = 0; wakeup(&type->cr); } ctlr->clist = 0; unlock(&ctlr->clock); } . 408,413c while(ctlr->rb[ctlr->rh].owner == Host){ ctlr->inpackets++; ring = &ctlr->rb[ctlr->rh]; etherup(ctlr, (Etherpkt*)ring->pkt, ring->len); ring->owner = Interface; ctlr->rh = NEXT(ctlr->rh, ctlr->nrb); . 406c * Process any received packets. . 399,401c while(bp = getq(&ctlr->lbq)){ ctlr->inpackets++; etherup(ctlr, (Etherpkt*)bp->rptr, BLEN(bp)); . 397c * Process any internal loopback packets. . 392,394c tsleep(&ctlr->rr, isinput, ctlr, 500); if(ctlr->board->watch) (*ctlr->board->watch)(ctlr); . 390c . 384,387c print("%s noted\n", ctlr->name); /* fix if(ctlr->board->reset) (*ctlr->board->reset)(ctlr); */ ctlr->kproc = 0; . 381a Type *type; . 379,380c Ctlr *ctlr = arg; RingBuf *ring; . 373c return ctlr->lbq.first || ctlr->rb[ctlr->rh].owner == Host || ctlr->clist; . 371c Ctlr *ctlr = arg; . 364d 361c PUTNEXT(type->q, bp); . 358c memmove(bp->rptr, pkt, len); . 352,356c if(waserror() == 0){ . 350c if(type->type != -1 && pkt->d[0] != 0xFF && (*pkt->d != *ctlr->ea || memcmp(pkt->d, ctlr->ea, sizeof(pkt->d)))) . 347,348c * Only a trace channel gets packets destined for other machines. . 344a if(t != type->type && type->type != -1) continue; if(type->q->next->len > Streamhi) continue; . 343c if(type->q == 0) . 341c * Check for open, the right type, and flow control. . 331,338c t = (pkt->type[0]<<8)|pkt->type[1]; for(type = &ctlr->type[0]; type < &ctlr->type[NType]; type++){ . 328c Type *type; . 326d 324c etherup(Ctlr *ctlr, Etherpkt *pkt, int len) . 318,319c type = &softctlr[0]->type[STREAMID(c->qid.path)]; sprint(buf, "%d", type->type); . 316c Type *type; . 306,308c ctlr->inpackets, ctlr->outpackets, ctlr->crcs, ctlr->overflows, ctlr->frames, ctlr->buffs, ctlr->oerrs, ctlr->ea[0], ctlr->ea[1], ctlr->ea[2], ctlr->ea[3], ctlr->ea[4], ctlr->ea[5]); . 301c Ctlr *ctlr = softctlr[0]; . 289,292c type->inuse = 1; netown(type, u->p->user, 0); qunlock(type); return type - ctlr->type; . 283,286c for(type = ctlr->type; type < &ctlr->type[NType]; type++){ qlock(type); if(type->inuse || type->q){ qunlock(type); . 279,280c Ctlr *ctlr = softctlr[0]; Type *type; . 255,265c if(type->prom){ qlock(ctlr); ctlr->prom--; if(ctlr->prom == 0) (*ctlr->board->mode)(ctlr, 0); qunlock(ctlr); } if(type->type == -1){ qlock(ctlr); ctlr->all--; qunlock(ctlr); } /* * Mark as closing and wait for kproc * to close us. */ lock(&ctlr->clock); type->clist = ctlr->clist; ctlr->clist = type; unlock(&ctlr->clock); wakeup(&ctlr->rr); sleep(&type->cr, isclosed, type); type->type = 0; type->prom = 0; type->inuse = 0; netdisown(type); type->ctlr = 0; . 253c Type *type = (Type*)(q->ptr); Ctlr *ctlr = type->ctlr; . 249a static int isclosed(void *arg) { return ((Type*)arg)->q == 0; } . 247,248c * The locking is to synchronize changing the ethertype with * sending packets up the stream on interrupts. . 245c * Close ether line discipline. . 234,241c type = &ctlr->type[s->id]; RD(q)->ptr = WR(q)->ptr = type; type->type = 0; type->q = RD(q); type->inuse = 1; type->ctlr = ctlr; . 231,232c Ctlr *ctlr = softctlr[0]; Type *type; . 223,226c * Open an ether line discipline. . 218c qunlock(&ctlr->tlock); . 211,215c ctlr->outpackets++; ring->len = len; ring->owner = Interface; ctlr->th = NEXT(ctlr->th, ctlr->ntb); (*ctlr->board->transmit)(ctlr); . 208,209c * Set up the transmit buffer and * start the transmission. . 203c memset(ring->pkt+len, 0, ETHERMINTU-len); . 200c * Pad the packet (zero the pad). . 193,194c } . 191c memmove(ring->pkt+len, nbp->rptr, n); . 186c * Copy message into buffer. . 183c ring = &ctlr->tb[ctlr->th]; . 181c sleep(&ctlr->tr, isobuf, ctlr); . 178c * Wait till we get an output buffer. . 173c qunlock(&ctlr->tlock); . 170c qlock(&ctlr->tlock); . 168c * Only one transmitter at a time. . 162,163c putq(&ctlr->lbq, nbp); wakeup(&ctlr->rr); . 157c if(memcmp(ctlr->ba, pkt->d, sizeof(ctlr->ba)) == 0 || ctlr->prom || ctlr->all){ . 151,153c if(bp = expandb(bp, len >= ETHERMINTU ? len: ETHERMINTU)){ putq(&ctlr->lbq, bp); wakeup(&ctlr->rr); . 147,149c pkt = (Etherpkt*)bp->rptr; memmove(pkt->s, ctlr->ea, sizeof(ctlr->ea)); if(memcmp(ctlr->ea, pkt->d, sizeof(ctlr->ea)) == 0){ . 142c * Give packet a local address, return upstream if destined for . 139,140d 134a qunlock(ctlr); . 132,133c type->prom = 1; ctlr->prom++; if(ctlr->prom == 1) (*ctlr->board->mode)(ctlr, 1); . 128,130c qlock(ctlr); if(streamparse("connect", bp)){ if(type->type == -1) ctlr->all--; type->type = strtol((char*)bp->rptr, 0, 0); if(type->type == -1) ctlr->all++; } . 126a type = q->ptr; ctlr = type->ctlr; . 120,123c Ctlr *ctlr; Type *type; Etherpkt *pkt; RingBuf *ring; . 114c return ctlr->tb[ctlr->th].owner == Host; . 112c Ctlr *ctlr = arg; . 106c netwstat(c, dp, &softctlr[0]->net); . 86c return netread(c, a, n, offset, &softctlr[0]->net); . 66c return netopen(c, omode, &softctlr[0]->net); . 60c netstat(c, dp, &softctlr[0]->net); . 54c return netwalk(c, name, &softctlr[0]->net); . 38,45d 32,36d 30c static struct Ctlr *softctlr[NCtlr]; static int nctlr; . 27c NCtlr = 1, . 22d 20c /* * The ordering here is important for those boards * using the DP8390 (WD8003, 3COM503 and NE2000) as * attempting to determine if a board is a NE2000 * cannot be done passively, so it must be last to * prevent scrogging one of the others. */ static Board *boards[] = { ðer8003, ðer503, ðer2000, . 17,18c extern Board ether8003; extern Board ether503; extern Board ether2000; extern Board ether509; . 9a #include "ether.h" . ## diffname pc/devether.c 1993/0212 ## diff -e /n/bootesdump/1992/1222/sys/src/9/pc/devether.c /n/bootesdump/1993/0212/sys/src/9/pc/devether.c 554c (*ctlr->card.attach)(ctlr); . 493a print("ether%d: %s: I/O addr %lux width %d addr %lux size %d irq %d:", nctlr, ctlr->card.id, ctlr->card.io, ctlr->card.bit16 ? 16: 8, ctlr->card.ramstart, ctlr->card.ramstop-ctlr->card.ramstart, ctlr->card.irq); for(i = 0; i < sizeof(ctlr->ea); i++) print(" %2.2ux", ctlr->ea[i]); print("\n"); . 486,488c if(ctlr->card.irq == 2) ctlr->card.irq = 9; setvec(Int0vec + ctlr->card.irq, etherintr); . 476,478c for(card = cards; *card; card++){ memset(ctlr, 0, sizeof(Ctlr)); ctlr->card = **card; if((*ctlr->card.reset)(ctlr) == 0){ . 472a if(nctlr >= NCtlr) return; . 470c Card **card; . 463c (*ctlr->card.intr)(ctlr); . 419,420c if(ctlr->card.watch) (*ctlr->card.watch)(ctlr); . 410,411c if(ctlr->card.reset) (*ctlr->card.reset)(ctlr); . 270c (*ctlr->card.mode)(ctlr, 0); . 227a freeb(bp); . 226d 224c (*ctlr->card.transmit)(ctlr); splx(s); . 220c s = splhi(); . 191c if(isobuf(ctlr) == 0){ tsleep(&ctlr->tr, isobuf, ctlr, 3*1000); if(isobuf(ctlr) == 0){ qunlock(&ctlr->tlock); freeb(bp); poperror(); return; } } . 183a freeb(bp); . 182d 144c (*ctlr->card.mode)(ctlr, 1); . 126c int len, n, s; . 44c /*static */struct Ctlr *softctlr[NCtlr]; . 31c static Card *cards[] = { . 25,27c * The ordering here is important for those cards * using the DP8390 (WD8003, 3Com503 and NE2000) as * attempting to determine if a card is a NE2000 . 19,22c extern Card ether8003, ether503, ether2000; extern Card ether509; . 17a * need a ctl file passed down to card drivers * so we can set options. . ## diffname pc/devether.c 1993/1113 ## diff -e /n/bootesdump/1993/0212/sys/src/9/pc/devether.c /n/fornaxdump/1993/1113/sys/src/brazil/pc/devether.c 581c if(ctlr) free(ctlr); . 517,579c ether[ctlrno] = ctlr; ctlr = 0; } . 515c netifinit(ctlr, "ether", Ntypes, 32*1024); ctlr->alen = Eaddrlen; memmove(ctlr->addr, ctlr->ea, sizeof(ctlr->ea)); memmove(ctlr->bcast, etherbcast, sizeof(etherbcast)); . 507,513c print("ether%d: %s: port %lux irq %d addr %lux size %d:", ctlrno, ctlr->type, ctlr->port, ctlr->irq, ctlr->mem, ctlr->size); for(i = 0; i < sizeof(ctlr->ea); i++) print(" %2.2ux", ctlr->ea[i]); print("\n"); . 498,505c if(ctlr->irq == 2) ctlr->irq = 9; if((irqmask & (1<irq)) == 0){ setvec(Int0vec+ctlr->irq, etherintr); irqmask |= 1<irq; } . 496a * If there are multiple controllers on the same IRQ, only * call setvec() for one of them, etherintr() will scan through * all the controllers looking for those at the IRQ it was * called with. This is a hack, see the comments in etherintr(). . 482,491c irqmask = 0; for(ctlr = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++){ if(ctlr == 0) ctlr = malloc(sizeof(Ether)); memset(ctlr, 0, sizeof(Ether)); if(isaconfig("ether", ctlrno, ctlr) == 0) continue; for(n = 0; cards[n].type; n++){ if(strcmp(cards[n].type, ctlr->type)) continue; if((*cards[n].reset)(ctlr)) break; . 478,480c Ether *ctlr; int i, n, ctlrno; ulong irqmask; . 362,474d 357,359c if(ncard == NCARD) panic("too many ether cards"); cards[ncard].type = t; cards[ncard].reset = r; ncard++; . 354,355c static int ncard; . 342,352c void addethercard(char *t, int (*r)(Ether*)) . 336,340c #define NCARD 32 static struct { char *type; int (*reset)(Ether*); } cards[NCARD+1]; . 332,333d 292,330c irq = ur->trap-Int0vec; for(i = 0; i < MaxEther; i++){ if(ether[i] && ether[i]->irq == irq) (*ether[i]->interrupt)(ether[i]); . 289,290c * Call all ethernet interrupt routines on this IRQ. * Might be better if setvec() took an argument which * was passed down to the interrupt routine when * called. This would let us easily distinguish multiple * controllers. A hack by any other name... . 275,287d 272,273c int i, irq; . 270c etherintr(Ureg *ur) . 257,268d 240,254c return n; . 238c qunlock(&ctlr->tlock); . 186,236c n = (*ctlr->write)(ctlr, buf, n); . 183d 129,179d 119,127c if(NETTYPE(c->qid.path) != Ndataqid) return netifwrite(ctlr, c, buf, n); . 116,117c USED(offset); if(n > ETHERMAXTU) error(Ebadarg); ctlr = ether[c->dev]; . 114c Ether *ctlr; . 111,112c long etherwrite(Chan *c, void *buf, long n, ulong offset) . 108c netifwstat(ether[c->dev], c, dp); . 102d 91,97d 88c return netifread(ether[c->dev], c, buf, n, offset); . 86c etherread(Chan *c, void *buf, long n, ulong offset) . 81,82c netifclose(ether[c->dev], c); . 75d 68c return netifopen(ether[c->dev], c, omode); . 62c netifstat(ether[c->dev], c, dp); . 56c return netifwalk(ether[c->dev], c, name); . 44,45c c = devattach('l', spec); c->dev = ctlrno; if(ether[ctlrno]->attach) (*ether[ctlrno]->attach)(ether[ctlrno]); return c; } . 40,42c ctlrno = 0; if(spec && *spec){ ctlrno = strtoul(spec, &p, 0); if((ctlrno == 0 && p == spec) || *p || (ctlrno >= MaxEther)) error(Ebadarg); } if(ether[ctlrno] == 0) error(Enodev); . 36,38c Chan* etherattach(char *spec) { ulong ctlrno; char *p; Chan *c; . 24,34c void etherinit(void) { } . 12,22c static Ether *ether[MaxEther]; . 10c #include "etherif.h" . 8c #include "ureg.h" #include "../port/error.h" #include "../port/netif.h" . 6d ## diffname pc/devether.c 1993/1119 ## diff -e /n/fornaxdump/1993/1113/sys/src/brazil/pc/devether.c /n/fornaxdump/1993/1119/sys/src/brazil/pc/devether.c 152c if(ncard == MaxEther) . 145c } cards[MaxEther+1]; . 141d ## diffname pc/devether.c 1993/1120 ## diff -e /n/fornaxdump/1993/1119/sys/src/brazil/pc/devether.c /n/fornaxdump/1993/1120/sys/src/brazil/pc/devether.c 206a break; . 109a if(etherwloop(ctlr, buf, n)) return n; . 96a void etherrloop(Ether *ctlr, Etherpkt *pkt, long len) { ushort type; Netfile *f, **fp, **ep; type = (pkt->type[0]<<8)|pkt->type[1]; ep = &ctlr->f[Ntypes]; for(fp = ctlr->f; fp < ep; fp++){ f = *fp; if(f && (f->type == type || f->type < 0)){ switch(qproduce(f->in, pkt->d, len)){ case -1: print("etherrloop overflow\n"); break; case -2: print("etherrloop memory\n"); break; } } } } static int etherwloop(Ether *ctlr, Etherpkt *pkt, long len) { int s, different; different = memcmp(pkt->d, pkt->s, sizeof(pkt->s)); if(different && memcmp(pkt->d, ctlr->bcast, sizeof(pkt->d))) return 0; s = splhi(); etherrloop(ctlr, pkt, len); splx(s); return !different; } . ## diffname pc/devether.c 1993/1124 ## diff -e /n/fornaxdump/1993/1120/sys/src/brazil/pc/devether.c /n/fornaxdump/1993/1124/sys/src/brazil/pc/devether.c 233c setvec(Int0vec+ctlr->irq, ctlr->interrupt, ctlr); . 225,228d 165,183d ## diffname pc/devether.c 1994/0202 ## diff -e /n/fornaxdump/1993/1124/sys/src/brazil/pc/devether.c /n/fornaxdump/1994/0202/sys/src/brazil/pc/devether.c 106,118c if((f = *fp) && (f->type == type || f->type < 0)) qproduce(f->in, pkt->d, len); . ## diffname pc/devether.c 1994/0629 ## diff -e /n/fornaxdump/1994/0202/sys/src/brazil/pc/devether.c /n/fornaxdump/1994/0629/sys/src/brazil/pc/devether.c 117c if(different && memcmp(pkt->d, ctlr->bcast, sizeof(pkt->d)) && ctlr->prom==0 && ctlr->all==0) . ## diffname pc/devether.c 1994/0702 ## diff -e /n/fornaxdump/1994/0629/sys/src/brazil/pc/devether.c /n/fornaxdump/1994/0702/sys/src/brazil/pc/devether.c 124c return tome; . 122c etherrloop(ctlr, pkt, len, tome||bcast); . 116,118c tome = memcmp(pkt->d, ctlr->ea, sizeof(pkt->d)) == 0; bcast = memcmp(pkt->d, ctlr->bcast, sizeof(pkt->d)) == 0; if(!tome && !bcast && ctlr->prom==0 && ctlr->all==0) . 114c int s, tome, bcast; . 106c if((f = *fp) && ((tome && f->type==type) || f->type < 0)) . 98c etherrloop(Ether *ctlr, Etherpkt *pkt, long len, int tome) . ## diffname pc/devether.c 1994/0713 ## diff -e /n/fornaxdump/1994/0702/sys/src/brazil/pc/devether.c /n/fornaxdump/1994/0713/sys/src/brazil/pc/devether.c 200,203c setvec(Int0vec+ctlr->irq, ctlr->interrupt, ctlr); . 180d 178d ## diffname pc/devether.c 1995/0108 ## diff -e /n/fornaxdump/1994/0713/sys/src/brazil/pc/devether.c /n/fornaxdump/1995/0108/sys/src/brazil/pc/devether.c 153a } long etherbwrite(Chan *c, Block *bp, ulong offset) { return devbwrite(c, bp, offset); . 84a Block* etherbread(Chan *c, long n, ulong offset) { return devbread(c, n, offset); } . ## diffname pc/devether.c 1995/0504 ## diff -e /n/fornaxdump/1995/0108/sys/src/brazil/pc/devether.c /n/fornaxdump/1995/0504/sys/src/brazil/pc/devether.c 212,213c print("ether%d: %s: port 0x%lux irq %d", ctlrno, ctlr->type, ctlr->port, ctlr->irq); if(ctlr->mem) print(" addr 0x%lux", ctlr->mem); if(ctlr->mem) print(" size %d", ctlr->size); print(": ea"); . ## diffname pc/devether.c 1995/0505 ## diff -e /n/fornaxdump/1995/0504/sys/src/brazil/pc/devether.c /n/fornaxdump/1995/0505/sys/src/brazil/pc/devether.c 218c print(":"); . 216c if(ctlr->size) . ## diffname pc/devether.c 1995/0511 ## diff -e /n/fornaxdump/1995/0505/sys/src/brazil/pc/devether.c /n/fornaxdump/1995/0511/sys/src/brazil/pc/devether.c 217c print(" size 0x%lux", ctlr->size); . 215c print(" addr 0x%lux", ctlr->mem & ~KZERO); . ## diffname pc/devether.c 1995/0513 ## diff -e /n/fornaxdump/1995/0511/sys/src/brazil/pc/devether.c /n/fornaxdump/1995/0513/sys/src/brazil/pc/devether.c 220c print(" %2.2uX", ctlr->ea[i]); . 217c print(" size 0x%luX", ctlr->size); . 215c print(" addr 0x%luX", ctlr->mem & ~KZERO); . 212c print("ether%d: %s: port 0x%luX irq %d", . ## diffname pc/devether.c 1995/0711 ## diff -e /n/fornaxdump/1995/0513/sys/src/brazil/pc/devether.c /n/fornaxdump/1995/0711/sys/src/brazil/pc/devether.c 113c if(qproduce(f->in, pkt->d, len) < 0) ctlr->soverflows++; . ## diffname pc/devether.c 1995/0713 ## diff -e /n/fornaxdump/1995/0711/sys/src/brazil/pc/devether.c /n/fornaxdump/1995/0713/sys/src/brazil/pc/devether.c 112,114c if((f = *fp) && ((tome && f->type==type) || f->type < 0)){ if(f->type > -2){ if(qproduce(f->in, pkt->d, len) < 0) ctlr->soverflows++; } else { if(qwindow(f->in) <= 0) continue; if(len > 60) len = 60; bp = iallocb(len); if(bp == 0) continue; memmove(bp->wp, pkt->d, len); i = TK2MS(m->ticks); bp->wp[60] = i>>24; bp->wp[61] = i>>16; bp->wp[62] = i>>8; bp->wp[63] = i; bp->wp += 64; qpass(f->in, bp); } } . 106a int i; . 105a Block *bp; . ## diffname pc/devether.c 1995/0721 ## diff -e /n/fornaxdump/1995/0713/sys/src/brazil/pc/devether.c /n/fornaxdump/1995/0721/sys/src/brazil/pc/devether.c 153c return different == 0; . 150c etherrloop(ctlr, pkt, len); . 144,146c different = memcmp(pkt->d, ctlr->ea, sizeof(pkt->d)); if(different && memcmp(pkt->d, ctlr->bcast, sizeof(pkt->d))) . 142c int s, different; . 114c if((f = *fp) && (f->type == type || f->type < 0)){ . 104c etherrloop(Ether *ctlr, Etherpkt *pkt, long len) . ## diffname pc/devether.c 1995/0725 ## diff -e /n/fornaxdump/1995/0721/sys/src/brazil/pc/devether.c /n/fornaxdump/1995/0725/sys/src/brazil/pc/devether.c 248a ctlr->ctlrno = ctlrno; . ## diffname pc/devether.c 1995/0726 ## diff -e /n/fornaxdump/1995/0725/sys/src/brazil/pc/devether.c /n/fornaxdump/1995/0726/sys/src/brazil/pc/devether.c 70d 68c ethercreate(Chan*, char*, int, ulong) . ## diffname pc/devether.c 1995/0731 ## diff -e /n/fornaxdump/1995/0726/sys/src/brazil/pc/devether.c /n/fornaxdump/1995/0731/sys/src/brazil/pc/devether.c 144c if(!ctlr->prom && different && memcmp(pkt->d, ctlr->bcast, sizeof(pkt->d))) . 126a bp->wp[58] = len>>8; bp->wp[59] = len; . ## diffname pc/devether.c 1995/0801 ## diff -e /n/fornaxdump/1995/0731/sys/src/brazil/pc/devether.c /n/fornaxdump/1995/0801/sys/src/brazil/pc/devether.c 125c memmove(bp->wp, pkt->d, n); . 120,122c if(len > 64) n = 64; else n = len; bp = iallocb(n); . 107c int i, n; . ## diffname pc/devether.c 1995/0822 ## diff -e /n/fornaxdump/1995/0801/sys/src/brazil/pc/devether.c /n/fornaxdump/1995/0822/sys/src/brazil/pc/devether.c 181a poperror(); . 180d 163d 159c etherwrite(Chan *c, void *buf, long n, ulong) . 148c if(different && memcmp(pkt->d, ctlr->bcast, sizeof(pkt->d))) . 93d 91c etherremove(Chan*) . ## diffname pc/devether.c 1995/1004 ## diff -e /n/fornaxdump/1995/0822/sys/src/brazil/pc/devether.c /n/fornaxdump/1995/1004/sys/src/brazil/pc/devether.c 147c if(different && memcmp(pkt->d, ctlr->bcast, sizeof(pkt->d)) && ctlr->prom == 0) . ## diffname pc/devether.c 1996/0601 ## diff -e /n/fornaxdump/1995/1004/sys/src/brazil/pc/devether.c /n/fornaxdump/1996/0601/sys/src/brazil/pc/devether.c 250d 245c if(ctlr->mbps == 100) netifinit(ctlr, "ether", Ntypes, 100*1024); else netifinit(ctlr, "ether", Ntypes, 32*1024); . 242c print("%2.2uX", ctlr->ea[i]); . 240c print(": "); . 234,235c print("ether%d: %s: %dMbps port 0x%luX irq %d", ctlrno, ctlr->type, ctlr->mbps, ctlr->port, ctlr->irq); . 216a ctlr->ctlrno = ctlrno; ctlr->mbps = 10; . ## diffname pc/devether.c 1996/0607 ## diff -e /n/fornaxdump/1996/0601/sys/src/brazil/pc/devether.c /n/fornaxdump/1996/0607/sys/src/brazil/pc/devether.c 248c netifinit(ctlr, "ether", Ntypes, 128*1024); . 236c print("ether#%d: %s: %dMbps port 0x%luX irq %d", . 81c Ether *ctlr; ctlr = ether[c->dev]; if((c->qid.path & CHDIR) == 0 && ctlr->ifstat){ /* * With some controllers it is necessary to reach * into the chip to extract statistics. */ if(NETTYPE(c->qid.path) == Nifstatqid) return (*ctlr->ifstat)(ctlr, buf, n, offset); else if(NETTYPE(c->qid.path) == Nstatqid) (*ctlr->ifstat)(ctlr, buf, 0, offset); } return netifread(ctlr, c, buf, n, offset); . ## diffname pc/devether.c 1997/0327 ## diff -e /n/fornaxdump/1996/0607/sys/src/brazil/pc/devether.c /n/emeliedump/1997/0327/sys/src/brazil/pc/devether.c 276a Dev etherdevtab = { etherreset, devinit, etherattach, devclone, etherwalk, etherstat, etheropen, ethercreate, etherclose, etherread, etherbread, etherwrite, etherbwrite, etherremove, etherwstat, }; . 274,275c if(ether) free(ether); . 269,270c etherxx[ctlrno] = ether; ether = 0; . 261,267c snprint(name, sizeof(name), "ether%d", ctlrno); if(ether->mbps == 100){ netifinit(ether, name, Ntypes, 256*1024); if(ether->oq == 0) ether->oq = qopen(256*1024, 1, 0, 0); } else{ netifinit(ether, name, Ntypes, 32*1024); if(ether->oq == 0) ether->oq = qopen(64*1024, 1, 0, 0); } ether->alen = Eaddrlen; memmove(ether->addr, ether->ea, Eaddrlen); memset(ether->bcast, 0xFF, Eaddrlen); . 250,259c i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %d", ctlrno, ether->type, ether->mbps, ether->port, ether->irq); if(ether->mem) i += sprint(buf+i, " addr 0x%luX", ether->mem & ~KZERO); if(ether->size) i += sprint(buf+i, " size 0x%luX", ether->size); i += sprint(buf+i, ": %2.2uX%2.2uX%2.2uX%2.2uX%2.2uX%2.2uX", ether->ea[0], ether->ea[1], ether->ea[2], ether->ea[3], ether->ea[4], ether->ea[5]); sprint(buf+i, "\n"); print(buf); . 246,248c if(ether->irq == 2) ether->irq = 9; intrenable(VectorPIC+ether->irq, ether->interrupt, ether, ether->tbdf); . 238c for(i = 0; i < ether->nopt; i++){ if(strncmp(ether->opt[i], "ea=", 3)) continue; if(parseether(ether->ea, ðer->opt[i][3]) == -1) memset(ether->ea, 0, Eaddrlen); } if(cards[n].reset(ether)) . 236c if(cistrcmp(cards[n].type, ether->type)) . 227,233c for(ether = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++){ if(ether == 0) ether = malloc(sizeof(Ether)); memset(ether, 0, sizeof(Ether)); ether->ctlrno = ctlrno; ether->tbdf = BUSUNKNOWN; ether->mbps = 10; if(isaconfig("ether", ctlrno, ether) == 0) . 225a char name[NAMELEN], buf[128]; . 224c Ether *ether; . 221c int parseether(uchar *to, char *from) { char nip[4]; char *p; int i; p = from; for(i = 0; i < 6; i++){ if(*p == 0) return -1; nip[0] = *p++; if(*p == 0) return -1; nip[1] = *p++; nip[2] = 0; to[i] = strtoul(nip, 0, 16); if(*p == ':') p++; } return 0; } static void . 210c addethercard(char* t, int (*r)(Ether*)) . 205c char* type; . 201c Ether *ether; long n; n = BLEN(bp); if(n > ETHERMAXTU){ freeb(bp); error(Ebadarg); } ether = etherxx[chan->dev]; if(NETTYPE(chan->qid.path) != Ndataqid){ n = netifwrite(ether, chan, bp->rp, n); freeb(bp); return n; } return etheroq(ether, bp); . 198,199c static long etherbwrite(Chan* chan, Block* bp, ulong) . 195c return etheroq(ether, bp); . 193a bp->wp += n; . 191,192c memmove(bp->rp, buf, n); memmove(bp->rp+Eaddrlen, ether->ea, Eaddrlen); . 188c freeb(bp); . 183,186c bp = allocb(n); . 180,181c ether = etherxx[chan->dev]; if(NETTYPE(chan->qid.path) != Ndataqid) return netifwrite(ether, chan, buf, n); . 178d 174c Ether *ether; Block *bp; . 171,172c static long etherwrite(Chan* chan, void* buf, long n, ulong) . 168c if(!loopback){ qbwrite(ether->oq, bp); ether->transmit(ether); } return len; . 164,166c /* * Check if the packet has to be placed back onto the input queue, * i.e. if it's a loopback or broadcast packet or the interface is * in promiscuous mode. * If it's a loopback packet indicate to etheriq that the data isn't * needed and return, etheriq will pass-on or free the block. */ pkt = (Etherpkt*)bp->rp; len = BLEN(bp); loopback = !memcmp(pkt->d, ether->ea, sizeof(pkt->d)); if(loopback || !memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) || ether->prom){ s = splhi(); etheriq(ether, bp, loopback); splx(s); } . 160,162c ether->outpackets++; . 158c int len, loopback, s; Etherpkt *pkt; . 156c etheroq(Ether* ether, Block* bp) . 152a if(fx){ qpass(fx->in, bp); return 0; } if(freebp){ freeb(bp); return 0; } return bp; . 150a else etherrtrace(f, pkt, len); . 136,149c ether->soverflows++; . 128,134c if(freebp && fx == 0) fx = f; else if(xbp = iallocb(len)){ memmove(xbp->wp, pkt, len); xbp->wp += len; qpass(f->in, xbp); } . 124,125c fx = 0; ep = ðer->f[Ntypes]; /* * Multiplex the packet to all the connections which want it. * If the packet is not to be used subsequently (freebp != 0), * attempt to simply pass it into one of the connections, thereby * saving a copy of the data (usual case hopefully). */ for(fp = ether->f; fp < ep; fp++){ . 122a ether->inpackets++; pkt = (Etherpkt*)bp->rp; len = BLEN(bp); . 120,121c int len; Netfile **ep, *f, **fp, *fx; Block *xbp; . 118a if(qwindow(f->in) <= 0) return; if(len > 64) n = 64; else n = len; bp = iallocb(n); if(bp == 0) return; memmove(bp->wp, pkt->d, n); i = TK2MS(m->ticks); bp->wp[58] = len>>8; bp->wp[59] = len; bp->wp[60] = i>>24; bp->wp[61] = i>>16; bp->wp[62] = i>>8; bp->wp[63] = i; bp->wp += 64; qpass(f->in, bp); } Block* etheriq(Ether* ether, Block* bp, int freebp) { Etherpkt *pkt; . 117a int i, n; . 115,116c static void etherrtrace(Netfile* f, Etherpkt* pkt, int len) . 112c netifwstat(etherxx[chan->dev], chan, dp); . 109,110c static void etherwstat(Chan* chan, char* dp) . 104c static void . 101c return netifbread(etherxx[chan->dev], chan, n, offset); . 98,99c static Block* etherbread(Chan* chan, long n, ulong offset) . 95c return netifread(ether, chan, buf, n, offset); . 89,92c if(NETTYPE(chan->qid.path) == Nifstatqid) return ether->ifstat(ether, buf, n, offset); else if(NETTYPE(chan->qid.path) == Nstatqid) ether->ifstat(ether, buf, 0, offset); . 83,84c ether = etherxx[chan->dev]; if((chan->qid.path & CHDIR) == 0 && ether->ifstat){ . 81c Ether *ether; . 78,79c static long etherread(Chan* chan, void* buf, long n, ulong offset) . 75c netifclose(etherxx[chan->dev], chan); . 72,73c static void etherclose(Chan* chan) . 61,67c static void . 58c return netifopen(etherxx[chan->dev], chan, omode); . 55,56c static Chan* etheropen(Chan* chan, int omode) . 52c netifstat(etherxx[chan->dev], chan, dp); . 49,50c static void etherstat(Chan* chan, char* dp) . 46c return netifwalk(etherxx[chan->dev], chan, name); . 43,44c static int etherwalk(Chan* chan, char* name) . 36,40c chan = devattach('l', spec); chan->dev = ctlrno; if(etherxx[ctlrno]->attach) etherxx[ctlrno]->attach(etherxx[ctlrno]); return chan; . 33c if(etherxx[ctlrno] == 0) . 25c Chan *chan; . 21c etherattach(char* spec) . 15,19d 13c static Ether *etherxx[MaxEther]; . ## diffname pc/devether.c 1997/0404 ## diff -e /n/emeliedump/1997/0327/sys/src/brazil/pc/devether.c /n/emeliedump/1997/0404/sys/src/brazil/pc/devether.c 147a /* check for valid multcast addresses */ if((pkt->d[0] & 1) && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) != 0 && ether->prom == 0){ if(!activemulti(ether, pkt->d, sizeof(pkt->d))){ if(freebp){ freeb(bp); bp = 0; } return bp; } } . ## diffname pc/devether.c 1997/0408 ## diff -e /n/emeliedump/1997/0404/sys/src/brazil/pc/devether.c /n/emeliedump/1997/0408/sys/src/brazil/pc/devether.c 388a 'l', "ether", . ## diffname pc/devether.c 1997/0415 ## diff -e /n/emeliedump/1997/0408/sys/src/brazil/pc/devether.c /n/emeliedump/1997/0415/sys/src/brazil/pc/devether.c 387a #define POLY 0xedb88320 /* really slow 32 bit crc for ethers */ ulong ethercrc(uchar *p, int len) { int i, j; ulong crc, b; crc = 0xffffffff; for(i = 0; i < len; i++){ b = *p++; for(j = 0; j < 8; j++){ crc = (crc>>1); if((crc^b) & 1) crc ^= POLY; b >>= 1; } } return crc; } . ## diffname pc/devether.c 1997/0418 ## diff -e /n/emeliedump/1997/0415/sys/src/brazil/pc/devether.c /n/emeliedump/1997/0418/sys/src/brazil/pc/devether.c 401,403c crc = (crc>>1) ^ (((crc^b) & 1) ? POLY : 0); . ## diffname pc/devether.c 1997/0808 ## diff -e /n/emeliedump/1997/0418/sys/src/brazil/pc/devether.c /n/emeliedump/1997/0808/sys/src/brazil/pc/devether.c 212,213c loopback = (memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0); if(loopback || memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) == 0 || ether->prom){ . 149c if((pkt->d[0] & 1) && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) && ether->prom == 0){ . 120c i = TK2MS(MACHP(0)->ticks); . ## diffname pc/devether.c 1997/1101 ## diff -e /n/emeliedump/1997/0808/sys/src/brazil/pc/devether.c /n/emeliedump/1997/1101/sys/src/brazil/pc/devether.c 355c i += sprint(buf+i, " addr 0x%luX", PADDR(ether->mem)); . 271a if(n > ETHERMAXTU){ freeb(bp); error(Ebadarg); } if(n < ETHERMINTU){ freeb(bp); error(Etoosmall); } . 260,264d 239a if(n > ETHERMAXTU) error(Etoobig); if(n < ETHERMINTU) error(Etoosmall); . 233,235d ## diffname pc/devether.c 1997/1105 ## diff -e /n/emeliedump/1997/1101/sys/src/brazil/pc/devether.c /n/emeliedump/1997/1105/sys/src/brazil/pc/devether.c 380a if(ether->oq == 0) panic("etherreset %s", name); . ## diffname pc/devether.c 1998/0218 ## diff -e /n/emeliedump/1997/1105/sys/src/brazil/pc/devether.c /n/emeliedump/1998/0218/sys/src/brazil/pc/devether.c 379c ether->oq = qopen(65*1024, 1, 0, 0); . 377c netifinit(ether, name, Ntypes, 65*1024); . ## diffname pc/devether.c 1998/0319 ## diff -e /n/emeliedump/1998/0218/sys/src/brazil/pc/devether.c /n/emeliedump/1998/0319/sys/src/brazil/pc/devether.c 228c etherwrite(Chan* chan, void* buf, long n, vlong) . 70a ulong offset = off; . 68c etherread(Chan* chan, void* buf, long n, vlong off) . ## diffname pc/devether.c 1998/0825 ## diff -e /n/emeliedump/1998/0319/sys/src/brazil/pc/devether.c /n/emeliedump/1998/0825/sys/src/brazil/pc/devether.c 359c i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %lud", . ## diffname pc/devether.c 1998/0910 ## diff -e /n/emeliedump/1998/0825/sys/src/brazil/pc/devether.c /n/emeliedump/1998/0910/sys/src/brazil/pc/devether.c 357c intrenable(ether->irq, ether->interrupt, ether, ether->tbdf); . ## diffname pc/devether.c 1998/1013 ## diff -e /n/emeliedump/1998/0910/sys/src/brazil/pc/devether.c /n/emeliedump/1998/1013/sys/src/brazil/pc/devether.c 185c if(qpass(fx->in, bp) < 0) ether->soverflows++; . ## diffname pc/devether.c 1999/0316 ## diff -e /n/emeliedump/1998/1013/sys/src/brazil/pc/devether.c /n/emeliedump/1999/0316/sys/src/brazil/pc/devether.c 214a mine = memcmp(pkt->s, ether->ea, sizeof(pkt->s)) == 0; if(mine) . 210a * To enable bridging to work, only packets that were originated * by this interface are feedback . 200c int len, loopback, s, mine; . 167c if((f = *fp) && (f->type == type || f->type < 0) && (forme || multi || f->prom)){ . 159a // is it for me? forme = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0; . 150c if(multi && memcmp(pkt->d, ether->bcast, sizeof(pkt->d)) && ether->prom == 0){ . 148a multi = pkt->d[0] & 1; . 137c int len, multi, forme; . ## diffname pc/devether.c 1999/0402 ## diff -e /n/emeliedump/1999/0316/sys/src/brazil/pc/devether.c /n/emeliedump/1999/0402/sys/src/brazil/pc/devether.c 216c * by this interface are fed back. . ## diffname pc/devether.c 1999/0625 ## diff -e /n/emeliedump/1999/0402/sys/src/brazil/pc/devether.c /n/emeliedump/1999/0625/sys/src/brazil/pc/devether.c 232c } else freeb(bp); . 225c etheriq(ether, bp, 0); . 220,222c loopback = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0; . 204c int len, loopback, s; . 193c if(fromwire){ . 171,173c if(f = *fp) if(f->type == type || f->type < 0) if(tome || multi || f->prom){ /* Don't want to hear bridged packets */ if(f->bridge && !fromwire && !fromme) continue; if(!f->headersonly){ if(fromwire && fx == 0) . 166c * If the packet is not to be used subsequently (fromwire != 0), . 161,162c /* is it for me? */ tome = memcmp(pkt->d, ether->ea, sizeof(pkt->d)) == 0; fromme = memcmp(pkt->s, ether->ea, sizeof(pkt->s)) == 0; . 153c if(fromwire){ . 137c int len, multi, tome, fromme; . 133c etheriq(Ether* ether, Block* bp, int fromwire) . ## diffname pc/devether.c 1999/0819 ## diff -e /n/emeliedump/1999/0625/sys/src/brazil/pc/devether.c /n/emeliedump/1999/0819/sys/src/brazil/pc/devether.c 385d 371c snprint(name, sizeof(name), "ether%d", ctlrno); intrenable(ether->irq, ether->interrupt, ether, ether->tbdf, name); . ## diffname pc/devether.c 2000/0713 ## diff -e /n/emeliedump/1999/0819/sys/src/brazil/pc/devether.c /n/emeliedump/2000/0713/sys/src/9/pc/devether.c 117,118c bp = iallocb(64); if(bp == nil) . 113,114c if(len > 58) n = 58; . ## diffname pc/devether.c 2000/0817 ## diff -e /n/emeliedump/2000/0713/sys/src/9/pc/devether.c /n/emeliedump/2000/0817/sys/src/9/pc/devether.c 372c /* If ether->irq is less than 0, it is a hack to indicate no interrupt * used for the seocnd logical ethernet for the wavelan card */ if(ether->irq >= 0) intrenable(ether->irq, ether->interrupt, ether, ether->tbdf, name); . 282a ether = etherxx[chan->dev]; . 279c if(waserror()) { freeb(bp); nexterror(); } n = etherwrite(chan, bp->rp, n, 0); . 277d 264d 258,261d 251a if(ether->ctl!=nil) return ether->ctl(ether,buf,n); error(Ebadctl); } . 249,250c if(NETTYPE(chan->qid.path) != Ndataqid) { nn = netifwrite(ether, chan, buf, n); if(nn >= 0) return nn; . 246a int nn; . ## diffname pc/devether.c 2000/0921 ## diff -e /n/emeliedump/2000/0817/sys/src/9/pc/devether.c /n/emeliedump/2000/0921/sys/src/9/pc/devether.c 399c if(ether->mbps >= 100){ . 357a ether->minmtu = ETHERMINTU; ether->maxmtu = ETHERMAXTU; . 296c if(n < ether->minmtu){ . 294c error(Etoobig); . 292c if(n > ether->maxmtu){ . 286a poperror(); . 263c if(n < ether->minmtu) . 261c if(n > ether->maxmtu) . ## diffname pc/devether.c 2000/1110 ## diff -e /n/emeliedump/2000/0921/sys/src/9/pc/devether.c /n/emeliedump/2000/1110/sys/src/9/pc/devether.c 385c * used for the second logical ethernet for the wavelan card . ## diffname pc/devether.c 2001/0203 ## diff -e /n/emeliedump/2000/1110/sys/src/9/pc/devether.c /n/emeliedump/2001/0203/sys/src/9/pc/devether.c 124,128c bp->wp[60] = ts>>56; bp->wp[61] = ts>>48; bp->wp[62] = ts>>40; bp->wp[63] = ts>>32; bp->wp[64] = ts>>24; bp->wp[65] = ts>>16; bp->wp[66] = ts>>8; bp->wp[67] = ts; bp->wp += 68; . 121c ts = fastticks(nil); . 117c bp = iallocb(68); . 109a uvlong ts; . 108c int n; . ## diffname pc/devether.c 2001/0504 ## diff -e /n/emeliedump/2001/0203/sys/src/9/pc/devether.c /n/emeliedump/2001/0504/sys/src/9/pc/devether.c 273a poperror(); . 271a if(waserror()){ freeb(bp); nexterror(); } . 251c Block *volatile bp; . ## diffname pc/devether.c 2001/0527 ## diff -e /n/emeliedump/2001/0504/sys/src/9/pc/devether.c /n/emeliedump/2001/0527/sys/src/9/pc/devether.c 464d 360c char name[32], buf[128]; . 251c Block *bp; . 125,133c bp->wp[60] = i>>24; bp->wp[61] = i>>16; bp->wp[62] = i>>8; bp->wp[63] = i; bp->wp += 64; . 122c i = TK2MS(MACHP(0)->ticks); . 118c bp = iallocb(64); . 110d 108c int i, n; . 102c return netifwstat(etherxx[chan->dev], chan, dp, n); . 99,100c static int etherwstat(Chan* chan, uchar* dp, int n) . 74c if((chan->qid.type & QTDIR) == 0 && ether->ifstat){ . 47c return netifstat(etherxx[chan->dev], chan, dp, n); . 44,45c static int etherstat(Chan* chan, uchar* dp, int n) . 41c return netifwalk(etherxx[chan->dev], chan, nchan, name, nname); . 38,39c static Walkqid* etherwalk(Chan* chan, Chan* nchan, char** name, int nname) . ## diffname pc/devether.c 2001/0622 ## diff -e /n/emeliedump/2001/0527/sys/src/9/pc/devether.c /n/emeliedump/2001/0622/sys/src/9/pc/devether.c 356a print("Searching for ethernet devices\n"); . ## diffname pc/devether.c 2001/0626 ## diff -e /n/emeliedump/2001/0622/sys/src/9/pc/devether.c /n/emeliedump/2001/0626/sys/src/9/pc/devether.c 357d ## diffname pc/devether.c 2001/1130 ## diff -e /n/emeliedump/2001/0626/sys/src/9/pc/devether.c /n/emeliedump/2001/1130/sys/src/9/pc/devether.c 392c if(ether->irq > 0) . 389,390c /* * If ether->irq is 0, it is a hack to indicate no interrupt * used by ethersink. . ## diffname pc/devether.c 2001/1204 ## diff -e /n/emeliedump/2001/1130/sys/src/9/pc/devether.c /n/emeliedump/2001/1204/sys/src/9/pc/devether.c 469c devremove, . 94,98d ## diffname pc/devether.c 2002/0109 ## diff -e /n/emeliedump/2001/1204/sys/src/9/pc/devether.c /n/emeliedump/2002/0109/sys/src/9/pc/devether.c 453a ethershutdown, . 427a static void ethershutdown(void) { Ether *ether; int i; for(i = 0; i < MaxEther; i++){ ether = etherxx[i]; if(ether == nil) continue; if(ether->shutdown == nil) { print("#l%d: no shutdown fuction\n", i); continue; } (*ether->shutdown)(ether); } } . ## diffname pc/devether.c 2002/0314 ## diff -e /n/emeliedump/2002/0109/sys/src/9/pc/devether.c /n/emeliedump/2002/0314/sys/src/9/pc/devether.c 179c if(qpass(f->in, xbp) < 0) ether->soverflows++; . ## diffname pc/devether.c 2002/0403 ## diff -e /n/emeliedump/2002/0314/sys/src/9/pc/devether.c /n/emeliedump/2002/0403/sys/src/9/pc/devether.c 425,426d 423a if((ether = etherprobe(cardno, ctlrno)) == nil){ cardno++; continue; } etherxx[ctlrno] = ether; ctlrno++; . 420,422c if(ether->mbps >= 100){ netifinit(ether, name, Ntypes, 256*1024); if(ether->oq == 0) ether->oq = qopen(256*1024, 1, 0, 0); } else{ netifinit(ether, name, Ntypes, 65*1024); if(ether->oq == 0) ether->oq = qopen(65*1024, 1, 0, 0); } if(ether->oq == 0) panic("etherreset %s", name); ether->alen = Eaddrlen; memmove(ether->addr, ether->ea, Eaddrlen); memset(ether->bcast, 0xFF, Eaddrlen); return ether; } static void etherreset(void) { Ether *ether; int cardno, ctlrno; for(ctlrno = 0; ctlrno < MaxEther; ctlrno++){ if((ether = etherprobe(-1, ctlrno)) == nil) continue; etherxx[ctlrno] = ether; } cardno = ctlrno = 0; while(cards[cardno].type != nil && ctlrno < MaxEther){ if(etherxx[ctlrno] != nil){ ctlrno++; continue; . 404,418c i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %lud", ctlrno, cards[cardno].type, ether->mbps, ether->port, ether->irq); if(ether->mem) i += sprint(buf+i, " addr 0x%luX", PADDR(ether->mem)); if(ether->size) i += sprint(buf+i, " size 0x%luX", ether->size); i += sprint(buf+i, ": %2.2uX%2.2uX%2.2uX%2.2uX%2.2uX%2.2uX", ether->ea[0], ether->ea[1], ether->ea[2], ether->ea[3], ether->ea[4], ether->ea[5]); sprint(buf+i, "\n"); print(buf); . 392,402c /* * If ether->irq is 0, it is a hack to indicate no interrupt * used by ethersink. */ if(ether->irq > 0) intrenable(ether->irq, ether->interrupt, ether, ether->tbdf, name); . 385,390c /* * IRQ2 doesn't really exist, it's used to gang the interrupt * controllers together. A device set to IRQ2 will appear on * the second interrupt controller as IRQ9. */ if(ether->irq == 2) ether->irq = 9; snprint(name, sizeof(name), "ether%d", ctlrno); . 376,383c if(cardno >= MaxEther || cards[cardno].type == nil){ free(ether); return nil; } if(cards[cardno].reset(ether) < 0){ free(ether); return nil; } . 372,374c } break; } } . 370c if(parseether(ether->ea, ðer->opt[i][3])) . 353,365c ether = malloc(sizeof(Ether)); memset(ether, 0, sizeof(Ether)); ether->ctlrno = ctlrno; ether->tbdf = BUSUNKNOWN; ether->mbps = 10; ether->minmtu = ETHERMINTU; ether->maxmtu = ETHERMAXTU; if(cardno < 0){ if(isaconfig("ether", ctlrno, ether) == 0){ free(ether); return nil; } for(cardno = 0; cards[cardno].type; cardno++){ if(cistrcmp(cards[cardno].type, ether->type)) . 350,351c char buf[128], name[32]; . 348a int i; . 346,347c static Ether* etherprobe(int cardno, int ctlrno) . ## diffname pc/devether.c 2002/0502 ## diff -e /n/emeliedump/2002/0403/sys/src/9/pc/devether.c /n/emeliedump/2002/0502/sys/src/9/pc/devether.c 446a if(getconf("*noetherprobe")) return; . ## diffname pc/devether.c 2002/0703 ## diff -e /n/emeliedump/2002/0502/sys/src/9/pc/devether.c /n/emeliedump/2002/0703/sys/src/9/pc/devether.c 331c for(i = 0; i < Eaddrlen; i++){ . ## diffname pc/devether.c 2002/0710 ## diff -e /n/emeliedump/2002/0703/sys/src/9/pc/devether.c /n/emeliedump/2002/0710/sys/src/9/pc/devether.c 424c ether->oq = qopen(128*1024, 1, 0, 0); . 422c netifinit(ether, name, Ntypes, 128*1024); . 417c netifinit(ether, name, Ntypes, 512*1024); . ## diffname pc/devether.c 2002/0711 ## diff -e /n/emeliedump/2002/0710/sys/src/9/pc/devether.c /n/emeliedump/2002/0711/sys/src/9/pc/devether.c 424c ether->oq = qopen(128*1024, Qmsg, 0, 0); . 419c ether->oq = qopen(256*1024, Qmsg, 0, 0); . ## diffname pc/devether.c 2002/0712 ## diff -e /n/emeliedump/2002/0711/sys/src/9/pc/devether.c /n/emeliedump/2002/0712/sys/src/9/pc/devether.c 417c netifinit(ether, name, Ntypes, 256*1024); . 250c if(n == sizeof("nonblocking")-1 && strncmp((char*)buf, "nonblocking", n) == 0){ qnoblock(ether->oq, 1); return n; } . ## diffname pc/devether.c 2002/1123 ## diff -e /n/emeliedump/2002/0712/sys/src/9/pc/devether.c /n/emeliedump/2002/1123/sys/src/9/pc/devether.c 231c if(ether->transmit != nil) ether->transmit(ether); . ## diffname pc/devether.c 2003/0301 ## diff -e /n/emeliedump/2002/1123/sys/src/9/pc/devether.c /n/emeliedump/2003/0301/sys/src/9/pc/devether.c 408c i = sprint(buf, "#l%d: %s: %dMbps port 0x%luX irq %d", . 405c if(ether->irq >= 0) . 402c * If ether->irq is <0, it is a hack to indicate no interrupt . ## diffname pc/devether.c 2003/0312 ## diff -e /n/emeliedump/2003/0301/sys/src/9/pc/devether.c /n/emeliedump/2003/0312/sys/src/9/pc/devether.c 254a free(cb); . 251,252c cb = parsecmd(buf, n); if(strcmp(cb->f[0], "nonblocking") == 0){ if(cb->nf <= 1) onoff = 1; else onoff = atoi(cb->f[1]); qnoblock(ether->oq, onoff); free(cb); . 244c int nn, onoff; Cmdbuf *cb; .