|
/************************************************************************ * File : fat32_base.c * Processor : ADSP-BF533 * IDDE : VisualDSP++3.5 * Description : FAT driver functions which is mainly cluster-based operation, includes: * * Wait_Ready(); * Wait_ReadyBusy(); * CheckforError(); * IdeStandby(); * IdeIdle(); * *************************************************************************/
#include "FAT/filesystem.h" #include "FAT/fat32.h" #include "IDE/ide_access.h" #include "IDE/ide_base.h" #include "type.h"
#define FAT_BUFFER_SIZE 1048576 //1M #define FAT_GROUP_NUM_M 3 //2^3=8 #define FAT_GROUP_SIZE_M 17 //2^17= 128K #define FAT_GROUP_DWORD_SIZE_M FAT_GROUP_SIZE_M-2 #define FAT_GROUP_SECTOR_NUM (1<<(FAT_GROUP_DWORD_SIZE_M-7)) #define FAT_GROUP_NUM (1<<FAT_GROUP_NUM_M) #define FAT_GROUP_SIZE (1<<FAT_GROUP_SIZE_M)
#pragma align 4 section("sdram0") BYTE fat_chain[FAT_GROUP_NUM][FAT_GROUP_SIZE];
BYTE fat_group_index[FAT_GROUP_NUM]={ 0, 0, 0, 0, 0, 0, 0, 0}; BYTE next_fat_group=1;
FS_t *current_fs; extern unsigned int cycles[100];
/****************************************************************** * Function : fnFAT32_LBAofCluster * Description : get cluster number and LBA of start sector in the cluster * Input : DWORD Cluster_Number-cluster number * Output : DWORD LBA of start sector in the cluster *******************************************************************/
DWORD fnFAT32_LBAofCluster(DWORD Cluster_Number) { return ((current_fs->cluster_begin_lba + ((Cluster_Number-2)*current_fs->bpb.sector_per_cluster))); }
/****************************************************************** * Function : fnFATChainInit * Description : cluster chain initialization-read fist 128K FAT data to FAT buffer in SDRAM * Input : none * Output : none *******************************************************************/
void fnFATChainInit() { BYTE i,j; BUFFER *fat_sector; fat_sector = (BUFFER *)(fat_chain[0]); // Read the first 256 sectors to SDRAM fnIDE_BufferSector(fat_sector,partition_table[0]->fs->fat_begin_lba,FAT_GROUP_SECTOR_NUM); }
/****************************************************************** * Function : fnFAT32_init * Description : FAT32 partition initialization-get FAT32 partition information * Input : * FS_t *fs - pointer to structure which store FAT partition information * DWORD offest_sector - starting sector of FAT partition table * Output : none *******************************************************************/ void fnFAT32_init(FS_t *fs,DWORD offset_sector) { fnIDE_BufferSector(&buffers,offset_sector,1); // read DBR
// Load Parameters of FAT32 fs->bpb.byte_per_sector = fnIDE_SectorWord(BYTE_PER_SECTOR); fs->bpb.sector_per_cluster = fnIDE_SectorByte(SECTOR_PER_CLUSTER); fs->bpb.reserve_sector = fnIDE_SectorWord(RESERVE_SECTOR); fs->bpb.FATnum = fnIDE_SectorByte(FAT_NUM); fs->bpb.root_entrice = fnIDE_SectorWord(ROOT_ENTRICE); fs->bpb.media_descriptor = fnIDE_SectorByte(MEDIA_DESCRIPTOR); fs->bpb.sector_per_track = fnIDE_SectorWord(SECTOR_PER_TRACK); fs->bpb.head_num= fnIDE_SectorWord(HEAD_NUM); fs->bpb.hide_sector= fnIDE_SectorDWORD(HIDE_SECTOR); fs->bpb.sector_num= fnIDE_SectorDWORD(LARGE_SECTOR); fs->bpb.sector_per_FAT= fnIDE_SectorDWORD(SECTOR_PER_FAT_4); fs->bpb.flag= fnIDE_SectorWord(EXT_FLAG); fs->bpb.root_cluster= fnIDE_SectorDWORD(ROOT_CLUSTER); fs->bpb.FSinfo_sector= fnIDE_SectorDWORD(FSINFO_SECTOR); fs->bpb.backup_sector= fnIDE_SectorWord(BACKUP_SECTOR); fs->byte_per_cluster= fs->bpb.byte_per_sector*fs->bpb.sector_per_cluster; fs->fat_begin_lba = offset_sector + fs->bpb.reserve_sector; fs->cluster_begin_lba = fs->fat_begin_lba + (fs->bpb.FATnum * fs->bpb.sector_per_FAT);
fs->fs_type= FS_TYPE_FAT32; fs->total_cluster=fs->bpb.sector_num/fs->bpb.sector_per_cluster; fnFATChainInit();
if (fnIDE_SectorWord(0x1FE)!=0xAA55) //check ending - 0xAA55 in DBR { printf("\r\nError: Incorrect Volume Signature"); while(1); } }
/****************************************************************** * Function : fnFAT32_FindNextCluster * Description : find next cluster (according to current cluster in cluster chain). Finding steps: * 1, find next cluster in FAT buffer in SDRAM (128K) * 2, read another 128K FAT data from HD and write to FAT buffer to SDRAM if find nothing in step1 * 3, repeat step 1 * Input : * DWORD current_cluster - current cluster number * Output : next cluster number *******************************************************************/
DWORD fnFAT32_FindNextCluster(DWORD current_cluster) { BYTE i; DWORD FAT_group_offset, UI32position; DWORD nextcluster; DWORD *cluster_buffer; DWORD sector_offset;
if(current_cluster>current_fs->total_cluster) return 0xFFFFFFFF;
// find image of current cluster in FAT table FAT_group_offset = current_cluster>>FAT_GROUP_DWORD_SIZE_M; UI32position = (current_cluster - (FAT_group_offset <<FAT_GROUP_DWORD_SIZE_M)) ;
//step 1 - begin searching next cluster in SDRAM for(i=0;i<FAT_GROUP_NUM;i++) { if(FAT_group_offset==fat_group_index[i]) { cluster_buffer=(DWORD *)(fat_chain[i]); nextcluster = cluster_buffer[UI32position]; if((nextcluster&0x0FFFFFFF)==0x0FFFFFFF) { return 0xFFFFFFFF; } else { return nextcluster; } } }
//step 2 - read 128kB FAT table data(including current cluster) from HD and write to SDRAM sector_offset = (FAT_group_offset<<FAT_GROUP_SIZE_M)/current_fs->bpb.byte_per_sector; cluster_buffer = (DWORD*)(fat_chain[next_fat_group]); fnIDE_BufferSector(cluster_buffer,current_fs->fat_begin_lba+sector_offset,FAT_GROUP_SECTOR_NUM); fat_group_index[next_fat_group]=FAT_group_offset; next_fat_group= next_fat_group +1 ; if(next_fat_group==FAT_GROUP_NUM) { next_fat_group=1; } nextcluster = cluster_buffer[UI32position]; if((nextcluster&0x0FFFFFFF)==0x0FFFFFFF) { return 0xFFFFFFFF; } else { return nextcluster; } }
/****************************************************************** * Function : fnFAT32_SectorReader * Description : read target sector( according to offset of target sector in cluster) * case 1 (normally)-target sector is in current cluster * case 2 - target sector is not in current cluster, find next cluster (according to offset) * Input : * currentcluster_t cluster - current cluster number ( do not contain the sector in case 2) * DWORD offset - offset of target sector in the cluster * Output : cluster - current cluster number *******************************************************************/ currentcluster_t fnFAT32_SectorReader(currentcluster_t cluster, DWORD offset) { DWORD SectortoRead = 0; DWORD ClustertoRead = 0; DWORD ClusterChain = 0; WORD sector_per_cluster=current_fs->bpb.sector_per_cluster; int i; if(cluster.value==0xFFFFFFFF) return cluster; ClusterChain = cluster.value;
ClustertoRead = offset / sector_per_cluster; SectortoRead = offset - (ClustertoRead*sector_per_cluster); // cast 2 -call finFAT32_FindNextCluster() to find cluster that contain target sector for (i=cluster.offset; i<ClustertoRead; i++) { ClusterChain = fnFAT32_FindNextCluster(ClusterChain); }
//register current cluster cluster.value=ClusterChain; cluster.offset=ClustertoRead; if (ClusterChain==0xFFFFFFFF) return cluster;
//read target sector fnIDE_BufferSector(&buffers,fnFAT32_LBAofCluster(ClusterChain)+SectortoRead,1);
return cluster; }
/****************************************************************** * Function : fnFAT32_WriteSector * Description : write target sector( according to offset of target sector in cluster) * case 1 (normally)-target sector is in current cluster * case 2 - target sector is not in current cluster, find next cluster (according to offset) * Input : * currentcluster_t cluster - current cluster number ( do not contain the sector in case 2) * DWORD offset - offset of target sector in the cluster * Output : cluster - current cluster number *******************************************************************/ currentcluster_t fnFAT32_WriteSector(currentcluster_t cluster, DWORD offset) { DWORD SectortoRead = 0; DWORD ClustertoRead = 0; DWORD ClusterChain = 0; int i; if(cluster.value==0xFFFFFFFF) return cluster;
ClusterChain = cluster.value;
ClustertoRead = offset / current_fs->bpb.sector_per_cluster; SectortoRead = offset - (ClustertoRead*current_fs->bpb.sector_per_cluster); // cast 2 -call finFAT32_FindNextCluster() to find cluster that contain target sector for (i=cluster.offset; i<ClustertoRead; i++) ClusterChain = fnFAT32_FindNextCluster(ClusterChain);
//register current cluster cluster.value=ClusterChain; cluster.offset=ClustertoRead; if (ClusterChain==0xFFFFFFFF) { return cluster; } //write target sector fnIDE_WriteBufferSector(&(buffers.currentsector),fnFAT32_LBAofCluster(ClusterChain)+SectortoRead,1); return cluster; }
/****************************************************************** * Function : fnFAT32_UpdateFAT * Description : Update FAT data table in HD with fat buffer data in SDRAM * write target sector( according to offset of target sector in cluster) * Input : * DWORD - Current_Cluster - cluster in buffer * Output : 1-done/ 0-fail *******************************************************************/ YTE fnFAT32_UpdateFAT(DWORD Current_Cluster) { DWORD FAT_group_num; DWORD *buffer; BYTE i; if (Current_Cluster<2||Current_Cluster>=(current_fs->bpb.sector_per_FAT*current_fs->bpb.byte_per_sector/4)) return 0;
FAT_group_num = Current_Cluster>>FAT_GROUP_DWORD_SIZE_M; // write FAT data in SDRAM to HD FAT data table( according to Current_Cluster) for(i=0;i<FAT_GROUP_NUM;i++) { if(FAT_group_num==fat_group_index[i]) { buffer=(DWORD *)(fat_chain[i]); fnIDE_WriteBufferSector(buffer,current_fs->fat_begin_lba+FAT_group_num*FAT_GROUP_SECTOR_NUM,0); fnIDE_WriteBufferSector(buffer,current_fs->fat_begin_lba+FAT_group_num*FAT_GROUP_SECTOR_NUM+current_fs->bpb.sector_per_FAT,0); return 1; } } return 0; }
/****************************************************************** * Function : fnFAT32_NextEmptyCluster * Description : search next empty cluster in FAT buffer in SDRAM and fetch another 128KB data from HD FAT data table if not. * Input : * DWORD cluster - start cluster ( not used, routine search from cluster 2) * Output : Empty cluster number *******************************************************************/ DWORD fnFAT32_NextEmptyCluster(DWORD cluster) { DWORD i,j,k; DWORD FAT_group_num=0,FAT_group_offset; DWORD sector_offset,cluster_base; DWORD FAT_group_size=FAT_GROUP_SIZE>>2; DWORD total_group=current_fs->bpb.sector_per_FAT*current_fs->bpb.byte_per_sector/FAT_GROUP_SIZE+1; DWORD * data; DWORD buffer[128]; WORD u32_per_sector = current_fs->bpb.byte_per_sector>>2;
//start searching from cluster 2 for(i=0;i<total_group;i++) { // search in FAT buffer in SDRAM for(j=0;j<FAT_GROUP_NUM;j++) { if(i==fat_group_index[j]) { data = (DWORD *)(fat_chain[i]); break; } } //update FAT buffer if find nothing if(j==FAT_GROUP_NUM) { sector_offset = (i<<FAT_GROUP_SIZE_M)/current_fs->bpb.byte_per_sector; data = (DWORD*)(fat_chain[next_fat_group]); fnFAT32_UpdateFAT(cluster); fnIDE_BufferSector(data,current_fs->fat_begin_lba+sector_offset,FAT_GROUP_SECTOR_NUM); fat_group_index[next_fat_group] = FAT_group_num; next_fat_group= next_fat_group+1; if(next_fat_group==FAT_GROUP_NUM) { next_fat_group=1; } } cluster_base=i*FAT_group_size; //DWORD for(k=0;k<FAT_group_size;k++) { if(data[k]==0x00000000) { return cluster_base+k; } } } return 0xFFFFFFFF; }
/****************************************************************** * Function : fnFAT32_EditFat * Description : Edit FAT table * Input : * DWORD Current_Cluster-target cluster number * DWORD value-edit value * Output : 1-done/ 0-fail *******************************************************************/ BYTE fnFAT32_EditFat(DWORD Current_Cluster,DWORD value) { DWORD FAT_sector_offset, UI32position; DWORD FAT_group_num,FAT_group_offset,sector_offset; BUFFER *buffer; DWORD *cluster; BYTE i; if (Current_Cluster<2||Current_Cluster>=(current_fs->bpb.sector_per_FAT*current_fs->bpb.byte_per_sector/4)) return 0;
//get offset of target cluster in FAT buffer in SDRAM FAT_group_num = Current_Cluster>>FAT_GROUP_DWORD_SIZE_M; FAT_group_offset= Current_Cluster-(FAT_group_num<<FAT_GROUP_DWORD_SIZE_M); FAT_sector_offset = FAT_group_offset / 128; UI32position = (FAT_group_offset - (FAT_sector_offset * 128)) ;
//edit target cluster in FAT buffer, update FAT table for(i=0;i<FAT_GROUP_NUM;i++) { if(FAT_group_num==fat_group_index[i]) { buffer=(BUFFER *)(fat_chain[i]+FAT_sector_offset*512); buffer->u32data[UI32position]=value; fnIDE_WriteBufferSector(buffer,current_fs->fat_begin_lba+FAT_group_num*FAT_GROUP_SECTOR_NUM+FAT_sector_offset,1); fnIDE_WriteBufferSector(buffer,current_fs->fat_begin_lba+FAT_group_num*FAT_GROUP_SECTOR_NUM+current_fs->bpb.sector_per_FAT+FAT_sector_offset,1); return 1; } }
// read new data from FAT table in HD to SDRAM and edit it if there is no target cluster in SDRAM sector_offset = (FAT_group_num<<FAT_GROUP_SIZE_M)/current_fs->bpb.byte_per_sector; cluster = (DWORD*)(fat_chain[next_fat_group]); fnIDE_BufferSector(cluster,current_fs->fat_begin_lba+sector_offset,FAT_GROUP_SECTOR_NUM); fat_group_index[next_fat_group] = FAT_group_num; buffer=(BUFFER *)(fat_chain[next_fat_group]+FAT_sector_offset*512); buffer->u32data[UI32position]=value; fnIDE_WriteBufferSector(buffer,current_fs->fat_begin_lba+FAT_group_num*FAT_GROUP_SECTOR_NUM+FAT_sector_offset,1); fnIDE_WriteBufferSector(buffer,current_fs->fat_begin_lba+FAT_group_num*FAT_GROUP_SECTOR_NUM+current_fs->bpb.sector_per_FAT+FAT_sector_offset,1); next_fat_group= next_fat_group +1; if(next_fat_group==FAT_GROUP_NUM) { next_fat_group=1; } return 1; }
/****************************************************************** * Function : fnFAT32_EditFatChain * Description : Edit FAT table - only edit FAT buffer in SDRAM * Input : * DWORD Current_Cluster-target cluster number * DWORD value-edit value * Output : 1-done/ 0-fail *******************************************************************/ BYTE fnFAT32_EditFatChain(DWORD Current_Cluster,DWORD value) { DWORD FAT_group_num,FAT_group_offset,sector_offset; DWORD *buffer; BYTE i; if (Current_Cluster<2||Current_Cluster>=(current_fs->bpb.sector_per_FAT*current_fs->bpb.byte_per_sector/4)) return 0;
FAT_group_num = Current_Cluster>>FAT_GROUP_DWORD_SIZE_M; FAT_group_offset= Current_Cluster-(FAT_group_num<<FAT_GROUP_DWORD_SIZE_M);
for(i=0;i<FAT_GROUP_NUM;i++) { if(FAT_group_num==fat_group_index[i]) { buffer=(DWORD *)(fat_chain[i]); buffer[FAT_group_offset]=value; return 1; } } return 0; }
|