| Index: embios/trunk/target/ipodnano2g/ftl.c |
| — | — | @@ -29,6 +29,9 @@ |
| 30 | 30 | #include "thread.h"
|
| 31 | 31 | #include "panic.h"
|
| 32 | 32 | #include "debug.h"
|
| | 33 | +#include "console.h"
|
| | 34 | +#include "progressbar.h"
|
| | 35 | +#include "lcdconsole.h"
|
| 33 | 36 |
|
| 34 | 37 |
|
| 35 | 38 |
|
| — | — | @@ -362,13 +365,13 @@ |
| 363 | 366 | uint32_t ftl_banks;
|
| 364 | 367 |
|
| 365 | 368 | /* Block map, used vor pBlock to vBlock mapping */
|
| 366 | | -static uint16_t ftl_map[0x2000];
|
| | 369 | +static uint16_t ftl_map[0x2000] CACHEALIGN_ATTR;
|
| 367 | 370 |
|
| 368 | 371 | /* VFL context for each bank */
|
| 369 | 372 | static struct ftl_vfl_cxt_type ftl_vfl_cxt[4];
|
| 370 | 373 |
|
| 371 | 374 | /* FTL context */
|
| 372 | | -static struct ftl_cxt_type ftl_cxt;
|
| | 375 | +static struct ftl_cxt_type ftl_cxt CACHEALIGN_ATTR;
|
| 373 | 376 |
|
| 374 | 377 | /* Temporary data buffers for internal use by the FTL */
|
| 375 | 378 | static uint8_t ftl_buffer[0x800] CACHEALIGN_ATTR;
|
| — | — | @@ -383,7 +386,7 @@ |
| 384 | 387 | static uint8_t ftl_bbt[4][0x410];
|
| 385 | 388 |
|
| 386 | 389 | /* Erase counters for the vBlocks */
|
| 387 | | -static uint16_t ftl_erasectr[0x2000];
|
| | 390 | +static uint16_t ftl_erasectr[0x2000] CACHEALIGN_ATTR;
|
| 388 | 391 |
|
| 389 | 392 | /* Used by ftl_log */
|
| 390 | 393 | static uint16_t ftl_offsets[0x11][0x200];
|
| — | — | @@ -411,6 +414,19 @@ |
| 412 | 415 | back if something fails while compacting a scattered page block. */
|
| 413 | 416 | static uint16_t ftl_offsets_backup[0x200] CACHEALIGN_ATTR;
|
| 414 | 417 |
|
| | 418 | +/* Buffers needed for FTL recovery */
|
| | 419 | +static uint32_t blk_usn[0x2000] INITBSS_ATTR;
|
| | 420 | +static uint8_t blk_type[0x2000] INITBSS_ATTR;
|
| | 421 | +static uint32_t erasectr_usn[8] INITBSS_ATTR;
|
| | 422 | +static uint32_t pageusn[0x200] INITBSS_ATTR;
|
| | 423 | +static uint8_t pagedata[0x200][0x800] INITBSS_ATTR CACHEALIGN_ATTR;
|
| | 424 | +
|
| | 425 | +/* State information needed for FTL recovery */
|
| | 426 | +static uint32_t meta_usn INITBSS_ATTR;
|
| | 427 | +static uint32_t user_usn INITBSS_ATTR;
|
| | 428 | +static uint32_t allocmode INITBSS_ATTR;
|
| | 429 | +static uint32_t firstfree INITBSS_ATTR;
|
| | 430 | +
|
| 415 | 431 | #endif
|
| 416 | 432 |
|
| 417 | 433 |
|
| — | — | @@ -420,6 +436,7 @@ |
| 421 | 437 |
|
| 422 | 438 | /* Finds a device info page for the specified bank and returns its number.
|
| 423 | 439 | Used to check if one is present, and to read the lowlevel BBT. */
|
| | 440 | +static uint32_t ftl_find_devinfo(uint32_t bank) INITCODE_ATTR;
|
| 424 | 441 | static uint32_t ftl_find_devinfo(uint32_t bank)
|
| 425 | 442 | {
|
| 426 | 443 | /* Scan the last 10% of the flash for device info pages */
|
| — | — | @@ -444,6 +461,7 @@ |
| 445 | 462 |
|
| 446 | 463 |
|
| 447 | 464 | /* Checks if all banks have proper device info pages */
|
| | 465 | +static uint32_t ftl_has_devinfo(void) INITCODE_ATTR;
|
| 448 | 466 | static uint32_t ftl_has_devinfo(void)
|
| 449 | 467 | {
|
| 450 | 468 | uint32_t i;
|
| — | — | @@ -454,6 +472,7 @@ |
| 455 | 473 |
|
| 456 | 474 | /* Loads the lowlevel BBT for a bank to the specified buffer.
|
| 457 | 475 | This is based on some cryptic disassembly and not fully understood yet. */
|
| | 476 | +static uint32_t ftl_load_bbt(uint32_t bank, uint8_t* bbt) INITCODE_ATTR;
|
| 458 | 477 | static uint32_t ftl_load_bbt(uint32_t bank, uint8_t* bbt)
|
| 459 | 478 | {
|
| 460 | 479 | uint32_t i, j;
|
| — | — | @@ -604,6 +623,7 @@ |
| 605 | 624 | /* Returns a pointer to the most recently updated VFL context,
|
| 606 | 625 | used to find out the current FTL context vBlock numbers
|
| 607 | 626 | (planetbeing's "maxthing") */
|
| | 627 | +static struct ftl_vfl_cxt_type* ftl_vfl_get_newest_cxt(void) INITCODE_ATTR;
|
| 608 | 628 | static struct ftl_vfl_cxt_type* ftl_vfl_get_newest_cxt(void)
|
| 609 | 629 | {
|
| 610 | 630 | uint32_t i, maxusn;
|
| — | — | @@ -621,6 +641,7 @@ |
| 622 | 642 |
|
| 623 | 643 | /* Checks if the specified pBlock is marked bad in the supplied lowlevel BBT.
|
| 624 | 644 | Only used while mounting the VFL. */
|
| | 645 | +static uint32_t ftl_is_good_block(uint8_t* bbt, uint32_t block) INITCODE_ATTR;
|
| 625 | 646 | static uint32_t ftl_is_good_block(uint8_t* bbt, uint32_t block)
|
| 626 | 647 | {
|
| 627 | 648 | if ((bbt[block >> 3] & (1 << (block & 7))) == 0) return 0;
|
| — | — | @@ -652,6 +673,9 @@ |
| 653 | 674 | /* Tries to read a VFL context from the specified bank, pBlock and page */
|
| 654 | 675 | static uint32_t ftl_vfl_read_page(uint32_t bank, uint32_t block,
|
| 655 | 676 | uint32_t startpage, void* databuffer,
|
| | 677 | + union ftl_spare_data_type* sparebuffer) INITCODE_ATTR;
|
| | 678 | +static uint32_t ftl_vfl_read_page(uint32_t bank, uint32_t block,
|
| | 679 | + uint32_t startpage, void* databuffer,
|
| 656 | 680 | union ftl_spare_data_type* sparebuffer)
|
| 657 | 681 | {
|
| 658 | 682 | uint32_t i;
|
| — | — | @@ -1019,7 +1043,8 @@ |
| 1020 | 1044 |
|
| 1021 | 1045 |
|
| 1022 | 1046 | /* Mounts the VFL on all banks */
|
| 1023 | | -static uint32_t ftl_vfl_open(void)
|
| | 1047 | +static uint32_t ftl_vfl_open(void) INITCODE_ATTR;
|
| | 1048 | +static uint32_t ftl_vfl_open()
|
| 1024 | 1049 | {
|
| 1025 | 1050 | uint32_t i, j, k;
|
| 1026 | 1051 | uint32_t minusn, vflcxtidx, last;
|
| — | — | @@ -1112,7 +1137,8 @@ |
| 1113 | 1138 |
|
| 1114 | 1139 |
|
| 1115 | 1140 | /* Mounts the actual FTL */
|
| 1116 | | -static uint32_t ftl_open(void)
|
| | 1141 | +static uint32_t ftl_open(void) INITCODE_ATTR;
|
| | 1142 | +static uint32_t ftl_open()
|
| 1117 | 1143 | {
|
| 1118 | 1144 | uint32_t i;
|
| 1119 | 1145 | uint32_t ret;
|
| — | — | @@ -1227,7 +1253,7 @@ |
| 1228 | 1254 | {
|
| 1229 | 1255 | uint32_t badblocks = 0;
|
| 1230 | 1256 | #ifndef FTL_READONLY
|
| 1231 | | - for (j = 0; j < (*ftl_nand_type).blocks >> 3; j++)
|
| | 1257 | + for (j = 0; j < ftl_nand_type->blocks >> 3; j++)
|
| 1232 | 1258 | {
|
| 1233 | 1259 | uint8_t bbtentry = ftl_bbt[i][j];
|
| 1234 | 1260 | for (k = 0; k < 8; k++) if ((bbtentry & (1 << k)) == 0) badblocks++;
|
| — | — | @@ -1246,7 +1272,7 @@ |
| 1247 | 1273 | }
|
| 1248 | 1274 | #ifndef FTL_READONLY
|
| 1249 | 1275 | uint32_t min = 0xFFFFFFFF, max = 0, total = 0;
|
| 1250 | | - for (i = 0; i < (*ftl_nand_type).userblocks + 23; i++)
|
| | 1276 | + for (i = 0; i < ftl_nand_type->userblocks + 23; i++)
|
| 1251 | 1277 | {
|
| 1252 | 1278 | if (ftl_erasectr[i] > max) max = ftl_erasectr[i];
|
| 1253 | 1279 | if (ftl_erasectr[i] < min) min = ftl_erasectr[i];
|
| — | — | @@ -1253,7 +1279,7 @@ |
| 1254 | 1280 | total += ftl_erasectr[i];
|
| 1255 | 1281 | }
|
| 1256 | 1282 | DEBUGF("FTL: Erase counters: Minimum: %d, maximum %d, average: %d, total: %d",
|
| 1257 | | - min, max, total / ((*ftl_nand_type).userblocks + 23), total);
|
| | 1283 | + min, max, total / (ftl_nand_type->userblocks + 23), total);
|
| 1258 | 1284 | #endif
|
| 1259 | 1285 | #endif
|
| 1260 | 1286 |
|
| — | — | @@ -2167,10 +2193,313 @@ |
| 2168 | 2194 | #endif
|
| 2169 | 2195 |
|
| 2170 | 2196 |
|
| | 2197 | +/* Block allocator for FTL recovery */
|
| | 2198 | +static uint32_t ftl_alloc_block() INITCODE_ATTR;
|
| | 2199 | +static uint32_t ftl_alloc_block()
|
| | 2200 | +{
|
| | 2201 | + while (1)
|
| | 2202 | + {
|
| | 2203 | + for (; firstfree < ftl_nand_type->userblocks + 0x17; firstfree++)
|
| | 2204 | + if (!blk_type[firstfree]) break;
|
| | 2205 | + else if (allocmode && blk_type[firstfree] != 1)
|
| | 2206 | + {
|
| | 2207 | + if (ftl_erase_block(firstfree))
|
| | 2208 | + {
|
| | 2209 | + cprintf(CONSOLE_BOOT, "Couldn't erase vBlock %d (pool alloc)!\n", firstfree);
|
| | 2210 | + return 1;
|
| | 2211 | + }
|
| | 2212 | + break;
|
| | 2213 | + }
|
| | 2214 | + if (firstfree < ftl_nand_type->userblocks + 0x17)
|
| | 2215 | + {
|
| | 2216 | + blk_type[firstfree] = 1;
|
| | 2217 | + return firstfree++;
|
| | 2218 | + }
|
| | 2219 | + if (!allocmode)
|
| | 2220 | + {
|
| | 2221 | + allocmode = 1;
|
| | 2222 | + firstfree = 0;
|
| | 2223 | + }
|
| | 2224 | + else
|
| | 2225 | + {
|
| | 2226 | + cputs(CONSOLE_BOOT, "Out of empty blocks!\n");
|
| | 2227 | + return 1;
|
| | 2228 | + }
|
| | 2229 | + }
|
| | 2230 | +}
|
| | 2231 | +
|
| | 2232 | +
|
| | 2233 | +static uint32_t ftl_repair(void) INITCODE_ATTR;
|
| | 2234 | +static uint32_t ftl_repair()
|
| | 2235 | +{
|
| | 2236 | + uint32_t i, j, k;
|
| | 2237 | +#ifdef HAVE_LCD
|
| | 2238 | + struct progressbar_state progressbar;
|
| | 2239 | +#endif
|
| | 2240 | +
|
| | 2241 | + cputs(CONSOLE_BOOT, "Scanning flash...\n");
|
| | 2242 | +#ifdef HAVE_LCD
|
| | 2243 | + lcdconsole_progressbar(&progressbar, 0, ftl_nand_type->userblocks + 0x17);
|
| | 2244 | +#endif
|
| | 2245 | + uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks;
|
| | 2246 | + memset(&ftl_cxt, 0x00, 0x800);
|
| | 2247 | + memset(ftl_map, 0xff, 0x4000);
|
| | 2248 | + memset(blk_usn, 0x00, 0x8000);
|
| | 2249 | + memset(blk_type, 0x00, 0x2000);
|
| | 2250 | + memset(ftl_erasectr, 0x00, 0x4000);
|
| | 2251 | + memset(erasectr_usn, 0xff, 32);
|
| | 2252 | + user_usn = 0;
|
| | 2253 | + meta_usn = 0xffffffff;
|
| | 2254 | + for (i = 0; i < ftl_nand_type->userblocks + 0x17; i++)
|
| | 2255 | + {
|
| | 2256 | + uint32_t ret = ftl_vfl_read((i + 1) * ppb - 1, 0, &ftl_sparebuffer[0], 1, 0);
|
| | 2257 | + if ((ret & 0x11F) == 0 && ftl_sparebuffer[0].meta.type == 0x41)
|
| | 2258 | + {
|
| | 2259 | + uint32_t lbn = ftl_sparebuffer[0].user.lpn / ppb;
|
| | 2260 | + if (ftl_sparebuffer[0].user.usn > user_usn)
|
| | 2261 | + user_usn = ftl_sparebuffer[0].user.usn;
|
| | 2262 | + if (ftl_sparebuffer[0].user.usn > blk_usn[lbn])
|
| | 2263 | + {
|
| | 2264 | + if (ftl_map[lbn] != 0xffff)
|
| | 2265 | + blk_type[ftl_map[lbn]] = 5;
|
| | 2266 | + blk_usn[lbn] = ftl_sparebuffer[0].user.usn;
|
| | 2267 | + ftl_map[lbn] = i;
|
| | 2268 | + blk_type[i] = 1;
|
| | 2269 | + }
|
| | 2270 | + else blk_type[i] = 5;
|
| | 2271 | + }
|
| | 2272 | + else
|
| | 2273 | + for (j = 0; j < ppb; j++)
|
| | 2274 | + {
|
| | 2275 | + ret = ftl_vfl_read(i * ppb + j, 0, &ftl_sparebuffer[0], 1, 0);
|
| | 2276 | + if (ret & 2) break;
|
| | 2277 | + if (ret & 0x11F)
|
| | 2278 | + {
|
| | 2279 | + blk_type[i] = 4;
|
| | 2280 | + continue;
|
| | 2281 | + }
|
| | 2282 | + if (ftl_sparebuffer[0].meta.type == 0x40)
|
| | 2283 | + {
|
| | 2284 | + blk_type[i] = 2;
|
| | 2285 | + break;
|
| | 2286 | + }
|
| | 2287 | + else if (ftl_sparebuffer[0].meta.type - 0x43 <= 4)
|
| | 2288 | + {
|
| | 2289 | + blk_type[i] = 3;
|
| | 2290 | + if (ftl_sparebuffer[0].meta.type == 0x46)
|
| | 2291 | + {
|
| | 2292 | + uint32_t idx = ftl_sparebuffer[0].meta.idx;
|
| | 2293 | + if (ftl_sparebuffer[0].meta.usn < meta_usn)
|
| | 2294 | + meta_usn = ftl_sparebuffer[0].meta.usn;
|
| | 2295 | + if (ftl_sparebuffer[0].meta.usn < erasectr_usn[idx])
|
| | 2296 | + {
|
| | 2297 | + erasectr_usn[idx] = ftl_sparebuffer[0].meta.usn;
|
| | 2298 | + ret = ftl_vfl_read(i * ppb + j, &ftl_erasectr[idx << 10],
|
| | 2299 | + &ftl_sparebuffer[0], 1, 0);
|
| | 2300 | + if (ret & 0x11f) memset(&ftl_erasectr[idx << 10], 0, 0x800);
|
| | 2301 | + }
|
| | 2302 | + }
|
| | 2303 | + }
|
| | 2304 | + else
|
| | 2305 | + {
|
| | 2306 | + cprintf(CONSOLE_BOOT, "Invalid block type %02X while reading vPage %d\n",
|
| | 2307 | + ftl_sparebuffer[0].meta.type, i * ppb + j);
|
| | 2308 | + return 1;
|
| | 2309 | + }
|
| | 2310 | + }
|
| | 2311 | +#ifdef HAVE_LCD
|
| | 2312 | + progressbar_setpos(&progressbar, i + 1, false);
|
| | 2313 | +#endif
|
| | 2314 | + }
|
| | 2315 | +
|
| | 2316 | + uint32_t sum = 0;
|
| | 2317 | + uint32_t count = 0;
|
| | 2318 | + for (i = 0; i < 0x2000; i++)
|
| | 2319 | + if (ftl_erasectr[i])
|
| | 2320 | + {
|
| | 2321 | + sum += ftl_erasectr[i];
|
| | 2322 | + count++;
|
| | 2323 | + }
|
| | 2324 | + uint32_t average = sum / count;
|
| | 2325 | + for (i = 0; i < 0x2000; i++)
|
| | 2326 | + if (!ftl_erasectr[i])
|
| | 2327 | + ftl_erasectr[i] = average;
|
| | 2328 | +
|
| | 2329 | + cputs(CONSOLE_BOOT, "Committing scattered pages...\n");
|
| | 2330 | + count = 0;
|
| | 2331 | + for (i = 0; i < ftl_nand_type->userblocks + 0x17; i++)
|
| | 2332 | + if (blk_type[i] == 2) count++;
|
| | 2333 | + uint32_t block;
|
| | 2334 | + uint32_t dirty;
|
| | 2335 | + if (count)
|
| | 2336 | + {
|
| | 2337 | +#ifdef HAVE_LCD
|
| | 2338 | + lcdconsole_progressbar(&progressbar, 0, count * ppb);
|
| | 2339 | +#endif
|
| | 2340 | + count = 0;
|
| | 2341 | + for (i = 0; i < ftl_nand_type->userblocks + 0x17; i++)
|
| | 2342 | + if (blk_type[i] == 2)
|
| | 2343 | + {
|
| | 2344 | + block = 0xffff;
|
| | 2345 | + for (j = 0; j < ftl_nand_type->pagesperblock * ftl_banks; j++)
|
| | 2346 | + {
|
| | 2347 | + uint32_t ret = ftl_vfl_read(i * ppb + j, ftl_buffer,
|
| | 2348 | + &ftl_sparebuffer[0], 1, 0);
|
| | 2349 | + if (ret & 0x11F) continue;
|
| | 2350 | + if (ftl_sparebuffer[0].user.type != 0x40)
|
| | 2351 | + {
|
| | 2352 | + cprintf(CONSOLE_BOOT, "Invalid block type %02X while reading "
|
| | 2353 | + "vPage %d (scattered page)!\n",
|
| | 2354 | + ftl_sparebuffer[0].meta.type, i * ppb + j);
|
| | 2355 | + return 1;
|
| | 2356 | + }
|
| | 2357 | + if (block == 0xffff)
|
| | 2358 | + {
|
| | 2359 | + block = ftl_sparebuffer[0].user.lpn / ppb;
|
| | 2360 | + memset(pageusn, 0x00, 0x800);
|
| | 2361 | + memset(pagedata, 0x00, 0x100000);
|
| | 2362 | + if (ftl_map[block] != 0xffff)
|
| | 2363 | + for (k = 0; k < ppb; k++)
|
| | 2364 | + {
|
| | 2365 | + uint32_t ret = ftl_vfl_read(ftl_map[block] * ppb + k, pagedata[k],
|
| | 2366 | + &ftl_copyspare[0], 1, 0);
|
| | 2367 | + if (ret & 0x11F) continue;
|
| | 2368 | + if (ftl_copyspare[0].user.type != 0x40
|
| | 2369 | + && ftl_copyspare[0].user.type != 0x41)
|
| | 2370 | + {
|
| | 2371 | + cprintf(CONSOLE_BOOT, "Invalid block type %02X while reading "
|
| | 2372 | + "vPage %d (scattered page orig)!\n",
|
| | 2373 | + ftl_sparebuffer[0].meta.type,
|
| | 2374 | + ftl_map[block] * ppb + k);
|
| | 2375 | + return 1;
|
| | 2376 | + }
|
| | 2377 | + if (block != ftl_copyspare[0].user.lpn / ppb)
|
| | 2378 | + {
|
| | 2379 | + cprintf(CONSOLE_BOOT, "Foreign page in scattered page orig "
|
| | 2380 | + "block (vPage %d, LPN %d)!\n",
|
| | 2381 | + ftl_map[block] * ppb + k,
|
| | 2382 | + ftl_sparebuffer[0].user.usn);
|
| | 2383 | + return 1;
|
| | 2384 | + }
|
| | 2385 | + pageusn[k] = ftl_copyspare[0].user.usn;
|
| | 2386 | + }
|
| | 2387 | + dirty = 0;
|
| | 2388 | + }
|
| | 2389 | + if (block != ftl_sparebuffer[0].user.lpn / ppb)
|
| | 2390 | + {
|
| | 2391 | + cprintf(CONSOLE_BOOT, "Foreign page in scattered page block "
|
| | 2392 | + "block (vPage %d, LPN %d)!\n",
|
| | 2393 | + i * ppb + j, ftl_sparebuffer[0].user.lpn);
|
| | 2394 | + return 1;
|
| | 2395 | + }
|
| | 2396 | + uint32_t idx = ftl_sparebuffer[0].user.lpn % ppb;
|
| | 2397 | + if (ftl_sparebuffer[0].user.usn > user_usn)
|
| | 2398 | + user_usn = ftl_sparebuffer[0].user.usn;
|
| | 2399 | + if (ftl_sparebuffer[0].user.usn > pageusn[idx])
|
| | 2400 | + {
|
| | 2401 | + pageusn[idx] = ftl_sparebuffer[0].user.usn;
|
| | 2402 | + memcpy(pagedata[idx], ftl_buffer, 0x800);
|
| | 2403 | + dirty = 1;
|
| | 2404 | + }
|
| | 2405 | + }
|
| | 2406 | + if (dirty)
|
| | 2407 | + {
|
| | 2408 | + if (ftl_erase_block(i))
|
| | 2409 | + {
|
| | 2410 | + cprintf(CONSOLE_BOOT, "Couldn't erase vBlock %d "
|
| | 2411 | + "(scattered page commit)!\n", i);
|
| | 2412 | + return 1;
|
| | 2413 | + }
|
| | 2414 | + for (j = 0; j < ppb; j++)
|
| | 2415 | + {
|
| | 2416 | + memset(&ftl_sparebuffer[0], 0xFF, 0x40);
|
| | 2417 | + ftl_sparebuffer[0].user.lpn = block * ppb + j;
|
| | 2418 | + ftl_sparebuffer[0].user.usn = pageusn[j];
|
| | 2419 | + ftl_sparebuffer[0].user.type = 0x40;
|
| | 2420 | + if (j == ppb - 1) ftl_sparebuffer[0].user.type = 0x41;
|
| | 2421 | + if (ftl_vfl_write(i * ppb + j, 1, pagedata[j], &ftl_sparebuffer[0]))
|
| | 2422 | + {
|
| | 2423 | + cprintf(CONSOLE_BOOT, "Couldn't write vPage %d "
|
| | 2424 | + "(scattered page commit)!\n", i * ppb + j);
|
| | 2425 | + return 1;
|
| | 2426 | + }
|
| | 2427 | +#ifdef HAVE_LCD
|
| | 2428 | + progressbar_setpos(&progressbar, count * ppb + j, false);
|
| | 2429 | +#endif
|
| | 2430 | + }
|
| | 2431 | + if (ftl_map[block] != 0xffff) blk_type[ftl_map[block]] = 5;
|
| | 2432 | + blk_type[i] = 1;
|
| | 2433 | + ftl_map[block] = i;
|
| | 2434 | + }
|
| | 2435 | + else blk_type[i] = 5;
|
| | 2436 | +#ifdef HAVE_LCD
|
| | 2437 | + progressbar_setpos(&progressbar, ++count * ppb, false);
|
| | 2438 | +#endif
|
| | 2439 | + }
|
| | 2440 | + }
|
| | 2441 | +
|
| | 2442 | + cputs(CONSOLE_BOOT, "Fixing block map...\n");
|
| | 2443 | + allocmode = 0;
|
| | 2444 | + firstfree = 0;
|
| | 2445 | + for (i = 0; i < 3; i++) ftl_cxt.ftlctrlblocks[i] = ftl_alloc_block();
|
| | 2446 | + for (i = 0; i < 20; i++) ftl_cxt.blockpool[i] = ftl_alloc_block();
|
| | 2447 | + for (i = 0; i < ftl_nand_type->userblocks; i++)
|
| | 2448 | + if (ftl_map[i] == 0xffff)
|
| | 2449 | + ftl_map[i] = ftl_alloc_block();
|
| | 2450 | + ftl_cxt.usn = meta_usn - 1;
|
| | 2451 | + ftl_cxt.nextblockusn = user_usn + 1;
|
| | 2452 | + ftl_cxt.freecount = 20;
|
| | 2453 | + ftl_cxt.clean_flag = 1;
|
| | 2454 | +
|
| | 2455 | + cputs(CONSOLE_BOOT, "Committing FTL context...\n");
|
| | 2456 | + uint32_t blockmappages = ftl_nand_type->userblocks >> 10;
|
| | 2457 | + if ((ftl_nand_type->userblocks & 0x1FF) != 0) blockmappages++;
|
| | 2458 | + uint32_t erasectrpages = (ftl_nand_type->userblocks + 23) >> 10;
|
| | 2459 | + if (((ftl_nand_type->userblocks + 23) & 0x1FF) != 0) erasectrpages++;
|
| | 2460 | + uint32_t page = ftl_cxt.ftlctrlblocks[0] * ppb;
|
| | 2461 | + for (i = 0; i < erasectrpages; i++)
|
| | 2462 | + {
|
| | 2463 | + memset(&ftl_sparebuffer, 0xFF, 0x40);
|
| | 2464 | + ftl_sparebuffer[0].meta.usn = ftl_cxt.usn;
|
| | 2465 | + ftl_sparebuffer[0].meta.idx = i;
|
| | 2466 | + ftl_sparebuffer[0].meta.type = 0x46;
|
| | 2467 | + if (ftl_vfl_write(page, 1, &ftl_erasectr[i << 10], &ftl_sparebuffer[0]))
|
| | 2468 | + {
|
| | 2469 | + cprintf(CONSOLE_BOOT, "Couldn't write vPage %d (save erase counters)!\n", page);
|
| | 2470 | + return 1;
|
| | 2471 | + }
|
| | 2472 | + ftl_cxt.ftl_erasectr_pages[i] = page++;
|
| | 2473 | + }
|
| | 2474 | + for (i = 0; i < blockmappages; i++)
|
| | 2475 | + {
|
| | 2476 | + memset(&ftl_sparebuffer[0], 0xFF, 0x40);
|
| | 2477 | + ftl_sparebuffer[0].meta.usn = ftl_cxt.usn;
|
| | 2478 | + ftl_sparebuffer[0].meta.idx = i;
|
| | 2479 | + ftl_sparebuffer[0].meta.type = 0x44;
|
| | 2480 | + if (ftl_vfl_write(page, 1, &ftl_map[i << 10], &ftl_sparebuffer[0]))
|
| | 2481 | + {
|
| | 2482 | + cprintf(CONSOLE_BOOT, "Couldn't write vPage %d (save block map)!\n", page);
|
| | 2483 | + return 1;
|
| | 2484 | + }
|
| | 2485 | + ftl_cxt.ftl_map_pages[i] = page++;
|
| | 2486 | + }
|
| | 2487 | + ftl_cxt.ftlctrlpage = page;
|
| | 2488 | + memset(&ftl_sparebuffer[0], 0xFF, 0x40);
|
| | 2489 | + ftl_sparebuffer[0].meta.usn = ftl_cxt.usn;
|
| | 2490 | + ftl_sparebuffer[0].meta.type = 0x43;
|
| | 2491 | + if (ftl_vfl_write(page, 1, &ftl_cxt, &ftl_sparebuffer[0]))
|
| | 2492 | + {
|
| | 2493 | + cprintf(CONSOLE_BOOT, "Couldn't write vPage %d (save FTL context)!\n", page);
|
| | 2494 | + return 1;
|
| | 2495 | + }
|
| | 2496 | + ftl_store_ctrl_block_list();
|
| | 2497 | +}
|
| | 2498 | +
|
| | 2499 | +
|
| 2171 | 2500 | /* Initializes and mounts the FTL.
|
| 2172 | 2501 | As long as nothing was written, you won't need to unmount it.
|
| 2173 | 2502 | Before shutting down after writing something, call ftl_sync(),
|
| 2174 | | - which will just do nothing if everything was already clean. */
|
| | 2503 | + which will return immediately if everything was already clean. */
|
| 2175 | 2504 | uint32_t ftl_init(void)
|
| 2176 | 2505 | {
|
| 2177 | 2506 | mutex_init(&ftl_mtx);
|
| — | — | @@ -2214,8 +2543,20 @@ |
| 2215 | 2544 | return 1;
|
| 2216 | 2545 | }
|
| 2217 | 2546 | if (ftl_vfl_open() == 0)
|
| | 2547 | + {
|
| 2218 | 2548 | if (ftl_open() == 0)
|
| 2219 | 2549 | return 0;
|
| | 2550 | + cprintf(CONSOLE_BOOT, "The FTL seems to be damaged. Forcing check.\n");
|
| | 2551 | + if (ftl_repair() != 0)
|
| | 2552 | + cprintf(CONSOLE_BOOT, "FTL recovery failed. Use disk mode to recover.\n");
|
| | 2553 | + else
|
| | 2554 | + {
|
| | 2555 | + cprintf(CONSOLE_BOOT, "FTL recovery finished. Trying to mount again...\n");
|
| | 2556 | + if (ftl_open() == 0)
|
| | 2557 | + return 0;
|
| | 2558 | + cprintf(CONSOLE_BOOT, "Mounting FTL failed again, use disk mode to recover.\n");
|
| | 2559 | + }
|
| | 2560 | + }
|
| 2220 | 2561 |
|
| 2221 | 2562 | DEBUGF("FTL: Initialization failed!");
|
| 2222 | 2563 |
|
| Index: embios/trunk/target/ipodnano2g/ftl.h |
| — | — | @@ -31,7 +31,7 @@ |
| 32 | 32 | extern uint32_t ftl_banks;
|
| 33 | 33 |
|
| 34 | 34 |
|
| 35 | | -uint32_t ftl_init(void);
|
| | 35 | +uint32_t ftl_init(void) INITCODE_ATTR;
|
| 36 | 36 | uint32_t ftl_read(uint32_t sector, uint32_t count, void* buffer);
|
| 37 | 37 | uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer);
|
| 38 | 38 | uint32_t ftl_sync(void);
|
| Index: embios/trunk/progressbar.c |
| — | — | @@ -26,10 +26,10 @@ |
| 27 | 27 | #include "lcd.h"
|
| 28 | 28 |
|
| 29 | 29 |
|
| 30 | | -static void progressbar_drawborderbg(struct progressbar_state* state)
|
| | 30 | +static void progressbar_drawborderbg(struct progressbar_state* state, int bgstart)
|
| 31 | 31 | {
|
| 32 | 32 | state->currentx = state->startx;
|
| 33 | | - displaylcd(state->startx + 1, state->endx - 1, state->starty + 1, state->endy - 1,
|
| | 33 | + displaylcd(bgstart + 1, state->endx - 1, state->starty + 1, state->endy - 1,
|
| 34 | 34 | (void*)-1, state->bgcolor);
|
| 35 | 35 | displaylcd(state->startx, state->endx, state->starty, state->starty,
|
| 36 | 36 | (void*)-1, state->bordercolor);
|
| — | — | @@ -53,7 +53,7 @@ |
| 54 | 54 | state->fgcolor = fgcolor;
|
| 55 | 55 | state->min = min;
|
| 56 | 56 | state->max = max;
|
| 57 | | - progressbar_drawborderbg(state);
|
| | 57 | + progressbar_drawborderbg(state, state->startx);
|
| 58 | 58 | }
|
| 59 | 59 |
|
| 60 | 60 | void progressbar_setpos(struct progressbar_state* state, int value, bool redraw)
|
| — | — | @@ -62,7 +62,7 @@ |
| 63 | 63 | if (value < state->min) value = state->min;
|
| 64 | 64 | int newx = (value - state->min) * (state->endx - state->startx - 1)
|
| 65 | 65 | / (state->max - state->min) + state->startx;
|
| 66 | | - if (redraw || newx < state->currentx) progressbar_drawborderbg(state);
|
| | 66 | + if (redraw || newx < state->currentx) progressbar_drawborderbg(state, newx);
|
| 67 | 67 | if (newx > state->currentx)
|
| 68 | 68 | displaylcd(state->currentx + 1, newx, state->starty + 1, state->endy - 1,
|
| 69 | 69 | (void*)-1, state->fgcolor);
|
| Index: embios/trunk/export/syscallwrappers.h |
| — | — | @@ -75,6 +75,7 @@ |
| 76 | 76 | #define lcdconsole_get_current_y(args...) __embios_syscall->lcdconsole_get_current_y(args)
|
| 77 | 77 | #define lcdconsole_get_lineend_x(args...) __embios_syscall->lcdconsole_get_lineend_x(args)
|
| 78 | 78 | #define lcdconsole_get_lineend_y(args...) __embios_syscall->lcdconsole_get_lineend_y(args)
|
| | 79 | +#define lcdconsole_progressbar(args...) __embios_syscall->lcdconsole_progressbar(args)
|
| 79 | 80 | #define progressbar_init(args...) __embios_syscall->progressbar_init(args)
|
| 80 | 81 | #define progressbar_setpos(args...) __embios_syscall->progressbar_setpos(args)
|
| 81 | 82 | #define shutdown(args...) __embios_syscall->shutdown(args)
|
| Index: embios/trunk/export/syscallapi.h |
| — | — | @@ -112,6 +112,7 @@ |
| 113 | 113 | typeof(lcdconsole_get_current_y) *lcdconsole_get_current_y;
|
| 114 | 114 | typeof(lcdconsole_get_lineend_x) *lcdconsole_get_lineend_x;
|
| 115 | 115 | typeof(lcdconsole_get_lineend_y) *lcdconsole_get_lineend_y;
|
| | 116 | + typeof(lcdconsole_progressbar) *lcdconsole_progressbar;
|
| 116 | 117 | typeof(progressbar_init) *progressbar_init;
|
| 117 | 118 | typeof(progressbar_setpos) *progressbar_setpos;
|
| 118 | 119 | typeof(shutdown) *shutdown;
|
| Index: embios/trunk/syscallapi.c |
| — | — | @@ -133,6 +133,7 @@ |
| 134 | 134 | .lcdconsole_get_current_y = lcdconsole_get_current_y,
|
| 135 | 135 | .lcdconsole_get_lineend_x = lcdconsole_get_lineend_x,
|
| 136 | 136 | .lcdconsole_get_lineend_y = lcdconsole_get_lineend_y,
|
| | 137 | + .lcdconsole_progressbar = lcdconsole_progressbar,
|
| 137 | 138 | .progressbar_init = progressbar_init,
|
| 138 | 139 | .progressbar_setpos = progressbar_setpos,
|
| 139 | 140 | .displaylcd = displaylcd,
|
| Index: embios/trunk/lcdconsole.c |
| — | — | @@ -26,6 +26,7 @@ |
| 27 | 27 | #include "drawing.h"
|
| 28 | 28 | #include "util.h"
|
| 29 | 29 | #include "contextswitch.h"
|
| | 30 | +#include "progressbar.h"
|
| 30 | 31 |
|
| 31 | 32 |
|
| 32 | 33 | #define OFFSETX LCDCONSOLE_OFFSETX
|
| — | — | @@ -153,3 +154,11 @@ |
| 154 | 155 | {
|
| 155 | 156 | return (current_row + 1) * FONT_HEIGHT + OFFSETY - 1;
|
| 156 | 157 | }
|
| | 158 | +
|
| | 159 | +void lcdconsole_progressbar(struct progressbar_state* progressbar, int min, int max)
|
| | 160 | +{
|
| | 161 | + progressbar_init(progressbar, lcdconsole_get_current_x(), lcdconsole_get_lineend_x(),
|
| | 162 | + lcdconsole_get_current_y(), lcdconsole_get_lineend_y(),
|
| | 163 | + lcd_translate_color(0, 0, 0, 0), lcd_translate_color(0, 0xcf, 0xcf, 0xcf),
|
| | 164 | + lcd_translate_color(0, 0, 0, 0xef), min, max);
|
| | 165 | +}
|
| Index: embios/trunk/lcdconsole.h |
| — | — | @@ -28,6 +28,7 @@ |
| 29 | 29 | #include "global.h"
|
| 30 | 30 | #include "drawing.h"
|
| 31 | 31 | #include "lcd.h"
|
| | 32 | +#include "progressbar.h"
|
| 32 | 33 |
|
| 33 | 34 |
|
| 34 | 35 | #define LCDCONSOLE_COLS (LCD_WIDTH / FONT_WIDTH)
|
| — | — | @@ -49,6 +50,7 @@ |
| 50 | 51 | int lcdconsole_get_current_y() ICODE_ATTR;
|
| 51 | 52 | int lcdconsole_get_lineend_x() ICODE_ATTR;
|
| 52 | 53 | int lcdconsole_get_lineend_y() ICODE_ATTR;
|
| | 54 | +void lcdconsole_progressbar(struct progressbar_state* progressbar, int min, int max);
|
| 53 | 55 |
|
| 54 | 56 |
|
| 55 | 57 | #endif
|