mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-12-10 13:45:10 -05:00
Fix numerous non-critical iPod Nano 2G FTL bugs
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@24999 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
b8eb44d7db
commit
aadecdd77e
2 changed files with 22 additions and 18 deletions
|
|
@ -113,19 +113,19 @@ struct ftl_cxt_type
|
||||||
/* Count of currently free pages in the block pool */
|
/* Count of currently free pages in the block pool */
|
||||||
uint16_t freecount;
|
uint16_t freecount;
|
||||||
|
|
||||||
/* Index to the first free block in the blockpool ring buffer */
|
/* Index to the first free hyperblock in the blockpool ring buffer */
|
||||||
uint16_t nextfreeidx;
|
uint16_t nextfreeidx;
|
||||||
|
|
||||||
/* This is a counter that is used to better distribute block
|
/* This is a counter that is used to better distribute block
|
||||||
wear. It is incremented on every block erase, and if it
|
wear. It is incremented on every block erase, and if it
|
||||||
gets too high (300 on writes, 20 on sync), the most and
|
gets too high (300 on writes, 20 on sync), the most and
|
||||||
least worn block will be swapped (inferring an additional
|
least worn hyperblock will be swapped (causing an additional
|
||||||
block write) and the counter will be decreased by 20. */
|
block write) and the counter will be decreased by 20. */
|
||||||
uint16_t swapcounter;
|
uint16_t swapcounter;
|
||||||
|
|
||||||
/* Ring buffer of currently free blocks. nextfreeidx is the
|
/* Ring buffer of currently free hyperblocks. nextfreeidx is the
|
||||||
index to freecount free ones, the other ones are currently
|
index to freecount free ones, the other ones are currently
|
||||||
allocated for scattered page blocks. */
|
allocated for scattered page hyperblocks. */
|
||||||
uint16_t blockpool[0x14];
|
uint16_t blockpool[0x14];
|
||||||
|
|
||||||
/* Alignment to 32 bits */
|
/* Alignment to 32 bits */
|
||||||
|
|
@ -153,7 +153,7 @@ struct ftl_cxt_type
|
||||||
uint32_t ftl_log_ptr;
|
uint32_t ftl_log_ptr;
|
||||||
|
|
||||||
/* Flag used to indicate that some erase counter pages should be committed
|
/* Flag used to indicate that some erase counter pages should be committed
|
||||||
as they were changed more than 100 times since the last commit. */
|
because they were changed more than 100 times since the last commit. */
|
||||||
uint32_t erasedirty;
|
uint32_t erasedirty;
|
||||||
|
|
||||||
/* Seems to be unused */
|
/* Seems to be unused */
|
||||||
|
|
@ -203,7 +203,7 @@ typedef struct ftl_vfl_cxt_type
|
||||||
into vflcxtblocks. */
|
into vflcxtblocks. */
|
||||||
uint16_t activecxtblock;
|
uint16_t activecxtblock;
|
||||||
|
|
||||||
/* Number of the first free page in the active FTL context block */
|
/* Number of the first free page in the active VFL context block */
|
||||||
uint16_t nextcxtpage;
|
uint16_t nextcxtpage;
|
||||||
|
|
||||||
/* Seems to be unused */
|
/* Seems to be unused */
|
||||||
|
|
@ -270,7 +270,8 @@ union ftl_spare_data_type
|
||||||
/* Seems to be unused */
|
/* Seems to be unused */
|
||||||
uint8_t field_8;
|
uint8_t field_8;
|
||||||
|
|
||||||
/* Type field, 0x40 (data page) or 0x41 (last data page of block) */
|
/* Type field, 0x40 (data page) or 0x41
|
||||||
|
(last data page of hyperblock) */
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
|
|
||||||
/* ECC mark, usually 0xFF. If an error occurred while reading the
|
/* ECC mark, usually 0xFF. If an error occurred while reading the
|
||||||
|
|
@ -379,7 +380,7 @@ union ftl_spare_data_type ftl_sparebuffer __attribute__((aligned(16)));
|
||||||
/* Lowlevel BBT for each bank */
|
/* Lowlevel BBT for each bank */
|
||||||
uint8_t ftl_bbt[4][0x410];
|
uint8_t ftl_bbt[4][0x410];
|
||||||
|
|
||||||
/* Erase countes for the vBlocks */
|
/* Erase counters for the vBlocks */
|
||||||
uint16_t ftl_erasectr[0x2000];
|
uint16_t ftl_erasectr[0x2000];
|
||||||
|
|
||||||
/* Used by ftl_log */
|
/* Used by ftl_log */
|
||||||
|
|
@ -462,8 +463,8 @@ uint32_t ftl_load_bbt(uint32_t bank, uint8_t* bbt)
|
||||||
if (memcmp(&ftl_buffer[0x18], "BBT", 4) != 0) return 1;
|
if (memcmp(&ftl_buffer[0x18], "BBT", 4) != 0) return 1;
|
||||||
unk1 = ((uint16_t*)ftl_buffer)[0x10];
|
unk1 = ((uint16_t*)ftl_buffer)[0x10];
|
||||||
unk2 = ((uint16_t*)ftl_buffer)[0x11];
|
unk2 = ((uint16_t*)ftl_buffer)[0x11];
|
||||||
unk3 = ((uint16_t*)ftl_buffer)[((uint32_t*)ftl_buffer)[4] * 0xC + 10]
|
unk3 = ((uint16_t*)ftl_buffer)[((uint32_t*)ftl_buffer)[4] * 6 + 10]
|
||||||
+ ((uint16_t*)ftl_buffer)[((uint32_t*)ftl_buffer)[4] * 0xC + 11];
|
+ ((uint16_t*)ftl_buffer)[((uint32_t*)ftl_buffer)[4] * 6 + 11];
|
||||||
for (i = 0; i < unk1; i++)
|
for (i = 0; i < unk1; i++)
|
||||||
{
|
{
|
||||||
for (j = 0; ; j++)
|
for (j = 0; ; j++)
|
||||||
|
|
@ -976,16 +977,16 @@ uint32_t ftl_open(void)
|
||||||
struct ftl_vfl_cxt_type* cxt = ftl_vfl_get_newest_cxt();
|
struct ftl_vfl_cxt_type* cxt = ftl_vfl_get_newest_cxt();
|
||||||
|
|
||||||
uint32_t ftlcxtblock = 0xffffffff;
|
uint32_t ftlcxtblock = 0xffffffff;
|
||||||
uint32_t minlpn = 0xffffffff;
|
uint32_t minusn = 0xffffffff;
|
||||||
for (i = 0; i < 3; i++)
|
for (i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
ret = ftl_vfl_read(ppb * (*cxt).ftlctrlblocks[i],
|
ret = ftl_vfl_read(ppb * (*cxt).ftlctrlblocks[i],
|
||||||
ftl_buffer, &ftl_sparebuffer, 1, 0);
|
ftl_buffer, &ftl_sparebuffer, 1, 0);
|
||||||
if ((ret &= 0x11F) != 0) continue;
|
if ((ret &= 0x11F) != 0) continue;
|
||||||
if (ftl_sparebuffer.user.type - 0x43 > 4) continue;
|
if (ftl_sparebuffer.meta.type - 0x43 > 4) continue;
|
||||||
if (ftlcxtblock != 0xffffffff && ftl_sparebuffer.user.lpn >= minlpn)
|
if (ftlcxtblock != 0xffffffff && ftl_sparebuffer.meta.usn >= minusn)
|
||||||
continue;
|
continue;
|
||||||
minlpn = ftl_sparebuffer.user.lpn;
|
minusn = ftl_sparebuffer.meta.usn;
|
||||||
ftlcxtblock = (*cxt).ftlctrlblocks[i];
|
ftlcxtblock = (*cxt).ftlctrlblocks[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -998,7 +999,7 @@ uint32_t ftl_open(void)
|
||||||
ret = ftl_vfl_read(ppb * ftlcxtblock + i,
|
ret = ftl_vfl_read(ppb * ftlcxtblock + i,
|
||||||
ftl_buffer, &ftl_sparebuffer, 1, 0);
|
ftl_buffer, &ftl_sparebuffer, 1, 0);
|
||||||
if ((ret & 0x11F) != 0) continue;
|
if ((ret & 0x11F) != 0) continue;
|
||||||
else if (ftl_sparebuffer.user.type == 0x43)
|
else if (ftl_sparebuffer.meta.type == 0x43)
|
||||||
{
|
{
|
||||||
memcpy(&ftl_cxt, ftl_buffer, 0x28C);
|
memcpy(&ftl_cxt, ftl_buffer, 0x28C);
|
||||||
ftlcxtfound = 1;
|
ftlcxtfound = 1;
|
||||||
|
|
|
||||||
|
|
@ -406,9 +406,12 @@ uint32_t nand_read_page(uint32_t bank, uint32_t page, void* databuffer,
|
||||||
return nand_unlock(rc);
|
return nand_unlock(rc);
|
||||||
}
|
}
|
||||||
if (nand_transfer_data(bank, 0, spare, 0x40)) return nand_unlock(1);
|
if (nand_transfer_data(bank, 0, spare, 0x40)) return nand_unlock(1);
|
||||||
memcpy(nand_ecc, &spare[0xC], 0x28);
|
if (databuffer)
|
||||||
rc |= (ecc_decode(3, data, nand_ecc) & 0xF) << 4;
|
{
|
||||||
if (databuffer && data != databuffer) memcpy(databuffer, data, 0x800);
|
memcpy(nand_ecc, &spare[0xC], 0x28);
|
||||||
|
rc |= (ecc_decode(3, data, nand_ecc) & 0xF) << 4;
|
||||||
|
if (data != databuffer) memcpy(databuffer, data, 0x800);
|
||||||
|
}
|
||||||
memset(nand_ctrl, 0xFF, 0x200);
|
memset(nand_ctrl, 0xFF, 0x200);
|
||||||
memcpy(nand_ctrl, spare, 0xC);
|
memcpy(nand_ctrl, spare, 0xC);
|
||||||
memcpy(nand_ecc, &spare[0x34], 0xC);
|
memcpy(nand_ecc, &spare[0x34], 0xC);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue