ide.2.4.0-prerelease.1231.patch ./drivers/ide/cs5530.c ./drivers/ide/hpt366.c ./drivers/ide/ide-dma.c ./drivers/ide/ide-features.c ./drivers/ide/ide-pci.c ./drivers/ide/osb4.c ./drivers/ide/piix.c ./drivers/ide/sis5513.c ./drivers/pci/pci.ids ./include/linux/pci_ids.h Chipset fixes, validity bits fixed, dma-timeout fix noted but solution still in the works. ide.2.4.0-prerelease.cd.1231.patch : ./drivers/ide/ide-cd.c ./drivers/ide/ide-cd.h Adds ATAPI DVD-RAM native read/write mode for any FS. mke2fs -b 2048 /dev/hdc You must format to 2048 size blocks. UDF is an unknown. Regards, Andre Hedrick CTO Timpanogas Research Group EVP Linux Development, TRG Linux ATA Development
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 <asm/io.h> #include <asm/irq.h> +#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 <linux/stat.h> #include <linux/proc_fs.h> -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
diff -urN linux-2.4.0-prerelease/drivers/ide/ide-cd.c linux-2.4.0-prerelease.cd/drivers/ide/ide-cd.c --- linux-2.4.0-prerelease/drivers/ide/ide-cd.c Sun Dec 31 20:58:38 2000 +++ linux-2.4.0-prerelease.cd/drivers/ide/ide-cd.c Sun Dec 31 22:12:08 2000 @@ -513,9 +513,9 @@ struct request_sense *sense, struct packet_command *failed_command) { - struct cdrom_info *info = drive->driver_data; + struct cdrom_info *info = drive->driver_data; + struct packet_command *pc = &info->request_sense_pc; struct request *rq; - struct packet_command *pc = &info->request_sense_pc; if (sense == NULL) sense = &info->sense_data; @@ -541,13 +541,14 @@ struct request *rq = HWGROUP(drive)->rq; if (rq->cmd == REQUEST_SENSE_COMMAND && uptodate) { - struct packet_command *pc = (struct packet_command *)rq->buffer; + struct packet_command *pc = (struct packet_command *) rq->buffer; cdrom_analyze_sense_data(drive, (struct packet_command *) pc->sense, (struct request_sense *) (pc->buffer - pc->c[4])); } - if (rq->cmd == READ && !rq->current_nr_sectors) - uptodate = 1; + if (rq->cmd == READ || rq->cmd == WRITE) + if (!rq->current_nr_sectors) + uptodate = 1; ide_end_request (uptodate, HWGROUP(drive)); } @@ -628,7 +629,7 @@ if ((stat & ERR_STAT) != 0) cdrom_queue_request_sense(drive, sem, pc->sense, pc); } else { - /* Handle errors from READ requests. */ + /* Handle errors from READ and WRITE requests. */ if (sense_key == NOT_READY) { /* Tray open. */ @@ -679,12 +680,22 @@ struct packet_command *pc = (struct packet_command *) rq->buffer; unsigned long wait = 0; - /* blank and format can take an extremly long time to - * complete, if the IMMED bit was not set. + /* + * Some commands are *slow* and normally take a long time to + * complete. Usually we can use the ATAPI "disconnect" to bypass + * this, but not all commands/drives support that. Let + * ide_timer_expiry keep polling us for these. */ - if (pc->c[0] == GPCMD_BLANK || pc->c[0] == GPCMD_FORMAT_UNIT) - wait = 60*60*HZ; - + switch (pc->c[0]) { + case GPCMD_BLANK: + case GPCMD_FORMAT_UNIT: + case GPCMD_RESERVE_RZONE_TRACK: + wait = WAIT_CMD; + break; + default: + wait = 0; + break; + } return wait; } @@ -706,8 +717,15 @@ if (ide_wait_stat(&startstop, drive, 0, BUSY_STAT, WAIT_READY)) return startstop; - if (info->dma) - info->dma = !HWIF(drive)->dmaproc(ide_dma_read, drive); + if (info->dma) { + if (info->cmd == READ) { + info->dma = !HWIF(drive)->dmaproc(ide_dma_read, drive); + } else if (info->cmd == WRITE) { + info->dma = !HWIF(drive)->dmaproc(ide_dma_write, drive); + } else { + printk("ide-cd: DMA set, but not allowed\n"); + } + } /* Set up the controller registers. */ OUT_BYTE (info->dma, IDE_FEATURE_REG); @@ -737,11 +755,20 @@ by cdrom_start_packet_command. HANDLER is the interrupt handler to call when the command completes or there's data ready. */ +/* + * changed 5 parameters to 3 for dvd-ram + * struct packet_command *pc; now packet_command_t *pc; + */ +#undef CLASSIC_PACKET_STRUCT static ide_startstop_t cdrom_transfer_packet_command (ide_drive_t *drive, - unsigned char *cmd_buf, int cmd_len, - ide_handler_t *handler, - unsigned int timeout) + struct packet_command *pc, + ide_handler_t *handler) { +#ifdef CLASSIC_PACKET_STRUCT + unsigned char *cmd_buf = pc->c; + int cmd_len = sizeof(pc->c); + unsigned int timeout = pc->timeout; +#endif ide_startstop_t startstop; if (CDROM_CONFIG_FLAGS (drive)->drq_interrupt) { @@ -759,16 +786,25 @@ } /* Arm the interrupt handler. */ +#ifdef CLASSIC_PACKET_STRUCT + /* Arm the interrupt handler. */ ide_set_handler (drive, handler, timeout, cdrom_timer_expiry); /* Send the command to the device. */ atapi_output_bytes (drive, cmd_buf, cmd_len); +#else /* !CLASSIC_PACKET_STRUCT */ + /* Arm the interrupt handler. */ +// ide_set_handler (drive, handler, (unsigned int) pc->timeout, +cdrom_timer_expiry); + ide_set_handler (drive, handler, pc->timeout, cdrom_timer_expiry); + + /* Send the command to the device. */ +// atapi_output_bytes (drive, (void *)pc->c, (unsigned int) sizeof(pc->c)); + atapi_output_bytes (drive, pc->c, sizeof(pc->c)); +#endif /* CLASSIC_PACKET_STRUCT */ return ide_started; } - - /**************************************************************************** * Block read functions. */ @@ -1101,10 +1137,10 @@ pc.c[7] = (nframes >> 8); pc.c[8] = (nframes & 0xff); put_unaligned(cpu_to_be32(frame), (unsigned int *) &pc.c[2]); + pc.timeout = WAIT_CMD; /* Send the command to the drive and return. */ - return cdrom_transfer_packet_command(drive, pc.c, sizeof(pc.c), - &cdrom_read_intr, WAIT_CMD); + return cdrom_transfer_packet_command(drive, &pc, &cdrom_read_intr); } @@ -1153,7 +1189,9 @@ memset (&pc.c, 0, sizeof (pc.c)); pc.c[0] = GPCMD_SEEK; put_unaligned(cpu_to_be32(frame), (unsigned int *) &pc.c[2]); - return cdrom_transfer_packet_command(drive, pc.c, sizeof(pc.c), &cdrom_seek_intr, WAIT_CMD); + + pc.timeout = WAIT_CMD; + return cdrom_transfer_packet_command(drive, &pc, &cdrom_seek_intr); } static ide_startstop_t cdrom_start_seek (ide_drive_t *drive, unsigned int block) @@ -1161,6 +1199,7 @@ struct cdrom_info *info = drive->driver_data; info->dma = 0; + info->cmd = 0; info->start_seek = jiffies; return cdrom_start_packet_command (drive, 0, cdrom_start_seek_continuation); } @@ -1213,6 +1252,7 @@ else info->dma = 0; + info->cmd = READ; /* Start sending the read request to the drive. */ return cdrom_start_packet_command(drive, 32768, cdrom_start_read_continuation); } @@ -1332,8 +1372,7 @@ pc->timeout = WAIT_CMD; /* Send the command to the drive and return. */ - return cdrom_transfer_packet_command(drive, pc->c, sizeof(pc->c), - &cdrom_pc_intr, pc->timeout); + return cdrom_transfer_packet_command(drive, pc, &cdrom_pc_intr); } @@ -1345,6 +1384,7 @@ struct cdrom_info *info = drive->driver_data; info->dma = 0; + info->cmd = 0; pc->stat = 0; len = pc->buflen; @@ -1414,6 +1454,162 @@ return pc->stat ? -EIO : 0; } +/* + * Write handling + */ +static inline int cdrom_write_check_ireason(ide_drive_t *drive, int len, int ireason) +{ + /* Two notes about IDE interrupt reason here - 0 means that + * the drive wants to receive data from us, 2 means that + * the drive is expecting data from us. + */ + ireason &= 3; + + if (ireason == 2) { + /* Whoops... The drive wants to send data. */ + printk("%s: cdrom_write_intr: wrong transfer direction!\n", + drive->name); + + /* Throw some data at the drive so it doesn't hang + and quit this request. */ + while (len > 0) { + int dum = 0; + atapi_output_bytes(drive, &dum, sizeof(dum)); + len -= sizeof(dum); + } + } else { + /* Drive wants a command packet, or invalid ireason... */ + printk("%s: cdrom_write_intr: bad interrupt reason %d\n", + drive->name, ireason); + } + + cdrom_end_request(0, drive); + return 1; +} + +static ide_startstop_t cdrom_write_intr(ide_drive_t *drive) +{ + int stat, ireason, len, sectors_to_transfer; + struct cdrom_info *info = drive->driver_data; + int i, dma_error = 0, dma = info->dma; + ide_startstop_t startstop; + + struct request *rq = HWGROUP(drive)->rq; + + /* Check for errors. */ + if (dma) { + info->dma = 0; + if ((dma_error = HWIF(drive)->dmaproc(ide_dma_end, drive))) { + printk("ide-cd: write dma error\n"); + HWIF(drive)->dmaproc(ide_dma_off, drive); + } + } + + if (cdrom_decode_status(&startstop, drive, 0, &stat)) { + printk("ide-cd: write_intr decode_status bad\n"); + return startstop; + } + + if (dma) { + if (dma_error) + return ide_error(drive, "dma error", stat); + + rq = HWGROUP(drive)->rq; + for (i = rq->nr_sectors; i > 0;) { + i -= rq->current_nr_sectors; + ide_end_request(1, HWGROUP(drive)); + } + return ide_stopped; + } + + /* Read the interrupt reason and the transfer length. */ + ireason = IN_BYTE(IDE_NSECTOR_REG); + len = IN_BYTE(IDE_LCYL_REG) + 256 * IN_BYTE(IDE_HCYL_REG); + + /* If DRQ is clear, the command has completed. */ + if ((stat & DRQ_STAT) == 0) { + /* If we're not done writing, complain. + * Otherwise, complete the command normally. + */ + if (rq->current_nr_sectors > 0) { + printk("%s: write_intr: data underrun (%ld blocks)\n", + drive->name, rq->current_nr_sectors); + cdrom_end_request(0, drive); + } else + cdrom_end_request(1, drive); + return ide_stopped; + } + + /* Check that the drive is expecting to do the same thing we are. */ + if (ireason & 3) + if (cdrom_write_check_ireason(drive, len, ireason)) + return ide_stopped; + + /* The number of sectors we need to read from the drive. */ + sectors_to_transfer = len / SECTOR_SIZE; + + /* Now loop while we still have data to read from the drive. DMA + * transfers will already have been complete + */ + while (sectors_to_transfer > 0) { + /* If we've filled the present buffer but there's another + chained buffer after it, move on. */ + if (rq->current_nr_sectors == 0 && rq->nr_sectors > 0) + cdrom_end_request(1, drive); + + atapi_output_bytes(drive, rq->buffer, rq->current_nr_sectors); + rq->nr_sectors -= rq->current_nr_sectors; + rq->current_nr_sectors = 0; + rq->sector += rq->current_nr_sectors; + sectors_to_transfer -= rq->current_nr_sectors; + } + + /* arm handler */ + ide_set_handler(drive, &cdrom_write_intr, 5 * WAIT_CMD, NULL); + return ide_started; +} + +static ide_startstop_t cdrom_start_write_cont(ide_drive_t *drive) +{ + struct packet_command pc; /* packet_command_t pc; */ + struct request *rq = HWGROUP(drive)->rq; + unsigned nframes, frame; + + nframes = rq->nr_sectors >> 2; + frame = rq->sector >> 2; + + memset(&pc.c, 0, sizeof(pc.c)); + /* + * we might as well use WRITE_12, but none of the device I have + * support the streaming feature anyway, so who cares. + */ + pc.c[0] = GPCMD_WRITE_10; +#if 0 /* the immediate bit */ + pc.c[1] = 1 << 3; +#endif + pc.c[7] = (nframes >> 8) & 0xff; + pc.c[8] = nframes & 0xff; + put_unaligned(cpu_to_be32(frame), (unsigned int *)&pc.c[2]); + pc.timeout = 2 * WAIT_CMD; + + return cdrom_transfer_packet_command(drive, &pc, cdrom_write_intr); +} + +static ide_startstop_t cdrom_start_write(ide_drive_t *drive) +{ + struct cdrom_info *info = drive->driver_data; + + info->nsectors_buffered = 0; + + /* use dma, if possible. we don't need to check more, since we + * know that the transfer is always (at least!) 2KB aligned */ + info->dma = drive->using_dma ? 1 : 0; + info->cmd = WRITE; + + /* Start sending the read request to the drive. */ + return cdrom_start_packet_command(drive, 32768, cdrom_start_write_cont); +} + /**************************************************************************** * cdrom driver request routine. */ @@ -1424,6 +1620,7 @@ struct cdrom_info *info = drive->driver_data; switch (rq->cmd) { + case WRITE: case READ: { if (CDROM_CONFIG_FLAGS(drive)->seeking) { unsigned long elpased = jiffies - info->start_seek; @@ -1440,8 +1637,12 @@ } if (IDE_LARGE_SEEK(info->last_block, block, IDECD_SEEK_THRESHOLD) && drive->dsc_overlap) action = cdrom_start_seek (drive, block); - else - action = cdrom_start_read (drive, block); + else { + if (rq->cmd == READ) + action = cdrom_start_read(drive, block); + else + action = cdrom_start_write(drive); + } info->last_block = block; return action; } @@ -1457,7 +1658,7 @@ } default: { - printk("ide-cd: bad cmd %d\n", rq -> cmd); + printk("ide-cd: bad cmd %d\n", rq->cmd); cdrom_end_request(0, drive); return ide_stopped; } @@ -1849,8 +2050,9 @@ pc.c[2] = (speed >> 8) & 0xff; /* Read Drive speed in kbytes/second LSB */ pc.c[3] = speed & 0xff; - if ( CDROM_CONFIG_FLAGS(drive)->cd_r || - CDROM_CONFIG_FLAGS(drive)->cd_rw ) { + if (CDROM_CONFIG_FLAGS(drive)->cd_r || + CDROM_CONFIG_FLAGS(drive)->cd_rw || + CDROM_CONFIG_FLAGS(drive)->dvd_r) { /* Write Drive speed in kbytes/second MSB */ pc.c[4] = (speed >> 8) & 0xff; /* Write Drive speed in kbytes/second LSB */ @@ -1902,10 +2104,6 @@ return 0; } - - - - /* the generic packet interface to cdrom.c */ static int ide_cdrom_packet(struct cdrom_device_info *cdi, struct cdrom_generic_command *cgc) @@ -2441,6 +2639,9 @@ int minor = drive->select.b.unit << PARTN_BITS; int nslots; + /* + * default to read-only always and fix latter at the bottom + */ set_device_ro(MKDEV(HWIF(drive)->major, minor), 1); set_blocksize(MKDEV(HWIF(drive)->major, minor), CD_FRAMESIZE); @@ -2559,6 +2760,9 @@ info->start_seek = 0; nslots = ide_cdrom_probe_capabilities (drive); + + if (CDROM_CONFIG_FLAGS(drive)->dvd_ram) + set_device_ro(MKDEV(HWIF(drive)->major, minor), 0); if (ide_cdrom_register (drive, nslots)) { printk ("%s: ide_cdrom_setup failed to register device with the cdrom driver.\n", drive->name); diff -urN linux-2.4.0-prerelease/drivers/ide/ide-cd.h linux-2.4.0-prerelease.cd/drivers/ide/ide-cd.h --- linux-2.4.0-prerelease/drivers/ide/ide-cd.h Sun Dec 31 20:58:38 2000 +++ linux-2.4.0-prerelease.cd/drivers/ide/ide-cd.h Sun Dec 31 22:12:08 2000 @@ -478,6 +478,7 @@ struct request request_sense_request; struct packet_command request_sense_pc; int dma; + int cmd; unsigned long last_block; unsigned long start_seek; /* Buffer to hold mechanism status and changer slot table. */