mirror of https://gitee.com/openkylin/linux.git
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>
This commit is contained in:
parent
21b8247713
commit
f92d50e6fd
|
@ -1,6 +1,6 @@
|
|||
/* $Id: cmd64x.c,v 1.21 2000/01/30 23:23:16
|
||||
*
|
||||
* linux/drivers/ide/pci/cmd64x.c Version 1.30 Sept 10, 2002
|
||||
* linux/drivers/ide/pci/cmd64x.c Version 1.41 Feb 3, 2007
|
||||
*
|
||||
* cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines.
|
||||
* Note, this driver is not used at all on other systems because
|
||||
|
@ -12,6 +12,7 @@
|
|||
* Copyright (C) 1998 David S. Miller (davem@redhat.com)
|
||||
*
|
||||
* Copyright (C) 1999-2002 Andre Hedrick <andre@linux-ide.org>
|
||||
* Copyright (C) 2007 MontaVista Software, Inc. <source@mvista.com>
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
|
@ -262,43 +263,25 @@ static void program_drive_counts (ide_drive_t *drive, int setup_count, int activ
|
|||
}
|
||||
|
||||
/*
|
||||
* Attempts to set the interface PIO mode.
|
||||
* The preferred method of selecting PIO modes (e.g. mode 4) is
|
||||
* "echo 'piomode:4' > /proc/ide/hdx/settings". Special cases are
|
||||
* 8: prefetch off, 9: prefetch on, 255: auto-select best mode.
|
||||
* Called with 255 at boot time.
|
||||
* This routine selects drive's best PIO mode, calculates setup/active/recovery
|
||||
* counts, and then writes them into the chipset registers.
|
||||
*/
|
||||
|
||||
static void cmd64x_tuneproc (ide_drive_t *drive, u8 mode_wanted)
|
||||
static u8 cmd64x_tune_pio (ide_drive_t *drive, u8 mode_wanted)
|
||||
{
|
||||
int setup_time, active_time, recovery_time;
|
||||
int clock_time, pio_mode, cycle_time;
|
||||
u8 recovery_count2, cycle_count;
|
||||
int setup_count, active_count, recovery_count;
|
||||
int bus_speed = system_bus_clock();
|
||||
/*byte b;*/
|
||||
ide_pio_data_t d;
|
||||
|
||||
switch (mode_wanted) {
|
||||
case 8: /* set prefetch off */
|
||||
case 9: /* set prefetch on */
|
||||
mode_wanted &= 1;
|
||||
/*set_prefetch_mode(index, mode_wanted);*/
|
||||
cmdprintk("%s: %sabled cmd640 prefetch\n",
|
||||
drive->name, mode_wanted ? "en" : "dis");
|
||||
return;
|
||||
}
|
||||
|
||||
mode_wanted = ide_get_best_pio_mode (drive, mode_wanted, 5, &d);
|
||||
pio_mode = d.pio_mode;
|
||||
pio_mode = ide_get_best_pio_mode(drive, mode_wanted, 5, &d);
|
||||
cycle_time = d.cycle_time;
|
||||
|
||||
/*
|
||||
* I copied all this complicated stuff from cmd640.c and made a few
|
||||
* minor changes. For now I am just going to pray that it is correct.
|
||||
*/
|
||||
if (pio_mode > 5)
|
||||
pio_mode = 5;
|
||||
setup_time = ide_pio_timings[pio_mode].setup_time;
|
||||
active_time = ide_pio_timings[pio_mode].active_time;
|
||||
recovery_time = cycle_time - (setup_time + active_time);
|
||||
|
@ -320,22 +303,33 @@ static void cmd64x_tuneproc (ide_drive_t *drive, u8 mode_wanted)
|
|||
if (active_count > 16)
|
||||
active_count = 16; /* maximum allowed by cmd646 */
|
||||
|
||||
/*
|
||||
* In a perfect world, we might set the drive pio mode here
|
||||
* (using WIN_SETFEATURE) before continuing.
|
||||
*
|
||||
* But we do not, because:
|
||||
* 1) this is the wrong place to do it
|
||||
* (proper is do_special() in ide.c)
|
||||
* 2) in practice this is rarely, if ever, necessary
|
||||
*/
|
||||
program_drive_counts (drive, setup_count, active_count, recovery_count);
|
||||
|
||||
cmdprintk("%s: selected cmd646 PIO mode%d : %d (%dns)%s, "
|
||||
cmdprintk("%s: PIO mode wanted %d, selected %d (%dns)%s, "
|
||||
"clocks=%d/%d/%d\n",
|
||||
drive->name, pio_mode, mode_wanted, cycle_time,
|
||||
drive->name, mode_wanted, pio_mode, cycle_time,
|
||||
d.overridden ? " (overriding vendor mode)" : "",
|
||||
setup_count, active_count, recovery_count);
|
||||
|
||||
return pio_mode;
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempts to set drive's PIO mode.
|
||||
* Special cases are 8: prefetch off, 9: prefetch on (both never worked),
|
||||
* and 255: auto-select best mode (used at boot time).
|
||||
*/
|
||||
static void cmd64x_tune_drive (ide_drive_t *drive, u8 pio)
|
||||
{
|
||||
/*
|
||||
* Filter out the prefetch control values
|
||||
* to prevent PIO5 from being programmed
|
||||
*/
|
||||
if (pio == 8 || pio == 9)
|
||||
return;
|
||||
|
||||
pio = cmd64x_tune_pio(drive, pio);
|
||||
(void) ide_config_drive_speed(drive, XFER_PIO_0 + pio);
|
||||
}
|
||||
|
||||
static u8 cmd64x_ratemask (ide_drive_t *drive)
|
||||
|
@ -387,22 +381,6 @@ static u8 cmd64x_ratemask (ide_drive_t *drive)
|
|||
return mode;
|
||||
}
|
||||
|
||||
static void config_cmd64x_chipset_for_pio (ide_drive_t *drive, u8 set_speed)
|
||||
{
|
||||
u8 speed = 0x00;
|
||||
u8 set_pio = ide_get_best_pio_mode(drive, 4, 5, NULL);
|
||||
|
||||
cmd64x_tuneproc(drive, set_pio);
|
||||
speed = XFER_PIO_0 + set_pio;
|
||||
if (set_speed)
|
||||
(void) ide_config_drive_speed(drive, speed);
|
||||
}
|
||||
|
||||
static void config_chipset_for_pio (ide_drive_t *drive, u8 set_speed)
|
||||
{
|
||||
config_cmd64x_chipset_for_pio(drive, set_speed);
|
||||
}
|
||||
|
||||
static int cmd64x_tune_chipset (ide_drive_t *drive, u8 xferspeed)
|
||||
{
|
||||
ide_hwif_t *hwif = HWIF(drive);
|
||||
|
@ -414,7 +392,7 @@ static int cmd64x_tune_chipset (ide_drive_t *drive, u8 xferspeed)
|
|||
|
||||
u8 speed = ide_rate_filter(cmd64x_ratemask(drive), xferspeed);
|
||||
|
||||
if (speed > XFER_PIO_4) {
|
||||
if (speed >= XFER_SW_DMA_0) {
|
||||
(void) pci_read_config_byte(dev, pciD, ®D);
|
||||
(void) pci_read_config_byte(dev, pciU, ®U);
|
||||
regD &= ~(unit ? 0x40 : 0x20);
|
||||
|
@ -438,17 +416,20 @@ static int cmd64x_tune_chipset (ide_drive_t *drive, u8 xferspeed)
|
|||
case XFER_SW_DMA_2: regD |= (unit ? 0x40 : 0x10); break;
|
||||
case XFER_SW_DMA_1: regD |= (unit ? 0x80 : 0x20); break;
|
||||
case XFER_SW_DMA_0: regD |= (unit ? 0xC0 : 0x30); break;
|
||||
case XFER_PIO_4: cmd64x_tuneproc(drive, 4); break;
|
||||
case XFER_PIO_3: cmd64x_tuneproc(drive, 3); break;
|
||||
case XFER_PIO_2: cmd64x_tuneproc(drive, 2); break;
|
||||
case XFER_PIO_1: cmd64x_tuneproc(drive, 1); break;
|
||||
case XFER_PIO_0: cmd64x_tuneproc(drive, 0); break;
|
||||
case XFER_PIO_5:
|
||||
case XFER_PIO_4:
|
||||
case XFER_PIO_3:
|
||||
case XFER_PIO_2:
|
||||
case XFER_PIO_1:
|
||||
case XFER_PIO_0:
|
||||
(void) cmd64x_tune_pio(drive, speed - XFER_PIO_0);
|
||||
break;
|
||||
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (speed > XFER_PIO_4) {
|
||||
if (speed >= XFER_SW_DMA_0) {
|
||||
(void) pci_write_config_byte(dev, pciU, regU);
|
||||
regD |= (unit ? 0x40 : 0x20);
|
||||
(void) pci_write_config_byte(dev, pciD, regD);
|
||||
|
@ -461,8 +442,6 @@ static int config_chipset_for_dma (ide_drive_t *drive)
|
|||
{
|
||||
u8 speed = ide_dma_speed(drive, cmd64x_ratemask(drive));
|
||||
|
||||
config_chipset_for_pio(drive, !speed);
|
||||
|
||||
if (!speed)
|
||||
return 0;
|
||||
|
||||
|
@ -478,7 +457,7 @@ static int cmd64x_config_drive_for_dma (ide_drive_t *drive)
|
|||
return 0;
|
||||
|
||||
if (ide_use_fast_pio(drive))
|
||||
config_chipset_for_pio(drive, 1);
|
||||
cmd64x_tune_drive(drive, 255);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -679,14 +658,13 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
|
|||
pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
|
||||
class_rev &= 0xff;
|
||||
|
||||
hwif->tuneproc = &cmd64x_tuneproc;
|
||||
hwif->tuneproc = &cmd64x_tune_drive;
|
||||
hwif->speedproc = &cmd64x_tune_chipset;
|
||||
|
||||
if (!hwif->dma_base) {
|
||||
hwif->drives[0].autotune = 1;
|
||||
hwif->drives[1].autotune = 1;
|
||||
hwif->drives[0].autotune = hwif->drives[1].autotune = 1;
|
||||
|
||||
if (!hwif->dma_base)
|
||||
return;
|
||||
}
|
||||
|
||||
hwif->atapi_dma = 1;
|
||||
|
||||
|
|
Loading…
Reference in New Issue