Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3509 lines
134 KiB

  1. /*
  2. * $Log: V:/Flite/archives/TrueFFS5/Src/NFTLLITE.C_V $
  3. *
  4. * Rev 1.27 Apr 15 2002 07:38:22 oris
  5. * Added support for RAM based MTD power failure tests.
  6. * Remove cache allocation checks - They are not needed since the cache routine itself check for proper allocation.
  7. * Improved power failure resistant:
  8. * - Added support for VERIFY_ERASED_SECTOR compilation flag - make sure a sector is free before writing it.
  9. * - writeAndCheck() -
  10. * 1) Added an option to verify that the sector is erased before writing.
  11. * It subject to the FL_UPS/FL_OFF/FL_ON modes of the flVerifyWrite environment variable.
  12. * 2) Added support for partition > 0.
  13. * - getUnitData() - Bug fix - in case of invalid replacement unit if we are mounting or formatting store physical unit number in
  14. * invalidReplacement field of the Anand record otherwise mark head of chain as frozen and not the unit itself.
  15. * - Bug fix - Added logic to find end of endless loops - findEndOfEndlessLoop()
  16. * - virtual2Physical() - Added call to findEndOfEndlessLoop() if needed and return address of next free sector (used verifySector()).
  17. * - initNFTL() - Added initialization of TL verifyBuffer buffer and invalidReplacement fields.
  18. * - Separated the search for a free unit in physical table from allocateUnit() into dedicated routine findFreeUnit().
  19. * - foldUnit()
  20. * 1) Added support for partition > 0.
  21. * 2) Prevent a recursive call to foldUnit by changing allocateUnit() with findFreeUnit().
  22. * 3) Added logic for endless loops.
  23. * 4) Added check that last sector of chain can be used.
  24. * - foldBestChain() - revised the entire routine
  25. * 1) If folding not in place was forced free all frozen units.
  26. * 2) Validate that a unit was actually freed.
  27. * - mountUnit() -
  28. * 1) In case of bad virtual unit number format the unit . An invalid virtual unit might be a result of power failures.
  29. * - allocateAndWrite() - Bug fix - sector count might be incorrectly updated in case folding found a sector with bad EDC.
  30. * - mountNFTL -
  31. * 1) Moved badFormat initialization to the end of the routine so that getUnitData() might know if it was called by mount routine.
  32. * 2) Made sure there is at least 1 free unit.
  33. * 3) Fold chains with invalid pointer in their end of chain - caused by power failures.
  34. * - Added MAKE_SURE_IGNORE_HAS_BAD_EDC compilation flag - make sure that the sector is really marked
  35. * - verifySector() - was completely revised.
  36. *
  37. * Rev 1.26 Feb 19 2002 21:00:56 oris
  38. * Compilation errors - NO_READ_BBT_CODE
  39. * Removed warnings.
  40. * Replaced TL_LEAVE_BINARY_AREA with FL_LEAVE_BINARY_AREA
  41. *
  42. * Rev 1.25 Jan 29 2002 20:09:58 oris
  43. * Bug fix - if an invalid sector flag is found in getSectorFlags routine and read operation failed, SECTOR_IGNORED should have been returned.
  44. *
  45. * Rev 1.24 Jan 23 2002 23:33:56 oris
  46. * Improved markAsIgnored routine.
  47. * Changed DFORMAT_PRINT syntax.
  48. *
  49. * Rev 1.23 Jan 20 2002 20:29:26 oris
  50. * Remove warnings
  51. * Bug fix - Missing cache buffers allocation check in formatUnit.
  52. *
  53. * Rev 1.22 Jan 17 2002 23:04:22 oris
  54. * Added onesCount routine - number of bits in a byte.
  55. * Improved FL_READ_ONLY compilation mode.
  56. * Flash field of the TL was changed to a pointer.
  57. * Added check verifyVolume routine to issue a longer, but safer mount.
  58. * Moved RAM tables to far heap to allow BIOS driver to allocate far memory heap even when compiled as tiny model:
  59. * - InitTables : allocation was change from FL_MALLOC to FL_FAR_MALLOC.
  60. * - mountUnit : changes pointer to virtual table to be FAR.
  61. * - mountNFTL :
  62. * - changes pointer to virtual table to be FAR.
  63. * - allocation of cache tables was change from FL_MALLOC to FL_FAR_MALLOC.
  64. * - dismount : use FL_FAR_FREE instead of FL_FREE
  65. * formatUnit routine improved re-initialization of sector cache.
  66. * Changed flPolicy to be socket specific.
  67. * Added \r to all DEBUG_PRINT.
  68. * writeSector routine if this sector is the cached sector then force re-mapping.
  69. * Bug fix in formatNFTL :
  70. * - Add binary length to percentage of bad blocks.
  71. * - Report error if there is not enough good blocks.
  72. * - Report error if block 0 is bad.
  73. * New power failures protection algorithm
  74. * - setUnitData : When verify write is on , no need to reread unit data
  75. * - getSectorFlags : if flags is not valid (including SECTOR_IGNORE) check EDC and bit distance instead of simple or.
  76. * - virtual2Physical : Added endAddress parameter to allow retrieval of not the newest sector.
  77. * - writeAndCheck :
  78. * - Toggle socket verify write mode according to global verify write mode.
  79. * - Moved the marking of the sector as bad into a dedicated routine (markAsIgnored)
  80. * - initNftl :
  81. * - Init FLFlash pointer (and not structure)
  82. * - Init socket number of the TL
  83. * - Init verifiedSectorNo for FL_OFF verify write mode
  84. * - swapUnits : Catch failed folding operation
  85. * - Moved copySector routine into foldUnit.
  86. * - Changed chain bound for all chains "for loops" to the constant DOUBLE_MAX_UNIT_CHAIN (support MAX_UNIT_CHAIN of 1 in case of folding not in place).
  87. * - foldUnit :
  88. * - When verify write is set to FL_OFF call verifySectors routine to gradually scan the entire media
  89. * - Force re-mapping of cached sector
  90. * - Add force folding parameter
  91. * - Toggle socket verify write mode according to verify write mode and currently scanned sector number
  92. * - Verify copied sector EDC even for last sector of chain (no need to copy it) and if bad freeze chain and return flCanNotFold (unless forced folding is issued)
  93. * - In case of bad EDC use older sector.
  94. * - In case write operation failed (could be partially written sector that was discovered by verify write mode) freeze chain and return flCanNotFold (unless forced folding is issued)
  95. * - foldBestChain : if folding of the chosen unit failed, freeze and try another unit MAX_FOLDING_TRIES times.
  96. * - allocateUnit : free media space even if there is a free unit available
  97. * - mapSector : if sector has bad EDC read older sector until no sectors were found or chain bound has been reached
  98. * - allocateAndWriteSector :
  99. * - Catch failed folding operation.
  100. * - Set curSectorWrite to current sector so that writeAndCheck routine will be able to decide whether to verify this sector or not while in FL_OFF verify mode.
  101. * - deleteSectors : Catch failed folding operation.
  102. * - mountNFTL :
  103. * - Set default verify write policy to FL_UPS.
  104. * - Set checkVolme routine pointer.
  105. * - Added checkVolume / checkFolding / verifySectors and markAsIgnored routines.
  106. *
  107. * Rev 1.21 Nov 21 2001 11:38:04 oris
  108. * Changed FL_MARK_DELETE to FL_ON.
  109. *
  110. * Rev 1.20 15 Nov 2001 16:28:24 dimitrys
  111. * Fix Big BDK partition with Bad Units problem in formatNFTL()
  112. *
  113. * Rev 1.19 Sep 25 2001 15:39:58 oris
  114. * Removed warnings.
  115. *
  116. * Rev 1.18 Jul 29 2001 18:48:50 oris
  117. * Bug fix - unit 0 of floors > 0 were not marked as bad blocks therefore future write operation might force the device into external eprom mode.
  118. *
  119. * Rev 1.17 Jul 15 2001 20:45:26 oris
  120. * Changed DFORMAT_PRINT syntax to be similar to DEBUG_PRINT.
  121. *
  122. * Rev 1.16 Jul 13 2001 01:08:38 oris
  123. * Removed EDC for media header.
  124. * Added dformat debug print for virgin media.
  125. *
  126. * Rev 1.15 Jun 17 2001 16:39:12 oris
  127. * Improved documentation and remove warnings.
  128. *
  129. * Rev 1.14 Jun 17 2001 08:17:34 oris
  130. * Removed warnings.
  131. * Changed erase routine to formatUnit.
  132. * Bug fix - original meida header was not written.
  133. * Added NO_READ_BBT_CODE compilation flag to reduce code size.
  134. *
  135. * Rev 1.13 May 29 2001 23:12:28 oris
  136. * Added EDC check of the media header both in the mount and format routines.
  137. *
  138. * Rev 1.12 May 16 2001 21:21:26 oris
  139. * Added EDC check for media header.
  140. * Added the FL_ prefix to the following defines: ON , OFF, MALLOC and FREE.
  141. * Changed wear level counter from 0xFF to 0xFFF0
  142. *
  143. * Rev 1.11 May 06 2001 22:42:26 oris
  144. * Removed warnings.
  145. *
  146. * Rev 1.10 May 01 2001 16:33:46 oris
  147. * Bug fix - readBBT routine returned used blocks as bad.
  148. *
  149. * Rev 1.9 Apr 30 2001 18:03:30 oris
  150. * Bug fix - marking binary partition blocks of devices that use artifitial large erase blocks (units).
  151. * Added support for the flMarkDeleteOnFlash environment variable.
  152. *
  153. * Rev 1.8 Apr 24 2001 17:10:14 oris
  154. * Bug fix - readBBT routine missing casting.
  155. *
  156. * Rev 1.7 Apr 16 2001 13:56:46 oris
  157. * Removed warrnings.
  158. *
  159. * Rev 1.6 Apr 09 2001 15:04:42 oris
  160. * End with an empty line.
  161. *
  162. * Rev 1.5 Apr 01 2001 07:55:42 oris
  163. * copywrite notice.
  164. * changed SEPERATED to SEPARATED.
  165. * Changed SEPARATED_CASCADED ifdef to a runtime if.
  166. *
  167. * Rev 1.3 Feb 14 2001 02:03:38 oris
  168. * Changed readBBT to return media size.
  169. *
  170. * Rev 1.2 Feb 12 2001 12:10:56 oris
  171. * Moved SEPARATED cascaded to include more uneeded code.
  172. * Rewritten readBBT to support far pointers.
  173. *
  174. * Rev 1.1 Feb 07 2001 17:46:26 oris
  175. * Added SEPARATED_CASCADED compilation flag
  176. *
  177. * Rev 1.0 Feb 05 2001 12:24:18 oris
  178. * Initial revision.
  179. *
  180. */
  181. /***********************************************************************************/
  182. /* M-Systems Confidential */
  183. /* Copyright (C) M-Systems Flash Disk Pioneers Ltd. 1995-2001 */
  184. /* All Rights Reserved */
  185. /***********************************************************************************/
  186. /* NOTICE OF M-SYSTEMS OEM */
  187. /* SOFTWARE LICENSE AGREEMENT */
  188. /* */
  189. /* THE USE OF THIS SOFTWARE IS GOVERNED BY A SEPARATE LICENSE */
  190. /* AGREEMENT BETWEEN THE OEM AND M-SYSTEMS. REFER TO THAT AGREEMENT */
  191. /* FOR THE SPECIFIC TERMS AND CONDITIONS OF USE, */
  192. /* OR CONTACT M-SYSTEMS FOR LICENSE ASSISTANCE: */
  193. /* E-MAIL = [email protected] */
  194. /***********************************************************************************/
  195. #include "nftllite.h"
  196. #include "nanddefs.h"
  197. #ifndef FL_READ_ONLY
  198. #if (defined(VERIFY_WRITE) || defined (VERIFY_VOLUME) || defined(VERIFY_ERASED_SECTOR))
  199. static FLStatus checkVolume(Anand vol);
  200. static FLStatus verifySectors(Anand vol, dword sectorCount);
  201. #endif /* VERIFY_WRITE || VERIFY_VOLUME || VERIFY_ERASED_SECTOR */
  202. static void markAsIgnored(Anand vol,CardAddress addr);
  203. static FLStatus foldBestChain(Anand vol, ANANDUnitNo *unitNo);
  204. static FLStatus foldUnit(Anand vol, ANANDUnitNo virtualUnitNo, FLBoolean);
  205. static FLStatus checkFolding(Anand vol, ANANDUnitNo virtualUnitNo);
  206. static FLStatus allocateUnit(Anand vol, ANANDUnitNo *);
  207. #endif /* FL_READ_ONLY */
  208. static Anand vols[VOLUMES];
  209. #ifdef NFTL_CACHE
  210. /* translation table for Sector Flags cache */
  211. static unsigned char scacheTable[4] = { SECTOR_DELETED, /* 0 */
  212. SECTOR_IGNORE, /* 1 */
  213. SECTOR_USED, /* 2 */
  214. SECTOR_FREE }; /* 3 */
  215. #endif /* NFTL_CACHE */
  216. #ifdef FORMAT_VOLUME
  217. byte ff[ANAND_SPARE_SIZE];
  218. #endif /* FORMAT_VOLUME */
  219. /*------------------------------------------------------*/
  220. /* o n e s C o u n t */
  221. /* */
  222. /* counts number of bits that valued 1 in a given byte */
  223. /*------------------------------------------------------*/
  224. static byte onesCount(byte flag)
  225. {
  226. byte counter;
  227. for (counter = 0; flag; flag >>= 1)
  228. if (flag & 1)
  229. counter++;
  230. return counter;
  231. }
  232. /*----------------------------------------------------------------------*/
  233. /* u n i t B a s e A d d r e s s */
  234. /* */
  235. /* Returns the physical address of a unit. */
  236. /* */
  237. /* Parameters: */
  238. /* vol : Pointer identifying drive */
  239. /* unitNo : Physical unit number */
  240. /* */
  241. /* Returns: */
  242. /* physical address of unitNo */
  243. /*----------------------------------------------------------------------*/
  244. static CardAddress unitBaseAddress(Anand vol, ANANDUnitNo unitNo)
  245. {
  246. return (CardAddress)unitNo << vol.unitSizeBits;
  247. }
  248. /*----------------------------------------------------------------------*/
  249. /* g e t U n i t D a t a */
  250. /* */
  251. /* Get virtual unit No. and replacement unit no. of a unit. */
  252. /* */
  253. /* Parameters: */
  254. /* vol : Pointer identifying drive */
  255. /* unitNo : Physical unit number */
  256. /* virtualUnitNo : Receives the virtual unit no. */
  257. /* replacementUnitNo : Receives the replacement unit no. */
  258. /* */
  259. /*----------------------------------------------------------------------*/
  260. static void getUnitData(Anand vol,
  261. ANANDUnitNo unitNo,
  262. ANANDUnitNo *virtualUnitNo,
  263. ANANDUnitNo *replacementUnitNo)
  264. {
  265. ANANDUnitHeader unitData;
  266. #ifdef NFTL_CACHE
  267. /* check ANANDUnitHeader cache first */
  268. if (vol.ucache != NULL) {
  269. /* on cache miss read ANANDUnitHeader from flash and re-fill cache */
  270. if((vol.ucache[unitNo].virtualUnitNo == 0xDEAD) &&
  271. (vol.ucache[unitNo].replacementUnitNo == 0xDEAD)) {
  272. vol.flash->read(vol.flash,
  273. unitBaseAddress(&vol,unitNo) + UNIT_DATA_OFFSET,
  274. &unitData,
  275. sizeof(ANANDUnitHeader),
  276. EXTRA);
  277. vol.ucache[unitNo].virtualUnitNo =
  278. LE2(unitData.virtualUnitNo) | LE2(unitData.spareVirtualUnitNo);
  279. vol.ucache[unitNo].replacementUnitNo =
  280. LE2(unitData.replacementUnitNo) | LE2(unitData.spareReplacementUnitNo);
  281. }
  282. *virtualUnitNo = vol.ucache[unitNo].virtualUnitNo;
  283. *replacementUnitNo = vol.ucache[unitNo].replacementUnitNo;
  284. }
  285. else
  286. #endif /* NFTL_CACHE */
  287. { /* no ANANDUnitHeader cache */
  288. vol.flash->read(vol.flash,
  289. unitBaseAddress(&vol,unitNo) + UNIT_DATA_OFFSET,
  290. &unitData,
  291. sizeof(ANANDUnitHeader),
  292. EXTRA);
  293. /* Mask out any 1 -> 0 bit faults by or'ing with spare data */
  294. *virtualUnitNo = LE2(unitData.virtualUnitNo) |
  295. LE2(unitData.spareVirtualUnitNo);
  296. *replacementUnitNo = LE2(unitData.replacementUnitNo) |
  297. LE2(unitData.spareReplacementUnitNo);
  298. }
  299. if( !isLegalUnit(*replacementUnitNo) ) {
  300. vol.invalidReplacement = unitNo;
  301. if(vol.badFormat == FALSE) /* Not called by mount operation */
  302. {
  303. ANANDUnitNo firstUnits = vol.virtualUnits[*virtualUnitNo];
  304. if(firstUnits != ANAND_NO_UNIT)
  305. setUnavail(firstUnits & (~ANAND_REPLACING_UNIT)); /* freeze unit chain */
  306. }
  307. *replacementUnitNo = ANAND_NO_UNIT;
  308. }
  309. }
  310. #ifndef FL_READ_ONLY
  311. /*----------------------------------------------------------------------*/
  312. /* s e t U n i t D a t a */
  313. /* */
  314. /* Set virtual unit No. and replacement unit no. of a unit. */
  315. /* */
  316. /* Parameters: */
  317. /* vol : Pointer identifying drive */
  318. /* unitNo : Physical unit number */
  319. /* virtualUnitNo : Virtual unit no. */
  320. /* replacementUnitNo : Replacement unit no. */
  321. /* */
  322. /* Returns: */
  323. /* FLStatus : 0 on success, failed otherwise */
  324. /* */
  325. /*----------------------------------------------------------------------*/
  326. static FLStatus setUnitData(Anand vol,
  327. ANANDUnitNo unitNo,
  328. ANANDUnitNo virtualUnitNo,
  329. ANANDUnitNo replacementUnitNo)
  330. {
  331. ANANDUnitHeader unitData;
  332. ANANDUnitNo newVirtualUnitNo, newReplacementUnitNo;
  333. if( replacementUnitNo == unitNo ) /* prevent chain loop */
  334. return flGeneralFailure;
  335. toLE2(unitData.virtualUnitNo,virtualUnitNo);
  336. toLE2(unitData.spareVirtualUnitNo,virtualUnitNo);
  337. toLE2(unitData.replacementUnitNo,replacementUnitNo);
  338. toLE2(unitData.spareReplacementUnitNo,replacementUnitNo);
  339. checkStatus(vol.flash->write(vol.flash,
  340. unitBaseAddress(&vol,unitNo) + UNIT_DATA_OFFSET,
  341. &unitData,
  342. sizeof(ANANDUnitHeader),
  343. EXTRA));
  344. #ifdef VERIFY_WRITE
  345. if (vol.flash->socket->verifyWrite==FL_ON)
  346. {
  347. #ifdef NFTL_CACHE
  348. /* Set new entries for ANANDUnitHeader cache */
  349. if (vol.ucache != NULL) {
  350. vol.ucache[unitNo].virtualUnitNo = virtualUnitNo;
  351. vol.ucache[unitNo].replacementUnitNo = replacementUnitNo;
  352. }
  353. #endif /* NFTL_CACHE */
  354. return flOK;
  355. }
  356. #endif /* VERIFY_WRITE */
  357. #ifdef NFTL_CACHE
  358. /* purge ANANDUnitHeader cache to force re-filling from flash */
  359. if (vol.ucache != NULL) {
  360. vol.ucache[unitNo].virtualUnitNo = 0xDEAD;
  361. vol.ucache[unitNo].replacementUnitNo = 0xDEAD;
  362. }
  363. #endif /* NFTL_CACHE */
  364. /* Verify the new unit data */
  365. getUnitData(&vol,unitNo,&newVirtualUnitNo, &newReplacementUnitNo);
  366. if (virtualUnitNo != newVirtualUnitNo ||
  367. replacementUnitNo != newReplacementUnitNo)
  368. return flWriteFault;
  369. else
  370. return flOK;
  371. }
  372. #endif /* FL_READ_ONLY */
  373. /*----------------------------------------------------------------------*/
  374. /* g e t N e x t U n i t */
  375. /* */
  376. /* Get next unit in chain. */
  377. /* */
  378. /* Parameters: */
  379. /* vol : Pointer identifying drive */
  380. /* unitNo : Physical unit number */
  381. /* virUnitNo : Virtual unit number of the chain. */
  382. /* */
  383. /* Returns: */
  384. /* Physical unit number of the unit following unitNo in the chain. */
  385. /* If such unit do not exist, return ANAND_NO_UNIT. */
  386. /*----------------------------------------------------------------------*/
  387. static ANANDUnitNo getNextUnit(Anand vol, ANANDUnitNo unitNo, ANANDUnitNo virUnitNo)
  388. {
  389. ANANDUnitNo virtualUnitNo, replacementUnitNo;
  390. if (!(vol.physicalUnits[unitNo] & UNIT_REPLACED))
  391. return ANAND_NO_UNIT;
  392. getUnitData(&vol,unitNo,&virtualUnitNo,&replacementUnitNo);
  393. if( virUnitNo != (virtualUnitNo & ~ANAND_REPLACING_UNIT) ) {
  394. unitNo = vol.virtualUnits[virUnitNo];
  395. setUnavail(unitNo); /* freeze unit chain */
  396. return ANAND_NO_UNIT;
  397. }
  398. return replacementUnitNo;
  399. }
  400. #ifdef NFTL_CACHE
  401. /*----------------------------------------------------------------------*/
  402. /* g e t S e c t o r F l a g s F r o m C a c h e */
  403. /* */
  404. /* Get sector flags from Sector Cache. */
  405. /* */
  406. /* Parameters: */
  407. /* vol : Pointer identifying drive */
  408. /* address : starting address of the sector */
  409. /* */
  410. /* Returns: */
  411. /* sector flags (SECTOR_USED, SECTOR_DELETED etc.) */
  412. /*----------------------------------------------------------------------*/
  413. static unsigned char getSectorFlagsFromCache(Anand vol, CardAddress address)
  414. {
  415. return scacheTable[(vol.scache[address >> (SECTOR_SIZE_BITS+2)] >>
  416. (((unsigned int)address >> 8) & 0x7)) & 0x3];
  417. }
  418. /*----------------------------------------------------------------------*/
  419. /* s e t S e c t o r F l a g s C a c h e */
  420. /* */
  421. /* Get sector flags from Sector Cache. */
  422. /* */
  423. /* Parameters: */
  424. /* vol : Pointer identifying drive */
  425. /* address : starting address of the sector */
  426. /* sectorFlags : one of SECTOR_USED, SECTOR_DELETED etc. */
  427. /* */
  428. /*----------------------------------------------------------------------*/
  429. static void setSectorFlagsCache(Anand vol, CardAddress address,
  430. unsigned char sectorFlags)
  431. {
  432. register unsigned char tmp, val;
  433. if (vol.scache == NULL)
  434. return;
  435. tmp = vol.scache[address >> (SECTOR_SIZE_BITS+2)];
  436. switch(sectorFlags) {
  437. case SECTOR_USED: val = S_CACHE_SECTOR_USED; break;
  438. case SECTOR_FREE: val = S_CACHE_SECTOR_FREE; break;
  439. case SECTOR_DELETED: val = S_CACHE_SECTOR_DELETED; break;
  440. default:/* SECTOR_IGNORE */val = S_CACHE_SECTOR_IGNORE; break;
  441. }
  442. switch (((unsigned int)address >> 8) & 0x7) {
  443. case 0: tmp = (tmp & 0xfc) | (val ); break; /* update bits 0..1 */
  444. case 2: tmp = (tmp & 0xf3) | (val << 2); break; /* bits 2..3 */
  445. case 4: tmp = (tmp & 0xcf) | (val << 4); break; /* bits 4..5 */
  446. case 6: tmp = (tmp & 0x3f) | (val << 6); break; /* bits 6..7 */
  447. }
  448. vol.scache[address >> (SECTOR_SIZE_BITS+2)] = tmp;
  449. }
  450. #endif /* NFTL_CACHE */
  451. /*----------------------------------------------------------------------*/
  452. /* g e t S e c t o r F l a g s */
  453. /* */
  454. /* Get sector status. */
  455. /* */
  456. /* Parameters: */
  457. /* vol : Pointer identifying drive */
  458. /* sectorAddress : Physical address of the sector */
  459. /* */
  460. /* Returns: */
  461. /* Return the OR of the two bytes in the sector status area (the */
  462. /* bytes should contain the same data). */
  463. /*----------------------------------------------------------------------*/
  464. static unsigned char getSectorFlags(Anand vol, CardAddress sectorAddress)
  465. {
  466. byte flags[2];
  467. byte blockFlag = SECTOR_IGNORE;
  468. byte index,tmpSector;
  469. FLStatus status;
  470. #ifdef NFTL_CACHE
  471. if (vol.scache != NULL) { /* check for Sector Flags cache hit */
  472. blockFlag = getSectorFlagsFromCache(&vol, sectorAddress);
  473. if (blockFlag != SECTOR_IGNORE)
  474. return blockFlag;
  475. }
  476. #endif /* NFTL_CACHE */
  477. vol.flash->read(vol.flash, sectorAddress + SECTOR_DATA_OFFSET,
  478. flags, sizeof flags, EXTRA);
  479. if((flags[0] == flags[1]) && (isValidSectorFlag(flags[0])))
  480. {
  481. blockFlag = flags[0];
  482. }
  483. else /* Sector flags that were read are not legal */
  484. {
  485. /* Force remapping of internal catched sector */
  486. vol.flash->socket->remapped = TRUE;
  487. /* Check for ignored sector using the EDC */
  488. status = vol.flash->read(vol.flash, sectorAddress,
  489. nftlBuffer, SECTOR_SIZE, EDC);
  490. if(status == flOK)
  491. {
  492. /* Check if distance is less then 2 bits failure since */
  493. /* 2 bits failure can be either delete or used */
  494. for (index=0 , tmpSector = (byte)SECTOR_USED ; index < 2 ;
  495. index++ , tmpSector = (byte)SECTOR_DELETED)
  496. {
  497. if (distanceOf(flags[0], tmpSector) +
  498. distanceOf(flags[1], tmpSector) <= 2)
  499. {
  500. blockFlag = tmpSector;
  501. break;
  502. }
  503. }
  504. if(index>=2)
  505. return SECTOR_IGNORE;
  506. }
  507. else
  508. {
  509. return SECTOR_IGNORE;
  510. }
  511. }
  512. #ifdef NFTL_CACHE
  513. /* update Sector Flags cache */
  514. setSectorFlagsCache(&vol, sectorAddress, blockFlag);
  515. #endif /* NFTL_CACHE */
  516. return blockFlag;
  517. }
  518. /*----------------------------------------------------------------------*/
  519. /* f i n d E n d O f E n d l e s s C h a i n */
  520. /* */
  521. /* Find end of endless chain - last unit of unit chain that points to */
  522. /* itself. */
  523. /* */
  524. /* Parameters: */
  525. /* vol : Pointer identifying drive */
  526. /* virUnitNo : Virtual unit number */
  527. /* */
  528. /* Returns: */
  529. /* Physical unit number of oldest unit of the chain */
  530. /*----------------------------------------------------------------------*/
  531. static ANANDUnitNo findEndOfEndlessChain(Anand vol, ANANDUnitNo virUnitNo)
  532. {
  533. ANANDUnitNo chainsUnit[DOUBLE_MAX_UNIT_CHAIN/2+2];
  534. ANANDUnitNo unitNo;
  535. int i;
  536. int chainBound;
  537. for (unitNo = vol.virtualUnits[virUnitNo] , chainBound = 0 ;
  538. chainBound < MAX_UNIT_CHAIN ;
  539. unitNo = getNextUnit(&vol,unitNo,virUnitNo) , chainBound++)
  540. {
  541. chainsUnit[chainBound] = unitNo; /* Save location of current unit */
  542. for(i = 0 ; i < chainBound ; i++) /* Check if already been to this unit */
  543. {
  544. if(chainsUnit[chainBound] == unitNo) /* Bad next unit number pointer */
  545. break;
  546. }
  547. }
  548. return chainsUnit[chainBound-1];
  549. }
  550. /*----------------------------------------------------------------------*/
  551. /* v i r t u a l 2 P h y s i c a l */
  552. /* */
  553. /* Translate virtual sector number to physical address. */
  554. /* */
  555. /* Parameters: */
  556. /* vol : Pointer identifying drive */
  557. /* sectorNo : Virtual sector number */
  558. /* endAddress : End address for sector search. NULL for no end */
  559. /* */
  560. /* Returns: */
  561. /* endAddress : Next free sector address */
  562. /* physical address of sectorNo */
  563. /*----------------------------------------------------------------------*/
  564. static CardAddress virtual2Physical(Anand vol, SectorNo sectorNo , CardAddress* endAddress)
  565. {
  566. unsigned unitOffset = (unsigned)((sectorNo % vol.sectorsPerUnit) << SECTOR_SIZE_BITS);
  567. CardAddress prevSectorAddress = ANAND_UNASSIGNED_ADDRESS;
  568. CardAddress sectorAddress;
  569. CardAddress *freeSectorAddressPtr;
  570. ANANDUnitNo unitNo, virUnitNo;
  571. ANANDUnitNo chainBound = 0;
  572. ANANDUnitNo endUnit;
  573. byte sectorFlags;
  574. FLBoolean badPointerFound = FALSE;
  575. /* Set end unit and nextFreeSectorAddress */
  576. if(endAddress == NULL)
  577. {
  578. endUnit = ANAND_NO_UNIT;
  579. }
  580. else
  581. {
  582. endUnit = (ANANDUnitNo)(*endAddress>>vol.unitSizeBits);
  583. *endAddress = ANAND_UNASSIGNED_ADDRESS;
  584. }
  585. /* follow the chain */
  586. virUnitNo = (ANANDUnitNo)(sectorNo / vol.sectorsPerUnit);
  587. for (unitNo = vol.virtualUnits[virUnitNo];
  588. ( (unitNo != endUnit) && (chainBound < DOUBLE_MAX_UNIT_CHAIN) );
  589. unitNo = getNextUnit(&vol,unitNo,virUnitNo))
  590. {
  591. sectorAddress = unitBaseAddress(&vol,unitNo) + unitOffset;
  592. sectorFlags = getSectorFlags(&vol,sectorAddress);
  593. if (sectorFlags == SECTOR_FREE)
  594. {
  595. if(endAddress != NULL)
  596. *endAddress = sectorAddress;
  597. break;
  598. }
  599. if (sectorFlags != SECTOR_IGNORE)
  600. prevSectorAddress = sectorFlags != SECTOR_DELETED ? sectorAddress :
  601. ANAND_UNASSIGNED_ADDRESS;
  602. chainBound++;
  603. }
  604. if(chainBound < DOUBLE_MAX_UNIT_CHAIN)
  605. return prevSectorAddress;
  606. /* Infint loop caused by power failure */
  607. if(endAddress == NULL)
  608. {
  609. freeSectorAddressPtr = &sectorAddress;
  610. }
  611. else
  612. {
  613. freeSectorAddressPtr = endAddress;
  614. }
  615. *freeSectorAddressPtr = unitOffset +
  616. unitBaseAddress(&vol,
  617. findEndOfEndlessChain(&vol,virUnitNo));
  618. return virtual2Physical(&vol, sectorNo , freeSectorAddressPtr);
  619. }
  620. /*----------------------------------------------------------------------*/
  621. /* g e t F o l d M a r k */
  622. /* */
  623. /* Get the fold mark a unit. */
  624. /* */
  625. /* Parameters: */
  626. /* vol : Pointer identifying drive */
  627. /* unitNo : Physical unit number */
  628. /* */
  629. /* Returns: */
  630. /* Return the OR of the two words in the fold mark area (the words */
  631. /* should be identical) */
  632. /*----------------------------------------------------------------------*/
  633. static unsigned short getFoldMark(Anand vol, ANANDUnitNo unitNo)
  634. {
  635. unsigned short foldMark[2];
  636. vol.flash->read(vol.flash,
  637. unitBaseAddress(&vol,unitNo) + FOLD_MARK_OFFSET,
  638. foldMark, sizeof foldMark,
  639. EXTRA);
  640. return foldMark[0] | foldMark[1];
  641. }
  642. /*----------------------------------------------------------------------*/
  643. /* g e t U n i t T a i l e r */
  644. /* */
  645. /* Get the erase record of a unit. */
  646. /* */
  647. /* Parameters: */
  648. /* vol : Pointer identifying drive */
  649. /* unitNo : Physical unit number */
  650. /* eraseMark : Receives the erase mark of the unit */
  651. /* eraseCount : Receives the erase count of the unit */
  652. /* */
  653. /*----------------------------------------------------------------------*/
  654. static void getUnitTailer(Anand vol,
  655. ANANDUnitNo unitNo,
  656. unsigned short *eraseMark,
  657. unsigned long *eraseCount)
  658. {
  659. UnitTailer unitTailer;
  660. vol.flash->read(vol.flash,
  661. unitBaseAddress(&vol,unitNo) + UNIT_TAILER_OFFSET,
  662. &unitTailer,
  663. sizeof(UnitTailer),
  664. EXTRA);
  665. /* Mask out any 1 -> 0 bit faults by or'ing with spare data */
  666. *eraseMark = LE2(unitTailer.eraseMark) | LE2(unitTailer.eraseMark1);
  667. *eraseCount = LE4(unitTailer.eraseCount);
  668. }
  669. /*----------------------------------------------------------------------*/
  670. /* s e t U n i t T a i l e r */
  671. /* */
  672. /* Set the erase record of a unit. */
  673. /* */
  674. /* Parameters: */
  675. /* vol : Pointer identifying drive */
  676. /* unitNo : Physical unit number */
  677. /* eraseMark : Erase mark to set */
  678. /* eraseCount : Erase count to set */
  679. /* */
  680. /*----------------------------------------------------------------------*/
  681. static FLStatus setUnitTailer(Anand vol,
  682. ANANDUnitNo unitNo,
  683. unsigned short eraseMark,
  684. unsigned long eraseCount)
  685. {
  686. UnitTailer unitTailer;
  687. toLE2(unitTailer.eraseMark,eraseMark);
  688. toLE2(unitTailer.eraseMark1,eraseMark);
  689. toLE4(unitTailer.eraseCount,eraseCount);
  690. return vol.flash->write(vol.flash,
  691. unitBaseAddress(&vol,unitNo) + UNIT_TAILER_OFFSET,
  692. &unitTailer,
  693. sizeof(UnitTailer),
  694. EXTRA);
  695. }
  696. /*----------------------------------------------------------------------*/
  697. /* i n i t N F T L */
  698. /* */
  699. /* Initializes essential volume data as a preparation for mount or */
  700. /* format. */
  701. /* */
  702. /* Parameters: */
  703. /* vol : Pointer identifying drive */
  704. /* flash : Flash media mounted on this socket */
  705. /* */
  706. /* Returns: */
  707. /* FLStatus : 0 on success, failed otherwise */
  708. /*----------------------------------------------------------------------*/
  709. static FLStatus initNFTL(Anand vol, FLFlash *flash)
  710. {
  711. dword size = 1;
  712. if (flash == NULL || !(flash->flags & NFTL_ENABLED)) {
  713. DEBUG_PRINT(("Debug: media is not fit for NFTL format.\r\n"));
  714. return flUnknownMedia;
  715. }
  716. vol.flash = flash;
  717. #ifdef NT5PORT
  718. vol.socketNo = (byte)(flSocketNoOf(vol.flash->socket));
  719. #else
  720. vol.socketNo = flSocketNoOf(vol.flash->socket);
  721. #endif NT5PORT
  722. vol.physicalUnits = NULL;
  723. vol.virtualUnits = NULL;
  724. #ifdef NFTL_CACHE
  725. vol.ucache = NULL;
  726. vol.scache = NULL;
  727. #endif
  728. for (vol.erasableBlockSizeBits = 0; size < vol.flash->erasableBlockSize;
  729. vol.erasableBlockSizeBits++, size <<= 1);
  730. vol.unitSizeBits = vol.erasableBlockSizeBits;
  731. vol.noOfUnits = (unsigned short)((vol.flash->noOfChips * vol.flash->chipSize) >> vol.unitSizeBits);
  732. /* Adjust unit size so header unit fits in one unit */
  733. while (vol.noOfUnits * sizeof(ANANDPhysUnit) + SECTOR_SIZE > (1UL << vol.unitSizeBits)) {
  734. vol.unitSizeBits++;
  735. vol.noOfUnits >>= 1;
  736. }
  737. /* Bound number of units to find room in 64 Kbytes Segment */
  738. if( (vol.noOfUnits >= MAX_UNIT_NUM) && (vol.unitSizeBits < MAX_UNIT_SIZE_BITS) ) {
  739. vol.unitSizeBits++;
  740. vol.noOfUnits >>= 1;
  741. }
  742. vol.badFormat = TRUE; /* until mount completes*/
  743. vol.mappedSectorNo = UNASSIGNED_SECTOR;
  744. vol.countsValid = 0; /* No units have a valid count yet */
  745. /*get pointer to buffer (we assume SINGLE_BUFFER is not defined) */
  746. vol.buffer = flBufferOf(flSocketNoOf(vol.flash->socket));
  747. #ifdef VERIFY_ERASED_SECTOR
  748. vol.verifyBuffer = (dword *)flReadBackBufferOf(flSocketNoOf(flash->socket));
  749. #endif /* VERIFY_ERASED_SECTOR */
  750. #if (defined(VERIFY_WRITE) || defined(VERIFY_VOLUME) || defined(VERIFY_ERASED_SECTOR))
  751. vol.verifiedSectorNo = 0; /* Largest sector verified so far */
  752. #endif /* VERIFY_WRITE || VERIFY_VOLUME || VERIFY_ERASED_SECTOR */
  753. vol.invalidReplacement = ANAND_NO_UNIT; /* a unit with bad RUN */
  754. return flOK;
  755. }
  756. /*----------------------------------------------------------------------*/
  757. /* i n i t T a b l e s */
  758. /* */
  759. /* Allocates and initializes the dynamic volume table, including the */
  760. /* unit tables and secondary virtual map. */
  761. /* */
  762. /* Parameters: */
  763. /* vol : Pointer identifying drive */
  764. /* */
  765. /* Returns: */
  766. /* FLStatus : 0 on success, failed otherwise */
  767. /*----------------------------------------------------------------------*/
  768. static FLStatus initTables(Anand vol)
  769. {
  770. /* Allocate the conversion tables */
  771. #ifdef FL_MALLOC
  772. vol.physicalUnits = (ANANDPhysUnit FAR1*) FL_FAR_MALLOC (vol.noOfUnits * sizeof(ANANDPhysUnit));
  773. vol.virtualUnits = (ANANDUnitNo FAR1*) FL_FAR_MALLOC (vol.noOfVirtualUnits * sizeof(ANANDUnitNo));
  774. if (vol.physicalUnits == NULL ||
  775. vol.virtualUnits == NULL) {
  776. DEBUG_PRINT(("Debug: failed allocating conversion tables for NFTL.\r\n"));
  777. return flNotEnoughMemory;
  778. }
  779. #else
  780. char *heapPtr;
  781. heapPtr = vol.heap;
  782. vol.physicalUnits = (ANANDPhysUnit *) heapPtr;
  783. heapPtr += vol.noOfUnits * sizeof(ANANDPhysUnit);
  784. vol.virtualUnits = (ANANDUnitNo *) heapPtr;
  785. heapPtr += vol.noOfVirtualUnits * sizeof(ANANDUnitNo);
  786. if (heapPtr > vol.heap + sizeof vol.heap) {
  787. DEBUG_PRINT(("Debug: not enough memory for NFTL conversion tables.\r\n"));
  788. return flNotEnoughMemory;
  789. }
  790. #endif
  791. return flOK;
  792. }
  793. /*----------------------------------------------------------------------*/
  794. /* m a r k U n i t B a d */
  795. /* */
  796. /* Mark a unit as bad in the conversion table and the bad units table. */
  797. /* */
  798. /* Parameters: */
  799. /* vol : Pointer identifying drive */
  800. /* unitNo : Physical number of bad unit */
  801. /* */
  802. /* Returns: */
  803. /* FLStatus : 0 on success, failed otherwise */
  804. /*----------------------------------------------------------------------*/
  805. static FLStatus markUnitBad(Anand vol, ANANDUnitNo unitNo)
  806. {
  807. unsigned short eraseMark;
  808. unsigned long eraseCount;
  809. vol.physicalUnits[unitNo] = UNIT_BAD_MOUNT;
  810. getUnitTailer(&vol,unitNo,&eraseMark,&eraseCount);
  811. return setUnitTailer(&vol,unitNo,0,eraseCount);
  812. }
  813. /*----------------------------------------------------------------------*/
  814. /* f o r m a t U n i t */
  815. /* */
  816. /* Format one unit. Erase the unit, and mark the physical units table. */
  817. /* */
  818. /* Parameters: */
  819. /* vol : Pointer identifying drive */
  820. /* unitNo : Unit to format */
  821. /* */
  822. /* Returns: */
  823. /* FLStatus : 0 on success, failed otherwise */
  824. /*----------------------------------------------------------------------*/
  825. static FLStatus formatUnit(Anand vol, ANANDUnitNo unitNo)
  826. {
  827. unsigned short eraseMark;
  828. unsigned long eraseCount;
  829. FLStatus status;
  830. if (!isAvailable(unitNo))
  831. return flWriteFault;
  832. if (vol.physicalUnits[unitNo] == ANAND_UNIT_FREE)
  833. vol.freeUnits--;
  834. setUnavail(unitNo);
  835. getUnitTailer(&vol,unitNo,&eraseMark,&eraseCount);
  836. #ifdef NFTL_CACHE
  837. /* purge ANANDUnitHeader cache to force re-filling from flash */
  838. if (vol.ucache != NULL) {
  839. vol.ucache[unitNo].virtualUnitNo = 0xDEAD;
  840. vol.ucache[unitNo].replacementUnitNo = 0xDEAD;
  841. }
  842. /*
  843. * Purge the Sector Flags cache (set entries for all the unit's
  844. * sectors to SECTOR_FREE).
  845. */
  846. if (vol.scache != NULL) {
  847. tffsset(&(vol.scache[unitNo << (vol.unitSizeBits - SECTOR_SIZE_BITS-2)]),
  848. S_CACHE_4_SECTORS_FREE, 1 << (vol.unitSizeBits - SECTOR_SIZE_BITS - 2));
  849. }
  850. #endif /* NFTL_CACHE */
  851. status = vol.flash->erase(vol.flash,
  852. (word)(unitNo << (vol.unitSizeBits - vol.erasableBlockSizeBits)),
  853. (word)(1 << (vol.unitSizeBits - vol.erasableBlockSizeBits)));
  854. if (status != flOK) {
  855. markUnitBad(&vol,unitNo); /* make sure unit format is not valid */
  856. return status;
  857. }
  858. vol.eraseSum++;
  859. eraseCount++;
  860. if (eraseCount == 0) /* was hex FF's */
  861. eraseCount++;
  862. checkStatus(setUnitTailer(&vol,unitNo,ERASE_MARK,eraseCount));
  863. vol.physicalUnits[unitNo] = ANAND_UNIT_FREE;
  864. vol.freeUnits++;
  865. return flOK;
  866. }
  867. #ifndef FL_READ_ONLY
  868. /*----------------------------------------------------------------------*/
  869. /* w r i t e A n d C h e c k */
  870. /* */
  871. /* Write one sector. */
  872. /* */
  873. /* Parameters: */
  874. /* vol : Pointer identifying drive */
  875. /* address : Physical address of the sector to write to */
  876. /* fromAddress : Buffer of data to write */
  877. /* flags : Write flags (ECC, overwrite etc.) */
  878. /* */
  879. /* Returns: */
  880. /* Status : 0 on success, failed otherwise. */
  881. /*----------------------------------------------------------------------*/
  882. static FLStatus writeAndCheck(Anand vol,
  883. CardAddress address,
  884. void FAR1 *fromAddress,
  885. unsigned flags)
  886. {
  887. FLStatus status;
  888. #ifdef VERIFY_ERASED_SECTOR
  889. register int noOfDword;
  890. int i;
  891. #endif /* VERIFY_ERASED_SECTOR */
  892. /* Toggle verify write flag */
  893. #if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
  894. switch (flVerifyWrite[vol.socketNo][vol.flash->socket->curPartition])
  895. {
  896. case FL_OFF:
  897. if (vol.verifiedSectorNo>vol.curSectorWrite)
  898. break;
  899. case FL_ON:
  900. #ifdef VERIFY_WRITE
  901. vol.flash->socket->verifyWrite = FL_ON;
  902. #endif /* VERIFY_WRITE */
  903. #ifdef VERIFY_ERASED_SECTOR
  904. /* Make sure all of the sectors are really free */
  905. checkStatus(vol.flash->read(vol.flash,address,vol.verifyBuffer,SECTOR_SIZE,0));
  906. noOfDword = SECTOR_SIZE/sizeof(dword);
  907. for(i = 0;i<noOfDword;i++) /* Loop over sector data */
  908. {
  909. if(vol.verifyBuffer[i]!=0xffffffffL)
  910. {
  911. markAsIgnored(&vol,address);
  912. DEBUG_PRINT(("writeAndCheck : The sector was not erased and is ignored\r\n"));
  913. return flWriteFault;
  914. }
  915. }
  916. #endif /* VERIFY_ERASED_SECTOR */
  917. default:
  918. break;
  919. }
  920. #endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
  921. /* Write sector */
  922. status = vol.flash->write(vol.flash,address,fromAddress,SECTOR_SIZE,(word)flags);
  923. if (status == flWriteFault) { /* write failed, ignore this sector */
  924. markAsIgnored(&vol,address);
  925. }
  926. #ifdef NFTL_CACHE
  927. else {
  928. setSectorFlagsCache(&vol, address, SECTOR_USED);
  929. }
  930. #endif
  931. #ifdef VERIFY_WRITE
  932. /* Restore verify write mode */
  933. if(flVerifyWrite[flSocketNoOf(vol.flash->socket)][vol.flash->socket->curPartition] != FL_ON)
  934. vol.flash->socket->verifyWrite = FL_OFF;
  935. #endif /* VERIFY_WRITE */
  936. return status;
  937. }
  938. #endif /* FL_READ_ONLY */
  939. /*----------------------------------------------------------------------*/
  940. /* l a s t I n C h a i n */
  941. /* */
  942. /* Find last unit in chain. */
  943. /* */
  944. /* Parameters: */
  945. /* vol : Pointer identifying drive */
  946. /* unitNo : Start the search from this unit */
  947. /* */
  948. /* Returns: */
  949. /* Physical unit number of the last unit in chain. */
  950. /*----------------------------------------------------------------------*/
  951. static ANANDUnitNo lastInChain(Anand vol, ANANDUnitNo unitNo)
  952. {
  953. ANANDUnitNo firstVirtualUnitNo, firstReplacementUnitNo;
  954. ANANDUnitNo lastUnit = unitNo, nextUnitNo;
  955. ANANDUnitNo chainBound = 0;
  956. if(unitNo == ANAND_NO_UNIT)
  957. return ANAND_NO_UNIT;
  958. getUnitData(&vol,unitNo,&firstVirtualUnitNo,&firstReplacementUnitNo);
  959. nextUnitNo = firstReplacementUnitNo;
  960. while( (nextUnitNo < vol.noOfUnits) && /* Validate replacement unit no. */
  961. (chainBound < DOUBLE_MAX_UNIT_CHAIN) ) {
  962. ANANDUnitNo nextVirtualUnitNo, nextReplacementUnitNo;
  963. if( !isAvailable(nextUnitNo) )
  964. break;
  965. getUnitData(&vol,nextUnitNo,&nextVirtualUnitNo,&nextReplacementUnitNo);
  966. if( nextVirtualUnitNo != (firstVirtualUnitNo | ANAND_REPLACING_UNIT) )
  967. break; /* Virtual unit no. not validated */
  968. lastUnit = nextUnitNo;
  969. nextUnitNo = nextReplacementUnitNo;
  970. chainBound++;
  971. }
  972. return lastUnit;
  973. }
  974. #ifndef FL_READ_ONLY
  975. /*----------------------------------------------------------------------*/
  976. /* a s s i g n U n i t */
  977. /* */
  978. /* Assigns a virtual unit no. to a unit */
  979. /* */
  980. /* Parameters: */
  981. /* vol : Pointer identifying drive */
  982. /* unitNo : Physical unit number */
  983. /* virtualUnitNo : Virtual unit number to assign */
  984. /* */
  985. /* Returns: */
  986. /* FLStatus : 0 on success, failed otherwise */
  987. /*----------------------------------------------------------------------*/
  988. static FLStatus assignUnit(Anand vol, ANANDUnitNo unitNo, ANANDUnitNo virtualUnitNo)
  989. {
  990. ANANDUnitNo newVirtualUnitNo, newReplacementUnitNo;
  991. ANANDUnitNo oldVirtualUnitNo, oldReplacementUnitNo;
  992. FLStatus status;
  993. ANANDUnitNo newestUnitNo = vol.virtualUnits[virtualUnitNo];
  994. ANANDUnitNo oldUnitNo;
  995. /* Assign the new unit */
  996. newVirtualUnitNo = virtualUnitNo;
  997. if (newestUnitNo != ANAND_NO_UNIT)
  998. newVirtualUnitNo |= ANAND_REPLACING_UNIT;
  999. newReplacementUnitNo = ANAND_NO_UNIT;
  1000. vol.physicalUnits[unitNo] = 0;
  1001. vol.freeUnits--;
  1002. status = setUnitData(&vol,unitNo,newVirtualUnitNo,newReplacementUnitNo);
  1003. if (status != flOK)
  1004. {
  1005. markUnitBad(&vol,unitNo);
  1006. return status;
  1007. }
  1008. /* Add unit to chain */
  1009. if (newestUnitNo != ANAND_NO_UNIT)
  1010. {
  1011. /* If unit is frozen, don't attempt to chain (folding not-in-place) */
  1012. if (!isAvailable(newestUnitNo))
  1013. return flOK;
  1014. oldUnitNo = lastInChain(&vol,newestUnitNo);
  1015. getUnitData(&vol,oldUnitNo,&oldVirtualUnitNo,&oldReplacementUnitNo);
  1016. if (oldReplacementUnitNo != ANAND_NO_UNIT)
  1017. status = flWriteFault; /* can't write here, so assume failure */
  1018. else {
  1019. vol.physicalUnits[oldUnitNo] |= UNIT_REPLACED;
  1020. status = setUnitData(&vol,oldUnitNo,oldVirtualUnitNo,unitNo);
  1021. }
  1022. if (status != flOK) {
  1023. formatUnit(&vol,unitNo); /* Get rid of the allocated unit quickly */
  1024. setUnavail(newestUnitNo); /* freeze the chain */
  1025. return status;
  1026. }
  1027. if (vol.countsValid > virtualUnitNo && newestUnitNo != oldUnitNo){
  1028. if (countOf(newestUnitNo) + countOf(oldUnitNo) <= UNIT_MAX_COUNT)
  1029. vol.physicalUnits[newestUnitNo] += countOf(oldUnitNo);
  1030. else
  1031. return flGeneralFailure;
  1032. }
  1033. }
  1034. else
  1035. vol.virtualUnits[virtualUnitNo] = unitNo;
  1036. return flOK;
  1037. }
  1038. #endif /* FL_READ_ONLY */
  1039. /*----------------------------------------------------------------------*/
  1040. /* f o r m a t C h a i n */
  1041. /* */
  1042. /* Format all the units in a chain. Start from the last one and go */
  1043. /* backwards until unitNo is reached. */
  1044. /* */
  1045. /* Parameters: */
  1046. /* vol : Pointer identifying drive */
  1047. /* unitNo : Format the chain from this unit onwards */
  1048. /* */
  1049. /* Returns: */
  1050. /* FLStatus : 0 on success, failed otherwise */
  1051. /*----------------------------------------------------------------------*/
  1052. static FLStatus formatChain(Anand vol, ANANDUnitNo unitNo)
  1053. {
  1054. /* Erase the chain from end to start */
  1055. ANANDUnitNo chainBound;
  1056. setUnitCount(unitNo,0); /* Reenable erase of this unit */
  1057. for (chainBound=0;( chainBound < DOUBLE_MAX_UNIT_CHAIN ); chainBound++) {
  1058. /* Find last unit in chain */
  1059. ANANDUnitNo unitToErase = lastInChain(&vol,unitNo);
  1060. if( formatUnit(&vol,unitToErase) != flOK )
  1061. break;
  1062. if (unitToErase == unitNo)
  1063. break; /* Erased everything */
  1064. }
  1065. return flOK;
  1066. }
  1067. #ifndef FL_READ_ONLY
  1068. /*----------------------------------------------------------------------*/
  1069. /* S w a p U n i t s */
  1070. /* */
  1071. /* Applies wear leveling. */
  1072. /* A rover unit dictates the current unit to level. If a unit chain */
  1073. /* fold, if single unit chain , append a unit and then fold. */
  1074. /* */
  1075. /* Parameters: */
  1076. /* vol : Pointer identifying drive */
  1077. /* */
  1078. /* Returns: */
  1079. /* FLStatus : 0 on success, failed otherwise */
  1080. /*----------------------------------------------------------------------*/
  1081. FLStatus swapUnits(Anand vol)
  1082. {
  1083. ANANDUnitNo i,unitNo,virtualUnitNo,replacementUnitNo;
  1084. FLStatus status;
  1085. if(vol.wearLevel.currUnit>=vol.noOfVirtualUnits)
  1086. return flOK;
  1087. for(i=0,unitNo=vol.virtualUnits[vol.wearLevel.currUnit];
  1088. (unitNo==ANAND_NO_UNIT) && (i<vol.noOfVirtualUnits);i++) {
  1089. vol.wearLevel.currUnit++;
  1090. if(vol.wearLevel.currUnit>=vol.noOfVirtualUnits)
  1091. vol.wearLevel.currUnit = 0;
  1092. unitNo=vol.virtualUnits[vol.wearLevel.currUnit];
  1093. }
  1094. if(unitNo==ANAND_NO_UNIT) /*The media is empty*/
  1095. return flOK;
  1096. virtualUnitNo = vol.wearLevel.currUnit;
  1097. vol.wearLevel.currUnit++;
  1098. if(vol.wearLevel.currUnit>=vol.noOfVirtualUnits)
  1099. vol.wearLevel.currUnit = 0;
  1100. if((vol.physicalUnits[unitNo] & UNIT_REPLACED) ||
  1101. (!isAvailable(unitNo) ) )
  1102. {
  1103. status = foldUnit(&vol,virtualUnitNo,FALSE);
  1104. }
  1105. else
  1106. {
  1107. checkStatus(allocateUnit(&vol,&replacementUnitNo));
  1108. return assignUnit(&vol,replacementUnitNo,virtualUnitNo);
  1109. }
  1110. /* If folding failed make sure there are enough units and call again */
  1111. if(status == flCanNotFold)
  1112. return checkFolding(&vol,virtualUnitNo);
  1113. return status;
  1114. }
  1115. /*----------------------------------------------------------------------*/
  1116. /* f i n d F r e e U n i t */
  1117. /* */
  1118. /* Find a free unit from the physical unit pool. */
  1119. /* */
  1120. /* Parameters: */
  1121. /* vol : Pointer identifying drive */
  1122. /* unitNo : Receives the physical unit no. */
  1123. /* */
  1124. /* Returns: */
  1125. /* FLStatus : 0 on success, failed otherwise */
  1126. /*----------------------------------------------------------------------*/
  1127. static FLStatus findFreeUnit(Anand vol, ANANDUnitNo *unitNo)
  1128. {
  1129. ANANDUnitNo originalUnit = vol.roverUnit;
  1130. unsigned short eraseMark;
  1131. unsigned long eraseCount;
  1132. do
  1133. {
  1134. if (++vol.roverUnit >= vol.noOfUnits)
  1135. vol.roverUnit = vol.bootUnits;
  1136. if (vol.physicalUnits[vol.roverUnit] == ANAND_UNIT_FREE)
  1137. {
  1138. /* found a free unit, if not erased, */
  1139. getUnitTailer(&vol,vol.roverUnit,&eraseMark,&eraseCount);
  1140. if (eraseMark != ERASE_MARK)
  1141. {
  1142. if (formatUnit(&vol,vol.roverUnit) != flOK)
  1143. continue; /* this unit is bad, find another */
  1144. }
  1145. *unitNo = vol.roverUnit;
  1146. return flOK;
  1147. }
  1148. } while (vol.roverUnit != originalUnit);
  1149. return flNotEnoughMemory; /* Report no space at all */
  1150. }
  1151. /*----------------------------------------------------------------------*/
  1152. /* f o l d U n i t */
  1153. /* */
  1154. /* Copy all the sectors that hold valid data in the chain to the last */
  1155. /* unit of the chain and erase the chain. */
  1156. /* */
  1157. /* Parameters: */
  1158. /* vol : Pointer identifying drive */
  1159. /* virtualUnitNo : Virtual unit number of the first unit in chain. */
  1160. /* forceFolding : Boolean flag stating wether to force folding even */
  1161. /* at the cost of loosing sector data. */
  1162. /* */
  1163. /* Returns: */
  1164. /* FLStatus : 0 on success, failed otherwise */
  1165. /*----------------------------------------------------------------------*/
  1166. static FLStatus foldUnit(Anand vol, ANANDUnitNo virtualUnitNo, FLBoolean forceFolding)
  1167. {
  1168. ANANDUnitNo unitNo = vol.virtualUnits[virtualUnitNo];
  1169. ANANDUnitNo targetUnitNo, chainBound;
  1170. unsigned long foldMark;
  1171. SectorNo virtualSectorNo = (SectorNo)virtualUnitNo * vol.sectorsPerUnit;
  1172. CardAddress endSectorAddress;
  1173. CardAddress targetSectorAddress;
  1174. CardAddress sourceSectorAddress;
  1175. unsigned newSectorCount, i;
  1176. FLBoolean partialFoldingFlag = FALSE;
  1177. FLStatus status;
  1178. /* Force remapping of internal catched sector */
  1179. vol.flash->socket->remapped = TRUE;
  1180. vol.unitsFolded++;
  1181. /* When using FL_OFF option the media is scanned in the folding operation */
  1182. #if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
  1183. if(flVerifyWrite[flSocketNoOf(vol.flash->socket)][vol.flash->socket->curPartition]==FL_OFF)
  1184. {
  1185. checkStatus(verifySectors(&vol,SECTORS_VERIFIED_PER_FOLDING));
  1186. vol.curSectorWrite = virtualSectorNo;
  1187. }
  1188. #endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
  1189. /* Find target unit */
  1190. if (!isAvailable(unitNo)) /* If this unit is frozen, */
  1191. {
  1192. if(vol.freeUnits > 0)
  1193. {
  1194. /* allocate a new unit to fold into */
  1195. checkStatus(findFreeUnit(&vol,&targetUnitNo));
  1196. checkStatus(assignUnit(&vol,targetUnitNo,virtualUnitNo));
  1197. }
  1198. else
  1199. {
  1200. if(forceFolding==FALSE)
  1201. return flCanNotFold;
  1202. partialFoldingFlag = TRUE;
  1203. }
  1204. }
  1205. if((isAvailable(unitNo)) || (partialFoldingFlag == TRUE))
  1206. { /* Default. Fold into end of chain */
  1207. targetUnitNo = unitNo;
  1208. for (chainBound=0;( chainBound < DOUBLE_MAX_UNIT_CHAIN );chainBound++)
  1209. {
  1210. ANANDUnitNo nextUnitNo = getNextUnit(&vol,targetUnitNo,virtualUnitNo);
  1211. if (nextUnitNo == ANAND_NO_UNIT)
  1212. break;
  1213. targetUnitNo = nextUnitNo;
  1214. }
  1215. if(chainBound == DOUBLE_MAX_UNIT_CHAIN)
  1216. {
  1217. targetUnitNo = findEndOfEndlessChain(&vol, virtualUnitNo);
  1218. }
  1219. }
  1220. /***********************************/
  1221. /* Copy all sectors to target unit */
  1222. /***********************************/
  1223. /* Mark unit as currently folded */
  1224. foldMark = FOLDING_IN_PROGRESS * 0x10001l;
  1225. if( getFoldMark(&vol,unitNo) != FOLDING_IN_PROGRESS )
  1226. vol.flash->write(vol.flash,
  1227. unitBaseAddress(&vol,unitNo) + FOLD_MARK_OFFSET,
  1228. &foldMark,
  1229. sizeof foldMark,
  1230. EXTRA);
  1231. setUnavail(unitNo); /* Freeze this unit chain */
  1232. /* Copy all sectors to target unit */
  1233. targetSectorAddress = unitBaseAddress(&vol,targetUnitNo);
  1234. newSectorCount = 0;
  1235. for (i = 0; i < vol.sectorsPerUnit; i++, virtualSectorNo++,
  1236. #if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
  1237. vol.curSectorWrite++,
  1238. #endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
  1239. targetSectorAddress += SECTOR_SIZE)
  1240. {
  1241. endSectorAddress = ANAND_UNASSIGNED_ADDRESS;
  1242. for(chainBound=0;chainBound<DOUBLE_MAX_UNIT_CHAIN;chainBound++)
  1243. {
  1244. sourceSectorAddress = virtual2Physical(&vol,virtualSectorNo,&endSectorAddress);
  1245. if(sourceSectorAddress == targetSectorAddress)
  1246. {
  1247. /* Sector resides on the last unit of the virtual chain and */
  1248. /* does not need to be copied */
  1249. #if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
  1250. switch(flVerifyWrite[flSocketNoOf(vol.flash->socket)][vol.flash->socket->curPartition])
  1251. {
  1252. case FL_UPS:
  1253. newSectorCount++;
  1254. goto nextSectorLable;
  1255. case FL_OFF:
  1256. if(vol.verifiedSectorNo > virtualSectorNo)
  1257. {
  1258. newSectorCount++;
  1259. goto nextSectorLable;
  1260. }
  1261. default: /* FL_ON */
  1262. break;
  1263. }
  1264. /* Validate the sector has valid EDC/ECC */
  1265. status = vol.flash->read(vol.flash,sourceSectorAddress,nftlBuffer,SECTOR_SIZE,EDC);
  1266. if(status!=flOK)
  1267. { /* Last sector of chain has EDC errors - can not fold there */
  1268. if(forceFolding!=TRUE)
  1269. {
  1270. return flCanNotFold;
  1271. }
  1272. else
  1273. {
  1274. goto nextSectorLable;
  1275. }
  1276. }
  1277. newSectorCount++;
  1278. goto nextSectorLable;
  1279. #endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
  1280. }
  1281. else if(sourceSectorAddress != ANAND_UNASSIGNED_ADDRESS)
  1282. {
  1283. /* Check that area is free (ignore flag) */
  1284. if(getSectorFlags(&vol,targetSectorAddress) != SECTOR_FREE)
  1285. {
  1286. if(forceFolding!=TRUE)
  1287. {
  1288. return flCanNotFold;
  1289. }
  1290. else
  1291. {
  1292. break;
  1293. }
  1294. }
  1295. /* Copy sector to target sector */
  1296. status = vol.flash->read(vol.flash,sourceSectorAddress,nftlBuffer,SECTOR_SIZE,EDC);
  1297. if (status != flOK) /* Try reading previous sector */
  1298. {
  1299. endSectorAddress = sourceSectorAddress;
  1300. continue;
  1301. }
  1302. status = writeAndCheck(&vol,targetSectorAddress,nftlBuffer,EDC);
  1303. switch (status)
  1304. {
  1305. case flOK: /* Success */
  1306. vol.parasiteWrites++;
  1307. newSectorCount++;
  1308. goto nextSectorLable;
  1309. case flWriteFault: /* Faild in verify write */
  1310. if (forceFolding == FALSE)
  1311. return flCanNotFold;
  1312. goto nextSectorLable;
  1313. default : /* Protection error or any other */
  1314. return status;
  1315. }
  1316. }
  1317. else /* ANAND_UNASSIGNED_ADDRESS - Sector not used */
  1318. {
  1319. goto nextSectorLable;
  1320. }
  1321. }
  1322. return flGeneralFailure;
  1323. nextSectorLable:;
  1324. } /* End of copy sector loop */
  1325. /*****************************/
  1326. /* Add unit to virtual chain */
  1327. /*****************************/
  1328. if (newSectorCount > 0) { /* Some sectors remaining*/
  1329. /* Mark target unit as original */
  1330. if( (setUnitData(&vol,targetUnitNo,virtualUnitNo,ANAND_NO_UNIT) != flOK ) ||
  1331. (partialFoldingFlag == TRUE))
  1332. {
  1333. setUnavail(targetUnitNo); /* freeze this unit */
  1334. }
  1335. else
  1336. {
  1337. setUnitCount(targetUnitNo,newSectorCount);
  1338. }
  1339. /* Set target unit in virtual unit table */
  1340. vol.virtualUnits[virtualUnitNo] = targetUnitNo;
  1341. }
  1342. else {
  1343. if (unitNo != targetUnitNo) {
  1344. /* If there is a chain to delete ... */
  1345. /* mark unit as completed folding, pending erase */
  1346. #ifndef NT5PORT
  1347. unsigned long foldMark = FOLDING_COMPLETE * 0x10001l;
  1348. #else /*NT5PORT*/
  1349. foldMark = FOLDING_COMPLETE * 0x10001l;
  1350. #endif /*NT5PORT*/
  1351. vol.flash->write(vol.flash,
  1352. unitBaseAddress(&vol,unitNo) + FOLD_MARK_OFFSET,
  1353. &foldMark,
  1354. sizeof foldMark,
  1355. EXTRA);
  1356. }
  1357. vol.virtualUnits[virtualUnitNo] = ANAND_NO_UNIT;
  1358. }
  1359. /* Erase source units */
  1360. return formatChain(&vol,unitNo);
  1361. }
  1362. /*----------------------------------------------------------------------*/
  1363. /* c r e a t e U n i t C o u n t */
  1364. /* */
  1365. /* Count the number of sectors in a unit that hold valid data. */
  1366. /* */
  1367. /* Parameters: */
  1368. /* vol : Pointer identifying drive */
  1369. /* unitNo : Physical unit number */
  1370. /* */
  1371. /*----------------------------------------------------------------------*/
  1372. static void createUnitCount(Anand vol, ANANDUnitNo unitNo)
  1373. {
  1374. unsigned int i;
  1375. SectorNo sectorNo;
  1376. CardAddress sectorAddress;
  1377. ANANDUnitNo physicalUnitNo = vol.virtualUnits[unitNo];
  1378. if (physicalUnitNo == ANAND_NO_UNIT)
  1379. return;
  1380. if (!isAvailable(physicalUnitNo))
  1381. return;
  1382. /* Get a count of the valid sector in this unit */
  1383. setUnitCount(physicalUnitNo,0);
  1384. sectorNo = (SectorNo)unitNo * vol.sectorsPerUnit;
  1385. for (i = 0; i < vol.sectorsPerUnit; i++, sectorNo++) {
  1386. sectorAddress = virtual2Physical(&vol,sectorNo,NULL);
  1387. if (sectorAddress != ANAND_UNASSIGNED_ADDRESS) {
  1388. ANANDUnitNo currUnitNo = (ANANDUnitNo)(sectorAddress >> vol.unitSizeBits);
  1389. if (vol.physicalUnits[currUnitNo] & UNIT_REPLACED)
  1390. currUnitNo = physicalUnitNo;
  1391. /* Increament sector count - Assumed EDC OK , was not verified */
  1392. vol.physicalUnits[currUnitNo]++;
  1393. }
  1394. }
  1395. }
  1396. /*----------------------------------------------------------------------*/
  1397. /* f o l d B e s t C h a i n */
  1398. /* */
  1399. /* Find the best chain to fold and fold it.A good chain to fold is a */
  1400. /* long chain with a small number of sectors that hold valid data. */
  1401. /* */
  1402. /* Parameters: */
  1403. /* vol : Pointer identifying drive */
  1404. /* unitNo : Receives the physical unit no. of the first */
  1405. /* unit in the chain that was folded. */
  1406. /* */
  1407. /* Returns: */
  1408. /* FLStatus : 0 on success, failed otherwise */
  1409. /*----------------------------------------------------------------------*/
  1410. static FLStatus foldBestChain(Anand vol, ANANDUnitNo *unitNo)
  1411. {
  1412. unsigned leastCount;
  1413. unsigned longestChain;
  1414. unsigned unitCount;
  1415. ANANDUnitNo virtualUnitNo;
  1416. ANANDUnitNo u;
  1417. ANANDUnitNo firstUnitNo;
  1418. unsigned int maxCounter;
  1419. FLStatus status = flCanNotFold;
  1420. /* Loop as long as can not fold in place or until MAX_FOLDING_TRIES time */
  1421. for (maxCounter = 0 ; maxCounter < MAX_FOLDING_TRIES ; maxCounter++)
  1422. {
  1423. leastCount = vol.sectorsPerUnit + 1; /* Set to invalid sector count */
  1424. longestChain = 0; /* Set to invalid unit length */
  1425. virtualUnitNo = ANAND_NO_UNIT;
  1426. /*************************************************************/
  1427. /* Loop over all virtual units until best candidate is found */
  1428. /*************************************************************/
  1429. for (u = 0; u < vol.noOfVirtualUnits; u++)
  1430. {
  1431. /* If virtual unit does not exist continue to next unit */
  1432. firstUnitNo = vol.virtualUnits[u];
  1433. if( firstUnitNo == ANAND_NO_UNIT )
  1434. continue;
  1435. /* Make sure sector count of unit is valid */
  1436. if (vol.countsValid <= u)
  1437. {
  1438. createUnitCount(&vol,u); /* Update sector count */
  1439. vol.countsValid = u + 1;
  1440. }
  1441. if( isAvailable(firstUnitNo) ) /* store sector count */
  1442. {
  1443. unitCount = countOf(firstUnitNo);
  1444. }
  1445. else
  1446. {
  1447. unitCount = vol.sectorsPerUnit; /* set low priority */
  1448. }
  1449. /* This is an empty unit. We can simply erase it */
  1450. if (unitCount == 0)
  1451. {
  1452. leastCount = 0;
  1453. virtualUnitNo = u;
  1454. break;
  1455. }
  1456. if(/* Smallest sector count found so far */
  1457. (leastCount >= unitCount ) &&
  1458. /* And this unit is not a single unit chain */
  1459. (vol.physicalUnits[firstUnitNo] & UNIT_REPLACED) )
  1460. {
  1461. unsigned chainLength = 0;
  1462. /* Compare chain length */
  1463. ANANDUnitNo nextUnitNo = getNextUnit(&vol,firstUnitNo,u);
  1464. if(isAvailable(firstUnitNo))
  1465. {
  1466. while((nextUnitNo != ANAND_NO_UNIT ) &&
  1467. (chainLength < DOUBLE_MAX_UNIT_CHAIN))
  1468. {
  1469. chainLength++;
  1470. nextUnitNo = getNextUnit(&vol,nextUnitNo,u);
  1471. }
  1472. }
  1473. else
  1474. {
  1475. chainLength = 0; /* Set lowest priority to frozen chain */
  1476. }
  1477. /* set low priority to neverending loop chain */
  1478. if(chainLength == DOUBLE_MAX_UNIT_CHAIN)
  1479. chainLength = 0;
  1480. if((leastCount == unitCount ) && (longestChain >= chainLength))
  1481. continue;
  1482. longestChain = chainLength;
  1483. leastCount = unitCount;
  1484. virtualUnitNo = u;
  1485. } /* End - unit has less (or eqaul) no' of used sectors found so far */
  1486. } /* End - Loop over all virtual units and find best candidate */
  1487. /*************************************************************/
  1488. /* Candidate virtual chain has been chosen - try and fold it */
  1489. /*************************************************************/
  1490. if ((leastCount > vol.sectorsPerUnit) ||
  1491. (virtualUnitNo == ANAND_NO_UNIT))
  1492. {
  1493. /* Only single units chains were found */
  1494. if(maxCounter==0) /* And no chain was frozen while searching */
  1495. return flNotEnoughMemory; /* Report no space at all */
  1496. break; /* Try and fold the frozen units that have been found */
  1497. }
  1498. else /* Try and fold the candidate unit */
  1499. {
  1500. if(!isAvailable(vol.virtualUnits[virtualUnitNo])) /* This is a frozen unit */
  1501. {
  1502. /* Frozen chains have the lowest priority - stop searching */
  1503. break;
  1504. }
  1505. else /* Try and fold the unit */
  1506. {
  1507. /* Store the first unit as the new free unit */
  1508. *unitNo = vol.virtualUnits[virtualUnitNo];
  1509. /* Store number of free Units */
  1510. u = vol.freeUnits;
  1511. /* Fold the candidate unit */
  1512. status = foldUnit(&vol,virtualUnitNo,FALSE);
  1513. switch(status)
  1514. {
  1515. case flOK:
  1516. if(vol.freeUnits == u) /* Did not free any units */
  1517. continue;
  1518. break;
  1519. case flCanNotFold: /* Need to fold not in place */
  1520. continue;
  1521. default:
  1522. return status;
  1523. }
  1524. break;
  1525. }
  1526. }
  1527. } /* End MAX_FOLDING_TRIES loop */
  1528. /***************************************************************/
  1529. /* Check folding status - might need a special kind of folding */
  1530. /***************************************************************/
  1531. if(maxCounter)
  1532. {
  1533. *unitNo = ANAND_NO_UNIT;
  1534. /* Unfreeze all units */
  1535. for (u = vol.spareOrgUnit + 1; u < vol.noOfUnits; u++)
  1536. {
  1537. if(!isAvailable(u)) /* This is a frozen unit */
  1538. {
  1539. /* Get virtual unit of frozen physical unit */
  1540. getUnitData(&vol,u,&virtualUnitNo,&firstUnitNo);
  1541. if(virtualUnitNo < vol.noOfVirtualUnits)
  1542. {
  1543. /* Store the first unit as the new free unit */
  1544. firstUnitNo = vol.virtualUnits[virtualUnitNo];
  1545. /* Force folding no matter what */
  1546. if(firstUnitNo != ANAND_NO_UNIT)
  1547. {
  1548. checkStatus(foldUnit(&vol,virtualUnitNo,TRUE));
  1549. /* Recalculate sector count */
  1550. createUnitCount(&vol, virtualUnitNo);
  1551. *unitNo = firstUnitNo;
  1552. }
  1553. }
  1554. }
  1555. }
  1556. }
  1557. if((*unitNo!= ANAND_NO_UNIT) && (vol.freeUnits > 0)) /* A unit was freed */
  1558. return flOK;
  1559. else
  1560. return flGeneralFailure;
  1561. }
  1562. /*----------------------------------------------------------------------*/
  1563. /* a l l o c a t e U n i t */
  1564. /* */
  1565. /* Find a free unit to allocate, erase it if necessary. */
  1566. /* */
  1567. /* Parameters: */
  1568. /* vol : Pointer identifying drive */
  1569. /* unitNo : Receives the physical number of the allocated */
  1570. /* unit */
  1571. /* Returns: */
  1572. /* FLStatus : 0 on success, failed otherwise */
  1573. /*----------------------------------------------------------------------*/
  1574. static FLStatus allocateUnit(Anand vol, ANANDUnitNo *unitNo)
  1575. {
  1576. ANANDUnitNo originalUnit = vol.roverUnit;
  1577. FLStatus status;
  1578. if (vol.freeUnits < 2) /* Try to make sure not to use the last unit */
  1579. {
  1580. status = foldBestChain(&vol,unitNo);
  1581. if(status != flNotEnoughMemory)
  1582. return status;
  1583. }
  1584. return findFreeUnit(&vol, unitNo);
  1585. }
  1586. #endif /* FL_READ_ONLY */
  1587. /*----------------------------------------------------------------------*/
  1588. /* m a p S e c t o r */
  1589. /* */
  1590. /* Maps and returns location of a given sector no. */
  1591. /* NOTE: This function is used in place of a read-sector operation. */
  1592. /* */
  1593. /* A one-sector cache is maintained to save on map operations. */
  1594. /* */
  1595. /* Parameters: */
  1596. /* vol : Pointer identifying drive */
  1597. /* sectorNo : Sector no. to read */
  1598. /* physAddress : Optional pointer to receive sector address */
  1599. /* */
  1600. /* Returns: */
  1601. /* Pointer to physical sector location. NULL returned if sector */
  1602. /* does not exist. */
  1603. /*----------------------------------------------------------------------*/
  1604. static const void FAR0 *mapSector(Anand vol, SectorNo sectorNo, CardAddress *physAddress)
  1605. {
  1606. if (sectorNo != vol.mappedSectorNo || vol.flash->socket->remapped)
  1607. {
  1608. if (sectorNo >= vol.virtualSectors)
  1609. {
  1610. vol.mappedSector = NULL;
  1611. }
  1612. else
  1613. {
  1614. int chainBound = 0;
  1615. for(vol.mappedSectorAddress=ANAND_UNASSIGNED_ADDRESS;
  1616. chainBound<DOUBLE_MAX_UNIT_CHAIN;chainBound++)
  1617. {
  1618. CardAddress endSectorAddress = vol.mappedSectorAddress;
  1619. vol.mappedSectorAddress = virtual2Physical(&vol,sectorNo,&endSectorAddress);
  1620. if (vol.mappedSectorAddress == ANAND_UNASSIGNED_ADDRESS)
  1621. {
  1622. vol.mappedSector = NULL; /* no such sector */
  1623. break;
  1624. }
  1625. else
  1626. {
  1627. vol.mappedSector = nftlBuffer;
  1628. if (vol.flash->read(vol.flash,vol.mappedSectorAddress,nftlBuffer,SECTOR_SIZE,EDC) == flOK)
  1629. break;
  1630. }
  1631. }
  1632. vol.mappedSectorNo = sectorNo;
  1633. vol.flash->socket->remapped = FALSE;
  1634. }
  1635. }
  1636. if (physAddress)
  1637. *physAddress = vol.mappedSectorAddress;
  1638. return vol.mappedSector;
  1639. }
  1640. /* Mounting and formatting */
  1641. /*----------------------------------------------------------------------*/
  1642. /* m o u n t U n i t */
  1643. /* */
  1644. /* Mount one unit. Read the relevant data from the unit header and */
  1645. /* update the conversion tables. */
  1646. /* */
  1647. /* Parameters: */
  1648. /* vol : Pointer identifying drive */
  1649. /* unitNo : Unit to mount */
  1650. /* */
  1651. /* Returns: */
  1652. /* FLStatus : 0 on success, failed otherwise */
  1653. /*----------------------------------------------------------------------*/
  1654. static FLStatus mountUnit(Anand vol, ANANDUnitNo unitNo,
  1655. unsigned long* eraseCount)
  1656. {
  1657. ANANDUnitNo virtualUnitNo, replacementUnitNo;
  1658. unsigned short eraseMark;
  1659. ANANDPhysUnit FAR1 *pU = &vol.physicalUnits[unitNo];
  1660. getUnitData(&vol,unitNo,&virtualUnitNo,&replacementUnitNo);
  1661. getUnitTailer(&vol,unitNo,&eraseMark,eraseCount);
  1662. if (virtualUnitNo == ANAND_NO_UNIT ||
  1663. eraseMark != ERASE_MARK) { /* this unit is not assigned */
  1664. *pU = ANAND_UNIT_FREE;
  1665. }
  1666. else { /* this unit is assigned */
  1667. *pU &= UNIT_ORPHAN;
  1668. if (replacementUnitNo < vol.noOfUnits) {
  1669. *pU |= UNIT_REPLACED;
  1670. if (isAvailable(replacementUnitNo) ||
  1671. isReplaced(replacementUnitNo))
  1672. /* Mark replacement unit as non-orphan */
  1673. vol.physicalUnits[replacementUnitNo] &= ~UNIT_ORPHAN;
  1674. }
  1675. if (!(virtualUnitNo & ANAND_REPLACING_UNIT)) {
  1676. unsigned short foldMark;
  1677. ANANDUnitNo physUnitNo;
  1678. if (virtualUnitNo >= vol.noOfVirtualUnits)
  1679. return formatUnit(&vol,unitNo);
  1680. foldMark = getFoldMark(&vol,unitNo);
  1681. physUnitNo = vol.virtualUnits[virtualUnitNo];
  1682. if (foldMark == FOLDING_COMPLETE)
  1683. formatChain(&vol,unitNo);
  1684. else if (physUnitNo == ANAND_NO_UNIT || !isAvailable(physUnitNo)) {
  1685. /* If we have duplicates, it's OK if one of them is currently folded */
  1686. vol.virtualUnits[virtualUnitNo] = unitNo;
  1687. *pU &= ~UNIT_ORPHAN;
  1688. if (foldMark == FOLDING_IN_PROGRESS) {
  1689. setUnavail(unitNo);
  1690. }
  1691. if (physUnitNo != ANAND_NO_UNIT)
  1692. formatChain(&vol,physUnitNo); /* Get rid of old chain */
  1693. }
  1694. else if (foldMark == FOLDING_IN_PROGRESS)
  1695. formatChain(&vol,unitNo);
  1696. else
  1697. return flBadFormat; /* We have a duplicate to a unit that */
  1698. /* is not currently folded. That's bad. */
  1699. }
  1700. }
  1701. return flOK;
  1702. }
  1703. #ifndef FL_READ_ONLY
  1704. /*----------------------------------------------------------------------*/
  1705. /* a l l o c a t e A n d W r i t e S e c t o r */
  1706. /* */
  1707. /* Write to sectorNo. if necessary, allocate a free sector first. */
  1708. /* */
  1709. /* Parameters: */
  1710. /* vol : Pointer identifying drive */
  1711. /* sectorNo : Virtual sector no. to write */
  1712. /* fromAddress : Address of sector data. */
  1713. /* */
  1714. /* Returns: */
  1715. /* FLStatus : 0 on success, failed otherwise */
  1716. /*----------------------------------------------------------------------*/
  1717. static FLStatus allocateAndWriteSector(void* rec,
  1718. SectorNo sectorNo,
  1719. void FAR1 *fromAddress)
  1720. {
  1721. Anand vol = (Anand*)rec;
  1722. ANANDUnitNo virtualUnitNo = (ANANDUnitNo)(sectorNo / vol.sectorsPerUnit);
  1723. ANANDUnitNo firstUnitNo = vol.virtualUnits[virtualUnitNo];
  1724. ANANDUnitNo unitNo;
  1725. unsigned unitOffset = (unsigned)((sectorNo % vol.sectorsPerUnit) << SECTOR_SIZE_BITS);
  1726. unsigned unitChainLength = 0;
  1727. FLBoolean sectorExists = FALSE;
  1728. FLBoolean unitWasFoldedOutOfPlace = FALSE;
  1729. FLStatus status;
  1730. /* If we can't write to this unit, must fold it first */
  1731. if (firstUnitNo != ANAND_NO_UNIT && !isAvailable(firstUnitNo)) {
  1732. status = foldUnit(&vol,virtualUnitNo,FALSE);
  1733. switch(status)
  1734. {
  1735. case flOK:
  1736. break;
  1737. case flCanNotFold:
  1738. checkStatus(checkFolding(&vol,virtualUnitNo));
  1739. break;
  1740. default:
  1741. return status;
  1742. }
  1743. firstUnitNo = vol.virtualUnits[virtualUnitNo];
  1744. }
  1745. /* Find a unit to write this sector */
  1746. unitNo = firstUnitNo;
  1747. while ((unitNo != ANAND_NO_UNIT) && (unitChainLength < DOUBLE_MAX_UNIT_CHAIN)) {
  1748. unsigned char sectorFlags = getSectorFlags(&vol,unitBaseAddress(&vol,unitNo) + unitOffset);
  1749. if (sectorFlags == SECTOR_FREE)
  1750. break;
  1751. if (sectorFlags != SECTOR_IGNORE)
  1752. sectorExists = sectorFlags == SECTOR_USED;
  1753. unitNo = getNextUnit(&vol,unitNo,virtualUnitNo);
  1754. unitChainLength++;
  1755. }
  1756. if (unitChainLength == DOUBLE_MAX_UNIT_CHAIN) { /* unit points to itself */
  1757. unitNo = ANAND_NO_UNIT; /* force folding not in place */
  1758. setUnavail(firstUnitNo);
  1759. }
  1760. if (unitNo == ANAND_NO_UNIT) { /* Can not write in chain - must add a unit */
  1761. firstUnitNo = vol.virtualUnits[virtualUnitNo];
  1762. if (unitChainLength >= MAX_UNIT_CHAIN)
  1763. {
  1764. status = foldUnit(&vol,virtualUnitNo,FALSE);
  1765. switch(status)
  1766. {
  1767. case flOK:
  1768. break;
  1769. case flCanNotFold:
  1770. checkStatus(checkFolding(&vol,virtualUnitNo));
  1771. break;
  1772. default:
  1773. return status;
  1774. }
  1775. }
  1776. if(vol.virtualUnits[virtualUnitNo] != firstUnitNo)
  1777. {
  1778. firstUnitNo = vol.virtualUnits[virtualUnitNo];
  1779. unitWasFoldedOutOfPlace = TRUE;
  1780. }
  1781. checkStatus(allocateUnit(&vol,&unitNo));
  1782. checkStatus(assignUnit(&vol,unitNo,virtualUnitNo));
  1783. if(vol.virtualUnits[virtualUnitNo] != firstUnitNo)
  1784. {
  1785. firstUnitNo = vol.virtualUnits[virtualUnitNo];
  1786. unitWasFoldedOutOfPlace = TRUE;
  1787. }
  1788. #if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
  1789. /* Folding might have discovered that the sector we are using is invalid */
  1790. if(sectorExists) {
  1791. if( unitWasFoldedOutOfPlace ) {
  1792. /* Unit was folded out of place, so if sector exists it must be in
  1793. * the first unit of the chain
  1794. */
  1795. if(getSectorFlags(&vol,unitBaseAddress(&vol,firstUnitNo) + unitOffset)
  1796. != SECTOR_USED) {
  1797. /* The sector we saw before had bad EDC */
  1798. sectorExists = FALSE;
  1799. unitNo = firstUnitNo;
  1800. }
  1801. }
  1802. }
  1803. #endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
  1804. }
  1805. #if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
  1806. vol.curSectorWrite = sectorNo;
  1807. #endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
  1808. checkStatus(writeAndCheck(&vol,unitBaseAddress(&vol,unitNo) + unitOffset,fromAddress,EDC));
  1809. if (vol.countsValid > virtualUnitNo) {
  1810. if (unitNo != firstUnitNo && !(vol.physicalUnits[unitNo] & UNIT_REPLACED)) {
  1811. if (countOf(unitNo) < UNIT_MAX_COUNT) /* Increment block count */
  1812. vol.physicalUnits[unitNo]++;
  1813. else
  1814. return flGeneralFailure;
  1815. if (sectorExists) /* Decrement block count */
  1816. {
  1817. if (countOf(firstUnitNo) > 0)
  1818. vol.physicalUnits[firstUnitNo]--;
  1819. else
  1820. return flGeneralFailure;
  1821. }
  1822. }
  1823. else if (!sectorExists) {
  1824. if (countOf(firstUnitNo) < UNIT_MAX_COUNT) /* Increment block count */
  1825. vol.physicalUnits[firstUnitNo]++;
  1826. else
  1827. return flGeneralFailure;
  1828. }
  1829. }
  1830. return flOK;
  1831. }
  1832. /*----------------------------------------------------------------------*/
  1833. /* w r i t e S e c t o r */
  1834. /* */
  1835. /* Writes a sector. */
  1836. /* */
  1837. /* Parameters: */
  1838. /* vol : Pointer identifying drive */
  1839. /* sectorNo : Virtual sector no. to write */
  1840. /* fromAddress : Data to write */
  1841. /* */
  1842. /* Returns: */
  1843. /* FLStatus : 0 on success, failed otherwise */
  1844. /*----------------------------------------------------------------------*/
  1845. static FLStatus writeSector(Anand vol, SectorNo sectorNo, void FAR1 *fromAddress)
  1846. {
  1847. FLStatus status = flWriteFault;
  1848. int i;
  1849. if (vol.badFormat)
  1850. return flBadFormat;
  1851. if (sectorNo >= vol.virtualSectors)
  1852. return flSectorNotFound;
  1853. if(vol.wearLevel.currUnit!=ANAND_NO_UNIT) {
  1854. vol.wearLevel.alarm++;
  1855. if(vol.wearLevel.alarm>=WLnow) {
  1856. vol.wearLevel.alarm = 0;
  1857. checkStatus(swapUnits(&vol));
  1858. }
  1859. }
  1860. if (sectorNo == vol.mappedSectorNo)
  1861. {
  1862. /* Force remapping of internal catched sector */
  1863. vol.flash->socket->remapped = TRUE;
  1864. }
  1865. vol.sectorsWritten++;
  1866. for (i = 0; i < 4 && status == flWriteFault; i++) {
  1867. if (vol.mappedSectorNo == sectorNo)
  1868. vol.mappedSectorNo = UNASSIGNED_SECTOR;
  1869. status = allocateAndWriteSector(&vol,sectorNo,fromAddress);
  1870. }
  1871. return status;
  1872. }
  1873. /*----------------------------------------------------------------------*/
  1874. /* d e l e t e S e c t o r */
  1875. /* */
  1876. /* Marks contiguous sectors as deleted. */
  1877. /* */
  1878. /* Parameters: */
  1879. /* vol : Pointer identifying drive */
  1880. /* sectorNo : First sector no. to delete */
  1881. /* noOfSectors : No. of sectors to delete */
  1882. /* */
  1883. /* Returns: */
  1884. /* FLStatus : 0 on success, failed otherwise */
  1885. /*----------------------------------------------------------------------*/
  1886. static FLStatus deleteSector(Anand vol, SectorNo sectorNo, SectorNo noOfSectors)
  1887. {
  1888. SectorNo iSector;
  1889. FLStatus status;
  1890. if (vol.badFormat)
  1891. return flBadFormat;
  1892. if (sectorNo + noOfSectors > vol.virtualSectors)
  1893. return flSectorNotFound;
  1894. for (iSector = 0; iSector < noOfSectors; iSector++, sectorNo++,
  1895. vol.sectorsDeleted++) {
  1896. CardAddress sectorAddress = virtual2Physical(&vol,sectorNo,NULL);
  1897. if (sectorAddress != ANAND_UNASSIGNED_ADDRESS) {
  1898. byte sectorFlags[2];
  1899. ANANDUnitNo currUnitNo;
  1900. /* Check that the unit is writable, and if not, fold it first */
  1901. ANANDUnitNo virtualUnitNo = (ANANDUnitNo)(sectorNo / vol.sectorsPerUnit);
  1902. ANANDUnitNo unitNo = vol.virtualUnits[virtualUnitNo];
  1903. if (!isAvailable(unitNo)) {
  1904. status = foldUnit(&vol,virtualUnitNo,FALSE);
  1905. switch(status)
  1906. {
  1907. case flOK:
  1908. break;
  1909. case flCanNotFold:
  1910. checkStatus(checkFolding(&vol,virtualUnitNo));
  1911. break;
  1912. default:
  1913. return status;
  1914. }
  1915. sectorAddress = virtual2Physical(&vol,sectorNo,NULL);
  1916. }
  1917. /* Mark sector deleted */
  1918. sectorFlags[0] = sectorFlags[1] = SECTOR_DELETED;
  1919. #ifdef NFTL_CACHE
  1920. setSectorFlagsCache(&vol, sectorAddress, SECTOR_DELETED);
  1921. #ifdef ENVIRONMENT_VARS
  1922. if (((flMarkDeleteOnFlash == FL_ON) &&
  1923. (flPolicy[vol.socketNo][vol.flash->socket->curPartition] != FL_COMPLETE_ASAP)) ||
  1924. (vol.scache == NULL))
  1925. #endif /* ENVIRONMENT_VARS */
  1926. #endif
  1927. vol.flash->write(vol.flash,
  1928. sectorAddress + SECTOR_DATA_OFFSET,
  1929. #ifndef NT5PORT
  1930. &sectorFlags,
  1931. #else /*NT5PORT*/
  1932. sectorFlags,
  1933. #endif /*NT5PORT*/
  1934. sizeof sectorFlags,
  1935. EXTRA);
  1936. currUnitNo = (ANANDUnitNo)(sectorAddress >> vol.unitSizeBits);
  1937. if ( isAvailable(currUnitNo) ) {
  1938. if (vol.physicalUnits[currUnitNo] & UNIT_REPLACED)
  1939. currUnitNo = vol.virtualUnits[virtualUnitNo];
  1940. if (vol.countsValid > virtualUnitNo) {
  1941. if (countOf(currUnitNo) > 0)
  1942. vol.physicalUnits[currUnitNo]--; /* Decrement block count */
  1943. else
  1944. return flGeneralFailure;
  1945. }
  1946. }
  1947. }
  1948. }
  1949. return flOK;
  1950. }
  1951. #endif /* FL_READ_ONLY */
  1952. /*----------------------------------------------------------------------*/
  1953. /* t l S e t B u s y */
  1954. /* */
  1955. /* Notifies the start and end of a file-system operation. */
  1956. /* */
  1957. /* Parameters: */
  1958. /* vol : Pointer identifying drive */
  1959. /* state : FL_ON (1) = operation entry */
  1960. /* FL_OFF(0) = operation exit */
  1961. /* */
  1962. /* Returns: */
  1963. /* FLStatus : 0 on success, failed otherwise */
  1964. /*----------------------------------------------------------------------*/
  1965. static FLStatus tlSetBusy(Anand vol, FLBoolean state)
  1966. {
  1967. return flOK;
  1968. }
  1969. #ifndef FL_READ_ONLY
  1970. #ifdef DEFRAGMENT_VOLUME
  1971. /*----------------------------------------------------------------------*/
  1972. /* d e f r a g m e n t */
  1973. /* */
  1974. /* Performs unit allocations to arrange a minimum number of writable */
  1975. /* sectors. */
  1976. /* */
  1977. /* Parameters: */
  1978. /* vol : Pointer identifying drive */
  1979. /* sectorsNeeded : Minimum required sectors */
  1980. /* */
  1981. /* Returns: */
  1982. /* FLStatus : 0 on success, failed otherwise */
  1983. /*----------------------------------------------------------------------*/
  1984. static FLStatus defragment(Anand vol, long FAR2 *sectorsNeeded)
  1985. {
  1986. ANANDUnitNo dummyUnitNo, firstFreeUnit = ANAND_NO_UNIT;
  1987. FLBoolean firstRound = TRUE;
  1988. FLStatus status = flOK;
  1989. if( (*sectorsNeeded) == -1 ) { /* fold single chain */
  1990. if (vol.badFormat)
  1991. return flBadFormat;
  1992. status = foldBestChain(&vol,&dummyUnitNo);
  1993. if( (status != flOK) && (vol.freeUnits == 0) )
  1994. return status;
  1995. *sectorsNeeded = vol.freeUnits * vol.sectorsPerUnit;
  1996. return flOK;
  1997. }
  1998. while ((SectorNo)vol.freeUnits * vol.sectorsPerUnit < ((SectorNo)(*sectorsNeeded))) {
  1999. if (vol.badFormat)
  2000. return flBadFormat;
  2001. status = allocateUnit(&vol,&dummyUnitNo);
  2002. if( status != flOK )
  2003. break;
  2004. if (firstRound) { /* remember the first free unit */
  2005. firstFreeUnit = dummyUnitNo;
  2006. firstRound = FALSE;
  2007. }
  2008. else if (firstFreeUnit == dummyUnitNo) {
  2009. /* We have wrapped around, all the units that were marked as free */
  2010. /* are now erased, and we still don't have enough space. */
  2011. status = foldBestChain(&vol,&dummyUnitNo); /* make more free units */
  2012. if( status != flOK )
  2013. break;
  2014. }
  2015. }
  2016. *sectorsNeeded = (long)vol.freeUnits * vol.sectorsPerUnit;
  2017. return status;
  2018. }
  2019. #endif /* DEFRAGMENT_VOLUME */
  2020. #endif /* FL_READ_ONLY */
  2021. /*----------------------------------------------------------------------*/
  2022. /* s e c t o r s I n V o l u m e */
  2023. /* */
  2024. /* Gets the total number of sectors in the volume */
  2025. /* */
  2026. /* Parameters: */
  2027. /* vol : Pointer identifying drive */
  2028. /* */
  2029. /* Returns: */
  2030. /* Number of sectors in the volume */
  2031. /*----------------------------------------------------------------------*/
  2032. static SectorNo sectorsInVolume(Anand vol)
  2033. {
  2034. return vol.virtualSectors;
  2035. }
  2036. /*----------------------------------------------------------------------*/
  2037. /* d i s m o u n t N F T L */
  2038. /* */
  2039. /* Dismount NFTL volume */
  2040. /* */
  2041. /* Parameters: */
  2042. /* vol : Pointer identifying drive */
  2043. /* */
  2044. /*----------------------------------------------------------------------*/
  2045. static void dismountNFTL(Anand vol)
  2046. {
  2047. #ifdef FL_MALLOC
  2048. if( vol.physicalUnits != NULL )
  2049. FL_FAR_FREE (vol.physicalUnits);
  2050. if( vol.virtualUnits != NULL )
  2051. FL_FAR_FREE (vol.virtualUnits);
  2052. vol.physicalUnits = NULL;
  2053. vol.virtualUnits = NULL;
  2054. #ifdef NFTL_CACHE
  2055. if( vol.ucache != NULL )
  2056. FL_FAR_FREE (vol.ucache);
  2057. if( vol.scache != NULL )
  2058. FL_FAR_FREE (vol.scache);
  2059. vol.ucache = NULL;
  2060. vol.scache = NULL;
  2061. #endif /* NFTL_CACHE */
  2062. #endif /* FL_MALLOC */
  2063. }
  2064. Anand* getAnandRec(unsigned driveNo)
  2065. {
  2066. return (&vols[driveNo]);
  2067. }
  2068. #ifdef FORMAT_VOLUME
  2069. /*----------------------------------------------------------------------*/
  2070. /* i s E r a s e d U n i t */
  2071. /* */
  2072. /* Check if a unit is erased. */
  2073. /* */
  2074. /* Parameters: */
  2075. /* vol : Pointer identifying drive */
  2076. /* unitNo : unit to check */
  2077. /* */
  2078. /* Returns: */
  2079. /* TRUE if unit is erased, FALSE otherwise */
  2080. /*----------------------------------------------------------------------*/
  2081. static FLBoolean isErased(Anand vol, ANANDUnitNo unitNo)
  2082. {
  2083. CardAddress addr;
  2084. CardAddress endAddr;
  2085. word offset;
  2086. /* Force remapping of internal catched sector */
  2087. vol.flash->socket->remapped = TRUE;
  2088. addr = unitBaseAddress(&vol,unitNo);
  2089. endAddr = addr + (1L << vol.unitSizeBits);
  2090. for (;addr < endAddr; addr += SECTOR_SIZE)
  2091. {
  2092. /* Check area a and b */
  2093. vol.flash->read(vol.flash, addr, nftlBuffer,SECTOR_SIZE, 0);
  2094. for (offset=0;offset<SECTOR_SIZE;offset+=ANAND_SPARE_SIZE)
  2095. if (tffscmp(nftlBuffer+offset, ff, ANAND_SPARE_SIZE))
  2096. return FALSE;
  2097. /* Check area c */
  2098. vol.flash->read(vol.flash, addr, nftlBuffer,ANAND_SPARE_SIZE, EXTRA);
  2099. if (tffscmp( nftlBuffer, ff, ANAND_SPARE_SIZE ))
  2100. return FALSE;
  2101. }
  2102. return TRUE;
  2103. }
  2104. /*----------------------------------------------------------------------*/
  2105. /* f o r m a t N F T L */
  2106. /* */
  2107. /* Perform NFTL Format. */
  2108. /* */
  2109. /* Parameters: */
  2110. /* volNo : Volume serial no. */
  2111. /* formatParams : Address of FormatParams structure to use */
  2112. /* flash : Flash media mounted on this socket */
  2113. /* */
  2114. /* Returns: */
  2115. /* FLStatus : 0 on success, failed otherwise */
  2116. /*----------------------------------------------------------------------*/
  2117. static FLStatus formatNFTL(unsigned volNo, TLFormatParams *formatParams, FLFlash *flash)
  2118. {
  2119. Anand vol = &vols[volNo];
  2120. long int unitSize;
  2121. unsigned long prevVirtualSize;
  2122. ANANDUnitNo iUnit, prevOrgUnit;
  2123. ANANDUnitNo noOfBootUnits=0;
  2124. ANANDBootRecord bootRecord;
  2125. int noOfBadUnits = 0;
  2126. FLStatus status = flOK;
  2127. FLBoolean forceHeaderUpdate = FALSE;
  2128. static unsigned char checkSum[EXTRA_LEN] =
  2129. { 0x4B, 0x00, 0xE2, 0x0E, 0x93, 0xF7, 0x55, 0x55 };
  2130. #ifdef EXTRA_LARGE
  2131. int moreUnitBits;
  2132. unsigned char anandFlagsTmp;
  2133. #endif /* EXTRA_LARGE */
  2134. DEBUG_PRINT(("Debug: starting NFTL format.\r\n"));
  2135. checkStatus(initNFTL(&vol,flash));
  2136. tffsset(&bootRecord,0,sizeof(ANANDBootRecord));
  2137. /* Find the medium boot record */
  2138. for (vol.orgUnit = 0; vol.orgUnit < vol.noOfUnits; vol.orgUnit++)
  2139. {
  2140. vol.flash->read(vol.flash,
  2141. unitBaseAddress(&vol,vol.orgUnit),
  2142. &bootRecord,
  2143. sizeof bootRecord,
  2144. 0);
  2145. if (tffscmp(bootRecord.bootRecordId,"ANAND",sizeof bootRecord.bootRecordId) == 0)
  2146. break;
  2147. }
  2148. #ifdef EXTRA_LARGE
  2149. if (vol.orgUnit >= vol.noOfUnits) { /* first time formatting */
  2150. bootRecord.anandFlags = 0xFF;
  2151. moreUnitBits = 0;
  2152. while( ((vol.noOfUnits >> moreUnitBits) > 4096) &&
  2153. ((vol.unitSizeBits + moreUnitBits) < MAX_UNIT_SIZE_BITS) &&
  2154. (bootRecord.anandFlags > 0xFC) ) {
  2155. moreUnitBits++;
  2156. bootRecord.anandFlags--;
  2157. }
  2158. }
  2159. moreUnitBits = ~bootRecord.anandFlags & MORE_UNIT_BITS_MASK;
  2160. if (moreUnitBits > 0) {
  2161. vol.unitSizeBits += moreUnitBits;
  2162. vol.noOfUnits >>= moreUnitBits;
  2163. vol.orgUnit >>= moreUnitBits;
  2164. }
  2165. #endif /* EXTRA_LARGE */
  2166. /* adjust number of boot area units include the EXB area */
  2167. if (formatParams->flags & FL_LEAVE_BINARY_AREA)
  2168. {
  2169. /* Leave binary area (except for the area between the old
  2170. original unit and the new one */
  2171. if (formatParams->bootImageLen >= 0)
  2172. {
  2173. noOfBootUnits += (ANANDUnitNo)((formatParams->bootImageLen - 1) >> vol.unitSizeBits) + 1;
  2174. }
  2175. else /* Leave binary area excatly as it was */
  2176. {
  2177. if (vol.orgUnit >= vol.noOfUnits) /* first time formatting */
  2178. {
  2179. noOfBootUnits = 0;
  2180. }
  2181. else
  2182. {
  2183. if (LE2(bootRecord.bootUnits) > noOfBootUnits )
  2184. noOfBootUnits = LE2(bootRecord.bootUnits);
  2185. }
  2186. }
  2187. }
  2188. else /* Actualy format binary area with a signature */
  2189. {
  2190. #ifdef WRITE_EXB_IMAGE
  2191. if (formatParams->exbLen > 0)
  2192. {
  2193. noOfBootUnits = (ANANDUnitNo)((formatParams->exbLen - 1)
  2194. >> vol.unitSizeBits) + 1;
  2195. formatParams->exbLen = noOfBootUnits;
  2196. }
  2197. else
  2198. {
  2199. formatParams->exbLen = 0;
  2200. }
  2201. #endif /* WRITE_EXB_IMAGE */
  2202. if(formatParams->noOfBinaryPartitions > 0)
  2203. {
  2204. noOfBootUnits += (ANANDUnitNo)((formatParams->binaryPartitionInfo
  2205. ->length - 1) >> vol.unitSizeBits) + 1;
  2206. }
  2207. }
  2208. prevOrgUnit = vol.orgUnit; /* save previous Original Unit */
  2209. prevVirtualSize = UNAL4(bootRecord.virtualMediumSize);
  2210. vol.bootUnits = noOfBootUnits;
  2211. vol.unitOffsetMask = (1L << vol.unitSizeBits) - 1;
  2212. vol.sectorsPerUnit = 1 << (vol.unitSizeBits - SECTOR_SIZE_BITS);
  2213. /* Add 'percentUse'% of bootUnits to transfer units */
  2214. formatParams->percentUse -= (unsigned)(((long)(100 - formatParams->percentUse) * (vol.bootUnits)) / (vol.noOfUnits - vol.bootUnits));
  2215. vol.noOfTransferUnits = (ANANDUnitNo)formatParams->noOfSpareUnits;
  2216. vol.noOfTransferUnits += (ANANDUnitNo)((long)(vol.noOfUnits - vol.bootUnits) *
  2217. (100 - formatParams->percentUse) / 100);
  2218. if (vol.noOfUnits <= vol.bootUnits + vol.noOfTransferUnits)
  2219. return flVolumeTooSmall;
  2220. unitSize = 1L << vol.unitSizeBits;
  2221. vol.noOfVirtualUnits = vol.noOfUnits-vol.bootUnits;
  2222. checkStatus(initTables(&vol));
  2223. for (iUnit = 0; iUnit < (vol.noOfUnits-vol.bootUnits); iUnit++)
  2224. vol.virtualUnits[iUnit] = ANAND_NO_UNIT;
  2225. if (vol.orgUnit >= vol.noOfUnits)
  2226. {
  2227. /* no boot record - virgin card, scan it for bad blocks */
  2228. DFORMAT_PRINT(("Virgin card rebuilding unit map.\r\n"));
  2229. prevVirtualSize = 0L;
  2230. tffsset(ff,0xff,ANAND_SPARE_SIZE);
  2231. /* Generate the bad unit table */
  2232. /* if a unit is not erased it is marked as bad */
  2233. for (iUnit = 0; iUnit < vol.noOfUnits; iUnit++)
  2234. {
  2235. vol.physicalUnits[iUnit] = (unsigned char)(isErased(&vol,iUnit) ? ANAND_UNIT_FREE : UNIT_BAD_ORIGINAL);
  2236. #ifndef NT5PORT
  2237. DFORMAT_PRINT(("Checking unit %ld\r",(CardAddress)iUnit));
  2238. #endif/*NT5PORT*/
  2239. }
  2240. DFORMAT_PRINT(("\rMedia has been scanned\r\n"));
  2241. }
  2242. else /* Read bad unit table from boot record */
  2243. {
  2244. status = vol.flash->read(vol.flash,
  2245. unitBaseAddress(&vol,vol.orgUnit) + SECTOR_SIZE,
  2246. vol.physicalUnits,
  2247. vol.noOfUnits * sizeof(ANANDPhysUnit),
  2248. EDC);
  2249. if( status != flOK ) {
  2250. dismountNFTL(&vol); /*Free tables must be done after call to initTables*/
  2251. return status;
  2252. }
  2253. }
  2254. if(vol.physicalUnits[0] == UNIT_BAD_ORIGINAL)
  2255. {
  2256. DFORMAT_PRINT(("ERROR - IPL block is bad.\r\n"));
  2257. return flBadIPLBlock;
  2258. }
  2259. /* count bad units */
  2260. vol.noOfTransferUnits += 2; /* include orgUnit & spareOrgUnit */
  2261. /* Convert first unit of MDOC of any floor > 0 to BAD in order to make it
  2262. * unchangeable and force internal EEprom mode */
  2263. if(flash->flags & EXTERNAL_EPROM)
  2264. {
  2265. long docFloorSize;
  2266. int iFloor, iPage;
  2267. docFloorSize = (flash->chipSize * flash->noOfChips) / flash->noOfFloors;
  2268. for(iFloor=1;( iFloor < flash->noOfFloors ); iFloor++)
  2269. {
  2270. iUnit = (ANANDUnitNo)((docFloorSize * (long)iFloor) >> vol.unitSizeBits);
  2271. if( vol.physicalUnits[iUnit] == ANAND_UNIT_FREE )
  2272. {
  2273. forceHeaderUpdate = TRUE; /* force writing of NFTL Header */
  2274. vol.physicalUnits[iUnit] = UNIT_BAD_ORIGINAL; /* mark as BAD */
  2275. }
  2276. status = vol.flash->erase(vol.flash,
  2277. (word)(iUnit << (vol.unitSizeBits - vol.erasableBlockSizeBits)),
  2278. (word)(1 << (vol.unitSizeBits - vol.erasableBlockSizeBits)));
  2279. if( status != flOK ) {
  2280. dismountNFTL(&vol); /*Free tables must be done after call to initTables*/
  2281. return status;
  2282. }
  2283. for(iPage=0;( iPage < 2 ); iPage++) {
  2284. status = vol.flash->write(vol.flash,
  2285. unitBaseAddress(&vol,iUnit) + iPage * SECTOR_SIZE,
  2286. (const void FAR1 *)checkSum, EXTRA_LEN, EXTRA);
  2287. if( status != flOK ) {
  2288. dismountNFTL(&vol); /*Free tables must be done after call to initTables*/
  2289. return status;
  2290. }
  2291. }
  2292. }
  2293. }
  2294. /* Translate physicalUnits[] to internal representation */
  2295. for (iUnit = 0; iUnit < vol.noOfUnits; iUnit++) {
  2296. if (vol.physicalUnits[iUnit] != ANAND_UNIT_FREE)
  2297. vol.physicalUnits[iUnit] = UNIT_BAD_MOUNT;
  2298. }
  2299. /* extend bootimage area if there are bad units in it */
  2300. for( iUnit = vol.bootUnits = 0;
  2301. (vol.bootUnits < noOfBootUnits) && (iUnit < vol.noOfUnits);
  2302. iUnit++ )
  2303. if (isAvailable(iUnit))
  2304. vol.bootUnits++;
  2305. if (vol.bootUnits < noOfBootUnits) {
  2306. dismountNFTL(&vol); /*Free tables must be done after call to initTables*/
  2307. return flVolumeTooSmall;
  2308. }
  2309. vol.bootUnits = iUnit;
  2310. /* Discount transfer units taken by the boot image */
  2311. for (iUnit = 0; iUnit < vol.bootUnits; iUnit++)
  2312. if (!isAvailable(iUnit)) {
  2313. if( vol.noOfTransferUnits <= (ANANDUnitNo)formatParams->noOfSpareUnits ) {
  2314. dismountNFTL(&vol); /*Free tables must be done after call to initTables*/
  2315. return flVolumeTooSmall;
  2316. }
  2317. vol.noOfTransferUnits--;
  2318. }
  2319. if (vol.noOfUnits <= vol.bootUnits + vol.noOfTransferUnits) {
  2320. dismountNFTL(&vol); /*Free tables must be done after call to initTables*/
  2321. return flVolumeTooSmall;
  2322. }
  2323. vol.virtualSectors = (SectorNo)((vol.noOfUnits - vol.bootUnits - vol.noOfTransferUnits) *
  2324. (unitSize / SECTOR_SIZE));
  2325. vol.noOfVirtualUnits = (unsigned short)((vol.virtualSectors + vol.sectorsPerUnit - 1) / vol.sectorsPerUnit);
  2326. /* Find a place for the boot records and protect them */
  2327. /* NOTE : We don't erase the old orgUnits, this might cause a problem
  2328. when formatting with bootImageLen = 0 and then formatting with
  2329. bootImageLen = 44Kbyte */
  2330. for (vol.orgUnit = vol.bootUnits; vol.orgUnit < vol.noOfUnits; vol.orgUnit++)
  2331. if (vol.physicalUnits[vol.orgUnit] == ANAND_UNIT_FREE)
  2332. break;
  2333. vol.physicalUnits[vol.orgUnit] = UNIT_UNAVAIL;
  2334. for (vol.spareOrgUnit = vol.orgUnit + 1;
  2335. vol.spareOrgUnit < vol.noOfUnits;
  2336. vol.spareOrgUnit++)
  2337. if (vol.physicalUnits[vol.spareOrgUnit] == ANAND_UNIT_FREE)
  2338. break;
  2339. vol.physicalUnits[vol.spareOrgUnit] = UNIT_UNAVAIL;
  2340. for (iUnit = vol.bootUnits; iUnit < vol.noOfUnits; iUnit++)
  2341. {
  2342. status = formatUnit(&vol,iUnit);
  2343. if(status == flWriteFault)
  2344. {
  2345. if ((iUnit != vol.orgUnit) && (iUnit != vol.spareOrgUnit))
  2346. {
  2347. noOfBadUnits++;
  2348. vol.physicalUnits[iUnit] = UNIT_BAD_MOUNT; /* Mark it bad in table */
  2349. if ((noOfBadUnits+2) >= vol.noOfTransferUnits)
  2350. {
  2351. dismountNFTL(&vol); /*Free tables must be done after call to initTables*/
  2352. return status;
  2353. }
  2354. }
  2355. }
  2356. else if (status != flOK)
  2357. {
  2358. dismountNFTL(&vol); /*Free tables must be done after call to initTables*/
  2359. return status;
  2360. }
  2361. if (formatParams->progressCallback)
  2362. {
  2363. status = (*formatParams->progressCallback)
  2364. ((word)(vol.noOfUnits - vol.bootUnits),
  2365. (word)((iUnit + 1) - vol.bootUnits));
  2366. if(status!=flOK)
  2367. {
  2368. dismountNFTL(&vol); /*Free tables must be done after call to initTables*/
  2369. return status;
  2370. }
  2371. }
  2372. }
  2373. /* Prepare the boot record header */
  2374. for(iUnit = 0; iUnit < vol.noOfUnits; iUnit++) { /* Convert Bad Block table to previous state */
  2375. if( vol.physicalUnits[iUnit] == UNIT_BAD_MOUNT )
  2376. vol.physicalUnits[iUnit] = UNIT_BAD_ORIGINAL;
  2377. }
  2378. #ifdef EXTRA_LARGE
  2379. anandFlagsTmp = bootRecord.anandFlags;
  2380. #endif /* EXTRA_LARGE */
  2381. tffsset(&bootRecord,0xff,sizeof bootRecord);
  2382. #ifdef EXTRA_LARGE
  2383. bootRecord.anandFlags = anandFlagsTmp;
  2384. #endif /* EXTRA_LARGE */
  2385. toLE2(bootRecord.noOfUnits,vol.noOfUnits - vol.bootUnits);
  2386. toLE2(bootRecord.bootUnits,vol.bootUnits);
  2387. tffscpy(bootRecord.bootRecordId,"ANAND",sizeof bootRecord.bootRecordId);
  2388. toUNAL4(bootRecord.virtualMediumSize,(CardAddress) vol.virtualSectors * SECTOR_SIZE);
  2389. /* Write boot records, spare unit first */
  2390. vol.physicalUnits[vol.orgUnit] = ANAND_UNIT_FREE; /* Unprotect it */
  2391. vol.physicalUnits[vol.spareOrgUnit] = ANAND_UNIT_FREE; /* Unprotect it */
  2392. if( ((prevOrgUnit != vol.orgUnit) || (forceHeaderUpdate == TRUE)) ||
  2393. (prevVirtualSize != UNAL4(bootRecord.virtualMediumSize)) )
  2394. {
  2395. /* Copy boot Record to 512 bytes buffer in order to add EDC */
  2396. tffsset(nftlBuffer,0,sizeof nftlBuffer);
  2397. tffscpy(nftlBuffer,&bootRecord,sizeof bootRecord);
  2398. /* Loop over the original unit and the spare (spare first) */
  2399. for (iUnit = vol.spareOrgUnit, prevOrgUnit = 0;
  2400. prevOrgUnit < 2 ; prevOrgUnit ++)
  2401. {
  2402. status = formatUnit(&vol,iUnit); /* Erase unit */
  2403. if(status==flOK) /* Write BBT */
  2404. {
  2405. status = vol.flash->write(vol.flash,
  2406. unitBaseAddress(&vol,iUnit) + SECTOR_SIZE,
  2407. vol.physicalUnits,
  2408. vol.noOfUnits * sizeof(ANANDPhysUnit), EDC);
  2409. }
  2410. if(status==flOK) /* Write header */
  2411. {
  2412. status = vol.flash->write(vol.flash,
  2413. unitBaseAddress(&vol,iUnit),
  2414. nftlBuffer, sizeof (nftlBuffer), EDC);
  2415. }
  2416. if(status!=flOK)
  2417. {
  2418. dismountNFTL(&vol); /*Free tables must be done after call to initTables*/
  2419. return status;
  2420. }
  2421. iUnit = vol.orgUnit;
  2422. }
  2423. }
  2424. /* Mark Binary partition with the proper signature */
  2425. if (!(formatParams->flags & FL_LEAVE_BINARY_AREA)&&
  2426. (vol.bootUnits > 0))
  2427. {
  2428. byte sign[BINARY_SIGNATURE_LEN];
  2429. /* Add SPL special Signature */
  2430. #ifdef WRITE_EXB_IMAGE
  2431. byte signOffset = 8;
  2432. tffscpy(sign,SIGN_SPL,BINARY_SIGNATURE_NAME);
  2433. #else
  2434. byte signOffset = formatParams->binaryPartitionInfo->signOffset;
  2435. tffscpy(sign,formatParams->binaryPartitionInfo->sign,
  2436. BINARY_SIGNATURE_NAME);
  2437. #endif /* WRITE_EXB_IMAGE */
  2438. tffsset(sign+BINARY_SIGNATURE_NAME,'F',BINARY_SIGNATURE_NAME);
  2439. unitSize = 1L << vol.unitSizeBits;
  2440. for (iUnit=0;iUnit<vol.bootUnits;iUnit++)
  2441. {
  2442. if ( vol.physicalUnits[iUnit] == ANAND_UNIT_FREE )
  2443. {
  2444. status = formatUnit(&vol,iUnit);
  2445. if(status != flOK)
  2446. break;
  2447. #ifdef WRITE_EXB_IMAGE
  2448. if (iUnit == formatParams->exbLen)
  2449. {
  2450. signOffset = formatParams->binaryPartitionInfo->signOffset;
  2451. tffscpy(sign,formatParams->binaryPartitionInfo->sign,
  2452. BINARY_SIGNATURE_NAME);
  2453. }
  2454. #endif /* WRITE_EXB_IMAGE */
  2455. /* Each logical unit might contain several physical blocks */
  2456. for (noOfBootUnits = 0 ;
  2457. (noOfBootUnits < unitSize) && (status == flOK) ;
  2458. noOfBootUnits += (ANANDUnitNo)vol.flash->erasableBlockSize)
  2459. {
  2460. status = vol.flash->write(vol.flash, unitBaseAddress(&vol,iUnit) +
  2461. noOfBootUnits + signOffset, sign,
  2462. BINARY_SIGNATURE_LEN,EXTRA);
  2463. }
  2464. if(status != flOK)
  2465. break;
  2466. }
  2467. #ifdef WRITE_EXB_IMAGE
  2468. else
  2469. {
  2470. formatParams->exbLen++;
  2471. }
  2472. #endif /* WRITE_EXB_IMAGE */
  2473. }
  2474. }
  2475. else /* Erase previous Original and SpareOriginal Unit */
  2476. {
  2477. for (iUnit = prevOrgUnit; iUnit < vol.orgUnit; iUnit++)
  2478. if( vol.physicalUnits[iUnit] != UNIT_BAD_ORIGINAL )
  2479. formatUnit(&vol,iUnit);
  2480. }
  2481. if (status != flOK)
  2482. {
  2483. DEBUG_PRINT(("Debug: NFTL failed while formating the binary partition.\r\n"));
  2484. }
  2485. else
  2486. {
  2487. DEBUG_PRINT(("Debug: finished NFTL format.\r\n"));
  2488. }
  2489. dismountNFTL(&vol); /*Free tables must be done after call to initTables*/
  2490. return status;
  2491. }
  2492. #endif /* FORMAT_VOLUME */
  2493. /*----------------------------------------------------------------------*/
  2494. /* N F T L I n f o */
  2495. /* */
  2496. /* get NFTL information. */
  2497. /* */
  2498. /* Parameters: */
  2499. /* volNo : Volume serial no. */
  2500. /* tlInfo : Address of TLInfo record */
  2501. /* */
  2502. /* Returns: */
  2503. /* FLStatus : 0 on success, failed otherwise */
  2504. /*----------------------------------------------------------------------*/
  2505. static FLStatus NFTLInfo(Anand vol, TLInfo *tlInfo)
  2506. {
  2507. tlInfo->sectorsInVolume = vol.virtualSectors;
  2508. tlInfo->bootAreaSize = (unsigned long)vol.bootUnits << vol.unitSizeBits;
  2509. tlInfo->eraseCycles = vol.eraseSum;
  2510. tlInfo->tlUnitBits = vol.unitSizeBits;
  2511. return flOK;
  2512. }
  2513. #ifndef NO_READ_BBT_CODE
  2514. /*----------------------------------------------------------------------*/
  2515. /* r e a d B B T */
  2516. /* */
  2517. /* Returns a pointer to the BBT of the device. */
  2518. /* Note: Bad unit are marked with a 4 bytes address of the unit. */
  2519. /* Note: A unit can contain several blocks */
  2520. /* */
  2521. /* Parameters: */
  2522. /* vol : Pointer identifying drive */
  2523. /* buf : pointer to buffer to read into */
  2524. /* */
  2525. /* Returns: */
  2526. /* FLStatus : 0 on success, failed otherwise */
  2527. /* noOfBB : returns the number of bad unit of the media */
  2528. /* meidaSize : returns the media size in bytes */
  2529. /*----------------------------------------------------------------------*/
  2530. static FLStatus readBBT(Anand vol, CardAddress FAR1 * buf,
  2531. long FAR2 * mediaSize, unsigned FAR2 * noOfBB)
  2532. {
  2533. ANANDUnitNo iUnit;
  2534. ANANDUnitNo maxBad = vol.noOfUnits * ANAND_BAD_PERCENTAGE / 100;
  2535. CardAddress FAR1* ptr = (CardAddress FAR1*) buf;
  2536. *noOfBB = 0;
  2537. for (iUnit=0;(iUnit<vol.noOfUnits);iUnit++)
  2538. {
  2539. if (vol.physicalUnits[iUnit] == UNIT_BAD_MOUNT)
  2540. {
  2541. if (*noOfBB <= maxBad)
  2542. {
  2543. *ptr = (CardAddress) iUnit << vol.unitSizeBits;
  2544. (*noOfBB)++;
  2545. ptr = (CardAddress FAR1*)flAddLongToFarPointer((byte FAR1 *)ptr,
  2546. sizeof(CardAddress));
  2547. }
  2548. else
  2549. {
  2550. DEBUG_PRINT(("Debug: ERROR to many bad blocks.\r\n"));
  2551. return flVolumeTooSmall;
  2552. }
  2553. }
  2554. }
  2555. *mediaSize = vol.noOfUnits << vol.unitSizeBits;
  2556. return flOK;
  2557. }
  2558. #endif /* NO_READ_BBT_CODE */
  2559. /*----------------------------------------------------------------------*/
  2560. /* m o u n t N F T L */
  2561. /* */
  2562. /* Mount the volume. Initialize data structures and conversion tables */
  2563. /* */
  2564. /* Parameters: */
  2565. /* volNo : Volume serial no. */
  2566. /* tl : Mounted translation layer on exit */
  2567. /* flash : Flash media mounted on this socket */
  2568. /* volForCallback : Pointer to FLFlash structure for power on */
  2569. /* callback routine. */
  2570. /* */
  2571. /* update the tlType field of the TL record to NFTL */
  2572. /* */
  2573. /* Returns: */
  2574. /* FLStatus : 0 on success, failed otherwise */
  2575. /*----------------------------------------------------------------------*/
  2576. static FLStatus mountNFTL(unsigned volNo, TL *tl, FLFlash *flash, FLFlash **volForCallback)
  2577. {
  2578. Anand vol = &vols[volNo];
  2579. ANANDUnitNo iUnit,virUnit,nextUnit;
  2580. unsigned long currEraseCount=0;
  2581. ANANDBootRecord bootRecord,spareBootRecord;
  2582. FLStatus status;
  2583. #ifdef NFTL_CACHE
  2584. unsigned long scacheSize = 0;
  2585. #endif /* NFTL_CACHE */
  2586. #ifdef EXTRA_LARGE
  2587. int moreUnitBits;
  2588. #endif /* EXTRA_LARGE */
  2589. #if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
  2590. /* Default for NFTL is FL_UPS */
  2591. flVerifyWrite[vol.socketNo][tl->partitionNo] = FL_UPS;
  2592. #endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
  2593. tffsset(&bootRecord,0,sizeof(ANANDBootRecord));
  2594. DEBUG_PRINT(("Debug: starting NFTL mount.\r\n"));
  2595. checkStatus(initNFTL(&vol,flash));
  2596. *volForCallback = vol.flash;
  2597. vol.eraseSum = 0;
  2598. /* Find the medium boot record */
  2599. for (vol.orgUnit = 0; vol.orgUnit < vol.noOfUnits; vol.orgUnit++) {
  2600. vol.flash->read(vol.flash,
  2601. unitBaseAddress(&vol,vol.orgUnit),
  2602. &bootRecord,
  2603. sizeof bootRecord,
  2604. 0);
  2605. if (tffscmp(bootRecord.bootRecordId,"ANAND",sizeof bootRecord.bootRecordId) == 0)
  2606. break;
  2607. }
  2608. if (vol.orgUnit >= vol.noOfUnits) {
  2609. DEBUG_PRINT(("Debug: not NFTL format.\r\n"));
  2610. return flUnknownMedia;
  2611. }
  2612. for (vol.spareOrgUnit = vol.orgUnit + 1;
  2613. vol.spareOrgUnit < vol.noOfUnits;
  2614. vol.spareOrgUnit++) {
  2615. vol.flash->read(vol.flash,
  2616. unitBaseAddress(&vol,vol.spareOrgUnit),
  2617. &spareBootRecord,
  2618. sizeof spareBootRecord,
  2619. 0);
  2620. if (tffscmp(spareBootRecord.bootRecordId,"ANAND",sizeof spareBootRecord.bootRecordId) == 0)
  2621. break;
  2622. }
  2623. if (vol.spareOrgUnit >= vol.noOfUnits)
  2624. vol.spareOrgUnit = ANAND_NO_UNIT;
  2625. /* Get media information from unit header */
  2626. vol.noOfUnits = LE2(bootRecord.noOfUnits);
  2627. vol.bootUnits = LE2(bootRecord.bootUnits);
  2628. vol.virtualSectors = (SectorNo)(UNAL4(bootRecord.virtualMediumSize) >> SECTOR_SIZE_BITS);
  2629. vol.noOfUnits += vol.bootUnits;
  2630. #ifdef EXTRA_LARGE
  2631. moreUnitBits = ~bootRecord.anandFlags & MORE_UNIT_BITS_MASK;
  2632. if (moreUnitBits > 0) {
  2633. vol.unitSizeBits += moreUnitBits;
  2634. vol.orgUnit >>= moreUnitBits;
  2635. if (vol.spareOrgUnit != ANAND_NO_UNIT)
  2636. vol.spareOrgUnit >>= moreUnitBits;
  2637. }
  2638. #endif /* EXTRA_LARGE */
  2639. vol.unitOffsetMask = (1L << vol.unitSizeBits) - 1;
  2640. vol.sectorsPerUnit = 1 << (vol.unitSizeBits - SECTOR_SIZE_BITS);
  2641. vol.noOfVirtualUnits = (ANANDUnitNo)((vol.virtualSectors + vol.sectorsPerUnit - 1) / vol.sectorsPerUnit);
  2642. if(((ANANDUnitNo)(vol.virtualSectors >> (vol.unitSizeBits - SECTOR_SIZE_BITS)) >
  2643. (vol.noOfUnits - vol.bootUnits)) ) {
  2644. if( vol.spareOrgUnit != ANAND_NO_UNIT ) {
  2645. vol.noOfUnits = LE2(spareBootRecord.noOfUnits);
  2646. vol.bootUnits = LE2(spareBootRecord.bootUnits);
  2647. vol.virtualSectors = (SectorNo)(UNAL4(spareBootRecord.virtualMediumSize) >> SECTOR_SIZE_BITS);
  2648. vol.noOfUnits += vol.bootUnits;
  2649. #ifdef EXTRA_LARGE
  2650. moreUnitBits = ~spareBootRecord.anandFlags & MORE_UNIT_BITS_MASK;
  2651. if (moreUnitBits > 0) {
  2652. vol.unitSizeBits += moreUnitBits;
  2653. vol.orgUnit >>= moreUnitBits;
  2654. if (vol.spareOrgUnit != ANAND_NO_UNIT)
  2655. vol.spareOrgUnit >>= moreUnitBits;
  2656. }
  2657. #endif /* EXTRA_LARGE */
  2658. vol.unitOffsetMask = (1L << vol.unitSizeBits) - 1;
  2659. vol.sectorsPerUnit = 1 << (vol.unitSizeBits - SECTOR_SIZE_BITS);
  2660. vol.noOfVirtualUnits = (ANANDUnitNo)((vol.virtualSectors + vol.sectorsPerUnit - 1) / vol.sectorsPerUnit);
  2661. if ((ANANDUnitNo)(vol.virtualSectors >> (vol.unitSizeBits - SECTOR_SIZE_BITS)) >
  2662. (vol.noOfUnits - vol.bootUnits))
  2663. return flBadFormat;
  2664. }
  2665. else
  2666. return flBadFormat;
  2667. }
  2668. checkStatus(initTables(&vol));
  2669. /* Read bad unit table from boot record */
  2670. status = vol.flash->read(vol.flash,
  2671. unitBaseAddress(&vol,vol.orgUnit) + SECTOR_SIZE,
  2672. vol.physicalUnits,
  2673. vol.noOfUnits * sizeof(ANANDPhysUnit),
  2674. EDC);
  2675. if( status != flOK ) {
  2676. if( vol.spareOrgUnit != ANAND_NO_UNIT ) {
  2677. status = vol.flash->read(vol.flash,
  2678. unitBaseAddress(&vol,vol.spareOrgUnit) + SECTOR_SIZE,
  2679. vol.physicalUnits,
  2680. vol.noOfUnits * sizeof(ANANDPhysUnit),
  2681. EDC);
  2682. if( status != flOK ) {
  2683. dismountNFTL(&vol); /* Free tables must be done after call to initTables */
  2684. return status;
  2685. }
  2686. }
  2687. else
  2688. return status;
  2689. }
  2690. /* Exclude boot-image units */
  2691. for (iUnit = 0; iUnit < vol.noOfVirtualUnits; iUnit++)
  2692. vol.virtualUnits[iUnit] = ANAND_NO_UNIT;
  2693. /* Translate bad unit table to internal representation */
  2694. for (iUnit = 0; iUnit < vol.noOfUnits; iUnit++) {
  2695. /* Exclude bad & protected units */
  2696. if (iUnit < vol.bootUnits || iUnit == vol.orgUnit || iUnit == vol.spareOrgUnit ||
  2697. vol.physicalUnits[iUnit] != ANAND_UNIT_FREE) {
  2698. if (vol.physicalUnits[iUnit] != ANAND_UNIT_FREE) {
  2699. vol.physicalUnits[iUnit] = UNIT_BAD_MOUNT;
  2700. }
  2701. else {
  2702. vol.physicalUnits[iUnit] = UNIT_UNAVAIL;
  2703. }
  2704. }
  2705. }
  2706. /* Mount all units */
  2707. for (iUnit = 0; iUnit < vol.noOfUnits; iUnit++) {
  2708. if ((vol.physicalUnits[iUnit] != UNIT_UNAVAIL) && (vol.physicalUnits[iUnit] != UNIT_BAD_MOUNT)) {
  2709. status = mountUnit(&vol,iUnit,&currEraseCount);
  2710. if(status!=flOK) {
  2711. dismountNFTL(&vol); /*Free tables must be done after call to initTables*/
  2712. return status;
  2713. }
  2714. vol.eraseSum+=currEraseCount;
  2715. }
  2716. }
  2717. /* Scan for orphan units, and count free units */
  2718. vol.freeUnits = 0;
  2719. for (iUnit = vol.bootUnits; iUnit < vol.noOfUnits; iUnit++) {
  2720. ANANDPhysUnit FAR1 *pU = &vol.physicalUnits[iUnit];
  2721. if (*pU == UNIT_ORPHAN ||
  2722. *pU == (UNIT_REPLACED | UNIT_ORPHAN)) {
  2723. formatChain(&vol,iUnit); /* Get rid of orphan */
  2724. if(iUnit == vol.invalidReplacement)
  2725. vol.invalidReplacement = ANAND_NO_UNIT;
  2726. }
  2727. else
  2728. if (*pU == (ANAND_UNIT_FREE & ~UNIT_ORPHAN))
  2729. *pU = ANAND_UNIT_FREE; /* Reference to free unit. That's OK */
  2730. }
  2731. /* Calculate Free Units again after formatChain */
  2732. vol.freeUnits = 0;
  2733. for (iUnit = vol.bootUnits; iUnit < vol.noOfUnits; iUnit++) {
  2734. if( vol.physicalUnits[iUnit] == ANAND_UNIT_FREE )
  2735. vol.freeUnits++;
  2736. }
  2737. /* Initialize allocation rover */
  2738. vol.roverUnit = vol.bootUnits;
  2739. /* Initialize statistics */
  2740. vol.sectorsRead = vol.sectorsWritten = vol.sectorsDeleted = 0;
  2741. vol.parasiteWrites = vol.unitsFolded = 0;
  2742. #ifndef FL_READ_ONLY
  2743. /*
  2744. * Make sure no unit chain with an invalid replacemenet unit
  2745. * pointer on the last unit
  2746. */
  2747. if(vol.invalidReplacement != ANAND_NO_UNIT)
  2748. {
  2749. getUnitData(&vol,vol.invalidReplacement,&virUnit,&nextUnit);
  2750. virUnit = virUnit&(~ANAND_REPLACING_UNIT);
  2751. if(virUnit >= vol.noOfVirtualUnits)
  2752. {
  2753. DEBUG_PRINT(("ERROR - a bad unit header encountered.\r\n"));
  2754. dismountNFTL(&vol);
  2755. return flBadFormat;
  2756. }
  2757. iUnit = vol.virtualUnits[virUnit];
  2758. if(iUnit >= vol.noOfUnits)
  2759. {
  2760. DEBUG_PRINT(("ERROR - a bad unit header encountered.\r\n"));
  2761. dismountNFTL(&vol);
  2762. return flBadFormat;
  2763. }
  2764. setUnavail(iUnit);
  2765. checkStatus(foldUnit(&vol,virUnit,TRUE));
  2766. }
  2767. /* Make sure there is at least 1 free unit */
  2768. if(vol.freeUnits == 0)
  2769. foldBestChain(&vol,&iUnit); /* make free units by folding the best chain */
  2770. #endif /* FL_READ_ONLY */
  2771. /* Set TL routine */
  2772. tl->rec = &vol;
  2773. tl->mapSector = mapSector;
  2774. #ifndef FL_READ_ONLY
  2775. tl->writeSector = writeSector;
  2776. tl->deleteSector = deleteSector;
  2777. #ifdef DEFRAGMENT_VOLUME
  2778. tl->defragment = defragment;
  2779. #endif
  2780. #if (defined(VERIFY_WRITE) || defined (VERIFY_VOLUME) || defined(VERIFY_ERASED_SECTOR))
  2781. tl->checkVolume = checkVolume;
  2782. #endif /* VERIFY_WRITE || VERIFY_VOLUME || VERIFY_ERASED_SECTOR */
  2783. #endif /* FL_READ_ONLY */
  2784. tl->sectorsInVolume = sectorsInVolume;
  2785. tl->getTLInfo = NFTLInfo;
  2786. tl->tlSetBusy = tlSetBusy;
  2787. tl->dismount = dismountNFTL;
  2788. #ifndef NO_READ_BBT_CODE
  2789. tl->readBBT = readBBT;
  2790. #endif /* NO_READ_BBT_CODE */
  2791. tl->writeMultiSector = NULL;
  2792. tl->readSectors = NULL;
  2793. DEBUG_PRINT(("Debug: finished NFTL mount.\r\n"));
  2794. #ifdef NFTL_CACHE
  2795. /* create and initialize ANANDUnitHeader cache */
  2796. #ifdef ENVIRONMENT_VARS
  2797. if( flUseNFTLCache == 1 ) /* behave according to the value of env variable */
  2798. #endif
  2799. {
  2800. #ifdef FL_MALLOC
  2801. vol.ucache = (ucacheEntry FAR1*) FL_FAR_MALLOC (vol.noOfUnits * sizeof(ucacheEntry));
  2802. #else
  2803. vol.ucache = vol.ucacheBuf;
  2804. #endif /* FL_MALLOC */
  2805. }
  2806. #ifdef ENVIRONMENT_VARS
  2807. else
  2808. vol.ucache = NULL;
  2809. #endif
  2810. if (vol.ucache != NULL) {
  2811. for (iUnit = 0; iUnit < vol.noOfUnits; iUnit++) {
  2812. vol.ucache[iUnit].virtualUnitNo = 0xDEAD;
  2813. vol.ucache[iUnit].replacementUnitNo = 0xDEAD;
  2814. }
  2815. }
  2816. else {
  2817. DEBUG_PRINT(("Debug: NFTL runs without U-cache\r\n"));
  2818. }
  2819. /* create and initialize SectorFlags cache */
  2820. #ifdef ENVIRONMENT_VARS
  2821. if( flUseNFTLCache == 1 ) /* behave according to the value of env variable */
  2822. #endif
  2823. {
  2824. scacheSize = (unsigned long)vol.noOfUnits << (vol.unitSizeBits - SECTOR_SIZE_BITS - 2);
  2825. #ifdef FL_MALLOC
  2826. if( (sizeof(unsigned) < sizeof(scacheSize)) &&
  2827. (scacheSize >= 0x10000L) ) /* Out of Segment Boundary */
  2828. vol.scache = NULL;
  2829. else
  2830. vol.scache = (unsigned char FAR1*) FL_FAR_MALLOC (scacheSize);
  2831. #else
  2832. vol.scache = vol.scacheBuf;
  2833. #endif /* FL_MALLOC */
  2834. }
  2835. #ifdef ENVIRONMENT_VARS
  2836. else
  2837. vol.scache = NULL;
  2838. #endif
  2839. if (vol.scache != NULL) {
  2840. /*
  2841. * Whenever SECTOR_IGNORE is found in Sector Flags cache it is double
  2842. * checked by reading actual sector flags from flash-> This is way
  2843. * all the cache entries are initially set to SECTOR_IGNORE.
  2844. */
  2845. unsigned char val = (S_CACHE_SECTOR_IGNORE << 6) | (S_CACHE_SECTOR_IGNORE << 4) |
  2846. (S_CACHE_SECTOR_IGNORE << 2) | S_CACHE_SECTOR_IGNORE;
  2847. unsigned long iC;
  2848. for(iC=0;( iC < scacheSize );iC++)
  2849. vol.scache[iC] = val;
  2850. }
  2851. else {
  2852. DEBUG_PRINT(("Debug: NFTL runs without S-cache\r\n"));
  2853. }
  2854. #endif /* NFTL_CACHE */
  2855. vol.badFormat = FALSE;
  2856. vol.wearLevel.alarm = (unsigned char)(vol.eraseSum % WLnow);
  2857. vol.wearLevel.currUnit = (ANANDUnitNo)(vol.eraseSum % vol.noOfVirtualUnits);
  2858. return flOK;
  2859. }
  2860. /*----------------------------------------------------------------------*/
  2861. /* f l R e g i s t e r N F T L */
  2862. /* */
  2863. /* Register this translation layer */
  2864. /* */
  2865. /* Parameters: */
  2866. /* None */
  2867. /* */
  2868. /* Returns: */
  2869. /* FLStatus : 0 on success, otherwise failure */
  2870. /*----------------------------------------------------------------------*/
  2871. FLStatus flRegisterNFTL(void)
  2872. {
  2873. #ifdef FL_MALLOC
  2874. unsigned i;
  2875. #endif
  2876. if (noOfTLs >= TLS)
  2877. return flTooManyComponents;
  2878. tlTable[noOfTLs].mountRoutine = mountNFTL;
  2879. #ifdef FORMAT_VOLUME
  2880. tlTable[noOfTLs].formatRoutine = formatNFTL;
  2881. #else
  2882. tlTable[noOfTLs].formatRoutine = noFormat;
  2883. #endif
  2884. noOfTLs++;
  2885. #ifdef FL_MALLOC
  2886. for(i=0;( i < VOLUMES );i++) {
  2887. vols[i].physicalUnits = NULL;
  2888. vols[i].virtualUnits = NULL;
  2889. #ifdef NFTL_CACHE
  2890. vols[i].ucache = NULL;
  2891. vols[i].scache = NULL;
  2892. #endif /* NFTL_CACHE */
  2893. }
  2894. #endif /* FL_MALLOC */
  2895. return flOK;
  2896. }
  2897. #ifndef FL_READ_ONLY
  2898. /*----------------------------------------------------------------------*/
  2899. /* m a r k A s I g n o r e d */
  2900. /* */
  2901. /* Mark sector at given address as ignored. */
  2902. /* */
  2903. /* Parameters: */
  2904. /* vol : Pointer identifying drive */
  2905. /* addr : Physical address of the sector */
  2906. /* */
  2907. /*----------------------------------------------------------------------*/
  2908. static void markAsIgnored(Anand vol,CardAddress addr)
  2909. {
  2910. #ifndef RAM_MTD
  2911. static const
  2912. #endif /* RAM_MTD */
  2913. byte sectorFlags[2] = {SECTOR_IGNORE,SECTOR_IGNORE};
  2914. DEBUG_PRINT(("markAsIgnored : A sector is being marked as ignored\r\n"));
  2915. /* Force remapping of internal catched sector */
  2916. vol.flash->socket->remapped = TRUE;
  2917. #ifdef NFTL_CACHE
  2918. setSectorFlagsCache(&vol, addr, SECTOR_IGNORE);
  2919. #endif /* NFTL_CACHE */
  2920. vol.flash->write(vol.flash,addr+SECTOR_DATA_OFFSET,sectorFlags,sizeof(sectorFlags),EXTRA);
  2921. #if MAKE_SURE_IGNORE_HAS_BAD_EDC
  2922. /* Force remapping of internal catched sector */
  2923. vol.flash->socket->remapped = TRUE;
  2924. /* Make sure EDC is wrong - a slite problem with PPP */
  2925. if(vol.flash->read(vol.flash,addr,nftlBuffer,sizeof(nftlBuffer),EDC)==flOK)
  2926. {
  2927. tffsset(nftlBuffer,0,sizeof(nftlBuffer));
  2928. vol.flash->write(vol.flash,addr,nftlBuffer,sizeof(nftlBuffer),0);
  2929. #if (defined(VERIFY_WRITE) || defined (VERIFY_VOLUME) || defined(VERIFY_ERASED_SECTOR))
  2930. /* Set all ff's for verifySector routine */
  2931. tffsset(nftlBuffer,0xff,sizeof(nftlBuffer));
  2932. #endif /* VERIFY_WRITE || VERIFY_VOLUME || VERIFY_ERASED_SECTOR */
  2933. }
  2934. #endif /* MAKE_SURE_IGNORE_HAS_BAD_EDC */
  2935. }
  2936. #if (defined(VERIFY_WRITE) || defined (VERIFY_VOLUME) || defined(VERIFY_ERASED_SECTOR))
  2937. /*----------------------------------------------------------------------*/
  2938. /* v e r i f y S e c t o r s */
  2939. /* */
  2940. /* Verify sectors for power failures simptoms and fix if neccesary. */
  2941. /* */
  2942. /* Parameters: */
  2943. /* vol : Pointer identifying drive */
  2944. /* sectorCount : No of sectors to verify */
  2945. /* */
  2946. /* Returns: */
  2947. /* FLStatus : 0 on success, failed otherwise */
  2948. /*----------------------------------------------------------------------*/
  2949. FLStatus verifySectors(Anand vol, dword sectorCount)
  2950. {
  2951. FLStatus status;
  2952. ANANDUnitNo virUnitNo;
  2953. ANANDUnitNo unitNo;
  2954. dword curRead;
  2955. CardAddress unitOffset;
  2956. CardAddress startSectorAddress;
  2957. CardAddress sourceSectorAddress;
  2958. CardAddress nextFreeSectorAddress;
  2959. byte index,sectorFlags;
  2960. byte FAR1* buffer;
  2961. if (vol.verifiedSectorNo >= vol.virtualSectors)
  2962. return flOK;
  2963. /* Initialize variables */
  2964. buffer = flReadBackBufferOf(vol.socketNo);
  2965. if(buffer==NULL)
  2966. {
  2967. DEBUG_PRINT(("\nDebug : Can not verify sectors since no buffer was allocated\r\n"));
  2968. return flOK;
  2969. }
  2970. virUnitNo = (ANANDUnitNo)(vol.verifiedSectorNo / vol.sectorsPerUnit);
  2971. sectorCount = TFFSMIN(vol.virtualSectors - vol.verifiedSectorNo,sectorCount);
  2972. /* Force remapping of internal catched sector */
  2973. vol.flash->socket->remapped = TRUE;
  2974. tffsset(nftlBuffer,0xff,sizeof(nftlBuffer));
  2975. /* Run over required number of virtual sectors */
  2976. for (; sectorCount > 0 ; virUnitNo++ ,sectorCount -= curRead)
  2977. {
  2978. /* Calculate needed number of sector in this unit */
  2979. unitOffset = (word)((vol.verifiedSectorNo % vol.sectorsPerUnit) << SECTOR_SIZE_BITS);
  2980. curRead = TFFSMIN(sectorCount,((1UL<<vol.unitSizeBits)-unitOffset)>>SECTOR_SIZE_BITS);
  2981. unitNo = vol.virtualUnits[virUnitNo];
  2982. if(unitNo == ANAND_NO_UNIT) /* Unit is empty */
  2983. {
  2984. vol.verifiedSectorNo += ((1<<vol.unitSizeBits)-unitOffset)>>SECTOR_SIZE_BITS;
  2985. continue;
  2986. }
  2987. /* Check all sector of unit or until required sectors */
  2988. startSectorAddress = unitBaseAddress(&vol,unitNo)+unitOffset;
  2989. for (index = 0 ; index < curRead ;
  2990. index++, vol.verifiedSectorNo++)
  2991. {
  2992. nextFreeSectorAddress = ANAND_UNASSIGNED_ADDRESS; /* Search end addr */
  2993. sourceSectorAddress = virtual2Physical(&vol,
  2994. vol.verifiedSectorNo,
  2995. &nextFreeSectorAddress);
  2996. if(sourceSectorAddress == ANAND_UNASSIGNED_ADDRESS) /* No written sector */
  2997. sourceSectorAddress = startSectorAddress +
  2998. ((CardAddress)index << SECTOR_SIZE_BITS);
  2999. sectorFlags = getSectorFlags(&vol,sourceSectorAddress);
  3000. if(sectorFlags == SECTOR_FREE)
  3001. {
  3002. checkStatus(vol.flash->read(vol.flash,sourceSectorAddress,buffer,SECTOR_SIZE,0));
  3003. if (tffscmp(nftlBuffer,buffer,SECTOR_SIZE)!=0)
  3004. markAsIgnored(&vol,sourceSectorAddress);
  3005. continue;
  3006. }
  3007. else /* Used sector */
  3008. {
  3009. status = vol.flash->read(vol.flash,sourceSectorAddress,buffer,SECTOR_SIZE,EDC);
  3010. switch (status)
  3011. {
  3012. case flDataError:
  3013. markAsIgnored(&vol,sourceSectorAddress);
  3014. createUnitCount(&vol,virUnitNo);
  3015. break; /* Mark as ignored */
  3016. case flOK:
  3017. break; /* Sector OK */
  3018. default:
  3019. return status; /* Report error */
  3020. }
  3021. }
  3022. /* Check the next free sector to make sure it is erased */
  3023. if(nextFreeSectorAddress != ANAND_UNASSIGNED_ADDRESS)
  3024. {
  3025. checkStatus(vol.flash->read(vol.flash,nextFreeSectorAddress,buffer,SECTOR_SIZE,0));
  3026. if (tffscmp(nftlBuffer,buffer,SECTOR_SIZE)!=0)
  3027. markAsIgnored(&vol,nextFreeSectorAddress);
  3028. }
  3029. } /* Loop over all sector of unit or until required sectors */
  3030. } /* Loop over all required sectors */
  3031. return flOK;
  3032. }
  3033. /*----------------------------------------------------------------------*/
  3034. /* c h e c k V o l u m e */
  3035. /* */
  3036. /* Scanthe entire media for partialy written sectors. */
  3037. /* */
  3038. /* Parameters: */
  3039. /* vol : Pointer identifying drive */
  3040. /* */
  3041. /* Returns: */
  3042. /* FLStatus : 0 on success, failed otherwise */
  3043. /*----------------------------------------------------------------------*/
  3044. static FLStatus checkVolume(Anand vol)
  3045. {
  3046. return verifySectors(&vol, 0xffffffff);
  3047. }
  3048. #endif /* VERIFY_WRITE || VERIFY_VOLUME || VERIFY_ERASED_SECTOR */
  3049. /*----------------------------------------------------------------------*/
  3050. /* c h e c k F o l d i n g */
  3051. /* */
  3052. /* Check folding status and if needed fold again. */
  3053. /* */
  3054. /* Parameters: */
  3055. /* vol : Pointer identifying drive */
  3056. /* virtualUnitNo : Virtual unit number to re-fold */
  3057. /* */
  3058. /* Returns: */
  3059. /* FLStatus : 0 on success, failed otherwise */
  3060. /*----------------------------------------------------------------------*/
  3061. static FLStatus checkFolding(Anand vol, ANANDUnitNo virtualUnitNo)
  3062. {
  3063. ANANDUnitNo tmp;
  3064. if(vol.freeUnits == 0)
  3065. checkStatus(foldBestChain(&vol, &tmp));
  3066. return foldUnit(&vol,virtualUnitNo,TRUE);
  3067. }
  3068. #endif /* FL_READ_ONLY */