⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filesys.c

📁 MP3 Player Source Code
💻 C
📖 第 1 页 / 共 2 页
字号:
/** \file filesys.c * File system functions, Implemented: FAT16, FAT32. */#include "board.h"#include "filesys.h"#include "storage.h"#include "console.h"#include "mmc.h"/* This needs display to put file name directly to display buffer *//* It's not pretty but it saves a lot of memory! */#include "display.h"/** Starting sector of FAT table. */    data  unsigned long fatStart;/** Starting sector of root directory */data unsigned long rootStart;/** Sector of (unexistent) data cluster 0. *//** (In FAT the start is cluster 2, so dataStart actually ** points to 2 clusters before the start of data area) */data unsigned long dataStart;/** FAT Global sectors per cluster */data unsigned char fatSectorsPerCluster;/** Maximum allowable number of fragments in file */#define MAX_NUMBER_FRAGMENTS 10/** Fragment Table. Maximum fragment size is (4G-1 sectors) */xdata struct fragmentEntry {  unsigned long start; /**< Starting sector of fragment */  unsigned long length; /**< Length of fragment in sectors */} fragment[MAX_NUMBER_FRAGMENTS];/** Size of current file to play */xdata unsigned long fileSize;/** Maximum number of nested subdirectories */#define MAX_NUMBER_SUBDIRECTORIES 5/** Directory traversing structure */xdata struct directoryStack {  unsigned long sector; /**< Directory table sector in disk */  unsigned char entry;  /**< Entry number (0..15) */} dirStack[MAX_NUMBER_SUBDIRECTORIES];/** Current directory level, 0=Root directory */xdata unsigned char dirLevel = 0;/** Next free cluster number */xdata unsigned long freeSector = 0;/** Current file name */xdata char currentFileName[12];/** Set if this is a FAT12 filesystem */bit IS_FAT_12 = 0;/** Convert sector number to cluster number */void PConvertSectorToCluster(unsigned long *sector){  *sector-=dataStart;  *sector/=fatSectorsPerCluster;}/** Convert cluster number to sector number */void PConvertClusterToSector(unsigned long *cluster){  *cluster*=fatSectorsPerCluster;  *cluster+=dataStart;}/** Return the FAT entry for cluster clusterNumber */unsigned long GetFatEntry(unsigned long clusterNumber){  unsigned char entryNumber; /* entry number inside page */  if (!IS_FAT_32){ //FAT16    entryNumber = clusterNumber & 0xff;     clusterNumber >>= 8;   }else{ //FAT32    entryNumber = clusterNumber & 0x7f;    clusterNumber >>= 7;   }  clusterNumber += fatStart;  if (sectorAddress.l != clusterNumber){    sectorAddress.l = clusterNumber;    ReadDiskSector(sectorAddress.l);  }  if (IS_FAT_32){    clusterNumber=diskSect.Fat32Table[entryNumber];    return clusterNumber;  }  if ((clusterNumber=diskSect.Fat16Table[entryNumber])==0xffff) return 0xffffffff;  return clusterNumber;}/** 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].*/void WriteClusterChain(){  xdata unsigned long currentCluster;    //is now fragment[0].start  xdata unsigned long fragSize;          //is now fragment[0].length  xdata unsigned long fatPageSector;  xdata unsigned char entryNumber;     // PREPARE  // Calculate starting cluster number...  currentCluster = fragment[0].start;  PConvertSectorToCluster(&currentCluster);    fragSize = fragment[0].length;         //size in sectors  // Write cluster number and size in bytes to fragment[0]  // for the function that registers directory entries  fragment[0].start = currentCluster;  fragment[0].length *= 512;  // Locate the relevant page in FAT clusterchain records  fatPageSector = currentCluster;  if (!IS_FAT_32){ //FAT16    entryNumber = fatPageSector & 0xff;     fatPageSector >>= 8;   }else{ //FAT32    entryNumber = fatPageSector & 0x7f;    fatPageSector >>= 7;   }  fatPageSector += fatStart;       ConsoleWrite("Writing clusterchain from: "); ConsolePutUInt(currentCluster);  ConsoleWrite("Fragment size (sectors): "); ConsolePutUInt(fragSize);  ConsoleWrite("FatPageSector: "); ConsolePutUInt(fatPageSector);  ConsoleWrite("EntryNumber: "); ConsolePutUInt(entryNumber);    // WRITE CLUSTER CHAIN TO FIRST FAT  while (fragSize>fatSectorsPerCluster){     // while more than 1 cluster left...    // is the FAT clusterchain page changed?    if (sectorAddress.l != fatPageSector){      // Yes, have we advanced by 1 sector?      if (sectorAddress.l == (fatPageSector - 1)){	//Yes, we must save the edited sector	WriteDiskSector (sectorAddress.l);	///\todo update second FAT too	        }      // at least we need to load the new clusterchain page      sectorAddress.l = fatPageSector;      ReadDiskSector(sectorAddress.l);    }//Load/Save FAT sector        // Register Middle Entry    currentCluster++; //advancce to next cluster        //fragSize-=fatSectorsPerCluster; //we will register one cluster    //to avoid memory spill in C compiler, the preceding line is written as:    for (temp.c = fatSectorsPerCluster;temp.c;temp.c--){      fragSize--;    }       if (IS_FAT_32){      diskSect.Fat32Table[entryNumber]=currentCluster;    }else{      diskSect.Fat16Table[entryNumber]=(currentCluster&0xffff);    }          // Calculate next entry position in FAT records    fatPageSector = currentCluster;    if (!IS_FAT_32){ //FAT16      entryNumber = fatPageSector & 0xff;       fatPageSector >>= 8;     }else{ //FAT32      entryNumber = fatPageSector & 0x7f;      fatPageSector >>= 7;     }    fatPageSector += fatStart;  }//while  // WRITE THE FINAL ENTRY TO FAT CLUSTERCHAIN  // is the FAT clusterchain page changed?  if (sectorAddress.l != fatPageSector){    // Yes, have we advanced by 1 sector?    if (sectorAddress.l == (fatPageSector - 1)){      //Yes, we must save the edited sector      WriteDiskSector (sectorAddress.l);      ///\todo update second FAT too	  	}    // at least we need to load the new clusterchain page    sectorAddress.l = fatPageSector;    ReadDiskSector(sectorAddress.l);  }//Load/Save FAT sector    //Write the Last entry  if (IS_FAT_32){    diskSect.Fat32Table[entryNumber]=fragment[1].start;  }else{    diskSect.Fat16Table[entryNumber]=(fragment[1].start & 0xffff);  }      WriteDiskSector(sectorAddress.l); //Write last sector      OpenFile(0); //Register FAT entry}/** Search for next free sector. * If freeSector is zero, a new file should be allocated. */    unsigned char ScanForFreeSector(){  //ConsoleWrite("\rLooking for free space starting from ");  if ((freeSector) && (freeSector-dataStart+1)%fatSectorsPerCluster){    //Still room in current cluster...    freeSector++;    //ConsoleWrite("free at sector ");    //ConsolePutUInt(freeSector);    return 1;  }      if (freeSector){    //Advance to next sector    freeSector++;    //switch from using sectors to using clusters    PConvertSectorToCluster(&freeSector);  }else{    freeSector=3; //starting cluster entry (should be 2?)  }  //scan until free entry is found  //freeSector actually counts clusters here.  while(GetFatEntry(freeSector)){        freeSector++;  }  ConsoleWrite("F");  ConsolePutUInt(freeSector);    //while (!KEY_BUTTON);  //ConsoleWrite("free at cluster ");  //ConsolePutUInt(freeSector);  //switch back from using clusters to using sectors.  PConvertClusterToSector(&freeSector);  //ConsoleWrite("sector ");  //ConsolePutUInt(freeSector);  return 1;}/** Calculate next sector from currentSector. *  Return sector address with MSB set if end of file.  * * This is the essence of FAT filesystem: traversing through * the file allocation table to scan for cluster chains.*/unsigned long GetNextSector(unsigned long currentSector){  addressType fatSector;  unsigned char entryNumber;    /* how manyth sector from start of data area -> fatsector */  fatSector.l = currentSector - dataStart;    /* Check for cluster boundary */  /* if we're not in cluster boundary then return currentsector + 1 */  if ((fatSector.b.b0 + 1) % fatSectorsPerCluster){    return currentSector + 1;  }    /* is the value negative? then return currentSector + 1 */  if (fatSector.b.b3 & 0x80) {    return currentSector + 1;  }      /* The trivial conditions are not met, we actually do need to      look up the next sector info from FAT tables in the disk.*/  /* convert fatSector from CurrentSectorN to currentClusterN */  fatSector.l /= fatSectorsPerCluster;  /* calculate which page (fatSector) and entry of FAT table correspond     to current sector */     if (!IS_FAT_32){ //FAT16    entryNumber = fatSector.b.b0; /* 256 entries / page in FAT16 table */    fatSector.l >>= 8; /* Divide by 256 (n of entries/page in FAT32 table */  }else{ //FAT32    entryNumber =(fatSector.b.b0 & 0x7f); /* 128 entries/page in FAT32 tbl */    fatSector.l >>= 7; /* Divide by 128 (n of entries/sector in FAT32 table */  }    /* Get sector address for the needed page */  fatSector.l += fatStart;    /* Load (if needed) table page from disk */  if (sectorAddress.l != fatSector.l){    sectorAddress.l = fatSector.l; /* (not needed because mmc.c does this) */    ReadDiskSector(fatSector.l);        ConsolePutChar('n');          }  /* Now there should be correct FAT entry page in memory... */    if (!IS_FAT_32){ //FAT16    fatSector.l = diskSect.Fat16Table[entryNumber];    /* Check for FAT16 end-of-file condition */    if ((fatSector.b.b1 == 0xff) && (fatSector.b.b0 == 0xff)){      /* End of file */      fatSector.b.b3 = 0xff; /* return a large value (fat32 compatible) */      return fatSector.l;    }  }else{ //FAT32    fatSector.l = diskSect.Fat32Table[entryNumber] & 0x0fffffff;    /* Check for FAT32 end-of-file condition */    if ((fatSector.b.b3&0x08) //Quick test	&& (fatSector.l>0x0ffffff0)){ //Complete test      /* End of file */      return 0xffffffff; /* return EOF*/    }  }    /* now fatSector.l contains the proper next cluster value */  fatSector.l *= fatSectorsPerCluster;  /* now fatSector.l contains the next sector value */  fatSector.l += dataStart;  /* now fatSector.l contains the proper absolute sector address */  return fatSector.l;}/** 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... */Public unsigned char BuildFragmentTable(){  unsigned char c=0;  addressType this,next;  addressType fatSector;  unsigned char entryNumber;  if (IS_FAT_12){    ConsoleWrite("Single fragment support for FAT12");    fragment[0].start = sectorAddress.l;    fragment[0].length = fileSize/512;    return(1); //Return 1 fragment  }  //as long as the sectorAddress is "sane"...  while (!(sectorAddress.b.b3 & 0x80)){            fragment[c].start = sectorAddress.l;    fragment[c].length = fatSectorsPerCluster;        /* Find cluster entry for the current sector */        /* in how manyth sector from start of data area are we? ->this */    this.l = sectorAddress.l - dataStart;    /* convert from CurrentSectorN to currentClusterN */    this.l /= fatSectorsPerCluster;    /* this.l is now the current cluster number */            /* now let's find the FAT entry for this.l cluster */    if (!IS_FAT_32){ //FAT16      entryNumber = this.b.b0; /* 256 entries / page in FAT16 table */      fatSector.l = this.l >> 8; /* Div by n of entries/page in FAT16 tbl*/    }else{ //FAT32      entryNumber = (this.b.b0 & 0x7f); /* 128 entries/page in FAT32 table */      fatSector.l = this.l >> 7; /* Div by n of entries/page in FAT32 tbl*/    }    fatSector.l += fatStart;    /* fatSector.l is now the DISK SECTOR NUMBER CONTAINING THE FAT table */    /* read this page into memory */    ReadDiskSector(fatSector.l);            if (!IS_FAT_32){ //FAT16      next.l = diskSect.Fat16Table[entryNumber]; /* get next cluster n */      /* Check for FAT16 end-of-file condition */      if ((next.b.b1 == 0xff) && (next.b.b0 == 0xff)){	/* FAT16 End of file */	next.b.b3 = 0xff; /* return a large value (fat32 compatible) */      }    }else{ //FAT32      next.l = diskSect.Fat32Table[entryNumber]&0x0fffffff;    }    /* next.l is the FAT entry (next cluster number) */            ConsoleWrite("\rFragment start: cluster ");    ConsolePutUInt(this.l);    ConsoleWrite("sector ");    ConsolePutUInt(fragment[c].start);    while (next.l==(this.l+1)){      //Not a fragment break -- continue to next entry       //in this temp.l is used only to allow compiler memory spilling to temp      temp.l = fragment[c].length;      temp.l += fatSectorsPerCluster;      fragment[c].length = temp.l;      entryNumber++;      // --- Check for a page break      if (entryNumber==0){ //entryNumber has rolled over!!!! (8bit char)	//FAT16 table page border is reached	fatSector.l++; //Advance to next page;	entryNumber=0;	ReadDiskSector(fatSector.l);      }      if (IS_FAT_32 && (entryNumber==128)){	//FAT32 table page border is reached	fatSector.l++;	entryNumber=0;	ReadDiskSector(fatSector.l);      }            // --- Advance to next cluster      this.l = next.l;            if (!IS_FAT_32){	//FAT16 get next cluster n	next.l = diskSect.Fat16Table[entryNumber];       	if ((next.b.b1==0xff)&&(next.b.b0==0xff)){	  //FAT16 end-of-file	  next.b.b3 = 0xff; //mark end-of-file (FAT32 compatible)	}      }else{	//FAT32 get next cluster n	next.l = diskSect.Fat32Table[entryNumber];      }    }//This repeats until there is a discontinuity        /* next.l now has the cluster entry for last cluster in fragment       it has a high value if eof (see FAT spec) */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -