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.c

Go to the documentation of this file.
00001 00005 #include "board.h" 00006 #include "filesys.h" 00007 #include "storage.h" 00008 #include "console.h" 00009 #include "mmc.h" 00010 00011 00012 /* This needs display to put file name directly to display buffer */ 00013 /* It's not pretty but it saves a lot of memory! */ 00014 #include "display.h" 00015 00016 00017 00021 data unsigned long fatStart; 00022 00024 data unsigned long rootStart; 00025 00029 data unsigned long dataStart; 00030 00032 data unsigned char fatSectorsPerCluster; 00033 00034 00035 00037 #define MAX_NUMBER_FRAGMENTS 10 00038 00039 00041 xdata struct fragmentEntry { 00042 unsigned long start; 00043 unsigned long length; 00044 } fragment[MAX_NUMBER_FRAGMENTS]; 00045 00047 xdata unsigned long fileSize; 00048 00050 #define MAX_NUMBER_SUBDIRECTORIES 5 00051 00053 xdata struct directoryStack { 00054 unsigned long sector; 00055 unsigned char entry; 00056 } dirStack[MAX_NUMBER_SUBDIRECTORIES]; 00057 00059 xdata unsigned char dirLevel = 0; 00060 00062 xdata unsigned long freeSector = 0; 00063 00065 xdata char currentFileName[12]; 00066 00068 bit IS_FAT_12 = 0; 00069 00070 00072 void PConvertSectorToCluster(unsigned long *sector){ 00073 *sector-=dataStart; 00074 *sector/=fatSectorsPerCluster; 00075 } 00076 00078 void PConvertClusterToSector(unsigned long *cluster){ 00079 *cluster*=fatSectorsPerCluster; 00080 *cluster+=dataStart; 00081 } 00082 00083 00085 unsigned long GetFatEntry(unsigned long clusterNumber){ 00086 unsigned char entryNumber; /* entry number inside page */ 00087 00088 if (!IS_FAT_32){ //FAT16 00089 entryNumber = clusterNumber & 0xff; 00090 clusterNumber >>= 8; 00091 }else{ //FAT32 00092 entryNumber = clusterNumber & 0x7f; 00093 clusterNumber >>= 7; 00094 } 00095 clusterNumber += fatStart; 00096 if (sectorAddress.l != clusterNumber){ 00097 sectorAddress.l = clusterNumber; 00098 ReadDiskSector(sectorAddress.l); 00099 } 00100 if (IS_FAT_32){ 00101 clusterNumber=diskSect.Fat32Table[entryNumber]; 00102 return clusterNumber; 00103 } 00104 if ((clusterNumber=diskSect.Fat16Table[entryNumber])==0xffff) return 0xffffffff; 00105 return clusterNumber; 00106 } 00107 00108 00109 00110 00129 void WriteClusterChain(){ 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 } 00242 00243 00244 00245 00248 unsigned char ScanForFreeSector(){ 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 } 00294 00295 00303 unsigned long GetNextSector(unsigned long currentSector){ 00304 addressType fatSector; 00305 unsigned char entryNumber; 00306 00307 /* how manyth sector from start of data area -> fatsector */ 00308 fatSector.l = currentSector - dataStart; 00309 00310 /* Check for cluster boundary */ 00311 /* if we're not in cluster boundary then return currentsector + 1 */ 00312 if ((fatSector.b.b0 + 1) % fatSectorsPerCluster){ 00313 return currentSector + 1; 00314 } 00315 00316 /* is the value negative? then return currentSector + 1 */ 00317 if (fatSector.b.b3 & 0x80) { 00318 return currentSector + 1; 00319 } 00320 00321 /* The trivial conditions are not met, we actually do need to 00322 look up the next sector info from FAT tables in the disk.*/ 00323 00324 /* convert fatSector from CurrentSectorN to currentClusterN */ 00325 fatSector.l /= fatSectorsPerCluster; 00326 00327 /* calculate which page (fatSector) and entry of FAT table correspond 00328 to current sector */ 00329 00330 if (!IS_FAT_32){ //FAT16 00331 entryNumber = fatSector.b.b0; /* 256 entries / page in FAT16 table */ 00332 fatSector.l >>= 8; /* Divide by 256 (n of entries/page in FAT32 table */ 00333 }else{ //FAT32 00334 entryNumber =(fatSector.b.b0 & 0x7f); /* 128 entries/page in FAT32 tbl */ 00335 fatSector.l >>= 7; /* Divide by 128 (n of entries/sector in FAT32 table */ 00336 } 00337 00338 /* Get sector address for the needed page */ 00339 fatSector.l += fatStart; 00340 00341 /* Load (if needed) table page from disk */ 00342 if (sectorAddress.l != fatSector.l){ 00343 sectorAddress.l = fatSector.l; /* (not needed because mmc.c does this) */ 00344 ReadDiskSector(fatSector.l); 00345 00346 ConsolePutChar('n'); 00347 00348 00349 } 00350 /* Now there should be correct FAT entry page in memory... */ 00351 00352 if (!IS_FAT_32){ //FAT16 00353 fatSector.l = diskSect.Fat16Table[entryNumber]; 00354 /* Check for FAT16 end-of-file condition */ 00355 if ((fatSector.b.b1 == 0xff) && (fatSector.b.b0 == 0xff)){ 00356 /* End of file */ 00357 fatSector.b.b3 = 0xff; /* return a large value (fat32 compatible) */ 00358 return fatSector.l; 00359 } 00360 }else{ //FAT32 00361 fatSector.l = diskSect.Fat32Table[entryNumber] & 0x0fffffff; 00362 /* Check for FAT32 end-of-file condition */ 00363 if ((fatSector.b.b3&0x08) //Quick test 00364 && (fatSector.l>0x0ffffff0)){ //Complete test 00365 /* End of file */ 00366 return 0xffffffff; /* return EOF*/ 00367 } 00368 } 00369 00370 00371 /* now fatSector.l contains the proper next cluster value */ 00372 00373 fatSector.l *= fatSectorsPerCluster; 00374 /* now fatSector.l contains the next sector value */ 00375 00376 fatSector.l += dataStart; 00377 /* now fatSector.l contains the proper absolute sector address */ 00378 00379 return fatSector.l; 00380 } 00381 00382 00401 Public unsigned char BuildFragmentTable(){ 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 } 00537 00538 00539 00541 unsigned char LoadNextSector(){ 00542 sectorAddress.l = GetNextSector(sectorAddress.l); 00543 if (sectorAddress.b.b1 & 0x80){ 00545 return 0x0d; /*EOF*/ 00546 } 00547 if (ReadDiskSector(sectorAddress.l)){ 00548 return 0x0d; /*EOF*/ 00549 } 00550 return 0; /* All OK return */ 00551 } 00552 00561 Public unsigned char FGetChar(){ 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 } 00586 00587 00588 00610 Public unsigned char OpenFile(unsigned int fileNumber){ 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 } 00804 00805 00806 00809 unsigned char FatInitGlobals(){ 00810 00811 ConsoleWrite("Formatter signature:"); 00812 for (temp.c=0; temp.c<8; temp.c++){ 00813 ConsolePutChar(diskSect.fat.BS_OEMName[temp.c]); 00814 } 00815 ConsoleWrite("\rBytes per sector: "); 00816 ConsolePutUInt(diskSect.fat.BPB_BytsPerSec); 00817 ConsoleWrite("\rSectors per Cluster: "); 00818 ConsolePutUInt(diskSect.fat.BPB_SecPerClus); 00819 ConsoleWrite("\rReserved sectors: "); 00820 ConsolePutUInt(diskSect.fat.BPB_RsvdSecCnt); 00821 ConsoleWrite("\rNumber of FATs: "); 00822 ConsolePutUInt(diskSect.fat.BPB_NumFATs); 00823 ConsoleWrite("\rRoot entries: "); 00824 ConsolePutUInt(diskSect.fat.BPB_RootEntCnt); 00825 ConsoleWrite("\rTotal Sectors 16: "); 00826 ConsolePutUInt(diskSect.fat.BPB_TotSec16); 00827 ConsoleWrite("\rFat Size 16: "); 00828 ConsolePutUInt(diskSect.fat.BPB_FATSz16); 00829 ConsoleWrite("\rHidden Sectors: "); 00830 ConsolePutUInt(diskSect.fat.BPB_HiddSec); 00831 ConsoleWrite("\rTotal Sectors 32: "); 00832 ConsolePutUInt(diskSect.fat.BPB_TotSec32); 00833 00834 00835 00836 /* Determine FAT Type (16/32) */ 00837 /* This should be done better, but it'll do for now. */ 00838 IS_FAT_32 = 1; 00839 if (diskSect.fat.BPB_RootEntCnt) 00840 IS_FAT_32 = 0; /* FAT32 does not have separate root entries. */ 00841 00842 ConsoleWrite("\rFile system is "); 00843 if (IS_FAT_32){ 00844 ConsoleWrite("FAT32"); 00845 } else { 00846 ConsoleWrite("FAT16"); 00847 } 00848 00849 ConsoleWrite("\rFile system signature is "); 00850 for (temp.c=0;temp. c<8; temp.c++) 00851 if (IS_FAT_32){ 00852 ConsolePutChar(diskSect.fat.ext._32.BS_FilSysType[temp.c]); 00853 } else { 00854 ConsolePutChar(diskSect.fat.ext._16.BS_FilSysType[temp.c]); 00855 } 00856 00857 if (!IS_FAT_32){ 00858 if (diskSect.fat.ext._16.BS_FilSysType[4]=='2'){ 00859 IS_FAT_12 = 1; 00860 ConsoleWrite("Well, actually it's FAT12 filesystem.\r"); 00861 } 00862 } 00863 00864 00865 ConsoleWrite("\rVolume Label is "); 00866 for (temp.c=0; temp.c<11; temp.c++) 00867 if (IS_FAT_32){ 00868 ConsolePutChar(diskSect.fat.ext._32.BS_VolLab[temp.c]); 00869 } else { 00870 ConsolePutChar(diskSect.fat.ext._16.BS_VolLab[temp.c]); 00871 } 00872 /* OK, let's calculate */ 00873 /* First, let's get rid of the idea that we have byte addresses 00874 in the file system. Nope, let's only deal in physical disk 00875 sectors of 512 bytes. First we convert the FAT byter per sector 00876 value to "512B disk sectors per fat sector" value. */ 00877 00878 diskSect.fat.BPB_BytsPerSec /= 512; 00879 00880 /* Then we adjust the Sector per Cluster to mean physical disk 00881 sectors. in 99% of the cases it is already so because bytes 00882 per sector almost always is 512 in FAT. Maximum cluster size 00883 is 65536 bytes (128 disk sectors). */ 00884 00885 fatSectorsPerCluster = 00886 diskSect.fat.BPB_SecPerClus *= diskSect.fat.BPB_BytsPerSec; 00887 /* Note: BPB_BytsPerSec has already been divided by 512 */ 00888 00889 ConsoleWrite("\rSectors per Cluster: "); 00890 ConsolePutUInt(fatSectorsPerCluster); 00891 00892 fatStart = (unsigned long)sectorAddress.l 00893 + (unsigned long)diskSect.fat.BPB_RsvdSecCnt 00894 * (unsigned long)diskSect.fat.BPB_BytsPerSec; 00895 00896 ConsoleWrite("\rFAT Start sector: "); 00897 ConsolePutUInt(fatStart); 00898 00899 rootStart = diskSect.fat.BPB_FATSz16; 00900 if (rootStart==0){ 00901 if (!IS_FAT_32) 00902 return 0x0b; /* should be FAT32; can not find root directory */ 00903 rootStart = diskSect.fat.ext._32.BPB_FATSz32; 00904 } 00905 rootStart *= diskSect.fat.BPB_NumFATs; 00906 rootStart *= diskSect.fat.BPB_BytsPerSec; /* ADJUSTED BytsPerSec! */ 00907 rootStart += fatStart; 00908 00909 ConsoleWrite("\rRoot start sector: "); 00910 ConsolePutUInt(rootStart); 00911 00912 dataStart = diskSect.fat.BPB_RootEntCnt >> 4; 00913 dataStart += rootStart; 00914 dataStart -= (fatSectorsPerCluster*2); /*first cluster is cluster 2*/ 00915 00916 ConsoleWrite("\rData start sector: "); 00917 ConsolePutUInt(dataStart); 00918 ConsolePutChar(13); 00919 00920 return 0; 00921 } 00922 00926 Public unsigned char InitFileSystem(){ 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 } 01017 01018 01019 01020 01021

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