static void ed_pccard_tick(struct ed_softc *sc) { struct mii_data *mii; int media = 0; ED_ASSERT_LOCKED(sc); if (sc->miibus != NULL) { mii = device_get_softc(sc->miibus); media = mii->mii_media_status; mii_tick(mii); if (mii->mii_media_status & IFM_ACTIVE && media != mii->mii_media_status) { if (sc->chip_type == ED_CHIP_TYPE_DL10022) { ed_asic_outb(sc, ED_DL10022_DIAG, (mii->mii_media_active & IFM_FDX) ? ED_DL10022_COLLISON_DIS : 0); #ifdef notyet } else if (sc->chip_type == ED_CHIP_TYPE_DL10019) { write_asic(sc, ED_DL10019_MAGIC, (mii->mii_media_active & IFM_FDX) ? DL19FDUPLX : 0); #endif } } } }
static void ei_watchdog(u_long arg) { struct net_device *dev = (struct net_device *)arg; pcnet_dev_t *info = PRIV(dev); unsigned int nic_base = dev->base_addr; unsigned int mii_addr = nic_base + DLINK_GPIO; u_short link; if (!netif_device_present(dev)) goto reschedule; /* Check for pending interrupt with expired latency timer: with this, we can limp along even if the interrupt is blocked */ if (info->stale++ && (inb_p(nic_base + EN0_ISR) & ENISR_ALL)) { if (!info->fast_poll) netdev_info(dev, "interrupt(s) dropped!\n"); ei_irq_wrapper(dev->irq, dev); info->fast_poll = HZ; } if (info->fast_poll) { info->fast_poll--; info->watchdog.expires = jiffies + 1; add_timer(&info->watchdog); return; } if (!(info->flags & HAS_MII)) goto reschedule; mdio_read(mii_addr, info->phy_id, 1); link = mdio_read(mii_addr, info->phy_id, 1); if (!link || (link == 0xffff)) { if (info->eth_phy) { info->phy_id = info->eth_phy = 0; } else { netdev_info(dev, "MII is missing!\n"); info->flags &= ~HAS_MII; } goto reschedule; } link &= 0x0004; if (link != info->link_status) { u_short p = mdio_read(mii_addr, info->phy_id, 5); netdev_info(dev, "%s link beat\n", link ? "found" : "lost"); if (link && (info->flags & IS_DL10022)) { /* Disable collision detection on full duplex links */ outb((p & 0x0140) ? 4 : 0, nic_base + DLINK_DIAG); } else if (link && (info->flags & IS_DL10019)) { /* Disable collision detection on full duplex links */ write_asic(dev->base_addr, 4, (p & 0x140) ? DL19FDUPLX : 0); } if (link) { if (info->phy_id == info->eth_phy) { if (p) netdev_info(dev, "autonegotiation complete: " "%sbaseT-%cD selected\n", ((p & 0x0180) ? "100" : "10"), ((p & 0x0140) ? 'F' : 'H')); else netdev_info(dev, "link partner did not autonegotiate\n"); } NS8390_init(dev, 1); } info->link_status = link; } if (info->pna_phy && time_after(jiffies, info->mii_reset + 6*HZ)) { link = mdio_read(mii_addr, info->eth_phy, 1) & 0x0004; if (((info->phy_id == info->pna_phy) && link) || ((info->phy_id != info->pna_phy) && !link)) { /* isolate this MII and try flipping to the other one */ mdio_write(mii_addr, info->phy_id, 0, 0x0400); info->phy_id ^= info->pna_phy ^ info->eth_phy; netdev_info(dev, "switched to %s transceiver\n", (info->phy_id == info->eth_phy) ? "ethernet" : "PNA"); mdio_write(mii_addr, info->phy_id, 0, (info->phy_id == info->eth_phy) ? 0x1000 : 0); info->link_status = 0; info->mii_reset = jiffies; } } reschedule: info->watchdog.expires = jiffies + HZ; add_timer(&info->watchdog); }