diff options
author | Jens Arnold <amiconn@rockbox.org> | 2005-04-28 20:47:55 +0000 |
---|---|---|
committer | Jens Arnold <amiconn@rockbox.org> | 2005-04-28 20:47:55 +0000 |
commit | 74875ef37ebe70c1ed54c6eb75cf3cf218dfc212 (patch) | |
tree | 687e1ffa39316dc8d6a7a1ae57f72d41ab2c799f | |
parent | 238bea737050f22007a06035cdd78c96beb50f06 (diff) | |
download | rockbox-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.c | 125 |
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 | } |