This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / drivers / usb / net / catc.c
index c825ef7..455fe6e 100644 (file)
@@ -43,7 +43,7 @@
 #include <linux/spinlock.h>
 #include <linux/ethtool.h>
 #include <linux/crc32.h>
-#include <linux/bitops.h>
+#include <asm/bitops.h>
 #include <asm/uaccess.h>
 
 #undef DEBUG
@@ -411,7 +411,7 @@ static void catc_tx_done(struct urb *urb, struct pt_regs *regs)
 
 static int catc_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 {
-       struct catc *catc = netdev_priv(netdev);
+       struct catc *catc = netdev->priv;
        unsigned long flags;
        char *tx_buf;
 
@@ -442,7 +442,7 @@ static int catc_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev)
 
 static void catc_tx_timeout(struct net_device *netdev)
 {
-       struct catc *catc = netdev_priv(netdev);
+       struct catc *catc = netdev->priv;
 
        warn("Transmit timed out.");
        catc->tx_urb->transfer_flags |= URB_ASYNC_UNLINK;
@@ -604,7 +604,7 @@ static void catc_stats_timer(unsigned long data)
 
 static struct net_device_stats *catc_get_stats(struct net_device *netdev)
 {
-       struct catc *catc = netdev_priv(netdev);
+       struct catc *catc = netdev->priv;
        return &catc->stats;
 }
 
@@ -622,7 +622,7 @@ static void catc_multicast(unsigned char *addr, u8 *multicast)
 
 static void catc_set_multicast_list(struct net_device *netdev)
 {
-       struct catc *catc = netdev_priv(netdev);
+       struct catc *catc = netdev->priv;
        struct dev_mc_list *mc;
        u8 broadcast[6];
        u8 rx = RxEnable | RxPolarity | RxMultiCast;
@@ -664,38 +664,74 @@ static void catc_set_multicast_list(struct net_device *netdev)
        }
 }
 
-void catc_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+/*
+ * ioctl's
+ */
+static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr)
 {
-       struct catc *catc = netdev_priv(dev);
-       strncpy(info->driver, driver_name, ETHTOOL_BUSINFO_LEN);
-       strncpy(info->version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN);
-       usb_make_path (catc->usbdev, info->bus_info, sizeof info->bus_info);
+        struct catc *catc = dev->priv;
+        u32 cmd;
+        
+        if (get_user(cmd, (u32 __user *)useraddr))
+                return -EFAULT;
+
+        switch (cmd) {
+        /* get driver info */
+        case ETHTOOL_GDRVINFO: {
+                struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
+                strncpy(info.driver, driver_name, ETHTOOL_BUSINFO_LEN);
+                strncpy(info.version, DRIVER_VERSION, ETHTOOL_BUSINFO_LEN);
+               usb_make_path (catc->usbdev, info.bus_info, sizeof info.bus_info);
+                if (copy_to_user(useraddr, &info, sizeof(info)))
+                        return -EFAULT;
+                return 0;
+        }
+
+       /* get settings */
+       case ETHTOOL_GSET:
+               if (catc->is_f5u011) {
+                       struct ethtool_cmd ecmd = { ETHTOOL_GSET, 
+                                                   SUPPORTED_10baseT_Half | SUPPORTED_TP, 
+                                                   ADVERTISED_10baseT_Half | ADVERTISED_TP, 
+                                                   SPEED_10, 
+                                                   DUPLEX_HALF, 
+                                                   PORT_TP, 
+                                                   0, 
+                                                   XCVR_INTERNAL, 
+                                                   AUTONEG_DISABLE, 
+                                                   1, 
+                                                   1 
+                       };
+                       if (copy_to_user(useraddr, &ecmd, sizeof(ecmd)))
+                               return -EFAULT;
+                       return 0;
+               } else {
+                       return -EOPNOTSUPP;
+               }
+
+        /* get link status */
+        case ETHTOOL_GLINK: {
+                struct ethtool_value edata = {ETHTOOL_GLINK};
+                edata.data = netif_carrier_ok(dev);
+                if (copy_to_user(useraddr, &edata, sizeof(edata)))
+                        return -EFAULT;
+                return 0;
+        }
+       }
+        
+        return -EOPNOTSUPP;
 }
 
-static int catc_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+static int catc_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-       struct catc *catc = netdev_priv(dev);
-       if (!catc->is_f5u011)
-               return -EOPNOTSUPP;
-
-       cmd->supported = SUPPORTED_10baseT_Half | SUPPORTED_TP;
-       cmd->advertising = ADVERTISED_10baseT_Half | ADVERTISED_TP;
-       cmd->speed = SPEED_10;
-       cmd->duplex = DUPLEX_HALF;
-       cmd->port = PORT_TP; 
-       cmd->phy_address = 0;
-       cmd->transceiver = XCVR_INTERNAL;
-       cmd->autoneg = AUTONEG_DISABLE;
-       cmd->maxtxpkt = 1;
-       cmd->maxrxpkt = 1;
-       return 0;
+        switch(cmd) {
+        case SIOCETHTOOL:
+                return netdev_ethtool_ioctl(dev, rq->ifr_data);
+        default:
+                return -EOPNOTSUPP;
+        }
 }
 
-static struct ethtool_ops ops = {
-       .get_drvinfo = catc_get_drvinfo,
-       .get_settings = catc_get_settings,
-       .get_link = ethtool_op_get_link
-};
 
 /*
  * Open, close.
@@ -703,7 +739,7 @@ static struct ethtool_ops ops = {
 
 static int catc_open(struct net_device *netdev)
 {
-       struct catc *catc = netdev_priv(netdev);
+       struct catc *catc = netdev->priv;
        int status;
 
        catc->irq_urb->dev = catc->usbdev;
@@ -722,17 +758,17 @@ static int catc_open(struct net_device *netdev)
 
 static int catc_stop(struct net_device *netdev)
 {
-       struct catc *catc = netdev_priv(netdev);
+       struct catc *catc = netdev->priv;
 
        netif_stop_queue(netdev);
 
        if (!catc->is_f5u011)
                del_timer_sync(&catc->timer);
 
-       usb_kill_urb(catc->rx_urb);
-       usb_kill_urb(catc->tx_urb);
-       usb_kill_urb(catc->irq_urb);
-       usb_kill_urb(catc->ctrl_urb);
+       usb_unlink_urb(catc->rx_urb);
+       usb_unlink_urb(catc->tx_urb);
+       usb_unlink_urb(catc->irq_urb);
+       usb_unlink_urb(catc->ctrl_urb);
 
        return 0;
 }
@@ -755,11 +791,17 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
                return -EIO;
        }
 
-       netdev = alloc_etherdev(sizeof(struct catc));
-       if (!netdev)
+       catc = kmalloc(sizeof(struct catc), GFP_KERNEL);
+       if (!catc)
                return -ENOMEM;
 
-       catc = netdev_priv(netdev);
+       memset(catc, 0, sizeof(struct catc));
+
+       netdev = alloc_etherdev(0);
+       if (!netdev) {
+               kfree(catc);
+               return -EIO;
+       }
 
        netdev->open = catc_open;
        netdev->hard_start_xmit = catc_hard_start_xmit;
@@ -768,13 +810,14 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
        netdev->tx_timeout = catc_tx_timeout;
        netdev->watchdog_timeo = TX_TIMEOUT;
        netdev->set_multicast_list = catc_set_multicast_list;
-       SET_ETHTOOL_OPS(netdev, &ops);
+       netdev->do_ioctl = catc_ioctl;
+       netdev->priv = catc;
 
        catc->usbdev = usbdev;
        catc->netdev = netdev;
 
-       spin_lock_init(&catc->tx_lock);
-       spin_lock_init(&catc->ctrl_lock);
+       catc->tx_lock = SPIN_LOCK_UNLOCKED;
+       catc->ctrl_lock = SPIN_LOCK_UNLOCKED;
 
        init_timer(&catc->timer);
        catc->timer.data = (long) catc;
@@ -796,6 +839,7 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
                if (catc->irq_urb)
                        usb_free_urb(catc->irq_urb);
                free_netdev(netdev);
+               kfree(catc);
                return -ENOMEM;
        }
 
@@ -900,6 +944,7 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
                usb_free_urb(catc->rx_urb);
                usb_free_urb(catc->irq_urb);
                free_netdev(netdev);
+               kfree(catc);
                return -EIO;
        }
        return 0;
@@ -917,6 +962,7 @@ static void catc_disconnect(struct usb_interface *intf)
                usb_free_urb(catc->rx_urb);
                usb_free_urb(catc->irq_urb);
                free_netdev(catc->netdev);
+               kfree(catc);
        }
 }