diff options
author | Jordan Crouse <jordan.crouse@amd.com> | 2005-12-15 02:17:46 +0100 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2005-12-15 02:17:46 +0100 |
commit | 8f29e650bffc1e22ed6b2d0b321bc77627f3bb7a (patch) | |
tree | d6b785c09c57a8f742e9a81162ee0d176677dc21 /drivers/ide/mips | |
parent | 65e5f2e3b457b6b20a5c4481312189d141a33d24 (diff) |
[PATCH] ide: AU1200 IDE update
Changes here include removing all of CONFIG_PM while it is being repeatedly
smacked with a lead pipe, moving the BURSTMODE param to a #define (it should
be defined almost always anyway), fixing the rqsize stuff, pulling ide_ioreg_t,
and general cleanups and whatnot.
Signed-off-by: Jordan Crouse <jordan.crouse@amd.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide/mips')
-rw-r--r-- | drivers/ide/mips/Makefile | 3 | ||||
-rw-r--r-- | drivers/ide/mips/au1xxx-ide.c | 1498 |
2 files changed, 535 insertions, 966 deletions
diff --git a/drivers/ide/mips/Makefile b/drivers/ide/mips/Makefile index 578e52a5958..677c7b2bac9 100644 --- a/drivers/ide/mips/Makefile +++ b/drivers/ide/mips/Makefile @@ -1 +1,4 @@ obj-$(CONFIG_BLK_DEV_IDE_SWARM) += swarm.o +obj-$(CONFIG_BLK_DEV_IDE_AU1XXX) += au1xxx-ide.o + +EXTRA_CFLAGS := -Idrivers/ide diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c index 2b6327c576b..32431dcf5d8 100644 --- a/drivers/ide/mips/au1xxx-ide.c +++ b/drivers/ide/mips/au1xxx-ide.c @@ -31,865 +31,638 @@ */ #undef REALLY_SLOW_IO /* most systems can safely undef this */ -#include <linux/config.h> /* for CONFIG_BLK_DEV_IDEPCI */ #include <linux/types.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/delay.h> -#include <linux/timer.h> -#include <linux/mm.h> -#include <linux/ioport.h> -#include <linux/hdreg.h> +#include <linux/platform_device.h> + #include <linux/init.h> #include <linux/ide.h> #include <linux/sysdev.h> #include <linux/dma-mapping.h> +#include "ide-timing.h" + #include <asm/io.h> #include <asm/mach-au1x00/au1xxx.h> #include <asm/mach-au1x00/au1xxx_dbdma.h> -#if CONFIG_PM -#include <asm/mach-au1x00/au1xxx_pm.h> -#endif - #include <asm/mach-au1x00/au1xxx_ide.h> #define DRV_NAME "au1200-ide" #define DRV_VERSION "1.0" -#define DRV_AUTHOR "AMD PCS / Pete Popov <ppopov@embeddedalley.com>" -#define DRV_DESC "Au1200 IDE" - -static _auide_hwif auide_hwif; -static spinlock_t ide_tune_drive_spin_lock = SPIN_LOCK_UNLOCKED; -static spinlock_t ide_tune_chipset_spin_lock = SPIN_LOCK_UNLOCKED; -static int dbdma_init_done = 0; - -/* - * local I/O functions - */ -u8 auide_inb(unsigned long port) -{ - return (au_readb(port)); -} +#define DRV_AUTHOR "Enrico Walther <enrico.walther@amd.com> / Pete Popov <ppopov@embeddedalley.com>" -u16 auide_inw(unsigned long port) -{ - return (au_readw(port)); -} +/* enable the burstmode in the dbdma */ +#define IDE_AU1XXX_BURSTMODE 1 -u32 auide_inl(unsigned long port) -{ - return (au_readl(port)); -} +static _auide_hwif auide_hwif; +static int dbdma_init_done; -void auide_insw(unsigned long port, void *addr, u32 count) -{ #if defined(CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA) - _auide_hwif *ahwif = &auide_hwif; - chan_tab_t *ctp; - au1x_ddma_desc_t *dp; - - if(!put_dest_flags(ahwif->rx_chan, (void*)addr, count << 1, - DDMA_FLAGS_NOIE)) { - printk(KERN_ERR "%s failed %d\n", __FUNCTION__, __LINE__); - return; - } - ctp = *((chan_tab_t **)ahwif->rx_chan); - dp = ctp->cur_ptr; - while (dp->dscr_cmd0 & DSCR_CMD0_V) - ; - ctp->cur_ptr = au1xxx_ddma_get_nextptr_virt(dp); -#else - while (count--) - { - *(u16 *)addr = au_readw(port); - addr +=2 ; - } -#endif -} - -void auide_insl(unsigned long port, void *addr, u32 count) -{ - while (count--) - { - *(u32 *)addr = au_readl(port); - /* NOTE: For IDE interfaces over PCMCIA, - * 32-bit access does not work - */ - addr += 4; - } -} - -void auide_outb(u8 addr, unsigned long port) +void auide_insw(unsigned long port, void *addr, u32 count) { - return (au_writeb(addr, port)); -} + _auide_hwif *ahwif = &auide_hwif; + chan_tab_t *ctp; + au1x_ddma_desc_t *dp; -void auide_outbsync(ide_drive_t *drive, u8 addr, unsigned long port) -{ - return (au_writeb(addr, port)); + if(!put_dest_flags(ahwif->rx_chan, (void*)addr, count << 1, + DDMA_FLAGS_NOIE)) { + printk(KERN_ERR "%s failed %d\n", __FUNCTION__, __LINE__); + return; + } + ctp = *((chan_tab_t **)ahwif->rx_chan); + dp = ctp->cur_ptr; + while (dp->dscr_cmd0 & DSCR_CMD0_V) + ; + ctp->cur_ptr = au1xxx_ddma_get_nextptr_virt(dp); } -void auide_outw(u16 addr, unsigned long port) +void auide_outsw(unsigned long port, void *addr, u32 count) { - return (au_writew(addr, port)); -} + _auide_hwif *ahwif = &auide_hwif; + chan_tab_t *ctp; + au1x_ddma_desc_t *dp; -void auide_outl(u32 addr, unsigned long port) -{ - return (au_writel(addr, port)); + if(!put_source_flags(ahwif->tx_chan, (void*)addr, + count << 1, DDMA_FLAGS_NOIE)) { + printk(KERN_ERR "%s failed %d\n", __FUNCTION__, __LINE__); + return; + } + ctp = *((chan_tab_t **)ahwif->tx_chan); + dp = ctp->cur_ptr; + while (dp->dscr_cmd0 & DSCR_CMD0_V) + ; + ctp->cur_ptr = au1xxx_ddma_get_nextptr_virt(dp); } -void auide_outsw(unsigned long port, void *addr, u32 count) -{ -#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA) - _auide_hwif *ahwif = &auide_hwif; - chan_tab_t *ctp; - au1x_ddma_desc_t *dp; - - if(!put_source_flags(ahwif->tx_chan, (void*)addr, - count << 1, DDMA_FLAGS_NOIE)) { - printk(KERN_ERR "%s failed %d\n", __FUNCTION__, __LINE__); - return; - } - ctp = *((chan_tab_t **)ahwif->tx_chan); - dp = ctp->cur_ptr; - while (dp->dscr_cmd0 & DSCR_CMD0_V) - ; - ctp->cur_ptr = au1xxx_ddma_get_nextptr_virt(dp); -#else - while (count--) - { - au_writew(*(u16 *)addr, port); - addr += 2; - } #endif -} - -void auide_outsl(unsigned long port, void *addr, u32 count) -{ - while (count--) - { - au_writel(*(u32 *)addr, port); - /* NOTE: For IDE interfaces over PCMCIA, - * 32-bit access does not work - */ - addr += 4; - } -} static void auide_tune_drive(ide_drive_t *drive, byte pio) { - int mem_sttime; - int mem_stcfg; - unsigned long flags; - u8 speed; - - /* get the best pio mode for the drive */ - pio = ide_get_best_pio_mode(drive, pio, 4, NULL); - - printk("%s: setting Au1XXX IDE to PIO mode%d\n", - drive->name, pio); - - spin_lock_irqsave(&ide_tune_drive_spin_lock, flags); - - mem_sttime = 0; - mem_stcfg = au_readl(MEM_STCFG2); - - /* set pio mode! */ - switch(pio) { - case 0: - /* set timing parameters for RCS2# */ - mem_sttime = SBC_IDE_PIO0_TWCS - | SBC_IDE_PIO0_TCSH - | SBC_IDE_PIO0_TCSOFF - | SBC_IDE_PIO0_TWP - | SBC_IDE_PIO0_TCSW - | SBC_IDE_PIO0_TPM - | SBC_IDE_PIO0_TA; - /* set configuration for RCS2# */ - mem_stcfg |= TS_MASK; - mem_stcfg &= ~TCSOE_MASK; - mem_stcfg &= ~TOECS_MASK; - mem_stcfg |= SBC_IDE_PIO0_TCSOE | SBC_IDE_PIO0_TOECS; - - au_writel(mem_sttime,MEM_STTIME2); - au_writel(mem_stcfg,MEM_STCFG2); - break; - - case 1: - /* set timing parameters for RCS2# */ - mem_sttime = SBC_IDE_PIO1_TWCS - | SBC_IDE_PIO1_TCSH - | SBC_IDE_PIO1_TCSOFF - | SBC_IDE_PIO1_TWP - | SBC_IDE_PIO1_TCSW - | SBC_IDE_PIO1_TPM - | SBC_IDE_PIO1_TA; - /* set configuration for RCS2# */ - mem_stcfg |= TS_MASK; - mem_stcfg &= ~TCSOE_MASK; - mem_stcfg &= ~TOECS_MASK; - mem_stcfg |= SBC_IDE_PIO1_TCSOE | SBC_IDE_PIO1_TOECS; - break; - - case 2: - /* set timing parameters for RCS2# */ - mem_sttime = SBC_IDE_PIO2_TWCS - | SBC_IDE_PIO2_TCSH - | SBC_IDE_PIO2_TCSOFF - | SBC_IDE_PIO2_TWP - | SBC_IDE_PIO2_TCSW - | SBC_IDE_PIO2_TPM - | SBC_IDE_PIO2_TA; - /* set configuration for RCS2# */ - mem_stcfg &= ~TS_MASK; - mem_stcfg &= ~TCSOE_MASK; - mem_stcfg &= ~TOECS_MASK; - mem_stcfg |= SBC_IDE_PIO2_TCSOE | SBC_IDE_PIO2_TOECS; - break; - - case 3: - /* set timing parameters for RCS2# */ - mem_sttime = SBC_IDE_PIO3_TWCS - | SBC_IDE_PIO3_TCSH - | SBC_IDE_PIO3_TCSOFF - | SBC_IDE_PIO3_TWP - | SBC_IDE_PIO3_TCSW - | SBC_IDE_PIO3_TPM - | SBC_IDE_PIO3_TA; - /* set configuration for RCS2# */ - mem_stcfg |= TS_MASK; - mem_stcfg &= ~TS_MASK; - mem_stcfg &= ~TCSOE_MASK; - mem_stcfg &= ~TOECS_MASK; - mem_stcfg |= SBC_IDE_PIO3_TCSOE | SBC_IDE_PIO3_TOECS; - - break; - - case 4: - /* set timing parameters for RCS2# */ - mem_sttime = SBC_IDE_PIO4_TWCS - | SBC_IDE_PIO4_TCSH - | SBC_IDE_PIO4_TCSOFF - | SBC_IDE_PIO4_TWP - | SBC_IDE_PIO4_TCSW - | SBC_IDE_PIO4_TPM - | SBC_IDE_PIO4_TA; - /* set configuration for RCS2# */ - mem_stcfg &= ~TS_MASK; - mem_stcfg &= ~TCSOE_MASK; - mem_stcfg &= ~TOECS_MASK; - mem_stcfg |= SBC_IDE_PIO4_TCSOE | SBC_IDE_PIO4_TOECS; - break; - } - - au_writel(mem_sttime,MEM_STTIME2); - au_writel(mem_stcfg,MEM_STCFG2); - - spin_unlock_irqrestore(&ide_tune_drive_spin_lock, flags); - - speed = pio + XFER_PIO_0; - ide_config_drive_speed(drive, speed); + int mem_sttime; + int mem_stcfg; + u8 speed; + + /* get the best pio mode for the drive */ + pio = ide_get_best_pio_mode(drive, pio, 4, NULL); + + printk(KERN_INFO "%s: setting Au1XXX IDE to PIO mode%d\n", + drive->name, pio); + + mem_sttime = 0; + mem_stcfg = au_readl(MEM_STCFG2); + + /* set pio mode! */ + switch(pio) { + case 0: + mem_sttime = SBC_IDE_TIMING(PIO0); + + /* set configuration for RCS2# */ + mem_stcfg |= TS_MASK; + mem_stcfg &= ~TCSOE_MASK; + mem_stcfg &= ~TOECS_MASK; + mem_stcfg |= SBC_IDE_PIO0_TCSOE | SBC_IDE_PIO0_TOECS; + break; + + case 1: + mem_sttime = SBC_IDE_TIMING(PIO1); + + /* set configuration for RCS2# */ + mem_stcfg |= TS_MASK; + mem_stcfg &= ~TCSOE_MASK; + mem_stcfg &= ~TOECS_MASK; + mem_stcfg |= SBC_IDE_PIO1_TCSOE | SBC_IDE_PIO1_TOECS; + break; + + case 2: + mem_sttime = SBC_IDE_TIMING(PIO2); + + /* set configuration for RCS2# */ + mem_stcfg &= ~TS_MASK; + mem_stcfg &= ~TCSOE_MASK; + mem_stcfg &= ~TOECS_MASK; + mem_stcfg |= SBC_IDE_PIO2_TCSOE | SBC_IDE_PIO2_TOECS; + break; + + case 3: + mem_sttime = SBC_IDE_TIMING(PIO3); + + /* set configuration for RCS2# */ + mem_stcfg &= ~TS_MASK; + mem_stcfg &= ~TCSOE_MASK; + mem_stcfg &= ~TOECS_MASK; + mem_stcfg |= SBC_IDE_PIO3_TCSOE | SBC_IDE_PIO3_TOECS; + + break; + + case 4: + mem_sttime = SBC_IDE_TIMING(PIO4); + + /* set configuration for RCS2# */ + mem_stcfg &= ~TS_MASK; + mem_stcfg &= ~TCSOE_MASK; + mem_stcfg &= ~TOECS_MASK; + mem_stcfg |= SBC_IDE_PIO4_TCSOE | SBC_IDE_PIO4_TOECS; + break; + } + + au_writel(mem_sttime,MEM_STTIME2); + au_writel(mem_stcfg,MEM_STCFG2); + + speed = pio + XFER_PIO_0; + ide_config_drive_speed(drive, speed); } static int auide_tune_chipset (ide_drive_t *drive, u8 speed) { - u8 mode = 0; - int mem_sttime; - int mem_stcfg; - unsigned long flags; + int mem_sttime; + int mem_stcfg; + unsigned long mode; + #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA - struct hd_driveid *id = drive->id; - - /* - * Now see what the current drive is capable of, - * selecting UDMA only if the mate said it was ok. - */ - if (id && (id->capability & 1) && drive->autodma && - !__ide_dma_bad_drive(drive)) { - if (!mode && (id->field_valid & 2) && (id->dma_mword & 7)) { - if (id->dma_mword & 4) - mode = XFER_MW_DMA_2; - else if (id->dma_mword & 2) - mode = XFER_MW_DMA_1; - else if (id->dma_mword & 1) - mode = XFER_MW_DMA_0; - } - } + if (ide_use_dma(drive)) + mode = ide_dma_speed(drive, 0); #endif - spin_lock_irqsave(&ide_tune_chipset_spin_lock, flags); + mem_sttime = 0; + mem_stcfg = au_readl(MEM_STCFG2); - mem_sttime = 0; - mem_stcfg = au_readl(MEM_STCFG2); - - switch(speed) { - case XFER_PIO_4: - case XFER_PIO_3: - case XFER_PIO_2: - case XFER_PIO_1: - case XFER_PIO_0: - auide_tune_drive(drive, (speed - XFER_PIO_0)); - break; + if (speed >= XFER_PIO_0 && speed <= XFER_PIO_4) { + auide_tune_drive(drive, speed - XFER_PIO_0); + return 0; + } + + switch(speed) { #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA - case XFER_MW_DMA_2: - /* set timing parameters for RCS2# */ - mem_sttime = SBC_IDE_MDMA2_TWCS - | SBC_IDE_MDMA2_TCSH - | SBC_IDE_MDMA2_TCSOFF - | SBC_IDE_MDMA2_TWP - | SBC_IDE_MDMA2_TCSW - | SBC_IDE_MDMA2_TPM - | SBC_IDE_MDMA2_TA; - /* set configuration for RCS2# */ - mem_stcfg &= ~TS_MASK; - mem_stcfg &= ~TCSOE_MASK; - mem_stcfg &= ~TOECS_MASK; - mem_stcfg |= SBC_IDE_MDMA2_TCSOE | SBC_IDE_MDMA2_TOECS; - - mode = XFER_MW_DMA_2; - break; - case XFER_MW_DMA_1: - /* set timing parameters for RCS2# */ - mem_sttime = SBC_IDE_MDMA1_TWCS - | SBC_IDE_MDMA1_TCSH - | SBC_IDE_MDMA1_TCSOFF - | SBC_IDE_MDMA1_TWP - | SBC_IDE_MDMA1_TCSW - | SBC_IDE_MDMA1_TPM - | SBC_IDE_MDMA1_TA; - /* set configuration for RCS2# */ - mem_stcfg &= ~TS_MASK; - mem_stcfg &= ~TCSOE_MASK; - mem_stcfg &= ~TOECS_MASK; - mem_stcfg |= SBC_IDE_MDMA1_TCSOE | SBC_IDE_MDMA1_TOECS; - - mode = XFER_MW_DMA_1; - break; - case XFER_MW_DMA_0: - /* set timing parameters for RCS2# */ - mem_sttime = SBC_IDE_MDMA0_TWCS - | SBC_IDE_MDMA0_TCSH - | SBC_IDE_MDMA0_TCSOFF - | SBC_IDE_MDMA0_TWP - | SBC_IDE_MDMA0_TCSW - | SBC_IDE_MDMA0_TPM - | SBC_IDE_MDMA0_TA; - /* set configuration for RCS2# */ - mem_stcfg |= TS_MASK; - mem_stcfg &= ~TCSOE_MASK; - mem_stcfg &= ~TOECS_MASK; - mem_stcfg |= SBC_IDE_MDMA0_TCSOE | SBC_IDE_MDMA0_TOECS; - - mode = XFER_MW_DMA_0; - break; + case XFER_MW_DMA_2: + mem_sttime = SBC_IDE_TIMING(MDMA2); + + /* set configuration for RCS2# */ + mem_stcfg &= ~TS_MASK; + mem_stcfg &= ~TCSOE_MASK; + mem_stcfg &= ~TOECS_MASK; + mem_stcfg |= SBC_IDE_MDMA2_TCSOE | SBC_IDE_MDMA2_TOECS; + + mode = XFER_MW_DMA_2; + break; + case XFER_MW_DMA_1: + mem_sttime = SBC_IDE_TIMING(MDMA1); + + /* set configuration for RCS2# */ + mem_stcfg &= ~TS_MASK; + mem_stcfg &= ~TCSOE_MASK; + mem_stcfg &= ~TOECS_MASK; + mem_stcfg |= SBC_IDE_MDMA1_TCSOE | SBC_IDE_MDMA1_TOECS; + + mode = XFER_MW_DMA_1; + break; + case XFER_MW_DMA_0: + mem_sttime = SBC_IDE_TIMING(MDMA0); + + /* set configuration for RCS2# */ + mem_stcfg |= TS_MASK; + mem_stcfg &= ~TCSOE_MASK; + mem_stcfg &= ~TOECS_MASK; + mem_stcfg |= SBC_IDE_MDMA0_TCSOE | SBC_IDE_MDMA0_TOECS; + + mode = XFER_MW_DMA_0; + break; #endif - default: - return 1; - } - - /* - * Tell the drive to switch to the new mode; abort on failure. - */ - if (!mode || ide_config_drive_speed(drive, mode)) - { - return 1; /* failure */ - } - - - au_writel(mem_sttime,MEM_STTIME2); - au_writel(mem_stcfg,MEM_STCFG2); + default: + return 1; + } + + if (ide_config_drive_speed(drive, mode)) + return 1; - spin_unlock_irqrestore(&ide_tune_chipset_spin_lock, flags); + au_writel(mem_sttime,MEM_STTIME2); + au_writel(mem_stcfg,MEM_STCFG2); - return 0; + return 0; } /* * Multi-Word DMA + DbDMA functions */ -#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA -static int in_drive_list(struct hd_driveid *id, - const struct drive_list_entry *drive_table) -{ - for ( ; drive_table->id_model ; drive_table++){ - if ((!strcmp(drive_table->id_model, id->model)) && - ((strstr(drive_table->id_firmware, id->fw_rev)) || - (!strcmp(drive_table->id_firmware, "ALL"))) - ) - return 1; - } - return 0; -} +#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA static int auide_build_sglist(ide_drive_t *drive, struct request *rq) { - ide_hwif_t *hwif = drive->hwif; - _auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data; - struct scatterlist *sg = hwif->sg_table; + ide_hwif_t *hwif = drive->hwif; + _auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data; + struct scatterlist *sg = hwif->sg_table; - ide_map_sg(drive, rq); + ide_map_sg(drive, rq); - if (rq_data_dir(rq) == READ) - hwif->sg_dma_direction = DMA_FROM_DEVICE; - else - hwif->sg_dma_direction = DMA_TO_DEVICE; + if (rq_data_dir(rq) == READ) + hwif->sg_dma_direction = DMA_FROM_DEVICE; + else + hwif->sg_dma_direction = DMA_TO_DEVICE; - return dma_map_sg(ahwif->dev, sg, hwif->sg_nents, - hwif->sg_dma_direction); + return dma_map_sg(ahwif->dev, sg, hwif->sg_nents, + hwif->sg_dma_direction); } static int auide_build_dmatable(ide_drive_t *drive) { - int i, iswrite, count = 0; - ide_hwif_t *hwif = HWIF(drive); - - struct request *rq = HWGROUP(drive)->rq; - - _auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data; - struct scatterlist *sg; - - iswrite = (rq_data_dir(rq) == WRITE); - /* Save for interrupt context */ - ahwif->drive = drive; - - /* Build sglist */ - hwif->sg_nents = i = auide_build_sglist(drive, rq); - - if (!i) - return 0; - - /* fill the descriptors */ - sg = hwif->sg_table; - while (i && sg_dma_len(sg)) { - u32 cur_addr; - u32 cur_len; - - cur_addr = sg_dma_address(sg); - cur_len = sg_dma_len(sg); - - while (cur_len) { - u32 flags = DDMA_FLAGS_NOIE; - unsigned int tc = (cur_len < 0xfe00)? cur_len: 0xfe00; - - if (++count >= PRD_ENTRIES) { - printk(KERN_WARNING "%s: DMA table too small\n", - drive->name); - goto use_pio_instead; - } - - /* Lets enable intr for the last descriptor only */ - if (1==i) - flags = DDMA_FLAGS_IE; - else - flags = DDMA_FLAGS_NOIE; - - if (iswrite) { - if(!put_source_flags(ahwif->tx_chan, - (void*)(page_address(sg->page) - + sg->offset), - tc, flags)) { - printk(KERN_ERR "%s failed %d\n", - __FUNCTION__, __LINE__); + int i, iswrite, count = 0; + ide_hwif_t *hwif = HWIF(drive); + + struct request *rq = HWGROUP(drive)->rq; + + _auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data; + struct scatterlist *sg; + + iswrite = (rq_data_dir(rq) == WRITE); + /* Save for interrupt context */ + ahwif->drive = drive; + + /* Build sglist */ + hwif->sg_nents = i = auide_build_sglist(drive, rq); + + if (!i) + return 0; + + /* fill the descriptors */ + sg = hwif->sg_table; + while (i && sg_dma_len(sg)) { + u32 cur_addr; + u32 cur_len; + + cur_addr = sg_dma_address(sg); + cur_len = sg_dma_len(sg); + + while (cur_len) { + u32 flags = DDMA_FLAGS_NOIE; + unsigned int tc = (cur_len < 0xfe00)? cur_len: 0xfe00; + + if (++count >= PRD_ENTRIES) { + printk(KERN_WARNING "%s: DMA table too small\n", + drive->name); + goto use_pio_instead; + } + + /* Lets enable intr for the last descriptor only */ + if (1==i) + flags = DDMA_FLAGS_IE; + else + flags = DDMA_FLAGS_NOIE; + + if (iswrite) { + if(!put_source_flags(ahwif->tx_chan, + (void*)(page_address(sg->page) + + sg->offset), + tc, flags)) { + printk(KERN_ERR "%s failed %d\n", + __FUNCTION__, __LINE__); } - } else + } else { - if(!put_dest_flags(ahwif->rx_chan, - (void*)(page_address(sg->page) - + sg->offset), - tc, flags)) { - printk(KERN_ERR "%s failed %d\n", - __FUNCTION__, __LINE__); + if(!put_dest_flags(ahwif->rx_chan, + (void*)(page_address(sg->page) + + sg->offset), + tc, flags)) { + printk(KERN_ERR "%s failed %d\n", + __FUNCTION__, __LINE__); } - } + } - cur_addr += tc; - cur_len -= tc; - } - sg++; - i--; - } + cur_addr += tc; + cur_len -= tc; + } + sg++; + i--; + } - if (count) - return 1; + if (count) + return 1; -use_pio_instead: - dma_unmap_sg(ahwif->dev, - hwif->sg_table, - hwif->sg_nents, - hwif->sg_dma_direction); + use_pio_instead: + dma_unmap_sg(ahwif->dev, + hwif->sg_table, + hwif->sg_nents, + hwif->sg_dma_direction); - return 0; /* revert to PIO for this request */ + return 0; /* revert to PIO for this request */ } static int auide_dma_end(ide_drive_t *drive) { - ide_hwif_t *hwif = HWIF(drive); - _auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data; + ide_hwif_t *hwif = HWIF(drive); + _auide_hwif *ahwif = (_auide_hwif*)hwif->hwif_data; - if (hwif->sg_nents) { - dma_unmap_sg(ahwif->dev, hwif->sg_table, hwif->sg_nents, - hwif->sg_dma_direction); - hwif->sg_nents = 0; - } + if (hwif->sg_nents) { + dma_unmap_sg(ahwif->dev, hwif->sg_table, hwif->sg_nents, + hwif->sg_dma_direction); + hwif->sg_nents = 0; + } - return 0; + return 0; } static void auide_dma_start(ide_drive_t *drive ) { -// printk("%s\n", __FUNCTION__); } -ide_startstop_t auide_dma_intr(ide_drive_t *drive) -{ - //printk("%s\n", __FUNCTION__); - - u8 stat = 0, dma_stat = 0; - - dma_stat = HWIF(drive)->ide_dma_end(drive); - stat = HWIF(drive)->INB(IDE_STATUS_REG); /* get drive status */ - if (OK_STAT(stat,DRIVE_READY,drive->bad_wstat|DRQ_STAT)) { - if (!dma_stat) { - struct request *rq = HWGROUP(drive)->rq; - - ide_end_request(drive, 1, rq->nr_sectors); - return ide_stopped; - } - printk(KERN_ERR "%s: dma_intr: bad DMA status (dma_stat=%x)\n", - drive->name, dma_stat); - } - return ide_error(drive, "dma_intr", stat); -} static void auide_dma_exec_cmd(ide_drive_t *drive, u8 command) { - //printk("%s\n", __FUNCTION__); - - /* issue cmd to drive */ - ide_execute_command(drive, command, &auide_dma_intr, - (2*WAIT_CMD), NULL); + /* issue cmd to drive */ + ide_execute_command(drive, command, &ide_dma_intr, + (2*WAIT_CMD), NULL); } static int auide_dma_setup(ide_drive_t *drive) -{ -// printk("%s\n", __FUNCTION__); - - if (drive->media != ide_disk) - return 1; - - if (!auide_build_dmatable(drive)) - /* try PIO instead of DMA */ - return 1; +{ + struct request *rq = HWGROUP(drive)->rq; - drive->waiting_for_dma = 1; + if (!auide_build_dmatable(drive)) { + ide_map_sg(drive, rq); + return 1; + } - return 0; + drive->waiting_for_dma = 1; + return 0; } static int auide_dma_check(ide_drive_t *drive) { -// printk("%s\n", __FUNCTION__); + u8 speed; #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA - if( !dbdma_init_done ){ - auide_hwif.white_list = in_drive_list(drive->id, - dma_white_list); - auide_hwif.black_list = in_drive_list(drive->id, - dma_black_list); - auide_hwif.drive = drive; - auide_ddma_init(&auide_hwif); - dbdma_init_done = 1; - } + + if( dbdma_init_done == 0 ){ + auide_hwif.white_list = ide_in_drive_list(drive->id, + dma_white_list); + auide_hwif.black_list = ide_in_drive_list(drive->id, + dma_black_list); + auide_hwif.drive = drive; + auide_ddma_init(&auide_hwif); + dbdma_init_done = 1; + } #endif - /* Is the drive in our DMA black list? */ - if ( auide_hwif.black_list ) { - drive->using_dma = 0; - printk("%s found in dma_blacklist[]! Disabling DMA.\n", - drive->id->model); - } - else - drive->using_dma = 1; + /* Is the drive in our DMA black list? */ + + if ( auide_hwif.black_list ) { + drive->using_dma = 0; + + /* Borrowed the warning message from ide-dma.c */ - return HWIF(drive)->ide_dma_host_on(drive); + printk(KERN_WARNING "%s: Disabling DMA for %s (blacklisted)\n", + drive->name, drive->id->model); + } + else + drive->using_dma = 1; + + speed = ide_find_best_mode(drive, XFER_PIO | XFER_MWDMA); + + if (drive->autodma && (speed & XFER_MODE) != XFER_PIO) + return HWIF(drive)->ide_dma_on(drive); + + return HWIF(drive)->ide_dma_off_quietly(drive); } static int auide_dma_test_irq(ide_drive_t *drive) -{ -// printk("%s\n", __FUNCTION__); - - if (!drive->waiting_for_dma) - printk(KERN_WARNING "%s: ide_dma_test_irq \ +{ + if (drive->waiting_for_dma == 0) + printk(KERN_WARNING "%s: ide_dma_test_irq \ called while not waiting\n", drive->name); - /* If dbdma didn't execute the STOP command yet, the - * active bit is still set + /* If dbdma didn't execute the STOP command yet, the + * active bit is still set */ - drive->waiting_for_dma++; - if (drive->waiting_for_dma >= DMA_WAIT_TIMEOUT) { - printk(KERN_WARNING "%s: timeout waiting for ddma to \ + drive->waiting_for_dma++; + if (drive->waiting_for_dma >= DMA_WAIT_TIMEOUT) { + printk(KERN_WARNING "%s: timeout waiting for ddma to \ complete\n", drive->name); - return 1; - } - udelay(10); - return 0; + return 1; + } + udelay(10); + return 0; } static int auide_dma_host_on(ide_drive_t *drive) { -// printk("%s\n", __FUNCTION__); - return 0; + return 0; } static int auide_dma_on(ide_drive_t *drive) { -// printk("%s\n", __FUNCTION__); - drive->using_dma = 1; - return auide_dma_host_on(drive); + drive->using_dma = 1; + return auide_dma_host_on(drive); } static int auide_dma_host_off(ide_drive_t *drive) { -// printk("%s\n", __FUNCTION__); - return 0; + return 0; } static int auide_dma_off_quietly(ide_drive_t *drive) { -// printk("%s\n", __FUNCTION__); - drive->using_dma = 0; - return auide_dma_host_off(drive); + drive->using_dma = 0; + return auide_dma_host_off(drive); } static int auide_dma_lostirq(ide_drive_t *drive) { -// printk("%s\n", __FUNCTION__); - - printk(KERN_ERR "%s: IRQ lost\n", drive->name); - return 0; + printk(KERN_ERR "%s: IRQ lost\n", drive->name); + return 0; } static void auide_ddma_tx_callback(int irq, void *param, struct pt_regs *regs) { -// printk("%s\n", __FUNCTION__); - - _auide_hwif *ahwif = (_auide_hwif*)param; - ahwif->drive->waiting_for_dma = 0; - return; + _auide_hwif *ahwif = (_auide_hwif*)param; + ahwif->drive->waiting_for_dma = 0; } static void auide_ddma_rx_callback(int irq, void *param, struct pt_regs *regs) { -// printk("%s\n", __FUNCTION__); + _auide_hwif *ahwif = (_auide_hwif*)param; + ahwif->drive->waiting_for_dma = 0; +} + +#endif /* end CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA */ - _auide_hwif *ahwif = (_auide_hwif*)param; - ahwif->drive->waiting_for_dma = 0; - return; +static void auide_init_dbdma_dev(dbdev_tab_t *dev, u32 dev_id, u32 tsize, u32 devwidth, u32 flags) +{ + dev->dev_id = dev_id; + dev->dev_physaddr = (u32)AU1XXX_ATA_PHYS_ADDR; + dev->dev_intlevel = 0; + dev->dev_intpolarity = 0; + dev->dev_tsize = tsize; + dev->dev_devwidth = devwidth; + dev->dev_flags = flags; } + +#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA) static int auide_dma_timeout(ide_drive_t *drive) { // printk("%s\n", __FUNCTION__); - printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name); + printk(KERN_ERR "%s: DMA timeout occurred: ", drive->name); - if (HWIF(drive)->ide_dma_test_irq(drive)) - return 0; + if (HWIF(drive)->ide_dma_test_irq(drive)) + return 0; - return HWIF(drive)->ide_dma_end(drive); + return HWIF(drive)->ide_dma_end(drive); } -#endif /* end CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA */ + +static int auide_ddma_init(_auide_hwif *auide) { + + dbdev_tab_t source_dev_tab, target_dev_tab; + u32 dev_id, tsize, devwidth, flags; + ide_hwif_t *hwif = auide->hwif; -static int auide_ddma_init( _auide_hwif *auide ) -{ -// printk("%s\n", __FUNCTION__); + dev_id = AU1XXX_ATA_DDMA_REQ; - dbdev_tab_t source_dev_tab; -#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA) - dbdev_tab_t target_dev_tab; - ide_hwif_t *hwif = auide->hwif; - char warning_output [2][80]; - int i; -#endif + if (auide->white_list || auide->black_list) { + tsize = 8; + devwidth = 32; + } + else { + tsize = 1; + devwidth = 16; + + printk(KERN_ERR "au1xxx-ide: %s is not on ide driver whitelist.\n",auide_hwif.drive->id->model); + printk(KERN_ERR " please read 'Documentation/mips/AU1xxx_IDE.README'"); + } - /* Add our custom device to DDMA device table */ - /* Create our new device entries in the table */ -#if defined(CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA) - source_dev_tab.dev_id = AU1XXX_ATA_DDMA_REQ; - - if( auide->white_list || auide->black_list ){ - source_dev_tab.dev_tsize = 8; - source_dev_tab.dev_devwidth = 32; - source_dev_tab.dev_physaddr = (u32)AU1XXX_ATA_PHYS_ADDR; - source_dev_tab.dev_intlevel = 0; - source_dev_tab |