140 iRootClusterNum=2; //As recomended in the document |
142 iRootClusterNum=2; //As recomended in the document |
141 iSectorsPerFat=MaxFat32Sectors(); |
143 iSectorsPerFat=MaxFat32Sectors(); |
142 |
144 |
143 } |
145 } |
144 |
146 |
|
147 const TFatType fatType = SuggestFatType(); |
|
148 |
145 // Ensure cluster size is a multiple of the block size |
149 // Ensure cluster size is a multiple of the block size |
146 TInt blockSizeInSectors = aCaps.iBlockSize >> iSectorSizeLog2; |
150 TInt blockSizeInSectors = aCaps.iBlockSize >> iSectorSizeLog2; |
147 __PRINT1(_L("blockSizeInSectors: %d"),blockSizeInSectors); |
151 __PRINT1(_L("blockSizeInSectors: %d"),blockSizeInSectors); |
148 ASSERT(blockSizeInSectors == 0 || IsPowerOf2(blockSizeInSectors)); |
152 ASSERT(blockSizeInSectors == 0 || IsPowerOf2(blockSizeInSectors)); |
149 if (blockSizeInSectors != 0 && IsPowerOf2(blockSizeInSectors)) |
153 if (blockSizeInSectors != 0 && IsPowerOf2(blockSizeInSectors)) |
150 { |
154 { |
151 __PRINT1(_L("iSectorsPerCluster (old): %d"),iSectorsPerCluster); |
155 __PRINT1(_L("iSectorsPerCluster (old): %d"),iSectorsPerCluster); |
152 AdjustClusterSize(blockSizeInSectors); |
156 AdjustClusterSize(blockSizeInSectors); |
153 __PRINT1(_L("iSectorsPerCluster (new): %d"),iSectorsPerCluster); |
157 __PRINT1(_L("iSectorsPerCluster (new): %d"),iSectorsPerCluster); |
154 } |
158 } |
155 |
159 |
156 // Align first data sector on an erase block boundary if |
160 |
157 // (1) the iEraseBlockSize is specified |
161 for (; iSectorsPerCluster>1; iSectorsPerCluster>>= 1) |
158 // (2) the start of the partition is already aligned to an erase block boundary, |
162 { |
159 // i.e. iHiddenSectors is zero or a multiple of iEraseBlockSize |
163 // Align first data sector on an erase block boundary if |
160 __PRINT1(_L("iHiddenSectors: %d"),iHiddenSectors); |
164 // (1) the iEraseBlockSize is specified |
161 TInt eraseblockSizeInSectors = aCaps.iEraseBlockSize >> iSectorSizeLog2; |
165 // (2) the start of the partition is already aligned to an erase block boundary, |
162 __PRINT1(_L("eraseblockSizeInSectors: %d"),eraseblockSizeInSectors); |
166 // i.e. iHiddenSectors is zero or a multiple of iEraseBlockSize |
163 ASSERT(eraseblockSizeInSectors == 0 || IsPowerOf2(eraseblockSizeInSectors)); |
167 __PRINT1(_L("iHiddenSectors: %d"),iHiddenSectors); |
164 ASSERT(eraseblockSizeInSectors == 0 || eraseblockSizeInSectors >= blockSizeInSectors); |
168 TInt eraseblockSizeInSectors = aCaps.iEraseBlockSize >> iSectorSizeLog2; |
165 if ((eraseblockSizeInSectors != 0) && |
169 __PRINT1(_L("eraseblockSizeInSectors: %d"),eraseblockSizeInSectors); |
166 (iHiddenSectors % eraseblockSizeInSectors == 0) && |
170 ASSERT(eraseblockSizeInSectors == 0 || IsPowerOf2(eraseblockSizeInSectors)); |
167 (IsPowerOf2(eraseblockSizeInSectors)) && |
171 ASSERT(eraseblockSizeInSectors == 0 || eraseblockSizeInSectors >= blockSizeInSectors); |
168 (eraseblockSizeInSectors >= blockSizeInSectors)) |
172 if ((eraseblockSizeInSectors != 0) && |
169 { |
173 (iHiddenSectors % eraseblockSizeInSectors == 0) && |
170 TInt r = AdjustFirstDataSectorAlignment(eraseblockSizeInSectors); |
174 (IsPowerOf2(eraseblockSizeInSectors)) && |
171 ASSERT(r == KErrNone); |
175 (eraseblockSizeInSectors >= blockSizeInSectors)) |
172 (void) r; |
176 { |
173 } |
177 TInt r = AdjustFirstDataSectorAlignment(eraseblockSizeInSectors); |
174 __PRINT1(_L("iReservedSectors: %d"),iReservedSectors); |
178 ASSERT(r == KErrNone); |
175 __PRINT1(_L("FirstDataSector: %d"), FirstDataSector()); |
179 (void) r; |
|
180 } |
|
181 __PRINT1(_L("iReservedSectors: %d"),iReservedSectors); |
|
182 __PRINT1(_L("FirstDataSector: %d"), FirstDataSector()); |
|
183 |
|
184 // If we've shrunk the number of clusters by so much that it's now invalid for this FAT type |
|
185 // then we need to decrease the cluster size and try again, otherwise we're finshed. |
|
186 if (SuggestFatType() == fatType) |
|
187 break; |
|
188 } |
|
189 __PRINT1(_L("iSectorsPerCluster (final): %d"),iSectorsPerCluster); |
176 |
190 |
177 return KErrNone; |
191 return KErrNone; |
178 } |
192 } |
179 |
193 |
180 TInt CFatFormatCB::FirstDataSector() const |
194 TInt CFatFormatCB::FirstDataSector() const |
181 { |
195 { |
182 TInt rootDirSectors = (iRootDirEntries * KSizeOfFatDirEntry + (iBytesPerSector-1)) / iBytesPerSector; |
196 TInt rootDirSectors = (iRootDirEntries * KSizeOfFatDirEntry + (iBytesPerSector-1)) / iBytesPerSector; |
183 return iHiddenSectors + iReservedSectors + iNumberOfFats*iSectorsPerFat + rootDirSectors; |
197 return iHiddenSectors + iReservedSectors + iNumberOfFats*iSectorsPerFat + rootDirSectors; |
184 } |
198 } |
185 |
199 |
186 void CFatFormatCB::AdjustClusterSize(TInt aRecommendedSectorsPerCluster) |
200 void CFatFormatCB::AdjustClusterSize(TUint aRecommendedSectorsPerCluster) |
187 { |
201 { |
188 const TInt KMaxSecPerCluster = 64; // 32K |
202 const TUint KMaxSecPerCluster = 64; // 32K |
|
203 |
189 while (aRecommendedSectorsPerCluster > iSectorsPerCluster && iSectorsPerCluster <= (KMaxSecPerCluster/2)) |
204 while (aRecommendedSectorsPerCluster > iSectorsPerCluster && iSectorsPerCluster <= (KMaxSecPerCluster/2)) |
190 iSectorsPerCluster<<= 1; |
205 iSectorsPerCluster<<= 1; |
|
206 |
191 } |
207 } |
192 |
208 |
193 // AdjustFirstDataSectorAlignment() |
209 // AdjustFirstDataSectorAlignment() |
194 // Attempts to align the first data sector on an erase block boundary by modifying the |
210 // Attempts to align the first data sector on an erase block boundary by modifying the |
195 // number of reserved sectors. |
211 // number of reserved sectors. |
196 TInt CFatFormatCB::AdjustFirstDataSectorAlignment(TInt aEraseBlockSizeInSectors) |
212 TInt CFatFormatCB::AdjustFirstDataSectorAlignment(TUint aEraseBlockSizeInSectors) |
197 { |
213 { |
198 const TBool bFat16 = Is16BitFat(); |
214 const TBool bFat16 = Is16BitFat(); |
199 const TBool bFat32 = Is32BitFat(); |
215 const TBool bFat32 = Is32BitFat(); |
200 |
216 |
201 // Save these 2 values in the event of a convergence failure; this should |
217 // Save these 2 values in the event of a convergence failure; this should |
202 // hopefully never happen, but we will cater for this in release mode to be safe, |
218 // hopefully never happen, but we will cater for this in release mode to be safe, |
203 TInt reservedSectorsSaved = iReservedSectors; |
219 TUint reservedSectorsSaved = iReservedSectors; |
204 TInt sectorsPerFatSaved = iSectorsPerFat; |
220 TUint sectorsPerFatSaved = iSectorsPerFat; |
205 |
221 |
206 TInt reservedSectorsOld = 0; |
222 TUint reservedSectorsOld = 0; |
207 |
223 |
208 // zero for FAT32 |
224 // zero for FAT32 |
209 TInt rootDirSectors = (iRootDirEntries * KSizeOfFatDirEntry + (iBytesPerSector-1)) / iBytesPerSector; |
225 TUint rootDirSectors = (iRootDirEntries * KSizeOfFatDirEntry + (iBytesPerSector-1)) / iBytesPerSector; |
210 TInt fatSectors = 0; |
226 TUint fatSectors = 0; |
211 |
227 |
212 TInt KMaxIterations = 10; |
228 TUint KMaxIterations = 10; |
213 TInt n; |
229 TUint n; |
214 for (n=0; n<KMaxIterations && reservedSectorsOld != iReservedSectors; n++) |
230 for (n=0; n<KMaxIterations && reservedSectorsOld != iReservedSectors; n++) |
215 { |
231 { |
216 reservedSectorsOld = iReservedSectors; |
232 reservedSectorsOld = iReservedSectors; |
217 |
233 |
218 iSectorsPerFat = bFat32 ? MaxFat32Sectors() : bFat16 ? MaxFat16Sectors() : MaxFat12Sectors(); |
234 iSectorsPerFat = bFat32 ? MaxFat32Sectors() : bFat16 ? MaxFat16Sectors() : MaxFat12Sectors(); |
599 iSectorsPerCluster = 1; |
615 iSectorsPerCluster = 1; |
600 iRootDirEntries = 128; |
616 iRootDirEntries = 128; |
601 } |
617 } |
602 else if (aDiskSizeInSectors < 8192) // < 4MB |
618 else if (aDiskSizeInSectors < 8192) // < 4MB |
603 { |
619 { |
604 iSectorsPerCluster = Min(iSectorsPerCluster, 2); |
620 iSectorsPerCluster = Min((TUint32)iSectorsPerCluster, (TUint32)2); |
605 iRootDirEntries = 256; |
621 iRootDirEntries = 256; |
606 } |
622 } |
607 else if (aDiskSizeInSectors < 32768) // < 16MB |
623 else if (aDiskSizeInSectors < 32768) // < 16MB |
608 { |
624 { |
609 iSectorsPerCluster = Min(iSectorsPerCluster, 4); |
625 iSectorsPerCluster = Min((TUint32)iSectorsPerCluster, (TUint32)4); |
610 iRootDirEntries = 512; |
626 iRootDirEntries = 512; |
611 } |
627 } |
612 else if (aDiskSizeInSectors < 1048576) // < 512MB |
628 else if (aDiskSizeInSectors < 1048576) // < 512MB |
613 { |
629 { |
614 iSectorsPerCluster = Min(iSectorsPerCluster, 8); |
630 iSectorsPerCluster = Min((TUint32)iSectorsPerCluster, (TUint32)8); |
615 iRootDirEntries = 512; |
631 iRootDirEntries = 512; |
616 } |
632 } |
617 else // FAT32 |
633 else // FAT32 |
618 { |
634 { |
619 iRootDirEntries = 512; |
635 iRootDirEntries = 512; |
620 iSectorsPerCluster = Min(iSectorsPerCluster, KMaxSecPerCluster); |
636 iSectorsPerCluster = Min((TUint32)iSectorsPerCluster, (TUint32)KMaxSecPerCluster); |
621 } |
637 } |
622 |
638 |
623 |
639 |
624 //----------------------------------------- |
640 //----------------------------------------- |
625 |
641 |
805 TInt sizeofFatAndRootDir; |
821 TInt sizeofFatAndRootDir; |
806 if (iFileSystemName != KFileSystemName32) |
822 if (iFileSystemName != KFileSystemName32) |
807 sizeofFatAndRootDir = iSectorsPerFat*iNumberOfFats + ((iRootDirEntries*KSizeOfFatDirEntry+(1<<iSectorSizeLog2)-1)>>iSectorSizeLog2); |
823 sizeofFatAndRootDir = iSectorsPerFat*iNumberOfFats + ((iRootDirEntries*KSizeOfFatDirEntry+(1<<iSectorSizeLog2)-1)>>iSectorSizeLog2); |
808 else |
824 else |
809 sizeofFatAndRootDir = (iRootClusterNum-2) * iSectorsPerCluster; |
825 sizeofFatAndRootDir = (iRootClusterNum-2) * iSectorsPerCluster; |
810 TInt firstFreeSector = iReservedSectors + sizeofFatAndRootDir; |
826 |
|
827 TUint firstFreeSector = iReservedSectors + sizeofFatAndRootDir; |
811 |
828 |
812 // Check in rare case that corrupt in critical area |
829 // Check in rare case that corrupt in critical area |
813 // which includes bootsector, FAT table, (and root dir if not FAT32) |
830 // which includes bootsector, FAT table, (and root dir if not FAT32) |
814 TInt i, r; |
831 TInt i, r; |
815 for (i=0; i<iBadSectors.Count(); ++i) |
832 for (i=0; i<iBadSectors.Count(); ++i) |
816 { |
833 { |
817 TInt badSector = iBadSectors[i]; |
834 const TUint badSector = iBadSectors[i]; |
818 // Check in rare case that corrupt in critical area |
835 // Check in rare case that corrupt in critical area |
819 // which includes bootsector, FAT table, (and root dir if not FAT32) |
836 // which includes bootsector, FAT table, (and root dir if not FAT32) |
820 if (firstFreeSector > badSector) |
837 if (firstFreeSector > badSector) |
821 { |
838 { |
822 if (badSector == 0) // Boot sector corrupt |
839 if (badSector == 0) // Boot sector corrupt |