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