fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / atm / fore200e.c
index c41bbe2..4aeb3d0 100644 (file)
@@ -25,7 +25,6 @@
 */
 
 
-#include <linux/config.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
 #include <linux/init.h>
@@ -38,6 +37,8 @@
 #include <linux/atmdev.h>
 #include <linux/sonet.h>
 #include <linux/atm_suni.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
 #include <asm/io.h>
 #include <asm/string.h>
 #include <asm/page.h>
 
 #define FORE200E_NEXT_ENTRY(index, modulo)         (index = ++(index) % (modulo))
 
-
-#define MSECS(ms)  (((ms)*HZ/1000)+1)
-
-
 #if 1
 #define ASSERT(expr)     if (!(expr)) { \
                             printk(FORE200E "assertion failed! %s[%d]: %s\n", \
 #endif
 
 
-extern const struct atmdev_ops   fore200e_ops;
-extern const struct fore200e_bus fore200e_bus[];
+static const struct atmdev_ops   fore200e_ops;
+static const struct fore200e_bus fore200e_bus[];
 
-static struct fore200e* fore200e_boards = NULL;
+static LIST_HEAD(fore200e_boards);
 
 
 MODULE_AUTHOR("Christophe Lizzi - credits to Uwe Dannowski and Heikki Vatiainen");
@@ -169,34 +166,9 @@ fore200e_atm2fore_aal(int aal)
 static char*
 fore200e_irq_itoa(int irq)
 {
-#if defined(__sparc_v9__)
-    return __irq_itoa(irq);
-#else
     static char str[8];
     sprintf(str, "%d", irq);
     return str;
-#endif
-}
-
-
-static void*
-fore200e_kmalloc(int size, int flags)
-{
-    void* chunk = kmalloc(size, flags);
-
-    if (chunk)
-       memset(chunk, 0x00, size);
-    else
-       printk(FORE200E "kmalloc() failed, requested size = %d, flags = 0x%x\n", size, flags);
-    
-    return chunk;
-}
-
-
-static void
-fore200e_kfree(void* chunk)
-{
-    kfree(chunk);
 }
 
 
@@ -215,7 +187,7 @@ fore200e_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, int size, i
     chunk->align_size = size;
     chunk->direction  = direction;
 
-    chunk->alloc_addr = fore200e_kmalloc(chunk->alloc_size, GFP_KERNEL | GFP_DMA);
+    chunk->alloc_addr = kzalloc(chunk->alloc_size, GFP_KERNEL | GFP_DMA);
     if (chunk->alloc_addr == NULL)
        return -ENOMEM;
 
@@ -237,14 +209,14 @@ fore200e_chunk_free(struct fore200e* fore200e, struct chunk* chunk)
 {
     fore200e->bus->dma_unmap(fore200e, chunk->dma_addr, chunk->dma_size, chunk->direction);
 
-    fore200e_kfree(chunk->alloc_addr);
+    kfree(chunk->alloc_addr);
 }
 
 
 static void
 fore200e_spin(int msecs)
 {
-    unsigned long timeout = jiffies + MSECS(msecs);
+    unsigned long timeout = jiffies + msecs_to_jiffies(msecs);
     while (time_before(jiffies, timeout));
 }
 
@@ -252,7 +224,7 @@ fore200e_spin(int msecs)
 static int
 fore200e_poll(struct fore200e* fore200e, volatile u32* addr, u32 val, int msecs)
 {
-    unsigned long timeout = jiffies + MSECS(msecs);
+    unsigned long timeout = jiffies + msecs_to_jiffies(msecs);
     int           ok;
 
     mb();
@@ -274,9 +246,9 @@ fore200e_poll(struct fore200e* fore200e, volatile u32* addr, u32 val, int msecs)
 
 
 static int
-fore200e_io_poll(struct fore200e* fore200e, volatile u32addr, u32 val, int msecs)
+fore200e_io_poll(struct fore200e* fore200e, volatile u32 __iomem *addr, u32 val, int msecs)
 {
-    unsigned long timeout = jiffies + MSECS(msecs);
+    unsigned long timeout = jiffies + msecs_to_jiffies(msecs);
     int           ok;
 
     do {
@@ -346,7 +318,7 @@ fore200e_reset(struct fore200e* fore200e, int diag)
 {
     int ok;
 
-    fore200e->cp_monitor = (struct cp_monitor*)(fore200e->virt_base + FORE200E_CP_MONITOR_OFFSET);
+    fore200e->cp_monitor = fore200e->virt_base + FORE200E_CP_MONITOR_OFFSET;
     
     fore200e->bus->write(BSTAT_COLD_START, &fore200e->cp_monitor->bstat);
 
@@ -385,8 +357,7 @@ fore200e_shutdown(struct fore200e* fore200e)
     switch(fore200e->state) {
 
     case FORE200E_STATE_COMPLETE:
-       if (fore200e->stats)
-           kfree(fore200e->stats);
+       kfree(fore200e->stats);
 
     case FORE200E_STATE_IRQ:
        free_irq(fore200e->irq, fore200e->atm_dev);
@@ -439,7 +410,7 @@ fore200e_shutdown(struct fore200e* fore200e)
 
 #ifdef CONFIG_ATM_FORE200E_PCA
 
-static u32 fore200e_pca_read(volatile u32addr)
+static u32 fore200e_pca_read(volatile u32 __iomem *addr)
 {
     /* on big-endian hosts, the board is configured to convert
        the endianess of slave RAM accesses  */
@@ -447,7 +418,7 @@ static u32 fore200e_pca_read(volatile u32* addr)
 }
 
 
-static void fore200e_pca_write(u32 val, volatile u32addr)
+static void fore200e_pca_write(u32 val, volatile u32 __iomem *addr)
 {
     /* on big-endian hosts, the board is configured to convert
        the endianess of slave RAM accesses  */
@@ -560,7 +531,7 @@ fore200e_pca_reset(struct fore200e* fore200e)
 }
 
 
-static int __init
+static int __devinit
 fore200e_pca_map(struct fore200e* fore200e)
 {
     DPRINTK(2, "device %s being mapped in memory\n", fore200e->name);
@@ -575,9 +546,9 @@ fore200e_pca_map(struct fore200e* fore200e)
     DPRINTK(1, "device %s mapped to 0x%p\n", fore200e->name, fore200e->virt_base);
 
     /* gain access to the PCA specific registers  */
-    fore200e->regs.pca.hcr = (u32*)(fore200e->virt_base + PCA200E_HCR_OFFSET);
-    fore200e->regs.pca.imr = (u32*)(fore200e->virt_base + PCA200E_IMR_OFFSET);
-    fore200e->regs.pca.psr = (u32*)(fore200e->virt_base + PCA200E_PSR_OFFSET);
+    fore200e->regs.pca.hcr = fore200e->virt_base + PCA200E_HCR_OFFSET;
+    fore200e->regs.pca.imr = fore200e->virt_base + PCA200E_IMR_OFFSET;
+    fore200e->regs.pca.psr = fore200e->virt_base + PCA200E_PSR_OFFSET;
 
     fore200e->state = FORE200E_STATE_MAP;
     return 0;
@@ -594,7 +565,7 @@ fore200e_pca_unmap(struct fore200e* fore200e)
 }
 
 
-static int __init
+static int __devinit
 fore200e_pca_configure(struct fore200e* fore200e)
 {
     struct pci_dev* pci_dev = (struct pci_dev*)fore200e->bus_dev;
@@ -635,39 +606,6 @@ fore200e_pca_configure(struct fore200e* fore200e)
 }
 
 
-static struct fore200e* __init
-fore200e_pca_detect(const struct fore200e_bus* bus, int index)
-{
-    struct fore200e* fore200e;
-    struct pci_dev*  pci_dev = NULL;
-    int              count = index;
-    
-    do {
-       pci_dev = pci_find_device(PCI_VENDOR_ID_FORE, PCI_DEVICE_ID_FORE_PCA200E, pci_dev);
-       if (pci_dev == NULL)
-           return NULL;
-    } while (count--);
-
-    if (pci_enable_device(pci_dev))
-       return NULL;
-    
-    fore200e = fore200e_kmalloc(sizeof(struct fore200e), GFP_KERNEL);
-    if (fore200e == NULL)
-       return NULL;
-
-    fore200e->bus       = bus;
-    fore200e->bus_dev   = pci_dev;    
-    fore200e->irq       = pci_dev->irq;
-    fore200e->phys_base = pci_resource_start(pci_dev, 0);
-
-    sprintf(fore200e->name, "%s-%d", bus->model_name, index - 1);
-
-    pci_set_master(pci_dev);
-
-    return fore200e;
-}
-
-
 static int __init
 fore200e_pca_prom_read(struct fore200e* fore200e, struct prom_data* prom)
 {
@@ -682,19 +620,19 @@ fore200e_pca_prom_read(struct fore200e* fore200e, struct prom_data* prom)
     opcode.opcode = OPCODE_GET_PROM;
     opcode.pad    = 0;
 
-    prom_dma = fore200e->bus->dma_map(fore200e, prom, sizeof(struct prom_data), FORE200E_DMA_FROMDEVICE);
+    prom_dma = fore200e->bus->dma_map(fore200e, prom, sizeof(struct prom_data), DMA_FROM_DEVICE);
 
     fore200e->bus->write(prom_dma, &entry->cp_entry->cmd.prom_block.prom_haddr);
     
     *entry->status = STATUS_PENDING;
 
-    fore200e->bus->write(*(u32*)&opcode, (u32*)&entry->cp_entry->cmd.prom_block.opcode);
+    fore200e->bus->write(*(u32*)&opcode, (u32 __iomem *)&entry->cp_entry->cmd.prom_block.opcode);
 
     ok = fore200e_poll(fore200e, entry->status, STATUS_COMPLETE, 400);
 
     *entry->status = STATUS_FREE;
 
-    fore200e->bus->dma_unmap(fore200e, prom_dma, sizeof(struct prom_data), FORE200E_DMA_FROMDEVICE);
+    fore200e->bus->dma_unmap(fore200e, prom_dma, sizeof(struct prom_data), DMA_FROM_DEVICE);
 
     if (ok == 0) {
        printk(FORE200E "unable to get PROM data from device %s\n", fore200e->name);
@@ -729,14 +667,14 @@ fore200e_pca_proc_read(struct fore200e* fore200e, char *page)
 #ifdef CONFIG_ATM_FORE200E_SBA
 
 static u32
-fore200e_sba_read(volatile u32addr)
+fore200e_sba_read(volatile u32 __iomem *addr)
 {
     return sbus_readl(addr);
 }
 
 
 static void
-fore200e_sba_write(u32 val, volatile u32addr)
+fore200e_sba_write(u32 val, volatile u32 __iomem *addr)
 {
     sbus_writel(val, addr);
 }
@@ -855,10 +793,10 @@ fore200e_sba_map(struct fore200e* fore200e)
     unsigned int bursts;
 
     /* gain access to the SBA specific registers  */
-    fore200e->regs.sba.hcr = (u32*)sbus_ioremap(&sbus_dev->resource[0], 0, SBA200E_HCR_LENGTH, "SBA HCR");
-    fore200e->regs.sba.bsr = (u32*)sbus_ioremap(&sbus_dev->resource[1], 0, SBA200E_BSR_LENGTH, "SBA BSR");
-    fore200e->regs.sba.isr = (u32*)sbus_ioremap(&sbus_dev->resource[2], 0, SBA200E_ISR_LENGTH, "SBA ISR");
-    fore200e->virt_base    = (u32*)sbus_ioremap(&sbus_dev->resource[3], 0, SBA200E_RAM_LENGTH, "SBA RAM");
+    fore200e->regs.sba.hcr = sbus_ioremap(&sbus_dev->resource[0], 0, SBA200E_HCR_LENGTH, "SBA HCR");
+    fore200e->regs.sba.bsr = sbus_ioremap(&sbus_dev->resource[1], 0, SBA200E_BSR_LENGTH, "SBA BSR");
+    fore200e->regs.sba.isr = sbus_ioremap(&sbus_dev->resource[2], 0, SBA200E_ISR_LENGTH, "SBA ISR");
+    fore200e->virt_base    = sbus_ioremap(&sbus_dev->resource[3], 0, SBA200E_RAM_LENGTH, "SBA RAM");
 
     if (fore200e->virt_base == NULL) {
        printk(FORE200E "unable to map RAM of device %s\n", fore200e->name);
@@ -883,10 +821,10 @@ fore200e_sba_map(struct fore200e* fore200e)
 static void
 fore200e_sba_unmap(struct fore200e* fore200e)
 {
-    sbus_iounmap((ulong)fore200e->regs.sba.hcr, SBA200E_HCR_LENGTH);
-    sbus_iounmap((ulong)fore200e->regs.sba.bsr, SBA200E_BSR_LENGTH);
-    sbus_iounmap((ulong)fore200e->regs.sba.isr, SBA200E_ISR_LENGTH);
-    sbus_iounmap((ulong)fore200e->virt_base,    SBA200E_RAM_LENGTH);
+    sbus_iounmap(fore200e->regs.sba.hcr, SBA200E_HCR_LENGTH);
+    sbus_iounmap(fore200e->regs.sba.bsr, SBA200E_BSR_LENGTH);
+    sbus_iounmap(fore200e->regs.sba.isr, SBA200E_ISR_LENGTH);
+    sbus_iounmap(fore200e->virt_base,    SBA200E_RAM_LENGTH);
 }
 
 
@@ -925,7 +863,7 @@ fore200e_sba_detect(const struct fore200e_bus* bus, int index)
        return NULL;
     }
 
-    fore200e = fore200e_kmalloc(sizeof(struct fore200e), GFP_KERNEL);
+    fore200e = kzalloc(sizeof(struct fore200e), GFP_KERNEL);
     if (fore200e == NULL)
        return NULL;
 
@@ -998,12 +936,11 @@ fore200e_tx_irq(struct fore200e* fore200e)
                entry, txq->tail, entry->vc_map, entry->skb);
 
        /* free copy of misaligned data */
-       if (entry->data)
-           kfree(entry->data);
+       kfree(entry->data);
        
        /* remove DMA mapping */
        fore200e->bus->dma_unmap(fore200e, entry->tpd->tsd[ 0 ].buffer, entry->tpd->tsd[ 0 ].length,
-                                FORE200E_DMA_TODEVICE);
+                                DMA_TO_DEVICE);
 
        vc_map = entry->vc_map;
 
@@ -1025,7 +962,7 @@ fore200e_tx_irq(struct fore200e* fore200e)
                /* when a vcc is closed, some PDUs may be still pending in the tx queue.
                   if the same vcc is immediately re-opened, those pending PDUs must
                   not be popped after the completion of their emission, as they refer
-                  to the prior incarnation of that vcc. otherwise, vcc->sk->sk_wmem_alloc
+                  to the prior incarnation of that vcc. otherwise, sk_atm(vcc)->sk_wmem_alloc
                   would be decremented by the size of the (unrelated) skb, possibly
                   leading to a negative sk->sk_wmem_alloc count, ultimately freezing the vcc.
                   we thus bind the tx entry to the current incarnation of the vcc
@@ -1052,8 +989,8 @@ fore200e_tx_irq(struct fore200e* fore200e)
                }
 #if 1
                /* race fixed by the above incarnation mechanism, but... */
-               if (atomic_read(&vcc->sk->sk_wmem_alloc) < 0) {
-                   atomic_set(&vcc->sk->sk_wmem_alloc, 0);
+               if (atomic_read(&sk_atm(vcc)->sk_wmem_alloc) < 0) {
+                   atomic_set(&sk_atm(vcc)->sk_wmem_alloc, 0);
                }
 #endif
                /* check error condition */
@@ -1213,7 +1150,7 @@ fore200e_push_rpd(struct fore200e* fore200e, struct atm_vcc* vcc, struct rpd* rp
        return -ENOMEM;
     } 
 
-    do_gettimeofday(&skb->stamp);
+    __net_timestamp(skb);
     
 #ifdef FORE200E_52BYTE_AAL0_SDU
     if (cell_header) {
@@ -1228,12 +1165,12 @@ fore200e_push_rpd(struct fore200e* fore200e, struct atm_vcc* vcc, struct rpd* rp
        buffer = FORE200E_HDL2BUF(rpd->rsd[ i ].handle);
        
        /* Make device DMA transfer visible to CPU.  */
-       fore200e->bus->dma_sync_for_cpu(fore200e, buffer->data.dma_addr, rpd->rsd[ i ].length, FORE200E_DMA_FROMDEVICE);
+       fore200e->bus->dma_sync_for_cpu(fore200e, buffer->data.dma_addr, rpd->rsd[ i ].length, DMA_FROM_DEVICE);
        
        memcpy(skb_put(skb, rpd->rsd[ i ].length), buffer->data.align_addr, rpd->rsd[ i ].length);
 
        /* Now let the device get at it again.  */
-       fore200e->bus->dma_sync_for_device(fore200e, buffer->data.dma_addr, rpd->rsd[ i ].length, FORE200E_DMA_FROMDEVICE);
+       fore200e->bus->dma_sync_for_device(fore200e, buffer->data.dma_addr, rpd->rsd[ i ].length, DMA_FROM_DEVICE);
     }
 
     DPRINTK(3, "rx skb: len = %d, truesize = %d\n", skb->len, skb->truesize);
@@ -1256,12 +1193,12 @@ fore200e_push_rpd(struct fore200e* fore200e, struct atm_vcc* vcc, struct rpd* rp
        return -ENOMEM;
     }
 
-    ASSERT(atomic_read(&vcc->sk->sk_wmem_alloc) >= 0);
+    ASSERT(atomic_read(&sk_atm(vcc)->sk_wmem_alloc) >= 0);
 
     vcc->push(vcc, skb);
     atomic_inc(&vcc->stats->rx);
 
-    ASSERT(atomic_read(&vcc->sk->sk_wmem_alloc) >= 0);
+    ASSERT(atomic_read(&sk_atm(vcc)->sk_wmem_alloc) >= 0);
 
     return 0;
 }
@@ -1372,7 +1309,7 @@ fore200e_irq(struct fore200e* fore200e)
 
 
 static irqreturn_t
-fore200e_interrupt(int irq, void* dev, struct pt_regs* regs)
+fore200e_interrupt(int irq, void* dev)
 {
     struct fore200e* fore200e = FORE200E_DEV((struct atm_dev*)dev);
 
@@ -1476,12 +1413,12 @@ fore200e_activate_vcin(struct fore200e* fore200e, int activate, struct atm_vcc*
 #endif
        /* the MTU is not used by the cp, except in the case of AAL0 */
        fore200e->bus->write(mtu,                        &entry->cp_entry->cmd.activate_block.mtu);
-       fore200e->bus->write(*(u32*)&vpvc,         (u32*)&entry->cp_entry->cmd.activate_block.vpvc);
-       fore200e->bus->write(*(u32*)&activ_opcode, (u32*)&entry->cp_entry->cmd.activate_block.opcode);
+       fore200e->bus->write(*(u32*)&vpvc,         (u32 __iomem *)&entry->cp_entry->cmd.activate_block.vpvc);
+       fore200e->bus->write(*(u32*)&activ_opcode, (u32 __iomem *)&entry->cp_entry->cmd.activate_block.opcode);
     }
     else {
-       fore200e->bus->write(*(u32*)&vpvc,           (u32*)&entry->cp_entry->cmd.deactivate_block.vpvc);
-       fore200e->bus->write(*(u32*)&deactiv_opcode, (u32*)&entry->cp_entry->cmd.deactivate_block.opcode);
+       fore200e->bus->write(*(u32*)&vpvc,         (u32 __iomem *)&entry->cp_entry->cmd.deactivate_block.vpvc);
+       fore200e->bus->write(*(u32*)&deactiv_opcode, (u32 __iomem *)&entry->cp_entry->cmd.deactivate_block.opcode);
     }
 
     ok = fore200e_poll(fore200e, entry->status, STATUS_COMPLETE, 400);
@@ -1549,7 +1486,7 @@ fore200e_open(struct atm_vcc *vcc)
 
     spin_unlock_irqrestore(&fore200e->q_lock, flags);
 
-    fore200e_vcc = fore200e_kmalloc(sizeof(struct fore200e_vcc), GFP_ATOMIC);
+    fore200e_vcc = kzalloc(sizeof(struct fore200e_vcc), GFP_ATOMIC);
     if (fore200e_vcc == NULL) {
        vc_map->vcc = NULL;
        return -ENOMEM;
@@ -1570,7 +1507,7 @@ fore200e_open(struct atm_vcc *vcc)
        if (fore200e->available_cell_rate < vcc->qos.txtp.max_pcr) {
            up(&fore200e->rate_sf);
 
-           fore200e_kfree(fore200e_vcc);
+           kfree(fore200e_vcc);
            vc_map->vcc = NULL;
            return -EAGAIN;
        }
@@ -1598,7 +1535,7 @@ fore200e_open(struct atm_vcc *vcc)
 
        fore200e->available_cell_rate += vcc->qos.txtp.max_pcr;
 
-       fore200e_kfree(fore200e_vcc);
+       kfree(fore200e_vcc);
        return -EINVAL;
     }
     
@@ -1656,7 +1593,7 @@ fore200e_close(struct atm_vcc* vcc)
     vcc->itf = vcc->vci = vcc->vpi = 0;
 
     fore200e_vcc = FORE200E_VCC(vcc);
-    FORE200E_VCC(vcc) = NULL;
+    vcc->dev_data = NULL;
 
     spin_unlock_irqrestore(&fore200e->q_lock, flags);
 
@@ -1674,7 +1611,7 @@ fore200e_close(struct atm_vcc* vcc)
     clear_bit(ATM_VF_PARTIAL,&vcc->flags);
 
     ASSERT(fore200e_vcc);
-    fore200e_kfree(fore200e_vcc);
+    kfree(fore200e_vcc);
 }
 
 
@@ -1698,7 +1635,7 @@ fore200e_send(struct atm_vcc *vcc, struct sk_buff *skb)
     unsigned long           flags;
 
     ASSERT(vcc);
-    ASSERT(atomic_read(&vcc->sk->sk_wmem_alloc) >= 0);
+    ASSERT(atomic_read(&sk_atm(vcc)->sk_wmem_alloc) >= 0);
     ASSERT(fore200e);
     ASSERT(fore200e_vcc);
 
@@ -1778,7 +1715,7 @@ fore200e_send(struct atm_vcc *vcc, struct sk_buff *skb)
 
            /* retry once again? */
            if (--retry > 0) {
-               schedule();
+               udelay(50);
                goto retry_here;
            }
 
@@ -1807,7 +1744,7 @@ fore200e_send(struct atm_vcc *vcc, struct sk_buff *skb)
     entry->data   = tx_copy ? data : NULL;
 
     tpd = entry->tpd;
-    tpd->tsd[ 0 ].buffer = fore200e->bus->dma_map(fore200e, data, tx_len, FORE200E_DMA_TODEVICE);
+    tpd->tsd[ 0 ].buffer = fore200e->bus->dma_map(fore200e, data, tx_len, DMA_TO_DEVICE);
     tpd->tsd[ 0 ].length = tx_len;
 
     FORE200E_NEXT_ENTRY(txq->head, QUEUE_SIZE_TX);
@@ -1857,7 +1794,7 @@ fore200e_send(struct atm_vcc *vcc, struct sk_buff *skb)
     tpd_haddr.haddr = entry->tpd_dma >> TPD_HADDR_SHIFT;          /* shift the address, as we are in a bitfield */
 
     *entry->status = STATUS_PENDING;
-    fore200e->bus->write(*(u32*)&tpd_haddr, (u32*)&entry->cp_entry->tpd_haddr);
+    fore200e->bus->write(*(u32*)&tpd_haddr, (u32 __iomem *)&entry->cp_entry->tpd_haddr);
 
     spin_unlock_irqrestore(&fore200e->q_lock, flags);
 
@@ -1875,13 +1812,13 @@ fore200e_getstats(struct fore200e* fore200e)
     u32                     stats_dma_addr;
 
     if (fore200e->stats == NULL) {
-       fore200e->stats = fore200e_kmalloc(sizeof(struct stats), GFP_KERNEL | GFP_DMA);
+       fore200e->stats = kzalloc(sizeof(struct stats), GFP_KERNEL | GFP_DMA);
        if (fore200e->stats == NULL)
            return -ENOMEM;
     }
     
     stats_dma_addr = fore200e->bus->dma_map(fore200e, fore200e->stats,
-                                           sizeof(struct stats), FORE200E_DMA_FROMDEVICE);
+                                           sizeof(struct stats), DMA_FROM_DEVICE);
     
     FORE200E_NEXT_ENTRY(cmdq->head, QUEUE_SIZE_CMD);
 
@@ -1892,13 +1829,13 @@ fore200e_getstats(struct fore200e* fore200e)
     
     *entry->status = STATUS_PENDING;
 
-    fore200e->bus->write(*(u32*)&opcode, (u32*)&entry->cp_entry->cmd.stats_block.opcode);
+    fore200e->bus->write(*(u32*)&opcode, (u32 __iomem *)&entry->cp_entry->cmd.stats_block.opcode);
 
     ok = fore200e_poll(fore200e, entry->status, STATUS_COMPLETE, 400);
 
     *entry->status = STATUS_FREE;
 
-    fore200e->bus->dma_unmap(fore200e, stats_dma_addr, sizeof(struct stats), FORE200E_DMA_FROMDEVICE);
+    fore200e->bus->dma_unmap(fore200e, stats_dma_addr, sizeof(struct stats), DMA_FROM_DEVICE);
     
     if (ok == 0) {
        printk(FORE200E "unable to get statistics from device %s\n", fore200e->name);
@@ -1910,7 +1847,7 @@ fore200e_getstats(struct fore200e* fore200e)
 
 
 static int
-fore200e_getsockopt(struct atm_vcc* vcc, int level, int optname, voidoptval, int optlen)
+fore200e_getsockopt(struct atm_vcc* vcc, int level, int optname, void __user *optval, int optlen)
 {
     /* struct fore200e* fore200e = FORE200E_DEV(vcc->dev); */
 
@@ -1922,7 +1859,7 @@ fore200e_getsockopt(struct atm_vcc* vcc, int level, int optname, void* optval, i
 
 
 static int
-fore200e_setsockopt(struct atm_vcc* vcc, int level, int optname, voidoptval, int optlen)
+fore200e_setsockopt(struct atm_vcc* vcc, int level, int optname, void __user *optval, int optlen)
 {
     /* struct fore200e* fore200e = FORE200E_DEV(vcc->dev); */
     
@@ -1943,7 +1880,7 @@ fore200e_get_oc3(struct fore200e* fore200e, struct oc3_regs* regs)
     int                     ok;
     u32                     oc3_regs_dma_addr;
 
-    oc3_regs_dma_addr = fore200e->bus->dma_map(fore200e, regs, sizeof(struct oc3_regs), FORE200E_DMA_FROMDEVICE);
+    oc3_regs_dma_addr = fore200e->bus->dma_map(fore200e, regs, sizeof(struct oc3_regs), DMA_FROM_DEVICE);
 
     FORE200E_NEXT_ENTRY(cmdq->head, QUEUE_SIZE_CMD);
 
@@ -1962,7 +1899,7 @@ fore200e_get_oc3(struct fore200e* fore200e, struct oc3_regs* regs)
 
     *entry->status = STATUS_FREE;
 
-    fore200e->bus->dma_unmap(fore200e, oc3_regs_dma_addr, sizeof(struct oc3_regs), FORE200E_DMA_FROMDEVICE);
+    fore200e->bus->dma_unmap(fore200e, oc3_regs_dma_addr, sizeof(struct oc3_regs), DMA_FROM_DEVICE);
     
     if (ok == 0) {
        printk(FORE200E "unable to get OC-3 regs of device %s\n", fore200e->name);
@@ -1995,7 +1932,7 @@ fore200e_set_oc3(struct fore200e* fore200e, u32 reg, u32 value, u32 mask)
     
     *entry->status = STATUS_PENDING;
 
-    fore200e->bus->write(*(u32*)&opcode, (u32*)&entry->cp_entry->cmd.oc3_block.opcode);
+    fore200e->bus->write(*(u32*)&opcode, (u32 __iomem *)&entry->cp_entry->cmd.oc3_block.opcode);
 
     ok = fore200e_poll(fore200e, entry->status, STATUS_COMPLETE, 400);
 
@@ -2046,38 +1983,27 @@ fore200e_setloop(struct fore200e* fore200e, int loop_mode)
 }
 
 
-static inline unsigned int
-fore200e_swap(unsigned int in)
-{
-#if defined(__LITTLE_ENDIAN)
-    return swab32(in);
-#else
-    return in;
-#endif
-}
-
-
 static int
-fore200e_fetch_stats(struct fore200e* fore200e, struct sonet_statsarg)
+fore200e_fetch_stats(struct fore200e* fore200e, struct sonet_stats __user *arg)
 {
     struct sonet_stats tmp;
 
     if (fore200e_getstats(fore200e) < 0)
        return -EIO;
 
-    tmp.section_bip = fore200e_swap(fore200e->stats->oc3.section_bip8_errors);
-    tmp.line_bip    = fore200e_swap(fore200e->stats->oc3.line_bip24_errors);
-    tmp.path_bip    = fore200e_swap(fore200e->stats->oc3.path_bip8_errors);
-    tmp.line_febe   = fore200e_swap(fore200e->stats->oc3.line_febe_errors);
-    tmp.path_febe   = fore200e_swap(fore200e->stats->oc3.path_febe_errors);
-    tmp.corr_hcs    = fore200e_swap(fore200e->stats->oc3.corr_hcs_errors);
-    tmp.uncorr_hcs  = fore200e_swap(fore200e->stats->oc3.ucorr_hcs_errors);
-    tmp.tx_cells    = fore200e_swap(fore200e->stats->aal0.cells_transmitted)  +
-                     fore200e_swap(fore200e->stats->aal34.cells_transmitted) +
-                     fore200e_swap(fore200e->stats->aal5.cells_transmitted);
-    tmp.rx_cells    = fore200e_swap(fore200e->stats->aal0.cells_received)     +
-                     fore200e_swap(fore200e->stats->aal34.cells_received)    +
-                     fore200e_swap(fore200e->stats->aal5.cells_received);
+    tmp.section_bip = cpu_to_be32(fore200e->stats->oc3.section_bip8_errors);
+    tmp.line_bip    = cpu_to_be32(fore200e->stats->oc3.line_bip24_errors);
+    tmp.path_bip    = cpu_to_be32(fore200e->stats->oc3.path_bip8_errors);
+    tmp.line_febe   = cpu_to_be32(fore200e->stats->oc3.line_febe_errors);
+    tmp.path_febe   = cpu_to_be32(fore200e->stats->oc3.path_febe_errors);
+    tmp.corr_hcs    = cpu_to_be32(fore200e->stats->oc3.corr_hcs_errors);
+    tmp.uncorr_hcs  = cpu_to_be32(fore200e->stats->oc3.ucorr_hcs_errors);
+    tmp.tx_cells    = cpu_to_be32(fore200e->stats->aal0.cells_transmitted)  +
+                     cpu_to_be32(fore200e->stats->aal34.cells_transmitted) +
+                     cpu_to_be32(fore200e->stats->aal5.cells_transmitted);
+    tmp.rx_cells    = cpu_to_be32(fore200e->stats->aal0.cells_received)     +
+                     cpu_to_be32(fore200e->stats->aal34.cells_received)    +
+                     cpu_to_be32(fore200e->stats->aal5.cells_received);
 
     if (arg)
        return copy_to_user(arg, &tmp, sizeof(struct sonet_stats)) ? -EFAULT : 0;       
@@ -2087,7 +2013,7 @@ fore200e_fetch_stats(struct fore200e* fore200e, struct sonet_stats* arg)
 
 
 static int
-fore200e_ioctl(struct atm_dev* dev, unsigned int cmd, void* arg)
+fore200e_ioctl(struct atm_dev* dev, unsigned int cmd, void __user * arg)
 {
     struct fore200e* fore200e = FORE200E_DEV(dev);
     
@@ -2096,19 +2022,19 @@ fore200e_ioctl(struct atm_dev* dev, unsigned int cmd, void* arg)
     switch (cmd) {
 
     case SONET_GETSTAT:
-       return fore200e_fetch_stats(fore200e, (struct sonet_stats*)arg);
+       return fore200e_fetch_stats(fore200e, (struct sonet_stats __user *)arg);
 
     case SONET_GETDIAG:
-       return put_user(0, (int*)arg) ? -EFAULT : 0;
+       return put_user(0, (int __user *)arg) ? -EFAULT : 0;
 
     case ATM_SETLOOP:
        return fore200e_setloop(fore200e, (int)(unsigned long)arg);
 
     case ATM_GETLOOP:
-       return put_user(fore200e->loop_mode, (int*)arg) ? -EFAULT : 0;
+       return put_user(fore200e->loop_mode, (int __user *)arg) ? -EFAULT : 0;
 
     case ATM_QUERYLOOP:
-       return put_user(ATM_LM_LOC_PHY | ATM_LM_RMT_PHY, (int*)arg) ? -EFAULT : 0;
+       return put_user(ATM_LM_LOC_PHY | ATM_LM_RMT_PHY, (int __user *)arg) ? -EFAULT : 0;
     }
 
     return -ENOSYS; /* not implemented */
@@ -2164,10 +2090,10 @@ fore200e_change_qos(struct atm_vcc* vcc,struct atm_qos* qos, int flags)
 }
     
 
-static int __init
+static int __devinit
 fore200e_irq_request(struct fore200e* fore200e)
 {
-    if (request_irq(fore200e->irq, fore200e_interrupt, SA_SHIRQ, fore200e->name, fore200e->atm_dev) < 0) {
+    if (request_irq(fore200e->irq, fore200e_interrupt, IRQF_SHARED, fore200e->name, fore200e->atm_dev) < 0) {
 
        printk(FORE200E "unable to reserve IRQ %s for device %s\n",
               fore200e_irq_itoa(fore200e->irq), fore200e->name);
@@ -2187,10 +2113,10 @@ fore200e_irq_request(struct fore200e* fore200e)
 }
 
 
-static int __init
+static int __devinit
 fore200e_get_esi(struct fore200e* fore200e)
 {
-    struct prom_data* prom = fore200e_kmalloc(sizeof(struct prom_data), GFP_KERNEL | GFP_DMA);
+    struct prom_data* prom = kzalloc(sizeof(struct prom_data), GFP_KERNEL | GFP_DMA);
     int ok, i;
 
     if (!prom)
@@ -2198,7 +2124,7 @@ fore200e_get_esi(struct fore200e* fore200e)
 
     ok = fore200e->bus->prom_read(fore200e, prom);
     if (ok < 0) {
-       fore200e_kfree(prom);
+       kfree(prom);
        return -EBUSY;
     }
        
@@ -2213,13 +2139,13 @@ fore200e_get_esi(struct fore200e* fore200e)
        fore200e->esi[ i ] = fore200e->atm_dev->esi[ i ] = prom->mac_addr[ i + 2 ];
     }
     
-    fore200e_kfree(prom);
+    kfree(prom);
 
     return 0;
 }
 
 
-static int __init
+static int __devinit
 fore200e_alloc_rx_buf(struct fore200e* fore200e)
 {
     int scheme, magn, nbr, size, i;
@@ -2238,7 +2164,7 @@ fore200e_alloc_rx_buf(struct fore200e* fore200e)
            DPRINTK(2, "rx buffers %d / %d are being allocated\n", scheme, magn);
 
            /* allocate the array of receive buffers */
-           buffer = bsq->buffer = fore200e_kmalloc(nbr * sizeof(struct buffer), GFP_KERNEL);
+           buffer = bsq->buffer = kzalloc(nbr * sizeof(struct buffer), GFP_KERNEL);
 
            if (buffer == NULL)
                return -ENOMEM;
@@ -2257,11 +2183,11 @@ fore200e_alloc_rx_buf(struct fore200e* fore200e)
                /* allocate the receive buffer body */
                if (fore200e_chunk_alloc(fore200e,
                                         &buffer[ i ].data, size, fore200e->bus->buffer_alignment,
-                                        FORE200E_DMA_FROMDEVICE) < 0) {
+                                        DMA_FROM_DEVICE) < 0) {
                    
                    while (i > 0)
                        fore200e_chunk_free(fore200e, &buffer[ --i ].data);
-                   fore200e_kfree(buffer);
+                   kfree(buffer);
                    
                    return -ENOMEM;
                }
@@ -2284,13 +2210,13 @@ fore200e_alloc_rx_buf(struct fore200e* fore200e)
 }
 
 
-static int __init
+static int __devinit
 fore200e_init_bs_queue(struct fore200e* fore200e)
 {
     int scheme, magn, i;
 
     struct host_bsq*     bsq;
-    struct cp_bsq_entry* cp_entry;
+    struct cp_bsq_entry __iomem * cp_entry;
 
     for (scheme = 0; scheme < BUFFER_SCHEME_NBR; scheme++) {
        for (magn = 0; magn < BUFFER_MAGN_NBR; magn++) {
@@ -2320,8 +2246,8 @@ fore200e_init_bs_queue(struct fore200e* fore200e)
            }
            
            /* get the base address of the cp resident buffer supply queue entries */
-           cp_entry = (struct cp_bsq_entry*)(fore200e->virt_base + 
-                      fore200e->bus->read(&fore200e->cp_queues->cp_bsq[ scheme ][ magn ]));
+           cp_entry = fore200e->virt_base + 
+                      fore200e->bus->read(&fore200e->cp_queues->cp_bsq[ scheme ][ magn ]);
            
            /* fill the host resident and cp resident buffer supply queue entries */
            for (i = 0; i < QUEUE_SIZE_BS; i++) {
@@ -2347,11 +2273,11 @@ fore200e_init_bs_queue(struct fore200e* fore200e)
 }
 
 
-static int __init
+static int __devinit
 fore200e_init_rx_queue(struct fore200e* fore200e)
 {
     struct host_rxq*     rxq =  &fore200e->host_rxq;
-    struct cp_rxq_entry* cp_entry;
+    struct cp_rxq_entry __iomem * cp_entry;
     int i;
 
     DPRINTK(2, "receive queue is being initialized\n");
@@ -2377,8 +2303,7 @@ fore200e_init_rx_queue(struct fore200e* fore200e)
     }
 
     /* get the base address of the cp resident rx queue entries */
-    cp_entry = (struct cp_rxq_entry*)(fore200e->virt_base + 
-                                     fore200e->bus->read(&fore200e->cp_queues->cp_rxq));
+    cp_entry = fore200e->virt_base + fore200e->bus->read(&fore200e->cp_queues->cp_rxq);
 
     /* fill the host resident and cp resident rx entries */
     for (i=0; i < QUEUE_SIZE_RX; i++) {
@@ -2408,11 +2333,11 @@ fore200e_init_rx_queue(struct fore200e* fore200e)
 }
 
 
-static int __init
+static int __devinit
 fore200e_init_tx_queue(struct fore200e* fore200e)
 {
     struct host_txq*     txq =  &fore200e->host_txq;
-    struct cp_txq_entry* cp_entry;
+    struct cp_txq_entry __iomem * cp_entry;
     int i;
 
     DPRINTK(2, "transmit queue is being initialized\n");
@@ -2438,8 +2363,7 @@ fore200e_init_tx_queue(struct fore200e* fore200e)
     }
 
     /* get the base address of the cp resident tx queue entries */
-    cp_entry = (struct cp_txq_entry*)(fore200e->virt_base + 
-                                     fore200e->bus->read(&fore200e->cp_queues->cp_txq));
+    cp_entry = fore200e->virt_base + fore200e->bus->read(&fore200e->cp_queues->cp_txq);
 
     /* fill the host resident and cp resident tx entries */
     for (i=0; i < QUEUE_SIZE_TX; i++) {
@@ -2472,11 +2396,11 @@ fore200e_init_tx_queue(struct fore200e* fore200e)
 }
 
 
-static int __init
+static int __devinit
 fore200e_init_cmd_queue(struct fore200e* fore200e)
 {
     struct host_cmdq*     cmdq =  &fore200e->host_cmdq;
-    struct cp_cmdq_entry* cp_entry;
+    struct cp_cmdq_entry __iomem * cp_entry;
     int i;
 
     DPRINTK(2, "command queue is being initialized\n");
@@ -2491,8 +2415,7 @@ fore200e_init_cmd_queue(struct fore200e* fore200e)
     }
     
     /* get the base address of the cp resident cmd queue entries */
-    cp_entry = (struct cp_cmdq_entry*)(fore200e->virt_base + 
-                                      fore200e->bus->read(&fore200e->cp_queues->cp_cmdq));
+    cp_entry = fore200e->virt_base + fore200e->bus->read(&fore200e->cp_queues->cp_cmdq);
 
     /* fill the host resident and cp resident cmd entries */
     for (i=0; i < QUEUE_SIZE_CMD; i++) {
@@ -2520,7 +2443,7 @@ fore200e_param_bs_queue(struct fore200e* fore200e,
                        enum buffer_scheme scheme, enum buffer_magn magn,
                        int queue_length, int pool_size, int supply_blksize)
 {
-    struct bs_spec* bs_spec = &fore200e->cp_queues->init.bs_spec[ scheme ][ magn ];
+    struct bs_spec __iomem * bs_spec = &fore200e->cp_queues->init.bs_spec[ scheme ][ magn ];
 
     fore200e->bus->write(queue_length,                           &bs_spec->queue_length);
     fore200e->bus->write(fore200e_rx_buf_size[ scheme ][ magn ], &bs_spec->buffer_size);
@@ -2529,10 +2452,10 @@ fore200e_param_bs_queue(struct fore200e* fore200e,
 }
 
 
-static int __init
+static int __devinit
 fore200e_initialize(struct fore200e* fore200e)
 {
-    struct cp_queues* cpq;
+    struct cp_queues __iomem * cpq;
     int               ok, scheme, magn;
 
     DPRINTK(2, "device %s being initialized\n", fore200e->name);
@@ -2540,7 +2463,7 @@ fore200e_initialize(struct fore200e* fore200e)
     init_MUTEX(&fore200e->rate_sf);
     spin_lock_init(&fore200e->q_lock);
 
-    cpq = fore200e->cp_queues = (struct cp_queues*) (fore200e->virt_base + FORE200E_CP_QUEUES_OFFSET);
+    cpq = fore200e->cp_queues = fore200e->virt_base + FORE200E_CP_QUEUES_OFFSET;
 
     /* enable cp to host interrupts */
     fore200e->bus->write(1, &cpq->imask);
@@ -2581,10 +2504,10 @@ fore200e_initialize(struct fore200e* fore200e)
 }
 
 
-static void __init
+static void __devinit
 fore200e_monitor_putc(struct fore200e* fore200e, char c)
 {
-    struct cp_monitor* monitor = fore200e->cp_monitor;
+    struct cp_monitor __iomem * monitor = fore200e->cp_monitor;
 
 #if 0
     printk("%c", c);
@@ -2593,11 +2516,11 @@ fore200e_monitor_putc(struct fore200e* fore200e, char c)
 }
 
 
-static int __init
+static int __devinit
 fore200e_monitor_getc(struct fore200e* fore200e)
 {
-    struct cp_monitor* monitor = fore200e->cp_monitor;
-    unsigned long      timeout = jiffies + MSECS(50);
+    struct cp_monitor __iomem * monitor = fore200e->cp_monitor;
+    unsigned long      timeout = jiffies + msecs_to_jiffies(50);
     int                c;
 
     while (time_before(jiffies, timeout)) {
@@ -2618,7 +2541,7 @@ fore200e_monitor_getc(struct fore200e* fore200e)
 }
 
 
-static void __init
+static void __devinit
 fore200e_monitor_puts(struct fore200e* fore200e, char* str)
 {
     while (*str) {
@@ -2633,7 +2556,7 @@ fore200e_monitor_puts(struct fore200e* fore200e, char* str)
 }
 
 
-static int __init
+static int __devinit
 fore200e_start_fw(struct fore200e* fore200e)
 {
     int               ok;
@@ -2664,7 +2587,7 @@ fore200e_start_fw(struct fore200e* fore200e)
 }
 
 
-static int __init
+static int __devinit
 fore200e_load_fw(struct fore200e* fore200e)
 {
     u32* fw_data = (u32*) fore200e->bus->fw_data;
@@ -2672,7 +2595,7 @@ fore200e_load_fw(struct fore200e* fore200e)
 
     struct fw_header* fw_header = (struct fw_header*) fw_data;
 
-    u32load_addr = fore200e->virt_base + le32_to_cpu(fw_header->load_offset);
+    u32 __iomem *load_addr = fore200e->virt_base + le32_to_cpu(fw_header->load_offset);
 
     DPRINTK(2, "device %s firmware being loaded at 0x%p (%d words)\n", 
            fore200e->name, load_addr, fw_size);
@@ -2690,7 +2613,7 @@ fore200e_load_fw(struct fore200e* fore200e)
 }
 
 
-static int __init
+static int __devinit
 fore200e_register(struct fore200e* fore200e)
 {
     struct atm_dev* atm_dev;
@@ -2717,7 +2640,7 @@ fore200e_register(struct fore200e* fore200e)
 }
 
 
-static int __init
+static int __devinit
 fore200e_init(struct fore200e* fore200e)
 {
     if (fore200e_register(fore200e) < 0)
@@ -2763,26 +2686,111 @@ fore200e_init(struct fore200e* fore200e)
        return -EBUSY;
 
     fore200e_supply(fore200e);
-    
+
     /* all done, board initialization is now complete */
     fore200e->state = FORE200E_STATE_COMPLETE;
     return 0;
 }
 
+
+static int __devinit
+fore200e_pca_detect(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
+{
+    const struct fore200e_bus* bus = (struct fore200e_bus*) pci_ent->driver_data;
+    struct fore200e* fore200e;
+    int err = 0;
+    static int index = 0;
+
+    if (pci_enable_device(pci_dev)) {
+       err = -EINVAL;
+       goto out;
+    }
+    
+    fore200e = kzalloc(sizeof(struct fore200e), GFP_KERNEL);
+    if (fore200e == NULL) {
+       err = -ENOMEM;
+       goto out_disable;
+    }
+
+    fore200e->bus       = bus;
+    fore200e->bus_dev   = pci_dev;    
+    fore200e->irq       = pci_dev->irq;
+    fore200e->phys_base = pci_resource_start(pci_dev, 0);
+
+    sprintf(fore200e->name, "%s-%d", bus->model_name, index - 1);
+
+    pci_set_master(pci_dev);
+
+    printk(FORE200E "device %s found at 0x%lx, IRQ %s\n",
+          fore200e->bus->model_name, 
+          fore200e->phys_base, fore200e_irq_itoa(fore200e->irq));
+
+    sprintf(fore200e->name, "%s-%d", bus->model_name, index);
+
+    err = fore200e_init(fore200e);
+    if (err < 0) {
+       fore200e_shutdown(fore200e);
+       goto out_free;
+    }
+
+    ++index;
+    pci_set_drvdata(pci_dev, fore200e);
+
+out:
+    return err;
+
+out_free:
+    kfree(fore200e);
+out_disable:
+    pci_disable_device(pci_dev);
+    goto out;
+}
+
+
+static void __devexit fore200e_pca_remove_one(struct pci_dev *pci_dev)
+{
+    struct fore200e *fore200e;
+
+    fore200e = pci_get_drvdata(pci_dev);
+
+    fore200e_shutdown(fore200e);
+    kfree(fore200e);
+    pci_disable_device(pci_dev);
+}
+
+
+#ifdef CONFIG_ATM_FORE200E_PCA
+static struct pci_device_id fore200e_pca_tbl[] = {
+    { PCI_VENDOR_ID_FORE, PCI_DEVICE_ID_FORE_PCA200E, PCI_ANY_ID, PCI_ANY_ID,
+      0, 0, (unsigned long) &fore200e_bus[0] },
+    { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, fore200e_pca_tbl);
+
+static struct pci_driver fore200e_pca_driver = {
+    .name =     "fore_200e",
+    .probe =    fore200e_pca_detect,
+    .remove =   __devexit_p(fore200e_pca_remove_one),
+    .id_table = fore200e_pca_tbl,
+};
+#endif
+
+
 static int __init
 fore200e_module_init(void)
 {
     const struct fore200e_bus* bus;
     struct       fore200e*     fore200e;
-    int                        index, link;
+    int                        index;
 
     printk(FORE200E "FORE Systems 200E-series ATM driver - version " FORE200E_VERSION "\n");
 
     /* for each configured bus interface */
-    for (link = 0, bus = fore200e_bus; bus->model_name; bus++) {
+    for (bus = fore200e_bus; bus->model_name; bus++) {
 
        /* detect all boards present on that bus */
-       for (index = 0; (fore200e = bus->detect(bus, index)); index++) {
+       for (index = 0; bus->detect && (fore200e = bus->detect(bus, index)); index++) {
            
            printk(FORE200E "device %s found at 0x%lx, IRQ %s\n",
                   fore200e->bus->model_name, 
@@ -2796,15 +2804,18 @@ fore200e_module_init(void)
                break;
            }
 
-           link++;
-
-           fore200e->next  = fore200e_boards;
-           fore200e_boards = fore200e;
+           list_add(&fore200e->entry, &fore200e_boards);
        }
     }
 
-    if (link)
-        return 0;
+#ifdef CONFIG_ATM_FORE200E_PCA
+    if (!pci_register_driver(&fore200e_pca_driver))
+       return 0;
+#endif
+
+    if (!list_empty(&fore200e_boards))
+       return 0;
+
     return -ENODEV;
 }
 
@@ -2812,11 +2823,14 @@ fore200e_module_init(void)
 static void __exit
 fore200e_module_cleanup(void)
 {
-    while (fore200e_boards) {
-        struct fore200e* fore200e = fore200e_boards;
+    struct fore200e *fore200e, *next;
 
+#ifdef CONFIG_ATM_FORE200E_PCA
+    pci_unregister_driver(&fore200e_pca_driver);
+#endif
+
+    list_for_each_entry_safe(fore200e, next, &fore200e_boards, entry) {
        fore200e_shutdown(fore200e);
-       fore200e_boards = fore200e->next;
        kfree(fore200e);
     }
     DPRINTK(1, "module being removed\n");
@@ -2853,7 +2867,7 @@ fore200e_proc_read(struct atm_dev *dev, loff_t* pos, char* page)
                "   board serial number:\t\t%d\n\n",
                fore200e_irq_itoa(fore200e->irq),
                (void*)fore200e->phys_base,
-               (void*)fore200e->virt_base,
+               fore200e->virt_base,
                fore200e->esi[0], fore200e->esi[1], fore200e->esi[2],
                fore200e->esi[3], fore200e->esi[4], fore200e->esi[5],
                fore200e->esi[4] * 256 + fore200e->esi[5]);
@@ -2937,7 +2951,7 @@ fore200e_proc_read(struct atm_dev *dev, loff_t* pos, char* page)
     }
 
     if (!left--) {
-       struct cp_monitor* cp_monitor = fore200e->cp_monitor;
+       struct cp_monitor __iomem * cp_monitor = fore200e->cp_monitor;
 
        return sprintf(page,
                       "\n\n"
@@ -2955,8 +2969,8 @@ fore200e_proc_read(struct atm_dev *dev, loff_t* pos, char* page)
                       "  4b5b:\n"
                       "     crc_header_errors:\t\t%10u\n"
                       "     framing_errors:\t\t%10u\n",
-                      fore200e_swap(fore200e->stats->phy.crc_header_errors),
-                      fore200e_swap(fore200e->stats->phy.framing_errors));
+                      cpu_to_be32(fore200e->stats->phy.crc_header_errors),
+                      cpu_to_be32(fore200e->stats->phy.framing_errors));
     
     if (!left--)
        return sprintf(page, "\n"
@@ -2968,13 +2982,13 @@ fore200e_proc_read(struct atm_dev *dev, loff_t* pos, char* page)
                       "     path_febe_errors:\t\t%10u\n"
                       "     corr_hcs_errors:\t\t%10u\n"
                       "     ucorr_hcs_errors:\t\t%10u\n",
-                      fore200e_swap(fore200e->stats->oc3.section_bip8_errors),
-                      fore200e_swap(fore200e->stats->oc3.path_bip8_errors),
-                      fore200e_swap(fore200e->stats->oc3.line_bip24_errors),
-                      fore200e_swap(fore200e->stats->oc3.line_febe_errors),
-                      fore200e_swap(fore200e->stats->oc3.path_febe_errors),
-                      fore200e_swap(fore200e->stats->oc3.corr_hcs_errors),
-                      fore200e_swap(fore200e->stats->oc3.ucorr_hcs_errors));
+                      cpu_to_be32(fore200e->stats->oc3.section_bip8_errors),
+                      cpu_to_be32(fore200e->stats->oc3.path_bip8_errors),
+                      cpu_to_be32(fore200e->stats->oc3.line_bip24_errors),
+                      cpu_to_be32(fore200e->stats->oc3.line_febe_errors),
+                      cpu_to_be32(fore200e->stats->oc3.path_febe_errors),
+                      cpu_to_be32(fore200e->stats->oc3.corr_hcs_errors),
+                      cpu_to_be32(fore200e->stats->oc3.ucorr_hcs_errors));
 
     if (!left--)
        return sprintf(page,"\n"
@@ -2985,12 +2999,12 @@ fore200e_proc_read(struct atm_dev *dev, loff_t* pos, char* page)
                       "     vpi no conn:\t\t%10u\n"
                       "     vci out of range:\t\t%10u\n"
                       "     vci no conn:\t\t%10u\n",
-                      fore200e_swap(fore200e->stats->atm.cells_transmitted),
-                      fore200e_swap(fore200e->stats->atm.cells_received),
-                      fore200e_swap(fore200e->stats->atm.vpi_bad_range),
-                      fore200e_swap(fore200e->stats->atm.vpi_no_conn),
-                      fore200e_swap(fore200e->stats->atm.vci_bad_range),
-                      fore200e_swap(fore200e->stats->atm.vci_no_conn));
+                      cpu_to_be32(fore200e->stats->atm.cells_transmitted),
+                      cpu_to_be32(fore200e->stats->atm.cells_received),
+                      cpu_to_be32(fore200e->stats->atm.vpi_bad_range),
+                      cpu_to_be32(fore200e->stats->atm.vpi_no_conn),
+                      cpu_to_be32(fore200e->stats->atm.vci_bad_range),
+                      cpu_to_be32(fore200e->stats->atm.vci_no_conn));
     
     if (!left--)
        return sprintf(page,"\n"
@@ -2998,9 +3012,9 @@ fore200e_proc_read(struct atm_dev *dev, loff_t* pos, char* page)
                       "     TX:\t\t\t%10u\n"
                       "     RX:\t\t\t%10u\n"
                       "     dropped:\t\t\t%10u\n",
-                      fore200e_swap(fore200e->stats->aal0.cells_transmitted),
-                      fore200e_swap(fore200e->stats->aal0.cells_received),
-                      fore200e_swap(fore200e->stats->aal0.cells_dropped));
+                      cpu_to_be32(fore200e->stats->aal0.cells_transmitted),
+                      cpu_to_be32(fore200e->stats->aal0.cells_received),
+                      cpu_to_be32(fore200e->stats->aal0.cells_dropped));
     
     if (!left--)
        return sprintf(page,"\n"
@@ -3016,15 +3030,15 @@ fore200e_proc_read(struct atm_dev *dev, loff_t* pos, char* page)
                       "       RX:\t\t\t%10u\n"
                       "       dropped:\t\t\t%10u\n"
                       "       protocol errors:\t\t%10u\n",
-                      fore200e_swap(fore200e->stats->aal34.cells_transmitted),
-                      fore200e_swap(fore200e->stats->aal34.cells_received),
-                      fore200e_swap(fore200e->stats->aal34.cells_dropped),
-                      fore200e_swap(fore200e->stats->aal34.cells_crc_errors),
-                      fore200e_swap(fore200e->stats->aal34.cells_protocol_errors),
-                      fore200e_swap(fore200e->stats->aal34.cspdus_transmitted),
-                      fore200e_swap(fore200e->stats->aal34.cspdus_received),
-                      fore200e_swap(fore200e->stats->aal34.cspdus_dropped),
-                      fore200e_swap(fore200e->stats->aal34.cspdus_protocol_errors));
+                      cpu_to_be32(fore200e->stats->aal34.cells_transmitted),
+                      cpu_to_be32(fore200e->stats->aal34.cells_received),
+                      cpu_to_be32(fore200e->stats->aal34.cells_dropped),
+                      cpu_to_be32(fore200e->stats->aal34.cells_crc_errors),
+                      cpu_to_be32(fore200e->stats->aal34.cells_protocol_errors),
+                      cpu_to_be32(fore200e->stats->aal34.cspdus_transmitted),
+                      cpu_to_be32(fore200e->stats->aal34.cspdus_received),
+                      cpu_to_be32(fore200e->stats->aal34.cspdus_dropped),
+                      cpu_to_be32(fore200e->stats->aal34.cspdus_protocol_errors));
     
     if (!left--)
        return sprintf(page,"\n"
@@ -3040,15 +3054,15 @@ fore200e_proc_read(struct atm_dev *dev, loff_t* pos, char* page)
                       "       dropped:\t\t\t%10u\n"
                       "       CRC errors:\t\t%10u\n"
                       "       protocol errors:\t\t%10u\n",
-                      fore200e_swap(fore200e->stats->aal5.cells_transmitted),
-                      fore200e_swap(fore200e->stats->aal5.cells_received),
-                      fore200e_swap(fore200e->stats->aal5.cells_dropped),
-                      fore200e_swap(fore200e->stats->aal5.congestion_experienced),
-                      fore200e_swap(fore200e->stats->aal5.cspdus_transmitted),
-                      fore200e_swap(fore200e->stats->aal5.cspdus_received),
-                      fore200e_swap(fore200e->stats->aal5.cspdus_dropped),
-                      fore200e_swap(fore200e->stats->aal5.cspdus_crc_errors),
-                      fore200e_swap(fore200e->stats->aal5.cspdus_protocol_errors));
+                      cpu_to_be32(fore200e->stats->aal5.cells_transmitted),
+                      cpu_to_be32(fore200e->stats->aal5.cells_received),
+                      cpu_to_be32(fore200e->stats->aal5.cells_dropped),
+                      cpu_to_be32(fore200e->stats->aal5.congestion_experienced),
+                      cpu_to_be32(fore200e->stats->aal5.cspdus_transmitted),
+                      cpu_to_be32(fore200e->stats->aal5.cspdus_received),
+                      cpu_to_be32(fore200e->stats->aal5.cspdus_dropped),
+                      cpu_to_be32(fore200e->stats->aal5.cspdus_crc_errors),
+                      cpu_to_be32(fore200e->stats->aal5.cspdus_protocol_errors));
     
     if (!left--)
        return sprintf(page,"\n"
@@ -3059,11 +3073,11 @@ fore200e_proc_read(struct atm_dev *dev, loff_t* pos, char* page)
                       "     large b2:\t\t\t%10u\n"
                       "     RX PDUs:\t\t\t%10u\n"
                       "     TX PDUs:\t\t\t%10lu\n",
-                      fore200e_swap(fore200e->stats->aux.small_b1_failed),
-                      fore200e_swap(fore200e->stats->aux.large_b1_failed),
-                      fore200e_swap(fore200e->stats->aux.small_b2_failed),
-                      fore200e_swap(fore200e->stats->aux.large_b2_failed),
-                      fore200e_swap(fore200e->stats->aux.rpd_alloc_failed),
+                      cpu_to_be32(fore200e->stats->aux.small_b1_failed),
+                      cpu_to_be32(fore200e->stats->aux.large_b1_failed),
+                      cpu_to_be32(fore200e->stats->aux.small_b2_failed),
+                      cpu_to_be32(fore200e->stats->aux.large_b2_failed),
+                      cpu_to_be32(fore200e->stats->aux.rpd_alloc_failed),
                       fore200e->tx_sat);
     
     if (!left--)
@@ -3151,7 +3165,7 @@ static const struct fore200e_bus fore200e_bus[] = {
       fore200e_pca_dma_sync_for_device,
       fore200e_pca_dma_chunk_alloc,
       fore200e_pca_dma_chunk_free,
-      fore200e_pca_detect,
+      NULL,
       fore200e_pca_configure,
       fore200e_pca_map,
       fore200e_pca_reset,