Esempio n. 1
0
static error_t virtual_page_number_to_physical(vfl_vsvfl_device_t *_vfl, uint32_t _vpNum, uint32_t* _ce, uint32_t* _page) {
	uint32_t ce, vBank, ret, bank_offset, pBlock;

	vBank = _vpNum % _vfl->geometry.banks_total;
	ce = vBank % _vfl->geometry.num_ce;

	ret = virtual_block_to_physical_block(_vfl, vBank, _vpNum / _vfl->geometry.pages_per_sublk, &pBlock);

	if(FAILED(ret))
		return ret;

	pBlock = remap_block(_vfl, ce, pBlock, 0);

	bank_offset = _vfl->geometry.bank_address_space * (pBlock / _vfl->geometry.blocks_per_bank);

	*_ce = ce;
	*_page = _vfl->geometry.pages_per_block_2 * (bank_offset + (pBlock % _vfl->geometry.blocks_per_bank))
			+ ((_vpNum % _vfl->geometry.pages_per_sublk) / _vfl->geometry.banks_total);

	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;
}