#include "buffer.h"
#include "board.h"
Include dependency graph for filesys.h:
This graph shows which files directly or indirectly include this file:
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, unsigned char ext1, unsigned char ext2, unsigned char ext3) |
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 | LocateFreeBlock () |
unsigned char | SelectDisk (unsigned char n) |
Start the filing system and initialize all necessary subsystems. | |
Variables | |
Public xdata unsigned long | fileSize |
Size of current file to play. | |
xdata struct fragmentEntry | fragment [MAX_NUMBER_FRAGMENTS] |
Fragment Table. | |
xdata struct fragmentEntry | midiFragment [MAX_NUMBER_FRAGMENTS] |
xdata struct fragmentEntry | waveFragment [MAX_NUMBER_FRAGMENTS] |
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. | |
xdata unsigned long | freeStart |
xdata unsigned long | freeEnd |
bit | currentDisk |
Definition in file filesys.h.
|
Use PSW User Definable Flag to indicate FAT16/32.
Definition at line 15 of file filesys.h. Referenced by BuildFragmentTable(), and FatInitGlobals(). |
|
Maximum allowable number of fragments in file.
Definition at line 22 of file filesys.h. Referenced by BuildFragmentTable(). |
|
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, Temp::l, Address::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:
|
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:
|
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:
|
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:
|
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.
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, DirRecordUnion::entry, directoryStack::entry, DirRecordUnion::Entry::FileSize, 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:
|
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:
|
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, dataStart, diskInfoStruct::dataStart, disk, fatSectorsPerCluster, diskInfoStruct::fatSectorsPerCluster, fatStart, diskInfoStruct::fatStart, rootStart, and diskInfoStruct::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 }
|
|
|
|
8 first characters of current file name
Definition at line 74 of file filesys.c. Referenced by OpenFile(), SelectMidiFile(), SelectRecordFile(), and SelectWaveFile(). |
|
FAT Global sectors per cluster.
Definition at line 25 of file filesys.c. Referenced by FatInitGlobals(), and SelectDisk(). |
|
Size of current file to play.
Definition at line 56 of file filesys.c. Referenced by BuildFragmentTable(), FGetChar(), and OpenFile(). |
|
Fragment Table.
|
|
Definition at line 164 of file filesys.c. Referenced by LocateFreeBlock(). |
|
Next free cluster number.
Definition at line 71 of file filesys.c. Referenced by LocateFreeBlock(), RealInitFileSystem(), and ScanForFreeSector(). |
|
Definition at line 163 of file filesys.c. Referenced by LocateFreeBlock(). |
|
Definition at line 51 of file filesys.c. Referenced by PlayerTaskHandler(), and SelectMidiFile(). |
|
Definition at line 52 of file filesys.c. Referenced by PlayerTaskHandler(), and SelectWaveFile(). |