Subversion Repositories freemyipod

Rev

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

Rev 2 Rev 54
Line 22... Line 22...
22
 
22
 
23
 
23
 
24
 
24
 
25
#include "global.h"
25
#include "global.h"
26
#include "nand.h"
26
#include "nand.h"
27
#include "storage.h"
27
#include "ftl.h"
28
#include "util.h"
28
#include "util.h"
-
 
29
#include "thread.h"
-
 
30
#include "panic.h"
-
 
31
#include "debug.h"
29
 
32
 
30
 
33
 
31
 
34
 
-
 
35
#define FTL_COPYBUF_SIZE 4
-
 
36
#define FTL_WRITESPARE_SIZE 32
32
//#define FTL_FORCEMOUNT
37
//#define FTL_FORCEMOUNT
33
 
38
 
34
 
39
 
35
 
40
 
36
#ifdef FTL_FORCEMOUNT
41
#ifdef FTL_FORCEMOUNT
Line 39... Line 44...
39
#endif
44
#endif
40
#endif
45
#endif
41
 
46
 
42
 
47
 
43
#ifdef FTL_READONLY
48
#ifdef FTL_READONLY
44
uint32_t storage_write(uint32_t sector, uint32_t count, const void* buffer)
49
uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer)
45
{
50
{
46
    (void)sector;
51
    (void)sector;
47
    (void)count;
52
    (void)count;
48
    (void)buffer;
53
    (void)buffer;
49
    return -1;
54
    return -1;
50
}
55
}
51
uint32_t storage_sync(void)
56
uint32_t ftl_sync(void)
52
{
57
{
53
    return 0;
58
    return 0;
54
}
59
}
55
#endif
60
#endif
56
 
61
 
Line 109... Line 114...
109
    uint32_t nextblockusn;
114
    uint32_t nextblockusn;
110
 
115
 
111
    /* Count of currently free pages in the block pool */
116
    /* Count of currently free pages in the block pool */
112
    uint16_t freecount;
117
    uint16_t freecount;
113
 
118
 
114
    /* Index to the first free block in the blockpool ring buffer */
119
    /* Index to the first free hyperblock in the blockpool ring buffer */
115
    uint16_t nextfreeidx;
120
    uint16_t nextfreeidx;
116
 
121
 
117
    /* This is a counter that is used to better distribute block
122
    /* This is a counter that is used to better distribute block
118
       wear. It is incremented on every block erase, and if it
123
       wear. It is incremented on every block erase, and if it
119
       gets too high (300 on writes, 20 on sync), the most and
124
       gets too high (300 on writes, 20 on sync), the most and
120
       least worn block will be swapped (inferring an additional
125
       least worn hyperblock will be swapped (causing an additional
121
       block write) and the counter will be decreased by 20. */
126
       block write) and the counter will be decreased by 20. */
122
    uint16_t swapcounter;
127
    uint16_t swapcounter;
123
 
128
 
124
    /* Ring buffer of currently free blocks. nextfreeidx is the
129
    /* Ring buffer of currently free hyperblocks. nextfreeidx is the
125
       index to freecount free ones, the other ones are currently
130
       index to freecount free ones, the other ones are currently
126
       allocated for scattered page blocks. */
131
       allocated for scattered page hyperblocks. */
127
    uint16_t blockpool[0x14];
132
    uint16_t blockpool[0x14];
128
 
133
 
129
    /* Alignment to 32 bits */
134
    /* Alignment to 32 bits */
130
    uint16_t field_36;
135
    uint16_t field_36;
131
 
136
 
Line 149... Line 154...
149
 
154
 
150
    /* Pointer to ftl_log used by Whimory, not used by us */
155
    /* Pointer to ftl_log used by Whimory, not used by us */
151
    uint32_t ftl_log_ptr;
156
    uint32_t ftl_log_ptr;
152
 
157
 
153
    /* Flag used to indicate that some erase counter pages should be committed
158
    /* Flag used to indicate that some erase counter pages should be committed
154
       as they were changed more than 100 times since the last commit. */
159
       because they were changed more than 100 times since the last commit. */
155
    uint32_t erasedirty;
160
    uint32_t erasedirty;
156
 
161
 
157
    /* Seems to be unused */
162
    /* Seems to be unused */
158
    uint16_t field_120;
163
    uint16_t field_120;
159
 
164
 
Line 199... Line 204...
199
 
204
 
200
    /* Number of the currently active VFL context block, it's an index
205
    /* Number of the currently active VFL context block, it's an index
201
       into vflcxtblocks. */
206
       into vflcxtblocks. */
202
    uint16_t activecxtblock;
207
    uint16_t activecxtblock;
203
 
208
 
204
    /* Number of the first free page in the active FTL context block */
209
    /* Number of the first free page in the active VFL context block */
205
    uint16_t nextcxtpage;
210
    uint16_t nextcxtpage;
206
 
211
 
207
    /* Seems to be unused */
212
    /* Seems to be unused */
208
    uint8_t field_14[4];
213
    uint8_t field_14[4];
209
 
214
 
Line 364... Line 369...
364
 
369
 
365
/* FTL context */
370
/* FTL context */
366
struct ftl_cxt_type ftl_cxt;
371
struct ftl_cxt_type ftl_cxt;
367
 
372
 
368
/* Temporary data buffers for internal use by the FTL */
373
/* Temporary data buffers for internal use by the FTL */
369
uint8_t ftl_buffer[0x800] __attribute__((aligned(16)));
374
uint8_t ftl_buffer[0x800] CACHEALIGN_ATTR;
370
 
375
 
371
/* Temporary spare byte buffer for internal use by the FTL */
376
/* Temporary spare byte buffer for internal use by the FTL */
372
union ftl_spare_data_type ftl_sparebuffer __attribute__((aligned(16)));
377
union ftl_spare_data_type ftl_sparebuffer[FTL_WRITESPARE_SIZE] CACHEALIGN_ATTR;
373
 
-
 
374
uint32_t ftl_initialized;
-
 
375
 
378
 
376
 
379
 
377
#ifndef FTL_READONLY
380
#ifndef FTL_READONLY
378
 
381
 
379
/* Lowlevel BBT for each bank */
382
/* Lowlevel BBT for each bank */
380
uint8_t ftl_bbt[4][0x410];
383
uint8_t ftl_bbt[4][0x410];
381
 
384
 
382
/* Erase countes for the vBlocks */
385
/* Erase counters for the vBlocks */
383
uint16_t ftl_erasectr[0x2000];
386
uint16_t ftl_erasectr[0x2000];
384
 
387
 
385
/* Used by ftl_log */
388
/* Used by ftl_log */
386
uint16_t ftl_offsets[0x11][0x200];
389
uint16_t ftl_offsets[0x11][0x200];
387
 
390
 
Line 399... Line 402...
399
uint8_t ftl_erasectr_dirt[8];
402
uint8_t ftl_erasectr_dirt[8];
400
 
403
 
401
/* Buffer needed for copying pages around while moving or committing blocks.
404
/* Buffer needed for copying pages around while moving or committing blocks.
402
   This can't be shared with ftl_buffer, because this one could be overwritten
405
   This can't be shared with ftl_buffer, because this one could be overwritten
403
   during the copying operation in order to e.g. commit a CXT. */
406
   during the copying operation in order to e.g. commit a CXT. */
404
uint8_t ftl_copybuffer[0x800] __attribute__((aligned(16)));
407
uint8_t ftl_copybuffer[FTL_COPYBUF_SIZE][0x800] CACHEALIGN_ATTR;
-
 
408
union ftl_spare_data_type ftl_copyspare[FTL_COPYBUF_SIZE] CACHEALIGN_ATTR;
405
 
409
 
406
/* Needed to store the old scattered page offsets in order to be able to roll
410
/* Needed to store the old scattered page offsets in order to be able to roll
407
   back if something fails while compacting a scattered page block. */
411
   back if something fails while compacting a scattered page block. */
408
uint16_t ftl_offsets_backup[0x200] __attribute__((aligned(16)));
412
uint16_t ftl_offsets_backup[0x200] CACHEALIGN_ATTR;
409
 
413
 
410
#endif
414
#endif
411
 
415
 
412
 
416
 
-
 
417
static struct mutex ftl_mtx;
413
 
418
 
414
 
419
 
415
 
420
 
416
/* Finds a device info page for the specified bank and returns its number.
421
/* Finds a device info page for the specified bank and returns its number.
417
   Used to check if one is present, and to read the lowlevel BBT. */
422
   Used to check if one is present, and to read the lowlevel BBT. */
418
uint32_t ftl_find_devinfo(uint32_t bank)
423
uint32_t ftl_find_devinfo(uint32_t bank)
419
{
424
{
420
    /* Scan the last 10% of the flash for device info pages */
425
    /* Scan the last 10% of the flash for device info pages */
421
    uint32_t lowestBlock = (*ftl_nand_type).blocks
426
    uint32_t lowestBlock = ftl_nand_type->blocks
422
                         - ((*ftl_nand_type).blocks / 10);
427
                         - (ftl_nand_type->blocks / 10);
423
    uint32_t block, page, pagenum;
428
    uint32_t block, page, pagenum;
424
    for (block = (*ftl_nand_type).blocks - 1; block >= lowestBlock; block--)
429
    for (block = ftl_nand_type->blocks - 1; block >= lowestBlock; block--)
425
    {
430
    {
426
        page = (*ftl_nand_type).pagesperblock - 8;
431
        page = ftl_nand_type->pagesperblock - 8;
427
        for (; page < (*ftl_nand_type).pagesperblock; page++)
432
        for (; page < ftl_nand_type->pagesperblock; page++)
428
        {
433
        {
429
            pagenum = block * (*ftl_nand_type).pagesperblock + page;
434
            pagenum = block * ftl_nand_type->pagesperblock + page;
430
            if ((nand_read_page(bank, pagenum, ftl_buffer,
435
            if ((nand_read_page(bank, pagenum, ftl_buffer,
431
                                &ftl_sparebuffer, 1, 0) & 0x11F) != 0)
436
                                &ftl_sparebuffer[0], 1, 0) & 0x11F) != 0)
432
                continue;
437
                continue;
433
            if (memcmp(ftl_buffer, "DEVICEINFOSIGN\0", 0x10) == 0)
438
            if (memcmp(ftl_buffer, "DEVICEINFOSIGN\0", 0x10) == 0)
434
                return pagenum;
439
                return pagenum;
435
        }
440
        }
436
    }
441
    }
Line 453... Line 458...
453
{
458
{
454
    uint32_t i, j;
459
    uint32_t i, j;
455
    uint32_t pagebase, page = ftl_find_devinfo(bank), page2;
460
    uint32_t pagebase, page = ftl_find_devinfo(bank), page2;
456
    uint32_t unk1, unk2, unk3;
461
    uint32_t unk1, unk2, unk3;
457
    if (page == 0) return 1;
462
    if (page == 0) return 1;
458
    pagebase = page & ~((*ftl_nand_type).pagesperblock - 1);
463
    pagebase = page & ~(ftl_nand_type->pagesperblock - 1);
459
    if ((nand_read_page(bank, page, ftl_buffer,
464
    if ((nand_read_page(bank, page, ftl_buffer,
460
                        (uint32_t*)0, 1, 0) & 0x11F) != 0) return 1;
465
                        (uint32_t*)0, 1, 0) & 0x11F) != 0) return 1;
461
    if (memcmp(&ftl_buffer[0x18], "BBT", 4) != 0) return 1;
466
    if (memcmp(&ftl_buffer[0x18], "BBT", 4) != 0) return 1;
462
    unk1 = ((uint16_t*)ftl_buffer)[0x10];
467
    unk1 = ((uint16_t*)ftl_buffer)[0x10];
463
    unk2 = ((uint16_t*)ftl_buffer)[0x11];
468
    unk2 = ((uint16_t*)ftl_buffer)[0x11];
464
    unk3 = ((uint16_t*)ftl_buffer)[((uint32_t*)ftl_buffer)[4] * 0xC + 10]
469
    unk3 = ((uint16_t*)ftl_buffer)[((uint32_t*)ftl_buffer)[4] * 6 + 10]
465
         + ((uint16_t*)ftl_buffer)[((uint32_t*)ftl_buffer)[4] * 0xC + 11];
470
         + ((uint16_t*)ftl_buffer)[((uint32_t*)ftl_buffer)[4] * 6 + 11];
466
    for (i = 0; i < unk1; i++)
471
    for (i = 0; i < unk1; i++)
467
    {
472
    {
468
        for (j = 0; ; j++)
473
        for (j = 0; ; j++)
469
        {
474
        {
470
            page2 = unk2 + i + unk3 * j;
475
            page2 = unk2 + i + unk3 * j;
471
            if (page2 >= (uint32_t)((*ftl_nand_type).pagesperblock - 8))
476
            if (page2 >= (uint32_t)(ftl_nand_type->pagesperblock - 8))
472
                break;
477
                break;
473
            if ((nand_read_page(bank, pagebase + page2, ftl_buffer,
478
            if ((nand_read_page(bank, pagebase + page2, ftl_buffer,
474
                                (void*)0, 1, 0) & 0x11F) == 0)
479
                                (void*)0, 1, 0) & 0x11F) == 0)
475
            {
480
            {
476
                memcpy(bbt, ftl_buffer, 0x410);
481
                memcpy(bbt, ftl_buffer, 0x410);
Line 505... Line 510...
505
    ftl_vfl_calculate_checksum(bank, &checksum1, &checksum2);
510
    ftl_vfl_calculate_checksum(bank, &checksum1, &checksum2);
506
    if (checksum1 == ftl_vfl_cxt[bank].checksum1) return 0;
511
    if (checksum1 == ftl_vfl_cxt[bank].checksum1) return 0;
507
    /* The following line is pretty obviously a bug in Whimory,
512
    /* The following line is pretty obviously a bug in Whimory,
508
       but we do it the same way for compatibility. */
513
       but we do it the same way for compatibility. */
509
    if (checksum2 != ftl_vfl_cxt[bank].checksum2) return 0;
514
    if (checksum2 != ftl_vfl_cxt[bank].checksum2) return 0;
-
 
515
    DEBUGF("FTL: Bad VFL CXT checksum on bank %d!", bank);
510
    return 1;
516
    return 1;
511
}
517
}
512
 
518
 
513
 
519
 
514
#ifndef FTL_READONLY
520
#ifndef FTL_READONLY
Line 529... Line 535...
529
    uint32_t i;
535
    uint32_t i;
530
    ftl_vfl_cxt[bank].updatecount--;
536
    ftl_vfl_cxt[bank].updatecount--;
531
    ftl_vfl_cxt[bank].usn = ++ftl_vfl_usn;
537
    ftl_vfl_cxt[bank].usn = ++ftl_vfl_usn;
532
    ftl_vfl_cxt[bank].nextcxtpage += 8;
538
    ftl_vfl_cxt[bank].nextcxtpage += 8;
533
    ftl_vfl_update_checksum(bank);
539
    ftl_vfl_update_checksum(bank);
534
    memset(&ftl_sparebuffer, 0xFF, 0x40);
540
    memset(&ftl_sparebuffer[0], 0xFF, 0x40);
535
    ftl_sparebuffer.meta.usn = ftl_vfl_cxt[bank].updatecount;
541
    ftl_sparebuffer[0].meta.usn = ftl_vfl_cxt[bank].updatecount;
536
    ftl_sparebuffer.meta.field_8 = 0;
542
    ftl_sparebuffer[0].meta.field_8 = 0;
537
    ftl_sparebuffer.meta.type = 0x80;
543
    ftl_sparebuffer[0].meta.type = 0x80;
538
    for (i = 1; i <= 8; i++)
544
    for (i = 1; i <= 8; i++)
539
    {
545
    {
540
        uint32_t index = ftl_vfl_cxt[bank].activecxtblock;
546
        uint32_t index = ftl_vfl_cxt[bank].activecxtblock;
541
        uint32_t block = ftl_vfl_cxt[bank].vflcxtblocks[index];
547
        uint32_t block = ftl_vfl_cxt[bank].vflcxtblocks[index];
542
        uint32_t page = block * (*ftl_nand_type).pagesperblock;
548
        uint32_t page = block * ftl_nand_type->pagesperblock;
543
        page += ftl_vfl_cxt[bank].nextcxtpage - i;
549
        page += ftl_vfl_cxt[bank].nextcxtpage - i;
544
        nand_write_page(bank, page, &ftl_vfl_cxt[bank], &ftl_sparebuffer, 1);
550
        nand_write_page(bank, page, &ftl_vfl_cxt[bank], &ftl_sparebuffer[0], 1);
545
    }
551
    }
546
    uint32_t good = 0;
552
    uint32_t good = 0;
547
    for (i = 0; i < 8; i++)
553
    for (i = 1; i <= 8; i++)
548
    {
554
    {
549
        uint32_t index = ftl_vfl_cxt[bank].activecxtblock;
555
        uint32_t index = ftl_vfl_cxt[bank].activecxtblock;
550
        uint32_t block = ftl_vfl_cxt[bank].vflcxtblocks[index];
556
        uint32_t block = ftl_vfl_cxt[bank].vflcxtblocks[index];
551
        uint32_t page = block * (*ftl_nand_type).pagesperblock;
557
        uint32_t page = block * ftl_nand_type->pagesperblock;
552
        page += ftl_vfl_cxt[bank].nextcxtpage - i;
558
        page += ftl_vfl_cxt[bank].nextcxtpage - i;
553
        if ((nand_read_page(bank, page, ftl_buffer,
559
        if ((nand_read_page(bank, page, ftl_buffer,
554
                            &ftl_sparebuffer, 1, 0) & 0x11F) != 0)
560
                            &ftl_sparebuffer[0], 1, 0) & 0x11F) != 0)
555
            continue;
561
            continue;
556
        if (memcmp(ftl_buffer, &ftl_vfl_cxt[bank], 0x7AC) != 0)
562
        if (memcmp(ftl_buffer, &ftl_vfl_cxt[bank], 0x7AC) != 0)
557
            continue;
563
            continue;
558
        if (ftl_sparebuffer.meta.usn != ftl_vfl_cxt[bank].updatecount)
564
        if (ftl_sparebuffer[0].meta.usn != ftl_vfl_cxt[bank].updatecount)
559
            continue;
565
            continue;
560
        if (ftl_sparebuffer.meta.field_8 == 0
566
        if (ftl_sparebuffer[0].meta.field_8 == 0
561
         && ftl_sparebuffer.meta.type == 0x80) good++;
567
         && ftl_sparebuffer[0].meta.type == 0x80) good++;
562
    }
568
    }
563
    return good > 3 ? 0 : 1;
569
    return good > 3 ? 0 : 1;
564
}
570
}
565
#endif
571
#endif
566
 
572
 
Line 568... Line 574...
568
#ifndef FTL_READONLY
574
#ifndef FTL_READONLY
569
/* Commits the VFL context of the specified bank to flash,
575
/* Commits the VFL context of the specified bank to flash,
570
   retries until it works or all available pages have been tried */
576
   retries until it works or all available pages have been tried */
571
uint32_t ftl_vfl_commit_cxt(uint32_t bank)
577
uint32_t ftl_vfl_commit_cxt(uint32_t bank)
572
{
578
{
-
 
579
    DEBUGF("FTL: VFL: Committing context on bank %d\n", bank);
573
    if (ftl_vfl_cxt[bank].nextcxtpage + 8 <= (*ftl_nand_type).pagesperblock)
580
    if (ftl_vfl_cxt[bank].nextcxtpage + 8 <= ftl_nand_type->pagesperblock)
574
        if (ftl_vfl_store_cxt(bank) == 0) return 0;
581
        if (ftl_vfl_store_cxt(bank) == 0) return 0;
575
    uint32_t current = ftl_vfl_cxt[bank].activecxtblock;
582
    uint32_t current = ftl_vfl_cxt[bank].activecxtblock;
576
    uint32_t i = current, j;
583
    uint32_t i = current, j;
577
    while (1)
584
    while (1)
578
    {
585
    {
579
        i = (i + 1) & 3;
586
        i = (i + 1) & 3;
580
        if (i == current) break;
587
        if (i == current) break;
581
        if (ftl_vfl_cxt[bank].vflcxtblocks[i] == 0xFFFF) continue;
588
        if (ftl_vfl_cxt[bank].vflcxtblocks[i] == 0xFFFF) continue;
582
        for (j = 0; j < 4; j++)
589
        for (j = 0; j < 4; j++)
583
            if (nand_block_erase(bank, ftl_vfl_cxt[bank].vflcxtblocks[i]
590
            if (nand_block_erase(bank, ftl_vfl_cxt[bank].vflcxtblocks[i]
584
                                     * (*ftl_nand_type).pagesperblock) == 0)
591
                                     * ftl_nand_type->pagesperblock) == 0)
585
                break;
592
                break;
586
        if (j == 4) continue;
593
        if (j == 4) continue;
587
        ftl_vfl_cxt[bank].activecxtblock = i;
594
        ftl_vfl_cxt[bank].activecxtblock = i;
588
        ftl_vfl_cxt[bank].nextcxtpage = 0;
595
        ftl_vfl_cxt[bank].nextcxtpage = 0;
589
        if (ftl_vfl_store_cxt(bank) == 0) return 0;
596
        if (ftl_vfl_store_cxt(bank) == 0) return 0;
590
    }
597
    }
-
 
598
    panicf(PANIC_FATAL, "VFL: Failed to commit VFL CXT!\n");
591
    return 1;
599
    return 1;
592
}
600
}
593
#endif
601
#endif
594
 
602
 
595
 
603
 
Line 647... Line 655...
647
                           union ftl_spare_data_type* sparebuffer)
655
                           union ftl_spare_data_type* sparebuffer)
648
{
656
{
649
    uint32_t i;
657
    uint32_t i;
650
    for (i = 0; i < 8; i++)
658
    for (i = 0; i < 8; i++)
651
    {
659
    {
652
        uint32_t page = block * (*ftl_nand_type).pagesperblock
660
        uint32_t page = block * ftl_nand_type->pagesperblock
653
                      + startpage + i;
661
                      + startpage + i;
654
        if ((nand_read_page(bank, page, databuffer,
662
        if ((nand_read_page(bank, page, databuffer,
655
                            sparebuffer, 1, 1) & 0x11F) == 0)
663
                            sparebuffer, 1, 1) & 0x11F) == 0)
656
            if ((*sparebuffer).meta.field_8 == 0
664
            if (sparebuffer->meta.field_8 == 0
657
             && (*sparebuffer).meta.type == 0x80)
665
             && sparebuffer->meta.type == 0x80)
658
                return 0;
666
                return 0;
659
    }
667
    }
660
    return 1;
668
    return 1;
661
}
669
}
662
 
670
 
Line 668... Line 676...
668
 
676
 
669
    uint32_t spareindex;
677
    uint32_t spareindex;
670
    uint32_t spareused = ftl_vfl_cxt[bank].spareused;
678
    uint32_t spareused = ftl_vfl_cxt[bank].spareused;
671
    for (spareindex = 0; spareindex < spareused; spareindex++)
679
    for (spareindex = 0; spareindex < spareused; spareindex++)
672
        if (ftl_vfl_cxt[bank].remaptable[spareindex] == block)
680
        if (ftl_vfl_cxt[bank].remaptable[spareindex] == block)
-
 
681
		{
-
 
682
            DEBUGF("FTL: VFL: Following remapped block: %d => %d\n",
-
 
683
                   block, ftl_vfl_cxt[bank].firstspare + spareindex);
673
            return ftl_vfl_cxt[bank].firstspare + spareindex;
684
            return ftl_vfl_cxt[bank].firstspare + spareindex;
-
 
685
		}
674
    return block;
686
    return block;
675
}
687
}
676
 
688
 
677
 
689
 
678
#ifndef FTL_READONLY
690
#ifndef FTL_READONLY
Line 690... Line 702...
690
#ifndef FTL_READONLY
702
#ifndef FTL_READONLY
691
/* Schedules remapping for the specified bank and vBlock */
703
/* Schedules remapping for the specified bank and vBlock */
692
void ftl_vfl_schedule_block_for_remap(uint32_t bank, uint32_t block)
704
void ftl_vfl_schedule_block_for_remap(uint32_t bank, uint32_t block)
693
{
705
{
694
    if (ftl_vfl_check_remap_scheduled(bank, block) == 1) return;
706
    if (ftl_vfl_check_remap_scheduled(bank, block) == 1) return;
-
 
707
    panicf(PANIC_FATAL, "FTL: Scheduling bank %u block %u for remap!",
-
 
708
	       (unsigned)bank, (unsigned)block);
695
    if (ftl_vfl_cxt[bank].scheduledstart == ftl_vfl_cxt[bank].spareused)
709
    if (ftl_vfl_cxt[bank].scheduledstart == ftl_vfl_cxt[bank].spareused)
696
        return;
710
        return;
697
    ftl_vfl_cxt[bank].remaptable[--ftl_vfl_cxt[bank].scheduledstart] = block;
711
    ftl_vfl_cxt[bank].remaptable[--ftl_vfl_cxt[bank].scheduledstart] = block;
698
    ftl_vfl_commit_cxt(bank);
712
    ftl_vfl_commit_cxt(bank);
699
}
713
}
Line 775... Line 789...
775
   if not (no more spare blocks available), it will return zero. */
789
   if not (no more spare blocks available), it will return zero. */
776
uint32_t ftl_vfl_remap_block(uint32_t bank, uint32_t block)
790
uint32_t ftl_vfl_remap_block(uint32_t bank, uint32_t block)
777
{
791
{
778
    uint32_t i;
792
    uint32_t i;
779
    uint32_t newblock = 0, newidx;
793
    uint32_t newblock = 0, newidx;
-
 
794
    panicf(PANIC_FATAL, "FTL: Remapping bank %u block %u!",
-
 
795
	       (unsigned)bank, (unsigned)block);
780
    if (bank >= ftl_banks || block >= (*ftl_nand_type).blocks) return 0;
796
    if (bank >= ftl_banks || block >= ftl_nand_type->blocks) return 0;
781
    for (i = 0; i < ftl_vfl_cxt[bank].sparecount; i++)
797
    for (i = 0; i < ftl_vfl_cxt[bank].sparecount; i++)
782
        if (ftl_vfl_cxt[bank].remaptable[i] == 0)
798
        if (ftl_vfl_cxt[bank].remaptable[i] == 0)
783
        {
799
        {
784
            newblock = ftl_vfl_cxt[bank].firstspare + i;
800
            newblock = ftl_vfl_cxt[bank].firstspare + i;
785
            newidx = i;
801
            newidx = i;
786
            break;
802
            break;
787
        }
803
        }
788
    if (newblock == 0) return 0;
804
    if (newblock == 0) return 0;
789
    for (i = 0; i < 9; i++)
805
    for (i = 0; i < 9; i++)
790
        if (nand_block_erase(bank,
806
        if (nand_block_erase(bank,
791
                             newblock * (*ftl_nand_type).pagesperblock) == 0)
807
                             newblock * ftl_nand_type->pagesperblock) == 0)
792
            break;
808
            break;
793
    for (i = 0; i < newidx; i++)
809
    for (i = 0; i < newidx; i++)
794
        if (ftl_vfl_cxt[bank].remaptable[i] == block)
810
        if (ftl_vfl_cxt[bank].remaptable[i] == block)
795
            ftl_vfl_cxt[bank].remaptable[i] = 0xFFFF;
811
            ftl_vfl_cxt[bank].remaptable[i] = 0xFFFF;
796
    ftl_vfl_cxt[bank].remaptable[newidx] = block;
812
    ftl_vfl_cxt[bank].remaptable[newidx] = block;
Line 799... Line 815...
799
    return newblock;
815
    return newblock;
800
}
816
}
801
#endif
817
#endif
802
 
818
 
803
 
819
 
804
// Reads the specified vPage, dealing with all kinds of trouble
820
/* Reads the specified vPage, dealing with all kinds of trouble */
805
uint32_t ftl_vfl_read(uint32_t vpage, void* buffer, void* sparebuffer,
821
uint32_t ftl_vfl_read(uint32_t vpage, void* buffer, void* sparebuffer,
806
                      uint32_t checkempty, uint32_t remaponfail)
822
                      uint32_t checkempty, uint32_t remaponfail)
807
{
823
{
-
 
824
#ifdef VFL_TRACE
-
 
825
    DEBUGF("FTL: VFL: Reading page %d\n", vpage);
-
 
826
#endif
-
 
827
 
808
    uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
828
    uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks;
809
    uint32_t syshyperblocks = (*ftl_nand_type).blocks
829
    uint32_t syshyperblocks = ftl_nand_type->blocks
810
                            - (*ftl_nand_type).userblocks - 0x17;
830
                            - ftl_nand_type->userblocks - 0x17;
811
    uint32_t abspage = vpage + ppb * syshyperblocks;
831
    uint32_t abspage = vpage + ppb * syshyperblocks;
812
    if (abspage >= (*ftl_nand_type).blocks * ppb || abspage < ppb)
832
    if (abspage >= ftl_nand_type->blocks * ppb || abspage < ppb)
813
    {
833
    {
-
 
834
        DEBUG("FTL: Trying to read out-of-bounds vPage %u", (unsigned)vpage);
814
        return 4;
835
        return 4;
815
    }
836
    }
816
 
837
 
817
    uint32_t bank = abspage % ftl_banks;
838
    uint32_t bank = abspage % ftl_banks;
818
    uint32_t block = abspage / ((*ftl_nand_type).pagesperblock * ftl_banks);
839
    uint32_t block = abspage / (ftl_nand_type->pagesperblock * ftl_banks);
819
    uint32_t page = (abspage / ftl_banks) % (*ftl_nand_type).pagesperblock;
840
    uint32_t page = (abspage / ftl_banks) % ftl_nand_type->pagesperblock;
820
    uint32_t physblock = ftl_vfl_get_physical_block(bank, block);
841
    uint32_t physblock = ftl_vfl_get_physical_block(bank, block);
821
    uint32_t physpage = physblock * (*ftl_nand_type).pagesperblock + page;
842
    uint32_t physpage = physblock * ftl_nand_type->pagesperblock + page;
822
 
843
 
823
    uint32_t ret = nand_read_page(bank, physpage, buffer,
844
    uint32_t ret = nand_read_page(bank, physpage, buffer,
824
                                  sparebuffer, 1, checkempty);
845
                                  sparebuffer, 1, checkempty);
825
 
846
 
826
    if ((ret & 0x11D) != 0 && (ret & 2) == 0)
847
    if ((ret & 0x11D) != 0 && (ret & 2) == 0)
Line 831... Line 852...
831
#ifdef FTL_READONLY
852
#ifdef FTL_READONLY
832
        (void)remaponfail;
853
        (void)remaponfail;
833
#else
854
#else
834
        if (remaponfail == 1 &&(ret & 0x11D) != 0 && (ret & 2) == 0)
855
        if (remaponfail == 1 &&(ret & 0x11D) != 0 && (ret & 2) == 0)
835
        {
856
        {
-
 
857
            DEBUGF("FTL: VFL: Scheduling vBlock %d for remapping!\n", block);
836
            ftl_vfl_schedule_block_for_remap(bank, block);
858
            ftl_vfl_schedule_block_for_remap(bank, block);
837
        }
859
        }
838
#endif
860
#endif
839
        return ret;
861
        return ret;
840
    }
862
    }
841
 
863
 
842
    return ret;
864
    return ret;
843
}
865
}
844
 
866
 
845
 
867
 
-
 
868
/* Multi-bank version of ftl_vfl_read, will read ftl_banks pages in parallel */
-
 
869
uint32_t ftl_vfl_read_fast(uint32_t vpage, void* buffer, void* sparebuffer,
-
 
870
                           uint32_t checkempty, uint32_t remaponfail)
-
 
871
{
-
 
872
#ifdef VFL_TRACE
-
 
873
    DEBUGF("FTL: VFL: Fast reading page %d on all banks\n", vpage);
-
 
874
#endif
-
 
875
 
-
 
876
    uint32_t i, rc = 0;
-
 
877
    uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks;
-
 
878
    uint32_t syshyperblocks = ftl_nand_type->blocks
-
 
879
                            - ftl_nand_type->userblocks - 0x17;
-
 
880
    uint32_t abspage = vpage + ppb * syshyperblocks;
-
 
881
    if (abspage + ftl_banks - 1 >= ftl_nand_type->blocks * ppb || abspage < ppb)
-
 
882
	{
-
 
883
        DEBUGF("FTL: Trying to read out-of-bounds vPage %u", (unsigned)vpage);
-
 
884
        return 4;
-
 
885
	}
-
 
886
 
-
 
887
    uint32_t bank = abspage % ftl_banks;
-
 
888
    uint32_t block = abspage / (ftl_nand_type->pagesperblock * ftl_banks);
-
 
889
    uint32_t page = (abspage / ftl_banks) % ftl_nand_type->pagesperblock;
-
 
890
    uint32_t remapped = 0;
-
 
891
    for (i = 0; i < ftl_banks; i++)
-
 
892
        if (ftl_vfl_get_physical_block(i, block) != block)
-
 
893
            remapped = 1;
-
 
894
    if (bank || remapped)
-
 
895
    {
-
 
896
        for (i = 0; i < ftl_banks; i++)
-
 
897
        {
-
 
898
            void* databuf = (void*)0;
-
 
899
            void* sparebuf = (void*)0;
-
 
900
            if (buffer) databuf = (void*)((uint32_t)buffer + 0x800 * i);
-
 
901
            if (sparebuffer) sparebuf = (void*)((uint32_t)sparebuffer + 0x40 * i);
-
 
902
            uint32_t ret = ftl_vfl_read(vpage + i, databuf, sparebuf, checkempty, remaponfail);
-
 
903
            if (ret & 1) rc |= 1 << (i << 2);
-
 
904
            if (ret & 2) rc |= 2 << (i << 2);
-
 
905
            if (ret & 0x10) rc |= 4 << (i << 2);
-
 
906
            if (ret & 0x100) rc |= 8 << (i << 2);
-
 
907
        }
-
 
908
        return rc;
-
 
909
    }
-
 
910
    uint32_t physpage = block * ftl_nand_type->pagesperblock + page;
-
 
911
 
-
 
912
    rc = nand_read_page_fast(physpage, buffer, sparebuffer, 1, checkempty);
-
 
913
    if (!(rc & 0xdddd)) return rc;
-
 
914
 
-
 
915
    for (i = 0; i < ftl_banks; i++)
-
 
916
    {
-
 
917
        if ((rc >> (i << 2)) & 0x2) continue;
-
 
918
        if ((rc >> (i << 2)) & 0xd)
-
 
919
        {
-
 
920
            rc &= ~(0xf << (i << 2));
-
 
921
            nand_reset(i);
-
 
922
            uint32_t ret = nand_read_page(i, physpage,
-
 
923
                                          (void*)((uint32_t)buffer + 0x800 * i),
-
 
924
                                          (void*)((uint32_t)sparebuffer + 0x40 * i),
-
 
925
                                          1, checkempty);
-
 
926
#ifdef FTL_READONLY
-
 
927
            (void)remaponfail;
-
 
928
#else
-
 
929
            if (remaponfail == 1 && (ret & 0x11D) != 0 && (ret & 2) == 0)
-
 
930
                ftl_vfl_schedule_block_for_remap(i, block);
-
 
931
#endif
-
 
932
            if (ret & 1) rc |= 1 << (i << 2);
-
 
933
            if (ret & 2) rc |= 2 << (i << 2);
-
 
934
            if (ret & 0x10) rc |= 4 << (i << 2);
-
 
935
            if (ret & 0x100) rc |= 8 << (i << 2);
-
 
936
        }
-
 
937
    }
-
 
938
 
-
 
939
    return rc;
-
 
940
}
-
 
941
 
-
 
942
 
846
#ifndef FTL_READONLY
943
#ifndef FTL_READONLY
847
/* Writes the specified vPage, dealing with all kinds of trouble */
944
/* Writes the specified vPage, dealing with all kinds of trouble */
848
uint32_t ftl_vfl_write(uint32_t vpage, void* buffer, void* sparebuffer)
945
uint32_t ftl_vfl_write(uint32_t vpage, uint32_t count,
-
 
946
                       void* buffer, void* sparebuffer)
849
{
947
{
-
 
948
    uint32_t i, j;
-
 
949
#ifdef VFL_TRACE
-
 
950
    DEBUGF("FTL: VFL: Writing page %d\n", vpage);
-
 
951
#endif
-
 
952
 
850
    uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
953
    uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks;
851
    uint32_t syshyperblocks = (*ftl_nand_type).blocks
954
    uint32_t syshyperblocks = ftl_nand_type->blocks
852
                            - (*ftl_nand_type).userblocks - 0x17;
955
                            - ftl_nand_type->userblocks - 0x17;
853
    uint32_t abspage = vpage + ppb * syshyperblocks;
956
    uint32_t abspage = vpage + ppb * syshyperblocks;
854
    if (abspage >= (*ftl_nand_type).blocks * ppb || abspage < ppb)
957
    if (abspage + count > ftl_nand_type->blocks * ppb || abspage < ppb)
855
    {
958
	{
-
 
959
        DEBUGF("FTL: Trying to write out-of-bounds vPage %u",
-
 
960
               (unsigned)vpage);
856
        return 4;
961
        return 4;
-
 
962
	}
-
 
963
 
-
 
964
    uint32_t bank[5];
-
 
965
    uint32_t block[5];
-
 
966
    uint32_t physpage[5];
-
 
967
 
-
 
968
    for (i = 0; i < count; i++, abspage++)
-
 
969
    {
-
 
970
        for (j = ftl_banks; j > 0; j--)
-
 
971
        {
-
 
972
            bank[j] = bank[j - 1];
-
 
973
            block[j] = block[j - 1];
-
 
974
            physpage[j] = physpage[j - 1];
-
 
975
        }
-
 
976
        bank[0] = abspage % ftl_banks;
-
 
977
        block[0] = abspage / (ftl_nand_type->pagesperblock * ftl_banks);
-
 
978
        uint32_t page = (abspage / ftl_banks) % ftl_nand_type->pagesperblock;
-
 
979
        uint32_t physblock = ftl_vfl_get_physical_block(bank[0], block[0]);
-
 
980
        physpage[0] = physblock * ftl_nand_type->pagesperblock + page;
-
 
981
 
-
 
982
        if (i >= ftl_banks)
-
 
983
            if (nand_write_page_collect(bank[ftl_banks]))
-
 
984
                if (nand_read_page(bank[ftl_banks], physpage[ftl_banks],
-
 
985
                                   ftl_buffer, &ftl_sparebuffer[0], 1, 1) & 0x11F)
-
 
986
                {
-
 
987
                    panicf(PANIC_FATAL, "FTL: write error (2) on vPage %u, bank %u, pPage %u",
-
 
988
                           (unsigned)(vpage + i - ftl_banks),
-
 
989
                           (unsigned)bank[ftl_banks],
-
 
990
                           (unsigned)physpage[ftl_banks]);
-
 
991
                    ftl_vfl_log_trouble(bank[ftl_banks], block[ftl_banks]);
-
 
992
                }
-
 
993
        if (nand_write_page_start(bank[0], physpage[0],
-
 
994
                                  (void*)((uint32_t)buffer + 0x800 * i),
-
 
995
                                  (void*)((uint32_t)sparebuffer + 0x40 * i), 1))
-
 
996
            if (nand_read_page(bank[0], physpage[0], ftl_buffer,
-
 
997
                               &ftl_sparebuffer[0], 1, 1) & 0x11F)
-
 
998
            {
-
 
999
                panicf(PANIC_FATAL, "FTL: write error (1) on vPage %u, bank %u, pPage %u",
-
 
1000
                       (unsigned)(vpage + i), (unsigned)bank[0], (unsigned)physpage[0]);
-
 
1001
                ftl_vfl_log_trouble(bank[0], block[0]);
-
 
1002
            }
857
    }
1003
    }
858
 
1004
 
859
    uint32_t bank = abspage % ftl_banks;
1005
    for (i = count < ftl_banks ? count : ftl_banks; i > 0; i--)
860
    uint32_t block = abspage / ((*ftl_nand_type).pagesperblock * ftl_banks);
1006
        if (nand_write_page_collect(bank[i - 1]))
-
 
1007
            if (nand_read_page(bank[i - 1], physpage[i - 1],
861
    uint32_t page = (abspage / ftl_banks) % (*ftl_nand_type).pagesperblock;
1008
                               ftl_buffer, &ftl_sparebuffer[0], 1, 1) & 0x11F)
-
 
1009
            {
-
 
1010
                panicf(PANIC_FATAL, "FTL: write error (2) on vPage %u, bank %u, pPage %u",
862
    uint32_t physblock = ftl_vfl_get_physical_block(bank, block);
1011
                       (unsigned)(vpage + count - i),
863
    uint32_t physpage = physblock * (*ftl_nand_type).pagesperblock + page;
1012
                       (unsigned)bank[i - 1], (unsigned)physpage[i - 1]);
-
 
1013
                ftl_vfl_log_trouble(bank[i - 1], block[i - 1]);
-
 
1014
            }
864
 
1015
 
865
    if (nand_write_page(bank, physpage, buffer, sparebuffer, 1) == 0)
-
 
866
        return 0;
-
 
867
    if ((nand_read_page(bank, physpage, ftl_buffer,
-
 
868
                        &ftl_sparebuffer, 1, 1) & 0x11F) == 0)
-
 
869
        return 0;
-
 
870
    ftl_vfl_log_trouble(bank, block);
-
 
871
    return 1;
1016
    return 0;
872
}
1017
}
873
#endif
1018
#endif
874
 
1019
 
875
 
1020
 
876
/* Mounts the VFL on all banks */
1021
/* Mounts the VFL on all banks */
Line 886... Line 1031...
886
    /* Temporary BBT buffer if we're readonly,
1031
    /* Temporary BBT buffer if we're readonly,
887
       as we won't need it again after mounting */
1032
       as we won't need it again after mounting */
888
    uint8_t bbt[0x410];
1033
    uint8_t bbt[0x410];
889
#endif
1034
#endif
890
 
1035
 
891
    uint32_t syshyperblocks = (*ftl_nand_type).blocks
1036
    uint32_t syshyperblocks = ftl_nand_type->blocks
892
                            - (*ftl_nand_type).userblocks - 0x18;
1037
                            - ftl_nand_type->userblocks - 0x18;
893
 
1038
 
894
    for (i = 0; i < ftl_banks; i++)
1039
    for (i = 0; i < ftl_banks; i++)
895
#ifndef FTL_READONLY
1040
#ifndef FTL_READONLY
896
        if (ftl_load_bbt(i, ftl_bbt[i]) == 0)
1041
        if (ftl_load_bbt(i, ftl_bbt[i]) == 0)
897
#else
1042
#else
Line 903... Line 1048...
903
                if (ftl_is_good_block(ftl_bbt[i], j) != 0)
1048
                if (ftl_is_good_block(ftl_bbt[i], j) != 0)
904
#else
1049
#else
905
                if (ftl_is_good_block(bbt, j) != 0)
1050
                if (ftl_is_good_block(bbt, j) != 0)
906
#endif
1051
#endif
907
                    if (ftl_vfl_read_page(i, j, 0, ftl_buffer,
1052
                    if (ftl_vfl_read_page(i, j, 0, ftl_buffer,
908
                                          &ftl_sparebuffer) == 0)
1053
                                          &ftl_sparebuffer[0]) == 0)
909
                    {
1054
                    {
910
                        struct ftl_vfl_cxt_type* cxt;
1055
                        struct ftl_vfl_cxt_type* cxt;
911
                        cxt = (struct ftl_vfl_cxt_type*)ftl_buffer;
1056
                        cxt = (struct ftl_vfl_cxt_type*)ftl_buffer;
912
                        memcpy(vflcxtblock, &(*cxt).vflcxtblocks, 8);
1057
                        memcpy(vflcxtblock, &cxt->vflcxtblocks, 8);
913
                        minusn = 0xFFFFFFFF;
1058
                        minusn = 0xFFFFFFFF;
914
                        vflcxtidx = 4;
1059
                        vflcxtidx = 4;
915
                        for (k = 0; k < 4; k++)
1060
                        for (k = 0; k < 4; k++)
916
                            if (vflcxtblock[k] != 0xFFFF)
1061
                            if (vflcxtblock[k] != 0xFFFF)
917
                                if (ftl_vfl_read_page(i, vflcxtblock[k], 0,
1062
                                if (ftl_vfl_read_page(i, vflcxtblock[k], 0,
918
                                                      ftl_buffer,
1063
                                                      ftl_buffer,
919
                                                      &ftl_sparebuffer) == 0)
1064
                                                      &ftl_sparebuffer[0]) == 0)
920
                                    if (ftl_sparebuffer.meta.usn > 0
1065
                                    if (ftl_sparebuffer[0].meta.usn > 0
921
                                     && ftl_sparebuffer.meta.usn <= minusn)
1066
                                     && ftl_sparebuffer[0].meta.usn <= minusn)
922
                                    {
1067
                                    {
923
                                        minusn = ftl_sparebuffer.meta.usn;
1068
                                        minusn = ftl_sparebuffer[0].meta.usn;
924
                                        vflcxtidx = k;
1069
                                        vflcxtidx = k;
925
                                    }
1070
                                    }
926
                        if (vflcxtidx == 4) return 1;
1071
                        if (vflcxtidx == 4)
-
 
1072
						{
-
 
1073
                            DEBUGF("FTL: No VFL CXT block found on bank %u!",
-
 
1074
                                   (unsigned)i);
-
 
1075
						    return 1;
-
 
1076
						}
927
                        last = 0;
1077
                        last = 0;
928
                        uint32_t max = (*ftl_nand_type).pagesperblock;
1078
                        uint32_t max = ftl_nand_type->pagesperblock;
929
                        for (k = 8; k < max; k += 8)
1079
                        for (k = 8; k < max; k += 8)
930
                        {
1080
                        {
931
                            if (ftl_vfl_read_page(i, vflcxtblock[vflcxtidx],
1081
                            if (ftl_vfl_read_page(i, vflcxtblock[vflcxtidx],
932
                                                  k, ftl_buffer,
1082
                                                  k, ftl_buffer,
933
                                                  &ftl_sparebuffer) != 0)
1083
                                                  &ftl_sparebuffer[0]) != 0)
934
                                break;
1084
                                break;
935
                            last = k;
1085
                            last = k;
936
                        }
1086
                        }
937
                        if (ftl_vfl_read_page(i, vflcxtblock[vflcxtidx],
1087
                        if (ftl_vfl_read_page(i, vflcxtblock[vflcxtidx],
938
                                              last, ftl_buffer,
1088
                                              last, ftl_buffer,
939
                                              &ftl_sparebuffer) != 0)
1089
                                              &ftl_sparebuffer[0]) != 0)
-
 
1090
                            panicf(PANIC_FATAL, "FTL: Re-reading VFL CXT block "
-
 
1091
                                        "on bank %u failed!?", (unsigned)i);
940
                            return 1;
1092
                            //return 1;
941
                        memcpy(&ftl_vfl_cxt[i], ftl_buffer, 0x800);
1093
                        memcpy(&ftl_vfl_cxt[i], ftl_buffer, 0x800);
942
                        if (ftl_vfl_verify_checksum(i) != 0) return 1;
1094
                        if (ftl_vfl_verify_checksum(i) != 0) return 1;
943
#ifndef FTL_READONLY
1095
#ifndef FTL_READONLY
944
                        if (ftl_vfl_usn < ftl_vfl_cxt[i].usn)
1096
                        if (ftl_vfl_usn < ftl_vfl_cxt[i].usn)
945
                            ftl_vfl_usn = ftl_vfl_cxt[i].usn;
1097
                            ftl_vfl_usn = ftl_vfl_cxt[i].usn;
Line 947... Line 1099...
947
                        break;
1099
                        break;
948
                    }
1100
                    }
949
        }
1101
        }
950
        else
1102
        else
951
		{
1103
		{
-
 
1104
            DEBUGF("FTL: Couldn't load bank %u lowlevel BBT!", (unsigned)i);
952
		    return 1;
1105
		    return 1;
953
		}
1106
		}
954
    cxt = ftl_vfl_get_newest_cxt();
1107
    cxt = ftl_vfl_get_newest_cxt();
955
    for (i = 0; i < ftl_banks; i++)
1108
    for (i = 0; i < ftl_banks; i++)
956
        memcpy(ftl_vfl_cxt[i].ftlctrlblocks, (*cxt).ftlctrlblocks, 6);
1109
        memcpy(ftl_vfl_cxt[i].ftlctrlblocks, cxt->ftlctrlblocks, 6);
957
    return 0;
1110
    return 0;
958
}
1111
}
959
 
1112
 
960
 
1113
 
961
/* Mounts the actual FTL */
1114
/* Mounts the actual FTL */
962
uint32_t ftl_open(void)
1115
uint32_t ftl_open(void)
963
{
1116
{
964
    uint32_t i;
1117
    uint32_t i;
965
    uint32_t ret;
1118
    uint32_t ret;
966
    uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
1119
    uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks;
967
    struct ftl_vfl_cxt_type* cxt = ftl_vfl_get_newest_cxt();
1120
    struct ftl_vfl_cxt_type* cxt = ftl_vfl_get_newest_cxt();
968
 
1121
 
969
    uint32_t ftlcxtblock = 0xffffffff;
1122
    uint32_t ftlcxtblock = 0xffffffff;
970
    uint32_t minlpn = 0xffffffff;
1123
    uint32_t minusn = 0xffffffff;
971
    for (i = 0; i < 3; i++)
1124
    for (i = 0; i < 3; i++)
972
    {
1125
    {
973
        ret = ftl_vfl_read(ppb * (*cxt).ftlctrlblocks[i],
1126
        ret = ftl_vfl_read(ppb * cxt->ftlctrlblocks[i],
974
                           ftl_buffer, &ftl_sparebuffer, 1, 0);
1127
                           ftl_buffer, &ftl_sparebuffer[0], 1, 0);
975
        if ((ret &= 0x11F) != 0) continue;
1128
        if ((ret &= 0x11F) != 0) continue;
976
        if (ftl_sparebuffer.user.type - 0x43 > 4) continue;
1129
        if (ftl_sparebuffer[0].meta.type - 0x43 > 4) continue;
977
        if (ftlcxtblock != 0xffffffff && ftl_sparebuffer.user.lpn >= minlpn)
1130
        if (ftlcxtblock != 0xffffffff && ftl_sparebuffer[0].meta.usn >= minusn)
978
            continue;
1131
            continue;
979
        minlpn = ftl_sparebuffer.user.lpn;
1132
        minusn = ftl_sparebuffer[0].meta.usn;
980
        ftlcxtblock = (*cxt).ftlctrlblocks[i];
1133
        ftlcxtblock = cxt->ftlctrlblocks[i];
981
    }
1134
    }
982
 
1135
 
983
    if (ftlcxtblock == 0xffffffff) return 1;
1136
    if (ftlcxtblock == 0xffffffff)
-
 
1137
    {
-
 
1138
        DEBUGF("FTL: Couldn't find readable FTL CXT block!");
-
 
1139
        return 1;
-
 
1140
    }
984
 
1141
 
-
 
1142
    DEBUGF("FTL: Found FTL context block: vBlock %d\n", ftlcxtblock);
985
    uint32_t ftlcxtfound = 0;
1143
    uint32_t ftlcxtfound = 0;
986
    for (i = (*ftl_nand_type).pagesperblock * ftl_banks - 1; i > 0; i--)
1144
    for (i = ftl_nand_type->pagesperblock * ftl_banks - 1; i > 0; i--)
987
    {
1145
    {
988
        ret = ftl_vfl_read(ppb * ftlcxtblock + i,
1146
        ret = ftl_vfl_read(ppb * ftlcxtblock + i,
989
                           ftl_buffer, &ftl_sparebuffer, 1, 0);
1147
                           ftl_buffer, &ftl_sparebuffer[0], 1, 0);
990
        if ((ret & 0x11F) != 0) continue;
1148
        if ((ret & 0x11F) != 0) continue;
991
        else if (ftl_sparebuffer.user.type == 0x43)
1149
        else if (ftl_sparebuffer[0].meta.type == 0x43)
992
        {
1150
        {
993
            memcpy(&ftl_cxt, ftl_buffer, 0x28C);
1151
            memcpy(&ftl_cxt, ftl_buffer, 0x28C);
994
            ftlcxtfound = 1;
1152
            ftlcxtfound = 1;
995
            break;
1153
            break;
996
        }
1154
        }
997
        else
1155
        else
998
        {
1156
        {
999
            // This will trip if there was an unclean unmount before.
1157
            /* This will trip if there was an unclean unmount before. */
-
 
1158
            DEBUGF("FTL: Unclean shutdown before!\n");
1000
#ifndef FTL_FORCEMOUNT
1159
#ifdef FTL_FORCEMOUNT
-
 
1160
            DEBUGF("FTL: Forcing mount nevertheless...\n");
-
 
1161
#else
1001
            break;
1162
            break;
1002
#endif
1163
#endif
1003
        }
1164
        }
1004
    }
1165
    }
1005
 
1166
 
1006
    if (ftlcxtfound == 0) return 1;
1167
    if (ftlcxtfound == 0)
-
 
1168
	{
-
 
1169
        DEBUGF("FTL: Couldn't find FTL CXT page!");
-
 
1170
	    return 1;
-
 
1171
	}
1007
 
1172
 
-
 
1173
    DEBUGF("FTL: Successfully read FTL context block\n");
1008
    uint32_t pagestoread = (*ftl_nand_type).userblocks >> 10;
1174
    uint32_t pagestoread = ftl_nand_type->userblocks >> 10;
1009
    if (((*ftl_nand_type).userblocks & 0x1FF) != 0) pagestoread++;
1175
    if ((ftl_nand_type->userblocks & 0x1FF) != 0) pagestoread++;
1010
 
1176
 
1011
    for (i = 0; i < pagestoread; i++)
1177
    for (i = 0; i < pagestoread; i++)
1012
    {
1178
    {
1013
        if ((ftl_vfl_read(ftl_cxt.ftl_map_pages[i],
1179
        if ((ftl_vfl_read(ftl_cxt.ftl_map_pages[i],
1014
                          ftl_buffer, &ftl_sparebuffer, 1, 1) & 0x11F) != 0)
1180
                          ftl_buffer, &ftl_sparebuffer[0], 1, 1) & 0x11F) != 0)
-
 
1181
		{
-
 
1182
            DEBUGF("FTL: Failed to read block map page %u", (unsigned)i);
1015
            return 1;
1183
            return 1;
-
 
1184
		}
1016
 
1185
 
1017
        uint32_t toread = 2048;
1186
        uint32_t toread = 2048;
1018
        if (toread > ((*ftl_nand_type).userblocks << 1) - (i << 11))
1187
        if (toread > (ftl_nand_type->userblocks << 1) - (i << 11))
1019
            toread = ((*ftl_nand_type).userblocks << 1) - (i << 11);
1188
            toread = (ftl_nand_type->userblocks << 1) - (i << 11);
1020
 
1189
 
1021
        memcpy(&ftl_map[i << 10], ftl_buffer, toread);
1190
        memcpy(&ftl_map[i << 10], ftl_buffer, toread);
1022
    }
1191
    }
1023
 
1192
 
1024
#ifndef FTL_READONLY
1193
#ifndef FTL_READONLY
1025
    pagestoread = ((*ftl_nand_type).userblocks + 23) >> 10;
1194
    pagestoread = (ftl_nand_type->userblocks + 23) >> 10;
1026
    if ((((*ftl_nand_type).userblocks + 23) & 0x1FF) != 0) pagestoread++;
1195
    if (((ftl_nand_type->userblocks + 23) & 0x1FF) != 0) pagestoread++;
1027
 
1196
 
1028
    for (i = 0; i < pagestoread; i++)
1197
    for (i = 0; i < pagestoread; i++)
1029
    {
1198
    {
1030
        if ((ftl_vfl_read(ftl_cxt.ftl_erasectr_pages[i],
1199
        if ((ftl_vfl_read(ftl_cxt.ftl_erasectr_pages[i],
1031
                          ftl_buffer, &ftl_sparebuffer, 1, 1) & 0x11F) != 0)
1200
                          ftl_buffer, &ftl_sparebuffer[0], 1, 1) & 0x11F) != 0)
-
 
1201
		{
-
 
1202
            DEBUGF("FTL: Failed to read erase counter page %u", (unsigned)i);
1032
            return 1;
1203
            return 1;
-
 
1204
		}
1033
 
1205
 
1034
        uint32_t toread = 2048;
1206
        uint32_t toread = 2048;
1035
        if (toread > (((*ftl_nand_type).userblocks + 23) << 1) - (i << 11))
1207
        if (toread > ((ftl_nand_type->userblocks + 23) << 1) - (i << 11))
1036
            toread = (((*ftl_nand_type).userblocks + 23) << 1) - (i << 11);
1208
            toread = ((ftl_nand_type->userblocks + 23) << 1) - (i << 11);
1037
 
1209
 
1038
        memcpy(&ftl_erasectr[i << 10], ftl_buffer, toread);
1210
        memcpy(&ftl_erasectr[i << 10], ftl_buffer, toread);
1039
    }
1211
    }
1040
 
1212
 
1041
    for (i = 0; i < 0x11; i++)
1213
    for (i = 0; i < 0x11; i++)
Line 1047... Line 1219...
1047
 
1219
 
1048
    memset(ftl_troublelog, 0xFF, 20);
1220
    memset(ftl_troublelog, 0xFF, 20);
1049
    memset(ftl_erasectr_dirt, 0, 8);
1221
    memset(ftl_erasectr_dirt, 0, 8);
1050
#endif
1222
#endif
1051
 
1223
 
-
 
1224
#ifdef FTL_DEBUG
-
 
1225
    uint32_t j, k;
-
 
1226
    for (i = 0; i < ftl_banks; i++)
-
 
1227
    {
-
 
1228
        uint32_t badblocks = 0;
-
 
1229
#ifndef FTL_READONLY
-
 
1230
        for (j = 0; j < (*ftl_nand_type).blocks >> 3; j++)
-
 
1231
        {
-
 
1232
            uint8_t bbtentry = ftl_bbt[i][j];
-
 
1233
            for (k = 0; k < 8; k++) if ((bbtentry & (1 << k)) == 0) badblocks++;
-
 
1234
        }
-
 
1235
        DEBUGF("FTL: BBT for bank %d: %d bad blocks\n", i, badblocks);
-
 
1236
        badblocks = 0;
-
 
1237
#endif
-
 
1238
        for (j = 0; j < ftl_vfl_cxt[i].sparecount; j++)
-
 
1239
            if (ftl_vfl_cxt[i].remaptable[j] == 0xFFFF) badblocks++;
-
 
1240
        DEBUGF("FTL: VFL: Bank %d: %d of %d spare blocks are bad\n",
-
 
1241
               i, badblocks, ftl_vfl_cxt[i].sparecount);
-
 
1242
        DEBUGF("FTL: VFL: Bank %d: %d blocks remapped\n",
-
 
1243
               i, ftl_vfl_cxt[i].spareused);
-
 
1244
        DEBUGF("FTL: VFL: Bank %d: %d blocks scheduled for remapping\n",
-
 
1245
               i, 0x334 - ftl_vfl_cxt[i].scheduledstart);
-
 
1246
    }
-
 
1247
#ifndef FTL_READONLY
-
 
1248
    uint32_t min = 0xFFFFFFFF, max = 0, total = 0;
-
 
1249
    for (i = 0; i < (*ftl_nand_type).userBlocks + 23; i++)
-
 
1250
    {
-
 
1251
        if (ftl_erasectr[i] > max) max = ftl_erasectr[i];
-
 
1252
        if (ftl_erasectr[i] < min) min = ftl_erasectr[i];
-
 
1253
        total += ftl_erasectr[i];
-
 
1254
    }
-
 
1255
    DEBUGF("FTL: Erase counters: Minimum: %d, maximum %d, average: %d, total: %d\n",
-
 
1256
           min, max, total / ((*ftl_nand_type).userBlocks + 23), total);
-
 
1257
#endif
-
 
1258
#endif
-
 
1259
 
1052
    return 0;
1260
    return 0;
1053
}
1261
}
1054
 
1262
 
1055
 
1263
 
1056
#ifndef FTL_READONLY
1264
#ifndef FTL_READONLY
Line 1067... Line 1275...
1067
    return (struct ftl_log_type*)0;
1275
    return (struct ftl_log_type*)0;
1068
}
1276
}
1069
#endif
1277
#endif
1070
 
1278
 
1071
/* Exposed function: Read highlevel sectors */
1279
/* Exposed function: Read highlevel sectors */
1072
uint32_t storage_read(uint32_t sector, uint32_t count, void* buffer)
1280
uint32_t ftl_read(uint32_t sector, uint32_t count, void* buffer)
1073
{
1281
{
1074
    uint32_t i;
1282
    uint32_t i, j;
1075
    uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
1283
    uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks;
1076
    uint32_t error = 0;
1284
    uint32_t error = 0;
1077
 
1285
 
-
 
1286
#ifdef FTL_TRACE
-
 
1287
    DEBUGF("FTL: Reading %d sectors starting at %d\n", count, sector);
-
 
1288
#endif
-
 
1289
 
1078
    if (sector + count > (*ftl_nand_type).userblocks * ppb)
1290
    if (sector + count > ftl_nand_type->userblocks * ppb)
-
 
1291
    {
-
 
1292
        DEBUGF("FTL: Sector %d is out of range!\n", sector + count - 1);
1079
        return 1;
1293
        return 1;
-
 
1294
    }
1080
    if (count == 0) return 0;
1295
    if (count == 0) return 0;
1081
 
1296
 
-
 
1297
    mutex_lock(&ftl_mtx, TIMEOUT_BLOCK);
-
 
1298
 
1082
    for (i = 0; i < count; i++)
1299
    for (i = 0; i < count; i++)
1083
    {
1300
    {
1084
        uint32_t block = (sector + i) / ppb;
1301
        uint32_t block = (sector + i) / ppb;
1085
        uint32_t page = (sector + i) % ppb;
1302
        uint32_t page = (sector + i) % ppb;
1086
 
1303
 
1087
        uint32_t abspage = ftl_map[block] * ppb + page;
1304
        uint32_t abspage = ftl_map[block] * ppb + page;
1088
#ifndef FTL_READONLY
1305
#ifndef FTL_READONLY
1089
        struct ftl_log_type* logentry = ftl_get_log_entry(block);
1306
        struct ftl_log_type* logentry = ftl_get_log_entry(block);
1090
        if (logentry != (struct ftl_log_type*)0)
1307
        if (logentry != (struct ftl_log_type*)0)
1091
        {
1308
        {
-
 
1309
#ifdef FTL_TRACE
-
 
1310
	        DEBUGF("FTL: Block %d has a log entry\n", block);
-
 
1311
#endif
1092
            if ((*logentry).scatteredvblock != 0xFFFF
1312
            if (logentry->scatteredvblock != 0xFFFF
1093
             && (*logentry).pageoffsets[page] != 0xFFFF)
1313
             && logentry->pageoffsets[page] != 0xFFFF)
1094
            {
1314
            {
-
 
1315
#ifdef FTL_TRACE
-
 
1316
   		     DEBUGF("FTL: Found page %d at block %d, page %d\n", page,
-
 
1317
          		    (*logentry).scatteredvblock, (*logentry).pageoffsets[page]);
-
 
1318
#endif
1095
                abspage = (*logentry).scatteredvblock * ppb
1319
                abspage = logentry->scatteredvblock * ppb
1096
                        + (*logentry).pageoffsets[page];
1320
                        + logentry->pageoffsets[page];
1097
            }
1321
            }
1098
        }
1322
        }
1099
#endif
1323
#endif
1100
 
1324
 
1101
        uint32_t ret = ftl_vfl_read(abspage, &((uint8_t*)buffer)[i << 11],
1325
#ifndef FTL_READONLY
1102
                                    &ftl_sparebuffer, 1, 1);
1326
        if (count >= i + ftl_banks && !(page & (ftl_banks - 1))
1103
        if ((ret & 2) != 0) memset(&((uint8_t*)buffer)[i << 11], 0, 0x800);
1327
         && logentry == (struct ftl_log_type*)0)
-
 
1328
#else
1104
        else if ((ret & 0x11D) != 0 || ftl_sparebuffer.user.eccmark != 0xFF)
1329
        if (count >= i + ftl_banks && !(page & (ftl_banks - 1)))
-
 
1330
#endif
1105
        {
1331
        {
-
 
1332
            uint32_t ret = ftl_vfl_read_fast(abspage, &((uint8_t*)buffer)[i << 11],
-
 
1333
                                             &ftl_sparebuffer[0], 1, 1);
-
 
1334
            for (j = 0; j < ftl_banks; j++)
-
 
1335
                if (ret & (2 << (j << 2)))
-
 
1336
                    memset(&((uint8_t*)buffer)[(i + j) << 11], 0, 0x800);
-
 
1337
                else if ((ret & (0xd << (j << 2))) || ftl_sparebuffer[j].user.eccmark != 0xFF)
-
 
1338
                {
-
 
1339
		            DEBUGF("FTL: Error while reading sector %d!\n", (sector + i));
-
 
1340
                    error = 1;
-
 
1341
                    memset(&((uint8_t*)buffer)[(i + j) << 11], 0, 0x800);
-
 
1342
                }
-
 
1343
            i += ftl_banks - 1;
-
 
1344
        }
-
 
1345
        else
-
 
1346
        {
-
 
1347
            uint32_t ret = ftl_vfl_read(abspage, &((uint8_t*)buffer)[i << 11],
-
 
1348
                                        &ftl_sparebuffer[0], 1, 1);
-
 
1349
            if (ret & 2) memset(&((uint8_t*)buffer)[i << 11], 0, 0x800);
-
 
1350
            else if ((ret & 0x11D) != 0 || ftl_sparebuffer[0].user.eccmark != 0xFF)
-
 
1351
            {
-
 
1352
	            DEBUGF("FTL: Error while reading sector %d!\n", (sector + i));
1106
            error = 1;
1353
                error = 1;
1107
            memset(&((uint8_t*)buffer)[i << 11], 0, 0x800);
1354
                memset(&((uint8_t*)buffer)[i << 11], 0, 0x800);
-
 
1355
            }
1108
        }
1356
        }
1109
    }
1357
    }
-
 
1358
 
-
 
1359
    mutex_unlock(&ftl_mtx);
-
 
1360
 
1110
    return error;
1361
    return error;
1111
}
1362
}
1112
 
1363
 
1113
 
1364
 
1114
#ifndef FTL_READONLY
1365
#ifndef FTL_READONLY
1115
/* Performs a vBlock erase, dealing with hardware,
1366
/* Performs a vBlock erase, dealing with hardware,
1116
   remapping and all kinds of trouble */
1367
   remapping and all kinds of trouble */
1117
uint32_t ftl_erase_block_internal(uint32_t block)
1368
uint32_t ftl_erase_block_internal(uint32_t block)
1118
{
1369
{
1119
    uint32_t i, j;
1370
    uint32_t i, j;
1120
    block = block + (*ftl_nand_type).blocks
1371
    block = block + ftl_nand_type->blocks
1121
          - (*ftl_nand_type).userblocks - 0x17;
1372
          - ftl_nand_type->userblocks - 0x17;
1122
    if (block == 0 || block >= (*ftl_nand_type).blocks) return 1;
1373
    if (block == 0 || block >= ftl_nand_type->blocks) return 1;
1123
    for (i = 0; i < ftl_banks; i++)
1374
    for (i = 0; i < ftl_banks; i++)
1124
    {
1375
    {
1125
        if (ftl_vfl_check_remap_scheduled(i, block) == 1)
1376
        if (ftl_vfl_check_remap_scheduled(i, block) == 1)
1126
        {
1377
        {
1127
            ftl_vfl_remap_block(i, block);
1378
            ftl_vfl_remap_block(i, block);
Line 1130... Line 1381...
1130
        ftl_vfl_log_success(i, block);
1381
        ftl_vfl_log_success(i, block);
1131
        uint32_t pblock = ftl_vfl_get_physical_block(i, block);
1382
        uint32_t pblock = ftl_vfl_get_physical_block(i, block);
1132
        uint32_t rc;
1383
        uint32_t rc;
1133
        for (j = 0; j < 3; j++)
1384
        for (j = 0; j < 3; j++)
1134
        {
1385
        {
1135
            rc = nand_block_erase(i, pblock * (*ftl_nand_type).pagesperblock);
1386
            rc = nand_block_erase(i, pblock * ftl_nand_type->pagesperblock);
1136
            if (rc == 0) break;
1387
            if (rc == 0) break;
1137
        }
1388
        }
1138
        if (rc != 0)
1389
        if (rc != 0)
1139
        {
1390
        {
-
 
1391
            panicf(PANIC_FATAL, "FTL: Block erase failed on bank %u block %u",
-
 
1392
                   (unsigned)i, (unsigned)block);
1140
            if (pblock != block)
1393
            if (pblock != block)
1141
            {
1394
            {
1142
                uint32_t spareindex = pblock - ftl_vfl_cxt[i].firstspare;
1395
                uint32_t spareindex = pblock - ftl_vfl_cxt[i].firstspare;
1143
                ftl_vfl_cxt[i].remaptable[spareindex] = 0xFFFF;
1396
                ftl_vfl_cxt[i].remaptable[spareindex] = 0xFFFF;
1144
            }
1397
            }
Line 1182... Line 1435...
1182
        {
1435
        {
1183
            erasectr = ftl_erasectr[ftl_cxt.blockpool[idx]];
1436
            erasectr = ftl_erasectr[ftl_cxt.blockpool[idx]];
1184
            bestidx = idx;
1437
            bestidx = idx;
1185
        }
1438
        }
1186
    }
1439
    }
1187
    if (bestidx == 0xFFFFFFFF) return 0xFFFFFFFF;
1440
    if (bestidx == 0xFFFFFFFF) panicf(PANIC_FATAL, "FTL: Out of pool blocks!");
1188
    block = ftl_cxt.blockpool[bestidx];
1441
    block = ftl_cxt.blockpool[bestidx];
1189
    if (bestidx != ftl_cxt.nextfreeidx)
1442
    if (bestidx != ftl_cxt.nextfreeidx)
1190
    {
1443
    {
1191
        ftl_cxt.blockpool[bestidx] = ftl_cxt.blockpool[ftl_cxt.nextfreeidx];
1444
        ftl_cxt.blockpool[bestidx] = ftl_cxt.blockpool[ftl_cxt.nextfreeidx];
1192
        ftl_cxt.blockpool[ftl_cxt.nextfreeidx] = block;
1445
        ftl_cxt.blockpool[ftl_cxt.nextfreeidx] = block;
1193
    }
1446
    }
1194
    if (block > (uint32_t)(*ftl_nand_type).userblocks + 0x17) return 0xFFFFFFFF;
1447
    if (block > (uint32_t)ftl_nand_type->userblocks + 0x17)
-
 
1448
        panicf(PANIC_FATAL, "FTL: Bad block number in pool: %u", (unsigned)block);
1195
    if (ftl_erase_block(block) != 0) return 0xFFFFFFFF;
1449
    if (ftl_erase_block(block) != 0) return 0xFFFFFFFF;
1196
    if (++ftl_cxt.nextfreeidx == 0x14) ftl_cxt.nextfreeidx = 0;
1450
    if (++ftl_cxt.nextfreeidx == 0x14) ftl_cxt.nextfreeidx = 0;
1197
    ftl_cxt.freecount--;
1451
    ftl_cxt.freecount--;
1198
    return block;
1452
    return block;
1199
}
1453
}
Line 1202... Line 1456...
1202
 
1456
 
1203
#ifndef FTL_READONLY
1457
#ifndef FTL_READONLY
1204
/* Releases a vBlock back into the pool */
1458
/* Releases a vBlock back into the pool */
1205
void ftl_release_pool_block(uint32_t block)
1459
void ftl_release_pool_block(uint32_t block)
1206
{
1460
{
-
 
1461
    if (block >= (uint32_t)ftl_nand_type->userblocks + 0x17)
-
 
1462
        panicf(PANIC_FATAL, "FTL: Tried to release block %u", (unsigned)block);
1207
    uint32_t idx = ftl_cxt.nextfreeidx + ftl_cxt.freecount++;
1463
    uint32_t idx = ftl_cxt.nextfreeidx + ftl_cxt.freecount++;
1208
    if (idx >= 0x14) idx -= 0x14;
1464
    if (idx >= 0x14) idx -= 0x14;
1209
    ftl_cxt.blockpool[idx] = block;
1465
    ftl_cxt.blockpool[idx] = block;
1210
}
1466
}
1211
#endif
1467
#endif
Line 1227... Line 1483...
1227
#ifndef FTL_READONLY
1483
#ifndef FTL_READONLY
1228
/* Saves the n-th erase counter page to the flash,
1484
/* Saves the n-th erase counter page to the flash,
1229
   because it is too dirty or needs to be moved. */
1485
   because it is too dirty or needs to be moved. */
1230
uint32_t ftl_save_erasectr_page(uint32_t index)
1486
uint32_t ftl_save_erasectr_page(uint32_t index)
1231
{
1487
{
1232
    memset(&ftl_sparebuffer, 0xFF, 0x40);
1488
    memset(&ftl_sparebuffer[0], 0xFF, 0x40);
1233
    ftl_sparebuffer.meta.usn = ftl_cxt.usn;
1489
    ftl_sparebuffer[0].meta.usn = ftl_cxt.usn;
1234
    ftl_sparebuffer.meta.idx = index;
1490
    ftl_sparebuffer[0].meta.idx = index;
1235
    ftl_sparebuffer.meta.type = 0x46;
1491
    ftl_sparebuffer[0].meta.type = 0x46;
1236
    if (ftl_vfl_write(ftl_cxt.ftlctrlpage, &ftl_erasectr[index << 10],
1492
    if (ftl_vfl_write(ftl_cxt.ftlctrlpage, 1, &ftl_erasectr[index << 10],
1237
                      &ftl_sparebuffer) != 0)
1493
                      &ftl_sparebuffer[0]) != 0)
1238
        return 1;
1494
        return 1;
1239
    if ((ftl_vfl_read(ftl_cxt.ftlctrlpage, ftl_buffer,
1495
    if ((ftl_vfl_read(ftl_cxt.ftlctrlpage, ftl_buffer,
1240
                      &ftl_sparebuffer, 1, 1) & 0x11F) != 0)
1496
                      &ftl_sparebuffer[0], 1, 1) & 0x11F) != 0)
1241
        return 1;
1497
        return 1;
1242
    if (memcmp(ftl_buffer, &ftl_erasectr[index << 10], 0x800) != 0) return 1;
1498
    if (memcmp(ftl_buffer, &ftl_erasectr[index << 10], 0x800) != 0) return 1;
1243
    if (ftl_sparebuffer.meta.type != 0x46) return 1;
1499
    if (ftl_sparebuffer[0].meta.type != 0x46) return 1;
1244
    if (ftl_sparebuffer.meta.idx != index) return 1;
1500
    if (ftl_sparebuffer[0].meta.idx != index) return 1;
1245
    if (ftl_sparebuffer.meta.usn != ftl_cxt.usn) return 1;
1501
    if (ftl_sparebuffer[0].meta.usn != ftl_cxt.usn) return 1;
1246
    ftl_cxt.ftl_erasectr_pages[index] = ftl_cxt.ftlctrlpage;
1502
    ftl_cxt.ftl_erasectr_pages[index] = ftl_cxt.ftlctrlpage;
1247
    ftl_erasectr_dirt[index] = 0;
1503
    ftl_erasectr_dirt[index] = 0;
1248
    return 0;
1504
    return 0;
1249
}
1505
}
1250
#endif
1506
#endif
Line 1254... Line 1510...
1254
/* Increments ftl_cxt.ftlctrlpage to the next available FTL context page,
1510
/* Increments ftl_cxt.ftlctrlpage to the next available FTL context page,
1255
   allocating a new context block if neccessary. */
1511
   allocating a new context block if neccessary. */
1256
uint32_t ftl_next_ctrl_pool_page(void)
1512
uint32_t ftl_next_ctrl_pool_page(void)
1257
{
1513
{
1258
    uint32_t i;
1514
    uint32_t i;
1259
    uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
1515
    uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks;
1260
    if (++ftl_cxt.ftlctrlpage % ppb != 0) return 0;
1516
    if (++ftl_cxt.ftlctrlpage % ppb != 0) return 0;
1261
    for (i = 0; i < 3; i++)
1517
    for (i = 0; i < 3; i++)
1262
        if ((ftl_cxt.ftlctrlblocks[i] + 1) * ppb == ftl_cxt.ftlctrlpage)
1518
        if ((ftl_cxt.ftlctrlblocks[i] + 1) * ppb == ftl_cxt.ftlctrlpage)
1263
            break;
1519
            break;
1264
    i = (i + 1) % 3;
1520
    i = (i + 1) % 3;
1265
    uint32_t oldblock = ftl_cxt.ftlctrlblocks[i];
1521
    uint32_t oldblock = ftl_cxt.ftlctrlblocks[i];
1266
    uint32_t newblock = ftl_allocate_pool_block();
1522
    uint32_t newblock = ftl_allocate_pool_block();
1267
    if (newblock == 0xFFFFFFFF) return 1;
1523
    if (newblock == 0xFFFFFFFF) return 1;
1268
    ftl_cxt.ftlctrlblocks[i] = newblock;
1524
    ftl_cxt.ftlctrlblocks[i] = newblock;
1269
    ftl_cxt.ftlctrlpage = newblock * ppb;
1525
    ftl_cxt.ftlctrlpage = newblock * ppb;
-
 
1526
    DEBUGF("Starting new FTL control block at %d\n", ftl_cxt.ftlctrlpage);
1270
    uint32_t pagestoread = ((*ftl_nand_type).userblocks + 23) >> 10;
1527
    uint32_t pagestoread = (ftl_nand_type->userblocks + 23) >> 10;
1271
    if ((((*ftl_nand_type).userblocks + 23) & 0x1FF) != 0) pagestoread++;
1528
    if (((ftl_nand_type->userblocks + 23) & 0x1FF) != 0) pagestoread++;
1272
    for (i = 0; i < pagestoread; i++)
1529
    for (i = 0; i < pagestoread; i++)
1273
        if (oldblock * ppb <= ftl_cxt.ftl_erasectr_pages[i]
1530
        if (oldblock * ppb <= ftl_cxt.ftl_erasectr_pages[i]
1274
         && (oldblock + 1) * ppb > ftl_cxt.ftl_erasectr_pages[i])
1531
         && (oldblock + 1) * ppb > ftl_cxt.ftl_erasectr_pages[i])
1275
         {
1532
         {
1276
            ftl_cxt.usn--;
1533
            ftl_cxt.usn--;
Line 1292... Line 1549...
1292
#ifndef FTL_READONLY
1549
#ifndef FTL_READONLY
1293
/* Copies a vPage from one location to another */
1550
/* Copies a vPage from one location to another */
1294
uint32_t ftl_copy_page(uint32_t source, uint32_t destination,
1551
uint32_t ftl_copy_page(uint32_t source, uint32_t destination,
1295
                       uint32_t lpn, uint32_t type)
1552
                       uint32_t lpn, uint32_t type)
1296
{
1553
{
1297
    uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
1554
    uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks;
1298
    uint32_t rc = ftl_vfl_read(source, ftl_copybuffer,
1555
    uint32_t rc = ftl_vfl_read(source, ftl_copybuffer[0],
1299
                               &ftl_sparebuffer, 1, 1) & 0x11F;
1556
                               &ftl_copyspare[0], 1, 1) & 0x11F;
1300
    memset(&ftl_sparebuffer, 0xFF, 0x40);
1557
    memset(&ftl_copyspare[0], 0xFF, 0x40);
1301
    ftl_sparebuffer.user.lpn = lpn;
1558
    ftl_copyspare[0].user.lpn = lpn;
1302
    ftl_sparebuffer.user.usn = ++ftl_cxt.nextblockusn;
1559
    ftl_copyspare[0].user.usn = ++ftl_cxt.nextblockusn;
1303
    ftl_sparebuffer.user.type = 0x40;
1560
    ftl_copyspare[0].user.type = 0x40;
1304
    if ((rc & 2) != 0) memset(ftl_copybuffer, 0, 0x800);
1561
    if ((rc & 2) != 0) memset(ftl_copybuffer[0], 0, 0x800);
1305
    else if (rc != 0) ftl_sparebuffer.user.eccmark = 0x55;
1562
    else if (rc != 0) ftl_copyspare[0].user.eccmark = 0x55;
1306
    if (type == 1 && destination % ppb == ppb - 1)
1563
    if (type == 1 && destination % ppb == ppb - 1)
1307
        ftl_sparebuffer.user.type = 0x41;
1564
        ftl_copyspare[0].user.type = 0x41;
1308
    return ftl_vfl_write(destination, ftl_copybuffer, &ftl_sparebuffer);
1565
    return ftl_vfl_write(destination, 1, ftl_copybuffer[0], &ftl_copyspare[0]);
1309
}
1566
}
1310
#endif
1567
#endif
1311
 
1568
 
1312
 
1569
 
1313
#ifndef FTL_READONLY
1570
#ifndef FTL_READONLY
1314
/* Copies a pBlock to a vBlock */
1571
/* Copies a pBlock to a vBlock */
1315
uint32_t ftl_copy_block(uint32_t source, uint32_t destination)
1572
uint32_t ftl_copy_block(uint32_t source, uint32_t destination)
1316
{
1573
{
1317
    uint32_t i;
1574
    uint32_t i, j;
1318
    uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
1575
    uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks;
1319
    uint32_t error = 0;
1576
    uint32_t error = 0;
1320
    ftl_cxt.nextblockusn++;
1577
    ftl_cxt.nextblockusn++;
1321
    for (i = 0; i < ppb; i++)
1578
    for (i = 0; i < ppb; i += FTL_COPYBUF_SIZE)
1322
    {
1579
    {
1323
        uint32_t rc = storage_read(source * ppb + i, 1, ftl_copybuffer);
1580
        uint32_t rc = ftl_read(source * ppb + i,
-
 
1581
                               FTL_COPYBUF_SIZE, ftl_copybuffer[0]);
1324
        memset(&ftl_sparebuffer, 0xFF, 0x40);
1582
        memset(&ftl_copyspare[0], 0xFF, 0x40 * FTL_COPYBUF_SIZE);
-
 
1583
        for (j = 0; j < FTL_COPYBUF_SIZE; j++)
-
 
1584
        {
1325
        ftl_sparebuffer.user.lpn = source * ppb + i;
1585
            ftl_copyspare[j].user.lpn = source * ppb + i + j;
1326
        ftl_sparebuffer.user.usn = ftl_cxt.nextblockusn;
1586
            ftl_copyspare[j].user.usn = ftl_cxt.nextblockusn;
1327
        ftl_sparebuffer.user.type = 0x40;
1587
            ftl_copyspare[j].user.type = 0x40;
-
 
1588
            if (rc)
-
 
1589
            {
-
 
1590
                if (ftl_read(source * ppb + i + j, 1, ftl_copybuffer[j]))
1328
        if (rc != 0) ftl_sparebuffer.user.eccmark = 0x55;
1591
                    ftl_copyspare[j].user.eccmark = 0x55;
-
 
1592
            }
1329
        if (i == ppb - 1) ftl_sparebuffer.user.type = 0x41;
1593
            if (i + j == ppb - 1) ftl_copyspare[j].user.type = 0x41;
-
 
1594
        }
1330
        if (ftl_vfl_write(destination * ppb + i,
1595
        if (ftl_vfl_write(destination * ppb + i, FTL_COPYBUF_SIZE,
1331
                          ftl_copybuffer, &ftl_sparebuffer) != 0)
1596
                          ftl_copybuffer[0], &ftl_copyspare[0]))
1332
        {
1597
        {
1333
            error = 1;
1598
            error = 1;
1334
            break;
1599
            break;
1335
        }
1600
        }
1336
    }
1601
    }
Line 1346... Line 1611...
1346
 
1611
 
1347
#ifndef FTL_READONLY
1612
#ifndef FTL_READONLY
1348
/* Clears ftl_log.issequential, if something violating that is written. */
1613
/* Clears ftl_log.issequential, if something violating that is written. */
1349
void ftl_check_still_sequential(struct ftl_log_type* entry, uint32_t page)
1614
void ftl_check_still_sequential(struct ftl_log_type* entry, uint32_t page)
1350
{
1615
{
1351
    if ((*entry).pagesused != (*entry).pagescurrent
1616
    if (entry->pagesused != entry->pagescurrent
1352
     || (*entry).pageoffsets[page] != page)
1617
     || entry->pageoffsets[page] != page)
1353
        (*entry).issequential = 0;
1618
        entry->issequential = 0;
1354
}
1619
}
1355
#endif
1620
#endif
1356
 
1621
 
1357
 
1622
 
1358
#ifndef FTL_READONLY
1623
#ifndef FTL_READONLY
Line 1364... Line 1629...
1364
   removed because it is full, but less than half of the pages in there are
1629
   removed because it is full, but less than half of the pages in there are
1365
   still in use and rest is just filled with old crap. */
1630
   still in use and rest is just filled with old crap. */
1366
uint32_t ftl_compact_scattered(struct ftl_log_type* entry)
1631
uint32_t ftl_compact_scattered(struct ftl_log_type* entry)
1367
{
1632
{
1368
    uint32_t i, j;
1633
    uint32_t i, j;
1369
    uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
1634
    uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks;
1370
    uint32_t error;
1635
    uint32_t error;
1371
    struct ftl_log_type backup;
1636
    struct ftl_log_type backup;
1372
    if ((*entry).pagescurrent == 0)
1637
    if (entry->pagescurrent == 0)
1373
    {
1638
    {
1374
        ftl_release_pool_block((*entry).scatteredvblock);
1639
        ftl_release_pool_block(entry->scatteredvblock);
1375
        (*entry).scatteredvblock = 0xFFFF;
1640
        entry->scatteredvblock = 0xFFFF;
1376
        return 0;
1641
        return 0;
1377
    }
1642
    }
1378
    backup = *entry;
1643
    backup = *entry;
1379
    memcpy(ftl_offsets_backup, (*entry).pageoffsets, 0x400);
1644
    memcpy(ftl_offsets_backup, entry->pageoffsets, 0x400);
1380
    for (i = 0; i < 4; i++)
1645
    for (i = 0; i < 4; i++)
1381
    {
1646
    {
1382
        uint32_t block = ftl_allocate_pool_block();
1647
        uint32_t block = ftl_allocate_pool_block();
1383
        if (block == 0xFFFFFFFF) return 1;
1648
        if (block == 0xFFFFFFFF) return 1;
1384
        (*entry).pagesused = 0;
1649
        entry->pagesused = 0;
1385
        (*entry).pagescurrent = 0;
1650
        entry->pagescurrent = 0;
1386
        (*entry).issequential = 1;
1651
        entry->issequential = 1;
1387
        (*entry).scatteredvblock = block;
1652
        entry->scatteredvblock = block;
1388
        error = 0;
1653
        error = 0;
1389
        for (j = 0; j < ppb; j++)
1654
        for (j = 0; j < ppb; j++)
1390
            if ((*entry).pageoffsets[j] != 0xFFFF)
1655
            if (entry->pageoffsets[j] != 0xFFFF)
1391
            {
1656
            {
1392
                uint32_t lpn = (*entry).logicalvblock * ppb + j;
1657
                uint32_t lpn = entry->logicalvblock * ppb + j;
1393
                uint32_t newpage = block * ppb + (*entry).pagesused;
1658
                uint32_t newpage = block * ppb + entry->pagesused;
1394
                uint32_t oldpage = backup.scatteredvblock * ppb
1659
                uint32_t oldpage = backup.scatteredvblock * ppb
1395
                                 + (*entry).pageoffsets[j];
1660
                                 + entry->pageoffsets[j];
1396
                if (ftl_copy_page(oldpage, newpage, lpn,
1661
                if (ftl_copy_page(oldpage, newpage, lpn,
1397
                                  (*entry).issequential) != 0)
1662
                                  entry->issequential) != 0)
1398
                {
1663
                {
1399
                    error = 1;
1664
                    error = 1;
1400
                    break;
1665
                    break;
1401
                }
1666
                }
1402
                (*entry).pageoffsets[j] = (*entry).pagesused++;
1667
                entry->pageoffsets[j] = entry->pagesused++;
1403
                (*entry).pagescurrent++;
1668
                entry->pagescurrent++;
1404
                ftl_check_still_sequential(entry, j);
1669
                ftl_check_still_sequential(entry, j);
1405
            }
1670
            }
1406
        if (backup.pagescurrent != (*entry).pagescurrent) error = 1;
1671
        if (backup.pagescurrent != entry->pagescurrent) error = 1;
1407
        if (error == 0)
1672
        if (error == 0)
1408
        {
1673
        {
1409
            ftl_release_pool_block(backup.scatteredvblock);
1674
            ftl_release_pool_block(backup.scatteredvblock);
1410
            break;
1675
            break;
1411
        }
1676
        }
1412
        *entry = backup;
1677
        *entry = backup;
1413
        memcpy((*entry).pageoffsets, ftl_offsets_backup, 0x400);
1678
        memcpy(entry->pageoffsets, ftl_offsets_backup, 0x400);
1414
    }
1679
    }
1415
    return error;
1680
    return error;
1416
}
1681
}
1417
#endif
1682
#endif
1418
 
1683
 
Line 1426... Line 1691...
1426
    uint32_t block;
1691
    uint32_t block;
1427
    for (i = 0; i < 4; i++)
1692
    for (i = 0; i < 4; i++)
1428
    {
1693
    {
1429
        block = ftl_allocate_pool_block();
1694
        block = ftl_allocate_pool_block();
1430
        if (block == 0xFFFFFFFF) return 1;
1695
        if (block == 0xFFFFFFFF) return 1;
1431
        error = ftl_copy_block((*entry).logicalvblock, block);
1696
        error = ftl_copy_block(entry->logicalvblock, block);
1432
        if (error == 0) break;
1697
        if (error == 0) break;
1433
        ftl_release_pool_block(block);
1698
        ftl_release_pool_block(block);
1434
    }
1699
    }
1435
    if (error != 0) return 1;
1700
    if (error != 0) return 1;
1436
    ftl_release_pool_block((*entry).scatteredvblock);
1701
    ftl_release_pool_block(entry->scatteredvblock);
1437
    (*entry).scatteredvblock = 0xFFFF;
1702
    entry->scatteredvblock = 0xFFFF;
1438
    ftl_release_pool_block(ftl_map[(*entry).logicalvblock]);
1703
    ftl_release_pool_block(ftl_map[entry->logicalvblock]);
1439
    ftl_map[(*entry).logicalvblock] = block;
1704
    ftl_map[entry->logicalvblock] = block;
1440
    return 0;
1705
    return 0;
1441
}
1706
}
1442
#endif
1707
#endif
1443
 
1708
 
1444
 
1709
 
Line 1447... Line 1712...
1447
   sequentially until now, in order to be able to save a block erase by
1712
   sequentially until now, in order to be able to save a block erase by
1448
   committing it without needing to copy it again.
1713
   committing it without needing to copy it again.
1449
   If this fails for whichever reason, it will be committed the usual way. */
1714
   If this fails for whichever reason, it will be committed the usual way. */
1450
uint32_t ftl_commit_sequential(struct ftl_log_type* entry)
1715
uint32_t ftl_commit_sequential(struct ftl_log_type* entry)
1451
{
1716
{
-
 
1717
    uint32_t i;
1452
    uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
1718
    uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks;
1453
 
1719
 
1454
    if ((*entry).issequential != 1
1720
    if (entry->issequential != 1
1455
     || (*entry).pagescurrent != (*entry).pagesused)
1721
     || entry->pagescurrent != entry->pagesused)
1456
        return 1;
1722
        return 1;
1457
 
1723
 
1458
    for (; (*entry).pagesused < ppb; (*entry).pagesused++)
1724
    for (; entry->pagesused < ppb; )
1459
    {
1725
    {
1460
        uint32_t lpn = (*entry).logicalvblock * ppb + (*entry).pagesused;
1726
        uint32_t lpn = entry->logicalvblock * ppb + entry->pagesused;
1461
        uint32_t newpage = (*entry).scatteredvblock * ppb
1727
        uint32_t newpage = entry->scatteredvblock * ppb
1462
                         + (*entry).pagesused;
1728
                         + entry->pagesused;
1463
        uint32_t oldpage = ftl_map[(*entry).logicalvblock] * ppb
1729
        uint32_t count = FTL_COPYBUF_SIZE < ppb - entry->pagesused
1464
                         + (*entry).pagesused;
1730
                       ? FTL_COPYBUF_SIZE : ppb - entry->pagesused;
-
 
1731
        for (i = 0; i < count; i++)
1465
        if ((*entry).pageoffsets[(*entry).pagesused] != 0xFFFF
1732
            if (entry->pageoffsets[entry->pagesused + i] != 0xFFFF)
-
 
1733
                return ftl_commit_scattered(entry);
-
 
1734
        uint32_t rc = ftl_read(lpn, count, ftl_copybuffer[0]);
-
 
1735
        memset(&ftl_copyspare[0], 0xFF, 0x40 * FTL_COPYBUF_SIZE);
-
 
1736
        for (i = 0; i < count; i++)
-
 
1737
        {
1466
         || ftl_copy_page(oldpage, newpage, lpn, 1) != 0)
1738
            ftl_copyspare[i].user.lpn = lpn + i;
-
 
1739
            ftl_copyspare[i].user.usn = ++ftl_cxt.nextblockusn;
-
 
1740
            ftl_copyspare[i].user.type = 0x40;
-
 
1741
            if (rc) ftl_copyspare[i].user.eccmark = 0x55;
-
 
1742
            if (entry->pagesused + i == ppb - 1)
-
 
1743
                ftl_copyspare[i].user.type = 0x41;
-
 
1744
        }
-
 
1745
        if (ftl_vfl_write(newpage, count, ftl_copybuffer[0], &ftl_copyspare[0]))
1467
            return ftl_commit_scattered(entry);
1746
            return ftl_commit_scattered(entry);
-
 
1747
        entry->pagesused += count;
1468
    }
1748
    }
1469
    ftl_release_pool_block(ftl_map[(*entry).logicalvblock]);
1749
    ftl_release_pool_block(ftl_map[entry->logicalvblock]);
1470
    ftl_map[(*entry).logicalvblock] = (*entry).scatteredvblock;
1750
    ftl_map[entry->logicalvblock] = entry->scatteredvblock;
1471
    (*entry).scatteredvblock = 0xFFFF;
1751
    entry->scatteredvblock = 0xFFFF;
1472
    return 0;
1752
    return 0;
1473
}
1753
}
1474
#endif
1754
#endif
1475
 
1755
 
1476
 
1756
 
Line 1479... Line 1759...
1479
   whatever way seems most appropriate. Else, the oldest scattered page block
1759
   whatever way seems most appropriate. Else, the oldest scattered page block
1480
   will be freed by committing it. */
1760
   will be freed by committing it. */
1481
uint32_t ftl_remove_scattered_block(struct ftl_log_type* entry)
1761
uint32_t ftl_remove_scattered_block(struct ftl_log_type* entry)
1482
{
1762
{
1483
    uint32_t i;
1763
    uint32_t i;
1484
    uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
1764
    uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks;
1485
    uint32_t age = 0xFFFFFFFF, used = 0;
1765
    uint32_t age = 0xFFFFFFFF, used = 0;
1486
    if (entry == (struct ftl_log_type*)0)
1766
    if (entry == (struct ftl_log_type*)0)
1487
    {
1767
    {
1488
        for (i = 0; i < 0x11; i++)
1768
        for (i = 0; i < 0x11; i++)
1489
        {
1769
        {
Line 1498... Line 1778...
1498
                entry = &ftl_log[i];
1778
                entry = &ftl_log[i];
1499
            }
1779
            }
1500
        }
1780
        }
1501
        if (entry == (struct ftl_log_type*)0) return 1;
1781
        if (entry == (struct ftl_log_type*)0) return 1;
1502
    }
1782
    }
1503
    else if ((*entry).pagescurrent < ppb / 2)
1783
    else if (entry->pagescurrent < ppb / 2)
1504
    {
1784
    {
1505
        ftl_cxt.swapcounter++;
1785
        ftl_cxt.swapcounter++;
1506
        return ftl_compact_scattered(entry);
1786
        return ftl_compact_scattered(entry);
1507
    }
1787
    }
1508
    ftl_cxt.swapcounter++;
1788
    ftl_cxt.swapcounter++;
1509
    if ((*entry).issequential == 1) return ftl_commit_sequential(entry);
1789
    if (entry->issequential == 1) return ftl_commit_sequential(entry);
1510
    else return ftl_commit_scattered(entry);
1790
    else return ftl_commit_scattered(entry);
1511
}
1791
}
1512
#endif
1792
#endif
1513
 
1793
 
1514
 
1794
 
1515
#ifndef FTL_READONLY
1795
#ifndef FTL_READONLY
1516
/* Initialize a log entry to the values for an empty scattered page block */
1796
/* Initialize a log entry to the values for an empty scattered page block */
1517
void ftl_init_log_entry(struct ftl_log_type* entry)
1797
void ftl_init_log_entry(struct ftl_log_type* entry)
1518
{
1798
{
1519
    (*entry).issequential = 1;
1799
    entry->issequential = 1;
1520
    (*entry).pagescurrent = 0;
1800
    entry->pagescurrent = 0;
1521
    (*entry).pagesused = 0;
1801
    entry->pagesused = 0;
1522
    memset((*entry).pageoffsets, 0xFF, 0x400);
1802
    memset(entry->pageoffsets, 0xFF, 0x400);
1523
}
1803
}
1524
#endif
1804
#endif
1525
 
1805
 
1526
 
1806
 
1527
#ifndef FTL_READONLY
1807
#ifndef FTL_READONLY
Line 1529... Line 1809...
1529
   first making space, if neccessary. */
1809
   first making space, if neccessary. */
1530
struct ftl_log_type* ftl_allocate_log_entry(uint32_t block)
1810
struct ftl_log_type* ftl_allocate_log_entry(uint32_t block)
1531
{
1811
{
1532
    uint32_t i;
1812
    uint32_t i;
1533
    struct ftl_log_type* entry = ftl_get_log_entry(block);
1813
    struct ftl_log_type* entry = ftl_get_log_entry(block);
-
 
1814
    entry->usn = ftl_cxt.nextblockusn - 1;
1534
    if (entry != (struct ftl_log_type*)0) return entry;
1815
    if (entry != (struct ftl_log_type*)0) return entry;
1535
 
1816
 
1536
    for (i = 0; i < 0x11; i++)
1817
    for (i = 0; i < 0x11; i++)
1537
    {
1818
    {
1538
        if (ftl_log[i].scatteredvblock == 0xFFFF) continue;
1819
        if (ftl_log[i].scatteredvblock == 0xFFFF) continue;
Line 1543... Line 1824...
1543
        }
1824
        }
1544
    }
1825
    }
1545
 
1826
 
1546
    if (entry == (struct ftl_log_type*)0)
1827
    if (entry == (struct ftl_log_type*)0)
1547
    {
1828
    {
-
 
1829
        if (ftl_cxt.freecount < 3) panicf(PANIC_FATAL, "FTL: Detected a pool block leak!");
1548
        if (ftl_cxt.freecount <= 3)
1830
        else if (ftl_cxt.freecount == 3)
1549
            if (ftl_remove_scattered_block((struct ftl_log_type*)0) != 0)
1831
            if (ftl_remove_scattered_block((struct ftl_log_type*)0) != 0)
1550
                return (struct ftl_log_type*)0;
1832
                return (struct ftl_log_type*)0;
1551
        entry = ftl_log;
1833
        entry = ftl_log;
1552
        while ((*entry).scatteredvblock != 0xFFFF) entry = &entry[1];
1834
        while (entry->scatteredvblock != 0xFFFF) entry = &entry[1];
1553
        (*entry).scatteredvblock = ftl_allocate_pool_block();
1835
        entry->scatteredvblock = ftl_allocate_pool_block();
1554
        if ((*entry).scatteredvblock == 0xFFFF)
1836
        if (entry->scatteredvblock == 0xFFFF)
1555
        {
-
 
1556
            (*entry).scatteredvblock = 0xFFFF;
-
 
1557
            return (struct ftl_log_type*)0;
1837
            return (struct ftl_log_type*)0;
1558
        }
-
 
1559
    }
1838
    }
1560
 
1839
 
1561
    ftl_init_log_entry(entry);
1840
    ftl_init_log_entry(entry);
1562
    (*entry).logicalvblock = block;
1841
    entry->logicalvblock = block;
1563
    (*entry).usn = ftl_cxt.nextblockusn - 1;
1842
    entry->usn = ftl_cxt.nextblockusn - 1;
1564
 
1843
 
1565
    return entry;
1844
    return entry;
1566
}
1845
}
1567
#endif
1846
#endif
1568
 
1847
 
Line 1570... Line 1849...
1570
#ifndef FTL_READONLY
1849
#ifndef FTL_READONLY
1571
/* Commits the FTL block map, erase counters, and context to flash */
1850
/* Commits the FTL block map, erase counters, and context to flash */
1572
uint32_t ftl_commit_cxt(void)
1851
uint32_t ftl_commit_cxt(void)
1573
{
1852
{
1574
    uint32_t i;
1853
    uint32_t i;
1575
    uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
1854
    uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks;
1576
    uint32_t mappages = ((*ftl_nand_type).userblocks + 0x3ff) >> 10;
1855
    uint32_t mappages = (ftl_nand_type->userblocks + 0x3ff) >> 10;
1577
    uint32_t ctrpages = ((*ftl_nand_type).userblocks + 23 + 0x3ff) >> 10;
1856
    uint32_t ctrpages = (ftl_nand_type->userblocks + 23 + 0x3ff) >> 10;
1578
    uint32_t endpage = ftl_cxt.ftlctrlpage + mappages + ctrpages + 1;
1857
    uint32_t endpage = ftl_cxt.ftlctrlpage + mappages + ctrpages + 1;
-
 
1858
    DEBUGF("FTL: Committing context\n");
1579
    if (endpage % ppb > ppb - 1)
1859
    if (endpage >= (ftl_cxt.ftlctrlpage / ppb + 1) * ppb)
1580
        ftl_cxt.ftlctrlpage |= ppb - 1;
1860
        ftl_cxt.ftlctrlpage |= ppb - 1;
1581
    for (i = 0; i < ctrpages; i++)
1861
    for (i = 0; i < ctrpages; i++)
1582
    {
1862
    {
1583
        if (ftl_next_ctrl_pool_page() != 0) return 1;
1863
        if (ftl_next_ctrl_pool_page() != 0) return 1;
1584
        if (ftl_save_erasectr_page(i) != 0) return 1;
1864
        if (ftl_save_erasectr_page(i) != 0) return 1;
1585
    }
1865
    }
1586
    for (i = 0; i < mappages; i++)
1866
    for (i = 0; i < mappages; i++)
1587
    {
1867
    {
1588
        if (ftl_next_ctrl_pool_page() != 0) return 1;
1868
        if (ftl_next_ctrl_pool_page() != 0) return 1;
1589
        memset(&ftl_sparebuffer, 0xFF, 0x40);
1869
        memset(&ftl_sparebuffer[0], 0xFF, 0x40);
1590
        ftl_sparebuffer.meta.usn = ftl_cxt.usn;
1870
        ftl_sparebuffer[0].meta.usn = ftl_cxt.usn;
1591
        ftl_sparebuffer.meta.idx = i;
1871
        ftl_sparebuffer[0].meta.idx = i;
1592
        ftl_sparebuffer.meta.type = 0x44;
1872
        ftl_sparebuffer[0].meta.type = 0x44;
1593
        if (ftl_vfl_write(ftl_cxt.ftlctrlpage, &ftl_map[i << 10],
1873
        if (ftl_vfl_write(ftl_cxt.ftlctrlpage, 1, &ftl_map[i << 10],
1594
                          &ftl_sparebuffer) != 0)
1874
                          &ftl_sparebuffer[0]) != 0)
1595
            return 1;
1875
            return 1;
1596
        ftl_cxt.ftl_map_pages[i] = ftl_cxt.ftlctrlpage;
1876
        ftl_cxt.ftl_map_pages[i] = ftl_cxt.ftlctrlpage;
1597
    }
1877
    }
1598
    if (ftl_next_ctrl_pool_page() != 0) return 1;
1878
    if (ftl_next_ctrl_pool_page() != 0) return 1;
1599
    ftl_cxt.clean_flag = 1;
1879
    ftl_cxt.clean_flag = 1;
1600
    memset(&ftl_sparebuffer, 0xFF, 0x40);
1880
    memset(&ftl_sparebuffer[0], 0xFF, 0x40);
1601
    ftl_sparebuffer.meta.usn = ftl_cxt.usn;
1881
    ftl_sparebuffer[0].meta.usn = ftl_cxt.usn;
1602
    ftl_sparebuffer.meta.type = 0x43;
1882
    ftl_sparebuffer[0].meta.type = 0x43;
1603
    if (ftl_vfl_write(ftl_cxt.ftlctrlpage, &ftl_cxt, &ftl_sparebuffer) != 0)
1883
    if (ftl_vfl_write(ftl_cxt.ftlctrlpage, 1, &ftl_cxt, &ftl_sparebuffer[0]) != 0)
1604
        return 1;
1884
        return 1;
-
 
1885
    DEBUGF("FTL: Wrote context to page %d\n", ftl_cxt.ftlctrlpage);
1605
    return 0;
1886
    return 0;
1606
}
1887
}
1607
#endif
1888
#endif
1608
 
1889
 
1609
 
1890
 
Line 1626... Line 1907...
1626
            maxvb = ftl_cxt.blockpool[idx];
1907
            maxvb = ftl_cxt.blockpool[idx];
1627
            max = ftl_erasectr[maxidx];
1908
            max = ftl_erasectr[maxidx];
1628
        }
1909
        }
1629
    }
1910
    }
1630
    if (maxidx == 0x14) return 0;
1911
    if (maxidx == 0x14) return 0;
1631
    for (i = 0; i < (*ftl_nand_type).userblocks; i++)
1912
    for (i = 0; i < ftl_nand_type->userblocks; i++)
1632
    {
1913
    {
1633
        if (ftl_erasectr[ftl_map[i]] > max) max = ftl_erasectr[ftl_map[i]];
1914
        if (ftl_erasectr[ftl_map[i]] > max) max = ftl_erasectr[ftl_map[i]];
1634
        if (ftl_get_log_entry(i) != (struct ftl_log_type*)0) continue;
1915
        if (ftl_get_log_entry(i) != (struct ftl_log_type*)0) continue;
1635
        if (ftl_erasectr[ftl_map[i]] < min)
1916
        if (ftl_erasectr[ftl_map[i]] < min)
1636
        {
1917
        {
Line 1650... Line 1931...
1650
#endif
1931
#endif
1651
 
1932
 
1652
 
1933
 
1653
#ifndef FTL_READONLY
1934
#ifndef FTL_READONLY
1654
/* Exposed function: Write highlevel sectors */
1935
/* Exposed function: Write highlevel sectors */
1655
uint32_t storage_write(uint32_t sector, uint32_t count, const void* buffer)
1936
uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer)
1656
{
1937
{
1657
    uint32_t i, j;
1938
    uint32_t i, j, k;
1658
    uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
1939
    uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks;
1659
 
1940
 
-
 
1941
#ifdef FTL_TRACE
1660
    if (sector + count > (*ftl_nand_type).userblocks * ppb)
1942
    DEBUGF("FTL: Writing %d sectors starting at %d\n", count, sector);
1661
        return 1;
1943
#endif
1662
 
1944
 
-
 
1945
    if (sector + count > ftl_nand_type->userblocks * ppb)
-
 
1946
    {
-
 
1947
        DEBUGF("FTL: Sector %d is out of range!\n", sector + count - 1);
-
 
1948
        return 1;
-
 
1949
    }
1663
    if (count == 0) return 0;
1950
    if (count == 0) return 0;
1664
 
1951
 
-
 
1952
    mutex_lock(&ftl_mtx, TIMEOUT_BLOCK);
-
 
1953
 
1665
    if (ftl_cxt.clean_flag == 1)
1954
    if (ftl_cxt.clean_flag == 1)
1666
    {
1955
    {
1667
        for (i = 0; i < 3; i++)
1956
        for (i = 0; i < 3; i++)
1668
        {
1957
        {
-
 
1958
		    DEBUGF("FTL: Marking dirty, try %d\n", i);
1669
            if (ftl_next_ctrl_pool_page() != 0) return 1;
1959
            if (ftl_next_ctrl_pool_page() != 0)
-
 
1960
            {
-
 
1961
                mutex_unlock(&ftl_mtx);
-
 
1962
                return 1;
-
 
1963
            }
1670
            memset(ftl_buffer, 0xFF, 0x800);
1964
            memset(ftl_buffer, 0xFF, 0x800);
1671
            memset(&ftl_sparebuffer, 0xFF, 0x40);
1965
            memset(&ftl_sparebuffer[0], 0xFF, 0x40);
1672
            ftl_sparebuffer.meta.usn = ftl_cxt.usn;
1966
            ftl_sparebuffer[0].meta.usn = ftl_cxt.usn;
1673
            ftl_sparebuffer.meta.type = 0x47;
1967
            ftl_sparebuffer[0].meta.type = 0x47;
1674
            if (ftl_vfl_write(ftl_cxt.ftlctrlpage, ftl_buffer,
1968
            if (ftl_vfl_write(ftl_cxt.ftlctrlpage, 1, ftl_buffer,
1675
                              &ftl_sparebuffer) == 0)
1969
                              &ftl_sparebuffer[0]) == 0)
1676
                break;
1970
                break;
1677
        }
1971
        }
-
 
1972
        if (i == 3)
-
 
1973
        {
-
 
1974
            mutex_unlock(&ftl_mtx);
1678
        if (i == 3) return 1;
1975
            return 1;
-
 
1976
        }
-
 
1977
    	DEBUGF("FTL: Wrote dirty mark to %d\n", ftl_cxt.ftlctrlpage);
1679
        ftl_cxt.clean_flag = 0;
1978
        ftl_cxt.clean_flag = 0;
1680
    }
1979
    }
1681
 
1980
 
1682
    for (i = 0; i < count; )
1981
    for (i = 0; i < count; )
1683
    {
1982
    {
1684
        uint32_t block = (sector + i) / ppb;
1983
        uint32_t block = (sector + i) / ppb;
1685
        uint32_t page = (sector + i) % ppb;
1984
        uint32_t page = (sector + i) % ppb;
1686
 
1985
 
1687
        struct ftl_log_type* logentry = ftl_allocate_log_entry(block);
1986
        struct ftl_log_type* logentry = ftl_allocate_log_entry(block);
1688
        if (logentry == (struct ftl_log_type*)0) return 1;
1987
        if (logentry == (struct ftl_log_type*)0)
-
 
1988
        {
-
 
1989
            mutex_unlock(&ftl_mtx);
-
 
1990
            return 1;
-
 
1991
        }
1689
        if (page == 0 && count - i >= ppb)
1992
        if (page == 0 && count - i >= ppb)
1690
        {
1993
        {
-
 
1994
#ifdef FTL_TRACE
-
 
1995
		    DEBUGF("FTL: Going to write a full hyperblock in one shot\n");
-
 
1996
#endif
1691
            uint32_t vblock = (*logentry).scatteredvblock;
1997
            uint32_t vblock = logentry->scatteredvblock;
1692
            (*logentry).scatteredvblock = 0xFFFF;
1998
            logentry->scatteredvblock = 0xFFFF;
1693
            if ((*logentry).pagesused != 0)
1999
            if (logentry->pagesused != 0)
1694
            {
2000
            {
-
 
2001
#ifdef FTL_TRACE
-
 
2002
    			DEBUGF("FTL: Scattered block had some pages already used, committing\n");
-
 
2003
#endif
1695
                ftl_release_pool_block(vblock);
2004
                ftl_release_pool_block(vblock);
1696
                vblock = ftl_allocate_pool_block();
2005
                vblock = ftl_allocate_pool_block();
1697
                if (vblock == 0xFFFFFFFF) return 1;
2006
                if (vblock == 0xFFFFFFFF)
-
 
2007
                {
-
 
2008
                    mutex_unlock(&ftl_mtx);
-
 
2009
                    return 1;
-
 
2010
                }
1698
            }
2011
            }
1699
            ftl_cxt.nextblockusn++;
2012
            ftl_cxt.nextblockusn++;
1700
            for (j = 0; j < ppb; j++)
2013
            for (j = 0; j < ppb; j += FTL_WRITESPARE_SIZE)
1701
            {
2014
            {
1702
                memset(&ftl_sparebuffer, 0xFF, 0x40);
2015
                memset(&ftl_sparebuffer[0], 0xFF, 0x40 * FTL_WRITESPARE_SIZE);
-
 
2016
                for (k = 0; k < FTL_WRITESPARE_SIZE; k++)
-
 
2017
                {
1703
                ftl_sparebuffer.user.lpn = sector + i + j;
2018
                    ftl_sparebuffer[k].user.lpn = sector + i + j + k;
1704
                ftl_sparebuffer.user.usn = ftl_cxt.nextblockusn;
2019
                    ftl_sparebuffer[k].user.usn = ftl_cxt.nextblockusn;
1705
                ftl_sparebuffer.user.type = 0x40;
2020
                    ftl_sparebuffer[k].user.type = 0x40;
1706
                if (j == ppb - 1) ftl_sparebuffer.user.type = 0x41;
2021
                    if (j == ppb - 1) ftl_sparebuffer[k].user.type = 0x41;
-
 
2022
                }
-
 
2023
                uint32_t rc = ftl_vfl_write(vblock * ppb + j, FTL_WRITESPARE_SIZE,
-
 
2024
                                            &((uint8_t*)buffer)[(i + j) << 11],
-
 
2025
                                            &ftl_sparebuffer[0]);
-
 
2026
                if (rc)
-
 
2027
                    for (k = 0; k < ftl_banks; k++)
-
 
2028
                        if (rc & (1 << k))
-
 
2029
                        {
1707
                while (ftl_vfl_write(vblock * ppb + j,
2030
                            while (ftl_vfl_write(vblock * ppb + j + k, 1,
1708
                                     &((uint8_t*)buffer)[(i + j) << 11],
2031
                                                 &((uint8_t*)buffer)[(i + j + k) << 11],
1709
                                     &ftl_sparebuffer) != 0);
2032
                                                 &ftl_sparebuffer[k]));
-
 
2033
                        }
1710
            }
2034
            }
1711
            ftl_release_pool_block(ftl_map[block]);
2035
            ftl_release_pool_block(ftl_map[block]);
1712
            ftl_map[block] = vblock;
2036
            ftl_map[block] = vblock;
1713
            i += ppb;
2037
            i += ppb;
1714
        }
2038
        }
1715
        else
2039
        else
1716
        {
2040
        {
1717
            if ((*logentry).pagesused == ppb)
2041
            if (logentry->pagesused == ppb)
1718
            {
2042
            {
-
 
2043
#ifdef FTL_TRACE
-
 
2044
    			DEBUGF("FTL: Scattered block is full, committing\n");
-
 
2045
#endif
1719
                ftl_remove_scattered_block(logentry);
2046
                ftl_remove_scattered_block(logentry);
1720
                logentry = ftl_allocate_log_entry(block);
2047
                logentry = ftl_allocate_log_entry(block);
1721
                if (logentry == (struct ftl_log_type*)0) return 1;
2048
                if (logentry == (struct ftl_log_type*)0)
-
 
2049
                {
-
 
2050
                    mutex_unlock(&ftl_mtx);
-
 
2051
                    return 1;
-
 
2052
                }
-
 
2053
            }
-
 
2054
            uint32_t cnt = FTL_WRITESPARE_SIZE;
-
 
2055
            if (cnt > count - i) cnt = count - i;
-
 
2056
            if (cnt > ppb - logentry->pagesused) cnt = ppb - logentry->pagesused;
-
 
2057
            if (cnt > ppb - page) cnt = ppb - page;
-
 
2058
            memset(&ftl_sparebuffer[0], 0xFF, 0x40 * cnt);
-
 
2059
            for (j = 0; j < cnt; j++)
-
 
2060
            {
-
 
2061
                ftl_sparebuffer[j].user.lpn = sector + i + j;
-
 
2062
                ftl_sparebuffer[j].user.usn = ++ftl_cxt.nextblockusn;
-
 
2063
                ftl_sparebuffer[j].user.type = 0x40;
-
 
2064
                if (logentry->pagesused + j == ppb - 1 && logentry->issequential)
-
 
2065
                    ftl_sparebuffer[j].user.type = 0x41;
1722
            }
2066
            }
1723
            memset(&ftl_sparebuffer, 0xFF, 0x40);
-
 
1724
            ftl_sparebuffer.user.lpn = sector + i;
-
 
1725
            ftl_sparebuffer.user.usn = ++ftl_cxt.nextblockusn;
-
 
1726
            ftl_sparebuffer.user.type = 0x40;
-
 
1727
            uint32_t abspage = (*logentry).scatteredvblock * ppb
2067
            uint32_t abspage = logentry->scatteredvblock * ppb
1728
                             + (*logentry).pagesused++;
2068
                             + logentry->pagesused;
-
 
2069
            logentry->pagesused += cnt;
1729
            if (ftl_vfl_write(abspage, &((uint8_t*)buffer)[i << 11],
2070
            if (ftl_vfl_write(abspage, cnt, &((uint8_t*)buffer)[i << 11],
1730
                              &ftl_sparebuffer) == 0)
2071
                              &ftl_sparebuffer[0]) == 0)
1731
            {
2072
            {
-
 
2073
                for (j = 0; j < cnt; j++)
-
 
2074
                {
1732
                if ((*logentry).pageoffsets[page] == 0xFFFF)
2075
                    if (logentry->pageoffsets[page + j] == 0xFFFF)
1733
                    (*logentry).pagescurrent++;
2076
                        logentry->pagescurrent++;
1734
                (*logentry).pageoffsets[page] = (*logentry).pagesused - 1;
2077
                    logentry->pageoffsets[page + j] = logentry->pagesused - cnt + j;
-
 
2078
                    if (logentry->pagesused - cnt + j + 1 != logentry->pagescurrent
-
 
2079
                     || logentry->pageoffsets[page + j] != page + j)
1735
                ftl_check_still_sequential(logentry, page);
2080
                        logentry->issequential = 0;
1736
                i++;
2081
                }
-
 
2082
                i += cnt;
1737
            }
2083
            }
-
 
2084
            else panicf(PANIC_FATAL, "FTL: Write error: %u %u %u!",
-
 
2085
                        (unsigned)sector, (unsigned)count, (unsigned)i);
1738
        }
2086
        }
-
 
2087
        if (logentry->pagesused == ppb) ftl_remove_scattered_block(logentry);
1739
    }
2088
    }
1740
    if (ftl_cxt.swapcounter >= 300)
2089
    if (ftl_cxt.swapcounter >= 300)
1741
    {
2090
    {
1742
        ftl_cxt.swapcounter -= 20;
2091
        ftl_cxt.swapcounter -= 20;
1743
        for (i = 0; i < 4; i++) if (ftl_swap_blocks() == 0) break;
2092
        for (i = 0; i < 4; i++) if (ftl_swap_blocks() == 0) break;
Line 1750... Line 2099...
1750
            {
2099
            {
1751
                ftl_next_ctrl_pool_page();
2100
                ftl_next_ctrl_pool_page();
1752
                ftl_save_erasectr_page(i);
2101
                ftl_save_erasectr_page(i);
1753
            }
2102
            }
1754
    }
2103
    }
-
 
2104
    mutex_unlock(&ftl_mtx);
1755
    return 0;
2105
    return 0;
1756
}
2106
}
1757
#endif
2107
#endif
1758
 
2108
 
1759
 
2109
 
1760
#ifndef FTL_READONLY
2110
#ifndef FTL_READONLY
1761
// Exposed function: Performes a sync / unmount, i.e. commits all scattered page blocks,
2111
/* Exposed function: Performes a sync / unmount,
-
 
2112
   i.e. commits all scattered page blocks,
1762
// distributes wear, and commits the FTL context.
2113
   distributes wear, and commits the FTL context. */
1763
uint32_t storage_sync()
2114
uint32_t ftl_sync(void)
1764
{
2115
{
1765
    uint32_t i;
2116
    uint32_t i;
1766
    uint32_t rc = 0;
2117
    uint32_t rc = 0;
1767
    uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
2118
    uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks;
1768
    if (ftl_cxt.clean_flag == 1) return 0;
2119
    if (ftl_cxt.clean_flag == 1) return 0;
1769
 
2120
 
-
 
2121
#ifdef FTL_TRACE
-
 
2122
    DEBUGF("FTL: Syncing\n");
-
 
2123
#endif
-
 
2124
 
1770
    if (ftl_cxt.swapcounter >= 20)
2125
    if (ftl_cxt.swapcounter >= 20)
1771
        for (i = 0; i < 4; i++)
2126
        for (i = 0; i < 4; i++)
1772
            if (ftl_swap_blocks() == 0)
2127
            if (ftl_swap_blocks() == 0)
1773
            {
2128
            {
1774
                ftl_cxt.swapcounter -= 20;
2129
                ftl_cxt.swapcounter -= 20;
Line 1780... Line 2135...
1780
        ftl_cxt.nextblockusn++;
2135
        ftl_cxt.nextblockusn++;
1781
        if (ftl_log[i].issequential == 1)
2136
        if (ftl_log[i].issequential == 1)
1782
            rc |= ftl_commit_sequential(&ftl_log[i]);
2137
            rc |= ftl_commit_sequential(&ftl_log[i]);
1783
        else rc |= ftl_commit_scattered(&ftl_log[i]);
2138
        else rc |= ftl_commit_scattered(&ftl_log[i]);
1784
    }
2139
    }
1785
    if (rc == 0)
2140
    if (rc != 0)
-
 
2141
    {
-
 
2142
        mutex_unlock(&ftl_mtx);
-
 
2143
        return 1;
-
 
2144
    }
1786
        for (i = 0; i < 5; i++)
2145
    for (i = 0; i < 5; i++)
1787
            if (ftl_commit_cxt() == 0) return 0;
2146
        if (ftl_commit_cxt() == 0)
-
 
2147
        {
-
 
2148
            mutex_unlock(&ftl_mtx);
-
 
2149
            return 0;
-
 
2150
        }
1788
            else ftl_cxt.ftlctrlpage |= ppb - 1;
2151
        else ftl_cxt.ftlctrlpage |= ppb - 1;
-
 
2152
    mutex_unlock(&ftl_mtx);
1789
    return 1;
2153
    return 1;
1790
}
2154
}
1791
#endif
2155
#endif
1792
 
2156
 
1793
 
2157
 
1794
uint32_t storage_get_sector_count()
-
 
1795
{
-
 
1796
    return (*ftl_nand_type).pagesperblock * ftl_banks * (*ftl_nand_type).userblocks;
-
 
1797
}
-
 
1798
 
-
 
1799
 
-
 
1800
/* Initializes and mounts the FTL.
2158
/* Initializes and mounts the FTL.
1801
   As long as nothing was written, you won't need to unmount it.
2159
   As long as nothing was written, you won't need to unmount it.
1802
   Before shutting down after writing something, call storage_sync(),
2160
   Before shutting down after writing something, call ftl_sync(),
1803
   which will just do nothing if everything was already clean. */
2161
   which will just do nothing if everything was already clean. */
1804
uint32_t storage_init(void)
2162
uint32_t ftl_init(void)
1805
{
2163
{
-
 
2164
    mutex_init(&ftl_mtx);
1806
    uint32_t i;
2165
    uint32_t i;
1807
    uint32_t result = 0;
2166
    uint32_t result = 0;
1808
    uint32_t foundsignature, founddevinfo, blockwiped, repaired, skip;
2167
    uint32_t foundsignature, founddevinfo, blockwiped, repaired, skip;
1809
 
-
 
1810
    if (ftl_initialized) return 0;
2168
    if (nand_device_init() != 0) //return 1;
1811
 
-
 
1812
    if (nand_init() != 0) return 1;
2169
        panicf(PANIC_FATAL, "FTL: Lowlevel NAND driver init failed!");
1813
    ftl_banks = 0;
2170
    ftl_banks = 0;
1814
    for (i = 0; i < 4; i++)
2171
    for (i = 0; i < 4; i++)
1815
        if (nand_get_device_type(i) != 0) ftl_banks = i + 1;
2172
        if (nand_get_device_type(i) != 0) ftl_banks = i + 1;
1816
    ftl_nand_type = nand_get_device_type(0);
2173
    ftl_nand_type = nand_get_device_type(0);
1817
    foundsignature = 0;
2174
    foundsignature = 0;
1818
    blockwiped = 1;
2175
    blockwiped = 1;
1819
    for (i = 0; i < (*ftl_nand_type).pagesperblock; i++)
2176
    for (i = 0; i < ftl_nand_type->pagesperblock; i++)
1820
    {
2177
    {
1821
        result = nand_read_page(0, i, ftl_buffer, (uint32_t*)0, 1, 1);
2178
        result = nand_read_page(0, i, ftl_buffer, (uint32_t*)0, 1, 1);
1822
        if ((result & 0x11F) == 0)
2179
        if ((result & 0x11F) == 0)
1823
        {
2180
        {
1824
            blockwiped = 0;
2181
            blockwiped = 0;
Line 1826... Line 2183...
1826
            foundsignature = 1;
2183
            foundsignature = 1;
1827
            break;
2184
            break;
1828
        }
2185
        }
1829
        else if ((result & 2) != 2) blockwiped = 0;
2186
        else if ((result & 2) != 2) blockwiped = 0;
1830
    }
2187
    }
-
 
2188
 
1831
    founddevinfo = ftl_has_devinfo();
2189
    founddevinfo = ftl_has_devinfo();
1832
 
2190
 
1833
    repaired = 0;
2191
    repaired = 0;
1834
    skip = 0;
2192
    skip = 0;
-
 
2193
    if (founddevinfo == 0)
1835
 
2194
    {
-
 
2195
	   	DEBUGF("FTL: No DEVICEINFO found!");
1836
    if (founddevinfo == 0) return 1;
2196
        return 1;
1837
 
2197
    }
1838
    if (foundsignature != 0 && (result & 0x11F) != 0) return 1;
2198
    if (foundsignature != 0 && (result & 0x11F) != 0)
-
 
2199
    {
-
 
2200
        DEBUGF("FTL: Problem with the signature!");
-
 
2201
        return 1;
1839
 
2202
    }
1840
    if (ftl_vfl_open() == 0)
2203
    if (ftl_vfl_open() == 0)
1841
        if (ftl_open() == 0)
2204
        if (ftl_open() == 0)
1842
        {
-
 
1843
            ftl_initialized = 1;
-
 
1844
            return 0;
2205
            return 0;
-
 
2206
 
1845
        }
2207
    DEBUGF("FTL: Initialization failed!");
1846
 
2208
 
1847
    return 1;
2209
    return 1;
1848
}
2210
}