Leaked source code of windows server 2003
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.

3511 lines
137 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. *unitNo = ANAND_NO_UNIT;
  1421. /* Loop as long as can not fold in place or until MAX_FOLDING_TRIES time */
  1422. for (maxCounter = 0 ; maxCounter < MAX_FOLDING_TRIES ; maxCounter++)
  1423. {
  1424. leastCount = vol.sectorsPerUnit + 1; /* Set to invalid sector count */
  1425. longestChain = 0; /* Set to invalid unit length */
  1426. virtualUnitNo = ANAND_NO_UNIT;
  1427. /*************************************************************/
  1428. /* Loop over all virtual units until best candidate is found */
  1429. /*************************************************************/
  1430. for (u = 0; u < vol.noOfVirtualUnits; u++)
  1431. {
  1432. /* If virtual unit does not exist continue to next unit */
  1433. firstUnitNo = vol.virtualUnits[u];
  1434. if( firstUnitNo == ANAND_NO_UNIT )
  1435. continue;
  1436. /* Make sure sector count of unit is valid */
  1437. if (vol.countsValid <= u)
  1438. {
  1439. createUnitCount(&vol,u); /* Update sector count */
  1440. vol.countsValid = u + 1;
  1441. }
  1442. if( isAvailable(firstUnitNo) ) /* store sector count */
  1443. {
  1444. unitCount = countOf(firstUnitNo);
  1445. }
  1446. else
  1447. {
  1448. unitCount = vol.sectorsPerUnit; /* set low priority */
  1449. }
  1450. /* This is an empty unit. We can simply erase it */
  1451. if (unitCount == 0)
  1452. {
  1453. leastCount = 0;
  1454. virtualUnitNo = u;
  1455. break;
  1456. }
  1457. if(/* Smallest sector count found so far */
  1458. (leastCount >= unitCount ) &&
  1459. /* And this unit is not a single unit chain */
  1460. (vol.physicalUnits[firstUnitNo] & UNIT_REPLACED) )
  1461. {
  1462. unsigned chainLength = 0;
  1463. /* Compare chain length */
  1464. ANANDUnitNo nextUnitNo = getNextUnit(&vol,firstUnitNo,u);
  1465. if(isAvailable(firstUnitNo))
  1466. {
  1467. while((nextUnitNo != ANAND_NO_UNIT ) &&
  1468. (chainLength < DOUBLE_MAX_UNIT_CHAIN))
  1469. {
  1470. chainLength++;
  1471. nextUnitNo = getNextUnit(&vol,nextUnitNo,u);
  1472. }
  1473. }
  1474. else
  1475. {
  1476. chainLength = 0; /* Set lowest priority to frozen chain */
  1477. }
  1478. /* set low priority to neverending loop chain */
  1479. if(chainLength == DOUBLE_MAX_UNIT_CHAIN)
  1480. chainLength = 0;
  1481. if((leastCount == unitCount ) && (longestChain >= chainLength))
  1482. continue;
  1483. longestChain = chainLength;
  1484. leastCount = unitCount;
  1485. virtualUnitNo = u;
  1486. } /* End - unit has less (or eqaul) no' of used sectors found so far */
  1487. } /* End - Loop over all virtual units and find best candidate */
  1488. /*************************************************************/
  1489. /* Candidate virtual chain has been chosen - try and fold it */
  1490. /*************************************************************/
  1491. if ((leastCount > vol.sectorsPerUnit) ||
  1492. (virtualUnitNo == ANAND_NO_UNIT))
  1493. {
  1494. /* Only single units chains were found */
  1495. if(maxCounter==0) /* And no chain was frozen while searching */
  1496. return flNotEnoughMemory; /* Report no space at all */
  1497. break; /* Try and fold the frozen units that have been found */
  1498. }
  1499. else /* Try and fold the candidate unit */
  1500. {
  1501. if(!isAvailable(vol.virtualUnits[virtualUnitNo])) /* This is a frozen unit */
  1502. {
  1503. /* Frozen chains have the lowest priority - stop searching */
  1504. break;
  1505. }
  1506. else /* Try and fold the unit */
  1507. {
  1508. /* Store the first unit as the new free unit */
  1509. *unitNo = vol.virtualUnits[virtualUnitNo];
  1510. /* Store number of free Units */
  1511. u = vol.freeUnits;
  1512. /* Fold the candidate unit */
  1513. status = foldUnit(&vol,virtualUnitNo,FALSE);
  1514. switch(status)
  1515. {
  1516. case flOK:
  1517. if(vol.freeUnits == u) /* Did not free any units */
  1518. continue;
  1519. break;
  1520. case flCanNotFold: /* Need to fold not in place */
  1521. continue;
  1522. default:
  1523. return status;
  1524. }
  1525. break;
  1526. }
  1527. }
  1528. } /* End MAX_FOLDING_TRIES loop */
  1529. /***************************************************************/
  1530. /* Check folding status - might need a special kind of folding */
  1531. /***************************************************************/
  1532. if(maxCounter)
  1533. {
  1534. *unitNo = ANAND_NO_UNIT;
  1535. /* Unfreeze all units */
  1536. for (u = vol.spareOrgUnit + 1; u < vol.noOfUnits; u++)
  1537. {
  1538. if(!isAvailable(u)) /* This is a frozen unit */
  1539. {
  1540. /* Get virtual unit of frozen physical unit */
  1541. getUnitData(&vol,u,&virtualUnitNo,&firstUnitNo);
  1542. if(virtualUnitNo < vol.noOfVirtualUnits)
  1543. {
  1544. /* Store the first unit as the new free unit */
  1545. firstUnitNo = vol.virtualUnits[virtualUnitNo];
  1546. /* Force folding no matter what */
  1547. if(firstUnitNo != ANAND_NO_UNIT)
  1548. {
  1549. checkStatus(foldUnit(&vol,virtualUnitNo,TRUE));
  1550. /* Recalculate sector count */
  1551. createUnitCount(&vol, virtualUnitNo);
  1552. *unitNo = firstUnitNo;
  1553. }
  1554. }
  1555. }
  1556. }
  1557. }
  1558. if((*unitNo!= ANAND_NO_UNIT) && (vol.freeUnits > 0)) /* A unit was freed */
  1559. return flOK;
  1560. else
  1561. return flGeneralFailure;
  1562. }
  1563. /*----------------------------------------------------------------------*/
  1564. /* a l l o c a t e U n i t */
  1565. /* */
  1566. /* Find a free unit to allocate, erase it if necessary. */
  1567. /* */
  1568. /* Parameters: */
  1569. /* vol : Pointer identifying drive */
  1570. /* unitNo : Receives the physical number of the allocated */
  1571. /* unit */
  1572. /* Returns: */
  1573. /* FLStatus : 0 on success, failed otherwise */
  1574. /*----------------------------------------------------------------------*/
  1575. static FLStatus allocateUnit(Anand vol, ANANDUnitNo *unitNo)
  1576. {
  1577. ANANDUnitNo originalUnit = vol.roverUnit;
  1578. FLStatus status;
  1579. if (vol.freeUnits < 2) /* Try to make sure not to use the last unit */
  1580. {
  1581. status = foldBestChain(&vol,unitNo);
  1582. if(status != flNotEnoughMemory)
  1583. return status;
  1584. }
  1585. return findFreeUnit(&vol, unitNo);
  1586. }
  1587. #endif /* FL_READ_ONLY */
  1588. /*----------------------------------------------------------------------*/
  1589. /* m a p S e c t o r */
  1590. /* */
  1591. /* Maps and returns location of a given sector no. */
  1592. /* NOTE: This function is used in place of a read-sector operation. */
  1593. /* */
  1594. /* A one-sector cache is maintained to save on map operations. */
  1595. /* */
  1596. /* Parameters: */
  1597. /* vol : Pointer identifying drive */
  1598. /* sectorNo : Sector no. to read */
  1599. /* physAddress : Optional pointer to receive sector address */
  1600. /* */
  1601. /* Returns: */
  1602. /* Pointer to physical sector location. NULL returned if sector */
  1603. /* does not exist. */
  1604. /*----------------------------------------------------------------------*/
  1605. static const void FAR0 *mapSector(Anand vol, SectorNo sectorNo, CardAddress *physAddress)
  1606. {
  1607. if (sectorNo != vol.mappedSectorNo || vol.flash->socket->remapped)
  1608. {
  1609. if (sectorNo >= vol.virtualSectors)
  1610. {
  1611. vol.mappedSector = NULL;
  1612. }
  1613. else
  1614. {
  1615. int chainBound = 0;
  1616. for(vol.mappedSectorAddress=ANAND_UNASSIGNED_ADDRESS;
  1617. chainBound<DOUBLE_MAX_UNIT_CHAIN;chainBound++)
  1618. {
  1619. CardAddress endSectorAddress = vol.mappedSectorAddress;
  1620. vol.mappedSectorAddress = virtual2Physical(&vol,sectorNo,&endSectorAddress);
  1621. if (vol.mappedSectorAddress == ANAND_UNASSIGNED_ADDRESS)
  1622. {
  1623. vol.mappedSector = NULL; /* no such sector */
  1624. break;
  1625. }
  1626. else
  1627. {
  1628. vol.mappedSector = nftlBuffer;
  1629. if (vol.flash->read(vol.flash,vol.mappedSectorAddress,nftlBuffer,SECTOR_SIZE,EDC) == flOK)
  1630. break;
  1631. }
  1632. }
  1633. vol.mappedSectorNo = sectorNo;
  1634. vol.flash->socket->remapped = FALSE;
  1635. }
  1636. }
  1637. if (physAddress)
  1638. *physAddress = vol.mappedSectorAddress;
  1639. return vol.mappedSector;
  1640. }
  1641. /* Mounting and formatting */
  1642. /*----------------------------------------------------------------------*/
  1643. /* m o u n t U n i t */
  1644. /* */
  1645. /* Mount one unit. Read the relevant data from the unit header and */
  1646. /* update the conversion tables. */
  1647. /* */
  1648. /* Parameters: */
  1649. /* vol : Pointer identifying drive */
  1650. /* unitNo : Unit to mount */
  1651. /* */
  1652. /* Returns: */
  1653. /* FLStatus : 0 on success, failed otherwise */
  1654. /*----------------------------------------------------------------------*/
  1655. static FLStatus mountUnit(Anand vol, ANANDUnitNo unitNo,
  1656. unsigned long* eraseCount)
  1657. {
  1658. ANANDUnitNo virtualUnitNo, replacementUnitNo;
  1659. unsigned short eraseMark;
  1660. ANANDPhysUnit FAR1 *pU = &vol.physicalUnits[unitNo];
  1661. getUnitData(&vol,unitNo,&virtualUnitNo,&replacementUnitNo);
  1662. getUnitTailer(&vol,unitNo,&eraseMark,eraseCount);
  1663. if (virtualUnitNo == ANAND_NO_UNIT ||
  1664. eraseMark != ERASE_MARK) { /* this unit is not assigned */
  1665. *pU = ANAND_UNIT_FREE;
  1666. }
  1667. else { /* this unit is assigned */
  1668. *pU &= UNIT_ORPHAN;
  1669. if (replacementUnitNo < vol.noOfUnits) {
  1670. *pU |= UNIT_REPLACED;
  1671. if (isAvailable(replacementUnitNo) ||
  1672. isReplaced(replacementUnitNo))
  1673. /* Mark replacement unit as non-orphan */
  1674. vol.physicalUnits[replacementUnitNo] &= ~UNIT_ORPHAN;
  1675. }
  1676. if (!(virtualUnitNo & ANAND_REPLACING_UNIT)) {
  1677. unsigned short foldMark;
  1678. ANANDUnitNo physUnitNo;
  1679. if (virtualUnitNo >= vol.noOfVirtualUnits)
  1680. return formatUnit(&vol,unitNo);
  1681. foldMark = getFoldMark(&vol,unitNo);
  1682. physUnitNo = vol.virtualUnits[virtualUnitNo];
  1683. if (foldMark == FOLDING_COMPLETE)
  1684. formatChain(&vol,unitNo);
  1685. else if (physUnitNo == ANAND_NO_UNIT || !isAvailable(physUnitNo)) {
  1686. /* If we have duplicates, it's OK if one of them is currently folded */
  1687. vol.virtualUnits[virtualUnitNo] = unitNo;
  1688. *pU &= ~UNIT_ORPHAN;
  1689. if (foldMark == FOLDING_IN_PROGRESS) {
  1690. setUnavail(unitNo);
  1691. }
  1692. if (physUnitNo != ANAND_NO_UNIT)
  1693. formatChain(&vol,physUnitNo); /* Get rid of old chain */
  1694. }
  1695. else if (foldMark == FOLDING_IN_PROGRESS)
  1696. formatChain(&vol,unitNo);
  1697. else
  1698. return flBadFormat; /* We have a duplicate to a unit that */
  1699. /* is not currently folded. That's bad. */
  1700. }
  1701. }
  1702. return flOK;
  1703. }
  1704. #ifndef FL_READ_ONLY
  1705. /*----------------------------------------------------------------------*/
  1706. /* a l l o c a t e A n d W r i t e S e c t o r */
  1707. /* */
  1708. /* Write to sectorNo. if necessary, allocate a free sector first. */
  1709. /* */
  1710. /* Parameters: */
  1711. /* vol : Pointer identifying drive */
  1712. /* sectorNo : Virtual sector no. to write */
  1713. /* fromAddress : Address of sector data. */
  1714. /* */
  1715. /* Returns: */
  1716. /* FLStatus : 0 on success, failed otherwise */
  1717. /*----------------------------------------------------------------------*/
  1718. static FLStatus allocateAndWriteSector(void* rec,
  1719. SectorNo sectorNo,
  1720. void FAR1 *fromAddress)
  1721. {
  1722. Anand vol = (Anand*)rec;
  1723. ANANDUnitNo virtualUnitNo = (ANANDUnitNo)(sectorNo / vol.sectorsPerUnit);
  1724. ANANDUnitNo firstUnitNo = vol.virtualUnits[virtualUnitNo];
  1725. ANANDUnitNo unitNo;
  1726. unsigned unitOffset = (unsigned)((sectorNo % vol.sectorsPerUnit) << SECTOR_SIZE_BITS);
  1727. unsigned unitChainLength = 0;
  1728. FLBoolean sectorExists = FALSE;
  1729. FLBoolean unitWasFoldedOutOfPlace = FALSE;
  1730. FLStatus status;
  1731. /* If we can't write to this unit, must fold it first */
  1732. if (firstUnitNo != ANAND_NO_UNIT && !isAvailable(firstUnitNo)) {
  1733. status = foldUnit(&vol,virtualUnitNo,FALSE);
  1734. switch(status)
  1735. {
  1736. case flOK:
  1737. break;
  1738. case flCanNotFold:
  1739. checkStatus(checkFolding(&vol,virtualUnitNo));
  1740. break;
  1741. default:
  1742. return status;
  1743. }
  1744. firstUnitNo = vol.virtualUnits[virtualUnitNo];
  1745. }
  1746. /* Find a unit to write this sector */
  1747. unitNo = firstUnitNo;
  1748. while ((unitNo != ANAND_NO_UNIT) && (unitChainLength < DOUBLE_MAX_UNIT_CHAIN)) {
  1749. unsigned char sectorFlags = getSectorFlags(&vol,unitBaseAddress(&vol,unitNo) + unitOffset);
  1750. if (sectorFlags == SECTOR_FREE)
  1751. break;
  1752. if (sectorFlags != SECTOR_IGNORE)
  1753. sectorExists = sectorFlags == SECTOR_USED;
  1754. unitNo = getNextUnit(&vol,unitNo,virtualUnitNo);
  1755. unitChainLength++;
  1756. }
  1757. if (unitChainLength == DOUBLE_MAX_UNIT_CHAIN) { /* unit points to itself */
  1758. unitNo = ANAND_NO_UNIT; /* force folding not in place */
  1759. setUnavail(firstUnitNo);
  1760. }
  1761. if (unitNo == ANAND_NO_UNIT) { /* Can not write in chain - must add a unit */
  1762. firstUnitNo = vol.virtualUnits[virtualUnitNo];
  1763. if (unitChainLength >= MAX_UNIT_CHAIN)
  1764. {
  1765. status = foldUnit(&vol,virtualUnitNo,FALSE);
  1766. switch(status)
  1767. {
  1768. case flOK:
  1769. break;
  1770. case flCanNotFold:
  1771. checkStatus(checkFolding(&vol,virtualUnitNo));
  1772. break;
  1773. default:
  1774. return status;
  1775. }
  1776. }
  1777. if(vol.virtualUnits[virtualUnitNo] != firstUnitNo)
  1778. {
  1779. firstUnitNo = vol.virtualUnits[virtualUnitNo];
  1780. unitWasFoldedOutOfPlace = TRUE;
  1781. }
  1782. checkStatus(allocateUnit(&vol,&unitNo));
  1783. checkStatus(assignUnit(&vol,unitNo,virtualUnitNo));
  1784. if(vol.virtualUnits[virtualUnitNo] != firstUnitNo)
  1785. {
  1786. firstUnitNo = vol.virtualUnits[virtualUnitNo];
  1787. unitWasFoldedOutOfPlace = TRUE;
  1788. }
  1789. #if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
  1790. /* Folding might have discovered that the sector we are using is invalid */
  1791. if(sectorExists) {
  1792. if( unitWasFoldedOutOfPlace ) {
  1793. /* Unit was folded out of place, so if sector exists it must be in
  1794. * the first unit of the chain
  1795. */
  1796. if(getSectorFlags(&vol,unitBaseAddress(&vol,firstUnitNo) + unitOffset)
  1797. != SECTOR_USED) {
  1798. /* The sector we saw before had bad EDC */
  1799. sectorExists = FALSE;
  1800. unitNo = firstUnitNo;
  1801. }
  1802. }
  1803. }
  1804. #endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
  1805. }
  1806. #if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
  1807. vol.curSectorWrite = sectorNo;
  1808. #endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
  1809. checkStatus(writeAndCheck(&vol,unitBaseAddress(&vol,unitNo) + unitOffset,fromAddress,EDC));
  1810. if (vol.countsValid > virtualUnitNo) {
  1811. if (unitNo != firstUnitNo && !(vol.physicalUnits[unitNo] & UNIT_REPLACED)) {
  1812. if (countOf(unitNo) < UNIT_MAX_COUNT) /* Increment block count */
  1813. vol.physicalUnits[unitNo]++;
  1814. else
  1815. return flGeneralFailure;
  1816. if (sectorExists) /* Decrement block count */
  1817. {
  1818. if (countOf(firstUnitNo) > 0)
  1819. vol.physicalUnits[firstUnitNo]--;
  1820. else
  1821. return flGeneralFailure;
  1822. }
  1823. }
  1824. else if (!sectorExists) {
  1825. if (countOf(firstUnitNo) < UNIT_MAX_COUNT) /* Increment block count */
  1826. vol.physicalUnits[firstUnitNo]++;
  1827. else
  1828. return flGeneralFailure;
  1829. }
  1830. }
  1831. return flOK;
  1832. }
  1833. /*----------------------------------------------------------------------*/
  1834. /* w r i t e S e c t o r */
  1835. /* */
  1836. /* Writes a sector. */
  1837. /* */
  1838. /* Parameters: */
  1839. /* vol : Pointer identifying drive */
  1840. /* sectorNo : Virtual sector no. to write */
  1841. /* fromAddress : Data to write */
  1842. /* */
  1843. /* Returns: */
  1844. /* FLStatus : 0 on success, failed otherwise */
  1845. /*----------------------------------------------------------------------*/
  1846. static FLStatus writeSector(Anand vol, SectorNo sectorNo, void FAR1 *fromAddress)
  1847. {
  1848. FLStatus status = flWriteFault;
  1849. int i;
  1850. if (vol.badFormat)
  1851. return flBadFormat;
  1852. if (sectorNo >= vol.virtualSectors)
  1853. return flSectorNotFound;
  1854. if(vol.wearLevel.currUnit!=ANAND_NO_UNIT) {
  1855. vol.wearLevel.alarm++;
  1856. if(vol.wearLevel.alarm>=WLnow) {
  1857. vol.wearLevel.alarm = 0;
  1858. checkStatus(swapUnits(&vol));
  1859. }
  1860. }
  1861. if (sectorNo == vol.mappedSectorNo)
  1862. {
  1863. /* Force remapping of internal catched sector */
  1864. vol.flash->socket->remapped = TRUE;
  1865. }
  1866. vol.sectorsWritten++;
  1867. for (i = 0; i < 4 && status == flWriteFault; i++) {
  1868. if (vol.mappedSectorNo == sectorNo)
  1869. vol.mappedSectorNo = UNASSIGNED_SECTOR;
  1870. status = allocateAndWriteSector(&vol,sectorNo,fromAddress);
  1871. }
  1872. return status;
  1873. }
  1874. /*----------------------------------------------------------------------*/
  1875. /* d e l e t e S e c t o r */
  1876. /* */
  1877. /* Marks contiguous sectors as deleted. */
  1878. /* */
  1879. /* Parameters: */
  1880. /* vol : Pointer identifying drive */
  1881. /* sectorNo : First sector no. to delete */
  1882. /* noOfSectors : No. of sectors to delete */
  1883. /* */
  1884. /* Returns: */
  1885. /* FLStatus : 0 on success, failed otherwise */
  1886. /*----------------------------------------------------------------------*/
  1887. static FLStatus deleteSector(Anand vol, SectorNo sectorNo, SectorNo noOfSectors)
  1888. {
  1889. SectorNo iSector;
  1890. FLStatus status;
  1891. if (vol.badFormat)
  1892. return flBadFormat;
  1893. if (sectorNo + noOfSectors > vol.virtualSectors)
  1894. return flSectorNotFound;
  1895. for (iSector = 0; iSector < noOfSectors; iSector++, sectorNo++,
  1896. vol.sectorsDeleted++) {
  1897. CardAddress sectorAddress = virtual2Physical(&vol,sectorNo,NULL);
  1898. if (sectorAddress != ANAND_UNASSIGNED_ADDRESS) {
  1899. byte sectorFlags[2];
  1900. ANANDUnitNo currUnitNo;
  1901. /* Check that the unit is writable, and if not, fold it first */
  1902. ANANDUnitNo virtualUnitNo = (ANANDUnitNo)(sectorNo / vol.sectorsPerUnit);
  1903. ANANDUnitNo unitNo = vol.virtualUnits[virtualUnitNo];
  1904. if (!isAvailable(unitNo)) {
  1905. status = foldUnit(&vol,virtualUnitNo,FALSE);
  1906. switch(status)
  1907. {
  1908. case flOK:
  1909. break;
  1910. case flCanNotFold:
  1911. checkStatus(checkFolding(&vol,virtualUnitNo));
  1912. break;
  1913. default:
  1914. return status;
  1915. }
  1916. sectorAddress = virtual2Physical(&vol,sectorNo,NULL);
  1917. }
  1918. /* Mark sector deleted */
  1919. sectorFlags[0] = sectorFlags[1] = SECTOR_DELETED;
  1920. #ifdef NFTL_CACHE
  1921. setSectorFlagsCache(&vol, sectorAddress, SECTOR_DELETED);
  1922. #ifdef ENVIRONMENT_VARS
  1923. if (((flMarkDeleteOnFlash == FL_ON) &&
  1924. (flPolicy[vol.socketNo][vol.flash->socket->curPartition] != FL_COMPLETE_ASAP)) ||
  1925. (vol.scache == NULL))
  1926. #endif /* ENVIRONMENT_VARS */
  1927. #endif
  1928. vol.flash->write(vol.flash,
  1929. sectorAddress + SECTOR_DATA_OFFSET,
  1930. #ifndef NT5PORT
  1931. &sectorFlags,
  1932. #else /*NT5PORT*/
  1933. sectorFlags,
  1934. #endif /*NT5PORT*/
  1935. sizeof sectorFlags,
  1936. EXTRA);
  1937. currUnitNo = (ANANDUnitNo)(sectorAddress >> vol.unitSizeBits);
  1938. if ( isAvailable(currUnitNo) ) {
  1939. if (vol.physicalUnits[currUnitNo] & UNIT_REPLACED)
  1940. currUnitNo = vol.virtualUnits[virtualUnitNo];
  1941. if (vol.countsValid > virtualUnitNo) {
  1942. if (countOf(currUnitNo) > 0)
  1943. vol.physicalUnits[currUnitNo]--; /* Decrement block count */
  1944. else
  1945. return flGeneralFailure;
  1946. }
  1947. }
  1948. }
  1949. }
  1950. return flOK;
  1951. }
  1952. #endif /* FL_READ_ONLY */
  1953. /*----------------------------------------------------------------------*/
  1954. /* t l S e t B u s y */
  1955. /* */
  1956. /* Notifies the start and end of a file-system operation. */
  1957. /* */
  1958. /* Parameters: */
  1959. /* vol : Pointer identifying drive */
  1960. /* state : FL_ON (1) = operation entry */
  1961. /* FL_OFF(0) = operation exit */
  1962. /* */
  1963. /* Returns: */
  1964. /* FLStatus : 0 on success, failed otherwise */
  1965. /*----------------------------------------------------------------------*/
  1966. static FLStatus tlSetBusy(Anand vol, FLBoolean state)
  1967. {
  1968. return flOK;
  1969. }
  1970. #ifndef FL_READ_ONLY
  1971. #ifdef DEFRAGMENT_VOLUME
  1972. /*----------------------------------------------------------------------*/
  1973. /* d e f r a g m e n t */
  1974. /* */
  1975. /* Performs unit allocations to arrange a minimum number of writable */
  1976. /* sectors. */
  1977. /* */
  1978. /* Parameters: */
  1979. /* vol : Pointer identifying drive */
  1980. /* sectorsNeeded : Minimum required sectors */
  1981. /* */
  1982. /* Returns: */
  1983. /* FLStatus : 0 on success, failed otherwise */
  1984. /*----------------------------------------------------------------------*/
  1985. static FLStatus defragment(Anand vol, long FAR2 *sectorsNeeded)
  1986. {
  1987. ANANDUnitNo dummyUnitNo, firstFreeUnit = ANAND_NO_UNIT;
  1988. FLBoolean firstRound = TRUE;
  1989. FLStatus status = flOK;
  1990. if( (*sectorsNeeded) == -1 ) { /* fold single chain */
  1991. if (vol.badFormat)
  1992. return flBadFormat;
  1993. status = foldBestChain(&vol,&dummyUnitNo);
  1994. if( (status != flOK) && (vol.freeUnits == 0) )
  1995. return status;
  1996. *sectorsNeeded = vol.freeUnits * vol.sectorsPerUnit;
  1997. return flOK;
  1998. }
  1999. while ((SectorNo)vol.freeUnits * vol.sectorsPerUnit < ((SectorNo)(*sectorsNeeded))) {
  2000. if (vol.badFormat)
  2001. return flBadFormat;
  2002. status = allocateUnit(&vol,&dummyUnitNo);
  2003. if( status != flOK )
  2004. break;
  2005. if (firstRound) { /* remember the first free unit */
  2006. firstFreeUnit = dummyUnitNo;
  2007. firstRound = FALSE;
  2008. }
  2009. else if (firstFreeUnit == dummyUnitNo) {
  2010. /* We have wrapped around, all the units that were marked as free */
  2011. /* are now erased, and we still don't have enough space. */
  2012. status = foldBestChain(&vol,&dummyUnitNo); /* make more free units */
  2013. if( status != flOK )
  2014. break;
  2015. }
  2016. }
  2017. *sectorsNeeded = (long)vol.freeUnits * vol.sectorsPerUnit;
  2018. return status;
  2019. }
  2020. #endif /* DEFRAGMENT_VOLUME */
  2021. #endif /* FL_READ_ONLY */
  2022. /*----------------------------------------------------------------------*/
  2023. /* s e c t o r s I n V o l u m e */
  2024. /* */
  2025. /* Gets the total number of sectors in the volume */
  2026. /* */
  2027. /* Parameters: */
  2028. /* vol : Pointer identifying drive */
  2029. /* */
  2030. /* Returns: */
  2031. /* Number of sectors in the volume */
  2032. /*----------------------------------------------------------------------*/
  2033. static SectorNo sectorsInVolume(Anand vol)
  2034. {
  2035. return vol.virtualSectors;
  2036. }
  2037. /*----------------------------------------------------------------------*/
  2038. /* d i s m o u n t N F T L */
  2039. /* */
  2040. /* Dismount NFTL volume */
  2041. /* */
  2042. /* Parameters: */
  2043. /* vol : Pointer identifying drive */
  2044. /* */
  2045. /*----------------------------------------------------------------------*/
  2046. static void dismountNFTL(Anand vol)
  2047. {
  2048. #ifdef FL_MALLOC
  2049. if( vol.physicalUnits != NULL )
  2050. FL_FAR_FREE (vol.physicalUnits);
  2051. if( vol.virtualUnits != NULL )
  2052. FL_FAR_FREE (vol.virtualUnits);
  2053. vol.physicalUnits = NULL;
  2054. vol.virtualUnits = NULL;
  2055. #ifdef NFTL_CACHE
  2056. if( vol.ucache != NULL )
  2057. FL_FAR_FREE (vol.ucache);
  2058. if( vol.scache != NULL )
  2059. FL_FAR_FREE (vol.scache);
  2060. vol.ucache = NULL;
  2061. vol.scache = NULL;
  2062. #endif /* NFTL_CACHE */
  2063. #endif /* FL_MALLOC */
  2064. }
  2065. Anand* getAnandRec(unsigned driveNo)
  2066. {
  2067. return (&vols[driveNo]);
  2068. }
  2069. #ifdef FORMAT_VOLUME
  2070. /*----------------------------------------------------------------------*/
  2071. /* i s E r a s e d U n i t */
  2072. /* */
  2073. /* Check if a unit is erased. */
  2074. /* */
  2075. /* Parameters: */
  2076. /* vol : Pointer identifying drive */
  2077. /* unitNo : unit to check */
  2078. /* */
  2079. /* Returns: */
  2080. /* TRUE if unit is erased, FALSE otherwise */
  2081. /*----------------------------------------------------------------------*/
  2082. static FLBoolean isErased(Anand vol, ANANDUnitNo unitNo)
  2083. {
  2084. CardAddress addr;
  2085. CardAddress endAddr;
  2086. word offset;
  2087. /* Force remapping of internal catched sector */
  2088. vol.flash->socket->remapped = TRUE;
  2089. addr = unitBaseAddress(&vol,unitNo);
  2090. endAddr = addr + (1L << vol.unitSizeBits);
  2091. for (;addr < endAddr; addr += SECTOR_SIZE)
  2092. {
  2093. /* Check area a and b */
  2094. vol.flash->read(vol.flash, addr, nftlBuffer,SECTOR_SIZE, 0);
  2095. for (offset=0;offset<SECTOR_SIZE;offset+=ANAND_SPARE_SIZE)
  2096. if (tffscmp(nftlBuffer+offset, ff, ANAND_SPARE_SIZE))
  2097. return FALSE;
  2098. /* Check area c */
  2099. vol.flash->read(vol.flash, addr, nftlBuffer,ANAND_SPARE_SIZE, EXTRA);
  2100. if (tffscmp( nftlBuffer, ff, ANAND_SPARE_SIZE ))
  2101. return FALSE;
  2102. }
  2103. return TRUE;
  2104. }
  2105. /*----------------------------------------------------------------------*/
  2106. /* f o r m a t N F T L */
  2107. /* */
  2108. /* Perform NFTL Format. */
  2109. /* */
  2110. /* Parameters: */
  2111. /* volNo : Volume serial no. */
  2112. /* formatParams : Address of FormatParams structure to use */
  2113. /* flash : Flash media mounted on this socket */
  2114. /* */
  2115. /* Returns: */
  2116. /* FLStatus : 0 on success, failed otherwise */
  2117. /*----------------------------------------------------------------------*/
  2118. static FLStatus formatNFTL(unsigned volNo, TLFormatParams *formatParams, FLFlash *flash)
  2119. {
  2120. Anand vol = &vols[volNo];
  2121. long int unitSize;
  2122. unsigned long prevVirtualSize;
  2123. ANANDUnitNo iUnit, prevOrgUnit;
  2124. ANANDUnitNo noOfBootUnits=0;
  2125. ANANDBootRecord bootRecord;
  2126. int noOfBadUnits = 0;
  2127. FLStatus status = flOK;
  2128. FLBoolean forceHeaderUpdate = FALSE;
  2129. static unsigned char checkSum[EXTRA_LEN] =
  2130. { 0x4B, 0x00, 0xE2, 0x0E, 0x93, 0xF7, 0x55, 0x55 };
  2131. #ifdef EXTRA_LARGE
  2132. int moreUnitBits;
  2133. unsigned char anandFlagsTmp;
  2134. #endif /* EXTRA_LARGE */
  2135. DEBUG_PRINT(("Debug: starting NFTL format.\r\n"));
  2136. checkStatus(initNFTL(&vol,flash));
  2137. tffsset(&bootRecord,0,sizeof(ANANDBootRecord));
  2138. /* Find the medium boot record */
  2139. for (vol.orgUnit = 0; vol.orgUnit < vol.noOfUnits; vol.orgUnit++)
  2140. {
  2141. vol.flash->read(vol.flash,
  2142. unitBaseAddress(&vol,vol.orgUnit),
  2143. &bootRecord,
  2144. sizeof bootRecord,
  2145. 0);
  2146. if (tffscmp(bootRecord.bootRecordId,"ANAND",sizeof bootRecord.bootRecordId) == 0)
  2147. break;
  2148. }
  2149. #ifdef EXTRA_LARGE
  2150. if (vol.orgUnit >= vol.noOfUnits) { /* first time formatting */
  2151. bootRecord.anandFlags = 0xFF;
  2152. moreUnitBits = 0;
  2153. while( ((vol.noOfUnits >> moreUnitBits) > 4096) &&
  2154. ((vol.unitSizeBits + moreUnitBits) < MAX_UNIT_SIZE_BITS) &&
  2155. (bootRecord.anandFlags > 0xFC) ) {
  2156. moreUnitBits++;
  2157. bootRecord.anandFlags--;
  2158. }
  2159. }
  2160. moreUnitBits = ~bootRecord.anandFlags & MORE_UNIT_BITS_MASK;
  2161. if (moreUnitBits > 0) {
  2162. vol.unitSizeBits += moreUnitBits;
  2163. vol.noOfUnits >>= moreUnitBits;
  2164. vol.orgUnit >>= moreUnitBits;
  2165. }
  2166. #endif /* EXTRA_LARGE */
  2167. /* adjust number of boot area units include the EXB area */
  2168. if (formatParams->flags & FL_LEAVE_BINARY_AREA)
  2169. {
  2170. /* Leave binary area (except for the area between the old
  2171. original unit and the new one */
  2172. if (formatParams->bootImageLen >= 0)
  2173. {
  2174. noOfBootUnits += (ANANDUnitNo)((formatParams->bootImageLen - 1) >> vol.unitSizeBits) + 1;
  2175. }
  2176. else /* Leave binary area excatly as it was */
  2177. {
  2178. if (vol.orgUnit >= vol.noOfUnits) /* first time formatting */
  2179. {
  2180. noOfBootUnits = 0;
  2181. }
  2182. else
  2183. {
  2184. if (LE2(bootRecord.bootUnits) > noOfBootUnits )
  2185. noOfBootUnits = LE2(bootRecord.bootUnits);
  2186. }
  2187. }
  2188. }
  2189. else /* Actualy format binary area with a signature */
  2190. {
  2191. #ifdef WRITE_EXB_IMAGE
  2192. if (formatParams->exbLen > 0)
  2193. {
  2194. noOfBootUnits = (ANANDUnitNo)((formatParams->exbLen - 1)
  2195. >> vol.unitSizeBits) + 1;
  2196. formatParams->exbLen = noOfBootUnits;
  2197. }
  2198. else
  2199. {
  2200. formatParams->exbLen = 0;
  2201. }
  2202. #endif /* WRITE_EXB_IMAGE */
  2203. if(formatParams->noOfBinaryPartitions > 0)
  2204. {
  2205. noOfBootUnits += (ANANDUnitNo)((formatParams->binaryPartitionInfo
  2206. ->length - 1) >> vol.unitSizeBits) + 1;
  2207. }
  2208. }
  2209. prevOrgUnit = vol.orgUnit; /* save previous Original Unit */
  2210. prevVirtualSize = UNAL4(bootRecord.virtualMediumSize);
  2211. vol.bootUnits = noOfBootUnits;
  2212. vol.unitOffsetMask = (1L << vol.unitSizeBits) - 1;
  2213. vol.sectorsPerUnit = 1 << (vol.unitSizeBits - SECTOR_SIZE_BITS);
  2214. /* Add 'percentUse'% of bootUnits to transfer units */
  2215. formatParams->percentUse -= (unsigned)(((long)(100 - formatParams->percentUse) * (vol.bootUnits)) / (vol.noOfUnits - vol.bootUnits));
  2216. vol.noOfTransferUnits = (ANANDUnitNo)formatParams->noOfSpareUnits;
  2217. vol.noOfTransferUnits += (ANANDUnitNo)((long)(vol.noOfUnits - vol.bootUnits) *
  2218. (100 - formatParams->percentUse) / 100);
  2219. if (vol.noOfUnits <= vol.bootUnits + vol.noOfTransferUnits)
  2220. return flVolumeTooSmall;
  2221. unitSize = 1L << vol.unitSizeBits;
  2222. vol.noOfVirtualUnits = vol.noOfUnits-vol.bootUnits;
  2223. checkStatus(initTables(&vol));
  2224. for (iUnit = 0; iUnit < (vol.noOfUnits-vol.bootUnits); iUnit++)
  2225. vol.virtualUnits[iUnit] = ANAND_NO_UNIT;
  2226. if (vol.orgUnit >= vol.noOfUnits)
  2227. {
  2228. /* no boot record - virgin card, scan it for bad blocks */
  2229. DFORMAT_PRINT(("Virgin card rebuilding unit map.\r\n"));
  2230. prevVirtualSize = 0L;
  2231. tffsset(ff,0xff,ANAND_SPARE_SIZE);
  2232. /* Generate the bad unit table */
  2233. /* if a unit is not erased it is marked as bad */
  2234. for (iUnit = 0; iUnit < vol.noOfUnits; iUnit++)
  2235. {
  2236. vol.physicalUnits[iUnit] = (unsigned char)(isErased(&vol,iUnit) ? ANAND_UNIT_FREE : UNIT_BAD_ORIGINAL);
  2237. #ifndef NT5PORT
  2238. DFORMAT_PRINT(("Checking unit %ld\r",(CardAddress)iUnit));
  2239. #endif/*NT5PORT*/
  2240. }
  2241. DFORMAT_PRINT(("\rMedia has been scanned\r\n"));
  2242. }
  2243. else /* Read bad unit table from boot record */
  2244. {
  2245. status = vol.flash->read(vol.flash,
  2246. unitBaseAddress(&vol,vol.orgUnit) + SECTOR_SIZE,
  2247. vol.physicalUnits,
  2248. vol.noOfUnits * sizeof(ANANDPhysUnit),
  2249. EDC);
  2250. if( status != flOK ) {
  2251. dismountNFTL(&vol); /*Free tables must be done after call to initTables*/
  2252. return status;
  2253. }
  2254. }
  2255. if(vol.physicalUnits[0] == UNIT_BAD_ORIGINAL)
  2256. {
  2257. DFORMAT_PRINT(("ERROR - IPL block is bad.\r\n"));
  2258. return flBadIPLBlock;
  2259. }
  2260. /* count bad units */
  2261. vol.noOfTransferUnits += 2; /* include orgUnit & spareOrgUnit */
  2262. /* Convert first unit of MDOC of any floor > 0 to BAD in order to make it
  2263. * unchangeable and force internal EEprom mode */
  2264. if(flash->flags & EXTERNAL_EPROM)
  2265. {
  2266. long docFloorSize;
  2267. int iFloor, iPage;
  2268. docFloorSize = (flash->chipSize * flash->noOfChips) / flash->noOfFloors;
  2269. for(iFloor=1;( iFloor < flash->noOfFloors ); iFloor++)
  2270. {
  2271. iUnit = (ANANDUnitNo)((docFloorSize * (long)iFloor) >> vol.unitSizeBits);
  2272. if( vol.physicalUnits[iUnit] == ANAND_UNIT_FREE )
  2273. {
  2274. forceHeaderUpdate = TRUE; /* force writing of NFTL Header */
  2275. vol.physicalUnits[iUnit] = UNIT_BAD_ORIGINAL; /* mark as BAD */
  2276. }
  2277. status = vol.flash->erase(vol.flash,
  2278. (word)(iUnit << (vol.unitSizeBits - vol.erasableBlockSizeBits)),
  2279. (word)(1 << (vol.unitSizeBits - vol.erasableBlockSizeBits)));
  2280. if( status != flOK ) {
  2281. dismountNFTL(&vol); /*Free tables must be done after call to initTables*/
  2282. return status;
  2283. }
  2284. for(iPage=0;( iPage < 2 ); iPage++) {
  2285. status = vol.flash->write(vol.flash,
  2286. unitBaseAddress(&vol,iUnit) + iPage * SECTOR_SIZE,
  2287. (const void FAR1 *)checkSum, EXTRA_LEN, EXTRA);
  2288. if( status != flOK ) {
  2289. dismountNFTL(&vol); /*Free tables must be done after call to initTables*/
  2290. return status;
  2291. }
  2292. }
  2293. }
  2294. }
  2295. /* Translate physicalUnits[] to internal representation */
  2296. for (iUnit = 0; iUnit < vol.noOfUnits; iUnit++) {
  2297. if (vol.physicalUnits[iUnit] != ANAND_UNIT_FREE)
  2298. vol.physicalUnits[iUnit] = UNIT_BAD_MOUNT;
  2299. }
  2300. /* extend bootimage area if there are bad units in it */
  2301. for( iUnit = vol.bootUnits = 0;
  2302. (vol.bootUnits < noOfBootUnits) && (iUnit < vol.noOfUnits);
  2303. iUnit++ )
  2304. if (isAvailable(iUnit))
  2305. vol.bootUnits++;
  2306. if (vol.bootUnits < noOfBootUnits) {
  2307. dismountNFTL(&vol); /*Free tables must be done after call to initTables*/
  2308. return flVolumeTooSmall;
  2309. }
  2310. vol.bootUnits = iUnit;
  2311. /* Discount transfer units taken by the boot image */
  2312. for (iUnit = 0; iUnit < vol.bootUnits; iUnit++)
  2313. if (!isAvailable(iUnit)) {
  2314. if( vol.noOfTransferUnits <= (ANANDUnitNo)formatParams->noOfSpareUnits ) {
  2315. dismountNFTL(&vol); /*Free tables must be done after call to initTables*/
  2316. return flVolumeTooSmall;
  2317. }
  2318. vol.noOfTransferUnits--;
  2319. }
  2320. if (vol.noOfUnits <= vol.bootUnits + vol.noOfTransferUnits) {
  2321. dismountNFTL(&vol); /*Free tables must be done after call to initTables*/
  2322. return flVolumeTooSmall;
  2323. }
  2324. vol.virtualSectors = (SectorNo)((vol.noOfUnits - vol.bootUnits - vol.noOfTransferUnits) *
  2325. (unitSize / SECTOR_SIZE));
  2326. vol.noOfVirtualUnits = (unsigned short)((vol.virtualSectors + vol.sectorsPerUnit - 1) / vol.sectorsPerUnit);
  2327. /* Find a place for the boot records and protect them */
  2328. /* NOTE : We don't erase the old orgUnits, this might cause a problem
  2329. when formatting with bootImageLen = 0 and then formatting with
  2330. bootImageLen = 44Kbyte */
  2331. for (vol.orgUnit = vol.bootUnits; vol.orgUnit < vol.noOfUnits; vol.orgUnit++)
  2332. if (vol.physicalUnits[vol.orgUnit] == ANAND_UNIT_FREE)
  2333. break;
  2334. vol.physicalUnits[vol.orgUnit] = UNIT_UNAVAIL;
  2335. for (vol.spareOrgUnit = vol.orgUnit + 1;
  2336. vol.spareOrgUnit < vol.noOfUnits;
  2337. vol.spareOrgUnit++)
  2338. if (vol.physicalUnits[vol.spareOrgUnit] == ANAND_UNIT_FREE)
  2339. break;
  2340. vol.physicalUnits[vol.spareOrgUnit] = UNIT_UNAVAIL;
  2341. for (iUnit = vol.bootUnits; iUnit < vol.noOfUnits; iUnit++)
  2342. {
  2343. status = formatUnit(&vol,iUnit);
  2344. if(status == flWriteFault)
  2345. {
  2346. if ((iUnit != vol.orgUnit) && (iUnit != vol.spareOrgUnit))
  2347. {
  2348. noOfBadUnits++;
  2349. vol.physicalUnits[iUnit] = UNIT_BAD_MOUNT; /* Mark it bad in table */
  2350. if ((noOfBadUnits+2) >= vol.noOfTransferUnits)
  2351. {
  2352. dismountNFTL(&vol); /*Free tables must be done after call to initTables*/
  2353. return status;
  2354. }
  2355. }
  2356. }
  2357. else if (status != flOK)
  2358. {
  2359. dismountNFTL(&vol); /*Free tables must be done after call to initTables*/
  2360. return status;
  2361. }
  2362. if (formatParams->progressCallback)
  2363. {
  2364. status = (*formatParams->progressCallback)
  2365. ((word)(vol.noOfUnits - vol.bootUnits),
  2366. (word)((iUnit + 1) - vol.bootUnits));
  2367. if(status!=flOK)
  2368. {
  2369. dismountNFTL(&vol); /*Free tables must be done after call to initTables*/
  2370. return status;
  2371. }
  2372. }
  2373. }
  2374. /* Prepare the boot record header */
  2375. for(iUnit = 0; iUnit < vol.noOfUnits; iUnit++) { /* Convert Bad Block table to previous state */
  2376. if( vol.physicalUnits[iUnit] == UNIT_BAD_MOUNT )
  2377. vol.physicalUnits[iUnit] = UNIT_BAD_ORIGINAL;
  2378. }
  2379. #ifdef EXTRA_LARGE
  2380. anandFlagsTmp = bootRecord.anandFlags;
  2381. #endif /* EXTRA_LARGE */
  2382. tffsset(&bootRecord,0xff,sizeof bootRecord);
  2383. #ifdef EXTRA_LARGE
  2384. bootRecord.anandFlags = anandFlagsTmp;
  2385. #endif /* EXTRA_LARGE */
  2386. toLE2(bootRecord.noOfUnits,vol.noOfUnits - vol.bootUnits);
  2387. toLE2(bootRecord.bootUnits,vol.bootUnits);
  2388. tffscpy(bootRecord.bootRecordId,"ANAND",sizeof bootRecord.bootRecordId);
  2389. toUNAL4(bootRecord.virtualMediumSize,(CardAddress) vol.virtualSectors * SECTOR_SIZE);
  2390. /* Write boot records, spare unit first */
  2391. vol.physicalUnits[vol.orgUnit] = ANAND_UNIT_FREE; /* Unprotect it */
  2392. vol.physicalUnits[vol.spareOrgUnit] = ANAND_UNIT_FREE; /* Unprotect it */
  2393. if( ((prevOrgUnit != vol.orgUnit) || (forceHeaderUpdate == TRUE)) ||
  2394. (prevVirtualSize != UNAL4(bootRecord.virtualMediumSize)) )
  2395. {
  2396. /* Copy boot Record to 512 bytes buffer in order to add EDC */
  2397. tffsset(nftlBuffer,0,sizeof nftlBuffer);
  2398. tffscpy(nftlBuffer,&bootRecord,sizeof bootRecord);
  2399. /* Loop over the original unit and the spare (spare first) */
  2400. for (iUnit = vol.spareOrgUnit, prevOrgUnit = 0;
  2401. prevOrgUnit < 2 ; prevOrgUnit ++)
  2402. {
  2403. status = formatUnit(&vol,iUnit); /* Erase unit */
  2404. if(status==flOK) /* Write BBT */
  2405. {
  2406. status = vol.flash->write(vol.flash,
  2407. unitBaseAddress(&vol,iUnit) + SECTOR_SIZE,
  2408. vol.physicalUnits,
  2409. vol.noOfUnits * sizeof(ANANDPhysUnit), EDC);
  2410. }
  2411. if(status==flOK) /* Write header */
  2412. {
  2413. status = vol.flash->write(vol.flash,
  2414. unitBaseAddress(&vol,iUnit),
  2415. nftlBuffer, sizeof (nftlBuffer), EDC);
  2416. }
  2417. if(status!=flOK)
  2418. {
  2419. dismountNFTL(&vol); /*Free tables must be done after call to initTables*/
  2420. return status;
  2421. }
  2422. iUnit = vol.orgUnit;
  2423. }
  2424. }
  2425. /* Mark Binary partition with the proper signature */
  2426. if (!(formatParams->flags & FL_LEAVE_BINARY_AREA)&&
  2427. (vol.bootUnits > 0))
  2428. {
  2429. byte sign[BINARY_SIGNATURE_LEN];
  2430. /* Add SPL special Signature */
  2431. #ifdef WRITE_EXB_IMAGE
  2432. byte signOffset = 8;
  2433. tffscpy(sign,SIGN_SPL,BINARY_SIGNATURE_NAME);
  2434. #else
  2435. byte signOffset = formatParams->binaryPartitionInfo->signOffset;
  2436. tffscpy(sign,formatParams->binaryPartitionInfo->sign,
  2437. BINARY_SIGNATURE_NAME);
  2438. #endif /* WRITE_EXB_IMAGE */
  2439. tffsset(sign+BINARY_SIGNATURE_NAME,'F',BINARY_SIGNATURE_NAME);
  2440. unitSize = 1L << vol.unitSizeBits;
  2441. for (iUnit=0;iUnit<vol.bootUnits;iUnit++)
  2442. {
  2443. if ( vol.physicalUnits[iUnit] == ANAND_UNIT_FREE )
  2444. {
  2445. status = formatUnit(&vol,iUnit);
  2446. if(status != flOK)
  2447. break;
  2448. #ifdef WRITE_EXB_IMAGE
  2449. if (iUnit == formatParams->exbLen)
  2450. {
  2451. signOffset = formatParams->binaryPartitionInfo->signOffset;
  2452. tffscpy(sign,formatParams->binaryPartitionInfo->sign,
  2453. BINARY_SIGNATURE_NAME);
  2454. }
  2455. #endif /* WRITE_EXB_IMAGE */
  2456. /* Each logical unit might contain several physical blocks */
  2457. for (noOfBootUnits = 0 ;
  2458. (noOfBootUnits < unitSize) && (status == flOK) ;
  2459. noOfBootUnits += (ANANDUnitNo)vol.flash->erasableBlockSize)
  2460. {
  2461. status = vol.flash->write(vol.flash, unitBaseAddress(&vol,iUnit) +
  2462. noOfBootUnits + signOffset, sign,
  2463. BINARY_SIGNATURE_LEN,EXTRA);
  2464. }
  2465. if(status != flOK)
  2466. break;
  2467. }
  2468. #ifdef WRITE_EXB_IMAGE
  2469. else
  2470. {
  2471. formatParams->exbLen++;
  2472. }
  2473. #endif /* WRITE_EXB_IMAGE */
  2474. }
  2475. }
  2476. else /* Erase previous Original and SpareOriginal Unit */
  2477. {
  2478. for (iUnit = prevOrgUnit; iUnit < vol.orgUnit; iUnit++)
  2479. if( vol.physicalUnits[iUnit] != UNIT_BAD_ORIGINAL )
  2480. formatUnit(&vol,iUnit);
  2481. }
  2482. if (status != flOK)
  2483. {
  2484. DEBUG_PRINT(("Debug: NFTL failed while formating the binary partition.\r\n"));
  2485. }
  2486. else
  2487. {
  2488. DEBUG_PRINT(("Debug: finished NFTL format.\r\n"));
  2489. }
  2490. dismountNFTL(&vol); /*Free tables must be done after call to initTables*/
  2491. return status;
  2492. }
  2493. #endif /* FORMAT_VOLUME */
  2494. /*----------------------------------------------------------------------*/
  2495. /* N F T L I n f o */
  2496. /* */
  2497. /* get NFTL information. */
  2498. /* */
  2499. /* Parameters: */
  2500. /* volNo : Volume serial no. */
  2501. /* tlInfo : Address of TLInfo record */
  2502. /* */
  2503. /* Returns: */
  2504. /* FLStatus : 0 on success, failed otherwise */
  2505. /*----------------------------------------------------------------------*/
  2506. static FLStatus NFTLInfo(Anand vol, TLInfo *tlInfo)
  2507. {
  2508. tlInfo->sectorsInVolume = vol.virtualSectors;
  2509. tlInfo->bootAreaSize = (unsigned long)vol.bootUnits << vol.unitSizeBits;
  2510. tlInfo->eraseCycles = vol.eraseSum;
  2511. tlInfo->tlUnitBits = vol.unitSizeBits;
  2512. return flOK;
  2513. }
  2514. #ifndef NO_READ_BBT_CODE
  2515. /*----------------------------------------------------------------------*/
  2516. /* r e a d B B T */
  2517. /* */
  2518. /* Returns a pointer to the BBT of the device. */
  2519. /* Note: Bad unit are marked with a 4 bytes address of the unit. */
  2520. /* Note: A unit can contain several blocks */
  2521. /* */
  2522. /* Parameters: */
  2523. /* vol : Pointer identifying drive */
  2524. /* buf : pointer to buffer to read into */
  2525. /* */
  2526. /* Returns: */
  2527. /* FLStatus : 0 on success, failed otherwise */
  2528. /* noOfBB : returns the number of bad unit of the media */
  2529. /* meidaSize : returns the media size in bytes */
  2530. /*----------------------------------------------------------------------*/
  2531. static FLStatus readBBT(Anand vol, CardAddress FAR1 * buf,
  2532. long FAR2 * mediaSize, unsigned FAR2 * noOfBB)
  2533. {
  2534. ANANDUnitNo iUnit;
  2535. ANANDUnitNo maxBad = vol.noOfUnits * ANAND_BAD_PERCENTAGE / 100;
  2536. CardAddress FAR1* ptr = (CardAddress FAR1*) buf;
  2537. *noOfBB = 0;
  2538. for (iUnit=0;(iUnit<vol.noOfUnits);iUnit++)
  2539. {
  2540. if (vol.physicalUnits[iUnit] == UNIT_BAD_MOUNT)
  2541. {
  2542. if (*noOfBB <= maxBad)
  2543. {
  2544. *ptr = (CardAddress) iUnit << vol.unitSizeBits;
  2545. (*noOfBB)++;
  2546. ptr = (CardAddress FAR1*)flAddLongToFarPointer((byte FAR1 *)ptr,
  2547. sizeof(CardAddress));
  2548. }
  2549. else
  2550. {
  2551. DEBUG_PRINT(("Debug: ERROR to many bad blocks.\r\n"));
  2552. return flVolumeTooSmall;
  2553. }
  2554. }
  2555. }
  2556. *mediaSize = vol.noOfUnits << vol.unitSizeBits;
  2557. return flOK;
  2558. }
  2559. #endif /* NO_READ_BBT_CODE */
  2560. /*----------------------------------------------------------------------*/
  2561. /* m o u n t N F T L */
  2562. /* */
  2563. /* Mount the volume. Initialize data structures and conversion tables */
  2564. /* */
  2565. /* Parameters: */
  2566. /* volNo : Volume serial no. */
  2567. /* tl : Mounted translation layer on exit */
  2568. /* flash : Flash media mounted on this socket */
  2569. /* volForCallback : Pointer to FLFlash structure for power on */
  2570. /* callback routine. */
  2571. /* */
  2572. /* update the tlType field of the TL record to NFTL */
  2573. /* */
  2574. /* Returns: */
  2575. /* FLStatus : 0 on success, failed otherwise */
  2576. /*----------------------------------------------------------------------*/
  2577. static FLStatus mountNFTL(unsigned volNo, TL *tl, FLFlash *flash, FLFlash **volForCallback)
  2578. {
  2579. Anand vol = &vols[volNo];
  2580. ANANDUnitNo iUnit,virUnit,nextUnit;
  2581. unsigned long currEraseCount=0;
  2582. ANANDBootRecord bootRecord,spareBootRecord;
  2583. FLStatus status;
  2584. #ifdef NFTL_CACHE
  2585. unsigned long scacheSize = 0;
  2586. #endif /* NFTL_CACHE */
  2587. #ifdef EXTRA_LARGE
  2588. int moreUnitBits;
  2589. #endif /* EXTRA_LARGE */
  2590. #if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
  2591. /* Default for NFTL is FL_UPS */
  2592. flVerifyWrite[vol.socketNo][tl->partitionNo] = FL_UPS;
  2593. #endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
  2594. tffsset(&bootRecord,0,sizeof(ANANDBootRecord));
  2595. DEBUG_PRINT(("Debug: starting NFTL mount.\r\n"));
  2596. checkStatus(initNFTL(&vol,flash));
  2597. *volForCallback = vol.flash;
  2598. vol.eraseSum = 0;
  2599. /* Find the medium boot record */
  2600. for (vol.orgUnit = 0; vol.orgUnit < vol.noOfUnits; vol.orgUnit++) {
  2601. vol.flash->read(vol.flash,
  2602. unitBaseAddress(&vol,vol.orgUnit),
  2603. &bootRecord,
  2604. sizeof bootRecord,
  2605. 0);
  2606. if (tffscmp(bootRecord.bootRecordId,"ANAND",sizeof bootRecord.bootRecordId) == 0)
  2607. break;
  2608. }
  2609. if (vol.orgUnit >= vol.noOfUnits) {
  2610. DEBUG_PRINT(("Debug: not NFTL format.\r\n"));
  2611. return flUnknownMedia;
  2612. }
  2613. for (vol.spareOrgUnit = vol.orgUnit + 1;
  2614. vol.spareOrgUnit < vol.noOfUnits;
  2615. vol.spareOrgUnit++) {
  2616. vol.flash->read(vol.flash,
  2617. unitBaseAddress(&vol,vol.spareOrgUnit),
  2618. &spareBootRecord,
  2619. sizeof spareBootRecord,
  2620. 0);
  2621. if (tffscmp(spareBootRecord.bootRecordId,"ANAND",sizeof spareBootRecord.bootRecordId) == 0)
  2622. break;
  2623. }
  2624. if (vol.spareOrgUnit >= vol.noOfUnits)
  2625. vol.spareOrgUnit = ANAND_NO_UNIT;
  2626. /* Get media information from unit header */
  2627. vol.noOfUnits = LE2(bootRecord.noOfUnits);
  2628. vol.bootUnits = LE2(bootRecord.bootUnits);
  2629. vol.virtualSectors = (SectorNo)(UNAL4(bootRecord.virtualMediumSize) >> SECTOR_SIZE_BITS);
  2630. vol.noOfUnits += vol.bootUnits;
  2631. #ifdef EXTRA_LARGE
  2632. moreUnitBits = ~bootRecord.anandFlags & MORE_UNIT_BITS_MASK;
  2633. if (moreUnitBits > 0) {
  2634. vol.unitSizeBits += moreUnitBits;
  2635. vol.orgUnit >>= moreUnitBits;
  2636. if (vol.spareOrgUnit != ANAND_NO_UNIT)
  2637. vol.spareOrgUnit >>= moreUnitBits;
  2638. }
  2639. #endif /* EXTRA_LARGE */
  2640. vol.unitOffsetMask = (1L << vol.unitSizeBits) - 1;
  2641. vol.sectorsPerUnit = 1 << (vol.unitSizeBits - SECTOR_SIZE_BITS);
  2642. vol.noOfVirtualUnits = (ANANDUnitNo)((vol.virtualSectors + vol.sectorsPerUnit - 1) / vol.sectorsPerUnit);
  2643. if(((ANANDUnitNo)(vol.virtualSectors >> (vol.unitSizeBits - SECTOR_SIZE_BITS)) >
  2644. (vol.noOfUnits - vol.bootUnits)) ) {
  2645. if( vol.spareOrgUnit != ANAND_NO_UNIT ) {
  2646. vol.noOfUnits = LE2(spareBootRecord.noOfUnits);
  2647. vol.bootUnits = LE2(spareBootRecord.bootUnits);
  2648. vol.virtualSectors = (SectorNo)(UNAL4(spareBootRecord.virtualMediumSize) >> SECTOR_SIZE_BITS);
  2649. vol.noOfUnits += vol.bootUnits;
  2650. #ifdef EXTRA_LARGE
  2651. moreUnitBits = ~spareBootRecord.anandFlags & MORE_UNIT_BITS_MASK;
  2652. if (moreUnitBits > 0) {
  2653. vol.unitSizeBits += moreUnitBits;
  2654. vol.orgUnit >>= moreUnitBits;
  2655. if (vol.spareOrgUnit != ANAND_NO_UNIT)
  2656. vol.spareOrgUnit >>= moreUnitBits;
  2657. }
  2658. #endif /* EXTRA_LARGE */
  2659. vol.unitOffsetMask = (1L << vol.unitSizeBits) - 1;
  2660. vol.sectorsPerUnit = 1 << (vol.unitSizeBits - SECTOR_SIZE_BITS);
  2661. vol.noOfVirtualUnits = (ANANDUnitNo)((vol.virtualSectors + vol.sectorsPerUnit - 1) / vol.sectorsPerUnit);
  2662. if ((ANANDUnitNo)(vol.virtualSectors >> (vol.unitSizeBits - SECTOR_SIZE_BITS)) >
  2663. (vol.noOfUnits - vol.bootUnits))
  2664. return flBadFormat;
  2665. }
  2666. else
  2667. return flBadFormat;
  2668. }
  2669. checkStatus(initTables(&vol));
  2670. /* Read bad unit table from boot record */
  2671. status = vol.flash->read(vol.flash,
  2672. unitBaseAddress(&vol,vol.orgUnit) + SECTOR_SIZE,
  2673. vol.physicalUnits,
  2674. vol.noOfUnits * sizeof(ANANDPhysUnit),
  2675. EDC);
  2676. if( status != flOK ) {
  2677. if( vol.spareOrgUnit != ANAND_NO_UNIT ) {
  2678. status = vol.flash->read(vol.flash,
  2679. unitBaseAddress(&vol,vol.spareOrgUnit) + SECTOR_SIZE,
  2680. vol.physicalUnits,
  2681. vol.noOfUnits * sizeof(ANANDPhysUnit),
  2682. EDC);
  2683. if( status != flOK ) {
  2684. dismountNFTL(&vol); /* Free tables must be done after call to initTables */
  2685. return status;
  2686. }
  2687. }
  2688. else
  2689. return status;
  2690. }
  2691. /* Exclude boot-image units */
  2692. for (iUnit = 0; iUnit < vol.noOfVirtualUnits; iUnit++)
  2693. vol.virtualUnits[iUnit] = ANAND_NO_UNIT;
  2694. /* Translate bad unit table to internal representation */
  2695. for (iUnit = 0; iUnit < vol.noOfUnits; iUnit++) {
  2696. /* Exclude bad & protected units */
  2697. if (iUnit < vol.bootUnits || iUnit == vol.orgUnit || iUnit == vol.spareOrgUnit ||
  2698. vol.physicalUnits[iUnit] != ANAND_UNIT_FREE) {
  2699. if (vol.physicalUnits[iUnit] != ANAND_UNIT_FREE) {
  2700. vol.physicalUnits[iUnit] = UNIT_BAD_MOUNT;
  2701. }
  2702. else {
  2703. vol.physicalUnits[iUnit] = UNIT_UNAVAIL;
  2704. }
  2705. }
  2706. }
  2707. /* Mount all units */
  2708. for (iUnit = 0; iUnit < vol.noOfUnits; iUnit++) {
  2709. if ((vol.physicalUnits[iUnit] != UNIT_UNAVAIL) && (vol.physicalUnits[iUnit] != UNIT_BAD_MOUNT)) {
  2710. status = mountUnit(&vol,iUnit,&currEraseCount);
  2711. if(status!=flOK) {
  2712. dismountNFTL(&vol); /*Free tables must be done after call to initTables*/
  2713. return status;
  2714. }
  2715. vol.eraseSum+=currEraseCount;
  2716. }
  2717. }
  2718. /* Scan for orphan units, and count free units */
  2719. vol.freeUnits = 0;
  2720. for (iUnit = vol.bootUnits; iUnit < vol.noOfUnits; iUnit++) {
  2721. ANANDPhysUnit FAR1 *pU = &vol.physicalUnits[iUnit];
  2722. if (*pU == UNIT_ORPHAN ||
  2723. *pU == (UNIT_REPLACED | UNIT_ORPHAN)) {
  2724. formatChain(&vol,iUnit); /* Get rid of orphan */
  2725. if(iUnit == vol.invalidReplacement)
  2726. vol.invalidReplacement = ANAND_NO_UNIT;
  2727. }
  2728. else
  2729. if (*pU == (ANAND_UNIT_FREE & ~UNIT_ORPHAN))
  2730. *pU = ANAND_UNIT_FREE; /* Reference to free unit. That's OK */
  2731. }
  2732. /* Calculate Free Units again after formatChain */
  2733. vol.freeUnits = 0;
  2734. for (iUnit = vol.bootUnits; iUnit < vol.noOfUnits; iUnit++) {
  2735. if( vol.physicalUnits[iUnit] == ANAND_UNIT_FREE )
  2736. vol.freeUnits++;
  2737. }
  2738. /* Initialize allocation rover */
  2739. vol.roverUnit = vol.bootUnits;
  2740. /* Initialize statistics */
  2741. vol.sectorsRead = vol.sectorsWritten = vol.sectorsDeleted = 0;
  2742. vol.parasiteWrites = vol.unitsFolded = 0;
  2743. #ifndef FL_READ_ONLY
  2744. /*
  2745. * Make sure no unit chain with an invalid replacemenet unit
  2746. * pointer on the last unit
  2747. */
  2748. if(vol.invalidReplacement != ANAND_NO_UNIT)
  2749. {
  2750. getUnitData(&vol,vol.invalidReplacement,&virUnit,&nextUnit);
  2751. virUnit = virUnit&(~ANAND_REPLACING_UNIT);
  2752. if(virUnit >= vol.noOfVirtualUnits)
  2753. {
  2754. DEBUG_PRINT(("ERROR - a bad unit header encountered.\r\n"));
  2755. dismountNFTL(&vol);
  2756. return flBadFormat;
  2757. }
  2758. iUnit = vol.virtualUnits[virUnit];
  2759. if(iUnit >= vol.noOfUnits)
  2760. {
  2761. DEBUG_PRINT(("ERROR - a bad unit header encountered.\r\n"));
  2762. dismountNFTL(&vol);
  2763. return flBadFormat;
  2764. }
  2765. setUnavail(iUnit);
  2766. checkStatus(foldUnit(&vol,virUnit,TRUE));
  2767. }
  2768. /* Make sure there is at least 1 free unit */
  2769. if(vol.freeUnits == 0)
  2770. foldBestChain(&vol,&iUnit); /* make free units by folding the best chain */
  2771. #endif /* FL_READ_ONLY */
  2772. /* Set TL routine */
  2773. tl->rec = &vol;
  2774. tl->mapSector = mapSector;
  2775. #ifndef FL_READ_ONLY
  2776. tl->writeSector = writeSector;
  2777. tl->deleteSector = deleteSector;
  2778. #ifdef DEFRAGMENT_VOLUME
  2779. tl->defragment = defragment;
  2780. #endif
  2781. #if (defined(VERIFY_WRITE) || defined (VERIFY_VOLUME) || defined(VERIFY_ERASED_SECTOR))
  2782. tl->checkVolume = checkVolume;
  2783. #endif /* VERIFY_WRITE || VERIFY_VOLUME || VERIFY_ERASED_SECTOR */
  2784. #endif /* FL_READ_ONLY */
  2785. tl->sectorsInVolume = sectorsInVolume;
  2786. tl->getTLInfo = NFTLInfo;
  2787. tl->tlSetBusy = tlSetBusy;
  2788. tl->dismount = dismountNFTL;
  2789. #ifndef NO_READ_BBT_CODE
  2790. tl->readBBT = readBBT;
  2791. #endif /* NO_READ_BBT_CODE */
  2792. tl->writeMultiSector = NULL;
  2793. tl->readSectors = NULL;
  2794. DEBUG_PRINT(("Debug: finished NFTL mount.\r\n"));
  2795. #ifdef NFTL_CACHE
  2796. /* create and initialize ANANDUnitHeader cache */
  2797. #ifdef ENVIRONMENT_VARS
  2798. if( flUseNFTLCache == 1 ) /* behave according to the value of env variable */
  2799. #endif
  2800. {
  2801. #ifdef FL_MALLOC
  2802. vol.ucache = (ucacheEntry FAR1*) FL_FAR_MALLOC (vol.noOfUnits * sizeof(ucacheEntry));
  2803. #else
  2804. vol.ucache = vol.ucacheBuf;
  2805. #endif /* FL_MALLOC */
  2806. }
  2807. #ifdef ENVIRONMENT_VARS
  2808. else
  2809. vol.ucache = NULL;
  2810. #endif
  2811. if (vol.ucache != NULL) {
  2812. for (iUnit = 0; iUnit < vol.noOfUnits; iUnit++) {
  2813. vol.ucache[iUnit].virtualUnitNo = 0xDEAD;
  2814. vol.ucache[iUnit].replacementUnitNo = 0xDEAD;
  2815. }
  2816. }
  2817. else {
  2818. DEBUG_PRINT(("Debug: NFTL runs without U-cache\r\n"));
  2819. }
  2820. /* create and initialize SectorFlags cache */
  2821. #ifdef ENVIRONMENT_VARS
  2822. if( flUseNFTLCache == 1 ) /* behave according to the value of env variable */
  2823. #endif
  2824. {
  2825. scacheSize = (unsigned long)vol.noOfUnits << (vol.unitSizeBits - SECTOR_SIZE_BITS - 2);
  2826. #ifdef FL_MALLOC
  2827. if( (sizeof(unsigned) < sizeof(scacheSize)) &&
  2828. (scacheSize >= 0x10000L) ) /* Out of Segment Boundary */
  2829. vol.scache = NULL;
  2830. else
  2831. vol.scache = (unsigned char FAR1*) FL_FAR_MALLOC (scacheSize);
  2832. #else
  2833. vol.scache = vol.scacheBuf;
  2834. #endif /* FL_MALLOC */
  2835. }
  2836. #ifdef ENVIRONMENT_VARS
  2837. else
  2838. vol.scache = NULL;
  2839. #endif
  2840. if (vol.scache != NULL) {
  2841. /*
  2842. * Whenever SECTOR_IGNORE is found in Sector Flags cache it is double
  2843. * checked by reading actual sector flags from flash-> This is way
  2844. * all the cache entries are initially set to SECTOR_IGNORE.
  2845. */
  2846. unsigned char val = (S_CACHE_SECTOR_IGNORE << 6) | (S_CACHE_SECTOR_IGNORE << 4) |
  2847. (S_CACHE_SECTOR_IGNORE << 2) | S_CACHE_SECTOR_IGNORE;
  2848. unsigned long iC;
  2849. for(iC=0;( iC < scacheSize );iC++)
  2850. vol.scache[iC] = val;
  2851. }
  2852. else {
  2853. DEBUG_PRINT(("Debug: NFTL runs without S-cache\r\n"));
  2854. }
  2855. #endif /* NFTL_CACHE */
  2856. vol.badFormat = FALSE;
  2857. vol.wearLevel.alarm = (unsigned char)(vol.eraseSum % WLnow);
  2858. vol.wearLevel.currUnit = (ANANDUnitNo)(vol.eraseSum % vol.noOfVirtualUnits);
  2859. return flOK;
  2860. }
  2861. /*----------------------------------------------------------------------*/
  2862. /* f l R e g i s t e r N F T L */
  2863. /* */
  2864. /* Register this translation layer */
  2865. /* */
  2866. /* Parameters: */
  2867. /* None */
  2868. /* */
  2869. /* Returns: */
  2870. /* FLStatus : 0 on success, otherwise failure */
  2871. /*----------------------------------------------------------------------*/
  2872. FLStatus flRegisterNFTL(void)
  2873. {
  2874. #ifdef FL_MALLOC
  2875. unsigned i;
  2876. #endif
  2877. if (noOfTLs >= TLS)
  2878. return flTooManyComponents;
  2879. tlTable[noOfTLs].mountRoutine = mountNFTL;
  2880. #ifdef FORMAT_VOLUME
  2881. tlTable[noOfTLs].formatRoutine = formatNFTL;
  2882. #else
  2883. tlTable[noOfTLs].formatRoutine = noFormat;
  2884. #endif
  2885. noOfTLs++;
  2886. #ifdef FL_MALLOC
  2887. for(i=0;( i < VOLUMES );i++) {
  2888. vols[i].physicalUnits = NULL;
  2889. vols[i].virtualUnits = NULL;
  2890. #ifdef NFTL_CACHE
  2891. vols[i].ucache = NULL;
  2892. vols[i].scache = NULL;
  2893. #endif /* NFTL_CACHE */
  2894. }
  2895. #endif /* FL_MALLOC */
  2896. return flOK;
  2897. }
  2898. #ifndef FL_READ_ONLY
  2899. /*----------------------------------------------------------------------*/
  2900. /* m a r k A s I g n o r e d */
  2901. /* */
  2902. /* Mark sector at given address as ignored. */
  2903. /* */
  2904. /* Parameters: */
  2905. /* vol : Pointer identifying drive */
  2906. /* addr : Physical address of the sector */
  2907. /* */
  2908. /*----------------------------------------------------------------------*/
  2909. static void markAsIgnored(Anand vol,CardAddress addr)
  2910. {
  2911. #ifndef RAM_MTD
  2912. static const
  2913. #endif /* RAM_MTD */
  2914. byte sectorFlags[2] = {SECTOR_IGNORE,SECTOR_IGNORE};
  2915. DEBUG_PRINT(("markAsIgnored : A sector is being marked as ignored\r\n"));
  2916. /* Force remapping of internal catched sector */
  2917. vol.flash->socket->remapped = TRUE;
  2918. #ifdef NFTL_CACHE
  2919. setSectorFlagsCache(&vol, addr, SECTOR_IGNORE);
  2920. #endif /* NFTL_CACHE */
  2921. vol.flash->write(vol.flash,addr+SECTOR_DATA_OFFSET,sectorFlags,sizeof(sectorFlags),EXTRA);
  2922. #if MAKE_SURE_IGNORE_HAS_BAD_EDC
  2923. /* Force remapping of internal catched sector */
  2924. vol.flash->socket->remapped = TRUE;
  2925. /* Make sure EDC is wrong - a slite problem with PPP */
  2926. if(vol.flash->read(vol.flash,addr,nftlBuffer,sizeof(nftlBuffer),EDC)==flOK)
  2927. {
  2928. tffsset(nftlBuffer,0,sizeof(nftlBuffer));
  2929. vol.flash->write(vol.flash,addr,nftlBuffer,sizeof(nftlBuffer),0);
  2930. #if (defined(VERIFY_WRITE) || defined (VERIFY_VOLUME) || defined(VERIFY_ERASED_SECTOR))
  2931. /* Set all ff's for verifySector routine */
  2932. tffsset(nftlBuffer,0xff,sizeof(nftlBuffer));
  2933. #endif /* VERIFY_WRITE || VERIFY_VOLUME || VERIFY_ERASED_SECTOR */
  2934. }
  2935. #endif /* MAKE_SURE_IGNORE_HAS_BAD_EDC */
  2936. }
  2937. #if (defined(VERIFY_WRITE) || defined (VERIFY_VOLUME) || defined(VERIFY_ERASED_SECTOR))
  2938. /*----------------------------------------------------------------------*/
  2939. /* v e r i f y S e c t o r s */
  2940. /* */
  2941. /* Verify sectors for power failures simptoms and fix if neccesary. */
  2942. /* */
  2943. /* Parameters: */
  2944. /* vol : Pointer identifying drive */
  2945. /* sectorCount : No of sectors to verify */
  2946. /* */
  2947. /* Returns: */
  2948. /* FLStatus : 0 on success, failed otherwise */
  2949. /*----------------------------------------------------------------------*/
  2950. FLStatus verifySectors(Anand vol, dword sectorCount)
  2951. {
  2952. FLStatus status;
  2953. ANANDUnitNo virUnitNo;
  2954. ANANDUnitNo unitNo;
  2955. dword curRead;
  2956. CardAddress unitOffset;
  2957. CardAddress startSectorAddress;
  2958. CardAddress sourceSectorAddress;
  2959. CardAddress nextFreeSectorAddress;
  2960. byte index,sectorFlags;
  2961. byte FAR1* buffer;
  2962. if (vol.verifiedSectorNo >= vol.virtualSectors)
  2963. return flOK;
  2964. /* Initialize variables */
  2965. buffer = flReadBackBufferOf(vol.socketNo);
  2966. if(buffer==NULL)
  2967. {
  2968. DEBUG_PRINT(("\nDebug : Can not verify sectors since no buffer was allocated\r\n"));
  2969. return flOK;
  2970. }
  2971. virUnitNo = (ANANDUnitNo)(vol.verifiedSectorNo / vol.sectorsPerUnit);
  2972. sectorCount = TFFSMIN(vol.virtualSectors - vol.verifiedSectorNo,sectorCount);
  2973. /* Force remapping of internal catched sector */
  2974. vol.flash->socket->remapped = TRUE;
  2975. tffsset(nftlBuffer,0xff,sizeof(nftlBuffer));
  2976. /* Run over required number of virtual sectors */
  2977. for (; sectorCount > 0 ; virUnitNo++ ,sectorCount -= curRead)
  2978. {
  2979. /* Calculate needed number of sector in this unit */
  2980. unitOffset = (word)((vol.verifiedSectorNo % vol.sectorsPerUnit) << SECTOR_SIZE_BITS);
  2981. curRead = TFFSMIN(sectorCount,((1UL<<vol.unitSizeBits)-unitOffset)>>SECTOR_SIZE_BITS);
  2982. unitNo = vol.virtualUnits[virUnitNo];
  2983. if(unitNo == ANAND_NO_UNIT) /* Unit is empty */
  2984. {
  2985. vol.verifiedSectorNo += ((1<<vol.unitSizeBits)-unitOffset)>>SECTOR_SIZE_BITS;
  2986. continue;
  2987. }
  2988. /* Check all sector of unit or until required sectors */
  2989. startSectorAddress = unitBaseAddress(&vol,unitNo)+unitOffset;
  2990. for (index = 0 ; index < curRead ;
  2991. index++, vol.verifiedSectorNo++)
  2992. {
  2993. nextFreeSectorAddress = ANAND_UNASSIGNED_ADDRESS; /* Search end addr */
  2994. sourceSectorAddress = virtual2Physical(&vol,
  2995. vol.verifiedSectorNo,
  2996. &nextFreeSectorAddress);
  2997. if(sourceSectorAddress == ANAND_UNASSIGNED_ADDRESS) /* No written sector */
  2998. sourceSectorAddress = startSectorAddress +
  2999. ((CardAddress)index << SECTOR_SIZE_BITS);
  3000. sectorFlags = getSectorFlags(&vol,sourceSectorAddress);
  3001. if(sectorFlags == SECTOR_FREE)
  3002. {
  3003. checkStatus(vol.flash->read(vol.flash,sourceSectorAddress,buffer,SECTOR_SIZE,0));
  3004. if (tffscmp(nftlBuffer,buffer,SECTOR_SIZE)!=0)
  3005. markAsIgnored(&vol,sourceSectorAddress);
  3006. continue;
  3007. }
  3008. else /* Used sector */
  3009. {
  3010. status = vol.flash->read(vol.flash,sourceSectorAddress,buffer,SECTOR_SIZE,EDC);
  3011. switch (status)
  3012. {
  3013. case flDataError:
  3014. markAsIgnored(&vol,sourceSectorAddress);
  3015. createUnitCount(&vol,virUnitNo);
  3016. break; /* Mark as ignored */
  3017. case flOK:
  3018. break; /* Sector OK */
  3019. default:
  3020. return status; /* Report error */
  3021. }
  3022. }
  3023. /* Check the next free sector to make sure it is erased */
  3024. if(nextFreeSectorAddress != ANAND_UNASSIGNED_ADDRESS)
  3025. {
  3026. checkStatus(vol.flash->read(vol.flash,nextFreeSectorAddress,buffer,SECTOR_SIZE,0));
  3027. if (tffscmp(nftlBuffer,buffer,SECTOR_SIZE)!=0)
  3028. markAsIgnored(&vol,nextFreeSectorAddress);
  3029. }
  3030. } /* Loop over all sector of unit or until required sectors */
  3031. } /* Loop over all required sectors */
  3032. return flOK;
  3033. }
  3034. /*----------------------------------------------------------------------*/
  3035. /* c h e c k V o l u m e */
  3036. /* */
  3037. /* Scanthe entire media for partialy written sectors. */
  3038. /* */
  3039. /* Parameters: */
  3040. /* vol : Pointer identifying drive */
  3041. /* */
  3042. /* Returns: */
  3043. /* FLStatus : 0 on success, failed otherwise */
  3044. /*----------------------------------------------------------------------*/
  3045. static FLStatus checkVolume(Anand vol)
  3046. {
  3047. return verifySectors(&vol, 0xffffffff);
  3048. }
  3049. #endif /* VERIFY_WRITE || VERIFY_VOLUME || VERIFY_ERASED_SECTOR */
  3050. /*----------------------------------------------------------------------*/
  3051. /* c h e c k F o l d i n g */
  3052. /* */
  3053. /* Check folding status and if needed fold again. */
  3054. /* */
  3055. /* Parameters: */
  3056. /* vol : Pointer identifying drive */
  3057. /* virtualUnitNo : Virtual unit number to re-fold */
  3058. /* */
  3059. /* Returns: */
  3060. /* FLStatus : 0 on success, failed otherwise */
  3061. /*----------------------------------------------------------------------*/
  3062. static FLStatus checkFolding(Anand vol, ANANDUnitNo virtualUnitNo)
  3063. {
  3064. ANANDUnitNo tmp;
  3065. if(vol.freeUnits == 0)
  3066. checkStatus(foldBestChain(&vol, &tmp));
  3067. return foldUnit(&vol,virtualUnitNo,TRUE);
  3068. }
  3069. #endif /* FL_READ_ONLY */