Maintained by Jeff Garzik <jgarzik@pobox.com> Copyright 2001,2002 Jeff Garzik
Various code came from myson803.c and other files by Donald Becker. Copyright:
Written 1998-2002 by Donald Becker.
This software may be used and distributed according to the terms of the GNU General Public License (GPL), incorporated herein by reference. Drivers based on or derived from this code fall under the GPL and must retain the authorship, copyright and license notice. This file is not a complete program and may only be used when the entire operating system is licensed under the GPL.
The author may be reached as becker@scyld.com, or C/O Scyld Computing Corporation 410 Severn Ave., Suite 210 Annapolis MD 21403
/* advertise only what has been requested */
advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE);
tmp = advert & ~(ADVERTISE_ALL | ADVERTISE_100BASE4); if (mii->supports_gmii) {
advert2 = mii->mdio_read(dev, mii->phy_id,
MII_CTRL1000);
tmp2 = advert2 &
~(ADVERTISE_1000HALF | ADVERTISE_1000FULL);
}
tmp |= ethtool_adv_to_mii_adv_t(advertising);
if (mii->supports_gmii)
tmp2 |= ethtool_adv_to_mii_ctrl1000_t(advertising); if (advert != tmp) {
mii->mdio_write(dev, mii->phy_id, MII_ADVERTISE, tmp);
mii->advertising = tmp;
} if ((mii->supports_gmii) && (advert2 != tmp2))
mii->mdio_write(dev, mii->phy_id, MII_CTRL1000, tmp2);
/* turn on autonegotiation, and force a renegotiate */
bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART);
mii->mdio_write(dev, mii->phy_id, MII_BMCR, bmcr);
mii->force_media = 0;
} else {
u32 bmcr, tmp;
/* turn off auto negotiation, set speed and duplexity */
bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR);
tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 |
BMCR_SPEED1000 | BMCR_FULLDPLX); if (speed == SPEED_1000)
tmp |= BMCR_SPEED1000; elseif (speed == SPEED_100)
tmp |= BMCR_SPEED100; if (cmd->base.duplex == DUPLEX_FULL) {
tmp |= BMCR_FULLDPLX;
mii->full_duplex = 1;
} else {
mii->full_duplex = 0;
} if (bmcr != tmp)
mii->mdio_write(dev, mii->phy_id, MII_BMCR, tmp);
mii->force_media = 1;
} return 0;
}
/** * mii_check_gmii_support - check if the MII supports Gb interfaces * @mii: the MII interface
*/ int mii_check_gmii_support(struct mii_if_info *mii)
{ int reg;
/** * mii_link_ok - is link status up/ok * @mii: the MII interface * * Returns 1 if the MII reports link status up/ok, 0 otherwise.
*/ int mii_link_ok (struct mii_if_info *mii)
{ /* first, a dummy read, needed to latch some MII phys */
mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR); if (mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR) & BMSR_LSTATUS) return 1; return 0;
}
/** * mii_nway_restart - restart NWay (autonegotiation) for this interface * @mii: the MII interface * * Returns 0 on success, negative on error.
*/ int mii_nway_restart (struct mii_if_info *mii)
{ int bmcr; int r = -EINVAL;
/* if autoneg is off, it's an error */
bmcr = mii->mdio_read(mii->dev, mii->phy_id, MII_BMCR);
if (bmcr & BMCR_ANENABLE) {
bmcr |= BMCR_ANRESTART;
mii->mdio_write(mii->dev, mii->phy_id, MII_BMCR, bmcr);
r = 0;
}
return r;
}
/** * mii_check_link - check MII link status * @mii: MII interface * * If the link status changed (previous != current), call * netif_carrier_on() if current link status is Up or call * netif_carrier_off() if current link status is Down.
*/ void mii_check_link (struct mii_if_info *mii)
{ int cur_link = mii_link_ok(mii); int prev_link = netif_carrier_ok(mii->dev);
/** * mii_check_media - check the MII interface for a carrier/speed/duplex change * @mii: the MII interface * @ok_to_print: OK to print link up/down messages * @init_media: OK to save duplex mode in @mii * * Returns 1 if the duplex mode changed, 0 if not. * If the media type is forced, always returns 0.
*/ unsignedint mii_check_media (struct mii_if_info *mii, unsignedint ok_to_print, unsignedint init_media)
{ unsignedint old_carrier, new_carrier; int advertise, lpa, media, duplex; int lpa2 = 0;
/* check current and old link status */
old_carrier = netif_carrier_ok(mii->dev) ? 1 : 0;
new_carrier = (unsignedint) mii_link_ok(mii);
/* if carrier state did not change, this is a "bounce", * just exit as everything is already set correctly
*/ if ((!init_media) && (old_carrier == new_carrier)) return 0; /* duplex did not change */
/* no carrier, nothing much to do */ if (!new_carrier) {
netif_carrier_off(mii->dev); if (ok_to_print)
netdev_info(mii->dev, "link down\n"); return 0; /* duplex did not change */
}
/* * we have carrier, see who's on the other end
*/
netif_carrier_on(mii->dev);
if (mii->force_media) { if (ok_to_print)
netdev_info(mii->dev, "link up\n"); return 0; /* duplex did not change */
}
/* get MII advertise and LPA values */ if ((!init_media) && (mii->advertising))
advertise = mii->advertising; else {
advertise = mii->mdio_read(mii->dev, mii->phy_id, MII_ADVERTISE);
mii->advertising = advertise;
}
lpa = mii->mdio_read(mii->dev, mii->phy_id, MII_LPA); if (mii->supports_gmii)
lpa2 = mii->mdio_read(mii->dev, mii->phy_id, MII_STAT1000);
/* figure out media and duplex from advertise and LPA values */
media = mii_nway_result(lpa & advertise);
duplex = (media & ADVERTISE_FULL) ? 1 : 0; if (lpa2 & LPA_1000FULL)
duplex = 1;
/** * generic_mii_ioctl - main MII ioctl interface * @mii_if: the MII interface * @mii_data: MII ioctl data structure * @cmd: MII ioctl command * @duplex_chg_out: pointer to @duplex_changed status if there was no * ioctl error * * Returns 0 on success, negative on error.
*/ int generic_mii_ioctl(struct mii_if_info *mii_if, struct mii_ioctl_data *mii_data, int cmd, unsignedint *duplex_chg_out)
{ int rc = 0; unsignedint duplex_changed = 0;
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.