#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");
static void*
-fore200e_kmalloc(int size, int flags)
+fore200e_kmalloc(int size, gfp_t flags)
{
- void* chunk = kmalloc(size, flags);
+ void *chunk = kzalloc(size, flags);
- if (chunk)
- memset(chunk, 0x00, size);
- else
- printk(FORE200E "kmalloc() failed, requested size = %d, flags = 0x%x\n", size, flags);
+ if (!chunk)
+ printk(FORE200E "kmalloc() failed, requested size = %d, flags = 0x%x\n", size, flags);
return chunk;
}
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));
}
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();
static int
-fore200e_io_poll(struct fore200e* fore200e, volatile u32* addr, 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 {
{
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);
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);
#ifdef CONFIG_ATM_FORE200E_PCA
-static u32 fore200e_pca_read(volatile u32* addr)
+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 */
}
-static void fore200e_pca_write(u32 val, volatile u32* addr)
+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 */
}
-static int __init
+static int __devinit
fore200e_pca_map(struct fore200e* fore200e)
{
DPRINTK(2, "device %s being mapped in memory\n", fore200e->name);
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;
}
-static int __init
+static int __devinit
fore200e_pca_configure(struct fore200e* fore200e)
{
struct pci_dev* pci_dev = (struct pci_dev*)fore200e->bus_dev;
}
-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)
{
*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);
#ifdef CONFIG_ATM_FORE200E_SBA
static u32
-fore200e_sba_read(volatile u32* addr)
+fore200e_sba_read(volatile u32 __iomem *addr)
{
return sbus_readl(addr);
}
static void
-fore200e_sba_write(u32 val, volatile u32* addr)
+fore200e_sba_write(u32 val, volatile u32 __iomem *addr)
{
sbus_writel(val, addr);
}
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);
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);
}
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,
/* 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
}
#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 */
return -ENOMEM;
}
- do_gettimeofday(&skb->stamp);
+ __net_timestamp(skb);
#ifdef FORE200E_52BYTE_AAL0_SDU
if (cell_header) {
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;
}
#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);
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);
/* retry once again? */
if (--retry > 0) {
- schedule();
+ udelay(50);
goto retry_here;
}
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);
*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_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);
}
-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) {
}
-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);
}
-static int __init
+static int __devinit
fore200e_alloc_rx_buf(struct fore200e* fore200e)
{
int scheme, magn, nbr, size, i;
}
-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++) {
}
/* 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++) {
}
-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");
}
/* 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++) {
}
-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");
}
/* 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++) {
}
-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");
}
/* 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++) {
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);
}
-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);
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);
}
-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);
}
-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)) {
}
-static void __init
+static void __devinit
fore200e_monitor_puts(struct fore200e* fore200e, char* str)
{
while (*str) {
}
-static int __init
+static int __devinit
fore200e_start_fw(struct fore200e* fore200e)
{
int ok;
}
-static int __init
+static int __devinit
fore200e_load_fw(struct fore200e* fore200e)
{
u32* fw_data = (u32*) fore200e->bus->fw_data;
struct fw_header* fw_header = (struct fw_header*) fw_data;
- u32* load_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);
}
-static int __init
+static int __devinit
fore200e_register(struct fore200e* fore200e)
{
struct atm_dev* atm_dev;
}
-static int __init
+static int __devinit
fore200e_init(struct fore200e* fore200e)
{
if (fore200e_register(fore200e) < 0)
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 = fore200e_kmalloc(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,
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;
}
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");
" 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]);
}
if (!left--) {
- struct cp_monitor* cp_monitor = fore200e->cp_monitor;
+ struct cp_monitor __iomem * cp_monitor = fore200e->cp_monitor;
return sprintf(page,
"\n\n"
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,