00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 #include <string.h>
00027 
00028 #include "device.h"
00029 #include "rprintf.h"
00030 #include "debug.h"
00031 
00032 #include "fat.h"
00033 #include "fatconf.h"
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00041 unsigned char SectorBuffer[0x200];
00042 unsigned char FileNameBuffer[0x100];
00043 unsigned char PathNameBuffer[0x100];
00044 unsigned char FatCacheBuffer[0x200];
00045 
00046 struct fatFsInfo
00047 {
00048     unsigned long FirstDataSector;
00049     unsigned short BytesPerSector;
00050     unsigned short SectorsPerCluster;
00051     unsigned long FirstFATSector;
00052     unsigned long SectorsPerFat;
00053     unsigned long RootDirStartCluster;
00054     unsigned long FatInCache;
00055     unsigned long FatMask;
00056     unsigned char Fat32Enabled;
00057     unsigned char NumberOfFats;
00058 
00059     DevDisk_t devdisk;
00060 
00061 } GNUC_PACKED;
00062 
00063 typedef struct FatFsInfo FatFsInfo_t;
00064 
00065 
00066 struct fatFsInfo FatFsInfo;
00067 
00068 
00069 unsigned long CurrentDirStartCluster;   
00070 struct FileInfo_s FileInfo;             
00071 
00072 
00073 
00074 
00075 
00076 unsigned char fatInit(DevDisk_t* devdisk)
00077 {
00078     
00079     struct bpb710 *bpb;
00080 
00081     
00082     FatFsInfo.devdisk = *devdisk;
00083 
00084     rprintfProgStrM("DevDisk pointers\r\n");
00085     rprintfu32((unsigned long)devdisk->ReadSector);
00086     rprintfu32((unsigned long)devdisk->WriteSector);
00087     rprintfCRLF();
00088 
00089     FatFsInfo.FatInCache = 0;
00090 
00091     
00092     FatFsInfo.devdisk.ReadSector(0, 1, SectorBuffer);
00093     bpb = (struct bpb710 *) ((struct bootsector710 *) SectorBuffer)->bsBPB;
00094 
00095     
00096     if(bpb->bpbFATsecs)
00097     {
00098         
00099         FatFsInfo.SectorsPerFat = bpb->bpbFATsecs;
00100         
00101         
00102         FatFsInfo.RootDirStartCluster = CLUST_FIRST;
00103         
00104         
00105         FatFsInfo.Fat32Enabled = FALSE;
00106         
00107         FatFsInfo.FatMask = FAT16_MASK;
00108     }
00109     else
00110     {
00111         
00112         FatFsInfo.SectorsPerFat = bpb->bpbBigFATsecs;
00113         
00114         
00115         FatFsInfo.RootDirStartCluster = bpb->bpbRootClust;
00116         
00117         
00118         FatFsInfo.Fat32Enabled = TRUE;
00119         
00120         FatFsInfo.FatMask = FAT32_MASK;
00121     }
00122     FatFsInfo.SectorsPerCluster     = bpb->bpbSecPerClust;
00123     FatFsInfo.BytesPerSector        = bpb->bpbBytesPerSec;
00124     FatFsInfo.FirstFATSector        = bpb->bpbResSectors;
00125     FatFsInfo.NumberOfFats          = bpb->bpbFATs;
00126     FatFsInfo.FirstDataSector       = bpb->bpbResSectors + FatFsInfo.NumberOfFats * FatFsInfo.SectorsPerFat;
00127 
00128     
00129     CurrentDirStartCluster = FatFsInfo.RootDirStartCluster;
00130     PathNameBuffer[0] = '\\';
00131     PathNameBuffer[1] = 0;
00132 
00133     
00134 #ifdef DEBUG_FAT
00135     rprintfProgStrM("---------- Disk/Partition Information ----------\r\n");
00136     rprintfProgStrM("Volume/Part Size: ");  rprintfu32(FatFsInfo.devdisk.numsectors);       rprintfCRLF();
00137     rprintfProgStrM("---------- FAT Volume Information --------------\r\n");
00138     rprintfProgStrM("Reserved Sectors: ");  rprintfu16(bpb->bpbResSectors);             rprintfCRLF();
00139     rprintfProgStrM("FatSectors      : ");  rprintfu16(bpb->bpbFATsecs);                rprintfCRLF();
00140     rprintfProgStrM("BigFatSectors   : ");  rprintfu32(bpb->bpbBigFATsecs);             rprintfCRLF();
00141     rprintfProgStrM("Bytes/Sector    : ");  rprintfu16(FatFsInfo.BytesPerSector);       rprintfCRLF();
00142     rprintfProgStrM("First Fat Sector: ");  rprintfu32(FatFsInfo.FirstFATSector);       rprintfCRLF();
00143     rprintfProgStrM("Number of Fats  : ");  rprintfu08(FatFsInfo.NumberOfFats);         rprintfCRLF();
00144     rprintfProgStrM("Sectors/FAT     : ");  rprintfu32(FatFsInfo.SectorsPerFat);        rprintfCRLF();
00145     rprintfProgStrM("First Data Sect : ");  rprintfu32(FatFsInfo.FirstDataSector);      rprintfCRLF();
00146     rprintfProgStrM("Sectors/Cluster : ");  rprintfu08(FatFsInfo.SectorsPerCluster);    rprintfCRLF();
00147     rprintfProgStrM("RootDirStartClus: ");  rprintfu32(FatFsInfo.RootDirStartCluster);  rprintfCRLF();
00148 #endif
00149 
00150     return 0;   
00151 }
00152 
00153 
00154 
00155 
00156 unsigned char fatGetDirEntry(unsigned short entry)
00157 {
00158     unsigned long sector;
00159     struct direntry *de = 0;    
00160     struct winentry *we;
00161     unsigned char haveLongNameEntry;
00162     unsigned char gotEntry;
00163     unsigned short b;
00164     int i,index;
00165     char *fnbPtr;
00166     unsigned short entrycount = 0;
00167 
00168     
00169 
00170     sector = fatClusterToSector(CurrentDirStartCluster);
00171 
00172     haveLongNameEntry = 0;
00173     gotEntry = 0;
00174 
00175     index = 16; 
00176     
00177     
00178     while(1)
00179     {
00180         if(index == 16) 
00181         {
00182             FatFsInfo.devdisk.ReadSector(sector++, 1, SectorBuffer);
00183             de = (struct direntry *) SectorBuffer;
00184             index = 0;
00185         }
00186         
00187         
00188         if(de->deName[0] == 0x00)
00189         {
00190             
00191             gotEntry = 0;
00192             break;
00193         }
00194         else if(de->deName[0] == 0xE5)
00195         {
00196             
00197             
00198         }
00199         else
00200         {
00201             
00202             
00203             if(de->deAttributes == ATTR_LONG_FILENAME)
00204             {
00205                 
00206                 
00207                 we = (struct winentry *) de;
00208                 
00209                 b = WIN_ENTRY_CHARS*( (we->weCnt-1) & 0x0f);        
00210                 fnbPtr = &FileNameBuffer[b];
00211                 for (i=0;i<5;i++)   *fnbPtr++ = we->wePart1[i*2];   
00212                 for (i=0;i<6;i++)   *fnbPtr++ = we->wePart2[i*2];   
00213                 for (i=0;i<2;i++)   *fnbPtr++ = we->wePart3[i*2];   
00214                 if (we->weCnt & WIN_LAST) *fnbPtr = 0;              
00215                 if ((we->weCnt & 0x0f) == 1) haveLongNameEntry = 1; 
00216             }
00217             else
00218             {
00219                 
00220                 
00221                 
00222                 
00223                 if(haveLongNameEntry)
00224                 {
00225                     
00226                     if(entrycount == entry)     
00227                     {
00228                         
00229                         gotEntry = 1;
00230                         break;
00231                     }
00232                     
00233                     haveLongNameEntry = 0;  
00234                     entrycount++;           
00235                 }
00236                 else
00237                 {
00238                     
00239                     
00240                     fnbPtr = FileNameBuffer;
00241                     for (i=0;i<8;i++)   *fnbPtr++ = de->deName[i];      
00242                     *fnbPtr++ = '.';                                    
00243                     for (i=0;i<3;i++)   *fnbPtr++ = de->deExtension[i]; 
00244                     *fnbPtr = 0;                                        
00245 
00246                     if(entrycount == entry)     
00247                     {
00248                         
00249                         gotEntry = 1;
00250                         break;
00251                     }
00252                     
00253                     entrycount++;           
00254                 }
00255             }
00256         }
00257         
00258         de++;
00259         
00260         index++;
00261     }
00262     
00263     
00264     
00265     FileInfo.StartCluster = (unsigned long) ((unsigned long)de->deHighClust << 16) + de->deStartCluster;
00266     
00267     
00268     FileInfo.Size = de->deFileSize;
00269     
00270     FileInfo.Attr = de->deAttributes;
00271     
00272     FileInfo.CreateTime = de->deCTime[0] | de->deCTime[1]<<8;
00273     
00274     FileInfo.CreateTime = de->deCDate[0] | de->deCDate[1]<<8;
00275 
00276     return gotEntry;
00277 }
00278 
00279 int fatCreateFile(unsigned char* filename, FileInfo_t* fileInfo)
00280 {
00281     unsigned long sector;
00282     struct direntry *de = 0;    
00283     unsigned int index;
00284     unsigned char* strptr;
00285     unsigned char i;
00286     
00287     
00288     sector = fatClusterToSector(CurrentDirStartCluster);
00289 
00290     index = DIRENTRIES_PER_SECTOR;
00291 
00292     while(1)
00293     {
00294         if(index == DIRENTRIES_PER_SECTOR)  
00295         {
00296             FatFsInfo.devdisk.ReadSector(sector++, 1, SectorBuffer);
00297             de = (struct direntry *)SectorBuffer;
00298             index = 0;
00299         }
00300         
00301         
00302         if(de->deName[0] == SLOT_EMPTY)
00303         {
00304             
00305             
00306             break;
00307         }
00308         else if(de->deName[0] == SLOT_DELETED)
00309         {
00310             
00311             break;
00312         }
00313         
00314         
00315         de++;
00316         index++;
00317     }
00318 
00319     
00320     strptr = filename;
00321     
00322     for(i=0; i<8; i++)
00323     {
00324         if( (*strptr != '.') && (*strptr != 0) )
00325             de->deName[i] = *strptr++;
00326         else
00327             de->deName[i] = ' ';
00328     }
00329     
00330     
00331     if(*strptr == '.')
00332     {
00333         strptr++;
00334         de->deExtension[0] = *strptr++;
00335         de->deExtension[1] = *strptr++;
00336         de->deExtension[2] = *strptr++;
00337     }
00338     else
00339     {
00340         de->deExtension[0] = ' ';
00341         de->deExtension[1] = ' ';
00342         de->deExtension[2] = ' ';
00343     }
00344     
00345     de->deAttributes = fileInfo->Attr;
00346     
00347     de->deLowerCase = 0;
00348     
00349     de->deCHundredth = 0;
00350     de->deCTime[0] = fileInfo->CreateTime;
00351     de->deCTime[1] = fileInfo->CreateTime>>8;
00352     de->deCDate[0] = fileInfo->CreateDate;
00353     de->deCDate[1] = fileInfo->CreateDate>>8;
00354     de->deADate[0] = 0;
00355     de->deADate[1] = 0;
00356     de->deMTime[0] = 0;
00357     de->deMTime[1] = 0;
00358     de->deMDate[0] = 0;
00359     de->deMDate[1] = 0;
00360     
00361     de->deFileSize = fileInfo->Size;
00362     
00363     de->deStartCluster = fileInfo->StartCluster;
00364     de->deHighClust = fileInfo->StartCluster>>16;
00365 
00366     
00367     FatFsInfo.devdisk.WriteSector(--sector, 1, SectorBuffer);
00368 
00369     return 0;
00370 }
00371 
00372 int fatFormat(unsigned long volsize)
00373 {
00374     unsigned long i,j,fatsecs;
00375     unsigned long sector;
00376 
00377     struct bootsector710 *bs;
00378     struct bpb710* bpb;
00379 
00380     
00381     rprintfProgStrM("Calculating filesystem parameters\r\n");
00382     
00383     memset(SectorBuffer, 0, 512);
00384     
00385     bs = (struct bootsector710 *)SectorBuffer;
00386 
00387     strcpy(&bs->bsOEMName[0], "MSDOS5.0");
00388     
00389     bpb = (struct bpb710*)bs->bsBPB;
00390 
00391     
00392     bpb->bpbBytesPerSec = 0x200;    
00393     bpb->bpbSecPerClust = 8;        
00394     bpb->bpbResSectors = 4;         
00395     bpb->bpbFATs = 2;               
00396     bpb->bpbRootDirEnts = 0x200;    
00397     if(volsize < 0x10000)
00398     {
00399         
00400         bpb->bpbSectors = volsize;  
00401         bpb->bpbHugeSectors = 0;    
00402     }
00403     else
00404     {
00405         
00406         bpb->bpbSectors = 0;
00407         bpb->bpbHugeSectors = volsize;  
00408     }
00409     
00410     
00411     
00412     i = volsize - (bpb->bpbResSectors + (bpb->bpbRootDirEnts+(DIRENTRIES_PER_SECTOR-1))/DIRENTRIES_PER_SECTOR);
00413     
00414     j = ((unsigned short)bpb->bpbSecPerClust<<8) + bpb->bpbFATs;
00415     
00416     fatsecs = (i+(j-1))/j;
00417     
00418 
00419 
00420 
00421 
00422 
00423     
00424     if(fatsecs < 65525)
00425     {
00426         
00427         bpb->bpbFATsecs = fatsecs;  
00428     }
00429     else
00430     {
00431         
00432         bpb->bpbFATsecs = 0;            
00433         bpb->bpbBigFATsecs = fatsecs;   
00434     }
00435     bpb->bpbMedia = 0xF8;           
00436     bpb->bpbSecPerTrack = 63;   
00437     bpb->bpbHeads = 255;
00438     bpb->bpbHiddenSecs = 0;
00439     
00440     bpb->bpbExtFlags = 0;           
00441     bpb->bpbFSVers = FSVERS;
00442 
00443     
00444     bs->bsBootSectSig0 = 0x55;
00445     bs->bsBootSectSig1 = 0xAA;
00446 
00447     
00448     rprintfProgStrM("Writing boot sector\r\n");
00449     FatFsInfo.devdisk.WriteSector(0, 1, SectorBuffer);
00450 
00451     
00452     
00453 
00454     
00455     rprintfProgStrM("Remounting Filesystem...\r\n");
00456     fatInit(&FatFsInfo.devdisk);
00457     
00458     memset(SectorBuffer, 0, 512);
00459     
00460     rprintfProgStrM("Initializing FAT sectors...\r\n");
00461     for(i=0; i<(FatFsInfo.NumberOfFats*FatFsInfo.SectorsPerFat); i++)
00462     {
00463         rprintfProgStrM("Writing FAT sector: "); rprintfu32(FatFsInfo.FirstFATSector+i); rprintfChar('\r');
00464         FatFsInfo.devdisk.WriteSector(FatFsInfo.FirstFATSector+i, 1, SectorBuffer);
00465     }
00466     rprintfCRLF();
00467 
00468     
00469     rprintfProgStrM("Creating Root Directory...\r\n");
00470     
00471     fatWriteClusterValue(FatFsInfo.RootDirStartCluster, CLUST_EOFE);
00472     
00473     sector = fatClusterToSector(FatFsInfo.RootDirStartCluster);
00474     
00475     memset(SectorBuffer, 0, 512);
00476     
00477     for(i=0; i<FatFsInfo.SectorsPerCluster; i++)
00478     {
00479         rprintfProgStrM("Writing Root Dir sector: "); rprintfu32(sector+i); rprintfChar('\r');
00480         FatFsInfo.devdisk.WriteSector(sector+i, 1, SectorBuffer);
00481     }
00482     rprintfCRLF();
00483 
00484     
00485     rprintfProgStrM("Creating Volume Label...\r\n");
00486     
00487     FileInfo.Attr = ATTR_VOLUME;
00488     FileInfo.Size = 0;
00489     FileInfo.StartCluster = 0;
00490     FileInfo.CreateDate = 0;
00491     FileInfo.CreateTime = 0;
00492 
00493     fatCreateFile("MYDISK", &FileInfo);
00494 
00495     return 0;
00496 }
00497 
00498 
00499 unsigned char fatChangeDirectory(unsigned short entry)
00500 {
00501     
00502     if( fatGetDirEntry(entry) )
00503     {
00504         
00505         if(FileInfo.Attr & ATTR_DIRECTORY)
00506         {
00507             
00508             
00509             if(FileInfo.StartCluster)
00510             {
00511                 
00512                 CurrentDirStartCluster = FileInfo.StartCluster;
00513             }
00514             else
00515             {
00516                 
00517                 
00518                 
00519                 CurrentDirStartCluster = FatFsInfo.RootDirStartCluster;
00520             }
00521             
00522             
00523             strcat(PathNameBuffer, FileNameBuffer);
00524             strcat(PathNameBuffer, "\\");
00525             
00526             return TRUE;
00527         }
00528         else
00529         {
00530             
00531             return FALSE;
00532         }
00533     }
00534     else
00535     {
00536         
00537         return FALSE;
00538     }
00539 }
00540 
00541 void fatPrintDirEntry(void)
00542 {
00543     
00544     
00545     rprintfNum(10, 2, FALSE, '0', (FileInfo.CreateDate&DD_MONTH_MASK)>>DD_MONTH_SHIFT );    
00546     rprintfChar('/');
00547     rprintfNum(10, 2, FALSE, '0', (FileInfo.CreateDate&DD_DAY_MASK)>>DD_DAY_SHIFT );        
00548     rprintfChar('/');
00549     rprintfNum(10, 4, FALSE, '0', (FileInfo.CreateDate&DD_YEAR_MASK)>>DD_YEAR_SHIFT );  
00550     rprintfChar(' ');
00551 
00552     
00553     rprintfNum(10, 2, FALSE, '0', (FileInfo.CreateTime&DT_HOURS_MASK)>>DT_HOURS_SHIFT );    
00554     rprintfChar(':');
00555     rprintfNum(10, 2, FALSE, '0', (FileInfo.CreateTime&DT_MINUTES_MASK)>>DT_MINUTES_SHIFT );        
00556     rprintfChar(':');
00557     rprintfNum(10, 2, FALSE, '0', 2*(FileInfo.CreateTime&DT_2SECONDS_MASK)>>DT_2SECONDS_SHIFT );    
00558     rprintfChar(' ');
00559 
00560     
00561     if(FileInfo.Attr & ATTR_VOLUME)     rprintfChar('V'); else rprintfChar('-');
00562     if(FileInfo.Attr & ATTR_DIRECTORY)  rprintfChar('D'); else rprintfChar('-');
00563     if(FileInfo.Attr & ATTR_READONLY)   rprintfChar('R'); else rprintfChar('-');
00564     if(FileInfo.Attr & ATTR_HIDDEN)     rprintfChar('H'); else rprintfChar('-');
00565     if(FileInfo.Attr & ATTR_SYSTEM)     rprintfChar('S'); else rprintfChar('-');
00566     if(FileInfo.Attr & ATTR_ARCHIVE)    rprintfChar('A'); else rprintfChar('-');
00567     rprintfChar(' ');
00568 
00569     
00570     rprintfNum(10, 8, FALSE, ' ', FileInfo.Size);   
00571     rprintfChar(' ');
00572 
00573     
00574     rprintfStr(FileNameBuffer);
00575 }
00576 
00577 void fatDumpDirSlot(unsigned short slot)
00578 {
00579     unsigned long sector;
00580     
00581     
00582     sector = fatClusterToSector(CurrentDirStartCluster);
00583     sector += slot/DIRENTRIES_PER_SECTOR;
00584 
00585     rprintf("CurrentDirStartCluster:");
00586     rprintfu32(CurrentDirStartCluster);
00587     rprintfCRLF();
00588     rprintf("Sector access         :");
00589     rprintfu32(sector);
00590     rprintfCRLF();
00591         
00592     
00593     debugPrintHexTable(32, SectorBuffer+(slot<<5) );
00594 }
00595 
00596 FileInfo_t* fatGetFileInfo(void)
00597 {
00598     return &FileInfo;
00599 }
00600 
00601 
00602 unsigned long fatGetFilesize(void)
00603 {
00604     return FileInfo.Size;
00605 }
00606 
00607 
00608 char* fatGetFilename(void)
00609 {   
00610     return FileNameBuffer;
00611 }
00612 
00613 
00614 char* fatGetDirname(void)
00615 {   
00616     return PathNameBuffer;
00617 }
00618 
00619 
00620 void fatLoadCluster(unsigned long cluster, unsigned char *buffer)
00621 {
00622     register unsigned char i;
00623     
00624     
00625     for(i=0; i<FatFsInfo.SectorsPerCluster; i++)
00626     {
00627         FatFsInfo.devdisk.ReadSector(fatClusterToSector(cluster)+i, 1, buffer+(i<<9) );
00628         
00629         
00630 
00631     }
00632 }
00633 
00634 
00635 
00636 unsigned long fatNextCluster(unsigned long cluster)
00637 {
00638     unsigned long nextCluster;
00639 
00640     
00641     nextCluster = fatClusterValue(cluster);
00642 
00643     
00644     if (nextCluster == (CLUST_EOFE & FatFsInfo.FatMask))
00645         nextCluster = 0;
00646 
00647 #ifdef DEBUG_FAT
00648     rprintfProgStrM(">");
00649     rprintfu32(nextCluster);
00650     rprintfCRLF();
00651 #endif
00652     
00653     return nextCluster;
00654 }
00655 
00656 unsigned long fatNextFreeCluster(void)
00657 {
00658     unsigned long cluster;
00659 
00660     
00661     cluster = FatFsInfo.RootDirStartCluster;
00662 
00663     while( fatClusterValue(cluster) != CLUST_FREE)
00664     {
00665         
00666         cluster++;
00667     }
00668     return cluster;
00669 }
00670 
00671 unsigned long fatClusterValue(unsigned long cluster)
00672 {
00673     
00674     unsigned char* buffer;
00675     unsigned long fatOffset;
00676     unsigned long sector;
00677     unsigned int offset;
00678     
00679     
00680     if(FatFsInfo.Fat32Enabled)
00681     {
00682         
00683         fatOffset = cluster << 2;
00684     }
00685     else
00686     {
00687         
00688         fatOffset = cluster << 1;
00689     }
00690     
00691     
00692     sector = (fatOffset / FatFsInfo.BytesPerSector);
00693     
00694     offset = fatOffset % FatFsInfo.BytesPerSector;
00695     
00696     buffer = fatGetFatSector( sector );
00697     
00698     
00699     
00700     
00701     
00702     return (*((unsigned long*) &buffer[offset])) & FatFsInfo.FatMask;
00703 }
00704 
00705 int fatWriteClusterValue(unsigned long cluster, unsigned value)
00706 {
00707     
00708     unsigned char* buffer;
00709     unsigned long fatOffset;
00710     unsigned long fatSector;
00711     unsigned int offset;
00712     
00713     
00714     if(FatFsInfo.Fat32Enabled)
00715     {
00716         
00717         fatOffset = cluster << 2;
00718     }
00719     else
00720     {
00721         
00722         fatOffset = cluster << 1;
00723     }
00724     
00725     
00726     fatSector = (fatOffset / FatFsInfo.BytesPerSector);
00727     
00728     offset = fatOffset % FatFsInfo.BytesPerSector;
00729     
00730     buffer = fatGetFatSector( fatSector );
00731     
00732     
00733     
00734     
00735     
00736     *((unsigned long*) &buffer[offset]) = (value & FatFsInfo.FatMask);
00737 
00738     
00739     FatFsInfo.devdisk.WriteSector(FatFsInfo.FirstFATSector+fatSector, 1, buffer);
00740 
00741     return 0;
00742 }
00743 
00744 unsigned char* fatGetFatSector(unsigned long fatsector)
00745 {
00746     
00747     
00748 
00749     
00750     
00751     
00752 
00753     
00754     if(fatsector != FatFsInfo.FatInCache)
00755     {
00756         
00757         while (FatFsInfo.devdisk.ReadSector(FatFsInfo.FirstFATSector+fatsector, 1, FatCacheBuffer) != 0);
00758         FatFsInfo.FatInCache = fatsector;
00759     }
00760     return FatCacheBuffer;
00761 }
00762 
00763 unsigned long fatClusterToSector(unsigned long cluster)
00764 {
00765     return ((cluster-2) * FatFsInfo.SectorsPerCluster) + FatFsInfo.FirstDataSector;
00766 }
00767 
00768 unsigned int fatClusterSize(void)
00769 {
00770     
00771     return FatFsInfo.SectorsPerCluster;
00772 }