VLSI Solution Oy VLSI Solution Oy Evaluation MP3 Player Source Code Documentation

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

filesys.h File Reference

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

#include "buffer.h"
#include "board.h"

Include dependency graph for filesys.h:

Include dependency graph

This graph shows which files directly or indirectly include this file:

Included by dependency graph

Go to the source code of this file.

Classes

struct  fragmentEntry
 Fragment Table. More...


Defines

#define IS_FAT_32   UDF
 Use PSW User Definable Flag to indicate FAT16/32.

#define MAX_NUMBER_FRAGMENTS   10
 Maximum allowable number of fragments in file.


Functions

unsigned char InitFileSystem ()
 Start the filing system and initialize all necessary subsystems.

unsigned char OpenFile (unsigned int fileNumber)
 Open a file for reading.

unsigned char FGetChar ()
 Read a character from current file.

unsigned char BuildFragmentTable (void)
 Build a fragment table starting from current sector.

unsigned char ScanForFreeSector ()
 Search for next free sector.

void WriteClusterChain ()
 Write a cluster chain to FAT for a fragment.


Variables

Public xdata unsigned long fileSize
 Size of current file to play.

xdata struct fragmentEntry fragment [MAX_NUMBER_FRAGMENTS]
 Fragment Table.

xdata char currentFileName [12]
 8 first characters of current file name

xdata unsigned long freeSector
 Next free cluster number.

data unsigned char fatSectorsPerCluster
 FAT Global sectors per cluster.


Detailed Description

File system interface, Implemented: FAT16, FAT32.

Definition in file filesys.h.


Define Documentation

#define IS_FAT_32   UDF
 

Use PSW User Definable Flag to indicate FAT16/32.

Definition at line 15 of file filesys.h.

Referenced by BuildFragmentTable(), FatInitGlobals(), GetFatEntry(), GetNextSector(), and WriteClusterChain().

#define MAX_NUMBER_FRAGMENTS   10
 

Maximum allowable number of fragments in file.

Definition at line 22 of file filesys.h.


Function Documentation

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 401 of file filesys.c.

References Address::b, Address::B::b0, Address::B::b1, Address::B::b3, dataStart, diskSect, DiskBlock::Fat16Table, DiskBlock::Fat32Table, fatSectorsPerCluster, fatStart, fileSize, fragment, IS_FAT_12, IS_FAT_32, Temp::l, Address::l, fragmentEntry::length, MAX_NUMBER_FRAGMENTS, Public, ReadDiskSector(), sectorAddress, fragmentEntry::start, and temp.

Referenced by PlayCurrentFile().

00401 { 00402 00403 unsigned char c=0; 00404 addressType this,next; 00405 addressType fatSector; 00406 unsigned char entryNumber; 00407 00408 00409 if (IS_FAT_12){ 00410 ConsoleWrite("Single fragment support for FAT12"); 00411 fragment[0].start = sectorAddress.l; 00412 fragment[0].length = fileSize/512; 00413 return(1); //Return 1 fragment 00414 } 00415 00416 00417 //as long as the sectorAddress is "sane"... 00418 while (!(sectorAddress.b.b3 & 0x80)){ 00419 00420 fragment[c].start = sectorAddress.l; 00421 fragment[c].length = fatSectorsPerCluster; 00422 00423 /* Find cluster entry for the current sector */ 00424 00425 /* in how manyth sector from start of data area are we? ->this */ 00426 this.l = sectorAddress.l - dataStart; 00427 /* convert from CurrentSectorN to currentClusterN */ 00428 this.l /= fatSectorsPerCluster; 00429 /* this.l is now the current cluster number */ 00430 00431 00432 /* now let's find the FAT entry for this.l cluster */ 00433 if (!IS_FAT_32){ //FAT16 00434 entryNumber = this.b.b0; /* 256 entries / page in FAT16 table */ 00435 fatSector.l = this.l >> 8; /* Div by n of entries/page in FAT16 tbl*/ 00436 }else{ //FAT32 00437 entryNumber = (this.b.b0 & 0x7f); /* 128 entries/page in FAT32 table */ 00438 fatSector.l = this.l >> 7; /* Div by n of entries/page in FAT32 tbl*/ 00439 } 00440 fatSector.l += fatStart; 00441 /* fatSector.l is now the DISK SECTOR NUMBER CONTAINING THE FAT table */ 00442 /* read this page into memory */ 00443 ReadDiskSector(fatSector.l); 00444 00445 if (!IS_FAT_32){ //FAT16 00446 next.l = diskSect.Fat16Table[entryNumber]; /* get next cluster n */ 00447 /* Check for FAT16 end-of-file condition */ 00448 if ((next.b.b1 == 0xff) && (next.b.b0 == 0xff)){ 00449 /* FAT16 End of file */ 00450 next.b.b3 = 0xff; /* return a large value (fat32 compatible) */ 00451 } 00452 }else{ //FAT32 00453 next.l = diskSect.Fat32Table[entryNumber]&0x0fffffff; 00454 } 00455 /* next.l is the FAT entry (next cluster number) */ 00456 00457 00458 ConsoleWrite("\rFragment start: cluster "); 00459 ConsolePutUInt(this.l); 00460 ConsoleWrite("sector "); 00461 ConsolePutUInt(fragment[c].start); 00462 00463 while (next.l==(this.l+1)){ 00464 //Not a fragment break -- continue to next entry 00465 00466 //in this temp.l is used only to allow compiler memory spilling to temp 00467 temp.l = fragment[c].length; 00468 temp.l += fatSectorsPerCluster; 00469 fragment[c].length = temp.l; 00470 00471 entryNumber++; 00472 00473 // --- Check for a page break 00474 if (entryNumber==0){ //entryNumber has rolled over!!!! (8bit char) 00475 //FAT16 table page border is reached 00476 fatSector.l++; //Advance to next page; 00477 entryNumber=0; 00478 ReadDiskSector(fatSector.l); 00479 } 00480 if (IS_FAT_32 && (entryNumber==128)){ 00481 //FAT32 table page border is reached 00482 fatSector.l++; 00483 entryNumber=0; 00484 ReadDiskSector(fatSector.l); 00485 } 00486 00487 // --- Advance to next cluster 00488 this.l = next.l; 00489 00490 if (!IS_FAT_32){ 00491 //FAT16 get next cluster n 00492 next.l = diskSect.Fat16Table[entryNumber]; 00493 if ((next.b.b1==0xff)&&(next.b.b0==0xff)){ 00494 //FAT16 end-of-file 00495 next.b.b3 = 0xff; //mark end-of-file (FAT32 compatible) 00496 } 00497 }else{ 00498 //FAT32 get next cluster n 00499 next.l = diskSect.Fat32Table[entryNumber]; 00500 } 00501 }//This repeats until there is a discontinuity 00502 00503 /* next.l now has the cluster entry for last cluster in fragment 00504 it has a high value if eof (see FAT spec) */ 00505 00506 00507 ConsoleWrite("Size: "); 00508 ConsolePutUInt(fragment[c].length); 00509 ConsoleWrite("sectors."); 00510 00511 //EOF test 00512 if ((next.b.b3&0x08) //Quick test 00513 && ((next.l>0x0ffffff0) | !IS_FAT_32)){ //Complete test 00514 //EOF 00515 ConsoleWrite(" <EOF>\r"); 00516 sectorAddress.b.b3 = 0xff; 00517 }else{ 00518 00519 //Determine next physical sector for next fragment 00520 sectorAddress.l = next.l; 00521 sectorAddress.l *= fatSectorsPerCluster; 00522 sectorAddress.l += dataStart; 00523 } 00524 00525 c++; //Advance to next fragment number 00526 00527 if (c==MAX_NUMBER_FRAGMENTS){ 00528 //End of RAM space allocated for fragment table 00529 //Force end-of-file 00530 sectorAddress.b.b3=0xff; 00531 } 00532 00533 }//break or continue to next cluster 00534 00535 return c; //Return number of fragments; 00536 }

Here is the call graph for this function:

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 561 of file filesys.c.

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

Referenced by GetAVIBlock().

00561 { 00562 00563 if (!fileSize) return 0; //return 0 for end-of-file 00564 00565 if (dataBufPtr==0){ 00566 /* A file has been opened but not read from yet, so read the first 00567 sector. */ 00568 ReadDiskSector(sectorAddress.l); 00569 dataBufPtr = diskSect.raw.buf; 00570 } 00571 00572 if (dataBufPtr>diskSect.raw.buf+511){ 00573 /* An end of sector has been reached, read the next sector */ 00574 if (LoadNextSector()){ 00575 /* Error, end-of-file according to FAT records */ 00576 return 0; /* must return something */ 00577 } 00578 dataBufPtr=diskSect.raw.buf; 00579 } 00580 00581 /* Everything should now be ok for reading a byte. */ 00582 00583 fileSize--; 00584 return (*dataBufPtr++); 00585 }

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 923 of file filesys.c.

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

Referenced by main().

00923 { 00924 unsigned char c; 00925 00926 /* Initialize variables to sane values in case of error exit. */ 00927 fatStart = 0; 00928 rootStart = 0; 00929 dataStart = 0; 00930 freeSector = 0; 00931 00932 ConsoleWrite("Init: Filesystem; supports: MBR, FAT16, FAT32\r"); 00933 00934 ConsoleWrite("Trying to bring up storage...\r"); 00935 /* Initialize the storage system */ 00936 if ((c=InitStorage())){ 00937 ConsoleWrite("Storage init returns error "); 00938 ConsolePutUInt(c); 00939 ConsolePutChar(13); 00940 return c; /* Error in InitStorage */ 00941 } 00942 00943 ConsoleWrite("Storage ok.\rSector 0 read..."); 00944 00945 /* Load MBR */ 00946 sectorAddress.l = 0; /* the first sector on disk */ 00947 ReadDiskSector(0); 00948 00949 00950 00951 00952 ConsoleWrite("ok.\rSector signature..."); 00953 00954 /* Ok, it should be a MBR sector. Let's verify */ 00955 if (diskSect.raw.buf[510] != 0x55) 00956 return 8; /* sector 0 is not MBR. */ 00957 if (diskSect.raw.buf[511] != 0xaa) 00958 return 8; /* sector 0 is not MBR. */ 00959 00960 ConsoleWrite("ok.\rPartition 1..."); 00961 00962 00963 if (!((diskSect.raw.buf[0x036]=='F') 00964 &&(diskSect.raw.buf[0x037]=='A') 00965 &&(diskSect.raw.buf[0x038]=='T'))){ 00966 00967 00968 00969 00970 /* This checks that partition 1 is active. Alter code to allow 00971 * other partition configurations. */ 00972 if (diskSect.raw.buf[0x1be] == 0x80){ 00973 sectorAddress.b.b0 = diskSect.raw.buf[0x1c6]; 00974 sectorAddress.b.b1 = diskSect.raw.buf[0x1c7]; 00975 sectorAddress.b.b2 = diskSect.raw.buf[0x1c8]; 00976 sectorAddress.b.b3 = diskSect.raw.buf[0x1c9]; 00977 ConsoleWrite (" active"); 00978 }else{ 00979 //-------- DEBUG: Uncomment if you want to explore the sector 00980 //DumpDiskSector(); 00981 //while (!KEY_BUTTON); 00982 sectorAddress.b.b0 = diskSect.raw.buf[0x1c6]; 00983 sectorAddress.b.b1 = diskSect.raw.buf[0x1c7]; 00984 sectorAddress.b.b2 = diskSect.raw.buf[0x1c8]; 00985 sectorAddress.b.b3 = diskSect.raw.buf[0x1c9]; 00986 00987 } 00988 00989 // return 9; /* No active partition*/ 00990 00991 } 00992 00993 ConsoleWrite(" at sector "); 00994 ConsolePutHex8(sectorAddress.b.b3); 00995 ConsolePutHex8(sectorAddress.b.b2); 00996 ConsolePutHex8(sectorAddress.b.b1); 00997 ConsolePutHex8(sectorAddress.b.b0); 00998 ConsolePutChar('\r'); 00999 01000 01001 /* Now leave MBR and load sector 0 of partition */ 01002 //SeekDiskSectorToRead(); 01003 //ReadDiskSector(); /* to global buffer */ 01004 01005 ReadDiskSector(sectorAddress.l); 01006 01007 if (FatInitGlobals()){ 01008 return 0x0a; /* FAT init failed */ 01009 } 01010 01011 return 0; /* All ok return */ 01012 01013 }

Here is the call graph for this function:

unsigned char OpenFile unsigned int  fileNumber  ) 
 

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 610 of file filesys.c.

References DirRecordUnion::Entry::Attr, Temp::c, currentFileName, dataBufPtr, dataStart, DiskBlock::dir, dirLevel, dirStack, diskSect, displayText, DirRecordUnion::entry, directoryStack::entry, fatSectorsPerCluster, fileSize, DirRecordUnion::Entry::FileSize, fragment, DirRecordUnion::Entry::FstClusHi, DirRecordUnion::Entry::FstClusLo, GetNextSector(), InitMMC(), Address::l, fragmentEntry::length, MAX_NUMBER_SUBDIRECTORIES, DirRecordUnion::Entry::Name, Public, ReadDiskSector(), rootStart, directoryStack::sector, sectorAddress, fragmentEntry::start, temp, and WriteDiskSector().

Referenced by main(), and WriteClusterChain().

00610 { 00611 char tempc; 00612 00613 ConsoleWrite("\rFilesystem: Looking for file "); 00614 ConsolePutUInt(fileNumber); 00615 ConsoleWrite("... "); 00616 00617 /* Start at the start of root directory. */ 00618 dirLevel = 0; /* At root directory */ 00619 dirStack[dirLevel].sector=rootStart; 00620 dirStack[dirLevel].entry=0; 00621 00622 00623 if (fileNumber==0){ 00624 fileNumber = 32766; //use max-1 value for scanning for free entry 00625 } 00626 00627 while (fileNumber){ 00628 if (dirStack[dirLevel].entry==0){ 00629 /* At the start of new dir, load first disk sector */ 00630 while (ReadDiskSector(dirStack[dirLevel].sector)){ 00631 InitMMC; 00632 } 00633 } 00634 temp.c = dirStack[dirLevel].entry; 00635 00636 /* We are now looking at FAT directory structure. */ 00637 00638 /* Is current entry empty? */ 00639 if ((diskSect.dir[temp.c].entry.Name[0]==0) 00640 ||(diskSect.dir[temp.c].entry.Name[0]==0xe5)){ 00641 /* Yes. Are we supposed to make an entry now? */ 00642 if (fileNumber>30000){ 00643 //yes, this is actually a request to write file directory entry!; 00644 00645 fileNumber = 32767-fileNumber; 00646 00647 diskSect.dir[temp.c].entry.Name[0] ='R'; 00648 diskSect.dir[temp.c].entry.Name[1] ='E'; 00649 diskSect.dir[temp.c].entry.Name[2] ='C'; 00650 diskSect.dir[temp.c].entry.Name[7] =(fileNumber%10)+'0'; 00651 fileNumber /= 10; 00652 diskSect.dir[temp.c].entry.Name[6] =(fileNumber%10)+'0'; 00653 fileNumber /= 10; 00654 diskSect.dir[temp.c].entry.Name[5] =(fileNumber%10)+'0'; 00655 fileNumber /= 10; 00656 diskSect.dir[temp.c].entry.Name[4] =(fileNumber%10)+'0'; 00657 fileNumber /= 10; 00658 diskSect.dir[temp.c].entry.Name[3] =(fileNumber%10)+'0'; 00659 diskSect.dir[temp.c].entry.Name[8] ='W'; 00660 diskSect.dir[temp.c].entry.Name[9] ='A'; 00661 diskSect.dir[temp.c].entry.Name[10]='V'; 00662 diskSect.dir[temp.c].entry.Attr = 0; 00663 diskSect.dir[temp.c].entry.FstClusHi = (fragment[0].start >> 16); 00664 diskSect.dir[temp.c].entry.FstClusLo = (fragment[0].start & 0xffff); 00665 diskSect.dir[temp.c].entry.FileSize = (fragment[0].length); 00666 00667 ConsoleWrite(" Making Directory Entry "); 00668 WriteDiskSector(sectorAddress.l); 00669 00670 return 99; //created a FAT entry 00671 } //register file 00672 } 00673 00674 00675 /* Does current entry point to a regular file? */ 00676 /* Attributes: NO directory, NO volume id, NO system, NO hidden */ 00677 if (((diskSect.dir[temp.c].entry.Attr & 222) == 0) 00678 && (diskSect.dir[temp.c].entry.Name[0] != 0xe5) 00679 && (diskSect.dir[temp.c].entry.Name[0] != 0) ){ 00680 00681 /* It is a regular file. */ 00682 if (!(--fileNumber)){ 00683 00684 /* ------------ FILE FOUND ------------- */ 00685 00686 sectorAddress.l = 00687 ((unsigned long)diskSect.dir[temp.c].entry.FstClusHi<<16) 00688 + diskSect.dir[temp.c].entry.FstClusLo; 00689 sectorAddress.l *= fatSectorsPerCluster; 00690 sectorAddress.l += dataStart; 00691 00692 fileSize = diskSect.dir[temp.c].entry.FileSize; 00693 dataBufPtr = 0; /* Reset data buffer ptr for FGetChar */ 00694 00695 ConsoleWrite("found, FAT name is \""); 00696 for (tempc=0; tempc<11; tempc++){ 00697 ConsolePutChar(diskSect.dir[temp.c].entry.Name[tempc]); 00698 } 00699 00700 //Store file name nicely for displaying on screen :) 00701 for (tempc=0; tempc<8; tempc++){ 00702 currentFileName[tempc]=diskSect.dir[temp.c].entry.Name[tempc]; 00703 } 00704 currentFileName[8]='.'; 00705 currentFileName[9]=diskSect.dir[temp.c].entry.Name[8]; 00706 currentFileName[10]=diskSect.dir[temp.c].entry.Name[9]; 00707 currentFileName[11]=diskSect.dir[temp.c].entry.Name[10]; 00708 displayText[0]=' '; 00709 for (tempc=0; tempc<12; tempc++){ 00710 displayText[tempc+1]=currentFileName[tempc]; 00711 } 00712 00713 ConsoleWrite("\"\rFile size: "); 00714 ConsolePutUInt(fileSize); 00715 ConsoleWrite("bytes. "); 00716 00717 ConsoleWrite("Start cluster: "); 00718 ConsolePutHex8(diskSect.dir[temp.c].entry.FstClusHi); 00719 ConsolePutHex8(diskSect.dir[temp.c].entry.FstClusLo); 00720 ConsoleWrite("h, sector "); 00721 ConsolePutUInt(sectorAddress.l); 00722 ConsoleWrite("decimal.\r"); 00723 00724 return 0; /* File found, All OK return */ 00725 } 00726 } /* it was a regular file */ 00727 00728 00729 00730 /* Is it a subdirectory? */ 00731 if (((diskSect.dir[temp.c].entry.Attr & 16) != 0) 00732 && (diskSect.dir[temp.c].entry.Name[0] != '.') /* skip . and .. */ 00733 && (diskSect.dir[temp.c].entry.Name[0] != 0xe5) 00734 && (diskSect.dir[temp.c].entry.Name[0] != 0) ){ 00735 00736 /* It is a subdirectory. */ 00737 00738 if (dirLevel<MAX_NUMBER_SUBDIRECTORIES-1){ 00739 /* Yes, we have room in dirStack to traverse deeper. */ 00740 dirLevel++; /* Advance to next directory level */ 00741 sectorAddress.l = 00742 ((unsigned long)diskSect.dir[temp.c].entry.FstClusHi<<16) 00743 + diskSect.dir[temp.c].entry.FstClusLo; 00744 sectorAddress.l *= fatSectorsPerCluster; 00745 sectorAddress.l += dataStart; 00746 00747 /* Prepare for loading. */ 00748 dirStack[dirLevel].sector = sectorAddress.l; 00749 dirStack[dirLevel].entry = 255; /* Magic number */ 00750 00751 } /* we had room in dirStack */ 00752 } /* it was a subdirectory */ 00753 00754 00755 /* Have we reached the end of the directory? */ 00756 if (diskSect.dir[temp.c].entry.Name[0] == 0){ 00757 /* It's the end of directory. */ 00758 00759 /* Is it the end of root directory? */ 00760 if (dirLevel == 0){ 00761 /* End of root directory, end of all files in volume */ 00762 ConsoleWrite("File not found.\r"); 00763 sectorAddress.l = dataStart; 00764 /* when in error point to start of data */ 00765 return 0x0c; /* File Not Found return */ 00766 } 00767 00768 /* End of subdirectory, return from subdirectory */ 00769 dirLevel--; 00770 ReadDiskSector(dirStack[dirLevel].sector); 00771 /* restore temp entry pointer */ 00772 temp.c = dirStack[dirLevel].entry; 00773 00774 } /* it was end of directory */ 00775 00776 00777 /* Advance to next entry */ 00778 temp.c++; 00779 00780 /* If we just went to a subdir, set temp entry pointer to 0 */ 00781 if (dirStack[dirLevel].entry == 255){ 00782 /* Magic Number 255: we have gone to a subdirectory */ 00783 temp.c=0; 00784 } 00785 00786 if (temp.c==16){ /* End of sector */ 00787 /* Prepare to load next sector */ 00788 dirStack[dirLevel].sector = GetNextSector (dirStack[dirLevel].sector); 00789 temp.c=0; 00790 } 00791 00792 dirStack[dirLevel].entry = temp.c; 00793 } 00794 00795 /* Control should never reach this far, end of root directory should 00796 occur first. */ 00797 00798 sectorAddress.l = dataStart; /* when in error point to start of data */ 00799 return 0x0c; /* File Not Found return */ 00800 }

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 248 of file filesys.c.

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

Referenced by Record().

00248 { 00249 00250 //ConsoleWrite("\rLooking for free space starting from "); 00251 00252 if ((freeSector) && (freeSector-dataStart+1)%fatSectorsPerCluster){ 00253 //Still room in current cluster... 00254 freeSector++; 00255 00256 //ConsoleWrite("free at sector "); 00257 //ConsolePutUInt(freeSector); 00258 00259 return 1; 00260 } 00261 00262 if (freeSector){ 00263 //Advance to next sector 00264 freeSector++; 00265 //switch from using sectors to using clusters 00266 PConvertSectorToCluster(&freeSector); 00267 }else{ 00268 freeSector=3; //starting cluster entry (should be 2?) 00269 } 00270 00271 00272 //scan until free entry is found 00273 //freeSector actually counts clusters here. 00274 while(GetFatEntry(freeSector)){ 00275 freeSector++; 00276 } 00277 00278 ConsoleWrite("F"); 00279 ConsolePutUInt(freeSector); 00280 00281 00282 //while (!KEY_BUTTON); 00283 //ConsoleWrite("free at cluster "); 00284 //ConsolePutUInt(freeSector); 00285 00286 //switch back from using clusters to using sectors. 00287 PConvertClusterToSector(&freeSector); 00288 00289 //ConsoleWrite("sector "); 00290 //ConsolePutUInt(freeSector); 00291 00292 return 1; 00293 }

Here is the call graph for this function:

void WriteClusterChain  ) 
 

Write a cluster chain to FAT for a fragment.

This takes its input from the fragment[] table. It currently has the ability to register only single fragment from fragment[0]. fragment[1].start should contain the next cluster number after this fragment or 0x0fffffff if this is the last fragment.

This function currently also registers a FAT directory entry for the file to first free entry slot in the directory structure. If no free directory entries are available, it will behave unpredictably. This could happen in FAT32.

OpenFile(0) is a special call to register a directory entry for fragment[0].

Todo:
update second FAT too

update second FAT too

Definition at line 129 of file filesys.c.

References Temp::c, diskSect, DiskBlock::Fat16Table, DiskBlock::Fat32Table, fatSectorsPerCluster, fatStart, fragment, IS_FAT_32, Address::l, fragmentEntry::length, OpenFile(), PConvertSectorToCluster(), ReadDiskSector(), sectorAddress, fragmentEntry::start, temp, and WriteDiskSector().

Referenced by Record().

00129 { 00130 00131 xdata unsigned long currentCluster; //is now fragment[0].start 00132 xdata unsigned long fragSize; //is now fragment[0].length 00133 xdata unsigned long fatPageSector; 00134 xdata unsigned char entryNumber; 00135 00136 00137 // PREPARE 00138 00139 // Calculate starting cluster number... 00140 currentCluster = fragment[0].start; 00141 PConvertSectorToCluster(&currentCluster); 00142 00143 fragSize = fragment[0].length; //size in sectors 00144 00145 // Write cluster number and size in bytes to fragment[0] 00146 // for the function that registers directory entries 00147 fragment[0].start = currentCluster; 00148 fragment[0].length *= 512; 00149 00150 // Locate the relevant page in FAT clusterchain records 00151 fatPageSector = currentCluster; 00152 if (!IS_FAT_32){ //FAT16 00153 entryNumber = fatPageSector & 0xff; 00154 fatPageSector >>= 8; 00155 }else{ //FAT32 00156 entryNumber = fatPageSector & 0x7f; 00157 fatPageSector >>= 7; 00158 } 00159 fatPageSector += fatStart; 00160 00161 ConsoleWrite("Writing clusterchain from: "); ConsolePutUInt(currentCluster); 00162 ConsoleWrite("Fragment size (sectors): "); ConsolePutUInt(fragSize); 00163 ConsoleWrite("FatPageSector: "); ConsolePutUInt(fatPageSector); 00164 ConsoleWrite("EntryNumber: "); ConsolePutUInt(entryNumber); 00165 00166 00167 // WRITE CLUSTER CHAIN TO FIRST FAT 00168 00169 while (fragSize>fatSectorsPerCluster){ 00170 // while more than 1 cluster left... 00171 00172 // is the FAT clusterchain page changed? 00173 if (sectorAddress.l != fatPageSector){ 00174 // Yes, have we advanced by 1 sector? 00175 if (sectorAddress.l == (fatPageSector - 1)){ 00176 //Yes, we must save the edited sector 00177 WriteDiskSector (sectorAddress.l); 00179 } 00180 // at least we need to load the new clusterchain page 00181 sectorAddress.l = fatPageSector; 00182 ReadDiskSector(sectorAddress.l); 00183 }//Load/Save FAT sector 00184 00185 00186 // Register Middle Entry 00187 currentCluster++; //advancce to next cluster 00188 00189 //fragSize-=fatSectorsPerCluster; //we will register one cluster 00190 //to avoid memory spill in C compiler, the preceding line is written as: 00191 for (temp.c = fatSectorsPerCluster;temp.c;temp.c--){ 00192 fragSize--; 00193 } 00194 00195 if (IS_FAT_32){ 00196 diskSect.Fat32Table[entryNumber]=currentCluster; 00197 }else{ 00198 diskSect.Fat16Table[entryNumber]=(currentCluster&0xffff); 00199 } 00200 00201 // Calculate next entry position in FAT records 00202 fatPageSector = currentCluster; 00203 if (!IS_FAT_32){ //FAT16 00204 entryNumber = fatPageSector & 0xff; 00205 fatPageSector >>= 8; 00206 }else{ //FAT32 00207 entryNumber = fatPageSector & 0x7f; 00208 fatPageSector >>= 7; 00209 } 00210 fatPageSector += fatStart; 00211 00212 }//while 00213 00214 00215 // WRITE THE FINAL ENTRY TO FAT CLUSTERCHAIN 00216 00217 // is the FAT clusterchain page changed? 00218 if (sectorAddress.l != fatPageSector){ 00219 // Yes, have we advanced by 1 sector? 00220 if (sectorAddress.l == (fatPageSector - 1)){ 00221 //Yes, we must save the edited sector 00222 WriteDiskSector (sectorAddress.l); 00224 } 00225 // at least we need to load the new clusterchain page 00226 sectorAddress.l = fatPageSector; 00227 ReadDiskSector(sectorAddress.l); 00228 }//Load/Save FAT sector 00229 00230 00231 //Write the Last entry 00232 if (IS_FAT_32){ 00233 diskSect.Fat32Table[entryNumber]=fragment[1].start; 00234 }else{ 00235 diskSect.Fat16Table[entryNumber]=(fragment[1].start & 0xffff); 00236 } 00237 WriteDiskSector(sectorAddress.l); //Write last sector 00238 00239 OpenFile(0); //Register FAT entry 00240 00241 }

Here is the call graph for this function:


Variable Documentation

xdata char currentFileName[12]
 

8 first characters of current file name

Definition at line 31 of file filesys.h.

Referenced by main(), and OpenFile().

data unsigned char fatSectorsPerCluster
 

FAT Global sectors per cluster.

Definition at line 84 of file filesys.h.

Referenced by BuildFragmentTable(), FatInitGlobals(), GetNextSector(), OpenFile(), PConvertClusterToSector(), PConvertSectorToCluster(), Record(), ScanForFreeSector(), and WriteClusterChain().

Public xdata unsigned long fileSize
 

Size of current file to play.

Definition at line 17 of file filesys.h.

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

xdata struct fragmentEntry fragment[MAX_NUMBER_FRAGMENTS]
 

Fragment Table.

xdata unsigned long freeSector
 

Next free cluster number.

Definition at line 82 of file filesys.h.

Referenced by InitFileSystem(), Record(), and ScanForFreeSector().


All software copyright 2000-2004 VLSI Solution OY. Redistribution of these software modules are limited to promotional use only and only with the VS1011 / VS1002 / VS1003 MP3-Evakit evaluation boards. Free or commercial use of these software modules in MP3 players is ok if the product includes MP3 decoder chip(s) from VLSI. You can request the complete (compilable) package from mp3@vlsi.fi