summaryrefslogtreecommitdiffstats
path: root/drivers/ide
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-06-15 01:55:58 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-06-15 01:55:58 +0000
commit53b3988d474435254a3b053a68bb24ce9e439295 (patch)
treef8da8e40f01f4ad02bbd76b8c9920749b118235f /drivers/ide
parentb0cb48abe83d1a4389ea938bf624f8baa82c5047 (diff)
Merge with 2.3.99-pre9.
Diffstat (limited to 'drivers/ide')
-rw-r--r--drivers/ide/Config.in9
-rw-r--r--drivers/ide/aec62xx.c43
-rw-r--r--drivers/ide/alim15x3.c10
-rw-r--r--drivers/ide/amd7409.c51
-rw-r--r--drivers/ide/cmd64x.c34
-rw-r--r--drivers/ide/hd.c9
-rw-r--r--drivers/ide/hpt34x.c17
-rw-r--r--drivers/ide/hpt366.c30
-rw-r--r--drivers/ide/icside.c156
-rw-r--r--drivers/ide/ide-disk.c11
-rw-r--r--drivers/ide/ide-features.c66
-rw-r--r--drivers/ide/ide-pci.c20
-rw-r--r--drivers/ide/ide-pmac.c243
-rw-r--r--drivers/ide/ide-probe.c66
-rw-r--r--drivers/ide/ide.c224
-rw-r--r--drivers/ide/pdc202xx.c243
-rw-r--r--drivers/ide/piix.c107
-rw-r--r--drivers/ide/qd6580.c252
-rw-r--r--drivers/ide/sis5513.c16
-rw-r--r--drivers/ide/via82cxxx.c48
20 files changed, 1055 insertions, 600 deletions
diff --git a/drivers/ide/Config.in b/drivers/ide/Config.in
index 6d68bd5ea..09c6451cf 100644
--- a/drivers/ide/Config.in
+++ b/drivers/ide/Config.in
@@ -12,6 +12,15 @@ if [ "$CONFIG_BLK_DEV_IDE" != "n" ]; then
dep_tristate ' Include IDE/ATA-2 DISK support' CONFIG_BLK_DEV_IDEDISK $CONFIG_BLK_DEV_IDE
dep_mbool ' Use multi-mode by default' CONFIG_IDEDISK_MULTI_MODE $CONFIG_BLK_DEV_IDEDISK
+
+ define_bool CONFIG_BLK_DEV_IDEDISK_VENDOR n
+ dep_mbool ' Fujitsu Vendor Specific' CONFIG_BLK_DEV_IDEDISK_FUJITSU $CONFIG_BLK_DEV_IDEDISK_VENDOR
+ dep_mbool ' IBM Vendor Specific' CONFIG_BLK_DEV_IDEDISK_IBM $CONFIG_BLK_DEV_IDEDISK_VENDOR
+ dep_mbool ' Maxtor Vendor Specific' CONFIG_BLK_DEV_IDEDISK_MAXTOR $CONFIG_BLK_DEV_IDEDISK_VENDOR
+ dep_mbool ' Quantum Vendor Specific' CONFIG_BLK_DEV_IDEDISK_QUANTUM $CONFIG_BLK_DEV_IDEDISK_VENDOR
+ dep_mbool ' Seagate Vendor Specific' CONFIG_BLK_DEV_IDEDISK_SEAGATE $CONFIG_BLK_DEV_IDEDISK_VENDOR
+ dep_mbool ' Western Digital Vendor Specific' CONFIG_BLK_DEV_IDEDISK_WD $CONFIG_BLK_DEV_IDEDISK_VENDOR
+
dep_tristate ' PCMCIA IDE support' CONFIG_BLK_DEV_IDECS $CONFIG_BLK_DEV_IDE $CONFIG_PCMCIA
dep_tristate ' Include IDE/ATAPI CDROM support' CONFIG_BLK_DEV_IDECD $CONFIG_BLK_DEV_IDE
dep_tristate ' Include IDE/ATAPI TAPE support' CONFIG_BLK_DEV_IDETAPE $CONFIG_BLK_DEV_IDE
diff --git a/drivers/ide/aec62xx.c b/drivers/ide/aec62xx.c
index 0158b4279..75b3153b7 100644
--- a/drivers/ide/aec62xx.c
+++ b/drivers/ide/aec62xx.c
@@ -176,6 +176,7 @@ struct chipset_bus_clock_list_entry {
};
struct chipset_bus_clock_list_entry aec62xx_base [] = {
+#ifdef CONFIG_BLK_DEV_IDEDMA
{ XFER_UDMA_4, 0x41, 0x04, 0x31, 0x05 },
{ XFER_UDMA_3, 0x41, 0x03, 0x31, 0x04 },
{ XFER_UDMA_2, 0x41, 0x02, 0x31, 0x03 },
@@ -185,7 +186,7 @@ struct chipset_bus_clock_list_entry aec62xx_base [] = {
{ XFER_MW_DMA_2, 0x41, 0x00, 0x31, 0x00 },
{ XFER_MW_DMA_1, 0x42, 0x00, 0x31, 0x00 },
{ XFER_MW_DMA_0, 0x7a, 0x00, 0x0a, 0x00 },
-
+#endif /* CONFIG_BLK_DEV_IDEDMA */
{ XFER_PIO_4, 0x41, 0x00, 0x31, 0x00 },
{ XFER_PIO_3, 0x43, 0x00, 0x33, 0x00 },
{ XFER_PIO_2, 0x78, 0x00, 0x08, 0x00 },
@@ -202,18 +203,22 @@ extern char *ide_xfer_verbose (byte xfer_rate);
static byte pci_bus_clock_list (byte speed, struct chipset_bus_clock_list_entry * chipset_table)
{
+ int bus_speed = system_bus_clock();
+
for ( ; chipset_table->xfer_speed ; chipset_table++)
if (chipset_table->xfer_speed == speed) {
- return ((byte) ((1) ? chipset_table->chipset_settings_33 : chipset_table->chipset_settings_34));
+ return ((byte) ((bus_speed <= 33) ? chipset_table->chipset_settings_33 : chipset_table->chipset_settings_34));
}
return 0x00;
}
static byte pci_bus_clock_list_ultra (byte speed, struct chipset_bus_clock_list_entry * chipset_table)
{
+ int bus_speed = system_bus_clock();
+
for ( ; chipset_table->xfer_speed ; chipset_table++)
if (chipset_table->xfer_speed == speed) {
- return ((byte) ((1) ? chipset_table->ultra_settings_33 : chipset_table->ultra_settings_34));
+ return ((byte) ((bus_speed <= 33) ? chipset_table->ultra_settings_33 : chipset_table->ultra_settings_34));
}
return 0x00;
}
@@ -222,8 +227,6 @@ static int aec6210_tune_chipset (ide_drive_t *drive, byte speed)
{
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev;
- byte unit = (drive->select.b.unit & 0x01);
- int drive_number = ((hwif->channel ? 2 : 0) + unit);
int err = 0;
unsigned short d_conf = 0x0000;
byte ultra = 0x00;
@@ -236,18 +239,18 @@ static int aec6210_tune_chipset (ide_drive_t *drive, byte speed)
__save_flags(flags); /* local CPU only */
__cli(); /* local CPU only */
- pci_read_config_word(dev, 0x40|(2*drive_number), &d_conf);
+ pci_read_config_word(dev, 0x40|(2*drive->dn), &d_conf);
tmp0 = pci_bus_clock_list(speed, aec62xx_base);
SPLIT_BYTE(tmp0,tmp1,tmp2);
MAKE_WORD(d_conf,tmp1,tmp2);
- pci_write_config_word(dev, 0x40|(2*drive_number), d_conf);
+ pci_write_config_word(dev, 0x40|(2*drive->dn), d_conf);
tmp1 = 0x00;
tmp2 = 0x00;
pci_read_config_byte(dev, 0x54, &ultra);
- tmp1 = ((0x00 << (2*drive_number)) | (ultra & ~(3 << (2*drive_number))));
+ tmp1 = ((0x00 << (2*drive->dn)) | (ultra & ~(3 << (2*drive->dn))));
ultra_conf = pci_bus_clock_list_ultra(speed, aec62xx_base);
- tmp2 = ((ultra_conf << (2*drive_number)) | (tmp1 & ~(3 << (2*drive_number))));
+ tmp2 = ((ultra_conf << (2*drive->dn)) | (tmp1 & ~(3 << (2*drive->dn))));
pci_write_config_byte(dev, 0x54, tmp2);
__restore_flags(flags); /* local CPU only */
@@ -261,7 +264,6 @@ static int aec6260_tune_chipset (ide_drive_t *drive, byte speed)
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev;
byte unit = (drive->select.b.unit & 0x01);
- int drive_number = ((hwif->channel ? 2 : 0) + unit);
byte ultra_pci = hwif->channel ? 0x45 : 0x44;
int err = 0;
byte drive_conf = 0x00;
@@ -269,15 +271,14 @@ static int aec6260_tune_chipset (ide_drive_t *drive, byte speed)
byte ultra = 0x00;
byte tmp1 = 0x00;
byte tmp2 = 0x00;
-
unsigned long flags;
__save_flags(flags); /* local CPU only */
__cli(); /* local CPU only */
- pci_read_config_byte(dev, 0x40|drive_number, &drive_conf);
+ pci_read_config_byte(dev, 0x40|drive->dn, &drive_conf);
drive_conf = pci_bus_clock_list(speed, aec62xx_base);
- pci_write_config_byte(dev, 0x40|drive_number, drive_conf);
+ pci_write_config_byte(dev, 0x40|drive->dn, drive_conf);
pci_read_config_byte(dev, ultra_pci, &ultra);
tmp1 = ((0x00 << (4*unit)) | (ultra & ~(7 << (4*unit))));
@@ -286,10 +287,24 @@ static int aec6260_tune_chipset (ide_drive_t *drive, byte speed)
pci_write_config_byte(dev, ultra_pci, tmp2);
__restore_flags(flags); /* local CPU only */
+ if (!drive->init_speed)
+ drive->init_speed = speed;
+
err = ide_config_drive_speed(drive, speed);
+ drive->current_speed = speed;
return(err);
}
+
+static int aec62xx_tune_chipset (ide_drive_t *drive, byte speed)
+{
+ if (HWIF(drive)->pci_dev->device == PCI_DEVICE_ID_ARTOP_ATP850UF) {
+ return ((int) aec6210_tune_chipset(drive, speed));
+ } else {
+ return ((int) aec6260_tune_chipset(drive, speed));
+ }
+}
+
#ifdef CONFIG_BLK_DEV_IDEDMA
static int config_aec6210_chipset_for_dma (ide_drive_t *drive, byte ultra)
{
@@ -524,7 +539,7 @@ void __init ide_init_aec62xx (ide_hwif_t *hwif)
{
#ifdef CONFIG_AEC62XX_TUNING
hwif->tuneproc = &aec62xx_tune_drive;
-
+ hwif->speedproc = &aec62xx_tune_chipset;
#ifdef CONFIG_BLK_DEV_IDEDMA
if (hwif->dma_base)
hwif->dmaproc = &aec62xx_dmaproc;
diff --git a/drivers/ide/alim15x3.c b/drivers/ide/alim15x3.c
index c5f570674..02af0a0f8 100644
--- a/drivers/ide/alim15x3.c
+++ b/drivers/ide/alim15x3.c
@@ -333,6 +333,7 @@ static int ali15x3_tune_chipset (ide_drive_t *drive, byte speed)
err = ide_config_drive_speed(drive, speed);
+#ifdef CONFIG_BLK_DEV_IDEDMA
if (speed >= XFER_SW_DMA_0) {
unsigned long dma_base = hwif->dma_base;
@@ -353,6 +354,9 @@ static int ali15x3_tune_chipset (ide_drive_t *drive, byte speed)
pci_write_config_byte(dev, 0x4b, tmpbyte);
}
}
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+
+ drive->current_speed = speed;
return (err);
}
@@ -399,6 +403,9 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra33)
(void) ali15x3_tune_chipset(drive, speed);
+ if (!drive->init_speed)
+ drive->init_speed = speed;
+
rval = (int)( ((id->dma_ultra >> 11) & 3) ? ide_dma_on :
((id->dma_ultra >> 8) & 7) ? ide_dma_on :
((id->dma_mword >> 8) & 7) ? ide_dma_on :
@@ -629,7 +636,7 @@ unsigned int __init ata66_ali15x3 (ide_hwif_t *hwif)
* has 80-pin (from host view)
*/
pci_read_config_byte(dev, 0x4a, &tmpbyte);
- ata66 = (!(tmpbyte & ata66mask)) ? 0 : 1;
+ ata66 = (!(tmpbyte & ata66mask)) ? 1 : 0;
__restore_flags(flags);
return(ata66);
@@ -673,6 +680,7 @@ void __init ide_init_ali15x3 (ide_hwif_t *hwif)
hwif->tuneproc = &ali15x3_tune_drive;
hwif->drives[0].autotune = 1;
hwif->drives[1].autotune = 1;
+ hwif->speedproc = &ali15x3_tune_chipset;
#ifndef CONFIG_BLK_DEV_IDEDMA
hwif->autodma = 0;
return;
diff --git a/drivers/ide/amd7409.c b/drivers/ide/amd7409.c
index 14a8a83f1..d54a240d4 100644
--- a/drivers/ide/amd7409.c
+++ b/drivers/ide/amd7409.c
@@ -81,21 +81,22 @@ static int amd7409_tune_chipset (ide_drive_t *drive, byte speed)
struct pci_dev *dev = hwif->pci_dev;
int err = 0;
byte unit = (drive->select.b.unit & 0x01);
- int drive_number = ((HWIF(drive)->channel ? 2 : 0) + unit);
+#ifdef CONFIG_BLK_DEV_IDEDMA
unsigned long dma_base = hwif->dma_base;
+#endif /* CONFIG_BLK_DEV_IDEDMA */
byte drive_pci = 0x00;
byte drive_pci2 = 0x00;
byte ultra_timing = 0x00;
byte dma_pio_timing = 0x00;
byte pio_timing = 0x00;
- switch (drive_number) {
+ switch (drive->dn) {
case 0: drive_pci = 0x53; drive_pci2 = 0x4b; break;
case 1: drive_pci = 0x52; drive_pci2 = 0x4a; break;
case 2: drive_pci = 0x51; drive_pci2 = 0x49; break;
case 3: drive_pci = 0x50; drive_pci2 = 0x48; break;
default:
- return ((int) ide_dma_off_quietly);
+ return -1;
}
pci_read_config_byte(dev, drive_pci, &ultra_timing);
@@ -109,7 +110,7 @@ static int amd7409_tune_chipset (ide_drive_t *drive, byte speed)
ultra_timing &= ~0xC7;
dma_pio_timing &= ~0xFF;
- pio_timing &= ~(0x03 << drive_number);
+ pio_timing &= ~(0x03 << drive->dn);
#ifdef DEBUG
printk(":: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x ",
@@ -117,67 +118,74 @@ static int amd7409_tune_chipset (ide_drive_t *drive, byte speed)
#endif
switch(speed) {
+#ifdef CONFIG_BLK_DEV_IDEDMA
case XFER_UDMA_4:
ultra_timing |= 0x45;
dma_pio_timing |= 0x20;
- pio_timing |= (0x03 << drive_number);
+ pio_timing |= (0x03 << drive->dn);
break;
case XFER_UDMA_3:
ultra_timing |= 0x44;
dma_pio_timing |= 0x20;
- pio_timing |= (0x03 << drive_number);
+ pio_timing |= (0x03 << drive->dn);
break;
case XFER_UDMA_2:
ultra_timing |= 0x40;
dma_pio_timing |= 0x20;
- pio_timing |= (0x03 << drive_number);
+ pio_timing |= (0x03 << drive->dn);
break;
case XFER_UDMA_1:
ultra_timing |= 0x41;
dma_pio_timing |= 0x20;
- pio_timing |= (0x03 << drive_number);
+ pio_timing |= (0x03 << drive->dn);
break;
case XFER_UDMA_0:
ultra_timing |= 0x42;
dma_pio_timing |= 0x20;
- pio_timing |= (0x03 << drive_number);
+ pio_timing |= (0x03 << drive->dn);
break;
case XFER_MW_DMA_2:
dma_pio_timing |= 0x20;
- pio_timing |= (0x03 << drive_number);
+ pio_timing |= (0x03 << drive->dn);
break;
case XFER_MW_DMA_1:
dma_pio_timing |= 0x21;
- pio_timing |= (0x03 << drive_number);
+ pio_timing |= (0x03 << drive->dn);
break;
case XFER_MW_DMA_0:
dma_pio_timing |= 0x77;
- pio_timing |= (0x03 << drive_number);
+ pio_timing |= (0x03 << drive->dn);
break;
+#endif /* CONFIG_BLK_DEV_IDEDMA */
case XFER_PIO_4:
dma_pio_timing |= 0x20;
- pio_timing |= (0x03 << drive_number);
+ pio_timing |= (0x03 << drive->dn);
break;
case XFER_PIO_3:
dma_pio_timing |= 0x22;
- pio_timing |= (0x03 << drive_number);
+ pio_timing |= (0x03 << drive->dn);
break;
case XFER_PIO_2:
dma_pio_timing |= 0x42;
- pio_timing |= (0x03 << drive_number);
+ pio_timing |= (0x03 << drive->dn);
break;
case XFER_PIO_1:
dma_pio_timing |= 0x65;
- pio_timing |= (0x03 << drive_number);
+ pio_timing |= (0x03 << drive->dn);
break;
case XFER_PIO_0:
default:
dma_pio_timing |= 0xA8;
- pio_timing |= (0x03 << drive_number);
+ pio_timing |= (0x03 << drive->dn);
break;
}
+ if (!drive->init_speed)
+ drive->init_speed = speed;
+
+#ifdef CONFIG_BLK_DEV_IDEDMA
pci_write_config_byte(dev, drive_pci, ultra_timing);
+#endif /* CONFIG_BLK_DEV_IDEDMA */
pci_write_config_byte(dev, drive_pci2, dma_pio_timing);
pci_write_config_byte(dev, 0x4c, pio_timing);
@@ -186,12 +194,16 @@ static int amd7409_tune_chipset (ide_drive_t *drive, byte speed)
ultra_timing, dma_pio_timing, pio_timing);
#endif
+#ifdef CONFIG_BLK_DEV_IDEDMA
if (speed > XFER_PIO_4) {
outb(inb(dma_base+2)|(1<<(5+unit)), dma_base+2);
} else {
outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2);
}
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+
err = ide_config_drive_speed(drive, speed);
+ drive->current_speed = speed;
return (err);
}
@@ -231,6 +243,7 @@ static void config_chipset_for_pio (ide_drive_t *drive)
break;
}
(void) amd7409_tune_chipset(drive, speed);
+ drive->current_speed = speed;
}
static void amd7409_tune_drive (ide_drive_t *drive, byte pio)
@@ -403,13 +416,14 @@ unsigned int __init ata66_amd7409 (ide_hwif_t *hwif)
void __init ide_init_amd7409 (ide_hwif_t *hwif)
{
hwif->tuneproc = &amd7409_tune_drive;
+ hwif->speedproc = &amd7409_tune_chipset;
#ifndef CONFIG_BLK_DEV_IDEDMA
hwif->drives[0].autotune = 1;
hwif->drives[1].autotune = 1;
hwif->autodma = 0;
return;
-#endif /* CONFIG_BLK_DEV_IDEDMA */
+#else
if (hwif->dma_base) {
hwif->dmaproc = &amd7409_dmaproc;
@@ -419,6 +433,7 @@ void __init ide_init_amd7409 (ide_hwif_t *hwif)
hwif->drives[0].autotune = 1;
hwif->drives[1].autotune = 1;
}
+#endif /* CONFIG_BLK_DEV_IDEDMA */
}
void ide_dmacapable_amd7409 (ide_hwif_t *hwif, unsigned long dmabase)
diff --git a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c
index 8e100de3c..7e9f0c7ee 100644
--- a/drivers/ide/cmd64x.c
+++ b/drivers/ide/cmd64x.c
@@ -344,9 +344,9 @@ static void config_chipset_for_pio (ide_drive_t *drive, byte set_speed)
(void) ide_config_drive_speed(drive, speed);
}
-#ifdef CONFIG_BLK_DEV_IDEDMA
-static int tune_chipset_for_dma (ide_drive_t *drive, byte speed)
+static int cmd64x_tune_chipset (ide_drive_t *drive, byte speed)
{
+#ifdef CONFIG_BLK_DEV_IDEDMA
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev;
byte unit = (drive->select.b.unit & 0x01);
@@ -357,6 +357,8 @@ static int tune_chipset_for_dma (ide_drive_t *drive, byte speed)
u8 regU = 0;
u8 regD = 0;
+ if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0)) return 1;
+
(void) pci_read_config_byte(dev, pciD, &regD);
(void) pci_read_config_byte(dev, pciU, &regU);
regD &= ~(unit ? 0x40 : 0x20);
@@ -378,17 +380,37 @@ static int tune_chipset_for_dma (ide_drive_t *drive, byte speed)
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;
+#else
+ int err = 0;
+
+ switch(speed) {
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+ 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;
+
default:
return 1;
}
+#ifdef CONFIG_BLK_DEV_IDEDMA
(void) pci_write_config_byte(dev, pciU, regU);
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+
err = ide_config_drive_speed(drive, speed);
+
+ drive->current_speed = speed;
+
+#ifdef CONFIG_BLK_DEV_IDEDMA
regD |= (unit ? 0x40 : 0x20);
(void) pci_write_config_byte(dev, pciD, regD);
+#endif /* CONFIG_BLK_DEV_IDEDMA */
return err;
}
+#ifdef CONFIG_BLK_DEV_IDEDMA
static int config_chipset_for_dma (ide_drive_t *drive, unsigned int rev, byte ultra_66)
{
struct hd_driveid *id = drive->id;
@@ -450,12 +472,15 @@ static int config_chipset_for_dma (ide_drive_t *drive, unsigned int rev, byte ul
set_pio = 1;
}
+ if (!drive->init_speed)
+ drive->init_speed = speed;
+
config_chipset_for_pio(drive, set_pio);
if (set_pio)
return ((int) ide_dma_off_quietly);
- if (tune_chipset_for_dma(drive, speed))
+ if (cmd64x_tune_chipset(drive, speed))
return ((int) ide_dma_off);
rval = (int)( ((id->dma_ultra >> 11) & 3) ? ide_dma_on :
@@ -680,8 +705,9 @@ void __init ide_init_cmd64x (ide_hwif_t *hwif)
class_rev &= 0xff;
hwif->tuneproc = &cmd64x_tuneproc;
+ hwif->speedproc = &cmd64x_tune_chipset;
hwif->drives[0].autotune = 1;
- hwif->drives[0].autotune = 1;
+ hwif->drives[1].autotune = 1;
if (!hwif->dma_base)
return;
diff --git a/drivers/ide/hd.c b/drivers/ide/hd.c
index b64a9738c..1c6a0b286 100644
--- a/drivers/ide/hd.c
+++ b/drivers/ide/hd.c
@@ -881,3 +881,12 @@ static int revalidate_hddisk(kdev_t dev, int maxusage)
return 0;
}
+static int parse_hd_setup (char *line) {
+ int ints[6];
+
+ (void) get_options(line, ARRAY_SIZE(ints), ints);
+ hd_setup(NULL, ints);
+
+ return 0;
+}
+__setup("hd=", parse_hd_setup);
diff --git a/drivers/ide/hpt34x.c b/drivers/ide/hpt34x.c
index a68e7f740..911068f78 100644
--- a/drivers/ide/hpt34x.c
+++ b/drivers/ide/hpt34x.c
@@ -96,14 +96,13 @@ extern char *ide_xfer_verbose (byte xfer_rate);
static void hpt34x_clear_chipset (ide_drive_t *drive)
{
- int drive_number = ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
unsigned int reg1 = 0, tmp1 = 0;
unsigned int reg2 = 0, tmp2 = 0;
pci_read_config_dword(HWIF(drive)->pci_dev, 0x44, &reg1);
pci_read_config_dword(HWIF(drive)->pci_dev, 0x48, &reg2);
- tmp1 = ((0x00 << (3*drive_number)) | (reg1 & ~(7 << (3*drive_number))));
- tmp2 = (reg2 & ~(0x11 << drive_number));
+ tmp1 = ((0x00 << (3*drive->dn)) | (reg1 & ~(7 << (3*drive->dn))));
+ tmp2 = (reg2 & ~(0x11 << drive->dn));
pci_write_config_dword(HWIF(drive)->pci_dev, 0x44, tmp1);
pci_write_config_dword(HWIF(drive)->pci_dev, 0x48, tmp2);
}
@@ -112,7 +111,6 @@ static int hpt34x_tune_chipset (ide_drive_t *drive, byte speed)
{
int err;
byte hi_speed, lo_speed;
- int drive_number = ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
unsigned int reg1 = 0, tmp1 = 0;
unsigned int reg2 = 0, tmp2 = 0;
@@ -127,20 +125,24 @@ static int hpt34x_tune_chipset (ide_drive_t *drive, byte speed)
pci_read_config_dword(HWIF(drive)->pci_dev, 0x44, &reg1);
pci_read_config_dword(HWIF(drive)->pci_dev, 0x48, &reg2);
- tmp1 = ((lo_speed << (3*drive_number)) | (reg1 & ~(7 << (3*drive_number))));
- tmp2 = ((hi_speed << drive_number) | reg2);
+ tmp1 = ((lo_speed << (3*drive->dn)) | (reg1 & ~(7 << (3*drive->dn))));
+ tmp2 = ((hi_speed << drive->dn) | reg2);
err = ide_config_drive_speed(drive, speed);
pci_write_config_dword(HWIF(drive)->pci_dev, 0x44, tmp1);
pci_write_config_dword(HWIF(drive)->pci_dev, 0x48, tmp2);
+ if (!drive->init_speed)
+ drive->init_speed = speed;
+
#if HPT343_DEBUG_DRIVE_INFO
printk("%s: %s drive%d (0x%04x 0x%04x) (0x%04x 0x%04x)" \
" (0x%02x 0x%02x) 0x%04x\n",
drive->name, ide_xfer_verbose(speed),
- drive_number, reg1, tmp1, reg2, tmp2,
+ drive->dn, reg1, tmp1, reg2, tmp2,
hi_speed, lo_speed, err);
#endif /* HPT343_DEBUG_DRIVE_INFO */
+ drive->current_speed = speed;
return(err);
}
@@ -410,6 +412,7 @@ unsigned int __init pci_init_hpt34x (struct pci_dev *dev, const char *name)
void __init ide_init_hpt34x (ide_hwif_t *hwif)
{
hwif->tuneproc = &hpt34x_tune_drive;
+ hwif->speedproc = &hpt34x_tune_chipset;
#ifdef CONFIG_BLK_DEV_IDEDMA
if (hwif->dma_base) {
diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c
index fd5971ef9..28232b576 100644
--- a/drivers/ide/hpt366.c
+++ b/drivers/ide/hpt366.c
@@ -173,6 +173,14 @@ extern char *ide_xfer_verbose (byte xfer_rate);
byte hpt363_shared_irq = 0;
byte hpt363_shared_pin = 0;
+static unsigned int pci_rev_check_hpt366 (struct pci_dev *dev)
+{
+ unsigned int class_rev;
+ pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+ class_rev &= 0xff;
+ return ((int) (class_rev == 0x03) ? 1 : 0);
+}
+
static int check_in_drive_lists (ide_drive_t *drive, const char **list)
{
struct hd_driveid *id = drive->id;
@@ -212,9 +220,6 @@ static unsigned int pci_bus_clock_list (byte speed, struct chipset_bus_clock_lis
static int hpt366_tune_chipset (ide_drive_t *drive, byte speed)
{
int err;
-#if HPT366_DEBUG_DRIVE_INFO
- int drive_number = ((HWIF(drive)->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
-#endif /* HPT366_DEBUG_DRIVE_INFO */
byte regtime = (drive->select.b.unit & 0x01) ? 0x44 : 0x40;
unsigned int reg1 = 0;
unsigned int reg2 = 0;
@@ -251,11 +256,15 @@ static int hpt366_tune_chipset (ide_drive_t *drive, byte speed)
pci_write_config_dword(HWIF(drive)->pci_dev, regtime, reg2);
err = ide_config_drive_speed(drive, speed);
+ if (!drive->init_speed)
+ drive->init_speed = speed;
+
#if HPT366_DEBUG_DRIVE_INFO
printk("%s: speed=0x%02x(%s), drive%d, old=0x%08x, new=0x%08x, err=0x%04x\n",
drive->name, speed, ide_xfer_verbose(speed),
- drive_number, reg1, reg2, err);
+ drive->dn, reg1, reg2, err);
#endif /* HPT366_DEBUG_DRIVE_INFO */
+ drive->current_speed = speed;
return(err);
}
@@ -469,10 +478,12 @@ int hpt366_dmaproc (ide_dma_action_t func, ide_drive_t *drive)
case ide_dma_check:
return config_drive_xfer_rate(drive);
case ide_dma_lostirq:
+#if 0
pci_read_config_byte(HWIF(drive)->pci_dev, 0x50, &reg50h);
pci_write_config_byte(HWIF(drive)->pci_dev, 0x50, reg50h|0x03);
pci_read_config_byte(HWIF(drive)->pci_dev, 0x50, &reg50h);
/* ide_set_handler(drive, &ide_dma_intr, WAIT_CMD, NULL); */
+#endif
case ide_dma_timeout:
default:
break;
@@ -508,6 +519,8 @@ unsigned int __init pci_init_hpt366 (struct pci_dev *dev, const char *name)
if (!hpt366_proc) {
hpt366_proc = 1;
bmide_dev = dev;
+ if (pci_rev_check_hpt366(dev))
+ bmide2_dev = dev;
hpt366_display_info = &hpt366_get_info;
}
if ((hpt366_proc) && ((dev->devfn - bmide_dev->devfn) == 1)) {
@@ -533,7 +546,11 @@ unsigned int __init ata66_hpt366 (ide_hwif_t *hwif)
void __init ide_init_hpt366 (ide_hwif_t *hwif)
{
+ if (pci_rev_check_hpt366(hwif->pci_dev)) return;
+
hwif->tuneproc = &hpt366_tune_drive;
+ hwif->speedproc = &hpt366_tune_chipset;
+
#ifdef CONFIG_BLK_DEV_IDEDMA
if (hwif->dma_base) {
hwif->dmaproc = &hpt366_dmaproc;
@@ -556,6 +573,11 @@ void ide_dmacapable_hpt366 (ide_hwif_t *hwif, unsigned long dmabase)
byte dma_new = 0, dma_old = inb(dmabase+2);
unsigned long flags;
+ if (pci_rev_check_hpt366(hwif->pci_dev)) {
+ ide_setup_dma(hwif, dmabase, 8);
+ return;
+ }
+
__save_flags(flags); /* local CPU only */
__cli(); /* local CPU only */
diff --git a/drivers/ide/icside.c b/drivers/ide/icside.c
index 8ef0f9356..dcc50362f 100644
--- a/drivers/ide/icside.c
+++ b/drivers/ide/icside.c
@@ -19,6 +19,7 @@
#include <linux/errno.h>
#include <linux/hdreg.h>
#include <linux/ide.h>
+#include <linux/pci.h>
#include <linux/init.h>
#include <asm/dma.h>
@@ -219,55 +220,73 @@ static iftype_t icside_identifyif (struct expansion_card *ec)
* here, but we rely on the main IDE driver spotting that both
* interfaces use the same IRQ, which should guarantee this.
*/
-#define TABLE_SIZE 2048
+#define NR_ENTRIES 256
+#define TABLE_SIZE (NR_ENTRIES * 8)
-static int
-icside_build_dmatable(ide_drive_t *drive, int reading)
+static int ide_build_sglist(ide_hwif_t *hwif, struct request *rq)
{
- struct request *rq = HWGROUP(drive)->rq;
- struct buffer_head *bh = rq->bh;
- unsigned long addr, size;
- unsigned char *virt_addr;
- unsigned int count = 0;
- dmasg_t *sg = (dmasg_t *)HWIF(drive)->dmatable_cpu;
+ struct buffer_head *bh;
+ struct scatterlist *sg = hwif->sg_table;
+ int nents = 0;
+ if (rq->cmd == READ)
+ hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
+ else
+ hwif->sg_dma_direction = PCI_DMA_TODEVICE;
+ bh = rq->bh;
do {
- if (bh == NULL) {
- /* paging requests have (rq->bh == NULL) */
- virt_addr = rq->buffer;
- addr = virt_to_bus (virt_addr);
- size = rq->nr_sectors << 9;
- } else {
- /* group sequential buffers into one large buffer */
- virt_addr = bh->b_data;
- addr = virt_to_bus (virt_addr);
- size = bh->b_size;
- while ((bh = bh->b_reqnext) != NULL) {
- if ((addr + size) != virt_to_bus (bh->b_data))
- break;
- size += bh->b_size;
- }
- }
+ unsigned char *virt_addr = bh->b_data;
+ unsigned int size = bh->b_size;
- if (addr & 3) {
- printk("%s: misaligned DMA buffer\n", drive->name);
- return 0;
+ while ((bh = bh->b_reqnext) != NULL) {
+ if ((virt_addr + size) != (unsigned char *)bh->b_data)
+ break;
+ size += bh->b_size;
}
+ memset(&sg[nents], 0, sizeof(*sg));
+ sg[nents].address = virt_addr;
+ sg[nents].length = size;
+ nents++;
+ } while (bh != NULL);
- if (size) {
- if (reading)
- dma_cache_inv((unsigned int)virt_addr, size);
- else
- dma_cache_wback((unsigned int)virt_addr, size);
- }
+ return pci_map_sg(NULL, sg, nents, hwif->sg_dma_direction);
+}
- sg[count].address = addr;
- sg[count].length = size;
- if (++count >= (TABLE_SIZE / sizeof(dmasg_t))) {
- printk("%s: DMA table too small\n", drive->name);
+static int
+icside_build_dmatable(ide_drive_t *drive, int reading)
+{
+ dmasg_t *ide_sg = (dmasg_t *)HWIF(drive)->dmatable_cpu;
+ unsigned int count = 0;
+ int i;
+ struct scatterlist *sg;
+
+ HWIF(drive)->sg_nents = i = ide_build_sglist(HWIF(drive), HWGROUP(drive)->rq);
+
+ sg = HWIF(drive)->sg_table;
+ while (i && sg_dma_len(sg)) {
+ u32 cur_addr;
+ u32 cur_len;
+
+ cur_addr = sg_dma_address(sg);
+ cur_len = sg_dma_len(sg);
+
+ if (count >= (TABLE_SIZE / sizeof(dmasg_t))) {
+ printk("%s: DMA table too small\n",
+ drive->name);
+ pci_unmap_sg(NULL,
+ HWIF(drive)->sg_table,
+ HWIF(drive)->sg_nents,
+ HWIF(drive)->sg_dma_direction);
return 0;
+ } else {
+ ide_sg[count].address = cur_addr;
+ ide_sg[count].length = cur_len;
}
- } while (bh != NULL);
+
+ count++;
+ sg++;
+ i--;
+ }
if (!count)
printk("%s: empty DMA table?\n", drive->name);
@@ -275,6 +294,15 @@ icside_build_dmatable(ide_drive_t *drive, int reading)
return count;
}
+/* Teardown mappings after DMA has completed. */
+static void icside_destroy_dmatable(ide_drive_t *drive)
+{
+ struct scatterlist *sg = HWIF(drive)->sg_table;
+ int nents = HWIF(drive)->sg_nents;
+
+ pci_unmap_sg(NULL, sg, nents, HWIF(drive)->sg_dma_direction);
+}
+
static int
icside_config_if(ide_drive_t *drive, int xfer_mode)
{
@@ -303,6 +331,9 @@ icside_config_if(ide_drive_t *drive, int xfer_mode)
break;
}
+ if (!drive->init_speed)
+ drive->init_speed = (byte) xfer_mode;
+
if (drive->drive_data &&
ide_config_drive_speed(drive, (byte) xfer_mode) == 0)
func = ide_dma_on;
@@ -312,10 +343,18 @@ icside_config_if(ide_drive_t *drive, int xfer_mode)
printk("%s: %s selected (peak %dMB/s)\n", drive->name,
ide_xfer_verbose(xfer_mode), 2000 / drive->drive_data);
+ drive->current_speed = (byte) xfer_mode;
+
return func;
}
static int
+icside_set_speed(ide_drive_t *drive, byte speed)
+{
+ return ((int) icside_config_if(drive, (int) speed));
+}
+
+static int
icside_dma_check(ide_drive_t *drive)
{
struct hd_driveid *id = drive->id;
@@ -415,6 +454,7 @@ icside_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
case ide_dma_end:
drive->waiting_for_dma = 0;
disable_dma(hwif->hw.dma);
+ icside_destroy_dmatable(drive);
return get_dma_residue(hwif->hw.dma) != 0;
case ide_dma_test_irq:
@@ -425,8 +465,7 @@ icside_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
}
}
-static unsigned long
-icside_alloc_dmatable(void)
+static void *icside_alloc_dmatable(void)
{
static unsigned long dmatable;
static unsigned int leftover;
@@ -448,28 +487,39 @@ icside_alloc_dmatable(void)
leftover -= TABLE_SIZE;
}
- return table;
+ return (void *)table;
}
static int
icside_setup_dma(ide_hwif_t *hwif, int autodma)
{
- unsigned long table = icside_alloc_dmatable();
-
printk(" %s: SG-DMA", hwif->name);
- if (!table)
- printk(" -- ERROR, unable to allocate DMA table\n");
- else {
- hwif->dmatable_cpu = (void *)table;
- hwif->dmaproc = icside_dmaproc;
- hwif->autodma = autodma;
+ hwif->sg_table = kmalloc(sizeof(struct scatterlist) * NR_ENTRIES,
+ GFP_KERNEL);
+ if (!hwif->sg_table)
+ goto failed;
+
+ hwif->dmatable_cpu = icside_alloc_dmatable();
- printk(" capable%s\n", autodma ?
- ", auto-enable" : "");
+ if (!hwif->dmatable_cpu) {
+ kfree(hwif->sg_table);
+ hwif->sg_table = NULL;
+ goto failed;
}
- return hwif->dmatable_cpu != NULL;
+ hwif->dmaproc = &icside_dmaproc;
+ hwif->autodma = autodma;
+ hwif->speedproc = &icside_set_speed;
+
+ printk(" capable%s\n", autodma ?
+ ", auto-enable" : "");
+
+ return 1;
+
+failed:
+ printk(" -- ERROR, unable to allocate DMA table\n");
+ return 0;
}
#endif
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index 66bf35a70..4e2952018 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -33,8 +33,6 @@
#undef REALLY_SLOW_IO /* most systems can safely undef this */
-#define _IDE_DISK_C /* Tell linux/hdsmart.h it's really us */
-
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
@@ -688,13 +686,12 @@ static int set_multcount(ide_drive_t *drive, int arg)
static int set_nowerr(ide_drive_t *drive, int arg)
{
- unsigned long flags;
-
- if (ide_spin_wait_hwgroup(drive, &flags))
+ if (ide_spin_wait_hwgroup(drive))
return -EBUSY;
+
drive->nowerr = arg;
drive->bad_wstat = arg ? BAD_R_STAT : BAD_W_STAT;
- spin_unlock_irqrestore(&io_request_lock, flags);
+ spin_unlock_irq(&io_request_lock);
return 0;
}
@@ -713,7 +710,7 @@ static void idedisk_add_settings(ide_drive_t *drive)
ide_add_setting(drive, "breada_readahead", SETTING_RW, BLKRAGET, BLKRASET, TYPE_INT, 0, 255, 1, 2, &read_ahead[major], NULL);
ide_add_setting(drive, "file_readahead", SETTING_RW, BLKFRAGET, BLKFRASET, TYPE_INTA, 0, INT_MAX, 1, 1024, &max_readahead[major][minor], NULL);
ide_add_setting(drive, "max_kb_per_request", SETTING_RW, BLKSECTGET, BLKSECTSET, TYPE_INTA, 1, 255, 1, 2, &max_sectors[major][minor], NULL);
-
+ ide_add_setting(drive, "lun", SETTING_RW, -1, -1, TYPE_INT, 0, 7, 1, 1, &drive->lun, NULL);
}
/*
diff --git a/drivers/ide/ide-features.c b/drivers/ide/ide-features.c
index 371f57ad8..fcf0aab63 100644
--- a/drivers/ide/ide-features.c
+++ b/drivers/ide/ide-features.c
@@ -27,6 +27,7 @@
#include <linux/malloc.h>
#include <linux/pci.h>
#include <linux/delay.h>
+#include <linux/hdreg.h>
#include <linux/ide.h>
#include <asm/byteorder.h>
@@ -109,6 +110,46 @@ char *ide_dmafunc_verbose (ide_dma_action_t dmafunc)
}
/*
+ *
+ */
+byte ide_auto_reduce_xfer (ide_drive_t *drive)
+{
+ switch(drive->current_speed) {
+ case XFER_UDMA_7: return XFER_UDMA_6;
+ case XFER_UDMA_6: return XFER_UDMA_5;
+ case XFER_UDMA_5: return XFER_UDMA_4;
+ case XFER_UDMA_4: return XFER_UDMA_3;
+ case XFER_UDMA_3: return XFER_UDMA_2;
+ case XFER_UDMA_2: return XFER_UDMA_1;
+ case XFER_UDMA_1: return XFER_UDMA_0;
+ case XFER_UDMA_0:
+ if (drive->id->dma_mword & 0x0004) return XFER_MW_DMA_2;
+ else if (drive->id->dma_mword & 0x0002) return XFER_MW_DMA_1;
+ else if (drive->id->dma_mword & 0x0001) return XFER_MW_DMA_0;
+ else return XFER_PIO_4;
+ case XFER_MW_DMA_2: return XFER_MW_DMA_1;
+ case XFER_MW_DMA_1: return XFER_MW_DMA_0;
+ case XFER_MW_DMA_0:
+ if (drive->id->dma_1word & 0x0004) return XFER_SW_DMA_2;
+ else if (drive->id->dma_1word & 0x0002) return XFER_SW_DMA_1;
+ else if (drive->id->dma_1word & 0x0001) return XFER_SW_DMA_0;
+ else return XFER_PIO_4;
+ case XFER_SW_DMA_2: return XFER_SW_DMA_1;
+ case XFER_SW_DMA_1: return XFER_SW_DMA_0;
+ case XFER_SW_DMA_0:
+ {
+ return XFER_PIO_4;
+ }
+ case XFER_PIO_4: return XFER_PIO_3;
+ case XFER_PIO_3: return XFER_PIO_2;
+ case XFER_PIO_2: return XFER_PIO_1;
+ case XFER_PIO_1: return XFER_PIO_0;
+ case XFER_PIO_0:
+ default: return XFER_PIO_SLOW;
+ }
+}
+
+/*
* Update the
*/
int ide_driveid_update (ide_drive_t *drive)
@@ -136,8 +177,10 @@ int ide_driveid_update (ide_drive_t *drive)
ide_delay_50ms(); /* give drive a breather */
} while (IN_BYTE(IDE_ALTSTATUS_REG) & BUSY_STAT);
ide_delay_50ms(); /* wait for IRQ and DRQ_STAT */
- if (!OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT))
+ if (!OK_STAT(GET_STAT(),DRQ_STAT,BAD_R_STAT)) {
+ printk("%s: CHECK for good STATUS\n", drive->name);
return 0;
+ }
__save_flags(flags); /* local CPU only */
__cli(); /* local CPU only; some systems need this */
id = kmalloc(SECTOR_WORDS*4, GFP_ATOMIC);
@@ -146,17 +189,14 @@ int ide_driveid_update (ide_drive_t *drive)
ide__sti(); /* local CPU only */
__restore_flags(flags); /* local CPU only */
ide_fix_driveid(id);
- if (id && id->cyls) {
+ if (id) {
drive->id->dma_ultra = id->dma_ultra;
drive->id->dma_mword = id->dma_mword;
drive->id->dma_1word = id->dma_1word;
/* anything more ? */
-#ifdef DEBUG
- printk("%s: dma_ultra=%04X, dma_mword=%04X, dma_1word=%04X\n",
- drive->name, id->dma_ultra, id->dma_mword, id->dma_1word);
-#endif
kfree(id);
}
+
return 1;
}
@@ -167,7 +207,7 @@ int ide_driveid_update (ide_drive_t *drive)
* in combination with the device (usually a disk) properly detect
* and acknowledge each end of the ribbon.
*/
-int ide_ata66_check (ide_drive_t *drive, int cmd, int nsect, int feature)
+int ide_ata66_check (ide_drive_t *drive, byte cmd, byte nsect, byte feature)
{
if ((cmd == WIN_SETFEATURES) &&
(nsect > XFER_UDMA_2) &&
@@ -189,15 +229,16 @@ int ide_ata66_check (ide_drive_t *drive, int cmd, int nsect, int feature)
* 1 : Safe to update drive->id DMA registers.
* 0 : OOPs not allowed.
*/
-int set_transfer (ide_drive_t *drive, int cmd, int nsect, int feature)
+int set_transfer (ide_drive_t *drive, byte cmd, byte nsect, byte feature)
{
- struct hd_driveid *id = drive->id;
-
if ((cmd == WIN_SETFEATURES) &&
(nsect >= XFER_SW_DMA_0) &&
(feature == SETFEATURES_XFER) &&
- (id->dma_ultra || id->dma_mword || id->dma_1word))
+ (drive->id->dma_ultra ||
+ drive->id->dma_mword ||
+ drive->id->dma_1word))
return 1;
+
return 0;
}
@@ -219,6 +260,8 @@ int ide_config_drive_speed (ide_drive_t *drive, byte speed)
byte unit = (drive->select.b.unit & 0x01);
byte stat;
+ outb(inb(hwif->dma_base+2) & ~(1<<(5+unit)), hwif->dma_base+2);
+
/*
* Don't use ide_wait_cmd here - it will
* attempt to set_geometry and recalibrate,
@@ -307,6 +350,7 @@ int ide_config_drive_speed (ide_drive_t *drive, byte speed)
return error;
}
+EXPORT_SYMBOL(ide_auto_reduce_xfer);
EXPORT_SYMBOL(ide_driveid_update);
EXPORT_SYMBOL(ide_ata66_check);
EXPORT_SYMBOL(set_transfer);
diff --git a/drivers/ide/ide-pci.c b/drivers/ide/ide-pci.c
index 8d999d91c..c10ae4b51 100644
--- a/drivers/ide/ide-pci.c
+++ b/drivers/ide/ide-pci.c
@@ -30,6 +30,7 @@
#define DEVID_PIIX3 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_1})
#define DEVID_PIIX4 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB})
#define DEVID_PIIX4E ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_1})
+#define DEVID_PIIX4E2 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_1})
#define DEVID_PIIX4U ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_1})
#define DEVID_PIIX4U2 ((ide_pci_devid_t){PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82372FB_1})
#define DEVID_VIA_IDE ((ide_pci_devid_t){PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C561})
@@ -303,6 +304,7 @@ static ide_pci_device_t ide_pci_chipsets[] __initdata = {
{DEVID_PIIX3, "PIIX3", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
{DEVID_PIIX4, "PIIX4", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
{DEVID_PIIX4E, "PIIX4", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
+ {DEVID_PIIX4E2, "PIIX4", PCI_PIIX, NULL, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
{DEVID_PIIX4U, "PIIX4", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
{DEVID_PIIX4U2, "PIIX4", PCI_PIIX, ATA66_PIIX, INIT_PIIX, NULL, {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, ON_BOARD, 0 },
{DEVID_VIA_IDE, "VIA_IDE", NULL, NULL, NULL, NULL, {{0x00,0x00,0x00}, {0x00,0x00,0x00}}, ON_BOARD, 0 },
@@ -476,6 +478,7 @@ static void __init ide_setup_pci_device (struct pci_dev *dev, ide_pci_device_t *
unsigned short pcicmd = 0, tried_config = 0;
byte tmp = 0;
ide_hwif_t *hwif, *mate = NULL;
+ unsigned int class_rev;
#ifdef CONFIG_IDEDMA_AUTO
autodma = 1;
@@ -504,6 +507,11 @@ check_if_enabled:
}
if (tried_config)
printk("%s: device enabled (Linux)\n", d->name);
+
+ pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+ class_rev &= 0xff;
+ printk("%s: chipset revision %d\n", d->name, class_rev);
+
/*
* Can we trust the reported IRQ?
*/
@@ -545,7 +553,7 @@ check_if_enabled:
ide_pci_enablebit_t *e = &(d->enablebits[port]);
if (e->reg && (pci_read_config_byte(dev, e->reg, &tmp) || (tmp & e->mask) != e->val))
continue; /* port not enabled */
- if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) && (port))
+ if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT366) && (port) && (class_rev != 0x03))
return;
if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE || (dev->class & (port ? 4 : 1)) != 0) {
ctl = dev->resource[(2*port)+1].start;
@@ -656,9 +664,19 @@ static void __init hpt366_device_order_fixup (struct pci_dev *dev, ide_pci_devic
struct pci_dev *dev2 = NULL, *findev;
ide_pci_device_t *d2;
unsigned char pin1 = 0, pin2 = 0;
+ unsigned int class_rev;
if (PCI_FUNC(dev->devfn) & 1)
return;
+
+ pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
+ class_rev &= 0xff;
+
+ switch(class_rev) {
+ case 3: return;
+ default: break;
+ }
+
pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin1);
pci_for_each_dev(findev) {
if ((findev->vendor == dev->vendor) &&
diff --git a/drivers/ide/ide-pmac.c b/drivers/ide/ide-pmac.c
index 7f5226db9..45bbe77ac 100644
--- a/drivers/ide/ide-pmac.c
+++ b/drivers/ide/ide-pmac.c
@@ -7,6 +7,8 @@
*
* Copyright (C) 1998 Paul Mackerras.
*
+ * Bits from Benjamin Herrenschmidt
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
@@ -16,12 +18,6 @@
*
* Copyright (c) 1995-1998 Mark Lord
*
- * BenH: I began adding more complete timing setup code, mostly because DMA
- * won't work on new machines unless timings are setup correctly. This
- * code was mainly stolen from Cmd646 driver and should be completed to
- * include real timing calc. instead of hard coded values. The format of
- * the timing register can be found in Darwin's source code, except for
- * Keylargo ATA-4 controller.
*/
#include <linux/config.h>
#include <linux/types.h>
@@ -44,14 +40,18 @@
#endif
#include "ide_modes.h"
+extern char *ide_dmafunc_verbose(ide_dma_action_t dmafunc);
+
#undef IDE_PMAC_DEBUG
-#define IDE_SYSCLK_NS 30
+#define IDE_SYSCLK_NS 30
+#define IDE_SYSCLK_ULTRA_PS 0x1d4c /* (15 * 1000 / 2)*/
struct pmac_ide_hwif {
ide_ioreg_t regbase;
int irq;
int kind;
+ int aapl_bus_id;
struct device_node* node;
u32 timings[2];
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
@@ -90,17 +90,27 @@ static pmac_ide_timing mdma_timings[] =
static pmac_ide_timing udma_timings[] =
{
{ 0, 114 }, /* Mode 0 */
- { 0, 73 }, /* 1 */
- { 0, 54 }, /* 2 */
- { 0, 39 }, /* 3 */
- { 0, 25 } /* 4 */
+ { 0, 75 }, /* 1 */
+ { 0, 55 }, /* 2 */
+ { 100, 45 }, /* 3 */
+ { 100, 25 } /* 4 */
};
-#define MAX_DCMDS 256 /* allow up to 256 DBDMA commands per xfer */
+/* allow up to 256 DBDMA commands per xfer */
+#define MAX_DCMDS 256
+
+/* Wait 1.5s for disk to answer on IDE bus after
+ * enable operation.
+ * NOTE: There is at least one case I know of a disk that needs about 10sec
+ * before anwering on the bus. I beleive we could add a kernel command
+ * line arg to override this delay for such cases.
+ */
+#define IDE_WAKEUP_DELAY_MS 1500
static void pmac_ide_setup_dma(struct device_node *np, int ix);
static int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive);
static int pmac_ide_build_dmatable(ide_drive_t *drive, int ix, int wr);
+static int pmac_ide_tune_chipset(ide_drive_t *drive, byte speed);
static void pmac_ide_tuneproc(ide_drive_t *drive, byte pio);
static void pmac_ide_selectproc(ide_drive_t *drive);
@@ -156,14 +166,6 @@ void pmac_ide_init_hwif_ports(hw_regs_t *hw,
return;
}
- /* we check only for -EINVAL meaning that we have found a matching
- bay but with the wrong device type */
- i = check_media_bay_by_base(data_port, MB_CD);
- if (i == -EINVAL) {
- hw->io_ports[IDE_DATA_OFFSET] = 0;
- return;
- }
-
for (i = 0; i < 8; ++i)
hw->io_ports[i] = data_port + i * 0x10;
hw->io_ports[8] = data_port + 0x160;
@@ -178,6 +180,7 @@ void pmac_ide_init_hwif_ports(hw_regs_t *hw,
#ifdef CONFIG_PMAC_IDEDMA_AUTO
ide_hwifs[ix].autodma = 1;
#endif
+// ide_hwifs[ix].speedproc = &pmac_ide_tune_chipset;
}
}
@@ -214,7 +217,9 @@ pmac_ide_selectproc(ide_drive_t *drive)
/* Number of IDE_SYSCLK_NS ticks, argument is in nanoseconds */
#define SYSCLK_TICKS(t) (((t) + IDE_SYSCLK_NS - 1) / IDE_SYSCLK_NS)
+#define SYSCLK_TICKS_UDMA(t) (((t) + IDE_SYSCLK_ULTRA_PS - 1) / IDE_SYSCLK_ULTRA_PS)
+/* Calculate PIO timings */
static void
pmac_ide_tuneproc(ide_drive_t *drive, byte pio)
{
@@ -227,26 +232,31 @@ pmac_ide_tuneproc(ide_drive_t *drive, byte pio)
if (i < 0)
return;
- /* The "ata-4" IDE controller of UMA machines is a bit different.
- * We don't do anything for PIO modes until we know how to do the
- * calculation.
- */
- if (pmac_ide[i].kind == controller_kl_ata4)
- return;
-
pio = ide_get_best_pio_mode(drive, pio, 4, &d);
accessTicks = SYSCLK_TICKS(ide_pio_timings[pio].active_time);
- if (accessTicks < 4)
- accessTicks = 4;
- recTicks = SYSCLK_TICKS(d.cycle_time) - accessTicks - 4;
- if (recTicks < 1)
- recTicks = 1;
if (drive->select.all & 0x10)
timings = &pmac_ide[i].timings[1];
else
timings = &pmac_ide[i].timings[0];
- *timings = ((*timings) & 0xFFFFFF800) | accessTicks | (recTicks << 5);
+ if (pmac_ide[i].kind == controller_kl_ata4) {
+ /* The "ata-4" IDE controller of Core99 machines */
+ accessTicks = SYSCLK_TICKS_UDMA(ide_pio_timings[pio].active_time * 1000);
+ recTicks = SYSCLK_TICKS_UDMA(d.cycle_time * 1000) - accessTicks;
+
+ *timings = ((*timings) & 0x1FFFFFC00) | accessTicks | (recTicks << 5);
+ } else {
+ /* The old "ata-3" IDE controller */
+ accessTicks = SYSCLK_TICKS(ide_pio_timings[pio].active_time);
+ if (accessTicks < 4)
+ accessTicks = 4;
+ recTicks = SYSCLK_TICKS(d.cycle_time) - accessTicks - 4;
+ if (recTicks < 1)
+ recTicks = 1;
+
+ *timings = ((*timings) & 0xFFFFFF800) | accessTicks | (recTicks << 5);
+ }
+
#ifdef IDE_PMAC_DEBUG
printk("ide_pmac: Set PIO timing for mode %d, reg: 0x%08x\n",
pio, *timings);
@@ -294,7 +304,7 @@ pmac_ide_probe(void)
struct device_node *atas;
struct device_node *p, **pp, *removables, **rp;
unsigned long base;
- int irq;
+ int irq, big_delay;
ide_hwif_t *hwif;
if (_machine != _MACH_Pmac)
@@ -322,9 +332,11 @@ pmac_ide_probe(void)
}
*rp = NULL;
*pp = removables;
+ big_delay = 0;
for (i = 0, np = atas; i < MAX_HWIFS && np != NULL; np = np->next) {
struct device_node *tp;
+ int *bidp;
/*
* If this node is not under a mac-io or dbdma node,
@@ -378,6 +390,9 @@ pmac_ide_probe(void)
else
pmac_ide[i].kind = controller_ohare;
+ bidp = (int *)get_property(np, "AAPL,bus-id", NULL);
+ pmac_ide[i].aapl_bus_id = bidp ? *bidp : 0;
+
if (np->parent && np->parent->name
&& strcasecmp(np->parent->name, "media-bay") == 0) {
media_bay_set_ide_infos(np->parent,base,irq,i);
@@ -388,42 +403,41 @@ pmac_ide_probe(void)
*/
feature_set(np, FEATURE_IDE0_enable);
} else {
- /* This is necessary to enable IDE when net-booting */
- int *bidp = (int *)get_property(np, "AAPL,bus-id", NULL);
- int bid = bidp ? *bidp : 0;
- printk("pmac_ide: enabling IDE bus ID %d\n", bid);
- switch(bid) {
+ /* This is necessary to enable IDE when net-booting */
+ printk("pmac_ide: enabling IDE bus ID %d\n",
+ pmac_ide[i].aapl_bus_id);
+ switch(pmac_ide[i].aapl_bus_id) {
case 0:
feature_set(np, FEATURE_IDE0_reset);
- feature_set(np, FEATURE_IOBUS_enable);
mdelay(10);
feature_set(np, FEATURE_IDE0_enable);
mdelay(10);
feature_clear(np, FEATURE_IDE0_reset);
break;
case 1:
- feature_set(np, FEATURE_Mediabay_IDE_reset);
+ feature_set(np, FEATURE_IDE1_reset);
mdelay(10);
- feature_set(np, FEATURE_Mediabay_IDE_enable);
+ feature_set(np, FEATURE_IDE1_enable);
mdelay(10);
- feature_clear(np, FEATURE_Mediabay_IDE_reset);
+ feature_clear(np, FEATURE_IDE1_reset);
break;
case 2:
- /* This one exists only for KL, I don't know about any
- enable bit */
+ /* This one exists only for KL, I don't know
+ about any enable bit */
feature_set(np, FEATURE_IDE2_reset);
mdelay(10);
feature_clear(np, FEATURE_IDE2_reset);
break;
}
- mdelay(1000);
+ big_delay = 1;
}
hwif = &ide_hwifs[i];
pmac_ide_init_hwif_ports(&hwif->hw, base, 0, &hwif->irq);
memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->io_ports));
hwif->chipset = ide_pmac;
- hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
+ hwif->noprobe = (!hwif->io_ports[IDE_DATA_OFFSET]) ||
+ (check_media_bay_by_base(base, MB_CD) == -EINVAL);
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC
if (np->n_addrs >= 2) {
@@ -435,6 +449,8 @@ pmac_ide_probe(void)
++i;
}
pmac_ide_count = i;
+ if (big_delay)
+ mdelay(IDE_WAKEUP_DELAY_MS);
#ifdef CONFIG_PMAC_PBOOK
pmu_register_sleep_notifier(&idepmac_sleep_notifier);
@@ -642,6 +658,7 @@ out:
return result;
}
+/* Calculate MultiWord DMA timings */
static int
pmac_ide_mdma_enable(ide_drive_t *drive, int idx)
{
@@ -652,18 +669,15 @@ pmac_ide_mdma_enable(ide_drive_t *drive, int idx)
int accessTicks, recTicks;
struct hd_driveid *id = drive->id;
- /* For now, we don't know these values */
- if (pmac_ide[idx].kind == controller_kl_ata4 && feature != IDE_DMA2_ENABLE)
- return 0;
- if (pmac_ide[idx].kind != controller_kl_ata4 && feature == IDE_DMA0_ENABLE)
- return 0;
-
/* Set feature on drive */
printk("%s: Enabling MultiWord DMA %d\n", drive->name, feature & 0xf);
if (pmac_ide_do_setfeature(drive, feature)) {
printk("%s: Failed !\n", drive->name);
return 0;
}
+
+ if (!drive->init_speed)
+ drive->init_speed = feature;
/* which drive is it ? */
if (drive->select.all & 0x10)
@@ -681,7 +695,10 @@ pmac_ide_mdma_enable(ide_drive_t *drive, int idx)
/* For ata-4 controller, we don't know the calculation */
if (pmac_ide[idx].kind == controller_kl_ata4) {
- *timings = 0x00019465; /* MDMA2 */
+ accessTicks = SYSCLK_TICKS_UDMA(accessTime * 1000);
+ recTicks = SYSCLK_TICKS_UDMA(cycleTime * 1000) - accessTicks;
+ *timings = ((*timings) & 0xffe003ff) |
+ (accessTicks | (recTicks << 5)) << 10;
} else {
int halfTick = 0;
int origAccessTime = accessTime;
@@ -696,7 +713,9 @@ pmac_ide_mdma_enable(ide_drive_t *drive, int idx)
recTicks = 1;
cycleTime = (recTicks + 1 + accessTicks) * IDE_SYSCLK_NS;
- if ((accessTicks > 1) &&
+ /* KeyLargo ata-3 don't support the half-tick stuff */
+ if ((pmac_ide[idx].kind != controller_kl_ata3) &&
+ (accessTicks > 1) &&
((accessTime - IDE_SYSCLK_NS/2) >= origAccessTime) &&
((cycleTime - IDE_SYSCLK_NS) >= origCycleTime)) {
halfTick = 1;
@@ -708,21 +727,21 @@ pmac_ide_mdma_enable(ide_drive_t *drive, int idx)
#ifdef IDE_PMAC_DEBUG
printk("ide_pmac: Set MDMA timing for mode %d, reg: 0x%08x\n",
feature & 0xf, *timings);
-#endif
+#endif
+ drive->current_speed = feature;
return 1;
}
+/* Calculate Ultra DMA timings */
static int
pmac_ide_udma_enable(ide_drive_t *drive, int idx)
{
byte bits = drive->id->dma_ultra & 0x1f;
byte feature = udma_bits_to_command(bits);
- u32 timings;
+ int cycleTime, accessTime;
+ int rdyToPauseTicks, cycleTicks;
+ u32 *timings;
- /* We support only those values */
- if (feature != IDE_UDMA4_ENABLE && feature != IDE_UDMA2_ENABLE)
- return 0;
-
/* Set feature on drive */
printk("%s: Enabling Ultra DMA %d\n", drive->name, feature & 0xf);
if (pmac_ide_do_setfeature(drive, feature)) {
@@ -730,23 +749,25 @@ pmac_ide_udma_enable(ide_drive_t *drive, int idx)
return 0;
}
- /* Put this channel into UDMA mode.
- * This value is set by MacOS on the iBook for U/DMA2
- */
- switch(feature) {
- case IDE_UDMA4_ENABLE:
- timings = 0x0cd00065;
- break;
- case IDE_UDMA2_ENABLE:
- timings = 0x11100065;
- break;
- }
-
+ if (!drive->init_speed)
+ drive->init_speed = feature;
+
+ /* which drive is it ? */
if (drive->select.all & 0x10)
- pmac_ide[idx].timings[1] = timings;
+ timings = &pmac_ide[idx].timings[1];
else
- pmac_ide[idx].timings[0] = timings;
-
+ timings = &pmac_ide[idx].timings[0];
+
+ cycleTime = udma_timings[feature & 0xf].cycleTime;
+ accessTime = udma_timings[feature & 0xf].accessTime;
+
+ rdyToPauseTicks = SYSCLK_TICKS_UDMA(accessTime * 1000);
+ cycleTicks = SYSCLK_TICKS_UDMA(cycleTime * 1000);
+
+ *timings = ((*timings) & 0xe00fffff) |
+ ((cycleTicks << 1) | (rdyToPauseTicks << 5) | 1) << 20;
+
+ drive->current_speed = feature;
return 1;
}
@@ -792,6 +813,12 @@ pmac_ide_dma_onoff(ide_drive_t *drive, int enable)
return 0;
}
+static int
+pmac_ide_tune_chipset(ide_drive_t *drive, byte speed)
+{
+ return 0;
+}
+
int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
@@ -813,6 +840,7 @@ int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
pmac_ide_dma_onoff(drive, (func == ide_dma_on));
break;
case ide_dma_check:
+ printk("IDE-DMA check !\n");
if (hwif->autodma)
pmac_ide_dma_onoff(drive, 1);
break;
@@ -837,8 +865,21 @@ int pmac_ide_dmaproc(ide_dma_action_t func, ide_drive_t *drive)
return (dstat & (RUN|DEAD|ACTIVE)) != RUN;
case ide_dma_test_irq:
return (in_le32(&dma->status) & (RUN|ACTIVE)) == RUN;
+
+ /* Let's implement tose just in case someone wants them */
+ case ide_dma_bad_drive:
+ case ide_dma_good_drive:
+ return check_drive_lists(drive, (func == ide_dma_good_drive));
+ case ide_dma_verbose:
+ return report_drive_dmaing(drive);
+ case ide_dma_retune:
+ case ide_dma_lostirq:
+ case ide_dma_timeout:
+ printk("ide_pmac_dmaproc: chipset supported %s func only: %d\n", ide_dmafunc_verbose(func), func);
+ return 1;
default:
- printk(KERN_ERR "pmac_ide_dmaproc: bad func %d\n", func);
+ printk("ide_pmac_dmaproc: unsupported %s func: %d\n", ide_dmafunc_verbose(func), func);
+ return 1;
}
return 0;
}
@@ -869,8 +910,20 @@ static void idepmac_sleep_disk(int i, unsigned long base)
}
}
feature_set(np, FEATURE_IDE0_reset);
- feature_clear(np, FEATURE_IOBUS_enable);
feature_clear(np, FEATURE_IDE0_enable);
+ switch(pmac_ide[i].aapl_bus_id) {
+ case 0:
+ feature_set(np, FEATURE_IDE0_reset);
+ feature_clear(np, FEATURE_IDE0_enable);
+ break;
+ case 1:
+ feature_set(np, FEATURE_IDE1_reset);
+ feature_clear(np, FEATURE_IDE1_enable);
+ break;
+ case 2:
+ feature_set(np, FEATURE_IDE2_reset);
+ break;
+ }
pmac_ide[i].timings[0] = 0;
pmac_ide[i].timings[1] = 0;
}
@@ -881,12 +934,30 @@ static void idepmac_wake_disk(int i, unsigned long base)
int j;
/* Revive IDE disk and controller */
- feature_set(np, FEATURE_IOBUS_enable);
- mdelay(10);
- feature_set(np, FEATURE_IDE0_enable);
- mdelay(10);
- feature_clear(np, FEATURE_IDE0_reset);
- mdelay(100);
+ switch(pmac_ide[i].aapl_bus_id) {
+ case 0:
+ feature_set(np, FEATURE_IDE0_reset);
+ mdelay(10);
+ feature_set(np, FEATURE_IDE0_enable);
+ mdelay(10);
+ feature_clear(np, FEATURE_IDE0_reset);
+ break;
+ case 1:
+ feature_set(np, FEATURE_IDE1_reset);
+ mdelay(10);
+ feature_set(np, FEATURE_IDE1_enable);
+ mdelay(10);
+ feature_clear(np, FEATURE_IDE1_reset);
+ break;
+ case 2:
+ /* This one exists only for KL, I don't know
+ about any enable bit */
+ feature_set(np, FEATURE_IDE2_reset);
+ mdelay(10);
+ feature_clear(np, FEATURE_IDE2_reset);
+ break;
+ }
+ mdelay(IDE_WAKEUP_DELAY_MS);
/* Reset timings */
pmac_ide_selectproc(&ide_hwifs[i].drives[0]);
@@ -940,7 +1011,7 @@ static int idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when)
/* Disable irq during sleep */
disable_irq(pmac_ide[i].irq);
ret = check_media_bay_by_base(base, MB_CD);
- if (ret == -ENODEV)
+ if ((ret == -ENODEV) && ide_hwifs[i].drives[0].present)
/* not media bay - put the disk to sleep */
idepmac_sleep_disk(i, base);
}
@@ -953,7 +1024,7 @@ static int idepmac_notify_sleep(struct pmu_sleep_notifier *self, int when)
hwif = &ide_hwifs[i];
/* We don't handle media bay devices this way */
ret = check_media_bay_by_base(base, MB_CD);
- if (ret == -ENODEV)
+ if ((ret == -ENODEV) && ide_hwifs[i].drives[0].present)
idepmac_wake_disk(i, base);
else if (ret == 0)
idepmac_wake_bay(i, base);
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c
index 7c5130e77..83b14b1fd 100644
--- a/drivers/ide/ide-probe.c
+++ b/drivers/ide/ide-probe.c
@@ -56,6 +56,11 @@ static inline void do_identify (ide_drive_t *drive, byte cmd)
ide_input_data(drive, id, SECTOR_WORDS); /* read 512 bytes of id info */
ide__sti(); /* local CPU only */
ide_fix_driveid(id);
+
+ if (id->word156 == 0x4d42) {
+ printk("%s: drive->id->word156 == 0x%04x \n", drive->name, drive->id->word156);
+ }
+
if (!drive->forced_lun)
drive->last_lun = id->last_lun & 0x7;
#if defined (CONFIG_SCSI_EATA_DMA) || defined (CONFIG_SCSI_EATA_PIO) || defined (CONFIG_SCSI_EATA)
@@ -764,9 +769,10 @@ static void init_gendisk (ide_hwif_t *hwif)
char name[64];
ide_add_generic_settings(hwif->drives + unit);
+ hwif->drives[unit].dn = ((hwif->channel ? 2 : 0) + unit);
sprintf (name, "host%d/bus%d/target%d/lun%d",
(hwif->channel && hwif->mate) ? hwif->mate->index : hwif->index,
- hwif->channel, unit, 0);
+ hwif->channel, unit, hwif->drives[unit].lun);
hwif->drives[unit].de =
devfs_mk_dir (ide_devfs_handle, name, 0, NULL);
}
@@ -775,9 +781,9 @@ static void init_gendisk (ide_hwif_t *hwif)
static int hwif_init (ide_hwif_t *hwif)
{
- ide_drive_t *drive;
- void (*rfn)(request_queue_t *);
-
+ request_queue_t *q;
+ unsigned int unit;
+
if (!hwif->present)
return 0;
if (!hwif->irq) {
@@ -795,39 +801,7 @@ static int hwif_init (ide_hwif_t *hwif)
#endif /* CONFIG_BLK_DEV_HD */
hwif->present = 0; /* we set it back to 1 if all is ok below */
- switch (hwif->major) {
- case IDE0_MAJOR: rfn = &do_ide0_request; break;
-#if MAX_HWIFS > 1
- case IDE1_MAJOR: rfn = &do_ide1_request; break;
-#endif
-#if MAX_HWIFS > 2
- case IDE2_MAJOR: rfn = &do_ide2_request; break;
-#endif
-#if MAX_HWIFS > 3
- case IDE3_MAJOR: rfn = &do_ide3_request; break;
-#endif
-#if MAX_HWIFS > 4
- case IDE4_MAJOR: rfn = &do_ide4_request; break;
-#endif
-#if MAX_HWIFS > 5
- case IDE5_MAJOR: rfn = &do_ide5_request; break;
-#endif
-#if MAX_HWIFS > 6
- case IDE6_MAJOR: rfn = &do_ide6_request; break;
-#endif
-#if MAX_HWIFS > 7
- case IDE7_MAJOR: rfn = &do_ide7_request; break;
-#endif
-#if MAX_HWIFS > 8
- case IDE8_MAJOR: rfn = &do_ide8_request; break;
-#endif
-#if MAX_HWIFS > 9
- case IDE9_MAJOR: rfn = &do_ide9_request; break;
-#endif
- default:
- printk("%s: request_fn NOT DEFINED\n", hwif->name);
- return (hwif->present = 0);
- }
+
if (devfs_register_blkdev (hwif->major, hwif->name, ide_fops)) {
printk("%s: UNABLE TO GET MAJOR NUMBER %d\n", hwif->name, hwif->major);
return (hwif->present = 0);
@@ -860,19 +834,11 @@ static int hwif_init (ide_hwif_t *hwif)
read_ahead[hwif->major] = 8; /* (4kB) */
hwif->present = 1; /* success */
- /*
- * FIXME(eric) - This needs to be tested. I *think* that this
- * is correct. Also, I believe that there is no longer any
- * reason to have multiple functions (do_ide[0-7]_request)
- * functions - the queuedata field could be used to indicate
- * the correct hardware group - either this, or we could add
- * a new field to request_queue_t to hold this information.
- */
- drive = &hwif->drives[0];
- blk_init_queue(&drive->queue, rfn);
-
- drive = &hwif->drives[1];
- blk_init_queue(&drive->queue, rfn);
+ for (unit = 0; unit < MAX_DRIVES; ++unit) {
+ q = &hwif->drives[unit].queue;
+ q->queuedata = hwif->hwgroup;
+ blk_init_queue(q, do_ide_request);
+ }
#if (DEBUG_SPINLOCK > 0)
{
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index 039c0bfd9..cb34d3544 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -321,6 +321,7 @@ int drive_is_flashcard (ide_drive_t *drive)
|| !strncmp(id->model, "Hitachi CV", 10) /* Hitachi */
|| !strncmp(id->model, "SunDisk SDCFB", 13) /* SunDisk */
|| !strncmp(id->model, "HAGIWARA HPC", 12) /* Hagiwara */
+ || !strncmp(id->model, "LEXAR ATA_FLASH", 15) /* Lexar */
|| !strncmp(id->model, "ATA_FLASH", 9)) /* Simple Tech */
{
return 1; /* yes, it is a flash memory card */
@@ -767,6 +768,18 @@ void ide_end_drive_cmd (ide_drive_t *drive, byte stat, byte err)
args[1] = err;
args[2] = IN_BYTE(IDE_NSECTOR_REG);
}
+ } else if (rq->cmd == IDE_DRIVE_TASK) {
+ byte *args = (byte *) rq->buffer;
+ rq->errors = !OK_STAT(stat,READY_STAT,BAD_STAT);
+ if (args) {
+ args[0] = stat;
+ args[1] = err;
+ args[2] = IN_BYTE(IDE_NSECTOR_REG);
+ args[3] = IN_BYTE(IDE_SECTOR_REG);
+ args[4] = IN_BYTE(IDE_LCYL_REG);
+ args[5] = IN_BYTE(IDE_HCYL_REG);
+ args[6] = IN_BYTE(IDE_SELECT_REG);
+ }
}
spin_lock_irqsave(&io_request_lock, flags);
blkdev_dequeue_request(rq);
@@ -876,7 +889,7 @@ ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, byte stat)
if (drive == NULL || (rq = HWGROUP(drive)->rq) == NULL)
return ide_stopped;
/* retry only "normal" I/O: */
- if (rq->cmd == IDE_DRIVE_CMD) {
+ if (rq->cmd == IDE_DRIVE_CMD || rq->cmd == IDE_DRIVE_TASK) {
rq->errors = 1;
ide_end_drive_cmd(drive, stat, err);
return ide_stopped;
@@ -1036,7 +1049,20 @@ int ide_wait_stat (ide_startstop_t *startstop, ide_drive_t *drive, byte good, by
static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, struct request *rq)
{
byte *args = rq->buffer;
- if (args) {
+ if (args && rq->cmd == IDE_DRIVE_TASK) {
+
+#ifdef DEBUG
+ printk("%s: DRIVE_TASK_CMD data=x%02x cmd=0x%02x fr=0x%02x ns=0x%02x sc=0x%02x lcyl=0x%02x hcyl=0x%02x sel=0x%02x\n",
+ drive->name, args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
+#endif
+ OUT_BYTE(args[1], IDE_FEATURE_REG);
+ OUT_BYTE(args[3], IDE_SECTOR_REG);
+ OUT_BYTE(args[4], IDE_LCYL_REG);
+ OUT_BYTE(args[5], IDE_HCYL_REG);
+ OUT_BYTE(args[6], IDE_SELECT_REG);
+ ide_cmd(drive, args[0], args[2], &drive_cmd_intr);
+ return ide_started;
+ } else if (args) {
#ifdef DEBUG
printk("%s: DRIVE_CMD cmd=0x%02x sc=0x%02x fr=0x%02x xx=0x%02x\n",
drive->name, args[0], args[1], args[2], args[3]);
@@ -1116,7 +1142,7 @@ static ide_startstop_t start_request (ide_drive_t *drive)
return startstop;
}
if (!drive->special.all) {
- if (rq->cmd == IDE_DRIVE_CMD) {
+ if (rq->cmd == IDE_DRIVE_CMD || rq->cmd == IDE_DRIVE_TASK) {
return execute_drive_cmd(drive, rq);
}
if (drive->driver != NULL) {
@@ -1225,7 +1251,7 @@ repeat:
* the driver. This makes the driver much more friendlier to shared IRQs
* than previous designs, while remaining 100% (?) SMP safe and capable.
*/
-static void ide_do_request (ide_hwgroup_t *hwgroup, int masked_irq)
+static void ide_do_request(ide_hwgroup_t *hwgroup, int masked_irq)
{
ide_drive_t *drive;
ide_hwif_t *hwif;
@@ -1313,73 +1339,13 @@ request_queue_t *ide_get_queue (kdev_t dev)
return &hwif->drives[DEVICE_NR(dev) & 1].queue;
}
-void do_ide0_request (request_queue_t *q)
-{
- ide_do_request (ide_hwifs[0].hwgroup, 0);
-}
-
-#if MAX_HWIFS > 1
-void do_ide1_request (request_queue_t *q)
-{
- ide_do_request (ide_hwifs[1].hwgroup, 0);
-}
-#endif /* MAX_HWIFS > 1 */
-
-#if MAX_HWIFS > 2
-void do_ide2_request (request_queue_t *q)
-{
- ide_do_request (ide_hwifs[2].hwgroup, 0);
-}
-#endif /* MAX_HWIFS > 2 */
-
-#if MAX_HWIFS > 3
-void do_ide3_request (request_queue_t *q)
-{
- ide_do_request (ide_hwifs[3].hwgroup, 0);
-}
-#endif /* MAX_HWIFS > 3 */
-
-#if MAX_HWIFS > 4
-void do_ide4_request (request_queue_t *q)
-{
- ide_do_request (ide_hwifs[4].hwgroup, 0);
-}
-#endif /* MAX_HWIFS > 4 */
-
-#if MAX_HWIFS > 5
-void do_ide5_request (request_queue_t *q)
-{
- ide_do_request (ide_hwifs[5].hwgroup, 0);
-}
-#endif /* MAX_HWIFS > 5 */
-
-#if MAX_HWIFS > 6
-void do_ide6_request (request_queue_t *q)
-{
- ide_do_request (ide_hwifs[6].hwgroup, 0);
-}
-#endif /* MAX_HWIFS > 6 */
-
-#if MAX_HWIFS > 7
-void do_ide7_request (request_queue_t *q)
-{
- ide_do_request (ide_hwifs[7].hwgroup, 0);
-}
-#endif /* MAX_HWIFS > 7 */
-
-#if MAX_HWIFS > 8
-void do_ide8_request (request_queue_t *q)
-{
- ide_do_request (ide_hwifs[8].hwgroup, 0);
-}
-#endif /* MAX_HWIFS > 8 */
-
-#if MAX_HWIFS > 9
-void do_ide9_request (request_queue_t *q)
+/*
+ * Passes the stuff to ide_do_request
+ */
+void do_ide_request(request_queue_t *q)
{
- ide_do_request (ide_hwifs[9].hwgroup, 0);
+ ide_do_request(q->queuedata, 0);
}
-#endif /* MAX_HWIFS > 9 */
/*
* ide_timer_expiry() is our timeout function for all drive operations.
@@ -1656,16 +1622,8 @@ ide_drive_t *get_info_ptr (kdev_t i_rdev)
*/
void ide_init_drive_cmd (struct request *rq)
{
- rq->buffer = NULL;
+ memset(rq, 0, sizeof(*rq));
rq->cmd = IDE_DRIVE_CMD;
- rq->sector = 0;
- rq->nr_sectors = 0;
- rq->nr_segments = 0;
- rq->current_nr_sectors = 0;
- rq->sem = NULL;
- rq->bh = NULL;
- rq->bhtail = NULL;
- rq->q = NULL;
}
/*
@@ -2049,8 +2007,10 @@ void ide_unregister (unsigned int index)
hwgroup->hwif = HWIF(hwgroup->drive);
#ifdef CONFIG_BLK_DEV_IDEDMA
- if (hwif->dma_base)
+ if (hwif->dma_base) {
(void) ide_release_dma(hwif);
+ hwif->dma_base = 0;
+ }
#endif /* CONFIG_BLK_DEV_IDEDMA */
/*
@@ -2083,6 +2043,7 @@ void ide_unregister (unsigned int index)
init_hwif_data (index); /* restore hwif data to pristine status */
hwif->hwgroup = old_hwif.hwgroup;
hwif->tuneproc = old_hwif.tuneproc;
+ hwif->speedproc = old_hwif.speedproc;
hwif->selectproc = old_hwif.selectproc;
hwif->resetproc = old_hwif.resetproc;
hwif->dmaproc = old_hwif.dmaproc;
@@ -2103,7 +2064,7 @@ void ide_unregister (unsigned int index)
hwif->pci_devid = old_hwif.pci_devid;
#endif /* CONFIG_BLK_DEV_IDEPCI */
hwif->straight8 = old_hwif.straight8;
-
+ hwif->hwif_data = old_hwif.hwif_data;
abort:
restore_flags(flags); /* all CPUs */
}
@@ -2304,24 +2265,24 @@ int ide_read_setting (ide_drive_t *drive, ide_settings_t *setting)
return val;
}
-int ide_spin_wait_hwgroup (ide_drive_t *drive, unsigned long *flags)
+int ide_spin_wait_hwgroup (ide_drive_t *drive)
{
ide_hwgroup_t *hwgroup = HWGROUP(drive);
unsigned long timeout = jiffies + (3 * HZ);
- spin_lock_irqsave(&io_request_lock, *flags);
+ spin_lock_irq(&io_request_lock);
while (hwgroup->busy) {
- unsigned long lflags;
- spin_unlock_irqrestore(&io_request_lock, *flags);
- __save_flags(lflags); /* local CPU only */
+ unsigned long flags;
+ spin_unlock_irq(&io_request_lock);
+ __save_flags(flags); /* local CPU only */
__sti(); /* local CPU only; needed for jiffies */
if (0 < (signed long)(jiffies - timeout)) {
- __restore_flags(lflags); /* local CPU only */
+ __restore_flags(flags);
printk("%s: channel busy\n", drive->name);
return -EBUSY;
}
- __restore_flags(lflags); /* local CPU only */
- spin_lock_irqsave(&io_request_lock, *flags);
+ __restore_flags(flags); /* local CPU only */
+ spin_lock_irq(&io_request_lock);
}
return 0;
}
@@ -2333,7 +2294,6 @@ int ide_spin_wait_hwgroup (ide_drive_t *drive, unsigned long *flags)
*/
int ide_write_setting (ide_drive_t *drive, ide_settings_t *setting, int val)
{
- unsigned long flags;
int i;
u32 *p;
@@ -2345,7 +2305,7 @@ int ide_write_setting (ide_drive_t *drive, ide_settings_t *setting, int val)
return -EINVAL;
if (setting->set)
return setting->set(drive, val);
- if (ide_spin_wait_hwgroup(drive, &flags))
+ if (ide_spin_wait_hwgroup(drive))
return -EBUSY;
switch (setting->data_type) {
case TYPE_BYTE:
@@ -2363,7 +2323,7 @@ int ide_write_setting (ide_drive_t *drive, ide_settings_t *setting, int val)
*p = val;
break;
}
- spin_unlock_irqrestore(&io_request_lock, flags);
+ spin_unlock_irq(&io_request_lock);
return 0;
}
@@ -2416,6 +2376,9 @@ void ide_add_generic_settings (ide_drive_t *drive)
ide_add_setting(drive, "unmaskirq", drive->no_unmask ? SETTING_READ : SETTING_RW, HDIO_GET_UNMASKINTR, HDIO_SET_UNMASKINTR, TYPE_BYTE, 0, 1, 1, 1, &drive->unmask, NULL);
ide_add_setting(drive, "using_dma", SETTING_RW, HDIO_GET_DMA, HDIO_SET_DMA, TYPE_BYTE, 0, 1, 1, 1, &drive->using_dma, set_using_dma);
ide_add_setting(drive, "ide_scsi", SETTING_RW, -1, -1, TYPE_BYTE, 0, 1, 1, 1, &drive->scsi, NULL);
+ ide_add_setting(drive, "init_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 69, 1, 1, &drive->init_speed, NULL);
+ ide_add_setting(drive, "current_speed", SETTING_RW, -1, -1, TYPE_BYTE, 0, 69, 1, 1, &drive->current_speed, NULL);
+ ide_add_setting(drive, "number", SETTING_RW, -1, -1, TYPE_BYTE, 0, 3, 1, 1, &drive->dn, NULL);
}
int ide_wait_cmd (ide_drive_t *drive, int cmd, int nsect, int feature, int sectors, byte *buf)
@@ -2435,6 +2398,16 @@ int ide_wait_cmd (ide_drive_t *drive, int cmd, int nsect, int feature, int secto
return ide_do_drive_cmd(drive, &rq, ide_wait);
}
+int ide_wait_cmd_task (ide_drive_t *drive, byte *buf)
+{
+ struct request rq;
+
+ ide_init_drive_cmd(&rq);
+ rq.cmd = IDE_DRIVE_TASK;
+ rq.buffer = buf;
+ return ide_do_drive_cmd(drive, &rq, ide_wait);
+}
+
/*
* Delay for *at least* 50ms. As we don't know how much time is left
* until the next tick occurs, we wait an extra tick to be safe.
@@ -2551,6 +2524,7 @@ static int ide_ioctl (struct inode *inode, struct file *file,
case HDIO_DRIVE_CMD:
{
byte args[4], *argbuf = args;
+ byte xfer_rate = 0;
int argsize = 4;
if (!capable(CAP_SYS_ADMIN)) return -EACCES;
if (NULL == (void *) arg)
@@ -2564,18 +2538,22 @@ static int ide_ioctl (struct inode *inode, struct file *file,
return -ENOMEM;
memcpy(argbuf, args, 4);
}
- if (ide_ata66_check(drive, args[0], args[1], args[2]))
- goto abort;
+
+ if (set_transfer(drive, args[0], args[1], args[2])) {
+ xfer_rate = args[1];
+ if (ide_ata66_check(drive, args[0], args[1], args[2]))
+ goto abort;
+ }
err = ide_wait_cmd(drive, args[0], args[1], args[2], args[3], argbuf);
- if (!err && set_transfer(drive, args[0], args[1], args[2])) {
-#if 0
+ if (!err && xfer_rate) {
/* active-retuning-calls future */
- if (HWIF(drive)->tune2proc)
- HWIF(drive)->tune2proc(drive, args[1]);
-#endif
+ if ((HWIF(drive)->speedproc) != NULL)
+ HWIF(drive)->speedproc(drive, xfer_rate);
ide_driveid_update(drive);
+ } else {
+ printk("%s: \n", drive->name);
}
abort:
if (copy_to_user((void *)arg, argbuf, argsize))
@@ -2584,6 +2562,18 @@ static int ide_ioctl (struct inode *inode, struct file *file,
kfree(argbuf);
return err;
}
+ case HDIO_DRIVE_TASK:
+ {
+ byte args[7], *argbuf = args;
+ int argsize = 7;
+ if (!capable(CAP_SYS_ADMIN)) return -EACCES;
+ if (copy_from_user(args, (void *)arg, 7))
+ return -EFAULT;
+ err = ide_wait_cmd_task(drive, argbuf);
+ if (copy_to_user((void *)arg, argbuf, argsize))
+ err = -EFAULT;
+ return err;
+ }
case HDIO_SCAN_HWIF:
{
@@ -3512,37 +3502,9 @@ EXPORT_SYMBOL(ide_timer_expiry);
EXPORT_SYMBOL(ide_intr);
EXPORT_SYMBOL(ide_fops);
EXPORT_SYMBOL(ide_get_queue);
-EXPORT_SYMBOL(do_ide0_request);
EXPORT_SYMBOL(ide_add_generic_settings);
EXPORT_SYMBOL(ide_devfs_handle);
-#if MAX_HWIFS > 1
-EXPORT_SYMBOL(do_ide1_request);
-#endif /* MAX_HWIFS > 1 */
-#if MAX_HWIFS > 2
-EXPORT_SYMBOL(do_ide2_request);
-#endif /* MAX_HWIFS > 2 */
-#if MAX_HWIFS > 3
-EXPORT_SYMBOL(do_ide3_request);
-#endif /* MAX_HWIFS > 3 */
-#if MAX_HWIFS > 4
-EXPORT_SYMBOL(do_ide4_request);
-#endif /* MAX_HWIFS > 4 */
-#if MAX_HWIFS > 5
-EXPORT_SYMBOL(do_ide5_request);
-#endif /* MAX_HWIFS > 5 */
-#if MAX_HWIFS > 6
-EXPORT_SYMBOL(do_ide6_request);
-#endif /* MAX_HWIFS > 6 */
-#if MAX_HWIFS > 7
-EXPORT_SYMBOL(do_ide7_request);
-#endif /* MAX_HWIFS > 7 */
-#if MAX_HWIFS > 8
-EXPORT_SYMBOL(do_ide8_request);
-#endif /* MAX_HWIFS > 8 */
-#if MAX_HWIFS > 9
-EXPORT_SYMBOL(do_ide9_request);
-#endif /* MAX_HWIFS > 9 */
-
+EXPORT_SYMBOL(do_ide_request);
/*
* Driver module
*/
@@ -3567,6 +3529,7 @@ EXPORT_SYMBOL(ide_end_request);
EXPORT_SYMBOL(ide_revalidate_disk);
EXPORT_SYMBOL(ide_cmd);
EXPORT_SYMBOL(ide_wait_cmd);
+EXPORT_SYMBOL(ide_wait_cmd_task);
EXPORT_SYMBOL(ide_delay_50ms);
EXPORT_SYMBOL(ide_stall_queue);
#ifdef CONFIG_PROC_FS
@@ -3652,8 +3615,13 @@ void cleanup_module (void)
{
int index;
- for (index = 0; index < MAX_HWIFS; ++index)
+ for (index = 0; index < MAX_HWIFS; ++index) {
ide_unregister(index);
+#ifdef CONFIG_BLK_DEV_IDEDMA
+ if (ide_hwifs[index].dma_base)
+ (void) ide_release_dma(&ide_hwifs[index]);
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+ }
#ifdef CONFIG_PROC_FS
proc_ide_destroy();
diff --git a/drivers/ide/pdc202xx.c b/drivers/ide/pdc202xx.c
index b93c6ad1b..f16d33921 100644
--- a/drivers/ide/pdc202xx.c
+++ b/drivers/ide/pdc202xx.c
@@ -262,59 +262,99 @@ static void decode_registers (byte registers, byte value)
#endif /* PDC202XX_DECODE_REGISTER_INFO */
-/* 0 1 2 3 4 5 6 7 8
- * 960, 480, 390, 300, 240, 180, 120, 90, 60
- * 180, 150, 120, 90, 60
- * DMA_Speed
- * 180, 120, 90, 90, 90, 60, 30
- * 11, 5, 4, 3, 2, 1, 0
- */
-static int config_chipset_for_pio (ide_drive_t *drive, byte pio)
+static int pdc202xx_tune_chipset (ide_drive_t *drive, byte speed)
{
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev;
- byte drive_pci, speed;
- byte AP, BP, TA, TB;
- int drive_number = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
- int err;
+ unsigned int drive_conf;
+ int err;
+ byte drive_pci, AP, BP, CP, DP;
+ byte TA = 0, TB = 0, TC = 0;
- switch (drive_number) {
+ switch (drive->dn) {
case 0: drive_pci = 0x60; break;
case 1: drive_pci = 0x64; break;
case 2: drive_pci = 0x68; break;
case 3: drive_pci = 0x6c; break;
- default: return 1;
+ default: return -1;
}
+ if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0)) return -1;
+
+ pci_read_config_dword(dev, drive_pci, &drive_conf);
pci_read_config_byte(dev, (drive_pci), &AP);
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);
+#ifdef CONFIG_BLK_DEV_IDEDMA
+ if (speed >= XFER_SW_DMA_0) {
+ 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);
+ }
+ } else {
+#else
+ {
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+ 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);
- 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);
+ pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
- /* clear PIO modes of lower 421 bits of B Register */
- pci_write_config_byte(dev, (drive_pci)|0x01, BP & ~0x07);
- pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
+ pci_read_config_byte(dev, (drive_pci), &AP);
+ pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
+ }
+ }
- pci_read_config_byte(dev, (drive_pci), &AP);
- pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
+ pci_read_config_byte(dev, (drive_pci), &AP);
+ pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
+ pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
+
+ switch(speed) {
+#ifdef CONFIG_BLK_DEV_IDEDMA
+ case XFER_UDMA_4: TB = 0x20; TC = 0x01; break; /* speed 8 == UDMA mode 4 */
+ case XFER_UDMA_3: TB = 0x40; TC = 0x02; break; /* speed 7 == UDMA mode 3 */
+ case XFER_UDMA_2: TB = 0x20; TC = 0x01; break; /* speed 6 == UDMA mode 2 */
+ case XFER_UDMA_1: TB = 0x40; TC = 0x02; break; /* speed 5 == UDMA mode 1 */
+ case XFER_UDMA_0: TB = 0x60; TC = 0x03; break; /* speed 4 == UDMA mode 0 */
+ case XFER_MW_DMA_2: TB = 0x60; TC = 0x03; break; /* speed 4 == MDMA mode 2 */
+ case XFER_MW_DMA_1: TB = 0x60; TC = 0x04; break; /* speed 3 == MDMA mode 1 */
+ case XFER_MW_DMA_0: TB = 0x60; TC = 0x05; break; /* speed 2 == MDMA mode 0 */
+ case XFER_SW_DMA_2: TB = 0x60; TC = 0x05; break; /* speed 0 == SDMA mode 2 */
+ case XFER_SW_DMA_1: TB = 0x80; TC = 0x06; break; /* speed 1 == SDMA mode 1 */
+ case XFER_SW_DMA_0: TB = 0xC0; TC = 0x0B; break; /* speed 0 == SDMA mode 0 */
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+ case XFER_PIO_4: TA = 0x01; TB = 0x04; break;
+ case XFER_PIO_3: TA = 0x02; TB = 0x06; break;
+ case XFER_PIO_2: TA = 0x03; TB = 0x08; break;
+ case XFER_PIO_1: TA = 0x05; TB = 0x0C; break;
+ case XFER_PIO_0:
+ default: TA = 0x09; TB = 0x13; break;
}
- pio = (pio == 5) ? 4 : pio;
- switch (ide_get_best_pio_mode(drive, 255, pio, NULL)) {
- case 4:speed = XFER_PIO_4; TA=0x01; TB=0x04; break;
- case 3:speed = XFER_PIO_3; TA=0x02; TB=0x06; break;
- case 2:speed = XFER_PIO_2; TA=0x03; TB=0x08; break;
- case 1:speed = XFER_PIO_1; TA=0x05; TB=0x0C; break;
- case 0:
- default:speed = XFER_PIO_0; TA=0x09; TB=0x13; break;
+#ifdef CONFIG_BLK_DEV_IDEDMA
+ if (speed >= XFER_SW_DMA_0) {
+ pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB);
+ pci_write_config_byte(dev, (drive_pci)|0x02, CP|TC);
+ } else {
+#else
+ {
+#endif /* CONFIG_BLK_DEV_IDEDMA */
+ pci_write_config_byte(dev, (drive_pci), AP|TA);
+ pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB);
}
- pci_write_config_byte(dev, (drive_pci), AP|TA);
- pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB);
#if PDC202XX_DECODE_REGISTER_INFO
pci_read_config_byte(dev, (drive_pci), &AP);
@@ -333,13 +373,30 @@ static int config_chipset_for_pio (ide_drive_t *drive, byte pio)
#if PDC202XX_DEBUG_DRIVE_INFO
printk("%s: %s drive%d 0x%08x ",
drive->name, ide_xfer_verbose(speed),
- drive_number, drive_conf);
+ drive->dn, drive_conf);
pci_read_config_dword(dev, drive_pci, &drive_conf);
printk("0x%08x\n", drive_conf);
#endif /* PDC202XX_DEBUG_DRIVE_INFO */
return err;
}
+/* 0 1 2 3 4 5 6 7 8
+ * 960, 480, 390, 300, 240, 180, 120, 90, 60
+ * 180, 150, 120, 90, 60
+ * DMA_Speed
+ * 180, 120, 90, 90, 90, 60, 30
+ * 11, 5, 4, 3, 2, 1, 0
+ */
+static int config_chipset_for_pio (ide_drive_t *drive, byte pio)
+{
+ byte speed = 0x00;
+
+ pio = (pio == 5) ? 4 : pio;
+ speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, pio, NULL);
+
+ return ((int) pdc202xx_tune_chipset(drive, speed));
+}
+
static void pdc202xx_tune_drive (ide_drive_t *drive, byte pio)
{
(void) config_chipset_for_pio(drive, pio);
@@ -352,15 +409,15 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev;
unsigned long high_16 = dev->resource[4].start & PCI_BASE_ADDRESS_IO_MASK;
+ unsigned long dma_base = hwif->dma_base;
+ byte unit = (drive->select.b.unit & 0x01);
- int err;
unsigned int drive_conf;
byte drive_pci;
byte test1, test2, speed = -1;
- byte AP, BP, CP, DP, TB, TC;
+ byte AP;
unsigned short EP;
byte CLKSPD = IN_BYTE(high_16 + 0x11);
- int drive_number = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
byte udma_66 = ((id->hw_config & 0x2000) && (hwif->udma_four)) ? 1 : 0;
byte udma_33 = ultra ? (inb(high_16 + 0x001f) & 1) : 0;
@@ -397,9 +454,9 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
* check to make sure drive on same channel
* is u66 capable
*/
- if (hwif->drives[!(drive_number%2)].id) {
- if ((hwif->drives[!(drive_number%2)].id->dma_ultra & 0x0010) ||
- (hwif->drives[!(drive_number%2)].id->dma_ultra & 0x0008)) {
+ if (hwif->drives[!(drive->dn%2)].id) {
+ if ((hwif->drives[!(drive->dn%2)].id->dma_ultra & 0x0010) ||
+ (hwif->drives[!(drive->dn%2)].id->dma_ultra & 0x0008)) {
OUT_BYTE(CLKSPD | mask, (high_16 + 0x11));
} else {
OUT_BYTE(CLKSPD & ~mask, (high_16 + 0x11));
@@ -410,7 +467,7 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
}
}
- switch(drive_number) {
+ switch(drive->dn) {
case 0: drive_pci = 0x60;
pci_read_config_dword(dev, drive_pci, &drive_conf);
if ((drive_conf != 0x004ff304) && (drive_conf != 0x004ff3c4))
@@ -451,101 +508,34 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
chipset_is_set:
- if (drive->media != ide_disk)
- return ide_dma_off_quietly;
+ if (drive->media != ide_disk) return ide_dma_off_quietly;
pci_read_config_byte(dev, (drive_pci), &AP);
- 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 (id->capability & 4) { /* IORDY_EN */
+ 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);
- pci_read_config_byte(dev, (drive_pci), &AP);
- }
-
- 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)|0x01, &BP);
- pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
+ if (drive->media == ide_disk) /* PREFETCH_EN */
+ pci_write_config_byte(dev, (drive_pci), AP|PREFETCH_EN);
- if ((id->dma_ultra & 0x0010) && (udma_66) && (udma_33)) {
- /* speed 8 == UDMA mode 4 == speed 6 plus cable */
- speed = XFER_UDMA_4; TB = 0x20; TC = 0x01;
- } else if ((id->dma_ultra & 0x0008) && (udma_66) && (udma_33)) {
- /* speed 7 == UDMA mode 3 == speed 5 plus cable */
- speed = XFER_UDMA_3; TB = 0x40; TC = 0x02;
- } else if ((id->dma_ultra & 0x0004) && (udma_33)) {
- /* speed 6 == UDMA mode 2 */
- speed = XFER_UDMA_2; TB = 0x20; TC = 0x01;
- } else if ((id->dma_ultra & 0x0002) && (udma_33)) {
- /* speed 5 == UDMA mode 1 */
- speed = XFER_UDMA_1; TB = 0x40; TC = 0x02;
- } else if ((id->dma_ultra & 0x0001) && (udma_33)) {
- /* speed 4 == UDMA mode 0 */
- speed = XFER_UDMA_0; TB = 0x60; TC = 0x03;
- } else if (id->dma_mword & 0x0004) {
- /* speed 4 == DMA mode 2 multi-word */
- speed = XFER_MW_DMA_2; TB = 0x60; TC = 0x03;
- } else if (id->dma_mword & 0x0002) {
- /* speed 3 == DMA mode 1 multi-word */
- speed = XFER_MW_DMA_1; TB = 0x60; TC = 0x04;
- } else if (id->dma_mword & 0x0001) {
- /* speed 2 == DMA mode 0 multi-word */
- speed = XFER_MW_DMA_0; TB = 0x60; TC = 0x05;
- } else if (id->dma_1word & 0x0004) {
- /* speed 2 == DMA mode 2 single-word */
- speed = XFER_SW_DMA_2; TB = 0x60; TC = 0x05;
- } else if (id->dma_1word & 0x0002) {
- /* speed 1 == DMA mode 1 single-word */
- speed = XFER_SW_DMA_1; TB = 0x80; TC = 0x06;
- } else if (id->dma_1word & 0x0001) {
- /* speed 0 == DMA mode 0 single-word */
- speed = XFER_SW_DMA_0; TB = 0xC0; TC = 0x0B;
- } else {
+ if ((id->dma_ultra & 0x0010) && (udma_66) && (udma_33)) speed = XFER_UDMA_4;
+ else if ((id->dma_ultra & 0x0008) && (udma_66) && (udma_33)) speed = XFER_UDMA_3;
+ else if ((id->dma_ultra & 0x0004) && (udma_33)) speed = XFER_UDMA_2;
+ else if ((id->dma_ultra & 0x0002) && (udma_33)) speed = XFER_UDMA_1;
+ else if ((id->dma_ultra & 0x0001) && (udma_33)) speed = XFER_UDMA_0;
+ else if (id->dma_mword & 0x0004) speed = XFER_MW_DMA_2;
+ else if (id->dma_mword & 0x0002) speed = XFER_MW_DMA_1;
+ else if (id->dma_mword & 0x0001) speed = XFER_MW_DMA_0;
+ else if (id->dma_1word & 0x0004) speed = XFER_SW_DMA_2;
+ else if (id->dma_1word & 0x0002) speed = XFER_SW_DMA_1;
+ else if (id->dma_1word & 0x0001) speed = XFER_SW_DMA_0;
+ else {
/* restore original pci-config space */
pci_write_config_dword(dev, drive_pci, drive_conf);
return ide_dma_off_quietly;
}
- pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB);
- pci_write_config_byte(dev, (drive_pci)|0x02, CP|TC);
-
-#if PDC202XX_DECODE_REGISTER_INFO
- pci_read_config_byte(dev, (drive_pci), &AP);
- pci_read_config_byte(dev, (drive_pci)|0x01, &BP);
- pci_read_config_byte(dev, (drive_pci)|0x02, &CP);
-
- decode_registers(REG_A, AP);
- decode_registers(REG_B, BP);
- decode_registers(REG_C, CP);
- decode_registers(REG_D, DP);
-#endif /* PDC202XX_DECODE_REGISTER_INFO */
-
- err = ide_config_drive_speed(drive, speed);
-
-#if PDC202XX_DEBUG_DRIVE_INFO
- printk("%s: %s drive%d 0x%08x ",
- drive->name, ide_xfer_verbose(speed),
- drive_number, drive_conf);
- pci_read_config_dword(dev, drive_pci, &drive_conf);
- printk("0x%08x\n", drive_conf);
-#endif /* PDC202XX_DEBUG_DRIVE_INFO */
+ outb(inb(dma_base+2) & ~(1<<(5+unit)), dma_base+2);
+ (void) pdc202xx_tune_chipset(drive, speed);
return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_on :
((id->dma_ultra >> 8) & 7) ? ide_dma_on :
@@ -716,6 +706,7 @@ unsigned int __init ata66_pdc202xx (ide_hwif_t *hwif)
void __init ide_init_pdc202xx (ide_hwif_t *hwif)
{
hwif->tuneproc = &pdc202xx_tune_drive;
+ hwif->speedproc = &pdc202xx_tune_chipset;
#ifdef CONFIG_BLK_DEV_IDEDMA
if (hwif->dma_base) {
diff --git a/drivers/ide/piix.c b/drivers/ide/piix.c
index fafd0533f..90af168c3 100644
--- a/drivers/ide/piix.c
+++ b/drivers/ide/piix.c
@@ -112,6 +112,7 @@ static int piix_get_info (char *buffer, char **addr, off_t offset, int count)
p += sprintf(p, "\n Intel PIIX4 Ultra 66 Chipset.\n");
break;
case PCI_DEVICE_ID_INTEL_82801AB_1:
+ case PCI_DEVICE_ID_INTEL_82443MX_1:
case PCI_DEVICE_ID_INTEL_82371AB:
p += sprintf(p, "\n Intel PIIX4 Ultra 33 Chipset.\n");
break;
@@ -258,28 +259,18 @@ static void piix_tune_drive (ide_drive_t *drive, byte pio)
}
#if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_PIIX_TUNING)
-static int piix_config_drive_for_dma (ide_drive_t *drive)
+static int piix_tune_chipset (ide_drive_t *drive, byte speed)
{
- struct hd_driveid *id = drive->id;
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev;
-
- int sitre;
- short reg4042, reg44, reg48, reg4a, reg54;
- byte speed;
-
byte maslave = hwif->channel ? 0x42 : 0x40;
- byte udma_66 = ((id->hw_config & 0x2000) && (hwif->udma_four)) ? 1 : 0;
- int ultra66 = ((dev->device == PCI_DEVICE_ID_INTEL_82801AA_1) ||
- (dev->device == PCI_DEVICE_ID_INTEL_82372FB_1)) ? 1 : 0;
- int ultra = ((ultra66) ||
- (dev->device == PCI_DEVICE_ID_INTEL_82371AB) ||
- (dev->device == PCI_DEVICE_ID_INTEL_82801AB_1)) ? 1 : 0;
- int drive_number = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
- int a_speed = 2 << (drive_number * 4);
- int u_flag = 1 << drive_number;
- int v_flag = 0x10 << drive_number;
+ int a_speed = 2 << (drive->dn * 4);
+ int u_flag = 1 << drive->dn;
+ int v_flag = 0x10 << drive->dn;
int u_speed = 0;
+ int err = 0;
+ int sitre;
+ short reg4042, reg44, reg48, reg4a, reg54;
pci_read_config_word(dev, maslave, &reg4042);
sitre = (reg4042 & 0x4000) ? 1 : 0;
@@ -288,29 +279,16 @@ static int piix_config_drive_for_dma (ide_drive_t *drive)
pci_read_config_word(dev, 0x4a, &reg4a);
pci_read_config_word(dev, 0x54, &reg54);
- if ((id->dma_ultra & 0x0010) && (ultra)) {
- u_speed = 2 << (drive_number * 4);
- speed = ((udma_66) && (ultra66)) ? XFER_UDMA_4 : XFER_UDMA_2;
- } else if ((id->dma_ultra & 0x0008) && (ultra)) {
- u_speed = 1 << (drive_number * 4);
- speed = ((udma_66) && (ultra66)) ? XFER_UDMA_3 : XFER_UDMA_1;
- } else if ((id->dma_ultra & 0x0004) && (ultra)) {
- u_speed = 2 << (drive_number * 4);
- speed = XFER_UDMA_2;
- } else if ((id->dma_ultra & 0x0002) && (ultra)) {
- u_speed = 1 << (drive_number * 4);
- speed = XFER_UDMA_1;
- } else if ((id->dma_ultra & 0x0001) && (ultra)) {
- u_speed = 0 << (drive_number * 4);
- speed = XFER_UDMA_0;
- } else if (id->dma_mword & 0x0004) {
- speed = XFER_MW_DMA_2;
- } else if (id->dma_mword & 0x0002) {
- speed = XFER_MW_DMA_1;
- } else if (id->dma_1word & 0x0004) {
- speed = XFER_SW_DMA_2;
- } else {
- speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL);
+ switch(speed) {
+ case XFER_UDMA_4:
+ case XFER_UDMA_2: u_speed = 2 << (drive->dn * 4); break;
+ case XFER_UDMA_3:
+ case XFER_UDMA_1: u_speed = 1 << (drive->dn * 4); break;
+ case XFER_UDMA_0: u_speed = 0 << (drive->dn * 4); break;
+ case XFER_MW_DMA_2:
+ case XFER_MW_DMA_1:
+ case XFER_SW_DMA_2: break;
+ default: return -1;
}
if (speed >= XFER_UDMA_0) {
@@ -328,7 +306,6 @@ static int piix_config_drive_for_dma (ide_drive_t *drive)
pci_write_config_word(dev, 0x54, reg54 & ~v_flag);
}
}
-
if (speed < XFER_UDMA_0) {
if (reg48 & u_flag)
pci_write_config_word(dev, 0x48, reg48 & ~u_flag);
@@ -340,11 +317,52 @@ static int piix_config_drive_for_dma (ide_drive_t *drive)
piix_tune_drive(drive, piix_dma_2_pio(speed));
- (void) ide_config_drive_speed(drive, speed);
-
#if PIIX_DEBUG_DRIVE_INFO
- printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive_number);
+ printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive->dn);
#endif /* PIIX_DEBUG_DRIVE_INFO */
+ if (!drive->init_speed)
+ drive->init_speed = speed;
+ err = ide_config_drive_speed(drive, speed);
+ drive->current_speed = speed;
+ return err;
+}
+
+static int piix_config_drive_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;
+ byte speed;
+
+ byte udma_66 = ((id->hw_config & 0x2000) && (hwif->udma_four)) ? 1 : 0;
+ int ultra66 = ((dev->device == PCI_DEVICE_ID_INTEL_82801AA_1) ||
+ (dev->device == PCI_DEVICE_ID_INTEL_82372FB_1)) ? 1 : 0;
+ int ultra = ((ultra66) ||
+ (dev->device == PCI_DEVICE_ID_INTEL_82371AB) ||
+ (dev->device == PCI_DEVICE_ID_INTEL_82443MX_1) ||
+ (dev->device == PCI_DEVICE_ID_INTEL_82801AB_1)) ? 1 : 0;
+
+ if ((id->dma_ultra & 0x0010) && (ultra)) {
+ speed = ((udma_66) && (ultra66)) ? XFER_UDMA_4 : XFER_UDMA_2;
+ } else if ((id->dma_ultra & 0x0008) && (ultra)) {
+ speed = ((udma_66) && (ultra66)) ? XFER_UDMA_3 : XFER_UDMA_1;
+ } else if ((id->dma_ultra & 0x0004) && (ultra)) {
+ speed = XFER_UDMA_2;
+ } else if ((id->dma_ultra & 0x0002) && (ultra)) {
+ speed = XFER_UDMA_1;
+ } else if ((id->dma_ultra & 0x0001) && (ultra)) {
+ speed = XFER_UDMA_0;
+ } else if (id->dma_mword & 0x0004) {
+ speed = XFER_MW_DMA_2;
+ } else if (id->dma_mword & 0x0002) {
+ speed = XFER_MW_DMA_1;
+ } else if (id->dma_1word & 0x0004) {
+ speed = XFER_SW_DMA_2;
+ } else {
+ speed = XFER_PIO_0 + ide_get_best_pio_mode(drive, 255, 5, NULL);
+ }
+
+ (void) piix_tune_chipset(drive, speed);
return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_on :
((id->dma_ultra >> 8) & 7) ? ide_dma_on :
@@ -413,6 +431,7 @@ void __init ide_init_piix (ide_hwif_t *hwif)
#ifdef CONFIG_PIIX_TUNING
hwif->autodma = 1;
hwif->dmaproc = &piix_dmaproc;
+ hwif->speedproc = &piix_tune_chipset;
#endif /* CONFIG_PIIX_TUNING */
#endif /* !CONFIG_BLK_DEV_IDEDMA */
}
diff --git a/drivers/ide/qd6580.c b/drivers/ide/qd6580.c
index ad56c295c..4c00de504 100644
--- a/drivers/ide/qd6580.c
+++ b/drivers/ide/qd6580.c
@@ -1,12 +1,21 @@
/*
- * linux/drivers/ide/qd6580.c Version 0.02 Feb 09, 1996
+ * linux/drivers/ide/qd6580.c Version 0.03 May 13, 2000
*
- * Copyright (C) 1996 Linus Torvalds & author (see below)
+ * Copyright (C) 1996-2000 Linus Torvalds & author (see below)
*/
/*
- * QDI QD6580 EIDE controller fast support by Colten Edwards.
- * No net access, but (maybe) can be reached at pje120@cs.usask.ca
+ * Version 0.03 Cleaned auto-tune, added probe
+ *
+ * QDI QD6580 EIDE controller fast support
+ *
+ * To activate controller support use kernel parameter "ide0=qd6580"
+ * To enable tuning use kernel parameter "ide0=autotune"
+ */
+
+/*
+ * Rewritten from the work of Colten Edwards <pje120@cs.usask.ca> by
+ * Samuel Thibault <samuel.thibault@fnac.net>
*/
#undef REALLY_SLOW_IO /* most systems can safely undef this */
@@ -27,42 +36,237 @@
#include "ide_modes.h"
/*
- * Register 0xb3 looks like:
- * 0x4f is fast mode3 ?
- * 0x3f is medium mode2 ?
- * 0x2f is slower mode1 ?
- * 0x1f is slower yet mode0 ?
- * 0x0f ??? ???
+ * I/O ports are 0xb0 0xb1 0xb2 and 0xb3
+ * or 0x30 0x31 0x32 and 0x33
+ * -- this is a dual IDE interface with I/O chips
+ *
+ * More research on qd6580 being done by willmore@cig.mot.com (David)
+ */
+
+/*
+ * 0xb0: Timer1
*
- * Don't know whether this sets BOTH drives, or just the first drive.
- * Don't know if there is a separate setting for the second drive.
+ *
+ * 0xb1: Status
*
- * Feel free to patch this if you have one of these beasts
- * and can work out the answers!
+ * && 0xf0 is either 0b1010000 or 0b01010000, or else it isn't a qd6580
+ * bit 3 & 2: unknown (useless ?) I have 0 & 1, respectively
+ * bit 1: 1 if qd6580 baseport is 0xb0
+ * 0 if qd6580 baseport is 0x30
+ * bit 0: 1 if ide baseport is 0x1f0
+ * 0 if ide baseport is 0x170
+ * (? Strange: the Dos driver uses it, and then forces baseport to 0x1f0 ?)
+ *
+ *
+ * 0xb2: Timer2
*
- * I/O ports are 0xb0 0xb2 and 0xb3
+ *
+ * 0xb3: Control
*
- * More research on qd6580 being done by willmore@cig.mot.com (David)
- * -- this is apparently a *dual* IDE interface
+ * bits 0-3 are always set 1
+ * bit 6 : if 1, must be set 1
+ * bit 1 : if 1, bit 7 must be set 1
+ * bit 0 : if 1, drives are independant, we can have two different timers for
+ * the two drives.
+ * if 0, we have to take the slowest drive into account,
+ * but we may tune the second hwif ?
*/
-static void tune_qd6580 (ide_drive_t *drive, byte pio)
+typedef struct ide_hd_timings_s {
+ int active_time; /* Active pulse (ns) minimum */
+ int recovery_time; /* Recovery pulse (ns) minimum */
+} ide_hd_timings_t;
+
+static int basePort; /* base port address (0x30 or 0xb0) */
+static byte status; /* status register of qd6580 */
+static byte control; /* control register of qd6580 */
+
+/* truncates a in [b,c] */
+#define IDE_IN(a,b,c) ( ((a)<(b)) ? (b) : ( (a)>(c) ? (c) : (a)) )
+
+static int bus_clock; /* Vesa local bus clock (ns) */
+static int tuned=0; /* to remember whether we've already been tuned */
+
+/*
+ * tune_drive
+ *
+ * Finds timings for the specified drive, returns it in struc t
+ */
+
+static void tune_drive ( ide_drive_t *drive, byte pio, ide_hd_timings_t *t)
+{
+ ide_pio_data_t d;
+
+ t->active_time = 0xaf;
+ t->recovery_time = 0x19f; /* worst cases values from the dos driver */
+
+ if (drive->present == 0) { /* not present : free to give any timing */
+ t->active_time = 0x0;
+ t->recovery_time = 0x0;
+ return;
+ }
+
+ pio = ide_get_best_pio_mode(drive, pio, 4, &d);
+
+ if (pio) {
+
+ switch (pio) {
+ case 0: break;
+ case 3: t->active_time = 0x56;
+ t->recovery_time = d.cycle_time-0x66;
+ break;
+ case 4: t->active_time = 0x46;
+ t->recovery_time = d.cycle_time-0x3d;
+ break;
+ default: if (d.cycle_time >= 0xb4) {
+ t->active_time = 0x6e;
+ t->recovery_time = d.cycle_time - 0x78;
+ } else {
+ t->active_time = ide_pio_timings[pio].active_time;
+ t->recovery_time = d.cycle_time
+ -t->active_time
+ -ide_pio_timings[pio].setup_time;
+ }
+ }
+ }
+ printk("%s: PIO mode%d, tim1=%dns tim2=%dns\n", drive->name, pio, t->active_time, t->recovery_time);
+}
+
+/*
+ * tune_ide
+ *
+ * Tunes the whole ide, ie tunes each drives, and takes the worst timings
+ * to tune qd6580
+ */
+
+static void tune_ide ( ide_hwif_t *hwif, byte pio )
{
unsigned long flags;
+ ide_hd_timings_t t[2]={{0,0},{0,0}};
+
+ byte active_cycle;
+ byte recovery_cycle;
+ byte parameter;
+ int bus_speed = ide_system_bus_speed ();
+
+ bus_clock = 1000 / bus_speed;
+
+ save_flags(flags); /* all CPUs */
+ cli(); /* all CPUs */
+ outb( (bus_clock<30) ? 0x0 : 0x0a, basePort + 0x02);
+ outb( 0x40 | ((control & 0x02) ? 0x9f:0x1f), basePort+0x03);
+ restore_flags(flags);
- pio = ide_get_best_pio_mode(drive, pio, 3, NULL);
+ tune_drive (&hwif->drives[0], pio, &t[0]);
+ tune_drive (&hwif->drives[1], pio, &t[1]);
- save_flags(flags); /* all CPUs */
- cli(); /* all CPUs */
- outb_p(0x8d,0xb0);
- outb_p(0x0 ,0xb2);
- outb_p(((pio+1)<<4)|0x0f,0xb3);
+ t[0].active_time = IDE_MAX(t[0].active_time, t[1].active_time);
+ t[0].recovery_time = IDE_MAX(t[0].recovery_time,t[1].recovery_time);
+
+ active_cycle = 17-IDE_IN(t[0].active_time / bus_clock + 1, 2, 17);
+ recovery_cycle = 15-IDE_IN(t[0].recovery_time / bus_clock + 1, 2, 15);
+
+ parameter=active_cycle | (recovery_cycle<<4);
+
+ printk("%s: tim1=%dns tim2=%dns => %#x\n", hwif->name, t[0].active_time, t[0].recovery_time, parameter);
+
+ save_flags(flags); /* all CPUs */
+ cli(); /* all CPUs */
+ outb_p(parameter,0xb0);
inb(0x3f6);
restore_flags(flags); /* all CPUs */
+
+}
+
+/*
+ * tune_qd6580
+ *
+ * tunes the hwif if not tuned
+ */
+
+static void tune_qd6580 (ide_drive_t *drive, byte pio)
+{
+ if (! tuned) {
+ tune_ide(HWIF(drive), pio);
+ tuned = 1;
+ }
+}
+
+/*
+ * testreg
+ *
+ * tests if the given port is a register
+ */
+
+static int __init testreg(int port)
+{
+ byte savereg;
+ byte readreg;
+ unsigned long flags;
+
+ save_flags(flags); /* all CPUs */
+ cli(); /* all CPUs */
+ savereg = inb(port);
+ outb_p(0x15,port); /* safe value */
+ readreg = inb_p(port);
+ outb(savereg,port);
+ restore_flags(flags); /* all CPUs */
+
+ if (savereg == 0x15) {
+ printk("Outch ! the probe for qd6580 isn't reliable !\n");
+ printk("Please contact samuel.thibault@fnac.net to tell about your hardware\n");
+ printk("Assuming qd6580 is present");
+ }
+
+ return (readreg == 0x15);
}
+/*
+ * trybase:
+ *
+ * tries to find a qd6580 at the given base and save it if found
+ */
+
+static int __init trybase (int base)
+{
+ unsigned long flags;
+
+ save_flags(flags); /* all CPUs */
+ cli(); /* all CPUs */
+ status = inb(base+0x01);
+ control = inb(base+0x03);
+ restore_flags(flags); /* all CPUs */
+
+ if (((status & 0xf0) != 0x50) && ((status & 0xf0) != 0xa0)) return(0);
+ if (! ( ((status & 0x02) == 0x0) == (base == 0x30) ) ) return (0);
+
+ /* Seems to be OK, let's use it */
+
+ basePort = base;
+ return(testreg(base));
+}
+
+/*
+ * probe:
+ *
+ * probes qd6580 at 0xb0 (the default) or 0x30
+ */
+
+static int __init probe (void)
+{
+ return (trybase(0xb0) ? 1 : trybase(0x30));
+}
+
+
void __init init_qd6580 (void)
{
+ if (! probe()) {
+ printk("qd6580: not found\n");
+ return;
+ }
+
+ printk("qd6580: base=%#x, status=%#x, control=%#x\n", basePort, status, control);
+
ide_hwifs[0].chipset = ide_qd6580;
ide_hwifs[1].chipset = ide_qd6580;
ide_hwifs[0].tuneproc = &tune_qd6580;
diff --git a/drivers/ide/sis5513.c b/drivers/ide/sis5513.c
index 581992c63..be56a7f24 100644
--- a/drivers/ide/sis5513.c
+++ b/drivers/ide/sis5513.c
@@ -227,9 +227,8 @@ static void config_drive_art_rwp (ide_drive_t *drive)
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev;
- int drive_number = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
byte reg4bh = 0;
- byte rw_prefetch = (0x11 << drive_number);
+ byte rw_prefetch = (0x11 << drive->dn);
pci_read_config_byte(dev, 0x4b, &reg4bh);
if (drive->media != ide_disk)
@@ -248,12 +247,8 @@ static void config_art_rwp_pio (ide_drive_t *drive, byte pio)
unsigned short eide_pio_timing[6] = {600, 390, 240, 180, 120, 90};
unsigned short xfer_pio = drive->id->eide_pio_modes;
- int drive_number = ((hwif->channel ? 2 : 0) + (drive->select.b.unit & 0x01));
-#if 0
config_drive_art_rwp(drive);
-#endif
-
pio = ide_get_best_pio_mode(drive, 255, pio, NULL);
if (xfer_pio> 4)
@@ -281,7 +276,7 @@ static void config_art_rwp_pio (ide_drive_t *drive, byte pio)
* Cycle time 20T (600ns) 13T (390ns) 8T (240ns) 6T (180ns) 4T (120ns)
*/
- switch(drive_number) {
+ switch(drive->dn) {
case 0: drive_pci = 0x40; break;
case 1: drive_pci = 0x42; break;
case 2: drive_pci = 0x44; break;
@@ -329,7 +324,7 @@ static int config_chipset_for_pio (ide_drive_t *drive, byte pio)
return err;
}
-#undef SIS5513_TUNEPROC
+#define SIS5513_TUNEPROC
#ifdef SIS5513_TUNEPROC
static void sis5513_tune_drive (ide_drive_t *drive, byte pio)
@@ -354,7 +349,6 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
unsigned long dma_base = hwif->dma_base;
byte unit = (drive->select.b.unit & 0x01);
byte speed = 0x00, unmask = 0xE0, four_two = 0x00;
- int drive_number = ((hwif->channel ? 2 : 0) + unit);
byte udma_66 = ((id->hw_config & 0x2000) && (hwif->udma_four)) ? 1 : 0;
if (host_dev) {
@@ -370,7 +364,7 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
}
}
- switch(drive_number) {
+ switch(drive->dn) {
case 0: drive_pci = 0x40;break;
case 1: drive_pci = 0x42;break;
case 2: drive_pci = 0x44;break;
@@ -438,7 +432,7 @@ static int config_chipset_for_dma (ide_drive_t *drive, byte ultra)
err = ide_config_drive_speed(drive, speed);
#if SIS5513_DEBUG_DRIVE_INFO
- printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive_number);
+ printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive->dn);
#endif /* SIS5513_DEBUG_DRIVE_INFO */
return ((int) ((id->dma_ultra >> 11) & 3) ? ide_dma_on :
diff --git a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c
index f9d96a865..39258362c 100644
--- a/drivers/ide/via82cxxx.c
+++ b/drivers/ide/via82cxxx.c
@@ -115,6 +115,7 @@ static struct chipset_bus_clock_list_entry * via82cxxx_table = NULL;
struct chipset_bus_clock_list_entry via82cxxx_type_one [] = {
/* speed */ /* 25 */ /* 33 */ /* 37.5 */ /* 41.5 */
+#ifdef CONFIG_BLK_DEV_IDEDMA
{ XFER_UDMA_4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ XFER_UDMA_3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ XFER_UDMA_2, 0x60, 0x20, 0x60, 0x20, 0x60, 0x21, 0x00, 0x00 },
@@ -124,7 +125,7 @@ struct chipset_bus_clock_list_entry via82cxxx_type_one [] = {
{ XFER_MW_DMA_2, 0x03, 0x20, 0x03, 0x20, 0x03, 0x21, 0x00, 0x00 },
{ XFER_MW_DMA_1, 0x03, 0x31, 0x03, 0x31, 0x03, 0x32, 0x00, 0x00 },
{ XFER_MW_DMA_0, 0x03, 0x31, 0x03, 0x31, 0x03, 0x32, 0x00, 0x00 },
-
+#endif /* CONFIG_BLK_DEV_IDEDMA */
{ XFER_PIO_4, 0x03, 0x20, 0x03, 0x20, 0x03, 0x21, 0x00, 0x00 },
{ XFER_PIO_3, 0x03, 0x31, 0x03, 0x31, 0x03, 0x32, 0x00, 0x00 },
{ XFER_PIO_2, 0x03, 0x65, 0x03, 0x65, 0x03, 0x76, 0x00, 0x00 },
@@ -135,6 +136,7 @@ struct chipset_bus_clock_list_entry via82cxxx_type_one [] = {
struct chipset_bus_clock_list_entry via82cxxx_type_two [] = {
/* speed */ /* 25 */ /* 33 */ /* 37.5 */ /* 41.5 */
+#ifdef CONFIG_BLK_DEV_IDEDMA
{ XFER_UDMA_4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ XFER_UDMA_3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ XFER_UDMA_2, 0xE0, 0x20, 0xE0, 0x20, 0xE1, 0x31, 0xE1, 0x32 },
@@ -144,7 +146,7 @@ struct chipset_bus_clock_list_entry via82cxxx_type_two [] = {
{ XFER_MW_DMA_2, 0x03, 0x20, 0x03, 0x20, 0x03, 0x31, 0x03, 0x32 },
{ XFER_MW_DMA_1, 0x03, 0x31, 0x03, 0x31, 0x03, 0x42, 0x03, 0x53 },
{ XFER_MW_DMA_0, 0x03, 0x31, 0x03, 0x31, 0x03, 0x42, 0x03, 0x53 },
-
+#endif /* CONFIG_BLK_DEV_IDEDMA */
{ XFER_PIO_4, 0x03, 0x20, 0x03, 0x20, 0x03, 0x31, 0x03, 0x32 },
{ XFER_PIO_3, 0x03, 0x31, 0x03, 0x31, 0x03, 0x42, 0x03, 0x53 },
{ XFER_PIO_2, 0x03, 0x65, 0x03, 0x65, 0x03, 0x87, 0x03, 0xA8 },
@@ -155,6 +157,7 @@ struct chipset_bus_clock_list_entry via82cxxx_type_two [] = {
struct chipset_bus_clock_list_entry via82cxxx_type_three [] = {
/* speed */ /* 25 */ /* 33 */ /* 37.5 */ /* 41.5 */
+#ifdef CONFIG_BLK_DEV_IDEDMA
{ XFER_UDMA_4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ XFER_UDMA_3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ XFER_UDMA_2, 0xE0, 0x20, 0xE0, 0x20, 0xE1, 0x31, 0xE1, 0x32 },
@@ -164,7 +167,7 @@ struct chipset_bus_clock_list_entry via82cxxx_type_three [] = {
{ XFER_MW_DMA_2, 0x03, 0x20, 0x03, 0x20, 0x03, 0x31, 0x03, 0x32 },
{ XFER_MW_DMA_1, 0x03, 0x31, 0x03, 0x31, 0x03, 0x42, 0x03, 0x53 },
{ XFER_MW_DMA_0, 0x03, 0x31, 0x03, 0x31, 0x03, 0x42, 0x03, 0x53 },
-
+#endif /* CONFIG_BLK_DEV_IDEDMA */
{ XFER_PIO_4, 0x03, 0x20, 0x03, 0x20, 0x03, 0x31, 0x03, 0x32 },
{ XFER_PIO_3, 0x03, 0x31, 0x03, 0x31, 0x03, 0x42, 0x03, 0x53 },
{ XFER_PIO_2, 0x03, 0x65, 0x03, 0x65, 0x03, 0x87, 0x03, 0xA8 },
@@ -175,6 +178,7 @@ struct chipset_bus_clock_list_entry via82cxxx_type_three [] = {
struct chipset_bus_clock_list_entry via82cxxx_type_four [] = {
/* speed */ /* 25 */ /* 33 */ /* 37.5 */ /* 41.5 */
+#ifdef CONFIG_BLK_DEV_IDEDMA
{ XFER_UDMA_4, 0x00, 0x00, 0xE0, 0x20, 0xE1, 0x31, 0x00, 0x00 },
{ XFER_UDMA_3, 0x00, 0x00, 0xE1, 0x20, 0xE2, 0x31, 0x00, 0x00 },
{ XFER_UDMA_2, 0x00, 0x00, 0xE2, 0x20, 0xE4, 0x31, 0x00, 0x00 },
@@ -184,7 +188,7 @@ struct chipset_bus_clock_list_entry via82cxxx_type_four [] = {
{ XFER_MW_DMA_2, 0x00, 0x00, 0x03, 0x20, 0x03, 0x31, 0x00, 0x00 },
{ XFER_MW_DMA_1, 0x00, 0x00, 0x03, 0x31, 0x03, 0x42, 0x00, 0x00 },
{ XFER_MW_DMA_0, 0x00, 0x00, 0x03, 0x31, 0x03, 0x42, 0x00, 0x00 },
-
+#endif /* CONFIG_BLK_DEV_IDEDMA */
{ XFER_PIO_4, 0x00, 0x00, 0x03, 0x20, 0x03, 0x31, 0x00, 0x00 },
{ XFER_PIO_3, 0x00, 0x00, 0x03, 0x31, 0x03, 0x42, 0x00, 0x00 },
{ XFER_PIO_2, 0x00, 0x00, 0x03, 0x65, 0x03, 0x87, 0x00, 0x00 },
@@ -651,8 +655,7 @@ static int via82cxxx_tune_chipset (ide_drive_t *drive, byte speed)
{
ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev;
- byte unit = (drive->select.b.unit & 0x01);
- int drive_number = ((hwif->channel ? 2 : 0) + unit);
+ struct chipset_bus_clock_list_entry * temp_table = NULL;
byte ata2_pci = 0x00;
byte ata3_pci = 0x00;
@@ -662,7 +665,10 @@ static int via82cxxx_tune_chipset (ide_drive_t *drive, byte speed)
int bus_speed = system_bus_clock();
- switch(drive_number) {
+ if (via82cxxx_table == NULL)
+ return -1;
+
+ switch(drive->dn) {
case 0: ata2_pci = 0x4b; ata3_pci = 0x53; break;
case 1: ata2_pci = 0x4a; ata3_pci = 0x52; break;
case 2: ata2_pci = 0x49; ata3_pci = 0x51; break;
@@ -671,16 +677,26 @@ static int via82cxxx_tune_chipset (ide_drive_t *drive, byte speed)
return -1;
}
+ if ((via82cxxx_table == via82cxxx_type_four) && (speed <= XFER_UDMA_2)) {
+ temp_table = via82cxxx_type_three;
+ } else {
+ temp_table = via82cxxx_table;
+ }
+
pci_read_config_byte(dev, ata2_pci, &timing);
- timing = pci_bus_clock_list(speed, bus_speed, via82cxxx_table);
+ timing = pci_bus_clock_list(speed, bus_speed, temp_table);
pci_write_config_byte(dev, ata2_pci, timing);
pci_read_config_byte(dev, ata3_pci, &ultra);
- ultra = pci_bus_clock_list_ultra(speed, bus_speed, via82cxxx_table);
+ ultra = pci_bus_clock_list_ultra(speed, bus_speed, temp_table);
pci_write_config_byte(dev, ata3_pci, ultra);
+ if (!drive->init_speed)
+ drive->init_speed = speed;
+
err = ide_config_drive_speed(drive, speed);
+ drive->current_speed = speed;
return(err);
}
@@ -845,6 +861,7 @@ unsigned int __init pci_init_via82cxxx (struct pci_dev *dev, const char *name)
struct pci_dev *isa;
int i, j, ata33, ata66;
+ int bus_speed = system_bus_clock();
byte revision = 0;
for (i = 0; i < arraysize (ApolloHostChipInfo) && !host_dev; i++) {
@@ -873,18 +890,26 @@ unsigned int __init pci_init_via82cxxx (struct pci_dev *dev, const char *name)
ata33 = 1;
ata66 = 0;
+ via82cxxx_table = ApolloISAChipInfo[j].chipset_table;
+
if (ApolloISAChipInfo[j].flags & VIA_FLAG_CHECK_REV) {
pci_read_config_byte(isa_dev, 0x0d, &revision);
ata33 = (revision >= 0x20) ? 1 : 0;
} else if (ApolloISAChipInfo[j].flags & VIA_FLAG_ATA_66) {
+ byte ata66_0 = 0, ata66_1 = 0;
ata33 = 0;
ata66 = 1;
+ pci_read_config_byte(dev, 0x50, &ata66_1);
+ pci_read_config_byte(dev, 0x52, &ata66_0);
+ if ((ata66_0 & 0x04) || (ata66_1 & 0x04)) {
+ via82cxxx_table = (bus_speed == 33 || bus_speed == 37) ?
+ via82cxxx_type_four :
+ via82cxxx_type_three;
+ }
}
if (ata33 | ata66)
printk(" Chipset Core ATA-%s", ata66 ? "66" : "33");
-
- via82cxxx_table = ApolloISAChipInfo[j].chipset_table;
}
printk("\n");
}
@@ -915,6 +940,7 @@ void __init ide_init_via82cxxx (ide_hwif_t *hwif)
#ifdef CONFIG_VIA82CXXX_TUNING
hwif->tuneproc = &via82cxxx_tune_drive;
+ hwif->speedproc = &via82cxxx_tune_chipset;
hwif->drives[0].autotune = 1;
hwif->drives[1].autotune = 1;
hwif->autodma = 0;