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-lib.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-lib.c')
-rw-r--r-- | drivers/ide/ide-lib.c | 125 |
1 files changed, 18 insertions, 107 deletions
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index 68719314df3f..4557fc5a3ea3 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c | |||
@@ -69,123 +69,34 @@ char *ide_xfer_verbose (u8 xfer_rate) | |||
69 | EXPORT_SYMBOL(ide_xfer_verbose); | 69 | EXPORT_SYMBOL(ide_xfer_verbose); |
70 | 70 | ||
71 | /** | 71 | /** |
72 | * ide_dma_speed - compute DMA speed | 72 | * ide_rate_filter - filter transfer mode |
73 | * @drive: drive | 73 | * @drive: IDE device |
74 | * @mode: modes available | ||
75 | * | ||
76 | * Checks the drive capabilities and returns the speed to use | ||
77 | * for the DMA transfer. Returns 0 if the drive is incapable | ||
78 | * of DMA transfers. | ||
79 | */ | ||
80 | |||
81 | u8 ide_dma_speed(ide_drive_t *drive, u8 mode) | ||
82 | { | ||
83 | struct hd_driveid *id = drive->id; | ||
84 | ide_hwif_t *hwif = HWIF(drive); | ||
85 | u8 ultra_mask, mwdma_mask, swdma_mask; | ||
86 | u8 speed = 0; | ||
87 | |||
88 | if (drive->media != ide_disk && hwif->atapi_dma == 0) | ||
89 | return 0; | ||
90 | |||
91 | /* Capable of UltraDMA modes? */ | ||
92 | ultra_mask = id->dma_ultra & hwif->ultra_mask; | ||
93 | |||
94 | if (!(id->field_valid & 4)) | ||
95 | mode = 0; /* fallback to MW/SW DMA if no UltraDMA */ | ||
96 | |||
97 | switch (mode) { | ||
98 | case 4: | ||
99 | if (ultra_mask & 0x40) { | ||
100 | speed = XFER_UDMA_6; | ||
101 | break; | ||
102 | } | ||
103 | case 3: | ||
104 | if (ultra_mask & 0x20) { | ||
105 | speed = XFER_UDMA_5; | ||
106 | break; | ||
107 | } | ||
108 | case 2: | ||
109 | if (ultra_mask & 0x10) { | ||
110 | speed = XFER_UDMA_4; | ||
111 | break; | ||
112 | } | ||
113 | if (ultra_mask & 0x08) { | ||
114 | speed = XFER_UDMA_3; | ||
115 | break; | ||
116 | } | ||
117 | case 1: | ||
118 | if (ultra_mask & 0x04) { | ||
119 | speed = XFER_UDMA_2; | ||
120 | break; | ||
121 | } | ||
122 | if (ultra_mask & 0x02) { | ||
123 | speed = XFER_UDMA_1; | ||
124 | break; | ||
125 | } | ||
126 | if (ultra_mask & 0x01) { | ||
127 | speed = XFER_UDMA_0; | ||
128 | break; | ||
129 | } | ||
130 | case 0: | ||
131 | mwdma_mask = id->dma_mword & hwif->mwdma_mask; | ||
132 | |||
133 | if (mwdma_mask & 0x04) { | ||
134 | speed = XFER_MW_DMA_2; | ||
135 | break; | ||
136 | } | ||
137 | if (mwdma_mask & 0x02) { | ||
138 | speed = XFER_MW_DMA_1; | ||
139 | break; | ||
140 | } | ||
141 | if (mwdma_mask & 0x01) { | ||
142 | speed = XFER_MW_DMA_0; | ||
143 | break; | ||
144 | } | ||
145 | |||
146 | swdma_mask = id->dma_1word & hwif->swdma_mask; | ||
147 | |||
148 | if (swdma_mask & 0x04) { | ||
149 | speed = XFER_SW_DMA_2; | ||
150 | break; | ||
151 | } | ||
152 | if (swdma_mask & 0x02) { | ||
153 | speed = XFER_SW_DMA_1; | ||
154 | break; | ||
155 | } | ||
156 | if (swdma_mask & 0x01) { | ||
157 | speed = XFER_SW_DMA_0; | ||
158 | break; | ||
159 | } | ||
160 | } | ||
161 | |||
162 | return speed; | ||
163 | } | ||
164 | EXPORT_SYMBOL(ide_dma_speed); | ||
165 | |||
166 | |||
167 | /** | ||
168 | * ide_rate_filter - return best speed for mode | ||
169 | * @mode: modes available | ||
170 | * @speed: desired speed | 74 | * @speed: desired speed |
171 | * | 75 | * |
172 | * Given the available DMA/UDMA mode this function returns | 76 | * Given the available transfer modes this function returns |
173 | * the best available speed at or below the speed requested. | 77 | * the best available speed at or below the speed requested. |
78 | * | ||
79 | * FIXME: filter also PIO/SWDMA/MWDMA modes | ||
174 | */ | 80 | */ |
175 | 81 | ||
176 | u8 ide_rate_filter (u8 mode, u8 speed) | 82 | u8 ide_rate_filter(ide_drive_t *drive, u8 speed) |
177 | { | 83 | { |
178 | #ifdef CONFIG_BLK_DEV_IDEDMA | 84 | #ifdef CONFIG_BLK_DEV_IDEDMA |
179 | static u8 speed_max[] = { | 85 | ide_hwif_t *hwif = drive->hwif; |
180 | XFER_MW_DMA_2, XFER_UDMA_2, XFER_UDMA_4, | 86 | u8 mask = hwif->ultra_mask, mode = XFER_MW_DMA_2; |
181 | XFER_UDMA_5, XFER_UDMA_6 | 87 | |
182 | }; | 88 | if (hwif->udma_filter) |
89 | mask = hwif->udma_filter(drive); | ||
90 | |||
91 | if ((mask & 0x78) && (eighty_ninty_three(drive) == 0)) | ||
92 | mask &= 0x07; | ||
93 | |||
94 | if (mask) | ||
95 | mode = fls(mask) - 1 + XFER_UDMA_0; | ||
183 | 96 | ||
184 | // printk("%s: mode 0x%02x, speed 0x%02x\n", __FUNCTION__, mode, speed); | 97 | // printk("%s: mode 0x%02x, speed 0x%02x\n", __FUNCTION__, mode, speed); |
185 | 98 | ||
186 | /* So that we remember to update this if new modes appear */ | 99 | return min(speed, mode); |
187 | BUG_ON(mode > 4); | ||
188 | return min(speed, speed_max[mode]); | ||
189 | #else /* !CONFIG_BLK_DEV_IDEDMA */ | 100 | #else /* !CONFIG_BLK_DEV_IDEDMA */ |
190 | return min(speed, (u8)XFER_PIO_4); | 101 | return min(speed, (u8)XFER_PIO_4); |
191 | #endif /* CONFIG_BLK_DEV_IDEDMA */ | 102 | #endif /* CONFIG_BLK_DEV_IDEDMA */ |