/kern_oII/drivers/tfsr/Core/BML/FSR_BML_BBMMount.c

http://omnia2droid.googlecode.com/ · C · 1523 lines · 926 code · 196 blank · 401 comment · 218 complexity · 8feff690509a3ea923c98e35a5fd998f MD5 · raw file

  1. /**
  2. * @mainpage Flex Sector Remapper : LinuStoreIII_1.2.0_b032-FSR_1.2.1p1_b129_RTM
  3. *
  4. * @section Intro
  5. * Flash Translation Layer for Flex-OneNAND and OneNAND
  6. *
  7. * @section Copyright
  8. *---------------------------------------------------------------------------*
  9. * *
  10. * Copyright (C) 2003-2010 Samsung Electronics *
  11. * This program is free software; you can redistribute it and/or modify *
  12. * it under the terms of the GNU General Public License version 2 as *
  13. * published by the Free Software Foundation. *
  14. * *
  15. *---------------------------------------------------------------------------*
  16. *
  17. * @section Description
  18. *
  19. */
  20. /**
  21. * @file FSR_BML_BBMMount.c
  22. * @brief This file contains the routine for mounting of reservoir
  23. * @author MinYoung Kim
  24. * @date 30-MAY-2007
  25. * @remark
  26. * REVISION HISTORY
  27. * @n 30-MAY-2007 [MinYoung Kim] : first writing
  28. *
  29. */
  30. /*****************************************************************************/
  31. /* Header file inclusions */
  32. /*****************************************************************************/
  33. #define FSR_NO_INCLUDE_STL_HEADER
  34. #include "FSR.h"
  35. #include "FSR_BML_Config.h"
  36. #include "FSR_BML_Types.h"
  37. #include "FSR_BML_BBMCommon.h"
  38. #include "FSR_BML_BBMMount.h"
  39. #if !defined(TINY_FSR)
  40. #include "FSR_BML_BadBlkMgr.h"
  41. #endif /* TINY_FSR */
  42. /*****************************************************************************/
  43. /* Function prototype */
  44. /*****************************************************************************/
  45. PRIVATE INT32 _Mount (BmlVolCxt *pstVol,
  46. BmlDevCxt *pstDev,
  47. FSRPartI *pstPI,
  48. FSRPIExt *pstPExt,
  49. UINT32 nDieIdx);
  50. PRIVATE INT32 _ScanReservoir (BmlDevCxt *pstDev,
  51. BmlVolCxt *pstVol,
  52. UINT32 nDieIdx);
  53. PRIVATE BOOL32 _IsFreePg (BmlVolCxt *pstVol,
  54. BmlReservoir *pstRsv,
  55. UINT32 nPDev,
  56. UINT32 nPbn,
  57. UINT32 nPgOffset);
  58. PRIVATE BOOL32 _FindValidMetaData (BmlDevCxt *pstDev,
  59. BmlVolCxt *pstVol,
  60. BmlDieCxt *pstDie,
  61. UINT32 nPbn,
  62. UINT32 *pValidOffset,
  63. UINT32 nType);
  64. PRIVATE BOOL32 _LoadBMS (BmlVolCxt *pstVol,
  65. BmlReservoir *pstRsv,
  66. BmlBMS *pstBMS);
  67. PRIVATE INT32 _LoadMetaData (BmlVolCxt *pstVol,
  68. BmlDevCxt *pstDev,
  69. UINT32 nDieIdx,
  70. UINT32 nPbn,
  71. UINT32 nStartOffset,
  72. VOID *pstPI,
  73. UINT32 nType);
  74. /*
  75. * @brief This function mounts BmlReservoir of the given (nPDev) device.
  76. * @n Actually, it search for latest LPCB, UPCB. And load PI and PIExt.
  77. * @n Then, it loads the latest BMI.
  78. *
  79. * @param[in] *pstVol : volume context pointer
  80. * @param[in] *pstDev : device context pointer
  81. * @param[in] *pstPI : pointer for partition info
  82. * @param[in] *pstPExt : pointer for partition extension info
  83. *
  84. * @return FSR_BML_SUCCESS
  85. * @return FSR_BML_CRITICAL_ERROR
  86. *
  87. * @author MinYoung Kim
  88. * @version 1.0.0
  89. * @remark none
  90. *
  91. * @since since v1.0.0
  92. * @exception none
  93. *
  94. */
  95. PUBLIC INT32
  96. FSR_BBM_Mount(BmlVolCxt *pstVol,
  97. BmlDevCxt *pstDev,
  98. FSRPartI *pstPI,
  99. FSRPIExt *pstPExt)
  100. {
  101. INT32 nRet = FSR_BML_SUCCESS;
  102. UINT32 nDieIdx;
  103. FSR_STACK_VAR;
  104. FSR_STACK_END;
  105. FSR_ASSERT((pstVol != NULL) && (pstDev != NULL));
  106. FSR_DBZ_DBGMOUT(FSR_DBZ_BML_BBM, (TEXT("[BBM:IN ] ++%s(PDev: %d)\r\n"),
  107. __FSR_FUNC__, pstDev->nDevNo));
  108. do
  109. {
  110. /* calculate BmlReservoir size before mounting */
  111. nRet = _CalcRsvrSize(pstVol, pstDev, NULL, FALSE32);
  112. if (nRet != FSR_BML_SUCCESS)
  113. {
  114. FSR_DBZ_RTLMOUT(FSR_DBZ_ERROR, (TEXT("[BBM:ERR] _CalcRsvrSize(nFlag: 0x%x) is failed\r\n"), FALSE32));
  115. break;
  116. }
  117. /* initialize memory and set variables for BmlReservoir */
  118. _InitBBM(pstVol, pstDev);
  119. /* set volume context */
  120. _SetVolCxt(pstVol, pstDev);
  121. /* In case of DDP, do BBM mount for each die */
  122. for (nDieIdx = 0; nDieIdx < pstVol->nNumOfDieInDev; nDieIdx++)
  123. {
  124. /* mount for each die */
  125. nRet = _Mount(pstVol, pstDev, pstPI, pstPExt, nDieIdx);
  126. if (nRet != FSR_BML_SUCCESS)
  127. {
  128. FSR_DBZ_RTLMOUT(FSR_DBZ_ERROR, (TEXT("[BBM:ERR] _Mount(nDie:%d) is failed\r\n"), nDieIdx));
  129. break;
  130. }
  131. }
  132. if (nRet != FSR_BML_SUCCESS)
  133. {
  134. break;
  135. }
  136. } while (0);
  137. FSR_DBZ_DBGMOUT(FSR_DBZ_BML_BBM, (TEXT("[BBM:OUT] --%s(nRe: 0x%x)\r\n"), __FSR_FUNC__, nRet));
  138. return nRet;
  139. }
  140. /**
  141. * @brief this function unlock blocks in the reservoir
  142. *
  143. * @param[in] *pstVol : volume context pointer
  144. * @param[in] *pstDev : device context pointer
  145. * @param[in] nDieIdx : die index
  146. *
  147. * @return FSR_BML_SUCCESS
  148. * @return FSR_BML_CANT_UNLOCK_BLOCK
  149. * @return FSR_BML_CRITICAL_ERROR
  150. *
  151. * @author MinYoung Kim
  152. * @version 1.0.0
  153. * @remark none
  154. *
  155. * @since since v1.0.0
  156. * @exception none
  157. *
  158. */
  159. PUBLIC INT32
  160. FSR_BBM_UnlockRsvr(BmlVolCxt *pstVol,
  161. BmlDevCxt *pstDev,
  162. UINT32 nDieIdx)
  163. {
  164. LLDProtectionArg stLLDPrtArg;
  165. BmlReservoir *pstRsv;
  166. BmlReservoirSh *pstRsvSh;
  167. BmlBMI *pstBMI;
  168. UINT32 nSbn;
  169. UINT32 nIdx;
  170. UINT32 nByteReturned;
  171. UINT32 nErrPbn;
  172. UINT32 nLockState;
  173. INT32 nLLDRe;
  174. INT32 nRet = FSR_BML_SUCCESS;
  175. UINT32 nNumOfRemainLockedRCB;
  176. FSR_STACK_VAR;
  177. FSR_STACK_END;
  178. FSR_DBZ_DBGMOUT(FSR_DBZ_BML_BBM, (TEXT("[BBM:IN ] ++%s(PDev: %d, nDieIdx: %d)\r\n"),
  179. __FSR_FUNC__, pstDev->nDevNo, nDieIdx));
  180. pstRsv = pstDev->pstDie[nDieIdx]->pstRsv;
  181. pstRsvSh = pstDev->pstDie[nDieIdx]->pstRsvSh;
  182. pstBMI = pstRsv->pstBMI;
  183. do
  184. {
  185. /* unlock reservoir meta blocks or unmapped reservoir block */
  186. for (nSbn = pstRsv->n1stSbnOfRsvr; nSbn <= pstRsv->nLastSbnOfRsvr; nSbn++)
  187. {
  188. /* unmapped area or BBM meta block */
  189. if ((_IsAllocRB(pstRsv, nSbn) != TRUE32) ||
  190. (nSbn == pstRsvSh->nUPCBSbn) ||
  191. (nSbn == pstRsvSh->nLPCBSbn) ||
  192. (nSbn == pstRsvSh->nTPCBSbn) ||
  193. (nSbn == pstRsvSh->nREFSbn))
  194. {
  195. /* get lock state of the block */
  196. nLLDRe = pstVol->LLD_IOCtl(pstDev->nDevNo,
  197. FSR_LLD_IOCTL_GET_LOCK_STAT,
  198. (UINT8 *) &nSbn,
  199. sizeof(nSbn),
  200. (UINT8*) &nLockState,
  201. sizeof(nLockState),
  202. &nByteReturned);
  203. if (nLLDRe != FSR_LLD_SUCCESS)
  204. {
  205. nRet = FSR_BML_CRITICAL_ERROR;
  206. FSR_DBZ_RTLMOUT(FSR_DBZ_ERROR, (TEXT("[BBM:ERR] Can not get lock status of RCB block (Skip this block)\r\n")));
  207. FSR_DBZ_RTLMOUT(FSR_DBZ_ERROR, (TEXT("[BBM:ERR] nPDev: %d, nOrgSbn: %d, nLLDRe: 0x%x\r\n"), pstDev->nDevNo, nSbn, nLLDRe));
  208. break;
  209. }
  210. if (nLockState == FSR_LLD_BLK_STAT_LOCKED)
  211. {
  212. /* Set the parameter of LLD_IOCtl() */
  213. stLLDPrtArg.nStartBlk = nSbn;
  214. stLLDPrtArg.nBlks = 1;
  215. nLLDRe = pstVol->LLD_IOCtl(pstDev->nDevNo,
  216. FSR_LLD_IOCTL_UNLOCK_BLOCK,
  217. (UINT8 *) &stLLDPrtArg,
  218. sizeof(stLLDPrtArg),
  219. (UINT8 *) &nErrPbn,
  220. sizeof(nErrPbn),
  221. &nByteReturned);
  222. if (nLLDRe != FSR_LLD_SUCCESS)
  223. {
  224. nRet= FSR_BML_CANT_UNLOCK_BLOCK;
  225. FSR_DBZ_RTLMOUT(FSR_DBZ_ERROR, (TEXT("[BBM:ERR] Can't unlock BmlReservoir blocks (Skip this block, nPDev: %d, nSbn: %d)\r\n"),
  226. pstDev->nDevNo, nSbn));
  227. break;
  228. }
  229. }
  230. /*
  231. * if (nLockState == FSR_LLD_BLK_STAT_LOCKED_TIGHT), skip current block
  232. * if current block is already locked tightly,
  233. * BBM does not try to unlock the block.
  234. */
  235. }
  236. }
  237. if (nRet != FSR_BML_SUCCESS)
  238. {
  239. break;
  240. }
  241. /* multi plane case */
  242. if (pstVol->nNumOfPlane > 1)
  243. {
  244. /* unlock unused reservoir candidate blocks */
  245. for ( nNumOfRemainLockedRCB = pstBMI->nNumOfRCBs, nIdx = 0;
  246. ( nNumOfRemainLockedRCB > 0 ) && ( nIdx < ( ( pstRsv->nNumOfRsvrInSLC + pstRsv->nNumOfRsvrInMLC ) / 2 ) );
  247. nIdx ++ )
  248. {
  249. /* if the block is in the RCB queue, the block is unlocked */
  250. nSbn = pstRsv->pstRCB[nIdx];
  251. /* If the getting RCB is already in use, Don't touch */
  252. if ( nSbn == 0xFFFF )
  253. {
  254. continue;
  255. }
  256. /* get lock state of the block */
  257. nLLDRe = pstVol->LLD_IOCtl(pstDev->nDevNo,
  258. FSR_LLD_IOCTL_GET_LOCK_STAT,
  259. (UINT8 *) &nSbn,
  260. sizeof(nSbn),
  261. (UINT8*) &nLockState,
  262. sizeof(nLockState),
  263. &nByteReturned);
  264. if (nLLDRe != FSR_LLD_SUCCESS)
  265. {
  266. nRet = FSR_BML_CRITICAL_ERROR;
  267. FSR_DBZ_RTLMOUT(FSR_DBZ_ERROR, (TEXT("[BBM:ERR] Can not get lock status of RCB block\r\n")));
  268. FSR_DBZ_RTLMOUT(FSR_DBZ_ERROR, (TEXT("[BBM:ERR] nPDev: %d, nOrgSbn: %d, nLLDRe: 0x%x\r\n"), pstDev->nDevNo, nSbn, nLLDRe));
  269. break;
  270. }
  271. /* if the block is locked */
  272. if (nLockState == FSR_LLD_BLK_STAT_LOCKED)
  273. {
  274. /* Set the parameter of LLD_IOCtl() */
  275. stLLDPrtArg.nStartBlk = nSbn;
  276. stLLDPrtArg.nBlks = 1;
  277. nLLDRe = pstVol->LLD_IOCtl(pstDev->nDevNo,
  278. FSR_LLD_IOCTL_UNLOCK_BLOCK,
  279. (UINT8 *) &stLLDPrtArg,
  280. sizeof(stLLDPrtArg),
  281. (UINT8 *) &nErrPbn,
  282. sizeof(nErrPbn),
  283. &nByteReturned);
  284. if (nLLDRe != FSR_LLD_SUCCESS)
  285. {
  286. nRet= FSR_BML_CANT_UNLOCK_BLOCK;
  287. FSR_DBZ_RTLMOUT(FSR_DBZ_ERROR, (TEXT("[BBM:ERR] Can't unlock free RCB blocks(nPDev: %d, nSbn: %d)\r\n"),
  288. pstDev->nDevNo, nSbn));
  289. break;
  290. }
  291. }
  292. nNumOfRemainLockedRCB --;
  293. /*
  294. * if (nLockState == FSR_LLD_BLK_STAT_LOCKED_TIGHT), skip current block
  295. * if current block is already locked tightly,
  296. * BBM does not try to unlock the block.
  297. */
  298. } /* end of for ( nNumOfRemainLockedRCB = pstBMI->nNumOfRCBs, ... */
  299. } /* end of if (multi-plane) */
  300. } while(0);
  301. FSR_DBZ_DBGMOUT(FSR_DBZ_BML_BBM, (TEXT("[BBM:OUT] --%s(nRe: 0x%x)\r\n"), __FSR_FUNC__, nRet));
  302. return nRet;
  303. }
  304. /*
  305. * @brief This function mounts BmlReservoir of the given (nPDev) device.
  306. * @n Actually, it search for latest LPCB, UPCB. And load PI and PIExt.
  307. * @n Then, it loads the latest BMI.
  308. *
  309. * @param[in] *pstVol : volume context pointer
  310. * @param[in] *pstDev : device context pointer
  311. * @param[in] *pstPI : pointer for partition info
  312. * @param[in] *pstPExt : pointer for partition extension info
  313. * @param[in] nDieIdx : index of die
  314. *
  315. * @return FSR_BML_SUCCESS
  316. * @return FSR_BML_NO_LPCB
  317. * @return FSR_BML_NO_UPCB
  318. * @return FSR_BML_NO_TPCB
  319. * @return FSR_BML_LOAD_LBMS_FAILURE
  320. * @return FSR_BML_CRITICAL_ERROR
  321. *
  322. * @author MinYoung Kim
  323. * @version 1.0.0
  324. * @remark none
  325. *
  326. * @since since v1.0.0
  327. * @exception none
  328. *
  329. */
  330. PRIVATE INT32
  331. _Mount(BmlVolCxt *pstVol,
  332. BmlDevCxt *pstDev,
  333. FSRPartI *pstPI,
  334. FSRPIExt *pstPExt,
  335. UINT32 nDieIdx)
  336. {
  337. BmlReservoir *pstRsv;
  338. BmlReservoirSh *pstRsvSh;
  339. INT32 nRet = FSR_BML_SUCCESS;
  340. BOOL32 bRet = FALSE32;
  341. UINT32 nValidOffset;
  342. UINT16 nPCBSbn;
  343. FSR_STACK_VAR;
  344. FSR_STACK_END;
  345. FSR_DBZ_DBGMOUT(FSR_DBZ_BML_BBM, (TEXT("[BBM:IN ] ++%s(nPDev: %d, nDieIdx: %d)\r\n"),
  346. __FSR_FUNC__, pstDev->nDevNo, nDieIdx));
  347. pstRsv = pstDev->pstDie[nDieIdx]->pstRsv;
  348. pstRsvSh = pstDev->pstDie[nDieIdx]->pstRsvSh;
  349. /* In order to search latest UPCB and latest LPCB, scan BmlReservoir */
  350. nRet = _ScanReservoir(pstDev, pstVol, nDieIdx);
  351. /* If there is no LPCB or no UPCB,
  352. it is unformated status or critical error */
  353. if (nRet != FSR_BML_SUCCESS)
  354. {
  355. FSR_DBZ_RTLMOUT(FSR_DBZ_ERROR, (TEXT("[BBM:ERR] _ScanReservoir(nPDev: %d, nDie:%d) is failed\r\n"), pstDev->nDevNo, nDieIdx));
  356. FSR_DBZ_DBGMOUT(FSR_DBZ_BML_BBM, (TEXT("[BBM:OUT] --%s(nRe: 0x%x)\r\n"), __FSR_FUNC__, nRet));
  357. return nRet;
  358. }
  359. /* Find valid meta data for LPCB */
  360. bRet = _FindValidMetaData(pstDev, pstVol, pstDev->pstDie[nDieIdx], pstRsvSh->nLPCBSbn, &nValidOffset, BML_TYPE_LPCB);
  361. if (bRet == FALSE32)
  362. {
  363. /* If TPCB exists for backup */
  364. if (pstRsvSh->nTPCBSbn != 0)
  365. {
  366. /* Find valid meta data in TPCB */
  367. bRet = _FindValidMetaData(pstDev, pstVol, pstDev->pstDie[nDieIdx], pstRsvSh->nTPCBSbn, &nValidOffset, BML_TYPE_TPCB | BML_TYPE_LPCB);
  368. if (bRet == FALSE32)
  369. {
  370. FSR_DBZ_RTLMOUT(FSR_DBZ_ERROR, (TEXT("[BBM:ERR] _FindValidMetaData(nSbn:%d, LPCB) is failed\r\n"), pstRsvSh->nLPCBSbn));
  371. FSR_DBZ_DBGMOUT(FSR_DBZ_BML_BBM, (TEXT("[BBM:OUT] --%s(nRe: 0x%x)\r\n"), __FSR_FUNC__, FSR_BML_NO_LPCB));
  372. return FSR_BML_NO_LPCB;
  373. }
  374. /* swap LPCB with TPCB to restore previous data */
  375. nPCBSbn = pstRsvSh->nLPCBSbn;
  376. pstRsvSh->nLPCBSbn = pstRsvSh->nTPCBSbn;
  377. pstRsvSh->nTPCBSbn = nPCBSbn;
  378. }
  379. }
  380. /* Load meta data for LPCB */
  381. nRet = _LoadMetaData(pstVol, pstDev, nDieIdx, pstRsvSh->nLPCBSbn, nValidOffset, pstPI, BML_TYPE_LPCB);
  382. if (nRet != FSR_BML_SUCCESS)
  383. {
  384. FSR_DBZ_RTLMOUT(FSR_DBZ_ERROR, (TEXT("[BBM:ERR] _LoadMetaData(nPDev: %d, nDieIdx: %d, nSbn:%d, nOffset: %d, LPCB) is failed\r\n"),
  385. pstDev->nDevNo, nDieIdx, pstRsvSh->nLPCBSbn, nValidOffset));
  386. FSR_DBZ_DBGMOUT(FSR_DBZ_BML_BBM, (TEXT("[BBM:OUT] --%s(nRe: 0x%x)\r\n"), __FSR_FUNC__, FSR_BML_LOAD_LBMS_FAILURE));
  387. return FSR_BML_LOAD_LBMS_FAILURE;
  388. }
  389. /* Find valid meta data for UPCB */
  390. bRet = _FindValidMetaData(pstDev, pstVol, pstDev->pstDie[nDieIdx], pstRsvSh->nUPCBSbn, &nValidOffset, BML_TYPE_UPCB);
  391. if (bRet == FALSE32)
  392. {
  393. /* If TPCB exists for backup */
  394. if (pstRsvSh->nTPCBSbn != 0)
  395. {
  396. /* Find valid meta data in TPCB */
  397. bRet = _FindValidMetaData(pstDev, pstVol, pstDev->pstDie[nDieIdx], pstRsvSh->nTPCBSbn, &nValidOffset, BML_TYPE_TPCB | BML_TYPE_UPCB);
  398. if (bRet == FALSE32)
  399. {
  400. FSR_DBZ_RTLMOUT(FSR_DBZ_ERROR, (TEXT("[BBM:ERR] _FindValidMetaData(nSbn:%d, UPCB) is failed\r\n"), pstRsvSh->nUPCBSbn));
  401. FSR_DBZ_DBGMOUT(FSR_DBZ_BML_BBM, (TEXT("[BBM:OUT] --%s(nRe: 0x%x)\r\n"), __FSR_FUNC__, FSR_BML_NO_UPCB));
  402. return FSR_BML_NO_UPCB;
  403. }
  404. /* swap UPCB with TPCB to restore previous data */
  405. nPCBSbn = pstRsvSh->nUPCBSbn;
  406. pstRsvSh->nUPCBSbn = pstRsvSh->nTPCBSbn;
  407. pstRsvSh->nTPCBSbn = nPCBSbn;
  408. }
  409. }
  410. /* PIExt data is stored in die 0 of device 0 */
  411. if ((pstDev->nDevNo == 0) && (nDieIdx == 0))
  412. {
  413. /* Load meta data for UPCB */
  414. nRet = _LoadMetaData(pstVol, pstDev, nDieIdx, pstRsvSh->nUPCBSbn, nValidOffset, pstPExt, BML_TYPE_UPCB);
  415. }
  416. /* other cases */
  417. else
  418. {
  419. /* Load meta data for UPCB (Do not load PIExt) */
  420. nRet = _LoadMetaData(pstVol, pstDev, nDieIdx, pstRsvSh->nUPCBSbn, nValidOffset, NULL, BML_TYPE_UPCB);
  421. }
  422. if (nRet != FSR_BML_SUCCESS)
  423. {
  424. FSR_DBZ_RTLMOUT(FSR_DBZ_ERROR, (TEXT("[BBM:ERR] _LoadMetaData(nPDev: %d, nDieIdx: %d, nSbn:%d, nOffset: %d, UPCB) is failed\r\n"),
  425. pstDev->nDevNo, nDieIdx, pstRsvSh->nUPCBSbn, nValidOffset));
  426. FSR_DBZ_DBGMOUT(FSR_DBZ_BML_BBM, (TEXT("[BBM:OUT] --%s(nRe: 0x%x)\r\n"), __FSR_FUNC__, FSR_BML_LOAD_UBMS_FAILURE));
  427. return FSR_BML_LOAD_UBMS_FAILURE;
  428. }
  429. /* sorts by ascending power of pstBMI->pstBMF[].nSbn */
  430. _SortBMI(pstRsv);
  431. /* make BUMap to enhance performance of address translation */
  432. _ReconstructBUMap(pstVol, pstRsv, nDieIdx);
  433. FSR_DBZ_DBGMOUT(FSR_DBZ_BML_BBM, (TEXT("[BBM:OUT] --%s(nRe: 0x%x)\r\n"), __FSR_FUNC__, nRet));
  434. return nRet;
  435. }
  436. /*
  437. * @brief This function scans BmlReservoir to search latest UPCB/LPCB
  438. *
  439. * @param[in] *pstVol : volume context pointer
  440. * @param[in] *pstDev : device context pointer
  441. * @param[in] nDieIdx : Index of die
  442. *
  443. * @return FSR_BML_SUCCESS
  444. * @return FSR_BML_NO_UPCB
  445. * @return FSR_BML_NO_LPCB
  446. *
  447. * @author MinYoung Kim
  448. * @version 1.0.0
  449. * @remark none
  450. *
  451. * @since since v1.0.0
  452. * @exception none
  453. *
  454. */
  455. PRIVATE INT32
  456. _ScanReservoir(BmlDevCxt *pstDev,
  457. BmlVolCxt *pstVol,
  458. UINT32 nDieIdx)
  459. {
  460. FSRSpareBuf stSBuf;
  461. BmlReservoir *pstRsv;
  462. BmlReservoirSh *pstRsvSh;
  463. BmlPoolCtlHdr *pstPCH;
  464. INT32 nLLDRe;
  465. INT32 nUPCHCmpRet;
  466. INT32 nLPCHCmpRet;
  467. UINT32 nPbn;
  468. UINT32 n1stSbnOfRsvr;
  469. UINT32 nLastSbnOfRsvr;
  470. UINT32 nCnt;
  471. UINT32 nDZMask;
  472. BOOL32 bUPCB = FALSE32;
  473. BOOL32 bLPCB = FALSE32;
  474. FSR_STACK_VAR;
  475. FSR_STACK_END;
  476. FSR_DBZ_DBGMOUT(FSR_DBZ_BML_BBM, (TEXT("[BBM:IN ] ++%s(nPDev: %d, nDieIdx: %d)\r\n"),
  477. __FSR_FUNC__, pstDev->nDevNo, nDieIdx));
  478. pstRsv = pstDev->pstDie[nDieIdx]->pstRsv;
  479. pstRsvSh = pstDev->pstDie[nDieIdx]->pstRsvSh;
  480. /* initialize age of PCB blocks */
  481. pstRsvSh->nUPcbAge = 0;
  482. pstRsvSh->nLPcbAge = 0;
  483. /* Flex-OneNAND: SLC + MLC type */
  484. if (pstRsv->nRsvrType == BML_HYBRID_RESERVOIR)
  485. {
  486. /* Set range of BmlReservoir */
  487. n1stSbnOfRsvr = pstRsv->n1stSbnOfRsvr;
  488. nLastSbnOfRsvr = pstRsv->n1stSbnOfMLC - 1;
  489. }
  490. /* MLC only or SLC only */
  491. else
  492. {
  493. /* Set range of BmlReservoir */
  494. n1stSbnOfRsvr = pstRsv->n1stSbnOfRsvr;
  495. nLastSbnOfRsvr = pstRsv->nLastSbnOfRsvr;
  496. }
  497. FSR_OAM_MEMCPY(&stSBuf, pstRsv->pSBuf, sizeof(FSRSpareBuf));
  498. if (stSBuf.nNumOfMetaExt != 0)
  499. {
  500. stSBuf.nNumOfMetaExt = pstVol->nSizeOfPage / FSR_PAGE_SIZE_PER_SPARE_BUF_EXT;
  501. }
  502. FSR_DBZ_RTLMOUT(FSR_DBZ_ERROR, (TEXT("[BBM:INF] Scan from %d to %d to find BML meta blocks (die: %d)\r\n"),
  503. n1stSbnOfRsvr, nLastSbnOfRsvr, nDieIdx));
  504. nCnt = 0;
  505. /* scan all blocks in BmlReservoir */
  506. for (nPbn = n1stSbnOfRsvr; nPbn <= nLastSbnOfRsvr; nPbn++)
  507. {
  508. /* Get current debug zone mask */
  509. nDZMask = FSR_DBG_GetDbgZoneMask();
  510. /*
  511. * Unset all debug zone mask
  512. * to remove uncorrectable read error msg at open time
  513. */
  514. FSR_DBG_UnsetAllDbgZoneMask();
  515. /*
  516. * Check 0th page in a block to check BBM meta mark in spare area
  517. */
  518. nLLDRe = _LLDRead(pstVol,
  519. pstDev->nDevNo,
  520. nPbn,
  521. 0,
  522. pstRsv,
  523. pstRsv->pMBuf, /* main buffer pointer */
  524. &stSBuf, /* spare buffer pointer */
  525. BML_META_DATA,
  526. FALSE32,
  527. FSR_LLD_FLAG_ECC_ON);
  528. /* restore previous debug zone mask */
  529. FSR_DBG_SetDbgZoneMask(nDZMask);
  530. /*
  531. * if the block is an initial bad block
  532. * BML_VALID_BLK_MARK = FSR_FND_VALID_BLK_MARK = FSR_OND_VALID_BLK_MARK
  533. */
  534. if (stSBuf.pstSpareBufBase->nBadMark != BML_VALID_BLK_MARK)
  535. {
  536. /* if this block is initial bad block, skip */
  537. continue;
  538. }
  539. /* uncorrectable read error case */
  540. if ((FSR_RETURN_MAJOR(nLLDRe) != FSR_LLD_SUCCESS) &&
  541. (FSR_RETURN_MAJOR(nLLDRe) != FSR_LLD_PREV_2LV_READ_DISTURBANCE) &&
  542. (FSR_RETURN_MAJOR(nLLDRe) != FSR_LLD_PREV_1LV_READ_DISTURBANCE))
  543. {
  544. /* skip and move to next block */
  545. continue;
  546. }
  547. if (nCnt % 10 == 0)
  548. {
  549. FSR_DBZ_RTLMOUT(FSR_DBZ_ERROR, (TEXT("[BBM:INF] ")));
  550. }
  551. /* print BBM meta mark area */
  552. FSR_DBZ_RTLMOUT(FSR_DBZ_ERROR, (TEXT("%x "), stSBuf.pstSpareBufBase->nBMLMetaBase0));
  553. if (nCnt % 10 == 9)
  554. {
  555. FSR_DBZ_RTLMOUT(FSR_DBZ_ERROR, (TEXT("\r\n")));
  556. }
  557. nCnt++;
  558. /* if this block is not a BBM meta block */
  559. if (stSBuf.pstSpareBufBase->nBMLMetaBase0 != FSR_LLD_BBM_META_MARK)
  560. {
  561. /* skip and move to next block */
  562. continue;
  563. }
  564. pstPCH = (BmlPoolCtlHdr *) pstRsv->pMBuf;
  565. /* Change Byte-Order for Tool */
  566. FSR_BBM_CHANGE_BYTE_ORDER_BMLPOOLCTLHDR( pstPCH );
  567. /* check signature of UPCB and LPCB */
  568. nUPCHCmpRet = FSR_OAM_MEMCMP(pstPCH->aSig, BML_UPCH_SIG, BML_MAX_PCH_SIG);
  569. nLPCHCmpRet = FSR_OAM_MEMCMP(pstPCH->aSig, BML_LPCH_SIG, BML_MAX_PCH_SIG);
  570. /* UPCB */
  571. if (nUPCHCmpRet == 0)
  572. {
  573. if (pstPCH->nAge == 0xFFFFFFFF)
  574. {
  575. FSR_DBZ_RTLMOUT(FSR_DBZ_ERROR, (TEXT("[BBM:ERR] Invalid UPCB age(nPbn: %d)\r\n"), nPbn));
  576. FSR_DBZ_DBGMOUT(FSR_DBZ_BML_BBM, (TEXT("[BBM:OUT] --%s(nRe: 0x%x)\r\n"), __FSR_FUNC__, FSR_BML_INVALID_PCB_AGE));
  577. return FSR_BML_INVALID_PCB_AGE;
  578. }
  579. /* check age of UPCB */
  580. if (pstPCH->nAge > pstRsvSh->nUPcbAge)
  581. {
  582. pstRsvSh->nUPCBSbn = (UINT16)nPbn;
  583. pstRsvSh->nUPcbAge = pstPCH->nAge;
  584. }
  585. /* Valid UPCB */
  586. bUPCB = TRUE32;
  587. }
  588. /* LPCB */
  589. else if (nLPCHCmpRet == 0)
  590. {
  591. if (pstPCH->nAge == 0xFFFFFFFF)
  592. {
  593. FSR_DBZ_RTLMOUT(FSR_DBZ_ERROR, (TEXT("[BBM:ERR] Invalid LPCB age(nPbn: %d)\r\n"), nPbn));
  594. FSR_DBZ_DBGMOUT(FSR_DBZ_BML_BBM, (TEXT("[BBM:OUT] --%s(nRe: 0x%x)\r\n"), __FSR_FUNC__, FSR_BML_INVALID_PCB_AGE));
  595. return FSR_BML_INVALID_PCB_AGE;
  596. }
  597. /* check age of LPCB */
  598. if (pstPCH->nAge > pstRsvSh->nLPcbAge)
  599. {
  600. pstRsvSh->nLPCBSbn = (UINT16)nPbn;
  601. pstRsvSh->nLPcbAge = pstPCH->nAge;
  602. }
  603. bLPCB = TRUE32;
  604. }
  605. /* Update global age for PCB blocks */
  606. if (((nUPCHCmpRet == 0) || (nLPCHCmpRet == 0)) &&
  607. (pstPCH->nGlobalAge > pstRsvSh->nGlobalPCBAge))
  608. {
  609. pstRsvSh->nGlobalPCBAge = pstPCH->nGlobalAge;
  610. /* Get latest TPCB info */
  611. pstRsvSh->nTPCBSbn = pstPCH->nTPCBPbn;
  612. }
  613. }
  614. FSR_DBZ_RTLMOUT(FSR_DBZ_ERROR, (TEXT("\r\n")));
  615. /* If UPCB is not found */
  616. if (bUPCB == FALSE32)
  617. {
  618. FSR_DBZ_RTLMOUT(FSR_DBZ_ERROR, (TEXT("[BBM:ERR] NO UPCB(1st Sbn: %d, Last Sbn: %d)\r\n"),
  619. n1stSbnOfRsvr, nLastSbnOfRsvr));
  620. FSR_DBZ_DBGMOUT(FSR_DBZ_BML_BBM, (TEXT("[BBM:OUT] --%s(nRe: 0x%x)\r\n"), __FSR_FUNC__, FSR_BML_NO_UPCB));
  621. return FSR_BML_NO_UPCB;
  622. }
  623. /* If LPCB is not found */
  624. if (bLPCB == FALSE32)
  625. {
  626. FSR_DBZ_RTLMOUT(FSR_DBZ_ERROR, (TEXT("[BBM:ERR] NO LPCB(1st Sbn: %d, Last Sbn: %d)\r\n"),
  627. n1stSbnOfRsvr, nLastSbnOfRsvr));
  628. FSR_DBZ_DBGMOUT(FSR_DBZ_BML_BBM, (TEXT("[BBM:OUT] --%s(nRe: 0x%x)\r\n"), __FSR_FUNC__, FSR_BML_NO_LPCB));
  629. return FSR_BML_NO_LPCB;
  630. }
  631. FSR_DBZ_DBGMOUT(FSR_DBZ_BML_BBM, (TEXT("[BBM:OUT] --%s(nRe: 0x%x)\r\n"), __FSR_FUNC__, FSR_BML_SUCCESS));
  632. return FSR_BML_SUCCESS;
  633. }
  634. /*
  635. * @brief This function reads data from the given nPbn and this
  636. * @n function checks confirmation page
  637. *
  638. * @param[in] *pstDev : device context pointer
  639. * @param[in] *pstVol : volume context pointer
  640. * @param[in] *pstRsv : resercoir context pointer
  641. * @param[in] nPbn : physical block number
  642. * @param[out] *pValidOffset: page offset for valid meta data
  643. * @param[in] nType : PCB block type
  644. * @param[in] *pbLastest : data which will be loaded is lastest info
  645. * @n or previous info
  646. *
  647. * @return TRUE32
  648. * @return FALSE32
  649. *
  650. * @author MinYoung Kim
  651. * @version 1.0.0
  652. * @remark none
  653. *
  654. * @since since v1.0.0
  655. * @exception none
  656. *
  657. */
  658. PRIVATE BOOL32
  659. _FindValidMetaData(BmlDevCxt *pstDev,
  660. BmlVolCxt *pstVol,
  661. BmlDieCxt *pstDie,
  662. UINT32 nPbn,
  663. UINT32 *pValidOffset,
  664. UINT32 nType)
  665. {
  666. BmlReservoir *pstRsv;
  667. BmlReservoirSh *pstRsvSh;
  668. FSRSpareBuf stSBuf;
  669. BmlPoolCtlHdr *pstPCH;
  670. INT32 nLLDRe;
  671. INT32 nCmpRet;
  672. UINT32 nPDev;
  673. UINT32 nPgOffset;
  674. UINT32 nLatestPgOff;
  675. BOOL32 bFree = TRUE32;
  676. BOOL32 bFound = FALSE32;
  677. BOOL32 bRet = FALSE32;
  678. UINT32 nIdx;
  679. FSR_STACK_VAR;
  680. FSR_STACK_END;
  681. FSR_DBZ_DBGMOUT(FSR_DBZ_BML_BBM, (TEXT("[BBM:IN ] ++%s(nPDev: %d, nPbn: %d, nType: %d)\r\n"),
  682. __FSR_FUNC__, pstDev->nDevNo, nPbn, nType));
  683. do
  684. {
  685. nPDev = pstDev->nDevNo;
  686. pstRsv = pstDie->pstRsv;
  687. pstRsvSh = pstDie->pstRsvSh;
  688. *pValidOffset = 0xFFFFFFFF;
  689. /*
  690. * Find the latest confirm page
  691. * Read the specific page offset to reduce the number of read operations
  692. * ex) 3, 7, 11, ..., 63
  693. */
  694. for (nPgOffset = pstVol->nNumOfPgsInSLCBlk;
  695. nPgOffset > 0;
  696. nPgOffset -= (BML_NUM_OF_META_PGS + 1))
  697. {
  698. /* checks this page is free or not */
  699. bFree = _IsFreePg(pstVol, pstRsv, nPDev, nPbn, nPgOffset - 1);
  700. /* If the page is not free, the page contains confirm in main area */
  701. if (bFree == FALSE32)
  702. {
  703. break;
  704. }
  705. }
  706. /* If all pages are free */
  707. if (bFree == TRUE32)
  708. {
  709. break;
  710. }
  711. /* UPCB case */
  712. if ((nType & BML_TYPE_UPCB) == BML_TYPE_UPCB)
  713. {
  714. pstRsvSh->nNextUPCBPgOff = (UINT16)nPgOffset;
  715. }
  716. /* LPCB case */
  717. else if ((nType & BML_TYPE_LPCB) == BML_TYPE_LPCB)
  718. {
  719. pstRsvSh->nNextLPCBPgOff = (UINT16)nPgOffset;
  720. }
  721. /* Confirm page offset */
  722. nPgOffset--;
  723. /* save latest written page offset */
  724. nLatestPgOff = nPgOffset;
  725. FSR_OAM_MEMCPY(&stSBuf, pstRsv->pSBuf, sizeof(FSRSpareBuf));
  726. if (stSBuf.nNumOfMetaExt != 0)
  727. {
  728. stSBuf.nNumOfMetaExt = pstVol->nSizeOfPage / FSR_PAGE_SIZE_PER_SPARE_BUF_EXT;
  729. }
  730. do
  731. {
  732. /* read confirm page */
  733. nLLDRe = _LLDRead(pstVol,
  734. nPDev,
  735. nPbn,
  736. nPgOffset,
  737. pstRsv,
  738. pstRsv->pMBuf, /* main buffer pointer */
  739. &stSBuf, /* spare buffer pointer */
  740. BML_META_DATA,
  741. FALSE32,
  742. FSR_LLD_FLAG_ECC_ON);
  743. if ((FSR_RETURN_MAJOR(nLLDRe) == FSR_LLD_SUCCESS) ||
  744. (FSR_RETURN_MAJOR(nLLDRe) == FSR_LLD_PREV_2LV_READ_DISTURBANCE) ||
  745. (FSR_RETURN_MAJOR(nLLDRe) == FSR_LLD_PREV_1LV_READ_DISTURBANCE))
  746. {
  747. /* Data of confirm page should be all 0x0 */
  748. bRet = _CmpData(pstVol, pstRsv->pMBuf, 0x0, FALSE32);
  749. if (bRet == TRUE32)
  750. {
  751. bFound = TRUE32;
  752. for (nIdx = nPgOffset - BML_NUM_OF_META_PGS;
  753. nIdx < nPgOffset;
  754. nIdx++)
  755. {
  756. /* if valid confirm page is found, read meta-data pages */
  757. nLLDRe = _LLDRead(pstVol,
  758. nPDev,
  759. nPbn,
  760. nIdx,
  761. pstRsv,
  762. pstRsv->pMBuf, /* main buffer pointer */
  763. &stSBuf, /* spare buffer pointer */
  764. BML_META_DATA,
  765. FALSE32,
  766. FSR_LLD_FLAG_ECC_ON);
  767. if ((FSR_RETURN_MAJOR(nLLDRe) != FSR_LLD_SUCCESS) &&
  768. (FSR_RETURN_MAJOR(nLLDRe) != FSR_LLD_PREV_2LV_READ_DISTURBANCE) &&
  769. (FSR_RETURN_MAJOR(nLLDRe) != FSR_LLD_PREV_1LV_READ_DISTURBANCE))
  770. {
  771. /* invalid meta data */
  772. bFound = FALSE32;
  773. break;
  774. }
  775. }
  776. /* If all meta data pages are valid */
  777. if (bFound == TRUE32)
  778. {
  779. /*
  780. * If lastest written page has valid info, load data from the latest pages.
  781. * If not, load data from previous pages and write new data to newly allocated block
  782. */
  783. if ((nLatestPgOff == nPgOffset) &&
  784. (nPgOffset < pstVol->nNumOfPgsInSLCBlk - 1))
  785. {
  786. /* checks next page is free or not */
  787. bFree = _IsFreePg(pstVol, pstRsv, nPDev, nPbn, nPgOffset + 1);
  788. }
  789. /* first page offset of valid meta data */
  790. *pValidOffset = nPgOffset - BML_NUM_OF_META_PGS;
  791. /*
  792. * Find TPCB block to restore previous PCB data
  793. * when there is no valid PCB data
  794. */
  795. if ((nType & BML_TYPE_TPCB) == BML_TYPE_TPCB)
  796. {
  797. /* read valid page offset to check the PCH signature (ignore error) */
  798. _LLDRead(pstVol,
  799. nPDev,
  800. nPbn,
  801. *pValidOffset,
  802. pstRsv,
  803. pstRsv->pMBuf, /* main buffer pointer */
  804. &stSBuf, /* spare buffer pointer */
  805. BML_META_DATA,
  806. FALSE32,
  807. FSR_LLD_FLAG_ECC_ON);
  808. pstPCH = (BmlPoolCtlHdr *) pstRsv->pMBuf;
  809. /* Change Byte-Order for Tool */
  810. FSR_BBM_CHANGE_BYTE_ORDER_BMLPOOLCTLHDR( pstPCH );
  811. nCmpRet = FSR_OAM_MEMCMP(pstPCH->aSig, BML_UPCH_SIG, BML_MAX_PCH_SIG);
  812. /* the block has UPCH signature */
  813. if ((nCmpRet == 0) && ((nType & BML_TYPE_UPCB) == BML_TYPE_UPCB))
  814. {
  815. break;
  816. }
  817. nCmpRet = FSR_OAM_MEMCMP(pstPCH->aSig, BML_LPCH_SIG, BML_MAX_PCH_SIG);
  818. /* the block has LPCH signature */
  819. if ((nCmpRet == 0) && ((nType & BML_TYPE_LPCB) == BML_TYPE_LPCB))
  820. {
  821. break;
  822. }
  823. /* If type of TPCB and PCH signature is not matched */
  824. bFound = FALSE32;
  825. break;
  826. }
  827. /* not TPCB, UPCB or LPCB */
  828. else
  829. {
  830. break;
  831. }
  832. }
  833. }
  834. }
  835. /* If this block has no valid data, escape from the loop */
  836. if ((nPgOffset == 0) && (bFound == FALSE32))
  837. {
  838. break;
  839. }
  840. /* power-failure case, move previous confirm page */
  841. nPgOffset--;
  842. /* go backward until valid confirm is found */
  843. } while (bFound == FALSE32);
  844. } while(0);
  845. FSR_DBZ_DBGMOUT(FSR_DBZ_BML_BBM, (TEXT("[BBM:OUT] --%s(nRe: 0x%x)\r\n"), __FSR_FUNC__, bFound));
  846. return bFound;
  847. }
  848. /*
  849. * @brief This function checks the page is free or not
  850. *
  851. * @param[in] pstRsv : BmlReservoir context pointer
  852. * @param[in] nPDev : physical device number
  853. * @param[in] nPbn : physical block number
  854. * @param[in] nPgOffset : page offset to be read
  855. *
  856. * @return TRUE32
  857. * @return FALSE32
  858. *
  859. * @author MinYoung Kim
  860. * @version 1.0.0
  861. * @remark none
  862. *
  863. * @since since v1.0.0
  864. * @exception none
  865. *
  866. */
  867. PRIVATE BOOL32
  868. _IsFreePg(BmlVolCxt *pstVol,
  869. BmlReservoir *pstRsv,
  870. UINT32 nPDev,
  871. UINT32 nPbn,
  872. UINT32 nPgOffset)
  873. {
  874. FSRSpareBuf stSBuf;
  875. BOOL32 bFree;
  876. FSR_STACK_VAR;
  877. FSR_STACK_END;
  878. FSR_OAM_MEMCPY(&stSBuf, pstRsv->pSBuf, sizeof(FSRSpareBuf));
  879. if (stSBuf.nNumOfMetaExt != 0)
  880. {
  881. stSBuf.nNumOfMetaExt = pstVol->nSizeOfPage / FSR_PAGE_SIZE_PER_SPARE_BUF_EXT;
  882. }
  883. /* read a page and ignore LLD error */
  884. _LLDRead(pstVol,
  885. nPDev,
  886. nPbn,
  887. nPgOffset,
  888. pstRsv,
  889. pstRsv->pMBuf, /* main buffer pointer */
  890. &stSBuf, /* spare buffer pointer */
  891. BML_META_DATA,
  892. FALSE32,
  893. FSR_LLD_FLAG_ECC_OFF);
  894. /* check spare buffer */
  895. bFree = _CmpData(pstVol, (UINT8 *) &stSBuf, 0xFF, TRUE32);
  896. if (bFree != TRUE32)
  897. {
  898. return bFree;
  899. }
  900. /* check main buffer */
  901. bFree = _CmpData(pstVol, (UINT8 *) pstRsv->pMBuf, 0xFF, FALSE32);
  902. if (bFree != TRUE32)
  903. {
  904. return bFree;
  905. }
  906. return TRUE32;
  907. }
  908. /*
  909. * @brief This function loads BBM meta data from PCB
  910. *
  911. * @param[in] *pstVol : volume context pointer
  912. * @param[in] *pstDev : device context pointer
  913. * @param[in] nDieIdx : die index
  914. * @param[in] nPbn : physical block number
  915. * @param[in] nStartOffset: start page offset
  916. * @param[in] *pstPI : partition info pointer
  917. * @param[in] nType : PCB block type
  918. *
  919. * @return FSR_BML_SUCCESS
  920. * @return FSR_BML_LOAD_UBMS_FAILURE
  921. * @return FSR_BML_LOAD_LBMS_FAILURE
  922. * @return Some LLD errors
  923. *
  924. * @author MinYoung Kim
  925. * @version 1.0.0
  926. * @remark none
  927. *
  928. * @since since v1.0.0
  929. * @exception none
  930. *
  931. */
  932. PRIVATE INT32
  933. _LoadMetaData(BmlVolCxt *pstVol,
  934. BmlDevCxt *pstDev,
  935. UINT32 nDieIdx,
  936. UINT32 nPbn,
  937. UINT32 nStartOffset,
  938. VOID *pstPI,
  939. UINT32 nType)
  940. {
  941. BmlPoolCtlHdr *pstPCH;
  942. FSRPartI *pstPartI;
  943. FSRPIExt *pstPIExt;
  944. BmlBMS *pstBMS;
  945. BmlReservoir *pstRsv;
  946. BmlReservoirSh *pstRsvSh;
  947. FSRSpareBuf stSBuf;
  948. INT32 nLLDRe;
  949. INT32 nMajorRe = 0;
  950. INT32 nRet = FSR_BML_SUCCESS;
  951. UINT32 nIdx = 0;
  952. UINT32 nSctIdx;
  953. UINT32 nPDev;
  954. UINT32 nNumOfRCB;
  955. UINT32 nNumOfBMS;
  956. UINT32 nBMSSctOffset;
  957. UINT32 nSizeOfMaxRsvr;
  958. UINT32 nSizeOfBABitMap;
  959. BOOL32 bLoaded = TRUE32;
  960. BOOL32 bRet = TRUE32;
  961. UINT8 *pBufPtr = NULL;
  962. UINT16 *pRCBSbn;
  963. #if !defined(TINY_FSR)
  964. BOOL32 bReadDisturb = FALSE32;
  965. #endif
  966. FSR_STACK_VAR;
  967. FSR_STACK_END;
  968. FSR_DBZ_DBGMOUT(FSR_DBZ_BML_BBM, (TEXT("[BBM:IN ] ++%s(nPDev: %d, nDieIdx: %d, nPbn: %d, nStartOffset: %d, nType: %d)\r\n"),
  969. __FSR_FUNC__, pstDev->nDevNo, nDieIdx, nPbn, nStartOffset, nType));
  970. nPDev = pstDev->nDevNo;
  971. pstRsv = pstDev->pstDie[nDieIdx]->pstRsv;
  972. pstRsvSh = pstDev->pstDie[nDieIdx]->pstRsvSh;
  973. /* 2KB page: 4, 4KB page: 8 */
  974. nBMSSctOffset = pstVol->nSctsPerPg;
  975. /* default value for 1 plane device */
  976. nNumOfRCB = 0;
  977. /* 2KB page device */
  978. if (pstVol->nSctsPerPg == BML_2KB_PG)
  979. {
  980. /* number of BMS sectors */
  981. nNumOfBMS = BML_NUM_OF_BMS_2KB_PG;
  982. /* max number of reservoir blocks */
  983. nSizeOfMaxRsvr = ((BML_NUM_OF_BMS_2KB_PG * BML_BMFS_PER_BMS) * 2) / 3;
  984. }
  985. /* 4KB page device */
  986. else
  987. {
  988. /* number of BMS sectors */
  989. nNumOfBMS = BML_NUM_OF_BMS_4KB_PG;
  990. /* max number of reservoir blocks */
  991. nSizeOfMaxRsvr = ((BML_NUM_OF_BMS_4KB_PG * BML_BMFS_PER_BMS) * 2) / 3;
  992. }
  993. /* calculate size of BABitMap using nSizeOfMaxRsvr */
  994. if (nSizeOfMaxRsvr % BML_NUM_OF_BITS_IN_1BYTE)
  995. {
  996. nSizeOfBABitMap = (nSizeOfMaxRsvr / BML_NUM_OF_BITS_IN_1BYTE) + 1;
  997. }
  998. else
  999. {
  1000. nSizeOfBABitMap = (nSizeOfMaxRsvr / BML_NUM_OF_BITS_IN_1BYTE);
  1001. }
  1002. /* multi plane device */
  1003. if (pstVol->nNumOfPlane > 1)
  1004. {
  1005. /*
  1006. * number of entries for reservoir candidate block =
  1007. * max number of reservoir blocks which is supported by FSR / 2
  1008. *
  1009. * max number of BMF entries = 3/2 * max number of reservoir blocks
  1010. * = nNumOfBMS * BML_BMFS_PER_BMS
  1011. *
  1012. * max number of BMF entries / 3 = max number of reservoir blocks / 2
  1013. *
  1014. * number of sectors for reservoir candidate block =
  1015. * ceiling of (number of entries for reservoir candidate block / number of RCB entries in sector)
  1016. *
  1017. */
  1018. nNumOfRCB = ((nNumOfBMS * BML_BMFS_PER_BMS) / 3);
  1019. if (nNumOfRCB % BML_RCBFS_PER_RCBS)
  1020. {
  1021. nNumOfRCB = (nNumOfRCB / BML_RCBFS_PER_RCBS) + 1;
  1022. }
  1023. else
  1024. {
  1025. nNumOfRCB = (nNumOfRCB / BML_RCBFS_PER_RCBS);
  1026. }
  1027. }
  1028. FSR_OAM_MEMCPY(&stSBuf, pstRsv->pSBuf, sizeof(FSRSpareBuf));
  1029. if (stSBuf.nNumOfMetaExt != 0)
  1030. {
  1031. stSBuf.nNumOfMetaExt = pstVol->nSizeOfPage / FSR_PAGE_SIZE_PER_SPARE_BUF_EXT;
  1032. }
  1033. /* read all meta pages : 3 pages(4KB page) or 6 pages(2KB page) */
  1034. for (nSctIdx = 0; nSctIdx < (BML_NUM_OF_META_PGS * pstVol->nSctsPerPg); nSctIdx++)
  1035. {
  1036. /* when a sector is first sector of a page, read one page */
  1037. if ((nSctIdx % pstVol->nSctsPerPg) == 0)
  1038. {
  1039. /* read one page */
  1040. nLLDRe = _LLDRead(pstVol,
  1041. nPDev,
  1042. nPbn,
  1043. nStartOffset + (nSctIdx / pstVol->nSctsPerPg),
  1044. pstRsv,
  1045. pstRsv->pMBuf, /* main buffer pointer */
  1046. &stSBuf, /* spare buffer pointer */
  1047. BML_META_DATA,
  1048. FALSE32,
  1049. FSR_LLD_FLAG_ECC_ON);
  1050. nMajorRe = FSR_RETURN_MAJOR(nLLDRe);
  1051. /* uncorrectable read error case */
  1052. if ((nMajorRe != FSR_LLD_SUCCESS) &&
  1053. (nMajorRe != FSR_LLD_PREV_2LV_READ_DISTURBANCE) &&
  1054. (nMajorRe != FSR_LLD_PREV_1LV_READ_DISTURBANCE))
  1055. {
  1056. FSR_DBZ_RTLMOUT(FSR_DBZ_ERROR, (TEXT("[BBM:ERR] _LLDRead(nPDev: %d, nPbn:%d, nOffset:%d, BBM META) is failed\r\n"),
  1057. nPDev, nPbn, nStartOffset + (nSctIdx / pstVol->nSctsPerPg)));
  1058. FSR_DBZ_DBGMOUT(FSR_DBZ_BML_BBM, (TEXT("[BBM:OUT] --%s(nRe: 0x%x)\r\n"), __FSR_FUNC__, nLLDRe));
  1059. return nLLDRe;
  1060. }
  1061. #if !defined(TINY_FSR)
  1062. if (nMajorRe == FSR_LLD_PREV_2LV_READ_DISTURBANCE)
  1063. {
  1064. bReadDisturb = TRUE32;
  1065. }
  1066. #endif
  1067. pBufPtr = pstRsv->pMBuf;
  1068. }
  1069. /* PCH sector offset : 0 */
  1070. if (nSctIdx == BML_PCH_SCT_OFF)
  1071. {
  1072. pstPCH = (BmlPoolCtlHdr *) pBufPtr;
  1073. /* Change Byte-Order for Tool */
  1074. FSR_BBM_CHANGE_BYTE_ORDER_BMLPOOLCTLHDR( pstPCH );
  1075. /* UPCB */
  1076. if (nType == BML_TYPE_UPCB)
  1077. {
  1078. pstRsvSh->nUPcbAge = pstPCH->nAge;
  1079. pstRsvSh->nREFSbn = pstPCH->nREFPbn;
  1080. }
  1081. /* LPCB */
  1082. else
  1083. {
  1084. pstRsvSh->nLPcbAge = pstPCH->nAge;
  1085. }
  1086. /* update global PCB age */
  1087. if (pstPCH->nGlobalAge > pstRsvSh->nGlobalPCBAge)
  1088. {
  1089. pstRsvSh->nGlobalPCBAge = pstPCH->nGlobalAge;
  1090. }
  1091. pBufPtr += sizeof(BmlPoolCtlHdr);
  1092. }
  1093. /* PIA sector offset : 1 */
  1094. else if (nSctIdx == BML_PIA_SCT_OFF)
  1095. {
  1096. /* UPCB */
  1097. if (nType == BML_TYPE_UPCB)
  1098. {
  1099. if (pstPI != NULL)
  1100. {
  1101. pstPIExt = (FSRPIExt *)pstPI;
  1102. /* load PI extension */
  1103. FSR_OAM_MEMCPY(pstPIExt, &pBufPtr[0], sizeof(FSRPIExt));
  1104. /* Change Byte-Order for Tool */
  1105. FSR_BBM_CHANGE_BYTE_ORDER_FSRPIEXT( pstPIExt );
  1106. }
  1107. }
  1108. /* LPCB */
  1109. else
  1110. {
  1111. if (pstPI != NULL)
  1112. {
  1113. pstPartI = (FSRPartI *)pstPI;
  1114. /* load PI */
  1115. FSR_OAM_MEMCPY(pstPartI, pBufPtr, sizeof(FSRPartI));
  1116. /* Change Byte-Order for Tool */
  1117. FSR_BBM_CHANGE_BYTE_ORDER_FSRPARTI( pstPartI );
  1118. }
  1119. }
  1120. /* move buffer pointer to next */
  1121. pBufPtr += FSR_SECTOR_SIZE;
  1122. }
  1123. /* ERL sector offset : 2 */
  1124. else if (nSctIdx == BML_ERL_SCT_OFF)
  1125. {
  1126. if (nType == BML_TYPE_UPCB)
  1127. {
  1128. /* UPCB has valid ERL list (LPCB has empty ERL) */
  1129. FSR_OAM_MEMCPY(pstRsv->pstERL, pBufPtr, sizeof(BmlERL));
  1130. /* Change Byte-Order for Tool */
  1131. FSR_BBM_CHANGE_BYTE_ORDER_BMLERL( pstRsv->pstERL );
  1132. }
  1133. pBufPtr += sizeof(BmlERL);
  1134. }
  1135. /* BAB sector offset : 3 */
  1136. else if (nSctIdx == BML_BAB_SCT_OFF)
  1137. {
  1138. /* UPCB */
  1139. if (nType == BML_TYPE_UPCB)
  1140. {
  1141. /* UPCB has bad block allocation bitmap */
  1142. FSR_OAM_MEMCPY(pstRsv->pBABitMap, pBufPtr, nSizeOfBABitMap);
  1143. }
  1144. /* move buffer pointer to next */
  1145. pBufPtr += FSR_SECTOR_SIZE;
  1146. }
  1147. /* BMS sector */
  1148. else if ((nBMSSctOffset <= nSctIdx) &&
  1149. (nSctIdx < nBMSSctOffset + nNumOfBMS))
  1150. {
  1151. pstBMS = (BmlBMS *) pBufPtr;
  1152. /* Change Byte-Order for Tool */
  1153. FSR_BBM_CHANGE_BYTE_ORDER_BMLBMS( pstBMS );
  1154. /* Load first BMS sector */
  1155. bRet = _LoadBMS(pstVol, pstRsv, pstBMS);
  1156. if (bRet == FALSE32)
  1157. {
  1158. /* if it is not found... */
  1159. bLoaded = FALSE32;
  1160. break;
  1161. }
  1162. /* move buffer pointer to next */
  1163. pBufPtr += FSR_SECTOR_SIZE;
  1164. }
  1165. /* RCBS sector */
  1166. else if ((nSctIdx >= ((BML_NUM_OF_META_PGS * pstVol->nSctsPerPg) - nNumOfRCB)) &&
  1167. (nSctIdx < (BML_NUM_OF_META_PGS * pstVol->nSctsPerPg)))
  1168. {
  1169. if (nType == BML_TYPE_UPCB)
  1170. {
  1171. pRCBSbn = (UINT16 *) pBufPtr;
  1172. /* Change Byte-Order for Tool */
  1173. FSR_BBM_CHANGE_BYTE_ORDER_RCB( pRCBSbn );
  1174. for (nIdx = 0; nIdx < BML_RCBFS_PER_RCBS; nIdx++)
  1175. {
  1176. if (pRCBSbn[nIdx] != 0xFFFF)
  1177. {
  1178. pstRsv->pstRCB[pstRsv->pstBMI->nNumOfRCBs++] = pRCBSbn[nIdx];
  1179. }
  1180. else
  1181. {
  1182. break;
  1183. }
  1184. }
  1185. }
  1186. /* move buffer pointer to next */
  1187. pBufPtr += FSR_SECTOR_SIZE;
  1188. }
  1189. /* unused sectors */
  1190. else
  1191. {
  1192. /* skip reserved area (1 sector) */
  1193. pBufPtr += FSR_SECTOR_SIZE;
  1194. }
  1195. }
  1196. /* if BMS is not loaded yet */
  1197. if (bLoaded == FALSE32)
  1198. {
  1199. if (nType == BML_TYPE_UPCB)
  1200. {
  1201. /* UPCB load fails */
  1202. nRet = FSR_BML_LOAD_UBMS_FAILURE;
  1203. }
  1204. else
  1205. {
  1206. /* LPCB load fails */
  1207. nRet = FSR_BML_LOAD_LBMS_FAILURE;
  1208. }
  1209. }
  1210. /* BMS is loaded successfully */
  1211. else
  1212. {
  1213. #if !defined(TINY_FSR)
  1214. /*
  1215. * if UPCB has read disturbance error, BBM discards meta-data in UPCB and
  1216. * writes current meta-data into TPCB to avoid using UPCB.
  1217. * Meta-data will program into TPCB even if ERL is empty.
  1218. * (read disturbance error of LPCB is ignored)
  1219. */
  1220. if ((bReadDisturb == TRUE32) &&
  1221. (nType == BML_TYPE_UPCB))
  1222. {
  1223. /*
  1224. * RSVR should be unlocked, because of running FSR_BBM_UpdateERL
  1225. * nRet is only used by error message,
  1226. */
  1227. nRet = FSR_BBM_UnlockRsvr(pstVol,
  1228. pstDev,
  1229. nDieIdx);
  1230. if (nRet != FSR_BML_SUCCESS)
  1231. {
  1232. FSR_DBZ_RTLMOUT(FSR_DBZ_ERROR, (TEXT("[BBM:ERR] %s / %d line\r\n"),
  1233. __FSR_FUNC__, __LINE__));
  1234. FSR_DBZ_RTLMOUT(FSR_DBZ_ERROR, (TEXT("[BBM:ERR] FSR_BBM_UnlockRsvr(nPDev: %d, nDieIdx: %d)\r\n"),
  1235. nPDev, nDieIdx));
  1236. }
  1237. /* solve read disturbance error of UPCB */
  1238. nRet = FSR_BBM_UpdateERL(pstVol,
  1239. pstDev,
  1240. nDieIdx,
  1241. nPbn,
  1242. BML_FLAG_ERL_FORCED_PROGRAM);
  1243. }
  1244. #endif /* TINY_FSR */
  1245. }
  1246. FSR_DBZ_DBGMOUT(FSR_DBZ_BML_BBM, (TEXT("[BBM:OUT] --%s(nRe: 0x%x)\r\n"), __FSR_FUNC__, nRet));
  1247. return nRet;
  1248. }
  1249. /*
  1250. * @brief This function loads BMS
  1251. *
  1252. * @param[in] *pstRsv : BmlReservoir structure pointer
  1253. * @param[in] *pstBMS : BMS structure pointer
  1254. *
  1255. * @return TRUE32
  1256. * @return FALSE32
  1257. *
  1258. * @author MinYoung Kim
  1259. * @version 1.0.0
  1260. * @remark none
  1261. *
  1262. * @since since v1.0.0
  1263. * @exception none
  1264. *
  1265. */
  1266. PRIVATE BOOL32
  1267. _LoadBMS(BmlVolCxt *pstVol,
  1268. BmlReservoir *pstRsv,
  1269. BmlBMS *pstBMS)
  1270. {
  1271. BmlBMI *pstBMI;
  1272. BmlBMF *pSrcBMF;
  1273. BmlBMF *pDstBMF;
  1274. UINT32 nBMFIdx;
  1275. UINT32 nNumOfRsvrBlks;
  1276. FSR_STACK_VAR;
  1277. FSR_STACK_END;
  1278. FSR_DBZ_DBGMOUT(FSR_DBZ_BML_BBM, (TEXT("[BBM:IN ] ++%s()\r\n"), __FSR_FUNC__));
  1279. pstBMI = pstRsv->pstBMI;
  1280. pSrcBMF = (BmlBMF *) (pstBMS->stBMF);
  1281. pDstBMF = pstRsv->pstBMF;
  1282. /* set number of Reservoir blocks in a die */
  1283. nNumOfRsvrBlks = pstVol->nNumOfRsvrBlks >> pstVol->nSftDDP;
  1284. do
  1285. {
  1286. /* construct Block Map Information using BMS */
  1287. for (nBMFIdx = 0; nBMFIdx < BML_BMFS_PER_BMS; nBMFIdx++)
  1288. {
  1289. /* if Rbn is 0xFFFF, slot (nIdx2) is empty */
  1290. if (pSrcBMF[nBMFIdx].nRbn == (UINT16) 0xFFFF && pSrcBMF[nBMFIdx].nSbn == (UINT16) 0xFFFF)
  1291. {
  1292. break;
  1293. }
  1294. /* multi plane device */
  1295. if (pstVol->nNumOfPlane > 1)
  1296. {
  1297. if (pstBMI->nNumOfBMFs > (UINT16) (nNumOfRsvrBlks + (nNumOfRsvrBlks / 2)))
  1298. {
  1299. FSR_DBZ_RTLMOUT(FSR_DBZ_ERROR, (TEXT("[BBM:ERR] pstBMI->nNumOfBMFs(%d) >= number of blocks in reservoir + 50%\r\n"), pstBMI->nNumOfBMFs));
  1300. FSR_DBZ_RTLMOUT(FSR_DBZ_ERROR, (TEXT("[BBM:ERR] n1stSbnOfRsvr(%d) >= nLastSbnOfRsvr(%d)\r\n"),
  1301. pstRsv->n1stSbnOfRsvr, pstRsv->nLastSbnOfRsvr));
  1302. FSR_DBZ_DBGMOUT(FSR_DBZ_BML_BBM, (TEXT("[BBM:OUT] --%s(nRe: 0x%x)\r\n"), __FSR_FUNC__, FALSE32));
  1303. return FALSE32;
  1304. }
  1305. }
  1306. else
  1307. {
  1308. if (pstBMI->nNumOfBMFs > (UINT16) (nNumOfRsvrBlks))
  1309. {
  1310. FSR_DBZ_RTLMOUT(FSR_DBZ_ERROR, (TEXT("[BBM:ERR] pstBMI->nNumOfBMFs(%d) >= number of blocks in reservoir\r\n"), pstBMI->nNumOfBMFs));
  1311. FSR_DBZ_RTLMOUT(FSR_DBZ_ERROR, (TEXT("[BBM:ERR] n1stSbnOfRsvr(%d) >= nLastSbnOfRsvr(%d)\r\n"),
  1312. pstRsv->n1stSbnOfRsvr, pstRsv->nLastSbnOfRsvr));
  1313. FSR_DBZ_DBGMOUT(FSR_DBZ_BML_BBM, (TEXT("[BBM:OUT] --%s(nRe: 0x%x)\r\n"), __FSR_FUNC__, FALSE32));
  1314. return FALSE32;
  1315. }
  1316. }
  1317. /* save Sbn and Rbn */
  1318. pDstBMF[pstBMI->nNumOfBMFs].nSbn = pSrcBMF[nBMFIdx].nSbn;
  1319. pDstBMF[pstBMI->nNumOfBMFs].nRbn = pSrcBMF[nBMFIdx].nRbn;
  1320. /* increase the number of BMFs */
  1321. pstBMI->nNumOfBMFs++;
  1322. }
  1323. }
  1324. while (0);
  1325. FSR_DBZ_DBGMOUT(FSR_DBZ_BML_BBM, (TEXT("[BBM:OUT] --%s(nRe: 0x%x)\r\n"), __FSR_FUNC__, TRUE32));
  1326. return TRUE32;
  1327. }