#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
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;
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;
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;
}
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;
}
}
-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.
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;
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;
}
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;
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;
if (catc->irq_urb)
usb_free_urb(catc->irq_urb);
free_netdev(netdev);
+ kfree(catc);
return -ENOMEM;
}
usb_free_urb(catc->rx_urb);
usb_free_urb(catc->irq_urb);
free_netdev(netdev);
+ kfree(catc);
return -EIO;
}
return 0;
usb_free_urb(catc->rx_urb);
usb_free_urb(catc->irq_urb);
free_netdev(catc->netdev);
+ kfree(catc);
}
}