VLSI Solution Oy VS1103 VLSI Solution Karaoke, MIDI and ADPCM Player Source Code Documentation

Main Page | Class List | File List | Class Members | File Members | Related Pages

filesys.c File Reference

File system functions, Implemented: FAT16, FAT32. More...

#include "board.h"
#include "filesys.h"
#include "storage.h"
#include "noconsole.h"
#include "mmc.h"
#include "lcd.h"
#include "display.h"

Include dependency graph for filesys.c:

Include dependency graph

Go to the source code of this file.

Classes

struct  diskInfoStruct
 Collection of disk globals. More...
struct  fragmentEntry
 Fragment Table. More...
struct  directoryStack
 Directory traversing structure. More...

Defines

#define MAX_NUMBER_SUBDIRECTORIES   5
 Maximum number of nested subdirectories.
#define NEEDEDSIZE   60000

Typedefs

typedef diskInfoStruct diskInfo
 Collection of disk globals.

Functions

void PConvertSectorToCluster (unsigned long *sector)
 Convert sector number to cluster number.
void PConvertClusterToSector (unsigned long *cluster)
 Convert cluster number to sector number.
unsigned long GetFatEntry (unsigned long clusterNumber)
 Return the FAT entry for cluster clusterNumber.
unsigned char ScanForFreeSector ()
 Search for next free sector.
void LocateFreeBlock ()
unsigned long GetNextSector (unsigned long currentSector)
 Calculate next sector from currentSector.
Public unsigned char BuildFragmentTable ()
 Build a fragment table starting from current sector.
unsigned char LoadNextSector ()
 Traverse to next sector in file or directory.
Public unsigned char FGetChar ()
 Read a character from current file.
unsigned char OpenFile (unsigned int fileNumber, unsigned char ext1, unsigned char ext2, unsigned char ext3)
 Open a file for reading.
unsigned char FatInitGlobals ()
 Decipher structure of FAT volume and set globals accordingly.
unsigned char SelectDisk (unsigned char n)
 Start the filing system and initialize all necessary subsystems.
unsigned char RealInitFileSystem ()
unsigned char InitFileSystem ()
 Start the filing system and initialize all necessary subsystems.

Variables

data unsigned long fatStart
 Starting sector of FAT table.
data unsigned long rootStart
 Starting sector of root directory.
data unsigned long dataStart
 (In FAT the start is cluster 2, so dataStart actually points to 2 clusters before the start of data area)
data unsigned char fatSectorsPerCluster
 FAT Global sectors per cluster.
xdata diskInfo disk [2]
bit currentDisk = 0
xdata struct fragmentEntry fragment [MAX_NUMBER_FRAGMENTS]
 Fragment Table.
xdata struct fragmentEntry midiFragment [MAX_NUMBER_FRAGMENTS]
xdata struct fragmentEntry waveFragment [MAX_NUMBER_FRAGMENTS]
xdata unsigned long fileSize
 Size of current file to play.
xdata struct directoryStack dirStack [MAX_NUMBER_SUBDIRECTORIES]
 Directory traversing structure.
xdata unsigned char dirLevel = 0
 Current directory level, 0=Root directory.
xdata unsigned long freeSector = 0
 Next free cluster number.
xdata char currentFileName [12]
 8 first characters of current file name
bit IS_FAT_12 = 0
 Set if this is a FAT12 filesystem.
xdata unsigned long freeStart
xdata unsigned long freeEnd


Detailed Description

File system functions, Implemented: FAT16, FAT32.

Definition in file filesys.c.


Define Documentation

#define MAX_NUMBER_SUBDIRECTORIES   5
 

Maximum number of nested subdirectories.

Definition at line 59 of file filesys.c.

Referenced by OpenFile().

#define NEEDEDSIZE   60000
 

Definition at line 162 of file filesys.c.


Typedef Documentation

typedef struct diskInfoStruct diskInfo
 

Collection of disk globals.


Function Documentation

Public unsigned char BuildFragmentTable void   ) 
 

Build a fragment table starting from current sector.

Returns number of fragments in song. This function is used to get fast access to the filesystem when playing so cluster chain needs not be followed when the song is playing, that would be too slow with MMC cards without extra buffer memory for the file allocation tables.

Note: filesys.c module does not use the fragment table internally. it is written to be a service to the player routine, which uses storage.c module directly for disk access after using the filesys.c module for finding a file to play. I am listening to Darude's Sandstorm while coding this.

In terms of memory allocation, this function is devilish. At one stage temp.l is used just to make compiler use memory at temp.l instead of spilling to another unnecessary temp variable...

Definition at line 303 of file filesys.c.

References addressType, Address::b, Address::B::b0, Address::B::b1, Address::B::b3, ConsolePutChar, ConsolePutUInt, ConsoleWrite, diskSect, DiskBlock::Fat16Table, DiskBlock::Fat32Table, fileSize, fragment, IS_FAT_32, Address::l, Temp::l, fragmentEntry::length, MAX_NUMBER_FRAGMENTS, Public, ReadDiskSector(), sectorAddress, fragmentEntry::start, and temp.

Referenced by SelectMidiFile(), SelectRecordFile(), and SelectWaveFile().

00303                                          {
00304 
00305   unsigned char c=0;
00306   addressType this,next;
00307   addressType fatSector;
00308   unsigned char entryNumber;
00309 
00310   // First clear fragment table
00311   for (c=0; c<MAX_NUMBER_FRAGMENTS; c++){
00312     fragment[c].start = 0;
00313     fragment[c].length = 0;
00314   }
00315   c=0;
00316 
00317 
00318   if (IS_FAT_12){
00319     ConsoleWrite("Single fragment support for FAT12");
00320     fragment[0].start = sectorAddress.l;
00321     fragment[0].length = fileSize/512;
00322     return(1); //Return 1 fragment
00323   }
00324 
00325 
00326   //as long as the sectorAddress is "sane"...
00327   while (!(sectorAddress.b.b3 & 0x80)){
00328         
00329     fragment[c].start = sectorAddress.l;
00330     fragment[c].length = fatSectorsPerCluster;
00331     
00332     /* Find cluster entry for the current sector */
00333     
00334     /* in how manyth sector from start of data area are we? ->this */
00335     this.l = sectorAddress.l - dataStart;
00336     /* convert from CurrentSectorN to currentClusterN */
00337     this.l /= fatSectorsPerCluster;
00338     /* this.l is now the current cluster number */
00339     
00340     
00341     /* now let's find the FAT entry for this.l cluster */
00342     if (!IS_FAT_32){ //FAT16
00343       entryNumber = this.b.b0; /* 256 entries / page in FAT16 table */
00344       fatSector.l = this.l >> 8; /* Div by n of entries/page in FAT16 tbl*/
00345     }else{ //FAT32
00346       entryNumber = (this.b.b0 & 0x7f); /* 128 entries/page in FAT32 table */
00347       fatSector.l = this.l >> 7; /* Div by n of entries/page in FAT32 tbl*/
00348     }
00349     fatSector.l += fatStart;
00350     /* fatSector.l is now the DISK SECTOR NUMBER CONTAINING THE FAT table */
00351     /* read this page into memory */
00352     ReadDiskSector(fatSector.l);    
00353     
00354     if (!IS_FAT_32){ //FAT16
00355       next.l = diskSect.Fat16Table[entryNumber]; /* get next cluster n */
00356       /* Check for FAT16 end-of-file condition */
00357       if ((next.b.b1 == 0xff) && (next.b.b0 == 0xff)){
00358         /* FAT16 End of file */
00359         next.b.b3 = 0xff; /* return a large value (fat32 compatible) */
00360       }
00361     }else{ //FAT32
00362       next.l = diskSect.Fat32Table[entryNumber]&0x0fffffff;
00363     }
00364     /* next.l is the FAT entry (next cluster number) */
00365     
00366     
00367     ConsoleWrite("\rFragment start: cluster ");
00368     ConsolePutUInt(this.l);
00369     ConsoleWrite("sector ");
00370     ConsolePutUInt(fragment[c].start);
00371 
00372     while (next.l==(this.l+1)){
00373       //Not a fragment break -- continue to next entry 
00374 
00375       //in this temp.l is used only to allow compiler memory spilling to temp
00376       temp.l = fragment[c].length;
00377       temp.l += fatSectorsPerCluster;
00378       fragment[c].length = temp.l;
00379 
00380       entryNumber++;
00381 
00382       // --- Check for a page break
00383       if (entryNumber==0){ //entryNumber has rolled over!!!! (8bit char)
00384         //FAT16 table page border is reached
00385         fatSector.l++; //Advance to next page;
00386         entryNumber=0;
00387         ReadDiskSector(fatSector.l);
00388       }
00389       if (IS_FAT_32 && (entryNumber==128)){
00390         //FAT32 table page border is reached
00391         fatSector.l++;
00392         entryNumber=0;
00393         ReadDiskSector(fatSector.l);
00394       }
00395       
00396       // --- Advance to next cluster
00397       this.l = next.l;
00398       
00399       if (!IS_FAT_32){
00400         //FAT16 get next cluster n
00401         next.l = diskSect.Fat16Table[entryNumber];       
00402         if ((next.b.b1==0xff)&&(next.b.b0==0xff)){
00403           //FAT16 end-of-file
00404           next.b.b3 = 0xff; //mark end-of-file (FAT32 compatible)
00405         }
00406       }else{
00407         //FAT32 get next cluster n
00408         next.l = diskSect.Fat32Table[entryNumber];
00409       }
00410     }//This repeats until there is a discontinuity
00411     
00412     /* next.l now has the cluster entry for last cluster in fragment
00413        it has a high value if eof (see FAT spec) */
00414 
00415     
00416     ConsoleWrite("Size: ");
00417     ConsolePutUInt(fragment[c].length);
00418     ConsoleWrite("sectors.");
00419 
00420     //EOF test
00421     if ((next.b.b3&0x08) //Quick test
00422         && ((next.l>0x0ffffff0) | !IS_FAT_32)){ //Complete test
00423       //EOF
00424       ConsoleWrite(" <EOF>\r");
00425       sectorAddress.b.b3 = 0xff;
00426     }else{
00427       
00428       //Determine next physical sector for next fragment
00429       sectorAddress.l = next.l;
00430       sectorAddress.l *= fatSectorsPerCluster;
00431       sectorAddress.l += dataStart;
00432     }
00433     
00434     c++; //Advance to next fragment number
00435     
00436     if (c==MAX_NUMBER_FRAGMENTS-1){
00437       //End of RAM space allocated for fragment table
00438       //Force end-of-file
00439       sectorAddress.b.b3=0xff;
00440     }
00441     
00442   }//break or continue to next cluster
00443   
00444 
00445   ConsolePutChar(13);
00446   for (c=0; c<MAX_NUMBER_FRAGMENTS; c++){
00447     ConsolePutUInt(fragment[c].start);
00448     ConsolePutUInt(fragment[c].length);
00449   }
00450   ConsolePutChar(13);
00451 
00452 
00453 
00454 
00455   return c; //Return number of fragments;
00456 }

Here is the call graph for this function:

unsigned char FatInitGlobals  ) 
 

Decipher structure of FAT volume and set globals accordingly.

Definition at line 700 of file filesys.c.

References DiskBlock::Fat::Extensions::_16, DiskBlock::Fat::Extensions::_32, DiskBlock::Fat::BPB_BytsPerSec, DiskBlock::Fat::BPB_FATSz16, DiskBlock::Fat::Extensions::Fat32Specific::BPB_FATSz32, DiskBlock::Fat::BPB_HiddSec, DiskBlock::Fat::BPB_NumFATs, DiskBlock::Fat::BPB_RootEntCnt, DiskBlock::Fat::BPB_RsvdSecCnt, DiskBlock::Fat::BPB_SecPerClus, DiskBlock::Fat::BPB_TotSec16, DiskBlock::Fat::BPB_TotSec32, DiskBlock::Fat::Extensions::Fat16Specific::BS_FilSysType, DiskBlock::Fat::Extensions::Fat32Specific::BS_FilSysType, DiskBlock::Fat::BS_OEMName, DiskBlock::Fat::Extensions::Fat16Specific::BS_VolLab, DiskBlock::Fat::Extensions::Fat32Specific::BS_VolLab, Temp::c, ConsolePutChar, ConsolePutUInt, ConsoleWrite, dataStart, diskSect, DiskBlock::Fat::ext, DiskBlock::fat, fatSectorsPerCluster, fatStart, IS_FAT_12, IS_FAT_32, Address::l, rootStart, sectorAddress, and temp.

Referenced by RealInitFileSystem().

00700                               {
00701 
00702   ConsoleWrite("Formatter signature:");
00703   for (temp.c=0; temp.c<8; temp.c++){
00704     ConsolePutChar(diskSect.fat.BS_OEMName[temp.c]);
00705   }
00706   ConsoleWrite("\rBytes per sector: ");
00707   ConsolePutUInt(diskSect.fat.BPB_BytsPerSec);
00708   ConsoleWrite("\rSectors per Cluster: ");
00709   ConsolePutUInt(diskSect.fat.BPB_SecPerClus);
00710   ConsoleWrite("\rReserved sectors: ");
00711   ConsolePutUInt(diskSect.fat.BPB_RsvdSecCnt);
00712   ConsoleWrite("\rNumber of FATs: ");
00713   ConsolePutUInt(diskSect.fat.BPB_NumFATs);
00714   ConsoleWrite("\rRoot entries: ");
00715   ConsolePutUInt(diskSect.fat.BPB_RootEntCnt);
00716   ConsoleWrite("\rTotal Sectors 16: ");
00717   ConsolePutUInt(diskSect.fat.BPB_TotSec16);
00718   ConsoleWrite("\rFat Size 16: ");
00719   ConsolePutUInt(diskSect.fat.BPB_FATSz16);
00720   ConsoleWrite("\rHidden Sectors: ");
00721   ConsolePutUInt(diskSect.fat.BPB_HiddSec);
00722   ConsoleWrite("\rTotal Sectors 32: ");
00723   ConsolePutUInt(diskSect.fat.BPB_TotSec32);
00724   
00725 
00726 
00727   /* Determine FAT Type (16/32) */
00728   /* This should be done better, but it'll do for now. */
00729   IS_FAT_32 = 1;
00730   if (diskSect.fat.BPB_RootEntCnt) 
00731     IS_FAT_32 = 0; /* FAT32 does not have separate root entries. */
00732   
00733   ConsoleWrite("\rFile system is ");
00734   if (IS_FAT_32){
00735     ConsoleWrite("FAT32");
00736   } else {
00737     ConsoleWrite("FAT16");
00738   }
00739 
00740   ConsoleWrite("\rFile system signature is ");
00741   for (temp.c=0;temp. c<8; temp.c++)
00742     if (IS_FAT_32){
00743       ConsolePutChar(diskSect.fat.ext._32.BS_FilSysType[temp.c]);
00744     } else {
00745       ConsolePutChar(diskSect.fat.ext._16.BS_FilSysType[temp.c]);
00746     }
00747 
00748   if (!IS_FAT_32){
00749     if (diskSect.fat.ext._16.BS_FilSysType[4]=='2'){
00750       IS_FAT_12 = 1;
00751       ConsoleWrite("Well, actually it's FAT12 filesystem.\r");
00752     }
00753   }    
00754   
00755 
00756   ConsoleWrite("\rVolume Label is ");
00757   for (temp.c=0; temp.c<11; temp.c++)
00758     if (IS_FAT_32){
00759       ConsolePutChar(diskSect.fat.ext._32.BS_VolLab[temp.c]);
00760     } else {
00761       ConsolePutChar(diskSect.fat.ext._16.BS_VolLab[temp.c]);
00762     }
00763   /* OK, let's calculate */
00764   /* First, let's get rid of the idea that we have byte addresses
00765      in the file system. Nope, let's only deal in physical disk
00766      sectors of 512 bytes. First we convert the FAT byter per sector
00767      value to "512B disk sectors per fat sector" value. */
00768 
00769   diskSect.fat.BPB_BytsPerSec /= 512;
00770 
00771   /* Then we adjust the Sector per Cluster to mean physical disk
00772      sectors. in 99% of the cases it is already so because bytes
00773      per sector almost always is 512 in FAT. Maximum cluster size
00774      is 65536 bytes (128 disk sectors). */
00775 
00776   fatSectorsPerCluster =
00777     diskSect.fat.BPB_SecPerClus *= diskSect.fat.BPB_BytsPerSec;
00778   /* Note: BPB_BytsPerSec has already been divided by 512 */  
00779 
00780   ConsoleWrite("\rSectors per Cluster: ");
00781   ConsolePutUInt(fatSectorsPerCluster);
00782   
00783   fatStart = (unsigned long)sectorAddress.l
00784     + (unsigned long)diskSect.fat.BPB_RsvdSecCnt 
00785     * (unsigned long)diskSect.fat.BPB_BytsPerSec;
00786 
00787   ConsoleWrite("\rFAT Start sector: ");
00788   ConsolePutUInt(fatStart);
00789 
00790   rootStart = diskSect.fat.BPB_FATSz16;
00791   if (rootStart==0){
00792     if (!IS_FAT_32) 
00793       return 0x0b; /* should be FAT32; can not find root directory */
00794     rootStart = diskSect.fat.ext._32.BPB_FATSz32;
00795   }
00796   rootStart *= diskSect.fat.BPB_NumFATs;
00797   rootStart *= diskSect.fat.BPB_BytsPerSec; /* ADJUSTED BytsPerSec! */
00798   rootStart += fatStart;
00799 
00800   ConsoleWrite("\rRoot start sector: ");
00801   ConsolePutUInt(rootStart);
00802 
00803   dataStart = diskSect.fat.BPB_RootEntCnt >> 4;
00804   dataStart += rootStart;
00805   dataStart -= (fatSectorsPerCluster*2); /*first cluster is cluster 2*/
00806 
00807   ConsoleWrite("\rData start sector: ");
00808   ConsolePutUInt(dataStart);
00809   ConsolePutChar(13);
00810 
00811   return 0;
00812 }

Public unsigned char FGetChar  ) 
 

Read a character from current file.

This can be called after calling OpenFile. It is a slow method for reading character based file data. fileSize holds the number of characters still left in file to be read, check for fileSize=0 to detect end-of-file. If FGetChar is called after the end of file is reached, it does nothing and returns 0.

Definition at line 481 of file filesys.c.

References DiskBlock::Raw::buf, dataBufPtr, diskSect, fileSize, Address::l, LoadNextSector(), Public, DiskBlock::raw, ReadDiskSector(), and sectorAddress.

00481                                {
00482 
00483   if (!fileSize) return 0; //return 0 for end-of-file
00484 
00485   if (dataBufPtr==0){
00486     /* A file has been opened but not read from yet, so read the first
00487        sector. */
00488     ReadDiskSector(sectorAddress.l);
00489     dataBufPtr = diskSect.raw.buf;
00490   }
00491 
00492   if (dataBufPtr>diskSect.raw.buf+511){
00493     /* An end of sector has been reached, read the next sector */    
00494     if (LoadNextSector()){
00495       /* Error, end-of-file according to FAT records */
00496       return 0; /* must return something */
00497     }
00498     dataBufPtr=diskSect.raw.buf;
00499   }
00500 
00501   /* Everything should now be ok for reading a byte. */
00502 
00503   fileSize--;
00504   return (*dataBufPtr++);
00505 }

Here is the call graph for this function:

unsigned long GetFatEntry unsigned long  clusterNumber  ) 
 

Return the FAT entry for cluster clusterNumber.

Definition at line 94 of file filesys.c.

References diskSect, DiskBlock::Fat16Table, DiskBlock::Fat32Table, Address::l, ReadDiskSector(), and sectorAddress.

Referenced by ScanForFreeSector().

00094                                                       {
00095   unsigned char entryNumber; /* entry number inside page */
00096 
00097   if (!IS_FAT_32){ //FAT16
00098     entryNumber = clusterNumber & 0xff; 
00099     clusterNumber >>= 8; 
00100   }else{ //FAT32
00101     entryNumber = clusterNumber & 0x7f;
00102     clusterNumber >>= 7; 
00103   }
00104   clusterNumber += fatStart;
00105   if (sectorAddress.l != clusterNumber){
00106     sectorAddress.l = clusterNumber;
00107     ReadDiskSector(sectorAddress.l);
00108   }
00109   if (IS_FAT_32){
00110     clusterNumber=diskSect.Fat32Table[entryNumber];
00111     return clusterNumber;
00112   }
00113   if ((clusterNumber=diskSect.Fat16Table[entryNumber])==0xffff) return 0xffffffff;
00114   return clusterNumber;
00115 }

Here is the call graph for this function:

unsigned long GetNextSector unsigned long  currentSector  ) 
 

Calculate next sector from currentSector.

Return sector address with MSB set if end of file.

This is the essence of FAT filesystem: traversing through the file allocation table to scan for cluster chains.

Definition at line 205 of file filesys.c.

References addressType, Address::b, Address::B::b0, Address::B::b1, Address::B::b3, ConsolePutChar, diskSect, DiskBlock::Fat16Table, DiskBlock::Fat32Table, Address::l, ReadDiskSector(), and sectorAddress.

Referenced by LoadNextSector(), and OpenFile().

00205                                                         {
00206   addressType fatSector;
00207   unsigned char entryNumber;
00208   
00209   /* how manyth sector from start of data area -> fatsector */
00210   fatSector.l = currentSector - dataStart;
00211   
00212   /* Check for cluster boundary */
00213   /* if we're not in cluster boundary then return currentsector + 1 */
00214   if ((fatSector.b.b0 + 1) % fatSectorsPerCluster){
00215     return currentSector + 1;
00216   }
00217   
00218   /* is the value negative? then return currentSector + 1 */
00219   if (fatSector.b.b3 & 0x80) {
00220     return currentSector + 1;
00221   }    
00222 
00223   /* The trivial conditions are not met, we actually do need to 
00224      look up the next sector info from FAT tables in the disk.*/
00225 
00226   /* convert fatSector from CurrentSectorN to currentClusterN */
00227   fatSector.l /= fatSectorsPerCluster;
00228 
00229   /* calculate which page (fatSector) and entry of FAT table correspond
00230      to current sector */
00231    
00232   if (!IS_FAT_32){ //FAT16
00233     entryNumber = fatSector.b.b0; /* 256 entries / page in FAT16 table */
00234     fatSector.l >>= 8; /* Divide by 256 (n of entries/page in FAT32 table */
00235   }else{ //FAT32
00236     entryNumber =(fatSector.b.b0 & 0x7f); /* 128 entries/page in FAT32 tbl */
00237     fatSector.l >>= 7; /* Divide by 128 (n of entries/sector in FAT32 table */
00238   }
00239   
00240   /* Get sector address for the needed page */
00241   fatSector.l += fatStart;
00242   
00243   /* Load (if needed) table page from disk */
00244   if (sectorAddress.l != fatSector.l){
00245     sectorAddress.l = fatSector.l; /* (not needed because mmc.c does this) */
00246     ReadDiskSector(fatSector.l);
00247     
00248     ConsolePutChar('n');
00249     
00250     
00251   }
00252   /* Now there should be correct FAT entry page in memory... */
00253   
00254   if (!IS_FAT_32){ //FAT16
00255     fatSector.l = diskSect.Fat16Table[entryNumber];
00256     /* Check for FAT16 end-of-file condition */
00257     if ((fatSector.b.b1 == 0xff) && (fatSector.b.b0 == 0xff)){
00258       /* End of file */
00259       fatSector.b.b3 = 0xff; /* return a large value (fat32 compatible) */
00260       return fatSector.l;
00261     }
00262   }else{ //FAT32
00263     fatSector.l = diskSect.Fat32Table[entryNumber] & 0x0fffffff;
00264     /* Check for FAT32 end-of-file condition */
00265     if ((fatSector.b.b3&0x08) //Quick test
00266         && (fatSector.l>0x0ffffff0)){ //Complete test
00267       /* End of file */
00268       return 0xffffffff; /* return EOF*/
00269     }
00270   }
00271   
00272 
00273   /* now fatSector.l contains the proper next cluster value */
00274 
00275   fatSector.l *= fatSectorsPerCluster;
00276   /* now fatSector.l contains the next sector value */
00277 
00278   fatSector.l += dataStart;
00279   /* now fatSector.l contains the proper absolute sector address */
00280 
00281   return fatSector.l;
00282 }

Here is the call graph for this function:

unsigned char InitFileSystem  ) 
 

Start the filing system and initialize all necessary subsystems.

Init storage and file system. FAT16 and FAT32 are supported

Definition at line 931 of file filesys.c.

References currentDisk, LcdLocateHome, LcdPutConstantString(), LcdReset(), RealInitFileSystem(), and SelectDisk().

Referenced by main().

00931                               {
00932   currentDisk = 0;
00933   SelectDisk(0);
00934   LcdReset();
00935   LcdPutConstantString("Insert Card for Drive A:");
00936   RealInitFileSystem();
00937   SelectDisk(1);
00938   LcdLocateHome();
00939   LcdPutConstantString("Insert Card for Drive B:");
00940   RealInitFileSystem();
00941   LcdReset();
00942   SelectDisk(0);
00943   return 0;
00944 }

Here is the call graph for this function:

unsigned char LoadNextSector  ) 
 

Traverse to next sector in file or directory.

End of File

Definition at line 461 of file filesys.c.

References Address::b, Address::B::b1, GetNextSector(), Address::l, ReadDiskSector(), and sectorAddress.

Referenced by FGetChar().

00461                               {
00462   sectorAddress.l = GetNextSector(sectorAddress.l);
00463   if (sectorAddress.b.b1 & 0x80){
00465     return 0x0d; /*EOF*/
00466   }
00467   if (ReadDiskSector(sectorAddress.l)){
00468     return 0x0d; /*EOF*/
00469   }
00470   return 0; /* All OK return */
00471 }

Here is the call graph for this function:

void LocateFreeBlock  ) 
 

Definition at line 166 of file filesys.c.

References ConsolePutChar, ConsolePutUInt, ConsoleWrite, freeEnd, freeSector, freeStart, and ScanForFreeSector().

00166                       {
00167   unsigned long prevFree;
00168   unsigned int neededSize;
00169   
00170   neededSize = NEEDEDSIZE;
00171   freeSector = 0;
00172   ScanForFreeSector();
00173   prevFree = freeSector;
00174   freeStart = freeSector;
00175   while (neededSize--){
00176     ScanForFreeSector();
00177     if (freeSector != (prevFree+1)){ //Gap in free area, restart
00178       freeStart = freeSector;
00179       neededSize = NEEDEDSIZE;
00180     }
00181     prevFree = freeSector;    
00183   }
00184   freeEnd = freeSector; 
00185 
00186   ConsoleWrite("\rFree disk space from ");
00187   ConsolePutUInt(freeStart);
00188   ConsoleWrite(" to ");
00189   ConsolePutUInt(freeEnd);
00190   ConsolePutChar(13);
00191 
00192 }

Here is the call graph for this function:

unsigned char OpenFile unsigned int  fileNumber,
unsigned char  ext1,
unsigned char  ext2,
unsigned char  ext3
 

Open a file for reading.

Prepares the Filing System to read a data file from the storage. Files are referred to by their numbers, not file names. This makes the system generic, not necessarily needing a complex file system such as FAT. The way to assign numbers to files is implementation dependent. Returns 0 when ok, error code otherwise.

Parameters:
fileNumber number of file, starting from beginning of storage, to open.
What this function actually does, is: it starts reading the FAT records from start of the root directory, traversing through subdirectories as it encounters them. When the fileNumber'th valid record is encountered, it sets sectorAddress to point to its first data sector but doesn't load any sector. fileSize is loaded with the size in bytes indicated in the FAT record.

Additionally, if it's called with 0 as the fileNumber and it happens to see an empty directory record, it registers a new file with name RECnnnnn.WAV starting from cluster fragment[0].start with file size from fragment[0].length

Definition at line 530 of file filesys.c.

References DirRecordUnion::Entry::Attr, Temp::c, ConsolePutChar, ConsolePutHex8, ConsolePutUInt, ConsoleWrite, currentFileName, dataBufPtr, DiskBlock::dir, dirLevel, dirStack, diskSect, directoryStack::entry, DirRecordUnion::entry, fileSize, DirRecordUnion::Entry::FileSize, DirRecordUnion::Entry::FstClusHi, DirRecordUnion::Entry::FstClusLo, GetNextSector(), Address::l, MAX_NUMBER_SUBDIRECTORIES, DirRecordUnion::Entry::Name, ReadDiskSector(), directoryStack::sector, sectorAddress, and temp.

Referenced by SelectMidiFile(), SelectRecordFile(), and SelectWaveFile().

00533                                            {
00534   char tempc;
00535 
00536   ConsoleWrite("\rFilesystem: Looking for file ");
00537   ConsolePutUInt(fileNumber);
00538   ConsoleWrite("... ");
00539   
00540   /* Start at the start of root directory. */
00541   dirLevel = 0; /* At root directory */
00542   dirStack[dirLevel].sector=rootStart;
00543   dirStack[dirLevel].entry=0;
00544 
00545 
00546   if (fileNumber==0){
00547     fileNumber = 32766; //use max-1 value for scanning for free entry
00548   }
00549  
00550   while (fileNumber){
00551     ConsolePutChar('f');
00552     if (dirStack[dirLevel].entry==0){
00553       /* At the start of new dir, load first disk sector */
00554       while (ReadDiskSector(dirStack[dirLevel].sector)){
00555         ConsolePutChar('i');
00556         InitMMC;
00557         ConsolePutChar('I');
00558       }
00559     }
00560     temp.c = dirStack[dirLevel].entry;
00561 
00562     /* We are now looking at FAT directory structure. */
00563 
00564     /* Does current entry point to a valid regular file
00565        with the correct first character of extension ? */
00566     /* Attributes: NO directory, NO volume id, NO system, NO hidden */
00567     if (((diskSect.dir[temp.c].entry.Attr & 222) == 0) 
00568         && (diskSect.dir[temp.c].entry.Name[0] != 0xe5) 
00569         && (diskSect.dir[temp.c].entry.Name[8] == ext1)  
00570         && (diskSect.dir[temp.c].entry.Name[9] == ext2)  
00571         && (diskSect.dir[temp.c].entry.Name[10] == ext3)
00572         ){
00573       
00574       /* It is a regular file. */
00575       if (!(--fileNumber)){
00576         
00577         /* ------------ FILE FOUND ------------- */
00578 
00579         sectorAddress.l = 
00580           ((unsigned long)diskSect.dir[temp.c].entry.FstClusHi<<16) 
00581           + diskSect.dir[temp.c].entry.FstClusLo;
00582         sectorAddress.l *= fatSectorsPerCluster;
00583         sectorAddress.l += dataStart;
00584         
00585         fileSize = diskSect.dir[temp.c].entry.FileSize;
00586         dataBufPtr = 0; /* Reset data buffer ptr for FGetChar */
00587 
00588         ConsoleWrite("found, FAT name is \"");
00589         for (tempc=0; tempc<11; tempc++){
00590           ConsolePutChar(diskSect.dir[temp.c].entry.Name[tempc]);
00591         }
00592 
00593         //Store file name nicely for displaying on screen :)
00594         for (tempc=0; tempc<8; tempc++){
00595           currentFileName[tempc]=diskSect.dir[temp.c].entry.Name[tempc];
00596         }
00597         currentFileName[8]='.';
00598         currentFileName[9]=diskSect.dir[temp.c].entry.Name[8];
00599         currentFileName[10]=diskSect.dir[temp.c].entry.Name[9];
00600         currentFileName[11]=diskSect.dir[temp.c].entry.Name[10];
00601 #if 0   
00602         displayText[0]=' ';
00603         for (tempc=0; tempc<12; tempc++){
00604           displayText[tempc+1]=currentFileName[tempc];
00605         }
00606 #endif
00607         ConsoleWrite("\"\rFile size: ");
00608         ConsolePutUInt(fileSize);
00609         ConsoleWrite("bytes. ");
00610 
00611         ConsoleWrite("Start cluster: ");
00612         ConsolePutHex8(diskSect.dir[temp.c].entry.FstClusHi);
00613         ConsolePutHex8(diskSect.dir[temp.c].entry.FstClusLo);
00614         ConsoleWrite("h, sector ");
00615         ConsolePutUInt(sectorAddress.l);
00616         ConsoleWrite("decimal.\r");
00617         
00618         return 0; /* File found, All OK return */
00619       }
00620     } /* it was a regular file */
00621     
00622 
00623 
00624     /* Is it a subdirectory? */
00625     if (((diskSect.dir[temp.c].entry.Attr & 16) != 0) 
00626         && (diskSect.dir[temp.c].entry.Name[0] != '.') /* skip . and .. */ 
00627         && (diskSect.dir[temp.c].entry.Name[0] != 0xe5) 
00628         && (diskSect.dir[temp.c].entry.Name[0] != 0)  ){
00629 
00630       /* It is a subdirectory. */
00631 
00632       if (dirLevel<MAX_NUMBER_SUBDIRECTORIES-1){
00633         /* Yes, we have room in dirStack to traverse deeper. */
00634         dirLevel++; /* Advance to next directory level */       
00635         sectorAddress.l = 
00636           ((unsigned long)diskSect.dir[temp.c].entry.FstClusHi<<16) 
00637           + diskSect.dir[temp.c].entry.FstClusLo;
00638         sectorAddress.l *= fatSectorsPerCluster;
00639         sectorAddress.l += dataStart;
00640       
00641         /* Prepare for loading. */
00642         dirStack[dirLevel].sector = sectorAddress.l;
00643         dirStack[dirLevel].entry = 255; /* Magic number */
00644                 
00645       } /* we had room in dirStack */      
00646     } /* it was a subdirectory */
00647       
00648 
00649     /* Have we reached the end of the directory? */
00650     if (diskSect.dir[temp.c].entry.Name[0] == 0){
00651       /* It's the end of directory. */
00652 
00653       /* Is it the end of root directory? */
00654       if (dirLevel == 0){
00655         /* End of root directory, end of all files in volume */
00656         ConsoleWrite("File not found.\r");
00657         sectorAddress.l = dataStart; 
00658         /* when in error point to start of data */
00659         return 0x0c; /* File Not Found return */
00660       } 
00661 
00662       /* End of subdirectory, return from subdirectory */
00663       dirLevel--;
00664       ReadDiskSector(dirStack[dirLevel].sector);
00665       /* restore temp entry pointer */
00666       temp.c = dirStack[dirLevel].entry;
00667 
00668     } /* it was end of directory */
00669 
00670 
00671     /* Advance to next entry */
00672     temp.c++;
00673     
00674     /* If we just went to a subdir, set temp entry pointer to 0 */
00675     if (dirStack[dirLevel].entry == 255){
00676       /* Magic Number 255: we have gone to a subdirectory */
00677       temp.c=0;
00678     }
00679       
00680     if (temp.c==16){ /* End of sector */
00681       /* Prepare to load next sector */
00682       dirStack[dirLevel].sector = GetNextSector (dirStack[dirLevel].sector);
00683       temp.c=0;
00684     }
00685 
00686     dirStack[dirLevel].entry = temp.c;
00687   }
00688 
00689   /* Control should never reach this far, end of root directory should
00690      occur first. */
00691 
00692   sectorAddress.l = dataStart; /* when in error point to start of data */
00693   return 0x0c; /* File Not Found return */
00694 }

Here is the call graph for this function:

void PConvertClusterToSector unsigned long *  cluster  ) 
 

Convert cluster number to sector number.

Definition at line 87 of file filesys.c.

Referenced by ScanForFreeSector().

00087                                                     {
00088   *cluster*=fatSectorsPerCluster;
00089   *cluster+=dataStart;
00090 }

void PConvertSectorToCluster unsigned long *  sector  ) 
 

Convert sector number to cluster number.

Definition at line 81 of file filesys.c.

Referenced by ScanForFreeSector().

00081                                                    {
00082   *sector-=dataStart;
00083   *sector/=fatSectorsPerCluster;
00084 }

unsigned char RealInitFileSystem  ) 
 

Definition at line 841 of file filesys.c.

References Address::b, Address::B::b0, Address::B::b1, Address::B::b2, Address::B::b3, DiskBlock::Raw::buf, ConsolePutChar, ConsolePutHex8, ConsolePutUInt, ConsoleWrite, dataStart, diskSect, FatInitGlobals(), fatStart, freeSector, InitStorage(), Address::l, DiskBlock::raw, ReadDiskSector(), rootStart, and sectorAddress.

Referenced by InitFileSystem().

00841                                   {
00842   unsigned char c;
00843   
00844   /* Initialize variables to sane values in case of error exit. */
00845   fatStart = 0;
00846   rootStart = 0;
00847   dataStart = 0;
00848   freeSector = 0;
00849 
00850 
00851   ConsoleWrite("Init: Filesystem; supports: MBR, FAT16, FAT32\r");
00852 
00853   ConsoleWrite("Trying to bring up storage...\r");
00854   /* Initialize the storage system */
00855   if ((c=InitStorage())){
00856     ConsoleWrite("Storage init returns error ");
00857     ConsolePutUInt(c);
00858     ConsolePutChar(13);
00859     return c; /* Error in InitStorage */
00860   }
00861 
00862   ConsoleWrite("Storage ok.\rSector 0 read...");
00863 
00864   /* Load MBR */
00865   sectorAddress.l = 0; /* the first sector on disk */
00866   ReadDiskSector(0);
00867 
00868 
00869 
00870 
00871   ConsoleWrite("ok.\rSector signature...");
00872   
00873   /* Ok, it should be a MBR sector. Let's verify */
00874   if (diskSect.raw.buf[510] != 0x55)
00875     return 8; /* sector 0 is not MBR. */
00876   if (diskSect.raw.buf[511] != 0xaa)
00877     return 8; /* sector 0 is not MBR. */
00878 
00879   ConsoleWrite("ok.\rPartition 1...");
00880 
00881 
00882   if (!((diskSect.raw.buf[0x036]=='F')
00883       &&(diskSect.raw.buf[0x037]=='A')
00884       &&(diskSect.raw.buf[0x038]=='T'))){
00885    
00886     /* This checks that partition 1 is active. Alter code to allow
00887      * other partition configurations. */
00888     if (diskSect.raw.buf[0x1be] == 0x80){
00889       sectorAddress.b.b0 = diskSect.raw.buf[0x1c6];
00890       sectorAddress.b.b1 = diskSect.raw.buf[0x1c7];
00891       sectorAddress.b.b2 = diskSect.raw.buf[0x1c8];
00892       sectorAddress.b.b3 = diskSect.raw.buf[0x1c9];
00893       ConsoleWrite (" active");
00894     }else{
00895       //-------- DEBUG: Uncomment if you want to explore the sector
00896       //DumpDiskSector();
00897       //while (!KEY_BUTTON);
00898       sectorAddress.b.b0 = diskSect.raw.buf[0x1c6];
00899       sectorAddress.b.b1 = diskSect.raw.buf[0x1c7];
00900       sectorAddress.b.b2 = diskSect.raw.buf[0x1c8];
00901       sectorAddress.b.b3 = diskSect.raw.buf[0x1c9];
00902             
00903     }
00904     
00905     //    return 9; /* No active partition*/
00906     
00907   }
00908   
00909   ConsoleWrite(" at sector ");
00910   ConsolePutHex8(sectorAddress.b.b3);
00911   ConsolePutHex8(sectorAddress.b.b2);
00912   ConsolePutHex8(sectorAddress.b.b1);
00913   ConsolePutHex8(sectorAddress.b.b0);
00914   ConsolePutChar('\r');
00915 
00916 
00917   /* Now leave MBR and load sector 0 of partition */
00918   //SeekDiskSectorToRead();
00919   //ReadDiskSector(); /* to global buffer */
00920   
00921   ReadDiskSector(sectorAddress.l);
00922 
00923   if (FatInitGlobals()){
00924     return 0x0a; /* FAT init failed */
00925   }
00926 
00927   return 0; /* All ok return */
00928 
00929 }

Here is the call graph for this function:

unsigned char ScanForFreeSector  ) 
 

Search for next free sector.

If freeSector is zero, a new file should be allocated.

Definition at line 139 of file filesys.c.

References dataStart, freeSector, GetFatEntry(), PConvertClusterToSector(), and PConvertSectorToCluster().

Referenced by LocateFreeBlock().

00139                                  {
00140   if ((freeSector) && (freeSector-dataStart+1)%fatSectorsPerCluster){
00141     freeSector++;
00142     return 1;
00143   }  
00144   
00145   if (freeSector){
00146     freeSector++;
00147     PConvertSectorToCluster(&freeSector); //Sector converted to cluster
00148   }else{
00149     freeSector=3; //First Cluster# to start search
00150   }
00151 
00152   //scan until free entry is found
00153   while(GetFatEntry(freeSector)){    
00154     freeSector++;
00155   }
00156 
00157   PConvertClusterToSector(&freeSector); //Converted back to sector
00158   return 1;
00159 }

Here is the call graph for this function:

unsigned char SelectDisk unsigned char  n  ) 
 

Start the filing system and initialize all necessary subsystems.

Init storage and file system. FAT16 and FAT32 are supported

Definition at line 817 of file filesys.c.

References currentDisk, diskInfoStruct::dataStart, dataStart, disk, diskInfoStruct::fatSectorsPerCluster, fatSectorsPerCluster, diskInfoStruct::fatStart, fatStart, diskInfoStruct::rootStart, and rootStart.

Referenced by InitFileSystem(), PlayerTaskHandler(), SelectMidiFile(), SelectRecordFile(), and SelectWaveFile().

00817                                          {
00818   unsigned char oldDisk;
00819   if (n>1) return 1;
00820   oldDisk = currentDisk;
00821 
00822   disk[oldDisk].fatStart = fatStart;
00823   disk[oldDisk].rootStart = rootStart; 
00824   disk[oldDisk].dataStart = dataStart; 
00825   disk[oldDisk].fatSectorsPerCluster = fatSectorsPerCluster;
00826   
00827   fatStart = disk[n].fatStart;
00828   rootStart = disk[n].rootStart;
00829   dataStart = disk[n].dataStart;
00830   fatSectorsPerCluster = disk[n].fatSectorsPerCluster;
00831   if (n==0) {
00832     currentDisk = 0;
00833   }else{
00834     currentDisk = 1;
00835   }
00836   return 0;
00837 }


Variable Documentation

bit currentDisk = 0
 

Definition at line 43 of file filesys.c.

xdata char currentFileName[12]
 

8 first characters of current file name

Definition at line 74 of file filesys.c.

Referenced by OpenFile(), SelectMidiFile(), SelectRecordFile(), and SelectWaveFile().

data unsigned long dataStart
 

(In FAT the start is cluster 2, so dataStart actually points to 2 clusters before the start of data area)

Definition at line 23 of file filesys.c.

Referenced by FatInitGlobals(), RealInitFileSystem(), ScanForFreeSector(), and SelectDisk().

xdata unsigned char dirLevel = 0
 

Current directory level, 0=Root directory.

Definition at line 68 of file filesys.c.

Referenced by OpenFile().

xdata struct directoryStack dirStack[MAX_NUMBER_SUBDIRECTORIES]
 

Directory traversing structure.

Referenced by OpenFile().

xdata diskInfo disk[2]
 

Definition at line 42 of file filesys.c.

Referenced by SelectDisk().

data unsigned char fatSectorsPerCluster
 

FAT Global sectors per cluster.

Definition at line 25 of file filesys.c.

Referenced by FatInitGlobals(), and SelectDisk().

data unsigned long fatStart
 

Starting sector of FAT table.

Definition at line 17 of file filesys.c.

Referenced by FatInitGlobals(), RealInitFileSystem(), and SelectDisk().

xdata unsigned long fileSize
 

Size of current file to play.

Definition at line 56 of file filesys.c.

Referenced by BuildFragmentTable(), FGetChar(), and OpenFile().

xdata struct fragmentEntry fragment[MAX_NUMBER_FRAGMENTS]
 

Fragment Table.

Maximum fragment size is (4G-1 sectors)

Referenced by BuildFragmentTable(), SelectMidiFile(), SelectRecordFile(), and SelectWaveFile().

xdata unsigned long freeEnd
 

Definition at line 164 of file filesys.c.

Referenced by LocateFreeBlock().

xdata unsigned long freeSector = 0
 

Next free cluster number.

Definition at line 71 of file filesys.c.

Referenced by LocateFreeBlock(), RealInitFileSystem(), and ScanForFreeSector().

xdata unsigned long freeStart
 

Definition at line 163 of file filesys.c.

Referenced by LocateFreeBlock().

bit IS_FAT_12 = 0
 

Set if this is a FAT12 filesystem.

Definition at line 77 of file filesys.c.

Referenced by FatInitGlobals().

xdata struct fragmentEntry midiFragment[MAX_NUMBER_FRAGMENTS]
 

Definition at line 51 of file filesys.c.

Referenced by PlayerTaskHandler(), and SelectMidiFile().

data unsigned long rootStart
 

Starting sector of root directory.

Definition at line 19 of file filesys.c.

Referenced by FatInitGlobals(), RealInitFileSystem(), and SelectDisk().

xdata struct fragmentEntry waveFragment[MAX_NUMBER_FRAGMENTS]
 

Definition at line 52 of file filesys.c.

Referenced by PlayerTaskHandler(), and SelectWaveFile().


All software copyright 2000-2004 VLSI Solution OY. Redistribution of these software modules is limited to VLSI Solution Oy chip promotional use only. Free or commercial use of these software modules in MP3 players is ok if the product includes chip(s) from VLSI. You can request the complete (compilable) package from mp3@vlsi.fi. This exampe code is provided with good faith to assist You in code development, but under no circumstances will VLSI offer any guarantees on the usability or functionality of any example software or its fitness for any purpose.