diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-06-15 01:55:58 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-06-15 01:55:58 +0000 |
commit | 53b3988d474435254a3b053a68bb24ce9e439295 (patch) | |
tree | f8da8e40f01f4ad02bbd76b8c9920749b118235f /drivers/ide | |
parent | b0cb48abe83d1a4389ea938bf624f8baa82c5047 (diff) |
Merge with 2.3.99-pre9.
Diffstat (limited to 'drivers/ide')
-rw-r--r-- | drivers/ide/Config.in | 9 | ||||
-rw-r--r-- | drivers/ide/aec62xx.c | 43 | ||||
-rw-r--r-- | drivers/ide/alim15x3.c | 10 | ||||
-rw-r--r-- | drivers/ide/amd7409.c | 51 | ||||
-rw-r--r-- | drivers/ide/cmd64x.c | 34 | ||||
-rw-r--r-- | drivers/ide/hd.c | 9 | ||||
-rw-r--r-- | drivers/ide/hpt34x.c | 17 | ||||
-rw-r--r-- | drivers/ide/hpt366.c | 30 | ||||
-rw-r--r-- | drivers/ide/icside.c | 156 | ||||
-rw-r--r-- | drivers/ide/ide-disk.c | 11 | ||||
-rw-r--r-- | drivers/ide/ide-features.c | 66 | ||||
-rw-r--r-- | drivers/ide/ide-pci.c | 20 | ||||
-rw-r--r-- | drivers/ide/ide-pmac.c | 243 | ||||
-rw-r--r-- | drivers/ide/ide-probe.c | 66 | ||||
-rw-r--r-- | drivers/ide/ide.c | 224 | ||||
-rw-r--r-- | drivers/ide/pdc202xx.c | 243 | ||||
-rw-r--r-- | drivers/ide/piix.c | 107 | ||||
-rw-r--r-- | drivers/ide/qd6580.c | 252 | ||||
-rw-r--r-- | drivers/ide/sis5513.c | 16 | ||||
-rw-r--r-- | drivers/ide/via82cxxx.c | 48 |
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, ®D); (void) pci_read_config_byte(dev, pciU, ®U); 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, ®1); pci_read_config_dword(HWIF(drive)->pci_dev, 0x48, ®2); - 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, ®1); pci_read_config_dword(HWIF(drive)->pci_dev, 0x48, ®2); - 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, ®50h); pci_write_config_byte(HWIF(drive)->pci_dev, 0x50, reg50h|0x03); pci_read_config_byte(HWIF(drive)->pci_dev, 0x50, ®50h); /* 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, ®4042); 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, ®4a); pci_read_config_word(dev, 0x54, ®54); - 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, ®4bh); 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; |