?? zfat.c
字號:
#include "zfat.h"
//Following includes aren't required if using CodeVision AVR C
//CodeVision will include automatically if .H files are in project list.
//#include "ztype.h"
//#inlcude "zata.h"
//#inlcude "zlcd.h"
//#include "zcontrol.h"
unsigned long clust2LBA(unsigned long clust) {
//Convert cluster address to LBA address, uses the formula 將簇地址轉換為lba地址 使用下面的公式
return ((clust-2) * Sectors_Per_Cluster) + FirstDataSector;
}
/*
unsigned long LBA2Cluster(unsigned long LBA) {
return ((LBA-FirstDataSector)/Sectors_Per_Cluster)+2; 將lba地址轉換為簇地址
}
*/
void InitFAT(){
struct partRec *pr; 指向分區表的指針
struct bootSec710 *boot; 指向啟動扇區 ????????
struct driveID *driveInfo; 指向硬盤id結構
word rootDirSectors;
struct FAT32fsInfo *fsInfo; ??????????
dword tartSector;
dword FATSz, dataSec, totalSector;
byte i;
RegWrite(DrvHeadReg,LBAMaster); 表示大硬盤模式
RegWrite(CmdStsReg,0xEC); //ATA identify command. ata識別命令 也就是讀出ata的信息
while ((RegRead(CmdStsReg) & SR_DRQ)!=SR_DRQ); //no error handling 沒有錯誤
WriteAddr(IOReg);
ATA_Read(128);讀出128*2個字節
driveInfo = (struct driveID *) sectorBuffer.data; 得到硬盤信息
LCDclrscr();
for (i=0; i<20; i+=2) 將讀出的數據進行解析
{writechar(driveInfo->model[i+1]);//顯示部分
writechar(driveInfo->model[i]); }; //顯示部分
//Determine drive size. Multiplication and division is done by shifts
startSector = driveInfo->totalSecHi;
startSector = ((startSector<<16) + driveInfo->totalSecLo)>>11;
gotoxy(1,0);
writeNumber(startSector); //Display drive size
writestring("MB ");
//skipping boot code in first 445 bytes. So go to offset 446
GoToSectorOffset(0,446);
ATA_Read_Sectors_LBA(0, 32); //reading 64 byte partition records of 4 partition
readPos=0; //New sector needs to be read
sectorPos=0;
pr = (struct partRec *) sectorBuffer.data;
startSector = pr->startLBA;
ATA_Read_Sectors_LBA(startSector, 64); //Go to start sector of the partition
boot = (struct bootSec710 *) sectorBuffer.data; //Load BPB struct pointer
//All of the following calculations are from Microsoft FAT32 White Paper
Sectors_Per_Cluster = boot->BPB.secPerClust;
Bytes_Per_Sector = boot->BPB.bytesPerSec;
FirstFATSector = boot->BPB.resSectors + startSector;
rootDirSectors=(((boot->BPB.rootDirEnts * 32)+ (Bytes_Per_Sector - 1)) / Bytes_Per_Sector);
FATSz = boot->BPB.FATSz16;
if (FATSz==0) FATSz = boot->BPB.FATSz32;
if (boot->BPB.totSec16 != 0) totalSector=boot->BPB.totSec16;
else totalSector=boot->BPB.totSec32;
dataSec = totalSector - (boot->BPB.resSectors + (boot->BPB.FATs * FATSz) + rootDirSectors);
FirstDataSector = boot->BPB.resSectors + (boot->BPB.FATs * FATSz) + rootDirSectors + startSector;
if ((dataSec / Sectors_Per_Cluster) < 65525) {
Halt(3); //System is FAT16, not supported in this version.
}
else {
FirstDirSector = boot->BPB.rootClust;
writestring("FAT32");//FATType=32;
}
GoToSectorOffset(startSector+1,484); //Goto offset 484 of FSInfo sector (2nd sector)
ATA_Read(28);
fsInfo= (struct FAT32fsInfo *) sectorBuffer.data;
DriveSize=fsInfo->freeCluster; //driveSize in # of cluster
//Next freeCluster address changes everytime new file added or removed
//Thus ZipAmp will see that user modified total files in drive, so
//re-count of all files are needed.
gotoxy(2,0);
writeNumber((DriveSize*Sectors_Per_Cluster)>>11); //Display approx. free space in MB
writestring("MB Free"); //Right shift of 11 is found from equation given below
//Display will give wrong value if free space > 65GB
//Because writeNumber function expects word value.
//DriveSize is in # of cluster
//size = (DriveSize * Sectors_Per_Cluster * Bytes_Per_Sector / (1024 * 1024)) MB
//Assume Bytes_Per_Sector = 512,
//Therefore, operation of ( 512 / ( 1024 * 1024) ) = Right shift of 11
}
unsigned char getDirEntry(byte onlyMP3){
//gets a filename.ext, filesize, and start cluster of that file from the directory entry table.
//Returns 1 if file is found, returns 0 if no file found and reaches end of dir table.
//Finds only MP3 files and enters sub-directory if onlyMP3 is set, if its 0 then only reads root dir.
//Each file record in dir is 32 byte long.
unsigned long cluster;
word fileNum=0;
dword extension;
byte i,j,start,longNameFound;
struct direntry *file;
struct winentry *longFile;
readPos=0;
if ((currentFileNum & dirReadOffset.fileNum) ==0) { //if reading from start of root dir
cluster=FirstDirSector;
sectorPos=0;
subDirLevel=0;
dirString[0]=2;
dirString[1]='/';
}
else {
cluster=dirReadOffset.cluster; //Start from last read cluster position.
sectorPos=dirReadOffset.sectorPos; //Last read sectorPos
fileNum=dirReadOffset.fileNum; //Last read file number
//Find the previous file record read offset in the cluster
GoToSectorOffset(clust2LBA(cluster)+sectorPos,dirReadOffset.offset);
}
CLEAR: //Jump position if an entry was invalid entry, clear fileName
for (i=0; i<40; i++) fileName[i]=0; //Clear file name so all position is NULL.
extension=0;
longNameFound=0;
do { //Directory read loop (infinite, unless a file found or reached end of directory)
ATA_Read_Sectors_LBA(clust2LBA(cluster)+sectorPos, 16); //reading 32 byte in each iteration
if (sectorPos==Sectors_Per_Cluster) {
currentCluster=cluster;
cluster=findNextCluster();
sectorPos=0; readPos=0;
}
longFile=(struct winentry *) sectorBuffer.data; //Initialize pointer for long file name structure
file = (struct direntry *) sectorBuffer.data; //Initialize pointer for short file name structure
if (sectorBuffer.data[0] == 0xE5) {
//Deleted entry
goto CLEAR;
}
//------------------------------------------------------------------------------
/*End of a directory block */
if (sectorBuffer.data[0] == 0) { //We reached end of a dir
if (subDirLevel>0) { //Check if this end of a sub-dir, if true then go to one level up directory
subDirLevel--;
popDir(); //pop cluster address from stackfile to currentCluster
cluster=currentCluster; //set dir cluster to popped cluster
GoToSectorOffset(clust2LBA(cluster)+sectorPos,readPos); //go to dir file entry offset
//Remove subdir text in dir string
j=dirString[0]-2;
while ((j>1)&&(dirString[j]!='/')) j--;
dirString[0]=j+1;
goto CLEAR;
}
//If we are here then we reached end of root directory.
currentFileNum=0;
return 0; //Done. Finished reading all entries so return 0
}
//-------------------------------------------------------------------------------
/* Active long name sub-component block. */
if ((longFile->Attr & ATTR_LONG_NAME_MASK) == ATTR_LONG_NAME) {
start = 13 *( (longFile->Cnt-1) & 0x0F); //Fine offset of text in long file name
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -