Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[linux-2.6.git] / drivers / net / defxx.c
index 5acd35c..6a6ea03 100644 (file)
  *
  * Abstract:
  *   A Linux device driver supporting the Digital Equipment Corporation
- *   FDDI EISA and PCI controller families.  Supported adapters include:
+ *   FDDI TURBOchannel, EISA and PCI controller families.  Supported
+ *   adapters include:
  *
- *             DEC FDDIcontroller/EISA (DEFEA)
- *             DEC FDDIcontroller/PCI  (DEFPA)
+ *             DEC FDDIcontroller/TURBOchannel (DEFTA)
+ *             DEC FDDIcontroller/EISA         (DEFEA)
+ *             DEC FDDIcontroller/PCI          (DEFPA)
  *
  * The original author:
  *   LVS       Lawrence V. Stefani <lstefani@yahoo.com>
  *             04 Aug 2003     macro           Converted to the DMA API.
  *             14 Aug 2004     macro           Fix device names reported.
  *             14 Jun 2005     macro           Use irqreturn_t.
+ *             23 Oct 2006     macro           Big-endian host support.
+ *             14 Dec 2006     macro           TURBOchannel support.
  */
 
 /* Include files */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
+#include <linux/bitops.h>
+#include <linux/compiler.h>
 #include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/eisa.h>
+#include <linux/errno.h>
+#include <linux/fddidevice.h>
 #include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/netdevice.h>
-#include <linux/fddidevice.h>
+#include <linux/pci.h>
 #include <linux/skbuff.h>
-#include <linux/bitops.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/tc.h>
 
 #include <asm/byteorder.h>
 #include <asm/io.h>
 
 /* Version information string should be updated prior to each new release!  */
 #define DRV_NAME "defxx"
-#define DRV_VERSION "v1.08"
-#define DRV_RELDATE "2005/06/14"
+#define DRV_VERSION "v1.10"
+#define DRV_RELDATE "2006/12/14"
 
 static char version[] __devinitdata =
        DRV_NAME ": " DRV_VERSION " " DRV_RELDATE
@@ -234,12 +241,39 @@ static char version[] __devinitdata =
  */
 #define NEW_SKB_SIZE (PI_RCV_DATA_K_SIZE_MAX+128)
 
+#ifdef CONFIG_PCI
+#define DFX_BUS_PCI(dev) (dev->bus == &pci_bus_type)
+#else
+#define DFX_BUS_PCI(dev) 0
+#endif
+
+#ifdef CONFIG_EISA
+#define DFX_BUS_EISA(dev) (dev->bus == &eisa_bus_type)
+#else
+#define DFX_BUS_EISA(dev) 0
+#endif
+
+#ifdef CONFIG_TC
+#define DFX_BUS_TC(dev) (dev->bus == &tc_bus_type)
+#else
+#define DFX_BUS_TC(dev) 0
+#endif
+
+#ifdef CONFIG_DEFXX_MMIO
+#define DFX_MMIO 1
+#else
+#define DFX_MMIO 0
+#endif
+
 /* Define module-wide (static) routines */
 
 static void            dfx_bus_init(struct net_device *dev);
+static void            dfx_bus_uninit(struct net_device *dev);
 static void            dfx_bus_config_check(DFX_board_t *bp);
 
-static int             dfx_driver_init(struct net_device *dev, const char *print_name);
+static int             dfx_driver_init(struct net_device *dev,
+                                       const char *print_name,
+                                       resource_size_t bar_start);
 static int             dfx_adap_init(DFX_board_t *bp, int get_buffers);
 
 static int             dfx_open(struct net_device *dev);
@@ -248,8 +282,7 @@ static int          dfx_close(struct net_device *dev);
 static void            dfx_int_pr_halt_id(DFX_board_t *bp);
 static void            dfx_int_type_0_process(DFX_board_t *bp);
 static void            dfx_int_common(struct net_device *dev);
-static irqreturn_t     dfx_interrupt(int irq, void *dev_id,
-                                     struct pt_regs *regs);
+static irqreturn_t     dfx_interrupt(int irq, void *dev_id);
 
 static struct          net_device_stats *dfx_ctl_get_stats(struct net_device *dev);
 static void            dfx_ctl_set_multicast_list(struct net_device *dev);
@@ -267,41 +300,41 @@ static int                dfx_rcv_init(DFX_board_t *bp, int get_buffers);
 static void            dfx_rcv_queue_process(DFX_board_t *bp);
 static void            dfx_rcv_flush(DFX_board_t *bp);
 
-static int             dfx_xmt_queue_pkt(struct sk_buff *skb, struct net_device *dev);
+static netdev_tx_t dfx_xmt_queue_pkt(struct sk_buff *skb,
+                                    struct net_device *dev);
 static int             dfx_xmt_done(DFX_board_t *bp);
 static void            dfx_xmt_flush(DFX_board_t *bp);
 
 /* Define module-wide (static) variables */
 
-static struct net_device *root_dfx_eisa_dev;
+static struct pci_driver dfx_pci_driver;
+static struct eisa_driver dfx_eisa_driver;
+static struct tc_driver dfx_tc_driver;
+
 
-\f
 /*
  * =======================
- * = dfx_port_write_byte =
- * = dfx_port_read_byte         =
  * = dfx_port_write_long =
  * = dfx_port_read_long  =
  * =======================
- *   
+ *
  * Overview:
  *   Routines for reading and writing values from/to adapter
- *  
+ *
  * Returns:
  *   None
- *       
+ *
  * Arguments:
- *   bp     - pointer to board information
- *   offset - register offset from base I/O address
- *   data   - for dfx_port_write_byte and dfx_port_write_long, this
- *                       is a value to write.
- *                       for dfx_port_read_byte and dfx_port_read_byte, this
- *                       is a pointer to store the read value.
+ *   bp                - pointer to board information
+ *   offset    - register offset from base I/O address
+ *   data      - for dfx_port_write_long, this is a value to write;
+ *               for dfx_port_read_long, this is a pointer to store
+ *               the read value
  *
  * Functional Description:
  *   These routines perform the correct operation to read or write
  *   the adapter register.
- *   
+ *
  *   EISA port block base addresses are based on the slot number in which the
  *   controller is installed.  For example, if the EISA controller is installed
  *   in slot 4, the port block base address is 0x4000.  If the controller is
@@ -310,7 +343,7 @@ static struct net_device *root_dfx_eisa_dev;
  *   registers using the register offsets defined in DEFXX.H.
  *
  *   PCI port block base addresses are assigned by the PCI BIOS or system
- *      firmware.  There is one 128 byte port block which can be accessed.  It
+ *   firmware.  There is one 128 byte port block which can be accessed.  It
  *   allows for I/O mapping of both PDQ and PFI registers using the register
  *   offsets defined in DEFXX.H.
  *
@@ -318,7 +351,7 @@ static struct net_device *root_dfx_eisa_dev;
  *   None
  *
  * Assumptions:
- *   bp->base_addr is a valid base I/O address for this adapter.
+ *   bp->base is a valid base I/O address for this adapter.
  *   offset is a valid register offset for this adapter.
  *
  * Side Effects:
@@ -329,69 +362,144 @@ static struct net_device *root_dfx_eisa_dev;
  *   advantage of strict data type checking.
  */
 
-static inline void dfx_port_write_byte(
-       DFX_board_t     *bp,
-       int                     offset,
-       u8                      data
-       )
+static inline void dfx_writel(DFX_board_t *bp, int offset, u32 data)
+{
+       writel(data, bp->base.mem + offset);
+       mb();
+}
 
-       {
-       u16 port = bp->base_addr + offset;
+static inline void dfx_outl(DFX_board_t *bp, int offset, u32 data)
+{
+       outl(data, bp->base.port + offset);
+}
 
-       outb(data, port);
-       }
+static void dfx_port_write_long(DFX_board_t *bp, int offset, u32 data)
+{
+       struct device __maybe_unused *bdev = bp->bus_dev;
+       int dfx_bus_tc = DFX_BUS_TC(bdev);
+       int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
 
-static inline void dfx_port_read_byte(
-       DFX_board_t     *bp,
-       int                     offset,
-       u8                      *data
-       )
+       if (dfx_use_mmio)
+               dfx_writel(bp, offset, data);
+       else
+               dfx_outl(bp, offset, data);
+}
 
-       {
-       u16 port = bp->base_addr + offset;
 
-       *data = inb(port);
-       }
+static inline void dfx_readl(DFX_board_t *bp, int offset, u32 *data)
+{
+       mb();
+       *data = readl(bp->base.mem + offset);
+}
 
-static inline void dfx_port_write_long(
-       DFX_board_t     *bp,
-       int                     offset,
-       u32                     data
-       )
+static inline void dfx_inl(DFX_board_t *bp, int offset, u32 *data)
+{
+       *data = inl(bp->base.port + offset);
+}
 
-       {
-       u16 port = bp->base_addr + offset;
+static void dfx_port_read_long(DFX_board_t *bp, int offset, u32 *data)
+{
+       struct device __maybe_unused *bdev = bp->bus_dev;
+       int dfx_bus_tc = DFX_BUS_TC(bdev);
+       int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
 
-       outl(data, port);
-       }
+       if (dfx_use_mmio)
+               dfx_readl(bp, offset, data);
+       else
+               dfx_inl(bp, offset, data);
+}
 
-static inline void dfx_port_read_long(
-       DFX_board_t     *bp,
-       int                     offset,
-       u32                     *data
-       )
 
-       {
-       u16 port = bp->base_addr + offset;
+/*
+ * ================
+ * = dfx_get_bars =
+ * ================
+ *
+ * Overview:
+ *   Retrieves the address range used to access control and status
+ *   registers.
+ *
+ * Returns:
+ *   None
+ *
+ * Arguments:
+ *   bdev      - pointer to device information
+ *   bar_start - pointer to store the start address
+ *   bar_len   - pointer to store the length of the area
+ *
+ * Assumptions:
+ *   I am sure there are some.
+ *
+ * Side Effects:
+ *   None
+ */
+static void dfx_get_bars(struct device *bdev,
+                        resource_size_t *bar_start, resource_size_t *bar_len)
+{
+       int dfx_bus_pci = DFX_BUS_PCI(bdev);
+       int dfx_bus_eisa = DFX_BUS_EISA(bdev);
+       int dfx_bus_tc = DFX_BUS_TC(bdev);
+       int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
+
+       if (dfx_bus_pci) {
+               int num = dfx_use_mmio ? 0 : 1;
 
-       *data = inl(port);
+               *bar_start = pci_resource_start(to_pci_dev(bdev), num);
+               *bar_len = pci_resource_len(to_pci_dev(bdev), num);
        }
+       if (dfx_bus_eisa) {
+               unsigned long base_addr = to_eisa_device(bdev)->base_addr;
+               resource_size_t bar;
+
+               if (dfx_use_mmio) {
+                       bar = inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_2);
+                       bar <<= 8;
+                       bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_1);
+                       bar <<= 8;
+                       bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_CMP_0);
+                       bar <<= 16;
+                       *bar_start = bar;
+                       bar = inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_2);
+                       bar <<= 8;
+                       bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_1);
+                       bar <<= 8;
+                       bar |= inb(base_addr + PI_ESIC_K_MEM_ADD_MASK_0);
+                       bar <<= 16;
+                       *bar_len = (bar | PI_MEM_ADD_MASK_M) + 1;
+               } else {
+                       *bar_start = base_addr;
+                       *bar_len = PI_ESIC_K_CSR_IO_LEN;
+               }
+       }
+       if (dfx_bus_tc) {
+               *bar_start = to_tc_dev(bdev)->resource.start +
+                            PI_TC_K_CSR_OFFSET;
+               *bar_len = PI_TC_K_CSR_LEN;
+       }
+}
+
+static const struct net_device_ops dfx_netdev_ops = {
+       .ndo_open               = dfx_open,
+       .ndo_stop               = dfx_close,
+       .ndo_start_xmit         = dfx_xmt_queue_pkt,
+       .ndo_get_stats          = dfx_ctl_get_stats,
+       .ndo_set_multicast_list = dfx_ctl_set_multicast_list,
+       .ndo_set_mac_address    = dfx_ctl_set_mac_address,
+};
 
-\f
 /*
- * =============
- * = dfx_init_one_pci_or_eisa =
- * =============
- *   
+ * ================
+ * = dfx_register =
+ * ================
+ *
  * Overview:
- *   Initializes a supported FDDI EISA or PCI controller
- *  
+ *   Initializes a supported FDDI controller
+ *
  * Returns:
  *   Condition code
- *       
+ *
  * Arguments:
- *   pdev - pointer to pci device information (NULL for EISA)
- *   ioaddr - pointer to port (NULL for PCI)
+ *   bdev - pointer to device information
  *
  * Functional Description:
  *
@@ -407,80 +515,82 @@ static inline void dfx_port_read_long(
  *   initialized and the board resources are read and stored in
  *   the device structure.
  */
-static int __devinit dfx_init_one_pci_or_eisa(struct pci_dev *pdev, long ioaddr)
+static int __devinit dfx_register(struct device *bdev)
 {
        static int version_disp;
-       char *print_name = DRV_NAME;
+       int dfx_bus_pci = DFX_BUS_PCI(bdev);
+       int dfx_bus_tc = DFX_BUS_TC(bdev);
+       int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
+       const char *print_name = dev_name(bdev);
        struct net_device *dev;
        DFX_board_t       *bp;                  /* board pointer */
+       resource_size_t bar_start = 0;          /* pointer to port */
+       resource_size_t bar_len = 0;            /* resource length */
        int alloc_size;                         /* total buffer size used */
-       int err;
+       struct resource *region;
+       int err = 0;
 
        if (!version_disp) {    /* display version info if adapter is found */
                version_disp = 1;       /* set display flag to TRUE so that */
                printk(version);        /* we only display this string ONCE */
        }
 
-       if (pdev != NULL)
-               print_name = pci_name(pdev);
-
        dev = alloc_fddidev(sizeof(*bp));
        if (!dev) {
-               printk(KERN_ERR "%s: unable to allocate fddidev, aborting\n",
+               printk(KERN_ERR "%s: Unable to allocate fddidev, aborting\n",
                       print_name);
                return -ENOMEM;
        }
 
        /* Enable PCI device. */
-       if (pdev != NULL) {
-               err = pci_enable_device (pdev);
-               if (err) goto err_out;
-               ioaddr = pci_resource_start (pdev, 1);
+       if (dfx_bus_pci && pci_enable_device(to_pci_dev(bdev))) {
+               printk(KERN_ERR "%s: Cannot enable PCI device, aborting\n",
+                      print_name);
+               goto err_out;
        }
 
-       SET_MODULE_OWNER(dev);
-       if (pdev != NULL)
-               SET_NETDEV_DEV(dev, &pdev->dev);
+       SET_NETDEV_DEV(dev, bdev);
+
+       bp = netdev_priv(dev);
+       bp->bus_dev = bdev;
+       dev_set_drvdata(bdev, dev);
 
-       bp = dev->priv;
+       dfx_get_bars(bdev, &bar_start, &bar_len);
 
-       if (!request_region(ioaddr,
-                           pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN,
-                           print_name)) {
+       if (dfx_use_mmio)
+               region = request_mem_region(bar_start, bar_len, print_name);
+       else
+               region = request_region(bar_start, bar_len, print_name);
+       if (!region) {
                printk(KERN_ERR "%s: Cannot reserve I/O resource "
-                      "0x%x @ 0x%lx, aborting\n", print_name,
-                      pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN, ioaddr);
+                      "0x%lx @ 0x%lx, aborting\n",
+                      print_name, (long)bar_len, (long)bar_start);
                err = -EBUSY;
-               goto err_out;
+               goto err_out_disable;
        }
 
-       /* Initialize new device structure */
-
-       dev->base_addr                  = ioaddr; /* save port (I/O) base address */
-
-       dev->get_stats                  = dfx_ctl_get_stats;
-       dev->open                       = dfx_open;
-       dev->stop                       = dfx_close;
-       dev->hard_start_xmit            = dfx_xmt_queue_pkt;
-       dev->set_multicast_list         = dfx_ctl_set_multicast_list;
-       dev->set_mac_address            = dfx_ctl_set_mac_address;
-
-       if (pdev == NULL) {
-               /* EISA board */
-               bp->bus_type = DFX_BUS_TYPE_EISA;
-               bp->next = root_dfx_eisa_dev;
-               root_dfx_eisa_dev = dev;
+       /* Set up I/O base address. */
+       if (dfx_use_mmio) {
+               bp->base.mem = ioremap_nocache(bar_start, bar_len);
+               if (!bp->base.mem) {
+                       printk(KERN_ERR "%s: Cannot map MMIO\n", print_name);
+                       err = -ENOMEM;
+                       goto err_out_region;
+               }
        } else {
-               /* PCI board */
-               bp->bus_type = DFX_BUS_TYPE_PCI;
-               bp->pci_dev = pdev;
-               pci_set_drvdata (pdev, dev);
-               pci_set_master (pdev);
+               bp->base.port = bar_start;
+               dev->base_addr = bar_start;
        }
 
-       if (dfx_driver_init(dev, print_name) != DFX_K_SUCCESS) {
+       /* Initialize new device structure */
+       dev->netdev_ops                 = &dfx_netdev_ops;
+
+       if (dfx_bus_pci)
+               pci_set_master(to_pci_dev(bdev));
+
+       if (dfx_driver_init(dev, print_name, bar_start) != DFX_K_SUCCESS) {
                err = -ENODEV;
-               goto err_out_region;
+               goto err_out_unmap;
        }
 
        err = register_netdev(dev);
@@ -499,56 +609,40 @@ err_out_kfree:
                     sizeof(PI_CONSUMER_BLOCK) +
                     (PI_ALIGN_K_DESC_BLK - 1);
        if (bp->kmalloced)
-               pci_free_consistent(pdev, alloc_size,
-                                   bp->kmalloced, bp->kmalloced_dma);
+               dma_free_coherent(bdev, alloc_size,
+                                 bp->kmalloced, bp->kmalloced_dma);
+
+err_out_unmap:
+       if (dfx_use_mmio)
+               iounmap(bp->base.mem);
+
 err_out_region:
-       release_region(ioaddr, pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN);
+       if (dfx_use_mmio)
+               release_mem_region(bar_start, bar_len);
+       else
+               release_region(bar_start, bar_len);
+
+err_out_disable:
+       if (dfx_bus_pci)
+               pci_disable_device(to_pci_dev(bdev));
+
 err_out:
        free_netdev(dev);
        return err;
 }
 
-static int __devinit dfx_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-       return dfx_init_one_pci_or_eisa(pdev, 0);
-}
-
-static int __init dfx_eisa_init(void)
-{
-       int rc = -ENODEV;
-       int i;                  /* used in for loops */
-       u16 port;               /* temporary I/O (port) address */
-       u32 slot_id;            /* EISA hardware (slot) ID read from adapter */
-
-       DBG_printk("In dfx_eisa_init...\n");
-
-       /* Scan for FDDI EISA controllers */
-
-       for (i=0; i < DFX_MAX_EISA_SLOTS; i++)          /* only scan for up to 16 EISA slots */
-       {
-               port = (i << 12) + PI_ESIC_K_SLOT_ID;   /* port = I/O address for reading slot ID */
-               slot_id = inl(port);                                    /* read EISA HW (slot) ID */
-               if ((slot_id & 0xF0FFFFFF) == DEFEA_PRODUCT_ID)
-               {
-                       port = (i << 12);                                       /* recalc base addr */
 
-                       if (dfx_init_one_pci_or_eisa(NULL, port) == 0) rc = 0;
-               }
-       }
-       return rc;
-}
-\f
 /*
  * ================
  * = dfx_bus_init =
  * ================
- *   
+ *
  * Overview:
- *   Initializes EISA and PCI controller bus-specific logic.
- *  
+ *   Initializes the bus-specific controller logic.
+ *
  * Returns:
  *   None
- *       
+ *
  * Arguments:
  *   dev - pointer to device information
  *
@@ -560,7 +654,7 @@ static int __init dfx_eisa_init(void)
  *   None
  *
  * Assumptions:
- *   dev->base_addr has already been set with the proper
+ *   bp->base has already been set with the proper
  *      base I/O address for this device.
  *
  * Side Effects:
@@ -571,87 +665,103 @@ static int __init dfx_eisa_init(void)
 
 static void __devinit dfx_bus_init(struct net_device *dev)
 {
-       DFX_board_t *bp = dev->priv;
-       u8                      val;    /* used for I/O read/writes */
+       DFX_board_t *bp = netdev_priv(dev);
+       struct device *bdev = bp->bus_dev;
+       int dfx_bus_pci = DFX_BUS_PCI(bdev);
+       int dfx_bus_eisa = DFX_BUS_EISA(bdev);
+       int dfx_bus_tc = DFX_BUS_TC(bdev);
+       int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
+       u8 val;
 
        DBG_printk("In dfx_bus_init...\n");
 
-       /*
-        * Initialize base I/O address field in bp structure
-        *
-        * Note: bp->base_addr is the same as dev->base_addr.
-        *               It's useful because often we'll need to read
-        *               or write registers where we already have the
-        *               bp pointer instead of the dev pointer.  Having
-        *               the base address in the bp structure will
-        *               save a pointer dereference.
-        *
-        *               IMPORTANT!! This field must be defined before
-        *               any of the dfx_port_* inline functions are
-        *               called.
-        */
-
-       bp->base_addr = dev->base_addr;
-
-       /* And a pointer back to the net_device struct */
+       /* Initialize a pointer back to the net_device struct */
        bp->dev = dev;
 
        /* Initialize adapter based on bus type */
 
-       if (bp->bus_type == DFX_BUS_TYPE_EISA)
-               {
-               /* Get the interrupt level from the ESIC chip */
-
-               dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &val);
-               switch ((val & PI_CONFIG_STAT_0_M_IRQ) >> PI_CONFIG_STAT_0_V_IRQ)
-                       {
-                       case PI_CONFIG_STAT_0_IRQ_K_9:
-                               dev->irq = 9;
-                               break;
-
-                       case PI_CONFIG_STAT_0_IRQ_K_10:
-                               dev->irq = 10;
-                               break;
+       if (dfx_bus_tc)
+               dev->irq = to_tc_dev(bdev)->interrupt;
+       if (dfx_bus_eisa) {
+               unsigned long base_addr = to_eisa_device(bdev)->base_addr;
 
-                       case PI_CONFIG_STAT_0_IRQ_K_11:
-                               dev->irq = 11;
-                               break;
+               /* Get the interrupt level from the ESIC chip.  */
+               val = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);
+               val &= PI_CONFIG_STAT_0_M_IRQ;
+               val >>= PI_CONFIG_STAT_0_V_IRQ;
 
-                       case PI_CONFIG_STAT_0_IRQ_K_15:
-                               dev->irq = 15;
-                               break;
-                       }
-
-               /* Enable access to I/O on the board by writing 0x03 to Function Control Register */
+               switch (val) {
+               case PI_CONFIG_STAT_0_IRQ_K_9:
+                       dev->irq = 9;
+                       break;
 
-               dfx_port_write_byte(bp, PI_ESIC_K_FUNCTION_CNTRL, PI_ESIC_K_FUNCTION_CNTRL_IO_ENB);
+               case PI_CONFIG_STAT_0_IRQ_K_10:
+                       dev->irq = 10;
+                       break;
 
-               /* Set the I/O decode range of the board */
+               case PI_CONFIG_STAT_0_IRQ_K_11:
+                       dev->irq = 11;
+                       break;
 
-               val = ((dev->base_addr >> 12) << PI_IO_CMP_V_SLOT);
-               dfx_port_write_byte(bp, PI_ESIC_K_IO_CMP_0_1, val);
-               dfx_port_write_byte(bp, PI_ESIC_K_IO_CMP_1_1, val);
+               case PI_CONFIG_STAT_0_IRQ_K_15:
+                       dev->irq = 15;
+                       break;
+               }
 
-               /* Enable access to rest of module (including PDQ and packet memory) */
+               /*
+                * Enable memory decoding (MEMCS0) and/or port decoding
+                * (IOCS1/IOCS0) as appropriate in Function Control
+                * Register.  One of the port chip selects seems to be
+                * used for the Burst Holdoff register, but this bit of
+                * documentation is missing and as yet it has not been
+                * determined which of the two.  This is also the reason
+                * the size of the decoded port range is twice as large
+                * as one required by the PDQ.
+                */
 
-               dfx_port_write_byte(bp, PI_ESIC_K_SLOT_CNTRL, PI_SLOT_CNTRL_M_ENB);
+               /* Set the decode range of the board.  */
+               val = ((bp->base.port >> 12) << PI_IO_CMP_V_SLOT);
+               outb(base_addr + PI_ESIC_K_IO_ADD_CMP_0_1, val);
+               outb(base_addr + PI_ESIC_K_IO_ADD_CMP_0_0, 0);
+               outb(base_addr + PI_ESIC_K_IO_ADD_CMP_1_1, val);
+               outb(base_addr + PI_ESIC_K_IO_ADD_CMP_1_0, 0);
+               val = PI_ESIC_K_CSR_IO_LEN - 1;
+               outb(base_addr + PI_ESIC_K_IO_ADD_MASK_0_1, (val >> 8) & 0xff);
+               outb(base_addr + PI_ESIC_K_IO_ADD_MASK_0_0, val & 0xff);
+               outb(base_addr + PI_ESIC_K_IO_ADD_MASK_1_1, (val >> 8) & 0xff);
+               outb(base_addr + PI_ESIC_K_IO_ADD_MASK_1_0, val & 0xff);
+
+               /* Enable the decoders.  */
+               val = PI_FUNCTION_CNTRL_M_IOCS1 | PI_FUNCTION_CNTRL_M_IOCS0;
+               if (dfx_use_mmio)
+                       val |= PI_FUNCTION_CNTRL_M_MEMCS0;
+               outb(base_addr + PI_ESIC_K_FUNCTION_CNTRL, val);
 
                /*
-                * Map PDQ registers into I/O space.  This is done by clearing a bit
-                * in Burst Holdoff register.
+                * Enable access to the rest of the module
+                * (including PDQ and packet memory).
                 */
+               val = PI_SLOT_CNTRL_M_ENB;
+               outb(base_addr + PI_ESIC_K_SLOT_CNTRL, val);
 
-               dfx_port_read_byte(bp, PI_ESIC_K_BURST_HOLDOFF, &val);
-               dfx_port_write_byte(bp, PI_ESIC_K_BURST_HOLDOFF, (val & ~PI_BURST_HOLDOFF_M_MEM_MAP));
+               /*
+                * Map PDQ registers into memory or port space.  This is
+                * done with a bit in the Burst Holdoff register.
+                */
+               val = inb(base_addr + PI_DEFEA_K_BURST_HOLDOFF);
+               if (dfx_use_mmio)
+                       val |= PI_BURST_HOLDOFF_V_MEM_MAP;
+               else
+                       val &= ~PI_BURST_HOLDOFF_V_MEM_MAP;
+               outb(base_addr + PI_DEFEA_K_BURST_HOLDOFF, val);
 
                /* Enable interrupts at EISA bus interface chip (ESIC) */
-
-               dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &val);
-               dfx_port_write_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, (val | PI_CONFIG_STAT_0_M_INT_ENB));
-               }
-       else
-               {
-               struct pci_dev *pdev = bp->pci_dev;
+               val = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);
+               val |= PI_CONFIG_STAT_0_M_INT_ENB;
+               outb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0, val);
+       }
+       if (dfx_bus_pci) {
+               struct pci_dev *pdev = to_pci_dev(bdev);
 
                /* Get the interrupt level from the PCI Configuration Table */
 
@@ -660,31 +770,84 @@ static void __devinit dfx_bus_init(struct net_device *dev)
                /* Check Latency Timer and set if less than minimal */
 
                pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &val);
-               if (val < PFI_K_LAT_TIMER_MIN)  /* if less than min, override with default */
-                       {
+               if (val < PFI_K_LAT_TIMER_MIN) {
                        val = PFI_K_LAT_TIMER_DEF;
                        pci_write_config_byte(pdev, PCI_LATENCY_TIMER, val);
-                       }
+               }
 
                /* Enable interrupts at PCI bus interface chip (PFI) */
+               val = PFI_MODE_M_PDQ_INT_ENB | PFI_MODE_M_DMA_ENB;
+               dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL, val);
+       }
+}
 
-               dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL, (PFI_MODE_M_PDQ_INT_ENB | PFI_MODE_M_DMA_ENB));
-               }
+/*
+ * ==================
+ * = dfx_bus_uninit =
+ * ==================
+ *
+ * Overview:
+ *   Uninitializes the bus-specific controller logic.
+ *
+ * Returns:
+ *   None
+ *
+ * Arguments:
+ *   dev - pointer to device information
+ *
+ * Functional Description:
+ *   Perform bus-specific logic uninitialization.
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   bp->base has already been set with the proper
+ *      base I/O address for this device.
+ *
+ * Side Effects:
+ *   Interrupts are disabled at the adapter bus-specific logic.
+ */
+
+static void __devexit dfx_bus_uninit(struct net_device *dev)
+{
+       DFX_board_t *bp = netdev_priv(dev);
+       struct device *bdev = bp->bus_dev;
+       int dfx_bus_pci = DFX_BUS_PCI(bdev);
+       int dfx_bus_eisa = DFX_BUS_EISA(bdev);
+       u8 val;
+
+       DBG_printk("In dfx_bus_uninit...\n");
+
+       /* Uninitialize adapter based on bus type */
+
+       if (dfx_bus_eisa) {
+               unsigned long base_addr = to_eisa_device(bdev)->base_addr;
+
+               /* Disable interrupts at EISA bus interface chip (ESIC) */
+               val = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);
+               val &= ~PI_CONFIG_STAT_0_M_INT_ENB;
+               outb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0, val);
        }
+       if (dfx_bus_pci) {
+               /* Disable interrupts at PCI bus interface chip (PFI) */
+               dfx_port_write_long(bp, PFI_K_REG_MODE_CTRL, 0);
+       }
+}
+
 
-\f
 /*
  * ========================
  * = dfx_bus_config_check =
  * ========================
- *   
+ *
  * Overview:
  *   Checks the configuration (burst size, full-duplex, etc.)  If any parameters
  *   are illegal, then this routine will set new defaults.
- *  
+ *
  * Returns:
  *   None
- *       
+ *
  * Arguments:
  *   bp - pointer to board information
  *
@@ -705,18 +868,16 @@ static void __devinit dfx_bus_init(struct net_device *dev)
 
 static void __devinit dfx_bus_config_check(DFX_board_t *bp)
 {
+       struct device __maybe_unused *bdev = bp->bus_dev;
+       int dfx_bus_eisa = DFX_BUS_EISA(bdev);
        int     status;                         /* return code from adapter port control call */
-       u32     slot_id;                        /* EISA-bus hardware id (DEC3001, DEC3002,...) */
        u32     host_data;                      /* LW data returned from port control call */
 
        DBG_printk("In dfx_bus_config_check...\n");
 
        /* Configuration check only valid for EISA adapter */
 
-       if (bp->bus_type == DFX_BUS_TYPE_EISA)
-               {
-               dfx_port_read_long(bp, PI_ESIC_K_SLOT_ID, &slot_id);
-
+       if (dfx_bus_eisa) {
                /*
                 * First check if revision 2 EISA controller.  Rev. 1 cards used
                 * PDQ revision B, so no workaround needed in this case.  Rev. 3
@@ -724,14 +885,11 @@ static void __devinit dfx_bus_config_check(DFX_board_t *bp)
                 * case, either.  Only Rev. 2 cards used either Rev. D or E
                 * chips, so we must verify the chip revision on Rev. 2 cards.
                 */
-
-               if (slot_id == DEFEA_PROD_ID_2)
-                       {
+               if (to_eisa_device(bdev)->id.driver_data == DEFEA_PROD_ID_2) {
                        /*
-                        * Revision 2 FDDI EISA controller found, so let's check PDQ
-                        * revision of adapter.
+                        * Revision 2 FDDI EISA controller found,
+                        * so let's check PDQ revision of adapter.
                         */
-
                        status = dfx_hw_port_ctrl_req(bp,
                                                                                        PI_PCTRL_M_SUB_CMD,
                                                                                        PI_SUB_CMD_K_PDQ_REV_GET,
@@ -766,19 +924,19 @@ static void __devinit dfx_bus_config_check(DFX_board_t *bp)
                }
        }
 
-\f
+
 /*
  * ===================
  * = dfx_driver_init =
  * ===================
- *   
+ *
  * Overview:
  *   Initializes remaining adapter board structure information
  *   and makes sure adapter is in a safe state prior to dfx_open().
- *  
+ *
  * Returns:
  *   Condition code
- *       
+ *
  * Arguments:
  *   dev - pointer to device information
  *   print_name - printable device name
@@ -805,13 +963,21 @@ static void __devinit dfx_bus_config_check(DFX_board_t *bp)
  */
 
 static int __devinit dfx_driver_init(struct net_device *dev,
-                                    const char *print_name)
+                                    const char *print_name,
+                                    resource_size_t bar_start)
 {
-       DFX_board_t *bp = dev->priv;
-       int                     alloc_size;                     /* total buffer size needed */
-       char            *top_v, *curr_v;        /* virtual addrs into memory block */
-       dma_addr_t              top_p, curr_p;          /* physical addrs into memory block */
-       u32                     data;                           /* host data register value */
+       DFX_board_t *bp = netdev_priv(dev);
+       struct device *bdev = bp->bus_dev;
+       int dfx_bus_pci = DFX_BUS_PCI(bdev);
+       int dfx_bus_eisa = DFX_BUS_EISA(bdev);
+       int dfx_bus_tc = DFX_BUS_TC(bdev);
+       int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
+       int alloc_size;                 /* total buffer size needed */
+       char *top_v, *curr_v;           /* virtual addrs into memory block */
+       dma_addr_t top_p, curr_p;       /* physical addrs into memory block */
+       u32 data;                       /* host data register value */
+       __le32 le32;
+       char *board_name = NULL;
 
        DBG_printk("In dfx_driver_init...\n");
 
@@ -860,7 +1026,8 @@ static int __devinit dfx_driver_init(struct net_device *dev,
                       print_name);
                return(DFX_K_FAILURE);
        }
-       memcpy(&bp->factory_mac_addr[0], &data, sizeof(u32));
+       le32 = cpu_to_le32(data);
+       memcpy(&bp->factory_mac_addr[0], &le32, sizeof(u32));
 
        if (dfx_hw_port_ctrl_req(bp, PI_PCTRL_M_MLA, PI_PDATA_A_MLA_K_HI, 0,
                                 &data) != DFX_K_SUCCESS) {
@@ -868,7 +1035,8 @@ static int __devinit dfx_driver_init(struct net_device *dev,
                       print_name);
                return(DFX_K_FAILURE);
        }
-       memcpy(&bp->factory_mac_addr[4], &data, sizeof(u16));
+       le32 = cpu_to_le32(data);
+       memcpy(&bp->factory_mac_addr[4], &le32, sizeof(u16));
 
        /*
         * Set current address to factory address
@@ -878,20 +1046,18 @@ static int __devinit dfx_driver_init(struct net_device *dev,
         */
 
        memcpy(dev->dev_addr, bp->factory_mac_addr, FDDI_K_ALEN);
-       if (bp->bus_type == DFX_BUS_TYPE_EISA)
-               printk("%s: DEFEA at I/O addr = 0x%lX, IRQ = %d, "
-                      "Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n",
-                      print_name, dev->base_addr, dev->irq,
-                      dev->dev_addr[0], dev->dev_addr[1],
-                      dev->dev_addr[2], dev->dev_addr[3],
-                      dev->dev_addr[4], dev->dev_addr[5]);
-       else
-               printk("%s: DEFPA at I/O addr = 0x%lX, IRQ = %d, "
-                      "Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n",
-                      print_name, dev->base_addr, dev->irq,
-                      dev->dev_addr[0], dev->dev_addr[1],
-                      dev->dev_addr[2], dev->dev_addr[3],
-                      dev->dev_addr[4], dev->dev_addr[5]);
+       if (dfx_bus_tc)
+               board_name = "DEFTA";
+       if (dfx_bus_eisa)
+               board_name = "DEFEA";
+       if (dfx_bus_pci)
+               board_name = "DEFPA";
+       pr_info("%s: %s at %saddr = 0x%llx, IRQ = %d, "
+               "Hardware addr = %02X-%02X-%02X-%02X-%02X-%02X\n",
+               print_name, board_name, dfx_use_mmio ? "" : "I/O ",
+               (long long)bar_start, dev->irq,
+               dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+               dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
 
        /*
         * Get memory for descriptor block, consumer block, and other buffers
@@ -906,8 +1072,9 @@ static int __devinit dfx_driver_init(struct net_device *dev,
 #endif
                                        sizeof(PI_CONSUMER_BLOCK) +
                                        (PI_ALIGN_K_DESC_BLK - 1);
-       bp->kmalloced = top_v = pci_alloc_consistent(bp->pci_dev, alloc_size,
-                                                    &bp->kmalloced_dma);
+       bp->kmalloced = top_v = dma_alloc_coherent(bp->bus_dev, alloc_size,
+                                                  &bp->kmalloced_dma,
+                                                  GFP_ATOMIC);
        if (top_v == NULL) {
                printk("%s: Could not allocate memory for host buffers "
                       "and structures!\n", print_name);
@@ -984,18 +1151,18 @@ static int __devinit dfx_driver_init(struct net_device *dev,
        return(DFX_K_SUCCESS);
 }
 
-\f
+
 /*
  * =================
  * = dfx_adap_init =
  * =================
- *   
+ *
  * Overview:
  *   Brings the adapter to the link avail/link unavailable state.
- *  
+ *
  * Returns:
  *   Condition code
- *       
+ *
  * Arguments:
  *   bp - pointer to board information
  *   get_buffers - non-zero if buffers to be allocated
@@ -1086,27 +1253,23 @@ static int dfx_adap_init(DFX_board_t *bp, int get_buffers)
                }
 
        /*
-        * Set base address of Descriptor Block and bring adapter to DMA_AVAILABLE state
+        * Set the base address of Descriptor Block and bring adapter
+        * to DMA_AVAILABLE state.
         *
-        * Note: We also set the literal and data swapping requirements in this
-        *           command.  Since this driver presently runs on Intel platforms
-        *               which are Little Endian, we'll tell the adapter to byte swap
-        *               data only.  This code will need to change when we support
-        *               Big Endian systems (eg. PowerPC).
+        * Note: We also set the literal and data swapping requirements
+        *       in this command.
         *
-        * Assumption: 32-bit physical address of descriptor block is 8Kbyte
-        *             aligned.  That is, bits 0-12 of the address must be zero.
+        * Assumption: 32-bit physical address of descriptor block
+        *       is 8Kbyte aligned.
         */
-
-       if (dfx_hw_port_ctrl_req(bp,
-                                                       PI_PCTRL_M_INIT,
-                                                       (u32) (bp->descr_block_phys | PI_PDATA_A_INIT_M_BSWAP_DATA),
-                                                       0,
-                                                       NULL) != DFX_K_SUCCESS)
-               {
-               printk("%s: Could not set descriptor block address!\n", bp->dev->name);
-               return(DFX_K_FAILURE);
-               }
+       if (dfx_hw_port_ctrl_req(bp, PI_PCTRL_M_INIT,
+                                (u32)(bp->descr_block_phys |
+                                      PI_PDATA_A_INIT_M_BSWAP_INIT),
+                                0, NULL) != DFX_K_SUCCESS) {
+               printk("%s: Could not set descriptor block address!\n",
+                      bp->dev->name);
+               return DFX_K_FAILURE;
+       }
 
        /* Set transmit flush timeout value */
 
@@ -1188,18 +1351,18 @@ static int dfx_adap_init(DFX_board_t *bp, int get_buffers)
        return(DFX_K_SUCCESS);
        }
 
-\f
+
 /*
  * ============
  * = dfx_open =
  * ============
- *   
+ *
  * Overview:
  *   Opens the adapter
- *  
+ *
  * Returns:
  *   Condition code
- *       
+ *
  * Arguments:
  *   dev - pointer to device information
  *
@@ -1221,14 +1384,15 @@ static int dfx_adap_init(DFX_board_t *bp, int get_buffers)
 
 static int dfx_open(struct net_device *dev)
 {
+       DFX_board_t *bp = netdev_priv(dev);
        int ret;
-       DFX_board_t     *bp = dev->priv;
 
        DBG_printk("In dfx_open...\n");
-       
+
        /* Register IRQ - support shared interrupts by passing device ptr */
 
-       ret = request_irq(dev->irq, dfx_interrupt, SA_SHIRQ, dev->name, dev);
+       ret = request_irq(dev->irq, dfx_interrupt, IRQF_SHARED, dev->name,
+                         dev);
        if (ret) {
                printk(KERN_ERR "%s: Requested IRQ %d is busy\n", dev->name, dev->irq);
                return ret;
@@ -1276,18 +1440,18 @@ static int dfx_open(struct net_device *dev)
        return(0);
 }
 
-\f
+
 /*
  * =============
  * = dfx_close =
  * =============
- *   
+ *
  * Overview:
  *   Closes the device/module.
- *  
+ *
  * Returns:
  *   Condition code
- *       
+ *
  * Arguments:
  *   dev - pointer to device information
  *
@@ -1311,7 +1475,7 @@ static int dfx_open(struct net_device *dev)
 
 static int dfx_close(struct net_device *dev)
 {
-       DFX_board_t     *bp = dev->priv;
+       DFX_board_t *bp = netdev_priv(dev);
 
        DBG_printk("In dfx_close...\n");
 
@@ -1360,26 +1524,26 @@ static int dfx_close(struct net_device *dev)
        /* Clear device structure flags */
 
        netif_stop_queue(dev);
-       
+
        /* Deregister (free) IRQ */
 
        free_irq(dev->irq, dev);
-       
+
        return(0);
 }
 
-\f
+
 /*
  * ======================
  * = dfx_int_pr_halt_id =
  * ======================
- *   
+ *
  * Overview:
  *   Displays halt id's in string form.
- *  
+ *
  * Returns:
  *   None
- *       
+ *
  * Arguments:
  *   bp - pointer to board information
  *
@@ -1452,18 +1616,18 @@ static void dfx_int_pr_halt_id(DFX_board_t      *bp)
                }
        }
 
-\f
+
 /*
  * ==========================
  * = dfx_int_type_0_process =
  * ==========================
- *   
+ *
  * Overview:
  *   Processes Type 0 interrupts.
- *  
+ *
  * Returns:
  *   None
- *       
+ *
  * Arguments:
  *   bp - pointer to board information
  *
@@ -1569,7 +1733,7 @@ static void dfx_int_type_0_process(DFX_board_t    *bp)
        /* Check for adapter state change */
 
        if (type_0_status & PI_TYPE_0_STAT_M_STATE_CHANGE)
-               {                     
+               {
                /* Get latest adapter state */
 
                state = dfx_hw_adap_state_rd(bp);       /* get adapter state */
@@ -1604,18 +1768,18 @@ static void dfx_int_type_0_process(DFX_board_t  *bp)
                }
        }
 
-\f
+
 /*
  * ==================
  * = dfx_int_common =
  * ==================
- *   
+ *
  * Overview:
  *   Interrupt service routine (ISR)
- *  
+ *
  * Returns:
  *   None
- *       
+ *
  * Arguments:
  *   bp - pointer to board information
  *
@@ -1647,7 +1811,7 @@ static void dfx_int_type_0_process(DFX_board_t    *bp)
 
 static void dfx_int_common(struct net_device *dev)
 {
-       DFX_board_t     *bp = dev->priv;
+       DFX_board_t *bp = netdev_priv(dev);
        PI_UINT32       port_status;            /* Port Status register */
 
        /* Process xmt interrupts - frequent case, so always call this routine */
@@ -1678,7 +1842,7 @@ static void dfx_int_common(struct net_device *dev)
                dfx_int_type_0_process(bp);     /* process Type 0 interrupts */
        }
 
-\f
+
 /*
  * =================
  * = dfx_interrupt =
@@ -1693,7 +1857,6 @@ static void dfx_int_common(struct net_device *dev)
  * Arguments:
  *   irq       - interrupt vector
  *   dev_id    - pointer to device information
- *      regs   - pointer to registers structure
  *
  * Functional Description:
  *   This routine calls the interrupt processing routine for this adapter.  It
@@ -1716,20 +1879,18 @@ static void dfx_int_common(struct net_device *dev)
  *   Interrupts are disabled, then reenabled at the adapter.
  */
 
-static irqreturn_t dfx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t dfx_interrupt(int irq, void *dev_id)
 {
-       struct net_device       *dev = dev_id;
-       DFX_board_t             *bp;    /* private board structure pointer */
-
-       /* Get board pointer only if device structure is valid */
-
-       bp = dev->priv;
-
-       /* See if we're already servicing an interrupt */
+       struct net_device *dev = dev_id;
+       DFX_board_t *bp = netdev_priv(dev);
+       struct device *bdev = bp->bus_dev;
+       int dfx_bus_pci = DFX_BUS_PCI(bdev);
+       int dfx_bus_eisa = DFX_BUS_EISA(bdev);
+       int dfx_bus_tc = DFX_BUS_TC(bdev);
 
        /* Service adapter interrupts */
 
-       if (bp->bus_type == DFX_BUS_TYPE_PCI) {
+       if (dfx_bus_pci) {
                u32 status;
 
                dfx_port_read_long(bp, PFI_K_REG_STATUS, &status);
@@ -1753,10 +1914,12 @@ static irqreturn_t dfx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
                                     PFI_MODE_M_DMA_ENB));
 
                spin_unlock(&bp->lock);
-       } else {
+       }
+       if (dfx_bus_eisa) {
+               unsigned long base_addr = to_eisa_device(bdev)->base_addr;
                u8 status;
 
-               dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &status);
+               status = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);
                if (!(status & PI_CONFIG_STAT_0_M_PEND))
                        return IRQ_NONE;
 
@@ -1764,15 +1927,35 @@ static irqreturn_t dfx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
                /* Disable interrupts at the ESIC */
                status &= ~PI_CONFIG_STAT_0_M_INT_ENB;
-               dfx_port_write_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, status);
+               outb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0, status);
 
                /* Call interrupt service routine for this adapter */
                dfx_int_common(dev);
 
                /* Reenable interrupts at the ESIC */
-               dfx_port_read_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, &status);
+               status = inb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0);
                status |= PI_CONFIG_STAT_0_M_INT_ENB;
-               dfx_port_write_byte(bp, PI_ESIC_K_IO_CONFIG_STAT_0, status);
+               outb(base_addr + PI_ESIC_K_IO_CONFIG_STAT_0, status);
+
+               spin_unlock(&bp->lock);
+       }
+       if (dfx_bus_tc) {
+               u32 status;
+
+               dfx_port_read_long(bp, PI_PDQ_K_REG_PORT_STATUS, &status);
+               if (!(status & (PI_PSTATUS_M_RCV_DATA_PENDING |
+                               PI_PSTATUS_M_XMT_DATA_PENDING |
+                               PI_PSTATUS_M_SMT_HOST_PENDING |
+                               PI_PSTATUS_M_UNSOL_PENDING |
+                               PI_PSTATUS_M_CMD_RSP_PENDING |
+                               PI_PSTATUS_M_CMD_REQ_PENDING |
+                               PI_PSTATUS_M_TYPE_0_PENDING)))
+                       return IRQ_NONE;
+
+               spin_lock(&bp->lock);
+
+               /* Call interrupt service routine for this adapter */
+               dfx_int_common(dev);
 
                spin_unlock(&bp->lock);
        }
@@ -1780,18 +1963,18 @@ static irqreturn_t dfx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        return IRQ_HANDLED;
 }
 
-\f
+
 /*
  * =====================
  * = dfx_ctl_get_stats =
  * =====================
- *   
+ *
  * Overview:
  *   Get statistics for FDDI adapter
- *  
+ *
  * Returns:
  *   Pointer to FDDI statistics structure
- *       
+ *
  * Arguments:
  *   dev - pointer to device information
  *
@@ -1826,7 +2009,7 @@ static irqreturn_t dfx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
 
 static struct net_device_stats *dfx_ctl_get_stats(struct net_device *dev)
        {
-       DFX_board_t     *bp = dev->priv;
+       DFX_board_t *bp = netdev_priv(dev);
 
        /* Fill the bp->stats structure with driver-maintained counters */
 
@@ -1967,19 +2150,19 @@ static struct net_device_stats *dfx_ctl_get_stats(struct net_device *dev)
        return((struct net_device_stats *) &bp->stats);
        }
 
-\f
+
 /*
  * ==============================
  * = dfx_ctl_set_multicast_list =
  * ==============================
- *   
+ *
  * Overview:
  *   Enable/Disable LLC frame promiscuous mode reception
  *   on the adapter and/or update multicast address table.
- *  
+ *
  * Returns:
  *   None
- *       
+ *
  * Arguments:
  *   dev - pointer to device information
  *
@@ -2012,8 +2195,8 @@ static struct net_device_stats *dfx_ctl_get_stats(struct net_device *dev)
  */
 
 static void dfx_ctl_set_multicast_list(struct net_device *dev)
-       {
-       DFX_board_t                     *bp = dev->priv;
+{
+       DFX_board_t *bp = netdev_priv(dev);
        int                                     i;                      /* used as index in for loop */
        struct dev_mc_list      *dmi;           /* ptr to multicast addr entry */
 
@@ -2088,19 +2271,19 @@ static void dfx_ctl_set_multicast_list(struct net_device *dev)
                }
        }
 
-\f
+
 /*
  * ===========================
  * = dfx_ctl_set_mac_address =
  * ===========================
- *   
+ *
  * Overview:
  *   Add node address override (unicast address) to adapter
  *   CAM and update dev_addr field in device table.
- *  
+ *
  * Returns:
  *   None
- *       
+ *
  * Arguments:
  *   dev  - pointer to device information
  *   addr - pointer to sockaddr structure containing unicast address to add
@@ -2127,8 +2310,8 @@ static void dfx_ctl_set_multicast_list(struct net_device *dev)
 
 static int dfx_ctl_set_mac_address(struct net_device *dev, void *addr)
        {
-       DFX_board_t             *bp = dev->priv;
        struct sockaddr *p_sockaddr = (struct sockaddr *)addr;
+       DFX_board_t *bp = netdev_priv(dev);
 
        /* Copy unicast address to driver-maintained structs and update count */
 
@@ -2178,7 +2361,7 @@ static int dfx_ctl_set_mac_address(struct net_device *dev, void *addr)
        return(0);                      /* always return zero */
        }
 
-\f
+
 /*
  * ======================
  * = dfx_ctl_update_cam =
@@ -2263,7 +2446,7 @@ static int dfx_ctl_update_cam(DFX_board_t *bp)
        return(DFX_K_SUCCESS);
        }
 
-\f
+
 /*
  * ==========================
  * = dfx_ctl_update_filters =
@@ -2272,10 +2455,10 @@ static int dfx_ctl_update_cam(DFX_board_t *bp)
  * Overview:
  *   Procedure to update adapter filters with desired
  *   filter settings.
- *  
+ *
  * Returns:
  *   Condition code
- *       
+ *
  * Arguments:
  *   bp - pointer to board information
  *
@@ -2329,18 +2512,18 @@ static int dfx_ctl_update_filters(DFX_board_t *bp)
        return(DFX_K_SUCCESS);
        }
 
-\f
+
 /*
  * ======================
  * = dfx_hw_dma_cmd_req =
  * ======================
- *   
+ *
  * Overview:
  *   Sends PDQ DMA command to adapter firmware
- *  
+ *
  * Returns:
  *   Condition code
- *       
+ *
  * Arguments:
  *   bp - pointer to board information
  *
@@ -2374,9 +2557,9 @@ static int dfx_hw_dma_cmd_req(DFX_board_t *bp)
        {
        int status;                     /* adapter status */
        int timeout_cnt;        /* used in for loops */
-       
+
        /* Make sure the adapter is in a state that we can issue the DMA command in */
-       
+
        status = dfx_hw_adap_state_rd(bp);
        if ((status == PI_STATE_K_RESET)                ||
                (status == PI_STATE_K_HALTED)           ||
@@ -2397,7 +2580,7 @@ static int dfx_hw_dma_cmd_req(DFX_board_t *bp)
        dfx_port_write_long(bp, PI_PDQ_K_REG_CMD_RSP_PROD, bp->cmd_rsp_reg.lword);
 
        /* Put request buffer on the command request queue */
-       
+
        bp->descr_block_virt->cmd_req[bp->cmd_req_reg.index.prod].long_0 = (u32) (PI_XMT_DESCR_M_SOP |
                        PI_XMT_DESCR_M_EOP | (PI_CMD_REQ_K_SIZE_MAX << PI_XMT_DESCR_V_SEG_LEN));
        bp->descr_block_virt->cmd_req[bp->cmd_req_reg.index.prod].long_1 = bp->cmd_req_phys;
@@ -2419,7 +2602,7 @@ static int dfx_hw_dma_cmd_req(DFX_board_t *bp)
                        break;
                udelay(100);                    /* wait for 100 microseconds */
                }
-       if (timeout_cnt == 0) 
+       if (timeout_cnt == 0)
                return(DFX_K_HW_TIMEOUT);
 
        /* Bump (and wrap) the completion index and write out to register */
@@ -2439,7 +2622,7 @@ static int dfx_hw_dma_cmd_req(DFX_board_t *bp)
                        break;
                udelay(100);                    /* wait for 100 microseconds */
                }
-       if (timeout_cnt == 0) 
+       if (timeout_cnt == 0)
                return(DFX_K_HW_TIMEOUT);
 
        /* Bump (and wrap) the completion index and write out to register */
@@ -2450,18 +2633,18 @@ static int dfx_hw_dma_cmd_req(DFX_board_t *bp)
        return(DFX_K_SUCCESS);
        }
 
-\f
+
 /*
  * ========================
  * = dfx_hw_port_ctrl_req =
  * ========================
- *   
+ *
  * Overview:
  *   Sends PDQ port control command to adapter firmware
- *  
+ *
  * Returns:
  *   Host data register value in host_data if ptr is not NULL
- *       
+ *
  * Arguments:
  *   bp                        - pointer to board information
  *      command        - port control command
@@ -2497,7 +2680,7 @@ static int dfx_hw_port_ctrl_req(
        int                     timeout_cnt;    /* used in for loops */
 
        /* Set Command Error bit in command longword */
-       
+
        port_cmd = (PI_UINT32) (command | PI_PCTRL_M_CMD_ERROR);
 
        /* Issue port command to the adapter */
@@ -2520,12 +2703,12 @@ static int dfx_hw_port_ctrl_req(
                        break;
                udelay(100);                    /* wait for 100 microseconds */
                }
-       if (timeout_cnt == 0) 
+       if (timeout_cnt == 0)
                return(DFX_K_HW_TIMEOUT);
 
        /*
-        * If the address of host_data is non-zero, assume caller has supplied a  
-        * non NULL pointer, and return the contents of the HOST_DATA register in 
+        * If the address of host_data is non-zero, assume caller has supplied a
+        * non NULL pointer, and return the contents of the HOST_DATA register in
         * it.
         */
 
@@ -2534,18 +2717,18 @@ static int dfx_hw_port_ctrl_req(
        return(DFX_K_SUCCESS);
        }
 
-\f
+
 /*
  * =====================
  * = dfx_hw_adap_reset =
  * =====================
- *   
+ *
  * Overview:
  *   Resets adapter
- *  
+ *
  * Returns:
  *   None
- *       
+ *
  * Arguments:
  *   bp   - pointer to board information
  *   type - type of reset to perform
@@ -2588,18 +2771,18 @@ static void dfx_hw_adap_reset(
        dfx_port_write_long(bp, PI_PDQ_K_REG_PORT_RESET, 0);
        }
 
-\f
+
 /*
  * ========================
  * = dfx_hw_adap_state_rd =
  * ========================
- *   
+ *
  * Overview:
  *   Returns current adapter state
- *  
+ *
  * Returns:
  *   Adapter state per PDQ Port Specification
- *       
+ *
  * Arguments:
  *   bp - pointer to board information
  *
@@ -2624,18 +2807,18 @@ static int dfx_hw_adap_state_rd(DFX_board_t *bp)
        return((port_status & PI_PSTATUS_M_STATE) >> PI_PSTATUS_V_STATE);
        }
 
-\f
+
 /*
  * =====================
  * = dfx_hw_dma_uninit =
  * =====================
- *   
+ *
  * Overview:
  *   Brings adapter to DMA_UNAVAILABLE state
- *  
+ *
  * Returns:
  *   Condition code
- *       
+ *
  * Arguments:
  *   bp   - pointer to board information
  *   type - type of reset to perform
@@ -2672,38 +2855,38 @@ static int dfx_hw_dma_uninit(DFX_board_t *bp, PI_UINT32 type)
                        break;
                udelay(100);                                    /* wait for 100 microseconds */
                }
-       if (timeout_cnt == 0) 
+       if (timeout_cnt == 0)
                return(DFX_K_HW_TIMEOUT);
        return(DFX_K_SUCCESS);
        }
-\f
+
 /*
  *     Align an sk_buff to a boundary power of 2
  *
  */
+
 static void my_skb_align(struct sk_buff *skb, int n)
 {
        unsigned long x = (unsigned long)skb->data;
        unsigned long v;
-       
+
        v = ALIGN(x, n);        /* Where we want to be */
-       
+
        skb_reserve(skb, v - x);
 }
 
-\f
+
 /*
  * ================
  * = dfx_rcv_init =
  * ================
- *   
+ *
  * Overview:
  *   Produces buffers to adapter LLC Host receive descriptor block
- *  
+ *
  * Returns:
  *   None
- *       
+ *
  * Arguments:
  *   bp - pointer to board information
  *   get_buffers - non-zero if buffers to be allocated
@@ -2755,7 +2938,7 @@ static int dfx_rcv_init(DFX_board_t *bp, int get_buffers)
        for (i = 0; i < (int)(bp->rcv_bufs_to_post); i++)
                for (j = 0; (i + j) < (int)PI_RCV_DATA_K_NUM_ENTRIES; j += bp->rcv_bufs_to_post)
                {
-                       struct sk_buff *newskb = __dev_alloc_skb(NEW_SKB_SIZE, GFP_NOIO);
+                       struct sk_buff *newskb = __netdev_alloc_skb(bp->dev, NEW_SKB_SIZE, GFP_NOIO);
                        if (!newskb)
                                return -ENOMEM;
                        bp->descr_block_virt->rcv_data[i+j].long_0 = (u32) (PI_RCV_DESCR_M_SOP |
@@ -2764,12 +2947,12 @@ static int dfx_rcv_init(DFX_board_t *bp, int get_buffers)
                         * align to 128 bytes for compatibility with
                         * the old EISA boards.
                         */
-                        
+
                        my_skb_align(newskb, 128);
                        bp->descr_block_virt->rcv_data[i + j].long_1 =
-                               (u32)pci_map_single(bp->pci_dev, newskb->data,
+                               (u32)dma_map_single(bp->bus_dev, newskb->data,
                                                    NEW_SKB_SIZE,
-                                                   PCI_DMA_FROMDEVICE);
+                                                   DMA_FROM_DEVICE);
                        /*
                         * p_rcv_buff_va is only used inside the
                         * kernel so we put the skb pointer here.
@@ -2795,18 +2978,18 @@ static int dfx_rcv_init(DFX_board_t *bp, int get_buffers)
        return 0;
        }
 
-\f
+
 /*
  * =========================
  * = dfx_rcv_queue_process =
  * =========================
- *   
+ *
  * Overview:
  *   Process received LLC frames.
- *  
+ *
  * Returns:
  *   None
- *       
+ *
  * Arguments:
  *   bp - pointer to board information
  *
@@ -2880,20 +3063,20 @@ static void dfx_rcv_queue_process(
                                        newskb = dev_alloc_skb(NEW_SKB_SIZE);
                                        if (newskb){
                                                rx_in_place = 1;
-                                               
+
                                                my_skb_align(newskb, 128);
                                                skb = (struct sk_buff *)bp->p_rcv_buff_va[entry];
-                                               pci_unmap_single(bp->pci_dev,
+                                               dma_unmap_single(bp->bus_dev,
                                                        bp->descr_block_virt->rcv_data[entry].long_1,
                                                        NEW_SKB_SIZE,
-                                                       PCI_DMA_FROMDEVICE);
+                                                       DMA_FROM_DEVICE);
                                                skb_reserve(skb, RCV_BUFF_K_PADDING);
                                                bp->p_rcv_buff_va[entry] = (char *)newskb;
                                                bp->descr_block_virt->rcv_data[entry].long_1 =
-                                                       (u32)pci_map_single(bp->pci_dev,
+                                                       (u32)dma_map_single(bp->bus_dev,
                                                                newskb->data,
                                                                NEW_SKB_SIZE,
-                                                               PCI_DMA_FROMDEVICE);
+                                                               DMA_FROM_DEVICE);
                                        } else
                                                skb = NULL;
                                } else
@@ -2912,19 +3095,18 @@ static void dfx_rcv_queue_process(
                                        {
                                                /* Receive buffer allocated, pass receive packet up */
 
-                                               memcpy(skb->data, p_buff + RCV_BUFF_K_PADDING, pkt_len+3);
+                                               skb_copy_to_linear_data(skb,
+                                                              p_buff + RCV_BUFF_K_PADDING,
+                                                              pkt_len + 3);
                                        }
-                                       
+
                                        skb_reserve(skb,3);             /* adjust data field so that it points to FC byte */
                                        skb_put(skb, pkt_len);          /* pass up packet length, NOT including CRC */
-                                       skb->dev = bp->dev;             /* pass up device pointer */
-
                                        skb->protocol = fddi_type_trans(skb, bp->dev);
                                        bp->rcv_total_bytes += skb->len;
                                        netif_rx(skb);
 
                                        /* Update the rcv counters */
-                                       bp->dev->last_rx = jiffies;
                                        bp->rcv_total_frames++;
                                        if (*(p_buff + RCV_BUFF_K_DA) & 0x01)
                                                bp->rcv_multicast_frames++;
@@ -2945,18 +3127,18 @@ static void dfx_rcv_queue_process(
                }
        }
 
-\f
+
 /*
  * =====================
  * = dfx_xmt_queue_pkt =
  * =====================
- *   
+ *
  * Overview:
  *   Queues packets for transmission
- *  
+ *
  * Returns:
  *   Condition code
- *       
+ *
  * Arguments:
  *   skb - pointer to sk_buff to queue for transmission
  *   dev - pointer to device information
@@ -3007,20 +3189,17 @@ static void dfx_rcv_queue_process(
  *   None
  */
 
-static int dfx_xmt_queue_pkt(
-       struct sk_buff  *skb,
-       struct net_device       *dev
-       )
-
+static netdev_tx_t dfx_xmt_queue_pkt(struct sk_buff *skb,
+                                    struct net_device *dev)
        {
-       DFX_board_t             *bp = dev->priv;
+       DFX_board_t             *bp = netdev_priv(dev);
        u8                      prod;                           /* local transmit producer index */
        PI_XMT_DESCR            *p_xmt_descr;           /* ptr to transmit descriptor block entry */
        XMT_DRIVER_DESCR        *p_xmt_drv_descr;       /* ptr to transmit driver descriptor */
        unsigned long           flags;
 
        netif_stop_queue(dev);
-       
+
        /*
         * Verify that incoming transmit request is OK
         *
@@ -3032,12 +3211,12 @@ static int dfx_xmt_queue_pkt(
 
        if (!IN_RANGE(skb->len, FDDI_K_LLC_ZLEN, FDDI_K_LLC_LEN))
        {
-               printk("%s: Invalid packet length - %u bytes\n", 
+               printk("%s: Invalid packet length - %u bytes\n",
                        dev->name, skb->len);
                bp->xmt_length_errors++;                /* bump error counter */
                netif_wake_queue(dev);
                dev_kfree_skb(skb);
-               return(0);                              /* return "success" */
+               return NETDEV_TX_OK;                    /* return "success" */
        }
        /*
         * See if adapter link is available, if not, free buffer
@@ -3060,12 +3239,12 @@ static int dfx_xmt_queue_pkt(
                        bp->xmt_discards++;                                     /* bump error counter */
                        dev_kfree_skb(skb);             /* free sk_buff now */
                        netif_wake_queue(dev);
-                       return(0);                                                      /* return "success" */
+                       return NETDEV_TX_OK;            /* return "success" */
                        }
                }
 
        spin_lock_irqsave(&bp->lock, flags);
-       
+
        /* Get the current producer and the next free xmt data descriptor */
 
        prod            = bp->rcv_xmt_reg.index.xmt_prod;
@@ -3119,8 +3298,8 @@ static int dfx_xmt_queue_pkt(
         */
 
        p_xmt_descr->long_0     = (u32) (PI_XMT_DESCR_M_SOP | PI_XMT_DESCR_M_EOP | ((skb->len) << PI_XMT_DESCR_V_SEG_LEN));
-       p_xmt_descr->long_1 = (u32)pci_map_single(bp->pci_dev, skb->data,
-                                                 skb->len, PCI_DMA_TODEVICE);
+       p_xmt_descr->long_1 = (u32)dma_map_single(bp->bus_dev, skb->data,
+                                                 skb->len, DMA_TO_DEVICE);
 
        /*
         * Verify that descriptor is actually available
@@ -3137,7 +3316,7 @@ static int dfx_xmt_queue_pkt(
        {
                skb_pull(skb,3);
                spin_unlock_irqrestore(&bp->lock, flags);
-               return(1);                      /* requeue packet for later */
+               return NETDEV_TX_BUSY;  /* requeue packet for later */
        }
 
        /*
@@ -3164,21 +3343,21 @@ static int dfx_xmt_queue_pkt(
        dfx_port_write_long(bp, PI_PDQ_K_REG_TYPE_2_PROD, bp->rcv_xmt_reg.lword);
        spin_unlock_irqrestore(&bp->lock, flags);
        netif_wake_queue(dev);
-       return(0);                                                      /* packet queued to adapter */
+       return NETDEV_TX_OK;    /* packet queued to adapter */
        }
 
-\f
+
 /*
  * ================
  * = dfx_xmt_done =
  * ================
- *   
+ *
  * Overview:
  *   Processes all frames that have been transmitted.
- *  
+ *
  * Returns:
  *   None
- *       
+ *
  * Arguments:
  *   bp - pointer to board information
  *
@@ -3223,10 +3402,10 @@ static int dfx_xmt_done(DFX_board_t *bp)
 
                /* Return skb to operating system */
                comp = bp->rcv_xmt_reg.index.xmt_comp;
-               pci_unmap_single(bp->pci_dev,
+               dma_unmap_single(bp->bus_dev,
                                 bp->descr_block_virt->xmt_data[comp].long_1,
                                 p_xmt_drv_descr->p_skb->len,
-                                PCI_DMA_TODEVICE);
+                                DMA_TO_DEVICE);
                dev_kfree_skb_irq(p_xmt_drv_descr->p_skb);
 
                /*
@@ -3246,18 +3425,18 @@ static int dfx_xmt_done(DFX_board_t *bp)
        return freed;
        }
 
-\f
+
 /*
  * =================
  * = dfx_rcv_flush =
  * =================
- *   
+ *
  * Overview:
  *   Remove all skb's in the receive ring.
- *  
+ *
  * Returns:
  *   None
- *       
+ *
  * Arguments:
  *   bp - pointer to board information
  *
@@ -3299,14 +3478,14 @@ static inline void dfx_rcv_flush( DFX_board_t *bp )
  * =================
  * = dfx_xmt_flush =
  * =================
- *   
+ *
  * Overview:
  *   Processes all frames whether they've been transmitted
  *   or not.
- *  
+ *
  * Returns:
  *   None
- *       
+ *
  * Arguments:
  *   bp - pointer to board information
  *
@@ -3347,10 +3526,10 @@ static void dfx_xmt_flush( DFX_board_t *bp )
 
                /* Return skb to operating system */
                comp = bp->rcv_xmt_reg.index.xmt_comp;
-               pci_unmap_single(bp->pci_dev,
+               dma_unmap_single(bp->bus_dev,
                                 bp->descr_block_virt->xmt_data[comp].long_1,
                                 p_xmt_drv_descr->p_skb->len,
-                                PCI_DMA_TODEVICE);
+                                DMA_TO_DEVICE);
                dev_kfree_skb(p_xmt_drv_descr->p_skb);
 
                /* Increment transmit error counter */
@@ -3378,13 +3557,44 @@ static void dfx_xmt_flush( DFX_board_t *bp )
        bp->cons_block_virt->xmt_rcv_data = prod_cons;
        }
 
-static void __devexit dfx_remove_one_pci_or_eisa(struct pci_dev *pdev, struct net_device *dev)
+/*
+ * ==================
+ * = dfx_unregister =
+ * ==================
+ *
+ * Overview:
+ *   Shuts down an FDDI controller
+ *
+ * Returns:
+ *   Condition code
+ *
+ * Arguments:
+ *   bdev - pointer to device information
+ *
+ * Functional Description:
+ *
+ * Return Codes:
+ *   None
+ *
+ * Assumptions:
+ *   It compiles so it should work :-( (PCI cards do :-)
+ *
+ * Side Effects:
+ *   Device structures for FDDI adapters (fddi0, fddi1, etc) are
+ *   freed.
+ */
+static void __devexit dfx_unregister(struct device *bdev)
 {
-       DFX_board_t     *bp = dev->priv;
+       struct net_device *dev = dev_get_drvdata(bdev);
+       DFX_board_t *bp = netdev_priv(dev);
+       int dfx_bus_pci = DFX_BUS_PCI(bdev);
+       int dfx_bus_tc = DFX_BUS_TC(bdev);
+       int dfx_use_mmio = DFX_MMIO || dfx_bus_tc;
+       resource_size_t bar_start = 0;          /* pointer to port */
+       resource_size_t bar_len = 0;            /* resource length */
        int             alloc_size;             /* total buffer size used */
 
        unregister_netdev(dev);
-       release_region(dev->base_addr,  pdev ? PFI_K_CSR_IO_LEN : PI_ESIC_K_CSR_IO_LEN );
 
        alloc_size = sizeof(PI_DESCR_BLOCK) +
                     PI_CMD_REQ_K_SIZE_MAX + PI_CMD_RSP_K_SIZE_MAX +
@@ -3394,84 +3604,140 @@ static void __devexit dfx_remove_one_pci_or_eisa(struct pci_dev *pdev, struct ne
                     sizeof(PI_CONSUMER_BLOCK) +
                     (PI_ALIGN_K_DESC_BLK - 1);
        if (bp->kmalloced)
-               pci_free_consistent(pdev, alloc_size, bp->kmalloced,
-                                   bp->kmalloced_dma);
+               dma_free_coherent(bdev, alloc_size,
+                                 bp->kmalloced, bp->kmalloced_dma);
+
+       dfx_bus_uninit(dev);
+
+       dfx_get_bars(bdev, &bar_start, &bar_len);
+       if (dfx_use_mmio) {
+               iounmap(bp->base.mem);
+               release_mem_region(bar_start, bar_len);
+       } else
+               release_region(bar_start, bar_len);
+
+       if (dfx_bus_pci)
+               pci_disable_device(to_pci_dev(bdev));
+
        free_netdev(dev);
 }
 
-static void __devexit dfx_remove_one (struct pci_dev *pdev)
-{
-       struct net_device *dev = pci_get_drvdata(pdev);
 
-       dfx_remove_one_pci_or_eisa(pdev, dev);
-       pci_set_drvdata(pdev, NULL);
-}
+static int __devinit __maybe_unused dfx_dev_register(struct device *);
+static int __devexit __maybe_unused dfx_dev_unregister(struct device *);
+
+#ifdef CONFIG_PCI
+static int __devinit dfx_pci_register(struct pci_dev *,
+                                     const struct pci_device_id *);
+static void __devexit dfx_pci_unregister(struct pci_dev *);
 
-static struct pci_device_id dfx_pci_tbl[] = {
-       { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_FDDI, PCI_ANY_ID, PCI_ANY_ID, },
-       { 0, }
+static struct pci_device_id dfx_pci_table[] = {
+       { PCI_DEVICE(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_FDDI) },
+       { }
 };
-MODULE_DEVICE_TABLE(pci, dfx_pci_tbl);
+MODULE_DEVICE_TABLE(pci, dfx_pci_table);
 
-static struct pci_driver dfx_driver = {
+static struct pci_driver dfx_pci_driver = {
        .name           = "defxx",
-       .probe          = dfx_init_one,
-       .remove         = __devexit_p(dfx_remove_one),
-       .id_table       = dfx_pci_tbl,
+       .id_table       = dfx_pci_table,
+       .probe          = dfx_pci_register,
+       .remove         = __devexit_p(dfx_pci_unregister),
 };
 
-static int dfx_have_pci;
-static int dfx_have_eisa;
-
+static __devinit int dfx_pci_register(struct pci_dev *pdev,
+                                     const struct pci_device_id *ent)
+{
+       return dfx_register(&pdev->dev);
+}
 
-static void __exit dfx_eisa_cleanup(void)
+static void __devexit dfx_pci_unregister(struct pci_dev *pdev)
 {
-       struct net_device *dev = root_dfx_eisa_dev;
+       dfx_unregister(&pdev->dev);
+}
+#endif /* CONFIG_PCI */
+
+#ifdef CONFIG_EISA
+static struct eisa_device_id dfx_eisa_table[] = {
+        { "DEC3001", DEFEA_PROD_ID_1 },
+        { "DEC3002", DEFEA_PROD_ID_2 },
+        { "DEC3003", DEFEA_PROD_ID_3 },
+        { "DEC3004", DEFEA_PROD_ID_4 },
+        { }
+};
+MODULE_DEVICE_TABLE(eisa, dfx_eisa_table);
+
+static struct eisa_driver dfx_eisa_driver = {
+       .id_table       = dfx_eisa_table,
+       .driver         = {
+               .name   = "defxx",
+               .bus    = &eisa_bus_type,
+               .probe  = dfx_dev_register,
+               .remove = __devexit_p(dfx_dev_unregister),
+       },
+};
+#endif /* CONFIG_EISA */
+
+#ifdef CONFIG_TC
+static struct tc_device_id const dfx_tc_table[] = {
+       { "DEC     ", "PMAF-FA " },
+       { "DEC     ", "PMAF-FD " },
+       { "DEC     ", "PMAF-FS " },
+       { "DEC     ", "PMAF-FU " },
+       { }
+};
+MODULE_DEVICE_TABLE(tc, dfx_tc_table);
+
+static struct tc_driver dfx_tc_driver = {
+       .id_table       = dfx_tc_table,
+       .driver         = {
+               .name   = "defxx",
+               .bus    = &tc_bus_type,
+               .probe  = dfx_dev_register,
+               .remove = __devexit_p(dfx_dev_unregister),
+       },
+};
+#endif /* CONFIG_TC */
 
-       while (dev)
-       {
-               struct net_device *tmp;
-               DFX_board_t *bp;
+static int __devinit __maybe_unused dfx_dev_register(struct device *dev)
+{
+       int status;
 
-               bp = (DFX_board_t*)dev->priv;
-               tmp = bp->next;
-               dfx_remove_one_pci_or_eisa(NULL, dev);
-               dev = tmp;
-       }
+       status = dfx_register(dev);
+       if (!status)
+               get_device(dev);
+       return status;
 }
 
-static int __init dfx_init(void)
+static int __devexit __maybe_unused dfx_dev_unregister(struct device *dev)
 {
-       int rc_pci, rc_eisa;
+       put_device(dev);
+       dfx_unregister(dev);
+       return 0;
+}
 
-       rc_pci = pci_module_init(&dfx_driver);
-       if (rc_pci >= 0) dfx_have_pci = 1;
-       
-       rc_eisa = dfx_eisa_init();
-       if (rc_eisa >= 0) dfx_have_eisa = 1;
 
-       return ((rc_eisa < 0) ? 0 : rc_eisa)  + ((rc_pci < 0) ? 0 : rc_pci); 
+static int __devinit dfx_init(void)
+{
+       int status;
+
+       status = pci_register_driver(&dfx_pci_driver);
+       if (!status)
+               status = eisa_driver_register(&dfx_eisa_driver);
+       if (!status)
+               status = tc_register_driver(&dfx_tc_driver);
+       return status;
 }
 
-static void __exit dfx_cleanup(void)
+static void __devexit dfx_cleanup(void)
 {
-       if (dfx_have_pci)
-               pci_unregister_driver(&dfx_driver);
-       if (dfx_have_eisa)
-               dfx_eisa_cleanup();
-               
-}      
+       tc_unregister_driver(&dfx_tc_driver);
+       eisa_driver_unregister(&dfx_eisa_driver);
+       pci_unregister_driver(&dfx_pci_driver);
+}
 
 module_init(dfx_init);
 module_exit(dfx_cleanup);
 MODULE_AUTHOR("Lawrence V. Stefani");
-MODULE_DESCRIPTION("DEC FDDIcontroller EISA/PCI (DEFEA/DEFPA) driver "
+MODULE_DESCRIPTION("DEC FDDIcontroller TC/EISA/PCI (DEFTA/DEFEA/DEFPA) driver "
                   DRV_VERSION " " DRV_RELDATE);
 MODULE_LICENSE("GPL");
-
-\f
-/*
- * Local variables:
- * kernel-compile-command: "gcc -D__KERNEL__ -I/root/linux/include -Wall -Wstrict-prototypes -O2 -pipe -fomit-frame-pointer -fno-strength-reduce -m486 -malign-loops=2 -malign-jumps=2 -malign-functions=2 -c defxx.c"
- * End:
- */