diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1999-06-22 23:05:57 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1999-06-22 23:05:57 +0000 |
commit | 51d3b7814cdccef9188240fe0cbd8d97ff2c7470 (patch) | |
tree | 5cbb01d0323d4f63ade66bdf48ba4a91aaa6df16 /drivers/block | |
parent | 52273a23c9a84336b93a35e4847fc88fac7eb0e4 (diff) |
Merge with Linux 2.3.7.
WARNING: 2.3.7 is known to eat filesystems for breakfast and little
children for lunch, so if you try this on your machine make backups
first ...
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/Config.in | 31 | ||||
-rw-r--r-- | drivers/block/icside.c | 634 | ||||
-rw-r--r-- | drivers/block/ll_rw_blk.c | 2 | ||||
-rw-r--r-- | drivers/block/rapide.c | 92 |
4 files changed, 750 insertions, 9 deletions
diff --git a/drivers/block/Config.in b/drivers/block/Config.in index 47fc9eac1..a9b9a000f 100644 --- a/drivers/block/Config.in +++ b/drivers/block/Config.in @@ -38,16 +38,16 @@ else bool ' RZ1000 chipset bugfix/support' CONFIG_BLK_DEV_RZ1000 bool ' Generic PCI IDE chipset support' CONFIG_BLK_DEV_IDEPCI if [ "$CONFIG_BLK_DEV_IDEPCI" = "y" ]; then - bool ' Generic PCI bus-master DMA support' CONFIG_BLK_DEV_IDEDMA + bool ' Generic PCI bus-master DMA support' CONFIG_BLK_DEV_IDEDMA_PCI + if [ "$CONFIG_BLK_DEV_IDEDMA_PCI" = "y" ]; then + bool ' Use PCI DMA by default when available' CONFIG_IDEDMA_PCI_AUTO + fi bool ' Boot off-board chipsets first support' CONFIG_BLK_DEV_OFFBOARD bool ' AEC6210 chipset support' CONFIG_BLK_DEV_AEC6210 - if [ "$CONFIG_BLK_DEV_IDEDMA" = "y" ]; then - bool ' Use DMA by default when available' CONFIG_IDEDMA_AUTO - fi if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then bool ' OPTi 82C621 chipset enhanced support (EXPERIMENTAL)' CONFIG_BLK_DEV_OPTI621 bool ' Intel PIIXn chipsets support (EXPERIMENTAL)' CONFIG_BLK_DEV_PIIX - if [ "$CONFIG_BLK_DEV_IDEDMA" = "y" ]; then + if [ "$CONFIG_BLK_DEV_IDEDMA_PCI" = "y" ]; then bool ' Tekram TRM290 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_TRM290 bool ' NS87415 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_NS87415 bool ' VIA82C586 chipset support (EXPERIMENTAL)' CONFIG_BLK_DEV_VIA82C586 @@ -66,7 +66,7 @@ else fi fi fi - if [ "$CONFIG_PPC" = "y" ]; then + if [ "$CONFIG_PPC" = "y" -o "$CONFIG_ARM" = "y" ]; then bool ' Winbond SL82c105 support' CONFIG_BLK_DEV_SL82C105 fi fi @@ -75,11 +75,25 @@ else if [ "$CONFIG_BLK_DEV_IDE_PMAC" != "n" ]; then bool ' PowerMac IDE DMA support' CONFIG_BLK_DEV_IDEDMA_PMAC if [ "$CONFIG_BLK_DEV_IDEDMA_PMAC" = "y" ]; then - define_bool CONFIG_BLK_DEV_IDEDMA y bool ' Use DMA by default' CONFIG_PMAC_IDEDMA_AUTO fi fi fi + if [ "$CONFIG_ARCH_ACORN" = "y" ]; then + bool ' ICS IDE interface support' CONFIG_BLK_DEV_IDE_ICSIDE + if [ "$CONFIG_BLK_DEV_IDE_ICSIDE" = "y" ]; then + bool ' ICS DMA support' CONFIG_BLK_DEV_IDEDMA_ICS + if [ "$CONFIG_BLK_DEV_IDEDMA_ICS" = "y" ]; then + bool ' Use ICS DMA by default' CONFIG_IDEDMA_ICS_AUTO + fi + fi + bool ' RapIDE interface support' CONFIG_BLK_DEV_IDE_RAPIDE + fi + if [ "$CONFIG_BLK_DEV_IDEDMA_PCI" = "y" -o \ + "$CONFIG_BLK_DEV_IDEDMA_PMAC" = "y" -o \ + "$CONFIG_BLK_DEV_IDEDMA_ICS" = "y" ]; then + define_bool CONFIG_BLK_DEV_IDEDMA y + fi bool ' Other IDE chipset support' CONFIG_IDE_CHIPSETS if [ "$CONFIG_IDE_CHIPSETS" = "y" ]; then comment 'Note: most of these also require special kernel boot parameters' @@ -170,7 +184,8 @@ if [ "$CONFIG_BLK_DEV_CMD640" = "y" -o \ "$CONFIG_BLK_DEV_IDE_PMAC" = "y" -o \ "$CONFIG_BLK_DEV_CY82C693" = "y" -o \ "$CONFIG_BLK_DEV_HPT343" = "y" -o \ - "$CONFIG_BLK_DEV_PIIX" = "y" ]; then + "$CONFIG_BLK_DEV_PIIX" = "y" -o \ + "$CONFIG_BLK_DEV_SL82C105" = "y" ]; then define_bool CONFIG_BLK_DEV_IDE_MODES y else define_bool CONFIG_BLK_DEV_IDE_MODES n diff --git a/drivers/block/icside.c b/drivers/block/icside.c new file mode 100644 index 000000000..299bce7a6 --- /dev/null +++ b/drivers/block/icside.c @@ -0,0 +1,634 @@ +/* + * linux/drivers/block/icside.c + * + * Copyright (c) 1996,1997 Russell King. + * + * Changelog: + * 08-Jun-1996 RMK Created + * 12-Sep-1997 RMK Added interrupt enable/disable + * 17-Apr-1999 RMK Added support for V6 EASI + * 22-May-1999 RMK Added support for V6 DMA + */ + +#include <linux/string.h> +#include <linux/module.h> +#include <linux/ioport.h> +#include <linux/malloc.h> +#include <linux/blkdev.h> +#include <linux/errno.h> +#include <linux/hdreg.h> +#include <linux/ide.h> + +#include <asm/dma.h> +#include <asm/ecard.h> +#include <asm/io.h> + +/* + * Maximum number of interfaces per card + */ +#define MAX_IFS 2 + +#define ICS_IDENT_OFFSET 0x8a0 + +#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 + +struct cardinfo { + unsigned int dataoffset; + unsigned int ctrloffset; + unsigned int stepping; +}; + +static struct cardinfo icside_cardinfo_v5 = { + ICS_ARCIN_V5_IDEOFFSET, + ICS_ARCIN_V5_IDEALTOFFSET, + 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 +}; + +static struct cardinfo icside_cardinfo_v6_2 = { + ICS_ARCIN_V6_IDEOFFSET_2, + ICS_ARCIN_V6_IDEALTOFFSET_2, + ICS_ARCIN_V6_IDESTEPPING +}; + +static const card_ids icside_cids[] = { + { MANU_ICS, PROD_ICS_IDE }, + { MANU_ICS2, PROD_ICS2_IDE }, + { 0xffff, 0xffff } +}; + +typedef enum { + ics_if_unknown, + ics_if_arcin_v5, + ics_if_arcin_v6 +} iftype_t; + +/* ---------------- Version 5 PCB Support Functions --------------------- */ +/* Prototype: icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr) + * Purpose : enable interrupts from card + */ +static void icside_irqenable_arcin_v5 (struct expansion_card *ec, int irqnr) +{ + unsigned int memc_port = (unsigned int)ec->irq_data; + outb (0, memc_port + ICS_ARCIN_V5_INTROFFSET); +} + +/* Prototype: icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr) + * Purpose : disable interrupts from card + */ +static void icside_irqdisable_arcin_v5 (struct expansion_card *ec, int irqnr) +{ + unsigned int memc_port = (unsigned int)ec->irq_data; + inb (memc_port + ICS_ARCIN_V5_INTROFFSET); +} + +static const expansioncard_ops_t icside_ops_arcin_v5 = { + icside_irqenable_arcin_v5, + icside_irqdisable_arcin_v5, + NULL, + NULL, + NULL, + NULL +}; + + +/* ---------------- Version 6 PCB Support Functions --------------------- */ +/* Prototype: icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr) + * Purpose : enable interrupts from card + */ +static void icside_irqenable_arcin_v6 (struct expansion_card *ec, int irqnr) +{ + unsigned int ide_base_port = (unsigned int)ec->irq_data; + + outb (0, ide_base_port + ICS_ARCIN_V6_INTROFFSET_1); + outb (0, ide_base_port + ICS_ARCIN_V6_INTROFFSET_2); +} + +/* Prototype: icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr) + * Purpose : disable interrupts from card + */ +static void icside_irqdisable_arcin_v6 (struct expansion_card *ec, int irqnr) +{ + unsigned int ide_base_port = (unsigned int)ec->irq_data; + + inb (ide_base_port + ICS_ARCIN_V6_INTROFFSET_1); + inb (ide_base_port + ICS_ARCIN_V6_INTROFFSET_2); +} + +/* Prototype: icside_irqprobe(struct expansion_card *ec) + * Purpose : detect an active interrupt from card + */ +static int icside_irqpending_arcin_v6(struct expansion_card *ec) +{ + unsigned int ide_base_port = (unsigned int)ec->irq_data; + + return inb(ide_base_port + ICS_ARCIN_V6_INTRSTAT_1) & 1 || + inb(ide_base_port + ICS_ARCIN_V6_INTRSTAT_2) & 1; +} + +static const expansioncard_ops_t icside_ops_arcin_v6 = { + icside_irqenable_arcin_v6, + icside_irqdisable_arcin_v6, + icside_irqpending_arcin_v6, + NULL, + NULL, + NULL +}; + +/* Prototype: icside_identifyif (struct expansion_card *ec) + * Purpose : identify IDE interface type + * Notes : checks the description string + */ +static iftype_t icside_identifyif (struct expansion_card *ec) +{ + unsigned int addr; + iftype_t iftype; + int id = 0; + + iftype = ics_if_unknown; + + addr = ecard_address (ec, ECARD_IOC, ECARD_FAST) + ICS_IDENT_OFFSET; + + id = inb (addr) & 1; + id |= (inb (addr + 1) & 1) << 1; + id |= (inb (addr + 2) & 1) << 2; + id |= (inb (addr + 3) & 1) << 3; + + switch (id) { + case 0: /* A3IN */ + printk("icside: A3IN unsupported\n"); + break; + + case 1: /* A3USER */ + printk("icside: A3USER unsupported\n"); + break; + + case 3: /* ARCIN V6 */ + printk(KERN_DEBUG "icside: detected ARCIN V6 in slot %d\n", ec->slot_no); + iftype = ics_if_arcin_v6; + break; + + case 15:/* ARCIN V5 (no id) */ + printk(KERN_DEBUG "icside: detected ARCIN V5 in slot %d\n", ec->slot_no); + iftype = ics_if_arcin_v5; + break; + + default:/* we don't know - complain very loudly */ + printk("icside: ***********************************\n"); + printk("icside: *** UNKNOWN ICS INTERFACE id=%d ***\n", id); + printk("icside: ***********************************\n"); + printk("icside: please report this to linux@arm.linux.org.uk\n"); + printk("icside: defaulting to ARCIN V5\n"); + iftype = ics_if_arcin_v5; + break; + } + + return iftype; +} + +#ifdef CONFIG_BLK_DEV_IDEDMA_ICS +/* + * SG-DMA support. + * + * Similar to the BM-DMA, but we use the RiscPCs IOMD + * DMA controllers. There is only one DMA controller + * per card, which means that only one drive can be + * accessed at one time. NOTE! We do not inforce that + * here, but we rely on the main IDE driver spotting + * that both interfaces use the same IRQ, which should + * guarantee this. + * + * We are limited by the drives IOR/IOW pulse time. + * The closest that we can get to the requirements is + * a type C cycle for both mode 1 and mode 2. However, + * this does give a burst of 8MB/s. + * + * This has been tested with a couple of Conner + * Peripherals 1080MB CFS1081A drives, one on each + * interface, which deliver about 2MB/s each. I + * believe that this is limited by the lack of + * on-board drive cache. + */ +#define TABLE_SIZE 2048 + +static int +icside_build_dmatable(ide_drive_t *drive, int reading) +{ + struct request *rq = HWGROUP(drive)->rq; + struct buffer_head *bh = rq->bh; + unsigned long addr, size; + unsigned char *virt_addr; + unsigned int count = 0; + dmasg_t *sg = (dmasg_t *)HWIF(drive)->dmatable; + + do { + if (bh == NULL) { + /* paging requests have (rq->bh == NULL) */ + virt_addr = rq->buffer; + addr = virt_to_bus (virt_addr); + size = rq->nr_sectors << 9; + } else { + /* group sequential buffers into one large buffer */ + virt_addr = bh->b_data; + addr = virt_to_bus (virt_addr); + size = bh->b_size; + while ((bh = bh->b_reqnext) != NULL) { + if ((addr + size) != virt_to_bus (bh->b_data)) + break; + size += bh->b_size; + } + } + + if (addr & 3) { + printk("%s: misaligned DMA buffer\n", drive->name); + return 0; + } + + if (size) { + if (reading) + dma_cache_inv((unsigned int)virt_addr, size); + else + dma_cache_wback((unsigned int)virt_addr, size); + } + + sg[count].address = addr; + sg[count].length = size; + if (++count >= (TABLE_SIZE / sizeof(dmasg_t))) { + printk("%s: DMA table too small\n", drive->name); + return 0; + } + } while (bh != NULL); + + if (!count) + printk("%s: empty DMA table?\n", drive->name); + + return count; +} + +static int +icside_config_drive(ide_drive_t *drive, int mode) +{ + ide_hwif_t *hwif = HWIF(drive); + int speed, err; + + if (mode == 2) { + speed = XFER_MW_DMA_2; + drive->drive_data = 250; + } else { + speed = XFER_MW_DMA_1; + drive->drive_data = 250; + } + + /* + * Don't use ide_wait_cmd here - it will + * attempt to set_geometry and recalibrate, + * but for some reason these don't work at + * this point (lost interrupt). + */ + SELECT_DRIVE(hwif, drive); + OUT_BYTE(drive->ctl | 2, IDE_CONTROL_REG); + OUT_BYTE(speed, IDE_NSECTOR_REG); + OUT_BYTE(SETFEATURES_XFER, IDE_FEATURE_REG); + OUT_BYTE(WIN_SETFEATURES, IDE_COMMAND_REG); + + err = ide_wait_stat(drive, DRIVE_READY, + BUSY_STAT|DRQ_STAT|ERR_STAT, WAIT_CMD); + + if (err == 0) { + drive->id->dma_mword &= 0x00ff; + drive->id->dma_mword |= 256 << mode; + } else + drive->drive_data = 0; + + return err; +} + +static int +icside_dma_check(ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + ide_hwif_t *hwif = HWIF(drive); + int autodma = hwif->autodma; + + if (id && (id->capability & 1) && autodma) { + int dma_mode = 0; + + /* Consult the list of known "bad" drives */ + if (ide_dmaproc(ide_dma_bad_drive, drive)) + return hwif->dmaproc(ide_dma_off, drive); + + /* Enable DMA on any drive that has + * UltraDMA (mode 0/1/2) enabled + */ + if (id->field_valid & 4 && id->dma_ultra & 7) + dma_mode = 2; + + /* Enable DMA on any drive that has mode1 + * or mode2 multiword DMA enabled + */ + if (id->field_valid & 2 && id->dma_mword & 6) + dma_mode = id->dma_mword & 4 ? 2 : 1; + + /* Consult the list of known "good" drives */ + if (ide_dmaproc(ide_dma_good_drive, drive)) + dma_mode = 1; + + if (dma_mode && icside_config_drive(drive, dma_mode) == 0) + return hwif->dmaproc(ide_dma_on, drive); + } + return hwif->dmaproc(ide_dma_off_quietly, drive); +} + +static int +icside_dmaproc(ide_dma_action_t func, ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + int count, reading = 0; + + switch (func) { + case ide_dma_check: + return icside_dma_check(drive); + + case ide_dma_read: + reading = 1; + case ide_dma_write: + count = icside_build_dmatable(drive, reading); + if (!count) + return 1; + disable_dma(hwif->hw.dma); + + /* Route the DMA signals to + * to the correct interface. + */ + outb(hwif->select_data, hwif->config_data); + + /* Select the correct timing + * for this drive + */ + set_dma_speed(hwif->hw.dma, drive->drive_data); + + set_dma_sg(hwif->hw.dma, (dmasg_t *)hwif->dmatable, count); + set_dma_mode(hwif->hw.dma, reading ? DMA_MODE_READ + : DMA_MODE_WRITE); + + drive->waiting_for_dma = 1; + if (drive->media != ide_disk) + return 0; + + ide_set_handler(drive, &ide_dma_intr, WAIT_CMD); + OUT_BYTE(reading ? WIN_READDMA : WIN_WRITEDMA, + IDE_COMMAND_REG); + + case ide_dma_begin: + enable_dma(hwif->hw.dma); + return 0; + + case ide_dma_end: + drive->waiting_for_dma = 0; + disable_dma(hwif->hw.dma); + return get_dma_residue(hwif->hw.dma) != 0; + + case ide_dma_test_irq: + return inb((unsigned long)hwif->hw.priv) & 1; + + default: + return ide_dmaproc(func, drive); + } +} + +static unsigned long +icside_alloc_dmatable(void) +{ + static unsigned long dmatable; + static unsigned int leftover; + unsigned long table; + + if (leftover < TABLE_SIZE) { +#if PAGE_SIZE == TABLE_SIZE * 2 + dmatable = __get_free_pages(GFP_KERNEL, 1); + leftover = PAGE_SIZE; +#else + dmatable = kmalloc(TABLE_SIZE, GFP_KERNEL); + leftover = TABLE_SIZE; +#endif + } + + table = dmatable; + if (table) { + dmatable += TABLE_SIZE; + leftover -= TABLE_SIZE; + } + + return table; +} + +static int +icside_setup_dma(ide_hwif_t *hwif, int autodma) +{ + unsigned long table = icside_alloc_dmatable(); + + printk(" %s: SG-DMA", hwif->name); + + if (!table) + printk(" -- ERROR, unable to allocate DMA table\n"); + else { + hwif->dmatable = (void *)table; + hwif->dmaproc = icside_dmaproc; + hwif->autodma = autodma; + + printk(" capable%s\n", autodma ? + ", auto-enable" : ""); + } + + return hwif->dmatable != NULL; +} +#endif + +static ide_hwif_t * +icside_find_hwif(unsigned long dataport) +{ + ide_hwif_t *hwif; + int index; + + for (index = 0; index < MAX_HWIFS; ++index) { + hwif = &ide_hwifs[index]; + if (hwif->hw.io_ports[IDE_DATA_OFFSET] == (ide_ioreg_t)dataport) + goto found; + } + + for (index = 0; index < MAX_HWIFS; ++index) { + hwif = &ide_hwifs[index]; + if (!hwif->hw.io_ports[IDE_DATA_OFFSET]) + goto found; + } + + return NULL; +found: + return hwif; +} + +static ide_hwif_t * +icside_setup(unsigned long base, struct cardinfo *info, int irq) +{ + unsigned long port = base + info->dataoffset; + ide_hwif_t *hwif; + + hwif = icside_find_hwif(base); + if (hwif) { + int i; + + memset(&hwif->hw, 0, sizeof(hw_regs_t)); + + for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { + hwif->hw.io_ports[i] = (ide_ioreg_t)port; + port += 1 << info->stepping; + } + hwif->hw.io_ports[IDE_CONTROL_OFFSET] = base + info->ctrloffset; + hwif->hw.irq = irq; + hwif->hw.dma = NO_DMA; + hwif->noprobe = 0; + hwif->chipset = ide_acorn; + } + + return hwif; +} + +static int icside_register_v5(struct expansion_card *ec, int autodma) +{ + unsigned long slot_port; + ide_hwif_t *hwif; + + slot_port = ecard_address(ec, ECARD_MEMC, 0); + + ec->irqaddr = (unsigned char *)ioaddr(slot_port + ICS_ARCIN_V5_INTRSTAT); + ec->irqmask = 1; + ec->irq_data = (void *)slot_port; + ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v5; + + /* + * Be on the safe side - disable interrupts + */ + inb(slot_port + ICS_ARCIN_V5_INTROFFSET); + + hwif = icside_setup(slot_port, &icside_cardinfo_v5, ec->irq); + + return hwif ? 0 : -1; +} + +static int icside_register_v6(struct expansion_card *ec, int autodma) +{ + unsigned long slot_port, port; + ide_hwif_t *hwif, *mate; + int sel = 0; + + slot_port = ecard_address(ec, ECARD_IOC, ECARD_FAST); + port = ecard_address(ec, ECARD_EASI, ECARD_FAST); + + if (port == 0) + port = slot_port; + else + sel = 1 << 5; + + outb(sel, slot_port); + + ec->irq_data = (void *)port; + ec->ops = (expansioncard_ops_t *)&icside_ops_arcin_v6; + + /* + * Be on the safe side - disable interrupts + */ + inb(port + ICS_ARCIN_V6_INTROFFSET_1); + inb(port + ICS_ARCIN_V6_INTROFFSET_2); + + hwif = icside_setup(port, &icside_cardinfo_v6_1, ec->irq); + mate = icside_setup(port, &icside_cardinfo_v6_2, ec->irq); + +#ifdef CONFIG_BLK_DEV_IDEDMA_ICS + if (ec->dma != NO_DMA) { + if (request_dma(ec->dma, hwif->name)) + goto no_dma; + + if (hwif) { + hwif->config_data = slot_port; + hwif->select_data = sel; + hwif->hw.dma = ec->dma; + hwif->hw.priv = (void *) + (port + ICS_ARCIN_V6_INTRSTAT_1); + hwif->channel = 0; + icside_setup_dma(hwif, autodma); + } + if (mate) { + mate->config_data = slot_port; + mate->select_data = sel | 1; + mate->hw.dma = ec->dma; + mate->hw.priv = (void *) + (port + ICS_ARCIN_V6_INTRSTAT_2); + mate->channel = 1; + icside_setup_dma(mate, autodma); + } + } +#endif + +no_dma: + return hwif || mate ? 0 : -1; +} + +int icside_init(void) +{ + int autodma = 0; + +#ifdef CONFIG_IDEDMA_ICS_AUTO + autodma = 1; +#endif + + ecard_startfind (); + + do { + struct expansion_card *ec; + int result; + + ec = ecard_find(0, icside_cids); + if (ec == NULL) + break; + + ecard_claim(ec); + + switch (icside_identifyif(ec)) { + case ics_if_arcin_v5: + result = icside_register_v5(ec, autodma); + break; + + case ics_if_arcin_v6: + result = icside_register_v6(ec, autodma); + break; + + default: + result = -1; + break; + } + + if (result) + ecard_release(ec); + } while (1); + + return 0; +} diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 9b29f4f55..185591b3a 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -603,7 +603,7 @@ void ll_rw_block(int rw, int nr, struct buffer_head * bh[]) /* Verify requested block sizes. */ for (i = 0; i < nr; i++) { - if (bh[i] && bh[i]->b_size != correct_size) { + if (bh[i]->b_size != correct_size) { printk(KERN_NOTICE "ll_rw_block: device %s: " "only %d-char blocks implemented (%lu)\n", kdevname(bh[0]->b_dev), diff --git a/drivers/block/rapide.c b/drivers/block/rapide.c new file mode 100644 index 000000000..468f2e3b1 --- /dev/null +++ b/drivers/block/rapide.c @@ -0,0 +1,92 @@ +/* + * linux/arch/arm/drivers/block/ide-rapide.c + * + * Copyright (c) 1996-1998 Russell King. + * + * Changelog: + * 08-06-1996 RMK Created + * 13-04-1998 RMK Added manufacturer and product IDs + */ + +#include <linux/module.h> +#include <linux/malloc.h> +#include <linux/blkdev.h> +#include <linux/errno.h> +#include <linux/ide.h> + +#include <asm/ecard.h> + +static const card_ids rapide_cids[] = { + { MANU_YELLOWSTONE, PROD_YELLOWSTONE_RAPIDE32 }, + { 0xffff, 0xffff } +}; + +static struct expansion_card *ec[MAX_ECARDS]; +static int result[MAX_ECARDS]; + +static inline int rapide_register(struct expansion_card *ec) +{ + unsigned long port = ecard_address (ec, ECARD_MEMC, 0); + hw_regs_t hw; + + int i; + + memset(&hw, 0, sizeof(hw)); + + for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) { + hw.io_ports[i] = (ide_ioreg_t)port; + port += 1 << 4; + } + hw.io_ports[IDE_CONTROL_OFFSET] = port + 0x206; + hw.irq = ec->irq; + + return ide_register_hw(&hw, NULL); +} + +int rapide_init(void) +{ + int i; + + for (i = 0; i < MAX_ECARDS; i++) + ec[i] = NULL; + + ecard_startfind(); + + for (i = 0; ; i++) { + if ((ec[i] = ecard_find(0, rapide_cids)) == NULL) + break; + + ecard_claim(ec[i]); + result[i] = rapide_register(ec[i]); + } + for (i = 0; i < MAX_ECARDS; i++) + if (ec[i] && result[i] < 0) { + ecard_release(ec[i]); + ec[i] = NULL; + } + return 0; +} + +#ifdef MODULE + +int init_module (void) +{ + return rapide_init(); +} + +void cleanup_module (void) +{ + int i; + + for (i = 0; i < MAX_ECARDS; i++) + if (ec[i]) { + unsigned long port; + port = ecard_address(ec[i], ECARD_MEMC, 0); + + ide_unregister_port(port, ec[i]->irq, 16); + ecard_release(ec[i]); + ec[i] = NULL; + } +} +#endif + |