Merge to Fedora kernel-2.6.18-1.2224_FC5 patched with stable patch-2.6.18.1-vs2.0...
[linux-2.6.git] / drivers / net / hamachi.c
index b5169e8..409c6aa 100644 (file)
 
        Support and updates available at
        http://www.scyld.com/network/hamachi.html
+       [link no longer provides useful info -jgarzik]
        or
        http://www.parl.clemson.edu/~keithu/hamachi.html
 
-
-
-       Linux kernel changelog:
-
-       LK1.0.1:
-       - fix lack of pci_dev<->dev association
-       - ethtool support (jgarzik)
-
 */
 
 #define DRV_NAME       "hamachi"
-#define DRV_VERSION    "1.01+LK1.0.1"
-#define DRV_RELDATE    "5/18/2001"
+#define DRV_VERSION    "2.0"
+#define DRV_RELDATE    "June 27, 2006"
 
 
 /* A few user-configurable values. */
@@ -170,10 +163,10 @@ static int tx_params[MAX_UNITS] = {-1, -1, -1, -1, -1, -1, -1, -1};
 #include <linux/skbuff.h>
 #include <linux/ip.h>
 #include <linux/delay.h>
+#include <linux/bitops.h>
 
 #include <asm/uaccess.h>
 #include <asm/processor.h>     /* Processor type for cache alignment. */
-#include <asm/bitops.h>
 #include <asm/io.h>
 #include <asm/unaligned.h>
 #include <asm/cache.h>
@@ -204,6 +197,10 @@ KERN_INFO "   Further modifications by Keith Underwood <keithu@parl.clemson.edu>
 
 #define RUN_AT(x) (jiffies + (x))
 
+#ifndef ADDRLEN
+#define ADDRLEN 32
+#endif
+
 /* Condensed bus+endian portability operations. */
 #if ADDRLEN == 64
 #define cpu_to_leXX(addr)      cpu_to_le64(addr)
@@ -423,7 +420,7 @@ that case.
 static void hamachi_timer(unsigned long data);
 
 enum capability_flags {CanHaveMII=1, };
-static struct chip_info {
+static const struct chip_info {
        u16     vendor_id, device_id, device_id_mask, pad;
        const char *name;
        void (*media_timer)(unsigned long data);
@@ -512,27 +509,28 @@ struct hamachi_private {
        u32 rx_int_var, tx_int_var;     /* interrupt control variables */
        u32 option;                                                     /* Hold on to a copy of the options */
        struct pci_dev *pci_dev;
+       void __iomem *base;
 };
 
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>, Eric Kasten <kasten@nscl.msu.edu>, Keith Underwood <keithu@parl.clemson.edu>");
 MODULE_DESCRIPTION("Packet Engines 'Hamachi' GNIC-II Gigabit Ethernet driver");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(max_interrupt_work, "i");
-MODULE_PARM(mtu, "i");
-MODULE_PARM(debug, "i");
-MODULE_PARM(min_rx_pkt, "i");
-MODULE_PARM(max_rx_gap, "i");
-MODULE_PARM(max_rx_latency, "i");
-MODULE_PARM(min_tx_pkt, "i");
-MODULE_PARM(max_tx_gap, "i");
-MODULE_PARM(max_tx_latency, "i");
-MODULE_PARM(rx_copybreak, "i");
-MODULE_PARM(rx_params, "1-" __MODULE_STRING(MAX_UNITS) "i");
-MODULE_PARM(tx_params, "1-" __MODULE_STRING(MAX_UNITS) "i");
-MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
-MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
-MODULE_PARM(force32, "i");
+module_param(max_interrupt_work, int, 0);
+module_param(mtu, int, 0);
+module_param(debug, int, 0);
+module_param(min_rx_pkt, int, 0);
+module_param(max_rx_gap, int, 0);
+module_param(max_rx_latency, int, 0);
+module_param(min_tx_pkt, int, 0);
+module_param(max_tx_gap, int, 0);
+module_param(max_tx_latency, int, 0);
+module_param(rx_copybreak, int, 0);
+module_param_array(rx_params, int, NULL, 0);
+module_param_array(tx_params, int, NULL, 0);
+module_param_array(options, int, NULL, 0);
+module_param_array(full_duplex, int, NULL, 0);
+module_param(force32, int, 0);
 MODULE_PARM_DESC(max_interrupt_work, "GNIC-II maximum events handled per interrupt");
 MODULE_PARM_DESC(mtu, "GNIC-II MTU (all boards)");
 MODULE_PARM_DESC(debug, "GNIC-II debug level (0-7)");
@@ -549,7 +547,7 @@ MODULE_PARM_DESC(options, "GNIC-II Bits 0-3: media type, bits 4-6: as force32, b
 MODULE_PARM_DESC(full_duplex, "GNIC-II full duplex setting(s) (1)");
 MODULE_PARM_DESC(force32, "GNIC-II: Bit 0: 32 bit PCI, bit 1: disable parity, bit 2: 64 bit PCI (all boards)");
                                                                         
-static int read_eeprom(long ioaddr, int location);
+static int read_eeprom(void __iomem *ioaddr, int location);
 static int mdio_read(struct net_device *dev, int phy_id, int location);
 static void mdio_write(struct net_device *dev, int phy_id, int location, int value);
 static int hamachi_open(struct net_device *dev);
@@ -559,13 +557,14 @@ static void hamachi_tx_timeout(struct net_device *dev);
 static void hamachi_init_ring(struct net_device *dev);
 static int hamachi_start_xmit(struct sk_buff *skb, struct net_device *dev);
 static irqreturn_t hamachi_interrupt(int irq, void *dev_instance, struct pt_regs *regs);
-static inline int hamachi_rx(struct net_device *dev);
+static int hamachi_rx(struct net_device *dev);
 static inline int hamachi_tx(struct net_device *dev);
 static void hamachi_error(struct net_device *dev, int intr_status);
 static int hamachi_close(struct net_device *dev);
 static struct net_device_stats *hamachi_get_stats(struct net_device *dev);
 static void set_rx_mode(struct net_device *dev);
-
+static struct ethtool_ops ethtool_ops;
+static struct ethtool_ops ethtool_ops_no_mii;
 
 static int __devinit hamachi_init_one (struct pci_dev *pdev,
                                    const struct pci_device_id *ent)
@@ -574,7 +573,8 @@ static int __devinit hamachi_init_one (struct pci_dev *pdev,
        int option, i, rx_int_var, tx_int_var, boguscnt;
        int chip_id = ent->driver_data;
        int irq;
-       long ioaddr;
+       void __iomem *ioaddr;
+       unsigned long base;
        static int card_idx;
        struct net_device *dev;
        void *ring_space;
@@ -593,18 +593,19 @@ static int __devinit hamachi_init_one (struct pci_dev *pdev,
                goto err_out;
        }
 
-       ioaddr = pci_resource_start(pdev, 0);
+       base = pci_resource_start(pdev, 0);
 #ifdef __alpha__                               /* Really "64 bit addrs" */
-       ioaddr |= (pci_resource_start(pdev, 1) << 32);
+       base |= (pci_resource_start(pdev, 1) << 32);
 #endif
 
        pci_set_master(pdev);
 
        i = pci_request_regions(pdev, DRV_NAME);
-       if (i) return i;
+       if (i)
+               return i;
 
        irq = pdev->irq;
-       ioaddr = (long) ioremap(ioaddr, 0x400);
+       ioaddr = ioremap(base, 0x400);
        if (!ioaddr)
                goto err_out_release;
 
@@ -631,7 +632,7 @@ static int __devinit hamachi_init_one (struct pci_dev *pdev,
                                   read_eeprom(ioaddr, i), i % 16 != 15 ? " " : "\n");
 #endif
 
-       hmp = dev->priv;
+       hmp = netdev_priv(dev);
        spin_lock_init(&hmp->lock);
 
        hmp->mii_if.dev = dev;
@@ -677,7 +678,8 @@ static int __devinit hamachi_init_one (struct pci_dev *pdev,
                i = readb(ioaddr + PCIClkMeas); 
        }
 
-       dev->base_addr = ioaddr;
+       hmp->base = ioaddr;
+       dev->base_addr = (unsigned long)ioaddr;
        dev->irq = irq;
        pci_set_drvdata(pdev, dev);
 
@@ -725,6 +727,10 @@ static int __devinit hamachi_init_one (struct pci_dev *pdev,
        dev->get_stats = &hamachi_get_stats;
        dev->set_multicast_list = &set_rx_mode;
        dev->do_ioctl = &netdev_ioctl;
+       if (chip_tbl[hmp->chip_id].flags & CanHaveMII)
+               SET_ETHTOOL_OPS(dev, &ethtool_ops);
+       else
+               SET_ETHTOOL_OPS(dev, &ethtool_ops_no_mii);
        dev->tx_timeout = &hamachi_tx_timeout;
        dev->watchdog_timeo = TX_TIMEOUT;
        if (mtu)
@@ -736,7 +742,7 @@ static int __devinit hamachi_init_one (struct pci_dev *pdev,
                goto err_out_unmap_rx;
        }
 
-       printk(KERN_INFO "%s: %s type %x at 0x%lx, ",
+       printk(KERN_INFO "%s: %s type %x at %p, ",
                   dev->name, chip_tbl[chip_id].name, readl(ioaddr + ChipRev),
                   ioaddr);
        for (i = 0; i < 5; i++)
@@ -785,14 +791,14 @@ err_out_unmap_tx:
 err_out_cleardev:
        free_netdev (dev);
 err_out_iounmap:
-       iounmap((char *)ioaddr);
+       iounmap(ioaddr);
 err_out_release:
        pci_release_regions(pdev);
 err_out:
        return ret;
 }
 
-static int __devinit read_eeprom(long ioaddr, int location)
+static int __devinit read_eeprom(void __iomem *ioaddr, int location)
 {
        int bogus_cnt = 1000;
 
@@ -814,7 +820,8 @@ static int __devinit read_eeprom(long ioaddr, int location)
 
 static int mdio_read(struct net_device *dev, int phy_id, int location)
 {
-       long ioaddr = dev->base_addr;
+       struct hamachi_private *hmp = netdev_priv(dev);
+       void __iomem *ioaddr = hmp->base;
        int i;
 
        /* We should check busy first - per docs -KDU */
@@ -831,7 +838,8 @@ static int mdio_read(struct net_device *dev, int phy_id, int location)
 
 static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
 {
-       long ioaddr = dev->base_addr;
+       struct hamachi_private *hmp = netdev_priv(dev);
+       void __iomem *ioaddr = hmp->base;
        int i;
 
        /* We should check busy first - per docs -KDU */
@@ -851,13 +859,13 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val
 \f
 static int hamachi_open(struct net_device *dev)
 {
-       struct hamachi_private *hmp = dev->priv;
-       long ioaddr = dev->base_addr;
+       struct hamachi_private *hmp = netdev_priv(dev);
+       void __iomem *ioaddr = hmp->base;
        int i;
        u32 rx_int_var, tx_int_var;
        u16 fifo_info;
 
-       i = request_irq(dev->irq, &hamachi_interrupt, SA_SHIRQ, dev->name, dev);
+       i = request_irq(dev->irq, &hamachi_interrupt, IRQF_SHARED, dev->name, dev);
        if (i)
                return i;
 
@@ -982,7 +990,7 @@ static int hamachi_open(struct net_device *dev)
        writew(0x001D, ioaddr + RxDMACtrl);
        writew(0x001D, ioaddr + TxDMACtrl);
 #endif
-       writew(0x0001, dev->base_addr + RxCmd);
+       writew(0x0001, ioaddr + RxCmd);
 
        if (hamachi_debug > 2) {
                printk(KERN_DEBUG "%s: Done hamachi_open(), status: Rx %x Tx %x.\n",
@@ -1000,7 +1008,7 @@ static int hamachi_open(struct net_device *dev)
 
 static inline int hamachi_tx(struct net_device *dev)
 {
-       struct hamachi_private *hmp = dev->priv;
+       struct hamachi_private *hmp = netdev_priv(dev);
 
        /* Update the dirty pointer until we find an entry that is
                still owned by the card */
@@ -1032,8 +1040,8 @@ static inline int hamachi_tx(struct net_device *dev)
 static void hamachi_timer(unsigned long data)
 {
        struct net_device *dev = (struct net_device *)data;
-       struct hamachi_private *hmp = dev->priv;
-       long ioaddr = dev->base_addr;
+       struct hamachi_private *hmp = netdev_priv(dev);
+       void __iomem *ioaddr = hmp->base;
        int next_tick = 10*HZ;
 
        if (hamachi_debug > 2) {
@@ -1057,8 +1065,8 @@ static void hamachi_timer(unsigned long data)
 static void hamachi_tx_timeout(struct net_device *dev)
 {
        int i;
-       struct hamachi_private *hmp = dev->priv;
-       long ioaddr = dev->base_addr;
+       struct hamachi_private *hmp = netdev_priv(dev);
+       void __iomem *ioaddr = hmp->base;
 
        printk(KERN_WARNING "%s: Hamachi transmit timed out, status %8.8x,"
                   " resetting...\n", dev->name, (int)readw(ioaddr + TxStatus));
@@ -1110,7 +1118,7 @@ static void hamachi_tx_timeout(struct net_device *dev)
        }
 
        udelay(60); /* Sleep 60 us just for safety sake */
-       writew(0x0002, dev->base_addr + RxCmd); /* STOP Rx */
+       writew(0x0002, ioaddr + RxCmd); /* STOP Rx */
                
        writeb(0x01, ioaddr + ChipReset);  /* Reinit the hardware */ 
 
@@ -1139,7 +1147,7 @@ static void hamachi_tx_timeout(struct net_device *dev)
                skb->dev = dev;         /* Mark as being used by this device. */
                skb_reserve(skb, 2); /* 16 byte align the IP header. */
                 hmp->rx_ring[i].addr = cpu_to_leXX(pci_map_single(hmp->pci_dev, 
-                       skb->tail, hmp->rx_buf_sz, PCI_DMA_FROMDEVICE));
+                       skb->data, hmp->rx_buf_sz, PCI_DMA_FROMDEVICE));
                hmp->rx_ring[i].status_n_length = cpu_to_le32(DescOwn | 
                        DescEndPacket | DescIntr | (hmp->rx_buf_sz - 2));
        }
@@ -1152,9 +1160,9 @@ static void hamachi_tx_timeout(struct net_device *dev)
        hmp->stats.tx_errors++;
 
        /* Restart the chip's Tx/Rx processes . */
-       writew(0x0002, dev->base_addr + TxCmd); /* STOP Tx */
-       writew(0x0001, dev->base_addr + TxCmd); /* START Tx */
-       writew(0x0001, dev->base_addr + RxCmd); /* START Rx */
+       writew(0x0002, ioaddr + TxCmd); /* STOP Tx */
+       writew(0x0001, ioaddr + TxCmd); /* START Tx */
+       writew(0x0001, ioaddr + RxCmd); /* START Rx */
 
        netif_wake_queue(dev);
 }
@@ -1163,7 +1171,7 @@ static void hamachi_tx_timeout(struct net_device *dev)
 /* Initialize the Rx and Tx rings, along with various 'dev' bits. */
 static void hamachi_init_ring(struct net_device *dev)
 {
-       struct hamachi_private *hmp = dev->priv;
+       struct hamachi_private *hmp = netdev_priv(dev);
        int i;
 
        hmp->tx_full = 0;
@@ -1200,7 +1208,7 @@ static void hamachi_init_ring(struct net_device *dev)
                skb->dev = dev;         /* Mark as being used by this device. */
                skb_reserve(skb, 2); /* 16 byte align the IP header. */
                 hmp->rx_ring[i].addr = cpu_to_leXX(pci_map_single(hmp->pci_dev, 
-                       skb->tail, hmp->rx_buf_sz, PCI_DMA_FROMDEVICE));
+                       skb->data, hmp->rx_buf_sz, PCI_DMA_FROMDEVICE));
                /* -2 because it doesn't REALLY have that first 2 bytes -KDU */
                hmp->rx_ring[i].status_n_length = cpu_to_le32(DescOwn | 
                        DescEndPacket | DescIntr | (hmp->rx_buf_sz -2));
@@ -1255,7 +1263,7 @@ do { \
 
 static int hamachi_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-       struct hamachi_private *hmp = dev->priv;
+       struct hamachi_private *hmp = netdev_priv(dev);
        unsigned entry;
        u16 status;
 
@@ -1270,9 +1278,9 @@ static int hamachi_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
                /* Wake the potentially-idle transmit channel. */
                /* If we don't need to read status, DON'T -KDU */
-               status=readw(dev->base_addr + TxStatus);
+               status=readw(hmp->base + TxStatus);
                if( !(status & 0x0001) || (status & 0x0002))
-                       writew(0x0001, dev->base_addr + TxCmd);
+                       writew(0x0001, hmp->base + TxCmd);
                return 1;
        } 
 
@@ -1338,9 +1346,9 @@ static int hamachi_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        /* Wake the potentially-idle transmit channel. */
        /* If we don't need to read status, DON'T -KDU */
-       status=readw(dev->base_addr + TxStatus);
+       status=readw(hmp->base + TxStatus);
        if( !(status & 0x0001) || (status & 0x0002))
-               writew(0x0001, dev->base_addr + TxCmd);
+               writew(0x0001, hmp->base + TxCmd);
 
        /* Immediately before returning, let's clear as many entries as we can. */
        hamachi_tx(dev);
@@ -1371,8 +1379,9 @@ static int hamachi_start_xmit(struct sk_buff *skb, struct net_device *dev)
 static irqreturn_t hamachi_interrupt(int irq, void *dev_instance, struct pt_regs *rgs)
 {
        struct net_device *dev = dev_instance;
-       struct hamachi_private *hmp;
-       long ioaddr, boguscnt = max_interrupt_work;
+       struct hamachi_private *hmp = netdev_priv(dev);
+       void __iomem *ioaddr = hmp->base;
+       long boguscnt = max_interrupt_work;
        int handled = 0;
 
 #ifndef final_version                  /* Can never occur. */
@@ -1382,8 +1391,6 @@ static irqreturn_t hamachi_interrupt(int irq, void *dev_instance, struct pt_regs
        }
 #endif
 
-       ioaddr = dev->base_addr;
-       hmp = dev->priv;
        spin_lock(&hmp->lock);
 
        do {
@@ -1477,7 +1484,7 @@ static irqreturn_t hamachi_interrupt(int irq, void *dev_instance, struct pt_regs
    for clarity and better register allocation. */
 static int hamachi_rx(struct net_device *dev)
 {
-       struct hamachi_private *hmp = dev->priv;
+       struct hamachi_private *hmp = netdev_priv(dev);
        int entry = hmp->cur_rx % RX_RING_SIZE;
        int boguscnt = (hmp->dirty_rx + RX_RING_SIZE) - hmp->cur_rx;
 
@@ -1500,7 +1507,7 @@ static int hamachi_rx(struct net_device *dev)
                                            desc->addr,
                                            hmp->rx_buf_sz,
                                            PCI_DMA_FROMDEVICE);
-               buf_addr = (u8 *) hmp->rx_skbuff[entry]->tail;
+               buf_addr = (u8 *) hmp->rx_skbuff[entry]->data;
                frame_status = le32_to_cpu(get_unaligned((s32*)&(buf_addr[data_size - 12])));
                if (hamachi_debug > 4)
                        printk(KERN_DEBUG "  hamachi_rx() status was %8.8x.\n",
@@ -1669,7 +1676,7 @@ static int hamachi_rx(struct net_device *dev)
                        skb->dev = dev;         /* Mark as being used by this device. */
                        skb_reserve(skb, 2);    /* Align IP on 16 byte boundaries */
                        desc->addr = cpu_to_leXX(pci_map_single(hmp->pci_dev, 
-                               skb->tail, hmp->rx_buf_sz, PCI_DMA_FROMDEVICE));
+                               skb->data, hmp->rx_buf_sz, PCI_DMA_FROMDEVICE));
                }
                desc->status_n_length = cpu_to_le32(hmp->rx_buf_sz);
                if (entry >= RX_RING_SIZE-1)
@@ -1682,8 +1689,8 @@ static int hamachi_rx(struct net_device *dev)
 
        /* Restart Rx engine if stopped. */
        /* If we don't need to check status, don't. -KDU */
-       if (readw(dev->base_addr + RxStatus) & 0x0002)
-               writew(0x0001, dev->base_addr + RxCmd);
+       if (readw(hmp->base + RxStatus) & 0x0002)
+               writew(0x0001, hmp->base + RxCmd);
 
        return 0;
 }
@@ -1692,8 +1699,8 @@ static int hamachi_rx(struct net_device *dev)
    than just errors. */
 static void hamachi_error(struct net_device *dev, int intr_status)
 {
-       long ioaddr = dev->base_addr;
-       struct hamachi_private *hmp = dev->priv;
+       struct hamachi_private *hmp = netdev_priv(dev);
+       void __iomem *ioaddr = hmp->base;
 
        if (intr_status & (LinkChange|NegotiationChange)) {
                if (hamachi_debug > 1)
@@ -1726,8 +1733,8 @@ static void hamachi_error(struct net_device *dev, int intr_status)
 
 static int hamachi_close(struct net_device *dev)
 {
-       long ioaddr = dev->base_addr;
-       struct hamachi_private *hmp = dev->priv;
+       struct hamachi_private *hmp = netdev_priv(dev);
+       void __iomem *ioaddr = hmp->base;
        struct sk_buff *skb;
        int i;
 
@@ -1763,9 +1770,9 @@ static int hamachi_close(struct net_device *dev)
                                   readl(ioaddr + RxCurPtr) == (long)&hmp->rx_ring[i] ? '>' : ' ',
                                   i, hmp->rx_ring[i].status_n_length, hmp->rx_ring[i].addr);
                        if (hamachi_debug > 6) {
-                               if (*(u8*)hmp->rx_skbuff[i]->tail != 0x69) {
+                               if (*(u8*)hmp->rx_skbuff[i]->data != 0x69) {
                                        u16 *addr = (u16 *)
-                                               hmp->rx_skbuff[i]->tail;
+                                               hmp->rx_skbuff[i]->data;
                                        int j;
 
                                        for (j = 0; j < 0x50; j++)
@@ -1812,8 +1819,8 @@ static int hamachi_close(struct net_device *dev)
 
 static struct net_device_stats *hamachi_get_stats(struct net_device *dev)
 {
-       long ioaddr = dev->base_addr;
-       struct hamachi_private *hmp = dev->priv;
+       struct hamachi_private *hmp = netdev_priv(dev);
+       void __iomem *ioaddr = hmp->base;
 
        /* We should lock this segment of code for SMP eventually, although
           the vulnerability window is very small and statistics are
@@ -1840,7 +1847,8 @@ static struct net_device_stats *hamachi_get_stats(struct net_device *dev)
 
 static void set_rx_mode(struct net_device *dev)
 {
-       long ioaddr = dev->base_addr;
+       struct hamachi_private *hmp = netdev_priv(dev);
+       void __iomem *ioaddr = hmp->base;
 
        if (dev->flags & IFF_PROMISC) {                 /* Set promiscuous. */
                /* Unconditionally log net taps. */
@@ -1867,84 +1875,76 @@ static void set_rx_mode(struct net_device *dev)
        }
 }
 
-static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr)
+static int check_if_running(struct net_device *dev)
 {
-       struct hamachi_private *np = dev->priv;
-       u32 ethcmd;
-               
-       if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
-               return -EFAULT;
-
-        switch (ethcmd) {
-        case ETHTOOL_GDRVINFO: {
-               struct ethtool_drvinfo info = {ETHTOOL_GDRVINFO};
-               strcpy(info.driver, DRV_NAME);
-               strcpy(info.version, DRV_VERSION);
-               strcpy(info.bus_info, pci_name(np->pci_dev));
-               if (copy_to_user(useraddr, &info, sizeof(info)))
-                       return -EFAULT;
-               return 0;
-       }
+       if (!netif_running(dev))
+               return -EINVAL;
+       return 0;
+}
 
-       /* get settings */
-       case ETHTOOL_GSET: {
-               struct ethtool_cmd ecmd = { ETHTOOL_GSET };
-               if (!(chip_tbl[np->chip_id].flags & CanHaveMII))
-                       return -EINVAL;
-               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 (!(chip_tbl[np->chip_id].flags & CanHaveMII))
-                       return -EINVAL;
-               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: {
-               if (!(chip_tbl[np->chip_id].flags & CanHaveMII))
-                       return -EINVAL;
-               return mii_nway_restart(&np->mii_if);
-       }
-       /* get link status */
-       case ETHTOOL_GLINK: {
-               struct ethtool_value edata = {ETHTOOL_GLINK};
-               if (!(chip_tbl[np->chip_id].flags & CanHaveMII))
-                       return -EINVAL;
-               edata.data = mii_link_ok(&np->mii_if);
-               if (copy_to_user(useraddr, &edata, sizeof(edata)))
-                       return -EFAULT;
-               return 0;
-       }
-        }
-       
-       return -EOPNOTSUPP;
+static void hamachi_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+       struct hamachi_private *np = netdev_priv(dev);
+       strcpy(info->driver, DRV_NAME);
+       strcpy(info->version, DRV_VERSION);
+       strcpy(info->bus_info, pci_name(np->pci_dev));
+}
+
+static int hamachi_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+       struct hamachi_private *np = netdev_priv(dev);
+       spin_lock_irq(&np->lock);
+       mii_ethtool_gset(&np->mii_if, ecmd);
+       spin_unlock_irq(&np->lock);
+       return 0;
+}
+
+static int hamachi_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+       struct hamachi_private *np = netdev_priv(dev);
+       int res;
+       spin_lock_irq(&np->lock);
+       res = mii_ethtool_sset(&np->mii_if, ecmd);
+       spin_unlock_irq(&np->lock);
+       return res;
 }
 
+static int hamachi_nway_reset(struct net_device *dev)
+{
+       struct hamachi_private *np = netdev_priv(dev);
+       return mii_nway_restart(&np->mii_if);
+}
+
+static u32 hamachi_get_link(struct net_device *dev)
+{
+       struct hamachi_private *np = netdev_priv(dev);
+       return mii_link_ok(&np->mii_if);
+}
+
+static struct ethtool_ops ethtool_ops = {
+       .begin = check_if_running,
+       .get_drvinfo = hamachi_get_drvinfo,
+       .get_settings = hamachi_get_settings,
+       .set_settings = hamachi_set_settings,
+       .nway_reset = hamachi_nway_reset,
+       .get_link = hamachi_get_link,
+};
+
+static struct ethtool_ops ethtool_ops_no_mii = {
+       .begin = check_if_running,
+       .get_drvinfo = hamachi_get_drvinfo,
+};
+
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-       struct hamachi_private *np = dev->priv;
+       struct hamachi_private *np = netdev_priv(dev);
        struct mii_ioctl_data *data = if_mii(rq);
        int rc;
 
        if (!netif_running(dev))
                return -EINVAL;
 
-       if (cmd == SIOCETHTOOL)
-               rc = netdev_ethtool_ioctl(dev, rq->ifr_data);
-
-       else if (cmd == (SIOCDEVPRIVATE+3)) { /* set rx,tx intr params */
+       if (cmd == (SIOCDEVPRIVATE+3)) { /* set rx,tx intr params */
                u32 *d = (u32 *)&rq->ifr_ifru;
                /* Should add this check here or an ordinary user can do nasty
                 * things. -KDU
@@ -1953,11 +1953,11 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                 */
                if (!capable(CAP_NET_ADMIN))
                        return -EPERM;
-               writel(d[0], dev->base_addr + TxIntrCtrl);
-               writel(d[1], dev->base_addr + RxIntrCtrl);
+               writel(d[0], np->base + TxIntrCtrl);
+               writel(d[1], np->base + RxIntrCtrl);
                printk(KERN_NOTICE "%s: tx %08x, rx %08x intr\n", dev->name,
-                 (u32) readl(dev->base_addr + TxIntrCtrl),
-                 (u32) readl(dev->base_addr + RxIntrCtrl));
+                 (u32) readl(np->base + TxIntrCtrl),
+                 (u32) readl(np->base + RxIntrCtrl));
                rc = 0;
        }
 
@@ -1976,14 +1976,14 @@ static void __devexit hamachi_remove_one (struct pci_dev *pdev)
        struct net_device *dev = pci_get_drvdata(pdev);
 
        if (dev) {
-               struct hamachi_private *hmp = dev->priv;
+               struct hamachi_private *hmp = netdev_priv(dev);
 
                pci_free_consistent(pdev, RX_TOTAL_SIZE, hmp->rx_ring, 
                        hmp->rx_ring_dma);
                pci_free_consistent(pdev, TX_TOTAL_SIZE, hmp->tx_ring, 
                        hmp->tx_ring_dma);
                unregister_netdev(dev);
-               iounmap((char *)dev->base_addr);
+               iounmap(hmp->base);
                free_netdev(dev);
                pci_release_regions(pdev);
                pci_set_drvdata(pdev, NULL);
@@ -2009,10 +2009,7 @@ static int __init hamachi_init (void)
 #ifdef MODULE
        printk(version);
 #endif
-       if (pci_register_driver(&hamachi_driver) > 0)
-               return 0;
-       pci_unregister_driver(&hamachi_driver);
-       return -ENODEV;
+       return pci_register_driver(&hamachi_driver);
 }
 
 static void __exit hamachi_exit (void)