vserver 1.9.5.x5
[linux-2.6.git] / drivers / net / sundance.c
index e0ddf2b..f3e4876 100644 (file)
@@ -162,9 +162,9 @@ static char *media[MAX_UNITS];
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/init.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 <linux/delay.h>
 #include <linux/spinlock.h>
@@ -188,10 +188,10 @@ MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("Sundance Alta Ethernet driver");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(debug, "i");
-MODULE_PARM(rx_copybreak, "i");
-MODULE_PARM(media, "1-" __MODULE_STRING(MAX_UNITS) "s");
-MODULE_PARM(flowctrl, "i");
+module_param(debug, int, 0);
+module_param(rx_copybreak, int, 0);
+module_param_array(media, charp, NULL, 0);
+module_param(flowctrl, int, 0);
 MODULE_PARM_DESC(debug, "Sundance Alta debug level (0-5)");
 MODULE_PARM_DESC(rx_copybreak, "Sundance Alta copy breakpoint for copy-only-tiny-frames");
 MODULE_PARM_DESC(flowctrl, "Sundance Alta flow control [0|1]");
@@ -305,20 +305,6 @@ static struct pci_id_info pci_id_tbl[] = {
 
 /* This driver was written to use PCI memory space, however x86-oriented
    hardware often uses I/O space accesses. */
-#ifdef USE_IO_OPS
-#undef readb
-#undef readw
-#undef readl
-#undef writeb
-#undef writew
-#undef writel
-#define readb inb
-#define readw inw
-#define readl inl
-#define writeb outb
-#define writew outw
-#define writel outl
-#endif
 
 /* Offsets to the device registers.
    Unlike software-only systems, device drivers interact with complex hardware.
@@ -480,6 +466,7 @@ struct netdev_private {
        int mii_preamble_required;
        unsigned char phys[MII_CNT];            /* MII device addresses, only first one used. */
        struct pci_dev *pci_dev;
+       void __iomem *base;
        unsigned char pci_rev_id;
 };
 
@@ -490,7 +477,7 @@ struct netdev_private {
                        LinkChange)
 
 static int  change_mtu(struct net_device *dev, int new_mtu);
-static int  eeprom_read(long ioaddr, int location);
+static int  eeprom_read(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  netdev_open(struct net_device *dev);
@@ -511,8 +498,7 @@ static int __set_mac_addr(struct net_device *dev);
 static struct net_device_stats *get_stats(struct net_device *dev);
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 static int  netdev_close(struct net_device *dev);
-
-
+static struct ethtool_ops ethtool_ops;
 
 static int __devinit sundance_probe1 (struct pci_dev *pdev,
                                      const struct pci_device_id *ent)
@@ -523,10 +509,15 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
        int chip_idx = ent->driver_data;
        int irq;
        int i;
-       long ioaddr;
+       void __iomem *ioaddr;
        u16 mii_ctl;
        void *ring_space;
        dma_addr_t ring_dma;
+#ifdef USE_IO_OPS
+       int bar = 0;
+#else
+       int bar = 1;
+#endif
 
 
 /* when built into the kernel, we only print version if device is found */
@@ -551,23 +542,19 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
        if (pci_request_regions(pdev, DRV_NAME))
                goto err_out_netdev;
 
-#ifdef USE_IO_OPS
-       ioaddr = pci_resource_start(pdev, 0);
-#else
-       ioaddr = pci_resource_start(pdev, 1);
-       ioaddr = (long) ioremap (ioaddr, netdev_io_size);
+       ioaddr = pci_iomap(pdev, bar, netdev_io_size);
        if (!ioaddr)
                goto err_out_res;
-#endif
 
        for (i = 0; i < 3; i++)
                ((u16 *)dev->dev_addr)[i] =
                        le16_to_cpu(eeprom_read(ioaddr, i + EEPROM_SA_OFFSET));
 
-       dev->base_addr = ioaddr;
+       dev->base_addr = (unsigned long)ioaddr;
        dev->irq = irq;
 
-       np = dev->priv;
+       np = netdev_priv(dev);
+       np->base = ioaddr;
        np->pci_dev = pdev;
        np->chip_id = chip_idx;
        np->msg_enable = (1 << debug) - 1;
@@ -600,6 +587,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
        dev->get_stats = &get_stats;
        dev->set_multicast_list = &set_rx_mode;
        dev->do_ioctl = &netdev_ioctl;
+       SET_ETHTOOL_OPS(dev, &ethtool_ops);
        dev->tx_timeout = &tx_timeout;
        dev->watchdog_timeo = TX_TIMEOUT;
        dev->change_mtu = &change_mtu;
@@ -611,7 +599,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
        if (i)
                goto err_out_unmap_rx;
 
-       printk(KERN_INFO "%s: %s at 0x%lx, ",
+       printk(KERN_INFO "%s: %s at %p, ",
                   dev->name, pci_id_tbl[chip_idx].name, ioaddr);
        for (i = 0; i < 5; i++)
                        printk("%2.2x:", dev->dev_addr[i]);
@@ -637,7 +625,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
 
                if (phy_idx == 0) {
                        printk(KERN_INFO "%s: No MII transceiver found, aborting.  ASIC status %x\n",
-                                  dev->name, readl(ioaddr + ASICCtrl));
+                                  dev->name, ioread32(ioaddr + ASICCtrl));
                        goto err_out_unregister;
                }
 
@@ -674,7 +662,7 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
        }
 
        /* Fibre PHY? */
-       if (readl (ioaddr + ASICCtrl) & 0x80) {
+       if (ioread32 (ioaddr + ASICCtrl) & 0x80) {
                /* Default 100Mbps Full */
                if (np->an_enable) {
                        np->speed = 100;
@@ -703,10 +691,10 @@ static int __devinit sundance_probe1 (struct pci_dev *pdev,
        /* Perhaps move the reset here? */
        /* Reset the chip to erase previous misconfiguration. */
        if (netif_msg_hw(np))
-               printk("ASIC Control is %x.\n", readl(ioaddr + ASICCtrl));
-       writew(0x007f, ioaddr + ASICCtrl + 2);
+               printk("ASIC Control is %x.\n", ioread32(ioaddr + ASICCtrl));
+       iowrite16(0x007f, ioaddr + ASICCtrl + 2);
        if (netif_msg_hw(np))
-               printk("ASIC Control is now %x.\n", readl(ioaddr + ASICCtrl));
+               printk("ASIC Control is now %x.\n", ioread32(ioaddr + ASICCtrl));
 
        card_idx++;
        return 0;
@@ -719,10 +707,8 @@ err_out_unmap_tx:
         pci_free_consistent(pdev, TX_TOTAL_SIZE, np->tx_ring, np->tx_ring_dma);
 err_out_cleardev:
        pci_set_drvdata(pdev, NULL);
-#ifndef USE_IO_OPS
-       iounmap((void *)ioaddr);
+       pci_iounmap(pdev, ioaddr);
 err_out_res:
-#endif
        pci_release_regions(pdev);
 err_out_netdev:
        free_netdev (dev);
@@ -739,16 +725,16 @@ static int change_mtu(struct net_device *dev, int new_mtu)
        return 0;
 }
 
-#define eeprom_delay(ee_addr)  readl(ee_addr)
+#define eeprom_delay(ee_addr)  ioread32(ee_addr)
 /* Read the EEPROM and MII Management Data I/O (MDIO) interfaces. */
-static int __devinit eeprom_read(long ioaddr, int location)
+static int __devinit eeprom_read(void __iomem *ioaddr, int location)
 {
        int boguscnt = 10000;           /* Typical 1900 ticks. */
-       writew(0x0200 | (location & 0xff), ioaddr + EECtrl);
+       iowrite16(0x0200 | (location & 0xff), ioaddr + EECtrl);
        do {
                eeprom_delay(ioaddr + EECtrl);
-               if (! (readw(ioaddr + EECtrl) & 0x8000)) {
-                       return readw(ioaddr + EEData);
+               if (! (ioread16(ioaddr + EECtrl) & 0x8000)) {
+                       return ioread16(ioaddr + EEData);
                }
        } while (--boguscnt > 0);
        return 0;
@@ -761,7 +747,7 @@ static int __devinit eeprom_read(long ioaddr, int location)
 
        The maximum data clock rate is 2.5 Mhz.  The minimum timing is usually
        met by back-to-back 33Mhz PCI cycles. */
-#define mdio_delay() readb(mdio_addr)
+#define mdio_delay() ioread8(mdio_addr)
 
 enum mii_reg_bits {
        MDIO_ShiftClk=0x0001, MDIO_Data=0x0002, MDIO_EnbOutput=0x0004,
@@ -772,23 +758,23 @@ enum mii_reg_bits {
 
 /* Generate the preamble required for initial synchronization and
    a few older transceivers. */
-static void mdio_sync(long mdio_addr)
+static void mdio_sync(void __iomem *mdio_addr)
 {
        int bits = 32;
 
        /* Establish sync by sending at least 32 logic ones. */
        while (--bits >= 0) {
-               writeb(MDIO_WRITE1, mdio_addr);
+               iowrite8(MDIO_WRITE1, mdio_addr);
                mdio_delay();
-               writeb(MDIO_WRITE1 | MDIO_ShiftClk, mdio_addr);
+               iowrite8(MDIO_WRITE1 | MDIO_ShiftClk, mdio_addr);
                mdio_delay();
        }
 }
 
 static int mdio_read(struct net_device *dev, int phy_id, int location)
 {
-       struct netdev_private *np = dev->priv;
-       long mdio_addr = dev->base_addr + MIICtrl;
+       struct netdev_private *np = netdev_priv(dev);
+       void __iomem *mdio_addr = np->base + MIICtrl;
        int mii_cmd = (0xf6 << 10) | (phy_id << 5) | location;
        int i, retval = 0;
 
@@ -799,17 +785,17 @@ static int mdio_read(struct net_device *dev, int phy_id, int location)
        for (i = 15; i >= 0; i--) {
                int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
 
-               writeb(dataval, mdio_addr);
+               iowrite8(dataval, mdio_addr);
                mdio_delay();
-               writeb(dataval | MDIO_ShiftClk, mdio_addr);
+               iowrite8(dataval | MDIO_ShiftClk, mdio_addr);
                mdio_delay();
        }
        /* Read the two transition, 16 data, and wire-idle bits. */
        for (i = 19; i > 0; i--) {
-               writeb(MDIO_EnbIn, mdio_addr);
+               iowrite8(MDIO_EnbIn, mdio_addr);
                mdio_delay();
-               retval = (retval << 1) | ((readb(mdio_addr) & MDIO_Data) ? 1 : 0);
-               writeb(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr);
+               retval = (retval << 1) | ((ioread8(mdio_addr) & MDIO_Data) ? 1 : 0);
+               iowrite8(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr);
                mdio_delay();
        }
        return (retval>>1) & 0xffff;
@@ -817,8 +803,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)
 {
-       struct netdev_private *np = dev->priv;
-       long mdio_addr = dev->base_addr + MIICtrl;
+       struct netdev_private *np = netdev_priv(dev);
+       void __iomem *mdio_addr = np->base + MIICtrl;
        int mii_cmd = (0x5002 << 16) | (phy_id << 23) | (location<<18) | value;
        int i;
 
@@ -829,16 +815,16 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val
        for (i = 31; i >= 0; i--) {
                int dataval = (mii_cmd & (1 << i)) ? MDIO_WRITE1 : MDIO_WRITE0;
 
-               writeb(dataval, mdio_addr);
+               iowrite8(dataval, mdio_addr);
                mdio_delay();
-               writeb(dataval | MDIO_ShiftClk, mdio_addr);
+               iowrite8(dataval | MDIO_ShiftClk, mdio_addr);
                mdio_delay();
        }
        /* Clear out extra bits. */
        for (i = 2; i > 0; i--) {
-               writeb(MDIO_EnbIn, mdio_addr);
+               iowrite8(MDIO_EnbIn, mdio_addr);
                mdio_delay();
-               writeb(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr);
+               iowrite8(MDIO_EnbIn | MDIO_ShiftClk, mdio_addr);
                mdio_delay();
        }
        return;
@@ -846,8 +832,8 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val
 
 static int netdev_open(struct net_device *dev)
 {
-       struct netdev_private *np = dev->priv;
-       long ioaddr = dev->base_addr;
+       struct netdev_private *np = netdev_priv(dev);
+       void __iomem *ioaddr = np->base;
        int i;
 
        /* Do we need to reset the chip??? */
@@ -861,45 +847,45 @@ static int netdev_open(struct net_device *dev)
                           dev->name, dev->irq);
        init_ring(dev);
 
-       writel(np->rx_ring_dma, ioaddr + RxListPtr);
+       iowrite32(np->rx_ring_dma, ioaddr + RxListPtr);
        /* The Tx list pointer is written as packets are queued. */
 
        /* Initialize other registers. */
        __set_mac_addr(dev);
 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-       writew(dev->mtu + 18, ioaddr + MaxFrameSize);
+       iowrite16(dev->mtu + 18, ioaddr + MaxFrameSize);
 #else
-       writew(dev->mtu + 14, ioaddr + MaxFrameSize);
+       iowrite16(dev->mtu + 14, ioaddr + MaxFrameSize);
 #endif
        if (dev->mtu > 2047)
-               writel(readl(ioaddr + ASICCtrl) | 0x0C, ioaddr + ASICCtrl);
+               iowrite32(ioread32(ioaddr + ASICCtrl) | 0x0C, ioaddr + ASICCtrl);
 
        /* Configure the PCI bus bursts and FIFO thresholds. */
 
        if (dev->if_port == 0)
                dev->if_port = np->default_port;
 
-       np->mcastlock = SPIN_LOCK_UNLOCKED;
+       spin_lock_init(&np->mcastlock);
 
        set_rx_mode(dev);
-       writew(0, ioaddr + IntrEnable);
-       writew(0, ioaddr + DownCounter);
+       iowrite16(0, ioaddr + IntrEnable);
+       iowrite16(0, ioaddr + DownCounter);
        /* Set the chip to poll every N*320nsec. */
-       writeb(100, ioaddr + RxDMAPollPeriod);
-       writeb(127, ioaddr + TxDMAPollPeriod);
+       iowrite8(100, ioaddr + RxDMAPollPeriod);
+       iowrite8(127, ioaddr + TxDMAPollPeriod);
        /* Fix DFE-580TX packet drop issue */
        if (np->pci_rev_id >= 0x14)
-               writeb(0x01, ioaddr + DebugCtrl1);
+               iowrite8(0x01, ioaddr + DebugCtrl1);
        netif_start_queue(dev);
 
-       writew (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl1);
+       iowrite16 (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl1);
 
        if (netif_msg_ifup(np))
                printk(KERN_DEBUG "%s: Done netdev_open(), status: Rx %x Tx %x "
                           "MAC Control %x, %4.4x %4.4x.\n",
-                          dev->name, readl(ioaddr + RxStatus), readb(ioaddr + TxStatus),
-                          readl(ioaddr + MACCtrl0),
-                          readw(ioaddr + MACCtrl1), readw(ioaddr + MACCtrl0));
+                          dev->name, ioread32(ioaddr + RxStatus), ioread8(ioaddr + TxStatus),
+                          ioread32(ioaddr + MACCtrl0),
+                          ioread16(ioaddr + MACCtrl1), ioread16(ioaddr + MACCtrl0));
 
        /* Set the timer to check for link beat. */
        init_timer(&np->timer);
@@ -909,15 +895,15 @@ static int netdev_open(struct net_device *dev)
        add_timer(&np->timer);
 
        /* Enable interrupts by setting the interrupt mask. */
-       writew(DEFAULT_INTR, ioaddr + IntrEnable);
+       iowrite16(DEFAULT_INTR, ioaddr + IntrEnable);
 
        return 0;
 }
 
 static void check_duplex(struct net_device *dev)
 {
-       struct netdev_private *np = dev->priv;
-       long ioaddr = dev->base_addr;
+       struct netdev_private *np = netdev_priv(dev);
+       void __iomem *ioaddr = np->base;
        int mii_lpa = mdio_read(dev, np->phys[0], MII_LPA);
        int negotiated = mii_lpa & np->mii_if.advertising;
        int duplex;
@@ -925,7 +911,7 @@ static void check_duplex(struct net_device *dev)
        /* Force media */
        if (!np->an_enable || mii_lpa == 0xffff) {
                if (np->mii_if.full_duplex)
-                       writew (readw (ioaddr + MACCtrl0) | EnbFullDuplex,
+                       iowrite16 (ioread16 (ioaddr + MACCtrl0) | EnbFullDuplex,
                                ioaddr + MACCtrl0);
                return;
        }
@@ -938,22 +924,22 @@ static void check_duplex(struct net_device *dev)
                        printk(KERN_INFO "%s: Setting %s-duplex based on MII #%d "
                                   "negotiated capability %4.4x.\n", dev->name,
                                   duplex ? "full" : "half", np->phys[0], negotiated);
-               writew(readw(ioaddr + MACCtrl0) | duplex ? 0x20 : 0, ioaddr + MACCtrl0);
+               iowrite16(ioread16(ioaddr + MACCtrl0) | duplex ? 0x20 : 0, ioaddr + MACCtrl0);
        }
 }
 
 static void netdev_timer(unsigned long data)
 {
        struct net_device *dev = (struct net_device *)data;
-       struct netdev_private *np = dev->priv;
-       long ioaddr = dev->base_addr;
+       struct netdev_private *np = netdev_priv(dev);
+       void __iomem *ioaddr = np->base;
        int next_tick = 10*HZ;
 
        if (netif_msg_timer(np)) {
                printk(KERN_DEBUG "%s: Media selection timer tick, intr status %4.4x, "
                           "Tx %x Rx %x.\n",
-                          dev->name, readw(ioaddr + IntrEnable),
-                          readb(ioaddr + TxStatus), readl(ioaddr + RxStatus));
+                          dev->name, ioread16(ioaddr + IntrEnable),
+                          ioread8(ioaddr + TxStatus), ioread32(ioaddr + RxStatus));
        }
        check_duplex(dev);
        np->timer.expires = jiffies + next_tick;
@@ -962,17 +948,17 @@ static void netdev_timer(unsigned long data)
 
 static void tx_timeout(struct net_device *dev)
 {
-       struct netdev_private *np = dev->priv;
-       long ioaddr = dev->base_addr;
+       struct netdev_private *np = netdev_priv(dev);
+       void __iomem *ioaddr = np->base;
        unsigned long flag;
        
        netif_stop_queue(dev);
        tasklet_disable(&np->tx_tasklet);
-       writew(0, ioaddr + IntrEnable);
+       iowrite16(0, ioaddr + IntrEnable);
        printk(KERN_WARNING "%s: Transmit timed out, TxStatus %2.2x "
                   "TxFrameId %2.2x,"
-                  " resetting...\n", dev->name, readb(ioaddr + TxStatus),
-                  readb(ioaddr + TxFrameId));
+                  " resetting...\n", dev->name, ioread8(ioaddr + TxStatus),
+                  ioread8(ioaddr + TxFrameId));
 
        {
                int i;
@@ -986,7 +972,7 @@ static void tx_timeout(struct net_device *dev)
                                le32_to_cpu(np->tx_ring[i].frag[0].length));
                }
                printk(KERN_DEBUG "TxListPtr=%08x netif_queue_stopped=%d\n", 
-                       readl(dev->base_addr + TxListPtr), 
+                       ioread32(np->base + TxListPtr), 
                        netif_queue_stopped(dev));
                printk(KERN_DEBUG "cur_tx=%d(%02x) dirty_tx=%d(%02x)\n", 
                        np->cur_tx, np->cur_tx % TX_RING_SIZE,
@@ -1007,7 +993,7 @@ static void tx_timeout(struct net_device *dev)
        if (np->cur_tx - np->dirty_tx < TX_QUEUE_LEN - 4) {
                netif_wake_queue(dev);
        }
-       writew(DEFAULT_INTR, ioaddr + IntrEnable);
+       iowrite16(DEFAULT_INTR, ioaddr + IntrEnable);
        tasklet_enable(&np->tx_tasklet);
 }
 
@@ -1015,7 +1001,7 @@ static void tx_timeout(struct net_device *dev)
 /* Initialize the Rx and Tx rings, along with various 'dev' bits. */
 static void init_ring(struct net_device *dev)
 {
-       struct netdev_private *np = dev->priv;
+       struct netdev_private *np = netdev_priv(dev);
        int i;
 
        np->cur_rx = np->cur_tx = 0;
@@ -1058,7 +1044,7 @@ static void init_ring(struct net_device *dev)
 static void tx_poll (unsigned long data)
 {
        struct net_device *dev = (struct net_device *)data;
-       struct netdev_private *np = dev->priv;
+       struct netdev_private *np = netdev_priv(dev);
        unsigned head = np->cur_task % TX_RING_SIZE;
        struct netdev_desc *txdesc = 
                &np->tx_ring[(np->cur_tx - 1) % TX_RING_SIZE];
@@ -1076,16 +1062,16 @@ static void tx_poll (unsigned long data)
        /* Indicate the latest descriptor of tx ring */
        txdesc->status |= cpu_to_le32(DescIntrOnTx);
 
-       if (readl (dev->base_addr + TxListPtr) == 0)
-               writel (np->tx_ring_dma + head * sizeof(struct netdev_desc),
-                       dev->base_addr + TxListPtr);
+       if (ioread32 (np->base + TxListPtr) == 0)
+               iowrite32 (np->tx_ring_dma + head * sizeof(struct netdev_desc),
+                       np->base + TxListPtr);
        return;
 }
 
 static int
 start_tx (struct sk_buff *skb, struct net_device *dev)
 {
-       struct netdev_private *np = dev->priv;
+       struct netdev_private *np = netdev_priv(dev);
        struct netdev_desc *txdesc;
        unsigned entry;
 
@@ -1127,18 +1113,18 @@ start_tx (struct sk_buff *skb, struct net_device *dev)
 static int
 reset_tx (struct net_device *dev)
 {
-       struct netdev_private *np = dev->priv;
-       long ioaddr = dev->base_addr;
+       struct netdev_private *np = netdev_priv(dev);
+       void __iomem *ioaddr = np->base;
        struct sk_buff *skb;
        int i;
        int irq = in_interrupt();
        
        /* Reset tx logic, TxListPtr will be cleaned */
-       writew (TxDisable, ioaddr + MACCtrl1);
-       writew (TxReset | DMAReset | FIFOReset | NetworkReset,
+       iowrite16 (TxDisable, ioaddr + MACCtrl1);
+       iowrite16 (TxReset | DMAReset | FIFOReset | NetworkReset,
                        ioaddr + ASICCtrl + 2);
        for (i=50; i > 0; i--) {
-               if ((readw(ioaddr + ASICCtrl + 2) & ResetBusy) == 0)
+               if ((ioread16(ioaddr + ASICCtrl + 2) & ResetBusy) == 0)
                        break;
                mdelay(1);
        }
@@ -1159,7 +1145,7 @@ reset_tx (struct net_device *dev)
        }
        np->cur_tx = np->dirty_tx = 0;
        np->cur_task = 0;
-       writew (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl1);
+       iowrite16 (StatsEnable | RxEnable | TxEnable, ioaddr + MACCtrl1);
        return 0;
 }
 
@@ -1168,19 +1154,17 @@ reset_tx (struct net_device *dev)
 static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
 {
        struct net_device *dev = (struct net_device *)dev_instance;
-       struct netdev_private *np;
-       long ioaddr;
+       struct netdev_private *np = netdev_priv(dev);
+       void __iomem *ioaddr = np->base;
        int hw_frame_id;
        int tx_cnt;
        int tx_status;
        int handled = 0;
 
-       ioaddr = dev->base_addr;
-       np = dev->priv;
 
        do {
-               int intr_status = readw(ioaddr + IntrStatus);
-               writew(intr_status, ioaddr + IntrStatus);
+               int intr_status = ioread16(ioaddr + IntrStatus);
+               iowrite16(intr_status, ioaddr + IntrStatus);
 
                if (netif_msg_intr(np))
                        printk(KERN_DEBUG "%s: Interrupt, status %4.4x.\n",
@@ -1192,14 +1176,14 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs
                handled = 1;
 
                if (intr_status & (IntrRxDMADone)) {
-                       writew(DEFAULT_INTR & ~(IntrRxDone|IntrRxDMADone),
+                       iowrite16(DEFAULT_INTR & ~(IntrRxDone|IntrRxDMADone),
                                        ioaddr + IntrEnable);
                        if (np->budget < 0)
                                np->budget = RX_BUDGET;
                        tasklet_schedule(&np->rx_tasklet);
                }
                if (intr_status & (IntrTxDone | IntrDrvRqst)) {
-                       tx_status = readw (ioaddr + TxStatus);
+                       tx_status = ioread16 (ioaddr + TxStatus);
                        for (tx_cnt=32; tx_status & 0x80; --tx_cnt) {
                                if (netif_msg_tx_done(np))
                                        printk
@@ -1221,18 +1205,18 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs
                                                spin_unlock(&np->lock);
                                        }
                                        if (tx_status & 0x1e)   /* Restart the Tx. */
-                                               writew (TxEnable,
+                                               iowrite16 (TxEnable,
                                                        ioaddr + MACCtrl1);
                                }
                                /* Yup, this is a documentation bug.  It cost me *hours*. */
-                               writew (0, ioaddr + TxStatus);
-                               tx_status = readw (ioaddr + TxStatus);
+                               iowrite16 (0, ioaddr + TxStatus);
+                               tx_status = ioread16 (ioaddr + TxStatus);
                                if (tx_cnt < 0)
                                        break;
                        }
                        hw_frame_id = (tx_status >> 8) & 0xff;
                } else  {
-                       hw_frame_id = readb(ioaddr + TxFrameId);
+                       hw_frame_id = ioread8(ioaddr + TxFrameId);
                }
                        
                if (np->pci_rev_id >= 0x14) {   
@@ -1293,18 +1277,18 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs
        } while (0);
        if (netif_msg_intr(np))
                printk(KERN_DEBUG "%s: exiting interrupt, status=%#4.4x.\n",
-                          dev->name, readw(ioaddr + IntrStatus));
-       writel(5000, ioaddr + DownCounter);
+                          dev->name, ioread16(ioaddr + IntrStatus));
+       iowrite32(5000, ioaddr + DownCounter);
        return IRQ_RETVAL(handled);
 }
 
 static void rx_poll(unsigned long data)
 {
        struct net_device *dev = (struct net_device *)data;
-       struct netdev_private *np = dev->priv;
+       struct netdev_private *np = netdev_priv(dev);
        int entry = np->cur_rx % RX_RING_SIZE;
        int boguscnt = np->budget;
-       long ioaddr = dev->base_addr;
+       void __iomem *ioaddr = np->base;
        int received = 0;
 
        /* If EOP is set on the next entry, it's a new packet. Send it up. */
@@ -1381,7 +1365,7 @@ static void rx_poll(unsigned long data)
        np->cur_rx = entry;
        refill_rx (dev);
        np->budget -= received;
-       writew(DEFAULT_INTR, ioaddr + IntrEnable);
+       iowrite16(DEFAULT_INTR, ioaddr + IntrEnable);
        return;
 
 not_done:
@@ -1398,7 +1382,7 @@ not_done:
 
 static void refill_rx (struct net_device *dev)
 {
-       struct netdev_private *np = dev->priv;
+       struct netdev_private *np = netdev_priv(dev);
        int entry;
        int cnt = 0;
 
@@ -1428,8 +1412,8 @@ static void refill_rx (struct net_device *dev)
 }
 static void netdev_error(struct net_device *dev, int intr_status)
 {
-       long ioaddr = dev->base_addr;
-       struct netdev_private *np = dev->priv;
+       struct netdev_private *np = netdev_priv(dev);
+       void __iomem *ioaddr = np->base;
        u16 mii_ctl, mii_advertise, mii_lpa;
        int speed;
 
@@ -1465,9 +1449,9 @@ static void netdev_error(struct net_device *dev, int intr_status)
                }
                check_duplex (dev);
                if (np->flowctrl && np->mii_if.full_duplex) {
-                       writew(readw(ioaddr + MulticastFilter1+2) | 0x0200,
+                       iowrite16(ioread16(ioaddr + MulticastFilter1+2) | 0x0200,
                                ioaddr + MulticastFilter1+2);
-                       writew(readw(ioaddr + MACCtrl0) | EnbFlowCtrl,
+                       iowrite16(ioread16(ioaddr + MACCtrl0) | EnbFlowCtrl,
                                ioaddr + MACCtrl0);
                }
        }
@@ -1483,36 +1467,36 @@ static void netdev_error(struct net_device *dev, int intr_status)
 
 static struct net_device_stats *get_stats(struct net_device *dev)
 {
-       struct netdev_private *np = dev->priv;
-       long ioaddr = dev->base_addr;
+       struct netdev_private *np = netdev_priv(dev);
+       void __iomem *ioaddr = np->base;
        int i;
 
        /* We should lock this segment of code for SMP eventually, although
           the vulnerability window is very small and statistics are
           non-critical. */
        /* The chip only need report frame silently dropped. */
-       np->stats.rx_missed_errors      += readb(ioaddr + RxMissed);
-       np->stats.tx_packets += readw(ioaddr + TxFramesOK);
-       np->stats.rx_packets += readw(ioaddr + RxFramesOK);
-       np->stats.collisions += readb(ioaddr + StatsLateColl);
-       np->stats.collisions += readb(ioaddr + StatsMultiColl);
-       np->stats.collisions += readb(ioaddr + StatsOneColl);
-       np->stats.tx_carrier_errors += readb(ioaddr + StatsCarrierError);
-       readb(ioaddr + StatsTxDefer);
+       np->stats.rx_missed_errors      += ioread8(ioaddr + RxMissed);
+       np->stats.tx_packets += ioread16(ioaddr + TxFramesOK);
+       np->stats.rx_packets += ioread16(ioaddr + RxFramesOK);
+       np->stats.collisions += ioread8(ioaddr + StatsLateColl);
+       np->stats.collisions += ioread8(ioaddr + StatsMultiColl);
+       np->stats.collisions += ioread8(ioaddr + StatsOneColl);
+       np->stats.tx_carrier_errors += ioread8(ioaddr + StatsCarrierError);
+       ioread8(ioaddr + StatsTxDefer);
        for (i = StatsTxDefer; i <= StatsMcastRx; i++)
-               readb(ioaddr + i);
-       np->stats.tx_bytes += readw(ioaddr + TxOctetsLow);
-       np->stats.tx_bytes += readw(ioaddr + TxOctetsHigh) << 16;
-       np->stats.rx_bytes += readw(ioaddr + RxOctetsLow);
-       np->stats.rx_bytes += readw(ioaddr + RxOctetsHigh) << 16;
+               ioread8(ioaddr + i);
+       np->stats.tx_bytes += ioread16(ioaddr + TxOctetsLow);
+       np->stats.tx_bytes += ioread16(ioaddr + TxOctetsHigh) << 16;
+       np->stats.rx_bytes += ioread16(ioaddr + RxOctetsLow);
+       np->stats.rx_bytes += ioread16(ioaddr + RxOctetsHigh) << 16;
 
        return &np->stats;
 }
 
 static void set_rx_mode(struct net_device *dev)
 {
-       long ioaddr = dev->base_addr;
-       struct netdev_private *np = dev->priv;
+       struct netdev_private *np = netdev_priv(dev);
+       void __iomem *ioaddr = np->base;
        u16 mc_filter[4];                       /* Multicast hash filter */
        u32 rx_mode;
        int i;
@@ -1542,129 +1526,113 @@ static void set_rx_mode(struct net_device *dev)
                }
                rx_mode = AcceptBroadcast | AcceptMultiHash | AcceptMyPhys;
        } else {
-               writeb(AcceptBroadcast | AcceptMyPhys, ioaddr + RxMode);
+               iowrite8(AcceptBroadcast | AcceptMyPhys, ioaddr + RxMode);
                return;
        }
        if (np->mii_if.full_duplex && np->flowctrl)
                mc_filter[3] |= 0x0200;
 
        for (i = 0; i < 4; i++)
-               writew(mc_filter[i], ioaddr + MulticastFilter0 + i*2);
-       writeb(rx_mode, ioaddr + RxMode);
+               iowrite16(mc_filter[i], ioaddr + MulticastFilter0 + i*2);
+       iowrite8(rx_mode, ioaddr + RxMode);
 }
 
 static int __set_mac_addr(struct net_device *dev)
 {
+       struct netdev_private *np = netdev_priv(dev);
        u16 addr16;
 
        addr16 = (dev->dev_addr[0] | (dev->dev_addr[1] << 8));
-       writew(addr16, dev->base_addr + StationAddr);
+       iowrite16(addr16, np->base + StationAddr);
        addr16 = (dev->dev_addr[2] | (dev->dev_addr[3] << 8));
-       writew(addr16, dev->base_addr + StationAddr+2);
+       iowrite16(addr16, np->base + StationAddr+2);
        addr16 = (dev->dev_addr[4] | (dev->dev_addr[5] << 8));
-       writew(addr16, dev->base_addr + StationAddr+4);
+       iowrite16(addr16, np->base + StationAddr+4);
        return 0;
 }
-       
 
-static int netdev_ethtool_ioctl(struct net_device *dev, void __user *useraddr)
+static int check_if_running(struct net_device *dev)
 {
-       struct netdev_private *np = dev->priv;
-       u32 ethcmd;
-
-       if (copy_from_user(&ethcmd, useraddr, sizeof(ethcmd)))
-               return -EFAULT;
-
-        switch (ethcmd) {
-               /* get constant driver settings/info */
-               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));
-                       memset(&info.fw_version, 0, sizeof(info.fw_version));
-                       if (copy_to_user(useraddr, &info, sizeof(info)))
-                               return -EFAULT;
-                       return 0;
-               }
+       if (!netif_running(dev))
+               return -EINVAL;
+       return 0;
+}
 
-               /* get media 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 media 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;
-               }
+static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+       struct netdev_private *np = netdev_priv(dev);
+       strcpy(info->driver, DRV_NAME);
+       strcpy(info->version, DRV_VERSION);
+       strcpy(info->bus_info, pci_name(np->pci_dev));
+}
 
-               /* restart autonegotiation */
-               case ETHTOOL_NWAY_RST: {
-                       return mii_nway_restart(&np->mii_if);
-               }
+static int get_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+       struct netdev_private *np = netdev_priv(dev);
+       spin_lock_irq(&np->lock);
+       mii_ethtool_gset(&np->mii_if, ecmd);
+       spin_unlock_irq(&np->lock);
+       return 0;
+}
 
-               /* 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;
-               }
+static int set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
+{
+       struct netdev_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;
+}
 
-               /* get message-level */
-               case ETHTOOL_GMSGLVL: {
-                       struct ethtool_value edata = {ETHTOOL_GMSGLVL};
-                       edata.data = np->msg_enable;
-                       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;
-                       np->msg_enable = edata.data;
-                       return 0;
-               }
+static int nway_reset(struct net_device *dev)
+{
+       struct netdev_private *np = netdev_priv(dev);
+       return mii_nway_restart(&np->mii_if);
+}
+
+static u32 get_link(struct net_device *dev)
+{
+       struct netdev_private *np = netdev_priv(dev);
+       return mii_link_ok(&np->mii_if);
+}
 
-               default:
-               return -EOPNOTSUPP;
+static u32 get_msglevel(struct net_device *dev)
+{
+       struct netdev_private *np = netdev_priv(dev);
+       return np->msg_enable;
+}
 
-        }
+static void set_msglevel(struct net_device *dev, u32 val)
+{
+       struct netdev_private *np = netdev_priv(dev);
+       np->msg_enable = val;
 }
 
+static struct ethtool_ops ethtool_ops = {
+       .begin = check_if_running,
+       .get_drvinfo = get_drvinfo,
+       .get_settings = get_settings,
+       .set_settings = set_settings,
+       .nway_reset = nway_reset,
+       .get_link = get_link,
+       .get_msglevel = get_msglevel,
+       .set_msglevel = set_msglevel,
+};
+
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-       struct netdev_private *np = dev->priv;
+       struct netdev_private *np = netdev_priv(dev);
+       void __iomem *ioaddr = np->base;
        int rc;
        int i;
-       long ioaddr = dev->base_addr;
 
        if (!netif_running(dev))
                return -EINVAL;
 
-       if (cmd == SIOCETHTOOL)
-               rc = netdev_ethtool_ioctl(dev, rq->ifr_data);
-
-       else {
-               spin_lock_irq(&np->lock);
-               rc = generic_mii_ioctl(&np->mii_if, if_mii(rq), cmd, NULL);
-               spin_unlock_irq(&np->lock);
-       }
+       spin_lock_irq(&np->lock);
+       rc = generic_mii_ioctl(&np->mii_if, if_mii(rq), cmd, NULL);
+       spin_unlock_irq(&np->lock);
        switch (cmd) {
                case SIOCDEVPRIVATE:
                for (i=0; i<TX_RING_SIZE; i++) {
@@ -1678,14 +1646,14 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                                le32_to_cpu(np->tx_ring[i].frag[0].length));
                }
                printk(KERN_DEBUG "TxListPtr=%08x netif_queue_stopped=%d\n", 
-                       readl(dev->base_addr + TxListPtr), 
+                       ioread32(np->base + TxListPtr), 
                        netif_queue_stopped(dev));
                printk(KERN_DEBUG "cur_tx=%d(%02x) dirty_tx=%d(%02x)\n", 
                        np->cur_tx, np->cur_tx % TX_RING_SIZE,
                        np->dirty_tx, np->dirty_tx % TX_RING_SIZE);
                printk(KERN_DEBUG "cur_rx=%d dirty_rx=%d\n", np->cur_rx, np->dirty_rx);
                printk(KERN_DEBUG "cur_task=%d\n", np->cur_task);
-               printk(KERN_DEBUG "TxStatus=%04x\n", readw(ioaddr + TxStatus));
+               printk(KERN_DEBUG "TxStatus=%04x\n", ioread16(ioaddr + TxStatus));
                        return 0;
        }
                                
@@ -1695,8 +1663,8 @@ static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 
 static int netdev_close(struct net_device *dev)
 {
-       long ioaddr = dev->base_addr;
-       struct netdev_private *np = dev->priv;
+       struct netdev_private *np = netdev_priv(dev);
+       void __iomem *ioaddr = np->base;
        struct sk_buff *skb;
        int i;
 
@@ -1705,17 +1673,17 @@ static int netdev_close(struct net_device *dev)
        if (netif_msg_ifdown(np)) {
                printk(KERN_DEBUG "%s: Shutting down ethercard, status was Tx %2.2x "
                           "Rx %4.4x Int %2.2x.\n",
-                          dev->name, readb(ioaddr + TxStatus),
-                          readl(ioaddr + RxStatus), readw(ioaddr + IntrStatus));
+                          dev->name, ioread8(ioaddr + TxStatus),
+                          ioread32(ioaddr + RxStatus), ioread16(ioaddr + IntrStatus));
                printk(KERN_DEBUG "%s: Queue pointers were Tx %d / %d,  Rx %d / %d.\n",
                           dev->name, np->cur_tx, np->dirty_tx, np->cur_rx, np->dirty_rx);
        }
 
        /* Disable interrupts by clearing the interrupt mask. */
-       writew(0x0000, ioaddr + IntrEnable);
+       iowrite16(0x0000, ioaddr + IntrEnable);
 
        /* Stop the chip's Tx and Rx processes. */
-       writew(TxDisable | RxDisable | StatsDisable, ioaddr + MACCtrl1);
+       iowrite16(TxDisable | RxDisable | StatsDisable, ioaddr + MACCtrl1);
 
        /* Wait and kill tasklet */
        tasklet_kill(&np->rx_tasklet);
@@ -1775,17 +1743,15 @@ static void __devexit sundance_remove1 (struct pci_dev *pdev)
        struct net_device *dev = pci_get_drvdata(pdev);
 
        if (dev) {
-               struct netdev_private *np = dev->priv;
+               struct netdev_private *np = netdev_priv(dev);
 
                unregister_netdev(dev);
                pci_free_consistent(pdev, RX_TOTAL_SIZE, np->rx_ring,
                        np->rx_ring_dma);
                pci_free_consistent(pdev, TX_TOTAL_SIZE, np->tx_ring,
                        np->tx_ring_dma);
+               pci_iounmap(pdev, np->base);
                pci_release_regions(pdev);
-#ifndef USE_IO_OPS
-               iounmap((char *)(dev->base_addr));
-#endif
                free_netdev(dev);
                pci_set_drvdata(pdev, NULL);
        }