diff options
author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2007-07-19 19:11:54 -0400 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2007-07-19 19:11:54 -0400 |
commit | 328dcbb63657ebbb2dd26982fa9e1fa9e04b6fa2 (patch) | |
tree | 902daf365cd6e8ecf559dbc98419140a9d3b6b8f /drivers/ide/pci | |
parent | 485efc6cf507eae2b8e83b56e179c8fa3980641a (diff) |
siimage: PIO mode setup fixes (take 2)
* Add sil_tuneproc() wrapper for siimage_tuneproc() which also sets
PIO mode on the device.
* Add missing ide_get_best_pio_mode() call to sil_tuneproc() so
"pio" == 255 (autotune) is handled correctly (previously PIO0 was used)
and "pio" values > 4 && < 255 are filtered to PIO4 (instead of PIO0).
* Add code limiting maximum PIO mode according to the pair device capabilities
to sil_tuneproc().
* Convert users of config_siimage_chipset_for_pio() to use sil_tune_pio() and
sil_tuneproc(). This fixes PIO fallback in siimage_config_drive_for_dma() to
use max PIO mode available instead of PIO4 (config_siimage_chipset_for_pio()
used wrong arguments for ide_get_best_pio_mode() and as a results always
tried to set PIO4).
* Remove no longer needed siimage_taskfile_timing()
and config_siimage_chipset_for_pio().
* Enable ->autotune unconditionally and remove PIO tuning for UDMA/MDMA modes
from siimage_speedproc()
* Bump driver version.
v2:
* Fix issues noticed by Sergei:
- correct pair device check
- trim only taskfile PIO to the slowest of the master/slave
- enable ->autotune unconditionally and remove PIO tuning for UDMA/MDMA modes
from siimage_speedproc()
- add TODO item for IORDY bugs
- minor cleanups
Reviewed-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide/pci')
-rw-r--r-- | drivers/ide/pci/siimage.c | 137 |
1 files changed, 39 insertions, 98 deletions
diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c index 1c3e35487893..5304fc5c616a 100644 --- a/drivers/ide/pci/siimage.c +++ b/drivers/ide/pci/siimage.c | |||
@@ -1,9 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/ide/pci/siimage.c Version 1.12 Mar 10 2007 | 2 | * linux/drivers/ide/pci/siimage.c Version 1.15 Jun 29 2007 |
3 | * | 3 | * |
4 | * Copyright (C) 2001-2002 Andre Hedrick <andre@linux-ide.org> | 4 | * Copyright (C) 2001-2002 Andre Hedrick <andre@linux-ide.org> |
5 | * Copyright (C) 2003 Red Hat <alan@redhat.com> | 5 | * Copyright (C) 2003 Red Hat <alan@redhat.com> |
6 | * Copyright (C) 2007 MontaVista Software, Inc. | 6 | * Copyright (C) 2007 MontaVista Software, Inc. |
7 | * Copyright (C) 2007 Bartlomiej Zolnierkiewicz | ||
7 | * | 8 | * |
8 | * May be copied or modified under the terms of the GNU General Public License | 9 | * May be copied or modified under the terms of the GNU General Public License |
9 | * | 10 | * |
@@ -31,6 +32,10 @@ | |||
31 | * unplugging/replugging the virtual CD interface when the DRAC is reset. | 32 | * unplugging/replugging the virtual CD interface when the DRAC is reset. |
32 | * This often causes drivers/ide/siimage to panic but is ok with the rather | 33 | * This often causes drivers/ide/siimage to panic but is ok with the rather |
33 | * smarter code in libata. | 34 | * smarter code in libata. |
35 | * | ||
36 | * TODO: | ||
37 | * - IORDY fixes | ||
38 | * - VDMA support | ||
34 | */ | 39 | */ |
35 | 40 | ||
36 | #include <linux/types.h> | 41 | #include <linux/types.h> |
@@ -160,82 +165,45 @@ out: | |||
160 | } | 165 | } |
161 | 166 | ||
162 | /** | 167 | /** |
163 | * siimage_taskfile_timing - turn timing data to a mode | 168 | * sil_tune_pio - tune a drive |
164 | * @hwif: interface to query | ||
165 | * | ||
166 | * Read the timing data for the interface and return the | ||
167 | * mode that is being used. | ||
168 | */ | ||
169 | |||
170 | static byte siimage_taskfile_timing (ide_hwif_t *hwif) | ||
171 | { | ||
172 | u16 timing = 0x328a; | ||
173 | unsigned long addr = siimage_selreg(hwif, 2); | ||
174 | |||
175 | if (hwif->mmio) | ||
176 | timing = hwif->INW(addr); | ||
177 | else | ||
178 | pci_read_config_word(hwif->pci_dev, addr, &timing); | ||
179 | |||
180 | switch (timing) { | ||
181 | case 0x10c1: return 4; | ||
182 | case 0x10c3: return 3; | ||
183 | case 0x1104: | ||
184 | case 0x1281: return 2; | ||
185 | case 0x2283: return 1; | ||
186 | case 0x328a: | ||
187 | default: return 0; | ||
188 | } | ||
189 | } | ||
190 | |||
191 | /** | ||
192 | * simmage_tuneproc - tune a drive | ||
193 | * @drive: drive to tune | 169 | * @drive: drive to tune |
194 | * @mode_wanted: the target operating mode | 170 | * @pio: the desired PIO mode |
195 | * | 171 | * |
196 | * Load the timing settings for this device mode into the | 172 | * Load the timing settings for this device mode into the |
197 | * controller. If we are in PIO mode 3 or 4 turn on IORDY | 173 | * controller. If we are in PIO mode 3 or 4 turn on IORDY |
198 | * monitoring (bit 9). The TF timing is bits 31:16 | 174 | * monitoring (bit 9). The TF timing is bits 31:16 |
199 | */ | 175 | */ |
200 | 176 | ||
201 | static void siimage_tuneproc (ide_drive_t *drive, byte mode_wanted) | 177 | static void sil_tune_pio(ide_drive_t *drive, u8 pio) |
202 | { | 178 | { |
179 | const u16 tf_speed[] = { 0x328a, 0x2283, 0x1281, 0x10c3, 0x10c1 }; | ||
180 | const u16 data_speed[] = { 0x328a, 0x2283, 0x1104, 0x10c3, 0x10c1 }; | ||
181 | |||
203 | ide_hwif_t *hwif = HWIF(drive); | 182 | ide_hwif_t *hwif = HWIF(drive); |
183 | ide_drive_t *pair = &hwif->drives[drive->dn ^ 1]; | ||
204 | u32 speedt = 0; | 184 | u32 speedt = 0; |
205 | u16 speedp = 0; | 185 | u16 speedp = 0; |
206 | unsigned long addr = siimage_seldev(drive, 0x04); | 186 | unsigned long addr = siimage_seldev(drive, 0x04); |
207 | unsigned long tfaddr = siimage_selreg(hwif, 0x02); | 187 | unsigned long tfaddr = siimage_selreg(hwif, 0x02); |
208 | 188 | u8 tf_pio = pio; | |
209 | /* cheat for now and use the docs */ | 189 | |
210 | switch (mode_wanted) { | 190 | /* trim *taskfile* PIO to the slowest of the master/slave */ |
211 | case 4: | 191 | if (pair->present) { |
212 | speedp = 0x10c1; | 192 | u8 pair_pio = ide_get_best_pio_mode(pair, 255, 4, NULL); |
213 | speedt = 0x10c1; | 193 | |
214 | break; | 194 | if (pair_pio < tf_pio) |
215 | case 3: | 195 | tf_pio = pair_pio; |
216 | speedp = 0x10c3; | ||
217 | speedt = 0x10c3; | ||
218 | break; | ||
219 | case 2: | ||
220 | speedp = 0x1104; | ||
221 | speedt = 0x1281; | ||
222 | break; | ||
223 | case 1: | ||
224 | speedp = 0x2283; | ||
225 | speedt = 0x2283; | ||
226 | break; | ||
227 | case 0: | ||
228 | default: | ||
229 | speedp = 0x328a; | ||
230 | speedt = 0x328a; | ||
231 | break; | ||
232 | } | 196 | } |
233 | 197 | ||
198 | /* cheat for now and use the docs */ | ||
199 | speedp = data_speed[pio]; | ||
200 | speedt = tf_speed[tf_pio]; | ||
201 | |||
234 | if (hwif->mmio) { | 202 | if (hwif->mmio) { |
235 | hwif->OUTW(speedp, addr); | 203 | hwif->OUTW(speedp, addr); |
236 | hwif->OUTW(speedt, tfaddr); | 204 | hwif->OUTW(speedt, tfaddr); |
237 | /* Now set up IORDY */ | 205 | /* Now set up IORDY */ |
238 | if(mode_wanted == 3 || mode_wanted == 4) | 206 | if (pio > 2) |
239 | hwif->OUTW(hwif->INW(tfaddr-2)|0x200, tfaddr-2); | 207 | hwif->OUTW(hwif->INW(tfaddr-2)|0x200, tfaddr-2); |
240 | else | 208 | else |
241 | hwif->OUTW(hwif->INW(tfaddr-2)&~0x200, tfaddr-2); | 209 | hwif->OUTW(hwif->INW(tfaddr-2)&~0x200, tfaddr-2); |
@@ -245,42 +213,17 @@ static void siimage_tuneproc (ide_drive_t *drive, byte mode_wanted) | |||
245 | pci_read_config_word(hwif->pci_dev, tfaddr-2, &speedp); | 213 | pci_read_config_word(hwif->pci_dev, tfaddr-2, &speedp); |
246 | speedp &= ~0x200; | 214 | speedp &= ~0x200; |
247 | /* Set IORDY for mode 3 or 4 */ | 215 | /* Set IORDY for mode 3 or 4 */ |
248 | if(mode_wanted == 3 || mode_wanted == 4) | 216 | if (pio > 2) |
249 | speedp |= 0x200; | 217 | speedp |= 0x200; |
250 | pci_write_config_word(hwif->pci_dev, tfaddr-2, speedp); | 218 | pci_write_config_word(hwif->pci_dev, tfaddr-2, speedp); |
251 | } | 219 | } |
252 | } | 220 | } |
253 | 221 | ||
254 | /** | 222 | static void sil_tuneproc(ide_drive_t *drive, u8 pio) |
255 | * config_siimage_chipset_for_pio - set drive timings | ||
256 | * @drive: drive to tune | ||
257 | * @speed we want | ||
258 | * | ||
259 | * Compute the best pio mode we can for a given device. Also honour | ||
260 | * the timings for the driver when dealing with mixed devices. Some | ||
261 | * of this is ugly but its all wrapped up here | ||
262 | * | ||
263 | * The SI680 can also do VDMA - we need to start using that | ||
264 | * | ||
265 | * FIXME: we use the BIOS channel timings to avoid driving the task | ||
266 | * files too fast at the disk. We need to compute the master/slave | ||
267 | * drive PIO mode properly so that we can up the speed on a hotplug | ||
268 | * system. | ||
269 | */ | ||
270 | |||
271 | static void config_siimage_chipset_for_pio (ide_drive_t *drive, byte set_speed) | ||
272 | { | 223 | { |
273 | u8 channel_timings = siimage_taskfile_timing(HWIF(drive)); | 224 | pio = ide_get_best_pio_mode(drive, pio, 4, NULL); |
274 | u8 speed = 0, set_pio = ide_get_best_pio_mode(drive, 4, 5, NULL); | 225 | sil_tune_pio(drive, pio); |
275 | 226 | (void)ide_config_drive_speed(drive, XFER_PIO_0 + pio); | |
276 | /* WARNING PIO timing mess is going to happen b/w devices, argh */ | ||
277 | if ((channel_timings != set_pio) && (set_pio > channel_timings)) | ||
278 | set_pio = channel_timings; | ||
279 | |||
280 | siimage_tuneproc(drive, set_pio); | ||
281 | speed = XFER_PIO_0 + set_pio; | ||
282 | if (set_speed) | ||
283 | (void) ide_config_drive_speed(drive, speed); | ||
284 | } | 227 | } |
285 | 228 | ||
286 | /** | 229 | /** |
@@ -335,7 +278,7 @@ static int siimage_tune_chipset (ide_drive_t *drive, byte xferspeed) | |||
335 | case XFER_PIO_2: | 278 | case XFER_PIO_2: |
336 | case XFER_PIO_1: | 279 | case XFER_PIO_1: |
337 | case XFER_PIO_0: | 280 | case XFER_PIO_0: |
338 | siimage_tuneproc(drive, (speed - XFER_PIO_0)); | 281 | sil_tune_pio(drive, speed - XFER_PIO_0); |
339 | mode |= ((unit) ? 0x10 : 0x01); | 282 | mode |= ((unit) ? 0x10 : 0x01); |
340 | break; | 283 | break; |
341 | case XFER_MW_DMA_2: | 284 | case XFER_MW_DMA_2: |
@@ -343,7 +286,6 @@ static int siimage_tune_chipset (ide_drive_t *drive, byte xferspeed) | |||
343 | case XFER_MW_DMA_0: | 286 | case XFER_MW_DMA_0: |
344 | multi = dma[speed - XFER_MW_DMA_0]; | 287 | multi = dma[speed - XFER_MW_DMA_0]; |
345 | mode |= ((unit) ? 0x20 : 0x02); | 288 | mode |= ((unit) ? 0x20 : 0x02); |
346 | config_siimage_chipset_for_pio(drive, 0); | ||
347 | break; | 289 | break; |
348 | case XFER_UDMA_6: | 290 | case XFER_UDMA_6: |
349 | case XFER_UDMA_5: | 291 | case XFER_UDMA_5: |
@@ -356,7 +298,6 @@ static int siimage_tune_chipset (ide_drive_t *drive, byte xferspeed) | |||
356 | ultra |= ((scsc) ? (ultra6[speed - XFER_UDMA_0]) : | 298 | ultra |= ((scsc) ? (ultra6[speed - XFER_UDMA_0]) : |
357 | (ultra5[speed - XFER_UDMA_0])); | 299 | (ultra5[speed - XFER_UDMA_0])); |
358 | mode |= ((unit) ? 0x30 : 0x03); | 300 | mode |= ((unit) ? 0x30 : 0x03); |
359 | config_siimage_chipset_for_pio(drive, 0); | ||
360 | break; | 301 | break; |
361 | default: | 302 | default: |
362 | return 1; | 303 | return 1; |
@@ -390,7 +331,7 @@ static int siimage_config_drive_for_dma (ide_drive_t *drive) | |||
390 | return 0; | 331 | return 0; |
391 | 332 | ||
392 | if (ide_use_fast_pio(drive)) | 333 | if (ide_use_fast_pio(drive)) |
393 | config_siimage_chipset_for_pio(drive, 1); | 334 | sil_tuneproc(drive, 255); |
394 | 335 | ||
395 | return -1; | 336 | return -1; |
396 | } | 337 | } |
@@ -961,7 +902,7 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif) | |||
961 | 902 | ||
962 | hwif->resetproc = &siimage_reset; | 903 | hwif->resetproc = &siimage_reset; |
963 | hwif->speedproc = &siimage_tune_chipset; | 904 | hwif->speedproc = &siimage_tune_chipset; |
964 | hwif->tuneproc = &siimage_tuneproc; | 905 | hwif->tuneproc = &sil_tuneproc; |
965 | hwif->reset_poll = &siimage_reset_poll; | 906 | hwif->reset_poll = &siimage_reset_poll; |
966 | hwif->pre_reset = &siimage_pre_reset; | 907 | hwif->pre_reset = &siimage_pre_reset; |
967 | hwif->udma_filter = &sil_udma_filter; | 908 | hwif->udma_filter = &sil_udma_filter; |
@@ -976,11 +917,11 @@ static void __devinit init_hwif_siimage(ide_hwif_t *hwif) | |||
976 | first = 0; | 917 | first = 0; |
977 | } | 918 | } |
978 | } | 919 | } |
979 | if (!hwif->dma_base) { | 920 | |
980 | hwif->drives[0].autotune = 1; | 921 | hwif->drives[0].autotune = hwif->drives[1].autotune = 1; |
981 | hwif->drives[1].autotune = 1; | 922 | |
923 | if (hwif->dma_base == 0) | ||
982 | return; | 924 | return; |
983 | } | ||
984 | 925 | ||
985 | hwif->ultra_mask = 0x7f; | 926 | hwif->ultra_mask = 0x7f; |
986 | hwif->mwdma_mask = 0x07; | 927 | hwif->mwdma_mask = 0x07; |