/* The maximum data clock rate is 2.5 Mhz. The minimum timing is usually metbyback-to-backPCII/Ocycles,butweinsertadelaytoavoid
"overclocking" issues or future 66Mhz PCI. */ #define mdio_delay() ioread32(mdio_addr)
/* Read and write the MII registers using software-generated serial MDIOprotocol.ItisjustdifferentenoughfromtheEEPROMprotocol
to not share code. The maxium data clock rate is 2.5 Mhz. */ #define MDIO_SHIFT_CLK 0x10000 #define MDIO_DATA_WRITE0 0x00000 #define MDIO_DATA_WRITE1 0x20000 #define MDIO_ENB 0x00000 /* Ignore the 0x02000 databook setting. */ #define MDIO_ENB_IN 0x40000 #define MDIO_DATA_READ 0x80000
/* MII transceiver control section. ReadandwritetheMIIregistersusingsoftware-generatedserial MDIOprotocol. SeeIEEE802.3-2002.pdf(Section2,Chapter"22.2.4Managementfunctions") orDP83840Adatasheetformoredetails.
*/
int tulip_mdio_read(struct net_device *dev, int phy_id, int location)
{ struct tulip_private *tp = netdev_priv(dev); int i; int read_cmd = (0xf6 << 10) | ((phy_id & 0x1f) << 5) | location; int retval = 0; void __iomem *ioaddr = tp->base_addr; void __iomem *mdio_addr = ioaddr + CSR9; unsignedlong flags;
if (location & ~0x1f) return0xffff;
if (tp->chip_id == COMET && phy_id == 30) { if (comet_miireg2offset[location]) return ioread32(ioaddr + comet_miireg2offset[location]); return0xffff;
}
spin_lock_irqsave(&tp->mii_lock, flags); if (tp->chip_id == LC82C168) {
iowrite32(0x60020000 + (phy_id<<23) + (location<<18), ioaddr + 0xA0);
ioread32(ioaddr + 0xA0);
ioread32(ioaddr + 0xA0); for (i = 1000; i >= 0; --i) {
barrier(); if ( ! ((retval = ioread32(ioaddr + 0xA0)) & 0x80000000)) break;
}
spin_unlock_irqrestore(&tp->mii_lock, flags); return retval & 0xffff;
}
/* Establish sync by sending at least 32 logic ones. */ for (i = 32; i >= 0; i--) {
iowrite32(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
mdio_delay();
iowrite32(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
mdio_delay();
} /* Shift the read command bits out. */ for (i = 15; i >= 0; i--) { int dataval = (read_cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
iowrite32(MDIO_ENB | dataval, mdio_addr);
mdio_delay();
iowrite32(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr);
mdio_delay();
} /* Read the two transition, 16 data, and wire-idle bits. */ for (i = 19; i > 0; i--) {
iowrite32(MDIO_ENB_IN, mdio_addr);
mdio_delay();
retval = (retval << 1) | ((ioread32(mdio_addr) & MDIO_DATA_READ) ? 1 : 0);
iowrite32(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
mdio_delay();
}
void tulip_mdio_write(struct net_device *dev, int phy_id, int location, int val)
{ struct tulip_private *tp = netdev_priv(dev); int i; int cmd = (0x5002 << 16) | ((phy_id & 0x1f) << 23) | (location<<18) | (val & 0xffff); void __iomem *ioaddr = tp->base_addr; void __iomem *mdio_addr = ioaddr + CSR9; unsignedlong flags;
if (location & ~0x1f) return;
if (tp->chip_id == COMET && phy_id == 30) { if (comet_miireg2offset[location])
iowrite32(val, ioaddr + comet_miireg2offset[location]); return;
}
spin_lock_irqsave(&tp->mii_lock, flags); if (tp->chip_id == LC82C168) {
iowrite32(cmd, ioaddr + 0xA0); for (i = 1000; i >= 0; --i) {
barrier(); if ( ! (ioread32(ioaddr + 0xA0) & 0x80000000)) break;
}
spin_unlock_irqrestore(&tp->mii_lock, flags); return;
}
/* Establish sync by sending 32 logic ones. */ for (i = 32; i >= 0; i--) {
iowrite32(MDIO_ENB | MDIO_DATA_WRITE1, mdio_addr);
mdio_delay();
iowrite32(MDIO_ENB | MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, mdio_addr);
mdio_delay();
} /* Shift the command bits out. */ for (i = 31; i >= 0; i--) { int dataval = (cmd & (1 << i)) ? MDIO_DATA_WRITE1 : 0;
iowrite32(MDIO_ENB | dataval, mdio_addr);
mdio_delay();
iowrite32(MDIO_ENB | dataval | MDIO_SHIFT_CLK, mdio_addr);
mdio_delay();
} /* Clear out extra bits. */ for (i = 2; i > 0; i--) {
iowrite32(MDIO_ENB_IN, mdio_addr);
mdio_delay();
iowrite32(MDIO_ENB_IN | MDIO_SHIFT_CLK, mdio_addr);
mdio_delay();
}
spin_unlock_irqrestore(&tp->mii_lock, flags);
}
/* Set up the transceiver control registers for the selected media type. */ void tulip_select_media(struct net_device *dev, int startup)
{ struct tulip_private *tp = netdev_priv(dev); void __iomem *ioaddr = tp->base_addr; struct mediatable *mtable = tp->mtable;
u32 new_csr6; int i;
if (mtable) { struct medialeaf *mleaf = &mtable->mleaf[tp->cur_index]; unsignedchar *p = mleaf->leafdata; switch (mleaf->type) { case0: /* 21140 non-MII xcvr. */ if (tulip_debug > 1)
netdev_dbg(dev, "Using a 21140 non-MII transceiver with control setting %02x\n",
p[1]);
dev->if_port = p[0]; if (startup)
iowrite32(mtable->csr12dir | 0x100, ioaddr + CSR12);
iowrite32(p[1], ioaddr + CSR12);
new_csr6 = 0x02000000 | ((p[2] & 0x71) << 18); break; case2: case4: {
u16 setup[5];
u32 csr13val, csr14val, csr15dir, csr15val; for (i = 0; i < 5; i++)
setup[i] = get_u16(&p[i*2 + 1]);
bmsr = tulip_mdio_read(dev, tp->phys[0], MII_BMSR);
lpa = tulip_mdio_read(dev, tp->phys[0], MII_LPA); if (tulip_debug > 1)
dev_info(&dev->dev, "MII status %04x, Link partner report %04x\n",
bmsr, lpa); if (bmsr == 0xffff) return -2; if ((bmsr & BMSR_LSTATUS) == 0) { int new_bmsr = tulip_mdio_read(dev, tp->phys[0], MII_BMSR); if ((new_bmsr & BMSR_LSTATUS) == 0) { if (tulip_debug > 1)
dev_info(&dev->dev, "No link beat on the MII interface, status %04x\n",
new_bmsr); return -1;
}
}
negotiated = lpa & tp->advertising[0];
tp->full_duplex = mii_duplex(tp->full_duplex_lock, negotiated);
new_csr6 = tp->csr6;
if (negotiated & LPA_100) new_csr6 &= ~TxThreshold; else new_csr6 |= TxThreshold; if (tp->full_duplex) new_csr6 |= FullDuplex; else new_csr6 &= ~FullDuplex;
if (new_csr6 != tp->csr6) {
tp->csr6 = new_csr6;
tulip_restart_rxtx(tp);
if (tulip_debug > 0)
dev_info(&dev->dev, "Setting %s-duplex based on MII#%d link partner capability of %04x\n",
tp->full_duplex ? "full" : "half",
tp->phys[0], lpa); return1;
}
return0;
}
void tulip_find_mii(struct net_device *dev, int board_idx)
{ struct tulip_private *tp = netdev_priv(dev); int phyn, phy_idx = 0; int mii_reg0; int mii_advert; unsignedint to_advert, new_bmcr, ane_switch;
/* Find the connected MII xcvrs. Doingthisinopen()wouldallowdetectingexternalxcvrslater,
but takes much time. */ for (phyn = 1; phyn <= 32 && phy_idx < ARRAY_SIZE(tp->phys); phyn++) { int phy = phyn & 0x1f; int mii_status = tulip_mdio_read (dev, phy, MII_BMSR); if ((mii_status & 0x8301) == 0x8001 ||
((mii_status & BMSR_100BASE4) == 0 &&
(mii_status & 0x7800) != 0)) { /* preserve Becker logic, gain indentation level */
} else { continue;
}
/* if not advertising at all, gen an *advertisingvaluefromthecapability *bitsinBMSR
*/ if ((mii_advert & ADVERTISE_ALL) == 0) { unsignedint tmpadv = tulip_mdio_read (dev, phy, MII_BMSR);
mii_advert = ((tmpadv >> 6) & 0x3e0) | 1;
}
pr_info("tulip%d: MII transceiver #%d config %04x status %04x advertising %04x\n",
board_idx, phy, mii_reg0, mii_status, mii_advert);
/* Fixup for DLink with miswired PHY. */ if (mii_advert != to_advert) {
pr_debug("tulip%d: Advertising %04x on PHY %d, previously advertising %04x\n",
board_idx, to_advert, phy, mii_advert);
tulip_mdio_write (dev, phy, 4, to_advert);
}
/* Enable autonegotiation: some boards default to off. */ if (tp->default_port == 0) {
new_bmcr = mii_reg0 | BMCR_ANENABLE; if (new_bmcr != mii_reg0) {
new_bmcr |= BMCR_ANRESTART;
ane_switch = 1;
}
} /* ...or disable nway, if forcing media */ else {
new_bmcr = mii_reg0 & ~BMCR_ANENABLE; if (new_bmcr != mii_reg0)
ane_switch = 1;
}
/* clear out bits we never want at this point */
new_bmcr &= ~(BMCR_CTST | BMCR_FULLDPLX | BMCR_ISOLATE |
BMCR_PDOWN | BMCR_SPEED100 | BMCR_LOOPBACK |
BMCR_RESET);
if (tp->full_duplex)
new_bmcr |= BMCR_FULLDPLX; if (tulip_media_cap[tp->default_port] & MediaIs100)
new_bmcr |= BMCR_SPEED100;
if (new_bmcr != mii_reg0) { /* some phys need the ANE switch to *happenbeforeforcedmediasettings *will"take."However,wewritethe *samevaluetwiceinordernotto *confusethesanephys.
*/ if (ane_switch) {
tulip_mdio_write (dev, phy, MII_BMCR, new_bmcr);
udelay (10);
}
tulip_mdio_write (dev, phy, MII_BMCR, new_bmcr);
}
}
tp->mii_cnt = phy_idx; if (tp->mtable && tp->mtable->has_mii && phy_idx == 0) {
pr_info("tulip%d: ***WARNING***: No MII transceiver found!\n",
board_idx);
tp->phys[0] = 1;
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet am 2026-10-03)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.