first and last commit

This commit is contained in:
Chris Nutter committed 2023-07-08 13:03:17 -07:00
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_ */
+212
View File
@@ -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_ */
+155
View File
@@ -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_ */
+265
View File
@@ -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_ */
+171
View File
@@ -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");
}
}
+5
View File
@@ -0,0 +1,5 @@
_WMR_Init
_WMR_GetFPart
_WMR_PreInit
_WMR_CtrlIO
_raw_nand_init
+58
View File
@@ -0,0 +1,58 @@
# 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.
#
WHIMORY_DIR := $(GET_LOCAL_DIR)
WHIMORY_BUILD := $(call TOLIBDIR,$(WHIMORY_DIR)/WHIMORY.a)
COMMONLIBS += WHIMORY
# Only process the remainder of the makefile if we are building libraries
#
ifeq ($(MAKEPHASE),libraries)
NAND_DIR := $(patsubst %/,%,$(dir $(GET_LOCAL_DIR)))
MODULES += \
drivers/flash_nand/OAM \
lib/blockdev
GLOBAL_INCLUDES += \
$(WHIMORY_DIR)/Whimory/Core/VFL \
$(WHIMORY_DIR)/Whimory/Core/FTL \
$(WHIMORY_DIR)/Whimory/Core/FPart \
$(WHIMORY_DIR)/Whimory/Exam \
$(WHIMORY_DIR)/Whimory/Inc \
$(NAND_DIR)/OAM \
$(NAND_DIR)/OAM/iBoot
# base library files
WHIMORY_SUBOBJS += \
$(WHIMORY_DIR)/raw_nand.o \
$(WHIMORY_DIR)/Whimory/Core/FTL/FTLInterface.o \
$(WHIMORY_DIR)/Whimory/Core/FPart/FPart.o \
$(WHIMORY_DIR)/Whimory/Core/FTL/yaFTL.o \
$(WHIMORY_DIR)/Whimory/Core/FTL/yaFTL_BTOC.o \
$(WHIMORY_DIR)/Whimory/Core/VFL/VFLBuffer.o \
$(WHIMORY_DIR)/Whimory/Core/VFL/VFLInterface.o \
$(WHIMORY_DIR)/Whimory/Core/VFL/VSVFLInterface.o \
$(WHIMORY_DIR)/Whimory/Exam/WMRExam.o \
$(WHIMORY_DIR)/Whimory/Test/FILTest.o
WHIMORY_SUBOBJS := $(call TOLIBOBJDIR,$(WHIMORY_SUBOBJS))
ALL_DEPS += $(WHIMORY_SUBOBJS:%o=%d)
WHIMORY_OBJS := $(call TOLIBOBJDIR,$(WHIMORY_DIR)/WHIMORY.o)
$(WHIMORY_OBJS): $(WHIMORY_SUBOBJS)
@echo LIB_LD $@
$(_v)$(_LD) $(LIBRARY_LDFLAGS) $(WHIMORY_SUBOBJS) -o $@ -exported_symbols_list $(WHIMORY_DIR)/export.txt
$(WHIMORY_BUILD): $(WHIMORY_OBJS)
endif
+88
View File
@@ -0,0 +1,88 @@
/*
* Copyright (c) 2007-2009 Apple Inc. All rights reserved.
* Copyright (c) 2006 Apple Computer, 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 <debug.h>
#include <lib/heap.h>
#include <lib/blockdev.h>
#include <lib/partition.h>
#include <platform/clocks.h>
#include <sys/menu.h>
#include "WMRConfig.h"
#include "ANDTypes.h"
#include "FIL.h"
#include "VFLBuffer.h"
#include "VFL.h"
#include "FTL.h"
#include "WMRExam.h"
#include "WMROAM.h"
extern uint32_t nand_fsys_block_offset;
static int nand_filesys_init(uint32_t block_size, uint32_t block_count);
static FTLFunctions *TLFuncPtr=NULL;
static int nand_read_block_hook(struct blockdev *_dev, void *ptr, block_addr block, uint32_t count)
{
Int32 err;
if (count > 0) {
err = TLFuncPtr->Read(block, count, ptr);
//err = FTL_Read(block, count, ptr);
if (err != FIL_SUCCESS) {
printf("nand_read_block_hook: failure %d reading block %u, count %zd\n", err, block, count);
return -1;
}
}
return count;
}
int raw_nand_init(void)
{
Int32 intRes;
uint32_t block_size, block_count;
uint32_t index_cache = 0;
dprintf(DEBUG_INFO,"raw_nand_init()\n");
// Initialise the FTL
intRes = WMR_Init(&block_count, &block_size, &index_cache, gWhimoryInitParameters, nand_fsys_block_offset);
if (intRes != WMR_SUCCESS) {
dprintf(DEBUG_CRITICAL, "Raw NAND FTL failed initialisation\n");
return -1;
}
if (0 != nand_filesys_init(block_size, block_count))
return -1;
return 0;
}
static int nand_filesys_init(uint32_t block_size, uint32_t block_count)
{
struct blockdev *nand;
TLFuncPtr = WMR_GetFTL();
// build a block device around this NAND
nand = malloc(sizeof(struct blockdev));
construct_blockdev(nand, "nand0", (off_t)block_count * block_size, block_size);
nand->read_block_hook = &nand_read_block_hook;
register_blockdev(nand);
/* scan ourselves for partitions and publish subdevices */
partition_scan_and_publish_subdevices("nand0");
return 0;
}
+35
View File
@@ -0,0 +1,35 @@
# Copyright (c) 2007-2009 Apple Inc. All rights reserved.
# Copyright (c) 2006 Apple Computer, 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.
#
LOCAL_DIR := $(GET_LOCAL_DIR)
OPTIONS += \
WITH_RAW_NAND=1
MODULES += \
drivers/flash_nand
GLOBAL_INCLUDES += \
$(LOCAL_DIR)/Whimory/Core/FPart \
$(LOCAL_DIR)/Whimory/Core/VFL \
$(LOCAL_DIR)/Whimory/Exam
#
# If a NAND FTL has not been configured, we need some of the raw NAND bits.
#
ifeq ($(WITH_NAND_FTL),)
ALL_OBJS += \
$(LOCAL_DIR)/Whimory/Core/FPart/FPart.o \
$(LOCAL_DIR)/Whimory/Core/VFL/VFLBuffer.o \
$(LOCAL_DIR)/Whimory/Exam/WMRExam.o
else
LIBRARY_MODULES += $(LOCAL_DIR)
endif