Commit 66602c83 authored by Sergei Shtylyov's avatar Sergei Shtylyov Committed by Bartlomiej Zolnierkiewicz

cmd64x: use interrupt status from MRDMODE register (take 2)

Fold the parts of the ide_dma_end() methods identical to __ide_dma_end() into a
mere call to it.
Start using faster versions of the ide_dma_end() and ide_dma_test_irq() methods
for the PCI0646U and newer chips that have the duplicate interrupt status bits
in the I/O mapped MRDMODE register, determing what methods to use at the driver
load time. Do some cleanup/renaming in the "old" ide_dma_test_irq() method too.
Signed-off-by: default avatarSergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: default avatarBartlomiej Zolnierkiewicz <bzolnier@gmail.com>
parent 5826b318
/* /*
* linux/drivers/ide/pci/cmd64x.c Version 1.46 Mar 16, 2007 * linux/drivers/ide/pci/cmd64x.c Version 1.47 Mar 19, 2007
* *
* cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines. * cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines.
* Due to massive hardware bugs, UltraDMA is only supported * Due to massive hardware bugs, UltraDMA is only supported
...@@ -425,67 +425,80 @@ static int cmd64x_config_drive_for_dma (ide_drive_t *drive) ...@@ -425,67 +425,80 @@ static int cmd64x_config_drive_for_dma (ide_drive_t *drive)
return -1; return -1;
} }
static int cmd64x_alt_dma_status (struct pci_dev *dev) static int cmd648_ide_dma_end (ide_drive_t *drive)
{ {
switch(dev->device) { ide_hwif_t *hwif = HWIF(drive);
case PCI_DEVICE_ID_CMD_648: int err = __ide_dma_end(drive);
case PCI_DEVICE_ID_CMD_649: u8 irq_mask = hwif->channel ? MRDMODE_INTR_CH1 :
return 1; MRDMODE_INTR_CH0;
default: u8 mrdmode = inb(hwif->dma_master + 0x01);
break;
} /* clear the interrupt bit */
return 0; outb(mrdmode | irq_mask, hwif->dma_master + 0x01);
return err;
} }
static int cmd64x_ide_dma_end (ide_drive_t *drive) static int cmd64x_ide_dma_end (ide_drive_t *drive)
{ {
u8 dma_stat = 0, dma_cmd = 0;
ide_hwif_t *hwif = HWIF(drive); ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev; struct pci_dev *dev = hwif->pci_dev;
int irq_reg = hwif->channel ? ARTTIM23 : CFR;
u8 irq_mask = hwif->channel ? ARTTIM23_INTR_CH1 :
CFR_INTR_CH0;
u8 irq_stat = 0;
int err = __ide_dma_end(drive);
drive->waiting_for_dma = 0; (void) pci_read_config_byte(dev, irq_reg, &irq_stat);
/* read DMA command state */ /* clear the interrupt bit */
dma_cmd = inb(hwif->dma_command); (void) pci_write_config_byte(dev, irq_reg, irq_stat | irq_mask);
/* stop DMA */
outb(dma_cmd & ~1, hwif->dma_command); return err;
/* get DMA status */ }
dma_stat = inb(hwif->dma_status);
/* clear the INTR & ERROR bits */ static int cmd648_ide_dma_test_irq (ide_drive_t *drive)
outb(dma_stat | 6, hwif->dma_status); {
if (cmd64x_alt_dma_status(dev)) { ide_hwif_t *hwif = HWIF(drive);
u8 dma_intr = 0; u8 irq_mask = hwif->channel ? MRDMODE_INTR_CH1 :
u8 dma_mask = (hwif->channel) ? ARTTIM23_INTR_CH1 : MRDMODE_INTR_CH0;
CFR_INTR_CH0; u8 dma_stat = inb(hwif->dma_status);
u8 dma_reg = (hwif->channel) ? ARTTIM2 : CFR; u8 mrdmode = inb(hwif->dma_master + 0x01);
(void) pci_read_config_byte(dev, dma_reg, &dma_intr);
/* clear the INTR bit */ #ifdef DEBUG
(void) pci_write_config_byte(dev, dma_reg, dma_intr|dma_mask); printk("%s: dma_stat: 0x%02x mrdmode: 0x%02x irq_mask: 0x%02x\n",
} drive->name, dma_stat, mrdmode, irq_mask);
/* purge DMA mappings */ #endif
ide_destroy_dmatable(drive); if (!(mrdmode & irq_mask))
/* verify good DMA status */ return 0;
return (dma_stat & 7) != 4;
/* return 1 if INTR asserted */
if (dma_stat & 4)
return 1;
return 0;
} }
static int cmd64x_ide_dma_test_irq (ide_drive_t *drive) static int cmd64x_ide_dma_test_irq (ide_drive_t *drive)
{ {
ide_hwif_t *hwif = HWIF(drive); ide_hwif_t *hwif = HWIF(drive);
struct pci_dev *dev = hwif->pci_dev; struct pci_dev *dev = hwif->pci_dev;
u8 irq_reg = hwif->channel ? ARTTIM23 : CFR; int irq_reg = hwif->channel ? ARTTIM23 : CFR;
u8 irq_stat = 0, mask = hwif->channel ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0; u8 irq_mask = hwif->channel ? ARTTIM23_INTR_CH1 :
u8 dma_stat = inb(hwif->dma_status); CFR_INTR_CH0;
u8 dma_stat = inb(hwif->dma_status);
u8 irq_stat = 0;
(void) pci_read_config_byte(dev, irq_reg, &irq_stat); (void) pci_read_config_byte(dev, irq_reg, &irq_stat);
#ifdef DEBUG #ifdef DEBUG
printk("%s: dma_stat: 0x%02x irq_stat: 0x%02x mask: 0x%02x\n", printk("%s: dma_stat: 0x%02x irq_stat: 0x%02x irq_mask: 0x%02x\n",
drive->name, dma_stat, irq_stat, mask); drive->name, dma_stat, irq_stat, irq_mask);
#endif #endif
if (!(irq_stat & mask)) if (!(irq_stat & irq_mask))
return 0; return 0;
/* return 1 if INTR asserted */ /* return 1 if INTR asserted */
if ((dma_stat & 4) == 4) if (dma_stat & 4)
return 1; return 1;
return 0; return 0;
...@@ -645,17 +658,25 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif) ...@@ -645,17 +658,25 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
if (!(hwif->udma_four)) if (!(hwif->udma_four))
hwif->udma_four = ata66_cmd64x(hwif); hwif->udma_four = ata66_cmd64x(hwif);
if (dev->device == PCI_DEVICE_ID_CMD_646) { switch(dev->device) {
case PCI_DEVICE_ID_CMD_648:
case PCI_DEVICE_ID_CMD_649:
alt_irq_bits:
hwif->ide_dma_end = &cmd648_ide_dma_end;
hwif->ide_dma_test_irq = &cmd648_ide_dma_test_irq;
break;
case PCI_DEVICE_ID_CMD_646:
hwif->chipset = ide_cmd646; hwif->chipset = ide_cmd646;
if (class_rev == 0x01) { if (class_rev == 0x01) {
hwif->ide_dma_end = &cmd646_1_ide_dma_end; hwif->ide_dma_end = &cmd646_1_ide_dma_end;
} else { break;
hwif->ide_dma_end = &cmd64x_ide_dma_end; } else if (class_rev >= 0x03)
hwif->ide_dma_test_irq = &cmd64x_ide_dma_test_irq; goto alt_irq_bits;
} /* fall thru */
} else { default:
hwif->ide_dma_end = &cmd64x_ide_dma_end; hwif->ide_dma_end = &cmd64x_ide_dma_end;
hwif->ide_dma_test_irq = &cmd64x_ide_dma_test_irq; hwif->ide_dma_test_irq = &cmd64x_ide_dma_test_irq;
break;
} }
......
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