X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fide%2Farm%2Ficside.c;h=8a1c27f28692c02c6fee0d43899eab4d000f126d;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=edc9de780165121cdfc4613bb19d7f03e990faaf;hpb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;p=linux-2.6.git diff --git a/drivers/ide/arm/icside.c b/drivers/ide/arm/icside.c index edc9de780..8a1c27f28 100644 --- a/drivers/ide/arm/icside.c +++ b/drivers/ide/arm/icside.c @@ -1,10 +1,11 @@ /* * 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 #include #include #include @@ -16,6 +17,7 @@ #include #include #include +#include #include #include @@ -23,21 +25,21 @@ #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 +48,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 +89,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 +99,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 +116,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 +141,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 +152,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 +179,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 +210,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 +387,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 +422,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 +441,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 +452,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 +477,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 +487,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 +501,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 +513,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 +541,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 +578,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 +596,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 +684,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,20 +693,36 @@ 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 icside_probe(struct expansion_card *ec, const struct ecard_id *id) { struct icside_state *state; - void *idmem; + void __iomem *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 +745,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 +763,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 +789,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 +809,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[] = {