fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / net / starfire.c
index 9b47edb..bf873ea 100644 (file)
@@ -2,7 +2,7 @@
 /*
        Written 1998-2000 by Donald Becker.
 
 /*
        Written 1998-2000 by Donald Becker.
 
-       Current maintainer is Ion Badulescu <ionut@cs.columbia.edu>. Please
+       Current maintainer is Ion Badulescu <ionut ta badula tod org>. Please
        send all bug reports to me, and not to Donald Becker, as this code
        has been heavily modified from Donald's original version.
 
        send all bug reports to me, and not to Donald Becker, as this code
        has been heavily modified from Donald's original version.
 
 
        Support and updates available at
        http://www.scyld.com/network/starfire.html
 
        Support and updates available at
        http://www.scyld.com/network/starfire.html
+       [link no longer provides useful info -jgarzik]
 
 
-       -----------------------------------------------------------
-
-       Linux kernel-specific changes:
-
-       LK1.1.1 (jgarzik):
-       - Use PCI driver interface
-       - Fix MOD_xxx races
-       - softnet fixups
-
-       LK1.1.2 (jgarzik):
-       - Merge Becker version 0.15
-
-       LK1.1.3 (Andrew Morton)
-       - Timer cleanups
-
-       LK1.1.4 (jgarzik):
-       - Merge Becker version 1.03
-
-       LK1.2.1 (Ion Badulescu <ionut@cs.columbia.edu>)
-       - Support hardware Rx/Tx checksumming
-       - Use the GFP firmware taken from Adaptec's Netware driver
-
-       LK1.2.2 (Ion Badulescu)
-       - Backported to 2.2.x
-
-       LK1.2.3 (Ion Badulescu)
-       - Fix the flaky mdio interface
-       - More compat clean-ups
-
-       LK1.2.4 (Ion Badulescu)
-       - More 2.2.x initialization fixes
-
-       LK1.2.5 (Ion Badulescu)
-       - Several fixes from Manfred Spraul
-
-       LK1.2.6 (Ion Badulescu)
-       - Fixed ifup/ifdown/ifup problem in 2.4.x
-
-       LK1.2.7 (Ion Badulescu)
-       - Removed unused code
-       - Made more functions static and __init
-
-       LK1.2.8 (Ion Badulescu)
-       - Quell bogus error messages, inform about the Tx threshold
-       - Removed #ifdef CONFIG_PCI, this driver is PCI only
-
-       LK1.2.9 (Ion Badulescu)
-       - Merged Jeff Garzik's changes from 2.4.4-pre5
-       - Added 2.2.x compatibility stuff required by the above changes
-
-       LK1.2.9a (Ion Badulescu)
-       - More updates from Jeff Garzik
-
-       LK1.3.0 (Ion Badulescu)
-       - Merged zerocopy support
-
-       LK1.3.1 (Ion Badulescu)
-       - Added ethtool support
-       - Added GPIO (media change) interrupt support
-
-       LK1.3.2 (Ion Badulescu)
-       - Fixed 2.2.x compatibility issues introduced in 1.3.1
-       - Fixed ethtool ioctl returning uninitialized memory
-
-       LK1.3.3 (Ion Badulescu)
-       - Initialize the TxMode register properly
-       - Don't dereference dev->priv after freeing it
-
-       LK1.3.4 (Ion Badulescu)
-       - Fixed initialization timing problems
-       - Fixed interrupt mask definitions
-
-       LK1.3.5 (jgarzik)
-       - ethtool NWAY_RST, GLINK, [GS]MSGLVL support
-
-       LK1.3.6:
-       - Sparc64 support and fixes (Ion Badulescu)
-       - Better stats and error handling (Ion Badulescu)
-       - Use new pci_set_mwi() PCI API function (jgarzik)
-
-       LK1.3.7 (Ion Badulescu)
-       - minimal implementation of tx_timeout()
-       - correctly shutdown the Rx/Tx engines in netdev_close()
-       - added calls to netif_carrier_on/off
-       (patch from Stefan Rompf <srompf@isg.de>)
-       - VLAN support
-
-       LK1.3.8 (Ion Badulescu)
-       - adjust DMA burst size on sparc64
-       - 64-bit support
-       - reworked zerocopy support for 64-bit buffers
-       - working and usable interrupt mitigation/latency
-       - reduced Tx interrupt frequency for lower interrupt overhead
-
-       LK1.3.9 (Ion Badulescu)
-       - bugfix for mcast filter
-       - enable the right kind of Tx interrupts (TxDMADone, not TxDone)
-
-       LK1.4.0 (Ion Badulescu)
-       - NAPI support
-
-       LK1.4.1 (Ion Badulescu)
-       - flush PCI posting buffers after disabling Rx interrupts
-       - put the chip to a D3 slumber on driver unload
-       - added config option to enable/disable NAPI
-
-TODO:  bugfixes (no bugs known as of right now)
 */
 
 #define DRV_NAME       "starfire"
 */
 
 #define DRV_NAME       "starfire"
-#define DRV_VERSION    "1.03+LK1.4.1"
-#define DRV_RELDATE    "February 10, 2002"
+#define DRV_VERSION    "2.0"
+#define DRV_RELDATE    "June 27, 2006"
 
 
-#include <linux/config.h>
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
@@ -145,40 +37,33 @@ TODO:      bugfixes (no bugs known as of right now)
 #include <linux/etherdevice.h>
 #include <linux/init.h>
 #include <linux/delay.h>
 #include <linux/etherdevice.h>
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/crc32.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/if_vlan.h>
+#include <linux/mm.h>
 #include <asm/processor.h>             /* Processor type for cache alignment. */
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
 #include <asm/processor.h>             /* Processor type for cache alignment. */
 #include <asm/uaccess.h>
 #include <asm/io.h>
 
-/*
- * Adaptec's license for their drivers (which is where I got the
- * firmware files) does not allow one to redistribute them. Thus, we can't
- * include the firmware with this driver.
- *
- * However, should a legal-to-distribute firmware become available,
- * the driver developer would need only to obtain the firmware in the
- * form of a C header file.
- * Once that's done, the #undef below must be changed into a #define
- * for this driver to really use the firmware. Note that Rx/Tx
- * hardware TCP checksumming is not possible without the firmware.
- *
- * WANTED: legal firmware to include with this GPL'd driver.
- */
-#undef HAS_FIRMWARE
+#include "starfire_firmware.h"
 /*
  * The current frame processor firmware fails to checksum a fragment
  * of length 1. If and when this is fixed, the #define below can be removed.
  */
 #define HAS_BROKEN_FIRMWARE
 /*
  * The current frame processor firmware fails to checksum a fragment
  * of length 1. If and when this is fixed, the #define below can be removed.
  */
 #define HAS_BROKEN_FIRMWARE
+
 /*
 /*
- * Define this if using the driver with the zero-copy patch
+ * If using the broken firmware, data must be padded to the next 32-bit boundary.
  */
  */
-#if defined(HAS_FIRMWARE) && defined(MAX_SKB_FRAGS)
-#define ZEROCOPY
+#ifdef HAS_BROKEN_FIRMWARE
+#define PADDING_MASK 3
 #endif
 
 #endif
 
-#ifdef HAS_FIRMWARE
-#include "starfire_firmware.h"
-#endif /* HAS_FIRMWARE */
+/*
+ * Define this if using the driver with the zero-copy patch
+ */
+#define ZEROCOPY
 
 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
 #define VLAN_SUPPORT
 
 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
 #define VLAN_SUPPORT
@@ -200,13 +85,9 @@ static int max_interrupt_work = 20;
 static int mtu;
 /* Maximum number of multicast addresses to filter (vs. rx-all-multicast).
    The Starfire has a 512 element hash table based on the Ethernet CRC. */
 static int mtu;
 /* Maximum number of multicast addresses to filter (vs. rx-all-multicast).
    The Starfire has a 512 element hash table based on the Ethernet CRC. */
-static int multicast_filter_limit = 512;
+static const int multicast_filter_limit = 512;
 /* Whether to do TCP/UDP checksums in hardware */
 /* Whether to do TCP/UDP checksums in hardware */
-#ifdef HAS_FIRMWARE
 static int enable_hw_cksum = 1;
 static int enable_hw_cksum = 1;
-#else
-static int enable_hw_cksum = 0;
-#endif
 
 #define PKT_BUF_SZ     1536            /* Size of each temporary Rx buffer.*/
 /*
 
 #define PKT_BUF_SZ     1536            /* Size of each temporary Rx buffer.*/
 /*
@@ -271,9 +152,10 @@ static int full_duplex[MAX_UNITS] = {0, };
  * This SUCKS.
  * We need a much better method to determine if dma_addr_t is 64-bit.
  */
  * This SUCKS.
  * We need a much better method to determine if dma_addr_t is 64-bit.
  */
-#if (defined(__i386__) && defined(CONFIG_HIGHMEM) && (LINUX_VERSION_CODE > 0x20500 || defined(CONFIG_HIGHMEM64G))) || defined(__x86_64__) || defined (__ia64__) || defined(__mips64__) || (defined(__mips__) && defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR))
+#if (defined(__i386__) && defined(CONFIG_HIGHMEM64G)) || defined(__x86_64__) || defined (__ia64__) || defined(__mips64__) || (defined(__mips__) && defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR))
 /* 64-bit dma_addr_t */
 #define ADDR_64BITS    /* This chip uses 64 bit addresses. */
 /* 64-bit dma_addr_t */
 #define ADDR_64BITS    /* This chip uses 64 bit addresses. */
+#define netdrv_addr_t u64
 #define cpu_to_dma(x) cpu_to_le64(x)
 #define dma_to_cpu(x) le64_to_cpu(x)
 #define RX_DESC_Q_ADDR_SIZE RxDescQAddr64bit
 #define cpu_to_dma(x) cpu_to_le64(x)
 #define dma_to_cpu(x) le64_to_cpu(x)
 #define RX_DESC_Q_ADDR_SIZE RxDescQAddr64bit
@@ -282,6 +164,7 @@ static int full_duplex[MAX_UNITS] = {0, };
 #define TX_COMPL_Q_ADDR_SIZE TxComplQAddr64bit
 #define RX_DESC_ADDR_SIZE RxDescAddr64bit
 #else  /* 32-bit dma_addr_t */
 #define TX_COMPL_Q_ADDR_SIZE TxComplQAddr64bit
 #define RX_DESC_ADDR_SIZE RxDescAddr64bit
 #else  /* 32-bit dma_addr_t */
+#define netdrv_addr_t u32
 #define cpu_to_dma(x) cpu_to_le32(x)
 #define dma_to_cpu(x) le32_to_cpu(x)
 #define RX_DESC_Q_ADDR_SIZE RxDescQAddr32bit
 #define cpu_to_dma(x) cpu_to_le32(x)
 #define dma_to_cpu(x) le32_to_cpu(x)
 #define RX_DESC_Q_ADDR_SIZE RxDescQAddr32bit
@@ -291,46 +174,15 @@ static int full_duplex[MAX_UNITS] = {0, };
 #define RX_DESC_ADDR_SIZE RxDescAddr32bit
 #endif
 
 #define RX_DESC_ADDR_SIZE RxDescAddr32bit
 #endif
 
-#ifdef MAX_SKB_FRAGS
 #define skb_first_frag_len(skb)        skb_headlen(skb)
 #define skb_num_frags(skb) (skb_shinfo(skb)->nr_frags + 1)
 #define skb_first_frag_len(skb)        skb_headlen(skb)
 #define skb_num_frags(skb) (skb_shinfo(skb)->nr_frags + 1)
-#else  /* not MAX_SKB_FRAGS */
-#define skb_first_frag_len(skb)        (skb->len)
-#define skb_num_frags(skb) 1
-#endif /* not MAX_SKB_FRAGS */
-
-/* 2.2.x compatibility code */
-#if LINUX_VERSION_CODE < 0x20300
-
-#include "starfire-kcomp22.h"
-
-#else  /* LINUX_VERSION_CODE > 0x20300 */
-
-#include <linux/crc32.h>
-#include <linux/ethtool.h>
-#include <linux/mii.h>
-
-#include <linux/if_vlan.h>
-
-#define COMPAT_MOD_INC_USE_COUNT
-#define COMPAT_MOD_DEC_USE_COUNT
-
-#define init_tx_timer(dev, func, timeout) \
-       dev->tx_timeout = func; \
-       dev->watchdog_timeo = timeout;
-#define kick_tx_timer(dev, func, timeout)
-
-#define netif_start_if(dev)
-#define netif_stop_if(dev)
-
-#define PCI_SLOT_NAME(pci_dev) pci_name(pci_dev)
-
-#endif /* LINUX_VERSION_CODE > 0x20300 */
 
 #ifdef HAVE_NETDEV_POLL
 #define init_poll(dev) \
 
 #ifdef HAVE_NETDEV_POLL
 #define init_poll(dev) \
+do { \
        dev->poll = &netdev_poll; \
        dev->poll = &netdev_poll; \
-       dev->weight = max_interrupt_work;
+       dev->weight = max_interrupt_work; \
+} while (0)
 #define netdev_rx(dev, ioaddr) \
 do { \
        u32 intr_enable; \
 #define netdev_rx(dev, ioaddr) \
 do { \
        u32 intr_enable; \
@@ -344,7 +196,7 @@ do { \
                /* Paranoia check */ \
                intr_enable = readl(ioaddr + IntrEnable); \
                if (intr_enable & (IntrRxDone | IntrRxEmpty)) { \
                /* Paranoia check */ \
                intr_enable = readl(ioaddr + IntrEnable); \
                if (intr_enable & (IntrRxDone | IntrRxEmpty)) { \
-                       printk("%s: interrupt while in polling mode!\n", dev->name); \
+                       printk(KERN_INFO "%s: interrupt while in polling mode!\n", dev->name); \
                        intr_enable &= ~(IntrRxDone | IntrRxEmpty); \
                        writel(intr_enable, ioaddr + IntrEnable); \
                } \
                        intr_enable &= ~(IntrRxDone | IntrRxEmpty); \
                        writel(intr_enable, ioaddr + IntrEnable); \
                } \
@@ -367,23 +219,24 @@ do { \
 
 
 /* These identify the driver base version and may not be removed. */
 
 
 /* These identify the driver base version and may not be removed. */
-static char version[] __devinitdata =
+static const char version[] __devinitdata =
 KERN_INFO "starfire.c:v1.03 7/26/2000  Written by Donald Becker <becker@scyld.com>\n"
 KERN_INFO " (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n";
 
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver");
 MODULE_LICENSE("GPL");
 KERN_INFO "starfire.c:v1.03 7/26/2000  Written by Donald Becker <becker@scyld.com>\n"
 KERN_INFO " (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELDATE ")\n";
 
 MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
 MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver");
 MODULE_LICENSE("GPL");
-
-MODULE_PARM(max_interrupt_work, "i");
-MODULE_PARM(mtu, "i");
-MODULE_PARM(debug, "i");
-MODULE_PARM(rx_copybreak, "i");
-MODULE_PARM(intr_latency, "i");
-MODULE_PARM(small_frames, "i");
-MODULE_PARM(options, "1-" __MODULE_STRING(MAX_UNITS) "i");
-MODULE_PARM(full_duplex, "1-" __MODULE_STRING(MAX_UNITS) "i");
-MODULE_PARM(enable_hw_cksum, "i");
+MODULE_VERSION(DRV_VERSION);
+
+module_param(max_interrupt_work, int, 0);
+module_param(mtu, int, 0);
+module_param(debug, int, 0);
+module_param(rx_copybreak, int, 0);
+module_param(intr_latency, int, 0);
+module_param(small_frames, int, 0);
+module_param_array(options, int, NULL, 0);
+module_param_array(full_duplex, int, NULL, 0);
+module_param(enable_hw_cksum, int, 0);
 MODULE_PARM_DESC(max_interrupt_work, "Maximum events handled per interrupt");
 MODULE_PARM_DESC(mtu, "MTU (all boards)");
 MODULE_PARM_DESC(debug, "Debug level (0-6)");
 MODULE_PARM_DESC(max_interrupt_work, "Maximum events handled per interrupt");
 MODULE_PARM_DESC(mtu, "MTU (all boards)");
 MODULE_PARM_DESC(debug, "Debug level (0-6)");
@@ -428,7 +281,7 @@ on the 32/64 bitness of the architecture), and relies on automatic
 minimum-length padding.  It does not use the completion queue
 consumer index, but instead checks for non-zero status entries.
 
 minimum-length padding.  It does not use the completion queue
 consumer index, but instead checks for non-zero status entries.
 
-For receive this driver uses type 0/1/2/3 receive descriptors.  The driver
+For receive this driver uses type 2/3 receive descriptors.  The driver
 allocates full frame size skbuffs for the Rx ring buffers, so all frames
 should fit in a single descriptor.  The driver does not use the completion
 queue consumer index, but instead checks for non-zero status entries.
 allocates full frame size skbuffs for the Rx ring buffers, so all frames
 should fit in a single descriptor.  The driver does not use the completion
 queue consumer index, but instead checks for non-zero status entries.
@@ -479,7 +332,7 @@ IVc. Errata
 
 */
 
 
 */
 
-\f
+
 
 enum chip_capability_flags {CanHaveMII=1, };
 
 
 enum chip_capability_flags {CanHaveMII=1, };
 
@@ -494,7 +347,7 @@ static struct pci_device_id starfire_pci_tbl[] = {
 MODULE_DEVICE_TABLE(pci, starfire_pci_tbl);
 
 /* A chip capabilities table, matching the CH_xxx entries in xxx_pci_tbl[] above. */
 MODULE_DEVICE_TABLE(pci, starfire_pci_tbl);
 
 /* A chip capabilities table, matching the CH_xxx entries in xxx_pci_tbl[] above. */
-static struct chip_info {
+static const struct chip_info {
        const char *name;
        int drv_flags;
 } netdrv_tbl[] __devinitdata = {
        const char *name;
        int drv_flags;
 } netdrv_tbl[] __devinitdata = {
@@ -673,7 +526,6 @@ struct full_rx_done_desc {
        u32 timestamp;
 };
 /* XXX: this is ugly and I'm not sure it's worth the trouble -Ion */
        u32 timestamp;
 };
 /* XXX: this is ugly and I'm not sure it's worth the trouble -Ion */
-#ifdef HAS_FIRMWARE
 #ifdef VLAN_SUPPORT
 typedef struct full_rx_done_desc rx_done_desc;
 #define RxComplType RxComplType3
 #ifdef VLAN_SUPPORT
 typedef struct full_rx_done_desc rx_done_desc;
 #define RxComplType RxComplType3
@@ -681,15 +533,6 @@ typedef struct full_rx_done_desc rx_done_desc;
 typedef struct csum_rx_done_desc rx_done_desc;
 #define RxComplType RxComplType2
 #endif /* not VLAN_SUPPORT */
 typedef struct csum_rx_done_desc rx_done_desc;
 #define RxComplType RxComplType2
 #endif /* not VLAN_SUPPORT */
-#else  /* not HAS_FIRMWARE */
-#ifdef VLAN_SUPPORT
-typedef struct basic_rx_done_desc rx_done_desc;
-#define RxComplType RxComplType1
-#else  /* not VLAN_SUPPORT */
-typedef struct short_rx_done_desc rx_done_desc;
-#define RxComplType RxComplType0
-#endif /* not VLAN_SUPPORT */
-#endif /* not HAS_FIRMWARE */
 
 enum rx_done_bits {
        RxOK=0x20000000, RxFIFOErr=0x10000000, RxBufQ2=0x08000000,
 
 enum rx_done_bits {
        RxOK=0x20000000, RxFIFOErr=0x10000000, RxBufQ2=0x08000000,
@@ -779,6 +622,7 @@ struct netdev_private {
        struct mii_if_info mii_if;              /* MII lib hooks/info */
        int phy_cnt;                    /* MII device addresses. */
        unsigned char phys[PHY_CNT];    /* MII device addresses. */
        struct mii_if_info mii_if;              /* MII lib hooks/info */
        int phy_cnt;                    /* MII device addresses. */
        unsigned char phys[PHY_CNT];    /* MII device addresses. */
+       void __iomem *base;
 };
 
 
 };
 
 
@@ -789,7 +633,7 @@ static void check_duplex(struct net_device *dev);
 static void    tx_timeout(struct net_device *dev);
 static void    init_ring(struct net_device *dev);
 static int     start_tx(struct sk_buff *skb, struct net_device *dev);
 static void    tx_timeout(struct net_device *dev);
 static void    init_ring(struct net_device *dev);
 static int     start_tx(struct sk_buff *skb, struct net_device *dev);
-static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *regs);
+static irqreturn_t intr_handler(int irq, void *dev_instance);
 static void    netdev_error(struct net_device *dev, int intr_status);
 static int     __netdev_rx(struct net_device *dev, int *quota);
 static void    refill_rx_ring(struct net_device *dev);
 static void    netdev_error(struct net_device *dev, int intr_status);
 static int     __netdev_rx(struct net_device *dev, int *quota);
 static void    refill_rx_ring(struct net_device *dev);
@@ -799,12 +643,13 @@ 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 void    netdev_media_change(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 void    netdev_media_change(struct net_device *dev);
+static const struct ethtool_ops ethtool_ops;
 
 
 #ifdef VLAN_SUPPORT
 static void netdev_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
 {
 
 
 #ifdef VLAN_SUPPORT
 static void netdev_vlan_rx_register(struct net_device *dev, struct vlan_group *grp)
 {
-        struct netdev_private *np = dev->priv;
+        struct netdev_private *np = netdev_priv(dev);
 
         spin_lock(&np->lock);
        if (debug > 2)
 
         spin_lock(&np->lock);
        if (debug > 2)
@@ -816,7 +661,7 @@ static void netdev_vlan_rx_register(struct net_device *dev, struct vlan_group *g
 
 static void netdev_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
 {
 
 static void netdev_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
 {
-       struct netdev_private *np = dev->priv;
+       struct netdev_private *np = netdev_priv(dev);
 
        spin_lock(&np->lock);
        if (debug > 1)
 
        spin_lock(&np->lock);
        if (debug > 1)
@@ -827,7 +672,7 @@ static void netdev_vlan_rx_add_vid(struct net_device *dev, unsigned short vid)
 
 static void netdev_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 {
 
 static void netdev_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 {
-       struct netdev_private *np = dev->priv;
+       struct netdev_private *np = netdev_priv(dev);
 
        spin_lock(&np->lock);
        if (debug > 1)
 
        spin_lock(&np->lock);
        if (debug > 1)
@@ -848,6 +693,7 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
        struct net_device *dev;
        static int card_idx = -1;
        long ioaddr;
        struct net_device *dev;
        static int card_idx = -1;
        long ioaddr;
+       void __iomem *base;
        int drv_flags, io_size;
        int boguscnt;
 
        int drv_flags, io_size;
        int boguscnt;
 
@@ -880,33 +726,27 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
 
        irq = pdev->irq;
 
 
        irq = pdev->irq;
 
-       if (pci_request_regions (pdev, dev->name)) {
+       if (pci_request_regions (pdev, DRV_NAME)) {
                printk(KERN_ERR DRV_NAME " %d: cannot reserve PCI resources, aborting\n", card_idx);
                goto err_out_free_netdev;
        }
 
                printk(KERN_ERR DRV_NAME " %d: cannot reserve PCI resources, aborting\n", card_idx);
                goto err_out_free_netdev;
        }
 
-       /* ioremap is borken in Linux-2.2.x/sparc64 */
-#if !defined(CONFIG_SPARC64) || LINUX_VERSION_CODE > 0x20300
-       ioaddr = (long) ioremap(ioaddr, io_size);
-       if (!ioaddr) {
+       base = ioremap(ioaddr, io_size);
+       if (!base) {
                printk(KERN_ERR DRV_NAME " %d: cannot remap %#x @ %#lx, aborting\n",
                        card_idx, io_size, ioaddr);
                goto err_out_free_res;
        }
                printk(KERN_ERR DRV_NAME " %d: cannot remap %#x @ %#lx, aborting\n",
                        card_idx, io_size, ioaddr);
                goto err_out_free_res;
        }
-#endif /* !CONFIG_SPARC64 || Linux 2.3.0+ */
 
        pci_set_master(pdev);
 
        /* enable MWI -- it vastly improves Rx performance on sparc64 */
        pci_set_mwi(pdev);
 
 
        pci_set_master(pdev);
 
        /* enable MWI -- it vastly improves Rx performance on sparc64 */
        pci_set_mwi(pdev);
 
-#ifdef MAX_SKB_FRAGS
-       dev->features |= NETIF_F_SG;
-#endif /* MAX_SKB_FRAGS */
 #ifdef ZEROCOPY
        /* Starfire can do TCP/UDP checksumming */
        if (enable_hw_cksum)
 #ifdef ZEROCOPY
        /* Starfire can do TCP/UDP checksumming */
        if (enable_hw_cksum)
-               dev->features |= NETIF_F_IP_CSUM;
+               dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
 #endif /* ZEROCOPY */
 #ifdef VLAN_SUPPORT
        dev->features |= NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER;
 #endif /* ZEROCOPY */
 #ifdef VLAN_SUPPORT
        dev->features |= NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER;
@@ -920,27 +760,27 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
 
        /* Serial EEPROM reads are hidden by the hardware. */
        for (i = 0; i < 6; i++)
 
        /* Serial EEPROM reads are hidden by the hardware. */
        for (i = 0; i < 6; i++)
-               dev->dev_addr[i] = readb(ioaddr + EEPROMCtrl + 20 - i);
+               dev->dev_addr[i] = readb(base + EEPROMCtrl + 20 - i);
 
 #if ! defined(final_version) /* Dump the EEPROM contents during development. */
        if (debug > 4)
                for (i = 0; i < 0x20; i++)
                        printk("%2.2x%s",
 
 #if ! defined(final_version) /* Dump the EEPROM contents during development. */
        if (debug > 4)
                for (i = 0; i < 0x20; i++)
                        printk("%2.2x%s",
-                              (unsigned int)readb(ioaddr + EEPROMCtrl + i),
+                              (unsigned int)readb(base + EEPROMCtrl + i),
                               i % 16 != 15 ? " " : "\n");
 #endif
 
        /* Issue soft reset */
                               i % 16 != 15 ? " " : "\n");
 #endif
 
        /* Issue soft reset */
-       writel(MiiSoftReset, ioaddr + TxMode);
+       writel(MiiSoftReset, base + TxMode);
        udelay(1000);
        udelay(1000);
-       writel(0, ioaddr + TxMode);
+       writel(0, base + TxMode);
 
        /* Reset the chip to erase previous misconfiguration. */
 
        /* Reset the chip to erase previous misconfiguration. */
-       writel(1, ioaddr + PCIDeviceConfig);
+       writel(1, base + PCIDeviceConfig);
        boguscnt = 1000;
        while (--boguscnt > 0) {
                udelay(10);
        boguscnt = 1000;
        while (--boguscnt > 0) {
                udelay(10);
-               if ((readl(ioaddr + PCIDeviceConfig) & 1) == 0)
+               if ((readl(base + PCIDeviceConfig) & 1) == 0)
                        break;
        }
        if (boguscnt == 0)
                        break;
        }
        if (boguscnt == 0)
@@ -948,10 +788,11 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
        /* wait a little longer */
        udelay(1000);
 
        /* wait a little longer */
        udelay(1000);
 
-       dev->base_addr = ioaddr;
+       dev->base_addr = (unsigned long)base;
        dev->irq = irq;
 
        dev->irq = irq;
 
-       np = dev->priv;
+       np = netdev_priv(dev);
+       np->base = base;
        spin_lock_init(&np->lock);
        pci_set_drvdata(pdev, dev);
 
        spin_lock_init(&np->lock);
        pci_set_drvdata(pdev, dev);
 
@@ -1009,12 +850,14 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
        /* The chip-specific entries in the device structure. */
        dev->open = &netdev_open;
        dev->hard_start_xmit = &start_tx;
        /* The chip-specific entries in the device structure. */
        dev->open = &netdev_open;
        dev->hard_start_xmit = &start_tx;
-       init_tx_timer(dev, tx_timeout, TX_TIMEOUT);
+       dev->tx_timeout = tx_timeout;
+       dev->watchdog_timeo = TX_TIMEOUT;
        init_poll(dev);
        dev->stop = &netdev_close;
        dev->get_stats = &get_stats;
        dev->set_multicast_list = &set_rx_mode;
        dev->do_ioctl = &netdev_ioctl;
        init_poll(dev);
        dev->stop = &netdev_close;
        dev->get_stats = &get_stats;
        dev->set_multicast_list = &set_rx_mode;
        dev->do_ioctl = &netdev_ioctl;
+       SET_ETHTOOL_OPS(dev, &ethtool_ops);
 
        if (mtu)
                dev->mtu = mtu;
 
        if (mtu)
                dev->mtu = mtu;
@@ -1022,8 +865,8 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
        if (register_netdev(dev))
                goto err_out_cleardev;
 
        if (register_netdev(dev))
                goto err_out_cleardev;
 
-       printk(KERN_INFO "%s: %s at %#lx, ",
-                  dev->name, netdrv_tbl[chip_idx].name, ioaddr);
+       printk(KERN_INFO "%s: %s at %p, ",
+                  dev->name, netdrv_tbl[chip_idx].name, base);
        for (i = 0; i < 5; i++)
                printk("%2.2x:", dev->dev_addr[i]);
        printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq);
        for (i = 0; i < 5; i++)
                printk("%2.2x:", dev->dev_addr[i]);
        printk("%2.2x, IRQ %d.\n", dev->dev_addr[i], irq);
@@ -1039,7 +882,7 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
                                if ((mdio_read(dev, phy, MII_BMCR) & BMCR_RESET) == 0)
                                        break;
                        if (boguscnt == 0) {
                                if ((mdio_read(dev, phy, MII_BMCR) & BMCR_RESET) == 0)
                                        break;
                        if (boguscnt == 0) {
-                               printk("%s: PHY reset never completed!\n", dev->name);
+                               printk("%s: PHY#%d reset never completed!\n", dev->name, phy);
                                continue;
                        }
                        mii_status = mdio_read(dev, phy, MII_BMSR);
                                continue;
                        }
                        mii_status = mdio_read(dev, phy, MII_BMSR);
@@ -1066,7 +909,7 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
 
 err_out_cleardev:
        pci_set_drvdata(pdev, NULL);
 
 err_out_cleardev:
        pci_set_drvdata(pdev, NULL);
-       iounmap((void *)ioaddr);
+       iounmap(base);
 err_out_free_res:
        pci_release_regions (pdev);
 err_out_free_netdev:
 err_out_free_res:
        pci_release_regions (pdev);
 err_out_free_netdev:
@@ -1078,7 +921,8 @@ err_out_free_netdev:
 /* Read the MII Management Data I/O (MDIO) interfaces. */
 static int mdio_read(struct net_device *dev, int phy_id, int location)
 {
 /* Read the MII Management Data I/O (MDIO) interfaces. */
 static int mdio_read(struct net_device *dev, int phy_id, int location)
 {
-       long mdio_addr = dev->base_addr + MIICtrl + (phy_id<<7) + (location<<2);
+       struct netdev_private *np = netdev_priv(dev);
+       void __iomem *mdio_addr = np->base + MIICtrl + (phy_id<<7) + (location<<2);
        int result, boguscnt=1000;
        /* ??? Should we add a busy-wait here? */
        do
        int result, boguscnt=1000;
        /* ??? Should we add a busy-wait here? */
        do
@@ -1094,7 +938,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)
 {
 
 static void mdio_write(struct net_device *dev, int phy_id, int location, int value)
 {
-       long mdio_addr = dev->base_addr + MIICtrl + (phy_id<<7) + (location<<2);
+       struct netdev_private *np = netdev_priv(dev);
+       void __iomem *mdio_addr = np->base + MIICtrl + (phy_id<<7) + (location<<2);
        writel(value, mdio_addr);
        /* The busy-wait will occur before a read. */
 }
        writel(value, mdio_addr);
        /* The busy-wait will occur before a read. */
 }
@@ -1102,20 +947,16 @@ static void mdio_write(struct net_device *dev, int phy_id, int location, int val
 
 static int netdev_open(struct net_device *dev)
 {
 
 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, retval;
        size_t tx_done_q_size, rx_done_q_size, tx_ring_size, rx_ring_size;
 
        /* Do we ever need to reset the chip??? */
 
        int i, retval;
        size_t tx_done_q_size, rx_done_q_size, tx_ring_size, rx_ring_size;
 
        /* Do we ever need to reset the chip??? */
 
-       COMPAT_MOD_INC_USE_COUNT;
-
-       retval = request_irq(dev->irq, &intr_handler, SA_SHIRQ, dev->name, dev);
-       if (retval) {
-               COMPAT_MOD_DEC_USE_COUNT;
+       retval = request_irq(dev->irq, &intr_handler, IRQF_SHARED, dev->name, dev);
+       if (retval)
                return retval;
                return retval;
-       }
 
        /* Disable the Rx and Tx, and reset the chip. */
        writel(0, ioaddr + GenCtrl);
 
        /* Disable the Rx and Tx, and reset the chip. */
        writel(0, ioaddr + GenCtrl);
@@ -1132,8 +973,8 @@ static int netdev_open(struct net_device *dev)
                rx_ring_size = sizeof(struct starfire_rx_desc) * RX_RING_SIZE;
                np->queue_mem_size = tx_done_q_size + rx_done_q_size + tx_ring_size + rx_ring_size;
                np->queue_mem = pci_alloc_consistent(np->pci_dev, np->queue_mem_size, &np->queue_mem_dma);
                rx_ring_size = sizeof(struct starfire_rx_desc) * RX_RING_SIZE;
                np->queue_mem_size = tx_done_q_size + rx_done_q_size + tx_ring_size + rx_ring_size;
                np->queue_mem = pci_alloc_consistent(np->pci_dev, np->queue_mem_size, &np->queue_mem_dma);
-               if (np->queue_mem == 0) {
-                       COMPAT_MOD_DEC_USE_COUNT;
+               if (np->queue_mem == NULL) {
+                       free_irq(dev->irq, dev);
                        return -ENOMEM;
                }
 
                        return -ENOMEM;
                }
 
@@ -1199,7 +1040,7 @@ static int netdev_open(struct net_device *dev)
        writew(0, ioaddr + PerfFilterTable + 8);
        for (i = 1; i < 16; i++) {
                u16 *eaddrs = (u16 *)dev->dev_addr;
        writew(0, ioaddr + PerfFilterTable + 8);
        for (i = 1; i < 16; i++) {
                u16 *eaddrs = (u16 *)dev->dev_addr;
-               long setup_frm = ioaddr + PerfFilterTable + i * 16;
+               void __iomem *setup_frm = ioaddr + PerfFilterTable + i * 16;
                writew(cpu_to_be16(eaddrs[2]), setup_frm); setup_frm += 4;
                writew(cpu_to_be16(eaddrs[1]), setup_frm); setup_frm += 4;
                writew(cpu_to_be16(eaddrs[0]), setup_frm); setup_frm += 8;
                writew(cpu_to_be16(eaddrs[2]), setup_frm); setup_frm += 4;
                writew(cpu_to_be16(eaddrs[1]), setup_frm); setup_frm += 4;
                writew(cpu_to_be16(eaddrs[0]), setup_frm); setup_frm += 8;
@@ -1216,7 +1057,6 @@ static int netdev_open(struct net_device *dev)
 
        writel(np->intr_timer_ctrl, ioaddr + IntrTimerCtrl);
 
 
        writel(np->intr_timer_ctrl, ioaddr + IntrTimerCtrl);
 
-       netif_start_if(dev);
        netif_start_queue(dev);
 
        if (debug > 1)
        netif_start_queue(dev);
 
        if (debug > 1)
@@ -1243,13 +1083,11 @@ static int netdev_open(struct net_device *dev)
        writel(ETH_P_8021Q, ioaddr + VlanType);
 #endif /* VLAN_SUPPORT */
 
        writel(ETH_P_8021Q, ioaddr + VlanType);
 #endif /* VLAN_SUPPORT */
 
-#ifdef HAS_FIRMWARE
        /* Load Rx/Tx firmware into the frame processors */
        for (i = 0; i < FIRMWARE_RX_SIZE * 2; i++)
                writel(firmware_rx[i], ioaddr + RxGfpMem + i * 4);
        for (i = 0; i < FIRMWARE_TX_SIZE * 2; i++)
                writel(firmware_tx[i], ioaddr + TxGfpMem + i * 4);
        /* Load Rx/Tx firmware into the frame processors */
        for (i = 0; i < FIRMWARE_RX_SIZE * 2; i++)
                writel(firmware_rx[i], ioaddr + RxGfpMem + i * 4);
        for (i = 0; i < FIRMWARE_TX_SIZE * 2; i++)
                writel(firmware_tx[i], ioaddr + TxGfpMem + i * 4);
-#endif /* HAS_FIRMWARE */
        if (enable_hw_cksum)
                /* Enable the Rx and Tx units, and the Rx/Tx frame processors. */
                writel(TxEnable|TxGFPEnable|RxEnable|RxGFPEnable, ioaddr + GenCtrl);
        if (enable_hw_cksum)
                /* Enable the Rx and Tx units, and the Rx/Tx frame processors. */
                writel(TxEnable|TxGFPEnable|RxEnable|RxGFPEnable, ioaddr + GenCtrl);
@@ -1267,7 +1105,7 @@ static int netdev_open(struct net_device *dev)
 
 static void check_duplex(struct net_device *dev)
 {
 
 static void check_duplex(struct net_device *dev)
 {
-       struct netdev_private *np = dev->priv;
+       struct netdev_private *np = netdev_priv(dev);
        u16 reg0;
        int silly_count = 1000;
 
        u16 reg0;
        int silly_count = 1000;
 
@@ -1302,8 +1140,8 @@ static void check_duplex(struct net_device *dev)
 
 static void tx_timeout(struct net_device *dev)
 {
 
 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;
        int old_debug;
 
        printk(KERN_WARNING "%s: Transmit timed out, status %#8.8x, "
        int old_debug;
 
        printk(KERN_WARNING "%s: Transmit timed out, status %#8.8x, "
@@ -1332,7 +1170,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)
 {
 /* 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 = np->reap_tx = 0;
        int i;
 
        np->cur_rx = np->cur_tx = np->reap_tx = 0;
@@ -1346,12 +1184,12 @@ static void init_ring(struct net_device *dev)
                np->rx_info[i].skb = skb;
                if (skb == NULL)
                        break;
                np->rx_info[i].skb = skb;
                if (skb == NULL)
                        break;
-               np->rx_info[i].mapping = pci_map_single(np->pci_dev, skb->tail, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
+               np->rx_info[i].mapping = pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
                skb->dev = dev;                 /* Mark as being used by this device. */
                /* Grrr, we cannot offset to correctly align the IP header. */
                np->rx_ring[i].rxaddr = cpu_to_dma(np->rx_info[i].mapping | RxDescValid);
        }
                skb->dev = dev;                 /* Mark as being used by this device. */
                /* Grrr, we cannot offset to correctly align the IP header. */
                np->rx_ring[i].rxaddr = cpu_to_dma(np->rx_info[i].mapping | RxDescValid);
        }
-       writew(i - 1, dev->base_addr + RxDescQIdx);
+       writew(i - 1, np->base + RxDescQIdx);
        np->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
 
        /* Clear the remainder of the Rx buffer ring. */
        np->dirty_rx = (unsigned int)(i - RX_RING_SIZE);
 
        /* Clear the remainder of the Rx buffer ring. */
@@ -1378,13 +1216,11 @@ static void init_ring(struct net_device *dev)
 
 static int start_tx(struct sk_buff *skb, struct net_device *dev)
 {
 
 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);
        unsigned int entry;
        u32 status;
        int i;
 
        unsigned int entry;
        u32 status;
        int i;
 
-       kick_tx_timer(dev, tx_timeout, TX_TIMEOUT);
-
        /*
         * be cautious here, wrapping the queue has weird semantics
         * and we may not have enough slots even when it seems we do.
        /*
         * be cautious here, wrapping the queue has weird semantics
         * and we may not have enough slots even when it seems we do.
@@ -1395,21 +1231,9 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
        }
 
 #if defined(ZEROCOPY) && defined(HAS_BROKEN_FIRMWARE)
        }
 
 #if defined(ZEROCOPY) && defined(HAS_BROKEN_FIRMWARE)
-       {
-               int has_bad_length = 0;
-
-               if (skb_first_frag_len(skb) == 1)
-                       has_bad_length = 1;
-               else {
-                       for (i = 0; i < skb_shinfo(skb)->nr_frags; i++)
-                               if (skb_shinfo(skb)->frags[i].size == 1) {
-                                       has_bad_length = 1;
-                                       break;
-                               }
-               }
-
-               if (has_bad_length)
-                       skb_checksum_help(skb);
+       if (skb->ip_summed == CHECKSUM_PARTIAL) {
+               if (skb_padto(skb, (skb->len + PADDING_MASK) & ~PADDING_MASK))
+                       return NETDEV_TX_OK;
        }
 #endif /* ZEROCOPY && HAS_BROKEN_FIRMWARE */
 
        }
 #endif /* ZEROCOPY && HAS_BROKEN_FIRMWARE */
 
@@ -1429,7 +1253,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
                                status |= TxDescIntr;
                                np->reap_tx = 0;
                        }
                                status |= TxDescIntr;
                                np->reap_tx = 0;
                        }
-                       if (skb->ip_summed == CHECKSUM_HW) {
+                       if (skb->ip_summed == CHECKSUM_PARTIAL) {
                                status |= TxCalTCP;
                                np->stats.tx_compressed++;
                        }
                                status |= TxCalTCP;
                                np->stats.tx_compressed++;
                        }
@@ -1438,12 +1262,10 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
                        np->tx_info[entry].mapping =
                                pci_map_single(np->pci_dev, skb->data, skb_first_frag_len(skb), PCI_DMA_TODEVICE);
                } else {
                        np->tx_info[entry].mapping =
                                pci_map_single(np->pci_dev, skb->data, skb_first_frag_len(skb), PCI_DMA_TODEVICE);
                } else {
-#ifdef MAX_SKB_FRAGS
                        skb_frag_t *this_frag = &skb_shinfo(skb)->frags[i - 1];
                        status |= this_frag->size;
                        np->tx_info[entry].mapping =
                                pci_map_single(np->pci_dev, page_address(this_frag->page) + this_frag->page_offset, this_frag->size, PCI_DMA_TODEVICE);
                        skb_frag_t *this_frag = &skb_shinfo(skb)->frags[i - 1];
                        status |= this_frag->size;
                        np->tx_info[entry].mapping =
                                pci_map_single(np->pci_dev, page_address(this_frag->page) + this_frag->page_offset, this_frag->size, PCI_DMA_TODEVICE);
-#endif /* MAX_SKB_FRAGS */
                }
 
                np->tx_ring[entry].addr = cpu_to_dma(np->tx_info[entry].mapping);
                }
 
                np->tx_ring[entry].addr = cpu_to_dma(np->tx_info[entry].mapping);
@@ -1472,7 +1294,7 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
        wmb();
 
        /* Update the producer index. */
        wmb();
 
        /* Update the producer index. */
-       writel(entry * (sizeof(starfire_tx_desc) / 8), dev->base_addr + TxProducerIdx);
+       writel(entry * (sizeof(starfire_tx_desc) / 8), np->base + TxProducerIdx);
 
        /* 4 is arbitrary, but should be ok */
        if ((np->cur_tx - np->dirty_tx) + 4 > TX_RING_SIZE)
 
        /* 4 is arbitrary, but should be ok */
        if ((np->cur_tx - np->dirty_tx) + 4 > TX_RING_SIZE)
@@ -1486,19 +1308,16 @@ static int start_tx(struct sk_buff *skb, struct net_device *dev)
 
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
 
 /* The interrupt handler does all of the Rx thread work and cleans up
    after the Tx thread. */
-static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
+static irqreturn_t intr_handler(int irq, void *dev_instance)
 {
        struct net_device *dev = dev_instance;
 {
        struct net_device *dev = dev_instance;
-       struct netdev_private *np;
-       long ioaddr;
+       struct netdev_private *np = netdev_priv(dev);
+       void __iomem *ioaddr = np->base;
        int boguscnt = max_interrupt_work;
        int consumer;
        int tx_status;
        int handled = 0;
 
        int boguscnt = max_interrupt_work;
        int consumer;
        int tx_status;
        int handled = 0;
 
-       ioaddr = dev->base_addr;
-       np = dev->priv;
-
        do {
                u32 intr_status = readl(ioaddr + IntrClear);
 
        do {
                u32 intr_status = readl(ioaddr + IntrClear);
 
@@ -1539,7 +1358,6 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs
                                np->tx_info[entry].mapping = 0;
                                np->dirty_tx += np->tx_info[entry].used_slots;
                                entry = (entry + np->tx_info[entry].used_slots) % TX_RING_SIZE;
                                np->tx_info[entry].mapping = 0;
                                np->dirty_tx += np->tx_info[entry].used_slots;
                                entry = (entry + np->tx_info[entry].used_slots) % TX_RING_SIZE;
-#ifdef MAX_SKB_FRAGS
                                {
                                        int i;
                                        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
                                {
                                        int i;
                                        for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
@@ -1551,7 +1369,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs
                                                entry++;
                                        }
                                }
                                                entry++;
                                        }
                                }
-#endif /* MAX_SKB_FRAGS */
+
                                dev_kfree_skb_irq(skb);
                        }
                        np->tx_done_q[np->tx_done].status = 0;
                                dev_kfree_skb_irq(skb);
                        }
                        np->tx_done_q[np->tx_done].status = 0;
@@ -1597,7 +1415,7 @@ static irqreturn_t intr_handler(int irq, void *dev_instance, struct pt_regs *rgs
    for clarity, code sharing between NAPI/non-NAPI, and better register allocation. */
 static int __netdev_rx(struct net_device *dev, int *quota)
 {
    for clarity, code sharing between NAPI/non-NAPI, and better register allocation. */
 static int __netdev_rx(struct net_device *dev, int *quota)
 {
-       struct netdev_private *np = dev->priv;
+       struct netdev_private *np = netdev_priv(dev);
        u32 desc_status;
        int retcode = 0;
 
        u32 desc_status;
        int retcode = 0;
 
@@ -1611,7 +1429,7 @@ static int __netdev_rx(struct net_device *dev, int *quota)
                if (debug > 4)
                        printk(KERN_DEBUG "  netdev_rx() status of %d was %#8.8x.\n", np->rx_done, desc_status);
                if (!(desc_status & RxOK)) {
                if (debug > 4)
                        printk(KERN_DEBUG "  netdev_rx() status of %d was %#8.8x.\n", np->rx_done, desc_status);
                if (!(desc_status & RxOK)) {
-                       /* There was a error. */
+                       /* There was an error. */
                        if (debug > 2)
                                printk(KERN_DEBUG "  netdev_rx() Rx error was %#8.8x.\n", desc_status);
                        np->stats.rx_errors++;
                        if (debug > 2)
                                printk(KERN_DEBUG "  netdev_rx() Rx error was %#8.8x.\n", desc_status);
                        np->stats.rx_errors++;
@@ -1640,7 +1458,7 @@ static int __netdev_rx(struct net_device *dev, int *quota)
                        pci_dma_sync_single_for_cpu(np->pci_dev,
                                                    np->rx_info[entry].mapping,
                                                    pkt_len, PCI_DMA_FROMDEVICE);
                        pci_dma_sync_single_for_cpu(np->pci_dev,
                                                    np->rx_info[entry].mapping,
                                                    pkt_len, PCI_DMA_FROMDEVICE);
-                       eth_copy_and_sum(skb, np->rx_info[entry].skb->tail, pkt_len, 0);
+                       eth_copy_and_sum(skb, np->rx_info[entry].skb->data, pkt_len, 0);
                        pci_dma_sync_single_for_device(np->pci_dev,
                                                       np->rx_info[entry].mapping,
                                                       pkt_len, PCI_DMA_FROMDEVICE);
                        pci_dma_sync_single_for_device(np->pci_dev,
                                                       np->rx_info[entry].mapping,
                                                       pkt_len, PCI_DMA_FROMDEVICE);
@@ -1664,11 +1482,10 @@ static int __netdev_rx(struct net_device *dev, int *quota)
 #endif
 
                skb->protocol = eth_type_trans(skb, dev);
 #endif
 
                skb->protocol = eth_type_trans(skb, dev);
-#if defined(HAS_FIRMWARE) || defined(VLAN_SUPPORT)
+#ifdef VLAN_SUPPORT
                if (debug > 4)
                        printk(KERN_DEBUG "  netdev_rx() status2 of %d was %#4.4x.\n", np->rx_done, le16_to_cpu(desc->status2));
 #endif
                if (debug > 4)
                        printk(KERN_DEBUG "  netdev_rx() status2 of %d was %#4.4x.\n", np->rx_done, le16_to_cpu(desc->status2));
 #endif
-#ifdef HAS_FIRMWARE
                if (le16_to_cpu(desc->status2) & 0x0100) {
                        skb->ip_summed = CHECKSUM_UNNECESSARY;
                        np->stats.rx_compressed++;
                if (le16_to_cpu(desc->status2) & 0x0100) {
                        skb->ip_summed = CHECKSUM_UNNECESSARY;
                        np->stats.rx_compressed++;
@@ -1683,11 +1500,10 @@ static int __netdev_rx(struct net_device *dev, int *quota)
                 * Until then, the printk stays. :-) -Ion
                 */
                else if (le16_to_cpu(desc->status2) & 0x0040) {
                 * Until then, the printk stays. :-) -Ion
                 */
                else if (le16_to_cpu(desc->status2) & 0x0040) {
-                       skb->ip_summed = CHECKSUM_HW;
+                       skb->ip_summed = CHECKSUM_COMPLETE;
                        skb->csum = le16_to_cpu(desc->csum);
                        printk(KERN_DEBUG "%s: checksum_hw, status2 = %#x\n", dev->name, le16_to_cpu(desc->status2));
                }
                        skb->csum = le16_to_cpu(desc->csum);
                        printk(KERN_DEBUG "%s: checksum_hw, status2 = %#x\n", dev->name, le16_to_cpu(desc->status2));
                }
-#endif /* HAS_FIRMWARE */
 #ifdef VLAN_SUPPORT
                if (np->vlgrp && le16_to_cpu(desc->status2) & 0x0200) {
                        if (debug > 4)
 #ifdef VLAN_SUPPORT
                if (np->vlgrp && le16_to_cpu(desc->status2) & 0x0200) {
                        if (debug > 4)
@@ -1705,7 +1521,7 @@ static int __netdev_rx(struct net_device *dev, int *quota)
                desc->status = 0;
                np->rx_done = (np->rx_done + 1) % DONE_Q_SIZE;
        }
                desc->status = 0;
                np->rx_done = (np->rx_done + 1) % DONE_Q_SIZE;
        }
-       writew(np->rx_done, dev->base_addr + CompletionQConsumerIdx);
+       writew(np->rx_done, np->base + CompletionQConsumerIdx);
 
  out:
        refill_rx_ring(dev);
 
  out:
        refill_rx_ring(dev);
@@ -1720,7 +1536,8 @@ static int __netdev_rx(struct net_device *dev, int *quota)
 static int netdev_poll(struct net_device *dev, int *budget)
 {
        u32 intr_status;
 static int netdev_poll(struct net_device *dev, int *budget)
 {
        u32 intr_status;
-       long ioaddr = dev->base_addr;
+       struct netdev_private *np = netdev_priv(dev);
+       void __iomem *ioaddr = np->base;
        int retcode = 0, quota = dev->quota;
 
        do {
        int retcode = 0, quota = dev->quota;
 
        do {
@@ -1752,7 +1569,7 @@ static int netdev_poll(struct net_device *dev, int *budget)
 
 static void refill_rx_ring(struct net_device *dev)
 {
 
 static void refill_rx_ring(struct net_device *dev)
 {
-       struct netdev_private *np = dev->priv;
+       struct netdev_private *np = netdev_priv(dev);
        struct sk_buff *skb;
        int entry = -1;
 
        struct sk_buff *skb;
        int entry = -1;
 
@@ -1765,7 +1582,7 @@ static void refill_rx_ring(struct net_device *dev)
                        if (skb == NULL)
                                break;  /* Better luck next round. */
                        np->rx_info[entry].mapping =
                        if (skb == NULL)
                                break;  /* Better luck next round. */
                        np->rx_info[entry].mapping =
-                               pci_map_single(np->pci_dev, skb->tail, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
+                               pci_map_single(np->pci_dev, skb->data, np->rx_buf_sz, PCI_DMA_FROMDEVICE);
                        skb->dev = dev; /* Mark as being used by this device. */
                        np->rx_ring[entry].rxaddr =
                                cpu_to_dma(np->rx_info[entry].mapping | RxDescValid);
                        skb->dev = dev; /* Mark as being used by this device. */
                        np->rx_ring[entry].rxaddr =
                                cpu_to_dma(np->rx_info[entry].mapping | RxDescValid);
@@ -1774,14 +1591,14 @@ static void refill_rx_ring(struct net_device *dev)
                        np->rx_ring[entry].rxaddr |= cpu_to_dma(RxDescEndRing);
        }
        if (entry >= 0)
                        np->rx_ring[entry].rxaddr |= cpu_to_dma(RxDescEndRing);
        }
        if (entry >= 0)
-               writew(entry, dev->base_addr + RxDescQIdx);
+               writew(entry, np->base + RxDescQIdx);
 }
 
 
 static void netdev_media_change(struct net_device *dev)
 {
 }
 
 
 static void netdev_media_change(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;
        u16 reg0, reg1, reg4, reg5;
        u32 new_tx_mode;
        u32 new_intr_timer_ctrl;
        u16 reg0, reg1, reg4, reg5;
        u32 new_tx_mode;
        u32 new_intr_timer_ctrl;
@@ -1855,12 +1672,12 @@ static void netdev_media_change(struct net_device *dev)
 
 static void netdev_error(struct net_device *dev, int intr_status)
 {
 
 static void netdev_error(struct net_device *dev, int intr_status)
 {
-       struct netdev_private *np = dev->priv;
+       struct netdev_private *np = netdev_priv(dev);
 
        /* Came close to underrunning the Tx FIFO, increase threshold. */
        if (intr_status & IntrTxDataLow) {
                if (np->tx_threshold <= PKT_BUF_SZ / 16) {
 
        /* Came close to underrunning the Tx FIFO, increase threshold. */
        if (intr_status & IntrTxDataLow) {
                if (np->tx_threshold <= PKT_BUF_SZ / 16) {
-                       writel(++np->tx_threshold, dev->base_addr + TxThreshold);
+                       writel(++np->tx_threshold, np->base + TxThreshold);
                        printk(KERN_NOTICE "%s: PCI bus congestion, increasing Tx FIFO threshold to %d bytes\n",
                               dev->name, np->tx_threshold * 16);
                } else
                        printk(KERN_NOTICE "%s: PCI bus congestion, increasing Tx FIFO threshold to %d bytes\n",
                               dev->name, np->tx_threshold * 16);
                } else
@@ -1882,8 +1699,8 @@ static void netdev_error(struct net_device *dev, int intr_status)
 
 static struct net_device_stats *get_stats(struct net_device *dev)
 {
 
 static struct net_device_stats *get_stats(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;
 
        /* This adapter architecture needs no SMP locks. */
        np->stats.tx_bytes = readl(ioaddr + 0x57010);
 
        /* This adapter architecture needs no SMP locks. */
        np->stats.tx_bytes = readl(ioaddr + 0x57010);
@@ -1907,22 +1724,19 @@ static struct net_device_stats *get_stats(struct net_device *dev)
 }
 
 
 }
 
 
-/* Chips may use the upper or lower CRC bits, and may reverse and/or invert
-   them.  Select the endian-ness that results in minimal calculations.
-*/
 static void set_rx_mode(struct net_device *dev)
 {
 static void set_rx_mode(struct net_device *dev)
 {
-       long ioaddr = dev->base_addr;
+       struct netdev_private *np = netdev_priv(dev);
+       void __iomem *ioaddr = np->base;
        u32 rx_mode = MinVLANPrio;
        struct dev_mc_list *mclist;
        int i;
 #ifdef VLAN_SUPPORT
        u32 rx_mode = MinVLANPrio;
        struct dev_mc_list *mclist;
        int i;
 #ifdef VLAN_SUPPORT
-       struct netdev_private *np = dev->priv;
 
        rx_mode |= VlanMode;
        if (np->vlgrp) {
                int vlan_count = 0;
 
        rx_mode |= VlanMode;
        if (np->vlgrp) {
                int vlan_count = 0;
-               long filter_addr = ioaddr + HashTable + 8;
+               void __iomem *filter_addr = ioaddr + HashTable + 8;
                for (i = 0; i < VLAN_VID_MASK; i++) {
                        if (np->vlgrp->vlan_devices[i]) {
                                if (vlan_count >= 32)
                for (i = 0; i < VLAN_VID_MASK; i++) {
                        if (np->vlgrp->vlan_devices[i]) {
                                if (vlan_count >= 32)
@@ -1951,7 +1765,7 @@ static void set_rx_mode(struct net_device *dev)
                rx_mode |= AcceptBroadcast|AcceptAllMulticast|PerfectFilter;
        } else if (dev->mc_count <= 14) {
                /* Use the 16 element perfect filter, skip first two entries. */
                rx_mode |= AcceptBroadcast|AcceptAllMulticast|PerfectFilter;
        } else if (dev->mc_count <= 14) {
                /* Use the 16 element perfect filter, skip first two entries. */
-               long filter_addr = ioaddr + PerfFilterTable + 2 * 16;
+               void __iomem *filter_addr = ioaddr + PerfFilterTable + 2 * 16;
                u16 *eaddrs;
                for (i = 2, mclist = dev->mc_list; mclist && i < dev->mc_count + 2;
                     i++, mclist = mclist->next) {
                u16 *eaddrs;
                for (i = 2, mclist = dev->mc_list; mclist && i < dev->mc_count + 2;
                     i++, mclist = mclist->next) {
@@ -1969,13 +1783,15 @@ static void set_rx_mode(struct net_device *dev)
                rx_mode |= AcceptBroadcast|PerfectFilter;
        } else {
                /* Must use a multicast hash table. */
                rx_mode |= AcceptBroadcast|PerfectFilter;
        } else {
                /* Must use a multicast hash table. */
-               long filter_addr;
+               void __iomem *filter_addr;
                u16 *eaddrs;
                u16 mc_filter[32] __attribute__ ((aligned(sizeof(long))));      /* Multicast hash filter */
 
                memset(mc_filter, 0, sizeof(mc_filter));
                for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
                     i++, mclist = mclist->next) {
                u16 *eaddrs;
                u16 mc_filter[32] __attribute__ ((aligned(sizeof(long))));      /* Multicast hash filter */
 
                memset(mc_filter, 0, sizeof(mc_filter));
                for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
                     i++, mclist = mclist->next) {
+                       /* The chip uses the upper 9 CRC bits
+                          as index into the hash table */
                        int bit_nr = ether_crc_le(ETH_ALEN, mclist->dmi_addr) >> 23;
                        __u32 *fptr = (__u32 *) &mc_filter[(bit_nr >> 4) & ~1];
 
                        int bit_nr = ether_crc_le(ETH_ALEN, mclist->dmi_addr) >> 23;
                        __u32 *fptr = (__u32 *) &mc_filter[(bit_nr >> 4) & ~1];
 
@@ -1996,118 +1812,100 @@ static void set_rx_mode(struct net_device *dev)
        writel(rx_mode, ioaddr + RxFilterMode);
 }
 
        writel(rx_mode, ioaddr + RxFilterMode);
 }
 
+static int check_if_running(struct net_device *dev)
+{
+       if (!netif_running(dev))
+               return -EINVAL;
+       return 0;
+}
 
 
-static int netdev_ethtool_ioctl(struct net_device *dev, void *useraddr)
+static void get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
 {
 {
-       struct ethtool_cmd ecmd;
-       struct netdev_private *np = dev->priv;
-
-       if (copy_from_user(&ecmd, useraddr, sizeof(ecmd)))
-               return -EFAULT;
-
-       switch (ecmd.cmd) {
-       case ETHTOOL_GDRVINFO: {
-               struct ethtool_drvinfo info;
-               memset(&info, 0, sizeof(info));
-               info.cmd = ecmd.cmd;
-               strcpy(info.driver, DRV_NAME);
-               strcpy(info.version, DRV_VERSION);
-               *info.fw_version = 0;
-               strcpy(info.bus_info, PCI_SLOT_NAME(np->pci_dev));
-               if (copy_to_user(useraddr, &info, sizeof(info)))
-                      return -EFAULT;
-               return 0;
-       }
+       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));
+}
 
 
-       /* get 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 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);
-               check_duplex(dev);
-               return r;
-       }
-       /* restart autonegotiation */
-       case ETHTOOL_NWAY_RST: {
-               return mii_nway_restart(&np->mii_if);
-       }
-       /* 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 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 message-level */
-       case ETHTOOL_GMSGLVL: {
-               struct ethtool_value edata = {ETHTOOL_GMSGLVL};
-               edata.data = debug;
-               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;
-               debug = edata.data;
-               return 0;
-       }
-       default:
-               return -EOPNOTSUPP;
-       }
+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);
+       check_duplex(dev);
+       return res;
 }
 
 }
 
+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);
+}
+
+static u32 get_msglevel(struct net_device *dev)
+{
+       return debug;
+}
+
+static void set_msglevel(struct net_device *dev, u32 val)
+{
+       debug = val;
+}
+
+static const 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)
 {
 
 static int netdev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-       struct netdev_private *np = dev->priv;
-       struct mii_ioctl_data *data = (struct mii_ioctl_data *) & rq->ifr_data;
+       struct netdev_private *np = netdev_priv(dev);
+       struct mii_ioctl_data *data = if_mii(rq);
        int rc;
 
        if (!netif_running(dev))
                return -EINVAL;
 
        int rc;
 
        if (!netif_running(dev))
                return -EINVAL;
 
-       if (cmd == SIOCETHTOOL)
-               rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);
-
-       else {
-               spin_lock_irq(&np->lock);
-               rc = generic_mii_ioctl(&np->mii_if, data, cmd, NULL);
-               spin_unlock_irq(&np->lock);
+       spin_lock_irq(&np->lock);
+       rc = generic_mii_ioctl(&np->mii_if, data, cmd, NULL);
+       spin_unlock_irq(&np->lock);
 
 
-               if ((cmd == SIOCSMIIREG) && (data->phy_id == np->phys[0]))
-                       check_duplex(dev);
-       }
+       if ((cmd == SIOCSMIIREG) && (data->phy_id == np->phys[0]))
+               check_duplex(dev);
 
        return rc;
 }
 
 static int netdev_close(struct net_device *dev)
 {
 
        return rc;
 }
 
 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;
        int i;
 
        netif_stop_queue(dev);
        int i;
 
        netif_stop_queue(dev);
-       netif_stop_if(dev);
 
        if (debug > 1) {
                printk(KERN_DEBUG "%s: Shutting down ethercard, Intr status %#8.8x.\n",
 
        if (debug > 1) {
                printk(KERN_DEBUG "%s: Shutting down ethercard, Intr status %#8.8x.\n",
@@ -2165,31 +1963,60 @@ static int netdev_close(struct net_device *dev)
                np->tx_info[i].skb = NULL;
        }
 
                np->tx_info[i].skb = NULL;
        }
 
-       COMPAT_MOD_DEC_USE_COUNT;
+       return 0;
+}
+
+#ifdef CONFIG_PM
+static int starfire_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       struct net_device *dev = pci_get_drvdata(pdev);
+
+       if (netif_running(dev)) {
+               netif_device_detach(dev);
+               netdev_close(dev);
+       }
+
+       pci_save_state(pdev);
+       pci_set_power_state(pdev, pci_choose_state(pdev,state));
 
        return 0;
 }
 
 
        return 0;
 }
 
+static int starfire_resume(struct pci_dev *pdev)
+{
+       struct net_device *dev = pci_get_drvdata(pdev);
+
+       pci_set_power_state(pdev, PCI_D0);
+       pci_restore_state(pdev);
+
+       if (netif_running(dev)) {
+               netdev_open(dev);
+               netif_device_attach(dev);
+       }
+
+       return 0;
+}
+#endif /* CONFIG_PM */
+
 
 static void __devexit starfire_remove_one (struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
 
 static void __devexit starfire_remove_one (struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
-       struct netdev_private *np;
+       struct netdev_private *np = netdev_priv(dev);
 
 
-       if (!dev)
-               BUG();
+       BUG_ON(!dev);
+
+       unregister_netdev(dev);
 
 
-       np = dev->priv;
        if (np->queue_mem)
                pci_free_consistent(pdev, np->queue_mem_size, np->queue_mem, np->queue_mem_dma);
 
        if (np->queue_mem)
                pci_free_consistent(pdev, np->queue_mem_size, np->queue_mem, np->queue_mem_dma);
 
-       unregister_netdev(dev);
 
        /* XXX: add wakeup code -- requires firmware for MagicPacket */
 
        /* XXX: add wakeup code -- requires firmware for MagicPacket */
-       pci_set_power_state(pdev, 3);   /* go to sleep in D3 mode */
+       pci_set_power_state(pdev, PCI_D3hot);   /* go to sleep in D3 mode */
        pci_disable_device(pdev);
 
        pci_disable_device(pdev);
 
-       iounmap((char *)dev->base_addr);
+       iounmap(np->base);
        pci_release_regions(pdev);
 
        pci_set_drvdata(pdev, NULL);
        pci_release_regions(pdev);
 
        pci_set_drvdata(pdev, NULL);
@@ -2201,6 +2028,10 @@ static struct pci_driver starfire_driver = {
        .name           = DRV_NAME,
        .probe          = starfire_init_one,
        .remove         = __devexit_p(starfire_remove_one),
        .name           = DRV_NAME,
        .probe          = starfire_init_one,
        .remove         = __devexit_p(starfire_remove_one),
+#ifdef CONFIG_PM
+       .suspend        = starfire_suspend,
+       .resume         = starfire_resume,
+#endif /* CONFIG_PM */
        .id_table       = starfire_pci_tbl,
 };
 
        .id_table       = starfire_pci_tbl,
 };
 
@@ -2210,19 +2041,20 @@ static int __init starfire_init (void)
 /* when a module, this is printed whether or not devices are found in probe */
 #ifdef MODULE
        printk(version);
 /* when a module, this is printed whether or not devices are found in probe */
 #ifdef MODULE
        printk(version);
+#ifdef HAVE_NETDEV_POLL
+       printk(KERN_INFO DRV_NAME ": polling (NAPI) enabled\n");
+#else
+       printk(KERN_INFO DRV_NAME ": polling (NAPI) disabled\n");
 #endif
 #endif
-#ifndef ADDR_64BITS
+#endif
+
        /* we can do this test only at run-time... sigh */
        /* we can do this test only at run-time... sigh */
-       if (sizeof(dma_addr_t) == sizeof(u64)) {
-               printk("This driver has not been ported to this 64-bit architecture yet\n");
+       if (sizeof(dma_addr_t) != sizeof(netdrv_addr_t)) {
+               printk("This driver has dma_addr_t issues, please send email to maintainer\n");
                return -ENODEV;
        }
                return -ENODEV;
        }
-#endif /* not ADDR_64BITS */
-#ifndef HAS_FIRMWARE
-       /* unconditionally disable hw cksums if firmware is not present */
-       enable_hw_cksum = 0;
-#endif /* not HAS_FIRMWARE */
-       return pci_module_init (&starfire_driver);
+
+       return pci_register_driver(&starfire_driver);
 }
 
 
 }