--- linux.orig/drivers/ide/Kconfig Fri Dec 24 21:34:44 2004 +++ linux/drivers/ide/Kconfig Mon Jan 10 00:30:19 2005 @@ -808,7 +808,8 @@ depends on ARM && ARCH_ACORN help Say Y here if you want to support the Yellowstone RapIDE controller - manufactured for use with Acorn computers. + manufactured for use with Acorn computers. This driver only works + with version 2 cards presently. config BLK_DEV_IDE_BAST tristate "Simtec BAST / Thorcom VR1000 IDE support" --- linux.orig/drivers/ide/arm/Makefile Sun Jan 9 23:47:32 2005 +++ linux/drivers/ide/arm/Makefile Mon Jan 10 00:11:19 2005 @@ -1,6 +1,6 @@ obj-$(CONFIG_BLK_DEV_IDE_ICSIDE) += icside.o -obj-$(CONFIG_BLK_DEV_IDE_RAPIDE) += rapide.o +obj-$(CONFIG_BLK_DEV_IDE_RAPIDE) += rapide.o rapide_io_asm.o obj-$(CONFIG_BLK_DEV_IDE_BAST) += bast-ide.o EXTRA_CFLAGS := -Idrivers/ide --- linux.orig/drivers/ide/arm/rapide_io_asm.S Thu Jan 1 01:00:00 1970 +++ linux/drivers/ide/arm/rapide_io_asm.S Tue Jan 11 23:45:03 2005 @@ -0,0 +1,177 @@ +/* + * Copyright (c) 1997 Mark Brinicombe. + * Copyright (c) 1997 Causality Limited. + * All rights reserved. + * + * Ported to ARM Linux by Peter Naulls + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mark Brinicombe + * for the NetBSD Project. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * EASI space I/O functions for Yellowstone RapIDE podule + * + * These are optimised 32 bit transfer routines + */ + +#define __ASSEMBLY__ +#include +#include + + +ENTRY(rapide_bs_rm_4) + cmp r2, #0 + moveq pc, lr + + tst r2, #0x7f + beq rapide_rm_4_m512 + tst r2, #0x07 + beq rapide_rm_4_m32 + + /* xfer 4 bytes at a time */ +rapide_rm_4_loop: + ldr r3, [r0] + str r3, [r1], #4 + subs r2, r2, #1 + bne rapide_rm_4_loop + + mov pc, lr + +rapide_rm_4_m32: + /* xfer 32 bytes at a time */ + stmfd sp!, {r4-r10} + +rapide_rm_4_m32_loop: + ldmia r0, {r3-r10} + stmia r1!, {r3-r10} + subs r2, r2, #8 + bne rapide_rm_4_m32_loop + + ldmfd sp!, {r4-r10} + mov pc, lr + +rapide_rm_4_m512: + /* xfer 512 bytes at a time */ + stmfd sp!, {r4-r12, r14} + +rapide_rm_4_m512_loop: + ldmia r0, {r3-r12, r14} + stmia r1!, {r3-r12, r14} /* 44 */ + ldmia r0, {r3-r12, r14} + stmia r1!, {r3-r12, r14} /* 88 */ + ldmia r0, {r3-r12, r14} + stmia r1!, {r3-r12, r14} /* 132 */ + ldmia r0, {r3-r12, r14} + stmia r1!, {r3-r12, r14} /* 176 */ + ldmia r0, {r3-r12, r14} + stmia r1!, {r3-r12, r14} /* 220 */ + ldmia r0, {r3-r12, r14} + stmia r1!, {r3-r12, r14} /* 264 */ + ldmia r0, {r3-r12, r14} + stmia r1!, {r3-r12, r14} /* 308 */ + ldmia r0, {r3-r12, r14} + stmia r1!, {r3-r12, r14} /* 352 */ + ldmia r0, {r3-r12, r14} + stmia r1!, {r3-r12, r14} /* 396 */ + ldmia r0, {r3-r12, r14} + stmia r1!, {r3-r12, r14} /* 440 */ + ldmia r0, {r3-r12, r14} + stmia r1!, {r3-r12, r14} /* 484 */ + ldmia r0, {r3-r9} + stmia r1!, {r3-r9} /* 512 */ + subs r2, r2, #128 + bne rapide_rm_4_m512_loop + + ldmfd sp!, {r4-r12, pc} + + +ENTRY(rapide_bs_wm_4) + cmp r2, #0 + moveq pc, lr + + tst r2, #0x7f + beq rapide_wm_4_m512 + tst r2, #0x07 + beq rapide_wm_4_m32 + + /* xfer 4 bytes at a time */ +rapide_wm_4_loop: + ldr r3, [r1], #4 + str r3, [r0] + subs r2, r2, #1 + bne rapide_wm_4_loop + + mov pc, lr + +rapide_wm_4_m32: + /* xfer 32 bytes at a time */ + stmfd sp!, {r4-r10} + +rapide_wm_4_m32_loop: + ldmia r1!, {r3-r10} + stmia r0, {r3-r10} + subs r2, r2, #8 + bne rapide_wm_4_m32_loop + + ldmfd sp!, {r4-r10} + mov pc, lr + +rapide_wm_4_m512: + /* xfer 512 bytes at a time */ + stmfd sp!, {r4-r12, r14} + +rapide_wm_4_m512_loop: + ldmia r1!, {r3-r12, r14} + stmia r0, {r3-r12, r14} /* 44 */ + ldmia r1!, {r3-r12, r14} + stmia r0, {r3-r12, r14} /* 88 */ + ldmia r1!, {r3-r12, r14} + stmia r0, {r3-r12, r14} /* 132 */ + ldmia r1!, {r3-r12, r14} + stmia r0, {r3-r12, r14} /* 176 */ + ldmia r1!, {r3-r12, r14} + stmia r0, {r3-r12, r14} /* 220 */ + ldmia r1!, {r3-r12, r14} + stmia r0, {r3-r12, r14} /* 264 */ + ldmia r1!, {r3-r12, r14} + stmia r0, {r3-r12, r14} /* 308 */ + ldmia r1!, {r3-r12, r14} + stmia r0, {r3-r12, r14} /* 352 */ + ldmia r1!, {r3-r12, r14} + stmia r0, {r3-r12, r14} /* 396 */ + ldmia r1!, {r3-r12, r14} + stmia r0, {r3-r12, r14} /* 440 */ + ldmia r1!, {r3-r12, r14} + stmia r0, {r3-r12, r14} /* 484 */ + ldmia r1!, {r3-r9} + stmia r0, {r3-r9} /* 512 */ + subs r2, r2, #128 + bne rapide_wm_4_m512_loop + + ldmfd sp!, {r4-r12, pc} --- linux.orig/include/asm-arm/ecard.h Sun Jan 9 23:47:42 2005 +++ linux/include/asm-arm/ecard.h Mon Jan 10 00:28:14 2005 @@ -9,7 +9,7 @@ * 11-12-1996 RMK Further minor improvements * 12-09-1997 RMK Added interrupt enable/disable for card level * - * Reference: Acorns Risc OS 3 Programmers Reference Manuals. + * Reference: Acorn's RISC OS 3 Programmers Reference Manuals. */ #ifndef __ASM_ECARD_H @@ -74,8 +74,8 @@ #define MANU_EESOX 0x0064 #define PROD_EESOX_SCSI2 0x008c -#define MANU_YELLOWSTONE 0x0096 -#define PROD_YELLOWSTONE_RAPIDE32 0x0120 +#define MANU_YELLOWSTONE 0x0060 +#define PROD_YELLOWSTONE_RAPIDE32 0x0114 #ifdef ECARD_C #define CONST --- linux-2.6.22.1.orig/drivers/ide/arm/rapide.c 2007-07-10 19:56:30.000000000 +0100 +++ linux-2.6.22.1/drivers/ide/arm/rapide.c 2007-07-25 09:14:47.000000000 +0100 @@ -1,7 +1,13 @@ /* * linux/drivers/ide/arm/rapide.c * - * Copyright (c) 1996-2002 Russell King. + * Copyright (c) 2004 Peter Naulls + * + * Based loosely upon ARM Linux ICS IDE driver by Russell King and NetBSD RapIDE + * driver by Mark Brinicombe, and information from the RISC OS sources + * provided by Chris Honey + * + * Minor modifications to work with kernel 2.6 by Jim Hawkins */ #include @@ -13,110 +19,279 @@ #include -/* - * Something like this really should be in generic code, but isn't. - */ -static ide_hwif_t * -rapide_locate_hwif(void __iomem *base, void __iomem *ctrl, unsigned int sz, int irq) +/* IDE drive registers */ + +#define PRIMARY_DRIVE_REGISTERS_OFFSET (0x400080 >> 2) +#define PRIMARY_AUX_REGISTER_OFFSET (0x400298 >> 2) +#define PRIMARY_DATA_REGISTER_OFFSET (0x600080 >> 2) + +#define SECONDARY_DRIVE_REGISTERS_OFFSET (0x400000 >> 2) +#define SECONDARY_AUX_REGISTER_OFFSET (0x400218 >> 2) +#define SECONDARY_DATA_REGISTER_OFFSET (0x600000 >> 2) + +#define CONTROL_REGISTERS_OFFSET (0x200000 >> 2) + + +#define IRQ_MASK_REGISTER_OFFSET 0 +#define IRQ_STATUS_REGISTER_OFFSET 0 +#define IRQ_REQUEST_REGISTER_OFFSET 1 + +#define PRIMARY_IRQ_MASK 0x01 +#define SECONDARY_IRQ_MASK 0x02 +#define IRQ_MASK (PRIMARY_IRQ_MASK | SECONDARY_IRQ_MASK) + + + +struct cardinfo { + unsigned int primary; + unsigned int aux; + unsigned int data; + unsigned int mask; +}; + + +static struct cardinfo __initdata rapide_regs[] = { + { PRIMARY_DRIVE_REGISTERS_OFFSET, PRIMARY_AUX_REGISTER_OFFSET, + PRIMARY_DATA_REGISTER_OFFSET, PRIMARY_IRQ_MASK }, + { SECONDARY_DRIVE_REGISTERS_OFFSET, SECONDARY_AUX_REGISTER_OFFSET, + SECONDARY_DATA_REGISTER_OFFSET, SECONDARY_IRQ_MASK } +}; + + +struct rapide_card { + ide_hwif_t *hwif[2]; + int channel; + int enabled; + unsigned long base; + unsigned long control; + unsigned long data[2]; +}; + + +extern void rapide_bs_rm_4(char *data, char *buffer, u32 wcount); +extern void rapide_bs_wm_4(char *data, char *buffer, u32 wcount); + + +void rapide_input_data (ide_drive_t *drive, void *buffer, u32 wcount) +{ + ide_hwif_t *hwif = HWIF(drive); + char *data = (void *)((struct rapide_card *)hwif->hwif_data)->data[hwif->channel]; + + rapide_bs_rm_4(data, buffer, wcount); +} + + +void rapide_output_data (ide_drive_t *drive, void *buffer, u32 wcount) +{ + ide_hwif_t *hwif = HWIF(drive); + char *data = (void *)((struct rapide_card *)hwif->hwif_data)->data[hwif->channel]; + + rapide_bs_wm_4(data, buffer, wcount); +} + + +static void rapide_maskproc(ide_drive_t *drive, int mask) +{ + ide_hwif_t *hwif = HWIF(drive); + struct rapide_card *card = hwif->hwif_data; + unsigned long flags; + + local_irq_save(flags); + + card->channel = hwif->channel; + + if (card->enabled && !mask) { + outb(IRQ_MASK, card->control + IRQ_MASK_REGISTER_OFFSET); + } else { + outb(0, card->control + IRQ_MASK_REGISTER_OFFSET); + } + + local_irq_restore(flags); +} + + +static ide_hwif_t *rapide_find_hwif(unsigned long dataport) { - unsigned long port = (unsigned long)base; ide_hwif_t *hwif; - int index, i; + int index; for (index = 0; index < MAX_HWIFS; ++index) { - hwif = ide_hwifs + index; - if (hwif->io_ports[IDE_DATA_OFFSET] == port) - goto found; + hwif = &ide_hwifs[index]; + if (hwif->io_ports[IDE_DATA_OFFSET] == dataport) + return hwif; } for (index = 0; index < MAX_HWIFS; ++index) { - hwif = ide_hwifs + index; - if (hwif->io_ports[IDE_DATA_OFFSET] == 0) - goto found; + hwif = &ide_hwifs[index]; + if (!hwif->io_ports[IDE_DATA_OFFSET]) + return hwif; } return NULL; +} - found: - for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { - hwif->hw.io_ports[i] = port; - hwif->io_ports[i] = port; - port += sz; - } - hwif->hw.io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl; - hwif->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl; - hwif->hw.irq = hwif->irq = irq; - hwif->mmio = 1; - default_hwif_mmiops(hwif); - return hwif; +static inline int rapide_register(struct rapide_card *card, int irq, unsigned long regs, unsigned long control, + ide_hwif_t **hwif_p) +{ + unsigned long port = card->base; + int ide_reg; + hw_regs_t *hw; + ide_hwif_t *hwif = rapide_find_hwif(regs); + + if (!hwif) return -1; + hw = &hwif->hw; + + memset(hw, 0, sizeof(hw_regs_t)); + + for (ide_reg = IDE_DATA_OFFSET; ide_reg <= IDE_STATUS_OFFSET; ide_reg++) { + hwif->io_ports[ide_reg] = + hw->io_ports[ide_reg] = port + regs; + port++; + } + hwif->io_ports[IDE_CONTROL_OFFSET] = + hw->io_ports[IDE_CONTROL_OFFSET] = card->base + control; + hw->dma = NO_DMA; + + hwif->irq = + hw->irq = irq; + + hwif->hwif_data = card; + hwif->channel = card->channel; + hwif->maskproc = rapide_maskproc; + + hwif->noprobe = 0; + hwif->chipset = ide_acorn; + + hwif->ata_input_data = rapide_input_data; + hwif->ata_output_data = rapide_output_data; + + hwif->serialized = 1; + + card->hwif[card->channel] = hwif; + + probe_hwif_init(hwif); + ide_proc_register_port(hwif); + + *hwif_p = hwif; + return 0; + } -static int __devinit -rapide_probe(struct expansion_card *ec, const struct ecard_id *id) + +static void rapide_irqenable(struct expansion_card *ec, int irqnr) { - ide_hwif_t *hwif; - void __iomem *base; - int ret; + struct rapide_card *card = ec->irq_data; - ret = ecard_request_resources(ec); - if (ret) - goto out; - - base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0); - if (!base) { - ret = -ENOMEM; - goto release; - } + card->enabled = 1; - hwif = rapide_locate_hwif(base, base + 0x818, 1 << 6, ec->irq); - if (hwif) { - hwif->hwif_data = base; - hwif->gendev.parent = &ec->dev; - hwif->noprobe = 0; - probe_hwif_init(hwif); - ide_proc_register_port(hwif); - ecard_set_drvdata(ec, hwif); - goto out; - } + outb(IRQ_MASK, card->control + IRQ_MASK_REGISTER_OFFSET); +} - release: - ecard_release_resources(ec); - out: - return ret; + +static void rapide_irqdisable(struct expansion_card *ec, int irqnr) +{ + struct rapide_card *card = ec->irq_data; + + card->enabled = 0; + + outb(0, card->control + IRQ_MASK_REGISTER_OFFSET); } -static void __devexit rapide_remove(struct expansion_card *ec) + +static int rapide_irqpending(struct expansion_card *ec) { - ide_hwif_t *hwif = ecard_get_drvdata(ec); + struct rapide_card *card = ec->irq_data; + + return inb(card->control + IRQ_REQUEST_REGISTER_OFFSET); +} + + +static const expansioncard_ops_t rapide_ops = { + .irqenable = rapide_irqenable, + .irqdisable = rapide_irqdisable, + .irqpending = rapide_irqpending +}; + + +static int __init rapide_probe(struct expansion_card *ec, const struct ecard_id *id) +{ + int interface; + struct rapide_card *card; + unsigned long base; + + printk("RapIDE: IDE card driver for Yellowstone IDE Podule v2\n"); + + if (!(card = kmalloc(sizeof(struct rapide_card), GFP_KERNEL))) + return -ENOMEM; - ecard_set_drvdata(ec, NULL); + card->base = base = ecard_address(ec, ECARD_EASI, ECARD_SYNC); + card->control = base + CONTROL_REGISTERS_OFFSET; - /* there must be a better way */ - ide_unregister(hwif - ide_hwifs); - ecard_release_resources(ec); + ec->ops = &rapide_ops; + ec->irq_data = card; + + ecard_set_drvdata(ec, card); + + /* Enable IRQs */ + outb(~0, card->control + IRQ_MASK_REGISTER_OFFSET); + + for (interface = 0; interface < 2; interface++) { + ide_hwif_t *hwif; + + card->data[interface] = ioaddr(base + rapide_regs[interface].data); + card->channel = interface; + + if (rapide_register(card, ec->irq, rapide_regs[interface].primary, + rapide_regs[interface].aux, &hwif) != -1) { + + printk("RapIDE: interface found for channel %d\n", hwif->channel); + + } + } + return 0; + +} + +static void __devexit rapide_remove(struct expansion_card *ec) { + struct rapide_card *card = ecard_get_drvdata(ec); + + if (card->hwif[0]) + card->hwif[0]->io_ports[IDE_DATA_OFFSET] = 0; + if (card->hwif[1]) + card->hwif[1]->io_ports[IDE_DATA_OFFSET] = 0; + + kfree(card); +} + + +static void rapide_shutdown(struct expansion_card *ec) +{ + struct rapide_card *card = ecard_get_drvdata(ec); + + /* Disable interrupts */ + outb(0, card->control + IRQ_MASK_REGISTER_OFFSET); } -static struct ecard_id rapide_ids[] = { + +static struct ecard_id __initdata rapide_cids[] = { { MANU_YELLOWSTONE, PROD_YELLOWSTONE_RAPIDE32 }, { 0xffff, 0xffff } }; + static struct ecard_driver rapide_driver = { .probe = rapide_probe, .remove = __devexit_p(rapide_remove), - .id_table = rapide_ids, - .drv = { - .name = "rapide", - }, + .shutdown = rapide_shutdown, + .id_table = rapide_cids, }; -static int __init rapide_init(void) + +int __init rapide_init(void) { return ecard_register_driver(&rapide_driver); } -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Yellowstone RAPIDE driver"); -module_init(rapide_init); +__initcall(rapide_init);