* [9front] Adding support for RTL8125B
@ 2025-02-16 7:32 Aidan K. Wiggins
0 siblings, 0 replies; only message in thread
From: Aidan K. Wiggins @ 2025-02-16 7:32 UTC (permalink / raw)
To: 9front
Hi All,
I'm looking for more eyes/testing on the below patch adding support
specifically for the RTL8125B ethernet chip. I don't have any of the
other variants on hand (8125, 8125A, ..., 8126), and their
corresponding Macv's would need to be recognized at the least. The
connection seems pretty stable, with the only fluke being that if you
boot into 9front after using another OS (a Linux), the RX seems to be
dead and needs another reboot to function, but works fine after
subsequent 9front reboots. I haven't investigated fully, but is likely
related to PCIPM, ASPM, or WoL? Also not sure if this is restricted to
the 8125+ family of cards either since I don't have other, older
chips.
Written alongside linux(r8169) & openbsd(rge) sources:
diff b049bb81adf2e6b0e2ef30973195a5ced06d2185 uncommitted
--- a/sys/src/9/pc/ether8169.c
+++ b/sys/src/9/pc/ether8169.c
@@ -58,8 +58,20 @@
Coal = 0xE2, /* Interrupt Mitigation (Coalesce) */
Rdsar = 0xE4, /* Receive Descriptor Start Address */
Etx = 0xEC, /* Early Transmit Threshold */
+
+ Misc = 0xF0, /* Miscellaneous */
};
+enum { /* RTL8125 Family register diff. */
+ Phyar8125 = 0xb8,
+ Macocp8125 = 0xb0,
+ Imr8125 = 0x38,
+ Isr8125 = 0x3c,
+ Tppoll8125 = 0x90,
+ Coal8125 = 0xa00,
+ Phyocp8125 = 0x0a40
+};
+
enum { /* Dtccr */
Cmd = 0x00000008, /* Command */
};
@@ -127,6 +139,7 @@
Macv44 = 0x5c800000, /* RTL8411B */
Macv45 = 0x54000000, /* RTL8111HN/8168H */
Macv51 = 0x50000000, /* RTL8168EP */
+ Macv63 = 0x64000000, /* RTL8125B */
Ifg0 = 0x01000000, /* Interframe Gap 0 */
Ifg1 = 0x02000000, /* Interframe Gap 1 */
@@ -144,11 +157,13 @@
MrxdmaMASK = 0x00000700,
Mrxdmaunlimited = 0x00000700,
RxfthSHIFT = 13, /* Receive Buffer Length */
+ Rxpso = 0x00000800, /* RX Pause Slot On */
RxfthMASK = 0x0000E000,
Rxfth256 = 0x00008000,
Rxfthnone = 0x0000E000,
Rer8 = 0x00010000, /* Accept Error Packets > 8 bytes */
MulERINT = 0x01000000, /* Multiple Early Interrupt Select */
+ Rx8125fetchdflt = 0x40000000 /* 8125-specific */
};
enum { /* Cr9346 */
@@ -190,6 +205,10 @@
Endian = 0x0200, /* Endian Mode */
};
+enum { /* Misc */
+ Rxdven = 0x00080000 /* RXDV gate enable */
+};
+
typedef struct D D; /* Transmit/Receive Descriptor */
struct D {
u32int control;
@@ -263,6 +282,7 @@
Rtl8100e = (0x8136<<16)|0x10EC, /* RTL810[01]E: pci -e */
Rtl8169c = (0x0116<<16)|0x16EC, /* RTL8169C+ (USR997902) */
Rtl8111b = (0x8161<<16)|0x10EC, /* RTL8111/8168/8411: pci-e */
+ Rtl8125b = (0x8125<<16)|0x10EC, /* /RTL8125B?/ */
Rtl8169sc = (0x8167<<16)|0x10EC, /* RTL8169SC */
Rtl8168b = (0x8168<<16)|0x10EC, /* RTL8168B: pci-e */
Rtl8169 = (0x8169<<16)|0x10EC, /* RTL8169 */
@@ -338,22 +358,43 @@
#define csr16w(c, r, w) (outs((c)->port+(r), (u16int)(w)))
#define csr32w(c, r, l) (outl((c)->port+(r), (u32int)(l)))
+static uint
+rtl8169miireg(Ctlr *ctlr, int ra, int *phy, int *data)
+{
+ uint r;
+
+ if(ctlr->macv == Macv63){
+ *phy = Phyar8125;
+ r = ((Phyocp8125 + ra/8) << 4) + ((ra % 8) << 1);
+ r = (r >> 1) << 16;
+ if(data)
+ r |= Flag | *data;
+ }else{
+ *phy = Phyar;
+ r = (ra << 16) & RegaddrMASK;
+ if(data)
+ r |= Flag | ((*data<<DataSHIFT) & DataMASK);
+ }
+ return r;
+}
+
static int
-rtl8169miimir(Mii* mii, int pa, int ra)
+rtl8169miimir(Mii *mii, int pa, int ra)
{
+ Ctlr *ctlr;
uint r;
int timeo;
- Ctlr *ctlr;
+ int phy;
if(pa != 1)
return -1;
- ctlr = mii->ctlr;
- r = (ra<<16) & RegaddrMASK;
- csr32w(ctlr, Phyar, r);
+ ctlr = mii->ctlr;
+ r = rtl8169miireg(ctlr, ra, &phy, nil);
+ csr32w(ctlr, phy, r);
delay(1);
for(timeo = 0; timeo < 2000; timeo++){
- if((r = csr32r(ctlr, Phyar)) & Flag)
+ if((r = csr32r(ctlr, phy)) & Flag)
break;
microdelay(100);
}
@@ -360,31 +401,34 @@
if(!(r & Flag))
return -1;
- return (r & DataMASK)>>DataSHIFT;
+ r &= DataMASK;
+ if(ctlr->macv != Macv63)
+ r >>= DataSHIFT;
+ return r;
}
static int
-rtl8169miimiw(Mii* mii, int pa, int ra, int data)
+rtl8169miimiw(Mii *mii, int pa, int ra, int data)
{
+ Ctlr *ctlr;
uint r;
int timeo;
- Ctlr *ctlr;
+ int phy;
if(pa != 1)
return -1;
- ctlr = mii->ctlr;
- r = Flag|((ra<<16) & RegaddrMASK)|((data<<DataSHIFT) & DataMASK);
- csr32w(ctlr, Phyar, r);
+ ctlr = mii->ctlr;
+ r = rtl8169miireg(ctlr, ra, &phy, &data);
+ csr32w(ctlr, phy, r);
delay(1);
for(timeo = 0; timeo < 2000; timeo++){
- if(!((r = csr32r(ctlr, Phyar)) & Flag))
+ if(!((r = csr32r(ctlr, phy)) & Flag))
break;
microdelay(100);
}
if(r & Flag)
return -1;
-
return 0;
}
@@ -425,10 +469,9 @@
csr8w(ctlr, Ldps, 1); /* magic */
rtl8169miimiw(ctlr->mii, 1, 0x0B, 0x0000); /* magic */
}
-
- if(mii(ctlr->mii, (1<<1)) == 0 || (phy = ctlr->mii->curphy) == nil){
+
+ if(mii(ctlr->mii, (1<<1)) == 0 || (phy = ctlr->mii->curphy) == nil)
error("no phy");
- }
print("#l%d: rtl8169: oui %#ux phyno %d, macv = %#8.8ux phyv = %#4.4ux\n",
edev->ctlrno, phy->oui, phy->phyno, ctlr->macv, ctlr->phyv);
@@ -444,7 +487,7 @@
rtl8169promiscuous(void* arg, int on)
{
Ether *edev;
- Ctlr * ctlr;
+ Ctlr *ctlr;
edev = arg;
ctlr = edev->ctlr;
@@ -470,13 +513,13 @@
ulong c, crc, carry;
crc = ~0UL;
- for (i = 0; i < len; i++) {
+ for(i = 0; i < len; i++){
c = addr[i];
- for (j = 0; j < 8; j++) {
+ for(j = 0; j < 8; j++){
carry = ((crc & (1UL << 31))? 1: 0) ^ (c & 1);
crc <<= 1;
c >>= 1;
- if (carry)
+ if(carry)
crc = (crc ^ Etherpolybe) | carry;
}
}
@@ -496,7 +539,7 @@
Ether *edev;
Ctlr *ctlr;
- if (!add)
+ if(!add)
return; /* ok to keep receiving on old mcast addrs */
edev = ether;
@@ -509,10 +552,10 @@
csr32w(ctlr, Rcr, ctlr->rcr);
/* pci-e variants reverse the order of the hash byte registers */
- if (ctlr->pcie) {
+ if(ctlr->pcie){
csr32w(ctlr, Mar0, swabl(ctlr->mchash>>32));
csr32w(ctlr, Mar0+4, swabl(ctlr->mchash));
- } else {
+ }else{
csr32w(ctlr, Mar0, ctlr->mchash);
csr32w(ctlr, Mar0+4, ctlr->mchash>>32);
}
@@ -606,13 +649,30 @@
}
static void
+rtl8169setimr(Ctlr *ctlr, int m)
+{
+ ctlr->imr = m;
+ if(ctlr->macv == Macv63)
+ csr32w(ctlr, Imr8125, m);
+ else
+ csr16w(ctlr, Imr, m);
+}
+
+static void
+rtl8169setisr(Ctlr *ctlr, int s)
+{
+ if(ctlr->macv == Macv63)
+ csr32w(ctlr, Isr8125, s);
+ else
+ csr16w(ctlr, Isr, s);
+}
+
+static void
rtl8169halt(Ctlr* ctlr)
{
csr8w(ctlr, Cr, 0);
-
- ctlr->imr = 0;
- csr16w(ctlr, Imr, 0);
- csr16w(ctlr, Isr, ~0);
+ rtl8169setimr(ctlr, 0);
+ rtl8169setisr(ctlr, ~0);
}
static int
@@ -664,7 +724,20 @@
}
}
+static uint
+rtl8125macr(Ctlr *ctlr, int r)
+{
+ csr32w(ctlr, Macocp8125, r << 15);
+ return csr32r(ctlr, Macocp8125);
+}
+
static void
+rtl8125macw(Ctlr *ctlr, int r, int v)
+{
+ csr32w(ctlr, Macocp8125, Flag | (r << 15) | v);
+}
+
+static void
rtl8169init(Ether* edev)
{
int i;
@@ -713,6 +786,7 @@
case Macv44:
case Macv45:
case Macv51:
+ case Macv63:
cplusc |= Macstatdis;
break;
default:
@@ -736,24 +810,35 @@
case Macv44:
case Macv45:
case Macv51:
- /* RXDV gating */
- i = csr32r(ctlr, 0x00F0);
- csr32w(ctlr, 0x00F0, i&~0x00080000);
+ case Macv63:
+ /* disable RXDV gating */
+ csr32w(ctlr, Misc, csr32r(ctlr, Misc) & ~Rxdven);
break;
default:
csr8w(ctlr, Cr, Te|Re);
}
+ if(ctlr->macv == Macv63){
+ rtl8125macw(ctlr, 0xea84, rtl8125macr(ctlr, 0xea84) | 0x03); /* magic */
+
+ /* disable 8125 tx descriptor fmt */
+ rtl8125macw(ctlr, 0xeb58, rtl8125macr(ctlr, 0xeb58) & ~1);
+ }
+
csr32w(ctlr, Tcr, Ifg1|Ifg0|Mtxdmaunlimited);
ctlr->tcr = csr32r(ctlr, Tcr);
+ ctlr->rcr = Ab|Am|Apm|Mrxdmaunlimited;
switch(ctlr->macv){
case Macv42:
case Macv45:
case Macv51:
- ctlr->rcr = Rxfth256|Mrxdmaunlimited|Ab|Am|Apm;
+ ctlr->rcr |= Rxfth256;
break;
+ case Macv63:
+ ctlr->rcr |= Rx8125fetchdflt|Rxpso;
+ break;
default:
- ctlr->rcr = Rxfthnone|Mrxdmaunlimited|Ab|Am|Apm;
+ ctlr->rcr |= Rxfthnone;
break;
}
ctlr->mchash = 0;
@@ -765,7 +850,14 @@
csr8w(ctlr, Etx, 0x3f);
csr16w(ctlr, Rms, 0x3fff);
- csr16w(ctlr, Coal, 0);
+ /* disable interrupt coalescing */
+ if(ctlr->macv == Macv63){
+ csr8w(ctlr, 0x34, 0);
+ for(r = Coal8125; r < 4*32; r += 4)
+ csr32w(ctlr, r, 0);
+ csr16w(ctlr, 0x7a, 0);
+ }else
+ csr16w(ctlr, Coal, 0);
/* no early rx interrupts */
r = csr16r(ctlr, Mulint) & 0xF000;
@@ -774,8 +866,7 @@
if(ctlr->macv == Macv51)
csr8w(ctlr, Cr, Te|Re);
- ctlr->imr = Serr|Fovw|Punlc|Rdu|Ter|Rer|Rok|Tdu;
- csr16w(ctlr, Imr, ctlr->imr);
+ rtl8169setimr(ctlr, Serr|Fovw|Punlc|Rdu|Ter|Rer|Rok|Tdu);
csr32w(ctlr, Mpc, 0);
@@ -785,6 +876,7 @@
case Macv44:
case Macv45:
case Macv51:
+ case Macv63:
csr8w(ctlr, Cr, Te|Re);
default:
break;
@@ -896,9 +988,8 @@
else if(r & Speed1000)
ethersetspeed(edev, 1000);
ethersetlink(edev, 1);
- } else {
+ }else
ethersetlink(edev, 0);
- }
}
static void
@@ -955,7 +1046,10 @@
if(ctlr->ntq > 0){
coherence();
- csr8w(ctlr, Tppoll, Npq);
+ if(ctlr->macv == Macv63)
+ csr8w(ctlr, Tppoll8125, 1);
+ else
+ csr8w(ctlr, Tppoll, Npq);
}
unlock(ctlr);
}
@@ -1037,6 +1131,26 @@
wakeup(&ctlr->reset);
}
+static u32int
+rtl8169getintr(Ctlr *ctlr)
+{
+ u32int isr;
+
+ if(ctlr->macv == Macv63){
+ isr = csr32r(ctlr, Isr8125);
+ if(isr == 0xFFFFFFFF)
+ return 0;
+ }else{
+ isr = csr16r(ctlr, Isr);
+ if(isr == 0xFFFF)
+ return 0;
+ }
+ if((isr & ctlr->imr) == 0)
+ return 0;
+ rtl8169setisr(ctlr, isr);
+ return isr;
+}
+
static void
rtl8169interrupt(Ureg*, void* arg)
{
@@ -1047,11 +1161,7 @@
edev = arg;
ctlr = edev->ctlr;
- while((isr = csr16r(ctlr, Isr)) != 0 && isr != 0xFFFF){
- csr16w(ctlr, Isr, isr);
- if((isr & ctlr->imr) == 0)
- break;
-
+ while(isr = rtl8169getintr(ctlr)){
if(isr & Serr)
ctlr->serr++;
if(isr & Fovw)
@@ -1120,6 +1230,7 @@
case Macv44:
case Macv45:
case Macv51:
+ case Macv63:
break;
}
return 0;
@@ -1145,6 +1256,7 @@
case Rtl8100e: /* RTL810[01]E ? */
case Rtl8168b: /* RTL8168B */
case Rtl8111b: /* RTL8111/8168/8411 */
+ case Rtl8125b: /* RTL8125B */
pcie = 1;
break;
case Rtl8169c: /* RTL8169C */
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2025-02-16 7:35 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-02-16 7:32 [9front] Adding support for RTL8125B Aidan K. Wiggins
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).