summaryrefslogtreecommitdiffstats
path: root/drivers/ide/pci/piix.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ide/pci/piix.c')
-rw-r--r--drivers/ide/pci/piix.c119
1 files changed, 71 insertions, 48 deletions
diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
index 52cfc2ac22c1..569822f4cf55 100644
--- a/drivers/ide/pci/piix.c
+++ b/drivers/ide/pci/piix.c
@@ -369,7 +369,7 @@ static int piix_config_drive_for_dma (ide_drive_t *drive)
* If no DMA speed was available or the chipset has DMA bugs
* then disable DMA and use PIO
*/
- if (!speed || no_piix_dma)
+ if (!speed)
return 0;
(void) piix_tune_chipset(drive, speed);
@@ -386,41 +386,28 @@ static int piix_config_drive_for_dma (ide_drive_t *drive)
static int piix_config_drive_xfer_rate (ide_drive_t *drive)
{
- ide_hwif_t *hwif = HWIF(drive);
- struct hd_driveid *id = drive->id;
-
drive->init_speed = 0;
- if ((id->capability & 1) && drive->autodma) {
-
- if (ide_use_dma(drive) && piix_config_drive_for_dma(drive))
- return hwif->ide_dma_on(drive);
-
- goto fast_ata_pio;
+ if (ide_use_dma(drive) && piix_config_drive_for_dma(drive))
+ return 0;
- } else if ((id->capability & 8) || (id->field_valid & 2)) {
-fast_ata_pio:
+ if (ide_use_fast_pio(drive))
/* Find best PIO mode. */
- (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 */
- return 0;
+ piix_tune_chipset(drive, XFER_PIO_0 +
+ ide_get_best_pio_mode(drive, 255, 4, NULL));
+
+ return -1;
}
/**
- * 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:
@@ -438,19 +425,61 @@ 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);
+}
+
+static int __devinit piix_cable_detect(ide_hwif_t *hwif)
+{
+ struct pci_dev *dev = hwif->pci_dev;
+ u8 reg54h = 0, mask = hwif->channel ? 0xc0 : 0x30;
+
+ pci_read_config_byte(dev, 0x54, &reg54h);
+
+ return (reg54h & mask) ? 1 : 0;
+}
+
+/**
* init_hwif_piix - fill in the hwif for the PIIX
* @hwif: IDE interface
*
@@ -460,9 +489,6 @@ static unsigned int __devinit init_chipset_piix (struct pci_dev *dev, const char
static void __devinit init_hwif_piix(ide_hwif_t *hwif)
{
- u8 reg54h = 0, reg55h = 0, ata66 = 0;
- u8 mask = hwif->channel ? 0xc0 : 0x30;
-
#ifndef CONFIG_IA64
if (!hwif->irq)
hwif->irq = hwif->channel ? 15 : 14;
@@ -472,10 +498,6 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif)
/* This is a painful system best to let it self tune for now */
return;
}
- /* ESB2 appears to generate spurious DMA interrupts in PIO mode
- when in native mode */
- if (hwif->pci_dev->device == PCI_DEVICE_ID_INTEL_ESB2_18)
- hwif->atapi_irq_bogon = 1;
hwif->autodma = 0;
hwif->tuneproc = &piix_tune_drive;
@@ -486,15 +508,16 @@ 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;
hwif->swdma_mask = 0x04;
switch(hwif->pci_dev->device) {
- case PCI_DEVICE_ID_INTEL_82371MX:
- hwif->mwdma_mask = 0x80;
- hwif->swdma_mask = 0x80;
case PCI_DEVICE_ID_INTEL_82371FB_0:
case PCI_DEVICE_ID_INTEL_82371FB_1:
case PCI_DEVICE_ID_INTEL_82371SB_1:
@@ -507,14 +530,14 @@ static void __devinit init_hwif_piix(ide_hwif_t *hwif)
hwif->ultra_mask = 0x07;
break;
default:
- pci_read_config_byte(hwif->pci_dev, 0x54, &reg54h);
- pci_read_config_byte(hwif->pci_dev, 0x55, &reg55h);
- ata66 = (reg54h & mask) ? 1 : 0;
+ if (!hwif->udma_four)
+ hwif->udma_four = piix_cable_detect(hwif);
break;
}
- if (!(hwif->udma_four))
- hwif->udma_four = ata66;
+ if (no_piix_dma)
+ hwif->ultra_mask = hwif->mwdma_mask = hwif->swdma_mask = 0;
+
hwif->ide_dma_check = &piix_config_drive_xfer_rate;
if (!noautodma)
hwif->autodma = 1;
OpenPOWER on IntegriCloud