Hi!

I have found a couple bugs in the VIA IDE kernel I'm now maintaining
that manifest themselves on hardware I don't have:

1) On old SWDMA devices the timing is programmed incorrectly. This will
   result in DMA timeouts or data corruption.

2) On UDMA devices used with vt82c596a (old buggy VIA MobileSouth), the
   chip will get confused, which will result in DMA timeouts and UDMA
   being disabled. No data corruption here, just very poor performance.

3) One extra sprintf was forgotten in the via_display_info function.
   This is harmless, but a bug nevertheless.

Here goes a detailed description of the patch that fixes the above three
bugs:

Chunk1:
        Changes version number
Chunk2:
        Removes UDMA66 unknown southbridge entry. We can't try to program
        unknown southbridges to UDMA66, because that can result in crashes
        (as shown by vt82c596a). UDMA33 should be safe, because the only
        southbridge that doesn't support it is vt82c586.
Chunk3:
        Fix SWDMA modes. By a typo there were 0's everywhere. This is
        important, without this fix SWDMA devices will be programmed
        incorrectly.
Chunk4:
        Change version number in /proc
Chunk5:
        Remove the sprintf().
Chunk6:
        Don't program UDMA66 enable bit on UDMA33 controllers. They *should*
        ignore it, but 596a doesn't, resulting in timeouts on boot. This is
        critical. Also don't program UDMA at all on the old vt82c586.
Chunk7:
        The correct way to check for 596a.
Chunk8:
        Remove the old check for 596a. It doesn't work, because the 596a doesn't
        ignore the UDMA66 bits as it should. Don't set UDMA66 on 596a at
        all, it causes crashes. Critical.

I hope this will get into test9-pre6, because otherwise it's quite
unusable for vt82c596a users.

TIA.

-- 
Vojtech Pavlik
SuSE Labs
--- linux-old/drivers/ide/via82cxxx.c   Wed Sep  6 17:07:56 2000
+++ linux/drivers/ide/via82cxxx.c       Wed Sep 20 23:33:08 2000
@@ -1,5 +1,5 @@
 /*
- * $Id: via82cxxx.c,v 2.1 2000/08/29 01:34:60 vojtech Exp $
+ * $Id: via82cxxx.c,v 2.1b 2000/09/20 23:19:60 vojtech Exp $
  *
  *  Copyright (c) 2000 Vojtech Pavlik
  *
@@ -97,7 +97,6 @@
        { "vt82c586b",  PCI_DEVICE_ID_VIA_82C586_0, XFER_UDMA_2 },
        { "vt82c586a",  PCI_DEVICE_ID_VIA_82C586_0, XFER_UDMA_2 },
        { "vt82c586",   PCI_DEVICE_ID_VIA_82C586_0, XFER_MW_DMA_2 },
-       { "Unknown SouthBridge",        0,          XFER_UDMA_4 },
        { "Unknown SouthBridge",        0,          XFER_UDMA_2 },
 };
 
@@ -140,8 +139,8 @@
        { XFER_MW_DMA_1,  "MDMA1", 45,  80,  50, 150,   0 },
        { XFER_MW_DMA_0,  "MDMA0", 60, 215, 215, 480,   0 },
 
-       { XFER_SW_DMA_0,  "SDMA0", 60, 120, 120, 240,   0 },
-       { XFER_SW_DMA_0,  "SDMA0", 90, 240, 240, 480,   0 },
+       { XFER_SW_DMA_2,  "SDMA2", 60, 120, 120, 240,   0 },
+       { XFER_SW_DMA_1,  "SDMA1", 90, 240, 240, 480,   0 },
        { XFER_SW_DMA_0,  "SDMA0",120, 480, 480, 960,   0 },
 
        { XFER_PIO_5,     "PIO5",  20,  50,  30, 100,   0 },
@@ -193,7 +192,7 @@
 
        via_print("----------VIA BusMastering IDE Configuration----------------");
 
-       via_print("Driver Version:                     2.1");
+       via_print("Driver Version:                     2.1b");
 
        pci_read_config_byte(isa_dev, PCI_REVISION_ID, &t);
        via_print("South Bridge:                       VIA %s rev %#x", 
via_isa_bridges[via_config].name, t);
@@ -213,9 +212,6 @@
        via_print("FIFO Output Data 1/2 Clock Advance: %s", (t & 16) ? "on" : "off" );
        via_print("BM IDE Status Register Read Retry:  %s", (t & 8) ? "on" : "off" );
 
-       pci_read_config_byte(dev, VIA_MISC_2, &t);
-       sprintf(p, "Interrupt Steering Swap:           %s", (t & 64) ? "on" : "off");
-
        pci_read_config_byte(dev, VIA_MISC_3, &t);
        via_print("Max DRDY Pulse Width:               %s%s", via_control3[(t & 
0x03)], (t & 0x03) ? "PCI clocks" : "");
 
@@ -337,15 +333,13 @@
  * UDMA cycle
  */
 
-       if (via_timing[i].udma) {
-               t = 0xe8;
-               if (via_isa_bridges[via_config].speed >= XFER_UDMA_4)
-                       t |= FIT(ENOUGH(via_timing[i].udma, T >> 1) - 2, 0, 7);
-               else
-                       t |= FIT(ENOUGH(via_timing[i].udma, T     ) - 2, 0, 3);
-       } else t = 0x0b;
+       switch(via_isa_bridges[via_config].speed) {
+               case XFER_UDMA_2: t = via_timing[i].udma ? (0x60 | 
+(FIT(via_timing[i].udma, 2, 5) - 2)) : 0x03; break;
+               case XFER_UDMA_4: t = via_timing[i].udma ? (0xe8 | 
+(FIT(via_timing[i].udma, 2, 9) - 2)) : 0x0f; break;
+        }
 
-       via_write_config_byte(dev, VIA_UDMA_TIMING + (3 - drive->dn), t);
+       if (via_isa_bridges[via_config].speed != XFER_MW_DMA_2)
+               via_write_config_byte(dev, VIA_UDMA_TIMING + (3 - drive->dn), t);
 
 /*
  * Drive init
@@ -511,6 +505,11 @@
                if (t < 0x20) via_config++;                     /* vt82c586 */
        }
 
+       if (via_isa_bridges[via_config].id == PCI_DEVICE_ID_VIA_82C596) {
+               pci_read_config_byte(isa, PCI_REVISION_ID, &t);
+               if (t < 0x10) via_config++;                     /* vt82c596a */
+       }
+
 /*
  * Check UDMA66 mode set by BIOS.
  */
@@ -530,13 +529,8 @@
 /*
  * Set UDMA66 double clock bits.
  */
-
-       pci_write_config_dword(dev, VIA_UDMA_TIMING, u | 0x80008);
-       pci_read_config_dword(dev, VIA_UDMA_TIMING, &u);
-
-       if ((via_isa_bridges[via_config].id == PCI_DEVICE_ID_VIA_82C596 || !isa)
-               && (u & 0x80008) != 0x80008)
-                       via_config++;                           /* vt82c596a / Unknown 
UDMA33 */
+       if (via_isa_bridges[via_config].speed == XFER_UDMA_4)
+               pci_write_config_dword(dev, VIA_UDMA_TIMING, u | 0x80008);
 
 /*
  * Set up FIFO, flush, prefetch and post-writes.

Reply via email to