diff options
author | Sergei Shtylyov <sshtylyov@ru.mvista.com> | 2007-05-05 16:03:50 -0400 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2007-05-05 16:03:50 -0400 |
commit | 66602c83dcb6a5d82772d88ae7a32cd4a1213528 (patch) | |
tree | 5a282168207c87a1ff23175df3f2e10a822fd550 /drivers/ide/pci/cmd64x.c | |
parent | 5826b318aa02e81575c352ca26f00773c999795b (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.c | 117 |
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 | ||
428 | static int cmd64x_alt_dma_status (struct pci_dev *dev) | 428 | static 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 | ||
440 | static int cmd64x_ide_dma_end (ide_drive_t *drive) | 442 | static 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 */ | 459 | static 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 | ||
470 | static int cmd64x_ide_dma_test_irq (ide_drive_t *drive) | 481 | static 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 | ||