diff options
Diffstat (limited to 'drivers/ide/pci/cmd640.c')
-rw-r--r-- | drivers/ide/pci/cmd640.c | 131 |
1 files changed, 57 insertions, 74 deletions
diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c index cd1ba14984ab..1ad1e23e3105 100644 --- a/drivers/ide/pci/cmd640.c +++ b/drivers/ide/pci/cmd640.c | |||
@@ -521,6 +521,7 @@ static void program_drive_counts(ide_drive_t *drive, unsigned int index) | |||
521 | static void cmd640_set_mode(ide_drive_t *drive, unsigned int index, | 521 | static void cmd640_set_mode(ide_drive_t *drive, unsigned int index, |
522 | u8 pio_mode, unsigned int cycle_time) | 522 | u8 pio_mode, unsigned int cycle_time) |
523 | { | 523 | { |
524 | struct ide_timing *t; | ||
524 | int setup_time, active_time, recovery_time, clock_time; | 525 | int setup_time, active_time, recovery_time, clock_time; |
525 | u8 setup_count, active_count, recovery_count, recovery_count2, cycle_count; | 526 | u8 setup_count, active_count, recovery_count, recovery_count2, cycle_count; |
526 | int bus_speed; | 527 | int bus_speed; |
@@ -532,8 +533,11 @@ static void cmd640_set_mode(ide_drive_t *drive, unsigned int index, | |||
532 | 533 | ||
533 | if (pio_mode > 5) | 534 | if (pio_mode > 5) |
534 | pio_mode = 5; | 535 | pio_mode = 5; |
535 | setup_time = ide_pio_timings[pio_mode].setup_time; | 536 | |
536 | active_time = ide_pio_timings[pio_mode].active_time; | 537 | t = ide_timing_find_mode(XFER_PIO_0 + pio_mode); |
538 | setup_time = t->setup; | ||
539 | active_time = t->active; | ||
540 | |||
537 | recovery_time = cycle_time - (setup_time + active_time); | 541 | recovery_time = cycle_time - (setup_time + active_time); |
538 | clock_time = 1000 / bus_speed; | 542 | clock_time = 1000 / bus_speed; |
539 | cycle_count = DIV_ROUND_UP(cycle_time, clock_time); | 543 | cycle_count = DIV_ROUND_UP(cycle_time, clock_time); |
@@ -607,11 +611,40 @@ static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio) | |||
607 | 611 | ||
608 | display_clocks(index); | 612 | display_clocks(index); |
609 | } | 613 | } |
614 | #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ | ||
615 | |||
616 | static void cmd640_init_dev(ide_drive_t *drive) | ||
617 | { | ||
618 | unsigned int i = drive->hwif->channel * 2 + drive->select.b.unit; | ||
619 | |||
620 | #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED | ||
621 | /* | ||
622 | * Reset timing to the slowest speed and turn off prefetch. | ||
623 | * This way, the drive identify code has a better chance. | ||
624 | */ | ||
625 | setup_counts[i] = 4; /* max possible */ | ||
626 | active_counts[i] = 16; /* max possible */ | ||
627 | recovery_counts[i] = 16; /* max possible */ | ||
628 | program_drive_counts(drive, i); | ||
629 | set_prefetch_mode(drive, i, 0); | ||
630 | printk(KERN_INFO DRV_NAME ": drive%d timings/prefetch cleared\n", i); | ||
631 | #else | ||
632 | /* | ||
633 | * Set the drive unmask flags to match the prefetch setting. | ||
634 | */ | ||
635 | check_prefetch(drive, i); | ||
636 | printk(KERN_INFO DRV_NAME ": drive%d timings/prefetch(%s) preserved\n", | ||
637 | i, drive->no_io_32bit ? "off" : "on"); | ||
638 | #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ | ||
639 | } | ||
640 | |||
610 | 641 | ||
611 | static const struct ide_port_ops cmd640_port_ops = { | 642 | static const struct ide_port_ops cmd640_port_ops = { |
643 | .init_dev = cmd640_init_dev, | ||
644 | #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED | ||
612 | .set_pio_mode = cmd640_set_pio_mode, | 645 | .set_pio_mode = cmd640_set_pio_mode, |
646 | #endif | ||
613 | }; | 647 | }; |
614 | #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ | ||
615 | 648 | ||
616 | static int pci_conf1(void) | 649 | static int pci_conf1(void) |
617 | { | 650 | { |
@@ -654,10 +687,8 @@ static const struct ide_port_info cmd640_port_info __initdata = { | |||
654 | IDE_HFLAG_NO_DMA | | 687 | IDE_HFLAG_NO_DMA | |
655 | IDE_HFLAG_ABUSE_PREFETCH | | 688 | IDE_HFLAG_ABUSE_PREFETCH | |
656 | IDE_HFLAG_ABUSE_FAST_DEVSEL, | 689 | IDE_HFLAG_ABUSE_FAST_DEVSEL, |
657 | #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED | ||
658 | .port_ops = &cmd640_port_ops, | 690 | .port_ops = &cmd640_port_ops, |
659 | .pio_mask = ATA_PIO5, | 691 | .pio_mask = ATA_PIO5, |
660 | #endif | ||
661 | }; | 692 | }; |
662 | 693 | ||
663 | static int cmd640x_init_one(unsigned long base, unsigned long ctl) | 694 | static int cmd640x_init_one(unsigned long base, unsigned long ctl) |
@@ -683,12 +714,8 @@ static int cmd640x_init_one(unsigned long base, unsigned long ctl) | |||
683 | */ | 714 | */ |
684 | static int __init cmd640x_init(void) | 715 | static int __init cmd640x_init(void) |
685 | { | 716 | { |
686 | #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED | ||
687 | int second_port_toggled = 0; | ||
688 | #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ | ||
689 | int second_port_cmd640 = 0, rc; | 717 | int second_port_cmd640 = 0, rc; |
690 | const char *bus_type, *port2; | 718 | const char *bus_type, *port2; |
691 | unsigned int index; | ||
692 | u8 b, cfr; | 719 | u8 b, cfr; |
693 | u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; | 720 | u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; |
694 | hw_regs_t hw[2]; | 721 | hw_regs_t hw[2]; |
@@ -774,88 +801,44 @@ static int __init cmd640x_init(void) | |||
774 | put_cmd640_reg(CMDTIM, 0); | 801 | put_cmd640_reg(CMDTIM, 0); |
775 | put_cmd640_reg(BRST, 0x40); | 802 | put_cmd640_reg(BRST, 0x40); |
776 | 803 | ||
777 | cmd_hwif1 = ide_find_port(); | 804 | b = get_cmd640_reg(CNTRL); |
778 | 805 | ||
779 | /* | 806 | /* |
780 | * Try to enable the secondary interface, if not already enabled | 807 | * Try to enable the secondary interface, if not already enabled |
781 | */ | 808 | */ |
782 | if (cmd_hwif1 && | 809 | if (secondary_port_responding()) { |
783 | cmd_hwif1->drives[0].noprobe && cmd_hwif1->drives[1].noprobe) { | 810 | if ((b & CNTRL_ENA_2ND)) { |
784 | port2 = "not probed"; | 811 | second_port_cmd640 = 1; |
812 | port2 = "okay"; | ||
813 | } else if (cmd640_vlb) { | ||
814 | second_port_cmd640 = 1; | ||
815 | port2 = "alive"; | ||
816 | } else | ||
817 | port2 = "not cmd640"; | ||
785 | } else { | 818 | } else { |
786 | b = get_cmd640_reg(CNTRL); | 819 | put_cmd640_reg(CNTRL, b ^ CNTRL_ENA_2ND); /* toggle the bit */ |
787 | if (secondary_port_responding()) { | 820 | if (secondary_port_responding()) { |
788 | if ((b & CNTRL_ENA_2ND)) { | 821 | second_port_cmd640 = 1; |
789 | second_port_cmd640 = 1; | 822 | port2 = "enabled"; |
790 | port2 = "okay"; | ||
791 | } else if (cmd640_vlb) { | ||
792 | second_port_cmd640 = 1; | ||
793 | port2 = "alive"; | ||
794 | } else | ||
795 | port2 = "not cmd640"; | ||
796 | } else { | 823 | } else { |
797 | put_cmd640_reg(CNTRL, b ^ CNTRL_ENA_2ND); /* toggle the bit */ | 824 | put_cmd640_reg(CNTRL, b); /* restore original setting */ |
798 | if (secondary_port_responding()) { | 825 | port2 = "not responding"; |
799 | second_port_cmd640 = 1; | ||
800 | #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED | ||
801 | second_port_toggled = 1; | ||
802 | #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ | ||
803 | port2 = "enabled"; | ||
804 | } else { | ||
805 | put_cmd640_reg(CNTRL, b); /* restore original setting */ | ||
806 | port2 = "not responding"; | ||
807 | } | ||
808 | } | 826 | } |
809 | } | 827 | } |
810 | 828 | ||
811 | /* | 829 | /* |
812 | * Initialize data for secondary cmd640 port, if enabled | 830 | * Initialize data for secondary cmd640 port, if enabled |
813 | */ | 831 | */ |
814 | if (second_port_cmd640 && cmd_hwif1) { | 832 | if (second_port_cmd640) { |
815 | ide_init_port_hw(cmd_hwif1, &hw[1]); | 833 | cmd_hwif1 = ide_find_port(); |
816 | idx[1] = cmd_hwif1->index; | 834 | if (cmd_hwif1) { |
835 | ide_init_port_hw(cmd_hwif1, &hw[1]); | ||
836 | idx[1] = cmd_hwif1->index; | ||
837 | } | ||
817 | } | 838 | } |
818 | printk(KERN_INFO "cmd640: %sserialized, secondary interface %s\n", | 839 | printk(KERN_INFO "cmd640: %sserialized, secondary interface %s\n", |
819 | second_port_cmd640 ? "" : "not ", port2); | 840 | second_port_cmd640 ? "" : "not ", port2); |
820 | 841 | ||
821 | /* | ||
822 | * Establish initial timings/prefetch for all drives. | ||
823 | * Do not unnecessarily disturb any prior BIOS setup of these. | ||
824 | */ | ||
825 | for (index = 0; index < (2 + (second_port_cmd640 << 1)); index++) { | ||
826 | ide_drive_t *drive; | ||
827 | |||
828 | if (index > 1) { | ||
829 | if (cmd_hwif1 == NULL) | ||
830 | continue; | ||
831 | drive = &cmd_hwif1->drives[index & 1]; | ||
832 | } else { | ||
833 | if (cmd_hwif0 == NULL) | ||
834 | continue; | ||
835 | drive = &cmd_hwif0->drives[index & 1]; | ||
836 | } | ||
837 | |||
838 | #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED | ||
839 | /* | ||
840 | * Reset timing to the slowest speed and turn off prefetch. | ||
841 | * This way, the drive identify code has a better chance. | ||
842 | */ | ||
843 | setup_counts [index] = 4; /* max possible */ | ||
844 | active_counts [index] = 16; /* max possible */ | ||
845 | recovery_counts [index] = 16; /* max possible */ | ||
846 | program_drive_counts(drive, index); | ||
847 | set_prefetch_mode(drive, index, 0); | ||
848 | printk("cmd640: drive%d timings/prefetch cleared\n", index); | ||
849 | #else | ||
850 | /* | ||
851 | * Set the drive unmask flags to match the prefetch setting | ||
852 | */ | ||
853 | check_prefetch(drive, index); | ||
854 | printk("cmd640: drive%d timings/prefetch(%s) preserved\n", | ||
855 | index, drive->no_io_32bit ? "off" : "on"); | ||
856 | #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ | ||
857 | } | ||
858 | |||
859 | #ifdef CMD640_DUMP_REGS | 842 | #ifdef CMD640_DUMP_REGS |
860 | cmd640_dump_regs(); | 843 | cmd640_dump_regs(); |
861 | #endif | 844 | #endif |