diff --git a/zircon/system/ulib/ftl/ftl.h b/zircon/system/ulib/ftl/ftl.h new file mode 100644 index 0000000000000000000000000000000000000000..2e3dd9c609731e384b1acf13913d13adb3a6bf2a --- /dev/null +++ b/zircon/system/ulib/ftl/ftl.h @@ -0,0 +1,39 @@ +// Copyright 2018 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#pragma once + +#include <stdint.h> // For fixed width types. + +#ifdef __cplusplus +extern "C" { +#endif + +// +// Type Declarations. +// + +// NDM Control Block +typedef struct ndm* NDM; +typedef const struct ndm* CNDM; + +// FTL Interface Structure +typedef struct XfsVol { + // Driver functions + int (*write_pages)(const void* buf, uint32_t page0, int cnt, void* vol); + int (*read_pages)(void* buf, uint32_t page0, int cnt, void* vol); + int (*report)(void *vol, uint32_t msg, ...); + + const char* name; // volume name + uint32_t flags; // option flags + uint32_t num_pages; // number of pages in volume + uint32_t page_size; // page size in bytes + void* vol; // driver's volume pointer + void* ftl_volume; // ftl layer (block device) volume +} XfsVol; + +#ifdef __cplusplus +} +#endif + diff --git a/zircon/system/ulib/ftl/ftl_private.h b/zircon/system/ulib/ftl/ftl_private.h new file mode 100644 index 0000000000000000000000000000000000000000..742e875db5b58ac3d99a2339e09c116e81faa0a0 --- /dev/null +++ b/zircon/system/ulib/ftl/ftl_private.h @@ -0,0 +1,35 @@ +// Copyright 2018 The Fuchsia Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#pragma once + +#include <ftl.h> // For API definition. + +#ifdef __cplusplus +extern "C" { +#endif + +// +// Symbol Definitions. +// +#define ui8 uint8_t + +// +// Function Prototypes. +// + +// TargetNDM interface to TargetFTL +int ndmEraseBlock(uint32_t pn, NDM ndm); +int ndmReadPages(uint32_t pn0, uint32_t count, ui8* buf, ui8* spare, NDM ndm); +int ndmReadSpare(uint32_t vpn, ui8* spare, NDM ndm); +int ndmWritePages(uint32_t pn0, uint32_t cnt, const ui8* buf, ui8* spare, NDM ndm); +int ndmWritePage(uint32_t vpn, const ui8* buf, ui8* spare, NDM ndm); +int ndmTransferPage(uint32_t old_vpn, uint32_t new_vpn, ui8* buf, ui8* spare, NDM ndm); +int ndmCheckPage(uint32_t pn, ui8* data, ui8* spare, NDM ndm); +uint32_t ndmPairOffset(uint32_t page_offset, CNDM ndm); + +#ifdef __cplusplus +} +#endif + diff --git a/zircon/system/ulib/ftl/ftln/ftln_init.c b/zircon/system/ulib/ftl/ftln/ftln_init.c index f22b1995712e21189a25ed08039507fa73fe370e..9754559f6570e3cdaa52c50cae5c0b5ffc72f13e 100644 --- a/zircon/system/ulib/ftl/ftln/ftln_init.c +++ b/zircon/system/ulib/ftl/ftln/ftln_init.c @@ -91,7 +91,7 @@ static int map_page_check(FTLN ftl, ui32 apn, int process) { // Call driver validity check. Return -1 if error. ++ftl->stats.page_check; - status = ftl->page_check(apn, ftl->main_buf, ftl->spare_buf, ftl->ndm); + status = ndmCheckPage(apn, ftl->main_buf, ftl->spare_buf, ftl->ndm); if (status < 0) return FtlnFatErr(ftl); @@ -140,23 +140,17 @@ static int map_page_check(FTLN ftl, ui32 apn, int process) { // Process each elist page, from last to first. for (;;) { - //--------------------------------------------------------- // Verify and apply elist page. Return if page invalid. - //--------------------------------------------------------- status = proc_elist(ftl); if (status != NDM_PAGE_VALID) return status; - //--------------------------------------------------------- // If first (perhaps only) page was processed, finished! - //--------------------------------------------------------- if (apn == ap0) break; - //--------------------------------------------------------- // Move to next written page in backwards direction. If // MLC flash, move to page whose pair has higher offset. - //--------------------------------------------------------- #if INC_FTL_NDM_SLC --apn; #else @@ -170,29 +164,21 @@ static int map_page_check(FTLN ftl, ui32 apn, int process) { } #endif - //--------------------------------------------------------- // Call driver to read/check next page. Return -1 if error. - //--------------------------------------------------------- ++ftl->stats.page_check; - status = ftl->page_check(apn, ftl->main_buf, ftl->spare_buf, ftl->ndm); + status = ndmCheckPage(apn, ftl->main_buf, ftl->spare_buf, ftl->ndm); if (status < 0) return FtlnFatErr(ftl); - //--------------------------------------------------------- // If page is erased or invalid, return its status. - //--------------------------------------------------------- if (status != NDM_PAGE_VALID) return status; - //--------------------------------------------------------- // Verify the metadata version is correct. - //--------------------------------------------------------- if (RD32_LE(&ppns[0]) != FTLN_META_VER1) return NDM_PAGE_INVALID; - //--------------------------------------------------------- // Verify the metadata type is correct. - //--------------------------------------------------------- if (RD32_LE(&ppns[1]) != ERASED_LIST) return NDM_PAGE_INVALID; } @@ -294,7 +280,7 @@ static int build_map(FTLN ftl) { else { // Read page's spare area. ++ftl->stats.read_spare; - status = ftl->read_spare(pn, ftl->spare_buf, ftl->ndm); + status = ndmReadSpare(pn, ftl->spare_buf, ftl->ndm); // Return if fatal error. if (status == -2) { @@ -309,11 +295,11 @@ static int build_map(FTLN ftl) { // If first page, retrieve block count. Otherwise compare with // block count of block's already-checked-valid first page. - if (po == 0) + if (po == 0) { bc = GET_SA_BC(ftl->spare_buf); - else if (bc != GET_SA_BC(ftl->spare_buf)) { + } else if (bc != GET_SA_BC(ftl->spare_buf)) { #if FTLN_DEBUG > 1 - printf("build_ma: b = %u, po = %u, i_bc = %u vs 0_bc = %u\n", b, po, + printf("build_map: b = %u, po = %u, i_bc = %u vs 0_bc = %u\n", b, po, GET_SA_BC(ftl->spare_buf), bc); #endif @@ -332,7 +318,7 @@ static int build_map(FTLN ftl) { mpn = GET_SA_VPN(ftl->spare_buf); if (mpn > ftl->num_map_pgs) { #if FTLN_DEBUG > 1 - printf("build_ma: b = %u, po = %u, mpn = %u, max = %u\n", b, po, mpn, + printf("build_map: b = %u, po = %u, mpn = %u, max = %u\n", b, po, mpn, ftl->num_map_pgs); #endif @@ -361,7 +347,7 @@ static int build_map(FTLN ftl) { INC_USED(ftl->bdata[b]); } #if FTLN_DEBUG > 1 - printf("build_ma: mpn = %u, old_pn = %d, new_pn = %u\n", mpn, ftl->mpns[mpn], + printf("build_map: mpn = %u, old_pn = %d, new_pn = %u\n", mpn, ftl->mpns[mpn], b * ftl->pgs_per_blk + po); #endif @@ -533,7 +519,7 @@ static int format_status(FTLN ftl) { // Read spare area for first page. Return -1 if fatal error. ++ftl->stats.read_spare; - rc = ftl->read_spare(pn, ftl->spare_buf, ftl->ndm); + rc = ndmReadSpare(pn, ftl->spare_buf, ftl->ndm); if (rc == -2) return FtlnFatErr(ftl); @@ -565,7 +551,7 @@ static int format_status(FTLN ftl) { // Read spare area for higher page. Return -1 if fatal error. ++ftl->stats.read_spare; - rc = ftl->read_spare(pn + n, ftl->spare_buf, ftl->ndm); + rc = ndmReadSpare(pn + n, ftl->spare_buf, ftl->ndm); if (rc == -2) return FtlnFatErr(ftl); @@ -602,7 +588,7 @@ static int format_status(FTLN ftl) { #endif // Call driver validity check. Return -1 if error. ++ftl->stats.page_check; - rc = ftl->page_check(pn, ftl->main_buf, ftl->spare_buf, ftl->ndm); + rc = ndmCheckPage(pn, ftl->main_buf, ftl->spare_buf, ftl->ndm); if (rc < 0) return FtlnFatErr(ftl); @@ -624,7 +610,7 @@ static int format_status(FTLN ftl) { // Read spare data. Return if fatal error. Skip if ECC error. ++ftl->stats.read_spare; - rc = ftl->read_spare(pn + n, ftl->spare_buf, ftl->ndm); + rc = ndmReadSpare(pn + n, ftl->spare_buf, ftl->ndm); if (rc == -2) return FtlnFatErr(ftl); if (rc) @@ -642,7 +628,7 @@ static int format_status(FTLN ftl) { #endif // Read and check the copy-end page. Return -1 if error. ++ftl->stats.page_check; - rc = ftl->page_check(pn + n, ftl->main_buf, ftl->spare_buf, ftl->ndm); + rc = ndmCheckPage(pn + n, ftl->main_buf, ftl->spare_buf, ftl->ndm); if (rc < 0) return FtlnFatErr(ftl); @@ -819,7 +805,7 @@ static int copy_end_mark(CFTLN ftl, ui32 b) { SET_SA_WC(0, ftl->spare_buf); // Write page that marks the end of a volume resume copy block. - return ftl->write_page(pn, ftl->main_buf, ftl->spare_buf, ftl->ndm); + return ndmWritePage(pn, ftl->main_buf, ftl->spare_buf, ftl->ndm); } // resume_copy: Copy one volume block @@ -842,7 +828,7 @@ static int resume_copy(FTLN ftl, ui32 src_b, ui32 dst_b, ui32 bc) { for (po = 0; po <= ftl->resume_po; ++po) { // Read source page's spare area. ++ftl->stats.read_spare; - rc = ftl->read_spare(src_pg0 + po, ftl->spare_buf, ftl->ndm); + rc = ndmReadSpare(src_pg0 + po, ftl->spare_buf, ftl->ndm); // Return -1 if fatal error, skip page if ECC error on spare read. if (rc) { @@ -865,8 +851,10 @@ static int resume_copy(FTLN ftl, ui32 src_b, ui32 dst_b, ui32 bc) { // Invoke page transfer routine. If error, return -1. ++ftl->stats.transfer_page; - if (ftl->xfer_page(src_pg0 + po, dst_pg0 + po, ftl->main_buf, ftl->spare_buf, ftl->ndm)) + if (ndmTransferPage(src_pg0 + po, dst_pg0 + po, ftl->main_buf, + ftl->spare_buf, ftl->ndm)) { return FtlnFatErr(ftl); + } } // Return success. @@ -1133,31 +1121,31 @@ static int rd_map_pg(void* vol, ui32 mpn, void* buf, int* unmapped) { // FtlnAddVol: Create a new FTL volume // -// Inputs: ftl_dvr = pointer to FTL NDM driver control block +// Inputs: ftl_cfg = pointer to FTL configuration structure // xfs = pointer to FTL interface structure // // Returns: -1 if error, 0 for success. // -int FtlnAddVol(FtlNdmVol* ftl_dvr, XfsVol* xfs) { +int FtlnAddVol(FtlNdmVol* ftl_cfg, XfsVol* xfs) { ui32 n, vol_blks; ui8* buf; FTLN ftl; // If number of blocks less than 7, FTL-NDM cannot work. - if (ftl_dvr->num_blocks < 7) { + if (ftl_cfg->num_blocks < 7) { FsError2(FTL_CFG_ERR, EINVAL); return -1; } // Ensure FTL flags are valid. - if (ftl_dvr->flags & ~(FSF_EXTRA_FREE | FSF_READ_WEAR_LIMIT | FSF_READ_ONLY_INIT)) { + if (ftl_cfg->flags & ~(FSF_EXTRA_FREE | FSF_READ_WEAR_LIMIT | FSF_READ_ONLY_INIT)) { FsError2(FTL_CFG_ERR, EINVAL); return -1; } #if CACHE_LINE_SIZE // Ensure driver page size is a multiple of the CPU cache line size. - if (ftl_dvr->page_size % CACHE_LINE_SIZE) { + if (ftl_cfg->page_size % CACHE_LINE_SIZE) { FsError2(FTL_CFG_ERR, EINVAL); return -1; } @@ -1165,8 +1153,8 @@ int FtlnAddVol(FtlNdmVol* ftl_dvr, XfsVol* xfs) { // Ensure physical page size is a multiple of FAT sector size and // not bigger than the device block size. - if (ftl_dvr->page_size % FAT_SECT_SZ || ftl_dvr->page_size == 0 || - ftl_dvr->page_size > ftl_dvr->block_size) { + if (ftl_cfg->page_size % FAT_SECT_SZ || ftl_cfg->page_size == 0 || + ftl_cfg->page_size > ftl_cfg->block_size) { FsError2(FTL_CFG_ERR, EINVAL); return -1; } @@ -1181,17 +1169,16 @@ int FtlnAddVol(FtlNdmVol* ftl_dvr, XfsVol* xfs) { Ftln = ftl; #endif - // Set all FTL driver dependent variables. - ftl->num_blks = ftl_dvr->num_blocks; - ftl->page_size = ftl_dvr->page_size; - ftl->eb_size = ftl_dvr->eb_size; - ftl->block_size = ftl_dvr->block_size; + // Initialize the FTL control block. + ftl->num_blks = ftl_cfg->num_blocks; + ftl->page_size = ftl_cfg->page_size; + ftl->eb_size = ftl_cfg->eb_size; + ftl->block_size = ftl_cfg->block_size; ftl->pgs_per_blk = ftl->block_size / ftl->page_size; ftl->num_pages = ftl->pgs_per_blk * ftl->num_blks; - ftl->start_pn = ftl_dvr->start_page; - ftl->ndm = ftl_dvr->ndm; - ftl->type = ftl_dvr->type; - ftl->flags = ftl_dvr->flags; + ftl->start_pn = ftl_cfg->start_page; + ftl->ndm = ftl_cfg->ndm; + ftl->flags = ftl_cfg->flags; strcpy(ftl->vol_name, xfs->name); // Ensure pages per block doesn't exceed alloted metadata field width. @@ -1207,18 +1194,6 @@ int FtlnAddVol(FtlNdmVol* ftl_dvr, XfsVol* xfs) { } #endif - // Copy the NDM interface functions. - ftl->write_page = ftl_dvr->write_data_and_spare; - ftl->write_pages = ftl_dvr->write_pages; - ftl->read_spare = ftl_dvr->read_spare; - ftl->read_pages = ftl_dvr->read_pages; - ftl->page_check = ftl_dvr->page_check; - ftl->xfer_page = ftl_dvr->transfer_page; - ftl->erase_block = ftl_dvr->erase_block; -#if INC_FTL_NDM_MLC - ftl->pair_offset = ftl_dvr->pair_offset; -#endif - // Compute how many volume pages are mapped by a single map page. ftl->mappings_per_mpg = ftl->page_size / FTLN_PN_SZ; @@ -1283,8 +1258,8 @@ int FtlnAddVol(FtlNdmVol* ftl_dvr, XfsVol* xfs) { // 2%. Increasing number of map pages makes recycles more efficient // because the ratio of used to dirty pages is lower in map blocks. ftl->num_vpages = vol_blks * ftl->pgs_per_blk; - n = ftl_dvr->extra_free; - if (FLAG_IS_CLR(ftl_dvr->flags, FSF_EXTRA_FREE) || n < 2 || n > 50) + n = ftl_cfg->extra_free; + if (FLAG_IS_CLR(ftl_cfg->flags, FSF_EXTRA_FREE) || n < 2 || n > 50) n = 2; n = (n * ftl->num_vpages) / 100; if (n == 0) @@ -1340,25 +1315,25 @@ int FtlnAddVol(FtlNdmVol* ftl_dvr, XfsVol* xfs) { // For SLC devices, adjust driver cached MPNs if too big or zero. #if INC_FTL_NDM_SLC - if (ftl->num_map_pgs < ftl_dvr->cached_map_pages || ftl_dvr->cached_map_pages == 0) - ftl_dvr->cached_map_pages = ftl->num_map_pgs; + if (ftl->num_map_pgs < ftl_cfg->cached_map_pages || ftl_cfg->cached_map_pages == 0) + ftl_cfg->cached_map_pages = ftl->num_map_pgs; #else // For MLC devices, cache all map pages so that no map write occurs // due to cache preemption. - ftl_dvr->cached_map_pages = ftl->num_map_pgs; + ftl_cfg->cached_map_pages = ftl->num_map_pgs; #endif // Allocate map page cache for new volume. - ftl->map_cache = ftlmcNew(ftl, ftl_dvr->cached_map_pages, FtlnMapWr, rd_map_pg, ftl->page_size); + ftl->map_cache = ftlmcNew(ftl, ftl_cfg->cached_map_pages, FtlnMapWr, rd_map_pg, ftl->page_size); if (ftl->map_cache == NULL) goto FtlnAddV_err; // Set block read wear limit. - if (FLAG_IS_SET(ftl_dvr->flags, FSF_READ_WEAR_LIMIT)) - ftl->max_rc = ftl_dvr->read_wear_limit; - else { + if (FLAG_IS_SET(ftl_cfg->flags, FSF_READ_WEAR_LIMIT)) { + ftl->max_rc = ftl_cfg->read_wear_limit; + } else { #if INC_FTL_NDM_SLC ftl->max_rc = SLC_NAND_RC_LIMIT; #else diff --git a/zircon/system/ulib/ftl/ftln/ftln_intrnl.c b/zircon/system/ulib/ftl/ftln/ftln_intrnl.c index a522ed8a5db7d5bdf51bd058742b0c4d126acef1..dcd0dab02ee223c621c39d9b90c1f74365622f7a 100644 --- a/zircon/system/ulib/ftl/ftln/ftln_intrnl.c +++ b/zircon/system/ulib/ftl/ftln/ftln_intrnl.c @@ -250,13 +250,13 @@ static int wr_vol_page(FTLN ftl, ui32 vpn, void* buf, ui32 old_ppn) { // If page data in buffer, write it. Returns 0 or -2. if (buf) { ++ftl->stats.write_page; - rc = ftl->write_page(ftl->start_pn + ppn, buf, ftl->spare_buf, ftl->ndm); + rc = ndmWritePage(ftl->start_pn + ppn, buf, ftl->spare_buf, ftl->ndm); // Else invoke page transfer routine. Returns 0, -2, or 1. } else { ++ftl->stats.transfer_page; - rc = ftl->xfer_page(ftl->start_pn + old_ppn, ftl->start_pn + ppn, ftl->main_buf, - ftl->spare_buf, ftl->ndm); + rc = ndmTransferPage(ftl->start_pn + old_ppn, ftl->start_pn + ppn, + ftl->main_buf, ftl->spare_buf, ftl->ndm); } // Return -1 for any error. Any write error is fatal. @@ -566,7 +566,7 @@ static int recycle_vblk(FTLN ftl, ui32 recycle_b) { // Read page's spare area. ++ftl->stats.read_spare; - rc = ftl->read_spare(ftl->start_pn + pn, ftl->spare_buf, ftl->ndm); + rc = ndmReadSpare(ftl->start_pn + pn, ftl->spare_buf, ftl->ndm); // Return -1 if fatal error, skip page if ECC error on spare read. if (rc) { @@ -670,8 +670,8 @@ static int flush_pending_writes(FTLN ftl, StagedWr* staged) { // Issue driver multi-page write request. Return -1 if error. ftl->stats.write_page += staged->cnt; - if (ftl->write_pages(ftl->start_pn + staged->ppn0, staged->cnt, staged->buf, - ftl->spare_buf, ftl->ndm)) { + if (ndmWritePages(ftl->start_pn + staged->ppn0, staged->cnt, staged->buf, + ftl->spare_buf, ftl->ndm)) { return FtlnFatErr(ftl); } @@ -886,7 +886,7 @@ int FtlnRecycleMapBlk(FTLN ftl, ui32 recycle_b) { // Read page's spare area. Return -1 if fatal I/O error. ++ftl->stats.read_spare; - rc = ftl->read_spare(ftl->start_pn + pn, ftl->spare_buf, ftl->ndm); + rc = ndmReadSpare(ftl->start_pn + pn, ftl->spare_buf, ftl->ndm); if (rc == -2) return FtlnFatErr(ftl); @@ -1178,13 +1178,13 @@ int FtlnMapWr(void* vol, ui32 mpn, void* buf) { // If page data in buffer, invoke write_page(). if (buf) { ++ftl->stats.write_page; - status = ftl->write_page(ftl->start_pn + pn, buf, ftl->spare_buf, ftl->ndm); + status = ndmWritePage(ftl->start_pn + pn, buf, ftl->spare_buf, ftl->ndm); // Else source data is in flash. Invoke page transfer routine. } else { ++ftl->stats.transfer_page; - status = ftl->xfer_page(ftl->start_pn + old_pn, ftl->start_pn + pn, ftl->main_buf, - ftl->spare_buf, ftl->ndm); + status = ndmTransferPage(ftl->start_pn + old_pn, ftl->start_pn + pn, + ftl->main_buf, ftl->spare_buf, ftl->ndm); } // I/O or ECC decode error is fatal. diff --git a/zircon/system/ulib/ftl/ftln/ftln_rd.c b/zircon/system/ulib/ftl/ftln/ftln_rd.c index 15b61b0c84fa5f2418d8b2c3f75ecda6a2420d43..70a0912ea2f11e32b5598be32e063dfe1806ee5a 100644 --- a/zircon/system/ulib/ftl/ftln/ftln_rd.c +++ b/zircon/system/ulib/ftl/ftln/ftln_rd.c @@ -27,8 +27,8 @@ static int flush_pending_reads(FTLN ftl, StagedRd* staged) { // Issue pending reads. ftl->stats.read_page += staged->run_cnt; - status = ftl->read_pages(ftl->start_pn + staged->ppn0, staged->run_cnt, staged->buf, - ftl->spare_buf, ftl->ndm); + status = ndmReadPages(ftl->start_pn + staged->ppn0, staged->run_cnt, staged->buf, + ftl->spare_buf, ftl->ndm); // Adjust data buffer pointer. staged->buf += staged->run_cnt * ftl->page_size; @@ -183,7 +183,7 @@ int FtlnRdPage(FTLN ftl, ui32 ppn, void* rd_buf) { // Read page from flash. If error, set errno/fatal flag/return -1. ++ftl->stats.read_page; - status = ftl->read_pages(ftl->start_pn + ppn, 1, rd_buf, ftl->spare_buf, ftl->ndm); + status = ndmReadPages(ftl->start_pn + ppn, 1, rd_buf, ftl->spare_buf, ftl->ndm); if (status < 0) return FtlnFatErr(ftl); diff --git a/zircon/system/ulib/ftl/ftln/ftln_util.c b/zircon/system/ulib/ftl/ftln/ftln_util.c index 4197c7cd1981cf7bc4e3da97d2e46020d7c2f828..6b1f132ce004ef33fe40dab043d02640d3a55235 100644 --- a/zircon/system/ulib/ftl/ftln/ftln_util.c +++ b/zircon/system/ulib/ftl/ftln/ftln_util.c @@ -2,9 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ftlnp.h" +#include <stdarg.h> +#include <string.h> -#include <strings.h> +#include "ftlnp.h" // Local Function Definitions @@ -386,7 +387,7 @@ int FtlnReport(void* vol, ui32 msg, ...) { // Set TargetFTL-NDM driver call counts and reset internal ones. buf->xfs.drvr_stats.ftl.ndm = ftl->stats; - bzero(&ftl->stats, sizeof(ftl_ndm_stats)); + memset(&ftl->stats, 0, sizeof(ftl_ndm_stats)); // Return success. return 0; @@ -462,7 +463,7 @@ int FtlnEraseBlk(FTLN ftl, ui32 b) { // Call driver to erase block. Return -1 if error. ++ftl->stats.erase_block; - if (ftl->erase_block(ftl->start_pn + b * ftl->pgs_per_blk, ftl->ndm)) + if (ndmEraseBlock(ftl->start_pn + b * ftl->pgs_per_blk, ftl->ndm)) return FtlnFatErr(ftl); // Increment block wear count and possibly adjust highest. @@ -622,7 +623,7 @@ void FtlnDecUsed(FTLN ftl, ui32 pn, ui32 vpn) { #if FTLN_DEBUG // Read page spare area and assert VPNs match. ++ftl->stats.read_spare; - PfAssert(ftl->read_spare(ftl->start_pn + pn, ftl->spare_buf, ftl->ndm) >= 0); + PfAssert(ndmReadSpare(ftl->start_pn + pn, ftl->spare_buf, ftl->ndm) >= 0); PfAssert(GET_SA_VPN(ftl->spare_buf) == vpn); #endif } //lint !e818 diff --git a/zircon/system/ulib/ftl/ftln/ftlnp.h b/zircon/system/ulib/ftl/ftln/ftlnp.h index 8389072af5d5a9b8225eda96f92358d5c4e9557a..044472087d2dabc026b4b41f4a5841f821dc2d63 100644 --- a/zircon/system/ulib/ftl/ftln/ftlnp.h +++ b/zircon/system/ulib/ftl/ftln/ftlnp.h @@ -8,10 +8,10 @@ #include <errno.h> #include <string.h> -#include <sys.h> +#include <ftl_private.h> #include <fsprivate.h> #include <kprivate/ndm.h> -#include <kprivate/ftl_mc.h> +#include <ftl_mc.h> // // Configuration. @@ -164,68 +164,55 @@ typedef struct ftln* FTLN; typedef const struct ftln* CFTLN; struct ftln { - CircLink link; // volume list link - - // Driver Functions - int (*write_page)(ui32 pn, const void* data, void* spare, void* ndm); - int (*read_spare)(ui32 pn, void* spare, void* ndm); - int (*read_pages)(ui32 start_pn, ui32 count, void* data, void* spare, void* ndm); - int (*write_pages)(ui32 start_pn, ui32 count, const void* data, void* spare, void* ndm); - int (*page_check)(ui32 pn, ui8* data, ui8* spare, void* ndm); - int (*xfer_page)(ui32 old_pn, ui32 new_pn, ui8* data, ui8* spare, void* ndm); - int (*erase_block)(ui32 pn, void* ndm); -#if INC_FTL_NDM_MLC - ui32 (*pair_offset)(ui32 page_offset, void* ndm); -#endif + CircLink link; // volume list link // Driver Dependent Variables - ui32 num_pages; // total number of pages - ui32 pgs_per_blk; // number of pages in a block - ui32 block_size; // block size in bytes - ui32 num_blks; // number of blocks - ui32 page_size; // page size in bytes - ui32 start_pn; // first page on device for volume - void* ndm; // pointer to NDM this FTL belongs to + ui32 num_pages; // total number of pages + ui32 pgs_per_blk; // number of pages in a block + ui32 block_size; // block size in bytes + ui32 num_blks; // number of blocks + ui32 page_size; // page size in bytes + ui32 start_pn; // first page on device for volume + void* ndm; // pointer to NDM this FTL belongs to - ui32 flags; // holds various FTL flags - ui32* bdata; // block metadata: flags and counts - ui8* blk_wc_lag; // amount block erase counts lag 'high_wc' - ui32* mpns; // array holding phy page # of map pages + ui32 flags; // holds various FTL flags + ui32* bdata; // block metadata: flags and counts + ui8* blk_wc_lag; // amount block erase counts lag 'high_wc' + ui32* mpns; // array holding phy page # of map pages - FTLMC* map_cache; // handle to map page cache - ui32 free_vpn; // next free page for volume page write - ui32 free_mpn; // next free page for map page write - ui32 mappings_per_mpg; // number of phys page numbers per map page - ui32 num_vpages; // number of volume pages - ui32 num_free_blks; // number of free blocks - ui32 num_map_pgs; // number of pages holding map data - ui32 high_wc; // highest block wear count - ui32 high_bc; // highest map block write count - ui32 max_rc; // per block read wear limit - ui32 max_rc_blk; // if not -1, # of block w/high read cnt - ui32 high_bc_mblk; // last map block - ui32 high_bc_mblk_po; // used page offset on last map block - ui32 resume_vblk; // vblk in interrupted recycle recovery - ui32 resume_tblk; // tmp blk for interrupted recycle recovery - ui32 resume_po; // resume vblk's highest used page offset + FTLMC* map_cache; // handle to map page cache + ui32 free_vpn; // next free page for volume page write + ui32 free_mpn; // next free page for map page write + ui32 mappings_per_mpg; // number of phys page numbers per map page + ui32 num_vpages; // number of volume pages + ui32 num_free_blks; // number of free blocks + ui32 num_map_pgs; // number of pages holding map data + ui32 high_wc; // highest block wear count + ui32 high_bc; // highest map block write count + ui32 max_rc; // per block read wear limit + ui32 max_rc_blk; // if not -1, # of block w/high read cnt + ui32 high_bc_mblk; // last map block + ui32 high_bc_mblk_po; // used page offset on last map block + ui32 resume_vblk; // vblk in interrupted recycle recovery + ui32 resume_tblk; // tmp blk for interrupted recycle recovery + ui32 resume_po; // resume vblk's highest used page offset #if INC_ELIST - ui32 elist_blk; // if valid, # of block holding erased list + ui32 elist_blk; // if valid, # of block holding erased list #endif - ftl_ndm_stats stats; // driver call counts + ftl_ndm_stats stats; // driver call counts - ui8* main_buf; // NAND main page buffer - ui8* spare_buf; // spare buffer for single/multi-pg access + ui8* main_buf; // NAND main page buffer + ui8* spare_buf; // spare buffer for single/multi-pg access - ui8 type; // type of NAND - SLC or MLC - ui8 eb_size; // spare area size in bytes - ui8 copy_end_found; // vblk resume copy-end mark found - ui8 deferment; // # of recycles before applying wear limit + ui8 eb_size; // spare area size in bytes + ui8 copy_end_found; // vblk resume copy-end mark found + ui8 deferment; // # of recycles before applying wear limit #if FTLN_DEBUG - ui8 max_wc_lag; // maximum observed lag below hi wear count - ui8 max_wc_over; // # of times max WC (0xFF) was exceeded + ui8 max_wc_lag; // maximum observed lag below hi wear count + ui8 max_wc_over; // # of times max WC (0xFF) was exceeded #endif #if FS_ASSERT - ui8 assert_no_recycle; // test no recycle changes physical page # + ui8 assert_no_recycle; // test no recycle changes physical page # #endif char vol_name[FILENAME_MAX]; // volume name }; diff --git a/zircon/system/ulib/ftl/ftln/ndm-driver.cpp b/zircon/system/ulib/ftl/ftln/ndm-driver.cpp index ce322331de3ddb0b6207d81d5dcb93a6a0698395..507bd12d1a9957f1bea8df710a7f6a6004de82c7 100644 --- a/zircon/system/ulib/ftl/ftln/ndm-driver.cpp +++ b/zircon/system/ulib/ftl/ftln/ndm-driver.cpp @@ -6,7 +6,7 @@ #include <zircon/assert.h> -#include "kprivate/fsdriver.h" +#include <ftl_private.h> #include "kprivate/fsprivate.h" #include "kprivate/ndm.h" #include "posix.h" diff --git a/zircon/system/ulib/ftl/ftln/volume.cpp b/zircon/system/ulib/ftl/ftln/volume.cpp index 7d7c1453527ba62d14a77487dae2d5ef70c47e57..e534505815dd547f00c004aa57e703f6f7fee5bf 100644 --- a/zircon/system/ulib/ftl/ftln/volume.cpp +++ b/zircon/system/ulib/ftl/ftln/volume.cpp @@ -5,6 +5,7 @@ #include <lib/ftl/volume.h> #include <zircon/assert.h> +#include <ftl_private.h> #include "kprivate/ndm.h" #include "posix.h" diff --git a/zircon/system/ulib/ftl/inc/kprivate/fsdriver.h b/zircon/system/ulib/ftl/inc/kprivate/fsdriver.h index 6f659d6443b646a0b308733f369408b12f87d361..2da63349a3e5b1ea0e7a0f064991a157f1ce1160 100644 --- a/zircon/system/ulib/ftl/inc/kprivate/fsdriver.h +++ b/zircon/system/ulib/ftl/inc/kprivate/fsdriver.h @@ -61,46 +61,18 @@ void AssertError(int line, const char* file); /* Type Definitions */ /***********************************************************************/ -// XFS structure holding all driver information -typedef struct XfsVol { - // Driver functions - int (*write_pages)(const void* buf, ui32 frst_pg, int cnt, void* vol); - int (*read_pages)(void* buf, ui32 frst_pg, int cnt, void* vol); - int (*report)(void* vol, ui32 msg, ...); - - const char* name; // volume name - ui32 flags; // option flags - ui32 num_pages; // number of pages in volume - ui32 page_size; // page size in bytes - void* vol; // driver's volume pointer - void* ftl_volume; // ftl layer (block device) volume -} XfsVol; - // FTL NDM structure holding all driver information typedef struct { - ui32 block_size; // size of a block in bytes - ui32 num_blocks; // total number of blocks - ui32 page_size; // flash page data size in bytes - ui32 eb_size; // flash page spare size in bytes - ui32 start_page; // volume first page on flash - ui32 cached_map_pages; // number of map pages to be cached - ui32 extra_free; // volume percentage left unused - ui32 read_wear_limit; // device read-wear limit - void* ndm; // driver's NDM pointer - ui32 flags; // option flags - ui32 type; // device type - - // Driver functions: - int (*write_data_and_spare)(ui32 pn, const void* data, void* spare, void* ndm); - int (*write_pages)(ui32 start_pn, ui32 count, const void* data, void* spare, void* ndm); - int (*read_spare)(ui32 pn, void* spare, void* ndm); - int (*read_pages)(ui32 start_pn, ui32 count, void* data, void* spare, void* ndm); - int (*page_check)(ui32 pn, ui8* data, ui8* spare, void* ndm); - int (*transfer_page)(ui32 old_pn, ui32 new_pn, ui8* data, ui8* spare, void* ndm); - int (*erase_block)(ui32 pn, void* ndm); -#if INC_FTL_NDM_MLC - ui32 (*pair_offset)(ui32 page_offset, void* ndm); -#endif + ui32 block_size; // size of a block in bytes + ui32 num_blocks; // total number of blocks + ui32 page_size; // flash page data size in bytes + ui32 eb_size; // flash page spare size in bytes + ui32 start_page; // volume first page on flash + ui32 cached_map_pages; // number of map pages to be cached + ui32 extra_free; // volume percentage left unused + ui32 read_wear_limit; // device read-wear limit + void* ndm; // driver's NDM pointer + ui32 flags; // option flags } FtlNdmVol; // FS Report Events diff --git a/zircon/system/ulib/ftl/inc/kprivate/ndm.h b/zircon/system/ulib/ftl/inc/kprivate/ndm.h index 792c8d3780f924e7e0a3527f5fa463f685eef1d3..7dbfcde93b78ff2e12a1da8f955c9ae9174b7719 100644 --- a/zircon/system/ulib/ftl/inc/kprivate/ndm.h +++ b/zircon/system/ulib/ftl/inc/kprivate/ndm.h @@ -68,7 +68,7 @@ typedef struct { ui32 is_block_bad; // number of is_block_bad() calls } NdmDvrStats; -// Driver Interface Structure +// TargetNDM Configuration Structure typedef struct { ui32 num_blocks; // total number of blocks on device ui32 max_bad_blocks; // maximum number of bad blocks @@ -103,10 +103,6 @@ typedef struct { #endif } NDMDrvr; -// NDM Control Block -typedef struct ndm* NDM; -typedef const struct ndm* CNDM; - /***********************************************************************/ /* Functions Prototypes */ /***********************************************************************/ @@ -128,11 +124,6 @@ int ndmSavePartitionTable(NDM ndm); int ndmDelVols(CNDM ndm); int ndmDelVol(CNDM ndm, ui32 part_num); -// User Volume API -int ndmEraseBlock(ui32 pn, void* ndm_ptr); -int ndmReadPages(ui32 start_pn, ui32 count, void* data, void* spare, void* ndm_ptr); -int ndmWritePages(ui32 start_pn, ui32 count, const void* data, void* spare, void* ndm_ptr); - // FTL Volume API int ndmAddVolFTL(NDM ndm, ui32 part_no, FtlNdmVol* ftl, XfsVol* xfs); diff --git a/zircon/system/ulib/ftl/inc/sys.h b/zircon/system/ulib/ftl/inc/sys.h index 91ae7a1dfe3adce7df2605d2ec2e23e0dbeedc42..67887992ddefff23d82df490edfb181075945b04 100644 --- a/zircon/system/ulib/ftl/inc/sys.h +++ b/zircon/system/ulib/ftl/inc/sys.h @@ -8,38 +8,9 @@ extern "C" { #endif -#include <stdio.h> -#include <stdarg.h> #include <stdlib.h> -#include <time.h> #include <targetos.h> -/***********************************************************************/ -/* Symbol Definitions */ -/***********************************************************************/ -#define VERBOSE 1 - -/***********************************************************************/ -/* Definitions related to reading/writing NVRAM memory. */ -/***********************************************************************/ -int NvRead(const char* name, void* data, int type); -int NvReadBin(const char* name, void* data, int len); -int NvReadStr(const char* name, void* data, int maxlen); -int NvWrite(const char* name, const void* data, int type); -int NvWriteBin(const char* name, const void* data, int len); -int NvReadBinSize(const char* name); -#define NV_BYTE 0 -#define NV_SHORT 1 -#define NV_LONG 2 -#define NV_STRING 3 -#define NV_IP_ADDR 4 -#define NV_ETH_ADDR 5 -#define NV_ERR_LOG 6 -#define NV_IP6_ADDR 7 -#define NV_BINARY 8 -int NvDelete(const char* name, int type); -void NvSave(void); - void free_clear(void* alloc_ptr_addr); // Cache Line-Aligned Allocation/Deallocation Routines diff --git a/zircon/system/ulib/ftl/ndm/ndm_init.c b/zircon/system/ulib/ftl/ndm/ndm_init.c index e87040a70858cfc6071c87824bc532cb05bc6764..7aaa52e368419a6bd3576b168e992521070230c6 100644 --- a/zircon/system/ulib/ftl/ndm/ndm_init.c +++ b/zircon/system/ulib/ftl/ndm/ndm_init.c @@ -1153,10 +1153,9 @@ NDM ndmAddDev(const NDMDrvr* dvr) { if (FLAG_IS_SET(dvr->flags, FSF_TRANSFER_PAGE)) { ndm->dev_ndm = ndm->dev; ndm->xfr_page = dvr->transfer_page; - } // Else use internal read-page/write-page substitute. - else { + } else { ndm->dev_ndm = ndm; ndm->xfr_page = ndm_xfr_page; } @@ -1167,9 +1166,6 @@ NDM ndmAddDev(const NDMDrvr* dvr) { ndm->write_pages = dvr->write_pages; } - // Set the device type. - ndm->dev_type = dvr->type; - // Initialize the NDM. if (init_ndm(ndm)) goto ndmAddDe_err; diff --git a/zircon/system/ulib/ftl/ndm/ndm_intrnl.c b/zircon/system/ulib/ftl/ndm/ndm_intrnl.c index a0e0b23258e7e2d8c52c8a8f6d9f089ab6259637..a3e8919c034c9b18b323a03ad3c35cca49517909 100644 --- a/zircon/system/ulib/ftl/ndm/ndm_intrnl.c +++ b/zircon/system/ulib/ftl/ndm/ndm_intrnl.c @@ -165,11 +165,10 @@ static int wr_ctrl_page(NDM ndm, ui32 cpc, ui32* curr_pnp, ui32* badblkp) { if (rc == -2) { FsError2(NDM_EIO, EIO); return rc; - } // Else bad block caused write failure, output block number and // return bad block indication. - else { + } else { PfAssert(rc == -1); #if NDM_DEBUG printf("wr_ctrl_page: bad block for #%u at page #%u\n", cpc, cpn); @@ -688,8 +687,7 @@ static ui32 get_pbn(NDM ndm, ui32 vbn, int reason) { if (reason == WR_MAPPING) { ndm->last_wr_pbn = bn; ndm->last_wr_vbn = vbn; - } else // reason == RD_MAPPING - { + } else { // reason == RD_MAPPING ndm->last_rd_pbn = bn; ndm->last_rd_vbn = vbn; } @@ -701,15 +699,15 @@ static ui32 get_pbn(NDM ndm, ui32 vbn, int reason) { // write_page: Write a page to flash for FTL // // Inputs: ndm = pointer to NDM control block -// pn = virtual page number +// vpn = virtual page number // buf = pointer to main page buffer array // spare = pointer to spare page buffer array // action = NDM_NONE, NDM_ECC, or NDM_ECC_VAL // // Returns: 0 on success, -2 on fatal error // -static int write_page(NDM ndm, ui32 vpn, const ui8* data, ui8* spare, int action) { - ui32 vbn, bn, pn; +static int write_page(NDM ndm, uint32_t vpn, const ui8* buf, ui8* spare, int action) { + uint32_t vbn, bn, pn; int rc; // Compute the virtual block number and check for error. @@ -730,7 +728,7 @@ static int write_page(NDM ndm, ui32 vpn, const ui8* data, ui8* spare, int action pn = bn * ndm->pgs_per_blk + vpn % ndm->pgs_per_blk; // Call TargetNDM driver to write the page. - rc = ndm->write_page(pn, data, spare, action, ndm->dev); + rc = ndm->write_page(pn, buf, spare, action, ndm->dev); // Return 0 if successful. if (rc == 0) @@ -751,21 +749,72 @@ static int write_page(NDM ndm, ui32 vpn, const ui8* data, ui8* spare, int action } } //lint !e818 -// ftl_wr_pg: FTL driver function - write page (data + spare) +// read_page: FTL driver function - read page (data only) +// +// Inputs: vpn = virtual page number +// buf = pointer to buffer to copy data to +// ndm = NDM control block handle +// +// Returns: 0 on success, -1 on uncorrectable ECC error, -2 on +// permanent fatal error, 1 if block page belongs to +// needs to be recycled +// +static int read_page(ui32 vpn, void* buf, NDM ndm) { + ui32 vbn, bn, pn; + int status; + + // Compute the virtual block number based on virtual page number. + vbn = vpn / ndm->pgs_per_blk; + if (vbn >= ndm->num_vblks) { + FsError2(NDM_ASSERT, EINVAL); + return -2; + } + + // Grab exclusive access to TargetNDM internals. + semPend(ndm->sem, WAIT_FOREVER); + + // Get the physical block number from virtual one. + bn = get_pbn(ndm, vbn, RD_MAPPING); + if (bn == (ui32)-1) { + semPostBin(ndm->sem); + return -2; + } + + // Compute physical page number. + pn = bn * ndm->pgs_per_blk + vpn % ndm->pgs_per_blk; + + // Read decode page data. + status = ndm->read_page(pn, buf, ndm->spare_buf, ndm->dev); + + // Release exclusive access to TargetNDM internals. + semPostBin(ndm->sem); + + // If error, set errno. Return status. + if (status) { + if (status == -1) + FsError2(NDM_RD_ECC_FAIL, EINVAL); + else if (status == -2) + FsError2(NDM_EIO, EIO); + } + return status; +} + +// Global Function Definitions + +// ndmWritePage: FTL driver function - write page (data + spare) // // Inputs: vpn = virtual page number // data = pointer to buffer containing data to write // spare = pointer to buffer containing spare bytes -// ndm_ptr = NDM control block handle +// ndm = NDM control block handle // // Returns: 0 on success, -2 on fatal error // -static int ftl_wr_pg(ui32 vpn, const void* data, void* spare, void* ndm_ptr) { +int ndmWritePage(uint32_t vpn, const ui8* data, ui8* spare, NDM ndm) { int action, status; - NDM ndm = ndm_ptr; // If volume block, just ECC, else request validity checks too. - if (RD32_LE(&((ui8*)spare)[5]) == (ui32)-1) + if (RD32_LE(&spare[5]) == (ui32)-1) action = NDM_ECC; else action = NDM_ECC_VAL; @@ -781,18 +830,17 @@ static int ftl_wr_pg(ui32 vpn, const void* data, void* spare, void* ndm_ptr) { return status; } //lint !e818 -// ftl_rd_spare: FTL driver function - read/decode page spare area +// ndmReadSpare: FTL driver function - read/decode page spare area // // Inputs: vpn = virtual page number // spare = buffer to read sparea area into -// ndm_ptr = NDM control block handle +// ndm = NDM control block handle // // Returns: 0 on success, -1 on ECC error, -2 on fatal error, 1 if // block page belongs to needs to be recycled // -static int ftl_rd_spare(ui32 vpn, void* spare, void* ndm_ptr) { - ui32 vbn, bn, pn; - NDM ndm = ndm_ptr; +int ndmReadSpare(uint32_t vpn, ui8* spare, NDM ndm) { + uint32_t vbn, bn, pn; int status; // Compute virtual block number. Return -2 if out-of-range. @@ -825,19 +873,18 @@ static int ftl_rd_spare(ui32 vpn, void* spare, void* ndm_ptr) { return status; } -// ftl_check_pg: FTL driver function - determine status of a page +// ndmCheckPage: FTL driver function - determine status of a page // // Inputs: vpn = virtual page number // data = buffer that will hold page data // spare = buffer that will hold page spare -// ndm_ptr = NDM control block handle +// ndm = NDM control block handle // // Returns: -1 if error, else NDM_PAGE_ERASED (0), NDM_PAGE_VALID // (1), or NDM_PAGE_INVALID (2) // -static int ftl_check_pg(ui32 vpn, ui8* data, ui8* spare, void* ndm_ptr) { - NDM ndm = ndm_ptr; - ui32 vbn, bn, pn; +int ndmCheckPage(uint32_t vpn, ui8* data, ui8* spare, NDM ndm) { + uint32_t vbn, bn, pn; int status; // Compute the virtual block number. @@ -869,71 +916,19 @@ static int ftl_check_pg(ui32 vpn, ui8* data, ui8* spare, void* ndm_ptr) { return status; } -// read_page: FTL driver function - read page (data only) -// -// Inputs: vpn = virtual page number -// buf = pointer to buffer to copy data to -// ndm_ptr = NDM control block handle -// -// Returns: 0 on success, -1 on uncorrectable ECC error, -2 on -// permanent fatal error, 1 if block page belongs to -// needs to be recycled -// -static int read_page(ui32 vpn, void* buf, void* ndm_ptr) { - NDM ndm = ndm_ptr; - ui32 vbn, bn, pn; - int status; - - // Compute the virtual block number based on virtual page number. - vbn = vpn / ndm->pgs_per_blk; - if (vbn >= ndm->num_vblks) { - FsError2(NDM_ASSERT, EINVAL); - return -2; - } - - // Grab exclusive access to TargetNDM internals. - semPend(ndm->sem, WAIT_FOREVER); - - // Get the physical block number from virtual one. - bn = get_pbn(ndm, vbn, RD_MAPPING); - if (bn == (ui32)-1) { - semPostBin(ndm->sem); - return -2; - } - - // Compute physical page number. - pn = bn * ndm->pgs_per_blk + vpn % ndm->pgs_per_blk; - - // Read decode page data. - status = ndm->read_page(pn, buf, ndm->spare_buf, ndm->dev); - - // Release exclusive access to TargetNDM internals. - semPostBin(ndm->sem); - - // If error, set errno. Return status. - if (status) { - if (status == -1) - FsError2(NDM_RD_ECC_FAIL, EINVAL); - else if (status == -2) - FsError2(NDM_EIO, EIO); - } - return status; -} - -// ftl_xfr_page: FTL driver function - transfer a page +// ndmTransferPage: FTL driver function - transfer a page // // Inputs: old_vpn = old virtual page number // new_vpn = new virtual page number // buf = temporary buffer for swapping main page data // spare = buffer holding new page's spare data -// ndm_ptr = NDM control block handle +// ndm = NDM control block handle // // Returns: 0 on success, -2 on fatal error, 1 on ECC decode error // -static int ftl_xfr_page(ui32 old_vpn, ui32 new_vpn, ui8* buf, ui8* spare, void* ndm_ptr) { - ui32 old_vbn, new_vbn, old_bn, new_bn, old_pn, new_pn; +int ndmTransferPage(uint32_t old_vpn, uint32_t new_vpn, ui8* buf, ui8* spare, NDM ndm) { + uint32_t old_vbn, new_vbn, old_bn, new_bn, old_pn, new_pn; int status, action; - NDM ndm = ndm_ptr; // Grab exclusive access to TargetNDM internals. semPend(ndm->sem, WAIT_FOREVER); @@ -1004,23 +999,19 @@ static int ftl_xfr_page(ui32 old_vpn, ui32 new_vpn, ui8* buf, ui8* spare, void* } //lint !e818 #if INC_FTL_NDM_MLC -// pair_offset: FTL driver function (MLC NAND) - pair offset +// ndmPairOffset: FTL driver function (MLC NAND) - pair offset // // Inputs: page_offset = page offset within block -// ndm_ptr = NDM control block handle +// ndm = NDM control block handle // // Returns: Pair page offset within block if any, page offset // otherwise // -static ui32 pair_offset(ui32 page_offset, void* ndm_ptr) { - NDM ndm = ndm_ptr; - +uint32_t ndmPairOffset(uint32_t page_offset, CNDM ndm) { return ndm->pair_offset(page_offset, ndm->dev); } #endif // INC_FTL_NDM_MLC -// Global Function Definitions - // ndmMarkBadBlock: Mark virtual block bad and do bad block recovery // // Inputs: ndm = pointer to NDM control block @@ -1296,12 +1287,12 @@ ui32 ndmGetNumVBlocks(CNDM ndm) { // // Inputs: ndm = pointer to NDM control block // part_num = NDM partition number -// ftl = pointer to FTL config structure +// ftl_cfg = pointer to FTL config structure // xfs = XFS volume information // // Returns: 0 on success, -1 on error // -int ndmAddVolFTL(NDM ndm, ui32 part_num, FtlNdmVol* ftl, XfsVol* xfs) { +int ndmAddVolFTL(NDM ndm, ui32 part_num, FtlNdmVol* ftl_cfg, XfsVol* xfs) { NDMPartition* part; // Check partition number. @@ -1313,32 +1304,17 @@ int ndmAddVolFTL(NDM ndm, ui32 part_num, FtlNdmVol* ftl, XfsVol* xfs) { if (part->first_block + part->num_blocks > ndm->num_vblks) return FsError2(NDM_CFG_ERR, ENOSPC); - // Set the fields dependent on flash geometry. - ftl->page_size = ndm->page_size; - ftl->eb_size = ndm->eb_size; - ftl->block_size = ndm->block_size; - - // Set up the non-customizable part of the FTL/XFS drivers. - ftl->ndm = ndm; - ftl->start_page = part->first_block * ndm->pgs_per_blk; - ftl->num_blocks = part->num_blocks; - ftl->type = ndm->dev_type; + // Assign the NDM-supplied configuration. + ftl_cfg->page_size = ndm->page_size; + ftl_cfg->eb_size = ndm->eb_size; + ftl_cfg->block_size = ndm->block_size; + ftl_cfg->ndm = ndm; + ftl_cfg->start_page = part->first_block * ndm->pgs_per_blk; + ftl_cfg->num_blocks = part->num_blocks; xfs->name = part->name; - // Provide the TargetNDM lower-level interface to TargetFTL-NDM. - ftl->erase_block = ndmEraseBlock; - ftl->write_data_and_spare = ftl_wr_pg; - ftl->write_pages = ndmWritePages; - ftl->read_spare = ftl_rd_spare; - ftl->read_pages = ndmReadPages; - ftl->page_check = ftl_check_pg; - ftl->transfer_page = ftl_xfr_page; -#if INC_FTL_NDM_MLC - ftl->pair_offset = pair_offset; -#endif - // Add an FTL to this partition. Return status. - return FtlnAddVol(ftl, xfs); + return FtlnAddVol(ftl_cfg, xfs); } // ndmReadPages: FTL driver function - read multiple consecutive @@ -1346,20 +1322,19 @@ int ndmAddVolFTL(NDM ndm, ui32 part_num, FtlNdmVol* ftl, XfsVol* xfs) { // // Inputs: vpn = starting virtual page number // count = number of consecutive virtual pages to read -// data = pointer to buffer to copy main page data to +// buf = pointer to buffer to copy main page data to // spare = points to array of page spare data sets -// ndm_ptr = NDM control block handle +// ndm = NDM control block handle // // Returns: -2 on fatal error, -1 on error, 0 on success, 1 if // block needs to be recycled // -int ndmReadPages(ui32 vpn, ui32 count, void* data, void* spare, void* ndm_ptr) { - NDM ndm = ndm_ptr; +int ndmReadPages(uint32_t vpn, uint32_t count, ui8* buf, ui8* spare, NDM ndm) { int status; // If NDM driver supplies read_pages(), use it. if (ndm->read_pages) { - ui32 vbn, bn, pn; + uint32_t vbn, bn, pn; // Compute the virtual block number based on virtual page number. vbn = vpn / ndm->pgs_per_blk; @@ -1382,7 +1357,7 @@ int ndmReadPages(ui32 vpn, ui32 count, void* data, void* spare, void* ndm_ptr) { pn = bn * ndm->pgs_per_blk + vpn % ndm->pgs_per_blk; // Read pages. - status = ndm->read_pages(pn, count, data, spare, ndm->dev); + status = ndm->read_pages(pn, count, buf, spare, ndm->dev); // Release exclusive access to NDM and return status. semPostBin(ndm->sem); @@ -1391,14 +1366,13 @@ int ndmReadPages(ui32 vpn, ui32 count, void* data, void* spare, void* ndm_ptr) { // Else loop over all pages, reading one at a time. else { - ui32 i; + uint32_t i; int rd_status; - ui8* buf = data; // Loop over virtual pages. for (status = 0, i = 0; i < count; ++i, ++vpn, buf += ndm->page_size) { // Issue current page read request. - rd_status = read_page(vpn, buf, ndm_ptr); + rd_status = read_page(vpn, buf, ndm); // If error, return. if (rd_status < 0) @@ -1421,13 +1395,12 @@ int ndmReadPages(ui32 vpn, ui32 count, void* data, void* spare, void* ndm_ptr) { // count = number of consecutive virtual pages to write // data = points to array of page main data sets // spare = points to array of page spare data sets -// ndm_ptr = NDM control block handle +// ndm = NDM control block handle // // Returns: -1 on error, 0 on success // -int ndmWritePages(ui32 vpn, ui32 count, const void* data, void* spare, void* ndm_ptr) { +int ndmWritePages(uint32_t vpn, uint32_t count, const ui8* data, ui8* spare, NDM ndm) { int action, rc = 0; - NDM ndm = ndm_ptr; // Ensure all writes are to the same virtual block. PfAssert(count); @@ -1444,7 +1417,7 @@ int ndmWritePages(ui32 vpn, ui32 count, const void* data, void* spare, void* ndm // If NDM driver supplies write_pages(), use it. if (ndm->write_pages) { - ui32 vbn; + uint32_t vbn; // Compute the virtual block number based on virtual page number. vbn = vpn / ndm->pgs_per_blk; @@ -1455,11 +1428,11 @@ int ndmWritePages(ui32 vpn, ui32 count, const void* data, void* spare, void* ndm // Writing to flash until success or failure other than bad block. for (;;) { - ui32 bn, pn; + uint32_t bn, pn; // Get the physical block number from virtual one. bn = get_pbn(ndm, vbn, WR_MAPPING); - if (bn == (ui32)-1) { + if (bn == (uint32_t)-1) { rc = -1; break; } @@ -1489,7 +1462,7 @@ int ndmWritePages(ui32 vpn, ui32 count, const void* data, void* spare, void* ndm // Else loop over all pages, writing one at a time. else { - ui32 past = vpn + count; + uint32_t past = vpn + count; const ui8* curr_data = data; ui8* curr_spare = spare; @@ -1634,12 +1607,11 @@ int ndmWritePartition(NDM ndm, const NDMPartition* part, ui32 part_num, const ch // ndmEraseBlock: Erase a block // // Inputs: vpn = base virtual page for block to be erased -// ndm_ptr = NDM control block handle +// ndm = NDM control block handle // // Returns: 0 on success, -1 on fatal error // -int ndmEraseBlock(ui32 vpn, void* ndm_ptr) { - NDM ndm = ndm_ptr; +int ndmEraseBlock(ui32 vpn, NDM ndm) { ui32 vbn, bn, pn; int status; diff --git a/zircon/system/ulib/ftl/ndm/ndmp.h b/zircon/system/ulib/ftl/ndm/ndmp.h index 5e0a408fc66b613f6368ee96eedc4b7f8ad0fe74..d3600473a0590edf819cf127c6afb8a7990832d2 100644 --- a/zircon/system/ulib/ftl/ndm/ndmp.h +++ b/zircon/system/ulib/ftl/ndm/ndmp.h @@ -11,6 +11,7 @@ #include <stdio.h> #include <errno.h> +#include <ftl_private.h> #include <sys.h> #include <kprivate/ndm.h> @@ -131,7 +132,6 @@ struct ndm { ui32 pgs_per_blk; // number of pages in a block ui32 page_size; // page size in bytes ui8 eb_size; // spare area size in bytes - ui8 dev_type; // NAND device type }; // diff --git a/zircon/system/ulib/ftl/utils/aalloc.c b/zircon/system/ulib/ftl/utils/aalloc.c index 3441ec93470df9dfb42172a4d65e3381c230dbc7..aa4e1008f945dd76b8c388b0cbe58f81f5267da5 100644 --- a/zircon/system/ulib/ftl/utils/aalloc.c +++ b/zircon/system/ulib/ftl/utils/aalloc.c @@ -6,9 +6,10 @@ #include <stdlib.h> #include <sys.h> #include <bsp.h> +#include <ftl_private.h> #ifndef CACHE_LINE_SIZE -#error bsp.h must define CACHE_LINE_SIZE +#error CACHE_LINE_SIZE is undefined #endif // Free allocated memory and clear pointer to it. diff --git a/zircon/system/ulib/ftl/utils/crc32_tbl.c b/zircon/system/ulib/ftl/utils/crc32_tbl.c index 313d9ce77d6cb399e23295e8e8fdb14c46a3d22e..712e05007d5d08adff8272b095fa67162b3987c9 100644 --- a/zircon/system/ulib/ftl/utils/crc32_tbl.c +++ b/zircon/system/ulib/ftl/utils/crc32_tbl.c @@ -3,6 +3,7 @@ // found in the LICENSE file. #include <sys.h> +#include <ftl_private.h> // CRC Lookup Table. const ui32 Crc32Tbl[256] = { diff --git a/zircon/system/ulib/ftl/utils/fsmem.c b/zircon/system/ulib/ftl/utils/fsmem.c index a137cf7133856a9c95c08a37194ea60c711ad6ae..fccdd9fdfde81bab9e1c0c35be8c651fcb10041b 100644 --- a/zircon/system/ulib/ftl/utils/fsmem.c +++ b/zircon/system/ulib/ftl/utils/fsmem.c @@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <fsprivate.h> #include <stdlib.h> + +#include <ftl_private.h> +#include <fsprivate.h> #include <sys.h> // Wrapper for malloc() void* FsMalloc(size_t size) { void* mem = malloc(size); - if (mem == NULL) - FsError(ENOMEM); return mem; } @@ -18,8 +18,6 @@ void* FsMalloc(size_t size) { // Wrapper for calloc() void* FsCalloc(size_t nitems, size_t size) { void* mem = calloc(nitems, size); - if (mem == NULL) - FsError(ENOMEM); return mem; } @@ -27,8 +25,6 @@ void* FsCalloc(size_t nitems, size_t size) { // Wrapper for aalloc() void* FsAalloc(size_t size) { void* mem = aalloc(size); - if (mem == NULL) - FsError(ENOMEM); return mem; } diff --git a/zircon/system/ulib/ftl/utils/fsys.c b/zircon/system/ulib/ftl/utils/fsys.c index 657beefbb2b8f5c407c587c48fc5991f05df74b2..496bd312ba8131744c4d546fa2d94cb2330bf383 100644 --- a/zircon/system/ulib/ftl/utils/fsys.c +++ b/zircon/system/ulib/ftl/utils/fsys.c @@ -2,11 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <sys.h> +#include <ftl_private.h> #include <kprivate/fsprivate.h> -#include <string.h> - // Lookup for number of bits in half byte. const ui8 NumberOnes[] = { //0 1 2 3 4 5 6 7 8 9 A B C D E F diff --git a/zircon/system/ulib/ftl/utils/fsysinit.c b/zircon/system/ulib/ftl/utils/fsysinit.c index eb54ea1dccd5ac7284d04e73f98b61bebe4aae64..c4c75f175fe34d98347a75689787b027474f435f 100644 --- a/zircon/system/ulib/ftl/utils/fsysinit.c +++ b/zircon/system/ulib/ftl/utils/fsysinit.c @@ -6,6 +6,7 @@ #include <stdio.h> #include "kernel.h" +#include <ftl_private.h> #include "fsprivate.h" #include <lib/backtrace-request/backtrace-request.h> @@ -38,5 +39,6 @@ int FtlInit(void) { FileSysSem = semCreate("fsys sem", 1, OS_FIFO); if (FileSysSem == NULL) return -1; + return 0; } diff --git a/zircon/system/ulib/ftl/utils/ftl_mc.c b/zircon/system/ulib/ftl/utils/ftl_mc.c index 4653b220c346ce921a9ea1bba97ac7c25af90108..46b3a105f4bfdf0aee95add5a7e72b1569aba44e 100644 --- a/zircon/system/ulib/ftl/utils/ftl_mc.c +++ b/zircon/system/ulib/ftl/utils/ftl_mc.c @@ -3,7 +3,9 @@ // found in the LICENSE file. #include <sys.h> -#include "ftl_mc.h" + +#include <ftl_private.h> +#include <ftl_mc.h> #include <fsprivate.h> // Configuration diff --git a/zircon/system/ulib/ftl/inc/kprivate/ftl_mc.h b/zircon/system/ulib/ftl/utils/ftl_mc.h similarity index 100% rename from zircon/system/ulib/ftl/inc/kprivate/ftl_mc.h rename to zircon/system/ulib/ftl/utils/ftl_mc.h diff --git a/zircon/system/ulib/ftl/utils/kernel.h b/zircon/system/ulib/ftl/utils/kernel.h index e2fa97750f6f1c0b458f1e24cfb9663e2b6f9db1..005ac3201b5c8f9aa5b18c44bb27f2949ed1a9cd 100644 --- a/zircon/system/ulib/ftl/utils/kernel.h +++ b/zircon/system/ulib/ftl/utils/kernel.h @@ -25,8 +25,6 @@ void semDelete(SEM* semp); void semPostBin(SEM sem); int semPend(SEM sem, int wait_opt); -#define ENOMEM 12 // out of memory - #ifdef __cplusplus } #endif