static int kirkwoodmii(Ether *ether) { int i; Ctlr *ctlr; MiiPhy *phy; MIIDBG("mii\n"); ctlr = ether->ctlr; if((ctlr->mii = malloc(sizeof(Mii))) == nil) return -1; ctlr->mii->ctlr = ctlr; ctlr->mii->mir = miird; ctlr->mii->miw = miiwr; if(mymii(ctlr->mii, ~0) == 0 || (phy = ctlr->mii->curphy) == nil){ print("#l%d: ether1116: init mii failure\n", ether->ctlrno); free(ctlr->mii); ctlr->mii = nil; return -1; } /* oui 005043 is marvell */ MIIDBG("oui %#X phyno %d\n", phy->oui, phy->phyno); // TODO: does this make sense? shouldn't each phy be initialised? if((ctlr->ether->ctlrno == 0 || hackflavour != Hackdual) && miistatus(ctlr->mii) < 0){ miireset(ctlr->mii); MIIDBG("miireset\n"); if(miiane(ctlr->mii, ~0, 0, ~0) < 0){ iprint("miiane failed\n"); return -1; } MIIDBG("miistatus\n"); miistatus(ctlr->mii); if(miird(ctlr->mii, phy->phyno, Bmsr) & BmsrLs){ for(i = 0; ; i++){ if(i > 600){ iprint("ether1116: autonegotiation failed\n"); break; } if(miird(ctlr->mii, phy->phyno, Bmsr) & BmsrAnc) break; delay(10); } if(miistatus(ctlr->mii) < 0) iprint("miistatus failed\n"); }else{ iprint("ether1116: no link\n"); phy->speed = 10; /* simple default */ } } ether->mbps = phy->speed; MIIDBG("#l%d: kirkwoodmii: fd %d speed %d tfc %d rfc %d\n", ctlr->port, phy->fd, phy->speed, phy->tfc, phy->rfc); MIIDBG("mii done\n"); return 0; }
static int igbemii(Ctlr* ctlr) { MiiPhy *phy = (MiiPhy *)1; int ctrl, p, r; USED(phy); r = csr32r(ctlr, Status); if(r & Tbimode) return -1; if((ctlr->mii = malloc(sizeof(Mii))) == nil) return -1; ctlr->mii->ctlr = ctlr; ctrl = csr32r(ctlr, Ctrl); ctrl |= Slu; switch(ctlr->id){ case i82543gc: ctrl |= Frcdplx|Frcspd; csr32w(ctlr, Ctrl, ctrl); /* * The reset pin direction (Mdro) should already * be set from the EEPROM load. * If it's not set this configuration is unexpected * so bail. */ r = csr32r(ctlr, Ctrlext); if(!(r & Mdro)) return -1; csr32w(ctlr, Ctrlext, r); delay(20); r = csr32r(ctlr, Ctrlext); r &= ~Mdr; csr32w(ctlr, Ctrlext, r); delay(20); r = csr32r(ctlr, Ctrlext); r |= Mdr; csr32w(ctlr, Ctrlext, r); delay(20); ctlr->mii->mir = i82543miimir; ctlr->mii->miw = i82543miimiw; break; case i82544ei: case i82547ei: case i82540em: case i82540eplp: case i82547gi: case i82541gi: case i82541pi: case i82546gb: case i82546eb: ctrl &= ~(Frcdplx|Frcspd); csr32w(ctlr, Ctrl, ctrl); ctlr->mii->mir = igbemiimir; ctlr->mii->miw = igbemiimiw; break; default: free(ctlr->mii); ctlr->mii = nil; return -1; } if(mii(ctlr->mii, ~0) == 0 || (phy = ctlr->mii->curphy) == nil){ if (0) print("phy trouble: phy = 0x%lux\n", (uint32_t)phy); free(ctlr->mii); ctlr->mii = nil; return -1; } //print("oui %X phyno %d\n", phy->oui, phy->phyno); USED(phy); /* * 8254X-specific PHY registers not in 802.3: * 0x10 PHY specific control * 0x14 extended PHY specific control * Set appropriate values then reset the PHY to have * changes noted. */ switch(ctlr->id){ case i82547gi: case i82541gi: case i82541pi: case i82546gb: case i82546eb: break; default: r = miimir(ctlr->mii, 16); r |= 0x0800; /* assert CRS on Tx */ r |= 0x0060; /* auto-crossover all speeds */ r |= 0x0002; /* polarity reversal enabled */ miimiw(ctlr->mii, 16, r); r = miimir(ctlr->mii, 20); r |= 0x0070; /* +25MHz clock */ r &= ~0x0F00; r |= 0x0100; /* 1x downshift */ miimiw(ctlr->mii, 20, r); miireset(ctlr->mii); break; } p = 0; if(ctlr->txcw & TxcwPs) p |= AnaP; if(ctlr->txcw & TxcwAs) p |= AnaAP; miiane(ctlr->mii, ~0, p, ~0); return 0; }