示例#1
0
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
			}
		}
		
	}
}
示例#2
0
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);
}