//------------------------------------------------------------------------------ /// Unmaps a logical block by releasing the corresponding physical block (if /// any). /// Returns 0 if successful; otherwise returns a NandCommon_ERROR code. /// \param mapped Pointer to a MappedNandFlash instance. /// \param logicalBlock Number of logical block to unmap. //------------------------------------------------------------------------------ unsigned char MappedNandFlash_Unmap( struct MappedNandFlash *mapped, unsigned short logicalBlock) { signed short physicalBlock = mapped->logicalMapping[logicalBlock]; unsigned char error; TRACE_INFO("MappedNandFlash_Unmap(LB#%d)\r\n", logicalBlock); ASSERT( logicalBlock < ManagedNandFlash_GetDeviceSizeInBlocks(MANAGED(mapped)), "MappedNandFlash_Unmap: logicalBlock out-of-range\r\n"); if (physicalBlock != -1) { error = ManagedNandFlash_ReleaseBlock(MANAGED(mapped), physicalBlock); if (error) { return error; } } mapped->logicalMapping[logicalBlock] = -1; mapped->mappingModified = 1; return 0; }
//------------------------------------------------------------------------------ /// Maps a logical block number to an actual physical block. This allocates /// the physical block (meaning it must be FREE), and releases the previous /// block being replaced (if any). /// Returns 0 if successful; otherwise returns a NandCommon_ERROR_xxx code. /// \param mapped Pointer to a MappedNandFlash instance. /// \param logicalBlock Logical block number to map. /// \param physicalBlock Physical block to map to the logical one. //------------------------------------------------------------------------------ unsigned char MappedNandFlash_Map( struct MappedNandFlash *mapped, unsigned short logicalBlock, unsigned short physicalBlock) { unsigned char error; signed short oldPhysicalBlock; TRACE_INFO("MappedNandFlash_Map(LB#%d -> PB#%d)\r\n", logicalBlock, physicalBlock); ASSERT( logicalBlock < ManagedNandFlash_GetDeviceSizeInBlocks(MANAGED(mapped)), "MappedNandFlash_Map: logicalBlock out-of-range\r\n"); ASSERT( physicalBlock < ManagedNandFlash_GetDeviceSizeInBlocks(MANAGED(mapped)), "MappedNandFlash_Map: physicalBlock out-of-range\r\n"); // Allocate physical block error = ManagedNandFlash_AllocateBlock(MANAGED(mapped), physicalBlock); if (error) { return error; } // Release currently mapped block (if any) oldPhysicalBlock = mapped->logicalMapping[logicalBlock]; if (oldPhysicalBlock != -1) { error = ManagedNandFlash_ReleaseBlock(MANAGED(mapped), oldPhysicalBlock); if (error) { return error; } } // Set mapping mapped->logicalMapping[logicalBlock] = physicalBlock; mapped->mappingModified = 1; return 0; }
/** * \brief Maps a logical block number to an actual physical block. This allocates * the physical block (meaning it must be FREE), and releases the previous * block being replaced (if any). * \param mapped Pointer to a MappedNandFlash instance. * \param logicalBlock Logical block number to map. * \param physicalBlock Physical block to map to the logical one. * \return 0 if successful; otherwise returns a NandCommon_ERROR_xxx code. */ unsigned char MappedNandFlash_Map( struct MappedNandFlash *mapped, unsigned short logicalBlock, unsigned short physicalBlock) { unsigned char error; signed short oldPhysicalBlock; TRACE_INFO("MappedNandFlash_Map(LB#%d -> PB#%d)\n\r", logicalBlock, physicalBlock); assert( logicalBlock < ManagedNandFlash_GetDeviceSizeInBlocks(MANAGED(mapped)) ) ; /* "MappedNandFlash_Map: logicalBlock out-of-range\n\r" */ assert( physicalBlock < ManagedNandFlash_GetDeviceSizeInBlocks(MANAGED(mapped)) ) ; /* "MappedNandFlash_Map: physicalBlock out-of-range\n\r" */ /* Allocate physical block*/ error = ManagedNandFlash_AllocateBlock(MANAGED(mapped), physicalBlock); if ( error ) { return error; } /* Release currently mapped block (if any)*/ oldPhysicalBlock = mapped->logicalMapping[logicalBlock]; if (oldPhysicalBlock != -1) { error = ManagedNandFlash_ReleaseBlock(MANAGED(mapped), oldPhysicalBlock); if ( error ) { return error; } } /* Set mapping*/ mapped->logicalMapping[logicalBlock] = physicalBlock; mapped->mappingModified = 1; return 0; }
/** * \brief Saves the logical mapping on a FREE, unmapped physical block. Allocates the * new block, releases the previous one (if any) and save the mapping. * * \param mapped Pointer to a MappedNandFlash instance. * \param physicalBlock Physical block number. * \return 0 if successful; otherwise, returns NandCommon_ERROR_WRONGSTATUS * if the block is not LIVE, or a NandCommon_ERROR code. */ unsigned char MappedNandFlash_SaveLogicalMapping( 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 i; unsigned int remainingSize; unsigned char *currentBuffer; unsigned short currentPage; unsigned int writeSize; signed short previousPhysicalBlock; TRACE_INFO("MappedNandFlash_SaveLogicalMapping(B#%d)\n\r", physicalBlock); /* If mapping has not been modified, do nothing*/ if (!mapped->mappingModified) { return 0; } /* Allocate new block*/ error = ManagedNandFlash_AllocateBlock(MANAGED(mapped), physicalBlock); if (error) { return error; } /* Save mapping*/ previousPhysicalBlock = mapped->logicalMappingBlock; mapped->logicalMappingBlock = physicalBlock; /* Save actual mapping in pages #1-#XXX*/ currentBuffer = (unsigned char *) mapped->logicalMapping; remainingSize = sizeof(mapped->logicalMapping); currentPage = 1; while (remainingSize > 0) { writeSize = min(remainingSize, pageDataSize); memset(data, 0xFF, pageDataSize); memcpy(data, currentBuffer, writeSize); error = ManagedNandFlash_WritePage(MANAGED(mapped), physicalBlock, currentPage, data, 0); if (error) { TRACE_ERROR( "MappedNandFlash_SaveLogicalMapping: Failed to write mapping\n\r"); return error; } currentBuffer += writeSize; remainingSize -= writeSize; currentPage++; } /* Mark page #0 of block with a distinguishible pattern, so the mapping can be retrieved at startup*/ for (i=0; i < pageDataSize; i++) { data[i] = PATTERN(i); } error = ManagedNandFlash_WritePage(MANAGED(mapped), physicalBlock, 0, data, 0); if (error) { TRACE_ERROR( "MappedNandFlash_SaveLogicalMapping: Failed to write pattern\n\r"); return error; } /* Mapping is not modified anymore*/ mapped->mappingModified = 0; /* Release previous block (if any)*/ if (previousPhysicalBlock != -1) { TRACE_DEBUG("Previous physical block was #%d\n\r", previousPhysicalBlock); error = ManagedNandFlash_ReleaseBlock(MANAGED(mapped), previousPhysicalBlock); if (error) { return error; } } TRACE_INFO("Mapping saved on block #%d\n\r", physicalBlock); return 0; }
/** * \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; }