--- linux/drivers/block/ide-timing.h~ Mon Apr 2 17:26:03 2001 +++ linux/drivers/block/ide-timing.h Mon Apr 2 18:04:57 2001 @@ -277,7 +277,7 @@ return 0; } -#define VOJTECH_TIMER 0 +#define VOJTECH_TIMER 1 #if VOJTECH_TIMER #ifdef __i386__ --- linux/drivers/block/via82cxxx.c~ Mon Apr 2 15:55:32 2001 +++ linux/drivers/block/via82cxxx.c Mon Apr 2 16:36:00 2001 @@ -1,5 +1,5 @@ /* - * $Id: via82cxxx.c,v 3.20 2001/01/27 10:13:60 vojtech Exp $ + * $Id: via82cxxx.c,v 4.2 2001/02/11 20:40:60 vojtech Exp $ * * Copyright (c) 2000-2001 Vojtech Pavlik * @@ -89,10 +89,11 @@ #define VIA_UDMA_33 0x01 #define VIA_UDMA_66 0x02 #define VIA_UDMA_100 0x03 -#define VIA_BAD_PREQ 0x10 -#define VIA_BAD_CLK66 0x20 -#define VIA_SET_FIFO 0x40 -#define VIA_SET_THRESH 0x80 +#define VIA_BAD_PREQ 0x10 /* Crashes if PREQ# till DDACK# set */ +#define VIA_BAD_CLK66 0x20 /* 66 MHz clock doesn't work correctly */ +#define VIA_SET_FIFO 0x40 /* Needs to have FIFO split set */ +#define VIA_SET_THRESH 0x80 /* Needs to have FIFO thresholds set */ +#define VIA_BAD_PIO 0x80 /* Always uses 25 PCICLK/xfer regardles of PIO mode */ /* * VIA SouthBridge chips. @@ -107,10 +108,10 @@ } via_isa_bridges[] = { { "vt8233", PCI_DEVICE_ID_VIA_8233_0, 0x00, 0x2f, VIA_UDMA_100 }, { "vt8231", PCI_DEVICE_ID_VIA_8231, 0x00, 0x2f, VIA_UDMA_66 }, - { "vt82c686b", PCI_DEVICE_ID_VIA_82C686, 0x40, 0x4f, VIA_UDMA_100 }, + { "vt82c686b", PCI_DEVICE_ID_VIA_82C686, 0x40, 0x4f, VIA_UDMA_100 | VIA_BAD_PIO }, { "vt82c686a", PCI_DEVICE_ID_VIA_82C686, 0x10, 0x2f, VIA_UDMA_66 }, - { "vt82c686", PCI_DEVICE_ID_VIA_82C686, 0x00, 0x0f, VIA_UDMA_66 }, - { "vt82c596b", PCI_DEVICE_ID_VIA_82C596_0, 0x10, 0x2f, VIA_UDMA_66 }, + { "vt82c686", PCI_DEVICE_ID_VIA_82C686, 0x00, 0x0f, VIA_UDMA_33 | VIA_BAD_CLK66 }, + { "vt82c596b", PCI_DEVICE_ID_VIA_82C596_0, 0x12, 0x2f, VIA_UDMA_66 }, { "vt82c596a", PCI_DEVICE_ID_VIA_82C596_0, 0x00, 0x0f, VIA_UDMA_33 | VIA_BAD_CLK66 }, { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x40, 0x4f, VIA_UDMA_33 | VIA_SET_FIFO | VIA_BAD_PREQ }, { "vt82c586b", PCI_DEVICE_ID_VIA_82C586_0, 0x30, 0x3f, VIA_UDMA_33 | VIA_SET_FIFO }, @@ -135,9 +136,9 @@ int via_proc, via_base; static struct pci_dev *bmide_dev, *isa_dev; -static int via_get_info(char *, char **, off_t, int, int); extern int (*via_display_info)(char *, char **, off_t, int, int); /* ide-proc.c */ +static char *via_dma[] = { "MWDMA16", "UDMA33", "UDMA66", "UDMA100" }; static char *via_control3[] = { "No limit", "64", "128", "192" }; #define via_print(format, arg...) p += sprintf(p, format "\n" , ## arg) @@ -147,7 +148,7 @@ static int via_get_info(char *buffer, char **addr, off_t offset, int count, int dummy) { short speed[4], cycle[4], setup[4], active[4], - recover[4], uen[4], udma[4], active8b[4], recover8b[4]; + recover[4], uen[4], udma[4], umul[4], active8b[4], recover8b[4]; struct pci_dev *dev = bmide_dev; unsigned int v, u, i; unsigned short c, w; @@ -156,12 +157,13 @@ via_print("----------VIA BusMastering IDE Configuration----------------"); - via_print("Driver Version: 3.20"); + via_print("Driver Version: 4.1"); via_print("South Bridge: VIA %s", via_config->name); pci_read_config_byte(isa_dev, PCI_REVISION_ID, &t); pci_read_config_byte(dev, PCI_REVISION_ID, &x); via_print("Revision: ISA %#x IDE %#x", t, x); + via_print("Highest DMA rate: %s", via_dma[via_config->flags & VIA_UDMA]); via_print("BM-DMA base: %#x", via_base); via_print("PCI clock: %dMHz", via_clock); @@ -190,6 +192,9 @@ via_print("Cable Type: %10s%20s", (via_80w & 1) ? "80w" : "40w", (via_80w & 2) ? "80w" : "40w"); + if (!via_clock) + return p - buffer; + via_print("-------------------drive0----drive1----drive2----drive3-----"); pci_read_config_byte(dev, VIA_ADDRESS_SETUP, &t); @@ -207,18 +213,32 @@ active[i] = ((v >> (((3 - i) << 3) + 4)) & 0xf) + 1; recover[i] = ((v >> ((3 - i) << 3)) & 0xf) + 1; udma[i] = ((u >> ((3 - i) << 3)) & 0x7) + 2; + umul[i] = ((u >> (((3 - i) & 2) << 3)) & 0x8) ? 1 : 2; + uen[i] = (u >> ((3 - i) << 3)) & 0x20; - if ((via_config->flags & VIA_UDMA) == VIA_UDMA_100) { + speed[i] = 20 * via_clock / (active[i] + recover[i]); + cycle[i] = 1000 / via_clock * (active[i] + recover[i]); + + if (!uen[i]) + continue; + + switch (via_config->flags & VIA_UDMA) { + + case VIA_UDMA_100: speed[i] = 2000 / udma[i]; cycle[i] = 10 * udma[i]; - continue; - } + break; - uen[i] = (u >> ((3 - i) << 3)) & 0x20; - udma[i] *= ((u >> (((3 - i) & 2) << 3)) & 0x8) ? 1 : 2; + case VIA_UDMA_66: + speed[i] = 40 * via_clock / (udma[i] * umul[i]); + cycle[i] = 500 / via_clock * (udma[i] * umul[i]); + break; - speed[i] = 40 * via_clock / (uen[i] ? udma[i] : (active[i] + recover[i]) * 2); - cycle[i] = 1000 / via_clock * (uen[i] ? udma[i] : (active[i] + recover[i]) * 2) / 2; + case VIA_UDMA_33: + speed[i] = 20 * via_clock / udma[i]; + cycle[i] = 1000 / via_clock * udma[i]; + break; + } } via_print_drive("Transfer Mode: ", "%10s", @@ -266,6 +286,46 @@ } /* + * via_calibrate_pci_clock() calibrates the PCI clock using IDENTIFY transfers + * in PIO mode. It does this by measuring the time it takes to transfer the sector + * at PIO_SLOW speed. + */ + +static int via_calibrate_pci_clock(ide_drive_t *drive) +{ +#ifdef VIA83CXXX_EXPERIMENTAL + struct ide_timing t; + int time, clock, speed; + + printk(KERN_INFO "VP_IDE: Calibrating PCI clock ..."); + + clock = ide_timing_calibrate_timer(); + ide_timing_compute(drive, XFER_PIO_SLOW, &t, 20, 10); /* Assume 50 MHz PCI max */ + + via_set_speed(HWIF(drive)->pci_dev, drive->dn, &t); + if ((time = ide_timing_measure_xfer(drive)) <= 0) { /* Measurement failed */ + printk(" failed.\n"); + return system_bus_clock(); + } + + speed = clock * 256 / time * /* 256 words, 32 PCI clocks per word */ + (via_config->flags & VIA_BAD_PIO ? 26 : 32); /* PIO programming doesn't work */ + + printk(" %d.%02d MHz\n", speed / 1000, speed % 1000 / 10); + + return (speed + 500) / 1000; +#else + unsigned int clock = system_bus_clock(); + if (clock < 20 || clock > 50) { + printk(KERN_WARNING "VP_IDE: User given PCI clock speed impossible (%d), using 33 MHz instead.\n", clock); + printk(KERN_WARNING "VP_IDE: Use ide0=ata66 if you want to force UDMA66/UDMA100.\n"); + clock = 33; + } + return clock; +#endif +} + +/* * via_set_drive() computes timing values configures the drive and * the chipset to a desired transfer mode. It also can be called * by upper layers. @@ -277,6 +337,9 @@ struct ide_timing t, p; int T, UT; + if (!via_clock) + via_clock = via_calibrate_pci_clock(drive); + if (speed != XFER_PIO_SLOW && speed != drive->current_speed) if (ide_config_drive_speed(drive, speed)) printk(KERN_WARNING "ide%d: Drive %d didn't accept speed setting. Oh, well.\n", @@ -343,8 +406,8 @@ short speed = ide_find_best_mode(drive, XFER_PIO | XFER_EPIO | XFER_SWDMA | XFER_MWDMA | (via_config->flags & VIA_UDMA ? XFER_UDMA : 0) | - (w80 && (via_config->flags & VIA_UDMA) == VIA_UDMA_66 ? XFER_UDMA_66 : 0) | - (w80 && (via_config->flags & VIA_UDMA) == VIA_UDMA_100 ? XFER_UDMA_100 : 0)); + (w80 && (via_config->flags & VIA_UDMA) >= VIA_UDMA_66 ? XFER_UDMA_66 : 0) | + (w80 && (via_config->flags & VIA_UDMA) >= VIA_UDMA_100 ? XFER_UDMA_100 : 0)); func = ((speed & XFER_MODE) != XFER_PIO) ? ide_dma_on : ide_dma_off_quietly; @@ -409,7 +472,7 @@ } if (via_config->flags & VIA_BAD_CLK66) { /* Disable Clk66 */ - pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); /* Would cause trouble on 596a */ + pci_read_config_dword(dev, VIA_UDMA_TIMING, &u); /* Would cause CRC errors */ pci_write_config_dword(dev, VIA_UDMA_TIMING, u & ~0x80008); } @@ -427,7 +490,7 @@ pci_read_config_byte(dev, VIA_FIFO_CONFIG, &t); if (via_config->flags & VIA_BAD_PREQ) /* Disable PREQ# till DDACK# */ - t &= 0x7f; /* Would crash on 586b rev 41 */ + t &= 0x7f; /* Would crash */ if (via_config->flags & VIA_SET_FIFO) { /* Fix FIFO split between channels */ t &= (t & 0x9f); @@ -444,27 +507,12 @@ pci_write_config_byte(dev, VIA_FIFO_CONFIG, t); /* - * Determine system bus clock. - */ - - via_clock = system_bus_clock(); - if (via_clock < 20 || via_clock > 50) { - printk(KERN_WARNING "VP_IDE: User given PCI clock speed impossible (%d), using 33 MHz instead.\n", via_clock); - printk(KERN_WARNING "VP_IDE: Use ide0=ata66 if you want to force UDMA66/UDMA100.\n"); - via_clock = 33; - } - -/* * Print the boot message. */ pci_read_config_byte(isa, PCI_REVISION_ID, &t); printk(KERN_INFO "VP_IDE: VIA %s (rev %02x) IDE %s controller on pci%02d:%02d.%d\n", - via_config->name, t, - (via_config->flags & VIA_UDMA) == VIA_UDMA_100 ? "UDMA100" : - (via_config->flags & VIA_UDMA) == VIA_UDMA_66 ? "UDMA66" : - (via_config->flags & VIA_UDMA) == VIA_UDMA_33 ? "UDMA33" : "MWDMA16", - dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); + via_config->name, t, via_dma[via_config->flags & VIA_UDMA], dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); /* * Setup /proc/ide/via entry.