summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Arnold <amiconn@rockbox.org>2005-04-28 20:47:55 +0000
committerJens Arnold <amiconn@rockbox.org>2005-04-28 20:47:55 +0000
commit74875ef37ebe70c1ed54c6eb75cf3cf218dfc212 (patch)
tree687e1ffa39316dc8d6a7a1ae57f72d41ab2c799f
parent238bea737050f22007a06035cdd78c96beb50f06 (diff)
downloadrockbox-74875ef37ebe70c1ed54c6eb75cf3cf218dfc212.tar.gz
rockbox-74875ef37ebe70c1ed54c6eb75cf3cf218dfc212.zip
Speed optimisations: (1) Read, write: Use single/multiple block commands depending on the block count. (2) Write: Combine first partial sector transfer (after caching) & main loop into one block-transfer sequence.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6381 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/drivers/ata_mmc.c125
1 files changed, 72 insertions, 53 deletions
diff --git a/firmware/drivers/ata_mmc.c b/firmware/drivers/ata_mmc.c
index 3c242878e4..606bb0c822 100644
--- a/firmware/drivers/ata_mmc.c
+++ b/firmware/drivers/ata_mmc.c
@@ -744,16 +744,19 @@ int ata_read_sectors(IF_MV2(int drive,)
744 c_addr += len; 744 c_addr += len;
745 c_block++; 745 c_block++;
746 } 746 }
747 /* some cards don't like reading the very last sector with 747 /* some cards don't like reading the very last block with
748 * CMD_READ_MULTIPLE_BLOCK, so make sure this sector is always 748 * CMD_READ_MULTIPLE_BLOCK, so make sure this block is always
749 * read with CMD_READ_SINGLE_BLOCK. This is caught by the 'last 749 * read with CMD_READ_SINGLE_BLOCK. Let the 'last partial block'
750 * partial block' read. */ 750 * read catch this. */
751 if (c_end_block == card->numblocks) 751 if (c_end_block == card->numblocks)
752 c_end_block--; 752 c_end_block--;
753 753
754 if (c_block < c_end_block) 754 if (c_block < c_end_block)
755 { 755 {
756 rc = send_cmd(CMD_READ_MULTIPLE_BLOCK, c_addr, &response); 756 int read_cmd = (c_end_block - c_block > 1) ?
757 CMD_READ_MULTIPLE_BLOCK : CMD_READ_SINGLE_BLOCK;
758
759 rc = send_cmd(read_cmd, c_addr, &response);
757 if (rc) 760 if (rc)
758 { 761 {
759 rc = rc * 10 - 4; 762 rc = rc * 10 - 4;
@@ -774,11 +777,14 @@ int ata_read_sectors(IF_MV2(int drive,)
774 c_addr += blocksize; 777 c_addr += blocksize;
775 c_block++; 778 c_block++;
776 } 779 }
777 rc = send_cmd(CMD_STOP_TRANSMISSION, 0, &response); 780 if (read_cmd == CMD_READ_MULTIPLE_BLOCK)
778 if (rc)
779 { 781 {
780 rc = rc * 10 - 6; 782 rc = send_cmd(CMD_STOP_TRANSMISSION, 0, &response);
781 goto error; 783 if (rc)
784 {
785 rc = rc * 10 - 6;
786 goto error;
787 }
782 } 788 }
783 bitswap(inbuf_prev, blocksize); 789 bitswap(inbuf_prev, blocksize);
784 } 790 }
@@ -848,81 +854,94 @@ int ata_write_sectors(IF_MV2(int drive,)
848 offset = c_addr & (blocksize - 1); 854 offset = c_addr & (blocksize - 1);
849 c_block = c_addr >> card->block_exp; 855 c_block = c_addr >> card->block_exp;
850 c_end_block = c_end_addr >> card->block_exp; 856 c_end_block = c_end_addr >> card->block_exp;
851
852 if (offset) /* first partial block */
853 {
854 unsigned long len = MIN(c_end_addr - c_addr, blocksize - offset);
855 857
856 rc = cache_block(IF_MV2(drive,) c_block, blocksize, 858 /* Special case: first block is trimmed at both ends. May only happen
857 card->read_timeout); 859 * if (blocksize > 2 * sectorsize), i.e. blocksize == 2048 */
858 if (rc) 860 if ((c_block == c_end_block) && offset)
861 c_end_block++;
862
863 if (c_block < c_end_block)
864 {
865 int write_cmd;
866 unsigned char start_token;
867
868 if (c_end_block - c_block > 1)
859 { 869 {
860 rc = rc * 10 - 2; 870 write_cmd = CMD_WRITE_MULTIPLE_BLOCK;
861 goto error; 871 start_token = DT_START_WRITE_MULTIPLE;
862 } 872 }
863 swapcopy(block_cache[current_cache].data + 2 + offset, buf, len); 873 else
864 rc = send_cmd(CMD_WRITE_BLOCK, c_addr - offset, &response);
865 if (rc)
866 { 874 {
867 rc = rc * 10 - 3; 875 write_cmd = CMD_WRITE_BLOCK;
868 goto error; 876 start_token = DT_START_BLOCK;
869 } 877 }
870 buf += len; 878
871 rc = send_block(NULL, blocksize, DT_START_BLOCK, card->write_timeout); 879 if (offset)
872 if (rc)
873 { 880 {
874 rc = rc * 10 - 4; 881 unsigned long len = MIN(c_end_addr - c_addr, blocksize - offset);
875 goto error; 882
883 rc = cache_block(IF_MV2(drive,) c_block, blocksize,
884 card->read_timeout);
885 if (rc)
886 {
887 rc = rc * 10 - 2;
888 goto error;
889 }
890 swapcopy(block_cache[current_cache].data + 2 + offset, buf, len);
891 buf += len;
892 c_addr -= offset;
876 } 893 }
877 c_addr += len; 894 else
878 c_block++; 895 {
879 } 896 swapcopy_block(buf, blocksize);
880 if (c_block < c_end_block) 897 buf += blocksize;
881 { 898 }
882 swapcopy_block(buf, blocksize); 899 rc = send_cmd(write_cmd, c_addr, &response);
883 rc = send_cmd(CMD_WRITE_MULTIPLE_BLOCK, c_addr, &response);
884 if (rc) 900 if (rc)
885 { 901 {
886 rc = rc * 10 - 5; 902 rc = rc * 10 - 3;
887 goto error; 903 goto error;
888 } 904 }
889 while (c_block < c_end_block - 1) 905 c_block++; /* early increment to simplify the loop */
906
907 while (c_block < c_end_block)
890 { 908 {
891 buf += blocksize; 909 rc = send_block(buf, blocksize, start_token, card->write_timeout);
892 rc = send_block(buf, blocksize, DT_START_WRITE_MULTIPLE,
893 card->write_timeout);
894 if (rc) 910 if (rc)
895 { 911 {
896 rc = rc * 10 - 6; 912 rc = rc * 10 - 4;
897 goto error; 913 goto error;
898 } 914 }
899 last_disk_activity = current_tick; 915 last_disk_activity = current_tick;
916 buf += blocksize;
900 c_addr += blocksize; 917 c_addr += blocksize;
901 c_block++; 918 c_block++;
902 } 919 }
903 buf += blocksize; 920 rc = send_block(NULL, blocksize, start_token, card->write_timeout);
904 rc = send_block(NULL, blocksize, DT_START_WRITE_MULTIPLE,
905 card->write_timeout);
906 if (rc) 921 if (rc)
907 { 922 {
908 rc = rc * 10 - 7; 923 rc = rc * 10 - 5;
909 goto error; 924 goto error;
910 } 925 }
911 last_disk_activity = current_tick; 926 last_disk_activity = current_tick;
912 c_addr += blocksize; 927 c_addr += blocksize;
913 c_block++; 928 /* c_block++ was done early */
914 929
915 response = DT_STOP_TRAN; 930 if (write_cmd == CMD_WRITE_MULTIPLE_BLOCK)
916 write_transfer(&response, 1); 931 {
917 poll_busy(card->write_timeout); 932 response = DT_STOP_TRAN;
933 write_transfer(&response, 1);
934 poll_busy(card->write_timeout);
935 }
918 } 936 }
937
919 if (c_addr < c_end_addr) /* last partial block */ 938 if (c_addr < c_end_addr) /* last partial block */
920 { 939 {
921 rc = cache_block(IF_MV2(drive,) c_block, blocksize, 940 rc = cache_block(IF_MV2(drive,) c_block, blocksize,
922 card->read_timeout); 941 card->read_timeout);
923 if (rc) 942 if (rc)
924 { 943 {
925 rc = rc * 10 - 8; 944 rc = rc * 10 - 6;
926 goto error; 945 goto error;
927 } 946 }
928 swapcopy(block_cache[current_cache].data + 2, buf, 947 swapcopy(block_cache[current_cache].data + 2, buf,
@@ -930,13 +949,13 @@ int ata_write_sectors(IF_MV2(int drive,)
930 rc = send_cmd(CMD_WRITE_BLOCK, c_addr, &response); 949 rc = send_cmd(CMD_WRITE_BLOCK, c_addr, &response);
931 if (rc) 950 if (rc)
932 { 951 {
933 rc = rc * 10 - 9; 952 rc = rc * 10 - 7;
934 goto error; 953 goto error;
935 } 954 }
936 rc = send_block(NULL, blocksize, DT_START_BLOCK, card->write_timeout); 955 rc = send_block(NULL, blocksize, DT_START_BLOCK, card->write_timeout);
937 if (rc) 956 if (rc)
938 { 957 {
939 rc = rc * 10 - 9; 958 rc = rc * 10 - 8;
940 goto error; 959 goto error;
941 } 960 }
942 } 961 }