diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-11 19:20:44 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-11 19:20:44 -0700 |
commit | 19f71153b9be219756c6b2757921433a69b7975c (patch) | |
tree | cc2c5c290a88d61df16848f733aed8708e82c119 /drivers/ide/ide-lib.c | |
parent | e6005a85acb9609326512ecc784859831cfb24a3 (diff) | |
parent | 8f4dd2e42637fd61a6366d2cace69091926eaa15 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/bart/ide-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/bart/ide-2.6: (24 commits)
ide: use only ->set_pio_mode method for programming PIO modes (take 2)
sis5513: don't change UDMA settings when programming PIO
it8213/piix/slc90e66: don't change DMA settings when programming PIO
alim15x3: PIO mode setup fixes
siimage: fix ->set_pio_mode method to select PIO data transfer
cs5520: don't enable VDMA in ->speedproc
sc1200: remove redundant warning message from sc1200_tune_chipset()
ide-pmac: PIO mode setup fixes (take 3)
icside: fix ->speedproc to return on unsupported modes (take 5)
sgiioc4: use ide_tune_dma()
amd74xx/via82cxxx: use ide_tune_dma()
ide: add ide_set{_max}_pio() (take 4)
ide: Kconfig face-lift
ide: move ide_rate_filter() calls to the upper layer (take 2)
sis5513: add ->udma_filter method for chipset_family >= ATA_133
ide: mode limiting fixes for user requested speed changes
ide: add missing ide_rate_filter() calls to ->speedproc()-s
ide: call udma_filter() before resorting to the UltraDMA mask
ide: make jmicron match vendor and device class
pdc202xx_new: switch to using pci_get_slot() (take 2)
...
Diffstat (limited to 'drivers/ide/ide-lib.c')
-rw-r--r-- | drivers/ide/ide-lib.c | 85 |
1 files changed, 56 insertions, 29 deletions
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index 92a6c7bcf527..d97390c0543b 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c @@ -76,41 +76,26 @@ EXPORT_SYMBOL(ide_xfer_verbose); * Given the available transfer modes this function returns * the best available speed at or below the speed requested. * - * FIXME: filter also PIO/SWDMA/MWDMA modes + * TODO: check device PIO capabilities */ -u8 ide_rate_filter(ide_drive_t *drive, u8 speed) +static u8 ide_rate_filter(ide_drive_t *drive, u8 speed) { -#ifdef CONFIG_BLK_DEV_IDEDMA ide_hwif_t *hwif = drive->hwif; - u8 mask = hwif->ultra_mask, mode = XFER_MW_DMA_2; + u8 mode = ide_find_dma_mode(drive, speed); - if (hwif->udma_filter) - mask = hwif->udma_filter(drive); - - /* - * TODO: speed > XFER_UDMA_2 extra check is needed to avoid false - * cable warning from eighty_ninty_three(), moving ide_rate_filter() - * calls from ->speedproc to core code will make this hack go away - */ - if (speed > XFER_UDMA_2) { - if ((mask & 0x78) && (eighty_ninty_three(drive) == 0)) - mask &= 0x07; + if (mode == 0) { + if (hwif->pio_mask) + mode = fls(hwif->pio_mask) - 1 + XFER_PIO_0; + else + mode = XFER_PIO_4; } - if (mask) - mode = fls(mask) - 1 + XFER_UDMA_0; - // printk("%s: mode 0x%02x, speed 0x%02x\n", __FUNCTION__, mode, speed); return min(speed, mode); -#else /* !CONFIG_BLK_DEV_IDEDMA */ - return min(speed, (u8)XFER_PIO_4); -#endif /* CONFIG_BLK_DEV_IDEDMA */ } -EXPORT_SYMBOL(ide_rate_filter); - int ide_use_fast_pio(ide_drive_t *drive) { struct hd_driveid *id = drive->id; @@ -340,6 +325,35 @@ u8 ide_get_best_pio_mode (ide_drive_t *drive, u8 mode_wanted, u8 max_mode) EXPORT_SYMBOL_GPL(ide_get_best_pio_mode); +/* req_pio == "255" for auto-tune */ +void ide_set_pio(ide_drive_t *drive, u8 req_pio) +{ + ide_hwif_t *hwif = drive->hwif; + u8 host_pio, pio; + + if (hwif->set_pio_mode == NULL) + return; + + BUG_ON(hwif->pio_mask == 0x00); + + host_pio = fls(hwif->pio_mask) - 1; + + pio = ide_get_best_pio_mode(drive, req_pio, host_pio); + + /* + * TODO: + * - report device max PIO mode + * - check req_pio != 255 against device max PIO mode + */ + printk(KERN_DEBUG "%s: host max PIO%d wanted PIO%d%s selected PIO%d\n", + drive->name, host_pio, req_pio, + req_pio == 255 ? "(auto-tune)" : "", pio); + + hwif->set_pio_mode(drive, pio); +} + +EXPORT_SYMBOL_GPL(ide_set_pio); + /** * ide_toggle_bounce - handle bounce buffering * @drive: drive to update @@ -377,13 +391,26 @@ void ide_toggle_bounce(ide_drive_t *drive, int on) int ide_set_xfer_rate(ide_drive_t *drive, u8 rate) { -#ifndef CONFIG_BLK_DEV_IDEDMA - rate = min(rate, (u8) XFER_PIO_4); -#endif - if(HWIF(drive)->speedproc) - return HWIF(drive)->speedproc(drive, rate); - else + ide_hwif_t *hwif = drive->hwif; + + if (hwif->speedproc == NULL) return -1; + + rate = ide_rate_filter(drive, rate); + + if (rate >= XFER_PIO_0 && rate <= XFER_PIO_5) { + if (hwif->set_pio_mode) + hwif->set_pio_mode(drive, rate - XFER_PIO_0); + + /* + * FIXME: this is incorrect to return zero here but + * since all users of ide_set_xfer_rate() ignore + * the return value it is not a problem currently + */ + return 0; + } + + return hwif->speedproc(drive, rate); } static void ide_dump_opcode(ide_drive_t *drive) |