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 926 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().

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

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

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(), 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