summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c430
-rw-r--r--firmware/target/arm/s5l8700/ipodnano2g/nand-nano2g.c261
-rw-r--r--firmware/target/arm/s5l8700/ipodnano2g/nand-target.h7
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;
374uint8_t ftl_buffer[0x800] __attribute__((aligned(16))); 372uint8_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 */
377union ftl_spare_data_type ftl_sparebuffer[FTL_WRITESPARE_SIZE] __attribute__((aligned(16))); 375union 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. */
407uint8_t ftl_copybuffer[FTL_COPYBUF_SIZE][0x800] __attribute__((aligned(16))); 405uint8_t ftl_copybuffer[0x800] __attribute__((aligned(16)));
408union 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
854uint32_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) 852uint32_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 */
921uint32_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 */
1194uint32_t ftl_read(uint32_t sector, uint32_t count, void* buffer) 1087uint32_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. */
1381uint32_t ftl_save_erasectr_page(uint32_t index) 1252uint32_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 */
1466uint32_t ftl_copy_block(uint32_t source, uint32_t destination) 1337uint32_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. */
1609uint32_t ftl_commit_sequential(struct ftl_log_type* entry) 1472uint32_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 */
1828uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer) 1675uint32_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];
89uint8_t nand_tunk3[4]; 89uint8_t nand_tunk3[4];
90uint32_t nand_type[4]; 90uint32_t nand_type[4];
91int nand_powered = 0; 91int nand_powered = 0;
92int nand_sequential = 0;
93long nand_last_activity_value = -1; 92long nand_last_activity_value = -1;
94static long nand_stack[32]; 93static long nand_stack[32];
95 94
@@ -100,14 +99,13 @@ static struct wakeup ecc_wakeup;
100 99
101static uint8_t nand_data[0x800] __attribute__((aligned(16))); 100static uint8_t nand_data[0x800] __attribute__((aligned(16)));
102static uint8_t nand_ctrl[0x200] __attribute__((aligned(16))); 101static uint8_t nand_ctrl[0x200] __attribute__((aligned(16)));
103static uint8_t nand_spare[4][0x40] __attribute__((aligned(16))); 102static uint8_t nand_spare[0x40] __attribute__((aligned(16)));
104static uint8_t nand_ecc[0x30] __attribute__((aligned(16))); 103static uint8_t nand_ecc[0x30] __attribute__((aligned(16)));
105 104
106 105
107uint32_t nand_unlock(uint32_t rc) 106uint32_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
219void nand_transfer_data_start(uint32_t bank, uint32_t direction, 217uint32_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
237uint32_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
249uint32_t nand_transfer_data(uint32_t bank, uint32_t direction, 243uint32_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
257void 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
269uint32_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
280uint32_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
287uint32_t ecc_encode(uint32_t size, void* databuffer, void* sparebuffer) 262uint32_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
294uint32_t nand_check_empty(uint8_t* buffer) 281uint32_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
444uint32_t nand_write_page_int(uint32_t bank, uint32_t page, void* databuffer, 431uint32_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
488uint32_t nand_block_erase(uint32_t bank, uint32_t page) 473uint32_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
505uint32_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
641uint32_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
647uint32_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
679uint32_t nand_write_page_collect(uint32_t bank)
680{
681 return nand_wait_status_ready(bank);
682}
683
684const struct nand_device_info_type* nand_get_device_type(uint32_t bank) 490const 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);
47uint32_t nand_block_erase(uint32_t bank, uint32_t page); 47uint32_t nand_block_erase(uint32_t bank, uint32_t page);
48 48
49uint32_t nand_read_page_fast(uint32_t page, void* databuffer,
50 void* sparebuffer, uint32_t doecc,
51 uint32_t checkempty);
52uint32_t nand_write_page_start(uint32_t bank, uint32_t page, void* databuffer,
53 void* sparebuffer, uint32_t doecc);
54uint32_t nand_write_page_collect(uint32_t bank);
55
56const struct nand_device_info_type* nand_get_device_type(uint32_t bank); 49const struct nand_device_info_type* nand_get_device_type(uint32_t bank);
57uint32_t nand_reset(uint32_t bank); 50uint32_t nand_reset(uint32_t bank);
58uint32_t nand_device_init(void); 51uint32_t nand_device_init(void);