| Index: emcore/trunk/target/ipodnano2g/ftl.c | 
| — | — | @@ -417,19 +417,21 @@ | 
| 418 | 418 | back if something fails while compacting a scattered page block. */ | 
| 419 | 419 | static uint16_t ftl_offsets_backup[0x200] CACHEALIGN_ATTR; | 
| 420 | 420 |  | 
| 421 |  | -/* Buffers needed for FTL recovery */
 | 
| 422 |  | -static uint32_t blk_usn[0x2000] INITBSS_ATTR;
 | 
| 423 |  | -static uint8_t blk_type[0x2000] INITBSS_ATTR;
 | 
| 424 |  | -static uint32_t erasectr_usn[8] INITBSS_ATTR;
 | 
| 425 |  | -static uint32_t pageusn[0x200] INITBSS_ATTR;
 | 
| 426 |  | -static uint8_t pagedata[0x200][0x800] INITBSS_ATTR CACHEALIGN_ATTR;
 | 
|  | 421 | +struct nandfsck_bss  /* This will be malloc()ed if needed */ | 
|  | 422 | +{ | 
|  | 423 | +    /* Buffers needed for FTL recovery */ | 
|  | 424 | +    uint32_t blk_usn[0x2000]; | 
|  | 425 | +    int8_t blk_type[0x2000]; | 
|  | 426 | +    uint32_t erasectr_usn[8]; | 
|  | 427 | +    uint32_t pageusn[0x200]; | 
|  | 428 | +    uint8_t pagedata[0x200][0x800]; | 
| 427 | 429 |  | 
| 428 |  | -/* State information needed for FTL recovery */
 | 
| 429 |  | -static uint32_t meta_usn INITBSS_ATTR;
 | 
| 430 |  | -static uint32_t user_usn INITBSS_ATTR;
 | 
| 431 |  | -static uint32_t allocmode INITBSS_ATTR;
 | 
| 432 |  | -static uint32_t firstfree INITBSS_ATTR;
 | 
| 433 |  | -
 | 
|  | 430 | +    /* State information needed for FTL recovery */ | 
|  | 431 | +    uint32_t meta_usn; | 
|  | 432 | +    uint32_t user_usn; | 
|  | 433 | +    uint32_t allocmode; | 
|  | 434 | +    uint32_t firstfree; | 
|  | 435 | +}; | 
| 434 | 436 | #endif | 
| 435 | 437 |  | 
| 436 | 438 |  | 
| — | — | @@ -2236,31 +2238,32 @@ | 
| 2237 | 2239 |  | 
| 2238 | 2240 |  | 
| 2239 | 2241 | /* Block allocator for FTL recovery */ | 
| 2240 |  | -static uint32_t ftl_alloc_block() INITCODE_ATTR;
 | 
| 2241 |  | -static uint32_t ftl_alloc_block()
 | 
|  | 2242 | +static uint32_t ftl_alloc_block(struct nandfsck_bss* nb) INITCODE_ATTR; | 
|  | 2243 | +static uint32_t ftl_alloc_block(struct nandfsck_bss* nb) | 
| 2242 | 2244 | { | 
| 2243 | 2245 | while (1) | 
| 2244 | 2246 | { | 
| 2245 |  | -        for (; firstfree < ftl_nand_type->userblocks + 0x17; firstfree++)
 | 
| 2246 |  | -            if (!blk_type[firstfree]) break;
 | 
| 2247 |  | -            else if (allocmode && blk_type[firstfree] != 1)
 | 
|  | 2247 | +        for (; nb->firstfree < ftl_nand_type->userblocks + 0x17; nb->firstfree++) | 
|  | 2248 | +            if (!nb->blk_type[nb->firstfree]) break; | 
|  | 2249 | +            else if (nb->allocmode && nb->blk_type[nb->firstfree] != 1) | 
| 2248 | 2250 | { | 
| 2249 |  | -                if (ftl_erase_block(firstfree))
 | 
|  | 2251 | +                if (ftl_erase_block(nb->firstfree)) | 
| 2250 | 2252 | { | 
| 2251 |  | -                    cprintf(CONSOLE_BOOT, "Couldn't erase vBlock %d (pool alloc)!\n", firstfree);
 | 
|  | 2253 | +                    cprintf(CONSOLE_BOOT, "Couldn't erase vBlock %d (pool alloc)!\n", | 
|  | 2254 | +                            nb->firstfree); | 
| 2252 | 2255 | return 1; | 
| 2253 | 2256 | } | 
| 2254 | 2257 | break; | 
| 2255 | 2258 | } | 
| 2256 |  | -        if (firstfree < ftl_nand_type->userblocks + 0x17)
 | 
|  | 2259 | +        if (nb->firstfree < ftl_nand_type->userblocks + 0x17) | 
| 2257 | 2260 | { | 
| 2258 |  | -            blk_type[firstfree] = 1;
 | 
| 2259 |  | -            return firstfree++;
 | 
|  | 2261 | +            nb->blk_type[nb->firstfree] = 1; | 
|  | 2262 | +            return nb->firstfree++; | 
| 2260 | 2263 | } | 
| 2261 |  | -        if (!allocmode)
 | 
|  | 2264 | +        if (!nb->allocmode) | 
| 2262 | 2265 | { | 
| 2263 |  | -            allocmode = 1;
 | 
| 2264 |  | -            firstfree = 0;
 | 
|  | 2266 | +            nb->allocmode = 1; | 
|  | 2267 | +            nb->firstfree = 0; | 
| 2265 | 2268 | } | 
| 2266 | 2269 | else | 
| 2267 | 2270 | { | 
| — | — | @@ -2279,6 +2282,8 @@ | 
| 2280 | 2283 | struct progressbar_state progressbar; | 
| 2281 | 2284 | #endif | 
| 2282 | 2285 |  | 
|  | 2286 | +    struct nandfsck_bss* nb = (struct nandfsck_bss*)memalign(0x10, sizeof(struct nandfsck_bss)); | 
|  | 2287 | + | 
| 2283 | 2288 | cputs(CONSOLE_BOOT, "Scanning flash...\n"); | 
| 2284 | 2289 | #ifdef HAVE_LCD | 
| 2285 | 2290 | lcdconsole_progressbar(&progressbar, 0, ftl_nand_type->userblocks + 0x17); | 
| — | — | @@ -2286,12 +2291,12 @@ | 
| 2287 | 2292 | uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks; | 
| 2288 | 2293 | memset(&ftl_cxt, 0x00, sizeof(ftl_cxt)); | 
| 2289 | 2294 | memset(ftl_map, 0xff, sizeof(ftl_map)); | 
| 2290 |  | -    memset(blk_usn, 0x00, sizeof(blk_usn));
 | 
| 2291 |  | -    memset(blk_type, 0x00, sizeof(blk_type));
 | 
|  | 2295 | +    memset(nb->blk_usn, 0x00, sizeof(nb->blk_usn)); | 
|  | 2296 | +    memset(nb->blk_type, 0x00, sizeof(nb->blk_type)); | 
| 2292 | 2297 | memset(ftl_erasectr, 0x00, sizeof(ftl_erasectr)); | 
| 2293 |  | -    memset(erasectr_usn, 0xff, sizeof(erasectr_usn));
 | 
| 2294 |  | -    user_usn = 0;
 | 
| 2295 |  | -    meta_usn = 0xffffffff;
 | 
|  | 2298 | +    memset(nb->erasectr_usn, 0xff, sizeof(nb->erasectr_usn)); | 
|  | 2299 | +    nb->user_usn = 0; | 
|  | 2300 | +    nb->meta_usn = 0xffffffff; | 
| 2296 | 2301 | for (i = 0; i < ftl_nand_type->userblocks + 0x17; i++) | 
| 2297 | 2302 | { | 
| 2298 | 2303 | uint32_t ret = ftl_vfl_read((i + 1) * ppb - 1, 0, &ftl_sparebuffer[0], 1, 0); | 
| — | — | @@ -2298,17 +2303,17 @@ | 
| 2299 | 2304 | if ((ret & 0x11F) == 0 && ftl_sparebuffer[0].meta.type == 0x41) | 
| 2300 | 2305 | { | 
| 2301 | 2306 | uint32_t lbn = ftl_sparebuffer[0].user.lpn / ppb; | 
| 2302 |  | -            if (ftl_sparebuffer[0].user.usn > user_usn)
 | 
| 2303 |  | -                user_usn = ftl_sparebuffer[0].user.usn;
 | 
| 2304 |  | -            if (ftl_sparebuffer[0].user.usn > blk_usn[lbn])
 | 
|  | 2307 | +            if (ftl_sparebuffer[0].user.usn > nb->user_usn) | 
|  | 2308 | +                nb->user_usn = ftl_sparebuffer[0].user.usn; | 
|  | 2309 | +            if (ftl_sparebuffer[0].user.usn > nb->blk_usn[lbn]) | 
| 2305 | 2310 | { | 
| 2306 | 2311 | if (ftl_map[lbn] != 0xffff) | 
| 2307 |  | -                    blk_type[ftl_map[lbn]] = 5;
 | 
| 2308 |  | -                blk_usn[lbn] = ftl_sparebuffer[0].user.usn;
 | 
|  | 2312 | +                    nb->blk_type[ftl_map[lbn]] = 5; | 
|  | 2313 | +                nb->blk_usn[lbn] = ftl_sparebuffer[0].user.usn; | 
| 2309 | 2314 | ftl_map[lbn] = i; | 
| 2310 |  | -                blk_type[i] = 1;
 | 
|  | 2315 | +                nb->blk_type[i] = 1; | 
| 2311 | 2316 | } | 
| 2312 |  | -            else blk_type[i] = 5;
 | 
|  | 2317 | +            else nb->blk_type[i] = 5; | 
| 2313 | 2318 | } | 
| 2314 | 2319 | else | 
| 2315 | 2320 | for (j = 0; j < ppb; j++) | 
| — | — | @@ -2317,25 +2322,25 @@ | 
| 2318 | 2323 | if (ret & 2) break; | 
| 2319 | 2324 | if (ret & 0x11F) | 
| 2320 | 2325 | { | 
| 2321 |  | -                    blk_type[i] = 4;
 | 
|  | 2326 | +                    nb->blk_type[i] = 4; | 
| 2322 | 2327 | continue; | 
| 2323 | 2328 | } | 
| 2324 | 2329 | if (ftl_sparebuffer[0].meta.type == 0x40) | 
| 2325 | 2330 | { | 
| 2326 |  | -                    blk_type[i] = 2;
 | 
|  | 2331 | +                    nb->blk_type[i] = 2; | 
| 2327 | 2332 | break; | 
| 2328 | 2333 | } | 
| 2329 | 2334 | else if (ftl_sparebuffer[0].meta.type - 0x43 <= 4) | 
| 2330 | 2335 | { | 
| 2331 |  | -                    blk_type[i] = 3;
 | 
|  | 2336 | +                    nb->blk_type[i] = 3; | 
| 2332 | 2337 | if (ftl_sparebuffer[0].meta.type == 0x46) | 
| 2333 | 2338 | { | 
| 2334 | 2339 | uint32_t idx = ftl_sparebuffer[0].meta.idx; | 
| 2335 |  | -                        if (ftl_sparebuffer[0].meta.usn < meta_usn)
 | 
| 2336 |  | -                            meta_usn = ftl_sparebuffer[0].meta.usn;
 | 
| 2337 |  | -                        if (ftl_sparebuffer[0].meta.usn < erasectr_usn[idx])
 | 
|  | 2340 | +                        if (ftl_sparebuffer[0].meta.usn < nb->meta_usn) | 
|  | 2341 | +                            nb->meta_usn = ftl_sparebuffer[0].meta.usn; | 
|  | 2342 | +                        if (ftl_sparebuffer[0].meta.usn < nb->erasectr_usn[idx]) | 
| 2338 | 2343 | { | 
| 2339 |  | -                            erasectr_usn[idx] = ftl_sparebuffer[0].meta.usn;
 | 
|  | 2344 | +                            nb->erasectr_usn[idx] = ftl_sparebuffer[0].meta.usn; | 
| 2340 | 2345 | ret = ftl_vfl_read(i * ppb + j, &ftl_erasectr[idx << 10], | 
| 2341 | 2346 | &ftl_sparebuffer[0], 1, 0); | 
| 2342 | 2347 | if (ret & 0x11f) memset(&ftl_erasectr[idx << 10], 0, 0x800); | 
| — | — | @@ -2366,6 +2371,7 @@ | 
| 2367 | 2372 | } | 
| 2368 | 2373 | } | 
| 2369 | 2374 | cprintf(CONSOLE_BOOT, "\n"); | 
|  | 2375 | +                    free(nb); | 
| 2370 | 2376 | return 1; | 
| 2371 | 2377 | } | 
| 2372 | 2378 | } | 
| — | — | @@ -2391,7 +2397,7 @@ | 
| 2392 | 2398 | cputs(CONSOLE_BOOT, "Committing scattered pages...\n"); | 
| 2393 | 2399 | count = 0; | 
| 2394 | 2400 | for (i = 0; i < ftl_nand_type->userblocks + 0x17; i++) | 
| 2395 |  | -        if (blk_type[i] == 2) count++;
 | 
|  | 2401 | +        if (nb->blk_type[i] == 2) count++; | 
| 2396 | 2402 | uint32_t block; | 
| 2397 | 2403 | uint32_t dirty; | 
| 2398 | 2404 | if (count) | 
| — | — | @@ -2401,7 +2407,7 @@ | 
| 2402 | 2408 | #endif | 
| 2403 | 2409 | count = 0; | 
| 2404 | 2410 | for (i = 0; i < ftl_nand_type->userblocks + 0x17; i++) | 
| 2405 |  | -            if (blk_type[i] == 2)
 | 
|  | 2411 | +            if (nb->blk_type[i] == 2) | 
| 2406 | 2412 | { | 
| 2407 | 2413 | block = 0xffff; | 
| 2408 | 2414 | for (j = 0; j < ppb; j++) | 
| — | — | @@ -2417,17 +2423,18 @@ | 
| 2418 | 2424 | cprintf(CONSOLE_BOOT, "Invalid block type %02X while reading " | 
| 2419 | 2425 | "vPage %d (scattered page)!\n", | 
| 2420 | 2426 | ftl_sparebuffer[0].meta.type, i * ppb + j); | 
|  | 2427 | +                        free(nb); | 
| 2421 | 2428 | return 1; | 
| 2422 | 2429 | } | 
| 2423 | 2430 | if (block == 0xffff) | 
| 2424 | 2431 | { | 
| 2425 | 2432 | block = ftl_sparebuffer[0].user.lpn / ppb; | 
| 2426 |  | -                        memset(pageusn, 0x00, 0x800);
 | 
| 2427 |  | -                        memset(pagedata, 0x00, 0x100000);
 | 
|  | 2433 | +                        memset(nb->pageusn, 0x00, 0x800); | 
|  | 2434 | +                        memset(nb->pagedata, 0x00, 0x100000); | 
| 2428 | 2435 | if (ftl_map[block] != 0xffff) | 
| 2429 | 2436 | for (k = 0; k < ppb; k++) | 
| 2430 | 2437 | { | 
| 2431 |  | -                                uint32_t ret = ftl_vfl_read(ftl_map[block] * ppb + k, pagedata[k],
 | 
|  | 2438 | +                                uint32_t ret = ftl_vfl_read(ftl_map[block] * ppb + k, nb->pagedata[k], | 
| 2432 | 2439 | &ftl_copyspare[0], 1, 0); | 
| 2433 | 2440 | if (ret & 0x11F) continue; | 
| 2434 | 2441 | if (ftl_copyspare[0].user.type != 0x40 | 
| — | — | @@ -2437,6 +2444,7 @@ | 
| 2438 | 2445 | "vPage %d (scattered page orig)!\n", | 
| 2439 | 2446 | ftl_sparebuffer[0].meta.type, | 
| 2440 | 2447 | ftl_map[block] * ppb + k); | 
|  | 2448 | +                                    free(nb); | 
| 2441 | 2449 | return 1; | 
| 2442 | 2450 | } | 
| 2443 | 2451 | if (block != ftl_copyspare[0].user.lpn / ppb) | 
| — | — | @@ -2445,9 +2453,10 @@ | 
| 2446 | 2454 | "block (vPage %d, LPN %d)!\n", | 
| 2447 | 2455 | ftl_map[block] * ppb + k, | 
| 2448 | 2456 | ftl_sparebuffer[0].user.usn); | 
|  | 2457 | +                                    free(nb); | 
| 2449 | 2458 | return 1; | 
| 2450 | 2459 | } | 
| 2451 |  | -                                pageusn[k] = ftl_copyspare[0].user.usn;
 | 
|  | 2460 | +                                nb->pageusn[k] = ftl_copyspare[0].user.usn; | 
| 2452 | 2461 | } | 
| 2453 | 2462 | dirty = 0; | 
| 2454 | 2463 | } | 
| — | — | @@ -2456,15 +2465,16 @@ | 
| 2457 | 2466 | cprintf(CONSOLE_BOOT, "Foreign page in scattered page block " | 
| 2458 | 2467 | "block (vPage %d, LPN %d)!\n", | 
| 2459 | 2468 | i * ppb + j, ftl_sparebuffer[0].user.lpn); | 
|  | 2469 | +                        free(nb); | 
| 2460 | 2470 | return 1; | 
| 2461 | 2471 | } | 
| 2462 | 2472 | uint32_t idx = ftl_sparebuffer[0].user.lpn % ppb; | 
| 2463 |  | -                    if (ftl_sparebuffer[0].user.usn > user_usn)
 | 
| 2464 |  | -                        user_usn = ftl_sparebuffer[0].user.usn;
 | 
| 2465 |  | -                    if (ftl_sparebuffer[0].user.usn > pageusn[idx])
 | 
|  | 2473 | +                    if (ftl_sparebuffer[0].user.usn > nb->user_usn) | 
|  | 2474 | +                        nb->user_usn = ftl_sparebuffer[0].user.usn; | 
|  | 2475 | +                    if (ftl_sparebuffer[0].user.usn > nb->pageusn[idx]) | 
| 2466 | 2476 | { | 
| 2467 |  | -                        pageusn[idx] = ftl_sparebuffer[0].user.usn;
 | 
| 2468 |  | -                        memcpy(pagedata[idx], ftl_buffer, 0x800);
 | 
|  | 2477 | +                        nb->pageusn[idx] = ftl_sparebuffer[0].user.usn; | 
|  | 2478 | +                        memcpy(nb->pagedata[idx], ftl_buffer, 0x800); | 
| 2469 | 2479 | dirty = 1; | 
| 2470 | 2480 | } | 
| 2471 | 2481 | } | 
| — | — | @@ -2474,6 +2484,7 @@ | 
| 2475 | 2485 | { | 
| 2476 | 2486 | cprintf(CONSOLE_BOOT, "Couldn't erase vBlock %d " | 
| 2477 | 2487 | "(scattered page commit)!\n", i); | 
|  | 2488 | +                        free(nb); | 
| 2478 | 2489 | return 1; | 
| 2479 | 2490 | } | 
| 2480 | 2491 | for (j = 0; j < ppb; j++) | 
| — | — | @@ -2483,21 +2494,22 @@ | 
| 2484 | 2495 | #endif | 
| 2485 | 2496 | memset(&ftl_sparebuffer[0], 0xFF, 0x40); | 
| 2486 | 2497 | ftl_sparebuffer[0].user.lpn = block * ppb + j; | 
| 2487 |  | -                        ftl_sparebuffer[0].user.usn = pageusn[j];
 | 
|  | 2498 | +                        ftl_sparebuffer[0].user.usn = nb->pageusn[j]; | 
| 2488 | 2499 | ftl_sparebuffer[0].user.type = 0x40; | 
| 2489 | 2500 | if (j == ppb - 1) ftl_sparebuffer[0].user.type = 0x41; | 
| 2490 |  | -                        if (ftl_vfl_write(i * ppb + j, 1, pagedata[j], &ftl_sparebuffer[0]))
 | 
|  | 2501 | +                        if (ftl_vfl_write(i * ppb + j, 1, nb->pagedata[j], &ftl_sparebuffer[0])) | 
| 2491 | 2502 | { | 
| 2492 | 2503 | cprintf(CONSOLE_BOOT, "Couldn't write vPage %d " | 
| 2493 | 2504 | "(scattered page commit)!\n", i * ppb + j); | 
|  | 2505 | +                            free(nb); | 
| 2494 | 2506 | return 1; | 
| 2495 | 2507 | } | 
| 2496 | 2508 | } | 
| 2497 |  | -                    if (ftl_map[block] != 0xffff) blk_type[ftl_map[block]] = 5;
 | 
| 2498 |  | -                    blk_type[i] = 1;
 | 
|  | 2509 | +                    if (ftl_map[block] != 0xffff) nb->blk_type[ftl_map[block]] = 5; | 
|  | 2510 | +                    nb->blk_type[i] = 1; | 
| 2499 | 2511 | ftl_map[block] = i; | 
| 2500 | 2512 | } | 
| 2501 |  | -                else blk_type[i] = 5;
 | 
|  | 2513 | +                else nb->blk_type[i] = 5; | 
| 2502 | 2514 | #ifdef HAVE_LCD | 
| 2503 | 2515 | progressbar_setpos(&progressbar, ++count * ppb * 2, false); | 
| 2504 | 2516 | #endif | 
| — | — | @@ -2505,17 +2517,18 @@ | 
| 2506 | 2518 | } | 
| 2507 | 2519 |  | 
| 2508 | 2520 | cputs(CONSOLE_BOOT, "Fixing block map...\n"); | 
| 2509 |  | -    allocmode = 0;
 | 
| 2510 |  | -    firstfree = 0;
 | 
| 2511 |  | -    for (i = 0; i < 3; i++) ftl_cxt.ftlctrlblocks[i] = ftl_alloc_block();
 | 
| 2512 |  | -    for (i = 0; i < 20; i++) ftl_cxt.blockpool[i] = ftl_alloc_block();
 | 
|  | 2521 | +    nb->allocmode = 0; | 
|  | 2522 | +    nb->firstfree = 0; | 
|  | 2523 | +    for (i = 0; i < 3; i++) ftl_cxt.ftlctrlblocks[i] = ftl_alloc_block(nb); | 
|  | 2524 | +    for (i = 0; i < 20; i++) ftl_cxt.blockpool[i] = ftl_alloc_block(nb); | 
| 2513 | 2525 | for (i = 0; i < ftl_nand_type->userblocks; i++) | 
| 2514 | 2526 | if (ftl_map[i] == 0xffff) | 
| 2515 |  | -            ftl_map[i] = ftl_alloc_block();
 | 
| 2516 |  | -    ftl_cxt.usn = meta_usn - 1;
 | 
| 2517 |  | -    ftl_cxt.nextblockusn = user_usn + 1;
 | 
|  | 2527 | +            ftl_map[i] = ftl_alloc_block(nb); | 
|  | 2528 | +    ftl_cxt.usn = nb->meta_usn - 1; | 
|  | 2529 | +    ftl_cxt.nextblockusn = nb->user_usn + 1; | 
| 2518 | 2530 | ftl_cxt.freecount = 20; | 
| 2519 | 2531 | ftl_cxt.clean_flag = 1; | 
|  | 2532 | +    free(nb); | 
| 2520 | 2533 |  | 
| 2521 | 2534 | cputs(CONSOLE_BOOT, "Committing FTL context...\n"); | 
| 2522 | 2535 | uint32_t blockmappages = ftl_nand_type->userblocks >> 10; |