📄 ether8169.c
字号:
rtl8169halt(ctlr); /* * MAC Address. * Must put chip into config register write enable mode. */ csr8w(ctlr, Cr9346, Eem1|Eem0); r = (edev->ea[3]<<24)|(edev->ea[2]<<16)|(edev->ea[1]<<8)|edev->ea[0]; csr32w(ctlr, Idr0, r); r = (edev->ea[5]<<8)|edev->ea[4]; csr32w(ctlr, Idr0+4, r); /* * Transmitter. */ memset(ctlr->td, 0, sizeof(D)*ctlr->ntd); ctlr->tdh = ctlr->tdt = 0; ctlr->td[ctlr->ntd-1].control = Eor; /* * Receiver. * Need to do something here about the multicast filter. */ memset(ctlr->rd, 0, sizeof(D)*ctlr->nrd); ctlr->rdh = ctlr->rdt = 0; ctlr->rd[ctlr->nrd-1].control = Eor; rtl8169replenish(ctlr); ctlr->rcr = Rxfthnone|Mrxdmaunlimited|Ab|Apm; /* * Mtps is in units of 128 except for the RTL8169 * where is is 32. If using jumbo frames should be * set to 0x3F. * Setting Mulrw in Cplusc disables the Tx/Rx DMA burst * settings in Tcr/Rcr; the (1<<14) is magic. */ ctlr->mtps = HOWMANY(Mps, 128); cplusc = csr16r(ctlr, Cplusc) & ~(1<<14); cplusc |= Rxchksum|Mulrw; switch(ctlr->macv){ default: return -1; case Macv01: ctlr->mtps = HOWMANY(Mps, 32); break; case Macv02: case Macv03: cplusc |= (1<<14); /* magic */ break; case Macv05: /* * This is interpreted from clearly bogus code * in the manufacturer-supplied driver, it could * be wrong. Untested. */ r = csr8r(ctlr, Config2) & 0x07; if(r == 0x01) /* 66MHz PCI */ csr32w(ctlr, 0x7C, 0x0007FFFF); /* magic */ else csr32w(ctlr, 0x7C, 0x0007FF00); /* magic */ pciclrmwi(ctlr->pcidev); break; case Macv13: /* * This is interpreted from clearly bogus code * in the manufacturer-supplied driver, it could * be wrong. Untested. */ pcicfgw8(ctlr->pcidev, 0x68, 0x00); /* magic */ pcicfgw8(ctlr->pcidev, 0x69, 0x08); /* magic */ break; case Macv04: case Macv11: case Macv12: case Macv14: case Macv15: break; } /* * Enable receiver/transmitter. * Need to do this first or some of the settings below * won't take. */ switch(ctlr->pciv){ default: csr8w(ctlr, Cr, Te|Re); csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited); csr32w(ctlr, Rcr, ctlr->rcr); case Rtl8169sc: case Rtl8168b: break; } /* * Interrupts. * Disable Tdu|Tok for now, the transmit routine will tidy. * Tdu means the NIC ran out of descriptors to send, so it * doesn't really need to ever be on. */ csr32w(ctlr, Timerint, 0); csr16w(ctlr, Imr, Serr|Timeout|Fovw|Punlc|Rdu|Ter|Rer|Rok); /* * Clear missed-packet counter; * initial early transmit threshold value; * set the descriptor ring base addresses; * set the maximum receive packet size; * no early-receive interrupts. */ csr32w(ctlr, Mpc, 0); csr8w(ctlr, Mtps, ctlr->mtps); csr32w(ctlr, Tnpds+4, 0); csr32w(ctlr, Tnpds, PCIWADDR(ctlr->td)); csr32w(ctlr, Rdsar+4, 0); csr32w(ctlr, Rdsar, PCIWADDR(ctlr->rd)); csr16w(ctlr, Rms, Mps); r = csr16r(ctlr, Mulint) & 0xF000; csr16w(ctlr, Mulint, r); csr16w(ctlr, Cplusc, cplusc); /* * Set configuration. */ switch(ctlr->pciv){ default: break; case Rtl8169sc: csr16w(ctlr, 0xE2, 0); /* magic */ csr8w(ctlr, Cr, Te|Re); csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited); csr32w(ctlr, Rcr, ctlr->rcr); break; case Rtl8168b: case Rtl8169c: csr16w(ctlr, 0xE2, 0); /* magic */ csr16w(ctlr, Cplusc, 0x2000); /* magic */ csr8w(ctlr, Cr, Te|Re); csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited); csr32w(ctlr, Rcr, ctlr->rcr); csr16w(ctlr, Rms, 0x0800); csr8w(ctlr, Mtps, 0x3F); break; } csr8w(ctlr, Cr9346, 0); iunlock(&ctlr->ilock);// rtl8169mii(ctlr); return 0;}static voidrtl8169attach(Ether* edev){ int timeo; Ctlr *ctlr; ctlr = edev->ctlr; qlock(&ctlr->alock); if(ctlr->init == 0){ /* * Handle allocation/init errors here. */ ctlr->td = xspanalloc(sizeof(D)*Ntd, 256, 0); ctlr->tb = malloc(Ntd*sizeof(Block*)); ctlr->ntd = Ntd; ctlr->rd = xspanalloc(sizeof(D)*Nrd, 256, 0); ctlr->rb = malloc(Nrd*sizeof(Block*)); ctlr->nrd = Nrd; ctlr->dtcc = xspanalloc(sizeof(Dtcc), 64, 0); rtl8169init(edev); ctlr->init = 1; } qunlock(&ctlr->alock); for(timeo = 0; timeo < 3500; timeo++){ if(miistatus(ctlr->mii) == 0) break; delay(10); }}static voidrtl8169transmit(Ether* edev){ D *d; Block *bp; Ctlr *ctlr; int control, x; RingBuf *tb; ctlr = edev->ctlr; ilock(&ctlr->tlock); for(x = ctlr->tdh; ctlr->ntq > 0; x = NEXT(x, ctlr->ntd)){ d = &ctlr->td[x]; if((control = d->control) & Own) break; /* * Check errors and log here. */ USED(control); /* * Free it up. * Need to clean the descriptor here? Not really. * Simple freeb for now (no chain and freeblist). * Use ntq count for now. */ freeb(ctlr->tb[x]); ctlr->tb[x] = nil; d->control &= Eor; ctlr->ntq--; } ctlr->tdh = x; x = ctlr->tdt; while(ctlr->ntq < (ctlr->ntd-1)){ tb = &edev->tb[edev->ti]; if(tb->owner != Interface) break; bp = allocb(tb->len); memmove(bp->wp, tb->pkt, tb->len); memmove(bp->wp+Eaddrlen, edev->ea, Eaddrlen); bp->wp += tb->len; tb->owner = Host; edev->ti = NEXT(edev->ti, edev->ntb); d = &ctlr->td[x]; d->addrlo = PCIWADDR(bp->rp); d->addrhi = 0; ctlr->tb[x] = bp; coherence(); d->control |= Own|Fs|Ls|((BLEN(bp)<<TxflSHIFT) & TxflMASK); x = NEXT(x, ctlr->ntd); ctlr->ntq++; } if(x != ctlr->tdt){ ctlr->tdt = x; csr8w(ctlr, Tppoll, Npq); } else if(ctlr->ntq >= (ctlr->ntd-1)) ctlr->txdu++; iunlock(&ctlr->tlock);}static voidrtl8169receive(Ether* edev){ D *d; int len, rdh; Ctlr *ctlr; u32int control; RingBuf *ring; ctlr = edev->ctlr; rdh = ctlr->rdh; for(;;){ d = &ctlr->rd[rdh]; if(d->control & Own) break; control = d->control; if((control & (Fs|Ls|Res)) == (Fs|Ls)){ len = ((control & RxflMASK)>>RxflSHIFT) - 4; ring = &edev->rb[edev->ri]; if(ring->owner == Interface){ ring->owner = Host; ring->len = len; memmove(ring->pkt, ctlr->rb[rdh], len); edev->ri = NEXT(edev->ri, edev->nrb); } } else{ /* * Error stuff here. print("control %#8.8ux\n", control); */ } d->control &= Eor; ctlr->nrdfree--; rdh = NEXT(rdh, ctlr->nrd); } ctlr->rdh = rdh; if(ctlr->nrdfree < ctlr->nrd/2) rtl8169replenish(ctlr);}static voidrtl8169interrupt(Ureg*, void* arg){ Ctlr *ctlr; Ether *edev; u32int isr; edev = arg; ctlr = edev->ctlr; while((isr = csr16r(ctlr, Isr)) != 0 && isr != 0xFFFF){ csr16w(ctlr, Isr, isr); if(isr & (Fovw|Punlc|Rdu|Rer|Rok)){ rtl8169receive(edev); if(!(isr & (Punlc|Rok))) ctlr->ierrs++; if(isr & Rer) ctlr->rer++; if(isr & Rdu) ctlr->rdu++; if(isr & Punlc) ctlr->punlc++; if(isr & Fovw) ctlr->fovw++; isr &= ~(Fovw|Rdu|Rer|Rok); } if(isr & (Tdu|Ter|Tok)){ rtl8169transmit(edev); isr &= ~(Tdu|Ter|Tok); } if(isr & Punlc){// rtl8169link(edev); isr &= ~Punlc; } /* * Some of the reserved bits get set sometimes... */ if(isr & (Serr|Timeout|Tdu|Fovw|Punlc|Rdu|Ter|Tok|Rer|Rok)) panic("rtl8169interrupt: imr %#4.4ux isr %#4.4ux\n", csr16r(ctlr, Imr), isr); }}static voidrtl8169pci(void){ Pcidev *p; Ctlr *ctlr; int i, port; u32int bar; p = nil; while(p = pcimatch(p, 0, 0)){ if(p->ccrb != 0x02 || p->ccru != 0) continue; switch(i = ((p->did<<16)|p->vid)){ default: continue; case Rtl8100e: /* RTL810[01]E ? */ case Rtl8169c: /* RTL8169C */ case Rtl8169sc: /* RTL8169SC */ case Rtl8168b: /* RTL8168B */ case Rtl8169: /* RTL8169 */ break; case (0xC107<<16)|0x1259: /* Corega CG-LAPCIGT */ i = Rtl8169; break; } bar = p->mem[0].bar; port = bar & ~0x01; if(ioalloc(port, p->mem[0].size, 0, "rtl8169") < 0){ print("rtl8169: port %#ux in use\n", port); continue; } ctlr = malloc(sizeof(Ctlr)); ctlr->port = port; ctlr->pcidev = p; ctlr->pciv = i; if(pcigetpms(p) > 0){ pcisetpms(p, 0); for(i = 0; i < 6; i++) pcicfgw32(p, PciBAR0+i*4, p->mem[i].bar); pcicfgw8(p, PciINTL, p->intl); pcicfgw8(p, PciLTR, p->ltr); pcicfgw8(p, PciCLS, p->cls); pcicfgw16(p, PciPCR, p->pcr); } if(rtl8169reset(ctlr)){ iofree(port); free(ctlr); continue; } /* * Extract the chip hardware version, * needed to configure each properly. */ ctlr->macv = csr32r(ctlr, Tcr) & HwveridMASK; rtl8169mii(ctlr); pcisetbme(p); if(rtl8169ctlrhead != nil) rtl8169ctlrtail->next = ctlr; else rtl8169ctlrhead = ctlr; rtl8169ctlrtail = ctlr; }}intrtl8169pnp(Ether* edev){ u32int r; Ctlr *ctlr; if(rtl8169ctlrhead == nil) rtl8169pci(); /* * Any adapter matches if no edev->port is supplied, * otherwise the ports must match. */ for(ctlr = rtl8169ctlrhead; ctlr != nil; ctlr = ctlr->next){ if(ctlr->active) continue; if(edev->port == 0 || edev->port == ctlr->port){ ctlr->active = 1; break; } } if(ctlr == nil) return -1; edev->ctlr = ctlr; edev->port = ctlr->port; edev->irq = ctlr->pcidev->intl; edev->tbdf = ctlr->pcidev->tbdf;// edev->mbps = 100; /* * Pull the MAC address out of the chip. */ r = csr32r(ctlr, Idr0); edev->ea[0] = r; edev->ea[1] = r>>8; edev->ea[2] = r>>16; edev->ea[3] = r>>24; r = csr32r(ctlr, Idr0+4); edev->ea[4] = r; edev->ea[5] = r>>8; /* * Linkage to the generic ethernet driver. */ edev->attach = rtl8169attach; edev->transmit = rtl8169transmit; edev->interrupt = rtl8169interrupt; edev->detach = rtl8169detach;// edev->ifstat = rtl8169ifstat;// edev->ctl = nil;//// edev->arg = edev;// edev->promiscuous = rtl8169promiscuous;// edev->multicast = rtl8169multicast; return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -