diff options
author | Sergei Shtylyov <sshtylyov@ru.mvista.com> | 2007-03-03 11:48:53 -0500 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2007-03-03 11:48:53 -0500 |
commit | f92d50e6fd14f6e4601f59aac4cffe617b7b2ce6 (patch) | |
tree | cb5859a3087788c579ad051dd679f1acdc33ff1c /drivers/ide/pci/cmd64x.c | |
parent | 21b824771309927172247546b0bff0c4e6831875 (diff) |
cmd64x: fix PIO mode setup (take 3)
The driver's tuneproc() method fails to set the drive's own speed -- fix this
by renaming the function to cmd64x_tune_pio(), making it return the mode set,
and "wrapping" the new tuneproc() method around it; while at it, also get rid
of the non-working prefetch control code (filtering out related argument values
in the "wrapper"), remove redundant PIO5 mode limitation, make cmdprintk() give
more sensible mode info, and remove mention about the obsolete /proc/ interface.
Get rid of the broken config_chipset_for_pio() which always tried to set PIO4,
switch to always auto-tuning PIO instead.
Oh, and add the missing PIO5 support to the speedproc() method while at it. :-)
Warning: compile tested only -- getting to the real hardware isn't that easy...
On Tuesday 06 February 2007 22:11, Mikael Pettersson <mikpe@it.uu.se> wrote:
>
> Worked fine on my SPARC Ultra5 with a CMD646 IDE controller.
Signed-off-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide/pci/cmd64x.c')
-rw-r--r-- | drivers/ide/pci/cmd64x.c | 108 |
1 files changed, 43 insertions, 65 deletions
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c index 49df27513da7..b0d4825c56a9 100644 --- a/drivers/ide/pci/cmd64x.c +++ b/drivers/ide/pci/cmd64x.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* $Id: cmd64x.c,v 1.21 2000/01/30 23:23:16 | 1 | /* $Id: cmd64x.c,v 1.21 2000/01/30 23:23:16 |
2 | * | 2 | * |
3 | * linux/drivers/ide/pci/cmd64x.c Version 1.30 Sept 10, 2002 | 3 | * linux/drivers/ide/pci/cmd64x.c Version 1.41 Feb 3, 2007 |
4 | * | 4 | * |
5 | * cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines. | 5 | * cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines. |
6 | * Note, this driver is not used at all on other systems because | 6 | * Note, this driver is not used at all on other systems because |
@@ -12,6 +12,7 @@ | |||
12 | * Copyright (C) 1998 David S. Miller (davem@redhat.com) | 12 | * Copyright (C) 1998 David S. Miller (davem@redhat.com) |
13 | * | 13 | * |
14 | * Copyright (C) 1999-2002 Andre Hedrick <andre@linux-ide.org> | 14 | * Copyright (C) 1999-2002 Andre Hedrick <andre@linux-ide.org> |
15 | * Copyright (C) 2007 MontaVista Software, Inc. <source@mvista.com> | ||
15 | */ | 16 | */ |
16 | 17 | ||
17 | #include <linux/module.h> | 18 | #include <linux/module.h> |
@@ -262,43 +263,25 @@ static void program_drive_counts (ide_drive_t *drive, int setup_count, int activ | |||
262 | } | 263 | } |
263 | 264 | ||
264 | /* | 265 | /* |
265 | * Attempts to set the interface PIO mode. | 266 | * This routine selects drive's best PIO mode, calculates setup/active/recovery |
266 | * The preferred method of selecting PIO modes (e.g. mode 4) is | 267 | * counts, and then writes them into the chipset registers. |
267 | * "echo 'piomode:4' > /proc/ide/hdx/settings". Special cases are | ||
268 | * 8: prefetch off, 9: prefetch on, 255: auto-select best mode. | ||
269 | * Called with 255 at boot time. | ||
270 | */ | 268 | */ |
271 | 269 | static u8 cmd64x_tune_pio (ide_drive_t *drive, u8 mode_wanted) | |
272 | static void cmd64x_tuneproc (ide_drive_t *drive, u8 mode_wanted) | ||
273 | { | 270 | { |
274 | int setup_time, active_time, recovery_time; | 271 | int setup_time, active_time, recovery_time; |
275 | int clock_time, pio_mode, cycle_time; | 272 | int clock_time, pio_mode, cycle_time; |
276 | u8 recovery_count2, cycle_count; | 273 | u8 recovery_count2, cycle_count; |
277 | int setup_count, active_count, recovery_count; | 274 | int setup_count, active_count, recovery_count; |
278 | int bus_speed = system_bus_clock(); | 275 | int bus_speed = system_bus_clock(); |
279 | /*byte b;*/ | ||
280 | ide_pio_data_t d; | 276 | ide_pio_data_t d; |
281 | 277 | ||
282 | switch (mode_wanted) { | 278 | pio_mode = ide_get_best_pio_mode(drive, mode_wanted, 5, &d); |
283 | case 8: /* set prefetch off */ | ||
284 | case 9: /* set prefetch on */ | ||
285 | mode_wanted &= 1; | ||
286 | /*set_prefetch_mode(index, mode_wanted);*/ | ||
287 | cmdprintk("%s: %sabled cmd640 prefetch\n", | ||
288 | drive->name, mode_wanted ? "en" : "dis"); | ||
289 | return; | ||
290 | } | ||
291 | |||
292 | mode_wanted = ide_get_best_pio_mode (drive, mode_wanted, 5, &d); | ||
293 | pio_mode = d.pio_mode; | ||
294 | cycle_time = d.cycle_time; | 279 | cycle_time = d.cycle_time; |
295 | 280 | ||
296 | /* | 281 | /* |
297 | * I copied all this complicated stuff from cmd640.c and made a few | 282 | * I copied all this complicated stuff from cmd640.c and made a few |
298 | * minor changes. For now I am just going to pray that it is correct. | 283 | * minor changes. For now I am just going to pray that it is correct. |
299 | */ | 284 | */ |
300 | if (pio_mode > 5) | ||
301 | pio_mode = 5; | ||
302 | setup_time = ide_pio_timings[pio_mode].setup_time; | 285 | setup_time = ide_pio_timings[pio_mode].setup_time; |
303 | active_time = ide_pio_timings[pio_mode].active_time; | 286 | active_time = ide_pio_timings[pio_mode].active_time; |
304 | recovery_time = cycle_time - (setup_time + active_time); | 287 | recovery_time = cycle_time - (setup_time + active_time); |
@@ -320,22 +303,33 @@ static void cmd64x_tuneproc (ide_drive_t *drive, u8 mode_wanted) | |||
320 | if (active_count > 16) | 303 | if (active_count > 16) |
321 | active_count = 16; /* maximum allowed by cmd646 */ | 304 | active_count = 16; /* maximum allowed by cmd646 */ |
322 | 305 | ||
323 | /* | ||
324 | * In a perfect world, we might set the drive pio mode here | ||
325 | * (using WIN_SETFEATURE) before continuing. | ||
326 | * | ||
327 | * But we do not, because: | ||
328 | * 1) this is the wrong place to do it | ||
329 | * (proper is do_special() in ide.c) | ||
330 | * 2) in practice this is rarely, if ever, necessary | ||
331 | */ | ||
332 | program_drive_counts (drive, setup_count, active_count, recovery_count); | 306 | program_drive_counts (drive, setup_count, active_count, recovery_count); |
333 | 307 | ||
334 | cmdprintk("%s: selected cmd646 PIO mode%d : %d (%dns)%s, " | 308 | cmdprintk("%s: PIO mode wanted %d, selected %d (%dns)%s, " |
335 | "clocks=%d/%d/%d\n", | 309 | "clocks=%d/%d/%d\n", |
336 | drive->name, pio_mode, mode_wanted, cycle_time, | 310 | drive->name, mode_wanted, pio_mode, cycle_time, |
337 | d.overridden ? " (overriding vendor mode)" : "", | 311 | d.overridden ? " (overriding vendor mode)" : "", |
338 | setup_count, active_count, recovery_count); | 312 | setup_count, active_count, recovery_count); |
313 | |||
314 | return pio_mode; | ||
315 | } | ||
316 | |||
317 | /* | ||
318 | * Attempts to set drive's PIO mode. | ||
319 | * Special cases are 8: prefetch off, 9: prefetch on (both never worked), | ||
320 | * and 255: auto-select best mode (used at boot time). | ||
321 | */ | ||
322 | static void cmd64x_tune_drive (ide_drive_t *drive, u8 pio) | ||
323 | { | ||
324 | /* | ||
325 | * Filter out the prefetch control values | ||
326 | * to prevent PIO5 from being programmed | ||
327 | */ | ||
328 | if (pio == 8 || pio == 9) | ||
329 | return; | ||
330 | |||
331 | pio = cmd64x_tune_pio(drive, pio); | ||
332 | (void) ide_config_drive_speed(drive, XFER_PIO_0 + pio); | ||
339 | } | 333 | } |
340 | 334 | ||
341 | static u8 cmd64x_ratemask (ide_drive_t *drive) | 335 | static u8 cmd64x_ratemask (ide_drive_t *drive) |
@@ -387,22 +381,6 @@ static u8 cmd64x_ratemask (ide_drive_t *drive) | |||
387 | return mode; | 381 | return mode; |
388 | } | 382 | } |
389 | 383 | ||
390 | static void config_cmd64x_chipset_for_pio (ide_drive_t *drive, u8 set_speed) | ||
391 | { | ||
392 | u8 speed = 0x00; | ||
393 | u8 set_pio = ide_get_best_pio_mode(drive, 4, 5, NULL); | ||
394 | |||
395 | cmd64x_tuneproc(drive, set_pio); | ||
396 | speed = XFER_PIO_0 + set_pio; | ||
397 | if (set_speed) | ||
398 | (void) ide_config_drive_speed(drive, speed); | ||
399 | } | ||
400 | |||
401 | static void config_chipset_for_pio (ide_drive_t *drive, u8 set_speed) | ||
402 | { | ||
403 | config_cmd64x_chipset_for_pio(drive, set_speed); | ||
404 | } | ||
405 | |||
406 | static int cmd64x_tune_chipset (ide_drive_t *drive, u8 xferspeed) | 384 | static int cmd64x_tune_chipset (ide_drive_t *drive, u8 xferspeed) |
407 | { | 385 | { |
408 | ide_hwif_t *hwif = HWIF(drive); | 386 | ide_hwif_t *hwif = HWIF(drive); |
@@ -414,7 +392,7 @@ static int cmd64x_tune_chipset (ide_drive_t *drive, u8 xferspeed) | |||
414 | 392 | ||
415 | u8 speed = ide_rate_filter(cmd64x_ratemask(drive), xferspeed); | 393 | u8 speed = ide_rate_filter(cmd64x_ratemask(drive), xferspeed); |
416 | 394 | ||
417 | if (speed > XFER_PIO_4) { | 395 | if (speed >= XFER_SW_DMA_0) { |
418 | (void) pci_read_config_byte(dev, pciD, ®D); | 396 | (void) pci_read_config_byte(dev, pciD, ®D); |
419 | (void) pci_read_config_byte(dev, pciU, ®U); | 397 | (void) pci_read_config_byte(dev, pciU, ®U); |
420 | regD &= ~(unit ? 0x40 : 0x20); | 398 | regD &= ~(unit ? 0x40 : 0x20); |
@@ -438,17 +416,20 @@ static int cmd64x_tune_chipset (ide_drive_t *drive, u8 xferspeed) | |||
438 | case XFER_SW_DMA_2: regD |= (unit ? 0x40 : 0x10); break; | 416 | case XFER_SW_DMA_2: regD |= (unit ? 0x40 : 0x10); break; |
439 | case XFER_SW_DMA_1: regD |= (unit ? 0x80 : 0x20); break; | 417 | case XFER_SW_DMA_1: regD |= (unit ? 0x80 : 0x20); break; |
440 | case XFER_SW_DMA_0: regD |= (unit ? 0xC0 : 0x30); break; | 418 | case XFER_SW_DMA_0: regD |= (unit ? 0xC0 : 0x30); break; |
441 | case XFER_PIO_4: cmd64x_tuneproc(drive, 4); break; | 419 | case XFER_PIO_5: |
442 | case XFER_PIO_3: cmd64x_tuneproc(drive, 3); break; | 420 | case XFER_PIO_4: |
443 | case XFER_PIO_2: cmd64x_tuneproc(drive, 2); break; | 421 | case XFER_PIO_3: |
444 | case XFER_PIO_1: cmd64x_tuneproc(drive, 1); break; | 422 | case XFER_PIO_2: |
445 | case XFER_PIO_0: cmd64x_tuneproc(drive, 0); break; | 423 | case XFER_PIO_1: |
424 | case XFER_PIO_0: | ||
425 | (void) cmd64x_tune_pio(drive, speed - XFER_PIO_0); | ||
426 | break; | ||
446 | 427 | ||
447 | default: | 428 | default: |
448 | return 1; | 429 | return 1; |
449 | } | 430 | } |
450 | 431 | ||
451 | if (speed > XFER_PIO_4) { | 432 | if (speed >= XFER_SW_DMA_0) { |
452 | (void) pci_write_config_byte(dev, pciU, regU); | 433 | (void) pci_write_config_byte(dev, pciU, regU); |
453 | regD |= (unit ? 0x40 : 0x20); | 434 | regD |= (unit ? 0x40 : 0x20); |
454 | (void) pci_write_config_byte(dev, pciD, regD); | 435 | (void) pci_write_config_byte(dev, pciD, regD); |
@@ -461,8 +442,6 @@ static int config_chipset_for_dma (ide_drive_t *drive) | |||
461 | { | 442 | { |
462 | u8 speed = ide_dma_speed(drive, cmd64x_ratemask(drive)); | 443 | u8 speed = ide_dma_speed(drive, cmd64x_ratemask(drive)); |
463 | 444 | ||
464 | config_chipset_for_pio(drive, !speed); | ||
465 | |||
466 | if (!speed) | 445 | if (!speed) |
467 | return 0; | 446 | return 0; |
468 | 447 | ||
@@ -478,7 +457,7 @@ static int cmd64x_config_drive_for_dma (ide_drive_t *drive) | |||
478 | return 0; | 457 | return 0; |
479 | 458 | ||
480 | if (ide_use_fast_pio(drive)) | 459 | if (ide_use_fast_pio(drive)) |
481 | config_chipset_for_pio(drive, 1); | 460 | cmd64x_tune_drive(drive, 255); |
482 | 461 | ||
483 | return -1; | 462 | return -1; |
484 | } | 463 | } |
@@ -679,14 +658,13 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif) | |||
679 | pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); | 658 | pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev); |
680 | class_rev &= 0xff; | 659 | class_rev &= 0xff; |
681 | 660 | ||
682 | hwif->tuneproc = &cmd64x_tuneproc; | 661 | hwif->tuneproc = &cmd64x_tune_drive; |
683 | hwif->speedproc = &cmd64x_tune_chipset; | 662 | hwif->speedproc = &cmd64x_tune_chipset; |
684 | 663 | ||
685 | if (!hwif->dma_base) { | 664 | hwif->drives[0].autotune = hwif->drives[1].autotune = 1; |
686 | hwif->drives[0].autotune = 1; | 665 | |
687 | hwif->drives[1].autotune = 1; | 666 | if (!hwif->dma_base) |
688 | return; | 667 | return; |
689 | } | ||
690 | 668 | ||
691 | hwif->atapi_dma = 1; | 669 | hwif->atapi_dma = 1; |
692 | 670 | ||