first and last commit
This commit is contained in:
commit
1bf4efd552
2612 files changed
+636500
No files matched your search
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,125 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* COMPONENT : Rainbow */
|
||||
/* MODULE : Virtual Flash Layer */
|
||||
/* NAME : VFL types definition header */
|
||||
/* FILE : VFLTypes.h */
|
||||
/* PURPOSE : This header defines Data types which are shared */
|
||||
/* by all VFL submodules */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* COPYRIGHT 2003-2005 SAMSUNG ELECTRONICS CO., LTD. */
|
||||
/* ALL RIGHTS RESERVED */
|
||||
/* */
|
||||
/* Permission is hereby granted to licensees of Samsung Electronics */
|
||||
/* Co., Ltd. products to use or abstract this computer program for the */
|
||||
/* sole purpose of implementing a product based on Samsung */
|
||||
/* Electronics Co., Ltd. products. No other rights to reproduce, use, */
|
||||
/* or disseminate this computer program, whether in part or in whole, */
|
||||
/* are granted. */
|
||||
/* */
|
||||
/* Samsung Electronics Co., Ltd. makes no representation or warranties */
|
||||
/* with respect to the performance of this computer program, and */
|
||||
/* specifically disclaims any responsibility for any damages, */
|
||||
/* special or consequential, connected with the use of this program. */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* REVISION HISTORY */
|
||||
/* */
|
||||
/* 04-AUG-2003 [HM Jung] : first writing */
|
||||
/* 14-JUL-2005 [Jaesung Jung] : reorganize code */
|
||||
/* 06-SEP-2005 [Jaesung Jung] : fix from code inspection */
|
||||
/* 24-JAN-2006 [Yangsup Lee ] : support un-pair bad block management */
|
||||
/* 31-MAR-2006 [Yangsup Lee ] : support ftl meta block wear leveling */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
#ifndef _UNDER_VFL_TYPES_H_
|
||||
#define _UNDER_VFL_TYPES_H_
|
||||
|
||||
/* Device Information Structures and defines */
|
||||
|
||||
#define VFL_META_STRUCT_VERSION 0x00000004 /* changed Oct 6th 2006 */
|
||||
#define VFL_BBT_STRUCT_VERSION 0x00000004 /* changed Oct 6th 2006 */
|
||||
|
||||
#define BBT_BLOCK_SIGNATURE (UInt8*)"DEVICEINFOBBT\0\0\0"
|
||||
#define BBT_BLOCK_SIGNATURE_SIZE 16
|
||||
|
||||
#define UNIQUE_INFO_BLOCK_SIGNATURE (UInt8*)"DEVICEUNIQUEINFO"
|
||||
#define UNIQUE_INFO_BLOCK_SIGNATURE_SIZE 16
|
||||
|
||||
#define NAND_DRIVER_SIGN_BLOCK_SIGNATURE (UInt8*)"NANDDRIVERSIGN\0\0"
|
||||
#define NAND_DRIVER_SIGN_BLOCK_SIGNATURE_SIZE 16
|
||||
|
||||
#define DIAG_INFO_BLOCK_SIGNATURE (UInt8*)"DIAGCONTROLINFO\0"
|
||||
#define DIAG_INFO_BLOCK_SIGNATURE_SIZE 16
|
||||
|
||||
#define BBT_SIZE_PER_CS ((BLOCKS_PER_CS / 8) + (BLOCKS_PER_CS % 8 ? 1 : 0))
|
||||
|
||||
#define WMR_NUM_OF_ERASE_TRIALS_FOR_INDEX_BLOCKS (4)
|
||||
|
||||
#define VFL_BLOCK_INDEX_MASK (0xFFFF)
|
||||
#define VFL_INVALID_INFO_INDEX (0xFFFF)
|
||||
|
||||
#define FPART_SPECIAL_BLK_BBT_PRIMARY_IDX (0) // Primary copy of bad block table
|
||||
#define FPART_SPECIAL_BLK_BBT_BACKUP_IDX (1) // Backup copy of bad block table
|
||||
#define FPART_SPECIAL_BLK_DEV_UNIQUE_PRIMARY_IDX (2) // Primary copy of device-unique information
|
||||
#define FPART_SPECIAL_BLK_DEV_UNIQUE_BACKUP_IDX (3) // Backup copy of device-unique information
|
||||
#define FPART_SPECIAL_BLK_DEV_SIGNATURE_IDX (4) // Driver signature
|
||||
#define FPART_SPECIAL_BLK_DIAG_CTRL_PRIMARY_IDX (5) // Primary copy of diag control bits
|
||||
#define FPART_SPECIAL_BLK_DIAG_CTRL_BACKUP_IDX (6) // Backup copy of diag control bits
|
||||
|
||||
#define FPART_COPIES_OF_SPECIAL_INFO (2) // Copies of syscfg and diag bits
|
||||
|
||||
#define MAX_NUM_SPECIAL_BLOCKS_PER_CS (8) /* This should always be 8 as BBTInfoHeaderStruct and SpecialBlockHeaderStruct should be of the same size*/
|
||||
#define MAX_NUM_OF_SPECIALS (5) /* no of special blocks ( backups not included )*/
|
||||
#define MAX_SPECIAL_BLOCK_COPIES (2)
|
||||
#define SPECIAL_BLOCK_SIGNATURE_SIZE BBT_BLOCK_SIGNATURE_SIZE
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt8 abSignature[16];
|
||||
UInt32 dwVersion;
|
||||
UInt32 adwSpecialBlocks[MAX_NUM_SPECIAL_BLOCKS_PER_CS];
|
||||
UInt32 dwBBTSize;
|
||||
} BBTInfoHeaderStruct;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 location;
|
||||
BOOL32 locationValid;
|
||||
} specialBlockLocation;
|
||||
typedef struct
|
||||
{
|
||||
UInt8 abSignature[SPECIAL_BLOCK_SIGNATURE_SIZE];
|
||||
specialBlockLocation sbLocation[MAX_SPECIAL_BLOCK_COPIES];
|
||||
} specialBlockCache;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt8 abSignature[16];
|
||||
UInt32 dwVersion;
|
||||
UInt32 adwReserved[MAX_NUM_SPECIAL_BLOCKS_PER_CS];
|
||||
UInt32 dwDataSize;
|
||||
} SpecialBlockHeaderStruct;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt16 wPagesPerBlock; /* the count of pages per block */
|
||||
UInt16 wNumOfCEs;
|
||||
CheckInitialBadType checkInitialBadType;
|
||||
UInt16 wDiesPerCS;
|
||||
UInt16 wBlocksPerCS; /* the count of blocks per CS */
|
||||
|
||||
UInt16 wBlocksPerDie;
|
||||
UInt16 wDieStride;
|
||||
UInt16 wBlockStride;
|
||||
UInt16 wLastBlock;
|
||||
UInt16 wUserBlocksPerCS;
|
||||
UInt16 wBytesPerPage; /* bytes per page (main) */
|
||||
UInt16 wBytesPerSpare;
|
||||
UInt16 wBytesPerBLPage;
|
||||
} UnderVFLDeviceInfo;
|
||||
|
||||
#endif /* _UNDER_VFL_TYPES_H_ */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,305 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* COMPONENT : Rainbow */
|
||||
/* MODULE : FTL */
|
||||
/* NAME : FTL types definition header */
|
||||
/* FILE : FTLTypes.h */
|
||||
/* PURPOSE : This header defines Data types which are shared */
|
||||
/* by all FTL submodules */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* COPYRIGHT 2003-2005 SAMSUNG ELECTRONICS CO., LTD. */
|
||||
/* ALL RIGHTS RESERVED */
|
||||
/* */
|
||||
/* Permission is hereby granted to licensees of Samsung Electronics */
|
||||
/* Co., Ltd. products to use or abstract this computer program for the */
|
||||
/* sole purpose of implementing a product based on Samsung */
|
||||
/* Electronics Co., Ltd. products. No other rights to reproduce, use, */
|
||||
/* or disseminate this computer program, whether in part or in whole, */
|
||||
/* are granted. */
|
||||
/* */
|
||||
/* Samsung Electronics Co., Ltd. makes no representation or warranties */
|
||||
/* with respect to the performance of this computer program, and */
|
||||
/* specifically disclaims any responsibility for any damages, */
|
||||
/* special or consequential, connected with the use of this program. */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* REVISION HISTORY */
|
||||
/* */
|
||||
/* 22-JUL-2005 [Jaesung Jung] : first writing */
|
||||
/* 03-NOV-2005 [Yangsup Lee ] : Add wear-leveling algorithm */
|
||||
/* 14-MAR-2006 [Yangsup Lee ] : Don't use bad mark area */
|
||||
/* 29-MAR-2006 [Yangsup Lee ] : modify wear-leveling structure */
|
||||
/* 31-MAR-2006 [Yangsup Lee ] : support ftl meta block wear leveling */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
#ifndef _FTL_TYPES_H_
|
||||
#define _FTL_TYPES_H_
|
||||
|
||||
#include "WMRConfig.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// Info generated by CalcGlobal
|
||||
UInt16 wPagesPerVb; /* the count of pages per virtual block */
|
||||
UInt16 wUserVbTotal; /* the total number of data virtual block */
|
||||
UInt32 dwUserPagesTotal; /* the total number of data sector */
|
||||
UInt16 wBytesPerPage; /* bytes per page (main) */
|
||||
|
||||
UInt16 wNumOfBanks; /* the number of banks */
|
||||
} FTLWMRDeviceInfo;
|
||||
|
||||
#define PAGES_PER_SUBLK (stFTLDeviceInfo.wPagesPerVb)
|
||||
#define USER_SUBLKS_TOTAL (stFTLDeviceInfo.wUserVbTotal)
|
||||
#define USER_PAGES_TOTAL (stFTLDeviceInfo.dwUserPagesTotal)
|
||||
#define BYTES_PER_PAGE (stFTLDeviceInfo.wBytesPerPage)
|
||||
|
||||
#define BANKS_TOTAL (stFTLDeviceInfo.wNumOfBanks)
|
||||
#define WMR_NUM_OF_BANKS (8) /* the maximum number of bank */
|
||||
#define BYTES_PER_SECTOR (512)
|
||||
|
||||
#define FTL_INFO_SECTION_SIZE FTL_CXT_SECTION_SIZE
|
||||
#define FREE_SECTION_START FTL_CXT_SECTION_SIZE
|
||||
#define DATA_SECTION_START (FTL_CXT_SECTION_SIZE + FREE_SECTION_SIZE)
|
||||
|
||||
#define LOG_SECTION_SIZE (FREE_SECTION_SIZE - FREE_LIST_SIZE)
|
||||
|
||||
#define FREE_SECTION_SIZE (20)
|
||||
#define FREE_LIST_SIZE (3)
|
||||
|
||||
#define FTL_AREA_SIZE (FTL_CXT_SECTION_SIZE + FREE_SECTION_SIZE + USER_SUBLKS_TOTAL)
|
||||
|
||||
#define MAX_NUM_OF_MAP_TABLES (WMR_MAX_VB / (WMR_SECTORS_PER_PAGE_MIN * WMR_SECTOR_SIZE) + (WMR_MAX_VB % (WMR_SECTORS_PER_PAGE_MIN * WMR_SECTOR_SIZE) ? 1 : 0)) * (sizeof(UInt16))
|
||||
#define MAX_NUM_OF_EC_TABLES (WMR_MAX_VB / (WMR_SECTORS_PER_PAGE_MIN * WMR_SECTOR_SIZE) + (WMR_MAX_VB % (WMR_SECTORS_PER_PAGE_MIN * WMR_SECTOR_SIZE) ? 1 : 0)) * (sizeof(UInt32))
|
||||
#define MAX_NUM_OF_LOGCXT_MAPS (((LOG_SECTION_SIZE * WMR_MAX_PAGES_PER_BLOCK * WMR_NUM_OF_BANKS * sizeof(UInt16)) / (WMR_SECTOR_SIZE * WMR_SECTORS_PER_PAGE_MIN)) + (((LOG_SECTION_SIZE * WMR_MAX_PAGES_PER_BLOCK * WMR_NUM_OF_BANKS * sizeof(UInt16)) % (WMR_SECTOR_SIZE * WMR_SECTORS_PER_PAGE_MIN)) ? 1 : 0))
|
||||
|
||||
#define BBT_SIZE_PER_CS ((BLOCKS_PER_CS / 8) + (BLOCKS_PER_CS % 8 ? 1 : 0))
|
||||
|
||||
#if defined(FTL_SMALL_MERGE_BUFFER) && FTL_SMALL_MERGE_BUFFER
|
||||
#define FTL_SIMPLEMERGE_MIN_PAGES (4)
|
||||
#else
|
||||
#define FTL_SIMPLEMERGE_MIN_PAGES (PAGES_PER_SUBLK >> 3) /* creates a 64K to 128K buffer in current units */
|
||||
#endif
|
||||
#define FTL_RESTORE_MIN_PAGES (((FTL_AREA_SIZE * sizeof(FTLRestoreStruct)) - 1) / BYTES_PER_PAGE + 1)
|
||||
|
||||
/*
|
||||
* pstSimpleMergeDataBuffer is used in the following functions and must adhere to the following rules:
|
||||
* 1. _DoSimpleMerge() - Must be aligned to BANKS_TOTAL pages and a power of 2.
|
||||
* 2. _StoreFTLCxt() - Must be of size BANKS_TOTAL page at least.
|
||||
* 3. _FTLRestore() - Must be of size FTL_RESTORE_MIN_PAGES at least.
|
||||
*/
|
||||
#define PAGES_PER_SIMPLE_MERGE_BUFFER (1 << (WMR_LOG2(WMR_MAX(FTL_SIMPLEMERGE_MIN_PAGES, FTL_RESTORE_MIN_PAGES) - 1) + 1))
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data structure for storing the FTL log block context definition */
|
||||
/*****************************************************************************/
|
||||
#ifdef AND_COLLECT_STATISTICS
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt64 ddwPagesWrittenCnt;
|
||||
UInt64 ddwPagesReadCnt;
|
||||
UInt64 ddwFTLWriteCnt;
|
||||
UInt64 ddwFTLReadCnt;
|
||||
UInt64 ddwDoMoveMergeCnt;
|
||||
UInt64 ddwDoCopyMergeCnt1; /* case there is NO data to copy */
|
||||
UInt64 ddwDoCopyMergeCnt2; /* case there is data to copy */
|
||||
UInt64 ddwDoSimpleMergeCnt;
|
||||
UInt64 ddwMoveD2FCnt;
|
||||
UInt64 ddwFTLRestoreCnt;
|
||||
UInt64 ddwReadDisturbHandleCall;
|
||||
UInt64 ddwWearLevelCnt;
|
||||
UInt64 ddwFlushCnt;
|
||||
} FTLStatistics;
|
||||
|
||||
#define FTL_STATISTICS_DESCREPTION { \
|
||||
"ddwPagesWrittenCnt", \
|
||||
"ddwPagesReadCnt", \
|
||||
"ddwFTLWriteCnt", \
|
||||
"ddwFTLReadCnt", \
|
||||
"ddwDoMoveMergeCnt", \
|
||||
"ddwDoCopyMergeCnt1", \
|
||||
"ddwDoCopyMergeCnt2", \
|
||||
"ddwDoSimpleMergeCnt", \
|
||||
"ddwMoveD2FCnt", \
|
||||
"ddwFTLRestoreCnt", \
|
||||
"ddwReadDisturbHandleCall", \
|
||||
"ddwWearLevelCnt", \
|
||||
"ddwFlushCnt", \
|
||||
}
|
||||
|
||||
#endif /* AND_COLLECT_STATISTICS */
|
||||
|
||||
#define FTL_VERSION (0x46560001)
|
||||
#define FTL_VERSION_NOT (~(FTL_VERSION))
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data structure for log block spare area */
|
||||
/*****************************************************************************/
|
||||
typedef struct
|
||||
{
|
||||
UInt32 dwLogAge; /* log age - uses a global counter starting from 0 */
|
||||
UInt16 wVbn; /* the virtual block number of log block */
|
||||
UInt16 wLbn; /* the logical block number of log block */
|
||||
UInt16 *paPOffsetL2P; /* L2P page offset mapping table *//* size - PAGES_PER_SUBLK * sizeof(UInt16) functionality - maps pages of a logical block inside the block */
|
||||
UInt16 wFreePOffset; /* free page offset in log block *//* the next physical page to write to */
|
||||
UInt16 wNumOfValidLP; /* the number of valid page *//* the number of valid pages in the log - stay the same when rewriting a page */
|
||||
BOOL32 boolCopyMerge; /* can be copymerged or not *//* ??? */
|
||||
/* name sure this structure is aligned 16-bit */
|
||||
} LOGCxt;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt16 wLbn;
|
||||
UInt16 wVbn;
|
||||
} FTLReadRefreshStruct;
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data structure for storing the FTL context definition */
|
||||
/*****************************************************************************/
|
||||
/* NOTICE !!! */
|
||||
/* this structure is used directly to load FTL context by WMR_MEMCPY*/
|
||||
/* so the byte pad of this structure must be 0 */
|
||||
typedef struct
|
||||
{
|
||||
UInt32 dwAge; /* Cxt Write Age - Counter starting From 0xFFFFFFFF going down */
|
||||
|
||||
UInt32 dwWriteAge; /* counter starting from 0 - unique age of the first ftl write operation to the block */
|
||||
|
||||
UInt16 wNumOfFreeVb; /* number of free VB */
|
||||
UInt16 wFreeVbListTail; /* marks the first available VB in a cyclic list */
|
||||
UInt16 wWearLevelCounter; /* this counter is by the FTL to decide whether an Autowearlevel operation is needed after FTL_Write is done */
|
||||
|
||||
UInt16 awFreeVbList[FREE_SECTION_SIZE]; /* cyclic list of the free VBs */
|
||||
|
||||
UInt32 adwMapTablePtrs[MAX_NUM_OF_MAP_TABLES]; /* page address (Vpn) of the Map table pages in the Cxt block - only valid when boolFlashCxtIsValid is TRUE32 */
|
||||
UInt32 adwECTablePtrs[MAX_NUM_OF_EC_TABLES]; /* page address of the Erase Counter table */
|
||||
UInt32 adwLOGCxtMapPtrs[MAX_NUM_OF_LOGCXT_MAPS]; /* page address of the LOGCxt map table */
|
||||
|
||||
UInt16 * pawMapTable; /* cached map table logical blocks to virtual blocks - value will be recalculated in FTL_Init */
|
||||
UInt16 * pawECCacheTable; /* cached Erase counter table - value will be recalculated in FTL_Init - data is recovered from the last valid Erase Map in case of power failure */
|
||||
UInt16 * pawLOGCxtMapTable; /* pointer to the map of the logs - this is a pointer and will be calculated in the Init - data can be restored if the info is flushed */
|
||||
LOGCxt aLOGCxtTable[LOG_SECTION_SIZE + 1]; /* LOGCxt array */
|
||||
|
||||
UInt32 dwMetaWearLevelCounter; /* used to decide whether the index info super blocks need to be replaced or not (slows down VFL Cxt blocks wear) */
|
||||
UInt16 wOverErasedBlock; /* should not be used - mark the last erased vb before setting boolFlushECTable */
|
||||
|
||||
UInt16 awMapCxtVbn[FTL_CXT_SECTION_SIZE]; /* vb address of the FTL Cxt information */
|
||||
UInt32 dwCurrMapCxtPage; /* pointer to the last written Cxt info page */
|
||||
|
||||
BOOL32 boolFlashCxtIsValid; /* mark whether the FTLCxt on the flash is up to date or not */
|
||||
|
||||
// this code was added Apr 4th 2007
|
||||
UInt32 adwRCTablePtrs[MAX_NUM_OF_EC_TABLES]; /* page address of the Read Counter table */
|
||||
UInt16 * pawRCCacheTable; /* cached Erase counter table - value will be recalculated in FTL_Init - data is recovered from the last valid Erase Map in case of power failure */
|
||||
FTLReadRefreshStruct aFTLReadRefreshList[FTL_READ_REFRESH_LIST_SIZE];
|
||||
UInt32 dwRefreshListIdx;
|
||||
UInt32 dwReadsSinceLastRefreshMark;
|
||||
// this code was added Apr 20th 2007
|
||||
UInt32 adwStatPtrs[2]; // allocate 2 pages for stats
|
||||
} FTLCxt2;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
FTLCxt2 stFTLCxt;
|
||||
UInt8 abReserved[((BYTES_PER_SECTOR - 2) * sizeof(UInt32)) - sizeof(FTLCxt2)];
|
||||
UInt32 dwVersion;
|
||||
UInt32 dwVersionNot;
|
||||
} FTLMeta;
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data structure of the FTL context & virtual block mapping table definition*/
|
||||
/*****************************************************************************/
|
||||
/* NOTICE !!! */
|
||||
/* this structure is used directly to load FTL context by WMR_MEMCPY*/
|
||||
/* so the byte pad of this structure must be 0 */
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data structure for FTL context spare area */
|
||||
/*****************************************************************************/
|
||||
|
||||
/*
|
||||
Spare area of the flash:
|
||||
The implementation used here assumes a page has 12 free bytes in the redundant area to store data (index, age, etc).
|
||||
Bytes 0-7 are used for data
|
||||
Byte 8 - is currently reserved.
|
||||
Byte 9 is used for data type - bits 6-7 of the byte is 00 for VFL spare types and 01 for FTL spare types.
|
||||
Byte 10 is used to mark ECC error in LOGCxt reserved for Cxt
|
||||
Byte 11 is currently reserved
|
||||
*/
|
||||
|
||||
/* NirW - possibly need to define the next two structures as compact (i.e. no alignment should be done by the compiler). */
|
||||
|
||||
/* spare layout for SLC & MLC */
|
||||
typedef struct
|
||||
{
|
||||
UInt32 dwCxtAge; /* context age 0xFFFFFFFF --> 0x0 */
|
||||
UInt16 wLogicalNumber; /* status (confirm) mark */
|
||||
UInt8 bStatusMark; /* status (confirm) mark */
|
||||
UInt8 baReserved[1];
|
||||
UInt8 bECCMark;
|
||||
UInt8 bSpareType;
|
||||
} FTLCxtSpare;
|
||||
|
||||
/* spare layout for SLC */
|
||||
typedef struct
|
||||
{
|
||||
UInt32 dwLPOffset;
|
||||
UInt32 dwWriteAge;
|
||||
UInt8 bReserved;
|
||||
UInt8 bSpareType;
|
||||
} LOGSpare;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt16 wLbn; /* this struct can only handle 32K super blocks */
|
||||
UInt8 bSpareType;
|
||||
UInt8 bIsBlkFull; /* 0 - block is full; 1 - page 0 is written; 2 - page 0 is empty; 3 - page 0 is invalid */
|
||||
UInt32 dwWriteAge;
|
||||
} FTLRestoreStruct;
|
||||
|
||||
FTLCxt2 * FTL_GetFTLCxt2Ptr(void);
|
||||
|
||||
// defines
|
||||
/*
|
||||
FTL_SPARE_TYPE_LOG - log block (either not full or not fill consecutively
|
||||
we should look for this mark in page 0 and in the last page of the block for recovery
|
||||
*/
|
||||
#define FTL_SPARE_TYPE_LOG 0x40
|
||||
/*
|
||||
FTL_SPARE_TYPE_DATA - either originally data block or a log block filled from page 0 to the end (consecutively) -
|
||||
look for this mark at the last page of the block
|
||||
*/
|
||||
#define FTL_SPARE_TYPE_DATA 0x41
|
||||
|
||||
#define FTL_SPARE_TYPE_CXT 0x42 /* used only in restore operation */
|
||||
#define FTL_SPARE_TYPE_CXT_INDEX 0x43
|
||||
#define FTL_SPARE_TYPE_CXT_MAP_TABLE 0x44
|
||||
#define FTL_SPARE_TYPE_CXT_LOGCXT_MAP 0x45
|
||||
#define FTL_SPARE_TYPE_CXT_EC_TABLE 0x46
|
||||
#define FTL_SPARE_TYPE_CXT_STAT 0x47
|
||||
|
||||
#define FTL_SPARE_IS_CXT_MARK(x) ((x) >= FTL_SPARE_TYPE_CXT_INDEX && (x) <= FTL_SPARE_TYPE_CXT_INVALID)
|
||||
|
||||
#define FTL_SPARE_TYPE_FREE 0x48 /* this is not to be written on the flash but to use as a mark that a block can be erased */
|
||||
#define FTL_SPARE_TYPE_CXT_RC_TABLE 0x49
|
||||
#define FTL_SPARE_TYPE_CXT_INVALID 0x4F /* mark that the CXT saved is no longer relevant - write this mark before
|
||||
executing any ftl writes */
|
||||
|
||||
/*
|
||||
The ECC mark was originally in byte 10, but we have since shrunk to 10 total bytes of meta data.
|
||||
The FMSS guarantees bytes 10 and 11 to be 0xFFFF.
|
||||
To check ECC mark, check for any value besides 0xFF in either byte 8 or 10.
|
||||
*/
|
||||
#define FTL_SPARE_TYPE_LOCATION 9 /* the byte location of the spare type in the spare area */
|
||||
#define FTL_ECC_MARK_BYTE 8 /* the location of the byte in the spare that contains the mark */
|
||||
#define FTL_ECC_MARK_BYTE_LEGACY 10 /* the old location of the byte in the spare that contains the mark */
|
||||
#define FTL_ECC_MARK_WORD 2 /* the location of the word in the spare that contains the marks */
|
||||
#define FTL_ECC_MARK_MASK 0x00FF00FF /* use this mask on the 2nd word to check for ECC mark */
|
||||
#define FTL_TABLE_PTR_INVALID_VALUE 0xFFFFFFFF
|
||||
|
||||
#define LOG_EMPTY_SLOT (0xFFFF)
|
||||
|
||||
#endif /* _FTL_TYPES_H_ */
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#ifndef __L2V_H__
|
||||
#define __L2V_H__
|
||||
|
||||
#include "L2V_Types.h"
|
||||
|
||||
|
||||
extern L2V_t L2V;
|
||||
extern UInt8 *L2V_root_depth;
|
||||
|
||||
|
||||
#endif // __L2V_H__
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#ifndef __L2V_CASSERT_H__
|
||||
#define __L2V_CASSERT_H__
|
||||
|
||||
#define l2v_assert(e) WMR_ASSERT(e)
|
||||
|
||||
#define CASSERT(x, name) typedef char __CASSERT_##name[(x) ? 1 : -1]
|
||||
|
||||
#define l2v_assert_le(x, y) l2v_assert((x) <= (y))
|
||||
#define l2v_assert_lt(x, y) l2v_assert((x) < (y))
|
||||
#define l2v_assert_ge(x, y) l2v_assert((x) >= (y))
|
||||
#define l2v_assert_gt(x, y) l2v_assert((x) > (y))
|
||||
#define l2v_assert_eq(x, y) l2v_assert((x) == (y))
|
||||
#define l2v_assert_ne(x, y) l2v_assert((x) != (y))
|
||||
|
||||
#endif // __L2V_CASSERT_H__
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#ifndef __L2V_CONFIG_H__
|
||||
#define __L2V_CONFIG_H__
|
||||
|
||||
// Defines the minium page size--ONLY used for easier extent (logical range) configuration
|
||||
#define L2V_MINPAGESIZE_BITS (b_4 + KiB_bits)
|
||||
|
||||
// Defines the node size
|
||||
#define L2V_CACHELINE 64
|
||||
#define L2V_NODE_SIZE L2V_CACHELINE
|
||||
|
||||
// Defines the memory set aside for the node pool
|
||||
#define L2V_NODEPOOL_MEM (MiB>>2)
|
||||
|
||||
// Defines the size of a logical tree
|
||||
#define L2V_TREE_BITS 15
|
||||
|
||||
// Repack periodicity
|
||||
#define L2V_REPACK_PERIOD 200
|
||||
|
||||
|
||||
#endif // __L2V_CONFIG_H__
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#ifndef __L2V_DEFINES_H__
|
||||
#define __L2V_DEFINES_H__
|
||||
|
||||
// Shortcuts for the config
|
||||
#define b_1 0
|
||||
#define b_2 1
|
||||
#define b_4 2
|
||||
#define b_8 3
|
||||
#define b_16 4
|
||||
#define b_32 5
|
||||
#define b_64 6
|
||||
#define b_128 7
|
||||
#define b_256 8
|
||||
#define b_512 9
|
||||
#define KiB_bits 10
|
||||
#define MiB_bits 20
|
||||
#define GiB_bits 30
|
||||
#define TiB_bits 40
|
||||
#define KiB (1 << KiB_bits)
|
||||
#define MiB (1 << MiB_bits)
|
||||
#define GiB (1 << GiB_bits)
|
||||
#define TiB (1 << TiB_bits)
|
||||
|
||||
#include "L2V_Config.h"
|
||||
|
||||
|
||||
// Pointers to NAND
|
||||
// VPN bits were originally defined seperately as superblock bits, page offset bits;
|
||||
// combining them results in more flexibility. 10+3 was supposed to represent 8192 max superblocks;
|
||||
// 12 represented 4096 max pages per superblock.
|
||||
#define L2V_BITS_VPN (10+3+12)
|
||||
#define L2V_MAX_SB (1 << L2V_BITS_SB)
|
||||
#define L2V_BITS_NAND_SPAN (32 - 2 - L2V_BITS_VPN)
|
||||
|
||||
|
||||
// Node size
|
||||
#define L2V_CONTIG_ELEM_SMALL 4
|
||||
#define L2V_CONTIG_ELEM_LARGE 6
|
||||
#define L2V_MIN_CONTIG_PER_NODE (L2V_NODE_SIZE / L2V_CONTIG_ELEM_LARGE)
|
||||
#define L2V_MAX_CONTIG_PER_NODE (L2V_NODE_SIZE / L2V_CONTIG_ELEM_SMALL)
|
||||
|
||||
|
||||
// Memory usage
|
||||
#define L2V_NODEPOOL_COUNT (L2V_NODEPOOL_MEM / L2V_NODE_SIZE)
|
||||
#define L2V_BITS_NODEIDX 16
|
||||
#define L2V_BITS_NODE_SPAN (32 - 2 - L2V_BITS_NODEIDX)
|
||||
|
||||
|
||||
// Parameters
|
||||
#define L2V_SUCKUP_CHILDREN_MAX 3
|
||||
#define L2V_TRACK_VALID 0
|
||||
|
||||
|
||||
// Tree size
|
||||
#define L2V_TREE_SIZE (1 << L2V_TREE_BITS)
|
||||
#define L2V_TREE_MASK (L2V_TREE_SIZE - 1)
|
||||
#define L2V_MAX_TREE_DEPTH 32
|
||||
#define L2V_MAX_TREE_DEPTH_UPD 36
|
||||
#define L2V_TREE_DEPTH_REPACK 26
|
||||
|
||||
|
||||
// Magic numbers
|
||||
#define L2V_CONTIG_FREE_SIG 0xFFFFFFFF
|
||||
// These represent token values; normally, when we move along a span, we add to vpn and
|
||||
// subtract from span. If it's a token--such as "missing" or "deallocated"--we should
|
||||
// subtract from span, but not add to vpn, because it would change the meaning.
|
||||
#define L2V_VPN_DEALLOC ((1<<L2V_BITS_VPN)-0xfffe)
|
||||
#define L2V_VPN_MISS ((1<<L2V_BITS_VPN)-0xfffd)
|
||||
#define L2V_VPN_SPECIAL L2V_VPN_DEALLOC
|
||||
|
||||
|
||||
// Transforms
|
||||
#define L2V_IDX_TO_NODE(idx) (&L2V.Pool.Node[idx])
|
||||
#define L2V_NODE_TO_IDX(ptr) ((lNode_t*)(ptr) - &L2V.Pool.Node[0])
|
||||
|
||||
// Memory state
|
||||
#define L2V_LowMem (L2V.Pool.FreeCount <= (L2V_MAX_TREE_DEPTH*4))
|
||||
|
||||
|
||||
#endif // __L2V_DEFINES_H__
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#ifndef __L2V_EXTERN_H__
|
||||
#define __L2V_EXTERN_H__
|
||||
|
||||
|
||||
#include "L2V_Types.h"
|
||||
|
||||
|
||||
// Define the context structure for faster macro access
|
||||
extern L2V_t L2V;
|
||||
extern UInt8 *L2V_root_depth;
|
||||
|
||||
extern BOOL32 L2V_Init(UInt32 numLbas, UInt32 numSBs, UInt32 pagesPerSB);
|
||||
extern void L2V_Free(void);
|
||||
extern void L2V_Search_Init(L2V_SearchCtx_t *c);
|
||||
extern void L2V_Search(L2V_SearchCtx_t *c);
|
||||
extern void L2V_Update(UInt32 lba, UInt32 size, UInt32 vpn);
|
||||
extern void L2V_Repack(UInt32 tree);
|
||||
extern void L2V_ForgetBiggestTree(void);
|
||||
|
||||
#define L2V_LowMem (L2V.Pool.FreeCount <= (L2V_MAX_TREE_DEPTH*4))
|
||||
|
||||
|
||||
#endif // __L2V_EXTERN_H__
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#include "WMRFeatures.h"
|
||||
#if ENABLE_L2V_TREE
|
||||
#include "L2V.h"
|
||||
#include "L2V_Forget.h"
|
||||
#include "L2V_Funcs.h"
|
||||
#include "L2V_Mem.h"
|
||||
#include "L2V_Assert.h"
|
||||
|
||||
static UInt32 ChooseBiggest(void);
|
||||
static void Forget(lNode_t *node);
|
||||
static void ReplaceRoot(UInt32 tree);
|
||||
|
||||
void L2V_ForgetBiggestTree()
|
||||
{
|
||||
UInt32 tree;
|
||||
|
||||
tree = ChooseBiggest();
|
||||
|
||||
// Trying to repack a rootptr? Abort...
|
||||
if (((UInt32)~0 == tree) || (!LPTR_IS_NODEPTR(L2V.Tree[tree]))) {
|
||||
return;
|
||||
}
|
||||
|
||||
Forget(L2V_IDX_TO_NODE(LPTR_GET_NODEIDX(L2V.Tree[tree])));
|
||||
|
||||
ReplaceRoot(tree);
|
||||
}
|
||||
|
||||
static UInt32 ChooseBiggest()
|
||||
{
|
||||
UInt32 i, biggest, biggestSize;
|
||||
|
||||
biggest = ~0;
|
||||
biggestSize = 0;
|
||||
|
||||
for (i = 0; i < L2V.numRoots; i++) {
|
||||
if (L2V.TreeNodes[i] > biggestSize) {
|
||||
biggest = i;
|
||||
biggestSize = L2V.TreeNodes[i];
|
||||
}
|
||||
}
|
||||
|
||||
return biggest;
|
||||
}
|
||||
|
||||
static void Forget(lNode_t *node)
|
||||
{
|
||||
UInt32 nOfs, nodeSize; // Byte offset within the node and size
|
||||
lPtr_t thisPtr;
|
||||
ContigUnpacked_t cu;
|
||||
|
||||
// Iterate through the node,
|
||||
_L2V_NODE_ITERATE(node, nOfs, nodeSize, cu, thisPtr) {
|
||||
if (cu.isNodePtr) {
|
||||
// Recurse
|
||||
Forget(L2V_IDX_TO_NODE(cu.u.nodeIdx));
|
||||
}
|
||||
} _L2V_NODE_ITERATE_END(nOfs);
|
||||
|
||||
// Free the node
|
||||
_L2V_FreeNode(node);
|
||||
}
|
||||
|
||||
static void ReplaceRoot(UInt32 tree)
|
||||
{
|
||||
ContigUnpacked_t cu;
|
||||
|
||||
// Set up contig
|
||||
cu.isNodePtr = 0;
|
||||
cu.hasSpanOF = 0;
|
||||
cu.u.n.vpn = L2V_VPN_MISS;
|
||||
cu.span = 0; // Just so it's consistent... value doesn't matter in root
|
||||
|
||||
// Update tree
|
||||
L2V.Tree[tree] = LPTR_PACK_NAND(cu);
|
||||
L2V.TreeNodes[tree] = 0;
|
||||
L2V_root_depth[tree] = 0;
|
||||
}
|
||||
|
||||
#endif // ENABLE_L2V_TREE
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#ifndef __L2V_FORGET_H__
|
||||
#define __L2V_FORGET_H__
|
||||
|
||||
|
||||
#include "L2V_Types.h"
|
||||
|
||||
|
||||
extern void L2V_ForgetBiggestTree(void);
|
||||
|
||||
|
||||
#endif // __L2V_FORGET_H__
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (c) 2010 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#include "WMRFeatures.h"
|
||||
#include "L2V_Extern.h"
|
||||
|
||||
#if ENABLE_L2V_TREE
|
||||
|
||||
void L2V_Free(void)
|
||||
{
|
||||
if (0 == L2V.numRoots)
|
||||
return;
|
||||
|
||||
// Free arrays:
|
||||
|
||||
if (NULL != L2V.Tree) {
|
||||
WMR_FREE(L2V.Tree, L2V.numRoots * sizeof(lPtr_t));
|
||||
L2V.Tree = NULL;
|
||||
}
|
||||
|
||||
if (NULL != L2V.TreeNodes) {
|
||||
WMR_FREE(L2V.TreeNodes, L2V.numRoots * sizeof(UInt32));
|
||||
L2V.TreeNodes = NULL;
|
||||
}
|
||||
|
||||
if (NULL != L2V.UpdatesSinceRepack) {
|
||||
WMR_FREE(L2V.UpdatesSinceRepack, L2V.numRoots * sizeof(UInt32));
|
||||
L2V.UpdatesSinceRepack = NULL;
|
||||
}
|
||||
|
||||
if (NULL != L2V.Pool.Node) {
|
||||
WMR_FREE(L2V.Pool.Node, L2V_NODEPOOL_MEM);
|
||||
L2V.Pool.Node = NULL;
|
||||
}
|
||||
|
||||
if(L2V_root_depth != NULL)
|
||||
{
|
||||
WMR_FREE(L2V_root_depth, L2V.numRoots);
|
||||
L2V_root_depth = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // ENABLE_L2V_TREE
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#include "WMRFeatures.h"
|
||||
#if ENABLE_L2V_TREE
|
||||
#include "L2V_Funcs.h"
|
||||
|
||||
// Empty
|
||||
|
||||
#endif // ENABLE_L2V_TREE
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#ifndef __L2V_FUNCS_H__
|
||||
#define __L2V_FUNCS_H__
|
||||
|
||||
|
||||
#include "L2V_Types.h"
|
||||
|
||||
|
||||
BOOL32 L2V_Init(UInt32 numLbas, UInt32 numSBs, UInt32 pagesPerSB);
|
||||
extern void L2V_Search_Init(L2V_SearchCtx_t *c);
|
||||
extern void L2V_Search(L2V_SearchCtx_t *c);
|
||||
extern void L2V_Update(UInt32 lba, UInt32 size, UInt32 vpn);
|
||||
extern void L2V_Repack(UInt32 tree);
|
||||
extern void L2V_ForgetBiggestTree(void);
|
||||
|
||||
|
||||
// Macros
|
||||
|
||||
#define _L2V_NODE_ITERATE_RESUME(_node, _nodeByteOfs, _nodeSize, _cu, _destPtr) \
|
||||
while ((_nodeByteOfs) <= ((_nodeSize)-sizeof(lPtr_t))) { \
|
||||
(_destPtr) = *(lPtr_t*)(&(_node)->bytes[_nodeByteOfs]); \
|
||||
if (L2V_CONTIG_FREE_SIG == (_destPtr)) { \
|
||||
break; \
|
||||
} \
|
||||
if (LPTR_IS_NODEPTR(_destPtr)) { \
|
||||
LPTR_UNPACK_NODE(_destPtr, _cu); \
|
||||
} else { \
|
||||
LPTR_UNPACK_NAND(_destPtr, _cu); \
|
||||
} \
|
||||
if ((_cu).hasSpanOF) { \
|
||||
(_nodeSize) -= sizeof(UInt16); \
|
||||
(_cu).span += *(UInt16*)&(_node)->bytes[_nodeSize] << (LPTR_IS_NODEPTR(_destPtr) ? L2V_BITS_NODE_SPAN : L2V_BITS_NAND_SPAN); \
|
||||
l2v_assert_le(_nodeByteOfs, ((_nodeSize)-sizeof(lPtr_t))); \
|
||||
} \
|
||||
l2v_assert_ne((_cu).span, 0);
|
||||
|
||||
#define _L2V_NODE_ITERATE(_node, _nodeByteOfs, _nodeSize, _cu, _destPtr) \
|
||||
(_nodeByteOfs) = 0; \
|
||||
(_nodeSize) = L2V_NODE_SIZE; \
|
||||
_L2V_NODE_ITERATE_RESUME(_node, _nodeByteOfs, _nodeSize, _cu, _destPtr)
|
||||
|
||||
|
||||
#define _L2V_NODE_ITERATE_NEXT(_nodeByteOfs) \
|
||||
(_nodeByteOfs) += sizeof(lPtr_t);
|
||||
|
||||
#define _L2V_NODE_ITERATE_END_NOP }
|
||||
|
||||
#define _L2V_NODE_ITERATE_END(_nodeByteOfs) \
|
||||
(_nodeByteOfs) += sizeof(lPtr_t); \
|
||||
}
|
||||
|
||||
#define _L2V_NODE_PUSH_CONTIG_NODE(_node, _nodeByteOfs, _nodeSize, _cu) \
|
||||
{ \
|
||||
l2v_assert_ne((_cu).span, 0); \
|
||||
(_cu).hasSpanOF = 1; \
|
||||
*(lPtr_t*)(&(_node)->bytes[_nodeByteOfs]) = LPTR_PACK_NODE(_cu); \
|
||||
(_nodeByteOfs) += sizeof(lPtr_t); \
|
||||
(_nodeSize) -= sizeof(UInt16); \
|
||||
*(UInt16*)&(_node)->bytes[_nodeSize] = (_cu).span >> L2V_BITS_NODE_SPAN; \
|
||||
}
|
||||
#define _L2V_NODE_PUSH_CONTIG_NAND(_node, _nodeByteOfs, _nodeSize, _cu) \
|
||||
{ \
|
||||
l2v_assert_ne((_cu).span, 0); \
|
||||
(_cu).hasSpanOF = 0; \
|
||||
if ((_cu).span >= (1 << L2V_BITS_NAND_SPAN)) { \
|
||||
(_cu).hasSpanOF = 1; \
|
||||
(_nodeSize) -= sizeof(UInt16); \
|
||||
*(UInt16*)&(_node)->bytes[_nodeSize] = (_cu).span >> L2V_BITS_NAND_SPAN; \
|
||||
} \
|
||||
*(lPtr_t*)(&(_node)->bytes[_nodeByteOfs]) = LPTR_PACK_NAND(_cu); \
|
||||
(_nodeByteOfs) += sizeof(lPtr_t); \
|
||||
}
|
||||
#define _L2V_NODE_PUSH_CONTIG(_node, _nodeByteOfs, _nodeSize, _cu) \
|
||||
do { \
|
||||
if ((_cu).isNodePtr) { \
|
||||
_L2V_NODE_PUSH_CONTIG_NODE(_node, _nodeByteOfs, _nodeSize, _cu); \
|
||||
} else { \
|
||||
_L2V_NODE_PUSH_CONTIG_NAND(_node, _nodeByteOfs, _nodeSize, _cu); \
|
||||
} \
|
||||
} while (0)
|
||||
#define _L2V_CONTIG_SIZE(_cu) (sizeof(lPtr_t) + (((_cu).isNodePtr || ((_cu).span >= (1 << L2V_BITS_NAND_SPAN))) ? sizeof(UInt16) : 0))
|
||||
|
||||
#define _L2V_NODE_FILL(_node, _nodeByteOfs, _nodeSize) \
|
||||
do { \
|
||||
WMR_MEMSET(&(_node)->bytes[_nodeByteOfs], 0xFF, (_nodeSize) - (_nodeByteOfs)); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define min(a, b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // __L2V_FUNCS_H__
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#include "WMRFeatures.h"
|
||||
#if ENABLE_L2V_TREE
|
||||
#include "L2V_Mem.h"
|
||||
|
||||
|
||||
// Declare our L2V context structure here
|
||||
L2V_t L2V;
|
||||
UInt8 *L2V_root_depth;
|
||||
|
||||
// Functions
|
||||
BOOL32 L2V_Init(UInt32 numLbas, UInt32 numSBs, UInt32 pagesPerSB)
|
||||
{
|
||||
UInt32 i;
|
||||
Int32 j;
|
||||
ContigUnpacked_t cu;
|
||||
|
||||
// Set number of superblocks for valid accounting division
|
||||
L2V.numSBs = numSBs;
|
||||
L2V.pagesPerSB = pagesPerSB;
|
||||
if ((numSBs * pagesPerSB) >= L2V_VPN_SPECIAL) {
|
||||
WMR_PANIC("Tree bitspace not sufficient for geometry %dx%d: please re-adjust", numSBs, pagesPerSB);
|
||||
}
|
||||
|
||||
// Set tree version
|
||||
L2V.treeVersion = 0;
|
||||
|
||||
// Calculate roots
|
||||
L2V.numRoots = (numLbas >> L2V_TREE_BITS) + 1;
|
||||
|
||||
// Allocate arrays
|
||||
L2V.Tree = WMR_MALLOC(L2V.numRoots * sizeof(lPtr_t));
|
||||
l2v_assert_ne(L2V.Tree, NULL);
|
||||
L2V.TreeNodes = WMR_MALLOC(L2V.numRoots * sizeof(UInt32));
|
||||
l2v_assert_ne(L2V.TreeNodes, NULL);
|
||||
L2V.UpdatesSinceRepack = WMR_MALLOC(L2V.numRoots * sizeof(UInt32));
|
||||
l2v_assert_ne(L2V.UpdatesSinceRepack, NULL);
|
||||
L2V_root_depth = WMR_MALLOC(L2V.numRoots);
|
||||
l2v_assert_ne(L2V_root_depth , NULL);
|
||||
for (i = 0; i < L2V.numRoots; i++) {
|
||||
L2V_root_depth[i] = 0;
|
||||
}
|
||||
|
||||
// Empty roots; default to miss
|
||||
cu.hasSpanOF = 0;
|
||||
cu.u.n.vpn = L2V_VPN_MISS;
|
||||
cu.span = 0;
|
||||
for (i = 0; i < L2V.numRoots; i++) {
|
||||
L2V.Tree[i] = LPTR_PACK_NAND(cu);
|
||||
}
|
||||
|
||||
// Reset periodic repacker variables
|
||||
L2V.RepackCounter = 0;
|
||||
|
||||
// Allocate the node pool
|
||||
L2V.Pool.Node = (lNode_t*)WMR_MALLOC(L2V_NODEPOOL_MEM);
|
||||
if (NULL == L2V.Pool.Node) {
|
||||
return FALSE32;
|
||||
}
|
||||
|
||||
// Finally, put all nodes in the free pool
|
||||
L2V.Pool.FreePtr = NULL;
|
||||
L2V.Pool.FreeCount = 0;
|
||||
for (j = L2V_NODEPOOL_COUNT-1; j >= 0; j--) {
|
||||
_L2V_FreeNode(&L2V.Pool.Node[j]);
|
||||
}
|
||||
|
||||
return TRUE32;
|
||||
}
|
||||
|
||||
#endif // ENABLE_L2V_TREE
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#include "WMRFeatures.h"
|
||||
#if ENABLE_L2V_TREE
|
||||
#include "L2V.h"
|
||||
#include "L2V_Mem.h"
|
||||
#include "L2V_Assert.h"
|
||||
|
||||
|
||||
void _L2V_FreeNode(lNode_t *node)
|
||||
{
|
||||
static int freeCount = 0;
|
||||
|
||||
freeCount++;
|
||||
|
||||
l2v_assert_ge(node, &L2V.Pool.Node[0]);
|
||||
l2v_assert_le(node, &L2V.Pool.Node[L2V_NODEPOOL_COUNT]);
|
||||
|
||||
node->nextFreePtr = L2V.Pool.FreePtr;
|
||||
L2V.Pool.FreePtr = node;
|
||||
L2V.Pool.FreeCount++;
|
||||
}
|
||||
|
||||
|
||||
lNode_t *_L2V_AllocNode()
|
||||
{
|
||||
lNode_t *ret;
|
||||
static int allocCount = 0;
|
||||
|
||||
allocCount++;
|
||||
|
||||
ret = (lNode_t*)L2V.Pool.FreePtr;
|
||||
if (NULL != ret) {
|
||||
L2V.Pool.FreePtr = L2V.Pool.FreePtr->nextFreePtr;
|
||||
L2V.Pool.FreeCount--;
|
||||
}
|
||||
l2v_assert_ne(ret, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif // ENABLE_L2V_TREE
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#ifndef __L2V_MEM_H__
|
||||
#define __L2V_MEM_H__
|
||||
|
||||
|
||||
#include "L2V_Types.h"
|
||||
|
||||
|
||||
extern void _L2V_FreeNode(lNode_t *node);
|
||||
extern lNode_t *_L2V_AllocNode(void); // Warning: may return NULL; up to caller to handle gracefully
|
||||
|
||||
|
||||
#endif // __L2V_MEM_H__
|
||||
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#include "WMRFeatures.h"
|
||||
#if ENABLE_L2V_TREE
|
||||
#include "L2V_Print.h"
|
||||
#include "L2V_Funcs.h"
|
||||
#include "L2V.h"
|
||||
#include "L2V_Types.h"
|
||||
|
||||
|
||||
#define PRINT_MAXPATH 0
|
||||
|
||||
|
||||
// Prototypes
|
||||
|
||||
static int L2V_GetUsage(lNode_t *node, UInt32 *used, UInt32 *total, UInt32 *nodes, UInt32 totalSpan, BOOL32 isMax);
|
||||
|
||||
|
||||
// Functions
|
||||
|
||||
void L2V_PrintPtr(lPtr_t lptr)
|
||||
{
|
||||
ContigUnpacked_t cu;
|
||||
LPTR_UNPACK(lptr, cu);
|
||||
L2V_PrintCU(&cu);
|
||||
}
|
||||
|
||||
void L2V_PrintCU(ContigUnpacked_t *cu)
|
||||
{
|
||||
if (cu->isNodePtr)
|
||||
printf("[Node]");
|
||||
else
|
||||
printf("[NAND]");
|
||||
|
||||
if (cu->hasSpanOF)
|
||||
printf("o");
|
||||
else
|
||||
printf("-");
|
||||
|
||||
if (cu->isNodePtr) {
|
||||
printf("[idx:%d][span:%d]", cu->u.nodeIdx, cu->span);
|
||||
} else {
|
||||
printf("[vpn:%d][span:%d]", cu->u.n.vpn, cu->span);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
void L2V_PrintNode(lNode_t *node)
|
||||
{
|
||||
UInt32 nOfs, nodeSize;
|
||||
lPtr_t thisPtr;
|
||||
ContigUnpacked_t cu;
|
||||
|
||||
_L2V_NODE_ITERATE(node, nOfs, nodeSize, cu, thisPtr) {
|
||||
L2V_PrintCU(&cu);
|
||||
} _L2V_NODE_ITERATE_END(nOfs);
|
||||
}
|
||||
|
||||
|
||||
void L2V_PrintUsage(UInt32 tree)
|
||||
{
|
||||
UInt32 used, total, nodes, maxdepth;
|
||||
|
||||
ContigUnpacked_t cu;
|
||||
|
||||
used = total = nodes = maxdepth = 0;
|
||||
printf("Max depth path: ");
|
||||
printf("digraph G {\n");
|
||||
LPTR_UNPACK(L2V.Tree[tree], cu);
|
||||
if (cu.isNodePtr) {
|
||||
maxdepth = L2V_GetUsage(L2V_IDX_TO_NODE(cu.u.nodeIdx), &used, &total, &nodes, L2V_TREE_SIZE, 1);
|
||||
}
|
||||
printf("}\n");
|
||||
printf("\nUsage tree %d: %.2f, nodes: %d, maxdepth: %d\n", tree, (float)used/(float)total, nodes, maxdepth);
|
||||
printf("Nodes calc: %d tally: %d\n\n", nodes, L2V.TreeNodes[tree]);
|
||||
if (nodes != L2V.TreeNodes[tree]) while(1);//DP
|
||||
//l2v_assert_eq(nodes, L2V_NODEPOOL_COUNT - L2V.Pool.FreeCount); // Only valid when using 1 tree
|
||||
}
|
||||
|
||||
static int L2V_GetUsage(lNode_t *node, UInt32 *used, UInt32 *total, UInt32 *nodes, UInt32 totalSpan, BOOL32 isMax)
|
||||
{
|
||||
UInt32 nOfs, nodeSize; // Byte offset within the node
|
||||
UInt32 sumSpan;
|
||||
lPtr_t thisPtr, maxNode;
|
||||
UInt32 depth, maxDepth, maxSpan;
|
||||
ContigUnpacked_t cu;
|
||||
|
||||
// Walk through
|
||||
(*nodes)++;
|
||||
maxDepth = 0;
|
||||
sumSpan = 0;
|
||||
|
||||
// Iterate through the node,
|
||||
L2V_PrintNode(node);
|
||||
_L2V_NODE_ITERATE(node, nOfs, nodeSize, cu, thisPtr) {
|
||||
if (cu.isNodePtr) {
|
||||
printf("%d -> %d;\n", (int)L2V_NODE_TO_IDX(node), cu.u.nodeIdx); // DOT output
|
||||
l2v_assert_ne(cu.u.nodeIdx, 65535);
|
||||
l2v_assert_ne(L2V_IDX_TO_NODE(cu.u.nodeIdx), node);
|
||||
l2v_assert_ne(cu.span, 0);
|
||||
depth = L2V_GetUsage(L2V_IDX_TO_NODE(cu.u.nodeIdx), used, total, nodes, cu.span, 0);
|
||||
if (depth > maxDepth) {
|
||||
maxDepth = depth;
|
||||
maxNode = thisPtr;
|
||||
maxSpan = cu.span;
|
||||
}
|
||||
}
|
||||
sumSpan += cu.span;
|
||||
l2v_assert_le(cu.span, 32768);
|
||||
} _L2V_NODE_ITERATE_END(nOfs);
|
||||
*used += nOfs;
|
||||
*total += sizeof(lNode_t);
|
||||
printf("%d [label=\"us:%.2f\\nsp:%.2f\",shape=box,style=filled,color=\"1.0 %.2f 1.0\"];\n", (int)L2V_NODE_TO_IDX(node), (float)nOfs/sizeof(lNode_t), (float)totalSpan/L2V_TREE_SIZE, (float)nOfs/sizeof(lNode_t)); // DOT output
|
||||
|
||||
if (sumSpan != totalSpan) {
|
||||
printf("Sum: %d, total: %d\n", sumSpan, totalSpan);
|
||||
L2V_PrintNode(node);
|
||||
}
|
||||
l2v_assert_eq(sumSpan, totalSpan);
|
||||
l2v_assert_ne(nOfs, 0);
|
||||
|
||||
#if PRINT_MAXPATH
|
||||
if (maxDepth && isMax) {
|
||||
printf("<-%d", maxNode.node.nodeIdx);
|
||||
L2V_GetUsage(L2V_LPTR_TO_NODE(maxNode), &nOfs, &nOfs, &nOfs, maxSpan, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
return maxDepth+1;
|
||||
}
|
||||
|
||||
#endif // ENABLE_L2V_TREE
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#ifndef __L2V_PRINT_H__
|
||||
#define __L2V_PRINT_H__
|
||||
|
||||
|
||||
#include "L2V_Types.h"
|
||||
|
||||
|
||||
extern void L2V_PrintPtr(lPtr_t lptr);
|
||||
extern void L2V_PrintCU(ContigUnpacked_t *cu);
|
||||
extern void L2V_PrintNode(lNode_t *node);
|
||||
extern void L2V_PrintUsage(UInt32 tree);
|
||||
|
||||
|
||||
#endif // __L2V_PRINT_H__
|
||||
|
||||
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#define AND_TRACE_LAYER FTL
|
||||
|
||||
#include "WMRFeatures.h"
|
||||
#if ENABLE_L2V_TREE
|
||||
#include "L2V_Repack.h"
|
||||
#include "L2V.h"
|
||||
#include "L2V_Types.h"
|
||||
#include "L2V_Mem.h"
|
||||
#include "L2V_Funcs.h"
|
||||
|
||||
|
||||
#define REPACK_MAX_NODES (L2V_TREE_SIZE/L2V_MIN_CONTIG_PER_NODE)
|
||||
#define REPACK_TREE_LOG_SIZE 32
|
||||
|
||||
typedef struct {
|
||||
lNode_t *bottom[REPACK_MAX_NODES];
|
||||
UInt32 bottomSpan[REPACK_MAX_NODES];
|
||||
UInt32 bottomIdx;
|
||||
UInt32 bottom_nOfs;
|
||||
UInt32 bottom_nodeSize;
|
||||
UInt32 repackTreeLog[REPACK_TREE_LOG_SIZE];
|
||||
UInt32 repackTreeLogIdx;
|
||||
} RepackCtx_t;
|
||||
|
||||
|
||||
// Static definitions
|
||||
static void CopyAndDestroy(RepackCtx_t *r, lNode_t *node);
|
||||
static int Rebuild(RepackCtx_t *r);
|
||||
static void ReplaceRoot(RepackCtx_t *r, UInt32 tree);
|
||||
|
||||
|
||||
void L2V_PeriodicRepack()
|
||||
{
|
||||
Int32 best;
|
||||
UInt32 merit, bestMerit, i;
|
||||
|
||||
// Check if it's appropriate or not
|
||||
if (L2V.RepackCounter < L2V_REPACK_PERIOD) {
|
||||
return;
|
||||
}
|
||||
L2V.RepackCounter = 0;
|
||||
|
||||
// Find best candidate; merit==updates
|
||||
bestMerit = 0;
|
||||
best = -1;
|
||||
for (i = 0; i < L2V.numRoots; i++) {
|
||||
merit = L2V.UpdatesSinceRepack[i];
|
||||
if (merit >= bestMerit) {
|
||||
bestMerit = merit;
|
||||
best = i;
|
||||
}
|
||||
}
|
||||
|
||||
l2v_assert_ne(best, -1);
|
||||
|
||||
L2V_Repack(best);
|
||||
}
|
||||
|
||||
|
||||
// WARNING: NOT REENTRANT
|
||||
static RepackCtx_t r;
|
||||
void L2V_Repack(UInt32 tree)
|
||||
{
|
||||
lNode_t *root;
|
||||
ContigUnpacked_t cu;
|
||||
|
||||
LPTR_UNPACK(L2V.Tree[tree], cu);
|
||||
|
||||
// Trying to repack a rootptr? Abort...
|
||||
if (!cu.isNodePtr) {
|
||||
return;
|
||||
}
|
||||
|
||||
WMR_TRACE_1(Repack, START, tree);
|
||||
|
||||
// Up tree version for search-update coherency
|
||||
L2V.treeVersion++;
|
||||
|
||||
// Create list of new bottom layer
|
||||
r.bottomIdx = 0;
|
||||
r.bottom_nOfs = 0;
|
||||
r.bottom_nodeSize = L2V_NODE_SIZE;
|
||||
WMR_MEMSET(r.bottom, 0, REPACK_MAX_NODES * sizeof(r.bottom[0]));
|
||||
WMR_MEMSET(r.bottomSpan, 0, REPACK_MAX_NODES * sizeof(r.bottomSpan[0]));
|
||||
|
||||
// Recurse and destroy
|
||||
root = L2V_IDX_TO_NODE(cu.u.nodeIdx);
|
||||
CopyAndDestroy(&r, root);
|
||||
|
||||
l2v_assert_ne(r.bottom_nOfs, 0);
|
||||
|
||||
// Fill rest with "empty" markers
|
||||
_L2V_NODE_FILL(r.bottom[r.bottomIdx], r.bottom_nOfs, r.bottom_nodeSize);
|
||||
|
||||
// Rebuild hierarchy
|
||||
L2V.TreeNodes[tree] = Rebuild(&r);
|
||||
|
||||
// Replace root
|
||||
ReplaceRoot(&r, tree);
|
||||
|
||||
// Clear repack counter
|
||||
L2V.UpdatesSinceRepack[tree] = 0;
|
||||
|
||||
|
||||
// Log which tree we repacked
|
||||
if (r.repackTreeLogIdx >= REPACK_TREE_LOG_SIZE) {
|
||||
r.repackTreeLogIdx = 0;
|
||||
}
|
||||
r.repackTreeLog[r.repackTreeLogIdx] = tree;
|
||||
r.repackTreeLogIdx++;
|
||||
|
||||
WMR_TRACE_0(Repack, END);
|
||||
}
|
||||
|
||||
|
||||
static void CopyAndDestroy(RepackCtx_t *r, lNode_t *node)
|
||||
{
|
||||
UInt32 nOfs, nodeSize; // Byte offset within the node
|
||||
ContigUnpacked_t cu;
|
||||
lPtr_t thisPtr;
|
||||
|
||||
// Iterate through the node,
|
||||
_L2V_NODE_ITERATE(node, nOfs, nodeSize, cu, thisPtr) {
|
||||
if (cu.isNodePtr) {
|
||||
// Recurse
|
||||
CopyAndDestroy(r, L2V_IDX_TO_NODE(cu.u.nodeIdx));
|
||||
} else {
|
||||
// Would be full? Move along...
|
||||
if ((r->bottom_nOfs + _L2V_CONTIG_SIZE(cu)) > r->bottom_nodeSize) {
|
||||
// Fill rest with "empty" markers
|
||||
_L2V_NODE_FILL(r->bottom[r->bottomIdx], r->bottom_nOfs, r->bottom_nodeSize);
|
||||
|
||||
r->bottomIdx++;
|
||||
l2v_assert_lt(r->bottomIdx, REPACK_MAX_NODES);
|
||||
}
|
||||
|
||||
// Allocate node if necessary
|
||||
if (NULL == r->bottom[r->bottomIdx]) {
|
||||
// Allocate...
|
||||
r->bottom[r->bottomIdx] = _L2V_AllocNode();
|
||||
r->bottom_nOfs = 0;
|
||||
r->bottom_nodeSize = L2V_NODE_SIZE;
|
||||
}
|
||||
|
||||
// Copy out
|
||||
_L2V_NODE_PUSH_CONTIG(r->bottom[r->bottomIdx], r->bottom_nOfs, r->bottom_nodeSize, cu);
|
||||
r->bottomSpan[r->bottomIdx] += cu.span;
|
||||
l2v_assert_le(cu.span, L2V_TREE_SIZE);
|
||||
}
|
||||
} _L2V_NODE_ITERATE_END(nOfs);
|
||||
|
||||
// Free the node
|
||||
_L2V_FreeNode(node);
|
||||
}
|
||||
|
||||
|
||||
static int Rebuild(RepackCtx_t *r)
|
||||
{
|
||||
lNode_t *thisBranch;
|
||||
UInt32 nOfs, nodeSize, thisSpan, i, branchIdx;
|
||||
ContigUnpacked_t cu;
|
||||
int nodeCount;
|
||||
|
||||
nodeCount = r->bottomIdx+1;
|
||||
while (r->bottomIdx > 0) {
|
||||
thisBranch = _L2V_AllocNode();
|
||||
nodeCount++;
|
||||
nOfs = 0;
|
||||
nodeSize = L2V_NODE_SIZE;
|
||||
thisSpan = 0;
|
||||
branchIdx = 0;
|
||||
|
||||
// Rebuild this layer
|
||||
for (i = 0; i <= r->bottomIdx; i++) {
|
||||
cu.isNodePtr = 1;
|
||||
cu.u.nodeIdx = L2V_NODE_TO_IDX(r->bottom[i]);
|
||||
cu.span = r->bottomSpan[i];
|
||||
|
||||
if ((nOfs + _L2V_CONTIG_SIZE(cu)) > nodeSize) {
|
||||
// Fill rest with "empty" markers
|
||||
_L2V_NODE_FILL(thisBranch, nOfs, nodeSize);
|
||||
|
||||
// Place it down and get a new one
|
||||
r->bottom[branchIdx] = thisBranch;
|
||||
r->bottomSpan[branchIdx] = thisSpan;
|
||||
branchIdx++;
|
||||
thisBranch = _L2V_AllocNode();
|
||||
nodeCount++;
|
||||
nOfs = 0;
|
||||
nodeSize = L2V_NODE_SIZE;
|
||||
thisSpan = 0;
|
||||
}
|
||||
|
||||
_L2V_NODE_PUSH_CONTIG(thisBranch, nOfs, nodeSize, cu);
|
||||
thisSpan += cu.span;
|
||||
}
|
||||
|
||||
l2v_assert_ne(nOfs, 0);
|
||||
|
||||
r->bottom[branchIdx] = thisBranch;
|
||||
r->bottomSpan[branchIdx] = thisSpan;
|
||||
// Fill rest with "empty" markers
|
||||
_L2V_NODE_FILL(thisBranch, nOfs, nodeSize);
|
||||
|
||||
// Make sure the repack didn't munge the root node's spans
|
||||
if (0 == branchIdx) {
|
||||
l2v_assert_eq(thisSpan, L2V_TREE_SIZE);
|
||||
}
|
||||
|
||||
// Get ready for the next round
|
||||
r->bottomIdx = branchIdx;
|
||||
}
|
||||
|
||||
return nodeCount;
|
||||
}
|
||||
|
||||
|
||||
static void ReplaceRoot(RepackCtx_t *r, UInt32 tree)
|
||||
{
|
||||
ContigUnpacked_t cu;
|
||||
l2v_assert_eq(r->bottomIdx, 0);
|
||||
cu.u.nodeIdx = L2V_NODE_TO_IDX(r->bottom[0]);
|
||||
cu.hasSpanOF = 0;
|
||||
cu.span = 0;
|
||||
L2V.Tree[tree] = LPTR_PACK_NODE(cu);
|
||||
if (!LPTR_IS_NODEPTR(L2V.Tree[tree])) {
|
||||
L2V_root_depth[tree] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ENABLE_L2V_TREE
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#ifndef __L2V_REPACK_H__
|
||||
#define __L2V_REPACK_H__
|
||||
|
||||
|
||||
#include "WMROAM.h"
|
||||
|
||||
// Functions
|
||||
|
||||
extern void L2V_PeriodicRepack(void);
|
||||
extern void L2V_Repack(UInt32 tree);
|
||||
|
||||
|
||||
#endif // __L2V_REPACK_H__
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#include "WMRFeatures.h"
|
||||
#if ENABLE_L2V_TREE
|
||||
#include "L2V.h"
|
||||
#include "L2V_Funcs.h"
|
||||
|
||||
|
||||
void L2V_Search_Init(L2V_SearchCtx_t *c)
|
||||
{
|
||||
c->next_lba = 0xffffffff;
|
||||
c->last_node = NULL;
|
||||
c->span = 0;
|
||||
}
|
||||
|
||||
|
||||
static BOOL32 HitCache(L2V_SearchCtx_t *c)
|
||||
{
|
||||
ContigUnpacked_t cu;
|
||||
lPtr_t thisPtr;
|
||||
|
||||
|
||||
if ((c->treeVersion == L2V.treeVersion) && (c->lba == c->next_lba) && (NULL != c->last_node)) {
|
||||
// Sequential HIT
|
||||
_L2V_NODE_ITERATE_RESUME(c->last_node, c->next_nOfs, c->nodeSize, cu, thisPtr) {
|
||||
if (cu.isNodePtr)
|
||||
break;
|
||||
|
||||
c->vpn = cu.u.n.vpn;
|
||||
c->fromStart = 0;
|
||||
c->span = cu.span;
|
||||
|
||||
_L2V_NODE_ITERATE_NEXT(c->next_nOfs); // This will move nOfs along
|
||||
c->next_lba = c->lba + c->span;
|
||||
return TRUE32;
|
||||
|
||||
} _L2V_NODE_ITERATE_END_NOP;
|
||||
}
|
||||
|
||||
// Clear search history
|
||||
c->next_lba = 0xffffffff;
|
||||
c->last_node = NULL;
|
||||
|
||||
return FALSE32;
|
||||
}
|
||||
|
||||
|
||||
void L2V_Search(L2V_SearchCtx_t *c)
|
||||
{
|
||||
UInt32 targTree, targTofs;
|
||||
UInt32 thisStart, thisMax;
|
||||
UInt32 nOfs, nodeSize; // Byte offset within the node, and node effective size
|
||||
ContigUnpacked_t cu, thiscu;
|
||||
lNode_t *node = NULL;
|
||||
lPtr_t thisPtr;
|
||||
|
||||
if (HitCache(c)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine first root
|
||||
targTree = c->lba >> L2V_TREE_BITS;
|
||||
targTofs = c->lba & L2V_TREE_MASK;
|
||||
l2v_assert_lt(targTree, L2V.numRoots);
|
||||
|
||||
c->level = 0;
|
||||
thisStart = 0;
|
||||
c->vpn = L2V_VPN_MISS;
|
||||
LPTR_UNPACK(L2V.Tree[targTree], cu);
|
||||
thiscu.span = L2V_TREE_SIZE;
|
||||
c->next_nOfs = 0;
|
||||
|
||||
// Search from top down
|
||||
while (c->level < L2V_MAX_TREE_DEPTH) {
|
||||
// Down and next
|
||||
// Decode node pointer
|
||||
if (!cu.isNodePtr) {
|
||||
// Terminal case--pointer to physical location; calculate relative offset...
|
||||
c->vpn = cu.u.n.vpn;
|
||||
c->fromStart = targTofs - thisStart;
|
||||
if (cu.u.n.vpn < L2V_VPN_SPECIAL) {
|
||||
c->vpn += c->fromStart;
|
||||
}
|
||||
c->span = thiscu.span - c->fromStart;
|
||||
// Set up return case for sequential searching
|
||||
c->last_node = node;
|
||||
c->next_lba = c->lba + c->span;
|
||||
c->treeVersion = L2V.treeVersion;
|
||||
// c->next_nOfs is populated from code below, i.e. the previous iteration of this while loop
|
||||
|
||||
// Is it getting really big? Do some preventative maintenence...
|
||||
if (c->level >= L2V_TREE_DEPTH_REPACK) {
|
||||
L2V_Repack(targTree);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Walk through
|
||||
node = L2V_IDX_TO_NODE(cu.u.nodeIdx);
|
||||
|
||||
// Iterate through the node,
|
||||
_L2V_NODE_ITERATE(node, nOfs, nodeSize, thiscu, thisPtr) {
|
||||
// Calculate endpoint
|
||||
thisMax = thisStart + thiscu.span;
|
||||
|
||||
// Are we in range?
|
||||
if (targTofs < thisMax) {
|
||||
// HIT! (Left-hand side implied by order of search.)
|
||||
cu = thiscu;
|
||||
_L2V_NODE_ITERATE_NEXT(nOfs);
|
||||
c->next_nOfs = nOfs;
|
||||
c->nodeSize = nodeSize;
|
||||
goto decodePtr;
|
||||
}
|
||||
|
||||
// Move along in the node
|
||||
thisStart = thisMax;
|
||||
} _L2V_NODE_ITERATE_END(nOfs);
|
||||
|
||||
WMR_PANIC("NAND index: bad tree: targTofs %d, level %d\n", targTofs, c->level);
|
||||
|
||||
decodePtr:
|
||||
// Resume here so we can check the while() condition
|
||||
c->level++;
|
||||
}
|
||||
|
||||
l2v_assert(0); // Should never get here; otherwise, the tree is too deep (or recursive or pointing to randomness)
|
||||
}
|
||||
|
||||
#endif // ENABLE_L2V_TREE
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#include "L2V.h"
|
||||
#include "L2V_Funcs.h"
|
||||
#include "L2V_Print.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
L2V_t L2V;
|
||||
|
||||
|
||||
#define LAST_TREE_TEST 16
|
||||
#define SIMPLE_SIZE (L2V_TREE_SIZE*LAST_TREE_TEST)
|
||||
|
||||
|
||||
// Prototypes
|
||||
static void RandomTest(void);
|
||||
static void SequentialTest(void);
|
||||
static void Simple_Init(void);
|
||||
static void Simple_Update(UInt32 lba, UInt32 size, UInt32 vpn);
|
||||
static void Simple_Lookup(UInt32 lba, UInt32 *vpn);
|
||||
|
||||
void Usage(int argc, char** argv)
|
||||
{
|
||||
printf("Usage: %s s OR %s r (for sequential and random, respectively\n", argv[0], argv[0]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int test = 0;
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
L2V_Init(SIMPLE_SIZE, (L2V_VPN_SPECIAL-1) / 8192, 8192);
|
||||
|
||||
if (argc == 2) {
|
||||
if ('r' == argv[1][0]) {
|
||||
test = 0;
|
||||
} else if ('s' == argv[1][0]) {
|
||||
test = 1;
|
||||
} else {
|
||||
Usage(argc, argv);
|
||||
}
|
||||
}
|
||||
if (argc > 2) {
|
||||
Usage(argc, argv);
|
||||
}
|
||||
|
||||
if (0 == test) {
|
||||
RandomTest();
|
||||
} else {
|
||||
SequentialTest();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define MAXLEN 512
|
||||
static void RandomTest() {
|
||||
UInt32 lba, size, vpn;
|
||||
UInt32 i, svpn;
|
||||
L2V_SearchCtx_t c;
|
||||
|
||||
L2V_Search_Init(&c);
|
||||
|
||||
Simple_Init();
|
||||
|
||||
sranddev();
|
||||
|
||||
while (1) {
|
||||
lba = rand() % ((L2V_TREE_SIZE*LAST_TREE_TEST)-MAXLEN);
|
||||
size = (rand() % (MAXLEN-1))+1;
|
||||
vpn = rand() % ((1<<(L2V_BITS_VPN-1))-size-1);
|
||||
|
||||
printf("[UPD: lba:%d, size:%d, vpn:%d]\n", lba, size, vpn);
|
||||
L2V_Update(lba, size, vpn);
|
||||
Simple_Update(lba, size, vpn);
|
||||
//printf("\n");
|
||||
//L2V_PrintNode(L2V_LPTR_TO_NODE(L2V.Tree[0]));
|
||||
L2V_PrintUsage(0);
|
||||
|
||||
|
||||
// Validate entire range
|
||||
int maxlevel=0;
|
||||
for (i = 0; i < SIMPLE_SIZE; i++) {
|
||||
Simple_Lookup(i, &svpn);
|
||||
c.lba = i;
|
||||
L2V_Search(&c);
|
||||
if (c.level > maxlevel) maxlevel = c.level;
|
||||
if (svpn != c.vpn) {
|
||||
printf("\n\n\n");
|
||||
printf("====================\n");
|
||||
printf("MISMATCH lba:%d\n", i);
|
||||
printf("--------------------\n");
|
||||
printf("Simple vpn:%d\n", svpn);
|
||||
printf("Lookup vpn:%d\n", c.vpn);
|
||||
}
|
||||
l2v_assert_eq(svpn, c.vpn);
|
||||
}
|
||||
printf("maxlevel: %d\n", maxlevel);
|
||||
l2v_assert_lt(maxlevel, L2V_MAX_TREE_DEPTH);
|
||||
|
||||
#if 0
|
||||
if (repack++ > 10) {
|
||||
printf("Repacking tree %d...\n", nextRepack);
|
||||
L2V_Repack(nextRepack);
|
||||
L2V_PrintUsage(nextRepack);
|
||||
repack = 0;
|
||||
nextRepack = (nextRepack + 1) % LAST_TREE_TEST;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void SequentialTest() {
|
||||
UInt32 lba, size, vpn;
|
||||
UInt32 i, svpn;
|
||||
L2V_SearchCtx_t c;
|
||||
|
||||
L2V_Search_Init(&c);
|
||||
|
||||
Simple_Init();
|
||||
|
||||
sranddev();
|
||||
|
||||
lba = 0;
|
||||
size = 0;
|
||||
vpn = 1;
|
||||
|
||||
while (1) {
|
||||
lba += size;
|
||||
size = (rand() % (MAXLEN-1))+1;
|
||||
if ((lba + size) >= L2V_TREE_SIZE) {
|
||||
lba = 0;
|
||||
}
|
||||
if ((rand() & 3) == 0) {
|
||||
vpn = rand() % ((1<<(L2V_BITS_VPN-1))-size-1);
|
||||
}
|
||||
while (((vpn + size) & ((1<<(L2V_BITS_VPN-1))-1)) < vpn) {
|
||||
vpn = rand() % ((1<<(L2V_BITS_VPN-1))-size-1);
|
||||
}
|
||||
|
||||
printf("[UPD: lba:%d, size:%d, vpn:%d]\n", lba, size, vpn);
|
||||
L2V_Update(lba, size, vpn);
|
||||
Simple_Update(lba, size, vpn);
|
||||
L2V_PrintUsage(0);
|
||||
vpn += size;
|
||||
|
||||
|
||||
// Validate entire range
|
||||
int maxlevel=0;
|
||||
for (i = 0; i < SIMPLE_SIZE; i++) {
|
||||
Simple_Lookup(i, &svpn);
|
||||
c.lba = i;
|
||||
L2V_Search(&c);
|
||||
if (c.level > maxlevel) maxlevel = c.level;
|
||||
if (svpn != c.vpn) {
|
||||
printf("\n\n\n");
|
||||
printf("====================\n");
|
||||
printf("MISMATCH lba:%d\n", i);
|
||||
printf("--------------------\n");
|
||||
printf("Simple vpn:%d\n", svpn);
|
||||
printf("Lookup vpn:%d\n", c.vpn);
|
||||
}
|
||||
l2v_assert_eq(svpn, c.vpn);
|
||||
}
|
||||
printf("maxlevel: %d\n", maxlevel);
|
||||
l2v_assert_lt(maxlevel, L2V_MAX_TREE_DEPTH);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UInt32 Simple_vpn[SIMPLE_SIZE];
|
||||
|
||||
static void Simple_Init()
|
||||
{
|
||||
UInt32 i;
|
||||
|
||||
for (i = 0; i < SIMPLE_SIZE; i++) {
|
||||
Simple_vpn[i] = L2V_VPN_MISS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void Simple_Update(UInt32 lba, UInt32 size, UInt32 vpn)
|
||||
{
|
||||
while (size) {
|
||||
Simple_vpn[lba] = vpn;
|
||||
|
||||
// Iterate
|
||||
lba++;
|
||||
if (vpn < L2V_VPN_SPECIAL) {
|
||||
vpn++;
|
||||
}
|
||||
size--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void Simple_Lookup(UInt32 lba, UInt32 *vpn)
|
||||
{
|
||||
*vpn = Simple_vpn[lba];
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
OBJS=L2V_Test.o L2V_Funcs.o L2V_Init.o L2V_Mem.o L2V_Search.o L2V_Update.o L2V_Valid.o L2V_Types.o L2V_Print.o L2V_Repack.o L2V_Forget.o L2V_Free.o WMROAM.o
|
||||
LINK_TARGET=L2V_Test
|
||||
REBUILDABLES=$(OBJS) $(LINK_TARGET)
|
||||
|
||||
.PHONY: all
|
||||
all: copythem $(LINK_TARGET) cleanthem
|
||||
#
|
||||
|
||||
.PHONY: copythem
|
||||
copythem:
|
||||
cp WMROAM-test.h WMROAM.h
|
||||
cp WMROAM-test.c WMROAM.c
|
||||
cp WMRFeatures-test.h WMRFeatures.h
|
||||
|
||||
.PHONY: cleanthem
|
||||
cleanthem:
|
||||
rm WMROAM.c WMROAM.h WMRFeatures.h
|
||||
|
||||
$(LINK_TARGET): $(OBJS)
|
||||
gcc -g -o $@ $^ -Wall
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f $(REBUILDABLES)
|
||||
rm WMROAM.c WMROAM.h WMRFeatures.h
|
||||
|
||||
%.o: %.c
|
||||
gcc -g -o $@ -c $< -Wall -I.
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#include "WMRFeatures.h"
|
||||
#if ENABLE_L2V_TREE
|
||||
#include "L2V_Defines.h"
|
||||
#include "L2V_Types.h"
|
||||
|
||||
|
||||
BOOL32 _L2V_NodeBig_PushContig(lNodeBig_t *big, ContigUnpacked_t *cu)
|
||||
{
|
||||
Int32 last = ((Int32)big->max)-1;
|
||||
l2v_assert_ne(cu->span, 0);
|
||||
|
||||
if (!cu->isNodePtr && (last >= 0) && !big->cu[last].isNodePtr && (
|
||||
((cu->u.n.vpn < L2V_VPN_SPECIAL) && ((big->cu[last].u.n.vpn+big->cu[last].span) == cu->u.n.vpn))
|
||||
|| ((cu->u.n.vpn >= L2V_VPN_SPECIAL) && (big->cu[last].u.n.vpn == cu->u.n.vpn))))
|
||||
{
|
||||
big->cu[last].span += cu->span;
|
||||
return TRUE32;
|
||||
}
|
||||
|
||||
big->cu[big->max] = *cu;
|
||||
big->max++;
|
||||
|
||||
if (cu->isNodePtr) {
|
||||
l2v_assert_lt(cu->u.nodeIdx, L2V_NODEPOOL_COUNT);
|
||||
}
|
||||
|
||||
return FALSE32;
|
||||
}
|
||||
|
||||
|
||||
BOOL32 _L2V_NodeBig_PushContig_Node(lNodeBig_t *big, UInt32 nodeIdx, UInt32 span)
|
||||
{
|
||||
big->cu[big->max].isNodePtr = 1;
|
||||
big->cu[big->max].u.nodeIdx = nodeIdx;
|
||||
big->cu[big->max].span = span;
|
||||
big->max++;
|
||||
|
||||
return FALSE32;
|
||||
}
|
||||
|
||||
|
||||
BOOL32 _L2V_NodeBig_PushContig_Nand(lNodeBig_t *big, UInt32 vpn, UInt32 span)
|
||||
{
|
||||
Int32 last = ((Int32)big->max)-1;
|
||||
l2v_assert_ne(span, 0);
|
||||
|
||||
if ((last >= 0) && !big->cu[last].isNodePtr && (
|
||||
((vpn < L2V_VPN_SPECIAL) && ((big->cu[last].u.n.vpn+big->cu[last].span) == vpn))
|
||||
|| ((vpn >= L2V_VPN_SPECIAL) && (big->cu[last].u.n.vpn == vpn))))
|
||||
{
|
||||
big->cu[last].span += span;
|
||||
return TRUE32;
|
||||
}
|
||||
|
||||
big->cu[big->max].isNodePtr = 0;
|
||||
big->cu[big->max].u.n.vpn = vpn;
|
||||
big->cu[big->max].span = span;
|
||||
big->max++;
|
||||
|
||||
return FALSE32;
|
||||
}
|
||||
|
||||
#endif // ENABLE_L2V_TREE
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#ifndef __L2V_TYPES_H__
|
||||
#define __L2V_TYPES_H__
|
||||
|
||||
|
||||
#include "WMROAM.h"
|
||||
#include "L2V_Defines.h"
|
||||
#include "L2V_Assert.h"
|
||||
|
||||
|
||||
// Pointer type: can point to NAND, or to a subtree
|
||||
// Bits: 0=isNodePtr, 1=hasSpanOF.
|
||||
// isNodePtr=0: vpn:L2V_BITS_VPN, span:L2V_BITS_NAND_SPAN
|
||||
// isNodePtr=1: nodeIdx:L2V_BITS_NODEIDX, span:L2V_BITS_NODE_SPAN
|
||||
// hasSpanOF: fetch 2 bytes from the right end of the node
|
||||
|
||||
typedef UInt32 lPtr_t;
|
||||
#define LPTR_IS_NODEPTR(_lptr) ((_lptr) & 1)
|
||||
#define LPTR_HASSPANOF(_lptr) (((_lptr) & 2) >> 1)
|
||||
#define LPTR_PACK_NAND(_cu) ( \
|
||||
(((_cu).hasSpanOF & 1) << 1) | \
|
||||
(((_cu).u.n.vpn & (((1 <<L2V_BITS_VPN)-1))) << 2) | \
|
||||
(((_cu).span & ((1<<L2V_BITS_NAND_SPAN)-1)) << (2+L2V_BITS_VPN)) \
|
||||
)
|
||||
#define LPTR_PACK_NODE(_cu) ( \
|
||||
1 | \
|
||||
(((_cu).hasSpanOF & 1) << 1) | \
|
||||
(((_cu).u.nodeIdx & ((1 << L2V_BITS_NODEIDX)-1)) << 2) | \
|
||||
(((_cu).span & (((1 <<L2V_BITS_NODE_SPAN)-1))) << (2+L2V_BITS_NODEIDX)) \
|
||||
)
|
||||
#define LPTR_UNPACK_NAND(_lptr, _cu) do { \
|
||||
(_cu).isNodePtr = 0; \
|
||||
(_cu).hasSpanOF = ((_lptr) >> 1) & 1; \
|
||||
(_cu).u.n.vpn = ((_lptr) >> 2) & ((1 << L2V_BITS_VPN)-1); \
|
||||
(_cu).span = ((_lptr) >> (2+L2V_BITS_VPN)) & ((1 << L2V_BITS_NAND_SPAN)-1); \
|
||||
} while (0)
|
||||
#define LPTR_UNPACK_NODE(_lptr, _cu) do { \
|
||||
(_cu).isNodePtr = 1; \
|
||||
(_cu).hasSpanOF = ((_lptr) >> 1) & 1; \
|
||||
(_cu).u.nodeIdx = ((_lptr) >> 2) & ((1 << L2V_BITS_NODEIDX)-1); \
|
||||
(_cu).span = ((_lptr) >> (2+L2V_BITS_NODEIDX)) & ((1 << L2V_BITS_NODE_SPAN)-1); \
|
||||
} while (0)
|
||||
#define LPTR_GET_NODEIDX(_lptr) (((_lptr) >> 2) & ((1 << L2V_BITS_NODEIDX)-1))
|
||||
#define LPTR_UNPACK(_lptr, _cu) do { \
|
||||
if LPTR_IS_NODEPTR(_lptr) { \
|
||||
LPTR_UNPACK_NODE(_lptr, _cu); \
|
||||
} else { \
|
||||
LPTR_UNPACK_NAND(_lptr, _cu); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
typedef struct {
|
||||
UInt32 isNodePtr; // Values: 0, 1 (true)... must not be any other value
|
||||
UInt32 hasSpanOF; // Values: 0, 1 (true)... ditto
|
||||
union {
|
||||
struct {
|
||||
UInt32 vpn;
|
||||
} n;
|
||||
UInt32 nodeIdx;
|
||||
} u;
|
||||
UInt32 span;
|
||||
} ContigUnpacked_t;
|
||||
|
||||
|
||||
// Node type: union for dynamic and fixed node types (and FreePool linkage)
|
||||
typedef union _lNode_t {
|
||||
union _lNode_t *nextFreePtr;
|
||||
|
||||
UInt8 bytes[L2V_NODE_SIZE];
|
||||
} lNode_t;
|
||||
CASSERT(L2V_NODE_SIZE == sizeof(lNode_t), lNode_t_size_matches);
|
||||
|
||||
#define L2V_LNODEBIG_MAX (L2V_MAX_CONTIG_PER_NODE+(L2V_SUCKUP_CHILDREN_MAX*2)+5)
|
||||
typedef struct {
|
||||
ContigUnpacked_t cu[L2V_LNODEBIG_MAX];
|
||||
UInt32 start;
|
||||
UInt32 max;
|
||||
} lNodeBig_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
lNode_t *Node; // Node pool allocated with malloc()
|
||||
lNode_t *FreePtr;
|
||||
UInt32 FreeCount;
|
||||
} FTLight_NodePool_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
// Logical space
|
||||
UInt32 numRoots;
|
||||
lPtr_t *Tree;
|
||||
UInt32 *TreeNodes;
|
||||
UInt32 *UpdatesSinceRepack;
|
||||
UInt32 RepackCounter;
|
||||
UInt32 treeVersion;
|
||||
|
||||
// Physical space
|
||||
UInt32 numSBs;
|
||||
UInt32 pagesPerSB;
|
||||
#if L2V_TRACK_VALID!=0
|
||||
UInt32 Valid[L2V_MAX_SB];
|
||||
#endif
|
||||
|
||||
// Memory
|
||||
FTLight_NodePool_t Pool;
|
||||
} L2V_t;
|
||||
|
||||
typedef struct {
|
||||
// Input:
|
||||
UInt32 lba;
|
||||
|
||||
// Output:
|
||||
UInt32 fromStart; // blocks from start of treeSpan
|
||||
UInt32 vpn;
|
||||
UInt32 span;
|
||||
|
||||
// Internal state:
|
||||
lNode_t *last_node;
|
||||
UInt32 next_lba;
|
||||
UInt32 next_nOfs;
|
||||
UInt32 nodeSize;
|
||||
UInt32 level;
|
||||
UInt32 treeVersion;
|
||||
} L2V_SearchCtx_t;
|
||||
|
||||
|
||||
// Helper functions
|
||||
|
||||
extern BOOL32 _L2V_NodeBig_PushContig(lNodeBig_t *big, ContigUnpacked_t *cu); // True: compressed with left
|
||||
extern BOOL32 _L2V_NodeBig_PushContig_Node(lNodeBig_t *big, UInt32 nodeIdx, UInt32 span); // True: compress with left (always false)
|
||||
extern BOOL32 _L2V_NodeBig_PushContig_Nand(lNodeBig_t *big, UInt32 vpn, UInt32 span); // True: compressed with left
|
||||
#define _L2V_NodeBig_WillCompress(_big, _vpn, _span) \
|
||||
((_big.max > 0) && (!_big.cu[_big.max-1].isNodePtr) && \
|
||||
(((_vpn < L2V_VPN_SPECIAL) && ((_big.cu[_big.max-1].u.n.vpn+_big.cu[_big.max-1].span) == _vpn)) \
|
||||
|| ((_vpn >= L2V_VPN_SPECIAL) && (_big.cu[_big.max-1].u.n.vpn == _vpn))))
|
||||
|
||||
|
||||
#endif // __L2V_TYPES_H__
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#include "WMRFeatures.h"
|
||||
#if ENABLE_L2V_TREE
|
||||
#include "L2V.h"
|
||||
|
||||
|
||||
#if L2V_TRACK_VALID!=0
|
||||
|
||||
void _L2V_ValidUp(UInt32 vpn, UInt32 count)
|
||||
{
|
||||
UInt32 sb = vpn / L2V.pagesPerSB;
|
||||
L2V.Valid[sb] += count;
|
||||
//l2v_assert_le(L2V.Valid[sb], sbsize);
|
||||
}
|
||||
|
||||
void _L2V_ValidDown(UInt32 vpn, UInt32 count)
|
||||
{
|
||||
UInt32 sb = vpn / L2V.pagesPerSB;
|
||||
//l2v_assert_ge(L2V.Valid[sb], count);
|
||||
L2V.Valid[sb] -= count;
|
||||
}
|
||||
|
||||
#endif // track valid
|
||||
|
||||
#endif // ENABLE_L2V_TREE
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#ifndef __L2V_VALID_H__
|
||||
#define __L2V_VALID_H__
|
||||
|
||||
|
||||
#include "L2V_Defines.h"
|
||||
|
||||
#if L2V_TRACK_VALID!=0
|
||||
extern void _L2V_ValidUp(UInt32 vpn, UInt32 count);
|
||||
extern void _L2V_ValidDown(UInt32 vpn, UInt32 count);
|
||||
#else
|
||||
#define _L2V_ValidUp(vpn, count)
|
||||
#define _L2V_ValidDown(vpn, count)
|
||||
#endif
|
||||
|
||||
|
||||
#endif // __L2V_VALID_H__
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
#define ENABLE_L2V_TREE (1)
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2010 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
// Author: Daniel J. Post (djp), dpost@apple.com
|
||||
|
||||
#include "WMROAM.h"
|
||||
|
||||
|
||||
void *WMR_MALLOC(UInt32 size)
|
||||
{
|
||||
void * ptr = malloc(size);
|
||||
if (ptr)
|
||||
{
|
||||
WMR_MEMSET(ptr, 0, size);
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#ifndef __WMROAM_H__
|
||||
#define __WMROAM_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#define UInt32 uint32_t
|
||||
#define Int32 int32_t
|
||||
#define UInt16 uint16_t
|
||||
#define Int16 int16_t
|
||||
#define UInt8 uint8_t
|
||||
#define Int8 int8_t
|
||||
#define BOOL32 bool
|
||||
#define TRUE32 true
|
||||
#define FALSE32 false
|
||||
|
||||
#define _WMR_ASSERT(e, file, line) { printf("%s:%u: failed assertion '%s'\nWaiting for debugger...\n", file, line, e); abort(); }
|
||||
#define WMR_ASSERT(e) if (!(e)) _WMR_ASSERT(#e, __FILE__, __LINE__)
|
||||
#define WMR_PANIC(format, args...) { printf(format , ##args); abort(); }
|
||||
#define WMR_MEMSET(a, b, c) memset(a, b, c)
|
||||
#define WMR_FREE(x, y) free(x)
|
||||
|
||||
extern void *WMR_MALLOC(UInt32 size);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// WMR_TRACE_*
|
||||
//
|
||||
// Compile-time tracepoints (not supported)
|
||||
//
|
||||
#define WMR_TRACE_0(...)
|
||||
#define WMR_TRACE_1(...)
|
||||
#define WMR_TRACE_2(...)
|
||||
#define WMR_TRACE_3(...)
|
||||
#define WMR_TRACE_4(...)
|
||||
#define WMR_TRACE_IST_0(...)
|
||||
#define WMR_TRACE_IST_1(...)
|
||||
#define WMR_TRACE_IST_2(...)
|
||||
#define WMR_TRACE_IST_3(...)
|
||||
#define WMR_TRACE_IST_4(...)
|
||||
|
||||
#endif // __WMROAM_H__
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,335 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#ifndef _YAFTLTYPES_H_
|
||||
#define _YAFTLTYPES_H_
|
||||
|
||||
#include "yaFTL_whoami.h"
|
||||
#include "VFLBuffer.h"
|
||||
#include "yaFTL_Defines.h"
|
||||
#include "L2V/L2V_Extern.h"
|
||||
#include "WMRBuf.h"
|
||||
#include "yaFTL_meta.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// Info generated by CalcGlobal
|
||||
UInt16 wPagesPerVb; /* the count of pages per virtual block */
|
||||
UInt16 wUserVbTotal; /* the total number of data virtual block */
|
||||
UInt32 dwUserPagesTotal; /* the total number of data sector */
|
||||
UInt16 wBytesPerPage; /* bytes per page (main) */
|
||||
UInt16 wNumOfBanks; /* the number of banks */
|
||||
UInt16 wBytesPerPageMeta; /* bytes per page (meta) */
|
||||
} FTLWMRDeviceInfo;
|
||||
|
||||
#define PAGES_PER_SUBLK (yaFTL_FTLDeviceInfo.wPagesPerVb)
|
||||
#define NUM_BANKS (yaFTL_FTLDeviceInfo.wNumOfBanks)
|
||||
#define FTL_AREA_SIZE (yaFTL_FTLDeviceInfo.wUserVbTotal)
|
||||
#define USER_PAGES_TOTAL (yaFTL_FTLDeviceInfo.dwUserPagesTotal)
|
||||
#define BYTES_PER_PAGE (yaFTL_FTLDeviceInfo.wBytesPerPage)
|
||||
#define BYTES_PER_PAGE_META (yaFTL_FTLDeviceInfo.wBytesPerPageMeta)
|
||||
#define NUM_BANKS (yaFTL_FTLDeviceInfo.wNumOfBanks)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// UInt32 serialCounter; // serial allocation counter that would be used for restore
|
||||
// UInt16 validPagesNo; // Number of valid pages in block
|
||||
UInt32 erasableCount;
|
||||
UInt16 validPagesDNo;
|
||||
UInt16 validPagesINo;
|
||||
UInt16 pagesRead;
|
||||
UInt8 status;
|
||||
UInt8 eraseBeforeUse;
|
||||
UInt8 pagesReadSubCounter;
|
||||
} BlockEntry;
|
||||
|
||||
// TOCEntry: pointer to cache index if the given index page is in the cache, or pointer to NAND if not.
|
||||
// P.S.: not related to BlockTOCs.
|
||||
typedef struct
|
||||
{
|
||||
UInt32 indexPage; // location on the flash
|
||||
UInt16 cacheIndex; // 0xff means not cached
|
||||
} TOCEntry;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 *indexPage; // pointer to the page address array
|
||||
UInt32 tocEntry; // index of the TOCEntry
|
||||
UInt16 counter; // number of hits on this cache
|
||||
UInt16 status; // free/occupied/dirty
|
||||
} CacheIndexEntry;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt64 ddwPagesWrittenCnt;
|
||||
UInt64 ddwPagesReadCnt;
|
||||
UInt64 ddwFTLWriteCnt;
|
||||
UInt64 ddwFTLReadCnt;
|
||||
UInt64 ddwDataGCCnt;
|
||||
UInt64 ddwIndexGCCnt;
|
||||
UInt64 ddwEmptyGCDataCnt; /* case there is data to copy */
|
||||
UInt64 ddwEmptyGCIndexCnt; /* case there is data to copy */
|
||||
UInt64 ddwValidDataPages;
|
||||
UInt64 ddwValidIndexPages;
|
||||
UInt64 ddwFreeBlks;
|
||||
UInt64 ddwFTLRestoreCnt;
|
||||
UInt64 ddwReadDisturbHandleCall;
|
||||
UInt64 ddwWearLevelCnt;
|
||||
UInt64 ddwFlushCnt;
|
||||
UInt64 ddwRefreshCnt;
|
||||
UInt64 ddwRead[8];
|
||||
UInt64 ddwReadOver8;
|
||||
UInt64 ddwWrite[8];
|
||||
UInt64 ddwWriteOver8;
|
||||
UInt64 ddwNodesFree;
|
||||
UInt64 ddwNodesTotal;
|
||||
} FTLStatistics;
|
||||
|
||||
#define FTL_STATISTICS_DESCREPTION { \
|
||||
"ddwPagesWrittenCnt", \
|
||||
"ddwPagesReadCnt", \
|
||||
"ddwFTLWriteCnt", \
|
||||
"ddwFTLReadCnt", \
|
||||
"ddwDataGCCnt", \
|
||||
"ddwIndexGCCnt", \
|
||||
"ddwEmptyGCDataCnt", \
|
||||
"ddwEmptyGCIndexCnt", \
|
||||
"ddwValidDataPages", \
|
||||
"ddwValidIndexPages", \
|
||||
"ddwFreeBlks", \
|
||||
"ddwFTLRestoreCnt", \
|
||||
"ddwReadDisturbHandleCall", \
|
||||
"ddwWearLevelCnt", \
|
||||
"ddwFlushCnt", \
|
||||
"ddwRefreshCnt", \
|
||||
"ddwRead1", \
|
||||
"ddwRead2", \
|
||||
"ddwRead3", \
|
||||
"ddwRead4", \
|
||||
"ddwRead5", \
|
||||
"ddwRead6", \
|
||||
"ddwRead7", \
|
||||
"ddwRead8", \
|
||||
"ddwReadOver8", \
|
||||
"ddwWrite1", \
|
||||
"ddwWrite2", \
|
||||
"ddwWrite3", \
|
||||
"ddwWrite4", \
|
||||
"ddwWrite5", \
|
||||
"ddwWrite6", \
|
||||
"ddwWrite7", \
|
||||
"ddwWrite8", \
|
||||
"ddwWriteOver8", \
|
||||
"ddwNodesFree", \
|
||||
"ddwNodesTotal", \
|
||||
}
|
||||
|
||||
#define GCFIFO_DEPTH 16
|
||||
typedef struct
|
||||
{
|
||||
UInt32 block[GCFIFO_DEPTH + 1];
|
||||
UInt32 head, tail; // head==tail means it is empty
|
||||
} GC_Fifo_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GCD_IDLE,
|
||||
GCD_EVICT,
|
||||
GCD_ERASE,
|
||||
GCD_FIXINDEX_RETRY,
|
||||
GCD_FIXDATA_RETRY,
|
||||
} GCDState;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// In:
|
||||
UInt32 in_block;
|
||||
|
||||
// Work FIFO for error handling
|
||||
GC_Fifo_t workFifo;
|
||||
|
||||
// Choose out:
|
||||
UInt32 chosenBlock;
|
||||
UInt32 chosenValid;
|
||||
UInt32 chosenErases;
|
||||
|
||||
// Buffers:
|
||||
UInt32 outstandingAllocs;
|
||||
Buffer *tmpB1, *tmpB2, *tmpB3;
|
||||
UInt32 *TOCbuff;
|
||||
UInt8 *pageBuffer;
|
||||
|
||||
// GC zone:
|
||||
UInt32 *vpns;
|
||||
UInt8 *zone;
|
||||
PageMeta_t *meta;
|
||||
UInt32 curZoneSize;
|
||||
UInt32 ueccCounter;
|
||||
|
||||
// State:
|
||||
GCDState state;
|
||||
UInt32 curPage;
|
||||
UInt32 pagesRange;
|
||||
UInt32 pagesCopied;
|
||||
Int32 gcDataAdjust; // only meaningful for data GC
|
||||
|
||||
L2V_SearchCtx_t read_c; // Search context for GC translation
|
||||
} GC_Ctx_t;
|
||||
|
||||
#define ERASE_NOW_LIST_SIZE 5
|
||||
|
||||
typedef struct
|
||||
{
|
||||
WMR_BufZone_t BufZone; // Buffer zone allocators
|
||||
WMR_BufZone_t BufZone_IndexCache; // ...
|
||||
UInt16 controlPageNo, indexPageRatio; /* TOC of each block contains Lpa for each page written to block */
|
||||
UInt32 indexSize; /* index size in blocks */
|
||||
UInt32 dataSize;
|
||||
UInt32 logicalPartitionSize; /* partititon size in pages exposed to file system */
|
||||
UInt16 TOCtableEntriesNo; /* number of entries in index TOC table */
|
||||
|
||||
UInt16 freeCachePages;
|
||||
UInt16 erasedBlockCount;
|
||||
#ifndef AND_READONLY
|
||||
UInt16 nextFreeCachePage;
|
||||
UInt64 cxtAllocation;
|
||||
UInt32 currentCXTIndex, FTLRestoreCnt;
|
||||
UInt8 cxtEraseCounter;
|
||||
UInt32 currentDBlockAllocationNo;
|
||||
UInt8 cxtValid;
|
||||
UInt8 formatWasCalled;
|
||||
BOOL32 readLimit;
|
||||
UInt16 eraseNowList[ERASE_NOW_LIST_SIZE];
|
||||
#endif
|
||||
|
||||
struct
|
||||
{
|
||||
struct
|
||||
{
|
||||
UInt32 block;
|
||||
UInt32 *TOC;
|
||||
UInt16 nextPage;
|
||||
WeaveSeq_t minWeaveSeq;
|
||||
} data;
|
||||
struct
|
||||
{
|
||||
UInt32 block;
|
||||
UInt32 *TOC;
|
||||
UInt16 nextPage;
|
||||
WeaveSeq_t minWeaveSeq;
|
||||
} index;
|
||||
|
||||
WeaveSeq_t weaveSeq;
|
||||
UInt32 lastBlock;
|
||||
} wrState;
|
||||
|
||||
struct
|
||||
{
|
||||
UInt32 size;
|
||||
UInt32 curAge;
|
||||
UInt32 free;
|
||||
UInt32 isData;
|
||||
UInt32 **BTOC;
|
||||
UInt32 *sb;
|
||||
Int32 *age;
|
||||
WMR_BufZone_t BufZone; // Buffer zone allocator
|
||||
|
||||
// For srcVpn:
|
||||
UInt32 srcSize;
|
||||
UInt32 curSrc;
|
||||
UInt32 *srcSb;
|
||||
UInt32 **srcVpn;
|
||||
UInt32 isLocked;
|
||||
} BTOCcache;
|
||||
|
||||
struct
|
||||
{
|
||||
struct
|
||||
{
|
||||
UInt32 allocdBlocks;
|
||||
Int32 freeBlocks;
|
||||
UInt32 validPages;
|
||||
} data;
|
||||
struct
|
||||
{
|
||||
UInt32 allocdBlocks;
|
||||
Int32 freeBlocks;
|
||||
UInt32 validPages;
|
||||
} index;
|
||||
UInt32 freeBlocks;
|
||||
BOOL32 distCheckable;
|
||||
} seaState;
|
||||
|
||||
struct
|
||||
{
|
||||
UInt32 blocksSince;
|
||||
BOOL32 pointOfNoReturn;
|
||||
} wearLevel;
|
||||
|
||||
struct
|
||||
{
|
||||
UInt32 pagesWritten;
|
||||
UInt32 erases;
|
||||
} periodicCxt;
|
||||
|
||||
TOCEntry *tocArray; /* [TOC_SIZE] Table of content that contains location of index pages in flash and index cache */
|
||||
CacheIndexEntry *indexCache; /* [INDEX_CACHE_SIZE] cached index pages */
|
||||
BlockEntry *blockArray; /* [YAFTL_NO_OF_BLOCKS] block information */
|
||||
UInt32 *restoreTOC; // blockTOC for restore
|
||||
|
||||
PageMeta_t *meta_restoreIdx;
|
||||
PageMeta_t *meta_restoreData;
|
||||
PageMeta_t *meta_readCxt;
|
||||
PageMeta_t *meta_quickRestore;
|
||||
PageMeta_t *meta_invalidateCxt;
|
||||
PageMeta_t *meta_writeCxt;
|
||||
PageMeta_t *meta_restoreMountErase;
|
||||
PageMeta_t *meta_restoreMount;
|
||||
PageMeta_t *meta_clearEntryInCache;
|
||||
PageMeta_t *meta_writeBTOC;
|
||||
PageMeta_t *meta_indexLoadDirty;
|
||||
PageMeta_t *meta_getStats;
|
||||
PageMeta_t *meta_GetBlockTOC;
|
||||
PageMeta_t *meta_IsDataPageCurrent;
|
||||
PageMeta_t *meta_WriteZoneData;
|
||||
|
||||
UInt8 *quickRestore_tBuff;
|
||||
UInt32 *tmpReadBuffer; // = NULL;
|
||||
UInt32 readBufferIndex; // = 0xffffffff;
|
||||
PageMeta_t *writeMdPtr; // = NULL;
|
||||
UInt32 *multiReadvpN; // = NULL;
|
||||
PageMeta_t *readMdPtr; // = NULL;
|
||||
PageMeta_t *singleMdPtr;
|
||||
UInt32 cxtSize, cxtSizeTOC, cxtSizeBlockStatus, cxtSizeBlockRead,
|
||||
cxtSizeBlockErase, cxtSizeValidPagesD, cxtSizeValidPagesI;
|
||||
UInt32 currentCxtVpn; // = 0xffffffff;
|
||||
UInt16 cxtTable[FTL_CXT_SECTION_SIZE];
|
||||
UInt32 maxEraseCount, minEraseCount; // = 0
|
||||
|
||||
UInt32 indexCacheSize; // = DEFAULT_INDEX_CACHE_SIZE;
|
||||
UInt8 exportedRatio; // = DEFAULT_EXPO_RATIO;
|
||||
|
||||
// Garbage collection structures
|
||||
struct
|
||||
{
|
||||
UInt32 zoneSize;
|
||||
GC_Ctx_t data;
|
||||
GC_Ctx_t index;
|
||||
WMR_BufZone_t BufZone; // Buffer zone allocator
|
||||
PageMeta_t *meta_buf;
|
||||
} gc;
|
||||
|
||||
// Read search context
|
||||
L2V_SearchCtx_t read_c;
|
||||
} yaFTL_t;
|
||||
|
||||
#endif /* _YAFTLTYPES_H_ */
|
||||
@@ -0,0 +1,371 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#include "yaFTL_whoami.h"
|
||||
#include "WMRConfig.h"
|
||||
#include "yaFTL_BTOC.h"
|
||||
#include "ANDTypes.h"
|
||||
#include "WMROAM.h"
|
||||
#include "VFLBuffer.h"
|
||||
#include "VFL.h"
|
||||
#include "FTL.h"
|
||||
#include "yaFTLTypes.h"
|
||||
#include "yaFTL_Defines.h"
|
||||
|
||||
// Extern context struct
|
||||
extern yaFTL_t yaFTL;
|
||||
extern FTLWMRDeviceInfo yaFTL_FTLDeviceInfo;
|
||||
extern Int32 _readPage(UInt32 vpn, UInt8 *pageData, PageMeta_t *mdPtr, BOOL32 bInternalOp, BOOL32 boolCleanCheck, BOOL32 scrubOnUECC);
|
||||
extern ANDStatus invalidateCXT(void);
|
||||
|
||||
BOOL32 BTOC_Init()
|
||||
{
|
||||
UInt32 i;
|
||||
|
||||
yaFTL.BTOCcache.size = YAFTL_BTOCCACHE_SIZE_PER * 2;
|
||||
WMR_ASSERT(yaFTL.BTOCcache.size <= 32);
|
||||
yaFTL.BTOCcache.srcSize = YAFTL_BTOCCACHE_SRCSIZE;
|
||||
yaFTL.BTOCcache.curSrc = yaFTL.BTOCcache.srcSize-1;
|
||||
|
||||
yaFTL.BTOCcache.curAge = 0;
|
||||
yaFTL.BTOCcache.age = WMR_MALLOC(sizeof(*yaFTL.BTOCcache.age) * yaFTL.BTOCcache.size);
|
||||
yaFTL.BTOCcache.sb = WMR_MALLOC(sizeof(*yaFTL.BTOCcache.sb) * yaFTL.BTOCcache.size);
|
||||
yaFTL.BTOCcache.BTOC = WMR_MALLOC(sizeof(*yaFTL.BTOCcache.BTOC) * yaFTL.BTOCcache.size);
|
||||
yaFTL.BTOCcache.srcVpn = WMR_MALLOC(sizeof(*yaFTL.BTOCcache.srcVpn) * yaFTL.BTOCcache.srcSize);
|
||||
yaFTL.BTOCcache.srcSb = WMR_MALLOC(sizeof(*yaFTL.BTOCcache.srcSb) * yaFTL.BTOCcache.srcSize);
|
||||
yaFTL.BTOCcache.isLocked = 0;
|
||||
|
||||
// Check for allocation failure
|
||||
if ((NULL == yaFTL.BTOCcache.age) || (NULL == yaFTL.BTOCcache.sb) || (NULL == yaFTL.BTOCcache.BTOC)
|
||||
|| (NULL == yaFTL.BTOCcache.srcVpn) || (NULL == yaFTL.BTOCcache.srcSb))
|
||||
{
|
||||
return FALSE32;
|
||||
}
|
||||
|
||||
for (i = 0; i < yaFTL.BTOCcache.size; i++)
|
||||
{
|
||||
yaFTL.BTOCcache.sb[i] = 0xffffffff;
|
||||
}
|
||||
|
||||
for (i = 0; i < yaFTL.BTOCcache.srcSize; i++)
|
||||
{
|
||||
yaFTL.BTOCcache.srcSb[i] = 0xffffffff;
|
||||
yaFTL.BTOCcache.srcVpn[i] = WMR_MALLOC(sizeof(**yaFTL.BTOCcache.srcVpn) * PAGES_PER_SUBLK);
|
||||
WMR_MEMSET(yaFTL.BTOCcache.srcVpn[i], 0xff, sizeof(**yaFTL.BTOCcache.srcVpn) * PAGES_PER_SUBLK);
|
||||
}
|
||||
|
||||
yaFTL.BTOCcache.free = (1 << yaFTL.BTOCcache.size) - 1;
|
||||
yaFTL.BTOCcache.isData = (1 << YAFTL_BTOCCACHE_SIZE_PER) - 1;
|
||||
|
||||
// Allocate buffers
|
||||
WMR_BufZone_Init(&yaFTL.BTOCcache.BufZone);
|
||||
|
||||
for (i = 0; i < yaFTL.BTOCcache.size; i++)
|
||||
{
|
||||
yaFTL.BTOCcache.BTOC[i] = (UInt32*)WMR_Buf_Alloc_ForDMA(&yaFTL.BTOCcache.BufZone, yaFTL.controlPageNo * BYTES_PER_PAGE);
|
||||
}
|
||||
|
||||
if (!WMR_BufZone_FinishedAllocs(&yaFTL.BTOCcache.BufZone)) {
|
||||
return FALSE32;
|
||||
}
|
||||
|
||||
for (i = 0; i < yaFTL.BTOCcache.size; i++)
|
||||
{
|
||||
WMR_BufZone_Rebase(&yaFTL.BTOCcache.BufZone, (void**)&yaFTL.BTOCcache.BTOC[i]);
|
||||
}
|
||||
|
||||
WMR_BufZone_FinishedRebases(&yaFTL.BTOCcache.BufZone);
|
||||
|
||||
return TRUE32;
|
||||
}
|
||||
|
||||
void BTOC_Close()
|
||||
{
|
||||
UInt32 i;
|
||||
|
||||
WMR_BufZone_Free(&yaFTL.BTOCcache.BufZone);
|
||||
|
||||
if (NULL != yaFTL.BTOCcache.age)
|
||||
{
|
||||
WMR_FREE(yaFTL.BTOCcache.age, sizeof(*yaFTL.BTOCcache.age) * yaFTL.BTOCcache.size);
|
||||
}
|
||||
if (NULL != yaFTL.BTOCcache.sb)
|
||||
{
|
||||
WMR_FREE(yaFTL.BTOCcache.sb, sizeof(*yaFTL.BTOCcache.sb) * yaFTL.BTOCcache.size);
|
||||
}
|
||||
if (NULL != yaFTL.BTOCcache.BTOC)
|
||||
{
|
||||
WMR_FREE(yaFTL.BTOCcache.BTOC, sizeof(*yaFTL.BTOCcache.BTOC) * yaFTL.BTOCcache.size);
|
||||
}
|
||||
// Free srcVpn memory
|
||||
if (NULL != yaFTL.BTOCcache.srcSb)
|
||||
{
|
||||
WMR_FREE(yaFTL.BTOCcache.srcSb, sizeof(*yaFTL.BTOCcache.srcSb) * yaFTL.BTOCcache.srcSize);
|
||||
}
|
||||
for (i = 0; i < yaFTL.BTOCcache.srcSize; i++)
|
||||
{
|
||||
WMR_FREE(yaFTL.BTOCcache.srcVpn[i], sizeof(**yaFTL.BTOCcache.srcVpn) * PAGES_PER_SUBLK);
|
||||
}
|
||||
if (NULL != yaFTL.BTOCcache.srcVpn)
|
||||
{
|
||||
WMR_FREE(yaFTL.BTOCcache.srcVpn, sizeof(*yaFTL.BTOCcache.srcVpn) * yaFTL.BTOCcache.srcSize);
|
||||
}
|
||||
|
||||
yaFTL.BTOCcache.age = NULL;
|
||||
yaFTL.BTOCcache.sb = NULL;
|
||||
yaFTL.BTOCcache.BTOC = NULL;
|
||||
yaFTL.BTOCcache.srcSb = NULL;
|
||||
yaFTL.BTOCcache.srcVpn = NULL;
|
||||
|
||||
yaFTL.BTOCcache.size = 0;
|
||||
|
||||
yaFTL.BTOCcache.srcSize = 0;
|
||||
}
|
||||
|
||||
void BTOC_BootFixup()
|
||||
{
|
||||
UInt32 i;
|
||||
|
||||
for (i = 0; i < yaFTL.BTOCcache.size; i++)
|
||||
{
|
||||
if (0xfffffffd == yaFTL.BTOCcache.sb[i])
|
||||
{
|
||||
yaFTL.BTOCcache.sb[i] = yaFTL.wrState.data.block;
|
||||
}
|
||||
if (0xfffffffe == yaFTL.BTOCcache.sb[i])
|
||||
{
|
||||
yaFTL.BTOCcache.sb[i] = yaFTL.wrState.index.block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UInt32 *BTOC_Alloc(UInt32 sb, BOOL32 isData)
|
||||
{
|
||||
UInt32 i, minIdx, isData32 = (isData ? 1 : 0);
|
||||
Int32 minAge;
|
||||
|
||||
// Get a srcVpn
|
||||
yaFTL.BTOCcache.curSrc = (yaFTL.BTOCcache.curSrc + 1) % yaFTL.BTOCcache.srcSize;
|
||||
yaFTL.BTOCcache.srcSb[yaFTL.BTOCcache.curSrc] = sb;
|
||||
WMR_MEMSET(yaFTL.BTOCcache.srcVpn[yaFTL.BTOCcache.curSrc], 0xff, sizeof(**yaFTL.BTOCcache.srcVpn) * PAGES_PER_SUBLK);
|
||||
|
||||
// Get a BTOC
|
||||
yaFTL.BTOCcache.curAge++;
|
||||
|
||||
minAge = 0x7fffffff;
|
||||
minIdx = 0xffffffff;
|
||||
|
||||
for (i = 0; i < yaFTL.BTOCcache.size; i++)
|
||||
{
|
||||
if (((yaFTL.BTOCcache.isData & (1 << i)) == (isData32 << i))
|
||||
&& (yaFTL.BTOCcache.free & (1 << i))
|
||||
&& (yaFTL.BTOCcache.age[i] < minAge)
|
||||
&& ((yaFTL.BTOCcache.isLocked & (1 << i)) == 0))
|
||||
{
|
||||
minAge = yaFTL.BTOCcache.age[i];
|
||||
minIdx = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (0xffffffff != minIdx) {
|
||||
yaFTL.BTOCcache.free &= ~(1 << minIdx);
|
||||
yaFTL.BTOCcache.sb[minIdx] = sb;
|
||||
yaFTL.BTOCcache.age[minIdx] = yaFTL.BTOCcache.curAge;
|
||||
return yaFTL.BTOCcache.BTOC[minIdx];
|
||||
}
|
||||
#ifndef AND_READONLY
|
||||
// Invalidate context
|
||||
if (yaFTL.cxtValid == 1)
|
||||
{
|
||||
invalidateCXT();
|
||||
yaFTL.cxtValid = 0;
|
||||
}
|
||||
WMR_PANIC("Couldn't allocate a BTOC");
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UInt32 BTOC_GetSrc(UInt32 destVpn)
|
||||
{
|
||||
UInt32 i, sb, idx;
|
||||
|
||||
sb = destVpn / PAGES_PER_SUBLK;
|
||||
idx = destVpn % PAGES_PER_SUBLK;
|
||||
|
||||
for (i = 0; i < yaFTL.BTOCcache.srcSize; i++)
|
||||
{
|
||||
if (sb == yaFTL.BTOCcache.srcSb[i]) {
|
||||
return yaFTL.BTOCcache.srcVpn[i][idx];
|
||||
}
|
||||
}
|
||||
|
||||
return 0xffffffff;
|
||||
}
|
||||
|
||||
void BTOC_SetSrc(UInt32 destVpn, UInt32 srcVpn)
|
||||
{
|
||||
UInt32 i, sb, idx;
|
||||
|
||||
sb = destVpn / PAGES_PER_SUBLK;
|
||||
idx = destVpn % PAGES_PER_SUBLK;
|
||||
|
||||
for (i = 0; i < yaFTL.BTOCcache.srcSize; i++)
|
||||
{
|
||||
if (sb == yaFTL.BTOCcache.srcSb[i]) {
|
||||
yaFTL.BTOCcache.srcVpn[i][idx] = srcVpn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BTOC_Dealloc(UInt32 *BTOC)
|
||||
{
|
||||
UInt32 i;
|
||||
|
||||
for (i = 0; i < yaFTL.BTOCcache.size; i++)
|
||||
{
|
||||
if (BTOC == yaFTL.BTOCcache.BTOC[i])
|
||||
{
|
||||
yaFTL.BTOCcache.free |= (1 << i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
#ifndef AND_READONLY
|
||||
// Invalidate context
|
||||
if (yaFTL.cxtValid == 1)
|
||||
{
|
||||
invalidateCXT();
|
||||
yaFTL.cxtValid = 0;
|
||||
}
|
||||
WMR_PANIC("Couldn't deallocate BTOC: 0x%x", BTOC);
|
||||
#endif
|
||||
}
|
||||
|
||||
UInt32 *BTOC_Search(UInt32 sb, BOOL32 isData)
|
||||
{
|
||||
UInt32 i, isData32 = (isData ? 1 : 0);
|
||||
Int32 maxAge = -1;
|
||||
UInt32 *best = NULL;
|
||||
|
||||
for (i = 0; i < yaFTL.BTOCcache.size; i++)
|
||||
{
|
||||
if ((yaFTL.BTOCcache.sb[i] == sb) && (yaFTL.BTOCcache.age[i] > maxAge) && ((yaFTL.BTOCcache.isData & (1 << i)) == (isData32 << i)))
|
||||
{
|
||||
maxAge = yaFTL.BTOCcache.age[i];
|
||||
best = yaFTL.BTOCcache.BTOC[i];
|
||||
}
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
void BTOC_Lock(UInt32 sb)
|
||||
{
|
||||
UInt32 i;
|
||||
|
||||
for (i = 0; i < yaFTL.BTOCcache.size; i++)
|
||||
{
|
||||
if ((yaFTL.BTOCcache.sb[i] == sb) && ((yaFTL.BTOCcache.free & (1 << i)) == 0))
|
||||
{
|
||||
yaFTL.BTOCcache.isLocked |= (1 << i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void BTOC_Unlock(UInt32 sb)
|
||||
{
|
||||
UInt32 i;
|
||||
|
||||
for (i = 0; i < yaFTL.BTOCcache.size; i++)
|
||||
{
|
||||
if ((yaFTL.BTOCcache.sb[i] == sb) && (yaFTL.BTOCcache.isLocked & (1 << i)))
|
||||
{
|
||||
yaFTL.BTOCcache.isLocked &= ~(1 << i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ANDStatus BTOC_Read(UInt32 vpn, UInt32 *bTOC, PageMeta_t *mdPtr, BOOL32 val, BOOL32 scrubOnUECC, UInt32 upperBound)
|
||||
{
|
||||
UInt16 i;
|
||||
ANDStatus status = FTL_CRITICAL_ERROR;
|
||||
|
||||
for (i = 0; i < yaFTL.controlPageNo; i++)
|
||||
{
|
||||
status = _readPage(vpn + i, ((UInt8 *)bTOC) + (i * BYTES_PER_PAGE), mdPtr, val, TRUE32, scrubOnUECC);
|
||||
if (status != FTL_SUCCESS)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (status == FTL_SUCCESS)
|
||||
{
|
||||
UInt32 * tmpPtr = (UInt32 *)bTOC;
|
||||
for(i = 0; i < ((yaFTL.controlPageNo * BYTES_PER_PAGE) >> 2);i++)
|
||||
if(tmpPtr[i] >= upperBound)
|
||||
{
|
||||
tmpPtr[i] = 0xffffffff;
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
void BTOC_SetAll(UInt32 *bTOC, UInt8 value)
|
||||
{
|
||||
WMR_MEMSET(bTOC, value, yaFTL.controlPageNo * BYTES_PER_PAGE);
|
||||
}
|
||||
|
||||
|
||||
void BTOC_Copy(UInt32 *left, UInt32 *right, UInt32 upperBound)
|
||||
{
|
||||
UInt16 i;
|
||||
for(i = 0; i < ((yaFTL.controlPageNo * BYTES_PER_PAGE) >> 2);i++)
|
||||
if(right[i] >= upperBound)
|
||||
{
|
||||
left[i] = 0xffffffff;
|
||||
}
|
||||
else
|
||||
{
|
||||
left[i] = right[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UInt32 BTOC_Get(UInt32 *bTOC, UInt32 offset, UInt32 upperBound)
|
||||
{
|
||||
if(bTOC[offset] >= upperBound)
|
||||
{
|
||||
return 0xffffffff;
|
||||
}
|
||||
else
|
||||
{
|
||||
return bTOC[offset];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UInt32 BTOC_Set(UInt32 *bTOC, UInt32 offset, UInt32 val, UInt32 upperBound)
|
||||
{
|
||||
if(val >= upperBound)
|
||||
{
|
||||
bTOC[offset] = 0xffffffff;
|
||||
}
|
||||
else
|
||||
{
|
||||
bTOC[offset] = val;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#ifndef __YAFTL_BTOC_H__
|
||||
#define __YAFTL_BTOC_H__
|
||||
|
||||
// Includes
|
||||
#include "yaFTL_whoami.h"
|
||||
#include "ANDTypes.h"
|
||||
#include "WMROAM.h"
|
||||
#include "yaFTLTypes.h"
|
||||
#include "yaFTL_meta.h"
|
||||
|
||||
// Defines and types declared elsewhere
|
||||
|
||||
// Prototypes:
|
||||
|
||||
// BTOC init/alloc/dealloc
|
||||
extern BOOL32 BTOC_Init(void);
|
||||
extern void BTOC_BootFixup(void);
|
||||
extern void BTOC_Close(void);
|
||||
extern UInt32 *BTOC_Alloc(UInt32 sb, BOOL32 isData);
|
||||
extern void BTOC_Dealloc(UInt32 *BTOC);
|
||||
extern UInt32 *BTOC_Search(UInt32 sb, BOOL32 isData);
|
||||
extern void BTOC_Lock(UInt32 sb);
|
||||
extern void BTOC_Unlock(UInt32 sb);
|
||||
|
||||
// Read
|
||||
extern ANDStatus BTOC_Read(UInt32 vpn, UInt32 *bTOC, PageMeta_t *mdPtr, BOOL32 val, BOOL32 scrubOnUECC, UInt32 upperBound);
|
||||
|
||||
// Src for GC
|
||||
extern void BTOC_SetSrc(UInt32 destVpn, UInt32 srcVpn);
|
||||
extern UInt32 BTOC_GetSrc(UInt32 destVpn);
|
||||
|
||||
// Getters/setters
|
||||
extern void BTOC_SetAll(UInt32 *bTOC, UInt8 value);
|
||||
extern UInt32 BTOC_Get(UInt32 *bTOC, UInt32 offset, UInt32 upperBound);
|
||||
extern UInt32 BTOC_Set(UInt32 *bTOC, UInt32 offset, UInt32 val, UInt32 upperBound);
|
||||
|
||||
// Copy
|
||||
extern void BTOC_Copy(UInt32 *left, UInt32 *right, UInt32 upperBound);
|
||||
|
||||
#endif // ----- #ifndef __YAFTL_BTOC_H__
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#ifndef __YAFTL_DEFINES_H__
|
||||
#define __YAFTL_DEFINES_H__
|
||||
|
||||
|
||||
#define YAFTLDBG_INIT (1 << 0)
|
||||
#define YAFTLDBG_FORMAT (1 << 1)
|
||||
#define YAFTLDBG_READ (1 << 2)
|
||||
#define YAFTLDBG_WRITE (1 << 3)
|
||||
#define YAFTLDBG_ERASE (1 << 4)
|
||||
#define YAFTLDBG_MISC (1 << 5)
|
||||
#define YAFTLDBG_ERROR (1 << 6)
|
||||
#define YAFTLDBG_OPEN (1 << 7)
|
||||
#define YAFTLDBG_INFO (1 << 8)
|
||||
|
||||
//#define YAFTL_DEBUG (YAFTLDBG_INIT | YAFTLDBG_ERROR | YAFTLDBG_INFO)
|
||||
#define YAFTL_DEBUG (YAFTLDBG_ERROR)
|
||||
#ifdef YAFTL_DEBUG
|
||||
#define YAFTL_ENABLE_DEBUG_PRINT (0xff)
|
||||
|
||||
# define debug(fac, fmt, args ...) \
|
||||
do { \
|
||||
if (YAFTLDBG_ ## fac & YAFTL_DEBUG & YAFTL_ENABLE_DEBUG_PRINT) { \
|
||||
_WMR_PRINT("yaFTL::%s(l:%d): " fmt "\n", __FUNCTION__, __LINE__, ## args); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
# define debug(fac, fmt, args ...) do { } while (0)
|
||||
#endif
|
||||
|
||||
#define FREE_BLK_TRH (5) /* number of units we require to be avaiable at any time */
|
||||
#define INDEX_AREA (1) /* block belongs to Index area */
|
||||
#define DATA_AREA (2) /* block belongs to data area */
|
||||
#define FREE_I_BLOCK_TRS (2) /* minimum free blocks within index area */
|
||||
#define DEFAULT_INDEX_CACHE_SIZE (10) /* index cached pages */
|
||||
#define INDEX_BLOCKS_RATIO (3) /* ratio of index area in flash to required index area by flash size */
|
||||
#define DEFAULT_EXPO_RATIO (99) /* percentage of data area exposed to file system */
|
||||
#define CXT_ERASE_LIMIT (30)
|
||||
|
||||
|
||||
#define IC_DIRTY_PAGE 1
|
||||
#define IC_BUSY_PAGE 2
|
||||
#define FREE_CACHE_PAGE 0xffff
|
||||
|
||||
#define BLOCK_FREE (0xFF) /* block marked as free */
|
||||
#define BLOCK_ALLOCATED (1) /* block marked as allocated for data area */
|
||||
#define BLOCK_CURRENT (4) /* block marked as current in data area */
|
||||
|
||||
#define BLOCK_GC (8) /* block in data area goes through GC process */
|
||||
|
||||
#define BLOCK_I_FREE (0xFF) /* block marked as free */
|
||||
#define BLOCK_I_CURRENT (32) /* block marked as current index block */
|
||||
#define BLOCK_I_ALLOCATED (64) /* block marked as idex block */
|
||||
#define BLOCK_I_GC (128) /* block in index area goes through GC process */
|
||||
#define BLOCK_TO_BE_ERASED (0x1) /* erase block before use . make sure the block is not erased before current block is closed */
|
||||
#define BLOCK_TO_BE_ERASED_ALIGNED_DATA (0x2) /* erase block before use . make sure the block is not erased before current block is closed */
|
||||
#define BLOCK_TO_BE_ERASED_ALIGNED_INDEX (0x4) /* erase block before use . make sure the block is not erased before current block is closed */
|
||||
#define BLOCK_READ_SCATTER (0x8) /* mark a block as being used in multi-read operation */
|
||||
#define BLOCK_TO_BE_MOVED (0x80) /* use it as an idication that block is to be refreshed after full mount is complete due to UECCs */
|
||||
|
||||
#define ERASE_IDLE_LIMIT (5) /* number of free blocks to be erased in idle time */
|
||||
|
||||
#define BLOCK_CTX_CNTR (2) /* block marked as CXT */
|
||||
#define BLOCK_CTX_CURRENT (16) /* block marked as current CXT */
|
||||
#define INDEX_PAGE_MARK (0x80000000) /* to be defined */
|
||||
|
||||
#define YAFTL_READ_DISTURB_LIMIT YAFTL_RC_THRESHOLD /* read disturb limit */
|
||||
|
||||
#define MIN_RESTORE_BUFFER (0x10000)
|
||||
#define MAX_RESTORE_BUFFER (0x200000)
|
||||
#define YAFTL_WEARLEVEL_PERIOD 30
|
||||
#define ERASE_COUNT_GAP_LIMIT 100
|
||||
#define ERASE_COUNT_GAP_UPPER_LIMIT 500
|
||||
#define STATIC_WEARLEVEL_TRIGGER 1000
|
||||
#define NAND_MOUNT_INDEX_SIZE 1000
|
||||
#define YAFTL_WRITE_MAX_STRIPES 32
|
||||
#define YAFTL_INDEX_CACHE_COUNTER_LIMIT 0xFFFF
|
||||
#define PAGES_READ_SUB_COUNTER_LIMIT YAFTL_RC_MULTIPLIER
|
||||
|
||||
// GCZONE_DOUBLEUPTO defines the point up to which we will multiply banks to.
|
||||
// It is similar to setting a minimum of 16, but works with non-pow-2 configs.
|
||||
#define GCZONE_DOUBLEUPTO 16
|
||||
#define YAFTL_GC_RATIO_SCALAR 4
|
||||
|
||||
// Maximum number of TOC pages/block to support
|
||||
#define MAX_TOC_PAGES 4
|
||||
#define YAFTL_BTOCCACHE_SIZE_PER 2
|
||||
#define YAFTL_BTOCCACHE_SRCSIZE 2
|
||||
|
||||
// make the function pointers in vfl struct look like the old vfl functions
|
||||
#ifndef AND_READONLY
|
||||
#define VFL_Format (yaFTL_VFLFunctions.Format)
|
||||
#define VFL_Write (yaFTL_VFLFunctions.WriteSinglePage)
|
||||
#define VFL_Erase (yaFTL_VFLFunctions.Erase)
|
||||
#define VFL_ChangeFTLCxtVbn (yaFTL_VFLFunctions.ChangeFTLCxtVbn)
|
||||
#define VFL_WriteMultiplePagesInVb (yaFTL_VFLFunctions.WriteMultiplePagesInVb)
|
||||
#endif // ! AND_READONLY
|
||||
#define VFL_Init (yaFTL_VFLFunctions.Init)
|
||||
#define VFL_Open (yaFTL_VFLFunctions.Open)
|
||||
#define VFL_Close (yaFTL_VFLFunctions.Close)
|
||||
#define VFL_ReadMultiplePagesInVb (yaFTL_VFLFunctions.ReadMultiplePagesInVb)
|
||||
#define VFL_ReadScatteredPagesInVb (yaFTL_VFLFunctions.ReadScatteredPagesInVb)
|
||||
#define VFL_Read (yaFTL_VFLFunctions.ReadSinglePage)
|
||||
#define VFL_GetFTLCxtVbn (yaFTL_VFLFunctions.GetFTLCxtVbn)
|
||||
//#define VFL_GetAddress (yaFTL_VFLFunctions.GetAddress)
|
||||
#define VFL_GetDeviceInfo (yaFTL_VFLFunctions.GetDeviceInfo)
|
||||
#define VFL_GetStruct (yaFTL_VFLFunctions.GetStruct)
|
||||
#define VFL_SetStruct (yaFTL_VFLFunctions.SetStruct)
|
||||
|
||||
#endif // ----- #ifndef _YAFTL_DEFINES_H__INC -----
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#ifndef __YAFTL_GC_H__
|
||||
#define __YAFTL_GC_H__
|
||||
|
||||
#include "yaFTL_whoami.h"
|
||||
#include "ANDTypes.h"
|
||||
|
||||
// General setup/close
|
||||
extern ANDStatus YAFTL_GC_Init(void);
|
||||
extern void YAFTL_GC_Close(void);
|
||||
|
||||
// Called by Write
|
||||
extern void YAFTL_GC_PreWrite(UInt32 writeSize);
|
||||
|
||||
// For error recovery
|
||||
extern void YAFTL_GC_Data_Enq(UInt32 block);
|
||||
extern UInt32 YAFTL_GC_Data_Deq_sb(UInt32 block);
|
||||
extern void YAFTL_GC_Index_Enq(UInt32 block);
|
||||
|
||||
// Direct access to the machines
|
||||
extern ANDStatus YAFTL_GC_Index(UInt32 block, BOOL32 scrubOnUECC);
|
||||
extern ANDStatus YAFTL_GC_Data(UInt32 block, BOOL32 scrubOnUECC);
|
||||
|
||||
#ifdef AND_READONLY
|
||||
#define CheckBlockDist(x)
|
||||
#else
|
||||
extern void CheckBlockDist(void);
|
||||
#endif
|
||||
|
||||
#endif // ----- #ifndef __YAFTL_GC_H__
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __YAFTL_META_H__
|
||||
#define __YAFTL_META_H__
|
||||
|
||||
#include "yaFTL_whoami.h"
|
||||
#include "WMROAM.h"
|
||||
|
||||
#if NAND_PPN
|
||||
#include "yaFTL_meta_ppn.h"
|
||||
#else
|
||||
// Default to raw to avoid compilation errors--meta isn't needed by some of the parsers that include yaFTLTypes.h
|
||||
#include "yaFTL_meta_raw.h"
|
||||
#endif
|
||||
|
||||
#endif // __YAFTL_META_H__
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include "yaFTL_whoami.h"
|
||||
#include "yaFTL_meta_ppn.h"
|
||||
#include "WMRConfig.h"
|
||||
#include "yaFTLTypes.h"
|
||||
|
||||
extern yaFTL_t yaFTL;
|
||||
|
||||
|
||||
void SetupMeta_Data(PageMeta_t *__meta, UInt32 lba, UInt32 count)
|
||||
{
|
||||
PageMeta_Data_t *m = (PageMeta_Data_t*)__meta;
|
||||
|
||||
while (count--) {
|
||||
yaFTL.wrState.weaveSeq++;
|
||||
|
||||
m->c.PageType = PAGETYPE_FTL_DATA;
|
||||
m->c.FTLFlags = 0;
|
||||
m->lba = lba;
|
||||
m->c.weaveLo = yaFTL.wrState.weaveSeq;
|
||||
m->c.weaveHi = (UInt32)(yaFTL.wrState.weaveSeq >> 16);
|
||||
m->userSeq = (UInt32)(yaFTL.wrState.weaveSeq >> 16);
|
||||
|
||||
// Next
|
||||
lba++;
|
||||
m++;
|
||||
}
|
||||
}
|
||||
|
||||
void SetupMeta_Data_UECC(PageMeta_t *__meta)
|
||||
{
|
||||
__meta->c.FTLFlags |= PFLAG_UECC;
|
||||
}
|
||||
|
||||
void SetupMeta_Index(PageMeta_t *__meta, UInt32 ipn)
|
||||
{
|
||||
PageMeta_Idx_t *m = (PageMeta_Idx_t*)__meta;
|
||||
|
||||
yaFTL.wrState.weaveSeq++;
|
||||
|
||||
m->c.PageType = PAGETYPE_FTL_IDX;
|
||||
m->c.FTLFlags = 0;
|
||||
m->c.weaveLo = yaFTL.wrState.weaveSeq;
|
||||
m->c.weaveHi = (UInt32)(yaFTL.wrState.weaveSeq >> 16);
|
||||
m->baseLba = ipn * yaFTL.indexPageRatio;
|
||||
}
|
||||
|
||||
void SetupMeta_Data_BTOC(PageMeta_t *__meta)
|
||||
{
|
||||
PageMeta_BTOC_t *m = (PageMeta_BTOC_t*)__meta;
|
||||
|
||||
m->c.PageType = PAGETYPE_FTL_BTOC_DATA;
|
||||
m->c.FTLFlags = 0;
|
||||
m->c.weaveLo = yaFTL.wrState.data.minWeaveSeq;
|
||||
m->c.weaveHi = (UInt32)(yaFTL.wrState.data.minWeaveSeq >> 16);
|
||||
m->maxWeaveSeqAdd = (UInt32)(yaFTL.wrState.weaveSeq - yaFTL.wrState.data.minWeaveSeq);
|
||||
m->__rfu__ = 0xffffffff;
|
||||
}
|
||||
|
||||
void SetupMeta_Index_BTOC(PageMeta_t *__meta)
|
||||
{
|
||||
PageMeta_BTOC_t *m = (PageMeta_BTOC_t*)__meta;
|
||||
|
||||
m->c.PageType = PAGETYPE_FTL_BTOC_IDX;
|
||||
m->c.FTLFlags = 0;
|
||||
m->c.weaveLo = yaFTL.wrState.index.minWeaveSeq;
|
||||
m->c.weaveHi = (UInt32)(yaFTL.wrState.index.minWeaveSeq >> 16);
|
||||
m->maxWeaveSeqAdd = (UInt32)(yaFTL.wrState.weaveSeq - yaFTL.wrState.index.minWeaveSeq);
|
||||
m->__rfu__ = 0xffffffff;
|
||||
}
|
||||
|
||||
void SetupMeta_IndexGC(PageMeta_t *__meta, UInt32 count)
|
||||
{
|
||||
PageMeta_Idx_t *m = (PageMeta_Idx_t*)__meta;
|
||||
|
||||
while (count--) {
|
||||
yaFTL.wrState.weaveSeq++;
|
||||
|
||||
m->c.PageType = PAGETYPE_FTL_IDX;
|
||||
m->c.FTLFlags = 0;
|
||||
m->c.weaveLo = yaFTL.wrState.weaveSeq;
|
||||
m->c.weaveHi = (UInt32)(yaFTL.wrState.weaveSeq >> 16);
|
||||
|
||||
// Next
|
||||
m++;
|
||||
}
|
||||
}
|
||||
|
||||
void SetupMeta_DataGC(PageMeta_t *__meta, UInt32 count)
|
||||
{
|
||||
PageMeta_Data_t *m = (PageMeta_Data_t*)__meta;
|
||||
|
||||
while (count--) {
|
||||
yaFTL.wrState.weaveSeq++;
|
||||
|
||||
m->c.PageType = PAGETYPE_FTL_DATA;
|
||||
// Don't touch FTLFlags--might have uECC flag
|
||||
m->c.weaveLo = yaFTL.wrState.weaveSeq;
|
||||
m->c.weaveHi = (UInt32)(yaFTL.wrState.weaveSeq >> 16);
|
||||
// Don't touch LBA or userSeq
|
||||
|
||||
// Next
|
||||
m++;
|
||||
}
|
||||
}
|
||||
|
||||
void SetupMeta_Cxt(PageMeta_t *__meta, UInt64 weaveSeq)
|
||||
{
|
||||
PageMeta_Cxt_t *m = (PageMeta_Cxt_t*)__meta;
|
||||
|
||||
yaFTL.wrState.weaveSeq++;
|
||||
|
||||
m->c.PageType = PAGETYPE_FTL_CXT;
|
||||
m->c.FTLFlags = 0;
|
||||
m->c.weaveLo = weaveSeq;
|
||||
m->c.weaveHi = (UInt32)(weaveSeq >> 16);
|
||||
m->__rfu1__ = 0;
|
||||
m->__rfu2__ = 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#ifndef __YAFTL_META_PPN_H__
|
||||
#define __YAFTL_META_PPN_H__
|
||||
|
||||
#include "yaFTL_whoami.h"
|
||||
#include "WMROAM.h"
|
||||
|
||||
|
||||
|
||||
// PageType defines--
|
||||
#define PAGETYPE_FTL_DATA (AND_SPARE_TYPE_REGION_FTL + 0x00)
|
||||
#define PAGETYPE_FTL_BTOC_DATA (AND_SPARE_TYPE_REGION_FTL + 0x1C)
|
||||
#define PAGETYPE_FTL_BTOC_IDX (AND_SPARE_TYPE_REGION_FTL + 0x1D)
|
||||
#define PAGETYPE_FTL_IDX (AND_SPARE_TYPE_REGION_FTL + 0x1E)
|
||||
#define PAGETYPE_FTL_CXT (AND_SPARE_TYPE_REGION_FTL + 0x1F)
|
||||
|
||||
|
||||
// FTLFlags defines--
|
||||
#define PFLAG_UECC 0x01 // uECC state for data pages (moved by GC and thus re-encoded)
|
||||
|
||||
|
||||
// Must be 16 bytes on PPN
|
||||
|
||||
typedef struct {
|
||||
UInt8 PageType;
|
||||
UInt8 FTLFlags;
|
||||
UInt16 weaveLo;
|
||||
UInt32 weaveHi;
|
||||
} PageMeta_Common_t;
|
||||
|
||||
typedef struct {
|
||||
PageMeta_Common_t c;
|
||||
UInt32 __f1;
|
||||
UInt32 __f2;
|
||||
} PageMeta_t;
|
||||
|
||||
typedef struct {
|
||||
PageMeta_Common_t c;
|
||||
UInt32 userSeq;
|
||||
UInt32 lba;
|
||||
} PageMeta_Data_t;
|
||||
|
||||
typedef struct {
|
||||
PageMeta_Common_t c;
|
||||
UInt32 maxWeaveSeqAdd;
|
||||
UInt32 __rfu__;
|
||||
} PageMeta_BTOC_t;
|
||||
|
||||
typedef struct {
|
||||
PageMeta_Common_t c;
|
||||
UInt16 __rfu__;
|
||||
UInt16 lbaAdd;
|
||||
UInt32 baseLba;
|
||||
} PageMeta_Idx_t;
|
||||
|
||||
typedef struct {
|
||||
PageMeta_Common_t c;
|
||||
UInt32 __rfu1__;
|
||||
UInt32 __rfu2__;
|
||||
} PageMeta_Cxt_t;
|
||||
|
||||
|
||||
typedef UInt64 WeaveSeq_t;
|
||||
|
||||
|
||||
// Setup
|
||||
extern void SetupMeta_Data(PageMeta_t *__meta, UInt32 lba, UInt32 count);
|
||||
extern void SetupMeta_Data_UECC(PageMeta_t *__meta);
|
||||
|
||||
extern void SetupMeta_Index(PageMeta_t *__meta, UInt32 ipn);
|
||||
|
||||
extern void SetupMeta_Data_BTOC(PageMeta_t *__meta);
|
||||
extern void SetupMeta_Index_BTOC(PageMeta_t *__meta);
|
||||
|
||||
extern void SetupMeta_IndexGC(PageMeta_t *__meta, UInt32 count);
|
||||
extern void SetupMeta_DataGC(PageMeta_t *__meta, UInt32 count);
|
||||
|
||||
extern void SetupMeta_Cxt(PageMeta_t *__meta, UInt64 weaveSeq);
|
||||
|
||||
#define META_SET_LBA(meta, foo) do { ((PageMeta_Data_t*)(meta))->lba = (foo); } while (0)
|
||||
#define META_SET_WEAVESEQ(meta) do { (meta)->c.weaveLo = (UInt16)yaFTL.wrState.weaveSeq; (meta)->c.weaveHi = (UInt32)(yaFTL.wrState.weaveSeq >> 16); } while (0)
|
||||
#define META_SET_BTOC_DATA(meta) do { (meta)->c.PageType = PAGETYPE_FTL_BTOC_DATA; } while (0)
|
||||
#define META_SET_IPN_FROM_BTOC(meta, bte) do { ((PageMeta_Idx_t*)(meta))->baseLba = (bte); } while (0)
|
||||
#define BTOC_SET_FROM_IPN(bte, meta) do { (bte) = ((PageMeta_Idx_t*)(meta))->baseLba; } while (0)
|
||||
|
||||
|
||||
// Query
|
||||
#define BTOC_GET_IPN(bte) ((bte) / yaFTL.indexPageRatio)
|
||||
#define META_ARE_FLAGS_FF(meta) ((0xff == (meta)->c.PageType) && (0xff == (meta)->c.FTLFlags))
|
||||
#define META_IS_IDX(meta) (PAGETYPE_FTL_IDX == (meta)->c.PageType)
|
||||
#define META_IS_DATA(meta) (PAGETYPE_FTL_DATA == (meta)->c.PageType)
|
||||
#define META_IS_CXT(meta) (PAGETYPE_FTL_CXT == (meta)->c.PageType)
|
||||
#define META_IS_BTOC_IDX(meta) (PAGETYPE_FTL_BTOC_IDX == (meta)->c.PageType)
|
||||
#define META_IS_BTOC_DATA(meta) (PAGETYPE_FTL_BTOC_DATA == (meta)->c.PageType)
|
||||
#define META_IS_BTOC(meta) ((PAGETYPE_FTL_BTOC_IDX == (meta)->c.PageType) || (PAGETYPE_FTL_BTOC_DATA == ((meta)->c.PageType)))
|
||||
#define META_IS_UECC(meta) ((meta)->c.FTLFlags & PFLAG_UECC)
|
||||
#define META_GET_WEAVESEQ(meta) ((UInt64)(meta)->c.weaveLo | ((UInt64)(meta)->c.weaveHi << 16))
|
||||
#define META_GET_LBA(meta) (((PageMeta_Data_t*)(meta))->lba)
|
||||
#define META_GET_IPN(meta) (((PageMeta_Idx_t*)(meta))->baseLba / yaFTL.indexPageRatio)
|
||||
#define META_GET_IPNRAW(meta) (((PageMeta_Idx_t*)(meta))->baseLba)
|
||||
#define META_GET_ALL_FLAGS(meta) (((UInt32)((meta)->c.FTLFlags) << 8) | (UInt32)((meta)->c.PageType))
|
||||
|
||||
|
||||
|
||||
#endif // __YAFTL_META_PPN_H__
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
|
||||
#include "yaFTL_whoami.h"
|
||||
#include "yaFTL_meta_raw.h"
|
||||
#include "WMRConfig.h"
|
||||
#include "yaFTLTypes.h"
|
||||
|
||||
extern yaFTL_t yaFTL;
|
||||
|
||||
|
||||
void SetupMeta_Data(PageMeta_t *meta, UInt32 lba, UInt32 count)
|
||||
{
|
||||
if (yaFTL.wrState.lastBlock != yaFTL.wrState.data.block)
|
||||
{
|
||||
yaFTL.wrState.weaveSeq++;
|
||||
yaFTL.wrState.lastBlock = yaFTL.wrState.data.block;
|
||||
}
|
||||
|
||||
while (count--)
|
||||
{
|
||||
meta->FTLFlags = PAGETYPE_FTL_DATA;
|
||||
meta->lba = lba;
|
||||
meta->weaveSeq = (UInt32)yaFTL.wrState.weaveSeq;
|
||||
|
||||
// Next
|
||||
lba++;
|
||||
meta++;
|
||||
}
|
||||
}
|
||||
|
||||
void SetupMeta_Data_UECC(PageMeta_t *meta)
|
||||
{
|
||||
meta->FTLFlags |= PFLAG_UECC;
|
||||
}
|
||||
|
||||
void SetupMeta_Index(PageMeta_t *meta, UInt32 ipn)
|
||||
{
|
||||
if (yaFTL.wrState.lastBlock != yaFTL.wrState.index.block)
|
||||
{
|
||||
yaFTL.wrState.weaveSeq++;
|
||||
yaFTL.wrState.lastBlock = yaFTL.wrState.index.block;
|
||||
}
|
||||
|
||||
meta->FTLFlags = PAGETYPE_FTL_IDX;
|
||||
meta->lba = ipn;
|
||||
meta->weaveSeq = (UInt32)yaFTL.wrState.weaveSeq;
|
||||
}
|
||||
|
||||
void SetupMeta_Data_BTOC(PageMeta_t *meta)
|
||||
{
|
||||
meta->FTLFlags = PFLAG_BTOC;
|
||||
meta->weaveSeq = (UInt32)yaFTL.wrState.data.minWeaveSeq;
|
||||
}
|
||||
|
||||
void SetupMeta_Index_BTOC(PageMeta_t *meta)
|
||||
{
|
||||
meta->FTLFlags = PAGETYPE_FTL_IDX | PFLAG_BTOC;
|
||||
meta->weaveSeq = (UInt32)yaFTL.wrState.index.minWeaveSeq;
|
||||
}
|
||||
|
||||
void SetupMeta_IndexGC(PageMeta_t *meta, UInt32 count)
|
||||
{
|
||||
if (yaFTL.wrState.lastBlock != yaFTL.wrState.index.block)
|
||||
{
|
||||
yaFTL.wrState.weaveSeq++;
|
||||
yaFTL.wrState.lastBlock = yaFTL.wrState.index.block;
|
||||
}
|
||||
|
||||
while (count--)
|
||||
{
|
||||
meta->FTLFlags = PAGETYPE_FTL_IDX;
|
||||
meta->weaveSeq = (UInt32)yaFTL.wrState.weaveSeq;
|
||||
|
||||
// Next
|
||||
meta++;
|
||||
}
|
||||
}
|
||||
|
||||
void SetupMeta_DataGC(PageMeta_t *meta, UInt32 count)
|
||||
{
|
||||
if (yaFTL.wrState.lastBlock != yaFTL.wrState.data.block)
|
||||
{
|
||||
yaFTL.wrState.weaveSeq++;
|
||||
yaFTL.wrState.lastBlock = yaFTL.wrState.data.block;
|
||||
}
|
||||
|
||||
while (count--)
|
||||
{
|
||||
// Or in the page type and clear all but uECC flag
|
||||
meta->FTLFlags = (meta->FTLFlags & PFLAG_UECC) | PAGETYPE_FTL_DATA;
|
||||
meta->weaveSeq = (UInt32)yaFTL.wrState.weaveSeq;
|
||||
|
||||
// Next
|
||||
meta++;
|
||||
}
|
||||
}
|
||||
|
||||
void SetupMeta_Cxt(PageMeta_t *meta, UInt64 weaveSeq)
|
||||
{
|
||||
yaFTL.wrState.weaveSeq++;
|
||||
|
||||
meta->FTLFlags = PAGETYPE_FTL_CXT;
|
||||
meta->weaveSeq = (UInt32)yaFTL.wrState.weaveSeq;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#ifndef __YAFTL_META_RAW_H__
|
||||
#define __YAFTL_META_RAW_H__
|
||||
|
||||
#include "yaFTL_whoami.h"
|
||||
#include "WMROAM.h"
|
||||
|
||||
// Page FTLFlags
|
||||
#define PAGETYPE_FTL_IDX 0x04
|
||||
#define PAGETYPE_FTL_DATA 0x10
|
||||
#define PAGETYPE_FTL_CXT 0x20
|
||||
#define PFLAG_BTOC 0x08
|
||||
#define PFLAG_UECC 0x40 // uECC state (moved by GC and thus re-encoded)
|
||||
|
||||
// Must be 12 bytes on raw
|
||||
typedef struct
|
||||
{
|
||||
UInt32 lba; // formerly known as logicalPageNo
|
||||
UInt32 weaveSeq; // formerly known as allocationNo
|
||||
UInt8 __DEPRECATED_seqNo;
|
||||
UInt8 FTLFlags;
|
||||
UInt16 __pad;
|
||||
} PageMeta_t;
|
||||
|
||||
typedef UInt32 WeaveSeq_t;
|
||||
|
||||
|
||||
extern void SetupMeta_Data(PageMeta_t *meta, UInt32 lba, UInt32 count);
|
||||
extern void SetupMeta_Data_UECC(PageMeta_t *meta);
|
||||
|
||||
extern void SetupMeta_Index(PageMeta_t *meta, UInt32 ipn);
|
||||
|
||||
extern void SetupMeta_Data_BTOC(PageMeta_t *meta);
|
||||
extern void SetupMeta_Index_BTOC(PageMeta_t *meta);
|
||||
|
||||
extern void SetupMeta_IndexGC(PageMeta_t *meta, UInt32 count);
|
||||
extern void SetupMeta_DataGC(PageMeta_t *meta, UInt32 count);
|
||||
|
||||
extern void SetupMeta_Cxt(PageMeta_t *meta, UInt64 weaveSeq);
|
||||
|
||||
#define META_SET_LBA(meta, foo) do { (meta)->lba = (foo); } while (0)
|
||||
#define META_SET_WEAVESEQ(meta) do { \
|
||||
if (yaFTL.wrState.lastBlock != yaFTL.wrState.index.block) \
|
||||
{ \
|
||||
yaFTL.wrState.weaveSeq++; \
|
||||
yaFTL.wrState.lastBlock = yaFTL.wrState.index.block; \
|
||||
} \
|
||||
(meta)->weaveSeq = (UInt32)yaFTL.wrState.weaveSeq; \
|
||||
} while(0)
|
||||
#define META_SET_BTOC_DATA(meta) do { (meta)->FTLFlags = PFLAG_BTOC; } while (0)
|
||||
#define META_SET_IPN_FROM_BTOC(meta, bte) do { (meta)->lba = (bte); } while (0)
|
||||
#define BTOC_SET_FROM_IPN(bte, meta) do { (bte) = (meta)->lba; } while (0)
|
||||
|
||||
|
||||
// Query
|
||||
#define BTOC_GET_IPN(bte) (bte)
|
||||
#define META_ARE_FLAGS_FF(meta) (0xff == (meta)->FTLFlags)
|
||||
#define META_IS_IDX(meta) ((meta)->FTLFlags & PAGETYPE_FTL_IDX)
|
||||
#define META_IS_DATA(meta) ((meta)->FTLFlags & PAGETYPE_FTL_DATA)
|
||||
#define META_IS_CXT(meta) ((meta)->FTLFlags & PAGETYPE_FTL_CXT)
|
||||
#define META_IS_BTOC_IDX(meta) (((meta)->FTLFlags & PAGETYPE_FTL_IDX) && ((meta)->FTLFlags & PFLAG_BTOC))
|
||||
#define META_IS_BTOC_DATA(meta) (!((meta)->FTLFlags & PAGETYPE_FTL_IDX) && ((meta)->FTLFlags & PFLAG_BTOC))
|
||||
#define META_IS_BTOC(meta) ((meta)->FTLFlags & PFLAG_BTOC)
|
||||
#define META_IS_UECC(meta) ((meta)->FTLFlags & PFLAG_UECC)
|
||||
#define META_GET_WEAVESEQ(meta) ((meta)->weaveSeq)
|
||||
#define META_GET_LBA(meta) ((meta)->lba)
|
||||
#define META_GET_IPN(meta) ((meta)->lba)
|
||||
#define META_GET_IPNRAW(meta) ((meta)->lba)
|
||||
#define META_GET_ALL_FLAGS(meta) ((UInt32)((meta)->FTLFlags))
|
||||
|
||||
|
||||
|
||||
#endif // __YAFTL_META_RAW_H__
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2010 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#ifndef __YAFTL_WHOAMI_H__
|
||||
#define __YAFTL_WHOAMI_H__
|
||||
|
||||
#define NAND_RAW 1
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,399 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* COMPONENT : Rainbow */
|
||||
/* MODULE : Virtual Flash Layer */
|
||||
/* NAME : VFL Buffer Management */
|
||||
/* FILE : VFLBuffer.c */
|
||||
/* PURPOSE : This file contains routines for managing buffers which */
|
||||
/* whimory uses. */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* COPYRIGHT 2003-2005 SAMSUNG ELECTRONICS CO., LTD. */
|
||||
/* ALL RIGHTS RESERVED */
|
||||
/* */
|
||||
/* Permission is hereby granted to licensees of Samsung Electronics */
|
||||
/* Co., Ltd. products to use or abstract this computer program for the */
|
||||
/* sole purpose of implementing a product based on Samsung */
|
||||
/* Electronics Co., Ltd. products. No other rights to reproduce, use, */
|
||||
/* or disseminate this computer program, whether in part or in whole, */
|
||||
/* are granted. */
|
||||
/* */
|
||||
/* Samsung Electronics Co., Ltd. makes no representation or warranties */
|
||||
/* with respect to the performance of this computer program, and */
|
||||
/* specifically disclaims any responsibility for any damages, */
|
||||
/* special or consequential, connected with the use of this program. */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* REVISION HISTORY */
|
||||
/* */
|
||||
/* 13-JUL-2005 [Jaesung Jung] : separate from vfl.c & reorganize code */
|
||||
/* 06-SEP-2005 [Jaesung Jung] : fix from code inspection */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Header file inclusions */
|
||||
/*****************************************************************************/
|
||||
#include "WMRConfig.h"
|
||||
#include "ANDTypes.h"
|
||||
#include "WMROAM.h"
|
||||
#include "VFLBuffer.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Debug Print #defines */
|
||||
/*****************************************************************************/
|
||||
#if (defined(AND_SIMULATOR) && AND_SIMULATOR)
|
||||
#define BUF_ERR_PRINT(x) { WMR_RTL_PRINT(x); WMR_PANIC(); }
|
||||
#else
|
||||
#define BUF_ERR_PRINT(x) WMR_RTL_PRINT(x)
|
||||
#endif
|
||||
#define BUF_RTL_PRINT(x) WMR_RTL_PRINT(x)
|
||||
|
||||
#if defined (BUF_LOG_MSG_ON)
|
||||
#define BUF_LOG_PRINT(x) WMR_DBG_PRINT(x)
|
||||
#else
|
||||
#define BUF_LOG_PRINT(x)
|
||||
#endif
|
||||
|
||||
#if defined (BUF_INF_MSG_ON)
|
||||
#define BUF_INF_PRINT(x) WMR_DBG_PRINT(x)
|
||||
#else
|
||||
#define BUF_INF_PRINT(x)
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Static variables definitions */
|
||||
/*****************************************************************************/
|
||||
BUFCxt *pstBufferCxt = NULL;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt16 wBytesPerPage; /* bytes per page (main) */
|
||||
UInt16 wBytesPerPageMeta;
|
||||
} VFLBufferDeviceInfo;
|
||||
static VFLBufferDeviceInfo stVFLBufferDeviceInfo;
|
||||
|
||||
#define BYTES_PER_PAGE (stVFLBufferDeviceInfo.wBytesPerPage)
|
||||
#define BYTES_PER_PAGE_META (stVFLBufferDeviceInfo.wBytesPerPageMeta)
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code Implementation */
|
||||
/*****************************************************************************/
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* NAME */
|
||||
/* BUF_Init */
|
||||
/* DESCRIPTION */
|
||||
/* This function initializes the buffer manager & the buffer pool. */
|
||||
/* PARAMETERS */
|
||||
/* none */
|
||||
/* RETURN VALUES */
|
||||
/* BUF_SUCCESS */
|
||||
/* BUF_Init is completed. */
|
||||
/* BUF_CRITICAL_ERROR */
|
||||
/* BUF_Init is failed */
|
||||
/* NOTES */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
Int32
|
||||
BUF_Init(UInt16 wDataBytesPerPage, UInt16 wMetaBytesPerPage, UInt16 wNumberOfBuffers)
|
||||
{
|
||||
UInt32 nBufIdx;
|
||||
Buffer *pBufIdx;
|
||||
|
||||
if (pstBufferCxt != NULL)
|
||||
{
|
||||
return BUF_SUCCESS;
|
||||
}
|
||||
|
||||
BUF_LOG_PRINT((TEXT("[BUF: IN] ++BUF_Init(void)\n")));
|
||||
|
||||
stVFLBufferDeviceInfo.wBytesPerPage = wDataBytesPerPage;
|
||||
stVFLBufferDeviceInfo.wBytesPerPageMeta = wMetaBytesPerPage;
|
||||
|
||||
/* Initialize buffer context */
|
||||
pstBufferCxt = (BUFCxt *)WMR_MALLOC(sizeof(BUFCxt));
|
||||
pstBufferCxt->dwNumOfBuffers = wNumberOfBuffers;
|
||||
if (pstBufferCxt == NULL)
|
||||
{
|
||||
BUF_ERR_PRINT((TEXT("[BUF:ERR] BUF_Init(void) BUFCxt Init Failure\n")));
|
||||
BUF_Close();
|
||||
return BUF_CRITICAL_ERROR;
|
||||
}
|
||||
|
||||
/* Initialize buffer list */
|
||||
pstBufferCxt->pBufferList = (Buffer *)WMR_MALLOC(sizeof(Buffer) * pstBufferCxt->dwNumOfBuffers);
|
||||
|
||||
if (pstBufferCxt->pBufferList == NULL)
|
||||
{
|
||||
BUF_ERR_PRINT((TEXT("[BUF:ERR] BUF_Init(void) BUFCxt->pBufferList Init Failure\n")));
|
||||
BUF_Close();
|
||||
return BUF_CRITICAL_ERROR;
|
||||
}
|
||||
|
||||
pBufIdx = pstBufferCxt->pBufferList;
|
||||
|
||||
for (nBufIdx = 0; nBufIdx < pstBufferCxt->dwNumOfBuffers; nBufIdx++)
|
||||
{
|
||||
#ifdef WMR_USE_FAKE_POINTERS
|
||||
/*
|
||||
* In order to make it possible to DMA to the contents of the buffer pool,
|
||||
* OAM_Init has already allocated an IOBufferMemoryDescriptor of the appropriate
|
||||
* size. Thus, we just have to index into it...
|
||||
*/
|
||||
extern UInt8 *_OAM_PageBufferPoolBase;
|
||||
extern UInt8 *_OAM_SpareBufferPoolBase;
|
||||
pBufIdx->pData = _OAM_PageBufferPoolBase + (nBufIdx * BYTES_PER_PAGE);
|
||||
pBufIdx->pSpare = _OAM_SpareBufferPoolBase + (nBufIdx * BYTES_PER_PAGE_META);
|
||||
#else /* !WMR_USE_FAKE_POINTERS */
|
||||
pBufIdx->pData = (UInt8 *)WMR_MALLOC(BYTES_PER_PAGE + BYTES_PER_PAGE_META);
|
||||
pBufIdx->pSpare = pBufIdx->pData + BYTES_PER_PAGE;
|
||||
#endif
|
||||
|
||||
if (pBufIdx->pData == NULL || pBufIdx->pSpare == NULL)
|
||||
{
|
||||
BUF_ERR_PRINT((TEXT("[BUF:ERR] BUF_Init(void) pBufIdx->pData, pBufIdx->pSpare Init Failure\n")));
|
||||
BUF_Close();
|
||||
return BUF_CRITICAL_ERROR;
|
||||
}
|
||||
|
||||
pBufIdx->pDataBak = pBufIdx->pData;
|
||||
#ifdef WMR_USE_FAKE_POINTERS /* need to save the spare pointer as it is not contiguous */
|
||||
pBufIdx->pSpareBak = pBufIdx->pSpare;
|
||||
#endif
|
||||
pBufIdx->eStatus = BUF_FREE;
|
||||
|
||||
pBufIdx++;
|
||||
}
|
||||
|
||||
pstBufferCxt->nFreeBuffers = pstBufferCxt->dwNumOfBuffers;
|
||||
|
||||
BUF_LOG_PRINT((TEXT("[BUF:OUT] --BUF_Init(void) nRe=0x%x\n"), BUF_SUCCESS));
|
||||
return BUF_SUCCESS;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* NAME */
|
||||
/* BUF_Get */
|
||||
/* DESCRIPTION */
|
||||
/* This function returns a new free buffer. */
|
||||
/* if there is not a free buffer, this function calls the sync function */
|
||||
/* and generates a new free buffer. */
|
||||
/* PARAMETERS */
|
||||
/* eType [IN] */
|
||||
/* buffer type */
|
||||
/* RETURN VALUES */
|
||||
/* Buffer */
|
||||
/* BUF_Get is completed. */
|
||||
/* NULL */
|
||||
/* BUF_Get is failed. */
|
||||
/* NOTES */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
Buffer *
|
||||
BUF_Get(BUFType eType)
|
||||
{
|
||||
UInt32 nBufIdx;
|
||||
Buffer *pBufRet;
|
||||
|
||||
BUF_LOG_PRINT((TEXT("[BUF: IN] ++BUF_Get(eType = %d)\n"), eType));
|
||||
|
||||
/* Check buffer context was initialized */
|
||||
if (pstBufferCxt == NULL)
|
||||
{
|
||||
BUF_ERR_PRINT((TEXT("[BUF:ERR] BUF_Get(eType = %d) Buffer manager is not initialized\n"), eType));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* NirW - from the checked in M1 code - Check buffer context was not written over */
|
||||
if (pstBufferCxt->pBufferList == NULL)
|
||||
{
|
||||
BUF_ERR_PRINT((TEXT("[BUF:ERR] BUF_Get(eType = %d) Buffer pointer was overwritten!\n"), eType));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pstBufferCxt->nFreeBuffers == 0)
|
||||
{
|
||||
BUF_ERR_PRINT((TEXT("[BUF:ERR] BUF_Get(eType = %d) No free buffer\n"), eType));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Find a free buffer from the buffer pool. */
|
||||
pBufRet = pstBufferCxt->pBufferList;
|
||||
|
||||
for (nBufIdx = 0; nBufIdx < pstBufferCxt->dwNumOfBuffers; nBufIdx++, pBufRet++)
|
||||
{
|
||||
if (pBufRet->eStatus == BUF_FREE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (nBufIdx >= pstBufferCxt->dwNumOfBuffers)
|
||||
{
|
||||
BUF_ERR_PRINT((TEXT("[BUF:ERR] BUF_Get(eType = %d) Can't find a free buffer\n"), eType));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check the buffer type */
|
||||
if (eType == BUF_SPARE_ONLY)
|
||||
{
|
||||
pBufRet->pData = NULL;
|
||||
}
|
||||
else if (eType == BUF_MAIN_ONLY)
|
||||
{
|
||||
pBufRet->pSpare = NULL;
|
||||
}
|
||||
|
||||
/* Initialize the spare buffer */
|
||||
if (eType != BUF_MAIN_ONLY)
|
||||
{
|
||||
WMR_MEMSET(pBufRet->pSpare, 0xFF, BYTES_PER_PAGE_META);
|
||||
}
|
||||
|
||||
/* Change the buffer status & bitmap */
|
||||
pBufRet->eStatus = BUF_ALLOCATED;
|
||||
/* pBufRet->nBitmap = 0; */
|
||||
|
||||
/* Decrease the number of free buffers */
|
||||
pstBufferCxt->nFreeBuffers--;
|
||||
|
||||
BUF_LOG_PRINT((TEXT("[BUF:OUT] --BUF_Get(eType = %d)\n"), eType));
|
||||
|
||||
return pBufRet;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* NAME */
|
||||
/* BUF_Release */
|
||||
/* DESCRIPTION */
|
||||
/* This function releases the buffer to the buffer pool. */
|
||||
/* PARAMETERS */
|
||||
/* pBuf [IN] */
|
||||
/* buffer pointer */
|
||||
/* RETURN VALUES */
|
||||
/* none */
|
||||
/* NOTES */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void
|
||||
BUF_Release(Buffer *pBuf)
|
||||
{
|
||||
UInt16 wIdx;
|
||||
|
||||
BUF_LOG_PRINT((TEXT("[BUF: IN] ++BUF_Release(pBuf = %x)\n"), pBuf));
|
||||
|
||||
if (pBuf == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//WMR_ASSERT((pBuf - pstBufferCxt->pBufferList) >= 0 &&
|
||||
// (pBuf - pstBufferCxt->pBufferList) < pstBufferCxt->dwNumOfBuffers);
|
||||
for (wIdx = 0; wIdx < pstBufferCxt->dwNumOfBuffers; wIdx++)
|
||||
{
|
||||
if (pBuf == &pstBufferCxt->pBufferList[wIdx])
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
WMR_ASSERT(wIdx < pstBufferCxt->dwNumOfBuffers);
|
||||
/* NirW */
|
||||
if (pBuf->eStatus == BUF_FREE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
WMR_ASSERT(pBuf->eStatus == BUF_ALLOCATED);
|
||||
|
||||
/* Reinitialize the buffer */
|
||||
pBuf->pData = pBuf->pDataBak;
|
||||
#ifdef WMR_USE_FAKE_POINTERS /* need to restore non-adjacent spare pointer */
|
||||
pBuf->pSpare = pBuf->pSpareBak;
|
||||
#else
|
||||
pBuf->pSpare = pBuf->pDataBak + BYTES_PER_PAGE;
|
||||
#endif
|
||||
|
||||
pBuf->eStatus = BUF_FREE;
|
||||
|
||||
pstBufferCxt->nFreeBuffers++;
|
||||
|
||||
WMR_ASSERT(pstBufferCxt->nFreeBuffers <= pstBufferCxt->dwNumOfBuffers);
|
||||
|
||||
BUF_LOG_PRINT((TEXT("[BUF:OUT] --BUF_Release(pBuf = %x)\n"), pBuf));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* NAME */
|
||||
/* BUF_Close */
|
||||
/* DESCRIPTION */
|
||||
/* This function releases buffer manager context. */
|
||||
/* PARAMETERS */
|
||||
/* none */
|
||||
/* RETURN VALUES */
|
||||
/* none */
|
||||
/* NOTES */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
void
|
||||
BUF_Close(void)
|
||||
{
|
||||
UInt32 nBufIdx;
|
||||
Buffer *pBufIdx;
|
||||
|
||||
BUF_LOG_PRINT((TEXT("[BUF: IN] ++BUF_Close(void)\n")));
|
||||
|
||||
if (pstBufferCxt != NULL)
|
||||
{
|
||||
if (pstBufferCxt->pBufferList != NULL)
|
||||
{
|
||||
pBufIdx = pstBufferCxt->pBufferList;
|
||||
|
||||
for (nBufIdx = 0; nBufIdx < pstBufferCxt->dwNumOfBuffers; nBufIdx++)
|
||||
{
|
||||
#ifndef WMR_USE_FAKE_POINTERS
|
||||
WMR_FREE(pBufIdx->pDataBak, (BYTES_PER_PAGE + BYTES_PER_PAGE_META));
|
||||
#endif
|
||||
pBufIdx->pData = NULL;
|
||||
pBufIdx->pSpare = NULL;
|
||||
|
||||
pBufIdx++;
|
||||
}
|
||||
|
||||
WMR_FREE(pstBufferCxt->pBufferList, (sizeof(Buffer) * pstBufferCxt->dwNumOfBuffers));
|
||||
|
||||
pstBufferCxt->pBufferList = NULL;
|
||||
}
|
||||
|
||||
WMR_FREE(pstBufferCxt, sizeof(BUFCxt));
|
||||
|
||||
pstBufferCxt = NULL;
|
||||
}
|
||||
|
||||
BUF_LOG_PRINT((TEXT("[BUF:OUT] --BUF_Close(void)\n")));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
BUF_ReleaseAllBuffers(void)
|
||||
{
|
||||
UInt32 nBufIdx;
|
||||
Buffer *pBufIdx;
|
||||
|
||||
pBufIdx = pstBufferCxt->pBufferList;
|
||||
|
||||
for (nBufIdx = 0; nBufIdx < pstBufferCxt->dwNumOfBuffers; nBufIdx++)
|
||||
{
|
||||
BUF_Release(pBufIdx);
|
||||
pBufIdx++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* COMPONENT : Rainbow */
|
||||
/* MODULE : Virtual Flash Layer */
|
||||
/* NAME : VFL Buffer Management */
|
||||
/* FILE : VFLBuffer.h */
|
||||
/* PURPOSE : This file contains routines for managing buffers which */
|
||||
/* whimory uses. */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* COPYRIGHT 2003-2005 SAMSUNG ELECTRONICS CO., LTD. */
|
||||
/* ALL RIGHTS RESERVED */
|
||||
/* */
|
||||
/* Permission is hereby granted to licensees of Samsung Electronics */
|
||||
/* Co., Ltd. products to use or abstract this computer program for the */
|
||||
/* sole purpose of implementing a product based on Samsung */
|
||||
/* Electronics Co., Ltd. products. No other rights to reproduce, use, */
|
||||
/* or disseminate this computer program, whether in part or in whole, */
|
||||
/* are granted. */
|
||||
/* */
|
||||
/* Samsung Electronics Co., Ltd. makes no representation or warranties */
|
||||
/* with respect to the performance of this computer program, and */
|
||||
/* specifically disclaims any responsibility for any damages, */
|
||||
/* special or consequential, connected with the use of this program. */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* REVISION HISTORY */
|
||||
/* */
|
||||
/* 13-JUL-2005 [Jaesung Jung] : separate from vfl.c & reorganize code */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef _VFL_BUFFER_H_
|
||||
#define _VFL_BUFFER_H_
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Return value of BUF_XXX() */
|
||||
/*****************************************************************************/
|
||||
#define BUF_SUCCESS ANDErrorCodeOk
|
||||
#define BUF_CRITICAL_ERROR ANDErrorCodeAllocFailErr
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Buffer state enum definition */
|
||||
/*****************************************************************************/
|
||||
typedef enum
|
||||
{
|
||||
BUF_FREE = 0x10000000, /* the buffer is free */
|
||||
BUF_ALLOCATED = 0x10000001, /* the buffer is allocated to some layer */
|
||||
} BUFStat;
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Buffer type enum & macro definition */
|
||||
/*****************************************************************************/
|
||||
typedef enum
|
||||
{
|
||||
BUF_MAIN_AND_SPARE = 0x10000000, /* to get a buffer which has main & spare*/
|
||||
BUF_MAIN_ONLY = 0x10000001, /* to get a buffer which has main only */
|
||||
BUF_SPARE_ONLY = 0x10000002 /* to get a buffer which has spare only */
|
||||
} BUFType;
|
||||
|
||||
#define BITMAP_FULL_PAGE ((1 << SECTORS_PER_PAGE) - 1)
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Buffer structure definition */
|
||||
/*****************************************************************************/
|
||||
typedef struct Buf
|
||||
{
|
||||
UInt8 *pData; /* buffer area for main area */
|
||||
UInt8 *pSpare; /* buffer area for spare area */
|
||||
// UInt32 nBitmap; /* valid sector bitmap for pData */
|
||||
BUFStat eStatus; /* the status of buffer */
|
||||
UInt8 *pDataBak; /* the original pointer of data buffer */
|
||||
#ifdef WMR_USE_FAKE_POINTERS /* data and spare buffers are not adjacent */
|
||||
UInt8 *pSpareBak; /* the original pointer of spare buffer */
|
||||
#endif
|
||||
} Buffer;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Buffer *pBufferList; /* the list of all the buffers */
|
||||
UInt32 nFreeBuffers; /* the count of free buffers */
|
||||
UInt32 dwNumOfBuffers;
|
||||
} BUFCxt;
|
||||
|
||||
/*****************************************************************************/
|
||||
/* exported function prototype of VFL buffer manager */
|
||||
/*****************************************************************************/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
Int32 BUF_Init(UInt16 wDataBytesPerPage, UInt16 wMetaBytesPerPage, UInt16 wNumberOfBuffers);
|
||||
Buffer *BUF_Get(BUFType eType);
|
||||
void BUF_Release(Buffer *pBuf);
|
||||
void BUF_Close(void);
|
||||
void BUF_ReleaseAllBuffers(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* _VFL_BUFFER_H_ */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,233 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* COMPONENT : Rainbow */
|
||||
/* MODULE : Virtual Flash Layer */
|
||||
/* NAME : VFL types definition header */
|
||||
/* FILE : VFLTypes.h */
|
||||
/* PURPOSE : This header defines Data types which are shared */
|
||||
/* by all VFL submodules */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* COPYRIGHT 2003-2005 SAMSUNG ELECTRONICS CO., LTD. */
|
||||
/* ALL RIGHTS RESERVED */
|
||||
/* */
|
||||
/* Permission is hereby granted to licensees of Samsung Electronics */
|
||||
/* Co., Ltd. products to use or abstract this computer program for the */
|
||||
/* sole purpose of implementing a product based on Samsung */
|
||||
/* Electronics Co., Ltd. products. No other rights to reproduce, use, */
|
||||
/* or disseminate this computer program, whether in part or in whole, */
|
||||
/* are granted. */
|
||||
/* */
|
||||
/* Samsung Electronics Co., Ltd. makes no representation or warranties */
|
||||
/* with respect to the performance of this computer program, and */
|
||||
/* specifically disclaims any responsibility for any damages, */
|
||||
/* special or consequential, connected with the use of this program. */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* REVISION HISTORY */
|
||||
/* */
|
||||
/* 04-AUG-2003 [HM Jung] : first writing */
|
||||
/* 14-JUL-2005 [Jaesung Jung] : reorganize code */
|
||||
/* 06-SEP-2005 [Jaesung Jung] : fix from code inspection */
|
||||
/* 24-JAN-2006 [Yangsup Lee ] : support un-pair bad block management */
|
||||
/* 31-MAR-2006 [Yangsup Lee ] : support ftl meta block wear leveling */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
#ifndef _VFL_TYPES_H_
|
||||
#define _VFL_TYPES_H_
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt16 wPagesPerBlock; /* the count of pages per block */
|
||||
UInt16 wPagesPerSuBlk; /* the count of pages per virtual block */
|
||||
UInt32 dwPagesTotal; /* the total number of pages */
|
||||
UInt16 wUserSuBlkTotal; /* the total number of data virtual block */
|
||||
UInt32 dwUserPagesTotal; /* the total number of data sector */
|
||||
|
||||
UInt16 wBlocksPerBank; /* the count of blocks per bank */
|
||||
|
||||
UInt16 wBytesPerPage; /* bytes per page (main) */
|
||||
|
||||
UInt32 dwValidMetaPerLogicalPage;
|
||||
UInt32 dwTotalMetaPerLogicalPage;
|
||||
UInt32 dwLogicalPageSize;
|
||||
|
||||
UInt16 wNumOfBank; /* the number of banks */
|
||||
UInt8 bRefreshThreshold; // number of bit flips beyond which we want to rewrite the page
|
||||
|
||||
// taken from WMRLayout
|
||||
UInt16 dwVFLAreaStart; /* the block number where VFL area starts */
|
||||
UInt16 wVFLAreaSize; /* the block number of VFL area size */
|
||||
UInt16 wReservedSecSize; /* the size of reserved section */
|
||||
|
||||
UInt16 wFTLCxtStart; /* FTL cxt section start */
|
||||
UInt16 wFreeSecStart; /* free section start */
|
||||
} VFLWMRDeviceInfo;
|
||||
|
||||
#define PAGES_PER_BLOCK (stVFLDeviceInfo.wPagesPerBlock)
|
||||
#define PAGES_PER_SUBLK (stVFLDeviceInfo.wPagesPerSuBlk)
|
||||
#define PAGES_TOTAL (stVFLDeviceInfo.dwPagesTotal)
|
||||
#define USER_SUBLKS_TOTAL (stVFLDeviceInfo.wUserSuBlkTotal)
|
||||
#define USER_PAGES_TOTAL (stVFLDeviceInfo.dwUserPagesTotal)
|
||||
#define BLOCKS_PER_BANK (stVFLDeviceInfo.wBlocksPerBank)
|
||||
#define BYTES_PER_PAGE (stVFLDeviceInfo.wBytesPerPage)
|
||||
#define BANKS_TOTAL (stVFLDeviceInfo.wNumOfBank)
|
||||
|
||||
#define VFL_AREA_START (stVFLDeviceInfo.dwVFLAreaStart)
|
||||
#define VFL_AREA_SIZE (stVFLDeviceInfo.wVFLAreaSize)
|
||||
|
||||
#define VFL_INFO_SECTION_START (VFL_AREA_START)
|
||||
#define VFL_INFO_SECTION_SIZE (4)
|
||||
#define RESERVED_SECTION_SIZE (stVFLDeviceInfo.wReservedSecSize)
|
||||
|
||||
#define FTL_CXT_SECTION_START (stVFLDeviceInfo.wFTLCxtStart)
|
||||
#define FTL_INFO_SECTION_SIZE FTL_CXT_SECTION_SIZE
|
||||
#define LOG_SECTION_SIZE (FREE_SECTION_SIZE - FREE_LIST_SIZE)
|
||||
#define FREE_SECTION_SIZE (20)
|
||||
#define FREE_LIST_SIZE (3)
|
||||
|
||||
#define FTL_AREA_START (VFL_AREA_START + VFL_AREA_SIZE)
|
||||
#define FTL_AREA_SIZE (FTL_INFO_SECTION_SIZE + FREE_SECTION_SIZE + USER_SUBLKS_TOTAL)
|
||||
#define FIL_ECC_REFRESH_TRESHOLD (stVFLDeviceInfo.bRefreshThreshold)
|
||||
|
||||
#define BBT_SIZE_PER_BANK ((BLOCKS_PER_BANK / 8) + (BLOCKS_PER_BANK % 8 ? 1 : 0))
|
||||
#define BYTES_PER_SECTOR (512)
|
||||
#define WMR_MAX_DEVICE (8) /* the maximum number of banks */
|
||||
|
||||
/*****************************************************************************/
|
||||
/* VFL constant definitions */
|
||||
/*****************************************************************************/
|
||||
#define INIT_BAD_MARK (0) /* bad mark position in spare */
|
||||
#define INIT_BAD_MARK_SECOND (64) /* bad mark position in spare */
|
||||
/* (2 plane programming) */
|
||||
|
||||
#define BAD_MARK_COMPRESS_SIZE (8)
|
||||
|
||||
/*****************************************************************************/
|
||||
/* VFL context status(confirm) mark definition */
|
||||
/*****************************************************************************/
|
||||
#define PAGE_INCOMPLETE (0xFF)
|
||||
#define PAGE_VALID (0x00)
|
||||
|
||||
#define VFL_BAD_MARK_INFO_TABLE_SIZE (WMR_MAX_VB / 8 / BAD_MARK_COMPRESS_SIZE)
|
||||
/*****************************************************************************/
|
||||
/* Data structure for storing the VFL context definition */
|
||||
/*****************************************************************************/
|
||||
/* NOTICE !!! */
|
||||
/* this structure is used directly to load VFL context by WMR_MEMCPY*/
|
||||
/* so the byte pad of this structure must be 0 */
|
||||
typedef struct
|
||||
{
|
||||
UInt32 dwGlobalCxtAge; /* age for FTL meta information search */
|
||||
UInt16 aFTLCxtVbn[FTL_CXT_SECTION_SIZE]; /* page address (FTL virtual addressing space) of FTL Cxt */
|
||||
UInt16 wPadding; /* padding (align to UInt32) */
|
||||
|
||||
UInt32 dwCxtAge; /* context age 0xFFFFFFFF --> 0x0 - NirW - check if the variable is used anywhere - what is the difference between dwGlobalCxtAge and dwCxtAge */
|
||||
UInt16 wCxtLocation; /* current context block location (Physical) */
|
||||
UInt16 wNextCxtPOffset; /* current context page offset information */
|
||||
|
||||
/* this data is used for summary */
|
||||
UInt16 wNumOfInitBadBlk; /* the number of initial bad blocks - used for VFL format */
|
||||
UInt16 wNumOfWriteFail; /* the number of write fail - currently not used */
|
||||
UInt16 wNumOfEraseFail; /* the number of erase fail - updated (++) every time there is an erase failure that causes remapping of a block */
|
||||
|
||||
/* bad blocks management table & good block pointer */
|
||||
UInt16 wBadMapTableMaxIdx; /* index to the last bad block updated in the aBadMapTable */
|
||||
UInt16 wReservedSecStart; /* index of the first physical block that will be used as reserved in the bank (the first block after VFL Cxt Info) */
|
||||
UInt16 wReservedSecSize; /* number of physical blocks that are available as reserved (some might be bad blocks) */
|
||||
UInt16 aBadMapTable[WMR_MAX_RESERVED_SIZE]; /* remapping table of bad blocks - the UInt 16 value set here is the virtual block (vfl address space) that is being replaced */
|
||||
UInt8 aBadMark[VFL_BAD_MARK_INFO_TABLE_SIZE]; /* compact bitmap presentation of bad block (initial and accumulated) */
|
||||
|
||||
/* bad blocks management table within VFL info area */
|
||||
UInt16 awInfoBlk[VFL_INFO_SECTION_SIZE]; /* physical block addresses where Cxt information is stored */
|
||||
UInt16 wBadMapTableScrubIdx; /* Index for the scrub list (start from the top of aBadMapTable */
|
||||
} VFLCxt;
|
||||
|
||||
/* VFLMeta size is 2048 bytes(4 sector) */
|
||||
#define VFL_META_VERSION 0x00000001
|
||||
typedef struct
|
||||
{
|
||||
VFLCxt stVFLCxt;
|
||||
UInt8 abReserved[((BYTES_PER_SECTOR - 3) * sizeof(UInt32)) - sizeof(VFLCxt)];
|
||||
UInt32 dwVersion;
|
||||
UInt32 dwCheckSum;
|
||||
UInt32 dwXorSum;
|
||||
} VFLMeta;
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data structure for VFL context spare area */
|
||||
/*****************************************************************************/
|
||||
/* spare layout for SLC & MLC */
|
||||
typedef struct
|
||||
{
|
||||
UInt32 dwCxtAge; /* context age 0xFFFFFFFF --> 0x0 */
|
||||
UInt32 dwReserved; /* reserved */
|
||||
UInt8 cStatusMark; /* status (confirm) mark - currently not used for anything */
|
||||
UInt8 bSpareType; /* spare type */
|
||||
/* reserved for main ECC */
|
||||
} VFLSpare;
|
||||
|
||||
#define VFL_SPARE_TYPE_CXT 0x80
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Asynchronous operation management structure & enum definition */
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Device Information Structures and defines */
|
||||
|
||||
#define VFL_META_STRUCT_VERSION 0x00000004 /* changed Oct 6th 2006 */
|
||||
#define VFL_BBT_STRUCT_VERSION 0x00000004 /* changed Oct 6th 2006 */
|
||||
|
||||
#define BBT_BLOCK_SIGNATURE (UInt8*)"DEVICEINFOBBT\0\0\0"
|
||||
#define BBT_BLOCK_SIGNATURE_SIZE 16
|
||||
|
||||
#define UNIQUE_INFO_BLOCK_SIGNATURE (UInt8*)"DEVICEUNIQUEINFO"
|
||||
#define UNIQUE_INFO_BLOCK_SIGNATURE_SIZE 16
|
||||
|
||||
#define NAND_DRIVER_SIGN_BLOCK_SIGNATURE (UInt8*)"NANDDRIVERSIGN\0\0"
|
||||
#define NAND_DRIVER_SIGN_BLOCK_SIGNATURE_SIZE 16
|
||||
|
||||
#define NUMBER_OF_SPECIAL_BLOCKS (5) /* discuss what is the right value here with Mike Smith */
|
||||
|
||||
#define BBT_SIZE_PER_BANK ((BLOCKS_PER_BANK / 8) + (BLOCKS_PER_BANK % 8 ? 1 : 0))
|
||||
|
||||
#define WMR_NUM_OF_ERASE_TRIALS_FOR_INDEX_BLOCKS (4)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt8 abSignature[16];
|
||||
UInt32 dwVersion;
|
||||
UInt32 adwSpecialBlocks[8];
|
||||
UInt32 dwBBTSize;
|
||||
} BBTInfoHeaderStruct;
|
||||
|
||||
#ifdef AND_COLLECT_STATISTICS
|
||||
typedef struct
|
||||
{
|
||||
UInt64 ddwPagesWrittenCnt;
|
||||
UInt64 ddwPagesReadCnt;
|
||||
UInt64 ddwBlocksErasedCnt;
|
||||
UInt64 ddwSingleWriteCallCnt;
|
||||
UInt64 ddwSingleReadCallCnt;
|
||||
UInt64 ddwSequetialReadCallCnt;
|
||||
UInt64 ddwScatteredReadCallCnt;
|
||||
UInt64 ddwMultipleWriteCallCnt;
|
||||
UInt64 ddwEraseCallCnt;
|
||||
} VFLStatistics;
|
||||
|
||||
#define VFL_STATISTICS_DESCREPTION { \
|
||||
"ddwPagesWrittenCnt", \
|
||||
"ddwPagesReadCnt", \
|
||||
"ddwBlocksErasedCnt", \
|
||||
"ddwSingleWriteCallCnt", \
|
||||
"ddwSingleReadCallCnt", \
|
||||
"ddwSequetialReadCallCnt", \
|
||||
"ddwScatteredReadCallCnt", \
|
||||
"ddwMultipleWriteCallCnt", \
|
||||
"ddwEraseCallCnt", \
|
||||
}
|
||||
#endif /* AND_COLLECT_STATISTICS */
|
||||
|
||||
#endif /* _VFL_TYPES_H_ */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,218 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* COMPONENT : Rainbow */
|
||||
/* MODULE : Virtual Flash Layer */
|
||||
/* NAME : VFL types definition header */
|
||||
/* FILE : VFLTypes.h */
|
||||
/* PURPOSE : This header defines Data types which are shared */
|
||||
/* by all VFL submodules */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* COPYRIGHT 2003-2005 SAMSUNG ELECTRONICS CO., LTD. */
|
||||
/* ALL RIGHTS RESERVED */
|
||||
/* */
|
||||
/* Permission is hereby granted to licensees of Samsung Electronics */
|
||||
/* Co., Ltd. products to use or abstract this computer program for the */
|
||||
/* sole purpose of implementing a product based on Samsung */
|
||||
/* Electronics Co., Ltd. products. No other rights to reproduce, use, */
|
||||
/* or disseminate this computer program, whether in part or in whole, */
|
||||
/* are granted. */
|
||||
/* */
|
||||
/* Samsung Electronics Co., Ltd. makes no representation or warranties */
|
||||
/* with respect to the performance of this computer program, and */
|
||||
/* specifically disclaims any responsibility for any damages, */
|
||||
/* special or consequential, connected with the use of this program. */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* REVISION HISTORY */
|
||||
/* */
|
||||
/* 04-AUG-2003 [HM Jung] : first writing */
|
||||
/* 14-JUL-2005 [Jaesung Jung] : reorganize code */
|
||||
/* 06-SEP-2005 [Jaesung Jung] : fix from code inspection */
|
||||
/* 24-JAN-2006 [Yangsup Lee ] : support un-pair bad block management */
|
||||
/* 31-MAR-2006 [Yangsup Lee ] : support ftl meta block wear leveling */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
#ifndef _VFL_TYPES_H_
|
||||
#define _VFL_TYPES_H_
|
||||
|
||||
#include "WMRConfig.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt16 wPagesPerBlock; /* the count of pages per block */
|
||||
UInt8 bRefreshThreshold; // number of bit flips beyond which we want to rewrite the page
|
||||
UInt16 wNumOfCEs;
|
||||
UInt16 wBlocksPerCS; /* the count of blocks per CS */
|
||||
UInt16 wBlocksPerBank;
|
||||
UInt16 wBlocksPerDie;
|
||||
UInt16 wDieStride;
|
||||
UInt16 wBlockStride;
|
||||
UInt16 wUserBlocksPerCS;
|
||||
|
||||
// Info generated by CalcGlobal
|
||||
UInt16 wPagesPerSuBlk; /* the count of pages per virtual block */
|
||||
UInt16 wBytesPerPage; /* bytes per page (main) */
|
||||
|
||||
UInt32 dwValidMetaPerLogicalPage;
|
||||
UInt32 dwTotalMetaPerLogicalPage;
|
||||
UInt32 dwLogicalPageSize;
|
||||
|
||||
UInt16 wNumOfBank; /* the number of banks */
|
||||
UInt16 wNumOfBanksPerCS;
|
||||
|
||||
UInt16 dwVFLAreaStart; /* the block number where VFL area starts */
|
||||
|
||||
} VSVFLWMRDeviceInfo;
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Global variables redefinitions (WMRLayout) */
|
||||
/*****************************************************************************/
|
||||
#define VFL_AREA_START (stVSVFLWMRDeviceInfo.dwVFLAreaStart)
|
||||
#define VFL_FIRST_BLK_TO_SEARCH_CXT VFL_AREA_START
|
||||
#define VFL_LAST_BLK_TO_SEARCH_CXT (VFL_AREA_START + 199)
|
||||
|
||||
#define VFL_INFO_SECTION_START (VFL_AREA_START)
|
||||
#define VFL_INFO_SECTION_SIZE (4)
|
||||
|
||||
#define FIL_ECC_REFRESH_TRESHOLD (stVSVFLWMRDeviceInfo.bRefreshThreshold)
|
||||
|
||||
#define VFL_RESERVED_SECTION_SIZE_CS (BLOCKS_PER_CS - (_GetNumOfSuBlks() * BANKS_PER_CS))
|
||||
#define VFL_RESERVED_SECTION_SIZE_BANK (BLOCKS_PER_BANK - _GetNumOfSuBlks())
|
||||
|
||||
#define BBT_SIZE_PER_CS ((BLOCKS_PER_CS / 8) + (BLOCKS_PER_CS % 8 ? 1 : 0))
|
||||
#if (defined(VFL_SMALL_ADDRESS_BUFFER) && VFL_SMALL_ADDRESS_BUFFER)
|
||||
#define VSVFL_MAX_BANKS (4)
|
||||
#else
|
||||
#define VSVFL_MAX_PHYS_CS (16)
|
||||
#define VSVFL_MAX_BANKS (VSVFL_MAX_PHYS_CS * AND_MAX_BANKS_PER_CS) /* the total maximum number of bank */
|
||||
#endif
|
||||
#define VFL_SCRUB_LIST_SIZE (20)
|
||||
#define FTL_FORMAT_STRUCT_SIZE (16) // packed
|
||||
/*****************************************************************************/
|
||||
/* VFL context status(confirm) mark definition */
|
||||
/*****************************************************************************/
|
||||
#define PAGE_VALID (0x00)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt8 abNewFTLType[4];
|
||||
UInt8 abNewNumOfFTLSuBlk[2];
|
||||
UInt8 abReserved[9];
|
||||
UInt8 bFormatFTL; // 0 - false, 1 - format...
|
||||
} FTLFormatType;
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data structure for storing the VFL context definition */
|
||||
/*****************************************************************************/
|
||||
/* NOTICE !!! */
|
||||
/* this structure is used directly to load VFL context by WMR_MEMCPY*/
|
||||
/* so the byte pad of this structure must be 0 */
|
||||
typedef struct
|
||||
{
|
||||
UInt32 dwGlobalCxtAge; /* age for FTL meta information search */
|
||||
UInt32 dwCxtAge; /* context age 0xFFFFFFFF --> 0x0 */
|
||||
UInt32 dwFTLType; /* FTL identifier */
|
||||
|
||||
UInt16 wCxtLocation; /* current context block location (Physical) */
|
||||
UInt16 wNextCxtPOffset; /* current context page offset information */
|
||||
|
||||
/* this data is used for summary */
|
||||
UInt16 wNumOfInitBadBlk; /* the number of initial bad blocks - used for VFL format */
|
||||
UInt16 wNumOfWriteFail; /* the number of failed write operations*/
|
||||
UInt16 wNumOfEraseFail; /* the number of failed erase operations */
|
||||
|
||||
/* bad blocks management table & good block pointer */
|
||||
UInt16 awReplacementIdx[AND_MAX_BANKS_PER_CS]; /* index to the last bad block updated in the awBadMapTable per bank
|
||||
(some might be bad blocks) the array is divided to banks */
|
||||
UInt16 awBadMapTable[WMR_MAX_RESERVED_SIZE]; /* remapping table of bad blocks - the UInt 16 value set here is the virtual block (vfl address space) that is being replaced */
|
||||
|
||||
/* bad blocks management table within VFL info area */
|
||||
UInt16 awInfoBlk[VFL_INFO_SECTION_SIZE]; /* physical block addresses where FTL Cxt information is stored */
|
||||
|
||||
UInt16 wNumOfFTLSuBlk; /* the number of super blocks allocated for the FTL - default id to give all to FTL */
|
||||
UInt16 wNumOfVFLSuBlk; /* the total number of available super blocks */
|
||||
UInt16 awFTLCxtVbn[FTL_CXT_SECTION_SIZE]; /* page address (FTL virtual addressing space) of FTL Cxt */
|
||||
UInt16 wScrubIdx; /* Index for the scrub list */
|
||||
UInt16 awScrubList[VFL_SCRUB_LIST_SIZE]; /* scrub list */
|
||||
UInt8 abFTLFormat[FTL_FORMAT_STRUCT_SIZE];
|
||||
UInt8 abVSFormtType[4];
|
||||
} VFLCxt;
|
||||
|
||||
/* VFLMeta size is 2048 bytes(4 sector) */
|
||||
#define VFL_META_VERSION 0x00000002
|
||||
typedef struct _VFLMeta
|
||||
{
|
||||
VFLCxt stVFLCxt;
|
||||
UInt8 abReserved[2048 - ((3 * sizeof(UInt32)) + sizeof(VFLCxt))];
|
||||
UInt32 dwVersion;
|
||||
UInt32 dwCheckSum;
|
||||
UInt32 dwXorSum;
|
||||
} VFLMeta;
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data structure for VFL context spare area */
|
||||
/*****************************************************************************/
|
||||
/* spare layout for SLC & MLC */
|
||||
typedef struct
|
||||
{
|
||||
UInt32 dwCxtAge; /* context age 0xFFFFFFFF --> 0x0 */
|
||||
UInt32 dwReserved; /* reserved */
|
||||
UInt8 cStatusMark; /* status (confirm) mark - currently not used for anything */
|
||||
UInt8 bSpareType; /* spare type */
|
||||
/* reserved for main ECC */
|
||||
} VFLSpare;
|
||||
|
||||
#define VFL_SPARE_TYPE_CXT 0x80
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Asynchronous operation management structure & enum definition */
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Device Information Structures and defines */
|
||||
|
||||
#define BBT_SIZE_PER_CS ((BLOCKS_PER_CS / 8) + (BLOCKS_PER_CS % 8 ? 1 : 0))
|
||||
|
||||
#define WMR_NUM_OF_ERASE_TRIALS_FOR_INDEX_BLOCKS (4)
|
||||
|
||||
#define VFL_BLOCK_INDEX_MASK (0xFFFF)
|
||||
#define VFL_INVALID_INFO_INDEX (0xFFFF)
|
||||
#define VFL_BAD_MAP_TABLE_AVAILABLE_MARK (0xFFF0)
|
||||
#define VFL_BAD_MAP_TABLE_STRESS_FAIL_MARK (0xFFFD)
|
||||
#define VFL_BAD_MAP_TABLE_BORROW_MARK (0xFFFE)
|
||||
#define VFL_BAD_MAP_TABLE_BAD_MARK (0xFFFF)
|
||||
|
||||
#ifdef AND_COLLECT_STATISTICS
|
||||
typedef struct
|
||||
{
|
||||
UInt64 ddwPagesWrittenCnt;
|
||||
UInt64 ddwPagesReadCnt;
|
||||
UInt64 ddwBlocksErasedCnt;
|
||||
UInt64 ddwSingleWriteCallCnt;
|
||||
UInt64 ddwSingleReadCallCnt;
|
||||
UInt64 ddwSequetialReadCallCnt;
|
||||
UInt64 ddwScatteredReadCallCnt;
|
||||
UInt64 ddwMultipleWriteCallCnt;
|
||||
UInt64 ddwEraseCallCnt;
|
||||
UInt64 ddwEraseTimeoutFailCnt;
|
||||
UInt64 ddwBurnInCode;
|
||||
} VFLStatistics;
|
||||
|
||||
#define VFL_STATISTICS_DESCREPTION { \
|
||||
"ddwPagesWrittenCnt", \
|
||||
"ddwPagesReadCnt", \
|
||||
"ddwBlocksErasedCnt", \
|
||||
"ddwSingleWriteCallCnt", \
|
||||
"ddwSingleReadCallCnt", \
|
||||
"ddwSequetialReadCallCnt", \
|
||||
"ddwScatteredReadCallCnt", \
|
||||
"ddwMultipleWriteCallCnt", \
|
||||
"ddwEraseCallCnt", \
|
||||
"ddwEraseTimeoutFailCnt", \
|
||||
"ddwBurnInCode", \
|
||||
}
|
||||
#endif /* AND_COLLECT_STATISTICS */
|
||||
|
||||
#endif /* _VFL_TYPES_H_ */
|
||||
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#include "ANDTypes.h"
|
||||
#include "WMROAM.h"
|
||||
#include "VFLBuffer.h"
|
||||
#include "FPart.h"
|
||||
#include "FPartTypes.h"
|
||||
#include "WMRConfig.h"
|
||||
#include "WMRExam.h"
|
||||
#include "ANDStats.h"
|
||||
|
||||
static VFLFunctions *stVflFunctions;
|
||||
static FTLFunctions *stFtlFunctions;
|
||||
|
||||
typedef BOOL32 (*GetStructFunc)(UInt32 dwStructType, void * pvoidStructBuffer, UInt32 * pdwStructSize);
|
||||
|
||||
typedef struct {
|
||||
UInt32 dwStructLayer;
|
||||
UInt32 dwStructType;
|
||||
UInt32 dwStructVersion;
|
||||
} ExportStructParameters;
|
||||
|
||||
|
||||
static ExportStructParameters astrStructsToExport[] =
|
||||
{
|
||||
// header (must be first)
|
||||
{ 0, AND_STRUCT_WMR_EXPORT_ALL, AND_EXPORT_STRUCTURE_VERSION},
|
||||
|
||||
// WMR Version (FTL & VFL types)
|
||||
{AND_STRUCT_LAYER_WMR, AND_STRUCT_WMR_VERSION, 0},
|
||||
|
||||
// VFL_type
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_GET_TYPE, 0},
|
||||
|
||||
// FTL_type ( FTL/yaFTL)
|
||||
{AND_STRUCT_LAYER_FTL, AND_STRUCT_FTL_GET_TYPE, 0},
|
||||
|
||||
// All VFL Meta
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_VFLMETA | 0, 0},
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_VFLMETA | 1, 0},
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_VFLMETA | 2, 0},
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_VFLMETA | 3, 0},
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_VFLMETA | 4, 0},
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_VFLMETA | 5, 0},
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_VFLMETA | 6, 0},
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_VFLMETA | 7, 0},
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_VFLMETA | 8, 0},
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_VFLMETA | 9, 0},
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_VFLMETA | 10, 0},
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_VFLMETA | 11, 0},
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_VFLMETA | 12, 0},
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_VFLMETA | 13, 0},
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_VFLMETA | 14, 0},
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_VFLMETA | 15, 0},
|
||||
|
||||
//FTL geometry
|
||||
{AND_STRUCT_LAYER_FTL,AND_STRUCT_FTL_GET_FTL_DEVICEINFO, 0},
|
||||
|
||||
// FTL
|
||||
{AND_STRUCT_LAYER_FTL, AND_STRUCT_FTL_FTLCXT, 0},
|
||||
|
||||
// FTL counters
|
||||
{AND_STRUCT_LAYER_FTL, AND_STRUCT_FTL_GET_FTL_EC_BINS, 1},
|
||||
{AND_STRUCT_LAYER_FTL, AND_STRUCT_FTL_GET_FTL_RC_BINS, 1},
|
||||
|
||||
// FTL - Stat
|
||||
{AND_STRUCT_LAYER_FTL, AND_STRUCT_FTL_STATISTICS, 0},
|
||||
|
||||
// VFL - Stat
|
||||
{AND_STRUCT_LAYER_VFL, AND_STRUCT_VFL_STATISTICS, 0},
|
||||
|
||||
// FIL - Device Info
|
||||
{AND_STRUCT_LAYER_FIL, AND_STRUCT_FIL_DEVICE_INFO, 0},
|
||||
|
||||
// FIL - Stat
|
||||
{AND_STRUCT_LAYER_FIL, AND_STRUCT_FIL_STATISTICS, 0},
|
||||
|
||||
// footer (must be last)
|
||||
{0, AND_STRUCT_WMR_EXPORT_ALL_END, AND_EXPORT_STRUCTURE_VERSION},
|
||||
|
||||
};
|
||||
|
||||
#define AND_DUMP_DEBUG (0)
|
||||
|
||||
#if AND_DUMP_DEBUG
|
||||
#define DUMP_VAR(variable) WMR_PRINT(ALWAYS, "%s : %u\n", #variable, (UInt32)(variable))
|
||||
|
||||
|
||||
static void
|
||||
hexdump(UInt8 *bytes, int count)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < count; i += 16) {
|
||||
kprintf("%04x:", i);
|
||||
for (j = 0; (j < 16) && ((i + j) < count); j++)
|
||||
kprintf(" %02.2x", *bytes++);
|
||||
kprintf("\n");
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define DUMP_VAR(variable)
|
||||
#endif //AND_DUMP_DEBUG
|
||||
|
||||
|
||||
|
||||
static GetStructFunc _translateStructLayer (UInt32 dwStructLayer)
|
||||
{
|
||||
switch (dwStructLayer)
|
||||
{
|
||||
case AND_STRUCT_LAYER_FTL:
|
||||
return stFtlFunctions->GetStruct;
|
||||
case AND_STRUCT_LAYER_VFL:
|
||||
return stVflFunctions->GetStruct;
|
||||
case AND_STRUCT_LAYER_FIL:
|
||||
return FIL_GetStruct;
|
||||
case AND_STRUCT_LAYER_WMR:
|
||||
return WMRGetStruct;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static BOOL32 _appendStructToBuffer(void *pvoidExportBuffer,
|
||||
UInt32 *pdwBufferSize,
|
||||
UInt32 dwStructLayer,
|
||||
UInt32 dwStructType,
|
||||
UInt32 dwStructVersion)
|
||||
{
|
||||
UInt32 dwDataSize;
|
||||
BOOL32 boolResult;
|
||||
GetStructFunc fGetStruct = _translateStructLayer(dwStructLayer);
|
||||
UInt8 *cursor = (UInt8*) pvoidExportBuffer;
|
||||
|
||||
|
||||
DUMP_VAR(pvoidExportBuffer);
|
||||
if (pdwBufferSize)
|
||||
{
|
||||
DUMP_VAR(*pdwBufferSize);
|
||||
}
|
||||
DUMP_VAR(dwStructLayer);
|
||||
DUMP_VAR(dwStructType);
|
||||
DUMP_VAR(dwStructVersion);
|
||||
|
||||
if (fGetStruct)
|
||||
{
|
||||
if (pvoidExportBuffer)
|
||||
{
|
||||
// leave room for the struct header
|
||||
cursor += sizeof(ANDExportStruct);
|
||||
}
|
||||
dwDataSize = pdwBufferSize ? (*pdwBufferSize - sizeof(ANDExportStruct)) : 0;
|
||||
boolResult = fGetStruct(dwStructType, cursor, &dwDataSize);
|
||||
DUMP_VAR(dwDataSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
// for header and footer
|
||||
boolResult = TRUE32;
|
||||
dwDataSize = 0;
|
||||
}
|
||||
|
||||
if (boolResult)
|
||||
{
|
||||
#if AND_DUMP_DEBUG
|
||||
if (pvoidExportBuffer)
|
||||
{
|
||||
hexdump(pvoidExportBuffer, dwDataSize);
|
||||
}
|
||||
#endif
|
||||
if (pdwBufferSize)
|
||||
{
|
||||
*pdwBufferSize = dwDataSize + sizeof(ANDExportStruct);
|
||||
}
|
||||
|
||||
if (pvoidExportBuffer)
|
||||
{
|
||||
ANDExportStruct strExport;
|
||||
|
||||
strExport.dwStructID = dwStructType;
|
||||
strExport.dwStructureVersion = dwStructVersion;
|
||||
strExport.dwDataSize = dwDataSize;
|
||||
strExport.dwIndex = 0; // What is this?
|
||||
|
||||
WMR_MEMCPY(pvoidExportBuffer, &strExport, sizeof(ANDExportStruct));
|
||||
}
|
||||
}
|
||||
else if (pdwBufferSize)
|
||||
{
|
||||
*pdwBufferSize = 0;
|
||||
}
|
||||
|
||||
DUMP_VAR(boolResult);
|
||||
return boolResult;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define SUB_MIN_ZERO(minuend, subtrahend) (((minuend) > (subtrahend)) ? ((minuend) - (subtrahend)) : 0)
|
||||
|
||||
BOOL32 ANDExportAllStructs(void * pvoidDataBuffer, UInt32 * pdwDataSize)
|
||||
{
|
||||
UInt32 idx;
|
||||
ExportStructParameters *nextStruct;
|
||||
const UInt32 dwNumStructures = sizeof(astrStructsToExport) / sizeof(astrStructsToExport[0]);
|
||||
const UInt32 dwBufferSize = pdwDataSize ? *pdwDataSize : 0;
|
||||
UInt8 *cursor = (UInt8*) pvoidDataBuffer;
|
||||
UInt32 dwBufferRead = 0;
|
||||
UInt32 dwTmpStructSize;
|
||||
|
||||
if (!pdwDataSize)
|
||||
{
|
||||
return FALSE32;
|
||||
}
|
||||
|
||||
// Update globals
|
||||
stVflFunctions = WMR_GetVFL();
|
||||
stFtlFunctions = WMR_GetFTL();
|
||||
|
||||
nextStruct = &astrStructsToExport[0];
|
||||
for (idx = 0; idx < dwNumStructures; ++idx)
|
||||
{
|
||||
dwTmpStructSize = SUB_MIN_ZERO(dwBufferSize, dwBufferRead);
|
||||
_appendStructToBuffer(cursor,
|
||||
&dwTmpStructSize,
|
||||
nextStruct->dwStructLayer,
|
||||
nextStruct->dwStructType,
|
||||
nextStruct->dwStructVersion);
|
||||
nextStruct++;
|
||||
if (cursor)
|
||||
{
|
||||
cursor += dwTmpStructSize;
|
||||
}
|
||||
dwBufferRead += dwTmpStructSize;
|
||||
}
|
||||
|
||||
if (pdwDataSize)
|
||||
{
|
||||
*pdwDataSize = dwBufferRead;
|
||||
}
|
||||
|
||||
// pdwDataSize tells the whole story, always pass
|
||||
return TRUE32;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) 2008-2009 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#include "WMRTypes.h"
|
||||
|
||||
#ifndef _ANDSTATS_H_
|
||||
#define _ANDSTATS_H_
|
||||
|
||||
BOOL32 ANDExportAllStructs(void * pvoidDataBuffer, UInt32 * pdwDataSize);
|
||||
|
||||
#endif //_ANDSTATS_H_
|
||||
|
||||
|
||||
@@ -0,0 +1,1000 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* COMPONENT : Rainbow */
|
||||
/* MODULE : Example */
|
||||
/* NAME : Example */
|
||||
/* FILE : WMRExam.c */
|
||||
/* PURPOSE : the example for whimory initialization */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* COPYRIGHT 2003-2005 SAMSUNG ELECTRONICS CO., LTD. */
|
||||
/* ALL RIGHTS RESERVED */
|
||||
/* */
|
||||
/* Permission is hereby granted to licensees of Samsung Electronics */
|
||||
/* Co., Ltd. products to use or abstract this computer program for the */
|
||||
/* sole purpose of implementing a product based on Samsung */
|
||||
/* Electronics Co., Ltd. products. No other rights to reproduce, use, */
|
||||
/* or disseminate this computer program, whether in part or in whole, */
|
||||
/* are granted. */
|
||||
/* */
|
||||
/* Samsung Electronics Co., Ltd. makes no representation or warranties */
|
||||
/* with respect to the performance of this computer program, and */
|
||||
/* specifically disclaims any responsibility for any damages, */
|
||||
/* special or consequential, connected with the use of this program. */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* REVISION HISTORY */
|
||||
/* */
|
||||
/* 12-SEP-2005 [Jaesung Jung] : first writing */
|
||||
/* 15-MAR-2006 [Yangsup Lee ] : bad block detection bug fix */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
#if (!defined(AND_FPART_ONLY) || !AND_FPART_ONLY)
|
||||
#include "ANDTypes.h"
|
||||
#include "WMRConfig.h"
|
||||
#include "WMROAM.h"
|
||||
#include "VFLBuffer.h"
|
||||
#include "FPart.h"
|
||||
#include "VFL.h"
|
||||
#include "FTL.h"
|
||||
#include "FIL.h"
|
||||
#include "WMRExam.h"
|
||||
#include "FPartTypes.h"
|
||||
#include "ANDStats.h"
|
||||
#include "WMRTest.h"
|
||||
#else
|
||||
#include "ANDTypes.h"
|
||||
#include "WMRConfig.h"
|
||||
#include "WMROAM.h"
|
||||
#include "VFLBuffer.h"
|
||||
#include "FPart.h"
|
||||
#include "FIL.h"
|
||||
#include "WMRExam.h"
|
||||
#include "FPartTypes.h"
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Debug Print #defines */
|
||||
/*****************************************************************************/
|
||||
#define EXAM_INF_MSG_ON
|
||||
|
||||
#define EXAM_ERR_PRINT(x) WMR_RTL_PRINT(x)
|
||||
#define EXAM_RTL_PRINT(x) WMR_RTL_PRINT(x)
|
||||
|
||||
#if defined (EXAM_LOG_MSG_ON)
|
||||
#define EXAM_LOG_PRINT(x) WMR_DBG_PRINT(x)
|
||||
#else
|
||||
#define EXAM_LOG_PRINT(x)
|
||||
#endif
|
||||
|
||||
#if defined (EXAM_INF_MSG_ON)
|
||||
#define EXAM_INF_PRINT(x) WMR_DBG_PRINT(x)
|
||||
#else
|
||||
#define EXAM_INF_PRINT(x)
|
||||
#endif
|
||||
|
||||
#if (!defined(AND_FPART_ONLY) || !AND_FPART_ONLY)
|
||||
static ANDDriverSignature g_flashANDSignature; // Keep what was read from flash
|
||||
static ANDDriverSignature g_scratchANDSignature; // For writing new signatures
|
||||
static VFLFunctions stVflFunctions;
|
||||
static FTLFunctions stFtlFunctions;
|
||||
#endif
|
||||
static FPartFunctions stFPartFunctions;
|
||||
static BOOL32 boolFPartInitialized = FALSE32;
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code Implementation */
|
||||
/*****************************************************************************/
|
||||
|
||||
static Int32 _initFPart(UInt32 dwFormatType, UInt32 dwBootAreaSize)
|
||||
{
|
||||
UInt32 dwFPartOptions = 0;
|
||||
Int32 nRet;
|
||||
|
||||
if (FALSE32 == boolFPartInitialized)
|
||||
{
|
||||
WMR_MEMSET(&stFPartFunctions, 0, sizeof(FPartFunctions));
|
||||
FPart_Register(&stFPartFunctions);
|
||||
dwFPartOptions = 0;
|
||||
dwFPartOptions |= (dwFormatType & WMR_INIT_USE_DEV_UNIQUE_INFO) ? FPART_INIT_OPTION_DEV_UNIQUE : 0;
|
||||
dwFPartOptions |= (dwFormatType & WMR_INIT_USE_DIAG_CTRL_INFO) ? FPART_INIT_OPTION_DIAG_CTRL : 0;
|
||||
nRet = stFPartFunctions.Init(FIL_GetFuncTbl(), dwFPartOptions);
|
||||
if (nRet != TRUE32)
|
||||
{
|
||||
return WMR_CRITICAL_ERROR;
|
||||
}
|
||||
boolFPartInitialized = TRUE32;
|
||||
}
|
||||
return WMR_SUCCESS;
|
||||
}
|
||||
|
||||
Int32
|
||||
WMR_PreInit(UInt32 dwFormatType, UInt32 dwBootAreaSize)
|
||||
{
|
||||
Int32 nRet;
|
||||
|
||||
OAM_Init();
|
||||
|
||||
nRet = FIL_Init();
|
||||
if (nRet != FIL_SUCCESS)
|
||||
{
|
||||
return WMR_CRITICAL_ERROR;
|
||||
}
|
||||
if (0 == FIL_GetFuncTbl()->GetDeviceInfo(AND_DEVINFO_NUM_OF_CS))
|
||||
{
|
||||
EXAM_RTL_PRINT((TEXT("[FTL:MSG] No NAND attached\n")));
|
||||
return WMR_CRITICAL_ERROR;
|
||||
}
|
||||
|
||||
nRet = BUF_Init((UInt16)FIL_GetFuncTbl()->GetDeviceInfo(AND_DEVINFO_BYTES_PER_PAGE),
|
||||
BYTES_PER_METADATA_RAW,
|
||||
WMR_NUM_BUFFERS);
|
||||
if (nRet != BUF_SUCCESS)
|
||||
{
|
||||
return WMR_CRITICAL_ERROR;
|
||||
}
|
||||
|
||||
nRet = _initFPart(dwFormatType, dwBootAreaSize);
|
||||
if (nRet != WMR_SUCCESS)
|
||||
{
|
||||
return WMR_CRITICAL_ERROR;
|
||||
}
|
||||
|
||||
return WMR_SUCCESS;
|
||||
}
|
||||
|
||||
FPartFunctions * WMR_GetFPart(void)
|
||||
{
|
||||
return &stFPartFunctions;
|
||||
}
|
||||
|
||||
#if (!defined(AND_FPART_ONLY) || !AND_FPART_ONLY)
|
||||
|
||||
static BOOL32 _isSignatureCompatible(ANDDriverSignature *pstSignature)
|
||||
{
|
||||
const UInt8 bPlatform = WMR_SIGNATURE_PLATFORM(pstSignature->dwMainSignature);
|
||||
const UInt8 bLayout = WMR_SIGNATURE_LAYOUT(pstSignature->dwMainSignature);
|
||||
const UInt8 bVFLType = WMR_SIGNATURE_VFL(pstSignature->dwMainSignature);
|
||||
const UInt32 dw2ndId = WMR_SIGNATURE_FORMATTING_VERSION(pstSignature->dw2ndId);
|
||||
if ( WMR_PLATFORM_DARWIN != bPlatform)
|
||||
{
|
||||
return FALSE32;
|
||||
}
|
||||
|
||||
if ( (WMR_LAYOUT_SIMPLE != bLayout) && (WMR_LAYOUT_VS != bLayout) )
|
||||
{
|
||||
return FALSE32;
|
||||
}
|
||||
|
||||
if ( (WMR_M68_VFL != bVFLType) && (WMR_VSVFL != bVFLType) )
|
||||
{
|
||||
return FALSE32;
|
||||
}
|
||||
|
||||
// Only VS layout supports 2ndID field
|
||||
if ((WMR_LAYOUT_VS == bLayout) && (dw2ndId > WMR_FORMATTING_VERSION))
|
||||
{
|
||||
return FALSE32;
|
||||
}
|
||||
|
||||
return TRUE32;
|
||||
}
|
||||
|
||||
static BOOL32 _selectVFL(BOOL32 boolSignatureFound,
|
||||
BOOL32 boolAllowVSVFL,
|
||||
BOOL32 boolSignInBlockZero,
|
||||
ANDDriverSignature * pOldANDDriverSignature,
|
||||
ANDDriverSignature * pNewANDDriverSignature)
|
||||
{
|
||||
// decide what VFL to use
|
||||
if (((boolSignatureFound == TRUE32) &&
|
||||
WMR_SIGNATURE_VFL(pOldANDDriverSignature->dwMainSignature) == WMR_VSVFL)
|
||||
#ifndef AND_READONLY
|
||||
|| ((boolSignatureFound == FALSE32) && (boolAllowVSVFL == TRUE32))
|
||||
#endif
|
||||
)
|
||||
|
||||
{
|
||||
VSVFL_Register(&stVflFunctions);
|
||||
pNewANDDriverSignature->dwMainSignature = WMR_VSVFL_VS_SIGNATURE;
|
||||
EXAM_RTL_PRINT((TEXT("[FTL:MSG] VSVFL Register [OK]\n")));
|
||||
if (boolSignInBlockZero == FALSE32)
|
||||
{
|
||||
stFPartFunctions.SetSignatureStyle(&stFPartFunctions, SIGNATURE_STYLE_RESERVEDBLOCK_HEADER);
|
||||
}
|
||||
else
|
||||
{
|
||||
EXAM_ERR_PRINT((TEXT("[WMR:ERR] Signature Style RESERVEDBLOCK HEADER has to be used with VSVFL formatting.\n")));
|
||||
return FALSE32;
|
||||
}
|
||||
if ((WMR_SIGNATURE_METADATA(pOldANDDriverSignature->dw2ndId) == WMR_METADATA_WHITENING))
|
||||
{
|
||||
if (FIL_GetFuncTbl()->SetWhiteningMetadataState)
|
||||
{
|
||||
EXAM_RTL_PRINT((TEXT("[WMR:MSG] Metadata whitening is set in NAND signature\n")));
|
||||
FIL_GetFuncTbl()->SetWhiteningMetadataState(TRUE32);
|
||||
}
|
||||
else
|
||||
{
|
||||
EXAM_RTL_PRINT((TEXT("[WMR:ERR] Metadata whitening not supported.\n")));
|
||||
return FALSE32;
|
||||
}
|
||||
}
|
||||
else if (FIL_GetFuncTbl()->SetWhiteningMetadataState)
|
||||
{
|
||||
FIL_GetFuncTbl()->SetWhiteningMetadataState(FALSE32);
|
||||
}
|
||||
}
|
||||
else if (((boolSignatureFound == TRUE32) &&
|
||||
WMR_SIGNATURE_VFL(pOldANDDriverSignature->dwMainSignature) == WMR_M68_VFL)
|
||||
#ifndef AND_READONLY
|
||||
|| ((boolSignatureFound == FALSE32) && (boolAllowVSVFL == FALSE32))
|
||||
#endif
|
||||
)
|
||||
{
|
||||
#if AND_SUPPORT_LEGACY_VFL
|
||||
VFL_Register(&stVflFunctions);
|
||||
pNewANDDriverSignature->dwMainSignature = WMR_VFL_SIGNATURE;
|
||||
EXAM_RTL_PRINT((TEXT("[FTL:MSG] VFL Register [OK]\n")));
|
||||
if (boolSignInBlockZero == TRUE32)
|
||||
{
|
||||
stFPartFunctions.SetSignatureStyle(&stFPartFunctions, SIGNATURE_STYLE_BLOCKZERO_NOHEADER);
|
||||
}
|
||||
else
|
||||
{
|
||||
EXAM_ERR_PRINT((TEXT("[WMR:ERR] Signature Style BLOCKZERO NOHEADER has to be used with VFL formatting.\n")));
|
||||
return FALSE32;
|
||||
}
|
||||
#else
|
||||
EXAM_ERR_PRINT((TEXT("[FTL:ERR] Legacy VFL is not supported - init fail\n")));
|
||||
return FALSE32;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
EXAM_ERR_PRINT((TEXT("[WMR:ERR] No Valid VFL type found main signature 0x%08X\n"),
|
||||
pOldANDDriverSignature->dwMainSignature));
|
||||
return FALSE32;
|
||||
}
|
||||
return TRUE32;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* NAME */
|
||||
/* WMR_Init */
|
||||
/* DESCRIPTION */
|
||||
/* This function inits whimory & format & open. */
|
||||
/* PARAMETERS */
|
||||
/* pTotalScts [OUT] the count of sectors which user can use. */
|
||||
/* RETURN VALUES */
|
||||
/* WMR_SUCCESS */
|
||||
/* FTL_Open is completed */
|
||||
/* WMR_CRITICAL_ERROR */
|
||||
/* FTL_Open is failed */
|
||||
/* WMR_UNRECOVERABLE_ERROR */
|
||||
/* Open failed but we can possibly read syscfg */
|
||||
/* NOTES */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
Int32
|
||||
WMR_Init(UInt32 *pTotalScts, UInt32 * pdwSectorSize, UInt32 * tmpIndexCache, UInt32 dwFormatType, UInt32 dwBootAreaSize)
|
||||
{
|
||||
Int32 nRet;
|
||||
BOOL32 boolSignatureFound = FALSE32;
|
||||
volatile BOOL32 boolProductionFormatVerified = TRUE32;
|
||||
static UInt32 alreadyCalled = 0;
|
||||
BOOL32 boolFTLRegistered = FALSE32;
|
||||
BOOL32 boolSignInBlockZero = (dwFormatType & WMR_INIT_SIGNATURE_IN_BLOCKZERO ? TRUE32 : FALSE32);
|
||||
BOOL32 nandFullRestore = (dwFormatType & WMR_INIT_NAND_RESTORE ? TRUE32 : FALSE32);
|
||||
UInt32 ftlOpenOptions = 0;
|
||||
#if (defined(AND_LOW_POWER_MOUNT) && AND_LOW_POWER_MOUNT)
|
||||
UInt32 dwInitPowerMode = (dwFormatType & WMR_INIT_LOW_POWER_MODE) ? NAND_POWER_MODE_SINGLE_CE : NAND_POWER_MODE_FULL_SPEED;
|
||||
#endif
|
||||
BOOL32 boolAllowVSVFL = (dwFormatType & WMR_INIT_ALLOW_VSVFL ? TRUE32 : FALSE32);
|
||||
BOOL32 boolMetadataWhitening = (dwFormatType & WMR_INIT_METADATA_WHITENING ? TRUE32 : FALSE32);
|
||||
BOOL32 boolMetadataWhiteningCheck = (dwFormatType & WMR_INIT_METADATA_WHITENING_CHECK ? TRUE32 : FALSE32);
|
||||
|
||||
#ifndef AND_READONLY
|
||||
BOOL32 boolStatus;
|
||||
BOOL32 boolProductionFormatCompleted = FALSE32;
|
||||
BOOL32 bFormatAllowed = (dwFormatType & WMR_INIT_ALLOW_FORMAT ? TRUE32 : FALSE32);
|
||||
BOOL32 boolAllowYAFTL = (dwFormatType & WMR_INIT_ALLOW_YAFTL ? TRUE32 : FALSE32);
|
||||
BOOL32 boolRunProductionReformat = (dwFormatType & WMR_INIT_RUN_PRODUCTION_FORMAT ? TRUE32 : FALSE32);
|
||||
BOOL32 boolRunFTLFormat = (dwFormatType & WMR_INIT_RUN_FTL_FORMAT ? TRUE32 : FALSE32);
|
||||
WMR_ASSERT(!(boolRunFTLFormat && boolRunProductionReformat));
|
||||
#endif
|
||||
|
||||
// make sure we init the functions
|
||||
WMR_MEMSET(&stVflFunctions, 0, sizeof(VFLFunctions));
|
||||
WMR_MEMSET(&stFtlFunctions, 0, sizeof(FTLFunctions));
|
||||
|
||||
WMR_MEMSET(&g_flashANDSignature, 0, sizeof(ANDDriverSignature));
|
||||
WMR_MEMSET(&g_scratchANDSignature, 0, sizeof(ANDDriverSignature));
|
||||
|
||||
OAM_Init();
|
||||
|
||||
#ifdef AND_READONLY
|
||||
EXAM_RTL_PRINT((TEXT("[FTL:MSG] Apple NAND Driver (AND) RO\n")));
|
||||
#else
|
||||
EXAM_RTL_PRINT((TEXT("[FTL:MSG] Apple NAND Driver (AND) RW\n")));
|
||||
#endif
|
||||
if (alreadyCalled)
|
||||
{
|
||||
EXAM_ERR_PRINT((TEXT("[WMR:ERR] WMR_Init already called!\n")));
|
||||
}
|
||||
|
||||
alreadyCalled++;
|
||||
|
||||
nRet = FIL_Init();
|
||||
|
||||
if (nRet != FIL_SUCCESS)
|
||||
{
|
||||
return WMR_CRITICAL_ERROR;
|
||||
}
|
||||
#if (defined(AND_LOW_POWER_MOUNT) && AND_LOW_POWER_MOUNT)
|
||||
FIL_SetStruct(AND_STRUCT_FIL_POWER_MODE, &dwInitPowerMode, sizeof(UInt32));
|
||||
#endif
|
||||
|
||||
EXAM_RTL_PRINT((TEXT("[FTL:MSG] FIL_Init [OK]\n")));
|
||||
if (0 == FIL_GetFuncTbl()->GetDeviceInfo(AND_DEVINFO_NUM_OF_CS)) {
|
||||
EXAM_RTL_PRINT((TEXT("[FTL:MSG] No NAND attached\n")));
|
||||
return WMR_CRITICAL_ERROR;
|
||||
}
|
||||
#if defined(WMR_UNIT_TEST_ENABLED) && WMR_UNIT_TEST_ENABLED
|
||||
if (!FIL_Test())
|
||||
{
|
||||
return WMR_CRITICAL_ERROR;
|
||||
}
|
||||
#endif /* FIL_TEST_ENABLED */
|
||||
|
||||
nRet = BUF_Init((UInt16)FIL_GetFuncTbl()->GetDeviceInfo(AND_DEVINFO_BYTES_PER_PAGE), BYTES_PER_METADATA_RAW, WMR_NUM_BUFFERS);
|
||||
|
||||
if (nRet != BUF_SUCCESS)
|
||||
{
|
||||
return WMR_CRITICAL_ERROR;
|
||||
}
|
||||
|
||||
EXAM_RTL_PRINT((TEXT("[FTL:MSG] BUF_Init [OK]\n")));
|
||||
|
||||
nRet = _initFPart(dwFormatType, dwBootAreaSize);
|
||||
if (nRet != WMR_SUCCESS)
|
||||
{
|
||||
return WMR_CRITICAL_ERROR;
|
||||
}
|
||||
EXAM_RTL_PRINT((TEXT("[FTL:MSG] FPart Init [OK]\n")));
|
||||
|
||||
/* signature searching */
|
||||
// try old style signature first (quicker)
|
||||
|
||||
if (boolSignInBlockZero == TRUE32)
|
||||
{
|
||||
stFPartFunctions.SetSignatureStyle(&stFPartFunctions, SIGNATURE_STYLE_BLOCKZERO_NOHEADER);
|
||||
}
|
||||
else
|
||||
{
|
||||
stFPartFunctions.SetSignatureStyle(&stFPartFunctions, SIGNATURE_STYLE_RESERVEDBLOCK_HEADER);
|
||||
}
|
||||
|
||||
if (stFPartFunctions.ReadSignature(&g_flashANDSignature, sizeof(ANDDriverSignature)))
|
||||
{
|
||||
if (boolSignInBlockZero == TRUE32)
|
||||
{
|
||||
EXAM_RTL_PRINT((TEXT("read old style signature 0x%08X (line:%d)\n"), g_flashANDSignature.dwMainSignature, __LINE__));
|
||||
}
|
||||
else
|
||||
{
|
||||
EXAM_RTL_PRINT((TEXT("read new style signature 0x%08X (line:%d)\n"), g_flashANDSignature.dwMainSignature, __LINE__));
|
||||
}
|
||||
|
||||
if (_isSignatureCompatible(&g_flashANDSignature))
|
||||
{
|
||||
boolSignatureFound = TRUE32;
|
||||
#ifndef AND_READONLY
|
||||
if (boolRunProductionReformat == TRUE32)
|
||||
{
|
||||
stFPartFunctions.WriteSignature(NULL, 0);
|
||||
}
|
||||
#endif
|
||||
if (boolMetadataWhiteningCheck)
|
||||
{
|
||||
BOOL32 boolSignatureHasMetadataWhitening = (WMR_SIGNATURE_METADATA(g_flashANDSignature.dw2ndId) == WMR_METADATA_WHITENING);
|
||||
if ( (boolSignatureHasMetadataWhitening == TRUE32 && boolMetadataWhitening == FALSE32)
|
||||
|| (boolSignatureHasMetadataWhitening == FALSE32 && boolMetadataWhitening == TRUE32))
|
||||
{
|
||||
#ifndef AND_READONLY
|
||||
stFPartFunctions.WriteSignature(NULL, 0);
|
||||
#endif
|
||||
EXAM_RTL_PRINT((TEXT("[FTL:ERR] metadata whitening mismatch, please reformat\n")));
|
||||
return WMR_UNRECOVERABLE_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EXAM_RTL_PRINT((TEXT("[FTL:WRN] Incompatible Signature!\n")));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If we have been instructed to run a production reformat, force it by faking a signature
|
||||
* mismatch
|
||||
*/
|
||||
#ifndef AND_READONLY
|
||||
if (boolRunProductionReformat)
|
||||
{
|
||||
boolSignatureFound = FALSE32;
|
||||
}
|
||||
#endif // ! AND_READONLY
|
||||
|
||||
/*
|
||||
* If any of the basic criteria are violated, we are going to have to reformat.
|
||||
* If this isn't permitted, print a diagnoistic and bail out.
|
||||
*/
|
||||
if (!boolSignatureFound)
|
||||
{
|
||||
/*
|
||||
* Verify that we can read the BBT from all banks.
|
||||
*/
|
||||
#ifndef AND_READONLY
|
||||
if (!bFormatAllowed)
|
||||
#endif
|
||||
{
|
||||
EXAM_RTL_PRINT((TEXT("[WMR:ERR] NAND format invalid (mismatch, corrupt, read error or blank NAND device)\n")));
|
||||
EXAM_RTL_PRINT((TEXT("[WMR:ERR] boolSignatureFound %s boolProductionFormatVerified %s nSig 0x%x\n"),
|
||||
boolSignatureFound ? "true" : "false",
|
||||
boolProductionFormatVerified ? "true" : "false",
|
||||
g_flashANDSignature.dwMainSignature));
|
||||
goto fail_readonly;
|
||||
}
|
||||
#ifndef AND_READONLY
|
||||
boolProductionFormatVerified = stFPartFunctions.VerifyProductionFormat();
|
||||
#ifdef AND_USE_NOTIFY
|
||||
/* one or more of the failed criteria will require a reformat operation */
|
||||
FIL_GetFuncTbl()->Notify(AND_NOTIFY_REFORMAT);
|
||||
#endif
|
||||
#endif //!AND_READONLY
|
||||
}
|
||||
|
||||
// decide what VFL to use
|
||||
if (FALSE32 == _selectVFL(boolSignatureFound, boolAllowVSVFL,
|
||||
boolSignInBlockZero, &g_flashANDSignature, &g_scratchANDSignature))
|
||||
{
|
||||
return WMR_UNRECOVERABLE_ERROR;
|
||||
}
|
||||
nRet = stVflFunctions.Init(&stFPartFunctions);
|
||||
|
||||
if (nRet != VFL_SUCCESS)
|
||||
{
|
||||
return WMR_UNRECOVERABLE_ERROR;
|
||||
}
|
||||
EXAM_RTL_PRINT((TEXT("[FTL:MSG] VFL Init [OK]\n")));
|
||||
|
||||
#ifndef AND_READONLY
|
||||
/*
|
||||
* If we couldn't find the BBT, or the signature is missing (or we are pretending it's missing),
|
||||
* we need to think about (re)formatting.
|
||||
*/
|
||||
if (boolProductionFormatVerified != TRUE32 || boolSignatureFound != TRUE32)
|
||||
{
|
||||
Int32 nRetTemp;
|
||||
if (boolMetadataWhitening)
|
||||
{
|
||||
if (FIL_GetFuncTbl()->SetWhiteningMetadataState)
|
||||
{
|
||||
EXAM_RTL_PRINT((TEXT("[WMR:INF] Formatting with metadata whitening\n")));
|
||||
FIL_GetFuncTbl()->SetWhiteningMetadataState(TRUE32);
|
||||
}
|
||||
else
|
||||
{
|
||||
EXAM_RTL_PRINT((TEXT("[WMR:ERR] Metadata whitening unavailable!\n")));
|
||||
return WMR_UNRECOVERABLE_ERROR;
|
||||
}
|
||||
}
|
||||
if (boolProductionFormatVerified == FALSE32)
|
||||
{
|
||||
// this is a either virgin device or a device that went through
|
||||
// power failure during initial format. We have to scan for
|
||||
// the initial bad blocks and save them as a factory bad-block table.
|
||||
EXAM_RTL_PRINT((TEXT("[WMR:INF] Calling VFL_ProductionFormat()\n")));
|
||||
if (stFPartFunctions.WriteInitialBBT() != TRUE32)
|
||||
{
|
||||
EXAM_RTL_PRINT((TEXT("[WMR:ERR] Failed VFL_ProductionFormat\n")));
|
||||
return WMR_UNRECOVERABLE_ERROR;
|
||||
}
|
||||
EXAM_RTL_PRINT((TEXT("[WMR:MSG] Production Format OK!\n")));
|
||||
boolProductionFormatCompleted = TRUE32;
|
||||
}
|
||||
|
||||
if (boolProductionFormatCompleted == FALSE32)
|
||||
{
|
||||
EXAM_RTL_PRINT((TEXT("[FTL:MSG] Calling VFL_FactoryReformat()\n")));
|
||||
// erase signature before clearing the NAND
|
||||
stFPartFunctions.WriteSignature(NULL, 0);
|
||||
stFPartFunctions.FactoryReformat(FALSE32, FALSE32, dwBootAreaSize);
|
||||
}
|
||||
|
||||
nRetTemp = stVflFunctions.Format(dwBootAreaSize, 0);
|
||||
|
||||
if (nRetTemp != VFL_SUCCESS)
|
||||
{
|
||||
return WMR_UNRECOVERABLE_ERROR;
|
||||
}
|
||||
|
||||
EXAM_RTL_PRINT((TEXT("[FTL:MSG] VFL_Format [OK]\n")));
|
||||
|
||||
// check if we need a shrinked FTL partition
|
||||
if ((*pTotalScts) && (*pdwSectorSize))
|
||||
{
|
||||
UInt32 dwPageSize, dwPagesPerSuBlks;
|
||||
UInt16 wNewFTLSuBlkCnt;
|
||||
UInt32 dwRequestedPages;
|
||||
|
||||
dwPagesPerSuBlks = (UInt16)stVflFunctions.GetDeviceInfo(AND_DEVINFO_PAGES_PER_SUBLK);
|
||||
dwPageSize = (UInt16)stVflFunctions.GetDeviceInfo(AND_DEVINFO_BYTES_PER_PAGE);
|
||||
|
||||
dwRequestedPages = (*pTotalScts) * ((*pdwSectorSize) / dwPageSize);
|
||||
|
||||
wNewFTLSuBlkCnt = (UInt16)((UInt32)(110 * dwRequestedPages) /
|
||||
(dwPagesPerSuBlks * 100)) + 23;
|
||||
|
||||
stVflFunctions.SetStruct(AND_STRUCT_VFL_NUM_OF_FTL_SUBLKS, &wNewFTLSuBlkCnt, sizeof(UInt16));
|
||||
}
|
||||
|
||||
// choose the FTL we want to use and init it
|
||||
if (boolAllowYAFTL == TRUE32)
|
||||
{
|
||||
#if (defined (AND_SUPPORT_YAFTL) && AND_SUPPORT_YAFTL)
|
||||
YAFTL_Register(&stFtlFunctions);
|
||||
EXAM_RTL_PRINT((TEXT("[FTL:MSG] YAFTL Register [OK]\n")));
|
||||
#else
|
||||
EXAM_RTL_PRINT((TEXT("[FTL:ERR] YAFTL is not supported - init fail\n")));
|
||||
return WMR_UNRECOVERABLE_ERROR;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if AND_SUPPORT_LEGACY_FTL
|
||||
EXAM_RTL_PRINT((TEXT("[FTL:MSG] FTL Register [OK]\n")));
|
||||
FTL_Register(&stFtlFunctions);
|
||||
#else
|
||||
EXAM_RTL_PRINT((TEXT("[FTL:ERR] Legacy FTL is not supported - init fail\n")));
|
||||
return WMR_UNRECOVERABLE_ERROR;
|
||||
#endif
|
||||
}
|
||||
boolFTLRegistered = TRUE32;
|
||||
nRetTemp = stFtlFunctions.Init(&stVflFunctions);
|
||||
if (nRetTemp != FTL_SUCCESS)
|
||||
{
|
||||
EXAM_RTL_PRINT((TEXT("[FTL:ERR] FTL failed Init\n")));
|
||||
return WMR_UNRECOVERABLE_ERROR;
|
||||
}
|
||||
EXAM_RTL_PRINT((TEXT("[FTL:MSG] FTL Init [OK]\n")));
|
||||
nRetTemp = stFtlFunctions.Format(0);
|
||||
if (nRetTemp != FTL_SUCCESS)
|
||||
{
|
||||
EXAM_RTL_PRINT((TEXT("[FTL:ERR] FTL failed Formatting\n")));
|
||||
return WMR_UNRECOVERABLE_ERROR;
|
||||
}
|
||||
EXAM_RTL_PRINT((TEXT("[FTL:MSG] FTL Format [OK]\n")));
|
||||
|
||||
/* full reformat, write normal signature */
|
||||
// Main signature is set from _selectVFL
|
||||
g_scratchANDSignature.dw2ndId = WMR_FORMATTING_VERSION;
|
||||
// determine if metadata whitening is needed based on signature
|
||||
if (boolMetadataWhitening)
|
||||
{
|
||||
g_scratchANDSignature.dw2ndId |= WMR_METADATA_SIGNATURE;
|
||||
}
|
||||
/* 5249095 - this should write FTL build info, not kernel version */
|
||||
WMR_MEMSET(g_scratchANDSignature.strBuildInfo, 0, WMR_MAX_STR_BUILD_SIZE);
|
||||
WMR_MEMCPY(g_scratchANDSignature.strBuildInfo, WMR_GETVERSION(),
|
||||
WMR_MIN(WMR_STRLEN(WMR_GETVERSION()), (WMR_MAX_STR_BUILD_SIZE - 1)));
|
||||
boolStatus = stFPartFunctions.WriteSignature(&g_scratchANDSignature, sizeof(ANDDriverSignature));
|
||||
if (boolStatus)
|
||||
{
|
||||
WMR_MEMCPY(&g_flashANDSignature, &g_scratchANDSignature, sizeof(ANDDriverSignature));
|
||||
}
|
||||
else
|
||||
{
|
||||
EXAM_RTL_PRINT((TEXT("[FTL:MSG] Write Signature Failed 0x%08X\n"), g_flashANDSignature.dwMainSignature));
|
||||
return WMR_CRITICAL_ERROR;
|
||||
}
|
||||
|
||||
EXAM_RTL_PRINT((TEXT("[FTL:MSG] Write Signature OK 0x%08X\n"), g_flashANDSignature.dwMainSignature));
|
||||
{
|
||||
WMR_MEMSET(&g_scratchANDSignature, 0, sizeof(ANDDriverSignature));
|
||||
boolStatus = stFPartFunctions.ReadSignature(&g_scratchANDSignature, sizeof(ANDDriverSignature));
|
||||
if (!boolStatus || WMR_MEMCMP(&g_scratchANDSignature, &g_flashANDSignature, sizeof(ANDDriverSignature)))
|
||||
{
|
||||
EXAM_RTL_PRINT((TEXT("[FTL:MSG] Read back Signature Failed 0x%08X\n"), g_scratchANDSignature.dwMainSignature));
|
||||
return WMR_CRITICAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
EXAM_RTL_PRINT((TEXT("[FTL:MSG] Read back Signature OK\n")));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // ! AND_READONLY
|
||||
nRet = stVflFunctions.Open(dwBootAreaSize, 0, 0);
|
||||
|
||||
if (nRet != VFL_SUCCESS)
|
||||
{
|
||||
EXAM_RTL_PRINT((TEXT("[WMR:ERR] VFL_Open failed\n")));
|
||||
WMR_BEEP(1000000);
|
||||
return WMR_UNRECOVERABLE_ERROR;
|
||||
}
|
||||
|
||||
EXAM_RTL_PRINT((TEXT("[FTL:MSG] VFL_Open [OK]\n")));
|
||||
|
||||
if (boolFTLRegistered == FALSE32)
|
||||
{
|
||||
#ifndef AND_READONLY
|
||||
// Check if we wanted to reformat FTL...
|
||||
if (boolRunFTLFormat)
|
||||
{
|
||||
// change the FTL size inside the vfl and mark the FTL
|
||||
// for format
|
||||
if ((*pTotalScts) && (*pdwSectorSize))
|
||||
{
|
||||
UInt32 dwPageSize, dwPagesPerSuBlks;
|
||||
UInt16 wNewFTLSuBlkCnt;
|
||||
UInt32 dwRequestedPages;
|
||||
|
||||
dwPagesPerSuBlks = (UInt16)stVflFunctions.GetDeviceInfo(AND_DEVINFO_PAGES_PER_SUBLK);
|
||||
dwPageSize = (UInt16)stVflFunctions.GetDeviceInfo(AND_DEVINFO_BYTES_PER_PAGE);
|
||||
|
||||
dwRequestedPages = (*pTotalScts) * ((*pdwSectorSize) / dwPageSize);
|
||||
|
||||
wNewFTLSuBlkCnt = (UInt16)((UInt32)(110 * dwRequestedPages) /
|
||||
(dwPagesPerSuBlks * 100)) + 23;
|
||||
stVflFunctions.SetStruct(AND_STRUCT_VFL_NUM_OF_FTL_SUBLKS, &wNewFTLSuBlkCnt, sizeof(UInt16));
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt16 wNewFTLSuBlkCnt;
|
||||
UInt32 dwSize = sizeof(wNewFTLSuBlkCnt);
|
||||
stVflFunctions.GetStruct(AND_STRUCT_VFL_NUM_OF_SUBLKS, &wNewFTLSuBlkCnt, &dwSize);
|
||||
stVflFunctions.SetStruct(AND_STRUCT_VFL_NUM_OF_FTL_SUBLKS, &wNewFTLSuBlkCnt, sizeof(UInt16));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// check what FTL to use here
|
||||
if (stVflFunctions.GetDeviceInfo(AND_DEVINFO_FTL_TYPE) == FTL_TYPE_YAFTL)
|
||||
{
|
||||
#if (defined (AND_SUPPORT_YAFTL) && AND_SUPPORT_YAFTL)
|
||||
YAFTL_Register(&stFtlFunctions);
|
||||
EXAM_RTL_PRINT((TEXT("[FTL:MSG] YAFTL Register [OK]\n")));
|
||||
#else
|
||||
EXAM_RTL_PRINT((TEXT("[FTL:ERR] YAFTL is not supported - init fail\n")));
|
||||
return WMR_UNRECOVERABLE_ERROR;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if AND_SUPPORT_LEGACY_FTL
|
||||
EXAM_RTL_PRINT((TEXT("[FTL:MSG] FTL Register [OK]\n")));
|
||||
FTL_Register(&stFtlFunctions);
|
||||
#else
|
||||
EXAM_RTL_PRINT((TEXT("[FTL:ERR] Legacy FTL is not supported - init fail\n")));
|
||||
return WMR_UNRECOVERABLE_ERROR;
|
||||
#endif
|
||||
}
|
||||
nRet = stFtlFunctions.Init(&stVflFunctions);
|
||||
if (nRet != FTL_SUCCESS)
|
||||
{
|
||||
EXAM_RTL_PRINT((TEXT("[WMR:ERR] FTL Init Fail\n")));
|
||||
return WMR_UNRECOVERABLE_ERROR;
|
||||
}
|
||||
#ifndef AND_READONLY
|
||||
if (stVflFunctions.GetDeviceInfo(AND_DEVINFO_FTL_NEED_FORMAT) ||
|
||||
(boolRunFTLFormat == TRUE32))
|
||||
{
|
||||
nRet = stFtlFunctions.Format(0);
|
||||
if (nRet != FTL_SUCCESS)
|
||||
{
|
||||
EXAM_RTL_PRINT((TEXT("[WMR:ERR] FTL ReFormat Fail\n")));
|
||||
return WMR_UNRECOVERABLE_ERROR;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((dwFormatType & WMR_INIT_DISABLE_GC_IN_TRIM) == WMR_INIT_DISABLE_GC_IN_TRIM)
|
||||
{
|
||||
EXAM_RTL_PRINT((TEXT("FTL_Open will get trim GC disabled settings \n")));
|
||||
ftlOpenOptions |= WMR_INIT_DISABLE_GC_IN_TRIM;
|
||||
}
|
||||
|
||||
if ((dwFormatType & WMR_INIT_SET_INDEX_CACHE_SIZE) == WMR_INIT_SET_INDEX_CACHE_SIZE)
|
||||
{
|
||||
EXAM_RTL_PRINT((TEXT("FTL_Open will set index cache to 0x%x \n"),*tmpIndexCache));
|
||||
ftlOpenOptions |= WMR_INIT_SET_INDEX_CACHE_SIZE;
|
||||
ftlOpenOptions |= ((*tmpIndexCache) << 20);
|
||||
}
|
||||
|
||||
if ( WMR_INIT_OPEN_READONLY == (dwFormatType & WMR_INIT_OPEN_READONLY) )
|
||||
{
|
||||
ftlOpenOptions |= WMR_INIT_OPEN_READONLY;
|
||||
}
|
||||
nRet = stFtlFunctions.Open(pTotalScts, pdwSectorSize, nandFullRestore, FALSE32, 0, ftlOpenOptions);
|
||||
if (nRet != FTL_SUCCESS)
|
||||
{
|
||||
#ifdef WMR_ERASE_UNIT_WHEN_OPEN_FAIL
|
||||
if (!bFormatAllowed)
|
||||
{
|
||||
EXAM_RTL_PRINT((TEXT("[WMR:ERR] FTL_Open failed\n"),
|
||||
nSig, WMR_SIGNATURE));
|
||||
goto fail_readonly;
|
||||
}
|
||||
|
||||
EXAM_RTL_PRINT((TEXT("[WMR:ERR] FTL_Open failed - erasing block 0\n")));
|
||||
pLowFuncTbl->Erase(0, 0);
|
||||
#else
|
||||
EXAM_RTL_PRINT((TEXT("[WMR:ERR] FTL_Open failed\n")));
|
||||
WMR_BEEP(1000000);
|
||||
#endif
|
||||
return WMR_UNRECOVERABLE_ERROR;
|
||||
}
|
||||
EXAM_RTL_PRINT((TEXT("[FTL:MSG] FTL_Open [OK]\n")));
|
||||
|
||||
return WMR_SUCCESS;
|
||||
|
||||
fail_readonly:
|
||||
EXAM_RTL_PRINT((TEXT("******************************************************************************\n")));
|
||||
EXAM_RTL_PRINT((TEXT("******************************************************************************\n")));
|
||||
EXAM_RTL_PRINT((TEXT("AND: NAND initialisation failed due to format mismatch or uninitialised NAND.\n")));
|
||||
EXAM_RTL_PRINT((TEXT("AND: Please reboot with reformatting enabled.\n")));
|
||||
EXAM_RTL_PRINT((TEXT("******************************************************************************\n")));
|
||||
EXAM_RTL_PRINT((TEXT("******************************************************************************\n")));
|
||||
|
||||
return WMR_UNRECOVERABLE_ERROR;
|
||||
}
|
||||
|
||||
BOOL32 WMRGetStruct(UInt32 dwStructType, void * pvoidStructBuffer, UInt32 * pdwStructSize)
|
||||
{
|
||||
BOOL32 boolRes = FALSE32;
|
||||
switch(dwStructType)
|
||||
{
|
||||
case AND_STRUCT_WMR_VERSION:
|
||||
{
|
||||
UInt32 dwSignature = g_flashANDSignature.dwMainSignature;
|
||||
boolRes = WMR_FILL_STRUCT(pvoidStructBuffer, pdwStructSize, &dwSignature, sizeof(dwSignature));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
EXAM_ERR_PRINT((TEXT("[WMR:ERR] WMRGetStruct 0x%X is not identified is WMR data struct identifier!\n"), dwStructType));
|
||||
boolRes = FALSE32;
|
||||
}
|
||||
return boolRes;
|
||||
}
|
||||
|
||||
|
||||
static BOOL32 _andGetStruct(UInt32 dwStructType, void * pvoidStructBuffer, UInt32 * pdwStructSize)
|
||||
{
|
||||
BOOL32 boolRes = FALSE32;
|
||||
|
||||
if (dwStructType == LOCKDOWN_EXTRACT_ALL)
|
||||
{
|
||||
// Mobile Lockdown - Get All Structures
|
||||
#if AND_COLLECT_STATISTICS
|
||||
boolRes = ANDExportAllStructs(pvoidStructBuffer, pdwStructSize);
|
||||
#endif
|
||||
}
|
||||
else if (dwStructType == LOCKDOWN_GET_ALL_SIZE)
|
||||
{
|
||||
#if AND_COLLECT_STATISTICS
|
||||
UInt32 *dwAllSize = (UInt32*) pvoidStructBuffer;
|
||||
if (dwAllSize && pdwStructSize && (*pdwStructSize >= sizeof(UInt32)))
|
||||
{
|
||||
// Mobile Lockdown - Get Size
|
||||
boolRes = ANDExportAllStructs(NULL, dwAllSize);
|
||||
*pdwStructSize = sizeof(UInt32);
|
||||
}
|
||||
else
|
||||
{
|
||||
boolRes = FALSE32;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (dwStructType & AND_STRUCT_LAYER_MASK)
|
||||
{
|
||||
case AND_STRUCT_LAYER_FTL:
|
||||
{
|
||||
boolRes = stFtlFunctions.GetStruct(dwStructType, pvoidStructBuffer, pdwStructSize);
|
||||
break;
|
||||
}
|
||||
|
||||
case AND_STRUCT_LAYER_VFL:
|
||||
{
|
||||
boolRes = stVflFunctions.GetStruct(dwStructType, pvoidStructBuffer, pdwStructSize);
|
||||
break;
|
||||
}
|
||||
|
||||
case AND_STRUCT_LAYER_FIL:
|
||||
{
|
||||
boolRes = FIL_GetStruct(dwStructType, pvoidStructBuffer, pdwStructSize);
|
||||
break;
|
||||
}
|
||||
|
||||
case AND_STRUCT_LAYER_GETALL:
|
||||
{
|
||||
#if AND_COLLECT_STATISTICS
|
||||
if (dwStructType == AND_STRUCT_WMR_EXPORT_ALL)
|
||||
{
|
||||
boolRes = ANDExportAllStructs(pvoidStructBuffer, pdwStructSize);
|
||||
}
|
||||
else if (dwStructType == AND_STRUCT_WMR_EXPORT_ALL_GET_SIZE)
|
||||
{
|
||||
UInt32 *dwStructSizeVal = (UInt32*) pvoidStructBuffer;
|
||||
if (dwStructSizeVal && pdwStructSize && (*pdwStructSize >= sizeof(UInt32)))
|
||||
{
|
||||
boolRes = ANDExportAllStructs(NULL, dwStructSizeVal);
|
||||
*pdwStructSize = sizeof(UInt32);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
EXAM_ERR_PRINT((TEXT("[WMR:ERR] _andGetStruct 0x%X is not identified !\n"), dwStructType));
|
||||
boolRes = FALSE32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return boolRes;
|
||||
}
|
||||
|
||||
static BOOL32 _andPerformFunction(UInt32 dwFunctionSelector, void * pvoidStructBuffer, UInt32 * pdwStructSize)
|
||||
{
|
||||
switch (dwFunctionSelector)
|
||||
{
|
||||
#ifndef AND_READONLY
|
||||
|
||||
case _AND_FUNCTION_COMPLETE_EPOCH_UPDATE:
|
||||
{
|
||||
WMR_PRINT(ERROR, "Epoch update is deprecated\n");
|
||||
return FALSE32;
|
||||
}
|
||||
|
||||
case AND_FUNCTION_INDEX_CACHE_UPDATE:
|
||||
{
|
||||
BOOL32 boolRes = FALSE32;
|
||||
if (stFtlFunctions.GetStruct && pdwStructSize)
|
||||
{
|
||||
boolRes = stFtlFunctions.GetStruct(dwFunctionSelector, NULL, pdwStructSize);
|
||||
*pdwStructSize = 0;
|
||||
}
|
||||
return boolRes;
|
||||
}
|
||||
|
||||
case AND_FUNCTION_CHANGE_FTL_TYPE:
|
||||
{
|
||||
BOOL32 boolRes = FALSE32;
|
||||
if (stVflFunctions.SetStruct && pdwStructSize)
|
||||
{
|
||||
boolRes = stVflFunctions.SetStruct(AND_STRUCT_VFL_NEW_FTLTYPE, pvoidStructBuffer, *pdwStructSize);
|
||||
}
|
||||
return boolRes;
|
||||
}
|
||||
|
||||
case AND_FUNCTION_CHANGE_NUM_OF_SUBLKS:
|
||||
{
|
||||
BOOL32 boolRes = FALSE32;
|
||||
if (stVflFunctions.SetStruct && pdwStructSize)
|
||||
{
|
||||
boolRes = stVflFunctions.SetStruct(AND_STRUCT_VFL_NEW_NUM_OF_FTL_SUBLKS, pvoidStructBuffer, *pdwStructSize);
|
||||
}
|
||||
return boolRes;
|
||||
}
|
||||
|
||||
case AND_FUNCTION_SET_BURNIN_CODE:
|
||||
{
|
||||
BOOL32 boolRes = FALSE32;
|
||||
if (stVflFunctions.SetStruct && pdwStructSize)
|
||||
{
|
||||
boolRes = stVflFunctions.SetStruct(AND_STRUCT_VFL_BURNIN_CODE, pvoidStructBuffer, *pdwStructSize);
|
||||
}
|
||||
return boolRes;
|
||||
}
|
||||
|
||||
case AND_FUNCTION_ERASE_SIGNATURE:
|
||||
{
|
||||
BOOL32 boolRes;
|
||||
WMR_MEMSET(&g_flashANDSignature, 0, sizeof(ANDDriverSignature));
|
||||
boolRes = stFPartFunctions.WriteSignature(&g_flashANDSignature, sizeof(ANDDriverSignature));
|
||||
return boolRes;
|
||||
}
|
||||
|
||||
case AND_FUNCTION_SET_POWER_MODE:
|
||||
{
|
||||
BOOL32 boolRes = FALSE32;
|
||||
if (pdwStructSize)
|
||||
{
|
||||
boolRes = FIL_SetStruct(AND_STRUCT_FIL_POWER_MODE, pvoidStructBuffer, *pdwStructSize);
|
||||
}
|
||||
return boolRes;
|
||||
}
|
||||
|
||||
case AND_FUNCTION_NEURALIZE:
|
||||
{
|
||||
BOOL32 boolRes;
|
||||
boolRes = stFPartFunctions.Neuralize();
|
||||
return boolRes;
|
||||
}
|
||||
|
||||
case AND_FUNCTION_SET_TIMINGS:
|
||||
{
|
||||
BOOL32 boolRes = FALSE32;
|
||||
if (pdwStructSize)
|
||||
{
|
||||
boolRes = FIL_SetStruct(AND_STRUCT_FIL_SET_TIMINGS, pvoidStructBuffer, *pdwStructSize);
|
||||
}
|
||||
return boolRes;
|
||||
}
|
||||
|
||||
case AND_FUNCTION_SAVE_STATS:
|
||||
{
|
||||
BOOL32 boolRes = FALSE32;
|
||||
if(stFtlFunctions.WriteStats)
|
||||
{
|
||||
boolRes = stFtlFunctions.WriteStats();
|
||||
return boolRes;
|
||||
}
|
||||
}
|
||||
#endif // ! AND_READONLY
|
||||
|
||||
default:
|
||||
return FALSE32;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL32 WMR_CtrlIO(UInt32 dwCtlrIOType, void * pvoidDataBuffer, UInt32 * pdwDataSize)
|
||||
{
|
||||
if ((dwCtlrIOType & AND_STRUCT_LAYER_MASK) == AND_STRUCT_LAYER_FUNCTIONAL)
|
||||
{
|
||||
return _andPerformFunction(dwCtlrIOType, pvoidDataBuffer, pdwDataSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
return _andGetStruct(dwCtlrIOType, pvoidDataBuffer, pdwDataSize);
|
||||
}
|
||||
}
|
||||
|
||||
#if AND_SIMULATOR
|
||||
void WMR_Close(void)
|
||||
{
|
||||
stFtlFunctions.Close();
|
||||
WMR_MEMSET(&stFtlFunctions, 0, sizeof(FTLFunctions));
|
||||
stVflFunctions.Close();
|
||||
WMR_MEMSET(&stVflFunctions, 0, sizeof(VFLFunctions));
|
||||
stFPartFunctions.Close();
|
||||
WMR_MEMSET(&stFPartFunctions, 0, sizeof(FPartFunctions));
|
||||
boolFPartInitialized = FALSE32;
|
||||
// NirW - using Ram disk - killing FIL is a pain and irrelevant...
|
||||
// FIL_Close();
|
||||
// WMR_MEMSET(&stDeviceInfo, 0, sizeof(stDeviceInfo));
|
||||
}
|
||||
#endif
|
||||
|
||||
FTLFunctions * WMR_GetFTL(void)
|
||||
{
|
||||
return &stFtlFunctions;
|
||||
}
|
||||
|
||||
VFLFunctions * WMR_GetVFL(void)
|
||||
{
|
||||
return &stVflFunctions;
|
||||
}
|
||||
|
||||
#endif // (!defined(AND_FPART_ONLY) || !AND_FPART_ONLY)
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* COMPONENT : Rainbow */
|
||||
/* MODULE : Example */
|
||||
/* NAME : Example */
|
||||
/* FILE : WMRExam.h */
|
||||
/* PURPOSE : the example for whimory initialization */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* COPYRIGHT 2003-2005 SAMSUNG ELECTRONICS CO., LTD. */
|
||||
/* ALL RIGHTS RESERVED */
|
||||
/* */
|
||||
/* Permission is hereby granted to licensees of Samsung Electronics */
|
||||
/* Co., Ltd. products to use or abstract this computer program for the */
|
||||
/* sole purpose of implementing a product based on Samsung */
|
||||
/* Electronics Co., Ltd. products. No other rights to reproduce, use, */
|
||||
/* or disseminate this computer program, whether in part or in whole, */
|
||||
/* are granted. */
|
||||
/* */
|
||||
/* Samsung Electronics Co., Ltd. makes no representation or warranties */
|
||||
/* with respect to the performance of this computer program, and */
|
||||
/* specifically disclaims any responsibility for any damages, */
|
||||
/* special or consequential, connected with the use of this program. */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* REVISION HISTORY */
|
||||
/* */
|
||||
/* 12-SEP-2005 [Jaesung Jung] : first writing */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
#if (!defined(AND_FPART_ONLY) || !AND_FPART_ONLY)
|
||||
#include "FTL.h"
|
||||
#include "VFL.h"
|
||||
#include "FIL.h"
|
||||
#else
|
||||
#include "FPart.h"
|
||||
#include "FIL.h"
|
||||
#endif
|
||||
|
||||
#ifndef _WMR_EXAM_H_
|
||||
#define _WMR_EXAM_H_
|
||||
|
||||
/*****************************************************************************/
|
||||
/* whimory version signature */
|
||||
// Platform Types
|
||||
#define WMR_PLATFORM_SHIFT (24)
|
||||
#define WMR_PLATFORM_DARWIN ('C')
|
||||
|
||||
// Layout Types
|
||||
#define WMR_LAYOUT_SHIFT (16)
|
||||
#define WMR_LAYOUT_SIMPLE ('0')
|
||||
#define WMR_LAYOUT_VS ('1')
|
||||
|
||||
// VFL types
|
||||
#define WMR_VFL_SHIFT (8)
|
||||
#define WMR_M68_VFL ('0')
|
||||
#define WMR_VSVFL ('1')
|
||||
|
||||
// default signature goes here
|
||||
#define WMR_VFL_SIGNATURE ((WMR_PLATFORM_DARWIN << WMR_PLATFORM_SHIFT) | (WMR_LAYOUT_SIMPLE << WMR_LAYOUT_SHIFT) | (WMR_M68_VFL << 8)) /* 'C0' for P2 */
|
||||
#define WMR_VSVFL_SIGNATURE ((WMR_PLATFORM_DARWIN << WMR_PLATFORM_SHIFT) | (WMR_LAYOUT_SIMPLE << WMR_LAYOUT_SHIFT) | (WMR_VSVFL << 8)) /* 'C0' for P2 */
|
||||
#define WMR_VSVFL_VS_SIGNATURE ((WMR_PLATFORM_DARWIN << WMR_PLATFORM_SHIFT) | (WMR_LAYOUT_VS << WMR_LAYOUT_SHIFT) | (WMR_VSVFL << 8)) /* 'C1' for N72+ */
|
||||
|
||||
#define WMR_SIGNATURE_EPOCH_MASK (0x000000FF)
|
||||
#define WMR_SIGNATURE_VFL_MASK (0x0000FF00)
|
||||
#define WMR_SIGNATURE_LAYOUT_MASK (0x00FF0000)
|
||||
#define WMR_SIGNATURE_PLATFORM_MASK (0xFF000000)
|
||||
// signature bit masks for 2nd ID
|
||||
#define WMR_SIGNATURE_FORMAT_VERSION_MASK (0x0000FFFF)
|
||||
#define WMR_SIGNATURE_METADATA_MASK (0x00010000)
|
||||
|
||||
#define WMR_SIGNATURE_VFL(_x) (UInt8)(((_x) & WMR_SIGNATURE_VFL_MASK) >> WMR_VFL_SHIFT)
|
||||
#define WMR_SIGNATURE_LAYOUT(_x) (UInt8)(((_x) & WMR_SIGNATURE_LAYOUT_MASK) >> WMR_LAYOUT_SHIFT)
|
||||
#define WMR_SIGNATURE_PLATFORM(_x) (UInt8)(((_x) & WMR_SIGNATURE_PLATFORM_MASK) >> WMR_PLATFORM_SHIFT)
|
||||
#define WMR_SIGNATURE_FORMATTING_VERSION(_x) (UInt8)((_x) & WMR_SIGNATURE_FORMAT_VERSION_MASK)
|
||||
#define WMR_SIGNATURE_METADATA(_x) (UInt8)(((_x) & WMR_SIGNATURE_METADATA_MASK) >> WMR_METADATA_SHIFT)
|
||||
|
||||
#define WMR_FORMATTING_VERSION_2 ((UInt32)0x00000002) /* May 20th 2007 */
|
||||
#define WMR_FORMATTING_VERSION_3 ((UInt32)0x00000003) /* August 22nd 2007 */
|
||||
#define WMR_FORMATTING_VERSION_4 ((UInt32)0x00000004) /* July 23rd 2008 */
|
||||
#define WMR_FORMATTING_VERSION_5 ((UInt32)0x00000005) /* Dec 1st 2009 */
|
||||
#define WMR_FORMATTING_VERSION ((UInt32)0x00000006) /* July 30th 2010 */
|
||||
|
||||
// Metadata Whitening
|
||||
#define WMR_METADATA_SHIFT (16)
|
||||
#define WMR_METADATA_WHITENING_NONE ((UInt32)0x0)
|
||||
#define WMR_METADATA_WHITENING ((UInt32)0x1)
|
||||
#define WMR_METADATA_SIGNATURE (WMR_METADATA_WHITENING << WMR_METADATA_SHIFT)
|
||||
|
||||
#define WMR_FORMAT_SUPPORTED(_x) ((_x) <= WMR_FORMATTING_VERSION)
|
||||
|
||||
/* used during epoch updates */
|
||||
#define WMR_TEMP_SIGNATURE (('X' << 24) | ('X' << 16) | ('X' << 8) | ('X' << 0))
|
||||
/* Return value of WMR_XXX() */
|
||||
/*****************************************************************************/
|
||||
#define WMR_SUCCESS ANDErrorCodeOk
|
||||
#define WMR_CRITICAL_ERROR ANDErrorCodeHwErr
|
||||
#define WMR_UNRECOVERABLE_ERROR ANDErrorCodeUserDataErr
|
||||
|
||||
#define WMR_MAX_STR_BUILD_SIZE (256)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 dwMainSignature; // main driver version number
|
||||
UInt32 dw2ndId; // to be used for undetifying sub versions
|
||||
UInt8 strBuildInfo[WMR_MAX_STR_BUILD_SIZE]; // kernel / build version that formatted the device
|
||||
} ANDDriverSignature;
|
||||
|
||||
/*****************************************************************************/
|
||||
/* exported function prototype of WMR example */
|
||||
/*****************************************************************************/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
Int32 WMR_PreInit(UInt32 dwFormatType, UInt32 dwBootAreaSize);
|
||||
|
||||
#if (!defined(AND_FPART_ONLY) || !AND_FPART_ONLY)
|
||||
Int32 WMR_Init(UInt32 *pTotalScts, UInt32 * pdwSectorSize, UInt32 * tmpIndexCache, UInt32 dwFormatType, UInt32 dwBootAreaSize);
|
||||
void WMR_Close(void);
|
||||
BOOL32 WMR_CtrlIO(UInt32 dwCtlrIOType, void * pvoidDataBuffer, UInt32 * pdwDataSize);
|
||||
BOOL32 WMRGetStruct(UInt32 dwStructType, void * pvoidStructBuffer, UInt32 * pdwStructSize);
|
||||
|
||||
FTLFunctions * WMR_GetFTL(void);
|
||||
VFLFunctions * WMR_GetVFL(void);
|
||||
#endif // (!defined(AND_FPART_ONLY) || !AND_FPART_ONLY)
|
||||
|
||||
FPartFunctions * WMR_GetFPart(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* _FTL_H_ */
|
||||
@@ -0,0 +1,541 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef _AND_TYPES_H_
|
||||
#define _AND_TYPES_H_
|
||||
|
||||
#include "WMRTypes.h"
|
||||
|
||||
typedef Int32 ANDStatus;
|
||||
|
||||
#define ANDErrorCodeOk (Int32)0
|
||||
#define ANDErrorCodeCleanOk (Int32)1
|
||||
#define ANDErrorCodeHwErr (Int32)0x80000001
|
||||
#define ANDErrorCodeUserDataErr (Int32)0x80000002
|
||||
#define ANDErrorCodeOutOfRangeErr (Int32)0x80000003
|
||||
#define ANDErrorCodeAlignmentErr (Int32)0x80000004
|
||||
#define ANDErrorWriteFailureErr (Int32)0x80000005
|
||||
#define ANDErrorCodeAllocFailErr (Int32)0x80000006
|
||||
#define ANDErrorCodeNotSupportedErr (Int32)0x80000007
|
||||
|
||||
#define NAND_UID_RAW_PAGE_BYTES_TO_READ (256)
|
||||
#define NAND_UID_PPN_BYTES_TO_READ (16)
|
||||
#define NAND_UID_LEN_RAW (16)
|
||||
#define NAND_UID_LEN_PPN (16)
|
||||
//Length of PPN Firmware Version, Package Assembly Code, Controller UID, Controller HW ID
|
||||
#define NAND_DEV_PARAM_LEN_PPN (16)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt8 ce;
|
||||
UInt8 cmdSize;
|
||||
UInt8 addrSize;
|
||||
UInt8 confirmCmdSize;
|
||||
UInt8 arrCmd[10];
|
||||
UInt8 arrAddr[10];
|
||||
UInt8 arrConfirmCmd[10];
|
||||
UInt8 buf[NAND_UID_RAW_PAGE_BYTES_TO_READ];
|
||||
UInt32 bytesToRead;
|
||||
} GenericReadRequest;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt8 ce;
|
||||
UInt8 die;
|
||||
UInt8 buf[NAND_UID_PPN_BYTES_TO_READ];
|
||||
} PpnUIDReadRequest;
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct {
|
||||
UInt8 DCCYCLE;
|
||||
UInt8 tRP;
|
||||
UInt8 tREH;
|
||||
UInt8 tWP;
|
||||
UInt8 tWH;
|
||||
}sdrTimings;
|
||||
UInt8 ddr_tHALFCYCLE;
|
||||
}NandTimingParams;
|
||||
|
||||
// ANDAddressStruct - is used to translate logical and virtual
|
||||
// addresses to physical addresses
|
||||
typedef struct
|
||||
{
|
||||
UInt32 dwLpn;
|
||||
UInt32 dwVpn;
|
||||
UInt32 dwCS;
|
||||
UInt32 dwPpn;
|
||||
UInt32 dwColumn;
|
||||
UInt16 dwCau;
|
||||
} ANDAddressStruct;
|
||||
|
||||
// Describe the sections of a NAND page that contain data
|
||||
typedef struct
|
||||
{
|
||||
UInt32 dwNumSegments;
|
||||
UInt32 dwMetaSegmentIndex;
|
||||
struct {
|
||||
UInt32 dwOffset;
|
||||
UInt32 dwLength;
|
||||
} pastrSegments[32];
|
||||
|
||||
} ANDNandLayoutStruct;
|
||||
|
||||
// use this structure to export all the information from the AND driver in a single buffer / file.
|
||||
typedef struct
|
||||
{
|
||||
UInt32 dwStructID;
|
||||
UInt32 dwStructureVersion;
|
||||
UInt32 dwDataSize;
|
||||
UInt32 dwIndex;
|
||||
} ANDExportStruct;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt16 bank;
|
||||
UInt16 block;
|
||||
} SpecialBlockAddress;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 dwPhysicalCE;
|
||||
UInt32 dwPhysicalBlock;
|
||||
UInt16 wType;
|
||||
} BorrowBlockAddress;
|
||||
|
||||
#define VFL_VALUE_UNKNOWN (~0)
|
||||
typedef enum
|
||||
{
|
||||
VFLFailNone,
|
||||
VFLFailUECC,
|
||||
VFLFailErase,
|
||||
VFLFailWrite,
|
||||
VFLFailEraseTimeOut,
|
||||
VFLFailWriteTimeOut,
|
||||
VFLFailRefresh,
|
||||
VFLFailEnd = 0x7FFFFFFF
|
||||
} VFLFailureMode;
|
||||
|
||||
#define VFL_MAX_FAILURE_REGIONS (16)
|
||||
typedef struct
|
||||
{
|
||||
VFLFailureMode mode;
|
||||
UInt16 wCE[VFL_MAX_FAILURE_REGIONS];
|
||||
UInt16 wPhysicalBlock[VFL_MAX_FAILURE_REGIONS];
|
||||
UInt32 dwPhysicalPage;
|
||||
} VFLFailureDetails;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt64 ddwPagesWrittenCnt;
|
||||
UInt64 ddwPagesReadCnt;
|
||||
UInt64 ddwBlocksErasedCnt;
|
||||
UInt64 ddwSingleWriteCallCnt;
|
||||
UInt64 ddwSingleReadCallCnt;
|
||||
UInt64 ddwSequetialReadCallCnt;
|
||||
UInt64 ddwScatteredReadCallCnt;
|
||||
UInt64 ddwMultipleWriteCallCnt;
|
||||
UInt64 ddwEraseCallCnt;
|
||||
} genVFLStatistics;
|
||||
|
||||
#define TL_BLOCK_FREE 0x1
|
||||
#define TL_BLOCK_DATA 0x2
|
||||
#define TL_BLOCK_INDEX 0x4
|
||||
#define TL_BLOCK_CXT 0x8
|
||||
#define TL_BLOCK_DEAD 0x10
|
||||
#define TL_BLOCK_DATA_STATIC 0x20
|
||||
#define TL_BLOCK_UNKNOWN 0x80
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt8 blockType;
|
||||
UInt32 blockSizeInLbas;
|
||||
UInt32 validLbas;
|
||||
} ANDFTLBlockStruct;
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Global Structure Types which should be shared by FTL, VFL, FIL */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define FTL_TYPE_FTL 1
|
||||
#define FTL_TYPE_YAFTL 2
|
||||
#define FTL_TYPE_SFTL 3
|
||||
|
||||
#define VFL_TYPE_VFL 1
|
||||
#define VFL_TYPE_VSVFL 2
|
||||
#define VFL_TYPE_PPNVFL 3
|
||||
#define VFL_TYPE_SWISSPPNVFL 4
|
||||
|
||||
|
||||
#define AND_EXPORT_STRUCTURE_VERSION 0x00020001
|
||||
#define AND_EXPORT_STRUCTURE_MAJVER(v) (((v) >> 16) & 0xFFFF)
|
||||
#define AND_EXPORT_STRUCTURE_MINVER(v) (((v) >> 0) & 0xFFFF)
|
||||
#define AND_EXPORT_STRUCTURE_IS_1_X(v) (1 == AND_EXPORT_STRUCTURE_MAJVER(v))
|
||||
#define AND_EXPORT_STRUCTURE_IS_2_X(v) (2 == AND_EXPORT_STRUCTURE_MAJVER(v))
|
||||
|
||||
#define AND_STATISTICS_SIZE_PER_LAYER (0x200)
|
||||
|
||||
#define LOCKDOWN_EXTRACT_ALL (0xFE000000 | 0x00000100)
|
||||
#define LOCKDOWN_GET_ALL_SIZE (0xFE000000 | 0x00000200)
|
||||
|
||||
// CtrlIO defines and structures
|
||||
// defines for data structues queries from user applications
|
||||
#define AND_STRUCT_SIZE_MASK (0x80000000) // MSb indicates we're requesting the size
|
||||
#define AND_STRUCT_LAYER_MASK (0x3F000000) // use with & to get the layer struct type
|
||||
#define AND_STRUCT_INDEX_MASK (0xFFFFFF00) // use with & to clear the index (LSB)
|
||||
#define AND_STRUCT_CS_MASK (0x000000FF) // use with & to clear the CS
|
||||
#define AND_STRUCT_SET (0x40000000) // Use this bit to indicate a set operation
|
||||
#define AND_STRUCT_LAYER_OS (0x0A000000)
|
||||
|
||||
#define AND_STRUCT_LAYER_FTL (0x01000000)
|
||||
#define AND_STRUCT_LAYER_VFL (0x02000000)
|
||||
#define AND_STRUCT_LAYER_FIL (0x03000000)
|
||||
#define AND_STRUCT_LAYER_WMR (0x04000000)
|
||||
#define AND_STRUCT_LAYER_FUNCTIONAL (0x10000000)
|
||||
// Operations
|
||||
#define _AND_FUNCTION_COMPLETE_EPOCH_UPDATE (AND_STRUCT_LAYER_FUNCTIONAL | 0x00000001) // deprecated
|
||||
#define AND_FUNCTION_INDEX_CACHE_UPDATE (AND_STRUCT_LAYER_FUNCTIONAL | 0x00000200)
|
||||
#define AND_FUNCTION_CHANGE_FTL_TYPE (AND_STRUCT_LAYER_FUNCTIONAL | 0x00000300)
|
||||
#define AND_FUNCTION_CHANGE_NUM_OF_SUBLKS (AND_STRUCT_LAYER_FUNCTIONAL | 0x00000400)
|
||||
#define AND_FUNCTION_SET_BURNIN_CODE (AND_STRUCT_LAYER_FUNCTIONAL | 0x00000500)
|
||||
#define AND_FUNCTION_ERASE_SIGNATURE (AND_STRUCT_LAYER_FUNCTIONAL | 0x00000600)
|
||||
#define AND_FUNCTION_SET_POWER_MODE (AND_STRUCT_LAYER_FUNCTIONAL | 0x00000700)
|
||||
#define AND_FUNCTION_NEURALIZE (AND_STRUCT_LAYER_FUNCTIONAL | 0x00000800)
|
||||
#define AND_FUNCTION_SET_TIMINGS (AND_STRUCT_LAYER_FUNCTIONAL | 0x00000900)
|
||||
#define AND_FUNCTION_SAVE_STATS (AND_STRUCT_LAYER_FUNCTIONAL | 0x00000A00)
|
||||
|
||||
// the below is defined in ANDExport.h
|
||||
#define AND_STRUCT_LAYER_GETALL (0x30000000)
|
||||
|
||||
#define AND_STRUCT_WMR_EXPORT_ALL (AND_STRUCT_LAYER_GETALL | 0x00000100)
|
||||
#define AND_STRUCT_WMR_EXPORT_ALL_GET_SIZE (AND_STRUCT_LAYER_GETALL | 0x00000200)
|
||||
#define AND_STRUCT_WMR_EXPORT_ALL_END (AND_STRUCT_LAYER_GETALL | 0x0000FF00)
|
||||
|
||||
// use the LSB for indexing (do not use it for the identifiers)
|
||||
// OS structures
|
||||
#define AND_STRUCT_OS_GET_IOS (AND_STRUCT_LAYER_OS | 0x00000100)
|
||||
#define AND_STRUCT_OS_GET_HIST (AND_STRUCT_LAYER_OS | 0x00000200)
|
||||
#define AND_STRUCT_OS_SET_LOG_TAG (AND_STRUCT_LAYER_OS | 0x00000300)
|
||||
#define AND_STRUCT_OS_SET_GMT_TAG (AND_STRUCT_LAYER_OS | 0x00000400)
|
||||
|
||||
// FTL structures
|
||||
#define AND_STRUCT_FTL_STATISTICS (AND_STRUCT_LAYER_FTL | 0x00000200)
|
||||
#define AND_STRUCT_FTL_FTLCXT (AND_STRUCT_LAYER_FTL | 0x00000300)
|
||||
#define AND_STRUCT_FTL_MAPTABLE (AND_STRUCT_LAYER_FTL | 0x00000400)
|
||||
#define AND_STRUCT_FTL_LOGCXTTABLE (AND_STRUCT_LAYER_FTL | 0x00000500)
|
||||
#define AND_STRUCT_FTL_ECTABLE (AND_STRUCT_LAYER_FTL | 0x00000600)
|
||||
#define AND_STRUCT_FTL_RCTABLE (AND_STRUCT_LAYER_FTL | 0x00000700)
|
||||
#define AND_STRUCT_FTL_GETADDRESS (AND_STRUCT_LAYER_FTL | 0x00000800)
|
||||
#define AND_STRUCT_FTL_GET_TYPE (AND_STRUCT_LAYER_FTL | 0x00000900)
|
||||
#define AND_STRUCT_FTL_GET_FTL_STATS_SIZE (AND_STRUCT_LAYER_FTL | 0x00000A00)
|
||||
#define AND_STRUCT_FTL_GET_FTL_DEVICEINFO_SIZE (AND_STRUCT_LAYER_FTL | 0x00000B00)
|
||||
#define AND_STRUCT_FTL_GET_FTL_DEVICEINFO (AND_STRUCT_LAYER_FTL | 0x00000C00)
|
||||
#define AND_STRUCT_FTL_GET_FTL_EC_BINS (AND_STRUCT_LAYER_FTL | 0x00000D00)
|
||||
#define AND_STRUCT_FTL_GET_FTL_RC_BINS (AND_STRUCT_LAYER_FTL | 0x00000E00)
|
||||
#define AND_STRUCT_FTL_RECOMMEND_CONTENT_DELETION (AND_STRUCT_LAYER_FTL | 0x00000F00)
|
||||
#define AND_STRUCT_FTL_IDEAL_SIZE_1K (AND_STRUCT_LAYER_FTL | 0x00001000)
|
||||
#define AND_STRUCT_FTL_GET_FTL_BLOCK_COUNT (AND_STRUCT_LAYER_FTL | 0x00001100)
|
||||
#define AND_STRUCT_FTL_GET_FTL_BLOCK_STAT (AND_STRUCT_LAYER_FTL | 0x00001200)
|
||||
#define AND_STRUCT_FTL_L2V_STRUCT (AND_STRUCT_LAYER_FTL | 0x00001300)
|
||||
#define AND_STRUCT_FTL_L2V_ROOTS (AND_STRUCT_LAYER_FTL | 0x00001400)
|
||||
#define AND_STRUCT_FTL_L2V_POOL (AND_STRUCT_LAYER_FTL | 0x00001500)
|
||||
#define AND_STRUCT_FTL_SB_CYCLES (AND_STRUCT_LAYER_FTL | 0x00001600)
|
||||
#define AND_STRUCT_FTL_SB_READ_CYCLES (AND_STRUCT_LAYER_FTL | 0x00001700)
|
||||
|
||||
// VFL structures
|
||||
#define AND_STRUCT_VFL_MASK (AND_STRUCT_LAYER_VFL | 0x0000FF00)
|
||||
#define AND_STRUCT_VFL_STATISTICS (AND_STRUCT_LAYER_VFL | 0x00000200)
|
||||
#define AND_STRUCT_VFL_VFLMETA (AND_STRUCT_LAYER_VFL | 0x00000300)
|
||||
#define AND_STRUCT_VFL_BBT (AND_STRUCT_LAYER_VFL | 0x00000400)
|
||||
#define AND_STRUCT_VFL_FILSTATISTICS (AND_STRUCT_LAYER_VFL | 0x00000500)
|
||||
#define AND_STRUCT_VFL_GETADDRESS (AND_STRUCT_LAYER_VFL | 0x00000600)
|
||||
#define AND_STRUCT_VFL_GROWNBBT (AND_STRUCT_LAYER_VFL | 0x00000700)
|
||||
#define AND_STRUCT_VFL_GET_TYPE (AND_STRUCT_LAYER_VFL | 0x00000800)
|
||||
#define AND_STRUCT_VFL_STATISTICS_SIZE (AND_STRUCT_LAYER_VFL | 0x00000900)
|
||||
#define AND_STRUCT_VFL_DEVICEINFO_SIZE (AND_STRUCT_LAYER_VFL | 0x00000A00)
|
||||
#define AND_STRUCT_VFL_DEVICEINFO (AND_STRUCT_LAYER_VFL | 0x00000B00)
|
||||
#define AND_STRUCT_VFL_FTLTYPE (AND_STRUCT_LAYER_VFL | 0x00000C00)
|
||||
#define AND_STRUCT_VFL_NUM_OF_FTL_SUBLKS (AND_STRUCT_LAYER_VFL | 0x00000D00)
|
||||
#define AND_STRUCT_VFL_BYTES_PER_PAGE (AND_STRUCT_LAYER_VFL | 0x00000E00)
|
||||
#define AND_STRUCT_VFL_PAGES_PER_SUBLK (AND_STRUCT_LAYER_VFL | 0x00000F00)
|
||||
#define AND_STRUCT_VFL_BYTES_PER_META (AND_STRUCT_LAYER_VFL | 0x00001000)
|
||||
#define AND_STRUCT_VFL_CORRECTABLE_BITS (AND_STRUCT_LAYER_VFL | 0x00001100)
|
||||
#define AND_STRUCT_VFL_CORRECTABLE_SIZE (AND_STRUCT_LAYER_VFL | 0x00001200)
|
||||
#define AND_STRUCT_VFL_NUM_OF_SUBLKS (AND_STRUCT_LAYER_VFL | 0x00001300)
|
||||
#define AND_STRUCT_VFL_NEW_FTLTYPE (AND_STRUCT_LAYER_VFL | 0x00001400)
|
||||
#define AND_STRUCT_VFL_NEW_NUM_OF_FTL_SUBLKS (AND_STRUCT_LAYER_VFL | 0x00001500)
|
||||
#define AND_STRUCT_VFL_BURNIN_CODE (AND_STRUCT_LAYER_VFL | 0x00001600)
|
||||
#define AND_STRUCT_VFL_FACTORY_BBT (AND_STRUCT_LAYER_VFL | 0x00001700)
|
||||
#define AND_STRUCT_VFL_SIGNATURE_LOCATION (AND_STRUCT_LAYER_VFL | 0x00001800)
|
||||
#define AND_STRUCT_VFL_PAGES_PER_BLOCK (AND_STRUCT_LAYER_VFL | 0x00001900)
|
||||
#define AND_STRUCT_VFL_LAST_ERROR (AND_STRUCT_LAYER_VFL | 0x00001A00)
|
||||
#define AND_STRUCT_VFL_NAND_TYPE (AND_STRUCT_LAYER_VFL | 0x00001B00)
|
||||
#define AND_STRUCT_VFL_VALID_BYTES_PER_META (AND_STRUCT_LAYER_VFL | 0x00001C00)
|
||||
#define AND_STRUCT_VFL_FIND_BORROWED_BLOCKS (AND_STRUCT_LAYER_VFL | 0x00001D00)
|
||||
#define AND_STRUCT_VFL_EXPORTED_LBA_NO (AND_STRUCT_LAYER_VFL | 0x00001E00)
|
||||
#define AND_STRUCT_VFL_EXPORTED_L2V_POOL (AND_STRUCT_LAYER_VFL | 0x00001F00)
|
||||
#define AND_STRUCT_VFL_PUBLIC_FBBT (AND_STRUCT_LAYER_VFL | 0x00002000)
|
||||
#define AND_STRUCT_VFL_NUM_CHANNELS (AND_STRUCT_LAYER_VFL | 0x00002100)
|
||||
#define AND_STRUCT_VFL_CES_PER_CHANNEL (AND_STRUCT_LAYER_VFL | 0x00002200)
|
||||
#define AND_STRUCT_VFL_CAUS_PER_CE (AND_STRUCT_LAYER_VFL | 0x00002300)
|
||||
#define AND_STRUCT_VFL_MAX_TRANS_IN_PAGES (AND_STRUCT_LAYER_VFL | 0x00002400)
|
||||
|
||||
// FIL structures
|
||||
#define AND_STRUCT_FIL_MASK (AND_STRUCT_LAYER_FIL | 0x0000FF00) // LSB used for bank info
|
||||
#define AND_STRUCT_FIL_STATISTICS (AND_STRUCT_LAYER_FIL | 0x00000200) // LSB used for bank info
|
||||
#define AND_STRUCT_FIL_READPAGE (AND_STRUCT_LAYER_FIL | 0x00000300) // LSB used for bank info
|
||||
#define AND_STRUCT_FIL_STATISTICS_SIZE (AND_STRUCT_LAYER_FIL | 0x00000400) // LSB used for bank info
|
||||
#define AND_STRUCT_FIL_READTIMING (AND_STRUCT_LAYER_FIL | 0x00000500)
|
||||
#define AND_STRUCT_FIL_WRITETIMING (AND_STRUCT_LAYER_FIL | 0x00000600)
|
||||
#define AND_STRUCT_FIL_CHIPID (AND_STRUCT_LAYER_FIL | 0x00000700)
|
||||
#define AND_STRUCT_FIL_CHANNEL_BITMAP (AND_STRUCT_LAYER_FIL | 0x00000800)
|
||||
#define AND_STRUCT_FIL_UNIQUEID (AND_STRUCT_LAYER_FIL | 0x00000900)
|
||||
#define AND_STRUCT_FIL_HYNIX_BBT (AND_STRUCT_LAYER_FIL | 0x00000A00)
|
||||
#define AND_STRUCT_FIL_POWER_MODE (AND_STRUCT_LAYER_FIL | 0x00000B00)
|
||||
#define AND_STRUCT_FIL_NAND_LAYOUT (AND_STRUCT_LAYER_FIL | 0x00000C00)
|
||||
#define AND_STRUCT_FIL_SPARE_SIZE (AND_STRUCT_LAYER_FIL | 0x00000D00)
|
||||
#define AND_STRUCT_FIL_BITS_PER_CELL (AND_STRUCT_LAYER_FIL | 0x00000E00)
|
||||
#define AND_STRUCT_FIL_DEVICE_INFO (AND_STRUCT_LAYER_FIL | 0x00000F00)
|
||||
#define AND_STRUCT_FIL_DIES_PER_CE (AND_STRUCT_LAYER_FIL | 0x00001000)
|
||||
#define AND_STRUCT_FIL_BLOCKS_PER_CE (AND_STRUCT_LAYER_FIL | 0x00001100)
|
||||
#define AND_STRUCT_FIL_SET_TIMINGS (AND_STRUCT_LAYER_FIL | 0x00001200)
|
||||
#define AND_STRUCT_FIL_GET_TIMINGS (AND_STRUCT_LAYER_FIL | 0x00001300)
|
||||
#define AND_STRUCT_FIL_GET_CE_INFO (AND_STRUCT_LAYER_FIL | 0x00001400)
|
||||
#define AND_STRUCT_FIL_MFG_ID (AND_STRUCT_LAYER_FIL | 0x00001500)
|
||||
#define AND_STRUCT_FIL_FW_VERSION (AND_STRUCT_LAYER_FIL | 0x00001600)
|
||||
#define AND_STRUCT_FIL_PKG_ASSEMBLY_CODE (AND_STRUCT_LAYER_FIL | 0x00001700)
|
||||
#define AND_STRUCT_FIL_CONTROLLER_UID (AND_STRUCT_LAYER_FIL | 0x00001800)
|
||||
#define AND_STRUCT_FIL_CONTROLLER_HW_ID (AND_STRUCT_LAYER_FIL | 0x00001900)
|
||||
#define AND_STRUCT_FIL_LBAS_PER_PAGE (AND_STRUCT_LAYER_FIL | 0x00001A00)
|
||||
|
||||
// WMR structures
|
||||
#define AND_STRUCT_WMR_VERSION (AND_STRUCT_LAYER_WMR | 0x00000100)
|
||||
#define AND_STRUCT_WMR_DEVICEINFO (AND_STRUCT_LAYER_WMR | 0x00000200)
|
||||
#define AND_STRUCT_WMR_LAYOUT (AND_STRUCT_LAYER_WMR | 0x00000300)
|
||||
|
||||
// defines for device info types, these might move to an h file shared by all layers
|
||||
#define AND_DEVINFO_PAGES_PER_BLOCK (100)
|
||||
#define AND_DEVINFO_NUM_OF_CS (101)
|
||||
#define AND_DEVINFO_BBT_TYPE (102)
|
||||
#define AND_DEVINFO_BLOCKS_PER_CS (103)
|
||||
#define AND_DEVINFO_BYTES_PER_PAGE (104)
|
||||
#define AND_DEVINFO_BYTES_PER_SPARE (105)
|
||||
#define AND_DEVINFO_USER_BLOCKS_PER_CS (106)
|
||||
#define AND_DEVINFO_VENDOR_SPECIFIC_TYPE (107)
|
||||
#define AND_DEVINFO_REFRESH_THRESHOLD (108)
|
||||
#define AND_DEVINFO_BANKS_PER_CS (109)
|
||||
#define AND_DEVINFO_PAGES_PER_SUBLK (110)
|
||||
#define AND_DEVINFO_NUM_OF_BANKS (111)
|
||||
#define AND_DEVINFO_NUM_OF_USER_SUBLK (112)
|
||||
#define AND_DEVINFO_FTL_TYPE (113)
|
||||
#define AND_DEVINFO_BYTES_PER_BL_PAGE (114)
|
||||
#define AND_DEVINFO_CORRECTABLE_BITS (115)
|
||||
#define AND_DEVINFO_CORRECTABLE_SIZE (116)
|
||||
#define AND_DEVINFO_FTL_NEED_FORMAT (117)
|
||||
#define AND_DEVINFO_DIES_PER_CS (118)
|
||||
#define AND_DEVINFO_BLOCKS_PER_DIE (119)
|
||||
#define AND_DEVINFO_DIE_STRIDE (120)
|
||||
#define AND_DEVINFO_BLOCK_STRIDE (121)
|
||||
#define AND_DEVINFO_LAST_BLOCK (122)
|
||||
#define AND_DEVINFO_BLOCKS_PER_CAU (123)
|
||||
#define AND_DEVINFO_CAUS_PER_CE (124)
|
||||
#define AND_DEVINFO_SLC_PAGES_PER_BLOCK (125)
|
||||
#define AND_DEVINFO_MLC_PAGES_PER_BLOCK (126)
|
||||
#define AND_DEVINFO_MATCH_ODDEVEN_CAUS (127)
|
||||
#define AND_DEVINFO_BITS_PER_CAU_ADDRESS (128)
|
||||
#define AND_DEVINFO_BITS_PER_PAGE_ADDRESS (130)
|
||||
#define AND_DEVINFO_BITS_PER_BLOCK_ADDRESS (131)
|
||||
#define AND_DEVINFO_NUM_OF_CHANNELS (132)
|
||||
#define AND_DEVINFO_NUM_OF_CES_PER_CHANNEL (133)
|
||||
#define AND_DEVINFO_PPN_DEVICE (134)
|
||||
#define AND_DEVINFO_FIL_LBAS_PER_PAGE (135)
|
||||
#define AND_DEVINFO_FIL_META_VALID_BYTES (136)
|
||||
#define AND_DEVINFO_FIL_META_BUFFER_BYTES (137)
|
||||
#define AND_DEVINFO_FIL_MATCH_ODD_EVEN_BLKS (138)
|
||||
#define AND_DEVINFO_FIL_PREP_BUFFER_ENTRIES (139)
|
||||
#define AND_DEVINFO_VFL_AVAILABLE_VBAS (140)
|
||||
#define AND_DEVINFO_ADDR_BITS_BITS_PER_CELL (141)
|
||||
#define AND_DEVINFO_TOGGLE_DEVICE (142)
|
||||
#define AND_DEVINFO_L2V_POOL_SIZE (143)
|
||||
#define AND_DEVINFO_STREAM_BUFFER_MAX (144)
|
||||
|
||||
|
||||
// format params
|
||||
#define WMR_INIT_DISABLE_FORMAT (0x00000000) // default init value
|
||||
#define WMR_INIT_ALLOW_FORMAT (0x00000001) // allow normal unit format
|
||||
#define WMR_INIT_RUN_PRODUCTION_FORMAT (0x00000002) // call production format
|
||||
#define WMR_INIT_ALLOW_VSVFL (0x00000004) // allow VSVFL in case we format
|
||||
#define WMR_INIT_ALLOW_YAFTL (0x00000008) // allow VSVFL in case we format
|
||||
#define WMR_INIT_RUN_FTL_FORMAT (0x00000010) // call ftl format and change the FTL size
|
||||
#define WMR_INIT_SIGNATURE_IN_BLOCKZERO (0x00000020) // signature in block zero
|
||||
#define WMR_INIT_LOW_POWER_MODE (0x00000040) // driver should use minimum power until notified
|
||||
#define WMR_INIT_NAND_RESTORE (0x00000080) // force full nand restore during power up
|
||||
#define WMR_INIT_USE_DEV_UNIQUE_INFO (0x00000100) // allocate a partition for device unique info
|
||||
#define WMR_INIT_USE_DIAG_CTRL_INFO (0x00000200) // allocate a partition for diag control bits
|
||||
#define WMR_INIT_METADATA_WHITENING (0x00000400) // device should be formatted with metadata whitening
|
||||
#define WMR_INIT_METADATA_WHITENING_CHECK (0x00000800) // device should be formatted with metadata whitening if it already isn't
|
||||
#define _WMR_INIT_ALLOW_ANY_EPOCH (0x00001000) // driver will not fail security epoch check (deprecated)
|
||||
#define WMR_INIT_DISABLE_GC_IN_TRIM (0x00002000) // disable empty GC in trim
|
||||
#define WMR_INIT_SET_INDEX_CACHE_SIZE (0x00004000) // disable empty GC in trim
|
||||
#define WMR_INIT__USE_NEW_DUAL_CHANNEL_ADDRESS (0x00008000) // rdar://9159270
|
||||
#define WMR_INIT_OPEN_READONLY (0x00010000) // Disable writes/erase during open rdar://9407663
|
||||
#define WMR_INIT_USE_KEEPOUT_AS_BORROW (0x00020000)
|
||||
#ifdef AND_SIMULATOR
|
||||
#define WMR_INIT_IGNORE_ERASE_GAP (0x00040000)
|
||||
#endif
|
||||
|
||||
// flags for external VFL calls
|
||||
#define AND_EXTERNAL_VFL_TEST_PARTITION (0x00000000)
|
||||
#define AND_EXTERNAL_VFL_FTL_PARTITION (0x00000001)
|
||||
#define AND_EXTERNAL_VFL_FULL (0x00000002)
|
||||
|
||||
// factory test conditions
|
||||
#define VFL_BONFIRE_UNTESTED_CODE (0)
|
||||
#define VFL_BONFIRE_RMA_CODE (306)
|
||||
|
||||
// FIL defines
|
||||
typedef enum
|
||||
{
|
||||
INIT_BBT_TOSHIBA_MLC = 1,
|
||||
INIT_BBT_SAMSUNG_MLC = 2,
|
||||
INIT_BBT_HYNIX_MLC = 3,
|
||||
INIT_BBT_SAMSUNG_SLC = 4,
|
||||
INIT_BBT_INTEL_ONFI = 5,
|
||||
INIT_BBT_ONFI = 6,
|
||||
INIT_BBT_MICRON_ONFI = 7,
|
||||
INIT_BBT_SAMSUNG_MLC_8K = 8,
|
||||
INIT_BBT_SANDISK_MLC = 9,
|
||||
INIT_BBT_PPN = 10,
|
||||
INIT_BBT_BOGUS = 0x0FFFFFFF, // Force 4-byte enum field
|
||||
} CheckInitialBadType;
|
||||
|
||||
// format definitions
|
||||
#define VS_FMT_UNKNOWN 0x0000
|
||||
#define VS_FMT_SIMPLE 0x0001
|
||||
#define VS_FMT_TOSHIBA_TWO_DISTRICT 0x0010
|
||||
#define VS_FMT_TOSHIBA_TWO_DISTRICT_EXT 0x0011
|
||||
#define VS_FMT_2BANKS_MSB 0x0012
|
||||
#define VS_FMT_4BANKS_LSB_MSB 0x0013
|
||||
#define VS_FMT_2BANKS_LSB 0x0014
|
||||
#define VS_FMT_TOSHIBA_TWO_DIE 0x0015
|
||||
#define VS_FMT_4BANKS_LSB_MSB_NOPWR2 0x0016
|
||||
|
||||
// command definitions
|
||||
#define VS_CMD_UNKNOWN 0x0000
|
||||
#define VS_CMD_SIMPLE 0x0001
|
||||
#define VS_CMD_SAMSUNG_2P 0x0010
|
||||
#define VS_CMD_ONFI_2D 0x0011
|
||||
#define VS_CMD_ONFI_2P 0x0012
|
||||
#define VS_CMD_ONFI_2D_CACHE 0x0013
|
||||
#define VS_CMD_ONFI_2P_CACHE 0x0014
|
||||
#define VS_CMD_TOSHIBA_2P 0x0015
|
||||
#define VS_CMD_TOSHIBA_2P_CACHE 0x0016
|
||||
#define VS_CMD_TOSHIBA_2D 0x0017
|
||||
|
||||
typedef UInt32 VendorSpecificType;
|
||||
|
||||
#define VS_TYPE(cmd, fmt) (UInt32)(((UInt32)(cmd) << 16) | ((UInt32)(fmt) & 0x0000FFFF))
|
||||
#define VS_GET_CMD(vs) (((UInt32)(vs) >> 16))
|
||||
#define VS_GET_FMT(vs) (((UInt32)(vs) & 0x0000FFFF))
|
||||
|
||||
#define FIL_VS_UNKNOWN VS_TYPE(VS_CMD_UNKNOWN, VS_FMT_UNKNOWN)
|
||||
#define FIL_VS_SIMPLE VS_TYPE(VS_CMD_SIMPLE, VS_FMT_SIMPLE)
|
||||
// this is to make the current tables work...
|
||||
#define FIL_VS_HYNIX_2P VS_TYPE(VS_CMD_SAMSUNG_2P, VS_FMT_2BANKS_LSB)
|
||||
#define FIL_VS_ONFI_2D VS_TYPE(VS_CMD_ONFI_2D, VS_FMT_2BANKS_MSB)
|
||||
#define FIL_VS_ONFI_2P VS_TYPE(VS_CMD_ONFI_2P, VS_FMT_2BANKS_LSB)
|
||||
#define FIL_VS_ONFI_2P_2D VS_TYPE(VS_CMD_ONFI_2P, VS_FMT_4BANKS_LSB_MSB)
|
||||
#define FIL_VS_ONFI_2D_CACHE VS_TYPE(VS_CMD_ONFI_2D_CACHE, VS_FMT_2BANKS_MSB)
|
||||
#define FIL_VS_ONFI_2P_CACHE VS_TYPE(VS_CMD_ONFI_2P_CACHE, VS_FMT_2BANKS_LSB)
|
||||
#define FIL_VS_ONFI_2P_2D_CACHE VS_TYPE(VS_CMD_ONFI_2P_CACHE, VS_FMT_4BANKS_LSB_MSB)
|
||||
#define FIL_VS_SAMSUNG_2D VS_TYPE(VS_CMD_SIMPLE, VS_FMT_2BANKS_MSB)
|
||||
#define FIL_VS_SAMSUNG_2P_2D VS_TYPE(VS_CMD_SIMPLE, VS_FMT_4BANKS_LSB_MSB)
|
||||
#define FIL_VS_SAMSUNG_2P_2D_EXT VS_TYPE(VS_CMD_SIMPLE, VS_FMT_4BANKS_LSB_MSB_NOPWR2)
|
||||
#define FIL_VS_TOSHIBA_2P VS_TYPE(VS_CMD_TOSHIBA_2P, VS_FMT_TOSHIBA_TWO_DISTRICT)
|
||||
#define FIL_VS_TOSHIBA_2P_EXT VS_TYPE(VS_CMD_TOSHIBA_2P, VS_FMT_TOSHIBA_TWO_DISTRICT_EXT)
|
||||
#define FIL_VS_TOSHIBA_2P_CACHE VS_TYPE(VS_CMD_TOSHIBA_2P_CACHE, VS_FMT_TOSHIBA_TWO_DISTRICT)
|
||||
#define FIL_VS_TOSHIBA_2P_EXT_CACHE VS_TYPE(VS_CMD_TOSHIBA_2P_CACHE, VS_FMT_TOSHIBA_TWO_DISTRICT_EXT)
|
||||
#define FIL_VS_TOSHIBA_2D VS_TYPE(VS_CMD_TOSHIBA_2D, VS_FMT_TOSHIBA_TWO_DIE)
|
||||
|
||||
//CE status report definitions
|
||||
#define CE_STATUS_UNINITIALIZED ((UInt16)~0)
|
||||
#define PAGE_STATUS_UNINITIALIZED ((UInt32)~0)
|
||||
|
||||
//Enumeration for blocks that have failed erase
|
||||
#define BLOCK_STATUS_UNINITIALIZED ((UInt32)0xFFFFFFFF)
|
||||
|
||||
// =============================================================================
|
||||
// Power Mode
|
||||
// To be used with AND_FUNCTION_SET_POWER_MODE & AND_STRUCT_FIL_POWER_MODE
|
||||
#define NAND_POWER_MODE_UNKNOWN ((UInt32) 0)
|
||||
#define NAND_POWER_MODE_FULL_SPEED ((UInt32) 1)
|
||||
#define NAND_POWER_MODE_SINGLE_CE ((UInt32) 2)
|
||||
#define NAND_POWER_MODE_STANDBY ((UInt32) 3)
|
||||
|
||||
|
||||
#define NAND_DATA_REGION_SYSCFG ((UInt32)1)
|
||||
#define NAND_DATA_REGION_DIAG_CONTROL ((UInt32)0)
|
||||
|
||||
// Special Blcok Types - PPN VFL / FPart
|
||||
// Bit allocations:
|
||||
// [0-7] - code (uniquue per special block type - valid range is 0x00 - 0xEF
|
||||
// leaving the top to VFL Context
|
||||
// [8-13] - handler (how the special block shold be procesed - handler can be either supported
|
||||
// by FPart or other layers. handler handled by other layers can not be persistent.
|
||||
// [14] - persistent flag (1 - persistent, 0 - not persistent)
|
||||
// [15] - special bit flag (1 - special block, 0 - block is allocated to virtual block exported by vfl)
|
||||
|
||||
#define AND_SB_BIT_SPEICAL_FLAG (1 << 15) // if this bit is set the block is
|
||||
// NOT allocated to VBN
|
||||
// It is either a special block or
|
||||
// VFL context block
|
||||
|
||||
#define AND_SB_BIT_PERSISTENT_FLAG (1 << 14) // persistent type (need to survive loosing the signature)
|
||||
|
||||
#define andSBGetHandler(_x) ((UInt16)(((_x) & 0x3F00) >> 8))
|
||||
#define andSBSetHandler(_x) ((UInt16)(((_x) & 0x3F) << 8))
|
||||
|
||||
#define AND_SB_HANDLER_SINGLE_VERSION (1)
|
||||
#define AND_SB_HANDLER_MULTI_VERSION (2)
|
||||
#define AND_SB_HANDLER_NAND_BOOT (0x30)
|
||||
#define AND_SB_HANDLER_VFL_CXT (0x3F)
|
||||
|
||||
|
||||
#define andSBGetCode(_x) ((UInt16)((_x) & 0x00FF))
|
||||
#define andSBSetCode(_x) ((UInt16)((_x) & 0x00FF))
|
||||
|
||||
|
||||
#define AND_SB_CODE_DRIVER_SIGNATURE (0x01)
|
||||
#define AND_SB_CODE_BLOCK_ZERO (0x02)
|
||||
#define AND_SB_CODE_NAND_BOOT (0x03)
|
||||
#define AND_SB_CODE_DIAGNOSTICS (0x04)
|
||||
#define AND_SB_CODE_UNIQUE_INFO (0x05)
|
||||
#define AND_SB_CODE_KEEPOUT (0x06)
|
||||
|
||||
#define AND_SB_TYPE_DRIVER_SIGNATURE (AND_SB_BIT_SPEICAL_FLAG | AND_SB_BIT_PERSISTENT_FLAG | andSBSetHandler(AND_SB_HANDLER_SINGLE_VERSION) | andSBSetCode(AND_SB_CODE_DRIVER_SIGNATURE))
|
||||
#define AND_SB_TYPE_BLOCK_ZERO (AND_SB_BIT_SPEICAL_FLAG | andSBSetHandler(AND_SB_HANDLER_NAND_BOOT) | andSBSetCode(AND_SB_CODE_BLOCK_ZERO))
|
||||
#define AND_SB_TYPE_NAND_BOOT (AND_SB_BIT_SPEICAL_FLAG | andSBSetHandler(AND_SB_HANDLER_NAND_BOOT) | andSBSetCode(AND_SB_CODE_NAND_BOOT))
|
||||
#define AND_SB_TYPE_DIAGNOSTICS (AND_SB_BIT_SPEICAL_FLAG | AND_SB_BIT_PERSISTENT_FLAG | andSBSetHandler(AND_SB_HANDLER_SINGLE_VERSION) | andSBSetCode(AND_SB_CODE_DIAGNOSTICS))
|
||||
#define AND_SB_TYPE_UNIQUE_INFO (AND_SB_BIT_SPEICAL_FLAG | AND_SB_BIT_PERSISTENT_FLAG | andSBSetHandler(AND_SB_HANDLER_SINGLE_VERSION) | andSBSetCode(AND_SB_CODE_UNIQUE_INFO))
|
||||
#define AND_SB_TYPE_KEEPOUT_BOOT (AND_SB_BIT_SPEICAL_FLAG | andSBSetHandler(AND_SB_HANDLER_NAND_BOOT) | andSBSetCode(AND_SB_CODE_KEEPOUT))
|
||||
|
||||
#define NAND_TYPE_RAW (0)
|
||||
#define NAND_TYPE_PPN (1)
|
||||
|
||||
#define AND_SPARE_TYPE_REGION_FTL (0x00) // allowing FTL to use 5 bits for types
|
||||
#define AND_SPARE_TYPE_REGION_VFL (0x20) // allowing VFL to use 4 bits for types
|
||||
#define AND_SPARE_TYPE_REGION_FPART (0x30) // allowing FPART to use 4 bits for types
|
||||
#define AND_SPARE_TYPE_REGION_BFN (0x40) // allowing BFN to use 4 bits for types
|
||||
|
||||
// Get address special cases definitions
|
||||
#define AND_GET_ADDRESS_SPECIAL (0xFFFFFF80)
|
||||
#define AND_GET_ADDRESS_TRIMMED (AND_GET_ADDRESS_SPECIAL + 1)
|
||||
#define AND_GET_ADDRESS_OUT_OF_RANGE (AND_GET_ADDRESS_SPECIAL + 2)
|
||||
#define AND_GET_ADDRESS_CACHED_WRITE (AND_GET_ADDRESS_SPECIAL + 3)
|
||||
#define AND_GET_ADDRESS_UNINITIALIZED (0xFFFFFFFF)
|
||||
|
||||
#define AND_L2V_POOL_SIZE_UNSPECIFIED (0XFFFFFFFF)
|
||||
|
||||
#endif /* _AND_TYPES_H_ */
|
||||
|
||||
@@ -0,0 +1,212 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* COMPONENT : Rainbow */
|
||||
/* MODULE : FIL */
|
||||
/* NAME : Flash Interface Layer header file */
|
||||
/* FILE : FIL.h */
|
||||
/* PURPOSE : This file contains the definition and protypes of exported */
|
||||
/* functions for FIL of Whimory. */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* COPYRIGHT 2003-2005 SAMSUNG ELECTRONICS CO., LTD. */
|
||||
/* ALL RIGHTS RESERVED */
|
||||
/* */
|
||||
/* Permission is hereby granted to licensees of Samsung Electronics */
|
||||
/* Co., Ltd. products to use or abstract this computer program for the */
|
||||
/* sole purpose of implementing a product based on Samsung */
|
||||
/* Electronics Co., Ltd. products. No other rights to reproduce, use, */
|
||||
/* or disseminate this computer program, whether in part or in whole, */
|
||||
/* are granted. */
|
||||
/* */
|
||||
/* Samsung Electronics Co., Ltd. makes no representation or warranties */
|
||||
/* with respect to the performance of this computer program, and */
|
||||
/* specifically disclaims any responsibility for any damages, */
|
||||
/* special or consequential, connected with the use of this program. */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* REVISION HISTORY */
|
||||
/* */
|
||||
/* 19-JUL-2005 [Jaesung Jung] : first writing */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef _FIL_H_
|
||||
#define _FIL_H_
|
||||
|
||||
#include "ANDTypes.h"
|
||||
#include "WMRFeatures.h"
|
||||
#include "PPN_FIL.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Return value of FIL_XXX() & physical interface function pointer */
|
||||
/*****************************************************************************/
|
||||
#define FIL_SUCCESS ANDErrorCodeOk
|
||||
#define FIL_SUCCESS_CLEAN ANDErrorCodeCleanOk
|
||||
#define FIL_CRITICAL_ERROR ANDErrorCodeHwErr
|
||||
#define FIL_U_ECC_ERROR ANDErrorCodeUserDataErr
|
||||
#define FIL_WRITE_FAIL_ERROR ANDErrorWriteFailureErr
|
||||
#define FIL_UNSUPPORTED_ERROR ANDErrorCodeNotSupportedErr
|
||||
|
||||
/*****************************************************************************/
|
||||
/* FIL Function Table Data Structures */
|
||||
/*****************************************************************************/
|
||||
typedef struct
|
||||
{
|
||||
void (*Reset)(void);
|
||||
Int32 (*ReadWithECC)(UInt16 wBank, UInt32 nPpn, UInt8 *pDBuf, UInt8 *pSBuf, UInt8 * pbCorrectedBits, UInt8 * pdwaSectorStats, BOOL32 bDisableWhitening);
|
||||
Int32 (*ReadNoECC)(UInt16 wBank, UInt32 nPpn, UInt8 *pDBuf, UInt8 *pSBuf);
|
||||
Int32 (*ReadMultiplePages)(UInt32 * padwPpn, UInt8* pDBuf, UInt8* pSBuf, UInt16 wNumOfPagesToRead, UInt8 * pbCorrectedBits, UInt8 * pdwaSectorStats, BOOL32 bDisableWhitening);
|
||||
Int32 (*ReadScatteredPages)(UInt16 * pawBank, UInt32 * padwPpn, UInt8* pDBuf, UInt8* pSBuf, UInt16 wNumOfPagesToRead, UInt8 * pbCorrectedBits, UInt8 * pdwaSectorStats, BOOL32 bDisableWhitening);
|
||||
Int32 (*ReadMaxECC)(UInt16 wBank, UInt32 nPpn, UInt8 *pDBuf);
|
||||
Int32 (*ReadBLPage)(UInt16 wCS, UInt32 dwPpn, UInt8 *pabData);
|
||||
Int32 (*WriteBLPage)(UInt16 wCS, UInt32 dwPpn, UInt8 *pabData);
|
||||
BOOL32 (*Write2ndBootLoader)(UInt8* padw2ndBootLoader, UInt32 dwBLPageCount, UInt32 dwBLOffsetPage);
|
||||
BOOL32 (*Read2ndBootLoader)(UInt8* padw2ndBootLoader, UInt32 dwBLPageCount);
|
||||
Int32 (*Erase)(UInt16 wBank, UInt32 wPbn);
|
||||
Int32 (*Write)(UInt16 wBank, UInt32 nPpn, UInt8 *pDBuf, UInt8 *pSBuf, BOOL32 bDisableWhitening);
|
||||
Int32 (*WriteScatteredPages)(UInt16 * pawBanks, UInt32 * padwPpn, UInt8 * pabDataBuf, UInt8 * pabMetaBuf, UInt16 wNumOfPagesToWrite, UInt16 * pwFailingCE, BOOL32 bDisableWhitening, UInt32 *pwFailingPageNum);
|
||||
Int32 (*WriteMultiplePages)(UInt32 * padwPpn, UInt8* pDBuf, UInt8* pSBuf, UInt16 wNumOfPagesToWrite, BOOL32 boolAligned, BOOL32 boolCorrectBank, UInt16 * pwFailingCE, BOOL32 bDisableWhitening, UInt32 *pwFailingPageNum);
|
||||
Int32 (*EraseMultiple)(UInt16 *pawPbn, BOOL32 boolAligned, BOOL32 boolCorrectBank, UInt16 *failingCE, UInt32 *failingBlock);
|
||||
Int32 (*WriteNoECC)(UInt16 wBank, UInt32 nPpn, UInt8 *pDBuf, UInt8 *pSBuf);
|
||||
Int32 (*WriteMaxECC)(UInt16 wBank, UInt32 nPpn, UInt8 *pDBuf);
|
||||
void (*CalcCurrentTiming)(void);
|
||||
void (*Notify)(UInt32 notifyCode);
|
||||
BOOL32 (*Get2ndBootLoaderInfo)(UInt32 * pdwMax2ndLoaderSize, UInt32 * pdw2ndLoaderPageSize);
|
||||
UInt32 (*GetDeviceInfo)(UInt32 dwParamType);
|
||||
void (*SetDeviceInfo)(UInt32 dwParamType, UInt32 dwVal);
|
||||
void (*SetWhiteningState)(BOOL32 enable);
|
||||
void (*SetWhiteningMetadataState)(BOOL32 enable);
|
||||
void (*RegisterCurrentTransaction)(UInt64 ddwLba, UInt32 dwNum, void * pDest);
|
||||
Int32 (*UpdateFirmware)(UInt16 wCS, UInt8 *pDBuf, UInt32 length);
|
||||
void (*PerformCommandList)(PPNCommandStruct **commands, UInt32 num_commands);
|
||||
} LowFuncTbl;
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Notification values */
|
||||
/*****************************************************************************/
|
||||
#define AND_NOTIFY_REFORMAT 1
|
||||
#define AND_NOTIFY_RECOVER 2
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Statistics gathering definitions */
|
||||
/*****************************************************************************/
|
||||
typedef struct _FILStatistics
|
||||
{
|
||||
UInt64 ddwPagesWrittenCnt;
|
||||
UInt64 ddwPagesReadCnt;
|
||||
UInt64 ddwBlocksErasedCnt;
|
||||
UInt64 ddwResetCallCnt;
|
||||
UInt64 ddwReadWithECCCallCnt;
|
||||
UInt64 ddwReadMaxECCCallCnt;
|
||||
UInt64 ddwReadNoECCCallCnt;
|
||||
UInt64 ddwReadMultipleCallCnt;
|
||||
UInt64 ddwReadScatteredCallCnt;
|
||||
UInt64 ddwWriteSingleCallCnt;
|
||||
UInt64 ddwWriteMaxECCCallCnt;
|
||||
UInt64 ddwWriteMultipleCallCnt;
|
||||
UInt64 ddwWriteScatteredCallCnt;
|
||||
UInt64 ddwSingleEraseCallCnt;
|
||||
UInt64 ddwMultipleEraseCallCnt;
|
||||
UInt64 ddwReadCleanCnt;
|
||||
UInt64 ddwReadECCErrorCnt;
|
||||
UInt64 ddwReadHWErrorCnt;
|
||||
UInt64 ddwWriteHWErrCnt;
|
||||
UInt64 ddwWriteNANDErrCnt;
|
||||
UInt64 ddwEraseHWErrCnt;
|
||||
UInt64 ddwEraseNANDErrCnt;
|
||||
UInt64 addwReadBitFlipsCnt[FIL_MAX_ECC_CORRECTION + 1]; // 0 to max number of corrected bits
|
||||
UInt64 ddwTimeoutCnt;
|
||||
UInt64 ddwPartialUECCCnt;
|
||||
UInt64 ddwPartialCleanCnt;
|
||||
UInt64 ddwReadRefreshCnt;
|
||||
UInt64 ddwReadRetireCnt;
|
||||
} FILStatistics;
|
||||
|
||||
#define FIL_STATISTICS_DESCREPTION { \
|
||||
"ddwPagesWrittenCnt", \
|
||||
"ddwPagesReadCnt", \
|
||||
"ddwBlocksErasedCnt", \
|
||||
"ddwResetCallCnt", \
|
||||
"ddwReadWithECCCallCnt", \
|
||||
"ddwReadMaxECCCallCnt", \
|
||||
"ddwReadNoECCCallCnt", \
|
||||
"ddwReadMultipleCallCnt", \
|
||||
"ddwReadScatteredCallCnt", \
|
||||
"ddwWriteSingleCallCnt", \
|
||||
"ddwWriteMaxECCCallCnt", \
|
||||
"ddwWriteMultipleCallCnt", \
|
||||
"ddwWriteScatteredCallCnt", \
|
||||
"ddwSingleEraseCallCnt", \
|
||||
"ddwMultipleEraseCallCnt", \
|
||||
"ddwReadCleanCnt", \
|
||||
"ddwReadECCErrorCnt", \
|
||||
"ddwReadHWErrorCnt", \
|
||||
"ddwWriteHWErrCnt", \
|
||||
"ddwWriteNANDErrCnt", \
|
||||
"ddwEraseHWErrCnt", \
|
||||
"ddwEraseNANDErrCnt", \
|
||||
"addwReadBitFlipsCnt[0]", \
|
||||
"addwReadBitFlipsCnt[1]", \
|
||||
"addwReadBitFlipsCnt[2]", \
|
||||
"addwReadBitFlipsCnt[3]", \
|
||||
"addwReadBitFlipsCnt[4]", \
|
||||
"addwReadBitFlipsCnt[5]", \
|
||||
"addwReadBitFlipsCnt[6]", \
|
||||
"addwReadBitFlipsCnt[7]", \
|
||||
"addwReadBitFlipsCnt[8]", \
|
||||
"addwReadBitFlipsCnt[9]", \
|
||||
"addwReadBitFlipsCnt[10]", \
|
||||
"addwReadBitFlipsCnt[11]", \
|
||||
"addwReadBitFlipsCnt[12]", \
|
||||
"addwReadBitFlipsCnt[13]", \
|
||||
"addwReadBitFlipsCnt[14]", \
|
||||
"addwReadBitFlipsCnt[15]", \
|
||||
"addwReadBitFlipsCnt[16]", \
|
||||
"addwReadBitFlipsCnt[17]", \
|
||||
"addwReadBitFlipsCnt[18]", \
|
||||
"addwReadBitFlipsCnt[19]", \
|
||||
"addwReadBitFlipsCnt[20]", \
|
||||
"addwReadBitFlipsCnt[21]", \
|
||||
"addwReadBitFlipsCnt[22]", \
|
||||
"addwReadBitFlipsCnt[23]", \
|
||||
"addwReadBitFlipsCnt[24]", \
|
||||
"addwReadBitFlipsCnt[25]", \
|
||||
"addwReadBitFlipsCnt[26]", \
|
||||
"addwReadBitFlipsCnt[27]", \
|
||||
"addwReadBitFlipsCnt[28]", \
|
||||
"addwReadBitFlipsCnt[29]", \
|
||||
"addwReadBitFlipsCnt[30]", \
|
||||
"ddwTimeoutCnt", \
|
||||
"ddwPartialUECCCnt", \
|
||||
"ddwPartialCleanCnt", \
|
||||
"ddwReadRefreshCnt", \
|
||||
"ddwReadRetireCnt", \
|
||||
}
|
||||
|
||||
// Presented to the FMSS as an 18 word array
|
||||
typedef struct
|
||||
{
|
||||
UInt32 dwReadNoECCCorrection;
|
||||
UInt32 adwReadBitFlipsCnt[FIL_MAX_ECC_CORRECTION];
|
||||
UInt32 dwReadUncorrectableECCError;
|
||||
} CSStatistics;
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Exported Function Prototype of FIL */
|
||||
/*****************************************************************************/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
Int32 FIL_Init(void);
|
||||
void FIL_Close(void);
|
||||
LowFuncTbl *FIL_GetFuncTbl(void);
|
||||
BOOL32 FIL_GetStruct(UInt32 dwStructType, void * pvoidStructBuffer, UInt32 * pdwStructSize);
|
||||
BOOL32 FIL_SetStruct(UInt32 dwStructType, void * pvoidStructBuffer, UInt32 dwStructSize);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* _FIL_H_ */
|
||||
@@ -0,0 +1,62 @@
|
||||
#ifndef _FIL_TYPES_H_
|
||||
#define _FIL_TYPES_H_
|
||||
|
||||
#include "ANDTypes.h"
|
||||
|
||||
// physical device info (replacing stDeviceInfo)
|
||||
typedef struct
|
||||
{
|
||||
UInt32 dwDevID; /* Device ID */
|
||||
UInt16 wNumOfCS; /* number of CS */
|
||||
UInt16 wBlocksPerCS; /* Number of Blocks */
|
||||
UInt16 wPagesPerBlock; /* Pages per block */
|
||||
UInt16 wSectorsPerPage; /* Sectors per page */
|
||||
UInt16 wSpareBytesPerPage; /* Spare bytes per page */
|
||||
UInt16 wBanksPerCS;
|
||||
UInt16 wDiesPerCS;
|
||||
UInt16 wBlocksPerDie;
|
||||
UInt16 wDieStride;
|
||||
UInt16 wBlockStride;
|
||||
UInt16 wLastBlock;
|
||||
UInt16 wUserBlocksPerCS;
|
||||
|
||||
CheckInitialBadType checkInitialBadType;
|
||||
VendorSpecificType vendorSpecificType;
|
||||
UInt8 bECCThresholdBits;
|
||||
UInt8 bECCCorrectableBits;
|
||||
|
||||
// timing
|
||||
UInt8 bWriteCycleNanosecs;
|
||||
UInt8 bWriteSetupNanosecs;
|
||||
UInt8 bWriteHoldNanosecs;
|
||||
|
||||
// read cycle
|
||||
UInt8 bReadCycleNanosecs;
|
||||
UInt8 bReadSetupNanosecs;
|
||||
UInt8 bReadHoldNanosecs;
|
||||
|
||||
// read window
|
||||
UInt8 bReadDelayNanosecs;
|
||||
UInt8 bReadValidNanosecs;
|
||||
|
||||
// Additions, to keep above footprint the same
|
||||
UInt32 wNumOfBusses; /* number of busses */
|
||||
UInt32 dwBlocksPerCAU;
|
||||
UInt32 dwCAUsPerCE;
|
||||
UInt32 dwSLCPagesPerBlock;
|
||||
UInt32 dwMLCPagesPerBlock;
|
||||
UInt32 dwMatchOddEvenCAUs;
|
||||
UInt32 dwBitsPerCAUAddress;
|
||||
UInt32 dwBitsPerPageAddress;
|
||||
UInt32 dwBitsPerBlockAddress;
|
||||
UInt32 ppn;
|
||||
UInt32 dwPpnVersion;
|
||||
UInt32 toggle;
|
||||
UInt32 dwValidMetaPerLogicalPage;
|
||||
UInt32 dwTotalMetaPerLogicalPage;
|
||||
UInt32 dwLogicalPageSize;
|
||||
UInt32 dwMaxTransactionSize;
|
||||
UInt8 bAddrBitsForBitsPerCell;
|
||||
} FILDeviceInfo;
|
||||
|
||||
#endif /* _FIL_TYPES_H_ */
|
||||
@@ -0,0 +1,155 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* COMPONENT : Rainbow */
|
||||
/* MODULE : Virtual Flash Layer */
|
||||
/* NAME : VFL header file */
|
||||
/* FILE : VFL.h */
|
||||
/* PURPOSE : This file contains the definition and protypes of exported */
|
||||
/* functions for VFL. */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* COPYRIGHT 2003-2005 SAMSUNG ELECTRONICS CO., LTD. */
|
||||
/* ALL RIGHTS RESERVED */
|
||||
/* */
|
||||
/* Permission is hereby granted to licensees of Samsung Electronics */
|
||||
/* Co., Ltd. products to use or abstract this computer program for the */
|
||||
/* sole purpose of implementing a product based on Samsung */
|
||||
/* Electronics Co., Ltd. products. No other rights to reproduce, use, */
|
||||
/* or disseminate this computer program, whether in part or in whole, */
|
||||
/* are granted. */
|
||||
/* */
|
||||
/* Samsung Electronics Co., Ltd. makes no representation or warranties */
|
||||
/* with respect to the performance of this computer program, and */
|
||||
/* specifically disclaims any responsibility for any damages, */
|
||||
/* special or consequential, connected with the use of this program. */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* REVISION HISTORY */
|
||||
/* */
|
||||
/* 18-JUL-2005 [Jaesung Jung] : first writing */
|
||||
/* 31-MAR-2006 [Yangsup Lee ] : support ftl meta block wear leveling */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef _UNDER_VFL_H_
|
||||
#define _UNDER_VFL_H_
|
||||
#include "FIL.h"
|
||||
/*****************************************************************************/
|
||||
/* Type definition of checksum (confirm) state */
|
||||
/*****************************************************************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/* exported function prototype of VFL */
|
||||
/*****************************************************************************/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SIGNATURE_STYLE_BLOCKZERO_NOHEADER = 100,
|
||||
SIGNATURE_STYLE_RESERVEDBLOCK_HEADER = 101,
|
||||
SIGNATURE_STYLE_NOTSET = 250,
|
||||
} FPartSignatureStyle;
|
||||
|
||||
// Forward declare VFL
|
||||
//typedef struct _VFLFunctions VFLFunctions;
|
||||
struct _VFLFunctions;
|
||||
|
||||
#define FPART_INIT_OPTION_DEV_UNIQUE (1 << 0)
|
||||
#define FPART_INIT_OPTION_DIAG_CTRL (1 << 1)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
#ifndef AND_READONLY
|
||||
BOOL32 (*WriteInitialBBT)(void);
|
||||
Int32 (*FactoryReformat)(BOOL32 Force, BOOL32 boolEraseBlockZero, UInt32 dwBootAreaSize);
|
||||
BOOL32 (*WriteDeviceUniqueInfo)(UInt8 * pabData, UInt32 dwDataBufferSize);
|
||||
BOOL32 (*WriteDiagnosticInfo)(UInt8 * pabData, UInt32 dwDataBufferSize);
|
||||
BOOL32 (*WriteSignature)(void * pvoidSignature, UInt32 dwSignatureSize);
|
||||
BOOL32 (*WriteSpecialBlock)(void * data, UInt32 data_size, UInt16 type);
|
||||
#endif // ! AND_READONLY
|
||||
BOOL32 (*Neuralize)(void);
|
||||
BOOL32 (*ReadDeviceUniqueInfo)(UInt8 * pabData, UInt32 dwDataBufferSize);
|
||||
BOOL32 (*ReadDiagnosticInfo)(UInt8 * pabData, UInt32 dwDataBufferSize);
|
||||
BOOL32 (*VerifyProductionFormat)(void);
|
||||
BOOL32 (*ReadSignature)(void * pvoidSignature, UInt32 dwSignatureSize);
|
||||
BOOL32 (*Init)(LowFuncTbl *pFILFunctions, UInt32 dwOptions);
|
||||
void (*SetSignatureStyle)(void * pvoidFPartFunctions,
|
||||
FPartSignatureStyle fpartSignatureStyle);
|
||||
BOOL32 (*validateSignatureLocation)(void * signLocationPtr );
|
||||
LowFuncTbl* (*GetLowFuncTbl)(void);
|
||||
UInt32 (*GetMinorVersion)(void);
|
||||
BOOL32 (*Format)(struct _VFLFunctions *pVFL, UInt32 dwOptions);
|
||||
BOOL32 (*AllocateSpecialBlockType)(SpecialBlockAddress *blocks, UInt16 count, UInt16 type);
|
||||
BOOL32 (*IsSpecialBlockTypeAllocated)(UInt16 type);
|
||||
BOOL32 (*MapSpecialBlocks)(SpecialBlockAddress *blocks, UInt16 *types, UInt16 *count);
|
||||
BOOL32 (*ReadSpecialBlock)(void *data, UInt32 data_size, UInt16 type);
|
||||
void (*ChangeCacheState)(BOOL32 validate);
|
||||
void* (*GetSingleCommandStruct)(void); // allow vfl and fpart to share single operation struct
|
||||
void (*Close)(void);
|
||||
} FPartFunctions;
|
||||
|
||||
void FPart_Register(FPartFunctions * pFPartFunctions);
|
||||
void PPNFPart_Register(FPartFunctions * pFPartFunctions);
|
||||
|
||||
#define PPN_FPart_MAJOR_VER (0)
|
||||
FPartFunctions *PPN_FPart_GetFunctions(void);
|
||||
|
||||
BOOL32 VFL_ReadBBT(UInt16 wCS, UInt8 * pBBT);
|
||||
BOOL32 VFL_ReadBBTWithoutSpecial(UInt16 wCS, UInt8 * pBBT);
|
||||
|
||||
/*
|
||||
|
||||
NAME
|
||||
_MarkBlockAsBadInBBT
|
||||
DESCRIPTION
|
||||
This define marks block as bad in the bbt.
|
||||
PARAMETERS
|
||||
pBBT [IN] bbt buffer
|
||||
idx [IN] block index
|
||||
RETURN VALUES
|
||||
none
|
||||
NOTES
|
||||
|
||||
*/
|
||||
|
||||
#define _MarkBlockAsBadInBBT(pBBT, idx) \
|
||||
{ \
|
||||
UInt16 dByteLocation; \
|
||||
UInt8 bBit; \
|
||||
dByteLocation = ((UInt16)(idx)) >> 3; \
|
||||
bBit = (UInt8)(~(1 << (((UInt8)(idx)) & 0x07))); \
|
||||
((UInt8 *)(pBBT))[dByteLocation] &= bBit; \
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
NAME
|
||||
_MarkBlockAsGoodInBBT
|
||||
DESCRIPTION
|
||||
This define marks block as good in the bbt.
|
||||
PARAMETERS
|
||||
pBBT [IN] bbt buffer
|
||||
idx [IN] block index
|
||||
RETURN VALUES
|
||||
none
|
||||
NOTES
|
||||
|
||||
*/
|
||||
#define _MarkBlockAsGoodInBBT(pBBT, idx) \
|
||||
{ \
|
||||
UInt16 dByteLocation; \
|
||||
UInt8 bBit; \
|
||||
dByteLocation = ((UInt16)(idx)) >> 3; \
|
||||
bBit = (1 << (((UInt8)(idx)) & 0x07)); \
|
||||
((UInt8 *)(pBBT))[dByteLocation] |= bBit; \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* _UNDER_VFL_H_ */
|
||||
@@ -0,0 +1,265 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* COMPONENT : Rainbow */
|
||||
/* MODULE : FTL */
|
||||
/* NAME : FTL header file */
|
||||
/* FILE : FTL.h */
|
||||
/* PURPOSE : This file contains the definition and protypes of exported */
|
||||
/* functions for FTL. */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* COPYRIGHT 2003-2005 SAMSUNG ELECTRONICS CO., LTD. */
|
||||
/* ALL RIGHTS RESERVED */
|
||||
/* */
|
||||
/* Permission is hereby granted to licensees of Samsung Electronics */
|
||||
/* Co., Ltd. products to use or abstract this computer program for the */
|
||||
/* sole purpose of implementing a product based on Samsung */
|
||||
/* Electronics Co., Ltd. products. No other rights to reproduce, use, */
|
||||
/* or disseminate this computer program, whether in part or in whole, */
|
||||
/* are granted. */
|
||||
/* */
|
||||
/* Samsung Electronics Co., Ltd. makes no representation or warranties */
|
||||
/* with respect to the performance of this computer program, and */
|
||||
/* specifically disclaims any responsibility for any damages, */
|
||||
/* special or consequential, connected with the use of this program. */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* REVISION HISTORY */
|
||||
/* */
|
||||
/* 19-JUL-2005 [Jaesung Jung] : first writing */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
#include "VFL.h"
|
||||
#ifndef _FTL_H_
|
||||
#define _FTL_H_
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Return value of FTL_XXX() */
|
||||
/*****************************************************************************/
|
||||
#define FTL_SUCCESS ANDErrorCodeOk
|
||||
#define FTL_CRITICAL_ERROR ANDErrorCodeHwErr
|
||||
#define FTL_USERDATA_ERROR ANDErrorCodeUserDataErr
|
||||
#define FTL_OUT_OF_RANGE_ERROR ANDErrorCodeOutOfRangeErr
|
||||
#define FTL_ALIGNMENT_ERROR ANDErrorCodeAlignmentErr
|
||||
|
||||
/*****************************************************************************/
|
||||
/* exported function prototype of FTL */
|
||||
/*****************************************************************************/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt64 lba;
|
||||
UInt64 span;
|
||||
} FTLExtent_t;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Int32 (*Init)(VFLFunctions *pVFLFunctions);
|
||||
Int32 (*Open)(UInt32 *pTotalScts, UInt32 * pdwSectorSize, BOOL32 nandFullFormat, BOOL32 justFormatted, UInt32 minor_ver, UInt32 dwOptions);
|
||||
|
||||
Int32 (*Read)(UInt32 nLpn, UInt32 nNumOfScts, UInt8 *pBuf);
|
||||
Int32 (*ReadSpans)(FTLExtent_t *extents, UInt32 numExtents, UInt8 *pBuf);
|
||||
void (*Close)(void);
|
||||
BOOL32 (*GetStruct)(UInt32 dwStructType, void * pvoidStructBuffer, UInt32 * pdwStructSize);
|
||||
|
||||
#ifndef AND_READONLY
|
||||
UInt32 (*ConvertUserMBtoFTLSuperblocks)(VFLFunctions *pVFLFunctions, UInt32 dwUserMBs);
|
||||
Int32 (*Write)(UInt32 nLpn, UInt32 nNumOfScts, UInt8 *pBuf, BOOL32 isStatic);
|
||||
Int32 (*Format)(UInt32 dwOptions);
|
||||
Int32 (*WearLevel)(void);
|
||||
Int32 (*IdleGC)();
|
||||
Int32 (*Unmap)(FTLExtent_t *extents, UInt32 numExtents);
|
||||
BOOL32 (*GarbageCollect)(void);
|
||||
BOOL32 (*ShutdownNotify)(BOOL32 boolMergeLogs);
|
||||
BOOL32 (*Drain)(void);
|
||||
BOOL32 (*WriteStats)(void);
|
||||
#endif
|
||||
|
||||
UInt32 (*GetMinorVersion)(void);
|
||||
} FTLFunctions;
|
||||
|
||||
void FTL_Register(FTLFunctions * pFTLFunctions);
|
||||
#if (defined (AND_SUPPORT_YAFTL) && AND_SUPPORT_YAFTL)
|
||||
void YAFTL_Register(FTLFunctions * pFTLFunctions);
|
||||
#define YAFTL_PPN_MAJOR_VER (0)
|
||||
FTLFunctions *YAFTL_PPN_Register(void);
|
||||
#define SFTL_PPN_MAJOR_VER (1)
|
||||
FTLFunctions *SFTL_PPN_Register(void);
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* statistics gathering constants */
|
||||
/*****************************************************************************/
|
||||
|
||||
#define FTL_RC_BIN_SIZE(l) ((l)/FTL_NUM_RC_BINS)
|
||||
#define FTL_NUM_RC_BINS (100)
|
||||
|
||||
#define FTL_EC_BIN_SIZE (FTL_MAX_EC_BIN_VAL/FTL_NUM_EC_BINS)
|
||||
#define FTL_MAX_EC_BIN_VAL (5000)
|
||||
#define FTL_NUM_EC_BINS (100)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 maxValue;
|
||||
UInt32 binCount;
|
||||
UInt16 usage[0];
|
||||
} FTLBinsStruct;
|
||||
|
||||
// FTL statistics X-macro:
|
||||
// this defines all of the stats currently known to SFTL in key name / serialized
|
||||
// key number form. Stats users (parsers, savers, etc) define X_FTL_doStat to do
|
||||
// something meaningful.
|
||||
// The trivial case is the construction of s_statkey_e enum, which provides to C
|
||||
// code an enumeration of the key name to the key number.
|
||||
// A stat saver, for instance, compare a key from a blob to the key macro which
|
||||
// is currently being expanded; if they match, put into a variable inside a struct
|
||||
// that matches the name of the stat.
|
||||
// A parser, on the other hand, would convert the symbol into a C string using
|
||||
// the # preprocessor operator. It then has a string representation of the key
|
||||
// name that it can print or add to internal data structures for future use.
|
||||
//
|
||||
// Let's dissect the enum creation:
|
||||
// #undef X_FTL_doStat
|
||||
// -- this undefines the X macro, in case it was previously defined
|
||||
// #define X_FTL_doStat(_part, _val) S_STATKEY_ ## _part = (_val),
|
||||
// -- Each time X_FTL_doStat is invoked below, it will take the token, paste
|
||||
// -- S_STATKEY_ in front, and assign it the value. For instance, this:
|
||||
// -- X_FTL_doStat(lbas_read, 1)
|
||||
// -- becomes:
|
||||
// -- S_STATKEY_ ## lbas_read = (1),
|
||||
// -- which is interpreted by the preprocessor to mean:
|
||||
// -- S_STATKEY_lbas_read = (1),
|
||||
// -- Thus, we've created an enumeration without repeating the origial content.
|
||||
// typedef enum {
|
||||
// FTL_doAllStats
|
||||
// -- this invokes the X macro for all of the ones in the doAllStats list
|
||||
// S_STATKEY_VFL = 255,
|
||||
// S_STATKEY_FIL = 254,
|
||||
// -- these are special cases
|
||||
// } s_statkey_e;
|
||||
// -- and we're done! We now have something that looks like:
|
||||
// typedef enum {
|
||||
// S_STATKEY_lbas_read = (1),
|
||||
// S_STATKEY_lbas_written = (2),
|
||||
// ...
|
||||
// S_STATKEY_VFL = 255,
|
||||
// S_STATKEY_VFL = 254,
|
||||
// } s_statkey_e;
|
||||
// The neat part is the knowledge of key name/key number is centralized;
|
||||
// no repetition is required.
|
||||
|
||||
#undef X_FTL_doStat
|
||||
#define FTL_doAllStats \
|
||||
X_FTL_doStat(lbas_read, 1) \
|
||||
X_FTL_doStat(lbas_written, 2) \
|
||||
X_FTL_doStat(lbas_gc, 3) \
|
||||
X_FTL_doStat(lbas_flatten, 4) \
|
||||
X_FTL_doStat(xacts_read, 5) \
|
||||
X_FTL_doStat(xacts_write, 6) \
|
||||
X_FTL_doStat(data_gc, 7) \
|
||||
X_FTL_doStat(zero_valid_cross, 8) \
|
||||
X_FTL_doStat(valid_lbas, 9) \
|
||||
X_FTL_doStat(free_sb, 10) \
|
||||
X_FTL_doStat(data_sb, 11) \
|
||||
X_FTL_doStat(cxt_sb, 12) \
|
||||
X_FTL_doStat(dead_sb, 13) \
|
||||
X_FTL_doStat(boot_count, 14) \
|
||||
X_FTL_doStat(refresh_gcs, 15) \
|
||||
X_FTL_doStat(readCount_gcs, 16) \
|
||||
X_FTL_doStat(wearLev_gcs, 17) \
|
||||
X_FTL_doStat(shutdowns, 18) \
|
||||
X_FTL_doStat(lbas_read_1, 19) \
|
||||
X_FTL_doStat(lbas_read_2, 20) \
|
||||
X_FTL_doStat(lbas_read_3, 21) \
|
||||
X_FTL_doStat(lbas_read_4, 22) \
|
||||
X_FTL_doStat(lbas_read_5, 23) \
|
||||
X_FTL_doStat(lbas_read_6, 24) \
|
||||
X_FTL_doStat(lbas_read_7, 25) \
|
||||
X_FTL_doStat(lbas_read_8, 26) \
|
||||
X_FTL_doStat(lbas_read_over_8, 27) \
|
||||
X_FTL_doStat(lbas_write_1, 28) \
|
||||
X_FTL_doStat(lbas_write_2, 29) \
|
||||
X_FTL_doStat(lbas_write_3, 30) \
|
||||
X_FTL_doStat(lbas_write_4, 31) \
|
||||
X_FTL_doStat(lbas_write_5, 32) \
|
||||
X_FTL_doStat(lbas_write_6, 33) \
|
||||
X_FTL_doStat(lbas_write_7, 34) \
|
||||
X_FTL_doStat(lbas_write_8, 35) \
|
||||
X_FTL_doStat(lbas_write_over_8, 36) \
|
||||
X_FTL_doStat(L2V_pool_free, 37) \
|
||||
X_FTL_doStat(L2V_pool_count, 38) \
|
||||
X_FTL_doStat(lbas_written_static, 39) \
|
||||
X_FTL_doStat(lbas_written_dynamic, 40) \
|
||||
X_FTL_doStat(unclean_boot_count, 41) \
|
||||
X_FTL_doStat(span_xacts_read, 42) \
|
||||
X_FTL_doStat(span_freebies_read, 43) \
|
||||
// blank
|
||||
|
||||
#undef X_FTL_doStat
|
||||
#define X_FTL_doStat(_part, _val) S_STATKEY_ ## _part = (_val),
|
||||
typedef enum {
|
||||
FTL_doAllStats
|
||||
S_STATKEY_VFL = 255,
|
||||
S_STATKEY_FIL = 254,
|
||||
} s_statkey_e;
|
||||
#undef X_FTL_doStat
|
||||
|
||||
#define FTL_makeStatParser(_fname, _VFLFunc, _FILFunc) \
|
||||
void (_fname)(const UInt8 *buf, UInt32 bufSize) \
|
||||
{ \
|
||||
UInt32 len; \
|
||||
UInt32 key, size; \
|
||||
UInt32 *buf32; \
|
||||
UInt64 val64; \
|
||||
\
|
||||
if (bufSize < sizeof(len)) \
|
||||
return; \
|
||||
\
|
||||
len = *(UInt32*)buf; \
|
||||
buf += sizeof(len); \
|
||||
bufSize -= sizeof(len); \
|
||||
\
|
||||
size = (UInt32)(-2); \
|
||||
while (len--) { \
|
||||
buf += (size + 2) * sizeof(UInt32); /* for prior round */ \
|
||||
bufSize -= (size + 2) * sizeof(UInt32); \
|
||||
if (bufSize < ((2 * sizeof(UInt32)) + sizeof(UInt64))) \
|
||||
break; \
|
||||
/* Load key/size/val */ \
|
||||
buf32 = (UInt32*)buf; \
|
||||
key = buf32[0]; \
|
||||
size = buf32[1]; \
|
||||
val64 = *(UInt64*)(&buf32[2]); \
|
||||
\
|
||||
FTL_doAllStats \
|
||||
\
|
||||
if ((bufSize - (2 * sizeof(UInt32))) < size) \
|
||||
break; \
|
||||
\
|
||||
/* Got here--wasn't caught be easy filter above, so must be some other blob */ \
|
||||
if (0 == key) { \
|
||||
buf += sizeof(UInt32); \
|
||||
continue; \
|
||||
} \
|
||||
if (S_STATKEY_VFL == key) { \
|
||||
(_VFLFunc)(AND_STRUCT_VFL_STATISTICS, &buf32[2], size*sizeof(UInt32)); \
|
||||
continue; \
|
||||
} \
|
||||
if (S_STATKEY_FIL == key) { \
|
||||
(_FILFunc)(AND_STRUCT_VFL_FILSTATISTICS, &buf32[2], size*sizeof(UInt32)); \
|
||||
continue; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* _FTL_H_ */
|
||||
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright (c) 2010 Apple Inc. All rights reserved.
|
||||
*
|
||||
* This document is the property of Apple Inc.
|
||||
* It is considered confidential and proprietary.
|
||||
*
|
||||
* This document may not be reproduced or transmitted in any form,
|
||||
* in whole or in part, without the express written permission of
|
||||
* Apple Inc.
|
||||
*/
|
||||
|
||||
#ifndef _PPN_FIL_H_
|
||||
#define _PPN_FIL_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#include "FILTypes.h"
|
||||
|
||||
typedef UInt8 PPNStatusType;
|
||||
#define PPN_READ_STATUS_INVALID_DATA (((PPNStatusType)1) << 0)
|
||||
#define PPN_READ_STATUS_REFRESH (((PPNStatusType)1) << 1)
|
||||
#define PPN_READ_STATUS_RETIRE (((PPNStatusType)1) << 2)
|
||||
#define PPN_READ_STATUS_CLEAN (((PPNStatusType)1) << 3)
|
||||
#define PPN_READ_STATUS_GEB (((PPNStatusType)1) << 4)
|
||||
#define PPN_READ_STATUS_VALID (((PPNStatusType)1) << 6)
|
||||
#define PPN_READ_STATUS_WRONG_BITS_PER_CELL (((PPNStatusType)1) << 7)
|
||||
|
||||
#define PPN_OTHERS_STATUS_OP_FAILED (((PPNStatusType)1) << 0)
|
||||
#define PPN_OTHERS_STATUS_NOT_SUPPORTED (((PPNStatusType)1) << 2)
|
||||
#define PPN_OTHERS_STATUS_GEB (((PPNStatusType)1) << 4)
|
||||
#define PPN_OTHERS_STATUS_VALID (((PPNStatusType)1) << 6)
|
||||
|
||||
#if !(defined(AND_READONLY)) || AND_SUPPORT_NVRAM
|
||||
#define PPN_PROGRAM_STATUS_FAIL (((PPNStatusType)1) << 0)
|
||||
#define PPN_PROGRAM_STATUS_NOT_PROGRAMMED (((PPNStatusType)1) << 2)
|
||||
|
||||
#define PPN_PROGRAM_STATUS_GEB (((PPNStatusType)1) << 4)
|
||||
|
||||
#define PPN_ERASE_STATUS_FAIL (((PPNStatusType)1) << 0)
|
||||
#define PPN_ERASE_STATUS_RETIRE (((PPNStatusType)1) << 2)
|
||||
#define PPN_ERASE_STATUS_GEB (((PPNStatusType)1) << 4)
|
||||
#endif // !(defined(AND_READONLY)) || AND_SUPPORT_NVRAM
|
||||
|
||||
typedef UInt32 PPNOptions;
|
||||
#define PPN_OPTIONS_REPORT_HEALTH (((UInt32)1) << 0)
|
||||
#define PPN_OPTIONS_GET_PAGE_RMA_INFO (((UInt32)1) << 1)
|
||||
|
||||
// simulator debug options (allocate from the end)
|
||||
#if (defined (AND_SIMULATOR) && AND_SIMULATOR)
|
||||
#define PPN_OPTIONS_IGNORE_BAD_BLOCK (((UInt32)1) << 31)
|
||||
#define PPN_OPTIONS_GENERATE_BAD_BLOCK (((UInt32)1) << 30)
|
||||
#define PPN_OPTIONS_TAKE_SNAPSHOT (((UInt32)1) << 29)
|
||||
#else
|
||||
#define PPN_OPTIONS_IGNORE_BAD_BLOCK (0) // do not set any bits if we are running outside the simulator
|
||||
#define PPN_OPTIONS_GENERATE_BAD_BLOCK (0) // do not set any bits if we are running outside the simulator
|
||||
#define PPN_OPTIONS_TAKE_SNAPSHOT (0) // do not set any bits if we are running outside the simulator
|
||||
#endif
|
||||
|
||||
#define PPN_NO_OPTIONS (0)
|
||||
|
||||
typedef UInt32 PPNCommand;
|
||||
#define PPN_COMMAND_NONE (0UL)
|
||||
#define PPN_COMMAND_READ (1UL)
|
||||
#if !(defined(AND_READONLY)) || AND_SUPPORT_NVRAM || WMR_IBOOT_WRITE_ENABLE
|
||||
#define PPN_COMMAND_PROGRAM (2UL)
|
||||
#define PPN_COMMAND_ERASE (3UL)
|
||||
#endif // !(defined(AND_READONLY)) || AND_SUPPORT_NVRAM
|
||||
#define PPN_COMMAND_CAUBBT (4UL)
|
||||
|
||||
#define PPN_MAX_CES_PER_BUS 2
|
||||
#define PPN_MAX_PAGES_PER_CE 128
|
||||
#define PPN_MAX_PAGES 128
|
||||
|
||||
#define PPN_MAX_MEM_BUFFERS 256
|
||||
|
||||
#define PPN_VERSION_1_0_0 (0x00010000)
|
||||
#define PPN_VERSION_1_0_3 (0x00010003)
|
||||
#define PPN_VERSION_1_5_0 (0x00010500)
|
||||
#define PPN_VERSION_2_0_0 (0x00020000)
|
||||
#define PPN_VERSION_ERROR (0x00FEFEFE)
|
||||
#define PPN_VERSION_BAD_FW (0x00FFFFFF)
|
||||
#define PPN_VERSION_UNSUPPORTED PPN_VERSION_2_0_0
|
||||
|
||||
typedef UInt16 ChipEnableType;
|
||||
typedef UInt8 ChipEnableIndexType;
|
||||
typedef UInt32 PageAddressType;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt16 length;
|
||||
UInt16 column;
|
||||
PageAddressType row;
|
||||
} RowColLenAddressType;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
FILDeviceInfo *device_info;
|
||||
void *handle; //opaque to caller
|
||||
// at least for now, i am adding a bus identifier
|
||||
UInt16 bus_num;
|
||||
} BusContext;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt16 offset; // offset inside the mem_entry
|
||||
UInt8 idx; // what mem entry this is in
|
||||
} PPNMemoryIndex;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *data;
|
||||
void *meta;
|
||||
UInt16 num_of_lbas; // lba is a 4KB chunk - limited to 255 entries
|
||||
} PPNMemoryEntry;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ChipEnableType ce;
|
||||
UInt16 pages;
|
||||
UInt16 offset;
|
||||
} PPNCommandCeInfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
RowColLenAddressType addr;
|
||||
ChipEnableIndexType ceIdx;
|
||||
UInt8 lbas;
|
||||
PPNStatusType status;
|
||||
} PPNCommandEntry;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// This section is shared between the A8/A9 and the IOP.
|
||||
|
||||
PPNCommand command;
|
||||
PPNOptions options;
|
||||
UInt16 num_pages;
|
||||
UInt16 lbas;
|
||||
PPNStatusType page_status_summary; // logical OR of all page statuses
|
||||
|
||||
PPNCommandCeInfo ceInfo[PPN_MAX_CES_PER_BUS];
|
||||
PPNCommandEntry entry[PPN_MAX_PAGES];
|
||||
|
||||
// This section is used by the A8/A9 only
|
||||
|
||||
BusContext context;
|
||||
|
||||
PPNMemoryIndex mem_index[PPN_MAX_PAGES];
|
||||
PPNMemoryEntry mem_buffers[PPN_MAX_MEM_BUFFERS];
|
||||
UInt16 mem_buffers_count;
|
||||
} PPNCommandStruct;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt16 channel;
|
||||
ChipEnableIndexType chip_enable_idx;
|
||||
ChipEnableType physical_chip_enable;
|
||||
} PPNChipEnableStruct;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* _PPN_FIL_H_ */
|
||||
@@ -0,0 +1,171 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* COMPONENT : Rainbow */
|
||||
/* MODULE : Virtual Flash Layer */
|
||||
/* NAME : VFL header file */
|
||||
/* FILE : VFL.h */
|
||||
/* PURPOSE : This file contains the definition and protypes of exported */
|
||||
/* functions for VFL. */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* COPYRIGHT 2003-2005 SAMSUNG ELECTRONICS CO., LTD. */
|
||||
/* ALL RIGHTS RESERVED */
|
||||
/* */
|
||||
/* Permission is hereby granted to licensees of Samsung Electronics */
|
||||
/* Co., Ltd. products to use or abstract this computer program for the */
|
||||
/* sole purpose of implementing a product based on Samsung */
|
||||
/* Electronics Co., Ltd. products. No other rights to reproduce, use, */
|
||||
/* or disseminate this computer program, whether in part or in whole, */
|
||||
/* are granted. */
|
||||
/* */
|
||||
/* Samsung Electronics Co., Ltd. makes no representation or warranties */
|
||||
/* with respect to the performance of this computer program, and */
|
||||
/* specifically disclaims any responsibility for any damages, */
|
||||
/* special or consequential, connected with the use of this program. */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* REVISION HISTORY */
|
||||
/* */
|
||||
/* 18-JUL-2005 [Jaesung Jung] : first writing */
|
||||
/* 31-MAR-2006 [Yangsup Lee ] : support ftl meta block wear leveling */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef _VFL_H_
|
||||
#define _VFL_H_
|
||||
#include "FPart.h"
|
||||
#include "VFLBuffer.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Return value of VFL_XXX() */
|
||||
/*****************************************************************************/
|
||||
#define VFL_SUCCESS ANDErrorCodeOk
|
||||
#define VFL_SUCCESS_CLEAN ANDErrorCodeCleanOk
|
||||
#define VFL_CRITICAL_ERROR ANDErrorCodeHwErr
|
||||
#define VFL_U_ECC_ERROR ANDErrorCodeUserDataErr
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Type definition of checksum (confirm) state */
|
||||
/*****************************************************************************/
|
||||
|
||||
/*****************************************************************************/
|
||||
/* exported function prototype of VFL */
|
||||
/*****************************************************************************/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#define VFL_SPANS_MAX (128)
|
||||
|
||||
// read result flags - 32 Bit
|
||||
#define VFL_READ_STATUS_REFRESH (1 << 0)
|
||||
#define VFL_READ_STATUS_RETIRE (1 << 1)
|
||||
#define VFL_READ_STATUS_UECC (1 << 2) // UECC = invalid data TRUE and clean FALSE
|
||||
#define VFL_READ_STATUS_CLEAN (1 << 3) // UECC = invalid data TRUE and clean TRUE
|
||||
#define VFL_READ_STATUS_VALID_DATA (1 << 4) // at least one of the pages had valid data
|
||||
#define VFL_READ_STATUS_UNIDENTIFIED (1 << 5) // at least one status was something we do not expect
|
||||
#define VFL_READ_STATUS_ERRS (VFL_READ_STATUS_UECC | VFL_READ_STATUS_RETIRE | VFL_READ_STATUS_REFRESH)
|
||||
#define VFL_READ_STATUS_ALL (0xFFFFFFFF)
|
||||
|
||||
typedef UInt32 VFLReadStatusType;
|
||||
|
||||
typedef void (*VFL_ReadSpansCB_t)(UInt32 vba, VFLReadStatusType status, UInt8 *meta);
|
||||
typedef struct
|
||||
{
|
||||
BOOL32 bDisableWhitening;
|
||||
BOOL32 bMarkECCForScrub;
|
||||
UInt32 vba[VFL_SPANS_MAX];
|
||||
UInt32 count[VFL_SPANS_MAX];
|
||||
UInt8 *data[VFL_SPANS_MAX];
|
||||
UInt8 *meta[VFL_SPANS_MAX];
|
||||
UInt32 len;
|
||||
VFL_ReadSpansCB_t cb;
|
||||
UInt32 cbOpt;
|
||||
VFLReadStatusType op_status;
|
||||
} VFL_ReadSpans_t;
|
||||
|
||||
typedef struct _VFLFunctions
|
||||
{
|
||||
#ifndef AND_READONLY
|
||||
Int32 (*Format)(UInt32 dwBootAreaSize, UInt32 dwOptions);
|
||||
BOOL32 (*AllocateSpecialBlock)(SpecialBlockAddress *allocated_block, UInt16 type);
|
||||
Int32 (*WriteSinglePage)(UInt32 nVpn, Buffer *pBuf, BOOL32 boolReplaceBlockOnFail, BOOL32 bDisableWhitening);
|
||||
Int32 (*Erase)(UInt16 wVbn, BOOL32 bReplaceOnFail);
|
||||
Int32 (*ChangeFTLCxtVbn)(UInt16 *aFTLCxtVbn);
|
||||
BOOL32 (*WriteMultiplePagesInVb)
|
||||
(UInt32 dwVpn, UInt16 wNumPagesToWrite,
|
||||
UInt8 * pbaData, UInt8 * pbaSpare, BOOL32 boolReplaceBlockOnFail, BOOL32 bDisableWhitening);
|
||||
BOOL32 (*MarkBlockAsGrownBad)(SpecialBlockAddress *allocated_block);
|
||||
|
||||
#if AND_SUPPORT_BLOCK_BORROWING
|
||||
BOOL32 (*BorrowSpareBlock)(UInt32 *pdwPhysicalCE, UInt32 *pdwPhysicalBlock, UInt16 wType);
|
||||
#endif //AND_SUPPORT_BLOCK_BORROWING
|
||||
|
||||
BOOL32 (*ProgramMultipleVbas)(UInt32 vba, UInt16 count, UInt8 *data, UInt8 *meta,
|
||||
BOOL32 replaceOnPfail, BOOL32 disableWhitening);
|
||||
#endif // ! AND_READONLY
|
||||
|
||||
Int32 (*Init)(FPartFunctions * pFPartFunctions);
|
||||
Int32 (*Open)(UInt32 dwBootAreaSize, UInt32 minor_ver, UInt32 dwOptions);
|
||||
void (*Close)(void);
|
||||
BOOL32 (*ReadMultiplePagesInVb)
|
||||
(UInt16 wVbn, UInt16 wStartPOffset,
|
||||
UInt16 wNumPagesToRead,
|
||||
UInt8 * pbaData,
|
||||
UInt8 * pbaSpare,
|
||||
BOOL32 * pboolNeedRefresh,
|
||||
UInt8 * pabSectorStats,
|
||||
BOOL32 bDisableWhitening);
|
||||
BOOL32 (*ReadScatteredPagesInVb)
|
||||
(UInt32 * padwVpn,
|
||||
UInt16 wNumPagesToRead,
|
||||
UInt8 * pbaData, UInt8 * pbaSpare,
|
||||
BOOL32 * pboolNeedRefresh,
|
||||
UInt8 * pabSectorStats,
|
||||
BOOL32 bDisableWhitening, Int32 *actualStatus);
|
||||
Int32 (*ReadSinglePage)(UInt32 nVpn, Buffer *pBuf,
|
||||
BOOL32 bCleanCheck,
|
||||
BOOL32 bMarkECCForScrub,
|
||||
BOOL32 * pboolNeedRefresh,
|
||||
UInt8 * pabSectorStats,
|
||||
BOOL32 bDisableWhitening);
|
||||
UInt16* (*GetFTLCxtVbn)(void);
|
||||
BOOL32 (*GetStruct)(UInt32 dwStructType,
|
||||
void * pvoidStructBuffer,
|
||||
UInt32 * pdwStructSize);
|
||||
BOOL32 (*SetStruct)(UInt32 dwStructType,
|
||||
void * pvoidStructBuffer,
|
||||
UInt32 dwStructSize);
|
||||
|
||||
UInt32 (*GetDeviceInfo)(UInt32 dwParamType);
|
||||
UInt32 (*GetMinorVersion)(void);
|
||||
UInt16 (*GetVbasPerVb)(UInt16 wVbn);
|
||||
|
||||
|
||||
// new func - read
|
||||
VFLReadStatusType (*ReadMultipleVbas)(UInt32 vba, UInt16 count, UInt8 *data, UInt8 *meta,
|
||||
BOOL32 bDisableWhitening, BOOL32 bMarkECCForScrub);
|
||||
|
||||
void (*ReadSpansInit)(VFL_ReadSpans_t *s, VFL_ReadSpansCB_t cb, UInt32 cbOpt, BOOL32 bDisableWhitening, BOOL32 bMarkECCForScrub);
|
||||
void (*ReadSpansAdd)(VFL_ReadSpans_t *s, UInt32 vba, UInt32 count, UInt8 *data, UInt8 *meta);
|
||||
VFLReadStatusType (*ReadSpans)(VFL_ReadSpans_t *s);
|
||||
|
||||
} VFLFunctions;
|
||||
|
||||
void VSVFL_Register(VFLFunctions * pVFL_Functions);
|
||||
void VFL_Register(VFLFunctions * pVFL_Functions);
|
||||
void PPNVFL_Register(VFLFunctions * pVFL_Functions);
|
||||
|
||||
#define PPN_VFL_MAJOR_VER (1)
|
||||
VFLFunctions * PPN_VFL_GetFunctions(void);
|
||||
#define PPN_SVFL_MAJOR_VER (2)
|
||||
VFLFunctions * PPN_SVFL_GetFunctions(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* _VFL_H_ */
|
||||
@@ -0,0 +1,97 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* PROJECT : Rainbow */
|
||||
/* MODULE : Whimory configuration definition heade file */
|
||||
/* NAME : Whimory configuration definition */
|
||||
/* FILE : WMRConfig.h */
|
||||
/* PURPOSE : Configuation definition for Whimory */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* COPYRIGHT 2003-2005, SAMSUNG ELECTRONICS CO., LTD. */
|
||||
/* ALL RIGHTS RESERVED */
|
||||
/* */
|
||||
/* Permission is hereby granted to licensees of Samsung Electronics */
|
||||
/* Co., Ltd. products to use or abstract this computer program for the */
|
||||
/* sole purpose of implementing a product based on Samsung */
|
||||
/* Electronics Co., Ltd. products. No other rights to reproduce, use, */
|
||||
/* or disseminate this computer program, whether in part or in whole, */
|
||||
/* are granted. */
|
||||
/* */
|
||||
/* Samsung Electronics Co., Ltd. makes no representation or warranties */
|
||||
/* with respect to the performance of this computer program, and */
|
||||
/* specifically disclaims any responsibility for any damages, */
|
||||
/* special or consequential, connected with the use of this program. */
|
||||
/* */
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* */
|
||||
/* REVISION HISTORY */
|
||||
/* */
|
||||
/* 12-JUL-2005 [Jaesung Jung] : first writing */
|
||||
/* 03-NOV-2005 [Yangsup Lee ] : Add wear-leveling algorithm */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef _WMR_CONFIG_H_
|
||||
#define _WMR_CONFIG_H_
|
||||
|
||||
#include "WMRFeatures.h"
|
||||
|
||||
#if (defined (AND_SUPPORT_2ND_BOOTLOADER) && AND_SUPPORT_2ND_BOOTLOADER && defined (AND_SIGNATURE_IN_BLOCK_ZERO) && AND_SIGNATURE_IN_BLOCK_ZERO)
|
||||
#error "AND_SUPPORT_2ND_BOOTLOADER & AND_SIGNATURE_IN_BLOCK_ZERO can't both be defined"
|
||||
#endif
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Global Config Definition which should be shared by FTL, VFL, FIL */
|
||||
/*****************************************************************************/
|
||||
#define WMR_BOOT_AREA_DEFAULT_SIZE (1) /* this will be value used unless unit does boot-from-nand */
|
||||
#define AND_MAX_BANKS_PER_CS (8)
|
||||
#define WMR_SECTOR_SIZE (512) /* the size of sector */
|
||||
#if defined(AND_SUPPORT_YAFTL) && AND_SUPPORT_YAFTL
|
||||
#define WMR_NUM_BUFFERS (10) /* the number of buffers - used by VFLBuffer */
|
||||
#else /* defined(AND_SUPPORT_YAFTL) && AND_SUPPORT_YAFTL */
|
||||
#if !(defined(AND_READONLY) && AND_READONLY)
|
||||
#define WMR_NUM_BUFFERS (5) /* the number of buffers - used by VFLBuffer */
|
||||
#elif !(defined(WMR_DISABLE_FTL_RECOVERY) && WMR_DISABLE_FTL_RECOVERY) || \
|
||||
(defined(AND_COLLECT_STATISTICS) && AND_COLLECT_STATISTICS)
|
||||
#define WMR_NUM_BUFFERS (2) /* the number of buffers - used by VFLBuffer */
|
||||
#else
|
||||
#define WMR_NUM_BUFFERS (1) /* Used in _FTLRead and VFL_Open */
|
||||
#endif
|
||||
#endif /* defined(AND_SUPPORT_YAFTL) && AND_SUPPORT_YAFTL */
|
||||
|
||||
#define WMR_SECTORS_PER_PAGE_MIN (4)
|
||||
|
||||
#define WMR_MAX_PAGES_PER_BLOCK (0x100)
|
||||
|
||||
#define WMR_MAX_VB (18000) /* the maximum number of virtual block*/
|
||||
|
||||
#define WMR_MAX_RESERVED_SIZE (820) /* the maximum count of reserved blocks */
|
||||
|
||||
#define FTL_METAWEARLEVEL_RATIO (10) // consider bringing this number up
|
||||
#define WMR_WEAR_LEVEL_FREQUENCY (20)
|
||||
#define WMR_WEAR_LEVEL_FREQUENCY_DELAY (300)
|
||||
#define WMR_WEAR_LEVEL_MAX_DIFF (5)
|
||||
#define WMR_WEAR_LEVEL_MIN_EC_VALUE (3)
|
||||
|
||||
#define DEFAULT_NUMBER_OF_SPECIAL_BLOCKS_CS0 (3)
|
||||
#define NUMBER_OF_SPECIAL_BLOCKS_NOTCS0 (2)
|
||||
|
||||
#define FTL_READ_REFRESH_LIST_SIZE (5)
|
||||
#define FTL_RC_TRESHOLD (10000) // to review for real world drivers
|
||||
#define FTL_READS_SINCE_LAST_REFRESH_MARK_TRASHOLD (200)
|
||||
|
||||
#define YAFTL_RC_THRESHOLD (0xfffd)
|
||||
#define YAFTL_RC_MULTIPLIER (16)
|
||||
|
||||
#define S_RC_THRESHOLD (250000)
|
||||
|
||||
#define BYTES_PER_METADATA_RAW (12)
|
||||
|
||||
#define VSVFL_USER_BLKS_PER_1K (976)
|
||||
#define PPNVFL_USER_BLKS_PER_256B (244)
|
||||
#define VFL_USER_BLKS_PER_1K (968)
|
||||
#define FTL_CXT_SECTION_SIZE (3) // number of FTL Cxt locations are saved by VFL
|
||||
#define WMR_BLOCK_ADDRESS_MSB (1<<15)
|
||||
|
||||
#endif /* _WMR_CONFIG_H_ */
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright (C) 2009 Apple Inc. All rights reserved.
|
||||
//
|
||||
// This document is the property of Apple Inc.
|
||||
// It is considered confidential and proprietary.
|
||||
//
|
||||
// This document may not be reproduced or transmitted in any form,
|
||||
// in whole or in part, without the express written permission of
|
||||
// Apple Inc.
|
||||
//
|
||||
//
|
||||
|
||||
#include "WMRTypes.h"
|
||||
#include "FTL.h"
|
||||
#include "VFL.h"
|
||||
#include "FIL.h"
|
||||
|
||||
BOOL32 FIL_Test(void);
|
||||
|
||||
BOOL32 WMR_FTL_Test(FTLFunctions *ftl);
|
||||
BOOL32 WMR_VFL_Test(VFLFunctions *vfl);
|
||||
BOOL32 WMR_FIL_Test(LowFuncTbl *fil);
|
||||
BOOL32 WMR_FPart_Test(FPartFunctions *fpart);
|
||||
@@ -0,0 +1,901 @@
|
||||
// Copyright (C) 2009 Apple Inc. All rights reserved.
|
||||
//
|
||||
// This document is the property of Apple Inc.
|
||||
// It is considered confidential and proprietary.
|
||||
//
|
||||
// This document may not be reproduced or transmitted in any form,
|
||||
// in whole or in part, without the express written permission of
|
||||
// Apple Inc.
|
||||
//
|
||||
//
|
||||
#include "WMROAM.h"
|
||||
#include "FIL.h"
|
||||
#include "WMRTest.h"
|
||||
#include "WMRConfig.h"
|
||||
#include "WMRBuf.h"
|
||||
|
||||
#define AND_MAX_BANKS (AND_MAX_BANKS_PER_CS * 32)
|
||||
#define TEST_DATA_WATERMARK (0xB6)
|
||||
#define TEST_META_WATERMARK (0xC7)
|
||||
#define TEST_STATS_WATERMARK (0xD8)
|
||||
|
||||
// Static function definitions
|
||||
static BOOL32 FILInterfaceTest(UInt16 *blockList);
|
||||
static BOOL32 InitTestInfo(void);
|
||||
static const char* FILErrorToString(Int32 filStatus);
|
||||
static void InitPageListFromBlocks(const UInt16 *blockList, UInt32 *pageList);
|
||||
static void FillBufferWithCountingPattern(UInt32 *buffer, UInt32 startValue, UInt32 bytes);
|
||||
static void FillMetaBufferWithPattern(UInt8 *buffer, UInt32 startValue, UInt32 numPages);
|
||||
static void FILTestHexdump(void *data, UInt32 length);
|
||||
|
||||
// Static variables
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 pagesPerBlock;
|
||||
UInt32 numBanks;
|
||||
UInt32 numCE;
|
||||
UInt32 bytesPerPage;
|
||||
UInt32 bytesPerSpare;
|
||||
UInt32 bufferBytesPerMeta;
|
||||
UInt32 validBytesPerMeta;
|
||||
UInt32 bootPageBytes;
|
||||
UInt32 correctableSectorsPerPage;
|
||||
} FILTestInfo;
|
||||
|
||||
static FILTestInfo testInfo;
|
||||
static LowFuncTbl *pFIL = NULL;
|
||||
static WMR_BufZone_t bufZone;
|
||||
|
||||
|
||||
// Public functions
|
||||
BOOL32 FIL_Test(void)
|
||||
{
|
||||
UInt16 blockList[AND_MAX_BANKS] = { 0 };
|
||||
|
||||
WMR_BufZone_Init(&bufZone);
|
||||
|
||||
InitTestInfo();
|
||||
|
||||
return FILInterfaceTest(blockList);
|
||||
}
|
||||
|
||||
// Local functions
|
||||
|
||||
BOOL32 InitTestInfo(void)
|
||||
{
|
||||
|
||||
pFIL = FIL_GetFuncTbl();
|
||||
|
||||
testInfo.pagesPerBlock = pFIL->GetDeviceInfo(AND_DEVINFO_PAGES_PER_BLOCK);
|
||||
WMR_ASSERT(testInfo.pagesPerBlock > 0);
|
||||
testInfo.numBanks = pFIL->GetDeviceInfo(AND_DEVINFO_NUM_OF_BANKS);
|
||||
WMR_ASSERT(testInfo.numBanks > 0);
|
||||
testInfo.numCE = pFIL->GetDeviceInfo(AND_DEVINFO_NUM_OF_CS);
|
||||
WMR_ASSERT(testInfo.numCE > 0);
|
||||
testInfo.bytesPerPage = pFIL->GetDeviceInfo(AND_DEVINFO_BYTES_PER_PAGE);
|
||||
WMR_ASSERT(testInfo.bytesPerPage > 0);
|
||||
testInfo.bytesPerSpare = pFIL->GetDeviceInfo(AND_DEVINFO_BYTES_PER_SPARE);
|
||||
WMR_ASSERT(testInfo.bytesPerSpare > 0);
|
||||
testInfo.bufferBytesPerMeta = 12;
|
||||
testInfo.validBytesPerMeta = 10;
|
||||
testInfo.bootPageBytes = pFIL->GetDeviceInfo(AND_DEVINFO_BYTES_PER_BL_PAGE);
|
||||
WMR_ASSERT(testInfo.bootPageBytes > 0);
|
||||
testInfo.correctableSectorsPerPage = testInfo.bytesPerPage / pFIL->GetDeviceInfo(AND_DEVINFO_CORRECTABLE_SIZE);
|
||||
WMR_ASSERT(testInfo.correctableSectorsPerPage > 0);
|
||||
|
||||
return TRUE32;
|
||||
}
|
||||
|
||||
static BOOL32 TestBootloaderBlock(UInt32 ce, UInt32 block, UInt8 *writeDataBuffer, UInt8 *verifyDataBuffer)
|
||||
{
|
||||
UInt32 base_page = block * testInfo.pagesPerBlock;
|
||||
Int32 andStatus;
|
||||
UInt32 testSeed = 1234567890;
|
||||
UInt32 offset;
|
||||
|
||||
// Erase block
|
||||
WMR_PRINT(ALWAYS, "Erasing CE %d Block %d\n", ce, block);
|
||||
andStatus = pFIL->Erase(ce, block);
|
||||
|
||||
|
||||
if (FIL_SUCCESS != andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Erase failed with %s\n", FILErrorToString(andStatus));
|
||||
return FALSE32;
|
||||
}
|
||||
|
||||
for (offset = 0; offset < testInfo.pagesPerBlock; ++offset)
|
||||
{
|
||||
const UInt32 page = base_page + offset;
|
||||
// Read bootloader page and verify clean
|
||||
WMR_ASSERT(pFIL->ReadBLPage != NULL);
|
||||
WMR_MEMSET(verifyDataBuffer, TEST_DATA_WATERMARK, testInfo.bytesPerPage);
|
||||
WMR_PRINT(ALWAYS, "Using ReadBL for clean detect CE %d Page %d\n", (UInt32) ce, page);
|
||||
andStatus = pFIL->ReadBLPage(ce, page, verifyDataBuffer);
|
||||
|
||||
if (FIL_SUCCESS_CLEAN != andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "ReadBL Clean Detect failed with %s\n", FILErrorToString(andStatus));
|
||||
return FALSE32;
|
||||
}
|
||||
|
||||
// Write bootloader page
|
||||
WMR_ASSERT(pFIL->WriteBLPage != NULL);
|
||||
WMR_PRINT(ALWAYS, "Writing CE %d Page %d\n", (UInt32) ce, page);
|
||||
FillBufferWithCountingPattern((UInt32*)writeDataBuffer, testSeed++, testInfo.bootPageBytes);
|
||||
andStatus = pFIL->WriteBLPage(ce, page, writeDataBuffer);
|
||||
|
||||
if (FIL_SUCCESS != andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Write failed with %s\n", FILErrorToString(andStatus));
|
||||
return FALSE32;
|
||||
}
|
||||
|
||||
// Read back and verify
|
||||
WMR_MEMSET(verifyDataBuffer, TEST_DATA_WATERMARK, testInfo.bootPageBytes);
|
||||
WMR_PRINT(ALWAYS, "ReadBL CE %d Page %d\n", (UInt32) ce, page);
|
||||
|
||||
andStatus = pFIL->ReadBLPage(ce, page, verifyDataBuffer);
|
||||
|
||||
if (FIL_SUCCESS != andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "ReadBL readback failed with %s\n", FILErrorToString(andStatus));
|
||||
return FALSE32;
|
||||
}
|
||||
|
||||
if (WMR_MEMCMP(writeDataBuffer, verifyDataBuffer, testInfo.bootPageBytes))
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Read back contents of boot page failed comparison\n");
|
||||
return FALSE32;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE32;
|
||||
}
|
||||
|
||||
// Block list is assumed to be numBanks long and non-overlapping banks
|
||||
BOOL32 FILInterfaceTest(UInt16 *blockList)
|
||||
{
|
||||
UInt8 *writeDataBuffer = NULL;
|
||||
UInt8 *writeMetaBuffer = NULL;
|
||||
UInt8 *verifyDataBuffer = NULL;
|
||||
UInt8 *verifyMetaBuffer = NULL;
|
||||
Int32 andStatus;
|
||||
UInt32 pageList[2 * AND_MAX_BANKS];
|
||||
UInt16 ceList[AND_MAX_BANKS] = { 0 };
|
||||
UInt8 *sectorStats = NULL;
|
||||
UInt32 testSeed = 1234567890;
|
||||
UInt16 bankIdx;
|
||||
const UInt32 dataBufferSize = 2 * testInfo.numBanks * testInfo.bytesPerPage;
|
||||
const UInt32 metaBufferSize = 2 * testInfo.numBanks * testInfo.bytesPerSpare;
|
||||
const UInt32 sectorStatsSize = 2 * testInfo.numBanks * testInfo.correctableSectorsPerPage;
|
||||
|
||||
|
||||
InitPageListFromBlocks(blockList, pageList);
|
||||
|
||||
WMR_PRINT(ALWAYS, "Starting FIL Interface Test\n");
|
||||
|
||||
writeMetaBuffer = WMR_MALLOC(metaBufferSize);
|
||||
verifyMetaBuffer = WMR_MALLOC(metaBufferSize);
|
||||
sectorStats = WMR_MALLOC(sectorStatsSize);
|
||||
writeDataBuffer = WMR_Buf_Alloc_ForDMA(&bufZone, dataBufferSize);
|
||||
verifyDataBuffer = WMR_Buf_Alloc_ForDMA(&bufZone, dataBufferSize);
|
||||
|
||||
WMR_BufZone_FinishedAllocs(&bufZone);
|
||||
|
||||
WMR_BufZone_Rebase(&bufZone, (void **)&writeDataBuffer);
|
||||
WMR_BufZone_Rebase(&bufZone, (void **)&verifyDataBuffer);
|
||||
|
||||
if (!writeDataBuffer || !writeMetaBuffer || !verifyDataBuffer || !verifyMetaBuffer || !sectorStats)
|
||||
{
|
||||
WMR_PANIC("Buffer allocations failed");
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
WMR_BufZone_FinishedRebases(&bufZone);
|
||||
|
||||
// Enable whitening if available
|
||||
if (pFIL->SetWhiteningState) {
|
||||
pFIL->SetWhiteningState(TRUE32);
|
||||
}
|
||||
if (pFIL->RegisterCurrentTransaction) {
|
||||
pFIL->RegisterCurrentTransaction(0,0, NULL);
|
||||
}
|
||||
|
||||
WMR_ASSERT(TestBootloaderBlock(0, 16, writeDataBuffer, verifyDataBuffer));
|
||||
|
||||
// Erase Block
|
||||
WMR_ASSERT(pFIL->Erase != NULL);
|
||||
WMR_PRINT(ALWAYS, "Erasing CE %d Block %d\n", (UInt32) ceList[0], (UInt32) blockList[0]);
|
||||
andStatus = pFIL->Erase(ceList[0], blockList[0]);
|
||||
|
||||
if (FIL_SUCCESS != andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Erase failed with %s\n", FILErrorToString(andStatus));
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
// Clean check single page
|
||||
WMR_ASSERT(pFIL->ReadWithECC != NULL);
|
||||
WMR_PRINT(ALWAYS, "Clean checking CE %d Page %d\n", (UInt32) ceList[0], pageList[0]);
|
||||
WMR_MEMSET(verifyDataBuffer, TEST_DATA_WATERMARK, testInfo.bytesPerPage);
|
||||
WMR_MEMSET(verifyMetaBuffer, TEST_META_WATERMARK, testInfo.bytesPerSpare);
|
||||
andStatus = pFIL->ReadWithECC(ceList[0], pageList[0], verifyDataBuffer, verifyMetaBuffer, NULL, NULL, FALSE32);
|
||||
|
||||
if (FIL_SUCCESS_CLEAN != andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Clean Detect failed with %s\n", FILErrorToString(andStatus));
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
// Verify ReadNoECC on that page
|
||||
// XXX put guard bytes at end of buffer to make sure the right number of bytes are read
|
||||
WMR_ASSERT(pFIL->ReadNoECC != NULL);
|
||||
WMR_MEMSET(verifyDataBuffer, TEST_DATA_WATERMARK, testInfo.bytesPerPage);
|
||||
WMR_MEMSET(verifyMetaBuffer, TEST_META_WATERMARK, testInfo.bytesPerSpare);
|
||||
WMR_PRINT(ALWAYS, "ReadNoECC on clean CE %d Page %d\n", (UInt32) ceList[0], pageList[0]);
|
||||
andStatus = pFIL->ReadNoECC(ceList[0], pageList[0], verifyDataBuffer, verifyMetaBuffer);
|
||||
|
||||
if (FIL_UNSUPPORTED_ERROR == andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "WARNING: ReadNoECC is unsupported on this platform - formatting will not work\n");
|
||||
}
|
||||
else if (FIL_SUCCESS != andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "ReadNoECC failed with %s\n", FILErrorToString(andStatus));
|
||||
goto test_failed;
|
||||
}
|
||||
else
|
||||
{
|
||||
WMR_MEMSET(writeDataBuffer, 0xFF, testInfo.bytesPerPage);
|
||||
WMR_MEMSET(writeMetaBuffer, 0xFF, testInfo.bytesPerSpare);
|
||||
|
||||
if (WMR_MEMCMP(writeDataBuffer, verifyDataBuffer, testInfo.bytesPerPage))
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "ReadNoECC failed all 1's comparison in data section\n");
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
if (WMR_MEMCMP(writeMetaBuffer, verifyMetaBuffer, testInfo.bytesPerSpare))
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "ReadNoECC failed all 1's comparison in spare section\n");
|
||||
goto test_failed;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Clean check multiple pages
|
||||
WMR_ASSERT(pFIL->ReadScatteredPages != NULL);
|
||||
InitPageListFromBlocks(blockList, pageList);
|
||||
// Pick two consecutive pages from the same block
|
||||
pageList[1] = pageList[testInfo.numBanks];
|
||||
ceList[0] = 0;
|
||||
ceList[1] = 0;
|
||||
WMR_PRINT(ALWAYS, "Clean checking CE %d Page %d & %d\n", (UInt32) ceList[0], pageList[0], pageList[1]);
|
||||
andStatus = pFIL->ReadScatteredPages(ceList, pageList, verifyDataBuffer, verifyMetaBuffer, 2, NULL, NULL, FALSE32);
|
||||
|
||||
if (FIL_SUCCESS_CLEAN != andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Multi-page clean detect failed with %s\n", FILErrorToString(andStatus));
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
// Program first page
|
||||
WMR_ASSERT(pFIL->Write != NULL);
|
||||
WMR_PRINT(ALWAYS, "Writing CE %d Page %d\n", (UInt32) ceList[0], pageList[0]);
|
||||
FillBufferWithCountingPattern((UInt32*)writeDataBuffer, testSeed++, testInfo.bytesPerPage);
|
||||
FillMetaBufferWithPattern(writeMetaBuffer, testSeed++, 1);
|
||||
andStatus = pFIL->Write(ceList[0], pageList[0], writeDataBuffer, writeMetaBuffer, FALSE32);
|
||||
|
||||
if (FIL_SUCCESS != andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Write failed with %s\n", FILErrorToString(andStatus));
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
// Read back and verify
|
||||
WMR_PRINT(ALWAYS, "Reading back CE %d Page %d\n", (UInt32) ceList[0], pageList[0]);
|
||||
WMR_MEMSET(verifyDataBuffer, TEST_DATA_WATERMARK, testInfo.bytesPerPage);
|
||||
WMR_MEMSET(verifyMetaBuffer, TEST_META_WATERMARK, testInfo.bufferBytesPerMeta);
|
||||
andStatus = pFIL->ReadWithECC(ceList[0], pageList[0], verifyDataBuffer, verifyMetaBuffer, NULL, NULL, FALSE32);
|
||||
|
||||
if (FIL_SUCCESS != andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Read back failed with %s\n", FILErrorToString(andStatus));
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
if (WMR_MEMCMP(writeMetaBuffer, verifyMetaBuffer, testInfo.bufferBytesPerMeta))
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Read back contents failed comparison in meta section\n");
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
if (WMR_MEMCMP(writeDataBuffer, verifyDataBuffer, testInfo.bytesPerPage))
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Read back contents failed comparison in data section\n");
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
|
||||
// Verify ReadNoECC finds non-FF data
|
||||
WMR_MEMSET(verifyDataBuffer, TEST_DATA_WATERMARK, testInfo.bytesPerPage);
|
||||
WMR_MEMSET(verifyMetaBuffer, TEST_META_WATERMARK, testInfo.bytesPerSpare);
|
||||
WMR_PRINT(ALWAYS, "ReadNoECC on written CE %d Page %d\n", (UInt32) ceList[0], pageList[0]);
|
||||
andStatus = pFIL->ReadNoECC(ceList[0], pageList[0], verifyDataBuffer, verifyMetaBuffer);
|
||||
|
||||
if (FIL_UNSUPPORTED_ERROR == andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "WARNING: ReadNoECC is unsupported on this platform - formatting will not work\n");
|
||||
}
|
||||
else if (FIL_SUCCESS != andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "ReadNoECC failed with %s\n", FILErrorToString(andStatus));
|
||||
goto test_failed;
|
||||
}
|
||||
else
|
||||
{
|
||||
WMR_MEMSET(writeDataBuffer, 0xFF, testInfo.bytesPerPage);
|
||||
WMR_MEMSET(writeMetaBuffer, 0xFF, testInfo.bytesPerSpare);
|
||||
|
||||
if (!WMR_MEMCMP(writeMetaBuffer, verifyMetaBuffer, testInfo.bytesPerSpare))
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "ReadNoECC read all 1's on a programmed page in meta section\n");
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
if (!WMR_MEMCMP(writeDataBuffer, verifyDataBuffer, testInfo.bytesPerPage))
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "ReadNoECC read all 1's on a programmed page in data section\n");
|
||||
goto test_failed;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Read programmed + clean multiple, verify UECC status
|
||||
InitPageListFromBlocks(blockList, pageList);
|
||||
// Pick two consecutive pages from the same block
|
||||
pageList[1] = pageList[testInfo.numBanks];
|
||||
ceList[0] = 0;
|
||||
ceList[1] = 0;
|
||||
WMR_PRINT(ALWAYS, "Multi-page clean checking mixed CE %d Page %d & %d\n", (UInt32) ceList[0], pageList[0], pageList[1]);
|
||||
andStatus = pFIL->ReadScatteredPages(ceList, pageList, verifyDataBuffer, verifyMetaBuffer, 2, NULL, NULL, FALSE32);
|
||||
|
||||
if (FIL_U_ECC_ERROR != andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Multi-page clean checking mixed detect failed with %s\n", FILErrorToString(andStatus));
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
// Over-program the first page to induce real UECC
|
||||
WMR_PRINT(ALWAYS, "Over-programming CE %d Page %d\n", (UInt32) ceList[0], pageList[0]);
|
||||
WMR_MEMSET(writeDataBuffer, 0xA5, testInfo.bytesPerPage);
|
||||
WMR_MEMSET(writeDataBuffer, 0xA5, testInfo.validBytesPerMeta);
|
||||
andStatus = pFIL->Write(ceList[0], pageList[0], writeDataBuffer, writeMetaBuffer, FALSE32);
|
||||
|
||||
if (FIL_SUCCESS != andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Write failed with %s\n", FILErrorToString(andStatus));
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
// Read back and verify UECC
|
||||
WMR_PRINT(ALWAYS, "Reading back expecting UECC on CE %d Page %d\n", (UInt32) ceList[0], pageList[0]);
|
||||
WMR_MEMSET(verifyDataBuffer, TEST_DATA_WATERMARK, testInfo.bytesPerPage);
|
||||
WMR_MEMSET(verifyMetaBuffer, TEST_META_WATERMARK, testInfo.bufferBytesPerMeta);
|
||||
andStatus = pFIL->ReadWithECC(ceList[0], pageList[0], writeDataBuffer, writeMetaBuffer, NULL, NULL, FALSE32);
|
||||
|
||||
if (FIL_U_ECC_ERROR != andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Read with expected UECC failed with %s\n", FILErrorToString(andStatus));
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
// Program second page
|
||||
WMR_PRINT(ALWAYS, "Writing CE %d Page %d\n", (UInt32) ceList[1], pageList[1]);
|
||||
FillBufferWithCountingPattern((UInt32*)writeDataBuffer, testSeed++, testInfo.bytesPerPage);
|
||||
FillMetaBufferWithPattern(writeMetaBuffer, testSeed++, 1);
|
||||
andStatus = pFIL->Write(ceList[1], pageList[1], writeDataBuffer, writeMetaBuffer, FALSE32);
|
||||
|
||||
if (FIL_SUCCESS != andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Write failed with %s\n", FILErrorToString(andStatus));
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
|
||||
// Read back and verify
|
||||
WMR_PRINT(ALWAYS, "Reading back CE %d Page %d\n", (UInt32) ceList[1], pageList[1]);
|
||||
WMR_MEMSET(verifyDataBuffer, TEST_DATA_WATERMARK, testInfo.bytesPerPage);
|
||||
WMR_MEMSET(verifyMetaBuffer, TEST_META_WATERMARK, testInfo.bufferBytesPerMeta);
|
||||
andStatus = pFIL->ReadWithECC(ceList[1], pageList[1], verifyDataBuffer, verifyMetaBuffer, NULL, NULL, FALSE32);
|
||||
|
||||
if (FIL_SUCCESS != andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Read back failed with %s\n", FILErrorToString(andStatus));
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
if (WMR_MEMCMP(writeMetaBuffer, verifyMetaBuffer, testInfo.bufferBytesPerMeta))
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Read back contents failed comparison in meta section\n");
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
if (WMR_MEMCMP(writeDataBuffer, verifyDataBuffer, testInfo.bytesPerPage))
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Read back contents failed comparison in data section\n");
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
|
||||
// Read first + second pages and verify UECC status
|
||||
// Also make sure that reading did not stop on first UECC
|
||||
WMR_PRINT(ALWAYS, "Multi-page clean checking mixed CE %d Page %d & %d\n", (UInt32) ceList[0], pageList[0], pageList[1]);
|
||||
|
||||
WMR_MEMSET(verifyDataBuffer, TEST_DATA_WATERMARK, 2 * testInfo.bytesPerPage);
|
||||
WMR_MEMSET(verifyMetaBuffer, TEST_META_WATERMARK, 2 * testInfo.bufferBytesPerMeta);
|
||||
|
||||
andStatus = pFIL->ReadScatteredPages(ceList, pageList, verifyDataBuffer, verifyMetaBuffer, 2, NULL, NULL, FALSE32);
|
||||
|
||||
if (FIL_U_ECC_ERROR != andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Multi-page uecc checking mixed detect failed with %s\n", FILErrorToString(andStatus));
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
// Verify that the read continued after UECC (compare last buffer written versus the second page)
|
||||
|
||||
if (WMR_MEMCMP(writeMetaBuffer, verifyMetaBuffer + testInfo.bufferBytesPerMeta, testInfo.bufferBytesPerMeta))
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Read back contents of second page failed comparison in meta section\n");
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
if (WMR_MEMCMP(writeDataBuffer, verifyDataBuffer + testInfo.bytesPerPage, testInfo.bytesPerPage))
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Read back contents of second page failed comparison in data section\n");
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
// Erase block
|
||||
WMR_PRINT(ALWAYS, "Erasing CE %d Block %d\n", (UInt32) ceList[0], (UInt32) blockList[0]);
|
||||
andStatus = pFIL->Erase(ceList[0], blockList[0]);
|
||||
|
||||
if (FIL_SUCCESS != andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Erase failed with %s\n", FILErrorToString(andStatus));
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
// Read bootloader page and verify clean
|
||||
WMR_ASSERT(pFIL->ReadBLPage != NULL);
|
||||
WMR_MEMSET(verifyDataBuffer, TEST_DATA_WATERMARK, testInfo.bytesPerPage);
|
||||
WMR_PRINT(ALWAYS, "Using ReadBL for clean detect CE %d Page %d\n", (UInt32) ceList[0], pageList[0]);
|
||||
andStatus = pFIL->ReadBLPage(ceList[0], pageList[0], verifyDataBuffer);
|
||||
|
||||
if (FIL_SUCCESS_CLEAN != andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "ReadBL Clean Detect failed with %s\n", FILErrorToString(andStatus));
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
// Write bootloader page
|
||||
WMR_ASSERT(pFIL->WriteBLPage != NULL);
|
||||
WMR_PRINT(ALWAYS, "Writing CE %d Page %d\n", (UInt32) ceList[0], pageList[0]);
|
||||
FillBufferWithCountingPattern((UInt32*)writeDataBuffer, testSeed++, testInfo.bootPageBytes);
|
||||
andStatus = pFIL->WriteBLPage(ceList[0], pageList[0], writeDataBuffer);
|
||||
|
||||
if (FIL_SUCCESS != andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Write failed with %s\n", FILErrorToString(andStatus));
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
// Read back and verify
|
||||
WMR_MEMSET(verifyDataBuffer, TEST_DATA_WATERMARK, testInfo.bootPageBytes);
|
||||
WMR_PRINT(ALWAYS, "ReadBL CE %d Page %d\n", (UInt32) ceList[0], pageList[0]);
|
||||
|
||||
andStatus = pFIL->ReadBLPage(ceList[0], pageList[0], verifyDataBuffer);
|
||||
|
||||
if (FIL_SUCCESS != andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "ReadBL Clean Detect failed with %s\n", FILErrorToString(andStatus));
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
if (WMR_MEMCMP(writeDataBuffer, verifyDataBuffer, testInfo.bootPageBytes))
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Read back contents of boot page failed comparison\n");
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
// Over-program the same page
|
||||
WMR_PRINT(ALWAYS, "Over-program BL page CE %d Page %d\n", (UInt32) ceList[0], pageList[0]);
|
||||
WMR_MEMSET(writeDataBuffer, 0xA5, testInfo.bootPageBytes);
|
||||
andStatus = pFIL->WriteBLPage(ceList[0], pageList[0], writeDataBuffer);
|
||||
|
||||
if (FIL_SUCCESS != andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Write failed with %s\n", FILErrorToString(andStatus));
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
// Read back and verify UECC
|
||||
WMR_MEMSET(verifyDataBuffer, TEST_DATA_WATERMARK, testInfo.bootPageBytes);
|
||||
WMR_PRINT(ALWAYS, "ReadBL CE %d Page %d\n", (UInt32) ceList[0], pageList[0]);
|
||||
andStatus = pFIL->ReadBLPage(ceList[0], pageList[0], verifyDataBuffer);
|
||||
|
||||
if (FIL_U_ECC_ERROR != andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "ReadBL did not detect UECC with %s\n", FILErrorToString(andStatus));
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
// XXX Write the sections for multiple using VS (need to find paired blocks)
|
||||
|
||||
if (testInfo.numBanks == testInfo.numCE)
|
||||
{
|
||||
UInt16 wFailingCE = ~0;
|
||||
UInt32 wFailingBlock = ~0;
|
||||
|
||||
// Setup up ceList for scattered ops
|
||||
for (bankIdx = 0; bankIdx < testInfo.numCE; ++bankIdx)
|
||||
{
|
||||
ceList[bankIdx] = bankIdx;
|
||||
pageList[bankIdx] = blockList[bankIdx] * testInfo.pagesPerBlock; //XXX this won't work for block gaps
|
||||
}
|
||||
|
||||
// Erase multiple blocks
|
||||
|
||||
if (pFIL->EraseMultiple)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "EraseMultiple on %d blocks\n", testInfo.numCE);
|
||||
andStatus = pFIL->EraseMultiple(blockList, TRUE32, TRUE32, &wFailingCE, &wFailingBlock);
|
||||
}
|
||||
else
|
||||
{
|
||||
// only works for 1 bank per ce
|
||||
WMR_PRINT(ALWAYS, "EraseMultiple fallback on %d blocks\n", testInfo.numCE);
|
||||
for (bankIdx = 0; bankIdx < testInfo.numCE; ++bankIdx)
|
||||
{
|
||||
andStatus = pFIL->Erase(bankIdx, blockList[bankIdx]);
|
||||
if (FIL_SUCCESS != andStatus)
|
||||
{
|
||||
wFailingCE = bankIdx;
|
||||
wFailingBlock = blockList[bankIdx];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (FIL_SUCCESS != andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Erase failed CE %d Block %d with %s\n", wFailingCE, wFailingBlock, FILErrorToString(andStatus));
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
// Clean check
|
||||
WMR_MEMSET(verifyDataBuffer, TEST_DATA_WATERMARK, testInfo.numCE * testInfo.bytesPerPage);
|
||||
WMR_MEMSET(verifyMetaBuffer, TEST_META_WATERMARK, testInfo.numCE * testInfo.bufferBytesPerMeta);
|
||||
WMR_MEMSET(sectorStats, TEST_STATS_WATERMARK, testInfo.numCE * testInfo.correctableSectorsPerPage);
|
||||
// Only check the first page of each block
|
||||
WMR_PRINT(ALWAYS, "ReadScatteredPages clean check on %d pages\n", testInfo.numCE);
|
||||
andStatus = pFIL->ReadScatteredPages(ceList, pageList, verifyDataBuffer, verifyMetaBuffer, testInfo.numCE, NULL, sectorStats, FALSE32);
|
||||
|
||||
if (FIL_SUCCESS_CLEAN != andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Readback clean check failed with %s\n", FILErrorToString(andStatus));
|
||||
WMR_PRINT(ALWAYS, "Sector Stats:\n");
|
||||
FILTestHexdump(sectorStats, testInfo.numCE * testInfo.correctableSectorsPerPage);
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
// Program scattered pages
|
||||
|
||||
|
||||
WMR_ASSERT(pFIL->WriteScatteredPages != NULL);
|
||||
FillBufferWithCountingPattern((UInt32*)writeDataBuffer, testSeed++, testInfo.numCE * testInfo.bytesPerPage);
|
||||
FillMetaBufferWithPattern(writeMetaBuffer, testSeed++, testInfo.numCE);
|
||||
WMR_PRINT(ALWAYS, "WriteScatteredPages on %d pages\n", testInfo.numCE);
|
||||
andStatus = pFIL->WriteScatteredPages(ceList, pageList, writeDataBuffer, writeMetaBuffer, testInfo.numCE, &wFailingCE, FALSE32, NULL);
|
||||
|
||||
if (FIL_SUCCESS != andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "WriteScatteredPages failed CE %d with %s\n", wFailingCE, FILErrorToString(andStatus));
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
// Read back multiple pages
|
||||
|
||||
WMR_MEMSET(verifyDataBuffer, TEST_DATA_WATERMARK, testInfo.numCE * testInfo.bytesPerPage);
|
||||
WMR_MEMSET(verifyMetaBuffer, TEST_META_WATERMARK, testInfo.numCE * testInfo.bufferBytesPerMeta);
|
||||
WMR_MEMSET(sectorStats, TEST_STATS_WATERMARK, testInfo.numCE * testInfo.correctableSectorsPerPage);
|
||||
WMR_PRINT(ALWAYS, "ReadScatteredPages verify on %d pages\n", testInfo.numCE);
|
||||
andStatus = pFIL->ReadScatteredPages(ceList, pageList, verifyDataBuffer, verifyMetaBuffer, testInfo.numCE, NULL, sectorStats, FALSE32);
|
||||
|
||||
if (FIL_SUCCESS != andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "ReadScatteredPages failed with %s\n", FILErrorToString(andStatus));
|
||||
WMR_PRINT(ALWAYS, "Sector Stats:\n");
|
||||
FILTestHexdump(sectorStats, testInfo.numCE * testInfo.correctableSectorsPerPage);
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
if (WMR_MEMCMP(writeMetaBuffer, verifyMetaBuffer, testInfo.numCE * testInfo.bufferBytesPerMeta))
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Read back contents of pages failed comparison in meta section\n");
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
if (WMR_MEMCMP(writeDataBuffer, verifyDataBuffer, testInfo.numCE * testInfo.bytesPerPage))
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Read back contents of second page failed comparison in data section\n");
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
if (pFIL->EraseMultiple)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "EraseMultiple on %d blocks\n", testInfo.numCE);
|
||||
andStatus = pFIL->EraseMultiple(blockList, TRUE32, TRUE32, &wFailingCE, &wFailingBlock);
|
||||
}
|
||||
else
|
||||
{
|
||||
// only works for 1 bank per ce
|
||||
WMR_PRINT(ALWAYS, "EraseMultiple fallback on %d blocks\n", testInfo.numCE);
|
||||
for (bankIdx = 0; bankIdx < testInfo.numCE; ++bankIdx)
|
||||
{
|
||||
andStatus = pFIL->Erase(bankIdx, blockList[bankIdx]);
|
||||
if (FIL_SUCCESS != andStatus)
|
||||
{
|
||||
wFailingCE = bankIdx;
|
||||
wFailingBlock = blockList[bankIdx];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (FIL_SUCCESS != andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Erase failed CE %d Block %d with %s\n", wFailingCE, wFailingBlock, FILErrorToString(andStatus));
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
// Clean check
|
||||
WMR_MEMSET(verifyDataBuffer, TEST_DATA_WATERMARK, testInfo.numCE * testInfo.bytesPerPage);
|
||||
WMR_MEMSET(verifyMetaBuffer, TEST_META_WATERMARK, testInfo.numCE * testInfo.bufferBytesPerMeta);
|
||||
WMR_MEMSET(sectorStats, TEST_STATS_WATERMARK, testInfo.numCE * testInfo.correctableSectorsPerPage);
|
||||
|
||||
#if (!AND_DISABLE_READ_MULTIPLE)
|
||||
|
||||
// Only check the first page of each block
|
||||
WMR_PRINT(ALWAYS, "ReadMultiplePages clean check on %d pages\n", testInfo.numCE);
|
||||
andStatus = pFIL->ReadMultiplePages(pageList, verifyDataBuffer, verifyMetaBuffer, testInfo.numCE, NULL, sectorStats, FALSE32);
|
||||
|
||||
if (FIL_SUCCESS_CLEAN != andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Readback clean check failed with %s\n", FILErrorToString(andStatus));
|
||||
WMR_PRINT(ALWAYS, "Sector Stats:\n");
|
||||
FILTestHexdump(sectorStats, testInfo.numCE * testInfo.correctableSectorsPerPage);
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
#endif /* if (!AND_DISABLE_READ_MULTIPLE) */
|
||||
|
||||
// Program multiple pages
|
||||
|
||||
FillBufferWithCountingPattern((UInt32*)writeDataBuffer, testSeed++, testInfo.numCE * testInfo.bytesPerPage);
|
||||
FillMetaBufferWithPattern(writeMetaBuffer, testSeed++, testInfo.numCE);
|
||||
WMR_PRINT(ALWAYS, "WriteMultiplePages on %d pages\n", testInfo.numCE);
|
||||
andStatus = pFIL->WriteMultiplePages(pageList, writeDataBuffer, writeMetaBuffer, testInfo.numCE, FALSE32, FALSE32, &wFailingCE, FALSE32, NULL);
|
||||
|
||||
if (FIL_SUCCESS != andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "WriteMultiplePages failed CE %d with %s\n", wFailingCE, FILErrorToString(andStatus));
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
// Read back multiple pages
|
||||
|
||||
WMR_MEMSET(verifyDataBuffer, TEST_DATA_WATERMARK, testInfo.numCE * testInfo.bytesPerPage);
|
||||
WMR_MEMSET(verifyMetaBuffer, TEST_META_WATERMARK, testInfo.numCE * testInfo.bufferBytesPerMeta);
|
||||
WMR_MEMSET(sectorStats, TEST_STATS_WATERMARK, testInfo.numCE * testInfo.correctableSectorsPerPage);
|
||||
|
||||
#if (!AND_DISABLE_READ_MULTIPLE)
|
||||
|
||||
WMR_PRINT(ALWAYS, "ReadMultiplePages verify on %d pages\n", testInfo.numCE);
|
||||
andStatus = pFIL->ReadMultiplePages(pageList, verifyDataBuffer, verifyMetaBuffer, testInfo.numCE, NULL, sectorStats, FALSE32);
|
||||
|
||||
if (FIL_SUCCESS != andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "ReadMultiplePages failed with %s\n", FILErrorToString(andStatus));
|
||||
WMR_PRINT(ALWAYS, "Sector Stats:\n");
|
||||
FILTestHexdump(sectorStats, testInfo.numCE * testInfo.correctableSectorsPerPage);
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
#else /* if (!AND_DISABLE_READ_MULTIPLE) */
|
||||
|
||||
WMR_PRINT(ALWAYS, "ReadScatteredPages verify on %d pages\n", testInfo.numCE);
|
||||
andStatus = pFIL->ReadScatteredPages(ceList, pageList, verifyDataBuffer, verifyMetaBuffer, testInfo.numCE, NULL, sectorStats, FALSE32);
|
||||
|
||||
if (FIL_SUCCESS != andStatus)
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "ReadScatteredPages failed with %s\n", FILErrorToString(andStatus));
|
||||
WMR_PRINT(ALWAYS, "Sector Stats:\n");
|
||||
FILTestHexdump(sectorStats, testInfo.numCE * testInfo.correctableSectorsPerPage);
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
#endif /* if (!AND_DISABLE_READ_MULTIPLE) */
|
||||
|
||||
if (WMR_MEMCMP(writeMetaBuffer, verifyMetaBuffer, testInfo.numCE * testInfo.bufferBytesPerMeta))
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Read back contents of pages failed comparison in meta section\n");
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
if (WMR_MEMCMP(writeDataBuffer, verifyDataBuffer, testInfo.numCE * testInfo.bytesPerPage))
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Read back contents of second page failed comparison in data section\n");
|
||||
goto test_failed;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
WMR_PRINT(ALWAYS, "Skipping Multi-Page test on VS formatted part\n");
|
||||
}
|
||||
|
||||
(void) testSeed;
|
||||
|
||||
WMR_PRINT(ALWAYS, "Interface Test Passed\n");
|
||||
|
||||
WMR_BufZone_Free(&bufZone);
|
||||
|
||||
return TRUE32;
|
||||
|
||||
test_failed:
|
||||
WMR_PRINT(ALWAYS, "Interface Test Failed\n");
|
||||
|
||||
if (writeMetaBuffer)
|
||||
{
|
||||
WMR_FREE(writeMetaBuffer, metaBufferSize);
|
||||
}
|
||||
if (verifyMetaBuffer)
|
||||
{
|
||||
WMR_FREE(verifyMetaBuffer, metaBufferSize);
|
||||
}
|
||||
if (sectorStats)
|
||||
{
|
||||
WMR_FREE(sectorStats, sectorStatsSize);
|
||||
}
|
||||
|
||||
WMR_BufZone_Free(&bufZone);
|
||||
|
||||
return FALSE32;
|
||||
}
|
||||
|
||||
|
||||
const char * FILErrorToString(Int32 filStatus)
|
||||
{
|
||||
|
||||
switch (filStatus)
|
||||
{
|
||||
case FIL_SUCCESS:
|
||||
{
|
||||
return "FIL_SUCCESS";
|
||||
}
|
||||
case FIL_SUCCESS_CLEAN:
|
||||
{
|
||||
return "FIL_SUCCESS_CLEAN";
|
||||
}
|
||||
case FIL_CRITICAL_ERROR:
|
||||
{
|
||||
return "FIL_CRITICAL_ERROR";
|
||||
}
|
||||
case FIL_U_ECC_ERROR:
|
||||
{
|
||||
return "FIL_U_ECC_ERROR";
|
||||
}
|
||||
case FIL_WRITE_FAIL_ERROR:
|
||||
{
|
||||
return "FIL_WRITE_FAIL_ERROR";
|
||||
}
|
||||
case FIL_UNSUPPORTED_ERROR:
|
||||
{
|
||||
return "FIL_UNSUPPORTED_ERROR";
|
||||
}
|
||||
default:
|
||||
{
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void InitPageListFromBlocks(const UInt16 *blockList, UInt32 *pageList)
|
||||
{
|
||||
UInt32 pageIdx;
|
||||
|
||||
// Fill in page list based on provided blocks
|
||||
// XXX Mind the block gap
|
||||
for (pageIdx = 0; pageIdx < (2 * testInfo.numBanks); ++pageIdx)
|
||||
{
|
||||
pageList[pageIdx] = (blockList[pageIdx % testInfo.numBanks] * testInfo.pagesPerBlock) + (pageIdx / testInfo.numBanks);
|
||||
}
|
||||
}
|
||||
|
||||
static void FillBufferWithCountingPattern(UInt32 *buffer, UInt32 startValue, UInt32 bytes)
|
||||
{
|
||||
UInt32 wordIdx;
|
||||
const UInt32 kWordsToFill = bytes / sizeof(UInt32);
|
||||
|
||||
for (wordIdx = 0; wordIdx < kWordsToFill; wordIdx += 1)
|
||||
{
|
||||
if ((wordIdx + 1) == kWordsToFill)
|
||||
{
|
||||
// Last word may not be full
|
||||
UInt8 *endOfBuffer = (UInt8*) &buffer[wordIdx];
|
||||
switch (bytes % sizeof(UInt32))
|
||||
{
|
||||
case 0:
|
||||
endOfBuffer[1] = (startValue >> 24) & 0xFF;
|
||||
// fall through
|
||||
case 3:
|
||||
endOfBuffer[1] = (startValue >> 16) & 0xFF;
|
||||
// fall through
|
||||
case 2:
|
||||
endOfBuffer[1] = (startValue >> 8) & 0xFF;
|
||||
// fall through
|
||||
case 1:
|
||||
endOfBuffer[1] = startValue & 0xFF;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer[wordIdx] = startValue++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void FillMetaBufferWithPattern(UInt8 *buffer, UInt32 startValue, UInt32 numPages)
|
||||
{
|
||||
typedef struct
|
||||
{
|
||||
UInt32 valid1;
|
||||
UInt32 valid2;
|
||||
UInt16 valid3;
|
||||
UInt16 pad;
|
||||
} _TestMeta;
|
||||
|
||||
_TestMeta *pTestMeta = (_TestMeta*) buffer;
|
||||
|
||||
while (numPages--)
|
||||
{
|
||||
pTestMeta->valid1 = startValue++;
|
||||
pTestMeta->valid2 = startValue++;
|
||||
pTestMeta->valid3 = startValue++;
|
||||
pTestMeta->pad = ~0;
|
||||
|
||||
pTestMeta++;
|
||||
}
|
||||
}
|
||||
|
||||
#define HEXDUMP_WIDTH (16)
|
||||
static void FILTestHexdump(void *data, UInt32 length)
|
||||
{
|
||||
UInt32 i, j;
|
||||
UInt8 *bytes = (UInt8*) data;
|
||||
for (i = 0; i < length; i += HEXDUMP_WIDTH)
|
||||
{
|
||||
for (j = 0; (j < HEXDUMP_WIDTH) && ((i + j) < length); j++)
|
||||
{
|
||||
_WMR_PRINT(" %02x", (UInt32) *bytes++);
|
||||
}
|
||||
_WMR_PRINT("\n");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user