diff -ruN linux-2.4.21-rc1.orig/drivers/ide/pci/serverworks.c linux-2.4.21-rc1/drivers/ide/pci/serverworks.c --- linux-2.4.21-rc1.orig/drivers/ide/pci/serverworks.c Thu Apr 24 14:16:28 2003 +++ linux-2.4.21-rc1/drivers/ide/pci/serverworks.c Thu Apr 24 14:41:26 2003 @@ -203,11 +203,22 @@ } #endif /* defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) */ +static int check_in_drive_lists (ide_drive_t *drive, const char **list) +{ + while (*list) + if (!strcmp(*list++, drive->id->model)) + return 1; + return 0; +} + static u8 svwks_ratemask (ide_drive_t *drive) { struct pci_dev *dev = HWIF(drive)->pci_dev; u8 mode; + if (!svwks_revision) + pci_read_config_byte(dev, PCI_REVISION_ID, &svwks_revision); + if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) { u32 reg = 0; if (isa_dev) @@ -221,13 +232,15 @@ /* Check the OSB4 DMA33 enable bit */ return ((reg & 0x00004000) == 0x00004000) ? 1 : 0; } else if (svwks_revision < SVWKS_CSB5_REVISION_NEW) { - return 1; + return 2; } else if (svwks_revision >= SVWKS_CSB5_REVISION_NEW) { u8 btr = 0; pci_read_config_byte(dev, 0x5A, &btr); - mode = btr; + mode = btr & 0x3; if (!eighty_ninty_three(drive)) mode = min(mode, (u8)1); + if (mode == 3 && check_in_drive_lists(drive, svwks_bad_ata100)) + mode = 2; } if (((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) || (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) && diff -ruN linux-2.4.21-rc1.orig/drivers/ide/pci/serverworks.h linux-2.4.21-rc1/drivers/ide/pci/serverworks.h --- linux-2.4.21-rc1.orig/drivers/ide/pci/serverworks.h Thu Apr 24 14:16:28 2003 +++ linux-2.4.21-rc1/drivers/ide/pci/serverworks.h Thu Apr 24 14:41:41 2003 @@ -11,6 +11,16 @@ #define SVWKS_CSB5_REVISION_NEW 0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */ #define SVWKS_CSB6_REVISION 0xa0 /* min PCI_REVISION_ID for UDMA4 (A1.0) */ +/* Seagate Barracuda ATA IV Family drives in UDMA mode 5 + * can overrun their FIFOs when used with the CSB5 */ +const char *svwks_bad_ata100[] = { + "ST320011A", + "ST340016A", + "ST360021A", + "ST380021A", + NULL +}; + #define DISPLAY_SVWKS_TIMINGS 1 #if defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS)