diff -urN linux-2.4.0-prerelease-pristine/drivers/ide/cs5530.c linux-2.4.0-prerelease/drivers/ide/cs5530.c --- linux-2.4.0-prerelease-pristine/drivers/ide/cs5530.c Tue Jun 20 07:52:36 2000 +++ linux-2.4.0-prerelease/drivers/ide/cs5530.c Sun Dec 31 21:53:17 2000 @@ -257,6 +257,14 @@ unsigned short pcicmd = 0; unsigned long flags; +#if defined(DISPLAY_CS5530_TIMINGS) && defined(CONFIG_PROC_FS) + if (!cs5530_proc) { + cs5530_proc = 1; + bmide_dev = dev; + cs5530_display_info = &cs5530_get_info; + } +#endif /* DISPLAY_CS5530_TIMINGS && CONFIG_PROC_FS */ + pci_for_each_dev (dev) { if (dev->vendor == PCI_VENDOR_ID_CYRIX) { switch (dev->device) { @@ -326,14 +334,6 @@ pci_write_config_byte(master_0, 0x43, 0xc1); restore_flags(flags); - -#if defined(DISPLAY_CS5530_TIMINGS) && defined(CONFIG_PROC_FS) - if (!cs5530_proc) { - cs5530_proc = 1; - bmide_dev = dev; - cs5530_display_info = &cs5530_get_info; - } -#endif /* DISPLAY_CS5530_TIMINGS && CONFIG_PROC_FS */ return 0; } diff -urN linux-2.4.0-prerelease-pristine/drivers/ide/hpt366.c linux-2.4.0-prerelease/drivers/ide/hpt366.c --- linux-2.4.0-prerelease-pristine/drivers/ide/hpt366.c Tue Nov 7 11:02:24 2000 +++ linux-2.4.0-prerelease/drivers/ide/hpt366.c Sun Dec 31 21:53:17 2000 @@ -346,6 +346,9 @@ static int hpt3xx_tune_chipset (ide_drive_t *drive, byte speed) { + if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0)) + return -1; + if (!drive->init_speed) drive->init_speed = speed; @@ -428,6 +431,9 @@ byte ultra66 = eighty_ninty_three(drive); int rval; + if ((drive->media != ide_disk) && (speed < XFER_SW_DMA_0)) + return ((int) ide_dma_off_quietly); + if ((id->dma_ultra & 0x0020) && (!check_in_drive_lists(drive, bad_ata100_5)) && (HPT370_ALLOW_ATA100_5) && @@ -617,8 +623,14 @@ pci_write_config_byte(dev, PCI_ROM_ADDRESS, dev->resource[PCI_ROM_RESOURCE].start | PCI_ROM_ADDRESS_ENABLE); pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &test); + +#if 0 if (test != 0x08) pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x08); +#else + if (test != (L1_CACHE_BYTES / 4)) + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, (L1_CACHE_BYTES / 4)); +#endif pci_read_config_byte(dev, PCI_LATENCY_TIMER, &test); if (test != 0x78) diff -urN linux-2.4.0-prerelease-pristine/drivers/ide/ide-dma.c linux-2.4.0-prerelease/drivers/ide/ide-dma.c --- linux-2.4.0-prerelease-pristine/drivers/ide/ide-dma.c Thu Jul 27 16:40:57 2000 +++ linux-2.4.0-prerelease/drivers/ide/ide-dma.c Sun Dec 31 21:53:17 2000 @@ -90,6 +90,8 @@ #include #include +#undef CONFIG_BLK_DEV_IDEDMA_TIMEOUT + extern char *ide_dmafunc_verbose(ide_dma_action_t dmafunc); #ifdef CONFIG_IDEDMA_NEW_DRIVE_LISTINGS @@ -265,6 +267,12 @@ cur_addr = sg_dma_address(sg); cur_len = sg_dma_len(sg); + /* + * Fill in the dma table, without crossing any 64kB boundaries. + * Most hardware requires 16-bit alignment of all blocks, + * but the trm290 requires 32-bit alignment. + */ + while (cur_len) { if (++count >= PRD_ENTRIES) { printk("%s: DMA table too small\n", drive->name); @@ -515,9 +523,17 @@ return check_drive_lists(drive, (func == ide_dma_good_drive)); case ide_dma_verbose: return report_drive_dmaing(drive); + case ide_dma_timeout: +#ifdef CONFIG_BLK_DEV_IDEDMA_TIMEOUT + /* + * Have to issue an abort and requeue the request + * DMA engine got turned off by a goofy ASIC, and + * we have to clean up the mess, and here is as good + * as any. Do it globally for all chipsets. + */ +#endif /* CONFIG_BLK_DEV_IDEDMA_TIMEOUT */ case ide_dma_retune: case ide_dma_lostirq: - case ide_dma_timeout: printk("ide_dmaproc: chipset supported %s func only: %d\n", ide_dmafunc_verbose(func), func); return 1; default: diff -urN linux-2.4.0-prerelease-pristine/drivers/ide/ide-features.c linux-2.4.0-prerelease/drivers/ide/ide-features.c --- linux-2.4.0-prerelease-pristine/drivers/ide/ide-features.c Mon Oct 16 12:21:40 2000 +++ linux-2.4.0-prerelease/drivers/ide/ide-features.c Sun Dec 31 21:53:17 2000 @@ -224,7 +224,7 @@ #ifndef CONFIG_IDEDMA_IVB if ((drive->id->hw_config & 0x6000) == 0) { #else /* !CONFIG_IDEDMA_IVB */ - if (((drive->id->hw_config & 0x2000) == 0) || + if (((drive->id->hw_config & 0x2000) == 0) && ((drive->id->hw_config & 0x4000) == 0)) { #endif /* CONFIG_IDEDMA_IVB */ printk("%s: Speed warnings UDMA 3/4/5 is not functional.\n", drive->name); diff -urN linux-2.4.0-prerelease-pristine/drivers/ide/ide-pci.c linux-2.4.0-prerelease/drivers/ide/ide-pci.c --- linux-2.4.0-prerelease-pristine/drivers/ide/ide-pci.c Tue Nov 7 11:02:24 2000 +++ linux-2.4.0-prerelease/drivers/ide/ide-pci.c Sun Dec 31 21:53:17 2000 @@ -561,7 +561,7 @@ if (IDE_PCI_DEVID_EQ(d->devid, DEVID_HPT34X)) { /* see comments in hpt34x.c on why..... */ char *chipset_names[] = {"HPT343", "HPT345"}; - strcpy(d->name, chipset_names[(pcicmd & PCI_COMMAND_MEMORY)]); + strcpy(d->name, chipset_names[(pcicmd & PCI_COMMAND_MEMORY) ? 1 : 0]); d->bootable = (pcicmd & PCI_COMMAND_MEMORY) ? OFF_BOARD : NEVER_BOARD; } @@ -753,6 +753,12 @@ if (hpt363_shared_pin && hpt363_shared_irq) { d->bootable = ON_BOARD; printk("%s: onboard version of chipset, pin1=%d pin2=%d\n", d->name, pin1, pin2); +#if 0 + /* I forgot why I did this once, but it fixed something. */ + pci_write_config_byte(dev2, PCI_INTERRUPT_PIN, dev->irq); + printk("PCI: %s: Fixing interrupt %d pin %d to ZERO \n", d->name, dev2->irq, pin2); + pci_write_config_byte(dev2, PCI_INTERRUPT_LINE, 0); +#endif } break; } diff -urN linux-2.4.0-prerelease-pristine/drivers/ide/osb4.c linux-2.4.0-prerelease/drivers/ide/osb4.c --- linux-2.4.0-prerelease-pristine/drivers/ide/osb4.c Thu Oct 26 14:11:39 2000 +++ linux-2.4.0-prerelease/drivers/ide/osb4.c Sun Dec 31 21:53:17 2000 @@ -60,14 +60,13 @@ #include #include -static byte osb4_revision = 0; static struct pci_dev *bmide_dev; -static int osb4_get_info(char *, char **, off_t, int, int); -extern int (*osb4_display_info)(char *, char **, off_t, int, int); /* ide-proc.c */ +static int osb4_get_info(char *, char **, off_t, int); +extern int (*osb4_display_info)(char *, char **, off_t, int); /* ide-proc.c */ extern char *ide_media_verbose(ide_drive_t *); -static int osb4_get_info (char *buffer, char **addr, off_t offset, int count, int dummy) +static int osb4_get_info (char *buffer, char **addr, off_t offset, int count) { char *p = buffer; u32 bibma = pci_resource_start(bmide_dev, 4); @@ -113,116 +112,202 @@ } #endif /* defined(DISPLAY_OSB4_TIMINGS) && defined(CONFIG_PROC_FS) */ +static byte osb4_revision = 0; + byte osb4_proc = 0; extern char *ide_xfer_verbose (byte xfer_rate); -static void osb4_tune_drive (ide_drive_t *drive, byte pio) -{ - /* command/recover widths */ - byte timings[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 }; - int port = HWIF(drive)->index ? 0x42 : 0x40; - - pio = ide_get_best_pio_mode(drive, pio, 4, NULL); - if (&HWIF(drive)->drives[0] == drive) /* master drive */ - port++; - pci_write_config_byte(HWIF(drive)->pci_dev, port, timings[pio]); -} +static struct pci_dev *isa_dev; -#if defined(CONFIG_BLK_DEV_IDEDMA) && defined(CONFIG_BLK_DEV_OSB4) static int osb4_tune_chipset (ide_drive_t *drive, byte speed) { + byte udma_modes[] = { 0x00, 0x01, 0x02 }; + byte dma_modes[] = { 0x77, 0x21, 0x20 }; + byte pio_modes[] = { 0x5d, 0x47, 0x34, 0x22, 0x20 }; + ide_hwif_t *hwif = HWIF(drive); struct pci_dev *dev = hwif->pci_dev; - byte is_slave = (&HWIF(drive)->drives[1] == drive) ? 1 : 0; - byte bit8, enable; - int err; - - /* clear udma register if we don't want udma */ - if (speed < XFER_UDMA_0) { - enable = 0x1 << (is_slave + (hwif->channel ? 2 : 0)); - pci_read_config_byte(dev, 0x54, &bit8); - pci_write_config_byte(dev, 0x54, bit8 & ~enable); - } - + byte unit = (drive->select.b.unit & 0x01); #ifdef CONFIG_BLK_DEV_IDEDMA - if (speed >= XFER_MW_DMA_0) { - byte channel = hwif->channel ? 0x46 : 0x44; - if (!is_slave) - channel++; + unsigned long dma_base = hwif->dma_base; +#endif /* CONFIG_BLK_DEV_IDEDMA */ + int err; - switch (speed) { - case XFER_MW_DMA_0: - bit8 = 0x77; - break; - case XFER_MW_DMA_1: - bit8 = 0x21; - break; - case XFER_MW_DMA_2: + byte drive_pci = 0x00; + byte drive_pci2 = 0x00; + byte drive_pci3 = hwif->channel ? 0x57 : 0x56; + + byte ultra_enable = 0x00; + byte ultra_timing = 0x00; + byte dma_timing = 0x00; + byte pio_timing = 0x00; + + byte pio = ide_get_best_pio_mode(drive, 255, 5, NULL); + + switch (drive->dn) { + case 0: drive_pci = 0x41; drive_pci2 = 0x45; break; + case 1: drive_pci = 0x40; drive_pci2 = 0x44; break; + case 2: drive_pci = 0x43; drive_pci2 = 0x47; break; + case 3: drive_pci = 0x42; drive_pci2 = 0x46; break; default: - bit8 = 0x20; - break; - } - pci_write_config_byte(dev, channel, bit8); + return -1; } - if (speed >= XFER_UDMA_0) { - byte channel = hwif->channel ? 0x57 : 0x56; - int slave = is_slave ? 4 : 0; + pci_read_config_byte(dev, drive_pci, &pio_timing); + pci_read_config_byte(dev, drive_pci2, &dma_timing); + pci_read_config_byte(dev, drive_pci3, &ultra_timing); + pci_read_config_byte(dev, 0x54, &ultra_enable); + +#ifdef DEBUG + printk("%s: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x ", + drive->name, ultra_timing, dma_timing, pio_timing); +#endif - pci_read_config_byte(dev, channel, &bit8); - bit8 &= ~(0xf << slave); - switch (speed) { - case XFER_UDMA_0: + pio_timing &= ~0xFF; + dma_timing &= ~0xFF; + ultra_timing &= ~(0x0F << (4*unit)); + ultra_enable &= ~(0x01 << drive->dn); + + switch(speed) { + case XFER_PIO_4: + case XFER_PIO_3: + case XFER_PIO_2: + case XFER_PIO_1: + case XFER_PIO_0: + pio_timing |= pio_modes[speed - XFER_PIO_0]; break; - case XFER_UDMA_1: - bit8 |= 0x1 << slave; +#ifdef CONFIG_BLK_DEV_IDEDMA + case XFER_MW_DMA_2: + case XFER_MW_DMA_1: + case XFER_MW_DMA_0: + pio_timing |= pio_modes[pio]; + dma_timing |= dma_modes[speed - XFER_MW_DMA_0]; break; + +// case XFER_UDMA_5: +// case XFER_UDMA_4: +// case XFER_UDMA_3: case XFER_UDMA_2: + case XFER_UDMA_1: + case XFER_UDMA_0: + pio_timing |= pio_modes[pio]; + dma_timing |= dma_modes[2]; + ultra_timing |= ((udma_modes[speed - XFER_UDMA_0]) << (4*unit)); + ultra_enable |= (0x01 << drive->dn); +#endif default: - bit8 |= 0x2 << slave; break; - } - pci_write_config_byte(dev, channel, bit8); - - enable = 0x1 << (is_slave + (hwif->channel ? 2 : 0)); - pci_read_config_byte(dev, 0x54, &bit8); - pci_write_config_byte(dev, 0x54, bit8 | enable); } + +#ifdef DEBUG + printk("%s: UDMA 0x%02x DMAPIO 0x%02x PIO 0x%02x ", + drive->name, ultra_timing, dma_timing, pio_timing); #endif #if OSB4_DEBUG_DRIVE_INFO printk("%s: %s drive%d\n", drive->name, ide_xfer_verbose(speed), drive->dn); #endif /* OSB4_DEBUG_DRIVE_INFO */ + if (!drive->init_speed) drive->init_speed = speed; + + pci_write_config_byte(dev, drive_pci, pio_timing); +#ifdef CONFIG_BLK_DEV_IDEDMA + pci_write_config_byte(dev, drive_pci2, dma_timing); + pci_write_config_byte(dev, drive_pci3, ultra_timing); + pci_write_config_byte(dev, 0x54, ultra_enable); + + 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; } -static int osb4_config_drive_for_dma (ide_drive_t *drive) +static void config_chipset_for_pio (ide_drive_t *drive) +{ + unsigned short eide_pio_timing[6] = {960, 480, 240, 180, 120, 90}; + unsigned short xfer_pio = drive->id->eide_pio_modes; + byte timing, speed, pio; + + pio = ide_get_best_pio_mode(drive, 255, 5, NULL); + + if (xfer_pio> 4) + xfer_pio = 0; + + if (drive->id->eide_pio_iordy > 0) { + for (xfer_pio = 5; + xfer_pio>0 && + drive->id->eide_pio_iordy>eide_pio_timing[xfer_pio]; + xfer_pio--); + } else { + xfer_pio = (drive->id->eide_pio_modes & 4) ? 0x05 : + (drive->id->eide_pio_modes & 2) ? 0x04 : + (drive->id->eide_pio_modes & 1) ? 0x03 : + (drive->id->tPIO & 2) ? 0x02 : + (drive->id->tPIO & 1) ? 0x01 : xfer_pio; + } + + timing = (xfer_pio >= pio) ? xfer_pio : pio; + + switch(timing) { + case 4: speed = XFER_PIO_4;break; + case 3: speed = XFER_PIO_3;break; + case 2: speed = XFER_PIO_2;break; + case 1: speed = XFER_PIO_1;break; + default: + speed = (!drive->id->tPIO) ? XFER_PIO_0 : XFER_PIO_SLOW; + break; + } + (void) osb4_tune_chipset(drive, speed); + drive->current_speed = speed; +} + +static void osb4_tune_drive (ide_drive_t *drive, byte pio) +{ + byte speed; + switch(pio) { + case 4: speed = XFER_PIO_4;break; + case 3: speed = XFER_PIO_3;break; + case 2: speed = XFER_PIO_2;break; + case 1: speed = XFER_PIO_1;break; + default: speed = XFER_PIO_0;break; + } + (void) osb4_tune_chipset(drive, speed); +} + +#ifdef CONFIG_BLK_DEV_IDEDMA +static int config_chipset_for_dma (ide_drive_t *drive) { struct hd_driveid *id = drive->id; byte speed; +#if 0 byte udma_66 = eighty_ninty_three(drive); /* need specs to figure out if osb4 is capable of ata/66/100 */ int ultra100 = 0; int ultra66 = 0; - int ultra = 1; if ((id->dma_ultra & 0x0020) && (udma_66) && (ultra100)) { speed = XFER_UDMA_5; - } else if ((id->dma_ultra & 0x0010) && (ultra)) { + } else if (id->dma_ultra & 0x0010) { speed = ((udma_66) && (ultra66)) ? XFER_UDMA_4 : XFER_UDMA_2; - } else if ((id->dma_ultra & 0x0008) && (ultra)) { + } else if (id->dma_ultra & 0x0008) { speed = ((udma_66) && (ultra66)) ? XFER_UDMA_3 : XFER_UDMA_1; - } else if ((id->dma_ultra & 0x0004) && (ultra)) { + } else if (id->dma_ultra & 0x0004) { +#else + if (id->dma_ultra & 0x0004) { +#endif speed = XFER_UDMA_2; - } else if ((id->dma_ultra & 0x0002) && (ultra)) { + } else if (id->dma_ultra & 0x0002) { speed = XFER_UDMA_1; - } else if ((id->dma_ultra & 0x0001) && (ultra)) { + } else if (id->dma_ultra & 0x0001) { speed = XFER_UDMA_0; } else if (id->dma_mword & 0x0004) { speed = XFER_MW_DMA_2; @@ -243,45 +328,87 @@ ide_dma_off_quietly); } +static int config_drive_xfer_rate (ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + ide_dma_action_t dma_func = ide_dma_on; + + if (id && (id->capability & 1) && HWIF(drive)->autodma) { + /* Consult the list of known "bad" drives */ + if (ide_dmaproc(ide_dma_bad_drive, drive)) { + dma_func = ide_dma_off; + goto fast_ata_pio; + } + dma_func = ide_dma_off_quietly; + if (id->field_valid & 4) { + if (id->dma_ultra & 0x002F) { + /* Force if Capable UltraDMA */ + dma_func = config_chipset_for_dma(drive); + if ((id->field_valid & 2) && + (dma_func != ide_dma_on)) + goto try_dma_modes; + } + } else if (id->field_valid & 2) { +try_dma_modes: + if ((id->dma_mword & 0x0007) || + (id->dma_1word & 0x007)) { + /* Force if Capable regular DMA modes */ + dma_func = config_chipset_for_dma(drive); + if (dma_func != ide_dma_on) + goto no_dma_set; + } + } else if (ide_dmaproc(ide_dma_good_drive, drive)) { + if (id->eide_dma_time > 150) { + goto no_dma_set; + } + /* Consult the list of known "good" drives */ + dma_func = config_chipset_for_dma(drive); + if (dma_func != ide_dma_on) + goto no_dma_set; + } else { + goto fast_ata_pio; + } + } else if ((id->capability & 8) || (id->field_valid & 2)) { +fast_ata_pio: + dma_func = ide_dma_off_quietly; +no_dma_set: + config_chipset_for_pio(drive); + } + return HWIF(drive)->dmaproc(dma_func, drive); +} + static int osb4_dmaproc(ide_dma_action_t func, ide_drive_t *drive) { switch (func) { case ide_dma_check: - return ide_dmaproc((ide_dma_action_t) osb4_config_drive_for_dma(drive), drive); + return config_drive_xfer_rate(drive); default : break; } /* Other cases are done by generic IDE-DMA code. */ return ide_dmaproc(func, drive); } -#endif /* defined(CONFIG_BLK_DEV_IDEDMA) && (CONFIG_BLK_DEV_OSB4) */ +#endif /* CONFIG_BLK_DEV_IDEDMA */ unsigned int __init pci_init_osb4 (struct pci_dev *dev, const char *name) { - u16 word; - byte bit8; + unsigned int reg64; pci_read_config_byte(dev, PCI_REVISION_ID, &osb4_revision); - /* setup command register. just make sure that bus master and - * i/o ports are on. */ - pci_read_config_word(dev, PCI_COMMAND, &word); - if ((word & (PCI_COMMAND_MASTER | PCI_COMMAND_IO)) != - (PCI_COMMAND_MASTER | PCI_COMMAND_IO)) - pci_write_config_word(dev, PCI_COMMAND, word | - PCI_COMMAND_MASTER | PCI_COMMAND_IO); - - /* make sure that we're in pci native mode for both the primary - * and secondary channel. */ - pci_read_config_byte(dev, PCI_CLASS_PROG, &bit8); - if ((bit8 & 0x5) != 0x5) - pci_write_config_byte(dev, PCI_CLASS_PROG, bit8 | 0x5); - - /* setup up our latency. the default is 255 which is a bit large. - * set it to 64 instead. */ - pci_read_config_byte(dev, PCI_LATENCY_TIMER, &bit8); - if (bit8 != 0x40) - pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x40); + isa_dev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4, NULL); + + pci_read_config_dword(isa_dev, 0x64, ®64); +#ifdef DEBUG + printk("%s: reg64 == 0x%08x\n", name, reg64); +#endif + reg64 &= ~0x0000A000; +#ifdef CONFIG_SMP + reg64 |= 0x00008000; +#endif + pci_write_config_dword(isa_dev, 0x64, reg64); + + pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x40); #if defined(DISPLAY_OSB4_TIMINGS) && defined(CONFIG_PROC_FS) if (!osb4_proc) { @@ -304,19 +431,22 @@ hwif->irq = hwif->channel ? 15 : 14; hwif->tuneproc = &osb4_tune_drive; - hwif->drives[0].autotune = 1; - hwif->drives[1].autotune = 1; - - if (!hwif->dma_base) - return; + hwif->speedproc = &osb4_tune_chipset; #ifndef CONFIG_BLK_DEV_IDEDMA + hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; hwif->autodma = 0; + return; #else /* CONFIG_BLK_DEV_IDEDMA */ -#ifdef CONFIG_BLK_DEV_OSB4 - hwif->autodma = 1; - hwif->dmaproc = &osb4_dmaproc; - hwif->speedproc = &osb4_tune_chipset; -#endif /* CONFIG_BLK_DEV_OSB4 */ + + if (hwif->dma_base) { + hwif->autodma = 1; + hwif->dmaproc = &osb4_dmaproc; + } else { + hwif->autodma = 0; + hwif->drives[0].autotune = 1; + hwif->drives[1].autotune = 1; + } #endif /* !CONFIG_BLK_DEV_IDEDMA */ } diff -urN linux-2.4.0-prerelease-pristine/drivers/ide/piix.c linux-2.4.0-prerelease/drivers/ide/piix.c --- linux-2.4.0-prerelease-pristine/drivers/ide/piix.c Fri Jul 7 15:55:24 2000 +++ linux-2.4.0-prerelease/drivers/ide/piix.c Sun Dec 31 21:53:17 2000 @@ -399,11 +399,65 @@ ide_dma_off_quietly); } +static void config_chipset_for_pio (ide_drive_t *drive) +{ + piix_tune_drive(drive, ide_get_best_pio_mode(drive, 255, 5, NULL)); +} + +static int config_drive_xfer_rate (ide_drive_t *drive) +{ + struct hd_driveid *id = drive->id; + ide_dma_action_t dma_func = ide_dma_on; + + if (id && (id->capability & 1) && HWIF(drive)->autodma) { + /* Consult the list of known "bad" drives */ + if (ide_dmaproc(ide_dma_bad_drive, drive)) { + dma_func = ide_dma_off; + goto fast_ata_pio; + } + dma_func = ide_dma_off_quietly; + if (id->field_valid & 4) { + if (id->dma_ultra & 0x002F) { + /* Force if Capable UltraDMA */ + dma_func = piix_config_drive_for_dma(drive); + if ((id->field_valid & 2) && + (dma_func != ide_dma_on)) + goto try_dma_modes; + } + } else if (id->field_valid & 2) { +try_dma_modes: + if ((id->dma_mword & 0x0007) || + (id->dma_1word & 0x007)) { + /* Force if Capable regular DMA modes */ + dma_func = piix_config_drive_for_dma(drive); + if (dma_func != ide_dma_on) + goto no_dma_set; + } + } else if (ide_dmaproc(ide_dma_good_drive, drive)) { + if (id->eide_dma_time > 150) { + goto no_dma_set; + } + /* Consult the list of known "good" drives */ + dma_func = piix_config_drive_for_dma(drive); + if (dma_func != ide_dma_on) + goto no_dma_set; + } else { + goto fast_ata_pio; + } + } else if ((id->capability & 8) || (id->field_valid & 2)) { +fast_ata_pio: + dma_func = ide_dma_off_quietly; +no_dma_set: + config_chipset_for_pio(drive); + } + return HWIF(drive)->dmaproc(dma_func, drive); +} + static int piix_dmaproc(ide_dma_action_t func, ide_drive_t *drive) { switch (func) { case ide_dma_check: - return ide_dmaproc((ide_dma_action_t) piix_config_drive_for_dma(drive), drive); + return config_drive_xfer_rate(drive); default : break; } diff -urN linux-2.4.0-prerelease-pristine/drivers/ide/sis5513.c linux-2.4.0-prerelease/drivers/ide/sis5513.c --- linux-2.4.0-prerelease-pristine/drivers/ide/sis5513.c Tue Nov 7 10:59:43 2000 +++ linux-2.4.0-prerelease/drivers/ide/sis5513.c Sun Dec 31 21:53:17 2000 @@ -48,6 +48,7 @@ { "SiS540", PCI_DEVICE_ID_SI_540, SIS5513_FLAG_ATA_66, }, { "SiS620", PCI_DEVICE_ID_SI_620, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, { "SiS630", PCI_DEVICE_ID_SI_630, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, + { "SiS730", PCI_DEVICE_ID_SI_730, SIS5513_FLAG_ATA_66|SIS5513_FLAG_LATENCY, }, { "SiS5591", PCI_DEVICE_ID_SI_5591, SIS5513_FLAG_ATA_33, }, { "SiS5597", PCI_DEVICE_ID_SI_5597, SIS5513_FLAG_ATA_33, }, { "SiS5600", PCI_DEVICE_ID_SI_5600, SIS5513_FLAG_ATA_33, }, @@ -337,6 +338,7 @@ case PCI_DEVICE_ID_SI_540: case PCI_DEVICE_ID_SI_620: case PCI_DEVICE_ID_SI_630: + case PCI_DEVICE_ID_SI_730: unmask = 0xF0; four_two = 0x01; break; @@ -370,7 +372,7 @@ switch(speed) { #ifdef CONFIG_BLK_DEV_IDEDMA - case XFER_UDMA_5: /* can not do ultra mode 5 yet */ + case XFER_UDMA_5: mask = 0x80; break; case XFER_UDMA_4: mask = 0x90; break; case XFER_UDMA_3: mask = 0xA0; break; case XFER_UDMA_2: mask = (four_two) ? 0xB0 : 0xA0; break; @@ -417,20 +419,26 @@ byte unit = (drive->select.b.unit & 0x01); byte udma_66 = eighty_ninty_three(drive); + byte ultra_100 = 0; if (host_dev) { switch(host_dev->device) { + case PCI_DEVICE_ID_SI_730: + ultra_100 = 1; case PCI_DEVICE_ID_SI_530: case PCI_DEVICE_ID_SI_540: case PCI_DEVICE_ID_SI_620: case PCI_DEVICE_ID_SI_630: - four_two = 0x01; break; + four_two = 0x01; + break; default: four_two = 0x00; break; } } - if ((id->dma_ultra & 0x0010) && (ultra) && (udma_66) && (four_two)) + if ((id->dma_ultra & 0x0020) && (ultra) && (udma_66) && (four_two) && (ultra_100)) + speed = XFER_UDMA_5; + else if ((id->dma_ultra & 0x0010) && (ultra) && (udma_66) && (four_two)) speed = XFER_UDMA_4; else if ((id->dma_ultra & 0x0008) && (ultra) && (udma_66) && (four_two)) speed = XFER_UDMA_3; @@ -590,6 +598,7 @@ case PCI_DEVICE_ID_SI_540: case PCI_DEVICE_ID_SI_620: case PCI_DEVICE_ID_SI_630: + case PCI_DEVICE_ID_SI_730: ata66 = (reg48h & mask) ? 0 : 1; default: break; @@ -616,6 +625,7 @@ case PCI_DEVICE_ID_SI_540: case PCI_DEVICE_ID_SI_620: case PCI_DEVICE_ID_SI_630: + case PCI_DEVICE_ID_SI_730: case PCI_DEVICE_ID_SI_5600: case PCI_DEVICE_ID_SI_5597: case PCI_DEVICE_ID_SI_5591: diff -urN linux-2.4.0-prerelease-pristine/drivers/pci/pci.ids linux-2.4.0-prerelease/drivers/pci/pci.ids --- linux-2.4.0-prerelease-pristine/drivers/pci/pci.ids Sun Dec 31 20:58:44 2000 +++ linux-2.4.0-prerelease/drivers/pci/pci.ids Sun Dec 31 21:53:17 2000 @@ -734,6 +734,7 @@ 0601 85C601 0620 620 Host 0630 630 Host + 0730 730 Host 0900 SiS900 10/100 Ethernet 1039 0900 SiS900 10/100 Ethernet Adapter 3602 83C602 diff -urN linux-2.4.0-prerelease-pristine/include/linux/pci_ids.h linux-2.4.0-prerelease/include/linux/pci_ids.h --- linux-2.4.0-prerelease-pristine/include/linux/pci_ids.h Sun Dec 31 20:58:54 2000 +++ linux-2.4.0-prerelease/include/linux/pci_ids.h Sun Dec 31 21:53:17 2000 @@ -357,6 +357,7 @@ #define PCI_DEVICE_ID_SI_601 0x0601 #define PCI_DEVICE_ID_SI_620 0x0620 #define PCI_DEVICE_ID_SI_630 0x0630 +#define PCI_DEVICE_ID_SI_730 0x0730 #define PCI_DEVICE_ID_SI_630_VGA 0x6300 #define PCI_DEVICE_ID_SI_730_VGA 0x7300 #define PCI_DEVICE_ID_SI_5107 0x5107