vserver 1.9.5.x5
[linux-2.6.git] / drivers / ide / arm / icside.c
index edc9de7..e63ff1d 100644 (file)
@@ -1,7 +1,9 @@
 /*
  * linux/drivers/ide/arm/icside.c
  *
- * Copyright (c) 1996-2003 Russell King.
+ * Copyright (c) 1996-2004 Russell King.
+ *
+ * Please note that this platform does not support 32-bit IDE IO.
  */
 
 #include <linux/config.h>
@@ -16,6 +18,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/device.h>
 #include <linux/init.h>
+#include <linux/scatterlist.h>
 
 #include <asm/dma.h>
 #include <asm/ecard.h>
 
 #define ICS_IDENT_OFFSET               0x2280
 
-#define ICS_ARCIN_V5_INTRSTAT          0x000
-#define ICS_ARCIN_V5_INTROFFSET                0x001
-#define ICS_ARCIN_V5_IDEOFFSET         0xa00
-#define ICS_ARCIN_V5_IDEALTOFFSET      0xae0
-#define ICS_ARCIN_V5_IDESTEPPING       4
-
-#define ICS_ARCIN_V6_IDEOFFSET_1       0x800
-#define ICS_ARCIN_V6_INTROFFSET_1      0x880
-#define ICS_ARCIN_V6_INTRSTAT_1                0x8a4
-#define ICS_ARCIN_V6_IDEALTOFFSET_1    0x8e0
-#define ICS_ARCIN_V6_IDEOFFSET_2       0xc00
-#define ICS_ARCIN_V6_INTROFFSET_2      0xc80
-#define ICS_ARCIN_V6_INTRSTAT_2                0xca4
-#define ICS_ARCIN_V6_IDEALTOFFSET_2    0xce0
-#define ICS_ARCIN_V6_IDESTEPPING       4
+#define ICS_ARCIN_V5_INTRSTAT          0x0000
+#define ICS_ARCIN_V5_INTROFFSET                0x0004
+#define ICS_ARCIN_V5_IDEOFFSET         0x2800
+#define ICS_ARCIN_V5_IDEALTOFFSET      0x2b80
+#define ICS_ARCIN_V5_IDESTEPPING       6
+
+#define ICS_ARCIN_V6_IDEOFFSET_1       0x2000
+#define ICS_ARCIN_V6_INTROFFSET_1      0x2200
+#define ICS_ARCIN_V6_INTRSTAT_1                0x2290
+#define ICS_ARCIN_V6_IDEALTOFFSET_1    0x2380
+#define ICS_ARCIN_V6_IDEOFFSET_2       0x3000
+#define ICS_ARCIN_V6_INTROFFSET_2      0x3200
+#define ICS_ARCIN_V6_INTRSTAT_2                0x3290
+#define ICS_ARCIN_V6_IDEALTOFFSET_2    0x3380
+#define ICS_ARCIN_V6_IDESTEPPING       6
 
 struct cardinfo {
        unsigned int dataoffset;
@@ -46,28 +49,28 @@ struct cardinfo {
 };
 
 static struct cardinfo icside_cardinfo_v5 = {
-       ICS_ARCIN_V5_IDEOFFSET,
-       ICS_ARCIN_V5_IDEALTOFFSET,
-       ICS_ARCIN_V5_IDESTEPPING
+       .dataoffset     = ICS_ARCIN_V5_IDEOFFSET,
+       .ctrloffset     = ICS_ARCIN_V5_IDEALTOFFSET,
+       .stepping       = ICS_ARCIN_V5_IDESTEPPING,
 };
 
 static struct cardinfo icside_cardinfo_v6_1 = {
-       ICS_ARCIN_V6_IDEOFFSET_1,
-       ICS_ARCIN_V6_IDEALTOFFSET_1,
-       ICS_ARCIN_V6_IDESTEPPING
+       .dataoffset     = ICS_ARCIN_V6_IDEOFFSET_1,
+       .ctrloffset     = ICS_ARCIN_V6_IDEALTOFFSET_1,
+       .stepping       = ICS_ARCIN_V6_IDESTEPPING,
 };
 
 static struct cardinfo icside_cardinfo_v6_2 = {
-       ICS_ARCIN_V6_IDEOFFSET_2,
-       ICS_ARCIN_V6_IDEALTOFFSET_2,
-       ICS_ARCIN_V6_IDESTEPPING
+       .dataoffset     = ICS_ARCIN_V6_IDEOFFSET_2,
+       .ctrloffset     = ICS_ARCIN_V6_IDEALTOFFSET_2,
+       .stepping       = ICS_ARCIN_V6_IDESTEPPING,
 };
 
 struct icside_state {
        unsigned int channel;
        unsigned int enabled;
-       unsigned long irq_port;
-       unsigned long slot_port;
+       void __iomem *irq_port;
+       void __iomem *ioc_base;
        unsigned int type;
        /* parent device... until the IDE core gets one of its own */
        struct device *dev;
@@ -87,9 +90,8 @@ struct icside_state {
 static void icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr)
 {
        struct icside_state *state = ec->irq_data;
-       unsigned int base = state->irq_port;
 
-       outb(0, base + ICS_ARCIN_V5_INTROFFSET);
+       writeb(0, state->irq_port + ICS_ARCIN_V5_INTROFFSET);
 }
 
 /* Prototype: icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr)
@@ -98,9 +100,8 @@ static void icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr)
 static void icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr)
 {
        struct icside_state *state = ec->irq_data;
-       unsigned int base = state->irq_port;
 
-       inb(base + ICS_ARCIN_V5_INTROFFSET);
+       readb(state->irq_port + ICS_ARCIN_V5_INTROFFSET);
 }
 
 static const expansioncard_ops_t icside_ops_arcin_v5 = {
@@ -116,18 +117,18 @@ static const expansioncard_ops_t icside_ops_arcin_v5 = {
 static void icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr)
 {
        struct icside_state *state = ec->irq_data;
-       unsigned int base = state->irq_port;
+       void __iomem *base = state->irq_port;
 
        state->enabled = 1;
 
        switch (state->channel) {
        case 0:
-               outb(0, base + ICS_ARCIN_V6_INTROFFSET_1);
-               inb(base + ICS_ARCIN_V6_INTROFFSET_2);
+               writeb(0, base + ICS_ARCIN_V6_INTROFFSET_1);
+               readb(base + ICS_ARCIN_V6_INTROFFSET_2);
                break;
        case 1:
-               outb(0, base + ICS_ARCIN_V6_INTROFFSET_2);
-               inb(base + ICS_ARCIN_V6_INTROFFSET_1);
+               writeb(0, base + ICS_ARCIN_V6_INTROFFSET_2);
+               readb(base + ICS_ARCIN_V6_INTROFFSET_1);
                break;
        }
 }
@@ -141,8 +142,8 @@ static void icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr)
 
        state->enabled = 0;
 
-       inb (state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
-       inb (state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
+       readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
+       readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
 }
 
 /* Prototype: icside_irqprobe(struct expansion_card *ec)
@@ -152,8 +153,8 @@ static int icside_irqpending_arcin_v6(struct expansion_card *ec)
 {
        struct icside_state *state = ec->irq_data;
 
-       return inb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 ||
-              inb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_2) & 1;
+       return readb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 ||
+              readb(state->irq_port + ICS_ARCIN_V6_INTRSTAT_2) & 1;
 }
 
 static const expansioncard_ops_t icside_ops_arcin_v6 = {
@@ -179,23 +180,28 @@ static void icside_maskproc(ide_drive_t *drive, int mask)
        if (state->enabled && !mask) {
                switch (hwif->channel) {
                case 0:
-                       outb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
-                       inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
+                       writeb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
+                       readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
                        break;
                case 1:
-                       outb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
-                       inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
+                       writeb(0, state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
+                       readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
                        break;
                }
        } else {
-               inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
-               inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
+               readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
+               readb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
        }
 
        local_irq_restore(flags);
 }
 
 #ifdef CONFIG_BLK_DEV_IDEDMA_ICS
+
+#ifndef CONFIG_IDEDMA_ICS_AUTO
+#warning CONFIG_IDEDMA_ICS_AUTO=n support is obsolete, and will be removed soon.
+#endif
+
 /*
  * SG-DMA support.
  *
@@ -205,44 +211,24 @@ static void icside_maskproc(ide_drive_t *drive, int mask)
  * here, but we rely on the main IDE driver spotting that both
  * interfaces use the same IRQ, which should guarantee this.
  */
-#define NR_ENTRIES 256
-#define TABLE_SIZE (NR_ENTRIES * 8)
 
 static void icside_build_sglist(ide_drive_t *drive, struct request *rq)
 {
        ide_hwif_t *hwif = drive->hwif;
        struct icside_state *state = hwif->hwif_data;
        struct scatterlist *sg = hwif->sg_table;
-       int nents;
-
-       if (rq->flags & REQ_DRIVE_TASKFILE) {
-               ide_task_t *args = rq->special;
-
-               if (args->command_type == IDE_DRIVE_TASK_RAW_WRITE)
-                       hwif->sg_dma_direction = DMA_TO_DEVICE;
-               else
-                       hwif->sg_dma_direction = DMA_FROM_DEVICE;
-
-               memset(sg, 0, sizeof(*sg));
-               sg->page   = virt_to_page(rq->buffer);
-               sg->offset = offset_in_page(rq->buffer);
-               sg->length = rq->nr_sectors * SECTOR_SIZE;
-               nents = 1;
-       } else {
-               nents = blk_rq_map_sg(drive->queue, rq, sg);
 
-               if (rq_data_dir(rq) == READ)
-                       hwif->sg_dma_direction = DMA_FROM_DEVICE;
-               else
-                       hwif->sg_dma_direction = DMA_TO_DEVICE;
-       }
+       ide_map_sg(drive, rq);
 
-       nents = dma_map_sg(state->dev, sg, nents, hwif->sg_dma_direction);
+       if (rq_data_dir(rq) == READ)
+               hwif->sg_dma_direction = DMA_FROM_DEVICE;
+       else
+               hwif->sg_dma_direction = DMA_TO_DEVICE;
 
-       hwif->sg_nents = nents;
+       hwif->sg_nents = dma_map_sg(state->dev, sg, hwif->sg_nents,
+                                   hwif->sg_dma_direction);
 }
 
-
 /*
  * Configure the IOMD to give the appropriate timings for the transfer
  * mode being requested.  We take the advice of the ATA standards, and
@@ -402,50 +388,25 @@ static int icside_dma_end(ide_drive_t *drive)
        return get_dma_residue(hwif->hw.dma) != 0;
 }
 
-static int icside_dma_begin(ide_drive_t *drive)
+static void icside_dma_start(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = HWIF(drive);
 
        /* We can not enable DMA on both channels simultaneously. */
        BUG_ON(dma_channel_active(hwif->hw.dma));
        enable_dma(hwif->hw.dma);
-       return 0;
 }
 
-/*
- * dma_intr() is the handler for disk read/write DMA interrupts
- */
-static ide_startstop_t icside_dmaintr(ide_drive_t *drive)
-{
-       unsigned int stat;
-       int dma_stat;
-
-       dma_stat = icside_dma_end(drive);
-       stat = HWIF(drive)->INB(IDE_STATUS_REG);
-       if (OK_STAT(stat, DRIVE_READY, drive->bad_wstat | DRQ_STAT)) {
-               if (!dma_stat) {
-                       struct request *rq = HWGROUP(drive)->rq;
-                       int i;
-
-                       for (i = rq->nr_sectors; i > 0; ) {
-                               i -= rq->current_nr_sectors;
-                               DRIVER(drive)->end_request(drive, 1, rq->nr_sectors);
-                       }
-
-                       return ide_stopped;
-               }
-               printk(KERN_ERR "%s: bad DMA status (dma_stat=%x)\n",
-                      drive->name, dma_stat);
-       }
-
-       return DRIVER(drive)->error(drive, __FUNCTION__, stat);
-}
-
-static int
-icside_dma_common(ide_drive_t *drive, struct request *rq,
-                 unsigned int dma_mode)
+static int icside_dma_setup(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = HWIF(drive);
+       struct request *rq = hwif->hwgroup->rq;
+       unsigned int dma_mode;
+
+       if (rq_data_dir(rq))
+               dma_mode = DMA_MODE_WRITE;
+       else
+               dma_mode = DMA_MODE_READ;
 
        /*
         * We can not enable DMA on both channels.
@@ -462,7 +423,7 @@ icside_dma_common(ide_drive_t *drive, struct request *rq,
        /*
         * Route the DMA signals to the correct interface.
         */
-       outb(hwif->select_data, hwif->config_data);
+       writeb(hwif->select_data, hwif->config_data);
 
        /*
         * Select the correct timing for this drive.
@@ -481,79 +442,10 @@ icside_dma_common(ide_drive_t *drive, struct request *rq,
        return 0;
 }
 
-static int icside_dma_read(ide_drive_t *drive)
+static void icside_dma_exec_cmd(ide_drive_t *drive, u8 cmd)
 {
-       struct request *rq = HWGROUP(drive)->rq;
-       task_ioreg_t cmd;
-
-       if (icside_dma_common(drive, rq, DMA_MODE_READ))
-               return 1;
-
-       if (drive->media != ide_disk)
-               return 0;
-
-       BUG_ON(HWGROUP(drive)->handler != NULL);
-
-       /*
-        * FIX ME to use only ACB ide_task_t args Struct
-        */
-#if 0
-       {
-               ide_task_t *args = rq->special;
-               cmd = args->tfRegister[IDE_COMMAND_OFFSET];
-       }
-#else
-       if (rq->flags & REQ_DRIVE_TASKFILE) {
-               ide_task_t *args = rq->special;
-               cmd = args->tfRegister[IDE_COMMAND_OFFSET];
-       } else if (drive->addressing == 1) {
-               cmd = WIN_READDMA_EXT;
-       } else {
-               cmd = WIN_READDMA;
-       }
-#endif
-       /* issue cmd to drive */
-       ide_execute_command(drive, cmd, icside_dmaintr, 2*WAIT_CMD, NULL);
-
-       return icside_dma_begin(drive);
-}
-
-static int icside_dma_write(ide_drive_t *drive)
-{
-       struct request *rq = HWGROUP(drive)->rq;
-       task_ioreg_t cmd;
-
-       if (icside_dma_common(drive, rq, DMA_MODE_WRITE))
-               return 1;
-
-       if (drive->media != ide_disk)
-               return 0;
-
-       BUG_ON(HWGROUP(drive)->handler != NULL);
-
-       /*
-        * FIX ME to use only ACB ide_task_t args Struct
-        */
-#if 0
-       {
-               ide_task_t *args = rq->special;
-               cmd = args->tfRegister[IDE_COMMAND_OFFSET];
-       }
-#else
-       if (rq->flags & REQ_DRIVE_TASKFILE) {
-               ide_task_t *args = rq->special;
-               cmd = args->tfRegister[IDE_COMMAND_OFFSET];
-       } else if (drive->addressing == 1) {
-               cmd = WIN_WRITEDMA_EXT;
-       } else {
-               cmd = WIN_WRITEDMA;
-       }
-#endif
-
        /* issue cmd to drive */
-       ide_execute_command(drive, cmd, icside_dmaintr, 2*WAIT_CMD, NULL);
-
-       return icside_dma_begin(drive);
+       ide_execute_command(drive, cmd, ide_dma_intr, 2 * WAIT_CMD, NULL);
 }
 
 static int icside_dma_test_irq(ide_drive_t *drive)
@@ -561,20 +453,12 @@ static int icside_dma_test_irq(ide_drive_t *drive)
        ide_hwif_t *hwif = HWIF(drive);
        struct icside_state *state = hwif->hwif_data;
 
-       return inb(state->irq_port +
-                  (hwif->channel ?
+       return readb(state->irq_port +
+                    (hwif->channel ?
                        ICS_ARCIN_V6_INTRSTAT_2 :
                        ICS_ARCIN_V6_INTRSTAT_1)) & 1;
 }
 
-static int icside_dma_verbose(ide_drive_t *drive)
-{
-       printk(", %s (peak %dMB/s)",
-               ide_xfer_verbose(drive->current_speed),
-               2000 / drive->drive_data);
-       return 1;
-}
-
 static int icside_dma_timeout(ide_drive_t *drive)
 {
        printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name);
@@ -594,7 +478,7 @@ static int icside_dma_lostirq(ide_drive_t *drive)
        return 1;
 }
 
-static int icside_dma_init(ide_hwif_t *hwif)
+static void icside_dma_init(ide_hwif_t *hwif)
 {
        int autodma = 0;
 
@@ -604,11 +488,6 @@ static int icside_dma_init(ide_hwif_t *hwif)
 
        printk("    %s: SG-DMA", hwif->name);
 
-       hwif->sg_table = kmalloc(sizeof(struct scatterlist) * NR_ENTRIES,
-                                GFP_KERNEL);
-       if (!hwif->sg_table)
-               goto failed;
-
        hwif->atapi_dma         = 1;
        hwif->mwdma_mask        = 7; /* MW0..2 */
        hwif->swdma_mask        = 7; /* SW0..2 */
@@ -623,12 +502,11 @@ static int icside_dma_init(ide_hwif_t *hwif)
        hwif->ide_dma_off_quietly = icside_dma_off_quietly;
        hwif->ide_dma_host_on   = icside_dma_host_on;
        hwif->ide_dma_on        = icside_dma_on;
-       hwif->ide_dma_read      = icside_dma_read;
-       hwif->ide_dma_write     = icside_dma_write;
-       hwif->ide_dma_begin     = icside_dma_begin;
+       hwif->dma_setup         = icside_dma_setup;
+       hwif->dma_exec_cmd      = icside_dma_exec_cmd;
+       hwif->dma_start         = icside_dma_start;
        hwif->ide_dma_end       = icside_dma_end;
        hwif->ide_dma_test_irq  = icside_dma_test_irq;
-       hwif->ide_dma_verbose   = icside_dma_verbose;
        hwif->ide_dma_timeout   = icside_dma_timeout;
        hwif->ide_dma_lostirq   = icside_dma_lostirq;
 
@@ -636,24 +514,9 @@ static int icside_dma_init(ide_hwif_t *hwif)
        hwif->drives[1].autodma = hwif->autodma;
 
        printk(" capable%s\n", hwif->autodma ? ", auto-enable" : "");
-
-       return 1;
-
-failed:
-       printk(" disabled, unable to allocate DMA table\n");
-       return 0;
-}
-
-static void icside_dma_exit(ide_hwif_t *hwif)
-{
-       if (hwif->sg_table) {
-               kfree(hwif->sg_table);
-               hwif->sg_table = NULL;
-       }
 }
 #else
 #define icside_dma_init(hwif)  (0)
-#define icside_dma_exit(hwif)  do { } while (0)
 #endif
 
 static ide_hwif_t *icside_find_hwif(unsigned long dataport)
@@ -679,24 +542,30 @@ found:
 }
 
 static ide_hwif_t *
-icside_setup(unsigned long base, struct cardinfo *info, struct expansion_card *ec)
+icside_setup(void __iomem *base, struct cardinfo *info, struct expansion_card *ec)
 {
-       unsigned long port = base + info->dataoffset;
+       unsigned long port = (unsigned long)base + info->dataoffset;
        ide_hwif_t *hwif;
 
-       hwif = icside_find_hwif(base);
+       hwif = icside_find_hwif(port);
        if (hwif) {
                int i;
 
                memset(&hwif->hw, 0, sizeof(hw_regs_t));
 
+               /*
+                * Ensure we're using MMIO
+                */
+               default_hwif_mmiops(hwif);
+               hwif->mmio = 2;
+
                for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
                        hwif->hw.io_ports[i] = port;
                        hwif->io_ports[i] = port;
                        port += 1 << info->stepping;
                }
-               hwif->hw.io_ports[IDE_CONTROL_OFFSET] = base + info->ctrloffset;
-               hwif->io_ports[IDE_CONTROL_OFFSET] = base + info->ctrloffset;
+               hwif->hw.io_ports[IDE_CONTROL_OFFSET] = (unsigned long)base + info->ctrloffset;
+               hwif->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)base + info->ctrloffset;
                hwif->hw.irq  = ec->irq;
                hwif->irq     = ec->irq;
                hwif->noprobe = 0;
@@ -710,14 +579,17 @@ icside_setup(unsigned long base, struct cardinfo *info, struct expansion_card *e
 static int __init
 icside_register_v5(struct icside_state *state, struct expansion_card *ec)
 {
-       unsigned long slot_port;
        ide_hwif_t *hwif;
+       void __iomem *base;
 
-       slot_port = ecard_address(ec, ECARD_MEMC, 0);
+       base = ioremap(ecard_resource_start(ec, ECARD_RES_MEMC),
+                      ecard_resource_len(ec, ECARD_RES_MEMC));
+       if (!base)
+               return -ENOMEM;
 
-       state->irq_port = slot_port;
+       state->irq_port = base;
 
-       ec->irqaddr  = (unsigned char *)ioaddr(slot_port + ICS_ARCIN_V5_INTRSTAT);
+       ec->irqaddr  = base + ICS_ARCIN_V5_INTRSTAT;
        ec->irqmask  = 1;
        ec->irq_data = state;
        ec->ops      = &icside_ops_arcin_v5;
@@ -725,61 +597,86 @@ icside_register_v5(struct icside_state *state, struct expansion_card *ec)
        /*
         * Be on the safe side - disable interrupts
         */
-       inb(slot_port + ICS_ARCIN_V5_INTROFFSET);
+       icside_irqdisable_arcin_v5(ec, 0);
 
-       hwif = icside_setup(slot_port, &icside_cardinfo_v5, ec);
+       hwif = icside_setup(base, &icside_cardinfo_v5, ec);
+       if (!hwif) {
+               iounmap(base);
+               return -ENODEV;
+       }
 
        state->hwif[0] = hwif;
 
-       return hwif ? 0 : -ENODEV;
+       probe_hwif_init(hwif);
+       create_proc_ide_interfaces();
+
+       return 0;
 }
 
 static int __init
 icside_register_v6(struct icside_state *state, struct expansion_card *ec)
 {
-       unsigned long slot_port, port;
        ide_hwif_t *hwif, *mate;
+       void __iomem *ioc_base, *easi_base;
        unsigned int sel = 0;
+       int ret;
 
-       slot_port = ecard_address(ec, ECARD_IOC, ECARD_FAST);
-       port      = ecard_address(ec, ECARD_EASI, ECARD_FAST);
+       ioc_base = ioremap(ecard_resource_start(ec, ECARD_RES_IOCFAST),
+                          ecard_resource_len(ec, ECARD_RES_IOCFAST));
+       if (!ioc_base) {
+               ret = -ENOMEM;
+               goto out;
+       }
 
-       if (port == 0)
-               port = slot_port;
-       else
+       easi_base = ioc_base;
+
+       if (ecard_resource_flags(ec, ECARD_RES_EASI)) {
+               easi_base = ioremap(ecard_resource_start(ec, ECARD_RES_EASI),
+                                   ecard_resource_len(ec, ECARD_RES_EASI));
+               if (!easi_base) {
+                       ret = -ENOMEM;
+                       goto unmap_slot;
+               }
+
+               /*
+                * Enable access to the EASI region.
+                */
                sel = 1 << 5;
+       }
+
+       writeb(sel, ioc_base);
+
+       ec->irq_data      = state;
+       ec->ops           = &icside_ops_arcin_v6;
 
-       outb(sel, slot_port);
+       state->irq_port   = easi_base;
+       state->ioc_base   = ioc_base;
 
        /*
         * Be on the safe side - disable interrupts
         */
-       inb(port + ICS_ARCIN_V6_INTROFFSET_1);
-       inb(port + ICS_ARCIN_V6_INTROFFSET_2);
+       icside_irqdisable_arcin_v6(ec, 0);
 
        /*
         * Find and register the interfaces.
         */
-       hwif = icside_setup(port, &icside_cardinfo_v6_1, ec);
-       mate = icside_setup(port, &icside_cardinfo_v6_2, ec);
+       hwif = icside_setup(easi_base, &icside_cardinfo_v6_1, ec);
+       mate = icside_setup(easi_base, &icside_cardinfo_v6_2, ec);
 
-       if (!hwif || !mate)
-               return -ENODEV;
+       if (!hwif || !mate) {
+               ret = -ENODEV;
+               goto unmap_port;
+       }
 
-       state->irq_port   = port;
-       state->slot_port  = slot_port;
        state->hwif[0]    = hwif;
        state->hwif[1]    = mate;
 
-       ec->irq_data      = state;
-       ec->ops           = &icside_ops_arcin_v6;
-
        hwif->maskproc    = icside_maskproc;
        hwif->channel     = 0;
        hwif->hwif_data   = state;
        hwif->mate        = mate;
        hwif->serialized  = 1;
-       hwif->config_data = slot_port;
+       hwif->config_data = (unsigned long)ioc_base;
        hwif->select_data = sel;
        hwif->hw.dma      = ec->dma;
 
@@ -788,7 +685,7 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
        mate->hwif_data   = state;
        mate->mate        = hwif;
        mate->serialized  = 1;
-       mate->config_data = slot_port;
+       mate->config_data = (unsigned long)ioc_base;
        mate->select_data = sel | 1;
        mate->hw.dma      = ec->dma;
 
@@ -797,7 +694,19 @@ icside_register_v6(struct icside_state *state, struct expansion_card *ec)
                icside_dma_init(mate);
        }
 
+       probe_hwif_init(hwif);
+       probe_hwif_init(mate);
+       create_proc_ide_interfaces();
+
        return 0;
+
+ unmap_port:
+       if (easi_base != ioc_base)
+               iounmap(easi_base);
+ unmap_slot:
+       iounmap(ioc_base);
+ out:
+       return ret;
 }
 
 static int __devinit
@@ -807,10 +716,14 @@ icside_probe(struct expansion_card *ec, const struct ecard_id *id)
        void *idmem;
        int ret;
 
+       ret = ecard_request_resources(ec);
+       if (ret)
+               goto out;
+
        state = kmalloc(sizeof(struct icside_state), GFP_KERNEL);
        if (!state) {
                ret = -ENOMEM;
-               goto out;
+               goto release;
        }
 
        memset(state, 0, sizeof(state));
@@ -833,12 +746,12 @@ icside_probe(struct expansion_card *ec, const struct ecard_id *id)
 
        switch (state->type) {
        case ICS_TYPE_A3IN:
-               printk(KERN_WARNING "icside: A3IN unsupported\n");
+               dev_warn(&ec->dev, "A3IN unsupported\n");
                ret = -ENODEV;
                break;
 
        case ICS_TYPE_A3USER:
-               printk(KERN_WARNING "icside: A3USER unsupported\n");
+               dev_warn(&ec->dev, "A3USER unsupported\n");
                ret = -ENODEV;
                break;
 
@@ -851,15 +764,19 @@ icside_probe(struct expansion_card *ec, const struct ecard_id *id)
                break;
 
        default:
-               printk(KERN_WARNING "icside: unknown interface type\n");
+               dev_warn(&ec->dev, "unknown interface type\n");
                ret = -ENODEV;
                break;
        }
 
-       if (ret == 0)
+       if (ret == 0) {
                ecard_set_drvdata(ec, state);
-       else
-               kfree(state);
+               goto out;
+       }
+
+       kfree(state);
+ release:
+       ecard_release_resources(ec);
  out:
        return ret;
 }
@@ -873,23 +790,19 @@ static void __devexit icside_remove(struct expansion_card *ec)
                /* FIXME: tell IDE to stop using the interface */
 
                /* Disable interrupts */
-               inb(state->slot_port + ICS_ARCIN_V5_INTROFFSET);
+               icside_irqdisable_arcin_v5(ec, 0);
                break;
 
        case ICS_TYPE_V6:
                /* FIXME: tell IDE to stop using the interface */
-               icside_dma_exit(state->hwif[1]);
-               icside_dma_exit(state->hwif[0]);
-
                if (ec->dma != NO_DMA)
                        free_dma(ec->dma);
 
                /* Disable interrupts */
-               inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
-               inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
+               icside_irqdisable_arcin_v6(ec, 0);
 
                /* Reset the ROM pointer/EASI selection */
-               outb(0, state->slot_port);
+               writeb(0, state->ioc_base);
                break;
        }
 
@@ -897,28 +810,36 @@ static void __devexit icside_remove(struct expansion_card *ec)
        ec->ops = NULL;
        ec->irq_data = NULL;
 
+       if (state->ioc_base)
+               iounmap(state->ioc_base);
+       if (state->ioc_base != state->irq_port)
+               iounmap(state->irq_port);
+
        kfree(state);
+       ecard_release_resources(ec);
 }
 
 static void icside_shutdown(struct expansion_card *ec)
 {
        struct icside_state *state = ecard_get_drvdata(ec);
+       unsigned long flags;
 
-       switch (state->type) {
-       case ICS_TYPE_V5:
-               /* Disable interrupts */
-               inb(state->slot_port + ICS_ARCIN_V5_INTROFFSET);
-               break;
-
-       case ICS_TYPE_V6:
-               /* Disable interrupts */
-               inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_1);
-               inb(state->irq_port + ICS_ARCIN_V6_INTROFFSET_2);
+       /*
+        * Disable interrupts from this card.  We need to do
+        * this before disabling EASI since we may be accessing
+        * this register via that region.
+        */
+       local_irq_save(flags);
+       ec->ops->irqdisable(ec, 0);
+       local_irq_restore(flags);
 
-               /* Reset the ROM pointer/EASI selection */
-               outb(0, state->slot_port);
-               break;
-       }
+       /*
+        * Reset the ROM pointer so that we can read the ROM
+        * after a soft reboot.  This also disables access to
+        * the IDE taskfile via the EASI region.
+        */
+       if (state->ioc_base)
+               writeb(0, state->ioc_base);
 }
 
 static const struct ecard_id icside_ids[] = {