-static int netdev_get_ecmd(struct net_device *dev,
- struct ethtool_cmd *ecmd)
-{
- struct ar2313_private *np = dev->priv;
- u32 tmp;
-
- ecmd->supported =
- (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full |
- SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full |
- SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII);
-
- ecmd->port = PORT_TP;
- /* only supports internal transceiver */
- ecmd->transceiver = XCVR_INTERNAL;
- /* not sure what this is for */
- ecmd->phy_address = 1;
-
- ecmd->advertising = ADVERTISED_MII;
- tmp = armiiread(dev, np->phy, MII_ADVERTISE);
- if (tmp & ADVERTISE_10HALF)
- ecmd->advertising |= ADVERTISED_10baseT_Half;
- if (tmp & ADVERTISE_10FULL)
- ecmd->advertising |= ADVERTISED_10baseT_Full;
- if (tmp & ADVERTISE_100HALF)
- ecmd->advertising |= ADVERTISED_100baseT_Half;
- if (tmp & ADVERTISE_100FULL)
- ecmd->advertising |= ADVERTISED_100baseT_Full;
-
- tmp = armiiread(dev, np->phy, MII_BMCR);
- if (tmp & BMCR_ANENABLE) {
- ecmd->advertising |= ADVERTISED_Autoneg;
- ecmd->autoneg = AUTONEG_ENABLE;
- } else {
- ecmd->autoneg = AUTONEG_DISABLE;
- }
-
- if (ecmd->autoneg == AUTONEG_ENABLE) {
- tmp = armiiread(dev, np->phy, MII_LPA);
- if (tmp & (LPA_100FULL | LPA_10FULL)) {
- ecmd->duplex = DUPLEX_FULL;
- } else {
- ecmd->duplex = DUPLEX_HALF;
- }
- if (tmp & (LPA_100FULL | LPA_100HALF)) {
- ecmd->speed = SPEED_100;
- } else {
- ecmd->speed = SPEED_10;
- }
- } else {
- if (tmp & BMCR_FULLDPLX) {
- ecmd->duplex = DUPLEX_FULL;
- } else {
- ecmd->duplex = DUPLEX_HALF;
- }
- if (tmp & BMCR_SPEED100) {
- ecmd->speed = SPEED_100;
- } else {
- ecmd->speed = SPEED_10;
- }
- }
-
- /* ignore maxtxpkt, maxrxpkt for now */
-
- return 0;
-}
-
-static int netdev_set_ecmd(struct net_device *dev,
- struct ethtool_cmd *ecmd)
-{
- struct ar2313_private *np = dev->priv;
- u32 tmp;
-
- if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100)
- return -EINVAL;
- if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL)
- return -EINVAL;
- if (ecmd->port != PORT_TP)
- return -EINVAL;
- if (ecmd->transceiver != XCVR_INTERNAL)
- return -EINVAL;
- if (ecmd->autoneg != AUTONEG_DISABLE
- && ecmd->autoneg != AUTONEG_ENABLE)
- return -EINVAL;
- /* ignore phy_address, maxtxpkt, maxrxpkt for now */
-
- /* WHEW! now lets bang some bits */
-
- tmp = armiiread(dev, np->phy, MII_BMCR);
- if (ecmd->autoneg == AUTONEG_ENABLE) {
- /* turn on autonegotiation */
- tmp |= BMCR_ANENABLE;
- printk("%s: Enabling auto-neg\n", dev->name);
- } else {
- /* turn off auto negotiation, set speed and duplexity */
- tmp &= ~(BMCR_ANENABLE | BMCR_SPEED100 | BMCR_FULLDPLX);
- if (ecmd->speed == SPEED_100)
- tmp |= BMCR_SPEED100;
- if (ecmd->duplex == DUPLEX_FULL)
- tmp |= BMCR_FULLDPLX;
- printk("%s: Hard coding %d/%s\n", dev->name,
- (ecmd->speed == SPEED_100) ? 100 : 10,
- (ecmd->duplex == DUPLEX_FULL) ? "full" : "half");
- }
- armiiwrite(dev, np->phy, MII_BMCR, tmp);
- np->phyData = 0;
- return 0;
-}
-
-static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
-{
- struct ar2313_private *np = dev->priv;
- u32 cmd;
-
- if (get_user(cmd, (u32 *) useraddr))
- return -EFAULT;
-
- switch (cmd) {
- /* get settings */
- case ETHTOOL_GSET:{
- struct ethtool_cmd ecmd = { ETHTOOL_GSET };
- spin_lock_irq(&np->lock);
- netdev_get_ecmd(dev, &ecmd);
- spin_unlock_irq(&np->lock);
- if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
- return -EFAULT;
- return 0;
- }
- /* set settings */
- case ETHTOOL_SSET:{
- struct ethtool_cmd ecmd;
- int r;
- if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
- return -EFAULT;
- spin_lock_irq(&np->lock);
- r = netdev_set_ecmd(dev, &ecmd);
- spin_unlock_irq(&np->lock);
- return r;
- }
- /* restart autonegotiation */
- case ETHTOOL_NWAY_RST:{
- int tmp;
- int r = -EINVAL;
- /* if autoneg is off, it's an error */
- tmp = armiiread(dev, np->phy, MII_BMCR);
- if (tmp & BMCR_ANENABLE) {
- tmp |= (BMCR_ANRESTART);
- armiiwrite(dev, np->phy, MII_BMCR, tmp);
- r = 0;
- }
- return r;
- }
- /* get link status */
- case ETHTOOL_GLINK:{
- struct ethtool_value edata = { ETHTOOL_GLINK };
- edata.data =
- (armiiread(dev, np->phy, MII_BMSR) & BMSR_LSTATUS) ? 1 : 0;
- if (copy_to_user(useraddr, &edata, sizeof(edata)))
- return -EFAULT;
- return 0;
- }
- }
-
- return -EOPNOTSUPP;
-}
-