X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=sys%2Fsrc%2F9%2Fpc%2Fether8169.c;h=bf6cf8ef48f5f90a37fa33f150a810653c6658b3;hb=8243b6600f4c8d60e520aa1b20368ae9575aabf9;hp=cc27fabea1e9e38d222cb81c818c0e2be9ac6e28;hpb=9679d7525c205de90e9dcadcf6762b04114f8c45;p=plan9front.git diff --git a/sys/src/9/pc/ether8169.c b/sys/src/9/pc/ether8169.c index cc27fabea..bf6cf8ef4 100644 --- a/sys/src/9/pc/ether8169.c +++ b/sys/src/9/pc/ether8169.c @@ -15,9 +15,8 @@ #include "io.h" #include "../port/error.h" #include "../port/netif.h" - -#include "etherif.h" -#include "ethermii.h" +#include "../port/etherif.h" +#include "../port/ethermii.h" enum { /* registers */ Idr0 = 0x00, /* MAC address */ @@ -50,6 +49,8 @@ enum { /* registers */ Tbianar = 0x68, /* TBI Auto-Negotiation Advertisment */ Tbilpar = 0x6A, /* TBI Auto-Negotiation Link Partner */ Phystatus = 0x6C, /* PHY Status */ + Pmch = 0x6F, /* power management */ + Ldps = 0x82, /* link down power saving */ Rms = 0xDA, /* Receive Packet Maximum Size */ Cplusc = 0xE0, /* C+ Command */ @@ -113,6 +114,17 @@ enum { /* Tcr */ Macv15 = 0x38800000, /* RTL8100E */ // Macv19 = 0x3c000000, /* dup Macv12a: RTL8111c-gr */ Macv25 = 0x28000000, /* RTL8168D */ + Macv26 = 0x48000000, /* RTL8111/8168B */ + Macv27 = 0x2c800000, /* RTL8111e */ + Macv28 = 0x2c000000, /* RTL8111/8168B */ + Macv29 = 0x40800000, /* RTL8101/8102E */ + Macv30 = 0x24000000, /* RTL8101E? (untested) */ + Macv39 = 0x44800000, /* RTL8106E */ + Macv40 = 0x4c000000, /* RTL8168G */ + Macv42 = 0x50800000, /* RTL8168GU */ + Macv44 = 0x5c800000, /* RTL8411B */ + Macv45 = 0x54000000, /* RTL8111HN */ + Ifg0 = 0x01000000, /* Interframe Gap 0 */ Ifg1 = 0x02000000, /* Interframe Gap 1 */ }; @@ -171,6 +183,7 @@ enum { /* Cplusc */ Dac = 0x0010, /* PCI Dual Address Cycle Enable */ Rxchksum = 0x0020, /* Receive Checksum Offload Enable */ Rxvlan = 0x0040, /* Receive VLAN De-tagging Enable */ + Macstatdis = 0x0080, /* Disable Mac Statistics */ Endian = 0x0200, /* Endian Mode */ }; @@ -383,13 +396,27 @@ rtl8169mii(Ctlr* ctlr) ctlr->mii->miw = rtl8169miimiw; ctlr->mii->ctlr = ctlr; + /* + * PHY wakeup + */ + switch(ctlr->macv){ + case Macv25: + case Macv28: + case Macv29: + case Macv30: + csr8w(ctlr, Pmch, csr8r(ctlr, Pmch) | 0x80); + break; + } + rtl8169miimiw(ctlr->mii, 1, 0x1f, 0); + rtl8169miimiw(ctlr->mii, 1, 0x0e, 0); + /* * Get rev number out of Phyidr2 so can config properly. * There's probably more special stuff for Macv0[234] needed here. */ ctlr->phyv = rtl8169miimir(ctlr->mii, 1, Phyidr2) & 0x0F; if(ctlr->macv == Macv02){ - csr8w(ctlr, 0x82, 1); /* magic */ + csr8w(ctlr, Ldps, 1); /* magic */ rtl8169miimiw(ctlr->mii, 1, 0x0B, 0x0000); /* magic */ } @@ -401,6 +428,10 @@ rtl8169mii(Ctlr* ctlr) print("rtl8169: oui %#ux phyno %d, macv = %#8.8ux phyv = %#4.4ux\n", phy->oui, phy->phyno, ctlr->macv, ctlr->phyv); + miireset(ctlr->mii); + + microdelay(100); + miiane(ctlr->mii, ~0, ~0, ~0); return 0; @@ -560,7 +591,7 @@ rtl8169ifstat(Ether* edev, void* a, long n, ulong offset) l += snprint(p+l, READSTR-l, "multicast: %ud\n", ctlr->mcast); if(ctlr->mii != nil && ctlr->mii->curphy != nil){ - l += snprint(p+l, READSTR, "phy: "); + l += snprint(p+l, READSTR-l, "phy: "); for(i = 0; i < NMiiPhyr; i++){ if(i && ((i & 0x07) == 0)) l += snprint(p+l, READSTR-l, "\n "); @@ -643,7 +674,7 @@ rtl8169init(Ether* edev) u32int r; Block *bp; Ctlr *ctlr; - u8int cplusc; + u16int cplusc; ctlr = edev->ctlr; ilock(ctlr); @@ -672,7 +703,16 @@ rtl8169init(Ether* edev) cplusc = csr16r(ctlr, Cplusc); cplusc &= ~(Endian|Rxchksum); - cplusc |= Txenb|Rxenb|Mulrw; + cplusc |= Txenb|Mulrw; + switch(ctlr->macv){ + case Macv40: + case Macv44: + cplusc |= Macstatdis; + break; + default: + cplusc |= Rxenb; + break; + } csr16w(ctlr, Cplusc, cplusc); csr32w(ctlr, Tnpds+4, 0); @@ -684,7 +724,15 @@ rtl8169init(Ether* edev) csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited); ctlr->tcr = csr32r(ctlr, Tcr); - ctlr->rcr = Rxfthnone|Mrxdmaunlimited|Ab|Am|Apm; + switch(ctlr->macv){ + case Macv42: + case Macv45: + ctlr->rcr = Rxfth256|Mrxdmaunlimited|Ab|Am|Apm; + break; + default: + ctlr->rcr = Rxfthnone|Mrxdmaunlimited|Ab|Am|Apm; + break; + } ctlr->mchash = 0; csr32w(ctlr, Mar0, 0); csr32w(ctlr, Mar0+4, 0); @@ -761,11 +809,13 @@ rtl8169attach(Ether* edev) ctlr->rd = nil; free(ctlr->dtcc); ctlr->dtcc = nil; - qlock(&ctlr->alock); + qunlock(&ctlr->alock); error(Enomem); } ctlr->init = 1; kproc("rtl8169", rtl8169reseter, edev); + + /* rtl8169reseter() does qunlock(&ctlr->alock) when complete */ qlock(&ctlr->alock); } qunlock(&ctlr->alock); @@ -789,15 +839,12 @@ rtl8169link(Ether* edev) ctlr = edev->ctlr; + r = csr8r(ctlr, Phystatus); /* * Maybe the link changed - do we care very much? * Could stall transmits if no link, maybe? */ - if(!((r = csr8r(ctlr, Phystatus)) & Linksts)){ - edev->link = 0; - return; - } - edev->link = 1; + edev->link = (r & Linksts) != 0; limit = 256*1024; if(r & Speed10){ @@ -879,8 +926,10 @@ rtl8169receive(Ether* edev) int x; ctlr = edev->ctlr; - x = ctlr->rdh; - for(;;){ + if(ctlr->nrq < ctlr->nrd/2) + rtl8169replenish(ctlr); + + for(x = ctlr->rdh; x != ctlr->rdt;){ d = &ctlr->rd[x]; if((control = d->control) & Own) break; @@ -928,7 +977,7 @@ rtl8169receive(Ether* edev) bp->flag |= Bipck; break; } - etheriq(edev, bp, 1); + etheriq(edev, bp); }else{ if(!(control & Res)) ctlr->frag++; @@ -1008,6 +1057,16 @@ vetmacv(Ctlr *ctlr, uint *macv) case Macv14: case Macv15: case Macv25: + case Macv26: + case Macv27: + case Macv28: + case Macv29: + case Macv30: + case Macv39: + case Macv40: + case Macv42: + case Macv44: + case Macv45: break; } return 0; @@ -1059,25 +1118,17 @@ rtl8169pci(void) ctlr->pciv = i; ctlr->pcie = pcie; + pcienable(p); if(vetmacv(ctlr, &macv) == -1){ + pcidisable(p); iofree(port); free(ctlr); print("rtl8169: unknown mac %.4ux %.8ux\n", p->did, macv); continue; } - 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)){ + pcidisable(p); iofree(port); free(ctlr); print("rtl8169: reset failed\n"); @@ -1155,7 +1206,6 @@ rtl8169pnp(Ether* edev) edev->attach = rtl8169attach; edev->transmit = rtl8169transmit; - edev->interrupt = rtl8169interrupt; edev->ifstat = rtl8169ifstat; edev->arg = edev; @@ -1164,6 +1214,8 @@ rtl8169pnp(Ether* edev) rtl8169link(edev); + intrenable(edev->irq, rtl8169interrupt, edev, edev->tbdf, edev->name); + return 0; }