Commit 17e71a0b authored by Bartlomiej Zolnierkiewicz's avatar Bartlomiej Zolnierkiewicz Committed by Linus Torvalds

[PATCH] ServerWorks IDE driver update

ServerWorks CSB5 IDE fixes (from 2.4 patches by Duncan Laurie)

- blacklist drives overrunning their FIFOs in UDMA5/6 modes
- add PCI quirk (CSB5 IDE doesn't fully support native mode)

plus sync driver with 2.4 version.
parent 7b4e8ef0
/* /*
* linux/drivers/ide/pci/serverworks.c Version 0.7 10 Sept 2002 * linux/drivers/ide/pci/serverworks.c Version 0.8 25 Ebr 2003
* *
* Copyright (C) 1998-2000 Michel Aubry * Copyright (C) 1998-2000 Michel Aubry
* Copyright (C) 1998-2000 Andrzej Krzysztofowicz * Copyright (C) 1998-2000 Andrzej Krzysztofowicz
...@@ -203,11 +203,22 @@ static int svwks_get_info (char *buffer, char **addr, off_t offset, int count) ...@@ -203,11 +203,22 @@ static int svwks_get_info (char *buffer, char **addr, off_t offset, int count)
} }
#endif /* defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) */ #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) static u8 svwks_ratemask (ide_drive_t *drive)
{ {
struct pci_dev *dev = HWIF(drive)->pci_dev; struct pci_dev *dev = HWIF(drive)->pci_dev;
u8 mode; u8 mode;
if (!svwks_revision)
pci_read_config_byte(dev, PCI_REVISION_ID, &svwks_revision);
if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) { if (dev->device == PCI_DEVICE_ID_SERVERWORKS_OSB4IDE) {
u32 reg = 0; u32 reg = 0;
if (isa_dev) if (isa_dev)
...@@ -225,9 +236,13 @@ static u8 svwks_ratemask (ide_drive_t *drive) ...@@ -225,9 +236,13 @@ static u8 svwks_ratemask (ide_drive_t *drive)
} else if (svwks_revision >= SVWKS_CSB5_REVISION_NEW) { } else if (svwks_revision >= SVWKS_CSB5_REVISION_NEW) {
u8 btr = 0; u8 btr = 0;
pci_read_config_byte(dev, 0x5A, &btr); pci_read_config_byte(dev, 0x5A, &btr);
mode = btr; mode = btr & 0x3;
if (!eighty_ninty_three(drive)) if (!eighty_ninty_three(drive))
mode = min(mode, (u8)1); mode = min(mode, (u8)1);
/* If someone decides to do UDMA133 on CSB5 the same
issue will bite so be inclusive */
if (mode > 2 && check_in_drive_lists(drive, svwks_bad_ata100))
mode = 2;
} }
if (((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) || if (((dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE) ||
(dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) && (dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB6IDE2)) &&
...@@ -419,13 +434,10 @@ static void config_chipset_for_pio (ide_drive_t *drive) ...@@ -419,13 +434,10 @@ static void config_chipset_for_pio (ide_drive_t *drive)
static void svwks_tune_drive (ide_drive_t *drive, u8 pio) static void svwks_tune_drive (ide_drive_t *drive, u8 pio)
{ {
/* Tune to desired value or to "best". We must not adjust if(pio == 255)
"best" when we adjust from pio numbers to rate values! */
if(pio != 255)
(void) svwks_tune_chipset(drive, (XFER_PIO_0 + pio));
else
(void) svwks_tune_chipset(drive, 255); (void) svwks_tune_chipset(drive, 255);
else
(void) svwks_tune_chipset(drive, (XFER_PIO_0 + pio));
} }
static int config_chipset_for_dma (ide_drive_t *drive) static int config_chipset_for_dma (ide_drive_t *drive)
...@@ -446,7 +458,7 @@ static int svwks_config_drive_xfer_rate (ide_drive_t *drive) ...@@ -446,7 +458,7 @@ static int svwks_config_drive_xfer_rate (ide_drive_t *drive)
drive->init_speed = 0; drive->init_speed = 0;
if (id && (id->capability & 1) && drive->autodma) { if ((id->capability & 1) && drive->autodma) {
/* Consult the list of known "bad" drives */ /* Consult the list of known "bad" drives */
if (hwif->ide_dma_bad_drive(drive)) if (hwif->ide_dma_bad_drive(drive))
goto fast_ata_pio; goto fast_ata_pio;
...@@ -483,28 +495,10 @@ static int svwks_config_drive_xfer_rate (ide_drive_t *drive) ...@@ -483,28 +495,10 @@ static int svwks_config_drive_xfer_rate (ide_drive_t *drive)
return hwif->ide_dma_on(drive); return hwif->ide_dma_on(drive);
} }
/* This can go soon */
static int svwks_ide_dma_end (ide_drive_t *drive) static int svwks_ide_dma_end (ide_drive_t *drive)
{ {
/*
* We never place the OSB4 into a UDMA mode with a disk
* medium, that means the UDMA "all my data is 4 byte shifted"
* problem cannot occur.
*/
#if 0
ide_hwif_t *hwif = HWIF(drive);
u8 dma_stat = hwif->INB(hwif->dma_status);
if ((dma_stat & 1) && drive->media == ide_disk)
{
printk(KERN_CRIT "Serverworks OSB4 in impossible state.\n");
printk(KERN_CRIT "Disable UDMA or if you are using Seagate then try switching disk types\n");
printk(KERN_CRIT "on this controller. Please report this event to osb4-bug@ide.cabal.tm\n");
/* Panic might sys_sync -> death by corrupt disk */
printk(KERN_CRIT "OSB4: continuing might cause disk corruption.\n");
while(1)
cpu_relax();
}
#endif
return __ide_dma_end(drive); return __ide_dma_end(drive);
} }
...@@ -630,8 +624,6 @@ static unsigned int __init init_chipset_svwks (struct pci_dev *dev, const char * ...@@ -630,8 +624,6 @@ static unsigned int __init init_chipset_svwks (struct pci_dev *dev, const char *
static unsigned int __init ata66_svwks_svwks (ide_hwif_t *hwif) static unsigned int __init ata66_svwks_svwks (ide_hwif_t *hwif)
{ {
// struct pci_dev *dev = hwif->pci_dev;
// return 0;
return 1; return 1;
} }
......
...@@ -11,6 +11,16 @@ ...@@ -11,6 +11,16 @@
#define SVWKS_CSB5_REVISION_NEW 0x92 /* min PCI_REVISION_ID for UDMA5 (A2.0) */ #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) */ #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 #define DISPLAY_SVWKS_TIMINGS 1
#if defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS) #if defined(DISPLAY_SVWKS_TIMINGS) && defined(CONFIG_PROC_FS)
......
...@@ -635,7 +635,22 @@ static void __init quirk_via_bridge(struct pci_dev *pdev) ...@@ -635,7 +635,22 @@ static void __init quirk_via_bridge(struct pci_dev *pdev)
if(pdev->devfn == 0) if(pdev->devfn == 0)
interrupt_line_quirk = 1; interrupt_line_quirk = 1;
} }
/*
* Serverworks CSB5 IDE does not fully support native mode
*/
static void __init quirk_svwks_csb5ide(struct pci_dev *pdev)
{
u8 prog;
pci_read_config_byte(pdev, PCI_CLASS_PROG, &prog);
if (prog & 5) {
prog &= ~5;
pdev->class &= ~5;
pci_write_config_byte(pdev, PCI_CLASS_PROG, prog);
/* need to re-assign BARs for compat mode */
quirk_ide_bases(pdev);
}
}
/* This was originally an Alpha specific thing, but it really fits here. /* This was originally an Alpha specific thing, but it really fits here.
* The i82375 PCI/EISA bridge appears as non-classified. Fix that. * The i82375 PCI/EISA bridge appears as non-classified. Fix that.
...@@ -812,7 +827,9 @@ static struct pci_fixup pci_fixups[] __devinitdata = { ...@@ -812,7 +827,9 @@ static struct pci_fixup pci_fixups[] __devinitdata = {
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_TOSHIBA, 0x605, quirk_transparent_bridge }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_TOSHIBA, 0x605, quirk_transparent_bridge },
{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master }, { PCI_FIXUP_FINAL, PCI_VENDOR_ID_CYRIX, PCI_DEVICE_ID_CYRIX_PCI_MASTER, quirk_mediagx_master },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5IDE, quirk_svwks_csb5ide },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375, quirk_eisa_bridge }, { PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375, quirk_eisa_bridge },
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment