summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorMichael Sparmann <theseven@rockbox.org>2009-10-20 20:20:39 +0000
committerMichael Sparmann <theseven@rockbox.org>2009-10-20 20:20:39 +0000
commit1668cfa3dded5fcece8301a224402a709d956fec (patch)
tree95c963e207004e896f5d5a85f9451cb63a77a379 /firmware
parentad29c35d7b8b8bc9acc7da857bd642b1fdbf3a4c (diff)
Fixed a bunch of iPod Nano 2G FTL bugs.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23296 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c26
1 files changed, 16 insertions, 10 deletions
diff --git a/firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c b/firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c
index d6b4f1aedc..e3bdca6b30 100644
--- a/firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c
+++ b/firmware/target/arm/s5l8700/ipodnano2g/ftl-nano2g.c
@@ -334,7 +334,7 @@ union ftl_spare_data_type
};
-// Keeps track of troublesome blocks, only in memory, lost on unmount. */
+/* Keeps track of troublesome blocks, only in memory, lost on unmount. */
struct ftl_trouble_type
{
@@ -1161,24 +1161,27 @@ uint32_t ftl_erase_block(uint32_t block)
uint32_t ftl_allocate_pool_block(void)
{
uint32_t i;
- uint32_t erasectr = 0xFFFFFFFF, bestidx = 0, block;
+ uint32_t erasectr = 0xFFFFFFFF, bestidx = 0xFFFFFFFF, block;
for (i = 0; i < ftl_cxt.freecount; i++)
{
uint32_t idx = ftl_cxt.nextfreeidx + i;
if (idx >= 0x14) idx -= 0x14;
+ if (!ftl_cxt.blockpool[idx]) continue;
if (ftl_erasectr[ftl_cxt.blockpool[idx]] < erasectr)
{
erasectr = ftl_erasectr[ftl_cxt.blockpool[idx]];
bestidx = idx;
}
}
+ if (bestidx == 0xFFFFFFFF) panicf("Out of pool blocks!");
block = ftl_cxt.blockpool[bestidx];
if (bestidx != ftl_cxt.nextfreeidx)
{
ftl_cxt.blockpool[bestidx] = ftl_cxt.blockpool[ftl_cxt.nextfreeidx];
ftl_cxt.blockpool[ftl_cxt.nextfreeidx] = block;
}
- if (block > (*ftl_nand_type).userblocks) return 0;
+ if (block > (uint32_t)(*ftl_nand_type).userblocks + 0x17)
+ panicf("FTL: Bad block number in pool: %u", (unsigned)block);
if (ftl_erase_block(block) != 0) return 0;
if (++ftl_cxt.nextfreeidx == 0x14) ftl_cxt.nextfreeidx = 0;
ftl_cxt.freecount--;
@@ -1191,7 +1194,9 @@ uint32_t ftl_allocate_pool_block(void)
/* Releases a vBlock back into the pool */
void ftl_release_pool_block(uint32_t block)
{
- if (block >= (uint32_t)(*ftl_nand_type).userblocks + 0x17) return;
+ if (!block) panicf("FTL: Tried to put block 0 into the pool!");
+ if (block >= (uint32_t)(*ftl_nand_type).userblocks + 0x17)
+ panicf("FTL: Tried to release block %u", (unsigned)block);
uint32_t idx = ftl_cxt.nextfreeidx + ftl_cxt.freecount++;
if (idx >= 0x14) idx -= 0x14;
ftl_cxt.blockpool[idx] = block;
@@ -1370,10 +1375,11 @@ uint32_t ftl_compact_scattered(struct ftl_log_type* entry)
for (i = 0; i < 4; i++)
{
uint32_t block = ftl_allocate_pool_block();
+ if (block == 0) return 1;
(*entry).pagesused = 0;
(*entry).pagescurrent = 0;
(*entry).issequential = 1;
- if (block == 0) return 1;
+ (*entry).scatteredvblock = block;
error = 0;
for (j = 0; j < ppb; j++)
if ((*entry).pageoffsets[j] != 0xFFFF)
@@ -1430,7 +1436,7 @@ uint32_t ftl_commit_scattered(struct ftl_log_type* entry)
/* Fills the rest of a scattered page block that was actually written
sequentially until now, in order to be able to save a block erase by
committing it without needing to copy it again.
- If this fails for whatever reason, it will be committed the usual way. */
+ If this fails for whichever reason, it will be committed the usual way. */
uint32_t ftl_commit_sequential(struct ftl_log_type* entry)
{
uint32_t ppb = (*ftl_nand_type).pagesperblock * ftl_banks;
@@ -1534,7 +1540,7 @@ struct ftl_log_type* ftl_allocate_log_entry(uint32_t block)
if (entry == (struct ftl_log_type*)0)
{
- if (ftl_cxt.freecount == 3)
+ while (ftl_cxt.freecount <= 3)
if (ftl_remove_scattered_block((struct ftl_log_type*)0) != 0)
return (struct ftl_log_type*)0;
entry = ftl_log;
@@ -1547,8 +1553,8 @@ struct ftl_log_type* ftl_allocate_log_entry(uint32_t block)
}
}
- (*entry).logicalvblock = block;
ftl_init_log_entry(entry);
+ (*entry).logicalvblock = block;
(*entry).usn = ftl_cxt.nextblockusn - 1;
return entry;
@@ -1815,8 +1821,8 @@ uint32_t ftl_sync(void)
#endif
-/* Initializes and mounts the FTL. As long as nothing was written,
- you won't need to unmount it.
+/* Initializes and mounts the FTL.
+ As long as nothing was written, you won't need to unmount it.
Before shutting down after writing something, call ftl_sync(),
which will just do nothing if everything was already clean. */
uint32_t ftl_init(void)