//------------------------------------------------------------------------------ /// Reads the data and/or the spare area of a page on a managed nandflash. If /// the data pointer is not 0, then the block MUST be LIVE. /// Returns NandCommon_ERROR_WRONGSTATUS if the block is not LIVE and the data /// pointer is not null; Otherwise, returns EccNandFlash_ReadPage(). /// \param managed Pointer to a ManagedNandFlash instance. /// \param block Block to read page from, based on managed area. /// \param page Number of page to read inside the given block. /// \param data Data area buffer, can be 0. /// \param spare Spare area buffer, can be 0. //------------------------------------------------------------------------------ unsigned char ManagedNandFlash_ReadPage( const struct ManagedNandFlash *managed, unsigned short block, unsigned short page, void *data, void *spare) { // Check that the block is LIVE if data is requested if ((managed->blockStatuses[block].status != NandBlockStatus_LIVE) && (managed->blockStatuses[block].status != NandBlockStatus_DIRTY)) { TRACE_ERROR("ManagedNandFlash_ReadPage: Block must be LIVE or DIRTY.\n\r"); return NandCommon_ERROR_WRONGSTATUS; } // Read data with ECC verification return EccNandFlash_ReadPage(ECC(managed), managed->baseBlock + block, page, data, spare); }
/** * \brief Reads the data and/or the spare area of a page on a SkipBlock nandflash. * * \param skipBlock Pointer to a SkipBlockNandFlash instance. * \param block Number of block to read page from. * \param page Number of page to read inside the given block. * \param data Data area buffer, can be 0. * \param spare Spare area buffer, can be 0. * \note If one of the buffer pointer is 0, then the block MUST not be BAD. * \return NandCommon_ERROR_BADBLOCK if the block is BAD; Otherwise, returns EccNandFlash_ReadPage(). */ uint8_t SkipBlockNandFlash_ReadPage( const struct SkipBlockNandFlash *skipBlock, uint16_t block, uint16_t page, void *data, void *spare) { #if !defined(OP_BOOTSTRAP_on) /* Check that the block is not BAD if data is requested */ if (SkipBlockNandFlash_CheckBlock(skipBlock, block) != GOODBLOCK) { TRACE_ERROR("SkipBlockNandFlash_ReadPage: Block is BAD.\n\r"); return NandCommon_ERROR_BADBLOCK; } /* Read data with ECC verification */ return EccNandFlash_ReadPage(ECC(skipBlock), block, page, data, spare); #else return RawNandFlash_ReadPage(RAW(skipBlock), block, page, data, spare); #endif }
/** * \brief Reads the data of a whole block on a SkipBlock nandflash. * * \param skipBlock Pointer to a SkipBlockNandFlash instance. * \param block Number of block to read page from. * \param page Number of page to read inside the given block. * \param data Data area buffer, can be 0. * \param spare Spare area buffer, can be 0. * \return NandCommon_ERROR_BADBLOCK if the block is BAD; Otherwise, returns EccNandFlash_ReadPage(). */ uint8_t SkipBlockNandFlash_ReadBlock( const struct SkipBlockNandFlash *skipBlock, uint16_t block, void *data) { /* Number of pages per block */ uint32_t numPagesPerBlock, pageSize; /* Page index */ uint16_t i; /* Error returned by SkipBlockNandFlash_WritePage */ uint8_t error = 0; /* Retrieve model information */ pageSize = NandFlashModel_GetPageDataSize(MODEL(skipBlock)); numPagesPerBlock = NandFlashModel_GetBlockSizeInPages(MODEL(skipBlock)); /* Check that the block is not BAD if data is requested */ if (SkipBlockNandFlash_CheckBlock(skipBlock, block) != GOODBLOCK) { TRACE_ERROR("SkipBlockNandFlash_ReadBlock: Block is BAD.\n\r"); return NandCommon_ERROR_BADBLOCK; } /* Read all the pages of the block */ for (i = 0; i < numPagesPerBlock; i++) { error = EccNandFlash_ReadPage(ECC(skipBlock), block, i, data, 0); if (error) { TRACE_ERROR("SkipBlockNandFlash_ReadBlock: Cannot read page %d of block %d.\n\r", i, block); return error; } data = (void *) ((uint8_t *) data + pageSize); } return 0; }
//------------------------------------------------------------------------------ /// Copy the data & spare area of one page to another page. The source block /// can be either LIVE or DIRTY, and the destination block must be LIVE; they /// must both have the same parity. /// Returns 0 if successful; NandCommon_ERROR_WRONGSTATUS if one or more page /// is not live; otherwise returns an NandCommon_ERROR_xxx code. /// \param managed Pointer to a ManagedNandFlash instance. /// \param sourceBlock Source block number based on managed area. /// \param sourcePage Number of source page inside the source block. /// \param destBlock Destination block number based on managed area. /// \param destPage Number of destination page inside the dest block. //------------------------------------------------------------------------------ unsigned char ManagedNandFlash_CopyPage( const struct ManagedNandFlash *managed, unsigned short sourceBlock, unsigned short sourcePage, unsigned short destBlock, unsigned short destPage) { unsigned char *pDataBuffer = RawNandFlash_GetDataBuffer(RAW(managed)); unsigned char *pSpareBuffer = RawNandFlash_GetSpareBuffer(RAW(managed)); unsigned char error; ASSERT((sourcePage & 1) == (destPage & 1), "ManagedNandFlash_CopyPage: source & dest pages must have the same parity\n\r"); TRACE_INFO("ManagedNandFlash_CopyPage(B#%d:P#%d -> B#%d:P#%d)\n\r", sourceBlock, sourcePage, destBlock, destPage); // Check block statuses if ((managed->blockStatuses[sourceBlock].status != NandBlockStatus_LIVE) && (managed->blockStatuses[sourceBlock].status != NandBlockStatus_DIRTY)) { TRACE_ERROR("ManagedNandFlash_CopyPage: Source block must be LIVE or DIRTY.\n\r"); return NandCommon_ERROR_WRONGSTATUS; } if (managed->blockStatuses[destBlock].status != NandBlockStatus_LIVE) { TRACE_ERROR("ManagedNandFlash_CopyPage: Destination block must be LIVE.\n\r"); return NandCommon_ERROR_WRONGSTATUS; } // If destination page is page #0, block status information must not be // overwritten if (destPage == 0) { // Read data & spare to copy error = EccNandFlash_ReadPage(ECC(managed), managed->baseBlock + sourceBlock, sourcePage, pDataBuffer, pSpareBuffer); if (error) goto error; // Write destination block status information in spare NandSpareScheme_WriteExtra(NandFlashModel_GetScheme(MODEL(managed)), pSpareBuffer, &(managed->blockStatuses[destBlock]), 4, 0); // Write page error = RawNandFlash_WritePage(RAW(managed), managed->baseBlock + destBlock, destPage, pDataBuffer, pSpareBuffer); if (error) goto error; } // Otherwise, a normal copy can be done else { error = RawNandFlash_CopyPage(RAW(managed), managed->baseBlock + sourceBlock, sourcePage, managed->baseBlock + destBlock, destPage); } error: RawNandFlash_ReleaseDataBuffer(RAW(managed)); RawNandFlash_ReleaseSpareBuffer(RAW(managed)); return error; }