static bool write_bmt_to_flash(u8 *dat, u8 *oob) { bool need_erase = true; MSG(INIT, "Try to write BMT\n"); MSG(INIT, "bmt_block_index = 0x%x\n", bmt_block_index); if (bmt_block_index == 0) { // if we don't have index, we don't need to erase found block as it has been erased in find_available_block() need_erase = false; MSG(INIT, "set need_erase = 0x%x\n", need_erase); if ( !(bmt_block_index = find_available_block(true)) ) { MSG(INIT, "Cannot find an available block for BMT\n"); return false; } } MSG(INIT, "Find BMT block: 0x%x\n", bmt_block_index); MSG(INIT, "need_erase = 0x%x\n", need_erase); // write bmt to flash if (need_erase) { if (!nand_erase_bmt(OFFSET(bmt_block_index))) { MSG(INIT, "BMT block erase fail, mark bad: 0x%x\n", bmt_block_index); mark_block_bad_bmt(OFFSET(bmt_block_index)); // bmt.bad_count++; bmt_block_index = 0; return write_bmt_to_flash(dat, oob); // recursive call } } if ( !nand_write_page_bmt(PAGE_ADDR(bmt_block_index), dat, oob) ) { MSG(INIT, "Write BMT data fail, need to write again\n"); mark_block_bad_bmt(OFFSET(bmt_block_index)); // bmt.bad_count++; bmt_block_index = 0; return write_bmt_to_flash(dat, oob); // recursive call } MSG(INIT, "Write BMT data to block 0x%x success\n", bmt_block_index); return true; }
static int find_available_block_reserve(int block) { int i; for (i = block + 1; i < reserve_block; i++) { if (!nand_block_bad_bmt(OFFSET(i))) { if (nand_erase_bmt(OFFSET(i))) { // MSG(INIT, "return 0x%x\n", i); return i; } else mark_block_bad_bmt(i); } } return 0; }
static bool write_bmt_to_flash(u8 *dat, u8 *oob) { bool need_erase = true; MSG("Try to write BMT\n"); if (bmt_block_index == 0) { // if we don't have index, we don't need to erase found block as it has been erased in find_available_block() need_erase = false; if ( !(bmt_block_index = find_available_block(true)) ) { MSG("Cannot find an available block for BMT\n"); return false; } } // write bmt to flash if (need_erase) { if (nand_erase_bmt(OFFSET(bmt_block_index))) { MSG("BMT block erase fail, mark bad: 0x%x\n", bmt_block_index); mark_block_bad_bmt(OFFSET(bmt_block_index), BMT_BADBLOCK_GENERATE_LATER); bmt_block_index = 0; return write_bmt_to_flash(dat, oob); // recursive call } } if ( nand_write_page_bmt(PAGE_ADDR(bmt_block_index), dat, oob) ) { MSG("Write BMT data fail \n"); mark_block_bad_bmt(OFFSET(bmt_block_index), BMT_BADBLOCK_GENERATE_LATER); bmt_block_index = 0; return write_bmt_to_flash(dat, oob); // recursive call } MSG("Write BMT to block %d success\n", bmt_block_index); return true; }
/************************************************************************* * Find an available block and erase. * * start_from_end: if true, find available block from end of flash. * * else, find from the beginning of the pool * * need_erase: if true, all unmapped blocks in the pool will be erased * *************************************************************************/ static int find_available_block(bool start_from_end) { int i; // , j; int block = system_block_count; int direction; MSG(INIT, "Try to find_available_block, pool_erase: %d\n", pool_erased); if (!pool_erased) { MSG(INIT, "Erase all un-mapped blocks in pool\n"); for (i = 0; i < bmt_block_count; i++) { if (block == bmt_block_index) { MSG(INIT, "Skip bmt block 0x%x\n", block); continue; } if (nand_block_bad_bmt(OFFSET(block + i))) { MSG(INIT, "Skip bad block 0x%x\n", block + i); continue; } if (is_block_mapped(block + i) >= 0) { MSG(INIT, "Skip mapped block 0x%x\n", block + i); continue; } if (!nand_erase_bmt(OFFSET(block + i))) { MSG(INIT, "Erase block 0x%x failed\n", block + i); mark_block_bad_bmt(OFFSET(block + i)); } } pool_erased = 1; } if (start_from_end) { block = total_block_count - 1; direction = -1; } else { block = system_block_count; direction = 1; } for (i = 0; i < bmt_block_count; i++, block += direction) { if (block == bmt_block_index) { MSG(INIT, "Skip bmt block 0x%x\n", block); continue; } if (nand_block_bad_bmt(OFFSET(block))) { MSG(INIT, "Skip bad block 0x%x\n", block); continue; } if (is_block_mapped(block) >= 0) { MSG(INIT, "Skip mapped block 0x%x\n", block); continue; } MSG(INIT, "Find block 0x%x available\n", block); return block; } return 0; }
/************************************************************************* * Find an available block and erase. * * start_from_end: if true, find available block from end of flash. * * else, find from the beginning of the pool * * need_erase: if true, all unmapped blocks in the pool will be erased * *************************************************************************/ static int find_available_block(bool start_from_end) { int i; int block = system_block_count; int direction; MSG("Try to find_available_block, pool_erase: %d\n", pool_erased); // erase all un-mapped blocks in pool when finding avaliable block if (!pool_erased) { for (i = 0; i < bmt_block_count; i++) { if ((block + i) == bmt_block_index) { MSG("Skip bmt block %d \n", block + i); continue; } if ((block + i) == bbt_block_index) { MSG("Skip bbt block %d \n", block + i); continue; } if (nand_block_bad_bmt(OFFSET(block + i), BAD_BLOCK_RAW) || nand_block_bad_bmt(OFFSET(block + i), BMT_BADBLOCK_GENERATE_LATER)) { MSG("Skip bad block %d \n", block + i); continue; } if (is_block_mapped(block + i) >= 0) { MSG("Skip mapped block %d \n", block + i); continue; } if (nand_erase_bmt(OFFSET(block + i))) { MSG("Erase block %d fail\n", block + i); mark_block_bad_bmt(OFFSET(block + i), BMT_BADBLOCK_GENERATE_LATER); } } pool_erased = 1; } if (start_from_end) { block = total_block_count - 1; direction = -1; } else { block = system_block_count; direction = 1; } for (i = 0; i < bmt_block_count; i++, block += direction) { if (block == bmt_block_index) { MSG("Skip bmt block %d \n", block); continue; } if (block == bbt_block_index) { MSG("Skip bbt block %d \n", block); continue; } if (nand_block_bad_bmt(OFFSET(block), BAD_BLOCK_RAW) || nand_block_bad_bmt(OFFSET(block), BMT_BADBLOCK_GENERATE_LATER)) { MSG("Skip bad block %d \n", block); continue; } if (is_block_mapped(block) >= 0) { MSG("Skip mapped block %d \n", block); continue; } MSG("Find block %d available\n", block); return block; } return 0; }