ssfdc.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:64k
源码类别:

VxWorks

开发平台:

C/C++

  1. /*
  2.  * $Log:   V:/ssfdc.c_v  $
  3.  *
  4.  *    Rev 1.17   01 Mar 1998 12:59:30   amirban
  5.  * Add parameter to mapSector
  6.  *
  7.  *    Rev 1.16   29 Sep 1997 14:17:28   danig
  8.  * Call setBusy(OFF) from dismount function
  9.  *
  10.  *    Rev 1.15   18 Sep 1997 10:11:42   danig
  11.  * Warnings
  12.  *
  13.  *    Rev 1.14   10 Sep 1997 16:21:16   danig
  14.  * Got rid of generic names
  15.  *
  16.  *    Rev 1.13   10 Sep 1997 13:32:20   danig
  17.  * Limit number of virtual units
  18.  *
  19.  *    Rev 1.12   04 Sep 1997 15:52:46   danig
  20.  * Debug messages
  21.  *
  22.  *    Rev 1.11   04 Sep 1997 11:07:52   danig
  23.  * Share buffer with MTD
  24.  *
  25.  *    Rev 1.10   28 Jul 1997 15:13:34   danig
  26.  * volForCallback & moved standard typedefs to flbase.h
  27.  *
  28.  *    Rev 1.9   27 Jul 1997 14:04:18   danig
  29.  * FAR -> FAR0
  30.  *
  31.  *    Rev 1.8   24 Jul 1997 15:14:18   danig
  32.  * Fixed ECC on read
  33.  *
  34.  *    Rev 1.7   20 Jul 1997 11:01:52   danig
  35.  * Ver 2.0
  36.  *
  37.  *    Rev 1.6   13 Jul 1997 10:51:58   danig
  38.  * erasedSectors
  39.  *
  40.  *    Rev 1.5   01 Jul 1997 15:36:32   danig
  41.  * Changes to isErasedSector & isErasedUnit
  42.  *
  43.  *    Rev 1.4   29 Jun 1997 16:13:02   danig
  44.  * Comments
  45.  *
  46.  *    Rev 1.3   12 Jun 1997 17:41:54   danig
  47.  * ECC on read, use second address area.
  48.  *
  49.  *    Rev 1.2   08 Jun 1997 19:05:24   danig
  50.  * Delete sector bug & check for mount in setBusy()
  51.  *
  52.  *    Rev 1.1   01 Jun 1997 13:42:36   amirban
  53.  * Use ftllite.h I/F
  54.  *
  55.  *    Rev 1.0   15 Apr 1997 17:56:26   danig
  56.  * Initial revision.
  57.  */
  58. /************************************************************************/
  59. /*                                                                      */
  60. /* FAT-FTL Lite Software Development Kit */
  61. /* Copyright (C) M-Systems Ltd. 1995-1997 */
  62. /* */
  63. /************************************************************************/
  64. #include "fltl.h"
  65. #include "flflash.h"
  66. #include "flbuffer.h"
  67. /* VF: This macro is vital to supporting devices with 32 or more sectors per erase
  68.        unit.  Data types and code coming originally from M-Systems only provided
  69.        for up to 16 sectors per erase unit.  Some data types had bit fields that
  70.        depended on the number of sectors per erase unit not exceeding 16.
  71.        Several data type and code modifications have been made based on the value
  72.        of this macro to accomodate larger erase unit sized devices.
  73. */
  74. #define TFFS_SECTORS_PER_UNIT  32
  75. typedef long int VirtualAddress;
  76. /* VF: Updated PhysUnit storage type.  As used below in the Unit type,
  77.        a PhysUnit only provided 8 bits of storage:  The upper 3 bits were
  78.        used to bookkeep sector status, and the low 5 bits represented a count
  79.        of sectors free in the unit.  5 bits only counts up to 31.  We need more
  80.        bits for the count, hence the increase in size of this data type.
  81. */
  82. #if (TFFS_SECTORS_PER_UNIT < 32)
  83. typedef unsigned char PhysUnit;
  84. #else
  85. typedef unsigned short PhysUnit;
  86. #endif
  87. typedef unsigned short UnitNo;
  88. #define FORMAT_PATTERN 1, 3, 0xd9, 1, 0xff, 0x18, 2, 0xdf, 1, 0x20
  89. #define CIS_DATA 0x1, 0x3, 0xd9, 0x1, 0xff, 0x18, 0x2, 0xdf, 0x1, 
  90. 0x20, 0x4, 0x0, 0x0, 0x0, 0x0, 0x21, 0x2, 
  91. 0x4, 0x1, 0x22, 0x2, 0x1, 0x1, 0x22, 0x3, 
  92. 0x2, 0x4, 0x7, 0x1a, 0x5, 0x1, 0x3, 0x0, 
  93. 0x2, 0xf, 0x1b, 0x8, 0xc0, 0xc0, 0xa1, 0x1, 
  94. 0x55, 0x8, 0x0, 0x20, 0x1b, 0xa, 0xc1, 0x41, 
  95. 0x99, 0x1, 0x55, 0x64, 0xf0, 0xff, 0xff, 0x20, 
  96. 0x1b, 0xc, 0x82, 0x41, 0x18, 0xea, 0x61, 0xf0, 
  97. 0x1, 0x7, 0xf6, 0x3, 0x1, 0xee, 0x1b, 0xc, 
  98. 0x83, 0x41, 0x18, 0xea, 0x61, 0x70, 0x1, 0x7, 
  99. 0x76, 0x3, 0x1, 0xee, 0x15, 0x14, 0x5, 0x0, 
  100. 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0, 
  101. 0x20, 0x20, 0x20, 0x20, 0x0, 0x30, 0x2e, 0x30, 
  102. 0x0, 0xff, 0x14, 0x0, 0xff, 0x0, 0x0, 0x0, 
  103. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  104. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  105. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  106. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  107. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  108. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  109. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  110. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  111. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  112. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  113. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  114. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  115. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  116. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  117. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  118. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  119. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  120. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 
  121. 0x3, 0xd9, 0x1, 0xff, 0x18, 0x2, 0xdf, 0x1, 
  122. 0x20, 0x4, 0x0, 0x0, 0x0, 0x0, 0x21, 0x2, 
  123. 0x4, 0x1, 0x22, 0x2, 0x1, 0x1, 0x22, 0x3, 
  124. 0x2, 0x4, 0x7, 0x1a, 0x5, 0x1, 0x3, 0x0, 
  125. 0x2, 0xf, 0x1b, 0x8, 0xc0, 0xc0, 0xa1, 0x1, 
  126. 0x55, 0x8, 0x0, 0x20, 0x1b, 0xa, 0xc1, 0x41, 
  127. 0x99, 0x1, 0x55, 0x64, 0xf0, 0xff, 0xff, 0x20, 
  128. 0x1b, 0xc, 0x82, 0x41, 0x18, 0xea, 0x61, 0xf0, 
  129. 0x1, 0x7, 0xf6, 0x3, 0x1, 0xee, 0x1b, 0xc, 
  130. 0x83, 0x41, 0x18, 0xea, 0x61, 0x70, 0x1, 0x7, 
  131. 0x76, 0x3, 0x1, 0xee, 0x15, 0x14, 0x5, 0x0, 
  132. 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0, 
  133. 0x20, 0x20, 0x20, 0x20, 0x0, 0x30, 0x2e, 0x30, 
  134. 0x0, 0xff, 0x14, 0x0, 0xff, 0x0, 0x0, 0x0, 
  135. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  136. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  137. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  138. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  139. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  140. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  141. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  142. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  143. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  144. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  145. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  146. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  147. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  148. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  149. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  150. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  151. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
  152. 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
  153. #define SECTOR_ERASED 1
  154. #define SECTOR_ALLOCATED        2
  155. #define SECTOR_REPLACED 3
  156. #define SECTOR_DELETED1 0x80
  157. #define SECTOR_DELETED2 0xf0
  158. #define SECTORS_PER_UNIT 16  /* default number of sectors per unit */
  159. /*#define ECC_ON_READ*/
  160. #define UNASSIGNED_ADDRESS 0xffffffffl
  161. /* VF: Due to the increase in size of PhysUnit above from 8 to 16 bits, these macros
  162.        must be adjusted accordingly to represent the upper 3 bits of a 16-bit quantity.
  163. */
  164. #if (TFFS_SECTORS_PER_UNIT < 32)
  165. #define UNIT_FREE 0xe0   /* unassigned unit */
  166. #define UNIT_AVAILABLE 0x80   /* assigned unit */
  167. #define UNIT_ERASED 0xc0   /* unit is erased */
  168. #define UNIT_BAD 0      /* unit is defective */
  169. #define STATUS_MASK 0xe0   /* the unit status is in the 3 MSBs */
  170. #else
  171. #define UNIT_FREE 0xe000   /* unassigned unit */
  172. #define UNIT_AVAILABLE 0x8000   /* assigned unit */
  173. #define UNIT_ERASED 0xc000   /* unit is erased */
  174. #define UNIT_BAD 0x0000   /* unit is defective */
  175. #define STATUS_MASK 0xe000   /* the unit status is in the 3 MSBs */
  176. #endif
  177. /* extra area of odd pages is read before extra area of even pages
  178.    when page size is 256 */
  179. #define STATUS_AREA_OFFSET      ((vol.flash.flags & BIG_PAGE) ? 4 : 12)
  180. #define BLOCK_ADDRESS_OFFSET1   ((vol.flash.flags & BIG_PAGE) ? 6 : 14)
  181. #define BLOCK_ADDRESS_OFFSET2   ((vol.flash.flags & BIG_PAGE) ? 11 : 3)
  182. #define CIS_DATA_OFFSET ((vol.flash.flags & BIG_PAGE) ? 4 : 12)
  183. #define ECC1 ((vol.flash.flags & BIG_PAGE) ? 13 : 5)
  184. #define ECC2 ((vol.flash.flags & BIG_PAGE) ? 8 : 0)
  185. #define OFFSET1 1
  186. #define OFFSET2 2
  187. #define INCORRECT_DATA 0
  188. #define CORRECT_DATA 0xff
  189. #define NO_UNIT 0xffff
  190. typedef struct {
  191.   PhysUnit unitStatus;             /* unit status in the 3 MSBs, unassigned */
  192.    /* sectors counter in the rest of the bits. */
  193. /* VF: Updated next line.  This is a bit-field, so we need 32 bits to represent sectors: */
  194. #if (TFFS_SECTORS_PER_UNIT < 32)
  195.   unsigned short erasedSectors;    /* if bit i=1, sector i in the unit is erased. */
  196. #else
  197.   unsigned long erasedSectors;     /* if bit i=1, sector i in the unit is erased. */
  198. #endif
  199. } Unit;
  200. typedef struct  {
  201.   unsigned char sectorStatus;
  202.   unsigned char unitStatus;
  203. } StatusArea;
  204. typedef enum {BAD_FORMAT, SSFDC_FORMAT, ANAND_FORMAT} FormatType;
  205. #ifndef MALLOC_TFFS
  206. #define HEAP_SIZE (0x100000l / ASSUMED_NFTL_UNIT_SIZE) *       
  207. (sizeof(UnitNo) + sizeof(Unit)) *  
  208. MAX_VOLUME_MBYTES + SECTORS_PER_UNIT
  209. #endif
  210. struct tTLrec {
  211.   FLBoolean     badFormat; /* true if TFFS format is bad */
  212.   UnitNo     CISblock;           /* Unit no. of CIS block */
  213.   unsigned int     erasableBlockSizeBits;  /* log2 of erasable block size */
  214.   UnitNo     noOfVirtualUnits;
  215.   UnitNo     freeUnits;              /* number of unassigned units */
  216.   unsigned long     unitOffsetMask;
  217.   unsigned int     sectorsPerUnit;
  218.   UnitNo     noOfUnits;
  219.   unsigned int     unitSizeBits;
  220.   SectorNo     virtualSectors;
  221.   UnitNo            roverUnit;          /* Starting point for allocation search */
  222.   UnitNo     transferUnit;
  223.   UnitNo     replacedUnit;
  224.   unsigned int     sectorsDeleted;     /* number of sector deleted in the
  225.    replaced unit */
  226.   Unit      *physicalUnits;  /* unit table by physical no. */
  227.   UnitNo     *virtualUnits;  /* unit table by logical no. */
  228.   unsigned char     *replacementSectors; /* a table of the sectors in the
  229.     replaced unit */
  230.   SectorNo      mappedSectorNo;
  231.   void FAR0         *mappedSector;
  232.   CardAddress     mappedSectorAddress;
  233.   FLFlash     flash;
  234.   FLBuffer          *buffer;
  235. #ifndef MALLOC_TFFS
  236.   char     heap[HEAP_SIZE];
  237. #endif
  238. };
  239. #define ssfdcBuffer  vol.buffer->data
  240. typedef TLrec SSFDC;
  241. static SSFDC vols[DRIVES];
  242. /********************** ECCEDC part ******************************/
  243. /*----------------------------------------------------------------------*/
  244. /*          c h a r P a r i t y */
  245. /* */
  246. /* Get odd parity of one byte. */
  247. /*                                                                      */
  248. /* Parameters:                                                          */
  249. /* c : One byte of data. */
  250. /*                                                                      */
  251. /* Returns:                                                             */
  252. /* Odd parity. */
  253. /*----------------------------------------------------------------------*/
  254. static unsigned char charParity(unsigned char c)
  255. {
  256.   unsigned char parityBit = 1;
  257.   for (; c; c >>= 1)
  258.     parityBit ^= c & 0x01;
  259.   return parityBit;
  260. }
  261. /*----------------------------------------------------------------------*/
  262. /*          c r e a t e E c c */
  263. /* */
  264. /* Calculate 22 bits Error correction  detection code for 256 bytes    */
  265. /* of data. 16 bits line parity, 6 bits column parity. ECC scheme  */
  266. /* according to SSFDC specification. */
  267. /*                                                                      */
  268. /* Parameters:                                                          */
  269. /* buf : 256 bytes of data. */
  270. /* code : 3 bytes of ECC. */
  271. /*                                                                      */
  272. /*----------------------------------------------------------------------*/
  273. static void createEcc(unsigned char FAR0 *buf, unsigned char FAR0 *code)
  274. {
  275.   unsigned char lineParity[16], columnParity[6], temp;
  276.   int i, k;
  277.   /* initialize to 1's, odd parity */
  278.   for (i = 0; i < 16; i++)
  279.     lineParity[i] = 0xff;
  280.   for (i = 0; i < 6; i++)
  281.     columnParity[i] = 1;
  282.   /* xor the lines */
  283.   for (i = 0; i < 256; i++)
  284.     for (k = 0; k < 8; k++)
  285.       if ((i / (1 << k)) % 2)
  286. lineParity[2 * k + 1] ^= buf[i];
  287.       else
  288. lineParity[2 * k] ^= buf[i];
  289.   temp = lineParity[0] ^ lineParity[1];  /* temp holds the xor of all the lines */
  290.   for(i = 0; i < 3; i++)
  291.     code[i] = 0;
  292.   /* get line parity */
  293.   for(i = 0; i < 16; i++)
  294.     if (charParity(lineParity[i]))
  295.       code[i / 8] |= (1 << (i % 8));
  296.   /* xor the columns */
  297.   for(i = 0; i < 8; i++)
  298.     for (k = 0; k < 3; k++)
  299.       if ((i / (1 << k)) % 2)
  300. columnParity[2 * k + 1] ^= (temp & (0xff >> (7 -  i))) >> i;
  301.       else
  302. columnParity[2 * k] ^= (temp & (0xff >> (7 -  i))) >> i;
  303.   code[2] |= 0x03;  /* bits 16 and 17 are always 1 */
  304.   /* get column parity */
  305.   for(i = 0; i < 6; i++)
  306.     if (columnParity[i])
  307.       code[2] |= 4 << i;
  308. }
  309. #ifdef ECC_ON_READ
  310. /*----------------------------------------------------------------------*/
  311. /*          i s F i x a b l e */
  312. /* */
  313. /* We know there is an error, Check if it is fixable (one bit error in  */
  314. /* 256 bytes of data is fixable). */
  315. /*                                                                      */
  316. /* Parameters:                                                          */
  317. /* diff : The difference between the read and  */
  318. /*   calculated ECC. */
  319. /* */
  320. /* Returns: */
  321. /* TRUE if the error is fixable, otherwise FALSE. */
  322. /*                                                                      */
  323. /*----------------------------------------------------------------------*/
  324. static FLBoolean isFixable (unsigned char FAR0 *diff)
  325. {
  326.   int i, j;
  327.   unsigned char mask;
  328.   /* data is fixable if for each pair of bits one is 0 and one is 1 */
  329.   for (i = 0; i < 3; i++)
  330.     for (j = 0, mask = 1; j < 4; j++, mask <<= 2) {
  331.       if ((i == 2) && (j == 0))
  332. continue;     /* the two lowest bits in the 3rd byte are always 1 */
  333.       /* xor two neighbouring bits */
  334.       if (!(((diff[i] & mask) >> (2 * j)) ^
  335.     ((diff[i] & (mask << 1)) >> (2 * j + 1))))
  336. return FALSE;
  337.     }
  338.   return TRUE;
  339. }
  340. /*----------------------------------------------------------------------*/
  341. /*          c h e c k A n d F i x */
  342. /* */
  343. /* Compare the calculated ECC and the one read from the device.  */
  344. /* If there is a difference, try to fix the error. If both codes */
  345. /* are the same, data is correct. */
  346. /*                                                                      */
  347. /* Parameters:                                                          */
  348. /* ecc1 : Calculated ECC. */
  349. /* ecc2 : Read ECC. */
  350. /*      sectorToFix : The data to fix. */
  351. /* */
  352. /* Returns: */
  353. /* TRUE if data is correct or error fixed, otherwise FALSE. */
  354. /*                                                                      */
  355. /*----------------------------------------------------------------------*/
  356. static FLBoolean checkAndFix(unsigned char FAR0 *ecc1, unsigned char FAR0 *ecc2,
  357.  unsigned char FAR0 *sectorToFix)
  358. {
  359.   if((ecc1[0] != ecc2[0]) ||
  360.      (ecc1[1] != ecc2[1]) ||
  361.      (ecc1[2] != ecc2[2])) {  /* ECC error, try to fix */
  362.     unsigned char diff[3];
  363.     int i;
  364.     for (i = 0; i < 3; i++)
  365.       diff[i] = ecc1[i] ^ ecc2[i];
  366.     if (isFixable(diff)) {
  367.       unsigned char line = 0, column = 0, mask;
  368.       /* push the lower bits to the right */
  369.       for (i = 0, mask = 2; i < 4; i++, mask <<= 2)
  370. line |= (diff[0] & mask) >> (i + 1);
  371.       /* push the upper bits to the left */
  372.       for (i = 0, mask = 0x80; i < 4; i++, mask >>= 2)
  373. line |= (diff[1] & mask) << i;
  374.       /* push to the right */
  375.       for (i = 0, mask = 8; i < 3; i++, mask <<= 2)
  376. column |= (diff[2] & mask) >> (i + 3);
  377.       sectorToFix[line] ^= 1 << column;  /* fix */
  378.       return TRUE;
  379.     }
  380.     else {
  381.     #ifdef DEBUG_PRINT
  382.       DEBUG_PRINT("Debug: ECC error in SSFDC.n");
  383.     #endif
  384.       return FALSE;
  385.     }
  386.   }
  387.   else
  388.     return TRUE;
  389. }
  390. /*----------------------------------------------------------------------*/
  391. /*          e c c O n R e a d */
  392. /* */
  393. /* Use ECCEDC for a sector of data. Do each half seperately. */
  394. /* If there is a fixable error, fix it. */
  395. /*                                                                      */
  396. /* Parameters:                                                          */
  397. /* vol : Pointer identifying drive */
  398. /* sectorAddress : Physical address of the sector to check. */
  399. /* */
  400. /* Returns: */
  401. /*  FALSE if there is an error that can't be fixed, otherwise  */
  402. /* return TRUE. */
  403. /*                                                                      */
  404. /*----------------------------------------------------------------------*/
  405. static FLBoolean eccOnRead(SSFDC vol, CardAddress sectorAddress)
  406. {
  407.   unsigned char calcEcc[3], readEcc[3];
  408.   unsigned char FAR0 *sectorToFix = (unsigned char FAR0 *)vol.mappedSector;
  409.   createEcc(sectorToFix, calcEcc);
  410.   vol.flash.read(&vol.flash, sectorAddress + ECC1, readEcc, sizeof readEcc, EXTRA);
  411.   if (checkAndFix(calcEcc, readEcc, sectorToFix)) {
  412.     /* success in the first half go for the second half */
  413.     createEcc(sectorToFix + SECTOR_SIZE / 2, calcEcc);
  414.     vol.flash.read(&vol.flash, sectorAddress + ECC2, readEcc, sizeof readEcc, EXTRA);
  415.     if (checkAndFix(calcEcc, readEcc, sectorToFix + SECTOR_SIZE / 2))
  416.       return TRUE;
  417.   }
  418.   return FALSE;
  419. }
  420. #endif /* ECC_ON_READ */
  421. /******************* end of ECCEDC part ********************************/
  422. /*----------------------------------------------------------------------*/
  423. /*          u n i t B a s e A d d r e s s */
  424. /* */
  425. /* Returns the physical address of a unit. */
  426. /*                                                                      */
  427. /* Parameters:                                                          */
  428. /* vol : Pointer identifying drive */
  429. /* unitNo : Physical unit number */
  430. /*                                                                      */
  431. /* Returns:                                                             */
  432. /* physical address of unitNo */
  433. /*----------------------------------------------------------------------*/
  434. static CardAddress unitBaseAddress(SSFDC vol, UnitNo unitNo)
  435. {
  436.   return (CardAddress)unitNo << vol.unitSizeBits;
  437. }
  438. /*----------------------------------------------------------------------*/
  439. /*          v i r t u a l 2 P h y s i c a l */
  440. /* */
  441. /* Translate virtual sector number to physical address. */
  442. /*                                                                      */
  443. /* Parameters:                                                          */
  444. /* vol : Pointer identifying drive */
  445. /* sectorNo : Virtual sector number */
  446. /*                                                                      */
  447. /* Returns:                                                             */
  448. /* physical address of sectorNo */
  449. /*----------------------------------------------------------------------*/
  450. static CardAddress virtual2Physical(SSFDC vol, SectorNo sectorNo)
  451. {
  452.   unsigned unitOffset = (sectorNo % vol.sectorsPerUnit) << SECTOR_SIZE_BITS;
  453.   UnitNo unitNo = vol.virtualUnits[sectorNo / vol.sectorsPerUnit];
  454.   StatusArea statusArea;
  455.   /* no physical unit is assigned to this virtual sector number */
  456.   if (unitNo == NO_UNIT)
  457.     return UNASSIGNED_ADDRESS;
  458.   /* check if this sector was replaced */
  459.   vol.flash.read(&vol.flash,
  460.  unitBaseAddress(&vol, unitNo) + unitOffset + STATUS_AREA_OFFSET,
  461.  &statusArea, sizeof statusArea, EXTRA);
  462.   if (statusArea.sectorStatus != 0xff) {
  463.     if (vol.replacedUnit == unitNo)
  464.       if (vol.replacementSectors[sectorNo % vol.sectorsPerUnit] == SECTOR_REPLACED)
  465. return unitBaseAddress(&vol, vol.transferUnit) + unitOffset; /* this sector was replaced */
  466.     return UNASSIGNED_ADDRESS;  /* this sector is bad or deleted */
  467.   }
  468.   return unitBaseAddress(&vol, unitNo) + unitOffset;
  469. }
  470. /*----------------------------------------------------------------------*/
  471. /*          p h y s i c a l 2 V i r t u a l */
  472. /* */
  473. /* Translate physical unit number to virtual unit number. Read virtual */
  474. /* unit number from first or second address area according to the  */
  475. /* parameter addressAreaNo. */
  476. /*                                                                      */
  477. /* Parameters:                                                          */
  478. /* vol : Pointer identifying drive */
  479. /* unitNo : Physical unit number */
  480. /* addressAreaNo : Specify which address area to use */
  481. /*                                                                      */
  482. /* Returns:                                                             */
  483. /* Virtual unit number of unitNo. */
  484. /*----------------------------------------------------------------------*/
  485. static UnitNo physical2Virtual(SSFDC vol, UnitNo unitNo, int addressAreaNo)
  486. {
  487.   unsigned char addressArea[2];
  488.   UnitNo virtualUnitNo;
  489.   int offset;
  490.   offset = (addressAreaNo == OFFSET1 ? BLOCK_ADDRESS_OFFSET1 : BLOCK_ADDRESS_OFFSET2);
  491.   /* get virtual unit no. from address area */
  492.   vol.flash.read(&vol.flash, unitBaseAddress(&vol, unitNo) + offset, addressArea,
  493.  sizeof addressArea, EXTRA);
  494.   /* trade places of byte 0 and byte 1 */
  495.   virtualUnitNo = ((UnitNo)addressArea[0] << 8) | addressArea[1];
  496.   /* virtual address is in bits 1 through 11 */
  497.   virtualUnitNo <<= 4;
  498.   virtualUnitNo >>= 5;
  499.   return virtualUnitNo;
  500. }
  501. /*----------------------------------------------------------------------*/
  502. /*               s e c t o r s I n V o l u m e */
  503. /* */
  504. /* Gets the total number of sectors in the volume */
  505. /* */
  506. /* Parameters:                                                          */
  507. /* vol : Pointer identifying drive */
  508. /*                                                                      */
  509. /* Returns:                                                             */
  510. /* Number of sectors in the volume */
  511. /*----------------------------------------------------------------------*/
  512. static SectorNo sectorsInVolume(SSFDC vol)
  513. {
  514.   return vol.virtualSectors;
  515. }
  516. /*----------------------------------------------------------------------*/
  517. /*               I d e n t i f y F o r m a t */
  518. /* */
  519. /* There are two different formats for nand devices, this function  */
  520. /* tries to identify one of them by reading its ID string. If format is */
  521. /* identified, bootBlock holds the number of the unit where the boot  */
  522. /* sector is.  */
  523. /* */
  524. /* Parameters:                                                          */
  525. /* vol : Pointer identifying drive */
  526. /* bootBlock : Receives the number of the block where the */
  527. /*   boot sector is. */
  528. /*                                                                      */
  529. /* Returns:                                                             */
  530. /* The type of the format idetified (SSFDC, NFTL, unknown) */
  531. /*----------------------------------------------------------------------*/
  532. static FormatType identifyFormat(SSFDC vol, UnitNo *bootBlock)
  533. {
  534.   int i;
  535.   unsigned char bootRecordId[10], invalidDataFlag;
  536.   unsigned char formatPattern[10] = {FORMAT_PATTERN};
  537.   for (*bootBlock = 0; *bootBlock < vol.noOfUnits; (*bootBlock)++) {
  538.     vol.flash.read(&vol.flash, unitBaseAddress(&vol, *bootBlock),
  539.    bootRecordId, sizeof bootRecordId, 0);
  540.     if (tffscmp(bootRecordId, "ANAND", 6) == 0)
  541.       return ANAND_FORMAT;
  542.     for (i = 0; (unsigned)i < vol.sectorsPerUnit; i++) {
  543.       vol.flash.read(&vol.flash, unitBaseAddress(&vol, *bootBlock) + (i << SECTOR_SIZE_BITS),
  544.      bootRecordId, sizeof bootRecordId, 0);
  545.       if (tffscmp(bootRecordId, formatPattern, sizeof formatPattern) == 0) {
  546. /* check that the data is valid */
  547. vol.flash.read(&vol.flash,
  548.        unitBaseAddress(&vol, *bootBlock) +
  549.        (i << SECTOR_SIZE_BITS) + CIS_DATA_OFFSET,
  550.        &invalidDataFlag, sizeof invalidDataFlag, EXTRA);
  551. if (invalidDataFlag == 0xff)
  552.   return SSFDC_FORMAT;
  553.       }
  554.     }
  555.   }
  556.   return BAD_FORMAT;
  557. }
  558. /*----------------------------------------------------------------------*/
  559. /*               i s E r a s e d s e c t o r  */
  560. /* */
  561. /* Check if a sector is erased. */
  562. /* */
  563. /* Parameters:                                                          */
  564. /* vol : Pointer identifying drive */
  565. /*  unitNo : The sector to check is in this unit. */
  566. /* offset : Offset of the sector in the unit. */
  567. /*                                                                      */
  568. /* Returns:                                                             */
  569. /* TRUE if the sector is erased, otherwise FALSE */
  570. /*----------------------------------------------------------------------*/
  571. static FLBoolean isErasedSector(SSFDC vol, UnitNo unitNo, unsigned offset)
  572. {
  573.   unsigned char *buf;
  574.   StatusArea statusArea;
  575.   int i;
  576.   buf = (unsigned char *)vol.flash.map(&vol.flash,
  577.        unitBaseAddress(&vol, unitNo) +
  578.        offset, SECTOR_SIZE);
  579.   /* check data area */
  580.   for (i = 0; i < SECTOR_SIZE; i++)
  581.     if (buf[i] != 0xff)
  582.       return FALSE;
  583.   /* check status area */
  584.   vol.flash.read(&vol.flash,
  585.  unitBaseAddress(&vol, unitNo) + offset + STATUS_AREA_OFFSET,
  586.  &statusArea, sizeof statusArea, EXTRA);
  587.   if (statusArea.sectorStatus != 0xff)
  588.     return FALSE;
  589.   return TRUE;
  590. }
  591. /*----------------------------------------------------------------------*/
  592. /*               w r i t e A n d C h e c k  */
  593. /* */
  594. /* Write one sector. If eccMode is TRUE, calculate and write ECC. */
  595. /* */
  596. /* Parameters:                                                          */
  597. /* vol : Pointer identifying drive */
  598. /* address : Physical address of the sector to write to */
  599. /* fromAddress : Buffer of data to write */
  600. /* eccMode : If TRUE, calculate and write ECC */
  601. /*                                                                      */
  602. /* Returns:                                                             */
  603. /*  FLStatus  : 0 on success, failed otherwise. */
  604. /*----------------------------------------------------------------------*/
  605. static FLStatus writeAndCheck(SSFDC vol,
  606.       CardAddress address,
  607.       void FAR1 *fromAddress,
  608.       int eccMode)
  609. {
  610.   int sectorInUnit;
  611.   FLStatus status = vol.flash.write(&vol.flash,address,fromAddress,SECTOR_SIZE,0);
  612.   if (eccMode) {  /* calculate and write ECC */
  613.     unsigned char ecc[3];
  614.     createEcc((unsigned char FAR1 *)fromAddress, ecc);
  615.     status = vol.flash.write(&vol.flash, address + ECC1, ecc, sizeof ecc, EXTRA);
  616.     createEcc((unsigned char FAR1 *)fromAddress + SECTOR_SIZE / 2, ecc);
  617.     status = vol.flash.write(&vol.flash, address + ECC2, ecc, sizeof ecc, EXTRA);
  618.   }
  619.   if (status == flWriteFault) {   /* write failed, sector doesn't hold valid data. */
  620.     StatusArea statusArea = {0, 0xff};
  621.     vol.flash.write(&vol.flash, address + STATUS_AREA_OFFSET, &statusArea,
  622.     sizeof statusArea,EXTRA);
  623.   }
  624.   /* mark sector as assigned and not erased */
  625.   vol.physicalUnits[address >> vol.unitSizeBits].unitStatus--;
  626.   sectorInUnit = (address % (1 << vol.unitSizeBits)) / SECTOR_SIZE;
  627.   vol.physicalUnits[address >> vol.unitSizeBits].erasedSectors &= ~(1 << sectorInUnit);
  628.   return status;
  629. }
  630. /*----------------------------------------------------------------------*/
  631. /*                    m a p S e c t o r */
  632. /* */
  633. /* Maps and returns location of a given sector no. */
  634. /* NOTE: This function is used in place of a read-sector operation. */
  635. /* */
  636. /* A one-sector cache is maintained to save on map operations. */
  637. /* */
  638. /* Parameters:                                                          */
  639. /* vol : Pointer identifying drive */
  640. /* sectorNo : Sector no. to read */
  641. /* physAddress : Optional pointer to receive sector address */
  642. /*                                                                      */
  643. /* Returns:                                                             */
  644. /* Pointer to physical sector location. NULL returned if sector */
  645. /* does not exist, or holds invalid data. */
  646. /*----------------------------------------------------------------------*/
  647. static const void FAR0 *mapSector(SSFDC vol, SectorNo sectorNo, CardAddress *physAddress)
  648. {
  649.   if (sectorNo != vol.mappedSectorNo || vol.flash.socket->remapped) {
  650.     if (sectorNo >= vol.virtualSectors)
  651.       vol.mappedSector = NULL;
  652.     else {
  653.       vol.mappedSectorAddress = virtual2Physical(&vol, sectorNo);
  654.       if (vol.mappedSectorAddress == UNASSIGNED_ADDRESS)
  655. vol.mappedSector = NULL; /* no such sector */
  656.       else {
  657. vol.mappedSector = vol.flash.map(&vol.flash, vol.mappedSectorAddress, SECTOR_SIZE);
  658. #ifdef ECC_ON_READ
  659. if (!eccOnRead(&vol, sectorAddress))  /* check and fix errors */
  660.   return NULL; /* a non-fixable error  */
  661. #endif
  662.       }
  663.     }
  664.     vol.mappedSectorNo = sectorNo;
  665.     vol.flash.socket->remapped = FALSE;
  666.   }
  667.   if (physAddress)
  668.     *physAddress = vol.mappedSectorAddress;
  669.   return vol.mappedSector;
  670. }
  671. /*----------------------------------------------------------------------*/
  672. /*           f o r m a t U n i t */
  673. /* */
  674. /* Format one unit. Erase the unit, and mark the physical units table.  */
  675. /*                                                                      */
  676. /* Parameters:                                                          */
  677. /* vol : Pointer identifying drive */
  678. /* unitNo : Unit to format */
  679. /*                                                                      */
  680. /* Returns:                                                             */
  681. /* FLStatus        : 0 on success, failed otherwise */
  682. /*----------------------------------------------------------------------*/
  683. static FLStatus formatUnit(SSFDC vol, UnitNo unitNo)
  684. {
  685.   if (!(vol.physicalUnits[unitNo].unitStatus & UNIT_AVAILABLE))
  686.     return flWriteFault;
  687.   if (((vol.physicalUnits[unitNo].unitStatus & STATUS_MASK) == UNIT_FREE) ||
  688.       ((vol.physicalUnits[unitNo].unitStatus & STATUS_MASK) == UNIT_ERASED))
  689.     vol.freeUnits--;
  690.   vol.physicalUnits[unitNo].unitStatus &= ~UNIT_AVAILABLE; /* protect the unit */
  691.   checkStatus(vol.flash.erase(&vol.flash,
  692.       unitNo << (vol.unitSizeBits - vol.erasableBlockSizeBits),
  693.       1 << (vol.unitSizeBits - vol.erasableBlockSizeBits)));
  694.   /* mark unit erased */
  695.   vol.physicalUnits[unitNo].unitStatus = UNIT_ERASED | vol.sectorsPerUnit;
  696. /* VF: Updated next line: */
  697. #if (TFFS_SECTORS_PER_UNIT < 32)  /* VF */
  698.   vol.physicalUnits[unitNo].erasedSectors = 0xffff;  /* all sectors are erased */
  699. #else
  700.   vol.physicalUnits[unitNo].erasedSectors = 0xffffffff;  /* all sectors are erased */
  701. #endif
  702.   vol.freeUnits++;
  703.   return flOK;
  704. }
  705. /*----------------------------------------------------------------------*/
  706. /*            a s s i g n U n i t */
  707. /* */
  708. /* Assigns a virtual unit no. to a unit */
  709. /*                                                                      */
  710. /* Parameters:                                                          */
  711. /* vol : Pointer identifying drive */
  712. /* unitNo : Physical unit number */
  713. /* virtualUnitNo : Virtual unit number to assign */
  714. /*                                                                      */
  715. /* Returns:                                                             */
  716. /* FLStatus : 0 on success, failed otherwise */
  717. /*----------------------------------------------------------------------*/
  718. static FLStatus assignUnit(SSFDC vol, UnitNo unitNo, UnitNo virtualUnitNo)
  719. {
  720.   unsigned char blockAddressArea[2], parityBit = 1; /* bit 12 is always 1 */
  721.   FLStatus status;
  722.   UnitNo un;
  723.   unsigned sector;
  724.   /* create the block address area */
  725.   /* calculate parity bit */
  726.   for (un = virtualUnitNo; un; un >>= 1)
  727.     parityBit ^= un & 0x01;
  728.   blockAddressArea[0] = (virtualUnitNo >> 7) | 0x10;
  729.   blockAddressArea[1] = (virtualUnitNo << 1) | parityBit;
  730.   /* write the block address to the block address areas in all the sectors
  731.      of the unit.*/
  732.   for (sector = 0; sector < vol.sectorsPerUnit; sector++) {
  733.     CardAddress sectorAddress;
  734.     sectorAddress = unitBaseAddress(&vol, unitNo) + (sector << SECTOR_SIZE_BITS);
  735.     /* write to first address area */
  736.     status = vol.flash.write(&vol.flash, sectorAddress + BLOCK_ADDRESS_OFFSET1,
  737.      &blockAddressArea, sizeof blockAddressArea, EXTRA);
  738.     if (status == flOK)
  739.       /* write to second address area */
  740.       status = vol.flash.write(&vol.flash, sectorAddress + BLOCK_ADDRESS_OFFSET2,
  741.        &blockAddressArea, sizeof blockAddressArea, EXTRA);
  742.     if (status != flOK) {  /* write failed, mark unit as bad */
  743.       vol.physicalUnits[unitNo].unitStatus &= ~STATUS_MASK;
  744.       vol.physicalUnits[unitNo].unitStatus |= UNIT_BAD;
  745.       vol.freeUnits--;
  746.       return status;
  747.     }
  748.   }
  749.   /* mark unit assigned */
  750.   vol.physicalUnits[unitNo].unitStatus &= ~STATUS_MASK;
  751.   vol.physicalUnits[unitNo].unitStatus |= UNIT_AVAILABLE;
  752.   vol.freeUnits--;
  753.   vol.virtualUnits[virtualUnitNo] = unitNo;
  754.   return flOK;
  755. }
  756. /*----------------------------------------------------------------------*/
  757. /*            f i n i s h U n i t T r a n s f e r */
  758. /* */
  759. /* Finish unit transfer from replaced unit to transfer unit. */
  760. /* copy all the sectors that were not replaced from the replaced unit   */
  761. /* to the transfer unit. This routine is called when either another */
  762. /* unit needs replacement, or we finished the current Flie function. */
  763. /*                                                                      */
  764. /* Parameters:                                                          */
  765. /* vol : Pointer identifying drive */
  766. /*                                                                      */
  767. /* Returns:                                                             */
  768. /* FLStatus : 0 on success, failed otherwise */
  769. /*----------------------------------------------------------------------*/
  770. static FLStatus finishUnitTransfer(SSFDC vol)
  771. {
  772.   unsigned char ecc[3];
  773.   UnitNo virtualUnitNo;
  774.   unsigned freeSectors = 0, sector;  /* count the number of free sectors */
  775.   if (vol.replacedUnit == NO_UNIT) /* no unit to fold */
  776.     return flOK;
  777.   for (sector = 0; sector < vol.sectorsPerUnit; sector++) {
  778.     if (vol.replacementSectors[sector] == SECTOR_ALLOCATED) { /* copy only sectors
  779.  that holds valid data */
  780.       CardAddress fromSectorAddress, toSectorAddress;
  781.       fromSectorAddress = unitBaseAddress(&vol, vol.replacedUnit) +
  782.   (sector << SECTOR_SIZE_BITS);
  783.       toSectorAddress = unitBaseAddress(&vol, vol.transferUnit) +
  784. (sector << SECTOR_SIZE_BITS);
  785.       vol.flash.read(&vol.flash, fromSectorAddress, ssfdcBuffer,SECTOR_SIZE,0);
  786.       vol.flash.socket->remapped = TRUE;
  787.       checkStatus(writeAndCheck(&vol, toSectorAddress, ssfdcBuffer, 0));
  788.       /* copy ecc fields instead of recalculating them */
  789.       vol.flash.read(&vol.flash, fromSectorAddress + ECC1, ecc, sizeof ecc, EXTRA);
  790.       checkStatus(vol.flash.write(&vol.flash, toSectorAddress + ECC1, ecc,
  791.   sizeof ecc, EXTRA));
  792.       vol.flash.read(&vol.flash, fromSectorAddress + ECC2, ecc, sizeof ecc, EXTRA);
  793.       checkStatus(vol.flash.write(&vol.flash, toSectorAddress + ECC2, ecc,
  794.   sizeof ecc, EXTRA));
  795.     }
  796.     if ((vol.replacementSectors[sector] == SECTOR_ERASED) ||
  797. (vol.replacementSectors[sector] == SECTOR_DELETED1))
  798.       freeSectors++;
  799.   }
  800.   /* the old transfer unit gets the virtual number of the replaced unit */
  801.   virtualUnitNo = physical2Virtual(&vol, vol.replacedUnit, OFFSET1);
  802.   if (virtualUnitNo >= vol.noOfVirtualUnits) {
  803.     /* first address area is not good try the second address area */
  804.     virtualUnitNo = physical2Virtual(&vol, vol.replacedUnit, OFFSET2);
  805.     if (virtualUnitNo >= vol.noOfVirtualUnits)
  806.       return flGeneralFailure;
  807.   }
  808.   if (freeSectors < vol.sectorsPerUnit) {
  809.     checkStatus(assignUnit(&vol, vol.transferUnit, virtualUnitNo));
  810.     checkStatus(formatUnit(&vol, vol.replacedUnit));
  811.     vol.transferUnit = vol.replacedUnit;  /* The old transfer unit is dead,
  812.      long live the new one */
  813.   }
  814.   vol.replacedUnit = NO_UNIT;
  815.   return flOK;
  816. }
  817. /*----------------------------------------------------------------------*/
  818. /*                    t l s e t B u s y */
  819. /* */
  820. /* Notifies the start and end of a file-system operation. */
  821. /* On exit, finish unit transfer (if necessary). */
  822. /* */
  823. /* Parameters:                                                          */
  824. /* vol : Pointer identifying drive */
  825. /*      state : TFFS_ON (1) = operation entry */
  826. /*   TFFS_OFF(0) = operation exit */
  827. /*                                                                      */
  828. /*----------------------------------------------------------------------*/
  829. static void tlSetBusy(SSFDC vol, FLBoolean state)
  830. {
  831.   if (state == TFFS_ON)
  832.     vol.replacedUnit = NO_UNIT;  /* in case we exit without doing anything */
  833.   else
  834.     finishUnitTransfer(&vol);  /* I ignore the returned status */
  835. }
  836. /*----------------------------------------------------------------------*/
  837. /*                    s e t R e p l a c e m e n t U n i t */
  838. /* */
  839. /* Set a replaced unit. From now on, if write inplace to this unit */
  840. /* is impossible, write to the transfer unit instead. this routine */
  841. /* reads the status of each sector in the unit and updates the replaced */
  842. /* sectors table. */
  843. /* */
  844. /* Parameters:                                                          */
  845. /* vol : Pointer identifying drive */
  846. /*  unitNo : The new replaced unit */
  847. /*                                                                      */
  848. /*----------------------------------------------------------------------*/
  849. static void setReplacementUnit(SSFDC vol, UnitNo unitNo)
  850. {
  851.   int iSector;
  852.   StatusArea statusArea;
  853.   vol.replacedUnit = unitNo;
  854.   vol.sectorsDeleted = 0;
  855.   for (iSector = 0; (unsigned)iSector < vol.sectorsPerUnit; iSector++) {
  856.     vol.flash.read(&vol.flash, unitBaseAddress(&vol, unitNo) + (iSector << SECTOR_SIZE_BITS) +
  857.    STATUS_AREA_OFFSET, &statusArea, sizeof statusArea, EXTRA);
  858.     if (statusArea.sectorStatus != 0xff) {
  859.       vol.replacementSectors[iSector] = SECTOR_DELETED1;
  860.       vol.sectorsDeleted++;
  861.       continue;
  862.     }
  863.     if (vol.physicalUnits[unitNo].erasedSectors & (1 << iSector))
  864.       vol.replacementSectors[iSector] = SECTOR_ERASED;
  865.     else
  866.       vol.replacementSectors[iSector] = SECTOR_ALLOCATED;
  867.   }
  868. }
  869. /*----------------------------------------------------------------------*/
  870. /*                    m a r k S e c t o r D e l e t e d */
  871. /* */
  872. /* Mark a sector as deleted on the media, and update the unassigned */
  873. /* sectors counter in the physical units table. */
  874. /* */
  875. /* Parameters:                                                          */
  876. /* vol : Pointer identifying drive */
  877. /*  unitNo : The sector is in this unit */
  878. /* unitOffset : The offset of the sector in the unit */
  879. /*                                                                      */
  880. /* Returns: */
  881. /* FLStatus        : 0 on success, failed otherwise */
  882. /*----------------------------------------------------------------------*/
  883. static FLStatus markSectorDeleted(SSFDC vol, UnitNo unitNo, unsigned unitOffset)
  884. {
  885.   StatusArea statusArea;
  886.   /* check if this sector is already deleted or erased */
  887.   vol.flash.read(&vol.flash, unitBaseAddress(&vol, unitNo) +
  888.      unitOffset + STATUS_AREA_OFFSET,
  889.  &statusArea, sizeof statusArea, EXTRA);
  890.   if ((statusArea.sectorStatus != 0xff) ||
  891.       (vol.physicalUnits[unitNo].erasedSectors & (1 << (unitOffset / SECTOR_SIZE))))
  892.     return flOK;    /* sector is erased or already deleted */
  893.   statusArea.sectorStatus = 0;
  894.   statusArea.unitStatus = 0xff;
  895.   vol.physicalUnits[unitNo].unitStatus++;
  896.   return vol.flash.write(&vol.flash, unitBaseAddress(&vol, unitNo) +
  897.      unitOffset + STATUS_AREA_OFFSET,
  898.  &statusArea, sizeof statusArea, EXTRA);
  899. }
  900. /*----------------------------------------------------------------------*/
  901. /*                    a l l o c a t e U n i t */
  902. /* */
  903. /* Find a free unit to allocate, erase it if necessary. */
  904. /* */
  905. /* Parameters:                                                          */
  906. /* vol : Pointer identifying drive */
  907. /*  unitNo : Receives the physical number of the allocated */
  908. /*   unit  */
  909. /* Returns: */
  910. /* FLStatus : 0 on success, failed otherwise */
  911. /*----------------------------------------------------------------------*/
  912. static FLStatus allocateUnit(SSFDC vol, UnitNo *unitNo)
  913. {
  914.   UnitNo originalUnit = vol.roverUnit;
  915.   if (vol.freeUnits > 1) {    /* the transfer unit is always free */
  916.     do {
  917. /* VF: Take 8- vs. 16-bit PhysUnit quantity into account: */
  918. #if (TFFS_SECTORS_PER_UNIT < 32)
  919.       unsigned char unitFlags;
  920. #else
  921.       unsigned short unitFlags;
  922. #endif
  923.       if (++vol.roverUnit == vol.transferUnit) /* we don't want to allocate this one */
  924. vol.roverUnit++;
  925.       if (vol.roverUnit >= vol.noOfUnits)  /* we got to the end, wrap around */
  926. vol.roverUnit = vol.CISblock;
  927.       unitFlags = vol.physicalUnits[vol.roverUnit].unitStatus;
  928.       if (((unitFlags & STATUS_MASK) == UNIT_FREE) ||
  929.   ((unitFlags & STATUS_MASK) == UNIT_ERASED)) {
  930. if ((unitFlags & STATUS_MASK) == UNIT_FREE)
  931.   checkStatus(formatUnit(&vol, vol.roverUnit));
  932. *unitNo = vol.roverUnit;
  933. return flOK;
  934.       }
  935.     } while (vol.roverUnit != originalUnit);
  936.     return flGeneralFailure;  /* Didn't find the free units */
  937.   }
  938.   return flNotEnoughMemory;
  939. }
  940. #if defined(DEFRAGMENT_VOLUME) || defined(SINGLE_BUFFER)
  941. /*----------------------------------------------------------------------*/
  942. /*                   d e f r a g m e n t */
  943. /* */
  944. /* Performs unit allocations to arrange a minimum number of writable */
  945. /* sectors.                                                             */
  946. /* */
  947. /* Parameters:                                                          */
  948. /* vol : Pointer identifying drive */
  949. /* sectorsNeeded : Minimum required sectors */
  950. /*                                                                      */
  951. /* Returns:                                                             */
  952. /* FLStatus : 0 on success, failed otherwise */
  953. /*----------------------------------------------------------------------*/
  954. static FLStatus defragment(SSFDC vol, long FAR2 *sectorsNeeded)
  955. {
  956.   UnitNo erasedUnits = 0, dummyUnit;
  957.   while (erasedUnits * vol.sectorsPerUnit < *sectorsNeeded) {
  958.     if (vol.badFormat)
  959.       return flBadFormat;
  960.     checkStatus(allocateUnit(&vol, &dummyUnit));
  961.     erasedUnits++;
  962.   }
  963.   *sectorsNeeded = erasedUnits * vol.sectorsPerUnit;
  964.   return flOK;
  965. }
  966. #endif
  967. /*----------------------------------------------------------------------*/
  968. /*            a l l o c a t e A n d W r i t e S e c t o r */
  969. /* */
  970. /* Write to virtual sectorNo. If sectorsNo is not assigned to any  */
  971. /* physical sector, allocate a new one and write it there. If sectorNo  */
  972. /* is assigned, try to write in place, if impossible, replace this      */
  973. /* sector in the transfer unit (finish the previous unit transfer       */
  974. /* first).  */
  975. /* */
  976. /* Parameters:                                                          */
  977. /* vol : Pointer identifying drive */
  978. /* sectorNo : Virtual sector no. to write */
  979. /* fromAddress : Address of sector data.  */
  980. /*                                                                      */
  981. /* Returns:                                                             */
  982. /* FLStatus : 0 on success, failed otherwise */
  983. /*----------------------------------------------------------------------*/
  984. static FLStatus allocateAndWriteSector(SSFDC vol,
  985.        SectorNo sectorNo,
  986.        void FAR1 *fromAddress)
  987. {
  988.   UnitNo virtualUnitNo = sectorNo / vol.sectorsPerUnit;
  989.   UnitNo unitNo = vol.virtualUnits[virtualUnitNo];
  990.   unsigned sectorInUnit = sectorNo % vol.sectorsPerUnit;
  991.   unsigned unitOffset = sectorInUnit << SECTOR_SIZE_BITS;
  992.   /* Find a unit to write this sector */
  993.   if ((unitNo != NO_UNIT) &&
  994.       ((vol.physicalUnits[unitNo].unitStatus & STATUS_MASK) == UNIT_AVAILABLE)) {
  995.     if (vol.replacedUnit == unitNo) {
  996.       /* this unit is replaced by the transfer unit */
  997.       if ((vol.replacementSectors[sectorInUnit] == SECTOR_REPLACED) ||
  998.   (vol.replacementSectors[sectorInUnit] == SECTOR_DELETED2)) {
  999. /* this sector was already replaced */
  1000. UnitNo oldTransferUnit = vol.transferUnit;
  1001. checkStatus(finishUnitTransfer(&vol));
  1002. setReplacementUnit(&vol, oldTransferUnit);
  1003.       }
  1004.       if (vol.replacementSectors[sectorInUnit] != SECTOR_ERASED)  {
  1005. /* write to the transfer unit, mark deleted in the replaced unit, and
  1006.    mark replaced in the replaced sectors table. */
  1007. checkStatus(writeAndCheck(&vol, unitBaseAddress(&vol, vol.transferUnit) +
  1008. unitOffset,
  1009.   fromAddress, 1))
  1010. checkStatus(markSectorDeleted(&vol, vol.replacedUnit, unitOffset));
  1011. vol.replacementSectors[sectorInUnit] = SECTOR_REPLACED;
  1012.       }
  1013.       else {   /* sector erased, write inplace */
  1014. checkStatus(writeAndCheck(&vol, unitBaseAddress(&vol, vol.replacedUnit) +
  1015. unitOffset,
  1016.   fromAddress, 1));
  1017. vol.replacementSectors[sectorInUnit] = SECTOR_ALLOCATED;
  1018.       }
  1019.     }
  1020.     else {
  1021.       if (vol.physicalUnits[unitNo].erasedSectors &
  1022.   (1 << (unitOffset / SECTOR_SIZE))) {
  1023. /* sector is erased, write inplace */
  1024. checkStatus(writeAndCheck(&vol, unitBaseAddress(&vol, unitNo) + unitOffset,
  1025.   fromAddress, 1));
  1026.       }
  1027.       else {
  1028. /* finish the previous transfer first */
  1029. checkStatus(finishUnitTransfer(&vol));
  1030. setReplacementUnit(&vol, unitNo);
  1031. /* write to the transfer unit, mark deleted in the replaced unit, and
  1032.    mark replaced in the replaced sectors table. */
  1033. checkStatus(writeAndCheck(&vol, unitBaseAddress(&vol, vol.transferUnit) +
  1034. unitOffset,
  1035.   fromAddress, 1))
  1036. checkStatus(markSectorDeleted(&vol, vol.replacedUnit, unitOffset));
  1037. vol.replacementSectors[sectorInUnit] = SECTOR_REPLACED;
  1038.       }
  1039.     }
  1040.   }
  1041.   else {
  1042.     /* this sector is unassigned, find a free unit and write the sector there */
  1043.     UnitNo toUnit;
  1044.     checkStatus(allocateUnit(&vol, &toUnit));
  1045.     checkStatus(writeAndCheck(&vol, unitBaseAddress(&vol, toUnit) + unitOffset,
  1046.       fromAddress, 1));
  1047.     checkStatus(assignUnit(&vol, toUnit, virtualUnitNo));
  1048.   }
  1049.   return flOK;
  1050. }
  1051. /*----------------------------------------------------------------------*/
  1052. /*                d e l e t e S e c t o r */
  1053. /* */
  1054. /* Marks contiguous sectors as deleted. */
  1055. /* Update unassigned sectors counter in physical units table, and */
  1056. /* deleted replaced sectors table. If all the sectors in a unit are     */
  1057. /* deleted, mark it as free. */
  1058. /* */
  1059. /* Parameters:                                                          */
  1060. /* vol : Pointer identifying drive */
  1061. /* sectorNo : First sector no. to delete */
  1062. /* noOfSectors : No. of sectors to delete */
  1063. /*                                                                      */
  1064. /* Returns:                                                             */
  1065. /* FLStatus : 0 on success, failed otherwise */
  1066. /*----------------------------------------------------------------------*/
  1067. static FLStatus deleteSector(SSFDC vol, SectorNo sectorNo, int noOfSectors)
  1068. {
  1069.   int iSector;
  1070.   if (vol.badFormat)
  1071.     return flBadFormat;
  1072.   if (sectorNo + noOfSectors > vol.virtualSectors)
  1073.     return flSectorNotFound;
  1074.   for (iSector = 0; iSector < noOfSectors; iSector++, sectorNo++) {
  1075.     unsigned sectorInUnit = sectorNo % vol.sectorsPerUnit;
  1076.     CardAddress sectorAddress = virtual2Physical(&vol, sectorNo);
  1077.     if (sectorAddress != UNASSIGNED_ADDRESS) {
  1078.       UnitNo virtualUnitNo = sectorNo / vol.sectorsPerUnit;
  1079.       UnitNo unitNo = vol.virtualUnits[virtualUnitNo];
  1080.       if (!(vol.physicalUnits[unitNo].unitStatus & UNIT_AVAILABLE) ||
  1081.   (unitNo == NO_UNIT))
  1082. return flSectorNotFound;
  1083.       if (unitNo == vol.replacedUnit) {
  1084. /* this sector was replaced, mark it in the transfer unit, and
  1085.    update the repleced sectors table. */
  1086. if (vol.replacementSectors[sectorInUnit] == SECTOR_REPLACED) {
  1087.   checkStatus(markSectorDeleted(&vol, vol.transferUnit,
  1088. sectorInUnit << SECTOR_SIZE_BITS));
  1089.   vol.replacementSectors[sectorInUnit] = SECTOR_DELETED2;
  1090. }
  1091. else {
  1092.   checkStatus(markSectorDeleted(&vol, unitNo,
  1093. sectorInUnit << SECTOR_SIZE_BITS));
  1094.   vol.replacementSectors[sectorInUnit] = SECTOR_DELETED1;
  1095. }
  1096. if (++vol.sectorsDeleted >= vol.sectorsPerUnit) {
  1097.   /* all the sectors in the replaced unit are deleted, no point
  1098.      to keep their deleted copy in the transfer unit. */
  1099.   checkStatus(formatUnit(&vol, vol.transferUnit));
  1100.   vol.physicalUnits[vol.replacedUnit].unitStatus &= ~STATUS_MASK;
  1101.   vol.physicalUnits[vol.replacedUnit].unitStatus |= UNIT_FREE;
  1102.   vol.virtualUnits[virtualUnitNo] = NO_UNIT;
  1103.   vol.replacedUnit = NO_UNIT;
  1104.   vol.freeUnits++;
  1105. }
  1106.       }
  1107.       else {  /* this sector is not in the replaced unit */
  1108. checkStatus(markSectorDeleted(&vol, unitNo,
  1109.       sectorInUnit << SECTOR_SIZE_BITS));
  1110. if ((vol.physicalUnits[unitNo].unitStatus & ~STATUS_MASK) ==
  1111.      (int)vol.sectorsPerUnit) {
  1112.   /* all the sectors in this unit are unassigned, it can be marked
  1113.      as free. */
  1114.   vol.physicalUnits[unitNo].unitStatus &= ~STATUS_MASK;
  1115.   vol.physicalUnits[unitNo].unitStatus |= UNIT_FREE;
  1116.   vol.freeUnits++;
  1117.   vol.virtualUnits[virtualUnitNo] = NO_UNIT;
  1118. }
  1119.       }
  1120.     }
  1121.   }
  1122.   return flOK;
  1123. }
  1124. /*----------------------------------------------------------------------*/
  1125. /*                 w r i t e S e c t o r */
  1126. /* */
  1127. /* Writes a sector. */
  1128. /* */
  1129. /* Parameters:                                                          */
  1130. /* vol : Pointer identifying drive */
  1131. /* sectorNo : Sector no. to write */
  1132. /* fromAddress : Data to write */
  1133. /*                                                                      */
  1134. /* Returns:                                                             */
  1135. /* FLStatus        : 0 on success, failed otherwise */
  1136. /*----------------------------------------------------------------------*/
  1137. static FLStatus writeSector(SSFDC vol,SectorNo sectorNo, void FAR1 *fromAddress)
  1138. {
  1139.   FLStatus status;
  1140.   int i;
  1141.   if (vol.badFormat)
  1142.     return flBadFormat;
  1143.   if (sectorNo > vol.virtualSectors)
  1144.     return flSectorNotFound;
  1145.   status = flWriteFault;
  1146.   for (i = 0; i < 4 && status == flWriteFault; i++) {
  1147.     if (vol.mappedSectorNo == sectorNo)
  1148.       vol.mappedSectorNo = UNASSIGNED_SECTOR;
  1149.     status = allocateAndWriteSector(&vol,sectorNo,fromAddress);
  1150.   }
  1151.   return status;
  1152. }
  1153. /*----------------------------------------------------------------------*/
  1154. /*            m o u n t U n i t */
  1155. /* */
  1156. /* Mount one unit. Get the unit status (assigned, free or bad) and  */
  1157. /* update the tables. */
  1158. /*                                                                      */
  1159. /* Parameters:                                                          */
  1160. /* vol : Pointer identifying drive */
  1161. /* unitNo : Unit to mount */
  1162. /*                                                                      */
  1163. /* Returns:                                                             */
  1164. /* FLStatus : 0 on success, failed otherwise */
  1165. /*----------------------------------------------------------------------*/
  1166. static FLStatus mountUnit(SSFDC vol, UnitNo unitNo)
  1167. {
  1168.   StatusArea statusArea;
  1169.   UnitNo virtualUnitNo;
  1170.   /* initialize unassigned sectors counter */
  1171.   vol.physicalUnits[unitNo].unitStatus &= STATUS_MASK;
  1172.   vol.flash.read(&vol.flash, unitBaseAddress(&vol, unitNo) + STATUS_AREA_OFFSET,
  1173.  &statusArea, sizeof statusArea, EXTRA);
  1174.   if (statusArea.unitStatus != 0xff) {
  1175.     vol.physicalUnits[unitNo].unitStatus &= ~STATUS_MASK;
  1176.     vol.physicalUnits[unitNo].unitStatus |= UNIT_BAD;
  1177.     return flOK;
  1178.   }
  1179.   virtualUnitNo = physical2Virtual(&vol, unitNo, OFFSET1);
  1180.   if (virtualUnitNo >= vol.noOfVirtualUnits) {
  1181.     vol.physicalUnits[unitNo].unitStatus = UNIT_FREE | vol.sectorsPerUnit;
  1182.     vol.freeUnits++;
  1183.   }
  1184.   else {
  1185.     if (vol.virtualUnits[virtualUnitNo] != NO_UNIT) {
  1186.     /* there is another unit with this virtual address */
  1187.       vol.physicalUnits[unitNo].unitStatus = UNIT_FREE | vol.sectorsPerUnit;
  1188.       vol.freeUnits++;
  1189.     }
  1190.     else {  /* this unit is assigned */
  1191.       CardAddress unitBase;
  1192.       unsigned sector;
  1193.       vol.physicalUnits[unitNo].unitStatus &= ~STATUS_MASK;
  1194.       vol.physicalUnits[unitNo].unitStatus |= UNIT_AVAILABLE;
  1195.       vol.virtualUnits[virtualUnitNo] = unitNo;
  1196.       /* count the number of unassigned sectors and mark erased sectors */
  1197.       vol.physicalUnits[unitNo].erasedSectors = 0;
  1198.       unitBase = unitBaseAddress(&vol, unitNo);
  1199.       for (sector = 0; sector < vol.sectorsPerUnit; sector++) {
  1200. vol.flash.read(&vol.flash, unitBase + (sector << SECTOR_SIZE_BITS) +
  1201.    STATUS_AREA_OFFSET,
  1202.        &statusArea, sizeof statusArea, EXTRA);
  1203. if (statusArea.sectorStatus != 0xff)
  1204.   vol.physicalUnits[unitNo].unitStatus++;
  1205. else if (isErasedSector(&vol, unitNo, sector << SECTOR_SIZE_BITS)) {
  1206.   vol.physicalUnits[unitNo].unitStatus++;
  1207.   vol.physicalUnits[unitNo].erasedSectors |= (1 << sector);
  1208. }
  1209.       }
  1210.       /* check if all the sectors are unassigned */
  1211.       if ((vol.physicalUnits[unitNo].unitStatus & ~STATUS_MASK) ==
  1212.    (int)vol.sectorsPerUnit) {
  1213. vol.physicalUnits[unitNo].unitStatus &= ~STATUS_MASK;
  1214. vol.physicalUnits[unitNo].unitStatus |= UNIT_FREE;
  1215. vol.virtualUnits[virtualUnitNo] = NO_UNIT;
  1216. vol.freeUnits++;
  1217.       }
  1218.     }
  1219.   }
  1220.   /* prepare a transfer unit */
  1221.   if (((vol.physicalUnits[unitNo].unitStatus & STATUS_MASK) == UNIT_FREE) &&
  1222.       (vol.transferUnit == NO_UNIT)) {
  1223.     checkStatus (formatUnit(&vol, unitNo));
  1224.     vol.transferUnit = unitNo;
  1225.   }
  1226.   return flOK;
  1227. }
  1228. /*----------------------------------------------------------------------*/
  1229. /*                        i n i t S S F D C */
  1230. /* */
  1231. /* Initializes essential volume data as a preparation for mount or */
  1232. /* format. */
  1233. /* */
  1234. /* Parameters:                                                          */
  1235. /* vol : Pointer identifying drive */
  1236. /*                                                                      */
  1237. /* Returns:                                                             */
  1238. /* FLStatus : 0 on success, failed otherwise */
  1239. /*----------------------------------------------------------------------*/
  1240. static FLStatus initSSFDC(SSFDC vol)
  1241. {
  1242.   long int size = 1;
  1243.   if (!(vol.flash.flags & NFTL_ENABLED)) {
  1244.   #ifdef DEBUG_PRINT
  1245.     DEBUG_PRINT("Debug: media is not fit for SSFDC format.n");
  1246.   #endif
  1247.     return flUnknownMedia;
  1248.   }
  1249.   vol.physicalUnits = NULL;
  1250.   vol.virtualUnits = NULL;
  1251.   for (vol.erasableBlockSizeBits = 0; size < vol.flash.erasableBlockSize;
  1252.        vol.erasableBlockSizeBits++, size <<= 1);
  1253.   vol.unitSizeBits = vol.erasableBlockSizeBits;
  1254.   vol.noOfUnits = (vol.flash.noOfChips * vol.flash.chipSize) >> vol.unitSizeBits;
  1255.   vol.badFormat = TRUE; /* until mount completes*/
  1256.   vol.mappedSectorNo = UNASSIGNED_SECTOR;
  1257.   /*get pointer to buffer (we assume SINGLE_BUFFER is not defined) */
  1258.   vol.buffer = flBufferOf(flSocketNoOf(vol.flash.socket));
  1259.   return flOK;
  1260. }
  1261. /*----------------------------------------------------------------------*/
  1262. /*                   i n i t T a b l e s */
  1263. /* */
  1264. /* Allocates and initializes the dynamic volume table, including the */
  1265. /* unit tables and secondary virtual map. */
  1266. /* */
  1267. /* Parameters:                                                          */
  1268. /* vol : Pointer identifying drive */
  1269. /*                                                                      */
  1270. /* Returns:                                                             */
  1271. /* FLStatus : 0 on success, failed otherwise */
  1272. /*----------------------------------------------------------------------*/
  1273. static FLStatus initTables(SSFDC vol)
  1274. {
  1275.   /* Allocate the conversion tables */
  1276. #ifdef MALLOC_TFFS
  1277.   vol.physicalUnits = (Unit *) MALLOC_TFFS(vol.noOfUnits * sizeof(Unit));
  1278.   vol.virtualUnits = (UnitNo *) MALLOC_TFFS(vol.noOfVirtualUnits * sizeof(UnitNo));
  1279.   vol.replacementSectors = (unsigned char *)
  1280.    MALLOC_TFFS(vol.sectorsPerUnit * sizeof(unsigned char));
  1281.   if (vol.physicalUnits == NULL ||
  1282.       vol.virtualUnits == NULL ||
  1283.       vol.replacementSectors == NULL) {
  1284.   #ifdef DEBUG_PRINT
  1285.     DEBUG_PRINT("Debug: Failed allocating conversion tables for SSFDC.n");
  1286.   #endif
  1287.     return flNotEnoughMemory;
  1288.   }
  1289. #else
  1290.   char *heapPtr;
  1291.   heapPtr = vol.heap;
  1292.   vol.physicalUnits = (Unit *) heapPtr;
  1293.   heapPtr += vol.noOfUnits * sizeof(Unit);
  1294.   vol.virtualUnits = (UnitNo *) heapPtr;
  1295.   heapPtr += vol.noOfVirtualUnits * sizeof(UnitNo);
  1296.   vol.replacementSectors = (unsigned char *) heapPtr;
  1297.   heapPtr += vol.sectorsPerUnit * sizeof(unsigned char);
  1298.   if (heapPtr > vol.heap + sizeof vol.heap) {
  1299.   #ifdef DEBUG_PRINT
  1300.     DEBUG_PRINT("Debug: Not enough memory for SSFDC conversion tables.n");
  1301.   #endif
  1302.     return flNotEnoughMemory;
  1303.   }
  1304. #endif
  1305.   return flOK;
  1306. }
  1307. /*----------------------------------------------------------------------*/
  1308. /*                d i s m o u n t S S F D C */
  1309. /* */
  1310. /* Dismount SSFDC volume */
  1311. /* */
  1312. /* Parameters:                                                          */
  1313. /* vol : Pointer identifying drive */
  1314. /* */
  1315. /*----------------------------------------------------------------------*/
  1316. static void dismountSSFDC(SSFDC vol)
  1317. {
  1318.   finishUnitTransfer(&vol);  /* copy replaced sectors if needed */
  1319. #ifdef MALLOC_TFFS
  1320.   FREE_TFFS(vol.physicalUnits);
  1321.   FREE_TFFS(vol.virtualUnits);
  1322.   FREE_TFFS(vol.replacementSectors);
  1323. #endif
  1324. }
  1325. /*----------------------------------------------------------------------*/
  1326. /*                      m o u n t S S F D C */
  1327. /* */
  1328. /* Mount the volume */
  1329. /* */
  1330. /* Parameters:                                                          */
  1331. /* flash : Flash media to mount */
  1332. /* tl : Mounted translation layer on exit */
  1333. /*      volForCallback : Pointer to FLFlash structure for power on */
  1334. /*   callback routine. */
  1335. /*                                                                      */
  1336. /* Returns:                                                             */
  1337. /* FLStatus : 0 on success, failed otherwise */
  1338. /*----------------------------------------------------------------------*/
  1339. /*static*/ FLStatus mountSSFDC(FLFlash *flash, TL *tl, FLFlash **volForCallback)
  1340. {
  1341.   SSFDC vol = &vols[flSocketNoOf(flash->socket)];
  1342.   UnitNo iUnit;
  1343. #ifdef DEBUG_PRINT
  1344.   DEBUG_PRINT("Debug: starting SSFDC mount.n");
  1345. #endif
  1346.   vol.replacedUnit = NO_UNIT; /* this is for finishUnitTransfer in case mount fails */
  1347.   vol.flash = *flash;
  1348.   *volForCallback = &vol.flash;
  1349.   checkStatus(initSSFDC(&vol));
  1350.   vol.sectorsPerUnit = 1 << (vol.unitSizeBits - SECTOR_SIZE_BITS);
  1351.   if (identifyFormat(&vol, &vol.CISblock) != SSFDC_FORMAT) {
  1352.   #ifdef DEBUG_PRINT
  1353.     DEBUG_PRINT("Debug: not SSFDC format.n");
  1354.   #endif
  1355.     return flUnknownMedia;
  1356.   }
  1357.   vol.virtualSectors = vol.sectorsPerUnit;
  1358.   if (vol.noOfUnits < 500)
  1359.     vol.virtualSectors *= 250;         /* 1 MByte chip        */
  1360.   else if (vol.noOfUnits < 1000)
  1361.     vol.virtualSectors *= 500;         /* 2 or 4 MByte chip   */
  1362.   else
  1363.     vol.virtualSectors *= 1000;        /* 8 0r 16 MByte chip  */
  1364.   vol.unitOffsetMask = (1L << vol.unitSizeBits) - 1;
  1365.   vol.noOfVirtualUnits = (vol.virtualSectors + vol.sectorsPerUnit - 1) /
  1366.  vol.sectorsPerUnit;
  1367.   if ((vol.virtualSectors >> (vol.unitSizeBits - SECTOR_SIZE_BITS)) >
  1368.       (unsigned long)(vol.noOfUnits - 1))
  1369.     return flBadFormat;
  1370.   checkStatus(initTables(&vol));
  1371.   vol.badFormat = FALSE;
  1372.   vol.transferUnit = NO_UNIT;
  1373.   for (iUnit = 0; iUnit < vol.noOfVirtualUnits; iUnit++)
  1374.     vol.virtualUnits[iUnit] = NO_UNIT;
  1375.   /* Mount all units */
  1376.   vol.freeUnits = 0;
  1377.   for (iUnit = vol.CISblock; iUnit < vol.noOfUnits; iUnit++) {
  1378.     if (iUnit == vol.CISblock)
  1379.       vol.physicalUnits[iUnit].unitStatus &= ~UNIT_AVAILABLE;
  1380.     else
  1381.       checkStatus(mountUnit(&vol, iUnit));
  1382.   }
  1383.   /* Initialize allocation rover */
  1384.   vol.roverUnit = vol.CISblock;
  1385.   tl->rec = &vol;
  1386.   tl->mapSector = mapSector;
  1387.   tl->writeSector = writeSector;
  1388.   tl->deleteSector = deleteSector;
  1389. #if defined(DEFRAGMENT_VOLUME) || defined(SINGLE_BUFFER)
  1390.   tl->defragment = defragment;
  1391. #endif
  1392. #ifdef FORMAT_VOLUME
  1393.   tl->sectorsInVolume = sectorsInVolume;
  1394. #endif
  1395.   tl->tlSetBusy = tlSetBusy;
  1396.   tl->dismount = dismountSSFDC;
  1397. #ifdef DEBUG_PRINT
  1398.   DEBUG_PRINT("Debug: finished SSFDC mount.n");
  1399. #endif
  1400.   return flOK;
  1401. }
  1402. #ifdef FORMAT_VOLUME
  1403. /*----------------------------------------------------------------------*/
  1404. /*                      i s E r a s e d U n i t */
  1405. /* */
  1406. /* Check if a unit is erased.                                           */
  1407. /* */
  1408. /* Parameters:                                                          */
  1409. /* vol : Pointer identifying drive */
  1410. /*                                                                      */
  1411. /* Returns:                                                             */
  1412. /* TRUE if unit is erased, FALSE otherwise */
  1413. /*----------------------------------------------------------------------*/
  1414. static FLBoolean isErasedUnit(SSFDC vol, UnitNo unitNo)
  1415. {
  1416.   CardAddress offset;
  1417.   for (offset = 0; (long)offset < (1L << vol.unitSizeBits); offset += SECTOR_SIZE)
  1418.     if (!(isErasedSector(&vol, unitNo, offset)))
  1419.       return FALSE;
  1420.   return TRUE;
  1421. }
  1422. /*----------------------------------------------------------------------*/
  1423. /*                     f o r m a t S S F D C */
  1424. /* */
  1425. /* Perform SSFDC Format. */
  1426. /* */
  1427. /* Parameters:                                                          */
  1428. /* flash : Flash media to format */
  1429. /* formatParams : Address of FormatParams structure to use */
  1430. /*                                                                      */
  1431. /* Returns:                                                             */
  1432. /* FLStatus : 0 on success, failed otherwise */
  1433. /*----------------------------------------------------------------------*/
  1434. /*static*/ FLStatus formatSSFDC(FLFlash *flash, FormatParams FAR1 *formatParams)
  1435. {
  1436.   SSFDC vol = &vols[flSocketNoOf(flash->socket)];
  1437.   long int unitSize;
  1438.   UnitNo iUnit;
  1439.   unsigned char CISblock[SECTOR_SIZE] = {CIS_DATA}, CISextra[16], ecc[3];
  1440. #ifdef DEBUG_PRINT
  1441.   DEBUG_PRINT("Debug: Starting SSFDC format.n");
  1442. #endif
  1443.   vol.replacedUnit = NO_UNIT; /* this is for finishUnitTransfer in case format fails */
  1444.   vol.flash = *flash;
  1445.   checkStatus(initSSFDC(&vol));
  1446.   vol.unitOffsetMask = (1L << vol.unitSizeBits) - 1;
  1447.   vol.sectorsPerUnit = 1 << (vol.unitSizeBits - SECTOR_SIZE_BITS);
  1448.   unitSize = 1L << vol.unitSizeBits;
  1449.   vol.virtualSectors = vol.sectorsPerUnit;
  1450.   if (vol.noOfUnits < 500)
  1451.     vol.virtualSectors *= 250;         /* 1 MByte chip        */
  1452.   else if (vol.noOfUnits < 1000)
  1453.     vol.virtualSectors *= 500;         /* 2 or 4 MByte chip   */
  1454.   else
  1455.     vol.virtualSectors *= 1000;        /* 8 0r 16 MByte chip  */
  1456.   vol.noOfVirtualUnits = (vol.virtualSectors + vol.sectorsPerUnit - 1) /
  1457.  vol.sectorsPerUnit;
  1458.   checkStatus(initTables(&vol));
  1459.   for (iUnit = 0; iUnit < vol.noOfVirtualUnits; iUnit++)
  1460.     vol.virtualUnits[iUnit] = NO_UNIT;
  1461.   /* Find the medium boot record and identify the format */
  1462.   if (identifyFormat(&vol, &vol.CISblock) != SSFDC_FORMAT) {
  1463.     /* not ssfdc format - scan it for bad blocks */
  1464.     /* Generate the bad unit table and find a place for the CIS */
  1465.     vol.CISblock = vol.noOfUnits;
  1466.     for (iUnit = 0; iUnit < vol.noOfUnits; iUnit++) {
  1467.       if (isErasedUnit(&vol, iUnit)) {
  1468. vol.physicalUnits[iUnit].unitStatus &= ~STATUS_MASK;
  1469. vol.physicalUnits[iUnit].unitStatus |= UNIT_ERASED;
  1470. if (vol.CISblock == vol.noOfUnits)
  1471.   vol.CISblock = iUnit;
  1472.       }
  1473.       else {
  1474. vol.physicalUnits[iUnit].unitStatus &= ~STATUS_MASK;
  1475. vol.physicalUnits[iUnit].unitStatus |= UNIT_BAD;
  1476.       }
  1477.     }
  1478.     if (vol.CISblock == vol.noOfUnits) {
  1479.     #ifdef DEBUG_PRINT
  1480.       DEBUG_PRINT("Debug: format failed, too many bad blocks.n");
  1481.     #endif
  1482.       return flGeneralFailure;
  1483.     }
  1484.   }
  1485.   else {  /* ssfdc format - read unit status from block status area */
  1486.     StatusArea statusArea;
  1487.     for (iUnit = 0; iUnit < vol.noOfUnits; iUnit++) {
  1488.       vol.flash.read(&vol.flash, unitBaseAddress(&vol, iUnit) + STATUS_AREA_OFFSET,
  1489.      &statusArea, sizeof statusArea, EXTRA);
  1490.       vol.physicalUnits[iUnit].unitStatus &= ~STATUS_MASK;
  1491.       vol.physicalUnits[iUnit].unitStatus |= (statusArea.unitStatus == 0xff)
  1492.     ? UNIT_FREE : UNIT_BAD;
  1493.     }
  1494.   }
  1495.   /* protect the CIS block */
  1496.   vol.physicalUnits[vol.CISblock].unitStatus &= ~UNIT_AVAILABLE;
  1497.   /* format all units */
  1498.   for (iUnit = vol.CISblock; iUnit < vol.noOfUnits; iUnit++) {
  1499.     FLStatus status = formatUnit(&vol, iUnit);
  1500.     if(status == flWriteFault) {
  1501.       if (iUnit != vol.CISblock)
  1502. if ((vol.physicalUnits[iUnit].unitStatus & STATUS_MASK) != UNIT_BAD) {
  1503.   vol.physicalUnits[iUnit].unitStatus &= ~STATUS_MASK;
  1504.   vol.physicalUnits[iUnit].unitStatus |= UNIT_BAD;
  1505. }
  1506.     }
  1507.     else if (status != flOK)
  1508.       return status;
  1509.   }
  1510.   /* Write the CIS block */
  1511.   vol.physicalUnits[vol.CISblock].unitStatus &= ~STATUS_MASK;
  1512.   vol.physicalUnits[vol.CISblock].unitStatus |= UNIT_FREE;     /* Unprotect it */
  1513.   checkStatus(formatUnit(&vol, vol.CISblock));
  1514.   checkStatus(vol.flash.write(&vol.flash, unitBaseAddress(&vol, vol.CISblock),
  1515.    CISblock, sizeof CISblock, 0));
  1516.   /* write extra bytes */
  1517.   createEcc(CISblock, ecc);
  1518.   tffsset(CISextra, 0xff, sizeof CISextra);
  1519.   CISextra[CIS_DATA_OFFSET+2] = CISextra[CIS_DATA_OFFSET+3] = 0;
  1520.   CISextra[ECC1] = CISextra[ECC2] = ecc[0];
  1521.   CISextra[ECC1+1] = CISextra[ECC2+1] = ecc[1];
  1522.   CISextra[ECC1+2] = CISextra[ECC2+2] = ecc[2];
  1523.   CISextra[ECC1-2] = CISextra[ECC1-1] = 0;
  1524.   checkStatus(vol.flash.write(&vol.flash, unitBaseAddress(&vol, vol.CISblock),
  1525.       CISextra, sizeof CISextra, EXTRA));
  1526.   /* Protect the CIS block */
  1527.   vol.physicalUnits[vol.CISblock].unitStatus &= ~UNIT_AVAILABLE;
  1528. #ifdef DEBUG_PRINT
  1529.   DEBUG_PRINT("Debug: finished SSFDC format.n");
  1530. #endif
  1531.   return flOK;
  1532. }
  1533. #endif /* FORMAT_VOLUME */
  1534. #if FLASE
  1535. /*----------------------------------------------------------------------*/
  1536. /*                f l R e g i s t e r S S F D C */
  1537. /* */
  1538. /* Register this translation layer */
  1539. /* */
  1540. /* Parameters:                                                          */
  1541. /* None */
  1542. /*                                                                      */
  1543. /* Returns: */
  1544. /* FLStatus : 0 on success, failed otherwise */
  1545. /*----------------------------------------------------------------------*/
  1546. FLStatus flRegisterSSFDC(void)
  1547. {
  1548.   if (noOfTLs >= TLS)
  1549.     return flTooManyComponents;
  1550.   tlTable[noOfTLs].mountRoutine = mountSSFDC;
  1551. #ifdef FORMAT_VOLUME
  1552.   tlTable[noOfTLs].formatRoutine = formatSSFDC;
  1553. #endif
  1554.   noOfTLs++;
  1555.   return flOK;
  1556. }
  1557. #endif /* FLASE */