diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2007-05-09 18:01:08 -0400 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2007-05-09 18:01:08 -0400 |
commit | 2d5eaa6dd744a641e75503232a01f52d0768884c (patch) | |
tree | 0736bd00ea3bd032d601d0a676c998cb043b877a /drivers/ide/ide-dma.c | |
parent | 18137207236285989dfc0ee7f929b954199228f3 (diff) |
ide: rework the code for selecting the best DMA transfer mode (v3)
Depends on the "ide: fix UDMA/MWDMA/SWDMA masks" patch.
* add ide_hwif_t.udma_filter hook for filtering UDMA mask
(use it in alim15x3, hpt366, siimage and serverworks drivers)
* add ide_max_dma_mode() for finding best DMA mode for the device
(loosely based on some older libata-core.c code)
* convert ide_dma_speed() users to use ide_max_dma_mode()
* make ide_rate_filter() take "ide_drive_t *drive" as an argument instead
of "u8 mode" and teach it to how to use UDMA mask to do filtering
* use ide_rate_filter() in hpt366 driver
* remove no longer needed ide_dma_speed() and *_ratemask()
* unexport eighty_ninty_three()
v2:
* rename ->filter_udma_mask to ->udma_filter
[ Suggested by Sergei Shtylyov <sshtylyov@ru.mvista.com>. ]
v3:
* updated for scc_pata driver (fixes XFER_UDMA_6 filtering for user-space
originated transfer mode change requests when 100MHz clock is used)
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide/ide-dma.c')
-rw-r--r-- | drivers/ide/ide-dma.c | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index fd213088b06b..f28fabb791fe 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c | |||
@@ -705,6 +705,80 @@ int ide_use_dma(ide_drive_t *drive) | |||
705 | 705 | ||
706 | EXPORT_SYMBOL_GPL(ide_use_dma); | 706 | EXPORT_SYMBOL_GPL(ide_use_dma); |
707 | 707 | ||
708 | static const u8 xfer_mode_bases[] = { | ||
709 | XFER_UDMA_0, | ||
710 | XFER_MW_DMA_0, | ||
711 | XFER_SW_DMA_0, | ||
712 | }; | ||
713 | |||
714 | static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base) | ||
715 | { | ||
716 | struct hd_driveid *id = drive->id; | ||
717 | ide_hwif_t *hwif = drive->hwif; | ||
718 | unsigned int mask = 0; | ||
719 | |||
720 | switch(base) { | ||
721 | case XFER_UDMA_0: | ||
722 | if ((id->field_valid & 4) == 0) | ||
723 | break; | ||
724 | |||
725 | mask = id->dma_ultra & hwif->ultra_mask; | ||
726 | |||
727 | if (hwif->udma_filter) | ||
728 | mask &= hwif->udma_filter(drive); | ||
729 | |||
730 | if ((mask & 0x78) && (eighty_ninty_three(drive) == 0)) | ||
731 | mask &= 0x07; | ||
732 | break; | ||
733 | case XFER_MW_DMA_0: | ||
734 | mask = id->dma_mword & hwif->mwdma_mask; | ||
735 | break; | ||
736 | case XFER_SW_DMA_0: | ||
737 | mask = id->dma_1word & hwif->swdma_mask; | ||
738 | break; | ||
739 | default: | ||
740 | BUG(); | ||
741 | break; | ||
742 | } | ||
743 | |||
744 | return mask; | ||
745 | } | ||
746 | |||
747 | /** | ||
748 | * ide_max_dma_mode - compute DMA speed | ||
749 | * @drive: IDE device | ||
750 | * | ||
751 | * Checks the drive capabilities and returns the speed to use | ||
752 | * for the DMA transfer. Returns 0 if the drive is incapable | ||
753 | * of DMA transfers. | ||
754 | */ | ||
755 | |||
756 | u8 ide_max_dma_mode(ide_drive_t *drive) | ||
757 | { | ||
758 | ide_hwif_t *hwif = drive->hwif; | ||
759 | unsigned int mask; | ||
760 | int x, i; | ||
761 | u8 mode = 0; | ||
762 | |||
763 | if (drive->media != ide_disk && hwif->atapi_dma == 0) | ||
764 | return 0; | ||
765 | |||
766 | for (i = 0; i < ARRAY_SIZE(xfer_mode_bases); i++) { | ||
767 | mask = ide_get_mode_mask(drive, xfer_mode_bases[i]); | ||
768 | x = fls(mask) - 1; | ||
769 | if (x >= 0) { | ||
770 | mode = xfer_mode_bases[i] + x; | ||
771 | break; | ||
772 | } | ||
773 | } | ||
774 | |||
775 | printk(KERN_DEBUG "%s: selected mode 0x%x\n", drive->name, mode); | ||
776 | |||
777 | return mode; | ||
778 | } | ||
779 | |||
780 | EXPORT_SYMBOL_GPL(ide_max_dma_mode); | ||
781 | |||
708 | void ide_dma_verbose(ide_drive_t *drive) | 782 | void ide_dma_verbose(ide_drive_t *drive) |
709 | { | 783 | { |
710 | struct hd_driveid *id = drive->id; | 784 | struct hd_driveid *id = drive->id; |