diff options
Diffstat (limited to 'firmware/drivers')
-rw-r--r-- | firmware/drivers/ata_mmc.c | 33 |
1 files changed, 19 insertions, 14 deletions
diff --git a/firmware/drivers/ata_mmc.c b/firmware/drivers/ata_mmc.c index 7149e111cd..7ba6dac296 100644 --- a/firmware/drivers/ata_mmc.c +++ b/firmware/drivers/ata_mmc.c | |||
@@ -626,7 +626,7 @@ int ata_read_sectors(IF_MV2(int drive,) | |||
626 | void* inbuf) | 626 | void* inbuf) |
627 | { | 627 | { |
628 | int ret = 0; | 628 | int ret = 0; |
629 | int i; | 629 | int last_sector; |
630 | unsigned long addr; | 630 | unsigned long addr; |
631 | unsigned char response; | 631 | unsigned char response; |
632 | void *inbuf_prev = NULL; | 632 | void *inbuf_prev = NULL; |
@@ -645,38 +645,44 @@ int ata_read_sectors(IF_MV2(int drive,) | |||
645 | if (start + incount > card->numsectors) | 645 | if (start + incount > card->numsectors) |
646 | panicf("Reading past end of card\n"); | 646 | panicf("Reading past end of card\n"); |
647 | 647 | ||
648 | /* some cards don't like reading the very last sector with | ||
649 | * CMD_READ_MULTIPLE_BLOCK, so make sure this sector is always | ||
650 | * read with CMD_READ_SINGLE_BLOCK. */ | ||
651 | last_sector = (start + incount == card->numsectors) ? 1 : 0; | ||
652 | |||
648 | if (ret == 0) | 653 | if (ret == 0) |
649 | { | 654 | { |
650 | if (incount == 1) | 655 | if (incount > 1) |
651 | { | 656 | { |
652 | ret = send_cmd(CMD_READ_SINGLE_BLOCK, addr, &response); | 657 | ret = send_cmd(CMD_READ_MULTIPLE_BLOCK, addr, &response); |
653 | if (ret == 0) | 658 | for (; (incount > last_sector) && (ret == 0); incount--) |
654 | { | 659 | { |
655 | ret = receive_sector(inbuf, inbuf_prev, card->read_timeout); | 660 | ret = receive_sector(inbuf, inbuf_prev, card->read_timeout); |
656 | inbuf_prev = inbuf; | 661 | inbuf_prev = inbuf; |
662 | inbuf += SECTOR_SIZE; | ||
657 | last_disk_activity = current_tick; | 663 | last_disk_activity = current_tick; |
658 | } | 664 | } |
665 | if (ret == 0) | ||
666 | ret = send_cmd(CMD_STOP_TRANSMISSION, 0, &response); | ||
659 | } | 667 | } |
660 | else | 668 | if (incount && (ret == 0)) |
661 | { | 669 | { |
662 | ret = send_cmd(CMD_READ_MULTIPLE_BLOCK, addr, &response); | 670 | ret = send_cmd(CMD_READ_SINGLE_BLOCK, addr, &response); |
663 | for (i = 0; (i < incount) && (ret == 0); i++) | 671 | if (ret == 0) |
664 | { | 672 | { |
665 | ret = receive_sector(inbuf, inbuf_prev, card->read_timeout); | 673 | ret = receive_sector(inbuf, inbuf_prev, card->read_timeout); |
666 | inbuf_prev = inbuf; | 674 | inbuf_prev = inbuf; |
667 | inbuf += SECTOR_SIZE; | ||
668 | last_disk_activity = current_tick; | 675 | last_disk_activity = current_tick; |
669 | } | 676 | } |
670 | if (ret == 0) | ||
671 | ret = send_cmd(CMD_STOP_TRANSMISSION, 0, &response); | ||
672 | } | 677 | } |
678 | |||
673 | if (ret == 0) | 679 | if (ret == 0) |
674 | bitswap(inbuf_prev, SECTOR_SIZE); | 680 | bitswap(inbuf_prev, SECTOR_SIZE); |
675 | } | 681 | } |
676 | 682 | ||
677 | deselect_card(); | 683 | deselect_card(); |
678 | mutex_unlock(&mmc_mutex); | 684 | mutex_unlock(&mmc_mutex); |
679 | 685 | ||
680 | /* only flush if reading went ok */ | 686 | /* only flush if reading went ok */ |
681 | if ( (ret == 0) && delayed_write ) | 687 | if ( (ret == 0) && delayed_write ) |
682 | ata_flush(); | 688 | ata_flush(); |
@@ -690,7 +696,6 @@ int ata_write_sectors(IF_MV2(int drive,) | |||
690 | const void* buf) | 696 | const void* buf) |
691 | { | 697 | { |
692 | int ret = 0; | 698 | int ret = 0; |
693 | int i; | ||
694 | unsigned long addr; | 699 | unsigned long addr; |
695 | unsigned char response; | 700 | unsigned char response; |
696 | tCardInfo *card; | 701 | tCardInfo *card; |
@@ -724,7 +729,7 @@ int ata_write_sectors(IF_MV2(int drive,) | |||
724 | { | 729 | { |
725 | swapcopy_sector(buf); /* prepare first sector */ | 730 | swapcopy_sector(buf); /* prepare first sector */ |
726 | ret = send_cmd(CMD_WRITE_MULTIPLE_BLOCK, addr, &response); | 731 | ret = send_cmd(CMD_WRITE_MULTIPLE_BLOCK, addr, &response); |
727 | for (i = 1; (i < count) && (ret == 0); i++) | 732 | for (; (count > 1) && (ret == 0); count--) |
728 | { | 733 | { |
729 | buf += SECTOR_SIZE; | 734 | buf += SECTOR_SIZE; |
730 | ret = send_sector(buf, card->write_timeout); | 735 | ret = send_sector(buf, card->write_timeout); |