fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / ide / pci / piix.c
index e9b83e1..c5ec6f1 100644 (file)
@@ -1,13 +1,14 @@
 /*
- *  linux/drivers/ide/pci/piix.c       Version 0.44    March 20, 2003
+ *  linux/drivers/ide/pci/piix.c       Version 0.45    May 12, 2006
  *
  *  Copyright (C) 1998-1999 Andrzej Krzysztofowicz, Author and Maintainer
  *  Copyright (C) 1998-2000 Andre Hedrick <andre@linux-ide.org>
  *  Copyright (C) 2003 Red Hat Inc <alan@redhat.com>
+ *  Copyright (C) 2006 MontaVista Software, Inc. <source@mvista.com>
  *
  *  May be copied or modified under the terms of the GNU General Public License
  *
- *  PIO mode setting function for Intel chipsets.  
+ *  PIO mode setting function for Intel chipsets.
  *  For use instead of BIOS settings.
  *
  * 40-41
@@ -25,7 +26,7 @@
  * sitre = word42 & 0x4000; secondary
  *
  * 44 8421|8421    hdd|hdb
- * 
+ *
  * 48 8421         hdd|hdc|hdb|hda udma enabled
  *
  *    0001         hda
@@ -90,7 +91,6 @@
  *     ICH3    errata #18      - Don't use native mode
  */
 
-#include <linux/config.h>
 #include <linux/types.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -222,35 +222,56 @@ static void piix_tune_drive (ide_drive_t *drive, u8 pio)
        unsigned long flags;
        u16 master_data;
        u8 slave_data;
+       static DEFINE_SPINLOCK(tune_lock);
+       int control = 0;
+
                                 /* ISP  RTC */
-       u8 timings[][2] = { { 0, 0 },
-                           { 0, 0 },
-                           { 1, 0 },
-                           { 2, 1 },
-                           { 2, 3 }, };
+       static const u8 timings[][2]= {
+                                       { 0, 0 },
+                                       { 0, 0 },
+                                       { 1, 0 },
+                                       { 2, 1 },
+                                       { 2, 3 }, };
 
        pio = ide_get_best_pio_mode(drive, pio, 5, NULL);
-       spin_lock_irqsave(&ide_lock, flags);
+
+       /*
+        * Master vs slave is synchronized above us but the slave register is
+        * shared by the two hwifs so the corner case of two slave timeouts in
+        * parallel must be locked.
+        */
+       spin_lock_irqsave(&tune_lock, flags);
        pci_read_config_word(dev, master_port, &master_data);
+
+       if (pio >= 2)
+               control |= 1;   /* Programmable timing on */
+       if (drive->media == ide_disk)
+               control |= 4;   /* Prefetch, post write */
+       if (pio >= 3)
+               control |= 2;   /* IORDY */
        if (is_slave) {
                master_data = master_data | 0x4000;
-               if (pio > 1)
+               if (pio > 1) {
                        /* enable PPE, IE and TIME */
-                       master_data = master_data | 0x0070;
+                       master_data = master_data | (control << 4);
+               } else {
+                       master_data &= ~0x0070;
+               }
                pci_read_config_byte(dev, slave_port, &slave_data);
                slave_data = slave_data & (hwif->channel ? 0x0f : 0xf0);
                slave_data = slave_data | (((timings[pio][0] << 2) | timings[pio][1]) << (hwif->channel ? 4 : 0));
        } else {
                master_data = master_data & 0xccf8;
-               if (pio > 1)
+               if (pio > 1) {
                        /* enable PPE, IE and TIME */
-                       master_data = master_data | 0x0007;
+                       master_data = master_data | control;
+               }
                master_data = master_data | (timings[pio][0] << 12) | (timings[pio][1] << 8);
        }
        pci_write_config_word(dev, master_port, master_data);
        if (is_slave)
                pci_write_config_byte(dev, slave_port, slave_data);
-       spin_unlock_irqrestore(&ide_lock, flags);
+       spin_unlock_irqrestore(&tune_lock, flags);
 }
 
 /**
@@ -332,57 +353,25 @@ static int piix_tune_chipset (ide_drive_t *drive, u8 xferspeed)
        return (ide_config_drive_speed(drive, speed));
 }
 
-/**
- *     piix_faulty_dma0                -       check for DMA0 errata
- *     @hwif: IDE interface to check
- *
- *     If an ICH/ICH0/ICH2 interface is is operating in multi-word
- *     DMA mode with 600nS cycle time the IDE PIO prefetch buffer will
- *     inadvertently provide an extra piece of secondary data to the primary
- *     device resulting in data corruption.
- *
- *     With such a device this test function returns true. This allows
- *     our tuning code to follow Intel recommendations and use PIO on
- *     such devices.
- */
-static int piix_faulty_dma0(ide_hwif_t *hwif)
-{
-       switch(hwif->pci_dev->device)
-       {
-               case PCI_DEVICE_ID_INTEL_82801AA_1:     /* ICH */
-               case PCI_DEVICE_ID_INTEL_82801AB_1:     /* ICH0 */
-               case PCI_DEVICE_ID_INTEL_82801BA_8:     /* ICH2 */
-               case PCI_DEVICE_ID_INTEL_82801BA_9:     /* ICH2 */
-                       return 1;
-       }
-       return 0;
-}
-
 /**
  *     piix_config_drive_for_dma       -       configure drive for DMA
  *     @drive: IDE drive to configure
  *
  *     Set up a PIIX interface channel for the best available speed.
- *     We prefer UDMA if it is available and then MWDMA. If DMA is 
- *     not available we switch to PIO and return 0. 
+ *     We prefer UDMA if it is available and then MWDMA.  If DMA is
+ *     not available we switch to PIO and return 0.
  */
  
 static int piix_config_drive_for_dma (ide_drive_t *drive)
 {
        u8 speed = ide_dma_speed(drive, piix_ratemask(drive));
-       
-       /* Some ICH devices cannot support DMA mode 0 */
-       if(speed == XFER_MW_DMA_0 && piix_faulty_dma0(HWIF(drive)))
-               speed = 0;
-
-       /* If no DMA speed was available or the chipset has DMA bugs
-          then disable DMA and use PIO */
-          
-       if (!speed || no_piix_dma) {
-               u8 tspeed = ide_get_best_pio_mode(drive, 255, 5, NULL);
-               speed = piix_dma_2_pio(XFER_PIO_0 + tspeed);
-       }
+
+       /*
+        * If no DMA speed was available or the chipset has DMA bugs
+        * then disable DMA and use PIO
+        */
+       if (!speed || no_piix_dma)
+               return 0;
 
        (void) piix_tune_chipset(drive, speed);
        return ide_dma_enable(drive);
@@ -405,17 +394,16 @@ static int piix_config_drive_xfer_rate (ide_drive_t *drive)
 
        if ((id->capability & 1) && drive->autodma) {
 
-               if (ide_use_dma(drive)) {
-                       if (piix_config_drive_for_dma(drive))
-                               return hwif->ide_dma_on(drive);
-               }
+               if (ide_use_dma(drive) && piix_config_drive_for_dma(drive))
+                       return hwif->ide_dma_on(drive);
 
                goto fast_ata_pio;
 
        } else if ((id->capability & 8) || (id->field_valid & 2)) {
 fast_ata_pio:
                /* Find best PIO mode. */
-               hwif->tuneproc(drive, 255);
+               (void) hwif->speedproc(drive, XFER_PIO_0 +
+                                      ide_get_best_pio_mode(drive, 255, 4, NULL));
                return hwif->ide_dma_off_quietly(drive);
        }
        /* IORDY not supported */
@@ -423,17 +411,14 @@ fast_ata_pio:
 }
 
 /**
- *     init_chipset_piix       -       set up the PIIX chipset
- *     @dev: PCI device to set up
- *     @name: Name of the device
+ *     piix_is_ichx    -       check if ICHx
+ *     @dev: PCI device to check
  *
- *     Initialize the PCI device as required. For the PIIX this turns
- *     out to be nice and simple
+ *     returns 1 if ICHx, 0 otherwise.
  */
-static unsigned int __devinit init_chipset_piix (struct pci_dev *dev, const char *name)
+static int piix_is_ichx(struct pci_dev *dev)
 {
-        switch(dev->device) {
+        switch (dev->device) {
                case PCI_DEVICE_ID_INTEL_82801EB_1:
                case PCI_DEVICE_ID_INTEL_82801AA_1:
                case PCI_DEVICE_ID_INTEL_82801AB_1:
@@ -451,18 +436,50 @@ static unsigned int __devinit init_chipset_piix (struct pci_dev *dev, const char
                case PCI_DEVICE_ID_INTEL_ICH7_21:
                case PCI_DEVICE_ID_INTEL_ESB2_18:
                case PCI_DEVICE_ID_INTEL_ICH8_6:
-               {
-                       unsigned int extra = 0;
-                       pci_read_config_dword(dev, 0x54, &extra);
-                       pci_write_config_dword(dev, 0x54, extra|0x400);
-               }
-               default:
-                       break;
+                       return 1;
        }
 
        return 0;
 }
 
+/**
+ *     init_chipset_piix       -       set up the PIIX chipset
+ *     @dev: PCI device to set up
+ *     @name: Name of the device
+ *
+ *     Initialize the PCI device as required. For the PIIX this turns
+ *     out to be nice and simple
+ */
+
+static unsigned int __devinit init_chipset_piix (struct pci_dev *dev, const char *name)
+{
+       if (piix_is_ichx(dev)) {
+               unsigned int extra = 0;
+               pci_read_config_dword(dev, 0x54, &extra);
+               pci_write_config_dword(dev, 0x54, extra|0x400);
+       }
+
+       return 0;
+}
+
+/**
+ *     piix_dma_clear_irq      -       clear BMDMA status
+ *     @drive: IDE drive to clear
+ *
+ *     Called from ide_intr() for PIO interrupts
+ *     to clear BMDMA status as needed by ICHx
+ */
+static void piix_dma_clear_irq(ide_drive_t *drive)
+{
+       ide_hwif_t *hwif = HWIF(drive);
+       u8 dma_stat;
+
+       /* clear the INTR & ERROR bits */
+       dma_stat = hwif->INB(hwif->dma_status);
+       /* Should we force the bit as well ? */
+       hwif->OUTB(dma_stat, hwif->dma_status);
+}
+
 /**
  *     init_hwif_piix          -       fill in the hwif for the PIIX
  *     @hwif: IDE interface
@@ -495,6 +512,10 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif)
        if (!hwif->dma_base)
                return;
 
+       /* ICHx need to clear the bmdma status for all interrupts */
+       if (piix_is_ichx(hwif->pci_dev))
+               hwif->ide_dma_clear_irq = &piix_dma_clear_irq;
+
        hwif->atapi_dma = 1;
        hwif->ultra_mask = 0x3f;
        hwif->mwdma_mask = 0x06;
@@ -608,7 +629,7 @@ static void __devinit piix_check_450nx(void)
        struct pci_dev *pdev = NULL;
        u16 cfg;
        u8 rev;
-       while((pdev=pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev))!=NULL)
+       while((pdev=pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX, pdev))!=NULL)
        {
                /* Look for 450NX PXB. Check for problem configurations
                   A PCI quirk checks bit 6 already */