]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/usb/dm9601.c
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-next-2.6
[linux-2.6-omap-h63xx.git] / drivers / net / usb / dm9601.c
index edd244f3acb50488c031863997101ff41469c797..6fc4f82b0bebdd4d1fb7688675a680511d2a7f99 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/usb/usbnet.h>
 
 /* datasheet:
- http://www.davicom.com.tw/big5/download/Data%20Sheet/DM9601-DS-P01-930914.pdf
+ http://ptm2.cc.utu.fi/ftp/network/cards/DM9601/From_NET/DM9601-DS-P01-930914.pdf
 */
 
 /* control requests */
@@ -397,31 +397,50 @@ static void dm9601_set_multicast(struct net_device *net)
        dm_write_reg_async(dev, DM_RX_CTRL, rx_ctl);
 }
 
+static void __dm9601_set_mac_address(struct usbnet *dev)
+{
+       dm_write_async(dev, DM_PHY_ADDR, ETH_ALEN, dev->net->dev_addr);
+}
+
 static int dm9601_set_mac_address(struct net_device *net, void *p)
 {
        struct sockaddr *addr = p;
        struct usbnet *dev = netdev_priv(net);
 
-       if (!is_valid_ether_addr(addr->sa_data))
+       if (!is_valid_ether_addr(addr->sa_data)) {
+               dev_err(&net->dev, "not setting invalid mac address %pM\n",
+                                                               addr->sa_data);
                return -EINVAL;
+       }
 
        memcpy(net->dev_addr, addr->sa_data, net->addr_len);
-       dm_write_async(dev, DM_PHY_ADDR, net->addr_len, net->dev_addr);
+       __dm9601_set_mac_address(dev);
 
        return 0;
 }
 
+static const struct net_device_ops dm9601_netdev_ops = {
+       .ndo_open               = usbnet_open,
+       .ndo_stop               = usbnet_stop,
+       .ndo_start_xmit         = usbnet_start_xmit,
+       .ndo_tx_timeout         = usbnet_tx_timeout,
+       .ndo_change_mtu         = usbnet_change_mtu,
+       .ndo_validate_addr      = eth_validate_addr,
+       .ndo_do_ioctl           = dm9601_ioctl,
+       .ndo_set_multicast_list = dm9601_set_multicast,
+       .ndo_set_mac_address    = dm9601_set_mac_address,
+};
+
 static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf)
 {
        int ret;
+       u8 mac[ETH_ALEN];
 
        ret = usbnet_get_endpoints(dev, intf);
        if (ret)
                goto out;
 
-       dev->net->do_ioctl = dm9601_ioctl;
-       dev->net->set_multicast_list = dm9601_set_multicast;
-       dev->net->set_mac_address = dm9601_set_mac_address;
+       dev->net->netdev_ops = &dm9601_netdev_ops;
        dev->net->ethtool_ops = &dm9601_ethtool_ops;
        dev->net->hard_header_len += DM_TX_OVERHEAD;
        dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
@@ -438,12 +457,24 @@ static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf)
        udelay(20);
 
        /* read MAC */
-       if (dm_read(dev, DM_PHY_ADDR, ETH_ALEN, dev->net->dev_addr) < 0) {
+       if (dm_read(dev, DM_PHY_ADDR, ETH_ALEN, mac) < 0) {
                printk(KERN_ERR "Error reading MAC address\n");
                ret = -ENODEV;
                goto out;
        }
 
+       /*
+        * Overwrite the auto-generated address only with good ones.
+        */
+       if (is_valid_ether_addr(mac))
+               memcpy(dev->net->dev_addr, mac, ETH_ALEN);
+       else {
+               printk(KERN_WARNING
+                       "dm9601: No valid MAC address in EEPROM, using %pM\n",
+                       dev->net->dev_addr);
+               __dm9601_set_mac_address(dev);
+       }
+
        /* power up phy */
        dm_write_reg(dev, DM_GPR_CTRL, 1);
        dm_write_reg(dev, DM_GPR_DATA, 0);
@@ -612,6 +643,10 @@ static const struct usb_device_id products[] = {
         },
        {
        USB_DEVICE(0x0a47, 0x9601),     /* Hirose USB-100 */
+       .driver_info = (unsigned long)&dm9601_info,
+        },
+       {
+       USB_DEVICE(0x0fe6, 0x8101),     /* DM9601 USB to Fast Ethernet Adapter */
        .driver_info = (unsigned long)&dm9601_info,
         },
        {},                     // END