Esempio n. 1
0
static error_t vsvfl_store_vfl_cxt(vfl_vsvfl_device_t *_vfl, uint32_t _ce) {
	if(_ce >= _vfl->geometry.num_ce)
		system_panic("vfl: Can't store VFLCxt on non-existent CE\r\n");

	vfl_vsvfl_context_t *curVFLCxt = &_vfl->contexts[_ce];
	if(curVFLCxt->usn_page + 8 > _vfl->geometry.pages_per_block || FAILED(vsvfl_write_vfl_cxt_to_flash(_vfl, _ce))) {
		int startBlock = curVFLCxt->usn_block;
		int nextBlock = (curVFLCxt->usn_block + 1) % 4;
		while(startBlock != nextBlock) {
			if(curVFLCxt->vfl_context_block[nextBlock] != 0xFFFF) {
				int fail = 0;
				int i;
				for (i = 0; i < 4; i++) {
					uint32_t bankStart = (curVFLCxt->vfl_context_block[nextBlock] / _vfl->geometry.blocks_per_bank) * _vfl->geometry.bank_address_space;
					uint32_t blockOffset = curVFLCxt->vfl_context_block[nextBlock] % _vfl->geometry.blocks_per_bank;
					int status = nand_device_erase_single_block(_vfl->device, _ce, bankStart + blockOffset);
					if(SUCCEEDED(status))
						break;
					//vsvfl_mark_bad_vfl_block(_vfl, _ce, curVFLCxt->vfl_context_block[nextBlock], status);
					if(i == 3)
						fail = 1;
				}
				if(!fail) {
					if(!vfl_check_checksum(_vfl, _ce))
						system_panic("vsvfl_store_vfl_cxt: failed checksum\r\n");
					curVFLCxt->usn_block = nextBlock;
					curVFLCxt->usn_page = 0;
					vfl_gen_checksum(_vfl, _ce);
					int result = vsvfl_write_vfl_cxt_to_flash(_vfl, _ce);
					if(SUCCEEDED(result))
						return result;
				}
			}
			nextBlock = (nextBlock + 1) % 4;
		}
		return EIO;
	}
	return SUCCESS;
}
Esempio n. 2
0
static error_t vfl_vsvfl_erase_single_block(vfl_device_t *_vfl, uint32_t _vbn, int _replaceBadBlock) {
    vfl_vsvfl_device_t *vfl = CONTAINER_OF(vfl_vsvfl_device_t, vfl, _vfl);
    uint32_t bank;

    // In order to erase a single virtual block, we have to erase the matching
    // blocks across all banks.
    for (bank = 0; bank < vfl->geometry.banks_total; bank++) {
        uint32_t pBlock, pCE, blockRemapped;

        // Find the physical block before bad-block remapping.
        virtual_block_to_physical_block(vfl, bank, _vbn, &pBlock);
        pCE = bank % vfl->geometry.num_ce;
        vfl->blockBuffer[bank] = pBlock;

        if (is_block_in_scrub_list(vfl, pCE, pBlock)) {
            // TODO: this.
            system_panic("vsvfl: scrub list support not yet!\r\n");
        }

        // Remap the block and calculate its physical number (considering bank address space).
        blockRemapped = remap_block(vfl, pCE, pBlock, 0);
        vfl->blockBuffer[bank] = blockRemapped % vfl->geometry.blocks_per_bank
                                 + (blockRemapped / vfl->geometry.blocks_per_bank) * vfl->geometry.bank_address_space;
    }

    // TODO: H2FMI erase multiple blocks. Currently we erase the blocks one by one.
    // Actually, the block buffer is used for erase multiple blocks, so we won't use it here.
    uint32_t status = EINVAL;

    for (bank = 0; bank < vfl->geometry.banks_total; bank++) {
        uint32_t pBlock, pCE, tries;

        virtual_block_to_physical_block(vfl, bank, _vbn, &pBlock);
        pCE = bank % vfl->geometry.num_ce;

        // Try to erase each block at most 3 times.
        for (tries = 0; tries < 3; tries++) {
            uint32_t blockRemapped, bankStart, blockOffset;

            blockRemapped = remap_block(vfl, pCE, pBlock, 0);
            bankStart = (blockRemapped / vfl->geometry.blocks_per_bank) * vfl->geometry.bank_address_space;
            blockOffset = blockRemapped % vfl->geometry.blocks_per_bank;

            status = nand_device_erase_single_block(vfl->device, pCE, bankStart + blockOffset);
            if (status == 0)
                break;

            // TODO: add block map support.
            //mark_bad_block(vfl, pCE, pBlock, status);
            bufferPrintf("vfl: failed erasing physical block %d on bank %d. status: 0x%08x\r\n",
                         blockRemapped, bank, status);

            if (!_replaceBadBlock)
                return EINVAL;

            // TODO: complete bad block replacement.
            system_panic("vfl: found a bad block. we don't treat those for now. sorry!\r\n");
        }
    }

    if (status)
        system_panic("vfl: failed to erase virtual block %d!\r\n", _vbn);

    return 0;
}