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.

2312 lines
78 KiB

  1. /*
  2. * $Log: V:/Flite/archives/FLite/src/FTLLITE.C_V $
  3. *
  4. * Rev 1.50 12 Mar 2000 14:06:22 dimitrys
  5. * Change #define FL_BACKGROUND, get rid of
  6. * warnings
  7. *
  8. * Rev 1.49 05 Mar 2000 18:58:08 dimitrys
  9. * Fix possible memory faults because of out-of-range
  10. * memory access in next functions:
  11. * - setupMapCache(), setVirtualMap(), writeSector()
  12. *
  13. * Rev 1.48 05 Mar 2000 17:41:08 dimitrys
  14. * Memory leaks in mountFTL were fixed, add setting
  15. * pointers to Tables to NULL in dismountFTL() call,
  16. * fix possible memory faults because of out-of-range
  17. * memory access in next functions:
  18. * - logical2Physical(), mapLogical(), setupMapCache(),
  19. * virtual2Logical(), findFreeSector(), markAllocMap(),
  20. * AllocateAndWriteSector(), closeReplacementPage(),
  21. * setVirtualMap(), mapSector(), writeSector()
  22. *
  23. * Rev 1.47 Jul 26 1999 17:54:42 marinak
  24. * Fix memory leaks
  25. *
  26. * Rev 1.46 24 Feb 1999 14:17:44 marina
  27. * put TLrec back
  28. *
  29. * Rev 1.45 23 Feb 1999 20:24:16 marina
  30. * memory leaks in formatFTL and mountFTL were fixed; void in place of TLrec
  31. *
  32. * Rev 1.44 31 Jan 1999 19:54:08 marina
  33. * WriteMultiSector
  34. *
  35. * Rev 1.43 17 Jan 1999 17:07:16 marina
  36. * fix dismount bug
  37. *
  38. * Rev 1.42 13 Jan 1999 18:55:24 marina
  39. * Always define sectorsInVolume
  40. *
  41. * Rev 1.41 29 Dec 1998 11:03:02 marina
  42. * Get rid of warnings, prepare for unconditional dismount
  43. *
  44. * Rev 1.40 26 Oct 1998 17:29:36 marina
  45. * In function flRegisterFTL formatRoutine initialization
  46. * is called if not defined FORMAT_VOLUME
  47. *
  48. * Rev 1.39 03 Sep 1998 13:59:02 ANDRY
  49. * better DEBUG_PRINT
  50. *
  51. * Rev 1.38 16 Aug 1998 20:29:50 amirban
  52. * TL definition changes for ATA & ZIP
  53. *
  54. * Rev 1.37 24 Mar 1998 10:48:14 Yair
  55. * Added casts
  56. *
  57. * Rev 1.36 01 Mar 1998 12:59:36 amirban
  58. * Add parameter to mapSector
  59. *
  60. * Rev 1.35 23 Feb 1998 17:08:32 Yair
  61. * Added casts
  62. *
  63. * Rev 1.34 19 Feb 1998 19:05:46 amirban
  64. * Shortened FORMAT_PATTERN, and changed repl. page handling
  65. *
  66. * Rev 1.33 23 Nov 1997 17:19:36 Yair
  67. * Get rid of warnings (With Danny)
  68. *
  69. * Rev 1.32 11 Nov 1997 15:26:46 ANDRY
  70. * () in complex expressions to get rid of compiler warnings
  71. *
  72. * Rev 1.31 06 Oct 1997 18:37:24 ANDRY
  73. * no COBUX
  74. *
  75. * Rev 1.30 05 Oct 1997 15:31:40 ANDRY
  76. * for COBUX: checkForWriteInPlace() always skips even number of bytes
  77. ` *
  78. * Rev 1.29 28 Sep 1997 18:22:08 danig
  79. * Free socket buffer in flsocket.c
  80. *
  81. * Rev 1.28 23 Sep 1997 18:09:44 danig
  82. * Initialize buffer.sectorNo in initTables
  83. *
  84. * Rev 1.27 10 Sep 1997 16:17:16 danig
  85. * Got rid of generic names
  86. *
  87. * Rev 1.26 31 Aug 1997 14:28:30 danig
  88. * Registration routine return status
  89. *
  90. * Rev 1.25 28 Aug 1997 19:01:28 danig
  91. * buffer per socket
  92. *
  93. * Rev 1.24 28 Jul 1997 14:52:30 danig
  94. * volForCallback
  95. *
  96. * Rev 1.23 24 Jul 1997 18:02:44 amirban
  97. * FAR to FAR0
  98. *
  99. * Rev 1.22 21 Jul 1997 19:18:36 danig
  100. * Compile with SINGLE_BUFFER
  101. *
  102. * Rev 1.21 20 Jul 1997 17:17:12 amirban
  103. * Get rid of warnings
  104. *
  105. * Rev 1.20 07 Jul 1997 15:22:00 amirban
  106. * Ver 2.0
  107. *
  108. * Rev 1.19 03 Jun 1997 17:08:10 amirban
  109. * setBusy change
  110. *
  111. * Rev 1.18 18 May 1997 17:56:04 amirban
  112. * Add flash read/write flag parameter
  113. *
  114. * Rev 1.17 01 May 1997 12:15:52 amirban
  115. * Initialize vol.garbageCollectStatus
  116. *
  117. * Rev 1.16 02 Apr 1997 16:56:06 amirban
  118. * More Big-Endian: Virtual map
  119. *
  120. * Rev 1.15 18 Mar 1997 15:04:06 danig
  121. * More Big-Endian corrections for BAM
  122. *
  123. * Rev 1.14 10 Mar 1997 18:52:38 amirban
  124. * Big-Endian corrections for BAM
  125. *
  126. * Rev 1.13 21 Oct 1996 18:03:18 amirban
  127. * Defragment i/f change
  128. *
  129. * Rev 1.12 09 Oct 1996 11:55:30 amirban
  130. * Assign Big-Endian unit numbers
  131. *
  132. * Rev 1.11 08 Oct 1996 12:17:46 amirban
  133. * Use remapped
  134. *
  135. * Rev 1.10 03 Oct 1996 11:56:42 amirban
  136. * New Big-Endian
  137. *
  138. * Rev 1.9 09 Sep 1996 11:39:12 amirban
  139. * Background and mapSector bugs
  140. *
  141. * Rev 1.8 29 Aug 1996 14:19:04 amirban
  142. * Fix boot-image bug, warnings
  143. *
  144. * Rev 1.7 15 Aug 1996 14:04:38 amirban
  145. *
  146. * Rev 1.6 12 Aug 1996 15:49:54 amirban
  147. * Advanced background transfer, and defined setBusy
  148. *
  149. * Rev 1.5 31 Jul 1996 14:30:28 amirban
  150. * Background stuff
  151. *
  152. * Rev 1.3 08 Jul 1996 17:21:16 amirban
  153. * Better page scan in mount unit
  154. *
  155. * Rev 1.2 16 Jun 1996 14:03:42 amirban
  156. * Added badFormat return code for mount
  157. *
  158. * Rev 1.1 09 Jun 1996 18:16:02 amirban
  159. * Corrected definition of LogicalAddress
  160. *
  161. * Rev 1.0 20 Mar 1996 13:33:06 amirban
  162. * Initial revision.
  163. */
  164. /************************************************************************/
  165. /* */
  166. /* FAT-FTL Lite Software Development Kit */
  167. /* Copyright (C) M-Systems Ltd. 1995-1996 */
  168. /* */
  169. /************************************************************************/
  170. #include "flflash.h"
  171. #include "flbuffer.h"
  172. #include "fltl.h"
  173. #ifdef FL_BACKGROUND
  174. #include "backgrnd.h"
  175. #endif
  176. /* Implementation constants and type definitions */
  177. #define SECTOR_OFFSET_MASK (SECTOR_SIZE - 1)
  178. typedef long int LogicalAddress; /* Byte address of media in logical
  179. unit no. order. */
  180. typedef long int VirtualAddress; /* Byte address of media as specified
  181. by Virtual Map. */
  182. typedef SectorNo LogicalSectorNo; /* A logical sector no. is given
  183. by dividing its logical address by
  184. the sector size */
  185. typedef SectorNo VirtualSectorNo; /* A virtual sector no. is such that
  186. the first page is no. 0, the 2nd
  187. is 1 etc.
  188. The virtual sector no. is given
  189. by dividing its virtual address by
  190. the sector size and adding the
  191. number of pages (result always
  192. positive). */
  193. typedef unsigned short UnitNo;
  194. #define ADDRESSES_PER_SECTOR (SECTOR_SIZE / sizeof(LogicalAddress))
  195. #define UNASSIGNED_ADDRESS (ULONG_PTR)-1
  196. #define DELETED_ADDRESS 0
  197. #define DELETED_SECTOR 0
  198. #define PAGE_SIZE_BITS (SECTOR_SIZE_BITS + (SECTOR_SIZE_BITS - 2))
  199. /* Unit descriptor record */
  200. #define UNASSIGNED_UNIT_NO 0xffff
  201. #define MARKED_FOR_ERASE 0x7fff
  202. typedef struct {
  203. short noOfFreeSectors;
  204. short noOfGarbageSectors;
  205. } Unit;
  206. typedef Unit *UnitPtr;
  207. /* Structure of data on a unit */
  208. #define FREE_SECTOR 0xffffffffl
  209. #define GARBAGE_SECTOR 0
  210. #define ALLOCATED_SECTOR 0xfffffffel
  211. #define FORMAT_SECTOR 0x30
  212. #define DATA_SECTOR 0x40
  213. #define REPLACEMENT_PAGE 0x60
  214. #define BAD_SECTOR 0x70
  215. static char FORMAT_PATTERN[15] = { 0x13, 3, 'C', 'I', 'S',
  216. 0x46, 57, 0, 'F', 'T', 'L', '1', '0', '0', 0 };
  217. typedef struct {
  218. char formatPattern[15];
  219. unsigned char noOfTransferUnits; /* no. of transfer units */
  220. LEulong wearLevelingInfo;
  221. LEushort logicalUnitNo;
  222. unsigned char log2SectorSize;
  223. unsigned char log2UnitSize;
  224. LEushort firstPhysicalEUN; /* units reserved for boot image */
  225. LEushort noOfUnits; /* no. of formatted units */
  226. LEulong virtualMediumSize; /* virtual size of volume */
  227. LEulong directAddressingMemory; /* directly addressable memory */
  228. LEushort noOfPages; /* no. of virtual pages */
  229. unsigned char flags;
  230. unsigned char eccCode;
  231. LEulong serialNumber;
  232. LEulong altEUHoffset;
  233. LEulong BAMoffset;
  234. char reserved[12];
  235. char embeddedCIS[4]; /* Actual length may be larger. By
  236. default, this contains FF's */
  237. } UnitHeader;
  238. /* flags assignments */
  239. #define HIDDEN_AREA_FLAG 1
  240. #define REVERSE_POLARITY_FLASH 2
  241. #define DOUBLE_BAI 4
  242. #define dummyUnit ((const UnitHeader *) 0) /* for offset calculations */
  243. #define logicalUnitNoOffset ((char *) &dummyUnit->logicalUnitNo - \
  244. (char *) dummyUnit)
  245. #ifndef MALLOC
  246. #define HEAP_SIZE \
  247. ((0x100000l >> PAGE_SIZE_BITS) * \
  248. sizeof(LogicalSectorNo) + \
  249. (0x100000l / ASSUMED_FTL_UNIT_SIZE) * \
  250. (sizeof(Unit) + sizeof(UnitPtr))) * \
  251. MAX_VOLUME_MBYTES + \
  252. (ASSUMED_VM_LIMIT / SECTOR_SIZE) * \
  253. sizeof(LogicalSectorNo)
  254. #endif
  255. #define cannotWriteOver(newContents, oldContents) \
  256. ((newContents) & ~(oldContents))
  257. struct tTLrec {
  258. FLBoolean badFormat; /* true if FTL format is bad */
  259. VirtualSectorNo totalFreeSectors; /* Free sectors on volume */
  260. SectorNo virtualSectors; /* size of virtual volume */
  261. unsigned int unitSizeBits; /* log2 of unit size */
  262. unsigned int erasableBlockSizeBits; /* log2 of erasable block size */
  263. UnitNo noOfUnits;
  264. UnitNo noOfTransferUnits;
  265. UnitNo firstPhysicalEUN;
  266. int noOfPages;
  267. unsigned directAddressingSectors;/* no. of directly addressable sectors */
  268. VirtualAddress directAddressingMemory; /* end of directly addressable memory */
  269. CardAddress unitOffsetMask; /* = 1 << unitSizeBits - 1 */
  270. CardAddress bamOffset;
  271. unsigned int sectorsPerUnit;
  272. unsigned int unitHeaderSectors; /* sectors used by unit header */
  273. Unit * physicalUnits; /* unit table by physical no. */
  274. Unit ** logicalUnits; /* unit table by logical no. */
  275. Unit * transferUnit; /* The active transfer unit */
  276. LogicalSectorNo * pageTable; /* page translation table */
  277. /* directly addressable sectors */
  278. LogicalSectorNo replacementPageAddress;
  279. VirtualSectorNo replacementPageNo;
  280. SectorNo mappedSectorNo;
  281. const void FAR0 * mappedSector;
  282. CardAddress mappedSectorAddress;
  283. unsigned long currWearLevelingInfo;
  284. #ifdef FL_BACKGROUND
  285. Unit * unitEraseInProgress; /* Unit currently being formatted */
  286. FLStatus garbageCollectStatus; /* Status of garbage collection */
  287. /* When unit transfer is in the background, and is currently in progress,
  288. all write operations done on the 'from' unit moust be mirrored on the
  289. transfer unit. If so, 'mirrorOffset' will be non-zero and will be the
  290. offset of the alternate address from the original. 'mirrorFrom' and
  291. 'mirrorTo' will be the limits of the original addresses to mirror. */
  292. long int mirrorOffset;
  293. CardAddress mirrorFrom,
  294. mirrorTo;
  295. #endif
  296. #ifndef SINGLE_BUFFER
  297. FLBuffer * volBuffer; /* Define a sector buffer */
  298. #endif
  299. FLFlash flash;
  300. #ifndef MALLOC
  301. char heap[HEAP_SIZE];
  302. #endif
  303. };
  304. typedef TLrec Flare;
  305. static Flare vols[SOCKETS];
  306. #ifdef SINGLE_BUFFER
  307. extern FLBuffer buffer;
  308. #else
  309. #define buffer (*vol.volBuffer)
  310. /* Virtual map cache (shares memory with buffer) */
  311. #define mapCache ((LEulong *) buffer.flData)
  312. #endif
  313. /* Unit header buffer (shares memory with buffer) */
  314. #define uh ((UnitHeader *) buffer.flData)
  315. /* Transfer sector buffer (shares memory with buffer) */
  316. #define sectorCopy ((LEulong *) buffer.flData)
  317. #define FREE_UNIT -0x400 /* Indicates a transfer unit */
  318. /* Function definition */
  319. void dismountFTL(Flare vol);
  320. /*----------------------------------------------------------------------*/
  321. /* p h y s i c a l B a s e */
  322. /* */
  323. /* Returns the physical address of a unit. */
  324. /* */
  325. /* Parameters: */
  326. /* vol : Pointer identifying drive */
  327. /* unit : unit pointer */
  328. /* */
  329. /* Returns: */
  330. /* physical address of unit */
  331. /*----------------------------------------------------------------------*/
  332. static CardAddress physicalBase(Flare vol, const Unit *unit)
  333. {
  334. return (CardAddress) (unit - vol.physicalUnits) << vol.unitSizeBits;
  335. }
  336. /*----------------------------------------------------------------------*/
  337. /* l o g i c a l 2 P h y s i c a l */
  338. /* */
  339. /* Returns the physical address of a logical sector no. */
  340. /* */
  341. /* Parameters: */
  342. /* vol : Pointer identifying drive */
  343. /* address : logical sector no. */
  344. /* */
  345. /* Returns: */
  346. /* CardAddress : physical address of sector */
  347. /*----------------------------------------------------------------------*/
  348. static CardAddress logical2Physical(Flare vol, LogicalSectorNo address)
  349. {
  350. UnitNo index;
  351. CardAddress physAddr;
  352. index = (UnitNo)(address >> (vol.unitSizeBits - SECTOR_SIZE_BITS));
  353. if( index >= vol.noOfUnits )
  354. return UNASSIGNED_ADDRESS;
  355. physAddr = physicalBase(&vol,vol.logicalUnits[index]);
  356. physAddr |= (((CardAddress) address << SECTOR_SIZE_BITS) & vol.unitOffsetMask);
  357. return physAddr;
  358. }
  359. /*----------------------------------------------------------------------*/
  360. /* m a p L o g i c a l */
  361. /* */
  362. /* Maps a logical sector and returns pointer to physical Flash location.*/
  363. /* */
  364. /* Parameters: */
  365. /* vol : Pointer identifying drive */
  366. /* address : logical sector no. */
  367. /* */
  368. /* Returns: */
  369. /* Pointer to sector on Flash */
  370. /*----------------------------------------------------------------------*/
  371. static void FAR0 *mapLogical(Flare vol, LogicalSectorNo address)
  372. {
  373. CardAddress physAddress = logical2Physical(&vol,address);
  374. if( physAddress == UNASSIGNED_ADDRESS )
  375. return (void FAR0 *) ULongToPtr(UNASSIGNED_ADDRESS);
  376. return vol.flash.map(&vol.flash,physAddress,SECTOR_SIZE);
  377. }
  378. /*----------------------------------------------------------------------*/
  379. /* a l l o c E n t r y O f f s e t */
  380. /* */
  381. /* Returns unit offset of given BAM entry */
  382. /* */
  383. /* Parameters: */
  384. /* vol : Pointer identifying drive */
  385. /* sectorNo : BAM entry no. */
  386. /* */
  387. /* Returns: */
  388. /* Offset of BAM entry in unit */
  389. /*----------------------------------------------------------------------*/
  390. static int allocEntryOffset(Flare vol, int sectorNo)
  391. {
  392. return (int) (vol.bamOffset + sizeof(VirtualAddress) * sectorNo);
  393. }
  394. /*----------------------------------------------------------------------*/
  395. /* m a p U n i t H e a d e r */
  396. /* */
  397. /* Map a unit header and return pointer to it. */
  398. /* */
  399. /* Parameters: */
  400. /* vol : Pointer identifying drive */
  401. /* unit : Unit to map header */
  402. /* */
  403. /* Returns: */
  404. /* Pointer to mapped unit header */
  405. /* blockAllocMap : (optional) Pointer to mapped BAM */
  406. /*----------------------------------------------------------------------*/
  407. static UnitHeader FAR0 *mapUnitHeader(Flare vol,
  408. const Unit *unit,
  409. LEulong FAR0 **blockAllocMap)
  410. {
  411. UnitHeader FAR0 *unitHeader;
  412. int length = sizeof(UnitHeader);
  413. if (blockAllocMap)
  414. length = allocEntryOffset(&vol,vol.sectorsPerUnit);
  415. unitHeader = (UnitHeader FAR0 *) vol.flash.map(&vol.flash,physicalBase(&vol,unit),length);
  416. if (blockAllocMap)
  417. *blockAllocMap = (LEulong FAR0 *) ((char FAR0 *) unitHeader + allocEntryOffset(&vol,0));
  418. return unitHeader;
  419. }
  420. #ifndef SINGLE_BUFFER
  421. /*----------------------------------------------------------------------*/
  422. /* s e t u p M a p C a c h e */
  423. /* */
  424. /* Sets up map cache sector to contents of specified Virtual Map page */
  425. /* */
  426. /* Parameters: */
  427. /* vol : Pointer identifying drive */
  428. /* pageNo : Page no. to copy to map cache */
  429. /* */
  430. /*----------------------------------------------------------------------*/
  431. static FLStatus setupMapCache(Flare vol, int pageNo)
  432. {
  433. CardAddress physAddress = logical2Physical(&vol,vol.pageTable[pageNo]);
  434. if( physAddress == UNASSIGNED_ADDRESS )
  435. return flGeneralFailure;
  436. vol.flash.read(&vol.flash,physAddress,mapCache,SECTOR_SIZE,0);
  437. if ((VirtualSectorNo)pageNo == vol.replacementPageNo) {
  438. int i;
  439. LEulong FAR0 *replacementPage;
  440. void FAR0 *logicalAddr = mapLogical(&vol,vol.replacementPageAddress);
  441. if( logicalAddr == (void FAR0 *) ULongToPtr(UNASSIGNED_ADDRESS) )
  442. return flGeneralFailure;
  443. replacementPage = (LEulong FAR0 *)logicalAddr;
  444. for (i = 0; i < ADDRESSES_PER_SECTOR; i++) {
  445. if (LE4(mapCache[i]) == DELETED_ADDRESS)
  446. toLE4(mapCache[i],LE4(replacementPage[i]));
  447. }
  448. }
  449. buffer.sectorNo = pageNo;
  450. buffer.owner = &vol;
  451. return flOK;
  452. }
  453. #endif
  454. /*----------------------------------------------------------------------*/
  455. /* v i r t u a l 2 L o g i c a l */
  456. /* */
  457. /* Translates virtual sector no. to logical sector no. */
  458. /* */
  459. /* Parameters: */
  460. /* vol : Pointer identifying drive */
  461. /* sectorNo : Virtual sector no. */
  462. /* */
  463. /* Returns: */
  464. /* Logical sector no. corresponding to virtual sector no. */
  465. /*----------------------------------------------------------------------*/
  466. static LogicalSectorNo virtual2Logical(Flare vol, VirtualSectorNo sectorNo)
  467. {
  468. LogicalAddress virtualMapEntry;
  469. FLStatus status = flOK;
  470. if (sectorNo < (VirtualSectorNo)vol.directAddressingSectors)
  471. return vol.pageTable[((unsigned)sectorNo)];
  472. else {
  473. int pageNo;
  474. int sectorInPage;
  475. sectorNo -= vol.noOfPages;
  476. pageNo = (int) (sectorNo >> (PAGE_SIZE_BITS - SECTOR_SIZE_BITS));
  477. sectorInPage = (int) (sectorNo) % ADDRESSES_PER_SECTOR;
  478. {
  479. #ifdef SINGLE_BUFFER
  480. LogicalAddress FAR0 *virtualMapPage;
  481. virtualMapPage = (LogicalAddress FAR0 *) mapLogical(&vol, vol.pageTable[pageNo]);
  482. if( virtualMapPage == (LogicalAddress FAR0 *) UNASSIGNED_ADDRESS )
  483. return (LogicalSectorNo) UNASSIGNED_SECTOR;
  484. if( pageNo == vol.replacementPageNo &&
  485. virtualMapPage[sectorInPage] == DELETED_ADDRESS ) {
  486. virtualMapPage = (LogicalAddress FAR0 *) mapLogical(&vol, vol.replacementPageAddress);
  487. if( virtualMapPage == (LogicalAddress FAR0 *) UNASSIGNED_ADDRESS )
  488. return (LogicalSectorNo) UNASSIGNED_SECTOR;
  489. }
  490. virtualMapEntry = LE4(virtualMapPage[sectorInPage]);
  491. #else
  492. if( buffer.sectorNo != (SectorNo)pageNo || buffer.owner != &vol )
  493. status = setupMapCache(&vol,pageNo);
  494. if( status != flOK )
  495. return (LogicalSectorNo) UNASSIGNED_SECTOR;
  496. virtualMapEntry = LE4(mapCache[sectorInPage]);
  497. #endif
  498. if( (virtualMapEntry >> vol.unitSizeBits) < vol.noOfUnits )
  499. return (LogicalSectorNo) (virtualMapEntry >> SECTOR_SIZE_BITS);
  500. else
  501. return (LogicalSectorNo) UNASSIGNED_SECTOR;
  502. }
  503. }
  504. }
  505. /*----------------------------------------------------------------------*/
  506. /* v e r i f y F o r m a t */
  507. /* */
  508. /* Verify an FTL unit header. */
  509. /* */
  510. /* Parameters: */
  511. /* unitHeader : Pointer to unit header */
  512. /* */
  513. /* Returns: */
  514. /* TRUE if header is correct. FALSE if not. */
  515. /*----------------------------------------------------------------------*/
  516. static FLBoolean verifyFormat(UnitHeader FAR0 *unitHeader)
  517. {
  518. FORMAT_PATTERN[6] = unitHeader->formatPattern[6]; /* TPL_LINK */
  519. return tffscmp(unitHeader->formatPattern + 2,
  520. FORMAT_PATTERN + 2,
  521. sizeof unitHeader->formatPattern - 2) == 0;
  522. }
  523. /*----------------------------------------------------------------------*/
  524. /* f o r m a t U n i t */
  525. /* */
  526. /* Formats a unit by erasing it and writing a unit header. */
  527. /* */
  528. /* Parameters: */
  529. /* vol : Pointer identifying drive */
  530. /* unit : Unit to format */
  531. /* */
  532. /* Returns: */
  533. /* FLStatus : 0 on success, failed otherwise */
  534. /*----------------------------------------------------------------------*/
  535. static FLStatus formatUnit(Flare vol, Unit *unit)
  536. {
  537. unsigned unitHeaderLength = allocEntryOffset(&vol,vol.unitHeaderSectors);
  538. unit->noOfFreeSectors = FREE_UNIT;
  539. unit->noOfGarbageSectors = 0;
  540. #ifdef FL_BACKGROUND
  541. {
  542. FLStatus status;
  543. vol.unitEraseInProgress = unit;
  544. status = vol.flash.erase(&vol.flash,
  545. (int) (physicalBase(&vol,unit) >> vol.erasableBlockSizeBits),
  546. 1 << (vol.unitSizeBits - vol.erasableBlockSizeBits));
  547. vol.unitEraseInProgress = NULL;
  548. if (status != flOK)
  549. return status;
  550. /* Note: This suspend to the foreground is not only nice to have, it is
  551. necessary ! The reason is that we may have a write from the buffer
  552. waiting for the erase to complete. We are next going to overwrite the
  553. buffer, so this break enables the write to complete before the data is
  554. clobbered (what a relief). */
  555. while (flForeground(1) == BG_SUSPEND)
  556. ;
  557. }
  558. #else
  559. checkStatus(vol.flash.erase(&vol.flash,
  560. (word) (physicalBase(&vol,unit) >> vol.erasableBlockSizeBits),
  561. (word)(1 << (vol.unitSizeBits - vol.erasableBlockSizeBits))));
  562. #endif
  563. /* We will copy the unit header as far as the format entries of the BAM
  564. from another unit (logical unit 0) */
  565. #ifdef SINGLE_BUFFER
  566. if (buffer.dirty)
  567. return flBufferingError;
  568. #endif
  569. buffer.sectorNo = UNASSIGNED_SECTOR; /* Invalidate map cache so we can
  570. use it as a buffer */
  571. if (vol.logicalUnits[vol.firstPhysicalEUN]) {
  572. vol.flash.read(&vol.flash,
  573. physicalBase(&vol,vol.logicalUnits[vol.firstPhysicalEUN]),
  574. uh,
  575. unitHeaderLength,
  576. 0);
  577. }
  578. toLE4(uh->wearLevelingInfo,++vol.currWearLevelingInfo);
  579. toLE2(uh->logicalUnitNo,UNASSIGNED_UNIT_NO);
  580. checkStatus(vol.flash.write(&vol.flash,
  581. physicalBase(&vol,unit),
  582. uh,
  583. unitHeaderLength,
  584. 0));
  585. return flOK;
  586. }
  587. #ifdef FL_BACKGROUND
  588. /*----------------------------------------------------------------------*/
  589. /* f l a s h W r i t e */
  590. /* */
  591. /* Writes to flash through flash.write, but, if possible, allows a */
  592. /* background erase to continue while writing. */
  593. /* */
  594. /* Parameters: */
  595. /* Same as flash.write */
  596. /* */
  597. /* Returns: */
  598. /* Same as flash.write */
  599. /*----------------------------------------------------------------------*/
  600. static FLStatus flashWrite(Flare vol,
  601. CardAddress address,
  602. const void FAR1 *from,
  603. int length,
  604. FLBoolean overwrite)
  605. {
  606. if (vol.mirrorOffset != 0 &&
  607. address >= vol.mirrorFrom && address < vol.mirrorTo) {
  608. checkStatus(flashWrite(&vol,
  609. address + vol.mirrorOffset,
  610. from,
  611. length,
  612. overwrite));
  613. }
  614. if (vol.unitEraseInProgress) {
  615. CardAddress startChip = physicalBase(&vol,vol.unitEraseInProgress) &
  616. (-vol.flash.interleaving * vol.flash.chipSize);
  617. CardAddress endChip = startChip + vol.flash.interleaving * vol.flash.chipSize;
  618. if (address < startChip || address >= endChip) {
  619. flBackground(BG_RESUME);
  620. checkStatus(vol.flash.write(&vol.flash,address,from,length,overwrite));
  621. flBackground(BG_SUSPEND);
  622. return flOK;
  623. }
  624. else if (!(vol.flash.flags & SUSPEND_FOR_WRITE)) {
  625. do {
  626. flBackground(BG_RESUME);
  627. } while (vol.unitEraseInProgress);
  628. }
  629. }
  630. return vol.flash.write(&vol.flash,address,from,length,overwrite);
  631. }
  632. #else
  633. #define flashWrite(v,address,from,length,overwrite) \
  634. (v)->flash.write(&(v)->flash,address,from,length,overwrite)
  635. #endif /* FL_BACKGROUND */
  636. /*----------------------------------------------------------------------*/
  637. /* m o u n t U n i t */
  638. /* */
  639. /* Performs mount scan for a single unit */
  640. /* */
  641. /* Parameters: */
  642. /* vol : Pointer identifying drive */
  643. /* unit : Unit to mount */
  644. /* */
  645. /* Returns: */
  646. /* FLStatus : 0 on success, failed otherwise */
  647. /*----------------------------------------------------------------------*/
  648. static FLStatus mountUnit(Flare vol, Unit *unit)
  649. {
  650. unsigned i;
  651. LogicalSectorNo sectorAddress;
  652. LEulong FAR0 *blockAllocMap;
  653. UnitHeader FAR0 *unitHeader = mapUnitHeader(&vol,unit,&blockAllocMap);
  654. UnitNo logicalUnitNo = LE2(unitHeader->logicalUnitNo);
  655. unit->noOfGarbageSectors = 0;
  656. unit->noOfFreeSectors = FREE_UNIT;
  657. if (!verifyFormat(unitHeader) ||
  658. ((logicalUnitNo != UNASSIGNED_UNIT_NO) &&
  659. ((logicalUnitNo >= vol.noOfUnits) ||
  660. (logicalUnitNo < vol.firstPhysicalEUN) ||
  661. vol.logicalUnits[logicalUnitNo]))) {
  662. if (vol.transferUnit == NULL)
  663. vol.transferUnit = unit;
  664. return flBadFormat;
  665. }
  666. if (logicalUnitNo == UNASSIGNED_UNIT_NO) {
  667. vol.transferUnit = unit;
  668. return flOK; /* this is a transfer unit */
  669. }
  670. if (LE4(unitHeader->wearLevelingInfo) > vol.currWearLevelingInfo &&
  671. LE4(unitHeader->wearLevelingInfo) != 0xffffffffl)
  672. vol.currWearLevelingInfo = LE4(unitHeader->wearLevelingInfo);
  673. /* count sectors and setup virtual map */
  674. sectorAddress =
  675. ((LogicalSectorNo) logicalUnitNo << (vol.unitSizeBits - SECTOR_SIZE_BITS));
  676. unit->noOfFreeSectors = 0;
  677. for (i = 0; i < vol.sectorsPerUnit; i++, sectorAddress++) {
  678. VirtualAddress allocMapEntry = LE4(blockAllocMap[i]);
  679. if (allocMapEntry == GARBAGE_SECTOR || allocMapEntry == ALLOCATED_SECTOR)
  680. unit->noOfGarbageSectors++;
  681. else if (allocMapEntry == FREE_SECTOR) {
  682. unit->noOfFreeSectors++;
  683. vol.totalFreeSectors++;
  684. }
  685. else if (allocMapEntry < vol.directAddressingMemory) {
  686. char signature = (char)((short)(allocMapEntry) & SECTOR_OFFSET_MASK);
  687. if (signature == DATA_SECTOR || signature == REPLACEMENT_PAGE) {
  688. int pageNo = (int) (allocMapEntry >> SECTOR_SIZE_BITS) + vol.noOfPages;
  689. if (pageNo >= 0)
  690. if (signature == DATA_SECTOR)
  691. vol.pageTable[pageNo] = sectorAddress;
  692. else {
  693. vol.replacementPageAddress = sectorAddress;
  694. vol.replacementPageNo = pageNo;
  695. }
  696. }
  697. }
  698. }
  699. /* Place the logical mapping of the unit */
  700. vol.mappedSectorNo = UNASSIGNED_SECTOR;
  701. vol.logicalUnits[logicalUnitNo] = unit;
  702. return flOK;
  703. }
  704. /*----------------------------------------------------------------------*/
  705. /* a s s i g n U n i t */
  706. /* */
  707. /* Assigns a logical unit no. to a unit */
  708. /* */
  709. /* Parameters: */
  710. /* vol : Pointer identifying drive */
  711. /* unit : Unit to assign */
  712. /* */
  713. /* Returns: */
  714. /* FLStatus : 0 on success, failed otherwise */
  715. /*----------------------------------------------------------------------*/
  716. static FLStatus assignUnit(Flare vol, Unit *unit, UnitNo logicalUnitNo)
  717. {
  718. LEushort unitNoToWrite;
  719. toLE2(unitNoToWrite,logicalUnitNo);
  720. return flashWrite(&vol,
  721. (CardAddress)(physicalBase(&vol,unit) + logicalUnitNoOffset),
  722. &unitNoToWrite,
  723. sizeof unitNoToWrite,
  724. OVERWRITE);
  725. }
  726. /*----------------------------------------------------------------------*/
  727. /* b e s t U n i t T o T r a n s f e r */
  728. /* */
  729. /* Find best candidate for unit transfer, usually on the basis of which */
  730. /* unit has the most garbage space. A lower wear-leveling info serves */
  731. /* as a tie-breaker. If 'leastUsed' is NOT specified, then the least */
  732. /* wear-leveling info is the only criterion. */
  733. /* */
  734. /* Parameters: */
  735. /* vol : Pointer identifying drive */
  736. /* leastUsed : Whether most garbage space is the criterion */
  737. /* */
  738. /* Returns: */
  739. /* Best unit to transfer */
  740. /*----------------------------------------------------------------------*/
  741. static UnitNo bestUnitToTransfer(Flare vol, FLBoolean leastUsed)
  742. {
  743. UnitNo i;
  744. int mostGarbageSectors = 1;
  745. unsigned long int leastWearLevelingInfo = 0xffffffffl;
  746. UnitNo bestUnitSoFar = UNASSIGNED_UNIT_NO;
  747. for (i = 0; i < vol.noOfUnits; i++) {
  748. Unit *unit = vol.logicalUnits[i];
  749. if (unit && (!leastUsed || (unit->noOfGarbageSectors >= mostGarbageSectors))) {
  750. UnitHeader FAR0 *unitHeader = mapUnitHeader(&vol,unit,NULL);
  751. if ((leastUsed && (unit->noOfGarbageSectors > mostGarbageSectors)) ||
  752. (LE4(unitHeader->wearLevelingInfo) < leastWearLevelingInfo)) {
  753. mostGarbageSectors = unit->noOfGarbageSectors;
  754. leastWearLevelingInfo = LE4(unitHeader->wearLevelingInfo);
  755. bestUnitSoFar = i;
  756. }
  757. }
  758. }
  759. return bestUnitSoFar;
  760. }
  761. /*----------------------------------------------------------------------*/
  762. /* u n i t T r a n s f e r */
  763. /* */
  764. /* Performs a unit transfer from a selected unit to a tranfer unit. */
  765. /* */
  766. /* A side effect is to invalidate the map cache (reused as buffer). */
  767. /* */
  768. /* Parameters: */
  769. /* vol : Pointer identifying drive */
  770. /* toUnit : Target transfer unit */
  771. /* fromUnitNo: : Source logical unit no. */
  772. /* */
  773. /* Returns: */
  774. /* FLStatus : 0 on success, failed otherwise */
  775. /*----------------------------------------------------------------------*/
  776. static FLStatus unitTransfer(Flare vol, Unit *toUnit, UnitNo fromUnitNo)
  777. {
  778. unsigned i;
  779. Unit *fromUnit = vol.logicalUnits[fromUnitNo];
  780. UnitHeader FAR0 *transferUnitHeader = mapUnitHeader(&vol,toUnit,NULL);
  781. if (!verifyFormat(transferUnitHeader) ||
  782. LE2(transferUnitHeader->logicalUnitNo) != UNASSIGNED_UNIT_NO)
  783. /* previous formatting failed or did not complete. */
  784. checkStatus(formatUnit(&vol,toUnit));
  785. /* Should the transfer not complete, the unit is marked to be erased */
  786. checkStatus(assignUnit(&vol,toUnit,MARKED_FOR_ERASE));
  787. #ifdef FL_BACKGROUND
  788. vol.mirrorFrom = vol.mirrorTo = physicalBase(&vol,fromUnit);
  789. vol.mirrorOffset = physicalBase(&vol,toUnit) - vol.mirrorFrom;
  790. #endif
  791. /* copy the block allocation table and the good sectors */
  792. for (i = 0; i < vol.sectorsPerUnit;) {
  793. int j;
  794. FLBoolean needToWrite = FALSE;
  795. int firstOffset = allocEntryOffset(&vol,i);
  796. /* Up to 128 bytes of the BAM are processed per loop */
  797. int nEntries = (128 - (firstOffset & 127)) / sizeof(VirtualAddress);
  798. /* We are going to use the Virtual Map cache as our sector buffer in the */
  799. /* transfer, so let's better invalidate the cache first. */
  800. #ifdef SINGLE_BUFFER
  801. if (buffer.dirty)
  802. return flBufferingError;
  803. #endif
  804. buffer.sectorNo = UNASSIGNED_SECTOR;
  805. /* Read some of the BAM */
  806. vol.flash.read(&vol.flash,
  807. physicalBase(&vol,fromUnit) + firstOffset,
  808. sectorCopy,
  809. nEntries * sizeof(VirtualAddress),
  810. 0);
  811. /* Convert garbage entries to free entries */
  812. for (j = 0; j < nEntries && i+j < vol.sectorsPerUnit; j++) {
  813. unsigned bamSignature = (unsigned) LE4(sectorCopy[j]) & SECTOR_OFFSET_MASK;
  814. if (bamSignature == DATA_SECTOR ||
  815. bamSignature == REPLACEMENT_PAGE)
  816. needToWrite = TRUE;
  817. else if (bamSignature != FORMAT_SECTOR)
  818. toLE4(sectorCopy[j],FREE_SECTOR);
  819. }
  820. if (needToWrite) {
  821. FLStatus status;
  822. /* Write new BAM, and copy sectors that need to be copied */
  823. status = flashWrite(&vol,
  824. physicalBase(&vol,toUnit) + firstOffset,
  825. sectorCopy,
  826. nEntries * sizeof(VirtualAddress),
  827. 0);
  828. if (status != flOK) {
  829. #ifdef FL_BACKGROUND
  830. vol.mirrorOffset = 0; /* no more mirroring */
  831. #endif
  832. return status;
  833. }
  834. for (j = 0; j < nEntries && i+j < vol.sectorsPerUnit; j++) {
  835. unsigned bamSignature = (unsigned) LE4(sectorCopy[j]) & SECTOR_OFFSET_MASK;
  836. if (bamSignature == DATA_SECTOR ||
  837. bamSignature == REPLACEMENT_PAGE) { /* a good sector */
  838. CardAddress sectorOffset = (CardAddress) (i+j) << SECTOR_SIZE_BITS;
  839. vol.flash.read(&vol.flash,
  840. physicalBase(&vol,fromUnit) + sectorOffset,
  841. sectorCopy,SECTOR_SIZE,0);
  842. status = flashWrite(&vol,
  843. physicalBase(&vol,toUnit) + sectorOffset,
  844. sectorCopy,
  845. SECTOR_SIZE,
  846. 0);
  847. if (status != flOK) {
  848. #ifdef FL_BACKGROUND
  849. vol.mirrorOffset = 0; /* no more mirroring */
  850. #endif
  851. return status;
  852. }
  853. vol.flash.read(&vol.flash,
  854. physicalBase(&vol,fromUnit) + firstOffset,
  855. sectorCopy,
  856. nEntries * sizeof(VirtualAddress),0);
  857. }
  858. }
  859. #ifdef FL_BACKGROUND
  860. vol.mirrorTo = vol.mirrorFrom +
  861. ((CardAddress) (i + nEntries) << SECTOR_SIZE_BITS);
  862. while (flForeground(1) == BG_SUSPEND)
  863. ;
  864. #endif
  865. }
  866. i += nEntries;
  867. }
  868. #ifdef FL_BACKGROUND
  869. vol.mirrorOffset = 0; /* no more mirroring */
  870. #endif
  871. /* Write the new logical unit no. */
  872. checkStatus(assignUnit(&vol,toUnit,fromUnitNo));
  873. /* Mount the new unit in place of old one */
  874. vol.logicalUnits[fromUnitNo] = NULL;
  875. if (mountUnit(&vol,toUnit) == flOK) {
  876. vol.totalFreeSectors -= fromUnit->noOfFreeSectors;
  877. /* Finally, format the source unit (the new transfer unit) */
  878. vol.transferUnit = fromUnit;
  879. formatUnit(&vol,fromUnit); /* nothing we can or should do if this fails */
  880. }
  881. else { /* Something went wrong */
  882. vol.logicalUnits[fromUnitNo] = fromUnit; /* reinstate original unit */
  883. return flGeneralFailure;
  884. }
  885. return flOK;
  886. }
  887. /*----------------------------------------------------------------------*/
  888. /* g a r b a g e C o l l e c t */
  889. /* */
  890. /* Performs a unit transfer, selecting a unit to transfer and a */
  891. /* transfer unit. */
  892. /* */
  893. /* Parameters: */
  894. /* vol : Pointer identifying drive */
  895. /* */
  896. /* Returns: */
  897. /* FLStatus : 0 on success, failed otherwise */
  898. /*----------------------------------------------------------------------*/
  899. static FLStatus garbageCollect(Flare vol)
  900. {
  901. FLStatus status;
  902. UnitNo fromUnitNo;
  903. if (vol.transferUnit == NULL)
  904. return flWriteProtect; /* Cannot recover space without a spare unit */
  905. fromUnitNo = bestUnitToTransfer(&vol,flRandByte() >= 4);
  906. if (fromUnitNo == UNASSIGNED_UNIT_NO)
  907. return flGeneralFailure; /* nothing to collect */
  908. /* Find a unit we can transfer to. */
  909. status = unitTransfer(&vol,vol.transferUnit,fromUnitNo);
  910. if (status == flWriteFault) {
  911. int i;
  912. Unit *unit = vol.physicalUnits;
  913. for (i = 0; i < vol.noOfUnits; i++, unit++) {
  914. if (unit->noOfGarbageSectors == 0 && unit->noOfFreeSectors < 0) {
  915. if (unitTransfer(&vol,unit,fromUnitNo) == flOK)
  916. return flOK; /* found a good one */
  917. }
  918. }
  919. }
  920. return status;
  921. }
  922. #ifdef FL_BACKGROUND
  923. /*----------------------------------------------------------------------*/
  924. /* b g G a r b a g e C o l l e c t */
  925. /* */
  926. /* Entry point for garbage collection in the background. */
  927. /* */
  928. /* Status is returned in vol.garbageCollectStatus */
  929. /* */
  930. /* Parameters: */
  931. /* vol : Pointer identifying drive */
  932. /* */
  933. /* Returns: */
  934. /* None */
  935. /*----------------------------------------------------------------------*/
  936. static void bgGarbageCollect(void * object)
  937. {
  938. Flare vol = (Flare *)object;
  939. vol.garbageCollectStatus = flIncomplete;
  940. vol.garbageCollectStatus = garbageCollect(&vol);
  941. }
  942. #endif
  943. /*----------------------------------------------------------------------*/
  944. /* d e f r a g m e n t */
  945. /* */
  946. /* Performs unit transfers to arrange a minimum number of writable */
  947. /* sectors. */
  948. /* */
  949. /* Parameters: */
  950. /* vol : Pointer identifying drive */
  951. /* sectorsNeeded : Minimum required sectors */
  952. /* */
  953. /* Returns: */
  954. /* FLStatus : 0 on success, failed otherwise */
  955. /*----------------------------------------------------------------------*/
  956. #define GARBAGE_COLLECT_THRESHOLD 20
  957. static FLStatus defragment(Flare vol, long FAR2 *sectorsNeeded)
  958. {
  959. while ((long)(vol.totalFreeSectors) < *sectorsNeeded
  960. #ifdef FL_BACKGROUND
  961. || vol.totalFreeSectors < GARBAGE_COLLECT_THRESHOLD
  962. #endif
  963. ) {
  964. if (vol.badFormat)
  965. return flBadFormat;
  966. #ifdef FL_BACKGROUND
  967. if (vol.garbageCollectStatus == flIncomplete)
  968. flBackground(BG_RESUME);
  969. else
  970. flStartBackground(&vol - vols,bgGarbageCollect,&vol);
  971. if (vol.garbageCollectStatus != flOK &&
  972. vol.garbageCollectStatus != flIncomplete)
  973. return vol.garbageCollectStatus;
  974. if (vol.totalFreeSectors >= *sectorsNeeded)
  975. break;
  976. }
  977. if (vol.unitEraseInProgress)
  978. flBackground(BG_SUSPEND);
  979. #else
  980. checkStatus(garbageCollect(&vol));
  981. }
  982. #endif
  983. *sectorsNeeded = vol.totalFreeSectors;
  984. return flOK;
  985. }
  986. /*----------------------------------------------------------------------*/
  987. /* b e s t U n i t T o A l l o c a t e */
  988. /* */
  989. /* Finds the best unit from which to allocate a sector. The unit */
  990. /* selected is the one with most free space. */
  991. /* */
  992. /* Parameters: */
  993. /* vol : Pointer identifying drive */
  994. /* */
  995. /* Returns: */
  996. /* Best unit to allocate */
  997. /*----------------------------------------------------------------------*/
  998. static Unit *bestUnitToAllocate(Flare vol)
  999. {
  1000. int i;
  1001. int mostFreeSectors = 0;
  1002. Unit *bestUnitSoFar = NULL;
  1003. for (i = 0; i < vol.noOfUnits; i++) {
  1004. Unit *unit = vol.logicalUnits[i];
  1005. if (unit && unit->noOfFreeSectors > mostFreeSectors) {
  1006. mostFreeSectors = unit->noOfFreeSectors;
  1007. bestUnitSoFar = unit;
  1008. }
  1009. }
  1010. return bestUnitSoFar;
  1011. }
  1012. /*----------------------------------------------------------------------*/
  1013. /* f i n d F r e e S e c t o r */
  1014. /* */
  1015. /* The allocation strategy goes this way: */
  1016. /* */
  1017. /* We try to make consecutive virtual sectors physically consecutive if */
  1018. /* possible. If not, we prefer to have consecutive sectors on the same */
  1019. /* unit at least. If all else fails, a sector is allocated on the unit */
  1020. /* with most space available. */
  1021. /* */
  1022. /* The object of this strategy is to cluster related data (e.g. a file */
  1023. /* data) in one unit, and to distribute unrelated data evenly among all */
  1024. /* units. */
  1025. /* */
  1026. /* Parameters: */
  1027. /* vol : Pointer identifying drive */
  1028. /* sectorNo : virtual sector no. that we want to allocate. */
  1029. /* */
  1030. /* Returns: */
  1031. /* newAddress : Allocated logical sector no. */
  1032. /* FLStatus : 0 on success, failed otherwise */
  1033. /*----------------------------------------------------------------------*/
  1034. static FLStatus findFreeSector(Flare vol,
  1035. VirtualSectorNo sectorNo,
  1036. LogicalSectorNo *newAddress)
  1037. {
  1038. unsigned iSector;
  1039. LEulong FAR0 *blockAllocMap;
  1040. UnitHeader FAR0 *unitHeader;
  1041. Unit *allocationUnit = NULL;
  1042. LogicalSectorNo previousSectorAddress =
  1043. (sectorNo > 0 ? virtual2Logical(&vol,(VirtualSectorNo)(sectorNo - 1)) : UNASSIGNED_SECTOR);
  1044. if( ((previousSectorAddress != UNASSIGNED_SECTOR) &&
  1045. (previousSectorAddress != DELETED_SECTOR)) &&
  1046. ((previousSectorAddress >> (vol.unitSizeBits - SECTOR_SIZE_BITS)) < vol.noOfUnits) ) {
  1047. allocationUnit =
  1048. vol.logicalUnits[(UnitNo)(previousSectorAddress >> (vol.unitSizeBits - SECTOR_SIZE_BITS))];
  1049. if (allocationUnit->noOfFreeSectors > 0) {
  1050. unsigned int sectorIndex = ((unsigned) previousSectorAddress & (vol.sectorsPerUnit - 1)) + 1;
  1051. LEulong FAR0 *nextSectorAddress =
  1052. (LEulong FAR0 *) vol.flash.map(&vol.flash,
  1053. physicalBase(&vol,allocationUnit) +
  1054. allocEntryOffset(&vol, sectorIndex),
  1055. sizeof(VirtualAddress));
  1056. if (sectorIndex < vol.sectorsPerUnit && LE4(*nextSectorAddress) == FREE_SECTOR) {
  1057. /* can write sequentially */
  1058. *newAddress = previousSectorAddress + 1;
  1059. return flOK;
  1060. }
  1061. }
  1062. else
  1063. allocationUnit = NULL; /* no space here, try elsewhere */
  1064. }
  1065. if (allocationUnit == NULL)
  1066. allocationUnit = bestUnitToAllocate(&vol);
  1067. if (allocationUnit == NULL) /* No ? then all is lost */
  1068. return flGeneralFailure;
  1069. unitHeader = mapUnitHeader(&vol,allocationUnit,&blockAllocMap);
  1070. for (iSector = vol.unitHeaderSectors; iSector < vol.sectorsPerUnit; iSector++) {
  1071. if (LE4(blockAllocMap[iSector]) == FREE_SECTOR) {
  1072. *newAddress = ((LogicalSectorNo) (LE2(unitHeader->logicalUnitNo)) << (vol.unitSizeBits - SECTOR_SIZE_BITS)) +
  1073. iSector;
  1074. return flOK;
  1075. }
  1076. }
  1077. return flGeneralFailure; /* what are we doing here ? */
  1078. }
  1079. /*----------------------------------------------------------------------*/
  1080. /* m a r k A l l o c M a p */
  1081. /* */
  1082. /* Writes a new value to a BAM entry. */
  1083. /* */
  1084. /* This routine also updates the free & garbage sector counts. */
  1085. /* */
  1086. /* Parameters: */
  1087. /* vol : Pointer identifying drive */
  1088. /* sectorAddress : Logical sector no. whose BAM entry to mark */
  1089. /* allocMapEntry : New BAM entry value */
  1090. /* overwrite : Whether we are overwriting some old value */
  1091. /* */
  1092. /* Returns: */
  1093. /* FLStatus : 0 on success, failed otherwise */
  1094. /*----------------------------------------------------------------------*/
  1095. static FLStatus markAllocMap(Flare vol,
  1096. LogicalSectorNo sectorAddress,
  1097. VirtualAddress allocMapEntry,
  1098. FLBoolean overwrite)
  1099. {
  1100. UnitNo unitNo = (UnitNo) (sectorAddress >> (vol.unitSizeBits - SECTOR_SIZE_BITS));
  1101. Unit *unit;
  1102. int sectorInUnit = (unsigned) sectorAddress & (vol.sectorsPerUnit - 1);
  1103. LEulong bamEntry;
  1104. if (unitNo >= vol.noOfUnits - vol.noOfTransferUnits)
  1105. return flGeneralFailure;
  1106. unit = vol.logicalUnits[unitNo];
  1107. if (allocMapEntry == GARBAGE_SECTOR)
  1108. unit->noOfGarbageSectors++;
  1109. else if (!overwrite) {
  1110. unit->noOfFreeSectors--;
  1111. vol.totalFreeSectors--;
  1112. }
  1113. toLE4(bamEntry,allocMapEntry);
  1114. return flashWrite(&vol,
  1115. physicalBase(&vol,unit) + allocEntryOffset(&vol,sectorInUnit),
  1116. &bamEntry,
  1117. sizeof bamEntry,
  1118. (word)overwrite);
  1119. }
  1120. /*----------------------------------------------------------------------*/
  1121. /* d e l e t e L o g i c a l S e c t o r */
  1122. /* */
  1123. /* Marks a logical sector as deleted. */
  1124. /* */
  1125. /* Parameters: */
  1126. /* vol : Pointer identifying drive */
  1127. /* sectorAddress : Logical sector no. to delete */
  1128. /* */
  1129. /* Returns: */
  1130. /* FLStatus : 0 on success, failed otherwise */
  1131. /*----------------------------------------------------------------------*/
  1132. static FLStatus deleteLogicalSector(Flare vol, LogicalSectorNo sectorAddress)
  1133. {
  1134. if (sectorAddress == UNASSIGNED_SECTOR ||
  1135. sectorAddress == DELETED_SECTOR)
  1136. return flOK;
  1137. return markAllocMap(&vol,sectorAddress,GARBAGE_SECTOR,TRUE);
  1138. }
  1139. /* forward definition */
  1140. static FLStatus setVirtualMap(Flare vol,
  1141. VirtualSectorNo sectorNo,
  1142. LogicalSectorNo newAddress);
  1143. /*----------------------------------------------------------------------*/
  1144. /* a l l o c a t e A n d W r i t e S e c t o r */
  1145. /* */
  1146. /* Allocates a sector or replacement page and (optionally) writes it. */
  1147. /* */
  1148. /* An allocated replacement page also becomes the active replacement */
  1149. /* page. */
  1150. /* */
  1151. /* Parameters: */
  1152. /* vol : Pointer identifying drive */
  1153. /* sectorNo : Virtual sector no. to write */
  1154. /* fromAddress : Address of sector data. If NULL, sector is */
  1155. /* not written. */
  1156. /* replacementPage : This is a replacement page sector. */
  1157. /* */
  1158. /* Returns: */
  1159. /* FLStatus : 0 on success, failed otherwise */
  1160. /*----------------------------------------------------------------------*/
  1161. static FLStatus allocateAndWriteSector(Flare vol,
  1162. VirtualSectorNo sectorNo,
  1163. void FAR1 *fromAddress,
  1164. FLBoolean replacementPage)
  1165. {
  1166. FLStatus status;
  1167. LogicalSectorNo sectorAddress;
  1168. VirtualAddress bamEntry =
  1169. ((VirtualAddress) sectorNo - vol.noOfPages) << SECTOR_SIZE_BITS;
  1170. long sectorsNeeded = 1;
  1171. checkStatus(defragment(&vol,&sectorsNeeded)); /* Organize a free sector */
  1172. checkStatus(findFreeSector(&vol,sectorNo,&sectorAddress));
  1173. if (replacementPage)
  1174. bamEntry |= REPLACEMENT_PAGE;
  1175. else
  1176. bamEntry |= DATA_SECTOR;
  1177. status = markAllocMap(&vol,
  1178. sectorAddress,
  1179. sectorNo < (VirtualSectorNo)vol.directAddressingSectors ?
  1180. ALLOCATED_SECTOR : bamEntry,
  1181. FALSE);
  1182. if( status == flOK && fromAddress) {
  1183. CardAddress physAddress = logical2Physical(&vol,sectorAddress);
  1184. if( physAddress == UNASSIGNED_ADDRESS )
  1185. return flGeneralFailure;
  1186. status = flashWrite(&vol,
  1187. physAddress,
  1188. fromAddress,
  1189. SECTOR_SIZE,
  1190. 0);
  1191. }
  1192. if (sectorNo < (VirtualSectorNo)vol.directAddressingSectors && status == flOK)
  1193. status = markAllocMap(&vol,
  1194. sectorAddress,
  1195. bamEntry,
  1196. TRUE);
  1197. if (status == flOK)
  1198. if (replacementPage) {
  1199. vol.replacementPageAddress = sectorAddress;
  1200. vol.replacementPageNo = sectorNo;
  1201. }
  1202. else
  1203. status = setVirtualMap(&vol,sectorNo,sectorAddress);
  1204. if (status != flOK)
  1205. markAllocMap(&vol,sectorAddress,GARBAGE_SECTOR,TRUE);
  1206. return status;
  1207. }
  1208. /*----------------------------------------------------------------------*/
  1209. /* c l o s e R e p l a c e m e n t P a g e */
  1210. /* */
  1211. /* Closes the replacement page by merging it with the primary page. */
  1212. /* */
  1213. /* Parameters: */
  1214. /* vol : Pointer identifying drive */
  1215. /* */
  1216. /* Returns: */
  1217. /* FLStatus : 0 on success, failed otherwise */
  1218. /*----------------------------------------------------------------------*/
  1219. static FLStatus closeReplacementPage(Flare vol)
  1220. {
  1221. FLStatus status;
  1222. CardAddress physAddress;
  1223. #ifdef SINGLE_BUFFER
  1224. int i;
  1225. LogicalSectorNo nextReplacementPageAddress = vol.replacementPageAddress;
  1226. VirtualSectorNo firstSectorNo =
  1227. ((VirtualSectorNo) vol.replacementPageNo << (PAGE_SIZE_BITS - SECTOR_SIZE_BITS)) +
  1228. vol.noOfPages;
  1229. pageRetry:
  1230. for (i = 0; i < ADDRESSES_PER_SECTOR; i++) {
  1231. LogicalSectorNo logicalSectorNo = virtual2Logical(&vol,firstSectorNo + i);
  1232. LEulong entryToWrite;
  1233. toLE4(entryToWrite,logicalSectorNo == UNASSIGNED_SECTOR ?
  1234. UNASSIGNED_ADDRESS :
  1235. (LogicalAddress) logicalSectorNo << SECTOR_SIZE_BITS);
  1236. physAddress = logical2Physical(&vol,nextReplacementPageAddress);
  1237. if( physAddress == UNASSIGNED_ADDRESS )
  1238. return flGeneralFailure;
  1239. if (flashWrite(&vol,
  1240. physAddress + i * sizeof(LogicalAddress),
  1241. &entryToWrite,
  1242. sizeof entryToWrite,
  1243. OVERWRITE) != flOK)
  1244. break;
  1245. }
  1246. if (i < ADDRESSES_PER_SECTOR &&
  1247. nextReplacementPageAddress == vol.replacementPageAddress) {
  1248. /* Uh oh. Trouble. Let's replace this replacement page. */
  1249. LogicalSectorNo prevReplacementPageAddress = vol.replacementPageAddress;
  1250. checkStatus(allocateAndWriteSector(&vol,vol.replacementPageNo,NULL,TRUE));
  1251. nextReplacementPageAddress = vol.replacementPageAddress;
  1252. vol.replacementPageAddress = prevReplacementPageAddress;
  1253. goto pageRetry;
  1254. }
  1255. if (nextReplacementPageAddress != vol.replacementPageAddress) {
  1256. LogicalSectorNo prevReplacementPageAddress = vol.replacementPageAddress;
  1257. vol.replacementPageAddress = nextReplacementPageAddress;
  1258. checkStatus(deleteLogicalSector(&vol,prevReplacementPageAddress));
  1259. }
  1260. #else
  1261. status = setupMapCache(&vol,(unsigned)vol.replacementPageNo); /* read replacement page into map cache */
  1262. if( status != flOK )
  1263. return flGeneralFailure;
  1264. physAddress = logical2Physical(&vol,vol.replacementPageAddress);
  1265. if( physAddress == UNASSIGNED_ADDRESS )
  1266. return flGeneralFailure;
  1267. status = flashWrite(&vol,
  1268. physAddress,
  1269. mapCache, SECTOR_SIZE, OVERWRITE);
  1270. if (status != flOK) {
  1271. /* Uh oh. Trouble. Let's replace this replacement page. */
  1272. LogicalSectorNo prevReplacementPageAddress = vol.replacementPageAddress;
  1273. checkStatus(allocateAndWriteSector(&vol,vol.replacementPageNo,mapCache,TRUE));
  1274. checkStatus(deleteLogicalSector(&vol,prevReplacementPageAddress));
  1275. }
  1276. #endif
  1277. checkStatus(setVirtualMap(&vol,vol.replacementPageNo,vol.replacementPageAddress));
  1278. checkStatus(markAllocMap(&vol,
  1279. vol.replacementPageAddress,
  1280. (((VirtualAddress) vol.replacementPageNo - vol.noOfPages)
  1281. << SECTOR_SIZE_BITS) | DATA_SECTOR,
  1282. TRUE));
  1283. vol.replacementPageNo = UNASSIGNED_SECTOR;
  1284. return flOK;
  1285. }
  1286. /*----------------------------------------------------------------------*/
  1287. /* s e t V i r t u a l M a p */
  1288. /* */
  1289. /* Changes an entry in the virtual map */
  1290. /* */
  1291. /* Parameters: */
  1292. /* vol : Pointer identifying drive */
  1293. /* sectorNo : Virtual sector no. whose entry is changed. */
  1294. /* newAddress : Logical sector no. to assign in Virtual Map. */
  1295. /* */
  1296. /* Returns: */
  1297. /* FLStatus : 0 on success, failed otherwise */
  1298. /*----------------------------------------------------------------------*/
  1299. static FLStatus setVirtualMap(Flare vol,
  1300. VirtualSectorNo sectorNo,
  1301. LogicalSectorNo newAddress)
  1302. {
  1303. unsigned pageNo;
  1304. int sectorInPage;
  1305. CardAddress virtualMapEntryAddress;
  1306. LEulong addressToWrite;
  1307. LogicalAddress oldAddress;
  1308. LogicalSectorNo updatedPage;
  1309. CardAddress physAddress;
  1310. vol.mappedSectorNo = UNASSIGNED_SECTOR;
  1311. if (sectorNo < (VirtualSectorNo)vol.directAddressingSectors) {
  1312. checkStatus(deleteLogicalSector(&vol,vol.pageTable[(unsigned)sectorNo]));
  1313. vol.pageTable[(unsigned)sectorNo] = newAddress;
  1314. return flOK;
  1315. }
  1316. sectorNo -= vol.noOfPages;
  1317. pageNo = (unsigned)(sectorNo >> (PAGE_SIZE_BITS - SECTOR_SIZE_BITS));
  1318. sectorInPage = (int) (sectorNo % ADDRESSES_PER_SECTOR);
  1319. updatedPage = vol.pageTable[pageNo];
  1320. physAddress = logical2Physical(&vol,updatedPage);
  1321. if( physAddress == UNASSIGNED_ADDRESS )
  1322. return flGeneralFailure;
  1323. virtualMapEntryAddress = physAddress +
  1324. sectorInPage * sizeof(LogicalAddress);
  1325. oldAddress = LE4(*(LEulong FAR0 *)
  1326. vol.flash.map(&vol.flash,virtualMapEntryAddress,sizeof(LogicalAddress)));
  1327. if (oldAddress == DELETED_ADDRESS && vol.replacementPageNo == pageNo) {
  1328. updatedPage = vol.replacementPageAddress;
  1329. physAddress = logical2Physical(&vol,updatedPage);
  1330. if( physAddress == UNASSIGNED_ADDRESS )
  1331. return flGeneralFailure;
  1332. virtualMapEntryAddress = physAddress +
  1333. sectorInPage * sizeof(LogicalAddress);
  1334. oldAddress = LE4(*(LEulong FAR0 *)
  1335. vol.flash.map(&vol.flash,virtualMapEntryAddress,sizeof(LogicalAddress)));
  1336. }
  1337. if (newAddress == DELETED_ADDRESS && oldAddress == UNASSIGNED_ADDRESS)
  1338. return flOK;
  1339. toLE4(addressToWrite,(LogicalAddress) newAddress << SECTOR_SIZE_BITS);
  1340. if (cannotWriteOver(LE4(addressToWrite),oldAddress)) {
  1341. FLStatus status;
  1342. if (pageNo != vol.replacementPageNo ||
  1343. updatedPage == vol.replacementPageAddress) {
  1344. if (vol.replacementPageNo != UNASSIGNED_SECTOR)
  1345. checkStatus(closeReplacementPage(&vol));
  1346. checkStatus(allocateAndWriteSector(&vol,(VirtualSectorNo)pageNo,NULL,TRUE));
  1347. }
  1348. physAddress = logical2Physical(&vol,vol.replacementPageAddress);
  1349. if( physAddress == UNASSIGNED_ADDRESS )
  1350. return flGeneralFailure;
  1351. status = flashWrite(&vol,
  1352. physAddress + sectorInPage * sizeof(LogicalAddress),
  1353. &addressToWrite,
  1354. sizeof addressToWrite,
  1355. 0);
  1356. if (status != flOK) {
  1357. closeReplacementPage(&vol);
  1358. /* we may get a write-error because a
  1359. previous cache update did not complete. */
  1360. return status;
  1361. }
  1362. toLE4(addressToWrite,DELETED_ADDRESS);
  1363. updatedPage = vol.pageTable[pageNo];
  1364. }
  1365. physAddress = logical2Physical(&vol,updatedPage);
  1366. if( physAddress == UNASSIGNED_ADDRESS )
  1367. return flGeneralFailure;
  1368. checkStatus( flashWrite(&vol,
  1369. physAddress + sectorInPage * sizeof(LogicalAddress),
  1370. &addressToWrite,
  1371. (dword)sizeof addressToWrite,
  1372. (word)oldAddress |= UNASSIGNED_ADDRESS));
  1373. #ifndef SINGLE_BUFFER
  1374. if (buffer.sectorNo == pageNo && buffer.owner == &vol)
  1375. toLE4(mapCache[sectorInPage],(LogicalAddress) newAddress << SECTOR_SIZE_BITS);
  1376. #endif
  1377. return deleteLogicalSector(&vol,(LogicalSectorNo) (oldAddress >> SECTOR_SIZE_BITS));
  1378. }
  1379. /*----------------------------------------------------------------------*/
  1380. /* c h e c k F o r W r i t e I n p l a c e */
  1381. /* */
  1382. /* Checks possibility for writing Flash data inplace. */
  1383. /* */
  1384. /* Parameters: */
  1385. /* newData : New data to write. */
  1386. /* oldData : Old data at this location. */
  1387. /* */
  1388. /* Returns: */
  1389. /* < 0 => Writing inplace not possible */
  1390. /* >= 0 => Writing inplace is possible. Value indicates */
  1391. /* how many bytes at the start of data are */
  1392. /* identical and may be skipped. */
  1393. /*----------------------------------------------------------------------*/
  1394. static int checkForWriteInplace(long FAR1 *newData,
  1395. long FAR0 *oldData)
  1396. {
  1397. int i;
  1398. int skipBytes = 0;
  1399. FLBoolean stillSame = TRUE;
  1400. for (i = SECTOR_SIZE / sizeof *newData; i > 0; i--, newData++, oldData++) {
  1401. if (cannotWriteOver(*newData,*oldData))
  1402. return -1;
  1403. if (stillSame && *newData == *oldData)
  1404. skipBytes += sizeof *newData;
  1405. else
  1406. stillSame = FALSE;
  1407. }
  1408. return skipBytes;
  1409. }
  1410. /*----------------------------------------------------------------------*/
  1411. /* i n i t F T L */
  1412. /* */
  1413. /* Initializes essential volume data as a preparation for mount or */
  1414. /* format. */
  1415. /* */
  1416. /* Parameters: */
  1417. /* vol : Pointer identifying drive */
  1418. /* flash : Flash media mounted on this socket */
  1419. /* */
  1420. /* Returns: */
  1421. /* FLStatus : 0 on success, failed otherwise */
  1422. /*----------------------------------------------------------------------*/
  1423. static FLStatus initFTL(Flare vol, FLFlash *flash)
  1424. {
  1425. long int size = 1;
  1426. if (flash == NULL) {
  1427. DEBUG_PRINT(("Debug: media is not fit for FTL format.\n"));
  1428. return flUnknownMedia;
  1429. }
  1430. vol.flash = *flash;
  1431. for (vol.erasableBlockSizeBits = 0; ((unsigned int)size )< vol.flash.erasableBlockSize;
  1432. vol.erasableBlockSizeBits++, size <<= 1);
  1433. vol.unitSizeBits = vol.erasableBlockSizeBits;
  1434. if (vol.unitSizeBits < 16)
  1435. vol.unitSizeBits = 16; /* At least 64 KB */
  1436. vol.noOfUnits = (unsigned) ((vol.flash.noOfChips * vol.flash.chipSize) >> vol.unitSizeBits);
  1437. vol.unitOffsetMask = (1L << vol.unitSizeBits) - 1;
  1438. vol.sectorsPerUnit = 1 << (vol.unitSizeBits - SECTOR_SIZE_BITS);
  1439. vol.bamOffset = sizeof(UnitHeader);
  1440. vol.unitHeaderSectors = ((allocEntryOffset(&vol,vol.sectorsPerUnit) - 1) >>
  1441. SECTOR_SIZE_BITS) + 1;
  1442. vol.transferUnit = NULL;
  1443. vol.replacementPageNo = UNASSIGNED_SECTOR;
  1444. vol.badFormat = TRUE; /* until mount completes */
  1445. vol.mappedSectorNo = UNASSIGNED_SECTOR;
  1446. vol.currWearLevelingInfo = 0;
  1447. #ifdef FL_BACKGROUND
  1448. vol.unitEraseInProgress = NULL;
  1449. vol.garbageCollectStatus = flOK;
  1450. vol.mirrorOffset = 0;
  1451. #endif
  1452. return flOK;
  1453. }
  1454. /*----------------------------------------------------------------------*/
  1455. /* i n i t T a b l e s */
  1456. /* */
  1457. /* Allocates and initializes the dynamic volume table, including the */
  1458. /* unit tables and secondary virtual map. */
  1459. /* */
  1460. /* Parameters: */
  1461. /* vol : Pointer identifying drive */
  1462. /* */
  1463. /* Returns: */
  1464. /* FLStatus : 0 on success, failed otherwise */
  1465. /*----------------------------------------------------------------------*/
  1466. static FLStatus initTables(Flare vol)
  1467. {
  1468. unsigned iSector;
  1469. UnitNo iUnit;
  1470. /* Allocate the conversion tables */
  1471. #ifdef MALLOC
  1472. vol.physicalUnits = (Unit *) MALLOC(vol.noOfUnits * sizeof(Unit));
  1473. vol.logicalUnits = (UnitPtr *) MALLOC(vol.noOfUnits * sizeof(UnitPtr));
  1474. vol.pageTable = (LogicalSectorNo *)
  1475. MALLOC(vol.directAddressingSectors * sizeof(LogicalSectorNo));
  1476. if (vol.physicalUnits == NULL ||
  1477. vol.logicalUnits == NULL ||
  1478. vol.pageTable == NULL) {
  1479. dismountFTL(&vol);
  1480. return flNotEnoughMemory;
  1481. }
  1482. #else
  1483. char *heapPtr;
  1484. heapPtr = vol.heap;
  1485. vol.physicalUnits = (Unit *) heapPtr;
  1486. heapPtr += vol.noOfUnits * sizeof(Unit);
  1487. vol.logicalUnits = (UnitPtr *) heapPtr;
  1488. heapPtr += vol.noOfUnits * sizeof(UnitPtr);
  1489. vol.pageTable = (LogicalSectorNo *) heapPtr;
  1490. heapPtr += vol.directAddressingSectors * sizeof(LogicalSectorNo);
  1491. if (heapPtr > vol.heap + sizeof vol.heap)
  1492. return flNotEnoughMemory;
  1493. #endif
  1494. #ifndef SINGLE_BUFFER
  1495. vol.volBuffer = flBufferOf(flSocketNoOf(vol.flash.socket));
  1496. #endif
  1497. buffer.sectorNo = UNASSIGNED_SECTOR;
  1498. for (iSector = 0; iSector < vol.directAddressingSectors; iSector++)
  1499. vol.pageTable[iSector] = UNASSIGNED_SECTOR;
  1500. for (iUnit = 0; iUnit < vol.noOfUnits; iUnit++)
  1501. vol.logicalUnits[iUnit] = NULL;
  1502. return flOK;
  1503. }
  1504. /*----------------------------------------------------------------------*/
  1505. /* m a p S e c t o r */
  1506. /* */
  1507. /* Maps and returns location of a given sector no. */
  1508. /* NOTE: This function is used in place of a read-sector operation. */
  1509. /* */
  1510. /* A one-sector cache is maintained to save on map operations. */
  1511. /* */
  1512. /* Parameters: */
  1513. /* vol : Pointer identifying drive */
  1514. /* sectorNo : Sector no. to read */
  1515. /* physAddress : Optional pointer to receive sector address */
  1516. /* */
  1517. /* Returns: */
  1518. /* Pointer to physical sector location. NULL returned if sector */
  1519. /* does not exist. */
  1520. /*----------------------------------------------------------------------*/
  1521. static const void FAR0 *mapSector(Flare vol, SectorNo sectorNo, CardAddress *physAddress)
  1522. {
  1523. if (sectorNo != vol.mappedSectorNo || vol.flash.socket->remapped) {
  1524. LogicalSectorNo sectorAddress;
  1525. if (sectorNo >= vol.virtualSectors)
  1526. vol.mappedSector = NULL;
  1527. else {
  1528. sectorAddress = virtual2Logical(&vol,((VirtualSectorNo)(sectorNo + vol.noOfPages)));
  1529. if (sectorAddress == UNASSIGNED_SECTOR || sectorAddress == DELETED_SECTOR)
  1530. vol.mappedSector = NULL; /* no such sector */
  1531. else {
  1532. vol.mappedSectorAddress = logical2Physical(&vol,sectorAddress);
  1533. if( vol.mappedSectorAddress == UNASSIGNED_ADDRESS )
  1534. vol.mappedSector = NULL; /* no such sector */
  1535. else
  1536. vol.mappedSector = vol.flash.map(&vol.flash,
  1537. vol.mappedSectorAddress,
  1538. SECTOR_SIZE);
  1539. }
  1540. }
  1541. vol.mappedSectorNo = sectorNo;
  1542. vol.flash.socket->remapped = FALSE;
  1543. }
  1544. if (physAddress)
  1545. *physAddress = vol.mappedSectorAddress;
  1546. return vol.mappedSector;
  1547. }
  1548. /*----------------------------------------------------------------------*/
  1549. /* w r i t e S e c t o r */
  1550. /* */
  1551. /* Writes a sector. */
  1552. /* */
  1553. /* Parameters: */
  1554. /* vol : Pointer identifying drive */
  1555. /* sectorNo : Sector no. to write */
  1556. /* */
  1557. /* Returns: */
  1558. /* FLStatus : 0 on success, failed otherwise */
  1559. /*----------------------------------------------------------------------*/
  1560. static FLStatus writeSector(Flare vol, SectorNo sectorNo, void FAR1 *fromAddress)
  1561. {
  1562. LogicalSectorNo oldSectorAddress;
  1563. int skipBytes;
  1564. FLStatus status;
  1565. void FAR0 *logicalAddr;
  1566. if (vol.badFormat)
  1567. return flBadFormat;
  1568. if (sectorNo >= vol.virtualSectors)
  1569. return flSectorNotFound;
  1570. sectorNo += vol.noOfPages;
  1571. oldSectorAddress = virtual2Logical(&vol,sectorNo);
  1572. if( oldSectorAddress != UNASSIGNED_SECTOR && oldSectorAddress != DELETED_SECTOR ) {
  1573. logicalAddr = mapLogical(&vol,oldSectorAddress);
  1574. if( logicalAddr == (void FAR0 *) ULongToPtr(UNASSIGNED_ADDRESS) )
  1575. return flGeneralFailure;
  1576. }
  1577. if( ((oldSectorAddress != UNASSIGNED_SECTOR) &&
  1578. (oldSectorAddress != DELETED_SECTOR)) &&
  1579. ((skipBytes = checkForWriteInplace((long FAR1 *) fromAddress,
  1580. (long FAR0 *) logicalAddr)) >= 0) ) {
  1581. if( skipBytes < SECTOR_SIZE ) {
  1582. CardAddress physAddress = logical2Physical(&vol,oldSectorAddress);
  1583. if( physAddress == UNASSIGNED_ADDRESS )
  1584. return flGeneralFailure;
  1585. status = flashWrite(&vol,
  1586. physAddress + skipBytes,
  1587. (char FAR1 *) fromAddress + skipBytes,
  1588. SECTOR_SIZE - skipBytes,
  1589. OVERWRITE);
  1590. }
  1591. else
  1592. status = flOK; /* nothing to write */
  1593. }
  1594. else
  1595. status = allocateAndWriteSector(&vol,sectorNo,fromAddress,FALSE);
  1596. if (status == flWriteFault) /* Automatic retry */
  1597. status = allocateAndWriteSector(&vol,sectorNo,fromAddress,FALSE);
  1598. return status;
  1599. }
  1600. /*----------------------------------------------------------------------*/
  1601. /* t l S e t B u s y */
  1602. /* */
  1603. /* Notifies the start and end of a file-system operation. */
  1604. /* */
  1605. /* Parameters: */
  1606. /* vol : Pointer identifying drive */
  1607. /* state : ON (1) = operation entry */
  1608. /* OFF(0) = operation exit */
  1609. /* */
  1610. /* Returns: */
  1611. /* FLStatus : 0 on success, failed otherwise */
  1612. /*----------------------------------------------------------------------*/
  1613. static FLStatus tlSetBusy(Flare vol, FLBoolean state)
  1614. {
  1615. #ifdef FL_BACKGROUND
  1616. if (vol.unitEraseInProgress)
  1617. flBackground(state == ON ? BG_SUSPEND : BG_RESUME);
  1618. #endif
  1619. return flOK;
  1620. }
  1621. /*----------------------------------------------------------------------*/
  1622. /* d e l e t e S e c t o r */
  1623. /* */
  1624. /* Marks contiguous sectors as deleted */
  1625. /* */
  1626. /* Parameters: */
  1627. /* vol : Pointer identifying drive */
  1628. /* sectorNo : First sector no. to delete */
  1629. /* noOfSectors : No. of sectors to delete */
  1630. /* */
  1631. /* Returns: */
  1632. /* FLStatus : 0 on success, failed otherwise */
  1633. /*----------------------------------------------------------------------*/
  1634. static FLStatus deleteSector(Flare vol, SectorNo sectorNo, SectorNo noOfSectors)
  1635. {
  1636. SectorNo iSector;
  1637. if (vol.badFormat)
  1638. return flBadFormat;
  1639. if (sectorNo + noOfSectors > vol.virtualSectors)
  1640. return flSectorNotFound;
  1641. sectorNo += vol.noOfPages;
  1642. for (iSector = 0; iSector < noOfSectors; iSector++, sectorNo++)
  1643. checkStatus(setVirtualMap(&vol,sectorNo,DELETED_SECTOR));
  1644. return flOK;
  1645. }
  1646. /*----------------------------------------------------------------------*/
  1647. /* s e c t o r s I n V o l u m e */
  1648. /* */
  1649. /* Gets the total number of sectors in the volume */
  1650. /* */
  1651. /* Parameters: */
  1652. /* vol : Pointer identifying drive */
  1653. /* */
  1654. /* Returns: */
  1655. /* Number of sectors in the volume */
  1656. /*----------------------------------------------------------------------*/
  1657. static SectorNo sectorsInVolume(Flare vol)
  1658. {
  1659. return vol.virtualSectors;
  1660. }
  1661. /*----------------------------------------------------------------------*/
  1662. /* d i s m o u n t F T L */
  1663. /* */
  1664. /* Dismount FTL volume */
  1665. /* */
  1666. /* Parameters: */
  1667. /* vol : Pointer identifying drive */
  1668. /* */
  1669. /*----------------------------------------------------------------------*/
  1670. static void dismountFTL(Flare vol)
  1671. {
  1672. #ifdef MALLOC
  1673. if( vol.physicalUnits != NULL )
  1674. FREE(vol.physicalUnits);
  1675. if( vol.logicalUnits != NULL )
  1676. FREE(vol.logicalUnits);
  1677. if( vol.pageTable != NULL )
  1678. FREE(vol.pageTable);
  1679. vol.physicalUnits = NULL;
  1680. vol.logicalUnits = NULL;
  1681. vol.pageTable = NULL;
  1682. #ifdef NT5PORT
  1683. if( vol.flash.readBuffer != NULL ) {
  1684. FREE(vol.flash.readBuffer);
  1685. vol.flash.readBuffer = NULL;
  1686. }
  1687. #endif /* NT5PORT */
  1688. #endif /* MALLOC */
  1689. }
  1690. #ifdef FORMAT_VOLUME
  1691. /*----------------------------------------------------------------------*/
  1692. /* f o r m a t F T L */
  1693. /* */
  1694. /* Formats the Flash volume for FTL */
  1695. /* */
  1696. /* Parameters: */
  1697. /* volNo : Volume no. */
  1698. /* formatParams : Address of FormatParams structure to use */
  1699. /* flash : Flash media mounted on this socket */
  1700. /* */
  1701. /* Returns: */
  1702. /* FLStatus : 0 on success, failed otherwise */
  1703. /*----------------------------------------------------------------------*/
  1704. static FLStatus formatFTL(unsigned volNo, TLFormatParams FAR1 *formatParams, FLFlash *flash)
  1705. {
  1706. Flare vol = &vols[volNo];
  1707. UnitNo iUnit;
  1708. int iPage;
  1709. unsigned iSector, noOfBadUnits = 0;
  1710. LEulong *formatEntries;
  1711. FLStatus status;
  1712. DEBUG_PRINT(("Debug: formatFTL(): Start ... .\n"));
  1713. checkStatus(initFTL(&vol,flash));
  1714. if(formatParams->bootImageLen<0)
  1715. formatParams->bootImageLen = 0;
  1716. vol.firstPhysicalEUN =
  1717. (UnitNo) ((formatParams->bootImageLen - 1) >> vol.unitSizeBits) + 1;
  1718. vol.noOfTransferUnits = (UnitNo)formatParams->noOfSpareUnits;
  1719. if (vol.noOfUnits <= vol.firstPhysicalEUN + formatParams->noOfSpareUnits)
  1720. return flVolumeTooSmall;
  1721. vol.virtualSectors = (SectorNo)((unsigned long) (vol.noOfUnits - vol.firstPhysicalEUN - formatParams->noOfSpareUnits) *
  1722. (vol.sectorsPerUnit - vol.unitHeaderSectors) *
  1723. formatParams->percentUse / 100);
  1724. vol.noOfPages = (int)(((long) vol.virtualSectors * SECTOR_SIZE - 1) >> PAGE_SIZE_BITS) + 1;
  1725. /* take off size of virtual table, and one extra sector for sector writes */
  1726. vol.virtualSectors -= (vol.noOfPages + 1);
  1727. vol.directAddressingMemory = formatParams->vmAddressingLimit;
  1728. vol.directAddressingSectors = (unsigned) (formatParams->vmAddressingLimit / SECTOR_SIZE) +
  1729. vol.noOfPages;
  1730. checkStatus(initTables(&vol));
  1731. tffsset(uh,0xff,SECTOR_SIZE);
  1732. toLE2(uh->noOfUnits,vol.noOfUnits - vol.firstPhysicalEUN);
  1733. toLE2(uh->firstPhysicalEUN,vol.firstPhysicalEUN);
  1734. uh->noOfTransferUnits = (unsigned char) vol.noOfTransferUnits;
  1735. tffscpy(uh->formatPattern,FORMAT_PATTERN,sizeof uh->formatPattern);
  1736. uh->log2SectorSize = SECTOR_SIZE_BITS;
  1737. uh->log2UnitSize = (unsigned char)vol.unitSizeBits;
  1738. toLE4(uh->directAddressingMemory,vol.directAddressingMemory);
  1739. uh->flags = 0;
  1740. uh->eccCode = 0xff;
  1741. toLE4(uh->serialNumber,0);
  1742. toLE4(uh->altEUHoffset,0);
  1743. toLE4(uh->virtualMediumSize,(long)vol.virtualSectors * SECTOR_SIZE);
  1744. toLE2(uh->noOfPages,(unsigned short)vol.noOfPages);
  1745. if (formatParams->embeddedCISlength > 0) {
  1746. tffscpy(uh->embeddedCIS,formatParams->embeddedCIS,formatParams->embeddedCISlength);
  1747. vol.bamOffset = sizeof(UnitHeader) - sizeof uh->embeddedCIS +
  1748. (formatParams->embeddedCISlength + 3) / 4 * 4;
  1749. }
  1750. toLE4(uh->BAMoffset,vol.bamOffset);
  1751. formatEntries = (LEulong *) ((char *) uh + allocEntryOffset(&vol,0));
  1752. for (iSector = 0; iSector < vol.unitHeaderSectors; iSector++)
  1753. toLE4(formatEntries[iSector], FORMAT_SECTOR);
  1754. for (iUnit = vol.firstPhysicalEUN; iUnit < vol.noOfUnits; iUnit++) {
  1755. status = formatUnit(&vol,&vol.physicalUnits[iUnit]);
  1756. if (status != flOK)
  1757. status = formatUnit(&vol,&vol.physicalUnits[iUnit]); /* Do it again */
  1758. if (status == flWriteFault) {
  1759. noOfBadUnits++;
  1760. if (noOfBadUnits >= formatParams->noOfSpareUnits) {
  1761. dismountFTL(&vol); /*Free memory allocated in initTables*/
  1762. return status;
  1763. }
  1764. else
  1765. vol.transferUnit = &vol.physicalUnits[iUnit];
  1766. }
  1767. else if (status == flOK) {
  1768. if (iUnit - noOfBadUnits < (unsigned)(vol.noOfUnits - formatParams->noOfSpareUnits)) {
  1769. status = assignUnit(&vol,
  1770. &vol.physicalUnits[iUnit],
  1771. (UnitNo)(iUnit - noOfBadUnits));
  1772. if( status != flOK ) {
  1773. dismountFTL(&vol); /*Free memory allocated in initTables*/
  1774. return status;
  1775. }
  1776. vol.physicalUnits[iUnit].noOfFreeSectors = vol.sectorsPerUnit - vol.unitHeaderSectors;
  1777. vol.logicalUnits[iUnit - noOfBadUnits] = &vol.physicalUnits[iUnit];
  1778. }
  1779. else
  1780. vol.transferUnit = &vol.physicalUnits[iUnit];
  1781. }
  1782. else {
  1783. dismountFTL(&vol); /*Free memory allocated in initTables*/
  1784. return status;
  1785. }
  1786. if (formatParams->progressCallback) {
  1787. status = (*formatParams->progressCallback)
  1788. ((word)(vol.noOfUnits - vol.firstPhysicalEUN),
  1789. (word)((iUnit + 1) - vol.firstPhysicalEUN));
  1790. if( status != flOK ) {
  1791. dismountFTL(&vol); /*Free memory allocated in initTables*/
  1792. return status;
  1793. }
  1794. }
  1795. }
  1796. /* Allocate and write all page sectors */
  1797. vol.totalFreeSectors = 1000; /* Avoid any nuisance garbage collections */
  1798. for (iPage = 0; iPage < vol.noOfPages; iPage++) {
  1799. status = allocateAndWriteSector(&vol,(VirtualSectorNo)iPage,NULL,FALSE);
  1800. if( status != flOK ) {
  1801. dismountFTL(&vol); /*Free memory allocated in initTables*/
  1802. return status;
  1803. }
  1804. }
  1805. dismountFTL(&vol); /*Free memory allocated in initTables*/
  1806. DEBUG_PRINT(("Debug: formatFTL(): Finished :)\n"));
  1807. return flOK;
  1808. }
  1809. #endif
  1810. /*----------------------------------------------------------------------*/
  1811. /* m o u n t F T L */
  1812. /* */
  1813. /* Mount FTL volume */
  1814. /* */
  1815. /* Parameters: */
  1816. /* volNo : Volume no. */
  1817. /* tl : Where to store translation layer methods */
  1818. /* flash : Flash media mounted on this socket */
  1819. /* volForCallback : Pointer to FLFlash structure for power on */
  1820. /* callback routine. */
  1821. /* */
  1822. /* Returns: */
  1823. /* FLStatus : 0 on success, failed otherwise */
  1824. /*----------------------------------------------------------------------*/
  1825. static FLStatus mountFTL(unsigned volNo, TL *tl, FLFlash *flash, FLFlash **volForCallback)
  1826. {
  1827. Flare vol = &vols[volNo];
  1828. UnitHeader unitHeader;
  1829. UnitNo iUnit;
  1830. int iPage;
  1831. DEBUG_PRINT(("Debug: mountFTL(): Start ...\n"));
  1832. tffsset(&unitHeader,0,sizeof(UnitHeader));
  1833. checkStatus(initFTL(&vol,flash));
  1834. *volForCallback = &vol.flash;
  1835. /* Find the first properly formatted unit */
  1836. for (iUnit = 0; iUnit < vol.noOfUnits; iUnit++) {
  1837. vol.flash.read(&vol.flash,
  1838. (CardAddress) iUnit << vol.unitSizeBits,
  1839. &unitHeader,
  1840. sizeof(UnitHeader),
  1841. 0);
  1842. if (verifyFormat(&unitHeader)) {
  1843. if (unitHeader.flags || unitHeader.log2SectorSize != SECTOR_SIZE_BITS ||
  1844. (unitHeader.eccCode != 0xff && unitHeader.eccCode != 0)) {
  1845. dismountFTL(&vol);
  1846. return flBadFormat;
  1847. }
  1848. break;
  1849. }
  1850. }
  1851. if (iUnit >= vol.noOfUnits) {
  1852. dismountFTL(&vol);
  1853. DEBUG_PRINT(("Debug: mountFTL(): failed for unit Header\n"));
  1854. return flUnknownMedia;
  1855. }
  1856. /* Get volume information from unit header */
  1857. vol.noOfUnits = LE2(unitHeader.noOfUnits);
  1858. vol.noOfTransferUnits = unitHeader.noOfTransferUnits;
  1859. vol.firstPhysicalEUN = LE2(unitHeader.firstPhysicalEUN);
  1860. vol.bamOffset = LE4(unitHeader.BAMoffset);
  1861. vol.virtualSectors = (SectorNo) (LE4(unitHeader.virtualMediumSize) >> SECTOR_SIZE_BITS);
  1862. vol.noOfPages = LE2(unitHeader.noOfPages);
  1863. vol.noOfUnits += vol.firstPhysicalEUN;
  1864. vol.unitSizeBits = unitHeader.log2UnitSize;
  1865. vol.directAddressingMemory = LE4(unitHeader.directAddressingMemory);
  1866. vol.directAddressingSectors = vol.noOfPages +
  1867. (unsigned) (vol.directAddressingMemory >> SECTOR_SIZE_BITS);
  1868. vol.unitOffsetMask = (1L << vol.unitSizeBits) - 1;
  1869. vol.sectorsPerUnit = 1 << (vol.unitSizeBits - SECTOR_SIZE_BITS);
  1870. vol.unitHeaderSectors = ((allocEntryOffset(&vol,vol.sectorsPerUnit) - 1) >>
  1871. SECTOR_SIZE_BITS) + 1;
  1872. if (vol.noOfUnits <= vol.firstPhysicalEUN ||
  1873. LE4(unitHeader.virtualMediumSize) > MAX_VOLUME_MBYTES * 0x100000l ||
  1874. allocEntryOffset(&vol,vol.unitHeaderSectors) > SECTOR_SIZE ||
  1875. (int)(vol.virtualSectors >> (PAGE_SIZE_BITS - SECTOR_SIZE_BITS)) > vol.noOfPages ||
  1876. (int)(vol.virtualSectors >> (vol.unitSizeBits - SECTOR_SIZE_BITS)) > (vol.noOfUnits - vol.firstPhysicalEUN)) {
  1877. dismountFTL(&vol);
  1878. return flBadFormat;
  1879. }
  1880. checkStatus(initTables(&vol));
  1881. vol.totalFreeSectors = 0;
  1882. /* Mount all units */
  1883. for (iUnit = vol.firstPhysicalEUN; iUnit < vol.noOfUnits; iUnit++)
  1884. mountUnit(&vol,&vol.physicalUnits[iUnit]);
  1885. /* Verify the conversion tables */
  1886. vol.badFormat = FALSE;
  1887. for (iUnit = vol.firstPhysicalEUN; iUnit < vol.noOfUnits - vol.noOfTransferUnits; iUnit++)
  1888. if (vol.logicalUnits[iUnit] == NULL)
  1889. vol.badFormat = TRUE;
  1890. if (vol.replacementPageNo != UNASSIGNED_SECTOR &&
  1891. vol.pageTable[(unsigned)vol.replacementPageNo] == UNASSIGNED_SECTOR) {
  1892. /* A lonely replacement page. Mark it as a regular page (may fail */
  1893. /* because of write protection) and use it. */
  1894. markAllocMap(&vol,
  1895. vol.replacementPageAddress,
  1896. (((VirtualAddress) vol.replacementPageNo - vol.noOfPages)
  1897. << SECTOR_SIZE_BITS) | DATA_SECTOR,
  1898. TRUE);
  1899. vol.pageTable[(unsigned)vol.replacementPageNo] = vol.replacementPageAddress;
  1900. vol.replacementPageNo = UNASSIGNED_SECTOR;
  1901. }
  1902. for (iPage = 0; iPage < vol.noOfPages; iPage++)
  1903. if (vol.pageTable[iPage] == UNASSIGNED_SECTOR)
  1904. vol.badFormat = TRUE;
  1905. tl->rec = &vol;
  1906. tl->mapSector = mapSector;
  1907. tl->writeSector = writeSector;
  1908. tl->deleteSector = deleteSector;
  1909. #if defined(DEFRAGMENT_VOLUME) || defined(SINGLE_BUFFER)
  1910. tl->defragment = defragment;
  1911. #endif
  1912. tl->sectorsInVolume = sectorsInVolume;
  1913. tl->tlSetBusy = tlSetBusy;
  1914. tl->dismount = dismountFTL;
  1915. tl->writeMultiSector = NULL;
  1916. tl->readSectors = NULL;
  1917. if( vol.badFormat ) {
  1918. dismountFTL(&vol);
  1919. return flBadFormat;
  1920. }
  1921. DEBUG_PRINT(("Debug: mountFTL(): Finished OK! :)\n"));
  1922. return flOK;
  1923. }
  1924. /*----------------------------------------------------------------------*/
  1925. /* f l R e g i s t e r F T L */
  1926. /* */
  1927. /* Register this translation layer */
  1928. /* */
  1929. /* Parameters: */
  1930. /* None */
  1931. /* */
  1932. /* Returns: */
  1933. /* FLStatus : 0 on succes, otherwise failure */
  1934. /*----------------------------------------------------------------------*/
  1935. FLStatus flRegisterFTL(void)
  1936. {
  1937. #ifdef MALLOC
  1938. unsigned i,j;
  1939. #endif
  1940. j = 0x11223344;
  1941. PRINTF("flRegisterFTL():Started ... \n");
  1942. if (noOfTLs >= TLS)
  1943. return flTooManyComponents;
  1944. PRINTF("flRegisterFTL():SUSU TEST @@@@@@@@@@@@@@@ = %x \n",j);
  1945. tlTable[noOfTLs].mountRoutine = mountFTL;
  1946. PRINTF("flRegisterFTL():tlTable[noOfTLs].mountRoutine = %x \n",tlTable[noOfTLs].mountRoutine);
  1947. #ifdef FORMAT_VOLUME
  1948. tlTable[noOfTLs].formatRoutine = formatFTL;
  1949. #else
  1950. tlTable[noOfTLs].formatRoutine = noFormat;
  1951. tlTable[noOfTLs].preMountRoutine = NULL;
  1952. #endif
  1953. noOfTLs++;
  1954. #ifdef MALLOC
  1955. for(i=0;( i < SOCKETS );i++) {
  1956. vols[i].physicalUnits = NULL;
  1957. vols[i].logicalUnits = NULL;
  1958. vols[i].pageTable = NULL;
  1959. }
  1960. #endif
  1961. return flOK;
  1962. }