aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ide/pci/cmd64x.c
diff options
context:
space:
mode:
authorSergei Shtylyov <sshtylyov@ru.mvista.com>2007-05-05 16:03:50 -0400
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2007-05-05 16:03:50 -0400
commit66602c83dcb6a5d82772d88ae7a32cd4a1213528 (patch)
tree5a282168207c87a1ff23175df3f2e10a822fd550 /drivers/ide/pci/cmd64x.c
parent5826b318aa02e81575c352ca26f00773c999795b (diff)
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: Sergei Shtylyov <sshtylyov@ru.mvista.com> Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide/pci/cmd64x.c')
-rw-r--r--drivers/ide/pci/cmd64x.c117
1 files changed, 69 insertions, 48 deletions
diff --git a/drivers/ide/pci/cmd64x.c b/drivers/ide/pci/cmd64x.c
index 24acddfc27bc..77f51ab6d439 100644
--- a/drivers/ide/pci/cmd64x.c
+++ b/drivers/ide/pci/cmd64x.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * linux/drivers/ide/pci/cmd64x.c Version 1.46 Mar 16, 2007 2 * linux/drivers/ide/pci/cmd64x.c Version 1.47 Mar 19, 2007
3 * 3 *
4 * cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines. 4 * cmd64x.c: Enable interrupts at initialization time on Ultra/PCI machines.
5 * Due to massive hardware bugs, UltraDMA is only supported 5 * 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 return -1; 425 return -1;
426} 426}
427 427
428static int cmd64x_alt_dma_status (struct pci_dev *dev) 428static int cmd648_ide_dma_end (ide_drive_t *drive)
429{ 429{
430 switch(dev->device) { 430 ide_hwif_t *hwif = HWIF(drive);
431 case PCI_DEVICE_ID_CMD_648: 431 int err = __ide_dma_end(drive);
432 case PCI_DEVICE_ID_CMD_649: 432 u8 irq_mask = hwif->channel ? MRDMODE_INTR_CH1 :
433 return 1; 433 MRDMODE_INTR_CH0;
434 default: 434 u8 mrdmode = inb(hwif->dma_master + 0x01);
435 break; 435
436 } 436 /* clear the interrupt bit */
437 return 0; 437 outb(mrdmode | irq_mask, hwif->dma_master + 0x01);
438
439 return err;
438} 440}
439 441
440static int cmd64x_ide_dma_end (ide_drive_t *drive) 442static int cmd64x_ide_dma_end (ide_drive_t *drive)
441{ 443{
442 u8 dma_stat = 0, dma_cmd = 0;
443 ide_hwif_t *hwif = HWIF(drive); 444 ide_hwif_t *hwif = HWIF(drive);
444 struct pci_dev *dev = hwif->pci_dev; 445 struct pci_dev *dev = hwif->pci_dev;
446 int irq_reg = hwif->channel ? ARTTIM23 : CFR;
447 u8 irq_mask = hwif->channel ? ARTTIM23_INTR_CH1 :
448 CFR_INTR_CH0;
449 u8 irq_stat = 0;
450 int err = __ide_dma_end(drive);
445 451
446 drive->waiting_for_dma = 0; 452 (void) pci_read_config_byte(dev, irq_reg, &irq_stat);
447 /* read DMA command state */ 453 /* clear the interrupt bit */
448 dma_cmd = inb(hwif->dma_command); 454 (void) pci_write_config_byte(dev, irq_reg, irq_stat | irq_mask);
449 /* stop DMA */ 455
450 outb(dma_cmd & ~1, hwif->dma_command); 456 return err;
451 /* get DMA status */ 457}
452 dma_stat = inb(hwif->dma_status); 458
453 /* clear the INTR & ERROR bits */ 459static int cmd648_ide_dma_test_irq (ide_drive_t *drive)
454 outb(dma_stat | 6, hwif->dma_status); 460{
455 if (cmd64x_alt_dma_status(dev)) { 461 ide_hwif_t *hwif = HWIF(drive);
456 u8 dma_intr = 0; 462 u8 irq_mask = hwif->channel ? MRDMODE_INTR_CH1 :
457 u8 dma_mask = (hwif->channel) ? ARTTIM23_INTR_CH1 : 463 MRDMODE_INTR_CH0;
458 CFR_INTR_CH0; 464 u8 dma_stat = inb(hwif->dma_status);
459 u8 dma_reg = (hwif->channel) ? ARTTIM2 : CFR; 465 u8 mrdmode = inb(hwif->dma_master + 0x01);
460 (void) pci_read_config_byte(dev, dma_reg, &dma_intr); 466
461 /* clear the INTR bit */ 467#ifdef DEBUG
462 (void) pci_write_config_byte(dev, dma_reg, dma_intr|dma_mask); 468 printk("%s: dma_stat: 0x%02x mrdmode: 0x%02x irq_mask: 0x%02x\n",
463 } 469 drive->name, dma_stat, mrdmode, irq_mask);
464 /* purge DMA mappings */ 470#endif
465 ide_destroy_dmatable(drive); 471 if (!(mrdmode & irq_mask))
466 /* verify good DMA status */ 472 return 0;
467 return (dma_stat & 7) != 4; 473
474 /* return 1 if INTR asserted */
475 if (dma_stat & 4)
476 return 1;
477
478 return 0;
468} 479}
469 480
470static int cmd64x_ide_dma_test_irq (ide_drive_t *drive) 481static int cmd64x_ide_dma_test_irq (ide_drive_t *drive)
471{ 482{
472 ide_hwif_t *hwif = HWIF(drive); 483 ide_hwif_t *hwif = HWIF(drive);
473 struct pci_dev *dev = hwif->pci_dev; 484 struct pci_dev *dev = hwif->pci_dev;
474 u8 irq_reg = hwif->channel ? ARTTIM23 : CFR; 485 int irq_reg = hwif->channel ? ARTTIM23 : CFR;
475 u8 irq_stat = 0, mask = hwif->channel ? ARTTIM23_INTR_CH1 : CFR_INTR_CH0; 486 u8 irq_mask = hwif->channel ? ARTTIM23_INTR_CH1 :
476 u8 dma_stat = inb(hwif->dma_status); 487 CFR_INTR_CH0;
488 u8 dma_stat = inb(hwif->dma_status);
489 u8 irq_stat = 0;
477 490
478 (void) pci_read_config_byte(dev, irq_reg, &irq_stat); 491 (void) pci_read_config_byte(dev, irq_reg, &irq_stat);
479 492
480#ifdef DEBUG 493#ifdef DEBUG
481 printk("%s: dma_stat: 0x%02x irq_stat: 0x%02x mask: 0x%02x\n", 494 printk("%s: dma_stat: 0x%02x irq_stat: 0x%02x irq_mask: 0x%02x\n",
482 drive->name, dma_stat, irq_stat, mask); 495 drive->name, dma_stat, irq_stat, irq_mask);
483#endif 496#endif
484 if (!(irq_stat & mask)) 497 if (!(irq_stat & irq_mask))
485 return 0; 498 return 0;
486 499
487 /* return 1 if INTR asserted */ 500 /* return 1 if INTR asserted */
488 if ((dma_stat & 4) == 4) 501 if (dma_stat & 4)
489 return 1; 502 return 1;
490 503
491 return 0; 504 return 0;
@@ -645,17 +658,25 @@ static void __devinit init_hwif_cmd64x(ide_hwif_t *hwif)
645 if (!(hwif->udma_four)) 658 if (!(hwif->udma_four))
646 hwif->udma_four = ata66_cmd64x(hwif); 659 hwif->udma_four = ata66_cmd64x(hwif);
647 660
648 if (dev->device == PCI_DEVICE_ID_CMD_646) { 661 switch(dev->device) {
662 case PCI_DEVICE_ID_CMD_648:
663 case PCI_DEVICE_ID_CMD_649:
664 alt_irq_bits:
665 hwif->ide_dma_end = &cmd648_ide_dma_end;
666 hwif->ide_dma_test_irq = &cmd648_ide_dma_test_irq;
667 break;
668 case PCI_DEVICE_ID_CMD_646:
649 hwif->chipset = ide_cmd646; 669 hwif->chipset = ide_cmd646;
650 if (class_rev == 0x01) { 670 if (class_rev == 0x01) {
651 hwif->ide_dma_end = &cmd646_1_ide_dma_end; 671 hwif->ide_dma_end = &cmd646_1_ide_dma_end;
652 } else { 672 break;
653 hwif->ide_dma_end = &cmd64x_ide_dma_end; 673 } else if (class_rev >= 0x03)
654 hwif->ide_dma_test_irq = &cmd64x_ide_dma_test_irq; 674 goto alt_irq_bits;
655 } 675 /* fall thru */
656 } else { 676 default:
657 hwif->ide_dma_end = &cmd64x_ide_dma_end; 677 hwif->ide_dma_end = &cmd64x_ide_dma_end;
658 hwif->ide_dma_test_irq = &cmd64x_ide_dma_test_irq; 678 hwif->ide_dma_test_irq = &cmd64x_ide_dma_test_irq;
679 break;
659 } 680 }
660 681
661 682