Main Page   Data Structures   File List   Data Fields   Globals  

fat.c

Go to the documentation of this file.
00001 /*! \file fat.c \brief FAT16/32 file system driver. */
00002 //*****************************************************************************
00003 //
00004 // File Name    : 'fat.c'
00005 // Title        : FAT16/32 file system driver
00006 // Author       : Pascal Stang
00007 // Date         : 11/07/2000
00008 // Revised      : 12/12/2000
00009 // Version      : 0.3
00010 // Target MCU   : ATmega103 (should work for Atmel AVR Series)
00011 // Editor Tabs  : 4
00012 //
00013 // NOTE: This code is currently below version 1.0, and therefore is considered
00014 // to be lacking in some functionality or documentation, or may not be fully
00015 // tested.  Nonetheless, you can expect most functions to work.
00016 //
00017 // This code is distributed under the GNU Public License
00018 //      which can be found at http://www.gnu.org/licenses/gpl.txt
00019 //
00020 //*****************************************************************************
00021 
00022 
00023 #include <avr/io.h>
00024 #include <avr/string.h>
00025 #include <avr/progmem.h>
00026 
00027 #include "ata_if.h"
00028 #include "uart.h"
00029 
00030 #include "fat.h"
00031 
00032 // debug on/off
00033 //#define DEBUG_FAT
00034 
00035 // globals
00036 unsigned char *SectorBuffer  =      (unsigned char *) SECTOR_BUFFER1_ADDR;
00037 unsigned char *long_name_buffer =   (unsigned char *) LONGNAME_BUFFER_ADDR;
00038 unsigned char *dir_name_buffer =    (unsigned char *) DIRNAME_BUFFER_ADDR;
00039 
00040 struct partrecord PartInfo;
00041 unsigned char Fat32Enabled;
00042 unsigned long FirstDataSector;
00043 unsigned int  BytesPerSector;
00044 unsigned int  SectorsPerCluster;
00045 unsigned long FirstFATSector;
00046 unsigned long FirstDirSector;
00047 unsigned long FileSize;
00048 unsigned long FatInCache = 0;
00049 
00050 /*************************************************************************/
00051 /*************************************************************************/
00052 
00053 
00054 unsigned long clust2sect(unsigned long clust)
00055 {
00056     return ((clust-2) * SectorsPerCluster) + FirstDataSector;
00057 }
00058 
00059 unsigned int fatClusterSize(void)
00060 {
00061     // return the number of sectors in a disk cluster
00062     return SectorsPerCluster;
00063 }
00064 
00065 unsigned char fatInit( unsigned char device)
00066 {
00067     //struct partrecord *pr;
00068     struct bpb710 *bpb;
00069 
00070     // read partition table
00071     // TODO.... error checking
00072     ataReadSectors(DRIVE0, 0, 1, SectorBuffer);
00073     // map first partition record   
00074     // save partition information to global PartInfo
00075     PartInfo = *((struct partrecord *) ((struct partsector *) SectorBuffer)->psPart);
00076 //  PartInfo = *pr;
00077     
00078     // Read the Partition BootSector
00079     // **first sector of partition in PartInfo.prStartLBA
00080     ataReadSectors( DRIVE0, PartInfo.prStartLBA, 1, SectorBuffer );
00081     bpb = (struct bpb710 *) ((struct bootsector710 *) SectorBuffer)->bsBPB;
00082 
00083     // setup global disk constants
00084     FirstDataSector = PartInfo.prStartLBA;
00085     if(bpb->bpbFATsecs)
00086     {
00087         // bpbFATsecs is non-zero and is therefore valid
00088         FirstDataSector += bpb->bpbResSectors + bpb->bpbFATs * bpb->bpbFATsecs;
00089     }
00090     else
00091     {
00092         // bpbFATsecs is zero, real value is in bpbBigFATsecs
00093         FirstDataSector += bpb->bpbResSectors + bpb->bpbFATs * bpb->bpbBigFATsecs;
00094     }
00095     SectorsPerCluster   = bpb->bpbSecPerClust;
00096     BytesPerSector      = bpb->bpbBytesPerSec;
00097     FirstFATSector      = bpb->bpbResSectors + PartInfo.prStartLBA;
00098 
00099     switch (PartInfo.prPartType)
00100     {
00101         case PART_TYPE_DOSFAT16:
00102         case PART_TYPE_FAT16:
00103         case PART_TYPE_FAT16LBA:
00104             // first directory cluster is 2 by default (clusters range 2->big)
00105             FirstDirSector  = CLUST_FIRST;
00106             // push data sector pointer to end of root directory area
00107             //FirstDataSector += (bpb->bpbRootDirEnts)/DIRENTRIES_PER_SECTOR;
00108             Fat32Enabled = FALSE;
00109             break;
00110         case PART_TYPE_FAT32LBA:
00111         case PART_TYPE_FAT32:
00112             // bpbRootClust field exists in FAT32 bpb710, but not in lesser bpb's
00113             FirstDirSector = bpb->bpbRootClust;
00114             // push data sector pointer to end of root directory area
00115             // need this? FirstDataSector += (bpb->bpbRootDirEnts)/DIRENTRIES_PER_SECTOR;
00116             Fat32Enabled = TRUE;
00117             break;
00118         default:
00119             uartPrintfProgStrM("Found: No Partition!\r\n");
00120             //return 1;
00121             break;
00122     }
00123 
00124 
00125 #ifdef DEBUG_FAT
00126     switch (PartInfo.prPartType)
00127     {
00128         case PART_TYPE_DOSFAT16:
00129                 uartPrintfProgStrM("Found: DOSFAT 16\r\n");
00130                 break;
00131         case PART_TYPE_FAT16:
00132                 uartPrintfProgStrM("Found: FAT16\r\n");
00133                 break;
00134         case PART_TYPE_FAT16LBA:
00135                 uartPrintfProgStrM("Found: FAT16 LBA\r\n");
00136                 break;
00137         case PART_TYPE_FAT32LBA:
00138                 uartPrintfProgStrM("Found: FAT32 LBA\r\n");
00139                 break;
00140         case PART_TYPE_FAT32:
00141                 uartPrintfProgStrM("Found: FAT32\r\n");
00142                 //return 1; 
00143                 break;
00144         default:
00145                 uartPrintfProgStrM("Found: No Partition!\r\n");
00146                 //return 1;
00147                 break;
00148     }
00149 
00150     uartPrintfProgStrM("First sector    : ");
00151     uartPrintfu32(PartInfo.prStartLBA);
00152     uartPrintfCRLF();
00153     uartPrintfProgStrM("Size            : ");
00154     uartPrintfu32(PartInfo.prSize);
00155     uartPrintfCRLF();
00156 
00157     uartPrintfProgStrM("bytes/sector    : ");
00158     uartPrintfu16(bpb->bpbBytesPerSec);
00159     uartPrintfCRLF();
00160 
00161     uartPrintfProgStrM("sectors/cluster : ");
00162     uartPrintfu08(bpb->bpbSecPerClust);
00163     uartPrintfCRLF();
00164 
00165     uartPrintfProgStrM("reserved sectors: ");
00166     uartPrintfu16(bpb->bpbResSectors);
00167     uartPrintfCRLF();
00168 
00169     uartPrintfProgStrM("FatSectors      : ");
00170     uartPrintfu16(bpb->bpbFATsecs);
00171     uartPrintfCRLF();
00172 
00173     uartPrintfProgStrM("BigFatSectors   : ");
00174     uartPrintfu32(bpb->bpbBigFATsecs);
00175     uartPrintfCRLF();
00176 
00177     uartPrintfProgStrM("Number of Fats  : ");
00178     uartPrintfu08(bpb->bpbFATs);
00179     uartPrintfCRLF();
00180 
00181     uartPrintfProgStrM("First Fat Sector: ");
00182     uartPrintfu32(FirstFATSector);
00183     uartPrintfCRLF();
00184 
00185     uartPrintfProgStrM("First Data Sect : ");
00186     uartPrintfu32(FirstDataSector);
00187     uartPrintfCRLF();
00188 
00189     uartPrintfProgStrM("First Dir Clust : ");
00190     uartPrintfu32(FirstDirSector);
00191     uartPrintfCRLF();
00192 #endif
00193 
00194     return 0;   
00195 }
00196 
00197 //////////////////////////////////////////////////////////////
00198 
00199 
00200 unsigned int baseentry = 0;
00201 unsigned int entrycount = 0;
00202 
00203 
00204 unsigned long fatGetDirEntry(unsigned int entry, unsigned int count)
00205 {
00206     unsigned long sector;
00207     struct direntry *de = 0;    // avoid compiler warning by initializing
00208     struct winentry *we;
00209     unsigned int hasBuffer;
00210     unsigned int b;
00211     int i,index;
00212     char *p;
00213     
00214     if (count == 0)
00215     {
00216         entrycount = 0;
00217         *dir_name_buffer = 0;
00218     }
00219     
00220     // read dir data
00221     sector = clust2sect(FirstDirSector);
00222 
00223     hasBuffer = 0;
00224 
00225     index = 16; // crank it up
00226     do 
00227     {
00228         if (index == 16)    // time for next sector ?
00229         {
00230             ataReadSectors( DRIVE0, sector++, 1, SectorBuffer);
00231             de = (struct direntry *) SectorBuffer;
00232             index = 0;
00233         }   
00234     
00235         if (*de->deName != 0xE5)    // if not a deleted entry
00236         {
00237             // long name entry
00238             if (de->deAttributes == ATTR_LONG_FILENAME)
00239             {
00240                 we = (struct winentry *) de;
00241                 b = 13 *( (we->weCnt-1) & 0x0f);                // index into string
00242                 p = &long_name_buffer[b];
00243                 for (i=0;i<5;i++)   *p++ = we->wePart1[i*2];    // copy first part          
00244                 for (i=0;i<6;i++)   *p++ = we->wePart2[i*2];    // second part
00245                 for (i=0;i<2;i++)   *p++ = we->wePart3[i*2];    // and third part
00246                 if (we->weCnt & 0x40) *p = 0;                   // in case dirnamelength is multiple of 13
00247                 if ((we->weCnt & 0x0f) == 1) hasBuffer = 1;     // mark that we have a long entry
00248             }
00249             else // short name entry
00250             {
00251                 if (hasBuffer)      // a long entry name has been collected
00252                 {
00253                     if (de->deAttributes == ATTR_DIRECTORY) // is it a directory ?
00254                     {
00255                         unsigned long save = FirstDirSector;
00256                         unsigned int save2 = baseentry;
00257                         unsigned long rval;
00258                         
00259                         strcpy(dir_name_buffer,long_name_buffer);
00260                         strcat(dir_name_buffer,"/");
00261 //                      
00262 //                      uartPrintfStr(long_name_buffer); uartPrintfProgStrM("/"); //EOL();
00263 //
00264                         // call recursively
00265                         FirstDirSector = ((unsigned long)de->deHighClust << 16) + de->deStartCluster;
00266                         rval = fatGetDirEntry(entry,1);
00267                         FirstDirSector = save;
00268                         baseentry = save2;
00269                         if (rval)
00270                             return rval;
00271                         else    
00272                         {
00273                             // reload original sector
00274                             ataReadSectors( DRIVE0, sector-1, 1, SectorBuffer);
00275                             entrycount--;           // decrement entry counter      
00276                             *dir_name_buffer = 0;
00277                     }
00278                     }
00279                     else // normal file entry
00280                         if (entrycount == entry)        
00281                             break;
00282                     hasBuffer = 0;  // clear buffer 
00283                     entrycount++;           // increment entry counter      
00284                 }
00285                 // else ignore short_name_only entries
00286             }
00287         }
00288         de++;
00289         index++;
00290     }   while (*de->deName || index == 16); // 0 in de->deName[0] if no more entries
00291 
00292     if (hasBuffer == 0)     // end of entries
00293         return 0;
00294     
00295     FileSize = de->deFileSize;
00296     return (unsigned long) ((unsigned long)de->deHighClust << 16) + de->deStartCluster;
00297 }
00298 
00299 
00300 // return the size of the last directory entry
00301 unsigned long fatGetFilesize(void)
00302 {
00303     return FileSize;
00304 }
00305 
00306 
00307 // return the long name of the last directory entry
00308 char* fatGetFilename(void)
00309 {   
00310     return long_name_buffer;
00311 }
00312 
00313 
00314 // return the directory of the last directory entry
00315 char* fatGetDirname(void)
00316 {   
00317     return dir_name_buffer;
00318 }
00319 
00320 
00321 // load a clusterfull of data
00322 void fatLoadCluster(unsigned long cluster, unsigned char *buffer)
00323 {
00324     register unsigned char i;
00325     // read cluster
00326     //while ( ataReadSectors( DRIVE0, clust2sect(cluster), SectorsPerCluster, buffer) != 0);
00327     for(i=0; i<SectorsPerCluster; i++)
00328     {
00329 //      ataReadSectors( DRIVE0, clust2sect(cluster)+i, 1, buffer+(i<<9) );
00330         // temporary fix for wierd misaligned cluster problem
00331         // (only when using FAT16?)
00332         ataReadSectors( DRIVE0, clust2sect(cluster+8)+i, 1, buffer+(i<<9) );
00333     }
00334 }
00335 
00336 
00337 // find next cluster in the FAT chain
00338 unsigned long fatNextCluster(unsigned long cluster)
00339 {
00340     unsigned long nextCluster;
00341     unsigned long fatMask;
00342     unsigned long fatOffset;
00343     unsigned long sector;
00344     unsigned int offset;
00345     
00346     // get fat offset in bytes
00347     if(Fat32Enabled)
00348     {
00349         // four FAT bytes (32 bits) for every cluster
00350         fatOffset = cluster << 2;
00351         // set the FAT bit mask
00352         fatMask = FAT32_MASK;
00353     }
00354     else
00355     {
00356         // two FAT bytes (16 bits) for every cluster
00357         fatOffset = cluster << 1;
00358         // set the FAT bit mask
00359         fatMask = FAT16_MASK;
00360     }
00361     
00362     // calculate the FAT sector that we're interested in
00363     sector = FirstFATSector + (fatOffset / BytesPerSector);
00364     // calculate offset of the our entry within that FAT sector
00365     offset = fatOffset % BytesPerSector;
00366 
00367     // if we don't already have this FAT chunk loaded, go get it
00368     if (sector != FatInCache)
00369     {
00370         // read sector of FAT table
00371         while (ataReadSectors( DRIVE0, sector, 1, (unsigned char*)FAT_CACHE_ADDR) != 0);
00372         FatInCache = sector;
00373     }
00374 
00375     // read the nextCluster value
00376     nextCluster = (*((unsigned long*) &((char*)FAT_CACHE_ADDR)[offset])) & fatMask;
00377 
00378     // check to see if we're at the end of the chain
00379     if (nextCluster == (CLUST_EOFE & fatMask))
00380         nextCluster = 0;
00381 
00382 #ifdef DEBUG_FAT
00383     uartPrintfProgStrM(">");
00384     uartPrintfu32(nextCluster);
00385     uartPrintfCRLF();
00386 #endif
00387     
00388     return nextCluster;
00389 }

Generated on Tue Feb 4 20:18:36 2003 for Procyon AVRlib by doxygen1.3-rc2