Subversion Repositories freemyipod

Rev

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

Rev 249 Rev 251
Line 362... Line 362...
362
const struct nand_device_info_type* ftl_nand_type;
362
const struct nand_device_info_type* ftl_nand_type;
363
 
363
 
364
/* Number of banks we detected a chip on */
364
/* Number of banks we detected a chip on */
365
uint32_t ftl_banks;
365
uint32_t ftl_banks;
366
 
366
 
-
 
367
/* Number of banks we detected a chip on (power of two) */
-
 
368
uint32_t ftl_banks_exponent;
-
 
369
 
367
/* Block map, used vor pBlock to vBlock mapping */
370
/* Block map, used vor pBlock to vBlock mapping */
368
static uint16_t ftl_map[0x2000] CACHEALIGN_ATTR;
371
static uint16_t ftl_map[0x2000] CACHEALIGN_ATTR;
369
 
372
 
370
/* VFL context for each bank */
373
/* VFL context for each bank */
371
static struct ftl_vfl_cxt_type ftl_vfl_cxt[4];
374
static struct ftl_vfl_cxt_type ftl_vfl_cxt[4];
Line 431... Line 434...
431
 
434
 
432
 
435
 
433
static struct mutex ftl_mtx;
436
static struct mutex ftl_mtx;
434
bool ftl_initialized = false;
437
bool ftl_initialized = false;
435
 
438
 
-
 
439
/* Pages per hyperblock (ftl_nand_type->pagesperblock * ftl_banks) */
-
 
440
static uint32_t ppb;
-
 
441
 
-
 
442
/* Pages per hyperblock (power of two) */
-
 
443
static uint32_t ppb_exponent;
-
 
444
 
-
 
445
/* Reserved hyperblocks (ftl_nand_type->blocks
-
 
446
                       - ftl_nand_type->userblocks - 0x17) */
-
 
447
static uint32_t syshyperblocks;
436
 
448
 
437
 
449
 
438
/* Finds a device info page for the specified bank and returns its number.
450
/* Finds a device info page for the specified bank and returns its number.
439
   Used to check if one is present, and to read the lowlevel BBT. */
451
   Used to check if one is present, and to read the lowlevel BBT. */
440
static uint32_t ftl_find_devinfo(uint32_t bank) INITCODE_ATTR;
452
static uint32_t ftl_find_devinfo(uint32_t bank) INITCODE_ATTR;
Line 851... Line 863...
851
{
863
{
852
#ifdef VFL_TRACE
864
#ifdef VFL_TRACE
853
    DEBUGF("FTL: VFL: Reading page %d", vpage);
865
    DEBUGF("FTL: VFL: Reading page %d", vpage);
854
#endif
866
#endif
855
 
867
 
856
    uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks;
-
 
857
    uint32_t syshyperblocks = ftl_nand_type->blocks
-
 
858
                            - ftl_nand_type->userblocks - 0x17;
-
 
859
    uint32_t abspage = vpage + ppb * syshyperblocks;
868
    uint32_t abspage = vpage + ppb * syshyperblocks;
860
    if (abspage >= ftl_nand_type->blocks * ppb || abspage < ppb)
869
    if (abspage >= ftl_nand_type->blocks * ppb || abspage < ppb)
861
    {
870
    {
862
        DEBUGF("FTL: Trying to read out-of-bounds vPage %u", (unsigned)vpage);
871
        DEBUGF("FTL: Trying to read out-of-bounds vPage %u", (unsigned)vpage);
863
        return 4;
872
        return 4;
864
    }
873
    }
865
 
874
 
866
    uint32_t bank = abspage % ftl_banks;
875
    uint32_t bank = abspage & (ftl_banks - 1);
867
    uint32_t block = abspage / (ftl_nand_type->pagesperblock * ftl_banks);
876
    uint32_t block = abspage >> ppb_exponent;
868
    uint32_t page = (abspage / ftl_banks) % ftl_nand_type->pagesperblock;
877
    uint32_t page = (abspage >> ftl_banks_exponent) & ((1 << ftl_nand_type->blocksizeexponent) - 1);
869
    uint32_t physblock = ftl_vfl_get_physical_block(bank, block);
878
    uint32_t physblock = ftl_vfl_get_physical_block(bank, block);
870
    uint32_t physpage = physblock * ftl_nand_type->pagesperblock + page;
879
    uint32_t physpage = physblock * ftl_nand_type->pagesperblock + page;
871
 
880
 
872
    uint32_t ret = nand_read_page(bank, physpage, buffer,
881
    uint32_t ret = nand_read_page(bank, physpage, buffer,
873
                                  sparebuffer, 1, checkempty);
882
                                  sparebuffer, 1, checkempty);
Line 900... Line 909...
900
#ifdef VFL_TRACE
909
#ifdef VFL_TRACE
901
    DEBUGF("FTL: VFL: Fast reading page %d on all banks", vpage);
910
    DEBUGF("FTL: VFL: Fast reading page %d on all banks", vpage);
902
#endif
911
#endif
903
 
912
 
904
    uint32_t i, rc = 0;
913
    uint32_t i, rc = 0;
905
    uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks;
-
 
906
    uint32_t syshyperblocks = ftl_nand_type->blocks
-
 
907
                            - ftl_nand_type->userblocks - 0x17;
-
 
908
    uint32_t abspage = vpage + ppb * syshyperblocks;
914
    uint32_t abspage = vpage + ppb * syshyperblocks;
909
    if (abspage + ftl_banks - 1 >= ftl_nand_type->blocks * ppb || abspage < ppb)
915
    if (abspage + ftl_banks - 1 >= ftl_nand_type->blocks * ppb || abspage < ppb)
910
    {
916
    {
911
        DEBUGF("FTL: Trying to read out-of-bounds vPage %u", (unsigned)vpage);
917
        DEBUGF("FTL: Trying to read out-of-bounds vPage %u", (unsigned)vpage);
912
        return 4;
918
        return 4;
913
    }
919
    }
914
 
920
 
915
    uint32_t bank = abspage % ftl_banks;
921
    uint32_t bank = abspage & (ftl_banks - 1);
916
    uint32_t block = abspage / (ftl_nand_type->pagesperblock * ftl_banks);
922
    uint32_t block = abspage >> ppb_exponent;
917
    uint32_t page = (abspage / ftl_banks) % ftl_nand_type->pagesperblock;
923
    uint32_t page = (abspage >> ftl_banks_exponent) & ((1 << ftl_nand_type->blocksizeexponent) - 1);
918
    uint32_t remapped = 0;
924
    uint32_t remapped = 0;
919
    for (i = 0; i < ftl_banks; i++)
925
    for (i = 0; i < ftl_banks; i++)
920
        if (ftl_vfl_get_physical_block(i, block) != block)
926
        if (ftl_vfl_get_physical_block(i, block) != block)
921
            remapped = 1;
927
            remapped = 1;
922
    if (bank || remapped)
928
    if (bank || remapped)
Line 976... Line 982...
976
    uint32_t i, j;
982
    uint32_t i, j;
977
#ifdef VFL_TRACE
983
#ifdef VFL_TRACE
978
    DEBUGF("FTL: VFL: Writing page %d", vpage);
984
    DEBUGF("FTL: VFL: Writing page %d", vpage);
979
#endif
985
#endif
980
 
986
 
981
    uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks;
-
 
982
    uint32_t syshyperblocks = ftl_nand_type->blocks
-
 
983
                            - ftl_nand_type->userblocks - 0x17;
-
 
984
    uint32_t abspage = vpage + ppb * syshyperblocks;
987
    uint32_t abspage = vpage + ppb * syshyperblocks;
985
    if (abspage + count > ftl_nand_type->blocks * ppb || abspage < ppb)
988
    if (abspage + count > ftl_nand_type->blocks * ppb || abspage < ppb)
986
    {
989
    {
987
        DEBUGF("FTL: Trying to write out-of-bounds vPage %u",
990
        DEBUGF("FTL: Trying to write out-of-bounds vPage %u",
988
               (unsigned)vpage);
991
               (unsigned)vpage);
Line 1063... Line 1066...
1063
    /* Temporary BBT buffer if we're readonly,
1066
    /* Temporary BBT buffer if we're readonly,
1064
       as we won't need it again after mounting */
1067
       as we won't need it again after mounting */
1065
    uint8_t bbt[0x410];
1068
    uint8_t bbt[0x410];
1066
#endif
1069
#endif
1067
 
1070
 
1068
    uint32_t syshyperblocks = ftl_nand_type->blocks
-
 
1069
                            - ftl_nand_type->userblocks - 0x18;
-
 
1070
 
-
 
1071
    for (i = 0; i < ftl_banks; i++)
1071
    for (i = 0; i < ftl_banks; i++)
1072
#ifndef FTL_READONLY
1072
#ifndef FTL_READONLY
1073
        if (ftl_load_bbt(i, ftl_bbt[i]) == 0)
1073
        if (ftl_load_bbt(i, ftl_bbt[i]) == 0)
1074
#else
1074
#else
1075
        if (ftl_load_bbt(i, bbt) == 0)
1075
        if (ftl_load_bbt(i, bbt) == 0)
Line 1150... Line 1150...
1150
static uint32_t ftl_open(void) INITCODE_ATTR;
1150
static uint32_t ftl_open(void) INITCODE_ATTR;
1151
static uint32_t ftl_open()
1151
static uint32_t ftl_open()
1152
{
1152
{
1153
    uint32_t i;
1153
    uint32_t i;
1154
    uint32_t ret;
1154
    uint32_t ret;
1155
    uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks;
-
 
1156
    struct ftl_vfl_cxt_type* cxt = ftl_vfl_get_newest_cxt();
1155
    struct ftl_vfl_cxt_type* cxt = ftl_vfl_get_newest_cxt();
1157
 
1156
 
1158
    uint32_t ftlcxtblock = 0xffffffff;
1157
    uint32_t ftlcxtblock = 0xffffffff;
1159
    uint32_t minusn = 0xffffffff;
1158
    uint32_t minusn = 0xffffffff;
1160
    for (i = 0; i < 3; i++)
1159
    for (i = 0; i < 3; i++)
Line 1314... Line 1313...
1314
 
1313
 
1315
/* Exposed function: Read highlevel sectors */
1314
/* Exposed function: Read highlevel sectors */
1316
uint32_t ftl_read(uint32_t sector, uint32_t count, void* buffer)
1315
uint32_t ftl_read(uint32_t sector, uint32_t count, void* buffer)
1317
{
1316
{
1318
    uint32_t i, j;
1317
    uint32_t i, j;
1319
    uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks;
-
 
1320
    uint32_t error = 0;
1318
    uint32_t error = 0;
1321
 
1319
 
1322
    if (!ftl_initialized) return -1;
1320
    if (!ftl_initialized) return -1;
1323
 
1321
 
1324
#ifdef FTL_TRACE
1322
#ifdef FTL_TRACE
Line 1569... Line 1567...
1569
/* Increments ftl_cxt.ftlctrlpage to the next available FTL context page,
1567
/* Increments ftl_cxt.ftlctrlpage to the next available FTL context page,
1570
   allocating a new context block if neccessary. */
1568
   allocating a new context block if neccessary. */
1571
static uint32_t ftl_next_ctrl_pool_page(void)
1569
static uint32_t ftl_next_ctrl_pool_page(void)
1572
{
1570
{
1573
    uint32_t i;
1571
    uint32_t i;
1574
    uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks;
-
 
1575
    if (++ftl_cxt.ftlctrlpage % ppb != 0) return 0;
1572
    if (++ftl_cxt.ftlctrlpage % ppb != 0) return 0;
1576
    for (i = 0; i < 3; i++)
1573
    for (i = 0; i < 3; i++)
1577
        if ((ftl_cxt.ftlctrlblocks[i] + 1) * ppb == ftl_cxt.ftlctrlpage)
1574
        if ((ftl_cxt.ftlctrlblocks[i] + 1) * ppb == ftl_cxt.ftlctrlpage)
1578
            break;
1575
            break;
1579
    i = (i + 1) % 3;
1576
    i = (i + 1) % 3;
Line 1608... Line 1605...
1608
#ifndef FTL_READONLY
1605
#ifndef FTL_READONLY
1609
/* Copies a vPage from one location to another */
1606
/* Copies a vPage from one location to another */
1610
static uint32_t ftl_copy_page(uint32_t source, uint32_t destination,
1607
static uint32_t ftl_copy_page(uint32_t source, uint32_t destination,
1611
                              uint32_t lpn, uint32_t type)
1608
                              uint32_t lpn, uint32_t type)
1612
{
1609
{
1613
    uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks;
-
 
1614
    uint32_t rc = ftl_vfl_read(source, ftl_copybuffer[0],
1610
    uint32_t rc = ftl_vfl_read(source, ftl_copybuffer[0],
1615
                               &ftl_copyspare[0], 1, 1) & 0x11F;
1611
                               &ftl_copyspare[0], 1, 1) & 0x11F;
1616
    memset(&ftl_copyspare[0], 0xFF, 0x40);
1612
    memset(&ftl_copyspare[0], 0xFF, 0x40);
1617
    ftl_copyspare[0].user.lpn = lpn;
1613
    ftl_copyspare[0].user.lpn = lpn;
1618
    ftl_copyspare[0].user.usn = ++ftl_cxt.nextblockusn;
1614
    ftl_copyspare[0].user.usn = ++ftl_cxt.nextblockusn;
Line 1629... Line 1625...
1629
#ifndef FTL_READONLY
1625
#ifndef FTL_READONLY
1630
/* Copies a pBlock to a vBlock */
1626
/* Copies a pBlock to a vBlock */
1631
static uint32_t ftl_copy_block(uint32_t source, uint32_t destination)
1627
static uint32_t ftl_copy_block(uint32_t source, uint32_t destination)
1632
{
1628
{
1633
    uint32_t i, j;
1629
    uint32_t i, j;
1634
    uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks;
-
 
1635
    uint32_t error = 0;
1630
    uint32_t error = 0;
1636
    ftl_cxt.nextblockusn++;
1631
    ftl_cxt.nextblockusn++;
1637
    for (i = 0; i < ppb; i += FTL_COPYBUF_SIZE)
1632
    for (i = 0; i < ppb; i += FTL_COPYBUF_SIZE)
1638
    {
1633
    {
1639
        uint32_t rc = ftl_read(source * ppb + i,
1634
        uint32_t rc = ftl_read(source * ppb + i,
Line 1688... Line 1683...
1688
   removed because it is full, but less than half of the pages in there are
1683
   removed because it is full, but less than half of the pages in there are
1689
   still in use and rest is just filled with old crap. */
1684
   still in use and rest is just filled with old crap. */
1690
static uint32_t ftl_compact_scattered(struct ftl_log_type* entry)
1685
static uint32_t ftl_compact_scattered(struct ftl_log_type* entry)
1691
{
1686
{
1692
    uint32_t i, j;
1687
    uint32_t i, j;
1693
    uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks;
-
 
1694
    uint32_t error;
1688
    uint32_t error;
1695
    struct ftl_log_type backup;
1689
    struct ftl_log_type backup;
1696
    if (entry->pagescurrent == 0)
1690
    if (entry->pagescurrent == 0)
1697
    {
1691
    {
1698
        ftl_release_pool_block(entry->scatteredvblock);
1692
        ftl_release_pool_block(entry->scatteredvblock);
Line 1772... Line 1766...
1772
   committing it without needing to copy it again.
1766
   committing it without needing to copy it again.
1773
   If this fails for whichever reason, it will be committed the usual way. */
1767
   If this fails for whichever reason, it will be committed the usual way. */
1774
static uint32_t ftl_commit_sequential(struct ftl_log_type* entry)
1768
static uint32_t ftl_commit_sequential(struct ftl_log_type* entry)
1775
{
1769
{
1776
    uint32_t i;
1770
    uint32_t i;
1777
    uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks;
-
 
1778
 
1771
 
1779
    if (entry->issequential != 1
1772
    if (entry->issequential != 1
1780
     || entry->pagescurrent != entry->pagesused)
1773
     || entry->pagescurrent != entry->pagesused)
1781
        return 1;
1774
        return 1;
1782
 
1775
 
Line 1818... Line 1811...
1818
   whatever way seems most appropriate. Else, the oldest scattered page block
1811
   whatever way seems most appropriate. Else, the oldest scattered page block
1819
   will be freed by committing it. */
1812
   will be freed by committing it. */
1820
static uint32_t ftl_remove_scattered_block(struct ftl_log_type* entry)
1813
static uint32_t ftl_remove_scattered_block(struct ftl_log_type* entry)
1821
{
1814
{
1822
    uint32_t i;
1815
    uint32_t i;
1823
    uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks;
-
 
1824
    uint32_t age = 0xFFFFFFFF, used = 0;
1816
    uint32_t age = 0xFFFFFFFF, used = 0;
1825
    if (entry == NULL)
1817
    if (entry == NULL)
1826
    {
1818
    {
1827
        for (i = 0; i < 0x11; i++)
1819
        for (i = 0; i < 0x11; i++)
1828
        {
1820
        {
Line 1915... Line 1907...
1915
#ifndef FTL_READONLY
1907
#ifndef FTL_READONLY
1916
/* Commits the FTL block map, erase counters, and context to flash */
1908
/* Commits the FTL block map, erase counters, and context to flash */
1917
static uint32_t ftl_commit_cxt(void)
1909
static uint32_t ftl_commit_cxt(void)
1918
{
1910
{
1919
    uint32_t i;
1911
    uint32_t i;
1920
    uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks;
-
 
1921
    uint32_t mappages = (ftl_nand_type->userblocks + 0x3ff) >> 10;
1912
    uint32_t mappages = (ftl_nand_type->userblocks + 0x3ff) >> 10;
1922
    uint32_t ctrpages = (ftl_nand_type->userblocks + 23 + 0x3ff) >> 10;
1913
    uint32_t ctrpages = (ftl_nand_type->userblocks + 23 + 0x3ff) >> 10;
1923
    uint32_t endpage = ftl_cxt.ftlctrlpage + mappages + ctrpages + 1;
1914
    uint32_t endpage = ftl_cxt.ftlctrlpage + mappages + ctrpages + 1;
1924
    DEBUGF("FTL: Committing context");
1915
    DEBUGF("FTL: Committing context");
1925
    if (endpage >= (ftl_cxt.ftlctrlpage / ppb + 1) * ppb)
1916
    if (endpage >= (ftl_cxt.ftlctrlpage / ppb + 1) * ppb)
Line 2000... Line 1991...
2000
#ifndef FTL_READONLY
1991
#ifndef FTL_READONLY
2001
/* Exposed function: Write highlevel sectors */
1992
/* Exposed function: Write highlevel sectors */
2002
uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer)
1993
uint32_t ftl_write(uint32_t sector, uint32_t count, const void* buffer)
2003
{
1994
{
2004
    uint32_t i, j, k;
1995
    uint32_t i, j, k;
2005
    uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks;
-
 
2006
 
1996
 
2007
    if (!ftl_initialized) return -1;
1997
    if (!ftl_initialized) return -1;
2008
 
1998
 
2009
#ifdef FTL_TRACE
1999
#ifdef FTL_TRACE
2010
    DEBUGF("FTL: Writing %d sectors starting at %d", count, sector);
2000
    DEBUGF("FTL: Writing %d sectors starting at %d", count, sector);
Line 2195... Line 2185...
2195
   distributes wear, and commits the FTL context. */
2185
   distributes wear, and commits the FTL context. */
2196
uint32_t ftl_sync(void)
2186
uint32_t ftl_sync(void)
2197
{
2187
{
2198
    uint32_t i;
2188
    uint32_t i;
2199
    uint32_t rc = 0;
2189
    uint32_t rc = 0;
2200
    uint32_t ppb = ftl_nand_type->pagesperblock * ftl_banks;
-
 
2201
 
-
 
2202
    if (!ftl_initialized) return 0;
2190
    if (!ftl_initialized) return 0;
2203
 
2191
 
2204
    if (ftl_cxt.clean_flag == 1) return 0;
2192
    if (ftl_cxt.clean_flag == 1) return 0;
2205
 
2193
 
2206
    mutex_lock(&ftl_mtx, TIMEOUT_BLOCK);
2194
    mutex_lock(&ftl_mtx, TIMEOUT_BLOCK);
Line 2589... Line 2577...
2589
        panicf(PANIC_KILLTHREAD, "FTL: Lowlevel NAND driver init failed: %d", rc);
2577
        panicf(PANIC_KILLTHREAD, "FTL: Lowlevel NAND driver init failed: %d", rc);
2590
    ftl_banks = 0;
2578
    ftl_banks = 0;
2591
    for (i = 0; i < 4; i++)
2579
    for (i = 0; i < 4; i++)
2592
        if (nand_get_device_type(i) != 0) ftl_banks = i + 1;
2580
        if (nand_get_device_type(i) != 0) ftl_banks = i + 1;
2593
    ftl_nand_type = nand_get_device_type(0);
2581
    ftl_nand_type = nand_get_device_type(0);
-
 
2582
	ftl_banks_exponent = ftl_banks == 4 ? 2 : ftl_banks == 2 ? 1 : 0;
-
 
2583
	ppb_exponent = ftl_nand_type->blocksizeexponent + ftl_banks_exponent;
-
 
2584
    ppb = (1 << ppb_exponent);
-
 
2585
    syshyperblocks = ftl_nand_type->blocks - ftl_nand_type->userblocks - 0x17;
2594
 
2586
 
2595
    if (!ftl_has_devinfo())
2587
    if (!ftl_has_devinfo())
2596
    {
2588
    {
2597
           DEBUGF("FTL: No DEVICEINFO found!");
2589
           DEBUGF("FTL: No DEVICEINFO found!");
2598
        return -1;
2590
        return -1;