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.

1827 lines
70 KiB

  1. /***********************************************************************************/
  2. /* M-Systems Confidential */
  3. /* Copyright (C) M-Systems Flash Disk Pioneers Ltd. 1995-2001 */
  4. /* All Rights Reserved */
  5. /***********************************************************************************/
  6. /* NOTICE OF M-SYSTEMS OEM */
  7. /* SOFTWARE LICENSE AGREEMENT */
  8. /* */
  9. /* THE USE OF THIS SOFTWARE IS GOVERNED BY A SEPARATE LICENSE */
  10. /* AGREEMENT BETWEEN THE OEM AND M-SYSTEMS. REFER TO THAT AGREEMENT */
  11. /* FOR THE SPECIFIC TERMS AND CONDITIONS OF USE, */
  12. /* OR CONTACT M-SYSTEMS FOR LICENSE ASSISTANCE: */
  13. /* E-MAIL = [email protected] */
  14. /***********************************************************************************/
  15. /*
  16. * $Log: V:/Flite/archives/TrueFFS5/Src/flmtl.c_V $
  17. *
  18. * Rev 1.11 Nov 08 2001 10:49:20 oris
  19. * Added support for up to 1GB DiskOnChips.
  20. *
  21. * Rev 1.10 Sep 24 2001 18:23:40 oris
  22. * Removed warnings.
  23. *
  24. * Rev 1.9 Sep 15 2001 23:46:16 oris
  25. * Changed progress callback routine to support up to 64K units.
  26. *
  27. * Rev 1.8 Jul 13 2001 01:05:16 oris
  28. * Removed warnings.
  29. * Bug fix - exception when format routine is called with null progress call back routine.
  30. * Report noOfDrives as 1.
  31. *
  32. * Rev 1.7 Jun 17 2001 08:18:40 oris
  33. * Add improoved the format progress call back routine.
  34. * Removed fack number of TLS in mtlPreMount routine.
  35. *
  36. * Rev 1.6 May 21 2001 16:13:08 oris
  37. * Replaced memcpy with tffscpy Macro.
  38. *
  39. * Rev 1.5 May 17 2001 18:54:26 oris
  40. * Removed warnings.
  41. *
  42. * Rev 1.4 May 16 2001 21:19:02 oris
  43. * Changed the fl_MTLdefragMode variable to a global environment variable.
  44. * MTL now changes the noOfDriver variable after the first mount and restores it after uninstall.
  45. * Added missing ifdef directives.
  46. * Removed warnings.
  47. * Removed readBBT and writeBBT routines.
  48. * Improved MTL protection routine.
  49. *
  50. * Rev 1.3 Apr 01 2001 08:01:18 oris
  51. * copywrite notice.
  52. * Alligned left all # directives.
  53. *
  54. * Rev 1.2 Feb 18 2001 12:06:54 oris
  55. * Install mtl will now fake the noOfTLs in order to be the only TL.
  56. * Placed mtlFormat under FORMAT_VOLUME compilation flag.
  57. * Place mtlProtection under HW_PROTECTION compilation flag.
  58. * Changed mtlPreMount arg sanity check to include partition number.
  59. * Changed tmpflash to tmpFlash.
  60. *
  61. * Rev 1.1 Feb 14 2001 02:09:38 oris
  62. * Changed readBBT to return media size.
  63. * Added boundry argument to writeBBT.
  64. *
  65. * Rev 1.0 Feb 12 2001 12:07:02 oris
  66. * Initial revision.
  67. *
  68. * Rev 1.3 Jan 24 2001 18:10:48 oris
  69. * Bug fix: MTL failed to register because noOfTLs wan't updated
  70. *
  71. * Rev 1.2 Jan 24 2001 16:34:06 oris
  72. * MTL defragmentation changed, alt. defragmentation added.
  73. *
  74. * Rev 1.1 Jan 22 2001 22:10:50 amirm
  75. * #define FL_MTL_HIDDEN_SECTORS added
  76. *
  77. * Rev 1.0 Jan 22 2001 18:27:54 amirm
  78. * Initial revision.
  79. *
  80. */
  81. /*
  82. * Include
  83. */
  84. #include "fltl.h"
  85. /*
  86. * Configuration
  87. */
  88. /* This defined sets the number of sectors to ignore starting from the
  89. * first device. The default value should be 1 therfore ignoring sector
  90. * 0 of the first device. Ignioring sector 0 gurentees that the combined
  91. * device does not use the BPB of the first device, which does not report
  92. * the C/H/S of the new combined media. The next format operation would
  93. * write a new BPB that would fit the new combined media size.
  94. */
  95. #define FL_MTL_HIDDEN_SECTORS 1
  96. /*
  97. * Extern
  98. */
  99. /*
  100. * Globals
  101. */
  102. FLStatus flRegisterMTL (void); /* see also stdcomp.h */
  103. FLStatus flmtlInstall (void);
  104. FLStatus flmtlUninstall (void);
  105. /*
  106. * Local types
  107. */
  108. /* I/O vector for splitting I/O among physical devices */
  109. typedef struct {
  110. SectorNo startSector;
  111. SectorNo sectors;
  112. } tMTLiov;
  113. /* Physical flash device. Part of MTL volume. */
  114. typedef struct {
  115. SectorNo virtualSectors;
  116. TL tl;
  117. dword physicalSize;
  118. } tMTLPhysDev;
  119. /* MTL volume */
  120. struct tTLrec {
  121. int noOfTLs;
  122. int noOfDrives;
  123. SectorNo virtualSectors;
  124. tMTLPhysDev devs[SOCKETS];
  125. };
  126. typedef TLrec MTL;
  127. /*
  128. * Local data
  129. */
  130. /* only one MTL volume is supported */
  131. static MTL mvol;
  132. /* progress callBack routine */
  133. FLProgressCallback globalProgressCallback = NULL;
  134. /* access macros for MTL volume */
  135. #define mT(dev) (mvol.devs[dev].tl)
  136. #define mS(dev) (mvol.devs[dev].virtualSectors)
  137. #define mP(dev) (mvol.devs[dev].physicalSize)
  138. #define mpT(pvol,dev) ((pvol)->devs[dev].tl)
  139. #define mpF(pvol,dev) ((pvol)->devs[dev].flash)
  140. #define mpS(pvol,dev) ((pvol)->devs[dev].virtualSectors)
  141. /*
  142. * Local routines
  143. */
  144. static FLStatus mtlSplitIO (MTL *pvol, SectorNo startSector,
  145. SectorNo sectors, tMTLiov *iov);
  146. static FLStatus mtlWrite (MTL *pvol, SectorNo startSector,
  147. SectorNo *pSectorsToWrite, void FAR1 *buf);
  148. static FLStatus mtlMount (unsigned volNo, TL *tl, FLFlash *flash,
  149. FLFlash **notUsed);
  150. #if defined(DEFRAGMENT_VOLUME) || defined(SINGLE_BUFFER)
  151. static FLStatus mtlDefragment (MTL *pvol, long FAR2 *sectorsNeeded);
  152. #ifdef ENVIRONMENT_VARS
  153. static FLStatus mtlDefragmentAlt (MTL *pvol, long FAR2 *sectorsNeeded);
  154. #endif /* ENVIRNOMETN_VARS */
  155. #endif /* DEFRAGMENT_VOLUME || SINGLE_BUFFER */
  156. static void mtlUnmount (MTL *pvol);
  157. #ifdef FORMAT_VOLUME
  158. static FLStatus mtlFormat (unsigned volNo, TLFormatParams* formatParams,
  159. FLFlash *flash);
  160. #endif /* FORMAT_VOLUME */
  161. static FLStatus mtlWriteSector (MTL *pvol, SectorNo sectorNo,
  162. void FAR1 *fromAddress);
  163. static FLStatus mtlDeleteSector (MTL *pvol, SectorNo sectorNo,
  164. SectorNo noOfSectors);
  165. static FLStatus mtlInfo (MTL *pvol, TLInfo *tlInfo);
  166. static FLStatus mtlSetBusy (MTL *pvol, FLBoolean state);
  167. static SectorNo mtlSectorsInVolume (MTL *pvol);
  168. static const void FAR0 *mtlMapSector (MTL *pvol, SectorNo sectorNo,
  169. CardAddress *physAddress);
  170. #ifdef HW_PROTECTION
  171. static FLStatus mtlProtection(FLFunctionNo callType,
  172. IOreq FAR2* ioreq, FLFlash* flash);
  173. #endif /* HW_PROTECTION */
  174. static FLStatus mtlPreMount(FLFunctionNo callType, IOreq FAR2* ioreq ,
  175. FLFlash* flash,FLStatus* status);
  176. /* -------------------------------------------------------------------------- *
  177. * *
  178. * m t l S p l i t I O *
  179. * *
  180. * Setup I/O vector for splitting I/O request among physical devices. *
  181. * *
  182. * Parameters : *
  183. * *
  184. * pvol : Pointer identifying drive *
  185. * startSector : starting sector # (zero-based) *
  186. * sectors : total number of sectors *
  187. * iov : I/O vector to setup *
  188. * *
  189. * Returns : *
  190. * *
  191. * flOK on success, otherwise respective error code. *
  192. * *
  193. * -------------------------------------------------------------------------- */
  194. static FLStatus mtlSplitIO (MTL *pvol, SectorNo startSector, SectorNo sectors,
  195. tMTLiov *iov)
  196. {
  197. SectorNo devFirstSectNo;
  198. SectorNo devLastSectNo;
  199. int iDev;
  200. /* check 'pvol' for sanity */
  201. if (pvol != &mvol)
  202. return flBadDriveHandle;
  203. /* clear I/O vector */
  204. for (iDev = 0; iDev < SOCKETS; iDev++) {
  205. iov[iDev].sectors = (SectorNo) 0;
  206. iov[iDev].startSector = (SectorNo)(-1);
  207. }
  208. /* split I/O operation among physical devices */
  209. devFirstSectNo = (SectorNo) 0;
  210. for (iDev = 0; (iDev < noOfSockets) && (sectors > ((SectorNo) 0)); iDev++) {
  211. devLastSectNo = devFirstSectNo + (mpS(pvol,iDev) - ((SectorNo) 1));
  212. if ((startSector >= devFirstSectNo) && (startSector <= devLastSectNo)) {
  213. iov[iDev].startSector = startSector - devFirstSectNo + FL_MTL_HIDDEN_SECTORS;
  214. iov[iDev].sectors = devLastSectNo - startSector + ((SectorNo) 1);
  215. startSector = devLastSectNo + ((SectorNo) 1);
  216. if (sectors <= iov[iDev].sectors) {
  217. iov[iDev].sectors = sectors;
  218. startSector = (SectorNo) 0;
  219. sectors = (SectorNo) 0;
  220. }
  221. else {
  222. sectors -= iov[iDev].sectors;
  223. }
  224. }
  225. devFirstSectNo = devLastSectNo + ((SectorNo) 1);
  226. }
  227. if (sectors > ((SectorNo) 0)) {
  228. DEBUG_PRINT(("Debug: can't split I/O request among physical devices.\n"));
  229. return flNoSpaceInVolume;
  230. }
  231. return flOK;
  232. }
  233. /* -------------------------------------------------------------------------- *
  234. * *
  235. * m t l M a p S e c t o r *
  236. * *
  237. * TL's standard 'map one sector' routine. *
  238. * *
  239. * Parameters : *
  240. * *
  241. * pvol : Pointer identifying drive *
  242. * sectorNo : sector # to map (zero-based) *
  243. * physAddress : optional pointer to receive sector's physical *
  244. * address on the media *
  245. * *
  246. * Returns : *
  247. * *
  248. * flOK on success, otherwise respective error code. *
  249. * *
  250. * -------------------------------------------------------------------------- */
  251. static const void FAR0 *mtlMapSector (MTL *pvol, SectorNo sectorNo,
  252. CardAddress *physAddress)
  253. {
  254. SectorNo sectorsToMap;
  255. tMTLiov iov[SOCKETS];
  256. int iDev;
  257. /* pass call to the TL of the respective underlaying physical device */
  258. sectorsToMap = (SectorNo) 1;
  259. if (mtlSplitIO(pvol, sectorNo, sectorsToMap, iov) != flOK)
  260. return NULL;
  261. for (iDev = 0; iDev < noOfSockets; iDev++) {
  262. if (iov[iDev].sectors != ((SectorNo) 0)) {
  263. return mpT(pvol,iDev).mapSector (mpT(pvol,iDev).rec,
  264. iov[iDev].startSector, physAddress);
  265. }
  266. }
  267. return NULL;
  268. }
  269. /* -------------------------------------------------------------------------- *
  270. * *
  271. * m t l W r i t e *
  272. * *
  273. * Split call to write multiple consequitive sectors among TLs of the *
  274. * underlaying physical devices. *
  275. * *
  276. * Parameters : *
  277. * *
  278. * pvol : Pointer identifying drive *
  279. * startSector : starting sector # (zero-based) *
  280. * pSectorsToWrite : on entry - total number of sectors to write *
  281. * on exit - total number of sectors written *
  282. * buf : buffer containing data to write to the media *
  283. * *
  284. * Returns : *
  285. * *
  286. * flOK on success, otherwise respective error code. *
  287. * *
  288. * -------------------------------------------------------------------------- */
  289. static FLStatus mtlWrite (MTL *pvol, SectorNo startSector,
  290. SectorNo *pSectorsToWrite, void FAR1 *buf)
  291. {
  292. tMTLiov iov[SOCKETS];
  293. int iDev;
  294. /* split call among TLs of the underlaying physical devices */
  295. checkStatus( mtlSplitIO(pvol, startSector, *pSectorsToWrite, iov) );
  296. for (iDev = 0; iDev < noOfSockets; iDev++) {
  297. if (iov[iDev].sectors != ((SectorNo) 0)) {
  298. checkStatus( mpT(pvol,iDev).writeSector(mpT(pvol,iDev).rec,
  299. iov[iDev].startSector,buf) );
  300. *pSectorsToWrite -= iov[iDev].sectors;
  301. buf = BYTE_ADD_FAR(buf,(CardAddress)iov[iDev].sectors << SECTOR_SIZE_BITS);
  302. }
  303. }
  304. if (*pSectorsToWrite != ((SectorNo) 0))
  305. return flIncomplete;
  306. return flOK;
  307. }
  308. /* -------------------------------------------------------------------------- *
  309. * *
  310. * m t l W r i t e S e c t o r *
  311. * *
  312. * TL's standard 'write one sector' routine. *
  313. * *
  314. * Parameters : *
  315. * *
  316. * pvol : Pointer identifying drive *
  317. * sectorNo : sector # to write to (zero-based) *
  318. * fromAddress : buffer containing data to write to the media *
  319. * *
  320. * Returns : *
  321. * *
  322. * flOK on success, otherwise respective error code. *
  323. * *
  324. * -------------------------------------------------------------------------- */
  325. static FLStatus mtlWriteSector (MTL *pvol, SectorNo sectorNo, void FAR1 *fromAddress)
  326. {
  327. SectorNo sectorsToWrite = (SectorNo) 1;
  328. /* pass call to the TL of the respective underlaying physical device */
  329. checkStatus( mtlWrite(pvol, sectorNo, &sectorsToWrite, (char FAR1 *)fromAddress) );
  330. if (sectorsToWrite != ((SectorNo) 0))
  331. return flIncomplete;
  332. return flOK;
  333. }
  334. /* -------------------------------------------------------------------------- *
  335. * *
  336. * m t l D e l e t e S e c t o r *
  337. * *
  338. * TL's standard 'delete range of sectors' routine. *
  339. * *
  340. * Parameters : *
  341. * *
  342. * pvol : Pointer identifying drive *
  343. * startSector : starting sector # (zero-based) *
  344. * sectors : total number of sectors to delete *
  345. * *
  346. * Returns : *
  347. * *
  348. * flOK on success, otherwise respective error code. *
  349. * *
  350. * -------------------------------------------------------------------------- */
  351. static FLStatus mtlDeleteSector (MTL *pvol, SectorNo startSector,
  352. SectorNo sectors)
  353. {
  354. tMTLiov iov[SOCKETS];
  355. int iDev;
  356. /* split call among TLs of the underlaying physical devices */
  357. checkStatus( mtlSplitIO(pvol, startSector, sectors, iov) );
  358. for (iDev = 0; iDev < noOfSockets; iDev++) {
  359. if (iov[iDev].sectors != ((SectorNo) 0)) {
  360. checkStatus( mpT(pvol,iDev).deleteSector(mpT(pvol,iDev).rec,
  361. iov[iDev].startSector,
  362. iov[iDev].sectors) );
  363. }
  364. sectors -= iov[iDev].sectors;
  365. }
  366. if (sectors != ((SectorNo) 0))
  367. return flIncomplete;
  368. return flOK;
  369. }
  370. /* -------------------------------------------------------------------------- *
  371. * *
  372. * m t l I n f o *
  373. * *
  374. * TL's standard 'get info' routine. *
  375. * *
  376. * Parameters : *
  377. * *
  378. * pvol : Pointer identifying drive *
  379. * pTLinfo : pointer to the TLInfo structure to fill in *
  380. * *
  381. * Returns : *
  382. * *
  383. * flOK on success, otherwise respective error code. *
  384. * *
  385. * -------------------------------------------------------------------------- */
  386. static FLStatus mtlInfo (MTL *pvol, TLInfo *pTLinfo)
  387. {
  388. TLInfo tmp;
  389. int iDev;
  390. /* check 'pvol' for sanity */
  391. if (pvol != &mvol)
  392. return flBadDriveHandle;
  393. pTLinfo->sectorsInVolume = pvol->virtualSectors;
  394. /*
  395. * The 'eraseCycles' is reported as a sum of that of all the underlaying
  396. * physical devices. The 'bootAreaSize' is set to the one of the 1st
  397. * underlaying physical device.
  398. */
  399. pTLinfo->bootAreaSize = (dword) 0;
  400. pTLinfo->eraseCycles = (dword) 0;
  401. for (iDev = 0; iDev < noOfSockets; iDev++) {
  402. if (mpT(pvol,iDev).getTLInfo != NULL) {
  403. checkStatus( mpT(pvol,iDev).getTLInfo(mpT(pvol,iDev).rec, &tmp) );
  404. pTLinfo->eraseCycles += tmp.eraseCycles;
  405. if (iDev == 0)
  406. pTLinfo->bootAreaSize = tmp.bootAreaSize;
  407. }
  408. }
  409. return flOK;
  410. }
  411. /* -------------------------------------------------------------------------- *
  412. * *
  413. * m t l S e t B u s y *
  414. * *
  415. * TL's standard routine which is called at the beginning and and the end of *
  416. * the block device operation. *
  417. * *
  418. * Parameters : *
  419. * *
  420. * pvol : Pointer identifying drive *
  421. * state : FL_ON - start of block device operation *
  422. * FL_OFF - end of block device operation *
  423. * *
  424. * Returns : *
  425. * *
  426. * flOK on success, otherwise respective error code. *
  427. * *
  428. * -------------------------------------------------------------------------- */
  429. static FLStatus mtlSetBusy (MTL *pvol, FLBoolean state)
  430. {
  431. int iDev;
  432. /* check 'pvol' for sanity */
  433. if (pvol != &mvol)
  434. return flBadDriveHandle;
  435. /* broadcast this call to TLs of all the underlaying physical devices */
  436. for (iDev = 0; iDev < noOfSockets; iDev++) {
  437. if (mpT(pvol,iDev).tlSetBusy != NULL) {
  438. checkStatus( mpT(pvol,iDev).tlSetBusy(mpT(pvol,iDev).rec, state) );
  439. }
  440. }
  441. return flOK;
  442. }
  443. /* -------------------------------------------------------------------------- *
  444. * *
  445. * m t l S e c t o r s I n V o l u m e *
  446. * *
  447. * Report the total number of sectors in the volume. *
  448. * *
  449. * Parameters : *
  450. * *
  451. * pvol : Pointer identifying drive *
  452. * *
  453. * Returns : *
  454. * *
  455. * Total number of sectors in the volume, or zero in case of error. *
  456. * *
  457. * -------------------------------------------------------------------------- */
  458. static SectorNo mtlSectorsInVolume (MTL *pvol)
  459. {
  460. /* check 'pvol' for sanity */
  461. if (pvol != &mvol)
  462. return ((SectorNo) 0);
  463. return pvol->virtualSectors;
  464. }
  465. #if defined(DEFRAGMENT_VOLUME) || defined(SINGLE_BUFFER)
  466. /* -------------------------------------------------------------------------- *
  467. * *
  468. * m t l D e f r a g m e n t *
  469. * *
  470. * TL's standard garbage collection / volume defragmentaion routine. *
  471. * *
  472. * Note : The garbage collection algorithm will try and free the required *
  473. * number of sectors on each of the combined devices. *
  474. * *
  475. * Parameters : *
  476. * *
  477. * pvol : Pointer identifying drive *
  478. * sectorsNeeded : On entry - minimum number of free sectors that *
  479. * are requested to be on the media upon call *
  480. * completion. Two special cases: zero for *
  481. * complete defragmentation of all the physical *
  482. * devices, and '-1' for minimal defragmentation *
  483. * of each physical device. *
  484. * On exit - actual number of free sectors on *
  485. * the media. *
  486. * Returns : *
  487. * *
  488. * flOK on success, otherwise respective error code. *
  489. * *
  490. * -------------------------------------------------------------------------- */
  491. static FLStatus mtlDefragment (MTL *pvol, long FAR2 *sectorsNeeded)
  492. {
  493. long freeSectors;
  494. FLStatus status;
  495. int iDev;
  496. long tmp;
  497. FLStatus tmpStatus;
  498. /* check args for sanity */
  499. if (pvol != &mvol)
  500. return flBadDriveHandle;
  501. /*
  502. * Pass call to the TL of the respective underlaying physical device.
  503. * Count total number of free sectors on all devices.
  504. */
  505. status = flOK;
  506. freeSectors = (long) 0;
  507. for (iDev = 0; iDev < noOfSockets; iDev++) {
  508. if (mpT(pvol,iDev).defragment != NULL) {
  509. switch (*sectorsNeeded) {
  510. case ((long)(-1)): /* minimal defragmenation */
  511. tmp = (long)(-1);
  512. break;
  513. case ((long) 0): /* complete defragmenation */
  514. tmp = mpS(pvol,iDev);
  515. break;
  516. default: /* partial defragmentation */
  517. if (*sectorsNeeded < (long) mpS(pvol,iDev))
  518. {
  519. tmp = *sectorsNeeded;
  520. }
  521. else
  522. {
  523. tmp = mpS(pvol,iDev); /* complete defragmentation */
  524. }
  525. break;
  526. }
  527. tmpStatus = mpT(pvol,iDev).defragment (mpT(pvol,iDev).rec, ((long FAR2 *) &tmp));
  528. if (tmpStatus != flBadFormat)
  529. {
  530. freeSectors += tmp;
  531. }
  532. else
  533. {
  534. status = tmpStatus;
  535. }
  536. }
  537. }
  538. *sectorsNeeded = freeSectors;
  539. if (*sectorsNeeded == ((long) 0))
  540. return flNoSpaceInVolume;
  541. return status;
  542. }
  543. #ifdef ENVIRONMENT_VARS
  544. /* -------------------------------------------------------------------------- *
  545. * *
  546. * m t l D e f r a g m e n t A l t *
  547. * *
  548. * TL's alternative garbage collection / volume defragmentaion routine. *
  549. * *
  550. * Note : The garbage collection algorithm Perform quick gurbage collections *
  551. * from drive 0 until there is no more "garbage" to collect or until *
  552. * there is enough clean space. If the specified clean spage was not *
  553. * achieved try the next device. *
  554. * While this method is faster then the standard defragment, it does *
  555. * not gurantee that when the clean sectors are needed they will be *
  556. * available. This is becuase write operation on MTL will directed *
  557. * the write operation to a specific device according to the specifed *
  558. * virtual sector number (not necceseraly starting from device #0). *
  559. * *
  560. * Parameters : *
  561. * *
  562. * pvol : Pointer identifying drive *
  563. * sectorsNeeded : On entry - minimum number of free sectors that *
  564. * are requested to be on the media upon call *
  565. * completion. Two special cases: zero for *
  566. * complete defragmentation of all the physical *
  567. * devices, and '-1' for minimal defragmentation *
  568. * of each physical device. *
  569. * On exit - actual number of free sectors on *
  570. * the media. *
  571. * Returns : *
  572. * *
  573. * flOK on success, otherwise respective error code. *
  574. * *
  575. * -------------------------------------------------------------------------- */
  576. static FLStatus mtlDefragmentAlt (MTL *pvol, long FAR2 *sectorsNeeded)
  577. {
  578. long freeSectors;
  579. FLBoolean keepWorking;
  580. FLBoolean driveDone[SOCKETS];
  581. long freeSectorsOnDrive[SOCKETS];
  582. FLStatus status;
  583. int iDev;
  584. FLStatus tmpStatus;
  585. long tmp;
  586. /* check args for sanity */
  587. if (pvol != &mvol)
  588. return flBadDriveHandle;
  589. /*
  590. * Pass call to the TL of the respective underlaying physical device.
  591. * Count total number of free sectors on all devices.
  592. */
  593. status = flOK;
  594. freeSectors = (long) 0;
  595. if ((*sectorsNeeded == ((long) -1)) || (*sectorsNeeded == (long)0)) {
  596. /* Either total or minimal defragmentation of all physical devices. */
  597. for (iDev = 0; iDev < noOfSockets; iDev++) {
  598. if (mpT(pvol,iDev).defragment != NULL) {
  599. if (*sectorsNeeded == ((long) -1))
  600. tmp = (long)(-1); /* minimal defragmenation */
  601. else
  602. tmp = mpS(pvol,iDev); /* complete defragmenation */
  603. tmpStatus = mpT(pvol,iDev).defragment (mpT(pvol,iDev).rec, ((long FAR2 *) &tmp));
  604. if (tmpStatus != flBadFormat) {
  605. freeSectors += tmp;
  606. }
  607. else {
  608. DEBUG_PRINT(("Debug: Error defragmenting physical device.\n"));
  609. status = tmpStatus;
  610. }
  611. }
  612. }
  613. }
  614. else { /* Partial defragmentaion of the MTL volume */
  615. for (iDev = 0; iDev < SOCKETS; iDev++) {
  616. freeSectorsOnDrive[iDev] = (long) 0;
  617. if ((iDev < noOfSockets) && (mpT(pvol,iDev).defragment != NULL))
  618. driveDone[iDev] = FALSE;
  619. else
  620. driveDone[iDev] = TRUE;
  621. }
  622. keepWorking = TRUE;
  623. while (keepWorking == TRUE) {
  624. keepWorking = FALSE;
  625. for (iDev = 0; iDev < noOfSockets; iDev++) {
  626. /*
  627. * Do minimal defragmentation of this physical device. If we
  628. * have got error, or haven't gained any more free sectors,
  629. * this physical device is done. If that is the case for all
  630. * physical devices, the MTL defragmentation is done. If the
  631. * required number of free sectors has been reached, MTL
  632. * defragmentation is done.
  633. */
  634. if (driveDone[iDev] != TRUE) {
  635. tmp = (long) -1;
  636. tmpStatus = mpT(pvol,iDev).defragment (mpT(pvol,iDev).rec, ((long FAR2 *) &tmp));
  637. if (tmpStatus != flBadFormat) {
  638. if (freeSectorsOnDrive[iDev] < tmp) {
  639. /* got few more free sectors on that physical device */
  640. keepWorking = TRUE;
  641. freeSectors += (tmp - freeSectorsOnDrive[iDev]);
  642. freeSectorsOnDrive[iDev] = tmp;
  643. if (freeSectors >= *sectorsNeeded) {
  644. /* required number of free sectors reached */
  645. keepWorking = FALSE;
  646. break;
  647. }
  648. }
  649. else { /* didn't gain any free sectors */
  650. driveDone[iDev] = TRUE;
  651. }
  652. }
  653. else {
  654. DEBUG_PRINT(("Debug: Error defragmenting physical device.\n"));
  655. driveDone[iDev] = TRUE;
  656. status = tmpStatus;
  657. }
  658. }
  659. } /* for (iDev) */
  660. } /* while (keepWorking */
  661. }
  662. *sectorsNeeded = freeSectors;
  663. if (*sectorsNeeded == ((long) 0))
  664. return flNoSpaceInVolume;
  665. return status;
  666. }
  667. #endif /* ENVIRONEMENT_VARS */
  668. #endif /* DEFRAGMENT_VOLUME || SINGLE_BUFFER */
  669. #ifdef HW_PROTECTION
  670. /* -------------------------------------------------------------------------- *
  671. * *
  672. * m t l P r o t e c t i o n *
  673. * *
  674. * TL's protection routine. *
  675. * *
  676. * Parameters : *
  677. * *
  678. * callType : pre mount protection operation type. *
  679. * ioreq : pointer to the structure containing i\o fields *
  680. * flash : pointer to the flash record of device #0
  681. * *
  682. * Returns : *
  683. * *
  684. * flOK on success, otherwise respective error code. *
  685. * *
  686. * -------------------------------------------------------------------------- */
  687. static FLStatus mtlProtection(FLFunctionNo callType, IOreq FAR2* ioreq,
  688. FLFlash* flash)
  689. {
  690. FLSocket *socket;
  691. FLStatus status;
  692. FLStatus callStatus;
  693. FLFlash tmpFlash;
  694. int iTL;
  695. int iDev = 0;
  696. unsigned flags = 0;
  697. /*
  698. * Do flash recognition and identify protection attributes for devices
  699. * #0 .. (mvol.noOfSockets - 1) verifing that the operation can be
  700. * preformed and that the protection attributes of all the devieces
  701. * match.
  702. */
  703. tffscpy(&tmpFlash,flash,sizeof (tmpFlash)); /* Use the given flash */
  704. while(1)
  705. {
  706. /* The tmpFlash record is already intialized Try all the TLs */
  707. status = flUnknownMedia;
  708. for (iTL = 1;(iTL < mvol.noOfTLs) && (status == flUnknownMedia); iTL++)
  709. {
  710. if ((tlTable[iTL].formatRoutine == NULL) || /* TL filter */
  711. (tlTable[iTL].preMountRoutine == NULL))
  712. continue;
  713. status = tlTable[iTL].preMountRoutine(FL_PROTECTION_GET_TYPE,
  714. ioreq,&tmpFlash,&callStatus);
  715. }
  716. if (status != flOK)
  717. {
  718. DEBUG_PRINT(("Debug: no TL recognized the device, MTL protection aborted.\n"));
  719. return flFeatureNotSupported;
  720. }
  721. if (callStatus != flOK)
  722. {
  723. return callStatus;
  724. }
  725. /* Check protection attributes */
  726. if ((ioreq->irFlags & PROTECTABLE) == 0)
  727. return flNotProtected;
  728. if (iDev == 0) /* First device */
  729. {
  730. flags = ioreq->irFlags;
  731. }
  732. else
  733. {
  734. /* Diffrent protection attributes on diffrent devices */
  735. if (ioreq->irFlags != flags)
  736. return flMultiDocContrediction;
  737. }
  738. /* Validity check for the proper function call */
  739. switch(callType)
  740. {
  741. case FL_PROTECTION_GET_TYPE: /* Identify protection */
  742. if (iDev == noOfSockets-1)
  743. return flOK;
  744. break;
  745. case FL_PROTECTION_SET_LOCK: /* Change protection */
  746. case FL_PROTECTION_CHANGE_KEY:
  747. case FL_PROTECTION_CHANGE_TYPE:
  748. if (!(flags & CHANGEABLE_PROTECTION ) ||
  749. (tmpFlash.protectionBoundries == NULL ) ||
  750. (tmpFlash.protectionSet == NULL ))
  751. {
  752. return flUnchangeableProtection;
  753. }
  754. default: /* Insert and remove Key */
  755. break;
  756. }
  757. /* Identify flash for next device */
  758. if (iDev < noOfSockets - 1)
  759. {
  760. iDev++;
  761. socket = flSocketOf (iDev);
  762. /* Identify */
  763. status = flIdentifyFlash (socket, &tmpFlash);
  764. if ((status != flOK) && (status != flUnknownMedia))
  765. {
  766. DEBUG_PRINT(("Debug: no MTD recognized the device, MTL protection aborted.\n"));
  767. return status;
  768. }
  769. }
  770. else
  771. break;
  772. } /* for(iDev) */
  773. /*
  774. * Pass call to the TL of the respective underlaying physical device.
  775. * Do flash recognition try all TLs registered in tlTable[]. Assume MTL
  776. * is in tlTable[0], so skip it. Skip all the TL filters as well.
  777. */
  778. for (iDev = 0, callStatus = flOK;
  779. (iDev < noOfSockets) && (callStatus == flOK); iDev++)
  780. {
  781. socket = flSocketOf (iDev);
  782. /* Identify */
  783. status = flIdentifyFlash (socket, &tmpFlash);
  784. if ((status != flOK) && (status != flUnknownMedia))
  785. {
  786. DEBUG_PRINT(("Debug: no MTD recognized the device, MTL protection aborted.\n"));
  787. return status;
  788. }
  789. /* Try all the TLs */
  790. status = flUnknownMedia;
  791. for (iTL = 1; (iTL < mvol.noOfTLs) && (status == flUnknownMedia); iTL++)
  792. {
  793. if ((tlTable[iTL].formatRoutine == NULL) || /* TL filter */
  794. (tlTable[iTL].preMountRoutine == NULL))
  795. continue;
  796. status = tlTable[iTL].preMountRoutine(callType,ioreq,
  797. &tmpFlash,&callStatus);
  798. }
  799. if (status != flOK)
  800. {
  801. DEBUG_PRINT(("Debug: no TL recognized the device, MTL protection aborted.\n"));
  802. return flFeatureNotSupported;
  803. }
  804. }
  805. return callStatus;
  806. }
  807. #endif /* HW_PROTECTION */
  808. /* -------------------------------------------------------------------------- *
  809. * *
  810. * m t l P r e M o u n t *
  811. * *
  812. * TL's standard volume pre mount routine. *
  813. * *
  814. * Parameters : *
  815. * *
  816. * callType : pre mount operation type. *
  817. * ioreq : pointer to the structure containing i\o fields *
  818. * flash : MTD attached to the 1st underlaying physical *
  819. * device *
  820. * *
  821. * Returns : *
  822. * *
  823. * The routine always return flOK in order to stop other TLs from trying *
  824. * to perform the operation. The true status code is returned in the *
  825. * 'status' parameter. flOK on success, otherwise respective error code. * *
  826. * *
  827. * -------------------------------------------------------------------------- */
  828. static FLStatus mtlPreMount(FLFunctionNo callType, IOreq FAR2* ioreq ,
  829. FLFlash* flash,FLStatus* status)
  830. {
  831. /* arg sanity check */
  832. if (ioreq->irHandle != 0)
  833. {
  834. DEBUG_PRINT(("Debug: can't execute, MTL must address first volume of socket 0.\n"));
  835. *status = flBadParameter;
  836. return flOK;
  837. }
  838. switch (callType)
  839. {
  840. case FL_COUNT_VOLUMES:
  841. /* Count VOLUMES routine. We assume that while MTL is mounted only
  842. * one device of each socket can be mounted.
  843. */
  844. ioreq->irFlags = 1;
  845. *status = flOK;
  846. break;
  847. /* Protection rouines. Call each of the underlaying physical devices. */
  848. #ifdef HW_PROTECTION
  849. case FL_PROTECTION_GET_TYPE:
  850. case FL_PROTECTION_SET_LOCK:
  851. case FL_PROTECTION_CHANGE_KEY:
  852. case FL_PROTECTION_CHANGE_TYPE:
  853. case FL_PROTECTION_REMOVE_KEY:
  854. case FL_PROTECTION_INSERT_KEY:
  855. *status = mtlProtection(callType,ioreq,flash);
  856. break;
  857. #endif /* HW_PROTECTION */
  858. /* Write Bad Block Table. Call each of the underlaying physical device. */
  859. case FL_WRITE_BBT:
  860. *status = flFeatureNotSupported/*mtlWriteBBT(ioreq)*/;
  861. return flFeatureNotSupported;
  862. default:
  863. return flBadParameter;
  864. }
  865. DEBUG_PRINT(("Debug: MTL premount succeeded.\n"));
  866. return flOK;
  867. }
  868. /* -------------------------------------------------------------------------- *
  869. * *
  870. * m t l U n m o u n t *
  871. * *
  872. * TL's standard volume unmount routine. *
  873. * *
  874. * Parameters : *
  875. * *
  876. * pvol : Pointer identifying drive *
  877. * *
  878. * Returns : *
  879. * *
  880. * none *
  881. * *
  882. * -------------------------------------------------------------------------- */
  883. static void mtlUnmount (MTL *pvol)
  884. {
  885. int iDev;
  886. /* check 'pvol' for sanity */
  887. if (pvol != &mvol)
  888. return;
  889. /* broadcast this call to TLs of all the underlaying physical devices */
  890. for (iDev = 0; iDev < noOfSockets; iDev++) {
  891. if (mpT(pvol,iDev).dismount != NULL) {
  892. mpT(pvol,iDev).dismount (mpT(pvol,iDev).rec);
  893. }
  894. }
  895. /* Return the real number of drives */
  896. noOfDrives = mvol.noOfDrives;
  897. DEBUG_PRINT(("Debug: MTL dismounted succeeded.\n"));
  898. }
  899. /* -------------------------------------------------------------------------- *
  900. * *
  901. * m t l M o u n t *
  902. * *
  903. * TL's standard volume mount routine. *
  904. * *
  905. * Parameters : *
  906. * *
  907. * volNo : volume #, must be zero *
  908. * tl : pointer to TL structure to fill in *
  909. * flash : MTD attached to the 1st underlaying physical *
  910. * device *
  911. * forCallback : MTD for power on callback (not used). *
  912. * *
  913. * Returns : *
  914. * *
  915. * flOK on success, otherwise respective error code. *
  916. * *
  917. * -------------------------------------------------------------------------- */
  918. static FLStatus mtlMount (unsigned volNo, TL *tl, FLFlash *flash,
  919. FLFlash **forCallback)
  920. {
  921. FLFlash tmpFlash;
  922. FLFlash *volForCallback;
  923. FLSocket *socket;
  924. FLStatus status = flUnknownMedia;
  925. int iTL;
  926. int iDev = 0;
  927. /* Arg sanity check */
  928. if (volNo != ((unsigned) 0)) {
  929. DEBUG_PRINT(("Debug: can't mount, MTL volume # is not zero.\n"));
  930. return flBadParameter;
  931. }
  932. /*
  933. * Do TL mount for device #0. Routine flIdentifyFlash() has already been
  934. * called for this device (see arguement 'flash')
  935. */
  936. volForCallback = NULL;
  937. /* mT(0).recommendedClusterInfo = NULL;
  938. mT(0).writeMultiSector = NULL;
  939. mT(0).readSectors = NULL; */
  940. /*
  941. * Try all TLs registered in tlTable[]. Assume MTL is in tlTable[0], so
  942. * skip it. Skip all the TL filters as well.
  943. */
  944. for (iTL = 1; (iTL < mvol.noOfTLs) && (status != flOK); iTL++) {
  945. if (tlTable[iTL].formatRoutine == NULL) /* TL filter */
  946. continue;
  947. status = tlTable[iTL].mountRoutine (0, &mT(0), flash, &volForCallback);
  948. }
  949. if (status != flOK) {
  950. DEBUG_PRINT(("Debug: no TL recognized device #0, MTL mount aborted.\n"));
  951. return status;
  952. }
  953. mP(iDev) = (dword)(flash->chipSize * flash->noOfChips); /* Physical size */
  954. if (volForCallback)
  955. volForCallback->setPowerOnCallback (volForCallback);
  956. /*
  957. * Do flash recognition and TL mount for devices #1 .. (mvol.noOfSockets - 1).
  958. * First call flIdentifyFlash() to find MTD, then try all TLs registered
  959. * in tlTable[]. Assume MTL is in tlTable[0], so skip it. Skip all the
  960. * TL filters as well.
  961. */
  962. for (iDev = 1; iDev < noOfSockets; iDev++) {
  963. socket = flSocketOf (iDev);
  964. status = flIdentifyFlash (socket, &tmpFlash);
  965. if ((status != flOK) && (status != flUnknownMedia)) {
  966. DEBUG_PRINT(("Debug: no MTD recognized the device, MTL mount aborted.\n"));
  967. goto exitMount;
  968. }
  969. volForCallback = NULL;
  970. mP(iDev) = (dword)(tmpFlash.chipSize * tmpFlash.noOfChips); /* Physical size */
  971. mT(iDev).partitionNo = 0;
  972. mT(iDev).socketNo = (byte)iDev;
  973. /* mT(iDev).recommendedClusterInfo = NULL;
  974. mT(iDev).writeMultiSector = NULL;
  975. mT(iDev).readSectors = NULL;*/
  976. status = flUnknownMedia;
  977. for (iTL = 1; (iTL < mvol.noOfTLs) && (status != flOK); iTL++) {
  978. if (tlTable[iTL].formatRoutine == NULL) /* TL filter */
  979. continue;
  980. status = tlTable[iTL].mountRoutine (iDev, &mT(iDev), &tmpFlash, &volForCallback);
  981. }
  982. if (status != flOK) {
  983. DEBUG_PRINT(("Debug: no TL recognized the device, MTL mount aborted.\n"));
  984. goto exitMount;
  985. }
  986. if (volForCallback)
  987. volForCallback->setPowerOnCallback (volForCallback);
  988. } /* for (iDev) */
  989. /* Count the total of virtual sectors across all devices */
  990. mvol.virtualSectors = (SectorNo) 0;
  991. for (iDev = 0; iDev < SOCKETS; iDev++) {
  992. mS(iDev) = (SectorNo) 0;
  993. if (iDev >= noOfSockets)
  994. continue;
  995. mS(iDev) = mT(iDev).sectorsInVolume (mT(iDev).rec) - FL_MTL_HIDDEN_SECTORS;
  996. mvol.virtualSectors += mS(iDev);
  997. }
  998. exitMount:
  999. if (status != flOK)
  1000. {
  1001. /* If one of the devices failed mount dismount all devices */
  1002. for (;iDev >=0;iDev--)
  1003. {
  1004. if (mT(iDev).dismount != NULL)
  1005. mT(iDev).dismount(mT(iDev).rec);
  1006. }
  1007. DEBUG_PRINT(("Debug: MTL mount failed.\n"));
  1008. return status;
  1009. }
  1010. /*
  1011. * Attach MTL-specific record to 'tl'. This record will be passed
  1012. * as the first arguement to all TL calls.
  1013. */
  1014. tl->rec = &mvol;
  1015. /* Fill in the TL access methods */
  1016. tl->mapSector = mtlMapSector;
  1017. tl->writeSector = mtlWriteSector;
  1018. tl->deleteSector = mtlDeleteSector;
  1019. #if defined(DEFRAGMENT_VOLUME) || defined(SINGLE_BUFFER)
  1020. #ifdef ENVIRONMENT_VARS
  1021. if (flMTLdefragMode == FL_MTL_DEFRAGMENT_SEQUANTIAL)
  1022. {
  1023. tl->defragment = mtlDefragmentAlt;
  1024. }
  1025. else
  1026. #endif /* ENVIRONMENT_VARS */
  1027. {
  1028. tl->defragment = mtlDefragment;
  1029. }
  1030. #endif
  1031. tl->sectorsInVolume = mtlSectorsInVolume;
  1032. tl->getTLInfo = mtlInfo;
  1033. tl->tlSetBusy = mtlSetBusy;
  1034. tl->dismount = mtlUnmount;
  1035. tl->readBBT = NULL /*mtlReadBBT*/;
  1036. /*
  1037. * The following methods are not supported by NFTL, and have already
  1038. * been set to NULL by flMount(). We just confirm this here.
  1039. */
  1040. tl->writeMultiSector = NULL;
  1041. tl->readSectors = NULL;
  1042. tl->recommendedClusterInfo = NULL;
  1043. /* Fake the no of volume exported by TrueFFS */
  1044. mvol.noOfDrives = noOfDrives;
  1045. noOfDrives = 1;
  1046. DEBUG_PRINT(("Debug: MTL mount succeeded.\n"));
  1047. return status;
  1048. }
  1049. #ifdef FORMAT_VOLUME
  1050. /* -------------------------------------------------------------------------- *
  1051. * *
  1052. * m t l P r o g r e s s C a l l B a c k *
  1053. * *
  1054. * Extends the given format routine to report the full media size. *
  1055. * *
  1056. * Parameters : *
  1057. * *
  1058. * totalUnitsToFormat : total units needed to format *
  1059. * totalUnitsFormattedSoFar : unit formated so far. *
  1060. * *
  1061. * Notes *
  1062. * *
  1063. * 1) arguments 0 and 0 initializes the total unit counter to 0. *
  1064. * 2) arguments -1 and -1 indicates the ending of the last device. *
  1065. * * *
  1066. * Returns : *
  1067. * *
  1068. * flOK on success, otherwise respective error code. *
  1069. * -------------------------------------------------------------------------- */
  1070. static FLStatus mtlProgressCallback(word totalUnitsToFormat,
  1071. word totalUnitsFormattedSoFar)
  1072. {
  1073. static int lastTotal;
  1074. static int lastDevice;
  1075. /* Initialize lastTotal counter */
  1076. if ((totalUnitsToFormat == 0) && (totalUnitsFormattedSoFar == 0))
  1077. {
  1078. lastTotal = 0;
  1079. lastDevice = 0;
  1080. return flOK;
  1081. }
  1082. /* Indicate a new device is being formated */
  1083. if ((totalUnitsToFormat == 0) && (totalUnitsFormattedSoFar == 0xffff))
  1084. {
  1085. lastTotal += lastDevice;
  1086. return flOK;
  1087. }
  1088. /* Call original call back routine */
  1089. lastDevice = totalUnitsToFormat;
  1090. if (globalProgressCallback == NULL)
  1091. {
  1092. return flOK;
  1093. }
  1094. else
  1095. {
  1096. return globalProgressCallback((word)(lastTotal + totalUnitsToFormat),
  1097. (word)(lastTotal + totalUnitsFormattedSoFar));
  1098. }
  1099. }
  1100. /* -------------------------------------------------------------------------- *
  1101. * *
  1102. * m t l F o r m a t *
  1103. * *
  1104. * TL's standard volume mount routine. *
  1105. * *
  1106. * Parameters : *
  1107. * *
  1108. * volNo : volume #, must be zero *
  1109. * formatParams : pointer to the structure containing format *
  1110. * parameters *
  1111. * flash : MTD attached to the 1st underlaying physical *
  1112. * device *
  1113. * *
  1114. * Returns : *
  1115. * *
  1116. * flOK on success, otherwise respective error code. *
  1117. * *
  1118. * -------------------------------------------------------------------------- *
  1119. * *
  1120. * NOTE. Binary area has 2 possible options: *
  1121. * *
  1122. * - TL_LEAVE_BINARY_AREA is set - binary area is left for all devices *
  1123. * - TL_LEAVE_BINARY_AREA is off - binary area is placed only on the *
  1124. * device #0 *
  1125. * *
  1126. * Handling of 'formatParams.progressCallback' should be improved. *
  1127. * *
  1128. * -------------------------------------------------------------------------- */
  1129. static FLStatus mtlFormat (unsigned volNo, TLFormatParams* formatParams,
  1130. FLFlash *flash)
  1131. {
  1132. FLFlash tmpFlash;
  1133. FLSocket *socket;
  1134. FLStatus status = flUnknownMedia;
  1135. int iTL, iDev;
  1136. /* arg sanity check */
  1137. if (volNo != ((unsigned) 0)) {
  1138. DEBUG_PRINT(("Debug: can't format, MTL socket # is not zero.\n"));
  1139. return flBadParameter;
  1140. }
  1141. if (formatParams->noOfBDTLPartitions > 1){
  1142. DEBUG_PRINT(("Debug: can't format, MTL with more then 1 BDTL volume.\n"));
  1143. return flBadParameter;
  1144. }
  1145. if (formatParams->flags & TL_SINGLE_FLOOR_FORMATTING){
  1146. DEBUG_PRINT(("Debug: can't format, MTL does not support single floor formatting.\n"));
  1147. return flBadParameter;
  1148. }
  1149. /* Initialize the progress call back routine to indicate the agregated
  1150. * size. The actual routine is saved and mtl routine is used.
  1151. */
  1152. globalProgressCallback = formatParams->progressCallback;
  1153. formatParams->progressCallback = mtlProgressCallback; /* Set new routine */
  1154. mtlProgressCallback(0,0); /* Initialize new format operation */
  1155. /*
  1156. * Format device #0. Routine flIdentifyFlash() has already been called
  1157. * for this device (see arguement 'flash'). Try all TLs registered
  1158. * in tlTable[]. Assume MTL is in tlTable[0], so skip it. Skip all the
  1159. * TL filters as well.
  1160. */
  1161. for (iTL = 1; (iTL < mvol.noOfTLs) && (status == flUnknownMedia); iTL++) {
  1162. if (tlTable[iTL].formatRoutine == NULL) /* TL filter */
  1163. continue;
  1164. status = tlTable[iTL].formatRoutine(0, formatParams, flash);
  1165. }
  1166. if (status != flOK) {
  1167. DEBUG_PRINT(("Debug: no TL recognized device #0, MTL format aborted.\n"));
  1168. return status;
  1169. }
  1170. /*
  1171. * Put all 'bootImageLen' and 'exbLen' to the 1st physical device unless
  1172. * TL_LEAVE_BINARY_AREA is specified (which means to keep bootimage area
  1173. * size as is.
  1174. */
  1175. if (!(formatParams->flags & TL_LEAVE_BINARY_AREA))
  1176. {
  1177. formatParams->bootImageLen = (long) 0;
  1178. #ifdef WRITE_EXB_IMAGE
  1179. formatParams->exbLen = 0;
  1180. #endif /* WRITE_EXB_IMAGE */
  1181. formatParams->noOfBinaryPartitions = 0;
  1182. }
  1183. /*
  1184. * Do flash recognition and format for devices #1 .. (mvol.noOfSockets - 1).
  1185. * First call flIdentifyFlash() to find MTD, then try all TLs registered
  1186. * in tlTable[]. Assume MTL is in tlTable[0], so skip it. Skip all the
  1187. * TL filters as well.
  1188. */
  1189. for (iDev = 1; iDev < noOfSockets; iDev++) {
  1190. socket = flSocketOf (iDev);
  1191. status = flIdentifyFlash (socket, &tmpFlash);
  1192. if ((status != flOK) && (status != flUnknownMedia)) {
  1193. DEBUG_PRINT(("Debug: no MTD recognized the device, MTL format aborted.\n"));
  1194. return status;
  1195. }
  1196. mtlProgressCallback(0,0xffff); /* Initialize new device is being formated */
  1197. status = flUnknownMedia;
  1198. for (iTL = 1; (iTL < mvol.noOfTLs) && (status == flUnknownMedia); iTL++)
  1199. {
  1200. if (tlTable[iTL].formatRoutine == NULL) /* TL filter */
  1201. continue;
  1202. status = tlTable[iTL].formatRoutine (iDev, formatParams, &tmpFlash);
  1203. }
  1204. if (status != flOK)
  1205. {
  1206. DEBUG_PRINT(("Debug: no TL recognized the device, MTL format aborted.\n"));
  1207. return status;
  1208. }
  1209. } /* for(iDev) */
  1210. DEBUG_PRINT(("Debug: MTL format succeeded.\n"));
  1211. return flOK;
  1212. }
  1213. #endif /* FORMAT_VOLUME */
  1214. /* -------------------------------------------------------------------------- *
  1215. * *
  1216. * f l m t l U n i n s t a l l *
  1217. * *
  1218. * Removes MTL from the TL table. *
  1219. * *
  1220. * Note: Must be called after the medium was dismounted. *
  1221. * *
  1222. * Parameters : *
  1223. * *
  1224. * none *
  1225. * *
  1226. * Returns : *
  1227. * *
  1228. * flOK on success, otherwise respective error code. *
  1229. * *
  1230. * -------------------------------------------------------------------------- */
  1231. FLStatus flmtlUninstall (void)
  1232. {
  1233. int iTL;
  1234. if (noOfTLs > 0)
  1235. {
  1236. /* search for MTL in tlTable[] */
  1237. for (iTL = 0; iTL < mvol.noOfTLs; iTL++)
  1238. {
  1239. if (tlTable[iTL].mountRoutine == mtlMount)
  1240. break;
  1241. }
  1242. if (iTL < mvol.noOfTLs)
  1243. {
  1244. /* MTL is found in tlTable[iTL], so remove it */
  1245. for (; iTL < (mvol.noOfTLs - 1); iTL ++)
  1246. {
  1247. tlTable[iTL].mountRoutine = tlTable[iTL + 1].mountRoutine;
  1248. tlTable[iTL].formatRoutine = tlTable[iTL + 1].formatRoutine;
  1249. }
  1250. tlTable[mvol.noOfTLs - 1].mountRoutine = NULL;
  1251. tlTable[mvol.noOfTLs - 1].formatRoutine = NULL;
  1252. tlTable[mvol.noOfTLs - 1].preMountRoutine = NULL;
  1253. noOfTLs = mvol.noOfTLs - 1;
  1254. noOfDrives = mvol.noOfDrives;
  1255. }
  1256. }
  1257. return flOK;
  1258. }
  1259. /* -------------------------------------------------------------------------- *
  1260. * *
  1261. * f l m t l I n s t a l l *
  1262. * *
  1263. * If MTL is found in TL table, it is moved into 1st slot (i.e. effectively *
  1264. * enabled). If MTL isn't found in TL table, it is installed into 1st slot. *
  1265. * The TL does not increament the number of TL (noOfTLs) global variable, *
  1266. * but changes it to 1, therfore reporting it as the only registered TL. *
  1267. * *
  1268. * Note : The install routine should be the last TL to be regitered. *
  1269. * *
  1270. * Parameters : *
  1271. * *
  1272. * none *
  1273. * *
  1274. * Returns : *
  1275. * *
  1276. * flOK on success, otherwise respective error code. *
  1277. * *
  1278. * -------------------------------------------------------------------------- */
  1279. FLStatus flmtlInstall (void)
  1280. {
  1281. int iTL;
  1282. if (noOfTLs > 0)
  1283. {
  1284. checkStatus( flmtlUninstall() ); /* Dismount previous MTL if exists */
  1285. /* Save number of registered TLs and number of volumes */
  1286. mvol.noOfTLs = noOfTLs;
  1287. mvol.noOfDrives = noOfDrives;
  1288. /* search for MTL in tlTable[] */
  1289. for (iTL = 0; iTL < noOfTLs; iTL++)
  1290. {
  1291. if (tlTable[iTL].mountRoutine == mtlMount)
  1292. break;
  1293. }
  1294. if (iTL >= noOfTLs) /* MTL is not found in tlTable[iTL] */
  1295. {
  1296. /* MTL isn't in tlTable[], we will be adding it */
  1297. if (noOfTLs >= TLS)
  1298. {
  1299. DEBUG_PRINT(("Debug: can't install MTL, too many TLs.\n"));
  1300. return flTooManyComponents;
  1301. }
  1302. iTL = noOfTLs;
  1303. mvol.noOfTLs++;
  1304. }
  1305. else
  1306. {
  1307. /* MTL is found in tlTable[iTL] */
  1308. }
  1309. /* free the 1st slot in tlTable[] for MTL */
  1310. while (iTL >= 1)
  1311. {
  1312. tlTable[iTL].mountRoutine = tlTable[iTL - 1].mountRoutine;
  1313. tlTable[iTL].formatRoutine = tlTable[iTL - 1].formatRoutine;
  1314. iTL--;
  1315. }
  1316. }
  1317. else
  1318. {
  1319. /* No other TL registered so return error code */
  1320. return flMultiDocContrediction;
  1321. }
  1322. /* Make system believe that only MTL is registered */
  1323. noOfTLs = 1;
  1324. noOfDrives = 1;
  1325. /* put MTL in the 1st slot in tlTable[] */
  1326. tlTable[0].mountRoutine = mtlMount;
  1327. tlTable[0].preMountRoutine = mtlPreMount;
  1328. #ifdef FORMAT_VOLUME
  1329. tlTable[0].formatRoutine = mtlFormat;
  1330. #else
  1331. tlTable[0].formatRoutine = noFormat;
  1332. #endif
  1333. return flOK;
  1334. }
  1335. /* -------------------------------------------------------------------------- *
  1336. * *
  1337. * f l R e g i s t e r M T L *
  1338. * *
  1339. * Standard TL's component registration routine. *
  1340. * *
  1341. * Parameters : *
  1342. * *
  1343. * none *
  1344. * *
  1345. * Returns : *
  1346. * *
  1347. * flOK on success, otherwise respective error code. *
  1348. * *
  1349. * -------------------------------------------------------------------------- */
  1350. FLStatus flRegisterMTL (void)
  1351. {
  1352. checkStatus( flmtlInstall() );
  1353. return flOK;
  1354. }
  1355. /* Physical routines are not a part of TrueFFS code */
  1356. #if 0
  1357. /* -------------------------------------------------------------------------- *
  1358. * *
  1359. * m t l R e a d B B T *
  1360. * *
  1361. * TL's standard 'read bad blocks table' routine. *
  1362. * *
  1363. * Parameters : *
  1364. * *
  1365. * pvol : Pointer identifying drive *
  1366. * buf : Pointer to user buffer to read BB info to *
  1367. * *
  1368. * Returns : *
  1369. * *
  1370. * flOK on success, otherwise respective error code. *
  1371. * mediaSize : Size of the formated media *
  1372. * noOfBB : Total number of bad blocks read *
  1373. * *
  1374. * -------------------------------------------------------------------------- */
  1375. static FLStatus mtlReadBBT (MTL *pvol, byte FAR1 * buf,
  1376. long FAR2 * mediaSize, unsigned FAR2 * noOfBB)
  1377. {
  1378. CardAddress addressShift=0;
  1379. long bufOffset = 0;
  1380. unsigned tmpCounter;
  1381. long tmpMediaSize;
  1382. byte iDev;
  1383. /* check 'pvol' for sanity */
  1384. if (pvol != &mvol)
  1385. return flBadDriveHandle;
  1386. /* Read bbt of each device while incrementing the address simulating a
  1387. * big physical device */
  1388. *mediaSize = 0;
  1389. *noOfBB = 0;
  1390. for (iDev = 0; iDev < noOfSockets; iDev++)
  1391. {
  1392. checkStatus(mpT(pvol,iDev).readBBT(mpT(pvol,iDev).rec,
  1393. (byte FAR1 *)flAddLongToFarPointer(buf,bufOffset),
  1394. &tmpMediaSize,&tmpCounter));
  1395. *noOfBB += tmpCounter; /* Global BB counter */
  1396. for (;tmpCounter>0;tmpCounter--,bufOffset+=sizeof(CardAddress))
  1397. {
  1398. *((CardAddress *)(buf + bufOffset)) += addressShift;
  1399. }
  1400. addressShift += mP(iDev);
  1401. *mediaSize += tmpMediaSize;
  1402. }
  1403. return flOK;
  1404. }
  1405. /* -------------------------------------------------------------------------- *
  1406. * *
  1407. * m t l W r i t e B B T *
  1408. * *
  1409. * TL's write Bad Blocks Table routine. *
  1410. * *
  1411. * Parameters : *
  1412. * *
  1413. * ioreq : pointer to the structure containing i\o fields *
  1414. * *
  1415. * Returns : *
  1416. * *
  1417. * flOK on success, otherwise respective error code. *
  1418. * *
  1419. * -------------------------------------------------------------------------- */
  1420. static FLStatus mtlWriteBBT(IOreq FAR2* ioreq)
  1421. {
  1422. FLSocket *socket;
  1423. FLStatus status;
  1424. FLFlash tmpFlash;
  1425. CardAddress endUnit;
  1426. CardAddress lastDriveAddress;
  1427. CardAddress nextDriveAddress = 0;
  1428. CardAddress iUnit;
  1429. CardAddress bUnit;
  1430. CardAddress endAddress;
  1431. byte iDev;
  1432. word badBlockNo=0;
  1433. byte zeroes[2] = {0,0};
  1434. /* Initlize last erase address according to argument */
  1435. tffsset(&endAddress,0xff,sizeof(CardAddress));
  1436. if (ioreq->irLength == 0)
  1437. {
  1438. tffsset(&endAddress,0xff,sizeof(CardAddress));
  1439. }
  1440. else
  1441. {
  1442. endAddress = ioreq->irLength;
  1443. }
  1444. /*
  1445. * Do flash recognition while storing physical size of devices
  1446. * #0 .. (mvol.noOfSockets - 1). First call flIdentifyFlash() to find
  1447. * MTD, then erase the media while marking bad blocks. Note that the
  1448. * addresses are physical addresses of the virtual multi-doc. The address
  1449. * should be subtructed by the physical size of the previous devices.
  1450. */
  1451. for (iDev = 0; iDev < noOfSockets; iDev++)
  1452. {
  1453. socket = flSocketOf (iDev);
  1454. /* Identify */
  1455. status = flIdentifyFlash (socket, &tmpFlash);
  1456. if ((status != flOK) && (status != flUnknownMedia))
  1457. {
  1458. DEBUG_PRINT(("Debug: no MTD recognized the device, MTL writeBBT aborted.\n"));
  1459. return status;
  1460. }
  1461. /* Initialize new drive boundry variables */
  1462. mP(iDev) = (dword)(tmpFlash.chipSize * tmpFlash.noOfChips);
  1463. lastDriveAddress = nextDriveAddress;
  1464. nextDriveAddress += mP(iDev);
  1465. endUnit = mP(iDev) >> tmpFlash.erasableBlockSizeBits;
  1466. bUnit = ((*((CardAddress FAR1 *)flAddLongToFarPointer
  1467. (ioreq->irData,badBlockNo*sizeof(CardAddress)))) -
  1468. lastDriveAddress) >> tmpFlash.erasableBlockSizeBits;
  1469. /* Erase entire media */
  1470. for (iUnit = 0 ,badBlockNo = 0; iUnit < endUnit ; iUnit++)
  1471. {
  1472. if ((iUnit << tmpFlash.erasableBlockSizeBits) + lastDriveAddress >= endAddress)
  1473. return flOK;
  1474. tmpFlash.erase(&tmpFlash,iUnit,1);
  1475. if (ioreq->irFlags > badBlockNo)
  1476. {
  1477. if (bUnit == iUnit)
  1478. {
  1479. tmpFlash.write(&tmpFlash,bUnit <<
  1480. tmpFlash.erasableBlockSizeBits,zeroes,2,0);
  1481. badBlockNo++;
  1482. bUnit = ((*((CardAddress FAR1 *)flAddLongToFarPointer
  1483. (ioreq->irData,badBlockNo*sizeof(CardAddress)))) -
  1484. lastDriveAddress) >> tmpFlash.erasableBlockSizeBits;
  1485. }
  1486. }
  1487. }
  1488. }
  1489. return flOK;
  1490. }
  1491. #endif /* 0 */