diff options
-rw-r--r-- | drivers/ide/pci/cmd640.c | 67 |
1 files changed, 27 insertions, 40 deletions
diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c index a1cfe033a55f..3303ffb327a7 100644 --- a/drivers/ide/pci/cmd640.c +++ b/drivers/ide/pci/cmd640.c | |||
@@ -185,7 +185,6 @@ static DEFINE_SPINLOCK(cmd640_lock); | |||
185 | * These are initialized to point at the devices we control | 185 | * These are initialized to point at the devices we control |
186 | */ | 186 | */ |
187 | static ide_hwif_t *cmd_hwif0, *cmd_hwif1; | 187 | static ide_hwif_t *cmd_hwif0, *cmd_hwif1; |
188 | static ide_drive_t *cmd_drives[4]; | ||
189 | 188 | ||
190 | /* | 189 | /* |
191 | * Interface to access cmd640x registers | 190 | * Interface to access cmd640x registers |
@@ -386,9 +385,8 @@ static void cmd640_dump_regs (void) | |||
386 | * Check whether prefetch is on for a drive, | 385 | * Check whether prefetch is on for a drive, |
387 | * and initialize the unmask flags for safe operation. | 386 | * and initialize the unmask flags for safe operation. |
388 | */ | 387 | */ |
389 | static void __init check_prefetch (unsigned int index) | 388 | static void __init check_prefetch(ide_drive_t *drive, unsigned int index) |
390 | { | 389 | { |
391 | ide_drive_t *drive = cmd_drives[index]; | ||
392 | u8 b = get_cmd640_reg(prefetch_regs[index]); | 390 | u8 b = get_cmd640_reg(prefetch_regs[index]); |
393 | 391 | ||
394 | if (b & prefetch_masks[index]) { /* is prefetch off? */ | 392 | if (b & prefetch_masks[index]) { /* is prefetch off? */ |
@@ -404,28 +402,13 @@ static void __init check_prefetch (unsigned int index) | |||
404 | } | 402 | } |
405 | } | 403 | } |
406 | 404 | ||
407 | /* | ||
408 | * Figure out which devices we control | ||
409 | */ | ||
410 | static void __init setup_device_ptrs (void) | ||
411 | { | ||
412 | cmd_hwif0 = &ide_hwifs[0]; | ||
413 | cmd_hwif1 = &ide_hwifs[1]; | ||
414 | |||
415 | cmd_drives[0] = &cmd_hwif0->drives[0]; | ||
416 | cmd_drives[1] = &cmd_hwif0->drives[1]; | ||
417 | cmd_drives[2] = &cmd_hwif1->drives[0]; | ||
418 | cmd_drives[3] = &cmd_hwif1->drives[1]; | ||
419 | } | ||
420 | |||
421 | #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED | 405 | #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED |
422 | 406 | ||
423 | /* | 407 | /* |
424 | * Sets prefetch mode for a drive. | 408 | * Sets prefetch mode for a drive. |
425 | */ | 409 | */ |
426 | static void set_prefetch_mode (unsigned int index, int mode) | 410 | static void set_prefetch_mode(ide_drive_t *drive, unsigned int index, int mode) |
427 | { | 411 | { |
428 | ide_drive_t *drive = cmd_drives[index]; | ||
429 | unsigned long flags; | 412 | unsigned long flags; |
430 | int reg = prefetch_regs[index]; | 413 | int reg = prefetch_regs[index]; |
431 | u8 b; | 414 | u8 b; |
@@ -508,7 +491,7 @@ static void __init retrieve_drive_counts (unsigned int index) | |||
508 | * This routine writes the prepared setup/active/recovery counts | 491 | * This routine writes the prepared setup/active/recovery counts |
509 | * for a drive into the cmd640 chipset registers to active them. | 492 | * for a drive into the cmd640 chipset registers to active them. |
510 | */ | 493 | */ |
511 | static void program_drive_counts (unsigned int index) | 494 | static void program_drive_counts(ide_drive_t *drive, unsigned int index) |
512 | { | 495 | { |
513 | unsigned long flags; | 496 | unsigned long flags; |
514 | u8 setup_count = setup_counts[index]; | 497 | u8 setup_count = setup_counts[index]; |
@@ -522,8 +505,11 @@ static void program_drive_counts (unsigned int index) | |||
522 | * so we merge the timings, using the slowest value for each timing. | 505 | * so we merge the timings, using the slowest value for each timing. |
523 | */ | 506 | */ |
524 | if (index > 1) { | 507 | if (index > 1) { |
525 | unsigned int mate; | 508 | ide_hwif_t *hwif = drive->hwif; |
526 | if (cmd_drives[mate = index ^ 1]->present) { | 509 | ide_drive_t *peer = &hwif->drives[!drive->select.b.unit]; |
510 | unsigned int mate = index ^ 1; | ||
511 | |||
512 | if (peer->present) { | ||
527 | if (setup_count < setup_counts[mate]) | 513 | if (setup_count < setup_counts[mate]) |
528 | setup_count = setup_counts[mate]; | 514 | setup_count = setup_counts[mate]; |
529 | if (active_count < active_counts[mate]) | 515 | if (active_count < active_counts[mate]) |
@@ -562,7 +548,8 @@ static void program_drive_counts (unsigned int index) | |||
562 | /* | 548 | /* |
563 | * Set a specific pio_mode for a drive | 549 | * Set a specific pio_mode for a drive |
564 | */ | 550 | */ |
565 | static void cmd640_set_mode (unsigned int index, u8 pio_mode, unsigned int cycle_time) | 551 | static void cmd640_set_mode(ide_drive_t *drive, unsigned int index, |
552 | u8 pio_mode, unsigned int cycle_time) | ||
566 | { | 553 | { |
567 | int setup_time, active_time, recovery_time, clock_time; | 554 | int setup_time, active_time, recovery_time, clock_time; |
568 | u8 setup_count, active_count, recovery_count, recovery_count2, cycle_count; | 555 | u8 setup_count, active_count, recovery_count, recovery_count2, cycle_count; |
@@ -611,7 +598,7 @@ static void cmd640_set_mode (unsigned int index, u8 pio_mode, unsigned int cycle | |||
611 | * 1) this is the wrong place to do it (proper is do_special() in ide.c) | 598 | * 1) this is the wrong place to do it (proper is do_special() in ide.c) |
612 | * 2) in practice this is rarely, if ever, necessary | 599 | * 2) in practice this is rarely, if ever, necessary |
613 | */ | 600 | */ |
614 | program_drive_counts (index); | 601 | program_drive_counts(drive, index); |
615 | } | 602 | } |
616 | 603 | ||
617 | static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio) | 604 | static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio) |
@@ -619,13 +606,6 @@ static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio) | |||
619 | unsigned int index = 0, cycle_time; | 606 | unsigned int index = 0, cycle_time; |
620 | u8 b; | 607 | u8 b; |
621 | 608 | ||
622 | while (drive != cmd_drives[index]) { | ||
623 | if (++index > 3) { | ||
624 | printk(KERN_ERR "%s: bad news in %s\n", | ||
625 | drive->name, __FUNCTION__); | ||
626 | return; | ||
627 | } | ||
628 | } | ||
629 | switch (pio) { | 609 | switch (pio) { |
630 | case 6: /* set fast-devsel off */ | 610 | case 6: /* set fast-devsel off */ |
631 | case 7: /* set fast-devsel on */ | 611 | case 7: /* set fast-devsel on */ |
@@ -638,13 +618,13 @@ static void cmd640_set_pio_mode(ide_drive_t *drive, const u8 pio) | |||
638 | 618 | ||
639 | case 8: /* set prefetch off */ | 619 | case 8: /* set prefetch off */ |
640 | case 9: /* set prefetch on */ | 620 | case 9: /* set prefetch on */ |
641 | set_prefetch_mode(index, pio & 1); | 621 | set_prefetch_mode(drive, index, pio & 1); |
642 | printk("%s: %sabled cmd640 prefetch\n", drive->name, (pio & 1) ? "en" : "dis"); | 622 | printk("%s: %sabled cmd640 prefetch\n", drive->name, (pio & 1) ? "en" : "dis"); |
643 | return; | 623 | return; |
644 | } | 624 | } |
645 | 625 | ||
646 | cycle_time = ide_pio_cycle_time(drive, pio); | 626 | cycle_time = ide_pio_cycle_time(drive, pio); |
647 | cmd640_set_mode(index, pio, cycle_time); | 627 | cmd640_set_mode(drive, index, pio, cycle_time); |
648 | 628 | ||
649 | printk("%s: selected cmd640 PIO mode%d (%dns)", | 629 | printk("%s: selected cmd640 PIO mode%d (%dns)", |
650 | drive->name, pio, cycle_time); | 630 | drive->name, pio, cycle_time); |
@@ -764,11 +744,12 @@ static int __init cmd640x_init(void) | |||
764 | printk(KERN_INFO "cmd640: buggy cmd640%c interface on %s, config=0x%02x" | 744 | printk(KERN_INFO "cmd640: buggy cmd640%c interface on %s, config=0x%02x" |
765 | "\n", 'a' + cmd640_chip_version - 1, bus_type, cfr); | 745 | "\n", 'a' + cmd640_chip_version - 1, bus_type, cfr); |
766 | 746 | ||
747 | cmd_hwif0 = &ide_hwifs[0]; | ||
748 | cmd_hwif1 = &ide_hwifs[1]; | ||
749 | |||
767 | /* | 750 | /* |
768 | * Initialize data for primary port | 751 | * Initialize data for primary port |
769 | */ | 752 | */ |
770 | setup_device_ptrs (); | ||
771 | |||
772 | ide_init_port_hw(cmd_hwif0, &hw[0]); | 753 | ide_init_port_hw(cmd_hwif0, &hw[0]); |
773 | #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED | 754 | #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED |
774 | cmd_hwif0->set_pio_mode = &cmd640_set_pio_mode; | 755 | cmd_hwif0->set_pio_mode = &cmd640_set_pio_mode; |
@@ -836,7 +817,13 @@ static int __init cmd640x_init(void) | |||
836 | * Do not unnecessarily disturb any prior BIOS setup of these. | 817 | * Do not unnecessarily disturb any prior BIOS setup of these. |
837 | */ | 818 | */ |
838 | for (index = 0; index < (2 + (second_port_cmd640 << 1)); index++) { | 819 | for (index = 0; index < (2 + (second_port_cmd640 << 1)); index++) { |
839 | ide_drive_t *drive = cmd_drives[index]; | 820 | ide_drive_t *drive; |
821 | |||
822 | if (index > 1) | ||
823 | drive = &cmd_hwif1->drives[index & 1]; | ||
824 | else | ||
825 | drive = &cmd_hwif0->drives[index & 1]; | ||
826 | |||
840 | #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED | 827 | #ifdef CONFIG_BLK_DEV_CMD640_ENHANCED |
841 | if (drive->autotune || ((index > 1) && second_port_toggled)) { | 828 | if (drive->autotune || ((index > 1) && second_port_toggled)) { |
842 | /* | 829 | /* |
@@ -846,8 +833,8 @@ static int __init cmd640x_init(void) | |||
846 | setup_counts [index] = 4; /* max possible */ | 833 | setup_counts [index] = 4; /* max possible */ |
847 | active_counts [index] = 16; /* max possible */ | 834 | active_counts [index] = 16; /* max possible */ |
848 | recovery_counts [index] = 16; /* max possible */ | 835 | recovery_counts [index] = 16; /* max possible */ |
849 | program_drive_counts (index); | 836 | program_drive_counts(drive, index); |
850 | set_prefetch_mode (index, 0); | 837 | set_prefetch_mode(drive, index, 0); |
851 | printk("cmd640: drive%d timings/prefetch cleared\n", index); | 838 | printk("cmd640: drive%d timings/prefetch cleared\n", index); |
852 | } else { | 839 | } else { |
853 | /* | 840 | /* |
@@ -855,7 +842,7 @@ static int __init cmd640x_init(void) | |||
855 | * This preserves any prior BIOS setup. | 842 | * This preserves any prior BIOS setup. |
856 | */ | 843 | */ |
857 | retrieve_drive_counts (index); | 844 | retrieve_drive_counts (index); |
858 | check_prefetch (index); | 845 | check_prefetch(drive, index); |
859 | printk("cmd640: drive%d timings/prefetch(%s) preserved", | 846 | printk("cmd640: drive%d timings/prefetch(%s) preserved", |
860 | index, drive->no_io_32bit ? "off" : "on"); | 847 | index, drive->no_io_32bit ? "off" : "on"); |
861 | display_clocks(index); | 848 | display_clocks(index); |
@@ -864,7 +851,7 @@ static int __init cmd640x_init(void) | |||
864 | /* | 851 | /* |
865 | * Set the drive unmask flags to match the prefetch setting | 852 | * Set the drive unmask flags to match the prefetch setting |
866 | */ | 853 | */ |
867 | check_prefetch (index); | 854 | check_prefetch(drive, index); |
868 | printk("cmd640: drive%d timings/prefetch(%s) preserved\n", | 855 | printk("cmd640: drive%d timings/prefetch(%s) preserved\n", |
869 | index, drive->no_io_32bit ? "off" : "on"); | 856 | index, drive->no_io_32bit ? "off" : "on"); |
870 | #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ | 857 | #endif /* CONFIG_BLK_DEV_CMD640_ENHANCED */ |