📄 disk.cpp
字号:
#ifndef _disk_
#define _disk_
#include "disk.h"
#include "inout.cpp"
#include "shell.cpp"
#include "fs.cpp"
#define RW 33
#define RO 32
#define File_Not_Found 1
#define Folder_Not_Found 2
#define Destination_File_Exist 3
#define Destination_Folder_Exist 4
#define Access_Violation 5
char Error_Code;
char curr_dir_cnum;
extern Directory curr_dir;
extern char *path;
extern char floppy_hardd_tog;
char Drive_No=0x80;
// Initialise Routine //
Disk disk;
Drive d[4];
//To check whether the entered drive is valid or not
struct Entry_details Disk::validate_drive(char* str)
{
int dr_num;
struct Entry_details file_details;
dr_num = path[0]-'A';
if((dr_num==2)||(dr_num==3))
{
file_details.lba = curr_dir.dir_lba;
file_details = d[dr_num-2].validate_entry(str,file_details,dr_num);
return file_details;
}
}
//Convertion of chs to lba addressing
long Disk::chs_to_lba(int track,int head,int sector)
{
long lba;
lba = (track*255*63) + head*63 + sector;
return(lba);
}
//Convertion of chs to lba addressing
long Disk::chs_to_lba(char track,char head,char sector)
{
int h,t,s,temp;
long lba;
h=head;
s=(sector & 0x3f);
temp = (sector & 0xc0)<<2;
t=track+temp;
lba =(255*63*(long)t);
lba+= s+ (63*h);
return(lba);
}
//Constructor for Disk class
Disk::Disk()
{
char head,track,sector,buf[512];
int i,j,read_flag,inc=446;
long lba;
num_of_drives=2;//Number of drives assumed to be 2
read_flag = get_sector(lba = 1,0x01,buf);//MBR is on t=0,h=0,s=1;
for(i=0;i<4;i++)
for(j=0;j<16;j++)
partition[i][j] = buf[inc++];
head=partition[1][1];
sector=partition[1][2];
track=partition[1][3];
lba = chs_to_lba(track,head,sector);
read_flag = get_sector(lba,0x01,buf);
inc=446;
for(i=1;i<4;i++)
for(j=0;j<16;j++)
partition[i][j] = buf[inc++];
}
//Read sectors with a given lba
int Disk::get_sector(long lba,char num_sectors,char *buf)
{
char num;
int h,t,s,temp;
char head,sector,track;
if((lba==50)&&(priority!=1)) {Error_Code=Access_Violation;return 0;}
t = lba/(255*63);
h = (lba%(255*63))/63;
s = lba%63;
head = h;
sector = (t & 0x300)>>2;
sector+=s;
track = t;
asm mov cx,0x3;
lp:
asm push cx;
asm mov ah,0x02
asm mov al,num_sectors
asm mov ch,track
asm mov cl,sector
asm mov dh,head
asm mov dl,Drive_No
asm mov bx,buf
asm push ds
asm int 0x13
asm pop es
asm jnc nerror;
num=0;
asm pop cx;
asm dec cx;
asm jnz lp;
asm mov num,ah
return num;
nerror:
asm mov num,ah
return num;
}
//Write sectors with a given lba
int Disk::put_sector(long lba,char num_sectors,char *buf)
{
char num;
int h,t,s,temp;
char head,sector,track;
if((lba==50)&&(priority!=1)) {Error_Code=Access_Violation;return 0;}
t = lba/(255*63);
h = (lba%(255*63))/63;
s = lba%63;
head = h;
sector = (t & 0x300)>>2;
sector+=s;
track = t;
asm mov cx,0x3;
lp:
asm push cx;
asm mov ah,0x03
asm mov al,num_sectors
asm mov ch,track
asm mov cl,sector
asm mov dh,head
asm mov dl,Drive_No
asm mov bx,buf
asm push ds
asm int 0x13
asm pop es
asm jnc nerror;
num=0;
asm pop cx;
asm dec cx;
asm jnz lp;
asm mov num,ah
return num;
nerror:
asm mov num,ah
return num;
}
//Validate a given relative path
struct Entry_details Drive::validate_entry(char* str,struct Entry_details file_details,int dr_num)
{
Directory dir;
file_details = dir.get_lba(str,file_details,dr_num);
return file_details;
}
//Validate a given absolute path
struct Entry_details Disk::validate_drive_abs(char* path)
{
int dr_num;
struct Entry_details file_details;
dr_num = *path - 'A';
if((dr_num==2)||(dr_num==3))
{
file_details.lba = d[dr_num-2].rootdir_lba;
file_details = d[dr_num-2].validate_entry_abs(path+3,file_details,dr_num);
return file_details;
}
}
//Get a fat entry with the given lba
long Drive::get_fat_entry(long lba_num,int dr_num)
{
int read_flag,fat_entry;
char buf[512];
long lba,cluster;
cluster=((lba_num-d[dr_num-2].rootdir_lba)/d[dr_num-2].get_spc())+2;
lba = fat1_lba+(cluster)/128;
read_flag = disk.get_sector(lba ,0x01,buf);
fat_entry = (cluster%128)*4;
cluster =
rev_cat(
rev_cat(buf[fat_entry],buf[fat_entry+1]),
rev_cat(buf[fat_entry+2],buf[fat_entry+3])
);
if(cluster>=0x0ffffff8) return(cluster);
else
return(d[dr_num-2].rootdir_lba+(cluster-2)*d[dr_num-2].get_spc());
}
//Read data from a given lba
char* Drive::dataread(long lba)
{
char buf[512];
int read_flag;
read_flag = disk.get_sector(lba ,0x01,buf);
return(buf);
}
//Initialise drive parameters
void Drive::initialise(int drive_num)
{
long lba;
char buf[512];
int read_flag;
lba=disk.chs_to_lba(disk.partition[drive_num-2][3],disk.partition[drive_num-2][1],
disk.partition[drive_num-2][2]);
read_flag = disk.get_sector(lba ,0x01,drive_buf);
fat1_lba=lba + rev_cat(drive_buf[14],drive_buf[15]);
rootdir_lba = fat1_lba +
(2 *
(rev_cat
(rev_cat(drive_buf[36],drive_buf[37]),
rev_cat(drive_buf[38],drive_buf[39]))));
}
//Get free fat entries
long Drive::get_free_fat_entry()
{
int read_flag,fat_entry=0;
char buf[512];
long lba,cluster;
lba = fat1_lba;
while(1)
{
read_flag = disk.get_sector(lba++,0x01,buf);
fat_entry = 0;
while(fat_entry<128)
{
cluster =
rev_cat(
rev_cat(buf[fat_entry],buf[fat_entry+1]),
rev_cat(buf[fat_entry+2],buf[fat_entry+3])
);
fat_entry += 4;
if(cluster==0)
{
fat_entry -= 4;
lba--;
cluster = (lba-fat1_lba)*128 + (fat_entry/4);
return(cluster);
}
}
}
}
//Get sector per cluster value for the partition
char Drive :: get_spc()
{
return drive_buf[13];
}
//Sets a fat entry to a given value
Drive::set_fat_entry(long l_lba,long r_lba,int drive)// set the link og l_lba to r_lba
{
int read_flag,fat_entry;
char* temp;
char buf[512];
long lba,clusterl,clusterr;
clusterl=((l_lba-d[drive-2].rootdir_lba)/d[drive-2].get_spc())+2;
if(r_lba<0x0ffffff8)
clusterr=((r_lba-d[drive-2].rootdir_lba)/d[drive-2].get_spc())+2;
else clusterr=r_lba;
lba = fat1_lba+(clusterl)/128;
read_flag = disk.get_sector(lba ,0x01,buf);
fat_entry = ((clusterl)%128)*4;
temp = (char*)buf;
temp+=fat_entry;
temp[0] = clusterr;
temp[1] = clusterr>>8;
temp[2] = clusterr>>16;
temp[3] = clusterr>>24;
disk.put_sector(lba ,0x01,buf);
}
//Validate a given absolute path
struct Entry_details Drive::validate_entry_abs(char* path,struct Entry_details file_details,int dr_num)
{
char *name;
Directory dir;
if(*path == 0) return(file_details);
name = path;
while((*path != ':')&&(*path != 0))path++;
if(*path != 0)
{
*path = 0;
path++;
}
file_details = dir.get_lba_abs(name,file_details,dr_num);
file_details = validate_entry_abs(path,file_details,dr_num);
return file_details;
}
//Get entry details
struct Entry_details Directory::get_lba_abs(char* name,struct Entry_details file_details,int dr_num)
{
char *f_d;
char buf[64][32];
int flag=1,k;
long cluster;
int index;
disk.get_sector(file_details.lba,0x04,(char *)buf);
for(int i=0;i<64;i++)
{
for(int j=0,k=-1;j<11;j++)
{
if(k==-1) k++;
else if(name[k])k++;
if(name[k] == '.') {j=8;k++;}
if((buf[i][j] == 0x20 && name[k] == 0) || buf[i][j] == name[k])
{flag=0;}
else {flag = 1;break;}
}
if(!flag && (j == 11 || name[k] == 0))
break;
}
cluster =
rev_cat(rev_cat(buf[i][26],buf[i][27]),rev_cat(buf[i][20],buf[i][21]));
if(!flag)
{
f_d =(char*) &file_details;
index = 0;
while(index<32){*f_d = buf[i][index];index++;f_d++;}
file_details.lba = d[dr_num-2].rootdir_lba+(cluster-2)*d[dr_num-2].get_spc();
return(file_details);
}
else
{
file_details.lba = 0;
return file_details;
}
}
Directory::Directory(){}
Directory::Directory(char dr_num)
{
drive = dr_num;
}
Directory::Directory(char *path)
{
drive = *path-'A';
if(path[0] == 'C' && path[1] == ':')
dir_details = disk.validate_drive_abs(path);
else
dir_details = disk.validate_drive(path);
dir_lba = dir_details.lba;
found=1;
}
//Gets a directory with a given dir name
Directory Directory::get_dir(char *dir_name)
{
long cluster;
int j,k;
static Directory dir_ret(drive);
char buf[64][32];
int flag = 1;
disk.get_sector(dir_lba,0x04,(char *)buf);
for(int i=0;i<64;i++)
{
for(j=0,k=-1;j<11;j++)
{
if(k==-1) k++;
else if(dir_name[k])k++;
if((buf[i][j] == 0x20 && dir_name[k] == 0) || buf[i][j] == dir_name[k])
{flag=0;}
else {flag = 1;break;}
}
if(!flag && (j == 11 || dir_name[k] == 0))
break;
}
if(!flag)
{
cluster =
rev_cat(rev_cat(buf[i][26],buf[i][27]),rev_cat(buf[i][20],buf[i][21]));
dir_ret.dir_lba = d[drive-2].rootdir_lba+(cluster-2)*d[drive-2].get_spc();
char *temp = (char*)(&dir_ret.dir_details);
for(j=0;j<32;j++)temp[j] = buf[i][j];
dir_ret.dir_details.lba = dir_ret.dir_lba;
dir_ret.found=1;
return(dir_ret);
}
else
{
dir_ret.found=0;
return(dir_ret);
}
}
//Gets entries of a dir
Dir_Entries* Directory::dir_read()
{
static char buf[64][32];
char cnt=0;
int j,i,read_flag;
Dir_Entries dir_entries[64];
for(i=0;i<64;i++)
for(j=0;j<32;j++)
buf[i][j]=0;
if(dir_details.lba==0) found=0;
else
{
read_flag=disk.get_sector(dir_details.lba,4,(char*)buf);
for(i=0;i<64;i++)
{
j=0;
if(buf[i][j]==0) break;
if((buf[i][j]=='
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -