| plan 9 kernel history: overview | file list | diff list |
2002/0703/pc/devether.c (diff list | history)
| 1992/0403/sys/src/9/pc/devether.c:1,7 – 1992/0404/sys/src/9/pc/devether.c:1,7 (short | long) | ||
| 1992/0403 | /* * Western Digital ethernet adapter * BUGS: | |
| 1992/0404 | * no more than one controller | |
| 1992/0403 | * fix for different controller types */ #include "u.h" | |
| 1992/0403/sys/src/9/pc/devether.c:15,24 – 1992/0404/sys/src/9/pc/devether.c:15,36 | ||
| 1992/0403 | typedef struct Ctlr Ctlr; typedef struct Pktype Pktype; | |
| 1992/0404 | typedef struct Ring Ring; | |
| 1992/0403 | enum { IObase = 0x360, | |
| 1992/0404 | RAMbase = 0xC8000, RAMsize = 8*1024, BUFsize = 256, | |
| 1992/0403 | ||
| 1992/0404 | Nctlr = 1, NPktype = 9, /* types/interface */ }; /* * register offsets from IObase */ enum { | |
| 1992/0403 | EA = 0x08, /* Ethernet Address in ROM */ ID = 0x0E, /* interface type */ | |
| 1992/0403/sys/src/9/pc/devether.c:25,38 – 1992/0404/sys/src/9/pc/devether.c:37,49 | ||
| 1992/0403 | NIC = 0x10, /* National DP8390 Chip */ Cr = NIC+0x00, /* Page [01] */ | |
| 1992/0404 | Pstart = NIC+0x01, /* write */ Pstop = NIC+0x02, /* write */ Bnry = NIC+0x03, | |
| 1992/0403 | Tsr = NIC+0x04, /* read */ Tpsr = Tsr, /* write */ | |
| 1992/0404 | Tbcr0 = NIC+0x05, /* write */ Tbcr1 = NIC+0x06, /* write */ | |
| 1992/0403 | Isr = NIC+0x07, Rbcr0 = NIC+0x0A, Rbcr1 = NIC+0x0B, | |
| 1992/0403/sys/src/9/pc/devether.c:47,65 – 1992/0404/sys/src/9/pc/devether.c:58,82 | ||
| 1992/0403 | Par0 = NIC+0x01, /* Page 1 */ Curr = NIC+0x07, | |
| 1992/0404 | }; | |
| 1992/0403 |
| |
| 1992/0404 | /* * 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 */ }; | |
| 1992/0403 |
| |
| 1992/0404 | struct Ring { uchar status; uchar next; ushort len; uchar data[BUFsize-4]; | |
| 1992/0403 | }; /* | |
| 1992/0403/sys/src/9/pc/devether.c:81,89 – 1992/0404/sys/src/9/pc/devether.c:98,109 | ||
| 1992/0403 | QLock; Rendez rr; /* rendezvous for an input buffer */ | |
| 1992/0404 | uchar bnry; uchar curr; uchar ovw; | |
| 1992/0403 | Queue rq; | |
| 1992/0404 | QLock xl; | |
| 1992/0403 | Rendez xr; int iobase; /* I/O base address */ | |
| 1992/0403/sys/src/9/pc/devether.c:117,122 – 1992/0404/sys/src/9/pc/devether.c:137,144 | ||
| 1992/0403 | Etherpkt *p; Block *nbp; | |
| 1992/0404 | panic("etheroput\n"); #ifdef notdef | |
| 1992/0403 | c = ((Pktype *)q->ptr)->ctlr; if(bp->type == M_CTL){ t = q->ptr; | |
| 1992/0403/sys/src/9/pc/devether.c:126,133 – 1992/0404/sys/src/9/pc/devether.c:148,157 | ||
| 1992/0403 | t->prom = 1; qlock(c); c->prom++; | |
| 1992/0404 | if(c->prom == 1){ outb(t->ctlr->iobase+Cr, 0x22); /* Page0, RD2|STA */ | |
| 1992/0403 | outb(c->iobase+Rcr, 0x14); /* PRO|AB */ | |
| 1992/0404 | } | |
| 1992/0403 | qunlock(c); } freeb(bp); | |
| 1992/0403/sys/src/9/pc/devether.c:226,231 – 1992/0404/sys/src/9/pc/devether.c:250,256 | ||
| 1992/0403 | poperror(); enet.outpackets++; | |
| 1992/0404 | #endif | |
| 1992/0403 | } /* | |
| 1992/0403/sys/src/9/pc/devether.c:237,253 – 1992/0404/sys/src/9/pc/devether.c:262,278 | ||
| 1992/0403 | static void etherstopen(Queue *q, Stream *s) { | |
| 1992/0404 | Ctlr *cp = &ctlr[0]; Pktype *pp; | |
| 1992/0403 |
| |
| 1992/0404 | 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); | |
| 1992/0403 | } /* | |
| 1992/0403/sys/src/9/pc/devether.c:259,281 – 1992/0404/sys/src/9/pc/devether.c:284,308 | ||
| 1992/0403 | static void etherstclose(Queue *q) { | |
| 1992/0404 | Pktype *pp; | |
| 1992/0403 |
| |
| 1992/0404 | 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); | |
| 1992/0403 | } | |
| 1992/0404 | qlock(pp); pp->type = 0; pp->q = 0; pp->prom = 0; pp->inuse = 0; netdisown(&pp->ctlr->net, pp - pp->ctlr->pktype); qunlock(pp); | |
| 1992/0403 | } static Qinfo info = { | |
| 1992/0403/sys/src/9/pc/devether.c:287,321 – 1992/0404/sys/src/9/pc/devether.c:314,348 | ||
| 1992/0403 | }; static int | |
| 1992/0404 | clonecon(Chan *c) | |
| 1992/0403 | { | |
| 1992/0404 | Ctlr *cp = &ctlr[0]; Pktype *pp; | |
| 1992/0403 |
| |
| 1992/0404 | for(pp = cp->pktype; pp < &cp->pktype[NPktype]; pp++){ qlock(pp); if(pp->inuse || pp->q){ qunlock(pp); | |
| 1992/0403 | continue; } | |
| 1992/0404 | pp->inuse = 1; netown(&cp->net, pp - cp->pktype, u->p->user, 0); qunlock(pp); return pp - cp->pktype; | |
| 1992/0403 | } exhausted("ether channels"); } static void | |
| 1992/0404 | statsfill(Chan *c, char *p, int n) | |
| 1992/0403 | { | |
| 1992/0404 | Ctlr *cp = &ctlr[0]; | |
| 1992/0403 | 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", | |
| 1992/0404 | 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]); | |
| 1992/0403 | strncpy(p, buf, n); } | |
| 1992/0403/sys/src/9/pc/devether.c:323,332 – 1992/0404/sys/src/9/pc/devether.c:350,359 | ||
| 1992/0403 | typefill(Chan *c, char *p, int n) { char buf[16]; | |
| 1992/0404 | Pktype *pp; | |
| 1992/0403 |
| |
| 1992/0404 | pp = &ctlr[0].pktype[STREAMID(c->qid.path)]; sprint(buf, "%d", pp->type); | |
| 1992/0403 | strncpy(p, buf, n); } | |
| 1992/0403/sys/src/9/pc/devether.c:333,418 – 1992/0404/sys/src/9/pc/devether.c:360,554 | ||
| 1992/0403 | static void intr(Ureg *ur) { | |
| 1992/0404 | 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); } } | |
| 1992/0403 | } /* * the following initialisation procedure * is mandatory | |
| 1992/0404 | * we leave the chip idling on internal loopback | |
| 1992/0403 | */ static void | |
| 1992/0404 | init(Ctlr *cp) | |
| 1992/0403 | { int i; | |
| 1992/0404 | 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 */ | |
| 1992/0403 |
| |
| 1992/0404 | 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); | |
| 1992/0403 | } void etherreset(void) { | |
| 1992/0404 | Ctlr *cp = &ctlr[0]; | |
| 1992/0403 | int i; | |
| 1992/0404 | cp->iobase = IObase; init(cp); | |
| 1992/0403 | setvec(Ethervec, intr); | |
| 1992/0404 | for(i = 0; i < sizeof(cp->ea); i++) cp->ea[i] = inb(cp->iobase+EA+i); memset(cp->ba, 0xFF, sizeof(cp->ba)); | |
| 1992/0403 |
| |
| 1992/0404 | 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; | |
| 1992/0403 | } | |
| 1992/0404 | 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); } } | |
| 1992/0403 | static int isinput(void *arg) { | |
| 1992/0404 | Ctlr *cp = arg; | |
| 1992/0403 |
| |
| 1992/0404 | return cp->bnry != cp->curr; | |
| 1992/0403 | } static void etherkproc(void *arg) { | |
| 1992/0404 | Ctlr *cp = arg; Block *bp; uchar bnry, curr; Ring *rp; | |
| 1992/0403 | if(waserror()){ | |
| 1992/0404 | print("%s noted\n", cp->name); init(cp); cp->kproc = 0; | |
| 1992/0403 | nexterror(); } | |
| 1992/0404 | cp->kproc = 1; | |
| 1992/0403 | for(;;){ | |
| 1992/0404 | 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 | |
| 1992/0403 | } } | |
| 1992/0403/sys/src/9/pc/devether.c:425,432 – 1992/0404/sys/src/9/pc/devether.c:561,567 | ||
| 1992/0403 | * put the receiver online * and start the kproc */ | |
| 1992/0404 | outb(ctlr[ctlrno].iobase+Tcr, 0); | |
| 1992/0403 | if(ctlr[ctlrno].kproc == 0){ sprint(ctlr[ctlrno].name, "ether%dkproc", ctlrno); kproc(ctlr[ctlrno].name, etherkproc, &ctlr[ctlrno]); | |
| 1992/0404/sys/src/9/pc/devether.c:148,157 – 1992/0405/sys/src/9/pc/devether.c:148,155 (short | long) | ||
| 1992/0403 | t->prom = 1; qlock(c); c->prom++; | |
| 1992/0404 |
| |
| 1992/0405 | if(c->prom == 1) | |
| 1992/0403 | outb(c->iobase+Rcr, 0x14); /* PRO|AB */ | |
| 1992/0404 |
| |
| 1992/0403 | qunlock(c); } freeb(bp); | |
| 1992/0404/sys/src/9/pc/devether.c:290,299 – 1992/0405/sys/src/9/pc/devether.c:288,295 | ||
| 1992/0404 | if(pp->prom){ qlock(pp->ctlr); pp->ctlr->prom--; | |
| 1992/0405 | if(pp->ctlr->prom == 0) | |
| 1992/0404 | outb(pp->ctlr->iobase+Rcr, 0x04);/* AB */ | |
| 1992/0403 | } | |
| 1992/0404 | qlock(pp); | |
| 1992/0404/sys/src/9/pc/devether.c:363,369 – 1992/0405/sys/src/9/pc/devether.c:359,364 | ||
| 1992/0404 | Ctlr *cp = &ctlr[0]; uchar isr, curr; | |
| 1992/0404/sys/src/9/pc/devether.c:397,403 – 1992/0405/sys/src/9/pc/devether.c:392,398 | ||
| 1992/0404 | * we have received packets. * this is the only place, other than the init code, * where we set the controller to Page1. | |
| 1992/0405 | * we must be sure to reset it back to Page0 in case | |
| 1992/0404 | * we interrupted some other part of this driver. */ if(isr & (Ovw|Prx)){ | |
| 1992/0404/sys/src/9/pc/devether.c:411,418 – 1992/0405/sys/src/9/pc/devether.c:406,414 | ||
| 1992/0403 | /* * the following initialisation procedure | |
| 1992/0405 | * is mandatory. | |
| 1992/0404 | * we leave the chip idling on internal loopback | |
| 1992/0405 | * and pointing to Page0. | |
| 1992/0403 | */ static void | |
| 1992/0404 | init(Ctlr *cp) | |
| 1992/0405/sys/src/9/pc/devether.c:2,8 – 1992/0406/sys/src/9/pc/devether.c:2,12 (short | long) | ||
| 1992/0403 | * Western Digital ethernet adapter * BUGS: | |
| 1992/0404 | * no more than one controller | |
| 1992/0406 | * TODO: | |
| 1992/0403 | * fix for different controller types | |
| 1992/0406 | * output * deal with stalling and restarting output on input overflow * fix magic ring constants | |
| 1992/0403 | */ #include "u.h" #include "../port/lib.h" | |
| 1992/0405/sys/src/9/pc/devether.c:131,156 – 1992/0406/sys/src/9/pc/devether.c:135,158 | ||
| 1992/0403 | static void etheroput(Queue *q, Block *bp) { | |
| 1992/0406 | Ctlr *cp; | |
| 1992/0403 | int len, n; | |
| 1992/0406 | Pktype *pp; | |
| 1992/0403 | Etherpkt *p; Block *nbp; | |
| 1992/0404 |
| |
| 1992/0403 |
| |
| 1992/0406 | cp = ((Pktype *)q->ptr)->ctlr; | |
| 1992/0403 | if(bp->type == M_CTL){ | |
| 1992/0406 | pp = q->ptr; | |
| 1992/0403 | if(streamparse("connect", bp)) | |
| 1992/0406 | pp->type = strtol((char *)bp->rptr, 0, 0); | |
| 1992/0403 | else if(streamparse("promiscuous", bp)) { | |
| 1992/0405 |
| |
| 1992/0403 |
| |
| 1992/0406 | pp->prom = 1; qlock(cp); cp->prom++; if(cp->prom == 1) outb(cp->iobase+Rcr, 0x14); /* PRO|AB */ qunlock(cp); | |
| 1992/0403 | } freeb(bp); return; | |
| 1992/0405/sys/src/9/pc/devether.c:160,192 – 1992/0406/sys/src/9/pc/devether.c:162,191 | ||
| 1992/0403 | * give packet a local address, return upstream if destined for * this machine. */ | |
| 1992/0406 | if(BLEN(bp) < ETHERHDRSIZE && (bp = pullup(bp, ETHERHDRSIZE)) == 0) return; | |
| 1992/0403 | p = (Etherpkt *)bp->rptr; | |
| 1992/0406 | memmove(p->s, cp->ea, sizeof(cp->ea)); if(memcmp(cp->ea, p->d, sizeof(cp->ea)) == 0){ | |
| 1992/0403 | len = blen(bp); | |
| 1992/0406 | if (bp = expandb(bp, len >= ETHERMINTU ? len: ETHERMINTU)){ putq(&cp->rq, bp); wakeup(&cp->rr); | |
| 1992/0403 | } return; } | |
| 1992/0406 | if(memcmp(cp->ba, p->d, sizeof(cp->ba)) == 0){ | |
| 1992/0403 | len = blen(bp); nbp = copyb(bp, len); | |
| 1992/0406 | if(nbp = expandb(nbp, len >= ETHERMINTU ? len: ETHERMINTU)){ | |
| 1992/0403 | nbp->wptr = nbp->rptr+len; | |
| 1992/0406 | putq(&cp->rq, nbp); wakeup(&cp->rr); | |
| 1992/0403 | } } | |
| 1992/0406 | panic("etheroput\n"); #ifdef notdef | |
| 1992/0403 | /* * only one transmitter at a time */ | |
| 1992/0405/sys/src/9/pc/devether.c:509,514 – 1992/0406/sys/src/9/pc/devether.c:508,525 | ||
| 1992/0404 | } } | |
| 1992/0406 | 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]); } | |
| 1992/0403 | static int isinput(void *arg) { | |
| 1992/0405/sys/src/9/pc/devether.c:534,550 – 1992/0406/sys/src/9/pc/devether.c:545,578 | ||
| 1992/0404 | cp->kproc = 1; | |
| 1992/0403 | for(;;){ | |
| 1992/0404 | sleep(&cp->rr, isinput, cp); | |
| 1992/0406 | /* * process any internal loopback packets */ | |
| 1992/0404 | while(bp = getq(&cp->rq)){ cp->inpackets++; etherup(cp, (Etherpkt*)bp->rptr, BLEN(bp)); freeb(bp); } | |
| 1992/0406 | /* * 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); } | |
| 1992/0403 | } } | |
| 1992/0406/sys/src/9/pc/devether.c:7,12 – 1992/0407/sys/src/9/pc/devether.c:7,13 (short | long) | ||
| 1992/0406 | * output * deal with stalling and restarting output on input overflow * fix magic ring constants | |
| 1992/0407 | * rewrite per SMC doc | |
| 1992/0403 | */ #include "u.h" #include "../port/lib.h" | |
| 1992/0406/sys/src/9/pc/devether.c:79,85 – 1992/0407/sys/src/9/pc/devether.c:80,87 | ||
| 1992/0404 | struct Ring { uchar status; uchar next; | |
| 1992/0407 | uchar len0; uchar len1; | |
| 1992/0404 | uchar data[BUFsize-4]; | |
| 1992/0403 | }; | |
| 1992/0406/sys/src/9/pc/devether.c:101,114 – 1992/0407/sys/src/9/pc/devether.c:103,119 | ||
| 1992/0403 | struct Ctlr { QLock; | |
| 1992/0407 | Ring *ring; | |
| 1992/0403 | Rendez rr; /* rendezvous for an input buffer */ | |
| 1992/0407 | Queue rq; | |
| 1992/0404 | uchar bnry; uchar curr; uchar ovw; | |
| 1992/0403 |
| |
| 1992/0407 | Etherpkt *xpkt; | |
| 1992/0404 | QLock xl; | |
| 1992/0403 | Rendez xr; | |
| 1992/0407 | uchar xbusy; | |
| 1992/0403 | int iobase; /* I/O base address */ | |
| 1992/0406/sys/src/9/pc/devether.c:132,137 – 1992/0407/sys/src/9/pc/devether.c:137,150 | ||
| 1992/0403 | }; static Ctlr ctlr[Nctlr]; | |
| 1992/0407 | static int isxfree(void *arg) { Ctlr *cp = arg; return cp->xbusy == 0 && cp->ovw == 0; } | |
| 1992/0403 | static void etheroput(Queue *q, Block *bp) { | |
| 1992/0406/sys/src/9/pc/devether.c:184,205 – 1992/0407/sys/src/9/pc/devether.c:197,216 | ||
| 1992/0403 | } } | |
| 1992/0406 |
| |
| 1992/0403 | /* * only one transmitter at a time */ | |
| 1992/0407 | qlock(&cp->xl); | |
| 1992/0403 | if(waserror()){ | |
| 1992/0407 | qunlock(&cp->xl); | |
| 1992/0403 | nexterror(); } /* | |
| 1992/0407 | * Wait till we get an output buffer | |
| 1992/0403 | */ | |
| 1992/0407 | sleep(&cp->xr, isxfree, cp); p = cp->xpkt; | |
| 1992/0403 | /* * copy message into buffer | |
| 1992/0406/sys/src/9/pc/devether.c:216,253 – 1992/0407/sys/src/9/pc/devether.c:227,255 | ||
| 1992/0403 | } /* | |
| 1992/0407 | * pad the packet (zero the pad) | |
| 1992/0403 | */ if(len < ETHERMINTU){ memset(((char*)p)+len, 0, ETHERMINTU-len); len = ETHERMINTU; } | |
| 1992/0407 | * give packet a local address | |
| 1992/0403 | */ | |
| 1992/0407 | memmove(p->s, cp->ea, sizeof(cp->ea)); | |
| 1992/0403 | /* | |
| 1992/0407 | * start the transmission | |
| 1992/0403 | */ | |
| 1992/0407 | outb(cp->iobase+Tbcr0, len & 0xFF); outb(cp->iobase+Tbcr1, (len>>8) & 0xFF); outb(cp->iobase+Cr, 0x26); /* Page0|TXP|STA */ cp->xbusy = 1; | |
| 1992/0403 |
| |
| 1992/0407 | qunlock(&cp->xl); | |
| 1992/0403 | poperror(); | |
| 1992/0404 |
| |
| 1992/0403 | } /* | |
| 1992/0406/sys/src/9/pc/devether.c:370,376 – 1992/0407/sys/src/9/pc/devether.c:372,379 | ||
| 1992/0404 | if(isr & Ptx) cp->outpackets++; if(isr & (Txe|Ptx)){ | |
| 1992/0407 | cp->xbusy = 0; wakeup(&cp->xr); | |
| 1992/0404 | } /* * the receive ring is full. | |
| 1992/0406/sys/src/9/pc/devether.c:422,427 – 1992/0407/sys/src/9/pc/devether.c:425,431 | ||
| 1992/0404 | outb(cp->iobase+Tcr, 0x20); /* LB0 */ outb(cp->iobase+Bnry, 6); cp->bnry = 6; | |
| 1992/0407 | cp->ring = (Ring*)(KZERO|RAMbase); | |
| 1992/0404 | outb(cp->iobase+Pstart, 6); /* 6*256 */ outb(cp->iobase+Pstop, 32); /* 8*1024/256 */ outb(cp->iobase+Isr, 0xFF); | |
| 1992/0406/sys/src/9/pc/devether.c:435,440 – 1992/0407/sys/src/9/pc/devether.c:439,445 | ||
| 1992/0404 | outb(cp->iobase+Cr, 0x22); /* Page0, RD2|STA */ outb(cp->iobase+Tpsr, 0); | |
| 1992/0407 | cp->xpkt = (Etherpkt*)(KZERO|RAMbase); | |
| 1992/0403 | } void | |
| 1992/0406/sys/src/9/pc/devether.c:556,569 – 1992/0407/sys/src/9/pc/devether.c:561,573 | ||
| 1992/0406 | /* * process any received packets */ | |
| 1992/0407 | cp->bnry = inb(cp->iobase+Bnry); while(cp->bnry != cp->curr){ rp = &cp->ring[cp->bnry]; | |
| 1992/0406 | cp->inpackets++; | |
| 1992/0407 | etherup(cp, (Etherpkt*)rp->data, ((rp->len1<<8)+rp->len0)-4); cp->bnry = rp->next; outb(cp->iobase+Bnry, cp->bnry); | |
| 1992/0406 | } /* * if we idled input because of overflow, | |
| 1992/0406/sys/src/9/pc/devether.c:572,577 – 1992/0407/sys/src/9/pc/devether.c:576,582 | ||
| 1992/0406 | if(cp->ovw){ cp->ovw = 0; outb(cp->iobase+Tcr, 0); | |
| 1992/0407 | wakeup(&cp->xr); | |
| 1992/0406 | } | |
| 1992/0403 | } } | |
| 1992/0407/sys/src/9/pc/devether.c:32,37 – 1992/0408/sys/src/9/pc/devether.c:32,40 (short | long) | ||
| 1992/0404 | NPktype = 9, /* types/interface */ }; | |
| 1992/0408 | #define NEXT(x, l) ((((x)+1)%(l)) == 0 ? 6: (((x)+1)%(l))) #define PREV(x, l) (((x)-1) == 5 ? (l-1): ((x)-1)) | |
| 1992/0404 | /* * register offsets from IObase */ | |
| 1992/0407/sys/src/9/pc/devether.c:389,394 – 1992/0408/sys/src/9/pc/devether.c:392,398 | ||
| 1992/0404 | outb(cp->iobase+Tcr, 0x20); /* LB0 */ outb(cp->iobase+Cr, 0x22); /* Page0, RD2|STA */ cp->ovw = 1; | |
| 1992/0408 | cp->overflows++; | |
| 1992/0404 | } /* * we have received packets. | |
| 1992/0407/sys/src/9/pc/devether.c:423,430 – 1992/0408/sys/src/9/pc/devether.c:427,434 | ||
| 1992/0404 | outb(cp->iobase+Rbcr1, 0); outb(cp->iobase+Rcr, 0x04); /* AB */ outb(cp->iobase+Tcr, 0x20); /* LB0 */ | |
| 1992/0408 | outb(cp->iobase+Bnry, cp->bnry); | |
| 1992/0407 | cp->ring = (Ring*)(KZERO|RAMbase); | |
| 1992/0404 | outb(cp->iobase+Pstart, 6); /* 6*256 */ outb(cp->iobase+Pstop, 32); /* 8*1024/256 */ | |
| 1992/0407/sys/src/9/pc/devether.c:434,441 – 1992/0408/sys/src/9/pc/devether.c:438,445 | ||
| 1992/0404 | outb(cp->iobase+Cr, 0x61); /* Page1, RD2|STP */ for(i = 0; i < sizeof(cp->ea); i++) outb(cp->iobase+Par0+i, cp->ea[i]); | |
| 1992/0408 | cp->curr = cp->bnry+1; outb(cp->iobase+Curr, cp->curr); | |
| 1992/0404 | outb(cp->iobase+Cr, 0x22); /* Page0, RD2|STA */ outb(cp->iobase+Tpsr, 0); | |
| 1992/0407/sys/src/9/pc/devether.c:449,459 – 1992/0408/sys/src/9/pc/devether.c:453,462 | ||
| 1992/0403 | int i; | |
| 1992/0404 | cp->iobase = IObase; | |
| 1992/0403 |
| |
| 1992/0404 | for(i = 0; i < sizeof(cp->ea); i++) cp->ea[i] = inb(cp->iobase+EA+i); | |
| 1992/0408 | init(cp); setvec(Ethervec, intr); | |
| 1992/0404 | memset(cp->ba, 0xFF, sizeof(cp->ba)); | |
| 1992/0403 | ||
| 1992/0404 | cp->net.name = "ether"; | |
| 1992/0407/sys/src/9/pc/devether.c:530,536 – 1992/0408/sys/src/9/pc/devether.c:533,539 | ||
| 1992/0403 | { | |
| 1992/0404 | Ctlr *cp = arg; | |
| 1992/0403 | ||
| 1992/0404 |
| |
| 1992/0408 | return NEXT(cp->bnry, 32) != cp->curr; | |
| 1992/0403 | } static void | |
| 1992/0407/sys/src/9/pc/devether.c:558,574 – 1992/0408/sys/src/9/pc/devether.c:561,580 | ||
| 1992/0404 | etherup(cp, (Etherpkt*)bp->rptr, BLEN(bp)); freeb(bp); } | |
| 1992/0408 | ||
| 1992/0406 | /* * process any received packets */ | |
| 1992/0407 |
| |
| 1992/0408 | bnry = NEXT(cp->bnry, 32); while(bnry != cp->curr){ rp = &cp->ring[bnry]; | |
| 1992/0406 | cp->inpackets++; | |
| 1992/0407 | etherup(cp, (Etherpkt*)rp->data, ((rp->len1<<8)+rp->len0)-4); | |
| 1992/0408 | bnry = rp->next; cp->bnry = PREV(bnry, 32); | |
| 1992/0407 | outb(cp->iobase+Bnry, cp->bnry); | |
| 1992/0406 | } | |
| 1992/0408 | ||
| 1992/0406 | /* * if we idled input because of overflow, * restart | |
| 1992/0408/sys/src/9/pc/devether.c:111,117 – 1992/0409/sys/src/9/pc/devether.c:111,116 (short | long) | ||
| 1992/0407 | Queue rq; | |
| 1992/0404 | uchar bnry; uchar curr; | |
| 1992/0403 | ||
| 1992/0407 | Etherpkt *xpkt; | |
| 1992/0404 | QLock xl; | |
| 1992/0408/sys/src/9/pc/devether.c:145,151 – 1992/0409/sys/src/9/pc/devether.c:144,150 | ||
| 1992/0407 | { Ctlr *cp = arg; | |
| 1992/0409 | return cp->xbusy == 0; | |
| 1992/0407 | } | |
| 1992/0403 | static void | |
| 1992/0408/sys/src/9/pc/devether.c:378,399 – 1992/0409/sys/src/9/pc/devether.c:377,384 | ||
| 1992/0407 | cp->xbusy = 0; wakeup(&cp->xr); | |
| 1992/0404 | } | |
| 1992/0409 | if(isr & Ovw) | |
| 1992/0408 | cp->overflows++; | |
| 1992/0404 |
| |
| 1992/0408/sys/src/9/pc/devether.c:404,409 – 1992/0409/sys/src/9/pc/devether.c:389,396 | ||
| 1992/0404 | if(isr & (Ovw|Prx)){ outb(cp->iobase+Cr, 0x62); /* Page1, RD2|STA */ cp->curr = inb(cp->iobase+Curr); | |
| 1992/0409 | if(cp->curr == 0) print("C0: b%d i%ux\n", cp->bnry, isr); | |
| 1992/0404 | outb(cp->iobase+Cr, 0x22); /* Page0, RD2|STA */ wakeup(&cp->rr); } | |
| 1992/0408/sys/src/9/pc/devether.c:451,458 – 1992/0409/sys/src/9/pc/devether.c:438,451 | ||
| 1992/0403 | { | |
| 1992/0404 | Ctlr *cp = &ctlr[0]; | |
| 1992/0403 | int i; | |
| 1992/0409 | uchar msr; | |
| 1992/0403 | ||
| 1992/0404 | cp->iobase = IObase; | |
| 1992/0409 | msr = 0x40|inb(cp->iobase); outb(cp->iobase, msr); for(i = 0; i < 0x10; i++) print("#%2.2ux ", inb(cp->iobase+i)); print("\n"); | |
| 1992/0404 | for(i = 0; i < sizeof(cp->ea); i++) cp->ea[i] = inb(cp->iobase+EA+i); | |
| 1992/0408 | init(cp); | |
| 1992/0408/sys/src/9/pc/devether.c:574,589 – 1992/0409/sys/src/9/pc/devether.c:567,572 | ||
| 1992/0408 | cp->bnry = PREV(bnry, 32); | |
| 1992/0407 | outb(cp->iobase+Bnry, cp->bnry); | |
| 1992/0406 | } | |
| 1992/0408 | ||
| 1992/0406 |
| |
| 1992/0407 |
| |
| 1992/0406 |
| |
| 1992/0403 | } } | |
| 1992/0408/sys/src/9/pc/devether.c:668,671 – 1992/0409/sys/src/9/pc/devether.c:651,674 | ||
| 1992/0403 | etherwrite(Chan *c, char *a, long n, ulong offset) { return streamwrite(c, a, n, 0); | |
| 1992/0409 | } 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); | |
| 1992/0403 | } | |
| 1992/0409/sys/src/9/pc/devether.c:18,39 – 1992/0410/sys/src/9/pc/devether.c:18,44 (short | long) | ||
| 1992/0403 | #include "io.h" #include "devtab.h" | |
| 1992/0410 | static int debug; | |
| 1992/0403 | typedef struct Ctlr Ctlr; | |
| 1992/0410 | typedef struct Type Type; | |
| 1992/0404 | typedef struct Ring Ring; | |
| 1992/0403 | enum { IObase = 0x360, | |
| 1992/0404 |
| |
| 1992/0410 | RAMbase = 0xD0000, | |
| 1992/0404 | RAMsize = 8*1024, BUFsize = 256, | |
| 1992/0403 | ||
| 1992/0410 | RINGbase = 6, /* gak */ RINGsize = 32, /* gak */ | |
| 1992/0404 | Nctlr = 1, | |
| 1992/0410 | NType = 9, /* types/interface */ | |
| 1992/0404 | }; | |
| 1992/0408 |
| |
| 1992/0410 | #define NEXT(x, l) ((((x)+1)%(l)) == 0 ? RINGbase: (((x)+1)%(l))) #define PREV(x, l) (((x)-1) < RINGbase ? (l-1): ((x)-1)) | |
| 1992/0408 | ||
| 1992/0404 | /* * register offsets from IObase | |
| 1992/0409/sys/src/9/pc/devether.c:77,83 – 1992/0410/sys/src/9/pc/devether.c:82,87 | ||
| 1992/0404 | Rxe = 0x04, /* receive error */ Txe = 0x08, /* transmit error */ Ovw = 0x10, /* overwrite warning */ | |
| 1992/0403 | ||
| 1992/0404 | struct Ring { | |
| 1992/0409/sys/src/9/pc/devether.c:91,97 – 1992/0410/sys/src/9/pc/devether.c:95,101 | ||
| 1992/0403 | /* * one per ethernet packet type */ | |
| 1992/0410 | struct Type { | |
| 1992/0403 | QLock; int type; /* ethernet type */ int prom; /* promiscuous mode */ | |
| 1992/0409/sys/src/9/pc/devether.c:119,125 – 1992/0410/sys/src/9/pc/devether.c:123,129 | ||
| 1992/0403 | int iobase; /* I/O base address */ | |
| 1992/0410 | Type type[NType]; | |
| 1992/0403 | uchar ea[6]; uchar ba[6]; | |
| 1992/0409/sys/src/9/pc/devether.c:127,133 – 1992/0410/sys/src/9/pc/devether.c:131,137 | ||
| 1992/0403 | uchar kproc; /* true if kproc started */ char name[NAMELEN]; /* name of kproc */ Network net; | |
| 1992/0410 | Netprot prot[NType]; | |
| 1992/0403 | int inpackets; int outpackets; | |
| 1992/0409/sys/src/9/pc/devether.c:152,168 – 1992/0410/sys/src/9/pc/devether.c:156,172 | ||
| 1992/0403 | { | |
| 1992/0406 | Ctlr *cp; | |
| 1992/0403 | int len, n; | |
| 1992/0406 |
| |
| 1992/0410 | Type *tp; | |
| 1992/0403 | Etherpkt *p; Block *nbp; | |
| 1992/0406 |
| |
| 1992/0410 | cp = ((Type *)q->ptr)->ctlr; | |
| 1992/0403 | if(bp->type == M_CTL){ | |
| 1992/0406 |
| |
| 1992/0410 | tp = q->ptr; | |
| 1992/0403 | if(streamparse("connect", bp)) | |
| 1992/0406 |
| |
| 1992/0410 | tp->type = strtol((char *)bp->rptr, 0, 0); | |
| 1992/0403 | else if(streamparse("promiscuous", bp)) { | |
| 1992/0406 |
| |
| 1992/0410 | tp->prom = 1; | |
| 1992/0406 | qlock(cp); cp->prom++; if(cp->prom == 1) | |
| 1992/0409/sys/src/9/pc/devether.c:264,279 – 1992/0410/sys/src/9/pc/devether.c:268,283 | ||
| 1992/0403 | etherstopen(Queue *q, Stream *s) { | |
| 1992/0404 | Ctlr *cp = &ctlr[0]; | |
| 1992/0410 | Type *tp; | |
| 1992/0403 | ||
| 1992/0404 |
| |
| 1992/0410 | tp = &cp->type[s->id]; qlock(tp); RD(q)->ptr = WR(q)->ptr = tp; tp->type = 0; tp->q = RD(q); tp->inuse = 1; tp->ctlr = cp; qunlock(tp); | |
| 1992/0403 | } /* | |
| 1992/0409/sys/src/9/pc/devether.c:285,307 – 1992/0410/sys/src/9/pc/devether.c:289,311 | ||
| 1992/0403 | static void etherstclose(Queue *q) { | |
| 1992/0404 |
| |
| 1992/0410 | Type *tp; | |
| 1992/0403 | ||
| 1992/0404 |
| |
| 1992/0405 |
| |
| 1992/0404 |
| |
| 1992/0410 | tp = (Type *)(q->ptr); if(tp->prom){ qlock(tp->ctlr); tp->ctlr->prom--; if(tp->ctlr->prom == 0) outb(tp->ctlr->iobase+Rcr, 0x04);/* AB */ qunlock(tp->ctlr); | |
| 1992/0403 | } | |
| 1992/0404 |
| |
| 1992/0410 | qlock(tp); tp->type = 0; tp->q = 0; tp->prom = 0; tp->inuse = 0; netdisown(&tp->ctlr->net, tp - tp->ctlr->type); qunlock(tp); | |
| 1992/0403 | } static Qinfo info = { | |
| 1992/0409/sys/src/9/pc/devether.c:316,333 – 1992/0410/sys/src/9/pc/devether.c:320,337 | ||
| 1992/0404 | clonecon(Chan *c) | |
| 1992/0403 | { | |
| 1992/0404 | Ctlr *cp = &ctlr[0]; | |
| 1992/0410 | Type *tp; | |
| 1992/0403 | ||
| 1992/0404 |
| |
| 1992/0410 | for(tp = cp->type; tp < &cp->type[NType]; tp++){ qlock(tp); if(tp->inuse || tp->q){ qunlock(tp); | |
| 1992/0403 | continue; } | |
| 1992/0404 |
| |
| 1992/0410 | tp->inuse = 1; netown(&cp->net, tp - cp->type, u->p->user, 0); qunlock(tp); return tp - cp->type; | |
| 1992/0403 | } exhausted("ether channels"); } | |
| 1992/0409/sys/src/9/pc/devether.c:349,358 – 1992/0410/sys/src/9/pc/devether.c:353,362 | ||
| 1992/0403 | typefill(Chan *c, char *p, int n) { char buf[16]; | |
| 1992/0404 |
| |
| 1992/0410 | Type *tp; | |
| 1992/0403 | ||
| 1992/0404 |
| |
| 1992/0410 | tp = &ctlr[0].type[STREAMID(c->qid.path)]; sprint(buf, "%d", tp->type); | |
| 1992/0403 | strncpy(p, buf, n); } | |
| 1992/0409/sys/src/9/pc/devether.c:360,366 – 1992/0410/sys/src/9/pc/devether.c:364,370 | ||
| 1992/0403 | intr(Ureg *ur) { | |
| 1992/0404 | Ctlr *cp = &ctlr[0]; | |
| 1992/0410 | uchar isr, bnry, curr; | |
| 1992/0404 | while(isr = inb(cp->iobase+Isr)){ outb(cp->iobase+Isr, isr); | |
| 1992/0409/sys/src/9/pc/devether.c:369,375 – 1992/0410/sys/src/9/pc/devether.c:373,379 | ||
| 1992/0404 | if(isr & Rxe){ cp->frames += inb(cp->iobase+Cntr0); cp->crcs += inb(cp->iobase+Cntr1); | |
| 1992/0410 | cp->overflows += inb(cp->iobase+Cntr2); | |
| 1992/0404 | } if(isr & Ptx) cp->outpackets++; | |
| 1992/0409/sys/src/9/pc/devether.c:377,384 – 1992/0410/sys/src/9/pc/devether.c:381,391 | ||
| 1992/0407 | cp->xbusy = 0; wakeup(&cp->xr); | |
| 1992/0404 | } | |
| 1992/0409 |
| |
| 1992/0408 |
| |
| 1992/0410 | if(isr & Ovw){ bnry = inb(cp->iobase+Bnry); outb(cp->iobase+bnry, bnry); cp->buffs++; } | |
| 1992/0404 | /* * we have received packets. * this is the only place, other than the init code, | |
| 1992/0409/sys/src/9/pc/devether.c:386,397 – 1992/0410/sys/src/9/pc/devether.c:393,404 | ||
| 1992/0405 | * we must be sure to reset it back to Page0 in case | |
| 1992/0404 | * we interrupted some other part of this driver. */ | |
| 1992/0410 | if(isr & (Rxe|Prx)){ | |
| 1992/0404 | outb(cp->iobase+Cr, 0x62); /* Page1, RD2|STA */ cp->curr = inb(cp->iobase+Curr); | |
| 1992/0409 |
| |
| 1992/0404 | outb(cp->iobase+Cr, 0x22); /* Page0, RD2|STA */ | |
| 1992/0410 | if(debug) print("I%d/%d/%d|", isr, cp->curr, cp->bnry); | |
| 1992/0404 | wakeup(&cp->rr); } } | |
| 1992/0409/sys/src/9/pc/devether.c:414,424 – 1992/0410/sys/src/9/pc/devether.c:421,431 | ||
| 1992/0404 | outb(cp->iobase+Rbcr1, 0); outb(cp->iobase+Rcr, 0x04); /* AB */ outb(cp->iobase+Tcr, 0x20); /* LB0 */ | |
| 1992/0410 | cp->bnry = RINGbase; | |
| 1992/0408 | outb(cp->iobase+Bnry, cp->bnry); | |
| 1992/0407 | cp->ring = (Ring*)(KZERO|RAMbase); | |
| 1992/0404 |
| |
| 1992/0410 | outb(cp->iobase+Pstart, RINGbase); outb(cp->iobase+Pstop, RINGsize); | |
| 1992/0404 | outb(cp->iobase+Isr, 0xFF); outb(cp->iobase+Imr, 0x1F); /* OVWE|TXEE|RXEE|PTXE|PRXE */ | |
| 1992/0403 | ||
| 1992/0409/sys/src/9/pc/devether.c:443,451 – 1992/0410/sys/src/9/pc/devether.c:450,462 | ||
| 1992/0404 | cp->iobase = IObase; | |
| 1992/0409 | msr = 0x40|inb(cp->iobase); outb(cp->iobase, msr); | |
| 1992/0410 | msr=0x40|inb(cp->iobase+0x05); outb(cp->iobase+0x05, msr); | |
| 1992/0409 | for(i = 0; i < 0x10; i++) print("#%2.2ux ", inb(cp->iobase+i)); print("\n"); | |
| 1992/0410 | msr=0x40|inb(cp->iobase+0x05); outb(cp->iobase+0x05, msr); | |
| 1992/0404 | for(i = 0; i < sizeof(cp->ea); i++) cp->ea[i] = inb(cp->iobase+EA+i); | |
| 1992/0408 | init(cp); | |
| 1992/0409/sys/src/9/pc/devether.c:453,459 – 1992/0410/sys/src/9/pc/devether.c:464,470 | ||
| 1992/0404 | memset(cp->ba, 0xFF, sizeof(cp->ba)); | |
| 1992/0403 | ||
| 1992/0404 | cp->net.name = "ether"; | |
| 1992/0410 | cp->net.nconv = NType; | |
| 1992/0404 | cp->net.devp = &info; cp->net.protop = 0; cp->net.listen = 0; | |
| 1992/0409/sys/src/9/pc/devether.c:467,490 – 1992/0410/sys/src/9/pc/devether.c:478,503 | ||
| 1992/0403 | } | |
| 1992/0404 | static void | |
| 1992/0410 | etherup(Ctlr *cp, uchar *d0, int len0, uchar *d1, int len1) | |
| 1992/0404 | { | |
| 1992/0410 | Etherpkt *p; | |
| 1992/0404 | Block *bp; | |
| 1992/0410 | Type *tp; | |
| 1992/0404 | int t; | |
| 1992/0410 | p = (Etherpkt*)d0; t = (p->type[0]<<8)|p->type[1]; for(tp = &cp->type[0]; tp < &cp->type[NType]; tp++){ | |
| 1992/0404 | /* * check before locking just to save a lock */ | |
| 1992/0410 | if(tp->q == 0 || (t != tp->type && tp->type != -1)) | |
| 1992/0404 | continue; /* * only a trace channel gets packets destined for other machines */ | |
| 1992/0410 | if(tp->type != -1 && p->d[0] != 0xFF && memcmp(p->d, cp->ea, sizeof(p->d))) | |
| 1992/0404 | continue; /* | |
| 1992/0409/sys/src/9/pc/devether.c:491,511 – 1992/0410/sys/src/9/pc/devether.c:504,526 | ||
| 1992/0404 | * check after locking to make sure things didn't * change under foot */ | |
| 1992/0410 | if(canqlock(tp) == 0) | |
| 1992/0404 | continue; | |
| 1992/0410 | if(tp->q == 0 || tp->q->next->len > Streamhi || (t != tp->type && tp->type != -1)){ qunlock(tp); | |
| 1992/0404 | continue; } if(waserror() == 0){ | |
| 1992/0410 | bp = allocb(len0+len1); memmove(bp->rptr, d0, len0); if(len1) memmove(bp->rptr+len0, d1, len1); bp->wptr += len0+len1; | |
| 1992/0404 | bp->flags |= S_DELIM; | |
| 1992/0410 | PUTNEXT(tp->q, bp); | |
| 1992/0404 | } poperror(); | |
| 1992/0410 | qunlock(tp); | |
| 1992/0404 | } } | |
| 1992/0409/sys/src/9/pc/devether.c:526,532 – 1992/0410/sys/src/9/pc/devether.c:541,547 | ||
| 1992/0403 | { | |
| 1992/0404 | Ctlr *cp = arg; | |
| 1992/0403 | ||
| 1992/0408 |
| |
| 1992/0410 | return NEXT(cp->bnry, RINGsize) != cp->curr; | |
| 1992/0403 | } static void | |
| 1992/0409/sys/src/9/pc/devether.c:536,541 – 1992/0410/sys/src/9/pc/devether.c:551,557 | ||
| 1992/0404 | Block *bp; uchar bnry, curr; Ring *rp; | |
| 1992/0410 | int len0, len1; | |
| 1992/0403 | if(waserror()){ | |
| 1992/0404 | print("%s noted\n", cp->name); | |
| 1992/0409/sys/src/9/pc/devether.c:551,557 – 1992/0410/sys/src/9/pc/devether.c:567,573 | ||
| 1992/0406 | */ | |
| 1992/0404 | while(bp = getq(&cp->rq)){ cp->inpackets++; | |
| 1992/0410 | etherup(cp, bp->rptr, BLEN(bp), 0, 0); | |
| 1992/0404 | freeb(bp); } | |
| 1992/0408 | ||
| 1992/0409/sys/src/9/pc/devether.c:558,570 – 1992/0410/sys/src/9/pc/devether.c:574,599 | ||
| 1992/0406 | /* * process any received packets */ | |
| 1992/0408 |
| |
| 1992/0410 | bnry = NEXT(cp->bnry, RINGsize); | |
| 1992/0408 | while(bnry != cp->curr){ rp = &cp->ring[bnry]; | |
| 1992/0406 | cp->inpackets++; | |
| 1992/0407 |
| |
| 1992/0410 | len0 = ((rp->len1<<8)+rp->len0)-4; len1 = 0; if(rp->data+len0 >= (uchar*)&cp->ring[RINGsize]){ len1 = rp->data+len0 - (uchar*)&cp->ring[RINGsize]; len0 = (uchar*)&cp->ring[RINGsize] - rp->data; } etherup(cp, rp->data, len0, (uchar*)&cp->ring[RINGbase], len1); if(debug) print("K%d/%d/%d|", bnry, rp->next, PREV(rp->next, RINGsize)); | |
| 1992/0408 | bnry = rp->next; | |
| 1992/0410 | cp->bnry = PREV(bnry, RINGsize); | |
| 1992/0407 | outb(cp->iobase+Bnry, cp->bnry); | |
| 1992/0406 | } | |
| 1992/0403 | } | |
| 1992/0409/sys/src/9/pc/devether.c:661,666 – 1992/0410/sys/src/9/pc/devether.c:690,696 | ||
| 1992/0409 | int s; s = splhi(); | |
| 1992/0410 | debug++; | |
| 1992/0409 | bnry = inb(cp->iobase+Bnry); outb(cp->iobase+Cr, 0x62); /* Page1, RD2|STA */ curr = inb(cp->iobase+Curr); | |
| 1992/0409/sys/src/9/pc/devether.c:668,674 – 1992/0410/sys/src/9/pc/devether.c:698,704 | ||
| 1992/0409 | isr = inb(cp->iobase+Isr); print("b%d c%d x%d B%d C%d I%ux", cp->bnry, cp->curr, cp->xbusy, bnry, curr, isr); | |
| 1992/0410 | print("\t%d %d %d %d %d %d %d\n", cp->inpackets, cp->outpackets, | |
| 1992/0409 | cp->crcs, cp->oerrs, cp->frames, cp->overflows, cp->buffs); splx(s); | |
| 1992/0403 | } | |
| 1992/0410/sys/src/9/pc/devether.c:26,32 – 1992/0411/sys/src/9/pc/devether.c:26,32 (short | long) | ||
| 1992/0403 | enum { IObase = 0x360, | |
| 1992/0410 |
| |
| 1992/0411 | RAMbase = 0xC8000, | |
| 1992/0404 | RAMsize = 8*1024, BUFsize = 256, | |
| 1992/0403 | ||
| 1992/0410/sys/src/9/pc/devether.c:143,148 – 1992/0411/sys/src/9/pc/devether.c:143,172 | ||
| 1992/0403 | }; static Ctlr ctlr[Nctlr]; | |
| 1992/0411 | 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); } | |
| 1992/0407 | static int isxfree(void *arg) { | |
| 1992/0410/sys/src/9/pc/devether.c:208,213 – 1992/0411/sys/src/9/pc/devether.c:232,238 | ||
| 1992/0403 | */ | |
| 1992/0407 | qlock(&cp->xl); | |
| 1992/0403 | if(waserror()){ | |
| 1992/0411 | freeb(bp); | |
| 1992/0407 | qunlock(&cp->xl); | |
| 1992/0403 | nexterror(); } | |
| 1992/0410/sys/src/9/pc/devether.c:215,222 – 1992/0411/sys/src/9/pc/devether.c:240,249 | ||
| 1992/0403 | /* | |
| 1992/0407 | * Wait till we get an output buffer | |
| 1992/0403 | */ | |
| 1992/0407 |
| |
| 1992/0411 | tsleep(&cp->xr, isxfree, cp, 1000); if(isxfree(cp) == 0) print("Tx wedged\n"); p = &txpkt; | |
| 1992/0403 | /* * copy message into buffer | |
| 1992/0410/sys/src/9/pc/devether.c:244,249 – 1992/0411/sys/src/9/pc/devether.c:271,277 | ||
| 1992/0407 | * give packet a local address | |
| 1992/0403 | */ | |
| 1992/0407 | memmove(p->s, cp->ea, sizeof(cp->ea)); | |
| 1992/0411 | xmemmove(cp->xpkt, p, len); | |
| 1992/0403 | /* | |
| 1992/0407 | * start the transmission | |
| 1992/0410/sys/src/9/pc/devether.c:445,462 – 1992/0411/sys/src/9/pc/devether.c:473,488 | ||
| 1992/0403 | { | |
| 1992/0404 | Ctlr *cp = &ctlr[0]; | |
| 1992/0403 | int i; | |
| 1992/0409 |
| |
| 1992/0411 | uchar reg; | |
| 1992/0403 | ||
| 1992/0404 | cp->iobase = IObase; | |
| 1992/0409 |
| |
| 1992/0410 |
| |
| 1992/0411 | reg = 0x40|inb(cp->iobase); outb(cp->iobase, reg); reg = 0x40|inb(cp->iobase+0x05); outb(cp->iobase+0x05, reg); | |
| 1992/0409 | for(i = 0; i < 0x10; i++) print("#%2.2ux ", inb(cp->iobase+i)); print("\n"); | |
| 1992/0410 |
| |
| 1992/0404 | for(i = 0; i < sizeof(cp->ea); i++) cp->ea[i] = inb(cp->iobase+EA+i); | |
| 1992/0408 | init(cp); | |
| 1992/0410/sys/src/9/pc/devether.c:512,520 – 1992/0411/sys/src/9/pc/devether.c:538,546 | ||
| 1992/0404 | } if(waserror() == 0){ | |
| 1992/0410 | bp = allocb(len0+len1); | |
| 1992/0411 | xmemmove(bp->rptr, d0, len0); | |
| 1992/0410 | if(len1) | |
| 1992/0411 | xmemmove(bp->rptr+len0, d1, len1); | |
| 1992/0410 | bp->wptr += len0+len1; | |
| 1992/0404 | bp->flags |= S_DELIM; | |
| 1992/0410 | PUTNEXT(tp->q, bp); | |
| 1992/0410/sys/src/9/pc/devether.c:683,689 – 1992/0411/sys/src/9/pc/devether.c:709,715 | ||
| 1992/0409 | } void | |
| 1992/0411 | consdebug(void) | |
| 1992/0409 | { Ctlr *cp = &ctlr[0]; uchar bnry, curr, isr; | |
| 1992/0411/sys/src/9/pc/devether.c:1,14 – 1992/0424/sys/src/9/pc/devether.c:1,3 (short | long) | ||
| 1992/0403 |
| |
| 1992/0404 |
| |
| 1992/0406 |
| |
| 1992/0403 |
| |
| 1992/0406 |
| |
| 1992/0407 |
| |
| 1992/0403 |
| |
| 1992/0411/sys/src/9/pc/devether.c:18,97 – 1992/0424/sys/src/9/pc/devether.c:7,56 | ||
| 1992/0403 | #include "io.h" #include "devtab.h" | |
| 1992/0410 |
| |
| 1992/0403 |
| |
| 1992/0424 | typedef struct Hw Hw; typedef struct Buffer Buffer; | |
| 1992/0410 | typedef struct Type Type; | |
| 1992/0404 |
| |
| 1992/0424 | typedef struct Ctlr Ctlr; | |
| 1992/0403 |
| |
| 1992/0411 |
| |
| 1992/0404 |
| |
| 1992/0403 | ||
| 1992/0410 |
| |
| 1992/0404 |
| |
| 1992/0410 |
| |
| 1992/0424 | 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*); | |
| 1992/0404 | }; | |
| 1992/0424 | static Hw wd8013; | |
| 1992/0404 | ||
| 1992/0410 |
| |
| 1992/0408 | ||
| 1992/0404 |
| |
| 1992/0403 |
| |
| 1992/0424 | Nctlr = 1, /* even one of these is too many */ NType = 9, /* types/interface */ | |
| 1992/0403 |
| |
| 1992/0424 | Nrb = 16, /* software receive buffers */ Ntb = 4, /* software transmit buffers */ }; | |
| 1992/0403 | ||
| 1992/0404 |
| |
| 1992/0403 |
| |
| 1992/0404 |
| |
| 1992/0403 |
| |
| 1992/0424 | #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)) | |
| 1992/0403 |
| |
| 1992/0424 | struct Buffer { uchar owner; uchar busy; ushort len; Etherpkt pkt; | |
| 1992/0404 | }; | |
| 1992/0403 | ||
| 1992/0404 |
| |
| 1992/0424 | Host = 0, /* buffer owned by host */ Interface = 1, /* buffer owned by interface */ | |
| 1992/0404 | }; | |
| 1992/0403 | ||
| 1992/0404 |
| |
| 1992/0407 |
| |
| 1992/0404 |
| |
| 1992/0403 |
| |
| 1992/0411/sys/src/9/pc/devether.c:105,178 – 1992/0424/sys/src/9/pc/devether.c:64,185 | ||
| 1992/0403 | }; /* | |
| 1992/0424 | * per ethernet | |
| 1992/0403 | */ struct Ctlr { QLock; | |
| 1992/0407 |
| |
| 1992/0403 |
| |
| 1992/0407 |
| |
| 1992/0404 |
| |
| 1992/0424 | Hw *hw; | |
| 1992/0403 | ||
| 1992/0407 |
| |
| 1992/0404 |
| |
| 1992/0403 |
| |
| 1992/0407 |
| |
| 1992/0424 | ushort nrb; /* number of software receive buffers */ ushort ntb; /* number of software transmit buffers */ Buffer *rb; /* software receive buffers */ Buffer *tb; /* software transmit buffers */ | |
| 1992/0403 |
| |
| 1992/0424 | uchar ea[6]; /* ethernet address */ uchar ba[6]; /* broadcast address */ | |
| 1992/0403 | ||
| 1992/0410 |
| |
| 1992/0403 |
| |
| 1992/0424 | 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 */ | |
| 1992/0403 |
| |
| 1992/0424 | 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 */ | |
| 1992/0403 | Network net; | |
| 1992/0410 | Netprot prot[NType]; | |
| 1992/0403 | ||
| 1992/0424 | Queue lbq; /* software loopback packet queue */ | |
| 1992/0403 | int inpackets; int outpackets; | |
| 1992/0424 | int crcs; /* input crc errors */ int oerrs; /* output errors */ int frames; /* framing errors */ int overflows; /* packet overflows */ int buffs; /* buffering errors */ | |
| 1992/0403 | }; static Ctlr ctlr[Nctlr]; | |
| 1992/0411 |
| |
| 1992/0424 | void etherinit(void) { } | |
| 1992/0411 |
| |
| 1992/0424 | Chan* etherclone(Chan *c, Chan *nc) | |
| 1992/0411 | { | |
| 1992/0424 | return devclone(c, nc); } | |
| 1992/0411 |
| |
| 1992/0424 | 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); | |
| 1992/0411 | } | |
| 1992/0424 | 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); } | |
| 1992/0407 | static int | |
| 1992/0424 | isobuf(void *arg) | |
| 1992/0407 | { Ctlr *cp = arg; | |
| 1992/0409 |
| |
| 1992/0424 | cp->tb[cp->th].owner == Host; | |
| 1992/0407 | } | |
| 1992/0403 | static void | |
| 1992/0411/sys/src/9/pc/devether.c:182,190 – 1992/0424/sys/src/9/pc/devether.c:189,197 | ||
| 1992/0403 | int len, n; | |
| 1992/0410 | Type *tp; | |
| 1992/0403 | Etherpkt *p; | |
| 1992/0424 | Buffer *tb; | |
| 1992/0403 | Block *nbp; | |
| 1992/0410 |
| |
| 1992/0403 | if(bp->type == M_CTL){ | |
| 1992/0410 | tp = q->ptr; | |
| 1992/0403 | if(streamparse("connect", bp)) | |
| 1992/0411/sys/src/9/pc/devether.c:191,206 – 1992/0424/sys/src/9/pc/devether.c:198,211 | ||
| 1992/0410 | tp->type = strtol((char *)bp->rptr, 0, 0); | |
| 1992/0403 | else if(streamparse("promiscuous", bp)) { | |
| 1992/0410 | tp->prom = 1; | |
| 1992/0406 |
| |
| 1992/0424 | (*tp->ctlr->hw->mode)(tp->ctlr, 1); | |
| 1992/0403 | } freeb(bp); return; } | |
| 1992/0424 | cp = ((Type *)q->ptr)->ctlr; | |
| 1992/0403 | /* * give packet a local address, return upstream if destined for * this machine. | |
| 1992/0411/sys/src/9/pc/devether.c:212,218 – 1992/0424/sys/src/9/pc/devether.c:217,223 | ||
| 1992/0406 | if(memcmp(cp->ea, p->d, sizeof(cp->ea)) == 0){ | |
| 1992/0403 | len = blen(bp); | |
| 1992/0406 | if (bp = expandb(bp, len >= ETHERMINTU ? len: ETHERMINTU)){ | |
| 1992/0424 | putq(&cp->lbq, bp); | |
| 1992/0406 | wakeup(&cp->rr); | |
| 1992/0403 | } return; | |
| 1992/0411/sys/src/9/pc/devether.c:222,228 – 1992/0424/sys/src/9/pc/devether.c:227,233 | ||
| 1992/0403 | nbp = copyb(bp, len); | |
| 1992/0406 | if(nbp = expandb(nbp, len >= ETHERMINTU ? len: ETHERMINTU)){ | |
| 1992/0403 | nbp->wptr = nbp->rptr+len; | |
| 1992/0406 |
| |
| 1992/0424 | putq(&cp->lbq, nbp); | |
| 1992/0406 | wakeup(&cp->rr); | |
| 1992/0403 | } } | |
| 1992/0411/sys/src/9/pc/devether.c:230,250 – 1992/0424/sys/src/9/pc/devether.c:235,257 | ||
| 1992/0403 | /* * only one transmitter at a time */ | |
| 1992/0407 |
| |
| 1992/0424 | qlock(&cp->tlock); | |
| 1992/0403 | if(waserror()){ | |
| 1992/0411 | freeb(bp); | |
| 1992/0407 |
| |
| 1992/0424 | qunlock(&cp->tlock); | |
| 1992/0403 | nexterror(); } /* | |
| 1992/0407 |
| |
| 1992/0424 | * wait till we get an output buffer. * should try to restart. | |
| 1992/0403 | */ | |
| 1992/0411 |
| |
| 1992/0424 | print("oput sleep\n"); sleep(&cp->tr, isobuf, cp); | |
| 1992/0403 | ||
| 1992/0424 | tb = &cp->tb[cp->th]; p = &tb->pkt; | |
| 1992/0403 | /* * copy message into buffer */ | |
| 1992/0411/sys/src/9/pc/devether.c:271,288 – 1992/0424/sys/src/9/pc/devether.c:278,297 | ||
| 1992/0407 | * give packet a local address | |
| 1992/0403 | */ | |
| 1992/0407 | memmove(p->s, cp->ea, sizeof(cp->ea)); | |
| 1992/0411 |
| |
| 1992/0403 | /* | |
| 1992/0424 | * set up the transmit buffer and | |
| 1992/0407 | * start the transmission | |
| 1992/0403 | */ | |
| 1992/0407 |
| |
| 1992/0424 | cp->outpackets++; tb->len = len; tb->owner = Interface; cp->th = NEXT(cp->th, cp->ntb); (*cp->hw->transmit)(cp); | |
| 1992/0403 | freeb(bp); | |
| 1992/0407 |
| |
| 1992/0424 | qunlock(&cp->tlock); print("oput done\n"); | |
| 1992/0403 | poperror(); } | |
| 1992/0411/sys/src/9/pc/devether.c:320,332 – 1992/0424/sys/src/9/pc/devether.c:329,336 | ||
| 1992/0410 | Type *tp; | |
| 1992/0403 | ||
| 1992/0410 | tp = (Type *)(q->ptr); | |
| 1992/0403 |
| |
| 1992/0424 | if(tp->prom) (*tp->ctlr->hw->mode)(tp->ctlr, 0); | |
| 1992/0410 | qlock(tp); tp->type = 0; tp->q = 0; | |
| 1992/0411/sys/src/9/pc/devether.c:389,517 – 1992/0424/sys/src/9/pc/devether.c:393,404 | ||
| 1992/0403 | } static void | |
| 1992/0424 | etherup(Ctlr *cp, Etherpkt *p, int len) | |
| 1992/0403 | { | |
| 1992/0404 |
| |
| 1992/0410 |
| |
| 1992/0404 |
| |
| 1992/0410 |
| |
| 1992/0404 |
| |
| 1992/0407 |
| |
| 1992/0404 |
| |
| 1992/0410 |
| |
| 1992/0404 |
| |
| 1992/0405 |
| |
| 1992/0404 |
| |
| 1992/0410 |
| |
| 1992/0404 |
| |
| 1992/0410 |
| |
| 1992/0404 |
| |
| 1992/0403 |
| |
| 1992/0405 |
| |
| 1992/0404 |
| |
| 1992/0405 |
| |
| 1992/0403 |
| |
| 1992/0404 |
| |
| 1992/0403 |
| |
| 1992/0404 |
| |
| 1992/0410 |
| |
| 1992/0408 |
| |
| 1992/0407 |
| |
| 1992/0410 |
| |
| 1992/0404 |
| |
| 1992/0403 | ||
| 1992/0404 |
| |
| 1992/0408 |
| |
| 1992/0404 |
| |
| 1992/0407 |
| |
| 1992/0403 |
| |
| 1992/0404 |
| |
| 1992/0403 |
| |
| 1992/0411 |
| |
| 1992/0403 | ||
| 1992/0404 |
| |
| 1992/0411 |
| |
| 1992/0409 |
| |
| 1992/0404 |
| |
| 1992/0408 |
| |
| 1992/0404 |
| |
| 1992/0403 | ||
| 1992/0404 |
| |
| 1992/0410 |
| |
| 1992/0404 |
| |
| 1992/0403 |
| |
| 1992/0404 |
| |
| 1992/0410 |
| |
| 1992/0404 |
| |
| 1992/0410 |
| |
| 1992/0404 | Block *bp; | |
| 1992/0410 | Type *tp; | |
| 1992/0404 | int t; | |
| 1992/0410 |
| |
| 1992/0404 | /* | |
| 1992/0411/sys/src/9/pc/devether.c:537,547 – 1992/0424/sys/src/9/pc/devether.c:424,432 | ||
| 1992/0404 | continue; } if(waserror() == 0){ | |
| 1992/0410 |
| |
| 1992/0411 |
| |
| 1992/0410 |
| |
| 1992/0411 |
| |
| 1992/0410 |
| |
| 1992/0424 | bp = allocb(len); memmove(bp->rptr, p, len); bp->wptr += len; | |
| 1992/0404 | bp->flags |= S_DELIM; | |
| 1992/0410 | PUTNEXT(tp->q, bp); | |
| 1992/0404 | } | |
| 1992/0411/sys/src/9/pc/devether.c:550,573 – 1992/0424/sys/src/9/pc/devether.c:435,446 | ||
| 1992/0404 | } } | |
| 1992/0406 |
| |
| 1992/0403 | static int isinput(void *arg) { | |
| 1992/0404 | Ctlr *cp = arg; | |
| 1992/0403 | ||
| 1992/0410 |
| |
| 1992/0424 | return cp->lbq.first || cp->rb[cp->ri].owner == Host; | |
| 1992/0403 | } static void | |
| 1992/0411/sys/src/9/pc/devether.c:574,599 – 1992/0424/sys/src/9/pc/devether.c:447,471 | ||
| 1992/0403 | etherkproc(void *arg) { | |
| 1992/0404 | Ctlr *cp = arg; | |
| 1992/0424 | Buffer *rb; | |
| 1992/0404 | Block *bp; | |
| 1992/0410 |
| |
| 1992/0403 | if(waserror()){ | |
| 1992/0404 | print("%s noted\n", cp->name); | |
| 1992/0424 | (*cp->hw->init)(cp); | |
| 1992/0404 | cp->kproc = 0; | |
| 1992/0403 | nexterror(); } | |
| 1992/0404 | cp->kproc = 1; | |
| 1992/0403 | for(;;){ | |
| 1992/0404 |
| |
| 1992/0424 | qlock(&cp->rlock); | |
| 1992/0406 | /* * process any internal loopback packets */ | |
| 1992/0404 |
| |
| 1992/0424 | while(bp = getq(&cp->lbq)){ | |
| 1992/0404 | cp->inpackets++; | |
| 1992/0410 |
| |
| 1992/0424 | etherup(cp, (Etherpkt*)bp->rptr, BLEN(bp)); | |
| 1992/0404 | freeb(bp); } | |
| 1992/0408 | ||
| 1992/0411/sys/src/9/pc/devether.c:600,730 – 1992/0424/sys/src/9/pc/devether.c:472,823 | ||
| 1992/0406 | /* * process any received packets */ | |
| 1992/0410 |
| |
| 1992/0408 |
| |
| 1992/0424 | while(cp->rb[cp->rh].owner == Host){ | |
| 1992/0406 | cp->inpackets++; | |
| 1992/0410 |
| |
| 1992/0424 | rb = &cp->rb[cp->rh]; etherup(cp, &rb->pkt, rb->len); rb->owner = Interface; cp->rh = NEXT(cp->rh, Nrb); } | |
| 1992/0410 |
| |
| 1992/0424 | qunlock(&cp->rlock); sleep(&cp->rr, isinput, cp); } } | |
| 1992/0410 |
| |
| 1992/0424 | void etherreset(void) { Ctlr *cp = &ctlr[0]; | |
| 1992/0410 | ||
| 1992/0424 | cp->hw = &wd8013; (*cp->hw->reset)(cp); | |
| 1992/0410 | ||
| 1992/0424 | memset(cp->ba, 0xFF, sizeof(cp->ba)); | |
| 1992/0410 |
| |
| 1992/0408 |
| |
| 1992/0410 |
| |
| 1992/0407 |
| |
| 1992/0406 |
| |
| 1992/0403 |
| |
| 1992/0424 | 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; | |
| 1992/0403 | } | |
| 1992/0424 | Chan* etherattach(char *spec) | |
| 1992/0403 | { int ctlrno = 0; | |
| 1992/0424 | Ctlr *cp = &ctlr[ctlrno]; int i; | |
| 1992/0403 | ||
| 1992/0424 | 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; | |
| 1992/0403 | /* * put the receiver online * and start the kproc */ | |
| 1992/0404 |
| |
| 1992/0403 |
| |
| 1992/0424 | (*cp->hw->online)(cp, 1); if(cp->kproc == 0){ sprint(cp->name, "ether%dkproc", ctlrno); kproc(cp->name, etherkproc, cp); | |
| 1992/0403 | } | |
| 1992/0424 | 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; | |
| 1992/0403 |
| |
| 1992/0424 | 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; | |
| 1992/0403 |
| |
| 1992/0424 | #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) | |
| 1992/0403 | { | |
| 1992/0424 | Hw *hw = cp->hw; int i; uchar msr; | |
| 1992/0403 |
| |
| 1992/0424 | 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); | |
| 1992/0403 | { | |
| 1992/0424 | int addr = hw->addr; for(i = 0; i < 16; i++){ print("#%2.2ux ", inb(addr)); addr++; | |
| 1992/0403 | } | |
| 1992/0424 | print("\n"); } for(i = 0; i < sizeof(cp->ea); i++) cp->ea[i] = IN(hw, lan[i]); (*hw->init)(cp); setvec(Ethervec, hw->intr); } | |
| 1992/0403 |
| |
| 1992/0424 | /* * we leave the chip idling on internal loopback * and pointing to Page0. */ static void wd8013init(Ctlr *cp) | |
| 1992/0403 | { | |
| 1992/0424 | 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); | |
| 1992/0403 | } void | |
| 1992/0424 | wd8013mode(Ctlr *cp, int on) | |
| 1992/0403 | { | |
| 1992/0424 | 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); | |
| 1992/0403 | } | |
| 1992/0424 | static void wd8013online(Ctlr *cp, int on) | |
| 1992/0403 | { | |
| 1992/0424 | OUT(cp->hw, w.tcr, 0); | |
| 1992/0403 | } | |
| 1992/0424 | static void wd8013receive(Ctlr *cp) | |
| 1992/0403 | { | |
| 1992/0424 | 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); } | |
| 1992/0403 | } | |
| 1992/0424 | static void wd8013transmit(Ctlr *cp) | |
| 1992/0403 | { | |
| 1992/0424 | 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"); | |
| 1992/0403 | } | |
| 1992/0424 | static void wd8013intr(Ureg *ur) | |
| 1992/0403 | { | |
| 1992/0424 | 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); } } | |
| 1992/0409 | } | |
| 1992/0424 | 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, }; | |
| 1992/0409 | void | |
| 1992/0411 | consdebug(void) | |
| 1992/0409 | { | |
| 1992/0410 |
| |
| 1992/0409 |
| |
| 1992/0410 |
| |
| 1992/0409 |
| |
| 1992/0403 | } | |
| 1992/0424/sys/src/9/pc/devether.c:108,116 – 1992/0425/sys/src/9/pc/devether.c:108,117 (short | long) | ||
| 1992/0403 | }; static Ctlr ctlr[Nctlr]; | |
| 1992/0424 |
| |
| 1992/0425 | Chan* etherattach(char *spec) | |
| 1992/0424 | { | |
| 1992/0425 | return devattach('l', spec); | |
| 1992/0424 | } | |
| 1992/0411 | ||
| 1992/0424 | Chan* | |
| 1992/0424/sys/src/9/pc/devether.c:179,185 – 1992/0425/sys/src/9/pc/devether.c:180,186 | ||
| 1992/0407 | { Ctlr *cp = arg; | |
| 1992/0424 |
| |
| 1992/0425 | return cp->tb[cp->th].owner == Host; | |
| 1992/0407 | } | |
| 1992/0403 | static void | |
| 1992/0424/sys/src/9/pc/devether.c:246,252 – 1992/0425/sys/src/9/pc/devether.c:247,252 | ||
| 1992/0424 | * wait till we get an output buffer. * should try to restart. | |
| 1992/0403 | */ | |
| 1992/0424 |
| |
| 1992/0403 | ||
| 1992/0424 | tb = &cp->tb[cp->th]; | |
| 1992/0424/sys/src/9/pc/devether.c:291,297 – 1992/0425/sys/src/9/pc/devether.c:291,296 | ||
| 1992/0403 | freeb(bp); | |
| 1992/0424 | qunlock(&cp->tlock); | |
| 1992/0403 | poperror(); } | |
| 1992/0424/sys/src/9/pc/devether.c:509,516 – 1992/0425/sys/src/9/pc/devether.c:508,515 | ||
| 1992/0424 | cp->net.info[1].fill = typefill; | |
| 1992/0403 | } | |
| 1992/0424 |
| |
| 1992/0425 | void etherinit(void) | |
| 1992/0403 | { int ctlrno = 0; | |
| 1992/0424 | Ctlr *cp = &ctlr[ctlrno]; | |
| 1992/0424/sys/src/9/pc/devether.c:536,542 – 1992/0425/sys/src/9/pc/devether.c:535,540 | ||
| 1992/0424 | sprint(cp->name, "ether%dkproc", ctlrno); kproc(cp->name, etherkproc, cp); | |
| 1992/0403 | } | |
| 1992/0424 | typedef struct { | |
| 1992/0424/sys/src/9/pc/devether.c:610,616 – 1992/0425/sys/src/9/pc/devether.c:608,613 | ||
| 1992/0424 | int i; uchar msr; | |
| 1992/0403 | ||
| 1992/0424 |
| |
| 1992/0424/sys/src/9/pc/devether.c:705,711 – 1992/0425/sys/src/9/pc/devether.c:702,708 | ||
| 1992/0424 | uchar data[256-4]; } Ring; Ring *p; | |
| 1992/0425 | int len0, len1; | |
| 1992/0424 | bnry = IN(hw, r.bnry); next = NEXT(bnry, HOWMANY(hw->ramsz, 256)); | |
| 1992/0424/sys/src/9/pc/devether.c:719,730 – 1992/0425/sys/src/9/pc/devether.c:716,737 | ||
| 1992/0424 | break; cp->inpackets++; p = &((Ring*)hw->ram)[next]; | |
| 1992/0425 | len0 = (p->len1<<8)|p->len0-4; len1 = 0; | |
| 1992/0424 | rb = &cp->rb[cp->ri]; if(rb->owner == Interface){ | |
| 1992/0425 | rb->len = len0; | |
| 1992/0424 | /*copy in packet*/ | |
| 1992/0425 | 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); | |
| 1992/0424 | rb->owner = Host; cp->ri = NEXT(cp->ri, Nrb); } | |
| 1992/0425/sys/src/9/pc/devether.c:14,21 – 1992/0501/sys/src/9/pc/devether.c:14,24 (short | long) | ||
| 1992/0403 | ||
| 1992/0424 | struct Hw { int addr; /* interface address */ | |
| 1992/0501 | uchar *ram; /* interface shared memory address */ int size; uchar tstart; uchar pstart; uchar pstop; | |
| 1992/0424 | void (*reset)(Ctlr*); void (*init)(Ctlr*); void (*mode)(Ctlr*, int); | |
| 1992/0425/sys/src/9/pc/devether.c:43,49 – 1992/0501/sys/src/9/pc/devether.c:46,52 | ||
| 1992/0424 | uchar owner; uchar busy; ushort len; | |
| 1992/0501 | uchar pkt[sizeof(Etherpkt)]; | |
| 1992/0404 | }; | |
| 1992/0403 | ||
| 1992/0404 | enum { | |
| 1992/0425/sys/src/9/pc/devether.c:250,256 – 1992/0501/sys/src/9/pc/devether.c:253,258 | ||
| 1992/0424 | sleep(&cp->tr, isobuf, cp); | |
| 1992/0403 | ||
| 1992/0424 | tb = &cp->tb[cp->th]; | |
| 1992/0403 | /* * copy message into buffer | |
| 1992/0425/sys/src/9/pc/devether.c:258,264 – 1992/0501/sys/src/9/pc/devether.c:260,266 | ||
| 1992/0403 | len = 0; for(nbp = bp; nbp; nbp = nbp->next){ if(sizeof(Etherpkt) - len >= (n = BLEN(nbp))){ | |
| 1992/0501 | memmove(tb->pkt+len, nbp->rptr, n); | |
| 1992/0403 | len += n; } else print("no room damn it\n"); | |
| 1992/0425/sys/src/9/pc/devether.c:270,285 – 1992/0501/sys/src/9/pc/devether.c:272,282 | ||
| 1992/0407 | * pad the packet (zero the pad) | |
| 1992/0403 | */ if(len < ETHERMINTU){ | |
| 1992/0501 | memset(tb->pkt+len, 0, ETHERMINTU-len); | |
| 1992/0403 | len = ETHERMINTU; } /* | |
| 1992/0407 |
| |
| 1992/0403 |
| |
| 1992/0407 |
| |
| 1992/0403 |
| |
| 1992/0424 | * set up the transmit buffer and | |
| 1992/0407 | * start the transmission | |
| 1992/0403 | */ | |
| 1992/0425/sys/src/9/pc/devether.c:392,403 – 1992/0501/sys/src/9/pc/devether.c:389,402 | ||
| 1992/0403 | } static void | |
| 1992/0424 |
| |
| 1992/0501 | etherup(Ctlr *cp, void *data, int len) | |
| 1992/0403 | { | |
| 1992/0404 |
| |
| 1992/0410 |
| |
| 1992/0501 | Etherpkt *p; | |
| 1992/0404 | int t; | |
| 1992/0501 | Type *tp; Block *bp; | |
| 1992/0404 | ||
| 1992/0501 | p = data; | |
| 1992/0410 | t = (p->type[0]<<8)|p->type[1]; for(tp = &cp->type[0]; tp < &cp->type[NType]; tp++){ | |
| 1992/0404 | /* | |
| 1992/0425/sys/src/9/pc/devether.c:464,470 – 1992/0501/sys/src/9/pc/devether.c:463,469 | ||
| 1992/0406 | */ | |
| 1992/0424 | while(bp = getq(&cp->lbq)){ | |
| 1992/0404 | cp->inpackets++; | |
| 1992/0424 |
| |
| 1992/0501 | etherup(cp, bp->rptr, BLEN(bp)); | |
| 1992/0404 | freeb(bp); } | |
| 1992/0408 | ||
| 1992/0425/sys/src/9/pc/devether.c:474,480 – 1992/0501/sys/src/9/pc/devether.c:473,479 | ||
| 1992/0424 | while(cp->rb[cp->rh].owner == Host){ | |
| 1992/0406 | cp->inpackets++; | |
| 1992/0424 | rb = &cp->rb[cp->rh]; | |
| 1992/0501 | etherup(cp, rb->pkt, rb->len); | |
| 1992/0424 | rb->owner = Interface; cp->rh = NEXT(cp->rh, Nrb); } | |
| 1992/0425/sys/src/9/pc/devether.c:528,535 – 1992/0501/sys/src/9/pc/devether.c:527,533 | ||
| 1992/0403 | /* * put the receiver online * and start the kproc | |
| 1992/0424 | ||
| 1992/0501 | */ | |
| 1992/0424 | (*cp->hw->online)(cp, 1); if(cp->kproc == 0){ sprint(cp->name, "ether%dkproc", ctlrno); | |
| 1992/0425/sys/src/9/pc/devether.c:599,604 – 1992/0501/sys/src/9/pc/devether.c:597,610 | ||
| 1992/0424 | #define IN(hw, m) inb((hw)->addr+OFFSETOF(Wd8013, m)) #define OUT(hw, m, x) outb((hw)->addr+OFFSETOF(Wd8013, m), (x)) | |
| 1992/0501 | typedef struct { uchar status; uchar next; uchar len0; uchar len1; uchar data[256-4]; } Ring; | |
| 1992/0424 | /* */ static void | |
| 1992/0425/sys/src/9/pc/devether.c:608,631 – 1992/0501/sys/src/9/pc/devether.c:614,630 | ||
| 1992/0424 | int i; uchar msr; | |
| 1992/0403 | ||
| 1992/0424 |
| |
| 1992/0501 | cp->tb = ialloc(sizeof(Buffer)*Ntb, 1); | |
| 1992/0424 | cp->ntb = Ntb; | |
| 1992/0501 | cp->rb = ialloc(sizeof(Buffer)*Nrb, 1); cp->nrb = Nrb; | |
| 1992/0424 | msr = IN(hw, msr); OUT(hw, msr, 0x40|msr); | |
| 1992/0403 |
| |
| 1992/0424 |
| |
| 1992/0403 |
| |
| 1992/0424 |
| |
| 1992/0501 | ||
| 1992/0424 | (*hw->init)(cp); setvec(Ethervec, hw->intr); } | |
| 1992/0425/sys/src/9/pc/devether.c:639,647 – 1992/0501/sys/src/9/pc/devether.c:638,644 | ||
| 1992/0403 | { | |
| 1992/0424 | Hw *hw = cp->hw; int i; | |
| 1992/0425/sys/src/9/pc/devether.c:649,658 – 1992/0501/sys/src/9/pc/devether.c:646,654 | ||
| 1992/0424 | OUT(hw, w.rcr, 0x04); /* AB */ OUT(hw, w.tcr, 0x20); /* LB0 */ | |
| 1992/0501 | OUT(hw, w.bnry, hw->pstart); OUT(hw, w.pstart, hw->pstart); OUT(hw, w.pstop, hw->pstop); | |
| 1992/0424 | OUT(hw, w.isr, 0xFF); OUT(hw, w.imr, 0x1F); /* OVWE|TXEE|RXEE|PTXE|PRXE */ | |
| 1992/0425/sys/src/9/pc/devether.c:659,665 – 1992/0501/sys/src/9/pc/devether.c:655,661 | ||
| 1992/0424 | OUT(hw, w.cr, 0x61); /* Page1|RD2|STP */ for(i = 0; i < sizeof(cp->ea); i++) OUT(hw, par[i], cp->ea[i]); | |
| 1992/0501 | OUT(hw, curr, hw->pstart+1); | |
| 1992/0424 | OUT(hw, w.cr, 0x22); /* Page0|RD2|STA */ OUT(hw, w.tpsr, 0); | |
| 1992/0425/sys/src/9/pc/devether.c:688,693 – 1992/0501/sys/src/9/pc/devether.c:684,691 | ||
| 1992/0424 | OUT(cp->hw, w.tcr, 0); | |
| 1992/0403 | } | |
| 1992/0501 | static ulong wraps; | |
| 1992/0424 | static void wd8013receive(Ctlr *cp) | |
| 1992/0403 | { | |
| 1992/0425/sys/src/9/pc/devether.c:694,713 – 1992/0501/sys/src/9/pc/devether.c:692,704 | ||
| 1992/0424 | Hw *hw = cp->hw; Buffer *rb; uchar bnry, curr, next; | |
| 1992/0425 |
| |
| 1992/0501 | int len; | |
| 1992/0424 | bnry = IN(hw, r.bnry); | |
| 1992/0501 | next = bnry+1; if(next >= hw->pstop) next = hw->pstart; | |
| 1992/0424 | for(;;){ OUT(hw, w.cr, 0x62); /* Page1|RD2|STA */ curr = IN(hw, curr); | |
| 1992/0425/sys/src/9/pc/devether.c:716,745 – 1992/0501/sys/src/9/pc/devether.c:707,737 | ||
| 1992/0424 | break; cp->inpackets++; p = &((Ring*)hw->ram)[next]; | |
| 1992/0425 |
| |
| 1992/0501 | len = (p->len1<<8)|p->len0-4; if(len > sizeof(Etherpkt)) print("!"); | |
| 1992/0424 | rb = &cp->rb[cp->ri]; if(rb->owner == Interface){ | |
| 1992/0425 |
| |
| 1992/0501 | rb->len = len; | |
| 1992/0424 | /*copy in packet*/ | |
| 1992/0425 |
| |
| 1992/0501 | 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); | |
| 1992/0425 | } | |
| 1992/0501 | memmove(rb->pkt, p->data, len); | |
| 1992/0424 | rb->owner = Host; cp->ri = NEXT(cp->ri, Nrb); } | |
| 1992/0501 | p->status = 0; | |
| 1992/0424 | next = p->next; bnry = next-1; | |
| 1992/0501 | if(bnry < hw->pstart) bnry = hw->pstop-1; | |
| 1992/0424 | OUT(hw, w.bnry, bnry); } | |
| 1992/0403 | } | |
| 1992/0425/sys/src/9/pc/devether.c:751,763 – 1992/0501/sys/src/9/pc/devether.c:743,754 | ||
| 1992/0424 | Buffer *tb; int s; | |
| 1992/0501 | tb->len = tb->len+1 & ~1; memmove(hw->ram, tb->pkt, tb->len); | |
| 1992/0424 | OUT(hw, w.tbcr0, tb->len & 0xFF); OUT(hw, w.tbcr1, (tb->len>>8) & 0xFF); OUT(hw, w.cr, 0x26); /* Page0|RD2|TXP|STA */ | |
| 1992/0425/sys/src/9/pc/devether.c:764,770 – 1992/0501/sys/src/9/pc/devether.c:755,760 | ||
| 1992/0424 | tb->busy = 1; } splx(s); | |
| 1992/0403 | } | |
| 1992/0424 | static void | |
| 1992/0425/sys/src/9/pc/devether.c:814,820 – 1992/0501/sys/src/9/pc/devether.c:804,813 | ||
| 1992/0424 | static Hw wd8013 = { 0x360, /* I/O base address */ KZERO|0xC8000, /* shared memory address */ | |
| 1992/0501 | 8*1024, 0, HOWMANY(sizeof(Etherpkt), 256), HOWMANY(8*1024, 256), | |
| 1992/0424 | wd8013reset, wd8013init, wd8013mode, | |
| 1992/0425/sys/src/9/pc/devether.c:827,830 – 1992/0501/sys/src/9/pc/devether.c:820,841 | ||
| 1992/0409 | void | |
| 1992/0411 | consdebug(void) | |
| 1992/0409 | { | |
| 1992/0501 | 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); | |
| 1992/0403 | } | |
| 1992/0501/sys/src/9/pc/devether.c:475,481 – 1992/0502/sys/src/9/pc/devether.c:475,481 (short | long) | ||
| 1992/0424 | rb = &cp->rb[cp->rh]; | |
| 1992/0501 | etherup(cp, rb->pkt, rb->len); | |
| 1992/0424 | rb->owner = Interface; | |
| 1992/0502 | cp->rh = NEXT(cp->rh, cp->nrb); | |
| 1992/0424 | } | |
| 1992/0410 | ||
| 1992/0424 | qunlock(&cp->rlock); | |
| 1992/0501/sys/src/9/pc/devether.c:614,623 – 1992/0502/sys/src/9/pc/devether.c:614,623 | ||
| 1992/0424 | int i; uchar msr; | |
| 1992/0403 | ||
| 1992/0501 |
| |
| 1992/0424 |
| |
| 1992/0501 | cp->rb = ialloc(sizeof(Buffer)*Nrb, 1); cp->nrb = Nrb; | |
| 1992/0502 | cp->tb = ialloc(sizeof(Buffer)*Ntb, 1); cp->ntb = Ntb; | |
| 1992/0424 | msr = IN(hw, msr); OUT(hw, msr, 0x40|msr); | |
| 1992/0501/sys/src/9/pc/devether.c:684,691 – 1992/0502/sys/src/9/pc/devether.c:684,689 | ||
| 1992/0424 | OUT(cp->hw, w.tcr, 0); | |
| 1992/0403 | } | |
| 1992/0501 |
| |
| 1992/0424 | static void wd8013receive(Ctlr *cp) | |
| 1992/0403 | { | |
| 1992/0501/sys/src/9/pc/devether.c:708,733 – 1992/0502/sys/src/9/pc/devether.c:706,727 | ||
| 1992/0424 | cp->inpackets++; p = &((Ring*)hw->ram)[next]; | |
| 1992/0501 | len = (p->len1<<8)|p->len0-4; | |
| 1992/0424 | rb = &cp->rb[cp->ri]; if(rb->owner == Interface){ | |
| 1992/0501 | rb->len = len; | |
| 1992/0424 |
| |
| 1992/0501 |
| |
| 1992/0502 | if((p->data+len) >= (hw->ram+hw->size)){ | |
| 1992/0501 | len = hw->ram+hw->size - p->data; memmove(rb->pkt+len, &((Ring*)hw->ram)[hw->pstart], | |
| 1992/0502 | (p->data+rb->len) - (hw->ram+hw->size)); | |
| 1992/0425 | } | |
| 1992/0501 | memmove(rb->pkt, p->data, len); | |
| 1992/0424 | rb->owner = Host; | |
| 1992/0502 | cp->ri = NEXT(cp->ri, cp->nrb); | |
| 1992/0424 | } | |
| 1992/0501 |
| |
| 1992/0502 | p->status = 0; | |
| 1992/0424 | next = p->next; bnry = next-1; | |
| 1992/0501 | if(bnry < hw->pstart) | |
| 1992/0501/sys/src/9/pc/devether.c:747,753 – 1992/0502/sys/src/9/pc/devether.c:741,746 | ||
| 1992/0424 | tb = &cp->tb[cp->ti]; if(tb->busy == 0 && tb->owner == Interface){ hw = cp->hw; | |
| 1992/0501 |
| |
| 1992/0424 | OUT(hw, w.tbcr0, tb->len & 0xFF); OUT(hw, w.tbcr1, (tb->len>>8) & 0xFF); | |
| 1992/0501/sys/src/9/pc/devether.c:785,791 – 1992/0502/sys/src/9/pc/devether.c:778,784 | ||
| 1992/0424 | tb = &cp->tb[cp->ti]; tb->owner = Host; tb->busy = 0; | |
| 1992/0502 | cp->ti = NEXT(cp->ti, cp->ntb); | |
| 1992/0424 | (*cp->hw->transmit)(cp); wakeup(&cp->tr); } | |
| 1992/0501/sys/src/9/pc/devether.c:820,841 – 1992/0502/sys/src/9/pc/devether.c:813,816 | ||
| 1992/0409 | void | |
| 1992/0411 | consdebug(void) | |
| 1992/0409 | { | |
| 1992/0501 |
| |
| 1992/0403 | } | |
| 1992/0502/sys/src/9/pc/devether.c:711,717 – 1992/0503/sys/src/9/pc/devether.c:711,717 (short | long) | ||
| 1992/0424 | if(rb->owner == Interface){ | |
| 1992/0501 | rb->len = len; | |
| 1992/0502 | if((p->data+len) >= (hw->ram+hw->size)){ | |
| 1992/0501 |
| |
| 1992/0503 | len = (hw->ram+hw->size) - p->data; | |
| 1992/0501 | memmove(rb->pkt+len, &((Ring*)hw->ram)[hw->pstart], | |
| 1992/0502 | (p->data+rb->len) - (hw->ram+hw->size)); | |
| 1992/0503/sys/src/9/pc/devether.c:83,94 – 1992/0505/sys/src/9/pc/devether.c:83,93 (short | long) | ||
| 1992/0424 | uchar ba[6]; /* broadcast address */ | |
| 1992/0403 | ||
| 1992/0424 | Rendez rr; /* rendezvous for a receive buffer */ | |
| 1992/0403 | ||
| 1992/0424 | Rendez tr; /* rendezvous for a transmit buffer */ | |
| 1992/0505 | QLock tlock; /* semaphore on th */ | |
| 1992/0424 | ushort th; /* first transmit buffer belonging to host */ ushort ti; /* first transmit buffer belonging to interface */ | |
| 1992/0503/sys/src/9/pc/devether.c:333,338 – 1992/0505/sys/src/9/pc/devether.c:332,338 | ||
| 1992/0410 | tp->prom = 0; tp->inuse = 0; netdisown(&tp->ctlr->net, tp - tp->ctlr->type); | |
| 1992/0505 | tp->ctlr = 0; | |
| 1992/0410 | qunlock(tp); | |
| 1992/0403 | } | |
| 1992/0503/sys/src/9/pc/devether.c:456,462 – 1992/0505/sys/src/9/pc/devether.c:456,462 | ||
| 1992/0403 | } | |
| 1992/0404 | cp->kproc = 1; | |
| 1992/0403 | for(;;){ | |
| 1992/0424 |
| |
| 1992/0505 | sleep(&cp->rr, isinput, cp); | |
| 1992/0424 | ||
| 1992/0406 | /* * process any internal loopback packets | |
| 1992/0503/sys/src/9/pc/devether.c:477,485 – 1992/0505/sys/src/9/pc/devether.c:477,482 | ||
| 1992/0424 | rb->owner = Interface; | |
| 1992/0502 | cp->rh = NEXT(cp->rh, cp->nrb); | |
| 1992/0424 | } | |
| 1992/0410 | ||
| 1992/0424 |
| |
| 1992/0410 | ||
| 1992/0503/sys/src/9/pc/devether.c:629,634 – 1992/0505/sys/src/9/pc/devether.c:626,643 | ||
| 1992/0424 | setvec(Ethervec, hw->intr); } | |
| 1992/0403 | ||
| 1992/0505 | 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 */ } | |
| 1992/0424 | /* * we leave the chip idling on internal loopback * and pointing to Page0. | |
| 1992/0503/sys/src/9/pc/devether.c:705,711 – 1992/0505/sys/src/9/pc/devether.c:714,726 | ||
| 1992/0424 | break; cp->inpackets++; p = &((Ring*)hw->ram)[next]; | |
| 1992/0501 |
| |
| 1992/0505 | 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; } | |
| 1992/0424 | rb = &cp->rb[cp->ri]; if(rb->owner == Interface){ | |
| 1992/0505/sys/src/9/pc/devether.c:716,723 – 1992/0506/sys/src/9/pc/devether.c:716,724 (short | long) | ||
| 1992/0424 | p = &((Ring*)hw->ram)[next]; | |
| 1992/0505 | len = ((p->len1<<8)|p->len0)-4; if(p->next < hw->pstart || p->next >= hw->pstop || len < 60){ | |
| 1992/0506 | print("%d/%d : #%2.2ux #%2.2ux #%2.2ux #%2.2ux\n", next, len, | |
| 1992/0505 | p->status, p->next, p->len0, p->len1); | |
| 1992/0506 | panic("receive"); | |
| 1992/0505 | dp8390rinit(cp); return; } | |
| 1992/0506/sys/src/9/pc/devether.c:59,64 – 1992/0625/sys/src/9/pc/devether.c:59,65 (short | long) | ||
| 1992/0403 | */ | |
| 1992/0410 | struct Type { | |
| 1992/0403 | QLock; | |
| 1992/0625 | Netprot; /* stat info */ | |
| 1992/0403 | int type; /* ethernet type */ int prom; /* promiscuous mode */ Queue *q; | |
| 1992/0506/sys/src/9/pc/devether.c:96,102 – 1992/0625/sys/src/9/pc/devether.c:97,102 | ||
| 1992/0424 | uchar kproc; /* true if kproc started */ char name[NAMELEN]; /* name of kproc */ | |
| 1992/0403 | Network net; | |
| 1992/0410 |
| |
| 1992/0403 | ||
| 1992/0424 | Queue lbq; /* software loopback packet queue */ | |
| 1992/0506/sys/src/9/pc/devether.c:331,337 – 1992/0625/sys/src/9/pc/devether.c:331,337 | ||
| 1992/0410 | tp->q = 0; tp->prom = 0; tp->inuse = 0; | |
| 1992/0625 | netdisown(tp); | |
| 1992/0505 | tp->ctlr = 0; | |
| 1992/0410 | qunlock(tp); | |
| 1992/0403 | } | |
| 1992/0506/sys/src/9/pc/devether.c:357,363 – 1992/0625/sys/src/9/pc/devether.c:357,363 | ||
| 1992/0403 | continue; } | |
| 1992/0410 | tp->inuse = 1; | |
| 1992/0625 | netown(tp, u->p->user, 0); | |
| 1992/0410 | qunlock(tp); return tp - cp->type; | |
| 1992/0403 | } | |
| 1992/0506/sys/src/9/pc/devether.c:483,490 – 1992/0625/sys/src/9/pc/devether.c:483,492 | ||
| 1992/0424 | void etherreset(void) { | |
| 1992/0625 | int i; Ctlr *cp; | |
| 1992/0410 | ||
| 1992/0625 | cp = &ctlr[0]; | |
| 1992/0424 | cp->hw = &wd8013; (*cp->hw->reset)(cp); | |
| 1992/0410 | ||
| 1992/0506/sys/src/9/pc/devether.c:497,507 – 1992/0625/sys/src/9/pc/devether.c:499,510 | ||
| 1992/0424 | cp->net.listen = 0; cp->net.clone = clonecon; cp->net.ninfo = 2; | |
| 1992/0625 | for(i = 0; i < NType; i++) netadd(&cp->net, &cp->type[i], i); | |
| 1992/0403 | } | |
| 1992/0425 | void | |
| 1992/0506/sys/src/9/pc/devether.c:611,619 – 1992/0625/sys/src/9/pc/devether.c:614,622 | ||
| 1992/0424 | int i; uchar msr; | |
| 1992/0403 | ||
| 1992/0501 |
| |
| 1992/0625 | cp->rb = xspanalloc(sizeof(Buffer)*Nrb, BY2PG, 0); | |
| 1992/0501 | cp->nrb = Nrb; | |
| 1992/0502 |
| |
| 1992/0625 | cp->tb = xspanalloc(sizeof(Buffer)*Ntb, BY2PG, 0); | |
| 1992/0502 | cp->ntb = Ntb; | |
| 1992/0424 | msr = IN(hw, msr); | |
| 1992/0625/sys/src/9/pc/devether.c:143,148 – 1992/0711/sys/src/9/pc/devether.c:143,149 (short | long) | ||
| 1992/0424 | void ethercreate(Chan *c, char *name, int omode, ulong perm) { | |
| 1992/0711 | USED(c, name, omode, perm); | |
| 1992/0424 | error(Eperm); } | |
| 1992/0625/sys/src/9/pc/devether.c:162,167 – 1992/0711/sys/src/9/pc/devether.c:163,169 | ||
| 1992/0424 | long etherwrite(Chan *c, char *a, long n, ulong offset) { | |
| 1992/0711 | USED(offset); | |
| 1992/0424 | return streamwrite(c, a, n, 0); } | |
| 1992/0625/sys/src/9/pc/devether.c:168,173 – 1992/0711/sys/src/9/pc/devether.c:170,176 | ||
| 1992/0424 | void etherremove(Chan *c) { | |
| 1992/0711 | USED(c); | |
| 1992/0424 | error(Eperm); } | |
| 1992/0625/sys/src/9/pc/devether.c:350,355 – 1992/0711/sys/src/9/pc/devether.c:353,359 | ||
| 1992/0404 | Ctlr *cp = &ctlr[0]; | |
| 1992/0410 | Type *tp; | |
| 1992/0403 | ||
| 1992/0711 | USED(c); | |
| 1992/0410 | for(tp = cp->type; tp < &cp->type[NType]; tp++){ qlock(tp); if(tp->inuse || tp->q){ | |
| 1992/0625/sys/src/9/pc/devether.c:362,367 – 1992/0711/sys/src/9/pc/devether.c:366,372 | ||
| 1992/0410 | return tp - cp->type; | |
| 1992/0403 | } exhausted("ether channels"); | |
| 1992/0711 | return 0; | |
| 1992/0403 | } static void | |
| 1992/0625/sys/src/9/pc/devether.c:370,375 – 1992/0711/sys/src/9/pc/devether.c:375,381 | ||
| 1992/0404 | Ctlr *cp = &ctlr[0]; | |
| 1992/0403 | char buf[256]; | |
| 1992/0711 | USED(c); | |
| 1992/0403 | 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", | |
| 1992/0404 | cp->inpackets, cp->outpackets, cp->crcs, cp->overflows, cp->frames, cp->buffs, cp->oerrs, | |
| 1992/0625/sys/src/9/pc/devether.c:693,698 – 1992/0711/sys/src/9/pc/devether.c:699,705 | ||
| 1992/0424 | static void wd8013online(Ctlr *cp, int on) | |
| 1992/0403 | { | |
| 1992/0711 | USED(on); | |
| 1992/0424 | OUT(cp->hw, w.tcr, 0); | |
| 1992/0403 | } | |
| 1992/0625/sys/src/9/pc/devether.c:777,782 – 1992/0711/sys/src/9/pc/devether.c:784,790 | ||
| 1992/0424 | Buffer *tb; uchar isr; | |
| 1992/0711 | USED(ur); | |
| 1992/0424 | while(isr = IN(hw, r.isr)){ OUT(hw, w.isr, isr); if(isr & 0x08) /* Txe - transmit error */ | |
| 1992/0711/sys/src/9/pc/devether.c:600,605 – 1992/0905/sys/src/9/pc/devether.c:600,612 (short | long) | ||
| 1992/0424 | }; } Wd8013; | |
| 1992/0403 | ||
| 1992/0905 | enum { MENB = 0x40, /* memory enable */ L16EN = 0x40, /* enable 16-bit LAN operation */ M16EN = 0x80, /* enable 16-bit memory access */ }; | |
| 1992/0424 | #define IN(hw, m) inb((hw)->addr+OFFSETOF(Wd8013, m)) #define OUT(hw, m, x) outb((hw)->addr+OFFSETOF(Wd8013, m), (x)) | |
| 1992/0711/sys/src/9/pc/devether.c:611,616 – 1992/0905/sys/src/9/pc/devether.c:618,644 | ||
| 1992/0501 | uchar data[256-4]; } Ring; | |
| 1992/0905 | 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)); } | |
| 1992/0424 | /* */ static void | |
| 1992/0711/sys/src/9/pc/devether.c:619,624 – 1992/0905/sys/src/9/pc/devether.c:647,653 | ||
| 1992/0424 | Hw *hw = cp->hw; int i; uchar msr; | |
| 1992/0905 | ulong ram; | |
| 1992/0403 | ||
| 1992/0625 | cp->rb = xspanalloc(sizeof(Buffer)*Nrb, BY2PG, 0); | |
| 1992/0501 | cp->nrb = Nrb; | |
| 1992/0711/sys/src/9/pc/devether.c:626,636 – 1992/0905/sys/src/9/pc/devether.c:655,671 | ||
| 1992/0502 | cp->ntb = Ntb; | |
| 1992/0424 | msr = IN(hw, msr); | |
| 1992/0905 | OUT(hw, msr, MENB|msr); | |
| 1992/0424 | for(i = 0; i < sizeof(cp->ea); i++) cp->ea[i] = IN(hw, lan[i]); | |
| 1992/0501 | ||
| 1992/0905 | /* 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); | |
| 1992/0424 | (*hw->init)(cp); setvec(Ethervec, hw->intr); } | |
| 1992/0711/sys/src/9/pc/devether.c:704,709 – 1992/0905/sys/src/9/pc/devether.c:739,755 | ||
| 1992/0403 | } | |
| 1992/0424 | static void | |
| 1992/0905 | bmemmove(void *a, void *b, int n) { uchar *to, *from; to = a; from = b; while(n-- > 0) *to++ = *from++; } static void | |
| 1992/0424 | wd8013receive(Ctlr *cp) | |
| 1992/0403 | { | |
| 1992/0424 | Hw *hw = cp->hw; | |
| 1992/0711/sys/src/9/pc/devether.c:723,736 – 1992/0905/sys/src/9/pc/devether.c:769,786 | ||
| 1992/0424 | if(next == curr) break; cp->inpackets++; | |
| 1992/0905 | print("*"); OUT(hw, laar, 0xC1); print("!"); | |
| 1992/0424 | p = &((Ring*)hw->ram)[next]; | |
| 1992/0905 | { int ii; for(ii = 0; ii < 30; ii++) print("%2.2ux ", p->data[ii]); for(;;); } | |
| 1992/0505 | len = ((p->len1<<8)|p->len0)-4; if(p->next < hw->pstart || p->next >= hw->pstop || len < 60){ | |
| 1992/0506 | print("%d/%d : #%2.2ux #%2.2ux #%2.2ux #%2.2ux\n", next, len, | |
| 1992/0505 | p->status, p->next, p->len0, p->len1); | |
| 1992/0506 |
| |
| 1992/0905 | OUT(hw, laar, 0x01); | |
| 1992/0505 | dp8390rinit(cp); | |
| 1992/0905 | break; | |
| 1992/0505 | } | |
| 1992/0424 | rb = &cp->rb[cp->ri]; | |
| 1992/0711/sys/src/9/pc/devether.c:738,748 – 1992/0905/sys/src/9/pc/devether.c:788,798 | ||
| 1992/0501 | rb->len = len; | |
| 1992/0502 | if((p->data+len) >= (hw->ram+hw->size)){ | |
| 1992/0503 | len = (hw->ram+hw->size) - p->data; | |
| 1992/0501 |
| |
| 1992/0905 | bmemmove(rb->pkt+len, | |
| 1992/0501 | &((Ring*)hw->ram)[hw->pstart], | |
| 1992/0502 | (p->data+rb->len) - (hw->ram+hw->size)); | |
| 1992/0425 | } | |
| 1992/0501 |
| |
| 1992/0905 | bmemmove(rb->pkt, p->data, len); | |
| 1992/0424 | rb->owner = Host; | |
| 1992/0502 | cp->ri = NEXT(cp->ri, cp->nrb); | |
| 1992/0424 | } | |
| 1992/0711/sys/src/9/pc/devether.c:749,759 – 1992/0905/sys/src/9/pc/devether.c:799,812 | ||
| 1992/0424 | ||
| 1992/0502 | p->status = 0; | |
| 1992/0424 | next = p->next; | |
| 1992/0905 | OUT(hw, laar, 0x01); print("?"); | |
| 1992/0424 | bnry = next-1; | |
| 1992/0501 | if(bnry < hw->pstart) bnry = hw->pstop-1; | |
| 1992/0424 | OUT(hw, w.bnry, bnry); } | |
| 1992/0905 | print(">"); | |
| 1992/0403 | } | |
| 1992/0424 | static void | |
| 1992/0711/sys/src/9/pc/devether.c:767,773 – 1992/0905/sys/src/9/pc/devether.c:820,826 | ||
| 1992/0424 | tb = &cp->tb[cp->ti]; if(tb->busy == 0 && tb->owner == Interface){ hw = cp->hw; | |
| 1992/0501 |
| |
| 1992/0905 | bmemmove(hw->ram, tb->pkt, tb->len); | |
| 1992/0424 | OUT(hw, w.tbcr0, tb->len & 0xFF); OUT(hw, w.tbcr1, (tb->len>>8) & 0xFF); OUT(hw, w.cr, 0x26); /* Page0|RD2|TXP|STA */ | |
| 1992/0711/sys/src/9/pc/devether.c:823,829 – 1992/0905/sys/src/9/pc/devether.c:876,882 | ||
| 1992/0409 | ||
| 1992/0424 | static Hw wd8013 = { 0x360, /* I/O base address */ | |
| 1992/0905 | KZERO|0xF0000, /* shared memory address */ | |
| 1992/0501 | 8*1024, 0, HOWMANY(sizeof(Etherpkt), 256), | |
| 1992/0711/sys/src/9/pc/devether.c:836,843 – 1992/0905/sys/src/9/pc/devether.c:889,891 | ||
| 1992/0424 | wd8013transmit, wd8013intr, }; | |
| 1992/0409 |
| |
| 1992/0411 |
| |
| 1992/0409 |
| |
| 1992/0403 |
| |
| 1992/0905/sys/src/9/pc/devether.c:15,20 – 1992/0906/sys/src/9/pc/devether.c:15,22 (short | long) | ||
| 1992/0424 | struct Hw { int addr; /* interface address */ | |
| 1992/0501 | uchar *ram; /* interface shared memory address */ | |
| 1992/0906 | int bt16; /* true if a 16 bit interface */ int lvl; /* interrupt level */ | |
| 1992/0501 | int size; uchar tstart; uchar pstart; | |
| 1992/0905/sys/src/9/pc/devether.c:639,645 – 1992/0906/sys/src/9/pc/devether.c:641,654 | ||
| 1992/0905 | print("id=#%2.2ux\n", IN(hw, id)); } | |
| 1992/0906 | /* mapping from configuration bits to interrupt level */ int intrmap[] = { 9, 3, 5, 7, 10, 11, 15, 4, }; | |
| 1992/0424 | /* | |
| 1992/0906 | * get configuration parameters, enable memory | |
| 1992/0424 | */ static void wd8013reset(Ctlr *cp) | |
| 1992/0905/sys/src/9/pc/devether.c:647,652 – 1992/0906/sys/src/9/pc/devether.c:656,664 | ||
| 1992/0424 | Hw *hw = cp->hw; int i; uchar msr; | |
| 1992/0906 | uchar icr; uchar laar; uchar irr; | |
| 1992/0905 | ulong ram; | |
| 1992/0403 | ||
| 1992/0625 | cp->rb = xspanalloc(sizeof(Buffer)*Nrb, BY2PG, 0); | |
| 1992/0905/sys/src/9/pc/devether.c:655,673 – 1992/0906/sys/src/9/pc/devether.c:667,713 | ||
| 1992/0502 | cp->ntb = Ntb; | |
| 1992/0424 | msr = IN(hw, msr); | |
| 1992/0905 |
| |
| 1992/0906 | icr = IN(hw, icr); irr = IN(hw, irr); laar = IN(hw, laar); | |
| 1992/0424 | ||
| 1992/0906 | /* ethernet address */ | |
| 1992/0424 | for(i = 0; i < sizeof(cp->ea); i++) cp->ea[i] = IN(hw, lan[i]); | |
| 1992/0501 | ||
| 1992/0905 |
| |
| 1992/0906 | /* 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; | |
| 1992/0905 | hw->ram = (uchar*)ram; | |
| 1992/0906 | /* 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); | |
| 1992/0424 | (*hw->init)(cp); | |
| 1992/0906 | setvec(Int0vec + hw->lvl, hw->intr); | |
| 1992/0424 | } | |
| 1992/0403 | ||
| 1992/0505 | static void | |
| 1992/0905/sys/src/9/pc/devether.c:693,699 – 1992/0906/sys/src/9/pc/devether.c:733,742 | ||
| 1992/0424 | int i; OUT(hw, w.cr, 0x21); /* Page0|RD2|STP */ | |
| 1992/0906 | if(hw->bt16) OUT(hw, w.dcr, 0x49); /* 16 bit interface, DMA burst size 8 */ else OUT(hw, w.dcr, 0x48); /* FT1|LS */ | |
| 1992/0424 | OUT(hw, w.rbcr0, 0); OUT(hw, w.rbcr1, 0); OUT(hw, w.rcr, 0x04); /* AB */ | |
| 1992/0905/sys/src/9/pc/devether.c:739,755 – 1992/0906/sys/src/9/pc/devether.c:782,787 | ||
| 1992/0403 | } | |
| 1992/0424 | static void | |
| 1992/0905 |
| |
| 1992/0424 | wd8013receive(Ctlr *cp) | |
| 1992/0403 | { | |
| 1992/0424 | Hw *hw = cp->hw; | |
| 1992/0905/sys/src/9/pc/devether.c:769,784 – 1992/0906/sys/src/9/pc/devether.c:801,811 | ||
| 1992/0424 | if(next == curr) break; cp->inpackets++; | |
| 1992/0905 |
| |
| 1992/0424 | p = &((Ring*)hw->ram)[next]; | |
| 1992/0905 |
| |
| 1992/0505 | len = ((p->len1<<8)|p->len0)-4; if(p->next < hw->pstart || p->next >= hw->pstop || len < 60){ | |
| 1992/0506 | print("%d/%d : #%2.2ux #%2.2ux #%2.2ux #%2.2ux\n", next, len, | |
| 1992/0505 | p->status, p->next, p->len0, p->len1); | |
| 1992/0905 |
| |
| 1992/0505 | dp8390rinit(cp); | |
| 1992/0905 | break; | |
| 1992/0505 | } | |
| 1992/0905/sys/src/9/pc/devether.c:788,798 – 1992/0906/sys/src/9/pc/devether.c:815,825 | ||
| 1992/0501 | rb->len = len; | |
| 1992/0502 | if((p->data+len) >= (hw->ram+hw->size)){ | |
| 1992/0503 | len = (hw->ram+hw->size) - p->data; | |
| 1992/0905 |
| |
| 1992/0906 | memmove(rb->pkt+len, | |
| 1992/0501 | &((Ring*)hw->ram)[hw->pstart], | |
| 1992/0502 | (p->data+rb->len) - (hw->ram+hw->size)); | |
| 1992/0425 | } | |
| 1992/0905 |
| |
| 1992/0906 | memmove(rb->pkt, p->data, len); | |
| 1992/0424 | rb->owner = Host; | |
| 1992/0502 | cp->ri = NEXT(cp->ri, cp->nrb); | |
| 1992/0424 | } | |
| 1992/0905/sys/src/9/pc/devether.c:799,812 – 1992/0906/sys/src/9/pc/devether.c:826,836 | ||
| 1992/0424 | ||
| 1992/0502 | p->status = 0; | |
| 1992/0424 | next = p->next; | |
| 1992/0905 |
| |
| 1992/0424 | bnry = next-1; | |
| 1992/0501 | if(bnry < hw->pstart) bnry = hw->pstop-1; | |
| 1992/0424 | OUT(hw, w.bnry, bnry); } | |
| 1992/0905 |
| |
| 1992/0403 | } | |
| 1992/0424 | static void | |
| 1992/0905/sys/src/9/pc/devether.c:817,826 – 1992/0906/sys/src/9/pc/devether.c:841,850 | ||
| 1992/0424 | int s; s = splhi(); | |
| 1992/0906 | hw = cp->hw; | |
| 1992/0424 | tb = &cp->tb[cp->ti]; if(tb->busy == 0 && tb->owner == Interface){ | |
| 1992/0905 |
| |
| 1992/0906 | memmove(hw->ram, tb->pkt, tb->len); | |
| 1992/0424 | OUT(hw, w.tbcr0, tb->len & 0xFF); OUT(hw, w.tbcr1, (tb->len>>8) & 0xFF); OUT(hw, w.cr, 0x26); /* Page0|RD2|TXP|STA */ | |
| 1992/0905/sys/src/9/pc/devether.c:876,886 – 1992/0906/sys/src/9/pc/devether.c:900,912 | ||
| 1992/0409 | ||
| 1992/0424 | static Hw wd8013 = { 0x360, /* I/O base address */ | |
| 1992/0905 |
| |
| 1992/0501 |
| |
| 1992/0906 | 0, 0, 0, 0, | |
| 1992/0501 | HOWMANY(sizeof(Etherpkt), 256), | |
| 1992/0906 | 0, | |
| 1992/0424 | wd8013reset, wd8013init, wd8013mode, | |
| 1992/0906/sys/src/9/pc/devether.c:13,18 – 1992/0909/sys/src/9/pc/devether.c:13,26 (short | long) | ||
| 1992/0424 | typedef struct Ctlr Ctlr; | |
| 1992/0403 | ||
| 1992/0424 | struct Hw { | |
| 1992/0909 | 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*); | |
| 1992/0424 | int addr; /* interface address */ | |
| 1992/0501 | uchar *ram; /* interface shared memory address */ | |
| 1992/0906 | int bt16; /* true if a 16 bit interface */ | |
| 1992/0906/sys/src/9/pc/devether.c:21,33 – 1992/0909/sys/src/9/pc/devether.c:29,34 | ||
| 1992/0501 | uchar tstart; uchar pstart; uchar pstop; | |
| 1992/0424 |
| |
| 1992/0404 | }; | |
| 1992/0424 | static Hw wd8013; | |
| 1992/0404 | ||
| 1992/0906/sys/src/9/pc/devether.c:464,470 – 1992/0909/sys/src/9/pc/devether.c:465,472 | ||
| 1992/0403 | } | |
| 1992/0404 | cp->kproc = 1; | |
| 1992/0403 | for(;;){ | |
| 1992/0505 |
| |
| 1992/0909 | tsleep(&cp->rr, isinput, cp, 1000); (*cp->hw->tweek)(cp); | |
| 1992/0424 | ||
| 1992/0406 | /* * process any internal loopback packets | |
| 1992/0906/sys/src/9/pc/devether.c:620,626 – 1992/0909/sys/src/9/pc/devether.c:622,627 | ||
| 1992/0501 | uchar data[256-4]; } Ring; | |
| 1992/0905 |
| |
| 1992/0906/sys/src/9/pc/devether.c:696,701 – 1992/0909/sys/src/9/pc/devether.c:697,703 | ||
| 1992/0906 | hw->size = 8*1024; if(hw->bt16) hw->size <<= 1; | |
| 1992/0909 | hw->pstart = HOWMANY(sizeof(Etherpkt), 256); | |
| 1992/0906 | hw->pstop = HOWMANY(hw->size, 256); print("ether width %d addr %lux size %d lvl %d\n", hw->bt16?16:8, | |
| 1992/0906/sys/src/9/pc/devether.c:704,710 – 1992/0909/sys/src/9/pc/devether.c:706,712 | ||
| 1992/0906 | /* enable interface RAM, set interface width */ OUT(hw, msr, MENB|msr); if(hw->bt16) | |
| 1992/0909 | OUT(hw, laar, laar|L16EN); | |
| 1992/0906 | ||
| 1992/0424 | (*hw->init)(cp); | |
| 1992/0906 | setvec(Int0vec + hw->lvl, hw->intr); | |
| 1992/0906/sys/src/9/pc/devether.c:711,716 – 1992/0909/sys/src/9/pc/devether.c:713,752 | ||
| 1992/0424 | } | |
| 1992/0403 | ||
| 1992/0505 | static void | |
| 1992/0909 | 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 | |
| 1992/0505 | dp8390rinit(Ctlr *cp) { Hw *hw = cp->hw; | |
| 1992/0906/sys/src/9/pc/devether.c:727,733 – 1992/0909/sys/src/9/pc/devether.c:763,769 | ||
| 1992/0424 | * and pointing to Page0. */ static void | |
| 1992/0909 | dp8390init(Ctlr *cp) | |
| 1992/0403 | { | |
| 1992/0424 | Hw *hw = cp->hw; int i; | |
| 1992/0906/sys/src/9/pc/devether.c:805,811 – 1992/0909/sys/src/9/pc/devether.c:841,847 | ||
| 1992/0505 | len = ((p->len1<<8)|p->len0)-4; if(p->next < hw->pstart || p->next >= hw->pstop || len < 60){ | |
| 1992/0506 | print("%d/%d : #%2.2ux #%2.2ux #%2.2ux #%2.2ux\n", next, len, | |
| 1992/0505 |
| |
| 1992/0909 | p->status, p->next, p->len0, p->len1);/**/ | |
| 1992/0505 | dp8390rinit(cp); | |
| 1992/0905 | break; | |
| 1992/0505 | } | |
| 1992/0906/sys/src/9/pc/devether.c:839,854 – 1992/0909/sys/src/9/pc/devether.c:875,900 | ||
| 1992/0424 | Hw *hw; Buffer *tb; int s; | |
| 1992/0909 | uchar laar; | |
| 1992/0424 | s = splhi(); | |
| 1992/0906 | hw = cp->hw; | |
| 1992/0424 | tb = &cp->tb[cp->ti]; if(tb->busy == 0 && tb->owner == Interface){ | |
| 1992/0909 | if(hw->bt16){ OUT(hw, w.imr, 0x0); laar = IN(hw, laar); OUT(hw, laar, laar|M16EN); } | |
| 1992/0906 | memmove(hw->ram, tb->pkt, tb->len); | |
| 1992/0424 | 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; | |
| 1992/0909 | if(hw->bt16 && (laar&M16EN)==0){ OUT(hw, laar, laar); OUT(hw, w.imr, 0x1F); } | |
| 1992/0424 | } splx(s); | |
| 1992/0403 | } | |
| 1992/0906/sys/src/9/pc/devether.c:859,866 – 1992/0909/sys/src/9/pc/devether.c:905,917 | ||
| 1992/0424 | Ctlr *cp = &ctlr[0]; Hw *hw = cp->hw; Buffer *tb; | |
| 1992/0909 | uchar isr, laar; | |
| 1992/0424 | ||
| 1992/0909 | if(hw->bt16){ laar = IN(hw, laar); OUT(hw, w.imr, 0x0); OUT(hw, laar, laar|M16EN); } | |
| 1992/0711 | USED(ur); | |
| 1992/0424 | while(isr = IN(hw, r.isr)){ OUT(hw, w.isr, isr); | |
| 1992/0906/sys/src/9/pc/devether.c:896,917 – 1992/0909/sys/src/9/pc/devether.c:947,967 | ||
| 1992/0424 | wakeup(&cp->rr); } } | |
| 1992/0909 | if(hw->bt16){ OUT(hw, laar, laar); OUT(hw, w.imr, 0x1F); } | |
| 1992/0409 | } | |
| 1992/0424 |
| |
| 1992/0501 |
| |
| 1992/0906 |
| |
| 1992/0501 |
| |
| 1992/0906 |
| |
| 1992/0909 | static Hw wd8013 = { | |
| 1992/0424 | wd8013reset, | |
| 1992/0909 | dp8390init, | |
| 1992/0424 | wd8013mode, wd8013online, wd8013receive, wd8013transmit, wd8013intr, | |
| 1992/0909 | wd8013tweek, 0x360, /* I/O base address */ | |
| 1992/0424 | }; | |
| 1992/0909/sys/src/9/pc/devether.c:20,26 – 1992/0913/sys/src/9/pc/devether.c:20,25 (short | long) | ||
| 1992/0909 | void (*receive)(Ctlr*); void (*transmit)(Ctlr*); void (*intr)(Ureg*); | |
| 1992/0424 | int addr; /* interface address */ | |
| 1992/0501 | uchar *ram; /* interface shared memory address */ | |
| 1992/0906 | int bt16; /* true if a 16 bit interface */ | |
| 1992/0909/sys/src/9/pc/devether.c:465,472 – 1992/0913/sys/src/9/pc/devether.c:464,470 | ||
| 1992/0403 | } | |
| 1992/0404 | cp->kproc = 1; | |
| 1992/0403 | for(;;){ | |
| 1992/0909 |
| |
| 1992/0913 | sleep(&cp->rr, isinput, cp); | |
| 1992/0424 | ||
| 1992/0406 | /* * process any internal loopback packets | |
| 1992/0909/sys/src/9/pc/devether.c:713,752 – 1992/0913/sys/src/9/pc/devether.c:711,716 | ||
| 1992/0424 | } | |
| 1992/0403 | ||
| 1992/0505 | static void | |
| 1992/0909 |
| |
| 1992/0505 | dp8390rinit(Ctlr *cp) { Hw *hw = cp->hw; | |
| 1992/0909/sys/src/9/pc/devether.c:962,967 – 1992/0913/sys/src/9/pc/devether.c:926,930 | ||
| 1992/0424 | wd8013receive, wd8013transmit, wd8013intr, | |
| 1992/0909 |
| |
| 1992/0424 | }; | |
| 1992/0913/sys/src/9/pc/devether.c:20,25 – 1992/0915/sys/src/9/pc/devether.c:20,26 (short | long) | ||
| 1992/0909 | void (*receive)(Ctlr*); void (*transmit)(Ctlr*); void (*intr)(Ureg*); | |
| 1992/0915 | void (*tweek)(Ctlr*); | |
| 1992/0424 | int addr; /* interface address */ | |
| 1992/0501 | uchar *ram; /* interface shared memory address */ | |
| 1992/0906 | int bt16; /* true if a 16 bit interface */ | |
| 1992/0913/sys/src/9/pc/devether.c:464,470 – 1992/0915/sys/src/9/pc/devether.c:465,472 | ||
| 1992/0403 | } | |
| 1992/0404 | cp->kproc = 1; | |
| 1992/0403 | for(;;){ | |
| 1992/0913 |
| |
| 1992/0915 | tsleep(&cp->rr, isinput, cp, 500); (*cp->hw->tweek)(cp); | |
| 1992/0424 | ||
| 1992/0406 | /* * process any internal loopback packets | |
| 1992/0913/sys/src/9/pc/devether.c:660,669 – 1992/0915/sys/src/9/pc/devether.c:662,673 | ||
| 1992/0906 | uchar irr; | |
| 1992/0905 | ulong ram; | |
| 1992/0403 | ||
| 1992/0625 |
| |
| 1992/0501 |
| |
| 1992/0625 |
| |
| 1992/0502 |
| |
| 1992/0915 | 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; } | |
| 1992/0424 | msr = IN(hw, msr); | |
| 1992/0906 | icr = IN(hw, icr); | |
| 1992/0913/sys/src/9/pc/devether.c:698,710 – 1992/0915/sys/src/9/pc/devether.c:702,714 | ||
| 1992/0909 | hw->pstart = HOWMANY(sizeof(Etherpkt), 256); | |
| 1992/0906 | hw->pstop = HOWMANY(hw->size, 256); | |
| 1992/0915 | /* print("ether width %d addr %lux size %d lvl %d\n", hw->bt16?16:8, hw->ram, hw->size, hw->lvl);/**/ | |
| 1992/0906 | /* enable interface RAM, set interface width */ OUT(hw, msr, MENB|msr); if(hw->bt16) | |
| 1992/0909 |
| |
| 1992/0915 | OUT(hw, laar, laar|L16EN|M16EN); | |
| 1992/0906 | ||
| 1992/0424 | (*hw->init)(cp); | |
| 1992/0906 | setvec(Int0vec + hw->lvl, hw->intr); | |
| 1992/0913/sys/src/9/pc/devether.c:734,745 – 1992/0915/sys/src/9/pc/devether.c:738,752 | ||
| 1992/0424 | OUT(hw, w.cr, 0x21); /* Page0|RD2|STP */ | |
| 1992/0906 | if(hw->bt16) | |
| 1992/0915 | OUT(hw, w.dcr, 0x61); /* 16 bit interface */ | |
| 1992/0906 | else OUT(hw, w.dcr, 0x48); /* FT1|LS */ | |
| 1992/0424 | OUT(hw, w.rbcr0, 0); OUT(hw, w.rbcr1, 0); | |
| 1992/0915 | if(cp->prom) OUT(hw, w.rcr, 0x14); /* PRO|AB */ else OUT(hw, w.rcr, 0x04); /* AB */ | |
| 1992/0424 | OUT(hw, w.tcr, 0x20); /* LB0 */ | |
| 1992/0501 | OUT(hw, w.bnry, hw->pstart); | |
| 1992/0913/sys/src/9/pc/devether.c:782,787 – 1992/0915/sys/src/9/pc/devether.c:789,816 | ||
| 1992/0403 | } | |
| 1992/0424 | static void | |
| 1992/0915 | 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 | |
| 1992/0424 | wd8013receive(Ctlr *cp) | |
| 1992/0403 | { | |
| 1992/0424 | Hw *hw = cp->hw; | |
| 1992/0913/sys/src/9/pc/devether.c:804,811 – 1992/0915/sys/src/9/pc/devether.c:833,841 | ||
| 1992/0424 | p = &((Ring*)hw->ram)[next]; | |
| 1992/0505 | len = ((p->len1<<8)|p->len0)-4; if(p->next < hw->pstart || p->next >= hw->pstop || len < 60){ | |
| 1992/0506 |
| |
| 1992/0915 | /* print("%d/%d : #%2.2ux #%2.2ux #%2.2ux #%2.2ux\n", next, len, | |
| 1992/0909 | p->status, p->next, p->len0, p->len1);/**/ | |
| 1992/0915 | delay(100); | |
| 1992/0505 | dp8390rinit(cp); | |
| 1992/0905 | break; | |
| 1992/0505 | } | |
| 1992/0913/sys/src/9/pc/devether.c:830,835 – 1992/0915/sys/src/9/pc/devether.c:860,866 | ||
| 1992/0501 | if(bnry < hw->pstart) bnry = hw->pstop-1; | |
| 1992/0424 | OUT(hw, w.bnry, bnry); | |
| 1992/0915 | break; | |
| 1992/0424 | } | |
| 1992/0403 | } | |
| 1992/0913/sys/src/9/pc/devether.c:839,864 – 1992/0915/sys/src/9/pc/devether.c:870,885 | ||
| 1992/0424 | Hw *hw; Buffer *tb; int s; | |
| 1992/0909 |
| |
| 1992/0424 | s = splhi(); | |
| 1992/0906 | hw = cp->hw; | |
| 1992/0424 | tb = &cp->tb[cp->ti]; if(tb->busy == 0 && tb->owner == Interface){ | |
| 1992/0909 |
| |
| 1992/0906 | memmove(hw->ram, tb->pkt, tb->len); | |
| 1992/0424 | 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; | |
| 1992/0909 |
| |
| 1992/0424 | } splx(s); | |
| 1992/0403 | } | |
| 1992/0913/sys/src/9/pc/devether.c:869,881 – 1992/0915/sys/src/9/pc/devether.c:890,897 | ||
| 1992/0424 | Ctlr *cp = &ctlr[0]; Hw *hw = cp->hw; Buffer *tb; | |
| 1992/0909 |
| |
| 1992/0915 | uchar isr; | |
| 1992/0424 | ||
| 1992/0909 |
| |
| 1992/0711 | USED(ur); | |
| 1992/0424 | while(isr = IN(hw, r.isr)){ OUT(hw, w.isr, isr); | |
| 1992/0913/sys/src/9/pc/devether.c:911,920 – 1992/0915/sys/src/9/pc/devether.c:927,932 | ||
| 1992/0424 | wakeup(&cp->rr); } } | |
| 1992/0909 |
| |
| 1992/0409 | } | |
| 1992/0909 | static Hw wd8013 = | |
| 1992/0913/sys/src/9/pc/devether.c:926,930 – 1992/0915/sys/src/9/pc/devether.c:938,943 | ||
| 1992/0424 | wd8013receive, wd8013transmit, wd8013intr, | |
| 1992/0915 | wd8013tweek, | |
| 1992/0909 | 0x360, /* I/O base address */ | |
| 1992/0424 | }; | |
| 1992/0915/sys/src/9/pc/devether.c:738,744 – 1992/0916/sys/src/9/pc/devether.c:738,744 (short | long) | ||
| 1992/0424 | OUT(hw, w.cr, 0x21); /* Page0|RD2|STP */ | |
| 1992/0906 | if(hw->bt16) | |
| 1992/0915 |
| |
| 1992/0916 | OUT(hw, w.dcr, 0x01); /* 16 bit interface */ | |
| 1992/0906 | else OUT(hw, w.dcr, 0x48); /* FT1|LS */ | |
| 1992/0424 | OUT(hw, w.rbcr0, 0); | |
| 1992/0916/sys/src/9/pc/devether.c:13,19 – 1992/0917/sys/src/9/pc/devether.c:13,19 (short | long) | ||
| 1992/0424 | typedef struct Ctlr Ctlr; | |
| 1992/0403 | ||
| 1992/0424 | struct Hw { | |
| 1992/0909 |
| |
| 1992/0917 | int (*reset)(Ctlr*); | |
| 1992/0909 | void (*init)(Ctlr*); void (*mode)(Ctlr*, int); void (*online)(Ctlr*, int); | |
| 1992/0916/sys/src/9/pc/devether.c:77,82 – 1992/0917/sys/src/9/pc/devether.c:77,83 | ||
| 1992/0403 | QLock; | |
| 1992/0424 | Hw *hw; | |
| 1992/0917 | int present; | |
| 1992/0403 | ||
| 1992/0424 | ushort nrb; /* number of software receive buffers */ ushort ntb; /* number of software transmit buffers */ | |
| 1992/0916/sys/src/9/pc/devether.c:116,121 – 1992/0917/sys/src/9/pc/devether.c:117,124 | ||
| 1992/0425 | Chan* etherattach(char *spec) | |
| 1992/0424 | { | |
| 1992/0917 | if(ctlr[0].present == 0) error(Enodev); | |
| 1992/0425 | return devattach('l', spec); | |
| 1992/0424 | } | |
| 1992/0411 | ||
| 1992/0916/sys/src/9/pc/devether.c:498,504 – 1992/0917/sys/src/9/pc/devether.c:501,511 | ||
| 1992/0410 | ||
| 1992/0625 | cp = &ctlr[0]; | |
| 1992/0424 | cp->hw = &wd8013; | |
| 1992/0917 | if((*cp->hw->reset)(cp) < 0){ cp->present = 0; return; } cp->present = 1; | |
| 1992/0410 | ||
| 1992/0424 | memset(cp->ba, 0xFF, sizeof(cp->ba)); | |
| 1992/0410 | ||
| 1992/0916/sys/src/9/pc/devether.c:524,529 – 1992/0917/sys/src/9/pc/devether.c:531,539 | ||
| 1992/0424 | Ctlr *cp = &ctlr[ctlrno]; int i; | |
| 1992/0403 | ||
| 1992/0917 | if(cp->present == 0) return; | |
| 1992/0424 | cp->rh = 0; cp->ri = 0; for(i = 0; i < cp->nrb; i++) | |
| 1992/0916/sys/src/9/pc/devether.c:601,606 – 1992/0917/sys/src/9/pc/devether.c:611,640 | ||
| 1992/0424 | uchar curr; uchar mar[8]; }; | |
| 1992/0917 | 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; | |
| 1992/0424 | }; } Wd8013; | |
| 1992/0403 | ||
| 1992/0916/sys/src/9/pc/devether.c:607,614 – 1992/0917/sys/src/9/pc/devether.c:641,659 | ||
| 1992/0905 | enum { MENB = 0x40, /* memory enable */ | |
| 1992/0917 | /* 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), | |
| 1992/0905 | }; | |
| 1992/0424 | #define IN(hw, m) inb((hw)->addr+OFFSETOF(Wd8013, m)) | |
| 1992/0916/sys/src/9/pc/devether.c:648,657 – 1992/0917/sys/src/9/pc/devether.c:693,703 | ||
| 1992/0906 | 9, 3, 5, 7, 10, 11, 15, 4, }; | |
| 1992/0917 | ||
| 1992/0424 | /* | |
| 1992/0906 | * get configuration parameters, enable memory | |
| 1992/0424 | */ | |
| 1992/0917 | static int | |
| 1992/0424 | wd8013reset(Ctlr *cp) | |
| 1992/0403 | { | |
| 1992/0424 | Hw *hw = cp->hw; | |
| 1992/0916/sys/src/9/pc/devether.c:662,667 – 1992/0917/sys/src/9/pc/devether.c:708,721 | ||
| 1992/0906 | uchar irr; | |
| 1992/0905 | ulong ram; | |
| 1992/0403 | ||
| 1992/0917 | 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; | |
| 1992/0915 | if(cp->rb == 0){ cp->rb = xspanalloc(sizeof(Buffer)*Nrb, BY2PG, 0); cp->nrb = Nrb; | |
| 1992/0916/sys/src/9/pc/devether.c:669,679 – 1992/0917/sys/src/9/pc/devether.c:723,728 | ||
| 1992/0915 | cp->ntb = Ntb; } | |
| 1992/0424 |
| |
| 1992/0906 |
| |
| 1992/0424 | ||
| 1992/0906 | /* ethernet address */ | |
| 1992/0424 | for(i = 0; i < sizeof(cp->ea); i++) cp->ea[i] = IN(hw, lan[i]); | |
| 1992/0916/sys/src/9/pc/devether.c:708,717 – 1992/0917/sys/src/9/pc/devether.c:757,767 | ||
| 1992/0906 | /* enable interface RAM, set interface width */ OUT(hw, msr, MENB|msr); if(hw->bt16) | |
| 1992/0915 |
| |
| 1992/0917 | OUT(hw, laar, laar|L16EN|M16EN|ZeroWS16); | |
| 1992/0906 | ||
| 1992/0424 | (*hw->init)(cp); | |
| 1992/0906 | setvec(Int0vec + hw->lvl, hw->intr); | |
| 1992/0917 | return 0; | |
| 1992/0424 | } | |
| 1992/0403 | ||
| 1992/0505 | static void | |
| 1992/0916/sys/src/9/pc/devether.c:719,729 – 1992/0917/sys/src/9/pc/devether.c:769,779 | ||
| 1992/0505 | { Hw *hw = cp->hw; | |
| 1992/0917 | OUT(hw, w.cr, Page0|RD2|STP); | |
| 1992/0505 | OUT(hw, w.bnry, hw->pstart); | |
| 1992/0917 | OUT(hw, w.cr, Page1|RD2|STP); | |
| 1992/0505 | OUT(hw, curr, hw->pstart+1); | |
| 1992/0917 | OUT(hw, w.cr, Page0|RD2|STA); | |
| 1992/0505 | } | |
| 1992/0424 | /* | |
| 1992/0916/sys/src/9/pc/devether.c:736,744 – 1992/0917/sys/src/9/pc/devether.c:786,794 | ||
| 1992/0424 | Hw *hw = cp->hw; int i; | |
| 1992/0917 | OUT(hw, w.cr, Page0|RD2|STP); | |
| 1992/0906 | if(hw->bt16) | |
| 1992/0916 |
| |
| 1992/0917 | OUT(hw, w.dcr, (1<<0)|(3<<5)); /* 16 bit interface, 12 byte DMA burst */ | |
| 1992/0906 | else OUT(hw, w.dcr, 0x48); /* FT1|LS */ | |
| 1992/0424 | OUT(hw, w.rbcr0, 0); | |
| 1992/0916/sys/src/9/pc/devether.c:755,766 – 1992/0917/sys/src/9/pc/devether.c:805,816 | ||
| 1992/0424 | OUT(hw, w.isr, 0xFF); OUT(hw, w.imr, 0x1F); /* OVWE|TXEE|RXEE|PTXE|PRXE */ | |
| 1992/0917 | OUT(hw, w.cr, Page1|RD2|STP); | |
| 1992/0424 | for(i = 0; i < sizeof(cp->ea); i++) OUT(hw, par[i], cp->ea[i]); | |
| 1992/0501 | OUT(hw, curr, hw->pstart+1); | |
| 1992/0424 |
| |
| 1992/0917 | OUT(hw, w.cr, Page0|RD2|STA); | |
| 1992/0424 | OUT(hw, w.tpsr, 0); | |
| 1992/0403 | } | |
| 1992/0916/sys/src/9/pc/devether.c:810,815 – 1992/0917/sys/src/9/pc/devether.c:860,888 | ||
| 1992/0915 | splx(s); } | |
| 1992/0917 | /* * 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; } } | |
| 1992/0915 | static void | |
| 1992/0424 | wd8013receive(Ctlr *cp) | |
| 1992/0403 | { | |
| 1992/0916/sys/src/9/pc/devether.c:817,845 – 1992/0917/sys/src/9/pc/devether.c:890,917 | ||
| 1992/0424 | Buffer *rb; uchar bnry, curr, next; Ring *p; | |
| 1992/0501 |
| |
| 1992/0917 | int i, len; | |
| 1992/0424 | bnry = IN(hw, r.bnry); | |
| 1992/0501 | next = bnry+1; if(next >= hw->pstop) next = hw->pstart; | |
| 1992/0424 |
| |
| 1992/0917 | for(i = 0; ; i++){ OUT(hw, w.cr, Page1|RD2|STA); | |
| 1992/0424 | curr = IN(hw, curr); | |
| 1992/0917 | OUT(hw, w.cr, Page0|RD2|STA); | |
| 1992/0424 | if(next == curr) break; | |
| 1992/0917 | waitfordma(hw); | |
| 1992/0424 | cp->inpackets++; p = &((Ring*)hw->ram)[next]; | |
| 1992/0505 | len = ((p->len1<<8)|p->len0)-4; if(p->next < hw->pstart || p->next >= hw->pstop || len < 60){ | |
| 1992/0915 |
| |
| 1992/0917 | /*print("%d/%d : #%2.2ux #%2.2ux #%2.2ux #%2.2ux\n", next, len, | |
| 1992/0909 | p->status, p->next, p->len0, p->len1);/**/ | |
| 1992/0915 |
| |
| 1992/0505 | dp8390rinit(cp); | |
| 1992/0905 | break; | |
| 1992/0505 | } | |
| 1992/0424 |
| |
| 1992/0501 | rb->len = len; | |
| 1992/0916/sys/src/9/pc/devether.c:853,859 – 1992/0917/sys/src/9/pc/devether.c:925,930 | ||
| 1992/0424 | rb->owner = Host; | |
| 1992/0502 | cp->ri = NEXT(cp->ri, cp->nrb); | |
| 1992/0424 | } | |
| 1992/0502 | p->status = 0; | |
| 1992/0424 | next = p->next; bnry = next-1; | |
| 1992/0916/sys/src/9/pc/devether.c:860,866 – 1992/0917/sys/src/9/pc/devether.c:931,936 | ||
| 1992/0501 | if(bnry < hw->pstart) bnry = hw->pstop-1; | |
| 1992/0424 | OUT(hw, w.bnry, bnry); | |
| 1992/0915 |
| |
| 1992/0424 | } | |
| 1992/0403 | } | |
| 1992/0916/sys/src/9/pc/devether.c:878,884 – 1992/0917/sys/src/9/pc/devether.c:948,954 | ||
| 1992/0906 | memmove(hw->ram, tb->pkt, tb->len); | |
| 1992/0424 | OUT(hw, w.tbcr0, tb->len & 0xFF); OUT(hw, w.tbcr1, (tb->len>>8) & 0xFF); | |
| 1992/0917 | OUT(hw, w.cr, Page0|RD2|TXP|STA); | |
| 1992/0424 | tb->busy = 1; } splx(s); | |
| 1992/0916/sys/src/9/pc/devether.c:895,900 – 1992/0917/sys/src/9/pc/devether.c:965,979 | ||
| 1992/0711 | USED(ur); | |
| 1992/0424 | while(isr = IN(hw, r.isr)){ OUT(hw, w.isr, isr); | |
| 1992/0917 | /* * 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++; | |
| 1992/0424 | if(isr & 0x08) /* Txe - transmit error */ cp->oerrs++; if(isr & 0x04){ /* Rxe - receive error */ | |
| 1992/0916/sys/src/9/pc/devether.c:916,930 – 1992/0917/sys/src/9/pc/devether.c:995,1000 | ||
| 1992/0502 | cp->ti = NEXT(cp->ti, cp->ntb); | |
| 1992/0424 | (*cp->hw->transmit)(cp); wakeup(&cp->tr); | |
| 1992/0409 | } | |
| 1992/0917/sys/src/9/pc/devether.c:693,699 – 1992/0918/sys/src/9/pc/devether.c:693,698 (short | long) | ||
| 1992/0906 | 9, 3, 5, 7, 10, 11, 15, 4, }; | |
| 1992/0917 | ||
| 1992/0424 | /* | |
| 1992/0906 | * get configuration parameters, enable memory | |
| 1992/0424 | */ | |
| 1992/0917/sys/src/9/pc/devether.c:702,719 – 1992/0918/sys/src/9/pc/devether.c:701,728 | ||
| 1992/0403 | { | |
| 1992/0424 | Hw *hw = cp->hw; int i; | |
| 1992/0906 |
| |
| 1992/0918 | uchar msr, icr, laar, irr; | |
| 1992/0905 | ulong ram; | |
| 1992/0403 | ||
| 1992/0917 |
| |
| 1992/0918 | /* 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 */ | |
| 1992/0917 |
| |
| 1992/0918 | /* 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) | |
| 1992/0917 | return -1; | |
| 1992/0915 | if(cp->rb == 0){ | |
| 1992/0917/sys/src/9/pc/devether.c:723,732 – 1992/0918/sys/src/9/pc/devether.c:732,737 | ||
| 1992/0915 | cp->ntb = Ntb; } | |
| 1992/0424 | ||
| 1992/0906 |
| |
| 1992/0424 |
| |
| 1992/0501 | ||
| 1992/0906 | /* 16 bit operation? */ hw->bt16 = icr & 0x1; | |
| 1992/0917/sys/src/9/pc/devether.c:751,757 – 1992/0918/sys/src/9/pc/devether.c:756,762 | ||
| 1992/0909 | hw->pstart = HOWMANY(sizeof(Etherpkt), 256); | |
| 1992/0906 | hw->pstop = HOWMANY(hw->size, 256); | |
| 1992/0915 |
| |
| 1992/0918 | print("elite at %lux width %d addr %lux size %d lvl %d\n", hw->addr, hw->bt16?16:8, | |
| 1992/0915 | hw->ram, hw->size, hw->lvl);/**/ | |
| 1992/0906 | /* enable interface RAM, set interface width */ | |
| 1992/0917/sys/src/9/pc/devether.c:902,908 – 1992/0918/sys/src/9/pc/devether.c:907,914 | ||
| 1992/0917 | OUT(hw, w.cr, Page0|RD2|STA); | |
| 1992/0424 | if(next == curr) break; | |
| 1992/0917 |
| |
| 1992/0918 | if(strcmp(machtype, "NCRD.0") == 0) waitfordma(hw); | |
| 1992/0424 | cp->inpackets++; p = &((Ring*)hw->ram)[next]; | |
| 1992/0505 | len = ((p->len1<<8)|p->len0)-4; | |
| 1992/0917/sys/src/9/pc/devether.c:1009,1013 – 1992/0918/sys/src/9/pc/devether.c:1015,1018 | ||
| 1992/0424 | wd8013transmit, wd8013intr, | |
| 1992/0915 | wd8013tweek, | |
| 1992/0909 |
| |
| 1992/0424 | }; | |
| Too many diffs (26 > 25). Stopping. | ||