VDMA patch This thing uses pxa dma engine to transfer data from ide data register. It results in faster transfer rates and less cpu load. DMA can be enabled/diabled in common way (hdparm -d or ide=nodma boot parameter). Current version is for 2.6.21, I didn't port it to later kernels.
diff -ruN -X ../../new8/kernel/diffignore.txt linux-2.6.21-orig/drivers/ide/arm/ide-vdma-pxa2xx.c linux-2.6.21/drivers/ide/arm/ide-vdma-pxa2xx.c --- linux-2.6.21-orig/drivers/ide/arm/ide-vdma-pxa2xx.c 1970-01-01 03:00:00.000000000 +0300 +++ linux-2.6.21/drivers/ide/arm/ide-vdma-pxa2xx.c 2010-09-22 19:46:44.000000000 +0400 @@ -0,0 +1,430 @@ +/* + * Support for "virtual" DMA transfers using the DMA controller of pxa2xx processors. + * Currently this code is only tested on PXA270 processor. + * + * Copyright 2006 Kirill Kornilov + * + */ + +#include <linux/sched.h> +#include <linux/interrupt.h> +#include <linux/major.h> +#include <linux/errno.h> +#include <linux/genhd.h> +#include <linux/blkpg.h> +#include <linux/slab.h> +#include <linux/pci.h> +#include <linux/delay.h> +#include <linux/hdreg.h> +#include <linux/ide.h> +#include <linux/bitops.h> + +#include <asm/byteorder.h> +#include <asm/irq.h> +#include <asm/uaccess.h> +#include <asm/io.h> + +#include <asm/arch/system.h> +#include <asm/arch/dma.h> + +#include "ide-vdma.h" + +struct ide_vdma_state { + int dmach; +}; + +unsigned ide_vdma_pxa27x_burst_size = DCMD_BURST8; +EXPORT_SYMBOL(ide_vdma_pxa27x_burst_size); + +static ide_startstop_t ide_vdma_in_intr (ide_drive_t *drive); +static ide_startstop_t ide_vdma_out_intr (ide_drive_t *drive); +static int ide_vdma_end (ide_drive_t *drive); + +static ide_startstop_t ide_vdma_error(ide_drive_t *drive, struct request *rq, + const char *s, u8 stat) +{ + ide_hwif_t *hwif = drive->hwif; + + if(drive->waiting_for_dma) ide_vdma_end(drive); + if (rq->bio) { + int sectors = hwif->nsect - hwif->nleft - 1; + + if (sectors > 0) { + ide_driver_t *drv; + + drv = *(ide_driver_t **)rq->rq_disk->private_data; + drv->end_request(drive, 1, sectors); + } + } + return ide_error(drive, s, stat); +} + +static void ide_vdma_end_request(ide_drive_t *drive, struct request *rq, u8 stat) +{ + if (rq->rq_disk) { + ide_driver_t *drv; + + drv = *(ide_driver_t **)rq->rq_disk->private_data;; + drv->end_request(drive, 1, rq->hard_nr_sectors); + } else + ide_end_request(drive, 1, rq->hard_nr_sectors); +} + +static u8 ide_vdma_wait_drive_not_busy(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + int retries = 100; + u8 stat; + + /* + * Last sector was transfered, wait until drive is ready. + * This can take up to 10 usec, but we will wait max 1 ms + * (drive_cmd_intr() waits that long). + */ + while (((stat = hwif->INB(IDE_STATUS_REG)) & BUSY_STAT) && retries--) + udelay(10); + + if (!retries) + printk(KERN_ERR "%s: drive still BUSY!\n", drive->name); + + return stat; +} + +static void ide_vdma_intr(int channel, void *data) +{ + unsigned long flags; + unsigned dmach; + unsigned dcsr; + ide_hwif_t *hwif; + ide_hwgroup_t *hwgroup = (ide_hwgroup_t *)data; + + spin_lock_irqsave(&ide_lock, flags); + hwif = hwgroup->hwif; + dmach = hwif->hw.dma; + + dcsr = DCSR(dmach); + + if(hwif->nleft || hwgroup->handler != ide_vdma_in_intr + || !(dcsr&DCSR_ENDINTR)) { + /* stop dma, clear interrupt status */ + DCSR(dmach) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR; + spin_unlock_irqrestore(&ide_lock, flags); + printk("ide_vdma_intr: unexpected interrupt! DCSR=0x%x, DTADR=0x%x, DCMD=0x%x\n", + DCSR(dmach), DTADR(dmach), DCMD(dmach)); + return; + } + + disable_irq_nosync(hwif->irq); + spin_unlock_irqrestore(&ide_lock, flags); + ide_intr(hwif->irq, data); + enable_irq(hwif->irq); +} + + +static void ide_vdma_setup_in(ide_hwif_t *hwif) +{ + unsigned dmach = hwif->hw.dma; + struct scatterlist *sg = hwif->sg_table; + unsigned int nleft = hwif->nleft; + + DCSR(dmach) = DCSR_NODESC; + DSADR(dmach) = hwif->dma_base; + DTADR(dmach) = sg_dma_address(&sg[hwif->cursg]) + hwif->cursg_ofs*SECTOR_SIZE; + if(nleft == 1) DCMD(dmach) = DCMD_ENDIRQEN | DCMD_INCTRGADDR | ide_vdma_pxa27x_burst_size | SECTOR_SIZE; + else DCMD(dmach) = DCMD_INCTRGADDR | ide_vdma_pxa27x_burst_size | SECTOR_SIZE; + + hwif->nleft = nleft-1; /* we don't support multisector transfers... */ + hwif->cursg_ofs++; + if ((hwif->cursg_ofs * SECTOR_SIZE) == sg[hwif->cursg].length) { + hwif->cursg++; + hwif->cursg_ofs = 0; + } + + DCSR(dmach) |= DCSR_RUN; +} + +static void ide_vdma_setup_out(ide_hwif_t *hwif) +{ + unsigned dmach = hwif->hw.dma; + struct scatterlist *sg = hwif->sg_table; + unsigned int nleft = hwif->nleft; + + DCSR(dmach) = DCSR_NODESC; + DTADR(dmach) = hwif->dma_base; + DSADR(dmach) = sg_dma_address(&sg[hwif->cursg]) + hwif->cursg_ofs*SECTOR_SIZE; + DCMD(dmach) = DCMD_INCSRCADDR | ide_vdma_pxa27x_burst_size | SECTOR_SIZE; + + hwif->nleft = nleft-1; /* we don't support multisector transfers... */ + hwif->cursg_ofs++; + if ((hwif->cursg_ofs * SECTOR_SIZE) == sg[hwif->cursg].length) { + hwif->cursg++; + hwif->cursg_ofs = 0; + } + + DCSR(dmach) |= DCSR_RUN; +} + +static int ide_vdma_on(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct ide_vdma_state *st = hwif->hwif_data; + + if(st == NULL) return -EINVAL; + if(st->dmach >= 0) return 0; /* already enabled */ + hwif->hw.dma = pxa_request_dma("ide vdma", DMA_PRIO_LOW, + ide_vdma_intr, hwif->hwgroup); + if(hwif->hw.dma < 0) return -EBUSY; + st->dmach = hwif->hw.dma; + drive->using_dma = 1; + return 0; +} + +static ide_startstop_t ide_vdma_in_intr (ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + struct request *rq = HWGROUP(drive)->rq; + u8 stat = hwif->INB(IDE_STATUS_REG); + + if(hwif->nleft) { + if(!OK_STAT(stat, DATA_READY, BAD_R_STAT)) { + if (stat & (ERR_STAT | DRQ_STAT)) + return ide_vdma_error(drive, rq, __FUNCTION__, stat); + /* No data yet, so wait for another IRQ. */ + ide_set_handler(drive, &ide_vdma_in_intr, WAIT_WORSTCASE, NULL); + return ide_started; + } + + ide_set_handler(drive, &ide_vdma_in_intr, WAIT_WORSTCASE, NULL); + ide_vdma_setup_in(hwif); + return ide_started; + } + + ide_vdma_end(drive); + + /* If it was the last datablock check status and finish transfer. */ + stat = ide_vdma_wait_drive_not_busy(drive); + if (!OK_STAT(stat, 0, BAD_R_STAT)) + return ide_vdma_error(drive, rq, __FUNCTION__, stat); + ide_vdma_end_request(drive, rq, stat); + return ide_stopped; +} + + +static ide_startstop_t ide_vdma_out_intr (ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + struct request *rq = HWGROUP(drive)->rq; + u8 stat = hwif->INB(IDE_STATUS_REG); + + if (!OK_STAT(stat, DRIVE_READY, drive->bad_wstat)) goto error; + + /* Deal with unexpected ATA data phase. */ + if (((stat & DRQ_STAT) == 0) ^ !hwif->nleft) goto error; + + + if (!hwif->nleft) { + ide_vdma_end(drive); + ide_vdma_end_request(drive, rq, stat); + return ide_stopped; + } + + /* Still data left to transfer. */ + ide_vdma_setup_out(hwif); + ide_set_handler(drive, &ide_vdma_out_intr, WAIT_WORSTCASE, NULL); + + return ide_started; + +error: + return ide_vdma_error(drive, rq, __FUNCTION__, stat); +} + + +static void ide_vdma_off_quietly(ide_drive_t *drive) +{ + drive->using_dma = 0; +} + +static void ide_vdma_host_on(ide_drive_t *drive) +{ +} + +static void ide_vdma_host_off(ide_drive_t *drive) +{ +} + +static int ide_vdma_check(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct ide_vdma_state *st = hwif->hwif_data; + + if(st == NULL) return -EINVAL; + drive->vdma = 1; + if(st->dmach >= 0) return 0; /* already enabled */ + + if(hwif->autodma) return ide_vdma_on(drive); + return 0; +} + +static int ide_vdma_setup(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + struct request *rq = hwif->hwgroup->rq; + struct scatterlist *sg = hwif->sg_table; + + ide_init_sg_cmd(drive,rq); + ide_map_sg(drive, rq); + + hwif->sg_dma_direction = rq_data_dir(rq) == READ ? DMA_FROM_DEVICE : DMA_TO_DEVICE; + + hwif->sg_nents = dma_map_sg(hwif->hw.dev, sg, hwif->sg_nents, + hwif->sg_dma_direction); + /* + * This doesn't mean we're actually waiting for dma, but + * we need it to enable dma error recovery. + */ + drive->waiting_for_dma = 1; + return 0; +} + +static int ide_vdma_test_irq(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + unsigned dcsr; + int dmach = hwif->hw.dma; + + + dcsr = DCSR(dmach); + + /* We don't expect any interrupt, if DMA is running. */ + if(dcsr & DCSR_RUN) return 0; + + if(hwif->nleft == 0 && hwif->sg_dma_direction == DMA_FROM_DEVICE) { + /* Yes, we're expecting DMA interrupt... */ + return (dcsr&DCSR_ENDINTR) != 0; + } + + /* + * We expect normal IDE interrupt, + * if the drive is not busy, let the handler decide. + */ + return((hwif->INB(IDE_STATUS_REG) & BUSY_STAT) == 0); +} + +static void ide_vdma_exec_cmd(ide_drive_t *drive, u8 cmd) +{ + ide_handler_t *handler; + + switch(cmd) { + case WIN_READ: + case WIN_READ_EXT: + handler = ide_vdma_in_intr; + break; + case WIN_WRITE: + case WIN_WRITE_EXT: + handler = ide_vdma_out_intr; + break; + default: + BUG(); + } + + ide_execute_command(drive, cmd, handler, WAIT_CMD, NULL); +} + +int ide_vdma_lostirq (ide_drive_t *drive) +{ + printk("%s: VDMA: lost interrupt\n", drive->name); + return 1; +} + + +static void ide_vdma_start(ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + ide_startstop_t startstop; + + if(hwif->sg_dma_direction == DMA_TO_DEVICE) { + if (ide_wait_stat(&startstop, drive, DATA_READY, + drive->bad_wstat, WAIT_DRQ)) { + printk(KERN_ERR "%s: no DRQ after issuing WRITE%s\n", + drive->name, + drive->addressing ? "_EXT" : ""); + return; + } + ide_vdma_setup_out(drive->hwif); + } +} + +static int ide_vdma_end (ide_drive_t *drive) +{ + ide_hwif_t *hwif = HWIF(drive); + int dmach = hwif->hw.dma; + unsigned dcsr; + + drive->waiting_for_dma = 0; + + dcsr = DCSR(dmach); + /* disable dma, clear interrupts */ + DCSR(dmach) = DCSR_STARTINTR|DCSR_ENDINTR|DCSR_BUSERR; + + dma_unmap_sg(hwif->hw.dev, hwif->sg_table, hwif->sg_nents, + hwif->sg_dma_direction); + + return (dcsr & (DCSR_RUN|DCSR_BUSERR)) != 0; +} + + +static int ide_vdma_timeout(ide_drive_t *drive) +{ + printk(KERN_ERR "%s: timeout waiting for VDMA\n", drive->name); + if (ide_vdma_test_irq(drive)) return 0; + return ide_vdma_end(drive); +} + +struct ide_vdma_state* ide_vdma_init(ide_hwif_t *hwif, unsigned long dma_base) +{ + struct ide_vdma_state *st; + + st = kmalloc(sizeof(*st), GFP_KERNEL); + if(st == NULL) return NULL; + st->dmach = -1; + + printk(" %s: VDMA capable%s\n", hwif->name, + noautodma ? "" : ", auto-enable"); + + hwif->dmatable_cpu = NULL; + hwif->dmatable_dma = 0; + hwif->autodma = !noautodma; + + hwif->ide_dma_check = ide_vdma_check; + hwif->dma_host_off = ide_vdma_host_off; + hwif->dma_off_quietly = ide_vdma_off_quietly; + hwif->dma_host_on = ide_vdma_host_on; + hwif->ide_dma_on = ide_vdma_on; + hwif->dma_setup = ide_vdma_setup; + hwif->dma_exec_cmd = ide_vdma_exec_cmd; + hwif->ide_dma_lostirq = ide_vdma_lostirq; + hwif->ide_dma_test_irq = ide_vdma_test_irq; + hwif->dma_start = ide_vdma_start; + hwif->ide_dma_end = ide_vdma_end; + hwif->ide_dma_timeout = ide_vdma_timeout; + + hwif->drives[0].autodma = hwif->autodma; + + hwif->hwif_data = st; + hwif->dma_base = dma_base; + + return st; +} +EXPORT_SYMBOL(ide_vdma_init); + +void ide_vdma_fini(struct ide_vdma_state* st) +{ + if(!st) return; + + if(st->dmach != -1) pxa_free_dma(st->dmach); + kfree(st); +} +EXPORT_SYMBOL(ide_vdma_fini); +/* + * vim:ts=8 cino=>8 + */ diff -ruN -X ../../new8/kernel/diffignore.txt linux-2.6.21-orig/drivers/ide/ide.c linux-2.6.21/drivers/ide/ide.c --- linux-2.6.21-orig/drivers/ide/ide.c 2010-09-22 18:54:38.000000000 +0400 +++ linux-2.6.21/drivers/ide/ide.c 2010-09-22 19:34:51.000000000 +0400 @@ -1127,7 +1127,7 @@ ide_hwif_t *hwif = drive->hwif; int err = -EPERM; - if (!drive->id || !(drive->id->capability & 1)) + if ((!drive->id || !(drive->id->capability & 1)) && !drive->vdma) goto out; if (hwif->ide_dma_check == NULL) diff -ruN -X ../../new8/kernel/diffignore.txt linux-2.6.21-orig/drivers/ide/ide-io.c linux-2.6.21/drivers/ide/ide-io.c --- linux-2.6.21-orig/drivers/ide/ide-io.c 2010-09-22 18:54:38.000000000 +0400 +++ linux-2.6.21/drivers/ide/ide-io.c 2010-09-22 18:55:13.000000000 +0400 @@ -222,7 +222,7 @@ * we could be smarter and check for current xfer_speed * in struct drive etc... */ - if ((drive->id->capability & 1) == 0) + if ((drive->id->capability & 1) == 0 && drive->vdma == 0) break; if (drive->hwif->ide_dma_check == NULL) break; diff -ruN -X ../../new8/kernel/diffignore.txt linux-2.6.21-orig/drivers/ide/ide-vdma.h linux-2.6.21/drivers/ide/ide-vdma.h --- linux-2.6.21-orig/drivers/ide/ide-vdma.h 1970-01-01 03:00:00.000000000 +0300 +++ linux-2.6.21/drivers/ide/ide-vdma.h 2006-06-13 19:38:15.000000000 +0400 @@ -0,0 +1,19 @@ +/* + * Virtual DMA (PIO over DMA) handlers + * + * Copyright 2006 Kirill Kornilov + * + */ + +#ifndef _VDMA_H +#define _VDMA_H + +struct ide_vdma_state; + +/* initialize hwif for virtual DMA */ +extern struct ide_vdma_state *ide_vdma_init(ide_hwif_t *hwif, unsigned long dma_base); + +/* release resources */ +extern void ide_vdma_fini(struct ide_vdma_state* s); + +#endif diff -ruN -X ../../new8/kernel/diffignore.txt linux-2.6.21-orig/drivers/ide/Kconfig linux-2.6.21/drivers/ide/Kconfig --- linux-2.6.21-orig/drivers/ide/Kconfig 2010-09-22 18:54:38.000000000 +0400 +++ linux-2.6.21/drivers/ide/Kconfig 2010-09-22 19:05:56.000000000 +0400 @@ -170,6 +170,10 @@ Support for Compact Flash cards, outboard IDE disks, tape drives, and CD-ROM drives connected through a PCMCIA card. +config IDECS_VDMA + bool "Support PIO over DMA transfers (EXPERIMENTAL)" + depends on BLK_DEV_IDECS && IDE_VDMA && EXPERIMENTAL + config BLK_DEV_DELKIN tristate "Cardbus IDE support (Delkin/ASKA/Workbit)" depends on CARDBUS && PCI @@ -1042,7 +1046,7 @@ endif config BLK_DEV_IDEDMA - def_bool BLK_DEV_IDEDMA_PCI || BLK_DEV_IDEDMA_PMAC || BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA + def_bool BLK_DEV_IDEDMA_PCI || BLK_DEV_IDEDMA_PMAC || BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA || IDE_VDMA config IDEDMA_IVB bool "IGNORE word93 Validation BITS" @@ -1060,6 +1064,13 @@ It is normally safe to answer Y; however, the default is N. +config IDE_VDMA_PXA2xx + bool "Support PIO over DMA transfers with PXA2xx DMA controller (EXPERIMENTAL)" + depends on EXPERIMENTAL && PXA27x + +config IDE_VDMA + def_bool IDE_VDMA_PXA2xx + endif config BLK_DEV_HD_ONLY diff -ruN -X ../../new8/kernel/diffignore.txt linux-2.6.21-orig/drivers/ide/legacy/ide-cs.c linux-2.6.21/drivers/ide/legacy/ide-cs.c --- linux-2.6.21-orig/drivers/ide/legacy/ide-cs.c 2010-09-22 18:54:38.000000000 +0400 +++ linux-2.6.21/drivers/ide/legacy/ide-cs.c 2010-09-27 17:47:02.000000000 +0400 @@ -53,6 +53,10 @@ #include <pcmcia/cisreg.h> #include <pcmcia/ciscode.h> +#ifdef CONFIG_IDECS_VDMA +#include "ide-vdma.h" +#endif + /*====================================================================*/ /* Module parameters */ @@ -84,6 +88,9 @@ int ndev; dev_node_t node; int hd; +#ifdef CONFIG_IDECS_VDMA + void *vdma_data; +#endif } ide_info_t; static void ide_release(struct pcmcia_device *); @@ -106,6 +113,7 @@ { ide_info_t *info; + DEBUG(0, "ide_attach()\n"); /* Create new ide device */ @@ -145,15 +153,16 @@ kfree(link->priv); } /* ide_detach */ -static int idecs_register(unsigned long io, unsigned long ctl, unsigned long irq, struct pcmcia_device *handle) +static int idecs_register(ide_hwif_t **hwif, unsigned long io, unsigned long ctl, unsigned long irq, struct pcmcia_device *handle) { hw_regs_t hw; + memset(&hw, 0, sizeof(hw)); ide_init_hwif_ports(&hw, io, ctl, NULL); hw.irq = irq; hw.chipset = ide_pci; hw.dev = &handle->dev; - return ide_register_hw_with_fixup(&hw, NULL, ide_undecoded_slave); + return ide_register_hw_with_fixup(&hw, hwif, ide_undecoded_slave); } /*====================================================================== @@ -180,6 +189,10 @@ cistpl_cftable_entry_t *cfg; int i, pass, last_ret = 0, last_fn = 0, hd, is_kme = 0; unsigned long io_base, ctl_base; + ide_hwif_t *hwif; +#ifdef CONFIG_IDECS_VDMA + unsigned long dma_base; +#endif DEBUG(0, "ide_config(0x%p)\n", link); @@ -276,11 +289,11 @@ /* retry registration in case device is still spinning up */ for (hd = -1, i = 0; i < 10; i++) { - hd = idecs_register(io_base, ctl_base, link->irq.AssignedIRQ, link); + hd = idecs_register(&hwif, io_base, ctl_base, link->irq.AssignedIRQ, link); if (hd >= 0) break; if (link->io.NumPorts1 == 0x20) { outb(0x02, ctl_base + 0x10); - hd = idecs_register(io_base + 0x10, ctl_base + 0x10, + hd = idecs_register(&hwif, io_base + 0x10, ctl_base + 0x10, link->irq.AssignedIRQ, link); if (hd >= 0) { io_base += 0x10; @@ -298,6 +311,24 @@ goto failed; } +#ifdef CONFIG_IDECS_VDMA + if (pcmcia_get_phys_ioaddr(link, io_base, &dma_base) == CS_SUCCESS) { + info->vdma_data = ide_vdma_init(hwif, dma_base); + if (hwif->ide_dma_check) { + /* + * ide_dma_check is normally called from probe_hwif, + * but since dma hooks are installed after the ide_register_hw_with_fixup, + * we have to call dma_check here. + */ + for (i = 0; i < MAX_DRIVES; i++) { + ide_drive_t *drive = &hwif->drives[i]; + if (drive->present) + hwif->ide_dma_check(drive); + } + } + } +#endif + info->ndev = 1; sprintf(info->node.dev_name, "hd%c", 'a' + (hd * 2)); info->node.major = ide_major[hd]; @@ -342,11 +373,13 @@ ide_unregister(info->hd); } info->ndev = 0; - + +#ifdef CONFIG_IDECS_VDMA + ide_vdma_fini(info->vdma_data); +#endif pcmcia_disable_device(link); } /* ide_release */ - /*====================================================================== The card status event handler. Mostly, this schedules other @@ -407,6 +440,8 @@ PCMCIA_DEVICE_PROD_ID1("STI Flash", 0xe4a13209), PCMCIA_DEVICE_PROD_ID12("STI", "Flash 5.0", 0xbf2df18d, 0x8cb57a0e), PCMCIA_MFC_DEVICE_PROD_ID12(1, "SanDisk", "ConnectPlus", 0x7a954bd9, 0x74be00c6), + PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "04/05/06", 0x43d74cb4, 0x6a22777d), + PCMCIA_DEVICE_PROD_ID12("KINGSTON", "ELITE PRO CF CARD 32GB", 0x2e6d1829, 0x3526fdb3), PCMCIA_DEVICE_NULL, }; MODULE_DEVICE_TABLE(pcmcia, ide_ids); diff -ruN -X ../../new8/kernel/diffignore.txt linux-2.6.21-orig/drivers/ide/Makefile linux-2.6.21/drivers/ide/Makefile --- linux-2.6.21-orig/drivers/ide/Makefile 2010-09-22 18:54:38.000000000 +0400 +++ linux-2.6.21/drivers/ide/Makefile 2010-09-22 18:55:13.000000000 +0400 @@ -26,6 +26,7 @@ # built-in only drivers from arm/ ide-core-$(CONFIG_IDE_ARM) += arm/ide_arm.o +ide-core-$(CONFIG_IDE_VDMA_PXA2xx) += arm/ide-vdma-pxa2xx.o # built-in only drivers from legacy/ ide-core-$(CONFIG_BLK_DEV_BUDDHA) += legacy/buddha.o diff -ruN -X ../../new8/kernel/diffignore.txt linux-2.6.21-orig/drivers/pcmcia/soc_common.c linux-2.6.21/drivers/pcmcia/soc_common.c --- linux-2.6.21-orig/drivers/pcmcia/soc_common.c 2010-09-22 18:54:39.000000000 +0400 +++ linux-2.6.21/drivers/pcmcia/soc_common.c 2010-09-27 17:58:14.000000000 +0400 @@ -48,6 +48,8 @@ #include "soc_common.h" +#include <pcmcia/ds.h> + /* FIXME: platform dependent resource declaration has to move out of this file */ #ifdef CONFIG_ARCH_PXA #include <asm/arch/pxa-regs.h> @@ -378,7 +380,6 @@ return 0; } - /* * Implements the set_mem_map() operation for the in-kernel PCMCIA * service (formerly SS_SetMemMap in Card Services). We configure @@ -433,6 +434,17 @@ return 0; } +int pcmcia_get_phys_ioaddr(struct pcmcia_device *p_dev, ioaddr_t addr, unsigned long *phys_addr) +{ + struct pcmcia_socket *sock = p_dev->socket; + struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock); + + *phys_addr = (unsigned long)addr - (unsigned long)skt->virt_io + + skt->res_io.start; + return CS_SUCCESS; +} +EXPORT_SYMBOL(pcmcia_get_phys_ioaddr); + struct bittbl { unsigned int mask; const char *name; diff -ruN -X ../../new8/kernel/diffignore.txt linux-2.6.21-orig/include/pcmcia/cs.h linux-2.6.21/include/pcmcia/cs.h --- linux-2.6.21-orig/include/pcmcia/cs.h 2006-06-18 05:49:35.000000000 +0400 +++ linux-2.6.21/include/pcmcia/cs.h 2010-09-27 17:51:23.000000000 +0400 @@ -384,6 +384,7 @@ int pcmcia_request_io(struct pcmcia_device *p_dev, io_req_t *req); int pcmcia_request_irq(struct pcmcia_device *p_dev, irq_req_t *req); int pcmcia_request_window(struct pcmcia_device **p_dev, win_req_t *req, window_handle_t *wh); +int pcmcia_get_phys_ioaddr(struct pcmcia_device *p_dev, ioaddr_t addr, unsigned long *phys_addr); int pcmcia_suspend_card(struct pcmcia_socket *skt); int pcmcia_resume_card(struct pcmcia_socket *skt); int pcmcia_eject_card(struct pcmcia_socket *skt);
_______________________________________________ Zaurus-devel mailing list Zaurus-devel@lists.linuxtogo.org http://lists.linuxtogo.org/cgi-bin/mailman/listinfo/zaurus-devel