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
|