/** * \brief Reads the data and/or spare area of a page in a mapped logical block. * the data is valid using the ECC information contained in the spare. If one * buffer pointer is 0, the corresponding area is not saved. * \param mapped Pointer to a MappedNandFlash instance. * \param block Number of block to read from. * \param page Number of page to read inside given block. * \param data Data area buffer, can be 0. * \param spare Spare area buffer, can be 0. * \return 0 if successful; otherwise, returns NandCommon_ERROR_BLOCKNOTMAPPED * if the block is not mapped, or a NandCommon_ERROR_xxx code. */ unsigned char MappedNandFlash_ReadPage( const struct MappedNandFlash *mapped, unsigned short block, unsigned short page, void *data, void *spare) { signed short physicalBlock; TRACE_INFO("MappedNandFlash_ReadPage(LB#%d:P#%d)\n\r", block, page); /* Check if block is mapped*/ physicalBlock = mapped->logicalMapping[block]; if (physicalBlock == -1) { TRACE_INFO( "MappedNandFlash_ReadPage: Block %d not mapped\n\r", block); return NandCommon_ERROR_BLOCKNOTMAPPED; } /* Read page from corresponding physical block*/ return ManagedNandFlash_ReadPage(MANAGED(mapped), physicalBlock, page, data, spare); }
/** * \brief Reads the data and/or the spare area of a page on a translated nandflash. * If the block is not currently mapped but could be (i.e. there are available * physical blocks), then the data/spare is filled with 0xFF. * * \param translated Pointer to a TranslatedNandFlash instance. * \param block Logical block number. * \param page Number of page to read inside logical block. * \param data Data area buffer, can be 0. * \param spare Spare area buffer, can be 0. * \return 0 if successful; otherwise returns NandCommon_ERROR_NOMOREBLOCKS */ unsigned char TranslatedNandFlash_ReadPage( const struct TranslatedNandFlash *translated, unsigned short block, unsigned short page, void *data, void *spare ) { unsigned char error ; TRACE_INFO("TranslatedNandFlash_ReadPage(B#%d:P#%d)\n\r", block, page); /* If the page to read is in the current block, there is a previous physical block and the page is clean -> read the page in the old block since the new one does not contain meaningful data*/ if ( (block == translated->currentLogicalBlock) && (translated->previousPhysicalBlock != -1) && (PageIsClean(translated, page)) ) { TRACE_DEBUG("Reading page from current block\n\r"); return ManagedNandFlash_ReadPage( MANAGED( translated ), translated->previousPhysicalBlock, page, data, spare ) ; } else { /* Try to read the page from the logical block*/ error = MappedNandFlash_ReadPage(MAPPED(translated), block, page, data, spare); /* Block was not mapped*/ if ( error == NandCommon_ERROR_BLOCKNOTMAPPED ) { assert( !spare ) ; /* "Cannot read the spare information of an unmapped block\n\r" */ /* Check if a block can be allocated*/ if ( BlockCanBeAllocated( translated ) ) { /* Return 0xFF in buffers with no error*/ TRACE_DEBUG("Block #%d is not mapped but can be allocated, filling buffer with 0xFF\n\r", block); if (data) { memset(data, 0xFF, NandFlashModel_GetPageDataSize(MODEL(translated))); } if (spare) { memset(spare, 0xFF, NandFlashModel_GetPageSpareSize(MODEL(translated))); } } else { TRACE_ERROR("Block #%d is not mapped and there are no more blocks available\n\r", block); return NandCommon_ERROR_NOMOREBLOCKS; } } /* Error*/ else { if (error) { return error; } } } return 0; }
/** * \brief Scans a mapped nandflash to find an existing logical block mapping. If a * block contains the mapping, its index is stored in the provided variable (if * pointer is not 0). * * \param mapped Pointer to a MappedNandFlash instance. * \param logicalMappingBlock Pointer to a variable for storing the block number. * \return 0 if mapping has been found; otherwise returns * NandCommon_ERROR_NOMAPPING if no mapping exists, or another NandCommon_ERROR_xxx code. */ static unsigned char FindLogicalMappingBlock( const struct MappedNandFlash *mapped, signed short *logicalMappingBlock) { unsigned short block; unsigned char found; unsigned short numBlocks = ManagedNandFlash_GetDeviceSizeInBlocks(MANAGED(mapped)); unsigned short pageDataSize = NandFlashModel_GetPageDataSize(MODEL(mapped)); unsigned char error; unsigned char data[NandCommon_MAXPAGEDATASIZE]; unsigned int i; //TRACE_INFO("FindLogicalMappingBlock ~%d\n\r", numBlocks); /* Search each LIVE block */ found = 0; block = 0; while (!found && (block < numBlocks)) { /* Check that block is LIVE*/ if (MANAGED(mapped)->blockStatuses[block].status == NandBlockStatus_LIVE) { /* Read block*/ TRACE_INFO("Checking LIVE block #%d\n\r", block); error = ManagedNandFlash_ReadPage(MANAGED(mapped), block, 0, data, 0); if (!error) { /* Compare data with logical mapping pattern*/ i = 0; found = 1; while ((i < pageDataSize) && found) { if (data[i] != PATTERN(i)) { found = 0; } i++; } /* If this is the mapping, stop looking*/ if (found) { TRACE_WARNING_WP("-I- Logical mapping in block #%d\n\r", block); if (logicalMappingBlock) { *logicalMappingBlock = block; } return 0; } } else if (error != NandCommon_ERROR_WRONGSTATUS) { TRACE_ERROR( "FindLogicalMappingBlock: Failed to scan block #%d\n\r", block); return error; } } block++; } TRACE_WARNING("No logical mapping found in device\n\r"); return NandCommon_ERROR_NOMAPPING; }
/** * \brief Loads the logical mapping contained in the given physical block. * block contains the mapping, its index is stored in the provided variable (if * pointer is not 0). * * \param mapped Pointer to a MappedNandFlash instance. * \param physicalBlock Physical block number. * \return 0 if successful; otherwise, returns a NandCommon_ERROR code. */ static unsigned char LoadLogicalMapping( struct MappedNandFlash *mapped, unsigned short physicalBlock) { unsigned char error; unsigned char data[NandCommon_MAXPAGEDATASIZE]; unsigned short pageDataSize = NandFlashModel_GetPageDataSize(MODEL(mapped)); unsigned short numBlocks = ManagedNandFlash_GetDeviceSizeInBlocks(MANAGED(mapped)); unsigned int remainingSize; unsigned char *currentBuffer; unsigned short currentPage; unsigned int readSize; unsigned int i; unsigned char status; signed short logicalBlock; /*signed short firstBlock, lastBlock;*/ TRACE_INFO("LoadLogicalMapping(B#%d)\n\r", physicalBlock); /* Load mapping from pages #1 - #XXX of block*/ currentBuffer = (unsigned char *) mapped->logicalMapping; remainingSize = sizeof(mapped->logicalMapping); currentPage = 1; while (remainingSize > 0) { /* Read page*/ readSize = min(remainingSize, pageDataSize); error = ManagedNandFlash_ReadPage(MANAGED(mapped), physicalBlock, currentPage, data, 0); if (error) { TRACE_ERROR( "LoadLogicalMapping: Failed to load mapping\n\r"); return error; } /* Copy page info*/ memcpy(currentBuffer, data, readSize); currentBuffer += readSize; remainingSize -= readSize; currentPage++; } /* Store mapping block index*/ mapped->logicalMappingBlock = physicalBlock; /* Power-loss recovery*/ for (i=0; i < numBlocks; i++) { /* Check that this is not the logical mapping block*/ if (i != physicalBlock) { status = mapped->managed.blockStatuses[i].status; logicalBlock = MappedNandFlash_PhysicalToLogical(mapped, i); /* Block is LIVE*/ if (status == NandBlockStatus_LIVE) { /* Block is not mapped -> release it*/ if (logicalBlock == -1) { TRACE_WARNING_WP("-I- Release unmapped LIVE #%d\n\r", i); ManagedNandFlash_ReleaseBlock(MANAGED(mapped), i); } } /* Block is DIRTY*/ else if (status == NandBlockStatus_DIRTY) { /* Block is mapped -> fake it as live*/ if (logicalBlock != -1) { TRACE_WARNING_WP("-I- Mark mapped DIRTY #%d -> LIVE\n\r", i); mapped->managed.blockStatuses[i].status = NandBlockStatus_LIVE; } } /* Block is FREE or BAD*/ else { /* Block is mapped -> remove it from mapping*/ if (logicalBlock != -1) { TRACE_WARNING_WP("-I- Unmap FREE or BAD #%d\n\r", i); mapped->logicalMapping[logicalBlock] = -1; } } } } TRACE_WARNING_WP("-I- Mapping loaded from block #%d\n\r", physicalBlock); return 0; }
//------------------------------------------------------------------------------ /// Loads the logical mapping contained in the given physical block. /// Returns 0 if successful; otherwise, returns a NandCommon_ERROR code. /// \param mapped Pointer to a MappedNandFlash instance. /// \param physicalBlock Physical block number. //------------------------------------------------------------------------------ static unsigned char LoadLogicalMapping( struct MappedNandFlash *mapped, unsigned short physicalBlock) { unsigned char error; unsigned short pageDataSize = NandFlashModel_GetPageDataSize(MODEL(mapped)); unsigned short numBlocks = ManagedNandFlash_GetDeviceSizeInBlocks(MANAGED(mapped)); unsigned char *pDataBuffer = RawNandFlash_GetDataBuffer(RAW(mapped)); unsigned int remainingSize; unsigned char *currentBuffer; unsigned short currentPage; unsigned int readSize; unsigned int i; unsigned char status; signed short logicalBlock; //signed short firstBlock, lastBlock; TRACE_INFO("LoadLogicalMapping(B#%d)\r\n", physicalBlock); // Load mapping from pages #1 - #XXX of block currentBuffer = (unsigned char *) mapped->logicalMapping; remainingSize = sizeof(mapped->logicalMapping); currentPage = 1; while (remainingSize > 0) { // Read page readSize = min(remainingSize, pageDataSize); error = ManagedNandFlash_ReadPage(MANAGED(mapped), physicalBlock, currentPage, pDataBuffer, 0); if (error) { RawNandFlash_ReleaseDataBuffer(RAW(mapped)); TRACE_ERROR( "LoadLogicalMapping: Failed to load mapping\r\n"); return error; } // Copy page info memcpy(currentBuffer, pDataBuffer, readSize); currentBuffer += readSize; remainingSize -= readSize; currentPage++; } // Store mapping block index mapped->logicalMappingBlock = physicalBlock; // Power-loss recovery for (i=0; i < numBlocks; i++) { // Check that this is not the logical mapping block if (i != physicalBlock) { status = mapped->managed.blockStatuses[i].status; logicalBlock = MappedNandFlash_PhysicalToLogical(mapped, i); // Block is LIVE if (status == NandBlockStatus_LIVE) { // Block is not mapped -> release it if (logicalBlock == -1) { TRACE_WARNING_WP("-I- Release unmapped LIVE #%d\r\n", i); ManagedNandFlash_ReleaseBlock(MANAGED(mapped), i); } } // Block is DIRTY else if (status == NandBlockStatus_DIRTY) { // Block is mapped -> fake it as live if (logicalBlock != -1) { TRACE_WARNING_WP("-I- Mark mapped DIRTY #%d -> LIVE\r\n", i); mapped->managed.blockStatuses[i].status = NandBlockStatus_LIVE; } } // Block is FREE or BAD else { // Block is mapped -> remove it from mapping if (logicalBlock != -1) { TRACE_WARNING_WP("-I- Unmap FREE or BAD #%d\r\n", i); mapped->logicalMapping[logicalBlock] = -1; } } } } RawNandFlash_ReleaseDataBuffer(RAW(mapped)); TRACE_WARNING_WP("-I- Mapping loaded from block #%d\r\n", physicalBlock); return 0; }