diff options
Diffstat (limited to 'firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c')
-rw-r--r-- | firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c | 430 |
1 files changed, 124 insertions, 306 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 | { |