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

6317 lines
246 KiB

  1. /*
  2. * $Log: V:/Flite/archives/TrueFFS5/Src/inftl.c_V $
  3. *
  4. * Rev 1.40 Apr 15 2002 20:14:40 oris
  5. * Changed the use of SecondUnitStructure for INFTLTEST utility.
  6. *
  7. * Rev 1.39 Apr 15 2002 08:39:32 oris
  8. * Placed quick mount under if def of CHECK_MOUNT for INFTLTST.
  9. *
  10. * Rev 1.38 Apr 15 2002 07:37:20 oris
  11. * Improved power failure resistant:
  12. * - setUnavail macro was changed for improved code readability.
  13. * - MarkSectorAsChecking macro was changed to MarkSectorAsChecked
  14. * - Bug fix - getSectorFlags - in case invalid sector flags are found do not forget to reset TL buffer to ff's and mark it as remapped.
  15. * - Added support for VERIFY_ERASED_SECTOR compilation flag - make sure a sector is free before writing it - most of the code
  16. * is found in writeAndCheck routine.
  17. * - Added MAKE_SURE_IGNORE_HAS_BAD_EDC compilation flag - make sure that the sector is really marked
  18. * as ignored. If not mark the entire sector as 0.
  19. * - Initialize a addition 1k buffer for the TL - used for verify erase.
  20. * - Bug fix - verifySector routine had several bugs.
  21. * - Bug fix - foldUnit routine bad comparison in FL_OFF mode.
  22. * - Bug fix - foldBestChain routine missing update of sector count after folding failed and bad search for free unit.
  23. * - Bug fix - mountUnit routine had bad handling for corrupted unit header.
  24. * Added support for RAM based MTD power failure tests.
  25. * Remove cache allocation checks - They are not needed since the cache routine itself check for proper allocation.
  26. * Bug fix - prevent initialization of flash record in case flash is NULL.
  27. * Bug fix - defragment routine used to call allocateUnit instead of foldBestChain.
  28. * Bug fix - bad debug print when format routine none INFTL media.
  29. * Bug fix - missing several dismount in INFTL format.
  30. * Bug fix - format routine could not place protection onto binary partition containing only the bios driver.
  31. * Changed format debug massages.
  32. *
  33. * Rev 1.37 Feb 19 2002 21:00:22 oris
  34. * Fixed FL_READ_ONLY compilation problems.
  35. * Replaced TL_LEAVE_BINARY_AREA with FL_LEAVE_BINARY_AREA
  36. * Improved protection against power failures:
  37. * - formatUnit/getUnitTailer and setUnitTailer - Added argument to support temporary units (unit with erase mark on an invalid offset so that if not fixed before next mount they will be considered as free).
  38. * - foldUnit - Removed setUnavailable (not called only from foldBestChain) and added code to restore temporary unit into permanent ones(mark erase mark in proper place).
  39. * - foldBestChain - added folding not in place and several bug fixes.
  40. * - AllocatUnit - Change sequence to be more robust.
  41. * - checkFolding/applyWearLeveling - Bug fix - read newest unit in chain after allocate call it might change as part of the allocate process.
  42. * - deleteSector - check status of write operation.
  43. * - mountInftl - perforce space reclamation only if no free units.
  44. *
  45. * Rev 1.36 Jan 29 2002 20:09:28 oris
  46. * Removed warnings.
  47. * Buf fix - chainging protection attributes of a DiskOnChip with more then a single floor.
  48. * Bug fix - if an invalid sector flag is found in getSectorFlags routine and read operation failed, SECTOR_IGNORED should have been returned.
  49. *
  50. * Rev 1.35 Jan 28 2002 21:25:46 oris
  51. * Bug fix - discard mark write operation had bad casting causing the
  52. * mark to be written to much lower addresses.
  53. * Changed discard variable to static const.
  54. * allocateAndWriteSectors - improved going along chain algorithm to scan
  55. * chain only once.
  56. *
  57. * Rev 1.34 Jan 23 2002 23:33:20 oris
  58. * Removed CHECK_DISCARD compilation flag.
  59. * Bug fix - bad casting caused discard mark to be written to a different unit then was expected in formatUnit().
  60. * Changed discardQuickMountInfo to mark quick mount area as discarded instead of erasing it.
  61. * Improved markAsIgnored routine.
  62. * Bug fix - Problems with insert and remove key routines.
  63. * Bug fix - write BBT for INFTL formatted DiskOnChip was not supported.
  64. * Changed DFORMAT_PRINT syntax
  65. *
  66. * Rev 1.33 Jan 21 2002 20:44:56 oris
  67. * Bug fix - Erase of quick mount information does not take block multiplication into account.
  68. *
  69. * Rev 1.32 Jan 20 2002 20:28:48 oris
  70. * Removed warnings
  71. * Changed putGetBuffer to handle FAR pointers (prototype and pointers arithmetic's).
  72. * Quick mount is now saved if either of the following occurs
  73. * - Last mount did not use quick mount information.
  74. * - A write operation was made in this mount
  75. * Bug in quickMount units size calculation (affected large DiskOnChips).
  76. *
  77. * Rev 1.31 Jan 20 2002 10:49:52 oris
  78. * Added initialization of Bnand record in mount and format.
  79. * Removed badFormat field from Bnand record.
  80. * Improoved last sector cache mechanism
  81. * Removed support for PPP=3 interleave-2
  82. * Changed FL_MALLOC allocation calls to FL_FAR_MALLOC and changed RAM tables pointers to FAR1.
  83. * Split preMount routine into protection routine and other premount routins.
  84. * Added DOUBLE_MAX_UNIT_CHAIN instead of MAX_UNIT_CHAIN*2
  85. * Added protection agains power failures.
  86. * - Added several modes of verify write :
  87. * - FL_UPS no protection
  88. * - FL_ON verify each and every write operation
  89. * - FL_OFF full protection with minmal performance penalty.
  90. * - Added verifyVolume API to scan the media for slower mount, but with not further performance penalty.
  91. * - default after mount is FL_OFF
  92. * - Added folding not in place.
  93. * - Added verification of last sector of the chains (in folding).
  94. * - Added discard mark before erasing.
  95. * - Changed sector flags and unit data retrival error correction logic.
  96. * - Limit foldBestChain folding tryies.
  97. * - Improoved mount logic for choosing between invalid chains.
  98. * Quick mount mechanism
  99. * - Forced quick mount as default
  100. * - Delete previous data only after first write operation.
  101. * - Remove previous quick mount info with an erase operation.
  102. * - Added remove previous quick mount info API (In preMount).
  103. * Imprroved error report mechanizm of brocken chains (should never happen):
  104. * - error on read return unused area of flash
  105. * - error on write report flGeneralFailure
  106. * - error on mount fix chains. If error on a chain that was already validated , report flGeneralFailure
  107. * Format routine
  108. * - Force quick mount (ignoring user flag)
  109. * - Bug fix - format with leave binary partition of a protected binary partition.
  110. * - Removed single floor support.
  111. *
  112. * Rev 1.30 Nov 21 2001 11:38:26 oris
  113. * Changed FL_MARK_DELETE to FL_ON.
  114. * Changed FL_WITH_VERIFY_WRITE and FL_WITHOUT_VERIFY_WRITE to FL_ON and FL_OFF.
  115. *
  116. * Rev 1.29 Nov 16 2001 00:22:22 oris
  117. * Reorganized - removed function declaration, moved debug routines to a
  118. * separated file.
  119. * Bug fix - VERIFY_WRITE logic - marking unit as unavailable was done on the
  120. * virtual unit and not the last physical unit plus the least sector count and
  121. * max chain length , where not reinitialized in foldBestChange. The result
  122. * might cause infinite loop in foldbestchain if foldUnit fails.
  123. * Bug fix - Support for DiskOnChip with last floors having less chips.
  124. * Improved progress callback routine to show current unit starting from 1 and
  125. not 0 and to indicate bad and unavailable blocks as well.
  126. * Bug fix - all routines that changed protection attributes might not use
  127. * Bug fix - formatting with LEAVE_BINARY_PARTITION when binary partition is
  128. * exactly the floor size (virtual size). and improved it for bootAreaLen not
  129. * 0 and not -1 (leave only part of the previous binary partition).
  130. * Quick mount feature - Made sure the mount operation changes quick_mount
  131. * validity even if QUICK_MOUNT_FEATURE is commented.
  132. * Support 2 unchangeable protected partitions (not only 1).
  133. * Added discard mark before erase and placed this option under ifdef (default off).
  134. * Changed isValidUnitFlags to check all fields (isValidParityResult) not just
  135. * PUN and VUN.
  136. * getUnitData - bug in the logic of using second unit data structure.
  137. * No need to reread the unit data if verify write is activated after setUnitData.
  138. * Added check in virtual2physical to make sure this the unit found is valid.
  139. * initINFTLbasic - Use dword variable to calculate blocks per unit (support 64k blocks).
  140. * Change block multiplication from MORE then 32K units (not equal)
  141. * Improved support for read only mode including mount - FL_READ_ONLY
  142. * Add runtime option of VERIFY_WRITE
  143. * Bug fix - Binary partition in the first floor used only 1001 units while in
  144. * other floors 1002 units.
  145. *
  146. * Rev 1.28 Oct 11 2001 23:54:58 oris
  147. * Bug fix - When changing protection attribute of a BDTL partition (change
  148. * key, change lock , change protection type) on a DiskOnChip with more then
  149. * a single floor, an error massage might be returned since changing
  150. * protection attributes uses the same buffer as the structure holding the
  151. * protection area to work on.
  152. *
  153. * Rev 1.27 Sep 24 2001 18:23:50 oris
  154. * Bug fix - missing break in foldBestChain - very rare case.
  155. * Removed warnings.
  156. *
  157. * Rev 1.26 Sep 16 2001 21:47:54 oris
  158. * Placed intergrity check of sector in the last unit of the virtual unit under
  159. * VERIFY_WRITE compilation flag.
  160. * Bug fix - missing big-endian conversion when using static memory allocation.
  161. *
  162. * Rev 1.25 Sep 15 2001 23:46:54 oris
  163. * Removed redundant isAvailable checks.
  164. * Make sure mount operation does not reconstruct BBT.
  165. * Bug fix - folding in wear leveling does not change NAC to 1.
  166. * Bug fix - Bad casting caused bad protection type to be returned under BIG_ENDIAN.
  167. * Changed change protection attributes routine applied on protected partition
  168. * from flWrongKey to flHWProtection.
  169. * Improved algorithm reliability with VERIFY_WRITE. Following are the changes in the algorithm:
  170. * 1) virtual2Physical -
  171. * a) added flag stating if the specific sector is not free in the last unit of the chain.
  172. * 2) foldUnit -
  173. * a) if can not copy sector to the last unit of the chain, mark unit as
  174. * unavailable and return error code.
  175. * b) If verify write is enabled check even sectors that re marked as used and
  176. * are found on the last unit of the chain.
  177. * 3) foldBestChain -
  178. * a) Ignore unavailable units
  179. * b) If folding failed start looking from the beginning (it will be marked as
  180. * unavailable by the foldunit routine).
  181. * c) when done make all unit available.
  182. * 4) Added checkFolding routine - after folding check if succeeded. If not
  183. * loop up to MAX_FOLDING_LOOP each time free a unit with foldbestchain,
  184. * append a unit to the problematic chain and try to fold it.
  185. * 5) allocateUnit - Now when there are less then 2 unit reclaim space. This is
  186. * to minimize the chance of folding within a fold operation.
  187. * 6) MountINFTL - Make sure there are at least 2 free units.
  188. *
  189. * Rev 1.24 Jul 29 2001 16:10:00 oris
  190. * eraseOrphanUnit bug was fixed ( we did not add vol.firstUnit to the unitNo).
  191. *
  192. * Rev 1.23 Jul 15 2001 20:45:12 oris
  193. * Improoved documentation.
  194. * Changed unitBaseAddress function to a macro.
  195. * Removed unneccesary if statments in applyWearLeveling().
  196. *
  197. * Rev 1.22 Jul 13 2001 01:06:14 oris
  198. * Changed multiBufferCounter to signed allowing a better buffer management.
  199. * Changed consequtiveNumbers routine into a macro.
  200. * Reorganized the DEBUG chains routines.
  201. * Bug fix - H/W read protected partition did not report as such.
  202. * Changed swapUnits routine name to applyWearleveling.
  203. * Added basics for last sector return mechanism -
  204. * foldUnit receives an additional field.
  205. * read2Sectors returns edc error sector address and actually read sector address
  206. * Added several static prefixes for static routines.
  207. * Added edc check for media header read operation.
  208. * Bug fix - parturition size smaller then a unit was acceptable.
  209. * Added default protection for unused DPSes.
  210. * Bug fix - formatINFTL with leave binary partition flag when previous binary
  211. * partition was larger then a single floor.
  212. * Improved mount documentation.
  213. * Changed policy - do not erase unit with bad erase mark.
  214. *
  215. * Rev 1.21 Jun 17 2001 08:20:06 oris
  216. * Added NO_READ_BBT_CODE compilation flag to reduce code size.
  217. * Improoved Reliability:
  218. * 1) Try to return next sector in chain if the current one has EDC error
  219. * 2) Mount routine erases all blocks not marked with the erase mark.
  220. *
  221. * Affected routines:
  222. * 1) virtual2Physical can recive the physical address to start looking for and
  223. * not the last virtual unit of the chain.
  224. * 2) copySector ,foldUnit, mapSector, read2sectors- if EDC error accures
  225. * return try returning the next sector.
  226. * 3) foldUnit - if EDC error accures return try returning the next sector.
  227. * 4) writeMultiSecotr - improove ppp = 3
  228. * 5) mountINFTL - erase all units not marked with the erase mark.
  229. *
  230. * Rev 1.21 Jun 17 2001 08:18:02 oris
  231. * Changed recusive include define to INFTL_H.
  232. * Added FL_BAD_ERASE_MARK definition for units without the erase mark on
  233. * mount operation.
  234. *
  235. * For the rest of the revisions see revision 1.24 in the PVCS.
  236. */
  237. /***********************************************************************************/
  238. /* M-Systems Confidential */
  239. /* Copyright (C) M-Systems Flash Disk Pioneers Ltd. 1995-2001 */
  240. /* All Rights Reserved */
  241. /***********************************************************************************/
  242. /* NOTICE OF M-SYSTEMS OEM */
  243. /* SOFTWARE LICENSE AGREEMENT */
  244. /* */
  245. /* THE USE OF THIS SOFTWARE IS GOVERNED BY A SEPARATE LICENSE */
  246. /* AGREEMENT BETWEEN THE OEM AND M-SYSTEMS. REFER TO THAT AGREEMENT */
  247. /* FOR THE SPECIFIC TERMS AND CONDITIONS OF USE, */
  248. /* OR CONTACT M-SYSTEMS FOR LICENSE ASSISTANCE: */
  249. /* E-MAIL = [email protected] */
  250. /***********************************************************************************/
  251. /*************************************************/
  252. /* T r u e F F S 5.0 S o u r c e F i l e s */
  253. /* --------------------------------------------- */
  254. /*************************************************/
  255. /*****************************************************************************
  256. * File Header *
  257. * ----------- *
  258. * Name : inftl.c *
  259. * *
  260. * Description : Implementation of INFTL flash translation layer. *
  261. * *
  262. *****************************************************************************/
  263. /* Internal compilation flags */
  264. /* #define CHAINS_DEBUG */ /* Prints unit chains after mount routine */
  265. /* #define CHECK_MOUNT */ /* Print serious tl debug warnings to */
  266. /* tl_out global file handle */
  267. /* #define MAKE_SURE_IGNORE_HAS_BAD_EDC */ /* Make sure the ignore mark was */
  268. /* written. If not fill sector */
  269. /* with 0's. */
  270. /* List of included files */
  271. #include "inftl.h"
  272. /* Private variables */
  273. static Bnand vols[VOLUMES];
  274. #ifndef FL_MALLOC
  275. #ifdef NFTL_CACHE
  276. static ucacheEntry socketUcache[SOCKETS][U_CACHE_SIZE];
  277. static byte socketScache[SOCKETS][S_CACHE_SIZE];
  278. #endif /* NFTL_CACHE */
  279. static Sbyte socketHeap[SOCKETS][ANAND_HEAP_SIZE];
  280. static byte multiSectorBuf[SOCKETS][SECTOR_SIZE<<1];
  281. #else
  282. static byte *multiSectorBuf[SOCKETS];
  283. static Sbyte multiSectorBufCounter[SOCKETS];
  284. #endif /* FL_MALLOC */
  285. #ifdef NFTL_CACHE
  286. /* translation table for Sector Flags cache */
  287. static byte scacheTable[4] = { SECTOR_DELETED, /* 0 */
  288. SECTOR_IGNORE, /* 1 */
  289. SECTOR_USED, /* 2 */
  290. SECTOR_FREE }; /* 3 */
  291. #endif /* NFTL_CACHE */
  292. /* Macros */
  293. #define roundToUnits(var) ((var > 0) ? ((ANANDUnitNo)((var - 1) >> vol.unitSizeBits) + 1) : 0)
  294. #define NextGoodUnit(addr,bbt) for(;bbt[(addr >> vol.unitSizeBits) - vol.firstQuickMountUnit]!=ANAND_UNIT_FREE;addr+=1L<<vol.unitSizeBits)
  295. #define countOf(unitNo) (vol.physicalUnits[unitNo] & UNIT_COUNT)
  296. #define isAvailable(unitNo) ((vol.physicalUnits[unitNo] == ANAND_UNIT_FREE) || (countOf(unitNo) <= UNIT_MAX_COUNT))
  297. #define setUnavail(unitNo) (vol.physicalUnits[unitNo] = UNIT_UNAVAIL)
  298. #define setUnitCount(unitNo,unitCount) { vol.physicalUnits[unitNo] &= ~UNIT_COUNT; vol.physicalUnits[unitNo] |= (ANANDPhysUnit)unitCount; }
  299. #define isLegalUnit(unitNo) ((unitNo < vol.noOfUnits) || (unitNo == ANAND_NO_UNIT))
  300. #define isValidSectorFlag(sectorFlag) ((sectorFlag==SECTOR_FREE)||(sectorFlag==SECTOR_USED)||(sectorFlag==SECTOR_DELETED))
  301. #define badParityResult(parityResult) (parityResult != ALL_PARITY_BITS_OK)
  302. #define consecutiveNumbers(first,second) ((byte)(second+1)==first)
  303. #define unitBaseAddress(vol,unitNo) ((CardAddress)((ANANDUnitNo)unitNo+(ANANDUnitNo)vol.firstUnit) << vol.unitSizeBits)
  304. #define distanceOf(read, expected) (onesCount((byte)(read ^ expected)))
  305. #define MarkSectorAsChecked(addr) (scannedBlocks[((addr)>>SECTOR_SIZE_BITS) & vol.sectorsPerUnitMask] = TRUE)
  306. #define WasSectorChecked(addr) scannedBlocks[((addr)>>SECTOR_SIZE_BITS) & vol.sectorsPerUnitMask]
  307. /* M-Systems INFTL debug routines */
  308. #ifndef CHECK_MOUNT
  309. #define TL_DEBUG_PRINT(x,y,z)
  310. #define SET_EXIT(x)
  311. #define DID_MOUNT_FAIL 1
  312. #endif /* CHECK_MOUNT */
  313. #if (defined(CHECK_MOUNT) || defined (CHAINS_DEBUG))
  314. #include "inftldbg.c"
  315. #endif /* CHECK_MOUNT || CHAINS_DEBUG */
  316. /*------------------------------------------------------*/
  317. /* o n e s C o u n t */
  318. /* */
  319. /* counts number of bits that valued 1 in a given byte */
  320. /*------------------------------------------------------*/
  321. static byte onesCount(byte flag)
  322. {
  323. byte counter;
  324. for (counter = 0; flag; flag >>= 1)
  325. if (flag & 1)
  326. counter++;
  327. return counter;
  328. }
  329. /*----------------------------------------------------------------------*/
  330. /* g e t U n i t T a i l e r */
  331. /* */
  332. /* Get the erase record of a unit. */
  333. /* */
  334. /* Parameters: */
  335. /* vol : Pointer identifying drive */
  336. /* unitNo : Physical unit number */
  337. /* eraseMark : Receives the erase mark of the unit */
  338. /* eraseCount : Receives the erase count of the unit */
  339. /* offset : offset in unit */
  340. /* */
  341. /* Returns: */
  342. /* FLStatus : 0 on success, failed otherwise */
  343. /* */
  344. /*----------------------------------------------------------------------*/
  345. static FLStatus getUnitTailer(Bnand vol,
  346. ANANDUnitNo unitNo,
  347. word *eraseMark,
  348. dword *eraseCount,
  349. dword offset)
  350. {
  351. UnitTailer unitTailer;
  352. FLStatus status;
  353. status = vol.flash->read(vol.flash,
  354. unitBaseAddress(vol,unitNo) + offset,
  355. &unitTailer,
  356. sizeof(UnitTailer),
  357. EXTRA);
  358. /* Mask out any 1 -> 0 bit faults by or'ing with spare data */
  359. *eraseMark = (word)(LE2(unitTailer.eraseMark) | LE2(unitTailer.eraseMark1));
  360. *eraseCount = LE4(unitTailer.eraseCount);
  361. return status;
  362. }
  363. #ifndef FL_READ_ONLY
  364. /*----------------------------------------------------------------------*/
  365. /* s e t U n i t T a i l e r */
  366. /* */
  367. /* Set the erase record of a unit. */
  368. /* */
  369. /* Parameters: */
  370. /* vol : Pointer identifying drive */
  371. /* unitNo : Physical unit number */
  372. /* eraseMark : Erase mark to set */
  373. /* eraseCount : Erase count to set */
  374. /* offset : offset in unit */
  375. /* */
  376. /* Returns: */
  377. /* FLStatus : 0 on success, failed otherwise */
  378. /* */
  379. /*----------------------------------------------------------------------*/
  380. static FLStatus setUnitTailer(Bnand vol,
  381. ANANDUnitNo unitNo,
  382. word eraseMark,
  383. dword eraseCount,
  384. dword offset)
  385. {
  386. UnitTailer unitTailer;
  387. toLE2(unitTailer.eraseMark,eraseMark);
  388. toLE2(unitTailer.eraseMark1,eraseMark);
  389. toLE4(unitTailer.eraseCount,eraseCount);
  390. return vol.flash->write(vol.flash,
  391. unitBaseAddress(vol,unitNo) + offset,
  392. &unitTailer,
  393. sizeof(UnitTailer),
  394. EXTRA);
  395. }
  396. /*----------------------------------------------------------------------*/
  397. /* m a r k U n i t B a d */
  398. /* */
  399. /* Mark a unit as bad in the conversion table and the bad units table. */
  400. /* */
  401. /* Parameters: */
  402. /* vol : Pointer identifying drive */
  403. /* unitNo : Physical number of bad unit */
  404. /* */
  405. /* Returns: */
  406. /* FLStatus : 0 on success, failed otherwise */
  407. /*----------------------------------------------------------------------*/
  408. static FLStatus markUnitBad(Bnand vol, ANANDUnitNo unitNo)
  409. {
  410. word eraseMark;
  411. dword eraseCount;
  412. FLStatus status;
  413. vol.physicalUnits[unitNo] = UNIT_BAD;
  414. if(vol.freeUnits)
  415. vol.freeUnits--;
  416. status = getUnitTailer(&vol,unitNo,&eraseMark,&eraseCount,UNIT_TAILER_OFFSET);
  417. if (status == flOK)
  418. status = setUnitTailer(&vol,unitNo,FL_BAD_ERASE_MARK,eraseCount,UNIT_TAILER_OFFSET);
  419. #ifdef NFTL_CACHE
  420. if (vol.ucache != NULL) /* Mark unit cache as unavaialbel */
  421. {
  422. vol.ucache[unitNo].virtualUnitNo = 0xDEAD;
  423. vol.ucache[unitNo].prevUnitNo = 0xDEAD;
  424. }
  425. #endif /* NFTL_CACHE */
  426. return status;
  427. }
  428. /*----------------------------------------------------------------------*/
  429. /* f o r m a t U n i t */
  430. /* */
  431. /* Format one unit. Erase the unit, and mark the physical units table. */
  432. /* */
  433. /* Parameters: */
  434. /* vol : Pointer identifying drive */
  435. /* unitNo : Physical unit to format */
  436. /* eraseMarkOffset : Offset to place erase mark */
  437. /* */
  438. /* Returns: */
  439. /* FLStatus : 0 on success, failed otherwise */
  440. /*----------------------------------------------------------------------*/
  441. static FLStatus formatUnit(Bnand vol, ANANDUnitNo unitNo,
  442. dword eraseMarkOffset)
  443. {
  444. word eraseMark;
  445. dword eraseCount;
  446. FLStatus status;
  447. #ifndef RAM_MTD
  448. static const
  449. #endif /* RAM_MTD */
  450. byte discard = (byte)CLEAR_DISCARD;
  451. status = getUnitTailer(&vol,unitNo,&eraseMark,&eraseCount,UNIT_TAILER_OFFSET);
  452. if(status != flOK)
  453. return status;
  454. #ifdef NFTL_CACHE
  455. /* Update ANANDUnitHeader cache to prevent re-filling from flash */
  456. if (vol.ucache != NULL) {
  457. vol.ucache[unitNo].virtualUnitNo = ANAND_NO_UNIT;
  458. vol.ucache[unitNo].prevUnitNo = ANAND_NO_UNIT;
  459. vol.ucache[unitNo].ANAC = ANAND_UNIT_FREE;
  460. vol.ucache[unitNo].NAC = ANAND_UNIT_FREE;
  461. }
  462. /*
  463. * Purge the Sector Flags cache (set entries for all the unit's
  464. * sectors to SECTOR_FREE).
  465. */
  466. if(vol.scache!=NULL)
  467. {
  468. tffsset(&(vol.scache[unitNo << (vol.unitSizeBits - SECTOR_SIZE_BITS-2)]),
  469. S_CACHE_4_SECTORS_FREE, 1 << (vol.unitSizeBits - SECTOR_SIZE_BITS - 2));
  470. }
  471. #endif /* NFTL_CACHE */
  472. /* Mark unit as unusable before erase */
  473. vol.flash->write(vol.flash,(((dword)(vol.firstUnit + unitNo))<<vol.unitSizeBits)+DISCARD_UNIT_OFFSET,&discard,1,EXTRA);
  474. /* Physicaly erase unit */
  475. status = vol.flash->erase(vol.flash,(word)((word)(vol.firstUnit + unitNo)
  476. << vol.blockMultiplierBits),(word)(1 << vol.blockMultiplierBits));
  477. vol.eraseSum++;
  478. eraseCount++;
  479. if (eraseCount == 0) /* was hex FF's */
  480. eraseCount++;
  481. if (status == flOK)
  482. status = setUnitTailer(&vol,unitNo,ERASE_MARK,eraseCount,eraseMarkOffset);
  483. if (status != flOK) {
  484. markUnitBad(&vol,unitNo); /* make sure unit format is not valid */
  485. return status;
  486. }
  487. if (vol.physicalUnits[unitNo] != ANAND_UNIT_FREE)
  488. {
  489. vol.physicalUnits[unitNo] = ANAND_UNIT_FREE;
  490. vol.freeUnits++;
  491. }
  492. return status;
  493. }
  494. #endif /* FL_READ_ONLY */
  495. /*----------------------------------------------------------------------*/
  496. /* g e t U n i t D a t a */
  497. /* */
  498. /* Get virtual unit No. and replacement unit no. of a unit. */
  499. /* */
  500. /* Parameters: */
  501. /* vol : Pointer identifying drive */
  502. /* unitNo : Physical unit number */
  503. /* virtualUnitNo : Returns the virtual unit no. */
  504. /* prevUnitNo : Returns the previous unit no. */
  505. /* ANAC : Returns the Accumulating Number Along Chain. */
  506. /* NAC : Returns the Number Along Chain value. */
  507. /* validFields : Returns a bit map of the valid fields. */
  508. /* */
  509. /* Returns: */
  510. /* flOK on success, flHWProtection on H/W read protection. */
  511. /*----------------------------------------------------------------------*/
  512. static FLStatus getUnitData(Bnand vol,
  513. ANANDUnitNo unitNo,
  514. ANANDUnitNo *virtualUnitNo,
  515. ANANDUnitNo *prevUnitNo,
  516. byte *ANAC,
  517. byte *NAC,
  518. byte *validFields)
  519. {
  520. ANANDUnitHeader unitData;
  521. SecondANANDUnitHeader secondUnitData;
  522. FLStatus status;
  523. byte parityPerField=0;
  524. byte temp;
  525. byte returnedValidField = ALL_PARITY_BITS_OK;
  526. byte curValidFields[2];
  527. int index;
  528. #ifdef NFTL_CACHE
  529. /* on cache miss read ANANDUnitHeader from flash and re-fill cache */
  530. if ((vol.ucache != NULL)&&(vol.ucache[unitNo].virtualUnitNo != 0xDEAD) &&
  531. (vol.ucache[unitNo].prevUnitNo != 0xDEAD))
  532. {
  533. *virtualUnitNo = vol.ucache[unitNo].virtualUnitNo;
  534. *prevUnitNo = vol.ucache[unitNo].prevUnitNo;
  535. *ANAC = vol.ucache[unitNo].ANAC;
  536. *NAC = vol.ucache[unitNo].NAC;
  537. }
  538. else
  539. #endif /* NFTL_CACHE */
  540. { /* no ANANDUnitHeader cache MUST read first header */
  541. *validFields = 0; /* Set all fields to be invalid */
  542. /* Read first unit data */
  543. status = vol.flash->read(vol.flash,
  544. unitBaseAddress(vol,unitNo) + UNIT_DATA_OFFSET,
  545. &unitData,
  546. sizeof(ANANDUnitHeader),
  547. EXTRA);
  548. if(status != flOK)
  549. return status;
  550. *virtualUnitNo = LE2(unitData.virtualUnitNo);
  551. *prevUnitNo = LE2(unitData.prevUnitNo );
  552. *ANAC = unitData.ANAC;
  553. *NAC = unitData.NAC;
  554. for(index=0;index<2;index++)
  555. {
  556. /* If all data is 0xff assume a free unit */
  557. if((*virtualUnitNo == ANAND_NO_UNIT )&&
  558. (*prevUnitNo == ANAND_NO_UNIT )&&
  559. (*ANAC == ANAND_UNIT_FREE)&&
  560. (*NAC == ANAND_UNIT_FREE)&&
  561. (unitData.discarded == ANAND_UNIT_FREE))
  562. {
  563. #ifndef FL_READ_ONLY
  564. if(index!=0)
  565. {
  566. /* If this is the second copy then the first was not */
  567. /* erased, but since it was written first it makes no */
  568. /* sence. Let us erase it just in case. */
  569. status = formatUnit(&vol,unitNo,UNIT_TAILER_OFFSET);
  570. if(status != flOK)
  571. return status;
  572. }
  573. #endif /* FL_READ_ONLY */
  574. break;
  575. }
  576. /* Not a free unit check unit data validity (discard and partity) */
  577. if ((onesCount((byte)(unitData.discarded^DISCARD))>1))
  578. {
  579. /* Discarded mark is more then 1 bit distance from 0xAA */
  580. /* Assume erase operation was interrupted and erase unit */
  581. TL_DEBUG_PRINT(tl_out,"getUnitData : unit %d has an invalid discard mark\n",unitNo);
  582. TL_DEBUG_PRINT(tl_out," it might be helpful to know it was %d\n",unitData.discarded);
  583. #ifndef FL_READ_ONLY
  584. status = formatUnit(&vol,unitNo,UNIT_TAILER_OFFSET);
  585. if(status != flOK)
  586. return status;
  587. #endif /* FL_READ_ONLY */
  588. *virtualUnitNo = ANAND_NO_UNIT;
  589. *prevUnitNo = ANAND_NO_UNIT;
  590. *ANAC = ANAND_UNIT_FREE;
  591. *NAC = ANAND_UNIT_FREE;
  592. break;
  593. }
  594. /* Discarded OK now check parity field */
  595. parityPerField = 0;
  596. temp=(byte)(((byte *)virtualUnitNo)[0]^((byte *)virtualUnitNo)[1]);
  597. if((onesCount(temp) & 1)==1)
  598. parityPerField|=VU_PARITY_BIT;
  599. temp=(byte)(((byte *)prevUnitNo)[0]^((byte *)prevUnitNo)[1]);
  600. if((onesCount(temp) & 1)==1)
  601. parityPerField|=PU_PARITY_BIT;
  602. if((onesCount(unitData.ANAC) & 1)==1)
  603. parityPerField|=ANAC_PARITY_BIT;
  604. if((onesCount(unitData.NAC) & 1)==1)
  605. parityPerField|=NAC_PARITY_BIT;
  606. /* Store valid fields using bitmap */
  607. curValidFields[index] = (byte)((~(parityPerField ^ unitData.parityPerField))
  608. & ALL_PARITY_BITS_OK);
  609. if(curValidFields[index] == ALL_PARITY_BITS_OK)
  610. {
  611. /* If either copies has valid fields (all of them) use it */
  612. break;
  613. }
  614. else
  615. {
  616. if(index>0)
  617. {
  618. /* Use first header data if possible otherwise use second */
  619. returnedValidField = (byte)(curValidFields[0] | curValidFields[1]);
  620. TL_DEBUG_PRINT(tl_out,"getUnitData : The returned valid field indicator is %d\n",returnedValidField);
  621. TL_DEBUG_PRINT(tl_out," While %d indicates a valid unit data\n",ALL_PARITY_BITS_OK);
  622. if(curValidFields[0] & VU_PARITY_BIT)
  623. *virtualUnitNo = LE2(unitData.virtualUnitNo);
  624. if(curValidFields[0] & PU_PARITY_BIT)
  625. *prevUnitNo = LE2(unitData.prevUnitNo );
  626. if(curValidFields[0] & ANAC_PARITY_BIT)
  627. *ANAC = unitData.ANAC;
  628. if(curValidFields[0] & NAC_PARITY_BIT)
  629. *NAC = unitData.ANAC;
  630. break;
  631. }
  632. }
  633. /* Read second unit header for next iteration */
  634. status = vol.flash->read(vol.flash, unitBaseAddress(vol,unitNo) +
  635. SECOND_HEADER_OFFSET + UNIT_DATA_OFFSET,
  636. &secondUnitData,
  637. sizeof(SecondANANDUnitHeader),
  638. EXTRA);
  639. if(status != flOK)
  640. return status;
  641. *virtualUnitNo = LE2(secondUnitData.virtualUnitNo);
  642. *prevUnitNo = LE2(secondUnitData.prevUnitNo );
  643. *ANAC = secondUnitData.ANAC;
  644. *NAC = secondUnitData.NAC;
  645. TL_DEBUG_PRINT(tl_out,"getUnitData : First unit header is not OK in unit %d \n",unitNo);
  646. TL_DEBUG_PRINT(tl_out,"getUnitData : Virtual Unit No = %d \n",LE2(unitData.virtualUnitNo));
  647. TL_DEBUG_PRINT(tl_out,"getUnitData : Previous Unit No = %d \n",LE2(unitData.prevUnitNo));
  648. TL_DEBUG_PRINT(tl_out,"getUnitData : ANAC = %d \n",unitData.ANAC);
  649. TL_DEBUG_PRINT(tl_out,"getUnitData : NAC = %d \n",unitData.NAC);
  650. TL_DEBUG_PRINT(tl_out,"getUnitData : ParityPerField = %d \n",unitData.parityPerField);
  651. TL_DEBUG_PRINT(tl_out,"getUnitData : Discarded = %d \n",unitData.discarded);
  652. TL_DEBUG_PRINT(tl_out,"getUnitData : Second unit header of the same unit %d is:\n",unitNo);
  653. TL_DEBUG_PRINT(tl_out,"getUnitData : Virtual Unit No = %d \n",LE2(secondUnitData.virtualUnitNo));
  654. TL_DEBUG_PRINT(tl_out,"getUnitData : Previous Unit No = %d \n",LE2(secondUnitData.prevUnitNo));
  655. TL_DEBUG_PRINT(tl_out,"getUnitData : ANAC = %d \n",secondUnitData.ANAC);
  656. TL_DEBUG_PRINT(tl_out,"getUnitData : NAC = %d \n",secondUnitData.NAC);
  657. TL_DEBUG_PRINT(tl_out,"getUnitData : ParityPerField = %d \n",secondUnitData.parityPerField);
  658. }
  659. #ifdef NFTL_CACHE
  660. if ((vol.ucache != NULL) && /* Cache enabled */
  661. (returnedValidField == ALL_PARITY_BITS_OK)) /* All fields valid */
  662. {
  663. vol.ucache[unitNo].virtualUnitNo = *virtualUnitNo;
  664. vol.ucache[unitNo].prevUnitNo = *prevUnitNo;
  665. vol.ucache[unitNo].ANAC = *ANAC;
  666. vol.ucache[unitNo].NAC = *NAC;
  667. }
  668. #endif /* NFTL_CACHE */
  669. }
  670. *validFields = returnedValidField;
  671. return flOK;
  672. }
  673. /*----------------------------------------------------------------------*/
  674. /* g e t P r e v U n i t */
  675. /* */
  676. /* Get next unit in chain. */
  677. /* */
  678. /* Parameters: */
  679. /* vol : Pointer identifying drive */
  680. /* unitNo : Physical unit number */
  681. /* virUnitNo : The expected virtual unit number */
  682. /* */
  683. /* Returns: */
  684. /* Physical unit number of the unit following unitNo in the chain. */
  685. /* If such unit do not exist, return ANAND_NO_UNIT. */
  686. /*----------------------------------------------------------------------*/
  687. static ANANDUnitNo getPrevUnit(Bnand vol, ANANDUnitNo unitNo, ANANDUnitNo virUnitNo)
  688. {
  689. ANANDUnitNo virtualUnitNo, replacementUnitNo;
  690. byte ANAC,NAC;
  691. byte parityPerField;
  692. /* If first in chain there can be not previous unit */
  693. if ((vol.physicalUnits[unitNo] & FIRST_IN_CHAIN))
  694. return ANAND_NO_UNIT;
  695. getUnitData(&vol,unitNo,&virtualUnitNo,&replacementUnitNo,&ANAC,&NAC,&parityPerField);
  696. /* check if unit is valid */
  697. if((badParityResult(parityPerField)) || ( virUnitNo != virtualUnitNo ))
  698. {
  699. TL_DEBUG_PRINT(tl_out,"getPrevUnit : An invalid unit was detected on getPrevUnit - parity is %x/0xf ",parityPerField);
  700. TL_DEBUG_PRINT(tl_out,"given virtual unit no is %d ",virUnitNo);
  701. TL_DEBUG_PRINT(tl_out,"where %d was read\n",virtualUnitNo);
  702. SET_EXIT(INFTL_FAILED_MOUNT);
  703. return ANAND_BAD_CHAIN_UNIT;
  704. }
  705. return replacementUnitNo;
  706. }
  707. #ifdef NFTL_CACHE
  708. /*----------------------------------------------------------------------*/
  709. /* g e t S e c t o r F l a g s F r o m C a c h e */
  710. /* */
  711. /* Get sector flags from Sector Cache. */
  712. /* */
  713. /* Parameters: */
  714. /* vol : Pointer identifying drive */
  715. /* address : starting address of the sector */
  716. /* */
  717. /* Returns: */
  718. /* sector flags (SECTOR_USED, SECTOR_DELETED etc.) */
  719. /*----------------------------------------------------------------------*/
  720. static byte getSectorFlagsFromCache(Bnand vol, CardAddress address)
  721. {
  722. return scacheTable[((vol.scache[(address - vol.firstUnitAddress) >> (SECTOR_SIZE_BITS+2)] >>
  723. (((word)address >> 8) & 0x7)) & 0x3)];
  724. }
  725. /*----------------------------------------------------------------------*/
  726. /* s e t S e c t o r F l a g s C a c h e */
  727. /* */
  728. /* Get sector flags from Sector Cache. */
  729. /* */
  730. /* Parameters: */
  731. /* vol : Pointer identifying drive */
  732. /* address : starting address of the sector */
  733. /* sectorFlags : one of SECTOR_USED, SECTOR_DELETED etc. */
  734. /* */
  735. /*----------------------------------------------------------------------*/
  736. static void setSectorFlagsCache(Bnand vol, CardAddress address,
  737. byte sectorFlags)
  738. {
  739. register byte tmp, val;
  740. if (vol.scache == NULL)
  741. return;
  742. tmp = vol.scache[(address - vol.firstUnitAddress) >> (SECTOR_SIZE_BITS+2)];
  743. switch(sectorFlags) {
  744. case SECTOR_USED: val = S_CACHE_SECTOR_USED; break;
  745. case SECTOR_FREE: val = S_CACHE_SECTOR_FREE; break;
  746. case SECTOR_DELETED: val = S_CACHE_SECTOR_DELETED; break;
  747. default:/* SECTOR_IGNORE */val = S_CACHE_SECTOR_IGNORE; break;
  748. }
  749. switch (((word)address >> 8) & 0x7) {
  750. case 0: tmp = (tmp & 0xfc) | (val ); break; /* update bits 0..1 */
  751. case 2: tmp = (tmp & 0xf3) | (val << 2); break; /* bits 2..3 */
  752. case 4: tmp = (tmp & 0xcf) | (val << 4); break; /* bits 4..5 */
  753. case 6: tmp = (tmp & 0x3f) | (val << 6); break; /* bits 6..7 */
  754. }
  755. vol.scache[(address - vol.firstUnitAddress) >> (SECTOR_SIZE_BITS+2)] = tmp;
  756. }
  757. #endif /* NFTL_CACHE */
  758. /*----------------------------------------------------------------------*/
  759. /* g e t S e c t o r F l a g s */
  760. /* */
  761. /* Get sector status. */
  762. /* */
  763. /* Parameters: */
  764. /* vol : Pointer identifying drive */
  765. /* sectorAddress : Physical address of the sector */
  766. /* */
  767. /* Returns: */
  768. /* Return the OR of the two bytes in the sector status area (the */
  769. /* bytes should contain the same data). */
  770. /*----------------------------------------------------------------------*/
  771. static byte getSectorFlags(Bnand vol, CardAddress sectorAddress)
  772. {
  773. byte flags[2];
  774. byte blockFlag = SECTOR_IGNORE;
  775. byte index,tmpSector;
  776. FLStatus status;
  777. #ifdef NFTL_CACHE
  778. if (vol.scache != NULL) { /* check for Sector Flags cache hit */
  779. blockFlag = getSectorFlagsFromCache(&vol, sectorAddress);
  780. if (blockFlag != SECTOR_IGNORE)
  781. return blockFlag;
  782. }
  783. #endif /* NFTL_CACHE */
  784. vol.flash->read(vol.flash, sectorAddress + SECTOR_DATA_OFFSET,
  785. flags, sizeof flags, EXTRA);
  786. if((flags[0] == flags[1]) && (isValidSectorFlag(flags[0])))
  787. {
  788. blockFlag = flags[0];
  789. }
  790. else /* Sector flags that were read are not legal or not valid */
  791. {
  792. TL_DEBUG_PRINT(tl_out,"getSectorFlags : Sector flags are not valid - physical addr %ld ",sectorAddress);
  793. TL_DEBUG_PRINT(tl_out,"first flag was %x ",flags[0]);
  794. TL_DEBUG_PRINT(tl_out,"while scond is %x\n",flags[1]);
  795. SET_EXIT(INFTL_FAILED_MOUNT);
  796. /* Force remapping of internal catched sector */
  797. vol.flash->socket->remapped = TRUE;
  798. /* Check for ignored sector using the EDC */
  799. status = vol.flash->read(vol.flash, sectorAddress,
  800. inftlBuffer, SECTOR_SIZE, EDC);
  801. #if (defined(VERIFY_WRITE) || defined (VERIFY_VOLUME) || defined(VERIFY_ERASED_SECTOR))
  802. /* Now restore the ff's for the verifySectors routine */
  803. tffsset(inftlBuffer,0xff,SECTOR_SIZE);
  804. #endif /* VERIFY_WRITE || VERIFY_VOLUME || VERIFY_ERASED_SECTOR */
  805. if(status == flOK)
  806. {
  807. /* Check if distance is less then 2 bits failure since */
  808. /* 2 bits failure can be either delete or used */
  809. for (index=0 , tmpSector = (byte)SECTOR_USED ; index < 2 ;
  810. index++ , tmpSector = (byte)SECTOR_DELETED)
  811. {
  812. if (distanceOf(flags[0], tmpSector) +
  813. distanceOf(flags[1], tmpSector) <= 2)
  814. {
  815. blockFlag = tmpSector;
  816. break;
  817. }
  818. }
  819. if(index>=2)
  820. return SECTOR_IGNORE;
  821. }
  822. else
  823. {
  824. return SECTOR_IGNORE;
  825. }
  826. }
  827. #ifdef NFTL_CACHE
  828. /* update Sector Flags cache */
  829. setSectorFlagsCache(&vol, sectorAddress, blockFlag);
  830. #endif /* NFTL_CACHE */
  831. return blockFlag;
  832. }
  833. #ifndef FL_READ_ONLY
  834. /*----------------------------------------------------------------------*/
  835. /* s e t U n i t D a t a */
  836. /* */
  837. /* Set virtual unit No. and replacement unit no. of a unit. */
  838. /* */
  839. /* Parameters: */
  840. /* vol : Pointer identifying drive */
  841. /* unitNo : Physical unit number */
  842. /* virtualUnitNo : Virtual unit no. */
  843. /* prevUnitNo : Previous unit no. */
  844. /* ANAC : Accumulating Number Along Chain */
  845. /* NAC : Number Along Chain. */
  846. /* */
  847. /* Returns: */
  848. /* FLStatus : 0 on success, failed otherwise */
  849. /* */
  850. /*----------------------------------------------------------------------*/
  851. static FLStatus setUnitData(Bnand vol,
  852. ANANDUnitNo unitNo,
  853. ANANDUnitNo virtualUnitNo,
  854. ANANDUnitNo prevUnitNo,byte ANAC,byte NAC)
  855. {
  856. ANANDUnitHeader unitData;
  857. SecondANANDUnitHeader secondUnitData;
  858. FLStatus status;
  859. ANANDUnitNo newVirtualUnitNo, newPrevUnitNo;
  860. byte newANAC,newNAC;
  861. byte temp;
  862. byte parityPerField = 0;
  863. if( prevUnitNo == unitNo ) /* prevent chain loop */
  864. return flGeneralFailure;
  865. /* Calculate parity per field */
  866. temp=(byte)(((byte *)&virtualUnitNo)[0]^((byte *)&virtualUnitNo)[1]);
  867. if((onesCount(temp) & 1)==1)
  868. parityPerField|=VU_PARITY_BIT;
  869. temp=(byte)(((byte *)&prevUnitNo)[0]^((byte *)&prevUnitNo)[1]);
  870. if((onesCount(temp) & 1)==1)
  871. parityPerField|=PU_PARITY_BIT;
  872. if((onesCount(ANAC) & 1)==1)
  873. parityPerField|=ANAC_PARITY_BIT;
  874. if((onesCount(NAC) & 1)==1)
  875. parityPerField|=NAC_PARITY_BIT;
  876. /* Store fields in proper unit header record */
  877. toLE2(unitData.virtualUnitNo,virtualUnitNo);
  878. toLE2(secondUnitData.virtualUnitNo,virtualUnitNo);
  879. toLE2(unitData.prevUnitNo,prevUnitNo);
  880. toLE2(secondUnitData.prevUnitNo,prevUnitNo);
  881. unitData.ANAC=secondUnitData.ANAC=ANAC;
  882. unitData.NAC=secondUnitData.NAC=NAC;
  883. unitData.parityPerField=secondUnitData.parityPerField=parityPerField;
  884. unitData.discarded=DISCARD;
  885. /* Write first unit header */
  886. status = vol.flash->write(vol.flash,
  887. unitBaseAddress(vol,unitNo) + UNIT_DATA_OFFSET,
  888. &unitData,
  889. sizeof(ANANDUnitHeader),
  890. EXTRA);
  891. if(status == flOK) /* Write second unit header */
  892. status = vol.flash->write(vol.flash, unitBaseAddress(vol,unitNo) +
  893. SECOND_HEADER_OFFSET+UNIT_DATA_OFFSET,
  894. &secondUnitData,
  895. sizeof(SecondANANDUnitHeader),
  896. EXTRA);
  897. if(status == flOK)
  898. {
  899. #if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
  900. if (vol.flash->socket->verifyWrite == FL_ON)
  901. goto fillCache;
  902. #endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
  903. #ifdef NFTL_CACHE
  904. if (vol.ucache != NULL) /* Mark unit cache as none valid before read */
  905. {
  906. vol.ucache[unitNo].virtualUnitNo = 0xDEAD;
  907. vol.ucache[unitNo].prevUnitNo = 0xDEAD;
  908. }
  909. #endif /* NFTL_CACHE */
  910. status = getUnitData(&vol,unitNo,&newVirtualUnitNo, &newPrevUnitNo,&newANAC,&newNAC,&parityPerField);
  911. if (status == flOK)
  912. {
  913. if ((virtualUnitNo == newVirtualUnitNo) &&
  914. (prevUnitNo == newPrevUnitNo ) &&
  915. (!badParityResult(parityPerField) ) )
  916. goto fillCache;
  917. }
  918. }
  919. /* If we reached here we failed in writing unit header */
  920. /* Erase unit and report write fault */
  921. DEBUG_PRINT(("setUnitData : Failed setting unit data\r\n"));
  922. status = formatUnit(&vol,unitNo,UNIT_TAILER_OFFSET);
  923. if (status != flOK)
  924. {
  925. markUnitBad(&vol,unitNo);
  926. return status;
  927. }
  928. else
  929. {
  930. return flWriteFault;
  931. }
  932. fillCache: /* Unit headers were placed OK, now update cache */
  933. #ifdef NFTL_CACHE
  934. /* Update ANANDUnitHeader cache to prevent re-filling from flash */
  935. if (vol.ucache != NULL) {
  936. vol.ucache[unitNo].virtualUnitNo = virtualUnitNo;
  937. vol.ucache[unitNo].prevUnitNo = prevUnitNo;
  938. vol.ucache[unitNo].ANAC = ANAC;
  939. vol.ucache[unitNo].NAC = NAC;
  940. }
  941. #endif /* NFTL_CACHE */
  942. return flOK;
  943. }
  944. /*----------------------------------------------------------------------*/
  945. /* d i s c a r d Q u i c k M o u n t I n f o */
  946. /* */
  947. /* Mark quick mount information is none valid. */
  948. /* */
  949. /* Parameters: */
  950. /* vol : Pointer identifying drive */
  951. /* */
  952. /* Returns: */
  953. /* FLStatus : 0 on success, failed otherwise */
  954. /*----------------------------------------------------------------------*/
  955. static FLStatus discardQuickMountInfo(Bnand vol)
  956. {
  957. #ifndef RAM_MTD
  958. static const
  959. #endif /* RAM_MTD */
  960. dword tmp = 0;
  961. /* Dis - validate quick mount data */
  962. if(vol.firstMediaWrite == FALSE)
  963. {
  964. vol.firstMediaWrite = TRUE;
  965. return vol.flash->write(vol.flash, QUICK_MOUNT_VALID_SIGN_OFFSET +
  966. ((dword)vol.firstQuickMountUnit <<
  967. vol.unitSizeBits),
  968. &tmp,
  969. sizeof(tmp),
  970. 0);
  971. }
  972. return flOK;
  973. }
  974. /*----------------------------------------------------------------------*/
  975. /* m a r k A s I g n o r e d */
  976. /* */
  977. /* Mark sector at given address as ignored. */
  978. /* */
  979. /* Parameters: */
  980. /* vol : Pointer identifying drive */
  981. /* addr : Physical address of the sector */
  982. /* */
  983. /*----------------------------------------------------------------------*/
  984. static void markAsIgnored(Bnand vol,CardAddress addr)
  985. {
  986. #ifndef RAM_MTD
  987. static const
  988. #endif /* RAM_MTD */
  989. byte sectorFlags[2] = {SECTOR_IGNORE,SECTOR_IGNORE};
  990. DEBUG_PRINT(("markAsIgnored : A sector is being marked as ignored\r\n"));
  991. discardQuickMountInfo(&vol);
  992. #ifdef NFTL_CACHE
  993. setSectorFlagsCache(&vol, addr, SECTOR_IGNORE);
  994. #endif /* NFTL_CACHE */
  995. vol.flash->write(vol.flash,addr+SECTOR_DATA_OFFSET,sectorFlags,sizeof(sectorFlags),EXTRA);
  996. #ifdef MAKE_SURE_IGNORE_HAS_BAD_EDC
  997. /* Force remapping of internal catched sector */
  998. vol.flash->socket->remapped = TRUE;
  999. /* Make sure EDC is wrong - a slite problem with PPP */
  1000. if(vol.flash->read(vol.flash,addr,inftlBuffer,sizeof(inftlBuffer),EDC)==flOK)
  1001. {
  1002. tffsset(inftlBuffer,0,sizeof(inftlBuffer));
  1003. vol.flash->write(vol.flash,addr,inftlBuffer,sizeof(inftlBuffer),0);
  1004. }
  1005. #if (defined(VERIFY_WRITE) || defined (VERIFY_VOLUME) || defined(VERIFY_ERASED_SECTOR))
  1006. /* Now restore the ff's for the verifySectors routine */
  1007. tffsset(inftlBuffer,0xff,sizeof(inftlBuffer));
  1008. #endif /* VERIFY_WRITE || VERIFY_VOLUME || VERIFY_ERASED_SECTOR */
  1009. #endif /* MAKE_SURE_IGNORE_HAS_BAD_EDC */
  1010. }
  1011. #endif /* FL_READ_ONLY */
  1012. /*----------------------------------------------------------------------*/
  1013. /* v i r t u a l 2 P h y s i c a l */
  1014. /* */
  1015. /* Translate virtual sector number to physical address. */
  1016. /* */
  1017. /* Parameters: */
  1018. /* vol : Pointer identifying drive */
  1019. /* sectorNo : Virtual sector number */
  1020. /* startAddress : Physical address to start from */
  1021. /* lastOK : TRUE - the current sector in the last unit of */
  1022. /* virtual unit chain is free (not marked as */
  1023. /* deleted / ignored or used). */
  1024. /* */
  1025. /* Note: The first unit of the search is assumed to be valid. */
  1026. /* */
  1027. /* Returns: */
  1028. /* physical address of sectorNo */
  1029. /*----------------------------------------------------------------------*/
  1030. static CardAddress virtual2Physical(Bnand vol, SectorNo sectorNo,
  1031. CardAddress startAddress,FLBoolean* lastOK)
  1032. {
  1033. word unitOffset = (word)((sectorNo & vol.sectorsPerUnitMask) << SECTOR_SIZE_BITS);
  1034. ANANDUnitNo unitNo, virUnitNo;
  1035. ANANDUnitNo chainBound = 0;
  1036. CardAddress sectorAddress = ANAND_UNASSIGNED_ADDRESS;
  1037. byte sectorFlags = SECTOR_FREE;
  1038. /* follow the chain */
  1039. virUnitNo = (ANANDUnitNo)(sectorNo >> vol.sectorsPerUnitBits);
  1040. if (startAddress == ANAND_UNASSIGNED_ADDRESS)
  1041. {
  1042. /* Start from last unit in chain */
  1043. unitNo = vol.virtualUnits[virUnitNo];
  1044. }
  1045. else
  1046. {
  1047. /* Start from the unit that follows the given unit */
  1048. TL_DEBUG_PRINT(tl_out,"virtual2Physical : Virtual to physical started from middle of chain on unit %d\n",virUnitNo);
  1049. SET_EXIT(INFTL_FAILED_MOUNT);
  1050. unitNo = getPrevUnit(&vol,(ANANDUnitNo)((startAddress >> vol.unitSizeBits) - vol.firstUnit),virUnitNo);
  1051. if(unitNo == ANAND_BAD_CHAIN_UNIT)
  1052. return ANAND_BAD_CHAIN_ADDRESS;
  1053. }
  1054. for (;unitNo != ANAND_NO_UNIT;unitNo = getPrevUnit(&vol,unitNo,virUnitNo))
  1055. {
  1056. if((unitNo == ANAND_BAD_CHAIN_UNIT ) ||
  1057. (chainBound >= DOUBLE_MAX_UNIT_CHAIN) )
  1058. return ANAND_BAD_CHAIN_ADDRESS;
  1059. sectorAddress = unitBaseAddress(vol,unitNo) + unitOffset;
  1060. sectorFlags = getSectorFlags(&vol,sectorAddress);
  1061. /* Report if the last unit of the chain is used */
  1062. if ((unitNo == vol.virtualUnits[virUnitNo]) &&
  1063. (sectorFlags != SECTOR_FREE))
  1064. *lastOK = FALSE;
  1065. if((sectorFlags==SECTOR_FREE) || (sectorFlags==SECTOR_IGNORE))
  1066. {
  1067. chainBound++;
  1068. continue;
  1069. }
  1070. break;
  1071. }
  1072. if((sectorFlags==SECTOR_IGNORE)||(sectorFlags==SECTOR_FREE)||(sectorFlags==SECTOR_DELETED)) /* Sector was never written*/
  1073. return ANAND_UNASSIGNED_ADDRESS;
  1074. return sectorAddress;
  1075. }
  1076. /*----------------------------------------------------------------------*/
  1077. /* i n i t I N F T L b a s i c */
  1078. /* */
  1079. /* Initializes essential volume data */
  1080. /* */
  1081. /* Note : This routine is called both by the mount and format initINFTL */
  1082. /* and as a preparation for counting the number of partitions function. */
  1083. /* */
  1084. /* Parameters: */
  1085. /* vol : Pointer identifying drive */
  1086. /* flash : Flash media mounted on this socket */
  1087. /* */
  1088. /* Returns: */
  1089. /* FLStatus : 0 on success, failed otherwise */
  1090. /*----------------------------------------------------------------------*/
  1091. static FLStatus initINFTLbasic(Bnand vol, FLFlash *flash)
  1092. {
  1093. dword noOfUnits; /* Keep this variable dword , for large DiskOnChips */
  1094. if (flash == NULL || !(flash->flags & INFTL_ENABLED))
  1095. {
  1096. DEBUG_PRINT(("\nDebug: media is not fit for INFTL format.\r\n"));
  1097. return flUnknownMedia;
  1098. }
  1099. if(flash->readBBT == NULL)
  1100. {
  1101. DEBUG_PRINT(("\nDEBUG : MTD read BBT routine was not initialized\r\n"));
  1102. return flFeatureNotSupported;
  1103. }
  1104. vol.flash = flash;
  1105. vol.erasableBlockSizeBits = flash->erasableBlockSizeBits;
  1106. vol.unitSizeBits = vol.erasableBlockSizeBits;
  1107. noOfUnits = (dword)((vol.flash->noOfChips * vol.flash->chipSize) >> vol.unitSizeBits);
  1108. /* Bound number of units to find room in 64 Kbytes Segment */
  1109. if((noOfUnits > MAX_UNIT_NUM) && (vol.unitSizeBits < MAX_UNIT_SIZE_BITS))
  1110. {
  1111. vol.unitSizeBits++;
  1112. noOfUnits >>= 1;
  1113. }
  1114. vol.blockMultiplierBits = vol.unitSizeBits - vol.erasableBlockSizeBits;
  1115. /* get pointer to buffer (we assume SINGLE_BUFFER is not defined) */
  1116. vol.buffer = flBufferOf(flSocketNoOf(vol.flash->socket));
  1117. #ifdef VERIFY_ERASED_SECTOR
  1118. vol.verifyBuffer = (dword *)flReadBackBufferOf(flSocketNoOf(flash->socket));
  1119. #endif /* VERIFY_ERASED_SECTOR */
  1120. flash->socket->remapped = TRUE;
  1121. return flOK;
  1122. }
  1123. /*----------------------------------------------------------------------*/
  1124. /* i n i t N F T L */
  1125. /* */
  1126. /* Initializes essential volume data as a preparation for mount or */
  1127. /* format. */
  1128. /* */
  1129. /* Parameters: */
  1130. /* vol : Pointer identifying drive */
  1131. /* flash : Flash media mounted on this socket */
  1132. /* */
  1133. /* Returns: */
  1134. /* FLStatus : 0 on success, failed otherwise */
  1135. /*----------------------------------------------------------------------*/
  1136. static FLStatus initINFTL(Bnand vol, FLFlash *flash)
  1137. {
  1138. dword chipSize; /* Keep this variable dword , for large DiskOnChips */
  1139. FLStatus status;
  1140. if(flash!=NULL)
  1141. {
  1142. tffsset(&vol,0,sizeof(Bnand)); /* Clear Bnand volume */
  1143. #ifdef NT5PORT
  1144. vol.socketNo = (byte)(flSocketNoOf(flash->socket)); /* socket No */
  1145. #else
  1146. vol.socketNo = flSocketNoOf(flash->socket); /* socket No */
  1147. #endif /*NT5PORT*/
  1148. }
  1149. status = initINFTLbasic(&vol, flash);
  1150. if(status != flOK)
  1151. return status;
  1152. chipSize = (dword)(flash->chipSize * flash->noOfChips);
  1153. #ifndef FL_MALLOC
  1154. if (chipSize > (dword)MAX_VOLUME_MBYTES << 20)
  1155. {
  1156. DEBUG_PRINT(("\nDebug: TrueFFS is customized for smaller media capacities.\r\n"));
  1157. return flGeneralFailure;
  1158. }
  1159. if (ASSUMED_NFTL_UNIT_SIZE > (1L<<vol.unitSizeBits))
  1160. {
  1161. DEBUG_PRINT(("\nDebug: TrueFFS is customized for smaller unit sizes.\r\n"));
  1162. return flGeneralFailure;
  1163. }
  1164. #endif /* FL_MALLOC */
  1165. vol.physicalUnits = NULL;
  1166. vol.virtualUnits = NULL;
  1167. #ifdef NFTL_CACHE
  1168. vol.ucache = NULL;
  1169. vol.scache = NULL;
  1170. #endif /* NFTL_CACHE */
  1171. vol.mappedSectorNo = UNASSIGNED_SECTOR;
  1172. vol.countsValid = 0; /* No units have a valid count yet */
  1173. vol.firstUnit = 0;
  1174. vol.sectorsPerUnit = 1 << (vol.unitSizeBits - SECTOR_SIZE_BITS);
  1175. vol.sectorsPerUnitBits = vol.unitSizeBits - SECTOR_SIZE_BITS;
  1176. vol.sectorsPerUnitMask = vol.sectorsPerUnit - 1;
  1177. vol.noOfUnits = (ANANDUnitNo)(chipSize >> vol.unitSizeBits);
  1178. vol.firstMediaWrite = FALSE;
  1179. #if (defined(VERIFY_WRITE) || defined(VERIFY_VOLUME) || defined(VERIFY_ERASED_SECTOR))
  1180. vol.verifiedSectorNo = 0; /* Largest sector verified so far */
  1181. #endif /* VERIFY_WRITE || VERIFY_VOLUME || VERIFY_ERASED_SECTOR */
  1182. #ifdef CHECK_MOUNT
  1183. vol.debugState = 0;
  1184. #endif /* CHECK_MOUNT */
  1185. return flOK;
  1186. }
  1187. /*----------------------------------------------------------------------*/
  1188. /* i n i t T a b l e s */
  1189. /* */
  1190. /* Allocates and initializes the dynamic volume table, including the */
  1191. /* unit tables and secondary virtual map. */
  1192. /* */
  1193. /* Parameters: */
  1194. /* vol : Pointer identifying drive */
  1195. /* ramForUnits : Number of bytes allocated to previous volumes */
  1196. /* */
  1197. /* Returns: */
  1198. /* FLStatus : 0 on success, failed otherwise */
  1199. /*----------------------------------------------------------------------*/
  1200. #ifdef FL_MALLOC
  1201. static FLStatus initTables(Bnand vol)
  1202. {
  1203. /* Allocate the conversion tables */
  1204. vol.physicalUnits = (ANANDPhysUnit FAR1*) FL_FAR_MALLOC(vol.noOfUnits * sizeof(ANANDPhysUnit));
  1205. if (vol.noOfVirtualUnits > 0)
  1206. vol.virtualUnits = (ANANDUnitNo FAR1*) FL_FAR_MALLOC(vol.noOfVirtualUnits * sizeof(ANANDUnitNo));
  1207. if ((vol.physicalUnits == NULL) ||
  1208. ((vol.virtualUnits == NULL) && (vol.noOfVirtualUnits > 0)))
  1209. {
  1210. DEBUG_PRINT(("\nDebug: failed allocating conversion tables for INFTL.\r\n"));
  1211. return flNotEnoughMemory;
  1212. }
  1213. /* Allocate the multi-sector buffer (one per socket) */
  1214. if (++(multiSectorBufCounter[vol.socketNo]) == 0)
  1215. {
  1216. multiSectorBuf[vol.socketNo] = (byte *)FL_MALLOC(SECTOR_SIZE<<1);
  1217. if (multiSectorBuf[vol.socketNo] == NULL)
  1218. {
  1219. DEBUG_PRINT(("\nDebug: failed allocating multi-sector buffers for INFTL.\r\n"));
  1220. return flNotEnoughMemory;
  1221. }
  1222. }
  1223. return flOK;
  1224. }
  1225. #else
  1226. static FLStatus initTables(Bnand vol,dword ramForUnits)
  1227. {
  1228. Sbyte *heapPtr;
  1229. vol.heap = &socketHeap[flSocketNoOf(vol.flash->socket)][ramForUnits];
  1230. heapPtr = vol.heap;
  1231. vol.physicalUnits = (ANANDPhysUnit FAR1*) heapPtr;
  1232. heapPtr += vol.noOfUnits * sizeof(ANANDPhysUnit);
  1233. vol.virtualUnits = (ANANDUnitNo FAR1*) heapPtr;
  1234. heapPtr += vol.noOfVirtualUnits * sizeof(ANANDUnitNo);
  1235. if ((ANAND_HEAP_SIZE < heapPtr - vol.heap) ||
  1236. (ASSUMED_NFTL_UNIT_SIZE > 1L << vol.unitSizeBits))
  1237. {
  1238. DEBUG_PRINT(("\nDebug: not enough memory for INFTL conversion tables.\r\n"));
  1239. return flNotEnoughMemory;
  1240. }
  1241. return flOK;
  1242. }
  1243. #endif /* FL_MALLOC */
  1244. /*----------------------------------------------------------------------*/
  1245. /* f i r s t I n C h a i n */
  1246. /* */
  1247. /* Find first unit in chain. */
  1248. /* */
  1249. /* Parameters: */
  1250. /* vol : Pointer identifying drive */
  1251. /* unitNo : Start the search from this unit */
  1252. /* nextUnit : Returns the Second unit of the chain. */
  1253. /* */
  1254. /* Returns: */
  1255. /* Physical unit number of the last unit in chain. */
  1256. /*----------------------------------------------------------------------*/
  1257. static ANANDUnitNo firstInChain(Bnand vol, ANANDUnitNo unitNo,ANANDUnitNo* nextUnit)
  1258. {
  1259. ANANDUnitNo firstVirtualUnitNo, firstReplacementUnitNo,prevVirtualUnitNo;
  1260. ANANDUnitNo nextUnitNo,prevReplacementUnitNo;
  1261. ANANDUnitNo chainBound = 0;
  1262. byte ANAC,NAC,parityPerField;
  1263. if(unitNo==ANAND_NO_UNIT) /* Sanity check */
  1264. {
  1265. if(nextUnit!=NULL)
  1266. *nextUnit=ANAND_NO_UNIT;
  1267. return unitNo;
  1268. }
  1269. /* If this unit is the first of its chain , no need to keep looking */
  1270. if( vol.physicalUnits[unitNo] & FIRST_IN_CHAIN )
  1271. {
  1272. if(nextUnit!=NULL)
  1273. *nextUnit=ANAND_NO_UNIT;
  1274. return unitNo;
  1275. }
  1276. getUnitData(&vol,unitNo,&firstVirtualUnitNo,&firstReplacementUnitNo,&ANAC,&NAC,&parityPerField);
  1277. /* check if unit is valid */
  1278. if(badParityResult(parityPerField))
  1279. {
  1280. DEBUG_PRINT(("\nFirst In chain found bad unit header\r\n"));
  1281. if(nextUnit!=NULL)
  1282. *nextUnit=ANAND_NO_UNIT;
  1283. return ANAND_BAD_CHAIN_UNIT;
  1284. }
  1285. nextUnitNo=unitNo;
  1286. unitNo=firstReplacementUnitNo;
  1287. while( (unitNo < vol.noOfUnits) && /* Validate replacement unit no. */
  1288. (chainBound < DOUBLE_MAX_UNIT_CHAIN) )
  1289. {
  1290. if(unitNo==ANAND_NO_UNIT)
  1291. break;
  1292. getUnitData(&vol,unitNo,&prevVirtualUnitNo,&prevReplacementUnitNo,&ANAC,&NAC,&parityPerField);
  1293. /* check if unit is valid */
  1294. if(badParityResult(parityPerField))
  1295. {
  1296. DEBUG_PRINT(("\nFirst In chain found bad unit header\r\n"));
  1297. if(nextUnit!=NULL)
  1298. *nextUnit=ANAND_NO_UNIT;
  1299. return ANAND_BAD_CHAIN_UNIT;
  1300. }
  1301. if(( vol.physicalUnits[unitNo] & FIRST_IN_CHAIN )&&(firstVirtualUnitNo==prevVirtualUnitNo))
  1302. {
  1303. if(nextUnit!=NULL)
  1304. *nextUnit=nextUnitNo;
  1305. return unitNo;
  1306. }
  1307. if( prevVirtualUnitNo != (firstVirtualUnitNo ) )
  1308. {
  1309. /* This one does not belong to the chain */
  1310. if(nextUnit!=NULL)
  1311. *nextUnit=ANAND_NO_UNIT;
  1312. return nextUnitNo;
  1313. }
  1314. nextUnitNo = unitNo;
  1315. unitNo = prevReplacementUnitNo;
  1316. chainBound++;
  1317. }
  1318. return ANAND_BAD_CHAIN_UNIT;
  1319. }
  1320. #ifndef FL_READ_ONLY
  1321. /*----------------------------------------------------------------------*/
  1322. /* w r i t e A n d C h e c k */
  1323. /* */
  1324. /* Physicaly write up to 2 sectors on given address and verify. */
  1325. /* */
  1326. /* Parameters: */
  1327. /* vol : Pointer identifying drive */
  1328. /* address : Physical address of the sector to write to */
  1329. /* fromAddress : Buffer of data to write */
  1330. /* flags : Write flags (ECC, overwrite etc.) */
  1331. /* howMany : Number of sectors to write. */
  1332. /* */
  1333. /* Returns: */
  1334. /* Status : 0 on success, failed otherwise. */
  1335. /*----------------------------------------------------------------------*/
  1336. static FLStatus writeAndCheck(Bnand vol,
  1337. CardAddress address,
  1338. void FAR1 *fromAddress,
  1339. unsigned flags,word howMany)
  1340. {
  1341. FLStatus status;
  1342. register int i;
  1343. #ifdef VERIFY_ERASED_SECTOR
  1344. register int noOfDword;
  1345. int j;
  1346. #endif /* VERIFY_ERASED_SECTOR */
  1347. /* Toggle verify write flag */
  1348. #if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
  1349. switch (flVerifyWrite[vol.socketNo][vol.flash->socket->curPartition])
  1350. {
  1351. case FL_OFF:
  1352. if (vol.verifiedSectorNo>vol.curSectorWrite+howMany)
  1353. break;
  1354. case FL_ON:
  1355. #ifdef VERIFY_WRITE
  1356. vol.flash->socket->verifyWrite = FL_ON;
  1357. #endif /* VERIFY_WRITE */
  1358. #ifdef VERIFY_ERASED_SECTOR
  1359. /* Make sure all of the sectors are really free */
  1360. checkStatus(vol.flash->read(vol.flash,address,vol.verifyBuffer,SECTOR_SIZE*howMany,0));
  1361. noOfDword = SECTOR_SIZE/sizeof(dword);
  1362. for(j=0;j<howMany;j++) /* Loop over sectors */
  1363. {
  1364. for(i = 0;i<noOfDword;i++) /* Loop over sector data */
  1365. {
  1366. if(vol.verifyBuffer[i]!=0xffffffffL)
  1367. {
  1368. markAsIgnored(&vol,address+j*SECTOR_SIZE);
  1369. DEBUG_PRINT(("writeAndCheck : The sector was not erased and is ignored\r\n"));
  1370. return flWriteFault;
  1371. }
  1372. }
  1373. }
  1374. #endif /* VERIFY_ERASED_SECTOR */
  1375. break;
  1376. default:
  1377. break;
  1378. }
  1379. #endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
  1380. /* Write sector */
  1381. status = vol.flash->write(vol.flash,address,fromAddress,SECTOR_SIZE*howMany,(word)flags);
  1382. #ifdef VERIFY_WRITE
  1383. if(flVerifyWrite[vol.socketNo][vol.flash->socket->curPartition] != FL_ON)
  1384. vol.flash->socket->verifyWrite = FL_OFF;
  1385. #endif /* VERIFY_WRITE */
  1386. /* Make sure write succeded and update sector catche */
  1387. if (status == flWriteFault)
  1388. { /* write failed, ignore this sector */
  1389. DEBUG_PRINT(("writeAndCheck : Write of a sector failed and was marked as ignored\r\n"));
  1390. for(i=0;i<howMany;i++)
  1391. {
  1392. markAsIgnored(&vol,address+i*SECTOR_SIZE);
  1393. }
  1394. }
  1395. #ifdef NFTL_CACHE
  1396. else
  1397. {
  1398. for(i=0;i<howMany;i++)
  1399. setSectorFlagsCache(&vol, address+i*SECTOR_SIZE, SECTOR_USED);
  1400. }
  1401. #endif /* NFTL_CACHE */
  1402. return status;
  1403. }
  1404. /*----------------------------------------------------------------------*/
  1405. /* a s s i g n U n i t */
  1406. /* */
  1407. /* Assigns a virtual unit no. to a unit */
  1408. /* */
  1409. /* Parameters: */
  1410. /* vol : Pointer identifying drive */
  1411. /* unitNo : Physical unit number */
  1412. /* virtualUnitNo : Virtual unit number to assign */
  1413. /* ANAC : Accumulating Number Along Chain */
  1414. /* NAC : Number Along Chain. */
  1415. /* */
  1416. /* Returns: */
  1417. /* FLStatus : 0 on success, failed otherwise */
  1418. /*----------------------------------------------------------------------*/
  1419. static FLStatus assignUnit(Bnand vol, ANANDUnitNo unitNo,
  1420. ANANDUnitNo virtualUnitNo, byte ANAC,
  1421. byte NAC)
  1422. {
  1423. FLStatus status;
  1424. /* Perpare sector count */
  1425. if((vol.countsValid > virtualUnitNo ) && /* Has sector count */
  1426. (vol.virtualUnits[virtualUnitNo] != ANAND_NO_UNIT)) /* Was used */
  1427. {
  1428. vol.physicalUnits[unitNo] = countOf(vol.virtualUnits[virtualUnitNo]);
  1429. }
  1430. else
  1431. {
  1432. vol.physicalUnits[unitNo] = 0;
  1433. }
  1434. /* Vadim for ASAP policy*/
  1435. #ifdef ENVIRONMENT_VARS
  1436. if(NAC>=MAX_UNIT_CHAIN)
  1437. NAC=MAX_UNIT_CHAIN-1;
  1438. #endif /* ENVIRONMENT_VARS */
  1439. status = setUnitData(&vol,unitNo,virtualUnitNo,(ANANDUnitNo)vol.virtualUnits[virtualUnitNo],(byte)(ANAC+1),(byte)(NAC+1));
  1440. if (status != flOK)
  1441. {
  1442. markUnitBad(&vol,unitNo);
  1443. }
  1444. else
  1445. {
  1446. if(unitNo>vol.noOfUnits)
  1447. return flGeneralFailure;
  1448. vol.virtualUnits[virtualUnitNo]=unitNo;
  1449. if(vol.freeUnits)
  1450. vol.freeUnits--;
  1451. }
  1452. return status;
  1453. }
  1454. /*----------------------------------------------------------------------*/
  1455. /* f o r m a t C h a i n */
  1456. /* */
  1457. /* Format all the units in a chain. Start from the last one and go */
  1458. /* backwards until unitNo is reached. */
  1459. /* */
  1460. /* Parameters: */
  1461. /* vol : Pointer identifying drive */
  1462. /* unitNo : Format the chain from this unit onwards */
  1463. /* */
  1464. /* Returns: */
  1465. /* FLStatus : 0 on success, failed otherwise */
  1466. /*----------------------------------------------------------------------*/
  1467. static FLStatus formatChain(Bnand vol, ANANDUnitNo unitNo)
  1468. {
  1469. /* Erase the chain from end to start */
  1470. ANANDUnitNo chainBound;
  1471. ANANDUnitNo unitToErase;
  1472. FLStatus status;
  1473. for (chainBound=0;; chainBound++)
  1474. {
  1475. /* Find last unit in chain */
  1476. unitToErase = firstInChain(&vol,unitNo,NULL);
  1477. if((unitToErase == ANAND_BAD_CHAIN_UNIT ) ||
  1478. (chainBound >= DOUBLE_MAX_UNIT_CHAIN) )
  1479. return flGeneralFailure;
  1480. status = formatUnit(&vol,unitToErase,UNIT_TAILER_OFFSET);
  1481. if(status != flOK)
  1482. return status;
  1483. if (unitToErase == unitNo)
  1484. break; /* Erased everything */
  1485. }
  1486. return flOK;
  1487. }
  1488. /*----------------------------------------------------------------------*/
  1489. /* c r e a t e U n i t C o u n t */
  1490. /* */
  1491. /* Count the number of sectors in a unit that hold valid data. */
  1492. /* */
  1493. /* Parameters: */
  1494. /* vol : Pointer identifying drive */
  1495. /* unitNo : Physical unit number */
  1496. /* */
  1497. /*----------------------------------------------------------------------*/
  1498. static void createUnitCount(Bnand vol, ANANDUnitNo unitNo)
  1499. {
  1500. register int i;
  1501. SectorNo sectorNo;
  1502. ANANDUnitNo physicalUnitNo = vol.virtualUnits[unitNo];
  1503. CardAddress sectorAddress;
  1504. FLBoolean lastOK; /* Dummy variable */
  1505. if (physicalUnitNo == ANAND_NO_UNIT)
  1506. return;
  1507. /* Get a count of the valid sector in this unit */
  1508. setUnitCount(physicalUnitNo,0);
  1509. sectorNo = (SectorNo)unitNo << vol.sectorsPerUnitBits;
  1510. for (i = 0; i < vol.sectorsPerUnit; i++, sectorNo++)
  1511. {
  1512. sectorAddress = virtual2Physical(&vol,sectorNo,ANAND_UNASSIGNED_ADDRESS,&lastOK);
  1513. /* Do not check for brocken chain. If one exists we will have a */
  1514. /* large sector count , which will delay folding. */
  1515. if (sectorAddress != ANAND_UNASSIGNED_ADDRESS)
  1516. vol.physicalUnits[physicalUnitNo]++;
  1517. }
  1518. }
  1519. #if (defined(VERIFY_WRITE) || defined(VERIFY_VOLUME) || defined(VERIFY_ERASED_SECTOR))
  1520. /*----------------------------------------------------------------------*/
  1521. /* v e r i f y S e c t o r s */
  1522. /* */
  1523. /* Verify sectors for power failures simptoms and fix if neccesary. */
  1524. /* */
  1525. /* Parameters: */
  1526. /* vol : Pointer identifying drive */
  1527. /* sectorCount : No of sectors to verify */
  1528. /* */
  1529. /* Returns: */
  1530. /* FLStatus : 0 on success, failed otherwise */
  1531. /*----------------------------------------------------------------------*/
  1532. FLStatus verifySectors(Bnand vol, dword sectorCount)
  1533. {
  1534. FLStatus status;
  1535. word unitOffset;
  1536. ANANDUnitNo virUnitNo;
  1537. ANANDUnitNo unitNo;
  1538. dword curRead;
  1539. CardAddress sectorAddress;
  1540. word j;
  1541. byte chainBound,index;
  1542. byte sectorFlags[2];
  1543. static FLBoolean scannedBlocks[MAX_SECTORS_PER_BLOCK];
  1544. byte FAR1* buffer;
  1545. if (vol.verifiedSectorNo >= vol.virtualSectors)
  1546. return flOK;
  1547. /* Initialize variables */
  1548. buffer = flReadBackBufferOf(vol.socketNo);
  1549. if(buffer==NULL)
  1550. {
  1551. DEBUG_PRINT(("\nDebug : Can not verify sectors since no buffer was allocated\r\n"));
  1552. return flOK;
  1553. }
  1554. virUnitNo = (ANANDUnitNo)(vol.verifiedSectorNo >> vol.sectorsPerUnitBits);
  1555. sectorCount = TFFSMIN(vol.virtualSectors - vol.verifiedSectorNo,sectorCount);
  1556. /* Force remapping of internal catched sector */
  1557. vol.flash->socket->remapped = TRUE;
  1558. tffsset(inftlBuffer,0xff,sizeof(inftlBuffer)); /* Useds as FF'S buffer */
  1559. /* Run over required number of virtual sectors */
  1560. for (; sectorCount > 0 ; virUnitNo++ ,sectorCount -= curRead)
  1561. {
  1562. /* Calculate needed number of sector in this unit */
  1563. unitOffset = (word)((vol.verifiedSectorNo & vol.sectorsPerUnitMask) << SECTOR_SIZE_BITS);
  1564. curRead = TFFSMIN(sectorCount,((1UL<<vol.unitSizeBits)-unitOffset)>>SECTOR_SIZE_BITS);
  1565. unitNo = vol.virtualUnits[virUnitNo];
  1566. if(unitNo == ANAND_NO_UNIT) /* Unit is empty */
  1567. {
  1568. vol.verifiedSectorNo += ((1<<vol.unitSizeBits)-unitOffset)>>SECTOR_SIZE_BITS;
  1569. continue;
  1570. }
  1571. /* Unit is not empty - initialize sector array */
  1572. if(unitOffset==0)
  1573. tffsset(scannedBlocks,FALSE,sizeof(scannedBlocks));
  1574. for(chainBound=0;;chainBound++)
  1575. { /* Go over the chain from newest unit to oldest */
  1576. if(chainBound!=0) /* Get next unit */
  1577. {
  1578. unitNo = getPrevUnit(&vol,unitNo,virUnitNo);
  1579. if((unitNo == ANAND_BAD_CHAIN_UNIT ) ||
  1580. (chainBound>=DOUBLE_MAX_UNIT_CHAIN) )
  1581. {
  1582. DEBUG_PRINT(("\nverifySectors : Bad chain was found\r\n"));
  1583. return flGeneralFailure;
  1584. }
  1585. if(unitNo == ANAND_NO_UNIT)
  1586. break;
  1587. }
  1588. /* Check required sectors of the unit - 2 sectors at a time */
  1589. sectorAddress = unitBaseAddress(vol,unitNo)+unitOffset;
  1590. for (index=0;index<curRead;index+=2)
  1591. {
  1592. /* Read sector flags if needed
  1593. *
  1594. * Note - getSectorFlags routine must not change the inftlBuffer
  1595. */
  1596. if(WasSectorChecked(sectorAddress) == FALSE)
  1597. sectorFlags[0] = getSectorFlags(&vol,sectorAddress);
  1598. if(WasSectorChecked(sectorAddress+SECTOR_SIZE) == FALSE)
  1599. sectorFlags[1] = getSectorFlags(&vol,sectorAddress+SECTOR_SIZE);
  1600. /* Try checking 2 sectors together */
  1601. if((sectorFlags[0]==sectorFlags[1] ) &&
  1602. (WasSectorChecked(sectorAddress+SECTOR_SIZE) == FALSE) &&
  1603. (WasSectorChecked(sectorAddress) == FALSE))
  1604. {
  1605. /* Indenctical sector flags - sectors are checked together */
  1606. switch(sectorFlags[0])
  1607. {
  1608. case SECTOR_FREE:
  1609. status = vol.flash->read(vol.flash,sectorAddress,buffer,SECTOR_SIZE<<1,0);
  1610. if(status != flOK)
  1611. return status;
  1612. if (tffscmp(inftlBuffer,buffer,sizeof(inftlBuffer)))
  1613. {
  1614. markAsIgnored(&vol,sectorAddress);
  1615. createUnitCount(&vol,virUnitNo);
  1616. }
  1617. if (tffscmp(inftlBuffer,buffer+sizeof(inftlBuffer),sizeof(inftlBuffer)))
  1618. {
  1619. markAsIgnored(&vol,sectorAddress+SECTOR_SIZE);
  1620. createUnitCount(&vol,virUnitNo);
  1621. }
  1622. break;
  1623. case SECTOR_DELETED:
  1624. case SECTOR_USED:
  1625. status = vol.flash->read(vol.flash,sectorAddress,buffer,SECTOR_SIZE<<1,EDC);
  1626. if(status == flDataError)
  1627. {
  1628. status = vol.flash->read(vol.flash,sectorAddress,buffer,SECTOR_SIZE,EDC);
  1629. if(status != flOK)
  1630. {
  1631. markAsIgnored(&vol,sectorAddress);
  1632. status = vol.flash->read(vol.flash,sectorAddress+SECTOR_SIZE,buffer,SECTOR_SIZE,EDC);
  1633. if(status != flOK)
  1634. {
  1635. markAsIgnored(&vol,sectorAddress+SECTOR_SIZE);
  1636. }
  1637. else
  1638. {
  1639. MarkSectorAsChecked(sectorAddress+SECTOR_SIZE);
  1640. }
  1641. }
  1642. else
  1643. {
  1644. MarkSectorAsChecked(sectorAddress);
  1645. markAsIgnored(&vol,sectorAddress+SECTOR_SIZE);
  1646. }
  1647. createUnitCount(&vol,virUnitNo);
  1648. break;
  1649. }
  1650. MarkSectorAsChecked(sectorAddress);
  1651. default: /* SECTOR_IGNORE */
  1652. break;
  1653. }/* Flag type case */
  1654. sectorAddress+=SECTOR_SIZE<<1;
  1655. } /* Flags are indentical */
  1656. else /* Check each sectors individualy */
  1657. {
  1658. for(j=0;j<2;j++,sectorAddress+=SECTOR_SIZE)
  1659. {
  1660. if(WasSectorChecked(sectorAddress) == TRUE)
  1661. continue;
  1662. switch(sectorFlags[j])
  1663. {
  1664. case SECTOR_FREE:
  1665. status = vol.flash->read(vol.flash,sectorAddress,buffer,SECTOR_SIZE,0);
  1666. if(status != flOK)
  1667. return status;
  1668. if (tffscmp(inftlBuffer,buffer,sizeof(inftlBuffer)))
  1669. {
  1670. markAsIgnored(&vol,sectorAddress);
  1671. createUnitCount(&vol,virUnitNo);
  1672. }
  1673. break;
  1674. case SECTOR_USED:
  1675. case SECTOR_DELETED:
  1676. status = vol.flash->read(vol.flash,sectorAddress,buffer,SECTOR_SIZE,EDC);
  1677. if(status == flDataError)
  1678. {
  1679. markAsIgnored(&vol,sectorAddress);
  1680. createUnitCount(&vol,virUnitNo);
  1681. }
  1682. MarkSectorAsChecked(sectorAddress);
  1683. default: /* SECTOR_IGNORE || SECTOR_DELETED */
  1684. break;
  1685. } /* Flag type */
  1686. } /* Try second sector */
  1687. } /* Flags are NOT indentical */
  1688. } /* Loop over all sector of unit or until required sectors */
  1689. } /* Loop over all units chains */
  1690. vol.verifiedSectorNo+=curRead;
  1691. } /* Loop over all required sectors */
  1692. return flOK;
  1693. }
  1694. /*----------------------------------------------------------------------*/
  1695. /* c h e c k V o l u m e */
  1696. /* */
  1697. /* Scanthe entire media for partialy written sectors. */
  1698. /* */
  1699. /* Parameters: */
  1700. /* vol : Pointer identifying drive */
  1701. /* */
  1702. /* Returns: */
  1703. /* FLStatus : 0 on success, failed otherwise */
  1704. /*----------------------------------------------------------------------*/
  1705. static FLStatus checkVolume(Bnand vol)
  1706. {
  1707. return verifySectors(&vol, 0xffffffffL); /* Force scan of entire media */
  1708. }
  1709. #endif /* VERIFY_WRITE || VERIFY_VOLUME || VERIFY_ERASED_SECTOR */
  1710. /*----------------------------------------------------------------------*/
  1711. /* f o l d U n i t */
  1712. /* */
  1713. /* Copy all the sectors that hold valid data in the chain to the last */
  1714. /* unit of the chain and erase the chain. */
  1715. /* */
  1716. /* Parameters: */
  1717. /* vol : Pointer identifying drive */
  1718. /* virtualUnitNo : Virtual unit number of the first unit in */
  1719. /* chain. */
  1720. /* foldingFlag : One of the following flags: */
  1721. /* FL_NORMAL_FOLDING - Returns fail status if can not fold */
  1722. /* FL_FORCE_FOLDING - Force folding even if last sector is used */
  1723. /* FL_NOT_IN_PLACE - Fold into a unit with no erase mark */
  1724. /* */
  1725. /* Returns: */
  1726. /* FLStatus : 0 on success, failed otherwise */
  1727. /*----------------------------------------------------------------------*/
  1728. static FLStatus foldUnit(Bnand vol, ANANDUnitNo virtualUnitNo,
  1729. int foldingFlag)
  1730. {
  1731. ANANDUnitNo unitNo = vol.virtualUnits[virtualUnitNo];
  1732. ANANDUnitNo prevUnitNo;
  1733. SectorNo virtualSectorNo;
  1734. CardAddress targetSectorAddress;
  1735. int newSectorCount = 0;
  1736. int i;
  1737. byte ANAC,NAC,parityPerField;
  1738. #ifdef ENVIRONMENT_VARS
  1739. ANANDUnitNo nextUnitNo = ANAND_NO_UNIT;
  1740. CardAddress firstUnitAddress = ANAND_UNASSIGNED_ADDRESS;
  1741. ANANDUnitNo firstUnit = ANAND_NO_UNIT;
  1742. FLBoolean foldFirstOnly = (flPolicy[vol.socketNo]
  1743. [vol.flash->socket->curPartition] ==
  1744. FL_COMPLETE_ASAP) ? TRUE : FALSE;
  1745. #endif /* ENVIRONMENT_VARS */
  1746. #if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
  1747. byte verifyWriteState = flVerifyWrite[vol.socketNo]
  1748. [vol.flash->socket->curPartition];
  1749. #endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
  1750. FLBoolean lastOK;
  1751. byte chainBound;
  1752. FLStatus status;
  1753. CardAddress sourceSectorAddress;
  1754. /* Sanity checks */
  1755. if(unitNo>=vol.noOfUnits) /* Empty or INVALID */
  1756. {
  1757. return flGeneralFailure;
  1758. }
  1759. /* Internal statistics */
  1760. vol.unitsFolded++;
  1761. /* Force remapping of internal catched sector */
  1762. vol.flash->socket->remapped = TRUE;
  1763. virtualSectorNo = (SectorNo)virtualUnitNo << vol.sectorsPerUnitBits;
  1764. targetSectorAddress = unitBaseAddress(vol,unitNo);
  1765. /* When verify write option is set to FL_OFF a very lazy check of the */
  1766. /* media is done every time a folding operation is issued */
  1767. #if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
  1768. if(verifyWriteState == FL_OFF)
  1769. {
  1770. status = verifySectors(&vol,SECTORS_VERIFIED_PER_FOLDING);
  1771. if(status != flOK)
  1772. return status;
  1773. vol.curSectorWrite = virtualSectorNo; /* Store virtual sector Number */
  1774. }
  1775. #endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
  1776. /* When policy is set to FL_COMPLETE_ASAP - folding is performed only on */
  1777. /* the oldest unit, so find oldest unit and store its location */
  1778. #ifdef ENVIRONMENT_VARS
  1779. if(foldFirstOnly == TRUE)
  1780. {
  1781. firstUnit = firstInChain(&vol,unitNo,&nextUnitNo);
  1782. if(firstUnit == ANAND_BAD_CHAIN_UNIT) /* Error going along chain */
  1783. {
  1784. return flGeneralFailure;
  1785. }
  1786. firstUnitAddress = unitBaseAddress(vol,firstUnit);
  1787. }
  1788. #endif
  1789. /* If chain has no valid sectors simply erase it. */
  1790. if((vol.countsValid>virtualUnitNo) && /* Unit valid sectors were counted */
  1791. (countOf(unitNo)==0)) /* No valid sectors in unit chain */
  1792. {
  1793. #ifdef ENVIRONMENT_VARS
  1794. if((foldFirstOnly == TRUE) && (nextUnitNo != ANAND_NO_UNIT))
  1795. {
  1796. /* Erase only first unit of chain */
  1797. vol.physicalUnits[nextUnitNo] = FIRST_IN_CHAIN;
  1798. return formatChain(&vol,firstUnit);
  1799. }
  1800. else
  1801. #endif /* ENVIRONMENT_VARS */
  1802. {
  1803. /* Erase chain completely */
  1804. vol.virtualUnits[virtualUnitNo] = ANAND_NO_UNIT;
  1805. return formatChain(&vol,unitNo);
  1806. }
  1807. }
  1808. /* Single unit with valid sectors can not be folded */
  1809. if((vol.physicalUnits[unitNo]&FIRST_IN_CHAIN)==FIRST_IN_CHAIN)
  1810. return flGeneralFailure;
  1811. /***********************************/
  1812. /* Copy all sectors to target unit */
  1813. /***********************************/
  1814. for (i = 0; i < vol.sectorsPerUnit;
  1815. #ifdef ENVIRONMENT_VARS
  1816. firstUnitAddress += SECTOR_SIZE,
  1817. #endif /* ENVIRONMENT_VARS */
  1818. #if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
  1819. vol.curSectorWrite++, /* Update virtual sector Number */
  1820. #endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
  1821. i++, virtualSectorNo++,targetSectorAddress += SECTOR_SIZE)
  1822. {
  1823. lastOK = TRUE; /* Set last sector of chain as valid */
  1824. sourceSectorAddress = virtual2Physical(&vol,virtualSectorNo,ANAND_UNASSIGNED_ADDRESS,&lastOK);
  1825. /* Check if sector is on the target unit. If so on some configuration we */
  1826. /* Verify the content and on some , we just assume the data is fine. */
  1827. if(sourceSectorAddress == targetSectorAddress)
  1828. {
  1829. #if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
  1830. switch(verifyWriteState)
  1831. {
  1832. case FL_ON: /* Always verify */
  1833. break;
  1834. case FL_OFF: /* Verify only if area was not scanned yet */
  1835. if(virtualSectorNo >= vol.verifiedSectorNo)
  1836. break;
  1837. default: /* FL_UPS - Never verify */
  1838. newSectorCount++;
  1839. continue;
  1840. }
  1841. #else
  1842. newSectorCount++;
  1843. continue;
  1844. #endif /* VERIFY WRITE */
  1845. }
  1846. /* Read sector - Loop down the chain as long as there is an EDC error */
  1847. /* or infinit loop chain (chain bound) */
  1848. for (chainBound=0 ; (sourceSectorAddress != ANAND_UNASSIGNED_ADDRESS) ; chainBound++)
  1849. {
  1850. if(sourceSectorAddress == ANAND_BAD_CHAIN_ADDRESS) /* Could not follow chain */
  1851. return flGeneralFailure;
  1852. status = vol.flash->read(vol.flash,sourceSectorAddress,
  1853. inftlBuffer,SECTOR_SIZE,EDC);
  1854. if (status != flOK)
  1855. {
  1856. if (status == flDataError)
  1857. {
  1858. DEBUG_PRINT(("foldUnit : EDC error on folding\r\n"));
  1859. if (chainBound >= MAX_UNIT_CHAIN)
  1860. return status;
  1861. sourceSectorAddress = virtual2Physical(&vol,virtualSectorNo,sourceSectorAddress,&lastOK);
  1862. continue;
  1863. }
  1864. else
  1865. {
  1866. return status;
  1867. }
  1868. }
  1869. break;
  1870. } /* chain bound EDC error loop */
  1871. if (sourceSectorAddress == ANAND_UNASSIGNED_ADDRESS) /* Sector not found */
  1872. continue;
  1873. newSectorCount++;
  1874. if (sourceSectorAddress == targetSectorAddress) /* Sector already exists */
  1875. continue;
  1876. /* Try and copy the relevant sector */
  1877. #ifdef ENVIRONMENT_VARS
  1878. /* On FL_COMPLETE_ASAP copy sector only if it is on the first unit */
  1879. if((flPolicy[vol.socketNo][vol.flash->socket->curPartition]==FL_COMPLETE_ASAP) &&
  1880. (sourceSectorAddress!=firstUnitAddress))
  1881. continue;
  1882. #endif /* ENVIRONMENT_VARS */
  1883. if ((lastOK == FALSE) && (foldingFlag == FL_NORMAL_FOLDING))
  1884. {
  1885. /* Last sector of the chain is already used */
  1886. return flCanNotFold;
  1887. }
  1888. status = writeAndCheck(&vol,targetSectorAddress,inftlBuffer,EDC,1);
  1889. vol.parasiteWrites++;
  1890. /* On EDC error assume previous sector is empty */
  1891. switch (status)
  1892. {
  1893. case flOK: /* Success */
  1894. break;
  1895. case flWriteFault: /* Faild in verify write */
  1896. if (foldingFlag == FL_NORMAL_FOLDING)
  1897. {
  1898. DEBUG_PRINT(("foldUnit : Failed to write a sector while folding but will not force folding\r\n"));
  1899. return flCanNotFold;
  1900. }
  1901. break;
  1902. default : /* Protection error or any other */
  1903. return status;
  1904. }
  1905. } /* Sector copy loop */
  1906. /***************************************************************/
  1907. /* After all sectors have been copied , erase the unused units */
  1908. /***************************************************************/
  1909. if(foldingFlag == FL_NOT_IN_PLACE) /* Add erase mark to validate unit */
  1910. {
  1911. word eraseMark;
  1912. dword eraseCount;
  1913. checkStatus(getUnitTailer(&vol,unitNo,&eraseMark,&eraseCount,UNIT_TAILER_OFFSET_2));
  1914. checkStatus(setUnitTailer(&vol,unitNo,eraseMark,eraseCount,UNIT_TAILER_OFFSET));
  1915. }
  1916. if (newSectorCount > 0) /* Some sectors remaining*/
  1917. {
  1918. /* Set target unit in physical unit table as first in chain */
  1919. status = getUnitData(&vol,unitNo,&virtualUnitNo, &prevUnitNo,&ANAC,&NAC,&parityPerField);
  1920. if(status != flOK)
  1921. return status;
  1922. /* check if unit is valid */
  1923. if(badParityResult(parityPerField))
  1924. return flGeneralFailure;
  1925. #ifdef ENVIRONMENT_VARS
  1926. /* Erase only oldest unit */
  1927. if(flPolicy[vol.socketNo][vol.flash->socket->curPartition]==FL_COMPLETE_ASAP)
  1928. {
  1929. vol.physicalUnits[nextUnitNo] |= FIRST_IN_CHAIN;
  1930. return formatUnit(&vol, firstUnit,UNIT_TAILER_OFFSET);
  1931. }
  1932. else
  1933. #endif
  1934. {
  1935. vol.physicalUnits[unitNo] |= FIRST_IN_CHAIN;
  1936. unitNo=prevUnitNo; /* erase all units in chain but the last one */
  1937. }
  1938. }
  1939. else
  1940. {
  1941. /* Erase chain completely */
  1942. vol.virtualUnits[virtualUnitNo] = ANAND_NO_UNIT;
  1943. }
  1944. /* Erase source units */
  1945. return formatChain(&vol,unitNo);
  1946. }
  1947. /*----------------------------------------------------------------------*/
  1948. /* f o l d B e s t C h a i n */
  1949. /* */
  1950. /* Find the best chain to fold and fold it.A good chain to fold is a */
  1951. /* long chain with a small number of sectors that hold valid data. */
  1952. /* */
  1953. /* Parameters: */
  1954. /* vol : Pointer identifying drive */
  1955. /* unitNo : Receives the physical unit no. of the first */
  1956. /* unit in the chain that was folded. */
  1957. /* */
  1958. /* Returns: */
  1959. /* FLStatus : 0 on success, failed otherwise */
  1960. /*----------------------------------------------------------------------*/
  1961. static FLStatus foldBestChain(Bnand vol, ANANDUnitNo *unitNo)
  1962. {
  1963. word leastCount, longestChain, unitCount;
  1964. ANANDUnitNo u, firstUnitNo, newVirtualUnitNo, prevUnitNo;
  1965. ANANDUnitNo virtualUnitNo;
  1966. ANANDUnitNo frozenCandidate = ANAND_NO_UNIT;
  1967. ANANDUnitNo lazyMountCounter = 0;
  1968. ANANDUnitNo newestUnit;
  1969. FLStatus status = flOK;
  1970. byte NAC,ANAC,parityPerField;
  1971. int foldingTries;
  1972. /* Will exit when no more units are available or up to 10 times */
  1973. for (*unitNo = ANAND_NO_UNIT,foldingTries = 0 ;
  1974. foldingTries < MAX_FOLDING_LOOP ; foldingTries++)
  1975. {
  1976. /*********************************************/
  1977. /* Pick unit to fold using huristic function */
  1978. /*********************************************/
  1979. virtualUnitNo = ANAND_NO_UNIT;
  1980. longestChain = 1; /* Minimal chain length to fold == 1 */
  1981. leastCount = vol.sectorsPerUnit+1;
  1982. for (u = 0; u < vol.noOfVirtualUnits; u++)
  1983. {
  1984. firstUnitNo = vol.virtualUnits[u];
  1985. if(firstUnitNo == ANAND_NO_UNIT) /* Free unit */
  1986. continue;
  1987. if( !(isAvailable(firstUnitNo)) )
  1988. {
  1989. /* Do not attempt to fold frozen unit. */
  1990. /* They will become unfrozen by the end of this routine. */
  1991. frozenCandidate = u; /* Remember for forced folding */
  1992. DEBUG_PRINT(("FoldBestChains : Skiped unavailable unit\r\n"));
  1993. continue;
  1994. }
  1995. /* Lazy mount - Make sure unit has a valid sector count */
  1996. if (vol.countsValid <= u)
  1997. {
  1998. if(lazyMountCounter>=MAX_CREATE_UNIT_COUNT)
  1999. {
  2000. /* If lazy mount takes too long , try and shorten it. */
  2001. if(virtualUnitNo!=ANAND_NO_UNIT)
  2002. break;
  2003. }
  2004. createUnitCount(&vol,u);
  2005. lazyMountCounter++;
  2006. vol.countsValid = u + 1;
  2007. }
  2008. unitCount = countOf(firstUnitNo); /* No of valid sectors */
  2009. /* If empty unit, use it. */
  2010. if(unitCount==0)
  2011. {
  2012. leastCount = unitCount; /* Store minimal sector count */
  2013. virtualUnitNo = u; /* Store virtual unit number */
  2014. break;
  2015. }
  2016. if ((leastCount < unitCount) || /* Already found a better unit */
  2017. (vol.physicalUnits[firstUnitNo] & FIRST_IN_CHAIN)) /* 1 unit in chain */
  2018. continue;
  2019. /* Sector count is smaller or equal now check chains length */
  2020. status = getUnitData(&vol,firstUnitNo,&newVirtualUnitNo, &prevUnitNo,&ANAC,&NAC,&parityPerField);
  2021. if(status != flOK)
  2022. return status;
  2023. /* check if unit is valid */
  2024. if((badParityResult(parityPerField)) || (newVirtualUnitNo != u))
  2025. return flGeneralFailure;
  2026. if((leastCount == unitCount) && /* If sector count is equal */
  2027. (longestChain >= NAC) ) /* Use chain length */
  2028. continue;
  2029. /* If we reached here the current unit is the best so far */
  2030. longestChain = NAC; /* Store maximal chain length */
  2031. leastCount = unitCount; /* Store minimal sector count */
  2032. virtualUnitNo = u; /* Store virtual unit number */
  2033. } /* End of unit huristic loop */
  2034. /****************************************/
  2035. /* Try folding the unit that was picked */
  2036. /****************************************/
  2037. if (virtualUnitNo != ANAND_NO_UNIT) /* Found a chain (more then 1 unit) */
  2038. {
  2039. *unitNo = firstInChain(&vol,vol.virtualUnits[virtualUnitNo],NULL);
  2040. if(*unitNo==ANAND_BAD_CHAIN_UNIT)
  2041. return flGeneralFailure;
  2042. status = foldUnit(&vol,virtualUnitNo,FL_NORMAL_FOLDING);
  2043. switch(status)
  2044. {
  2045. case flOK:
  2046. /* Try to make sure that there are at least 2 free units */
  2047. if(pVol->freeUnits < 2)
  2048. {
  2049. DEBUG_PRINT(("foldBestChains : Folding success, but need more units.\r\n"));
  2050. continue;
  2051. }
  2052. break;
  2053. case flCanNotFold:
  2054. DEBUG_PRINT(("foldBestChains : Failed folding, mark as unavailable and try folding another\r\n"));
  2055. setUnavail(vol.virtualUnits[virtualUnitNo]);
  2056. *unitNo = ANAND_NO_UNIT;
  2057. continue;
  2058. default:
  2059. DEBUG_PRINT(("foldBestChains : ERROR - Failed folding, with status diffrent then flCanNotFold.\r\n"));
  2060. return status;
  2061. }
  2062. }
  2063. else /* All remaining chains have single unit */
  2064. {
  2065. if (frozenCandidate == ANAND_NO_UNIT) /* Simply no chain larger then 1 */
  2066. {
  2067. if(*unitNo == ANAND_NO_UNIT) /* Not even 1 unit was folded */
  2068. {
  2069. DEBUG_PRINT(("foldBestChains : Failed - not enough units on flash.\r\n"));
  2070. return flNotEnoughMemory;
  2071. }
  2072. else /* Aleady freed one unit - simply tried to get */
  2073. {
  2074. return flOK;
  2075. }
  2076. }
  2077. }
  2078. break;
  2079. } /* End folding tries loop */
  2080. /**************************************************************/
  2081. /* Unfreeze all frozen units , and fold them using freed unit */
  2082. /**************************************************************/
  2083. if (frozenCandidate != ANAND_NO_UNIT) /* At least one unit was frozen */
  2084. {
  2085. DEBUG_PRINT(("foldBestChains : Found a frozen unit.\r\n"));
  2086. /* find free unit to be appended */
  2087. if(*unitNo==ANAND_NO_UNIT) /* No unit was folded */
  2088. {
  2089. DEBUG_PRINT(("foldBestChains : No free unit was found so far, so search for one.\r\n"));
  2090. if(vol.freeUnits) /* There are free units */
  2091. {
  2092. ANANDUnitNo originalUnit = vol.roverUnit;
  2093. do
  2094. {
  2095. if (++vol.roverUnit >= vol.noOfUnits)
  2096. vol.roverUnit = 0;
  2097. if (vol.physicalUnits[vol.roverUnit] == ANAND_UNIT_FREE)
  2098. { /* found a free unit, if not erased, */
  2099. if (formatUnit(&vol,vol.roverUnit,UNIT_TAILER_OFFSET_2) != flOK)
  2100. continue; /* this unit is bad, find another */
  2101. *unitNo = vol.roverUnit;
  2102. DEBUG_PRINT(("foldBestChains : Found a free unit for folding not in place.\r\n"));
  2103. break;
  2104. }
  2105. }while (vol.roverUnit != originalUnit);
  2106. }
  2107. if(*unitNo==ANAND_NO_UNIT) /* No unit was found */
  2108. {
  2109. /* Force folding of the last frozen unit - Loose data */
  2110. DEBUG_PRINT(("foldBestChains : Will force folding on Frozen candidate\r\n"));
  2111. *unitNo = firstInChain(&vol,vol.virtualUnits[frozenCandidate],NULL);
  2112. if(*unitNo==ANAND_BAD_CHAIN_UNIT)
  2113. return flGeneralFailure;
  2114. createUnitCount(&vol,frozenCandidate);
  2115. status = foldUnit(&vol,frozenCandidate,FL_FORCE_FOLDING);
  2116. if(status!= flOK)
  2117. return status;
  2118. }
  2119. }
  2120. for (u=0 ; u < vol.noOfVirtualUnits ; u++) /* Loop over units and unfreeze */
  2121. {
  2122. if(vol.virtualUnits[u] == ANAND_NO_UNIT)
  2123. continue;
  2124. if(isAvailable(vol.virtualUnits[u]))
  2125. continue;
  2126. createUnitCount(&vol,u);
  2127. DEBUG_PRINT(("foldBestChains : Now free all frozen units.\r\n"));
  2128. /* If unit is unavailable append newly found unit to chain and fold */
  2129. checkStatus(getUnitData(&vol,vol.virtualUnits[u],&newVirtualUnitNo, &prevUnitNo,&ANAC,&NAC,&parityPerField));
  2130. /* check if unit is valid */
  2131. if((badParityResult(parityPerField)) || (newVirtualUnitNo != u))
  2132. return flGeneralFailure;
  2133. /* Remember the appended unit */
  2134. newestUnit = *unitNo;
  2135. /* Remember oldest unit to return as new allocated unit */
  2136. *unitNo = firstInChain(&vol,vol.virtualUnits[u],NULL);
  2137. /* Erase the erase mark and move erase count to offset 6K */
  2138. checkStatus(formatUnit(&vol,newestUnit,UNIT_TAILER_OFFSET_2));
  2139. checkStatus(assignUnit(&vol,newestUnit,u,ANAC,NAC));
  2140. status = foldUnit(&vol,u,FL_NOT_IN_PLACE);
  2141. if(status != flOK)
  2142. return status;
  2143. }
  2144. }
  2145. return flOK;
  2146. }
  2147. /*----------------------------------------------------------------------*/
  2148. /* a l l o c a t e U n i t */
  2149. /* */
  2150. /* Find a free unit to allocate, erase it if necessary. */
  2151. /* */
  2152. /* Parameters: */
  2153. /* vol : Pointer identifying drive */
  2154. /* unitNo : Receives the physical number of the allocated */
  2155. /* unit */
  2156. /* Returns: */
  2157. /* FLStatus : 0 on success, failed otherwise */
  2158. /*----------------------------------------------------------------------*/
  2159. static FLStatus allocateUnit(Bnand vol, ANANDUnitNo *unitNo)
  2160. {
  2161. ANANDUnitNo originalUnit = vol.roverUnit;
  2162. FLStatus status;
  2163. dword eraseCount;
  2164. word eraseMark;
  2165. if (vol.freeUnits < 2)
  2166. {
  2167. status = foldBestChain(&vol,unitNo); /* make free units by folding the best chain */
  2168. if(status != flNotEnoughMemory)
  2169. return status;
  2170. DEBUG_PRINT(("Debug: Using last free unit of the media.\r\n"));
  2171. }
  2172. do
  2173. {
  2174. if (++vol.roverUnit >= vol.noOfUnits)
  2175. vol.roverUnit = 0;
  2176. if (vol.physicalUnits[vol.roverUnit] == ANAND_UNIT_FREE)
  2177. { /* found a free unit, if not erased, */
  2178. status = getUnitTailer(&vol,vol.roverUnit,&eraseMark,&eraseCount,UNIT_TAILER_OFFSET);
  2179. if(status != flOK)
  2180. return status;
  2181. if (eraseMark != ERASE_MARK)
  2182. {
  2183. if (formatUnit(&vol,vol.roverUnit,UNIT_TAILER_OFFSET) != flOK)
  2184. continue; /* this unit is bad, find another */
  2185. }
  2186. *unitNo = vol.roverUnit;
  2187. return flOK;
  2188. }
  2189. } while (vol.roverUnit != originalUnit);
  2190. return foldBestChain(&vol,unitNo); /* make free units by folding the best chain */
  2191. }
  2192. /*----------------------------------------------------------------------*/
  2193. /* c h e c k F o l d i n g */
  2194. /* */
  2195. /* Check and complete a failed folding operation. */
  2196. /* */
  2197. /* Parameters: */
  2198. /* foldStatus : Pointer identifying drive */
  2199. /* virtualUnitNo : Virtual unit number of the first unit in */
  2200. /* */
  2201. /* Returns: */
  2202. /* FLStatus : 0 on success, failed otherwise */
  2203. /*----------------------------------------------------------------------*/
  2204. static FLStatus checkFolding(Bnand vol,FLStatus foldStatus,ANANDUnitNo virtualUnitNo)
  2205. {
  2206. ANANDUnitNo newVirtualUnitNo, prevUnitNo , dummyUnitNo;
  2207. byte ANAC,NAC,parityPerField;
  2208. if(foldStatus == flCanNotFold)
  2209. {
  2210. DEBUG_PRINT(("checkFolding : Perform folding not in place\r\n"));
  2211. /* Get a new unit for extending the virtual unit */
  2212. checkStatus(allocateUnit(&vol,&dummyUnitNo));
  2213. checkStatus(getUnitData(&vol,vol.virtualUnits[virtualUnitNo],&newVirtualUnitNo,
  2214. &prevUnitNo,&ANAC,&NAC,&parityPerField));
  2215. if((newVirtualUnitNo!=virtualUnitNo)||
  2216. (badParityResult(parityPerField)))
  2217. {
  2218. return flGeneralFailure;
  2219. }
  2220. #ifdef ENVIRONMENT_VARS
  2221. /* Prepare NAC */
  2222. if(NAC>=MAX_UNIT_CHAIN)
  2223. NAC=MAX_UNIT_CHAIN-1;
  2224. #endif /* ENVIRONMENT_VARS */
  2225. checkStatus(assignUnit(&vol,dummyUnitNo,virtualUnitNo,ANAC,NAC));
  2226. foldStatus = foldUnit(&vol,virtualUnitNo,FL_FORCE_FOLDING);
  2227. }
  2228. return foldStatus;
  2229. }
  2230. /*----------------------------------------------------------------------*/
  2231. /* a p p l y W e a r l e v e l i n g */
  2232. /* */
  2233. /* Try to extend the current vurtial chain in order to force static */
  2234. /* files wear leveling. */
  2235. /* */
  2236. /* Parameters: */
  2237. /* vol : Pointer identifying drive */
  2238. /* */
  2239. /* Returns: */
  2240. /* FLStatus : 0 on success, failed otherwise */
  2241. /*----------------------------------------------------------------------*/
  2242. static FLStatus applyWearleveling(Bnand vol)
  2243. {
  2244. ANANDUnitNo replacementUnitNo,newVirtualUnitNo;
  2245. ANANDUnitNo startUnit,curUnit;
  2246. FLStatus status;
  2247. byte NAC,ANAC,parityPerField;
  2248. /* Increament wear leveling counter */
  2249. vol.wearLevel.currUnit++;
  2250. if(vol.wearLevel.currUnit>=vol.noOfVirtualUnits)
  2251. vol.wearLevel.currUnit=0;
  2252. /****************************************************/
  2253. /* Searching for a candidate virtual unit to extend */
  2254. /****************************************************/
  2255. startUnit = vol.wearLevel.currUnit;
  2256. for(curUnit = startUnit ;
  2257. vol.virtualUnits[curUnit] == ANAND_NO_UNIT;curUnit++)
  2258. {
  2259. if(curUnit>=vol.noOfVirtualUnits)
  2260. curUnit = 0;
  2261. if(startUnit == curUnit)
  2262. break;
  2263. }
  2264. if(startUnit == curUnit) /* the media is empty*/
  2265. {
  2266. return flOK;
  2267. }
  2268. vol.wearLevel.currUnit = curUnit; /* Store last leveld unit */
  2269. /***************************************************************************/
  2270. /* Now fold the virtual chain. (if a single unit chain add before folding) */
  2271. /***************************************************************************/
  2272. if(vol.physicalUnits[vol.virtualUnits[curUnit]] & FIRST_IN_CHAIN) /* chain is 1 unit long */
  2273. {
  2274. /* This is a one unit chain, so we have to add a unit before folding */
  2275. status = allocateUnit(&vol,&replacementUnitNo); /* Find unit to append */
  2276. if(status != flOK)
  2277. return status;
  2278. if(vol.virtualUnits[curUnit] == ANAND_NO_UNIT)
  2279. {
  2280. /* We did folding for the very same unit and now virtual unit is FREE */
  2281. vol.freeUnits--;
  2282. return flOK;
  2283. }
  2284. /* Get previous unit information (ANAC and NAC) */
  2285. status = getUnitData(&vol,vol.virtualUnits[curUnit],&newVirtualUnitNo, &replacementUnitNo,
  2286. &ANAC,&NAC,&parityPerField);
  2287. if(status != flOK)
  2288. return status;
  2289. if(badParityResult(parityPerField)) /* check if unit is valid */
  2290. return flGeneralFailure;
  2291. if(newVirtualUnitNo != curUnit) /* Problem with RAM tables */
  2292. {
  2293. return flGeneralFailure;
  2294. }
  2295. status = assignUnit(&vol,replacementUnitNo,curUnit,ANAC,NAC);
  2296. if(status != flOK)
  2297. return status;
  2298. }
  2299. /* Perform folding and verify operation */
  2300. status = foldUnit(&vol,curUnit,FL_NORMAL_FOLDING);
  2301. if (status != flOK)
  2302. return checkFolding(&vol,status,curUnit);
  2303. return flOK;
  2304. }
  2305. #endif /* FL_READ_ONLY */
  2306. /*----------------------------------------------------------------------*/
  2307. /* m a p S e c t o r */
  2308. /* */
  2309. /* Maps and returns location of a given sector no. */
  2310. /* NOTE: This function is used in place of a read-sector operation. */
  2311. /* */
  2312. /* A one-sector cache is maintained to save on map operations. */
  2313. /* */
  2314. /* Parameters: */
  2315. /* vol : Pointer identifying drive */
  2316. /* sectorNo : Sector no. to read */
  2317. /* physAddress : Optional pointer to receive sector address */
  2318. /* */
  2319. /* Returns: */
  2320. /* Pointer to physical sector location. NULL returned if sector */
  2321. /* does not exist. */
  2322. /*----------------------------------------------------------------------*/
  2323. static const void FAR0 *mapSector(Bnand vol, SectorNo sectorNo, CardAddress *physAddress)
  2324. {
  2325. FLStatus status;
  2326. FLBoolean lastOK; /* Dummy variable */
  2327. byte chainBound;
  2328. if ((sectorNo != vol.mappedSectorNo) ||
  2329. (vol.flash->socket->remapped) ||
  2330. (vol.buffer->owner == &vol) )
  2331. {
  2332. vol.flash->socket->remapped = TRUE;
  2333. vol.mappedSector = NULL;
  2334. vol.mappedSectorAddress = ANAND_UNASSIGNED_ADDRESS;
  2335. if (sectorNo < vol.virtualSectors) /* While EDC error on sector read */
  2336. {
  2337. for (chainBound=0 ; (chainBound < DOUBLE_MAX_UNIT_CHAIN) ; chainBound++)
  2338. {
  2339. vol.mappedSectorAddress = virtual2Physical(&vol,sectorNo,vol.mappedSectorAddress,&lastOK);
  2340. switch(vol.mappedSectorAddress)
  2341. {
  2342. case ANAND_UNASSIGNED_ADDRESS:
  2343. case ANAND_BAD_CHAIN_ADDRESS:
  2344. vol.mappedSector = NULL; /* no such sector */
  2345. break;
  2346. default:
  2347. vol.mappedSector = inftlBuffer;
  2348. status = vol.flash->read(vol.flash,vol.mappedSectorAddress,inftlBuffer,SECTOR_SIZE,EDC);
  2349. if (status == flOK)
  2350. break;
  2351. if (status != flDataError)
  2352. return dataErrorToken;
  2353. continue;
  2354. }
  2355. break;
  2356. }
  2357. if (chainBound >= DOUBLE_MAX_UNIT_CHAIN)
  2358. return dataErrorToken;
  2359. /* Store sector for next mapping operation */
  2360. vol.mappedSectorNo = sectorNo; /* Sector number */
  2361. vol.buffer->owner = &vol; /* Partition */
  2362. vol.flash->socket->remapped = FALSE; /* Valid */
  2363. }
  2364. }
  2365. if (physAddress)
  2366. *physAddress = vol.mappedSectorAddress;
  2367. return vol.mappedSector;
  2368. }
  2369. /*----------------------------------------------------------------------*/
  2370. /* r e a d 2 S e c t o r s */
  2371. /* */
  2372. /* read content of a set of consecutive sectors. */
  2373. /* */
  2374. /* Parameters: */
  2375. /* vol : Pointer identifying drive */
  2376. /* sectorNo : Sector no. to read */
  2377. /* dest : pointer to buffer to read */
  2378. /* sectorCount : # of sectors to read ( up to 2 ) */
  2379. /* */
  2380. /* Returns: */
  2381. /* status of the read operaton */
  2382. /*----------------------------------------------------------------------*/
  2383. static FLStatus read2Sectors(Bnand vol, SectorNo sectorNo, byte FAR1 *dest,
  2384. SectorNo sectorCount)
  2385. {
  2386. CardAddress mappedSectorAddress[2];
  2387. FLStatus status = flOK;
  2388. FLStatus retStatus = flOK;
  2389. word i;
  2390. byte chainBound;
  2391. FLBoolean lastOK; /* Dummy variable */
  2392. if ((sectorNo+sectorCount-1) >= vol.virtualSectors)
  2393. {
  2394. return flSectorNotFound; /* Out of bounds */
  2395. }
  2396. else
  2397. {
  2398. /* find physical location of the 2 sectors */
  2399. for(i=0;i<sectorCount;i++)
  2400. {
  2401. mappedSectorAddress[i] = virtual2Physical(&vol,sectorNo+i,
  2402. ANAND_UNASSIGNED_ADDRESS,&lastOK);
  2403. /* If chain is brocken report sector not found */
  2404. if(mappedSectorAddress[i] == ANAND_BAD_CHAIN_ADDRESS)
  2405. mappedSectorAddress[i] = ANAND_UNASSIGNED_ADDRESS;
  2406. }
  2407. /* When possible read the 2 sectors together */
  2408. if((sectorCount==2)&&
  2409. ( mappedSectorAddress[1] > mappedSectorAddress[0] ) &&
  2410. ((mappedSectorAddress[1] - mappedSectorAddress[0])==SECTOR_SIZE) &&
  2411. ( mappedSectorAddress[0] != ANAND_UNASSIGNED_ADDRESS ) &&
  2412. ( mappedSectorAddress[1] != ANAND_UNASSIGNED_ADDRESS ))
  2413. {
  2414. if (vol.flash->read(vol.flash,mappedSectorAddress[0],
  2415. dest,SECTOR_SIZE<<1,EDC) == flOK)
  2416. {
  2417. vol.sectorsRead+=2;
  2418. return flOK;
  2419. }
  2420. }
  2421. /* Sectors are not together */
  2422. for (i=0;i<sectorCount;i++,dest = (byte FAR1 *)flAddLongToFarPointer(dest,SECTOR_SIZE))
  2423. {
  2424. /* While EDC error on sector read - keep reading from older unit */
  2425. for (chainBound=0 ; (chainBound < DOUBLE_MAX_UNIT_CHAIN) ; chainBound++)
  2426. {
  2427. if (mappedSectorAddress[i] == ANAND_UNASSIGNED_ADDRESS)
  2428. {
  2429. tffsset(dest,0,SECTOR_SIZE);
  2430. retStatus = flSectorNotFound;
  2431. break;
  2432. }
  2433. else
  2434. {
  2435. status=vol.flash->read(vol.flash,mappedSectorAddress[i],
  2436. dest,SECTOR_SIZE,EDC);
  2437. vol.sectorsRead++;
  2438. if (status == flOK)
  2439. {
  2440. break;
  2441. }
  2442. else if (status == flDataError)
  2443. {
  2444. mappedSectorAddress[i] = virtual2Physical(&vol,sectorNo+i,mappedSectorAddress[i],&lastOK);
  2445. /* If chain is brocken report sector not found */
  2446. if(mappedSectorAddress[i]==ANAND_BAD_CHAIN_ADDRESS)
  2447. mappedSectorAddress[i] = ANAND_UNASSIGNED_ADDRESS;
  2448. }
  2449. else
  2450. {
  2451. return status;
  2452. }
  2453. }
  2454. }
  2455. if (chainBound >= DOUBLE_MAX_UNIT_CHAIN)
  2456. return status;
  2457. }
  2458. }
  2459. return retStatus;
  2460. }
  2461. /*----------------------------------------------------------------------*/
  2462. /* r e a d S e c t o r s */
  2463. /* */
  2464. /* Read content of a set of consecutive sectors. */
  2465. /* */
  2466. /* Parameters: */
  2467. /* vol : Pointer identifying drive */
  2468. /* sectorNo : Sector no. to read */
  2469. /* dest : pointer to buffer to read */
  2470. /* sectorCount : # of sectors to read */
  2471. /* */
  2472. /* Returns: */
  2473. /* status of the read operaton */
  2474. /* */
  2475. /*----------------------------------------------------------------------*/
  2476. static FLStatus readSectors(Bnand vol, SectorNo sectorNo, void FAR1 *dest,
  2477. SectorNo sectorCount)
  2478. {
  2479. byte FAR1* curDest;
  2480. SectorNo lastSector = 0;
  2481. FLStatus retStatus = flOK;
  2482. FLStatus status;
  2483. SectorNo i;
  2484. #ifdef SCATTER_GATHER
  2485. curDest = *(byte FAR1 **)dest;
  2486. #else
  2487. curDest = (byte FAR1 *)dest;
  2488. #endif /* SCATTER_GATHER */
  2489. if ((sectorNo+sectorCount) > vol.virtualSectors)
  2490. {
  2491. return flSectorNotFound; /* Out of bounds */
  2492. }
  2493. /****************************************************************/
  2494. /* Read first sector if it's only one or it has odd address */
  2495. /****************************************************************/
  2496. if(((sectorNo & 1)!=0)||(sectorCount==1))
  2497. {
  2498. status=read2Sectors(&vol, sectorNo, curDest,1);
  2499. if (status != flOK)
  2500. {
  2501. if (status == flSectorNotFound)
  2502. {
  2503. retStatus = flSectorNotFound;
  2504. }
  2505. else
  2506. {
  2507. return status;
  2508. }
  2509. }
  2510. if(sectorCount==1)
  2511. return status;
  2512. sectorNo++;
  2513. sectorCount--;
  2514. #ifdef SCATTER_GATHER
  2515. dest = (byte FAR1 **)dest+1;
  2516. #else
  2517. dest = flAddLongToFarPointer(dest,SECTOR_SIZE);
  2518. #endif /* SCATTER_GATHER */
  2519. }
  2520. if(((sectorNo+sectorCount-1) & 1)==0) /* keep last sector if it has odd address*/
  2521. lastSector=sectorNo+sectorCount-1;
  2522. /*****************************************/
  2523. /* Read pairs of consequtive sectors */
  2524. /*****************************************/
  2525. #ifdef SCATTER_GATHER
  2526. curDest = multiSectorBuf[vol.socketNo];
  2527. #else
  2528. curDest = (byte FAR1 *)dest;
  2529. #endif /* SCATTER_GATHER */
  2530. for(i=0;i<((sectorCount>>1)<<1);i+=2) /* read pair of sectors*/
  2531. {
  2532. status=read2Sectors(&vol,sectorNo+i, curDest,2);
  2533. if (status != flOK)
  2534. {
  2535. if (status == flSectorNotFound)
  2536. {
  2537. retStatus = flSectorNotFound;
  2538. }
  2539. else
  2540. {
  2541. return status;
  2542. }
  2543. }
  2544. #ifdef SCATTER_GATHER
  2545. /* copy from temporary buffer to user scattered buffers */
  2546. tffscpy(*(byte FAR1 **)dest,curDest,SECTOR_SIZE);
  2547. tffscpy(*((byte FAR1 **)dest+1),&(curDest[SECTOR_SIZE]),SECTOR_SIZE);
  2548. dest = (byte FAR1 **)dest+2;
  2549. #else
  2550. curDest=(byte FAR1 *)flAddLongToFarPointer(curDest,(SECTOR_SIZE<<1));
  2551. #endif /* SCATTER_GATHER */
  2552. }
  2553. /********************************/
  2554. /* Read last uneven sectors */
  2555. /********************************/
  2556. #ifdef SCATTER_GATHER
  2557. curDest = *(byte FAR1 **)dest;
  2558. #endif /* SCATTER_GATHER */
  2559. if(lastSector!=0) /* read last sector */
  2560. {
  2561. checkStatus(read2Sectors(&vol,lastSector, curDest,1));
  2562. }
  2563. return retStatus;
  2564. }
  2565. #ifndef FL_READ_ONLY
  2566. /*----------------------------------------------------------------------*/
  2567. /* a l l o c a t e A n d W r i t e S e c t o r s */
  2568. /* */
  2569. /* Write to sectorNo. if necessary, allocate a free sector first. */
  2570. /* */
  2571. /* Parameters: */
  2572. /* vol : Pointer identifying drive */
  2573. /* sectorNo : Virtual sector no. to write */
  2574. /* fromAddress : Address of sector data. */
  2575. /* howMany : Number of sectors to write. */
  2576. /* */
  2577. /* Returns: */
  2578. /* FLStatus : 0 on success, failed otherwise */
  2579. /*----------------------------------------------------------------------*/
  2580. static FLStatus allocateAndWriteSectors(Bnand vol,
  2581. SectorNo sectorNo,
  2582. void FAR1 *fromAddress,word howMany)
  2583. {
  2584. ANANDUnitNo newVirtualUnitNo, newPrevUnitNo;
  2585. ANANDUnitNo virtualUnitNo = (ANANDUnitNo)(sectorNo >> vol.sectorsPerUnitBits);
  2586. ANANDUnitNo lastUnitNo = vol.virtualUnits[virtualUnitNo];
  2587. ANANDUnitNo unitNo,prevUnitNo;
  2588. FLStatus status;
  2589. byte ANAC,NAC,parityPerField;
  2590. word unitOffset = (word)((sectorNo & vol.sectorsPerUnitMask) << SECTOR_SIZE_BITS);
  2591. word chainBound = 0;
  2592. word foundSoFar = 0;
  2593. word newSect = howMany;
  2594. byte sectorFlags;
  2595. FLBoolean firstUnitFound = FALSE;
  2596. FLBoolean secondUnitFound = FALSE;
  2597. FLBoolean noneFreeFound = FALSE;
  2598. ANANDUnitNo commonPrevUnitNo = ANAND_NO_UNIT;
  2599. ANANDUnitNo commonUnitNo = lastUnitNo;
  2600. /************************************/
  2601. /* Find a unit to write this sector */
  2602. /************************************/
  2603. unitNo = lastUnitNo; /* newest unit that either sectors is not FREE */
  2604. prevUnitNo = ANAND_NO_UNIT; /* oldest unit with place for required sectors */
  2605. while (unitNo != ANAND_NO_UNIT)
  2606. {
  2607. if(firstUnitFound == FALSE)
  2608. {
  2609. sectorFlags = getSectorFlags(&vol,unitBaseAddress(vol,unitNo) + unitOffset);
  2610. switch(sectorFlags)
  2611. {
  2612. case SECTOR_USED:
  2613. newSect--; /* Sector exists - do not increament counter */
  2614. case SECTOR_DELETED:
  2615. foundSoFar++;
  2616. firstUnitFound = TRUE;
  2617. case SECTOR_IGNORE:
  2618. if(noneFreeFound == FALSE) /* Store none free space */
  2619. {
  2620. commonPrevUnitNo = prevUnitNo;
  2621. commonUnitNo = unitNo;
  2622. noneFreeFound = TRUE;
  2623. }
  2624. default:
  2625. break;
  2626. }
  2627. }
  2628. if(howMany==2)
  2629. {
  2630. if(secondUnitFound == FALSE)
  2631. {
  2632. sectorFlags = getSectorFlags(&vol,unitBaseAddress(vol,unitNo) + unitOffset+512);
  2633. switch(sectorFlags)
  2634. {
  2635. case SECTOR_USED:
  2636. newSect--; /* Sector exists - do not increament counter */
  2637. case SECTOR_DELETED:
  2638. foundSoFar++;
  2639. secondUnitFound = TRUE;
  2640. case SECTOR_IGNORE:
  2641. if(noneFreeFound == FALSE) /* Store none free space */
  2642. {
  2643. commonPrevUnitNo = prevUnitNo;
  2644. commonUnitNo = unitNo;
  2645. noneFreeFound = TRUE;
  2646. }
  2647. default:
  2648. break;
  2649. }
  2650. }
  2651. }
  2652. if(foundSoFar == howMany) /* Both sectors have been found */
  2653. break;
  2654. /* Both sectors are FREE */
  2655. prevUnitNo = unitNo;
  2656. unitNo = getPrevUnit(&vol,unitNo,virtualUnitNo);
  2657. if(unitNo == ANAND_BAD_CHAIN_UNIT)
  2658. return flGeneralFailure;
  2659. chainBound++;
  2660. if(chainBound >= DOUBLE_MAX_UNIT_CHAIN)
  2661. return flGeneralFailure;
  2662. } /* End of - go over chain while */
  2663. if(noneFreeFound == TRUE)
  2664. {
  2665. prevUnitNo = commonPrevUnitNo; /* Common free unit for both sectors */
  2666. unitNo = commonUnitNo; /* First unit with wither used sector */
  2667. }
  2668. if ((prevUnitNo == ANAND_NO_UNIT)) /* No place to write sectors */
  2669. {
  2670. if(unitNo!=ANAND_NO_UNIT) /* Unit already exists */
  2671. {
  2672. status = getUnitData(&vol,unitNo,&newVirtualUnitNo, &newPrevUnitNo,&ANAC,&NAC,&parityPerField);
  2673. if (status != flOK)
  2674. return status;
  2675. if(badParityResult(parityPerField)) /* check if unit is valid */
  2676. return flGeneralFailure;
  2677. /* Check if chain length is graeter then allowed, but remember */
  2678. /* that the first unit of the chain has invalid NAC. */
  2679. if ((NAC>=MAX_UNIT_CHAIN) &&
  2680. ((vol.physicalUnits[unitNo]&FIRST_IN_CHAIN)!=FIRST_IN_CHAIN))
  2681. {
  2682. status = foldUnit(&vol,virtualUnitNo,FL_NORMAL_FOLDING);
  2683. if (status != flOK)
  2684. {
  2685. status = checkFolding(&vol,status,virtualUnitNo);
  2686. if (status != flOK)
  2687. return status;
  2688. }
  2689. }
  2690. }
  2691. status = allocateUnit(&vol,&prevUnitNo);
  2692. if (status != flOK)
  2693. return status;
  2694. unitNo = vol.virtualUnits[virtualUnitNo];
  2695. if(unitNo==ANAND_NO_UNIT) /* Free virtual unit */
  2696. {
  2697. /* New Virtual unit. reinitialize NAC,ANAC and sector count */
  2698. ANAC=NAC=0;
  2699. /* Force FIRST_IN_CHAIN and sector count to 0. it must be done */
  2700. /* after assignUnit, so that assign unit will not change it. */
  2701. unitNo=ANAND_NO_UNIT;
  2702. }
  2703. else /* Read unit data to set ANAC , NAC and sector count */
  2704. {
  2705. status = getUnitData(&vol,unitNo,&newVirtualUnitNo, &newPrevUnitNo,
  2706. &ANAC,&NAC,&parityPerField);
  2707. if (status != flOK)
  2708. return status;
  2709. /* Check if unit is valid */
  2710. if((badParityResult(parityPerField)) || /* Bad unit data */
  2711. (newVirtualUnitNo!=virtualUnitNo)) /* Bad virtual unit no */
  2712. return flGeneralFailure;
  2713. if(vol.physicalUnits[unitNo]&FIRST_IN_CHAIN)
  2714. NAC=1;
  2715. }
  2716. status = assignUnit(&vol,prevUnitNo,virtualUnitNo,ANAC,NAC);
  2717. if (status != flOK)
  2718. return status;
  2719. if(unitNo==ANAND_NO_UNIT) /* First physical unit of chain */
  2720. {
  2721. vol.physicalUnits[prevUnitNo]=FIRST_IN_CHAIN;
  2722. }
  2723. lastUnitNo = vol.virtualUnits[virtualUnitNo];
  2724. unitNo=prevUnitNo;
  2725. }
  2726. else
  2727. {
  2728. unitNo=prevUnitNo;
  2729. }
  2730. /***********************************************/
  2731. /* Area has been allocated , now write sectors */
  2732. /***********************************************/
  2733. #if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
  2734. vol.curSectorWrite = sectorNo; /* Store virtual sector Number */
  2735. #endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
  2736. status = writeAndCheck(&vol,unitBaseAddress(vol,unitNo) + unitOffset,fromAddress,EDC,howMany);
  2737. if (status != flOK)
  2738. return status;
  2739. /* Take care of sector count */
  2740. if (vol.countsValid > virtualUnitNo)
  2741. {
  2742. lastUnitNo=vol.virtualUnits[virtualUnitNo];
  2743. if (countOf(lastUnitNo) + newSect <= UNIT_MAX_COUNT)
  2744. {
  2745. vol.physicalUnits[lastUnitNo]+=newSect; /* Increment block count */
  2746. }
  2747. else /* Should never happen , but sector count is not correct */
  2748. {
  2749. return flGeneralFailure;
  2750. }
  2751. }
  2752. return flOK;
  2753. }
  2754. /*----------------------------------------------------------------------*/
  2755. /* w r i t e 2 S e c t o r s */
  2756. /* */
  2757. /* Writes up to 2 consecutive sector. */
  2758. /* */
  2759. /* Parameters: */
  2760. /* vol : Pointer identifying drive */
  2761. /* sectorNo : Virtual sector no. to write */
  2762. /* fromAddress : Data to write */
  2763. /* sectorCount : No of sectors to write */
  2764. /* */
  2765. /* Returns: */
  2766. /* FLStatus : 0 on success, failed otherwise */
  2767. /*----------------------------------------------------------------------*/
  2768. static FLStatus write2Sectors(Bnand vol, SectorNo sectorNo,
  2769. void FAR1 *fromAddress,word sectorCount)
  2770. {
  2771. FLStatus status;
  2772. byte i;
  2773. if ((sectorNo+sectorCount-1) >= vol.virtualSectors)
  2774. return flSectorNotFound;
  2775. /* Check if cached sector is still valid */
  2776. if ((sectorNo == vol.mappedSectorNo ) &&
  2777. (sectorNo+sectorCount == vol.mappedSectorNo + sectorCount - 1) )
  2778. vol.flash->socket->remapped = TRUE;
  2779. #ifdef ENVIRONMENT_VARS
  2780. if(flPolicy[vol.socketNo][vol.flash->socket->curPartition]==FL_DEFAULT_POLICY)
  2781. #endif /* ENVIRONMENT_VARS */
  2782. if((vol.wearLevel.currUnit!=ANAND_NO_UNIT))
  2783. {
  2784. vol.wearLevel.alarm++;
  2785. if(vol.wearLevel.alarm>=WLnow)
  2786. {
  2787. vol.wearLevel.alarm = 0;
  2788. status = applyWearleveling(&vol);
  2789. if (status != flOK)
  2790. return status;
  2791. }
  2792. }
  2793. status = flWriteFault;
  2794. vol.sectorsWritten += sectorCount;
  2795. /* Try writing the sector up to 4 times before reporting an error */
  2796. for (i = 0; (i < 4) && (status == flWriteFault); i++)
  2797. status = allocateAndWriteSectors(&vol,sectorNo,fromAddress,sectorCount);
  2798. return status;
  2799. }
  2800. /*----------------------------------------------------------------------*/
  2801. /* w r i t e S e c t o r */
  2802. /* */
  2803. /* Writes a sector. */
  2804. /* */
  2805. /* Parameters: */
  2806. /* vol : Pointer identifying drive */
  2807. /* sectorNo : Virtual sector no. to write */
  2808. /* fromAddress : Data to write */
  2809. /* */
  2810. /* Returns: */
  2811. /* FLStatus : 0 on success, failed otherwise */
  2812. /*----------------------------------------------------------------------*/
  2813. static FLStatus writeSector(Bnand vol, SectorNo sectorNo,
  2814. void FAR1 *fromAddress)
  2815. {
  2816. checkStatus(discardQuickMountInfo(&vol));
  2817. return write2Sectors( &vol, sectorNo, fromAddress, ((SectorNo)1) );
  2818. }
  2819. #ifdef ENVIRONMENT_VARS
  2820. /*----------------------------------------------------------------------*/
  2821. /* w r i t e F u l l U n i t */
  2822. /* */
  2823. /* Write set of consecutive sectors that occupies a full unit. */
  2824. /* */
  2825. /* Parameters: */
  2826. /* vol : Pointer identifying drive */
  2827. /* sectorNo : Sector no. to write */
  2828. /* fromAddress : Pointer to buffer to write */
  2829. /* */
  2830. /* Returns: */
  2831. /* status of the write operaton */
  2832. /* */
  2833. /*----------------------------------------------------------------------*/
  2834. static FLStatus writeFullUnit(Bnand vol, SectorNo sectorNo, void FAR1 *fromAddress)
  2835. {
  2836. ANANDUnitNo virtualUnitNo = (ANANDUnitNo)(sectorNo >> vol.sectorsPerUnitBits);
  2837. ANANDUnitNo lastUnitNo,newVirtualUnitNo;
  2838. ANANDUnitNo unitNo,prevUnitNo;
  2839. FLStatus status;
  2840. byte ANAC,NAC,parityPerField;
  2841. if(virtualUnitNo==ANAND_NO_UNIT) /* Sanity check */
  2842. return flGeneralFailure;
  2843. status = allocateUnit(&vol,&unitNo);
  2844. if(status != flOK)
  2845. return status;
  2846. lastUnitNo = vol.virtualUnits[virtualUnitNo];
  2847. if(lastUnitNo == ANAND_NO_UNIT)
  2848. {
  2849. /* First time we write to this VU */
  2850. ANAC = NAC = 0;
  2851. }
  2852. else
  2853. {
  2854. status = getUnitData(&vol,lastUnitNo,&newVirtualUnitNo, &prevUnitNo,&ANAC,&NAC,&parityPerField);
  2855. if(status != flOK)
  2856. return status;
  2857. /* check if unit is valid */
  2858. if((badParityResult(parityPerField) ) ||
  2859. (virtualUnitNo != newVirtualUnitNo) )
  2860. {
  2861. DEBUG_PRINT(("\nwriteFullUnit: Found a brocken chain\r\n"));
  2862. return flGeneralFailure;
  2863. }
  2864. /* Update NAC */
  2865. if(vol.physicalUnits[lastUnitNo]&FIRST_IN_CHAIN)
  2866. {
  2867. NAC = 1; /* One unit chain , set proper NAC */
  2868. }
  2869. else
  2870. {
  2871. if(NAC>=MAX_UNIT_CHAIN)
  2872. {
  2873. status = foldUnit(&vol,virtualUnitNo,FL_NORMAL_FOLDING);
  2874. if (status != flOK)
  2875. {
  2876. status = checkFolding(&vol,status,virtualUnitNo);
  2877. if(status != flOK)
  2878. return status;
  2879. }
  2880. if(vol.virtualUnits[virtualUnitNo]==ANAND_NO_UNIT)
  2881. {
  2882. /* Unit had no used sectors and was erased */
  2883. lastUnitNo = ANAND_NO_UNIT;
  2884. ANAC = NAC = 0;
  2885. }
  2886. else /* After folding must be 1 unit chain */
  2887. {
  2888. NAC = 1;
  2889. }
  2890. }
  2891. }
  2892. }
  2893. status = assignUnit(&vol,unitNo,virtualUnitNo,ANAC,NAC);
  2894. if(status != flOK)
  2895. return status;
  2896. setUnitCount(unitNo,vol.sectorsPerUnit);
  2897. if(lastUnitNo==ANAND_NO_UNIT)
  2898. vol.physicalUnits[unitNo] |= FIRST_IN_CHAIN;
  2899. vol.virtualUnits[virtualUnitNo] = unitNo;
  2900. #if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
  2901. /* Turn verify write off since this is a new unit */
  2902. vol.curSectorWrite = 0; /* Store virtual sector Number */
  2903. #endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
  2904. #ifdef SCATTER_GATHER
  2905. /* Write in pairs (NAC is used as a simple index) */
  2906. for (NAC=0;NAC<vol.sectorsPerUnit;NAC+=2)
  2907. {
  2908. tffscpy(multiSectorBuf[vol.socketNo],
  2909. *((byte FAR1 **)fromAddress+NAC),SECTOR_SIZE);
  2910. tffscpy(multiSectorBuf[vol.socketNo]+SECTOR_SIZE,
  2911. *((byte FAR1 **)fromAddress+NAC+1),SECTOR_SIZE);
  2912. status = writeAndCheck(&vol,unitBaseAddress(vol,unitNo)+
  2913. (NAC<<(SECTOR_SIZE_BITS+1)),
  2914. multiSectorBuf[vol.socketNo],EDC,2);
  2915. if(status != flOK)
  2916. return status;
  2917. }
  2918. return status;
  2919. #else
  2920. return writeAndCheck(&vol,unitBaseAddress(vol,unitNo),fromAddress,
  2921. EDC,vol.sectorsPerUnit);
  2922. #endif /* SCATTER_GATHER */
  2923. }
  2924. #endif /* ENVIRONMENT_VARS */
  2925. /*----------------------------------------------------------------------*/
  2926. /* w r i t e M u l t i S e c t o r */
  2927. /* */
  2928. /* Write set of consecutive sectors */
  2929. /* */
  2930. /* Note : Special care was taken for SCATTER_GATHER option. In this */
  2931. /* user buffer is given as an array of 512 bytes buffers and not */
  2932. /* as a single large (sectors*512 Bytes) array. */
  2933. /* */
  2934. /* Parameters: */
  2935. /* vol : Pointer identifying drive */
  2936. /* sectorNo : Sector no. to write */
  2937. /* fromAddress : pointer to buffer to write */
  2938. /* sectorCount : # of sectors to write */
  2939. /* */
  2940. /* Returns: */
  2941. /* status of the write operaton */
  2942. /* */
  2943. /*----------------------------------------------------------------------*/
  2944. static FLStatus writeMultiSector(Bnand vol, SectorNo sectorNo,
  2945. void FAR1 *fromAddress,SectorNo sectorCount)
  2946. {
  2947. byte FAR1* curAddr = (byte FAR1 *)fromAddress;
  2948. SectorNo lastSector;
  2949. SectorNo i;
  2950. FLStatus status = flOK;
  2951. /* Check if sector is in virtual size boundries */
  2952. if (sectorNo + sectorCount > vol.virtualSectors)
  2953. return flSectorNotFound;
  2954. checkStatus(discardQuickMountInfo(&vol));
  2955. /*****************************************************/
  2956. /* Start from an odd address or only a one sector */
  2957. /*****************************************************/
  2958. if(((sectorNo & 1)!=0)||(sectorCount==1))
  2959. {
  2960. status=write2Sectors(&vol, sectorNo,
  2961. #ifdef SCATTER_GATHER
  2962. *(char FAR1 **)
  2963. #endif /* SCATTER_GATHER */
  2964. fromAddress,1);
  2965. if((sectorCount == 1 ) || /* finished (only 1 sector) */
  2966. (status != flOK) ) /* or operation failed */
  2967. return status;
  2968. sectorNo++;
  2969. sectorCount--;
  2970. /* Increament user buffer */
  2971. #ifdef SCATTER_GATHER
  2972. fromAddress=(void FAR1 *)((char FAR1 **)fromAddress+1);
  2973. #else
  2974. fromAddress=(byte FAR1 *)flAddLongToFarPointer(fromAddress,SECTOR_SIZE);
  2975. #endif /* SCATTER_GATHER */
  2976. }
  2977. /************************************************/
  2978. /* Write all the sequantial pair of sectors. */
  2979. /************************************************/
  2980. if(((sectorNo+sectorCount-1) & 1)==0)
  2981. {
  2982. /* Keep last sector since it can not be written as a pair */
  2983. lastSector = sectorNo+sectorCount-1;
  2984. }
  2985. else
  2986. {
  2987. lastSector = 0; /* All sectors can be written in pairs */
  2988. }
  2989. sectorCount = (sectorCount>>1)<<1; /* round down to even no' of sectors */
  2990. for(i=0;i<sectorCount;i+=2) /* write pair of sectors*/
  2991. {
  2992. #ifdef SCATTER_GATHER
  2993. curAddr = (void FAR1 *)((byte FAR1 **)fromAddress+i);
  2994. #else
  2995. curAddr=(byte FAR1 *)flAddLongToFarPointer(fromAddress,SECTOR_SIZE*i);
  2996. #endif /* SCATTER_GATHER */
  2997. #ifdef ENVIRONMENT_VARS
  2998. if((flPolicy[vol.socketNo][vol.flash->socket->curPartition]==FL_COMPLETE_ASAP) &&
  2999. /* sector is unit aligned */
  3000. (((sectorNo + i ) & vol.sectorsPerUnitMask) == 0) &&
  3001. /* enough sectors to fill a unit */
  3002. ( (sectorCount - i ) >= vol.sectorsPerUnit ))
  3003. {
  3004. status = writeFullUnit(&vol,sectorNo+i,curAddr);
  3005. if(status != flOK)
  3006. return status;
  3007. i += vol.sectorsPerUnit-2;
  3008. continue;
  3009. }
  3010. #endif /* ENVIRONMENT_VARS */
  3011. #ifdef SCATTER_GATHER
  3012. /* Copy scattered buffers to internal 1k buffer */
  3013. tffscpy(multiSectorBuf[vol.socketNo],*((char FAR1 **)curAddr),SECTOR_SIZE);
  3014. tffscpy(multiSectorBuf[vol.socketNo]+SECTOR_SIZE,*((char FAR1 **)curAddr+1),SECTOR_SIZE);
  3015. curAddr = multiSectorBuf[vol.socketNo];
  3016. #endif /* SCATTER_GATHER */
  3017. status = write2Sectors(&vol,sectorNo+i, curAddr,2);
  3018. if(status != flOK)
  3019. return status;
  3020. }
  3021. /*********************************************/
  3022. /* Write the last sector (not full page). */
  3023. /*********************************************/
  3024. if(lastSector!=0) /* write last sector */
  3025. {
  3026. #ifdef SCATTER_GATHER
  3027. fromAddress = (void FAR1 *)((byte FAR1 **)fromAddress+i);
  3028. #else
  3029. fromAddress = (void FAR1 *)flAddLongToFarPointer(fromAddress,SECTOR_SIZE*i);
  3030. #endif /* SCATTER_GATHER */
  3031. status=write2Sectors(&vol, lastSector,
  3032. #ifdef SCATTER_GATHER
  3033. *(char FAR1 **)
  3034. #endif /* SCATTER_GATHER */
  3035. fromAddress,1);
  3036. }
  3037. return status;
  3038. }
  3039. /*----------------------------------------------------------------------*/
  3040. /* d e l e t e S e c t o r */
  3041. /* */
  3042. /* Marks contiguous sectors as deleted. */
  3043. /* */
  3044. /* Parameters: */
  3045. /* vol : Pointer identifying drive */
  3046. /* sectorNo : First sector no. to delete */
  3047. /* noOfSectors : No. of sectors to delete */
  3048. /* */
  3049. /* Returns: */
  3050. /* FLStatus : 0 on success, failed otherwise */
  3051. /*----------------------------------------------------------------------*/
  3052. static FLStatus deleteSector(Bnand vol, SectorNo sectorNo,
  3053. SectorNo noOfSectors)
  3054. {
  3055. CardAddress sectorAddress;
  3056. SectorNo iSector;
  3057. ANANDUnitNo virtualUnitNo;
  3058. ANANDUnitNo currUnitNo;
  3059. byte sectorFlags[2] = {SECTOR_DELETED,SECTOR_DELETED};
  3060. FLBoolean lastOK; /* Dummy variable */
  3061. if (sectorNo + noOfSectors > vol.virtualSectors)
  3062. return flSectorNotFound;
  3063. checkStatus(discardQuickMountInfo(&vol));
  3064. for (iSector = 0; iSector < noOfSectors; iSector++, sectorNo++,
  3065. vol.sectorsDeleted++)
  3066. {
  3067. sectorAddress = virtual2Physical(&vol,sectorNo,ANAND_UNASSIGNED_ADDRESS,&lastOK);
  3068. switch(sectorAddress)
  3069. {
  3070. case ANAND_UNASSIGNED_ADDRESS:
  3071. continue;
  3072. case ANAND_BAD_CHAIN_ADDRESS:
  3073. return flGeneralFailure;
  3074. default:
  3075. virtualUnitNo = (ANANDUnitNo)(sectorNo >> vol.sectorsPerUnitBits);
  3076. #ifdef NFTL_CACHE
  3077. setSectorFlagsCache(&vol, sectorAddress, SECTOR_DELETED);
  3078. #ifdef ENVIRONMENT_VARS
  3079. if (((flMarkDeleteOnFlash == FL_ON) &&
  3080. (flPolicy[vol.socketNo][vol.flash->socket->curPartition] != FL_COMPLETE_ASAP)) ||
  3081. (vol.scache == NULL))
  3082. #endif /* ENVIRONMENT_VARS */
  3083. #endif /* NFTL_CACHE */
  3084. {
  3085. #ifndef NT5PORT
  3086. checkStatus(vol.flash->write(vol.flash,
  3087. sectorAddress + SECTOR_DATA_OFFSET,
  3088. &sectorFlags,
  3089. sizeof sectorFlags,
  3090. EXTRA));
  3091. #else /*NT5PORT*/
  3092. vol.flash->write(vol.flash,
  3093. sectorAddress + SECTOR_DATA_OFFSET,
  3094. sectorFlags,
  3095. sizeof sectorFlags,
  3096. EXTRA);
  3097. #endif /*NT5PORT*/
  3098. }
  3099. currUnitNo = vol.virtualUnits[virtualUnitNo];
  3100. if (vol.countsValid > virtualUnitNo)
  3101. {
  3102. if (countOf(currUnitNo) > 0)
  3103. {
  3104. vol.physicalUnits[currUnitNo]--; /* Decrement block count */
  3105. }
  3106. else
  3107. {
  3108. DEBUG_PRINT(("delete sector : Unit does not apear to have any sectors\r\n"));
  3109. return flGeneralFailure;
  3110. }
  3111. }
  3112. } /* End sectorAddress switch */
  3113. } /* End delete sector loop */
  3114. return flOK;
  3115. }
  3116. #ifdef DEFRAGMENT_VOLUME
  3117. /*----------------------------------------------------------------------*/
  3118. /* d e f r a g m e n t */
  3119. /* */
  3120. /* Performs unit allocations to arrange a minimum number of writable */
  3121. /* sectors. */
  3122. /* */
  3123. /* Parameters: */
  3124. /* vol : Pointer identifying drive */
  3125. /* sectorsNeeded : Minimum required sectors */
  3126. /* */
  3127. /* Returns: */
  3128. /* FLStatus : 0 on success, failed otherwise */
  3129. /*----------------------------------------------------------------------*/
  3130. static FLStatus defragment(Bnand vol, long FAR2 *sectorsNeeded)
  3131. {
  3132. ANANDUnitNo dummyUnitNo;
  3133. ANANDUnitNo firstFreeUnit = ANAND_NO_UNIT;
  3134. FLBoolean firstRound = TRUE;
  3135. FLStatus status = flOK;
  3136. checkStatus(discardQuickMountInfo(&vol));
  3137. if( (*sectorsNeeded) == -1 ) /* fold single best chain */
  3138. {
  3139. status = foldBestChain(&vol,&dummyUnitNo);
  3140. if( (status != flOK) && (vol.freeUnits == 0) )
  3141. return status;
  3142. *sectorsNeeded = (long)vol.freeUnits << vol.sectorsPerUnitBits;
  3143. return flOK;
  3144. }
  3145. /* Perform folding until the required number of sectors is achived */
  3146. while (((long)vol.freeUnits << vol.sectorsPerUnitBits) < *sectorsNeeded)
  3147. {
  3148. status = foldBestChain(&vol,&dummyUnitNo); /* make more free units */
  3149. if(status != flOK)
  3150. break;
  3151. }
  3152. *sectorsNeeded = (long)vol.freeUnits << vol.sectorsPerUnitBits;
  3153. return status;
  3154. }
  3155. #endif /* DEFRAGMENT */
  3156. #endif /* FL_READ_ONLY */
  3157. /*----------------------------------------------------------------------*/
  3158. /* t l S e t B u s y */
  3159. /* */
  3160. /* Notifies the start and end of a file-system operation. */
  3161. /* */
  3162. /* Parameters: */
  3163. /* vol : Pointer identifying drive */
  3164. /* state : FL_ON (1) = operation entry */
  3165. /* FL_OFF(0) = operation exit */
  3166. /* */
  3167. /* Returns: */
  3168. /* FLStatus : 0 on success, failed otherwise */
  3169. /*----------------------------------------------------------------------*/
  3170. static FLStatus tlSetBusy(Bnand vol, FLBoolean state)
  3171. {
  3172. return flOK;
  3173. }
  3174. /*----------------------------------------------------------------------*/
  3175. /* s e c t o r s I n V o l u m e */
  3176. /* */
  3177. /* Gets the total number of sectors in the volume */
  3178. /* */
  3179. /* Parameters: */
  3180. /* vol : Pointer identifying drive */
  3181. /* */
  3182. /* Returns: */
  3183. /* Number of sectors in the volume */
  3184. /*----------------------------------------------------------------------*/
  3185. static SectorNo sectorsInVolume(Bnand vol)
  3186. {
  3187. return vol.virtualSectors;
  3188. }
  3189. /*----------------------------------------------------------------------*/
  3190. /* p u t G e t B u f f e r */
  3191. /* */
  3192. /* Write \ Read a buffer to the flash from a specific flash offset */
  3193. /* while making sure only good units are used. */
  3194. /* */
  3195. /* Parameters: */
  3196. /* vol : Pointer identifying drive */
  3197. /* length : Size of the buffer (always full pages) */
  3198. /* bufferPtr : Data buffer */
  3199. /* flashAddr : Physcial address on the flash */
  3200. /* bbt : Buffer containing BBT of the quick mount area */
  3201. /* readFlag : TRUE - read data , FLASE - write data */
  3202. /* */
  3203. /* Returns: */
  3204. /* FLStatus : 0 on success, failed otherwise */
  3205. /* bufferPtr : Increamented data buffer */
  3206. /* flashAddr : Increamented physcial address on the flash */
  3207. /*----------------------------------------------------------------------*/
  3208. #ifdef QUICK_MOUNT_FEATURE
  3209. static FLStatus putGetBuffer(Bnand vol, dword length, byte FAR1** bufferPtr,
  3210. CardAddress* flashAddr, byte* bbt, FLBoolean readFlag)
  3211. {
  3212. FLStatus status;
  3213. word writeNow = 0;
  3214. while (length > 0)
  3215. {
  3216. writeNow = (word)TFFSMIN(length,(((*flashAddr >> vol.unitSizeBits)+1)
  3217. << vol.unitSizeBits) - *flashAddr);
  3218. if (readFlag)
  3219. {
  3220. status = vol.flash->read(vol.flash,*flashAddr,*bufferPtr,
  3221. (dword)writeNow,EDC);
  3222. }
  3223. #ifndef FL_READ_ONLY
  3224. else
  3225. {
  3226. status = vol.flash->write(vol.flash,*flashAddr,*bufferPtr,
  3227. (dword)writeNow,EDC);
  3228. }
  3229. #endif /* FL_READ_ONLY */
  3230. if(status != flOK)
  3231. return status;
  3232. length -= writeNow;
  3233. *flashAddr += writeNow;
  3234. *bufferPtr = BYTE_ADD_FAR(*bufferPtr,writeNow);
  3235. NextGoodUnit(*flashAddr,bbt);
  3236. }
  3237. return flOK;
  3238. }
  3239. /*----------------------------------------------------------------------*/
  3240. /* q u i c k M o u n t D a t a */
  3241. /* */
  3242. /* Saves or restores the quick mount data to and from the flash */
  3243. /* */
  3244. /* Note : the data is saved according to the mechines architecture. Big */
  3245. /* Indien is not converted into little indien like the rest of */
  3246. /* of INFTL flash data structure */
  3247. /* */
  3248. /* The following will be saved : */
  3249. /* */
  3250. /* 1) physical Units table */
  3251. /* 2) virutal Units table */
  3252. /* 3) TL strucutre (Not by this routien but by its caller */
  3253. /* */
  3254. /* Parameters: */
  3255. /* vol : Pointer identifying drive */
  3256. /* readFlag : TRUE for retrieve data FALSE for writing it */
  3257. /* */
  3258. /* Returns: */
  3259. /* flOK on success other error codes for erase\read\write failures */
  3260. /* start : Unit offset (from the first unit of the */
  3261. /* volume to start writting quick mount data. */
  3262. /* (remember migh be bad). */
  3263. /*----------------------------------------------------------------------*/
  3264. static FLStatus quickMountData(Bnand vol, FLBoolean readFlag, byte* start)
  3265. {
  3266. dword length;
  3267. dword remainder;
  3268. word partialSize;
  3269. CardAddress flashAddr;
  3270. FLStatus status;
  3271. byte FAR1* bufferPtr = vol.physicalUnits;
  3272. byte bbt[MAX_QUICK_MOUNT_UNITS]; /* Minimal bad blocks table */
  3273. /* Read bad block tabel and find the first good block of the volume */
  3274. status = vol.flash->readBBT(vol.flash,vol.firstQuickMountUnit,
  3275. MAX_QUICK_MOUNT_UNITS,vol.blockMultiplierBits,bbt,FALSE);
  3276. if(status != flOK)
  3277. return status;
  3278. for(*start = 0 ; (*start<MAX_QUICK_MOUNT_UNITS) &&
  3279. (bbt[*start] != BBT_GOOD_UNIT) ; (*start)++);
  3280. if (*start == MAX_QUICK_MOUNT_UNITS)
  3281. {
  3282. DEBUG_PRINT(("\nDebug: Too many Bad blocks in quick mount area\r\n"));
  3283. return flBadBBT;
  3284. }
  3285. /* Skip first page for Bnand record */
  3286. flashAddr = ((CardAddress)(vol.firstQuickMountUnit + (*start))
  3287. << vol.unitSizeBits) + vol.flash->pageSize;
  3288. /* Only the full pages of physical table */
  3289. length = vol.noOfUnits * sizeof(ANANDPhysUnit); /* Physicals length */
  3290. remainder = length & (SECTOR_SIZE-1)/*vol.flash->pageSize*/; /* Last partial page */
  3291. length -= remainder; /* Round to pages */
  3292. status = putGetBuffer(&vol, length, &bufferPtr, &flashAddr,bbt,readFlag);
  3293. if(status != flOK)
  3294. return status;
  3295. /* Partial page of the physical table + begining of virtual table */
  3296. length = vol.noOfVirtualUnits * sizeof(ANANDUnitNo); /* Virtuals */
  3297. partialSize = (word)TFFSMIN(length,(dword)SECTOR_SIZE-remainder);
  3298. if (remainder > 0)
  3299. {
  3300. if (readFlag)
  3301. {
  3302. status = vol.flash->read(vol.flash,flashAddr , inftlBuffer,
  3303. sizeof(inftlBuffer),EDC);
  3304. tffscpy(bufferPtr,inftlBuffer,(word)remainder);
  3305. tffscpy(vol.virtualUnits,inftlBuffer+(word)remainder,partialSize);
  3306. }
  3307. #ifndef FL_READ_ONLY
  3308. else
  3309. {
  3310. tffscpy(inftlBuffer,bufferPtr, (word)remainder);
  3311. tffscpy(inftlBuffer+(word)remainder,vol.virtualUnits,partialSize);
  3312. status = vol.flash->write(vol.flash,flashAddr,inftlBuffer,
  3313. sizeof(inftlBuffer),EDC);
  3314. }
  3315. #endif /* FL_READ_ONLY */
  3316. if(status != flOK)
  3317. return status;
  3318. bufferPtr = partialSize + (byte FAR1*)vol.virtualUnits;
  3319. flashAddr += SECTOR_SIZE/*vol.flash->pageSize*/;
  3320. NextGoodUnit(flashAddr,bbt); /* if needed check for next good unit */
  3321. }
  3322. else
  3323. {
  3324. bufferPtr = (byte FAR1*)vol.virtualUnits;
  3325. }
  3326. /* Only the full pages of virtual table */
  3327. length -= partialSize; /* Remaining virtuals */
  3328. remainder = length % SECTOR_SIZE/*vol.flash->pageSize*/; /* Last partial page */
  3329. length -= remainder; /* Round to pages */
  3330. status = putGetBuffer(&vol,length,&bufferPtr,&flashAddr,bbt,readFlag);
  3331. if(status != flOK)
  3332. return status;
  3333. /* Partial page of the virtual table */
  3334. if (remainder>0)
  3335. {
  3336. if(readFlag)
  3337. {
  3338. status = vol.flash->read(vol.flash,flashAddr,inftlBuffer,
  3339. sizeof(inftlBuffer),EDC);
  3340. tffscpy(bufferPtr , inftlBuffer,(word)remainder);
  3341. }
  3342. #ifndef FL_READ_ONLY
  3343. else
  3344. {
  3345. tffscpy(inftlBuffer , bufferPtr , (word)remainder);
  3346. status = vol.flash->write(vol.flash,flashAddr,inftlBuffer,
  3347. sizeof(inftlBuffer),EDC);
  3348. }
  3349. #endif /* FL_READ_ONLY */
  3350. }
  3351. return status;
  3352. }
  3353. #endif /* QUICK_MOUNT_FEATURE */
  3354. /*----------------------------------------------------------------------*/
  3355. /* d i s m o u n t I N F T L */
  3356. /* */
  3357. /* Dismount INFTL volume */
  3358. /* */
  3359. /* Parameters: */
  3360. /* vol : Pointer identifying drive */
  3361. /* */
  3362. /*----------------------------------------------------------------------*/
  3363. static void dismountINFTL(Bnand vol)
  3364. {
  3365. DEBUG_PRINT(("\nDebug: starting INFTL dismount.\r\n"));
  3366. #if (defined(QUICK_MOUNT_FEATURE) && !defined(FL_READ_ONLY))
  3367. if ((vol.flags & QUICK_MOUNT) && (vol.firstMediaWrite == TRUE))
  3368. {
  3369. savedBnand* newVol = (savedBnand*)inftlBuffer;
  3370. byte start;
  3371. FLStatus status;
  3372. DEBUG_PRINT(("\nDebug: with save operation of quick mount data.\r\n"));
  3373. start = vol.firstUnit - vol.firstQuickMountUnit;
  3374. status = vol.flash->erase(vol.flash,(word)(vol.firstQuickMountUnit
  3375. << vol.blockMultiplierBits),
  3376. (word)((1 << vol.blockMultiplierBits) * start));
  3377. if (status==flOK)
  3378. {
  3379. vol.flags &= ~QUICK_MOUNT; /* Prevent resaving the data */
  3380. status = quickMountData(&vol, FALSE,&start);
  3381. if (status == flOK)
  3382. {
  3383. /* Place Bnand record */
  3384. tffsset(inftlBuffer,0,sizeof(inftlBuffer)); /* Clear inftlBuffer */
  3385. /*********************************************************/
  3386. /* Convert internal volume to little indian dword fields */
  3387. /*********************************************************/
  3388. toLE4(newVol->freeUnits , vol.freeUnits );
  3389. toLE4(newVol->roverUnit , vol.roverUnit );
  3390. toLE4(newVol->countsValid , vol.countsValid );
  3391. toLE4(newVol->sectorsRead , vol.sectorsRead );
  3392. toLE4(newVol->sectorsWritten , vol.sectorsWritten );
  3393. toLE4(newVol->sectorsDeleted , vol.sectorsDeleted );
  3394. toLE4(newVol->parasiteWrites , vol.parasiteWrites );
  3395. toLE4(newVol->unitsFolded , vol.unitsFolded );
  3396. toLE4(newVol->wearLevel_1 , vol.wearLevel.alarm );
  3397. toLE4(newVol->wearLevel_2 , vol.wearLevel.currUnit);
  3398. toLE4(newVol->eraseSum , vol.eraseSum );
  3399. toLE4(newVol->validate , QUICK_MOUNT_VALID_SIGN);
  3400. #if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
  3401. toLE4(newVol->verifiedSectorNo , vol.verifiedSectorNo);
  3402. #else
  3403. toLE4(newVol->verifiedSectorNo , 0);
  3404. #endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
  3405. status = vol.flash->write(vol.flash,((CardAddress)(vol.firstQuickMountUnit
  3406. +start))<< vol.unitSizeBits,inftlBuffer, sizeof(inftlBuffer),EDC);
  3407. }
  3408. if (status != flOK)
  3409. DEBUG_PRINT(("Debug: ERROR writing quick mount information.\r\n"));
  3410. }
  3411. else /* continue with dismount */
  3412. {
  3413. DEBUG_PRINT(("Debug: Error erasing quick mount information.\r\n"));
  3414. }
  3415. }
  3416. #endif /* QUICK_MOUNT_FEATURE && not FL_READ_ONLY */
  3417. #ifdef FL_MALLOC
  3418. /* Free multi sector buffers */
  3419. if (multiSectorBufCounter[vol.socketNo] == 0)
  3420. {
  3421. if (multiSectorBuf[vol.socketNo] != NULL)
  3422. {
  3423. FL_FREE(multiSectorBuf[vol.socketNo]);
  3424. multiSectorBuf[vol.socketNo] = NULL;
  3425. }
  3426. }
  3427. if (multiSectorBufCounter[vol.socketNo] >= 0)
  3428. {
  3429. multiSectorBufCounter[vol.socketNo]--;
  3430. }
  3431. /* Free convertion tables */
  3432. if( vol.physicalUnits != NULL )
  3433. {
  3434. #if (defined (CHAINS_DEBUG) && !defined(CHECK_MOUNT))
  3435. FILE * out;
  3436. out = getFileHandle(&vol,0);
  3437. if (out == NULL)
  3438. {
  3439. DEBUG_PRINT(("Debug: Can not open debug file.\r\n"));
  3440. }
  3441. else
  3442. {
  3443. checkVirtualChains(&vol,out);
  3444. checkVolumeStatistics(&vol,out);
  3445. }
  3446. #endif /* CHAINS_DEBUG AND NOT CHECK_MOUNT*/
  3447. FL_FAR_FREE(vol.physicalUnits);
  3448. }
  3449. if( vol.virtualUnits != NULL )
  3450. FL_FAR_FREE(vol.virtualUnits);
  3451. vol.physicalUnits = NULL;
  3452. vol.virtualUnits = NULL;
  3453. /* Free catche tables */
  3454. #ifdef NFTL_CACHE
  3455. if( vol.ucache != NULL )
  3456. FL_FAR_FREE(vol.ucache);
  3457. if( vol.scache != NULL )
  3458. FL_FAR_FREE(vol.scache);
  3459. vol.ucache = NULL;
  3460. vol.scache = NULL;
  3461. #endif /* NFTL_CACHE */
  3462. #endif /* FL_MALLOC */
  3463. DEBUG_PRINT(("Debug: finished INFTL dismount.\r\n"));
  3464. }
  3465. /*----------------------------------------------------------------------*/
  3466. /* r e t r i e v e H e a d e r */
  3467. /* */
  3468. /* Retrieve media header by oring the headers of each floor */
  3469. /* */
  3470. /* Note: The header of each floor is read to the first half of the */
  3471. /* buffer and then ORed to the second half therefor constructing */
  3472. /* the real header in the upper half. After all copies are read */
  3473. /* the data is copied to the first half. */
  3474. /* */
  3475. /* Note: No endian format changes are made. */
  3476. /* */
  3477. /* Parameters: */
  3478. /* vol : Pointer identifying drive */
  3479. /* originalUnits : Array to store original units locations */
  3480. /* readFullBBT : Boolean flag. When true the entire BBT will be read */
  3481. /* and media units locations will be returned through */
  3482. /* the originalUnits argument array. When FALSE only */
  3483. /* the size of HEADER_SEARCH_BOUNDRY of each floor */
  3484. /* be read. */
  3485. /* retrieveData : Boolean flag. When true the header will be read */
  3486. /* */
  3487. /* Returns: */
  3488. /* flOK on success any other value on error */
  3489. /* flBadFormat if header was not found */
  3490. /*----------------------------------------------------------------------*/
  3491. FLStatus retrieveHeader (Bnand vol , ANANDUnitNo * originalUnits,
  3492. FLBoolean readFullBBT , FLBoolean retrieveData)
  3493. {
  3494. ANANDUnitNo iUnit,index;
  3495. ANANDUnitNo noOfUnitsPerFloor;
  3496. byte headerSize;
  3497. byte floorNo;
  3498. FLStatus status=flOK;
  3499. byte bbt[HEADER_SEARCH_BOUNDRY];
  3500. byte FAR1* BBT;
  3501. noOfUnitsPerFloor = (ANANDUnitNo)(vol.flash->chipSize >> vol.unitSizeBits) *
  3502. ((vol.flash->noOfChips + (vol.flash->noOfChips % vol.flash->noOfFloors)) /
  3503. vol.flash->noOfFloors);
  3504. headerSize = sizeof(BNANDBootRecord)+MAX_TL_PARTITIONS*sizeof(BNANDVolumeHeaderRecord);
  3505. tffsset(originalUnits,0,sizeof(ANANDUnitNo) * MAX_NO_OF_FLOORS);
  3506. if (readFullBBT == TRUE) /* read entire BBT into vol records (format) */
  3507. {
  3508. status = vol.flash->readBBT(vol.flash,0,vol.noOfUnits,
  3509. vol.blockMultiplierBits,
  3510. vol.physicalUnits,TRUE);
  3511. if(status != flOK)
  3512. return status;
  3513. BBT = vol.physicalUnits;
  3514. }
  3515. else
  3516. {
  3517. BBT = bbt;
  3518. }
  3519. /* Go over all of the media floors and find header location */
  3520. for (floorNo = 0 ; floorNo < vol.flash->noOfFloors ; floorNo++)
  3521. {
  3522. iUnit = (ANANDUnitNo)floorNo * noOfUnitsPerFloor;
  3523. if (readFullBBT == FALSE) /* read small part of the floors BBT */
  3524. {
  3525. status = vol.flash->readBBT(vol.flash,iUnit,
  3526. HEADER_SEARCH_BOUNDRY,vol.blockMultiplierBits,BBT,FALSE);
  3527. if(status != flOK)
  3528. return status;
  3529. iUnit=0;
  3530. }
  3531. /* find and save location of the first good block of the floor */
  3532. index = iUnit + HEADER_SEARCH_BOUNDRY;
  3533. while ((iUnit<index)&&(BBT[iUnit]!=BBT_GOOD_UNIT))
  3534. {
  3535. iUnit++;
  3536. }
  3537. if (iUnit==index)
  3538. {
  3539. DEBUG_PRINT(("Debug: ERROR too many bad blocks (can not find place for INFTL header.\r\n"));
  3540. return flBadBBT;
  3541. }
  3542. if (readFullBBT == FALSE) /* Restore iUnit pointer to the physical media */
  3543. {
  3544. iUnit += (ANANDUnitNo)floorNo * noOfUnitsPerFloor;
  3545. }
  3546. originalUnits[floorNo] = iUnit; /* Save origial unit location */
  3547. }
  3548. if (retrieveData == FALSE)
  3549. return flOK;
  3550. /* Need to read the previous header */
  3551. tffsset(inftlBuffer,0,SECTOR_SIZE);
  3552. for (floorNo = 0 ; floorNo < vol.flash->noOfFloors ; floorNo++)
  3553. {
  3554. for (index=0;index<NO_OF_MEDIA_HEADERS;index++) /* both 2 copies */
  3555. {
  3556. status = vol.flash->read(vol.flash,((CardAddress)originalUnits[floorNo]
  3557. << vol.unitSizeBits) + index * HEADERS_SPACING,
  3558. inftlBuffer + headerSize,headerSize,PARTIAL_EDC);
  3559. if (status != flOK)
  3560. {
  3561. DEBUG_PRINT(("Debug: ERROR reading original unit header.\r\n"));
  3562. }
  3563. else
  3564. {
  3565. if (tffscmp(inftlBuffer + headerSize, "BNAND", sizeof("BNAND")) == 0)
  3566. break;
  3567. }
  3568. }
  3569. if (index>=NO_OF_MEDIA_HEADERS)
  3570. {
  3571. DEBUG_PRINT(("Debug: Media header was not found on all copies.\r\n"));
  3572. return flBadFormat;
  3573. }
  3574. /* merge with previous headers */
  3575. for (index = 0 ; headerSize > index ; index++)
  3576. {
  3577. inftlBuffer[index] |= inftlBuffer[index + headerSize];
  3578. }
  3579. } /* loop of the floors */
  3580. return flOK;
  3581. }
  3582. /*----------------------------------------------------------------------*/
  3583. /* I N F T L I n f o */
  3584. /* */
  3585. /* get INFTL information. */
  3586. /* */
  3587. /* Parameters: */
  3588. /* vol : Pointer discribing volume. */
  3589. /* tlInfo : Pointer to user record */
  3590. /* */
  3591. /* Returns: */
  3592. /* FLStatus : 0 on success, failed otherwise */
  3593. /* tlInfo : Record containing tl infromation. */
  3594. /*----------------------------------------------------------------------*/
  3595. static FLStatus INFTLInfo(Bnand vol, TLInfo *tlInfo)
  3596. {
  3597. tlInfo->sectorsInVolume = vol.virtualSectors;
  3598. tlInfo->bootAreaSize = (dword)vol.bootUnits << vol.unitSizeBits;
  3599. tlInfo->eraseCycles = vol.eraseSum;
  3600. tlInfo->tlUnitBits = vol.unitSizeBits;
  3601. return flOK;
  3602. }
  3603. #ifndef NO_READ_BBT_CODE
  3604. /*----------------------------------------------------------------------*/
  3605. /* r e a d B B T */
  3606. /* */
  3607. /* Returns a pointer to the BBT of the device. */
  3608. /* Note: Bad unit are marked with a 4 bytes address of the unit. */
  3609. /* Note: A unit can contain several blocks */
  3610. /* */
  3611. /* Parameters: */
  3612. /* vol : Pointer identifying drive */
  3613. /* buf : pointer to buffer to read into */
  3614. /* */
  3615. /* Returns: */
  3616. /* FLStatus : 0 on success, failed otherwise */
  3617. /* noOfBB : returns the number of bad unit of the media */
  3618. /* meidaSize : returns the media size in bytes */
  3619. /*----------------------------------------------------------------------*/
  3620. static FLStatus readBBT(Bnand vol, CardAddress FAR1 * buf,
  3621. long FAR2 * mediaSize, unsigned FAR2 * noOfBB)
  3622. {
  3623. dword iUnit;
  3624. dword noOfUnits = (ANANDUnitNo)(((dword)vol.flash->noOfChips * vol.flash->chipSize) >> vol.unitSizeBits);
  3625. dword index,curRead;
  3626. ANANDUnitNo maxBad = (ANANDUnitNo)(noOfUnits * ANAND_BAD_PERCENTAGE / 100);
  3627. CardAddress FAR1 * ptr = buf;
  3628. *noOfBB = 0;
  3629. if ( vol.flash->readBBT == NULL)
  3630. {
  3631. DEBUG_PRINT(("Debug: ERROR unerasable BBT not supported by MTD.\r\n"));
  3632. return flGeneralFailure;
  3633. }
  3634. else
  3635. {
  3636. for (iUnit=vol.flash->firstUsableBlock;iUnit<noOfUnits;iUnit+=curRead)
  3637. {
  3638. curRead = TFFSMIN(SECTOR_SIZE,noOfUnits-iUnit);
  3639. vol.flash->readBBT(vol.flash,iUnit,curRead,vol.blockMultiplierBits,multiSectorBuf[vol.socketNo],FALSE);
  3640. for ( index = 0 ; (index < curRead) && (*noOfBB < maxBad); index++)
  3641. if ((*(multiSectorBuf[vol.socketNo] + index) != BBT_GOOD_UNIT) && /* Not good unit */
  3642. (*(multiSectorBuf[vol.socketNo] + index) != BBT_UNAVAIL_UNIT)) /* Not used for a special purpose */
  3643. {
  3644. *ptr = (iUnit+index) << vol.unitSizeBits;
  3645. ptr = (CardAddress FAR1*)flAddLongToFarPointer((byte FAR1 *)ptr,
  3646. sizeof(CardAddress));
  3647. (*noOfBB)++;
  3648. }
  3649. if ( *noOfBB == maxBad)
  3650. {
  3651. DEBUG_PRINT(("Debug: ERROR to many bad blocks.\r\n"));
  3652. return flVolumeTooSmall;
  3653. }
  3654. }
  3655. }
  3656. *mediaSize = (long) noOfUnits << vol.unitSizeBits;
  3657. return flOK;
  3658. }
  3659. #endif /* NO_READ_BBT_CODE */
  3660. /*----------------------------------------------------------------------*/
  3661. /* c o n v e r t C h a i n */
  3662. /* */
  3663. /* Convert candidate chain to given value. */
  3664. /* */
  3665. /* Parameters: */
  3666. /* vol : Pointer identifying drive */
  3667. /* newestUnitNo : newest unit in chain */
  3668. /* oldestUnitNo : oldest unit in chain */
  3669. /* virtualUnitNo : virtual unit no */
  3670. /* chainsMark : new value */
  3671. /* */
  3672. /* Returns: */
  3673. /* FLStatus : 0 on success, failed otherwise */
  3674. /*----------------------------------------------------------------------*/
  3675. static FLStatus convertChain(Bnand vol,
  3676. ANANDUnitNo newestUnitNo,
  3677. ANANDUnitNo oldestUnitNo,
  3678. ANANDUnitNo virtualUnitNo,
  3679. byte chainsMark)
  3680. {
  3681. ANANDUnitNo chainBound = 0;
  3682. for(;newestUnitNo != oldestUnitNo ; chainBound++,
  3683. newestUnitNo = getPrevUnit(&vol,newestUnitNo,virtualUnitNo))
  3684. {
  3685. if((newestUnitNo == ANAND_BAD_CHAIN_UNIT ) || /* Brocken chain */
  3686. (chainBound >= DOUBLE_MAX_UNIT_CHAIN)) /* Infinit loop */
  3687. return flGeneralFailure;
  3688. vol.physicalUnits[newestUnitNo] = chainsMark;
  3689. }
  3690. vol.physicalUnits[oldestUnitNo] = chainsMark;
  3691. return flOK;
  3692. }
  3693. #ifndef FL_READ_ONLY
  3694. /*----------------------------------------------------------------------*/
  3695. /* e r a s e O r p h a n U n i t */
  3696. /* */
  3697. /* Erase one unit. */
  3698. /* */
  3699. /* Parameters: */
  3700. /* vol : Pointer identifying drive */
  3701. /* unitNo : Unit to format */
  3702. /* */
  3703. /* Returns: */
  3704. /* FLStatus : 0 on success, failed otherwise */
  3705. /*----------------------------------------------------------------------*/
  3706. static FLStatus eraseOrphanUnit(Bnand vol, ANANDUnitNo unitNo)
  3707. {
  3708. word eraseMark;
  3709. dword eraseCount;
  3710. FLStatus status;
  3711. status = getUnitTailer(&vol,unitNo,&eraseMark,&eraseCount,UNIT_TAILER_OFFSET);
  3712. if(status != flOK)
  3713. return status;
  3714. if(unitNo+(ANANDUnitNo)vol.firstUnit<(ANANDUnitNo)vol.firstUnit)
  3715. {
  3716. return flGeneralFailure;
  3717. }
  3718. status = vol.flash->erase(vol.flash,
  3719. (word)(((dword)unitNo+(dword)vol.firstUnit) << (vol.unitSizeBits - vol.erasableBlockSizeBits)),
  3720. (word)(1 << vol.blockMultiplierBits));
  3721. if (status != flOK) {
  3722. markUnitBad(&vol,unitNo); /* make sure unit format is not valid */
  3723. return status;
  3724. }
  3725. vol.eraseSum++;
  3726. eraseCount++;
  3727. if (eraseCount == 0) /* was hex FF's */
  3728. eraseCount++;
  3729. return setUnitTailer(&vol,unitNo,ERASE_MARK,eraseCount,UNIT_TAILER_OFFSET);
  3730. }
  3731. #endif /* FL_READ_ONLY */
  3732. /*----------------------------------------------------------------------*/
  3733. /* c h e c k U n i t H e a d */
  3734. /* */
  3735. /* Compare 2 copies of unit header. */
  3736. /* */
  3737. /* Parameters: */
  3738. /* vol : Pointer identifying drive */
  3739. /* unitNo : Physical unit number */
  3740. /* */
  3741. /* Returns: */
  3742. /* flOK on success, flFormattingError on miscompare. */
  3743. /*----------------------------------------------------------------------*/
  3744. static FLStatus checkUnitHead(Bnand vol, ANANDUnitNo unitNo)
  3745. {
  3746. ANANDUnitHeader unitData;
  3747. SecondANANDUnitHeader secondUnitData;
  3748. /* Read first unit data */
  3749. checkStatus(vol.flash->read(vol.flash,
  3750. unitBaseAddress(vol,unitNo) + UNIT_DATA_OFFSET,
  3751. &unitData,
  3752. sizeof(ANANDUnitHeader),
  3753. EXTRA));
  3754. checkStatus(vol.flash->read(vol.flash, unitBaseAddress(vol,unitNo) +
  3755. SECOND_HEADER_OFFSET + UNIT_DATA_OFFSET,
  3756. &secondUnitData,
  3757. sizeof(SecondANANDUnitHeader),
  3758. EXTRA));
  3759. if((LE2(secondUnitData.virtualUnitNo) != LE2(unitData.virtualUnitNo)) ||
  3760. (LE2(secondUnitData.prevUnitNo ) != LE2(unitData.prevUnitNo )) ||
  3761. (secondUnitData.ANAC != secondUnitData.ANAC ) )
  3762. return flFormattingError;
  3763. return flOK;
  3764. }
  3765. /*----------------------------------------------------------------------*/
  3766. /* g o A l o n g C h a i n */
  3767. /* */
  3768. /* Go along the INFTL chaine while marking the chain in the convertion */
  3769. /* tables. This routine is called by the mount routine in order to */
  3770. /* initialize the volumes convertion tables. */
  3771. /* */
  3772. /* Parameters: */
  3773. /* vol : Pointer identifying drive */
  3774. /* unitNo : Physical unit to check. */
  3775. /* */
  3776. /* Returns: */
  3777. /* FLStatus : 0 on success, failed otherwise */
  3778. /*----------------------------------------------------------------------*/
  3779. static FLStatus goAlongChain(Bnand vol,ANANDUnitNo unitNo)
  3780. {
  3781. ANANDUnitNo origVirtualNo,virtualUnitNo,prevUnitNo;
  3782. ANANDUnitNo lastCurrent,nextUnitNo,lastUnitNo;
  3783. byte ANAC, NAC, prevANAC, parityPerField;
  3784. FLStatus status;
  3785. word eraseMark;
  3786. dword eraseCount;
  3787. /* Check if already been here */
  3788. if((vol.physicalUnits[unitNo]==FL_VALID) ||
  3789. (vol.physicalUnits[unitNo]==FL_FIRST_VALID) ||
  3790. (vol.physicalUnits[unitNo]==FL_PRELIMINARY) ||
  3791. (vol.physicalUnits[unitNo]==FL_FIRST_PRELIMINARY))
  3792. return flOK;
  3793. /* Read unit tailor to check the erase mark */
  3794. status = getUnitTailer(&vol,unitNo,&eraseMark,&eraseCount,UNIT_TAILER_OFFSET);
  3795. if(status != flOK)
  3796. return status;
  3797. vol.eraseSum+=eraseCount;
  3798. if (eraseMark != ERASE_MARK)
  3799. {
  3800. /* Do not perform erase in the mount. The allocateUnit routine */
  3801. /* rechecks for the erase mark and it will erase this unit. */
  3802. vol.physicalUnits[unitNo] = ANAND_UNIT_FREE;
  3803. return flOK;
  3804. }
  3805. status = getUnitData(&vol,unitNo,&virtualUnitNo, &prevUnitNo,
  3806. &ANAC,&NAC,&parityPerField);
  3807. if(status != flOK)
  3808. return status;
  3809. /* Check parity result of values returned by getUnitData */
  3810. if(badParityResult(parityPerField))
  3811. {
  3812. vol.physicalUnits[unitNo]=FL_PRELIMINARY;
  3813. return flOK;
  3814. }
  3815. /* Check if the unit is free (all fields are FF) */
  3816. if((virtualUnitNo == ANAND_NO_UNIT ) &&
  3817. (prevUnitNo == ANAND_NO_UNIT ) &&
  3818. (ANAC == ANAND_UNIT_FREE) &&
  3819. (NAC == ANAND_UNIT_FREE))
  3820. return flOK; /* free unit */
  3821. /* Check virtual unit number that was returned */
  3822. if((virtualUnitNo == ANAND_NO_UNIT) ||
  3823. (vol.noOfVirtualUnits <= virtualUnitNo) )
  3824. {
  3825. vol.physicalUnits[unitNo]=FL_PRELIMINARY;
  3826. return flOK;
  3827. }
  3828. /* Save location of currently known newest unit of our chain */
  3829. lastUnitNo = vol.virtualUnits[virtualUnitNo];
  3830. /* If older unit is none existing then there is only one unit in this */
  3831. /* chain so lets not complicate things. */
  3832. if(prevUnitNo >= vol.noOfUnits)
  3833. {
  3834. if(lastUnitNo == ANAND_NO_UNIT )
  3835. {
  3836. /* First access to this unit therefore a one unit chain */
  3837. vol.virtualUnits[virtualUnitNo] = unitNo;
  3838. vol.physicalUnits[unitNo] = FL_VALID | FIRST_IN_CHAIN;
  3839. return flOK;
  3840. }
  3841. else
  3842. {
  3843. /* One unit chain that has 2 ends mark and deal later */
  3844. if(checkUnitHead(&vol,unitNo)!=flOK) /* Invalid header */
  3845. {
  3846. vol.physicalUnits[unitNo] = FL_PRELIMINARY;
  3847. return flOK;
  3848. }
  3849. else
  3850. {
  3851. if(checkUnitHead(&vol,lastUnitNo)!=flOK)
  3852. {
  3853. vol.physicalUnits[lastUnitNo] = FL_PRELIMINARY;
  3854. vol.virtualUnits[virtualUnitNo] = unitNo;
  3855. vol.physicalUnits[unitNo] = FL_VALID | FIRST_IN_CHAIN;
  3856. /* Might want to check rest of chain - but not neccesary */
  3857. return flOK;
  3858. }
  3859. }
  3860. vol.physicalUnits[unitNo] = FL_PRELIMINARY;
  3861. DEBUG_PRINT(("Debug: We have reached a unit twice while mounting.\r\n"));
  3862. return flOK;
  3863. }
  3864. }
  3865. /* We know that our unit points to a valid unit , now check if we */
  3866. /* already checked that older unit */
  3867. if((vol.physicalUnits[prevUnitNo] == FL_VALID)||
  3868. (vol.physicalUnits[prevUnitNo] == FL_FIRST_VALID))
  3869. {
  3870. if(lastUnitNo == prevUnitNo)
  3871. {
  3872. /* Our older unit is the head of the current chain. All we need */
  3873. /* to do is append our newer unit and mark it as the new head */
  3874. vol.physicalUnits[unitNo] = FL_VALID;
  3875. vol.virtualUnits[virtualUnitNo] = unitNo;
  3876. /* Might be nice to check for ANAC consistency */
  3877. return flOK;
  3878. }
  3879. else /* The previous unit is not the newest unit of our chain */
  3880. {
  3881. if(lastUnitNo == ANAND_NO_UNIT)
  3882. {
  3883. /* This is the first time we accessed this chain, but the */
  3884. /* unit indicated by the previous unit field is taken. We */
  3885. /* must assume that it no longer belongs to our chain. */
  3886. vol.virtualUnits[virtualUnitNo] = unitNo;
  3887. vol.physicalUnits[unitNo] = FL_VALID | FIRST_IN_CHAIN;
  3888. return flOK;
  3889. }
  3890. else /* Virtual chain already has a head - 2 ends of chain */
  3891. {
  3892. /* If we reached this point we have a problem - its bad. */
  3893. /* We were never visited, so we are'nt a part of a known chain. */
  3894. /* Our previous unit is used and was visited so: */
  3895. /* a) It belong to our chain - so why is it not it's head */
  3896. /* b) It does not belong to our chain - so it will not lead */
  3897. /* us to the rest of our chain which was already found. */
  3898. if(checkUnitHead(&vol,unitNo)!=flOK) /* Invalid header */
  3899. {
  3900. vol.physicalUnits[unitNo] = FL_PRELIMINARY;
  3901. return flOK;
  3902. }
  3903. else
  3904. {
  3905. if(checkUnitHead(&vol,lastUnitNo)!=flOK)
  3906. {
  3907. vol.physicalUnits[lastUnitNo] = FL_PRELIMINARY;
  3908. vol.virtualUnits[virtualUnitNo] = unitNo;
  3909. vol.physicalUnits[unitNo] = FL_VALID | FIRST_IN_CHAIN;
  3910. /* Might want to check rest of chain - but not neccesary */
  3911. return flOK;
  3912. }
  3913. }
  3914. vol.physicalUnits[unitNo] = FL_PRELIMINARY;
  3915. DEBUG_PRINT(("Debug: We have reached a unit twice while mounting.\r\n"));
  3916. return flOK;
  3917. }
  3918. }
  3919. }
  3920. /* If we reached this point , we have a valid older unit pointer */
  3921. /* and it points to a unit we did not mark as visited yet. We need */
  3922. /* to go along the chain and reconstruct it in the RAM tables. */
  3923. /* Save location of our unit and virtual unit number */
  3924. lastCurrent = unitNo;
  3925. origVirtualNo = virtualUnitNo;
  3926. /* Mark unit as Orphane until we shall verify the 2 ends connect */
  3927. vol.physicalUnits[unitNo] = FL_PRELIMINARY;
  3928. /************************************************************/
  3929. /* Go over the chain starting the unit previous to our unit */
  3930. /************************************************************/
  3931. while(1)
  3932. {
  3933. nextUnitNo = unitNo;
  3934. unitNo = prevUnitNo;
  3935. prevANAC = ANAC;
  3936. if(unitNo == ANAND_NO_UNIT)
  3937. break;
  3938. /* If already been to this unit */
  3939. if((vol.physicalUnits[unitNo] == FL_VALID)||
  3940. (vol.physicalUnits[unitNo] == FL_FIRST_VALID))
  3941. {
  3942. if(lastUnitNo == unitNo)
  3943. {
  3944. /* We have returned to the chains head , so the unit is valid */
  3945. /* Convert all the units we passed as valid and mark new head */
  3946. status = convertChain(&vol,lastCurrent,nextUnitNo,
  3947. origVirtualNo,FL_VALID);
  3948. vol.virtualUnits[origVirtualNo] = lastCurrent;
  3949. return flOK;
  3950. }
  3951. /* We have reached a unit that was already checked, but was not */
  3952. /* registeredour as the chains head. We can safely assume it does */
  3953. /* not belong to our virtual unit */
  3954. break;
  3955. }
  3956. /* Read unit header of our previous unit */
  3957. status = getUnitData(&vol,unitNo,&virtualUnitNo, &prevUnitNo,
  3958. &ANAC,&NAC,&parityPerField);
  3959. if(status != flOK)
  3960. return status;
  3961. if(badParityResult(parityPerField)) /* Bad unit header */
  3962. {
  3963. /* We can no longer follow the chain */
  3964. vol.physicalUnits[unitNo] = FL_PRELIMINARY; /* Delete later */
  3965. break;
  3966. }
  3967. /* Check if unit belongs to our chain */
  3968. if((virtualUnitNo != origVirtualNo ) || /* Correct virtual unit no */
  3969. (!consecutiveNumbers(prevANAC,ANAC)) ) /* ANAC is consecutive */
  3970. {
  3971. /* Note : none consecutive ANAC might still be connected to the end */
  3972. /* the chain , on the next time we will read it. */
  3973. break;
  3974. }
  3975. /* We have verified that unit belongs to our chain */
  3976. /* Mark unit as Orphane until we shall verify the 2 ends connect */
  3977. vol.physicalUnits[unitNo]=FL_PRELIMINARY;
  3978. }
  3979. /* Chain reached a unit pointing to an invalid unit. */
  3980. if(lastUnitNo == ANAND_NO_UNIT)
  3981. {
  3982. /* Chain did not have a head so mark it as a valid chain */
  3983. status = convertChain(&vol,lastCurrent,nextUnitNo,
  3984. origVirtualNo,FL_VALID);
  3985. vol.physicalUnits[nextUnitNo] = FL_VALID | FIRST_IN_CHAIN;
  3986. vol.virtualUnits[origVirtualNo] = lastCurrent;
  3987. }
  3988. else
  3989. {
  3990. /* Chain had a head. Check if previous head is valid. */
  3991. if(checkUnitHead(&vol,lastUnitNo)!=flOK) /* Invalid header */
  3992. {
  3993. /* The unit we found earlier was a result of power failure */
  3994. vol.physicalUnits[lastUnitNo] = FL_PRELIMINARY;
  3995. vol.virtualUnits[virtualUnitNo] = lastCurrent;
  3996. status = convertChain(&vol,lastCurrent,nextUnitNo,
  3997. origVirtualNo,FL_VALID);
  3998. vol.physicalUnits[nextUnitNo] = FL_VALID | FIRST_IN_CHAIN;
  3999. return status;
  4000. }
  4001. DEBUG_PRINT(("Debug: We have reached a unit twice while mounting.\r\n"));
  4002. status = convertChain(&vol,lastCurrent,nextUnitNo,
  4003. origVirtualNo,FL_PRELIMINARY);
  4004. }
  4005. return status;
  4006. }
  4007. #ifdef QUICK_MOUNT_FEATURE
  4008. /*----------------------------------------------------------------------*/
  4009. /* c h e c k Q u i c k M o u n t I n f o */
  4010. /* */
  4011. /* Read the quick mount information and verfiy its itegrity. */
  4012. /* */
  4013. /* Note : If the data is valid it will be read to the vol record and */
  4014. /* will mark the current data as invalid. */
  4015. /* */
  4016. /* Note : checksum will be added in future versions. */
  4017. /* */
  4018. /* Parameters: */
  4019. /* vol : Pointer identifying drive */
  4020. /* */
  4021. /* Returns: TRUE if data is valid otherwise FALSE. */
  4022. /*----------------------------------------------------------------------*/
  4023. static FLBoolean checkQuickMountInfo(Bnand vol)
  4024. {
  4025. byte start; /* The first goot unit of the quick mount data */
  4026. FLStatus status;
  4027. savedBnand *newVol;
  4028. DEBUG_PRINT(("Debug: trying to read quick mount information.\r\n"));
  4029. status = quickMountData(&vol, TRUE,&start);
  4030. if (status==flOK)
  4031. {
  4032. status = vol.flash->read(vol.flash,(((CardAddress)(vol.firstQuickMountUnit
  4033. +start))<< vol.unitSizeBits),inftlBuffer, sizeof(inftlBuffer),EDC);
  4034. if (status == flOK)
  4035. {
  4036. /* Convert the dword fields to the internal volume */
  4037. newVol = (savedBnand *) inftlBuffer;
  4038. if (LE4(newVol->validate) == QUICK_MOUNT_VALID_SIGN)
  4039. {
  4040. vol.freeUnits = (ANANDUnitNo)LE4(newVol->freeUnits );
  4041. vol.roverUnit = (ANANDUnitNo)LE4(newVol->roverUnit );
  4042. vol.countsValid = (ANANDUnitNo)LE4(newVol->countsValid );
  4043. vol.sectorsRead = LE4(newVol->sectorsRead );
  4044. vol.sectorsWritten = LE4(newVol->sectorsWritten);
  4045. vol.sectorsDeleted = LE4(newVol->sectorsDeleted);
  4046. vol.parasiteWrites = LE4(newVol->parasiteWrites);
  4047. vol.unitsFolded = LE4(newVol->unitsFolded );
  4048. vol.wearLevel.alarm = (word)LE4(newVol->wearLevel_1 );
  4049. vol.wearLevel.currUnit = (ANANDUnitNo)LE4(newVol->wearLevel_2 );
  4050. vol.eraseSum = LE4(newVol->eraseSum );
  4051. #if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
  4052. vol.verifiedSectorNo = LE4(newVol->verifiedSectorNo);
  4053. #endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
  4054. DEBUG_PRINT(("Debug: quick mount information was successfuly restored.\r\n"));
  4055. return TRUE;
  4056. }
  4057. }
  4058. }
  4059. DEBUG_PRINT(("Debug: Error getting quick mount information.\r\n"));
  4060. return FALSE;
  4061. }
  4062. #endif /* QUICK_MOUNT_FEATURE */
  4063. #ifdef NFTL_CACHE
  4064. /*----------------------------------------------------------------------*/
  4065. /* i n i t C a t c h */
  4066. /* */
  4067. /* Initialize and allocate the unit and sector catche. */
  4068. /* */
  4069. /* Note - need to add check for not enough static memory. */
  4070. /* */
  4071. /* Parameters: */
  4072. /* vol : Pointer identifying drive */
  4073. /* ramForCache : Cache offset of previous volumes on device */
  4074. /* */
  4075. /* Returns: */
  4076. /*----------------------------------------------------------------------*/
  4077. #ifndef FL_MALLOC
  4078. void initCatch(Bnand vol, dword ramForCache)
  4079. #else
  4080. void initCatch(Bnand vol)
  4081. #endif /* FL_MALLOC */
  4082. {
  4083. dword scacheSize = 0; /* Initialized to remove warrnings */
  4084. dword iUnit;
  4085. /* create and initialize ANANDUnitHeader cache */
  4086. #ifdef ENVIRONMENT_VARS
  4087. if( flUseNFTLCache == 1 ) /* behave according to the value of env variable */
  4088. #endif
  4089. {
  4090. #ifdef FL_MALLOC
  4091. vol.ucache = (ucacheEntry FAR1*) FL_FAR_MALLOC(vol.noOfUnits * sizeof(ucacheEntry));
  4092. #else
  4093. vol.ucache = &socketUcache[flSocketNoOf(vol.flash->socket)][ramForCache];
  4094. #endif /* FL_MALLOC */
  4095. }
  4096. #ifdef ENVIRONMENT_VARS
  4097. else
  4098. {
  4099. vol.ucache = NULL;
  4100. }
  4101. #endif /* ENVIRONMENT_VARS */
  4102. if (vol.ucache != NULL)
  4103. {
  4104. for (iUnit = 0; iUnit < vol.noOfUnits; iUnit++)
  4105. {
  4106. vol.ucache[iUnit].virtualUnitNo = 0xDEAD;
  4107. vol.ucache[iUnit].prevUnitNo = 0xDEAD;
  4108. }
  4109. }
  4110. else
  4111. {
  4112. DEBUG_PRINT(("Debug: INFTL runs without U-cache\r\n"));
  4113. }
  4114. /* create and initialize SectorFlags cache */
  4115. #ifdef ENVIRONMENT_VARS
  4116. if( flUseNFTLCache == 1 ) /* behave according to the value of env variable */
  4117. #endif /* ENVIRONMENT_VARS */
  4118. {
  4119. scacheSize = (dword)vol.noOfUnits << (vol.unitSizeBits - SECTOR_SIZE_BITS - 2);
  4120. #ifdef FL_MALLOC
  4121. if( (sizeof(unsigned) < sizeof(scacheSize)) &&
  4122. (scacheSize >= 0x10000L) ) /* Out of Segment Boundary */
  4123. {
  4124. vol.scache = NULL;
  4125. }
  4126. else
  4127. {
  4128. vol.scache = (byte FAR1*) FL_FAR_MALLOC(scacheSize);
  4129. }
  4130. #else
  4131. vol.scache = &socketScache[flSocketNoOf(vol.flash->socket)][ramForCache << (vol.unitSizeBits - SECTOR_SIZE_BITS - 2)];
  4132. #endif /* FL_MALLOC */
  4133. }
  4134. #ifdef ENVIRONMENT_VARS
  4135. else
  4136. {
  4137. vol.scache = NULL;
  4138. }
  4139. #endif /* ENVIRONMENT_VARS */
  4140. if (vol.scache != NULL)
  4141. {
  4142. /*
  4143. * Whenever SECTOR_IGNORE is found in Sector Flags cache it is double
  4144. * checked by reading actual sector flags from flash-> This is way
  4145. * all the cache entries are initially set to SECTOR_IGNORE.
  4146. */
  4147. byte val = (S_CACHE_SECTOR_IGNORE << 6) | (S_CACHE_SECTOR_IGNORE << 4) |
  4148. (S_CACHE_SECTOR_IGNORE << 2) | S_CACHE_SECTOR_IGNORE;
  4149. dword iC;
  4150. for(iC=0;( iC < scacheSize );iC++)
  4151. vol.scache[iC] = val;
  4152. }
  4153. else
  4154. {
  4155. DEBUG_PRINT(("Debug: INFTL runs without S-cache\r\n"));
  4156. }
  4157. }
  4158. #endif /* NFTL_CACHE */
  4159. /*----------------------------------------------------------------------*/
  4160. /* m o u n t I N F T L */
  4161. /* */
  4162. /* Mount the volume. Initialize data structures and conversion tables */
  4163. /* */
  4164. /* Parameters: */
  4165. /* volNo : Volume serial no. */
  4166. /* tl : Mounted translation layer on exit */
  4167. /* flash : Flash media mounted on this socket */
  4168. /* volForCallback : Pointer to FLFlash structure for power on */
  4169. /* callback routine. */
  4170. /* */
  4171. /* Returns: */
  4172. /* FLStatus : 0 on success, failed otherwise */
  4173. /*----------------------------------------------------------------------*/
  4174. static FLStatus mountINFTL(unsigned volNo, TL *tl, FLFlash *flash, FLFlash **volForCallback)
  4175. {
  4176. Bnand vol = &vols[volNo];
  4177. ANANDUnitNo iUnit;
  4178. ANANDUnitNo originalUnits[MAX_NO_OF_FLOORS];
  4179. BNANDBootRecord * mediaHeader; /* Disk header record */
  4180. BNANDVolumeHeaderRecord * volumeHeader; /* volume header record */
  4181. FLStatus status;
  4182. byte index;
  4183. #ifndef FL_MALLOC
  4184. dword ramForUnits=0;
  4185. #ifdef NFTL_CACHE
  4186. dword ramForCache=0;
  4187. #endif /* NFTL_CACHE */
  4188. #endif /* FL_MALLOC */
  4189. #ifdef EXTRA_LARGE
  4190. word moreUnitBits;
  4191. #endif /* EXTRA_LARGE */
  4192. #ifdef CHAINS_DEBUG
  4193. FILE * out;
  4194. #endif /* CHAINS_DEBUG */
  4195. DEBUG_PRINT(("Debug: starting INFTL mount.\r\n"));
  4196. /*************************/
  4197. /* Find the media header */
  4198. /*************************/
  4199. tffsset(&vol,0,sizeof(vol));
  4200. status = initINFTL(&vol,flash);
  4201. if(status == flOK)
  4202. status = retrieveHeader(&vol,originalUnits,FALSE,TRUE);
  4203. if(status != flOK)
  4204. return status;
  4205. mediaHeader = (BNANDBootRecord *)inftlBuffer;
  4206. if (tl->partitionNo >= LE4(mediaHeader->noOfBDTLPartitions))
  4207. {
  4208. DEBUG_PRINT(("Debug: wrong partition number.\r\n"));
  4209. return flBadDriveHandle;
  4210. }
  4211. *volForCallback = vol.flash;
  4212. vol.eraseSum = 0;
  4213. /* Get media information from unit header */
  4214. volumeHeader = (BNANDVolumeHeaderRecord *)(inftlBuffer +
  4215. sizeof(BNANDBootRecord) +
  4216. (word)((LE4(mediaHeader->noOfBinaryPartitions) *
  4217. sizeof(BNANDVolumeHeaderRecord))));
  4218. vol.bootUnits = (ANANDUnitNo)LE4(volumeHeader->firstQuickMountUnit);
  4219. #ifndef FL_MALLOC
  4220. /* calculate the memory offset for static allocation */
  4221. for (index = tl->partitionNo;index>0;index--,volumeHeader++)
  4222. {
  4223. ramForUnits += LE4(volumeHeader->virtualUnits) * sizeof(ANANDUnitNo); /* virtual size */
  4224. iUnit = (word)(LE4(volumeHeader->lastUnit) - LE4(volumeHeader->firstUnit) + 1);
  4225. ramForUnits += iUnit * sizeof(ANANDPhysUnit);
  4226. #ifdef NFTL_CACHE
  4227. ramForCache += iUnit;
  4228. #endif /* NFTL_CACHE */
  4229. }
  4230. #else
  4231. volumeHeader += tl->partitionNo;
  4232. #endif /* FL_MALLOC */
  4233. vol.noOfVirtualUnits = (ANANDUnitNo)LE4(volumeHeader->virtualUnits);
  4234. vol.flags = (byte)LE4(mediaHeader->formatFlags);
  4235. vol.firstQuickMountUnit = (ANANDUnitNo)LE4(volumeHeader->firstQuickMountUnit);
  4236. vol.firstUnit =(ANANDUnitNo) LE4(volumeHeader->firstUnit);
  4237. #ifdef NFTL_CACHE
  4238. vol.firstUnitAddress = (dword)vol.firstUnit << vol.unitSizeBits;
  4239. #endif /* NFTL_CACHE */
  4240. vol.virtualSectors = (SectorNo)((LE4(volumeHeader->virtualUnits)<<
  4241. vol.unitSizeBits) >> SECTOR_SIZE_BITS);
  4242. vol.noOfUnits = (ANANDUnitNo)(LE4(volumeHeader->lastUnit) -
  4243. LE4(volumeHeader->firstUnit) + 1);
  4244. /* Validy check */
  4245. if((ANANDUnitNo)(vol.noOfVirtualUnits > vol.noOfUnits))
  4246. {
  4247. DEBUG_PRINT(("Reported no of virtual unit is larger then no of physical units\r\n"));
  4248. return flBadFormat;
  4249. }
  4250. #ifdef FL_MALLOC
  4251. status = initTables(&vol);
  4252. #else
  4253. status = initTables(&vol,ramForUnits);
  4254. #endif /* MALLOCK */
  4255. if(status != flOK)
  4256. return status;
  4257. #ifdef NFTL_CACHE
  4258. #ifndef FL_MALLOC
  4259. initCatch(&vol, ramForCache);
  4260. #else
  4261. initCatch(&vol);
  4262. #endif /* FL_MALLOC */
  4263. #endif /* NFTL_CACHE */
  4264. #if (defined(VERIFY_WRITE) || defined(VERIFY_ERASED_SECTOR))
  4265. /* Default for INFTL is FL_OFF */
  4266. flVerifyWrite[vol.socketNo][tl->partitionNo] = FL_OFF;
  4267. #endif /* VERIFY_WRITE || VERIFY_ERASED_SECTOR */
  4268. /******************************************/
  4269. /* Try mounting from the quick mount data */
  4270. /******************************************/
  4271. #ifdef QUICK_MOUNT_FEATURE
  4272. #if (!defined(RAM_MTD) && !defined(CHECK_MOUNT))
  4273. if (((LE4(mediaHeader->formatFlags) & QUICK_MOUNT) == 0) ||
  4274. ( checkQuickMountInfo(&vol) == FALSE ) )
  4275. #endif /* not RAM_MTD && not CHECK_MOUNT */
  4276. #endif /* QUICK_MOUNT_FORMAT */
  4277. {
  4278. vol.firstMediaWrite = TRUE; /* Force writing quick mount information */
  4279. /***************************************/
  4280. /* Read BBT to internal representation */
  4281. /***************************************/
  4282. status = flash->readBBT(vol.flash,vol.firstUnit,
  4283. vol.noOfUnits,vol.blockMultiplierBits, vol.physicalUnits,FALSE);
  4284. if( status != flOK )
  4285. {
  4286. DEBUG_PRINT(("Debug: Error reading BBT.\r\n"));
  4287. dismountINFTL(&vol); /* Free tables must be done after call to initTables */
  4288. return status;
  4289. }
  4290. /* Translate bad unit table to internal representation */
  4291. for (iUnit = 0; iUnit < vol.noOfUnits; iUnit++)
  4292. {
  4293. if (vol.physicalUnits[iUnit] != BBT_GOOD_UNIT)
  4294. {
  4295. vol.physicalUnits[iUnit] = UNIT_BAD;
  4296. }
  4297. else
  4298. {
  4299. vol.physicalUnits[iUnit] = ANAND_UNIT_FREE;
  4300. }
  4301. }
  4302. /* Translate original units to bad blocks */
  4303. for (index=0;index < vol.flash->noOfFloors;index++)
  4304. {
  4305. iUnit = originalUnits[index]-vol.firstUnit;
  4306. if ((iUnit < vol.noOfUnits) && (originalUnits[index] > vol.firstUnit))
  4307. vol.physicalUnits[iUnit] = UNIT_BAD;
  4308. }
  4309. /*************************/
  4310. /* Mount the unit chains */
  4311. /*************************/
  4312. /* Initialize virutal units table */
  4313. for (iUnit = 0; iUnit < vol.noOfVirtualUnits; iUnit++)
  4314. vol.virtualUnits[iUnit] = ANAND_NO_UNIT;
  4315. #ifdef CHECK_MOUNT
  4316. status = checkMountINFTL(&vol);
  4317. if (status != flOK)
  4318. {
  4319. TL_DEBUG_PRINT(tl_out,"Failed check Mount routine with status %d\n",status);
  4320. SET_EXIT(INFTL_FAILED_MOUNT);
  4321. }
  4322. #endif /* CHECK_MOUNT */
  4323. for (iUnit = 0; iUnit < vol.noOfUnits; iUnit++)
  4324. {
  4325. if (vol.physicalUnits[iUnit] != UNIT_BAD)
  4326. {
  4327. status = goAlongChain(&vol,iUnit);
  4328. if(status != flOK)
  4329. {
  4330. DEBUG_PRINT(("Debug: Error going along INFTL chains.\r\n"));
  4331. dismountINFTL(&vol); /*Free tables must be done after call to initTables*/
  4332. return status;
  4333. }
  4334. }
  4335. }
  4336. #ifdef CHAINS_DEBUG
  4337. out = getFileHandle(&vol,0);
  4338. if (out == NULL)
  4339. {
  4340. if (DID_MOUNT_FAIL)
  4341. DEBUG_PRINT(("Debug: Can not open debug file.\r\n"));
  4342. }
  4343. else
  4344. {
  4345. checkVirtualChains(&vol,out);
  4346. }
  4347. #endif /* CHAINS_DEBUG */
  4348. vol.freeUnits = 0;
  4349. for (iUnit = 0; iUnit < vol.noOfUnits; iUnit++)
  4350. {
  4351. switch( vol.physicalUnits[iUnit] )
  4352. {
  4353. case ANAND_UNIT_FREE:
  4354. vol.freeUnits++;
  4355. break;
  4356. case FL_FIRST_VALID: /* Mark as first in chain */
  4357. case FL_VALID:
  4358. vol.physicalUnits[iUnit] &= FIRST_IN_CHAIN;
  4359. break;
  4360. case FL_FIRST_PRELIMINARY: /* Vadim :erase this unit*/
  4361. case FL_PRELIMINARY:
  4362. DEBUG_PRINT(("Orphan unit found\r\n"));
  4363. TL_DEBUG_PRINT(tl_out,"Orphan units found , unit no %d\n",iUnit);
  4364. SET_EXIT(INFTL_FAILED_MOUNT);
  4365. #ifndef FL_READ_ONLY
  4366. if( eraseOrphanUnit(&vol,iUnit) == flOK)
  4367. {
  4368. vol.physicalUnits[iUnit] = ANAND_UNIT_FREE;
  4369. vol.freeUnits++;
  4370. }
  4371. break;
  4372. #else
  4373. #ifndef CHECK_MOUNT
  4374. dismountINFTL(&vol); /*Free tables must be done after call to initTables*/
  4375. return flWriteFault;
  4376. #endif /* CHECK_MOUNT */
  4377. #endif /* FL_READ_ONLY */
  4378. default: /* nothing here */
  4379. break;
  4380. }
  4381. }
  4382. /* Initialize allocation rover */
  4383. vol.roverUnit = 0;
  4384. /* Initialize statistics */
  4385. vol.sectorsRead = vol.sectorsWritten = vol.sectorsDeleted = 0;
  4386. vol.parasiteWrites = vol.unitsFolded = 0;
  4387. vol.wearLevel.alarm = (word)(vol.eraseSum % WLnow);
  4388. vol.wearLevel.currUnit = (ANANDUnitNo)(vol.eraseSum % vol.noOfVirtualUnits);
  4389. } /* end quick mounted succesful if */
  4390. #ifdef CHAINS_DEBUG
  4391. if (out != NULL)
  4392. {
  4393. checkVolumeStatistics(&vol,out);
  4394. }
  4395. #endif /* CHAINS_DEBUG */
  4396. #ifdef CHECK_MOUNT
  4397. dismountINFTL(&vol); /*Free tables must be done after call to initTables*/
  4398. if(vol.debugState & INFTL_FAILED_MOUNT)
  4399. {
  4400. TL_DEBUG_PRINT(tl_out,"Test failed\n\n");
  4401. fclose(tl_out);
  4402. exit(EXIT_FAILURE);
  4403. }
  4404. else
  4405. {
  4406. TL_DEBUG_PRINT(tl_out,"Test success\n\n");
  4407. exit(EXIT_SUCCESS);
  4408. }
  4409. #endif /* CHECK_MOUNT */
  4410. #ifndef FL_READ_ONLY
  4411. /* Make sure there are at least 2 free units */
  4412. if(vol.freeUnits == 0)
  4413. {
  4414. status = foldBestChain(&vol,&iUnit);
  4415. switch(status)
  4416. {
  4417. case flNotEnoughMemory:
  4418. DEBUG_PRINT(("Debug: Not enough free units. Media is read only.\r\n"));
  4419. case flOK:
  4420. break;
  4421. default:
  4422. return status;
  4423. }
  4424. }
  4425. tl->writeSector = writeSector;
  4426. tl->deleteSector = deleteSector;
  4427. tl->writeMultiSector = writeMultiSector;
  4428. #ifdef DEFRAGMENT_VOLUME
  4429. tl->defragment = defragment;
  4430. #endif /* DEFRAGMENT */
  4431. #if (defined(VERIFY_WRITE) || defined (VERIFY_VOLUME) || defined(VERIFY_ERASED_SECTOR))
  4432. tl->checkVolume = checkVolume;
  4433. #endif /* VERIFY_WRITE || VERIFY_VOLUME || VERIFY_ERASED_SECTOR */
  4434. #else /* FL_READ_ONLY */
  4435. tl->writeSector = NULL;
  4436. tl->deleteSector = NULL;
  4437. tl->writeMultiSector = NULL;
  4438. #ifdef DEFRAGMENT_VOLUME
  4439. tl->defragment = NULL;
  4440. #endif /* DEFRAGMENT */
  4441. #if (defined(VERIFY_WRITE) || defined (VERIFY_VOLUME) || defined(VERIFY_ERASED_SECTOR))
  4442. tl->checkVolume = NULL;
  4443. #endif /* VERIFY_WRITE || VERIFY_VOLUME || VERIFY_ERASED_SECTOR */
  4444. #endif /* FL_READ_ONLY */
  4445. tl->rec = &vol;
  4446. tl->mapSector = mapSector;
  4447. tl->sectorsInVolume = sectorsInVolume;
  4448. tl->getTLInfo = INFTLInfo;
  4449. tl->tlSetBusy = tlSetBusy;
  4450. tl->dismount = dismountINFTL;
  4451. tl->readSectors = readSectors;
  4452. #ifndef NO_READ_BBT_CODE
  4453. tl->readBBT = readBBT;
  4454. #endif
  4455. DEBUG_PRINT(("Debug: finished INFTL mount.\r\n"));
  4456. return flOK;
  4457. }
  4458. #ifdef HW_PROTECTION
  4459. /*----------------------------------------------------------------------*/
  4460. /* p r o t e c t i o n I N F T L */
  4461. /* */
  4462. /* Common entry point to all protection routines. */
  4463. /* */
  4464. /* Parameters: */
  4465. /* vol : Pointer identifying drive */
  4466. /* volume : Pointer to partition record of the media header */
  4467. /* */
  4468. /* Returns: */
  4469. /* FLStatus : 0 on success, otherwise failure */
  4470. /* */
  4471. /*----------------------------------------------------------------------*/
  4472. static FLStatus protectionINFTL(Bnand vol,BNANDVolumeHeaderRecord* volume,
  4473. IOreq FAR2* ioreq , FLFunctionNo callType)
  4474. {
  4475. FLFlash * flash = vol.flash;
  4476. FLStatus status;
  4477. #ifndef FL_READ_ONLY
  4478. CardAddress low;
  4479. CardAddress high;
  4480. byte floorNo;
  4481. #endif /* FL_READ_ONLY */
  4482. byte tempFlags = 0; /* Initialized to remove warrnings */
  4483. byte area;
  4484. word returnedFlags;
  4485. /* Save protection area since "volume" is overwritten by protectionSet */
  4486. area = (byte)LE4(volume->protectionArea); /* Protection area */
  4487. if ((LE4(volume->flags) & PROTECTABLE) == 0)
  4488. return flNotProtected;
  4489. /* Routine that need to get the partition type before executing */
  4490. if ((callType != FL_PROTECTION_INSERT_KEY) &&
  4491. (callType != FL_PROTECTION_REMOVE_KEY))
  4492. {
  4493. tempFlags = (byte)ioreq->irFlags;
  4494. if (flash->protectionType == NULL)
  4495. return flFeatureNotSupported;
  4496. status = flash->protectionType(flash,area,&returnedFlags);
  4497. ioreq->irFlags = (unsigned)returnedFlags;
  4498. if (status != flOK)
  4499. return status;
  4500. /* Routines that need to change the protection attributes */
  4501. #ifndef FL_READ_ONLY
  4502. if (callType!=FL_PROTECTION_GET_TYPE)
  4503. {
  4504. if((returnedFlags & KEY_INSERTED) == 0) /* Make sure the key is inserted */
  4505. {
  4506. DEBUG_PRINT(("Please insert key before trying to change protection attributes\r\n"));
  4507. return flHWProtection;
  4508. }
  4509. if ((flash->protectionBoundries == NULL ) ||
  4510. (flash->protectionSet == NULL ) ||
  4511. (flash->protectionKeyInsert == NULL ))
  4512. {
  4513. DEBUG_PRINT(("Protection routine are NULL\r\n"));
  4514. return flFeatureNotSupported;
  4515. }
  4516. if (!(LE4(volume->flags) & CHANGEABLE_PROTECTION))
  4517. return flUnchangeableProtection;
  4518. /* The DPS of unprotected partitions is protected by a default key */
  4519. flash->protectionKeyInsert(flash,area,(byte *)DEFAULT_KEY);
  4520. }
  4521. #endif /* FL_READ_ONLY */
  4522. } /* End of protection change routine */
  4523. /* Execute each of the posible protection routines */
  4524. switch (callType)
  4525. {
  4526. case FL_PROTECTION_GET_TYPE:
  4527. ioreq->irFlags |= PROTECTABLE;
  4528. if (LE4(volume->flags) & CHANGEABLE_PROTECTION)
  4529. {
  4530. if ((ioreq->irFlags & CHANGEABLE_PROTECTION)==0)
  4531. {
  4532. DEBUG_PRINT(("Debug: INFTL reported CHANGEALE protection, but MTD does not allow it.\r\n"));
  4533. return flBadFormat;
  4534. }
  4535. }
  4536. else
  4537. {
  4538. ioreq->irFlags &= (~CHANGEABLE_PROTECTION);
  4539. }
  4540. break;
  4541. #ifndef FL_READ_ONLY
  4542. case FL_PROTECTION_SET_LOCK:
  4543. if (tempFlags & LOCK_ENABLED)
  4544. {
  4545. ioreq->irFlags |= LOCK_ENABLED;
  4546. }
  4547. else
  4548. {
  4549. ioreq->irFlags &=~LOCK_ENABLED;
  4550. }
  4551. for (floorNo = 0 ; floorNo < flash->noOfFloors ; floorNo++)
  4552. {
  4553. /* Find boundries */
  4554. status = flash->protectionBoundries(flash,
  4555. area,&low,&high,floorNo);
  4556. if(status == flOK) /* Set new protection values */
  4557. {
  4558. status = flash->protectionSet(flash,area,
  4559. (word)((high == 0) ? PROTECTABLE : ioreq->irFlags),
  4560. low,high,NULL,
  4561. (byte)((floorNo == flash->noOfFloors - 1) ?
  4562. COMMIT_PROTECTION : DO_NOT_COMMIT_PROTECTION),floorNo);
  4563. }
  4564. if(status != flOK)
  4565. return status;
  4566. }
  4567. break;
  4568. case FL_PROTECTION_CHANGE_KEY:
  4569. for (floorNo = 0 ; floorNo < flash->noOfFloors ; floorNo++)
  4570. {
  4571. /* Find boundries */
  4572. status = flash->protectionBoundries(flash,area,
  4573. &low,&high,floorNo);
  4574. if(status == flOK) /* Set new protection values */
  4575. {
  4576. status = flash->protectionSet(flash,area,
  4577. (word)((high == 0) ? PROTECTABLE : ioreq->irFlags),
  4578. low,high,(byte FAR1*)ioreq->irData,
  4579. (byte)((floorNo == flash->noOfFloors - 1) ?
  4580. COMMIT_PROTECTION : DO_NOT_COMMIT_PROTECTION),floorNo);
  4581. }
  4582. if(status != flOK)
  4583. return status;
  4584. }
  4585. break;
  4586. case FL_PROTECTION_CHANGE_TYPE:
  4587. /* Only read and or write protected types are available */
  4588. if (((tempFlags & (READ_PROTECTED | WRITE_PROTECTED |
  4589. PROTECTABLE)) != tempFlags) ||
  4590. ((tempFlags & PROTECTABLE) == 0))
  4591. return flBadParameter;
  4592. for (floorNo = 0 ; floorNo < flash->noOfFloors ; floorNo++)
  4593. {
  4594. /* Find boundries */
  4595. status = flash->protectionBoundries(flash,area,
  4596. &low,&high,floorNo);
  4597. if(status == flOK) /* Set new protection values */
  4598. {
  4599. status = flash->protectionSet(flash,area,
  4600. (word)((high == 0) ? PROTECTABLE : tempFlags),
  4601. low,high,NULL,(byte)((floorNo == flash->noOfFloors - 1)
  4602. ? COMMIT_PROTECTION : DO_NOT_COMMIT_PROTECTION),floorNo);
  4603. }
  4604. if(status != flOK)
  4605. return status;
  4606. }
  4607. break;
  4608. #endif /* FL_READ_ONLY */
  4609. case FL_PROTECTION_REMOVE_KEY:
  4610. if (flash->protectionKeyRemove == NULL)
  4611. {
  4612. DEBUG_PRINT(("Protection routine is NULL\r\n"));
  4613. return flFeatureNotSupported;
  4614. }
  4615. return flash->protectionKeyRemove(flash,area);
  4616. case FL_PROTECTION_INSERT_KEY:
  4617. if (flash->protectionKeyInsert == NULL)
  4618. {
  4619. DEBUG_PRINT(("Protection routine is NULL\r\n"));
  4620. return flFeatureNotSupported;
  4621. }
  4622. return flash->protectionKeyInsert(flash,area,(byte FAR1*)ioreq->irData);
  4623. default:
  4624. break;
  4625. } /* protection routines */
  4626. return flOK;
  4627. }
  4628. #endif /* HW_PROTECTION */
  4629. /*----------------------------------------------------------------------*/
  4630. /* p r e M o u n t I N F T L */
  4631. /* */
  4632. /* Common entry point to all tl routines that may be perfomed before */
  4633. /* the volume is mounted (except for the format routine */
  4634. /* */
  4635. /* Parameters: */
  4636. /* callType : Enum type of posible routines */
  4637. /* ioreq : Input and output request packet */
  4638. /* flash : Flash media mounted on this socket */
  4639. /* */
  4640. /* Returns: */
  4641. /* FLStatus : 0 on success, otherwise failure */
  4642. /* */
  4643. /*----------------------------------------------------------------------*/
  4644. static FLStatus preMountINFTL(FLFunctionNo callType, IOreq FAR2* ioreq ,FLFlash* flash, FLStatus* status)
  4645. {
  4646. BNANDVolumeHeaderRecord* volume;
  4647. ANANDUnitNo originalUnits[MAX_NO_OF_FLOORS];
  4648. Bnand vol = vols + FL_GET_SOCKET_FROM_HANDLE(ioreq);
  4649. byte partition = FL_GET_PARTITION_FROM_HANDLE(ioreq);
  4650. FLStatus tmpStatus;
  4651. DEBUG_PRINT(("Debug: starting INFTL preMount operation.\r\n"));
  4652. /*************************/
  4653. /* Find the media header */
  4654. /*************************/
  4655. tmpStatus = initINFTLbasic(&vol,flash);
  4656. if(tmpStatus == flOK)
  4657. tmpStatus = retrieveHeader(&vol,originalUnits,FALSE,TRUE);
  4658. if(tmpStatus != flOK)
  4659. return tmpStatus;
  4660. *status = flOK;
  4661. if (callType == FL_COUNT_VOLUMES) /* get number of BDTL volumes routine */
  4662. {
  4663. ioreq->irFlags = (byte)LE4(((BNANDBootRecord *)inftlBuffer)->
  4664. noOfBDTLPartitions);
  4665. return flOK;
  4666. }
  4667. /* Check media header for the specific partition */
  4668. volume = (BNANDVolumeHeaderRecord*)(inftlBuffer + sizeof(BNANDBootRecord));
  4669. if (partition > LE4(((BNANDBootRecord *)inftlBuffer)->noOfBDTLPartitions))
  4670. {
  4671. *status = flBadDriveHandle;
  4672. }
  4673. else
  4674. {
  4675. volume += (LE4(((BNANDBootRecord *)inftlBuffer)->noOfBinaryPartitions)+
  4676. partition);
  4677. }
  4678. switch (callType)
  4679. {
  4680. #if (defined(QUICK_MOUNT_FEATURE) && !defined(FL_READ_ONLY))
  4681. case FL_CLEAR_QUICK_MOUNT_INFO:
  4682. if(*status != flBadDriveHandle) /* Valid partition number */
  4683. *status = flash->erase(flash,
  4684. (word)(LE4(volume->firstQuickMountUnit) << vol.blockMultiplierBits),
  4685. (word)((LE4(volume->firstUnit) - LE4(volume->firstQuickMountUnit))
  4686. << vol.blockMultiplierBits));
  4687. break;
  4688. #endif /* QUICK_MOUNT_FEATURE AND NOT FL_READ_ONLY */
  4689. #ifdef HW_PROTECTION
  4690. case FL_PROTECTION_GET_TYPE: /* Protection routines */
  4691. case FL_PROTECTION_SET_LOCK:
  4692. case FL_PROTECTION_CHANGE_KEY:
  4693. case FL_PROTECTION_CHANGE_TYPE:
  4694. case FL_PROTECTION_INSERT_KEY:
  4695. case FL_PROTECTION_REMOVE_KEY:
  4696. if(*status == flBadDriveHandle) /* Valid partition number */
  4697. break;
  4698. *status = protectionINFTL(&vol,volume,ioreq,callType);
  4699. break;
  4700. #endif /* HW_PROTECTION */
  4701. default: /* not supported pre mount routine */
  4702. return flBadParameter;
  4703. } /* end of callType switch */
  4704. return flOK; /* This TL took responsibility of this call */
  4705. }
  4706. #if (defined(FORMAT_VOLUME) && !defined(FL_READ_ONLY))
  4707. /*----------------------------------------------------------------------*/
  4708. /* e r a s e U n i t */
  4709. /* */
  4710. /* Erase the unit while retaining the erase count. */
  4711. /* */
  4712. /* Parameters: */
  4713. /* vol : Pointer identifying drive */
  4714. /* unitNo : Physical unit to format */
  4715. /* */
  4716. /* the progress is repored by the progressCallBack routine */
  4717. /* */
  4718. /* Returns: */
  4719. /* FLStatus : 0 on success, failed otherwise */
  4720. /*----------------------------------------------------------------------*/
  4721. static FLStatus eraseUnit(Bnand vol, ANANDUnitNo unitNo,
  4722. FLProgressCallback progressCallback)
  4723. {
  4724. word eraseMark;
  4725. dword eraseCount;
  4726. FLStatus status;
  4727. if (progressCallback)
  4728. {
  4729. status = (*progressCallback)((word)(vol.flash->noOfChips *
  4730. (vol.flash->chipSize >> vol.unitSizeBits)),(word)(unitNo+1));
  4731. if(status != flOK)
  4732. {
  4733. DFORMAT_PRINT(("Debug: ERROR failed reporting progress callback.\r\n"));
  4734. dismountINFTL(&vol); /*Free tables must be done after call to initTables*/
  4735. return status;
  4736. }
  4737. }
  4738. status = getUnitTailer(&vol,unitNo,&eraseMark,&eraseCount,UNIT_TAILER_OFFSET);
  4739. if(status == flOK)
  4740. {
  4741. status = vol.flash->erase(vol.flash,(word)(unitNo << vol.blockMultiplierBits),
  4742. (word)(1 << vol.blockMultiplierBits));
  4743. }
  4744. if (status == flOK)
  4745. {
  4746. eraseCount++;
  4747. if (eraseCount == 0) /* was hex FF's */
  4748. eraseCount++;
  4749. status = setUnitTailer(&vol,unitNo,ERASE_MARK,eraseCount,UNIT_TAILER_OFFSET);
  4750. }
  4751. if (status != flOK)
  4752. {
  4753. DEBUG_PRINT(("Debug: ERROR failed formating unit.\r\n"));
  4754. markUnitBad(&vol,unitNo); /* make sure unit format is not valid */
  4755. dismountINFTL(&vol); /*Free tables must be done after call to initTables*/
  4756. }
  4757. return status;
  4758. }
  4759. /*----------------------------------------------------------------------*/
  4760. /* f o r m a t I N F T L */
  4761. /* */
  4762. /* Perform INFTL Format. */
  4763. /* */
  4764. /* Parameters: */
  4765. /* volNo : Volume serial no. */
  4766. /* fp : Address of FormatParams structure to use */
  4767. /* flash : Flash media mounted on this socket */
  4768. /* */
  4769. /* Returns: */
  4770. /* FLStatus : 0 on success, failed otherwise */
  4771. /*----------------------------------------------------------------------*/
  4772. static FLStatus formatINFTL(unsigned volNo, TLFormatParams *fp, FLFlash *flash)
  4773. {
  4774. Bnand vol = &vols[volNo]; /* TL record */
  4775. BDTLPartitionFormatParams FAR2* bdtl = fp->BDTLPartitionInfo; /* bdtl input */
  4776. BinaryPartitionFormatParams FAR2* binary = fp->binaryPartitionInfo; /* binary input */
  4777. BNANDBootRecord * mediaHeader; /* Disk header record */
  4778. BNANDVolumeHeaderRecord * volumeHeader; /* volume header record */
  4779. BNANDVolumeHeaderRecord * volumeHeader2; /* volume header record */
  4780. CardAddress iBlock; /* Block counter index */
  4781. ANANDUnitNo iUnit; /* unit index for loops */
  4782. ANANDUnitNo unitsNeededForVolume; /* good units needed for volume */
  4783. ANANDUnitNo floorGarantiedUnitsLeft; /* garantied units not yet distributed */
  4784. ANANDUnitNo binaryUnitsInFloor; /* number of binary unit in this floor */
  4785. ANANDUnitNo noOfUnitsPerFloor[MAX_NO_OF_FLOORS];
  4786. ANANDUnitNo floorGarantiedUnits[MAX_NO_OF_FLOORS]; /* garantied good units in floor */
  4787. ANANDUnitNo originalUnits[MAX_NO_OF_FLOORS]; /* unit no' of the original units */
  4788. ANANDUnitNo goodUnits[MAX_NO_OF_FLOORS]; /* no of good blocks in floor */
  4789. ANANDUnitNo skipedUnits; /* number of good units to leave as unfrmated */
  4790. ANANDUnitNo goodBlocks;
  4791. FLStatus status; /* status of TrueFFS routines */
  4792. Sbyte volumeNo; /* current volume index */
  4793. Sbyte noOfVolumes = fp->noOfBDTLPartitions + fp->noOfBinaryPartitions;
  4794. dword index; /* general loops index */
  4795. dword sizeOfLastBinary;
  4796. byte * firstVolumePtr;
  4797. byte headersBuffer[sizeof(inftlBuffer)];
  4798. byte floorNo; /* current floor index */
  4799. byte noOfFloors;
  4800. byte temp;
  4801. byte lastBinaryFloor;
  4802. #ifdef HW_PROTECTION
  4803. ANANDUnitNo volumeStart;
  4804. word protectionType = 0; /* Initialized to remove warrnings */
  4805. /* Highest floor to leave DPS untouched - per DPS */
  4806. byte binaryFloorOfDPS[MAX_PROTECTED_PARTITIONS];
  4807. byte changeableProtection = 0;
  4808. byte unchangeableProtection = 0;
  4809. byte protectionKey[PROTECTION_KEY_LENGTH];
  4810. #endif /* HW_PROTECTION */
  4811. #ifdef WRITE_EXB_IMAGE
  4812. BinaryPartitionFormatParams exbBinaryPartition;
  4813. byte exbSign[BINARY_SIGNATURE_LEN];
  4814. byte noOfBinary = fp->noOfBinaryPartitions;
  4815. #endif /* WRITE_EXB_IMAGE */
  4816. #ifdef QUICK_MOUNT_FEATURE
  4817. Sword quickMount[MAX_VOLUMES_PER_DOC];
  4818. /* fp->flags |= TL_QUICK_MOUNT_FORMAT; */
  4819. for (volumeNo=0;volumeNo<MAX_VOLUMES_PER_DOC;volumeNo++)
  4820. {
  4821. quickMount[volumeNo]=0;
  4822. }
  4823. #endif /* QUICK_MOUNT_FEATURE */
  4824. /*-------------------------------------------------------
  4825. * Media header || Binary 0 + exb file || Binary 1,.. ||
  4826. *-------------------------------------------------------*/
  4827. /*-----------------------------------------------------
  4828. * quick mount + BDTL 0 || quick mount + BDTL 1, ... ||
  4829. *-----------------------------------------------------*/
  4830. DEBUG_PRINT(("Debug: starting INFTL format by verifying arguments.\r\n"));
  4831. tffsset(&vol,0,sizeof(vol));
  4832. /* Check that there is up to 4 volumes on the device provided one is a
  4833. * BDTL volume. If there is an exb file to be placed it would require
  4834. * at least 1 binary volume
  4835. */
  4836. if ((fp->noOfBDTLPartitions < 1) ||
  4837. #ifdef WRITE_EXB_IMAGE
  4838. ((fp->exbLen > 0) && (fp->noOfBDTLPartitions == MAX_VOLUMES_PER_DOC)) ||
  4839. #endif /* WRITE_EXB_IMAGE */
  4840. (noOfVolumes > MAX_VOLUMES_PER_DOC))
  4841. {
  4842. DFORMAT_PRINT(("ERROR - There can be up to 4 volumes while at least one is a BDTL.\r\n"));
  4843. return flBadParameter;
  4844. }
  4845. /*******************/
  4846. /* Initialization */
  4847. /*******************/
  4848. checkStatus(initINFTL(&vol,flash)); /* Initialize variables */
  4849. noOfFloors = flash->noOfFloors;
  4850. vol.noOfVirtualUnits = 0;
  4851. #ifdef FL_MALLOC
  4852. status = initTables(&vol); /* Allocate tables */
  4853. #else
  4854. status = initTables(&vol,0);
  4855. #endif /* FL_MALLOC */
  4856. if(status != flOK)
  4857. {
  4858. DFORMAT_PRINT(("ERROR - Failed allocating memory for INFTL tables.\r\n"));
  4859. dismountINFTL(&vol); /*Free tables must be done after call to initTables*/
  4860. return status;
  4861. }
  4862. /* Calculate units per floor */
  4863. noOfUnitsPerFloor[0] = (ANANDUnitNo)(vol.flash->chipSize >> vol.unitSizeBits) *
  4864. ((vol.flash->noOfChips + (vol.flash->noOfChips % vol.flash->noOfFloors)) /
  4865. vol.flash->noOfFloors);
  4866. floorGarantiedUnits[0] = (ANANDUnitNo)((dword)((dword)fp->percentUse * (dword)noOfUnitsPerFloor[0]) / 100 - 1); /* - header */
  4867. for (index=0;index+1<vol.flash->noOfFloors;index++)
  4868. {
  4869. noOfUnitsPerFloor[index] = noOfUnitsPerFloor[0];
  4870. floorGarantiedUnits[index] = floorGarantiedUnits[0];
  4871. }
  4872. /* Last floor might have diffrent number of chips */
  4873. noOfUnitsPerFloor[index] = (ANANDUnitNo)(vol.noOfUnits - (index*noOfUnitsPerFloor[0]));
  4874. floorGarantiedUnits[index] = (ANANDUnitNo)((dword)fp->percentUse *
  4875. noOfUnitsPerFloor[index] / 100 - 1);
  4876. /********************************************************************/
  4877. /* Read BBT , find headers location and count number of good blocks */
  4878. /********************************************************************/
  4879. status = retrieveHeader (&vol ,originalUnits,TRUE,
  4880. (fp->flags & FL_LEAVE_BINARY_AREA) ? TRUE : FALSE);
  4881. tffscpy(headersBuffer,inftlBuffer,sizeof(headersBuffer));
  4882. mediaHeader = (BNANDBootRecord *)headersBuffer;
  4883. firstVolumePtr= headersBuffer + sizeof(BNANDBootRecord);
  4884. /* If previous header was not found it is not possible to leave
  4885. * the previous binary partition.
  4886. */
  4887. if(status == flBadFormat)
  4888. {
  4889. if(fp->flags & FL_LEAVE_BINARY_AREA)
  4890. {
  4891. DFORMAT_PRINT(("NOTE - Previous binary partition data could not be found.\r\n"));
  4892. fp->flags &= ~FL_LEAVE_BINARY_AREA;
  4893. }
  4894. }
  4895. if(status == flBadBBT)
  4896. {
  4897. DFORMAT_PRINT(("ERROR - Unreadable Bad Blocks Table.\r\n"));
  4898. dismountINFTL(&vol); /*Free tables must be done after call to initTables*/
  4899. return status;
  4900. }
  4901. if(vol.physicalUnits[0] == BBT_BAD_UNIT)
  4902. {
  4903. DFORMAT_PRINT(("ERROR - IPL block is bad.\r\n"));
  4904. dismountINFTL(&vol); /*Free tables must be done after call to initTables*/
  4905. return flBadIPLBlock;
  4906. }
  4907. /* Loop over the floors of the media while counting the good units
  4908. * the good units are needed for the transfere unit calculation.
  4909. * In addition change the MTD values of Bad unit ro INFTL
  4910. */
  4911. for (floorNo = 0 , iUnit = 0 , index = 0 ; floorNo<noOfFloors ; floorNo++)
  4912. {
  4913. index += noOfUnitsPerFloor[floorNo];
  4914. goodBlocks = noOfUnitsPerFloor[floorNo];
  4915. for (;iUnit<index;iUnit++)
  4916. {
  4917. if (vol.physicalUnits[iUnit]!=BBT_GOOD_UNIT)
  4918. {
  4919. goodBlocks--;
  4920. vol.physicalUnits[iUnit] = UNIT_BAD;
  4921. }
  4922. else
  4923. {
  4924. vol.physicalUnits[iUnit] = ANAND_UNIT_FREE;
  4925. }
  4926. }
  4927. goodBlocks--; /* Do not count one unit for floor header */
  4928. if (goodBlocks < floorGarantiedUnits[floorNo])
  4929. {
  4930. DFORMAT_PRINT(("ERROR - Too many bad block on flash->\r\n"));
  4931. dismountINFTL(&vol); /*Free tables must be done after call to initTables*/
  4932. return flVolumeTooSmall;
  4933. }
  4934. /* Save amount of good blocks for later */
  4935. goodUnits[floorNo] = goodBlocks;
  4936. }
  4937. /************************************/
  4938. /* Construct binary volumes headers */
  4939. /************************************/
  4940. volumeHeader = (BNANDVolumeHeaderRecord *) firstVolumePtr;
  4941. goodBlocks = 0; /* good units already used (counting headers) */
  4942. skipedUnits = 0; /* good units to leave unformated (not counting headers) */
  4943. #ifdef HW_PROTECTION
  4944. for(index = 0 ; index < MAX_PROTECTED_PARTITIONS ; index++)
  4945. binaryFloorOfDPS[index] = MAX_NO_OF_FLOORS; /* Invalid floor no */
  4946. #endif /* HW_PROTECTION */
  4947. if(fp->flags & FL_LEAVE_BINARY_AREA) /* Previous Boot area is kept */
  4948. {
  4949. if(fp->bootImageLen == -1) /* kept entirely */
  4950. {
  4951. for (index = 0;index < LE4(mediaHeader->noOfBinaryPartitions);
  4952. index++,volumeHeader++)
  4953. {
  4954. /* not including headers */
  4955. skipedUnits += (ANANDUnitNo)LE4(volumeHeader->virtualUnits);
  4956. #ifdef HW_PROTECTION
  4957. if (LE4(volumeHeader->flags) & PROTECTABLE)
  4958. {
  4959. if (LE4(volumeHeader->protectionArea) >= flash->totalProtectedAreas)
  4960. {
  4961. tffsset(headersBuffer,0,sizeof(headersBuffer));
  4962. DFORMAT_PRINT(("ERROR - Previous Binary partition had a bad protection area field.\r\n"));
  4963. dismountINFTL(&vol); /*Free tables must be done after call to initTables*/
  4964. return flBadFormat;
  4965. }
  4966. binaryFloorOfDPS[LE4(volumeHeader->protectionArea)] =
  4967. skipedUnits / floorGarantiedUnits[0];
  4968. }
  4969. #endif /* HW_PROTECTION */
  4970. }
  4971. }
  4972. else /* erase all previous binary partitions */
  4973. {
  4974. tffsset(headersBuffer,0,sizeof(headersBuffer));
  4975. if(fp->bootImageLen != 0)
  4976. DFORMAT_PRINT(("ERROR - Requested Binary partition size is diffrent then previous one.\r\n"));
  4977. }
  4978. /* clean the bdtl entries */
  4979. tffsset(volumeHeader, 0,(word)(sizeof(headersBuffer)-((byte *)volumeHeader-headersBuffer)));
  4980. goodBlocks = skipedUnits;
  4981. /* Update the number of partitions with the binary partitions */
  4982. fp->noOfBinaryPartitions = (byte)(volumeHeader - (BNANDVolumeHeaderRecord *) firstVolumePtr);
  4983. noOfVolumes = fp->noOfBDTLPartitions + fp->noOfBinaryPartitions;
  4984. if(noOfVolumes > MAX_VOLUMES_PER_DOC)
  4985. {
  4986. DFORMAT_PRINT(("ERROR - There can be up to 4 volumes while at least one is a BDTL.\r\n"));
  4987. dismountINFTL(&vol); /*Free tables must be done after call to initTables*/
  4988. return flBadParameter;
  4989. }
  4990. }
  4991. else /* Apply binary area format parameters */
  4992. {
  4993. tffsset(headersBuffer,0,sizeof(headersBuffer)); /* reset all binary area */
  4994. for (volumeNo=0;volumeNo<fp->noOfBinaryPartitions;
  4995. volumeNo++,binary++,volumeHeader++)
  4996. {
  4997. binary->length = roundToUnits(binary->length);
  4998. if (binary->length == 0)
  4999. {
  5000. #ifdef WRITE_EXB_IMAGE
  5001. if(((fp->exbLen == 0) && (volumeNo == 0)) ||
  5002. ( volumeNo != 0 ) )
  5003. #endif /* WRITE_EXB_IMAGE */
  5004. {
  5005. DFORMAT_PRINT(("ERROR - BINARY partition length should not be 0.\r\n"));
  5006. dismountINFTL(&vol); /*Free tables must be done after call to initTables*/
  5007. return flBadParameter;
  5008. }
  5009. }
  5010. toLE4(volumeHeader->virtualUnits,binary->length);
  5011. #ifdef HW_PROTECTION
  5012. toLE4(volumeHeader->flags ,INFTL_BINARY |
  5013. binary->protectionType);
  5014. #else
  5015. toLE4(volumeHeader->flags ,INFTL_BINARY);
  5016. #endif /* HW_PROTECTION */
  5017. goodBlocks += (ANANDUnitNo)LE4(volumeHeader->virtualUnits); /* In Units */
  5018. }
  5019. binary = fp->binaryPartitionInfo;
  5020. /* Add EXB area */
  5021. #ifdef WRITE_EXB_IMAGE
  5022. if (fp->exbLen>0)
  5023. {
  5024. fp->exbLen = roundToUnits(fp->exbLen);
  5025. goodBlocks += (ANANDUnitNo)fp->exbLen;
  5026. tffscpy(exbSign,SIGN_SPL,BINARY_SIGNATURE_NAME);
  5027. tffsset(exbSign+BINARY_SIGNATURE_NAME,'F',BINARY_SIGNATURE_NAME);
  5028. if (fp->noOfBinaryPartitions > 0) /* Add firmware blocks */
  5029. {
  5030. toLE4(((BNANDVolumeHeaderRecord*)firstVolumePtr)->virtualUnits,
  5031. LE4(((BNANDVolumeHeaderRecord*)firstVolumePtr)->virtualUnits)
  5032. + fp->exbLen);
  5033. }
  5034. else /* Must create a binary partition just for firmware */
  5035. {
  5036. fp->noOfBinaryPartitions = 1;
  5037. toLE4(volumeHeader->virtualUnits,fp->exbLen );
  5038. #ifdef HW_PROTECTION
  5039. if(noOfBinary) /* Do not use binary record unless it was allocated */
  5040. {
  5041. toLE4(volumeHeader->flags ,INFTL_BINARY |
  5042. binary->protectionType);
  5043. exbBinaryPartition.protectionType = binary->protectionType;
  5044. }
  5045. else
  5046. #endif /* HW_PROTECTION */
  5047. toLE4(volumeHeader->flags ,INFTL_BINARY);
  5048. binary = &exbBinaryPartition;
  5049. volumeHeader++;
  5050. noOfVolumes++;
  5051. }
  5052. fp->exbLen <<= vol.blockMultiplierBits;
  5053. }
  5054. #endif /* WRITE_EXB_IMAGE */
  5055. toLE4(mediaHeader->noOfBinaryPartitions, fp->noOfBinaryPartitions);
  5056. }
  5057. binaryUnitsInFloor = goodBlocks % floorGarantiedUnits[0];
  5058. lastBinaryFloor = goodBlocks / floorGarantiedUnits[0];
  5059. goodBlocks += noOfFloors;
  5060. /********************************/
  5061. /* Construct Main media header */
  5062. /********************************/
  5063. tffscpy(mediaHeader->bootRecordId,"BNAND", TL_SIGNATURE);
  5064. tffscpy(&(mediaHeader->osakVersion),TrueFFSVersion,sizeof(TrueFFSVersion));
  5065. toLE4(mediaHeader->percentUsed , fp->percentUse );
  5066. toLE4(mediaHeader->blockMultiplierBits , vol.blockMultiplierBits);
  5067. toLE4(mediaHeader->formatFlags , 0 );
  5068. toLE4(mediaHeader->noOfBDTLPartitions , fp->noOfBDTLPartitions );
  5069. /* noOfBinaryPartitions was already determinded */
  5070. /**********************************/
  5071. /* Construct BDTL volumes headers */
  5072. /**********************************/
  5073. for (volumeNo=1;(byte)volumeNo<LE4(mediaHeader->noOfBDTLPartitions);
  5074. bdtl++,volumeNo++,volumeHeader++)
  5075. {
  5076. if (bdtl->length < flash->erasableBlockSize)
  5077. {
  5078. DFORMAT_PRINT(("ERROR - INFTL partition length should not be least one unit long.\r\n"));
  5079. dismountINFTL(&vol); /*Free tables must be done after call to initTables*/
  5080. return flBadParameter;
  5081. }
  5082. toLE4(volumeHeader->virtualUnits , roundToUnits(bdtl->length));
  5083. toLE4(volumeHeader->spareUnits , bdtl->noOfSpareUnits );
  5084. toLE4(volumeHeader->flags , INFTL_BDTL );
  5085. goodBlocks += (ANANDUnitNo)LE4(volumeHeader->virtualUnits) + bdtl->noOfSpareUnits;
  5086. #ifdef HW_PROTECTION
  5087. toLE4(volumeHeader->flags,LE4(volumeHeader->flags) |
  5088. bdtl->protectionType);
  5089. #endif /* HW_PROTECTION */
  5090. #ifdef QUICK_MOUNT_FEATURE
  5091. /* if (fp->flags & TL_QUICK_MOUNT_FORMAT) */
  5092. {
  5093. dword quickMountBytes;
  5094. quickMountBytes = (ANANDUnitNo)(LE4(volumeHeader->virtualUnits) +
  5095. LE4(volumeHeader->spareUnits));
  5096. quickMountBytes += ((quickMountBytes / noOfUnitsPerFloor[0] + 1) *
  5097. noOfUnitsPerFloor[0] * (100L-fp->percentUse) / 100L);
  5098. quickMountBytes *= RAM_FACTOR;
  5099. quickMountBytes += flash->pageSize;
  5100. quickMount[volumeNo-1] = roundToUnits(quickMountBytes);
  5101. goodBlocks += quickMount[volumeNo-1];
  5102. }
  5103. #endif /* QUICK_MOUNT_FEATURE */
  5104. }
  5105. /* The size of the last partition is defined by the media itself */
  5106. goodBlocks += fp->noOfSpareUnits;
  5107. for(index=0,floorNo=0;floorNo<noOfFloors;floorNo++)
  5108. {
  5109. index+=floorGarantiedUnits[floorNo];
  5110. }
  5111. toLE4(volumeHeader->flags , INFTL_BDTL | INFTL_LAST);
  5112. toLE4(volumeHeader->spareUnits , fp->noOfSpareUnits );
  5113. toLE4(volumeHeader->lastUnit , vol.noOfUnits-1);
  5114. toLE4(volumeHeader->virtualUnits , index + noOfFloors - goodBlocks);
  5115. #ifdef QUICK_MOUNT_FEATURE
  5116. /* if (fp->flags & TL_QUICK_MOUNT_FORMAT) */
  5117. {
  5118. dword quickMountBytes;
  5119. quickMountBytes = (ANANDUnitNo)(LE4(volumeHeader->virtualUnits) +
  5120. LE4(volumeHeader->spareUnits));
  5121. quickMountBytes += ((quickMountBytes / noOfUnitsPerFloor[0] + 1) *
  5122. noOfUnitsPerFloor[0] * (100L-fp->percentUse) / 100L);
  5123. quickMountBytes *= RAM_FACTOR;
  5124. quickMountBytes += flash->pageSize;
  5125. toLE4(mediaHeader->formatFlags , QUICK_MOUNT);
  5126. quickMount[volumeNo-1] = roundToUnits(quickMountBytes);
  5127. toLE4(volumeHeader->virtualUnits , LE4(volumeHeader->virtualUnits) -
  5128. quickMount[volumeNo-1]);
  5129. }
  5130. #endif /* QUICK_MOUNT_FEATURE */
  5131. if ((LE4(volumeHeader->virtualUnits) < 1) ||
  5132. (LE4(volumeHeader->virtualUnits) > vol.noOfUnits))
  5133. {
  5134. DFORMAT_PRINT(("ERROR - Partition lengths could not be placed on the media.\r\n"));
  5135. dismountINFTL(&vol); /*Free tables must be done after call to initTables*/
  5136. return flVolumeTooSmall;
  5137. }
  5138. /*******************************************/
  5139. /* Allocate protection area to the volumes */
  5140. /*******************************************/
  5141. #ifdef HW_PROTECTION
  5142. toLE4(volumeHeader->flags,LE4(volumeHeader->flags) | /* Ignore other flags */
  5143. fp->protectionType);
  5144. for (volumeNo = noOfVolumes,
  5145. volumeHeader = (BNANDVolumeHeaderRecord *)firstVolumePtr;
  5146. volumeNo>0;volumeNo--,volumeHeader++)
  5147. {
  5148. if (LE4(volumeHeader->flags) & PROTECTABLE)
  5149. {
  5150. if (flash->protectionSet == NULL)
  5151. {
  5152. DFORMAT_PRINT(("ERROR - setting protection routines are not available.\r\n"));
  5153. dismountINFTL(&vol); /*Free tables must be done after call to initTables*/
  5154. return flFeatureNotSupported;
  5155. }
  5156. if (LE4(volumeHeader->flags) & CHANGEABLE_PROTECTION) /* last areas (n,n-1,n-2..)*/
  5157. {
  5158. changeableProtection++; /* Number of protected partitions */
  5159. toLE4(volumeHeader->protectionArea ,
  5160. flash->totalProtectedAreas - changeableProtection);
  5161. }
  5162. else /* first areas (0,1,2,..) */
  5163. {
  5164. toLE4(volumeHeader->protectionArea , unchangeableProtection);
  5165. unchangeableProtection++;
  5166. }
  5167. }
  5168. }
  5169. /* Make sure the device support enough protected areas */
  5170. if ((changeableProtection > flash->changeableProtectedAreas) ||
  5171. (unchangeableProtection + changeableProtection >
  5172. flash->totalProtectedAreas))
  5173. {
  5174. DFORMAT_PRINT(("ERROR - too many protected areas.\r\n"));
  5175. dismountINFTL(&vol); /*Free tables must be done after call to initTables*/
  5176. return flBadParameter;
  5177. }
  5178. /* Clear previous protection areas and write protect them */
  5179. for (index=0;index<flash->totalProtectedAreas;index++)
  5180. {
  5181. /* Send default key to open all protected areas */
  5182. status = flash->protectionKeyInsert(flash,(byte)index,(byte FAR1 *)DEFAULT_KEY);
  5183. }
  5184. /* Clear all floors execpt for those that have only binary partitions */
  5185. for (floorNo=skipedUnits/floorGarantiedUnits[0];floorNo<noOfFloors;floorNo++)
  5186. {
  5187. for (index=0;index<flash->totalProtectedAreas;index++)
  5188. {
  5189. if(binaryFloorOfDPS[index] == floorNo)
  5190. break; /* Belongs to a binary partition that must be left */
  5191. status = flash->protectionSet(flash,(byte)index,
  5192. WRITE_PROTECTED, /* Write protect */
  5193. (index+1) << flash->erasableBlockSizeBits, /* Low address */
  5194. (index+1) << flash->erasableBlockSizeBits, /* High address */
  5195. (byte *)DEFAULT_KEY,DO_NOT_COMMIT_PROTECTION,floorNo);
  5196. if (status != flOK)
  5197. {
  5198. DFORMAT_PRINT(("ERROR - FAILED clearing previous protection areas.\r\n"));
  5199. dismountINFTL(&vol); /*Free tables must be done after call to initTables*/
  5200. return status;
  5201. }
  5202. }
  5203. }
  5204. #endif /* HW_PROTECTION */
  5205. /***********************************/
  5206. /* Actual format of the partitions */
  5207. /***********************************/
  5208. DEBUG_PRINT(("Debug: INFTL format arguments have been verified, starting format.\r\n"));
  5209. unitsNeededForVolume = 0;
  5210. floorNo = skipedUnits / floorGarantiedUnits[0];
  5211. volumeNo = -1; /* bdtl volume number */
  5212. bdtl = fp->BDTLPartitionInfo;
  5213. iUnit = originalUnits[floorNo]+1; /* write after the first header */
  5214. volumeHeader = (BNANDVolumeHeaderRecord *) firstVolumePtr; /* location of first partition header */
  5215. floorGarantiedUnitsLeft = floorGarantiedUnits[floorNo]; /* floors units left */
  5216. /* Skip the boot image area if the FL_LEAVE_BINARY_AREA was set */
  5217. if (skipedUnits > 0 )
  5218. {
  5219. skipedUnits %= floorGarantiedUnits[0]; /* skipped units on the current floor */
  5220. floorGarantiedUnitsLeft -= skipedUnits; /* floors units left */
  5221. volumeHeader += (word)LE4(mediaHeader->noOfBinaryPartitions);
  5222. sizeOfLastBinary = LE4((volumeHeader-1)->virtualUnits);
  5223. /* Clear previous BDTL entries and adjust binary partition */
  5224. for (index = 0 ; index < floorNo ; index++)
  5225. {
  5226. /* read previous floor header */
  5227. status = flash->read(flash,((CardAddress)originalUnits[index]
  5228. << vol.unitSizeBits) + sizeof(BNANDBootRecord),
  5229. firstVolumePtr, sizeof(BNANDVolumeHeaderRecord) *
  5230. (fp->noOfBinaryPartitions) ,0);
  5231. if(status != flOK)
  5232. {
  5233. DFORMAT_PRINT(("ERROR - FAILED reading previous INFTL header.\r\n"));
  5234. dismountINFTL(&vol); /*Free tables must be done after call to initTables*/
  5235. return status;
  5236. }
  5237. toLE4((volumeHeader-1)->virtualUnits , sizeOfLastBinary); /* adjust virtual size */
  5238. if((index == (dword)(floorNo - 1)) && (skipedUnits == 0))
  5239. toLE4((volumeHeader-1)->lastUnit , ((index+1) * noOfUnitsPerFloor[0]) - 1); /* adjust last block */
  5240. /* Erase and write the new updated header */
  5241. status = eraseUnit(&vol,originalUnits[index],fp->progressCallback);
  5242. if(status != flOK)
  5243. {
  5244. DFORMAT_PRINT(("ERROR - FAILED erasing previous INFTL header.\r\n"));
  5245. return status;
  5246. }
  5247. for (temp = 0 ; temp < NO_OF_MEDIA_HEADERS ; temp++)
  5248. {
  5249. status = flash->write(flash,((CardAddress)originalUnits[index]
  5250. << vol.unitSizeBits) + temp * HEADERS_SPACING,
  5251. headersBuffer, sizeof(headersBuffer),EDC);
  5252. if (status != flOK)
  5253. {
  5254. DFORMAT_PRINT(("ERROR - FAILED rewriting INFTL header.\r\n"));
  5255. dismountINFTL(&vol); /*Free tables must be done after call to initTables*/
  5256. return status;
  5257. }
  5258. }
  5259. }
  5260. /* Skip to first BDTL block */
  5261. for (;skipedUnits > 0;skipedUnits--)
  5262. {
  5263. do
  5264. {
  5265. iUnit++;
  5266. }while (vol.physicalUnits[iUnit] == UNIT_BAD);
  5267. }
  5268. /* Save last binary unit for floors header */
  5269. if(iUnit != originalUnits[floorNo]+1)
  5270. toLE4((volumeHeader-1)->lastUnit , iUnit - 1); /* adjust last block */
  5271. }
  5272. do /* loop over floors */
  5273. {
  5274. goodBlocks = goodUnits[floorNo]; /* Good blocks of the floor */
  5275. /* Format as many volumes as posible in this floor */
  5276. while((floorGarantiedUnitsLeft > 0) && (noOfVolumes >= 0))
  5277. {
  5278. if (unitsNeededForVolume == 0) /* Read header of next volume */
  5279. {
  5280. noOfVolumes--;
  5281. toLE4(volumeHeader->firstQuickMountUnit , iUnit);
  5282. unitsNeededForVolume = (ANANDUnitNo)(LE4(volumeHeader->virtualUnits) +
  5283. LE4(volumeHeader->spareUnits));
  5284. #ifdef QUICK_MOUNT_FEATURE
  5285. if (LE4(volumeHeader->flags) & INFTL_BDTL)
  5286. {
  5287. volumeNo++;
  5288. unitsNeededForVolume +=quickMount[volumeNo];
  5289. }
  5290. #else
  5291. toLE4(volumeHeader->firstUnit , iUnit);
  5292. #endif /* QUICK_MOUNT_FEATURE */
  5293. /* Copy protection key and type */
  5294. #ifdef HW_PROTECTION
  5295. if (LE4(volumeHeader->flags) & INFTL_BDTL)
  5296. {
  5297. if (LE4(volumeHeader->flags) & INFTL_LAST)
  5298. {
  5299. tffscpy(protectionKey,fp->protectionKey,PROTECTION_KEY_LENGTH);
  5300. protectionType = fp->protectionType;
  5301. }
  5302. else
  5303. {
  5304. tffscpy(protectionKey,bdtl->protectionKey,PROTECTION_KEY_LENGTH);
  5305. protectionType = bdtl->protectionType;
  5306. }
  5307. }
  5308. else /* Binary */
  5309. {
  5310. tffscpy(protectionKey,binary->protectionKey,PROTECTION_KEY_LENGTH);
  5311. protectionType = binary->protectionType;
  5312. }
  5313. #endif /* HW_PROTECTION */
  5314. }
  5315. /* update format indexs. */
  5316. if (unitsNeededForVolume > floorGarantiedUnitsLeft)
  5317. {
  5318. /* Volume does not fits in floor */
  5319. index = floorGarantiedUnitsLeft;
  5320. unitsNeededForVolume -= floorGarantiedUnitsLeft;
  5321. floorGarantiedUnitsLeft = 0;
  5322. }
  5323. else
  5324. {
  5325. /* Entire volume fits in floor */
  5326. index = unitsNeededForVolume;
  5327. floorGarantiedUnitsLeft -= unitsNeededForVolume;
  5328. unitsNeededForVolume = 0;
  5329. }
  5330. /*******************************************/
  5331. /* Format the volumes blocks of this floor */
  5332. /*******************************************/
  5333. #ifdef HW_PROTECTION
  5334. volumeStart = iUnit;
  5335. #endif /* HW_PROTECTION */
  5336. if (LE4(volumeHeader->flags) & INFTL_BDTL) /* BDTL VOLUME FORMAT */
  5337. {
  5338. /* Add transfer units */
  5339. if (floorNo == lastBinaryFloor)
  5340. {
  5341. index *= (goodBlocks - binaryUnitsInFloor);
  5342. index /= (floorGarantiedUnits[floorNo] - binaryUnitsInFloor);
  5343. }
  5344. else
  5345. {
  5346. index *= goodBlocks;
  5347. index /= floorGarantiedUnits[floorNo];
  5348. }
  5349. /* Format units */
  5350. while (index > 0)
  5351. {
  5352. if (vol.physicalUnits[iUnit] == ANAND_UNIT_FREE)
  5353. {
  5354. #ifdef QUICK_MOUNT_FEATURE
  5355. /* Set the real first unit after the quick mount data */
  5356. if (quickMount[volumeNo] >= 0)
  5357. {
  5358. if(quickMount[volumeNo] == 0)
  5359. {
  5360. toLE4(volumeHeader->firstUnit , iUnit);
  5361. }
  5362. (quickMount[volumeNo])--;
  5363. }
  5364. #endif /* QUICK_MOUNT_FEATURE */
  5365. index--;
  5366. status = eraseUnit(&vol, iUnit,fp->progressCallback);
  5367. if(status != flOK)
  5368. return status;
  5369. }
  5370. else
  5371. {
  5372. if (fp->progressCallback)
  5373. {
  5374. (*fp->progressCallback)((word)(flash->noOfChips *
  5375. (flash->chipSize >> vol.unitSizeBits)),(word)(iUnit+1));
  5376. }
  5377. }
  5378. iUnit++;
  5379. }
  5380. if (unitsNeededForVolume == 0)
  5381. bdtl++;
  5382. }
  5383. if (LE4(volumeHeader->flags) & INFTL_BINARY) /* BINARY VOLUME FORMAT */
  5384. {
  5385. toLE4(volumeHeader->firstUnit , LE4(volumeHeader->firstQuickMountUnit));
  5386. for (; (index > 0) ; iUnit++)
  5387. {
  5388. if (vol.physicalUnits[iUnit] == ANAND_UNIT_FREE)
  5389. {
  5390. index--;
  5391. status = eraseUnit(&vol, iUnit,fp->progressCallback);
  5392. if(status != flOK)
  5393. return status;
  5394. for (iBlock=0;iBlock<(1UL<<vol.unitSizeBits);iBlock+=(1L<<vol.erasableBlockSizeBits))
  5395. {
  5396. #ifdef WRITE_EXB_IMAGE
  5397. if (fp->exbLen > 0)
  5398. {
  5399. fp->exbLen--;
  5400. status = flash->write(flash, 8 + iBlock +
  5401. ((CardAddress)(iUnit) << vol.unitSizeBits),
  5402. exbSign,BINARY_SIGNATURE_LEN,EXTRA);
  5403. }
  5404. else
  5405. #endif /* WRITE_EXB_IMAGE */
  5406. {
  5407. status = flash->write(flash, binary->signOffset + iBlock +
  5408. ((CardAddress)(iUnit) << vol.unitSizeBits),
  5409. binary->sign,BINARY_SIGNATURE_NAME,EXTRA);
  5410. }
  5411. if (status != flOK)
  5412. {
  5413. DFORMAT_PRINT(("ERROR - FAILED formating binary unit.\r\n"));
  5414. dismountINFTL(&vol); /*Free tables must be done after call to initTables*/
  5415. return status;
  5416. }
  5417. }
  5418. }
  5419. else /* unit is bad */
  5420. {
  5421. if (fp->progressCallback)
  5422. {
  5423. (*fp->progressCallback)((word)(flash->noOfChips *
  5424. (flash->chipSize >> vol.unitSizeBits)),(word)(iUnit+1));
  5425. }
  5426. }
  5427. }
  5428. if (unitsNeededForVolume == 0)
  5429. binary++;
  5430. }
  5431. #ifdef HW_PROTECTION
  5432. /* Place protection attributes to the volume */
  5433. if (LE4(volumeHeader->flags) & PROTECTABLE)
  5434. {
  5435. #ifndef NT5PORT
  5436. status = flash->protectionSet(flash,(byte)LE4(volumeHeader->protectionArea),
  5437. protectionType, ((CardAddress)volumeStart %
  5438. noOfUnitsPerFloor[floorNo]) << vol.unitSizeBits,
  5439. ((CardAddress)((iUnit-1) % noOfUnitsPerFloor[floorNo])) << vol.unitSizeBits ,
  5440. (byte *)&protectionKey,DO_NOT_COMMIT_PROTECTION,floorNo);
  5441. #else /*NT5PORT*/
  5442. status = flash->protectionSet(flash,(byte)LE4(volumeHeader->protectionArea),
  5443. protectionType, ((CardAddress)volumeStart %
  5444. noOfUnitsPerFloor[floorNo]) << vol.unitSizeBits,
  5445. ((CardAddress)((iUnit-1) % noOfUnitsPerFloor[floorNo])) << vol.unitSizeBits ,
  5446. protectionKey,DO_NOT_COMMIT_PROTECTION,floorNo);
  5447. #endif /*NT5PORT*/
  5448. if (status != flOK)
  5449. {
  5450. DFORMAT_PRINT(("ERROR - FAILED setting protection.\r\n"));
  5451. dismountINFTL(&vol); /*Free tables must be done after call to initTables*/
  5452. return status;
  5453. }
  5454. }
  5455. #endif /* HW_PROTECTION */
  5456. if (unitsNeededForVolume == 0)
  5457. {
  5458. toLE4(volumeHeader->lastUnit , iUnit - 1);
  5459. volumeHeader++;
  5460. }
  5461. } /* loop until no more units in this floor */
  5462. /* Convert any leftovers to BDTL units */
  5463. index = noOfUnitsPerFloor[floorNo] + floorNo*noOfUnitsPerFloor[0];
  5464. while (iUnit < index)
  5465. {
  5466. if (vol.physicalUnits[iUnit] == ANAND_UNIT_FREE)
  5467. {
  5468. status = eraseUnit(&vol, iUnit,fp->progressCallback);
  5469. if(status != flOK)
  5470. return status;
  5471. }
  5472. else
  5473. {
  5474. if (fp->progressCallback)
  5475. {
  5476. (*fp->progressCallback)((word)(flash->noOfChips *
  5477. (flash->chipSize >> vol.unitSizeBits)),(word)(iUnit+1));
  5478. }
  5479. }
  5480. iUnit++;
  5481. }
  5482. /* Update last unit of BDTL partition */
  5483. if ((unitsNeededForVolume == 0) &&
  5484. (LE4((volumeHeader-1)->flags) & INFTL_BDTL))
  5485. {
  5486. toLE4((volumeHeader-1)->lastUnit , iUnit-1);
  5487. }
  5488. /***************************/
  5489. /* Place the floors header */
  5490. /***************************/
  5491. iUnit = originalUnits[floorNo];
  5492. status = eraseUnit(&vol, iUnit,NULL);
  5493. if(status != flOK)
  5494. return status;
  5495. for (index = 0 ; index < NO_OF_MEDIA_HEADERS;index++)
  5496. {
  5497. status = flash->write(flash,((CardAddress)iUnit << vol.unitSizeBits)
  5498. + index * HEADERS_SPACING,headersBuffer,
  5499. sizeof(headersBuffer),EDC);
  5500. if (status != flOK)
  5501. {
  5502. DFORMAT_PRINT(("ERROR - FAILED writing INFTL header.\r\n"));
  5503. dismountINFTL(&vol); /*Free tables must be done after call to initTables*/
  5504. return status;
  5505. }
  5506. }
  5507. /**************************/
  5508. /* Prepare next iteration */
  5509. /**************************/
  5510. floorNo++;
  5511. if (floorNo < noOfFloors)
  5512. {
  5513. iUnit=originalUnits[floorNo]+1;
  5514. floorGarantiedUnitsLeft = floorGarantiedUnits[floorNo];
  5515. /* Erase physical unit locations to enable independet unit headers */
  5516. volumeHeader2 = (BNANDVolumeHeaderRecord *) firstVolumePtr; /* location of first partition header */
  5517. while (volumeHeader2<=volumeHeader)
  5518. {
  5519. toLE4(volumeHeader2->firstUnit , 0);
  5520. toLE4(volumeHeader2->lastUnit , 0);
  5521. toLE4(volumeHeader2->firstQuickMountUnit , 0);
  5522. volumeHeader2++;
  5523. }
  5524. }
  5525. else
  5526. {
  5527. break;
  5528. }
  5529. } while (1); /* loop over floors */
  5530. DEBUG_PRINT(("Debug: finished INFTL format.\r\n"));
  5531. dismountINFTL(&vol); /*Free tables must be done after call to initTables*/
  5532. return flOK;
  5533. }
  5534. #endif /* FORMAT_VOLUME && not FL_READ_ONLY */
  5535. /*----------------------------------------------------------------------*/
  5536. /* f l R e g i s t e r I N F T L */
  5537. /* */
  5538. /* Register this translation layer */
  5539. /* */
  5540. /* Parameters: */
  5541. /* None */
  5542. /* */
  5543. /* Returns: */
  5544. /* FLStatus : 0 on success, otherwise failure */
  5545. /*----------------------------------------------------------------------*/
  5546. FLStatus flRegisterINFTL(void)
  5547. {
  5548. #ifdef FL_MALLOC
  5549. int i;
  5550. #endif /* FL_MALLOC */
  5551. if (noOfTLs >= TLS)
  5552. return flTooManyComponents;
  5553. tlTable[noOfTLs].mountRoutine = mountINFTL;
  5554. tlTable[noOfTLs].preMountRoutine = preMountINFTL;
  5555. #if (defined(FORMAT_VOLUME) && !defined(FL_READ_ONLY))
  5556. tlTable[noOfTLs].formatRoutine = formatINFTL;
  5557. #else
  5558. tlTable[noOfTLs].formatRoutine = noFormat;
  5559. #endif /* FORMAT_VOLUME && not FL_READ_ONLY */
  5560. noOfTLs++;
  5561. #ifdef FL_MALLOC
  5562. /* reset multi sector buffer */
  5563. for(i=0;( i < SOCKETS );i++) {
  5564. multiSectorBufCounter[i] = -1;
  5565. }
  5566. /* reset convertion tables */
  5567. for(i=0;( i < VOLUMES );i++) {
  5568. vols[i].physicalUnits = NULL;
  5569. vols[i].virtualUnits = NULL;
  5570. #ifdef NFTL_CACHE
  5571. /* reset catche tables */
  5572. vols[i].ucache = NULL;
  5573. vols[i].scache = NULL;
  5574. #endif /* NFTL_CACHE */
  5575. }
  5576. #endif /* FL_MALLOC */
  5577. return flOK;
  5578. }