summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/drivers/ata_mmc.c33
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);