#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 */
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 */
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 */
};
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 */
};
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 */
}
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;
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 ");
u32int r;
Block *bp;
Ctlr *ctlr;
- u8int cplusc;
+ u16int cplusc;
ctlr = edev->ctlr;
ilock(ctlr);
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);
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);
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);
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){
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;
bp->flag |= Bipck;
break;
}
- etheriq(edev, bp, 1);
+ etheriq(edev, bp);
}else{
if(!(control & Res))
ctlr->frag++;
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;
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");
edev->attach = rtl8169attach;
edev->transmit = rtl8169transmit;
- edev->interrupt = rtl8169interrupt;
edev->ifstat = rtl8169ifstat;
edev->arg = edev;
rtl8169link(edev);
+ intrenable(edev->irq, rtl8169interrupt, edev, edev->tbdf, edev->name);
+
return 0;
}