Commit e089d43f authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/pub/scm/linux/kernel/git/bart/ide-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/bart/ide-2.6:
  Use menuconfig objects: IDE
  sl82c105: Switch to ref counting API
  ide: remove ide_use_dma()
  ide: add missing validity checks for identify words 62 and 63
  ide: remove ide_dma_enable()
  sl82c105: add speedproc() method and MWDMA0/1 support
  cs5530/sc1200: add ->speedproc support
  cs5530/sc1200: DMA support cleanup
  ide: use ide_tune_dma() part #2
  cs5530/sc1200: add ->udma_filter methods
  ide: always disable DMA before tuning it
  pdc202xx_new: use ide_tune_dma()
  alim15x3: use ide_tune_dma()
  sis5513: PIO mode setup fixes
  serverworks: PIO mode setup fixes
  pdc202xx_old: rewrite mode programming code (v2)
parents 0e402c6e e0ff9cd1
...@@ -4,13 +4,10 @@ ...@@ -4,13 +4,10 @@
# Andre Hedrick <andre@linux-ide.org> # Andre Hedrick <andre@linux-ide.org>
# #
if BLOCK menuconfig IDE
menu "ATA/ATAPI/MFM/RLL support"
depends on HAS_IOMEM
config IDE
tristate "ATA/ATAPI/MFM/RLL support" tristate "ATA/ATAPI/MFM/RLL support"
depends on BLOCK
depends on HAS_IOMEM
---help--- ---help---
If you say Y here, your kernel will be able to manage low cost mass If you say Y here, your kernel will be able to manage low cost mass
storage units such as ATA/(E)IDE and ATAPI units. The most common storage units such as ATA/(E)IDE and ATAPI units. The most common
...@@ -1099,8 +1096,4 @@ config BLK_DEV_HD_ONLY ...@@ -1099,8 +1096,4 @@ config BLK_DEV_HD_ONLY
config BLK_DEV_HD config BLK_DEV_HD
def_bool BLK_DEV_HD_IDE || BLK_DEV_HD_ONLY def_bool BLK_DEV_HD_IDE || BLK_DEV_HD_ONLY
endif endif # IDE
endmenu
endif
...@@ -1002,18 +1002,6 @@ static int cris_ide_build_dmatable (ide_drive_t *drive) ...@@ -1002,18 +1002,6 @@ static int cris_ide_build_dmatable (ide_drive_t *drive)
return 1; /* let the PIO routines handle this weirdness */ return 1; /* let the PIO routines handle this weirdness */
} }
static int cris_config_drive_for_dma (ide_drive_t *drive)
{
u8 speed = ide_max_dma_mode(drive);
if (!speed)
return 0;
speed_cris_ide(drive, speed);
return ide_dma_enable(drive);
}
/* /*
* cris_dma_intr() is the handler for disk read/write DMA interrupts * cris_dma_intr() is the handler for disk read/write DMA interrupts
*/ */
...@@ -1043,7 +1031,7 @@ static ide_startstop_t cris_dma_intr (ide_drive_t *drive) ...@@ -1043,7 +1031,7 @@ static ide_startstop_t cris_dma_intr (ide_drive_t *drive)
static int cris_dma_check(ide_drive_t *drive) static int cris_dma_check(ide_drive_t *drive)
{ {
if (ide_use_dma(drive) && cris_config_drive_for_dma(drive)) if (ide_tune_dma(drive))
return 0; return 0;
return -1; return -1;
......
...@@ -670,41 +670,6 @@ int __ide_dma_good_drive (ide_drive_t *drive) ...@@ -670,41 +670,6 @@ int __ide_dma_good_drive (ide_drive_t *drive)
EXPORT_SYMBOL(__ide_dma_good_drive); EXPORT_SYMBOL(__ide_dma_good_drive);
int ide_use_dma(ide_drive_t *drive)
{
struct hd_driveid *id = drive->id;
ide_hwif_t *hwif = drive->hwif;
if ((id->capability & 1) == 0 || drive->autodma == 0)
return 0;
/* consult the list of known "bad" drives */
if (__ide_dma_bad_drive(drive))
return 0;
/* capable of UltraDMA modes */
if (id->field_valid & 4) {
if (hwif->ultra_mask & id->dma_ultra)
return 1;
}
/* capable of regular DMA modes */
if (id->field_valid & 2) {
if (hwif->mwdma_mask & id->dma_mword)
return 1;
if (hwif->swdma_mask & id->dma_1word)
return 1;
}
/* consult the list of known "good" drives */
if (__ide_dma_good_drive(drive) && id->eide_dma_time < 150)
return 1;
return 0;
}
EXPORT_SYMBOL_GPL(ide_use_dma);
static const u8 xfer_mode_bases[] = { static const u8 xfer_mode_bases[] = {
XFER_UDMA_0, XFER_UDMA_0,
XFER_MW_DMA_0, XFER_MW_DMA_0,
...@@ -731,9 +696,11 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base) ...@@ -731,9 +696,11 @@ static unsigned int ide_get_mode_mask(ide_drive_t *drive, u8 base)
mask &= 0x07; mask &= 0x07;
break; break;
case XFER_MW_DMA_0: case XFER_MW_DMA_0:
if (id->field_valid & 2)
mask = id->dma_mword & hwif->mwdma_mask; mask = id->dma_mword & hwif->mwdma_mask;
break; break;
case XFER_SW_DMA_0: case XFER_SW_DMA_0:
if (id->field_valid & 2)
mask = id->dma_1word & hwif->swdma_mask; mask = id->dma_1word & hwif->swdma_mask;
break; break;
default: default:
...@@ -783,8 +750,11 @@ int ide_tune_dma(ide_drive_t *drive) ...@@ -783,8 +750,11 @@ int ide_tune_dma(ide_drive_t *drive)
{ {
u8 speed; u8 speed;
/* TODO: use only ide_max_dma_mode() */ if ((drive->id->capability & 1) == 0 || drive->autodma == 0)
if (!ide_use_dma(drive)) return 0;
/* consult the list of known "bad" drives */
if (__ide_dma_bad_drive(drive))
return 0; return 0;
speed = ide_max_dma_mode(drive); speed = ide_max_dma_mode(drive);
...@@ -792,9 +762,10 @@ int ide_tune_dma(ide_drive_t *drive) ...@@ -792,9 +762,10 @@ int ide_tune_dma(ide_drive_t *drive)
if (!speed) if (!speed)
return 0; return 0;
drive->hwif->speedproc(drive, speed); if (drive->hwif->speedproc(drive, speed))
return 0;
return ide_dma_enable(drive); return 1;
} }
EXPORT_SYMBOL_GPL(ide_tune_dma); EXPORT_SYMBOL_GPL(ide_tune_dma);
......
...@@ -223,6 +223,7 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request * ...@@ -223,6 +223,7 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
break; break;
if (drive->hwif->ide_dma_check == NULL) if (drive->hwif->ide_dma_check == NULL)
break; break;
drive->hwif->dma_off_quietly(drive);
ide_set_dma(drive); ide_set_dma(drive);
break; break;
} }
......
...@@ -111,18 +111,6 @@ u8 ide_rate_filter(ide_drive_t *drive, u8 speed) ...@@ -111,18 +111,6 @@ u8 ide_rate_filter(ide_drive_t *drive, u8 speed)
EXPORT_SYMBOL(ide_rate_filter); EXPORT_SYMBOL(ide_rate_filter);
int ide_dma_enable (ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
struct hd_driveid *id = drive->id;
return ((int) ((((id->dma_ultra >> 8) & hwif->ultra_mask) ||
((id->dma_mword >> 8) & hwif->mwdma_mask) ||
((id->dma_1word >> 8) & hwif->swdma_mask)) ? 1 : 0));
}
EXPORT_SYMBOL(ide_dma_enable);
int ide_use_fast_pio(ide_drive_t *drive) int ide_use_fast_pio(ide_drive_t *drive)
{ {
struct hd_driveid *id = drive->id; struct hd_driveid *id = drive->id;
......
...@@ -910,6 +910,7 @@ int set_using_dma(ide_drive_t *drive, int arg) ...@@ -910,6 +910,7 @@ int set_using_dma(ide_drive_t *drive, int arg)
err = 0; err = 0;
if (arg) { if (arg) {
hwif->dma_off_quietly(drive);
if (ide_set_dma(drive) || hwif->ide_dma_on(drive)) if (ide_set_dma(drive) || hwif->ide_dma_on(drive))
err = -EIO; err = -EIO;
} else } else
......
...@@ -455,28 +455,6 @@ static int ali15x3_tune_chipset (ide_drive_t *drive, u8 xferspeed) ...@@ -455,28 +455,6 @@ static int ali15x3_tune_chipset (ide_drive_t *drive, u8 xferspeed)
return (ide_config_drive_speed(drive, speed)); return (ide_config_drive_speed(drive, speed));
} }
/**
* config_chipset_for_dma - set up DMA mode
* @drive: drive to configure for
*
* Place a drive into DMA mode and tune the chipset for
* the selected speed.
*
* Returns true if DMA mode can be used
*/
static int config_chipset_for_dma (ide_drive_t *drive)
{
u8 speed = ide_max_dma_mode(drive);
if (!(speed))
return 0;
(void) ali15x3_tune_chipset(drive, speed);
return ide_dma_enable(drive);
}
/** /**
* ali15x3_config_drive_for_dma - configure for DMA * ali15x3_config_drive_for_dma - configure for DMA
* @drive: drive to configure * @drive: drive to configure
...@@ -487,48 +465,14 @@ static int config_chipset_for_dma (ide_drive_t *drive) ...@@ -487,48 +465,14 @@ static int config_chipset_for_dma (ide_drive_t *drive)
static int ali15x3_config_drive_for_dma(ide_drive_t *drive) static int ali15x3_config_drive_for_dma(ide_drive_t *drive)
{ {
ide_hwif_t *hwif = HWIF(drive); drive->init_speed = 0;
struct hd_driveid *id = drive->id;
if ((m5229_revision<=0x20) && (drive->media!=ide_disk)) if (ide_tune_dma(drive))
goto ata_pio; return 0;
drive->init_speed = 0; ali15x3_tune_drive(drive, 255);
if ((id != NULL) && ((id->capability & 1) != 0) && drive->autodma) {
/* Consult the list of known "bad" drives */
if (__ide_dma_bad_drive(drive))
goto ata_pio;
if ((id->field_valid & 4) && (m5229_revision >= 0xC2)) {
if (id->dma_ultra & hwif->ultra_mask) {
/* Force if Capable UltraDMA */
int dma = config_chipset_for_dma(drive);
if ((id->field_valid & 2) && !dma)
goto try_dma_modes;
}
} else if (id->field_valid & 2) {
try_dma_modes:
if ((id->dma_mword & hwif->mwdma_mask) ||
(id->dma_1word & hwif->swdma_mask)) {
/* Force if Capable regular DMA modes */
if (!config_chipset_for_dma(drive))
goto ata_pio;
}
} else if (__ide_dma_good_drive(drive) &&
(id->eide_dma_time < 150)) {
/* Consult the list of known "good" drives */
if (!config_chipset_for_dma(drive))
goto ata_pio;
} else {
goto ata_pio;
}
} else {
ata_pio:
hwif->tuneproc(drive, 255);
return -1; return -1;
}
return 0;
} }
/** /**
...@@ -739,6 +683,7 @@ static void __devinit init_hwif_common_ali15x3 (ide_hwif_t *hwif) ...@@ -739,6 +683,7 @@ static void __devinit init_hwif_common_ali15x3 (ide_hwif_t *hwif)
return; return;
} }
if (m5229_revision > 0x20)
hwif->atapi_dma = 1; hwif->atapi_dma = 1;
if (m5229_revision <= 0x20) if (m5229_revision <= 0x20)
......
...@@ -352,22 +352,9 @@ static int cmd64x_tune_chipset (ide_drive_t *drive, u8 speed) ...@@ -352,22 +352,9 @@ static int cmd64x_tune_chipset (ide_drive_t *drive, u8 speed)
return ide_config_drive_speed(drive, speed); return ide_config_drive_speed(drive, speed);
} }
static int config_chipset_for_dma (ide_drive_t *drive)
{
u8 speed = ide_max_dma_mode(drive);
if (!speed)
return 0;
if (cmd64x_tune_chipset(drive, speed))
return 0;
return ide_dma_enable(drive);
}
static int cmd64x_config_drive_for_dma (ide_drive_t *drive) static int cmd64x_config_drive_for_dma (ide_drive_t *drive)
{ {
if (ide_use_dma(drive) && config_chipset_for_dma(drive)) if (ide_tune_dma(drive))
return 0; return 0;
if (ide_use_fast_pio(drive)) if (ide_use_fast_pio(drive))
......
/* /*
* linux/drivers/ide/pci/cs5530.c Version 0.7 Sept 10, 2002 * linux/drivers/ide/pci/cs5530.c Version 0.73 Mar 10 2007
* *
* Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 2000 Andre Hedrick <andre@linux-ide.org>
* Ditto of GNU General Public License.
*
* Copyright (C) 2000 Mark Lord <mlord@pobox.com> * Copyright (C) 2000 Mark Lord <mlord@pobox.com>
* Copyright (C) 2007 Bartlomiej Zolnierkiewicz
*
* May be copied or modified under the terms of the GNU General Public License * May be copied or modified under the terms of the GNU General Public License
* *
* Development of this chipset driver was funded * Development of this chipset driver was funded
...@@ -62,6 +62,14 @@ static unsigned int cs5530_pio_timings[2][5] = { ...@@ -62,6 +62,14 @@ static unsigned int cs5530_pio_timings[2][5] = {
#define CS5530_BAD_PIO(timings) (((timings)&~0x80000000)==0x0000e132) #define CS5530_BAD_PIO(timings) (((timings)&~0x80000000)==0x0000e132)
#define CS5530_BASEREG(hwif) (((hwif)->dma_base & ~0xf) + ((hwif)->channel ? 0x30 : 0x20)) #define CS5530_BASEREG(hwif) (((hwif)->dma_base & ~0xf) + ((hwif)->channel ? 0x30 : 0x20))
static void cs5530_tunepio(ide_drive_t *drive, u8 pio)
{
unsigned long basereg = CS5530_BASEREG(drive->hwif);
unsigned int format = (inl(basereg + 4) >> 31) & 1;
outl(cs5530_pio_timings[format][pio], basereg + ((drive->dn & 1)<<3));
}
/** /**
* cs5530_tuneproc - select/set PIO modes * cs5530_tuneproc - select/set PIO modes
* *
...@@ -74,98 +82,78 @@ static unsigned int cs5530_pio_timings[2][5] = { ...@@ -74,98 +82,78 @@ static unsigned int cs5530_pio_timings[2][5] = {
static void cs5530_tuneproc (ide_drive_t *drive, u8 pio) /* pio=255 means "autotune" */ static void cs5530_tuneproc (ide_drive_t *drive, u8 pio) /* pio=255 means "autotune" */
{ {
ide_hwif_t *hwif = HWIF(drive);
unsigned int format;
unsigned long basereg = CS5530_BASEREG(hwif);
static u8 modes[5] = { XFER_PIO_0, XFER_PIO_1, XFER_PIO_2, XFER_PIO_3, XFER_PIO_4};
pio = ide_get_best_pio_mode(drive, pio, 4, NULL); pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
if (!cs5530_set_xfer_mode(drive, modes[pio])) {
format = (inl(basereg + 4) >> 31) & 1; if (cs5530_set_xfer_mode(drive, XFER_PIO_0 + pio) == 0)
outl(cs5530_pio_timings[format][pio], cs5530_tunepio(drive, pio);
basereg+(drive->select.b.unit<<3));
}
} }
/** /**
* cs5530_config_dma - select/set DMA and UDMA modes * cs5530_udma_filter - UDMA filter
* @drive: drive to tune * @drive: drive
*
* cs5530_udma_filter() does UDMA mask filtering for the given drive
* taking into the consideration capabilities of the mate device.
*
* The CS5530 specifies that two drives sharing a cable cannot mix
* UDMA/MDMA. It has to be one or the other, for the pair, though
* different timings can still be chosen for each drive. We could
* set the appropriate timing bits on the fly, but that might be
* a bit confusing. So, for now we statically handle this requirement
* by looking at our mate drive to see what it is capable of, before
* choosing a mode for our own drive.
* *
* cs5530_config_dma() handles selection/setting of DMA/UDMA modes * Note: This relies on the fact we never fail from UDMA to MWDMA2
* for both the chipset and drive. The CS5530 has limitations about * but instead drop to PIO.
* mixing DMA/UDMA on the same cable.
*/ */
static int cs5530_config_dma (ide_drive_t *drive) static u8 cs5530_udma_filter(ide_drive_t *drive)
{ {
int udma_ok = 1, mode = 0; ide_hwif_t *hwif = drive->hwif;
ide_hwif_t *hwif = HWIF(drive); ide_drive_t *mate = &hwif->drives[(drive->dn & 1) ^ 1];
int unit = drive->select.b.unit; struct hd_driveid *mateid = mate->id;
ide_drive_t *mate = &hwif->drives[unit^1]; u8 mask = hwif->ultra_mask;
struct hd_driveid *id = drive->id;
unsigned int reg, timings = 0;
unsigned long basereg;
/* if (mate->present == 0)
* Default to DMA-off in case we run into trouble here. goto out;
*/
hwif->dma_off_quietly(drive);
/* if ((mateid->capability & 1) && __ide_dma_bad_drive(mate) == 0) {
* The CS5530 specifies that two drives sharing a cable cannot if ((mateid->field_valid & 4) && (mateid->dma_ultra & 7))
* mix UDMA/MDMA. It has to be one or the other, for the pair, goto out;
* though different timings can still be chosen for each drive. if ((mateid->field_valid & 2) && (mateid->dma_mword & 7))
* We could set the appropriate timing bits on the fly, mask = 0;
* but that might be a bit confusing. So, for now we statically
* handle this requirement by looking at our mate drive to see
* what it is capable of, before choosing a mode for our own drive.
*
* Note: This relies on the fact we never fail from UDMA to MWDMA_2
* but instead drop to PIO
*/
if (mate->present) {
struct hd_driveid *mateid = mate->id;
if (mateid && (mateid->capability & 1) &&
!__ide_dma_bad_drive(mate)) {
if ((mateid->field_valid & 4) &&
(mateid->dma_ultra & 7))
udma_ok = 1;
else if ((mateid->field_valid & 2) &&
(mateid->dma_mword & 7))
udma_ok = 0;
else
udma_ok = 1;
}
} }
out:
return mask;
}
/* /**
* Now see what the current drive is capable of, * cs5530_config_dma - set DMA/UDMA mode
* selecting UDMA only if the mate said it was ok. * @drive: drive to tune
*
* cs5530_config_dma() handles setting of DMA/UDMA mode
* for both the chipset and drive.
*/ */
if (id && (id->capability & 1) && drive->autodma &&
!__ide_dma_bad_drive(drive)) { static int cs5530_config_dma(ide_drive_t *drive)
if (udma_ok && (id->field_valid & 4) && (id->dma_ultra & 7)) { {
if (id->dma_ultra & 4) if (ide_tune_dma(drive))
mode = XFER_UDMA_2; return 0;
else if (id->dma_ultra & 2)
mode = XFER_UDMA_1; return 1;
else if (id->dma_ultra & 1) }
mode = XFER_UDMA_0;
} static int cs5530_tune_chipset(ide_drive_t *drive, u8 mode)
if (!mode && (id->field_valid & 2) && (id->dma_mword & 7)) { {
if (id->dma_mword & 4) unsigned long basereg;
mode = XFER_MW_DMA_2; unsigned int reg, timings = 0;
else if (id->dma_mword & 2)
mode = XFER_MW_DMA_1; mode = ide_rate_filter(drive, mode);
else if (id->dma_mword & 1)
mode = XFER_MW_DMA_0;
}
}
/* /*
* Tell the drive to switch to the new mode; abort on failure. * Tell the drive to switch to the new mode; abort on failure.
*/ */
if (!mode || cs5530_set_xfer_mode(drive, mode)) if (cs5530_set_xfer_mode(drive, mode))
return 1; /* failure */ return 1; /* failure */
/* /*
...@@ -178,14 +166,21 @@ static int cs5530_config_dma (ide_drive_t *drive) ...@@ -178,14 +166,21 @@ static int cs5530_config_dma (ide_drive_t *drive)
case XFER_MW_DMA_0: timings = 0x00077771; break; case XFER_MW_DMA_0: timings = 0x00077771; break;
case XFER_MW_DMA_1: timings = 0x00012121; break; case XFER_MW_DMA_1: timings = 0x00012121; break;
case XFER_MW_DMA_2: timings = 0x00002020; break; case XFER_MW_DMA_2: timings = 0x00002020; break;
case XFER_PIO_4:
case XFER_PIO_3:
case XFER_PIO_2:
case XFER_PIO_1:
case XFER_PIO_0:
cs5530_tunepio(drive, mode - XFER_PIO_0);
return 0;
default: default:
BUG(); BUG();
break; break;
} }
basereg = CS5530_BASEREG(hwif); basereg = CS5530_BASEREG(drive->hwif);
reg = inl(basereg + 4); /* get drive0 config register */ reg = inl(basereg + 4); /* get drive0 config register */
timings |= reg & 0x80000000; /* preserve PIO format bit */ timings |= reg & 0x80000000; /* preserve PIO format bit */
if (unit == 0) { /* are we configuring drive0? */ if ((drive-> dn & 1) == 0) { /* are we configuring drive0? */
outl(timings, basereg + 4); /* write drive0 config register */ outl(timings, basereg + 4); /* write drive0 config register */
} else { } else {
if (timings & 0x00100000) if (timings & 0x00100000)
...@@ -311,6 +306,8 @@ static void __devinit init_hwif_cs5530 (ide_hwif_t *hwif) ...@@ -311,6 +306,8 @@ static void __devinit init_hwif_cs5530 (ide_hwif_t *hwif)
hwif->serialized = hwif->mate->serialized = 1; hwif->serialized = hwif->mate->serialized = 1;
hwif->tuneproc = &cs5530_tuneproc; hwif->tuneproc = &cs5530_tuneproc;
hwif->speedproc = &cs5530_tune_chipset;
basereg = CS5530_BASEREG(hwif); basereg = CS5530_BASEREG(hwif);
d0_timings = inl(basereg + 0); d0_timings = inl(basereg + 0);
if (CS5530_BAD_PIO(d0_timings)) { if (CS5530_BAD_PIO(d0_timings)) {
...@@ -332,6 +329,7 @@ static void __devinit init_hwif_cs5530 (ide_hwif_t *hwif) ...@@ -332,6 +329,7 @@ static void __devinit init_hwif_cs5530 (ide_hwif_t *hwif)
hwif->ultra_mask = 0x07; hwif->ultra_mask = 0x07;
hwif->mwdma_mask = 0x07; hwif->mwdma_mask = 0x07;
hwif->udma_filter = cs5530_udma_filter;
hwif->ide_dma_check = &cs5530_config_dma; hwif->ide_dma_check = &cs5530_config_dma;
if (!noautodma) if (!noautodma)
hwif->autodma = 1; hwif->autodma = 1;
......
...@@ -463,25 +463,6 @@ static int it821x_tune_chipset (ide_drive_t *drive, byte xferspeed) ...@@ -463,25 +463,6 @@ static int it821x_tune_chipset (ide_drive_t *drive, byte xferspeed)
return ide_config_drive_speed(drive, speed); return ide_config_drive_speed(drive, speed);
} }
/**
* config_chipset_for_dma - configure for DMA
* @drive: drive to configure
*
* Called by the IDE layer when it wants the timings set up.
*/
static int config_chipset_for_dma (ide_drive_t *drive)
{
u8 speed = ide_max_dma_mode(drive);
if (speed == 0)
return 0;
it821x_tune_chipset(drive, speed);
return ide_dma_enable(drive);
}
/** /**
* it821x_configure_drive_for_dma - set up for DMA transfers * it821x_configure_drive_for_dma - set up for DMA transfers
* @drive: drive we are going to set up * @drive: drive we are going to set up
...@@ -494,7 +475,7 @@ static int config_chipset_for_dma (ide_drive_t *drive) ...@@ -494,7 +475,7 @@ static int config_chipset_for_dma (ide_drive_t *drive)
static int it821x_config_drive_for_dma (ide_drive_t *drive) static int it821x_config_drive_for_dma (ide_drive_t *drive)
{ {
if (ide_use_dma(drive) && config_chipset_for_dma(drive)) if (ide_tune_dma(drive))
return 0; return 0;
it821x_tuneproc(drive, 255); it821x_tuneproc(drive, 255);
......
...@@ -228,38 +228,11 @@ static u8 pdcnew_cable_detect(ide_hwif_t *hwif) ...@@ -228,38 +228,11 @@ static u8 pdcnew_cable_detect(ide_hwif_t *hwif)
return get_indexed_reg(hwif, 0x0b) & 0x04; return get_indexed_reg(hwif, 0x0b) & 0x04;
} }
static int config_chipset_for_dma(ide_drive_t *drive)
{
struct hd_driveid *id = drive->id;
ide_hwif_t *hwif = HWIF(drive);
u8 speed;
if (id->capability & 4) {
/*
* Set IORDY_EN & PREFETCH_EN (this seems to have
* NO real effect since this register is reloaded
* by hardware when the transfer mode is selected)
*/
u8 tmp, adj = (drive->dn & 1) ? 0x08 : 0x00;
tmp = get_indexed_reg(hwif, 0x13 + adj);
set_indexed_reg(hwif, 0x13 + adj, tmp | 0x03);
}
speed = ide_max_dma_mode(drive);
if (!speed)
return 0;
(void) hwif->speedproc(drive, speed);
return ide_dma_enable(drive);
}
static int pdcnew_config_drive_xfer_rate(ide_drive_t *drive) static int pdcnew_config_drive_xfer_rate(ide_drive_t *drive)
{ {
drive->init_speed = 0; drive->init_speed = 0;
if (ide_use_dma(drive) && config_chipset_for_dma(drive)) if (ide_tune_dma(drive))
return 0; return 0;
if (ide_use_fast_pio(drive)) if (ide_use_fast_pio(drive))
......
/* /*
* linux/drivers/ide/pci/pdc202xx_old.c Version 0.36 Sept 11, 2002 * linux/drivers/ide/pci/pdc202xx_old.c Version 0.50 Mar 3, 2007
* *
* Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2006-2007 MontaVista Software, Inc. * Copyright (C) 2006-2007 MontaVista Software, Inc.
* Copyright (C) 2007 Bartlomiej Zolnierkiewicz
* *
* Promise Ultra33 cards with BIOS v1.20 through 1.28 will need this * Promise Ultra33 cards with BIOS v1.20 through 1.28 will need this
* compiled into the kernel if you have more than one card installed. * compiled into the kernel if you have more than one card installed.
...@@ -60,45 +61,7 @@ static const char *pdc_quirk_drives[] = { ...@@ -60,45 +61,7 @@ static const char *pdc_quirk_drives[] = {
NULL NULL
}; };
/* A Register */ static void pdc_old_disable_66MHz_clock(ide_hwif_t *);
#define SYNC_ERRDY_EN 0xC0
#define SYNC_IN 0x80 /* control bit, different for master vs. slave drives */
#define ERRDY_EN 0x40 /* control bit, different for master vs. slave drives */
#define IORDY_EN 0x20 /* PIO: IOREADY */
#define PREFETCH_EN 0x10 /* PIO: PREFETCH */
#define PA3 0x08 /* PIO"A" timing */
#define PA2 0x04 /* PIO"A" timing */
#define PA1 0x02 /* PIO"A" timing */
#define PA0 0x01 /* PIO"A" timing */
/* B Register */
#define MB2 0x80 /* DMA"B" timing */
#define MB1 0x40 /* DMA"B" timing */
#define MB0 0x20 /* DMA"B" timing */
#define PB4 0x10 /* PIO_FORCE 1:0 */
#define PB3 0x08 /* PIO"B" timing */ /* PIO flow Control mode */
#define PB2 0x04 /* PIO"B" timing */ /* PIO 4 */
#define PB1 0x02 /* PIO"B" timing */ /* PIO 3 half */
#define PB0 0x01 /* PIO"B" timing */ /* PIO 3 other half */
/* C Register */
#define IORDYp_NO_SPEED 0x4F
#define SPEED_DIS 0x0F
#define DMARQp 0x80
#define IORDYp 0x40
#define DMAR_EN 0x20
#define DMAW_EN 0x10
#define MC3 0x08 /* DMA"C" timing */
#define MC2 0x04 /* DMA"C" timing */
#define MC1 0x02 /* DMA"C" timing */
#define MC0 0x01 /* DMA"C" timing */
static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed) static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed)
{ {
...@@ -107,52 +70,25 @@ static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed) ...@@ -107,52 +70,25 @@ static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed)
u8 drive_pci = 0x60 + (drive->dn << 2); u8 drive_pci = 0x60 + (drive->dn << 2);
u8 speed = ide_rate_filter(drive, xferspeed); u8 speed = ide_rate_filter(drive, xferspeed);
u32 drive_conf; u8 AP = 0, BP = 0, CP = 0;
u8 AP, BP, CP, DP;
u8 TA = 0, TB = 0, TC = 0; u8 TA = 0, TB = 0, TC = 0;
if (drive->media != ide_disk && #if PDC202XX_DEBUG_DRIVE_INFO
drive->media != ide_cdrom && speed < XFER_SW_DMA_0) u32 drive_conf = 0;
return -1;
pci_read_config_dword(dev, drive_pci, &drive_conf); pci_read_config_dword(dev, drive_pci, &drive_conf);
pci_read_config_byte(dev, (drive_pci), &AP); #endif
pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
pci_read_config_byte(dev, (drive_pci)|0x03, &DP);
if (speed < XFER_SW_DMA_0) {
if ((AP & 0x0F) || (BP & 0x07)) {
/* clear PIO modes of lower 8421 bits of A Register */
pci_write_config_byte(dev, (drive_pci), AP &~0x0F);
pci_read_config_byte(dev, (drive_pci), &AP);
/* clear PIO modes of lower 421 bits of B Register */ /*
pci_write_config_byte(dev, (drive_pci)|0x01, BP &~0x07); * TODO: do this once per channel
pci_read_config_byte(dev, (drive_pci)|0x01, &BP); */
if (dev->device != PCI_DEVICE_ID_PROMISE_20246)
pci_read_config_byte(dev, (drive_pci), &AP); pdc_old_disable_66MHz_clock(hwif);
pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
}
} else {
if ((BP & 0xF0) && (CP & 0x0F)) {
/* clear DMA modes of upper 842 bits of B Register */
/* clear PIO forced mode upper 1 bit of B Register */
pci_write_config_byte(dev, (drive_pci)|0x01, BP &~0xF0);
pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
/* clear DMA modes of lower 8421 bits of C Register */
pci_write_config_byte(dev, (drive_pci)|0x02, CP &~0x0F);
pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
}
}
pci_read_config_byte(dev, (drive_pci), &AP); pci_read_config_byte(dev, drive_pci, &AP);
pci_read_config_byte(dev, (drive_pci)|0x01, &BP); pci_read_config_byte(dev, drive_pci + 1, &BP);
pci_read_config_byte(dev, (drive_pci)|0x02, &CP); pci_read_config_byte(dev, drive_pci + 2, &CP);
switch(speed) { switch(speed) {
case XFER_UDMA_6: speed = XFER_UDMA_5;
case XFER_UDMA_5: case XFER_UDMA_5:
case XFER_UDMA_4: TB = 0x20; TC = 0x01; break; case XFER_UDMA_4: TB = 0x20; TC = 0x01; break;
case XFER_UDMA_2: TB = 0x20; TC = 0x01; break; case XFER_UDMA_2: TB = 0x20; TC = 0x01; break;
...@@ -161,7 +97,7 @@ static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed) ...@@ -161,7 +97,7 @@ static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed)
case XFER_UDMA_0: case XFER_UDMA_0:
case XFER_MW_DMA_2: TB = 0x60; TC = 0x03; break; case XFER_MW_DMA_2: TB = 0x60; TC = 0x03; break;
case XFER_MW_DMA_1: TB = 0x60; TC = 0x04; break; case XFER_MW_DMA_1: TB = 0x60; TC = 0x04; break;
case XFER_MW_DMA_0: case XFER_MW_DMA_0: TB = 0xE0; TC = 0x0F; break;
case XFER_SW_DMA_2: TB = 0x60; TC = 0x05; break; case XFER_SW_DMA_2: TB = 0x60; TC = 0x05; break;
case XFER_SW_DMA_1: TB = 0x80; TC = 0x06; break; case XFER_SW_DMA_1: TB = 0x80; TC = 0x06; break;
case XFER_SW_DMA_0: TB = 0xC0; TC = 0x0B; break; case XFER_SW_DMA_0: TB = 0xC0; TC = 0x0B; break;
...@@ -174,11 +110,26 @@ static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed) ...@@ -174,11 +110,26 @@ static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed)
} }
if (speed < XFER_SW_DMA_0) { if (speed < XFER_SW_DMA_0) {
pci_write_config_byte(dev, (drive_pci), AP|TA); /*
pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); * preserve SYNC_INT / ERDDY_EN bits while clearing
* Prefetch_EN / IORDY_EN / PA[3:0] bits of register A
*/
AP &= ~0x3f;
if (drive->id->capability & 4)
AP |= 0x20; /* set IORDY_EN bit */
if (drive->media == ide_disk)
AP |= 0x10; /* set Prefetch_EN bit */
/* clear PB[4:0] bits of register B */
BP &= ~0x1f;
pci_write_config_byte(dev, drive_pci, AP | TA);
pci_write_config_byte(dev, drive_pci + 1, BP | TB);
} else { } else {
pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); /* clear MB[2:0] bits of register B */
pci_write_config_byte(dev, (drive_pci)|0x02, CP|TC); BP &= ~0xe0;
/* clear MC[3:0] bits of register C */
CP &= ~0x0f;
pci_write_config_byte(dev, drive_pci + 1, BP | TB);
pci_write_config_byte(dev, drive_pci + 2, CP | TC);
} }
#if PDC202XX_DEBUG_DRIVE_INFO #if PDC202XX_DEBUG_DRIVE_INFO
...@@ -187,12 +138,11 @@ static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed) ...@@ -187,12 +138,11 @@ static int pdc202xx_tune_chipset (ide_drive_t *drive, u8 xferspeed)
drive->dn, drive_conf); drive->dn, drive_conf);
pci_read_config_dword(dev, drive_pci, &drive_conf); pci_read_config_dword(dev, drive_pci, &drive_conf);
printk("0x%08x\n", drive_conf); printk("0x%08x\n", drive_conf);
#endif /* PDC202XX_DEBUG_DRIVE_INFO */ #endif
return (ide_config_drive_speed(drive, speed)); return ide_config_drive_speed(drive, speed);
} }
static void pdc202xx_tune_drive(ide_drive_t *drive, u8 pio) static void pdc202xx_tune_drive(ide_drive_t *drive, u8 pio)
{ {
pio = ide_get_best_pio_mode(drive, pio, 4, NULL); pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
...@@ -210,6 +160,8 @@ static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif) ...@@ -210,6 +160,8 @@ static u8 pdc202xx_old_cable_detect (ide_hwif_t *hwif)
* Set the control register to use the 66MHz system * Set the control register to use the 66MHz system
* clock for UDMA 3/4/5 mode operation when necessary. * clock for UDMA 3/4/5 mode operation when necessary.
* *
* FIXME: this register is shared by both channels, some locking is needed
*
* It may also be possible to leave the 66MHz clock on * It may also be possible to leave the 66MHz clock on
* and readjust the timing parameters. * and readjust the timing parameters.
*/ */
...@@ -229,65 +181,11 @@ static void pdc_old_disable_66MHz_clock(ide_hwif_t *hwif) ...@@ -229,65 +181,11 @@ static void pdc_old_disable_66MHz_clock(ide_hwif_t *hwif)
outb(clock & ~(hwif->channel ? 0x08 : 0x02), clock_reg); outb(clock & ~(hwif->channel ? 0x08 : 0x02), clock_reg);
} }
static int config_chipset_for_dma (ide_drive_t *drive)
{
struct hd_driveid *id = drive->id;
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev;
u32 drive_conf = 0;
u8 drive_pci = 0x60 + (drive->dn << 2);
u8 test1 = 0, test2 = 0, speed = -1;
u8 AP = 0;
if (dev->device != PCI_DEVICE_ID_PROMISE_20246)
pdc_old_disable_66MHz_clock(drive->hwif);
drive_pci = 0x60 + (drive->dn << 2);
pci_read_config_dword(dev, drive_pci, &drive_conf);
if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4))
goto chipset_is_set;
pci_read_config_byte(dev, drive_pci, &test1);
if (!(test1 & SYNC_ERRDY_EN)) {
if (drive->select.b.unit & 0x01) {
pci_read_config_byte(dev, drive_pci - 4, &test2);
if ((test2 & SYNC_ERRDY_EN) &&
!(test1 & SYNC_ERRDY_EN)) {
pci_write_config_byte(dev, drive_pci,
test1|SYNC_ERRDY_EN);
}
} else {
pci_write_config_byte(dev, drive_pci,
test1|SYNC_ERRDY_EN);
}
}
chipset_is_set:
pci_read_config_byte(dev, (drive_pci), &AP);
if (id->capability & 4) /* IORDY_EN */
pci_write_config_byte(dev, (drive_pci), AP|IORDY_EN);
pci_read_config_byte(dev, (drive_pci), &AP);
if (drive->media == ide_disk) /* PREFETCH_EN */
pci_write_config_byte(dev, (drive_pci), AP|PREFETCH_EN);
speed = ide_max_dma_mode(drive);
if (!(speed)) {
/* restore original pci-config space */
pci_write_config_dword(dev, drive_pci, drive_conf);
return 0;
}
(void) hwif->speedproc(drive, speed);
return ide_dma_enable(drive);
}
static int pdc202xx_config_drive_xfer_rate (ide_drive_t *drive) static int pdc202xx_config_drive_xfer_rate (ide_drive_t *drive)
{ {
drive->init_speed = 0; drive->init_speed = 0;
if (ide_use_dma(drive) && config_chipset_for_dma(drive)) if (ide_tune_dma(drive))
return 0; return 0;
if (ide_use_fast_pio(drive)) if (ide_use_fast_pio(drive))
......
/* /*
* linux/drivers/ide/pci/sc1200.c Version 0.91 28-Jan-2003 * linux/drivers/ide/pci/sc1200.c Version 0.94 Mar 10 2007
* *
* Copyright (C) 2000-2002 Mark Lord <mlord@pobox.com> * Copyright (C) 2000-2002 Mark Lord <mlord@pobox.com>
* Copyright (C) 2007 Bartlomiej Zolnierkiewicz
*
* May be copied or modified under the terms of the GNU General Public License * May be copied or modified under the terms of the GNU General Public License
* *
* Development of this chipset driver was funded * Development of this chipset driver was funded
...@@ -93,64 +95,50 @@ static const unsigned int sc1200_pio_timings[4][5] = ...@@ -93,64 +95,50 @@ static const unsigned int sc1200_pio_timings[4][5] =
*/ */
//#define SC1200_BAD_PIO(timings) (((timings)&~0x80000000)==0x00009172) //#define SC1200_BAD_PIO(timings) (((timings)&~0x80000000)==0x00009172)
static int sc1200_autoselect_dma_mode (ide_drive_t *drive) static void sc1200_tunepio(ide_drive_t *drive, u8 pio)
{ {
int udma_ok = 1, mode = 0; ide_hwif_t *hwif = drive->hwif;
ide_hwif_t *hwif = HWIF(drive); struct pci_dev *pdev = hwif->pci_dev;
int unit = drive->select.b.unit; unsigned int basereg = hwif->channel ? 0x50 : 0x40, format = 0;
ide_drive_t *mate = &hwif->drives[unit^1];
struct hd_driveid *id = drive->id;
/* pci_read_config_dword(pdev, basereg + 4, &format);
* The SC1200 specifies that two drives sharing a cable cannot format = (format >> 31) & 1;
* mix UDMA/MDMA. It has to be one or the other, for the pair, if (format)
* though different timings can still be chosen for each drive. format += sc1200_get_pci_clock();
* We could set the appropriate timing bits on the fly, pci_write_config_dword(pdev, basereg + ((drive->dn & 1) << 3),
* but that might be a bit confusing. So, for now we statically sc1200_pio_timings[format][pio]);
* handle this requirement by looking at our mate drive to see }
* what it is capable of, before choosing a mode for our own drive.
/*
* The SC1200 specifies that two drives sharing a cable cannot mix
* UDMA/MDMA. It has to be one or the other, for the pair, though
* different timings can still be chosen for each drive. We could
* set the appropriate timing bits on the fly, but that might be
* a bit confusing. So, for now we statically handle this requirement
* by looking at our mate drive to see what it is capable of, before
* choosing a mode for our own drive.
*/ */
if (mate->present) { static u8 sc1200_udma_filter(ide_drive_t *drive)
{
ide_hwif_t *hwif = drive->hwif;
ide_drive_t *mate = &hwif->drives[(drive->dn & 1) ^ 1];
struct hd_driveid *mateid = mate->id; struct hd_driveid *mateid = mate->id;
if (mateid && (mateid->capability & 1) && !__ide_dma_bad_drive(mate)) { u8 mask = hwif->ultra_mask;
if (mate->present == 0)
goto out;
if ((mateid->capability & 1) && __ide_dma_bad_drive(mate) == 0) {
if ((mateid->field_valid & 4) && (mateid->dma_ultra & 7)) if ((mateid->field_valid & 4) && (mateid->dma_ultra & 7))
udma_ok = 1; goto out;
else if ((mateid->field_valid & 2) && (mateid->dma_mword & 7)) if ((mateid->field_valid & 2) && (mateid->dma_mword & 7))
udma_ok = 0; mask = 0;
else
udma_ok = 1;
}
}
/*
* Now see what the current drive is capable of,
* selecting UDMA only if the mate said it was ok.
*/
if (id && (id->capability & 1) && hwif->autodma && !__ide_dma_bad_drive(drive)) {
if (udma_ok && (id->field_valid & 4) && (id->dma_ultra & 7)) {
if (id->dma_ultra & 4)
mode = XFER_UDMA_2;
else if (id->dma_ultra & 2)
mode = XFER_UDMA_1;
else if (id->dma_ultra & 1)
mode = XFER_UDMA_0;
}
if (!mode && (id->field_valid & 2) && (id->dma_mword & 7)) {
if (id->dma_mword & 4)
mode = XFER_MW_DMA_2;
else if (id->dma_mword & 2)
mode = XFER_MW_DMA_1;
else if (id->dma_mword & 1)
mode = XFER_MW_DMA_0;
} }
} out:
return mode; return mask;
} }
/* static int sc1200_tune_chipset(ide_drive_t *drive, u8 mode)
* sc1200_config_dma2() handles selection/setting of DMA/UDMA modes
* for both the chipset and drive.
*/
static int sc1200_config_dma2 (ide_drive_t *drive, int mode)
{ {
ide_hwif_t *hwif = HWIF(drive); ide_hwif_t *hwif = HWIF(drive);
int unit = drive->select.b.unit; int unit = drive->select.b.unit;
...@@ -158,20 +146,26 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode) ...@@ -158,20 +146,26 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode)
unsigned short pci_clock; unsigned short pci_clock;
unsigned int basereg = hwif->channel ? 0x50 : 0x40; unsigned int basereg = hwif->channel ? 0x50 : 0x40;
/* mode = ide_rate_filter(drive, mode);
* Default to DMA-off in case we run into trouble here.
*/
hwif->dma_off_quietly(drive); /* turn off DMA while we fiddle */
outb(inb(hwif->dma_base+2)&~(unit?0x40:0x20), hwif->dma_base+2); /* clear DMA_capable bit */
/* /*
* Tell the drive to switch to the new mode; abort on failure. * Tell the drive to switch to the new mode; abort on failure.
*/ */
if (!mode || sc1200_set_xfer_mode(drive, mode)) { if (sc1200_set_xfer_mode(drive, mode)) {
printk("SC1200: set xfer mode failure\n"); printk("SC1200: set xfer mode failure\n");
return 1; /* failure */ return 1; /* failure */
} }
switch (mode) {
case XFER_PIO_4:
case XFER_PIO_3:
case XFER_PIO_2:
case XFER_PIO_1:
case XFER_PIO_0:
sc1200_tunepio(drive, mode - XFER_PIO_0);
return 0;
}
pci_clock = sc1200_get_pci_clock(); pci_clock = sc1200_get_pci_clock();
/* /*
...@@ -224,11 +218,9 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode) ...@@ -224,11 +218,9 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode)
case PCI_CLK_66: timings = 0x00015151; break; case PCI_CLK_66: timings = 0x00015151; break;
} }
break; break;
} default:
BUG();
if (timings == 0) { break;
printk("%s: sc1200_config_dma: huh? mode=%02x clk=%x \n", drive->name, mode, pci_clock);
return 1; /* failure */
} }
if (unit == 0) { /* are we configuring drive0? */ if (unit == 0) { /* are we configuring drive0? */
...@@ -239,8 +231,6 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode) ...@@ -239,8 +231,6 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode)
pci_write_config_dword(hwif->pci_dev, basereg+12, timings); pci_write_config_dword(hwif->pci_dev, basereg+12, timings);
} }
outb(inb(hwif->dma_base+2)|(unit?0x40:0x20), hwif->dma_base+2); /* set DMA_capable bit */
return 0; /* success */ return 0; /* success */
} }
...@@ -250,7 +240,10 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode) ...@@ -250,7 +240,10 @@ static int sc1200_config_dma2 (ide_drive_t *drive, int mode)
*/ */
static int sc1200_config_dma (ide_drive_t *drive) static int sc1200_config_dma (ide_drive_t *drive)
{ {
return sc1200_config_dma2(drive, sc1200_autoselect_dma_mode(drive)); if (ide_tune_dma(drive))
return 0;
return 1;
} }
...@@ -290,10 +283,11 @@ static int sc1200_ide_dma_end (ide_drive_t *drive) ...@@ -290,10 +283,11 @@ static int sc1200_ide_dma_end (ide_drive_t *drive)
static void sc1200_tuneproc (ide_drive_t *drive, byte pio) /* mode=255 means "autotune" */ static void sc1200_tuneproc (ide_drive_t *drive, byte pio) /* mode=255 means "autotune" */
{ {
ide_hwif_t *hwif = HWIF(drive); ide_hwif_t *hwif = HWIF(drive);
unsigned int format;
static byte modes[5] = {XFER_PIO_0, XFER_PIO_1, XFER_PIO_2, XFER_PIO_3, XFER_PIO_4};
int mode = -1; int mode = -1;
/*
* bad abuse of ->tuneproc interface
*/
switch (pio) { switch (pio) {
case 200: mode = XFER_UDMA_0; break; case 200: mode = XFER_UDMA_0; break;
case 201: mode = XFER_UDMA_1; break; case 201: mode = XFER_UDMA_1; break;
...@@ -304,20 +298,17 @@ static void sc1200_tuneproc (ide_drive_t *drive, byte pio) /* mode=255 means "au ...@@ -304,20 +298,17 @@ static void sc1200_tuneproc (ide_drive_t *drive, byte pio) /* mode=255 means "au
} }
if (mode != -1) { if (mode != -1) {
printk("SC1200: %s: changing (U)DMA mode\n", drive->name); printk("SC1200: %s: changing (U)DMA mode\n", drive->name);
(void)sc1200_config_dma2(drive, mode); hwif->dma_off_quietly(drive);
if (sc1200_tune_chipset(drive, mode) == 0)
hwif->dma_host_on(drive);
return; return;
} }
pio = ide_get_best_pio_mode(drive, pio, 4, NULL); pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
printk("SC1200: %s: setting PIO mode%d\n", drive->name, pio); printk("SC1200: %s: setting PIO mode%d\n", drive->name, pio);
if (!sc1200_set_xfer_mode(drive, modes[pio])) {
unsigned int basereg = hwif->channel ? 0x50 : 0x40; if (sc1200_set_xfer_mode(drive, XFER_PIO_0 + pio) == 0)
pci_read_config_dword (hwif->pci_dev, basereg+4, &format); sc1200_tunepio(drive, pio);
format = (format >> 31) & 1;
if (format)
format += sc1200_get_pci_clock();
pci_write_config_dword(hwif->pci_dev, basereg + (drive->select.b.unit << 3), sc1200_pio_timings[format][pio]);
}
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
...@@ -438,12 +429,12 @@ static int sc1200_resume (struct pci_dev *dev) ...@@ -438,12 +429,12 @@ static int sc1200_resume (struct pci_dev *dev)
for (d = 0; d < MAX_DRIVES; ++d) { for (d = 0; d < MAX_DRIVES; ++d) {
ide_drive_t *drive = &(hwif->drives[d]); ide_drive_t *drive = &(hwif->drives[d]);
if (drive->present && !__ide_dma_bad_drive(drive)) { if (drive->present && !__ide_dma_bad_drive(drive)) {
int was_using_dma = drive->using_dma; int enable_dma = drive->using_dma;
hwif->dma_off_quietly(drive); hwif->dma_off_quietly(drive);
sc1200_config_dma(drive); if (sc1200_config_dma(drive))
if (!was_using_dma && drive->using_dma) { enable_dma = 0;
hwif->dma_off_quietly(drive); if (enable_dma)
} hwif->dma_host_on(drive);
} }
} }
} }
...@@ -461,11 +452,13 @@ static void __devinit init_hwif_sc1200 (ide_hwif_t *hwif) ...@@ -461,11 +452,13 @@ static void __devinit init_hwif_sc1200 (ide_hwif_t *hwif)
hwif->serialized = hwif->mate->serialized = 1; hwif->serialized = hwif->mate->serialized = 1;
hwif->autodma = 0; hwif->autodma = 0;
if (hwif->dma_base) { if (hwif->dma_base) {
hwif->udma_filter = sc1200_udma_filter;
hwif->ide_dma_check = &sc1200_config_dma; hwif->ide_dma_check = &sc1200_config_dma;
hwif->ide_dma_end = &sc1200_ide_dma_end; hwif->ide_dma_end = &sc1200_ide_dma_end;
if (!noautodma) if (!noautodma)
hwif->autodma = 1; hwif->autodma = 1;
hwif->tuneproc = &sc1200_tuneproc; hwif->tuneproc = &sc1200_tuneproc;
hwif->speedproc = &sc1200_tune_chipset;
} }
hwif->atapi_dma = 1; hwif->atapi_dma = 1;
hwif->ultra_mask = 0x07; hwif->ultra_mask = 0x07;
......
...@@ -321,26 +321,6 @@ static int scc_tune_chipset(ide_drive_t *drive, byte xferspeed) ...@@ -321,26 +321,6 @@ static int scc_tune_chipset(ide_drive_t *drive, byte xferspeed)
return ide_config_drive_speed(drive, speed); return ide_config_drive_speed(drive, speed);
} }
/**
* scc_config_chipset_for_dma - configure for DMA
* @drive: drive to configure
*
* Called by scc_config_drive_for_dma().
*/
static int scc_config_chipset_for_dma(ide_drive_t *drive)
{
u8 speed = ide_max_dma_mode(drive);
if (!speed)
return 0;
if (scc_tune_chipset(drive, speed))
return 0;
return ide_dma_enable(drive);
}
/** /**
* scc_configure_drive_for_dma - set up for DMA transfers * scc_configure_drive_for_dma - set up for DMA transfers
* @drive: drive we are going to set up * @drive: drive we are going to set up
...@@ -354,7 +334,7 @@ static int scc_config_chipset_for_dma(ide_drive_t *drive) ...@@ -354,7 +334,7 @@ static int scc_config_chipset_for_dma(ide_drive_t *drive)
static int scc_config_drive_for_dma(ide_drive_t *drive) static int scc_config_drive_for_dma(ide_drive_t *drive)
{ {
if (ide_use_dma(drive) && scc_config_chipset_for_dma(drive)) if (ide_tune_dma(drive))
return 0; return 0;
if (ide_use_fast_pio(drive)) if (ide_use_fast_pio(drive))
......
/* /*
* linux/drivers/ide/pci/serverworks.c Version 0.8 25 Ebr 2003 * linux/drivers/ide/pci/serverworks.c Version 0.9 Mar 4 2007
* *
* Copyright (C) 1998-2000 Michel Aubry * Copyright (C) 1998-2000 Michel Aubry
* Copyright (C) 1998-2000 Andrzej Krzysztofowicz * Copyright (C) 1998-2000 Andrzej Krzysztofowicz
* Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2007 Bartlomiej Zolnierkiewicz
* Portions copyright (c) 2001 Sun Microsystems * Portions copyright (c) 2001 Sun Microsystems
* *
* *
...@@ -136,19 +137,14 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed) ...@@ -136,19 +137,14 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed)
ide_hwif_t *hwif = HWIF(drive); ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev; struct pci_dev *dev = hwif->pci_dev;
u8 speed; u8 speed = ide_rate_filter(drive, xferspeed);
u8 pio = ide_get_best_pio_mode(drive, 255, 5, NULL); u8 pio = ide_get_best_pio_mode(drive, 255, 4, NULL);
u8 unit = (drive->select.b.unit & 0x01); u8 unit = (drive->select.b.unit & 0x01);
u8 csb5 = svwks_csb_check(dev); u8 csb5 = svwks_csb_check(dev);
u8 ultra_enable = 0, ultra_timing = 0; u8 ultra_enable = 0, ultra_timing = 0;
u8 dma_timing = 0, pio_timing = 0; u8 dma_timing = 0, pio_timing = 0;
u16 csb5_pio = 0; u16 csb5_pio = 0;
if (xferspeed == 255) /* PIO auto-tuning */
speed = XFER_PIO_0 + pio;
else
speed = ide_rate_filter(drive, xferspeed);
/* If we are about to put a disk into UDMA mode we screwed up. /* If we are about to put a disk into UDMA mode we screwed up.
Our code assumes we never _ever_ do this on an OSB4 */ Our code assumes we never _ever_ do this on an OSB4 */
...@@ -231,6 +227,9 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed) ...@@ -231,6 +227,9 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed)
case XFER_MW_DMA_2: case XFER_MW_DMA_2:
case XFER_MW_DMA_1: case XFER_MW_DMA_1:
case XFER_MW_DMA_0: case XFER_MW_DMA_0:
/*
* TODO: always setup PIO mode so this won't be needed
*/
pio_timing |= pio_modes[pio]; pio_timing |= pio_modes[pio];
csb5_pio |= (pio << (4*drive->dn)); csb5_pio |= (pio << (4*drive->dn));
dma_timing |= dma_modes[speed - XFER_MW_DMA_0]; dma_timing |= dma_modes[speed - XFER_MW_DMA_0];
...@@ -242,6 +241,9 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed) ...@@ -242,6 +241,9 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed)
case XFER_UDMA_2: case XFER_UDMA_2:
case XFER_UDMA_1: case XFER_UDMA_1:
case XFER_UDMA_0: case XFER_UDMA_0:
/*
* TODO: always setup PIO mode so this won't be needed
*/
pio_timing |= pio_modes[pio]; pio_timing |= pio_modes[pio];
csb5_pio |= (pio << (4*drive->dn)); csb5_pio |= (pio << (4*drive->dn));
dma_timing |= dma_modes[2]; dma_timing |= dma_modes[2];
...@@ -262,72 +264,21 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed) ...@@ -262,72 +264,21 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed)
return (ide_config_drive_speed(drive, speed)); return (ide_config_drive_speed(drive, speed));
} }
static void config_chipset_for_pio (ide_drive_t *drive)
{
u16 eide_pio_timing[6] = {960, 480, 240, 180, 120, 90};
u16 xfer_pio = drive->id->eide_pio_modes;
u8 timing, speed, pio;
pio = ide_get_best_pio_mode(drive, 255, 5, NULL);
if (xfer_pio > 4)
xfer_pio = 0;
if (drive->id->eide_pio_iordy > 0)
for (xfer_pio = 5;
xfer_pio>0 &&
drive->id->eide_pio_iordy>eide_pio_timing[xfer_pio];
xfer_pio--);
else
xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 :
(drive->id->eide_pio_modes & 2) ? 0x04 :
(drive->id->eide_pio_modes & 1) ? 0x03 :
(drive->id->tPIO & 2) ? 0x02 :
(drive->id->tPIO & 1) ? 0x01 : xfer_pio;
timing = (xfer_pio >= pio) ? xfer_pio : pio;
switch(timing) {
case 4: speed = XFER_PIO_4;break;
case 3: speed = XFER_PIO_3;break;
case 2: speed = XFER_PIO_2;break;
case 1: speed = XFER_PIO_1;break;
default:
speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW;
break;
}
(void) svwks_tune_chipset(drive, speed);
drive->current_speed = speed;
}
static void svwks_tune_drive (ide_drive_t *drive, u8 pio) static void svwks_tune_drive (ide_drive_t *drive, u8 pio)
{ {
if(pio == 255) pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
(void) svwks_tune_chipset(drive, 255); (void)svwks_tune_chipset(drive, XFER_PIO_0 + pio);
else
(void) svwks_tune_chipset(drive, (XFER_PIO_0 + pio));
}
static int config_chipset_for_dma (ide_drive_t *drive)
{
u8 speed = ide_max_dma_mode(drive);
if (!(speed))
speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL);
(void) svwks_tune_chipset(drive, speed);
return ide_dma_enable(drive);
} }
static int svwks_config_drive_xfer_rate (ide_drive_t *drive) static int svwks_config_drive_xfer_rate (ide_drive_t *drive)
{ {
drive->init_speed = 0; drive->init_speed = 0;
if (ide_use_dma(drive) && config_chipset_for_dma(drive)) if (ide_tune_dma(drive))
return 0; return 0;
if (ide_use_fast_pio(drive)) if (ide_use_fast_pio(drive))
config_chipset_for_pio(drive); svwks_tune_drive(drive, 255);
return -1; return -1;
} }
......
...@@ -374,28 +374,6 @@ static int siimage_tune_chipset (ide_drive_t *drive, byte xferspeed) ...@@ -374,28 +374,6 @@ static int siimage_tune_chipset (ide_drive_t *drive, byte xferspeed)
return (ide_config_drive_speed(drive, speed)); return (ide_config_drive_speed(drive, speed));
} }
/**
* config_chipset_for_dma - configure for DMA
* @drive: drive to configure
*
* Called by the IDE layer when it wants the timings set up.
* For the CMD680 we also need to set up the PIO timings and
* enable DMA.
*/
static int config_chipset_for_dma (ide_drive_t *drive)
{
u8 speed = ide_max_dma_mode(drive);
if (!speed)
return 0;
if (siimage_tune_chipset(drive, speed))
return 0;
return ide_dma_enable(drive);
}
/** /**
* siimage_configure_drive_for_dma - set up for DMA transfers * siimage_configure_drive_for_dma - set up for DMA transfers
* @drive: drive we are going to set up * @drive: drive we are going to set up
...@@ -408,7 +386,7 @@ static int config_chipset_for_dma (ide_drive_t *drive) ...@@ -408,7 +386,7 @@ static int config_chipset_for_dma (ide_drive_t *drive)
static int siimage_config_drive_for_dma (ide_drive_t *drive) static int siimage_config_drive_for_dma (ide_drive_t *drive)
{ {
if (ide_use_dma(drive) && config_chipset_for_dma(drive)) if (ide_tune_dma(drive))
return 0; return 0;
if (ide_use_fast_pio(drive)) if (ide_use_fast_pio(drive))
......
/* /*
* linux/drivers/ide/pci/sis5513.c Version 0.16ac+vp Jun 18, 2003 * linux/drivers/ide/pci/sis5513.c Version 0.20 Mar 4, 2007
* *
* Copyright (C) 1999-2000 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 1999-2000 Andre Hedrick <andre@linux-ide.org>
* Copyright (C) 2002 Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer * Copyright (C) 2002 Lionel Bouton <Lionel.Bouton@inet6.fr>, Maintainer
* Copyright (C) 2003 Vojtech Pavlik <vojtech@suse.cz> * Copyright (C) 2003 Vojtech Pavlik <vojtech@suse.cz>
* Copyright (C) 2007 Bartlomiej Zolnierkiewicz
*
* May be copied or modified under the terms of the GNU General Public License * May be copied or modified under the terms of the GNU General Public License
* *
* *
...@@ -448,36 +450,15 @@ static void config_drive_art_rwp (ide_drive_t *drive) ...@@ -448,36 +450,15 @@ static void config_drive_art_rwp (ide_drive_t *drive)
pci_write_config_byte(dev, 0x4b, reg4bh|rw_prefetch); pci_write_config_byte(dev, 0x4b, reg4bh|rw_prefetch);
} }
/* Set per-drive active and recovery time */ /* Set per-drive active and recovery time */
static void config_art_rwp_pio (ide_drive_t *drive, u8 pio) static void config_art_rwp_pio (ide_drive_t *drive, u8 pio)
{ {
ide_hwif_t *hwif = HWIF(drive); ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev; struct pci_dev *dev = hwif->pci_dev;
u8 timing, drive_pci, test1, test2; u8 drive_pci, test1, test2;
u16 eide_pio_timing[6] = {600, 390, 240, 180, 120, 90};
u16 xfer_pio = drive->id->eide_pio_modes;
config_drive_art_rwp(drive); config_drive_art_rwp(drive);
pio = ide_get_best_pio_mode(drive, 255, pio, NULL);
if (xfer_pio> 4)
xfer_pio = 0;
if (drive->id->eide_pio_iordy > 0) {
for (xfer_pio = 5;
(xfer_pio > 0) &&
(drive->id->eide_pio_iordy > eide_pio_timing[xfer_pio]);
xfer_pio--);
} else {
xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 :
(drive->id->eide_pio_modes & 2) ? 0x04 :
(drive->id->eide_pio_modes & 1) ? 0x03 : xfer_pio;
}
timing = (xfer_pio >= pio) ? xfer_pio : pio;
/* In pre ATA_133 case, drives sit at 0x40 + 4*drive->dn */ /* In pre ATA_133 case, drives sit at 0x40 + 4*drive->dn */
drive_pci = 0x40; drive_pci = 0x40;
...@@ -500,17 +481,18 @@ static void config_art_rwp_pio (ide_drive_t *drive, u8 pio) ...@@ -500,17 +481,18 @@ static void config_art_rwp_pio (ide_drive_t *drive, u8 pio)
test1 &= ~0x0F; test1 &= ~0x0F;
test2 &= ~0x07; test2 &= ~0x07;
switch(timing) { switch(pio) {
case 4: test1 |= 0x01; test2 |= 0x03; break; case 4: test1 |= 0x01; test2 |= 0x03; break;
case 3: test1 |= 0x03; test2 |= 0x03; break; case 3: test1 |= 0x03; test2 |= 0x03; break;
case 2: test1 |= 0x04; test2 |= 0x04; break; case 2: test1 |= 0x04; test2 |= 0x04; break;
case 1: test1 |= 0x07; test2 |= 0x06; break; case 1: test1 |= 0x07; test2 |= 0x06; break;
case 0: /* PIO0: register setting == X000 */
default: break; default: break;
} }
pci_write_config_byte(dev, drive_pci, test1); pci_write_config_byte(dev, drive_pci, test1);
pci_write_config_byte(dev, drive_pci+1, test2); pci_write_config_byte(dev, drive_pci+1, test2);
} else if (chipset_family < ATA_133) { } else if (chipset_family < ATA_133) {
switch(timing) { /* active recovery switch(pio) { /* active recovery
v v */ v v */
case 4: test1 = 0x30|0x01; break; case 4: test1 = 0x30|0x01; break;
case 3: test1 = 0x30|0x03; break; case 3: test1 = 0x30|0x03; break;
...@@ -525,24 +507,28 @@ static void config_art_rwp_pio (ide_drive_t *drive, u8 pio) ...@@ -525,24 +507,28 @@ static void config_art_rwp_pio (ide_drive_t *drive, u8 pio)
pci_read_config_dword(dev, drive_pci, &test3); pci_read_config_dword(dev, drive_pci, &test3);
test3 &= 0xc0c00fff; test3 &= 0xc0c00fff;
if (test3 & 0x08) { if (test3 & 0x08) {
test3 |= (unsigned long)ini_time_value[ATA_133][timing] << 12; test3 |= ini_time_value[ATA_133][pio] << 12;
test3 |= (unsigned long)act_time_value[ATA_133][timing] << 16; test3 |= act_time_value[ATA_133][pio] << 16;
test3 |= (unsigned long)rco_time_value[ATA_133][timing] << 24; test3 |= rco_time_value[ATA_133][pio] << 24;
} else { } else {
test3 |= (unsigned long)ini_time_value[ATA_100][timing] << 12; test3 |= ini_time_value[ATA_100][pio] << 12;
test3 |= (unsigned long)act_time_value[ATA_100][timing] << 16; test3 |= act_time_value[ATA_100][pio] << 16;
test3 |= (unsigned long)rco_time_value[ATA_100][timing] << 24; test3 |= rco_time_value[ATA_100][pio] << 24;
} }
pci_write_config_dword(dev, drive_pci, test3); pci_write_config_dword(dev, drive_pci, test3);
} }
} }
static int config_chipset_for_pio (ide_drive_t *drive, u8 pio) static int sis5513_tune_drive(ide_drive_t *drive, u8 pio)
{ {
if (pio == 255) pio = ide_get_best_pio_mode(drive, pio, 4, NULL);
pio = ide_find_best_mode(drive, XFER_PIO | XFER_EPIO) - XFER_PIO_0;
config_art_rwp_pio(drive, pio); config_art_rwp_pio(drive, pio);
return ide_config_drive_speed(drive, XFER_PIO_0 + min_t(u8, pio, 4)); return ide_config_drive_speed(drive, XFER_PIO_0 + pio);
}
static void sis5513_tuneproc(ide_drive_t *drive, u8 pio)
{
(void)sis5513_tune_drive(drive, pio);
} }
static int sis5513_tune_chipset (ide_drive_t *drive, u8 xferspeed) static int sis5513_tune_chipset (ide_drive_t *drive, u8 xferspeed)
...@@ -622,25 +608,26 @@ static int sis5513_tune_chipset (ide_drive_t *drive, u8 xferspeed) ...@@ -622,25 +608,26 @@ static int sis5513_tune_chipset (ide_drive_t *drive, u8 xferspeed)
case XFER_SW_DMA_1: case XFER_SW_DMA_1:
case XFER_SW_DMA_0: case XFER_SW_DMA_0:
break; break;
case XFER_PIO_4: return((int) config_chipset_for_pio(drive, 4)); case XFER_PIO_4:
case XFER_PIO_3: return((int) config_chipset_for_pio(drive, 3)); case XFER_PIO_3:
case XFER_PIO_2: return((int) config_chipset_for_pio(drive, 2)); case XFER_PIO_2:
case XFER_PIO_1: return((int) config_chipset_for_pio(drive, 1)); case XFER_PIO_1:
case XFER_PIO_0: case XFER_PIO_0:
default: return((int) config_chipset_for_pio(drive, 0)); return sis5513_tune_drive(drive, speed - XFER_PIO_0);
default:
BUG();
break;
} }
return ((int) ide_config_drive_speed(drive, speed)); return ide_config_drive_speed(drive, speed);
}
static void sis5513_tune_drive (ide_drive_t *drive, u8 pio)
{
(void) config_chipset_for_pio(drive, pio);
} }
static int sis5513_config_xfer_rate(ide_drive_t *drive) static int sis5513_config_xfer_rate(ide_drive_t *drive)
{ {
config_art_rwp_pio(drive, 5); /*
* TODO: always set PIO mode and remove this
*/
sis5513_tuneproc(drive, 255);
drive->init_speed = 0; drive->init_speed = 0;
...@@ -648,7 +635,7 @@ static int sis5513_config_xfer_rate(ide_drive_t *drive) ...@@ -648,7 +635,7 @@ static int sis5513_config_xfer_rate(ide_drive_t *drive)
return 0; return 0;
if (ide_use_fast_pio(drive)) if (ide_use_fast_pio(drive))
sis5513_tune_drive(drive, 5); sis5513_tuneproc(drive, 255);
return -1; return -1;
} }
...@@ -836,7 +823,7 @@ static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif) ...@@ -836,7 +823,7 @@ static void __devinit init_hwif_sis5513 (ide_hwif_t *hwif)
if (!hwif->irq) if (!hwif->irq)
hwif->irq = hwif->channel ? 15 : 14; hwif->irq = hwif->channel ? 15 : 14;
hwif->tuneproc = &sis5513_tune_drive; hwif->tuneproc = &sis5513_tuneproc;
hwif->speedproc = &sis5513_tune_chipset; hwif->speedproc = &sis5513_tune_chipset;
if (!(hwif->dma_base)) { if (!(hwif->dma_base)) {
......
...@@ -82,7 +82,14 @@ static u8 sl82c105_tune_pio(ide_drive_t *drive, u8 pio) ...@@ -82,7 +82,14 @@ static u8 sl82c105_tune_pio(ide_drive_t *drive, u8 pio)
pio = ide_get_best_pio_mode(drive, pio, 5, &p); pio = ide_get_best_pio_mode(drive, pio, 5, &p);
drive->drive_data = drv_ctrl = get_pio_timings(&p); drv_ctrl = get_pio_timings(&p);
/*
* Store the PIO timings so that we can restore them
* in case DMA will be turned off...
*/
drive->drive_data &= 0xffff0000;
drive->drive_data |= drv_ctrl;
if (!drive->using_dma) { if (!drive->using_dma) {
/* /*
...@@ -100,17 +107,55 @@ static u8 sl82c105_tune_pio(ide_drive_t *drive, u8 pio) ...@@ -100,17 +107,55 @@ static u8 sl82c105_tune_pio(ide_drive_t *drive, u8 pio)
} }
/* /*
* Configure the drive for DMA. * Configure the drive and chipset for a new transfer speed.
* We'll program the chipset only when DMA is actually turned on.
*/ */
static int config_for_dma(ide_drive_t *drive) static int sl82c105_tune_chipset(ide_drive_t *drive, u8 speed)
{ {
DBG(("config_for_dma(drive:%s)\n", drive->name)); static u16 mwdma_timings[] = {0x0707, 0x0201, 0x0200};
u16 drv_ctrl;
if (ide_config_drive_speed(drive, XFER_MW_DMA_2) != 0) DBG(("sl82c105_tune_chipset(drive:%s, speed:%s)\n",
return 0; drive->name, ide_xfer_verbose(speed)));
speed = ide_rate_filter(drive, speed);
switch (speed) {
case XFER_MW_DMA_2:
case XFER_MW_DMA_1:
case XFER_MW_DMA_0:
drv_ctrl = mwdma_timings[speed - XFER_MW_DMA_0];
/*
* Store the DMA timings so that we can actually program
* them when DMA will be turned on...
*/
drive->drive_data &= 0x0000ffff;
drive->drive_data |= (unsigned long)drv_ctrl << 16;
/*
* If we are already using DMA, we just reprogram
* the drive control register.
*/
if (drive->using_dma) {
struct pci_dev *dev = HWIF(drive)->pci_dev;
int reg = 0x44 + drive->dn * 4;
return ide_dma_enable(drive); pci_write_config_word(dev, reg, drv_ctrl);
}
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) sl82c105_tune_pio(drive, speed - XFER_PIO_0);
break;
default:
return -1;
}
return ide_config_drive_speed(drive, speed);
} }
/* /*
...@@ -120,7 +165,7 @@ static int sl82c105_ide_dma_check(ide_drive_t *drive) ...@@ -120,7 +165,7 @@ static int sl82c105_ide_dma_check(ide_drive_t *drive)
{ {
DBG(("sl82c105_ide_dma_check(drive:%s)\n", drive->name)); DBG(("sl82c105_ide_dma_check(drive:%s)\n", drive->name));
if (ide_use_dma(drive) && config_for_dma(drive)) if (ide_tune_dma(drive))
return 0; return 0;
return -1; return -1;
...@@ -219,7 +264,7 @@ static int sl82c105_ide_dma_on(ide_drive_t *drive) ...@@ -219,7 +264,7 @@ static int sl82c105_ide_dma_on(ide_drive_t *drive)
rc = __ide_dma_on(drive); rc = __ide_dma_on(drive);
if (rc == 0) { if (rc == 0) {
pci_write_config_word(dev, reg, 0x0200); pci_write_config_word(dev, reg, drive->drive_data >> 16);
printk(KERN_INFO "%s: DMA enabled\n", drive->name); printk(KERN_INFO "%s: DMA enabled\n", drive->name);
} }
...@@ -304,7 +349,7 @@ static unsigned int sl82c105_bridge_revision(struct pci_dev *dev) ...@@ -304,7 +349,7 @@ static unsigned int sl82c105_bridge_revision(struct pci_dev *dev)
/* /*
* The bridge should be part of the same device, but function 0. * The bridge should be part of the same device, but function 0.
*/ */
bridge = pci_find_slot(dev->bus->number, bridge = pci_get_bus_and_slot(dev->bus->number,
PCI_DEVFN(PCI_SLOT(dev->devfn), 0)); PCI_DEVFN(PCI_SLOT(dev->devfn), 0));
if (!bridge) if (!bridge)
return -1; return -1;
...@@ -314,13 +359,15 @@ static unsigned int sl82c105_bridge_revision(struct pci_dev *dev) ...@@ -314,13 +359,15 @@ static unsigned int sl82c105_bridge_revision(struct pci_dev *dev)
*/ */
if (bridge->vendor != PCI_VENDOR_ID_WINBOND || if (bridge->vendor != PCI_VENDOR_ID_WINBOND ||
bridge->device != PCI_DEVICE_ID_WINBOND_83C553 || bridge->device != PCI_DEVICE_ID_WINBOND_83C553 ||
bridge->class >> 8 != PCI_CLASS_BRIDGE_ISA) bridge->class >> 8 != PCI_CLASS_BRIDGE_ISA) {
pci_dev_put(bridge);
return -1; return -1;
}
/* /*
* We need to find function 0's revision, not function 1 * We need to find function 0's revision, not function 1
*/ */
pci_read_config_byte(bridge, PCI_REVISION_ID, &rev); pci_read_config_byte(bridge, PCI_REVISION_ID, &rev);
pci_dev_put(bridge);
return rev; return rev;
} }
...@@ -357,6 +404,7 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif) ...@@ -357,6 +404,7 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index)); DBG(("init_hwif_sl82c105(hwif: ide%d)\n", hwif->index));
hwif->tuneproc = &sl82c105_tune_drive; hwif->tuneproc = &sl82c105_tune_drive;
hwif->speedproc = &sl82c105_tune_chipset;
hwif->selectproc = &sl82c105_selectproc; hwif->selectproc = &sl82c105_selectproc;
hwif->resetproc = &sl82c105_resetproc; hwif->resetproc = &sl82c105_resetproc;
...@@ -388,7 +436,7 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif) ...@@ -388,7 +436,7 @@ static void __devinit init_hwif_sl82c105(ide_hwif_t *hwif)
} }
hwif->atapi_dma = 1; hwif->atapi_dma = 1;
hwif->mwdma_mask = 0x04; hwif->mwdma_mask = 0x07;
hwif->ide_dma_check = &sl82c105_ide_dma_check; hwif->ide_dma_check = &sl82c105_ide_dma_check;
hwif->ide_dma_on = &sl82c105_ide_dma_on; hwif->ide_dma_on = &sl82c105_ide_dma_on;
......
...@@ -1281,7 +1281,6 @@ struct drive_list_entry { ...@@ -1281,7 +1281,6 @@ struct drive_list_entry {
int ide_in_drive_list(struct hd_driveid *, const struct drive_list_entry *); int ide_in_drive_list(struct hd_driveid *, const struct drive_list_entry *);
int __ide_dma_bad_drive(ide_drive_t *); int __ide_dma_bad_drive(ide_drive_t *);
int __ide_dma_good_drive(ide_drive_t *); int __ide_dma_good_drive(ide_drive_t *);
int ide_use_dma(ide_drive_t *);
u8 ide_max_dma_mode(ide_drive_t *); u8 ide_max_dma_mode(ide_drive_t *);
int ide_tune_dma(ide_drive_t *); int ide_tune_dma(ide_drive_t *);
void ide_dma_off(ide_drive_t *); void ide_dma_off(ide_drive_t *);
...@@ -1309,7 +1308,6 @@ extern int __ide_dma_timeout(ide_drive_t *); ...@@ -1309,7 +1308,6 @@ extern int __ide_dma_timeout(ide_drive_t *);
#endif /* CONFIG_BLK_DEV_IDEDMA_PCI */ #endif /* CONFIG_BLK_DEV_IDEDMA_PCI */
#else #else
static inline int ide_use_dma(ide_drive_t *drive) { return 0; }
static inline u8 ide_max_dma_mode(ide_drive_t *drive) { return 0; } static inline u8 ide_max_dma_mode(ide_drive_t *drive) { return 0; }
static inline int ide_tune_dma(ide_drive_t *drive) { return 0; } static inline int ide_tune_dma(ide_drive_t *drive) { return 0; }
static inline void ide_dma_off(ide_drive_t *drive) { ; } static inline void ide_dma_off(ide_drive_t *drive) { ; }
...@@ -1357,7 +1355,6 @@ static inline void ide_set_hwifdata (ide_hwif_t * hwif, void *data) ...@@ -1357,7 +1355,6 @@ static inline void ide_set_hwifdata (ide_hwif_t * hwif, void *data)
/* ide-lib.c */ /* ide-lib.c */
u8 ide_rate_filter(ide_drive_t *, u8); u8 ide_rate_filter(ide_drive_t *, u8);
extern int ide_dma_enable(ide_drive_t *drive);
extern char *ide_xfer_verbose(u8 xfer_rate); extern char *ide_xfer_verbose(u8 xfer_rate);
extern void ide_toggle_bounce(ide_drive_t *drive, int on); extern void ide_toggle_bounce(ide_drive_t *drive, int on);
extern int ide_set_xfer_rate(ide_drive_t *drive, u8 rate); extern int ide_set_xfer_rate(ide_drive_t *drive, u8 rate);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment