PageRenderTime 53ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/drivers/block/sun3i_nand/src/logic/logic_ctl.c

https://bitbucket.org/ndreys/linux-sunxi
C | 1436 lines | 796 code | 208 blank | 432 comment | 130 complexity | a38b5ef46dd4db74d4c430c29b9b14e7 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
  1. /*
  2. * drivers/block/sun3i_nand/src/logic/logic_ctl.c
  3. *
  4. * (C) Copyright 2007-2012
  5. * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License as
  9. * published by the Free Software Foundation; either version 2 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  20. * MA 02111-1307 USA
  21. */
  22. #include <linux/module.h>
  23. #include "../include/nand_logic.h"
  24. struct __NandDriverGlobal_t NandDriverInfo;
  25. struct __LogicArchitecture_t LogicArchiPar;
  26. struct __ZoneTblPstInfo_t ZoneTblPstInfo[MAX_ZONE_CNT];
  27. //define the parameter for manage the cached page
  28. static struct __GlobalLogicPageType_t CachePage;
  29. //define the parameter for manage the logical page read and write
  30. static struct __LogicCtlPar_t LogicalCtl;
  31. /*
  32. ************************************************************************************************************************
  33. * CALCLUATE PROCESSING DATA PARAMETER
  34. *
  35. *Description: Calculate the loigcal pages number and the sector bitmap in the page for the sectors
  36. * that pocessing currently.
  37. *
  38. *Arguments : nSectNum the number of the first sector of the sectors need be processed;
  39. * nSectCnt the count of the sectors that how many sectors need be processed;
  40. * pHeadPage the pointer to the paramter of the head page;
  41. * pMidPageCnt the pointer ot the count of full pages;
  42. * pTailPage the pointer to the paramter of the tail page.
  43. *
  44. *Return : calculate sector parameter result;
  45. * = 0 calculate sector parameter successful;
  46. * < 0 calcualte sector parameter failed.
  47. ************************************************************************************************************************
  48. */
  49. static __s32 _CalculateSectPar(__u32 nSectNum, __u32 nSectCnt, struct __GlobalLogicPageType_t *pHeadPage,
  50. __u32 *pMidPageCnt, struct __GlobalLogicPageType_t *pTailPage)
  51. {
  52. __u32 tmpSectCnt, tmpBitmap;
  53. LOGICCTL_DBG("[LOGICCTL_DBG]: Calculate logical sectors parameter, Lba:0x%x, Cnt:0x%x\n", nSectNum, nSectCnt);
  54. //initiate the middle page and tail page parameters, because they may be empty
  55. *pMidPageCnt = 0x00;
  56. pTailPage->LogicPageNum = 0xffffffff;
  57. pTailPage->SectorBitmap = 0x00;
  58. //calculate the head page parameter
  59. pHeadPage->LogicPageNum = nSectNum / SECTOR_CNT_OF_LOGIC_PAGE;
  60. tmpSectCnt = nSectCnt + (nSectNum % SECTOR_CNT_OF_LOGIC_PAGE);
  61. tmpBitmap = (FULL_BITMAP_OF_LOGIC_PAGE << (nSectNum % SECTOR_CNT_OF_LOGIC_PAGE));
  62. if(tmpSectCnt > SECTOR_CNT_OF_LOGIC_PAGE)
  63. {
  64. //set the head page bitmap
  65. pHeadPage->SectorBitmap = tmpBitmap & FULL_BITMAP_OF_LOGIC_PAGE;
  66. //calcualte the count of full pages
  67. tmpSectCnt -= SECTOR_CNT_OF_LOGIC_PAGE;
  68. while(tmpSectCnt >= SECTOR_CNT_OF_LOGIC_PAGE)
  69. {
  70. ++*pMidPageCnt;
  71. tmpSectCnt -= SECTOR_CNT_OF_LOGIC_PAGE;
  72. }
  73. //calculate parameter for the tail page
  74. if(tmpSectCnt)
  75. {
  76. //calcualte the tail page sector bitmap
  77. pTailPage->SectorBitmap = FULL_BITMAP_OF_LOGIC_PAGE >> (SECTOR_CNT_OF_LOGIC_PAGE - tmpSectCnt);
  78. //calculate the number of the tail page
  79. pTailPage->LogicPageNum = pHeadPage->LogicPageNum + *pMidPageCnt + 1;
  80. }
  81. }
  82. else
  83. {
  84. //the head page is not a full page, reset the sector bitmap
  85. pHeadPage->SectorBitmap = tmpBitmap & (FULL_BITMAP_OF_LOGIC_PAGE >> (SECTOR_CNT_OF_LOGIC_PAGE - tmpSectCnt));
  86. }
  87. LOGICCTL_DBG(" head page number:0x%x, head page bitmap:0x%x\n", pHeadPage->LogicPageNum, pHeadPage->SectorBitmap);
  88. LOGICCTL_DBG(" the count of middle page:0x%x\n", *pMidPageCnt);
  89. LOGICCTL_DBG(" tail page number:0x%x, tail page bitmap:0x%x\n\n", pTailPage->LogicPageNum, pTailPage->SectorBitmap);
  90. return 0;
  91. }
  92. /*
  93. ************************************************************************************************************************
  94. * CALCLUATE LOGICAL PAGE PARAMETER
  95. *
  96. *Description: Calculate the parameter for a logical page, the zone number, logic block number and
  97. * and page number in logical block.
  98. *
  99. *Arguments : pLogicPage the pointer to the parameter of the logical page;
  100. * nPage the number of the global logical page;
  101. * nBitmap the bitmap of the valid sector in the logical page.
  102. *
  103. *Return : calculate page parameter result;
  104. * = 0 calculate page parameter successful;
  105. * < 0 calcualte page parameter failed.
  106. ************************************************************************************************************************
  107. */
  108. static __s32 _CalculateLogicPagePar(struct __LogicPageType_t *pLogicPage, __u32 nPage, __u32 nBitmap)
  109. {
  110. __u32 tmpPage, tmpBlk, tmpZone;
  111. tmpPage = nPage % PAGE_CNT_OF_LOGIC_BLK;
  112. tmpBlk = nPage / PAGE_CNT_OF_LOGIC_BLK;
  113. tmpZone = tmpBlk / DATA_BLK_CNT_OF_ZONE;
  114. tmpBlk %= DATA_BLK_CNT_OF_ZONE;
  115. pLogicPage->ZoneNum = tmpZone;
  116. pLogicPage->BlockNum = tmpBlk;
  117. pLogicPage->PageNum = tmpPage;
  118. pLogicPage->SectBitmap = nBitmap;
  119. LOGICCTL_DBG("[LOGICCTL_DBG] The parameter of logical page 0x%x is : zone 0x%x, block 0x%x, page 0x%x\n",
  120. nPage, tmpZone, tmpBlk, tmpPage);
  121. return 0;
  122. }
  123. /*
  124. ************************************************************************************************************************
  125. * UPDATE USER DATA WITH THE CACHE PAGE
  126. *
  127. *Description: Update the user data with the cache page, because the number of the page read is
  128. * same as the cached page, so need update the page data.
  129. *
  130. *Arguments : nSectBitmap the bitmap of the valid sectors in the user buffer;
  131. * pBuf the pointer to he user buffer;
  132. *
  133. *Return : update page data result;
  134. * = 0 update page data successful;
  135. * < 0 update page data failed.
  136. ************************************************************************************************************************
  137. */
  138. static __s32 _UpdateReadPageData(__u32 nSectBitmap, void * pBuf)
  139. {
  140. __s32 i;
  141. __u8 *tmpSrc = LML_WRITE_PAGE_CACHE, *tmpDst = pBuf;
  142. for(i=0; i<SECTOR_CNT_OF_LOGIC_PAGE; i++)
  143. {
  144. if(nSectBitmap & CachePage.SectorBitmap & (1<<i))
  145. {
  146. MEMCPY(tmpDst, tmpSrc, SECTOR_SIZE);
  147. }
  148. tmpSrc += SECTOR_SIZE;
  149. tmpDst += SECTOR_SIZE;
  150. }
  151. return 0;
  152. }
  153. /*
  154. ************************************************************************************************************************
  155. * MERGE WRITE PAGE DATA WITH CACHE PAGE DATA
  156. *
  157. *Description: Merge the data of write page with the cached page.
  158. *
  159. *Arguments : nPage the number of the logical page which need write to nand flash;
  160. * nBitmap the bitmap of the valid sectors in the write page;
  161. * pBuf the pointer to the page data buffer;
  162. *
  163. *Return : merge page data result;
  164. * = 0 merge page data successful;
  165. * < 0 merge page data failed.
  166. ************************************************************************************************************************
  167. */
  168. static __s32 _MergeCachePageData(__u32 nPage, __u32 nBitmap, __u8 *pBuf)
  169. {
  170. __s32 i;
  171. __u8 *tmpSrc = pBuf, *tmpDst = LML_WRITE_PAGE_CACHE;
  172. //check if the cache page is valid
  173. if(CachePage.LogicPageNum == 0xffffffff)
  174. {
  175. //cache page is valid, set the logical page number, and reset the sector bitmap to null
  176. CachePage.LogicPageNum = nPage;
  177. CachePage.SectorBitmap = 0;
  178. }
  179. for(i=0; i<SECTOR_CNT_OF_LOGIC_PAGE; i++)
  180. {
  181. if(nBitmap & (1<<i))
  182. {
  183. //the sector of the write page is valid, copy data to the page cache
  184. MEMCPY(tmpDst, tmpSrc, SECTOR_SIZE);
  185. }
  186. tmpSrc += SECTOR_SIZE;
  187. tmpDst += SECTOR_SIZE;
  188. }
  189. //reset the sector bitmap for the cached page
  190. CachePage.SectorBitmap |= nBitmap;
  191. return 0;
  192. }
  193. /*
  194. ************************************************************************************************************************
  195. * WRITE DATA OF PAGE CACHE TO NAND FLASH
  196. *
  197. *Description: Write the data of page cache to nand flash.
  198. *
  199. *Arguments : none.
  200. *
  201. *Return : write page cache result;
  202. * = 0 write page cache successful;
  203. * < 0 write page cache failed.
  204. ************************************************************************************************************************
  205. */
  206. static __s32 _WritePageCacheToNand(void)
  207. {
  208. __s32 result = 0;
  209. __u32 tmpPage, tmpBitmap;
  210. __u8 *tmpBuf;
  211. tmpPage = CachePage.LogicPageNum;
  212. tmpBitmap = CachePage.SectorBitmap;
  213. tmpBuf = LML_WRITE_PAGE_CACHE;
  214. if(tmpPage != 0xffffffff)
  215. {
  216. if(tmpBitmap != FULL_BITMAP_OF_LOGIC_PAGE)
  217. {
  218. //get the data from logical page to fill the page cache
  219. result = LML_PageRead(tmpPage, tmpBitmap ^ FULL_BITMAP_OF_LOGIC_PAGE, tmpBuf);
  220. if(result < 0)
  221. {
  222. return -1;
  223. }
  224. }
  225. //the data in the page cache is full, write it to nand flash
  226. result = LML_PageWrite(tmpPage, FULL_BITMAP_OF_LOGIC_PAGE, tmpBuf);
  227. if(result < 0)
  228. {
  229. return -1;
  230. }
  231. //clear the buffer page parameter
  232. CachePage.LogicPageNum = 0xffffffff;
  233. CachePage.SectorBitmap = 0x00;
  234. }
  235. return 0;
  236. }
  237. /*
  238. ************************************************************************************************************************
  239. * CALCULATE PHYSICAL OPERATION PARAMETER
  240. *
  241. *Description: Calculate the paramter for physical operation with the number of zone, number of
  242. * super block and number of page in the super block.
  243. *
  244. *Arguments : pPhyPar the pointer to the physical operation parameter;
  245. * nZone the number of the zone which the super block blonged to;
  246. * nBlock the number of the super block;
  247. * nPage the number of the super page in the super block.
  248. *
  249. *Return : calculate parameter result;
  250. * = 0 calculate parameter successful;
  251. * < 0 calcualte parameter failed.
  252. ************************************************************************************************************************
  253. */
  254. #if(0)
  255. __s32 LML_CalculatePhyOpPar(struct __PhysicOpPara_t *pPhyPar, __u32 nZone, __u32 nBlock, __u32 nPage)
  256. {
  257. __u32 tmpDieNum, tmpBnkNum, tmpBlkNum, tmpPageNum;
  258. LOGICCTL_DBG("[LOGICCTL_DBG] Calculate the physical operation parameters.\n"
  259. " ZoneNum:0x%x, BlockNum:0x%x, PageNum: 0x%x\n", nZone, nBlock, nPage);
  260. //calcualte the Die number by the zone number
  261. tmpDieNum = nZone / ZONE_CNT_OF_DIE;
  262. if(SUPPORT_INT_INTERLEAVE && SUPPORT_EXT_INTERLEAVE)
  263. {
  264. //nand flash support internal inter-leave and external iner-leave, the block number is
  265. //same as the virtual block number in the die, the bank number is the virtual page number
  266. //model the inter-leave bank count, and the page number is the virtual page number
  267. //divide the inter-leave bank count
  268. tmpBnkNum = nPage % INTERLEAVE_BANK_CNT;
  269. tmpBlkNum = nBlock;
  270. tmpPageNum = nPage / INTERLEAVE_BANK_CNT;
  271. }
  272. else if(SUPPORT_INT_INTERLEAVE && !SUPPORT_EXT_INTERLEAVE)
  273. {
  274. //nand flash support internal inter-leave but don't support external inter-leave, the block
  275. //number if same as the vitual block number, the bank number is virtual page number model
  276. //inter-leave count and add the chip bank base, the page number is the virtual page number
  277. //divide the inter-leave bank count
  278. tmpBnkNum = (nPage % INTERLEAVE_BANK_CNT) + (tmpDieNum * INTERLEAVE_BANK_CNT);
  279. tmpBlkNum = nBlock;
  280. tmpPageNum = nPage / INTERLEAVE_BANK_CNT;
  281. }
  282. else if(!SUPPORT_INT_INTERLEAVE && SUPPORT_EXT_INTERLEAVE)
  283. {
  284. //nand flash support external inter-leave but don't support internal inter-leave, the block
  285. //number is virtual block number add the die block base, the bank number is the page number
  286. //model the inter-leave bank count, the page number is vitual page number divide the inter-leave
  287. //bank count
  288. tmpBnkNum = nPage % INTERLEAVE_BANK_CNT;
  289. tmpBlkNum = nBlock + (tmpDieNum * (BLOCK_CNT_OF_DIE / PLANE_CNT_OF_DIE));
  290. tmpPageNum = nPage / INTERLEAVE_BANK_CNT;
  291. }
  292. else//(!SUPPORT_INT_INTERLEAVE && !SUPPORT_EXT_INTERLEAVE)
  293. {
  294. //nand flash don't internal inter-leave and extern inter-leave either, the bank number is the
  295. //die number divide the die count of chip, the block number is the virtual block number add
  296. //the die block base in the chip, the page number is same as the virtual page number
  297. tmpBnkNum = tmpDieNum / DIE_CNT_OF_CHIP;
  298. tmpBlkNum = nBlock + (tmpDieNum % DIE_CNT_OF_CHIP) * (BLOCK_CNT_OF_DIE / PLANE_CNT_OF_DIE);
  299. tmpPageNum = nPage;
  300. }
  301. //set the physical operation paramter by the bank number, block number and page number
  302. pPhyPar->BankNum = tmpBnkNum;
  303. pPhyPar->PageNum = tmpPageNum;
  304. pPhyPar->BlkNum = tmpBlkNum;
  305. LOGICCTL_DBG(" Calculate Result: BankNum 0x%x, BlkNum 0x%x, PageNum 0x%x\n", tmpBnkNum, tmpBlkNum, tmpPageNum);
  306. //calculate physical operation parameter successful
  307. return 0;
  308. }
  309. #elif(1)
  310. __s32 LML_CalculatePhyOpPar(struct __PhysicOpPara_t *pPhyPar, __u32 nZone, __u32 nBlock, __u32 nPage)
  311. {
  312. __u32 tmpDieNum, tmpBnkNum, tmpBlkNum, tmpPageNum;
  313. LOGICCTL_DBG("[LOGICCTL_DBG] Calculate the physical operation parameters.\n"
  314. " ZoneNum:0x%x, BlockNum:0x%x, PageNum: 0x%x\n", nZone, nBlock, nPage);
  315. //calcualte the Die number by the zone number
  316. tmpDieNum = nZone / ZONE_CNT_OF_DIE;
  317. if(SUPPORT_INT_INTERLEAVE && SUPPORT_EXT_INTERLEAVE)
  318. {
  319. //nand flash support internal inter-leave and external iner-leave, the block number is
  320. //same as the virtual block number in the die, the bank number is the virtual page number
  321. //model the inter-leave bank count, and the page number is the virtual page number
  322. //divide the inter-leave bank count
  323. tmpBnkNum = nPage % INTERLEAVE_BANK_CNT + (tmpDieNum * INTERLEAVE_BANK_CNT);
  324. tmpBlkNum = nBlock ;
  325. tmpPageNum = nPage / INTERLEAVE_BANK_CNT;
  326. }
  327. else if(SUPPORT_INT_INTERLEAVE && !SUPPORT_EXT_INTERLEAVE)
  328. {
  329. //nand flash support internal inter-leave but don't support external inter-leave, the block
  330. //number if same as the vitual block number, the bank number is virtual page number model
  331. //inter-leave count and add the chip bank base, the page number is the virtual page number
  332. //divide the inter-leave bank count
  333. tmpBnkNum = (nPage % INTERLEAVE_BANK_CNT) + (tmpDieNum * INTERLEAVE_BANK_CNT);
  334. tmpBlkNum = nBlock;
  335. tmpPageNum = nPage / INTERLEAVE_BANK_CNT;
  336. }
  337. else if(!SUPPORT_INT_INTERLEAVE && SUPPORT_EXT_INTERLEAVE)
  338. {
  339. //nand flash support external inter-leave but don't support internal inter-leave, the block
  340. //number is virtual block number add the die block base, the bank number is the page number
  341. //model the inter-leave bank count, the page number is vitual page number divide the inter-leave
  342. //bank count
  343. //tmpBnkNum = nPage % INTERLEAVE_BANK_CNT + (tmpDieNum * INTERLEAVE_BANK_CNT);
  344. tmpBnkNum = nPage % INTERLEAVE_BANK_CNT + (tmpDieNum/DIE_CNT_OF_CHIP) *INTERLEAVE_BANK_CNT;
  345. tmpBlkNum = nBlock+ ((tmpDieNum % DIE_CNT_OF_CHIP) * (BLOCK_CNT_OF_DIE / PLANE_CNT_OF_DIE));
  346. tmpPageNum = nPage / INTERLEAVE_BANK_CNT;
  347. }
  348. else//(!SUPPORT_INT_INTERLEAVE && !SUPPORT_EXT_INTERLEAVE)
  349. {
  350. //nand flash don't internal inter-leave and extern inter-leave either, the bank number is the
  351. //die number divide the die count of chip, the block number is the virtual block number add
  352. //the die block base in the chip, the page number is same as the virtual page number
  353. tmpBnkNum = tmpDieNum / DIE_CNT_OF_CHIP;
  354. tmpBlkNum = nBlock + (tmpDieNum % DIE_CNT_OF_CHIP) * (BLOCK_CNT_OF_DIE / PLANE_CNT_OF_DIE);
  355. tmpPageNum = nPage;
  356. }
  357. //set the physical operation paramter by the bank number, block number and page number
  358. pPhyPar->BankNum = tmpBnkNum;
  359. pPhyPar->PageNum = tmpPageNum;
  360. pPhyPar->BlkNum = tmpBlkNum;
  361. LOGICCTL_DBG(" Calculate Result: BankNum 0x%x, BlkNum 0x%x, PageNum 0x%x\n", tmpBnkNum, tmpBlkNum, tmpPageNum);
  362. //calculate physical operation parameter successful
  363. return 0;
  364. }
  365. #endif
  366. /*
  367. ************************************************************************************************************************
  368. * READ PAGE DATA FROM VIRTUAL BLOCK
  369. *
  370. *Description: Read page data from virtual block, the block is composed by several physical block.
  371. * It is named super block too.
  372. *
  373. *Arguments : pVirtualPage the pointer to the virtual page paramter;
  374. *
  375. *Return : read result;
  376. * = 0 read page data successful;
  377. * < 0 read page data failed.
  378. ************************************************************************************************************************
  379. */
  380. __s32 LML_VirtualPageRead(struct __PhysicOpPara_t *pVirtualPage)
  381. {
  382. __s32 i, result;
  383. __u32 tmpBitmap;
  384. __u8 *tmpSpare, *tmpSrcData, *tmpDstData, *tmpSrcPtr[4], *tmpDstPtr[4];
  385. struct __PhysicOpPara_t tmpPhyPage;
  386. tmpPhyPage = *pVirtualPage;
  387. tmpSpare = tmpPhyPage.SDataPtr;
  388. tmpBitmap = tmpPhyPage.SectBitmap;
  389. if(tmpSpare)
  390. {
  391. tmpPhyPage.SDataPtr = LML_SPARE_BUF;
  392. //process the pointer to spare area data
  393. for(i=0; i<2; i++)
  394. {
  395. if(tmpBitmap & (1<<i))
  396. {
  397. tmpSrcPtr[i] = LML_SPARE_BUF + 4 * i;
  398. tmpDstPtr[i] = tmpSpare + 4 * i;
  399. }
  400. else
  401. {
  402. tmpDstPtr[i] = NULL;
  403. }
  404. }
  405. for(i=0; i<2; i++)
  406. {
  407. if(tmpBitmap & (1<<(i + SECTOR_CNT_OF_SINGLE_PAGE)))
  408. {
  409. tmpSrcPtr[i+2] = LML_SPARE_BUF + 4 * (i + SECTOR_CNT_OF_SINGLE_PAGE);
  410. tmpDstPtr[i+2] = tmpSpare + 8 + 4 * i;
  411. }
  412. else
  413. {
  414. tmpDstPtr[i+2] = NULL;
  415. }
  416. }
  417. }
  418. else
  419. {
  420. tmpPhyPage.SDataPtr = NULL;
  421. }
  422. result = PHY_PageRead(&tmpPhyPage);
  423. //process spare area data
  424. if(tmpSpare)
  425. {
  426. //get the spare area data
  427. for(i=0; i<4; i++)
  428. {
  429. if(tmpDstPtr[i] != NULL)
  430. {
  431. tmpSrcData = tmpSrcPtr[i];
  432. tmpDstData = tmpDstPtr[i];
  433. *tmpDstData++ = *tmpSrcData++;
  434. *tmpDstData++ = *tmpSrcData++;
  435. *tmpDstData++ = *tmpSrcData++;
  436. *tmpDstData++ = *tmpSrcData++;
  437. }
  438. }
  439. }
  440. //add in 2010-05-21 by penggang, the logic layer needn't care the ecc error
  441. if(result == -ERR_ECC)
  442. result = 0;
  443. return result;
  444. }
  445. /*
  446. ************************************************************************************************************************
  447. * WRITE PAGE DATA TO VIRTUAL BLOCK
  448. *
  449. *Description: Write page data to virtual block, the block is composed by several physical block.
  450. * It is named super block too.
  451. *
  452. *Arguments : pVirtualPage the pointer to the virtual page parameter.
  453. *
  454. *Return : write result;
  455. * = 0 write page data successful;
  456. * < 0 write page data failed.
  457. ************************************************************************************************************************
  458. */
  459. __s32 LML_VirtualPageWrite( struct __PhysicOpPara_t *pVirtualPage)
  460. {
  461. __s32 i, result;
  462. __u32 tmpBitmap;
  463. __u8 *tmpSpare, *tmpSrcData, *tmpDstData, *tmpSrcPtr[4], *tmpDstPtr[4];
  464. struct __PhysicOpPara_t tmpPhyPage;
  465. tmpPhyPage = *pVirtualPage;
  466. tmpSpare = tmpPhyPage.SDataPtr;
  467. //tmpBitmap = tmpPhyPage.SectBitmap;
  468. tmpBitmap = FULL_BITMAP_OF_LOGIC_PAGE;
  469. tmpPhyPage.SDataPtr = LML_SPARE_BUF;
  470. //process spare area data
  471. if(tmpSpare)
  472. {
  473. //process the pointer to spare area data
  474. for(i=0; i<2; i++)
  475. {
  476. if(tmpBitmap & (1<<i))
  477. {
  478. tmpSrcPtr[i] = tmpSpare + 4 * i;
  479. tmpDstPtr[i] = LML_SPARE_BUF + 4 * i;
  480. }
  481. else
  482. {
  483. tmpDstPtr[i] = NULL;
  484. }
  485. }
  486. for(i=0; i<2; i++)
  487. {
  488. if(tmpBitmap & (1<<(i + SECTOR_CNT_OF_SINGLE_PAGE)))
  489. {
  490. tmpSrcPtr[i+2] = tmpSpare + 8 + 4 * i;
  491. tmpDstPtr[i+2] = LML_SPARE_BUF + 4 * (i + SECTOR_CNT_OF_SINGLE_PAGE);
  492. }
  493. else
  494. {
  495. tmpDstPtr[i+2] = NULL;
  496. }
  497. }
  498. MEMSET(LML_SPARE_BUF, 0xff, SECTOR_CNT_OF_SUPER_PAGE * 4);
  499. for(i=0; i<4; i++)
  500. {
  501. tmpSrcData = tmpSrcPtr[i];
  502. tmpDstData = tmpDstPtr[i];
  503. if(tmpDstData != NULL)
  504. {
  505. *tmpDstData++ = *tmpSrcData++;
  506. *tmpDstData++ = *tmpSrcData++;
  507. *tmpDstData++ = *tmpSrcData++;
  508. *tmpDstData++ = *tmpSrcData++;
  509. }
  510. }
  511. }
  512. else
  513. {
  514. MEMSET(LML_SPARE_BUF, 0xff, SECTOR_CNT_OF_SUPER_PAGE * 4);
  515. }
  516. result = PHY_PageWrite(&tmpPhyPage);
  517. return result;
  518. }
  519. /*
  520. ************************************************************************************************************************
  521. * NAND FLASH LOGIC MANAGE LAYER ERASE SUPER BLOCK
  522. *
  523. *Description: Erase the given super block.
  524. *
  525. *Arguments : nZone the number of the zone which the super block belonged to;
  526. * nSuperBlk the number of the super block which need be erased.
  527. *
  528. *Return : erase result
  529. * = 0 super block erase successful;
  530. * =-1 super block erase failed.
  531. ************************************************************************************************************************
  532. */
  533. __s32 LML_VirtualBlkErase(__u32 nZone, __u32 nSuperBlk)
  534. {
  535. __s32 i, result = 0;
  536. struct __PhysicOpPara_t tmpPhyBlk;
  537. #if CFG_SUPPORT_WEAR_LEVELLING
  538. //increase the erase counter of super block
  539. BLK_ERASE_CNTER++;
  540. #endif
  541. //erase every block belonged to different banks
  542. for(i=0; i<INTERLEAVE_BANK_CNT; i++)
  543. {
  544. //calculate the physical operation parameter by te die number, block number and page number
  545. LML_CalculatePhyOpPar(&tmpPhyBlk, nZone, nSuperBlk, i);
  546. PHY_BlockErase(&tmpPhyBlk);
  547. }
  548. //check the result of the block erase
  549. for(i=0; i<INTERLEAVE_BANK_CNT; i++)
  550. {
  551. result = PHY_SynchBank(i, SYNC_BANK_MODE);
  552. if(result < 0)
  553. {
  554. //the operation of last page write is failed
  555. LOGICCTL_ERR("[LOGICCTL_DBG] erase zone %x block %x bank %x fail\n",
  556. nZone,nSuperBlk,i);
  557. return -1;
  558. }
  559. }
  560. return 0;
  561. }
  562. /*
  563. ************************************************************************************************************************
  564. * LOGICAL MANAGE LAYER CLOSE WRITE PAGE
  565. *
  566. *Description: Close last write page, for switch nand flash operation mode.
  567. *
  568. *Arguments : none.
  569. *
  570. *Return : clase page result;
  571. * = 0 close page successful;
  572. * = -1 close page failed.
  573. ************************************************************************************************************************
  574. */
  575. static __s32 _CloseWritePage(void)
  576. {
  577. __s32 result;
  578. struct __PhysicOpPara_t tmpPage;
  579. struct __LogBlkType_t tmpLogBlk;
  580. //check if current mode is write mode
  581. if(LogicalCtl.OpMode == 'w')
  582. {
  583. //calculate the paramter of last page
  584. LML_CalculatePhyOpPar(&tmpPage, LogicalCtl.ZoneNum, LogicalCtl.LogBlkNum.PhyBlkNum, LogicalCtl.LogPageNum);
  585. result = PHY_SynchBank(tmpPage.BankNum, SYNC_BANK_MODE);
  586. if(result < 0)
  587. {
  588. //the operation of last page write is failed
  589. LOGICCTL_DBG("[LOGICCTL_DBG] Write page failed when close write page! Bnk:0x%x, Blk:0x%x, Page:0x%x\n",
  590. tmpPage.BankNum, tmpPage.BlkNum, tmpPage.PageNum);
  591. //process the bad block
  592. result = LML_BadBlkManage(&LogicalCtl.LogBlkNum, LogicalCtl.ZoneNum, LogicalCtl.LogPageNum + 1, &LogicalCtl.LogBlkNum);
  593. if(result < 0)
  594. {
  595. LOGICCTL_ERR("[LOGICCTL_ERR] Bad block proecess failed when close write page, Err:0x%x\n", result);
  596. return -1;
  597. }
  598. //reset the physical block number of the log block with the new log block
  599. BMM_GetLogBlk(LogicalCtl.LogicBlkNum, &tmpLogBlk);
  600. tmpLogBlk.PhyBlk = LogicalCtl.LogBlkNum;
  601. BMM_SetLogBlk(LogicalCtl.LogicBlkNum, &tmpLogBlk);
  602. }
  603. //wait the nand flash chip ready
  604. PHY_SynchBank(tmpPage.BankNum, SYNC_CHIP_MODE);
  605. }
  606. LogicalCtl.OpMode = 'n';
  607. return 0;
  608. }
  609. /*
  610. ************************************************************************************************************************
  611. * NAND FLASH LOGIC MANAGE LAYER PAGE READ
  612. *
  613. *Description: Read data from logic disk to buffer based page.
  614. *
  615. *Arguments : nPage the page address which need be read;
  616. * nBitmap the bitmap of the sectors in the page which need be read data;
  617. * pBuf the pointer to the buffer where will store the data read out.
  618. *
  619. *Return : page read result;
  620. * = 0 read successful;
  621. * > 0 read successful, but need do some process;
  622. * < 0 read failed.
  623. ************************************************************************************************************************
  624. */
  625. __s32 LML_PageRead(__u32 nPage, __u32 nBitmap, void* pBuf)
  626. {
  627. __s32 result;
  628. __u32 tmpSuperBlk, tmpSuperPage;
  629. struct __LogicPageType_t tmpLogicPage;
  630. struct __PhysicOpPara_t tmpPhyPage;
  631. struct __LogBlkType_t tmpLogBlk;
  632. _CalculateLogicPagePar(&tmpLogicPage, nPage, nBitmap);
  633. //check if last operation is read, if not, need set to read mode
  634. if(LogicalCtl.OpMode != 'r')
  635. {
  636. if(LogicalCtl.OpMode == 'w')
  637. {
  638. //last operation is write, need close last write logical page, switch to read mode
  639. result = _CloseWritePage();
  640. if(result < 0)
  641. {
  642. LOGICCTL_ERR("[LOGICCTL_ERR] Close write page failed, when read logical page!\n");
  643. return -ERR_LOGICCTL;
  644. }
  645. }
  646. //set operation mode to read
  647. LogicalCtl.OpMode = 'r';
  648. }
  649. //check if access the same zone area as last access
  650. if(tmpLogicPage.ZoneNum != LogicalCtl.ZoneNum)
  651. {
  652. //swap the block mapping table to ram which is need be accessing currently
  653. result = BMM_SwitchMapTbl(tmpLogicPage.ZoneNum);
  654. if(result < 0)
  655. {
  656. LOGICCTL_ERR("[LOGICCTL_ERR] Switch block mapping table failed when read logical page! Err:0x%x\n", result);
  657. return -ERR_MAPPING;
  658. }
  659. //set the zone number that accessing currently
  660. LogicalCtl.ZoneNum = tmpLogicPage.ZoneNum;
  661. //reset the number of logical block
  662. LogicalCtl.LogicBlkNum = 0xffff;
  663. }
  664. //check if accessing the same logical block as last access
  665. if(tmpLogicPage.BlockNum != LogicalCtl.LogicBlkNum)
  666. {
  667. //get the data block number and log block number for read
  668. BMM_GetDataBlk(tmpLogicPage.BlockNum, &LogicalCtl.DataBlkNum);
  669. BMM_GetLogBlk(tmpLogicPage.BlockNum, &tmpLogBlk);
  670. LogicalCtl.LogBlkNum = tmpLogBlk.PhyBlk;
  671. //set the logical block number for logical control parameter
  672. LogicalCtl.LogicBlkNum = tmpLogicPage.BlockNum;
  673. }
  674. //set the number for logical page that accessing currently
  675. LogicalCtl.LogicPageNum = tmpLogicPage.PageNum;
  676. //get the number of log page for read
  677. if(LogicalCtl.LogBlkNum.PhyBlkNum != 0xffff)
  678. {
  679. //get log page with read mode
  680. LogicalCtl.LogPageNum = PMM_GetLogPage(tmpLogicPage.BlockNum, LogicalCtl.LogicPageNum, 'r');
  681. }
  682. else
  683. {
  684. LogicalCtl.LogPageNum = 0xffff;
  685. }
  686. //set the number of super block and super page in the super block for get page data
  687. if(LogicalCtl.LogPageNum != 0xffff)
  688. {
  689. tmpSuperBlk = LogicalCtl.LogBlkNum.PhyBlkNum;
  690. tmpSuperPage = LogicalCtl.LogPageNum;
  691. }
  692. else
  693. {
  694. tmpSuperBlk = LogicalCtl.DataBlkNum.PhyBlkNum;
  695. tmpSuperPage = LogicalCtl.LogicPageNum;
  696. }
  697. //calculate the parameter of physical operation for get page data
  698. LML_CalculatePhyOpPar(&tmpPhyPage, LogicalCtl.ZoneNum, tmpSuperBlk, tmpSuperPage);
  699. tmpPhyPage.SectBitmap = tmpLogicPage.SectBitmap;
  700. tmpPhyPage.MDataPtr = pBuf;
  701. tmpPhyPage.SDataPtr = NULL;
  702. //get data from physical page with the physical operation
  703. result = LML_VirtualPageRead(&tmpPhyPage);
  704. if(result < 0)
  705. {
  706. LOGICCTL_ERR("[LOGICCTL_ERR] Get page data failed when read logical page! Err:0x%x\n ", result);
  707. return -1;
  708. }
  709. return result;
  710. }
  711. /*
  712. ************************************************************************************************************************
  713. * NAND FLASH LOGIC MANAGE LAYER PAGE WRITE
  714. *
  715. *Description: Write data from buffer to logic area based on page.
  716. *
  717. *Arguments : nPage the page address which need be write;
  718. * nBitmap the bitmap of sectors in the page which need be write, it is always full;
  719. * pBuf the pointer to the buffer where is storing the data.
  720. *
  721. *Return : write result;
  722. * = 0 write successful;
  723. * > 0 write successful, but need do some process;
  724. * < 0 write failed.
  725. ************************************************************************************************************************
  726. */
  727. __s32 LML_PageWrite(__u32 nPage, __u32 nBitmap, void* pBuf)
  728. {
  729. __s32 result;
  730. struct __LogicPageType_t tmpLogicPage;
  731. struct __PhysicOpPara_t tmpPhyPage;
  732. struct __NandUserData_t tmpSpare[2];
  733. struct __LogBlkType_t tmpLogBlk;
  734. //check if the bitmap of valid sectors is full, if not, report error
  735. if(nBitmap != FULL_BITMAP_OF_LOGIC_PAGE)
  736. {
  737. LOGICCTL_ERR("[LOGICCTL_ERR] Sector bitmap is not full when write logical page!\n");
  738. return -ERR_LOGICCTL;
  739. }
  740. //calculate the pamater for the logical page
  741. _CalculateLogicPagePar(&tmpLogicPage, nPage, nBitmap);
  742. //check if access the same zone area as last access
  743. if(tmpLogicPage.ZoneNum != LogicalCtl.ZoneNum)
  744. {
  745. //last operation is write, need close last write logical page, switch to read mode
  746. result = _CloseWritePage();
  747. if(result < 0)
  748. {
  749. LOGICCTL_ERR("[LOGICCTL_ERR] Close write page failed, when write logical page!\n");
  750. return -ERR_LOGICCTL;
  751. }
  752. //swap the block mapping table to ram which is need be accessing currently
  753. result = BMM_SwitchMapTbl(tmpLogicPage.ZoneNum);
  754. if(result < 0)
  755. {
  756. LOGICCTL_ERR("[LOGICCTL_ERR] Switch block mapping table failed when write logical page! Err:0x%x\n", result);
  757. return -ERR_MAPPING;
  758. }
  759. //set the zone number that accessing currently
  760. LogicalCtl.ZoneNum = tmpLogicPage.ZoneNum;
  761. //reset the number of logical block
  762. LogicalCtl.LogicBlkNum = 0xffff;
  763. }
  764. //set dirty flag for block mapping table
  765. BMM_SetDirtyFlag();
  766. //check if accessing the same logical block as last access
  767. if(tmpLogicPage.BlockNum != LogicalCtl.LogicBlkNum)
  768. {
  769. //last operation is write, need close last write logical page, switch to read mode
  770. result = _CloseWritePage();
  771. if(result < 0)
  772. {
  773. LOGICCTL_ERR("[LOGICCTL_ERR] Close write page failed, when write logical page!\n");
  774. return -ERR_LOGICCTL;
  775. }
  776. //set the logical block number for logical control parameter
  777. LogicalCtl.LogicBlkNum = tmpLogicPage.BlockNum;
  778. }
  779. //set the number of the logical page for logical control
  780. LogicalCtl.LogicPageNum = tmpLogicPage.PageNum;
  781. //get log page for write page data, log page is necessary when write logical page
  782. LogicalCtl.LogPageNum = PMM_GetLogPage(LogicalCtl.LogicBlkNum, LogicalCtl.LogicPageNum, 'w');
  783. if(LogicalCtl.LogPageNum == 0xffff)
  784. {
  785. LOGICCTL_ERR("[LOGICCTL_ERR] Get log page failed when write logical page!\n");
  786. return -ERR_MAPPING;
  787. }
  788. //get the data block number and log block number for write
  789. BMM_GetDataBlk(tmpLogicPage.BlockNum, &LogicalCtl.DataBlkNum);
  790. BMM_GetLogBlk(tmpLogicPage.BlockNum, &tmpLogBlk);
  791. LogicalCtl.LogBlkNum = tmpLogBlk.PhyBlk;
  792. //check if the log block is valid, log block is nessesary necessary when write logical page
  793. if(LogicalCtl.LogBlkNum.PhyBlkNum == 0xffff)
  794. {
  795. LOGICCTL_ERR("[LOGICCTL_ERR] Get log block failed when write logical page!\n");
  796. return -ERR_MAPPING;
  797. }
  798. //set spare area data for writing to the spare area of nand flash
  799. if(LogicalCtl.LogPageNum == 0)
  800. {
  801. //log page is the page0 of the super block, the meaning of the page status is log age
  802. LML_CalculatePhyOpPar(&tmpPhyPage, LogicalCtl.ZoneNum, LogicalCtl.DataBlkNum.PhyBlkNum, 0);
  803. tmpPhyPage.SectBitmap = 0x3;
  804. tmpPhyPage.MDataPtr = LML_TEMP_BUF;
  805. tmpPhyPage.SDataPtr = (void *)tmpSpare;
  806. result = LML_VirtualPageRead(&tmpPhyPage);
  807. if(result < 0)
  808. {
  809. LOGICCTL_ERR("[LOGICCTL_ERR] Get log age of data block failed when write logical page, Err:0x%x!\n", result);
  810. return -ERR_PHYSIC;
  811. }
  812. //increase the log age
  813. tmpSpare[0].PageStatus = tmpSpare[0].PageStatus + 1;
  814. tmpSpare[1].PageStatus = tmpSpare[0].PageStatus;
  815. }
  816. else
  817. {
  818. //set page used mark to the spare area data
  819. tmpSpare[0].PageStatus = 0x55;
  820. tmpSpare[1].PageStatus = 0x55;
  821. }
  822. tmpSpare[0].BadBlkFlag = 0xff;
  823. tmpSpare[1].BadBlkFlag = 0xff;
  824. tmpSpare[0].LogicInfo = ((LogicalCtl.ZoneNum % ZONE_CNT_OF_DIE)<<10) | LogicalCtl.LogicBlkNum;
  825. tmpSpare[1].LogicInfo = ((LogicalCtl.ZoneNum % ZONE_CNT_OF_DIE)<<10) | LogicalCtl.LogicBlkNum;
  826. tmpSpare[0].LogicPageNum = LogicalCtl.LogicPageNum;
  827. tmpSpare[1].LogicPageNum = LogicalCtl.LogicPageNum;
  828. __TRY_WRITE_PHYSIC_PAGE:
  829. //calculate the parameter for writing page to nand flash
  830. LML_CalculatePhyOpPar(&tmpPhyPage, LogicalCtl.ZoneNum, LogicalCtl.LogBlkNum.PhyBlkNum, LogicalCtl.LogPageNum);
  831. tmpPhyPage.SectBitmap = tmpLogicPage.SectBitmap;
  832. tmpPhyPage.MDataPtr = pBuf;
  833. tmpPhyPage.SDataPtr = (void *)tmpSpare;
  834. #if !CFG_SUPPORT_CHECK_WRITE_SYNCH
  835. if (LogicalCtl.OpMode == 'w')
  836. {
  837. //synch currently write bank
  838. result = PHY_SynchBank(tmpPhyPage.BankNum, SYNC_BANK_MODE);
  839. if(result < 0)
  840. {
  841. //the last write operation on current bank is failed, the block is bad, need proccess it
  842. LOGICCTL_DBG("[LOGICCTL_DBG] Find a bad block when write logical page! bank:0x%x, block:0x%x, page:0x%x\n",
  843. tmpPhyPage.BankNum, tmpPhyPage.BlkNum, tmpPhyPage.PageNum);
  844. //process the bad block
  845. result = LML_BadBlkManage(&LogicalCtl.LogBlkNum, LogicalCtl.ZoneNum, LogicalCtl.LogPageNum, &LogicalCtl.LogBlkNum);
  846. if(result < 0)
  847. {
  848. LOGICCTL_ERR("[LOGICCTL_ERR] Bad block proecess failed when write page, Err:0x%x\n", result);
  849. return -1;
  850. }
  851. //reset the physical block number of the log block with the new log block
  852. BMM_GetLogBlk(LogicalCtl.LogicBlkNum, &tmpLogBlk);
  853. tmpLogBlk.PhyBlk = LogicalCtl.LogBlkNum;
  854. BMM_SetLogBlk(LogicalCtl.LogicBlkNum, &tmpLogBlk);
  855. goto __TRY_WRITE_PHYSIC_PAGE;
  856. }
  857. }
  858. #endif
  859. result = LML_VirtualPageWrite(&tmpPhyPage);
  860. if(result < 0)
  861. {
  862. LOGICCTL_ERR("[LOGICCTL_ERR] Physical write module failed when write logical page, Err:0x%x!\n", result);
  863. return -ERR_LOGICCTL;
  864. }
  865. #if CFG_SUPPORT_CHECK_WRITE_SYNCH
  866. //synch currently write bank
  867. result = PHY_SynchBank(tmpPhyPage.BankNum, SYNC_BANK_MODE);
  868. if(result < 0)
  869. {
  870. //the last write operation on current bank is failed, the block is bad, need proccess it
  871. LOGICCTL_DBG("[LOGICCTL_DBG] Find a bad block when write logical page! bank:0x%x, block:0x%x, page:0x%x\n",
  872. tmpPhyPage.BankNum, tmpPhyPage.BlkNum, tmpPhyPage.PageNum);
  873. //process the bad block
  874. result = LML_BadBlkManage(&LogicalCtl.LogBlkNum, LogicalCtl.ZoneNum, LogicalCtl.LogPageNum, &LogicalCtl.LogBlkNum);
  875. if(result < 0)
  876. {
  877. LOGICCTL_ERR("[LOGICCTL_ERR] Bad block proecess failed when write page, Err:0x$x\n", result);
  878. return -1;
  879. }
  880. //reset the physical block number of the log block with the new log block
  881. BMM_GetLogBlk(LogicalCtl.LogicBlkNum, &tmpLogBlk);
  882. tmpLogBlk.PhyBlk = LogicalCtl.LogBlkNum;
  883. BMM_SetLogBlk(LogicalCtl.LogicBlkNum, &tmpLogBlk);
  884. goto __TRY_WRITE_PHYSIC_PAGE;
  885. }
  886. #endif
  887. //set the mode of operation
  888. LogicalCtl.OpMode = 'w';
  889. return 0;
  890. }
  891. /*
  892. ************************************************************************************************************************
  893. * NAND FLASH LOGIC MANAGE LAYER FLUSH PAGE CACHE
  894. *
  895. *Description: Flush the data in the cache buffer to nand flash.
  896. *
  897. *Arguments : none
  898. *Return : flush result;
  899. * = 0 flush successful;
  900. * = -1 flush failed.
  901. ************************************************************************************************************************
  902. */
  903. __s32 LML_FlushPageCache(void)
  904. {
  905. __s32 result;
  906. result = _WritePageCacheToNand();
  907. if(result < 0)
  908. {
  909. LOGICCTL_ERR("[LOGICCTL_ERR] Write page cache to nand failed when flush page cache! Error:0x%x\n", result);
  910. return -1;
  911. }
  912. result = _CloseWritePage();
  913. if(result < 0)
  914. {
  915. LOGICCTL_ERR("[LOGICCTL_ERR] Close write page failed when flush page cache! Error:0x%x\n", result);
  916. return -1;
  917. }
  918. return 0;
  919. }
  920. /*
  921. ************************************************************************************************************************
  922. * NAND FLASH LOGIC MANAGE LAYER READ
  923. *
  924. *Description: Read data from logic disk area to buffer.
  925. *
  926. *Arguments : nSectNum the logic block address on the logic area from where to read;
  927. * nSectorCnt the size of the data need be read, based on sector;
  928. * pBuf the pointer to the buffer where will store the data readout of nand.
  929. *
  930. *Return : read result;
  931. * = 0 read successful;
  932. * = -1 read failed.
  933. ************************************************************************************************************************
  934. */
  935. __s32 LML_Read(__u32 nSectNum, __u32 nSectorCnt, void* pBuf)
  936. {
  937. __s32 i, result;
  938. __u32 tmpMidPageCnt, tmpPageNum, tmpBitmap, tmpPageCnt;
  939. __u8 *tmpBuf;
  940. struct __GlobalLogicPageType_t tmpHeadPage, tmpTailPage;
  941. LOGICCTL_DBG("[LOGICCTL_DBG] LML_Read, sector number:0x%x, sector cnt:0x%x, Buffer:0x%x\n", nSectNum, nSectorCnt, pBuf);
  942. if(((__u32)pBuf)&0x3)
  943. {
  944. LOGICCTL_ERR("[LOGICCTL_ERR] LML_Write, invalid bufaddr: 0x%x \n", (__u32)(pBuf));
  945. return -ERR_ADDRBEYOND;
  946. }
  947. //check if the parameter is valid
  948. if(((nSectNum + nSectorCnt) > LogicalCtl.DiskCap)||(nSectNum>LogicalCtl.DiskCap-1)||(nSectorCnt>LogicalCtl.DiskCap-1))
  949. {
  950. LOGICCTL_ERR("[LOGICCTL_ERR] LML_Read, the addr of read(start:%x, cnt:%x) is beyond the disk volume %x!!!\n",
  951. nSectNum, nSectorCnt,LogicalCtl.DiskCap);
  952. return -ERR_ADDRBEYOND;
  953. }
  954. if(!nSectorCnt)
  955. {
  956. LOGICCTL_DBG("[WARNING] LML_Read, sector count of read is 0!!!\n");
  957. return 0;
  958. }
  959. //calculate logical parameter of the sectors
  960. _CalculateSectPar(nSectNum, nSectorCnt, &tmpHeadPage, &tmpMidPageCnt, &tmpTailPage);
  961. tmpBuf = pBuf;
  962. //calculate the buffer address for page align
  963. for(i=0; i<SECTOR_CNT_OF_LOGIC_PAGE; i++)
  964. {
  965. if(tmpHeadPage.SectorBitmap & (1<<i))
  966. {
  967. break;
  968. }
  969. tmpBuf -= SECTOR_SIZE;
  970. }
  971. tmpPageNum = tmpHeadPage.LogicPageNum;
  972. tmpBitmap = tmpHeadPage.SectorBitmap;
  973. //calculate the whole count the logical pages
  974. tmpPageCnt = 1 + tmpMidPageCnt;
  975. if(tmpTailPage.SectorBitmap)
  976. {
  977. tmpPageCnt++;
  978. }
  979. for(i=0; i<tmpPageCnt; i++)
  980. {
  981. //read data from the logical page
  982. result = LML_PageRead(tmpPageNum, tmpBitmap, tmpBuf);
  983. if(result < 0)
  984. {
  985. //get page data failed!
  986. LOGICCTL_ERR("[LOGICCTL_ERR] LML_Read, read page data faild! the page number:0x%x, sector bitmap:0x%x, buffer:0x%x, "
  987. "error number:0x%x\n",tmpPageNum, tmpBitmap, (__u32)tmpBuf, result);
  988. return -1;
  989. }
  990. #if CFG_SUPPORT_READ_RECLAIM
  991. if(result == ECC_LIMIT)
  992. {
  993. LML_ReadReclaim(tmpPageNum);
  994. }
  995. #endif
  996. //check if need update the page data with the cache page
  997. if(tmpPageNum == CachePage.LogicPageNum)
  998. {
  999. _UpdateReadPageData(tmpBitmap, tmpBuf);
  1000. }
  1001. //increase the logical page number and the buffer address
  1002. tmpPageNum++;
  1003. tmpBuf += SECTOR_SIZE * SECTOR_CNT_OF_LOGIC_PAGE;
  1004. //check if read data from the tail page
  1005. if(tmpTailPage.SectorBitmap && (i == tmpPageCnt - 2))
  1006. {
  1007. tmpBitmap = tmpTailPage.SectorBitmap;
  1008. }
  1009. else
  1010. {
  1011. tmpBitmap = FULL_BITMAP_OF_LOGIC_PAGE;
  1012. }
  1013. }
  1014. return 0;
  1015. }
  1016. EXPORT_SYMBOL(LML_Read);
  1017. /*
  1018. extern dump(void * buf, __u32 len, __u8 nbyte, __u8 linelen);
  1019. void echo_write_data (__u32 nSectNum, __u32 nSectorCnt, void* pBuf)
  1020. {
  1021. __u32 i,j;
  1022. __u8 *buf;
  1023. for (i = 0,j = nSectNum; i < nSectorCnt; i++,j++)
  1024. {
  1025. buf = (__u8 *)pBuf + i*512;
  1026. PRINT("***********echo data from sector %d***************\n",j);
  1027. dump(buf, 16,1, 16);
  1028. }
  1029. return;
  1030. }*/
  1031. /*
  1032. ************************************************************************************************************************
  1033. * NAND FLASH LOGIC MANAGE LAYER WRITE
  1034. *
  1035. *Description: Write data from buffer to logic disk area.
  1036. *
  1037. *Arguments : nSectNum the logic block address on the logic area from where to write;
  1038. * nSectorCnt the size of the data need to be write, based on sector;
  1039. * pBuf the pointer to the buffer where stored the data write to nand flash.
  1040. *
  1041. *Return : write result;
  1042. * = 0 write successful;
  1043. * = -1 write failed.
  1044. ************************************************************************************************************************
  1045. */
  1046. __s32 LML_Write(__u32 nSectNum, __u32 nSectorCnt, void* pBuf)
  1047. {
  1048. __s32 i, result;
  1049. __u32 tmpMidPageCnt, tmpPageNum, tmpBitmap, tmpPageCnt;
  1050. __u8 *tmpBuf;
  1051. struct __GlobalLogicPageType_t tmpHeadPage, tmpTailPage;
  1052. if(((__u32)pBuf)&0x3)
  1053. {
  1054. LOGICCTL_ERR("[LOGICCTL_ERR] LML_Write, invalid bufaddr: 0x%x \n", (__u32)(pBuf));
  1055. return -ERR_ADDRBEYOND;
  1056. }
  1057. if(((nSectNum + nSectorCnt) > LogicalCtl.DiskCap)||(nSectNum>LogicalCtl.DiskCap-1)||(nSectorCnt>LogicalCtl.DiskCap-1))
  1058. {
  1059. LOGICCTL_ERR("[LOGICCTL_ERR] LML_Write, the addr of write(start:%x, cnt:%x) is beyond the disk volume %x!!!\n",
  1060. nSectNum, nSectorCnt,LogicalCtl.DiskCap);
  1061. return -ERR_ADDRBEYOND;
  1062. }
  1063. if(!nSectorCnt)
  1064. {
  1065. LOGICCTL_DBG("[WARNING] LML_Write, sector count of write is 0!!!\n");
  1066. return 0;
  1067. }
  1068. //calculate the logical parameter for the sectors
  1069. _CalculateSectPar(nSectNum, nSectorCnt, &tmpHeadPage, &tmpMidPageCnt, &tmpTailPage);
  1070. tmpBuf = pBuf;
  1071. //calculate the buffer address for page align
  1072. for(i=0; i<SECTOR_CNT_OF_LOGIC_PAGE; i++)
  1073. {
  1074. if(tmpHeadPage.SectorBitmap & (1<<i))
  1075. {
  1076. break;
  1077. }
  1078. tmpBuf -= SECTOR_SIZE;
  1079. }
  1080. tmpPageNum = tmpHeadPage.LogicPageNum;
  1081. tmpBitmap = tmpHeadPage.SectorBitmap;
  1082. //calculate the whole count the logical pages
  1083. tmpPageCnt = 1 + tmpMidPageCnt;
  1084. if(tmpTailPage.SectorBitmap)
  1085. {
  1086. tmpPageCnt++;
  1087. }
  1088. for(i=0; i<tmpPageCnt; i++)
  1089. {
  1090. //check if current write page is same as the cached page
  1091. if(tmpPageNum == CachePage.LogicPageNum)
  1092. {
  1093. //merge current page data with the cached page
  1094. _MergeCachePageData(tmpPageNum, tmpBitmap, tmpBuf);
  1095. }
  1096. else
  1097. {
  1098. //flush cached page to nand flash
  1099. result = _WritePageCacheToNand();
  1100. if(result < 0)
  1101. {
  1102. LOGICCTL_ERR("[LOGICCTL_ERR] Write page cache to nand flash failed!\n");
  1103. return -1;
  1104. }
  1105. if(tmpBitmap == FULL_BITMAP_OF_LOGIC_PAGE)
  1106. {
  1107. //write the full page to nand flash
  1108. result = LML_PageWrite(tmpPageNum, tmpBitmap, tmpBuf);
  1109. if(result < 0)
  1110. {
  1111. LOGICCTL_ERR("[LOGICCTL_ERR] Write logical page failed! Error:0x%x\n", result);
  1112. return -1;
  1113. }
  1114. }
  1115. else
  1116. {
  1117. //write page is not full, merge the data to page cache
  1118. _MergeCachePageData(tmpPageNum, tmpBitmap, tmpBuf);
  1119. }
  1120. }
  1121. //increase the logical page number and the buffer address
  1122. tmpPageNum++;
  1123. tmpBuf += SECTOR_SIZE * SECTOR_CNT_OF_LOGIC_PAGE;
  1124. //reset the sector bitmap in the logical page
  1125. if(tmpTailPage.SectorBitmap && (i == tmpPageCnt - 2))
  1126. {
  1127. tmpBitmap = tmpTailPage.SectorBitmap;
  1128. }
  1129. else
  1130. {
  1131. tmpBitmap = FULL_BITMAP_OF_LOGIC_PAGE;
  1132. }
  1133. }
  1134. return 0;
  1135. }
  1136. EXPORT_SYMBOL(LML_Write);
  1137. /*
  1138. ************************************************************************************************************************
  1139. * INITIATE NAND FLASH LOGIC MANAGE LAYER
  1140. *
  1141. *Description: initiate the logic manage layer for nand flash driver.
  1142. *
  1143. *Arguments : none;
  1144. *
  1145. *Return : intiate result;
  1146. * = 0 init successful;
  1147. * = -1 init failed.
  1148. ************************************************************************************************************************
  1149. */
  1150. __s32 LML_Init(void)
  1151. {
  1152. __s32 result;
  1153. CachePage.LogicPageNum = 0xffffffff;
  1154. CachePage.SectorBitmap = 0x00000000;
  1155. LogicalCtl.OpMode = 'n';
  1156. LogicalCtl.ZoneNum = 0xff;
  1157. LogicalCtl.LogicBlkNum = 0xffff;
  1158. LogicalCtl.LogicPageNum = 0xffff;
  1159. LogicalCtl.LogPageNum = 0xffff;
  1160. LogicalCtl.DataBlkNum.BlkEraseCnt = 0xffff;
  1161. LogicalCtl.DataBlkNum.PhyBlkNum = 0xffff;
  1162. LogicalCtl.LogBlkNum.BlkEraseCnt = 0xffff;
  1163. LogicalCtl.LogBlkNum.PhyBlkNum = 0xffff;
  1164. LogicalCtl.DiskCap = SECTOR_CNT_OF_SINGLE_PAGE * PAGE_CNT_OF_PHY_BLK * BLOCK_CNT_OF_DIE * \
  1165. DIE_CNT_OF_CHIP * NandDriverInfo.NandStorageInfo->ChipCnt / BLOCK_CNT_OF_ZONE * DATA_BLK_CNT_OF_ZONE;
  1166. //request page buffer for process data
  1167. NandDriverInfo.PageCachePool->PageCache1 = (__u8 *)MALLOC(SECTOR_CNT_OF_LOGIC_PAGE * SECTOR_SIZE);
  1168. if(!NandDriverInfo.PageCachePool->PageCache1)
  1169. {
  1170. LOGICCTL_ERR("[LOGICCTL_ERR] Request memory for nand flash page cache failed!!");
  1171. return -ERR_MALLOC;
  1172. }
  1173. NandDriverInfo.PageCachePool->PageCache2 = NULL;
  1174. //request buffer for process spare area data
  1175. MEMSET(LML_SPARE_BUF, 0xff, SECTOR_CNT_OF_SUPER_PAGE * 4);
  1176. //init the mapping tabel manage module
  1177. result = BMM_InitMapTblCache();
  1178. if(result < 0)
  1179. {
  1180. LOGICCTL_ERR("[LOGICCTL_ERR] Init the mapping table manage module failed! Err:0x%x\n", result);
  1181. return -ERR_MAPPING;
  1182. }
  1183. result = PMM_InitMapTblCache();
  1184. if(result < 0)
  1185. {
  1186. LOGICCTL_ERR("[LOGICCTL_ERR] Init the mapping table manage module failed! Err:0x%x\n", result);
  1187. return -ERR_MAPPING;
  1188. }
  1189. return 0;
  1190. }
  1191. /*
  1192. ************************************************************************************************************************
  1193. * NAND FLASH LOGIC MANAGE LAYER EXIT
  1194. *
  1195. *Description: exit nand flash logic manage layer.
  1196. *
  1197. *Arguments : none;
  1198. *
  1199. *Return : exit result;
  1200. * = 0 exit successfu;
  1201. * = -1 exit failed.
  1202. ************************************************************************************************************************
  1203. */
  1204. __s32 LML_Exit(void)
  1205. {
  1206. //flush page cache to nand flash
  1207. LML_FlushPageCache();
  1208. //write all mapping table to nand flash
  1209. BMM_WriteBackAllMapTbl();
  1210. //free the mapping module
  1211. PMM_ExitMapTblCache();
  1212. BMM_ExitMapTblCache();
  1213. FREE(NandDriverInfo.PageCachePool->PageCache1,SECTOR_CNT_OF_LOGIC_PAGE * SECTOR_SIZE);
  1214. return 0;
  1215. }
  1216. // 2010-12-04 modified
  1217. __u32 NAND_GetDiskSize(void)
  1218. {
  1219. __u32 disksize;
  1220. disksize = (SECTOR_CNT_OF_SINGLE_PAGE * PAGE_CNT_OF_PHY_BLK * BLOCK_CNT_OF_DIE * \
  1221. DIE_CNT_OF_CHIP * NandStorageInfo.ChipCnt / 1024 * DATA_BLK_CNT_OF_ZONE);
  1222. return disksize;
  1223. }