diff options
author | Michael Sparmann <theseven@rockbox.org> | 2010-03-13 00:43:34 +0000 |
---|---|---|
committer | Michael Sparmann <theseven@rockbox.org> | 2010-03-13 00:43:34 +0000 |
commit | 131bb698ada664a49e0a548b515b14733914654e (patch) | |
tree | ea3558892078fd667e43d55b739b0bc78b1f7d4f | |
parent | a4caff91f9e3aed8f512d51ca9012a220d4abdef (diff) | |
download | rockbox-131bb698ada664a49e0a548b515b14733914654e.tar.gz rockbox-131bb698ada664a49e0a548b515b14733914654e.zip |
Revert r25099, r25101, r25109 and r25137 for now. This doesn't seem to be quite stable on some NAND types yet.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@25139 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c | 430 | ||||
-rw-r--r-- | firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c | 261 | ||||
-rw-r--r-- | firmware/target/arm/s5l8700/ipodnano2g/nand-target.h | 7 |
3 files changed, 157 insertions, 541 deletions
diff --git a/firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c b/firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c index 321495a321..0cc7841cd5 100644 --- a/firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c +++ b/firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c | |||
@@ -31,8 +31,6 @@ | |||
31 | 31 | ||
32 | 32 | ||
33 | 33 | ||
34 | #define FTL_COPYBUF_SIZE 32 | ||
35 | #define FTL_WRITESPARE_SIZE 32 | ||
36 | //#define FTL_FORCEMOUNT | 34 | //#define FTL_FORCEMOUNT |
37 | 35 | ||
38 | 36 | ||
@@ -374,7 +372,7 @@ struct ftl_cxt_type ftl_cxt; | |||
374 | uint8_t ftl_buffer[0x800] __attribute__((aligned(16))); | 372 | uint8_t ftl_buffer[0x800] __attribute__((aligned(16))); |
375 | 373 | ||
376 | /* Temporary spare byte buffer for internal use by the FTL */ | 374 | /* Temporary spare byte buffer for internal use by the FTL */ |
377 | union ftl_spare_data_type ftl_sparebuffer[FTL_WRITESPARE_SIZE] __attribute__((aligned(16))); | 375 | union ftl_spare_data_type ftl_sparebuffer __attribute__((aligned(16))); |
378 | 376 | ||
379 | 377 | ||
380 | #ifndef FTL_READONLY | 378 | #ifndef FTL_READONLY |
@@ -404,8 +402,7 @@ uint8_t ftl_erasectr_dirt[8]; | |||
404 | /* Buffer needed for copying pages around while moving or committing blocks. | 402 | /* Buffer needed for copying pages around while moving or committing blocks. |
405 | This can't be shared with ftl_buffer, because this one could be overwritten | 403 | This can't be shared with ftl_buffer, because this one could be overwritten |
406 | during the copying operation in order to e.g. commit a CXT. */ | 404 | during the copying operation in order to e.g. commit a CXT. */ |
407 | uint8_t ftl_copybuffer[FTL_COPYBUF_SIZE][0x800] __attribute__((aligned(16))); | 405 | uint8_t ftl_copybuffer[0x800] __attribute__((aligned(16))); |
408 | union ftl_spare_data_type ftl_copyspare[FTL_COPYBUF_SIZE] __attribute__((aligned(16))); | ||
409 | 406 | ||
410 | /* Needed to store the old scattered page offsets in order to be able to roll | 407 | /* Needed to store the old scattered page offsets in order to be able to roll |
411 | back if something fails while compacting a scattered page block. */ | 408 | back if something fails while compacting a scattered page block. */ |
@@ -433,7 +430,7 @@ uint32_t ftl_find_devinfo(uint32_t bank) | |||
433 | { | 430 | { |
434 | pagenum = block * (*ftl_nand_type).pagesperblock + page; | 431 | pagenum = block * (*ftl_nand_type).pagesperblock + page; |
435 | if ((nand_read_page(bank, pagenum, ftl_buffer, | 432 | if ((nand_read_page(bank, pagenum, ftl_buffer, |
436 | &ftl_sparebuffer[0], 1, 0) & 0x11F) != 0) | 433 | &ftl_sparebuffer, 1, 0) & 0x11F) != 0) |
437 | continue; | 434 | continue; |
438 | if (memcmp(ftl_buffer, "DEVICEINFOSIGN\0", 0x10) == 0) | 435 | if (memcmp(ftl_buffer, "DEVICEINFOSIGN\0", 0x10) == 0) |
439 | return pagenum; | 436 | return pagenum; |
@@ -537,34 +534,34 @@ uint32_t ftl_vfl_store_cxt(uint32_t bank) | |||
537 | ftl_vfl_cxt[bank].usn = ++ftl_vfl_usn; | 534 | ftl_vfl_cxt[bank].usn = ++ftl_vfl_usn; |
538 | ftl_vfl_cxt[bank].nextcxtpage += 8; | 535 | ftl_vfl_cxt[bank].nextcxtpage += 8; |
539 | ftl_vfl_update_checksum(bank); | 536 | ftl_vfl_update_checksum(bank); |
540 | memset(&ftl_sparebuffer[0], 0xFF, 0x40); | 537 | memset(&ftl_sparebuffer, 0xFF, 0x40); |
541 | ftl_sparebuffer[0].meta.usn = ftl_vfl_cxt[bank].updatecount; | 538 | ftl_sparebuffer.meta.usn = ftl_vfl_cxt[bank].updatecount; |
542 | ftl_sparebuffer[0].meta.field_8 = 0; | 539 | ftl_sparebuffer.meta.field_8 = 0; |
543 | ftl_sparebuffer[0].meta.type = 0x80; | 540 | ftl_sparebuffer.meta.type = 0x80; |
544 | for (i = 1; i <= 8; i++) | 541 | for (i = 1; i <= 8; i++) |
545 | { | 542 | { |
546 | uint32_t index = ftl_vfl_cxt[bank].activecxtblock; | 543 | uint32_t index = ftl_vfl_cxt[bank].activecxtblock; |
547 | uint32_t block = ftl_vfl_cxt[bank].vflcxtblocks[index]; | 544 | uint32_t block = ftl_vfl_cxt[bank].vflcxtblocks[index]; |
548 | uint32_t page = block * (*ftl_nand_type).pagesperblock; | 545 | uint32_t page = block * (*ftl_nand_type).pagesperblock; |
549 | page += ftl_vfl_cxt[bank].nextcxtpage - i; | 546 | page += ftl_vfl_cxt[bank].nextcxtpage - i; |
550 | nand_write_page(bank, page, &ftl_vfl_cxt[bank], &ftl_sparebuffer[0], 1); | 547 | nand_write_page(bank, page, &ftl_vfl_cxt[bank], &ftl_sparebuffer, 1); |
551 | } | 548 | } |
552 | uint32_t good = 0; | 549 | uint32_t good = 0; |
553 | for (i = 1; i <= 8; i++) | 550 | for (i = 0; i < 8; i++) |
554 | { | 551 | { |
555 | uint32_t index = ftl_vfl_cxt[bank].activecxtblock; | 552 | uint32_t index = ftl_vfl_cxt[bank].activecxtblock; |
556 | uint32_t block = ftl_vfl_cxt[bank].vflcxtblocks[index]; | 553 | uint32_t block = ftl_vfl_cxt[bank].vflcxtblocks[index]; |
557 | uint32_t page = block * (*ftl_nand_type).pagesperblock; | 554 | uint32_t page = block * (*ftl_nand_type).pagesperblock; |
558 | page += ftl_vfl_cxt[bank].nextcxtpage - i; | 555 | page += ftl_vfl_cxt[bank].nextcxtpage - i; |
559 | if ((nand_read_page(bank, page, ftl_buffer, | 556 | if ((nand_read_page(bank, page, ftl_buffer, |
560 | &ftl_sparebuffer[0], 1, 0) & 0x11F) != 0) | 557 | &ftl_sparebuffer, 1, 0) & 0x11F) != 0) |
561 | continue; | 558 | continue; |
562 | if (memcmp(ftl_buffer, &ftl_vfl_cxt[bank], 0x7AC) != 0) | 559 | if (memcmp(ftl_buffer, &ftl_vfl_cxt[bank], 0x7AC) != 0) |
563 | continue; | 560 | continue; |
564 | if (ftl_sparebuffer[0].meta.usn != ftl_vfl_cxt[bank].updatecount) | 561 | if (ftl_sparebuffer.meta.usn != ftl_vfl_cxt[bank].updatecount) |
565 | continue; | 562 | continue; |
566 | if (ftl_sparebuffer[0].meta.field_8 == 0 | 563 | if (ftl_sparebuffer.meta.field_8 == 0 |
567 | && ftl_sparebuffer[0].meta.type == 0x80) good++; | 564 | && ftl_sparebuffer.meta.type == 0x80) good++; |
568 | } | 565 | } |
569 | return good > 3 ? 0 : 1; | 566 | return good > 3 ? 0 : 1; |
570 | } | 567 | } |
@@ -850,140 +847,36 @@ uint32_t ftl_vfl_read(uint32_t vpage, void* buffer, void* sparebuffer, | |||
850 | } | 847 | } |
851 | 848 | ||
852 | 849 | ||
853 | /* Multi-bank version of ftl_vfl_read, will read ftl_banks pages in parallel */ | 850 | #ifndef FTL_READONLY |
854 | uint32_t ftl_vfl_read_fast(uint32_t vpage, void* buffer, void* sparebuffer, | 851 | /* Writes the specified vPage, dealing with all kinds of trouble */ |
855 | uint32_t checkempty, uint32_t remaponfail) | 852 | uint32_t ftl_vfl_write(uint32_t vpage, void* buffer, void* sparebuffer) |
856 | { | 853 | { |
857 | uint32_t i, rc = 0; | ||
858 | uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks; | 854 | uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks; |
859 | uint32_t syshyperblocks = (*ftl_nand_type).blocks | 855 | uint32_t syshyperblocks = (*ftl_nand_type).blocks |
860 | - (*ftl_nand_type).userblocks - 0x17; | 856 | - (*ftl_nand_type).userblocks - 0x17; |
861 | uint32_t abspage = vpage + ppb * syshyperblocks; | 857 | uint32_t abspage = vpage + ppb * syshyperblocks; |
862 | if (abspage + ftl_banks - 1 >= (*ftl_nand_type).blocks * ppb || abspage < ppb) | 858 | if (abspage >= (*ftl_nand_type).blocks * ppb || abspage < ppb) |
863 | panicf("FTL: Trying to read out-of-bounds vPage %u", (unsigned)vpage); | 859 | panicf("FTL: Trying to write out-of-bounds vPage %u", |
860 | (unsigned)vpage); | ||
864 | //return 4; | 861 | //return 4; |
865 | 862 | ||
866 | uint32_t bank = abspage % ftl_banks; | 863 | uint32_t bank = abspage % ftl_banks; |
867 | uint32_t block = abspage / ((*ftl_nand_type).pagesperblock * ftl_banks); | 864 | uint32_t block = abspage / ((*ftl_nand_type).pagesperblock * ftl_banks); |
868 | uint32_t page = (abspage / ftl_banks) % (*ftl_nand_type).pagesperblock; | 865 | uint32_t page = (abspage / ftl_banks) % (*ftl_nand_type).pagesperblock; |
869 | if (bank) | ||
870 | { | ||
871 | for (i = 0; i < ftl_banks; i++) | ||
872 | { | ||
873 | void* databuf = (void*)0; | ||
874 | void* sparebuf = (void*)0; | ||
875 | if (buffer) databuf = (void*)((uint32_t)buffer + 0x800 * i); | ||
876 | if (sparebuffer) sparebuf = (void*)((uint32_t)sparebuffer + 0x40 * i); | ||
877 | uint32_t ret = ftl_vfl_read(vpage + i, databuf, sparebuf, checkempty, remaponfail); | ||
878 | if (ret & 1) rc |= 1 << (i << 2); | ||
879 | if (ret & 2) rc |= 2 << (i << 2); | ||
880 | if (ret & 0x10) rc |= 4 << (i << 2); | ||
881 | if (ret & 0x100) rc |= 8 << (i << 2); | ||
882 | } | ||
883 | return rc; | ||
884 | } | ||
885 | uint32_t physblock = ftl_vfl_get_physical_block(bank, block); | 866 | uint32_t physblock = ftl_vfl_get_physical_block(bank, block); |
886 | uint32_t physpage = physblock * (*ftl_nand_type).pagesperblock + page; | 867 | uint32_t physpage = physblock * (*ftl_nand_type).pagesperblock + page; |
887 | 868 | ||
888 | rc = nand_read_page_fast(physpage, buffer, sparebuffer, 1, checkempty); | 869 | if (nand_write_page(bank, physpage, buffer, sparebuffer, 1) == 0) |
889 | if (!(rc & 0xdddd)) return rc; | 870 | return 0; |
890 | |||
891 | for (i = 0; i < ftl_banks; i++) | ||
892 | { | ||
893 | if ((rc >> (i << 2)) & 0x2) continue; | ||
894 | if ((rc >> (i << 2)) & 0xf) | ||
895 | { | ||
896 | rc &= ~(0xf << (i << 2)); | ||
897 | nand_reset(i); | ||
898 | uint32_t ret = nand_read_page(i, physpage, | ||
899 | (void*)((uint32_t)buffer + 0x800 * i), | ||
900 | (void*)((uint32_t)sparebuffer + 0x40 * i), | ||
901 | 1, checkempty); | ||
902 | #ifdef FTL_READONLY | ||
903 | (void)remaponfail; | ||
904 | #else | ||
905 | if (remaponfail == 1 && (ret & 0x11D) != 0 && (ret & 2) == 0) | ||
906 | ftl_vfl_schedule_block_for_remap(i, block); | ||
907 | #endif | ||
908 | if (ret & 1) rc |= 1 << (i << 2); | ||
909 | if (ret & 2) rc |= 2 << (i << 2); | ||
910 | if (ret & 0x10) rc |= 4 << (i << 2); | ||
911 | if (ret & 0x100) rc |= 8 << (i << 2); | ||
912 | } | ||
913 | } | ||
914 | |||
915 | return rc; | ||
916 | } | ||
917 | |||
918 | |||
919 | #ifndef FTL_READONLY | ||
920 | /* Writes the specified vPage, dealing with all kinds of trouble */ | ||
921 | uint32_t ftl_vfl_write(uint32_t vpage, uint32_t count, | ||
922 | void* buffer, void* sparebuffer) | ||
923 | { | ||
924 | uint32_t i, j; | ||
925 | uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks; | ||
926 | uint32_t syshyperblocks = (*ftl_nand_type).blocks | ||
927 | - (*ftl_nand_type).userblocks - 0x17; | ||
928 | uint32_t abspage = vpage + ppb * syshyperblocks; | ||
929 | if (abspage + count > (*ftl_nand_type).blocks * ppb || abspage < ppb) | ||
930 | panicf("FTL: Trying to write out-of-bounds vPage %u", | ||
931 | (unsigned)vpage); | ||
932 | //return 4; | ||
933 | |||
934 | uint32_t bank[5]; | ||
935 | uint32_t block[5]; | ||
936 | uint32_t physpage[5]; | ||
937 | |||
938 | for (i = 0; i < count; i++, abspage++) | ||
939 | { | ||
940 | for (j = ftl_banks; j > 0; j--) | ||
941 | { | ||
942 | bank[j] = bank[j - 1]; | ||
943 | block[j] = block[j - 1]; | ||
944 | physpage[j] = physpage[j - 1]; | ||
945 | } | ||
946 | bank[0] = abspage % ftl_banks; | ||
947 | block[0] = abspage / ((*ftl_nand_type).pagesperblock * ftl_banks); | ||
948 | uint32_t page = (abspage / ftl_banks) % (*ftl_nand_type).pagesperblock; | ||
949 | uint32_t physblock = ftl_vfl_get_physical_block(bank[0], block[0]); | ||
950 | physpage[0] = physblock * (*ftl_nand_type).pagesperblock + page; | ||
951 | |||
952 | if (i >= ftl_banks) | ||
953 | if (nand_write_page_collect(bank[ftl_banks])) | ||
954 | if (nand_read_page(bank[ftl_banks], physpage[ftl_banks], | ||
955 | ftl_buffer, &ftl_sparebuffer[0], 1, 1) & 0x11F) | ||
956 | { | ||
957 | panicf("FTL: write error (2) on vPage %u, bank %u, pPage %u", | ||
958 | (unsigned)(vpage + i - ftl_banks), | ||
959 | (unsigned)bank[ftl_banks], | ||
960 | (unsigned)physpage[ftl_banks]); | ||
961 | ftl_vfl_log_trouble(bank[ftl_banks], block[ftl_banks]); | ||
962 | } | ||
963 | if (nand_write_page_start(bank[0], physpage[0], | ||
964 | (void*)((uint32_t)buffer + 0x800 * i), | ||
965 | (void*)((uint32_t)sparebuffer + 0x40 * i), 1)) | ||
966 | if (nand_read_page(bank[0], physpage[0], ftl_buffer, | ||
967 | &ftl_sparebuffer[0], 1, 1) & 0x11F) | ||
968 | { | ||
969 | panicf("FTL: write error (1) on vPage %u, bank %u, pPage %u", | ||
970 | (unsigned)(vpage + i), (unsigned)bank[0], (unsigned)physpage[0]); | ||
971 | ftl_vfl_log_trouble(bank[0], block[0]); | ||
972 | } | ||
973 | } | ||
974 | 871 | ||
975 | for (i = count < ftl_banks ? count : ftl_banks; i > 0; i--) | 872 | if ((nand_read_page(bank, physpage, ftl_buffer, |
976 | if (nand_write_page_collect(bank[i - 1])) | 873 | &ftl_sparebuffer, 1, 1) & 0x11F) == 0) |
977 | if (nand_read_page(bank[i - 1], physpage[i - 1], | 874 | return 0; |
978 | ftl_buffer, &ftl_sparebuffer[0], 1, 1) & 0x11F) | ||
979 | { | ||
980 | panicf("FTL: write error (2) on vPage %u, bank %u, pPage %u", | ||
981 | (unsigned)(vpage + count - i), | ||
982 | (unsigned)bank[i - 1], (unsigned)physpage[i - 1]); | ||
983 | ftl_vfl_log_trouble(bank[i - 1], block[i - 1]); | ||
984 | } | ||
985 | 875 | ||
986 | return 0; | 876 | panicf("FTL: write error on vPage %u, bank %u, pPage %u", |
877 | (unsigned)vpage, (unsigned)bank, (unsigned)physpage); | ||
878 | ftl_vfl_log_trouble(bank, block); | ||
879 | return 1; | ||
987 | } | 880 | } |
988 | #endif | 881 | #endif |
989 | 882 | ||
@@ -1020,7 +913,7 @@ uint32_t ftl_vfl_open(void) | |||
1020 | if (ftl_is_good_block(bbt, j) != 0) | 913 | if (ftl_is_good_block(bbt, j) != 0) |
1021 | #endif | 914 | #endif |
1022 | if (ftl_vfl_read_page(i, j, 0, ftl_buffer, | 915 | if (ftl_vfl_read_page(i, j, 0, ftl_buffer, |
1023 | &ftl_sparebuffer[0]) == 0) | 916 | &ftl_sparebuffer) == 0) |
1024 | { | 917 | { |
1025 | struct ftl_vfl_cxt_type* cxt; | 918 | struct ftl_vfl_cxt_type* cxt; |
1026 | cxt = (struct ftl_vfl_cxt_type*)ftl_buffer; | 919 | cxt = (struct ftl_vfl_cxt_type*)ftl_buffer; |
@@ -1031,11 +924,11 @@ uint32_t ftl_vfl_open(void) | |||
1031 | if (vflcxtblock[k] != 0xFFFF) | 924 | if (vflcxtblock[k] != 0xFFFF) |
1032 | if (ftl_vfl_read_page(i, vflcxtblock[k], 0, | 925 | if (ftl_vfl_read_page(i, vflcxtblock[k], 0, |
1033 | ftl_buffer, | 926 | ftl_buffer, |
1034 | &ftl_sparebuffer[0]) == 0) | 927 | &ftl_sparebuffer) == 0) |
1035 | if (ftl_sparebuffer[0].meta.usn > 0 | 928 | if (ftl_sparebuffer.meta.usn > 0 |
1036 | && ftl_sparebuffer[0].meta.usn <= minusn) | 929 | && ftl_sparebuffer.meta.usn <= minusn) |
1037 | { | 930 | { |
1038 | minusn = ftl_sparebuffer[0].meta.usn; | 931 | minusn = ftl_sparebuffer.meta.usn; |
1039 | vflcxtidx = k; | 932 | vflcxtidx = k; |
1040 | } | 933 | } |
1041 | if (vflcxtidx == 4) //return 1; | 934 | if (vflcxtidx == 4) //return 1; |
@@ -1047,13 +940,13 @@ uint32_t ftl_vfl_open(void) | |||
1047 | { | 940 | { |
1048 | if (ftl_vfl_read_page(i, vflcxtblock[vflcxtidx], | 941 | if (ftl_vfl_read_page(i, vflcxtblock[vflcxtidx], |
1049 | k, ftl_buffer, | 942 | k, ftl_buffer, |
1050 | &ftl_sparebuffer[0]) != 0) | 943 | &ftl_sparebuffer) != 0) |
1051 | break; | 944 | break; |
1052 | last = k; | 945 | last = k; |
1053 | } | 946 | } |
1054 | if (ftl_vfl_read_page(i, vflcxtblock[vflcxtidx], | 947 | if (ftl_vfl_read_page(i, vflcxtblock[vflcxtidx], |
1055 | last, ftl_buffer, | 948 | last, ftl_buffer, |
1056 | &ftl_sparebuffer[0]) != 0) | 949 | &ftl_sparebuffer) != 0) |
1057 | panicf("FTL: Re-reading VFL CXT block " | 950 | panicf("FTL: Re-reading VFL CXT block " |
1058 | "on bank %u failed!?", (unsigned)i); | 951 | "on bank %u failed!?", (unsigned)i); |
1059 | //return 1; | 952 | //return 1; |
@@ -1088,12 +981,12 @@ uint32_t ftl_open(void) | |||
1088 | for (i = 0; i < 3; i++) | 981 | for (i = 0; i < 3; i++) |
1089 | { | 982 | { |
1090 | ret = ftl_vfl_read(ppb * (*cxt).ftlctrlblocks[i], | 983 | ret = ftl_vfl_read(ppb * (*cxt).ftlctrlblocks[i], |
1091 | ftl_buffer, &ftl_sparebuffer[0], 1, 0); | 984 | ftl_buffer, &ftl_sparebuffer, 1, 0); |
1092 | if ((ret &= 0x11F) != 0) continue; | 985 | if ((ret &= 0x11F) != 0) continue; |
1093 | if (ftl_sparebuffer[0].meta.type - 0x43 > 4) continue; | 986 | if (ftl_sparebuffer.meta.type - 0x43 > 4) continue; |
1094 | if (ftlcxtblock != 0xffffffff && ftl_sparebuffer[0].meta.usn >= minusn) | 987 | if (ftlcxtblock != 0xffffffff && ftl_sparebuffer.meta.usn >= minusn) |
1095 | continue; | 988 | continue; |
1096 | minusn = ftl_sparebuffer[0].meta.usn; | 989 | minusn = ftl_sparebuffer.meta.usn; |
1097 | ftlcxtblock = (*cxt).ftlctrlblocks[i]; | 990 | ftlcxtblock = (*cxt).ftlctrlblocks[i]; |
1098 | } | 991 | } |
1099 | 992 | ||
@@ -1104,9 +997,9 @@ uint32_t ftl_open(void) | |||
1104 | for (i = (*ftl_nand_type).pagesperblock * ftl_banks - 1; i > 0; i--) | 997 | for (i = (*ftl_nand_type).pagesperblock * ftl_banks - 1; i > 0; i--) |
1105 | { | 998 | { |
1106 | ret = ftl_vfl_read(ppb * ftlcxtblock + i, | 999 | ret = ftl_vfl_read(ppb * ftlcxtblock + i, |
1107 | ftl_buffer, &ftl_sparebuffer[0], 1, 0); | 1000 | ftl_buffer, &ftl_sparebuffer, 1, 0); |
1108 | if ((ret & 0x11F) != 0) continue; | 1001 | if ((ret & 0x11F) != 0) continue; |
1109 | else if (ftl_sparebuffer[0].meta.type == 0x43) | 1002 | else if (ftl_sparebuffer.meta.type == 0x43) |
1110 | { | 1003 | { |
1111 | memcpy(&ftl_cxt, ftl_buffer, 0x28C); | 1004 | memcpy(&ftl_cxt, ftl_buffer, 0x28C); |
1112 | ftlcxtfound = 1; | 1005 | ftlcxtfound = 1; |
@@ -1131,7 +1024,7 @@ uint32_t ftl_open(void) | |||
1131 | for (i = 0; i < pagestoread; i++) | 1024 | for (i = 0; i < pagestoread; i++) |
1132 | { | 1025 | { |
1133 | if ((ftl_vfl_read(ftl_cxt.ftl_map_pages[i], | 1026 | if ((ftl_vfl_read(ftl_cxt.ftl_map_pages[i], |
1134 | ftl_buffer, &ftl_sparebuffer[0], 1, 1) & 0x11F) != 0) | 1027 | ftl_buffer, &ftl_sparebuffer, 1, 1) & 0x11F) != 0) |
1135 | panicf("FTL: Failed to read block map page %u", (unsigned)i); | 1028 | panicf("FTL: Failed to read block map page %u", (unsigned)i); |
1136 | //return 1; | 1029 | //return 1; |
1137 | 1030 | ||
@@ -1149,7 +1042,7 @@ uint32_t ftl_open(void) | |||
1149 | for (i = 0; i < pagestoread; i++) | 1042 | for (i = 0; i < pagestoread; i++) |
1150 | { | 1043 | { |
1151 | if ((ftl_vfl_read(ftl_cxt.ftl_erasectr_pages[i], | 1044 | if ((ftl_vfl_read(ftl_cxt.ftl_erasectr_pages[i], |
1152 | ftl_buffer, &ftl_sparebuffer[0], 1, 1) & 0x11F) != 0) | 1045 | ftl_buffer, &ftl_sparebuffer, 1, 1) & 0x11F) != 0) |
1153 | panicf("FTL: Failed to read erase counter page %u", (unsigned)i); | 1046 | panicf("FTL: Failed to read erase counter page %u", (unsigned)i); |
1154 | //return 1; | 1047 | //return 1; |
1155 | 1048 | ||
@@ -1193,7 +1086,7 @@ struct ftl_log_type* ftl_get_log_entry(uint32_t block) | |||
1193 | /* Exposed function: Read highlevel sectors */ | 1086 | /* Exposed function: Read highlevel sectors */ |
1194 | uint32_t ftl_read(uint32_t sector, uint32_t count, void* buffer) | 1087 | uint32_t ftl_read(uint32_t sector, uint32_t count, void* buffer) |
1195 | { | 1088 | { |
1196 | uint32_t i, j; | 1089 | uint32_t i; |
1197 | uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks; | 1090 | uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks; |
1198 | uint32_t error = 0; | 1091 | uint32_t error = 0; |
1199 | 1092 | ||
@@ -1219,35 +1112,13 @@ uint32_t ftl_read(uint32_t sector, uint32_t count, void* buffer) | |||
1219 | + (*logentry).pageoffsets[page]; | 1112 | + (*logentry).pageoffsets[page]; |
1220 | #endif | 1113 | #endif |
1221 | 1114 | ||
1222 | #ifndef FTL_READONLY | 1115 | uint32_t ret = ftl_vfl_read(abspage, &((uint8_t*)buffer)[i << 11], |
1223 | if (count >= i + ftl_banks && !(page & (ftl_banks - 1)) | 1116 | &ftl_sparebuffer, 1, 1); |
1224 | && logentry == (struct ftl_log_type*)0) | 1117 | if ((ret & 2) != 0) memset(&((uint8_t*)buffer)[i << 11], 0, 0x800); |
1225 | #else | 1118 | else if ((ret & 0x11D) != 0 || ftl_sparebuffer.user.eccmark != 0xFF) |
1226 | if (count >= i + ftl_banks && !(page & (ftl_banks - 1))) | ||
1227 | #endif | ||
1228 | { | 1119 | { |
1229 | uint32_t ret = ftl_vfl_read_fast(abspage, &((uint8_t*)buffer)[i << 11], | 1120 | error = 1; |
1230 | &ftl_sparebuffer[0], 1, 1); | 1121 | memset(&((uint8_t*)buffer)[i << 11], 0, 0x800); |
1231 | for (j = 0; j < ftl_banks; j++) | ||
1232 | if (ret & (2 << (j << 2))) | ||
1233 | memset(&((uint8_t*)buffer)[(i + j) << 11], 0, 0x800); | ||
1234 | else if ((ret & (0xd << (j << 2))) || ftl_sparebuffer[j].user.eccmark != 0xFF) | ||
1235 | { | ||
1236 | error = 1; | ||
1237 | memset(&((uint8_t*)buffer)[(i + j) << 11], 0, 0x800); | ||
1238 | } | ||
1239 | i += ftl_banks - 1; | ||
1240 | } | ||
1241 | else | ||
1242 | { | ||
1243 | uint32_t ret = ftl_vfl_read(abspage, &((uint8_t*)buffer)[i << 11], | ||
1244 | &ftl_sparebuffer[0], 1, 1); | ||
1245 | if (ret & 2) memset(&((uint8_t*)buffer)[i << 11], 0, 0x800); | ||
1246 | else if ((ret & 0x11D) != 0 || ftl_sparebuffer[0].user.eccmark != 0xFF) | ||
1247 | { | ||
1248 | error = 1; | ||
1249 | memset(&((uint8_t*)buffer)[i << 11], 0, 0x800); | ||
1250 | } | ||
1251 | } | 1122 | } |
1252 | } | 1123 | } |
1253 | 1124 | ||
@@ -1380,20 +1251,20 @@ uint32_t ftl_store_ctrl_block_list(void) | |||
1380 | because it is too dirty or needs to be moved. */ | 1251 | because it is too dirty or needs to be moved. */ |
1381 | uint32_t ftl_save_erasectr_page(uint32_t index) | 1252 | uint32_t ftl_save_erasectr_page(uint32_t index) |
1382 | { | 1253 | { |
1383 | memset(&ftl_sparebuffer[0], 0xFF, 0x40); | 1254 | memset(&ftl_sparebuffer, 0xFF, 0x40); |
1384 | ftl_sparebuffer[0].meta.usn = ftl_cxt.usn; | 1255 | ftl_sparebuffer.meta.usn = ftl_cxt.usn; |
1385 | ftl_sparebuffer[0].meta.idx = index; | 1256 | ftl_sparebuffer.meta.idx = index; |
1386 | ftl_sparebuffer[0].meta.type = 0x46; | 1257 | ftl_sparebuffer.meta.type = 0x46; |
1387 | if (ftl_vfl_write(ftl_cxt.ftlctrlpage, 1, &ftl_erasectr[index << 10], | 1258 | if (ftl_vfl_write(ftl_cxt.ftlctrlpage, &ftl_erasectr[index << 10], |
1388 | &ftl_sparebuffer[0]) != 0) | 1259 | &ftl_sparebuffer) != 0) |
1389 | return 1; | 1260 | return 1; |
1390 | if ((ftl_vfl_read(ftl_cxt.ftlctrlpage, ftl_buffer, | 1261 | if ((ftl_vfl_read(ftl_cxt.ftlctrlpage, ftl_buffer, |
1391 | &ftl_sparebuffer[0], 1, 1) & 0x11F) != 0) | 1262 | &ftl_sparebuffer, 1, 1) & 0x11F) != 0) |
1392 | return 1; | 1263 | return 1; |
1393 | if (memcmp(ftl_buffer, &ftl_erasectr[index << 10], 0x800) != 0) return 1; | 1264 | if (memcmp(ftl_buffer, &ftl_erasectr[index << 10], 0x800) != 0) return 1; |
1394 | if (ftl_sparebuffer[0].meta.type != 0x46) return 1; | 1265 | if (ftl_sparebuffer.meta.type != 0x46) return 1; |
1395 | if (ftl_sparebuffer[0].meta.idx != index) return 1; | 1266 | if (ftl_sparebuffer.meta.idx != index) return 1; |
1396 | if (ftl_sparebuffer[0].meta.usn != ftl_cxt.usn) return 1; | 1267 | if (ftl_sparebuffer.meta.usn != ftl_cxt.usn) return 1; |
1397 | ftl_cxt.ftl_erasectr_pages[index] = ftl_cxt.ftlctrlpage; | 1268 | ftl_cxt.ftl_erasectr_pages[index] = ftl_cxt.ftlctrlpage; |
1398 | ftl_erasectr_dirt[index] = 0; | 1269 | ftl_erasectr_dirt[index] = 0; |
1399 | return 0; | 1270 | return 0; |
@@ -1446,17 +1317,17 @@ uint32_t ftl_copy_page(uint32_t source, uint32_t destination, | |||
1446 | uint32_t lpn, uint32_t type) | 1317 | uint32_t lpn, uint32_t type) |
1447 | { | 1318 | { |
1448 | uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks; | 1319 | uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks; |
1449 | uint32_t rc = ftl_vfl_read(source, ftl_copybuffer[0], | 1320 | uint32_t rc = ftl_vfl_read(source, ftl_copybuffer, |
1450 | &ftl_copyspare[0], 1, 1) & 0x11F; | 1321 | &ftl_sparebuffer, 1, 1) & 0x11F; |
1451 | memset(&ftl_copyspare[0], 0xFF, 0x40); | 1322 | memset(&ftl_sparebuffer, 0xFF, 0x40); |
1452 | ftl_copyspare[0].user.lpn = lpn; | 1323 | ftl_sparebuffer.user.lpn = lpn; |
1453 | ftl_copyspare[0].user.usn = ++ftl_cxt.nextblockusn; | 1324 | ftl_sparebuffer.user.usn = ++ftl_cxt.nextblockusn; |
1454 | ftl_copyspare[0].user.type = 0x40; | 1325 | ftl_sparebuffer.user.type = 0x40; |
1455 | if ((rc & 2) != 0) memset(ftl_copybuffer[0], 0, 0x800); | 1326 | if ((rc & 2) != 0) memset(ftl_copybuffer, 0, 0x800); |
1456 | else if (rc != 0) ftl_copyspare[0].user.eccmark = 0x55; | 1327 | else if (rc != 0) ftl_sparebuffer.user.eccmark = 0x55; |
1457 | if (type == 1 && destination % ppb == ppb - 1) | 1328 | if (type == 1 && destination % ppb == ppb - 1) |
1458 | ftl_copyspare[0].user.type = 0x41; | 1329 | ftl_sparebuffer.user.type = 0x41; |
1459 | return ftl_vfl_write(destination, 1, ftl_copybuffer[0], &ftl_copyspare[0]); | 1330 | return ftl_vfl_write(destination, ftl_copybuffer, &ftl_sparebuffer); |
1460 | } | 1331 | } |
1461 | #endif | 1332 | #endif |
1462 | 1333 | ||
@@ -1465,29 +1336,21 @@ uint32_t ftl_copy_page(uint32_t source, uint32_t destination, | |||
1465 | /* Copies a pBlock to a vBlock */ | 1336 | /* Copies a pBlock to a vBlock */ |
1466 | uint32_t ftl_copy_block(uint32_t source, uint32_t destination) | 1337 | uint32_t ftl_copy_block(uint32_t source, uint32_t destination) |
1467 | { | 1338 | { |
1468 | uint32_t i, j; | 1339 | uint32_t i; |
1469 | uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks; | 1340 | uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks; |
1470 | uint32_t error = 0; | 1341 | uint32_t error = 0; |
1471 | ftl_cxt.nextblockusn++; | 1342 | ftl_cxt.nextblockusn++; |
1472 | for (i = 0; i < ppb; i += FTL_COPYBUF_SIZE) | 1343 | for (i = 0; i < ppb; i++) |
1473 | { | 1344 | { |
1474 | uint32_t rc = ftl_read(source * ppb + i, | 1345 | uint32_t rc = ftl_read(source * ppb + i, 1, ftl_copybuffer); |
1475 | FTL_COPYBUF_SIZE, ftl_copybuffer[0]); | 1346 | memset(&ftl_sparebuffer, 0xFF, 0x40); |
1476 | memset(&ftl_copyspare[0], 0xFF, 0x40 * FTL_COPYBUF_SIZE); | 1347 | ftl_sparebuffer.user.lpn = source * ppb + i; |
1477 | for (j = 0; j < FTL_COPYBUF_SIZE; j++) | 1348 | ftl_sparebuffer.user.usn = ftl_cxt.nextblockusn; |
1478 | { | 1349 | ftl_sparebuffer.user.type = 0x40; |
1479 | ftl_copyspare[j].user.lpn = source * ppb + i + j; | 1350 | if (rc != 0) ftl_sparebuffer.user.eccmark = 0x55; |
1480 | ftl_copyspare[j].user.usn = ftl_cxt.nextblockusn; | 1351 | if (i == ppb - 1) ftl_sparebuffer.user.type = 0x41; |
1481 | ftl_copyspare[j].user.type = 0x40; | 1352 | if (ftl_vfl_write(destination * ppb + i, |
1482 | if (rc) | 1353 | ftl_copybuffer, &ftl_sparebuffer) != 0) |
1483 | { | ||
1484 | if (ftl_read(source * ppb + i + j, 1, ftl_copybuffer[j])) | ||
1485 | ftl_copyspare[j].user.eccmark = 0x55; | ||
1486 | } | ||
1487 | if (i + j == ppb - 1) ftl_copyspare[j].user.type = 0x41; | ||
1488 | } | ||
1489 | if (ftl_vfl_write(destination * ppb + i, FTL_COPYBUF_SIZE, | ||
1490 | ftl_copybuffer[0], &ftl_copyspare[0])) | ||
1491 | { | 1354 | { |
1492 | error = 1; | 1355 | error = 1; |
1493 | break; | 1356 | break; |
@@ -1608,37 +1471,22 @@ uint32_t ftl_commit_scattered(struct ftl_log_type* entry) | |||
1608 | If this fails for whichever reason, it will be committed the usual way. */ | 1471 | If this fails for whichever reason, it will be committed the usual way. */ |
1609 | uint32_t ftl_commit_sequential(struct ftl_log_type* entry) | 1472 | uint32_t ftl_commit_sequential(struct ftl_log_type* entry) |
1610 | { | 1473 | { |
1611 | uint32_t i; | ||
1612 | uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks; | 1474 | uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks; |
1613 | 1475 | ||
1614 | if ((*entry).issequential != 1 | 1476 | if ((*entry).issequential != 1 |
1615 | || (*entry).pagescurrent != (*entry).pagesused) | 1477 | || (*entry).pagescurrent != (*entry).pagesused) |
1616 | return 1; | 1478 | return 1; |
1617 | 1479 | ||
1618 | for (; (*entry).pagesused < ppb; ) | 1480 | for (; (*entry).pagesused < ppb; (*entry).pagesused++) |
1619 | { | 1481 | { |
1620 | uint32_t lpn = (*entry).logicalvblock * ppb + (*entry).pagesused; | 1482 | uint32_t lpn = (*entry).logicalvblock * ppb + (*entry).pagesused; |
1621 | uint32_t newpage = (*entry).scatteredvblock * ppb | 1483 | uint32_t newpage = (*entry).scatteredvblock * ppb |
1622 | + (*entry).pagesused; | 1484 | + (*entry).pagesused; |
1623 | uint32_t count = FTL_COPYBUF_SIZE < ppb - (*entry).pagesused | 1485 | uint32_t oldpage = ftl_map[(*entry).logicalvblock] * ppb |
1624 | ? FTL_COPYBUF_SIZE : ppb - (*entry).pagesused; | 1486 | + (*entry).pagesused; |
1625 | for (i = 0; i < count; i++) | 1487 | if ((*entry).pageoffsets[(*entry).pagesused] != 0xFFFF |
1626 | if ((*entry).pageoffsets[(*entry).pagesused + i] != 0xFFFF) | 1488 | || ftl_copy_page(oldpage, newpage, lpn, 1) != 0) |
1627 | return ftl_commit_scattered(entry); | ||
1628 | uint32_t rc = ftl_read(lpn, count, ftl_copybuffer[0]); | ||
1629 | memset(&ftl_copyspare[0], 0xFF, 0x40 * FTL_COPYBUF_SIZE); | ||
1630 | for (i = 0; i < count; i++) | ||
1631 | { | ||
1632 | ftl_copyspare[i].user.lpn = lpn + i; | ||
1633 | ftl_copyspare[i].user.usn = ++ftl_cxt.nextblockusn; | ||
1634 | ftl_copyspare[i].user.type = 0x40; | ||
1635 | if (rc) ftl_copyspare[i].user.eccmark = 0x55; | ||
1636 | if ((*entry).pagesused + i == ppb - 1) | ||
1637 | ftl_copyspare[i].user.type = 0x41; | ||
1638 | } | ||
1639 | if (ftl_vfl_write(newpage, count, ftl_copybuffer[0], &ftl_copyspare[0])) | ||
1640 | return ftl_commit_scattered(entry); | 1489 | return ftl_commit_scattered(entry); |
1641 | (*entry).pagesused += count; | ||
1642 | } | 1490 | } |
1643 | ftl_release_pool_block(ftl_map[(*entry).logicalvblock]); | 1491 | ftl_release_pool_block(ftl_map[(*entry).logicalvblock]); |
1644 | ftl_map[(*entry).logicalvblock] = (*entry).scatteredvblock; | 1492 | ftl_map[(*entry).logicalvblock] = (*entry).scatteredvblock; |
@@ -1705,7 +1553,6 @@ struct ftl_log_type* ftl_allocate_log_entry(uint32_t block) | |||
1705 | { | 1553 | { |
1706 | uint32_t i; | 1554 | uint32_t i; |
1707 | struct ftl_log_type* entry = ftl_get_log_entry(block); | 1555 | struct ftl_log_type* entry = ftl_get_log_entry(block); |
1708 | (*entry).usn = ftl_cxt.nextblockusn - 1; | ||
1709 | if (entry != (struct ftl_log_type*)0) return entry; | 1556 | if (entry != (struct ftl_log_type*)0) return entry; |
1710 | 1557 | ||
1711 | for (i = 0; i < 0x11; i++) | 1558 | for (i = 0; i < 0x11; i++) |
@@ -1749,7 +1596,7 @@ uint32_t ftl_commit_cxt(void) | |||
1749 | uint32_t mappages = ((*ftl_nand_type).userblocks + 0x3ff) >> 10; | 1596 | uint32_t mappages = ((*ftl_nand_type).userblocks + 0x3ff) >> 10; |
1750 | uint32_t ctrpages = ((*ftl_nand_type).userblocks + 23 + 0x3ff) >> 10; | 1597 | uint32_t ctrpages = ((*ftl_nand_type).userblocks + 23 + 0x3ff) >> 10; |
1751 | uint32_t endpage = ftl_cxt.ftlctrlpage + mappages + ctrpages + 1; | 1598 | uint32_t endpage = ftl_cxt.ftlctrlpage + mappages + ctrpages + 1; |
1752 | if (endpage >= (ftl_cxt.ftlctrlpage / ppb + 1) * ppb) | 1599 | if (endpage % ppb > ppb - 1) |
1753 | ftl_cxt.ftlctrlpage |= ppb - 1; | 1600 | ftl_cxt.ftlctrlpage |= ppb - 1; |
1754 | for (i = 0; i < ctrpages; i++) | 1601 | for (i = 0; i < ctrpages; i++) |
1755 | { | 1602 | { |
@@ -1759,21 +1606,21 @@ uint32_t ftl_commit_cxt(void) | |||
1759 | for (i = 0; i < mappages; i++) | 1606 | for (i = 0; i < mappages; i++) |
1760 | { | 1607 | { |
1761 | if (ftl_next_ctrl_pool_page() != 0) return 1; | 1608 | if (ftl_next_ctrl_pool_page() != 0) return 1; |
1762 | memset(&ftl_sparebuffer[0], 0xFF, 0x40); | 1609 | memset(&ftl_sparebuffer, 0xFF, 0x40); |
1763 | ftl_sparebuffer[0].meta.usn = ftl_cxt.usn; | 1610 | ftl_sparebuffer.meta.usn = ftl_cxt.usn; |
1764 | ftl_sparebuffer[0].meta.idx = i; | 1611 | ftl_sparebuffer.meta.idx = i; |
1765 | ftl_sparebuffer[0].meta.type = 0x44; | 1612 | ftl_sparebuffer.meta.type = 0x44; |
1766 | if (ftl_vfl_write(ftl_cxt.ftlctrlpage, 1, &ftl_map[i << 10], | 1613 | if (ftl_vfl_write(ftl_cxt.ftlctrlpage, &ftl_map[i << 10], |
1767 | &ftl_sparebuffer[0]) != 0) | 1614 | &ftl_sparebuffer) != 0) |
1768 | return 1; | 1615 | return 1; |
1769 | ftl_cxt.ftl_map_pages[i] = ftl_cxt.ftlctrlpage; | 1616 | ftl_cxt.ftl_map_pages[i] = ftl_cxt.ftlctrlpage; |
1770 | } | 1617 | } |
1771 | if (ftl_next_ctrl_pool_page() != 0) return 1; | 1618 | if (ftl_next_ctrl_pool_page() != 0) return 1; |
1772 | ftl_cxt.clean_flag = 1; | 1619 | ftl_cxt.clean_flag = 1; |
1773 | memset(&ftl_sparebuffer[0], 0xFF, 0x40); | 1620 | memset(&ftl_sparebuffer, 0xFF, 0x40); |
1774 | ftl_sparebuffer[0].meta.usn = ftl_cxt.usn; | 1621 | ftl_sparebuffer.meta.usn = ftl_cxt.usn; |
1775 | ftl_sparebuffer[0].meta.type = 0x43; | 1622 | ftl_sparebuffer.meta.type = 0x43; |
1776 | if (ftl_vfl_write(ftl_cxt.ftlctrlpage, 1, &ftl_cxt, &ftl_sparebuffer[0]) != 0) | 1623 | if (ftl_vfl_write(ftl_cxt.ftlctrlpage, &ftl_cxt, &ftl_sparebuffer) != 0) |
1777 | return 1; | 1624 | return 1; |
1778 | return 0; | 1625 | return 0; |
1779 | } | 1626 | } |
@@ -1827,7 +1674,7 @@ uint32_t ftl_swap_blocks(void) | |||
1827 | /* Exposed function: Write highlevel sectors */ | 1674 | /* Exposed function: Write highlevel sectors */ |
1828 | uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer) | 1675 | uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer) |
1829 | { | 1676 | { |
1830 | uint32_t i, j, k; | 1677 | uint32_t i, j; |
1831 | uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks; | 1678 | uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks; |
1832 | 1679 | ||
1833 | if (sector + count > (*ftl_nand_type).userblocks * ppb) | 1680 | if (sector + count > (*ftl_nand_type).userblocks * ppb) |
@@ -1847,11 +1694,11 @@ uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer) | |||
1847 | return 1; | 1694 | return 1; |
1848 | } | 1695 | } |
1849 | memset(ftl_buffer, 0xFF, 0x800); | 1696 | memset(ftl_buffer, 0xFF, 0x800); |
1850 | memset(&ftl_sparebuffer[0], 0xFF, 0x40); | 1697 | memset(&ftl_sparebuffer, 0xFF, 0x40); |
1851 | ftl_sparebuffer[0].meta.usn = ftl_cxt.usn; | 1698 | ftl_sparebuffer.meta.usn = ftl_cxt.usn; |
1852 | ftl_sparebuffer[0].meta.type = 0x47; | 1699 | ftl_sparebuffer.meta.type = 0x47; |
1853 | if (ftl_vfl_write(ftl_cxt.ftlctrlpage, 1, ftl_buffer, | 1700 | if (ftl_vfl_write(ftl_cxt.ftlctrlpage, ftl_buffer, |
1854 | &ftl_sparebuffer[0]) == 0) | 1701 | &ftl_sparebuffer) == 0) |
1855 | break; | 1702 | break; |
1856 | } | 1703 | } |
1857 | if (i == 3) | 1704 | if (i == 3) |
@@ -1888,27 +1735,16 @@ uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer) | |||
1888 | } | 1735 | } |
1889 | } | 1736 | } |
1890 | ftl_cxt.nextblockusn++; | 1737 | ftl_cxt.nextblockusn++; |
1891 | for (j = 0; j < ppb; j += FTL_WRITESPARE_SIZE) | 1738 | for (j = 0; j < ppb; j++) |
1892 | { | 1739 | { |
1893 | memset(&ftl_sparebuffer[0], 0xFF, 0x40 * FTL_WRITESPARE_SIZE); | 1740 | memset(&ftl_sparebuffer, 0xFF, 0x40); |
1894 | for (k = 0; k < FTL_WRITESPARE_SIZE; k++) | 1741 | ftl_sparebuffer.user.lpn = sector + i + j; |
1895 | { | 1742 | ftl_sparebuffer.user.usn = ftl_cxt.nextblockusn; |
1896 | ftl_sparebuffer[k].user.lpn = sector + i + j + k; | 1743 | ftl_sparebuffer.user.type = 0x40; |
1897 | ftl_sparebuffer[k].user.usn = ftl_cxt.nextblockusn; | 1744 | if (j == ppb - 1) ftl_sparebuffer.user.type = 0x41; |
1898 | ftl_sparebuffer[k].user.type = 0x40; | 1745 | while (ftl_vfl_write(vblock * ppb + j, |
1899 | if (j == ppb - 1) ftl_sparebuffer[k].user.type = 0x41; | 1746 | &((uint8_t*)buffer)[(i + j) << 11], |
1900 | } | 1747 | &ftl_sparebuffer) != 0); |
1901 | uint32_t rc = ftl_vfl_write(vblock * ppb + j, FTL_WRITESPARE_SIZE, | ||
1902 | &((uint8_t*)buffer)[(i + j) << 11], | ||
1903 | &ftl_sparebuffer[0]); | ||
1904 | if (rc) | ||
1905 | for (k = 0; k < ftl_banks; k++) | ||
1906 | if (rc & (1 << k)) | ||
1907 | { | ||
1908 | while (ftl_vfl_write(vblock * ppb + j + k, 1, | ||
1909 | &((uint8_t*)buffer)[(i + j + k) << 11], | ||
1910 | &ftl_sparebuffer[k])); | ||
1911 | } | ||
1912 | } | 1748 | } |
1913 | ftl_release_pool_block(ftl_map[block]); | 1749 | ftl_release_pool_block(ftl_map[block]); |
1914 | ftl_map[block] = vblock; | 1750 | ftl_map[block] = vblock; |
@@ -1926,40 +1762,22 @@ uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer) | |||
1926 | return 1; | 1762 | return 1; |
1927 | } | 1763 | } |
1928 | } | 1764 | } |
1929 | uint32_t cnt = FTL_WRITESPARE_SIZE; | 1765 | memset(&ftl_sparebuffer, 0xFF, 0x40); |
1930 | if (cnt > count - i) cnt = count - i; | 1766 | ftl_sparebuffer.user.lpn = sector + i; |
1931 | if (cnt > ppb - (*logentry).pagesused) cnt = ppb - (*logentry).pagesused; | 1767 | ftl_sparebuffer.user.usn = ++ftl_cxt.nextblockusn; |
1932 | if (cnt > ppb - page) cnt = ppb - page; | 1768 | ftl_sparebuffer.user.type = 0x40; |
1933 | memset(&ftl_sparebuffer[0], 0xFF, 0x40 * cnt); | ||
1934 | for (j = 0; j < cnt; j++) | ||
1935 | { | ||
1936 | ftl_sparebuffer[j].user.lpn = sector + i + j; | ||
1937 | ftl_sparebuffer[j].user.usn = ++ftl_cxt.nextblockusn; | ||
1938 | ftl_sparebuffer[j].user.type = 0x40; | ||
1939 | if ((*logentry).pagesused + j == ppb - 1 && (*logentry).issequential) | ||
1940 | ftl_sparebuffer[j].user.type = 0x41; | ||
1941 | } | ||
1942 | uint32_t abspage = (*logentry).scatteredvblock * ppb | 1769 | uint32_t abspage = (*logentry).scatteredvblock * ppb |
1943 | + (*logentry).pagesused; | 1770 | + (*logentry).pagesused++; |
1944 | (*logentry).pagesused += cnt; | 1771 | if (ftl_vfl_write(abspage, &((uint8_t*)buffer)[i << 11], |
1945 | if (ftl_vfl_write(abspage, cnt, &((uint8_t*)buffer)[i << 11], | 1772 | &ftl_sparebuffer) == 0) |
1946 | &ftl_sparebuffer[0]) == 0) | ||
1947 | { | 1773 | { |
1948 | for (j = 0; j < cnt; j++) | 1774 | if ((*logentry).pageoffsets[page] == 0xFFFF) |
1949 | { | 1775 | (*logentry).pagescurrent++; |
1950 | if ((*logentry).pageoffsets[page + j] == 0xFFFF) | 1776 | (*logentry).pageoffsets[page] = (*logentry).pagesused - 1; |
1951 | (*logentry).pagescurrent++; | 1777 | ftl_check_still_sequential(logentry, page); |
1952 | (*logentry).pageoffsets[page + j] = (*logentry).pagesused - cnt + j; | 1778 | i++; |
1953 | if ((*logentry).pagesused - cnt + j + 1 != (*logentry).pagescurrent | ||
1954 | || (*logentry).pageoffsets[page + j] != page + j) | ||
1955 | (*logentry).issequential = 0; | ||
1956 | } | ||
1957 | i += cnt; | ||
1958 | } | 1779 | } |
1959 | else panicf("FTL: Write error: %u %u %u!", | ||
1960 | (unsigned)sector, (unsigned)count, (unsigned)i); | ||
1961 | } | 1780 | } |
1962 | if ((*logentry).pagesused == ppb) ftl_remove_scattered_block(logentry); | ||
1963 | } | 1781 | } |
1964 | if (ftl_cxt.swapcounter >= 300) | 1782 | if (ftl_cxt.swapcounter >= 300) |
1965 | { | 1783 | { |
diff --git a/firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c b/firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c index 687a3179f9..3b5f88d3c2 100644 --- a/firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c +++ b/firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c | |||
@@ -89,7 +89,6 @@ uint8_t nand_tunk2[4]; | |||
89 | uint8_t nand_tunk3[4]; | 89 | uint8_t nand_tunk3[4]; |
90 | uint32_t nand_type[4]; | 90 | uint32_t nand_type[4]; |
91 | int nand_powered = 0; | 91 | int nand_powered = 0; |
92 | int nand_sequential = 0; | ||
93 | long nand_last_activity_value = -1; | 92 | long nand_last_activity_value = -1; |
94 | static long nand_stack[32]; | 93 | static long nand_stack[32]; |
95 | 94 | ||
@@ -100,14 +99,13 @@ static struct wakeup ecc_wakeup; | |||
100 | 99 | ||
101 | static uint8_t nand_data[0x800] __attribute__((aligned(16))); | 100 | static uint8_t nand_data[0x800] __attribute__((aligned(16))); |
102 | static uint8_t nand_ctrl[0x200] __attribute__((aligned(16))); | 101 | static uint8_t nand_ctrl[0x200] __attribute__((aligned(16))); |
103 | static uint8_t nand_spare[4][0x40] __attribute__((aligned(16))); | 102 | static uint8_t nand_spare[0x40] __attribute__((aligned(16))); |
104 | static uint8_t nand_ecc[0x30] __attribute__((aligned(16))); | 103 | static uint8_t nand_ecc[0x30] __attribute__((aligned(16))); |
105 | 104 | ||
106 | 105 | ||
107 | uint32_t nand_unlock(uint32_t rc) | 106 | uint32_t nand_unlock(uint32_t rc) |
108 | { | 107 | { |
109 | led(false); | 108 | led(false); |
110 | nand_last_activity_value = current_tick; | ||
111 | mutex_unlock(&nand_mtx); | 109 | mutex_unlock(&nand_mtx); |
112 | return rc; | 110 | return rc; |
113 | } | 111 | } |
@@ -216,9 +214,10 @@ uint32_t nand_wait_status_ready(uint32_t bank) | |||
216 | return nand_send_cmd(NAND_CMD_READ); | 214 | return nand_send_cmd(NAND_CMD_READ); |
217 | } | 215 | } |
218 | 216 | ||
219 | void nand_transfer_data_start(uint32_t bank, uint32_t direction, | 217 | uint32_t nand_transfer_data(uint32_t bank, uint32_t direction, |
220 | void* buffer, uint32_t size) | 218 | void* buffer, uint32_t size) |
221 | { | 219 | { |
220 | long timeout = current_tick + HZ / 50; | ||
222 | nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA); | 221 | nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA); |
223 | FMDNUM = size - 1; | 222 | FMDNUM = size - 1; |
224 | FMCTRL1 = FMCTRL1_DOREADDATA << direction; | 223 | FMCTRL1 = FMCTRL1_DOREADDATA << direction; |
@@ -232,11 +231,6 @@ void nand_transfer_data_start(uint32_t bank, uint32_t direction, | |||
232 | DMATCNT3 = (size >> 4) - 1; | 231 | DMATCNT3 = (size >> 4) - 1; |
233 | clean_dcache(); | 232 | clean_dcache(); |
234 | DMACOM3 = 4; | 233 | DMACOM3 = 4; |
235 | } | ||
236 | |||
237 | uint32_t nand_transfer_data_collect(uint32_t direction) | ||
238 | { | ||
239 | long timeout = current_tick + HZ / 50; | ||
240 | while ((DMAALLST & DMAALLST_DMABUSY3)) | 234 | while ((DMAALLST & DMAALLST_DMABUSY3)) |
241 | if (nand_timeout(timeout)) return 1; | 235 | if (nand_timeout(timeout)) return 1; |
242 | if (!direction) invalidate_dcache(); | 236 | if (!direction) invalidate_dcache(); |
@@ -246,29 +240,17 @@ uint32_t nand_transfer_data_collect(uint32_t direction) | |||
246 | return 0; | 240 | return 0; |
247 | } | 241 | } |
248 | 242 | ||
249 | uint32_t nand_transfer_data(uint32_t bank, uint32_t direction, | 243 | uint32_t ecc_decode(uint32_t size, void* databuffer, void* sparebuffer) |
250 | void* buffer, uint32_t size) | ||
251 | { | ||
252 | nand_transfer_data_start(bank, direction, buffer, size); | ||
253 | uint32_t rc = nand_transfer_data_collect(direction); | ||
254 | return rc; | ||
255 | } | ||
256 | |||
257 | void ecc_start(uint32_t size, void* databuffer, void* sparebuffer, uint32_t type) | ||
258 | { | 244 | { |
259 | mutex_lock(&ecc_mtx); | 245 | mutex_lock(&ecc_mtx); |
246 | long timeout = current_tick + HZ / 50; | ||
260 | ECC_INT_CLR = 1; | 247 | ECC_INT_CLR = 1; |
261 | SRCPND = INTMSK_ECC; | 248 | SRCPND = INTMSK_ECC; |
262 | ECC_UNK1 = size; | 249 | ECC_UNK1 = size; |
263 | ECC_DATA_PTR = (uint32_t)databuffer; | 250 | ECC_DATA_PTR = (uint32_t)databuffer; |
264 | ECC_SPARE_PTR = (uint32_t)sparebuffer; | 251 | ECC_SPARE_PTR = (uint32_t)sparebuffer; |
265 | clean_dcache(); | 252 | clean_dcache(); |
266 | ECC_CTRL = type; | 253 | ECC_CTRL = ECCCTRL_STARTDECODING; |
267 | } | ||
268 | |||
269 | uint32_t ecc_collect(void) | ||
270 | { | ||
271 | long timeout = current_tick + HZ / 50; | ||
272 | while (!(SRCPND & INTMSK_ECC)) | 254 | while (!(SRCPND & INTMSK_ECC)) |
273 | if (nand_timeout(timeout)) return ecc_unlock(1); | 255 | if (nand_timeout(timeout)) return ecc_unlock(1); |
274 | invalidate_dcache(); | 256 | invalidate_dcache(); |
@@ -277,18 +259,23 @@ uint32_t ecc_collect(void) | |||
277 | return ecc_unlock(ECC_RESULT); | 259 | return ecc_unlock(ECC_RESULT); |
278 | } | 260 | } |
279 | 261 | ||
280 | uint32_t ecc_decode(uint32_t size, void* databuffer, void* sparebuffer) | ||
281 | { | ||
282 | ecc_start(size, databuffer, sparebuffer, ECCCTRL_STARTDECODING); | ||
283 | uint32_t rc = ecc_collect(); | ||
284 | return rc; | ||
285 | } | ||
286 | |||
287 | uint32_t ecc_encode(uint32_t size, void* databuffer, void* sparebuffer) | 262 | uint32_t ecc_encode(uint32_t size, void* databuffer, void* sparebuffer) |
288 | { | 263 | { |
289 | ecc_start(size, databuffer, sparebuffer, ECCCTRL_STARTENCODING); | 264 | mutex_lock(&ecc_mtx); |
290 | ecc_collect(); | 265 | long timeout = current_tick + HZ / 50; |
291 | return 0; | 266 | ECC_INT_CLR = 1; |
267 | SRCPND = INTMSK_ECC; | ||
268 | ECC_UNK1 = size; | ||
269 | ECC_DATA_PTR = (uint32_t)databuffer; | ||
270 | ECC_SPARE_PTR = (uint32_t)sparebuffer; | ||
271 | clean_dcache(); | ||
272 | ECC_CTRL = ECCCTRL_STARTENCODING; | ||
273 | while (!(SRCPND & INTMSK_ECC)) | ||
274 | if (nand_timeout(timeout)) return ecc_unlock(1); | ||
275 | invalidate_dcache(); | ||
276 | ECC_INT_CLR = 1; | ||
277 | SRCPND = INTMSK_ECC; | ||
278 | return ecc_unlock(0); | ||
292 | } | 279 | } |
293 | 280 | ||
294 | uint32_t nand_check_empty(uint8_t* buffer) | 281 | uint32_t nand_check_empty(uint8_t* buffer) |
@@ -384,7 +371,7 @@ uint32_t nand_read_page(uint32_t bank, uint32_t page, void* databuffer, | |||
384 | uint32_t checkempty) | 371 | uint32_t checkempty) |
385 | { | 372 | { |
386 | uint8_t* data = nand_data; | 373 | uint8_t* data = nand_data; |
387 | uint8_t* spare = nand_spare[0]; | 374 | uint8_t* spare = nand_spare; |
388 | if (databuffer && !((uint32_t)databuffer & 0xf)) | 375 | if (databuffer && !((uint32_t)databuffer & 0xf)) |
389 | data = (uint8_t*)databuffer; | 376 | data = (uint8_t*)databuffer; |
390 | if (sparebuffer && !((uint32_t)sparebuffer & 0xf)) | 377 | if (sparebuffer && !((uint32_t)sparebuffer & 0xf)) |
@@ -441,11 +428,11 @@ uint32_t nand_read_page(uint32_t bank, uint32_t page, void* databuffer, | |||
441 | return nand_unlock(rc); | 428 | return nand_unlock(rc); |
442 | } | 429 | } |
443 | 430 | ||
444 | uint32_t nand_write_page_int(uint32_t bank, uint32_t page, void* databuffer, | 431 | uint32_t nand_write_page(uint32_t bank, uint32_t page, void* databuffer, |
445 | void* sparebuffer, uint32_t doecc, uint32_t wait) | 432 | void* sparebuffer, uint32_t doecc) |
446 | { | 433 | { |
447 | uint8_t* data = nand_data; | 434 | uint8_t* data = nand_data; |
448 | uint8_t* spare = nand_spare[0]; | 435 | uint8_t* spare = nand_spare; |
449 | if (databuffer && !((uint32_t)databuffer & 0xf)) | 436 | if (databuffer && !((uint32_t)databuffer & 0xf)) |
450 | data = (uint8_t*)databuffer; | 437 | data = (uint8_t*)databuffer; |
451 | if (sparebuffer && !((uint32_t)sparebuffer & 0xf)) | 438 | if (sparebuffer && !((uint32_t)sparebuffer & 0xf)) |
@@ -459,14 +446,9 @@ uint32_t nand_write_page_int(uint32_t bank, uint32_t page, void* databuffer, | |||
459 | if (spare != sparebuffer) memcpy(spare, sparebuffer, 0x40); | 446 | if (spare != sparebuffer) memcpy(spare, sparebuffer, 0x40); |
460 | } | 447 | } |
461 | else memset(spare, 0xFF, 0x40); | 448 | else memset(spare, 0xFF, 0x40); |
462 | nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA); | ||
463 | if (nand_send_cmd(NAND_CMD_PROGRAM)) return nand_unlock(1); | ||
464 | if (nand_send_address(page, databuffer ? 0 : 0x800)) | ||
465 | return nand_unlock(1); | ||
466 | if (databuffer && data != databuffer) memcpy(data, databuffer, 0x800); | ||
467 | if (databuffer) nand_transfer_data_start(bank, 1, data, 0x800); | ||
468 | if (doecc) | 449 | if (doecc) |
469 | { | 450 | { |
451 | if (databuffer && data != databuffer) memcpy(data, databuffer, 0x800); | ||
470 | if (ecc_encode(3, data, nand_ecc)) return nand_unlock(1); | 452 | if (ecc_encode(3, data, nand_ecc)) return nand_unlock(1); |
471 | memcpy(&spare[0xC], nand_ecc, 0x28); | 453 | memcpy(&spare[0xC], nand_ecc, 0x28); |
472 | memset(nand_ctrl, 0xFF, 0x200); | 454 | memset(nand_ctrl, 0xFF, 0x200); |
@@ -474,15 +456,18 @@ uint32_t nand_write_page_int(uint32_t bank, uint32_t page, void* databuffer, | |||
474 | if (ecc_encode(0, nand_ctrl, nand_ecc)) return nand_unlock(1); | 456 | if (ecc_encode(0, nand_ctrl, nand_ecc)) return nand_unlock(1); |
475 | memcpy(&spare[0x34], nand_ecc, 0xC); | 457 | memcpy(&spare[0x34], nand_ecc, 0xC); |
476 | } | 458 | } |
459 | nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA); | ||
460 | if (nand_send_cmd(NAND_CMD_PROGRAM)) return nand_unlock(1); | ||
461 | if (nand_send_address(page, databuffer ? 0 : 0x800)) | ||
462 | return nand_unlock(1); | ||
477 | if (databuffer) | 463 | if (databuffer) |
478 | if (nand_transfer_data_collect(1)) | 464 | if (nand_transfer_data(bank, 1, data, 0x800)) |
479 | return nand_unlock(1); | 465 | return nand_unlock(1); |
480 | if (sparebuffer || doecc) | 466 | if (sparebuffer || doecc) |
481 | if (nand_transfer_data(bank, 1, spare, 0x40)) | 467 | if (nand_transfer_data(bank, 1, spare, 0x40)) |
482 | return nand_unlock(1); | 468 | return nand_unlock(1); |
483 | if (nand_send_cmd(NAND_CMD_PROGCNFRM)) return nand_unlock(1); | 469 | if (nand_send_cmd(NAND_CMD_PROGCNFRM)) return nand_unlock(1); |
484 | if (wait) if (nand_wait_status_ready(bank)) return nand_unlock(1); | 470 | return nand_unlock(nand_wait_status_ready(bank)); |
485 | return nand_unlock(0); | ||
486 | } | 471 | } |
487 | 472 | ||
488 | uint32_t nand_block_erase(uint32_t bank, uint32_t page) | 473 | uint32_t nand_block_erase(uint32_t bank, uint32_t page) |
@@ -502,185 +487,6 @@ uint32_t nand_block_erase(uint32_t bank, uint32_t page) | |||
502 | return nand_unlock(0); | 487 | return nand_unlock(0); |
503 | } | 488 | } |
504 | 489 | ||
505 | uint32_t nand_read_page_fast(uint32_t page, void* databuffer, | ||
506 | void* sparebuffer, uint32_t doecc, | ||
507 | uint32_t checkempty) | ||
508 | { | ||
509 | uint32_t i, rc = 0; | ||
510 | if (((uint32_t)databuffer & 0xf) || ((uint32_t)sparebuffer & 0xf) | ||
511 | || !databuffer || !sparebuffer || !doecc) | ||
512 | { | ||
513 | for (i = 0; i < 4; i++) | ||
514 | { | ||
515 | if (nand_type[i] == 0xFFFFFFFF) continue; | ||
516 | void* databuf = (void*)0; | ||
517 | void* sparebuf = (void*)0; | ||
518 | if (databuffer) databuf = (void*)((uint32_t)databuffer + 0x800 * i); | ||
519 | if (sparebuffer) sparebuf = (void*)((uint32_t)sparebuffer + 0x40 * i); | ||
520 | uint32_t ret = nand_read_page(i, page, databuf, sparebuf, doecc, checkempty); | ||
521 | if (ret & 1) rc |= 1 << (i << 2); | ||
522 | if (ret & 2) rc |= 2 << (i << 2); | ||
523 | if (ret & 0x10) rc |= 4 << (i << 2); | ||
524 | if (ret & 0x100) rc |= 8 << (i << 2); | ||
525 | } | ||
526 | return rc; | ||
527 | } | ||
528 | mutex_lock(&nand_mtx); | ||
529 | nand_last_activity_value = current_tick; | ||
530 | led(true); | ||
531 | if (!nand_powered) nand_power_up(); | ||
532 | uint8_t status[4]; | ||
533 | for (i = 0; i < 4; i++) status[i] = (nand_type[i] == 0xFFFFFFFF); | ||
534 | if (!status[0]) | ||
535 | { | ||
536 | nand_set_fmctrl0(0, FMCTRL0_ENABLEDMA); | ||
537 | if (nand_send_cmd(NAND_CMD_READ)) | ||
538 | status[0] = 1; | ||
539 | } | ||
540 | if (!status[0]) | ||
541 | if (nand_send_address(page, 0)) | ||
542 | status[0] = 1; | ||
543 | if (!status[0]) | ||
544 | if (nand_send_cmd(NAND_CMD_READ2)) | ||
545 | status[0] = 1; | ||
546 | if (!status[0]) | ||
547 | if (nand_wait_status_ready(0)) | ||
548 | status[0] = 1; | ||
549 | if (!status[0]) | ||
550 | if (nand_transfer_data(0, 0, databuffer, 0x800)) | ||
551 | status[0] = 1; | ||
552 | if (!status[0]) | ||
553 | if (nand_transfer_data(0, 0, sparebuffer, 0x40)) | ||
554 | status[0] = 1; | ||
555 | for (i = 1; i < 4; i++) | ||
556 | { | ||
557 | if (!status[i]) | ||
558 | { | ||
559 | nand_set_fmctrl0(i, FMCTRL0_ENABLEDMA); | ||
560 | if (nand_send_cmd(NAND_CMD_READ)) | ||
561 | status[i] = 1; | ||
562 | } | ||
563 | if (!status[i]) | ||
564 | if (nand_send_address(page, 0)) | ||
565 | status[i] = 1; | ||
566 | if (!status[i]) | ||
567 | if (nand_send_cmd(NAND_CMD_READ2)) | ||
568 | status[i] = 1; | ||
569 | if (!status[i]) | ||
570 | if (nand_wait_status_ready(i)) | ||
571 | status[i] = 1; | ||
572 | if (!status[i]) | ||
573 | nand_transfer_data_start(i, 0, (void*)((uint32_t)databuffer | ||
574 | + 0x800 * i), 0x800); | ||
575 | if (!status[i - 1]) | ||
576 | { | ||
577 | memcpy(nand_ecc, (void*)((uint32_t)sparebuffer + 0x40 * (i - 1) + 0xC), 0x28); | ||
578 | ecc_start(3, (void*)((uint32_t)databuffer | ||
579 | + 0x800 * (i - 1)), nand_ecc, ECCCTRL_STARTDECODING); | ||
580 | } | ||
581 | if (!status[i]) | ||
582 | if (nand_transfer_data_collect(0)) | ||
583 | status[i] = 1; | ||
584 | if (!status[i]) | ||
585 | nand_transfer_data_start(i, 0, (void*)((uint32_t)sparebuffer | ||
586 | + 0x40 * i), 0x40); | ||
587 | if (!status[i - 1]) | ||
588 | if (ecc_collect() & 1) | ||
589 | status[i - 1] = 4; | ||
590 | if (!status[i - 1]) | ||
591 | { | ||
592 | memset(nand_ctrl, 0xFF, 0x200); | ||
593 | memcpy(nand_ctrl, (void*)((uint32_t)sparebuffer + 0x40 * (i - 1)), 0xC); | ||
594 | memcpy(nand_ecc, (void*)((uint32_t)sparebuffer + 0x40 * (i - 1) + 0x34), 0xC); | ||
595 | ecc_start(0, nand_ctrl, nand_ecc, ECCCTRL_STARTDECODING); | ||
596 | } | ||
597 | if (!status[i]) | ||
598 | if (nand_transfer_data_collect(0)) | ||
599 | status[i] = 1; | ||
600 | if (!status[i - 1]) | ||
601 | { | ||
602 | if (ecc_collect() & 1) | ||
603 | { | ||
604 | status[i - 1] |= 8; | ||
605 | memset((void*)((uint32_t)sparebuffer + 0x40 * (i - 1)), 0xFF, 0xC); | ||
606 | } | ||
607 | else memcpy((void*)((uint32_t)sparebuffer + 0x40 * (i - 1)), nand_ctrl, 0xC); | ||
608 | if (checkempty) | ||
609 | status[i - 1] |= nand_check_empty((void*)((uint32_t)sparebuffer | ||
610 | + 0x40 * (i - 1))) << 1; | ||
611 | } | ||
612 | } | ||
613 | if (!status[i - 1]) | ||
614 | { | ||
615 | memcpy(nand_ecc,(void*)((uint32_t)sparebuffer + 0x40 * (i - 1) + 0xC), 0x28); | ||
616 | if (ecc_decode(3, (void*)((uint32_t)databuffer | ||
617 | + 0x800 * (i - 1)), nand_ecc) & 1) | ||
618 | status[i - 1] = 4; | ||
619 | } | ||
620 | if (!status[i - 1]) | ||
621 | { | ||
622 | memset(nand_ctrl, 0xFF, 0x200); | ||
623 | memcpy(nand_ctrl, (void*)((uint32_t)sparebuffer + 0x40 * (i - 1)), 0xC); | ||
624 | memcpy(nand_ecc, (void*)((uint32_t)sparebuffer + 0x40 * (i - 1) + 0x34), 0xC); | ||
625 | if (ecc_decode(0, nand_ctrl, nand_ecc) & 1) | ||
626 | { | ||
627 | status[i - 1] |= 8; | ||
628 | memset((void*)((uint32_t)sparebuffer + 0x40 * (i - 1)), 0xFF, 0xC); | ||
629 | } | ||
630 | else memcpy((void*)((uint32_t)sparebuffer + 0x40 * (i - 1)), nand_ctrl, 0xC); | ||
631 | if (checkempty) | ||
632 | status[i - 1] |= nand_check_empty((void*)((uint32_t)sparebuffer | ||
633 | + 0x40 * (i - 1))) << 1; | ||
634 | } | ||
635 | for (i = 0; i < 4; i++) | ||
636 | if (nand_type[i] != 0xFFFFFFFF) | ||
637 | rc |= status[i] << (i << 2); | ||
638 | return nand_unlock(rc); | ||
639 | } | ||
640 | |||
641 | uint32_t nand_write_page(uint32_t bank, uint32_t page, void* databuffer, | ||
642 | void* sparebuffer, uint32_t doecc) | ||
643 | { | ||
644 | return nand_write_page_int(bank, page, databuffer, sparebuffer, doecc, 1); | ||
645 | } | ||
646 | |||
647 | uint32_t nand_write_page_start(uint32_t bank, uint32_t page, void* databuffer, | ||
648 | void* sparebuffer, uint32_t doecc) | ||
649 | { | ||
650 | if (((uint32_t)databuffer & 0xf) || ((uint32_t)sparebuffer & 0xf) | ||
651 | || !databuffer || !sparebuffer || !doecc || nand_sequential) | ||
652 | return nand_write_page_int(bank, page, databuffer, sparebuffer, doecc, nand_sequential); | ||
653 | |||
654 | mutex_lock(&nand_mtx); | ||
655 | nand_last_activity_value = current_tick; | ||
656 | led(true); | ||
657 | if (!nand_powered) nand_power_up(); | ||
658 | nand_set_fmctrl0(bank, FMCTRL0_ENABLEDMA); | ||
659 | if (nand_send_cmd(NAND_CMD_PROGRAM)) | ||
660 | return nand_unlock(1); | ||
661 | if (nand_send_address(page, 0)) | ||
662 | return nand_unlock(1); | ||
663 | nand_transfer_data_start(bank, 1, databuffer, 0x800); | ||
664 | if (ecc_encode(3, databuffer, nand_ecc)) | ||
665 | return nand_unlock(1); | ||
666 | memcpy((void*)((uint32_t)sparebuffer + 0xC), nand_ecc, 0x28); | ||
667 | memset(nand_ctrl, 0xFF, 0x200); | ||
668 | memcpy(nand_ctrl, sparebuffer, 0xC); | ||
669 | if (ecc_encode(0, nand_ctrl, nand_ecc)) | ||
670 | return nand_unlock(1); | ||
671 | memcpy((void*)((uint32_t)sparebuffer + 0x34), nand_ecc, 0xC); | ||
672 | if (nand_transfer_data_collect(0)) | ||
673 | return nand_unlock(1); | ||
674 | if (nand_transfer_data(bank, 1, sparebuffer, 0x40)) | ||
675 | return nand_unlock(1); | ||
676 | return nand_unlock(nand_send_cmd(NAND_CMD_PROGCNFRM)); | ||
677 | } | ||
678 | |||
679 | uint32_t nand_write_page_collect(uint32_t bank) | ||
680 | { | ||
681 | return nand_wait_status_ready(bank); | ||
682 | } | ||
683 | |||
684 | const struct nand_device_info_type* nand_get_device_type(uint32_t bank) | 490 | const struct nand_device_info_type* nand_get_device_type(uint32_t bank) |
685 | { | 491 | { |
686 | if (nand_type[bank] == 0xFFFFFFFF) | 492 | if (nand_type[bank] == 0xFFFFFFFF) |
@@ -739,7 +545,6 @@ uint32_t nand_device_init(void) | |||
739 | nand_tunk3[i] = nand_deviceinfotable[nand_type[i]].tunk3; | 545 | nand_tunk3[i] = nand_deviceinfotable[nand_type[i]].tunk3; |
740 | } | 546 | } |
741 | if (nand_type[0] == 0xFFFFFFFF) return 1; | 547 | if (nand_type[0] == 0xFFFFFFFF) return 1; |
742 | nand_sequential = !((nand_type[0] >> 22) & 1); | ||
743 | 548 | ||
744 | nand_last_activity_value = current_tick; | 549 | nand_last_activity_value = current_tick; |
745 | create_thread(nand_thread, nand_stack, | 550 | create_thread(nand_thread, nand_stack, |
diff --git a/firmware/target/arm/s5l8700/ipodnano2g/nand-target.h b/firmware/target/arm/s5l8700/ipodnano2g/nand-target.h index aad15b2910..dee690e5e6 100644 --- a/firmware/target/arm/s5l8700/ipodnano2g/nand-target.h +++ b/firmware/target/arm/s5l8700/ipodnano2g/nand-target.h | |||
@@ -46,13 +46,6 @@ uint32_t nand_write_page(uint32_t bank, uint32_t page, void* databuffer, | |||
46 | void* sparebuffer, uint32_t doecc); | 46 | void* sparebuffer, uint32_t doecc); |
47 | uint32_t nand_block_erase(uint32_t bank, uint32_t page); | 47 | uint32_t nand_block_erase(uint32_t bank, uint32_t page); |
48 | 48 | ||
49 | uint32_t nand_read_page_fast(uint32_t page, void* databuffer, | ||
50 | void* sparebuffer, uint32_t doecc, | ||
51 | uint32_t checkempty); | ||
52 | uint32_t nand_write_page_start(uint32_t bank, uint32_t page, void* databuffer, | ||
53 | void* sparebuffer, uint32_t doecc); | ||
54 | uint32_t nand_write_page_collect(uint32_t bank); | ||
55 | |||
56 | const struct nand_device_info_type* nand_get_device_type(uint32_t bank); | 49 | const struct nand_device_info_type* nand_get_device_type(uint32_t bank); |
57 | uint32_t nand_reset(uint32_t bank); | 50 | uint32_t nand_reset(uint32_t bank); |
58 | uint32_t nand_device_init(void); | 51 | uint32_t nand_device_init(void); |