📄 hdd driver.c
字号:
lnf_tiles=buff[0] & 0b00111111;
bytes_read=bytes_read+lnf_tiles*32;
if(bytes_read>cluster_size_bytes){
// compute next cluster address next_cluster_ptr must be valid
// assigns this_cluster_ptr
dir_addr_ptr=cluster_addr(fnbr,NEXT_CLUSTER);
if (dir_addr_ptr==0xFFFFFF) return (22);
bytes_read=bytes_read-cluster_size_bytes;
dir_addr_ptr=dir_addr_ptr+bytes_read;
}
else{
dir_addr_ptr=dir_addr_ptr+lnf_tiles*32;
}
//advance over the lnf tiles
/// test to see if we need next cluster in chain
if (read_BLOCK(dir_addr_ptr,buff)==false) return(31);
/// !!! may read into next sector
}
/// check out the standard DOS tile
#IF MMC_OPEN_TRACE
printf("\n\r fname[%s] level=%u \n\r",file_name,level);
for (j=0;j<11;j++)printf("%c",buff[j]);
#ENDIF
if(strncmp(buff,file_name, 11)==0){ ///8.3 file name ex "FILE EXT" "FOLDER "
// we have a file type or a sub directory(folder)
// so we get the starting cluster number
attribute=buff[11];
file[fnbr].root_cluster_ptr=make16(buff[27],buff[26]);/// assign initial cluster ptr
/// if it is not a directory
/// it points to the begining of the file
/// cluster chain
if ((attribute & 0b00010000)>0)directory=true;
else directory=false;
if ((attribute & 0b00100000)>0 || attribute==0){
archive=true; //// we have our file
file[fnbr].size=make32(buff[31],buff[30],buff[29],buff[28]);
file[fnbr].dir_addr_ptr=dir_addr_ptr; ///save address of this files tile
/// assign global value
}
else archive=false;
goto match_found;
// goto fill_table; // we have a match
}
next_tile:
bytes_read=bytes_read+32;
if(bytes_read > cluster_size_bytes){
/// requires a valid next=next_cluster_ptr
// compute next cluster address and assign this cluster
dir_addr_ptr=cluster_addr(fnbr,NEXT_CLUSTER);
if (dir_addr_ptr==0xFFFFFF) return (23);
bytes_read=bytes_read-cluster_size_bytes;
dir_addr_ptr=dir_addr_ptr+bytes_read;
}
else{
dir_addr_ptr=dir_addr_ptr+32;
}
dir_addr_ptr=dir_addr_ptr+32;
if (read_BLOCK(dir_addr_ptr,buff)==false) return(32);
goto tile_decode;
match_found:
///// if we have a sub directory we need to cycle down a level
if (directory==true) {
// compute the sub directory address
// compute this cluster address this_cluster_ptr must be valid
dir_addr_ptr=cluster_addr(fnbr,ROOT_CLUSTER); /// set physical addr of starting cluster
#IF MMC_OPEN_TRACE
printf("\n\r next_cluster_ptr=%lu \n\r ",file[fnbr].next_cluster_ptr);
#ENDIF
//printf("\n\r dir_addr_ptr=%lu",dir_addr_ptr);
// dir_addr_ptr=((int32)cluster_table[0]-(int32)2)*(int32)cluster_size_bytes+
// data_area_address;
level++;
goto read_directory;
}
// note record length must divide into 512 to align properly
if (rec_length<2) return(12);
/// get the initial file_addr_ptr
file[fnbr].addr_ptr=cluster_addr(fnbr,ROOT_CLUSTER);
file[fnbr].offset=0; //init bytes read from beginning of open file
file[fnbr].cluster_offset=0; //init bytes read to beginning of the current cluster
file[fnbr].rec_size=(int32)rec_length; /// assign file record size
#IF MMC_OPEN_TRACE
printf("root_cluster=%lu \n\r",file[fnbr].root_cluster_ptr);
#ENDIF
//printf("\n\r fopen %u rec size=%lu",fnbr,file[fnbr].rec_size);
if(set_BLOCKLEN(file[fnbr].rec_size)==false) return(13);
return(0);
}
//////////////////////////////////////////////////////////////////////////////////
////////////////////////////// FILE READ ///////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
#separate
int file_read(int8 fnbr,char *buff){
int32 address;
int32 nxt_cluster;
//// MMC allows a read to start and stop at any address but this file system
//// imposes a record size restriction the record size must divide into the
/// 512 block to allow writing of the records
/// rec_size must align with cluster boundary 2048 ...must be a divisor of 2048
/// find the cluster containing the offset
/// buff must be at least the size of the recordsize requested in the File open
//printf("foffset=%lu coffset=%lu ",file[fnbr].offset,file[fnbr].cluster_offset);////$$$$
if ( file[fnbr].offset>=file[fnbr].size) return(10); /// already beyond eof
if ( file[fnbr].offset + (int32) file[fnbr].rec_size > file[fnbr].cluster_offset + (int32) cluster_size_bytes){
#IF MMC_READ_TRACE
printf("adv to next cluster");
#ENDIF
/// need to advance to the next cluster
nxt_cluster=cluster_addr(fnbr,NEXT_CLUSTER);
if ( nxt_cluster!=0XFFFFFFFF) file[fnbr].addr_ptr=nxt_cluster;
else return(11); /// last cluster in file reached
file[fnbr].cluster_offset=file[fnbr].cluster_offset+(int32)cluster_size_bytes; //foffset is the byte offset within the file
//that file_addr_ptr points to
}
address=file[fnbr].addr_ptr+file[fnbr].offset-file[fnbr].cluster_offset;
#IF MMC_READ_TRACE
//printf("\n\r offset=%lu",cluster_offset);
printf("\n\r data_area_address=%lu",address);
printf("\n\r cluster_size_bytes=%lu",cluster_size_bytes);
//printf("\n\r file_addr_ptr=%lu",file_addr_ptr);
#ENDIF
if (read_BLOCK(address,buff)==false)return(12); /// read block into buff
if ( file[fnbr].offset+file[fnbr].rec_size< file[fnbr].size ) file[fnbr].offset=file[fnbr].offset+file[fnbr].rec_size;
else{ /// end of file
#IF MMC_READ_TRACE
printf("eof size=%lu",file[fnbr].size);
#ENDIF
buff[ file[fnbr].size-file[fnbr].offset]=0; /// short record
file[fnbr].offset=file[fnbr].size;
return(255); //eof
}
return(0);
}
//////////////////////////////////////////////////////////////////////////////////
////////////////////////////// WRITE FILE /////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////
#separate
int file_write(int8 fnbr,int *buff){
//// buff size must be at least the recordsize requested in File open
//// the record is updated only chars beyond rec_size are ignored
/// set up for write
/// A MMC write is restricted it must be for a block and allign on block boundaries
/// blocklen must be exactly 512 and start address must be the begining of a
/// sector
/// the buff could potentially span a sector and or span a block(512) boundary
/// ex there could be 1byte left in a block and 1 byte lect in a sector
// if the block is the last block in the sector
/// worst case we could write to two blocks and need a new sector
int32 address,nxt_cluster;
int16 in_cluster_size,out_cluster_size;
int8 appending_flag;
appending_flag=0;
if (file[fnbr].offset + file[fnbr].rec_size>=file[fnbr].size) appending_flag=1;
/// find the cluster containing the offset
if ( file[fnbr].offset+file[fnbr].rec_size>=file[fnbr].cluster_offset + cluster_size_bytes){
#IF MMC_WRITE_TRACE
printf("spanning cluster \n\r");
#ENDIF
/// spans the current cluster so we split the write
in_cluster_size=file[fnbr].cluster_offset+cluster_size_bytes-file[fnbr].offset;
/// bytes from start of file to end of this cluste- bytes into the file
out_cluster_size=file[fnbr].rec_size - in_cluster_size;
#IF MMC_WRITE_TRACE
printf("write>> spanning cluster inside=%lu outside=%lu \n\r",in_cluster_size,out_cluster_size);
#ENDIF
address=file[fnbr].addr_ptr+file[fnbr].offset - file[fnbr].cluster_offset;
// physical address=
// physical address of the cluster +offset from begining of file
// - offset from the begining of file for the byte at the begining of the cluster
#IF MMC_WRITE_TRACE
printf("write file>>cluster=%lu in clstr addr=%lu",file[fnbr].this_cluster_ptr,address);
#ENDIF
//// address=physical offset of this cluster +bytes into this cluster
if(write_BLOCK(address,buff,in_cluster_size)==false)return(81); //// write first chunk
/// allocate the next cluster
nxt_cluster=cluster_addr(fnbr,NEXT_CLUSTER); ///physical address of file data that the
/// specific cluster indexes
#IF MMC_WRITE_TRACE
printf("nxt_cluster=%lu",nxt_cluster);
#ENDIF
if ( nxt_cluster==0xFFFFFFFF){
#IF MMC_WRITE_TRACE
printf("updating FAT");
#ENDIF
//// FAT2 is an identical copy of FAT1
file_new_cluster(fnbr,1); /// a new cluster is allocated in FAT1
file_new_cluster(fnbr,2); /// a new cluster is allocated in FAT2
nxt_cluster=cluster_addr(fnbr,NEXT_CLUSTER); ///physical address of file data that the
#IF MMC_WRITE_TRACE
printf("\n\r write>>nxt_cluster addr=%lu this clstr=%lu next=%lu",nxt_cluster,file[fnbr].this_cluster_ptr,file[fnbr].next_cluster_ptr); /// specific cluster indexes
#ENDIF
}
file[fnbr].addr_ptr =nxt_cluster;
file[fnbr].cluster_offset=file[fnbr].cluster_offset + cluster_size_bytes; //foffset is the byte offset within the file
//that file_addr_ptr points to
address=file[fnbr].addr_ptr + file[fnbr].offset - file[fnbr].cluster_offset + in_cluster_size;
#IF MMC_WRITE_TRACE
printf("out addr=%lu,out size=%lu",address,out_cluster_size);
#ENDIF
if(write_BLOCK(address,&buff[in_cluster_size],out_cluster_size)==false)return(82); /// write block pads with 0x00 to end of sector
}// end of spanned cluster
else{
/// within the current cluster
address=file[fnbr].addr_ptr+file[fnbr].offset - file[fnbr].cluster_offset;
if(write_BLOCK(address,buff,file[fnbr].rec_size)==false)return(84); /// write block pads with 0x00 to end of sector
}
if(appending_flag==1) {
/// if appended we need to up date the file size
file[fnbr].size=file[fnbr].size + file[fnbr].rec_size; /// add one record
address=file[fnbr].dir_addr_ptr+28; /// file size is offset 28 in tiles
#IF MMC_WRITE_TRACE
printf("new file size=%lu",file[fnbr].size);
#ENDIF
buff[0]=make8(file[fnbr].size,0);
buff[1]=make8(file[fnbr].size,1);
buff[2]=make8(file[fnbr].size,2);
buff[3]=make8(file[fnbr].size,3);
MMC_dir_protected=false;
if(write_BLOCK(address,buff,4)==false)return(85);
}
if(set_BLOCKLEN(file[fnbr].rec_size)==false) return(86); /// reset to original rec_size
return(0);
}
#separate
int file_set(int fnbr,int32 offset){
/// file open sets the offset to the begining offset=0
/// this sets the offset within the file ...offset of 0 is a reset
if(offset>=file[fnbr].size) return(71);
file[fnbr].offset=offset; //// overwrite the existing offset
file[fnbr].next_cluster_ptr=file[fnbr].root_cluster_ptr; /// set current ptr to beginning
file[fnbr].cluster_offset=0;
// move the cluster to the one containing the offset
while ( offset>cluster_size_bytes ){
file[fnbr].addr_ptr=cluster_addr(fnbr,NEXT_CLUSTER);
file[fnbr].cluster_offset+=cluster_size_bytes; //foffset is the byte offset within the file
if (offset-cluster_size_bytes >0) offset= offset - cluster_size_bytes;
}
return(0);
}
#separate
int file_new_cluster(int8 fnbr,int8 mode){ ///////////// this does identical writes to either the FAT1 and FAT2 sectors
int16 eof_cluster;
char buff[2],tmp_buff[2];
int32 address;
int32 fat_address;
int16 slot;
/// an unused cluster has the value 0x0000 as its next cluster ptr
/// a used cluster has either 0xFFFF meaning last in chain
/// or a valid cluster displacement in the FAT1 amd FAT2 area
/// to append a cluster the 0XFFFF needs to be replaced by the appended
/// cluster location and the appended locations data (next ptr) needs to be set to 0XFFFF
eof_cluster=file[fnbr].this_cluster_ptr;
#IF MMC_NEW_CLUSTER
printf("the cluster with eof (FFFF)=%lu \n\r",eof_cluster);
#ENDIF
slot=0;
if(set_BLOCKLEN((int32)2)==false)return(false); // force blocklen to 2
/// use global address of FAT1 assigned by INIT
if (mode==2)fat_address=fat2_address;
else fat_address=fat1_address;
address=fat_address;
#IF MMC_NEW_CLUSTER
printf("mode=%u FAT addr=%lu \n\r",mode,address);
#ENDIF
do{
if(read_block(address,buff)==false) return(false) ;
slot=slot+1;
address=address+2;
//printf(" slot %lu =%2x %2x",slot,buff[0],buff[1]);
}
while (buff[0]!=0 || buff[1]!=0);
address=address-2; // correct for over step
slot=slot-1;
#IF MMC_NEW_CLUSTER
printf("slot=%lu address=%lu",slot,address);
#ENDIF
/// found an unused cluster
tmp_buff[0]=0xFF;tmp_buff[1]=0xFF; /// stamp it as last
MMC_dir_protected=false; /// allow writes to the protected areas
if(write_block(address,tmp_buff,2)==false ) return(false);
/////////////////////////////////////////////
/// update prev cluster with 0xFFFF in it
tmp_buff[1]=make8(slot,1);
tmp_buff[0]=make8(slot,0);
if (mode==1){
//// update the file info
file[fnbr].next_cluster_ptr=slot;
#IF MMC_NEW_CLUSTER
printf("cluster %lu was updated to point to %lu",file[fnbr].this_cluster_ptr,file[fnbr].next_cluster_ptr);
#ENDIF
}
/// compute physical address of the current cluster
MMC_dir_protected=false; /// allow writes to the protected areas
if(write_BLOCK(fat_address+(file[fnbr].this_cluster_ptr)*2,tmp_buff,2)==false) return(33);
if(set_BLOCKLEN((int32)file[fnbr].rec_size)==false)return(false); // reset blocklen
return(true);
}
signed int strncmp(char *s1, char *s2, int n){
for (; n > 0; s1++, s2++, n--){
if (*s1 != *s2) return((*s1 <*s2) ? -1: 1);
else if (*s1 == '\0') return(0);
}
return(0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -