diff options
author | Michael Sparmann <theseven@rockbox.org> | 2010-08-12 08:49:54 +0000 |
---|---|---|
committer | Michael Sparmann <theseven@rockbox.org> | 2010-08-12 08:49:54 +0000 |
commit | c65a8e07552711f6a62bcdc195adbf9ff0345c0e (patch) | |
tree | a5a29f5504cc0af9d66464c6d26797bf7ac229ac /firmware | |
parent | b4d6d1e64392177f91adb2327f00f24091c0d56d (diff) | |
download | rockbox-c65a8e07552711f6a62bcdc195adbf9ff0345c0e.tar.gz rockbox-c65a8e07552711f6a62bcdc195adbf9ff0345c0e.zip |
emBIOS backports part four: Add a lot of DEBUGF()s to the FTL code, and return proper error codes instead of panicing in a lot of error cases.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27783 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c | 205 |
1 files changed, 157 insertions, 48 deletions
diff --git a/firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c b/firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c index 69fac62289..f7c636d7bd 100644 --- a/firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c +++ b/firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include "system.h" | 29 | #include "system.h" |
30 | #include "kernel.h" | 30 | #include "kernel.h" |
31 | #include "panic.h" | 31 | #include "panic.h" |
32 | #include "debug.h" | ||
32 | 33 | ||
33 | 34 | ||
34 | 35 | ||
@@ -183,7 +184,7 @@ struct ftl_cxt_type | |||
183 | 184 | ||
184 | /* Keeps the state of the bank's VFL, both on flash and in memory. | 185 | /* Keeps the state of the bank's VFL, both on flash and in memory. |
185 | There is one of these per bank. */ | 186 | There is one of these per bank. */ |
186 | typedef struct ftl_vfl_cxt_type | 187 | struct ftl_vfl_cxt_type |
187 | { | 188 | { |
188 | 189 | ||
189 | /* Cross-bank update sequence number, incremented on every VFL | 190 | /* Cross-bank update sequence number, incremented on every VFL |
@@ -252,7 +253,7 @@ typedef struct ftl_vfl_cxt_type | |||
252 | /* Second checksum (XOR), there is a bug in whimory regarding this. */ | 253 | /* Second checksum (XOR), there is a bug in whimory regarding this. */ |
253 | uint32_t checksum2; | 254 | uint32_t checksum2; |
254 | 255 | ||
255 | } __attribute__((packed)) FTLVFLCxtType; | 256 | } __attribute__((packed)); |
256 | 257 | ||
257 | 258 | ||
258 | /* Layout of the spare bytes of each page on the flash */ | 259 | /* Layout of the spare bytes of each page on the flash */ |
@@ -513,7 +514,7 @@ static uint32_t ftl_vfl_verify_checksum(uint32_t bank) | |||
513 | /* The following line is pretty obviously a bug in Whimory, | 514 | /* The following line is pretty obviously a bug in Whimory, |
514 | but we do it the same way for compatibility. */ | 515 | but we do it the same way for compatibility. */ |
515 | if (checksum2 != ftl_vfl_cxt[bank].checksum2) return 0; | 516 | if (checksum2 != ftl_vfl_cxt[bank].checksum2) return 0; |
516 | panicf("FTL: Bad VFL CXT checksum!"); | 517 | DEBUGF("FTL: Bad VFL CXT checksum on bank %d!\n", bank); |
517 | return 1; | 518 | return 1; |
518 | } | 519 | } |
519 | 520 | ||
@@ -577,6 +578,7 @@ static uint32_t ftl_vfl_store_cxt(uint32_t bank) | |||
577 | retries until it works or all available pages have been tried */ | 578 | retries until it works or all available pages have been tried */ |
578 | static uint32_t ftl_vfl_commit_cxt(uint32_t bank) | 579 | static uint32_t ftl_vfl_commit_cxt(uint32_t bank) |
579 | { | 580 | { |
581 | DEBUGF("FTL: VFL: Committing context on bank %d\n", bank); | ||
580 | if (ftl_vfl_cxt[bank].nextcxtpage + 8 <= ftl_nand_type->pagesperblock) | 582 | if (ftl_vfl_cxt[bank].nextcxtpage + 8 <= ftl_nand_type->pagesperblock) |
581 | if (ftl_vfl_store_cxt(bank) == 0) return 0; | 583 | if (ftl_vfl_store_cxt(bank) == 0) return 0; |
582 | uint32_t current = ftl_vfl_cxt[bank].activecxtblock; | 584 | uint32_t current = ftl_vfl_cxt[bank].activecxtblock; |
@@ -595,7 +597,7 @@ static uint32_t ftl_vfl_commit_cxt(uint32_t bank) | |||
595 | ftl_vfl_cxt[bank].nextcxtpage = 0; | 597 | ftl_vfl_cxt[bank].nextcxtpage = 0; |
596 | if (ftl_vfl_store_cxt(bank) == 0) return 0; | 598 | if (ftl_vfl_store_cxt(bank) == 0) return 0; |
597 | } | 599 | } |
598 | panicf("FTL: Failed to commit VFL CXT!"); | 600 | panicf("VFL: Failed to commit VFL CXT!"); |
599 | return 1; | 601 | return 1; |
600 | } | 602 | } |
601 | #endif | 603 | #endif |
@@ -678,7 +680,11 @@ static uint32_t ftl_vfl_get_physical_block(uint32_t bank, uint32_t block) | |||
678 | uint32_t spareused = ftl_vfl_cxt[bank].spareused; | 680 | uint32_t spareused = ftl_vfl_cxt[bank].spareused; |
679 | for (spareindex = 0; spareindex < spareused; spareindex++) | 681 | for (spareindex = 0; spareindex < spareused; spareindex++) |
680 | if (ftl_vfl_cxt[bank].remaptable[spareindex] == block) | 682 | if (ftl_vfl_cxt[bank].remaptable[spareindex] == block) |
683 | { | ||
684 | DEBUGF("FTL: VFL: Following remapped block: %d => %d\n", | ||
685 | block, ftl_vfl_cxt[bank].firstspare + spareindex); | ||
681 | return ftl_vfl_cxt[bank].firstspare + spareindex; | 686 | return ftl_vfl_cxt[bank].firstspare + spareindex; |
687 | } | ||
682 | return block; | 688 | return block; |
683 | } | 689 | } |
684 | 690 | ||
@@ -816,13 +822,19 @@ static uint32_t ftl_vfl_remap_block(uint32_t bank, uint32_t block) | |||
816 | static uint32_t ftl_vfl_read(uint32_t vpage, void* buffer, void* sparebuffer, | 822 | static uint32_t ftl_vfl_read(uint32_t vpage, void* buffer, void* sparebuffer, |
817 | uint32_t checkempty, uint32_t remaponfail) | 823 | uint32_t checkempty, uint32_t remaponfail) |
818 | { | 824 | { |
825 | #ifdef VFL_TRACE | ||
826 | DEBUGF("FTL: VFL: Reading page %d\n", vpage); | ||
827 | #endif | ||
828 | |||
819 | uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks; | 829 | uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks; |
820 | uint32_t syshyperblocks = ftl_nand_type->blocks | 830 | uint32_t syshyperblocks = ftl_nand_type->blocks |
821 | - ftl_nand_type->userblocks - 0x17; | 831 | - ftl_nand_type->userblocks - 0x17; |
822 | uint32_t abspage = vpage + ppb * syshyperblocks; | 832 | uint32_t abspage = vpage + ppb * syshyperblocks; |
823 | if (abspage >= ftl_nand_type->blocks * ppb || abspage < ppb) | 833 | if (abspage >= ftl_nand_type->blocks * ppb || abspage < ppb) |
824 | panicf("FTL: Trying to read out-of-bounds vPage %u", (unsigned)vpage); | 834 | { |
825 | //return 4; | 835 | DEBUGF("FTL: Trying to read out-of-bounds vPage %u\n", (unsigned)vpage); |
836 | return 4; | ||
837 | } | ||
826 | 838 | ||
827 | uint32_t bank = abspage % ftl_banks; | 839 | uint32_t bank = abspage % ftl_banks; |
828 | uint32_t block = abspage / (ftl_nand_type->pagesperblock * ftl_banks); | 840 | uint32_t block = abspage / (ftl_nand_type->pagesperblock * ftl_banks); |
@@ -842,7 +854,10 @@ static uint32_t ftl_vfl_read(uint32_t vpage, void* buffer, void* sparebuffer, | |||
842 | (void)remaponfail; | 854 | (void)remaponfail; |
843 | #else | 855 | #else |
844 | if (remaponfail == 1 &&(ret & 0x11D) != 0 && (ret & 2) == 0) | 856 | if (remaponfail == 1 &&(ret & 0x11D) != 0 && (ret & 2) == 0) |
857 | { | ||
858 | DEBUGF("FTL: VFL: Scheduling vBlock %d for remapping!\n", block); | ||
845 | ftl_vfl_schedule_block_for_remap(bank, block); | 859 | ftl_vfl_schedule_block_for_remap(bank, block); |
860 | } | ||
846 | #endif | 861 | #endif |
847 | return ret; | 862 | return ret; |
848 | } | 863 | } |
@@ -855,14 +870,20 @@ static uint32_t ftl_vfl_read(uint32_t vpage, void* buffer, void* sparebuffer, | |||
855 | static uint32_t ftl_vfl_read_fast(uint32_t vpage, void* buffer, void* sparebuffer, | 870 | static uint32_t ftl_vfl_read_fast(uint32_t vpage, void* buffer, void* sparebuffer, |
856 | uint32_t checkempty, uint32_t remaponfail) | 871 | uint32_t checkempty, uint32_t remaponfail) |
857 | { | 872 | { |
873 | #ifdef VFL_TRACE | ||
874 | DEBUGF("FTL: VFL: Fast reading page %d on all banks\n", vpage); | ||
875 | #endif | ||
876 | |||
858 | uint32_t i, rc = 0; | 877 | uint32_t i, rc = 0; |
859 | uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks; | 878 | uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks; |
860 | uint32_t syshyperblocks = ftl_nand_type->blocks | 879 | uint32_t syshyperblocks = ftl_nand_type->blocks |
861 | - ftl_nand_type->userblocks - 0x17; | 880 | - ftl_nand_type->userblocks - 0x17; |
862 | uint32_t abspage = vpage + ppb * syshyperblocks; | 881 | uint32_t abspage = vpage + ppb * syshyperblocks; |
863 | if (abspage + ftl_banks - 1 >= ftl_nand_type->blocks * ppb || abspage < ppb) | 882 | if (abspage + ftl_banks - 1 >= ftl_nand_type->blocks * ppb || abspage < ppb) |
864 | panicf("FTL: Trying to read out-of-bounds vPage %u", (unsigned)vpage); | 883 | { |
865 | //return 4; | 884 | DEBUGF("FTL: Trying to read out-of-bounds vPage %u\n", (unsigned)vpage); |
885 | return 4; | ||
886 | } | ||
866 | 887 | ||
867 | uint32_t bank = abspage % ftl_banks; | 888 | uint32_t bank = abspage % ftl_banks; |
868 | uint32_t block = abspage / (ftl_nand_type->pagesperblock * ftl_banks); | 889 | uint32_t block = abspage / (ftl_nand_type->pagesperblock * ftl_banks); |
@@ -926,14 +947,20 @@ static uint32_t ftl_vfl_write(uint32_t vpage, uint32_t count, | |||
926 | void* buffer, void* sparebuffer) | 947 | void* buffer, void* sparebuffer) |
927 | { | 948 | { |
928 | uint32_t i, j; | 949 | uint32_t i, j; |
950 | #ifdef VFL_TRACE | ||
951 | DEBUGF("FTL: VFL: Writing page %d\n", vpage); | ||
952 | #endif | ||
953 | |||
929 | uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks; | 954 | uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks; |
930 | uint32_t syshyperblocks = ftl_nand_type->blocks | 955 | uint32_t syshyperblocks = ftl_nand_type->blocks |
931 | - ftl_nand_type->userblocks - 0x17; | 956 | - ftl_nand_type->userblocks - 0x17; |
932 | uint32_t abspage = vpage + ppb * syshyperblocks; | 957 | uint32_t abspage = vpage + ppb * syshyperblocks; |
933 | if (abspage + count > ftl_nand_type->blocks * ppb || abspage < ppb) | 958 | if (abspage + count > ftl_nand_type->blocks * ppb || abspage < ppb) |
934 | panicf("FTL: Trying to write out-of-bounds vPage %u", | 959 | { |
960 | DEBUGF("FTL: Trying to write out-of-bounds vPage %u\n", | ||
935 | (unsigned)vpage); | 961 | (unsigned)vpage); |
936 | //return 4; | 962 | return 4; |
963 | } | ||
937 | 964 | ||
938 | uint32_t bank[5]; | 965 | uint32_t bank[5]; |
939 | uint32_t block[5]; | 966 | uint32_t block[5]; |
@@ -997,7 +1024,7 @@ static uint32_t ftl_vfl_open(void) | |||
997 | { | 1024 | { |
998 | uint32_t i, j, k; | 1025 | uint32_t i, j, k; |
999 | uint32_t minusn, vflcxtidx, last; | 1026 | uint32_t minusn, vflcxtidx, last; |
1000 | FTLVFLCxtType* cxt; | 1027 | struct ftl_vfl_cxt_type* cxt; |
1001 | uint16_t vflcxtblock[4]; | 1028 | uint16_t vflcxtblock[4]; |
1002 | #ifndef FTL_READONLY | 1029 | #ifndef FTL_READONLY |
1003 | ftl_vfl_usn = 0; | 1030 | ftl_vfl_usn = 0; |
@@ -1042,9 +1069,12 @@ static uint32_t ftl_vfl_open(void) | |||
1042 | minusn = ftl_sparebuffer[0].meta.usn; | 1069 | minusn = ftl_sparebuffer[0].meta.usn; |
1043 | vflcxtidx = k; | 1070 | vflcxtidx = k; |
1044 | } | 1071 | } |
1045 | if (vflcxtidx == 4) //return 1; | 1072 | if (vflcxtidx == 4) |
1046 | panicf("FTL: No VFL CXT block found on bank %u!", | 1073 | { |
1074 | DEBUGF("FTL: No VFL CXT block found on bank %u!\n", | ||
1047 | (unsigned)i); | 1075 | (unsigned)i); |
1076 | return 1; | ||
1077 | } | ||
1048 | last = 0; | 1078 | last = 0; |
1049 | uint32_t max = ftl_nand_type->pagesperblock; | 1079 | uint32_t max = ftl_nand_type->pagesperblock; |
1050 | for (k = 8; k < max; k += 8) | 1080 | for (k = 8; k < max; k += 8) |
@@ -1070,8 +1100,11 @@ static uint32_t ftl_vfl_open(void) | |||
1070 | break; | 1100 | break; |
1071 | } | 1101 | } |
1072 | } | 1102 | } |
1073 | else //return 1; | 1103 | else |
1074 | panicf("FTL: Couldn't load bank %u lowlevel BBT!", (unsigned)i); | 1104 | { |
1105 | DEBUGF("FTL: Couldn't load bank %u lowlevel BBT!\n", (unsigned)i); | ||
1106 | return 1; | ||
1107 | } | ||
1075 | cxt = ftl_vfl_get_newest_cxt(); | 1108 | cxt = ftl_vfl_get_newest_cxt(); |
1076 | for (i = 0; i < ftl_banks; i++) | 1109 | for (i = 0; i < ftl_banks; i++) |
1077 | memcpy(ftl_vfl_cxt[i].ftlctrlblocks, cxt->ftlctrlblocks, 6); | 1110 | memcpy(ftl_vfl_cxt[i].ftlctrlblocks, cxt->ftlctrlblocks, 6); |
@@ -1101,9 +1134,13 @@ static uint32_t ftl_open(void) | |||
1101 | ftlcxtblock = cxt->ftlctrlblocks[i]; | 1134 | ftlcxtblock = cxt->ftlctrlblocks[i]; |
1102 | } | 1135 | } |
1103 | 1136 | ||
1104 | if (ftlcxtblock == 0xffffffff) //return 1; | 1137 | if (ftlcxtblock == 0xffffffff) |
1105 | panicf("FTL: Couldn't find readable FTL CXT block!"); | 1138 | { |
1139 | DEBUGF("FTL: Couldn't find readable FTL CXT block!\n"); | ||
1140 | return 1; | ||
1141 | } | ||
1106 | 1142 | ||
1143 | DEBUGF("FTL: Found FTL context block: vBlock %d\n", ftlcxtblock); | ||
1107 | uint32_t ftlcxtfound = 0; | 1144 | uint32_t ftlcxtfound = 0; |
1108 | for (i = ftl_nand_type->pagesperblock * ftl_banks - 1; i > 0; i--) | 1145 | for (i = ftl_nand_type->pagesperblock * ftl_banks - 1; i > 0; i--) |
1109 | { | 1146 | { |
@@ -1119,15 +1156,20 @@ static uint32_t ftl_open(void) | |||
1119 | else | 1156 | else |
1120 | { | 1157 | { |
1121 | /* This will trip if there was an unclean unmount before. */ | 1158 | /* This will trip if there was an unclean unmount before. */ |
1122 | #ifndef FTL_FORCEMOUNT | 1159 | DEBUGF("FTL: Unclean shutdown before!\n"); |
1123 | panicf("FTL: Unclean shutdown before!"); | 1160 | #ifdef FTL_FORCEMOUNT |
1161 | DEBUGF("FTL: Forcing mount nevertheless...\n"); | ||
1162 | #else | ||
1124 | break; | 1163 | break; |
1125 | #endif | 1164 | #endif |
1126 | } | 1165 | } |
1127 | } | 1166 | } |
1128 | 1167 | ||
1129 | if (ftlcxtfound == 0) //return 1; | 1168 | if (ftlcxtfound == 0) |
1130 | panicf("FTL: Couldn't find FTL CXT page!"); | 1169 | { |
1170 | DEBUGF("FTL: Couldn't find FTL CXT page!\n"); | ||
1171 | return 1; | ||
1172 | } | ||
1131 | 1173 | ||
1132 | uint32_t pagestoread = ftl_nand_type->userblocks >> 10; | 1174 | uint32_t pagestoread = ftl_nand_type->userblocks >> 10; |
1133 | if ((ftl_nand_type->userblocks & 0x1FF) != 0) pagestoread++; | 1175 | if ((ftl_nand_type->userblocks & 0x1FF) != 0) pagestoread++; |
@@ -1136,8 +1178,10 @@ static uint32_t ftl_open(void) | |||
1136 | { | 1178 | { |
1137 | if ((ftl_vfl_read(ftl_cxt.ftl_map_pages[i], | 1179 | if ((ftl_vfl_read(ftl_cxt.ftl_map_pages[i], |
1138 | ftl_buffer, &ftl_sparebuffer[0], 1, 1) & 0x11F) != 0) | 1180 | ftl_buffer, &ftl_sparebuffer[0], 1, 1) & 0x11F) != 0) |
1139 | panicf("FTL: Failed to read block map page %u", (unsigned)i); | 1181 | { |
1140 | //return 1; | 1182 | DEBUGF("FTL: Failed to read block map page %u\n", (unsigned)i); |
1183 | return 1; | ||
1184 | } | ||
1141 | 1185 | ||
1142 | uint32_t toread = 2048; | 1186 | uint32_t toread = 2048; |
1143 | if (toread > (ftl_nand_type->userblocks << 1) - (i << 11)) | 1187 | if (toread > (ftl_nand_type->userblocks << 1) - (i << 11)) |
@@ -1154,8 +1198,10 @@ static uint32_t ftl_open(void) | |||
1154 | { | 1198 | { |
1155 | if ((ftl_vfl_read(ftl_cxt.ftl_erasectr_pages[i], | 1199 | if ((ftl_vfl_read(ftl_cxt.ftl_erasectr_pages[i], |
1156 | ftl_buffer, &ftl_sparebuffer[0], 1, 1) & 0x11F) != 0) | 1200 | ftl_buffer, &ftl_sparebuffer[0], 1, 1) & 0x11F) != 0) |
1157 | panicf("FTL: Failed to read erase counter page %u", (unsigned)i); | 1201 | { |
1158 | //return 1; | 1202 | DEBUGF("FTL: Failed to read erase counter page %u\n", (unsigned)i); |
1203 | return 1; | ||
1204 | } | ||
1159 | 1205 | ||
1160 | uint32_t toread = 2048; | 1206 | uint32_t toread = 2048; |
1161 | if (toread > ((ftl_nand_type->userblocks + 23) << 1) - (i << 11)) | 1207 | if (toread > ((ftl_nand_type->userblocks + 23) << 1) - (i << 11)) |
@@ -1175,6 +1221,42 @@ static uint32_t ftl_open(void) | |||
1175 | memset(ftl_erasectr_dirt, 0, 8); | 1221 | memset(ftl_erasectr_dirt, 0, 8); |
1176 | #endif | 1222 | #endif |
1177 | 1223 | ||
1224 | #ifdef FTL_DEBUG | ||
1225 | uint32_t j, k; | ||
1226 | for (i = 0; i < ftl_banks; i++) | ||
1227 | { | ||
1228 | uint32_t badblocks = 0; | ||
1229 | #ifndef FTL_READONLY | ||
1230 | for (j = 0; j < (*ftl_nand_type).blocks >> 3; j++) | ||
1231 | { | ||
1232 | uint8_t bbtentry = ftl_bbt[i][j]; | ||
1233 | for (k = 0; k < 8; k++) if ((bbtentry & (1 << k)) == 0) badblocks++; | ||
1234 | } | ||
1235 | DEBUGF("FTL: BBT for bank %d: %d bad blocks\n", i, badblocks); | ||
1236 | badblocks = 0; | ||
1237 | #endif | ||
1238 | for (j = 0; j < ftl_vfl_cxt[i].sparecount; j++) | ||
1239 | if (ftl_vfl_cxt[i].remaptable[j] == 0xFFFF) badblocks++; | ||
1240 | DEBUGF("FTL: VFL: Bank %d: %d of %d spare blocks are bad\n", | ||
1241 | i, badblocks, ftl_vfl_cxt[i].sparecount); | ||
1242 | DEBUGF("FTL: VFL: Bank %d: %d blocks remapped\n", | ||
1243 | i, ftl_vfl_cxt[i].spareused); | ||
1244 | DEBUGF("FTL: VFL: Bank %d: %d blocks scheduled for remapping\n", | ||
1245 | i, 0x334 - ftl_vfl_cxt[i].scheduledstart); | ||
1246 | } | ||
1247 | #ifndef FTL_READONLY | ||
1248 | uint32_t min = 0xFFFFFFFF, max = 0, total = 0; | ||
1249 | for (i = 0; i < (*ftl_nand_type).userblocks + 23; i++) | ||
1250 | { | ||
1251 | if (ftl_erasectr[i] > max) max = ftl_erasectr[i]; | ||
1252 | if (ftl_erasectr[i] < min) min = ftl_erasectr[i]; | ||
1253 | total += ftl_erasectr[i]; | ||
1254 | } | ||
1255 | DEBUGF("FTL: Erase counters: Minimum: %d, maximum %d, average: %d, total: %d\n", | ||
1256 | min, max, total / ((*ftl_nand_type).userblocks + 23), total); | ||
1257 | #endif | ||
1258 | #endif | ||
1259 | |||
1178 | return 0; | 1260 | return 0; |
1179 | } | 1261 | } |
1180 | 1262 | ||
@@ -1201,9 +1283,15 @@ uint32_t ftl_read(uint32_t sector, uint32_t count, void* buffer) | |||
1201 | uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks; | 1283 | uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks; |
1202 | uint32_t error = 0; | 1284 | uint32_t error = 0; |
1203 | 1285 | ||
1286 | #ifdef FTL_TRACE | ||
1287 | DEBUGF("FTL: Reading %d sectors starting at %d\n", count, sector); | ||
1288 | #endif | ||
1289 | |||
1204 | if (sector + count > ftl_nand_type->userblocks * ppb) | 1290 | if (sector + count > ftl_nand_type->userblocks * ppb) |
1291 | { | ||
1292 | DEBUGF("FTL: Sector %d is out of range!\n", sector + count - 1); | ||
1205 | return 1; | 1293 | return 1; |
1206 | 1294 | } | |
1207 | if (count == 0) return 0; | 1295 | if (count == 0) return 0; |
1208 | 1296 | ||
1209 | mutex_lock(&ftl_mtx); | 1297 | mutex_lock(&ftl_mtx); |
@@ -1217,10 +1305,21 @@ uint32_t ftl_read(uint32_t sector, uint32_t count, void* buffer) | |||
1217 | #ifndef FTL_READONLY | 1305 | #ifndef FTL_READONLY |
1218 | struct ftl_log_type* logentry = ftl_get_log_entry(block); | 1306 | struct ftl_log_type* logentry = ftl_get_log_entry(block); |
1219 | if (logentry != (struct ftl_log_type*)0) | 1307 | if (logentry != (struct ftl_log_type*)0) |
1308 | { | ||
1309 | #ifdef FTL_TRACE | ||
1310 | DEBUGF("FTL: Block %d has a log entry\n", block); | ||
1311 | #endif | ||
1220 | if (logentry->scatteredvblock != 0xFFFF | 1312 | if (logentry->scatteredvblock != 0xFFFF |
1221 | && logentry->pageoffsets[page] != 0xFFFF) | 1313 | && logentry->pageoffsets[page] != 0xFFFF) |
1314 | { | ||
1315 | #ifdef FTL_TRACE | ||
1316 | DEBUGF("FTL: Found page %d at block %d, page %d\n", page, | ||
1317 | (*logentry).scatteredvblock, (*logentry).pageoffsets[page]); | ||
1318 | #endif | ||
1222 | abspage = logentry->scatteredvblock * ppb | 1319 | abspage = logentry->scatteredvblock * ppb |
1223 | + logentry->pageoffsets[page]; | 1320 | + logentry->pageoffsets[page]; |
1321 | } | ||
1322 | } | ||
1224 | #endif | 1323 | #endif |
1225 | 1324 | ||
1226 | #ifndef FTL_READONLY | 1325 | #ifndef FTL_READONLY |
@@ -1237,6 +1336,7 @@ uint32_t ftl_read(uint32_t sector, uint32_t count, void* buffer) | |||
1237 | memset(&((uint8_t*)buffer)[(i + j) << 11], 0, 0x800); | 1336 | memset(&((uint8_t*)buffer)[(i + j) << 11], 0, 0x800); |
1238 | else if ((ret & (0xd << (j << 2))) || ftl_sparebuffer[j].user.eccmark != 0xFF) | 1337 | else if ((ret & (0xd << (j << 2))) || ftl_sparebuffer[j].user.eccmark != 0xFF) |
1239 | { | 1338 | { |
1339 | DEBUGF("FTL: Error while reading sector %d!\n", (sector + i)); | ||
1240 | error = 1; | 1340 | error = 1; |
1241 | memset(&((uint8_t*)buffer)[(i + j) << 11], 0, 0x800); | 1341 | memset(&((uint8_t*)buffer)[(i + j) << 11], 0, 0x800); |
1242 | } | 1342 | } |
@@ -1249,6 +1349,7 @@ uint32_t ftl_read(uint32_t sector, uint32_t count, void* buffer) | |||
1249 | if (ret & 2) memset(&((uint8_t*)buffer)[i << 11], 0, 0x800); | 1349 | if (ret & 2) memset(&((uint8_t*)buffer)[i << 11], 0, 0x800); |
1250 | else if ((ret & 0x11D) != 0 || ftl_sparebuffer[0].user.eccmark != 0xFF) | 1350 | else if ((ret & 0x11D) != 0 || ftl_sparebuffer[0].user.eccmark != 0xFF) |
1251 | { | 1351 | { |
1352 | DEBUGF("FTL: Error while reading sector %d!\n", (sector + i)); | ||
1252 | error = 1; | 1353 | error = 1; |
1253 | memset(&((uint8_t*)buffer)[i << 11], 0, 0x800); | 1354 | memset(&((uint8_t*)buffer)[i << 11], 0, 0x800); |
1254 | } | 1355 | } |
@@ -1422,6 +1523,7 @@ static uint32_t ftl_next_ctrl_pool_page(void) | |||
1422 | if (newblock == 0xFFFFFFFF) return 1; | 1523 | if (newblock == 0xFFFFFFFF) return 1; |
1423 | ftl_cxt.ftlctrlblocks[i] = newblock; | 1524 | ftl_cxt.ftlctrlblocks[i] = newblock; |
1424 | ftl_cxt.ftlctrlpage = newblock * ppb; | 1525 | ftl_cxt.ftlctrlpage = newblock * ppb; |
1526 | DEBUGF("Starting new FTL control block at %d\n", ftl_cxt.ftlctrlpage); | ||
1425 | uint32_t pagestoread = (ftl_nand_type->userblocks + 23) >> 10; | 1527 | uint32_t pagestoread = (ftl_nand_type->userblocks + 23) >> 10; |
1426 | if (((ftl_nand_type->userblocks + 23) & 0x1FF) != 0) pagestoread++; | 1528 | if (((ftl_nand_type->userblocks + 23) & 0x1FF) != 0) pagestoread++; |
1427 | for (i = 0; i < pagestoread; i++) | 1529 | for (i = 0; i < pagestoread; i++) |
@@ -1753,6 +1855,7 @@ static uint32_t ftl_commit_cxt(void) | |||
1753 | uint32_t mappages = (ftl_nand_type->userblocks + 0x3ff) >> 10; | 1855 | uint32_t mappages = (ftl_nand_type->userblocks + 0x3ff) >> 10; |
1754 | uint32_t ctrpages = (ftl_nand_type->userblocks + 23 + 0x3ff) >> 10; | 1856 | uint32_t ctrpages = (ftl_nand_type->userblocks + 23 + 0x3ff) >> 10; |
1755 | uint32_t endpage = ftl_cxt.ftlctrlpage + mappages + ctrpages + 1; | 1857 | uint32_t endpage = ftl_cxt.ftlctrlpage + mappages + ctrpages + 1; |
1858 | DEBUGF("FTL: Committing context\n"); | ||
1756 | if (endpage >= (ftl_cxt.ftlctrlpage / ppb + 1) * ppb) | 1859 | if (endpage >= (ftl_cxt.ftlctrlpage / ppb + 1) * ppb) |
1757 | ftl_cxt.ftlctrlpage |= ppb - 1; | 1860 | ftl_cxt.ftlctrlpage |= ppb - 1; |
1758 | for (i = 0; i < ctrpages; i++) | 1861 | for (i = 0; i < ctrpages; i++) |
@@ -1779,6 +1882,7 @@ static uint32_t ftl_commit_cxt(void) | |||
1779 | ftl_sparebuffer[0].meta.type = 0x43; | 1882 | ftl_sparebuffer[0].meta.type = 0x43; |
1780 | if (ftl_vfl_write(ftl_cxt.ftlctrlpage, 1, &ftl_cxt, &ftl_sparebuffer[0]) != 0) | 1883 | if (ftl_vfl_write(ftl_cxt.ftlctrlpage, 1, &ftl_cxt, &ftl_sparebuffer[0]) != 0) |
1781 | return 1; | 1884 | return 1; |
1885 | DEBUGF("FTL: Wrote context to page %d\n", ftl_cxt.ftlctrlpage); | ||
1782 | return 0; | 1886 | return 0; |
1783 | } | 1887 | } |
1784 | #endif | 1888 | #endif |
@@ -1834,9 +1938,15 @@ uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer) | |||
1834 | uint32_t i, j, k; | 1938 | uint32_t i, j, k; |
1835 | uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks; | 1939 | uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks; |
1836 | 1940 | ||
1941 | #ifdef FTL_TRACE | ||
1942 | DEBUGF("FTL: Writing %d sectors starting at %d\n", count, sector); | ||
1943 | #endif | ||
1944 | |||
1837 | if (sector + count > ftl_nand_type->userblocks * ppb) | 1945 | if (sector + count > ftl_nand_type->userblocks * ppb) |
1946 | { | ||
1947 | DEBUGF("FTL: Sector %d is out of range!\n", sector + count - 1); | ||
1838 | return 1; | 1948 | return 1; |
1839 | 1949 | } | |
1840 | if (count == 0) return 0; | 1950 | if (count == 0) return 0; |
1841 | 1951 | ||
1842 | mutex_lock(&ftl_mtx); | 1952 | mutex_lock(&ftl_mtx); |
@@ -1845,6 +1955,7 @@ uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer) | |||
1845 | { | 1955 | { |
1846 | for (i = 0; i < 3; i++) | 1956 | for (i = 0; i < 3; i++) |
1847 | { | 1957 | { |
1958 | DEBUGF("FTL: Marking dirty, try %d\n", i); | ||
1848 | if (ftl_next_ctrl_pool_page() != 0) | 1959 | if (ftl_next_ctrl_pool_page() != 0) |
1849 | { | 1960 | { |
1850 | mutex_unlock(&ftl_mtx); | 1961 | mutex_unlock(&ftl_mtx); |
@@ -1863,6 +1974,7 @@ uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer) | |||
1863 | mutex_unlock(&ftl_mtx); | 1974 | mutex_unlock(&ftl_mtx); |
1864 | return 1; | 1975 | return 1; |
1865 | } | 1976 | } |
1977 | DEBUGF("FTL: Wrote dirty mark to %d\n", ftl_cxt.ftlctrlpage); | ||
1866 | ftl_cxt.clean_flag = 0; | 1978 | ftl_cxt.clean_flag = 0; |
1867 | } | 1979 | } |
1868 | 1980 | ||
@@ -1879,10 +1991,16 @@ uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer) | |||
1879 | } | 1991 | } |
1880 | if (page == 0 && count - i >= ppb) | 1992 | if (page == 0 && count - i >= ppb) |
1881 | { | 1993 | { |
1994 | #ifdef FTL_TRACE | ||
1995 | DEBUGF("FTL: Going to write a full hyperblock in one shot\n"); | ||
1996 | #endif | ||
1882 | uint32_t vblock = logentry->scatteredvblock; | 1997 | uint32_t vblock = logentry->scatteredvblock; |
1883 | logentry->scatteredvblock = 0xFFFF; | 1998 | logentry->scatteredvblock = 0xFFFF; |
1884 | if (logentry->pagesused != 0) | 1999 | if (logentry->pagesused != 0) |
1885 | { | 2000 | { |
2001 | #ifdef FTL_TRACE | ||
2002 | DEBUGF("FTL: Scattered block had some pages already used, committing\n"); | ||
2003 | #endif | ||
1886 | ftl_release_pool_block(vblock); | 2004 | ftl_release_pool_block(vblock); |
1887 | vblock = ftl_allocate_pool_block(); | 2005 | vblock = ftl_allocate_pool_block(); |
1888 | if (vblock == 0xFFFFFFFF) | 2006 | if (vblock == 0xFFFFFFFF) |
@@ -1922,6 +2040,9 @@ uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer) | |||
1922 | { | 2040 | { |
1923 | if (logentry->pagesused == ppb) | 2041 | if (logentry->pagesused == ppb) |
1924 | { | 2042 | { |
2043 | #ifdef FTL_TRACE | ||
2044 | DEBUGF("FTL: Scattered block is full, committing\n"); | ||
2045 | #endif | ||
1925 | ftl_remove_scattered_block(logentry); | 2046 | ftl_remove_scattered_block(logentry); |
1926 | logentry = ftl_allocate_log_entry(block); | 2047 | logentry = ftl_allocate_log_entry(block); |
1927 | if (logentry == (struct ftl_log_type*)0) | 2048 | if (logentry == (struct ftl_log_type*)0) |
@@ -1998,6 +2119,10 @@ uint32_t ftl_sync(void) | |||
1998 | if (ftl_cxt.clean_flag == 1) return 0; | 2119 | if (ftl_cxt.clean_flag == 1) return 0; |
1999 | 2120 | ||
2000 | mutex_lock(&ftl_mtx); | 2121 | mutex_lock(&ftl_mtx); |
2122 | |||
2123 | #ifdef FTL_TRACE | ||
2124 | DEBUGF("FTL: Syncing\n"); | ||
2125 | #endif | ||
2001 | 2126 | ||
2002 | if (ftl_cxt.swapcounter >= 20) | 2127 | if (ftl_cxt.swapcounter >= 20) |
2003 | for (i = 0; i < 4; i++) | 2128 | for (i = 0; i < 4; i++) |
@@ -2050,7 +2175,6 @@ uint32_t ftl_init(void) | |||
2050 | ftl_nand_type = nand_get_device_type(0); | 2175 | ftl_nand_type = nand_get_device_type(0); |
2051 | foundsignature = 0; | 2176 | foundsignature = 0; |
2052 | blockwiped = 1; | 2177 | blockwiped = 1; |
2053 | mutex_unlock(&ftl_mtx); | ||
2054 | for (i = 0; i < ftl_nand_type->pagesperblock; i++) | 2178 | for (i = 0; i < ftl_nand_type->pagesperblock; i++) |
2055 | { | 2179 | { |
2056 | result = nand_read_page(0, i, ftl_buffer, (uint32_t*)0, 1, 1); | 2180 | result = nand_read_page(0, i, ftl_buffer, (uint32_t*)0, 1, 1); |
@@ -2070,34 +2194,19 @@ uint32_t ftl_init(void) | |||
2070 | skip = 0; | 2194 | skip = 0; |
2071 | if (founddevinfo == 0) | 2195 | if (founddevinfo == 0) |
2072 | { | 2196 | { |
2073 | mutex_unlock(&ftl_mtx); | 2197 | DEBUGF("FTL: No DEVICEINFO found!\n"); |
2074 | panicf("FTL: No DEVICEINFO found!"); | 2198 | return 1; |
2075 | //return 1; | ||
2076 | } | 2199 | } |
2077 | if (foundsignature != 0 && (result & 0x11F) != 0) | 2200 | if (foundsignature != 0 && (result & 0x11F) != 0) |
2078 | { | 2201 | { |
2079 | mutex_unlock(&ftl_mtx); | 2202 | DEBUGF("FTL: Problem with the signature!\n"); |
2080 | panicf("FTL: Problem with the signature!"); | 2203 | return 1; |
2081 | //return 1; | ||
2082 | } | 2204 | } |
2083 | if (ftl_vfl_open() == 0) | 2205 | if (ftl_vfl_open() == 0) |
2084 | if (ftl_open() == 0) | 2206 | if (ftl_open() == 0) |
2085 | { | ||
2086 | mutex_unlock(&ftl_mtx); | ||
2087 | return 0; | 2207 | return 0; |
2088 | } | ||
2089 | 2208 | ||
2090 | panicf("FTL: Initialization failed!"); | 2209 | DEBUGF("FTL: Initialization failed!\n"); |
2091 | 2210 | ||
2092 | /* Something went terribly wrong. We may want to allow the user to erase | ||
2093 | block zero in that condition, to make norboot reinitialize the FTL. | ||
2094 | (However there is curently no point in this, as iLoader would already | ||
2095 | fail if this would be the case.) | ||
2096 | |||
2097 | nand_block_erase(0, 0); | ||
2098 | */ | ||
2099 | |||
2100 | |||
2101 | mutex_unlock(&ftl_mtx); | ||
2102 | return 1; | 2211 | return 1; |
2103 | } | 2212 | } |