Subversion Repositories freemyipod

Rev

Rev 69 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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