]> git.hungrycats.org Git - linux/commitdiff
winbond-840 (tulip clone) net driver updates:
authorJeff Garzik <jgarzik@rum.normnet.org>
Wed, 6 Feb 2002 23:35:55 +0000 (18:35 -0500)
committerJeff Garzik <jgarzik@rum.normnet.org>
Wed, 6 Feb 2002 23:35:55 +0000 (18:35 -0500)
* Support MII ethtool helper interface, and related ioctls.
* Replace some MII-related magic numbers with constants.

drivers/net/Makefile
drivers/net/winbond-840.c

index b5e97397e3732e5f17fee35f6bc8418b759c3d27..2cdfd7ea622db5371cd5c27c86165bb4961022ce 100644 (file)
@@ -100,7 +100,7 @@ obj-$(CONFIG_AIRONET4500_NONCS)  += aironet4500_card.o
 obj-$(CONFIG_AIRONET4500_PROC) += aironet4500_proc.o
 obj-$(CONFIG_AIRONET4500_CS)   += aironet4500_proc.o
 
-obj-$(CONFIG_WINBOND_840) += winbond-840.o
+obj-$(CONFIG_WINBOND_840) += winbond-840.o mii.o
 obj-$(CONFIG_SUNDANCE) += sundance.o
 obj-$(CONFIG_HAMACHI) += hamachi.o
 obj-$(CONFIG_NET) += Space.o setup.o net_init.o loopback.o
index 92e18806848ec26c4c2edd49f10450cd28f12a15..96784ceed543e0296d3416daa6b7df51d05c3c7a 100644 (file)
@@ -36,6 +36,8 @@
                power management.
                support for big endian descriptors
                        Copyright (C) 2001 Manfred Spraul
+       * ethtool support (jgarzik)
+       * Replace some MII-related magic numbers with constants (jgarzik)
   
        TODO:
        * enable pci_power_off
@@ -43,8 +45,8 @@
 */
   
 #define DRV_NAME       "winbond-840"
-#define DRV_VERSION    "1.01-c"
-#define DRV_RELDATE    "6/30/2000"
+#define DRV_VERSION    "1.01-d"
+#define DRV_RELDATE    "Nov-17-2001"
 
 
 /* Automatically extracted configuration info:
@@ -364,14 +366,11 @@ struct netdev_private {
        unsigned int cur_tx, dirty_tx;
        unsigned int tx_q_bytes;
        unsigned int tx_full;                           /* The Tx queue is full. */
-       /* These values are keep track of the transceiver/media in use. */
-       unsigned int full_duplex:1;                     /* Full-duplex operation requested. */
-       unsigned int duplex_lock:1;
        /* MII transceiver section. */
        int mii_cnt;                                            /* MII device addresses. */
-       u16 advertising;                                        /* NWay media advertisement */
        unsigned char phys[MII_CNT];            /* MII device addresses, but only the first is used */
        u32 mii;
+       struct mii_if_info mii_if;
 };
 
 static int  eeprom_read(long ioaddr, int location);
@@ -453,6 +452,9 @@ static int __devinit w840_probe1 (struct pci_dev *pdev,
        np->chip_id = chip_idx;
        np->drv_flags = pci_id_tbl[chip_idx].drv_flags;
        spin_lock_init(&np->lock);
+       np->mii_if.dev = dev;
+       np->mii_if.mdio_read = mdio_read;
+       np->mii_if.mdio_write = mdio_write;
        
        pci_set_drvdata(pdev, dev);
 
@@ -462,16 +464,16 @@ static int __devinit w840_probe1 (struct pci_dev *pdev,
        /* The lower four bits are the media type. */
        if (option > 0) {
                if (option & 0x200)
-                       np->full_duplex = 1;
+                       np->mii_if.full_duplex = 1;
                if (option & 15)
                        printk(KERN_INFO "%s: ignoring user supplied media type %d",
                                dev->name, option & 15);
        }
        if (find_cnt < MAX_UNITS  &&  full_duplex[find_cnt] > 0)
-               np->full_duplex = 1;
+               np->mii_if.full_duplex = 1;
 
-       if (np->full_duplex)
-               np->duplex_lock = 1;
+       if (np->mii_if.full_duplex)
+               np->mii_if.duplex_lock = 1;
 
        /* The chip-specific entries in the device structure. */
        dev->open = &netdev_open;
@@ -496,18 +498,19 @@ static int __devinit w840_probe1 (struct pci_dev *pdev,
        if (np->drv_flags & CanHaveMII) {
                int phy, phy_idx = 0;
                for (phy = 1; phy < 32 && phy_idx < MII_CNT; phy++) {
-                       int mii_status = mdio_read(dev, phy, 1);
+                       int mii_status = mdio_read(dev, phy, MII_BMSR);
                        if (mii_status != 0xffff  &&  mii_status != 0x0000) {
                                np->phys[phy_idx++] = phy;
-                               np->advertising = mdio_read(dev, phy, 4);
-                               np->mii = (mdio_read(dev, phy, 2) << 16)+
-                                               mdio_read(dev, phy, 3);
+                               np->mii_if.advertising = mdio_read(dev, phy, MII_ADVERTISE);
+                               np->mii = (mdio_read(dev, phy, MII_PHYSID1) << 16)+
+                                               mdio_read(dev, phy, MII_PHYSID2);
                                printk(KERN_INFO "%s: MII PHY %8.8xh found at address %d, status "
                                           "0x%4.4x advertising %4.4x.\n",
-                                          dev->name, np->mii, phy, mii_status, np->advertising);
+                                          dev->name, np->mii, phy, mii_status, np->mii_if.advertising);
                        }
                }
                np->mii_cnt = phy_idx;
+               np->mii_if.phy_id = np->phys[0];
                if (phy_idx == 0) {
                                printk(KERN_WARNING "%s: MII PHY not found -- this device may "
                                           "not operate correctly.\n", dev->name);
@@ -654,7 +657,7 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val
        int i;
 
        if (location == 4  &&  phy_id == np->phys[0])
-               np->advertising = value;
+               np->mii_if.advertising = value;
 
        if (mii_preamble_required)
                mdio_sync(mdio_addr);
@@ -728,12 +731,12 @@ static int update_link(struct net_device *dev)
        int duplex, fasteth, result, mii_reg;
 
        /* BSMR */
-       mii_reg = mdio_read(dev, np->phys[0], 1);
+       mii_reg = mdio_read(dev, np->phys[0], MII_BMSR);
 
        if (mii_reg == 0xffff)
                return np->csr6;
        /* reread: the link status bit is sticky */
-       mii_reg = mdio_read(dev, np->phys[0], 1);
+       mii_reg = mdio_read(dev, np->phys[0], MII_BMSR);
        if (!(mii_reg & 0x4)) {
                if (netif_carrier_ok(dev)) {
                        if (debug)
@@ -759,18 +762,18 @@ static int update_link(struct net_device *dev)
                 * Instead bit 9 and 13 of the BMCR are updated to the result
                 * of the negotiation..
                 */
-               mii_reg = mdio_read(dev, np->phys[0], 0);
-               duplex = mii_reg & 0x100;
-               fasteth = mii_reg & 0x2000;
+               mii_reg = mdio_read(dev, np->phys[0], MII_BMCR);
+               duplex = mii_reg & BMCR_FULLDPLX;
+               fasteth = mii_reg & BMCR_SPEED100;
        } else {
                int negotiated;
-               mii_reg = mdio_read(dev, np->phys[0], 5);
-               negotiated = mii_reg & np->advertising;
+               mii_reg = mdio_read(dev, np->phys[0], MII_LPA);
+               negotiated = mii_reg & np->mii_if.advertising;
 
-               duplex = (negotiated & 0x0100) || ((negotiated & 0x02C0) == 0x0040);
+               duplex = (negotiated & LPA_100FULL) || ((negotiated & 0x02C0) == LPA_10FULL);
                fasteth = negotiated & 0x380;
        }
-       duplex |= np->duplex_lock;
+       duplex |= np->mii_if.duplex_lock;
        /* remove fastether and fullduplex */
        result = np->csr6 & ~0x20000200;
        if (duplex)
@@ -822,7 +825,7 @@ static inline void update_csr6(struct net_device *dev, int new)
        /* and restart them with the new configuration */
        writel(np->csr6, ioaddr + NetworkConfig);
        if (new & 0x200)
-               np->full_duplex = 1;
+               np->mii_if.full_duplex = 1;
 }
 
 static void netdev_timer(unsigned long data)
@@ -1131,7 +1134,7 @@ static void netdev_tx_done(struct net_device *dev)
                        if (tx_status & 0x0C80) np->stats.tx_carrier_errors++;
                        if (tx_status & 0x0200) np->stats.tx_window_errors++;
                        if (tx_status & 0x0002) np->stats.tx_fifo_errors++;
-                       if ((tx_status & 0x0080) && np->full_duplex == 0)
+                       if ((tx_status & 0x0080) && np->mii_if.full_duplex == 0)
                                np->stats.tx_heartbeat_errors++;
 #ifdef ETHER_STATS
                        if (tx_status & 0x0100) np->stats.collisions16++;
@@ -1469,6 +1472,56 @@ static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
                return 0;
        }
 
+       /* get settings */
+       case ETHTOOL_GSET: {
+               struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+               spin_lock_irq(&np->lock);
+               mii_ethtool_gset(&np->mii_if, &ecmd);
+               spin_unlock_irq(&np->lock);
+               if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+                       return -EFAULT;
+               return 0;
+       }
+       /* set settings */
+       case ETHTOOL_SSET: {
+               int r;
+               struct ethtool_cmd ecmd;
+               if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
+                       return -EFAULT;
+               spin_lock_irq(&np->lock);
+               r = mii_ethtool_sset(&np->mii_if, &ecmd);
+               spin_unlock_irq(&np->lock);
+               return r;
+       }
+       /* restart autonegotiation */
+       case ETHTOOL_NWAY_RST: {
+               return mii_nway_restart(&np->mii_if);
+       }
+       /* get link status */
+       case ETHTOOL_GLINK: {
+               struct ethtool_value edata = {ETHTOOL_GLINK};
+               edata.data = mii_link_ok(&np->mii_if);
+               if (copy_to_user(useraddr, &edata, sizeof(edata)))
+                       return -EFAULT;
+               return 0;
+       }
+
+       /* get message-level */
+       case ETHTOOL_GMSGLVL: {
+               struct ethtool_value edata = {ETHTOOL_GMSGLVL};
+               edata.data = debug;
+               if (copy_to_user(useraddr, &edata, sizeof(edata)))
+                       return -EFAULT;
+               return 0;
+       }
+       /* set message-level */
+       case ETHTOOL_SMSGLVL: {
+               struct ethtool_value edata;
+               if (copy_from_user(&edata, useraddr, sizeof(edata)))
+                       return -EFAULT;
+               debug = edata.data;
+               return 0;
+       }
         }
        
        return -EOPNOTSUPP;