diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2022-09-05 08:54:24 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2022-09-05 08:54:24 +0000 |
commit | 2370a41cd25286a586e27de2adf5c810c7d7bca3 (patch) | |
tree | 983786fa565ef549348884f6e6b2818a9cf908c5 /sys/src/9/pc | |
parent | d28925d81a1ec08696d1fffa77cbb3f1e42d4ba7 (diff) |
ethervgbe: fix fucked up merge
Diffstat (limited to 'sys/src/9/pc')
-rw-r--r-- | sys/src/9/pc/ethervgbe.c | 149 |
1 files changed, 139 insertions, 10 deletions
diff --git a/sys/src/9/pc/ethervgbe.c b/sys/src/9/pc/ethervgbe.c index eaf0a33b5..047d64f63 100644 --- a/sys/src/9/pc/ethervgbe.c +++ b/sys/src/9/pc/ethervgbe.c @@ -90,11 +90,32 @@ enum MiiAddr = 0x71, /* MII address */ MiiData = 0x72, /* MII data */ + PhySts0 = 0x6e, /* Phy Status */ + PhySts_TxF = 0x01, + PhySts_RxF = 0x02, + PhySts_Speed10 = 0x04, + PhySts_Speed1000 = 0x08, + PhySts_Fd = 0x10, + PhySts_Link = 0x40, + PhySts_RestSts = 0x80, /* 64 bits related registers. */ TxDescHi = 0x18, DataBufHi = 0x1d, + /* CAM Registers */ + Cam0 = 0x10, + CamAddr = 0x68, + CamAddr_Enable = 0x80, + CamCtl = 0x69, + CamCtl_PageSel = 0xc0, + CamCtl_Write = 0x04, + CamCtl_Read = 0x08, + CamPageSel = 0x69, /* Alias of CamCtl for better readability */ + CamPageSel_Mar = 0x00, + CamPageSel_CamMask = 0x40, + CamPageSel_CamData = 0x80, + /* Rx engine registers. */ RxDescLo = 0x38, /* Rx descriptor base address (lo 32 bits) */ RxCsrS = 0x32, /* Rx descriptor queue control/status (Set) */ @@ -311,6 +332,9 @@ struct Ctlr int active; uchar ea[6]; + uchar maddrs[32][Eaddrlen]; + uint camidx; + RxDesc* rx_ring; Block* rx_blocks[RxCount]; @@ -339,6 +363,33 @@ static Ctlr* vgbetail; #define ciow(c, r, b) wiow(c, r, riob(c, r) & ~b) #define ciol(c, r, b) wiol(c, r, riob(c, r) & ~b) + +static void +vgbemiip(Ctlr* ctlr, int on) +{ + int i; + + wiob(ctlr, MiiCmd, 0); + wiob(ctlr, MiiAddr, 0x80); + + for(i = 0; i < 10000; i++){ + if(riob(ctlr, MiiStatus) & MiiStatus_idle) + break; + microdelay(1); + } + + if(on == 0) + return; + + wiob(ctlr, MiiCmd, MiiCmd_auto); + + for(i = 0; i < 10000; i++){ + if(riob(ctlr, MiiStatus) & MiiStatus_idle) + break; + microdelay(1); + } +} + static int vgbemiiw(Mii* mii, int phy, int addr, int data) { @@ -350,6 +401,8 @@ vgbemiiw(Mii* mii, int phy, int addr, int data) ctlr = mii->ctlr; + vgbemiip(ctlr, 0); + wiob(ctlr, MiiAddr, addr); wiow(ctlr, MiiData, (ushort) data); wiob(ctlr, MiiCmd, MiiCmd_write); @@ -363,6 +416,8 @@ vgbemiiw(Mii* mii, int phy, int addr, int data) return -1; } + vgbemiip(ctlr, 1); + return 0; } @@ -371,12 +426,15 @@ vgbemiir(Mii* mii, int phy, int addr) { Ctlr* ctlr; int i; + u16int r; if(phy != 1) return -1; ctlr = mii->ctlr; + vgbemiip(ctlr, 0); + wiob(ctlr, MiiAddr, addr); wiob(ctlr, MiiCmd, MiiCmd_read); @@ -389,7 +447,11 @@ vgbemiir(Mii* mii, int phy, int addr) return -1; } - return riow(ctlr, MiiData); + r = riow(ctlr, MiiData); + + vgbemiip(ctlr, 1); + + return r; } static long @@ -652,9 +714,11 @@ vgbeinterrupt(Ureg *, void* arg) if(status & Isr_PhyIntr) print("vgbe: irq: PHY interrupt\n"); - if(status & Isr_LinkStatus) + if(status & Isr_LinkStatus){ + edev->link = (riob(ctlr, PhySts0) & PhySts_Link) ? 1 : 0; + vgbemiip(ctlr, 1); print("vgbe: irq: link status change\n"); - + } if(status & Isr_RxNoDesc) print("vgbe: irq: ran out of Rx descriptors\n"); @@ -778,9 +842,21 @@ vgbeattach(Ether* edev) for(i = 0; i < RxCount; i++) vgbenewrx(ctlr, i); + + /* Clear CAM Filter */ + ciob(ctlr, CamCtl, CamCtl_PageSel); + siob(ctlr, CamPageSel, CamPageSel_CamMask); + wiob(ctlr, CamAddr, CamAddr_Enable); + for(i = 0; i < 8; i++) + wiob(ctlr, Cam0+i, 0); + + wiob(ctlr, CamAddr, 0); + ciob(ctlr, CamCtl, CamCtl_PageSel); + siob(ctlr, CamPageSel, CamPageSel_Mar); + /* Init Rx MAC. */ wiob(ctlr, RxControl, - RxControl_MultiCast|RxControl_BroadCast|RxControl_UniCast); + RxControl_BroadCast|RxControl_UniCast); wiob(ctlr, RxConfig, RxConfig_VlanOpt0); /* Load Rx ring. */ @@ -825,7 +901,7 @@ vgbeattach(Ether* edev) static void vgbereset(Ctlr* ctlr) { -// MiiPhy* phy; + MiiPhy* phy; int timeo, i; // print("vgbe: reset\n"); @@ -898,8 +974,10 @@ vgbereset(Ctlr* ctlr) return; } -// phy = ctlr->mii->curphy; -// print("vgbe: phy:oui %#x\n", phy->oui); + phy = ctlr->mii->curphy; + print("vgbe: phy:oui %#x\n", phy->oui); + + vgbemiip(ctlr, 1); } static void @@ -1092,13 +1170,63 @@ vgbectl(Ether* edev, void* buf, long n) static void vgbepromiscuous(void* arg, int on) { - USED(arg, on); + Ether* edev; + Ctlr* ctlr; + + edev = arg; + ctlr = edev->ctlr; + if(on) + siob(ctlr, RxControl, RxControl_Promisc | RxControl_MultiCast); + else + ciob(ctlr, RxControl, RxControl_Promisc | RxControl_MultiCast); } /* multicast already on, don't need to do anything */ static void -vgbemulticast(void*, uchar*, int) +vgbemulticast(void* ether, uchar* ea, int add) { + Ether* edev; + Ctlr* ctlr; + int i; + + edev = ether; + ctlr = edev->ctlr; + + if(!add || ctlr->camidx == 32) + return; + + for(i = 0; i < ctlr->camidx; i++){ + if(memcmp(ea, ctlr->maddrs[i], Eaddrlen) == 0) + return; + } + + memmove(ctlr->maddrs[i], ea, Eaddrlen); + + ciob(ctlr, CamCtl, CamCtl_PageSel); + siob(ctlr, CamPageSel, CamPageSel_CamData); + + wiob(ctlr, CamAddr, CamAddr_Enable | ctlr->camidx); + + for(i = 0; i < Eaddrlen; i++) + wiob(ctlr, Cam0+i, ea[i]); + + siob(ctlr, CamCtl, CamCtl_Write); + + for(i = 0; i < 10000; i++){ + microdelay(1); + if((riob(ctlr, CamCtl) & CamCtl_Write) == 0) + break; + } + + ciob(ctlr, CamCtl, CamCtl_PageSel); + siob(ctlr, CamPageSel, CamPageSel_CamMask); + siob(ctlr, Cam0+(ctlr->camidx/8), 1<<(ctlr->camidx&7)); + + ctlr->camidx++; + + wiob(ctlr, CamAddr, 0); + ciob(ctlr, CamCtl, CamCtl_PageSel); + siob(ctlr, CamPageSel, CamPageSel_Mar); } static int @@ -1134,11 +1262,12 @@ vgbepnp(Ether* edev) edev->irq = ctlr->pdev->intl; edev->tbdf = ctlr->pdev->tbdf; edev->mbps = 1000; + edev->link = (riob(ctlr, PhySts0) & PhySts_Link) ? 1 : 0; memmove(edev->ea, ctlr->ea, Eaddrlen); edev->attach = vgbeattach; edev->transmit = vgbetransmit; edev->ifstat = vgbeifstat; -// edev->promiscuous = vgbepromiscuous; + edev->promiscuous = vgbepromiscuous; edev->multicast = vgbemulticast; // edev->shutdown = vgbeshutdown; edev->ctl = vgbectl; |